diff options
| -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 a125c2c85..367f70d64 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 ); | 
