Annotation of researchv9/X11/src/X.V11R1/clients/xcalc/xcalc.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     $Source: /u1/X11/clients/xcalc/RCS/xcalc.c,v $
                      3:  *     $Header: xcalc.c,v 1.4 87/09/12 19:00:36 rws Exp $
                      4:  */
                      5: 
                      6: #ifndef lint
                      7: static char *rcsid_xcalc_c = "$Header: xcalc.c,v 1.4 87/09/12 19:00:36 rws Exp $";
                      8: #endif lint
                      9: 
                     10: /*
                     11:  * xcalc.c  -  a hand calculator for the X Window system
                     12:  *
                     13:  *  Author:    John H. Bradley, University of Pennsylvania
                     14:  *                ([email protected])
                     15:  *                     March, 1987
                     16:  *
                     17:  *  RPN mode added and port to X11 by Mark Rosenstein, MIT Project Athena
                     18:  */
                     19: 
                     20: /*
                     21:  * color usage:  ForeColor is used for all frames, BackColor is the color of 
                     22:  *                  the calculator body.
                     23:  *               NKeyFore, NKeyBack are the colors used for the number keys.
                     24:  *               OKeyFore, OKeyBack are used for the operator keys (+-*=/).
                     25:  *               FKeyFore, FKeyBack are used for all the other keys.
                     26:  *               DispFore, DispBack are used for the display.
                     27:  *               IconFore, IconBack are used for the display.
                     28:  *
                     29:  *               if running on monochrome monitor, or if 'stipple' option
                     30:  *                  set, the calculator body is a 50% stipple of ForeColor
                     31:  *                  and BackColor.  This looks nice in mono, but can prevent
                     32:  *                  you from getting the 'right' colors in color mode, so
                     33:  *                  it's an option.
                     34:  */
                     35: 
                     36: #include <stdio.h>
                     37: #include <math.h>
                     38: #include <strings.h>
                     39: #include <signal.h>
                     40: #include <X11/Xlib.h>
                     41: #include <X11/Xutil.h>
                     42: #include <X11/cursorfont.h>
                     43: #include <sys/time.h>
                     44: #include <setjmp.h>
                     45: 
                     46: /* program icon */
                     47: #include "icon"
                     48: 
                     49: extern int errno;
                     50: 
                     51: 
                     52: /* constants used for setting up the calculator.  changing them would 
                     53:    probably be bad.  If you do, don't forget to change the values in the
                     54:    syntax routine */
                     55: 
                     56: #define KFONT "helvetica-medium9"
                     57: #define DFONT "helvetica-bold12"
                     58: #define FFONT "helvetica-medium8"
                     59: #define PADDINGW    4
                     60: #define PADDINGH    8
                     61: #define DEF_BDRWIDE 2
                     62: #define MAXDISP     11
                     63: #define KEYPADH     3
                     64: #define KEYPADW     2
                     65: #define EXTRAH      2
                     66: #define DISPPADH    4
                     67: #define DISPPADW    8
                     68: #define FLAGH       10
                     69: #define PI          3.14159265358979
                     70: #define E           2.71828182845904
                     71: 
                     72: /* DRG mode.  used for trig calculations */
                     73: #define DEG 0
                     74: #define RAD 1
                     75: #define GRAD 2
                     76: 
                     77: 
                     78: /* fonts */
                     79: char *kfont, *dfont, *ffont;
                     80: 
                     81: /* colors */
                     82: int ForeColor, BackColor, NKeyFore, NKeyBack, OKeyFore, OKeyBack;
                     83: int FKeyFore, FKeyBack, DispFore, DispBack, IconFore, IconBack;
                     84: 
                     85: int border = DEF_BDRWIDE;
                     86: 
                     87: 
                     88: /* objects */
                     89: Display         *dpy;
                     90: Window   theWindow, iconWindow, dispwid;
                     91: Cursor   arrow;
                     92: Font     keyfont, dispfont, flagfont;
                     93: XFontStruct *kfontinfo, *dfontinfo, *ffontinfo; 
                     94: Pixmap   stipplePix, dimBorder, IconPix;
                     95: GC      dispbgc,dispfgc,keygc,keyigc,flaggc;
                     96: 
                     97: /* variables used in setup */
                     98: int numkeys, dispwide, disphigh, keywide, keyhigh;
                     99: 
                    100: 
                    101: /* RPN or Infix mode */
                    102: int rpn          = 0;      /* infix syntax as default */
                    103: 
                    104: /* display flags */
                    105: int flagK, flagINV, flagPAREN, flagM, flagE, drgmode;
                    106: char dispstr[32];
                    107: 
                    108: 
                    109: /* stuff defining the keyboard layout.  The keypad is a 5x8 matrix of keys */
                    110: #define TINUMKEYS 40
                    111: #define HPNUMKEYS 39
                    112: 
                    113: struct _key {
                    114:            char   *st;
                    115:           int    code;
                    116:           int    (*fun)();
                    117:            Window wid;
                    118:            short  x,y,width,height;
                    119:            int    fore,back;
                    120:           void   (*func)();
                    121:             };
                    122: 
                    123: struct _key *key;
                    124:              
                    125: #define kRECIP 0
                    126: #define kSQR   1
                    127: #define kSQRT  2
                    128: #define kCLR   3
                    129: #define kOFF   4
                    130: #define kINV   5
                    131: #define kSIN   6
                    132: #define kCOS   7
                    133: #define kTAN   8
                    134: #define kDRG   9
                    135: #define kE     10
                    136: #define kEE    11
                    137: #define kLOG   12
                    138: #define kLN    13
                    139: #define kPOW   14
                    140: #define kPI    15
                    141: #define kFACT  16
                    142: #define kLPAR  17
                    143: #define kRPAR  18
                    144: #define kDIV   19
                    145: #define kSTO   20
                    146: #define kSEVEN 21
                    147: #define kEIGHT 22
                    148: #define kNINE  23
                    149: #define kMUL   24
                    150: #define kRCL   25
                    151: #define kFOUR  26
                    152: #define kFIVE  27
                    153: #define kSIX   28
                    154: #define kSUB   29
                    155: #define kSUM   30
                    156: #define kONE   31
                    157: #define kTWO   32
                    158: #define kTHREE 33
                    159: #define kADD   34
                    160: #define kEXC   35
                    161: #define kZERO  36
                    162: #define kDEC   37
                    163: #define kNEG   38
                    164: #define kEQU   39
                    165: #define kENTR  40
                    166: #define kXXY   41
                    167: #define kEXP   42
                    168: #define k10X   43
                    169: #define kROLL  44
                    170: #define kNOP   45
                    171: #define kBKSP  46
                    172: 
                    173: 
                    174: int  oneop(),twoop(),clearf(),offf(),invf(),drgf(),eef();
                    175: int  lparf(),rparf(),digit(),decf(),negf(),equf();
                    176: 
                    177: /* "1/x", "x^2", "SQRT","CE/C", "AC",
                    178:    "INV", "sin", "cos", "tan",  "DRG",
                    179:    "e",   "EE",  "log", "ln",   "y^x",
                    180:    "PI",  "x!",  "(",   ")",    "/",
                    181:    "STO", "7",   "8",   "9",    "*",
                    182:    "RCL", "4",   "5",   "6",    "-",
                    183:    "SUM", "1",   "2",   "3",    "+",
                    184:    "EXC", "0",   ".",   "+/-",  "="  */
                    185: 
                    186: struct _key tikeys[TINUMKEYS] = {
                    187:   {"1/x",kRECIP,oneop}, {"x^2",kSQR,oneop}, {"SQRT",kSQRT,oneop},
                    188:   {"CE/C",kCLR,clearf}, {"AC",kOFF,offf},
                    189:   {"INV",kINV,invf}, {"sin",kSIN,oneop}, {"cos",kCOS,oneop},
                    190:   {"tan",kTAN,oneop}, {"DRG",kDRG,drgf},
                    191:   {"e",kE,oneop}, {"EE",kEE,eef}, {"log",kLOG,oneop},
                    192:   {"ln",kLN,oneop},{"y^x",kPOW,twoop},
                    193:   {"PI",kPI,oneop},{"x!",kFACT,oneop},{"(",kLPAR,lparf},
                    194:   {")",kRPAR,rparf},{"/",kDIV,twoop},
                    195:   {"STO",kSTO,oneop},{"7",kSEVEN,digit},{"8",kEIGHT,digit},
                    196:   {"9",kNINE,digit},{"*",kMUL,twoop},
                    197:   {"RCL",kRCL,oneop},{"4",kFOUR,digit},{"5",kFIVE,digit},
                    198:   {"6",kSIX,digit},{"-",kSUB,twoop},
                    199:   {"SUM",kSUM,oneop},{"1",kONE,digit},{"2",kTWO,digit},
                    200:   {"3",kTHREE,digit},{"+",kADD,twoop},
                    201:   {"EXC",kEXC,oneop},{"0",kZERO,digit},{".",kDEC,decf},
                    202:   {"+/-",kNEG,negf},{"=",kEQU,equf}};
                    203: 
                    204: int  twof(),nop(),rollf(),bkspf(),entrf(),memf();
                    205: 
                    206: /*  { "SQRT","e^x", "10^x", "y^x", "1/x", "CHS", "7", "8", "9",  "/",
                    207:       "x!",  "PI",  "sin",  "cos", "tan", "EEX", "4", "5", "6",  "x",
                    208:       "",    "",    "R v",  "x:y", "<-",  "ENTR","1", "2", "3",  "-",
                    209:       "ON",  "DRG", "INV",  "STO", "RCL",        "0", ".", "SUM","+"  */
                    210: 
                    211: struct _key hpkeys[HPNUMKEYS] = {
                    212:   {"SQRT",kSQRT,oneop},{"e^x",kEXP,oneop},{"10^x",k10X,oneop},
                    213:   {"y^x",kPOW,twof},{"1/x",kRECIP,oneop},{"CHS",kNEG,negf},
                    214:   {"7",kSEVEN,digit},{"8",kEIGHT,digit},{"9",kNINE,digit},{"/",kDIV,twof},
                    215: 
                    216:   {"x!",kFACT,oneop},{"PI",kPI,oneop},{"sin",kSIN,oneop},{"cos",kCOS,oneop},
                    217:   {"tan",kTAN,oneop},{"EEX",kEE,eef},{"4",kFOUR,digit},{"5",kFIVE,digit},
                    218:   {"6",kSIX,digit},{"x",kMUL,twof},
                    219: 
                    220:   {"",kNOP,nop},{"",kNOP,nop},{"R v",kROLL,rollf},{"x:y",kXXY,twof},
                    221:   {"<-",kBKSP,bkspf},{"ENTR",kENTR,entrf},{"1",kONE,digit},{"2",kTWO,digit},
                    222:   {"3",kTHREE,digit},{"-",kSUB,twof},
                    223: 
                    224:   {"ON",kOFF,offf},{"DRG",kDRG,drgf},{"INV",kINV,invf},{"STO",kSTO,memf},
                    225:   {"RCL",kRCL,memf},{"0",kZERO,digit},{".",kDEC,decf},
                    226:   {"SUM",kSUM,memf},{"+",kADD,twof} };
                    227: 
                    228: 
                    229: /* checkerboard used in mono mode */
                    230: #define check_width 16
                    231: #define check_height 16
                    232: static char check_bits[] = {
                    233:    0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
                    234:    0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
                    235:    0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};
                    236: 
                    237: 
                    238: #ifndef IEEE
                    239:     jmp_buf env;
                    240: #endif
                    241: 
                    242: 
                    243: /**************/
                    244: main(argc, argv)
                    245:     int   argc;
                    246:     char *argv[];
                    247: /**************/
                    248: {
                    249:     int i, status,dpcs;
                    250:     char *strind;
                    251: #ifndef IEEE
                    252:     extern fperr();
                    253: #endif
                    254: 
                    255:     char *fc, *bc, *nfc, *nbc, *ofc, *obc, *ffc, *fbc, *dfc, *dbc, *ifc, *ibc;
                    256:     char *geom    = NULL;
                    257:     char *display = NULL;
                    258:     int rvflag    = 0;      /* don't use reverse video as a default */
                    259:     int stip      = 0;      /* don't stipple background by default */
                    260:     int analog   = 0;
                    261:     int invkey    = -1;
                    262: 
                    263:     XEvent     event;
                    264:     XGCValues  gcv;
                    265:     XWMHints   wmhints;
                    266:     Colormap   colors;
                    267:     XColor     xcsd, xced;
                    268:     int min_width, min_height;
                    269:     XSizeHints szhint;
                    270: 
                    271:     char *def;
                    272: 
                    273: 
                    274: 
                    275:     /*********************Defaults*********************/
                    276:     kfont=XGetDefault(dpy,argv[0],"KeyFont");
                    277:     if (!kfont) kfont = KFONT;    
                    278: 
                    279:     dfont=XGetDefault(dpy,argv[0],"DisplayFont");
                    280:     if (!dfont) dfont = DFONT;    
                    281: 
                    282:     ffont=XGetDefault(dpy,argv[0],"FlagFont");
                    283:     if (!ffont) ffont = FFONT;    
                    284: 
                    285:     if ((def=XGetDefault(dpy,argv[0],"BorderWidth"))!=NULL)
                    286:          border=atoi(def);
                    287: 
                    288:     if ((def=XGetDefault(dpy,argv[0],"ReverseVideo"))!=NULL)
                    289:          if (strcmp(def,"on")==0) rvflag=1;
                    290: 
                    291:     if ((def=XGetDefault(dpy,argv[0],"Stipple"))!=NULL)
                    292:          if (strcmp(def,"on")==0) stip=1;
                    293: 
                    294:     if ((def=XGetDefault(dpy,argv[0],"Mode"))!=NULL) {
                    295:          if (strcmp(def,"rpn")==0) rpn=1;
                    296:          else if (strcmp(def,"analog")==0) analog=1;
                    297:          }
                    298: 
                    299:     fc  = XGetDefault(dpy, argv[0], "Foreground");
                    300:     bc  = XGetDefault(dpy, argv[0], "Background");
                    301:     nfc = XGetDefault(dpy, argv[0], "NKeyFore");
                    302:     nbc = XGetDefault(dpy, argv[0], "NKeyBack");
                    303:     ofc = XGetDefault(dpy, argv[0], "OKeyFore");
                    304:     obc = XGetDefault(dpy, argv[0], "OKeyBack");
                    305:     ffc = XGetDefault(dpy, argv[0], "FKeyFore");
                    306:     fbc = XGetDefault(dpy, argv[0], "FKeyBack");
                    307:     dfc = XGetDefault(dpy, argv[0], "DispFore");
                    308:     dbc = XGetDefault(dpy, argv[0], "DispBack");
                    309:     ifc = XGetDefault(dpy, argv[0], "IconFore");
                    310:     ibc = XGetDefault(dpy, argv[0], "IconBack");
                    311: 
                    312:     /*********************Options*********************/
                    313: 
                    314:     for (i = 1; i < argc; i++) {
                    315: 
                    316:         if (argv[i][0] == '=') {
                    317:             geom = argv[i];
                    318:             continue;
                    319:             }
                    320: 
                    321:         strind = index(argv[i], ':');
                    322: 
                    323:         if(strind != NULL) {
                    324:             display = argv[i];
                    325:             continue;
                    326:             }
                    327: 
                    328:         if (strcmp(argv [i], "-bw") == 0) {
                    329:             if (++i >= argc) Syntax(argv[0]);
                    330:             border = atoi(argv [i]);
                    331:             continue;
                    332:             }
                    333: 
                    334:         if (strcmp(argv [i], "-stip") == 0) {
                    335:             stip=1;
                    336:             continue;
                    337:             }
                    338: 
                    339:         if (strcmp(argv [i], "-help") == 0) {
                    340:             Syntax(argv[0]);
                    341:             }
                    342: 
                    343:         if (strcmp(argv [i], "-rv") == 0) {
                    344:             rvflag++;
                    345:             continue;
                    346:             }
                    347: 
                    348:         if (strcmp(argv [i], "-rpn") == 0) {
                    349:             rpn++;
                    350:             continue;
                    351:             }
                    352: 
                    353:         if (strcmp(argv [i], "-analog") == 0) {
                    354:             analog++;
                    355:             continue;
                    356:             }
                    357: 
                    358:         Syntax(argv[0]);
                    359:     }
                    360: 
                    361: 
                    362:     /*****************************************************/
                    363: 
                    364:     /* Open up the display. */
                    365: 
                    366:     if ((dpy = XOpenDisplay(display)) == NULL) {
                    367:         fprintf(stderr, "%s: Can't open display '%s'\n",argv[0], display);
                    368:         exit(1);
                    369:         }
                    370: 
                    371:     /* Set up colors and pixmaps. */
                    372: 
                    373:     /* Set normal default colors */
                    374:     if (!rvflag) {
                    375:       ForeColor=BlackPixel(dpy, DefaultScreen(dpy));
                    376:       BackColor=WhitePixel(dpy, DefaultScreen(dpy));
                    377:     } else {
                    378:       BackColor=BlackPixel(dpy, DefaultScreen(dpy));
                    379:       ForeColor=WhitePixel(dpy, DefaultScreen(dpy));
                    380:     }
                    381: 
                    382:     dpcs=DisplayCells(dpy, DefaultScreen(dpy));
                    383:     if (dpcs<=2) stip=1;  /* monochrome display */
                    384: 
                    385:     colors = DefaultColormap(dpy, DefaultScreen(dpy));
                    386: 
                    387:     if (dpcs>2&&(fc !=NULL)&&XAllocNamedColor(dpy, colors, fc, &xcsd, &xced))
                    388:       ForeColor=xcsd.pixel;
                    389: 
                    390:     if (dpcs>2&&(bc !=NULL)&&XAllocNamedColor(dpy, colors, bc, &xcsd, &xced))
                    391:       BackColor=xcsd.pixel;
                    392: 
                    393:     NKeyFore = OKeyFore = FKeyFore = DispFore = IconFore = ForeColor;
                    394:     NKeyBack = OKeyBack = FKeyBack = DispBack = IconBack = BackColor;
                    395: 
                    396:     if (dpcs>2&&(nfc !=NULL)&&XAllocNamedColor(dpy, colors, nfc, &xcsd, &xced))
                    397:       NKeyFore=xcsd.pixel;
                    398: 
                    399:     if (dpcs>2&&(nbc !=NULL)&&XAllocNamedColor(dpy, colors, nbc, &xcsd, &xced))
                    400:       NKeyBack=xcsd.pixel;
                    401: 
                    402:     if (dpcs>2&&(ofc !=NULL)&&XAllocNamedColor(dpy, colors, ofc, &xcsd, &xced))
                    403:       OKeyFore=xcsd.pixel;
                    404: 
                    405:     if (dpcs>2&&(obc !=NULL)&&XAllocNamedColor(dpy, colors, obc, &xcsd, &xced))
                    406:       OKeyBack=xcsd.pixel;
                    407: 
                    408:     if (dpcs>2&&(ffc !=NULL)&&XAllocNamedColor(dpy, colors, ffc, &xcsd, &xced))
                    409:       FKeyFore=xcsd.pixel;
                    410: 
                    411:     if (dpcs>2&&(fbc !=NULL)&&XAllocNamedColor(dpy, colors, fbc, &xcsd, &xced))
                    412:       FKeyBack=xcsd.pixel;
                    413: 
                    414:     if (dpcs>2&&(dfc !=NULL)&&XAllocNamedColor(dpy, colors, dfc, &xcsd, &xced))
                    415:       DispFore=xcsd.pixel;
                    416: 
                    417:     if (dpcs>2&&(dbc !=NULL)&&XAllocNamedColor(dpy, colors, dbc, &xcsd, &xced))
                    418:       DispBack=xcsd.pixel;
                    419: 
                    420:     if (dpcs>2&&(ifc !=NULL)&&XAllocNamedColor(dpy, colors, ifc, &xcsd, &xced))
                    421:       IconFore=xcsd.pixel;
                    422: 
                    423:     if (dpcs>2&&(ibc !=NULL)&&XAllocNamedColor(dpy, colors, ibc, &xcsd, &xced))
                    424:       IconBack=xcsd.pixel;
                    425: 
                    426:     /* load fonts, figure out sizes of keypad and display */
                    427:     kfontinfo = XLoadQueryFont(dpy, kfont);
                    428:     if (!kfontinfo) kfontinfo = XLoadQueryFont(dpy, "fixed");
                    429:     if (!kfontinfo) XCalcError("Can't open '%s' or 'fixed' font\n",KFONT);
                    430:     keyfont = kfontinfo->fid;
                    431: 
                    432:     dfontinfo = XLoadQueryFont(dpy, dfont);
                    433:     if (!dfontinfo) dfontinfo = XLoadQueryFont(dpy, "fixed");
                    434:     if (!dfontinfo) XCalcError("Can't open '%s' or 'fixed' font\n",DFONT);
                    435:     dispfont = dfontinfo->fid;
                    436: 
                    437:     ffontinfo = XLoadQueryFont(dpy, ffont);
                    438:     if (!ffontinfo) ffontinfo = XLoadQueryFont(dpy, "fixed");
                    439:     if (!ffontinfo) XCalcError("Can't open '%s' or 'fixed' font\n",FFONT);
                    440:     flagfont = ffontinfo->fid;
                    441: 
                    442:     keywide = XTextWidth(kfontinfo, "MMM", 3) + KEYPADW;
                    443:     keyhigh = kfontinfo->ascent + KEYPADH + (rpn ? 2*EXTRAH : 0);
                    444: 
                    445:     dispwide  = (rpn ? 6 : 5)*keywide+4*PADDINGW;
                    446:     disphigh = dfontinfo->ascent + DISPPADH + FLAGH;
                    447: 
                    448:     /* Create Stipple pattern */
                    449:     stipplePix = XCreateBitmapFromData (dpy, DefaultRootWindow(dpy),
                    450:         check_bits, check_width, check_height);
                    451:        
                    452:     dimBorder        = stipplePix;
                    453: 
                    454:     /* Create Icon Pixmap */
                    455:     IconPix = XCreateBitmapFromData (dpy, DefaultRootWindow(dpy),
                    456:         icon_bits, icon_width, icon_height);
                    457: 
                    458:     if (analog)
                    459:       do_sr(argc, argv, geom, border);
                    460: 
                    461:     /* Open the main window. */
                    462: 
                    463:     if (rpn) {
                    464:        min_width  = 10*keywide + 11*PADDINGW + 2;
                    465:        min_height = disphigh + 4*keyhigh + 6*PADDINGH + 2;
                    466:     } else {
                    467:        min_width  = dispwide + 2*PADDINGW + 2;
                    468:        min_height = disphigh + 2 + 8*keyhigh + 10*PADDINGH + 10*EXTRAH;
                    469:     }
                    470: 
                    471:     theWindow = XCreateSimpleWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)),
                    472:                                    0, 0, min_width, min_height, border,
                    473:                                    ForeColor, BackColor);
                    474:     if (!theWindow) XCalcError("Can't open calculator window");
                    475: 
                    476:     if (stip)
                    477:       XSetWindowBackgroundPixmap(dpy, theWindow, stipplePix);
                    478: 
                    479:     szhint.flags = PSize|PMinSize;
                    480:     szhint.width = szhint.min_width = min_width;
                    481:     szhint.height = szhint.min_height = min_height;
                    482:     XSetStandardProperties(dpy, theWindow, "Calculator", NULL, IconPix,
                    483:                           argv, argc, &szhint);
                    484: 
                    485:     gcv.function = GXcopyInverted;
                    486:     gcv.foreground = DispFore;
                    487:     gcv.background = DispBack;
                    488:     gcv.font = dispfont;
                    489:     dispbgc = XCreateGC(dpy, theWindow,
                    490:                        GCForeground|GCBackground|GCFunction|GCFont, &gcv);
                    491:     gcv.function = GXcopy;
                    492:     dispfgc = XCreateGC(dpy, theWindow,
                    493:                        GCForeground|GCBackground|GCFunction|GCFont, &gcv);
                    494:     gcv.font = flagfont;
                    495:     flaggc = XCreateGC(dpy, theWindow,
                    496:                        GCForeground|GCBackground|GCFunction|GCFont, &gcv);
                    497:     gcv.function = GXcopy;
                    498:     gcv.foreground = NKeyFore;
                    499:     gcv.background = NKeyBack;
                    500:     gcv.font = keyfont;
                    501:     keygc = XCreateGC(dpy, theWindow,
                    502:                      GCForeground|GCBackground|GCFunction|GCFont, &gcv);
                    503:     gcv.function = GXinvert;
                    504:     keyigc = XCreateGC(dpy, theWindow, GCFunction, &gcv);
                    505:                        
                    506: 
                    507:     if (rpn)
                    508:       SetupHPCalc();
                    509:     else
                    510:       SetupTICalc();
                    511: 
                    512:     ResetCalc();
                    513: 
                    514:     XSelectInput(dpy, theWindow, ExposureMask|KeyPressMask|EnterWindowMask|
                    515:                                 LeaveWindowMask);
                    516:     XSelectInput(dpy, dispwid,   ExposureMask|EnterWindowMask|LeaveWindowMask);
                    517: 
                    518:     for (i=0; i<numkeys; i++)
                    519:         XSelectInput(dpy,key[i].wid,ExposureMask|ButtonPressMask|
                    520:                          ButtonReleaseMask|EnterWindowMask|LeaveWindowMask);
                    521:     XMapWindow    (dpy, theWindow);
                    522:     XMapSubwindows(dpy, theWindow);
                    523:     arrow=XCreateFontCursor(dpy, XC_hand2);
                    524:     XDefineCursor(dpy, theWindow,arrow);
                    525: 
                    526:     /*********** Set up SIGFPE hander ***********/
                    527: #ifndef IEEE
                    528:     signal(SIGFPE,fperr);
                    529: #endif
                    530: 
                    531:     /**************** Main loop *****************/
                    532: 
                    533:     while (1) {
                    534:         Window wind;
                    535: 
                    536:         XNextEvent(dpy, &event);
                    537: 
                    538:         switch (event.type) {
                    539: 
                    540:         case Expose: {
                    541:             XExposeEvent *exp_event = (XExposeEvent *) &event;
                    542:             wind = exp_event->window;
                    543: 
                    544:            if (wind==theWindow) XClearArea(dpy,theWindow,exp_event->x,
                    545:                                            exp_event->y,exp_event->width,
                    546:                                            exp_event->height,False);
                    547:            else if (wind==dispwid) DrawDisplay();
                    548:             else if (wind==iconWindow)
                    549:              ;
                    550:             else {
                    551:                 for (i=0; i<numkeys; i++) {
                    552:                    if (key[i].wid==wind) DrawKey(i);
                    553:                    }
                    554:                 }
                    555:             }
                    556:             break;
                    557: 
                    558:         case ButtonPress: {
                    559:             XButtonPressedEvent *but_event = (XButtonPressedEvent *) &event;
                    560:             wind = but_event->window;
                    561:             if ((but_event->button & 0xff) == Button1) {
                    562:                 for (i=0; i<numkeys; i++) {
                    563:                    if (key[i].wid==wind) { InvertKey(i); invkey=i; }
                    564:                    }
                    565:                 }
                    566: 
                    567:             else if ((but_event->button & 0xff) == Button3) {
                    568:              for (i=0; i<numkeys; i++) {
                    569:                if (key[i].wid==wind && key[i].code==kOFF)
                    570:                  Quit();
                    571:              }
                    572:            }
                    573:            else XBell(dpy, 0);
                    574:            }
                    575:             break;
                    576:                        
                    577:         case ButtonRelease: {
                    578:             XButtonReleasedEvent *but_event = (XButtonReleasedEvent *) &event;
                    579:             wind = but_event->window;
                    580:             if ((but_event->button & 0xff) == Button1) {
                    581:                 for (i=0; i<numkeys; i++) {
                    582:                    if (key[i].wid==wind) LetGoKey(invkey);
                    583:                    }
                    584:                 invkey = -1;
                    585:                 }
                    586:             }
                    587:             break;
                    588: 
                    589:         case KeyPress: {
                    590:             XKeyPressedEvent *key_event = (XKeyPressedEvent *) &event;
                    591:            char *st, keybuf[10];
                    592:             wind = key_event->window;
                    593:             if (wind==theWindow) {
                    594:              i = XLookupString(key_event, keybuf, sizeof(keybuf), NULL, NULL);
                    595:              for (st = keybuf; i > 0; i--)
                    596:                TypeChar(*st++);
                    597:            } else 
                    598:              printf("KeyPressed in window %ld\n",wind);
                    599:            }
                    600:            break;
                    601: 
                    602:        case EnterNotify:
                    603:        case LeaveNotify: {
                    604:            XCrossingEvent *cross_event = (XCrossingEvent *) &event;
                    605: 
                    606:            if ((cross_event->detail != NotifyInferior) &&
                    607:                (cross_event->window == theWindow) &&
                    608:                (cross_event->mode == NotifyNormal) &&
                    609:                cross_event->focus) {
                    610:                if (event.type == EnterNotify)
                    611:                    XSetWindowBorder(dpy,theWindow,ForeColor);
                    612:                else
                    613:                    XSetWindowBorderPixmap(dpy,theWindow,dimBorder);
                    614:            }
                    615:             break;
                    616:          }
                    617:         default:
                    618:            printf("event type=%ld\n",event.type); 
                    619:            XCalcError("Unexpected X_Event");
                    620: 
                    621:         }  /* end of switch */
                    622:     }  /* end main loop */}
                    623: 
                    624: 
                    625: 
                    626: /***********************************/
                    627: Syntax(call)
                    628:  char *call;
                    629: {
                    630:     printf ("Usage: %s [-bw <pixels>] [-stip] [-help] [-rv] [-rpn] [-analog]\n", call);
                    631:     printf ("          [[<host>]:[<vs>]] [=geometry]\n\n");
                    632:     printf ("Default: %s -bw %d =156x226-16-16\n\n",call, DEF_BDRWIDE);
                    633:     exit(0);
                    634: }
                    635: 
                    636: 
                    637: /***********************************/
                    638: XCalcError(identifier,arg1,arg2,arg3,arg4)
                    639:        char *identifier,*arg1,*arg2,*arg3,*arg4;
                    640: {
                    641:     fprintf(stderr, identifier, arg1,arg2,arg3,arg4);
                    642:     exit(1);
                    643: }
                    644: 
                    645: 
                    646: 
                    647: /***********************************/
                    648: SetupTICalc()
                    649: {
                    650:     int i;
                    651: 
                    652:     numkeys=TINUMKEYS;
                    653:     key = &tikeys[0];
                    654: 
                    655:     for (i=0; i<numkeys; i++) {
                    656:         key[i].x = PADDINGW+(i%5)*(keywide+PADDINGW);
                    657:         key[i].y = disphigh+2+2*PADDINGH+(i/5)*(keyhigh+PADDINGH);
                    658:         key[i].width = keywide;
                    659:         key[i].height = keyhigh;
                    660:         if (i>=15) {
                    661:             key[i].height+=(2*EXTRAH);
                    662:             key[i].y     += ((i-15)/5)*EXTRAH*2;
                    663:             }
                    664: 
                    665:         switch (tikeys[i].code) {
                    666:             case kZERO:  case kONE:  case kTWO:  case kTHREE:
                    667:             case kFOUR:  case kFIVE: case kSIX:  case kSEVEN:
                    668:             case kEIGHT: case kNINE: case kDEC:  case kNEG:
                    669:                 key[i].fore=NKeyFore;
                    670:                 key[i].back=NKeyBack;
                    671:                 break;
                    672:             case kADD:   case kSUB:  case kMUL:  case kDIV:  case kEQU:
                    673:                 key[i].fore=OKeyFore;
                    674:                 key[i].back=OKeyBack;
                    675:                 break;
                    676:             default:
                    677:                 key[i].fore=FKeyFore;
                    678:                 key[i].back=FKeyBack;
                    679:             }
                    680:        key[i].wid=XCreateSimpleWindow(dpy,theWindow,key[i].x,key[i].y,
                    681:                                       key[i].width,key[i].height,1,
                    682:                                       key[i].fore,key[i].back);
                    683:         }
                    684: 
                    685:     dispwid = XCreateSimpleWindow(dpy,theWindow,PADDINGW,PADDINGH,
                    686:                                  dispwide-2,disphigh,2,DispFore,DispBack);
                    687: }
                    688: 
                    689: SetupHPCalc()
                    690: {
                    691:     int i,j;
                    692: 
                    693:     numkeys=HPNUMKEYS;
                    694:     key = &hpkeys[0];
                    695: 
                    696:     for (i=0; i<numkeys; i++) {
                    697:         j = (i<35)? i : i + 1;
                    698:         key[i].x = PADDINGW+(j%10)*(keywide+PADDINGW);
                    699:         key[i].y = disphigh+2+2*PADDINGH+(j/10)*(keyhigh+PADDINGH);
                    700:         key[i].width = keywide;
                    701:         key[i].height = keyhigh;
                    702:         if (i==25) {
                    703:             key[i].height = keyhigh*2 + PADDINGH;
                    704:             }
                    705: 
                    706:         switch (hpkeys[i].code) {
                    707:             case kZERO:  case kONE:  case kTWO:  case kTHREE:
                    708:             case kFOUR:  case kFIVE: case kSIX:  case kSEVEN:
                    709:             case kEIGHT: case kNINE: case kDEC:  case kNEG:
                    710:            case kBKSP: case kEE:
                    711:                 key[i].fore=NKeyFore;
                    712:                 key[i].back=NKeyBack;
                    713:                 break;
                    714:             case kADD:   case kSUB:  case kMUL:  case kDIV:  case kENTR:
                    715:                 key[i].fore=OKeyFore;
                    716:                 key[i].back=OKeyBack;
                    717:                 break;
                    718:             default:
                    719:                 key[i].fore=FKeyFore;
                    720:                 key[i].back=FKeyBack;
                    721:             }
                    722:        key[i].wid=XCreateSimpleWindow(dpy,theWindow,key[i].x,key[i].y,
                    723:                                       key[i].width,key[i].height,1,
                    724:                                       key[i].fore,key[i].back);
                    725:         }
                    726:     dispwid = XCreateSimpleWindow(dpy,theWindow,PADDINGW+keywide,PADDINGH,
                    727:                                  dispwide-2,disphigh,2,DispFore,DispBack);
                    728: }
                    729: 
                    730: 
                    731: /**************/
                    732: DrawDisplay()
                    733: {
                    734:     int strwide;
                    735: 
                    736:     if (strlen(dispstr)>12) {       /* strip out some decimal digits */
                    737:         char tmp[32];
                    738:         char *exp = index(dispstr,'e');  /* search for exponent part */
                    739:         if (!exp) dispstr[12]='\0';      /* no exp, just trunc. */
                    740:         else {
                    741:             if (strlen(exp)<=4) 
                    742:                 sprintf(tmp,"%.8s",dispstr); /* leftmost 8 chars */
                    743:             else
                    744:                 sprintf(tmp,"%.7s",dispstr); /* leftmost 7 chars */
                    745:             strcat (tmp,exp);            /* plus exponent */
                    746:             strcpy (dispstr,tmp);
                    747:             }
                    748:         }
                    749: 
                    750:     strwide=XTextWidth(dfontinfo,dispstr,strlen(dispstr));
                    751: 
                    752:     XFillRectangle(dpy,dispwid,dispfgc,0,0,10,disphigh);
                    753:     XFillRectangle(dpy,dispwid,dispfgc,dispwide-10,0,dispwide,disphigh);
                    754:     XFillRectangle(dpy,dispwid,dispbgc,10,0,dispwide-20,disphigh);
                    755: 
                    756:     XDrawString(dpy,dispwid,dispfgc,dispwide-10-DISPPADW/2-strwide,
                    757:                DISPPADH/2+dfontinfo->ascent,dispstr,strlen(dispstr));
                    758: 
                    759:     if (flagM)                XDrawString(dpy,dispwid,flaggc,12,10,"M",1);
                    760:     if (flagE)                XDrawString(dpy,dispwid,flaggc,12,20,"E",1);
                    761:     if (flagK)         XDrawString(dpy,dispwid,flaggc,20,disphigh-2,"K",1);
                    762:     if (flagINV)       XDrawString(dpy,dispwid,flaggc,30,disphigh-2,"INV",3);
                    763:     if (drgmode==DEG)  XDrawString(dpy,dispwid,flaggc,60,disphigh-2,"DEG",3);
                    764:     if (drgmode==RAD)  XDrawString(dpy,dispwid,flaggc,80,disphigh-2,"RAD",3);
                    765:     if (drgmode==GRAD) XDrawString(dpy,dispwid,flaggc,100,disphigh-2,"GRAD",4);
                    766:     if (flagPAREN)     XDrawString(dpy,dispwid,flaggc,130,disphigh-2,"( )",3);
                    767: }
                    768: 
                    769: 
                    770: /***************/
                    771: DrawKey(keynum)
                    772:     int keynum;
                    773: {
                    774:     char *str;
                    775:     int strwide,extrapad;
                    776:     struct _key *kp;
                    777: 
                    778:     kp = &key[keynum];
                    779:     str = kp->st;
                    780:     strwide = XTextWidth(kfontinfo,str,strlen(str));
                    781: 
                    782:     extrapad = (keynum>=15 || rpn) ? EXTRAH : 0;
                    783:     if (rpn && kp->code == kENTR)
                    784:       extrapad = keyhigh;
                    785: 
                    786:     XDrawString(dpy,kp->wid,keygc,(kp->width-strwide)/2,
                    787:                KEYPADH/2+extrapad+kfontinfo->ascent,str,strlen(str));
                    788: }
                    789: 
                    790: 
                    791: /*********************************/
                    792: InvertKey(keynum)
                    793:     int keynum;
                    794: {
                    795:     struct _key *kp;
                    796: 
                    797:     kp = &key[keynum];
                    798:     
                    799:     XFillRectangle(dpy, kp->wid, keyigc, 0, 0, kp->width, kp->height);
                    800: }
                    801: 
                    802: 
                    803: /* This section is all of the state machine that implements the calculator
                    804:  * functions.  Much of it is shared between the infix and rpn modes.
                    805:  */
                    806: 
                    807: static double drg2rad=PI/180.0;  /* Conversion factors for trig funcs */
                    808: static double rad2drg=180.0/PI;
                    809: static int entered=1;  /* true if display contains a valid number.
                    810:                           if==2, then use 'dnum', rather than the string
                    811:                           stored in the display.  (for accuracy) 
                    812:                           if==3, then error occurred, only CLR & AC work */
                    813: static int clear  =0;  /* CLR clears display.  if 1, clears acc, also */
                    814: static int off    =0;  /* once clears mem, twice quits */
                    815: static int decimal=0;  /* to prevent using decimal pt twice in a # */
                    816: static int clrdisp=1;  /* if true clears display before entering # */
                    817: static int accset =0;
                    818: static int lastop =kCLR;
                    819: static int memop  =kCLR;
                    820: static int exponent=0;
                    821: static double acc =0.0;
                    822: static double dnum=0.0;
                    823: static double mem[10] = { 0.0 };
                    824: 
                    825: /*********************************/
                    826: LetGoKey(keynum)
                    827:      int keynum;
                    828: {
                    829:     int i;
                    830:     int code;
                    831: 
                    832:     if (keynum==-1) return;
                    833:  
                    834:     errno = 0;                 /* for non-IEEE machines */
                    835: 
                    836:     InvertKey(keynum);
                    837: 
                    838:     if ( (entered==3) && !(key[keynum].code==kCLR || key[keynum].code==kOFF)) {
                    839:       if (rpn) {
                    840:        clrdisp++;
                    841:       } else {
                    842:         XBell(dpy, 0);
                    843:         return;
                    844:       }
                    845:     }
                    846: 
                    847:     code = key[keynum].code;
                    848:     if (code != kCLR) clear=0;
                    849:     if (code != kOFF) off=0;
                    850: 
                    851: 
                    852: #ifndef IEEE
                    853:     i=setjmp(env);
                    854:     if (i) {
                    855:         switch (i) {
                    856: #ifdef FPE_FLTDIV_TRAP
                    857:            case FPE_FLTDIV_TRAP:  strcpy(dispstr,"div by zero"); break;
                    858: #endif
                    859: #ifdef FPE_FLTDIV_FAULT
                    860:            case FPE_FLTDIV_FAULT: strcpy(dispstr,"div by zero"); break;
                    861: #endif
                    862: #ifdef FPE_FLTOVF_TRAP
                    863:            case FPE_FLTOVF_TRAP:  strcpy(dispstr,"overflow"); break;
                    864: #endif
                    865: #ifdef FPE_FLTOVF_FAULT
                    866:            case FPE_FLTOVF_FAULT: strcpy(dispstr,"overflow"); break;
                    867: #endif
                    868: #ifdef FPE_FLTUND_TRAP
                    869:            case FPE_FLTUND_TRAP:  strcpy(dispstr,"underflow"); break;
                    870: #endif
                    871: #ifdef FPE_FLTUND_FAULT
                    872:            case FPE_FLTUND_FAULT: strcpy(dispstr,"underflow"); break;
                    873: #endif
                    874:            default:               strcpy(dispstr,"error");
                    875:            }
                    876:         entered=3;
                    877:         DrawDisplay();
                    878:         return;
                    879:         }
                    880: #endif
                    881: 
                    882:     (key[keynum].fun)(keynum);
                    883:     memop = code;
                    884: 
                    885: #ifndef IEEE
                    886:     if (errno) {
                    887:         strcpy(dispstr,"error");
                    888:         DrawDisplay();
                    889:         entered=3;
                    890:         errno=0;
                    891:         }
                    892: #endif
                    893: }
                    894: 
                    895: 
                    896: digit(keynum)
                    897:      int keynum;
                    898: {
                    899:   flagINV=0;
                    900:   if (rpn && (memop == kSTO || memop == kRCL || memop == kSUM)) {
                    901:       switch (memop) {
                    902:       case kSTO: mem[*(key[keynum].st) - '0'] = dnum; break;
                    903:       case kRCL: dnum = mem[*(key[keynum].st) - '0'];
                    904:                 sprintf(dispstr, "%.8g", dnum);
                    905:                 break;
                    906:       case kSUM: mem[*(key[keynum].st) - '0'] += dnum; break;
                    907:       }
                    908:       DrawDisplay();
                    909:       entered = 2;
                    910:       clrdisp++;
                    911:       return;
                    912:   }
                    913:   if (clrdisp) {
                    914:     dispstr[0]='\0';
                    915:     exponent=decimal=0;
                    916:     if (rpn && entered==2)
                    917:       PushNum(dnum);
                    918:   }
                    919:   if (strlen(dispstr)>=MAXDISP)
                    920:     return;
                    921:   strcat(dispstr,key[keynum].st);
                    922:   DrawDisplay();
                    923:   if (clrdisp && key[keynum].code != kZERO)
                    924:     clrdisp=0; /*no leading 0s*/
                    925:   entered=1;
                    926: }
                    927: 
                    928: bkspf()
                    929: {
                    930:   if (entered!=1 || clrdisp)
                    931:     return;
                    932:   if (strlen(dispstr) > 0)
                    933:     dispstr[strlen(dispstr)-1] = 0;
                    934:   if (strlen(dispstr) == 0) {
                    935:     strcat(dispstr, "0");
                    936:     clrdisp++;
                    937:   }
                    938:   DrawDisplay();
                    939: }
                    940: 
                    941: decf()
                    942: {
                    943:   flagINV=0;
                    944:   if (clrdisp) {
                    945:       if (rpn)
                    946:        PushNum(dnum);
                    947:       strcpy(dispstr,"0");
                    948:   }
                    949:   if (!decimal) {
                    950:     strcat(dispstr,".");
                    951:     DrawDisplay();
                    952:     decimal++;
                    953:   }
                    954:   clrdisp=0;
                    955:   entered=1;
                    956: }
                    957: 
                    958: eef()
                    959: {
                    960:   flagINV=0;
                    961:   if (clrdisp) {
                    962:       if (rpn)
                    963:        PushNum(dnum);
                    964:       strcpy(dispstr, rpn ? "1" : "0");
                    965:   }
                    966:   if (!exponent) {
                    967:     strcat(dispstr,"E+");
                    968:     DrawDisplay();
                    969:     exponent=strlen(dispstr)-1;  /* where the '-' goes */
                    970:   }
                    971:   clrdisp=0;
                    972:   entered=1;
                    973: }
                    974: 
                    975: clearf()
                    976: {
                    977:   flagINV=0;
                    978:   if (clear && !rpn) { /* clear all */
                    979:     ClearStacks();
                    980:     flagPAREN=0;
                    981:   }
                    982:   clear++;
                    983:   exponent=decimal=0;
                    984:   clrdisp=1;
                    985:   entered=1;
                    986:   strcpy(dispstr,"0");
                    987:   DrawDisplay();
                    988: }
                    989: 
                    990: negf()
                    991: {
                    992:   flagINV=0;
                    993:   if (exponent) {       /* neg the exponent */
                    994:     if (dispstr[exponent]=='-')
                    995:       dispstr[exponent]='+';
                    996:     else
                    997:       dispstr[exponent]='-';
                    998:     DrawDisplay();
                    999:     return;
                   1000:   }
                   1001: 
                   1002:   if (strcmp("0",dispstr)==0)
                   1003:     return;                    /* don't neg a zero */
                   1004:   if (dispstr[0]=='-')         /* already neg-ed */
                   1005:     strcpy(dispstr,dispstr+1);  /* move str left once */
                   1006:   else {                       /* not neg-ed.  add a '-' */
                   1007:     char tmp[32];
                   1008:     sprintf(tmp,"-%s",dispstr);
                   1009:     strcpy(dispstr,tmp);
                   1010:   }
                   1011:   if (entered==2)
                   1012:     dnum = -1.0 * dnum;
                   1013:   DrawDisplay();
                   1014: }
                   1015: 
                   1016: /* Two operand functions for infix calc */
                   1017: twoop(keynum)
                   1018: {
                   1019:   double PopNum();
                   1020: 
                   1021:   if (flagINV) {
                   1022:     flagINV=0;
                   1023:     DrawDisplay();
                   1024:   }
                   1025: 
                   1026:   if (!entered) {              /* something like "5+*" */
                   1027:     if (!isopempty())
                   1028:       PopOp();                 /* replace the prev op */
                   1029:     PushOp(key[keynum].code);  /* with the new one */
                   1030:     return;
                   1031:   }
                   1032:   
                   1033:   if (entered==1)
                   1034:     sscanf(dispstr,"%lf",&dnum);
                   1035: 
                   1036:   clrdisp=clear=1;
                   1037:   entered=decimal=exponent=0;
                   1038: 
                   1039:   if (!isopempty()) {  /* there was a previous op */
                   1040:     lastop=PopOp();   /* get it */
                   1041: 
                   1042:     if (lastop==kLPAR) {  /* put it back */
                   1043:       PushOp(kLPAR);
                   1044:       PushOp(key[keynum].code);
                   1045:       PushNum(dnum);
                   1046:       return;
                   1047:     }
                   1048: 
                   1049:     /* now, if the current op (keynum) is of
                   1050:        higher priority than the lastop, the current
                   1051:        op and number are just pushed on top 
                   1052:        Priorities:  (Y^X) > *,/ > +,- */
                   1053:     
                   1054:     if (priority(key[keynum].code) > priority(lastop)) {
                   1055:       PushNum(dnum);
                   1056:       PushOp(lastop);
                   1057:       PushOp(key[keynum].code);
                   1058:     } else {  /* execute lastop on lastnum and dnum, push
                   1059:               result and current op on stack */
                   1060:       acc=PopNum();
                   1061:       switch (lastop) { /* perform the operation */
                   1062:       case kADD: acc += dnum;  break;
                   1063:       case kSUB: acc -= dnum;  break;
                   1064:       case kMUL: acc *= dnum;  break;
                   1065:       case kDIV: acc /= dnum;  break;
                   1066:       case kPOW: acc =  pow(acc,dnum);  break;
                   1067:        }
                   1068:       PushNum(acc);
                   1069:       PushOp(key[keynum].code);
                   1070:       sprintf(dispstr,"%.8g",acc);
                   1071:       DrawDisplay();
                   1072:       dnum=acc;
                   1073:     }
                   1074:   }
                   1075:   else { /* op stack is empty, push op and num */
                   1076:     PushOp(key[keynum].code);
                   1077:     PushNum(dnum);
                   1078:   } 
                   1079: }                      
                   1080: 
                   1081: /* Two operand functions for rpn calc */
                   1082: twof(keynum)
                   1083: {
                   1084:   double PopNum();
                   1085: 
                   1086:   if (flagINV) {
                   1087:     flagINV=0;
                   1088:     DrawDisplay();
                   1089:   }
                   1090:   if (!entered)
                   1091:     return;
                   1092:   if (entered==1)
                   1093:     sscanf(dispstr, "%lf", &dnum);
                   1094:   acc = PopNum();
                   1095:   switch(key[keynum].code) {
                   1096:   case kADD: acc += dnum;  break;
                   1097:   case kSUB: acc -= dnum;  break;
                   1098:   case kMUL: acc *= dnum;  break;
                   1099:   case kDIV: acc /= dnum;  break;
                   1100:   case kPOW: acc =  pow(acc,dnum);  break;
                   1101:   case kXXY: PushNum(dnum);
                   1102:   }
                   1103:   sprintf(dispstr, "%.8g", acc);
                   1104:   DrawDisplay();
                   1105:   clrdisp++;
                   1106:   decimal = exponent = 0;
                   1107:   entered = 2;
                   1108:   dnum = acc;
                   1109: }
                   1110: 
                   1111: 
                   1112: entrf()
                   1113: {
                   1114:   flagINV=0;
                   1115:   if (!entered)
                   1116:     return;
                   1117: 
                   1118:   clrdisp=clear=1;
                   1119:   decimal=exponent=0;
                   1120: 
                   1121:   if (entered==1)
                   1122:     sscanf(dispstr,"%lf",&dnum);
                   1123:   entered=2;
                   1124: 
                   1125:   if (entered==2)
                   1126:     PushNum(dnum);
                   1127: }
                   1128: 
                   1129: equf()
                   1130: {
                   1131:   double PopNum();
                   1132: 
                   1133:   flagINV=0;
                   1134:   if (!entered)
                   1135:     return;
                   1136: 
                   1137:   clrdisp=clear=1;
                   1138:   decimal=exponent=0;
                   1139: 
                   1140:   if (entered==1)
                   1141:     sscanf(dispstr,"%lf",&dnum);
                   1142:   entered=2;
                   1143: 
                   1144:   PushNum(dnum);
                   1145: 
                   1146:   while (!isopempty()) {  /* do all pending ops */
                   1147:     dnum=PopNum();
                   1148:     acc=PopNum();
                   1149:     lastop=PopOp();
                   1150:     switch (lastop) {
                   1151:     case kADD:  acc += dnum;
                   1152:                break;
                   1153:     case kSUB:  acc -= dnum;
                   1154:                break;
                   1155:     case kMUL:  acc *= dnum;
                   1156:                break;
                   1157:     case kDIV:  acc /= dnum;
                   1158:                break;
                   1159:     case kPOW:  acc = pow(acc,dnum);
                   1160:                break;
                   1161:     case kLPAR:        flagPAREN--;
                   1162:                PushNum(acc);
                   1163:                break;
                   1164:     }
                   1165:     dnum=acc;
                   1166:     PushNum(dnum);
                   1167:   }
                   1168: 
                   1169:   sprintf(dispstr,"%.8g",dnum);
                   1170:   DrawDisplay();
                   1171: }
                   1172:         
                   1173: lparf()
                   1174: {
                   1175:   flagINV=0;
                   1176:   PushOp(kLPAR);
                   1177:   flagPAREN++;
                   1178:   DrawDisplay();
                   1179: }
                   1180: 
                   1181: rollf()
                   1182: {
                   1183:   double PopNum();
                   1184: 
                   1185:   if (!entered)
                   1186:     return;
                   1187:   if (entered==1)
                   1188:     sscanf(dispstr, "%lf", &dnum);
                   1189:   entered = 2;
                   1190:   RollNum(flagINV);
                   1191:   flagINV=0;
                   1192:   clrdisp++;
                   1193:   sprintf(dispstr, "%.8g", dnum);
                   1194:   DrawDisplay();
                   1195: }
                   1196: 
                   1197: rparf()
                   1198: {
                   1199:   double PopNum();
                   1200: 
                   1201:   flagINV=0;
                   1202:   if (!entered)
                   1203:     return;
                   1204: 
                   1205:   if (!flagPAREN)
                   1206:     return;
                   1207:   
                   1208:   clrdisp++;
                   1209:   decimal=exponent=0;
                   1210: 
                   1211:   if (entered==1)
                   1212:     sscanf(dispstr,"%lf",&dnum);
                   1213:   entered=2;
                   1214: 
                   1215:   PushNum(dnum);
                   1216:   while (!isopempty() && (lastop=PopOp())!=kLPAR) {
                   1217:     /* do all pending ops, back to left paren */
                   1218:     dnum=PopNum();
                   1219:     acc=PopNum();
                   1220:     switch (lastop) {
                   1221:     case kADD:  acc += dnum;
                   1222:                break;
                   1223:     case kSUB:  acc -= dnum;
                   1224:                break;
                   1225:     case kMUL:  acc *= dnum;
                   1226:                break;
                   1227:     case kDIV:  acc /= dnum;
                   1228:                break;
                   1229:     case kPOW:  acc = pow(acc,dnum);
                   1230:                break;
                   1231:     }
                   1232:     dnum=acc;
                   1233:     PushNum(dnum);
                   1234:   }
                   1235:   PopNum();
                   1236:   flagPAREN--;
                   1237:   entered=2;
                   1238:   sprintf(dispstr,"%.8g",dnum);
                   1239:   DrawDisplay();
                   1240: }
                   1241: 
                   1242: drgf()
                   1243: {
                   1244:   if (flagINV) {
                   1245:     if (entered==1)
                   1246:       sscanf(dispstr,"%lf",&dnum);
                   1247:     switch (drgmode) {
                   1248:     case DEG:  dnum=dnum*PI/180.0;    break;
                   1249:     case RAD:  dnum=dnum*200.0/PI;    break;
                   1250:     case GRAD: dnum=dnum*90.0/100.0;  break;
                   1251:     }
                   1252:     entered=2;
                   1253:     clrdisp=1;
                   1254:     flagINV=0;
                   1255:     sprintf(dispstr,"%.8g",dnum);
                   1256:   }
                   1257:                          
                   1258:   flagINV=0;
                   1259:   drgmode = ++drgmode % 3;
                   1260:   switch (drgmode) {
                   1261:   case DEG:  drg2rad=PI / 180.0;
                   1262:             rad2drg=180.0 / PI;
                   1263:             break;
                   1264:   case RAD:  drg2rad=1.0;
                   1265:             rad2drg=1.0;
                   1266:             break;
                   1267:   case GRAD: drg2rad=PI / 200.0;
                   1268:             rad2drg=200.0 / PI;
                   1269:             break;
                   1270:   }
                   1271:   DrawDisplay();
                   1272: }
                   1273: 
                   1274: invf()
                   1275: {
                   1276:   flagINV = ~flagINV;
                   1277:   DrawDisplay();
                   1278: }
                   1279: 
                   1280: memf(keynum)
                   1281: {
                   1282:     if (entered==1)
                   1283:       sscanf(dispstr,"%lf",&dnum);
                   1284:     entered = 2;
                   1285:     clrdisp++;
                   1286: }
                   1287: 
                   1288: oneop(keynum)
                   1289: {
                   1290:   int i,j;
                   1291:   double dtmp;
                   1292: 
                   1293:   if (entered==1)
                   1294:     sscanf(dispstr,"%lf",&dnum);
                   1295:   entered = 2;
                   1296: 
                   1297:   switch (key[keynum].code) {  /* do the actual math fn. */
                   1298:   case kE:     if (rpn && memop != kENTR) PushNum(dnum); dnum=E;  break;
                   1299:   case kPI:    if (rpn && memop != kENTR) PushNum(dnum); dnum=PI;  break;
                   1300:   case kRECIP: dnum=1.0/dnum;  break;
                   1301:   case kSQR:   flagINV = !flagINV; /* fall through to */
                   1302:   case kSQRT:  if (flagINV) dnum=dnum*dnum;
                   1303:               else dnum=sqrt(dnum);
                   1304:               break;
                   1305:   case k10X:   flagINV = !flagINV; /* fall through to */
                   1306:   case kLOG:   if (flagINV) dnum=pow(10.0,dnum);
                   1307:               else dnum=log10(dnum);
                   1308:               break;
                   1309:   case kEXP:   flagINV = !flagINV; /* fall through to */
                   1310:   case kLN:    if (flagINV) dnum=exp(dnum);
                   1311:               else dnum=log(dnum);
                   1312:               break;
                   1313:   case kSIN:   if (flagINV) dnum=asin(dnum)*rad2drg;
                   1314:               else dnum=sin(dnum*drg2rad);
                   1315:               break;
                   1316:   case kCOS:   if (flagINV) dnum=acos(dnum)*rad2drg;
                   1317:               else dnum=cos(dnum*drg2rad);
                   1318:               break;
                   1319:   case kTAN:   if (flagINV) dnum=atan(dnum)*rad2drg;
                   1320:               else dnum=tan(dnum*drg2rad);
                   1321:               break;
                   1322:   case kSTO:   mem[0]=dnum;  flagM=!(mem[0]==0.0);  break;
                   1323:   case kRCL:   dnum=mem[0];  flagM=!(mem[0]==0.0);  break;
                   1324:   case kSUM:   mem[0]+=dnum; flagM=!(mem[0]==0.0);  break;
                   1325:   case kEXC:   dtmp=dnum; dnum=mem[0];  mem[0]=dtmp;
                   1326:               flagM=!(mem[0]==0.0);  break;
                   1327:   case kFACT:  if (floor(dnum)!=dnum || dnum<0.0 || dnum>500.0) {
                   1328:                 strcpy(dispstr,"error");
                   1329:                 entered=3;
                   1330:                 break;
                   1331:               }
                   1332:               i=(int) (floor(dnum));
                   1333:               for (j=1,dnum=1.0; j<=i; j++) 
                   1334:                 dnum*=(float) j;
                   1335:               break;
                   1336:   }
                   1337:   
                   1338:   if (entered==3) {  /* error */
                   1339:     DrawDisplay();
                   1340:     return;
                   1341:   }
                   1342: 
                   1343:   entered=2;
                   1344:   clrdisp=1;
                   1345:   flagINV=0;
                   1346:   sprintf(dispstr,"%.8g",dnum);
                   1347:   DrawDisplay();
                   1348: }
                   1349: 
                   1350: offf()
                   1351: {
                   1352:   /* full reset */
                   1353:   ResetCalc();
                   1354:   entered=clrdisp=1;
                   1355:   dnum=mem[0]=0.0;
                   1356:   accset=exponent=decimal=0;
                   1357:   DrawDisplay();
                   1358: }
                   1359: 
                   1360: 
                   1361: nop()
                   1362: {
                   1363:   XBell(dpy, 0);
                   1364: }
                   1365: 
                   1366: 
                   1367: /*******/
                   1368: Quit()
                   1369: /*******/
                   1370: {
                   1371:     exit(0);
                   1372: }
                   1373: 
                   1374: 
                   1375: #define STACKMAX 32
                   1376: static int opstack[STACKMAX];
                   1377: static int opsp;
                   1378: static double numstack[STACKMAX];
                   1379: static int numsp;
                   1380: 
                   1381: 
                   1382: /*******/
                   1383: PushOp(op)
                   1384:    int op;
                   1385: /*******/
                   1386: {
                   1387:   if (opsp==STACKMAX) {strcpy(dispstr,"stack error");  entered=3;}
                   1388:   else opstack[opsp++]=op;
                   1389: }
                   1390: 
                   1391: /*******/
                   1392: int PopOp()
                   1393: /*******/
                   1394: {
                   1395:   if (opsp==0) {
                   1396:       strcpy(dispstr,"stack error");
                   1397:       entered=3;
                   1398:       return(kNOP);
                   1399:   } else
                   1400:     return(opstack[--opsp]);
                   1401: }
                   1402: 
                   1403: /*******/
                   1404: int isopempty()
                   1405: /*******/
                   1406: {
                   1407:   return( opsp ? 0 : 1 );
                   1408: }
                   1409: 
                   1410: /*******/
                   1411: PushNum(num)
                   1412:  double num;
                   1413: /*******/
                   1414: {
                   1415:   if (rpn) {
                   1416:       numstack[2] = numstack[1];
                   1417:       numstack[1] = numstack[0];
                   1418:       numstack[0] = num;
                   1419:       return;
                   1420:   }
                   1421:   if (numsp==STACKMAX) {
                   1422:       strcpy(dispstr,"stack error");
                   1423:       entered=3;
                   1424:   } else
                   1425:     numstack[numsp++]=num;
                   1426: }
                   1427: 
                   1428: /*******/
                   1429: double PopNum()
                   1430: /*******/
                   1431: {
                   1432:     if (rpn) {
                   1433:        double tmp = numstack[0];
                   1434:        numstack[0] = numstack[1];
                   1435:        numstack[1] = numstack[2];
                   1436:        return(tmp);
                   1437:     }
                   1438:     if (numsp==0) {
                   1439:        strcpy(dispstr,"stack error");
                   1440:        entered=3;
                   1441:     } else
                   1442:       return(numstack[--numsp]);
                   1443: }
                   1444: 
                   1445: /*******/
                   1446: RollNum(dir)
                   1447: /*******/
                   1448: {
                   1449:     double tmp;
                   1450: 
                   1451:     if (!dir) {
                   1452:        tmp         = dnum;
                   1453:        dnum        = numstack[2];
                   1454:        numstack[2] = numstack[1];
                   1455:        numstack[1] = numstack[0];
                   1456:        numstack[0] = tmp;
                   1457:     } else {
                   1458:        tmp         = dnum;
                   1459:        dnum        = numstack[0];
                   1460:        numstack[0] = numstack[1];
                   1461:        numstack[1] = numstack[2];
                   1462:        numstack[2] = tmp;
                   1463:     }
                   1464: }
                   1465: 
                   1466: 
                   1467: /*******/
                   1468: int isnumempty()
                   1469: /*******/
                   1470: {
                   1471:   return( numsp ? 0 : 1 );
                   1472: }
                   1473: 
                   1474: 
                   1475: /*******/
                   1476: ClearStacks()
                   1477: /*******/
                   1478: {
                   1479:     if (rpn)
                   1480:       numstack[0] = numstack[1] = numstack[2] = 0.;
                   1481:     opsp=numsp=0;
                   1482: }
                   1483: 
                   1484: 
                   1485: /*******/
                   1486: int priority(op)
                   1487:          int op;
                   1488: /*******/
                   1489: {
                   1490:     switch (op) {
                   1491:         case kPOW: return(2);
                   1492:         case kMUL:
                   1493:         case kDIV: return(1);
                   1494:         case kADD:
                   1495:         case kSUB: return(0);
                   1496:         }
                   1497: }
                   1498: 
                   1499: 
                   1500: /********/
                   1501: ResetCalc()
                   1502: /********/
                   1503: {
                   1504:     flagM=flagK=flagINV=flagE=flagPAREN=0;  drgmode=DEG;
                   1505:     strcpy(dispstr,"0");
                   1506:     ClearStacks();
                   1507:     drg2rad=PI/180.0;
                   1508:     rad2drg=180.0/PI;
                   1509: }
                   1510: 
                   1511: 
                   1512: /*********/
                   1513: TypeChar(c)
                   1514:     char c;
                   1515: /*********/
                   1516: {
                   1517:     /* figure out if person typed a valid calculator key.
                   1518:          If so, press the key, wait a bit, and release the key
                   1519:          else Feep() */
                   1520: 
                   1521:     int i,code;
                   1522: 
                   1523:     switch (c) {
                   1524:         case '0':  code=kZERO;   break;
                   1525:         case '1':  code=kONE;    break;
                   1526:         case '2':  code=kTWO;    break;
                   1527:         case '3':  code=kTHREE;  break;
                   1528:         case '4':  code=kFOUR;   break;
                   1529:         case '5':  code=kFIVE;   break;
                   1530:         case '6':  code=kSIX;    break;
                   1531:         case '7':  code=kSEVEN;  break;
                   1532:         case '8':  code=kEIGHT;  break;
                   1533:         case '9':  code=kNINE;   break;
                   1534:         case '.':  code=kDEC;    break;
                   1535:         case '+':  code=kADD;    break;
                   1536:         case '-':  code=kSUB;    break;
                   1537:         case '*':  code=kMUL;    break;
                   1538:         case '/':  code=kDIV;    break;
                   1539:         case '(':  code=kLPAR;   break;
                   1540:         case ')':  code=kRPAR;   break;
                   1541:         case '!':  code=kFACT;   break;
                   1542:         case 'e':  code=kEE;     break;
                   1543:         case '^':  code=kPOW;    break;
                   1544:         case 'p':  code=kPI;     break;
                   1545:         case 'i':  code=kINV;    break;
                   1546:         case 's':  code=kSIN;    break;
                   1547:         case 'c':  code=kCOS;    break;
                   1548:         case 't':  code=kTAN;    break;
                   1549:         case 'd':  code=kDRG;    break;
                   1550:         case 'l':  code=kLN;     break;
                   1551:         case '=':  code=kEQU;    break;
                   1552:         case 'n':  code=kNEG;    break;
                   1553:        case 'r':  code=kSQRT;   break;
                   1554:        case 'x':  code=kXXY;    break;
                   1555:        case '\r':
                   1556:        case '\n': code=kENTR;   break;
                   1557:         case '\177':
                   1558:         case '\010': code=kBKSP; break;
                   1559:        case ' ':  code=kCLR;    break;
                   1560:         case '\003': Quit();     break;
                   1561:         default:   code = -1;
                   1562:         }
                   1563: 
                   1564:     if (!rpn && code == kBKSP)
                   1565:       code = kCLR;
                   1566:     for (i=0; i < numkeys; i++)
                   1567:       if (key[i].code == code) break;
                   1568: 
                   1569:     if (code != -1 && i < numkeys && key[i].code == code) {
                   1570:         InvertKey(i);
                   1571:         XFlush(dpy);
                   1572:         Timer(100000L);
                   1573:         LetGoKey(i);
                   1574:         XFlush(dpy);
                   1575:         }
                   1576:     else XBell(dpy,0);
                   1577: }
                   1578: 
                   1579: 
                   1580: 
                   1581: static int timerdone;
                   1582: 
                   1583: /*******/
                   1584: onalarm()
                   1585: /*******/
                   1586: {
                   1587:   timerdone=1;
                   1588: }
                   1589: 
                   1590: /*******/
                   1591: Timer(val)
                   1592:  long val;
                   1593: /*******/
                   1594: {
                   1595:         struct itimerval it;
                   1596: 
                   1597:         bzero(&it, sizeof(it));
                   1598:         it.it_value.tv_usec = val;
                   1599:         timerdone=0;
                   1600:         signal(SIGALRM,onalarm);
                   1601:         setitimer(ITIMER_REAL, &it, (struct itimerval *)0);
                   1602:         while (!timerdone);
                   1603:         signal(SIGALRM,SIG_DFL);
                   1604: }
                   1605: 
                   1606: 
                   1607: 
                   1608: #ifndef IEEE
                   1609: /******************/
                   1610: fperr(sig,code,scp)
                   1611:   int sig,code;
                   1612:   struct sigcontext *scp;
                   1613: /******************/
                   1614: {
                   1615:     longjmp(env,code);
                   1616: }
                   1617: 
                   1618: #endif

unix.superglobalmegacorp.com

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