diff --git a/src/libs/cplusplus/BackwardsScanner.cpp b/src/libs/cplusplus/BackwardsScanner.cpp
index 251fa9bd19e1f51010857c10db0fea9fdcc06375..07c4688757a103f05087997d84b9e032ae479029 100644
--- a/src/libs/cplusplus/BackwardsScanner.cpp
+++ b/src/libs/cplusplus/BackwardsScanner.cpp
@@ -32,7 +32,7 @@
 
 using namespace CPlusPlus;
 
-BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, int maxBlockCount)
+BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, const QString &suffix, int maxBlockCount)
     : _offset(0)
     , _blocksTokenized(0)
     , _block(cursor.block())
@@ -40,6 +40,10 @@ BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, int maxBlockCount)
 {
     _tokenize.setSkipComments(true);
     _text = _block.text().left(cursor.position() - cursor.block().position());
+
+    if (! suffix.isEmpty())
+        _text += suffix;
+
     _tokens.append(_tokenize(_text, previousBlockState(_block)));
 }
 
diff --git a/src/libs/cplusplus/BackwardsScanner.h b/src/libs/cplusplus/BackwardsScanner.h
index 925527cbcf1b39793b4c2377cdc3d3f178f492ce..7b8e3b6e717f4667956008857f3c9f841c29e228 100644
--- a/src/libs/cplusplus/BackwardsScanner.h
+++ b/src/libs/cplusplus/BackwardsScanner.h
@@ -41,7 +41,9 @@ class CPLUSPLUS_EXPORT BackwardsScanner
     enum { MAX_BLOCK_COUNT = 10 };
 
 public:
-    BackwardsScanner(const QTextCursor &cursor, int maxBlockCount = MAX_BLOCK_COUNT);
+    BackwardsScanner(const QTextCursor &cursor,
+                     const QString &suffix = QString(),
+                     int maxBlockCount = MAX_BLOCK_COUNT);
 
     int state() const;
     int startToken() const;
diff --git a/src/libs/cplusplus/ExpressionUnderCursor.cpp b/src/libs/cplusplus/ExpressionUnderCursor.cpp
index 622b420048b6b845fddf8c2f575b6babca341444..106e3040b1bd8abe923f865103afad8beffccee5 100644
--- a/src/libs/cplusplus/ExpressionUnderCursor.cpp
+++ b/src/libs/cplusplus/ExpressionUnderCursor.cpp
@@ -153,10 +153,8 @@ QString ExpressionUnderCursor::operator()(const QTextCursor &cursor)
     return scanner.text(i, initialSize);
 }
 
-int ExpressionUnderCursor::startOfFunctionCall(const QTextCursor &cursor)
+int ExpressionUnderCursor::startOfFunctionCall(const QTextCursor &cursor) const
 {
-    QString text;
-
     BackwardsScanner scanner(cursor);
 
     int index = scanner.startToken();
diff --git a/src/libs/cplusplus/ExpressionUnderCursor.h b/src/libs/cplusplus/ExpressionUnderCursor.h
index 2c5ca12bcb6ae612146f0195e5d9ce73953af88a..35be67214df15603e3e2672e1b2456c7800ca58d 100644
--- a/src/libs/cplusplus/ExpressionUnderCursor.h
+++ b/src/libs/cplusplus/ExpressionUnderCursor.h
@@ -51,7 +51,7 @@ public:
     ~ExpressionUnderCursor();
 
     QString operator()(const QTextCursor &cursor);
-    int startOfFunctionCall(const QTextCursor &cursor);
+    int startOfFunctionCall(const QTextCursor &cursor) const;
 
 private:
     int startOfExpression(BackwardsScanner &tk, int index);
diff --git a/src/libs/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp
index 14449584d140db21803c82b60a50c12d38645bb8..86a31fc9ec58f4fee5e4c3046780fc6f12e09f7b 100644
--- a/src/libs/cplusplus/MatchingText.cpp
+++ b/src/libs/cplusplus/MatchingText.cpp
@@ -34,17 +34,124 @@
 
 using namespace CPlusPlus;
 
+enum { MAX_NUM_LINES = 400 };
+
+static bool maybeOverrideChar(const QChar &ch)
+{
+    if      (ch == QLatin1Char(')'))  return true;
+    else if (ch == QLatin1Char(']'))  return true;
+    else if (ch == QLatin1Char('"'))  return true;
+    else if (ch == QLatin1Char('\'')) return true;
+    else                               return false;
+}
+
+static bool isCompleteStringLiteral(const BackwardsScanner &tk, int index, int startToken)
+{
+    const QStringRef text = tk.textRef(index, startToken);
+
+    if (text.length() < 2)
+        return false;
+
+    else if (text.at(text.length() - 1) == QLatin1Char('"'))
+        return text.at(text.length() - 2) != QLatin1Char('\\'); // ### not exactly.
+
+    return false;
+}
+
+static bool isCompleteCharLiteral(const BackwardsScanner &tk, int index, int startToken)
+{
+    const QStringRef text = tk.textRef(index, startToken);
+
+    if (text.length() < 2)
+        return false;
+
+    else if (text.at(text.length() - 1) == QLatin1Char('\''))
+        return text.at(text.length() - 2) != QLatin1Char('\\'); // ### not exactly.
+
+    return false;
+}
+
 MatchingText::MatchingText()
 { }
 
+QString MatchingText::insertMatchingBrace(const QTextCursor &cursor, const QString &textToProcess, int *skippedChars) const
+{
+    *skippedChars = 0;
+
+    QTextCursor tc = cursor;
+    QString text = textToProcess;
+
+    const QString blockText = tc.block().text().mid(tc.columnNumber());
+    const int length = qMin(blockText.length(), textToProcess.length());
+
+    for (int i = 0; i < length; ++i) {
+        const QChar ch1 = blockText.at(i);
+        const QChar ch2 = textToProcess.at(i);
+
+        if (ch1 != ch2)
+            break;
+        else if (! maybeOverrideChar(ch1))
+            break;
+
+        ++*skippedChars;
+    }
+
+    if (*skippedChars != 0) {
+        tc.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, *skippedChars);
+        text = textToProcess.mid(*skippedChars);
+    }
+
+    if (text.isEmpty())
+        return QString();
+
+    BackwardsScanner tk(tc, textToProcess.left(*skippedChars), MAX_NUM_LINES);
+    const int startToken = tk.startToken();
+    int index = startToken;
+
+    const SimpleToken &token = tk[index - 1];
+
+    if (text.at(0) == QLatin1Char('"') && (token.is(T_STRING_LITERAL) || token.is(T_WIDE_STRING_LITERAL))) {
+        if (text.length() != 1)
+            qWarning() << Q_FUNC_INFO << "handle event compression";
+
+        if (isCompleteStringLiteral(tk, index - 1, startToken))
+            return QLatin1String("\"");
+
+        return QString();
+    } else if (text.at(0) == QLatin1Char('\'') && (token.is(T_CHAR_LITERAL) || token.is(T_WIDE_CHAR_LITERAL))) {
+        if (text.length() != 1)
+            qWarning() << Q_FUNC_INFO << "handle event compression";
+
+        if (isCompleteCharLiteral(tk, index - 1, startToken))
+            return QLatin1String("'");
+
+        return QString();
+    }
+
+    QString result;
+
+    foreach (const QChar &ch, text) {
+        if      (ch == QLatin1Char('('))  result += ')';
+        else if (ch == QLatin1Char('['))  result += ']';
+        else if (ch == QLatin1Char('"'))  result += '"';
+        else if (ch == QLatin1Char('\'')) result += '\'';
+    }
+
+    return result;
+}
+
 QString MatchingText::insertParagraphSeparator(const QTextCursor &tc) const
 {
-    BackwardsScanner tk(tc, 400);
+    BackwardsScanner tk(tc, QString(), MAX_NUM_LINES);
     int index = tk.startToken();
 
     if (tk[index - 1].isNot(T_LBRACE))
         return QString(); // nothing to do.
 
+    const QString textBlock = tc.block().text().mid(tc.columnNumber()).trimmed();
+    if (! textBlock.isEmpty())
+        return QString();
+
     --index; // consume the `{'
 
     const SimpleToken &token = tk[index - 1];
diff --git a/src/libs/cplusplus/MatchingText.h b/src/libs/cplusplus/MatchingText.h
index 3f7ef2cebf97c3481315cd576992c27950e7437c..f964c4245433d79601f1a18b06de15153fcc315e 100644
--- a/src/libs/cplusplus/MatchingText.h
+++ b/src/libs/cplusplus/MatchingText.h
@@ -41,6 +41,7 @@ class CPLUSPLUS_EXPORT MatchingText
 public:
     MatchingText();
 
+    QString insertMatchingBrace(const QTextCursor &tc, const QString &text, int *skippedChars) const;
     QString insertParagraphSeparator(const QTextCursor &tc) const;
 };
 
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index ee8f965497d9cc78321eaee44e914273f33411c3..714732e06f9a442314ce527cb38b42249d9bc15e 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -1269,6 +1269,27 @@ bool CPPEditor::isElectricCharacter(const QChar &ch) const
     return false;
 }
 
+#if 1
+QString CPPEditor::autoComplete(QTextCursor &cursor, const QString &text) const
+{
+    if (!contextAllowsAutoParentheses(cursor))
+        return QString();
+
+    QString autoText;
+    int skippedChars = 0;
+
+    MatchingText matchingText;
+    autoText = matchingText.insertMatchingBrace(cursor, text, &skippedChars);
+
+    if (skippedChars) {
+        const int pos = cursor.position();
+        cursor.setPosition(pos + skippedChars);
+        cursor.setPosition(pos, QTextCursor::KeepAnchor);
+    }
+
+    return autoText;
+}
+#else
 QString CPPEditor::autoComplete(QTextCursor &cursor, const QString &text) const
 {
     bool checkBlockEnd = m_allowSkippingOfBlockEnd;
@@ -1328,6 +1349,7 @@ QString CPPEditor::autoComplete(QTextCursor &cursor, const QString &text) const
 
     return autoText;
 }
+#endif
 
 bool CPPEditor::autoBackspace(QTextCursor &cursor)
 {
@@ -1401,9 +1423,10 @@ bool CPPEditor::contextAllowsAutoParentheses(const QTextCursor &cursor) const
 {
     CPlusPlus::TokenUnderCursor tokenUnderCursor;
     const SimpleToken tk = tokenUnderCursor(cursor);
-    if (tk.isComment() || tk.isLiteral())
-        if (tk.end() > cursor.position() - cursor.block().position())
-            return false;
+
+    if (tk.isComment())
+        return false;
+
     return true;
 }