#include "TextFeld.h" #include "Schrift.h" #include "Text.h" #include "AlphaFeld.h" #include "Rahmen.h" #include "Bild.h" #include "TastaturEreignis.h" #include "MausEreignis.h" #include "Fenster.h" #include "Scroll.h" #include #include "Globals.h" #include "ToolTip.h" #include "Scroll.h" using namespace Framework; bool TextFeld::TextStyle::operator==( const TextStyle &rhs ) { return fontSize == rhs.fontSize && fontColor == rhs.fontColor && selectedColor == rhs.selectedColor && selectedBackcroundColor == rhs.selectedBackcroundColor && underlined == rhs.underlined && selected == rhs.selected && interactParam == rhs.interactParam && rendererIndex == rhs.rendererIndex; } TextFeld::TextStyleManager::TextStyleManager() : ReferenceCounter(), renderer( new RCArray< TextRenderer >() ), index( 0 ), styleIndex( 0 ), text( 0 ) { current.beginIndex = 0; current.fontColor = 0xFFFFFFFF; current.fontSize = 12; current.selected = 0; current.selectedColor = 0xFFFFFFFF; current.selectedBackcroundColor = 0xFF0000FF; current.underlined = 0; current.interactParam = 0; current.rendererIndex = 0; textStyle.add( current ); } TextFeld::TextStyleManager::~TextStyleManager() { if( renderer ) renderer->release(); if( text ) text->release(); } // Setzt den Style eines Textabschnittes // begin: die startposition des Abschnittes // end: die endposition des Abschnittes (nicht enthalten) void TextFeld::TextStyleManager::setTextStyle( int begin, int end, TextFeld::TextStyle style ) { if( begin < 0 || begin > end || begin > text->getLength() ) return; int sc = textStyle.getEintragAnzahl(); int index = -1; TextStyle s = textStyle.get( 0 ); // suche bis zur richtigen stelle im stylearray for( int i = 0; i < sc; i++ ) { if( textStyle.get( i ).beginIndex >= begin ) { index = i; if( textStyle.get( i ).beginIndex > begin ) s = textStyle.get( i - 1 ); else { s = textStyle.get( i ); textStyle.remove( i ); sc--; } break; } } style.beginIndex = begin; s.beginIndex = end; if( index < 0 ) { // hinten an styles anfügen textStyle.add( style ); textStyle.add( s ); } else { // in die mitte des style arrays einfügen textStyle.add( style, index ); for( int i = index + 1; i < sc + 1; i++ ) { // styles entfernen die überschrieben wurden if( textStyle.get( i ).beginIndex <= end && textStyle.get( i ).beginIndex > begin ) { s = textStyle.get( i ); textStyle.remove( i ); i--; sc--; } } s.beginIndex = end; textStyle.add( s, index + 1 ); } cleanupStyles(); } // Entfernt einen Textabschnitt // begin: der index des ersten betroffenen zeichens // end: der index des ersten zeichens nach dem abschnitt void TextFeld::TextStyleManager::removeText( int begin, int end ) { int sc = textStyle.getEintragAnzahl(); for( int i = 1; i < sc; i++ ) { TextStyle s = textStyle.get( i ); if( s.beginIndex >= begin && s.beginIndex < end ) { textStyle.remove( i ); i--; sc--; } if( s.beginIndex >= end ) { s.beginIndex -= end - begin; textStyle.set( s, i ); } } text->remove( begin, end ); cleanupStyles(); } // Fügt ein Text an einer bestimmten Position ein // pos: die position des neuen Textausschnitts // text: der neue Text void TextFeld::TextStyleManager::insertText( int pos, const char *text ) { int len = textLength( text ); this->text->insert( pos, text ); int sc = textStyle.getEintragAnzahl(); for( int i = 0; i < sc; i++ ) { TextStyle s = textStyle.get( i ); if( s.beginIndex > pos ) { s.beginIndex += len; textStyle.set( s, i ); } } cleanupStyles(); } // Entfernt nicht benötiegte gleiche styles void TextFeld::TextStyleManager::cleanupStyles() { int sc = textStyle.getEintragAnzahl(); TextStyle last = textStyle.get( 0 ); for( int i = 1; i < sc; i++ ) { if( textStyle.get( i ).beginIndex == last.beginIndex ) { last = textStyle.get( i ); textStyle.remove( i - 1 ); i--; sc--; continue; } if( textStyle.get( i ) == last || ( text && textStyle.get( i ).beginIndex > text->getLength() ) ) { textStyle.remove( i ); i--; sc--; } else last = textStyle.get( i ); } } // gibt eine referenz auf das style objekt zurück TextFeld::TextStyle &TextFeld::TextStyleManager::currentStyle() { return current; } // gibt den aktuellen text renderer zurück TextRenderer *TextFeld::TextStyleManager::zCurrentRenderer() { TextRenderer *tr = renderer->z( current.rendererIndex ); if( !tr ) tr = renderer->z( 0 ); if( tr ) tr->setSchriftSize( current.fontSize ); return tr; } // ändert den inhalt des style objektes auf den style des nächsten zeichens bool TextFeld::TextStyleManager::nextStyle() { index++; if( textStyle.getEintragAnzahl() > styleIndex + 1 && index >= textStyle.get( styleIndex + 1 ).beginIndex ) current = textStyle.get( styleIndex++ + 1 ); return text && index < text->getLength(); } // ändert den inhalt des style objektes auf den style des angegebenen zeichens // index: der Index des Zeichens zu dem gesprungen werden soll // gibt 0 zurück falls es das zeichen nicht gibt bool TextFeld::TextStyleManager::stepTo( int index ) { resetIteration(); while( this->index < index && nextStyle() ); return text && this->index == index; } // ändert den inhalt des style objektes auf den style des ersten zeichens void TextFeld::TextStyleManager::resetIteration() { index = 0; styleIndex = 0; current = textStyle.get( 0 ); } // Gibt den Style eines bestimmten zeichens zurück // index: Der index des Zeichensf TextFeld::TextStyle TextFeld::TextStyleManager::getTextStyle( int index ) const { TextStyle last = textStyle.get( 0 ); int ind = 0; for( auto i = textStyle.getIterator(); i && ind <= index; ind++ ) { if( i._.beginIndex <= ind ) { last = i; i++; } } return last; } // Inhalt der TextFeld Klasse aus TextFeld.h // Konstruktor TextFeld::TextFeld() : ZeichnungHintergrund(), tm( new TextStyleManager() ), showChar( 0 ), cpos( 0 ), tickVal( 0 ), mausKlick( 0 ) { charEvent = 0; horizontalScrollBar = new HScrollBar(); vertikalScrollBar = new VScrollBar(); this->setMausEreignis( _ret1ME ); this->setTastaturEreignis( _ret1TE ); } // Destruktor TextFeld::~TextFeld() { tm->release(); } void TextFeld::doMausEreignis( MausEreignis &me, bool userRet ) // Maus Ereignis { if( !userRet ) return; if( hatStyleNicht( Style::Editierbar ) ) { int rbr = 0; if( rahmen ) rbr = rahmen->getRBreite(); if( ( ( vertikalScrollBar && hatStyle( Style::VScroll ) ) || ( horizontalScrollBar && hatStyle( Style::HScroll ) ) ) && me.mx > rbr && me.mx < gr.x - rbr && me.my > rbr && me.my < gr.y - rbr ) { me.verarbeitet |= vertikalScrollBar->doMausMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me ); me.verarbeitet |= horizontalScrollBar->doMausMessage( rbr, gr.y - rbr * 2 - 15, gr.x - rbr * 2 - ( ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? 15 : 0 ), 15, me ); } if( me.mx >= 0 && me.mx <= gr.x && me.my >= 0 && me.my <= gr.y && !me.verarbeitet && hatStyle( Style::Sichtbar ) ) { int scrollHi = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? vertikalScrollBar->getScroll() : 0; int scrollBr = ( horizontalScrollBar && hatStyle( Style::HScroll ) ) ? horizontalScrollBar->getScroll() : 0; int xxx = me.mx - rbr + scrollBr; int yyy = me.my - rbr + scrollHi; int mausChar = getTextIndexAt( xxx, yyy ); if( mausChar >= 0 ) { TextStyle s = tm->getTextStyle( mausChar ); if( charEvent && s.interactParam ) charEvent( mausChar, s.interactParam, me ); } if( charEvent ) me.verarbeitet = 1; } mausKlick = 0; return; } if( !me.verarbeitet ) { if( hatStyleNicht( Style::Fokus ) ) { mausKlick = 0; if( me.id == Framework::ME_PLinks ) addStyle( Style::Fokus ); } int rbr = 0; if( rahmen ) rbr = rahmen->getRBreite(); if( vertikalScrollBar && hatStyle( Style::VScroll ) ) { if( vertikalScrollBar->doMausMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me ) ) { me.verarbeitet = 1; return; } } if( horizontalScrollBar && hatStyle( Style::HScroll ) ) { if( horizontalScrollBar->doMausMessage( rbr, gr.y - rbr - 15, gr.x - rbr * 2 - ( ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? 15 : 0 ), 15, me ) ) { me.verarbeitet = 1; return; } } bool shift = TastenStand[ T_Shift ]; bool strg = TastenStand[ T_Strg ]; int tbr = getTextWidth(); int thi = getTextHeight(); int scrollHi = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? vertikalScrollBar->getScroll() : 0; int scrollBr = ( horizontalScrollBar && hatStyle( Style::HScroll ) ) ? horizontalScrollBar->getScroll() : 0; int xxx = me.mx - rbr + scrollBr; int yyy = me.my - rbr + scrollHi; int mausChar = getTextIndexAt( xxx, yyy ); int scrollBreite = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) * 15; int scrollHeight = ( horizontalScrollBar && hatStyle( Style::HScroll ) ) * 15; if( hatStyle( Style::HCenter ) ) xxx -= ( ( ( gr.x - scrollBreite ) / 2 ) - tbr / 2 ) - rbr; if( hatStyle( Style::VCenter ) && hatStyleNicht( Style::VScroll ) ) yyy -= ( ( ( gr.y - scrollHeight ) / 2 ) - thi / 2 ) - rbr; if( mausChar >= 0 ) { TextStyle s = tm->getTextStyle( mausChar ); if( charEvent ) charEvent( mausChar, s.interactParam, me ); } if( me.mx < gr.x - rbr - 15 ) { if( tm->renderer ) { int ncpos = getCurserPosAt( xxx, yyy ); if( me.id == Framework::ME_PLinks ) { if( ncpos != -1 ) { if( shift && cpos != ncpos ) addAuswahl( MIN( cpos, ncpos ), MAX( cpos, ncpos ) ); else if( !shift && !mausKlick && !strg ) deselectAuswahl(); cpos = ncpos; rend = 1; if( vertikalScrollBar && hatStyle( Style::VScroll ) ) updateVScroll(); if( horizontalScrollBar && hatStyle( Style::HScroll ) ) updateHScroll(); } mausKlick = 1; } if( me.id == ME_Bewegung && mausKlick ) { if( ncpos != -1 ) { rend = 1; if( cpos != ncpos ) invertAuswahl( MIN( cpos, ncpos ), MAX( cpos, ncpos ) ); cpos = ncpos; if( vertikalScrollBar && hatStyle( Style::VScroll ) ) updateVScroll( cpos ); if( horizontalScrollBar && hatStyle( Style::HScroll ) ) updateHScroll( cpos ); } } if( me.id == ME_RLinks ) { if( ncpos != -1 ) { rend = 1; if( cpos != ncpos ) invertAuswahl( MIN( cpos, ncpos ), MAX( cpos, ncpos ) ); cpos = ncpos; if( vertikalScrollBar && hatStyle( Style::VScroll ) ) updateVScroll( cpos ); if( horizontalScrollBar && hatStyle( Style::HScroll ) ) updateHScroll( cpos ); } mausKlick = 0; } } } } me.verarbeitet = 1; } int TextFeld::getTextHeight() const { if( !tm || !tm->text ) return 0; tm->resetIteration(); int th = 0; int len = tm->text->getLength(); char *text = tm->text->getText(); int max = 0; int abstand = 0; for( int i = 0; i < len; i++ ) { if( text[ i ] == '\n' ) { th += max + abstand; abstand = 0; max = 0; tm->nextStyle(); continue; } TextRenderer *r = tm->zCurrentRenderer(); if( r ) { int tmp = r->getZeilenHeight(); max = max >= tmp ? max : tmp; if( max == tmp ) abstand = r->getZeilenAbstand(); } tm->nextStyle(); } if( max > 0 ) th += max; return th; } int TextFeld::getTextWidth() const { if( !tm || !tm->text ) return 0; tm->resetIteration(); int maxBr = 0; int len = tm->text->getLength(); char *text = tm->text->getText(); int lineBr = 0; char buff[] = { 0,0 }; for( int i = 0; i < len; i++ ) { buff[ 0 ] = text[ i ]; if( text[ i ] == '\n' ) { maxBr = maxBr >= lineBr ? maxBr : lineBr; lineBr = 0; tm->nextStyle(); continue; } TextRenderer *r = tm->zCurrentRenderer(); if( r ) lineBr += r->getTextBreite( buff ); tm->nextStyle(); } if( lineBr > 0 ) maxBr = maxBr >= lineBr ? maxBr : lineBr; return maxBr; } // charEvent: eine funktion die aufgerufen wird, wenn sich die maus auf einem bestimmten zeichen befindet und der interactParam im style != 0 ist // aufruf: charEvent( charIndex, interactParam, mausEreignis ); void TextFeld::setCharEvent( std::function< void( int, int, MausEreignis me ) > charEvent ) { this->charEvent = charEvent; } void TextFeld::setText( Text *txt ) // setzt den angezeigten Text { lockZeichnung(); if( !tm->text ) tm->text = new Text(); tm->text->setText( txt ); if( hatStyle( Style::VScroll ) ) updateVScroll(); if( hatStyle( Style::HScroll ) ) updateHScroll(); unlockZeichnung(); rend = 1; } void TextFeld::setTextZ( Text *txt ) // setzt einen Zeiger zum angezeigten Text { lockZeichnung(); if( tm->text ) tm->text->release(); tm->text = txt; if( hatStyle( Style::VScroll ) ) updateVScroll(); if( hatStyle( Style::HScroll ) ) updateHScroll(); rend = 1; unlockZeichnung(); } void TextFeld::setText( const char *txt ) // setzt den angezeigten Text { lockZeichnung(); if( !tm->text ) tm->text = new Text(); tm->text->setText( txt ); if( hatStyle( Style::VScroll ) ) updateVScroll(); if( hatStyle( Style::HScroll ) ) updateHScroll(); rend = 1; unlockZeichnung(); } // setzt den Text mit styles // txt: der Text // format: \x1: aktiviert unterschtrich // \x2\xY: setzt die schriftgröße auf y für den folgenden text // \x3\xA\xR\xG\xB: setzt die schriftfarbe auf ARGB // \x4\xA\xR\xG\xB: setzt die farbe des ausgewählten textes // \x5\xA\xR\xG\xB: setzt die hintergrundfarbe des ausgewählten textes // \x6\xY: setzt text renderer index auf y // \x7: deaktiviert unterschtrich // \x8\xA\xB\xC\xD: set interact param to ABCD void TextFeld::setFormattedText( const char *txt ) { lockZeichnung(); if( !tm->text ) tm->text = new Text(); tm->textStyle.leeren(); TextStyle current; current.beginIndex = 0; current.fontColor = 0xFFFFFFFF; current.fontSize = 12; current.selected = 0; current.selectedColor = 0xFFFFFFFF; current.selectedBackcroundColor = 0xFF0000FF; current.underlined = 0; current.interactParam = 0; current.rendererIndex = 0; tm->textStyle.add( current ); Text result = ""; for( int i = 0; 1; i++ ) { bool br = 0; current.beginIndex = result.getLength(); switch( txt[ i ] ) { case 0: br = 1; break; case 1: current.underlined = 1; tm->textStyle.add( current ); break; case 2: current.fontSize = (unsigned char)txt[ ++i ]; tm->textStyle.add( current ); break; case 3: current.fontColor = 0; current.fontColor |= (unsigned char)txt[ ++i ] << 24; current.fontColor |= (unsigned char)txt[ ++i ] << 16; current.fontColor |= (unsigned char)txt[ ++i ] << 8; current.fontColor |= (unsigned char)txt[ ++i ]; tm->textStyle.add( current ); break; case 4: current.selectedColor = 0; current.selectedColor |= (unsigned char)txt[ ++i ] << 24; current.selectedColor |= (unsigned char)txt[ ++i ] << 16; current.selectedColor |= (unsigned char)txt[ ++i ] << 8; current.selectedColor |= (unsigned char)txt[ ++i ]; tm->textStyle.add( current ); break; case 5: current.selectedBackcroundColor = 0; current.selectedBackcroundColor |= (unsigned char)txt[ ++i ] << 24; current.selectedBackcroundColor |= (unsigned char)txt[ ++i ] << 16; current.selectedBackcroundColor |= (unsigned char)txt[ ++i ] << 8; current.selectedBackcroundColor |= (unsigned char)txt[ ++i ]; tm->textStyle.add( current ); break; case 6: current.rendererIndex = (unsigned char)txt[ ++i ]; tm->textStyle.add( current ); break; case 7: current.underlined = 0; tm->textStyle.add( current ); break; case 8: current.interactParam = 0; current.interactParam |= (unsigned char)txt[ ++i ] << 24; current.interactParam |= (unsigned char)txt[ ++i ] << 16; current.interactParam |= (unsigned char)txt[ ++i ] << 8; current.interactParam |= (unsigned char)txt[ ++i ]; tm->textStyle.add( current ); break; default: result.append( txt[ i ] ); } if( br ) break; } tm->text->setText( result ); tm->cleanupStyles(); if( hatStyle( Style::VScroll ) ) updateVScroll(); if( hatStyle( Style::HScroll ) ) updateHScroll(); rend = 1; unlockZeichnung(); } // fügt zeilenumbrüche so ein, dass der text nicht die breite des textfeldes überschreitet void TextFeld::addLineBreaks( const char *spacing ) { if( !tm->text ) return; int lastPos = -1; int lastPos2 = -1; int x = 0; const char *txt = tm->text->getText(); Text result = ""; int len = tm->text->getLength(); lockZeichnung(); int maxBr = getBreite(); if( hatStyle( Style::VScroll ) && vertikalScrollBar ) maxBr -= 15; tm->resetIteration(); TextStyle last; last.beginIndex = 0; last.fontColor = 0xFFFFFFFF; last.fontSize = 12; last.selected = 0; last.selectedColor = 0xFFFFFFFF; last.selectedBackcroundColor = 0xFF0000FF; last.underlined = 0; last.interactParam = 0; last.rendererIndex = 0; for( int i = 0; i < len; ++i ) { if( last.fontSize != tm->current.fontSize ) { char tmp[ 3 ] = { 2, (char)tm->current.fontSize, 0 }; result += tmp; last.fontSize = tm->current.fontSize; } if( last.fontColor != tm->current.fontColor ) { char tmp[ 6 ] = { 3, (char)( ( tm->current.fontColor >> 24 ) & 0xFF ), (char)( ( tm->current.fontColor >> 16 ) & 0xFF ), (char)( ( tm->current.fontColor >> 8 ) & 0xFF ), (char)( tm->current.fontColor & 0xFF ), 0 }; result += tmp; last.fontColor = tm->current.fontColor; } if( last.selectedColor != tm->current.selectedColor ) { char tmp[ 6 ] = { 4, (char)( ( tm->current.selectedColor >> 24 ) & 0xFF ), (char)( ( tm->current.selectedColor >> 16 ) & 0xFF ), (char)( ( tm->current.selectedColor >> 8 ) & 0xFF ), (char)( tm->current.selectedColor & 0xFF ), 0 }; result += tmp; last.selectedColor = tm->current.selectedColor; } if( last.selectedBackcroundColor != tm->current.selectedBackcroundColor ) { char tmp[ 6 ] = { 5, (char)( ( tm->current.selectedBackcroundColor >> 24 ) & 0xFF ), (char)( ( tm->current.selectedBackcroundColor >> 16 ) & 0xFF ), (char)( ( tm->current.selectedBackcroundColor >> 8 ) & 0xFF ), (char)( tm->current.selectedBackcroundColor & 0xFF ), 0 }; result += tmp; last.selectedBackcroundColor = tm->current.selectedBackcroundColor; } if( last.underlined != tm->current.underlined ) { char tmp[ 2 ] = { tm->current.underlined ? (char)1 : (char)7, 0 }; result += tmp; last.underlined = tm->current.underlined; } if( last.interactParam != tm->current.interactParam ) { char tmp[ 6 ] = { 8, (char)( ( tm->current.interactParam >> 24 ) & 0xFF ), (char)( ( tm->current.interactParam >> 16 ) & 0xFF ), (char)( ( tm->current.interactParam >> 8 ) & 0xFF ), (char)( tm->current.interactParam & 0xFF ), 0 }; result += tmp; last.interactParam = tm->current.interactParam; } if( last.rendererIndex != tm->current.rendererIndex ) { char tmp[ 3 ] = { 6, (char)tm->current.rendererIndex, 0 }; result += tmp; last.rendererIndex = tm->current.rendererIndex; } if( txt[ i ] == ' ' ) { lastPos = i; lastPos2 = result.getLength(); x += tm->zCurrentRenderer()->getTextBreite( " " ); result += " "; tm->nextStyle(); continue; } if( txt[ i ] == '\t' ) { lastPos = i; lastPos2 = result.getLength(); x += tm->zCurrentRenderer()->getTextBreite( "\t" ); result += "\t"; tm->nextStyle(); continue; } if( txt[ i ] == '\n' ) { x = 0; lastPos = -1; lastPos2 = -1; result += "\n"; tm->nextStyle(); continue; } char buff[ 2 ] = { txt[ i ], 0 }; x += tm->zCurrentRenderer()->getTextBreite( buff ); result += buff; if( x > maxBr && lastPos > -1 ) { result.remove( lastPos2, result.getLength() ); result += "\n"; result += spacing; x = tm->zCurrentRenderer()->getTextBreite( spacing ); i = lastPos; tm->stepTo( lastPos ); lastPos = -1; lastPos2 = -1; last = tm->currentStyle(); } tm->nextStyle(); } unlockZeichnung(); setFormattedText( result ); } // Setzt den Style eines Textabschnittes // begin: die startposition des Abschnittes // end: die endposition des Abschnittes (nicht enthalten) void TextFeld::setTextStyle( int begin, int end, TextStyle style ) { tm->setTextStyle( begin, end, style ); } void TextFeld::addZeile( const char *zeile ) // fügt Zeile An { if( tm->text ) { Text *txt = new Text( zeile ); if( zeile[ txt->getLength() - 1 ] != '\n' ) txt->append( "\n" ); TextRenderer *r = tm->renderer->z( 0 ); if( tm->textStyle.get( tm->textStyle.getEintragAnzahl() - 1 ).rendererIndex < tm->renderer->getEintragAnzahl() ) r = tm->renderer->z( tm->textStyle.get( tm->textStyle.getEintragAnzahl() - 1 ).rendererIndex ); if( r ) { bool vs = vertikalScrollBar && hatStyle( Style::VScroll ); int rbr = ( rahmen && hatStyle( Style::Rahmen ) ) ? rahmen->getRBreite() : 0; r->setSchriftSize( tm->textStyle.get( tm->textStyle.getEintragAnzahl() - 1 ).fontSize ); r->textFormatieren( txt, gr.x - ( (int)vs * 15 ) - rbr * 2 ); } lockZeichnung(); tm->text->append( txt->getText() ); unlockZeichnung(); txt->release(); if( hatStyle( Style::VScroll ) ) updateVScroll(); if( hatStyle( Style::HScroll ) ) updateHScroll(); rend = 1; } } // Fügt eine Zeile an den Text an // zeile: Die neue Zeile // color: Die Farbe der Zeile void TextFeld::addZeile( const char *zeile, int color ) { if( tm->text ) { Text *txt = new Text( zeile ); if( zeile[ txt->getLength() - 1 ] != '\n' ) txt->append( "\n" ); TextRenderer *r = tm->renderer->z( 0 ); if( tm->textStyle.get( tm->textStyle.getEintragAnzahl() - 1 ).rendererIndex < tm->renderer->getEintragAnzahl() ) r = tm->renderer->z( tm->textStyle.get( tm->textStyle.getEintragAnzahl() - 1 ).rendererIndex ); if( r ) { bool vs = vertikalScrollBar && hatStyle( Style::VScroll ); int rbr = ( rahmen && hatStyle( Style::Rahmen ) ) ? rahmen->getRBreite() : 0; r->setSchriftSize( tm->textStyle.get( tm->textStyle.getEintragAnzahl() - 1 ).fontSize ); r->textFormatieren( txt, gr.x - ( (int)vs * 15 ) - rbr * 2 ); } lockZeichnung(); tm->text->append( txt->getText() ); setSchriftFarbe( tm->text->getLength() - txt->getLength(), tm->text->getLength(), color ); unlockZeichnung(); txt->release(); if( hatStyle( Style::VScroll ) ) updateVScroll(); if( hatStyle( Style::HScroll ) ) updateHScroll(); rend = 1; } } // Deselectiert alle textabschnitte void TextFeld::deselectAuswahl() { for( int i = 0; i < tm->textStyle.getEintragAnzahl(); i++ ) { TextStyle s = tm->textStyle.get( i ); if( s.selected ) { s.selected = 0; tm->textStyle.set( s, i ); } } tm->cleanupStyles(); } void TextFeld::setAuswahl( int pos1, int pos2 ) // setzt den Ausgewählten Text { deselectAuswahl(); TextStyle s = tm->getTextStyle( pos1 ); s.selected = 1; tm->setTextStyle( pos1, pos2, s ); } void TextFeld::setAuswahl( Punkt &auswahl ) { deselectAuswahl(); TextStyle s = tm->getTextStyle( auswahl.x ); s.selected = 1; tm->setTextStyle( auswahl.x, auswahl.y, s ); rend = 1; } void TextFeld::addAuswahl( int pos1, int pos2 ) { TextStyle s = tm->getTextStyle( pos1 ); s.selected = 1; tm->setTextStyle( pos1, pos2, s ); } void TextFeld::addAuswahl( Punkt &auswahl ) { TextStyle s = tm->getTextStyle( auswahl.x ); s.selected = 1; tm->setTextStyle( auswahl.x, auswahl.y, s ); rend = 1; } // Setzt den ausgewählten textabschnitt fest // begin: Die Cursorposition im Text // end: Die Position im Text, bis zu der der Text eingefärbt werden soll void TextFeld::invertAuswahl( int begin, int end ) { for( int i = begin; i < end; i++ ) { TextStyle s = tm->getTextStyle( i ); s.selected = !s.selected; tm->setTextStyle( i, i + 1, s ); rend = 1; } } // ersetzt alle ausgewählten Textabschnitte mit einem text // text: der neue Text void TextFeld::replaceAuswahl( const char *text ) { tm->cleanupStyles(); int sa = tm->textStyle.getEintragAnzahl(); int last = tm->text->getLength(); int si = 0; for( int i = sa - 1; i >= 0; i-- ) { TextStyle s = tm->textStyle.get( i ); si = i; if( s.selected ) { if( ( i > 0 && !tm->textStyle.get( i - 1 ).selected ) || i == 0 ) { s.selected = false; tm->textStyle.set( s, si ); tm->removeText( s.beginIndex, last ); tm->insertText( s.beginIndex, text ); } } else last = s.beginIndex; } } void TextFeld::setTextRendererZ( TextRenderer *textRd ) { if( tm->renderer ) tm->renderer->leeren(); else tm->renderer = new RCArray< TextRenderer >(); tm->renderer->add( textRd ); rend = 1; } // Fügt einen TextRenderer hinzu // textRd: Der Textrenderer void TextFeld::addTextRendererZ( TextRenderer *textRd ) { if( !tm->renderer ) tm->renderer = new RCArray< TextRenderer >(); tm->renderer->add( textRd ); } // Setzt die verwendeten TextRenderer // textRd: Die Textrenderer void TextFeld::setTextRendererZ( RCArray< TextRenderer > *textRd ) { if( tm->renderer ) tm->renderer->release(); tm->renderer = textRd; } void TextFeld::setSchriftZ( Schrift *schrift ) // setzt einen Zeiger zur Schrift { if( !tm->renderer ) tm->renderer = new RCArray< TextRenderer >(); if( !tm->renderer->getEintragAnzahl() ) tm->renderer->add( new TextRenderer( schrift ) ); else tm->renderer->z( 0 )->setSchriftZ( schrift ); rend = 1; } // Setzt einen Zeiger zur Schrift // rendererIndex: Der Index des Renderers dessen Schrift gesetzt werden soll // schrift: Die Schrift, die zum Textzeichnen verwendet werden soll. void TextFeld::setSchriftZ( int rendererIndex, Schrift *schrift ) { if( !tm->renderer ) tm->renderer = new RCArray< TextRenderer >(); if( tm->renderer->getEintragAnzahl() <= rendererIndex ) tm->renderer->add( new TextRenderer( schrift ), rendererIndex ); else tm->renderer->z( rendererIndex )->setSchriftZ( schrift ); } void TextFeld::setSchriftSize( unsigned char gr ) // setzt die Schriftgröße { TextStyle s = tm->textStyle.get( 0 ); s.fontSize = gr; tm->textStyle.set( s, 0 ); rend = 1; } // Setzt die Schriftgröße (Standart: 12) // begin: Der Index des ersten betroffenen Zeichens // end: Der Index des ersten nicht betroffenen Zeichens // gr: Die Schriftgröße, die zum Textzeichnen verwendet werden soll void TextFeld::setSchriftSize( int begin, int end, unsigned char gr ) { TextStyle s = tm->getTextStyle( begin ); s.fontSize = gr; tm->setTextStyle( begin, end, s ); rend = 1; } void TextFeld::setSchriftFarbe( int fc ) // setzt die Schrift Farbe { TextStyle s = tm->textStyle.get( 0 ); s.fontColor = fc; tm->textStyle.set( s, 0 ); rend = 1; } // Setzt die Schrift Farbe // begin: Der Index des ersten betroffenen Zeichens // end: Der Index des ersten nicht betroffenen Zeichens // fc: Die Farbe, die zum Textzeichnen verwendet werden soll void TextFeld::setSchriftFarbe( int begin, int end, int fc ) { TextStyle s = tm->getTextStyle( begin ); s.fontColor = fc; tm->setTextStyle( begin, end, s ); rend = 1; } void TextFeld::setSchowChar( unsigned char c ) // bei Passwortfeld * { showChar = c; rend = 1; } void TextFeld::setVScrollZuZeile( int zeile ) // scrollt zur Zeile { if( vertikalScrollBar && tm->renderer && tm->renderer->getEintragAnzahl() && tm->text && hatStyle( Style::Mehrzeilig ) ) { lockZeichnung(); tm->resetIteration(); int len = tm->text->getLength(); int y = 0; int lnum = 0; char *text = tm->text->getText(); int max = 0; for( int i = 0; i < len && lnum < zeile; i++ ) { if( text[ i ] == '\n' ) { lnum++; y += max; max = 0; tm->nextStyle(); continue; } TextRenderer *r = tm->zCurrentRenderer(); if( r ) { int tmp = r->getZeilenabstand() + r->getZeilenHeight(); max = max >= tmp ? max : tmp; } tm->nextStyle(); } unlockZeichnung(); vertikalScrollBar->scroll( y ); rend = 1; } } void TextFeld::updateVScroll( int pos ) // scrollt nach unten { if( pos == -1 ) pos = cpos; if( vertikalScrollBar ) { int sPos = 0; int hi = 0; int sPosZH = 0; if( tm->text && tm->renderer ) { if( hatStyleNicht( Style::Mehrzeilig ) ) tm->text->remove( '\n' ); hi = gr.y; if( hatStyle( Style::Rahmen ) && rahmen ) hi -= rahmen->getRBreite() * 2; if( hatStyle( Style::HScroll ) && horizontalScrollBar ) hi -= 15; int th = 0; lockZeichnung(); tm->resetIteration(); int len = tm->text->getLength(); char *text = tm->text->getText(); int max = 0; int lastMax = 0; for( int i = 0; i < len; i++ ) { if( text[ i ] == '\n' ) { if( i <= pos ) { sPos += max; sPosZH = max; } th += max; lastMax = max; max = 0; tm->nextStyle(); continue; } TextRenderer *r = tm->zCurrentRenderer(); if( r ) { int tmp = r->getZeilenabstand() + r->getZeilenHeight(); max = max >= tmp ? max : tmp; } tm->nextStyle(); } if( max != lastMax && max > 0 ) { th += max; lastMax = max; } th += lastMax; unlockZeichnung(); vertikalScrollBar->update( th, hi ); } if( sPos - sPosZH < vertikalScrollBar->getScroll() ) vertikalScrollBar->scroll( sPos - sPosZH ); if( sPos + sPosZH > vertikalScrollBar->getScroll() + vertikalScrollBar->getScrollData()->anzeige ) vertikalScrollBar->scroll( sPos + sPosZH * 2 - hi ); rend = 1; } } void TextFeld::updateHScroll( int pos ) // scrollt zur Curser Position { if( pos == -1 ) pos = cpos; lockZeichnung(); if( horizontalScrollBar && tm->text && tm->renderer ) { if( hatStyleNicht( Style::Mehrzeilig ) ) tm->text->remove( '\n' ); int br = gr.x; if( hatStyle( Style::Rahmen ) && rahmen ) br -= rahmen->getRBreite() * 2; if( hatStyle( Style::VScroll ) && vertikalScrollBar ) br -= 15; tm->resetIteration(); int maxBr = 0; int len = tm->text->getLength(); char *text = tm->text->getText(); int lineBr = 0; char buff[] = { 0,0 }; int cbr = 0; for( int i = 0; i < len; i++ ) { buff[ 0 ] = text[ i ]; if( text[ i ] == '\n' ) { maxBr = maxBr >= lineBr ? maxBr : lineBr; lineBr = 0; tm->nextStyle(); continue; } TextRenderer *r = tm->zCurrentRenderer(); if( r ) { lineBr += r->getTextBreite( buff ); if( i <= pos ) cbr = lineBr; } tm->nextStyle(); } maxBr = maxBr >= lineBr ? maxBr : lineBr; horizontalScrollBar->update( maxBr, br ); if( cbr > horizontalScrollBar->getScroll() + horizontalScrollBar->getScrollData()->anzeige ) horizontalScrollBar->scroll( cbr - br ); if( cbr < horizontalScrollBar->getScroll() ) horizontalScrollBar->scroll( cbr ); } unlockZeichnung(); } // Gibt die breite in pixeln zurück, die benötigt wird um den aktuellen text mit den aktuellen styles voll anzuzeigen int TextFeld::getNeededWidth() { int maxBr = 0; lockZeichnung(); if( tm->text && tm->renderer ) maxBr = getTextWidth(); unlockZeichnung(); return maxBr; } // Gibt die höhe in pixeln zurück, die benötigt wird um den aktuellen text mit den aktuellen styles voll anzuzeigen int TextFeld::getNeededHeight() { int th = 0; lockZeichnung(); if( tm->text && tm->renderer ) th = getTextHeight(); unlockZeichnung(); return th; } bool TextFeld::tick( double tickval ) // tick { if( hatStyle( Style::Fokus ) ) { if( tickVal < 0.5 && tickVal + tickval >= 0.5 ) rend = 1; if( tickVal >= 0.5 && tickVal + tickval >= 1 ) rend = 1; tickVal += tickval; if( tickVal >= 1 ) tickVal -= 1; } return ZeichnungHintergrund::tick( tickval ); } void TextFeld::doTastaturEreignis( TastaturEreignis &te ) { bool ntakc = !te.verarbeitet; if( te.verarbeitet || hatStyleNicht( Style::Fokus ) ) return; if( !tak ) return; getThis(); if( tak( takParam, this, te ) ) { if( hatStyleNicht( Style::Editierbar ) ) { release(); return; } if( te.id == TE_Press ) { bool shift = TastenStand[ T_Shift ]; bool strg = TastenStand[ T_Strg ]; switch( te.taste ) { case T_Entf: if( !tm->getTextStyle( cpos ).selected ) tm->removeText( cpos, cpos + 1 ); else { cpos = tm->getTextStyle( cpos ).beginIndex; while( cpos > 0 && tm->getTextStyle( cpos - 1 ).selected ) cpos = tm->getTextStyle( cpos - 1 ).beginIndex; } replaceAuswahl( "" ); deselectAuswahl(); rend = 1; break; case T_BackSpace: if( !tm->getTextStyle( cpos ).selected ) { tm->removeText( cpos - 1, cpos ); cpos--; } else { cpos = tm->getTextStyle( cpos ).beginIndex; while( cpos > 0 && tm->getTextStyle( cpos - 1 ).selected ) cpos = tm->getTextStyle( cpos - 1 ).beginIndex; } replaceAuswahl( "" ); deselectAuswahl(); rend = 1; break; case T_Enter: if( !tm->getTextStyle( cpos ).selected ) tm->insertText( cpos, "\n" ); else { cpos = tm->getTextStyle( cpos ).beginIndex; while( cpos > 0 && tm->getTextStyle( cpos - 1 ).selected ) cpos = tm->getTextStyle( cpos - 1 ).beginIndex; } replaceAuswahl( "\n" ); ++cpos; rend = 1; break; case T_Links: if( shift ) { if( strg ) { int tmp = tm->text->getLKick( cpos ); invertAuswahl( tmp, cpos ); cpos = tmp; } else { invertAuswahl( cpos - 1, cpos ); --cpos; } } else { if( strg ) cpos = tm->text->getLKick( cpos ); else --cpos; deselectAuswahl(); } rend = 1; break; case T_Oben: { int tmp = tm->text->getOKick( cpos ); invertAuswahl( tmp, cpos ); cpos = tmp; if( !shift ) deselectAuswahl(); rend = 1; break; } case T_Rechts: if( shift ) { if( strg ) { int tmp = tm->text->getRKick( cpos ); invertAuswahl( cpos, tmp ); cpos = tmp; } else { invertAuswahl( cpos, cpos + 1 ); ++cpos; } } else { if( strg ) cpos = tm->text->getRKick( cpos ); else ++cpos; deselectAuswahl(); } rend = 1; break; case T_Unten: { int tmp = tm->text->getUKick( cpos ); invertAuswahl( cpos, tmp ); cpos = tmp; if( !shift ) deselectAuswahl(); rend = 1; break; } default: if( strg && te.id == TE_Press ) { if( te.taste == 'c' || te.taste == 'C' ) { int sa = tm->textStyle.getEintragAnzahl(); int length = 0; for( int i = 0; i < sa; i++ ) { TextStyle s = tm->textStyle.get( i ); if( s.selected ) { int max = tm->text->getLength(); if( i < sa - 1 ) max = tm->textStyle.get( i + 1 ).beginIndex; length += max - s.beginIndex; } } if( length ) { char *txt = new char[ length + 1 ]; txt[ length ] = 0; int index = 0; for( int i = 0; i < sa; i++ ) { TextStyle s = tm->textStyle.get( i ); if( s.selected ) { int max = tm->text->getLength(); if( i < sa - 1 ) max = tm->textStyle.get( i + 1 ).beginIndex; memcpy( txt + index, tm->text->getText() + s.beginIndex, max - s.beginIndex ); index += max - s.beginIndex; } } TextKopieren( txt ); delete[] txt; } else TextKopieren( tm->text->getText() ); } if( te.taste == 'v' || te.taste == 'V' ) { char *txt = TextInsert(); if( !tm->getTextStyle( cpos ).selected ) tm->insertText( cpos, txt ); else { cpos = tm->getTextStyle( cpos ).beginIndex; while( cpos > 0 && tm->getTextStyle( cpos - 1 ).selected ) cpos = tm->getTextStyle( cpos - 1 ).beginIndex; } replaceAuswahl( txt ); cpos += textLength( txt ); rend = 1; } break; } if( istSchreibbar( te.taste ) ) { char buff[] = { (char)te.taste, 0 }; if( !tm->getTextStyle( cpos ).selected ) tm->insertText( cpos, buff ); else { cpos = tm->getTextStyle( cpos ).beginIndex; while( cpos > 0 && tm->getTextStyle( cpos - 1 ).selected ) cpos = tm->getTextStyle( cpos - 1 ).beginIndex; } replaceAuswahl( buff ); ++cpos; rend = 1; } break; } } if( cpos < 0 ) cpos = 0; if( cpos > tm->text->getLength() ) cpos = tm->text->getLength(); if( hatStyle( Style::VScroll ) ) updateVScroll( cpos ); if( hatStyle( Style::HScroll ) ) updateHScroll( cpos ); te.verarbeitet = 1; } if( ntakc && te.verarbeitet && nTak ) te.verarbeitet = nTak( ntakParam, this, te ); release(); } void TextFeld::render( Bild &zRObj ) // zeichenet nach zRObj { if( hatStyleNicht( Style::Sichtbar ) ) return; ZeichnungHintergrund::render( zRObj ); if( !tm->text || !tm->renderer ) return; lockZeichnung(); if( !zRObj.setDrawOptions( innenPosition, innenSize ) ) { unlockZeichnung(); return; } if( hatStyleNicht( Style::Mehrzeilig ) ) tm->text->remove( '\n' ); int tbr = getTextWidth(); int thi = getTextHeight(); int xxx = 0; int yyy = 0; int breite = innenSize.x; int height = innenSize.y; bool hs = horizontalScrollBar && hatStyle( Style::HScroll ); bool vs = vertikalScrollBar && hatStyle( Style::VScroll ); if( vs ) yyy -= vertikalScrollBar->getScroll(); if( hs ) xxx -= horizontalScrollBar->getScroll(); if( hatStyle( Style::HCenter ) && !hs ) xxx = ( breite / 2 ) - tbr / 2; if( hatStyle( Style::VCenter ) && !vs ) yyy = ( height / 2 ) - thi / 2; int x = xxx; int y = yyy; int len = tm->text->getLength(); char *text = tm->text->getText(); lockZeichnung(); tm->resetIteration(); TextStyle &style = tm->currentStyle(); int maxLH = 0; for( int i = 0; i <= len; i++ ) { int oldX = x; if( i < len &&tm->zCurrentRenderer() ) tm->zCurrentRenderer()->renderChar( x, y, istSchreibbar( showChar ) ? showChar : text[ i ], zRObj, style.selected ? style.selectedColor : style.fontColor, style.underlined, style.selected, style.selectedBackcroundColor ); if( i == cpos && tickVal <= 0.5 && hatStyle( Style::Fokus ) && hatStyle( Style::Editierbar ) && tm->zCurrentRenderer() ) zRObj.drawLinieV( oldX, y, tm->zCurrentRenderer()->getZeilenHeight(), 0xFFFF5555 ); if( tm->zCurrentRenderer() ) { int tmp = tm->zCurrentRenderer()->getZeilenHeight() + tm->zCurrentRenderer()->getZeilenAbstand(); maxLH = tmp > maxLH ? tmp : maxLH; } if( i < len && text[ i ] == '\n' ) { x = xxx; y += maxLH; } tm->nextStyle(); } unlockZeichnung(); zRObj.releaseDrawOptions(); unlockZeichnung(); } // Konstant Text *TextFeld::getText() const // gibt vom Text zurück { if( !tm->text ) return 0; return (Text *)tm->text->getThis(); } Text *TextFeld::zText() const // gibt den Text zurück { return tm->text; } Schrift *TextFeld::getSchrift() const// gint getThis der Schrift Zurück { tm->resetIteration(); return tm->zCurrentRenderer() ? tm->zCurrentRenderer()->getSchrift() : 0; } Schrift *TextFeld::zSchrift() const// gibt die Schrift zurück { tm->resetIteration(); return tm->zCurrentRenderer() ? tm->zCurrentRenderer()->zSchrift() : 0; } // Gibt die Schrift zurück. // rendererIndex: Der Index des Renderers dessen Schrift zurückgegeben werden soll // return: 0, falls die Schrift nicht gesetzt wurde Schrift *TextFeld::getSchrift( int rendererIndex ) const { if( tm->renderer && tm->renderer->z( rendererIndex ) ) return tm->renderer->z( rendererIndex )->getSchrift(); return 0; } // Gibt die Schrift ohne erhöhten Reference Counter zurük // rendererIndex: Der Index des Renderers dessen Schrift zurückgegeben werden soll // return: 0, falls die Schrift nicht gesetzt wurde Schrift *TextFeld::zSchrift( int rendererIndex ) const { if( tm->renderer && tm->renderer->z( rendererIndex ) ) return tm->renderer->z( rendererIndex )->zSchrift(); return 0; } TextRenderer *TextFeld::getTextRenderer() const { tm->resetIteration(); return (TextRenderer *)tm->zCurrentRenderer()->getThis(); } TextRenderer *TextFeld::zTextRenderer() const { tm->resetIteration(); return tm->zCurrentRenderer(); } // Gibt den TextRenderer zurück. // index: Der Index des Renderers der zurückgegeben werden soll // return: 0, falls der TextRenderer nicht gesetzt wurde TextRenderer *TextFeld::getTextRenderer( int index ) const { if( tm->renderer && tm->renderer->z( index ) ) return tm->renderer->get( index ); return 0; } // Gibt dien TextRenderer ohne erhöhten Reference Counter zurük // index: Der Index des Renderers der zurückgegeben werden soll // return: 0, falls der TextRenderer nicht gesetzt wurde TextRenderer *TextFeld::zTextRenderer( int index ) const { if( tm->renderer && tm->renderer->z( index ) ) return tm->renderer->z( index ); return 0; } unsigned char TextFeld::getSchriftSize() const // gibt die Schriftgröße zurück { tm->resetIteration(); return tm->current.fontSize; } // Gibt die Schriftgröße zurück // index: Der Index des Zeichens unsigned char TextFeld::getSchriftSize( int index ) const { tm->resetIteration(); return tm->current.fontSize; } int TextFeld::getSchriftFarbe() const// gibt getThis der Schriftfarbe zurück { tm->resetIteration(); return tm->current.fontColor; } // Gibt die Schriftfarbe im A8R8G8B8 Format zurück // index: Der Index des Zeichens int TextFeld::getSchriftFarbe( int index ) const { return tm->getTextStyle( index ).fontColor; } unsigned char TextFeld::getShowChar() const // gibt den Anzeige Char zurück { return showChar; } int TextFeld::getCursorPos() const { return cpos; } // Gibt 1 zurück wenn das Zeichen ausgewählt ist // index: Der Index des Zeichens bool TextFeld::isCharSelected( int index ) const { return tm->getTextStyle( index ).selected; } // Gibt den Index des Zeichens zurück, das sich unter der Maus befindet // mx: die x position der maus relativ zur position des textfeldes // my: die y position der maus relativ zut position des textfeldes // return: -1, falls sich an der Position kein zeichen befindet int TextFeld::getTextIndexAt( int mx, int my ) const { if( !tm || !tm->text ) return -1; int tbr = getTextWidth(); int thi = getTextHeight(); int xxx = 0; int yyy = 0; int breite = innenSize.x; int height = innenSize.y; bool hs = horizontalScrollBar && hatStyle( Style::HScroll ); bool vs = vertikalScrollBar && hatStyle( Style::VScroll ); if( vs ) yyy -= vertikalScrollBar->getScroll(); if( hs ) xxx -= horizontalScrollBar->getScroll(); if( hatStyle( Style::HCenter ) && !hs ) xxx = ( breite / 2 ) - tbr / 2; if( hatStyle( Style::VCenter ) && !vs ) yyy = ( height / 2 ) - thi / 2; int x = xxx; int y = yyy; int len = tm->text->getLength(); char *text = tm->text->getText(); tm->resetIteration(); int maxLH = 0; for( int i = 0; i < len; i++ ) { char buff[ 2 ] = { istSchreibbar( showChar ) ? (char)showChar : text[ i ], 0 }; int tmpx = tm->zCurrentRenderer()->getTextBreite( buff ); int tmpy = tm->zCurrentRenderer()->getZeilenHeight(); if( mx >= x && mx < x + tmpx && my >= y && my < y + tmpy ) return i; if( mx < x + tmpx && my < y + tmpy ) return -1; x += tmpx; tmpy += tm->zCurrentRenderer()->getZeilenAbstand(); maxLH = tmpy > maxLH ? tmpy : maxLH; if( text[ i ] == '\n' ) { x = xxx; y += maxLH; } tm->nextStyle(); } return -1; } // Gibt den Index des Zeichens zurück, vor dem der curser gesetzt wird, wenn mit der maus geklickt wird // mx: die x position der maus relativ zur position des textfeldes // my: die y position der maus relativ zut position des textfeldes int TextFeld::getCurserPosAt( int mx, int my ) const { int tbr = getTextWidth(); int thi = getTextHeight(); int xxx = 0; int yyy = 0; int breite = innenSize.x; int height = innenSize.y; bool hs = horizontalScrollBar && hatStyle( Style::HScroll ); bool vs = vertikalScrollBar && hatStyle( Style::VScroll ); if( vs ) yyy -= vertikalScrollBar->getScroll(); if( hs ) xxx -= horizontalScrollBar->getScroll(); if( hatStyle( Style::HCenter ) && !hs ) xxx = ( breite / 2 ) - tbr / 2; if( hatStyle( Style::VCenter ) && !vs ) yyy = ( height / 2 ) - thi / 2; int x = xxx; int y = yyy; int len = tm->text->getLength(); char *text = tm->text->getText(); tm->resetIteration(); int maxLH = 0; for( int i = 0; i < len; i++ ) { int tmpx = tm->zCurrentRenderer()->getCharWidth( istSchreibbar( showChar ) ? showChar : text[ i ] ); int tmpy = tm->zCurrentRenderer()->getZeilenHeight() + tm->zCurrentRenderer()->getZeilenAbstand(); if( mx < x + tmpx / 2 && my < y + tmpy - tm->zCurrentRenderer()->getZeilenAbstand() / 2 ) return i; x += tmpx + tm->zCurrentRenderer()->getZeichenAbstand(); maxLH = tmpy > maxLH ? tmpy : maxLH; if( text[ i ] == '\n' ) { if( my >= y - tm->zCurrentRenderer()->getZeilenAbstand() / 2 && my < y + maxLH - tm->zCurrentRenderer()->getZeilenAbstand() / 2 ) return i; x = xxx; y += maxLH; } tm->nextStyle(); } return tm->text->getLength(); } // Gibt den Style eines bestimmten zeichens zurück // index: Der index des Zeichensf TextFeld::TextStyle TextFeld::getTextStyle( int index ) const { return tm->getTextStyle( index ); } Zeichnung *TextFeld::dublizieren() const // Erzeugt eine Kopie des Zeichnungs { TextFeld *obj = new TextFeld(); obj->setPosition( pos ); obj->setSize( gr ); obj->setMausEreignisParameter( makParam ); obj->setTastaturEreignisParameter( takParam ); obj->setMausEreignis( mak ); obj->setTastaturEreignis( tak ); if( toolTip ) obj->setToolTipZ( (ToolTip *)toolTip->dublizieren() ); obj->setStyle( style ); obj->tm->renderer->release(); obj->tm->renderer = ( RCArray * )tm->renderer->getThis(); obj->tm->textStyle.leeren(); for( auto i = tm->textStyle.getIterator(); i; i++ ) obj->tm->textStyle.add( i._ ); obj->tm->index = tm->index; obj->tm->styleIndex = tm->styleIndex; obj->tm->current = tm->current; if( tm->text ) obj->setText( tm->text->getText() ); obj->setHintergrundFarbe( hintergrundFarbe ); if( hintergrundFeld ) obj->setAlphaFeldZ( (AlphaFeld *)hintergrundFeld->dublizieren() ); if( rahmen ) obj->setRahmenZ( (Rahmen *)rahmen->dublizieren() ); if( hintergrundBild ) obj->setHintergrundBild( (Bild *)hintergrundBild->getThis() ); if( vertikalScrollBar ) { obj->setVertikalKlickScroll( vertikalScrollBar->getKlickScroll() ); obj->setVertikalScrollPos( vertikalScrollBar->getScroll() ); obj->setVertikalScrollFarbe( vertikalScrollBar->getFarbe(), vertikalScrollBar->getBgFarbe() ); } if( horizontalScrollBar ) { obj->setHorizontalKlickScroll( horizontalScrollBar->getKlickScroll() ); obj->setHorizontalScrollPos( horizontalScrollBar->getScroll() ); obj->setHorizontalScrollFarbe( horizontalScrollBar->getFarbe(), horizontalScrollBar->getBgFarbe() ); } obj->setSchowChar( showChar ); return obj; }