[comp.sys.sgi] panel04/06

dat@ORVILLE.NAS.NASA.GOV ("David A. Tristram") (08/19/88)

#!/bin/sh
# this is part 4 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file g_gets.c continued
#
CurArch=4
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> g_gets.c
Xchar *g_getstring(stringcolor, backcolor, cursorcolor, protostring, maxstringlen)
X		   /* do a gets without using textports ..echoing the    */
X		   /* character on the screen, erasing when necessary    */
X/*-----------------------------------------------------------------------*/
XColorindex stringcolor, backcolor, cursorcolor;
Xchar *protostring;	/* initial string */
Xint maxstringlen;
X{
X    int g_getchar();
X    register int i;
X    int c;
X    int protolen = strlen(protostring);
X
X    char_width  = strwidth("a");
X    char_height  = getheight();
X    char_descender = getdescender();
X    getcpos(&ix, &iy);
X
X    numqueued = 0;
X    numevents = 0;
X    capitalize = 0;
X    controlize = 0;
X
X    saveq();
X    pushviewport();
X    pushattributes();
X    pushmatrix();
X    screenspace();
X
X    frontbuffer(1); backbuffer(0);
X
X    for (i = 1; i <= MAXKBDBUT; i++) qdevice(i);
X    if (protolen>maxstringlen) goto exit;
X
Xrestart:
X    bzero(string, maxstringlen);
X    color(cursorcolor);
X    drawcursor(protolen, maxstringlen);
X    if (protolen) {
X	strcpy(string, protostring);
X	cmov2i(ix,iy);
X	color(stringcolor);
X	charstr(protostring);
X    }
X    for (i = protolen;;) {
X	string[i]=(char)(c=g_getchar());
X 	switch(c) {
X	    case '\n':
X	    case '\r':
X	    case '\0':
X	    case QUIT:
X		string[i] = '\0';
X		goto exit;
X	    case RESET:
X		color(backcolor);
X		drawcursor(i, maxstringlen);
X		cmov2i(ix,iy);
X		charstr(string);
X		cmov2i(ix,iy);
X		protolen=0;
X		goto restart;
X	    case ERASE:
X		if (i == 0) break;
X		string[i--] = '\0';
X		color(backcolor);
X		drawcursor(i+1, maxstringlen);
X		color(cursorcolor);
X		drawcursor(i, maxstringlen);
X	    	cmov2i(ix+ i*char_width , iy); 
X		break;
X	    default:
X		if (!(i<maxstringlen)) {
X		    ringbell();
X		    break;
X		}
X		color(backcolor);
X		drawcursor(i, maxstringlen);
X		color(cursorcolor);
X		drawcursor(i+1, maxstringlen);
X	    	color(stringcolor);
X		charstr(&string[i++]);
X		break;
X	}
X    }
Xexit:
X    for (i = 1; i <= MAXKBDBUT; i++) unqdevice(i);
X    restoreq();
X    popmatrix();
X    popattributes();
X    popviewport();
X    return(string);
X}
X
Xstatic int drawcursor(pos, max)
Xint pos, max;
X{
X    if (pos<max) {	/* normal */
X	rectfi(ix+pos*char_width,
X	       iy-char_descender,
X	       ix+pos*char_width+char_width,
X	       iy-char_descender+char_height);
X    } else {		/* at end */
X	rectfi(ix+(max-1)*char_width,
X	       iy-char_descender,
X	       ix+(max-1)*char_width+char_width,
X	       iy-char_descender+char_height);
X    }
X}
X
X/*-----------------------------------------------------------------------*/
Xstatic int g_getchar()   /* do a getchar without using textports	 */
X/*-----------------------------------------------------------------------*/
X{
X    short val; 
X    char upperkey(), lowerkey();
X    Device key;
X
X    for(;;){
X	switch (key= qread(&val)) {
X
X#ifdef IRIS_4D
X	    case LEFTCTRLKEY:
X	    case RIGHTCTRLKEY:	controlize = val; break;
X#else  /* IRIS_4D */
X	    case CTRLKEY:	controlize = val; break;
X#endif /* IRIS_4D */
X
X	    case LEFTSHIFTKEY:
X	    case RIGHTSHIFTKEY: capitalize = val; break;
X
X	    case DELKEY:
X	    case BACKSPACEKEY:  if (val) return(ERASE);
X
X	    case ESCKEY:	if (val) return(QUIT);
X
X	    case LEFTMOUSE:	
X	    case REDRAW:
X	    case RIGHTMOUSE:
X	    case MIDDLEMOUSE:
X		saveevent(key,val);
X		if (val) return(QUIT);
X		break;
X
X	    case INPUTCHANGE:
X	    case MOUSEX:
X	    case MOUSEY:
X		saveevent(key,val);
X		break;
X 	    default:
X		if (controlize)
X		switch (key) {
X		    case UKEY:
X			return RESET;
X		    default:
X			break;
X		} else if (val){
X		    if (capitalize) return(upperkey(key));
X		    else return (lowerkey(key));
X	 	}
X	}
X    }
X}
X
X/*-------------------------------------------------------------------------*/
Xstatic char lowerkey(dev) /* maps sgi keyboard device numbers to printable */
X			  /* ascii characters. null for nonprintables      */ 
X/*-------------------------------------------------------------------------*/
X{
X    register i;
X
X    for (i = 0; keyboard[i].device_num != -1; i++)
X	if(dev == keyboard[i].device_num) return(keyboard[i].lower);
X    return('\0');
X}
X
X/*-------------------------------------------------------------------------*/
Xstatic char upperkey(dev) /* maps sgi keyboard device numbers to printable */
X			  /* ascii characters. null for nonprintables	   */
X/*-------------------------------------------------------------------------*/
X{
X    register i;
X
X    for (i = 0; keyboard[i].device_num != -1; i++)
X	if(dev == keyboard[i].device_num) return(keyboard[i].upper);
X    return('\0');
X}
X
X
X/*------------------------------------------------------------------------*/
Xstatic saveq()  /* save the device numbers of all keyboard queued devices */
X		/* and unqueue them					  */
X/*------------------------------------------------------------------------*/
X{
X   register i;
X
X   buf_state = getbuffer();
X   for (i = 1; i <= MAXKBDBUT; i++)
X       if (isqueued(i)) {
X	   qstack[numqueued++] = i;
X	   unqdevice(i);
X   }
X}
X
X/*-----------------------------------------------------------------------*/
Xstatic restoreq()	/* requeue all devices that were queued 	 */
X/*-----------------------------------------------------------------------*/
X{
XDevice dev;
Xshort data;
X
X    if (buf_state & 1) backbuffer(1);
X    else backbuffer(0);
X    if (buf_state & 2) frontbuffer(1);
X    else frontbuffer(0);
X    while (qtest()) {
X	dev=qread(&data);
X	saveevent(dev,data);
X    }
X    while (numqueued) qdevice(--numqueued);
X    restoreevents();
X}
X
Xstatic saveevent(dev,data)
XDevice dev;
Xshort data;
X{
X    eventq[numevents].dev=dev;
X    eventq[numevents].data=data;
X    numevents++;
X}
X
Xstatic restoreevents()
X{
Xint i;    
X    for (i=0;i<numevents;i++) qenter(eventq[i].dev,eventq[i].data);
X}
SHAR_EOF
chmod 0644 g_gets.c || echo "restore of g_gets.c fails"
sed 's/^X//' << 'SHAR_EOF' > gets.c &&
X/*
X *	this software is in the public domain, it may not be resold
X *	or relicensed.  Do not remove this notice.  Send modifications
X *	and requests for most recent version to:
X *
X *	Author:  David A. Tristram
X *		 NASA  Ames Research Center
X *		 MS 258-5
X *		 Moffett Field, CA  94035
X *		 415-694-4404
X *		 dat@orville.nas.nasa.gov
X */
X/*
X * g_gets.c	: How to read a string from the keyboard without a textport.
X *	
X */
X#include <stdio.h>
X#include <gl.h>
X#include <device.h>
X
X#define MAXSTRINGLEN 	80
X#define MAXQUEUED 	100
X#define MAXDEVICES 	1024
X#define ERASE   	-2
X#define QUIT		-1
X
Xtypedef struct {
X    int device_num;
X    char lower;
X    char upper;
X} KEY ;
X
Xstatic KEY keyboard[] = 
X{
X    {	 AKEY,		'a',	'A' },
X    {	 BKEY,		'b',    'B' },
X    {	 CKEY,		'c',    'C' },
X    {	 DKEY,		'd',    'D' },
X    {	 EKEY,		'e',    'E' },
X    {	 FKEY,		'f',    'F' },
X    {	 GKEY,		'g',    'G' },
X    {	 HKEY,		'h',    'H' },
X    {	 IKEY,		'i',    'I' },
X    {	 JKEY,		'j',    'J' },
X    {	 KKEY,		'k',    'K' },
X    {	 LKEY,		'l',    'L' },
X    {	 MKEY,		'm',    'M' },
X    {	 NKEY,		'n',    'N' },
X    {	 OKEY,		'o',    'O' },
X    {	 PKEY,		'p',    'P' },
X    {	 QKEY,		'q',    'Q' },
X    {	 RKEY,		'r',    'R' },
X    {	 SKEY,		's',    'S' },
X    {	 TKEY,		't',    'T' },
X    {	 UKEY,		'u',    'U' },
X    {	 VKEY,		'v',    'V' },
X    {	 WKEY,		'w',    'W' },
X    {	 XKEY,		'x',    'X' },
X    {	 YKEY,		'y',    'Y' },
X    {	 ZKEY,		'z',    'Z' },
X    {	 ZEROKEY,	'0',    ')' },
X    {	 ONEKEY,	'1',    '!' },
X    {	 TWOKEY,	'2',    '@' },
X    {	 THREEKEY,	'3',    '#' }, 
X    {	 FOURKEY,	'4',    '$' }, 
X    {	 FIVEKEY,	'5',    '%' }, 
X    {	 SIXKEY,	'6',    '^' }, 
X    {	 SEVENKEY,	'7',    '&' }, 
X    {	 EIGHTKEY,	'8',    '*' }, 
X    {	 NINEKEY,	'9',    '(' },
X    { 	 SEMICOLONKEY,	';',    ':' },
X    {	 PERIODKEY,	'.',    '>' },
X    {	 COMMAKEY,	',',    '<' },
X    {	 ACCENTGRAVEKEY,'`',    '~' },
X    {	 MINUSKEY,	'-',    '_' },
X    {	 QUOTEKEY,	'\'',    '"' },
X    {	 BACKSLASHKEY,	'\\',    '|' },
X    {	 EQUALKEY,	'=',    '+' },
X    {	 LEFTBRACKETKEY,'[',    '{' },
X    {	 RIGHTBRACKETKEY,']',   '}' },
X    {	 VIRGULEKEY,	'/',	'?' },
X    {	 SPACEKEY,	' ',    '\0' },
X    {	 TABKEY,	'\t',    '\0' },
X    {	 RETKEY,	'\r',    '\0' },
X    {	 LINEFEEDKEY,	'\n',    '\0' },
X    {	 BREAKKEY,	'\0',    '\0' },
X    {	 BACKSPACEKEY,	'\b',    '\0' },
X    {	 DELKEY,	'\0',    '\0' },
X    {	 SETUPKEY,	'\0',    '\0' },
X    {	 CTRLKEY,	'\0',    '\0' },
X    {	 CAPSLOCKKEY,	'\0',    '\0' },
X    {	 RIGHTSHIFTKEY,	'\0',    '\0' },
X    {	 LEFTSHIFTKEY,	'\0',    '\0' },
X    {	 NOSCRLKEY,	'\0',    '\0' },
X    {	 ESCKEY,	'\0',    '\0' },
X    {	 LEFTARROWKEY,	'\0',    '\0' },
X    {	 DOWNARROWKEY,	'\0',    '\0' },
X    {	 RIGHTARROWKEY,	'\0',    '\0' },
X    {	 UPARROWKEY,	'\0',    '\0' },
X    {	 -1,		'\0',    '\0' } 
X};
X
X
Xstatic char string[MAXSTRINGLEN];
Xstatic int bufmode;
X
X/*-----------------------------------------------------------------------*/
Xchar *g_gets(ix, iy, stringcolor, backcolor)
X		   /* do a gets without using textports ..echoing the    */
X		   /* character on the screen, erasing when necesary     */
X/*-----------------------------------------------------------------------*/
XColorindex stringcolor, backcolor;
X{
X
X    static int inited = 0;
X    char g_getchar();
X    int i;
X    int char_width = strwidth("a");
X
X    saveq();
X    frontbuffer(TRUE);
X    backbuffer(FALSE);
X
X    for (i = 1; i <= MAXKBDBUT; i++) qdevice(i);
X    cmov2i(ix, iy);
X    bzero(string, MAXSTRINGLEN);
X
X    for (i = 0;  i < MAXSTRINGLEN;) {
X 	switch(string[i] = g_getchar())
X	{
X	    case '\n':
X	    case '\r':
X/* checkit(); */
X		string[i] = '\0';
X		goto exit;
X
X	    case '\0':
X	    case QUIT:
X		for (i = 1; i <= MAXKBDBUT; i++) unqdevice(i);
X		restoreq();
X		return(NULL);
X
X	    case ERASE:
X		if (i == 0) break;
X		string[i--] = '\0';
X	    	cmov2i(ix+ i*char_width , iy); 
X	        color(backcolor);
X		charstr(&string[i]);
X	    	cmov2i(ix+ i*char_width , iy); 
X		break;
X
X	    default:
X/* checkit(); */
X	    	color(stringcolor);
X		charstr(&string[i++]);
X		break;
X	}
X    }
X
Xexit:
X    for (i = 1; i <= MAXKBDBUT; i++) unqdevice(i);
X    restoreq();
X    return(string);
X}
X
X/*-----------------------------------------------------------------------*/
Xstatic char g_getchar()   /* do a getchar without using textports	 */
X/*-----------------------------------------------------------------------*/
X{
X    static capitalize = 0;
X    short val; 
X    char upperkey(), lowerkey();
X    long key;
X
X    for(;;){
X	key= qread(&val);
X	if (key == LEFTSHIFTKEY || key == RIGHTSHIFTKEY){
X	    capitalize = val;
X	    continue;
X	}else if (val)	/* do until user holds a key down */
X	    break;
X    }
X
X    switch(key)
X    {
X	case DELKEY:
X	case BACKSPACEKEY:
X	    return(ERASE);
X
X	case ESCKEY:
X	    return(QUIT);
X 	default:
X	    if (capitalize) return(upperkey(key));
X	    else return (lowerkey(key));
X    }
X}
X
X/*-------------------------------------------------------------------------*/
Xstatic char lowerkey(dev) /* maps sgi keyboard device numbers to printable */
X			  /* ascii characters. null for nonprintables      */ 
X/*-------------------------------------------------------------------------*/
X{
X    int i;
X
X    for (i = 0; keyboard[i].device_num != -1; i++)
X	if(dev == keyboard[i].device_num) return(keyboard[i].lower);
X    return('\0');
X}
X
X/*-------------------------------------------------------------------------*/
Xstatic char upperkey(dev) /* maps sgi keyboard device numbers to printable */
X			  /* ascii characters. null for nonprintables	   */
X/*-------------------------------------------------------------------------*/
X{
X    int i;
X
X    for (i = 0; keyboard[i].device_num != -1; i++)
X	if(dev == keyboard[i].device_num) return(keyboard[i].upper);
X    return('\0');
X}
X
X
Xstatic int numqueued = 0;
Xstatic int qstack[MAXQUEUED];
X
X/*------------------------------------------------------------------------*/
Xstatic saveq()  /* save the device numbers of all keyboard queued devices */
X		/* and unqueue them					  */
X/*------------------------------------------------------------------------*/
X{
X   int i;
X
X   bufmode = getbuffer();   /* also save enabled buffers */
X   for (i = 1; i <= MAXKBDBUT; i++)
X       if (isqueued(i)) {
X	   qstack[numqueued++] = i;
X	if (numqueued >= MAXQUEUED) {
X	   fprintf(stderr, "Eeeek qstack overflow\n");
X	   return;
X 	}
X        unqdevice(i);
X   }
X}
X
X/*-----------------------------------------------------------------------*/
Xstatic restoreq()	/* requeue all devices that were queued 	 */
X/*-----------------------------------------------------------------------*/
X{
X    backbuffer(bufmode&0x1);	/* also restore enabled buffers */
X    frontbuffer(bufmode&0x2);
X    while (numqueued) qdevice(--numqueued);
X    qreset();
X}
SHAR_EOF
chmod 0644 gets.c || echo "restore of gets.c fails"
sed 's/^X//' << 'SHAR_EOF' > mouse.c &&
X/*
X *	this software is in the public domain, it may not be resold
X *	or relicensed.  Do not remove this notice.  Send modifications
X *	and requests for most recent version to:
X *
X *	Author:  David A. Tristram
X *		 NASA  Ames Research Center
X *		 MS 258-5
X *		 Moffett Field, CA  94035
X *		 415-694-4404
X *		 dat@orville.nas.nasa.gov
X */
X#include <gl.h>
X#include "panel.h"
X
Xvoid _newvalmouse(a,p,sx,sy)
XActuator *a;
XPanel *p;
XScreencoord sx,sy;
X{
X  Mouse *ad=(Mouse *)a->data;
X
X  ad->x=p->x+sx; /* relative to screen origin */
X  ad->y=p->y+sy;
X
X  if (a->active) a->val=1.0;
X  else		 a->val=0.0;
X}
X
Xvoid
X_addmouse(a, p)
XActuator *a;
XPanel *p;
X{
X  if (pnl_mouse_act) {
X    fprintf(stderr, "libpanel: warning, duplicate pnl_mouse actuator\n");
X    return;
X  }
X  a->data=alloc(sizeof(Mouse));
X  pnl_mouse_act=a;
X}
X
Xvoid
Xpnl_mouse(a)
XActuator *a;
X{
X    a->type=PNL_MOUSE;
X
X/*     a->automatic=TRUE; */
X    a->visible=FALSE;
X    a->newvalfunc=_newvalmouse;
X    a->addfunc=_addmouse;
X    a->drawfunc=NULL;
X}
X
SHAR_EOF
chmod 0644 mouse.c || echo "restore of mouse.c fails"
sed 's/^X//' << 'SHAR_EOF' > palette.c &&
X/*
X *	this software is in the public domain, it may not be resold
X *	or relicensed.  Do not remove this notice.  Send modifications
X *	and requests for most recent version to:
X *
X *	Author:  David A. Tristram
X *		 NASA  Ames Research Center
X *		 MS 258-5
X *		 Moffett Field, CA  94035
X *		 415-694-4404
X *		 dat@orville.nas.nasa.gov
X */
X#include <gl.h>
X#include "panel.h"
X
X#define FINE_CONTROL_FACTOR	0.05
X
Xvoid setpaletteval(a, x, dist)
X     Actuator *a;
X     Coord x;
X     float dist;
X{
X  Palette *ad=(Palette *)a->data;
X
X  if (pnl_justdown) {
X    a->val=PNL_WORLD_TO_VAL(x, a->minval, a->maxval, dist);
X    ad->wsave=x;
X  }
X  
X  if (pnl_controlkey)  a->val+= ad->finefactor
X                           *(x-ad->wsave)/dist*(a->maxval-a->minval);
X  else {
X    a->val=PNL_WORLD_TO_VAL(x, a->minval, a->maxval, dist);
X  }
X  a->val=RANGE(a->val, a->maxval, a->minval);
X 
X  ad->wsave=x;
X }
X
Xvoid _newvalvpalette(a,p,sx,sy)
X     Actuator *a;
X     Panel *p;
X     Screencoord sx,sy;
X{    
X  Palette *ad=(Palette *)a->data;
X  Coord wx, wy;
X  float tmp;
X  
X  if (!a->active) return;
X  
X  mapw2(p->vobj,sx,sy,&wx,&wy);
X  
X  setpaletteval(a, wy-a->y, a->h);
X}
X
Xvoid _newvalhpalette(a,p,sx,sy)
X     Actuator *a;
X     Panel *p;
X     Screencoord sx,sy;
X{    
X  Palette *ad=(Palette *)a->data;
X  Coord wx, wy;
X  
X  if (!a->active) return;
X  
X  mapw2(p->vobj,sx,sy,&wx,&wy);
X  
X  setpaletteval(a, wx-a->x, a->w);
X}
X
Xvoid
X_drawvpalette(a, p)
XActuator *a;
XPanel *p;
X{
XCoord y;
X
X    pushmatrix();
X
X    translate(a->x,a->y,0.0);
X
X    setshade((Colorindex)a->minval);
X    pmv2(0.0, 0.0);
X    pdr2(a->w, 0.0);
X    setshade((Colorindex)a->maxval);
X    pdr2(a->w, a->h);
X    pdr2(0.0,  a->h);
X    spclos();
X
X    color(pnl_outline_color);
X    rect(0.0,0.0,a->w,a->h);
X
X    popmatrix();
X    if (a->label) drawlabel(a, p);
X}
X
Xvoid
X_drawhpalette(a, p)
XActuator *a;
XPanel *p;
X{
XCoord y;
X
X    pushmatrix();
X
X    translate(a->x,a->y,0.0);
X
X    setshade((Colorindex)a->minval);
X    pmv2(0.0, 0.0);
X    pdr2(0.0, a->h);
X    setshade((Colorindex)a->maxval);
X    pdr2(a->w, a->h);
X    pdr2(a->w, 0.0);
X    spclos();
X    color(pnl_outline_color);
X    rect(0.0,0.0,a->w,a->h);
X
X    popmatrix();
X    if (a->label) drawlabel(a, p);
X}
X
Xvoid
Xpnl_palette(a)
XActuator *a;
X{
X  Palette *ad;
X
X  a->type=PNL_PALETTE;
X
X  a->data = alloc(sizeof(Palette));
X  a->datasize = sizeof(Palette);
X  ad=(Palette *)a->data;
X  ad->wsave=0.0;
X  ad->finefactor=FINE_CONTROL_FACTOR;
X
X  a->labeltype=PNL_LABEL_BOTTOM;
X  a->w=PNL_SLIDER_WIDTH;
X  a->h=PNL_SLIDER_HEIGHT;
X  a->newvalfunc=_newvalvpalette;
X  a->drawfunc=_drawvpalette;
X}
X
Xvoid
Xpnl_vpalette(a)
XActuator *a;
X{
X  pnl_palette(a);
X  a->type=PNL_VSLIDER;
X
X  a->w=PNL_SLIDER_WIDTH;
X  a->h=PNL_SLIDER_HEIGHT;
X  a->newvalfunc=_newvalvpalette;
X  a->drawfunc=_drawvpalette;
X}
X
Xvoid
Xpnl_hpalette(a)
XActuator *a;
X{
X  pnl_palette(a);
X  a->type=PNL_HSLIDER;
X
X  a->w=PNL_SLIDER_HEIGHT;
X  a->h=PNL_SLIDER_WIDTH;
X  a->newvalfunc=_newvalhpalette;
X  a->drawfunc=_drawhpalette;
X}
X
SHAR_EOF
chmod 0644 palette.c || echo "restore of palette.c fails"
sed 's/^X//' << 'SHAR_EOF' > panel.c &&
X/*
X *	this software is in the public domain, it may not be resold
X *	or relicensed.  Do not remove this notice.  Send modifications
X *	and requests for most recent version to:
X *
X *	Author:  David A. Tristram
X *		 NASA  Ames Research Center
X *		 MS 258-5
X *		 Moffett Field, CA  94035
X *		 415-694-4404
X *		 dat@orville.nas.nasa.gov
X */
X#include <string.h>
X#include <fcntl.h>
X#include <sys/types.h>
X#include <setjmp.h>
X#include <stdio.h>
X#include <gl.h>
X#include <device.h>
X
X#define PNL_EXTERN	/* nothing */
X#define PNL_INIT(X)	= (X)
X#include "panel.h"
X
X#ifdef IRIS_4D
XActuator *pickact(Panel *, Screencoord, Screencoord);
XBoolean _hitact(/*Actuator *, Panel *, Coord, Coord*/);	/* note: can't declare floats */
Xvoid _dumpact(Actuator *, int);
Xvoid _loadact(Actuator *, int);
Xvoid _fixpnl(Panel *);
Xvoid _drawpnl(Panel *);
X#else  IRIS_4D
XActuator *pickact();
XBoolean _hitact();
Xvoid _dumpact();
Xvoid _loadact();
Xvoid _fixpnl();
Xvoid _drawpnl();
X#endif IRIS_4D
X
Xjmp_buf dopanel_return;
Xint pnl_winmouse;
XBoolean pnl_shiftkey_save;
XBoolean pnl_controlkey_save;
X
XPanel
X*mkpanel()
X{
X  Panel *p;
X  int winsave=winget();
X    
X    p=(Panel *)alloc(sizeof(Panel));
X
X    if (pnl_pl) p->next=pnl_pl;
X    else p->next=NULL;
X    pnl_pl=p;
X
X    pnl_table[pnl_id]=(char *)p;
X    p->id=pnl_id++;
X    p->al=NULL;
X    p->lastgroup=NULL;
X    p->active=FALSE;
X    p->gid= -1;
X    p->usergid=winget();
X    p->label=NULL;
X    p->enabled=TRUE;
X    p->fixfunc=_fixpnl;
X    p->drawfunc=_drawpnl;
X    p->downfunc=NULL;
X    p->activefunc=NULL;
X    p->upfunc=NULL;
X    p->dirtycnt=2;
X
X    /* if user touches these, we won't make our
X	own guesses for them in dopanel() */
X    p->x=p->y=p->w=p->h=0;
X
X    p->ppu=PNL_PIXELS_PER_UNIT;
X
X    p->vobj=genobj();
X    makeobj(p->vobj);
X    maketag(1);
X    ortho2(0.0,10.0,0.0,10.0);	/* placeholder viewing transform */
X    closeobj();
X
X    winset(winsave);
X    return p;
X}
X 
X
XActuator
X*mkact(initfunc)
Xvoid (* initfunc)();
X{
XActuator *a;
X
X    a=(Actuator *)alloc(sizeof(Actuator));
X
X    pnl_table[pnl_id]=(char *)a;
X    a->id=pnl_id++;
X    a->active=FALSE;
X    a->key=NULLDEV;
X    a->label=NULL;
X    a->labeltype=PNL_LABEL_BOTTOM;
X    a->addfunc=NULL;
X    a->fixfunc=NULL;
X    a->pickfunc=_hitact;
X    a->dumpfunc=_dumpact;
X    a->loadfunc=_loadact;
X    a->newvalfunc=NULL;
X    a->downfunc=NULL;
X    a->activefunc=NULL;
X    a->upfunc=NULL;
X    a->group=a;
X    a->automatic=FALSE;
X    a->selectable=TRUE;
X    a->visible=TRUE;
X    a->next=NULL;
X    a->w=0.0;
X    a->h=0.0;
X    a->minval=0.0;
X    a->maxval=1.0;
X    a->val=0.0;
X
X    if (initfunc) (* initfunc)(a);
X
X    return a;
X}
X
XActuator
X*_mkuseract(size, initfunc)
Xint size;
X#ifdef IRIS_4D
Xvoid (* initfunc)(Actuator *);
X#else  IRIS_4D
Xvoid (* initfunc)();
X#endif IRIS_4D
X{
X  Actuator *temp = (Actuator *) alloc (size);
X  if (size<sizeof(Actuator))
X    fprintf(stderr,
X      "libpanel:  warning: size in _mkuseract smaller than an Actuator\n");
X  *temp = *mkact(initfunc);   /* note actual structure copy */
X  return temp;
X}
X
Xvoid
Xaddact(a,p)
XActuator *a;
XPanel *p;
X{
X    a->p=p;
X
X    a->next=p->al;
X    p->al=a;
X
X    a->initval=a->val;	/* save for later resets */
X
X    if (a->label) {
X	a->lw=(float)strwidth(a->label)/p->ppu;
X	a->lh=(float)getheight()/p->ppu;
X	a->ld=(float)getdescender()/p->ppu;
X    }
X
X    if (a->addfunc) (*a->addfunc)(a, p);
X
X    if (a->automatic) {
X	Alist *al=(Alist *)alloc(sizeof(Alist));
X	al->a=a;
X	al->next=p->autolist;
X	p->autolist=al;
X    }
X
X    if (a->key!=NULLDEV) {
X      Alist *al=(Alist *)alloc(sizeof(Alist));
X      al->a=a;
X      al->next=pnl_kl;
X      pnl_kl=al;
X
X      qdevice(a->key);
X    }
X
X    a->dirtycnt=2;
X}
X
Xvoid
Xaddtogroup(a, p)
XActuator *a;
XPanel *p;
X{
X    if (!p->lastgroup) p->lastgroup=a;
X    a->group=p->lastgroup->group;
X    p->lastgroup->group=a;
X}
X
Xvoid
Xendgroup(p)
XPanel *p;
X{
X    p->lastgroup=NULL;
X}
X
Xvoid
Xfixpanel(p)
XPanel *p;
X{
X    if (p&&p->fixfunc) {
X	(*p->fixfunc)(p);
X    }
X    p->dirtycnt = 2;
X}
X
Xvoid
Xfixact(a)
XActuator *a;
X{
X    if (a&&a->fixfunc) {
X	(*a->fixfunc)(a);
X    }
X    a->dirtycnt = 2;
X}
X
Xvoid
Xlabeloffsets(a)
XActuator *a;
X{
X    switch (a->labeltype) {
X    case PNL_LABEL_NORMAL:
X	a->lx=0.0;
X	a->ly=0.0;
X	break;
X    case PNL_LABEL_CENTER:
X	a->lx=0.5*(a->w-a->lw);
X	a->ly=0.5*(a->h-a->lh);
X	break;
X    case PNL_LABEL_BOTTOM:
X	a->lx=0.5*(a->w-a->lw);
X	a->ly= -(a->lh+PNL_DIM_2);
X	break;
X    case PNL_LABEL_RIGHT:
X    	a->lx=a->w+PNL_DIM_2;
X	a->ly=0.5*(a->h-a->lh);
X	break;
X    case PNL_LABEL_LEFT:
X	a->lx= -(a->lw+PNL_DIM_2);
X	a->ly=0.5*(a->h-a->lh);
X	break;
X    case PNL_LABEL_TOP:
X	a->lx=0.5*(a->w-a->lw);
X	a->ly=a->h+PNL_DIM_2;
X	break;
X    default:
X    	printf("unknown label type %d\n", a->labeltype);
X	exit(1);
X    }
X}
X
Xvoid
Xpanellimits(p)
XPanel *p;
X{
XActuator *a;
Xfloat bx, by, bw, bh;
X
X    p->minx=100000.0;
X    p->miny=100000.0;
X    p->maxx= -100000.0;
X    p->maxy= -100000.0;
X
X    for (a=p->al;a;a=a->next) {
X
X        if (!a->visible) continue;
X
X	bx=a->x;
X	by=a->y;
X	bw=a->w;
X	bh=a->h;	/* bounding box */
X
X        if (a->label) {
X
X	    labeloffsets(a);
X
X	    bx=MIN(a->x,a->x+a->lx);
X	    by=MIN(a->y,a->y+a->ly);
X	    bw=a->w+MAX(0.0,-a->lx)+MAX(0.0,a->lx+a->lw-a->w);
X	    bh=a->h+MAX(0.0,-a->ly)+MAX(0.0,a->ly+a->lh-a->h);
X	}
X
X	p->minx=MIN(p->minx, bx);
X	p->maxx=MAX(p->maxx, bx+bw);
X	p->miny=MIN(p->miny, by);
X	p->maxy=MAX(p->maxy, by+bh);
X    }
X    p->minx-=PNL_MARGIN;
X    p->maxx+=PNL_MARGIN;
X    p->miny-=PNL_MARGIN;
X    p->maxy+=PNL_MARGIN;
X}
X
Xreshapepanel(p)
XPanel *p;
X{
Xfloat w,h;
X
X    winset(p->gid);
X    getorigin(&p->x,&p->y);
X    getsize(&p->w, &p->h);
X    reshapeviewport();
X    panellimits(p);
X
X    if ((p->maxx-p->minx)/(p->maxy-p->miny)
X	    >(float)p->w/(float)p->h) {
X	w=(p->maxx-p->minx);
X	h=(float)p->h/(float)p->w*w;
X        p->ppu=(float)p->w/w;
X    } else {
X	h=(p->maxy-p->miny);
X	w=(float)p->w/(float)p->h*h;
X        p->ppu=(float)p->h/h;
X    }
X
X    editobj(p->vobj);
X    objreplace(1);
X    ortho2(p->minx,p->minx+w,p->miny,p->miny+h);
X    closeobj();
X    callobj(p->vobj);
X
X    p->dirtycnt=2;
X}
X
Xpnl_initpanel(p)
XPanel *p;
X{
X  static long ux, uy, uh, uw, dx=0;
X  long lx, ly;
X  Scoord tbh;
X  Boolean no_user_port=FALSE;
X
X  panellimits(p);
X  
X  if (!(p->h&&p->w)) {
X    p->h=p->ppu*(p->maxy-p->miny);
X    p->w=p->ppu*(p->maxx-p->minx);
X  }
X  
X  /* panel position defaults */
X  
X  if (p->label) tbh=PNL_TITLE_BAR_HEIGHT;
X  else		tbh=0.0;
X  if (!(p->x&&p->y)) {
X    if (!(pnl_ox&&pnl_oy)) {
X      int tmp=winget();
X      
X      winset(p->usergid);
X      getorigin(&ux,&uy);
X      getsize(&uw,&uh);
X      if (uw&&uh) {
X	p->x=ux+uw+PNL_SCREEN_BORDER;
X	p->y=uy+uh-p->h;
X	winset(tmp);
X      } else
X      /* if no user window, do a */
X      /* prefsize instead of a prefposition */
X	no_user_port=TRUE;
X    } else {
X      p->x=pnl_ox;
X      p->y=pnl_oy-p->h-PNL_SCREEN_BORDER-tbh;
X      if (p->y<0) {		  /* off bottom of screen */
X	p->x+=dx;
X	p->y=uy+uh-p->h;
X	dx=0;
X      }
X      if (p->x+p->w>XMAXSCREEN) { /* off right edge of screen */
X	ux+=PNL_TITLE_BAR_HEIGHT;
X	uy-=PNL_TITLE_BAR_HEIGHT;
X	p->x=ux+uw+PNL_SCREEN_BORDER;
X	p->y=uy+uh-p->h;
X      }
X    }
X  }
X  dx=MAX(dx, p->w+PNL_SCREEN_BORDER);
X  pnl_ox=p->x;
X  pnl_oy=p->y;
X  
X  if (no_user_port) prefsize(p->w, p->h);
X  else		    prefposition(p->x,p->x+p->w,p->y,p->y+p->h);
X#ifdef IRIS_NEWS
X  if (!p->label) noborder();
X#endif IRIS_NEWS
X  
X  if (p->label)
X    p->gid=winopen(p->label);
X  else
X    p->gid=winopen("control panel");
X
X  if (no_user_port) {
X    getorigin(&lx, &ly);
X    p->x=lx;
X    p->y=ly;
X  }
X  
X#ifdef IRIS_NEWS
X  qenter(REDRAW, p->gid);
X  qenter(INPUTCHANGE, p->gid);
X#endif IRIS_NEWS
X  winconstraints();
X  winconstraints();
X  keepaspect(p->w,p->h);
X  winconstraints();
X  
X#ifdef IRIS_4D
X  doublebuffer();
X  gconfig();
X#endif IRIS_4D
X  
X  reshapepanel(p);
X  if (p->label) wintitle(p->label);
X}
X
Xvoid
Xneedredraw()
X{
X    pnl_saveuserredraw=TRUE;
X}
X
Xshort
Xuserredraw()
X{
XPanel *p;
XDevice dev;
Xshort data;
X
X    if (qtest()==REDRAW) {
X	dev=qread(&data);
X	for (p=pnl_pl;p&&!(p->gid==data);p=p->next);
X	if (!p) {
X#ifdef DEBUG
Xprintf("userredraw consuming a REDRAW for mex window %d\n",data);
X#endif DEBUG
X	    return data;
X	} else {
X#ifdef DEBUG
Xprintf("userredraw requeueing a REDRAW for panel %s\n",p->label);
X#endif DEBUG
X	    qenter(dev,data);
X	    return 0;
X	}
X    } else return 0;
X}
X
Xvoid init()
X{
X  Panel *p;
X
X  for (p=pnl_pl;p;p=p->next) pnl_initpanel(p);
X  
X  qdevice(LEFTMOUSE);
X  tie(LEFTMOUSE, MOUSEX, MOUSEY);
X  qdevice(LEFTSHIFTKEY);
X  qdevice(RIGHTSHIFTKEY);
X#ifdef IRIS_4D
X  qdevice(LEFTCTRLKEY);
X  qdevice(RIGHTCTRLKEY);
X#else  IRIS_4D
X  qdevice(CTRLKEY);
X#endif IRIS_4D
X#ifdef IRIS_NEWS
X  qdevice(WINFREEZE);	/* allows app to run when panels are collapsed */
X  qdevice(WINTHAW);
X#endif IRIS_NEWS
X  
X  pnl_virgin=FALSE;
X}
X
Xputactiontoscript() /* format could be compressed */
X{
X  static int lastframe=0;
X  static int msgtype_delay=PNL_MT_DELAY;
X  static int msgtype_mouse=PNL_MT_MOUSE;
X  static int buf[9];
X    
X  if (pnl_frame>1) {
X    if (pnl_delayvirgin) { pnl_delayvirgin--; } /* skip first two delays */
X    else if ((write(pnl_scriptoutfd,
X		      &msgtype_delay,
X		      sizeof(msgtype_delay))!=sizeof(msgtype_delay))
X	       || (write(pnl_scriptoutfd,
X			 &pnl_frame,
X			 sizeof(pnl_frame))!=sizeof(pnl_frame))) {
X      perror(pnl_scriptoutfile);
X      pnl_writescript=FALSE;
X      return FALSE;
X    }
X  }
X  pnl_frame=0;
X
X  buf[0]=(int)pnl_cp->id;
X  buf[1]=(int)pnl_ca->id;
X  buf[2]=(int)pnl_mx-pnl_cp->x; /* the ultimate would be in world space */
X  buf[3]=(int)pnl_my-pnl_cp->y;
X  buf[4]=(int)pnl_justup;
X  buf[5]=(int)pnl_justdown;
X  buf[6]=(int)pnl_mousedown;
X  buf[7]=(int)pnl_shiftkey;
X  buf[8]=(int)pnl_controlkey;
X  
X  if ((write(pnl_scriptoutfd,
X	     &msgtype_mouse,
X	     sizeof(msgtype_mouse))!=sizeof(msgtype_mouse))
X    ||(write(pnl_scriptoutfd,buf,sizeof(buf))!=sizeof(buf))) {
X    perror(pnl_scriptoutfile);
X    pnl_writescript=FALSE;
X    return FALSE;
X  }
X
X#ifdef DEBUG
X  fprintf(stderr,"X");
X#endif DEBUG
X  return TRUE;
X}
X
XBoolean
Xpnl_beginreadscript(name)
Xchar *name;
X{
X  if (pnl_writescript) return FALSE;
X  if (strcmp(name, pnl_scriptinfile)||!pnl_scriptinfd) {
X    if (pnl_scriptinfd) close(pnl_scriptinfd);
X    if (0>(pnl_scriptinfd=open(pnl_scriptinfile,O_RDONLY))) {
X      perror(pnl_scriptinfile);
X      return FALSE;
X    }
X    strcpy(pnl_scriptinfile, name);
X  }
X  lseek(pnl_scriptinfd, 0, 0);
X  pnl_readscript=TRUE;
X}
X
XBoolean
Xpnl_beginwritescript(name)
Xchar *name;
X{
X  if (pnl_readscript) return FALSE;
X  if (strcmp(name, pnl_scriptoutfile)||!pnl_scriptoutfd) {
X    if (pnl_scriptoutfd) close(pnl_scriptoutfd);
X/*    if (0>(pnl_scriptoutfd=open(pnl_scriptoutfile,
X				O_WRONLY||O_APPEND||O_CREAT))) { */
X    if (0>(pnl_scriptoutfd=creat(pnl_scriptoutfile,0777))) {
X      perror(pnl_scriptoutfile);
X      return FALSE;
X    }
X    strcpy(pnl_scriptoutfile, name);
X  }
X  pnl_writescript=TRUE;
X  pnl_delayvirgin=2;
X}
X
XBoolean
Xpnl_beginappendscript(name)
Xchar *name;
X{
X  int c;
X  
X  if (pnl_readscript) return FALSE;
X  if (strcmp(name, pnl_scriptoutfile)||!pnl_scriptoutfd) {
X    if (pnl_scriptoutfd) close(pnl_scriptoutfd);
X    if (0>(pnl_scriptoutfd=open(pnl_scriptoutfile,
X				O_WRONLY||O_APPEND))) {
X      perror(pnl_scriptoutfile);
X      return FALSE;
X    }
X    strcpy(pnl_scriptoutfile, name);
X  }
X  if (!strcmp(pnl_scriptinfile,pnl_scriptoutfile)&&pnl_scriptinfd) {
X    c=lseek(pnl_scriptinfd, 0, 1);
X    lseek(pnl_scriptoutfd,c);
X  } else
X    lseek(pnl_scriptoutfd, 0, 2);
X  pnl_writescript=TRUE;
X}
X
Xvoid
Xpnl_endreadscript()
X{
X/*if (pnl_scriptinfd) close(pnl_scriptinfd); */
X  pnl_readscript=FALSE;
X}
X
Xvoid
Xpnl_endwritescript()
X{
X  if (pnl_scriptoutfd) {
X    close(pnl_scriptoutfd);
X    pnl_scriptoutfd=0;
X  }
X  pnl_writescript=FALSE;
X}
X
XBoolean
Xalt()
X{
X  static Boolean state;
X  
X  return state=!state;
X}
X
Xvoid
Xdumpstate()
X{
XPanel *p;
XActuator *a;
X
X  if (pnl_readscript) return;
X  if (!pnl_scriptoutfd) pnl_beginwritescript("panel.script");
X  if (!pnl_scriptoutfd) {
X    fprintf(stderr, "Can't write script file\n");
X    return;
X  }
X
X  for (p=pnl_pl;p;p=p->next)
X    for (a=p->al;a;a=a->next)
X      (a->dumpfunc)(a, pnl_scriptoutfd);
X
X}
X
Xvoid
Xgetnewactive(ca,cp,mx,my)
X     Actuator **ca;
X     Panel **cp;
X     Screencoord mx, my;
X{
X  Panel *p=NULL;
X  Actuator *a=NULL;
X  
X#ifndef IRIS_NEWS
X#ifdef IRIS_4D
X  pnl_winmouse=gl_winat(mx,my);
X#else  IRIS_4D
X  pnl_winmouse=winat(mx,my);
X#endif IRIS_4D
X#endif IRIS_NEWS
X  for (p=pnl_pl;p;p=p->next) 
X    if (pnl_winmouse==p->gid) break;
X  
X#ifdef DEBUG
X  if (p) printf("a hit on panel %s\n", p->label);
X  else   printf("a mousedown on mex window %d missed all panels\n", pnl_winmouse);
X#endif DEBUG
X  
X  if (p) {
X    p->active=TRUE;
X    if ((a=pickact(p,mx,my))&&a->selectable) {
X      
X#ifdef DEBUG
X      printf("picked %s\n", a->label);
X#endif DEBUG
X      
X      a->active=TRUE;
X      a->dirtycnt=2;
X    } else {	/* hit background */
X      winset(p->gid);
X      winpop();
X    }
X  } else { /* special case, mouse actuator active outside all panels */
X    if (pnl_mouse_act&&pnl_mouse_act->selectable) {
X#ifdef DEBUG
X      printf("picked the mouse actuator\n");
X#endif DEBUG
X      p=pnl_pl;		/* set current panel to be non-null */
X      p->active=TRUE;
X      a=pnl_mouse_act;
X      a->active=TRUE;
X    }
X  }
X  *cp=p;
X  *ca=a;
X}
X
Xvoid
Xdofuncs(a,p)
XActuator *a;
XPanel *p;
X{
X    if (pnl_justdown) {
X	if (p&&a&&a->downfunc) {
X	    winset(p->usergid);
X	    (*a->downfunc)(a);
X	    winset(p->gid);
X	}
X	if (p&&p->downfunc) {
X	    winset(p->usergid);
X	    (*p->downfunc)(p);
X	    winset(p->gid);
X	}
X    }
X    if (p&&a&&a->active&&a->activefunc) {
X	winset(p->usergid);
X	(*a->activefunc)(a);
X	winset(p->gid);
X    }
X    if (p&&p->active&&p->activefunc) {
X	winset(p->usergid);
X	(*p->activefunc)(p);
X	winset(p->gid);
X    }
X    if (pnl_justup) {
X	if (p&&a&&a->upfunc) {
X	    winset(p->usergid);
X	    (*a->upfunc)(a);
X	    winset(p->gid);
X	}
X	if (p&&p->upfunc) {
X	    winset(p->usergid);
X	    (*p->upfunc)(p);
X	    winset(p->gid);
X	}
X    }
X}
X
Xsetinactive(a,p)
XActuator *a;
XPanel *p;
X{
X  if (p) p->active=FALSE;
X  if (a) {
X    
X#ifdef DEBUG
X    printf("unpicked %s\n", a->label);
X#endif DEBUG
X    
X    a->active=FALSE;
X    a->dirtycnt=2;
X  }
X}
X
Xvoid
Xdoautos(p,mx,my)
XPanel *p;
XScreencoord mx,my;
X{
XAlist *e;
XScreencoord sx=mx-p->x, sy=my-p->y;
X
X    for (e=p->autolist;e;e=e->next){
X	if (e->a->automatic) (*e->a->newvalfunc)(e->a,p,sx,sy);
X    }
X}
X
XBoolean
Xgetactionfromqueue()
X{
X  Panel *p=NULL;
X  Device dev;
X  short data;
X  Alist *e;
X
X  pnl_ca=pnl_ca_save;
X  pnl_cp=pnl_cp_save;
X  if (pnl_ca) pnl_ca->active=pnl_ca_active_save;
X  if (pnl_cp) pnl_cp->active=pnl_cp_active_save;
X  pnl_shiftkey=pnl_shiftkey_save;
X  pnl_controlkey=pnl_controlkey_save;
X
X  pnl_justup=pnl_justdown=FALSE;
X redo:
X  if (qtest()) {
X    dev=qread(&data);
X    switch(dev) {
X#ifdef IRIS_NEWS
X    case INPUTCHANGE:
X      pnl_winmouse=data;
X      goto redo;
X#endif IRIS_NEWS
X    case PNL_TOKEN:
X#ifdef DEBUG
X      printf("consumed a PNL_TOKEN, dopanel returning\n");
X#endif DEBUG
X#ifdef IRIS_4D
X      longjmp(dopanel_return,TRUE);
X#else  IRIS_4D
X       break;			/* mustn't get out of sync on 3030's */
X#endif IRIS_4D
X     case REDRAW:
X       for (p=pnl_pl;p;p=p->next) {
X 	if (p->gid==data) {
X 	  reshapepanel(p);
X 	  break;
X 	}
X       }
X       /* this redraw must not be for a panel, requeue it here */
X       if (!p&&pnl_saveuserredraw) { 
X#ifdef DEBUG
X 	printf("enqueing a PNL_TOKEN\n");
X#endif DEBUG
X 	qenter(PNL_TOKEN);
X 	qenter(dev,data);
X      }
X      break;
X    case LEFTMOUSE:
X      pnl_mousedown=data;
X      pnl_justdown=pnl_mousedown;
X      pnl_justup=!pnl_mousedown;
X      dev=qread(&data); pnl_mx=data;
X      dev=qread(&data); pnl_my=data;
X      break;
X    case LEFTSHIFTKEY:
X    case RIGHTSHIFTKEY:
X      pnl_shiftkey=data;
X      break;
X#ifdef IRIS_4D
X    case LEFTCTRLKEY:
X    case RIGHTCTRLKEY:
X#else  IRIS_4D
X    case CTRLKEY:
X#endif IRIS_4D
X      pnl_controlkey=data;
X      break;
X    default:
X      /* check for key equivalents */
X      for (e=pnl_kl;e;e=e->next)
X	if (e->a->key==dev) break;
X      if (e) {
X	pnl_mousedown=data;
X	pnl_justdown=pnl_mousedown;
X	pnl_justup=!pnl_mousedown;
X	
X	if (!pnl_justdown&&!pnl_justup&&pnl_cp) {
X	  pnl_mx=getvaluator(MOUSEX);
X	  pnl_my=getvaluator(MOUSEY);
X	}
X	
X	pnl_ca=e->a;
X	pnl_cp=e->a->p;
X	goto end;
X      }
X      break;
X    }
X  }
X 
X  if (!pnl_justdown&&!pnl_justup&&pnl_cp) {
X    pnl_mx=getvaluator(MOUSEX);
X    pnl_my=getvaluator(MOUSEY);
X  }
X
X  if (pnl_justdown) getnewactive(&pnl_ca,&pnl_cp,pnl_mx,pnl_my);
X  if (pnl_justup) setinactive(pnl_ca,pnl_cp);
X 
X end:
X  pnl_ca_save=pnl_ca;
X  pnl_cp_save=pnl_cp;
X  if (pnl_ca) pnl_ca_active_save=pnl_ca->active;
X  if (pnl_cp) pnl_cp_active_save=pnl_cp->active;
X  pnl_shiftkey_save=pnl_shiftkey;
X  pnl_controlkey_save=pnl_controlkey;
X
X  pnl_action_source=PNL_SRC_QUEUE;
X}
X
Xgetactionfromscript() 
X {
X  int c, msgtype;
X  short actid;
X  static int buf[9];
X    
X  pnl_justup=pnl_justdown=FALSE;
X
X  if (pnl_delay>pnl_frame) return FALSE;
X
X more:
X  pnl_cp=NULL;
X  pnl_ca=NULL;
X
X  if ((c=read(pnl_scriptinfd,&msgtype,sizeof(msgtype)))!=sizeof(msgtype)) {
X#ifdef DEBUG
X    fprintf(stderr, "end of script on read\n");
X#endif DEBUG
X     pnl_readscript=FALSE;
X    return FALSE;
X  }
X
X  switch (msgtype) {
X  case PNL_MT_MOUSE:
X    if ((c=read(pnl_scriptinfd,buf,sizeof(buf)))!=sizeof(buf)) {
X#ifdef DEBUG
X      fprintf(stderr, "end of script on read\n");
X#endif DEBUG
X      pnl_readscript=FALSE;
X      return FALSE;
X    }
X    
X    if (  buf[0]<0
X	||buf[0]>=pnl_id
X	||buf[1]<0
X	||buf[1]>=pnl_id) {
X      fprintf(stderr,"libpanel: bad actuator index in script file.\n");
X      pnl_readscript=FALSE;
X      return FALSE;
X    }
X    
X    /* throw away script events for actuator the user is mousing */
X    if ((Actuator *)pnl_table[buf[1]]==pnl_ca_save) return FALSE;
X
X    pnl_cp=(Panel *)pnl_table[buf[0]];
X    pnl_ca=(Actuator *)pnl_table[buf[1]];
X    pnl_mx=(Screencoord)buf[2]+pnl_cp->x;
X    pnl_my=(Screencoord)buf[3]+pnl_cp->y;
X    pnl_justup=(Boolean)buf[4];
X    pnl_justdown=(Boolean)buf[5];
X    pnl_mousedown=(Boolean)buf[6];
X    pnl_shiftkey=(Boolean)buf[7];
X    pnl_controlkey=(Boolean)buf[8];
X    
X    pnl_cp->active=pnl_ca->active=pnl_mousedown;
X     if (!pnl_mousedown) fixact(pnl_ca);
X    
X    pnl_action_source=PNL_SRC_SCRIPT;
X    return TRUE;
X  case PNL_MT_STATE:
X    if ((c=read(pnl_scriptinfd,&actid,sizeof(actid)))!=sizeof(actid)) {
X#ifdef DEBUG
X      fprintf(stderr, "end of script on read\n");
X#endif DEBUG
X      pnl_readscript=FALSE;
X      return FALSE;
X    }
X    if (  actid<0
X	||actid>=pnl_id) {
X      fprintf(stderr, "libpanel: bad actuator identifier in script file.\n");
X      pnl_readscript=FALSE;
X      return FALSE;
X    }
X    (*(((Actuator *)pnl_table[actid])->loadfunc))
X      (pnl_table[actid], pnl_scriptinfd);
X    fixact((Actuator *)pnl_table[actid]);
X    goto more;
X    break;
X   case PNL_MT_DELAY:
X    if ((c=read(pnl_scriptinfd,
X		&pnl_delay,
X		sizeof(pnl_delay)))!=sizeof(pnl_delay)) {
X#ifdef DEBUG
X      fprintf(stderr, "end of script on read\n");
X#endif DEBUG
X      pnl_readscript=FALSE;
X      return FALSE;
X    }
X    pnl_frame=0;
X    break;
X  default:
X    fprintf(stderr, "libpanel: unrecognized message type in script file\n");
X    return FALSE;
X  }
X}
X
Xgetaction()
X{
X  if (pnl_readscript) {
X    if (qtest())
X      getactionfromqueue();
X    else if (pnl_ca_save&&pnl_ca_save->active) {
X      if (alt())
X	getactionfromqueue();
X      else
X	if (!getactionfromscript()) getactionfromqueue();
X    } else
X      getactionfromscript();
X  } else getactionfromqueue();
X}
X
XActuator
X*dopanel()
X{
X  Actuator *a=NULL;
X  Panel *p=NULL;
X  int winsave=winget();
X
X  if (setjmp(dopanel_return)) goto return_from_dopanel;
X  if (pnl_virgin) init();
X
X redo:
X
X  pnl_frame++;
X  getaction();
X
X  if (pnl_cp) pnl_cp->a=pnl_ca;
X
X  if (pnl_cp&&pnl_ca&&pnl_ca->newvalfunc) {
X    winset(pnl_cp->gid);
X    (*pnl_ca->newvalfunc)(pnl_ca,pnl_cp,pnl_mx-pnl_cp->x,pnl_my-pnl_cp->y);
X    pnl_ca->dirtycnt=2;
X  }
X
X  for (p=pnl_pl;p;p=p->next) doautos(p,pnl_mx,pnl_my);
X  for (p=pnl_pl;p;p=p->next) (*p->drawfunc)(p);
X  dofuncs(pnl_ca,pnl_cp);
X
X  if (pnl_cp&&pnl_ca&&pnl_writescript) putactiontoscript();
X
X  if (pnl_cp&&!pnl_cp->active) {
X    pnl_cp=NULL;
X    if (pnl_action_source==PNL_SRC_QUEUE) {
X      pnl_cp_save=NULL;
X    }
X  }
X  if (pnl_ca&&!pnl_ca->active) {
X    pnl_ca=NULL;
X    if (pnl_action_source==PNL_SRC_QUEUE) pnl_ca_save=NULL;
X  }
X
X#ifdef IRIS_4D
X  /* no retries on 3030's so the user can swapbuffers */
X
X  if (qtest()==REDRAW) {	/* someone left to redraw? */
X    goto redo;
X  }
X  
X  if (pnl_justup) goto redo;	/* any mousedowns left in that queue? */
X  
X#endif IRIS_4D
X  
Xreturn_from_dopanel:
X  if (winsave!=winget()) winset(winsave);
X  return pnl_ca;
X}
X
X/*
X *	drawpanel-
X *
X *	this routine draws all actuators on every panel, which may be 
X *	a bit of overkill.  It also does not decrement the panel's
X *	dirtycnt so a later dopanel may draw them again.
X *
X */ 
X
Xvoid
Xdrawpanel()	/* user routine to update all panels */
X{
XPanel *p;
X
X    int winsave=winget();
X
X    if (pnl_virgin) {
X      dopanel();
X      return;
X    }
X    
X    for (p=pnl_pl;p;p=p->next) {
X      p->dirtycnt++;
X      (*p->drawfunc)(p);
X    }
X
X    winset(winsave);
X    return;
X}
X
X#ifdef 0
XActuator
X*pickact(p,mx,my)
XPanel *p;
XScreencoord mx, my;
X{
Xshort buf[10];
Xint i, n;
XActuator *a;
XScreencoord savex, savey;
X
X    picking=TRUE;
X    winset(p->gid);
X
X    savex=getvaluator(MOUSEX);
X    savey=getvaluator(MOUSEY);
X    setvaluator(MOUSEX,mx,0,XMAXSCREEN);
X    setvaluator(MOUSEY,my,0,YMAXSCREEN);
X
X    buf[1]=0;
X    picksize(1,1);
X
X    pushmatrix();
X    pick(buf, 9);
X    callobj(p->vobj);
X
X    initnames();
X    for (i=1,a=p->al;a;i++,a=a->next) {
X	loadname((short)i);
X	(*a->drawfunc)(a, p);
X    }
X    n=endpick(buf);
X    popmatrix();
X    
X    setvaluator(MOUSEX,savex,0,XMAXSCREEN);
X    setvaluator(MOUSEY,savey,0,YMAXSCREEN);
X
X    if (n<1) return NULL;
X    for (i=1,a=p->al;i<buf[1];i++,a=a->next);
X
X    picking=FALSE;
X    return a; 
X}
X#endif
X
XActuator
X*pickact(p,mx,my)
XPanel *p;
XScreencoord mx, my;
X{
Xint i, n;
XActuator *a;
XScreencoord sx,sy;
XCoord wx, wy;
X
X    winset(p->gid);
X    sx=mx-p->x, sy=my-p->y;
X    mapw2(p->vobj,sx,sy,&wx,&wy);
X
X    for (i=1,a=p->al;a;i++,a=a->next) {
X	if ((*a->pickfunc)(a,p,wx,wy)) break;
X    }
X
X    return a; 
X}
X
XBoolean 
X_hitact(a,p,x,y)
XActuator *a;
XPanel *p;
XCoord x,y;
X{
X    return PNL_HITACT(a,x,y);
X}
X
Xvoid
X_dumpact(a, fd)
XActuator *a;
Xint fd;
X{
Xstatic int msgtype=PNL_MT_STATE;
X
X  write(fd, &msgtype, sizeof(msgtype));
X  write(fd, &a->id, sizeof(a->id));
X  write(fd, a, sizeof(Actuator));
X  write(fd, &a->datasize, sizeof(int));
X  write(fd, a->data, a->datasize);
X}
X
Xvoid
X_loadact(a, fd)
XActuator *a;
Xint fd;
X{
Xint c;
X  if (a->label) fprintf(stderr, "loading actuator %s, ", a->label);
X  c=read(fd, a, sizeof(Actuator));
X#ifdef DEBUG
X  fprintf(stderr, "read %d bytes, ", c);
X#endif DEBUG
X  c=read(fd, &a->datasize, sizeof(int));
X#ifdef DEBUG  fprintf(stderr, "read %d bytes, ", c);
X  if (a->datasize) {
X#endif DEBUG
X      c=read(fd, a->data, a->datasize);
X#ifdef DEBUG
X      fprintf(stderr, "read %d bytes\n", c);
X#endif DEBUG
X  } 
X#ifdef DEBUG
X  else fprintf(stderr,"\n");
X}
X#endif DEBUG
X
Xvoid
X_fixpnl(p)
XPanel *p;
X{
X  long x, y, w, h;
X  int winsave=winget();
X
X  winset(p->gid);
X
X  getorigin(&x, &y);
X  getsize(&w, &h);
X  if (  p->x!=x
X      ||p->y!=y
X      ||p->w!=w
X      ||p->h!=h) {  /* user reset size or location */
X    winconstraints();
X    winposition(p->x, p->x+p->w, p->y, p->y+p->h);
X  } else {	    /* maybe just made a new actuator */
X    panellimits(p);
X    w=p->ppu*(p->maxx-p->minx);
X    h=p->ppu*(p->maxy-p->miny);
X    if (  ABS(p->w-w)>1
X	||ABS(p->h-h)>1) {
X      winconstraints();
X      winposition(x, x+w, y, y+h);
X      p->x=x; p->y=y; p->w=w; p->h=h;
X    }
X  }
X
X  keepaspect(p->w,p->h);
X  winconstraints();
X  reshapepanel(p);
X  
X  winset(winsave);
X}
X  
X
Xvoid
X_drawpnl(p)
XPanel *p;
X{
Xint i;
XActuator *a;
XBoolean drewsomething=FALSE;
X
X    if (p->dirtycnt) {
X      drewsomething=TRUE;
X      winset(p->gid);
X#ifdef DEBUG
Xprintf("drawing panel %s\n",  p->label);
X#endif DEBUG
X	p->dirtycnt--;
X        color(pnl_background_color);
X	clear();
X	for (i=0,a=p->al;a;i++,a=a->next) {
X	    if (a->visible&&a->drawfunc) (*a->drawfunc)(a, p);
X	}
X    }
X
X    for (i=0,a=p->al;a;i++,a=a->next) {
X	if (a->dirtycnt) {
X	  drewsomething=TRUE;
X	  winset(p->gid);
X#ifdef DEBUG
Xprintf("drawing actuator %s with value of %g\n", a->label,  a->val);
X#endif DEBUG
X	    if (a->visible&&a->drawfunc) (*a->drawfunc)(a, p);
X	    a->dirtycnt--;
X	}
X    }
X
X#ifdef IRIS_4D
X    if (drewsomething) swapbuffers();
X#endif IRIS_4D
X
X}
X
Xdrawlabel(a, p)
XActuator *a;
XPanel *p;
X{
X    color(pnl_background_color);
X    rectf(a->x+a->lx,a->y+a->ly,
X    a->x+a->lx+a->lw,a->y+a->ly+a->lh);
X    if (p->ppu>pnl_char_threshold) {
X	color(pnl_outline_color);
X	cmov2(a->x+a->lx,a->y+a->ly+a->ld);
X	charstr(a->label);
X    } else {
X	color(pnl_normal_color);
X	rectf(a->x+a->lx,a->y+a->ly,
X	      a->x+a->lx+a->lw,
X	      a->y+a->ly+a->lh);
X    }
X#ifdef 0
X	color(pnl_highlight_color);
X	cmov2(a->x+a->lx,a->y+a->ly+a->ld);
X	charstr(a->label);
X	rect(a->x+a->lx,a->y+a->ly,
X	      a->x+a->lx+a->lw,
X	      a->y+a->ly+a->lh);
X#endif
X}
X
X#ifdef 0
XBoolean
Xdumppanel()
X{
XPanel *p;
XActuator *a;
XFILE *dumpfile;
X    
X    if (!(dumpfile=fopen("panel.txt","w"))) {
X	perror("panel.txt");
X	return FALSE;
X    }
X    for (p=pnl_pl;p;p=p->next) {
X	if (p->label) fprintf(dumpfile, "panel: %-24s",p->label);
X	else	      fprintf(dumpfile, "panel: (NULL)                  ");
X	fprintf(dumpfile, "x: %-4d  ", p->x);
X	fprintf(dumpfile, "y: %-4d  ", p->y);
X	fprintf(dumpfile, "w: %-4d  ", p->w);
X	fprintf(dumpfile, "h: %-4d\n", p->h);
X	for (a=p->al;a;a=a->next) {
X	    if (a->label) fprintf(dumpfile, "  actuator: %-19s", a->label);
X	    else	  fprintf(dumpfile, "  actuator: (NULL)             ");
X	    fprintf(dumpfile, "x: %-5g ", a->x);
X	    fprintf(dumpfile, "y: %-5g ", a->y);
X	    fprintf(dumpfile, "w: %-5g ", a->w);
X	    fprintf(dumpfile, "h: %-5g\n", a->h);
X	}
X    }
X    fclose(dumpfile);
X    return TRUE;
X}
X#endif 0
X
X#define FP fprintf
X#define DF dumpfile
X
XBoolean
Xdumppanel()
X{
X  Panel *p;
X  Actuator *a;
X  FILE *dumpfile;
X  Boolean ingroup;
X
X  if (!(dumpfile=fopen("panel.txt","w"))) {
X    perror("panel.txt");
X    return FALSE;
X  }
X
X  for (p=pnl_pl;p;p=p->next) {
X    FP(DF, " p=mkpanel();\n");
X    FP(DF, " /* p->id=%d; */\n", p->id);
X    FP(DF, " /* p->a=0x%x; */\n", p->a);
X    FP(DF, " /* p->al=0x%x; */\n", p->al);
X    FP(DF, " /* p->autolist=0x%x; */\n", p->autolist);
X    FP(DF, " /* p->lastgroup=0x%x; */\n", p->lastgroup);
X    FP(DF, " /* p->active=%s; */\n", (p->active?"TRUE":"FALSE"));
X    FP(DF, "    p->enabled=%s;\n",(p->enabled?"TRUE":"FALSE"));
X    FP(DF, "    p->x=%d;\n", p->x);
X    FP(DF, "    p->y=%d;\n", p->y);
X    FP(DF, "    p->w=%d;\n", p->w);
X    FP(DF, "    p->h=%d;\n", p->h);
X    FP(DF, " /* p->minx=%f; */\n", p->minx);
X    FP(DF, " /* p->maxx=%f; */\n", p->maxx);
X    FP(DF, " /* p->miny=%f; */\n", p->miny);
X    FP(DF, " /* p->maxy=%f; */\n", p->maxy);
X    FP(DF, " /* p->cw=%f; */\n", p->cw);
X    FP(DF, " /* p->ch=%f; */\n", p->ch);
X    FP(DF, " /* p->gid=%d; */\n", p->gid);
X    FP(DF, " /* p->usergid=%d; */\n", p->usergid);
X    FP(DF, " /* p->vobj=%d; */\n", p->vobj);
X    FP(DF, "    p->ppu=%f;\n", p->ppu);
X    FP(DF, "    p->label=\"%s\";\n", (p->label?p->label:"NULL"));
X    FP(DF, " /* p->fixfunc=0x%x; */\n", p->fixfunc);
X    FP(DF, " /* p->drawfunc=0x%x; */\n", p->drawfunc);
X    FP(DF, " /* p->downfunc=0x%x; */\n", p->downfunc);
X    FP(DF, " /* p->activefunc=0x%x; */\n", p->activefunc);
X    FP(DF, " /* p->upfunc=0x%x; */\n", p->upfunc);
X    FP(DF, " /* p->dirtycnt=%d; */\n", p->dirtycnt);
X    FP(DF, " /* p->next=0x%x; */\n", p->next);
X    FP(DF, "\n");
X    
X    for (a=p->al;a;a=a->next) {
X      FP(DF, " /* a->id=%d; */\n", a->id);
X      FP(DF, " /* a->type=%d; */\n", a->type);
X      FP(DF, " /* a->active=%s; */\n", (a->active?"TRUE":"FALSE"));
X      FP(DF, "    a->x=%f;\n", a->x);
X      FP(DF, "    a->y=%f;\n", a->y);
X      FP(DF, "    a->w=%f;\n", a->w);
X      FP(DF, "    a->h=%f;\n", a->h);
X      FP(DF, "    a->lx=%f;\n", a->lx);
X      FP(DF, "    a->ly=%f;\n", a->ly);
X      FP(DF, "    a->lw=%f;\n", a->lw);
X      FP(DF, "    a->lh=%f;\n", a->lh);
X      FP(DF, "    a->ld=%f;\n", a->ld);
X      FP(DF, "    a->val=%f;\n", a->val);
X      FP(DF, "    a->initval=%f;\n", a->initval);
X      FP(DF, "    a->maxval=%f;\n", a->maxval);
X      FP(DF, "    a->minval=%f;\n", a->minval);
X      FP(DF, "    a->label=\"%s\";\n", (a->label?a->label:"NULL"));
X      FP(DF, "    a->key=%d;\n", a->key);
X      FP(DF, "    a->labeltype=%d;\n", a->labeltype);
X      FP(DF, " /* a->addfunc=0x%x; */\n", a->addfunc);
X      FP(DF, " /* a->fixfunc=0x%x; */\n", a->fixfunc);
X      FP(DF, " /* a->pickfunc=0x%x; */\n", a->pickfunc);
X      FP(DF, " /* a->newvalfunc=0x%x; */\n", a->newvalfunc);
X      FP(DF, " /* a->dumpfunc=0x%x; */\n", a->dumpfunc);
X      FP(DF, " /* a->loadfunc=0x%x; */\n", a->loadfunc);
X      FP(DF, " /* a->drawfunc=0x%x; */\n", a->drawfunc);
X      FP(DF, " /* a->downfunc=0x%x; */\n", a->downfunc);
X      FP(DF, " /* a->activefunc=0x%x; */\n", a->activefunc);
X      FP(DF, " /* a->upfunc=0x%x; */\n", a->upfunc);
X      FP(DF, " /* a->dirtycnt=%d; */\n", a->dirtycnt);
X      FP(DF, " /* a->u=0x%x; */\n", a->u);
X      FP(DF, " /* a->data=0x%x; */\n", a->data);
X      FP(DF, " /* a->datasize=%d; */\n", a->datasize);
X      FP(DF, "    a->automatic=%s;\n", (a->automatic?"TRUE":"FALSE"));
X      FP(DF, "    a->selectable=%s;\n", (a->selectable?"TRUE":"FALSE"));
X      FP(DF, "    a->visible=%s;\n", (a->visible?"TRUE":"FALSE"));
X      FP(DF, " /* a->group=0x%x; */\n", a->group);
X      FP(DF, " /* a->next=0x%x; */\n", a->next);
SHAR_EOF
echo "End of part 4, continue with part 5"
echo "5" > s2_seq_.tmp
exit 0