summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichele Calgaro <[email protected]>2025-01-30 23:40:14 +0900
committerMichele Calgaro <[email protected]>2025-02-13 22:39:34 +0900
commit9c648bea9bfb1113c070a05b36f78ff006d0877a (patch)
tree8318170d8f1fddf60e39686f5e3b872a6a610472 /src
parent98a90524a1d706f1143f39fd707b620be3184042 (diff)
downloadtqt3-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.cpp33
-rw-r--r--src/kernel/tqrichtext_p.cpp12
-rw-r--r--src/widgets/tqlineedit.cpp14
-rw-r--r--src/widgets/tqtextedit.cpp16
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();