home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk11 / tk3 / calc / calcmath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-20  |  12.8 KB  |  542 lines

  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. /******************************************************************************/
  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. extern BOOL fValueInMemory;
  19. extern CHAR chLastKey;
  20. extern CHAR szreg1[20], szreg2[20], szmem[20];
  21. extern HWND hwndCalc;
  22. extern CHAR szregx[];
  23. extern HAB  hab;
  24. BOOL   fReadNumber;
  25. CHAR   PendingOperation;
  26. BOOL   fFirstOperand, fError;
  27. CHAR   szresult[20];
  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.  
  36. /******************************************************************************/
  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);
  47. VOID FarStrcpy( PSZ, PSZ);
  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.  
  61. /******************************************************************************/
  62. VOID FarStrcpy( pszDest, pszSrc)
  63. PSZ  pszDest, pszSrc;
  64. {
  65.     while( *pszDest++ = *pszSrc++);
  66. }
  67.  
  68. /******************************************************************************/
  69. VOID
  70. reverse( s)
  71.  
  72. NPCH s;
  73. {
  74.     CHAR ch;
  75.     register INT iHead, iTail;
  76.  
  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;
  81.     }
  82. }
  83.  
  84. /******************************************************************************/
  85. NPCH
  86. ftoa( dblNum)
  87.  
  88. double dblNum;
  89. {
  90.     sprintf( szresult, "%.8f", dblNum );
  91.     return (szresult);
  92. }
  93.  
  94.  
  95. /******************************************************************************/
  96. VOID
  97. Negate()
  98. {
  99.     CHAR sztemp[ 20 ];
  100.  
  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.      }
  108. }
  109.  
  110. /******************************************************************************/
  111. VOID
  112. Number( ch)
  113.  
  114. CHAR ch;
  115. {
  116.     register INT iLen, iSize;
  117.  
  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;
  126. }
  127.  
  128. /******************************************************************************/
  129. VOID
  130. AppendNumber ( b)
  131.  
  132. BYTE b;
  133. {
  134.     if (b == '.') {            /*    if no decimal, add one at end */
  135.         if (!strchr(szreg1, '.'))   
  136.             strcat(szreg1, ".");
  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);
  155.  
  156.     switch (PendingOperation) {
  157.         case '+':
  158.         if (dblX2>(double)0) {        /* check for overflow */
  159.         if (dblX1>(double)0) {
  160.             if (dblX1 > (MAXINT - dblX2))
  161.                         fError = TRUE;
  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;
  172.             break;
  173.         case '-':
  174.         if (dblX2 < (double)0) {
  175.         if (dblX1 > (double)0) {
  176.             if (dblX1 > (dblX2 - MININT))
  177.                         fError = TRUE;
  178.         }
  179.         }
  180.         else if (dblX2 > (double)0) {
  181.             if (dblX1 < (double)0) {
  182.             if (dblX1 < (dblX2 - MAXINT))
  183.                             fError = TRUE;
  184.             }
  185.          }
  186.             if (!fError) 
  187.         dblResult = dblX2 - dblX1;
  188.             break;
  189.         case '/':
  190.         if (dblX1 == (double)0.0)
  191.                 fError = TRUE;
  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;
  214.             break;
  215.         case '*':
  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)))
  220.                         fError = TRUE;
  221.                     } 
  222.                 }                    
  223.         if (!fError) dblResult = dblX2 * dblX1;
  224.             break;
  225.         }
  226.     if (!fError) {
  227.     strcpy(szreg1, ftoa((double)dblResult));
  228.         strcpy( szreg2, szreg1 );
  229.         }
  230.     Simplify();
  231. }
  232.  
  233. /******************************************************************************/
  234. VOID
  235. SquareRoot()
  236. {
  237.     double dblResult;
  238.  
  239.     dblResult = (double)atof(szreg1);
  240.     if (dblResult < 0.0) {
  241.         fError = TRUE;
  242.         return;
  243.     }
  244.     if ((dblResult == 0.0) || ((chLastKey == 'q') && (dblResult == 1.0)))
  245.         return;
  246.     if ((dblResult < (double) 1.00000002) && (dblResult > (double) 1.0))
  247.     dblResult = (double)1.0;
  248.     else
  249.     dblResult = sqrt(dblResult);
  250.     strcpy( szreg1, ftoa((double)dblResult));
  251.     if (atof( szreg1 ) == 0.0)
  252.         strcpy(szreg1, "0.");
  253.     Simplify();
  254. }
  255.  
  256. /******************************************************************************/
  257. VOID
  258. BinaryOperator( ch)
  259.  
  260. CHAR ch;
  261. {
  262.     if (fFirstOperand) {
  263.         fFirstOperand = FALSE;
  264.         strcpy(szreg2, szreg1);
  265.     }
  266.     else {
  267.         Equilibrate();
  268.     }
  269.     PendingOperation = ch;
  270. }
  271.  
  272. /******************************************************************************/
  273. VOID
  274. Clear()
  275. {
  276.     fReadNumber = FALSE;
  277.     fFirstOperand = TRUE;
  278.     strcpy(szreg1, "0.");
  279.     if (fError || chLastKey == 'c'){
  280.         strcpy(szreg2, "0.");
  281.         PendingOperation = NULL;
  282.     }
  283.     fError = FALSE;
  284. }
  285.  
  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.     }
  302.     if (strchr(szreg1, '.')) {
  303.     iLen = strlen(szreg1);
  304.     while (szreg1[--iLen] == '0');
  305.     szreg1[min( iLen + 1, 11)] = 0; /* null terminate */
  306.     }
  307. }
  308.  
  309.  
  310. /******************************************************************************/
  311. VOID
  312. DataXPaste()
  313. {
  314.     PSZ       psz;
  315.     ULONG      ulText;
  316.     register CHAR ch;
  317.  
  318.     if (WinOpenClipbrd( hab))
  319.     {
  320.     ulText = WinQueryClipbrdData( hab, CF_TEXT);
  321.     if (ulText)
  322.     {
  323.         psz = MAKEP( (SEL)ulText, 0);
  324.         while (*psz)
  325.             {
  326.         ch = tolower(*psz);
  327.         if (ch == 'm')
  328.                 {
  329.             psz++;
  330.             switch (tolower(*psz))
  331.                     {
  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;
  347.                     }
  348.                 }
  349.         psz++;
  350.         InterpretChar(ch);
  351.                 UpdateDisplay();
  352.             }
  353.         }
  354.     }
  355.     WinCloseClipbrd( hab);
  356.     InterpretChar('=');
  357.     UpdateDisplay();
  358. }
  359.  
  360.  
  361. /******************************************************************************/
  362. VOID
  363. DataXCopy()
  364. {
  365.     PSZ  pszText;
  366.  
  367.     if (WinOpenClipbrd( hab))
  368.     {
  369.     WinEmptyClipbrd( hab);
  370.     DosAllocSeg( 20, (SEL FAR *)&sel, SEG_GIVEABLE);
  371.         if (sel == NULL) return;
  372.     pszText = MAKEP(sel, 0);
  373.     FarStrcpy( pszText, (PSZ)szreg1);
  374.     WinSetClipbrdData( hab, (ULONG)sel, CF_TEXT, CFI_SELECTOR);
  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. }
  542.