home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 2.ddi / TVDEMOS.ZIP / CALC.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  7.8 KB  |  336 lines

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