File:  [Research Unix] / researchv9 / X11 / src / X.V11R1 / lib / oldXtk / Form.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:22:00 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

/* $Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/lib/oldXtk/Form.c,v 1.1.1.1 2018/04/24 17:22:00 root Exp $ */
#ifndef lint
static char *sccsid = "@(#)Form.c	1.17	5/18/87";
#endif lint
/*
 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 * 
 *                         All Rights Reserved
 * 
 * Permission to use, copy, modify, and distribute this software and its 
 * documentation for any purpose and without fee is hereby granted, 
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in 
 * supporting documentation, and that the name of Digital Equipment
 * Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior permission.  
 * 
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

#include "Xlib.h"
#include "Intrinsic.h"
#include "Form.h"
#include "Atoms.h"


/* Private Definitions */


typedef struct SubWidgetDataRec {
    Window w;			/* Window id for this subwidget. */
    struct WidgetDataRec *data;	/* Pointer to form widget data. */
    XtEdgeType top, bottom, left, right;
				/* Where to drag things on resize. */
    int dx;			/* Desired initial horiz offset. */
    Window fromhoriz;		/* Other subwidget to base dx off of.
				   (NULL if form edge.) */
    int dy;			/* Desired initial vertical offset. */
    Window fromvert;		/* Other subwidget to base dy off of.
				   (NULL if form edge.) */
    Boolean allowresize;	/* TRUE if we allow the subwidget to resize
				   itself. */
    WindowBox wb;		/* Current coordinates.  */
} SubWidgetDataRec, *SubWidgetData;


static SubWidgetDataRec subglob;
static SubWidgetDataRec subinit = {0};

typedef struct WidgetDataRec {
    Display *dpy;		/* Display connection for the form widget */
    Window mywin;		/* Window ID of form widget. */
    WindowBox wb;		/* Coordinates of form widget. */
    SubWidgetData *sub;		/* Array of subwidgets. */
    int numsub;			/* Number of subwidgets. */
    Pixel background;		/* Background color. */
    Pixel border;		/* Border color. */
    int defaultdistance;	/* Default distance between widgets. */
    int dontrefigure;		/* Nonzero if we don't want to recalc. */
    Boolean needsrefigure;	/* TRUE if we need to recalc. */
} WidgetDataRec, *WidgetData;

/* !!! STATIC !!! */
static WidgetDataRec globaldata;
static WidgetDataRec globalinit = {0};

/* Private Data */

static Resource resources[] = {
    {XtNwindow, XtCWindow, XrmRWindow, sizeof(Window),
	 (caddr_t)&globaldata.mywin, (caddr_t)NULL},
    {XtNborderWidth, XtCBorderWidth, XrmRInt, sizeof(int),
	 (caddr_t)&globaldata.wb.borderWidth, (caddr_t)NULL},
    {XtNx, XtCX, XrmRInt, sizeof(int),
  (caddr_t)&globaldata.wb.x, (caddr_t)NULL},
    {XtNy, XtCY, XrmRInt, sizeof(int),
  (caddr_t)&globaldata.wb.y, (caddr_t)NULL},
    {XtNwidth, XtCWidth, XrmRInt, sizeof(int),
	 (caddr_t)&globaldata.wb.width, (caddr_t)NULL},
    {XtNheight, XtCHeight, XrmRInt, sizeof(int),
	 (caddr_t)&globaldata.wb.height, (caddr_t)NULL},
    {XtNbackground, XtCColor, XrmRPixel, sizeof(Pixel),
	 (caddr_t)&globaldata.background, (caddr_t)&XtDefaultBGPixel},
    {XtNborder, XtCColor, XrmRPixel, sizeof(Pixel),
	 (caddr_t)&globaldata.border,(caddr_t)&XtDefaultFGPixel},
    {XtNdefaultDistance, XtCThickness, XrmRInt,
	sizeof(int), (caddr_t)&globaldata.defaultdistance, (caddr_t)NULL},
};

static XtEdgeType defEdge = XtRubber;

static Resource subresources[] = {
    {XtNtop, XtCEdge, XtRJustify, sizeof(XtEdgeType),
	 (caddr_t)&subglob.top, (caddr_t)&defEdge},
    {XtNbottom, XtCEdge, XtRJustify, sizeof(XtEdgeType),
	 (caddr_t)&subglob.bottom, (caddr_t)&defEdge},
    {XtNleft, XtCEdge, XtRJustify, sizeof(XtEdgeType),
	 (caddr_t)&subglob.left, (caddr_t)&defEdge},
    {XtNright, XtCEdge, XtRJustify, sizeof(XtEdgeType),
	 (caddr_t)&subglob.right, (caddr_t)&defEdge},
    {XtNfromHoriz, XtCWindow, XrmRWindow, sizeof(Window),
	 (caddr_t)&subglob.fromhoriz, (caddr_t)NULL},
    {XtNfromVert, XtCWindow, XrmRWindow, sizeof(Window),
	 (caddr_t)&subglob.fromvert, (caddr_t)NULL},
    {XtNhorizDistance, XtCThickness, XrmRInt, sizeof(int),
	 (caddr_t)&subglob.dx, (caddr_t)NULL},
    {XtNvertDistance, XtCThickness, XrmRInt, sizeof(int),
	 (caddr_t)&subglob.dy, (caddr_t)NULL},
    {XtNresizable, XtCBoolean, XrmRBoolean, sizeof(Boolean),
	 (caddr_t)&subglob.allowresize, (caddr_t) NULL}
};


static XContext formContext;
static XContext subContext;

/****************************************************************
 *
 * Private Procedures
 *
 ****************************************************************/

static Boolean initialized = FALSE;

static void Initialize () 
{
    if (initialized)
    	return;
    initialized = TRUE;

    subinit.top = subinit.bottom = subinit.left = subinit.right = XtRubber;
    subinit.wb.x = subinit.wb.y = -1;

    globalinit.wb.width = globalinit.wb.height = 10;
    globalinit.wb.x = globalinit.wb.y = 0;
    globalinit.defaultdistance = 4;
    globalinit.wb.borderWidth = 1;

    formContext = XUniqueContext();
    subContext = XUniqueContext();
}


static WidgetData DataFromWindow(dpy, w)
Display *dpy;
Window w;
{
    WidgetData result;
    if (XFindContext(dpy, w, formContext, (caddr_t *)&result))
	return NULL;
    return result;
}

static SubWidgetData SubFromWindow(dpy, w)
Display *dpy;
Window w;
{
    SubWidgetData result;
    if (XFindContext(dpy, w, subContext, (caddr_t *)&result))
	return NULL;
    return result;
}

static void RefigureLocations(data)
WidgetData data;
{
    int i;
    Position x, y, maxx, maxy;
    SubWidgetData sub, sub2;
    WindowBox reqBox, replBox;
    XtGeometryReturnCode result;
    if (data->dontrefigure) {
	data->needsrefigure = TRUE;
	return;
    }
    maxx = maxy = 0;
    for (i=0 ; i<data->numsub ; i++) {
	sub = data->sub[i];
	x = sub->dx;
	y = sub->dy;
	if (sub->fromhoriz && (sub2 = SubFromWindow(data->dpy, sub->fromhoriz)))
	    x += sub2->wb.x + sub2->wb.width;
	if (sub->fromvert && (sub2 = SubFromWindow(data->dpy, sub->fromvert)))
	    y += sub2->wb.y + sub2->wb.height;
	if (x != sub->wb.x || y != sub->wb.y) {
	    XMoveWindow(data->dpy, sub->w, x, y);
	    sub->wb.x = x;
	    sub->wb.y = y;
	}
	if (maxx < x + sub->wb.width) maxx = x + sub->wb.width;
	if (maxy < y + sub->wb.height) maxy = y + sub->wb.height;
    }
    maxx += data->defaultdistance;
    maxy += data->defaultdistance;
    if (maxx != data->wb.width || maxy != data->wb.height) {
	reqBox.width = maxx;
	reqBox.height = maxy;
	result = XtMakeGeometryRequest(data->dpy, data->mywin, XtgeometryResize,
				       &reqBox, &replBox);
	if (result == XtgeometryAlmost) {
	    replBox = reqBox;
	    result = XtMakeGeometryRequest(data->dpy, data->mywin, XtgeometryResize,
					   &reqBox, &replBox);
	}
	if (result == XtgeometryYes) {
	    data->wb.width = reqBox.width;
	    data->wb.height = reqBox.height;
	}
    }
    data->needsrefigure = FALSE;
}


static int MoveEdge(loc, old, new, type)
int loc, old, new;
XtEdgeType type;
{
    if (type == XtRubber)
	return loc * new / old;
    if (type == XtChainTop || type == XtChainLeft)
	return loc;
    return loc + new - old;
}

static void ChangeSize(data, newwidth, newheight)
WidgetData data;
int newwidth, newheight;
{
    int i;
    SubWidgetData sub;
    WindowBox wb;
    for (i=0 ; i<data->numsub ; i++) {
	sub = data->sub[i];
	wb.borderWidth = sub->wb.borderWidth;
	wb.x = MoveEdge(sub->wb.x, (int)data->wb.width, newwidth, sub->left);
	wb.y = MoveEdge(sub->wb.y, (int)data->wb.height, newheight, sub->top);
	wb.width =
	    MoveEdge((int)(sub->wb.x + sub->wb.width),
		       (int)data->wb.width, newwidth, sub->right) - wb.x;
	wb.height = MoveEdge((int)(sub->wb.y + sub->wb.height),
			    (int)data->wb.height, newheight, sub->bottom)
			- wb.y;
	if (wb.width < 1) wb.width = 1;
	if (wb.height < 1) wb.height = 1;
	if (wb.x != sub->wb.x || wb.y != sub->wb.y ||
	        wb.width != sub->wb.width || wb.height != sub->wb.height) {
	    XMoveResizeWindow(data->dpy, sub->w, wb.x, wb.y,
			      wb.width, wb.height);
	    (void) XtSendConfigureNotify(data->dpy, sub->w, &wb);
	    sub->wb = wb;
	}
    }
    data->wb.width = newwidth;
    data->wb.height = newheight;
}


/* ARGSUSED */
static XtGeometryReturnCode FormGeometryHandler(dpy, w, req, reqBox, replBox)
Display *dpy;
Window w;
XtGeometryRequest req;
WindowBox *reqBox;
WindowBox *replBox;	/* RETURN */
{
    SubWidgetData sub;
    sub = SubFromWindow(dpy, w);
    if (sub && req == XtgeometryResize && sub->allowresize) {
	XResizeWindow(sub->data->dpy, sub->w, reqBox->width, reqBox->height);
	*replBox = *reqBox;
	sub->wb.width = reqBox->width;
	sub->wb.height = reqBox->height;
	(void) XtSendConfigureNotify(sub->data->dpy, w, &(sub->wb));
	RefigureLocations(sub->data);
	return XtgeometryYes;
    }
    return XtgeometryNo;
}


/*
 *
 * Destroy the widget
 *
 */

static void Destroy(data)
WidgetData data;
{
    int i;
    for (i=0 ; i<data->numsub; i++) {
	(void) XDeleteContext(data->dpy, data->sub[i]->w, subContext);
	(void) XtSendDestroyNotify(data->dpy, data->sub[i]->w);
    }
    XtClearEventHandlers(data->dpy, data->mywin);
    (void) XDeleteContext(data->dpy, data->mywin, formContext);
    XtFree((char *) data->sub);
    XtFree((char *) data);
}


/*
 *
 * Generic widget event handler
 *
 */

static XtEventReturnCode EventHandler(event, eventdata)
XEvent *event;
caddr_t eventdata;
{
    WidgetData	data = (WidgetData ) eventdata;
    int newwidth, newheight;

    switch (event->type) {
	case ConfigureNotify:
	    newwidth = event->xconfigure.width;
	    newheight = event->xconfigure.height;
	    if (newwidth != data->wb.width || newheight != data->wb.height)
		ChangeSize(data, newwidth, newheight);
	    break;

	case DestroyNotify:
	    Destroy(data);
	    break;
	
    }
    return (XteventHandled);
}

/*
 * Handle events in subwidgets. 
 */

static XtEventReturnCode SubEventHandler(event, sub)
XEvent *event;
SubWidgetData sub;
{
    if (event->type == DestroyNotify) {
	XtFormRemoveWidget(sub->data->dpy, sub->data->mywin, sub->w);
	return XteventHandled;
    }
    return XteventNotHandled;
}

/****************************************************************
 *
 * Public Procedures
 *
 ****************************************************************/

Window XtFormCreate(dpy, parent, args, argCount)
Display  *dpy;
Window   parent;
ArgList  args;
int      argCount;
{
    WidgetData data;
    XrmNameList  names;
    XrmClassList classes;
    if (!initialized)
    	Initialize ();

    data = (WidgetData) XtMalloc(sizeof(WidgetDataRec));

    /* Set Default Values */
    globaldata = globalinit;
    globaldata.dpy = dpy;
    XtGetResources(dpy, resources, XtNumber(resources), args, argCount, parent,
		   "form", "Form", &names, &classes);
    *data = globaldata;    

    data->numsub = 0;
    data->sub = (SubWidgetData *)XtMalloc(sizeof(SubWidgetData));
    if (data->mywin != NULL) {
	XWindowAttributes wi;
	/* set global data from window parameters */
	if (! XGetWindowAttributes(data->dpy, data->mywin, &wi)) {
	    data->mywin = NULL;
	} else {
	    data->wb.borderWidth = wi.border_width;
	    data->wb.width = wi.width;
	    data->wb.height = wi.height;
            data->wb.x = wi.x;
            data->wb.y = wi.y;
	}
    }
    if (data->mywin == NULL) {
	/* create the Form window */
        data->mywin = XCreateSimpleWindow(data->dpy, parent, data->wb.x,
					  data->wb.y, data->wb.width, data->wb.height,
					  data->wb.borderWidth,
					  data->border, data->background);
    }

    XtSetNameAndClass(data->dpy, data->mywin, names, classes);
    XrmFreeNameList(names);
    XrmFreeClassList(classes);
    (void) XSaveContext(data->dpy, data->mywin, formContext, (caddr_t)data);

    /* set handler for resize, and message events */

    XtSetEventHandler (data->dpy, data->mywin, (XtEventHandler)EventHandler,
		       StructureNotifyMask, (caddr_t)data);

    return (data->mywin);
}

/*
 *
 * Get Attributes
 *
 */

void XtFormGetValues (dpy, w, args, argCount)
Display *dpy;
Window w;
ArgList args;
int argCount;
{
    WidgetData data;

    if ((data = DataFromWindow(dpy, w)) == NULL)
	return;
    globaldata = *data;
    XtGetValues(resources, XtNumber(resources), args, argCount);
}

/*
 *
 * Set Values
 *
 */

void XtFormSetValues (dpy, w, args, argCount)
Display *dpy;
Window w;
ArgList args;
int argCount;
{
    WidgetData data;

    if ((data = DataFromWindow(dpy, w)) == NULL)
	return;
    globaldata = *data;
    XtSetValues(resources, XtNumber(resources), args, argCount);
    *data = globaldata;
}


/*
 * Add a new widget to the form.
 */

void XtFormAddWidget(dpy, mywin, w, args, argCount)
Display *dpy;
Window mywin, w;
ArgList args;
int argCount;
{
    WidgetData data;
    SubWidgetData sub;
    XrmNameList names;
    XrmClassList classes;
    XWindowAttributes info;
    if ((data = DataFromWindow(dpy, mywin)) == NULL) return;
    if ((sub = SubFromWindow(dpy, w)) == NULL) {
	data->sub = (SubWidgetData *)
	    XtRealloc((char *) data->sub,
		      (unsigned) sizeof(SubWidgetData) * ++data->numsub);
	sub = data->sub[data->numsub - 1] =
	    (SubWidgetData) XtMalloc(sizeof(SubWidgetDataRec));
	(void)XSaveContext(dpy, w, subContext, (caddr_t)sub);
	*sub = subinit;
	sub->data = data;
	sub->w = w;
	sub->dx = sub->dy = data->defaultdistance;
	(void) XGetWindowAttributes(data->dpy, w, &info); /* %%% Icky-poo. */
	sub->wb.width = info.width;
	sub->wb.height = info.height;
	sub->wb.borderWidth = info.border_width;
	(void) XtSetGeometryHandler(dpy, w, (XtGeometryHandler) FormGeometryHandler);
	(void) XtSetEventHandler(dpy, w, (XtEventHandler)SubEventHandler,
				 StructureNotifyMask, (caddr_t)sub);
    }
    subglob = *sub;
    XtGetResources(dpy, subresources, XtNumber(subresources), args, argCount,
		   w, "ignore", "Ignore", &names, &classes);
    *sub = subglob;
    XrmFreeNameList(names);
    XrmFreeClassList(classes);
    RefigureLocations(data);
    XMapWindow(data->dpy, w);
}


/*
 * Remove a subwidget from a form.  Doesn't delete the subwidget. 
 */

void XtFormRemoveWidget(dpy, mywin, w)
Display *dpy;
Window mywin, w;
{
    WidgetData data;
    SubWidgetData sub;
    Boolean found;
    int i;
    if ((data = DataFromWindow(dpy, mywin)) == NULL ||
	(sub = SubFromWindow(dpy, w)) == NULL) return;
    found = FALSE;
    for (i=0 ; i<data->numsub ; i++) {
	if (data->sub[i]->fromhoriz == w)
	    data->sub[i]->fromhoriz = sub->fromhoriz;
	if (data->sub[i]->fromvert == w)
	    data->sub[i]->fromvert = sub->fromvert;
	if (!found) found = (data->sub[i] == sub);
	if (found) data->sub[i] = data->sub[i+1];
    }
    if (found) (data->numsub)--;
    XtSetEventHandler(dpy, w, (XtEventHandler) SubEventHandler,
		      (unsigned long) 0, (caddr_t) NULL);
    (void) XtClearGeometryHandler(dpy, w);
    (void) XDeleteContext(dpy, w, subContext);
    XtFree((char *)sub);
}
    


/* 
 * Set or reset figuring
 */

void XtFormDoLayout(dpy, mywin, doit)
Display *dpy;
Window mywin;
Boolean doit;
{
    WidgetData data;
    if ((data = DataFromWindow(dpy, mywin)) == NULL)
	return;
    if (doit && data->dontrefigure > 0) data->dontrefigure--;
    else data->dontrefigure++;
    if (data->needsrefigure) RefigureLocations(data);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.