Commit 649e3a25 authored by dt's avatar dt
Browse files

Merge commit 'origin/1.1' into 1.1

parents d0159d7c 39bf47f7
......@@ -202,11 +202,12 @@ QT_END_NAMESPACE
#endif // PRIVATE_OBJECT_ALLOWED
// this can be mangled typenames of nested templates, each char-by-char
// comma-separated integer list
static char qDumpInBuffer[10000];
static char qDumpOutBuffer[100000];
//static char qDumpSize[20];
// This can be mangled typenames of nested templates, each char-by-char
// comma-separated integer list...
Q_DECL_EXPORT char qDumpInBuffer[10000];
// The output buffer.
Q_DECL_EXPORT char qDumpOutBuffer[100000];
namespace {
......@@ -2524,7 +2525,7 @@ static void handleProtocolVersion2and3(QDumper & d)
extern "C" Q_DECL_EXPORT
void qDumpObjectData440(
void *qDumpObjectData440(
int protocolVersion,
int token,
void *data,
......@@ -2629,4 +2630,5 @@ void qDumpObjectData440(
else {
qDebug() << "Unsupported protocol version" << protocolVersion;
}
return qDumpOutBuffer;
}
......@@ -453,7 +453,7 @@ void FileManager::changedFile(const QString &file)
foreach (IFile *fileinterface, managedFiles(file))
m_changedFiles << fileinterface;
if (wasempty && !m_changedFiles.isEmpty()) {
QTimer::singleShot (200, this, SLOT(checkForReload()));
QTimer::singleShot(200, this, SLOT(checkForReload()));
}
}
......
......@@ -1070,11 +1070,14 @@ static const char *settingsGroup = "MainWindow";
static const char *geometryKey = "Geometry";
static const char *colorKey = "Color";
static const char *maxKey = "Maximized";
static const char *fullScreenKey = "FullScreen";
void MainWindow::readSettings()
{
m_settings->beginGroup(QLatin1String(settingsGroup));
StyleHelper::setBaseColor(m_settings->value(QLatin1String(colorKey)).value<QColor>());
const QVariant geom = m_settings->value(QLatin1String(geometryKey));
if (geom.isValid()) {
setGeometry(geom.toRect());
......@@ -1083,8 +1086,10 @@ void MainWindow::readSettings()
}
if (m_settings->value(QLatin1String(maxKey), false).toBool())
setWindowState(Qt::WindowMaximized);
setFullScreen(m_settings->value(QLatin1String(fullScreenKey), false).toBool());
m_settings->endGroup();
m_editorManager->readSettings(m_settings);
m_navigationWidget->restoreSettings(m_settings);
m_rightPaneWidget->readSettings(m_settings);
......@@ -1093,14 +1098,18 @@ void MainWindow::readSettings()
void MainWindow::writeSettings()
{
m_settings->beginGroup(QLatin1String(settingsGroup));
m_settings->setValue(colorKey, StyleHelper::baseColor());
const QString maxSettingsKey = QLatin1String(maxKey);
if (windowState() & Qt::WindowMaximized) {
m_settings->setValue(maxSettingsKey, true);
m_settings->setValue(QLatin1String(colorKey), StyleHelper::baseColor());
if (windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen)) {
m_settings->setValue(QLatin1String(maxKey), (bool) (windowState() & Qt::WindowMaximized));
m_settings->setValue(QLatin1String(fullScreenKey), (bool) (windowState() & Qt::WindowFullScreen));
} else {
m_settings->setValue(maxSettingsKey, false);
m_settings->setValue(QLatin1String(maxKey), false);
m_settings->setValue(QLatin1String(fullScreenKey), false);
m_settings->setValue(QLatin1String(geometryKey), geometry());
}
m_settings->endGroup();
m_fileManager->saveRecentFiles();
......@@ -1209,7 +1218,7 @@ QPrinter *MainWindow::printer() const
{
if (!m_printer)
m_printer = new QPrinter(QPrinter::HighResolution);
return m_printer;
return m_printer;
}
void MainWindow::setFullScreen(bool on)
......
......@@ -158,7 +158,7 @@ DebuggerSettings *DebuggerSettings::instance()
instance->insertItem(UseDebuggingHelpers, item);
item->setDefaultValue(true);
item->setSettingsKey("DebugMode", "UseDebuggingHelper");
item->setText(tr("Use Debugging Helper"));
item->setText(tr("Use debugging helper"));
item->setCheckable(true);
item->setDefaultValue(true);
......
......@@ -103,6 +103,7 @@ enum GdbCommandType
GdbQuerySources,
GdbAsyncOutput2,
GdbStart,
GdbExit,
GdbAttached,
GdbStubAttached,
GdbExecRun,
......@@ -755,6 +756,9 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type,
case GdbInfoThreads:
handleInfoThreads(record);
break;
case GdbExit:
handleExit(record);
break;
case GdbShowVersion:
handleShowVersion(record);
......@@ -1167,7 +1171,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
+ data.findChild("signal-name").toString();
}
q->showStatusMessage(msg);
sendCommand("-gdb-exit");
sendCommand("-gdb-exit", GdbExit);
return;
}
......@@ -1525,7 +1529,7 @@ void GdbEngine::exitDebugger()
sendCommand("detach");
else
sendCommand("kill");
sendCommand("-gdb-exit");
sendCommand("-gdb-exit", GdbExit);
// 20s can easily happen when loading webkit debug information
m_gdbProc.waitForFinished(20000);
if (m_gdbProc.state() != QProcess::Running) {
......@@ -1797,6 +1801,12 @@ void GdbEngine::handleAttach()
qq->reloadRegisters();
}
void GdbEngine::handleExit(const GdbResultRecord &response)
{
Q_UNUSED(response);
q->showStatusMessage(tr("Debugger exited."));
}
void GdbEngine::stepExec()
{
setTokenBarrier();
......@@ -2210,6 +2220,11 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *
// within namespaces.
// Sometimes the path is relative too.
// 2 breakpoint keep y <MULTIPLE> 0x0040168e
// 2.1 y 0x0040168e in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7
// 2.2 y 0x00401792 in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7
// tested in ../../../tests/auto/debugger/
QRegExp re("MULTIPLE.*(0x[0-9a-f]+) in (.*)\\s+at (.*):([\\d]+)([^\\d]|$)");
re.setMinimal(true);
......@@ -2218,6 +2233,10 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *
data->bpFuncName = re.cap(2).trimmed();
data->bpLineNumber = re.cap(4);
QString full = fullName(re.cap(3));
if (full.isEmpty()) {
qDebug() << "NO FULL NAME KNOWN FOR" << re.cap(3);
full = re.cap(3); // FIXME: wrong, but prevents recursion
}
data->markerLineNumber = data->bpLineNumber.toInt();
data->markerFileName = full;
data->bpFileName = full;
......@@ -3400,14 +3419,15 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record)
m_availableSimpleDebuggingHelpers.append(item.data());
if (m_availableSimpleDebuggingHelpers.isEmpty()) {
m_debuggingHelperState = DebuggingHelperUnavailable;
QMessageBox::warning(q->mainWindow(),
tr("Cannot find special data dumpers"),
tr("The debugged binary does not contain information needed for "
"nice display of Qt data types.\n\n"
"You might want to try including the file\n\n"
".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n"
"into your project directly.")
);
q->showStatusMessage(tr("Debugging helpers not found."));
//QMessageBox::warning(q->mainWindow(),
// tr("Cannot find special data dumpers"),
// tr("The debugged binary does not contain information needed for "
// "nice display of Qt data types.\n\n"
// "You might want to try including the file\n\n"
// ".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n"
// "into your project directly.")
// );
} else {
m_debuggingHelperState = DebuggingHelperAvailable;
q->showStatusMessage(tr("%1 custom dumpers found.")
......@@ -4151,10 +4171,10 @@ void GdbEngine::tryLoadDebuggingHelpers()
QString flag = QString::number(RTLD_NOW);
sendCommand("sharedlibrary libc"); // for malloc
sendCommand("sharedlibrary libdl"); // for dlopen
sendCommand("call (void)dlopen(\"" + lib + "\", " + flag + ")",
sendCommand("call (void*)dlopen(\"" + lib + "\", " + flag + ")",
WatchDebuggingHelperSetup);
// some older systems like CentOS 4.6 prefer this:
sendCommand("call (void)__dlopen(\"" + lib + "\", " + flag + ")",
sendCommand("call (void*)__dlopen(\"" + lib + "\", " + flag + ")",
WatchDebuggingHelperSetup);
sendCommand("sharedlibrary " + dotEscape(lib));
#endif
......
......@@ -199,6 +199,7 @@ private:
void handleQueryPwd(const GdbResultRecord &response);
void handleQuerySources(const GdbResultRecord &response);
void handleTargetCore(const GdbResultRecord &response);
void handleExit(const GdbResultRecord &response);
void debugMessage(const QString &msg);
QString dumperLibraryName() const;
......
......@@ -932,7 +932,6 @@ QString WatchHandler::watcherName(const QString &exp)
void WatchHandler::watchExpression(const QString &exp)
{
// FIXME: 'exp' can contain illegal characters
//MODEL_DEBUG("WATCH: " << exp);
m_watchers[exp] = watcherCounter++;
WatchData data;
data.exp = exp;
......
......@@ -96,7 +96,7 @@ public:
} else if (index.column() == 0) {
// the watcher name column
theDebuggerAction(RemoveWatchExpression)->trigger(exp);
theDebuggerAction(WatchExpression)->trigger(lineEdit->text());
theDebuggerAction(WatchExpression)->trigger(value);
}
}
......@@ -175,8 +175,6 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QModelIndex idx = indexAt(ev->pos());
QModelIndex mi0 = idx.sibling(idx.row(), 0);
QString exp = model()->data(mi0).toString();
QModelIndex mi1 = idx.sibling(idx.row(), 0);
QString value = model()->data(mi1).toString();
menu.addSeparator();
int type = (m_type == LocalsType) ? WatchExpression : RemoveWatchExpression;
......
fakevim is based on eventFilters installed on a QTextEdit or a QPlainTextEdit.
It basically catches all keystrokes and modifies some internal state that
make the resulting text in the editor look like it was using vim.
There are only a few files in here:
fakevimplugin.{h,cpp} - interaction with the rest of Creator
fakevimactions.{h,cpp} - settings
fakevimhandler.{h,cpp} - the "real" event
There are some more hints for developers in fakevimhandler.cpp
......@@ -29,28 +29,33 @@
#include "fakevimhandler.h"
// Please do not add any direct dependencies to other Qt Creator code here.
// Instead emit signals and let the FakeVimPlugin channel the information to
// Qt Creator. The idea is to keep this file here in a "clean" state that
// allows easy reuse with any QTextEdit or QPlainTextEdit derived class.
// Some conventions:
//
// Use 1 based line numbers and 0 based column numbers. Even though
// the 1 based line are not nice it matches vim's and QTextEdit's 'line'
// concepts.
// ATTENTION:
//
// 1 Please do not add any direct dependencies to other Qt Creator code here.
// Instead emit signals and let the FakeVimPlugin channel the information to
// Qt Creator. The idea is to keep this file here in a "clean" state that
// allows easy reuse with any QTextEdit or QPlainTextEdit derived class.
//
// 2 There are a few auto tests located in ../../../tests/auto/fakevim.
// Commands that are covered there are marked as "// tested" below.
//
// 3 Some conventions:
//
// Do not pass QTextCursor etc around unless really needed. Convert
// early to line/column.
// Use 1 based line numbers and 0 based column numbers. Even though
// the 1 based line are not nice it matches vim's and QTextEdit's 'line'
// concepts.
//
// There is always a "current" cursor (m_tc). A current "region of interest"
// spans between m_anchor (== anchor()) and m_tc.position() (== position())
// The value of m_tc.anchor() is not used.
// Do not pass QTextCursor etc around unless really needed. Convert
// early to line/column.
//
// There is always a "current" cursor (m_tc). A current "region of interest"
// spans between m_anchor (== anchor()) and m_tc.position() (== position())
// The value of m_tc.anchor() is not used.
//
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QObject>
......@@ -278,7 +283,7 @@ public:
typedef QTextCursor::MoveOperation MoveOperation;
typedef QTextCursor::MoveMode MoveMode;
void moveToEndOfDocument() { m_tc.movePosition(EndOfDocument, MoveAnchor); }
void moveToStartOfLine() { m_tc.movePosition(StartOfLine, MoveAnchor); }
void moveToStartOfLine();
void moveToEndOfLine();
void moveUp(int n = 1) { moveDown(-n); }
void moveDown(int n = 1); // { m_tc.movePosition(Down, MoveAnchor, n); }
......@@ -353,6 +358,8 @@ public:
// extra data for '.'
void replay(const QString &text, int count);
void setDotCommand(const QString &cmd) { m_dotCommand = cmd; }
void setDotCommand(const QString &cmd, int n) { m_dotCommand = cmd.arg(n); }
QString m_dotCommand;
bool m_inReplay; // true if we are executing a '.'
......@@ -613,8 +620,9 @@ void FakeVimHandler::Private::moveDown(int n)
m_tc.movePosition(Down, MoveAnchor, n);
#else
const int col = m_tc.position() - m_tc.block().position();
const int line = m_tc.block().blockNumber();
const QTextBlock &block = m_tc.document()->findBlockByNumber(line + n);
const int lastLine = m_tc.document()->lastBlock().blockNumber();
const int targetLine = qMax(0, qMin(lastLine, m_tc.block().blockNumber() + n));
const QTextBlock &block = m_tc.document()->findBlockByNumber(targetLine);
const int pos = block.position();
setPosition(pos + qMin(block.length() - 1, col));
moveToTargetColumn();
......@@ -632,6 +640,17 @@ void FakeVimHandler::Private::moveToEndOfLine()
#endif
}
void FakeVimHandler::Private::moveToStartOfLine()
{
#if 0
// does not work for "hidden" documents like in the autotests
m_tc.movePosition(StartOfLine, MoveAnchor);
#else
const QTextBlock &block = m_tc.block();
setPosition(block.position());
#endif
}
void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
{
//qDebug() << "ANCHOR: " << position() << anchor();
......@@ -656,7 +675,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
if (anchor() >= position())
m_anchor++;
if (!dotCommand.isEmpty())
m_dotCommand = "c" + dotCommand;
setDotCommand("c" + dotCommand);
QString text = removeSelectedText();
//qDebug() << "CHANGING TO INSERT MODE" << text;
m_registers[m_register] = text;
......@@ -668,7 +687,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
if (anchor() >= position())
m_anchor++;
if (!dotCommand.isEmpty())
m_dotCommand = "d" + dotCommand;
setDotCommand("d" + dotCommand);
m_registers[m_register] = removeSelectedText();
m_submode = NoSubMode;
if (atEndOfLine())
......@@ -694,8 +713,6 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
updateMiniBuffer();
}
moveToTargetColumn();
m_moveType = MoveInclusive;
m_mvcount.clear();
m_opcount.clear();
......@@ -847,13 +864,19 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
} else if (m_submode == RegisterSubMode) {
m_register = key;
m_submode = NoSubMode;
} else if (m_submode == ChangeSubMode && key == 'c') {
moveToStartOfLine();
} else if (m_submode == ChangeSubMode && key == 'c') { // tested
moveDown(count() - 1);
moveToEndOfLine();
moveLeft();
setAnchor();
moveDown(count());
moveToStartOfLine();
setTargetColumn();
moveUp(count() - 1);
m_moveType = MoveLineWise;
finishMovement("c");
} else if (m_submode == DeleteSubMode && key == 'd') {
m_lastInsertion.clear();
setDotCommand("%1cc", count());
finishMovement();
} else if (m_submode == DeleteSubMode && key == 'd') { // tested
moveToStartOfLine();
setAnchor();
moveDown(count());
......@@ -869,19 +892,19 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
setAnchor();
moveDown(count() - 1);
m_moveType = MoveLineWise;
m_dotCommand = QString("%1<<").arg(count());
setDotCommand("%1<<", count());
finishMovement();
} else if (m_submode == ShiftRightSubMode && key == '>') {
setAnchor();
moveDown(count() - 1);
m_moveType = MoveLineWise;
m_dotCommand = QString("%1>>").arg(count());
setDotCommand("%1>>", count());
finishMovement();
} else if (m_submode == IndentSubMode && key == '=') {
setAnchor();
moveDown(count() - 1);
m_moveType = MoveLineWise;
m_dotCommand = QString("%1>>").arg(count());
setDotCommand("%1>>", count());
finishMovement();
} else if (m_submode == ZSubMode) {
//qDebug() << "Z_MODE " << cursorLineInDocument() << linesOnScreen();
......@@ -928,7 +951,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
m_tc.insertText(QString(count(), text.at(0)));
m_moveType = MoveExclusive;
m_submode = NoSubMode;
m_dotCommand = QString("%1r%2").arg(count()).arg(text);
setDotCommand("%1r" + text, count());
finishMovement();
} else {
m_submode = NoSubMode;
......@@ -1125,7 +1148,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
handleStartOfLine();
scrollToLineInDocument(cursorLineInDocument() - sline);
finishMovement();
} else if (key == 'e') {
} else if (key == 'e') { // tested
m_moveType = MoveInclusive;
moveToWordBoundary(false, true);
finishMovement();
......@@ -1175,13 +1198,13 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
handleStartOfLine();
finishMovement();
} else if (key == 'i') {
m_dotCommand = "i"; //QString("%1i").arg(count());
setDotCommand("i"); // setDotCommand("%1i", count());
enterInsertMode();
updateMiniBuffer();
if (atEndOfLine())
moveLeft();
} else if (key == 'I') {
m_dotCommand = "I"; //QString("%1I").arg(count());
setDotCommand("I"); // setDotCommand("%1I", count());
enterInsertMode();
if (m_gflag)
moveToStartOfLine();
......@@ -1256,7 +1279,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
search(lastSearchString(), !m_lastSearchForward);
recordJump();
} else if (key == 'o' || key == 'O') {
m_dotCommand = QString("%1o").arg(count());
setDotCommand("%1o", count());
enterInsertMode();
moveToFirstNonBlankOnLine();
if (key == 'O')
......@@ -1293,18 +1316,18 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
moveLeft();
}
}
m_dotCommand = QString("%1p").arg(count());
setDotCommand("%1p", count());
finishMovement();
} else if (key == 'r') {
m_submode = ReplaceSubMode;
m_dotCommand = "r";
setDotCommand("r");
} else if (key == 'R') {
// FIXME: right now we repeat the insertion count() times,
// but not the deletion
m_lastInsertion.clear();
m_mode = InsertMode;
m_submode = ReplaceSubMode;
m_dotCommand = "R";
setDotCommand("R");
} else if (key == control('r')) {
redo();
} else if (key == 's') {
......@@ -1313,7 +1336,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
setAnchor();
moveRight(qMin(count(), rightDist()));
m_registers[m_register] = removeSelectedText();
m_dotCommand = "s"; //QString("%1s").arg(count());
setDotCommand("s"); // setDotCommand("%1s", count());
m_opcount.clear();
m_mvcount.clear();
enterInsertMode();
......@@ -1340,7 +1363,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
enterVisualMode(VisualLineMode);
} else if (key == control('v')) {
enterVisualMode(VisualBlockMode);
} else if (key == 'w') {
} else if (key == 'w') { // tested
// Special case: "cw" and "cW" work the same as "ce" and "cE" if the
// cursor is on a non-blank.
if (m_submode == ChangeSubMode) {
......@@ -1369,7 +1392,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
setAnchor();
m_submode = DeleteSubMode;
moveRight(qMin(count(), rightDist()));
m_dotCommand = QString("%1x").arg(count());
setDotCommand("%1x", count());
finishMovement();
} else if (key == 'X') {
if (leftDist() > 0) {
......@@ -1957,16 +1980,16 @@ void FakeVimHandler::Private::highlightMatches(const QString &needle0)
void FakeVimHandler::Private::moveToFirstNonBlankOnLine()
{
QTextBlock block = m_tc.block();
QTextDocument *doc = m_tc.document();
m_tc.movePosition(StartOfLine, KeepAnchor);
int firstPos = m_tc.position();
const QTextBlock &block = m_tc.block();
int firstPos = block.position();
for (int i = firstPos, n = firstPos + block.length(); i < n; ++i) {
if (!doc->characterAt(i).isSpace()) {
m_tc.setPosition(i, KeepAnchor);
setPosition(i);
return;
}
}
setPosition(block.position());
}
void FakeVimHandler::Private::indentRegion(QChar typedChar)
......@@ -1978,7 +2001,7 @@ void FakeVimHandler::Private::indentRegion(QChar typedChar)
qSwap(beginLine, endLine);
int amount = 0;
emit q->indentRegion(&amount, beginLine, endLine, typedChar);
m_dotCommand = QString("%1==").arg(endLine - beginLine + 1);
setDotCommand("%1==", endLine - beginLine + 1);
}
void FakeVimHandler::Private::shiftRegionRight(int repeat)
......@@ -2000,7 +2023,7 @@ void FakeVimHandler::Private::shiftRegionRight(int repeat)
setPosition(firstPos);
moveToFirstNonBlankOnLine();
m_dotCommand = QString("%1>>").arg(endLine - beginLine + 1);
setDotCommand("%1>>", endLine - beginLine + 1);
}
void FakeVimHandler::Private::shiftRegionLeft(int repeat)
......@@ -2037,17 +2060,20 @@ void FakeVimHandler::Private::shiftRegionLeft(int repeat)
setPosition(firstPos);
moveToFirstNonBlankOnLine();
m_dotCommand = QString("%1<<").arg(endLine - beginLine + 1);
setDotCommand("%1<<", endLine - beginLine + 1);
}
void FakeVimHandler::Private::moveToTargetColumn()
{
if (m_targetColumn == -1 || m_tc.block().length() <= m_targetColumn) {
const QTextBlock &block = m_tc.block();
const QTextBlock &block = m_tc.block();
int col = m_tc.position() - m_tc.block().position();
if (col == m_targetColumn)
return;
//qDebug() << "CORRECTING COLUMN FROM: " << col << "TO" << m_targetColumn;
if (m_targetColumn == -1 || m_tc.block().length() <= m_targetColumn)
m_tc.setPosition(block.position() + block.length() - 1, KeepAnchor);
} else {
else
m_tc.setPosition(m_tc.block().position() + m_targetColumn, KeepAnchor);
}
}
/* if simple is given:
......@@ -2075,7 +2101,7 @@ void FakeVimHandler::Private::moveToWordBoundary(bool simple, bool forward)
int lastClass = -1;
while (true) {
QChar c = doc->characterAt(m_tc.position() + (forward ? 1 : -1));
qDebug() << "EXAMINING: " << c << " AT " << position();
//qDebug() << "EXAMINING: " << c << " AT " << position();
int thisClass = charClass(c, simple);
if (thisClass != lastClass && lastClass != 0)
--repeat;
......@@ -2319,6 +2345,7 @@ QString FakeVimHandler::Private::removeSelectedText()
m_tc.setPosition(pos, KeepAnchor);
QString from = m_tc.selection().toPlainText();
m_tc.removeSelectedText();
setAnchor();
return from;
}