home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv8.zip / VACPP / IBMCPP / samples / VISBUILD / CALCULAT / CPPOV13 / ICALCPU.CPP < prev    next >
Text File  |  1995-04-17  |  8KB  |  297 lines

  1. //****************************************************************************
  2. // ICalcPU Class - C++ Code File (icalcpu.cpp)                               *
  3. //                                                                           *
  4. // COPYRIGHT: Copyright (C) International Business Machines Corp., 1994,1995 *
  5. //                                                                           *
  6. // DISCLAIMER OF WARRANTIES:                                                 *
  7. //   The following [enclosed] code is sample code created by IBM             *
  8. //   Corporation.  This sample code is not part of any standard IBM product  *
  9. //   and is provided to you solely for the purpose of assisting you in the   *
  10. //   development of your applications.  The code is provided "AS IS",        *
  11. //   without warranty of any kind.  IBM shall not be liable for any damages  *
  12. //   arising out of your use of the sample code, even if they have been      *
  13. //   advised of the possibility of such damages.                             *
  14. //****************************************************************************
  15. //NOTE: WE RECOMMEND USING A FIXED-SPACE FONT TO LOOK AT THE SOURCE.
  16. //
  17. //
  18. // VERSION 2
  19. //
  20. // Changes:
  21. //   9/23/94 - Put in changes to get results of math computations via a return
  22. //             value on a connection.  This also allows for connecting in some
  23. //             exception handling.
  24. //****************************************************************************
  25.  
  26. #include <stdio.h>                    //for sprintf
  27. #include "icalcpu.hpp"                //ICalcPU header
  28. #include "icalcop.hpp"                //ICalcOperator header
  29. #include "icalcfnc.hpp"               //ICalcFunction header
  30. #include <inotifev.hpp>
  31.  
  32. //
  33. // Events
  34. //
  35.  
  36. INotificationId ICalcPU :: bufferId = "ICalcPU::buffer";
  37. INotificationId ICalcPU :: evaluateId = "ICalcPU::evaluate";
  38.  
  39. /*******************************************************************
  40.  * Contructors/Destructors
  41.  *******************************************************************/
  42.  
  43. ICalcPU :: ICalcPU() :
  44.         dBuffer(""),
  45.         dCurrentReg(none),
  46.         dR2SetFromDisplay(false),
  47.         dExpectNewOperand(false),
  48.         dPendingOp(0)
  49. {
  50. }
  51.  
  52. ICalcPU :: ~ICalcPU()
  53. {
  54. }
  55.  
  56. /*******************************************************************
  57.  * Access Member Functions (Part Actions)
  58.  *******************************************************************/
  59.  
  60. //
  61. // The Buffer attribute represents calculator display
  62. //
  63.  
  64. IString ICalcPU :: buffer () const
  65. {
  66.   return dBuffer;
  67. }
  68.  
  69.  
  70. ICalcPU & ICalcPU :: setBuffer
  71.   (const char * iBuffer)
  72. {
  73.  
  74.   if (dBuffer != iBuffer)
  75.   {
  76.     dBuffer = iBuffer;                  //Set class.attribute
  77.     notifyObservers(INotificationEvent(bufferId,*this));
  78.   }
  79.  
  80.   return *this;
  81.  
  82. }
  83.  
  84.  
  85. /*******************************************************************
  86.  * Implementor Member Functions (Part Actions)
  87.  *******************************************************************/
  88.  
  89.  
  90. //
  91. // Process each digit input to the PU
  92. //
  93.  
  94. ICalcPU & ICalcPU :: processDigit (IString iCurrentDigit)
  95. {
  96.   IString tempString;
  97.  
  98.   //
  99.   // If expecting a new input number or if the display has been cleared,
  100.   // start a new number. Otherwise get the current buffer contents and
  101.   // add the new digit to what is already there.
  102.   //
  103.  
  104.   if (dExpectNewOperand || dBuffer == "")
  105.   {
  106.      tempString = "";
  107.      dExpectNewOperand = false;
  108.   }
  109.  
  110.   else tempString = dBuffer;
  111.  
  112.   tempString += iCurrentDigit;   // Add to the current buffer contents
  113.   setBuffer(tempString);         // Want event, bufferId(), to get
  114.                                  //   signalled, so call set to display.
  115.   return *this;
  116.  
  117. }
  118.  
  119.  
  120. //
  121. // Process each binary operator key input to the PU
  122. //
  123.  
  124. ICalcPU & ICalcPU :: processOperator (ICalcOperator *iCurrentOp)
  125. {
  126.  
  127.   //
  128.   // Set display contents into the current register.
  129.   // If the current register is register 2, evaluate the pending
  130.   // operation.
  131.   // Set the current operation as the pending operation and wait for
  132.   // a new operand to be entered.
  133.   //
  134.  
  135.   setCurrentRegFromDisplay ();
  136.  
  137.   if (dCurrentReg == R2) evaluateIt();
  138.  
  139.   dPendingOp = iCurrentOp;
  140.   dExpectNewOperand = true;
  141.   return *this;
  142.  
  143. }
  144.  
  145.  
  146. //
  147. // Process the results of any binary operation.
  148. //
  149.  
  150. ICalcPU & ICalcPU :: processOperatorResult (double iAccumulator)
  151. {
  152.  
  153.   //
  154.   // Get the result of come operation, set it into register 1,
  155.   // display the results,and wait for the next operand to be entered.
  156.   //
  157.  
  158.   dCurrentReg = R1;
  159.   dRegisters[dCurrentReg] = iAccumulator;
  160.   dExpectNewOperand = true;
  161.   setDisplayFromAccumulator(iAccumulator);
  162.   return *this;
  163.  
  164. }
  165.  
  166.  
  167. //
  168. // Process each function key input to the PU
  169. //
  170.  
  171. ICalcPU & ICalcPU :: processFunction (ICalcFunction *iCurrentFunc)
  172. {
  173.  
  174.   //
  175.   // Invoke the specified unary function
  176.   //
  177.  
  178.   iCurrentFunc->perform(*this);
  179.   return *this;
  180.  
  181. }
  182.  
  183.  
  184. //
  185. // Evaluate any pending binary operation
  186. //
  187.  
  188. double ICalcPU :: evaluateOperation ()
  189. {
  190.  
  191.   //
  192.   // Invoke the pending operation
  193.   //
  194.  
  195.   return dPendingOp->evaluate (dRegisters[R1], dRegisters[R2]);
  196.  
  197. }
  198.  
  199.  
  200. //
  201. // Clear the calculator PU
  202. //
  203.  
  204. ICalcPU & ICalcPU :: clearCalc ()
  205. {
  206.  
  207.   setBuffer("");
  208.   dCurrentReg = none;
  209.   dExpectNewOperand = false;
  210.   dR2SetFromDisplay = false;  //reinit R2 has been set flag
  211.   dRegisters[R1] = 0;
  212.   dRegisters[R2] = 0;
  213.  
  214.   return *this;
  215.  
  216. }
  217.  
  218.  
  219. /*******************************************************************
  220.  * Implementor Member Functions (not Part Actions)
  221.  *******************************************************************/
  222.  
  223. ICalcPU & ICalcPU :: evaluateOperator ()
  224. {
  225.  
  226.    setCurrentRegFromDisplay ();
  227.  
  228.    if (dR2SetFromDisplay) evaluateIt();
  229.  
  230.    dExpectNewOperand = true;
  231.    return *this;
  232.  
  233. }
  234.  
  235.  
  236. /*******************************************************************
  237.  * Helping Member Functions (Not Part Actions)
  238.  *******************************************************************/
  239.  
  240. ICalcPU & ICalcPU :: evaluateIt ()
  241. {
  242.    notifyObservers(INotificationEvent(evaluateId,*this));
  243.    return *this;
  244. }
  245.  
  246.  
  247. ICalcPU & ICalcPU ::
  248.   setDisplayFromAccumulator (double iAccumulator)
  249. {
  250.   char tempString[20];
  251.   signed long tempAccum = iAccumulator;
  252.  
  253.   //
  254.   // Convert the accumulator value to a string and display it
  255.   //
  256.  
  257.   if (iAccumulator != tempAccum)
  258.      sprintf(tempString, "%f", iAccumulator);
  259.  
  260.   else
  261.      sprintf(tempString, "%d", tempAccum);
  262.  
  263.   setBuffer ( tempString );             //want the event, bufferId(),
  264.                                         //to be signalled, so call set
  265.   return *this;
  266.  
  267. }
  268.  
  269.  
  270. ICalcPU & ICalcPU ::
  271.   setCurrentRegFromDisplay ()           
  272. {
  273.  
  274.   /*****************************************************************
  275.    * As a precaution, only set the current register if dBuffer,
  276.    * which represents the calculator display, is not a nullstring.
  277.    * NOTE:  dBuffer should never be a nullstring as long as the
  278.    *        entry field that maps to it (i.e., that represents
  279.    *        the calculator display) is always a display-only field.
  280.    *****************************************************************/
  281.  
  282.   if (dBuffer.size() && !dExpectNewOperand)
  283.   {
  284.      dRegisters[++dCurrentReg] = dBuffer.asDouble();
  285.  
  286.      if ((dCurrentReg == R2) && (!dR2SetFromDisplay)) 
  287.      {
  288.         dR2SetFromDisplay = true;
  289.      }
  290.  
  291.   }
  292.  
  293.   return *this;
  294.  
  295. }
  296.  
  297.