Index: kasten/controllers/view/structures/parsers/osdparser.cpp
===================================================================
--- kasten/controllers/view/structures/parsers/osdparser.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/parsers/osdparser.cpp	(working copy)
@@ -24,6 +24,7 @@
 
 #include "../datatypes/array/arraydatainformation.h"
 #include "../datatypes/uniondatainformation.h"
+#include "../datatypes/pointerdatainformation.h"
 #include "../datatypes/structuredatainformation.h"
 #include "../datatypes/primitive/enumdatainformation.h"
 #include "../datatypes/primitive/flagdatainformation.h"
@@ -200,6 +201,7 @@
         info.enums = parseEnums(rootElem, logger);
         info.logger = logger;
         info.parent = 0;
+        info.delayed = new QQueue<QPair<PointerDataInformation*, QDomNode> >();
         DataInformation* data = parseNode(elem, info);
 
         if (!data)
@@ -208,6 +210,16 @@
             data = new DummyDataInformation(0,
                     fileInfo.absoluteFilePath() + QLatin1String("_element") + QString::number(i));
         }
+
+        // Parser all pointers after parsing the main structure
+        // This way we can refer to fields which come after the pointer field
+        while (!info.delayed->isEmpty())
+        {
+            QPair<PointerDataInformation*, QDomNode> delayParseInfo = info.delayed->dequeue();
+            delayParse(delayParseInfo.first, delayParseInfo.second, info);
+        }
+        delete info.delayed;
+
         //if we don't need the engine, there is no point in wasting memory for it
         if (!info.scriptEngineNeeded)
         {
@@ -278,13 +290,46 @@
         {
     QString name = xmlElem.attribute(QLatin1String("name"), i18n("<invalid name>"));
     QDomNode node = xmlElem.firstChild();
-    QString lengthStr = xmlElem.attribute(QLatin1String("length"));
+    QString lengthStr;
+
+    // The totallenght attribute indicates the size in bytes
+    // of the array
+    bool isTotalLength = false;
+    if (xmlElem.hasAttribute(QLatin1String("length")))
+    {
+        lengthStr = xmlElem.attribute(QLatin1String("length"));
+    }
+    else if (xmlElem.hasAttribute(QLatin1String("totallength")))
+    {
+        lengthStr = xmlElem.attribute(QLatin1String("totallength"));
+        isTotalLength = true;
+    }
+
     if (lengthStr.isNull())
     {
         info.logger->error() << "No length attribute specified!\n In element "
                 << toRawXML(xmlElem);
         return 0;
     }
+
+    //parse subelement
+    //use dummy until real type has been determined
+    ArrayDataInformation* tmp = new ArrayDataInformation(name, 0,
+            new DummyDataInformation(0, QString()), info.parent);
+    ParserInfo newInfo = info;
+    newInfo.parent = tmp;
+    DataInformation* subElem = parseNode(node, newInfo);
+    delete tmp;
+    if (newInfo.scriptEngineNeeded)
+        info.scriptEngineNeeded = true; //we need it since child needs it
+
+    if (!subElem)
+    {
+        info.logger->error() << "could not parse subelement type of array:" << toRawXML(xmlElem);
+        return 0;
+    }
+    Q_ASSERT(!subElem->isDummy());
+
     QScriptValue updateFunc;
     bool okay = true;
     int length = lengthStr.toInt(&okay, 10);
@@ -297,6 +342,16 @@
                     .arg(QString::number(length), toRawXML(xmlElem));
             return 0;
         }
+
+        // If the total size of the array was specified and we already
+        // know the size of each child then we can compute the number
+        // of elements simply dividing the total size by the size of
+        // a single element
+        if (isTotalLength && subElem->size() != 0)
+        {
+            length /= subElem->size() / 8;
+            isTotalLength = false;
+        }
     }
     else
     {
@@ -304,7 +359,7 @@
         //could not parse as number -> must be a member (dynamic array)
         QString access;
         //we have to find an element that matches the element passed in lengthStr
-        const DataInformation* currElem = info.parent;
+        DataInformation* currElem = info.parent;
         if (!currElem)
         {
             info.logger->error() << "Array with length depending on other"
@@ -333,16 +388,27 @@
         }
         else
         {
+            // Using a placeholder for the array make the search much simpler
+            DummyDataInformation placeholder = DummyDataInformation(currElem);
             QPair<DataInformation*, QString> tmp
-            = currElem->findChildForDynamicArrayLength(lengthStr, currElem->childCount());
+            = placeholder.findChildForDynamicArrayLength(lengthStr, placeholder.childCount());
             if (!tmp.first)
             {
                 info.logger->error().nospace() << "could not find referenced element '"
                         << lengthStr << "'.\nIn element " << toRawXML(xmlElem);
                 return 0;
             }
-            access = tmp.second;
+            access = QString::fromAscii("this.") + tmp.second;
         }
+
+        // If the total size was specified and we already know the size of the
+        // children then we add the division to the script code
+        if (isTotalLength && subElem->size() != 0)
+        {
+            access += QString::fromAscii(" / %1").arg(subElem->size() / 8);
+            isTotalLength = false;
+        }
+
         QString script(QLatin1String("var x = function(mainStruct) { this.length = ")
                 + access + QLatin1String(";};x"));
         updateFunc = info.engine->evaluate(script);
@@ -350,28 +416,56 @@
         Q_ASSERT(updateFunc.isFunction());
         info.scriptEngineNeeded = true;
     }
-    //parse subelement
-    //use dummy until real type has been determined
-    ArrayDataInformation* tmp = new ArrayDataInformation(name, 0,
-            new DummyDataInformation(0, QString()), info.parent);
+
+    ArrayDataInformation* retVal = new ArrayDataInformation(name, length, subElem, info.parent, isTotalLength);
+    if (updateFunc.isValid())
+        retVal->setUpdateFunc(updateFunc);
+
+    return retVal;
+}
+
+PointerDataInformation* OsdParser::pointerFromXML(const QDomElement& xmlElem,
+        ParserInfo& info) const
+        {
+
+    QString name = xmlElem.attribute(QLatin1String("name"), i18n("<invalid name>"));
+    // Allow different size of pointers
+    QString typeStr = xmlElem.attribute(QLatin1String("type"), QString());
+    PrimitiveDataInformation* offset = PrimitiveFactory::newInstance(name, typeStr, info.logger);
+
+    if (typeStr.isEmpty())
+    {
+        info.logger->error() << "No type attribute specified in element:" << toRawXML(xmlElem);
+        return 0;
+    }
+
+    // Create the PointerDataInformation now, but we'll explore it later,
+    // so put it in the queue
+    PointerDataInformation* result = new PointerDataInformation(name, offset, info.parent);
+    info.delayed->enqueue(qMakePair(result, xmlElem.firstChild()));
+    return result;
+}
+
+void OsdParser::delayParse(PointerDataInformation* pointer, const QDomNode& childType,
+        ParserInfo& info) const
+        {
+
+    // Parse subelement
+    // Use dummy until real type has been determined
     ParserInfo newInfo = info;
-    newInfo.parent = tmp;
-    DataInformation* subElem = parseNode(node, newInfo);
-    delete tmp;
+    newInfo.parent = pointer;
+    DataInformation* subElem = parseNode(childType, newInfo);
     if (newInfo.scriptEngineNeeded)
         info.scriptEngineNeeded = true; //we need it since child needs it
 
     if (!subElem)
     {
-        info.logger->error() << "could not parse subelement type of array:" << toRawXML(xmlElem);
-        return 0;
+        info.logger->error() << "could not parse subelement type of pointer:" << childType.nodeName();
+        return;
     }
+
     Q_ASSERT(!subElem->isDummy());
-    ArrayDataInformation* retVal = new ArrayDataInformation(name, length, subElem, info.parent);
-    if (updateFunc.isValid())
-        retVal->setUpdateFunc(updateFunc);
-
-    return retVal;
+    pointer->appendChild(subElem, false);
 }
 
 PrimitiveDataInformation* OsdParser::primitiveFromXML(const QDomElement& xmlElem,
@@ -431,17 +525,15 @@
     QString name = xmlElem.attribute(QLatin1String("name"), i18n("<invalid name>"));
     UnionDataInformation* un = new UnionDataInformation(name, info.parent);
     QDomNode node = xmlElem.firstChild();
-    QVector<DataInformation*> children;
     ParserInfo newInfo = info;
     newInfo.parent = un;
     while (!node.isNull())
     {
         DataInformation* data = parseNode(node, newInfo);
         if (data)
-            children.append(data);
+            un->appendChild(data, false);
         node = node.nextSibling();
     }
-    un->setInitialChildren(children);
     if (newInfo.scriptEngineNeeded)
         info.scriptEngineNeeded = true;
     return un;
@@ -453,17 +545,15 @@
     QString name = xmlElem.attribute(QLatin1String("name"), i18n("<invalid name>"));
     StructureDataInformation* stru = new StructureDataInformation(name, info.parent);
     QDomNode node = xmlElem.firstChild();
-    QVector<DataInformation*> children;
     ParserInfo newInfo = info;
     newInfo.parent = stru;
     while (!node.isNull())
     {
         DataInformation* data = parseNode(node, newInfo);
         if (data)
-            children.append(data);
+            stru->appendChild(data, false);
         node = node.nextSibling();
     }
-    stru->setInitialChildren(children);
     if (newInfo.scriptEngineNeeded)
         info.scriptEngineNeeded = true;
     return stru;
@@ -608,6 +698,8 @@
             data = enumFromXML(elem, true, info);
         else if (tag == QLatin1String("string"))
             data = stringFromXML(elem, info);
+        else if (tag == QLatin1String("pointer"))
+            data = pointerFromXML(elem, info);
     }
     if (data)
     {
Index: kasten/controllers/view/structures/parsers/osdparser.h
===================================================================
--- kasten/controllers/view/structures/parsers/osdparser.h	(revision 1309561)
+++ kasten/controllers/view/structures/parsers/osdparser.h	(working copy)
@@ -26,8 +26,11 @@
 #include <QtCore/QDir>
 #include <QtXml/QDomNode>
 #include <QtXml/QDomNodeList>
+#include <QtCore/QQueue>
+#include <QtCore/QPair>
 
 #include "../datatypes/primitive/enumdefinition.h"
+#include "../datatypes/pointerdatainformation.h"
 #include "abstractstructureparser.h"
 
 class StringDataInformation;
@@ -61,6 +64,7 @@
         ScriptLogger* logger;
         DataInformation* parent;
         QVector<EnumDefinition::Ptr> enums;
+        QQueue<QPair<PointerDataInformation*, QDomNode> >* delayed;
         bool scriptEngineNeeded;
     };
 
@@ -74,6 +78,9 @@
     UnionDataInformation* unionFromXML(const QDomElement& xmlElem, ParserInfo& info) const;
     StructureDataInformation* structFromXML(const QDomElement& xmlElem, ParserInfo& info) const;
     ArrayDataInformation* arrayFromXML(const QDomElement& xmlElem, ParserInfo& info) const;
+    PointerDataInformation* pointerFromXML(const QDomElement& xmlElem, ParserInfo& info) const;
+    void delayParse(PointerDataInformation* pointer, const QDomNode& childType,
+            ParserInfo& info) const;
 
     DataInformation* parseNode(const QDomNode& node, ParserInfo& info) const;
     EnumDefinition::Ptr findEnum(const QString& defName, const ParserInfo& info) const;
Index: kasten/controllers/view/structures/datatypes/topleveldatainformation.h
===================================================================
--- kasten/controllers/view/structures/datatypes/topleveldatainformation.h	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/topleveldatainformation.h	(working copy)
@@ -25,9 +25,11 @@
 #include <QtCore/QMap>
 #include <QtCore/QFileInfo>
 #include <QtCore/QSharedPointer>
+#include <QtCore/QQueue>
 
 #include <arraychangemetricslist.h>
 #include "datainformationbase.h"
+#include "pointerdatainformation.h"
 #include "../script/scripthandler.h"
 
 class ScriptLogger;
@@ -56,10 +58,13 @@
             QScriptEngine* engine = 0, const QFileInfo& structureFile = QFileInfo());
     virtual ~TopLevelDataInformation();
 
-    typedef QSharedPointer<TopLevelDataInformation> Ptr;
+    // TODO: Using here a QSharedPointer would cause a crash
+    // typedef QSharedPointer<TopLevelDataInformation> Ptr;
+    typedef TopLevelDataInformation* Ptr;
     typedef QVector<Ptr> List;
 
 public:
+
     void validate();
     /** Reads the necessary data from @p input
      *
@@ -87,6 +92,7 @@
     ScriptHandler* scriptHandler() const;
     ScriptLogger* logger() const;
     void setChildDataChanged();
+    void enqueueReadData(PointerDataInformation* toRead);
 
     virtual bool isTopLevel() const;
 
@@ -128,6 +134,7 @@
     int mIndex;
     bool mValid :1;
     bool mChildDataChanged :1;
+    QQueue<PointerDataInformation*> mDelayedRead;
 };
 
 inline DataInformation* TopLevelDataInformation::actualDataInformation() const
Index: kasten/controllers/view/structures/datatypes/datainformation.cpp
===================================================================
--- kasten/controllers/view/structures/datatypes/datainformation.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/datainformation.cpp	(working copy)
@@ -357,38 +357,53 @@
 }
 
 QPair<DataInformation*, QString> DataInformation::findChildForDynamicArrayLength(
-        const QString& name, uint upTo) const
+        const QString& name, int excludeChild) const
         {
-    Q_ASSERT(upTo <= childCount());
-    for (int i = upTo - 1; i >= 0; --i)
+
+    // We recurse towards the parent, so we must exclude the child from
+    // which we came
+    if (excludeChild >= 0)
     {
-        DataInformation* current = childAt(i);
-        QString start = name;
-        if (current->canHaveChildren())
+        for (int i = childCount() - 1; i >= 0; --i)
         {
-            QPair<DataInformation*, QString> tmp = findChildForDynamicArrayLength(name,
-                    current->childCount());
-            current = tmp.first;
-            if (current)
-                start = start + tmp.second;
+            if (i == excludeChild)
+                continue;
+            DataInformation* current = childAt(i);
+            QString start = name;
+            if (current->canHaveChildren())
+            {
+                // Recurse towards the children, no need to exlude anything
+                QPair<DataInformation*, QString> tmp = current->findChildForDynamicArrayLength(name,
+                        current->childCount());
+                current = tmp.first;
+                if (current)
+                    start = start + tmp.second;
+            }
+            if (current && current->name() == name)
+            {
+                // Found!
+                return qMakePair(current, QString(start + QLatin1String(".value")));
+            }
         }
-        if (current && current->name() == name)
-        {
-            return qMakePair(current, QString(start + QLatin1String(".value")));
-        }
     }
     if (!parent() || parent()->isTopLevel())
+    {
+        // Not found!
         return QPair<DataInformation*, QString>(0, QString());
+    }
 
+    // Let's recurse towards the parent excluding the current node
     QPair<DataInformation*, QString> ret =
             parent()->asDataInformation()->findChildForDynamicArrayLength(name, row());
     if (ret.first)
     {
-        //found one
+        // Found in a child, let's add "parent." to the script
         return qMakePair(ret.first, QString(QLatin1String("parent.") + ret.second));
     }
     else
+    {
         return QPair<DataInformation*, QString>(0, QString());
+    }
 }
 
 TopLevelDataInformation* DataInformation::topLevelDataInformation() const
Index: kasten/controllers/view/structures/datatypes/pointerdatainformation.cpp
===================================================================
--- kasten/controllers/view/structures/datatypes/pointerdatainformation.cpp	(revision 0)
+++ kasten/controllers/view/structures/datatypes/pointerdatainformation.cpp	(revision 0)
@@ -0,0 +1,161 @@
+/*
+ *   This file is part of the Okteta Kasten Framework, made within the KDE community.
+ *
+ *   Copyright 2011 Alex Richardson <alex.richardson@gmx.de>
+ *
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) version 3, or any
+ *   later version accepted by the membership of KDE e.V. (or its
+ *   successor approved by the membership of KDE e.V.), which shall
+ *   act as a proxy defined in Section 6 of version 3 of the license.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pointerdatainformation.h"
+#include <QtScript/QScriptContext>
+#include "topleveldatainformation.h"
+#include "../allprimitivetypes.h"
+#include "../script/scriptvalueconverter.h"
+#include "../script/scriptutils.h"
+#include "../script/scripthandlerinfo.h"
+#include "../script/classes/structunionscriptclass.h"
+#include "../script/scriptlogger.h"
+#include <QtScript/QScriptEngine>
+
+
+PointerDataInformation::PointerDataInformation(QString name, DataInformation* childType,
+            PrimitiveDataInformation* type, DataInformation* parent) : DataInformationWithChildren(name, QVector<DataInformation*>(1, childType), parent),
+            mValue(type)
+{
+    Q_CHECK_PTR(type);
+    Q_CHECK_PTR(childType);
+    type->setParent(this);
+}
+
+PointerDataInformation::PointerDataInformation(QString name, PrimitiveDataInformation* type, DataInformation* parent)
+    : DataInformationWithChildren(name, QVector<DataInformation*>(), parent),
+            mValue(type)
+{
+    Q_CHECK_PTR(type);
+    type->setParent(this);
+}
+
+PointerDataInformation::~PointerDataInformation()
+{
+}
+
+PointerDataInformation::PointerDataInformation(const PointerDataInformation& d) :
+    DataInformationWithChildren(d), mValue(0)
+{
+    mValue.reset(d.mValue->clone());
+    mValue->setParent(this);
+}
+
+QScriptValue PointerDataInformation::toScriptValue(QScriptEngine* engine, ScriptHandlerInfo* handlerInfo)
+{
+    QScriptValue ret = engine->newObject(handlerInfo->mStructUnionClass.data());
+    ret.setData(engine->toScriptValue(static_cast<DataInformation*>(this)));
+    return ret;
+}
+
+bool PointerDataInformation::setChildData(uint /*row*/, const QVariant& /*value*/, Okteta::AbstractByteArrayModel* /*out*/, Okteta::Address /*address*/, BitCount64 /*bitsRemaining*/, quint8 /*bitOffset*/)
+{
+    Q_ASSERT_X(false, "PointerDataInformation::setChildData()", "this should never be called!!");
+    return false;
+}
+
+bool PointerDataInformation::setData(const QVariant& value, Okteta::AbstractByteArrayModel* out, Okteta::Address address, BitCount64 bitsRemaining, quint8 bitOffset)
+{
+    return mValue->setData(value, out, address, bitsRemaining, bitOffset);
+}
+
+qint64 PointerDataInformation::readData(Okteta::AbstractByteArrayModel* input, Okteta::Address address, BitCount64 bitsRemaining, quint8* bitOffset)
+{
+    //update enum first (it is possible to change the enum definition this enum uses
+    topLevelDataInformation()->updateElement(this);
+    qint64 retVal = mValue->readData(input, address, bitsRemaining, bitOffset);
+    mWasAbleToRead = retVal >= 0; //not able to read if mValue->readData returns -1
+
+    // If the pointer it's outside the boundaries of the input simply ignore it
+    if (mValue->value().uintValue < input->size())
+    {
+        // Enqueue for later reading of the destination
+        topLevelDataInformation()->enqueueReadData(this);
+    }
+
+    return retVal;
+}
+
+qint64 PointerDataInformation::delayedReadData(Okteta::AbstractByteArrayModel *input, Okteta::Address address)
+{
+    quint8 childBitOffset;
+    // Compute the destination offset
+    Okteta::Address newAddress(mValue->value().uintValue + address);
+
+    // If the computed destination it's outside the boundaries of the input
+    // ignore it
+    if (newAddress < 0 || newAddress > input->size())
+        return 0;
+
+    // Let the child do the work
+    return mChildren.first()->readData(input, newAddress, (input->size() - newAddress) * 8, &childBitOffset);
+}
+
+BitCount32 PointerDataInformation::size() const
+{
+    return mValue->size();
+}
+
+void PointerDataInformation::setWidgetData(QWidget* w) const
+{
+    return mValue->setWidgetData(w);
+}
+
+QVariant PointerDataInformation::dataFromWidget(const QWidget* w) const
+{
+    return mValue->dataFromWidget(w);
+}
+
+QWidget* PointerDataInformation::createEditWidget(QWidget* parent) const
+{
+    return mValue->createEditWidget(parent);
+}
+
+QString PointerDataInformation::typeName() const
+{
+    QString result = mValue->typeName();
+    result.append(QString::fromAscii(" pointer"));
+    return result;
+}
+
+BitCount32 PointerDataInformation::positionRelativeToRoot(int row) const
+{
+    // Two cases position of the pointer itself or position
+    // from which calculate the position of the children
+    if (row < 0)
+        return mValue->value().uintValue * 8;
+    else
+        return DataInformationWithChildren::positionRelativeToRoot(row);
+}
+
+QString PointerDataInformation::valueString() const
+{
+    return mValue->valueString();
+}
+
+Qt::ItemFlags PointerDataInformation::flags(int column, bool fileLoaded) const
+{
+    if (column == (int)DataInformation::ColumnValue && fileLoaded)
+        return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
+    else
+        return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
Index: kasten/controllers/view/structures/datatypes/datainformationwithchildren.cpp
===================================================================
--- kasten/controllers/view/structures/datatypes/datainformationwithchildren.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/datainformationwithchildren.cpp	(working copy)
@@ -167,14 +167,6 @@
     }
 }
 
-void DataInformationWithChildren::setInitialChildren(const QVector<DataInformation*>& children)
-{
-    Q_ASSERT(mChildren.isEmpty());
-    mChildren = children;
-    for (int i = 0; i < mChildren.size(); ++i)
-        mChildren.at(i)->setParent(this);
-}
-
 void DataInformationWithChildren::setChildren(const QVector<DataInformation*>& newChildren)
 {
     uint numChildren = childCount();
@@ -222,12 +214,14 @@
     return mChildren.at(row)->data(column, role);
 }
 
-void DataInformationWithChildren::appendChild(DataInformation* newChild)
+void DataInformationWithChildren::appendChild(DataInformation* newChild, bool emitSignal)
 {
-    topLevelDataInformation()->_childrenAboutToBeInserted(this, mChildren.size(), mChildren.size());
+    if (emitSignal)
+        topLevelDataInformation()->_childrenAboutToBeInserted(this, mChildren.size(), mChildren.size());
     newChild->setParent(this);
     mChildren.append(newChild);
-    topLevelDataInformation()->_childrenInserted(this, mChildren.size(), mChildren.size());
+    if (emitSignal)
+        topLevelDataInformation()->_childrenInserted(this, mChildren.size(), mChildren.size());
 }
 
 void DataInformationWithChildren::appendChildren(const QVector<DataInformation*>& newChildren)
Index: kasten/controllers/view/structures/datatypes/datainformation.h
===================================================================
--- kasten/controllers/view/structures/datatypes/datainformation.h	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/datainformation.h	(working copy)
@@ -180,7 +180,7 @@
     virtual QScriptValue toScriptValue(QScriptEngine* engine, ScriptHandlerInfo* handlerInfo) = 0;
     void setParent(DataInformationBase* newParent);
     DataInformationBase* parent() const;
-    QPair<DataInformation*, QString> findChildForDynamicArrayLength(const QString& name, uint upTo) const;
+    QPair<DataInformation*, QString> findChildForDynamicArrayLength(const QString& name, int exclude) const;
     ScriptLogger* logger() const;
 
 protected:
Index: kasten/controllers/view/structures/datatypes/pointerdatainformation.h
===================================================================
--- kasten/controllers/view/structures/datatypes/pointerdatainformation.h	(revision 0)
+++ kasten/controllers/view/structures/datatypes/pointerdatainformation.h	(revision 0)
@@ -0,0 +1,65 @@
+/*
+ *   This file is part of the Okteta Kasten Framework, made within the KDE community.
+ *
+ *   Copyright 2011 Alex Richardson <alex.richardson@gmx.de>
+ *
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) version 3, or any
+ *   later version accepted by the membership of KDE e.V. (or its
+ *   successor approved by the membership of KDE e.V.), which shall
+ *   act as a proxy defined in Section 6 of version 3 of the license.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef POINTERDATAINFORMATION_H
+#define POINTERDATAINFORMATION_H
+
+#include "datainformationwithchildren.h"
+#include "primitive/primitivedatainformation.h"
+
+
+class PointerDataInformation : public DataInformationWithChildren
+{
+protected:
+    explicit PointerDataInformation(const PointerDataInformation& d);
+public:
+    /** creates a new pointer
+     *  takes ownership over @p childType
+     */
+    PointerDataInformation(QString name, DataInformation* childType,
+            PrimitiveDataInformation* type, DataInformation* parent);
+    PointerDataInformation(QString name, PrimitiveDataInformation* type, DataInformation* parent);
+    virtual ~PointerDataInformation();
+
+    DATAINFORMATION_CLONE(Pointer)
+
+protected:
+    QScopedPointer<PrimitiveDataInformation> mValue; // To allow different pointer sizes
+
+public:
+    virtual QScriptValue toScriptValue(QScriptEngine* engine, ScriptHandlerInfo* handlerInfo);
+    virtual bool setChildData(uint row, const QVariant& value, Okteta::AbstractByteArrayModel* out, Okteta::Address address, BitCount64 bitsRemaining, quint8 bitOffset);
+    virtual bool setData(const QVariant& value, Okteta::AbstractByteArrayModel* out, Okteta::Address address, BitCount64 bitsRemaining, quint8 bitOffset);
+    virtual qint64 readData(Okteta::AbstractByteArrayModel* input, Okteta::Address address, BitCount64 bitsRemaining, quint8* bitOffset);
+    virtual qint64 delayedReadData(Okteta::AbstractByteArrayModel* input, Okteta::Address address);
+    virtual BitCount32 size() const;
+    virtual void setWidgetData(QWidget* w) const;
+    virtual QVariant dataFromWidget(const QWidget* w) const;
+    virtual QWidget* createEditWidget(QWidget* parent) const;
+    virtual QString typeName() const;
+    virtual QString valueString() const;
+    virtual BitCount32 positionRelativeToRoot(int row = -1) const;
+    virtual Qt::ItemFlags flags(int column, bool fileLoaded = true) const;
+    
+};
+
+#endif // POINTERDATAINFORMATION_H
Index: kasten/controllers/view/structures/datatypes/primitive/primitivedatainformation.cpp
===================================================================
--- kasten/controllers/view/structures/datatypes/primitive/primitivedatainformation.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/primitive/primitivedatainformation.cpp	(working copy)
@@ -39,3 +39,8 @@
     else
         return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
 }
+
+// The inline destructor makes the compiler unhappy
+PrimitiveDataInformation::~PrimitiveDataInformation()
+{
+}
Index: kasten/controllers/view/structures/datatypes/primitive/basicprimitivedatainformation.cpp
===================================================================
--- kasten/controllers/view/structures/datatypes/primitive/basicprimitivedatainformation.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/primitive/basicprimitivedatainformation.cpp	(working copy)
@@ -84,7 +84,8 @@
 qint64 BasicPrimitiveDataInformation<T, C>::readData(Okteta::AbstractByteArrayModel* input,
         Okteta::Address address, BitCount64 bitsRemaining, quint8* bitOffset)
 {
-    Q_ASSERT((input->size() - address) * 8 - *bitOffset == bitsRemaining);
+    // TODO: this assertion is bad, sometimes we limit bitsReamining manually
+    // Q_ASSERT((input->size() - address) * 8 - *bitOffset == bitsRemaining);
     const bool wasValid = mWasAbleToRead;
     if (bitsRemaining < BitCount64(size()))
     {
Index: kasten/controllers/view/structures/datatypes/primitive/primitivedatainformation.h
===================================================================
--- kasten/controllers/view/structures/datatypes/primitive/primitivedatainformation.h	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/primitive/primitivedatainformation.h	(working copy)
@@ -112,8 +112,4 @@
 {
 }
 
-inline PrimitiveDataInformation::~PrimitiveDataInformation()
-{
-}
-
 #endif /* PRIMITIVEDATAINFORMATION_H_ */
Index: kasten/controllers/view/structures/datatypes/datainformationwithchildren.h
===================================================================
--- kasten/controllers/view/structures/datatypes/datainformationwithchildren.h	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/datainformationwithchildren.h	(working copy)
@@ -62,13 +62,11 @@
     virtual void calculateValidationState();
 
     /** Takes ownership! */
-    void appendChild(DataInformation* child);
+    void appendChild(DataInformation* child, bool emitSignal = true);
     /** Takes ownership of all elements */
     void appendChildren(const QVector<DataInformation*>& newChildren);
     void setChildren(const QVector<DataInformation*>& newChildren);
     void setChildren(QScriptValue newChildren);
-    /** the same as setChildren, but without emitting size change signals, since otherwise it would crash */
-    void setInitialChildren(const QVector<DataInformation*>& children);
 
     virtual QScriptValue toScriptValue(QScriptEngine* engine, ScriptHandlerInfo* handlerInfo);
 };
Index: kasten/controllers/view/structures/datatypes/topleveldatainformation.cpp
===================================================================
--- kasten/controllers/view/structures/datatypes/topleveldatainformation.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/topleveldatainformation.cpp	(working copy)
@@ -102,6 +102,13 @@
     updateElement(mData.data()); //unlikely that this is useful, but maybe someone needs it
     mData->readData(input, address, remainingBits, &bitOffset);
 
+    // Read all the delayed PointerDataInformation
+    // We do this because the pointed data is indipendent from the
+    // structure containing the pointer and so we can use fields
+    // which come after the pointer itself in the structure
+    while (!mDelayedRead.isEmpty())
+        mDelayedRead.dequeue()->delayedReadData(input, address);
+
     if (mChildDataChanged)
     {
         emit dataChanged();
@@ -109,6 +116,11 @@
     }
 }
 
+void TopLevelDataInformation::enqueueReadData(PointerDataInformation *toRead)
+{
+    mDelayedRead.append(toRead);
+}
+
 bool TopLevelDataInformation::isReadingNecessary(const Okteta::ArrayChangeMetricsList& changesList,
         Okteta::Address address)
 {
Index: kasten/controllers/view/structures/datatypes/array/arraydatainformation.cpp
===================================================================
--- kasten/controllers/view/structures/datatypes/array/arraydatainformation.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/array/arraydatainformation.cpp	(working copy)
@@ -32,7 +32,7 @@
 #include "primitivearraydata.h"
 
 ArrayDataInformation::ArrayDataInformation(QString name, uint length, DataInformation* childType,
-        DataInformation* parent) : DataInformation(name, parent)
+                                           DataInformation* parent, bool isTotalLength) : DataInformation(name, parent), isTotalLength(isTotalLength)
 {
     if (length > MAX_LEN)
     {
@@ -41,7 +41,7 @@
     }
     Q_CHECK_PTR(childType);
     childType->setParent(this);
-    mData.reset(arrayDataFromType(length, childType));
+    mData.reset(arrayDataFromType(length, childType, isTotalLength));
 }
 
 ArrayDataInformation::ArrayDataInformation(const ArrayDataInformation& d) :
@@ -54,7 +54,7 @@
         {
             //childtype creates a copy, so this is safe
             DataInformation* childType = static_cast<ComplexArrayData*>(d.mData.data())->childType();
-            mData.reset(new ComplexArrayData(length, childType, this));
+            mData.reset(new ComplexArrayData(length, childType, this, d.isTotalLength));
         }
         else
         {
@@ -208,6 +208,7 @@
 qint64 ArrayDataInformation::readData(Okteta::AbstractByteArrayModel* input, Okteta::Address address,
         BitCount64 bitsRemaining, quint8* bitOffset)
 {
+    topLevelDataInformation()->updateElement(this);
     if (Q_UNLIKELY(!mData))
     {
         kWarning() << "mData == null";
@@ -291,12 +292,12 @@
     }
 }
 
-AbstractArrayData* ArrayDataInformation::arrayDataFromType(uint length, DataInformation* data)
+AbstractArrayData* ArrayDataInformation::arrayDataFromType(uint length, DataInformation* data, bool isTotalLength)
 {
     if (!data->isPrimitive() || data->isBitfield() || data->isEnum())
     {
         //we cant use primitiveArrayData for bitfields/enums or any complex data type
-        return new ComplexArrayData(length, data, this);
+        return new ComplexArrayData(length, data, this, isTotalLength);
     }
     //it is primitive -> create a PrimitiveArrayData
     PrimitiveDataType type = data->asPrimitive()->type();
Index: kasten/controllers/view/structures/datatypes/array/complexarraydata.cpp
===================================================================
--- kasten/controllers/view/structures/datatypes/array/complexarraydata.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/array/complexarraydata.cpp	(working copy)
@@ -22,6 +22,7 @@
 
 #include "complexarraydata.h"
 
+#include <algorithm>
 #include <QScriptValue>
 #include <QVariant>
 #include <KLocalizedString>
@@ -32,11 +33,23 @@
 #include "../../script/scriptlogger.h"
 
 ComplexArrayData::ComplexArrayData(unsigned int initialLength, DataInformation* data,
-        DataInformation* parent): AbstractArrayData(parent), mChildType(data)
+                                   DataInformation* parent, bool isTotalLength)
+    : AbstractArrayData(parent), mChildType(data), maxLength(0), isTotalLength(isTotalLength)
 {
-    mChildren.reserve(initialLength);
     mChildType->setParent(mParent);
-    appendChildren(0, initialLength);
+
+    // If isTotalLength is true then initialLength is the maximum size
+    // in bytes of the array, we don't know how many elements the array
+    // will contain, so we don't reserve space for them
+    if (isTotalLength)
+    {
+        maxLength = initialLength;
+    }
+    else
+    {
+        mChildren.reserve(initialLength);
+        appendChildren(0, initialLength);
+    }
 }
 
 ComplexArrayData::~ComplexArrayData()
@@ -58,18 +71,27 @@
 
 void ComplexArrayData::setLength(uint newLength)
 {
-    uint oldLength = mChildren.count();
-    if (newLength > oldLength)
+    // If isTotalLength is true, simply update the maximum size
+    // of the array in bytes
+    if (isTotalLength)
     {
-        mChildren.reserve(newLength);
-        appendChildren(oldLength, newLength);
+        maxLength = newLength;
     }
-    else if (newLength < oldLength) //XXX maybe keep some cached
+    else
     {
-        qDeleteAll(mChildren.begin() + newLength, mChildren.end());
-        mChildren.resize(newLength);
+        uint oldLength = mChildren.count();
+        if (newLength > oldLength)
+        {
+            mChildren.reserve(newLength);
+            appendChildren(oldLength, newLength);
+        }
+        else if (newLength < oldLength) //XXX maybe keep some cached
+        {
+            qDeleteAll(mChildren.begin() + newLength, mChildren.end());
+            mChildren.resize(newLength);
+        }
+        //else nothing to do, length stays the same
     }
-    //else nothing to do, length stays the same
 }
 
 DataInformation* ComplexArrayData::childAt(unsigned int idx)
@@ -91,6 +113,8 @@
 
 BitCount32 ComplexArrayData::size() const
 {
+    if (isTotalLength)
+        return maxLength * 8;
     int max = mChildren.size();
     uint total = 0;
     for (int i = 0; i < max; ++i) {
@@ -151,19 +175,46 @@
     quint8 bitOffset = 0;
     TopLevelDataInformation* top = mParent->topLevelDataInformation();
     Q_CHECK_PTR(top);
+
+    // If isTotalLength is true then we have to limit the amount of data
+    // to read to maxLength bytes and add one element at a time
+    if (isTotalLength)
+    {
+        bitsRemaining = std::min(bitsRemaining, (BitCount64) 8 * maxLength);
+        appendChildren(0, 1);
+    }
+
     for (int i = 0; i < mChildren.size(); i++)
     {
         DataInformation* next = mChildren.at(i);
         top->updateElement(next);
         qint64 currentReadBits = next->readData(input, address + readBytes,
                 bitsRemaining - readBits, &bitOffset);
+
         if (currentReadBits == -1)
         {
             //could not read one element -> whole structure could not be read
             return -1;
         }
+        else if (bitsRemaining == readBits + currentReadBits)
+        {
+            // We read exactly how much data we expected, that's enough
+            return readBits + currentReadBits;
+        }
+        else if (bitsRemaining < readBits + currentReadBits)
+        {
+            // We exceede the array size, remove the last parsed element
+            mChildren.pop_front();
+            return readBits;
+        }
+
         readBits += currentReadBits;
         readBytes = (readBits + bitOffset) / 8;
+
+        // If isTotalLength is true we have to manually expand
+        // mChildren each time
+        if (isTotalLength)
+            appendChildren(mChildren.size(), mChildren.size() + 1);
     }
     return readBits;
 }
Index: kasten/controllers/view/structures/datatypes/array/arraydatainformation.h
===================================================================
--- kasten/controllers/view/structures/datatypes/array/arraydatainformation.h	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/array/arraydatainformation.h	(working copy)
@@ -42,7 +42,7 @@
      *  length should be > 0
      */
     ArrayDataInformation(QString name, uint length, DataInformation* childType,
-            DataInformation* parent = 0);
+            DataInformation* parent = 0, bool isTotalLength = false);
     virtual ~ArrayDataInformation();
     DATAINFORMATION_CLONE(Array)
 
@@ -84,8 +84,9 @@
     QScriptValue childToScriptValue(uint index, QScriptEngine* engine, ScriptHandlerInfo* handlerInfo) const;
 private:
     /** Takes ownership of @p data ! */
-    AbstractArrayData* arrayDataFromType(uint length, DataInformation* data);
+    AbstractArrayData* arrayDataFromType(uint length, DataInformation* data, bool isTotalLength = false);
     AbstractArrayData* primitiveArrayFromType(uint length, PrimitiveDataType type);
+    bool isTotalLength;
 protected:
     virtual BitCount32 offset(unsigned int index) const;
 
Index: kasten/controllers/view/structures/datatypes/array/complexarraydata.h
===================================================================
--- kasten/controllers/view/structures/datatypes/array/complexarraydata.h	(revision 1309561)
+++ kasten/controllers/view/structures/datatypes/array/complexarraydata.h	(working copy)
@@ -37,7 +37,7 @@
     Q_DISABLE_COPY(ComplexArrayData)
 public:
     /** Takes ownership of @p data !*/
-    ComplexArrayData(unsigned int initialLength, DataInformation* data, DataInformation* parent);
+    ComplexArrayData(unsigned int initialLength, DataInformation* data, DataInformation* parent, bool isTotalLength);
     virtual ~ComplexArrayData();
 
 
@@ -77,6 +77,8 @@
 private:
     DataInformation* mChildType;
     QVector<DataInformation*> mChildren;
+    unsigned int maxLength;
+    bool isTotalLength;
 };
 
 inline bool ComplexArrayData::isComplex() const
Index: kasten/controllers/view/structures/structview.cpp
===================================================================
--- kasten/controllers/view/structures/structview.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/structview.cpp	(working copy)
@@ -82,7 +82,7 @@
     mStructTreeView->setSortingEnabled(false);
     mStructTreeView->installEventFilter(this);
     QHeaderView* header = mStructTreeView->header();
-    header->setResizeMode(QHeaderView::Interactive);
+    header->setResizeMode(QHeaderView::ResizeToContents);
 
     baseLayout->addWidget(mStructTreeView, 10);
 
Index: kasten/controllers/view/structures/structtool.cpp
===================================================================
--- kasten/controllers/view/structures/structtool.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/structtool.cpp	(working copy)
@@ -278,12 +278,16 @@
                 this, SIGNAL(childrenAboutToBeRemoved(DataInformation*,uint,uint)));
         connect(child, SIGNAL(childrenRemoved(const DataInformation*,uint,uint)),
                 this, SIGNAL(childrenRemoved(const DataInformation*,uint,uint)));
-        d->mData.append(QSharedPointer<TopLevelDataInformation>(child));
+        // TODO: using QSharedPointer here crashes
+        // d->mData.append(QSharedPointer<TopLevelDataInformation>(child));
+        d->mData.append(child);
     }
     else
     {
         child->setIndex(d->mInvalidData.size());
-        d->mInvalidData.append(QSharedPointer<TopLevelDataInformation>(child));
+        // TODO: using QSharedPointer here crashes
+        // d->mInvalidData.append(QSharedPointer<TopLevelDataInformation>(child));
+        d->mInvalidData.append(child);
     }
 }
 
Index: kasten/controllers/view/structures/script/scripthandler.cpp
===================================================================
--- kasten/controllers/view/structures/script/scripthandler.cpp	(revision 1309561)
+++ kasten/controllers/view/structures/script/scripthandler.cpp	(working copy)
@@ -28,6 +28,7 @@
 #include "../datatypes/datainformation.h"
 #include "../datatypes/topleveldatainformation.h"
 
+#include <QtGui/QAction>
 #include <QtCore/QFile>
 #include <QtCore/QString>
 #include <QStringList>
@@ -92,7 +93,7 @@
         else if (mEngine->hasUncaughtException())
         {
             mTopLevel->logger()->error(result) << "Error occurred while validating element "
-                    << data->fullObjectPath() << "\nBacktrace:"
+                    << data->fullObjectPath() << "\nError: " << mEngine->uncaughtException().toString() << "\nBacktrace:"
                     << mEngine->uncaughtExceptionBacktrace();
             data->setValidationError(QLatin1String("Error occurred in validation: ")
                     + result.toString());
@@ -134,7 +135,7 @@
         if (mEngine->hasUncaughtException())
         {
             mTopLevel->logger()->error(result) << "error occurred while updating element "
-                    << data->fullObjectPath() << "\nBacktrace:"
+                    << data->fullObjectPath() << "\nError: " << mEngine->uncaughtException().toString() << "\nBacktrace:"
                     << mEngine->uncaughtExceptionBacktrace();
         }
     }
Index: kasten/controllers/CMakeLists.txt
===================================================================
--- kasten/controllers/CMakeLists.txt	(revision 1309561)
+++ kasten/controllers/CMakeLists.txt	(working copy)
@@ -289,6 +289,7 @@
   view/structures/datatypes/datainformation.cpp
   view/structures/datatypes/datainformationbase.cpp
   view/structures/datatypes/dummydatainformation.cpp
+  view/structures/datatypes/pointerdatainformation.cpp
   view/structures/datatypes/datainformationwithchildren.cpp
   view/structures/datatypes/structuredatainformation.cpp
   view/structures/datatypes/uniondatainformation.cpp
