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