#include "smlrenderervt100.h" #include "smlnode.h" SmlRendererVt100::SmlRendererVt100() { } SmlRendererVt100::~SmlRendererVt100() { } void SmlRendererVt100::appendToken( Bu::Formatter &f, Bu::String &sCurLine, Bu::String &sNextToken, int &iLineLen, int &iNextLen ) { if( iLineLen + iNextLen + 1 >= 78 ) { f << sCurLine << f.nl; iLineLen = 0; sCurLine = sNextToken; } else { sCurLine += sNextToken; } iLineLen += iNextLen + 1; sCurLine += " "; iNextLen = 0; sNextToken.clear(); } Bu::String SmlRendererVt100::getStyle( const StyleStack &sStyle ) { #ifdef WIN32 // Windows...we don't do colors for windows... return ""; #endif if( sStyle.isEmpty() ) { return "\x1B[0m"; } int sCurStyle = 0; for( StyleStack::const_iterator i = sStyle.begin(); i; i++ ) { // f << "Merging in: " << Fmt::hex() << *i << f.nl; if( ((sCurStyle&stTypeMask) & ((*i)&stTypeMask)) == 0 ) { sCurStyle |= *i; // f << " -> curStyle = " << Fmt::hex() << *i << f.nl; } } Bu::String sRet; // f << "Color: " << Fmt::hex() << sCurStyle << f.nl; switch( sCurStyle&stColor ) { case stRed: sRet += "\x1B[1;31m"; break; case stGreen: sRet += "\x1B[1;32m"; break; case stYellow: sRet += "\x1B[1;33m"; break; case stBlue: sRet += "\x1B[1;34m"; break; case stMagenta: sRet += "\x1B[1;35m"; break; case stCyan: sRet += "\x1B[1;36m"; break; case stWhite: sRet += "\x1B[1;37m"; break; } return sRet; } SmlRendererVt100::Style SmlRendererVt100::strToStyle( const Bu::String &sTag ) { if( sTag == "green" ) { return stGreen; } else if( sTag == "red" ) { return stRed; } else if( sTag == "yellow" ) { return stYellow; } else if( sTag == "blue" ) { return stBlue; } else if( sTag == "magenta" ) { return stMagenta; } else if( sTag == "cyan" ) { return stCyan; } else if( sTag == "white" ) { return stWhite; } else { return stNone; } } void SmlRendererVt100::render( Bu::Formatter &f, 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() ) { // f << "Pop'd: " << (*sNode.peek())->getText() << f.nl; Bu::String sTag = (*sNode.peek())->getText(); Style s = strToStyle( sTag ); if( sStyle.peek() == s ) { sStyle.pop(); sNextToken += getStyle( sStyle ); } else { throw Bu::ExceptionBase("Close tag doesn't match open tag."); } 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: { // f << "Process text node: " << pNode->getText() << // f.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 iNextLen += 4; sNextToken += " "; 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( f, sCurLine, sNextToken, iLineLen, iNextLen ); } break; } } } break; case SmlNode::typeTag: if( pNode->getChildren().isEmpty() ) { if( pNode->getText() == "break" ) { appendToken( f, sCurLine, sNextToken, iLineLen, iNextLen ); if( !sCurLine.isEmpty() ) f << sCurLine << f.nl; sCurLine.clear(); iLineLen = 0; iState = 0; } } else { // f << "Push'd: " << pNode->getText() << f.nl; Bu::String sTag = pNode->getText(); Style s = strToStyle( sTag ); if( s != 0 ) sStyle.push( s ); sNextToken += getStyle( 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( f, sCurLine, sNextToken, iLineLen, iNextLen ); f << sCurLine << f.nl; }