|
|
1.1 root 1: /****************************** Module Header ******************************\
2: * Module Name: calcmath.c - Calc application
3: *
4: * OS/2 Presentation Manager version of Calc, ported from Windows version
5: *
6: * Created by Microsoft Corporation, 1987
7: *
8: \***************************************************************************/
9:
10: #define INCL_PM
11: #include <os2.h>
12: #include <string.h>
13: #include <stdio.h>
14: #include <stdlib.h>
15: #include <math.h>
16:
17: BOOL fReadNumber;
18: extern BOOL fValueInMemory;
19: extern char currkey;
20: extern char szreg1[20], szreg2[20], szmem[20];
21: char PendingOperation;
22: extern HWND hwndCalc;
23: BOOL fFirstOperand, fError;
24: extern char lastkey;
25: char temp[30];
26: char szresult[20];
27: extern char szregx[];
28: SEL sel;
29:
30: #define tolower(x) (((x) >= 'A') && ((x)<='Z')) ? (x) - 'A' + 'a' : (x)
31: #define MAXINT (double)999999999
32: #define MININT (double)-999999999
33: #define ABS(x) (((x) >= (double)0) ? (x) : (-(x)))
34:
35: extern VOID FarStrcpy( PSZ, PSZ);
36: extern VOID UpdateDisplay( VOID);
37: extern BOOL InterpretChar( CHAR);
38:
39: VOID AppendNumber( BYTE);
40: VOID BinaryOperator( CHAR);
41: VOID Clear( VOID);
42: VOID DataXCopy( VOID);
43: VOID DataXPaste( VOID);
44: VOID Equilibrate( VOID);
45: VOID Evaluate( BYTE);
46: NPCH ftoa( double);
47: VOID InitCalc( VOID);
48: VOID MClear( VOID);
49: VOID MMinus( VOID);
50: VOID MPlus( VOID);
51: VOID Negate( VOID);
52: VOID Number( CHAR);
53: VOID Percent( VOID);
54: VOID reverse( NPCH);
55: VOID Simplify( VOID);
56: VOID SquareRoot( VOID);
57:
58:
59: VOID reverse(s)
60: NPCH s;
61: {
62: CHAR c;
63: register int i, j;
64:
65: for (i = 0, j = strlen(s) - 1; i<j; i++, j-- ) {
66: c = s[i];
67: s[i] = s[j];
68: s[j] = c;
69: }
70: }
71:
72: NPCH ftoa(num)
73: double num;
74: {
75: sprintf( szresult, "%.8f", num );
76: return (szresult);
77: }
78:
79:
80: VOID Negate()
81: {
82: char sztemp[ 20 ];
83:
84: if (szreg1[0] == '-') {
85: /* get rid of minus sign */
86: strcpy(szreg1, (&szreg1[1]));
87: }
88: /* can negate anything but zero */
89: else if (szreg1[0] != '0' || (strlen(szreg1) > 2)) {
90: sztemp[0] = '-';
91: strcpy(&sztemp[1], szreg1);
92: strcpy(szreg1, sztemp);
93: }
94: }
95:
96: VOID Number( n )
97: CHAR n;
98: {
99: register int len, size;
100:
101: size = 9;
102: if (szreg1[0] == '-') size++;
103: if (strchr(szreg1, '.')) size++;
104: len = strlen(szreg1 );
105: if (len == size) return;
106: if (len == 1 && szreg1[0] == '0') len--;
107: szreg1[ len ] = n;
108: szreg1[min(len + 1, 11)] = 0;
109: }
110:
111: VOID AppendNumber ( num )
112: BYTE num;
113: {
114: if (num == '.') { /* if no decimal, add one at end */
115: if (!strchr(szreg1, '.'))
116: strcat(szreg1, ".");
117: }
118: else if ( num == 0xb1 ) {
119: Negate();
120: }
121: else {
122: Number(num);
123: }
124: }
125:
126: VOID Equilibrate()
127: {
128: double result;
129: double x1, x2;
130:
131: if (lastkey == '=') return;
132: result = (double)atof(szreg1);
133: x1 = (double)atof(szreg1);
134: x2 = (double)atof(szreg2);
135:
136: switch (PendingOperation) {
137: case '+':
138: if (x2>(double)0) { /* check for overflow */
139: if (x1>(double)0) {
140: if (x1 > (MAXINT - x2))
141: fError = TRUE;
142: }
143: }
144: else if (x2 < (double)0) {
145: if (x1 < (double)0) {
146: if ( x1 < (MININT - x2))
147: fError = TRUE;
148: }
149: }
150: if (!fError) {
151: result = x2 + x1;
152: }
153: break;
154: case '-':
155: if (x2 < (double)0) {
156: if (x1 > (double)0) {
157: if (x1 > (x2 - MININT))
158: fError = TRUE;
159: }
160: }
161: else if (x2 > (double)0) {
162: if (x1 < (double)0) {
163: if (x1 < (x2 - MAXINT))
164: fError = TRUE;
165: }
166: }
167: if (!fError)
168: result = x2 - x1;
169: break;
170: case '/':
171: if (x1 == (double)0.0)
172: fError = TRUE;
173: else if (x2 > (double)0) {
174: if (x1 > (double)0) {
175: if (x1 < (x2 / MAXINT))
176: fError = TRUE;
177: }
178: else { /* x1 < 0 here */
179: if (x1 > (x2 / MININT))
180: fError = TRUE;
181: }
182: }
183: else { /* x2 < 0 here */
184: if (x1 < (double)0) {
185: if (x1 > (x2 / MAXINT))
186: fError = TRUE;
187: }
188: else { /* x1 > 0 here */
189: if (x1 < (x2 / MININT))
190: fError = TRUE;
191: }
192: }
193: if (!fError) result = x2 / x1;
194: break;
195: case '*':
196: if (x1 == (double)0) return;
197: if (ABS(x2) > (double)1) {
198: if (ABS(x1) > (double)1) {
199: if (ABS(x1) > (MAXINT / ABS(x2)))
200: fError = TRUE;
201: }
202: }
203: if (!fError) result = x2 * x1;
204: break;
205: }
206: if (!fError) {
207: strcpy(szreg1, ftoa((double)result));
208: strcpy( szreg2, szreg1 );
209: }
210: Simplify();
211: }
212:
213: VOID SquareRoot()
214: {
215: double result;
216:
217: result = (double)atof(szreg1);
218: if (result < 0.0) {
219: fError = TRUE;
220: return;
221: }
222:
223: if ((result == 0.0) || ((lastkey == 'q') && (result == 1.0)))
224: return;
225:
226: if ((result < (double) 1.00000002) && (result > (double) 1.0))
227: result = (double)1.0;
228: else
229: result = sqrt(result);
230:
231: strcpy( szreg1, ftoa((double)result));
232:
233: if (atof( szreg1 ) == 0.0)
234: strcpy(szreg1, "0.");
235:
236: Simplify();
237: }
238:
239: VOID BinaryOperator( op )
240: CHAR op;
241: {
242: if (fFirstOperand) {
243: fFirstOperand = FALSE;
244: strcpy(szreg2, szreg1);
245: }
246: else {
247: Equilibrate();
248: }
249: PendingOperation = op;
250: }
251:
252: VOID Clear()
253: {
254: fReadNumber = FALSE;
255: fFirstOperand = TRUE;
256: strcpy(szreg1, "0.");
257: if (fError || lastkey == 'c'){
258: strcpy(szreg2, "0.");
259: PendingOperation = NULL;
260: }
261: fError = FALSE;
262: }
263:
264: /* trash out trailing zeros, if a '.' is in the number */
265: /* and leading zeros in all cases. */
266: VOID Simplify()
267: {
268: register int len;
269: char local[20];
270: register int count;
271:
272: count = 0;
273: strcpy(local, szreg1);
274: if (atof(local) != 0.0) {
275: while (local[count++] == '0');
276: strcpy(szreg1, &local[count-1] );
277: }
278: if (strchr(szreg1, '.')) {
279: len = strlen(szreg1);
280: while (szreg1[--len] == '0');
281: szreg1[min(len + 1, 11)] = 0; /* null terminate */
282: }
283: }
284:
285:
286: VOID DataXPaste()
287: {
288: PSZ lp;
289: register char c;
290:
291: if (WinOpenClipbrd(NULL))
292: {
293: lp = (PSZ)WinQueryClipbrdData(NULL, CF_TEXT);
294: if (lp)
295: {
296: while (*lp)
297: {
298: c = tolower(*lp);
299: if (c == 'm')
300: {
301: lp++;
302: switch (tolower(*lp))
303: {
304: case '-':
305: c = '\271';
306: break;
307: case '+':
308: c = '\272';
309: break;
310: case 'r':
311: c = '\273';
312: break;
313: case 'c':
314: c = '\274';
315: break;
316: default:
317: c = ' ';
318: break;
319: }
320: }
321: lp++;
322: InterpretChar(c);
323: UpdateDisplay();
324: }
325: }
326: }
327: WinCloseClipbrd(NULL);
328: InterpretChar('=');
329: UpdateDisplay();
330: }
331:
332:
333: VOID DataXCopy()
334: {
335: PSZ lpsztext;
336:
337: if (WinOpenClipbrd(NULL))
338: {
339: WinEmptyClipbrd(NULL);
340: DosAllocSeg(20, (SEL FAR *)&sel, 2L); /* SEG_GETTABLE */
341: if (sel == NULL) return;
342: lpsztext = MAKEP(sel, 0);
343: FarStrcpy(lpsztext, (PSZ)szreg1);
344: WinSetClipbrdData(NULL, (ULONG)sel, CF_TEXT, CFI_SELECTOR);
345: WinCloseClipbrd(NULL);
346: }
347: }
348:
349:
350: VOID MPlus()
351: {
352: double x2, x1, result;
353:
354: x2 = atof(szmem);
355: x1 = atof(szreg1);
356:
357: if (x2>(double)0) { /* check for overflow */
358: if (x1>(double)0) {
359: if (x1 > (MAXINT - x2))
360: fError = TRUE;
361: }
362: }
363: else if (x2 < (double)0) {
364: if (x1 < (double)0) {
365: if ( x1 < (MININT - x2))
366: fError = TRUE;
367: }
368: }
369: if (!fError) {
370: result = x2 + x1;
371: strcpy( szmem, ftoa((double)result));
372: }
373: if (result == (double)0.0)
374: fValueInMemory = FALSE;
375: else fValueInMemory = TRUE;
376: }
377:
378: VOID MClear()
379: {
380: strcpy(szmem, "0.");
381: fValueInMemory = FALSE;
382: }
383:
384:
385: VOID MMinus()
386: {
387: double x1, x2, result;
388:
389: x2 = atof(szmem);
390: x1 = atof(szreg1);
391: if (x2 < (double)0) {
392: if (x1 > (double)0) {
393: if (x1 > (x2 - MININT))
394: fError = TRUE;
395: }
396: }
397: else if (x2 > (double)0) {
398: if (x1 < (double)0) {
399: if (x1 < (x2 - MAXINT))
400: fError = TRUE;
401: }
402: }
403: if (!fError) {
404: result = x2 - x1;
405: strcpy( szmem, ftoa((double)result));
406: }
407: if (result == (double)0.0)
408: fValueInMemory = FALSE;
409: else fValueInMemory = TRUE;
410: }
411:
412: VOID Evaluate( command )
413: BYTE command;
414: {
415: currkey = command;
416: switch( command ) {
417: case '0': case '1': case '2': case '3': case '4': case '5':
418: case '6': case '7': case '8': case '9': case '.': case 0xb1:
419: case 'n': /* n = 'negate' from keyboard */
420: if ( fReadNumber ) {
421: AppendNumber( command );
422: }
423: else {
424: /* if starting a new number */
425: if (command != 0xb1)
426: strcpy(szreg1, "0");
427: AppendNumber( command );
428: }
429: if (command != 0xb1)
430: fReadNumber = TRUE;
431: break;
432: case '+': case '-': case '/': case '*': case 'p':
433: BinaryOperator(command);
434: fReadNumber = FALSE;
435: break;
436: case '=':
437: fReadNumber = FALSE;
438: Equilibrate();
439: PendingOperation = NULL;
440: break;
441: case 'q':
442: SquareRoot();
443: fReadNumber = FALSE;
444: break;
445: case 0xBB: /* MR */
446: strcpy(szreg1, szmem);
447: fReadNumber = FALSE;
448: Simplify();
449: break;
450: case 0xBA: /* M+ */
451: MPlus();
452: fReadNumber = FALSE;
453: Simplify();
454: break;
455: case 0xB9: /* M- */
456: MMinus();
457: fReadNumber = FALSE;
458: Simplify();
459: break;
460: case 0xBC:
461: MClear(); /* MC */
462: break;
463: case '%':
464: Percent();
465: fReadNumber = FALSE;
466: break;
467: case 'c':
468: Clear();
469: break;
470: }
471: }
472:
473: VOID Percent()
474: {
475: double x1, x2, result;
476:
477: x1 = atof(szreg1) / 100.0;
478: x2 = atof(szreg2);
479: if (ABS(x2) > (double)1) {
480: if (ABS(x1) > (double)1) {
481: if (x1 > (MAXINT / x2))
482: fError = TRUE;
483: }
484: }
485: if (!fError) {
486: result = x2 * x1;
487: strcpy( szreg1, ftoa((double)result));
488: }
489: Simplify();
490: }
491:
492: VOID InitCalc()
493: {
494: fReadNumber = FALSE;
495: fError = FALSE;
496: fFirstOperand = TRUE;
497: PendingOperation = 0;
498: strcpy(szreg1, "0.");
499: strcpy(szmem, "0.");
500: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.