summaryrefslogtreecommitdiffstats
path: root/kate
diff options
context:
space:
mode:
Diffstat (limited to 'kate')
-rw-r--r--kate/part/katedocument.cpp41
-rw-r--r--kate/part/katerenderer.cpp72
-rw-r--r--kate/part/kateviewinternal.cpp41
3 files changed, 112 insertions, 42 deletions
diff --git a/kate/part/katedocument.cpp b/kate/part/katedocument.cpp
index 57cecf8a0..7781df55e 100644
--- a/kate/part/katedocument.cpp
+++ b/kate/part/katedocument.cpp
@@ -2411,7 +2411,7 @@ bool KateDocument::openFile(TDEIO::Job * job)
// read dir config (if possible and wanted)
if (!m_reloading)
- readDirConfig ();
+ readDirConfig ();
// do we have success ?
bool success = m_buffer->openFile (m_file);
@@ -3135,15 +3135,27 @@ void KateDocument::backspace( KateView *view, const KateTextCursor& c )
if ((col == 0) && (line == 0))
return;
+ KateTextLine::Ptr tl = m_buffer->plainLine(line);
+ if (!tl)
+ {
+ return;
+ }
+
+ // Make sure to handle surrogate pairs correctly
+ uint fromCol = col - 1;
+ TQChar prevChar = tl->getChar(col - 1);
+ if (prevChar.isLowSurrogate() && tl->getChar(col - 2).isHighSurrogate())
+ {
+ fromCol = col - 2;
+ prevChar = tl->getChar(col - 2);
+ }
+
int complement = 0;
if (col > 0)
{
if (config()->configFlags() & KateDocument::cfAutoBrackets)
{
// if inside empty (), {}, [], '', "" delete both
- KateTextLine::Ptr tl = m_buffer->plainLine(line);
- if(!tl) return;
- TQChar prevChar = tl->getChar(col-1);
TQChar nextChar = tl->getChar(col);
if ( (prevChar == '"' && nextChar == '"') ||
@@ -3158,8 +3170,7 @@ void KateDocument::backspace( KateView *view, const KateTextCursor& c )
if (!(config()->configFlags() & KateDocument::cfBackspaceIndents))
{
// ordinary backspace
- //c.cursor.col--;
- removeText(line, col-1, line, col+complement);
+ removeText(line, fromCol, line, col+complement);
}
else
{
@@ -3215,9 +3226,23 @@ void KateDocument::del( KateView *view, const KateTextCursor& c )
return;
}
- if( c.col() < (int) m_buffer->plainLine(c.line())->length())
+ KateTextLine::Ptr tl = m_buffer->plainLine(c.line());
+ if (!tl)
{
- removeText(c.line(), c.col(), c.line(), c.col()+1);
+ return;
+ }
+ uint lineLen = tl->length();
+ uint col = (uint)c.col();
+ if (col < lineLen)
+ {
+ // Make sure to handle surrogate pairs correctly
+ uint toCol = col + 1;
+ if (tl->getChar(col).isHighSurrogate() && tl->getChar(col + 1).isLowSurrogate())
+ {
+ toCol = col + 2;
+ }
+
+ removeText(c.line(), col, c.line(), toCol);
}
else if ( (uint)c.line() < lastLine() )
{
diff --git a/kate/part/katerenderer.cpp b/kate/part/katerenderer.cpp
index 67afb4bd6..30a93b817 100644
--- a/kate/part/katerenderer.cpp
+++ b/kate/part/katerenderer.cpp
@@ -400,7 +400,7 @@ void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, i
uint nextCol = curCol + 1;
// text + attrib data from line
- const uchar *textAttributes = textLine->attributes ();
+ const uchar *textAttributes = textLine->attributes();
bool noAttribs = !textAttributes;
// adjust to startcol ;)
@@ -421,26 +421,29 @@ void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, i
while (curCol - startcol < len)
{
+ const TQString &textString = textLine->string();
+ int currCharNumCols = textString[curCol].isHighSurrogate() ? 2 : 1;
+ nextCol = curCol + currCharNumCols;
+
// make sure curPos is updated correctly.
// ### if uncommented, causes an O(n^2) behaviour
//Q_ASSERT(curPos == textLine->cursorX(curCol, m_tabWidth));
- TQChar curChar = textLine->string()[curCol];
// Decide if this character is a tab - we treat the spacing differently
// TODO: move tab width calculation elsewhere?
- bool isTab = curChar == TQChar('\t');
+ bool isTab = textString[curCol] == TQChar('\t');
// Determine current syntax highlighting attribute
// A bit legacy but doesn't need to change
KateAttribute* curAt = (noAttribs || ((*textAttributes) >= atLen)) ? &attr[0] : &attr[*textAttributes];
// X position calculation. Incorrect for fonts with non-zero leftBearing() and rightBearing() results.
- // TODO: make internal charWidth() function, use TQFontMetrics::charWidth().
- xPosAfter += curAt->width(*fs, curChar, m_tabWidth);
+ // TODO: make internal charWidth() function.
+ xPosAfter += curAt->width(*fs, textString, curCol, m_tabWidth);
// Tab special treatment, move to charWidth().
if (isTab)
- xPosAfter -= (xPosAfter % curAt->width(*fs, curChar, m_tabWidth));
+ xPosAfter -= (xPosAfter % curAt->width(*fs, textString[curCol], m_tabWidth));
// Only draw after the starting X value
// Haha, this was always wrong, due to the use of individual char width calculations...?? :(
@@ -459,7 +462,9 @@ void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, i
curColor = isSel ? &(curAt->selectedTextColor()) : &(curAt->textColor());
// Incorporate in arbitrary highlighting
- if (curAt != oldAt || curColor != oldColor || (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)) {
+ if (curAt != oldAt || curColor != oldColor || (superRanges.count() &&
+ superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos))
+ {
if (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == currentPos)
customHL = KateArbitraryHighlightRange::merge(superRanges.rangesIncluding(currentPos));
@@ -495,10 +500,10 @@ void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, i
|| (superRanges.count() && superRanges.currentBoundary() && *(superRanges.currentBoundary()) == KateTextCursor(line, nextCol))
// it is the end of the line OR
- || (curCol - startcol >= len - 1)
+ || ((curCol - startcol) >= (len - currCharNumCols))
// the rest of the line is trailing whitespace OR
- || (curCol + 1 >= trailingWhitespaceColumn)
+ || (nextCol >= trailingWhitespaceColumn)
// indentation lines OR
|| (showIndentLines() && curCol < lastIndentColumn)
@@ -514,7 +519,7 @@ void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, i
// the next char is a tab (removed the "and this isn't" because that's dealt with above)
// i.e. we have to draw the current text so the tab can be rendered as above.
- || (textLine->string()[nextCol] == TQChar('\t'))
+ || (textString[nextCol] == TQChar('\t'))
// input method edit area
|| ( m_view && (isIMEdit != m_view->isIMEdit( line, nextCol )) )
@@ -557,7 +562,7 @@ void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, i
// If this is the last block of text, fill up to the end of the line if the
// selection stretches that far
- if ((curCol >= len - 1) && m_view->lineEndSelected (line, endcol))
+ if (curCol >= (len - currCharNumCols) && m_view->lineEndSelected(line, endcol))
width = xEnd - oldXPos;
}
else
@@ -632,7 +637,7 @@ void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, i
else
{
// Here's where the money is...
- paint.drawText(oldXPos-xStart, y, textLine->string(), blockStartCol, nextCol-blockStartCol);
+ paint.drawText(oldXPos-xStart, y, textString, blockStartCol, nextCol-blockStartCol);
// Draw preedit's underline
if (isIMEdit) {
@@ -650,7 +655,6 @@ void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, i
// variable advancement
blockStartCol = nextCol;
oldXPos = xPosAfter;
- //oldS = s+1;
}
} // renderNow
@@ -681,9 +685,8 @@ void KateRenderer::paintTextLine(TQPainter& paint, const KateLineRange* range, i
oldColor = curColor;
// col move
- curCol++;
- nextCol++;
- currentPos.setCol(currentPos.col() + 1);
+ curCol += currCharNumCols;
+ currentPos.setCol(currentPos.col() + currCharNumCols);
// Update the current indentation pos.
if (isTab)
@@ -756,8 +759,6 @@ uint KateRenderer::textWidth(const KateTextLine::Ptr &textLine, int cursorCol)
if (z < len) {
width = a->width(*fs, textString, z, m_tabWidth);
} else {
- // DF: commented out. It happens all the time.
- //Q_ASSERT(!m_doc->wrapCursor());
width = a->width(*fs, TQChar(' '), m_tabWidth);
}
@@ -765,6 +766,11 @@ uint KateRenderer::textWidth(const KateTextLine::Ptr &textLine, int cursorCol)
if (z < len && unicode[z] == TQChar('\t'))
x -= x % width;
+
+ if (textString[z].isHighSurrogate())
+ {
+ ++z;
+ }
}
return x;
@@ -803,7 +809,11 @@ uint KateRenderer::textWidth(const KateTextLine::Ptr &textLine, uint startcol, u
if (unicode[z] == TQChar('\t'))
x -= x % width;
- if (unicode[z].isSpace())
+ if (textString[z].isHighSurrogate())
+ {
+ ++z;
+ }
+ else if (unicode[z].isSpace())
{
lastWhiteSpace = z+1;
lastWhiteSpaceX = x;
@@ -876,7 +886,6 @@ uint KateRenderer::textWidth(const KateTextCursor &cursor)
uint KateRenderer::textWidth( KateTextCursor &cursor, int xPos, uint startCol)
{
bool wrapCursor = m_view->wrapCursor();
- int x, oldX;
KateFontStruct *fs = config()->fontStruct();
@@ -890,15 +899,17 @@ uint KateRenderer::textWidth( KateTextCursor &cursor, int xPos, uint startCol)
const TQChar *unicode = textLine->text();
const TQString &textString = textLine->string();
- x = oldX = 0;
+ int x = 0;
+ int oldX = 0;
+ int oldZ = 0;
+ int width = 0;
uint z = startCol;
while (x < xPos && (!wrapCursor || z < len)) {
oldX = x;
+ oldZ = z;
KateAttribute* a = attribute(textLine->attribute(z));
- int width = 0;
-
if (z < len)
width = a->width(*fs, textString, z, m_tabWidth);
else
@@ -909,11 +920,11 @@ uint KateRenderer::textWidth( KateTextCursor &cursor, int xPos, uint startCol)
if (z < len && unicode[z] == TQChar('\t'))
x -= x % width;
- z++;
+ z += textString[z].isHighSurrogate() ? 2 : 1;
}
if (xPos - oldX < x - xPos && z > 0) {
- z--;
x = oldX;
+ z = oldZ;
}
cursor.setCol(z);
return x;
@@ -942,23 +953,24 @@ uint KateRenderer::textPos(const KateTextLine::Ptr &textLine, int xPos, uint sta
KateFontStruct *fs = config()->fontStruct();
- int x, oldX;
- x = oldX = 0;
-
+ int x = 0;
+ int oldX = 0;
+ int oldZ = 0;
uint z = startCol;
const uint len = textLine->length();
const TQString &textString = textLine->string();
while ( (x < xPos) && (z < len)) {
oldX = x;
+ oldZ = z;
KateAttribute* a = attribute(textLine->attribute(z));
x += a->width(*fs, textString, z, m_tabWidth);
- z++;
+ z += textString[z].isHighSurrogate() ? 2 : 1;
}
if ( ( (! nearest) || xPos - oldX < x - xPos ) && z > 0 ) {
- z--;
+ z = oldZ;
// newXPos = oldX;
}// else newXPos = x;
return z;
diff --git a/kate/part/kateviewinternal.cpp b/kate/part/kateviewinternal.cpp
index 0f12f8562..40ab06252 100644
--- a/kate/part/kateviewinternal.cpp
+++ b/kate/part/kateviewinternal.cpp
@@ -1091,11 +1091,44 @@ public:
void KateViewInternal::moveChar( Bias bias, bool sel )
{
+ if (bias == Bias::none)
+ {
+ return;
+ }
+
+ KateTextLine::Ptr tl = m_doc->m_buffer->plainLine(cursor.line());
+ if (!tl)
+ {
+ return;
+ }
+
+ // Make sure to handle surrogate pairs correctly
+ int offset = 0;
+ int col = cursor.col();
+ if (bias == Bias::left_b)
+ {
+ offset = -1;
+ if (tl->getChar(col - 1).isLowSurrogate() && tl->getChar(col - 2).isHighSurrogate())
+ {
+ offset = -2;
+ }
+ }
+ else
+ {
+ offset = 1;
+ if (tl->getChar(col).isHighSurrogate() && tl->getChar(col + 1).isLowSurrogate())
+ {
+ offset = 2;
+ }
+ }
+
KateTextCursor c;
- if ( m_view->wrapCursor() ) {
- c = WrappingCursor( this, cursor ) += bias;
- } else {
- c = BoundedCursor( this, cursor ) += bias;
+ if (m_view->wrapCursor())
+ {
+ c = WrappingCursor( this, cursor ) += offset;
+ } else
+ {
+ c = BoundedCursor( this, cursor ) += offset;
}
updateSelection( c, sel );