#include "Text.hpp" Text::Text( const char * t, int s, GXColor c ) : GuiText( t, s, c ) { maxWidth = 400; linestodraw = 9; curLineStart = 0; FirstLineOffset = 0; wText = NULL; if ( !text ) return; wText = new ( std::nothrow ) wString( text ); if ( !wText ) { return; } if ( wText->size() == 0 ) { wText->push_back( L' ' ); wText->push_back( 0 ); } textWidth = ( font ? font : fontSystem )->getWidth( wText->data(), currentSize ); delete [] text; text = NULL; SetMaxWidth( maxWidth ); } Text::Text( const wchar_t * t, int s, GXColor c ) : GuiText( ( wchar_t * ) NULL, s, c ) { maxWidth = 400; linestodraw = 9; curLineStart = 0; FirstLineOffset = 0; wText = NULL; if ( !t ) return; wText = new ( std::nothrow ) wString( t ); if ( !wText ) { return; } if ( wText->size() == 0 ) { wText->push_back( L' ' ); wText->push_back( 0 ); } textWidth = ( font ? font : fontSystem )->getWidth( wText->data(), currentSize ); SetMaxWidth( maxWidth ); } Text::~Text() { if ( wText ) delete wText; wText = NULL; TextLines.clear(); ClearDynamicText(); } void Text::SetText( const char * t ) { wchar_t * tmp = charToWideChar( t ); if ( !tmp ) return; if ( wText ) delete wText; wText = new ( std::nothrow ) wString( tmp ); if ( !wText ) { return; } if ( wText->size() == 0 ) { wText->push_back( L' ' ); wText->push_back( 0 ); } textWidth = ( font ? font : fontSystem )->getWidth( wText->data(), currentSize ); delete [] tmp; ClearDynamicText(); CalcLineOffsets(); } void Text::SetText( const wchar_t * t ) { if ( !t ) return; if ( wText ) delete wText; wText = new wString( t ); textWidth = ( font ? font : fontSystem )->getWidth( wText->data(), currentSize ); CalcLineOffsets(); } void Text::SetMaxWidth( int w ) { maxWidth = w; curLineStart = 0; Refresh(); } void Text::SetTextLine( int line ) { if ( line < 0 ) line = 0; else if ( line > ( int ) TextLines.size() - 1 ) line = TextLines.size() - 1; curLineStart = line; FillRows(); while ( ( int ) textDyn.size() < linestodraw && curLineStart > 0 ) { PreviousLine(); } } void Text::SetTextPos( int pos ) { if ( !wText ) return; int diff = 10000; for ( u32 i = 0; i < TextLines.size(); i++ ) { int curDiff = abs( TextLines[i].LineOffset - pos ); if ( curDiff < diff ) { diff = curDiff; curLineStart = i; } } FillRows(); while ( ( int ) textDyn.size() < linestodraw && curLineStart > 0 ) { PreviousLine(); } } const wchar_t * Text::GetText() { return wText->c_str(); } std::string Text::GetUTF8String( void ) const { return wText->toUTF8(); } int Text::GetLineOffset( int ind ) { if ( TextLines.size() == 0 ) return 0; if ( ind < 0 ) return TextLines[0].LineOffset; if ( ind >= ( int ) TextLines.size() - 1 ) return TextLines[TextLines.size()-1].LineOffset; return TextLines[ind].LineOffset; } const wchar_t * Text::GetTextLine( int ind ) { if ( filling || textDyn.size() == 0 ) return NULL; if ( ind < 0 ) return textDyn[0]; if ( ind >= ( int ) textDyn.size() ) return textDyn[textDyn.size()-1]; return textDyn[ind]; } void Text::Refresh() { CalcLineOffsets(); FillRows(); } void Text::NextLine() { if ( !wText || ( curLineStart + 1 > ( ( int ) TextLines.size() - linestodraw ) ) ) return; ++curLineStart; FillRows(); } void Text::PreviousLine() { if ( !wText || curLineStart - 1 < 0 ) return; --curLineStart; FillRows(); } void Text::FillRows() { if ( !wText ) return; filling = true; ClearDynamicText(); for ( int i = 0; i < linestodraw && i < ( int ) TextLines.size(); i++ ) { if ( i >= ( int ) textDyn.size() ) { textDyn.resize( i + 1 ); textDyn[i] = new wchar_t[maxWidth]; } int offset = TextLines[curLineStart+i].LineOffset; int count = TextLines[curLineStart+i].CharCount + 1; for ( int n = 0; n < count && offset + n < ( int ) wText->size(); n++ ) textDyn[i][n] = wText->at( offset + n ); textDyn[i][count] = 0; } filling = false; return; } void Text::CalcLineOffsets() { if ( !wText ) return; TextLines.clear(); TextLine TmpLine; TmpLine.CharCount = 0; TmpLine.LineOffset = 0; TmpLine.width = 0; const wchar_t * origTxt = wText->c_str(); int ch = 0; int lastSpace = -1; int lastSpaceIndex = -1; int currWidth = 0; int i = 0; while ( origTxt[ch] ) { currWidth += fontSystem->getCharWidth( origTxt[ch], currentSize, ch > 0 ? origTxt[ch-1] : 0x0000 ); if ( currWidth >= maxWidth ) { if ( lastSpace > 0 ) { ch = lastSpace; } TmpLine.CharCount = ch - TmpLine.LineOffset; TmpLine.width = currWidth; TextLines.push_back( TmpLine ); currWidth = 0; lastSpace = -1; i = -1; TmpLine.LineOffset = ch + 1; } else if ( origTxt[ch] == '\n' ) { TmpLine.CharCount = ch - TmpLine.LineOffset; TmpLine.width = currWidth; TextLines.push_back( TmpLine ); currWidth = 0; lastSpace = -1; i = -1; TmpLine.LineOffset = ch + 1; } else if ( origTxt[ch] == ' ' ) { lastSpace = ch; lastSpaceIndex = i; } ch++; i++; } TmpLine.CharCount = ch - TmpLine.LineOffset; TmpLine.width = currWidth; if ( TmpLine.CharCount > 0 ) TextLines.push_back( TmpLine ); } void Text::Draw() { if ( textDyn.size() == 0 ) return; if ( !this->IsVisible() ) return; GXColor c = color; c.a = this->GetAlpha(); int newSize = size * GetScale(); if ( newSize != currentSize ) { currentSize = newSize; if ( wText ) textWidth = ( font ? font : fontSystem )->getWidth( wText->data(), currentSize ); } u16 lineheight = newSize + 6; for ( u32 i = 0; i < textDyn.size(); i++ ) { if ( !filling ) ( font ? font : fontSystem )->drawText( this->GetLeft(), this->GetTop() + i*lineheight, 0, textDyn[i], currentSize, c, style, 0, maxWidth ); } }