#include "interfaceconsole.h" #include "smlnode.h" #include "gamestate.h" #include #include PluginInterface3( plugin_interface_console, console, InterfaceConsole, Interface, "Mike Buland", 1, 0 ); using namespace Bu; InterfaceConsole::InterfaceConsole() { } InterfaceConsole::~InterfaceConsole() { } void InterfaceConsole::run( Game *pGame ) { GameState gs( pGame ); gs.init(); while( gs.isRunning() ) { char buf[1024]; sio << sio.nl << "command> " << sio.flush; fgets( buf, 1024, stdin ); gs.execCommand( buf ); } } void InterfaceConsole::appendToken( Bu::String &sCurLine, Bu::String &sNextToken, int &iLineLen, int &iNextLen ) { if( iLineLen + iNextLen + 1 >= 78 ) { sio << sCurLine << sio.nl; iLineLen = 0; sCurLine = sNextToken; } else { sCurLine += sNextToken; } iLineLen += iNextLen + 1; sCurLine += " "; iNextLen = 0; sNextToken.clear(); } Bu::String InterfaceConsole::getVt100Style( const StyleStack &sStyle ) { if( sStyle.isEmpty() ) { return "\x1B[0m"; } int sCurStyle = 0; for( StyleStack::const_iterator i = sStyle.begin(); i; i++ ) { // sio << "Merging in: " << Fmt::hex() << *i << sio.nl; if( ((sCurStyle&stTypeMask) & ((*i)&stTypeMask)) == 0 ) { sCurStyle |= *i; // sio << " -> curStyle = " << Fmt::hex() << *i << sio.nl; } } Bu::String sRet; // sio << "Color: " << Fmt::hex() << sCurStyle << sio.nl; switch( sCurStyle&stColor ) { case stRed: sRet += "\x1B[1;31m"; break; case stGreen: sRet += "\x1B[1;32m"; break; } return sRet; } void InterfaceConsole::display( const SmlNode *pNode ) { Bu::String sCurLine; Bu::String sNextToken; int iLineLen = 0; int iNextLen = 0; int iState = 0; typedef Bu::List NodeStack; NodeStack sNode; StyleStack sStyle; sNode.push( pNode->getChildren().begin() ); for(;;) { if( !sNode.peek() ) { sNode.pop(); if( sNode.isEmpty() ) break; if( sNode.peek() ) { // sio << "Pop'd: " << (*sNode.peek())->getText() << sio.nl; Bu::String sTag = (*sNode.peek())->getText(); if( sTag == "green" || sTag == "red" ) { sStyle.pop(); sNextToken += getVt100Style( sStyle ); } sNode.peek()++; continue; } } if( sNode.isEmpty() ) { break; } const SmlNode *pNode = (*sNode.peek()); switch( pNode->getType() ) { case SmlNode::typeRoot: throw Bu::ExceptionBase("Invalid root."); case SmlNode::typeText: { // sio << "Process text node: " << pNode->getText() << // sio.nl; Bu::String::const_iterator iBgn = pNode->getText().begin(); Bu::String::const_iterator iEnd = iBgn; int iTmpLen = 0; for(;iBgn;) { switch( iState ) { case 0: // begining of paragraph if( iBgn && ( *iBgn == ' ' || *iBgn == '\n' || *iBgn == '\r' || *iBgn == '\t' ) ) { iBgn++; } else { // Here is where you would indent paragraphs iEnd = iBgn; iState = 1; } break; case 1: // non-whitespace if( !iEnd ) { sNextToken.append( iBgn, iEnd ); iBgn = iEnd; iNextLen += iTmpLen; iTmpLen = 0; } else if( *iEnd == ' ' || *iEnd == '\n' || *iEnd == '\r' || *iEnd == '\t' ) { sNextToken.append( iBgn, iEnd ); iNextLen += iTmpLen; iTmpLen = 0; iState = 2; iBgn = iEnd; } else { iEnd++; iTmpLen++; } break; case 2: // Whitespace if( iBgn && (*iBgn == ' ' || *iBgn == '\n' || *iBgn == '\r' || *iBgn == '\t') ) { iBgn++; } else { iEnd = iBgn; iState = 1; appendToken( sCurLine, sNextToken, iLineLen, iNextLen ); } break; } } } break; case SmlNode::typeTag: if( pNode->getChildren().isEmpty() ) { if( pNode->getText() == "break" ) { appendToken( sCurLine, sNextToken, iLineLen, iNextLen ); if( !sCurLine.isEmpty() ) sio << sCurLine << sio.nl; sCurLine.clear(); iLineLen = 0; iState = 0; } } else { // sio << "Push'd: " << pNode->getText() << sio.nl; Bu::String sTag = pNode->getText(); if( sTag == "green" ) { sStyle.push( stGreen ); } else if( sTag == "red" ) { sStyle.push( stRed ); } sNextToken += getVt100Style( sStyle ); sNode.push( pNode->getChildren().begin() ); continue; /* for( SmlNode::SmlNodeList::const_iterator i = pNode->getChildren().begin(); i; i++ ) { s smlToConsole( *i, sCurLine, sNextToken, iLineLen, iState ); } */ } break; } sNode.peek()++; } if( !sNextToken.isEmpty() ) appendToken( sCurLine, sNextToken, iLineLen, iNextLen ); sio << sCurLine << sio.nl; }