/*------------------------------------------------------------*/ /* */ /* Calc.cpp: TCalcDisplay member functions and TCalculator */ /* constructor */ /* */ /*------------------------------------------------------------*/ /* * Turbo Vision - Version 2.0 * * Copyright (c) 1994 by Borland International * All Rights Reserved. * * Modified by Sergio Sigala * Modified by Max Okumoto */ #define Uses_TRect #define Uses_TEvent #define Uses_TButton #define Uses_TKeys #define Uses_TDrawBuffer #define Uses_TStreamableClass #define Uses_TStreamable #define Uses_TView #define Uses_TDialog #include __link( RView ) __link( RDialog ) __link( RButton ) #include "calc.h" #include #include #include #include #include using std::string; using std::ostringstream; #define cpCalcPalette "\x13" // // TCalcDisplay functions // const char * const TCalcDisplay::name = "TCalcDisplay"; void TCalcDisplay::write( opstream& os ) { TView::write( os ); os.writeBytes(&status, sizeof(status)); os.writeString(number); os.writeByte(sign); os.writeByte(operate); os.writeBytes(&operand, sizeof(operand)); } void *TCalcDisplay::read( ipstream& is ) { TView::read( is ); number = new char[DISPLAYLEN]; is.readBytes(&status, sizeof(status)); is.readString(number, DISPLAYLEN); sign = is.readByte(); operate = is.readByte(); is.readBytes(&operand, sizeof(operand)); return this; } TStreamable *TCalcDisplay::build() { return new TCalcDisplay( streamableInit ); } TStreamableClass RCalcDisplay( TCalcDisplay::name, TCalcDisplay::build, __DELTA(TCalcDisplay) ); TCalcDisplay::TCalcDisplay(TRect& r) : TView ( r ) { options |= ofSelectable; eventMask = (evKeyboard | evBroadcast); number = new char[DISPLAYLEN]; clear(); } TCalcDisplay::~TCalcDisplay() { delete number; } TPalette& TCalcDisplay::getPalette() const { static TPalette palette( cpCalcPalette, sizeof(cpCalcPalette)-1 ); return palette; } void TCalcDisplay::handleEvent(TEvent& event) { TView::handleEvent(event); switch(event.what) { case evKeyboard: calcKey(event.keyDown.charScan.charCode); clearEvent(event); break; case evBroadcast: if(event.message.command == cmCalcButton) { calcKey( ((TButton *) event.message.infoPtr)->title[0]); clearEvent(event); } break; } } void TCalcDisplay::draw() { char color = getColor(1); short i; TDrawBuffer buf; i = (short)(size.x - strlen(number) - 2); buf.moveChar(0, ' ', color, (short)size.x); buf.moveChar(i, sign, color, (short)1 ); buf.moveStr((short)(i+1), number, color); writeLine(0, 0, (short)size.x, 1, buf); } void TCalcDisplay::error() { status = csError; strcpy(number, "Error"); sign = ' '; } void TCalcDisplay::clear() { status = csFirst; strcpy(number, "0"); sign = ' '; operate = '='; } void TCalcDisplay::setDisplay(double r) { string str; ostringstream displayStr(str); if(r < 0.0) { sign = '-'; displayStr << -r << std::ends; } else { displayStr << r << std::ends; sign = ' '; } int len = str.length(); if (len > DISPLAYLEN) error(); else strcpy(number, str.c_str()); } void TCalcDisplay::checkFirst() { if( status == csFirst) { status = csValid; strcpy(number, "0"); sign = ' '; } } void TCalcDisplay::calcKey(unsigned char key) { char stub[2] = " "; double r; key = (unsigned char)toupper(key); if( status == csError && key != 'C') key = ' '; switch(key) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': checkFirst(); if (strlen(number) < 15) { // 15 is max visible display length if (strcmp(number, "0") == 0) number[0] = '\0'; stub[0] = key; strcat(number, stub); } break; case '.': checkFirst(); if(strchr(number, '.') == NULL) { stub[0] = '.'; strcat(number, stub); } break; case 8: case 27: int len; checkFirst(); if( (len = strlen(number)) == 1 ) strcpy(number, "0"); else number[len-1] = '\0'; break; case '_': // underscore (keyboard version of +/-) case 241: // +/- extended character. if (sign==' ') sign='-'; else sign=' '; break; case '+': case '-': case '*': case '/': case '=': case '%': case 13: if(status == csValid) { status = csFirst; r = getDisplay() * ((sign == '-') ? -1.0 : 1.0); if( key == '%' ) { if(operate == '+' || operate == '-') r = (operand * r) / 100; else r /= 100; } switch( operate ) { case '+': setDisplay(operand + r); break; case '-': setDisplay(operand - r); break; case '*': setDisplay(operand * r); break; case '/': if(r == 0) error(); else setDisplay(operand / r); break; } } operate = key; operand = getDisplay() * ((sign == '-') ? -1.0 : 1.0); break; case 'C': clear(); break; } drawView(); } static char *keyChar[20] = { "C", "\x1B", "%", "\xF1", // 0x1B is escape, 0xF1 is +/- char. "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+" }; // // TCalculator functions // const char * const TCalculator::name = "TCalculator"; TStreamable *TCalculator::build() { return new TCalculator( streamableInit ); } TStreamableClass RCalculator( TCalculator::name, TCalculator::build, __DELTA(TCalculator) ); TCalculator::TCalculator() : TDialog( TRect(5, 3, 29, 18), "Calculator" ), TWindowInit( &TCalculator::initFrame ) { TView *tv; TRect r; options |= ofFirstClick; for(int i = 0; i <= 19; i++) { int x = (i%4)*5+2; int y = (i/4)*2+4; r = TRect( x, y, x+5, y+2 ); tv = new TButton( r, keyChar[i], cmCalcButton, bfNormal | bfBroadcast ); tv->options &= ~ofSelectable; insert( tv ); } r = TRect( 3, 2, 21, 3 ); insert( new TCalcDisplay(r) ); }