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