diff options
Diffstat (limited to 'kate')
-rw-r--r-- | kate/part/katedocument.cpp | 41 | ||||
-rw-r--r-- | kate/part/katerenderer.cpp | 72 | ||||
-rw-r--r-- | kate/part/kateviewinternal.cpp | 41 |
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 ); |