diff --git a/src/libs/cplusplus/BackwardsScanner.cpp b/src/libs/cplusplus/BackwardsScanner.cpp
index b0b71ffecdf98e7234c93be90e2e245bd387ac9e..eb0e5c280335c9af1637b3733976819cda027b25 100644
--- a/src/libs/cplusplus/BackwardsScanner.cpp
+++ b/src/libs/cplusplus/BackwardsScanner.cpp
@@ -38,6 +38,7 @@ BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, const QString &suf
     , _block(cursor.block())
     , _maxBlockCount(maxBlockCount)
 {
+    _tokenize.setQtMocRunEnabled(true);
     _tokenize.setSkipComments(true);
     _text = _block.text().left(cursor.position() - cursor.block().position());
 
@@ -52,13 +53,10 @@ BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, const QString &suf
 int BackwardsScanner::state() const
 { return _tokenize.state(); }
 
-const QList<SimpleToken> &BackwardsScanner::tokens() const
-{ return _tokens; }
-
-const SimpleToken &BackwardsScanner::LA(int index) const
+SimpleToken BackwardsScanner::LA(int index) const
 { return const_cast<BackwardsScanner *>(this)->fetchToken(_startToken - index); }
 
-const SimpleToken &BackwardsScanner::operator[](int index) const
+SimpleToken BackwardsScanner::operator[](int index) const
 { return const_cast<BackwardsScanner *>(this)->fetchToken(index); }
 
 const SimpleToken &BackwardsScanner::fetchToken(int i)
@@ -72,16 +70,27 @@ const SimpleToken &BackwardsScanner::fetchToken(int i)
         } else {
             ++_blocksTokenized;
 
-            QString blockText = _block.text();
+            const QString blockText = _block.text();
             _text.prepend(blockText);
+
             QList<SimpleToken> adaptedTokens;
             for (int i = 0; i < _tokens.size(); ++i) {
-                const SimpleToken &t = _tokens.at(i);
-                const int position = t.position() + blockText.length();
-                adaptedTokens.append(SimpleToken(t.kind(),
-                                                 position,
-                                                 t.length(),
-                                                 _text.midRef(position, t.length())));
+                SimpleToken t = _tokens.at(i);
+                if (i == 0) {
+                    Q_ASSERT(t.followsNewline());
+                }
+                t.setPosition(t.position() + blockText.length());
+                t.setText(_text.midRef(t.position(), t.length()));
+
+                if (i == 0) {
+                    Q_ASSERT(t.followsNewline());
+                }
+
+                adaptedTokens.append(t);
+
+                if (i == 0) {
+                    Q_ASSERT(adaptedTokens.last().followsNewline());
+                }
             }
 
             _tokens = _tokenize(blockText, previousBlockState(_block));
@@ -156,6 +165,17 @@ int BackwardsScanner::startOfMatchingBrace(int index) const
                 --count;
             --i;
         } while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
+    } else if (tk[index - 1].is(T_RBRACE)) {
+        int i = index - 1;
+        int count = 0;
+        do {
+            if (tk[i].is(T_LBRACE)) {
+                if (! ++count)
+                    return i;
+            } else if (tk[i].is(T_RBRACE))
+                --count;
+            --i;
+        } while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
     } else if (tk[index - 1].is(T_GREATER)) {
         int i = index - 1;
         int count = 0;
@@ -167,7 +187,71 @@ int BackwardsScanner::startOfMatchingBrace(int index) const
                 --count;
             --i;
         } while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
+    } else {
+        Q_ASSERT(0);
+    }
+
+    return index;
+}
+
+int BackwardsScanner::startOfLine(int index) const
+{
+    const BackwardsScanner tk(*this);
+
+    forever {
+        const SimpleToken &tok = tk[index - 1];
+
+        if (tok.is(T_EOF_SYMBOL))
+            break;
+        else if (tok.followsNewline())
+            return index - 1;
+
+        --index;
     }
 
     return index;
 }
+
+int BackwardsScanner::startOfBlock(int index) const
+{
+    const BackwardsScanner tk(*this);
+
+    const int start = index;
+
+    forever {
+        SimpleToken token = tk[index - 1];
+
+        if (token.is(T_EOF_SYMBOL)) {
+            break;
+
+        } else if (token.is(T_GREATER)) {
+            const int matchingBrace = startOfMatchingBrace(index);
+
+            if (matchingBrace != index && tk[matchingBrace - 1].is(T_TEMPLATE))
+                index = matchingBrace;
+
+        } else if (token.is(T_RPAREN) || token.is(T_RBRACKET) || token.is(T_RBRACE)) {
+            const int matchingBrace = startOfMatchingBrace(index);
+
+            if (matchingBrace != index)
+                index = matchingBrace;
+
+        } else if (token.is(T_LPAREN) || token.is(T_LBRACKET)) {
+            break; // unmatched brace
+
+        } else if (token.is(T_LBRACE)) {
+            return index - 1;
+
+        }
+
+        --index;
+    }
+
+    return start;
+}
+
+int BackwardsScanner::indentation(int index) const
+{
+    SimpleToken newline = operator[](startOfLine(index + 1));
+    return newline.position();
+}
diff --git a/src/libs/cplusplus/BackwardsScanner.h b/src/libs/cplusplus/BackwardsScanner.h
index 68d1f047878ff5440b0421d964e45665f613555b..1ce6d3f85c20866c08ba6d965a55a5bf5e1d5738 100644
--- a/src/libs/cplusplus/BackwardsScanner.h
+++ b/src/libs/cplusplus/BackwardsScanner.h
@@ -55,17 +55,21 @@ public:
     QStringRef textRef(int begin, int end) const;
 
     // 1-based
-    const SimpleToken &LA(int index) const;
+    SimpleToken LA(int index) const;
 
     // n-la token is [startToken - n]
-    const SimpleToken &operator[](int index) const; // ### deprecate
+    SimpleToken operator[](int index) const; // ### deprecate
 
+    int indentation(int index) const;
+
+    int startOfLine(int index) const;
     int startOfMatchingBrace(int index) const;
+    int startOfBlock(int index) const;
+
     int previousBlockState(const QTextBlock &block) const;
 
 private:
     const SimpleToken &fetchToken(int i);
-    const QList<SimpleToken> &tokens() const;
 
 private:
     QList<SimpleToken> _tokens;
diff --git a/src/libs/cplusplus/SimpleLexer.cpp b/src/libs/cplusplus/SimpleLexer.cpp
index 7e60f76115bc7e8a27adc30612dac06fa91fb0f3..8c023d860366f35df73bd41d6fb40a192cc4b16f 100644
--- a/src/libs/cplusplus/SimpleLexer.cpp
+++ b/src/libs/cplusplus/SimpleLexer.cpp
@@ -35,6 +35,17 @@
 
 using namespace CPlusPlus;
 
+SimpleToken::SimpleToken(const Token &token, const QStringRef &text)
+    : _kind(token.f.kind)
+    , _flags(0)
+    , _position(token.begin())
+    , _length(token.f.length)
+    , _text(text)
+{
+    f._whitespace = token.f.whitespace;
+    f._newline = token.f.newline;
+}
+
 bool SimpleToken::isLiteral() const
 {
     return _kind >= T_FIRST_LITERAL && _kind <= T_LAST_LITERAL;
@@ -60,6 +71,11 @@ bool SimpleToken::isObjCAtKeyword() const
     return _kind >= T_FIRST_OBJC_AT_KEYWORD && _kind <= T_LAST_OBJC_AT_KEYWORD;
 }
 
+const char *SimpleToken::name() const
+{
+    return Token::name(_kind);
+}
+
 SimpleLexer::SimpleLexer()
     : _lastState(0),
       _skipComments(false),
@@ -113,6 +129,7 @@ QList<SimpleToken> SimpleLexer::operator()(const QString &text, int state)
     Lexer lex(firstChar, lastChar);
     lex.setQtMocRunEnabled(_qtMocRunEnabled);
     lex.setObjCEnabled(_objCEnabled);
+    lex.setStartWithNewline(true);
 
     if (! _skipComments)
         lex.setScanCommentTokens(true);
@@ -122,17 +139,26 @@ QList<SimpleToken> SimpleLexer::operator()(const QString &text, int state)
 
     bool inPreproc = false;
 
+    bool first = true;
+
     for (;;) {
         Token tk;
         lex(&tk);
         if (tk.is(T_EOF_SYMBOL))
             break;
 
-        SimpleToken simpleTk;
-        simpleTk._kind = int(tk.f.kind);
-        simpleTk._position = int(lex.tokenOffset());
-        simpleTk._length = int(lex.tokenLength());
-        simpleTk._text = text.midRef(simpleTk._position, simpleTk._length);
+        Q_ASSERT(lex.tokenOffset() == tk.begin());
+        Q_ASSERT(lex.tokenLength() == tk.f.length);
+
+        QStringRef spell = text.midRef(lex.tokenOffset(), lex.tokenLength());
+        SimpleToken simpleTk(tk, spell);
+
+        if (first) {
+            first = false;
+
+            Q_ASSERT(tk.f.newline);
+            Q_ASSERT(simpleTk.followsNewline());
+        }
 
         lex.setScanAngleStringLiteralTokens(false);
 
diff --git a/src/libs/cplusplus/SimpleLexer.h b/src/libs/cplusplus/SimpleLexer.h
index 3f15193ee036e0b76050a22eb64734766687d979..0775eccb1c9162bc7c31ec2c29757aafecc948ba 100644
--- a/src/libs/cplusplus/SimpleLexer.h
+++ b/src/libs/cplusplus/SimpleLexer.h
@@ -37,21 +37,18 @@
 namespace CPlusPlus {
 
 class SimpleLexer;
+class Token;
 
 class CPLUSPLUS_EXPORT SimpleToken
 {
 public:
-    SimpleToken(int kind, int position, int length, const QStringRef &text)
-        : _kind(kind)
-        , _position(position)
-        , _length(length)
-        , _text(text)
-    { }
+    SimpleToken(const Token &token, const QStringRef &text);
 
     SimpleToken()
-        : _kind(0),
-          _position(0),
-          _length(0)
+        : _kind(0)
+        , _flags(0)
+        , _position(0)
+        , _length(0)
     { }
 
     inline int kind() const
@@ -72,6 +69,12 @@ public:
     inline QStringRef text() const
     { return _text; }
 
+    inline bool followsNewline() const
+    { return f._newline; }
+
+    inline bool followsWhitespace() const
+    { return f._whitespace; }
+
     inline bool is(int k) const    { return _kind == k; }
     inline bool isNot(int k) const { return _kind != k; }
 
@@ -81,8 +84,27 @@ public:
     bool isComment() const;
     bool isObjCAtKeyword() const;
 
+    const char *name() const;
+
+    // internal
+    inline void setPosition(int position)
+    { _position = position; }
+
+    // internal
+    inline void setText(const QStringRef &text)
+    { _text = text; }
+
 public:
-    int _kind;
+    short _kind;
+    union {
+        short _flags;
+
+        struct {
+            short _newline: 1;
+            short _whitespace: 1;
+        } f;
+    };
+
     int _position;
     int _length;
     QStringRef _text;
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 2a681e858c514331a8ba32488909df83f2acea07..4a4c8dff1abe69d6432d8f25f39cedf7f7e8c7c0 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -53,6 +53,7 @@
 #include <cplusplus/TokenUnderCursor.h>
 #include <cplusplus/TypeOfExpression.h>
 #include <cplusplus/MatchingText.h>
+#include <cplusplus/BackwardsScanner.h>
 #include <cpptools/cppmodelmanagerinterface.h>
 
 #include <coreplugin/icore.h>
@@ -1263,6 +1264,7 @@ bool CPPEditor::isElectricCharacter(const QChar &ch) const
 {
     if (ch == QLatin1Char('{') ||
         ch == QLatin1Char('}') ||
+        ch == QLatin1Char(':') ||
         ch == QLatin1Char('#')) {
         return true;
     }
@@ -1473,6 +1475,40 @@ void CPPEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedCha
     const TextEditor::TextBlockIterator begin(doc->begin());
     const TextEditor::TextBlockIterator end(block.next());
 
+    QTextCursor tc(block);
+    tc.movePosition(QTextCursor::EndOfBlock);
+
+    BackwardsScanner tk(tc, QString(), 400);
+    const int tokenCount = tk.startToken();
+    const int indentSize = tabSettings().m_indentSize;
+
+    if (tokenCount != 0) {
+        const SimpleToken firstToken = tk[0];
+
+        if (firstToken.is(T_COLON)) {
+            const int indent = tk.indentation(-1) +  // indentation of the previous newline
+                               indentSize;
+            tabSettings().indentLine(block, indent);
+            return;
+        } else if ((firstToken.is(T_PUBLIC) || firstToken.is(T_PROTECTED) || firstToken.is(T_PRIVATE) ||
+                    firstToken.is(T_Q_SIGNALS) || firstToken.is(T_Q_SLOTS)) && tk[1].is(T_COLON)) {
+            const int startOfBlock = tk.startOfBlock(0);
+            if (startOfBlock != 0) {
+                const int indent = tk.indentation(startOfBlock);
+                tabSettings().indentLine(block, indent);
+                return;
+            }
+        } else if (firstToken.is(T_CASE) || firstToken.is(T_DEFAULT)) {
+            const int startOfBlock = tk.startOfBlock(0);
+            if (startOfBlock != 0) {
+                const int indent = tk.indentation(startOfBlock);
+                tabSettings().indentLine(block, indent);
+                return;
+            }
+            return;
+        }
+    }
+
     indentCPPBlock(tabSettings(), block, begin, end, typedChar);
 }