From 47995286b5767b47f36840e84ab958c855e2171e Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Thu, 2 Apr 2009 10:54:22 +0200
Subject: [PATCH] debugger: show non-ASCII in QString, too

---
 share/qtcreator/gdbmacros/gdbmacros.cpp  | 35 +++++++++---------
 src/plugins/debugger/debuggermanager.cpp |  3 +-
 src/plugins/debugger/gdbengine.cpp       | 45 +++++++++++++++++-------
 src/plugins/debugger/watchhandler.cpp    | 20 ++---------
 src/plugins/debugger/watchhandler.h      |  2 +-
 tests/manual/gdbdebugger/simple/app.cpp  |  5 +--
 6 files changed, 57 insertions(+), 53 deletions(-)

diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp
index 1bf515f92e5..80ab420c5fa 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/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index 6ea9da6d1c7..078692f7312 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 17cb99081ac..1cf006f496d 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -2776,36 +2776,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 +3430,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 +3626,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 9458bac9f38..06600b560ca 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -91,25 +91,9 @@ void WatchData::setError(const QString &msg)
     valuedisabled = true;
 }
 
-static QByteArray quoteUnprintable(const QByteArray &ba)
+void WatchData::setValue(const QString &value0)
 {
-    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)
-{
-    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 a31c8f0caec..ba6bb64dd1b 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/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp
index 141c7b54739..666d4c9a708 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();
-- 
GitLab