FakeVim: Update internal cursor if it changes externally

Change-Id: I8c335e5a79699d9ae1eefdb2cd60840eea1bb300
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
Lukas Holecek
2014-11-10 18:27:38 +01:00
committed by hjk
parent 4631da97af
commit 31eb0f96d7

View File

@@ -1827,8 +1827,6 @@ public:
void movePageUp(int count = 1) { movePageDown(-count); } void movePageUp(int count = 1) { movePageDown(-count); }
void dump(const char *msg) const { void dump(const char *msg) const {
qDebug() << msg << "POS: " << anchor() << position() qDebug() << msg << "POS: " << anchor() << position()
<< "EXT: " << m_oldExternalAnchor << m_oldExternalPosition
<< "INT: " << m_oldInternalAnchor << m_oldInternalPosition
<< "VISUAL: " << g.visualMode; << "VISUAL: " << g.visualMode;
} }
void moveRight(int n = 1) { void moveRight(int n = 1) {
@@ -1871,31 +1869,19 @@ public:
m_cursor.setPosition(anchor, MoveAnchor); m_cursor.setPosition(anchor, MoveAnchor);
m_cursor.setPosition(position, KeepAnchor); m_cursor.setPosition(position, KeepAnchor);
} }
// Set cursor in text editor widget.
void commitCursor() {
if (isVisualBlockMode()) {
emit q->requestSetBlockSelection(m_cursor);
} else {
emit q->requestDisableBlockSelection();
if (editor())
EDITOR(setTextCursor(m_cursor));
}
}
// Restore cursor from editor widget.
void pullCursor() {
if (isVisualBlockMode())
q->requestBlockSelection(&m_cursor);
else if (editor())
m_cursor = EDITOR(textCursor());
}
// Set cursor in text editor widget.
void commitCursor();
// Restore cursor from editor widget.
// Update selection, record jump and target column if cursor position // Update selection, record jump and target column if cursor position
// changes externally (e.g. by code completion). // changes externally (e.g. by code completion).
void updateCursorPosition(); void pullCursor();
// Values to save when starting FakeVim processing. // Values to save when starting FakeVim processing.
int m_firstVisibleLine; int m_firstVisibleLine;
QTextCursor m_cursor; QTextCursor m_cursor;
bool m_cursorNeedsUpdate;
bool moveToPreviousParagraph(int count) { return moveToNextParagraph(-count); } bool moveToPreviousParagraph(int count) { return moveToNextParagraph(-count); }
bool moveToNextParagraph(int count); bool moveToNextParagraph(int count);
@@ -1927,6 +1913,7 @@ public:
void breakEditBlock() { m_buffer->breakEditBlock = true; } void breakEditBlock() { m_buffer->breakEditBlock = true; }
Q_SLOT void onContentsChanged(int position, int charsRemoved, int charsAdded); Q_SLOT void onContentsChanged(int position, int charsRemoved, int charsAdded);
Q_SLOT void onCursorPositionChanged();
Q_SLOT void onUndoCommandAdded(); Q_SLOT void onUndoCommandAdded();
bool isCommandLineMode() const { return g.mode == ExMode || g.subsubmode == SearchSubSubMode; } bool isCommandLineMode() const { return g.mode == ExMode || g.subsubmode == SearchSubSubMode; }
@@ -1962,8 +1949,6 @@ public:
bool selectBlockTextObject(bool inner, char left, char right); bool selectBlockTextObject(bool inner, char left, char right);
bool selectQuotedStringTextObject(bool inner, const QString &quote); bool selectQuotedStringTextObject(bool inner, const QString &quote);
Q_SLOT void importSelection();
void exportSelection();
void commitInsertState(); void commitInsertState();
void invalidateInsertState(); void invalidateInsertState();
bool isInsertStateValid() const; bool isInsertStateValid() const;
@@ -1988,10 +1973,6 @@ public:
bool m_inFakeVim; // true if currently processing a key press or a command bool m_inFakeVim; // true if currently processing a key press or a command
FakeVimHandler *q; FakeVimHandler *q;
int m_oldExternalPosition; // copy from last event to check for external changes
int m_oldExternalAnchor;
int m_oldInternalPosition; // copy from last event to check for external changes
int m_oldInternalAnchor;
int m_register; int m_register;
BlockInsertMode m_visualBlockInsert; BlockInsertMode m_visualBlockInsert;
@@ -2051,7 +2032,7 @@ public:
void insertNewLine(); void insertNewLine();
bool handleInsertInEditor(const Input &input); bool handleInsertInEditor(const Input &input);
bool passEventToEditor(QEvent &event); // Pass event to editor widget without filtering. Returns true if event was processed. bool passEventToEditor(QEvent &event, QTextCursor &tc); // Pass event to editor widget without filtering. Returns true if event was processed.
// undo handling // undo handling
int revision() const { return document()->availableUndoSteps(); } int revision() const { return document()->availableUndoSteps(); }
@@ -2069,6 +2050,7 @@ public:
// visual modes // visual modes
void toggleVisualMode(VisualMode visualMode); void toggleVisualMode(VisualMode visualMode);
void leaveVisualMode(); void leaveVisualMode();
void saveLastVisualMode();
// marks // marks
Mark mark(QChar code) const; Mark mark(QChar code) const;
@@ -2308,12 +2290,15 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget)
connect(EDITOR(document()), SIGNAL(contentsChange(int,int,int)), connect(EDITOR(document()), SIGNAL(contentsChange(int,int,int)),
SLOT(onContentsChanged(int,int,int))); SLOT(onContentsChanged(int,int,int)));
connect(EDITOR(document()), SIGNAL(undoCommandAdded()), SLOT(onUndoCommandAdded())); connect(EDITOR(document()), SIGNAL(undoCommandAdded()), SLOT(onUndoCommandAdded()));
connect(editor(), SIGNAL(cursorPositionChanged()), SLOT(onCursorPositionChanged()));
m_buffer->lastRevision = revision(); m_buffer->lastRevision = revision();
} }
} }
void FakeVimHandler::Private::init() void FakeVimHandler::Private::init()
{ {
m_cursor = QTextCursor(document());
m_cursorNeedsUpdate = true;
m_inFakeVim = false; m_inFakeVim = false;
m_findStartPosition = -1; m_findStartPosition = -1;
m_visualBlockInsert = NoneBlockInsertMode; m_visualBlockInsert = NoneBlockInsertMode;
@@ -2324,10 +2309,6 @@ void FakeVimHandler::Private::init()
m_targetColumn = 0; m_targetColumn = 0;
m_visualTargetColumn = 0; m_visualTargetColumn = 0;
m_targetColumnWrapped = 0; m_targetColumnWrapped = 0;
m_oldInternalAnchor = -1;
m_oldInternalPosition = -1;
m_oldExternalAnchor = -1;
m_oldExternalPosition = -1;
m_searchStartPosition = 0; m_searchStartPosition = 0;
m_searchFromScreenLine = 0; m_searchFromScreenLine = 0;
m_firstVisibleLine = 0; m_firstVisibleLine = 0;
@@ -2336,6 +2317,7 @@ void FakeVimHandler::Private::init()
m_ctrlVBase = 0; m_ctrlVBase = 0;
pullOrCreateBufferData(); pullOrCreateBufferData();
pullCursor();
setupCharClass(); setupCharClass();
} }
@@ -2377,17 +2359,13 @@ void FakeVimHandler::Private::enterFakeVim()
pullOrCreateBufferData(); pullOrCreateBufferData();
pullCursor();
if (m_cursor.isNull())
m_cursor = QTextCursor(document());
m_inFakeVim = true; m_inFakeVim = true;
removeEventFilter(); removeEventFilter();
updateFirstVisibleLine(); pullCursor();
updateCursorPosition(); updateFirstVisibleLine();
if (m_fakeEnd) if (m_fakeEnd)
moveRight(); moveRight();
@@ -2412,12 +2390,7 @@ void FakeVimHandler::Private::leaveFakeVim(bool needUpdate)
if (hasConfig(ConfigShowMarks)) if (hasConfig(ConfigShowMarks))
updateSelection(); updateSelection();
exportSelection();
updateCursorShape();
if (needUpdate) { if (needUpdate) {
commitCursor();
// Move cursor line to middle of screen if it's not visible. // Move cursor line to middle of screen if it's not visible.
const int line = cursorLine(); const int line = cursorLine();
if (line < firstVisibleLine() || line > firstVisibleLine() + linesOnScreen()) if (line < firstVisibleLine() || line > firstVisibleLine() + linesOnScreen())
@@ -2425,6 +2398,9 @@ void FakeVimHandler::Private::leaveFakeVim(bool needUpdate)
else else
scrollToLine(firstVisibleLine()); scrollToLine(firstVisibleLine());
updateScrollOffset(); updateScrollOffset();
commitCursor();
updateCursorShape();
} }
installEventFilter(); installEventFilter();
@@ -2538,13 +2514,11 @@ EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev)
void FakeVimHandler::Private::installEventFilter() void FakeVimHandler::Private::installEventFilter()
{ {
EDITOR(viewport()->installEventFilter(q));
EDITOR(installEventFilter(q)); EDITOR(installEventFilter(q));
} }
void FakeVimHandler::Private::removeEventFilter() void FakeVimHandler::Private::removeEventFilter()
{ {
EDITOR(viewport()->removeEventFilter(q));
EDITOR(removeEventFilter(q)); EDITOR(removeEventFilter(q));
} }
@@ -2559,66 +2533,9 @@ void FakeVimHandler::Private::setupWidget()
updateMiniBuffer(); updateMiniBuffer();
updateCursorShape(); updateCursorShape();
updateCursorPosition();
leaveFakeVim(); leaveFakeVim();
} }
void FakeVimHandler::Private::exportSelection()
{
int pos = position();
int anc = isVisualMode() ? anchor() : position();
m_oldInternalPosition = pos;
m_oldInternalAnchor = anc;
if (isVisualMode()) {
if (g.visualMode == VisualBlockMode) {
const int col1 = columnAt(anc);
const int col2 = columnAt(pos);
if (col1 > col2)
++anc;
else if (!atBlockEnd())
++pos;
// FIXME: After '$' command (i.e. m_visualTargetColumn == -1), end of selected lines
// should be selected.
setAnchorAndPosition(anc, pos);
commitCursor();
} else if (g.visualMode == VisualLineMode) {
const int posLine = lineForPosition(pos);
const int ancLine = lineForPosition(anc);
if (anc < pos) {
pos = lastPositionInLine(posLine);
anc = firstPositionInLine(ancLine);
} else {
pos = firstPositionInLine(posLine);
anc = lastPositionInLine(ancLine) + 1;
}
// putting cursor on folded line will unfold the line, so move the cursor a bit
if (!blockAt(pos).isVisible())
++pos;
setAnchorAndPosition(anc, pos);
} else if (g.visualMode == VisualCharMode) {
if (anc > pos)
++anc;
} else {
QTC_CHECK(false);
}
setAnchorAndPosition(anc, pos);
setMark(QLatin1Char('<'), markLessPosition());
setMark(QLatin1Char('>'), markGreaterPosition());
} else {
if (g.subsubmode == SearchSubSubMode && !m_searchCursor.isNull())
m_cursor = m_searchCursor;
else
setAnchorAndPosition(pos, pos);
}
m_oldExternalPosition = position();
m_oldExternalAnchor = anchor();
}
void FakeVimHandler::Private::commitInsertState() void FakeVimHandler::Private::commitInsertState()
{ {
if (!isInsertStateValid()) if (!isInsertStateValid())
@@ -2655,16 +2572,14 @@ void FakeVimHandler::Private::commitInsertState()
void FakeVimHandler::Private::invalidateInsertState() void FakeVimHandler::Private::invalidateInsertState()
{ {
m_oldInternalPosition = position();
BufferData::InsertState &insertState = m_buffer->insertState; BufferData::InsertState &insertState = m_buffer->insertState;
insertState.pos1 = -1; insertState.pos1 = -1;
insertState.pos2 = m_oldInternalPosition; insertState.pos2 = position();
insertState.backspaces = 0; insertState.backspaces = 0;
insertState.deletes = 0; insertState.deletes = 0;
insertState.spaces.clear(); insertState.spaces.clear();
insertState.insertingSpaces = false; insertState.insertingSpaces = false;
insertState.textBeforeCursor = textAt(blockAt(m_oldInternalPosition).position(), insertState.textBeforeCursor = textAt(block().position(), position());
m_oldInternalPosition);
insertState.newLineBefore = false; insertState.newLineBefore = false;
insertState.newLineAfter = false; insertState.newLineAfter = false;
} }
@@ -2716,31 +2631,6 @@ void FakeVimHandler::Private::ensureCursorVisible()
} }
} }
void FakeVimHandler::Private::importSelection()
{
if (position() == m_oldExternalPosition
&& anchor() == m_oldExternalAnchor) {
// Undo drawing correction.
setAnchorAndPosition(m_oldInternalAnchor, m_oldInternalPosition);
} else {
// Import new selection.
Qt::KeyboardModifiers mods = QApplication::keyboardModifiers();
if (m_cursor.hasSelection()) {
if (mods & HostOsInfo::controlModifier())
g.visualMode = VisualBlockMode;
else if (mods & Qt::AltModifier)
g.visualMode = VisualBlockMode;
else if (mods & Qt::ShiftModifier)
g.visualMode = VisualLineMode;
else
g.visualMode = VisualCharMode;
m_buffer->lastVisualMode = g.visualMode;
} else {
g.visualMode = NoVisualMode;
}
}
}
void FakeVimHandler::Private::updateEditor() void FakeVimHandler::Private::updateEditor()
{ {
const int charWidth = QFontMetrics(EDITOR(font())).width(QLatin1Char(' ')); const int charWidth = QFontMetrics(EDITOR(font())).width(QLatin1Char(' '));
@@ -3095,10 +2985,6 @@ void FakeVimHandler::Private::pushUndoState(bool overwrite)
m_buffer->redo.clear(); m_buffer->redo.clear();
m_buffer->lastChangePosition = CursorPosition(document(), pos); m_buffer->lastChangePosition = CursorPosition(document(), pos);
if (isVisualMode()) {
setMark(QLatin1Char('<'), markLessPosition());
setMark(QLatin1Char('>'), markGreaterPosition());
}
m_buffer->undoState = State(revision(), m_buffer->lastChangePosition, m_buffer->marks, m_buffer->undoState = State(revision(), m_buffer->lastChangePosition, m_buffer->marks,
m_buffer->lastVisualMode, m_buffer->lastVisualModeInverted); m_buffer->lastVisualMode, m_buffer->lastVisualModeInverted);
} }
@@ -3179,19 +3065,97 @@ void FakeVimHandler::Private::movePageDown(int count)
scrollToLine(qMax(0, cursorLine() - screenLines + 1)); scrollToLine(qMax(0, cursorLine() - screenLines + 1));
} }
void FakeVimHandler::Private::updateCursorPosition() void FakeVimHandler::Private::commitCursor()
{ {
importSelection(); QTextCursor tc = m_cursor;
if (position() != m_oldInternalPosition) { if (isVisualMode()) {
// record external jump to different line int pos = tc.position();
if (m_oldInternalPosition != -1 && lineForPosition(m_oldInternalPosition) != lineForPosition(position())) int anc = tc.anchor();
recordJump(m_oldInternalPosition);
setTargetColumn(); if (isVisualBlockMode()) {
if (atEndOfLine() && !isVisualMode() && !isInsertMode()) const int col1 = columnAt(anc);
moveLeft(); const int col2 = columnAt(pos);
if (col1 > col2)
++anc;
else if (!tc.atBlockEnd())
++pos;
// FIXME: After '$' command (i.e. m_visualTargetColumn == -1), end of selected lines
// should be selected.
} else if (isVisualLineMode()) {
const int posLine = lineForPosition(pos);
const int ancLine = lineForPosition(anc);
if (anc < pos) {
pos = lastPositionInLine(posLine);
anc = firstPositionInLine(ancLine);
} else {
pos = firstPositionInLine(posLine);
anc = lastPositionInLine(ancLine) + 1;
}
// putting cursor on folded line will unfold the line, so move the cursor a bit
if (!blockAt(pos).isVisible())
++pos;
} else if (isVisualCharMode()) {
if (anc > pos)
++anc;
} else {
QTC_CHECK(false);
}
tc.setPosition(anc);
tc.setPosition(pos, KeepAnchor);
} else if (g.subsubmode == SearchSubSubMode && !m_searchCursor.isNull()) {
tc = m_searchCursor;
} else {
tc.clearSelection();
} }
if (isVisualBlockMode()) {
emit q->requestSetBlockSelection(tc);
} else {
emit q->requestDisableBlockSelection();
if (editor())
EDITOR(setTextCursor(tc));
}
}
void FakeVimHandler::Private::pullCursor()
{
if (!m_cursorNeedsUpdate)
return;
m_cursorNeedsUpdate = false;
QTextCursor oldCursor = m_cursor;
bool visualBlockMode = false;
emit q->requestHasBlockSelection(&visualBlockMode);
if (visualBlockMode)
q->requestBlockSelection(&m_cursor);
else if (editor())
m_cursor = EDITOR(textCursor());
// Cursor should be always valid.
if (m_cursor.isNull())
m_cursor = QTextCursor(document());
if (visualBlockMode)
g.visualMode = VisualBlockMode;
else if (m_cursor.hasSelection())
g.visualMode = VisualCharMode;
else
g.visualMode = NoVisualMode;
// Cursor position can be after the end of line only in some modes.
if (atEndOfLine() && !isVisualMode() && !isInsertMode())
moveLeft();
// Record external jump to different line.
if (lineForPosition(position()) != lineForPosition(oldCursor.position()))
recordJump(oldCursor.position());
setTargetColumn();
} }
bool FakeVimHandler::Private::moveToNextParagraph(int count) bool FakeVimHandler::Private::moveToNextParagraph(int count)
@@ -4105,6 +4069,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
else else
g.currentCommand.append(input.toString()); g.currentCommand.append(input.toString());
} }
saveLastVisualMode();
} else { } else {
leaveCurrentMode(); leaveCurrentMode();
//qDebug() << "IGNORED IN COMMAND MODE: " << key << text //qDebug() << "IGNORED IN COMMAND MODE: " << key << text
@@ -4305,8 +4271,7 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
m_buffer->insertState.newLineBefore = true; m_buffer->insertState.newLineBefore = true;
} else { } else {
moveUp(); moveUp();
m_oldInternalPosition = position(); m_buffer->insertState.pos1 = position();
m_buffer->insertState.pos1 = m_oldInternalPosition;
m_buffer->insertState.newLineAfter = true; m_buffer->insertState.newLineAfter = true;
} }
setTargetColumn(); setTargetColumn();
@@ -4367,13 +4332,15 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input)
handleStartOfLine(); handleStartOfLine();
scrollToLine(cursorLine() - sline); scrollToLine(cursorLine() - sline);
} else if (g.gflag && input.is('v')) { } else if (g.gflag && input.is('v')) {
if (m_buffer->lastVisualMode != NoVisualMode) { if (isNoVisualMode()) {
CursorPosition from = markLessPosition(); CursorPosition from = markLessPosition();
CursorPosition to = markGreaterPosition(); CursorPosition to = markGreaterPosition();
if (m_buffer->lastVisualModeInverted)
std::swap(from, to);
toggleVisualMode(m_buffer->lastVisualMode); toggleVisualMode(m_buffer->lastVisualMode);
setCursorPosition(m_buffer->lastVisualModeInverted ? to : from); setCursorPosition(from);
setAnchor(); setAnchor();
setCursorPosition(m_buffer->lastVisualModeInverted ? from : to); setCursorPosition(to);
setTargetColumn(); setTargetColumn();
} }
} else if (input.is('v')) { } else if (input.is('v')) {
@@ -4688,8 +4655,6 @@ EventResult FakeVimHandler::Private::handleInsertOrReplaceMode(const Input &inpu
invalidateInsertState(); invalidateInsertState();
breakEditBlock(); breakEditBlock();
m_visualBlockInsert = NoneBlockInsertMode; m_visualBlockInsert = NoneBlockInsertMode;
} else if (m_oldInternalPosition == position()) {
setTargetColumn();
} }
updateMiniBuffer(); updateMiniBuffer();
@@ -4727,6 +4692,7 @@ void FakeVimHandler::Private::handleReplaceMode(const Input &input)
const QString text = input.text(); const QString text = input.text();
setAnchor(); setAnchor();
insertText(text); insertText(text);
setTargetColumn();
endEditBlock(); endEditBlock();
} }
} }
@@ -4810,6 +4776,7 @@ void FakeVimHandler::Private::finishInsertMode()
m_buffer->lastInsertion.remove(0, m_buffer->lastInsertion.indexOf(QLatin1Char('\n')) + 1); m_buffer->lastInsertion.remove(0, m_buffer->lastInsertion.indexOf(QLatin1Char('\n')) + 1);
g.dotCommand.append(m_buffer->lastInsertion + _("<ESC>")); g.dotCommand.append(m_buffer->lastInsertion + _("<ESC>"));
setTargetColumn();
enterCommandMode(); enterCommandMode();
} }
@@ -5118,8 +5085,6 @@ EventResult FakeVimHandler::Private::handleExMode(const Input &input)
showMessage(MessageCommand, g.commandBuffer.display()); showMessage(MessageCommand, g.commandBuffer.display());
handleExCommand(g.commandBuffer.contents()); handleExCommand(g.commandBuffer.contents());
g.commandBuffer.clear(); g.commandBuffer.clear();
if (m_textedit || m_plaintextedit)
leaveVisualMode();
} else if (!g.commandBuffer.handleInput(input)) { } else if (!g.commandBuffer.handleInput(input)) {
qDebug() << "IGNORED IN EX-MODE: " << input.key() << input.text(); qDebug() << "IGNORED IN EX-MODE: " << input.key() << input.text();
return EventUnhandled; return EventUnhandled;
@@ -5769,8 +5734,6 @@ bool FakeVimHandler::Private::handleExMoveCommand(const ExCommand &cmd)
if (hasConfig(ConfigStartOfLine)) if (hasConfig(ConfigStartOfLine))
moveToFirstNonBlankOnLine(); moveToFirstNonBlankOnLine();
// correct last selection
leaveVisualMode();
if (lastAnchor.line >= startLine && lastAnchor.line <= endLine) if (lastAnchor.line >= startLine && lastAnchor.line <= endLine)
lastAnchor.line += targetLine - startLine + 1; lastAnchor.line += targetLine - startLine + 1;
if (lastPosition.line >= startLine && lastPosition.line <= endLine) if (lastPosition.line >= startLine && lastPosition.line <= endLine)
@@ -6096,6 +6059,8 @@ void FakeVimHandler::Private::handleExCommand(const QString &line0)
endEditBlock(); endEditBlock();
if (isVisualMode())
leaveVisualMode();
leaveCurrentMode(); leaveCurrentMode();
} }
@@ -6480,7 +6445,7 @@ void FakeVimHandler::Private::miniBufferTextEdited(const QString &text, int curs
// update search expression // update search expression
if (g.subsubmode == SearchSubSubMode) { if (g.subsubmode == SearchSubSubMode) {
updateFind(false); updateFind(false);
exportSelection(); commitCursor();
} }
} }
} }
@@ -7050,21 +7015,15 @@ void FakeVimHandler::Private::transformText(const Range &range,
void FakeVimHandler::Private::insertText(QTextCursor &tc, const QString &text) void FakeVimHandler::Private::insertText(QTextCursor &tc, const QString &text)
{ {
if (hasConfig(ConfigPassKeys)) { if (hasConfig(ConfigPassKeys)) {
QTextCursor oldTc = m_cursor;
m_cursor = tc;
if (tc.hasSelection() && text.isEmpty()) { if (tc.hasSelection() && text.isEmpty()) {
QKeyEvent event(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier, QString()); QKeyEvent event(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier, QString());
passEventToEditor(event); passEventToEditor(event, tc);
} }
foreach (QChar c, text) { foreach (QChar c, text) {
QKeyEvent event(QEvent::KeyPress, -1, Qt::NoModifier, QString(c)); QKeyEvent event(QEvent::KeyPress, -1, Qt::NoModifier, QString(c));
passEventToEditor(event); passEventToEditor(event, tc);
} }
tc = m_cursor;
m_cursor = oldTc;
} else { } else {
tc.insertText(text); tc.insertText(text);
} }
@@ -7279,7 +7238,7 @@ void FakeVimHandler::Private::insertNewLine()
{ {
if ( m_buffer->editBlockLevel <= 1 && hasConfig(ConfigPassKeys) ) { if ( m_buffer->editBlockLevel <= 1 && hasConfig(ConfigPassKeys) ) {
QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, QLatin1String("\n")); QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, QLatin1String("\n"));
if (passEventToEditor(event)) if (passEventToEditor(event, m_cursor))
return; return;
} }
@@ -7296,27 +7255,32 @@ bool FakeVimHandler::Private::handleInsertInEditor(const Input &input)
QKeyEvent event(QEvent::KeyPress, input.key(), input.modifiers(), input.text()); QKeyEvent event(QEvent::KeyPress, input.key(), input.modifiers(), input.text());
setAnchor(); setAnchor();
if (!passEventToEditor(event)) if (!passEventToEditor(event, m_cursor))
return !m_textedit && !m_plaintextedit; // Mark event as handled if it has destroyed editor. return !m_textedit && !m_plaintextedit; // Mark event as handled if it has destroyed editor.
endEditBlock(); endEditBlock();
setTargetColumn();
return true; return true;
} }
bool FakeVimHandler::Private::passEventToEditor(QEvent &event) bool FakeVimHandler::Private::passEventToEditor(QEvent &event, QTextCursor &tc)
{ {
removeEventFilter(); removeEventFilter();
emit q->requestDisableBlockSelection();
EDITOR(setOverwriteMode(false)); EDITOR(setOverwriteMode(false));
commitCursor(); EDITOR(setTextCursor(tc));
bool accepted = QApplication::sendEvent(editor(), &event); bool accepted = QApplication::sendEvent(editor(), &event);
if (!m_textedit && !m_plaintextedit) if (!m_textedit && !m_plaintextedit)
return false; return false;
updateCursorShape(); updateCursorShape();
if (accepted) if (accepted)
pullCursor(); tc = EDITOR(textCursor());
return accepted; return accepted;
} }
@@ -7506,9 +7470,6 @@ void FakeVimHandler::Private::leaveVisualMode()
if (!isVisualMode()) if (!isVisualMode())
return; return;
setMark(QLatin1Char('<'), markLessPosition());
setMark(QLatin1Char('>'), markGreaterPosition());
m_buffer->lastVisualModeInverted = anchor() > position();
if (isVisualLineMode()) { if (isVisualLineMode()) {
g.rangemode = RangeLineMode; g.rangemode = RangeLineMode;
g.movetype = MoveLineWise; g.movetype = MoveLineWise;
@@ -7524,6 +7485,16 @@ void FakeVimHandler::Private::leaveVisualMode()
updateMiniBuffer(); updateMiniBuffer();
} }
void FakeVimHandler::Private::saveLastVisualMode()
{
if (isVisualMode() && g.mode == CommandMode && g.submode == NoSubMode) {
setMark(QLatin1Char('<'), markLessPosition());
setMark(QLatin1Char('>'), markGreaterPosition());
m_buffer->lastVisualModeInverted = anchor() > position();
m_buffer->lastVisualMode = g.visualMode;
}
}
QWidget *FakeVimHandler::Private::editor() const QWidget *FakeVimHandler::Private::editor() const
{ {
return m_textedit return m_textedit
@@ -7579,8 +7550,9 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
// Record inserted and deleted text in insert mode. // Record inserted and deleted text in insert mode.
if (isInsertMode() && (charsAdded > 0 || charsRemoved > 0)) { if (isInsertMode() && (charsAdded > 0 || charsRemoved > 0)) {
BufferData::InsertState &insertState = m_buffer->insertState; BufferData::InsertState &insertState = m_buffer->insertState;
const int oldPosition = insertState.pos2;
if (!isInsertStateValid()) { if (!isInsertStateValid()) {
insertState.pos1 = m_oldInternalPosition; insertState.pos1 = oldPosition;
g.dotCommand = _("i"); g.dotCommand = _("i");
resetCount(); resetCount();
} }
@@ -7591,7 +7563,7 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
if (position < insertState.pos1) { if (position < insertState.pos1) {
// backspaces // backspaces
const int bs = insertState.pos1 - position; const int bs = insertState.pos1 - position;
const QString inserted = textAt(position, m_oldInternalPosition); const QString inserted = textAt(position, oldPosition);
const QString removed = insertState.textBeforeCursor.right(bs); const QString removed = insertState.textBeforeCursor.right(bs);
// Ignore backspaces if same text was just inserted. // Ignore backspaces if same text was just inserted.
if ( !inserted.endsWith(removed) ) { if ( !inserted.endsWith(removed) ) {
@@ -7611,11 +7583,9 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
} }
} }
insertState.pos2 = qMax(insertState.pos2 + charsAdded - charsRemoved, const int newPosition = position + charsAdded;
position + charsAdded); insertState.pos2 = qMax(insertState.pos2 + charsAdded - charsRemoved, newPosition);
m_oldInternalPosition = position + charsAdded; insertState.textBeforeCursor = textAt(block().position(), newPosition);
insertState.textBeforeCursor = textAt(blockAt(m_oldInternalPosition).position(),
m_oldInternalPosition);
} }
} }
@@ -7623,6 +7593,12 @@ void FakeVimHandler::Private::onContentsChanged(int position, int charsRemoved,
emit q->highlightMatches(m_highlighted); emit q->highlightMatches(m_highlighted);
} }
void FakeVimHandler::Private::onCursorPositionChanged()
{
if (!m_inFakeVim)
m_cursorNeedsUpdate = true;
}
void FakeVimHandler::Private::onUndoCommandAdded() void FakeVimHandler::Private::onUndoCommandAdded()
{ {
// Undo commands removed? // Undo commands removed?
@@ -7844,10 +7820,13 @@ void FakeVimHandler::Private::enterCommandMode(Mode returnToMode)
if (g.isRecording && isCommandLineMode()) if (g.isRecording && isCommandLineMode())
record(Input(Key_Escape, NoModifier)); record(Input(Key_Escape, NoModifier));
if (isNoVisualMode() && atEndOfLine()) { if (isNoVisualMode()) {
m_cursor.movePosition(Left, KeepAnchor); if (atEndOfLine()) {
if (m_targetColumn != -1) m_cursor.movePosition(Left, KeepAnchor);
setTargetColumn(); if (m_targetColumn != -1)
setTargetColumn();
}
setAnchor();
} }
g.mode = CommandMode; g.mode = CommandMode;
@@ -8423,28 +8402,6 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev)
return QObject::eventFilter(ob, ev); return QObject::eventFilter(ob, ev);
#endif #endif
// Catch mouse events on the viewport.
QWidget *viewport = 0;
if (d->m_plaintextedit)
viewport = d->m_plaintextedit->viewport();
else if (d->m_textedit)
viewport = d->m_textedit->viewport();
if (ob == viewport) {
if (ev->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mev = static_cast<QMouseEvent *>(ev);
if (mev->button() == Qt::LeftButton) {
d->importSelection();
//return true;
}
}
if (ev->type() == QEvent::MouseButtonPress) {
QMouseEvent *mev = static_cast<QMouseEvent *>(ev);
if (mev->button() == Qt::LeftButton)
Private::g.visualMode = NoVisualMode;
}
return QObject::eventFilter(ob, ev);
}
if (ev->type() == QEvent::Shortcut) { if (ev->type() == QEvent::Shortcut) {
d->passShortcuts(false); d->passShortcuts(false);
return false; return false;