diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp
index b51851cd3c3cbf4300bd42a4daf57a450bede60b..31672c1ec983cb19e7347e27f01c6e5d16ad0708 100644
--- a/src/plugins/fakevim/handler.cpp
+++ b/src/plugins/fakevim/handler.cpp
@@ -99,6 +99,14 @@ enum SubSubMode
     TickSubSubMode      // used for '
 };
 
+enum VisualMode
+{
+    NoVisualMode,
+    VisualCharMode,
+    VisualLineMode,
+    VisualBlockMode,
+};
+
 static const QString ConfigStartOfLine = "startofline";
 static const QString ConfigOn = "on";
 
@@ -128,7 +136,9 @@ public:
     Private(FakeVimHandler *parent);
 
     bool eventFilter(QObject *ob, QEvent *ev);
+    void handleExCommand(const QString &cmd);
 
+private:
     static int shift(int key) { return key + 32; }
     static int control(int key) { return key + 256; }
 
@@ -140,6 +150,7 @@ public:
     void handleExMode(int key, const QString &text);
     void finishMovement(const QString &text = QString());
     void updateMiniBuffer();
+    void updateSelection();
     void search(const QString &needle, bool forward);
     void showMessage(const QString &msg);
 
@@ -167,20 +178,22 @@ public:
     void moveToNextWord(bool simple);
     void moveToWordBoundary(bool simple, bool forward);
     void handleFfTt(int key);
-    void handleExCommand(const QString &cmd);
 
     // helper function for handleCommand. return 1 based line index.
     int readLineCode(QString &cmd);
     QTextCursor selectRange(int beginLine, int endLine);
 
+public:
+    QTextEdit *m_textedit;
+    QPlainTextEdit *m_plaintextedit;
+
+private:
     FakeVimHandler *q;
     Mode m_mode;
     SubMode m_submode;
     SubSubMode m_subsubmode;
     int m_subsubdata;
     QString m_input;
-    QTextEdit *m_textedit;
-    QPlainTextEdit *m_plaintextedit;
     QTextCursor m_tc;
     QHash<int, QString> m_registers;
     int m_register;
@@ -225,9 +238,9 @@ public:
     int m_commandHistoryIndex;
 
     // visual line mode
-    void enterVisualLineMode();
-    void leaveVisualLineMode();
-    bool m_visualLineMode;
+    void enterVisualMode(VisualMode visualMode);
+    void leaveVisualMode();
+    VisualMode m_visualMode;
 
     // marks as lines
     QHash<int, int> m_marks;
@@ -250,7 +263,7 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent)
     m_gflag = false;
     m_textedit = 0;
     m_plaintextedit = 0;
-    m_visualLineMode = false;
+    m_visualMode = NoVisualMode;
 
     m_config[ConfigStartOfLine] = ConfigOn;
 }
@@ -328,17 +341,56 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
     m_gflag = false;
     m_register = '"';
     m_tc.clearSelection();
+
+    updateSelection();
     updateMiniBuffer();
 }
 
+void FakeVimHandler::Private::updateSelection()
+{
+    QList<QTextEdit::ExtraSelection> selections;
+    if (m_visualMode != NoVisualMode) {
+        QTextEdit::ExtraSelection sel;
+        sel.cursor = m_tc;
+        sel.format = m_tc.blockCharFormat();
+        sel.format.setFontWeight(QFont::Bold);
+        sel.format.setFontUnderline(true);
+        int pos = m_tc.position();
+        int anchor = m_marks['<'];
+        //qDebug() << "POS: " << pos << " ANCHOR: " << anchor;
+        if (m_visualMode == VisualCharMode) {
+            sel.cursor.setPosition(anchor, KeepAnchor);
+            selections.append(sel);
+        } else if (m_visualMode == VisualLineMode) {
+            sel.cursor.setPosition(qMin(pos, anchor), MoveAnchor);
+            sel.cursor.movePosition(StartOfLine, MoveAnchor);
+            sel.cursor.setPosition(qMax(pos, anchor), KeepAnchor);
+            sel.cursor.movePosition(EndOfLine, KeepAnchor);
+            selections.append(sel);
+        } else if (m_visualMode == VisualBlockMode) {
+            // FIXME: This shows lines right now...
+            sel.cursor.setPosition(qMin(pos, anchor), MoveAnchor);
+            sel.cursor.movePosition(StartOfLine, MoveAnchor);
+            sel.cursor.setPosition(qMax(pos, anchor), KeepAnchor);
+            sel.cursor.movePosition(EndOfLine, KeepAnchor);
+            selections.append(sel);
+        }
+    }
+    EDITOR(setExtraSelections(selections));
+}
+
 void FakeVimHandler::Private::updateMiniBuffer()
 {
     QString msg;
     if (!m_currentMessage.isEmpty()) {
         msg = m_currentMessage;
         m_currentMessage.clear();
-    } else if (m_visualLineMode) {
+    } else if (m_visualMode == VisualCharMode) {
+        msg = "-- VISUAL --";
+    } else if (m_visualMode == VisualLineMode) {
         msg = "-- VISUAL LINE --";
+    } else if (m_visualMode == VisualBlockMode) {
+        msg = "-- VISUAL BLOCK --";
     } else if (m_mode == InsertMode) {
         msg = "-- INSERT --";
     } else {
@@ -488,18 +540,18 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
         m_submode = ChangeSubMode;
         m_tc.movePosition(EndOfLine, KeepAnchor);
         finishMovement();
-    } else if (key == 'd' && m_visualLineMode) {
-        leaveVisualLineMode();
-        int beginLine = lineForPosition(m_marks['<']);
-        int endLine = lineForPosition(m_marks['>']);
-        m_tc = selectRange(beginLine, endLine);
-        m_tc.removeSelectedText();
-    } else if (key == 'd') {
+    } else if (key == 'd' && m_visualMode == NoVisualMode) {
         if (atEol())
             m_tc.movePosition(Left, MoveAnchor, 1);
         m_opcount = m_mvcount;
         m_mvcount.clear();
         m_submode = DeleteSubMode;
+    } else if (key == 'd') {
+        leaveVisualMode();
+        int beginLine = lineForPosition(m_marks['<']);
+        int endLine = lineForPosition(m_marks['>']);
+        m_tc = selectRange(beginLine, endLine);
+        m_tc.removeSelectedText();
     } else if (key == 'D') {
         m_submode = DeleteSubMode;
         m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0));
@@ -615,8 +667,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
         m_subsubdata = key;
     } else if (key == 'u') {
         undo();
+    } else if (key == 'v') {
+        enterVisualMode(VisualCharMode);
     } else if (key == 'V') {
-        enterVisualLineMode();
+        enterVisualMode(VisualLineMode);
+    } else if (key == control('v')) {
+        enterVisualMode(VisualBlockMode);
     } else if (key == 'w') {
         moveToNextWord(false);
         finishMovement("w");
@@ -657,8 +713,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
     } else if (key == Key_Delete) {
         m_tc.deleteChar();
     } else if (key == Key_Escape) {
-        if (m_visualLineMode)
-            leaveVisualLineMode();
+        if (m_visualMode != NoVisualMode)
+            leaveVisualMode();
     } else {
         qDebug() << "Ignored" << key << text;
     }    
@@ -1135,16 +1191,16 @@ int FakeVimHandler::Private::lineForPosition(int pos) const
     return tc.block().blockNumber() + 1;
 }
 
-void FakeVimHandler::Private::enterVisualLineMode()
+void FakeVimHandler::Private::enterVisualMode(VisualMode visualMode)
 {
-    m_visualLineMode = true;
+    m_visualMode = visualMode;
     m_marks['<'] = m_tc.position();
     updateMiniBuffer();
 }
 
-void FakeVimHandler::Private::leaveVisualLineMode()
+void FakeVimHandler::Private::leaveVisualMode()
 {
-    m_visualLineMode = false;
+    m_visualMode = NoVisualMode;
     m_marks['>'] = m_tc.position();
     updateMiniBuffer();
 }