#include "TextFeld.h" #include #include "AlphaFeld.h" #include "Bild.h" #include "Fenster.h" #include "Globals.h" #include "MausEreignis.h" #include "Rahmen.h" #include "Schrift.h" #include "Scroll.h" #include "TastaturEreignis.h" #include "Text.h" #include "ToolTip.h" using namespace Framework; #ifndef test # define test bool TextStyle::equals(const TextStyle& rhs) { return fontSize == rhs.fontSize && fontColor == rhs.fontColor && selectedColor == rhs.selectedColor && selectedBackcroundColor == rhs.selectedBackcroundColor && underlined == rhs.underlined && selected == rhs.selected && interactParam == rhs.interactParam && rendererIndex == rhs.rendererIndex; } #endif TextFeld::TextStyleManager::TextStyleManager() : ReferenceCounter(), renderer(new RCArray()), index(0), styleIndex(0), text(0) { current.beginIndex = 0; current.fontColor = 0xFFFFFFFF; current.fontSize = 12; current.selected = 0; current.selectedColor = 0xFFFFFFFF; current.selectedBackcroundColor = 0xFF0000FF; current.underlined = 0; current.interactParam = 0; current.rendererIndex = 0; textStyle.add(current); } TextFeld::TextStyleManager::~TextStyleManager() { if (renderer) renderer->release(); if (text) text->release(); } // Sets the style of a text section // begin: the start position of the section // end: the end position of the section (not included) void TextFeld::TextStyleManager::setTextStyle( int begin, int end, TextStyle style) { if (begin < 0 || begin > end || begin > text->getLength()) return; int sc = textStyle.getEintragAnzahl(); int index = -1; TextStyle s = textStyle.get(0); // search to the correct position in the style array 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) { // append styles at the end textStyle.add(style); textStyle.add(s); } else { // insert into the middle of the style array textStyle.add(style, index); for (int i = index + 1; i < sc + 1; i++) { // remove styles that were overwritten 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(); } // Removes a text section // begin: the index of the first affected character // end: the index of the first character after the section void TextFeld::TextStyleManager::removeText(int begin, int end) { int sc = textStyle.getEintragAnzahl(); for (int i = 1; i < sc; i++) { TextStyle s = textStyle.get(i); if (s.beginIndex >= begin && s.beginIndex < end) { textStyle.remove(i); i--; sc--; } if (s.beginIndex >= end) { s.beginIndex -= end - begin; textStyle.set(s, i); } } text->remove(begin, end); cleanupStyles(); } // Inserts text at a specific position // pos: the position of the new text section // text: the new 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(); } // Removes unnecessary duplicate styles void TextFeld::TextStyleManager::cleanupStyles() { int sc = textStyle.getEintragAnzahl(); TextStyle last = textStyle.get(0); for (int i = 1; i < sc; i++) { if (textStyle.get(i).beginIndex == last.beginIndex) { last = textStyle.get(i); textStyle.remove(i - 1); i--; sc--; continue; } if (textStyle.get(i).equals(last) || (text && textStyle.get(i).beginIndex > text->getLength())) { textStyle.remove(i); i--; sc--; } else last = textStyle.get(i); } } // returns a reference to the style object TextStyle& TextFeld::TextStyleManager::currentStyle() { return current; } // returns the current text renderer TextRenderer* TextFeld::TextStyleManager::zCurrentRenderer() { if (renderer->getEintragAnzahl() == 0) return 0; TextRenderer* tr = renderer->z(current.rendererIndex); if (!tr) tr = renderer->z(0); if (tr) tr->setSchriftSize(current.fontSize); return tr; } // changes the content of the style object to the style of the next character 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(); } // changes the content of the style object to the style of the specified // character // index: the index of the character to jump to // returns 0 if the character does not exist bool TextFeld::TextStyleManager::stepTo(int index) { resetIteration(); while (this->index < index && nextStyle()) ; return text && this->index == index; } // changes the content of the style object to the style of the first character void TextFeld::TextStyleManager::resetIteration() { index = 0; styleIndex = 0; current = textStyle.get(0); } // Returns the style of a specific character\n// index: The index of the // character TextStyle TextFeld::TextStyleManager::getTextStyle(int index) const { TextStyle last = textStyle.get(0); int ind = 0; for (auto i = textStyle.begin(); i && ind <= index; ind++) { if (i._.beginIndex <= ind) { last = i; i++; } } return last; } // Contents of the TextFeld class from TextFeld.h // Constructor TextFeld::TextFeld() : ZeichnungHintergrund(), tm(new TextStyleManager()), autoLineBreakSpacing(0), showChar(0), cpos(0), tickVal(0), mausKlick(0) { charEvent = 0; horizontalScrollBar = new HScrollBar(); vertikalScrollBar = new VScrollBar(); this->setMausEreignis(_ret1ME); this->setTastaturEreignis(_ret1TE); } // Destructor TextFeld::~TextFeld() { tm->release(); if (autoLineBreakSpacing) autoLineBreakSpacing->release(); } void TextFeld::doMausEreignis(MausEreignis& me, bool userRet) // Mouse event { if (!userRet) return; if (hatStyleNicht(Style::Editierbar)) { int rbr = 0; if (rahmen) rbr = rahmen->getRBreite(); if (((vertikalScrollBar && hatStyle(Style::VScroll)) || (horizontalScrollBar && hatStyle(Style::HScroll))) && me.mx > rbr && me.mx < gr.x - rbr && me.my > rbr && me.my < gr.y - rbr) { me.verarbeitet |= vertikalScrollBar->doMausMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me); me.verarbeitet |= horizontalScrollBar->doMausMessage(rbr, gr.y - rbr * 2 - 15, gr.x - rbr * 2 - ((vertikalScrollBar && hatStyle(Style::VScroll)) ? 15 : 0), 15, me); } if (me.mx >= 0 && me.mx <= gr.x && me.my >= 0 && me.my <= gr.y && !me.verarbeitet && hatStyle(Style::Sichtbar)) { int scrollHi = (vertikalScrollBar && hatStyle(Style::VScroll)) ? vertikalScrollBar->getScroll() : 0; int scrollBr = (horizontalScrollBar && hatStyle(Style::HScroll)) ? horizontalScrollBar->getScroll() : 0; int xxx = me.mx - rbr + scrollBr; int yyy = me.my - rbr + scrollHi; int mausChar = getTextIndexAt(xxx, yyy); if (mausChar >= 0) { TextStyle s = tm->getTextStyle(mausChar); if (charEvent && s.interactParam) charEvent(mausChar, s.interactParam, me); } if (charEvent) me.verarbeitet = 1; } mausKlick = 0; return; } if (!me.verarbeitet) { if (hatStyleNicht(Style::Fokus)) { mausKlick = 0; if (me.id == Framework::ME_PLinks) addStyle(Style::Fokus); } int rbr = 0; if (rahmen) rbr = rahmen->getRBreite(); if (vertikalScrollBar && hatStyle(Style::VScroll)) { if (vertikalScrollBar->doMausMessage( gr.x - rbr - 15, rbr, 15, gr.y - rbr * 2, me)) { me.verarbeitet = 1; return; } } if (horizontalScrollBar && hatStyle(Style::HScroll)) { if (horizontalScrollBar->doMausMessage(rbr, gr.y - rbr - 15, gr.x - rbr * 2 - ((vertikalScrollBar && hatStyle(Style::VScroll)) ? 15 : 0), 15, me)) { me.verarbeitet = 1; return; } } bool shift = getTastenStand(T_Shift); bool strg = getTastenStand(T_Strg); int tbr = getTextWidth(); int thi = getTextHeight(); int scrollHi = (vertikalScrollBar && hatStyle(Style::VScroll)) ? vertikalScrollBar->getScroll() : 0; int scrollBr = (horizontalScrollBar && hatStyle(Style::HScroll)) ? horizontalScrollBar->getScroll() : 0; int xxx = me.mx - rbr + scrollBr; int yyy = me.my - rbr + scrollHi; int mausChar = getTextIndexAt(xxx, yyy); int scrollBreite = (vertikalScrollBar && hatStyle(Style::VScroll)) * 15; int scrollHeight = (horizontalScrollBar && hatStyle(Style::HScroll)) * 15; if (hatStyle(Style::HCenter)) xxx -= (((gr.x - scrollBreite) / 2) - tbr / 2) - rbr; if (hatStyle(Style::VCenter) && hatStyleNicht(Style::VScroll)) yyy -= (((gr.y - scrollHeight) / 2) - thi / 2) - rbr; if (mausChar >= 0) { TextStyle s = tm->getTextStyle(mausChar); if (charEvent) charEvent(mausChar, s.interactParam, me); } if (me.mx < gr.x - rbr - 15) { if (tm->renderer) { int ncpos = getCurserPosAt(xxx, yyy); if (me.id == Framework::ME_PLinks) { if (ncpos != -1) { if (shift && cpos != ncpos) addAuswahl(MIN(cpos, ncpos), MAX(cpos, ncpos)); else if (!shift && !mausKlick && !strg) deselectAuswahl(); cpos = ncpos; rend = 1; if (vertikalScrollBar && hatStyle(Style::VScroll)) updateVScroll(); if (horizontalScrollBar && hatStyle(Style::HScroll)) updateHScroll(); } mausKlick = 1; } if (me.id == ME_Bewegung && mausKlick) { if (ncpos != -1) { rend = 1; if (cpos != ncpos) invertAuswahl(MIN(cpos, ncpos), MAX(cpos, ncpos)); cpos = ncpos; if (vertikalScrollBar && hatStyle(Style::VScroll)) updateVScroll(cpos); if (horizontalScrollBar && hatStyle(Style::HScroll)) updateHScroll(cpos); } } if (me.id == ME_RLinks) { if (ncpos != -1) { rend = 1; if (cpos != ncpos) invertAuswahl(MIN(cpos, ncpos), MAX(cpos, ncpos)); cpos = ncpos; if (vertikalScrollBar && hatStyle(Style::VScroll)) updateVScroll(cpos); if (horizontalScrollBar && hatStyle(Style::HScroll)) updateHScroll(cpos); } mausKlick = 0; } } } } me.verarbeitet = 1; } int TextFeld::getTextHeight() const { if (!tm || !tm->text) return 0; tm->resetIteration(); int th = 0; int len = tm->text->getLength(); const char* text = tm->text->getText(); Text txtWithLineBreaks; if (hatStyle(Style::AutoLineBreak)) { txtWithLineBreaks = addLineBreaksToText(tm->text->getText(), autoLineBreakSpacing ? autoLineBreakSpacing->getText() : ""); text = txtWithLineBreaks; len = txtWithLineBreaks.getLength(); } int max = 0; int abstand = 0; for (int i = 0; i < len; i++) { if (text[i] == '\n') { th += max + abstand; abstand = 0; max = 0; tm->nextStyle(); continue; } TextRenderer* r = tm->zCurrentRenderer(); if (r) { int tmp = r->getZeilenHeight(); max = max >= tmp ? max : tmp; if (max == tmp) abstand = r->getZeilenAbstand(); } tm->nextStyle(); } if (max > 0) th += max; return th; } int TextFeld::getTextWidth() const { if (!tm || !tm->text) return 0; tm->resetIteration(); int maxBr = 0; int len = tm->text->getLength(); const char* text = tm->text->getText(); Text txtWithLineBreaks; if (hatStyle(Style::AutoLineBreak)) { txtWithLineBreaks = addLineBreaksToText(tm->text->getText(), autoLineBreakSpacing ? autoLineBreakSpacing->getText() : ""); text = txtWithLineBreaks; len = txtWithLineBreaks.getLength(); } int lineBr = 0; char buff[] = {0, 0}; for (int i = 0; i < len; i++) { buff[0] = text[i]; if (text[i] == '\n') { maxBr = maxBr >= lineBr ? maxBr : lineBr; lineBr = 0; tm->nextStyle(); continue; } TextRenderer* r = tm->zCurrentRenderer(); if (r) lineBr += r->getTextBreite(buff); tm->nextStyle(); } if (lineBr > 0) maxBr = maxBr >= lineBr ? maxBr : lineBr; return maxBr; } // charEvent: a function that is called when the mouse is on a // specific character and the interactParam in the style != 0 // call: charEvent( charIndex, interactParam, mausEreignis ); void TextFeld::setCharEvent( std::function charEvent) { this->charEvent = charEvent; } void TextFeld::setText(Text* txt) // sets the displayed text { lockZeichnung(); if (!tm->text) tm->text = new Text(); tm->text->setText(*txt); if (hatStyle(Style::VScroll)) updateVScroll(); if (hatStyle(Style::HScroll)) updateHScroll(); unlockZeichnung(); rend = 1; txt->release(); } void TextFeld::setTextZ(Text* txt) // sets a pointer to the displayed text { lockZeichnung(); if (tm->text) tm->text->release(); tm->text = txt; if (hatStyle(Style::VScroll)) updateVScroll(); if (hatStyle(Style::HScroll)) updateHScroll(); rend = 1; unlockZeichnung(); } void TextFeld::setText(const char* txt) // sets the displayed text { lockZeichnung(); if (!tm->text) tm->text = new Text(); tm->text->setText(txt); if (hatStyle(Style::VScroll)) updateVScroll(); if (hatStyle(Style::HScroll)) updateHScroll(); rend = 1; unlockZeichnung(); } // sets the text with styles // txt: the text // format: \x1: enables underline // \x2FF: sets the font size for the following text. // FF is a two-digit hex value // \x3AARRGGBB: sets the font color. // AARRGGBB is an 8-digit hex value with two characters each // for alpha, red, green and blue // \x4AARRGGBB: sets the color of the selected text. // AARRGGBB is an 8-digit hex value with two characters each // for alpha, red, green and blue // \x5AARRGGBB: sets the background color of the selected text. // AARRGGBB is an 8-digit hex value with two characters each // for alpha, red, green and blue // \x6FF: sets text renderer index. // FF is a two-digit hex value // \x7: deactivates underline // \x8FFFFFFFF: set interact param. // FFFFFFFF is an 8-digit hex value void TextFeld::setFormattedText(const char* txt) { lockZeichnung(); if (!tm->text) tm->text = new Text(); tm->textStyle.leeren(); TextStyle current; current.beginIndex = 0; current.fontColor = 0xFFFFFFFF; current.fontSize = 12; current.selected = 0; current.selectedColor = 0xFFFFFFFF; current.selectedBackcroundColor = 0xFF0000FF; current.underlined = 0; current.interactParam = 0; current.rendererIndex = 0; tm->textStyle.add(current); Text result = ""; for (int i = 0; 1; i++) { bool br = 0; current.beginIndex = result.getLength(); switch (txt[i]) { case 0: br = 1; break; case 1: current.underlined = 1; tm->textStyle.add(current); break; case 2: { Text p = "0x"; p.append(txt + i + 1, 2); current.fontSize = (unsigned char)(int)p; tm->textStyle.add(current); i += 2; break; } case 3: { Text p = "0x"; p.append(txt + i + 1, 8); current.fontColor = (int)p; tm->textStyle.add(current); i += 8; } break; case 4: { Text p = "0x"; p.append(txt + i + 1, 8); current.selectedColor = (int)p; tm->textStyle.add(current); i += 8; break; } case 5: { Text p = "0x"; p.append(txt + i + 1, 8); current.selectedBackcroundColor = (int)p; tm->textStyle.add(current); i += 8; break; } case 6: { Text p = "0x"; p.append(txt + i + 1, 2); current.rendererIndex = (unsigned char)(int)p; tm->textStyle.add(current); i += 2; } break; case 7: current.underlined = 0; tm->textStyle.add(current); break; case 8: { Text p = "0x"; p.append(txt + i + 1, 8); current.interactParam = (int)p; tm->textStyle.add(current); i += 8; } break; default: result.append(txt[i]); } if (br) break; } tm->text->setText(result); tm->cleanupStyles(); if (hatStyle(Style::VScroll)) updateVScroll(); if (hatStyle(Style::HScroll)) updateHScroll(); rend = 1; unlockZeichnung(); } // inserts line breaks so that the text does not exceed the width of the text // field void TextFeld::addLineBreaks(const char* spacing) { if (!tm->text) return; setFormattedText(addLineBreaksToText(tm->text->getText(), spacing)); } Text TextFeld::addLineBreaksToText( const char* txt, const char* spacing, bool includeFormat) const { int lastPos = -1; int lastPos2 = -1; int x = 0; Text result = ""; int len = (int)strlen(txt); int maxBr = getBreite(); if (hatStyle(Style::VScroll) && vertikalScrollBar) maxBr -= 15; tm->resetIteration(); TextStyle last; last.beginIndex = 0; last.fontColor = 0xFFFFFFFF; last.fontSize = 12; last.selected = 0; last.selectedColor = 0xFFFFFFFF; last.selectedBackcroundColor = 0xFF0000FF; last.underlined = 0; last.interactParam = 0; last.rendererIndex = 0; for (int i = 0; i < len; ++i) { if (last.fontSize != tm->current.fontSize && includeFormat) { Text param("\x2"); param.appendHex((char)tm->current.fontSize); result += param; last.fontSize = tm->current.fontSize; } if (last.fontColor != tm->current.fontColor && includeFormat) { Text param("\x3"); param.appendHex(tm->current.fontColor); result += param; last.fontColor = tm->current.fontColor; } if (last.selectedColor != tm->current.selectedColor && includeFormat) { Text param("\x4"); param.appendHex(tm->current.selectedColor); result += param; last.selectedColor = tm->current.selectedColor; } if (last.selectedBackcroundColor != tm->current.selectedBackcroundColor && includeFormat) { Text param("\x5"); param.appendHex(tm->current.selectedBackcroundColor); result += param; last.selectedBackcroundColor = tm->current.selectedBackcroundColor; } if (last.underlined != tm->current.underlined && includeFormat) { char tmp[2] = {tm->current.underlined ? (char)1 : (char)7, 0}; result += tmp; last.underlined = tm->current.underlined; } if (last.interactParam != tm->current.interactParam && includeFormat) { Text param("\x8"); param.appendHex(tm->current.interactParam); result += param; last.interactParam = tm->current.interactParam; } if (last.rendererIndex != tm->current.rendererIndex && includeFormat) { Text param("\x6"); param.appendHex((char)tm->current.rendererIndex); result += param; last.rendererIndex = tm->current.rendererIndex; } if (txt[i] == ' ') { lastPos = i; lastPos2 = result.getLength(); x += tm->zCurrentRenderer()->getTextBreite(" "); result += " "; tm->nextStyle(); continue; } if (txt[i] == '\t') { lastPos = i; lastPos2 = result.getLength(); x += tm->zCurrentRenderer()->getTextBreite("\t"); result += "\t"; tm->nextStyle(); continue; } if (txt[i] == '\n') { x = 0; lastPos = -1; lastPos2 = -1; result += "\n"; tm->nextStyle(); continue; } char buff[2] = {txt[i], 0}; x += tm->zCurrentRenderer()->getTextBreite(buff); result += buff; if (x > maxBr && lastPos > -1) { result.remove(lastPos2, result.getLength()); result += "\n"; result += spacing; x = tm->zCurrentRenderer()->getTextBreite(spacing); i = lastPos; tm->stepTo(lastPos); lastPos = -1; lastPos2 = -1; last = tm->currentStyle(); } tm->nextStyle(); } return result; } void TextFeld::setAutoLineBreakSpacing(const char* spacing) { if (!autoLineBreakSpacing) autoLineBreakSpacing = new Text(); autoLineBreakSpacing->setText(spacing); } // Sets the style of a text section // begin: the start position of the section // end: the end position of the section (not included) void TextFeld::setTextStyle(int begin, int end, TextStyle style) { tm->setTextStyle(begin, end, style); } void TextFeld::addZeile(const char* zeile) // appends a line { if (tm->text) { Text* txt = new Text(zeile); if (zeile[txt->getLength() - 1] != '\n') txt->append("\n"); TextRenderer* r = tm->renderer->z(0); if (tm->textStyle.get(tm->textStyle.getEintragAnzahl() - 1) .rendererIndex < tm->renderer->getEintragAnzahl()) r = tm->renderer->z( tm->textStyle.get(tm->textStyle.getEintragAnzahl() - 1) .rendererIndex); if (r) { bool vs = vertikalScrollBar && hatStyle(Style::VScroll); int rbr = (rahmen && hatStyle(Style::Rahmen)) ? rahmen->getRBreite() : 0; r->setSchriftSize( tm->textStyle.get(tm->textStyle.getEintragAnzahl() - 1) .fontSize); r->textFormatieren(txt, gr.x - ((int)vs * 15) - rbr * 2); } lockZeichnung(); tm->text->append(txt->getText()); unlockZeichnung(); txt->release(); if (hatStyle(Style::VScroll)) updateVScroll(); if (hatStyle(Style::HScroll)) updateHScroll(); rend = 1; } } // Appends a line to the text // zeile: The new line // color: The color of the line void TextFeld::addZeile(const char* zeile, int color) { if (tm->text) { Text* txt = new Text(zeile); if (zeile[txt->getLength() - 1] != '\n') txt->append("\n"); TextRenderer* r = tm->renderer->z(0); if (tm->textStyle.get(tm->textStyle.getEintragAnzahl() - 1) .rendererIndex < tm->renderer->getEintragAnzahl()) r = tm->renderer->z( tm->textStyle.get(tm->textStyle.getEintragAnzahl() - 1) .rendererIndex); if (r) { bool vs = vertikalScrollBar && hatStyle(Style::VScroll); int rbr = (rahmen && hatStyle(Style::Rahmen)) ? rahmen->getRBreite() : 0; r->setSchriftSize( tm->textStyle.get(tm->textStyle.getEintragAnzahl() - 1) .fontSize); r->textFormatieren(txt, gr.x - ((int)vs * 15) - rbr * 2); } lockZeichnung(); tm->text->append(txt->getText()); setSchriftFarbe(tm->text->getLength() - txt->getLength(), tm->text->getLength(), color); unlockZeichnung(); txt->release(); if (hatStyle(Style::VScroll)) updateVScroll(); if (hatStyle(Style::HScroll)) updateHScroll(); rend = 1; } } // Deselects all text sections 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) // sets the selected text { deselectAuswahl(); TextStyle s = tm->getTextStyle(pos1); s.selected = 1; tm->setTextStyle(pos1, pos2, s); } void TextFeld::setAuswahl(Punkt& auswahl) { deselectAuswahl(); TextStyle s = tm->getTextStyle(auswahl.x); s.selected = 1; tm->setTextStyle(auswahl.x, auswahl.y, s); rend = 1; } void TextFeld::addAuswahl(int pos1, int pos2) { TextStyle s = tm->getTextStyle(pos1); s.selected = 1; tm->setTextStyle(pos1, pos2, s); } void TextFeld::addAuswahl(Punkt& auswahl) { TextStyle s = tm->getTextStyle(auswahl.x); s.selected = 1; tm->setTextStyle(auswahl.x, auswahl.y, s); rend = 1; } // Sets the selected text section // begin: The cursor position in the text // end: The position in the text up to which the text should be colored 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; } } // replaces all selected text sections with a text // text: the new text void TextFeld::replaceAuswahl(const char* text) { tm->cleanupStyles(); int sa = tm->textStyle.getEintragAnzahl(); int last = tm->text->getLength(); int si = 0; for (int i = sa - 1; i >= 0; i--) { TextStyle s = tm->textStyle.get(i); si = i; if (s.selected) { if ((i > 0 && !tm->textStyle.get(i - 1).selected) || i == 0) { s.selected = false; tm->textStyle.set(s, si); tm->removeText(s.beginIndex, last); tm->insertText(s.beginIndex, text); } } else last = s.beginIndex; } } void TextFeld::setTextRendererZ(TextRenderer* textRd) { if (tm->renderer) tm->renderer->leeren(); else tm->renderer = new RCArray(); tm->renderer->add(textRd); rend = 1; } // Adds a TextRenderer // textRd: The text renderer void TextFeld::addTextRendererZ(TextRenderer* textRd) { if (!tm->renderer) tm->renderer = new RCArray(); tm->renderer->add(textRd); } // Sets the used TextRenderers // textRd: The text renderers void TextFeld::setTextRendererZ(RCArray* textRd) { if (tm->renderer) tm->renderer->release(); tm->renderer = textRd; } void TextFeld::setSchriftZ(Schrift* schrift) // sets a pointer to the font { if (!tm->renderer) tm->renderer = new RCArray(); if (!tm->renderer->getEintragAnzahl()) tm->renderer->add(new TextRenderer(schrift)); else tm->renderer->z(0)->setSchriftZ(schrift); rend = 1; } // Sets a pointer to the font // rendererIndex: The index of the renderer whose font should be set // schrift: The font to be used for text drawing. void TextFeld::setSchriftZ(int rendererIndex, Schrift* schrift) { if (!tm->renderer) tm->renderer = new RCArray(); if (tm->renderer->getEintragAnzahl() <= rendererIndex) tm->renderer->add(new TextRenderer(schrift), rendererIndex); else tm->renderer->z(rendererIndex)->setSchriftZ(schrift); } void TextFeld::setSchriftSize(unsigned char gr) // sets the font size { TextStyle s = tm->textStyle.get(0); s.fontSize = gr; tm->textStyle.set(s, 0); rend = 1; } // Sets the font size (default: 12) // begin: The index of the first affected character // end: The index of the first unaffected character // gr: The font size to be used for text drawing 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) // sets the font color { TextStyle s = tm->textStyle.get(0); s.fontColor = fc; tm->textStyle.set(s, 0); rend = 1; } // Sets the font color // begin: The index of the first affected character // end: The index of the first unaffected character // fc: The color to be used for text drawing 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) // for password field * { showChar = c; rend = 1; } void TextFeld::setVScrollZuZeile(int zeile) // scrolls to line { 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; const char* text = tm->text->getText(); Text txtWithLineBreaks; if (hatStyle(Style::AutoLineBreak)) { txtWithLineBreaks = addLineBreaksToText(tm->text->getText(), autoLineBreakSpacing ? autoLineBreakSpacing->getText() : ""); text = txtWithLineBreaks; len = txtWithLineBreaks.getLength(); } 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) // scrolls down { 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(); const char* text = tm->text->getText(); Text txtWithLineBreaks; if (hatStyle(Style::AutoLineBreak)) { txtWithLineBreaks = addLineBreaksToText(tm->text->getText(), autoLineBreakSpacing ? autoLineBreakSpacing->getText() : ""); text = txtWithLineBreaks; len = txtWithLineBreaks.getLength(); } 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) // scrolls to cursor position { if (pos == -1) pos = cpos; lockZeichnung(); if (horizontalScrollBar && tm->text && tm->renderer) { if (hatStyleNicht(Style::Mehrzeilig)) tm->text->remove('\n'); int br = gr.x; if (hatStyle(Style::Rahmen) && rahmen) br -= rahmen->getRBreite() * 2; if (hatStyle(Style::VScroll) && vertikalScrollBar) br -= 15; tm->resetIteration(); int maxBr = 0; int len = tm->text->getLength(); const char* text = tm->text->getText(); int lineBr = 0; char buff[] = {0, 0}; int cbr = 0; for (int i = 0; i < len; i++) { buff[0] = text[i]; if (text[i] == '\n') { maxBr = maxBr >= lineBr ? maxBr : lineBr; lineBr = 0; tm->nextStyle(); continue; } TextRenderer* r = tm->zCurrentRenderer(); if (r) { lineBr += r->getTextBreite(buff); if (i <= pos) cbr = lineBr; } tm->nextStyle(); } maxBr = maxBr >= lineBr ? maxBr : lineBr; horizontalScrollBar->update(maxBr, br); if (cbr > horizontalScrollBar->getScroll() + horizontalScrollBar->getScrollData()->anzeige) horizontalScrollBar->scroll(cbr - br); if (cbr < horizontalScrollBar->getScroll()) horizontalScrollBar->scroll(cbr); } unlockZeichnung(); } // Returns the width in pixels needed to fully display the current text with // the current styles int TextFeld::getNeededWidth() { int maxBr = 0; lockZeichnung(); if (tm->text && tm->renderer) maxBr = getTextWidth(); unlockZeichnung(); bool vs = vertikalScrollBar && hatStyle(Style::VScroll); bool r = rahmen && hatStyle(Style::Rahmen); return maxBr + (r ? rahmen->getRBreite() * 2 : 0) + (vs ? 15 : 0); } // Returns the height in pixels needed to fully display the current text with // the current styles int TextFeld::getNeededHeight() { int th = 0; lockZeichnung(); if (tm->text && tm->renderer) th = getTextHeight(); unlockZeichnung(); bool hs = horizontalScrollBar && hatStyle(Style::HScroll); bool r = rahmen && hatStyle(Style::Rahmen); return th + (r ? rahmen->getRBreite() * 2 : 0) + (hs ? 15 : 0); } bool TextFeld::tick(double tickval) // tick { if (hatStyle(Style::Fokus)) { if (tickVal < 0.5 && tickVal + tickval >= 0.5) rend = 1; if (tickVal >= 0.5 && tickVal + tickval >= 1) rend = 1; tickVal += tickval; if (tickVal >= 1) tickVal -= 1; } return ZeichnungHintergrund::tick(tickval); } void TextFeld::doTastaturEreignis(TastaturEreignis& te) { bool ntakc = !te.verarbeitet; if (te.verarbeitet || hatStyleNicht(Style::Fokus)) return; if (!tak) return; getThis(); if (tak(takParam, this, te)) { if (hatStyleNicht(Style::Editierbar)) { release(); return; } if (te.id == TE_Press) { bool shift = getTastenStand(T_Shift); bool strg = getTastenStand(T_Strg); switch (te.virtualKey) { 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 (hatStyle(TextFeld::Style::Mehrzeilig)) { 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.virtualKey == 'c' || te.virtualKey == '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.virtualKey == 'v' || te.virtualKey == 'V') { const 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[0])) { if (!tm->getTextStyle(cpos).selected) tm->insertText(cpos, te.taste); else { cpos = tm->getTextStyle(cpos).beginIndex; while (cpos > 0 && tm->getTextStyle(cpos - 1).selected) cpos = tm->getTextStyle(cpos - 1).beginIndex; } replaceAuswahl(te.taste); ++cpos; rend = 1; } break; } } if (cpos < 0) cpos = 0; if (cpos > tm->text->getLength()) cpos = tm->text->getLength(); if (hatStyle(Style::VScroll)) updateVScroll(cpos); if (hatStyle(Style::HScroll)) updateHScroll(cpos); te.verarbeitet = 1; } if (ntakc && te.verarbeitet && nTak) te.verarbeitet = nTak(ntakParam, this, te); release(); } void TextFeld::render(Bild& zRObj) // draws to zRObj { if (hatStyleNicht(Style::Sichtbar)) return; ZeichnungHintergrund::render(zRObj); if (!tm->text || !tm->renderer) return; lockZeichnung(); if (!zRObj.setDrawOptions(innenPosition, innenSize)) { unlockZeichnung(); return; } if (hatStyleNicht(Style::Mehrzeilig)) tm->text->remove('\n'); int tbr = getTextWidth(); int thi = getTextHeight(); int xxx = 0; int yyy = 0; int breite = innenSize.x; int height = innenSize.y; bool hs = horizontalScrollBar && hatStyle(Style::HScroll); bool vs = vertikalScrollBar && hatStyle(Style::VScroll); if (vs) yyy -= vertikalScrollBar->getScroll(); if (hs) xxx -= horizontalScrollBar->getScroll(); if (hatStyle(Style::HCenter) && !hs) xxx = (breite / 2) - tbr / 2; int x = xxx; int len = tm->text->getLength(); const char* text = tm->text->getText(); Text txtWithLineBreaks; if (hatStyle(Style::AutoLineBreak)) { txtWithLineBreaks = addLineBreaksToText(tm->text->getText(), autoLineBreakSpacing ? autoLineBreakSpacing->getText() : "", 0); text = txtWithLineBreaks; len = txtWithLineBreaks.getLength(); } lockZeichnung(); tm->resetIteration(); if (thi == 0) { thi = tm->zCurrentRenderer()->getZeilenHeight(); } if (hatStyle(Style::VCenter) && !vs) yyy = (height / 2) - thi / 2; int y = yyy; TextStyle& style = tm->currentStyle(); int maxLH = 0; int corrector = 0; int realLen = tm->text->getLength(); for (int i = 0; i <= len; i++) { int oldX = x; if (i < len && tm->zCurrentRenderer()) tm->zCurrentRenderer()->renderChar(x, y, istSchreibbar(showChar) ? showChar : text[i], zRObj, style.selected ? style.selectedColor : style.fontColor, style.underlined, style.selected, style.selectedBackcroundColor); if (i - corrector == cpos && tickVal <= 0.5 && hatStyle(Style::Fokus) && hatStyle(Style::Editierbar) && tm->zCurrentRenderer()) zRObj.drawLinieV( oldX, y, tm->zCurrentRenderer()->getZeilenHeight(), 0xFFFF5555); if (i >= realLen || text[i] != tm->text->getText()[i]) { corrector++; } if (tm->zCurrentRenderer()) { int tmp = tm->zCurrentRenderer()->getZeilenHeight() + tm->zCurrentRenderer()->getZeilenAbstand(); maxLH = tmp > maxLH ? tmp : maxLH; } if (i < len && text[i] == '\n') { x = xxx; y += maxLH; } tm->nextStyle(); } unlockZeichnung(); zRObj.releaseDrawOptions(); unlockZeichnung(); } // Constant Text* TextFeld::getText() const // returns the text { if (!tm->text) return 0; return dynamic_cast(tm->text->getThis()); } Text* TextFeld::zText() const // returns the text without reference counter { return tm->text; } Schrift* TextFeld::getSchrift() const // returns the font { tm->resetIteration(); return tm->zCurrentRenderer() ? tm->zCurrentRenderer()->getSchrift() : 0; } Schrift* TextFeld::zSchrift() const // returns the font without reference counter { tm->resetIteration(); return tm->zCurrentRenderer() ? tm->zCurrentRenderer()->zSchrift() : 0; } // Returns the font. // rendererIndex: The index of the renderer whose font should be returned // return: 0, if the font was not set Schrift* TextFeld::getSchrift(int rendererIndex) const { if (tm->renderer && tm->renderer->z(rendererIndex)) return tm->renderer->z(rendererIndex)->getSchrift(); return 0; } // Returns the font without increased reference counter // rendererIndex: The index of the renderer whose font should be returned // return: 0, if the font was not set Schrift* TextFeld::zSchrift(int rendererIndex) const { if (tm->renderer && tm->renderer->z(rendererIndex)) return tm->renderer->z(rendererIndex)->zSchrift(); return 0; } TextRenderer* TextFeld::getTextRenderer() const { tm->resetIteration(); return dynamic_cast(tm->zCurrentRenderer()->getThis()); } TextRenderer* TextFeld::zTextRenderer() const { tm->resetIteration(); return tm->zCurrentRenderer(); } // Returns the TextRenderer. // index: The index of the renderer to be returned // return: 0, if the TextRenderer was not set TextRenderer* TextFeld::getTextRenderer(int index) const { if (tm->renderer && tm->renderer->z(index)) return tm->renderer->get(index); return 0; } // Returns the TextRenderer without increased reference counter // index: The index of the renderer to be returned // return: 0, if the TextRenderer was not set 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 // returns the font size { tm->resetIteration(); return tm->current.fontSize; } // Returns the font size // index: The index of the character unsigned char TextFeld::getSchriftSize(int index) const { tm->resetIteration(); return tm->current.fontSize; } int TextFeld::getSchriftFarbe() const // returns the font color { tm->resetIteration(); return tm->current.fontColor; } // Returns the font color in A8R8G8B8 format // index: The index of the character int TextFeld::getSchriftFarbe(int index) const { return tm->getTextStyle(index).fontColor; } unsigned char TextFeld::getShowChar() const // returns the display character { return showChar; } int TextFeld::getCursorPos() const { return cpos; } // Returns 1 if the character is selected // index: The index of the character bool TextFeld::isCharSelected(int index) const { return tm->getTextStyle(index).selected; } // Returns the index of the character located under the mouse // mx: the x position of the mouse relative to the text field position // my: the y position of the mouse relative to the text field position // return: -1, if no character is at the position int TextFeld::getTextIndexAt(int mx, int my) const { if (!tm || !tm->text || !tm->zCurrentRenderer()) return -1; int tbr = getTextWidth(); int thi = getTextHeight(); int xxx = 0; int yyy = 0; int breite = innenSize.x; int height = innenSize.y; bool hs = horizontalScrollBar && hatStyle(Style::HScroll); bool vs = vertikalScrollBar && hatStyle(Style::VScroll); if (vs) yyy -= vertikalScrollBar->getScroll(); if (hs) xxx -= horizontalScrollBar->getScroll(); if (hatStyle(Style::HCenter) && !hs) xxx = (breite / 2) - tbr / 2; if (hatStyle(Style::VCenter) && !vs) yyy = (height / 2) - thi / 2; int x = xxx; int y = yyy; int len = tm->text->getLength(); const char* text = tm->text->getText(); Text txtWithLineBreaks; if (hatStyle(Style::AutoLineBreak)) { txtWithLineBreaks = addLineBreaksToText(tm->text->getText(), autoLineBreakSpacing ? autoLineBreakSpacing->getText() : ""); text = txtWithLineBreaks; len = txtWithLineBreaks.getLength(); } tm->resetIteration(); int corrector = 0; int maxLH = 0; int realLen = tm->text->getLength(); for (int i = 0; i < len; i++) { if (i >= realLen || text[i] != tm->text->getText()[i]) { corrector++; } char buff[2] = {istSchreibbar(showChar) ? (char)showChar : text[i], 0}; int tmpx = tm->zCurrentRenderer()->getTextBreite(buff); int tmpy = tm->zCurrentRenderer()->getZeilenHeight(); if (mx >= x && mx < x + tmpx && my >= y && my < y + tmpy) return i - corrector; if (mx < x + tmpx && my < y + tmpy) return -1; x += tmpx; tmpy += tm->zCurrentRenderer()->getZeilenAbstand(); maxLH = tmpy > maxLH ? tmpy : maxLH; if (text[i] == '\n') { x = xxx; y += maxLH; } tm->nextStyle(); } return -1; } // Returns the index of the character before which the cursor is placed when // the mouse is clicked // mx: the x position of the mouse relative to the text field position // my: the y position of the mouse relative to the text field position int TextFeld::getCurserPosAt(int mx, int my) const { if (!tm || !tm->text || !tm->zCurrentRenderer()) return tm->text->getLength(); 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(); const char* text = tm->text->getText(); Text txtWithLineBreaks; if (hatStyle(Style::AutoLineBreak)) { txtWithLineBreaks = addLineBreaksToText(tm->text->getText(), autoLineBreakSpacing ? autoLineBreakSpacing->getText() : ""); text = txtWithLineBreaks; len = txtWithLineBreaks.getLength(); } tm->resetIteration(); int maxLH = 0; int realLen = tm->text->getLength(); int corrector = 0; for (int i = 0; i < len; i++) { if (i >= realLen || text[i] != tm->text->getText()[i]) { corrector++; } 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 - corrector; 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 - corrector; x = xxx; y += maxLH; } tm->nextStyle(); } return tm->text->getLength(); } // Returns the style of a specific character // index: The index of the character TextStyle TextFeld::getTextStyle(int index) const { return tm->getTextStyle(index); } // returns the string that is inserted after each line break when using // the AutoLineBreak style Text TextFeld::getAutoLineBreakSpacing() const { return autoLineBreakSpacing ? *autoLineBreakSpacing : Text(""); } Zeichnung* TextFeld::dublizieren() const // Creates a copy of the drawing { 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 = dynamic_cast*>(tm->renderer->getThis()); obj->tm->textStyle.leeren(); for (const auto& i : tm->textStyle) 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( dynamic_cast(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()); } if (autoLineBreakSpacing) { obj->setAutoLineBreakSpacing(*autoLineBreakSpacing); } obj->setSchowChar(showChar); return obj; }