/* ************************************************************************* */
/*                             FICHIER x11.c                                 */
/* ************************************************************************* */
/* Ce fichier contient la partie C de l'implemenation du Bitmap Virtuel      */
/* pour les stations de travail sous X-Windows version 11.                   */
/* il va de pair avec les fichiers x11.h et x11.ll                           */
/*                                                                           */
/* Auteur: Pierre DUQUESNOY (ILOG)                  Date:  25 Novembre 1988  */
/* ************************************************************************* */

#include "x11.h"

extern char *malloc (); 
extern char *realloc ();

int *lispxerrorsymbol;
int *lisperrorsymbol;
int *lispnil;

int LLXError (dpy, event)
Display *dpy;
XErrorEvent *event;{

	char buffer1 [BUFSIZ];
	char buffer2 [BUFSIZ];
	char message1 [3*BUFSIZ];
	char message2 [BUFSIZ];
	char num [10];
        static  int count = 0; 
	
	XGetErrorText (dpy, event->error←code, buffer1, BUFSIZ);
	sprintf (num, "%d", event->request←code);
	XGetErrorDatabaseText (dpy, "XRequest", num, num, buffer2, BUFSIZ);
	sprintf (message1,
		 "[%d] %s (%d) %s",
		 ++count, buffer2, event->minor←code, buffer1);
	sprintf (message2,
		 "(%d . %d)",
		 (event->resourceid) >> 16, (event->resourceid) & 0xffff);
	pusharg (LLT←T, lispxerrorsymbol);
	pusharg (LLT←STRING, message1); 
	pusharg (LLT←STRING, message2); 
	lispcall (LLT←T, 3, lisperrorsymbol);
	return (0);
}

initialise (llnil, llxerror, llerror)
int *llnil, *llxerror, *llerror;{
	int LLXError ();
	
	lispnil = llnil;
	lispxerrorsymbol = llxerror;
	lisperrorsymbol = llerror; 
	XSetErrorHandler (LLXError);
}

struct LLDisplay *bitprologue (name, mask, override, xmax, ymax, fd)
char *name;
unsigned long mask;
int override;
int *xmax, *ymax;
int *fd;{
	unsigned long whitepixel, blackpixel;
	int screen;
	char *def;
	XGCValues values;
	struct LLDisplay *dpy;
	
       	dpy = (struct LLDisplay *) malloc (sizeof (struct LLDisplay));
	dpy->display = XOpenDisplay (name);
	if ((dpy->display) == NULL) {
		perror (MESSAGE1);
		return ((struct LLDisplay *) NULL);
	}
	screen = XDefaultScreen (dpy->display); 
	*xmax = XDisplayWidth (dpy->display, screen) - 1 ; 
	*ymax = XDisplayHeight (dpy->display, screen) - 1 ; 
	*fd = ConnectionNumber (dpy->display) ;
	dpy->subeventmask = mask ;
	dpy->eventmask = mask|EVENTMASK ;
	dpy->override = override;
	dpy->root = XRootWindow (dpy->display, screen); 
	dpy->colormap = DefaultColormap(dpy->display, screen);
	dpy->depth = XDefaultDepth (dpy->display, screen);
	whitepixel = XWhitePixel (dpy->display, screen);
	blackpixel = XBlackPixel (dpy->display, screen);
	dpy->lispcontext = XUniqueContext ();
	dpy->nbpoints = NBPOINTS;
	dpy->points = (XPoint *) malloc (dpy->nbpoints * sizeof (XPoint)); 
 	if (dpy->points == 0) {
		perror(MESSAGE2);
		return ((struct LLDisplay *) NULL);
	}
	dpy->setimage = XCreateImage (dpy->display,
				      XDefaultVisual (dpy->display, screen),
				      1, XYBitmap, 0, NULL, xmax, 1, 16, 0); 
	values.graphics←exposures = False;
	dpy->fullgc  = XCreateGC (dpy->display, dpy->root, 
				  FULLGCMASK, &values);
        dpy->currentwindow = dpy->root;
        dpy->currentgc = XDefaultGC (dpy->display, screen); 
        dpy->offset←x = 0;
        dpy->offset←y = 0;
	dpy->hostname = malloc(HOSTSIZE);
	gethostname(dpy->hostname, HOSTSIZE);
	return (dpy); 
}

/* ***************************** Pas teste' a` ILOG ***************************
#ifdef S5
gethostname(name, namelen)
char *name;
int namelen; {
    struct utsname uts;
   
    uname(&uts);
    return(strcpy(name, uts.nodename));
}
#endif
**************************************************************************** */

init←pixels (dpy, fore, back, planemask)
struct LLDisplay *dpy;
int fore, back, planemask; {
	dpy->ForePixel = fore;
	dpy->BackPixel = back;
	XSetForeground(dpy->display, dpy->fullgc, fore);
	XSetBackground(dpy->display, dpy->fullgc, back);
	dpy->monoplane = planemask;
}

bitepilogue (dpy)
struct LLDisplay *dpy; {
	XDestroyImage (dpy->setimage);
	XSetCloseDownMode (dpy->display, DestroyAll);
	XCloseDisplay (dpy->display);
        free ((char *)dpy->points); 
	free ((char *)dpy);
}

bitmap←flush (dpy) 
struct LLDisplay *dpy; {
	XFlush (dpy->display) ;
}

bitmap←sync (dpy) 
struct LLDisplay *dpy; {
	XSync (dpy->display, FLUSH);
}

bitmap←refresh (dpy, cursor)
struct LLDisplay *dpy;
Cursor cursor; {
	Window win;
	XSetWindowAttributes xswa;
	
	xswa.override←redirect = True;
	xswa.cursor = cursor; 
	win = XCreateWindow (dpy->display, dpy->root, 0, 0, 9999, 9999, 0,
			     dpy->depth, InputOutput, CopyFromParent,
			     CWOverrideRedirect|CWCursor, &xswa); 
	XMapWindow(dpy->display, win);
	XFlush(dpy->display);
	XDestroyWindow (dpy->display, win);	
	XFlush(dpy->display);
}

GC create←graph←env (dpy, window, font, width, style, pattern, mode)
struct LLDisplay *dpy; 
Window window;
XFontStruct *font;
int width, style, mode;
Pixmap pattern;{
 	GC gc;
	XGCValues values;
	
	values.foreground = dpy->ForePixel ;
	values.background = dpy->BackPixel ;
	values.line←width = width ;
	values.line←style = style ;
	values.tile = pattern ;
	values.font = font->fid;
	values.function = mode;
	values.plane←mask = AllPlanes;
	values.fill←style = FillSolid;
	values.graphics←exposures = False;
	values.subwindow←mode = IncludeInferiors;
	gc = XCreateGC (dpy->display, window, GCMASK, &values);
	return (gc);
}

current←clip (dpy, gc, x, y, w, h)
struct LLDisplay *dpy; 
GC gc;
int x, y, w, h; {
	XRectangle clip;
	
	clip.x = x ;
	clip.y = y ;
	clip.width =  w <= 0 ? 1 : w ;
	clip.height = h <= 0 ? 1 : h ;
	XSetClipRectangles (dpy->display, gc, 0, 0, &clip, 1, Unsorted); 
}

Window root←window (dpy)
struct LLDisplay *dpy; {
	return (dpy->root);
}

Window create←window (dpy, win, x, y, w, h, title, hilited, visible, cursor)
struct LLDisplay *dpy; 
int win;
int x, y, w, h;
char *title;
int hilited, visible; 
Cursor cursor;{
	Window window;
	XSetWindowAttributes attributes;
        XSizeHints hints;
        XClassHint classhint;
        XWMHints wmhints;

	if (w <= 0) w = 1;
	if (h <= 0) h = 1;
	attributes.background←pixel = dpy->BackPixel;                    
	attributes.border←pixel = dpy->ForePixel;
	attributes.override←redirect = dpy->override; 
	attributes.cursor = cursor;  
	attributes.event←mask = NULL;
	window = XCreateWindow (dpy->display, dpy->root, x, y, w, h,
				BORDERWIDTH, dpy->depth, InputOutput,
				CopyFromParent, WINDOWMASK, &attributes);

        hints.x = x;
        hints.y = y;
        hints.width = w; 
        hints.height = h;
        hints.flags = USPosition|USSize;
        XSetNormalHints(dpy->display, window, &hints);

        classhint.res←name = LELISP;
        classhint.res←class = LELISP;
        XSetClassHint(dpy->display, window, &classhint);

	wmhints.flags = InputHint;
	wmhints.input = True;
	XSetWMHints(dpy->display, window, &wmhints);

	XStoreName (dpy->display, window, title); 
        XSetIconName(dpy->display, window, title);
	SetHostName(dpy->display, window, dpy->hostname);

	XSetWindowBorderWidth (dpy->display, window,
			       hilited? BIGBORDERWIDTH : BORDERWIDTH);

	XSelectInput (dpy->display, window, dpy->eventmask);
	return ((set←userdata (dpy, window, win)) ? window : (Window) NULL);
}

/* Why isn't this in the library? My dear! */

static SetHostName(dpy, w, name)
	register Display *dpy;
	Window w;
	char *name;
{
	XChangeProperty(dpy, w, XA←WM←CLIENT←MACHINE, XA←STRING, 
		8, PropModeReplace, (unsigned char *)name, strlen(name));
}

activate←window (dpy, window)
struct LLDisplay *dpy; 
Window window; {
 	XMapWindow (dpy->display, window);
}

Window create←subwindow (dpy, win, x, y, w, h, visible, father)
struct LLDisplay *dpy; 
int win;
int x, y, w, h, visible;
Window father; {
	Window window;
	XSetWindowAttributes attributes;
	
	if (w <= 0) w = 1;
	if (h <= 0) h = 1;
	attributes.event←mask = NULL ;
	window = XCreateWindow (dpy->display, father, x, y, w, h, 0, 0,
				InputOnly, CopyFromParent, 
				SUBWINDOWMASK, &attributes);
	if (visible) XMapWindow (dpy->display, window);
	XSelectInput (dpy->display, window, dpy->subeventmask);
	return ((set←userdata (dpy, window, win)) ? window : (Window) NULL);
}

modify←window (dpy, window, xyp, x, y, whp, w, h, topp, titlep, title, hilitedp, hilited, visiblep, visible)
struct LLDisplay *dpy; 
Window window;
int xyp, whp, topp, titlep, hilitedp, visiblep, x, y, w, h, hilited, visible;
char *title;{
	
	XSelectInput (dpy->display, window, (unsigned long)NULL);
	if (whp){
		if (w <= 0) w = 1;
		if (h <= 0) h = 1;
	}
	if (xyp && whp) XMoveResizeWindow (dpy->display, window, x, y, w, h);
	else if (xyp) XMoveWindow (dpy->display, window, x, y);
	else if (whp) XResizeWindow (dpy->display, window, w, h);
	if (titlep && topp) {
		XStoreName (dpy->display, window, title);
		XSetIconName (dpy->display, window, title);
	}
	if (hilitedp && topp)
		XSetWindowBorderWidth (dpy->display, window,
				       hilited ? BIGBORDERWIDTH : BORDERWIDTH);
	if (visiblep) {
		if (visible) XMapWindow (dpy->display, window);
		else XUnmapWindow (dpy->display, window);
	}
	XSelectInput (dpy->display, window,
		      topp ? dpy->eventmask : dpy->subeventmask);
}

pop←window (dpy, window) 
struct LLDisplay *dpy; 
Window window;{
	XRaiseWindow (dpy->display, window);
}

move←behind←window (dpy, window1) 
struct LLDisplay *dpy; 
Window window1;{
	XLowerWindow (dpy->display, window1);
}

kill←window (dpy, window, gc)
struct LLDisplay *dpy; 
Window window;
GC gc;{
        kill←userdata (dpy, window);
	XDestroyWindow (dpy->display, window);	
	XFreeGC (dpy->display, gc);
}

current←window (dpy, window, gc, dx, dy)
struct LLDisplay *dpy; 
Window window;
GC gc;
int dx, dy; {
	dpy->offset←x = dx ;
        dpy->offset←y = dy ;
	dpy->currentwindow = window;
	dpy->currentgc = gc;
}

int find←window (dpy, x, y)
struct LLDisplay *dpy; 
int x, y;{
	Window w, w1; 
	int x1, y1;
	
	w = dpy->root ;
	do {
		x1= x ;
		y1= y ;
		w1= w ;
		XTranslateCoordinates (dpy->display, dpy->root, w1,
				       x1, y1, &x, &y, &w);
	} while (w != NULL);
	return (get←userdata (dpy, w1));
}

map←window (dpy, window, x, y, lx, ly)
struct LLDisplay *dpy; 
Window window;
int x, y ;
int *lx, *ly;{
	Window w;
	
	XTranslateCoordinates (dpy->display, dpy->root, window,
			       x, y, lx, ly, &w);
	*lx = (*lx + 1) & 0xffff;
	*ly = (*ly + 1) & 0xffff;
}

flush←event (dpy)
struct LLDisplay *dpy; {
	XSync (dpy->display, DISCARD) ;
}

grab←event (dpy, window)
struct LLDisplay *dpy; 
Window window;{
	return (XGrabPointer (dpy->display, window, False, dpy->subeventmask,
			      GrabModeAsync, GrabModeAsync, None, None,
			      CurrentTime)); 
}

ungrab←event (dpy)
struct LLDisplay *dpy; {
	XUngrabPointer (dpy->display, CurrentTime);
}

int *eventp (dpy)
struct LLDisplay *dpy; {
	return XPending (dpy->display) ? (int *) 1 : lispnil ;
}

#include <sys/ioctl.h>

int wait←in←socket (read←fds)
int read←fds;{
	int nb←fds ;
	
        nb←fds = select (32, &read←fds, 0, 0, 0);
	return (nb←fds > 0 ? read←fds : nb←fds);
}

int *read←event (dpy, event)
struct LLDisplay *dpy; 
struct LLEvent *event;{
	XEvent evt;
        int *was←in←socket;
	
	was←in←socket = XPending (dpy->display) ? lispnil : (int *) 1 ;
	if ((was←in←socket == lispnil) ||
	    (wait←in←socket(1<<ConnectionNumber(dpy->display))>0)) {
		XNextEvent (dpy->display, &evt);
		parse←event (dpy, event, &evt);
		return (was←in←socket);
	}else
		return((int *)2);
}

int *peek←event (dpy, event)
struct LLDisplay *dpy; 
struct LLEvent *event;{
	XEvent evt;
        int *was←in←socket;
	
	was←in←socket = XPending (dpy->display) ? lispnil : (int *) 1 ;	
	XPeekEvent (dpy->display, &evt);
	parse←event (dpy, event, &evt);
	return (was←in←socket);
}

read←mouse (dpy, event)
struct LLDisplay *dpy; 
struct LLEvent *event;{
	Window w, w1, w2;
	int x, y, gx, gy;
	unsigned int state;
	char c;
	
	w2 = dpy->root;
	do {
		w = w2;
		XQueryPointer (dpy->display, w, &w1, &w2,
			       &gx, &gy, &x, &y, &state);
	} while (w2 != NULL);
	event->window = (int *) get←userdata (dpy, w) ;
	event->gx = gx & 0xffff;
	event->gy = gy & 0xffff;
	event->x = x & 0xffff;
	event->y = y & 0xffff;	
	c = BUTTON (BIT (state, Button1Mask), 
		    BIT (state, Button2Mask),  
		    BIT (state, Button3Mask));
	event->detail = c == 0 ? 0 : (1 + DETAIL (c, state)) & 0xffff; 
}

parse←event (dpy, llevent, xevent)
struct LLDisplay *dpy; 
struct LLEvent *llevent;
XEvent *xevent;{
	int state = NULL;
	char buffer[BUFFERSIZE];
	KeySym funkey;
	char c;

	llevent->code = xevent->type & 0xffff;
	switch (xevent->type){
	case KeyPress:
	case KeyRelease:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xkey.window) ;
		llevent->gx = xevent->xkey.x←root & 0xffff;
		llevent->gy = xevent->xkey.y←root & 0xffff;
		llevent->x = xevent->xkey.x & 0xffff;
		llevent->y = xevent->xkey.y & 0xffff;
		if (NULL != XLookupString (&(xevent->xkey), buffer, BUFFERSIZE,
					   &funkey, NULL))
			llevent->detail = buffer[0] & 0xffff;
		else{
			llevent->code = FUNKEYCODE ;
			llevent->detail = funkey & 0xffff;
		}
		break;
	case ButtonPress:
	case ButtonRelease:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xbutton.window) ;
		llevent->gx = xevent->xbutton.x←root & 0xffff;
		llevent->gy = xevent->xbutton.y←root & 0xffff;
		llevent->x = xevent->xbutton.x & 0xffff;
		llevent->y = xevent->xbutton.y & 0xffff;
		state = xevent->xbutton.state;
		llevent->detail = DETAIL (xevent->xbutton.button, state)
			& 0xffff ;
		break;
	case MotionNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xmotion.window);
		llevent->gx = xevent->xmotion.x←root & 0xffff;
		llevent->gy = xevent->xmotion.y←root & 0xffff;
		llevent->x = xevent->xmotion.x & 0xffff;
		llevent->y = xevent->xmotion.y & 0xffff;
		state = xevent->xmotion.state;
		if (NULL != (c = BUTTON (BIT (state, Button1Mask), 
					 BIT (state, Button2Mask),  
					 BIT (state, Button3Mask))))
			llevent->detail = DETAIL (c, state) & 0xffff; 
		break;
	case EnterNotify:
	case LeaveNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xcrossing.window);
		llevent->gx = xevent->xcrossing.x←root & 0xffff;
		llevent->gy = xevent->xcrossing.y←root & 0xffff;
		llevent->x = xevent->xcrossing.x & 0xffff;
		llevent->y = xevent->xcrossing.y & 0xffff;
		state = xevent->xcrossing.state;
		if (NULL != (c = BUTTON (BIT (state, Button1Mask), 
					 BIT (state, Button2Mask),  
					 BIT (state, Button3Mask))))
			llevent->detail = DETAIL (c, state) & 0xffff; 
		break;
	case Expose:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xexpose.window);
		llevent->x = xevent->xexpose.x & 0xffff;
		llevent->y = xevent->xexpose.y & 0xffff;
		llevent->w = xevent->xexpose.width & 0xffff;
		llevent->h = xevent->xexpose.height & 0xffff;
		break;
	case GraphicsExpose:
		llevent->window = lispnil ;
		llevent->x = xevent->xgraphicsexpose.x & 0xffff;
		llevent->y = xevent->xgraphicsexpose.y & 0xffff;
		llevent->w = xevent->xgraphicsexpose.width & 0xffff;
		llevent->h = xevent->xgraphicsexpose.height & 0xffff;
		break;
	case CreateNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xcreatewindow.window);
		llevent->x = xevent->xcreatewindow.x & 0xffff;
		llevent->y = xevent->xcreatewindow.y & 0xffff;
		llevent->w = xevent->xcreatewindow.width & 0xffff;
		llevent->h = xevent->xcreatewindow.height & 0xffff;
		break;
	case ConfigureNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xconfigure.window);
		llevent->x = xevent->xconfigure.x & 0xffff;
		llevent->y = xevent->xconfigure.y & 0xffff;
		llevent->w = xevent->xconfigure.width & 0xffff;
		llevent->h = xevent->xconfigure.height & 0xffff;
		break;
	case ConfigureRequest:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xconfigurerequest.window);
		llevent->x = xevent->xconfigurerequest.x & 0xffff;
		llevent->y = xevent->xconfigurerequest.y & 0xffff;
		llevent->w = xevent->xconfigurerequest.width & 0xffff;
		llevent->h = xevent->xconfigurerequest.height & 0xffff;
		break;
	case ResizeRequest:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xresizerequest.window);
		llevent->w = xevent->xresizerequest.width & 0xffff;
		llevent->h = xevent->xresizerequest.height & 0xffff;
		break;
	case ReparentNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xreparent.window);
		llevent->x = xevent->xreparent.x & 0xffff;
		llevent->y = xevent->xreparent.y & 0xffff;
		break;
	case GravityNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xgravity.window);
		llevent->x = xevent->xgravity.x & 0xffff;
		llevent->y = xevent->xgravity.y & 0xffff;
		break;
	case DestroyNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xdestroywindow.window);
		break;
	case UnmapNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xunmap.window);
		break;
	case MapNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xmap.window);
		break;
	case FocusIn:
	case FocusOut:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xfocus.window);
		llevent->detail = xevent->xfocus.mode & 0xffff;
		break;
	case NoExpose:
		llevent->window = lispnil;
		break;
	case VisibilityNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xvisibility.window);
		break;
	case KeymapNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xkeymap.window);
		break;
	case CirculateNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xcirculate.window);
		break;
	case PropertyNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xproperty.window);
		break;
	case SelectionNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xcirculaterequest.window);
		break;
	case ColormapNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xcolormap.window);
		break;
	case MappingNotify:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xmapping.window);
		break;
	case ClientMessage:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xclient.window);
		break;
	case SelectionClear:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xselectionclear.window);
		break;
	case MapRequest:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xmaprequest.window);
		break;
	case CirculateRequest:
		llevent->window = (int *) get←userdata
			(dpy, xevent->xcirculaterequest.window);
		break;
	case SelectionRequest:
		break;
	case LASTEvent:
		break;
	}
}

clear←graph←env (dpy, x, y, w, h)
struct LLDisplay *dpy; 
int x, y, w, h;{
	x += dpy->offset←x;
	y += dpy->offset←y;
	if ((w > 0) && (h > 0))
		XClearArea (dpy->display, dpy->currentwindow, 
                            x, y, w, h, False);
}

XFontStruct *load←font (dpy, font)
struct LLDisplay *dpy; 
char *font;{
	return XLoadQueryFont (dpy->display, font);
}

current←font (dpy, font)
struct LLDisplay *dpy; 
XFontStruct *font;{
	XSetFont (dpy->display, dpy->currentgc, font->fid);
}

draw←cn (dpy, x, y, cn, mode)
struct LLDisplay *dpy; 
int x, y;
int mode;
char cn;{
	char string[2];

	x += dpy->offset←x;
	y += dpy->offset←y;
	string [0] = cn;
	if (mode == 3)
		XDrawImageString (dpy->display, dpy->currentwindow, 
				  dpy->currentgc, x, y, string, 1);
	else
		XDrawString (dpy->display, dpy->currentwindow, dpy->currentgc, 
		             x, y, string, 1);
}

draw←string (dpy, x, y, string, start, length, mode)
struct LLDisplay *dpy; 
int x, y, start, length;
int mode;
char *string;{
	x += dpy->offset←x;
	y += dpy->offset←y;
	string += start;
	if (mode == 3)
		XDrawImageString (dpy->display, dpy->currentwindow, 
				  dpy->currentgc, x, y, string, length);
	else
		XDrawString (dpy->display, dpy->currentwindow, dpy->currentgc,
			     x, y, string, length);
}

int width←string (font, string, start, length)
XFontStruct *font;
int start, length;
char *string;{
	string += start;
	return XTextWidth (font, string, length);
}

int height←string (font, string, start, length)
XFontStruct *font;
int start, length;
char *string;{
	XCharStruct overall;
	int direction, ascent, descent;

	string += start;
	XTextExtents (font, string, length,
		      &direction, &ascent, &descent, &overall);	
	return (overall.ascent + overall.descent);
}

int x←base←string (font, string, start, length)
XFontStruct *font;
int start, length;
char *string;{
	XCharStruct overall;
	int direction, ascent, descent;
	
	string += start;
	XTextExtents (font, string, length,
		      &direction, &ascent, &descent, &overall);	
	return overall.lbearing;
}

int y←base←string (font, string, start, length)
XFontStruct *font;
int start, length;
char *string;{
	XCharStruct overall;
	int direction, ascent, descent;
	
	string += start;
	XTextExtents (font, string, length,
		      &direction, &ascent, &descent, &overall);	
	return overall.ascent;
}

current←mode (dpy, mode)
struct LLDisplay *dpy; 
int mode;{
	if (mode == 3)
		XSetPlaneMask (dpy->display, dpy->currentgc, AllPlanes);
	else
		XSetPlaneMask (dpy->display, dpy->currentgc, dpy->monoplane);
	XSetFunction (dpy->display, dpy->currentgc, mode);
}

current←line←style (dpy, width, style)
struct LLDisplay *dpy; 
unsigned width; 
int style;{
	
	XSetLineAttributes (dpy->display, dpy->currentgc, width, style,
			    CapButt, JoinMiter);
}

current←pattern (dpy, pattern)
struct LLDisplay *dpy; 
Pixmap pattern;{
	XSetTile (dpy->display, dpy->currentgc, pattern); 
}

draw←point (dpy, x, y)
struct LLDisplay *dpy; 
int x, y;{
	x += dpy->offset←x;
	y += dpy->offset←y;
	XDrawPoint (dpy->display, dpy->currentwindow, dpy->currentgc, x, y);
}

draw←polymarker (dpy, n, vx, vy)
struct LLDisplay *dpy; 
int n;
int vx[], vy[];{

	if (store←points (dpy, n, vx, vy))		
		XDrawPoints (dpy->display, dpy->currentwindow, dpy->currentgc,
			     dpy->points, n, CoordModeOrigin);
}

draw←line (dpy, x1, y1, x2, y2)
struct LLDisplay *dpy; 
int x1, y1, x2, y2;{
	x1 += dpy->offset←x;
	y1 += dpy->offset←y;
	x2 += dpy->offset←x;
	y2 += dpy->offset←y;
	XDrawLine (dpy->display, dpy->currentwindow, dpy->currentgc,
		   x1, y1, x2, y2);
}

draw←rectangle (dpy, x, y, w, h)
struct LLDisplay *dpy; 
int x, y, w, h;{
	x += dpy->offset←x;
	y += dpy->offset←y;
	if ((w > 0) && (h > 0))
		XDrawRectangle (dpy->display, dpy->currentwindow,
				dpy->currentgc, x, y, w, h);
}

draw←ellipse (dpy, x, y, rx, ry)
struct LLDisplay *dpy; 
int x, y, rx, ry;{
	x += dpy->offset←x - rx;
	y += dpy->offset←y - ry;
	if ((rx > 0) && (ry > 0))
	        XDrawArc (dpy->display, dpy->currentwindow, dpy->currentgc,
	  	          x, y, rx+rx, ry+ry, NULL, TWOPI);
}	
	
draw←polyline (dpy, n, vx, vy)
struct LLDisplay *dpy; 
int n;
int vx[], vy[];{

	if (store←points (dpy, n, vx, vy))
		XDrawLines (dpy->display, dpy->currentwindow, dpy->currentgc,
			    dpy->points, n, CoordModeOrigin);
}

fill←rectangle (dpy, x, y, w, h, pattern)
struct LLDisplay *dpy; 
int x, y, w, h;
int pattern;{
	x += dpy->offset←x;
	y += dpy->offset←y;
	if ((w > 0) && (h > 0)){
		if (pattern > 1) 
			XSetFillStyle (dpy->display, dpy->currentgc,
				       FillTiled);
		XFillRectangle (dpy->display, dpy->currentwindow,
				dpy->currentgc, x, y, w, h);
		if (pattern > 1) 
			XSetFillStyle (dpy->display, dpy->currentgc,
				       FillSolid);
	}
}

fill←ellipse (dpy, x, y, rx, ry, pattern)
struct LLDisplay *dpy; 
int x, y, rx, ry;
int pattern;{

	x += dpy->offset←x - rx;
	y += dpy->offset←y - ry;
	if ((rx > 0) && (ry > 0)){
		if (pattern > 1) 
			XSetFillStyle (dpy->display, dpy->currentgc,
				       FillTiled);
        	XFillArc (dpy->display, dpy->currentwindow, dpy->currentgc,
		          x, y, rx+rx, ry+ry, NULL, TWOPI);
		if (pattern > 1) 
			XSetFillStyle (dpy->display, dpy->currentgc,
				       FillSolid);
	}
}

fill←area (dpy, n, vx, vy, pattern)
struct LLDisplay *dpy; 
int n;
int vx[], vy[];
int pattern;{

	if (store←points (dpy, n, vx, vy)){
		if (pattern > 1) 
			XSetFillStyle (dpy->display, dpy->currentgc,
				       FillTiled);
		XFillPolygon (dpy->display, dpy->currentwindow, dpy->currentgc,
			      dpy->points, n, Complex, CoordModeOrigin);
		if (pattern > 1) 
			XSetFillStyle (dpy->display, dpy->currentgc,
				       FillSolid);
	}
}

/* ************************************************************************* */

int store←points (dpy, n, vx, vy)
struct LLDisplay *dpy; 
int n;
int vx[], vy[];{
	int i;

	while (n > dpy->nbpoints){
		dpy->nbpoints = 2 * dpy->nbpoints ;
		dpy->points = (XPoint *) realloc ((char *)dpy->points,
					     dpy->nbpoints * sizeof (XPoint));
		if (dpy->points == 0) {
			perror(MESSAGE3);
			return (0);
		}
	}
	for (i = 0; i < n; i++){
		dpy->points[i].x = *vx++ + dpy->offset←x ;
		dpy->points[i].y = *vy++ + dpy->offset←y ;
	}
	return (1);
}

int set←userdata (dpy, win, lisp)
struct LLDisplay *dpy; 
Window win;
int lisp; {
	if (XSaveContext (dpy->display, win, dpy->lispcontext, lisp) != NULL) {
		perror(MESSAGE4);
		return (0);
	}
	return (1);
}

int get←userdata (dpy, win)
struct LLDisplay *dpy; 
Window win; {
        int lisp;
	if (XFindContext (dpy->display, win, dpy->lispcontext, &lisp)
	    != NULL)
		lisp = (int) lispnil;
	return (lisp);
}

kill←userdata (dpy, win)
struct LLDisplay *dpy; 
Window win;{
	
	XDeleteContext (dpy->display, win, dpy->lispcontext);
}

/* ************************************************************************* */

GC default←gc (dpy)
struct LLDisplay *dpy; {
	return dpy->fullgc;
}

Pixmap create←bitmap (dpy, w, h)
struct LLDisplay *dpy; 
unsigned int w, h ;{
	Pixmap pixmap; 
	
	if (w <= 0) w = 1;
	if (h <= 0) h = 1;
	pixmap = XCreatePixmap (dpy->display, dpy->root, w, h, dpy->depth);
	return (pixmap); 
}

kill←bitmap (dpy, bitmap)
struct LLDisplay *dpy; 
Pixmap bitmap;{
	XFreePixmap (dpy->display, bitmap);
}
 
bitblit (dpy, pixmap1, pixmap2, x1, y1, x2, y2, w, h, gc)
struct LLDisplay *dpy; 
Drawable pixmap1, pixmap2;
GC gc;
int x1, y1, x2, y2;
unsigned int w, h;{
	if ((w > 0) && (h > 0))
 		XCopyArea (dpy->display, pixmap2, pixmap1, gc, 
 			   x2, y2, w, h, x1, y1);
}

set←bit←line (dpy, pixmap, x, y, string, w)
struct LLDisplay *dpy; 
Drawable pixmap;
int x, y;
char *string;
int w;{
	if (w > 0){
		dpy->setimage->data = string;
		XPutImage (dpy->display, pixmap, dpy->fullgc, dpy->setimage,
			   0, 0, x, y, w, 1);
	}
}

get←bit←line (dpy, pixmap, x, y, string, w)
struct LLDisplay *dpy; 
Drawable pixmap;
int x, y;
char *string;
int w;{
	XImage *getimage;
	int i;
	int mask;
	
	if (w > 0){
		mask = 0;
 		getimage = XGetImage (dpy->display, pixmap, x, y, w, 1, 1,
			   	      XYPixmap);
		if (dpy->ForePixel == 0) mask = 0xff;  
		for (i = 0; i < ((w+15)/16)*2; i++)
			string [i] = mask ↑ getimage->data [i];
		XDestroyImage (getimage);
	}
}


int bmref (dpy, pixmap, x, y)
struct LLDisplay *dpy; 
Drawable pixmap;
int x, y;{
	XImage *getimage;
	int bit;
	
	getimage = XGetImage (dpy->display, pixmap, x, y, 1, 1, 1, XYPixmap);
	bit = XGetPixel (getimage, 0, 0);
	if (dpy->ForePixel == 0)
		bit = !bit;
	XDestroyImage (getimage);
	return (bit);
}

bmset (dpy, pixmap, x, y, bit)
struct LLDisplay *dpy; 
Drawable pixmap;
int x, y;
int bit;{
	dpy->setimage->data = EMPTYSTRING;
	XPutPixel (dpy->setimage, 0, 0, bit);
	XPutImage (dpy->display, pixmap, dpy->fullgc, dpy->setimage,
		   0, 0, x, y, 1, 1); 
}


Pixmap pixmap←to←bitmap (dpy, pixmap, w, h)
struct LLDisplay *dpy;
Pixmap pixmap;
int w, h; {
	Pixmap bitmap;
	GC monoplanegc;
	XGCValues values;
	
	bitmap = XCreatePixmap (dpy->display, dpy->root, w, h, 1);
	values.graphics←exposures = False;
	monoplanegc = XCreateGC (dpy->display, bitmap, GCGraphicsExposures, 
				 &values);
	XCopyPlane (dpy->display, pixmap, bitmap, monoplanegc,
		    0, 0, w, h, 0, 0, dpy->monoplane);
	XFreeGC(dpy->display, monoplanegc);
	return (bitmap);
}

Cursor create←cursor (dpy, cursor)
struct LLDisplay *dpy;
int cursor; {
	return (XCreateFontCursor (dpy->display, cursor));
}

Cursor make←cursor (dpy, pixmap1, pixmap2, fgr, fgg, fgb,
		    bgr, bgg, bgb, x, y)
struct LLDisplay *dpy; 
Pixmap pixmap1, pixmap2;
int fgr, fgg, fgb, bgr, bgg, bgb;
int x, y;{
	XColor fore, back;
	
	fore.red = 2*fgr;
	fore.green = 2*fgg;
	fore.blue = 2*fgb;
	back.red = 2*bgr;
	back.green = 2*bgg;
	back.blue = 2*bgb;
        return (XCreatePixmapCursor (dpy->display, pixmap1, pixmap2,
                                     &fore, &back, x, y)) ;
}

current←cursor (dpy, cursor)
struct LLDisplay *dpy; 
Cursor cursor;{
	XDefineCursor (dpy->display, dpy->currentwindow, cursor); 
}

move←cursor (dpy, x2, y2)
struct LLDisplay *dpy; 
int x2, y2;{
	XWarpPointer (dpy->display, None, dpy->root, 0, 0, 0, 0, x2, y2);
}

/* ************************************************************************* */
/*                               La Couleur                                  */
/* ************************************************************************* */

int make←color (dpy, r, g, b, color) 
struct LLDisplay *dpy;
int r, g, b;
struct LLColor *color; {
	XColor xcolor;

	xcolor.red = 2*r;
	xcolor.green= 2*g;
	xcolor.blue = 2*b;
	if (XAllocColor (dpy->display, dpy->colormap, &xcolor) == NULL)
      		 return (-1);
	color->red = xcolor.red / 2;
	color->green = xcolor.green / 2;
	color->blue = xcolor.blue / 2;
	return (xcolor.pixel);
}

int make←mutable←color (dpy, r, g, b)
struct LLDisplay *dpy;
int r, g, b; {
	XColor xcolor;
	
	if (XAllocColorCells (dpy->display, dpy->colormap, 
			      0, 0, 0, &xcolor.pixel, 1) == NULL)
		return (-1);
	
	xcolor.red = 2*r;
	xcolor.green= 2*g;
	xcolor.blue = 2*b;
	xcolor.flags = DoRed|DoGreen|DoBlue;
	XStoreColor (dpy->display, dpy->colormap, &xcolor);
	
	return (xcolor.pixel);
}

int make←named←color (dpy, name, color) 
struct LLDisplay *dpy;
char *name; 
struct LLColor *color; {
	XColor xcolor;

	if (XParseColor (dpy->display, dpy->colormap, name, &xcolor) == NULL)
 		return (-1);
	if (XAllocColor (dpy->display, dpy->colormap, &xcolor) == NULL)
		return (-1);
	color->red = xcolor.red / 2;
	color->green = xcolor.green / 2;
	color->blue = xcolor.blue / 2;
	return (xcolor.pixel);
}

kill←color (dpy, pix) 
struct LLDisplay *dpy;
int pix; {
	XColor color;
	color.pixel = pix;
	XFreeColors (dpy->display, dpy->colormap, &color, 1, 0);
}

current←foreground (dpy, pix) 
struct LLDisplay *dpy;
int pix; {
    XSetForeground(dpy->display, dpy->currentgc, pix);
    XSetForeground(dpy->display, dpy->fullgc, pix);
}

current←background (dpy, pix) 
struct LLDisplay *dpy;
int pix; {
    XSetBackground(dpy->display, dpy->currentgc, pix);
    XSetBackground(dpy->display, dpy->fullgc, pix);
}

int color←component (dpy, pix, red, green, blue, flag)
struct LLDisplay *dpy; 
int pix;
int red, green, blue, flag; {
	XColor color;

	color.red = 2*red;
	color.green = 2*green;
	color.blue = 2*blue;
	color.pixel = pix;
	switch (flag) {
	case 0: 
		color.flags = DoRed;
		break;
	case 1: 
		color.flags = DoGreen;
		break;
	case 2: 
		color.flags = DoBlue;
		break;
	}
	XStoreColor (dpy->display, dpy->colormap, &color);
	return 1;
}

char *get←default (dpy, prog, item)
struct LLDisplay *dpy; 
char *prog, *item; {
	char *res;
       	res = XGetDefault (dpy->display, prog, item);
	return res ? res : "";
}

set←menu←attributes (dpy, window)
struct LLDisplay *dpy; 
Window window; {
	XSetWindowAttributes xswa;
	
	xswa.override←redirect = True;
	xswa.save←under = True;
	XChangeWindowAttributes (dpy->display, window,
				 CWOverrideRedirect|CWSaveUnder,
				 &xswa);
}

/* ************************************************************************* */
/* Cause Bug X11R2 : La CURSOR Fonte n'est pas liberee au XCloseDisplay      */
/*                   et mal reallouee au XCreateFontCursor                   */
/* ************************************************************************* */

#ifdef x11r2
#define CURSORFONT "cursor"
Cursor XCreateFontCursor(dpy, which)
Display *dpy;
unsigned int which;
{
	static XColor foreground = { 0,    0,     0,     0  }; 
	static XColor background = { 0, 65535, 65535, 65535 }; 
	static Font cfont;
	
	cfont = XLoadFont(dpy, CURSORFONT);
	return (XCreateGlyphCursor (dpy, cfont, cfont, which, which + 1,
				    &foreground, &background));
}
#endif x11r2

/* ************************************************************************* */
/* ************************************************************************* */

/* ****************************************************************************
               A TESTER SANS LES PATCHES CLOCK

#include <sys/time.h>

extern double accudouble;
extern int **prtmsgs;   
#define  errreturn(M,V)   { if(**prtmsgs != 0) perror(M) ; return(V); }

setalarm(f) double f; {
	struct itimerval nit,oit;
	register int secs;

	secs = (long) (f * 1e+6);
	timerclear(&nit.it←interval);
	nit.it←value.tv←sec = secs / 1000000;
	nit.it←value.tv←usec = secs % 1000000;
	if (setitimer(ITIMER←REAL, &nit, &oit) < 0) {
		accudouble = 0;
		errreturn("clockalarm", -1);
	}
	accudouble = (oit.it←value.tv←sec + oit.it←value.tv←usec * 1e-6);
}

extern ll←break(), ll←merro(), ll←clock(); 

#include <signal.h>

inton () {
#ifndef LLDEBUG

#ifdef BSD42
        sigsetmask(0);
        signal(SIGALRM, ll←clock);
#endif BSD42
#ifdef S5
        signal(SIGALRM, ll←clock);
#endif S5
#ifdef V7
        signal(SIGALRM, ll←clock);
#endif V7
#ifdef BACKGND
        if(!background){
           signal(SIGINT, ll←break);
	}
#else BACKGND
        signal(SIGINT,  ll←break);
#endif BACKGND
        signal(SIGILL,  ll←merro);
        signal(SIGBUS,  ll←merro);
        signal(SIGSEGV, ll←merro);
	signal(SIGTRAP, ll←merro);
#ifndef SPS9
        signal(SIGFPE,  ll←merro);
#else
        signal(SIGFPE,  SIG←IGN);
#endif SPS9
#endif LLDEBUG
}               

intoff () {
#ifndef LLDEBUG
#ifdef LLMOUSE
        signal(SIGMOUS, SIG←IGN);
#endif LLMOUSE
#ifdef BSD42
#define mask(s) (1 << ((s)-1))
	return(sigblock (mask (SIGALRM) | mask(SIGINT)));
#else BSD42 
        signal(SIGINT,  SIG←IGN);
#endif LLDEBUG
}               

**************************************************************************** */