diff --git a/src/view/kateviewaccessible.h b/src/view/kateviewaccessible.h --- a/src/view/kateviewaccessible.h +++ b/src/view/kateviewaccessible.h @@ -183,14 +183,52 @@ static int positionFromCursor(KateViewInternal *view, const KTextEditor::Cursor &cursor) { - int pos = 0; - for (int line = 0; line < cursor.line(); ++line) { - // length of the line plus newline - pos += view->view()->document()->line(line).size() + 1; + // static values initialized only once, to speed up the execution + static KateViewInternal *m_lastView = nullptr; + static KTextEditor::Cursor m_lastCursor; + // m_lastPosition stores the positionFromCursor, but the cursor always in column 0 + static int m_lastPosition = 0; + + int pos = m_lastPosition; + const KTextEditor::Document *doc = view->view()->document(); + + // First try the fast path using data recollected from the the last call + if (m_lastView == view) { + // Nothing to do if the lines are the same, just add the cursor.column() + if (cursor.line() != m_lastCursor.line()) { + if (m_lastCursor.line() < cursor.line()) + { + for (int line = m_lastCursor.line(); line < cursor.line(); ++line) { + pos += doc->line(line).size(); + } + // add new line character for each line + pos += cursor.line() - m_lastCursor.line(); + } + else + { + for (int line = m_lastCursor.line(); line < cursor.line(); ++line) { + pos -= doc->line(line).size() - 1; + } + // remove new line character for each line + pos -= m_lastCursor.line() - cursor.line(); + } + m_lastPosition = pos; + m_lastCursor = cursor; + } } - pos += cursor.column(); + else { + // Default case + for (int line = 0; line < cursor.line(); ++line) { + pos += doc->line(line).size(); + } + // new line for each line + pos += cursor.line(); - return pos; + m_lastCursor = cursor; + m_lastView = view; + m_lastPosition = pos; + } + return pos + cursor.column(); } private: