diff options
author | Michele Calgaro <[email protected]> | 2025-01-30 23:40:14 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2025-02-13 22:39:34 +0900 |
commit | 9c648bea9bfb1113c070a05b36f78ff006d0877a (patch) | |
tree | 8318170d8f1fddf60e39686f5e3b872a6a610472 /src | |
parent | 98a90524a1d706f1143f39fd707b620be3184042 (diff) | |
download | tqt3-9c648bea9bfb1113c070a05b36f78ff006d0877a.tar.gz tqt3-9c648bea9bfb1113c070a05b36f78ff006d0877a.zip |
Fix editing of text containing surrogate characters.
This relates to issue #162.
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/tqrichtext.cpp | 33 | ||||
-rw-r--r-- | src/kernel/tqrichtext_p.cpp | 12 | ||||
-rw-r--r-- | src/widgets/tqlineedit.cpp | 14 | ||||
-rw-r--r-- | src/widgets/tqtextedit.cpp | 16 |
4 files changed, 59 insertions, 16 deletions
diff --git a/src/kernel/tqrichtext.cpp b/src/kernel/tqrichtext.cpp index 3585e470d..98fbc8f53 100644 --- a/src/kernel/tqrichtext.cpp +++ b/src/kernel/tqrichtext.cpp @@ -219,12 +219,19 @@ TQTextCursor *TQTextDeleteCommand::execute( TQTextCursor *c ) cursor.setParagraph( s ); cursor.setIndex( index ); int len = text.size(); + if ( c ) *c = cursor; if ( doc ) { doc->setSelectionStart( TQTextDocument::Temp, cursor ); for ( int i = 0; i < len; ++i ) + { + if (text[i].c.isHighSurrogate() && i < (len - 1) && text[i + 1].c.isLowSurrogate()) + { + ++i; // This is required for correct advancement when handling surrogate pairs + } cursor.gotoNextLetter(); + } doc->setSelectionEnd( TQTextDocument::Temp, cursor ); doc->removeSelectedText( TQTextDocument::Temp, &cursor ); if ( c ) @@ -1248,9 +1255,17 @@ bool TQTextCursor::removePreviousChar() { tmpX = -1; if ( !atParagStart() ) { - para->remove( idx-1, 1 ); + if (para->at(idx - 1)->c.isLowSurrogate() && idx > 1 && para->at(idx - 2)->c.isHighSurrogate()) + { + para->remove(idx - 2, 2); + idx -= 2; + } + else + { + para->remove(idx - 1, 1); + idx--; + } int h = para->rect().height(); - idx--; // shouldn't be needed, just to make sure. fixCursorPosition(); para->format( -1, TRUE ); @@ -4007,6 +4022,7 @@ int TQTextString::width( int idx ) const { int w = 0; TQTextStringChar *c = &at( idx ); + // '!c->charStop' already takes care of low surrogate chars if ( !c->charStop || c->c.unicode() == 0xad || c->c.unicode() == 0x2028 ) return 0; #ifndef TQT_NO_TEXTCUSTOMITEM @@ -4290,10 +4306,10 @@ void TQTextParagraph::format( int start, bool doMove ) if ( !str || str->length() == 0 || !formatter() ) return; - if ( hasdoc && - document()->preProcessor() && - ( needPreProcess || state == -1 ) ) + if ( hasdoc && document()->preProcessor() && ( needPreProcess || state == -1 ) ) + { document()->preProcessor()->process( document(), this, invalid <= 0 ? 0 : invalid ); + } needPreProcess = FALSE; if ( invalid == -1 ) @@ -5782,6 +5798,7 @@ int TQTextFormatterBreakWords::format( TQTextDocument *doc, TQTextParagraph *par lastChr = c->c; lastFormat = c->format(); } + bool lastWasOwnLineCustomItem = lastBreak == -2; bool hadBreakableChar = lastBreak != -1; bool lastWasHardBreak = lastChr == TQChar_linesep; @@ -5791,6 +5808,12 @@ int TQTextFormatterBreakWords::format( TQTextDocument *doc, TQTextParagraph *par c->format()->setPainter( painter ); c = &string->at( i ); + // Skip over low surrogate chars + if (c->c.isLowSurrogate()) + { + continue; + } + if (lastFormat != c->format() && !c->c.isSpace() && lastFormat->font().italic() && !c->format()->font().italic()) { int rb = lastFormat->fontMetrics().rightBearing(lastChr); diff --git a/src/kernel/tqrichtext_p.cpp b/src/kernel/tqrichtext_p.cpp index e9417d2a9..165d319db 100644 --- a/src/kernel/tqrichtext_p.cpp +++ b/src/kernel/tqrichtext_p.cpp @@ -114,15 +114,15 @@ int TQTextCursor::x() const return 0; TQTextStringChar *c = para->at( idx ); int curx = c->x; - if ( !c->rightToLeft && - c->c.isSpace() && - idx > 0 && - para->at( idx - 1 )->c != '\t' && - !c->lineStart && - ( para->alignment() & TQt::AlignJustify ) == TQt::AlignJustify ) + if ( !c->rightToLeft && c->c.isSpace() && idx > 0 && para->at( idx - 1 )->c != '\t' && + !c->lineStart && ( para->alignment() & TQt::AlignJustify ) == TQt::AlignJustify ) + { curx = para->at( idx - 1 )->x + para->string()->width( idx - 1 ); + } if ( c->rightToLeft ) + { curx += para->string()->width( idx ); + } return curx; } diff --git a/src/widgets/tqlineedit.cpp b/src/widgets/tqlineedit.cpp index 2267706d4..94cc54bc8 100644 --- a/src/widgets/tqlineedit.cpp +++ b/src/widgets/tqlineedit.cpp @@ -860,10 +860,18 @@ void TQLineEdit::backspace() if ( d->hasSelectedText() ) { d->removeSelectedText(); } else if ( d->cursor ) { + --d->cursor; + if ( d->maskData ) { + d->cursor = d->prevMaskBlank( d->cursor ); + } + // second half of a surrogate, check if we have the first half as well, + // if yes delete both at once + if (d->cursor > 0 && d->text.at(d->cursor).isLowSurrogate() && + d->text.at(d->cursor - 1).isHighSurrogate()) { + d->del(true); --d->cursor; - if ( d->maskData ) - d->cursor = d->prevMaskBlank( d->cursor ); - d->del( TRUE ); + } + d->del(true); } d->finishChange( priorState ); } diff --git a/src/widgets/tqtextedit.cpp b/src/widgets/tqtextedit.cpp index cc88b3dd9..7ea000f21 100644 --- a/src/widgets/tqtextedit.cpp +++ b/src/widgets/tqtextedit.cpp @@ -1782,8 +1782,20 @@ void TQTextEdit::doKeyboardAction( KeyboardAction action ) undoRedoInfo.index = cursor->index(); undoRedoInfo.d->text = TQString::null; } - undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index()-1 ), TRUE ); - undoRedoInfo.index = cursor->index()-1; + int cur_idx = cursor->index(); + const TQTextParagraph *para = cursor->paragraph(); + if (para->at(cur_idx - 1)->c.isLowSurrogate() && cur_idx > 1 && + para->at(cur_idx - 2)->c.isHighSurrogate()) + { + undoRedoInfo.d->text.insert( 0, para->at(cur_idx - 1), TRUE ); + undoRedoInfo.d->text.insert( 0, para->at(cur_idx - 2), TRUE ); + undoRedoInfo.index = cursor->index() - 2; + } + else + { + undoRedoInfo.d->text.insert( 0, para->at(cur_idx - 1), TRUE ); + undoRedoInfo.index = cursor->index() - 1; + } } cursor->removePreviousChar(); lastFormatted = cursor->paragraph(); |