|
|
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.