diff --git a/dist/changes-1.3.0 b/dist/changes-1.3.0
index 4fca7bb31942905a49eb0abfa3357ae2ebb61812..6232c458806c1865cbe18caeaf03ed58cb63b864 100644
--- a/dist/changes-1.3.0
+++ b/dist/changes-1.3.0
@@ -25,6 +25,7 @@ Editing
    * Objective-C: Added partial semantic checking and symbol navigation
    * Fixed searching in files to take open documents into account
    * Added a Locator filter for symbols in the current document
+   * Handle block selection in fakevim
 
 Project support
    * Added support for adding and removing files from a generic Makefile-based
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 581b7e2636d144fb226a2c72391c9db73e352de1..b35ae0ee2d8935b10fd6feb262dc1bf0204cdf50 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -172,6 +172,52 @@ enum MoveType
     MoveLineWise,
 };
 
+enum RangeMode
+{
+    RangeCharMode,
+    RangeLineMode,
+    RangeBlockMode,
+};
+
+enum EventResult
+{
+    EventHandled,
+    EventUnhandled,
+    EventPassedToCore
+};
+
+struct CursorPosition
+{
+    // for jump history
+    CursorPosition() : position(-1), scrollLine(-1) {}
+    CursorPosition(int pos, int line) : position(pos), scrollLine(line) {}
+    int position; // Position in document
+    int scrollLine; // First visible line
+};
+
+struct Register
+{
+    Register() : rangemode(RangeCharMode) {}
+    Register(const QString &c, RangeMode m) : contents(c), rangemode(m) {}
+    QString contents;
+    RangeMode rangemode;
+};
+
+struct Range
+{
+    Range()
+        : beginPos(-1), endPos(-1), rangemode(RangeCharMode)
+    {}
+
+    Range(int b, int e, RangeMode m = RangeCharMode)
+        : beginPos(qMin(b, e)), endPos(qMax(b, e)), rangemode(m)
+    {} 
+
+    int beginPos;
+    int endPos;
+    RangeMode rangemode;
+};
+
 QDebug &operator<<(QDebug &ts, const QList<QTextEdit::ExtraSelection> &sels)
 {
     foreach (QTextEdit::ExtraSelection sel, sels)
@@ -192,21 +238,6 @@ QString quoteUnprintable(const QString &ba)
     return res;
 }
 
-enum EventResult
-{
-    EventHandled,
-    EventUnhandled,
-    EventPassedToCore
-};
-
-struct CursorPosition
-{
-    CursorPosition() : position(-1), scrollLine(-1) {}
-    CursorPosition(int pos, int line) : position(pos), scrollLine(line) {}
-    int position; // Position in document
-    int scrollLine; // First visible line
-};
-
 class FakeVimHandler::Private
 {
 public:
@@ -335,11 +366,12 @@ public:
     QTextCursor m_tc;
     QTextCursor m_oldTc; // copy from last event to check for external changes
     int m_anchor;
-    static QHash<int, QString> m_registers;
+    static QHash<int, Register> m_registers;
     int m_register;
     QString m_mvcount;
     QString m_opcount;
-    MoveType m_moveType;
+    MoveType m_movetype;
+    RangeMode m_rangemode;
 
     bool m_fakeEnd;
 
@@ -354,10 +386,19 @@ public:
     bool m_lastSearchForward;
     QString m_lastInsertion;
 
-    QString removeSelectedText();
     int anchor() const { return m_anchor; }
     int position() const { return m_tc.position(); }
-    QString selectedText(MoveType moveType = MoveExclusive) const;
+
+    void removeSelectedText();
+    void removeText(const Range &range);
+
+    QString selectedText() const { return text(Range(position(), anchor())); }
+    QString text(const Range &range) const;
+
+    void yankSelectedText();
+    void yankText(const Range &range, int toregister = '"');
+
+    void pasteText(bool afterCursor);
 
     // undo handling
     void undo();
@@ -423,7 +464,7 @@ public:
 
 QStringList FakeVimHandler::Private::m_searchHistory;
 QStringList FakeVimHandler::Private::m_commandHistory;
-QHash<int, QString> FakeVimHandler::Private::m_registers;
+QHash<int, Register> FakeVimHandler::Private::m_registers;
 
 FakeVimHandler::Private::Private(FakeVimHandler *parent, QWidget *widget)
 {
@@ -445,12 +486,13 @@ void FakeVimHandler::Private::init()
     m_gflag = false;
     m_visualMode = NoVisualMode;
     m_targetColumn = 0;
-    m_moveType = MoveInclusive;
+    m_movetype = MoveInclusive;
     m_anchor = 0;
     m_savedYankPosition = 0;
     m_cursorWidth = EDITOR(cursorWidth());
     m_inReplay = false;
     m_justAutoIndented = 0;
+    m_rangemode = RangeCharMode;
 }
 
 bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev)
@@ -688,32 +730,35 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
         m_marks['>'] = m_tc.position();
 
     if (m_submode == ChangeSubMode) {
-        if (m_moveType == MoveInclusive)
+        if (m_movetype == MoveInclusive)
             moveRight(); // correction
         if (anchor() >= position())
            m_anchor++;
         if (!dotCommand.isEmpty())
             setDotCommand("c" + dotCommand);
-        QString text = removeSelectedText();
+        //QString text = removeSelectedText();
         //qDebug() << "CHANGING TO INSERT MODE" << text;
-        m_registers[m_register] = text;
+        //m_registers[m_register] = text;
+        yankSelectedText();
+        removeSelectedText();
         enterInsertMode();
         m_submode = NoSubMode;
     } else if (m_submode == DeleteSubMode) {
-        if (m_moveType == MoveInclusive)
+        if (m_movetype == MoveInclusive)
             moveRight(); // correction
         if (anchor() >= position())
            m_anchor++;
         if (!dotCommand.isEmpty())
             setDotCommand("d" + dotCommand);
-        m_registers[m_register] = removeSelectedText();
+        yankSelectedText();
+        removeSelectedText();
         m_submode = NoSubMode;
         if (atEndOfLine())
             moveLeft();
         else
             setTargetColumn();
     } else if (m_submode == YankSubMode) {
-        m_registers[m_register] = selectedText();
+        yankSelectedText();
         setPosition(m_savedYankPosition);
         m_submode = NoSubMode;
     } else if (m_submode == ReplaceSubMode) {
@@ -735,12 +780,13 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
         updateMiniBuffer();
     }
 
-    m_moveType = MoveInclusive;
+    m_movetype = MoveInclusive;
     m_mvcount.clear();
     m_opcount.clear();
     m_gflag = false;
     m_register = '"';
     m_tc.clearSelection();
+    m_rangemode = RangeCharMode;
 
     updateSelection();
     updateMiniBuffer();
@@ -901,7 +947,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         moveToStartOfLine();
         setTargetColumn();
         moveUp(count() - 1);
-        m_moveType = MoveLineWise;
+        m_movetype = MoveLineWise;
         m_lastInsertion.clear();
         setDotCommand("%1cc", count());
         finishMovement();
@@ -910,32 +956,33 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         setTargetColumn(); 
         setAnchor();
         moveDown(count());
-        m_moveType = MoveLineWise;
+        m_movetype = MoveLineWise;
         setDotCommand("%1dd", count());
         finishMovement();
     } else if (m_submode == YankSubMode && key == 'y') {
-        moveToStartOfLine();
-        setAnchor();
-        moveDown(count() - 1);
-        moveBehindEndOfLine();
-        m_moveType = MoveLineWise;
+        m_movetype = MoveLineWise;
+        int endPos = firstPositionInLine(lineForPosition(position()) + count() - 1);
+        Range range(position(), endPos, RangeLineMode);
+        ///range.extendByLines(count() - 1);
+        yankText(range);
+        m_submode = NoSubMode;
         finishMovement();
     } else if (m_submode == ShiftLeftSubMode && key == '<') {
         setAnchor();
         moveDown(count() - 1);
-        m_moveType = MoveLineWise;
+        m_movetype = MoveLineWise;
         setDotCommand("%1<<", count());
         finishMovement();
     } else if (m_submode == ShiftRightSubMode && key == '>') {
         setAnchor();
         moveDown(count() - 1);
-        m_moveType = MoveLineWise;
+        m_movetype = MoveLineWise;
         setDotCommand("%1>>", count());
         finishMovement();
     } else if (m_submode == IndentSubMode && key == '=') {
         setAnchor();
         moveDown(count() - 1);
-        m_moveType = MoveLineWise;
+        m_movetype = MoveLineWise;
         setDotCommand("%1==", count());
         finishMovement();
     } else if (m_submode == ZSubMode) {
@@ -988,9 +1035,9 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
                 moveLeft();
             setAnchor();
             moveRight(count());
-            QString rem = removeSelectedText();
+            removeSelectedText();
             m_tc.insertText(QString(count(), text.at(0)));
-            m_moveType = MoveExclusive;
+            m_movetype = MoveExclusive;
             setDotCommand("%1r" + text, count());
         }
         setTargetColumn();
@@ -1105,7 +1152,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
     } else if (key == '$' || key == Key_End) {
         int submode = m_submode;
         moveToEndOfLine();
-        m_moveType = MoveExclusive;
+        m_movetype = MoveExclusive;
         setTargetColumn();
         if (submode == NoSubMode)
             m_targetColumn = -1;
@@ -1138,7 +1185,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         indentRegion();
         leaveVisualMode();
     } else if (key == '%') {
-        m_moveType = MoveExclusive;
+        m_movetype = MoveExclusive;
         moveToMatchingParanthesis();
         finishMovement();
     } else if (key == 'a') {
@@ -1155,11 +1202,11 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
     } else if (key == control('a')) {
         // FIXME: eat it to prevent the global "select all" shortcut to trigger
     } else if (key == 'b') {
-        m_moveType = MoveExclusive;
+        m_movetype = MoveExclusive;
         moveToWordBoundary(false, false);
         finishMovement();
     } else if (key == 'B') {
-        m_moveType = MoveExclusive;
+        m_movetype = MoveExclusive;
         moveToWordBoundary(true, false);
         finishMovement();
     } else if (key == 'c' && m_visualMode == NoVisualMode) {
@@ -1172,7 +1219,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
     } else if (key == 'C') {
         setAnchor();
         moveToEndOfLine();
-        m_registers[m_register] = removeSelectedText();
+        yankSelectedText();
+        removeSelectedText();
         enterInsertMode();
         setDotCommand("C");
         finishMovement();
@@ -1191,15 +1239,20 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         finishMovement();
     } else if ((key == 'd' || key == 'x') && m_visualMode == VisualLineMode) {
         leaveVisualMode();
-        int beginLine = lineForPosition(m_marks['<']);
-        int endLine = lineForPosition(m_marks['>']);
-        selectRange(beginLine, endLine);
-        m_registers[m_register] = removeSelectedText();
+        m_rangemode = RangeLineMode;
+        yankSelectedText();
+        removeSelectedText();
+    } else if ((key == 'd' || key == 'x') && m_visualMode == VisualBlockMode) {
+        leaveVisualMode();
+        m_rangemode = RangeBlockMode;
+        yankSelectedText();
+        removeSelectedText();
+        setPosition(qMin(position(), anchor()));
     } else if (key == 'D') {
         setAnchor();
         m_submode = DeleteSubMode;
         moveDown(qMax(count() - 1, 0));
-        m_moveType = MoveExclusive;
+        m_movetype = MoveExclusive;
         moveToEndOfLine();
         setDotCommand("D");
         finishMovement();
@@ -1211,11 +1264,11 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         scrollToLineInDocument(cursorLineInDocument() - sline);
         finishMovement();
     } else if (key == 'e') { // tested
-        m_moveType = MoveInclusive;
+        m_movetype = MoveInclusive;
         moveToWordBoundary(false, true);
         finishMovement();
     } else if (key == 'E') {
-        m_moveType = MoveInclusive;
+        m_movetype = MoveInclusive;
         moveToWordBoundary(true, true);
         finishMovement();
     } else if (key == control('e')) {
@@ -1226,11 +1279,11 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         finishMovement();
     } else if (key == 'f') {
         m_subsubmode = FtSubSubMode;
-        m_moveType = MoveInclusive;
+        m_movetype = MoveInclusive;
         m_subsubdata = key;
     } else if (key == 'F') {
         m_subsubmode = FtSubSubMode;
-        m_moveType = MoveExclusive;
+        m_movetype = MoveExclusive;
         m_subsubdata = key;
     } else if (key == 'g') {
         if (m_gflag) {
@@ -1284,7 +1337,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
                 || m_submode == CapitalZSubMode || m_submode == RegisterSubMode) {
             moveDown(count());
         } else {
-            m_moveType = MoveLineWise;
+            m_movetype = MoveLineWise;
             moveToStartOfLine();
             setAnchor();
             moveDown(count() + 1);
@@ -1310,7 +1363,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
                 || m_submode == CapitalZSubMode || m_submode == RegisterSubMode) {
             moveUp(count());
         } else {
-            m_moveType = MoveLineWise;
+            m_movetype = MoveLineWise;
             moveToStartOfLine();
             moveDown();
             setAnchor();
@@ -1318,7 +1371,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         }
         finishMovement("k");
     } else if (key == 'l' || key == Key_Right || key == ' ') {
-        m_moveType = MoveExclusive;
+        m_movetype = MoveExclusive;
         moveRight(qMin(count(), rightDist()));
         setTargetColumn();
         finishMovement("l");
@@ -1363,29 +1416,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
             m_jumpListUndo.pop_back();
         }
     } else if (key == 'p' || key == 'P') {
-        QString text = m_registers[m_register];
-        int n = text.count(QChar('\n'));
-        //qDebug() << "REGISTERS: " << m_registers << "MOVE: " << m_moveType;
-        //qDebug() << "LINES: " << n << text << m_register;
-        if (n > 0) {
-            moveToStartOfLine();
-            m_targetColumn = 0;
-            for (int i = count(); --i >= 0; ) {
-                if (key == 'p')
-                    moveDown();
-                m_tc.insertText(text);
-                moveUp(n);
-            }
-            moveToFirstNonBlankOnLine();
-        } else {
-            m_targetColumn = 0;
-            for (int i = count(); --i >= 0; ) {
-                if (key == 'p')
-                    moveRight();
-                m_tc.insertText(text);
-                moveLeft();
-            }
-        }
+        pasteText(key == 'p');
+        setTargetColumn();
         setDotCommand("%1p", count());
         finishMovement();
     } else if (key == 'r') {
@@ -1405,17 +1437,18 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
             moveLeft();
         setAnchor();
         moveRight(qMin(count(), rightDist()));
-        m_registers[m_register] = removeSelectedText();
+        yankSelectedText();
+        removeSelectedText();
         setDotCommand("s"); // setDotCommand("%1s", count());
         m_opcount.clear();
         m_mvcount.clear();
         enterInsertMode();
     } else if (key == 't') {
-        m_moveType = MoveInclusive;
+        m_movetype = MoveInclusive;
         m_subsubmode = FtSubSubMode;
         m_subsubdata = key;
     } else if (key == 'T') {
-        m_moveType = MoveExclusive;
+        m_movetype = MoveExclusive;
         m_subsubmode = FtSubSubMode;
         m_subsubdata = key;
     } else if (key == 'u') {
@@ -1438,25 +1471,25 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         // cursor is on a non-blank.
         if (m_submode == ChangeSubMode) {
             moveToWordBoundary(false, true);
-            m_moveType = MoveInclusive;
+            m_movetype = MoveInclusive;
         } else {
             moveToNextWord(false);
-            m_moveType = MoveExclusive;
+            m_movetype = MoveExclusive;
         }
         finishMovement("w");
     } else if (key == 'W') {
         if (m_submode == ChangeSubMode) {
             moveToWordBoundary(true, true);
-            m_moveType = MoveInclusive;
+            m_movetype = MoveInclusive;
         } else {
             moveToNextWord(true);
-            m_moveType = MoveExclusive;
+            m_movetype = MoveExclusive;
         }
         finishMovement("W");
     } else if (key == control('w')) {
         m_submode = WindowSubMode;
     } else if (key == 'x' && m_visualMode == NoVisualMode) { // = "dl"
-        m_moveType = MoveExclusive;
+        m_movetype = MoveExclusive;
         if (atEndOfLine())
             moveLeft();
         setAnchor();
@@ -1468,7 +1501,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
         if (leftDist() > 0) {
             setAnchor();
             moveLeft(qMin(count(), leftDist()));
-            m_registers[m_register] = removeSelectedText();
+            yankSelectedText();
+            removeSelectedText();
         }
         finishMovement();
     } else if (key == 'y' && m_visualMode == NoVisualMode) {
@@ -1477,30 +1511,36 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
             moveLeft();
         setAnchor();
         m_submode = YankSubMode;
+        m_rangemode = RangeCharMode;
     } else if (key == 'y' && m_visualMode == VisualCharMode) {
-        m_registers[m_register] = selectedText(MoveInclusive);
+        Range range(position(), anchor(), RangeCharMode);
+        range.endPos++; // MoveInclusive
+        yankText(range, m_register);
         setPosition(qMin(position(), anchor()));
         leaveVisualMode();
         finishMovement();
     } else if (key == 'Y' && m_visualMode == NoVisualMode)  {
         const int line = cursorLineInDocument() + 1;
         selectRange(line, line + count() - 1);
-        m_registers[m_register] = selectedText();
+        m_rangemode = RangeLineMode;
+        yankSelectedText();
         setPosition(qMin(position(), anchor()));
         finishMovement();
     } else if ((key == 'y' && m_visualMode == VisualLineMode)
             || (key == 'Y' && m_visualMode == VisualLineMode)
             || (key == 'Y' && m_visualMode == VisualCharMode)) {
-        int beginLine = lineForPosition(m_marks['<']);
-        int endLine = lineForPosition(m_marks['>']);
-        selectRange(beginLine, endLine);
-        m_registers[m_register] = selectedText();
+        m_rangemode = RangeLineMode;
+        yankSelectedText();
         setPosition(qMin(position(), anchor()));
         moveToStartOfLine();
         leaveVisualMode();
         finishMovement();
     } else if ((key == 'y' || key == 'Y') && m_visualMode == VisualBlockMode) {
-        // not implemented
+        m_rangemode = RangeBlockMode;
+        yankSelectedText();
+        setPosition(qMin(position(), anchor()));
+        leaveVisualMode();
+        finishMovement();
     } else if (key == 'z') {
         m_submode = ZSubMode;
     } else if (key == 'Z') {
@@ -1508,7 +1548,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
     } else if (key == '~' && !atEndOfLine()) {
         setAnchor();
         moveRight(qMin(count(), rightDist()));
-        QString str = removeSelectedText();
+        QString str = selectedText();
+        removeSelectedText();
         for (int i = str.size(); --i >= 0; ) {
             QChar c = str.at(i);
             str[i] = c.isUpper() ? c.toLower() : c.toUpper();
@@ -1840,9 +1881,13 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
     } else if (reDelete.indexIn(cmd) != -1) { // :d
         selectRange(beginLine, endLine);
         QString reg = reDelete.cap(2);
-        QString text = removeSelectedText();
-        if (!reg.isEmpty())
-            m_registers[reg.at(0).unicode()] = text;
+        QString text = selectedText();
+        removeSelectedText();
+        if (!reg.isEmpty()) {
+            Register &r = m_registers[reg.at(0).unicode()];
+            r.contents = text;
+            r.rangemode = RangeLineMode;
+        }
     } else if (reWrite.indexIn(cmd) != -1) { // :w and :x
         bool noArgs = (beginLine == -1);
         if (beginLine == -1)
@@ -1869,8 +1914,9 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
         } else if (file1.open(QIODevice::ReadWrite)) {
             file1.close();
             QTextCursor tc = m_tc;
-            selectRange(beginLine, endLine);
-            QString contents = selectedText();
+            Range range(firstPositionInLine(beginLine),
+                firstPositionInLine(endLine), RangeLineMode);
+            QString contents = text(range);
             m_tc = tc;
             qDebug() << "LINES: " << beginLine << endLine;
             bool handled = false;
@@ -1913,7 +1959,8 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
     } else if (cmd.startsWith(QLatin1Char('!'))) {
         selectRange(beginLine, endLine);
         QString command = cmd.mid(1).trimmed();
-        QString text = removeSelectedText();
+        QString text = selectedText();
+        removeSelectedText();
         QProcess proc;
         proc.start(cmd.mid(1));
         proc.waitForStarted();
@@ -2203,7 +2250,8 @@ void FakeVimHandler::Private::shiftRegionLeft(int repeat)
                 break;
         }
         setPosition(pos + i);
-        text = removeSelectedText();
+        text = selectedText();
+        removeSelectedText();
         setPosition(pos);
     }
 
@@ -2413,16 +2461,168 @@ QString FakeVimHandler::Private::lastSearchString() const
      return m_searchHistory.empty() ? QString() : m_searchHistory.back();
 }
 
-QString FakeVimHandler::Private::selectedText(MoveType moveType) const
+QString FakeVimHandler::Private::text(const Range &range) const
+{
+    if (range.rangemode == RangeCharMode) {
+        QTextCursor tc = m_tc;
+        tc.setPosition(range.beginPos, MoveAnchor);
+        tc.setPosition(range.endPos, KeepAnchor);
+        return tc.selection().toPlainText();
+    }
+    // FIXME: Performance?
+    int beginLine = lineForPosition(range.beginPos);
+    int endLine = lineForPosition(range.endPos);
+    int beginColumn = 0;
+    int endColumn = INT_MAX;
+    if (range.rangemode == RangeBlockMode) {
+        int column1 = range.beginPos - firstPositionInLine(beginLine); 
+        int column2 = range.endPos - firstPositionInLine(endLine); 
+        beginColumn = qMin(column1, column2);
+        endColumn = qMax(column1, column2);
+        qDebug() << "COLS: " << beginColumn << endColumn;
+    } 
+    int len = endColumn - beginColumn + 1;
+    QString contents;
+    QTextBlock block = m_tc.document()->findBlockByNumber(beginLine - 1);
+    for (int i = beginLine; i <= endLine && block.isValid(); ++i) {
+        QString line = block.text();
+        if (range.rangemode == RangeBlockMode) {
+            line = line.mid(beginColumn, len);
+            if (line.size() < len)
+                line += QString(len - line.size(), QChar(' '));
+        }
+        contents += line;
+        if (!contents.endsWith('\n'))
+            contents += '\n';
+        block = block.next();
+    }
+    //qDebug() << "SELECTED: " << contents;
+    return contents;
+}
+
+void FakeVimHandler::Private::yankSelectedText()
+{
+    Range range(anchor(), position());
+    range.rangemode = m_rangemode;
+    yankText(range, m_register);
+}
+
+void FakeVimHandler::Private::yankText(const Range &range, int toregister)
+{
+    Register &reg = m_registers[toregister];
+    reg.contents = text(range);
+    reg.rangemode = range.rangemode;
+    //qDebug() << "YANKED: " << reg.contents;
+}
+
+void FakeVimHandler::Private::removeSelectedText()
+{
+    Range range(anchor(), position());
+    range.rangemode = m_rangemode;
+    removeText(range);
+}
+
+void FakeVimHandler::Private::removeText(const Range &range)
 {
-    int beginPos = qMin(position(), anchor());
-    int endPos = qMax(position(), anchor());
-    if (moveType == MoveInclusive)
-        ++endPos;
     QTextCursor tc = m_tc;
-    tc.setPosition(beginPos, MoveAnchor);
-    tc.setPosition(endPos, KeepAnchor);
-    return tc.selection().toPlainText();
+    switch (range.rangemode) {
+        case RangeCharMode: {
+            tc.setPosition(range.beginPos, MoveAnchor);
+            tc.setPosition(range.endPos, KeepAnchor);
+            tc.removeSelectedText();
+            return;
+        }
+        case RangeLineMode: {
+            tc.setPosition(range.beginPos, MoveAnchor);
+            tc.movePosition(StartOfLine, MoveAnchor);
+            tc.setPosition(range.endPos, KeepAnchor);
+            tc.movePosition(EndOfLine, KeepAnchor);
+            tc.movePosition(Right, KeepAnchor, 1);
+            tc.removeSelectedText();
+            return;
+        }
+        case RangeBlockMode: {
+            int beginLine = lineForPosition(range.beginPos);
+            int endLine = lineForPosition(range.endPos);
+            int column1 = range.beginPos - firstPositionInLine(beginLine); 
+            int column2 = range.endPos - firstPositionInLine(endLine); 
+            int beginColumn = qMin(column1, column2);
+            int endColumn = qMax(column1, column2);
+            qDebug() << "COLS: " << beginColumn << endColumn;
+
+            QTextBlock block = m_tc.document()->findBlockByNumber(endLine - 1);
+            beginEditBlock();
+            for (int i = beginLine; i <= endLine && block.isValid(); ++i) {
+                int bCol = qMin(beginColumn, block.length() - 1);
+                int eCol = qMin(endColumn, block.length() - 1);
+                tc.setPosition(block.position() + bCol, MoveAnchor);
+                tc.setPosition(block.position() + eCol, KeepAnchor);
+                tc.removeSelectedText();
+                block = block.previous();
+            }
+            endEditBlock();
+        }
+    }
+}
+
+void FakeVimHandler::Private::pasteText(bool afterCursor)
+{
+    const QString text = m_registers[m_register].contents;
+    const QStringList lines = text.split(QChar('\n'));
+    switch (m_registers[m_register].rangemode) {
+        case RangeCharMode: {
+            m_targetColumn = 0;
+            for (int i = count(); --i >= 0; ) {
+                if (afterCursor && rightDist() > 0)
+                    moveRight();
+                m_tc.insertText(text);
+                moveLeft();
+            }
+            break;
+        }
+        case RangeLineMode: {
+            moveToStartOfLine();
+            m_targetColumn = 0;
+            for (int i = count(); --i >= 0; ) {
+                if (afterCursor)
+                    moveDown();
+                m_tc.insertText(text);
+                moveUp(lines.size() - 1);
+            }
+            moveToFirstNonBlankOnLine();
+            break;
+        }
+        case RangeBlockMode: {
+            beginEditBlock();
+            QTextBlock block = m_tc.block();
+            moveRight();
+            QTextCursor tc = m_tc;
+            const int col = tc.position() - block.position();
+            //for (int i = lines.size(); --i >= 0; ) {
+            for (int i = 0; i < lines.size(); ++i) {
+                const QString line = lines.at(i);
+                tc.movePosition(StartOfLine, MoveAnchor);
+                if (col >= block.length()) {
+                    tc.movePosition(EndOfLine, MoveAnchor);
+                    tc.insertText(QString(col - line.size() + 1, QChar(' ')));
+                } else { 
+                    tc.movePosition(Right, MoveAnchor, col);
+                }
+                qDebug() << "INSERT " << line << " AT " << tc.position()
+                    << "COL: " << col;
+                tc.insertText(line);
+                tc.movePosition(StartOfLine, MoveAnchor);
+                tc.movePosition(Down, MoveAnchor, 1);
+                if (tc.position() >= lastPositionInDocument() - 1) {
+                    tc.insertText(QString(QChar('\n')));
+                    tc.movePosition(Up, MoveAnchor, 1);
+                }
+                block = block.next();
+            }
+            endEditBlock();
+            break;
+        }
+    }
 }
 
 int FakeVimHandler::Private::firstPositionInLine(int line) const
@@ -2497,20 +2697,6 @@ void FakeVimHandler::Private::redo()
         m_tc.setPosition(m_undoCursorPosition[rev]);
 }
 
-QString FakeVimHandler::Private::removeSelectedText()
-{
-    //qDebug() << "POS: " << position() << " ANCHOR: " << anchor() << m_tc.anchor();
-    int pos = m_tc.position();
-    if (pos == anchor())
-        return QString();
-    m_tc.setPosition(anchor(), MoveAnchor);
-    m_tc.setPosition(pos, KeepAnchor);
-    QString from = m_tc.selection().toPlainText();
-    m_tc.removeSelectedText();
-    setAnchor();
-    return from;
-}
-
 void FakeVimHandler::Private::enterInsertMode()
 {
     EDITOR(setCursorWidth(m_cursorWidth));
diff --git a/tests/manual/fakevim/main.cpp b/tests/manual/fakevim/main.cpp
index 0b4e1c612621effcb4096dde52ef9a457d93ce17..2b8717316b0f13bc452eb00c128af719a91f6001 100644
--- a/tests/manual/fakevim/main.cpp
+++ b/tests/manual/fakevim/main.cpp
@@ -108,8 +108,8 @@ int main(int argc, char *argv[])
 
     QObject::connect(&handler, SIGNAL(commandBufferChanged(QString)),
         &proxy, SLOT(changeStatusMessage(QString)));
-    QObject::connect(&handler, SIGNAL(quitRequested(bool)),
-        &app, SLOT(quit()));
+    //QObject::connect(&handler, SIGNAL(quitRequested(bool)),
+    //    &app, SLOT(quit()));
     QObject::connect(&handler,
         SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
         &proxy, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));