diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp
index 1bf515f92e5d33e38628e4adb29183ac6db78484..80ab420c5fa1e139c7ecac08aa6f59c551accc56 100644
--- a/share/qtcreator/gdbmacros/gdbmacros.cpp
+++ b/share/qtcreator/gdbmacros/gdbmacros.cpp
@@ -602,8 +602,7 @@ QDumper &QDumper::operator<<(const QByteArray &ba)
 
 QDumper &QDumper::operator<<(const QString &str)
 {
-    QByteArray ba = str.toUtf8();
-    putBase64Encoded(ba.constData(), ba.size());
+    putBase64Encoded((const char *)str.constData(), 2 * str.size());
     return *this;
 }
 
@@ -649,7 +648,7 @@ void QDumper::putEllipsis()
     P(dumper, "value", value); \
     P(dumper, "type", NS"QString"); \
     P(dumper, "numchild", "0"); \
-    P(dumper, "valueencoded", "1"); \
+    P(dumper, "valueencoded", "2"); \
     dumper.endHash();
 
 // simple integer property
@@ -680,7 +679,7 @@ void QDumper::putEllipsis()
     P(dumper, "name", name); \
     P(dumper, "value", QString(QLatin1String("'%1' (%2, 0x%3)")) \
         .arg(value).arg(value.unicode()).arg(value.unicode(), 0, 16)); \
-    P(dumper, "valueencoded", "1"); \
+    P(dumper, "valueencoded", "2"); \
     P(dumper, "type", NS"QChar"); \
     P(dumper, "numchild", "0"); \
     dumper.endHash();
@@ -755,7 +754,7 @@ static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr
                     const QObject *ob = reinterpret_cast<const QObject *>(addr);
                     P(d, "addr", ob);
                     P(d, "value", ob->objectName());
-                    P(d, "valueencoded", "1");
+                    P(d, "valueencoded", "2");
                     P(d, "type", NS"QObject");
                     P(d, "displayedtype", ob->metaObject()->className());
                 } else {
@@ -767,7 +766,7 @@ static void qDumpInnerValueHelper(QDumper &d, const char *type, const void *addr
         case 'S':
             if (isEqual(type, "QString")) {
                 d.addCommaIfNeeded();
-                d << field << "encoded=\"1\",";
+                d << field << "encoded=\"2\",";
                 P(d, field, *(QString*)addr);
             }
             return;
@@ -857,7 +856,7 @@ static void qDumpQDateTime(QDumper &d)
         P(d, "value", "(null)");
     } else {
         P(d, "value", date.toString());
-        P(d, "valueencoded", "1");
+        P(d, "valueencoded", "2");
     }
     P(d, "type", NS"QDateTime");
     P(d, "numchild", "3");
@@ -901,7 +900,7 @@ static void qDumpQDir(QDumper &d)
 {
     const QDir &dir = *reinterpret_cast<const QDir *>(d.data);
     P(d, "value", dir.path());
-    P(d, "valueencoded", "1");
+    P(d, "valueencoded", "2");
     P(d, "type", NS"QDir");
     P(d, "numchild", "3");
     if (d.dumpChildren) {
@@ -917,7 +916,7 @@ static void qDumpQFile(QDumper &d)
 {
     const QFile &file = *reinterpret_cast<const QFile *>(d.data);
     P(d, "value", file.fileName());
-    P(d, "valueencoded", "1");
+    P(d, "valueencoded", "2");
     P(d, "type", NS"QFile");
     P(d, "numchild", "2");
     if (d.dumpChildren) {
@@ -933,7 +932,7 @@ static void qDumpQFileInfo(QDumper &d)
 {
     const QFileInfo &info = *reinterpret_cast<const QFileInfo *>(d.data);
     P(d, "value", info.filePath());
-    P(d, "valueencoded", "1");
+    P(d, "valueencoded", "2");
     P(d, "type", NS"QFileInfo");
     P(d, "numchild", "3");
     if (d.dumpChildren) {
@@ -980,7 +979,7 @@ static void qDumpQFileInfo(QDumper &d)
         d.beginHash();
         P(d, "name", "created");
         P(d, "value", info.created().toString());
-        P(d, "valueencoded", "1");
+        P(d, "valueencoded", "2");
         P(d, "exp", "(("NSX"QFileInfo"NSY"*)" << d.data << ")->created()");
         P(d, "type", NS"QDateTime");
         P(d, "numchild", "1");
@@ -989,7 +988,7 @@ static void qDumpQFileInfo(QDumper &d)
         d.beginHash();
         P(d, "name", "lastModified");
         P(d, "value", info.lastModified().toString());
-        P(d, "valueencoded", "1");
+        P(d, "valueencoded", "2");
         P(d, "exp", "(("NSX"QFileInfo"NSY"*)" << d.data << ")->lastModified()");
         P(d, "type", NS"QDateTime");
         P(d, "numchild", "1");
@@ -998,7 +997,7 @@ static void qDumpQFileInfo(QDumper &d)
         d.beginHash();
         P(d, "name", "lastRead");
         P(d, "value", info.lastRead().toString());
-        P(d, "valueencoded", "1");
+        P(d, "valueencoded", "2");
         P(d, "exp", "(("NSX"QFileInfo"NSY"*)" << d.data << ")->lastRead()");
         P(d, "type", NS"QDateTime");
         P(d, "numchild", "1");
@@ -1296,7 +1295,7 @@ static void qDumpQLocale(QDumper &d)
 {
     const QLocale &locale = *reinterpret_cast<const QLocale *>(d.data);
     P(d, "value", locale.name());
-    P(d, "valueencoded", "1");
+    P(d, "valueencoded", "2");
     P(d, "type", NS"QLocale");
     P(d, "numchild", "8");
     if (d.dumpChildren) {
@@ -1508,7 +1507,7 @@ static void qDumpQObject(QDumper &d)
     const QMetaObject *mo = ob->metaObject();
     unsigned childrenOffset = d.extraInt[0];
     P(d, "value", ob->objectName());
-    P(d, "valueencoded", "1");
+    P(d, "valueencoded", "2");
     P(d, "type", NS"QObject");
     P(d, "displayedtype", mo->className());
     P(d, "numchild", 4);
@@ -1627,7 +1626,7 @@ static void qDumpQObjectPropertyList(QDumper &d)
                         << ")->" << prop.name() << "()");
             if (isEqual(prop.typeName(), "QString")) {
                 P(d, "value", prop.read(ob).toString());
-                P(d, "valueencoded", "1");
+                P(d, "valueencoded", "2");
                 P(d, "type", NS"QString");
                 P(d, "numchild", "0");
             } else if (isEqual(prop.typeName(), "bool")) {
@@ -1941,7 +1940,7 @@ static void qDumpQString(QDumper &d)
     }
 
     P(d, "value", str);
-    P(d, "valueencoded", "1");
+    P(d, "valueencoded", "2");
     P(d, "type", NS"QString");
     //P(d, "editvalue", str);  // handled generically below
     P(d, "numchild", "0");
@@ -1973,7 +1972,7 @@ static void qDumpQStringList(QDumper &d)
             d.beginHash();
             P(d, "name", i);
             P(d, "value", list[i]);
-            P(d, "valueencoded", "1");
+            P(d, "valueencoded", "2");
             d.endHash();
         }
         if (n < list.size())
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 2bdaa6445f632d134fcb720235b83d1f80c18d61..9a9dd71ec3cbcf49652f243a47acf90398f7ffdc 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -508,6 +508,9 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
     return start;
 }
 
+bool CppCodeCompletion::isValid(TextEditor::ITextEditable *editor)
+{ return m_manager->isCppEditor(editor); }
+
 bool CppCodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor)
 {
     if (! m_manager->isCppEditor(editor)) // ### remove me
diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h
index c37e09ea03e2ad5d22c9540e175de66411fc7d49..174e5d994f4fa4163f864795522be72e841171ee 100644
--- a/src/plugins/cpptools/cppcodecompletion.h
+++ b/src/plugins/cpptools/cppcodecompletion.h
@@ -58,6 +58,7 @@ class CppCodeCompletion : public TextEditor::ICompletionCollector
 public:
     explicit CppCodeCompletion(CppModelManager *manager);
 
+    bool isValid(TextEditor::ITextEditable *editor);
     bool triggersCompletion(TextEditor::ITextEditable *editor);
     int startCompletion(TextEditor::ITextEditable *editor);
     void completions(QList<TextEditor::CompletionItem> *completions);
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index 6ea9da6d1c72f8a131b6b675faeb04f729eaece0..078692f7312f4af48f00b1dabceb8b0e3aaa9639 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -1056,7 +1056,8 @@ void DebuggerManager::sessionLoaded()
 void DebuggerManager::sessionUnloaded()
 {
     return;
-    cleanupViews();
+    //FIXME: Breakview crashes on startup as there is 
+    //cleanupViews();
     if (m_engine)
         m_engine->shutdown();
     setStatus(DebuggerProcessNotReady);
diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index 17cb99081acaae01620b9ad178dbca6359bc012c..b53bee9607335799f2abbc75023170496b5bf4af 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -65,6 +65,7 @@
 #include <unistd.h>
 #include <dlfcn.h>
 #endif
+#include <ctype.h>
 
 using namespace Debugger;
 using namespace Debugger::Internal;
@@ -2776,36 +2777,55 @@ void GdbEngine::setToolTipExpression(const QPoint &pos, const QString &exp0)
 
 static const QString strNotInScope = QLatin1String("<not in scope>");
 
+static QString quoteUnprintableLatin1(const QByteArray &ba)
+{
+    QString res;
+    char buf[10];
+    for (int i = 0, n = ba.size(); i != n; ++i) {
+        unsigned char c = ba.at(i);
+        if (isprint(c)) {
+            res += c;
+        } else {
+            qsnprintf(buf, sizeof(buf) - 1, "\\%x", int(c));
+            res += buf;
+        }
+    }
+    return res;
+}
+
 static void setWatchDataValue(WatchData &data, const GdbMi &mi,
     int encoding = 0)
 {
     if (mi.isValid()) {
         QByteArray ba;
+        QString str;
         switch (encoding) {
             case 0: // unencoded 8 bit data
                 ba = mi.data();
+                str = quoteUnprintableLatin1(ba);
                 break;
-            case 1: //  base64 encoded 8 bit data
+            case 1: //  base64 encoded 8 bit data, used for QByteArray
                 ba = QByteArray::fromBase64(mi.data());
-                ba = '"' + ba + '"';
+                str = '"' + quoteUnprintableLatin1(ba) + '"';
                 break;
-            case 2: //  base64 encoded 16 bit data
+            case 2: //  base64 encoded 16 bit data, used for QString
                 ba = QByteArray::fromBase64(mi.data());
-                ba = QString::fromUtf16((ushort *)ba.data(), ba.size() / 2).toUtf8();
-                ba = '"' + ba + '"';
+                str = QString::fromUtf16((ushort *)ba.data(), ba.size() / 2);
+                str = '"' + str + '"';
                 break;
             case 3: //  base64 encoded 32 bit data
                 ba = QByteArray::fromBase64(mi.data());
-                ba = QString::fromUcs4((uint *)ba.data(), ba.size() / 4).toUtf8();
-                ba = '"' + ba + '"';
+                str = QString::fromUcs4((uint *)ba.data(), ba.size() / 4);
+                str = '"' + str + '"';
                 break;
-            case 4: //  base64 encoded 8 bit data 
+            case 4: //  base64 encoded 16 bit data, without quotes (see 2)
                 ba = QByteArray::fromBase64(mi.data());
+                str = QString::fromUtf16((ushort *)ba.data(), ba.size() / 2);
                 break;
         }
-       data.setValue(ba);
+        data.setValue(str);
     } else {
-       data.setValueNeeded();
+        data.setValueNeeded();
     }
 }
 
@@ -3411,7 +3431,7 @@ void GdbEngine::handleVarCreate(const GdbResultRecord &record,
                 data.setChildrenNeeded();
             setWatchDataChildCount(data, record.data.findChild("numchild"));
             //if (data.isValueNeeded() && data.childCount > 0)
-            //    data.setValue(QByteArray());
+            //    data.setValue(QString());
             insertData(data);
         }
     } else if (record.resultClass == GdbResultError) {
@@ -3607,13 +3627,13 @@ void GdbEngine::handleDumpCustomValue3(const GdbResultRecord &record,
         QString str;
         for (int i = 0; i < list.size(); ++i)
              str.append(list.at(i).toInt());
-        data.setValue('"' + str.toUtf8() + '"');
+        data.setValue('"' + str + '"');
         data.setChildCount(0);
         data.setAllUnneeded();
         insertData(data);
     } else if (data.type == "QStringList" || data.type.endsWith("::QStringList")) {
         int l = list.size();
-        data.setValue(QString("<%1 items>").arg(l).toLatin1());
+        data.setValue(tr("<%1 items>").arg(l));
         data.setChildCount(list.size());
         data.setAllUnneeded();
         insertData(data);
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 9458bac9f3800aeb69efa9cbed9502e300230f8b..af120e3a18ca8c47bc9e5379ce1715f34f25f5b7 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -47,9 +47,9 @@
 #include <QtGui/QToolTip>
 #include <QtGui/QTextEdit>
 
-
 #include <ctype.h>
 
+
 // creates debug output regarding pending watch data results
 #define DEBUG_PENDING 1
 // creates debug output for accesses to the itemmodel
@@ -91,25 +91,9 @@ void WatchData::setError(const QString &msg)
     valuedisabled = true;
 }
 
-static QByteArray quoteUnprintable(const QByteArray &ba)
-{
-    QByteArray res;
-    char buf[10];
-    for (int i = 0, n = ba.size(); i != n; ++i) {
-        unsigned char c = ba.at(i);
-        if (isprint(c)) {
-            res += c;
-        } else {
-            qsnprintf(buf, sizeof(buf) - 1, "\\%x", int(c));
-            res += buf;
-        }
-    }
-    return res;
-}
-
-void WatchData::setValue(const QByteArray &value0)
+void WatchData::setValue(const QString &value0)
 {
-    value = quoteUnprintable(value0);
+    value = value0;
     if (value == "{...}") {
         value.clear();
         childCount = 1; // at least one...
diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h
index a31c8f0caec7675fe2085427a26a675df827103e..ba6bb64dd1b646c32d1b618331d622523ea16bd7 100644
--- a/src/plugins/debugger/watchhandler.h
+++ b/src/plugins/debugger/watchhandler.h
@@ -66,7 +66,7 @@ public:
             | ChildCountNeeded
     };
 
-    void setValue(const QByteArray &);
+    void setValue(const QString &);
     void setType(const QString &);
     void setValueToolTip(const QString &);
     void setError(const QString &);
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index e2d777e8c4508e9a6a5d8b1dfee73a5db52b3195..34c0080ca099c8140debccff7138c663da17f3d4 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -1247,6 +1247,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
                 m_tc.insertText(text);
                 moveUp(n);
             }
+            moveToFirstNonBlankOnLine();
         } else {
             m_desiredColumn = 0;
             for (int i = count(); --i >= 0; ) {
diff --git a/src/plugins/projectexplorer/winguiprocess.cpp b/src/plugins/projectexplorer/winguiprocess.cpp
index 75efc7cb7364c558e86c39f2ee1c5fd6bebeb8ba..5085978175311cfc5a5f89d82a6307aa9a4a72a7 100644
--- a/src/plugins/projectexplorer/winguiprocess.cpp
+++ b/src/plugins/projectexplorer/winguiprocess.cpp
@@ -147,7 +147,7 @@ void WinGuiProcess::run()
             switch (ret) {
             case WAIT_OBJECT_0 + 0:
                 if (*processId == m_pid->dwProcessId)
-                    emit receivedDebugOutput(QString::fromAscii(message));
+                    emit receivedDebugOutput(QString::fromLocal8Bit(message));
                 SetEvent(bufferReadyEvent);
                 break;
             case WAIT_OBJECT_0 + 1:
diff --git a/src/plugins/qtscripteditor/parser/javascript.g b/src/plugins/qtscripteditor/parser/javascript.g
index f762498ee4c60cd19f3f2edd9e950735be84e791..80dfaddcad47229393aa98547e152568b8a3897f 100644
--- a/src/plugins/qtscripteditor/parser/javascript.g
+++ b/src/plugins/qtscripteditor/parser/javascript.g
@@ -2179,7 +2179,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ;
             }
         }
 
-        const QString msg = QString::fromUtf8("Unexpected token: `%1'").arg(token_buffer[0].token);
+        const QString msg = QString::fromUtf8("Unexpected token: `%1'").arg(spell[token_buffer[0].token]);
         diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error,
             token_buffer[0].loc.startLine, token_buffer[0].loc.startColumn, msg));
     }
diff --git a/src/plugins/qtscripteditor/parser/javascriptengine_p.h b/src/plugins/qtscripteditor/parser/javascriptengine_p.h
index 7bcbf1f3cc6a0a1017331554ca25a55e1bd58a31..480ef042a70595818773e7fdc271645b3cdcc592 100644
--- a/src/plugins/qtscripteditor/parser/javascriptengine_p.h
+++ b/src/plugins/qtscripteditor/parser/javascriptengine_p.h
@@ -77,6 +77,9 @@ public:
     : _lexer(0), _nodePool(0), _ast(0)
   { }
 
+  QSet<JavaScriptNameIdImpl> literals() const
+  { return _literals; }
+
   JavaScriptNameIdImpl *intern(const QChar *u, int s)
   { return const_cast<JavaScriptNameIdImpl *>(&*_literals.insert(JavaScriptNameIdImpl(u, s))); }
 
diff --git a/src/plugins/qtscripteditor/parser/javascriptparser.cpp b/src/plugins/qtscripteditor/parser/javascriptparser.cpp
index 794c416b763c8f3aeca13a92420df57a22c8b7ae..ac8eabf09548eed7b35f30958996d69b6c0bf8cc 100644
--- a/src/plugins/qtscripteditor/parser/javascriptparser.cpp
+++ b/src/plugins/qtscripteditor/parser/javascriptparser.cpp
@@ -1184,7 +1184,7 @@ case 266: {
             }
         }
 
-        const QString msg = QString::fromUtf8("Unexpected token: `%1'").arg(token_buffer[0].token);
+        const QString msg = QString::fromUtf8("Unexpected token: `%1'").arg(spell[token_buffer[0].token]);
         diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error,
             token_buffer[0].loc.startLine, token_buffer[0].loc.startColumn, msg));
     }
diff --git a/src/plugins/qtscripteditor/qtscriptcodecompletion.cpp b/src/plugins/qtscripteditor/qtscriptcodecompletion.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d08a3e175ef0a7d15d489fcb86f52d5ba505d5b9
--- /dev/null
+++ b/src/plugins/qtscripteditor/qtscriptcodecompletion.cpp
@@ -0,0 +1,151 @@
+
+#include "qtscriptcodecompletion.h"
+#include "qtscripteditor.h"
+#include <texteditor/basetexteditor.h>
+#include <QtDebug>
+
+using namespace QtScriptEditor::Internal;
+
+QtScriptCodeCompletion::QtScriptCodeCompletion(QObject *parent)
+    : TextEditor::ICompletionCollector(parent),
+      m_editor(0),
+      m_startPosition(0),
+      m_caseSensitivity(Qt::CaseSensitive)
+{ }
+
+QtScriptCodeCompletion::~QtScriptCodeCompletion()
+{ }
+
+Qt::CaseSensitivity QtScriptCodeCompletion::caseSensitivity() const
+{ return m_caseSensitivity; }
+
+void QtScriptCodeCompletion::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity)
+{ m_caseSensitivity = caseSensitivity; }
+
+bool QtScriptCodeCompletion::isValid(TextEditor::ITextEditable *editor)
+{
+    if (qobject_cast<ScriptEditor *>(editor->widget()))
+        return true;
+
+    return false;
+}
+
+bool QtScriptCodeCompletion::triggersCompletion(TextEditor::ITextEditable *)
+{ return false; }
+
+int QtScriptCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
+{
+    m_editor = editor;
+
+    ScriptEditor *edit = qobject_cast<ScriptEditor *>(m_editor->widget());
+    if (! edit)
+        return -1;
+
+    int pos = editor->position();
+
+    while (editor->characterAt(pos - 1).isLetterOrNumber() || editor->characterAt(pos - 1) == QLatin1Char('_'))
+        --pos;
+
+    m_startPosition = pos;
+    m_completions.clear();
+
+    foreach (const QString &word, edit->words()) {
+        TextEditor::CompletionItem item(this);
+        item.m_text = word;
+        m_completions.append(item);
+    }
+
+    return pos;
+}
+
+void QtScriptCodeCompletion::completions(QList<TextEditor::CompletionItem> *completions)
+{
+    // ### FIXME: this code needs to be generalized.
+
+    const int length = m_editor->position() - m_startPosition;
+
+    if (length == 0)
+        *completions = m_completions;
+    else if (length > 0) {
+        const QString key = m_editor->textAt(m_startPosition, length);
+
+        /*
+         * This code builds a regular expression in order to more intelligently match
+         * camel-case style. This means upper-case characters will be rewritten as follows:
+         *
+         *   A => [a-z0-9_]*A (for any but the first capital letter)
+         *
+         * Meaning it allows any sequence of lower-case characters to preceed an
+         * upper-case character. So for example gAC matches getActionController.
+         */
+        QString keyRegExp;
+        keyRegExp += QLatin1Char('^');
+        bool first = true;
+        foreach (const QChar &c, key) {
+            if (c.isUpper() && !first) {
+                keyRegExp += QLatin1String("[a-z0-9_]*");
+                keyRegExp += c;
+            } else if (m_caseSensitivity == Qt::CaseInsensitive && c.isLower()) {
+                keyRegExp += QLatin1Char('[');
+                keyRegExp += c;
+                keyRegExp += c.toUpper();
+                keyRegExp += QLatin1Char(']');
+            } else {
+                keyRegExp += QRegExp::escape(c);
+            }
+            first = false;
+        }
+        const QRegExp regExp(keyRegExp, Qt::CaseSensitive);
+
+        foreach (TextEditor::CompletionItem item, m_completions) {
+            if (regExp.indexIn(item.m_text) == 0) {
+                item.m_relevance = (key.length() > 0 &&
+                                    item.m_text.startsWith(key, Qt::CaseInsensitive)) ? 1 : 0;
+                (*completions) << item;
+            }
+        }
+    }
+}
+
+void QtScriptCodeCompletion::complete(const TextEditor::CompletionItem &item)
+{
+    const QString toInsert = item.m_text;
+    const int length = m_editor->position() - m_startPosition;
+    m_editor->setCurPos(m_startPosition);
+    m_editor->replace(length, toInsert);
+}
+
+bool QtScriptCodeCompletion::partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems)
+{
+    if (completionItems.count() == 1) {
+        complete(completionItems.first());
+        return true;
+    } else {
+        // Compute common prefix
+        QString firstKey = completionItems.first().m_text;
+        QString lastKey = completionItems.last().m_text;
+        const int length = qMin(firstKey.length(), lastKey.length());
+        firstKey.truncate(length);
+        lastKey.truncate(length);
+
+        while (firstKey != lastKey) {
+            firstKey.chop(1);
+            lastKey.chop(1);
+        }
+
+        int typedLength = m_editor->position() - m_startPosition;
+        if (!firstKey.isEmpty() && firstKey.length() > typedLength) {
+            m_editor->setCurPos(m_startPosition);
+            m_editor->replace(typedLength, firstKey);
+        }
+    }
+    return false;
+}
+
+void QtScriptCodeCompletion::cleanup()
+{
+    m_editor = 0;
+    m_startPosition = 0;
+    m_completions.clear();
+}
+
diff --git a/src/plugins/qtscripteditor/qtscriptcodecompletion.h b/src/plugins/qtscripteditor/qtscriptcodecompletion.h
new file mode 100644
index 0000000000000000000000000000000000000000..a0650d5266ae07d80427e068aa2d000f31d6cbd4
--- /dev/null
+++ b/src/plugins/qtscripteditor/qtscriptcodecompletion.h
@@ -0,0 +1,43 @@
+#ifndef QTSCRIPTCODECOMPLETION_H
+#define QTSCRIPTCODECOMPLETION_H
+
+#include <texteditor/icompletioncollector.h>
+
+namespace TextEditor {
+class ITextEditable;
+}
+
+namespace QtScriptEditor {
+namespace Internal {
+
+class QtScriptCodeCompletion: public TextEditor::ICompletionCollector
+{
+    Q_OBJECT
+
+public:
+    QtScriptCodeCompletion(QObject *parent = 0);
+    virtual ~QtScriptCodeCompletion();
+
+    Qt::CaseSensitivity caseSensitivity() const;
+    void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity);
+
+    virtual bool isValid(TextEditor::ITextEditable *editor);
+    virtual bool triggersCompletion(TextEditor::ITextEditable *editor);
+    virtual int startCompletion(TextEditor::ITextEditable *editor);
+    virtual void completions(QList<TextEditor::CompletionItem> *completions);
+    virtual void complete(const TextEditor::CompletionItem &item);
+    virtual bool partiallyComplete(const QList<TextEditor::CompletionItem> &completionItems);
+    virtual void cleanup();
+
+private:
+    TextEditor::ITextEditable *m_editor;
+    int m_startPosition;
+    QList<TextEditor::CompletionItem> m_completions;
+    Qt::CaseSensitivity m_caseSensitivity;
+};
+
+
+} // end of namespace Internal
+} // end of namespace QtScriptEditor
+
+#endif // QTSCRIPTCODECOMPLETION_H
diff --git a/src/plugins/qtscripteditor/qtscripteditor.cpp b/src/plugins/qtscripteditor/qtscripteditor.cpp
index 916567797ed99ce1da9046d560d103eb6caf40d0..14e77fb40edd9a6208ffec3f3377fb817e713b6e 100644
--- a/src/plugins/qtscripteditor/qtscripteditor.cpp
+++ b/src/plugins/qtscripteditor/qtscripteditor.cpp
@@ -166,6 +166,9 @@ ScriptEditor::~ScriptEditor()
 QList<Declaration> ScriptEditor::declarations() const
 { return m_declarations; }
 
+QStringList ScriptEditor::words() const
+{ return m_words; }
+
 Core::IEditor *ScriptEditorEditable::duplicate(QWidget *parent)
 {
     ScriptEditor *newEditor = new ScriptEditor(m_context, parent);
@@ -215,6 +218,10 @@ void ScriptEditor::updateDocumentNow()
         FindDeclarations decls;
         m_declarations = decls.accept(driver.ast());
 
+        m_words.clear();
+        foreach (const JavaScriptNameIdImpl &id, driver.literals())
+            m_words.append(id.asString());
+
         QStringList items;
         items.append(tr("<Select Symbol>"));
 
diff --git a/src/plugins/qtscripteditor/qtscripteditor.h b/src/plugins/qtscripteditor/qtscripteditor.h
index dc6aa364b1178abedef299695a670c07c4da64b9..8042185796b71e59de102e1fd8d2e50c7873623c 100644
--- a/src/plugins/qtscripteditor/qtscripteditor.h
+++ b/src/plugins/qtscripteditor/qtscripteditor.h
@@ -91,6 +91,7 @@ public:
     ~ScriptEditor();
 
     QList<Declaration> declarations() const;
+    QStringList words() const;
 
 public slots:
     virtual void setFontSettings(const TextEditor::FontSettings &);
@@ -117,6 +118,7 @@ private:
     QTimer *m_updateDocumentTimer;
     QComboBox *m_methodCombo;
     QList<Declaration> m_declarations;
+    QStringList m_words;
 };
 
 } // namespace Internal
diff --git a/src/plugins/qtscripteditor/qtscripteditor.pro b/src/plugins/qtscripteditor/qtscripteditor.pro
index 125b97e26c90d42798a5d20ba3631163c133c643..357e52df93d0e71b3799e832c510362259499a71 100644
--- a/src/plugins/qtscripteditor/qtscripteditor.pro
+++ b/src/plugins/qtscripteditor/qtscripteditor.pro
@@ -13,12 +13,14 @@ HEADERS += qtscripteditor.h \
 qtscripteditorfactory.h \
 qtscripteditorplugin.h \
 qtscripthighlighter.h \
-qtscripteditoractionhandler.h
+qtscripteditoractionhandler.h \
+qtscriptcodecompletion.h
 
 SOURCES += qtscripteditor.cpp \
 qtscripteditorfactory.cpp \
 qtscripteditorplugin.cpp \
 qtscripthighlighter.cpp \
-qtscripteditoractionhandler.cpp
+qtscripteditoractionhandler.cpp \
+qtscriptcodecompletion.cpp
 
 RESOURCES += qtscripteditor.qrc
diff --git a/src/plugins/qtscripteditor/qtscripteditorplugin.cpp b/src/plugins/qtscripteditor/qtscripteditorplugin.cpp
index b13ed76b8984ca92aa6cf7f6d1de4b99500c5ad2..eadf2711ea8c691abc5138d79318e1e223c30b96 100644
--- a/src/plugins/qtscripteditor/qtscripteditorplugin.cpp
+++ b/src/plugins/qtscripteditor/qtscripteditorplugin.cpp
@@ -33,6 +33,7 @@
 #include "qtscripteditor.h"
 #include "qtscripteditorconstants.h"
 #include "qtscripteditorfactory.h"
+#include "qtscriptcodecompletion.h"
 
 #include <coreplugin/icore.h>
 #include <coreplugin/coreconstants.h>
@@ -46,10 +47,12 @@
 #include <texteditor/texteditorsettings.h>
 #include <texteditor/textfilewizard.h>
 #include <texteditor/texteditoractionhandler.h>
+#include <texteditor/completionsupport.h>
 #include <utils/qtcassert.h>
 
 #include <QtCore/QtPlugin>
 #include <QtCore/QDebug>
+#include <QtCore/QSettings>
 #include <QtGui/QAction>
 
 using namespace QtScriptEditor::Internal;
@@ -60,7 +63,8 @@ QtScriptEditorPlugin *QtScriptEditorPlugin::m_instance = 0;
 QtScriptEditorPlugin::QtScriptEditorPlugin() :
     m_wizard(0),
     m_editor(0),
-    m_actionHandler(0)
+    m_actionHandler(0),
+    m_completion(0)
 {
     m_instance = this;
 }
@@ -105,6 +109,18 @@ bool QtScriptEditorPlugin::initialize(const QStringList & /*arguments*/, QString
         | TextEditor::TextEditorActionHandler::UnCommentSelection
         | TextEditor::TextEditorActionHandler::UnCollapseAll);
 
+    m_completion = new QtScriptCodeCompletion();
+    addAutoReleasedObject(m_completion);
+
+    // Restore settings
+    QSettings *settings = Core::ICore::instance()->settings();
+    settings->beginGroup(QLatin1String("CppTools")); // ### FIXME:
+    settings->beginGroup(QLatin1String("Completion"));
+    const bool caseSensitive = settings->value(QLatin1String("CaseSensitive"), true).toBool();
+    m_completion->setCaseSensitivity(caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
+    settings->endGroup();
+    settings->endGroup();
+    
     error_message->clear();
 
     return true;
@@ -122,6 +138,10 @@ void QtScriptEditorPlugin::initializeEditor(QtScriptEditor::Internal::ScriptEdit
     m_actionHandler->setupActions(editor);
 
     TextEditor::TextEditorSettings::instance()->initializeEditor(editor);
+
+    // auto completion
+    connect(editor, SIGNAL(requestAutoCompletion(ITextEditable*, bool)),
+            TextEditor::Internal::CompletionSupport::instance(), SLOT(autoComplete(ITextEditable*, bool)));
 }
 
 void QtScriptEditorPlugin::registerActions()
diff --git a/src/plugins/qtscripteditor/qtscripteditorplugin.h b/src/plugins/qtscripteditor/qtscripteditorplugin.h
index e43bb21c8a264807ca0d19161a788636ec6027be..4c1debb9fa11d7b36c9da4763331b2e9443607da 100644
--- a/src/plugins/qtscripteditor/qtscripteditorplugin.h
+++ b/src/plugins/qtscripteditor/qtscripteditorplugin.h
@@ -41,6 +41,7 @@ namespace QtScriptEditor {
 namespace Internal {
 
 class QtScriptEditorFactory;
+class QtScriptCodeCompletion;
 class ScriptEditor;
 
 class QtScriptEditorPlugin : public ExtensionSystem::IPlugin
@@ -72,6 +73,7 @@ private:
     TextEditor::TextFileWizard *m_wizard;
     QtScriptEditorFactory *m_editor;
     TextEditor::TextEditorActionHandler *m_actionHandler;
+    QtScriptCodeCompletion *m_completion;
 };
 
 } // namespace Internal
diff --git a/src/plugins/texteditor/completionsupport.cpp b/src/plugins/texteditor/completionsupport.cpp
index 2e456193ad52f2af57952a6667f6e3a63f885ea7..ef4834c80883dc2fa35bec9a1e74d14d6c1bdddc 100644
--- a/src/plugins/texteditor/completionsupport.cpp
+++ b/src/plugins/texteditor/completionsupport.cpp
@@ -58,10 +58,11 @@ CompletionSupport::CompletionSupport()
       m_completionList(0),
       m_startPosition(0),
       m_checkCompletionTrigger(false),
-      m_editor(0)
+      m_editor(0),
+      m_completionCollector(0)
 {
-    m_completionCollector = ExtensionSystem::PluginManager::instance()
-        ->getObject<ICompletionCollector>();
+    m_completionCollectors = ExtensionSystem::PluginManager::instance()
+        ->getObjects<ICompletionCollector>();
 }
 
 void CompletionSupport::performCompletion(const CompletionItem &item)
@@ -90,6 +91,15 @@ void CompletionSupport::cleanupCompletions()
 
 void CompletionSupport::autoComplete(ITextEditable *editor, bool forced)
 {
+    m_completionCollector = 0;
+
+    foreach (ICompletionCollector *collector, m_completionCollectors) {
+        if (collector->isValid(editor)) {
+            m_completionCollector = collector;
+            break;
+        }
+    }
+
     if (!m_completionCollector)
         return;
 
diff --git a/src/plugins/texteditor/completionsupport.h b/src/plugins/texteditor/completionsupport.h
index 7cbd5ece5b424a1951a3f08c9ef5700c84c38208..ebe9cbd70f3aeda30838eb540f867c2a1e28f06f 100644
--- a/src/plugins/texteditor/completionsupport.h
+++ b/src/plugins/texteditor/completionsupport.h
@@ -69,6 +69,7 @@ private:
     int m_startPosition;
     bool m_checkCompletionTrigger;          // Whether to check for completion trigger after cleanup
     ITextEditable *m_editor;
+    QList<ICompletionCollector *> m_completionCollectors;
     ICompletionCollector *m_completionCollector;
 };
 
diff --git a/src/plugins/texteditor/icompletioncollector.h b/src/plugins/texteditor/icompletioncollector.h
index 49d70f182883b2302cd16c1203b2216b3a39d749..a151e4cf41fd7d2451a3f18d65440ea23e1663f6 100644
--- a/src/plugins/texteditor/icompletioncollector.h
+++ b/src/plugins/texteditor/icompletioncollector.h
@@ -77,6 +77,11 @@ public:
     ICompletionCollector(QObject *parent = 0) : QObject(parent) {}
     virtual ~ICompletionCollector() {}
 
+    /*
+     * Returns true if this completion collector can be used with the given editor.
+     */
+    virtual bool isValid(ITextEditable *editor) = 0;
+
     /* This method should return whether the cursor is at a position which could
      * trigger an autocomplete. It will be called each time a character is typed in
      * the text editor.
diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp
index 141c7b547396283d785e298e0434d3c899e343bf..666d4c9a7085d25dc82e401edf2319beb71d6c7a 100644
--- a/tests/manual/gdbdebugger/simple/app.cpp
+++ b/tests/manual/gdbdebugger/simple/app.cpp
@@ -416,7 +416,8 @@ void testQObject(int &argc, char *argv[])
     obs.append(&app);
     ob1.setObjectName("A Subobject");
 */
-    QLabel l("XXXXXXXXXXXXXXXXX");
+    QString str = QString::fromUtf8("XXXXXXXXXXXXXXyyXXX ö");
+    QLabel l(str);
     l.show();
     app.exec();
 }
@@ -998,6 +999,7 @@ int main(int argc, char *argv[])
     testIO();
     testHidden();
     testArray();
+    testQByteArray();
 
     testStdDeque();
     testStdList();
@@ -1012,7 +1014,6 @@ int main(int argc, char *argv[])
     testQLinkedList();
     testNamespace();
     //return 0;
-    testQByteArray();
     testQHash();
     testQImage();
     testQMap();