|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.