Browse Source

Flexiblere styles für texte in textfeldern

Kolja Strohm 5 years ago
parent
commit
a3b36a3bf2
9 changed files with 1579 additions and 770 deletions
  1. 5 1
      Bildschirm.cpp
  2. 2 2
      Knopf.cpp
  3. 3 3
      Liste.cpp
  4. 8 8
      Rahmen.cpp
  5. 55 46
      Schrift.cpp
  6. 10 6
      Schrift.h
  7. 1342 688
      TextFeld.cpp
  8. 152 14
      TextFeld.h
  9. 2 2
      ToolTip.cpp

+ 5 - 1
Bildschirm.cpp

@@ -698,7 +698,11 @@ void Bildschirm3D::update() // aktualisiert directX
                                             &d3d11Device,
                                             &support,
                                             &d3d11Context );
-
+    if( result != S_OK )
+    {
+        std::cout << "ERROR: D3D11CreateDeviceAndSwapChain returned " << result << "\n";
+        return;
+    }
     ID3D11Texture2D *backBufferPtr;
     // Get the pointer to the back buffer.
     result = d3d11SpawChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&backBufferPtr );

+ 2 - 2
Knopf.cpp

@@ -33,7 +33,7 @@ Knopf::Knopf()
     setAlphaFeldStrength( -5 );
     setKBFarbe( 0xFF000000 );
     setKBStrength( 20 );
-    addStyle( TextFeld::Style::Center | TextFeld::Style::Mehrfarbig );
+    addStyle( TextFeld::Style::Center );
 }
 
 // Destruktor 
@@ -304,7 +304,7 @@ Zeichnung *Knopf::dublizieren() const // Erzeugt eine Kopie des Zeichnungs
         obj->setHorizontalScrollFarbe( horizontalScrollBar->getFarbe(), horizontalScrollBar->getBgFarbe() );
     }
     obj->setSchowChar( getShowChar() );
-    obj->setAuswahl( getSelectionPos(), getCursorPos() );
+    //obj->setAuswahl( getSelectionPos(), getCursorPos() );
     obj->setKlickFarbe( klickFarbe );
     if( klickBild )
         obj->setKlickBild( klickBild->getThis() );

+ 3 - 3
Liste.cpp

@@ -114,7 +114,7 @@ void AuswahlListe::update() // aktualisiert die Auswahl Liste
 void AuswahlListe::addEintrag( Text *txt ) // fügt einen Eintrag hinzu
 {
     TextFeld *tf = new TextFeld();
-    tf->setStyle( TextFeld::Style::Center | TextFeld::Style::Sichtbar | TextFeld::Style::Mehrfarbig | TextFeld::Style::Rahmen );
+    tf->setStyle( TextFeld::Style::Center | TextFeld::Style::Sichtbar | TextFeld::Style::Rahmen );
     tf->setSchriftFarbe( 0xFFFFFFFF );
     tf->setRahmenBreite( 1 );
     tf->setRahmenFarbe( 0xFFFFFFFF );
@@ -145,7 +145,7 @@ void AuswahlListe::addEintragZ( TextFeld *tf )
 void AuswahlListe::addEintrag( int pos, Text *txt ) // fügt einen Eintrag bei position pos ein
 {
     TextFeld *tf = new TextFeld();
-    tf->setStyle( TextFeld::Style::Center | TextFeld::Style::Sichtbar | TextFeld::Style::Mehrfarbig | TextFeld::Style::Rahmen );
+    tf->setStyle( TextFeld::Style::Center | TextFeld::Style::Sichtbar | TextFeld::Style::Rahmen );
     tf->setSchriftFarbe( 0xFFFFFFFF );
     tf->setRahmenBreite( 1 );
     tf->setRahmenFarbe( 0xFFFFFFFF );
@@ -181,7 +181,7 @@ void AuswahlListe::setEintrag( int pos, Text *txt ) // 
     if( !tf )
     {
         tf = new TextFeld();
-        tf->setStyle( TextFeld::Style::Center | TextFeld::Style::Sichtbar | TextFeld::Style::Mehrfarbig | TextFeld::Style::Rahmen );
+        tf->setStyle( TextFeld::Style::Center | TextFeld::Style::Sichtbar | TextFeld::Style::Rahmen );
         tf->setSchriftFarbe( 0xFFFFFFFF );
         tf->setRahmenFarbe( 0xFFFFFFFF );
         tf->setRahmenBreite( 1 );

+ 8 - 8
Rahmen.cpp

@@ -142,11 +142,11 @@ void LRahmen::render( Bild &Obj ) // Zeichnet den Rahmen in das RenderZeichnung
                 for( int x = breakOffset; x < gr.x; x += lineLength + breakLength )
                     Obj.drawLinieHAlpha( x + i + 1, y + i, lineLength - ( x + i + 1 + lineLength > gr.x - i - 1 ? gr.x - i - 1 - ( x + i + 1 + lineLength ) : 0 ), farbe );
                 for( int x = gr.x - breakOffset - lineLength; x >= 0; x -= lineLength + breakLength )
-                    Obj.drawLinieHAlpha( max( x + i + 1, i + 1 ), h - i, lineLength - ( x + i + 1 < i + 1 ? i + 1 - ( x + i + 1 ) : 0 ), farbe );
+                    Obj.drawLinieHAlpha( MAX( x + i + 1, i + 1 ), h - i, lineLength - ( x + i + 1 < i + 1 ? i + 1 - ( x + i + 1 ) : 0 ), farbe );
                 for( int y = breakOffset; y < gr.y; y += lineLength + breakLength )
                     Obj.drawLinieVAlpha( b - i, y + i + 1, lineLength - ( y + i + 1 + lineLength > gr.y - i - 1 ? gr.y - i - 1 - ( y + i + 1 + lineLength ) : 0 ), farbe );
                 for( int y = gr.y - breakOffset - lineLength; y >= 0; y -= lineLength + breakLength )
-                    Obj.drawLinieVAlpha( x + i, max( y + i, i ), lineLength - ( y + i < i ? i - ( y + i ) : 0 ), farbe );
+                    Obj.drawLinieVAlpha( x + i, MAX( y + i, i ), lineLength - ( y + i < i ? i - ( y + i ) : 0 ), farbe );
             }
         }
         else
@@ -156,11 +156,11 @@ void LRahmen::render( Bild &Obj ) // Zeichnet den Rahmen in das RenderZeichnung
                 for( int x = breakOffset; x < gr.x; x += lineLength + breakLength )
                     Obj.drawLinieH( x + i + 1, y + i, lineLength - ( x + i + 1 + lineLength > gr.x - i - 1 ? gr.x - i - 1 - ( x + i + 1 + lineLength ) : 0 ), farbe );
                 for( int x = gr.x - breakOffset - lineLength; x >= 0; x -= lineLength + breakLength )
-                    Obj.drawLinieH( max( x + i + 1, i + 1 ), h - i, lineLength - ( x + i + 1 < i + 1 ? i + 1 - ( x + i + 1 ) : 0 ), farbe );
+                    Obj.drawLinieH( MAX( x + i + 1, i + 1 ), h - i, lineLength - ( x + i + 1 < i + 1 ? i + 1 - ( x + i + 1 ) : 0 ), farbe );
                 for( int y = breakOffset; y < gr.y; y += lineLength + breakLength )
                     Obj.drawLinieV( b - i, y + i + 1, lineLength - ( y + i + 1 + lineLength > gr.y - i - 1 ? gr.y - i - 1 - ( y + i + 1 + lineLength ) : 0 ), farbe );
                 for( int y = gr.y - breakOffset - lineLength; y >= 0; y -= lineLength + breakLength )
-                    Obj.drawLinieV( x + i, max( y + i, i ), lineLength - ( y + i < i ? i - ( y + i ) : 0 ), farbe );
+                    Obj.drawLinieV( x + i, MAX( y + i, i ), lineLength - ( y + i < i ? i - ( y + i ) : 0 ), farbe );
             }
         }
     }
@@ -242,11 +242,11 @@ void Rahmen3D::render( Bild &Obj ) // Zeichnet den Rahmen in das RenderZeichnung
                 for( int x = breakOffset; x < gr.x; x += lineLength + breakLength )
                     Obj.drawLinieHAlpha( x + i + 1, y + i, lineLength - ( x + i + 1 + lineLength > gr.x - i - 1 ? gr.x - i - 1 - ( x + i + 1 + lineLength ) : 0 ), farbe );
                 for( int x = gr.x - breakOffset - lineLength; x >= 0; x -= lineLength + breakLength )
-                    Obj.drawLinieHAlpha( max( x + i + 1, i + 1 ), h - i, lineLength - ( x + i + 1 < i + 1 ? i + 1 - ( x + i + 1 ) : 0 ), fcomp );
+                    Obj.drawLinieHAlpha( MAX( x + i + 1, i + 1 ), h - i, lineLength - ( x + i + 1 < i + 1 ? i + 1 - ( x + i + 1 ) : 0 ), fcomp );
                 for( int y = breakOffset; y < gr.y; y += lineLength + breakLength )
                     Obj.drawLinieVAlpha( b - i, y + i + 1, lineLength - ( y + i + 1 + lineLength > gr.y - i - 1 ? gr.y - i - 1 - ( y + i + 1 + lineLength ) : 0 ), farbe );
                 for( int y = gr.y - breakOffset - lineLength; y >= 0; y -= lineLength + breakLength )
-                    Obj.drawLinieVAlpha( x + i, max( y + i, i ), lineLength - ( y + i < i ?i - ( y + i ) : 0 ), fcomp );
+                    Obj.drawLinieVAlpha( x + i, MAX( y + i, i ), lineLength - ( y + i < i ?i - ( y + i ) : 0 ), fcomp );
             }
         }
         else
@@ -256,11 +256,11 @@ void Rahmen3D::render( Bild &Obj ) // Zeichnet den Rahmen in das RenderZeichnung
                 for( int x = breakOffset; x < gr.x; x += lineLength + breakLength )
                     Obj.drawLinieH( x + i + 1, y + i, lineLength - ( x + i + 1 + lineLength > gr.x - i - 1 ? gr.x - i - 1 - ( x + i + 1 + lineLength ) : 0 ), farbe );
                 for( int x = gr.x - breakOffset - lineLength; x >= 0; x -= lineLength + breakLength )
-                    Obj.drawLinieH( max( x + i + 1, i + 1 ), h - i, lineLength - ( x + i + 1 < i + 1 ? i + 1 - ( x + i + 1 ) : 0 ), fcomp );
+                    Obj.drawLinieH( MAX( x + i + 1, i + 1 ), h - i, lineLength - ( x + i + 1 < i + 1 ? i + 1 - ( x + i + 1 ) : 0 ), fcomp );
                 for( int y = breakOffset; y < gr.y; y += lineLength + breakLength )
                     Obj.drawLinieV( b - i, y + i + 1, lineLength - ( y + i + 1 + lineLength > gr.y - i - 1 ? gr.y - i - 1 - ( y + i + 1 + lineLength ) : 0 ), farbe );
                 for( int y = gr.y - breakOffset - lineLength; y >= 0; y -= lineLength + breakLength )
-                    Obj.drawLinieV( x + i, max( y + i, i ), lineLength - ( y + i < i ? i - ( y + i ) : 0 ), fcomp );
+                    Obj.drawLinieV( x + i, MAX( y + i, i ), lineLength - ( y + i < i ? i - ( y + i ) : 0 ), fcomp );
             }
         }
     }

+ 55 - 46
Schrift.cpp

@@ -464,7 +464,6 @@ void TextRenderer::textFormatieren( Text *zTxt, int maxBreite )
     int x = 0;
     const char *txt = zTxt->getText();
     Text result = txt;
-    int len = zTxt->getLength();
     for( int i = 0; txt[ i ]; ++i )
     {
         if( txt[ i ] == ' ' )
@@ -485,11 +484,6 @@ void TextRenderer::textFormatieren( Text *zTxt, int maxBreite )
             lastPos = -1;
             continue;
         }
-        if( txt[ i ] == '\r' && len - i >= 11 )
-        {
-            i += 10;
-            continue;
-        }
         x += getCharWidth( txt[ i ] ) + zeichenAbstand;
         if( x > maxBreite && lastPos > -1 )
         {
@@ -555,22 +549,6 @@ void TextRenderer::renderText( int x, int y, const char *txt, Bild &zRObj, std::
             x = beginX;
             continue;
         }
-        if( txt[ i ] == '\r' && textLength( txt ) - i >= 11 )
-        {
-            i += 3;
-            Text *hex1 = Text( txt ).getTeilText( i, i + 6 );
-            Text *hex2 = Text( txt ).getTeilText( i + 6, i + 8 );
-            int nf = ( TextZuInt( hex1->getText(), 16 ) << 8 ) |
-                ( TextZuInt( hex2->getText(), 16 ) );
-            f = [ nf ]( int a, int b, int c )
-            {
-                return nf;
-            };
-            hex1->release();
-            hex2->release();
-            i += 7;
-            continue;
-        }
         renderChar( x, y, txt[ i ], zRObj, faerb, ff, f( x, y, i ) );
     }
     if( textLength( txt ) == cpos )
@@ -599,10 +577,11 @@ void TextRenderer::renderText( int x, int y, const char *txt, Bild &zRObj, int f
 //  y: y position des ersten zeichens
 //  txt: Der Text, der gezeichnet werden soll
 //  zRObj: Das Bild, auf das gezeichnet werden soll
+//  color: Die Farbe, in der der Text gezeichnet werden soll
+//  underlined: 1, falls der Text unterstrichen sein soll
 //  selected: 1, falls das zeichen eingefärbt sein soll
-//  ff: Die Hintergrund Farbe des eingefärbten Textes
-//  f: Die Farbe, in der der Text gezeichnet werden soll
-void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected, int ff, int f )
+//  selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes
+void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, int color, bool underlined, bool selected, int selectedBackgroundColor )
 {
     if( !s )
         return;
@@ -619,7 +598,7 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
             if( selected )
             {
                 int br = getCharWidth( c ) + zeichenAbstand;
-                zRObj.alphaRegion( x, y, br, getZeilenHeight(), ff );
+                zRObj.alphaRegion( x, y, br, getZeilenHeight(), selectedBackgroundColor );
             }
             if( b->getBuff() )
             {
@@ -629,8 +608,8 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                 int xp = x + zRObjOff.x, yp = y + zRObjOff.y;
                 int xs = xp < zRObjPos.x ? ( zRObjPos.x - xp ) : 0, ys = yp < zRObjPos.y ? ( zRObjPos.y - yp ) : 0;
                 int br = b->getBreite(), h = b->getHeight();
-                unsigned char a2 = (unsigned char)( 255 - ( f >> 24 ) );
-                f &= 0x00FFFFFF;
+                unsigned char a2 = (unsigned char)( 255 - ( color >> 24 ) );
+                color &= 0x00FFFFFF;
                 if( schriftSize == b->getSchriftSize() )
                 {
                     if( xp >= zRObjGr.x || yp >= zRObjGr.y || xp + br < zRObjPos.x || yp + h < zRObjPos.y )
@@ -647,7 +626,7 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                                 ygr += b->getBreite();
                                 ygr2 += zRObj.getBreite();
                                 for( xx = xs; xx < br; ++xx )
-                                    zRObj.alphaPixel3D( xp + xx + ygr2, f | ( b->getBuff()[ xx + ygr ] << 24 ) );
+                                    zRObj.alphaPixel3D( xp + xx + ygr2, color | ( b->getBuff()[ xx + ygr ] << 24 ) );
                             }
                         }
                         else
@@ -657,7 +636,7 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                                 ygr += b->getBreite();
                                 ygr2 += zRObj.getBreite();
                                 for( xx = xs; xx < br; ++xx )
-                                    zRObj.alphaPixel2D( xp + xx + ygr2, f | ( b->getBuff()[ xx + ygr ] << 24 ) );
+                                    zRObj.alphaPixel2D( xp + xx + ygr2, color | ( b->getBuff()[ xx + ygr ] << 24 ) );
                             }
                         }
                     }
@@ -675,7 +654,7 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                                 {
                                     a = b->getBuff()[ xx + ygr ] - a2;
                                     if( a > 0 )
-                                        zRObj.alphaPixel3D( xp + xx + ygr2, f | ( a << 24 ) );
+                                        zRObj.alphaPixel3D( xp + xx + ygr2, color | ( a << 24 ) );
                                 }
                             }
                         }
@@ -689,7 +668,7 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                                 {
                                     a = b->getBuff()[ xx + ygr ] - a2;
                                     if( a > 0 )
-                                        zRObj.alphaPixel2D( xp + xx + ygr2, f | ( a << 24 ) );
+                                        zRObj.alphaPixel2D( xp + xx + ygr2, color | ( a << 24 ) );
                                 }
                             }
                         }
@@ -714,7 +693,7 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                                 ygr = (int)y * br;
                                 for( dx = xs; dx < maxX; ++dx )
                                 {
-                                    zRObj.alphaPixel3D( xp + dx + ygr2, f | ( b->getBuff()[ (int)x + ygr ] << 24 ) );
+                                    zRObj.alphaPixel3D( xp + dx + ygr2, color | ( b->getBuff()[ (int)x + ygr ] << 24 ) );
                                     x += xoff;
                                 }
                                 x = xs;
@@ -729,7 +708,7 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                                 ygr = (int)y * br;
                                 for( dx = xs; dx < maxX; ++dx )
                                 {
-                                    zRObj.alphaPixel2D( xp + dx + ygr2, f | ( b->getBuff()[ (int)x + ygr ] << 24 ) );
+                                    zRObj.alphaPixel2D( xp + dx + ygr2, color | ( b->getBuff()[ (int)x + ygr ] << 24 ) );
                                     x += xoff;
                                 }
                                 x = xs;
@@ -749,7 +728,7 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                                 for( dx = xs; dx < maxX; ++dx )
                                 {
                                     a = b->getBuff()[ (int)x + ygr ] - a2;
-                                    zRObj.alphaPixel3D( xp + dx + ygr2, f | ( a << 24 ) );
+                                    zRObj.alphaPixel3D( xp + dx + ygr2, color | ( a << 24 ) );
                                     x += xoff;
                                 }
                                 x = xs;
@@ -765,7 +744,7 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                                 for( dx = xs; dx < maxX; ++dx )
                                 {
                                     a = b->getBuff()[ (int)x + ygr ] - a2;
-                                    zRObj.alphaPixel2D( xp + dx + ygr2, f | ( a << 24 ) );
+                                    zRObj.alphaPixel2D( xp + dx + ygr2, color | ( a << 24 ) );
                                     x += xoff;
                                 }
                                 x = xs;
@@ -775,9 +754,23 @@ void TextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected
                     }
                 }
             }
+            if( underlined )
+                zRObj.drawLinieHAlpha( x - (int)( zeichenAbstand / 2.0 + 0.5 ), y + getZeilenHeight() + getZeichenAbstand() / 2, getCharWidth( c ) + (int)( zeichenAbstand / 2.0 + 0.5 ), color );
         }
         x += getCharWidth( c ) + zeichenAbstand;
     }
+    else if( c == ' ' )
+    {
+        if( selected )
+            zRObj.alphaRegion( x, y, schriftSize / 2 + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor );
+        x += schriftSize / 2 + zeichenAbstand;
+    }
+    else if( c == '\t' )
+    {
+        if( selected )
+            zRObj.alphaRegion( x, y, schriftSize + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor );
+        x += schriftSize + zeichenAbstand;
+    }
 }
 
 // Gibt die Schriftgröße zurück, die zum Zeichnen verwendet wird
@@ -792,6 +785,12 @@ int TextRenderer::getZeilenabstand() const
     return zeilenAbstand;
 }
 
+// Gibt den Abstand in Pixeln zum zwischen zwei zeichen auf der x Achse zurück
+int TextRenderer::getZeichenAbstand() const
+{
+    return zeichenAbstand;
+}
+
 // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text vollständig darzustellen
 //  txt: Der Text, von dem die Breite in Pixeln ermitelt werden soll
 int TextRenderer::getTextBreite( const char *txt ) const
@@ -806,11 +805,6 @@ int TextRenderer::getTextBreite( const char *txt ) const
                 ret = tmp;
             tmp = 0;
         }
-        else if( txt[ i ] == '\r' )
-        {
-            i += 10;
-            continue;
-        }
         else if( txt[ i ] == '\t' )
             tmp += schriftSize + zeichenAbstand;
         else if( txt[ i ] == ' ' )
@@ -943,10 +937,11 @@ GravurTextRenderer::~GravurTextRenderer()
 //  y: y position des ersten zeichens
 //  txt: Der Text, der gezeichnet werden soll
 //  zRObj: Das Bild, auf das gezeichnet werden soll
+//  color: Die Farbe, in der der Text gezeichnet werden soll
+//  underlined: 1, falls der Text unterstrichen sein soll
 //  selected: 1, falls das zeichen eingefärbt sein soll
-//  ff: Die Hintergrund Farbe des eingefärbten Textes
-//  f: Die Farbe, in der der Text gezeichnet werden soll
-void GravurTextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool selected, int ff, int f )
+//  selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes
+void GravurTextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, int color, bool underlined, bool selected, int selectedBackgroundColor )
 {
     if( !s )
         return;
@@ -961,7 +956,7 @@ void GravurTextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool se
             if( selected )
             {
                 int br = getCharWidth( c ) + zeichenAbstand;
-                zRObj.alphaRegion( x, y, br, getZeilenHeight(), ff );
+                zRObj.alphaRegion( x, y, br, getZeilenHeight(), selectedBackgroundColor );
             }
             if( b->getBuff() )
             {
@@ -971,7 +966,7 @@ void GravurTextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool se
                 int xp = x + zRObjOff.x, yp = y + zRObjOff.y;
                 int xs = xp < zRObjPos.x ? ( zRObjPos.x - xp ) : 0, ys = yp < zRObjPos.y ? ( zRObjPos.y - yp ) : 0;
                 int br = b->getBreite(), h = b->getHeight();
-                f &= 0x00FFFFFF;
+                color &= 0x00FFFFFF;
                 double xoff = (double)b->getSchriftSize() / ( schriftSize * 2.0 ),
                     yoff = (double)b->getSchriftSize() / ( schriftSize * 2.0 );
                 double x = xs * xoff, y = ys * yoff;
@@ -1028,9 +1023,23 @@ void GravurTextRenderer::renderChar( int &x, int y, char c, Bild &zRObj, bool se
                     }
                 }
             }
+            if( underlined )
+                zRObj.drawLinieHAlpha( x - (int)( zeichenAbstand / 2.0 + 0.5 ), y + getZeilenHeight() + getZeichenAbstand() / 2, getCharWidth( c ) + (int)( zeichenAbstand / 2.0 + 0.5 ), color );
         }
         x += getCharWidth( c ) + zeichenAbstand;
     }
+    else if( c == ' ' )
+    {
+        if( selected )
+            zRObj.alphaRegion( x, y, schriftSize / 2 + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor );
+        x += schriftSize / 2 + zeichenAbstand;
+    }
+    else if( c == '\t' )
+    {
+        if( selected )
+            zRObj.alphaRegion( x, y, schriftSize + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor );
+        x += schriftSize + zeichenAbstand;
+    }
 }
 
 // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Buchstaben vollständig darzustellen

+ 10 - 6
Schrift.h

@@ -264,10 +264,11 @@ namespace Framework
         //  y: y position des ersten zeichens
         //  txt: Der Text, der gezeichnet werden soll
         //  zRObj: Das Bild, auf das gezeichnet werden soll
+        //  color: Die Farbe, in der der Text gezeichnet werden soll
+        //  underlined: 1, falls der Text unterstrichen sein soll
         //  selected: 1, falls das zeichen eingefärbt sein soll
-        //  ff: Die Hintergrund Farbe des eingefärbten Textes
-        //  f: Die Farbe, in der der Text gezeichnet werden soll
-        __declspec( dllexport ) virtual void renderChar( int &x, int y, char c, Bild &zRObj, bool selected, int ff, int f );
+        //  selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes
+        __declspec( dllexport ) virtual void renderChar( int &x, int y, char c, Bild &zRObj, int color, bool underlined = 0, bool selected = 0, int selectedBackgroundColor = 0 );
         // Gibt die Schriftgröße zurück, die zum Zeichnen verwendet wird
         __declspec( dllexport ) int getSchriftSize() const;
         // Gibt den Abstand in Pixeln zum unteren Ende der darüber ligenden Zeile zurück
@@ -286,6 +287,8 @@ namespace Framework
         __declspec( dllexport ) virtual int getCharHeight( const char c ) const;
         // Gibt den Abstand in Pixeln zum unteren Ende der darüber ligenden Zeile zurück
         __declspec( dllexport ) int getZeilenAbstand() const;
+        // Gibt den Abstand in Pixeln zum zwischen zwei zeichen auf der x Achse zurück
+        __declspec( dllexport ) int getZeichenAbstand() const;
         // Gibt die skallierte Höhe zurück, die eine gezeichnete Zeile in Pixeln benötigt
         __declspec( dllexport ) int getZeilenHeight() const;
         // Ermittelt das Zeichen im Text, auf das die Maus zeigt
@@ -313,10 +316,11 @@ namespace Framework
         //  y: y position des ersten zeichens
         //  txt: Der Text, der gezeichnet werden soll
         //  zRObj: Das Bild, auf das gezeichnet werden soll
+        //  color: Die Farbe, in der der Text gezeichnet werden soll
+        //  underlined: 1, falls der Text unterstrichen sein soll
         //  selected: 1, falls das zeichen eingefärbt sein soll
-        //  ff: Die Hintergrund Farbe des eingefärbten Textes
-        //  f: Die Farbe, in der der Text gezeichnet werden soll
-        __declspec( dllexport ) virtual void renderChar( int &x, int y, char c, Bild &zRObj, bool selected, int ff, int f );
+        //  selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes
+        __declspec( dllexport ) virtual void renderChar( int &x, int y, char c, Bild &zRObj, int color, bool underlined = 0, bool selected = 0, int selectedBackgroundColor = 0 );
         // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Buchstaben vollständig darzustellen
         //  c: Der Buchstabe, von dem die Breite in Pixeln ermitelt werden soll
         __declspec( dllexport ) virtual int getCharWidth( const char c ) const;

+ 1342 - 688
TextFeld.cpp

@@ -15,821 +15,1475 @@
 
 using namespace Framework;
 
+template<typename T, typename... U>
+size_t getAddress( std::function<T( U... )> f )
+{
+    typedef T( fnType )( U... );
+    fnType ** fnPointer = f.template target<fnType*>();
+    if( !fnPointer )
+        return 0;
+    return (size_t)*fnPointer;
+}
+
+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 && getAddress( onClick ) == getAddress( rhs.onClick ) && rendererIndex == rhs.rendererIndex;
+}
+
+
+TextFeld::TextStyleManager::TextStyleManager()
+    : renderer( new RCArray< TextRenderer >() ),
+    index( 0 ),
+    styleIndex( 0 ),
+    text( 0 ),
+    ref( 1 )
+{
+    current.beginIndex = 0;
+    current.fontColor = 0xFFFFFFFF;
+    current.fontSize = 12;
+    current.selected = 0;
+    current.selectedColor = 0xFFFFFFFF;
+    current.selectedBackcroundColor = 0xFF0000FF;
+    current.underlined = 0;
+    current.onClick = 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 = 0; 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 ) == 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 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;
+}
+
+// Erhöht den Reference Counting Zähler.
+//  return: this.
+TextFeld::TextStyleManager *TextFeld::TextStyleManager::getThis()
+{
+    ref++;
+    return this;
+}
+
+// Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
+//  return: 0.
+TextFeld::TextStyleManager *TextFeld::TextStyleManager::release()
+{
+    if( !--ref )
+        delete this;
+    return 0;
+}
+
+
 // Inhalt der TextFeld Klasse aus TextFeld.h 
 // Konstruktor 
 TextFeld::TextFeld()
-	: ZeichnungHintergrund(),
-	schriftSize( 12 ),
-    textRd( 0 ),
-	text( 0 ),
-	sF( 0xFF000000 ),
-	showChar( 0 ),
-	begf( 0 ),
-	cpos( 0 ),
-	tickVal( 0 ),
-	mausKlick( 0 )
-{
-	horizontalScrollBar = new HScrollBar();
-	vertikalScrollBar = new VScrollBar();
-	style = 0;
-	this->setMausEreignis( _ret1ME );
-	this->setTastaturEreignis( _ret1TE );
+    : ZeichnungHintergrund(),
+    tm( new TextStyleManager() ),
+    showChar( 0 ),
+    cpos( 0 ),
+    tickVal( 0 ),
+    mausKlick( 0 )
+{
+    horizontalScrollBar = new HScrollBar();
+    vertikalScrollBar = new VScrollBar();
+    this->setMausEreignis( _ret1ME );
+    this->setTastaturEreignis( _ret1TE );
 }
 
 // Destruktor 
 TextFeld::~TextFeld()
 {
-	if( textRd )
-        textRd->release();
-	if( text )
-		text->release();
+    tm->release();
+}
+
+int TextFeld::getTextHeight() const
+{
+    tm->resetIteration();
+    int th = 0;
+    int len = tm->text->getLength();
+    char *text = tm->text->getText();
+    int max = 0;
+    for( int i = 0; i < len; i++ )
+    {
+        if( text[ i ] == '\n' )
+        {
+            th += 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 > 0 )
+        th += max;
+    return th;
+}
+
+int TextFeld::getTextWidth() const
+{
+    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;
 }
 
-// nicht constant 
 void TextFeld::setText( Text *txt ) // setzt den angezeigten Text
 {
-	lockZeichnung();
-	if( !text )
-		text = new Text();
-	text->setText( txt );
-	if( hatStyle( Style::VScroll ) )
-		updateVScroll();
-	if( hatStyle( Style::HScroll ) )
-		updateHScroll();
-	unlockZeichnung();
-	rend = 1;
+    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( text )
-		text->release();
-	text = txt;
-	if( hatStyle( Style::VScroll ) )
-		updateVScroll();
-	if( hatStyle( Style::HScroll ) )
-		updateHScroll();
-	rend = 1;
-	unlockZeichnung();
+    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( !text )
-		text = new Text();
-	text->setText( txt );
-	if( hatStyle( Style::VScroll ) )
-		updateVScroll();
-	if( hatStyle( Style::HScroll ) )
-		updateHScroll();
-	rend = 1;
-	unlockZeichnung();
+    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 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( text )
-	{
-		Text *txt = new Text( zeile );
-		txt->append( "\n" );
-		if( textRd )
-		{
-			bool vs = vertikalScrollBar && hatStyle( Style::VScroll );
-			int rbr = ( rahmen && hatStyle( Style::Rahmen ) ) ? rahmen->getRBreite() : 0;
-            textRd->setSchriftSize( schriftSize );
-            textRd->textFormatieren( txt, gr.x - ( (int)vs * 15 ) - rbr * 2 );
-		}
-		lockZeichnung();
-		text->append( txt->getText() );
-		unlockZeichnung();
-		txt->release();
-		if( hatStyle( Style::VScroll ) )
-			updateVScroll();
-		if( hatStyle( Style::HScroll ) )
-			updateHScroll();
-		rend = 1;
-	}
+    if( tm->text )
+    {
+        Text *txt = new Text( zeile );
+        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;
+    }
+}
+
+// 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
 {
-	cpos = pos1;
-	begf = pos2;
-	rend = 1;
+    deselectAuswahl();
+    TextStyle s = tm->getTextStyle( pos1 );
+    s.selected = 1;
+    tm->setTextStyle( pos1, pos2, s );
 }
 
 void TextFeld::setAuswahl( Punkt &auswahl )
 {
-	cpos = auswahl.x;
-	begf = auswahl.y;
-	rend = 1;
+    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();
+    for( int i = sa - 1; i >= 0; i-- )
+    {
+        TextStyle s = tm->textStyle.get( i );
+        if( s.selected )
+        {
+            if( ( i > 0 && !tm->textStyle.get( i - 1 ).selected ) || i == 0 )
+            {
+                tm->removeText( s.beginIndex, last );
+                tm->insertText( s.beginIndex, text );
+            }
+        }
+        else
+            last = s.beginIndex;
+    }
 }
 
 void TextFeld::setTextRendererZ( TextRenderer *textRd )
 {
-    if( this->textRd )
-        this->textRd->release();
-    this->textRd = 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( !this->textRd )
-        textRd = new TextRenderer( 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
-        textRd->setSchriftZ( schrift );
-	rend = 1;
+        tm->renderer->z( rendererIndex )->setSchriftZ( schrift );
 }
 
 void TextFeld::setSchriftSize( unsigned char gr ) // setzt die Schriftgröße
 {
-	schriftSize = gr;
-	rend = 1;
+    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
 {
-	sF = fc;
-	rend = 1;
+    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;
+    showChar = c;
+    rend = 1;
 }
 
 void TextFeld::setVScrollZuZeile( int zeile ) // scrollt zur Zeile
 {
-	if( vertikalScrollBar && textRd && text && hatStyle( Style::Mehrzeilig ) )
-	{
-        textRd->setSchriftSize( schriftSize );
-		Text t = "a";
-		vertikalScrollBar->scroll( zeile * ( textRd->getZeilenabstand() + textRd->getTextHeight( t ) ) );
-		rend = 1;
-	}
+    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;
-		if( text && textRd )
-		{
-			if( hatStyleNicht( Style::Mehrzeilig ) )
-				text->remove( '\n' );
-            textRd->setSchriftSize( schriftSize );
-			hi = gr.y;
-			if( hatStyle( Style::Rahmen ) && rahmen )
-				hi -= rahmen->getRBreite() * 2;
-			if( hatStyle( Style::HScroll ) && horizontalScrollBar )
-				hi -= 15;
-			vertikalScrollBar->update( textRd->getTextHeight( text->getText() ) + schriftSize + textRd->getTextHeight( "a" ), hi );
-			Text t;
-			int zh = textRd->getTextHeight( t ) + textRd->getZeilenabstand();
-			int l = text->getLength();
-			for( int i = 0; i < l && ( i < pos || hatStyleNicht( Style::Erlaubt ) ); ++i )
-			{
-				if( text->getText()[ i ] == '\n' )
-					sPos += zh;
-			}
-		}
-		if( textRd )
-		{
-			if( sPos - textRd->getZeilenabstand() - textRd->getTextHeight( "a" ) < vertikalScrollBar->getScroll() )
-				vertikalScrollBar->scroll( sPos - textRd->getZeilenabstand() - textRd->getTextHeight( "a" ) );
-			if( sPos + textRd->getZeilenabstand() + textRd->getTextHeight( "a" ) > vertikalScrollBar->getScroll() + vertikalScrollBar->getScrollData()->anzeige )
-				vertikalScrollBar->scroll( sPos + ( textRd->getZeilenabstand() + textRd->getTextHeight( "a" ) ) * 2 - hi );
-		}
-		rend = 1;
-	}
+    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;
-	if( horizontalScrollBar && text && textRd )
-	{
-        textRd->setSchriftSize( schriftSize );
-		int br = gr.x;
-		if( hatStyle( Style::Rahmen ) && rahmen )
-			br -= rahmen->getRBreite() * 2;
-		if( hatStyle( Style::VScroll ) && vertikalScrollBar )
-			br -= 15;
-		int maxBr = textRd->getTextBreite( text->getText() ) + schriftSize;
-		horizontalScrollBar->update( maxBr, br );
-		if( hatStyle( Style::Erlaubt ) && maxBr > br && pos > 0 && pos < text->getLength() )
-		{
-			int p1 = 0;
-			char *tmp = text->getText();
-			for( int i = 0; i < pos; i++, tmp++ )
-			{
-				if( *tmp == '\n' )
-					p1 = i + 1;
-			}
-			Text *t = text->getTeilText( p1, pos );
-			int cbr = textRd->getTextBreite( t->getText() );
-			t->release();
-			if( cbr + schriftSize > horizontalScrollBar->getScroll() + horizontalScrollBar->getScrollData()->anzeige )
-				horizontalScrollBar->scroll( cbr + schriftSize - br );
-			if( cbr - schriftSize < horizontalScrollBar->getScroll() )
-				horizontalScrollBar->scroll( cbr - schriftSize );
-		}
-	}
+    if( pos == -1 )
+        pos = cpos;
+    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;
+        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();
+        }
+        horizontalScrollBar->update( maxBr, br );
+        if( cbr > horizontalScrollBar->getScroll() + horizontalScrollBar->getScrollData()->anzeige )
+            horizontalScrollBar->scroll( cbr - br );
+        if( cbr < horizontalScrollBar->getScroll() )
+            horizontalScrollBar->scroll( cbr );
+    }
 }
 
 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 );
+    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::doMausEreignis( MausEreignis &me ) // Maus Ereignis
 {
-	bool nmakc = !me.verarbeitet;
-	if( hatStyleNicht( Style::Erlaubt ) || hatStyleNicht( Style::Sichtbar ) )
-	{
-		if( toolTip )
-			toolTip->setMausIn( 0 );
-		me.mx -= pos.x, me.my -= pos.y;
-		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 )
-		{
-			vertikalScrollBar->doMausMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me );
-			horizontalScrollBar->doMausMessage( rbr, gr.y - rbr * 2 - 15, gr.x - rbr * 2 - ( ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? 15 : 0 ), 15, me );
-			me.verarbeitet = 1;
-		}
-		me.mx += pos.x, me.my += pos.y;
-		mausKlick = 0;
-		return;
-	}
-	bool removeFokus = 0;
-	if( me.verarbeitet || !( me.mx >= pos.x && me.mx <= pos.x + gr.x && me.my >= pos.y && me.my <= pos.y + gr.y ) )
-	{
-		if( mausIn )
-		{
-			mausIn = 0;
-			if( toolTip )
-				toolTip->setMausIn( 0 );
-			MausEreignis me2;
-			me2.id = ME_Leaves;
-			me2.mx = me.mx;
-			me2.my = me.my;
-			me2.verarbeitet = 0;
-			doMausEreignis( me2 );
-			return;
-		}
-		removeFokus = 1;
-	}
-	if( !( me.mx >= pos.x && me.mx <= pos.x + gr.x && me.my >= pos.y && me.my <= pos.y + gr.y ) && me.id != ME_Leaves )
-	{
-		if( removeFokus && me.id == ME_RLinks )
-		{
-			me.mx -= pos.x, me.my -= pos.y;
-			if( hatStyle( Style::Fokus ) && mak && ( me.verarbeitet || mak( makParam, this, me ) ) )
-				removeStyle( Style::Fokus );
-			if( nmakc && me.verarbeitet && nMak )
-				me.verarbeitet = nMak( nmakParam, this, me );
-			me.mx += pos.x, me.my += pos.y;
-		}
-		if( toolTip )
-			toolTip->setMausIn( 0 );
-		return;
-	}
-	if( !mausIn && me.id != ME_Leaves )
-	{
-		mausIn = 1;
-		if( toolTip )
-			toolTip->setMausIn( 1 );
-		MausEreignis me2;
-		me2.id = ME_Betritt;
-		me2.mx = me.mx;
-		me2.my = me.my;
-		me2.verarbeitet = 0;
-		doMausEreignis( me2 );
-	}
-	me.mx -= pos.x, me.my -= pos.y;
-	if( mak && ( me.verarbeitet || mak( makParam, this, me ) ) )
-	{
-		if( removeFokus && me.id == ME_RLinks )
-			removeStyle( Style::Fokus );
-		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 ) )
-				{
-					if( nmakc && me.verarbeitet && nMak )
-						me.verarbeitet = nMak( nmakParam, this, me );
-					me.mx += pos.x, me.my += pos.y;
-					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 ) )
-				{
-					if( nmakc && me.verarbeitet && nMak )
-						me.verarbeitet = nMak( nmakParam, this, me );
-					me.mx += pos.x, me.my += pos.y;
-					return;
-				}
-			}
-			if( me.mx < gr.x - rbr - 15 )
-			{
-				if( textRd )
-				{
-                    textRd->setSchriftSize( schriftSize );
-					bool shift = TastenStand[ T_Shift ];
-					if( me.id == Framework::ME_PLinks )
-					{
-						int tbr = textRd->getTextBreite( text->getText() );
-						int thi = textRd->getTextHeight( text->getText() );
-						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 scrollBreite = ( vertikalScrollBar && hatStyle( Style::VScroll ) ) * 15;
-						if( hatStyle( Style::HCenter ) )
-							xxx -= ( ( ( gr.x - scrollBreite ) / 2 ) - tbr / 2 ) - rbr;
-						if( hatStyle( Style::VCenter ) && hatStyleNicht( Style::VScroll ) )
-							yyy -= ( ( ( gr.y - scrollHi ) / 2 ) - thi / 2 ) - rbr;
-						int pos = textRd->textPos( text->getText(), xxx, yyy );
-						if( pos != -1 )
-						{
-							if( shift )
-								begf = pos;
-							else
-							{
-								cpos = pos;
-								begf = pos;
-							}
-							rend = 1;
-							if( vertikalScrollBar && hatStyle( Style::VScroll ) )
-								updateVScroll( begf );
-							if( horizontalScrollBar && hatStyle( Style::HScroll ) )
-								updateHScroll( begf );
-						}
-						mausKlick = 1;
-					}
-					if( me.id == ME_Bewegung && mausKlick )
-					{
-						int tbr = textRd->getTextBreite( text->getText() );
-						int thi = textRd->getTextHeight( text->getText() );
-						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 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;
-						int pos = textRd->textPos( text->getText(), xxx, yyy );
-						if( pos != -1 )
-						{
-							if( begf != pos )
-								rend = 1;
-							begf = pos;
-							if( vertikalScrollBar && hatStyle( Style::VScroll ) )
-								updateVScroll( begf );
-							if( horizontalScrollBar && hatStyle( Style::HScroll ) )
-								updateHScroll( begf );
-						}
-					}
-					if( me.id == ME_RLinks )
-					{
-						if( !shift )
-						{
-							int tbr = textRd->getTextBreite( text->getText() );
-							int thi = textRd->getTextHeight( text->getText() );
-							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 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;
-							int pos = textRd->textPos( text->getText(), xxx, yyy );
-							if( pos != -1 )
-							{
-								begf = pos;
-								if( vertikalScrollBar && hatStyle( Style::VScroll ) )
-									updateVScroll( begf );
-								if( horizontalScrollBar && hatStyle( Style::HScroll ) )
-									updateHScroll( begf );
-							}
-							rend = 1;
-						}
-						mausKlick = 0;
-					}
-				}
-			}
-		}
-		me.verarbeitet = 1;
-	}
-	if( nmakc && me.verarbeitet && nMak )
-		me.verarbeitet = nMak( nmakParam, this, me );
-	me.mx += pos.x, me.my += pos.y;
+    bool nmakc = !me.verarbeitet;
+    if( hatStyleNicht( Style::Erlaubt ) || hatStyleNicht( Style::Sichtbar ) )
+    {
+        if( toolTip )
+            toolTip->setMausIn( 0 );
+        me.mx -= pos.x, me.my -= pos.y;
+        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 )
+        {
+            vertikalScrollBar->doMausMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me );
+            horizontalScrollBar->doMausMessage( rbr, gr.y - rbr * 2 - 15, gr.x - rbr * 2 - ( ( vertikalScrollBar && hatStyle( Style::VScroll ) ) ? 15 : 0 ), 15, me );
+            me.verarbeitet = 1;
+        }
+        me.mx += pos.x, me.my += pos.y;
+        mausKlick = 0;
+        return;
+    }
+    bool removeFokus = 0;
+    if( me.verarbeitet || !( me.mx >= pos.x && me.mx <= pos.x + gr.x && me.my >= pos.y && me.my <= pos.y + gr.y ) )
+    {
+        if( mausIn )
+        {
+            mausIn = 0;
+            if( toolTip )
+                toolTip->setMausIn( 0 );
+            MausEreignis me2;
+            me2.id = ME_Leaves;
+            me2.mx = me.mx;
+            me2.my = me.my;
+            me2.verarbeitet = 0;
+            doMausEreignis( me2 );
+            return;
+        }
+        removeFokus = 1;
+    }
+    if( !( me.mx >= pos.x && me.mx <= pos.x + gr.x && me.my >= pos.y && me.my <= pos.y + gr.y ) && me.id != ME_Leaves )
+    {
+        if( removeFokus && me.id == ME_RLinks )
+        {
+            me.mx -= pos.x, me.my -= pos.y;
+            if( hatStyle( Style::Fokus ) && mak && ( me.verarbeitet || mak( makParam, this, me ) ) )
+                removeStyle( Style::Fokus );
+            if( nmakc && me.verarbeitet && nMak )
+                me.verarbeitet = nMak( nmakParam, this, me );
+            me.mx += pos.x, me.my += pos.y;
+        }
+        if( toolTip )
+            toolTip->setMausIn( 0 );
+        return;
+    }
+    if( !mausIn && me.id != ME_Leaves )
+    {
+        mausIn = 1;
+        if( toolTip )
+            toolTip->setMausIn( 1 );
+        MausEreignis me2;
+        me2.id = ME_Betritt;
+        me2.mx = me.mx;
+        me2.my = me.my;
+        me2.verarbeitet = 0;
+        doMausEreignis( me2 );
+    }
+    me.mx -= pos.x, me.my -= pos.y;
+    if( mak && ( me.verarbeitet || mak( makParam, this, me ) ) )
+    {
+        if( removeFokus && me.id == ME_RLinks )
+            removeStyle( Style::Fokus );
+        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 ) )
+                {
+                    if( nmakc && me.verarbeitet && nMak )
+                        me.verarbeitet = nMak( nmakParam, this, me );
+                    me.mx += pos.x, me.my += pos.y;
+                    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 ) )
+                {
+                    if( nmakc && me.verarbeitet && nMak )
+                        me.verarbeitet = nMak( nmakParam, this, me );
+                    me.mx += pos.x, me.my += pos.y;
+                    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( s.onClick )
+                    s.onClick( 0, this, 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;
+    }
+    if( nmakc && me.verarbeitet && nMak )
+        me.verarbeitet = nMak( nmakParam, this, me );
+    me.mx += pos.x, me.my += pos.y;
 }
 
 void TextFeld::doTastaturEreignis( TastaturEreignis &te )
 {
-	bool ntakc = !te.verarbeitet;
-	if( te.verarbeitet || hatStyleNicht( Style::Fokus ) )
-		return;
-	if( !tak )
-		return;
-	++ref;
-	if( tak( takParam, this, te ) )
-	{
-		if( hatStyleNicht( Style::Erlaubt ) )
-		{
-			--ref;
-			if( !ref )
-				delete this;
-			return;
-		}
-		if( te.id == TE_Press )
-		{
-			bool shift = TastenStand[ T_Shift ];
-			bool strg = TastenStand[ T_Strg ];
-			switch( te.taste )
-			{
-			case T_Entf:
-				if( cpos != begf )
-					text->remove( cpos, begf );
-				else
-					text->remove( cpos, cpos + 1 );
-				begf = cpos;
-				rend = 1;
-				break;
-			case T_BackSpace:
-				if( cpos != begf )
-				{
-					text->remove( cpos, begf );
-					if( cpos > begf )
-						cpos -= cpos - begf;
-				}
-				else
-				{
-					text->remove( cpos - 1, cpos );
-					--cpos;
-				}
-				begf = cpos;
-				rend = 1;
-				break;
-			case T_Enter:
-				if( cpos != begf )
-				{
-					text->remove( begf, cpos );
-					if( cpos > begf )
-						cpos -= cpos - begf;
-				}
-				text->insert( cpos, '\n' );
-				++cpos;
-				begf = cpos;
-				rend = 1;
-				break;
-			case T_Links:
-				if( shift )
-				{
-					if( strg )
-						begf = text->getLKick( begf );
-					else
-						--begf;
-				}
-				else
-				{
-					if( strg )
-						cpos = text->getLKick( cpos );
-					else
-						--cpos;
-					begf = cpos;
-				}
-				rend = 1;
-				break;
-			case T_Oben:
-				if( shift )
-				{
-					begf = text->getOKick( begf );
-				}
-				else
-				{
-					cpos = text->getOKick( cpos );
-					begf = cpos;
-				}
-				rend = 1;
-				break;
-			case T_Rechts:
-				if( shift )
-				{
-					if( strg )
-						begf = text->getRKick( begf );
-					else
-						++begf;
-				}
-				else
-				{
-					if( strg )
-						cpos = text->getRKick( cpos );
-					else
-						++cpos;
-					begf = cpos;
-				}
-				rend = 1;
-				break;
-			case T_Unten:
-				if( shift )
-				{
-					begf = text->getUKick( begf );
-				}
-				else
-				{
-					cpos = text->getUKick( cpos );
-					begf = cpos;
-				}
-				rend = 1;
-				break;
-			default:
-				if( strg && te.id == TE_Press )
-				{
-					if( te.taste == 'c' || te.taste == 'C' )
-					{
-						if( begf != cpos )
-						{
-							int len = begf - cpos;
-							if( len < 0 )
-								len = -len;
-							char *txt = new char[ len + 1 ];
-							txt[ len ] = 0;
-							int beg = begf < cpos ? begf : cpos;
-							for( int i = beg; i < beg + len; ++i )
-								txt[ i - beg ] = text->getText()[ i ];
-							TextKopieren( txt );
-							delete[] txt;
-						}
-						else
-							TextKopieren( text->getText() );
-					}
-					if( te.taste == 'v' || te.taste == 'V' )
-					{
-						if( begf != cpos )
-						{
-							text->remove( begf, cpos );
-							if( cpos > begf )
-								cpos = begf;
-						}
-						char *txt = TextInsert();
-						text->insert( cpos, txt );
-						cpos += textLength( txt );
-						begf = cpos;
-						rend = 1;
-					}
-					break;
-				}
-				if( istSchreibbar( te.taste ) )
-				{
-					if( begf != cpos )
-					{
-						text->remove( begf, cpos );
-						if( cpos > begf )
-							cpos = begf;
-					}
-					text->insert( cpos, (char)te.taste );
-					++cpos;
-					begf = cpos;
-					rend = 1;
-				}
-				break;
-			}
-		}
-		if( cpos < 0 )
-			cpos = 0;
-		if( cpos > text->getLength() )
-			cpos = text->getLength();
-		if( begf < 0 )
-			begf = 0;
-		if( begf > text->getLength() )
-			begf = text->getLength();
-		if( hatStyle( Style::VScroll ) )
-			updateVScroll( begf );
-		if( hatStyle( Style::HScroll ) )
-			updateHScroll( begf );
-		te.verarbeitet = 1;
-	}
-	--ref;
-	if( ntakc && te.verarbeitet && nTak )
-		te.verarbeitet = nTak( ntakParam, this, te );
-	if( !ref )
-		delete this;
+    bool ntakc = !te.verarbeitet;
+    if( te.verarbeitet || hatStyleNicht( Style::Fokus ) )
+        return;
+    if( !tak )
+        return;
+    ++ref;
+    if( tak( takParam, this, te ) )
+    {
+        if( hatStyleNicht( Style::Erlaubt ) )
+        {
+            --ref;
+            if( !ref )
+                delete this;
+            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;
+    }
+    --ref;
+    if( ntakc && te.verarbeitet && nTak )
+        te.verarbeitet = nTak( ntakParam, this, te );
+    if( !ref )
+        delete this;
 }
 
 void TextFeld::render( Bild &zRObj ) // zeichenet nach zRObj
 {
-	if( hatStyleNicht( Style::Sichtbar ) )
-		return;
-	ZeichnungHintergrund::render( zRObj );
-	if( !text || !textRd )
-		return;
-	lockZeichnung();
-	if( !zRObj.setDrawOptions( innenPosition, innenSize ) )
-	{
-		unlockZeichnung();
-		return;
-	}
-	if( hatStyleNicht( Style::Mehrzeilig ) )
-		text->remove( '\n' );
-	if( hatStyleNicht( Style::Mehrfarbig ) )
-	{
-		while( text->hat( '\r' ) )
-			text->remove( text->positionVon( '\r' ), text->positionVon( '\r' ) + 11 );
-	}
-    textRd->setSchriftSize( schriftSize );
-	int tbr = textRd->getTextBreite( text->getText() );
-	int thi = textRd->getTextHeight( text->getText() );
-	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;
-	if( hatStyle( Style::Fokus ) && hatStyle( Style::Erlaubt ) )
-	{
-		if( istSchreibbar( showChar ) )
-		{
-			Text rt;
-			int len = text->getLength() - text->anzahlVon( '\n' ) - text->anzahlVon( '\r' ) * 11;
-			rt.fillText( showChar, len );
-			if( tickVal <= 0.5 )
-                textRd->renderText( xxx, yyy, rt, zRObj, sF, cpos, 0xFFFF5555, begf, 0xFF0000FF );
-			else
-                textRd->renderText( xxx, yyy, rt, zRObj, sF, cpos, 0x00000000, begf, 0xFF0000FF );
-		}
-		else
-		{
-			if( tickVal <= 0.5 )
-                textRd->renderText( xxx, yyy, text->getText(), zRObj, sF, cpos, 0xFFFF5555, begf, 0xFF0000FF );
-			else
-                textRd->renderText( xxx, yyy, text->getText(), zRObj, sF, cpos, 0x00000000, begf, 0xFF0000FF );
-		}
-	}
-	else
-	{
-		if( istSchreibbar( showChar ) )
-		{
-			Text rt;
-			int len = text->getLength() - text->anzahlVon( '\n' ) - text->anzahlVon( '\r' ) * 11;
-			rt.fillText( showChar, len );
-            textRd->renderText( xxx, yyy, rt, zRObj, sF );
-		}
-		else
-            textRd->renderText( xxx, yyy, text->getText(), zRObj, sF );
-	}
-	zRObj.releaseDrawOptions();
-	unlockZeichnung();
+    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()->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::Erlaubt ) )
+            zRObj.drawLinieV( oldX, y, tm->zCurrentRenderer()->getZeilenHeight(), 0xFFFF5555 );
+        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( !text )
-		return 0;
-	return text->getThis();
+    if( !tm->text )
+        return 0;
+    return tm->text->getThis();
 }
 
 Text *TextFeld::zText() const // gibt den Text zurück
 {
-	return text;
+    return tm->text;
 }
 
 Schrift *TextFeld::getSchrift() const// gint getThis der Schrift Zurück
 {
-	if( !textRd )
-		return 0;
-	return textRd->getSchrift();
+    tm->resetIteration();
+    return tm->zCurrentRenderer()->getSchrift();
 }
 
 Schrift *TextFeld::zSchrift() const// gibt die Schrift zurück
 {
-	return textRd ? textRd->zSchrift() : 0;
+    tm->resetIteration();
+    return tm->zCurrentRenderer()->zSchrift();
+}
+
+// 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
 {
-    return textRd ? textRd->getThis() : 0;
+    tm->resetIteration();
+    return tm->zCurrentRenderer()->getThis();
 }
 
 TextRenderer *TextFeld::zTextRenderer() const
 {
-    return textRd;
+    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
 {
-	return schriftSize;
+    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
 {
-	return sF;
+    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;
+    return showChar;
 }
 
 int TextFeld::getCursorPos() const
 {
-	return cpos;
+    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
+{
+    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();
+        if( mx >= x && mx < x + tmpx && my >= y && my < maxLH + tmpy )
+            return i;
+        if( mx < x + tmpx && my < maxLH + tmpy )
+            return -1;
+        x += tmpx + tm->zCurrentRenderer()->getZeichenAbstand();
+        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();
 }
 
-int TextFeld::getSelectionPos() const
+// Gibt den Style eines bestimmten zeichens zurück
+//  index: Der index des Zeichensf
+TextFeld::TextStyle TextFeld::getTextStyle( int index ) const
 {
-	return begf;
+    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->setSchriftSize( schriftSize );
-	if( textRd )
-		obj->setSchriftZ( textRd->getSchrift() );
-	if( text )
-		obj->setText( text->getText() );
-	obj->setHintergrundFarbe( hintergrundFarbe );
-	obj->setSchriftFarbe( sF );
-	if( hintergrundFeld )
-		obj->setAlphaFeldZ( (AlphaFeld*)hintergrundFeld->dublizieren() );
-	if( rahmen )
-		obj->setRahmenZ( (Rahmen*)rahmen->dublizieren() );
-	if( hintergrundBild )
-		obj->setHintergrundBild( 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 );
-	obj->setAuswahl( begf, cpos );
-	return obj;
+    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 = 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( 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;
 }

+ 152 - 14
TextFeld.h

@@ -2,6 +2,7 @@
 #define TextFeld_H
 
 #include "Zeichnung.h"
+#include "Array.h"
 
 namespace Framework
 {
@@ -18,30 +19,92 @@ namespace Framework
     class TextFeld : public ZeichnungHintergrund
     {
     public:
+        struct TextStyle
+        {
+            int beginIndex;
+            unsigned char fontSize;
+            int fontColor;
+            int selectedColor;
+            int selectedBackcroundColor;
+            bool underlined;
+            bool selected;
+            MausAktion onClick;
+            char rendererIndex;
+            __declspec( dllexport ) bool operator==( const TextStyle& rhs );
+        };
+
+        class TextStyleManager
+        {
+        protected:
+            RCArray< TextRenderer > *renderer;
+            Array< TextStyle > textStyle;
+            int index;
+            int styleIndex;
+            TextStyle current;
+            Text *text;
+            int ref;
+
+        public:
+            __declspec( dllexport ) TextStyleManager();
+            __declspec( dllexport ) virtual ~TextStyleManager();
+            // Setzt den Style eines Textabschnittes
+            //  begin: die startposition des Abschnittes
+            //  end: die endposition des Abschnittes (nicht enthalten)
+            __declspec( dllexport ) void setTextStyle( int begin, int end, TextStyle style );
+            // Entfernt einen Textabschnitt
+            //  begin: der index des ersten betroffenen zeichens
+            //  end: der index des ersten zeichens nach dem abschnitt
+            __declspec( dllexport ) void removeText( int begin, int end );
+            // Fügt ein Text an einer bestimmten Position ein
+            //  pos: die position des neuen Textausschnitts
+            //  text: der neue Text
+            __declspec( dllexport ) void insertText( int pos, const char *text );
+            // Entfernt nicht benötiegte gleiche styles
+            __declspec( dllexport ) void cleanupStyles();
+            // gibt eine referenz auf das style objekt zurück
+            __declspec( dllexport ) TextStyle &currentStyle();
+            // gibt den aktuellen text renderer zurück
+            __declspec( dllexport ) TextRenderer *zCurrentRenderer();
+            // ändert den inhalt des style objektes auf den style des nächsten zeichens
+            //  gibt 0 zurück falls es kein weiteres zeichen gibt
+            __declspec( dllexport ) bool nextStyle();
+            // ändert den inhalt des style objektes auf den style des ersten zeichens
+            __declspec( dllexport ) void resetIteration();
+            // Gibt den Style eines bestimmten zeichens zurück
+            //  index: Der index des Zeichensf
+            __declspec( dllexport ) TextStyle getTextStyle( int index ) const;
+            // Erhöht den Reference Counting Zähler.
+            //  return: this.
+            __declspec( dllexport ) TextStyleManager *getThis();
+            // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
+            //  return: 0.
+            __declspec( dllexport ) virtual TextStyleManager *release();
+            friend TextFeld;
+        };
+
         class Style : public ZeichnungHintergrund::Style
         {
         public:
             const static __int64 Mehrzeilig = 0x001000; // Wenn dieser Flag nicht gesetzt wird, werden alle Zeilenumbrüche automatisch aus dem Text entfernt
             const static __int64 HCenter = 0x002000; // Wenn dieser Flag gesetzt wird, wird der Text genau in der horizontaen Mitte des Feldes plaziert
             const static __int64 VCenter = 0x004000; // Wenn dieser Flag gesetzt wird, wird der Text genau in der vertikalen Mitte des Feldes plaziert
-            const static __int64 Mehrfarbig = 0x008000; // Wenn dieser Flag gesetzt wird, kann der Text mehrfarbig sein. Die Textfarbe wird im Text selbst gesetzt mit "\r0xAARRGGBB"
-
+            //const static __int64 Styled = 0x008000; // Wenn dieser Flag gesetzt wird, kann der Text verschiedene Styles haben
+            
             const static __int64 Center = HCenter | VCenter; // Vereint die Flags HCenter und VCenter
             const static __int64 TextFeld = Sichtbar | Erlaubt | Rahmen | Buffered | VCenter; // Vereint die Flags Sichtbar, Erlaubt, Rahmen, Buffered, VCenter
-            const static __int64 Text = Sichtbar | Mehrfarbig | Mehrzeilig; // Vereint die Flags Sichtbar, Mehrfarbig, Mehrzeilig
-            const static __int64 TextGebiet = Sichtbar | Erlaubt | Rahmen | Hintergrund | Mehrfarbig | Mehrzeilig | VScroll; // Vereint die Flags Sichtbar, Erlaubt, Rahmen, Hintergrund, Mehrzeilig, Mehrfarbig, VScroll
+            const static __int64 Text = Sichtbar | /*Styled |*/ Mehrzeilig; // Vereint die Flags Sichtbar, Mehrfarbig, Mehrzeilig
+            const static __int64 TextGebiet = Sichtbar | Erlaubt | Rahmen | Hintergrund | /*Styled |*/ Mehrzeilig | VScroll; // Vereint die Flags Sichtbar, Erlaubt, Rahmen, Hintergrund, Mehrzeilig, Mehrfarbig, VScroll
             const static __int64 Scroll = VScroll | HScroll; // Vereint die Flags VScroll und HScroll
         };
     private:
-        unsigned char schriftSize;
-        TextRenderer *textRd;
-        Text *text;
-        int sF;
+        TextStyleManager *tm;
         unsigned char showChar;
-        int begf, cpos;
+        int cpos;
         double tickVal;
         bool mausKlick;
-    protected:
+
+        int getTextHeight() const;
+        int getTextWidth() const;
 
     public:
         // Konstruktor 
@@ -57,28 +120,68 @@ namespace Framework
         // setzt den Text des Textfeldes
         //  txt: der Text
         __declspec( dllexport ) void setText( const char *txt );
+        // Setzt den Style eines Textabschnittes
+        //  begin: die startposition des Abschnittes
+        //  end: die endposition des Abschnittes (nicht enthalten)
+        __declspec( dllexport ) void setTextStyle( int begin, int end, TextStyle style );
         // Fügt eine Zeile an den Text an
         //  zeile: Die neue Zeile
         __declspec( dllexport ) void addZeile( const char *zeile );
-        // Setzt den ausgewählten textabschnitt fest (benötigt Flag zum Zeichnen: Erlaubt, Fokus)
+        // Deselectiert alle textabschnitte
+        __declspec( dllexport ) void deselectAuswahl();
+        // Setzt den ausgewählten textabschnitt fest
         //  pos1: Die Cursorposition im Text
         //  pos2: Die Position im Text, bis zu der der Text eingefärbt werden soll
         __declspec( dllexport ) void setAuswahl( int pos1, int pos2 );
-        // Setzt den ausgewählten textabschnitt fest (benötigt Flag zum Zeichnen: Erlaubt, Fokus)
+        // Setzt den ausgewählten textabschnitt fest
         //  auswahl: Ein punkt mit x als Cursorposition und y als der Position, bis zu der der Text eingefärbt werden soll
         __declspec( dllexport ) void setAuswahl( Punkt &auswahl );
+        // Setzt den ausgewählten textabschnitt fest
+        //  pos1: Die Cursorposition im Text
+        //  pos2: Die Position im Text, bis zu der der Text eingefärbt werden soll
+        __declspec( dllexport ) void addAuswahl( int pos1, int pos2 );
+        // Setzt den ausgewählten textabschnitt fest
+        //  auswahl: Ein punkt mit x als Cursorposition und y als der Position, bis zu der der Text eingefärbt werden soll
+        __declspec( dllexport ) void addAuswahl( Punkt &auswahl );
+        // 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
+        __declspec( dllexport ) void invertAuswahl( int begin, int end );
+        // ersetzt alle ausgewählten Textabschnitte mit einem text
+        //  text: der neue Text
+        __declspec( dllexport ) void replaceAuswahl( const char *text );
         // Setzt den verwendeten TextRenderer
         //  textRd: Der Textrenderer
         __declspec( dllexport ) void setTextRendererZ( TextRenderer *textRd );
+        // Fügt einen TextRenderer hinzu
+        //  textRd: Der Textrenderer
+        __declspec( dllexport ) void addTextRendererZ( TextRenderer *textRd );
+        // Setzt die verwendeten TextRenderer
+        //  textRd: Die Textrenderer
+        __declspec( dllexport ) void setTextRendererZ( RCArray< TextRenderer > *textRd );
         // Setzt einen Zeiger zur Schrift
         //  schrift: Die Schrift, die zum Textzeichnen verwendet werden soll.
         __declspec( dllexport ) void setSchriftZ( Schrift *schrift );
+        // Setzt einen Zeiger zur Schrift
+        //  rendererIndex: Der Index des Renderers dessen Schrift gesetzt werden soll
+        //  schrift: Die Schrift, die zum Textzeichnen verwendet werden soll.
+        __declspec( dllexport ) void setSchriftZ( int rendererIndex, Schrift *schrift );
         // Setzt die Schriftgröße (Standart: 12)
         //  gr: Die Schriftgröße, die zum Textzeichnen verwendet werden soll
         __declspec( dllexport ) void setSchriftSize( unsigned char gr );
+        // 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
+        __declspec( dllexport ) void setSchriftSize( int begin, int end, unsigned char gr );
         // Setzt die Schrift Farbe
         //  fc: Die Farbe, die zum Textzeichnen verwendet werden soll
         __declspec( dllexport ) void setSchriftFarbe( int fc );
+        // 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
+        __declspec( dllexport ) void setSchriftFarbe( int begin, int end, int fc );
         // Legt einen Buchstaben fest, der zum zeichnen verwendet werden soll, unabhängig vom Text des Textfeldes (benötigt Flag zum Zeichnen: Rahmen)
         //  c: Der Buchstabe, der gezeichnet werden soll
         // Beispiel: setShowChar( '*' ); Bei Passwort Textfeldern
@@ -115,22 +218,57 @@ namespace Framework
         // Gibt die Schrift ohne erhöhten Reference Counter zurük
         //  return: 0, falls die Schrift nicht gesetzt wurde
         __declspec( dllexport ) Schrift *zSchrift() const;
+        // Gibt die Schrift zurück.
+        //  rendererIndex: Der Index des Renderers dessen Schrift zurückgegeben werden soll
+        //  return: 0, falls die Schrift nicht gesetzt wurde
+        __declspec( dllexport ) Schrift *getSchrift( int rendererIndex ) const;
+        // 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
+        __declspec( dllexport ) Schrift *zSchrift( int rendererIndex ) const;
         // Gibt den TextRenderer zurück.
         //  return: 0, falls der TextRenderer nicht gesetzt wurde
         __declspec( dllexport ) TextRenderer *getTextRenderer() const;
         // Gibt dien TextRenderer ohne erhöhten Reference Counter zurük
         //  return: 0, falls der TextRenderer nicht gesetzt wurde
         __declspec( dllexport ) TextRenderer *zTextRenderer() const;
+        // Gibt den TextRenderer zurück.
+        //  index: Der Index des Renderers der zurückgegeben werden soll
+        //  return: 0, falls der TextRenderer nicht gesetzt wurde
+        __declspec( dllexport ) TextRenderer *getTextRenderer( int index ) const;
+        // 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
+        __declspec( dllexport ) TextRenderer *zTextRenderer( int index ) const;
         // Gibt die Schriftgröße zurück
         __declspec( dllexport ) unsigned char getSchriftSize() const;
+        // Gibt die Schriftgröße zurück
+        //  index: Der Index des Zeichens
+        __declspec( dllexport ) unsigned char getSchriftSize( int index ) const;
         // Gibt die Schriftfarbe im A8R8G8B8 Format zurück
         __declspec( dllexport ) int getSchriftFarbe() const;
+        // Gibt die Schriftfarbe im A8R8G8B8 Format zurück
+        //  index: Der Index des Zeichens
+        __declspec( dllexport ) int getSchriftFarbe( int index ) const;
         // Gibt den Anzeigebuchstabe zurück
         __declspec( dllexport ) unsigned char getShowChar() const;
         // Gibt die Cursorposition zurück
         __declspec( dllexport ) int getCursorPos() const;
-        // Gibt den Index des Buchstaben zurück, con dem an der Text bis zur Cursorposition eingefärbt ist
-        __declspec( dllexport ) int getSelectionPos() const;
+        // Gibt 1 zurück wenn das Zeichen ausgewählt ist
+        //  index: Der Index des Zeichens
+        __declspec( dllexport ) bool isCharSelected( int index ) const;
+        // 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
+        __declspec( dllexport ) int getTextIndexAt( int mx, int my ) const;
+        // 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
+        __declspec( dllexport ) int getCurserPosAt( int mx, int my ) const;
+        // Gibt den Style eines bestimmten zeichens zurück
+        //  index: Der index des Zeichensf
+        __declspec( dllexport ) TextStyle getTextStyle( int index ) const;
         // Erzeugt eine Komplette Kopie des Textfeldes, welches ohne auswirkungen verändert werden kann
         __declspec( dllexport ) Zeichnung *dublizieren() const override;
     };

+ 2 - 2
ToolTip.cpp

@@ -114,8 +114,8 @@ bool ToolTip::tick( double tickVal )
 {
     for( auto z = members->getIterator(); z; z++ )
     {
-        size.x = max( size.x, z->getX() + z->getBreite() + 2 * getRahmenBreite() );
-        size.y = max( size.y, z->getY() + z->getHeight() + 2 * getRahmenBreite() );
+        size.x = MAX( size.x, z->getX() + z->getBreite() + 2 * getRahmenBreite() );
+        size.y = MAX( size.y, z->getY() + z->getHeight() + 2 * getRahmenBreite() );
     }
     this->tval += tickVal * animationSpeed;
     int val = (int)this->tval;