home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / c / actlib11 / tvtools / calcul.cpp < prev    next >
C/C++ Source or Header  |  1993-01-14  |  7KB  |  322 lines

  1. #define Uses_TButton
  2. #define Uses_TEvent
  3. #define Uses_TStreamableClass
  4. #define Uses_TView
  5. #define Uses_TCalculator
  6. #include "tvtools.h"
  7. __link( RView )
  8. __link( RDialog )
  9. __link( RButton )
  10.  
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <ctype.h>
  14. #include <strstrea.h>
  15. #include <iomanip.h>
  16.  
  17.  
  18.  
  19. #define cpCalcPalette   "\x13"
  20.  
  21.  
  22. //
  23. // TCalcDisplay functions
  24. //
  25.  
  26. const char * const TCalcDisplay::name = "TCalcDisplay";
  27.  
  28. void TCalcDisplay::write( opstream& os )
  29. {
  30.     TView::write( os );
  31.     os.writeBytes(&status, sizeof(status));
  32.     os.writeString(number);
  33.     os.writeByte(sign);
  34.     os.writeByte(operate);
  35.     os.writeBytes(&operand, sizeof(operand));
  36. }
  37.  
  38.  
  39. void *TCalcDisplay::read( ipstream& is )
  40. {
  41.     TView::read( is );
  42.     number = new char[DISPLAYLEN];
  43.     is.readBytes(&status, sizeof(status));
  44.     is.readString(number, DISPLAYLEN);
  45.     sign = is.readByte();
  46.     operate = is.readByte();
  47.     is.readBytes(&operand, sizeof(operand));
  48.     return this;
  49. }
  50.  
  51.  
  52. TStreamable *TCalcDisplay::build()
  53. {
  54.     return new TCalcDisplay( streamableInit );
  55. }
  56.  
  57.  
  58. TStreamableClass RCalcDisplay( TCalcDisplay::name,
  59.                                TCalcDisplay::build,
  60.                                __DELTA(TCalcDisplay)
  61.                              );
  62.  
  63.  
  64. TCalcDisplay::TCalcDisplay(TRect& r) : TView ( r )
  65. {
  66.     options |= ofSelectable;
  67.     eventMask = (evKeyboard | evBroadcast);
  68.     number = new char[DISPLAYLEN];
  69.     clear();
  70.  
  71. }
  72.  
  73. TCalcDisplay::~TCalcDisplay()
  74. {
  75.    delete number;
  76. }
  77.  
  78. TPalette& TCalcDisplay::getPalette() const
  79. {
  80.     static TPalette palette( cpCalcPalette, sizeof(cpCalcPalette)-1 );
  81.     return palette;
  82. }
  83.  
  84.  
  85. void TCalcDisplay::handleEvent(TEvent& event)
  86. {
  87.     TView::handleEvent(event);
  88.  
  89.     switch(event.what)
  90.         {
  91.         case evKeyboard:
  92.             calcKey(event.keyDown.charScan.charCode);
  93.             clearEvent(event);
  94.             break;
  95.         case evBroadcast:
  96.             if(event.message.command == cmCalcButton)
  97.                 {
  98.                 calcKey( ((TButton *) event.message.infoPtr)->title[0]);
  99.                 clearEvent(event);
  100.                 }
  101.             break;
  102.         }
  103. }
  104.  
  105.  
  106. void TCalcDisplay::draw()
  107. {
  108.     char color = getColor(1);
  109.     int i;
  110.     TDrawBuffer buf;
  111.  
  112.     i = size.x - strlen(number) - 2;
  113.     buf.moveChar(0, ' ', color, size.x);
  114.     buf.moveChar(i, sign, color, 1);
  115.     buf.moveStr(i+1, number, color);
  116.     writeLine(0, 0, size.x, 1, buf);
  117. }
  118.  
  119.  
  120. void TCalcDisplay::error()
  121. {
  122.     status = csError;
  123.     strcpy(number, "Error");
  124.     sign = ' ';
  125. }
  126.  
  127.  
  128. void TCalcDisplay::clear()
  129. {
  130.     status = csFirst;
  131.     strcpy(number, "0");
  132.     sign = ' ';
  133.     operate = '=';
  134. }
  135.  
  136.  
  137. void TCalcDisplay::setDisplay(double r)
  138. {
  139.     int  len;
  140.     char str[64];
  141.     ostrstream displayStr( str, sizeof str );
  142.  
  143.     if(r < 0.0)
  144.         {
  145.         sign = '-';
  146.         displayStr << -r << ends;
  147.         }
  148.     else
  149.         {
  150.         displayStr << r << ends;
  151.         sign = ' ';
  152.         }
  153.  
  154.     len = strlen(str) - 1;          // Minus one so we can use as an index.
  155.  
  156.     if(len > DISPLAYLEN)
  157.         error();
  158.     else
  159.         strcpy(number, str);
  160. }
  161.  
  162.  
  163. void TCalcDisplay::checkFirst()
  164. {
  165.     if( status == csFirst)
  166.         {
  167.         status = csValid;
  168.         strcpy(number, "0");
  169.         sign = ' ';
  170.         }
  171. }
  172.  
  173.  
  174. void TCalcDisplay::calcKey(unsigned char key)
  175. {
  176.     char stub[2] = " ";
  177.     double r;
  178.  
  179.     key = toupper(key);
  180.     if( status == csError && key != 'C')
  181.         key = ' ';
  182.  
  183.     switch(key)
  184.         {
  185.         case '0':   case '1':   case '2':   case '3':   case '4':
  186.         case '5':   case '6':   case '7':   case '8':   case '9':
  187.             checkFirst();
  188.             if (strlen(number) < 15) 
  189.                 {                       // 15 is max visible display length
  190.                 if (strcmp(number, "0") == NULL)
  191.                     number[0] = '\0';
  192.                 stub[0] = key;
  193.                 strcat(number, stub);
  194.                 }
  195.             break;
  196.  
  197.         case '.':
  198.             checkFirst();
  199.             if(strchr(number, '.') == NULL)
  200.                 {
  201.                 stub[0] = '.';
  202.                 strcat(number, stub);
  203.                 }
  204.             break;
  205.  
  206.         case 8:
  207.         case 27:
  208.             int len;
  209.  
  210.             checkFirst();
  211.             if( (len = strlen(number)) == 1 )
  212.                 strcpy(number, "0");
  213.             else
  214.                 number[len-1] = '\0';
  215.             break;
  216.  
  217.         case '_':                   // underscore (keyboard version of +/-)
  218.         case 241:                   // +/- extended character.
  219.             sign = (sign == ' ') ? '-' : ' ';
  220.             break;
  221.  
  222.         case '+':   case '-':   case '*':   case '/':
  223.         case '=':   case '%':   case 13:
  224.             if(status == csValid)
  225.                 {
  226.                 status = csFirst;
  227.                 r = getDisplay() * ((sign == '-') ? -1.0 : 1.0);
  228.                 if( key == '%' )
  229.                     {
  230.                     if(operate == '+' || operate == '-')
  231.                         r = (operand * r) / 100;
  232.                     else
  233.                         r /= 100;
  234.                     }
  235.                 switch( operate )
  236.                     {
  237.                     case '+':
  238.                         setDisplay(operand + r);
  239.                         break;
  240.  
  241.                     case '-':
  242.                         setDisplay(operand - r);
  243.                         break;
  244.  
  245.                     case '*':
  246.                         setDisplay(operand * r);
  247.                         break;
  248.  
  249.                     case '/':
  250.                         if(r == 0)
  251.                             error();
  252.                         else
  253.                             setDisplay(operand / r);
  254.                         break;
  255.  
  256.                     }
  257.                 }
  258.             operate = key;
  259.             operand = getDisplay() * ((sign == '-') ? -1.0 : 1.0);
  260.             break;
  261.  
  262.         case 'C':
  263.             clear();
  264.             break;
  265.  
  266.         }
  267.     drawView();
  268. }
  269.  
  270.  
  271.  
  272. static char *keyChar[20] =
  273.     {    "C", "\x1B",    "%", "\xF1",   // 0x1B is escape, 0xF1 is +/- char.
  274.          "7",    "8",    "9",    "/",
  275.          "4",    "5",    "6",    "*",
  276.          "1",    "2",    "3",    "-",
  277.          "0",    ".",    "=",    "+"
  278.     };
  279.  
  280.  
  281. //
  282. // TCalculator functions
  283. //
  284.  
  285. const char * const TCalculator::name = "TCalculator";
  286.  
  287. TStreamable *TCalculator::build()
  288. {
  289.     return new TCalculator( streamableInit );
  290. }
  291.  
  292.  
  293. TStreamableClass RCalculator( TCalculator::name,
  294.                               TCalculator::build,
  295.                               __DELTA(TCalculator)
  296.                             );
  297.  
  298.  
  299. TCalculator::TCalculator() :
  300.     TDialog( TRect(5, 3, 29, 18), "Calculator" ),
  301.     TWindowInit( &TCalculator::initFrame )
  302. {
  303.     TView *tv;
  304.     TRect r;
  305.  
  306.     options |= ofFirstClick;
  307.  
  308.     for(int i = 0; i <= 19; i++)
  309.         {
  310.         int x = (i%4)*5+2;
  311.         int y = (i/4)*2+4;
  312.         r = TRect( x, y, x+5, y+2 );
  313.  
  314.         tv = new TButton( r, keyChar[i], cmCalcButton, bfNormal | bfBroadcast );
  315.         tv->options &= ~ofSelectable;
  316.         insert( tv );
  317.         }
  318.     r = TRect( 3, 2, 21, 3 );
  319.     insert( new TCalcDisplay(r) );
  320. }
  321.  
  322.