|
|
1.1.1.2 ! 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 Corporation, 1987 */ ! 8: /* */ ! 9: /******************************************************************************/ 1.1 root 10: 1.1.1.2 ! root 11: #define INCL_WINCLIPBOARD 1.1 root 12: #include <os2.h> 13: #include <string.h> 14: #include <stdio.h> 15: #include <stdlib.h> 16: #include <math.h> 17: 18: extern BOOL fValueInMemory; 1.1.1.2 ! root 19: extern CHAR chLastKey; ! 20: extern CHAR szreg1[20], szreg2[20], szmem[20]; 1.1 root 21: extern HWND hwndCalc; 1.1.1.2 ! root 22: extern CHAR szregx[]; ! 23: extern HAB hab; ! 24: BOOL fReadNumber; ! 25: CHAR PendingOperation; 1.1 root 26: BOOL fFirstOperand, fError; 1.1.1.2 ! root 27: CHAR szresult[20]; ! 28: SEL sel; 1.1 root 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: 1.1.1.2 ! root 35: ! 36: /******************************************************************************/ 1.1 root 37: extern VOID UpdateDisplay( VOID); 38: extern BOOL InterpretChar( CHAR); 39: 40: VOID AppendNumber( BYTE); 41: VOID BinaryOperator( CHAR); 42: VOID Clear( VOID); 43: VOID DataXCopy( VOID); 44: VOID DataXPaste( VOID); 45: VOID Equilibrate( VOID); 46: VOID Evaluate( BYTE); 1.1.1.2 ! root 47: VOID FarStrcpy( PSZ, PSZ); 1.1 root 48: NPCH ftoa( double); 49: VOID InitCalc( VOID); 50: VOID MClear( VOID); 51: VOID MMinus( VOID); 52: VOID MPlus( VOID); 53: VOID Negate( VOID); 54: VOID Number( CHAR); 55: VOID Percent( VOID); 56: VOID reverse( NPCH); 57: VOID Simplify( VOID); 58: VOID SquareRoot( VOID); 59: 60: 1.1.1.2 ! root 61: /******************************************************************************/ ! 62: VOID FarStrcpy( pszDest, pszSrc) ! 63: PSZ pszDest, pszSrc; ! 64: { ! 65: while( *pszDest++ = *pszSrc++); ! 66: } ! 67: ! 68: /******************************************************************************/ ! 69: VOID ! 70: reverse( s) ! 71: 1.1 root 72: NPCH s; 73: { 1.1.1.2 ! root 74: CHAR ch; ! 75: register INT iHead, iTail; 1.1 root 76: 1.1.1.2 ! root 77: for (iHead = 0, iTail = strlen(s) - 1; iHead<iTail; iHead++, iTail-- ) { ! 78: ch = s[iHead]; ! 79: s[iHead] = s[iTail]; ! 80: s[iTail] = ch; 1.1 root 81: } 82: } 83: 1.1.1.2 ! root 84: /******************************************************************************/ ! 85: NPCH ! 86: ftoa( dblNum) ! 87: ! 88: double dblNum; 1.1 root 89: { 1.1.1.2 ! root 90: sprintf( szresult, "%.8f", dblNum ); 1.1 root 91: return (szresult); 92: } 93: 94: 1.1.1.2 ! root 95: /******************************************************************************/ ! 96: VOID ! 97: Negate() 1.1 root 98: { 1.1.1.2 ! root 99: CHAR sztemp[ 20 ]; 1.1 root 100: 1.1.1.2 ! root 101: if (szreg1[0] == '-') ! 102: strcpy(szreg1, (&szreg1[1])); /* get rid of minus sign */ ! 103: else if (szreg1[0] != '0' || (strlen(szreg1) > 2)) { /* can't negate zero */ ! 104: sztemp[0] = '-'; ! 105: strcpy(&sztemp[1], szreg1); ! 106: strcpy(szreg1, sztemp); ! 107: } 1.1 root 108: } 109: 1.1.1.2 ! root 110: /******************************************************************************/ ! 111: VOID ! 112: Number( ch) ! 113: ! 114: CHAR ch; 1.1 root 115: { 1.1.1.2 ! root 116: register INT iLen, iSize; 1.1 root 117: 1.1.1.2 ! root 118: iSize = 9; ! 119: if (szreg1[0] == '-') iSize++; ! 120: if (strchr(szreg1, '.')) iSize++; ! 121: iLen = strlen(szreg1 ); ! 122: if (iLen == iSize) return; ! 123: if (iLen == 1 && szreg1[0] == '0') iLen--; ! 124: szreg1[ iLen ] = ch; ! 125: szreg1[min(iLen + 1, 11)] = 0; 1.1 root 126: } 127: 1.1.1.2 ! root 128: /******************************************************************************/ ! 129: VOID ! 130: AppendNumber ( b) ! 131: ! 132: BYTE b; 1.1 root 133: { 1.1.1.2 ! root 134: if (b == '.') { /* if no decimal, add one at end */ 1.1 root 135: if (!strchr(szreg1, '.')) 136: strcat(szreg1, "."); 1.1.1.2 ! root 137: } ! 138: else if ( b == 0xb1 ) ! 139: Negate(); ! 140: else ! 141: Number(b); ! 142: } ! 143: ! 144: /******************************************************************************/ ! 145: VOID ! 146: Equilibrate() ! 147: { ! 148: double dblResult; ! 149: double dblX1, dblX2; ! 150: ! 151: if (chLastKey == '=') return; ! 152: dblResult = (double)atof(szreg1); ! 153: dblX1 = (double)atof(szreg1); ! 154: dblX2 = (double)atof(szreg2); 1.1 root 155: 156: switch (PendingOperation) { 157: case '+': 1.1.1.2 ! root 158: if (dblX2>(double)0) { /* check for overflow */ ! 159: if (dblX1>(double)0) { ! 160: if (dblX1 > (MAXINT - dblX2)) 1.1 root 161: fError = TRUE; 1.1.1.2 ! root 162: } ! 163: } ! 164: else if (dblX2 < (double)0) { ! 165: if (dblX1 < (double)0) { ! 166: if ( dblX1 < (MININT - dblX2)) ! 167: fError = TRUE; ! 168: } ! 169: } ! 170: if (!fError) ! 171: dblResult = dblX2 + dblX1; 1.1 root 172: break; 173: case '-': 1.1.1.2 ! root 174: if (dblX2 < (double)0) { ! 175: if (dblX1 > (double)0) { ! 176: if (dblX1 > (dblX2 - MININT)) 1.1 root 177: fError = TRUE; 1.1.1.2 ! root 178: } ! 179: } ! 180: else if (dblX2 > (double)0) { ! 181: if (dblX1 < (double)0) { ! 182: if (dblX1 < (dblX2 - MAXINT)) 1.1 root 183: fError = TRUE; 1.1.1.2 ! root 184: } ! 185: } 1.1 root 186: if (!fError) 1.1.1.2 ! root 187: dblResult = dblX2 - dblX1; 1.1 root 188: break; 189: case '/': 1.1.1.2 ! root 190: if (dblX1 == (double)0.0) 1.1 root 191: fError = TRUE; 1.1.1.2 ! root 192: else if (dblX2 > (double)0) { ! 193: if (dblX1 > (double)0) { ! 194: if (dblX1 < (dblX2 / MAXINT)) ! 195: fError = TRUE; ! 196: } ! 197: else { /* dblX1 < 0 here */ ! 198: if (dblX1 > (dblX2 / MININT)) ! 199: fError = TRUE; ! 200: } ! 201: } ! 202: else { /* dblX2 < 0 here */ ! 203: if (dblX1 < (double)0) { ! 204: if (dblX1 > (dblX2 / MAXINT)) ! 205: fError = TRUE; ! 206: } ! 207: else { /* dblX1 > 0 here */ ! 208: if (dblX1 < (dblX2 / MININT)) ! 209: fError = TRUE; ! 210: } ! 211: } ! 212: if (!fError) ! 213: dblResult = dblX2 / dblX1; 1.1 root 214: break; 215: case '*': 1.1.1.2 ! root 216: if (dblX1 == (double)0) return; ! 217: if (ABS(dblX2) > (double)1) { ! 218: if (ABS(dblX1) > (double)1) { ! 219: if (ABS(dblX1) > (MAXINT / ABS(dblX2))) 1.1 root 220: fError = TRUE; 221: } 222: } 1.1.1.2 ! root 223: if (!fError) dblResult = dblX2 * dblX1; 1.1 root 224: break; 225: } 226: if (!fError) { 1.1.1.2 ! root 227: strcpy(szreg1, ftoa((double)dblResult)); 1.1 root 228: strcpy( szreg2, szreg1 ); 229: } 230: Simplify(); 231: } 232: 1.1.1.2 ! root 233: /******************************************************************************/ ! 234: VOID ! 235: SquareRoot() 1.1 root 236: { 1.1.1.2 ! root 237: double dblResult; 1.1 root 238: 1.1.1.2 ! root 239: dblResult = (double)atof(szreg1); ! 240: if (dblResult < 0.0) { 1.1 root 241: fError = TRUE; 242: return; 1.1.1.2 ! root 243: } ! 244: if ((dblResult == 0.0) || ((chLastKey == 'q') && (dblResult == 1.0))) 1.1 root 245: return; 1.1.1.2 ! root 246: if ((dblResult < (double) 1.00000002) && (dblResult > (double) 1.0)) ! 247: dblResult = (double)1.0; 1.1 root 248: else 1.1.1.2 ! root 249: dblResult = sqrt(dblResult); ! 250: strcpy( szreg1, ftoa((double)dblResult)); 1.1 root 251: if (atof( szreg1 ) == 0.0) 252: strcpy(szreg1, "0."); 253: Simplify(); 254: } 255: 1.1.1.2 ! root 256: /******************************************************************************/ ! 257: VOID ! 258: BinaryOperator( ch) ! 259: ! 260: CHAR ch; 1.1 root 261: { 262: if (fFirstOperand) { 263: fFirstOperand = FALSE; 264: strcpy(szreg2, szreg1); 1.1.1.2 ! root 265: } 1.1 root 266: else { 267: Equilibrate(); 1.1.1.2 ! root 268: } ! 269: PendingOperation = ch; 1.1 root 270: } 271: 1.1.1.2 ! root 272: /******************************************************************************/ ! 273: VOID ! 274: Clear() 1.1 root 275: { 276: fReadNumber = FALSE; 277: fFirstOperand = TRUE; 278: strcpy(szreg1, "0."); 1.1.1.2 ! root 279: if (fError || chLastKey == 'c'){ 1.1 root 280: strcpy(szreg2, "0."); 281: PendingOperation = NULL; 1.1.1.2 ! root 282: } 1.1 root 283: fError = FALSE; 284: } 285: 1.1.1.2 ! root 286: /******************************************************************************/ ! 287: /* trash out trailing zeros, if a '.' is in the number */ ! 288: /* and leading zeros in all cases. */ ! 289: /******************************************************************************/ ! 290: VOID ! 291: Simplify() ! 292: { ! 293: register INT iLen, iCount; ! 294: CHAR achLocal[20]; ! 295: ! 296: iCount = 0; ! 297: strcpy(achLocal, szreg1); ! 298: if (atof(achLocal) != 0.0) { ! 299: while (achLocal[iCount++] == '0'); ! 300: strcpy(szreg1, &achLocal[iCount-1] ); ! 301: } 1.1 root 302: if (strchr(szreg1, '.')) { 1.1.1.2 ! root 303: iLen = strlen(szreg1); ! 304: while (szreg1[--iLen] == '0'); ! 305: szreg1[min( iLen + 1, 11)] = 0; /* null terminate */ ! 306: } 1.1 root 307: } 308: 309: 1.1.1.2 ! root 310: /******************************************************************************/ ! 311: VOID ! 312: DataXPaste() ! 313: { ! 314: PSZ psz; ! 315: ULONG ulText; ! 316: register CHAR ch; 1.1 root 317: 1.1.1.2 ! root 318: if (WinOpenClipbrd( hab)) 1.1 root 319: { 1.1.1.2 ! root 320: ulText = WinQueryClipbrdData( hab, CF_TEXT); ! 321: if (ulText) ! 322: { ! 323: psz = MAKEP( (SEL)ulText, 0); ! 324: while (*psz) 1.1 root 325: { 1.1.1.2 ! root 326: ch = tolower(*psz); ! 327: if (ch == 'm') 1.1 root 328: { 1.1.1.2 ! root 329: psz++; ! 330: switch (tolower(*psz)) 1.1 root 331: { 1.1.1.2 ! root 332: case '-': ! 333: ch = '\271'; ! 334: break; ! 335: case '+': ! 336: ch = '\272'; ! 337: break; ! 338: case 'r': ! 339: ch = '\273'; ! 340: break; ! 341: case 'c': ! 342: ch = '\274'; ! 343: break; ! 344: default: ! 345: ch = ' '; ! 346: break; 1.1 root 347: } 348: } 1.1.1.2 ! root 349: psz++; ! 350: InterpretChar(ch); 1.1 root 351: UpdateDisplay(); 352: } 353: } 354: } 1.1.1.2 ! root 355: WinCloseClipbrd( hab); 1.1 root 356: InterpretChar('='); 357: UpdateDisplay(); 358: } 359: 360: 1.1.1.2 ! root 361: /******************************************************************************/ ! 362: VOID ! 363: DataXCopy() 1.1 root 364: { 1.1.1.2 ! root 365: PSZ pszText; 1.1 root 366: 1.1.1.2 ! root 367: if (WinOpenClipbrd( hab)) 1.1 root 368: { 1.1.1.2 ! root 369: WinEmptyClipbrd( hab); ! 370: DosAllocSeg( 20, (SEL FAR *)&sel, SEG_GIVEABLE); 1.1 root 371: if (sel == NULL) return; 1.1.1.2 ! root 372: pszText = MAKEP(sel, 0); ! 373: FarStrcpy( pszText, (PSZ)szreg1); ! 374: WinSetClipbrdData( hab, (ULONG)sel, CF_TEXT, CFI_SELECTOR); ! 375: WinCloseClipbrd( hab); 1.1 root 376: } 377: } 378: 379: 1.1.1.2 ! root 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)) 1.1 root 392: fError = TRUE; 1.1.1.2 ! root 393: } ! 394: } ! 395: else if (dblX2 < (double)0) { ! 396: if (dblX1 < (double)0) { ! 397: if ( dblX1 < (MININT - dblX2)) ! 398: fError = TRUE; ! 399: } ! 400: } 1.1 root 401: if (!fError) { 1.1.1.2 ! root 402: dblResult = dblX2 + dblX1; ! 403: strcpy( szmem, ftoa((double)dblResult)); ! 404: } ! 405: if (dblResult == (double)0.0) 1.1 root 406: fValueInMemory = FALSE; 407: else fValueInMemory = TRUE; 408: } 409: 1.1.1.2 ! root 410: /******************************************************************************/ ! 411: VOID ! 412: MClear() 1.1 root 413: { 414: strcpy(szmem, "0."); 415: fValueInMemory = FALSE; 416: } 417: 418: 1.1.1.2 ! root 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)) 1.1 root 430: fError = TRUE; 1.1.1.2 ! root 431: } ! 432: } ! 433: else if (dblX2 > (double)0) { ! 434: if (dblX1 < (double)0) { ! 435: if (dblX1 < (dblX2 - MAXINT)) 1.1 root 436: fError = TRUE; 1.1.1.2 ! root 437: } ! 438: } 1.1 root 439: if (!fError) { 1.1.1.2 ! root 440: dblResult = dblX2 - dblX1; ! 441: strcpy( szmem, ftoa((double)dblResult)); ! 442: } ! 443: if (dblResult == (double)0.0) 1.1 root 444: fValueInMemory = FALSE; 445: else fValueInMemory = TRUE; 446: } 447: 1.1.1.2 ! root 448: /******************************************************************************/ ! 449: VOID ! 450: Evaluate( bCommand) ! 451: ! 452: BYTE bCommand; 1.1 root 453: { 1.1.1.2 ! root 454: switch( bCommand ) { 1.1 root 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 */ 1.1.1.2 ! root 458: if ( fReadNumber ) ! 459: AppendNumber( bCommand ); 1.1 root 460: else { 461: /* if starting a new number */ 1.1.1.2 ! root 462: if (bCommand != 0xb1) 1.1 root 463: strcpy(szreg1, "0"); 1.1.1.2 ! root 464: AppendNumber( bCommand ); ! 465: } ! 466: if (bCommand != 0xb1) 1.1 root 467: fReadNumber = TRUE; 468: break; 469: case '+': case '-': case '/': case '*': case 'p': 1.1.1.2 ! root 470: BinaryOperator(bCommand); 1.1 root 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: 1.1.1.2 ! root 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)) 1.1 root 521: fError = TRUE; 1.1.1.2 ! root 522: } ! 523: } 1.1 root 524: if (!fError) { 1.1.1.2 ! root 525: dblResult = dblX2 * dblX1; ! 526: strcpy( szreg1, ftoa((double)dblResult)); ! 527: } 1.1 root 528: Simplify(); 529: } 530: 1.1.1.2 ! root 531: /******************************************************************************/ ! 532: VOID ! 533: InitCalc() 1.1 root 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.