diff --git a/src/plugins/cpptools/cppcodeformatter.cpp b/src/plugins/cpptools/cppcodeformatter.cpp
index 1bfb0a574a044cfc65eedfc226e7a0bdc738c535..7028157c1b62e4b101693a799bfaa421d3db59f2 100644
--- a/src/plugins/cpptools/cppcodeformatter.cpp
+++ b/src/plugins/cpptools/cppcodeformatter.cpp
@@ -38,8 +38,7 @@ using namespace TextEditor;
 using namespace CppTools::Internal;
 
 CodeFormatter::CodeFormatter()
-    : m_document(0)
-    , m_indentDepth(0)
+    : m_indentDepth(0)
 {
 }
 
@@ -47,11 +46,6 @@ CodeFormatter::~CodeFormatter()
 {
 }
 
-void CodeFormatter::setDocument(QTextDocument *document)
-{
-    m_document = document;
-}
-
 void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
 {
     restoreBlockState(block.previous());
@@ -59,6 +53,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
     bool endedJoined = false;
     const int lexerState = tokenizeBlock(block, &endedJoined);
     m_tokenIndex = 0;
+    m_newStates.clear();
 
     if (tokenAt(0).kind() == T_POUND) {
         enter(cpp_macro_start);
@@ -84,7 +79,8 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
 
         case namespace_start:
             switch (kind) {
-            case T_LBRACE:      turnInto(namespace_open); break;
+            case T_LBRACE:      enter(namespace_open); break;
+            case T_RBRACE:      leave(); break;
             } break;
 
         case namespace_open:
@@ -92,7 +88,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
                 break;
             switch (kind) {
             case T_NAMESPACE:   enter(namespace_start); break;
-            case T_RBRACE:      leave(); break;
+            case T_RBRACE:      leave(); continue; // always nested in namespace_start
             case T_STRUCT:
             case T_UNION:
             case T_CLASS:       enter(class_start); break;
@@ -103,14 +99,14 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
         case class_start:
             switch (kind) {
             case T_SEMICOLON:   leave(); break;
-            case T_LBRACE:      turnInto(class_open); break;
+            case T_LBRACE:      enter(class_open); break;
             } break;
 
         case class_open:
             if (tryDeclaration())
                 break;
             switch (kind) {
-            case T_RBRACE:      leave(); break;
+            case T_RBRACE:      leave(); continue; // always nested in class_start
             case T_STRUCT:
             case T_UNION:
             case T_CLASS:       enter(class_start); break;
@@ -121,13 +117,19 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
         case enum_start:
             switch (kind) {
             case T_SEMICOLON:   leave(); break;
-            case T_LBRACE:      turnInto(brace_list_open); break;
+            case T_LBRACE:      enter(enum_open); break;
+            } break;
+
+        case enum_open:
+            switch (kind) {
+            case T_RBRACE:      leave(); continue; // always nested in enum_start
+            case T_LBRACE:      enter(brace_list_open); break;
             } break;
 
         case brace_list_open:
             switch (kind) {
             case T_RBRACE:      leave(); break;
-            case T_LBRACE:      enter(brace_list_open); break; // ### Other, nested brace list?
+            case T_LBRACE:      enter(brace_list_open); break;
             } break;
 
         case using_start:
@@ -156,10 +158,11 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
             if (tryExpression(true))
                 break;
             switch (kind) {
+            case T_RBRACE:
             case T_SEMICOLON:   leave(true); break;
             case T_EQUAL:       enter(initializer); break;
-            case T_LBRACE:      turnInto(defun_open); break;
-            case T_COLON:       turnInto(member_init_open); break;
+            case T_LBRACE:      enter(defun_open); break;
+            case T_COLON:       enter(member_init_open); break;
             case T_OPERATOR:    enter(operator_declaration); break;
             } break;
 
@@ -211,14 +214,14 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
         case member_init_open:
             switch (kind) {
             case T_LBRACE:      turnInto(defun_open); break;
-            case T_SEMICOLON:   leave(); break; // ### so we don't break completely if it's a bitfield or ternary
+            case T_SEMICOLON:   leave(); continue; // so we don't break completely if it's a bitfield or ternary
             } break;
 
         case defun_open:
             if (tryStatement())
                 break;
             switch (kind) {
-            case T_RBRACE:      leave(); break;
+            case T_RBRACE:      leave(); continue; // always nested in declaration_start
             } break;
 
         case switch_statement:
@@ -437,9 +440,6 @@ int CodeFormatter::indentFor(const QTextBlock &block)
 {
 //    qDebug() << "indenting for" << block.blockNumber() + 1;
 
-    Q_ASSERT(m_document);
-    Q_ASSERT(m_document == block.document());
-
     requireStatesUntil(block);
     correctIndentation(block);
     return m_indentDepth;
@@ -448,7 +448,7 @@ int CodeFormatter::indentFor(const QTextBlock &block)
 void CodeFormatter::requireStatesUntil(const QTextBlock &endBlock)
 {
     QStack<State> previousState = initialState();
-    QTextBlock it = m_document->firstBlock();
+    QTextBlock it = endBlock.document()->firstBlock();
     for (; it.isValid() && it != endBlock; it = it.next()) {
         TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
         CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
@@ -478,14 +478,19 @@ CodeFormatter::State CodeFormatter::state(int belowTop) const
         return State();
 }
 
+const QVector<CodeFormatter::State> &CodeFormatter::newStatesThisLine() const
+{
+    return m_newStates;
+}
+
 int CodeFormatter::tokenIndex() const
 {
     return m_tokenIndex;
 }
 
-int CodeFormatter::tokenIndexFromEnd() const
+int CodeFormatter::tokenCount() const
 {
-    return m_tokens.size() - 1 - m_tokenIndex;
+    return m_tokens.size();
 }
 
 const CPlusPlus::Token &CodeFormatter::currentToken() const
@@ -493,9 +498,12 @@ const CPlusPlus::Token &CodeFormatter::currentToken() const
     return m_currentToken;
 }
 
-void CodeFormatter::invalidateCache()
+void CodeFormatter::invalidateCache(QTextDocument *document)
 {
-    QTextBlock it = m_document->firstBlock();
+    if (!document)
+        return;
+
+    QTextBlock it = document->firstBlock();
     for (; it.isValid(); it = it.next()) {
         TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
         CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
@@ -509,7 +517,9 @@ void CodeFormatter::enter(int newState)
 {
     int savedIndentDepth = m_indentDepth;
     onEnter(newState, &m_indentDepth, &savedIndentDepth);
-    m_currentState.push(State(newState, savedIndentDepth));
+    State s(newState, savedIndentDepth);
+    m_currentState.push(s);
+    m_newStates.push(s);
 }
 
 void CodeFormatter::leave(bool statementDone)
@@ -518,6 +528,9 @@ void CodeFormatter::leave(bool statementDone)
     if (m_currentState.top().type == topmost_intro)
         return;
 
+    if (m_newStates.size() > 0)
+        m_newStates.pop();
+
     // restore indent depth
     State poppedState = m_currentState.pop();
     m_indentDepth = poppedState.savedIndentDepth;
@@ -794,24 +807,36 @@ void CodeFormatter::dump()
 
 QtStyleCodeFormatter::QtStyleCodeFormatter()
     : m_indentSize(4)
-    , m_style(QtStyle)
+    , m_indentSubstatementBraces(false)
+    , m_indentSubstatementStatements(true)
+    , m_indentDeclarationBraces(false)
+    , m_indentDeclarationMembers(true)
 {
 }
 
 void QtStyleCodeFormatter::setIndentSize(int size)
 {
-    if (size != m_indentSize) {
-        m_indentSize = size;
-        invalidateCache();
-    }
+    m_indentSize = size;
 }
 
-void QtStyleCodeFormatter::setCompoundStyle(CompoundStyle style)
+void QtStyleCodeFormatter::setIndentSubstatementBraces(bool onOff)
 {
-    if (style != m_style) {
-        m_style = style;
-        invalidateCache();
-    }
+    m_indentSubstatementBraces = onOff;
+}
+
+void QtStyleCodeFormatter::setIndentSubstatementStatements(bool onOff)
+{
+    m_indentSubstatementStatements = onOff;
+}
+
+void QtStyleCodeFormatter::setIndentDeclarationBraces(bool onOff)
+{
+    m_indentDeclarationBraces = onOff;
+}
+
+void QtStyleCodeFormatter::setIndentDeclarationMembers(bool onOff)
+{
+    m_indentDeclarationMembers = onOff;
 }
 
 void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedIndentDepth) const
@@ -820,7 +845,7 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
     const Token &tk = currentToken();
     const int tokenPosition = tk.begin();
     const bool firstToken = (tokenIndex() == 0);
-    const bool lastToken = (tokenIndexFromEnd() == 0);
+    const bool lastToken = (tokenIndex() == tokenCount() - 1);
 
     switch (newState) {
     case namespace_start:
@@ -874,28 +899,58 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
         break;
 
     case member_init_open:
+        // undo the continuation indent of the parent
+        *savedIndentDepth = parentState.savedIndentDepth;
+
         if (firstToken)
             *indentDepth = tokenPosition + tk.length() + 1;
         else
-            *indentDepth += m_indentSize;
+            *indentDepth = *savedIndentDepth + m_indentSize;
         break;
 
-    case defun_open:
-    case class_open:
     case case_cont:
         *indentDepth += m_indentSize;
         break;
 
-    case substatement_open:
-        if (m_style == WhitesmithsStyle)
-            break;
-        if (parentState.type != switch_statement)
+    case class_open:
+    case enum_open:
+    case defun_open:
+        // undo the continuation indent of the parent
+        *savedIndentDepth = parentState.savedIndentDepth;
+
+        if (firstToken)
+            *savedIndentDepth = tokenPosition;
+
+        *indentDepth = *savedIndentDepth;
+
+        if (m_indentDeclarationMembers)
             *indentDepth += m_indentSize;
         break;
 
+    case substatement_open:
+        if (firstToken) {
+            *savedIndentDepth = tokenPosition;
+            *indentDepth = *savedIndentDepth;
+        } else if (m_indentSubstatementBraces && !m_indentSubstatementStatements) {
+            // ### The preceding check is quite arbitrary.
+            // It actually needs another flag to determine whether the closing curly
+            // should be indented or not
+            *indentDepth = *savedIndentDepth += m_indentSize;
+        }
+
+        if (m_indentSubstatementStatements) {
+            if (parentState.type != switch_statement)
+                *indentDepth += m_indentSize;
+        }
+        break;
+
     case brace_list_open:
         if (parentState.type != initializer)
             *indentDepth = parentState.savedIndentDepth + m_indentSize;
+        else if (lastToken) {
+            *savedIndentDepth = state(1).savedIndentDepth;
+            *indentDepth = *savedIndentDepth + m_indentSize;
+        }
         break;
 
     case block_open:
@@ -919,9 +974,6 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
         // undo the continuation indent of the parent
         *indentDepth = parentState.savedIndentDepth;
         *savedIndentDepth = *indentDepth;
-        // these styles want to indent braces
-        if (m_style == GnuStyle || m_style == WhitesmithsStyle)
-            *savedIndentDepth += m_indentSize;
         break;
 
     case maybe_else: {
@@ -998,16 +1050,27 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
         }
         break;
     case T_LBRACE: {
-        // function definition - argument list is expression state
-        if (topState.type == case_cont)
+        if (topState.type == case_cont) {
             *indentDepth = topState.savedIndentDepth;
-        else if (topState.type == expression && previousState.type == declaration_start)
+        // function definition - argument list is expression state
+        } else if (topState.type == expression && previousState.type == declaration_start) {
             *indentDepth = previousState.savedIndentDepth;
-        else if (topState.type != defun_open
-                && topState.type != substatement_open
+            if (m_indentDeclarationBraces)
+                *indentDepth += m_indentSize;
+        } else if (topState.type == class_start) {
+            *indentDepth = topState.savedIndentDepth;
+            if (m_indentDeclarationBraces)
+                *indentDepth += m_indentSize;
+        } else if (topState.type == substatement) {
+            *indentDepth = topState.savedIndentDepth;
+            if (m_indentSubstatementBraces)
+                *indentDepth += m_indentSize;
+        } else if (topState.type != defun_open
                 && topState.type != block_open
-                && !topWasMaybeElse)
+                && !topWasMaybeElse) {
             *indentDepth = topState.savedIndentDepth;
+        }
+
         break;
     }
     case T_RBRACE: {
@@ -1022,7 +1085,8 @@ void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, i
                     || type == class_open
                     || type == brace_list_open
                     || type == namespace_open
-                    || type == block_open) {
+                    || type == block_open
+                    || type == enum_open) {
                 *indentDepth = state(i).savedIndentDepth;
                 break;
             }
diff --git a/src/plugins/cpptools/cppcodeformatter.h b/src/plugins/cpptools/cppcodeformatter.h
index 75a9c31095420c67c230cc54eaf43f18ec47256f..72d1fe095e4ba1ff4526c25d719f470cc93a822f 100644
--- a/src/plugins/cpptools/cppcodeformatter.h
+++ b/src/plugins/cpptools/cppcodeformatter.h
@@ -28,9 +28,8 @@ public:
     CodeFormatter();
     virtual ~CodeFormatter();
 
-    void setDocument(QTextDocument *document);
-
     int indentFor(const QTextBlock &block);
+    void invalidateCache(QTextDocument *document);
 
 protected:
     virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const = 0;
@@ -58,7 +57,8 @@ protected:
         member_init_open, // After ':' that starts a member initialization list.
 
         enum_start, // After 'enum'
-        brace_list_open, // Open brace of an enum or static array list.
+        enum_open, // Brace that opens a enum declaration.
+        brace_list_open, // Open brace nested inside an enum or for a static array list.
 
         namespace_start, // after the namespace token, before the opening brace.
         namespace_open, // Brace that opens a C++ namespace block.
@@ -125,15 +125,14 @@ protected:
     };
 
     State state(int belowTop = 0) const;
+    const QVector<State> &newStatesThisLine() const;
     int tokenIndex() const;
-    int tokenIndexFromEnd() const;
+    int tokenCount() const;
     const CPlusPlus::Token &currentToken() const;
     const CPlusPlus::Token &tokenAt(int idx) const;
 
     bool isBracelessState(int type) const;
 
-    void invalidateCache();
-
 private:
     void requireStatesUntil(const QTextBlock &block);
     void recalculateStateAfter(const QTextBlock &block);
@@ -159,10 +158,9 @@ private:
 private:
     static QStack<State> initialState();
 
-    QPointer<QTextDocument> m_document;
-
     QStack<State> m_beginState;
     QStack<State> m_currentState;
+    QStack<State> m_newStates;
 
     QList<CPlusPlus::Token> m_tokens;
     QString m_currentLine;
@@ -182,12 +180,10 @@ public:
 
     void setIndentSize(int size);
 
-    enum CompoundStyle {
-        QtStyle, // don't indent braces, add indent for contained statements
-        WhitesmithsStyle, // add indent for braces, don't for the contained statements
-        GnuStyle // add indent for braces and again for contained statements
-    };
-    void setCompoundStyle(CompoundStyle style);
+    void setIndentSubstatementBraces(bool onOff);
+    void setIndentSubstatementStatements(bool onOff);
+    void setIndentDeclarationBraces(bool onOff);
+    void setIndentDeclarationMembers(bool onOff);
 
 protected:
     virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const;
@@ -195,7 +191,10 @@ protected:
 
 private:
     int m_indentSize;
-    CompoundStyle m_style;
+    bool m_indentSubstatementBraces;
+    bool m_indentSubstatementStatements;
+    bool m_indentDeclarationBraces;
+    bool m_indentDeclarationMembers;
 };
 
 } // namespace CppTools
diff --git a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
index 7082c21b94f14218302d10d8c9d428a2ac1bd70d..8e9b5d3fec8acf08c9267ed391145f308a04cbe5 100644
--- a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
+++ b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
@@ -40,6 +40,8 @@ private Q_SLOTS:
     void memberInitializer();
     void templates();
     void operatorOverloads();
+    void gnuStyle();
+    void whitesmithsStyle();
 };
 
 struct Line {
@@ -73,12 +75,19 @@ QString concatLines(QList<Line> lines)
     return result;
 }
 
-void checkIndent(QList<Line> data)
+void checkIndent(QList<Line> data, int style = 0)
 {
     QString text = concatLines(data);
     QTextDocument document(text);
     QtStyleCodeFormatter formatter;
-    formatter.setDocument(&document);
+    if (style == 1) {// gnu
+        formatter.setIndentSubstatementBraces(true);
+    } else if (style == 2) { // whitesmiths
+        formatter.setIndentSubstatementStatements(false);
+        formatter.setIndentSubstatementBraces(true);
+        formatter.setIndentDeclarationMembers(false);
+        formatter.setIndentDeclarationBraces(true);
+    }
 
     int i = 0;
     foreach (const Line &l, data) {
@@ -594,6 +603,10 @@ void tst_CodeFormatter::braceList()
          << Line("void foo () {")
          << Line("    int[] a = { foo, bar, ")
          << Line("            car };")
+         << Line("    int[] a = {")
+         << Line("        a, b,")
+         << Line("        c")
+         << Line("    };")
          << Line("    int k;")
          ;
     checkIndent(data);
@@ -689,6 +702,46 @@ void tst_CodeFormatter::operatorOverloads()
     checkIndent(data);
 }
 
+void tst_CodeFormatter::gnuStyle()
+{
+    QList<Line> data;
+    data << Line("struct S")
+         << Line("{")
+         << Line("    void foo()")
+         << Line("    {")
+         << Line("        if (a)")
+         << Line("            {")
+         << Line("                fpp;")
+         << Line("            }")
+         << Line("        if (b) {")
+         << Line("            fpp;")
+         << Line("        }")
+         << Line("    }")
+         << Line("};")
+         ;
+    checkIndent(data, 1);
+}
+
+void tst_CodeFormatter::whitesmithsStyle()
+{
+    QList<Line> data;
+    data << Line("struct S")
+         << Line("    {")
+         << Line("    void foo()")
+         << Line("        {")
+         << Line("        if (a)")
+         << Line("            {")
+         << Line("            fpp;")
+         << Line("            }")
+         << Line("        if (b) {")
+         << Line("            fpp;")
+         << Line("            }")
+         << Line("        }")
+         << Line("    };")
+         ;
+    checkIndent(data, 2);
+}
+
 QTEST_APPLESS_MAIN(tst_CodeFormatter)
 #include "tst_codeformatter.moc"