File:  [Research Unix] / researchv9 / X11 / src / X.V11R1 / clients / xcalc / xcalc.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:39:18 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3, HEAD
researchv9-SUN3

/*
 *	$Source: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/clients/xcalc/xcalc.c,v $
 *	$Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/clients/xcalc/xcalc.c,v 1.1.1.2 2018/04/24 17:39:18 root Exp $
 */

#ifndef lint
static char *rcsid_xcalc_c = "$Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/clients/xcalc/xcalc.c,v 1.1.1.2 2018/04/24 17:39:18 root Exp $";
#endif	lint

/*
 * xcalc.c  -  a hand calculator for the X Window system
 *
 *  Author:    John H. Bradley, University of Pennsylvania
 *                ([email protected])
 *                     March, 1987
 *
 *  RPN mode added and port to X11 by Mark Rosenstein, MIT Project Athena
 */

/*
 * color usage:  ForeColor is used for all frames, BackColor is the color of 
 *                  the calculator body.
 *               NKeyFore, NKeyBack are the colors used for the number keys.
 *               OKeyFore, OKeyBack are used for the operator keys (+-*=/).
 *               FKeyFore, FKeyBack are used for all the other keys.
 *               DispFore, DispBack are used for the display.
 *               IconFore, IconBack are used for the display.
 *
 *               if running on monochrome monitor, or if 'stipple' option
 *                  set, the calculator body is a 50% stipple of ForeColor
 *                  and BackColor.  This looks nice in mono, but can prevent
 *                  you from getting the 'right' colors in color mode, so
 *                  it's an option.
 */

#include <stdio.h>
#include <math.h>
#include <strings.h>
#include <signal.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <setjmp.h>

/* program icon */
#include "icon"

extern int errno;


/* constants used for setting up the calculator.  changing them would 
   probably be bad.  If you do, don't forget to change the values in the
   syntax routine */

#define KFONT "helvetica-medium9"
#define DFONT "helvetica-bold12"
#define FFONT "helvetica-medium8"
#define PADDINGW    4
#define PADDINGH    8
#define DEF_BDRWIDE 2
#define MAXDISP     11
#define KEYPADH     3
#define KEYPADW     2
#define EXTRAH      2
#define DISPPADH    4
#define DISPPADW    8
#define FLAGH       10
#define PI          3.14159265358979
#define E           2.71828182845904

/* DRG mode.  used for trig calculations */
#define DEG 0
#define RAD 1
#define GRAD 2


/* fonts */
char *kfont, *dfont, *ffont;

/* colors */
int ForeColor, BackColor, NKeyFore, NKeyBack, OKeyFore, OKeyBack;
int FKeyFore, FKeyBack, DispFore, DispBack, IconFore, IconBack;

int border = DEF_BDRWIDE;


/* objects */
Display	 *dpy;
Window   theWindow, iconWindow, dispwid;
Cursor   arrow;
Font     keyfont, dispfont, flagfont;
XFontStruct *kfontinfo, *dfontinfo, *ffontinfo; 
Pixmap   stipplePix, dimBorder, IconPix;
GC	 dispbgc,dispfgc,keygc,keyigc,flaggc;

/* variables used in setup */
int numkeys, dispwide, disphigh, keywide, keyhigh;


/* RPN or Infix mode */
int rpn	  = 0;	    /* infix syntax as default */

/* display flags */
int flagK, flagINV, flagPAREN, flagM, flagE, drgmode;
char dispstr[32];


/* stuff defining the keyboard layout.  The keypad is a 5x8 matrix of keys */
#define TINUMKEYS 40
#define HPNUMKEYS 39

struct _key {
           char   *st;
	   int	  code;
	   int    (*fun)();
           Window wid;
           short  x,y,width,height;
           int    fore,back;
	   void	  (*func)();
            };

struct _key *key;
	      
#define kRECIP 0
#define kSQR   1
#define kSQRT  2
#define kCLR   3
#define kOFF   4
#define kINV   5
#define kSIN   6
#define kCOS   7
#define kTAN   8
#define kDRG   9
#define kE     10
#define kEE    11
#define kLOG   12
#define kLN    13
#define kPOW   14
#define kPI    15
#define kFACT  16
#define kLPAR  17
#define kRPAR  18
#define kDIV   19
#define kSTO   20
#define kSEVEN 21
#define kEIGHT 22
#define kNINE  23
#define kMUL   24
#define kRCL   25
#define kFOUR  26
#define kFIVE  27
#define kSIX   28
#define kSUB   29
#define kSUM   30
#define kONE   31
#define kTWO   32
#define kTHREE 33
#define kADD   34
#define kEXC   35
#define kZERO  36
#define kDEC   37
#define kNEG   38
#define kEQU   39
#define kENTR  40
#define kXXY   41
#define kEXP   42
#define k10X   43
#define kROLL  44
#define kNOP   45
#define kBKSP  46


int  oneop(),twoop(),clearf(),offf(),invf(),drgf(),eef();
int  lparf(),rparf(),digit(),decf(),negf(),equf();

/* "1/x", "x^2", "SQRT","CE/C", "AC",
   "INV", "sin", "cos", "tan",  "DRG",
   "e",   "EE",  "log", "ln",   "y^x",
   "PI",  "x!",  "(",   ")",    "/",
   "STO", "7",   "8",   "9",    "*",
   "RCL", "4",   "5",   "6",    "-",
   "SUM", "1",   "2",   "3",    "+",
   "EXC", "0",   ".",   "+/-",  "="  */

struct _key tikeys[TINUMKEYS] = {
  {"1/x",kRECIP,oneop}, {"x^2",kSQR,oneop}, {"SQRT",kSQRT,oneop},
  {"CE/C",kCLR,clearf}, {"AC",kOFF,offf},
  {"INV",kINV,invf}, {"sin",kSIN,oneop}, {"cos",kCOS,oneop},
  {"tan",kTAN,oneop}, {"DRG",kDRG,drgf},
  {"e",kE,oneop}, {"EE",kEE,eef}, {"log",kLOG,oneop},
  {"ln",kLN,oneop},{"y^x",kPOW,twoop},
  {"PI",kPI,oneop},{"x!",kFACT,oneop},{"(",kLPAR,lparf},
  {")",kRPAR,rparf},{"/",kDIV,twoop},
  {"STO",kSTO,oneop},{"7",kSEVEN,digit},{"8",kEIGHT,digit},
  {"9",kNINE,digit},{"*",kMUL,twoop},
  {"RCL",kRCL,oneop},{"4",kFOUR,digit},{"5",kFIVE,digit},
  {"6",kSIX,digit},{"-",kSUB,twoop},
  {"SUM",kSUM,oneop},{"1",kONE,digit},{"2",kTWO,digit},
  {"3",kTHREE,digit},{"+",kADD,twoop},
  {"EXC",kEXC,oneop},{"0",kZERO,digit},{".",kDEC,decf},
  {"+/-",kNEG,negf},{"=",kEQU,equf}};

int  twof(),nop(),rollf(),bkspf(),entrf(),memf();

/*  { "SQRT","e^x", "10^x", "y^x", "1/x", "CHS", "7", "8", "9",  "/",
      "x!",  "PI",  "sin",  "cos", "tan", "EEX", "4", "5", "6",  "x",
      "",    "",    "R v",  "x:y", "<-",  "ENTR","1", "2", "3",  "-",
      "ON",  "DRG", "INV",  "STO", "RCL",        "0", ".", "SUM","+"  */

struct _key hpkeys[HPNUMKEYS] = {
  {"SQRT",kSQRT,oneop},{"e^x",kEXP,oneop},{"10^x",k10X,oneop},
  {"y^x",kPOW,twof},{"1/x",kRECIP,oneop},{"CHS",kNEG,negf},
  {"7",kSEVEN,digit},{"8",kEIGHT,digit},{"9",kNINE,digit},{"/",kDIV,twof},

  {"x!",kFACT,oneop},{"PI",kPI,oneop},{"sin",kSIN,oneop},{"cos",kCOS,oneop},
  {"tan",kTAN,oneop},{"EEX",kEE,eef},{"4",kFOUR,digit},{"5",kFIVE,digit},
  {"6",kSIX,digit},{"x",kMUL,twof},

  {"",kNOP,nop},{"",kNOP,nop},{"R v",kROLL,rollf},{"x:y",kXXY,twof},
  {"<-",kBKSP,bkspf},{"ENTR",kENTR,entrf},{"1",kONE,digit},{"2",kTWO,digit},
  {"3",kTHREE,digit},{"-",kSUB,twof},

  {"ON",kOFF,offf},{"DRG",kDRG,drgf},{"INV",kINV,invf},{"STO",kSTO,memf},
  {"RCL",kRCL,memf},{"0",kZERO,digit},{".",kDEC,decf},
  {"SUM",kSUM,memf},{"+",kADD,twof} };


/* checkerboard used in mono mode */
#define check_width 16
#define check_height 16
static char check_bits[] = {
   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};


#ifndef IEEE
    jmp_buf env;
#endif


/**************/
main(argc, argv)
    int   argc;
    char *argv[];
/**************/
{
    int i, status,dpcs;
    char *strind;
#ifndef IEEE
    extern fperr();
#endif

    char *fc, *bc, *nfc, *nbc, *ofc, *obc, *ffc, *fbc, *dfc, *dbc, *ifc, *ibc;
    char *geom    = NULL;
    char *display = NULL;
    int rvflag    = 0;      /* don't use reverse video as a default */
    int stip      = 0;      /* don't stipple background by default */
    int analog	  = 0;
    int invkey    = -1;

    XEvent 	event;
    XGCValues 	gcv;
    XWMHints 	wmhints;
    Colormap 	colors;
    XColor	xcsd, xced;
    int min_width, min_height;
    XSizeHints	szhint;

    char *def;



    /*********************Defaults*********************/
    kfont=XGetDefault(dpy,argv[0],"KeyFont");
    if (!kfont) kfont = KFONT;    

    dfont=XGetDefault(dpy,argv[0],"DisplayFont");
    if (!dfont) dfont = DFONT;    

    ffont=XGetDefault(dpy,argv[0],"FlagFont");
    if (!ffont) ffont = FFONT;    

    if ((def=XGetDefault(dpy,argv[0],"BorderWidth"))!=NULL)
         border=atoi(def);

    if ((def=XGetDefault(dpy,argv[0],"ReverseVideo"))!=NULL)
         if (strcmp(def,"on")==0) rvflag=1;

    if ((def=XGetDefault(dpy,argv[0],"Stipple"))!=NULL)
         if (strcmp(def,"on")==0) stip=1;

    if ((def=XGetDefault(dpy,argv[0],"Mode"))!=NULL) {
         if (strcmp(def,"rpn")==0) rpn=1;
         else if (strcmp(def,"analog")==0) analog=1;
         }

    fc  = XGetDefault(dpy, argv[0], "Foreground");
    bc  = XGetDefault(dpy, argv[0], "Background");
    nfc = XGetDefault(dpy, argv[0], "NKeyFore");
    nbc = XGetDefault(dpy, argv[0], "NKeyBack");
    ofc = XGetDefault(dpy, argv[0], "OKeyFore");
    obc = XGetDefault(dpy, argv[0], "OKeyBack");
    ffc = XGetDefault(dpy, argv[0], "FKeyFore");
    fbc = XGetDefault(dpy, argv[0], "FKeyBack");
    dfc = XGetDefault(dpy, argv[0], "DispFore");
    dbc = XGetDefault(dpy, argv[0], "DispBack");
    ifc = XGetDefault(dpy, argv[0], "IconFore");
    ibc = XGetDefault(dpy, argv[0], "IconBack");

    /*********************Options*********************/

    for (i = 1; i < argc; i++) {

        if (argv[i][0] == '=') {
            geom = argv[i];
            continue;
            }

        strind = index(argv[i], ':');

        if(strind != NULL) {
            display = argv[i];
            continue;
            }

        if (strcmp(argv [i], "-bw") == 0) {
            if (++i >= argc) Syntax(argv[0]);
            border = atoi(argv [i]);
            continue;
            }

        if (strcmp(argv [i], "-stip") == 0) {
            stip=1;
            continue;
            }

        if (strcmp(argv [i], "-help") == 0) {
            Syntax(argv[0]);
            }

        if (strcmp(argv [i], "-rv") == 0) {
            rvflag++;
            continue;
            }

        if (strcmp(argv [i], "-rpn") == 0) {
            rpn++;
            continue;
            }

        if (strcmp(argv [i], "-analog") == 0) {
            analog++;
            continue;
            }

        Syntax(argv[0]);
    }


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

    /* Open up the display. */

    if ((dpy = XOpenDisplay(display)) == NULL) {
        fprintf(stderr, "%s: Can't open display '%s'\n",argv[0], display);
        exit(1);
        }

    /* Set up colors and pixmaps. */

    /* Set normal default colors */
    if (!rvflag) {
      ForeColor=BlackPixel(dpy, DefaultScreen(dpy));
      BackColor=WhitePixel(dpy, DefaultScreen(dpy));
    } else {
      BackColor=BlackPixel(dpy, DefaultScreen(dpy));
      ForeColor=WhitePixel(dpy, DefaultScreen(dpy));
    }

    dpcs=DisplayCells(dpy, DefaultScreen(dpy));
    if (dpcs<=2) stip=1;  /* monochrome display */

    colors = DefaultColormap(dpy, DefaultScreen(dpy));

    if (dpcs>2&&(fc !=NULL)&&XAllocNamedColor(dpy, colors, fc, &xcsd, &xced))
      ForeColor=xcsd.pixel;

    if (dpcs>2&&(bc !=NULL)&&XAllocNamedColor(dpy, colors, bc, &xcsd, &xced))
      BackColor=xcsd.pixel;

    NKeyFore = OKeyFore = FKeyFore = DispFore = IconFore = ForeColor;
    NKeyBack = OKeyBack = FKeyBack = DispBack = IconBack = BackColor;

    if (dpcs>2&&(nfc !=NULL)&&XAllocNamedColor(dpy, colors, nfc, &xcsd, &xced))
      NKeyFore=xcsd.pixel;

    if (dpcs>2&&(nbc !=NULL)&&XAllocNamedColor(dpy, colors, nbc, &xcsd, &xced))
      NKeyBack=xcsd.pixel;

    if (dpcs>2&&(ofc !=NULL)&&XAllocNamedColor(dpy, colors, ofc, &xcsd, &xced))
      OKeyFore=xcsd.pixel;

    if (dpcs>2&&(obc !=NULL)&&XAllocNamedColor(dpy, colors, obc, &xcsd, &xced))
      OKeyBack=xcsd.pixel;

    if (dpcs>2&&(ffc !=NULL)&&XAllocNamedColor(dpy, colors, ffc, &xcsd, &xced))
      FKeyFore=xcsd.pixel;

    if (dpcs>2&&(fbc !=NULL)&&XAllocNamedColor(dpy, colors, fbc, &xcsd, &xced))
      FKeyBack=xcsd.pixel;

    if (dpcs>2&&(dfc !=NULL)&&XAllocNamedColor(dpy, colors, dfc, &xcsd, &xced))
      DispFore=xcsd.pixel;

    if (dpcs>2&&(dbc !=NULL)&&XAllocNamedColor(dpy, colors, dbc, &xcsd, &xced))
      DispBack=xcsd.pixel;

    if (dpcs>2&&(ifc !=NULL)&&XAllocNamedColor(dpy, colors, ifc, &xcsd, &xced))
      IconFore=xcsd.pixel;

    if (dpcs>2&&(ibc !=NULL)&&XAllocNamedColor(dpy, colors, ibc, &xcsd, &xced))
      IconBack=xcsd.pixel;

    /* load fonts, figure out sizes of keypad and display */
    kfontinfo = XLoadQueryFont(dpy, kfont);
    if (!kfontinfo) kfontinfo = XLoadQueryFont(dpy, "fixed");
    if (!kfontinfo) XCalcError("Can't open '%s' or 'fixed' font\n",KFONT);
    keyfont = kfontinfo->fid;

    dfontinfo = XLoadQueryFont(dpy, dfont);
    if (!dfontinfo) dfontinfo = XLoadQueryFont(dpy, "fixed");
    if (!dfontinfo) XCalcError("Can't open '%s' or 'fixed' font\n",DFONT);
    dispfont = dfontinfo->fid;

    ffontinfo = XLoadQueryFont(dpy, ffont);
    if (!ffontinfo) ffontinfo = XLoadQueryFont(dpy, "fixed");
    if (!ffontinfo) XCalcError("Can't open '%s' or 'fixed' font\n",FFONT);
    flagfont = ffontinfo->fid;

    keywide = XTextWidth(kfontinfo, "MMM", 3) + KEYPADW;
    keyhigh = kfontinfo->ascent + KEYPADH + (rpn ? 2*EXTRAH : 0);

    dispwide  = (rpn ? 6 : 5)*keywide+4*PADDINGW;
    disphigh = dfontinfo->ascent + DISPPADH + FLAGH;

    /* Create Stipple pattern */
    stipplePix = XCreateBitmapFromData (dpy, DefaultRootWindow(dpy),
        check_bits, check_width, check_height);
       
    dimBorder        = stipplePix;

    /* Create Icon Pixmap */
    IconPix = XCreateBitmapFromData (dpy, DefaultRootWindow(dpy),
        icon_bits, icon_width, icon_height);

    if (analog)
      do_sr(argc, argv, geom, border);

    /* Open the main window. */

    if (rpn) {
	min_width  = 10*keywide + 11*PADDINGW + 2;
	min_height = disphigh + 4*keyhigh + 6*PADDINGH + 2;
    } else {
	min_width  = dispwide + 2*PADDINGW + 2;
	min_height = disphigh + 2 + 8*keyhigh + 10*PADDINGH + 10*EXTRAH;
    }

    theWindow = XCreateSimpleWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)),
				    0, 0, min_width, min_height, border,
				    ForeColor, BackColor);
    if (!theWindow) XCalcError("Can't open calculator window");

    if (stip)
      XSetWindowBackgroundPixmap(dpy, theWindow, stipplePix);

    szhint.flags = PSize|PMinSize;
    szhint.width = szhint.min_width = min_width;
    szhint.height = szhint.min_height = min_height;
    XSetStandardProperties(dpy, theWindow, "Calculator", NULL, IconPix,
			   argv, argc, &szhint);

    gcv.function = GXcopyInverted;
    gcv.foreground = DispFore;
    gcv.background = DispBack;
    gcv.font = dispfont;
    dispbgc = XCreateGC(dpy, theWindow,
			GCForeground|GCBackground|GCFunction|GCFont, &gcv);
    gcv.function = GXcopy;
    dispfgc = XCreateGC(dpy, theWindow,
			GCForeground|GCBackground|GCFunction|GCFont, &gcv);
    gcv.font = flagfont;
    flaggc = XCreateGC(dpy, theWindow,
			GCForeground|GCBackground|GCFunction|GCFont, &gcv);
    gcv.function = GXcopy;
    gcv.foreground = NKeyFore;
    gcv.background = NKeyBack;
    gcv.font = keyfont;
    keygc = XCreateGC(dpy, theWindow,
		      GCForeground|GCBackground|GCFunction|GCFont, &gcv);
    gcv.function = GXinvert;
    keyigc = XCreateGC(dpy, theWindow, GCFunction, &gcv);
			

    if (rpn)
      SetupHPCalc();
    else
      SetupTICalc();

    ResetCalc();

    XSelectInput(dpy, theWindow, ExposureMask|KeyPressMask|EnterWindowMask|
		 		 LeaveWindowMask);
    XSelectInput(dpy, dispwid,   ExposureMask|EnterWindowMask|LeaveWindowMask);

    for (i=0; i<numkeys; i++)
        XSelectInput(dpy,key[i].wid,ExposureMask|ButtonPressMask|
			  ButtonReleaseMask|EnterWindowMask|LeaveWindowMask);
    XMapWindow    (dpy, theWindow);
    XMapSubwindows(dpy, theWindow);
    arrow=XCreateFontCursor(dpy, XC_hand2);
    XDefineCursor(dpy, theWindow,arrow);

    /*********** Set up SIGFPE hander ***********/
#ifndef IEEE
    signal(SIGFPE,fperr);
#endif

    /**************** Main loop *****************/

    while (1) {
        Window wind;

        XNextEvent(dpy, &event);

        switch (event.type) {

        case Expose: {
            XExposeEvent *exp_event = (XExposeEvent *) &event;
            wind = exp_event->window;

	    if (wind==theWindow) XClearArea(dpy,theWindow,exp_event->x,
					    exp_event->y,exp_event->width,
					    exp_event->height,False);
	    else if (wind==dispwid) DrawDisplay();
            else if (wind==iconWindow)
	      ;
            else {
                for (i=0; i<numkeys; i++) {
                   if (key[i].wid==wind) DrawKey(i);
                   }
                }
            }
            break;

        case ButtonPress: {
            XButtonPressedEvent *but_event = (XButtonPressedEvent *) &event;
            wind = but_event->window;
            if ((but_event->button & 0xff) == Button1) {
                for (i=0; i<numkeys; i++) {
                   if (key[i].wid==wind) { InvertKey(i); invkey=i; }
                   }
                }

            else if ((but_event->button & 0xff) == Button3) {
	      for (i=0; i<numkeys; i++) {
		if (key[i].wid==wind && key[i].code==kOFF)
		  Quit();
	      }
	    }
	    else XBell(dpy, 0);
	    }
            break;
                       
        case ButtonRelease: {
            XButtonReleasedEvent *but_event = (XButtonReleasedEvent *) &event;
            wind = but_event->window;
            if ((but_event->button & 0xff) == Button1) {
                for (i=0; i<numkeys; i++) {
                   if (key[i].wid==wind) LetGoKey(invkey);
                   }
                invkey = -1;
                }
            }
            break;

        case KeyPress: {
            XKeyPressedEvent *key_event = (XKeyPressedEvent *) &event;
	    char *st, keybuf[10];
            wind = key_event->window;
            if (wind==theWindow) {
	      i = XLookupString(key_event, keybuf, sizeof(keybuf), NULL, NULL);
	      for (st = keybuf; i > 0; i--)
		TypeChar(*st++);
	    } else 
	      printf("KeyPressed in window %ld\n",wind);
	    }
	    break;

	case EnterNotify:
	case LeaveNotify: {
	    XCrossingEvent *cross_event = (XCrossingEvent *) &event;

	    if ((cross_event->detail != NotifyInferior) &&
		(cross_event->window == theWindow) &&
		(cross_event->mode == NotifyNormal) &&
		cross_event->focus) {
		if (event.type == EnterNotify)
		    XSetWindowBorder(dpy,theWindow,ForeColor);
		else
		    XSetWindowBorderPixmap(dpy,theWindow,dimBorder);
	    }
            break;
	  }
        default:
           printf("event type=%ld\n",event.type); 
           XCalcError("Unexpected X_Event");

        }  /* end of switch */
    }  /* end main loop */}



/***********************************/
Syntax(call)
 char *call;
{
    printf ("Usage: %s [-bw <pixels>] [-stip] [-help] [-rv] [-rpn] [-analog]\n", call);
    printf ("          [[<host>]:[<vs>]] [=geometry]\n\n");
    printf ("Default: %s -bw %d =156x226-16-16\n\n",call, DEF_BDRWIDE);
    exit(0);
}


/***********************************/
XCalcError(identifier,arg1,arg2,arg3,arg4)
       char *identifier,*arg1,*arg2,*arg3,*arg4;
{
    fprintf(stderr, identifier, arg1,arg2,arg3,arg4);
    exit(1);
}



/***********************************/
SetupTICalc()
{
    int i;

    numkeys=TINUMKEYS;
    key = &tikeys[0];

    for (i=0; i<numkeys; i++) {
        key[i].x = PADDINGW+(i%5)*(keywide+PADDINGW);
        key[i].y = disphigh+2+2*PADDINGH+(i/5)*(keyhigh+PADDINGH);
        key[i].width = keywide;
        key[i].height = keyhigh;
        if (i>=15) {
            key[i].height+=(2*EXTRAH);
            key[i].y     += ((i-15)/5)*EXTRAH*2;
            }

        switch (tikeys[i].code) {
            case kZERO:  case kONE:  case kTWO:  case kTHREE:
            case kFOUR:  case kFIVE: case kSIX:  case kSEVEN:
            case kEIGHT: case kNINE: case kDEC:  case kNEG:
                key[i].fore=NKeyFore;
                key[i].back=NKeyBack;
                break;
            case kADD:   case kSUB:  case kMUL:  case kDIV:  case kEQU:
                key[i].fore=OKeyFore;
                key[i].back=OKeyBack;
                break;
            default:
                key[i].fore=FKeyFore;
                key[i].back=FKeyBack;
            }
	key[i].wid=XCreateSimpleWindow(dpy,theWindow,key[i].x,key[i].y,
				       key[i].width,key[i].height,1,
				       key[i].fore,key[i].back);
        }

    dispwid = XCreateSimpleWindow(dpy,theWindow,PADDINGW,PADDINGH,
				  dispwide-2,disphigh,2,DispFore,DispBack);
}

SetupHPCalc()
{
    int i,j;

    numkeys=HPNUMKEYS;
    key = &hpkeys[0];

    for (i=0; i<numkeys; i++) {
        j = (i<35)? i : i + 1;
        key[i].x = PADDINGW+(j%10)*(keywide+PADDINGW);
        key[i].y = disphigh+2+2*PADDINGH+(j/10)*(keyhigh+PADDINGH);
        key[i].width = keywide;
        key[i].height = keyhigh;
        if (i==25) {
            key[i].height = keyhigh*2 + PADDINGH;
            }

        switch (hpkeys[i].code) {
            case kZERO:  case kONE:  case kTWO:  case kTHREE:
            case kFOUR:  case kFIVE: case kSIX:  case kSEVEN:
            case kEIGHT: case kNINE: case kDEC:  case kNEG:
	    case kBKSP: case kEE:
                key[i].fore=NKeyFore;
                key[i].back=NKeyBack;
                break;
            case kADD:   case kSUB:  case kMUL:  case kDIV:  case kENTR:
                key[i].fore=OKeyFore;
                key[i].back=OKeyBack;
                break;
            default:
                key[i].fore=FKeyFore;
                key[i].back=FKeyBack;
            }
	key[i].wid=XCreateSimpleWindow(dpy,theWindow,key[i].x,key[i].y,
				       key[i].width,key[i].height,1,
				       key[i].fore,key[i].back);
        }
    dispwid = XCreateSimpleWindow(dpy,theWindow,PADDINGW+keywide,PADDINGH,
				  dispwide-2,disphigh,2,DispFore,DispBack);
}


/**************/
DrawDisplay()
{
    int strwide;

    if (strlen(dispstr)>12) {       /* strip out some decimal digits */
        char tmp[32];
        char *exp = index(dispstr,'e');  /* search for exponent part */
        if (!exp) dispstr[12]='\0';      /* no exp, just trunc. */
        else {
            if (strlen(exp)<=4) 
                sprintf(tmp,"%.8s",dispstr); /* leftmost 8 chars */
            else
                sprintf(tmp,"%.7s",dispstr); /* leftmost 7 chars */
            strcat (tmp,exp);            /* plus exponent */
            strcpy (dispstr,tmp);
            }
        }

    strwide=XTextWidth(dfontinfo,dispstr,strlen(dispstr));

    XFillRectangle(dpy,dispwid,dispfgc,0,0,10,disphigh);
    XFillRectangle(dpy,dispwid,dispfgc,dispwide-10,0,dispwide,disphigh);
    XFillRectangle(dpy,dispwid,dispbgc,10,0,dispwide-20,disphigh);

    XDrawString(dpy,dispwid,dispfgc,dispwide-10-DISPPADW/2-strwide,
		DISPPADH/2+dfontinfo->ascent,dispstr,strlen(dispstr));

    if (flagM) 	       XDrawString(dpy,dispwid,flaggc,12,10,"M",1);
    if (flagE) 	       XDrawString(dpy,dispwid,flaggc,12,20,"E",1);
    if (flagK)         XDrawString(dpy,dispwid,flaggc,20,disphigh-2,"K",1);
    if (flagINV)       XDrawString(dpy,dispwid,flaggc,30,disphigh-2,"INV",3);
    if (drgmode==DEG)  XDrawString(dpy,dispwid,flaggc,60,disphigh-2,"DEG",3);
    if (drgmode==RAD)  XDrawString(dpy,dispwid,flaggc,80,disphigh-2,"RAD",3);
    if (drgmode==GRAD) XDrawString(dpy,dispwid,flaggc,100,disphigh-2,"GRAD",4);
    if (flagPAREN)     XDrawString(dpy,dispwid,flaggc,130,disphigh-2,"( )",3);
}


/***************/
DrawKey(keynum)
    int keynum;
{
    char *str;
    int strwide,extrapad;
    struct _key *kp;

    kp = &key[keynum];
    str = kp->st;
    strwide = XTextWidth(kfontinfo,str,strlen(str));

    extrapad = (keynum>=15 || rpn) ? EXTRAH : 0;
    if (rpn && kp->code == kENTR)
      extrapad = keyhigh;

    XDrawString(dpy,kp->wid,keygc,(kp->width-strwide)/2,
		KEYPADH/2+extrapad+kfontinfo->ascent,str,strlen(str));
}


/*********************************/
InvertKey(keynum)
    int keynum;
{
    struct _key *kp;

    kp = &key[keynum];
    
    XFillRectangle(dpy, kp->wid, keyigc, 0, 0, kp->width, kp->height);
}


/* This section is all of the state machine that implements the calculator
 * functions.  Much of it is shared between the infix and rpn modes.
 */

static double drg2rad=PI/180.0;  /* Conversion factors for trig funcs */
static double rad2drg=180.0/PI;
static int entered=1;  /* true if display contains a valid number.
                          if==2, then use 'dnum', rather than the string
                          stored in the display.  (for accuracy) 
                          if==3, then error occurred, only CLR & AC work */
static int clear  =0;  /* CLR clears display.  if 1, clears acc, also */
static int off    =0;  /* once clears mem, twice quits */
static int decimal=0;  /* to prevent using decimal pt twice in a # */
static int clrdisp=1;  /* if true clears display before entering # */
static int accset =0;
static int lastop =kCLR;
static int memop  =kCLR;
static int exponent=0;
static double acc =0.0;
static double dnum=0.0;
static double mem[10] = { 0.0 };

/*********************************/
LetGoKey(keynum)
     int keynum;
{
    int i;
    int code;

    if (keynum==-1) return;
 
    errno = 0;			/* for non-IEEE machines */

    InvertKey(keynum);

    if ( (entered==3) && !(key[keynum].code==kCLR || key[keynum].code==kOFF)) {
      if (rpn) {
	clrdisp++;
      } else {
        XBell(dpy, 0);
        return;
      }
    }

    code = key[keynum].code;
    if (code != kCLR) clear=0;
    if (code != kOFF) off=0;


#ifndef IEEE
    i=setjmp(env);
    if (i) {
        switch (i) {
#ifdef FPE_FLTDIV_TRAP
           case FPE_FLTDIV_TRAP:  strcpy(dispstr,"div by zero"); break;
#endif
#ifdef FPE_FLTDIV_FAULT
           case FPE_FLTDIV_FAULT: strcpy(dispstr,"div by zero"); break;
#endif
#ifdef FPE_FLTOVF_TRAP
           case FPE_FLTOVF_TRAP:  strcpy(dispstr,"overflow"); break;
#endif
#ifdef FPE_FLTOVF_FAULT
           case FPE_FLTOVF_FAULT: strcpy(dispstr,"overflow"); break;
#endif
#ifdef FPE_FLTUND_TRAP
           case FPE_FLTUND_TRAP:  strcpy(dispstr,"underflow"); break;
#endif
#ifdef FPE_FLTUND_FAULT
           case FPE_FLTUND_FAULT: strcpy(dispstr,"underflow"); break;
#endif
           default:               strcpy(dispstr,"error");
           }
        entered=3;
        DrawDisplay();
        return;
        }
#endif

    (key[keynum].fun)(keynum);
    memop = code;

#ifndef IEEE
    if (errno) {
        strcpy(dispstr,"error");
        DrawDisplay();
        entered=3;
        errno=0;
        }
#endif
}


digit(keynum)
     int keynum;
{
  flagINV=0;
  if (rpn && (memop == kSTO || memop == kRCL || memop == kSUM)) {
      switch (memop) {
      case kSTO: mem[*(key[keynum].st) - '0'] = dnum; break;
      case kRCL: dnum = mem[*(key[keynum].st) - '0'];
		 sprintf(dispstr, "%.8g", dnum);
	  	 break;
      case kSUM: mem[*(key[keynum].st) - '0'] += dnum; break;
      }
      DrawDisplay();
      entered = 2;
      clrdisp++;
      return;
  }
  if (clrdisp) {
    dispstr[0]='\0';
    exponent=decimal=0;
    if (rpn && entered==2)
      PushNum(dnum);
  }
  if (strlen(dispstr)>=MAXDISP)
    return;
  strcat(dispstr,key[keynum].st);
  DrawDisplay();
  if (clrdisp && key[keynum].code != kZERO)
    clrdisp=0; /*no leading 0s*/
  entered=1;
}

bkspf()
{
  if (entered!=1 || clrdisp)
    return;
  if (strlen(dispstr) > 0)
    dispstr[strlen(dispstr)-1] = 0;
  if (strlen(dispstr) == 0) {
    strcat(dispstr, "0");
    clrdisp++;
  }
  DrawDisplay();
}

decf()
{
  flagINV=0;
  if (clrdisp) {
      if (rpn)
	PushNum(dnum);
      strcpy(dispstr,"0");
  }
  if (!decimal) {
    strcat(dispstr,".");
    DrawDisplay();
    decimal++;
  }
  clrdisp=0;
  entered=1;
}

eef()
{
  flagINV=0;
  if (clrdisp) {
      if (rpn)
	PushNum(dnum);
      strcpy(dispstr, rpn ? "1" : "0");
  }
  if (!exponent) {
    strcat(dispstr,"E+");
    DrawDisplay();
    exponent=strlen(dispstr)-1;  /* where the '-' goes */
  }
  clrdisp=0;
  entered=1;
}

clearf()
{
  flagINV=0;
  if (clear && !rpn) { /* clear all */
    ClearStacks();
    flagPAREN=0;
  }
  clear++;
  exponent=decimal=0;
  clrdisp=1;
  entered=1;
  strcpy(dispstr,"0");
  DrawDisplay();
}

negf()
{
  flagINV=0;
  if (exponent) {       /* neg the exponent */
    if (dispstr[exponent]=='-')
      dispstr[exponent]='+';
    else
      dispstr[exponent]='-';
    DrawDisplay();
    return;
  }

  if (strcmp("0",dispstr)==0)
    return;			/* don't neg a zero */
  if (dispstr[0]=='-')	 	/* already neg-ed */
    strcpy(dispstr,dispstr+1);  /* move str left once */
  else {			/* not neg-ed.  add a '-' */
    char tmp[32];
    sprintf(tmp,"-%s",dispstr);
    strcpy(dispstr,tmp);
  }
  if (entered==2)
    dnum = -1.0 * dnum;
  DrawDisplay();
}

/* Two operand functions for infix calc */
twoop(keynum)
{
  double PopNum();

  if (flagINV) {
    flagINV=0;
    DrawDisplay();
  }

  if (!entered) {		/* something like "5+*" */
    if (!isopempty())
      PopOp();			/* replace the prev op */
    PushOp(key[keynum].code);	/* with the new one */
    return;
  }
  
  if (entered==1)
    sscanf(dispstr,"%lf",&dnum);

  clrdisp=clear=1;
  entered=decimal=exponent=0;

  if (!isopempty()) {  /* there was a previous op */
    lastop=PopOp();   /* get it */

    if (lastop==kLPAR) {  /* put it back */
      PushOp(kLPAR);
      PushOp(key[keynum].code);
      PushNum(dnum);
      return;
    }

    /* now, if the current op (keynum) is of
       higher priority than the lastop, the current
       op and number are just pushed on top 
       Priorities:  (Y^X) > *,/ > +,- */
    
    if (priority(key[keynum].code) > priority(lastop)) {
      PushNum(dnum);
      PushOp(lastop);
      PushOp(key[keynum].code);
    } else {  /* execute lastop on lastnum and dnum, push
	       result and current op on stack */
      acc=PopNum();
      switch (lastop) { /* perform the operation */
      case kADD: acc += dnum;  break;
      case kSUB: acc -= dnum;  break;
      case kMUL: acc *= dnum;  break;
      case kDIV: acc /= dnum;  break;
      case kPOW: acc =  pow(acc,dnum);  break;
	}
      PushNum(acc);
      PushOp(key[keynum].code);
      sprintf(dispstr,"%.8g",acc);
      DrawDisplay();
      dnum=acc;
    }
  }
  else { /* op stack is empty, push op and num */
    PushOp(key[keynum].code);
    PushNum(dnum);
  } 
}                      

/* Two operand functions for rpn calc */
twof(keynum)
{
  double PopNum();

  if (flagINV) {
    flagINV=0;
    DrawDisplay();
  }
  if (!entered)
    return;
  if (entered==1)
    sscanf(dispstr, "%lf", &dnum);
  acc = PopNum();
  switch(key[keynum].code) {
  case kADD: acc += dnum;  break;
  case kSUB: acc -= dnum;  break;
  case kMUL: acc *= dnum;  break;
  case kDIV: acc /= dnum;  break;
  case kPOW: acc =  pow(acc,dnum);  break;
  case kXXY: PushNum(dnum);
  }
  sprintf(dispstr, "%.8g", acc);
  DrawDisplay();
  clrdisp++;
  decimal = exponent = 0;
  entered = 2;
  dnum = acc;
}


entrf()
{
  flagINV=0;
  if (!entered)
    return;

  clrdisp=clear=1;
  decimal=exponent=0;

  if (entered==1)
    sscanf(dispstr,"%lf",&dnum);
  entered=2;

  if (entered==2)
    PushNum(dnum);
}

equf()
{
  double PopNum();

  flagINV=0;
  if (!entered)
    return;

  clrdisp=clear=1;
  decimal=exponent=0;

  if (entered==1)
    sscanf(dispstr,"%lf",&dnum);
  entered=2;

  PushNum(dnum);

  while (!isopempty()) {  /* do all pending ops */
    dnum=PopNum();
    acc=PopNum();
    lastop=PopOp();
    switch (lastop) {
    case kADD:  acc += dnum;
		break;
    case kSUB:  acc -= dnum;
		break;
    case kMUL:  acc *= dnum;
		break;
    case kDIV:  acc /= dnum;
		break;
    case kPOW:  acc = pow(acc,dnum);
		break;
    case kLPAR:	flagPAREN--;
		PushNum(acc);
		break;
    }
    dnum=acc;
    PushNum(dnum);
  }

  sprintf(dispstr,"%.8g",dnum);
  DrawDisplay();
}
        
lparf()
{
  flagINV=0;
  PushOp(kLPAR);
  flagPAREN++;
  DrawDisplay();
}

rollf()
{
  double PopNum();

  if (!entered)
    return;
  if (entered==1)
    sscanf(dispstr, "%lf", &dnum);
  entered = 2;
  RollNum(flagINV);
  flagINV=0;
  clrdisp++;
  sprintf(dispstr, "%.8g", dnum);
  DrawDisplay();
}

rparf()
{
  double PopNum();

  flagINV=0;
  if (!entered)
    return;

  if (!flagPAREN)
    return;
  
  clrdisp++;
  decimal=exponent=0;

  if (entered==1)
    sscanf(dispstr,"%lf",&dnum);
  entered=2;

  PushNum(dnum);
  while (!isopempty() && (lastop=PopOp())!=kLPAR) {
    /* do all pending ops, back to left paren */
    dnum=PopNum();
    acc=PopNum();
    switch (lastop) {
    case kADD:  acc += dnum;
		break;
    case kSUB:  acc -= dnum;
		break;
    case kMUL:  acc *= dnum;
		break;
    case kDIV:  acc /= dnum;
		break;
    case kPOW:  acc = pow(acc,dnum);
		break;
    }
    dnum=acc;
    PushNum(dnum);
  }
  PopNum();
  flagPAREN--;
  entered=2;
  sprintf(dispstr,"%.8g",dnum);
  DrawDisplay();
}

drgf()
{
  if (flagINV) {
    if (entered==1)
      sscanf(dispstr,"%lf",&dnum);
    switch (drgmode) {
    case DEG:  dnum=dnum*PI/180.0;    break;
    case RAD:  dnum=dnum*200.0/PI;    break;
    case GRAD: dnum=dnum*90.0/100.0;  break;
    }
    entered=2;
    clrdisp=1;
    flagINV=0;
    sprintf(dispstr,"%.8g",dnum);
  }
                         
  flagINV=0;
  drgmode = ++drgmode % 3;
  switch (drgmode) {
  case DEG:  drg2rad=PI / 180.0;
	     rad2drg=180.0 / PI;
	     break;
  case RAD:  drg2rad=1.0;
	     rad2drg=1.0;
	     break;
  case GRAD: drg2rad=PI / 200.0;
	     rad2drg=200.0 / PI;
	     break;
  }
  DrawDisplay();
}

invf()
{
  flagINV = ~flagINV;
  DrawDisplay();
}

memf(keynum)
{
    if (entered==1)
      sscanf(dispstr,"%lf",&dnum);
    entered = 2;
    clrdisp++;
}

oneop(keynum)
{
  int i,j;
  double dtmp;

  if (entered==1)
    sscanf(dispstr,"%lf",&dnum);
  entered = 2;

  switch (key[keynum].code) {  /* do the actual math fn. */
  case kE:     if (rpn && memop != kENTR) PushNum(dnum); dnum=E;  break;
  case kPI:    if (rpn && memop != kENTR) PushNum(dnum); dnum=PI;  break;
  case kRECIP: dnum=1.0/dnum;  break;
  case kSQR:   flagINV = !flagINV; /* fall through to */
  case kSQRT:  if (flagINV) dnum=dnum*dnum;
	       else dnum=sqrt(dnum);
	       break;
  case k10X:   flagINV = !flagINV; /* fall through to */
  case kLOG:   if (flagINV) dnum=pow(10.0,dnum);
  	       else dnum=log10(dnum);
	       break;
  case kEXP:   flagINV = !flagINV; /* fall through to */
  case kLN:    if (flagINV) dnum=exp(dnum);
	       else dnum=log(dnum);
	       break;
  case kSIN:   if (flagINV) dnum=asin(dnum)*rad2drg;
	       else dnum=sin(dnum*drg2rad);
	       break;
  case kCOS:   if (flagINV) dnum=acos(dnum)*rad2drg;
	       else dnum=cos(dnum*drg2rad);
	       break;
  case kTAN:   if (flagINV) dnum=atan(dnum)*rad2drg;
	       else dnum=tan(dnum*drg2rad);
	       break;
  case kSTO:   mem[0]=dnum;  flagM=!(mem[0]==0.0);  break;
  case kRCL:   dnum=mem[0];  flagM=!(mem[0]==0.0);  break;
  case kSUM:   mem[0]+=dnum; flagM=!(mem[0]==0.0);  break;
  case kEXC:   dtmp=dnum; dnum=mem[0];  mem[0]=dtmp;
	       flagM=!(mem[0]==0.0);  break;
  case kFACT:  if (floor(dnum)!=dnum || dnum<0.0 || dnum>500.0) {
		 strcpy(dispstr,"error");
		 entered=3;
		 break;
	       }
	       i=(int) (floor(dnum));
	       for (j=1,dnum=1.0; j<=i; j++) 
		 dnum*=(float) j;
	       break;
  }
  
  if (entered==3) {  /* error */
    DrawDisplay();
    return;
  }

  entered=2;
  clrdisp=1;
  flagINV=0;
  sprintf(dispstr,"%.8g",dnum);
  DrawDisplay();
}

offf()
{
  /* full reset */
  ResetCalc();
  entered=clrdisp=1;
  dnum=mem[0]=0.0;
  accset=exponent=decimal=0;
  DrawDisplay();
}


nop()
{
  XBell(dpy, 0);
}


/*******/
Quit()
/*******/
{
    exit(0);
}


#define STACKMAX 32
static int opstack[STACKMAX];
static int opsp;
static double numstack[STACKMAX];
static int numsp;


/*******/
PushOp(op)
   int op;
/*******/
{
  if (opsp==STACKMAX) {strcpy(dispstr,"stack error");  entered=3;}
  else opstack[opsp++]=op;
}

/*******/
int PopOp()
/*******/
{
  if (opsp==0) {
      strcpy(dispstr,"stack error");
      entered=3;
      return(kNOP);
  } else
    return(opstack[--opsp]);
}

/*******/
int isopempty()
/*******/
{
  return( opsp ? 0 : 1 );
}

/*******/
PushNum(num)
 double num;
/*******/
{
  if (rpn) {
      numstack[2] = numstack[1];
      numstack[1] = numstack[0];
      numstack[0] = num;
      return;
  }
  if (numsp==STACKMAX) {
      strcpy(dispstr,"stack error");
      entered=3;
  } else
    numstack[numsp++]=num;
}

/*******/
double PopNum()
/*******/
{
    if (rpn) {
	double tmp = numstack[0];
	numstack[0] = numstack[1];
	numstack[1] = numstack[2];
	return(tmp);
    }
    if (numsp==0) {
	strcpy(dispstr,"stack error");
	entered=3;
    } else
      return(numstack[--numsp]);
}

/*******/
RollNum(dir)
/*******/
{
    double tmp;

    if (!dir) {
	tmp         = dnum;
	dnum        = numstack[2];
	numstack[2] = numstack[1];
	numstack[1] = numstack[0];
	numstack[0] = tmp;
    } else {
	tmp         = dnum;
	dnum        = numstack[0];
	numstack[0] = numstack[1];
	numstack[1] = numstack[2];
	numstack[2] = tmp;
    }
}


/*******/
int isnumempty()
/*******/
{
  return( numsp ? 0 : 1 );
}


/*******/
ClearStacks()
/*******/
{
    if (rpn)
      numstack[0] = numstack[1] = numstack[2] = 0.;
    opsp=numsp=0;
}


/*******/
int priority(op)
         int op;
/*******/
{
    switch (op) {
        case kPOW: return(2);
        case kMUL:
        case kDIV: return(1);
        case kADD:
        case kSUB: return(0);
        }
}


/********/
ResetCalc()
/********/
{
    flagM=flagK=flagINV=flagE=flagPAREN=0;  drgmode=DEG;
    strcpy(dispstr,"0");
    ClearStacks();
    drg2rad=PI/180.0;
    rad2drg=180.0/PI;
}


/*********/
TypeChar(c)
    char c;
/*********/
{
    /* figure out if person typed a valid calculator key.
         If so, press the key, wait a bit, and release the key
         else Feep() */

    int i,code;

    switch (c) {
        case '0':  code=kZERO;   break;
        case '1':  code=kONE;    break;
        case '2':  code=kTWO;    break;
        case '3':  code=kTHREE;  break;
        case '4':  code=kFOUR;   break;
        case '5':  code=kFIVE;   break;
        case '6':  code=kSIX;    break;
        case '7':  code=kSEVEN;  break;
        case '8':  code=kEIGHT;  break;
        case '9':  code=kNINE;   break;
        case '.':  code=kDEC;    break;
        case '+':  code=kADD;    break;
        case '-':  code=kSUB;    break;
        case '*':  code=kMUL;    break;
        case '/':  code=kDIV;    break;
        case '(':  code=kLPAR;   break;
        case ')':  code=kRPAR;   break;
        case '!':  code=kFACT;   break;
        case 'e':  code=kEE;     break;
        case '^':  code=kPOW;    break;
        case 'p':  code=kPI;     break;
        case 'i':  code=kINV;    break;
        case 's':  code=kSIN;    break;
        case 'c':  code=kCOS;    break;
        case 't':  code=kTAN;    break;
        case 'd':  code=kDRG;    break;
        case 'l':  code=kLN;     break;
        case '=':  code=kEQU;    break;
        case 'n':  code=kNEG;    break;
	case 'r':  code=kSQRT;   break;
	case 'x':  code=kXXY;    break;
	case '\r':
	case '\n': code=kENTR;	 break;
        case '\177':
        case '\010': code=kBKSP; break;
	case ' ':  code=kCLR;    break;
        case '\003': Quit();     break;
        default:   code = -1;
        }

    if (!rpn && code == kBKSP)
      code = kCLR;
    for (i=0; i < numkeys; i++)
      if (key[i].code == code) break;

    if (code != -1 && i < numkeys && key[i].code == code) {
        InvertKey(i);
        XFlush(dpy);
        Timer(100000L);
        LetGoKey(i);
        XFlush(dpy);
        }
    else XBell(dpy,0);
}



static int timerdone;

/*******/
onalarm()
/*******/
{
  timerdone=1;
}

/*******/
Timer(val)
 long val;
/*******/
{
	val /= 1000;
	val = (val+17)/16;
	nap(val);
}



#ifndef IEEE
/******************/
fperr(sig,code,scp)
  int sig,code;
  struct sigcontext *scp;
/******************/
{
    longjmp(env,code);
}

#endif

unix.superglobalmegacorp.com

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