fakevim: Fix crash when setting cursor position in edit block

Workaround for crash when setting text cursor position while in edit
block (after QTextCursor::beginEditBlock() call and before
QTextCursor::endEditBlock() call).

Task-number: QTCREATORBUG-8148
Change-Id: I7faab2e878efea4106e375b32526ecd5984feac2
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Lukas Holecek
2012-11-01 21:25:43 +01:00
committed by hjk
parent e64543aa61
commit 67bf8aa863
2 changed files with 38 additions and 8 deletions

View File

@@ -1112,6 +1112,11 @@ void FakeVimPlugin::test_vim_copy_paste()
data.setText("123" N "456" N "789"); data.setText("123" N "456" N "789");
KEYS("wyiw" "wviwp", "123" N "456" N "45" X "6"); KEYS("wyiw" "wviwp", "123" N "456" N "45" X "6");
// QTCREATORBUG-8148
data.setText("abc");
KEYS("yyp", "abc" N X "abc");
KEYS("4p", "abc" N "abc" N X "abc" N "abc" N "abc" N "abc");
} }
void FakeVimPlugin::test_vim_undo_redo() void FakeVimPlugin::test_vim_undo_redo()

View File

@@ -1369,9 +1369,21 @@ public:
tc.setPosition(position, KeepAnchor); tc.setPosition(position, KeepAnchor);
setCursor(tc); setCursor(tc);
} }
QTextCursor cursor() const { return EDITOR(textCursor()); }
void setCursor(const QTextCursor &tc) { EDITOR(setTextCursor(tc)); } // Workaround for occational crash when setting text cursor while in edit block.
QTextCursor m_cursor;
QTextCursor cursor() const {
if (m_editBlockLevel > 0)
return m_cursor;
return EDITOR(textCursor());
}
void setCursor(const QTextCursor &tc) {
m_cursor = tc;
if (m_editBlockLevel == 0)
EDITOR(setTextCursor(tc));
}
bool handleFfTt(QString key); bool handleFfTt(QString key);
@@ -1391,6 +1403,7 @@ public:
QChar characterAtCursor() const QChar characterAtCursor() const
{ return document()->characterAt(position()); } { return document()->characterAt(position()); }
int m_editBlockLevel; // current level of edit blocks
void joinPreviousEditBlock(); void joinPreviousEditBlock();
void beginEditBlock(bool rememberPosition = true); void beginEditBlock(bool rememberPosition = true);
void beginLargeEditBlock() { beginEditBlock(false); } void beginLargeEditBlock() { beginEditBlock(false); }
@@ -1691,6 +1704,7 @@ void FakeVimHandler::Private::init()
m_breakEditBlock = false; m_breakEditBlock = false;
m_searchStartPosition = 0; m_searchStartPosition = 0;
m_searchFromScreenLine = 0; m_searchFromScreenLine = 0;
m_editBlockLevel = 0;
setupCharClass(); setupCharClass();
} }
@@ -3850,10 +3864,10 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input)
//} else if (key >= control('a') && key <= control('z')) { //} else if (key >= control('a') && key <= control('z')) {
// // ignore these // // ignore these
} else if (input.isControl('p') || input.isControl('n')) { } else if (input.isControl('p') || input.isControl('n')) {
QTextCursor tc = EDITOR(textCursor()); QTextCursor tc = cursor();
moveToNextWordStart(count(), false, false); moveToNextWordStart(count(), false, false);
QString str = selectText(Range(position(), tc.position())); QString str = selectText(Range(position(), tc.position()));
EDITOR(setTextCursor(tc)); setCursor(tc);
emit q->simpleCompletionRequested(str, input.isControl('n')); emit q->simpleCompletionRequested(str, input.isControl('n'));
} else if (!input.text().isEmpty()) { } else if (!input.text().isEmpty()) {
insertInInsertMode(input.text()); insertInInsertMode(input.text());
@@ -5826,8 +5840,7 @@ void FakeVimHandler::Private::pasteText(bool afterCursor)
} }
moveDown(); moveDown();
} }
const int pos = position() - lastLine; const int pos = position();
// do not insert empty line at the end of document
if (lastLine) if (lastLine)
insertText(text.repeated(count()).left(text.size() * count() - 1)); insertText(text.repeated(count()).left(text.size() * count() - 1));
else else
@@ -6068,15 +6081,22 @@ QWidget *FakeVimHandler::Private::editor() const
void FakeVimHandler::Private::joinPreviousEditBlock() void FakeVimHandler::Private::joinPreviousEditBlock()
{ {
UNDO_DEBUG("JOIN"); UNDO_DEBUG("JOIN");
if (m_breakEditBlock) if (m_breakEditBlock) {
beginEditBlock(); beginEditBlock();
else } else {
if (m_editBlockLevel == 0)
m_cursor = cursor();
++m_editBlockLevel;
cursor().joinPreviousEditBlock(); cursor().joinPreviousEditBlock();
} }
}
void FakeVimHandler::Private::beginEditBlock(bool rememberPosition) void FakeVimHandler::Private::beginEditBlock(bool rememberPosition)
{ {
UNDO_DEBUG("BEGIN EDIT BLOCK"); UNDO_DEBUG("BEGIN EDIT BLOCK");
if (m_editBlockLevel == 0)
m_cursor = cursor();
++m_editBlockLevel;
cursor().beginEditBlock(); cursor().beginEditBlock();
if (rememberPosition) if (rememberPosition)
setUndoPosition(false); setUndoPosition(false);
@@ -6086,7 +6106,12 @@ void FakeVimHandler::Private::beginEditBlock(bool rememberPosition)
void FakeVimHandler::Private::endEditBlock() void FakeVimHandler::Private::endEditBlock()
{ {
UNDO_DEBUG("END EDIT BLOCK"); UNDO_DEBUG("END EDIT BLOCK");
QTC_ASSERT(m_editBlockLevel > 0,
qDebug() << "beginEditBlock() not called before endEditBlock()!"; return);
--m_editBlockLevel;
cursor().endEditBlock(); cursor().endEditBlock();
if (m_editBlockLevel == 0)
setCursor(m_cursor);
} }
char FakeVimHandler::Private::currentModeCode() const char FakeVimHandler::Private::currentModeCode() const