#pragma prototyped
#include "common.h"
#include "g.h"
#include "gcommon.h"
#include "mem.h"
#define WAU widget->u.a
extern WidgetClass arrayWidgetClass;
static void awcallback (Widget, XtPointer, XtPointer);
int GAcreatewidget (Gwidget_t *parent, Gwidget_t *widget,
int attrn, Gwattr_t *attrp) {
PIXsize_t ps;
int ai;
XColor c;
int color;
if (!parent) {
Gerr (POS, G_ERRNOPARENTWIDGET);
return -1;
}
WAU->func = NULL;
ps.x = ps.y = MINAWSIZE;
RESETARGS;
for (ai = 0; ai < attrn; ai++) {
switch (attrp[ai].id) {
case G_ATTRSIZE:
GETSIZE (attrp[ai].u.s, ps, MINAWSIZE);
break;
case G_ATTRBORDERWIDTH:
ADD2ARGS (XtNborderWidth, attrp[ai].u.i);
break;
case G_ATTRMODE:
if (Strcmp ("horizontal", attrp[ai].u.t) == 0) {
ADD2ARGS (XtNorientation, XtorientHorizontal);
WAU->mode = G_AWHARRAY;
} else if (Strcmp ("vertical", attrp[ai].u.t) == 0) {
WAU->mode = G_AWVARRAY;
} else {
Gerr (POS, G_ERRBADATTRVALUE, attrp[ai].u.t);
return -1;
}
break;
case G_ATTRLAYOUT:
if (Strcmp ("on", attrp[ai].u.t) == 0)
Gawsetmode (widget, FALSE);
else if (Strcmp ("off", attrp[ai].u.t) == 0)
Gawsetmode (widget, TRUE);
else {
Gerr (POS, G_ERRBADATTRVALUE, attrp[ai].u.t);
return -1;
}
break;
case G_ATTRCOLOR:
color = attrp[ai].u.c.index;
if (color != 0 && color != 1) {
Gerr (POS, G_ERRBADCOLORINDEX, color);
return -1;
}
c.red = attrp[ai].u.c.r * 257;
c.green = attrp[ai].u.c.g * 257;
c.blue = attrp[ai].u.c.b * 257;
if (XAllocColor (
Gdisplay, DefaultColormap (Gdisplay, Gscreenn), &c
)) {
if (color == 0)
ADD2ARGS (XtNbackground, c.pixel);
else
ADD2ARGS (XtNforeground, c.pixel);
}
break;
case G_ATTRWINDOWID:
Gerr (POS, G_ERRCANNOTSETATTR1, "windowid");
return -1;
case G_ATTRRESIZECB:
WAU->func = (Gawcoordscb) attrp[ai].u.func;
break;
case G_ATTRUSERDATA:
widget->udata = attrp[ai].u.u;
break;
default:
Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
return -1;
}
}
ADD2ARGS (XtNwidth, ps.x);
ADD2ARGS (XtNheight, ps.y);
if (!(widget->w = XtCreateWidget ("array", arrayWidgetClass,
parent->w, argp, argn))) {
Gerr (POS, G_ERRCANNOTCREATEWIDGET);
return -1;
}
XtAddCallback (widget->w, XtNcallback, awcallback, (XtPointer) NULL);
Glazymanage (widget->w);
return 0;
}
int GAsetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
PIXsize_t ps;
int ai;
RESETARGS;
for (ai = 0; ai < attrn; ai++) {
switch (attrp[ai].id) {
case G_ATTRSIZE:
GETSIZE (attrp[ai].u.s, ps, MINAWSIZE);
ADD2ARGS (XtNwidth, ps.x);
ADD2ARGS (XtNheight, ps.y);
break;
case G_ATTRBORDERWIDTH:
ADD2ARGS (XtNborderWidth, attrp[ai].u.i);
break;
case G_ATTRMODE:
Gerr (POS, G_ERRCANNOTSETATTR2, "mode");
return -1;
case G_ATTRLAYOUT:
if (Strcmp ("on", attrp[ai].u.t) == 0)
Gawsetmode (widget, FALSE);
else if (Strcmp ("off", attrp[ai].u.t) == 0)
Gawsetmode (widget, TRUE);
else {
Gerr (POS, G_ERRBADATTRVALUE, attrp[ai].u.t);
return -1;
}
break;
case G_ATTRWINDOWID:
Gerr (POS, G_ERRCANNOTSETATTR2, "windowid");
return -1;
case G_ATTRRESIZECB:
WAU->func = (Gawcoordscb) attrp[ai].u.func;
break;
case G_ATTRUSERDATA:
widget->udata = attrp[ai].u.u;
break;
default:
Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
return -1;
}
}
XtSetValues (widget->w, argp, argn);
return 0;
}
int GAgetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
Dimension width, height;
int ai;
for (ai = 0; ai < attrn; ai++) {
RESETARGS;
switch (attrp[ai].id) {
case G_ATTRSIZE:
ADD2ARGS (XtNwidth, &width);
ADD2ARGS (XtNheight, &height);
XtGetValues (widget->w, argp, argn);
attrp[ai].u.s.x = width, attrp[ai].u.s.y = height;
break;
case G_ATTRBORDERWIDTH:
ADD2ARGS (XtNborderWidth, &width);
XtGetValues (widget->w, argp, argn);
attrp[ai].u.i = width;
break;
case G_ATTRMODE:
attrp[ai].u.t = (WAU->mode == G_AWHARRAY) ?
"horizontal" : "vertical";
break;
case G_ATTRLAYOUT:
attrp[ai].u.t = (Gawgetmode (widget)) ? "off" : "on";
break;
case G_ATTRWINDOWID:
sprintf (&Gbufp[0], "0x%lx", XtWindow (widget->w));
attrp[ai].u.t = &Gbufp[0];
break;
case G_ATTRRESIZECB:
attrp[ai].u.func = (void*)(WAU->func);
break;
case G_ATTRUSERDATA:
attrp[ai].u.u = widget->udata;
break;
default:
Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
return -1;
}
}
return 0;
}
int GAdestroywidget (Gwidget_t *widget) {
XtDestroyWidget (widget->w);
return 0;
}
static void awcallback (Widget w, XtPointer clientdata, XtPointer calldata) {
Gwidget_t *widget;
if (!(widget = findwidget ((unsigned long) w, G_ARRAYWIDGET)))
return;
if (WAU->func)
(*WAU->func) (widget - &Gwidgets[0], (Gawdata_t *) calldata);
else
Gawdefcoordscb (widget - &Gwidgets[0], (Gawdata_t *) calldata);
}
#include <X11/IntrinsicP.h>
typedef struct _ArrayClassRec *ArrayWidgetClass;
typedef struct _ArrayRec *ArrayWidget;
typedef struct _ArrayClassPart {
int dummy;
} ArrayClassPart;
typedef struct _ArrayClassRec {
CoreClassPart core_class;
CompositeClassPart composite_class;
ArrayClassPart array_class;
} ArrayClassRec;
typedef struct _ArrayPart {
XtCallbackList callbacks;
XtOrientation orientation;
Gawdata_t data;
int batchmode;
} ArrayPart;
typedef struct _ArrayRec {
CorePart core;
CompositePart composite;
ArrayPart array;
} ArrayRec;
#define CHILDINCR 10
#define CHILDSIZE sizeof (Gawcarray_t)
static XtResource resources[] = {
{
XtNcallback,
XtCCallback,
XtRCallback,
sizeof (XtPointer),
XtOffsetOf (ArrayRec, array.callbacks),
XtRCallback, (XtPointer) NULL
},
{
XtNorientation,
XtCOrientation,
XtROrientation,
sizeof (XtOrientation),
XtOffsetOf (ArrayRec, array.orientation),
XtRImmediate, (XtPointer) XtorientVertical
}
};
static void ClassInitialize (void);
static void Initialize (Widget, Widget, ArgList, Cardinal *);
static void Destroy (Widget);
static void Resize (Widget);
static Boolean SetValues (Widget, Widget, Widget, ArgList, Cardinal *);
static XtGeometryResult GeometryManager(Widget,
XtWidgetGeometry *, XtWidgetGeometry *);
static void ChangeManaged (Widget);
static void InsertChild (Widget);
static void DeleteChild (Widget);
static void dolayout (ArrayWidget, int);
ArrayClassRec arrayClassRec = {
{
(WidgetClass) &compositeClassRec,
"Array",
sizeof(ArrayRec),
ClassInitialize,
NULL,
FALSE,
Initialize,
NULL,
XtInheritRealize,
NULL,
0,
resources,
XtNumber (resources),
NULLQUARK,
TRUE,
TRUE,
TRUE,
FALSE,
Destroy,
Resize,
XtInheritExpose,
SetValues,
NULL,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
NULL,
XtInheritQueryGeometry,
XtInheritDisplayAccelerator,
NULL
},
{
GeometryManager,
ChangeManaged,
InsertChild,
DeleteChild,
NULL
},
{
0
}
};
WidgetClass arrayWidgetClass = (WidgetClass)&arrayClassRec;
int Gaworder (Gwidget_t *widget, void *data, Gawordercb func) {
ArrayWidget aw;
aw = (ArrayWidget) widget->w;
(*func) (data, &aw->array.data);
dolayout (aw, TRUE);
return 0;
}
int Gawsetmode (Gwidget_t *widget, int mode) {
ArrayWidget aw;
aw = (ArrayWidget) widget->w;
aw->array.batchmode = mode;
dolayout (aw, TRUE);
return 0;
}
int Gawgetmode (Gwidget_t *widget) {
ArrayWidget aw;
aw = (ArrayWidget) widget->w;
return aw->array.batchmode;
}
void Gawdefcoordscb (int wi, Gawdata_t *dp) {
Gawcarray_t *cp;
int sx, sy, csx, csy, ci;
sx = dp->sx, sy = dp->sy;
csx = csy = 0;
for (ci = 0; ci < dp->cj; ci++) {
cp = &dp->carray[ci];
if (!cp->flag)
continue;
cp->ox = csx, cp->oy = csy;
if (dp->type == G_AWVARRAY)
cp->sx = sx - 2 * cp->bs, csy += cp->sy + 2 * cp->bs;
else
cp->sy = sy - 2 * cp->bs, csx += cp->sx + 2 * cp->bs;
}
if (dp->type == G_AWVARRAY)
dp->sy = csy;
else
dp->sx = csx;
}
static void ClassInitialize (void) {
XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
NULL, (Cardinal)0 );
}
static void Initialize (Widget reqw, Widget neww,
ArgList args, Cardinal *num_args) {
ArrayWidget aw;
aw = (ArrayWidget) neww;
if (aw->array.orientation == XtorientVertical)
aw->array.data.type = G_AWVARRAY;
else
aw->array.data.type = G_AWHARRAY;
aw->array.data.carray = Marrayalloc ((long) CHILDINCR * CHILDSIZE);
aw->array.data.cn = CHILDINCR;
aw->array.data.cj = 0;
aw->array.batchmode = FALSE;
if (aw->core.width == 0)
aw->core.width = 100;
if (aw->core.height == 0)
aw->core.height = 100;
}
static void Destroy (Widget w) {
ArrayWidget aw;
aw = (ArrayWidget) w;
Marrayfree (aw->array.data.carray);
aw->array.data.cn = aw->array.data.cj = 0;
}
static void Resize (Widget w) {
dolayout ((ArrayWidget) w, FALSE);
}
static Boolean SetValues (Widget curw, Widget reqw, Widget neww,
ArgList args, Cardinal *num_args) {
ArrayWidget curaw;
ArrayWidget newaw;
curaw = (ArrayWidget) curw;
newaw = (ArrayWidget) neww;
if (curaw->array.orientation != newaw->array.orientation) {
if (newaw->array.orientation == XtorientVertical)
newaw->array.data.type = G_AWVARRAY;
else
newaw->array.data.type = G_AWHARRAY;
dolayout (newaw, TRUE);
return TRUE;
}
return FALSE;
}
static XtGeometryResult GeometryManager(Widget w,
XtWidgetGeometry *req, XtWidgetGeometry *rep) {
Dimension width, height;
if (req->request_mode & ~(CWX | CWY | CWWidth | CWHeight))
return XtGeometryNo;
if (req->request_mode & (CWX | CWY | CWWidth | CWHeight)) {
width = (req->request_mode & CWWidth) ? req->width : w->core.width;
height = (req->request_mode & CWHeight) ? req->height : w->core.height;
w->core.width = width, w->core.height = height;
dolayout ((ArrayWidget) XtParent (w), TRUE);
return XtGeometryYes;
}
return XtGeometryYes;
}
static void ChangeManaged (Widget w) {
ArrayWidget aw;
aw = (ArrayWidget) w;
if (!aw->array.batchmode)
dolayout (aw, TRUE);
}
static void InsertChild (Widget w) {
ArrayWidget aw;
CompositeWidgetClass sclass;
sclass = (CompositeWidgetClass) compositeWidgetClass;
(*sclass->composite_class.insert_child) (w);
aw = (ArrayWidget) XtParent (w);
if (aw->array.data.cj == aw->array.data.cn) {
aw->array.data.carray = Marraygrow (aw->array.data.carray,
(long) (aw->array.data.cn + CHILDINCR) * CHILDSIZE);
aw->array.data.cn += CHILDINCR;
}
aw->array.data.carray[aw->array.data.cj++].w = w;
}
static void DeleteChild (Widget w) {
ArrayWidget aw;
CompositeWidgetClass sclass;
int ci;
sclass = (CompositeWidgetClass) compositeWidgetClass;
(*sclass->composite_class.delete_child) (w);
aw = (ArrayWidget) XtParent (w);
for (ci = 0; ci < aw->array.data.cj; ci++)
if (aw->array.data.carray[ci].w == w)
break;
if (ci < aw->array.data.cj) {
for (; ci + 1 < aw->array.data.cj; ci++)
aw->array.data.carray[ci].w = aw->array.data.carray[ci + 1].w;
aw->array.data.cj--;
}
}
static void dolayout (ArrayWidget aw, int flag) {
XtWidgetGeometry req, ret_req;
Gawdata_t *dp;
Gawcarray_t *cp;
int sx, sy, ci;
if (aw->array.batchmode)
return;
dp = &aw->array.data;
for (ci = 0; ci < dp->cj; ci++) {
if (!XtIsManaged (dp->carray[ci].w)) {
dp->carray[ci].flag = 0;
continue;
}
cp = &dp->carray[ci];
cp->flag = 1;
cp->ox = cp->w->core.x;
cp->oy = cp->w->core.y;
cp->sx = cp->w->core.width;
cp->sy = cp->w->core.height;
cp->bs = cp->w->core.border_width;
}
dp->sx = aw->core.width, dp->sy = aw->core.height;
XtCallCallbackList ((Widget) aw, aw->array.callbacks, dp);
if ((sx = dp->sx) < MINAWSIZE)
sx = MINAWSIZE;
if ((sy = dp->sy) < MINAWSIZE)
sy = MINAWSIZE;
if (flag && (aw->core.width != sx || aw->core.height != sy)) {
req.width = sx, req.height = sy;
req.request_mode = CWWidth | CWHeight;
if (XtMakeGeometryRequest ((Widget) aw, &req, &ret_req) ==
XtGeometryAlmost) {
req = ret_req;
XtMakeGeometryRequest ((Widget) aw, &req, &ret_req);
dp->sx = req.width, dp->sy = req.height;
XtCallCallbackList ((Widget) aw, aw->array.callbacks, dp);
}
}
for (ci = 0; ci < dp->cj; ci++) {
cp = &dp->carray[ci];
if (!cp->flag)
continue;
XtConfigureWidget (cp->w, cp->ox, cp->oy, cp->sx, cp->sy, cp->bs);
}
}