//--------------------------------------
//--- 010 Editor v3.0 Binary Template
//
// File: iv-whm.bt
// Author: Stanislav "listener" Golovin
// XHM Revision: 0.0.1
// WHM Revision: 0.1 (2009/08/30) - Dageron
// WHM Revision: 0.3 (2009/09/06) - listener
//--------------------------------------
#include "Data/iv-types.bth" 

typedef enum <uint> {
    Node_HtmlNode = 0,
    Node_HtmlDataNode = 1,
    Node_HtmlTableNode = 2,
    Node_HtmlTableElementNode = 3
} HtmlNodeType;

typedef enum <uint> {
    HTMLTAG_HTML = 0,
    HTMLTAG_TITLE = 1,
    HTMLTAG_A = 2,
    HTMLTAG_BODY = 3,
    HTMLTAG_B = 4,
    HTMLTAG_BR = 5,
    HTMLTAG_CENTER = 6,
    HTMLTAG_CODE = 7,
    HTMLTAG_DL = 8,
    HTMLTAG_DT = 9,
    HTMLTAG_DD = 10,
    HTMLTAG_DIV = 11,
    HTMLTAG_EMBED = 12,
    HTMLTAG_EM = 13,
    HTMLTAG_HEAD = 14,
    HTMLTAG_H1 = 15,
    HTMLTAG_H2 = 16,
    HTMLTAG_H3 = 17,
    HTMLTAG_H4 = 18,
    HTMLTAG_H5 = 19,
    HTMLTAG_H6 = 20,
    HTMLTAG_IMG = 21,
    HTMLTAG_I = 22,
    HTMLTAG_LINK = 23,
    HTMLTAG_LI = 24,
    HTMLTAG_META = 25,
    HTMLTAG_OBJECT = 26,
    HTMLTAG_OL = 27,
    HTMLTAG_P = 28,
    HTMLTAG_PARAM = 29,
    HTMLTAG_SPAN = 30,
    HTMLTAG_STRONG = 31,
    HTMLTAG_STYLE = 32,
    HTMLTAG_TABLE = 33,
    HTMLTAG_TR = 34,
    HTMLTAG_TH = 35,
    HTMLTAG_TD = 36,
    HTMLTAG_UL = 37,
    HTMLTAG_TEXT = 38,
    HTMLTAG_SCRIPTOBJ = 39
} HtmlTag;

typedef enum<uint> {
    HTMLATTRVAL_LEFT = 0,
    HTMLATTRVAL_RIGHT = 1,
    HTMLATTRVAL_CENTER = 2,
    HTMLATTRVAL_JUSTIFY = 3,
    HTMLATTRVAL_TOP = 4,
    HTMLATTRVAL_BOTTOM = 5,
    HTMLATTRVAL_MIDDLE = 6,
    HTMLATTRVAL_INHERIT = 7,
    HTMLATTRVAL_XXSMALL = 8,
    HTMLATTRVAL_XSMALL = 9,
    HTMLATTRVAL_SMALL = 10,
    HTMLATTRVAL_MEDIUM = 11,
    HTMLATTRVAL_LARGE = 12,
    HTMLATTRVAL_XLARGE = 13,
    HTMLATTRVAL_XXLARGE = 14,
    HTMLATTRVAL_BLOCK = 15,
    HTMLATTRVAL_INLINE = 18,
    HTMLATTRVAL_NONE = 19,
    HTMLATTRVAL_SOLID = 20,
    HTMLATTRVAL_UNDERLINE = 21,
    HTMLATTRVAL_OVERLINE = 22,
    HTMLATTRVAL_LINETHROUGH = 23,
    HTMLATTRVAL_BLINK = 24,
    HTMLATTRVAL_REPEAT = 25,
    HTMLATTRVAL_NOREPEAT = 26,
    HTMLATTRVAL_REPEATX = 27,
    HTMLATTRVAL_REPEATY = 28,
    HTMLATTRVAL_COLLAPSE = 29,
    HTMLATTRVAL_SEPARATE = 30,
    HTMLATTRVAL_UNDEFINED = 0xFFFFFFFF
} HtmlAttrValue;

typedef enum<uint> {
    CSS_WIDTH   = 0,
    CSS_HEIGHT  = 1,
    CSS_DISPLAY = 2,
    CSS_BACKGROUND_COLOR = 3,
    CSS_BACKGROUND_REPEAT = 4,
    CSS_BACKGROUND_POSITION = 5,
    CSS_BACKGROUND_IMAGE = 6,
    CSS_COLOR = 7,
    CSS_TEXT_ALIGN = 8,
    CSS_TEXT_DECORATION = 9,
    CSS_VERTICAL_ALIGN = 10,
    CSS_FONT = 11,
    CSS_FONT_SIZE = 12,
    CSS_FONT_STYLE = 13,
    CSS_FONT_WEIGHT = 14,
    CSS_BORDER_COLLAPSE = 15,
    CSS_BORDER_STYLE = 16,
    CSS_BORDER_BOTTOM_STYLE = 17,
    CSS_BORDER_LEFT_STYLE = 18,
    CSS_BORDER_RIGHT_STYLE = 19,
    CSS_BORDER_TOP_STYLE = 20,
    CSS_BORDER_COLOR = 21,
    CSS_BORDER_BOTTOM_COLOR = 22,
    CSS_BORDER_LEFT_COLOR = 23,
    CSS_BORDER_RIGHT_COLOR = 24,
    CSS_BORDER_TOP_COLOR = 25,
    CSS_BORDER_WIDTH = 26,
    CSS_BORDER_BOTTOM_WIDTH = 27,
    CSS_BORDER_LEFT_WIDTH = 28,
    CSS_BORDER_RIGHT_WIDTH = 29,
    CSS_BORDER_TOP_WIDTHT = 30,
    CSS_MARGIN_BOTTOM = 31,
    CSS_MARGIN_LEFT = 32,
    CSS_MARGIN_RIGHT = 33,
    CSS_MARGIN_TOP = 34,
    CSS_PADDING_BOTTOM = 35,
    CSS_PADDING_LEFT = 36,
    CSS_PADDING_RIGHT = 37,
    CSS_PADDING_TOP = 38,
    CSS_UNUSED = 39
} CssProperty;


struct pgPtr_DWORD {
    int offset:28  <format=hex>;
    int type:4;
    if (type == 5) {   // RAM location
        // SetBackColor (0xC0C0C0);
        local uint doffset = FTell();
        FSeek(offset);
        DWORD DataStart;
        FSeek(doffset);
    }
};

struct CHtmlNode;

struct HtmlRenderState {
    HtmlAttrValue       eDisplay;
    float               fWidth;
    float               fHeight;
    float               _fC;
    float               _f10;
    uchar               _f14[4];
    float               _f18;
    float               _f1C;
    uint                dwBgColor<format=hex>;  
    pgPtr               pBackgroundImage;
    uint                _f28h;
    uint                _f28l;
    HtmlAttrValue       _f30;   // TODO: background-repeat? 
    uint                dwColor<format=hex>;    
    HtmlAttrValue       eAlign;
    HtmlAttrValue       eValign;
    HtmlAttrValue       eTextDecoration;
    uint                _f44;
    HtmlAttrValue       eFontSize;
    int                 nFontStyle;
    int                 nFontWeight;    
    float               _f54;
    uint                dwBorderBottomColor<format=hex>;    
    HtmlAttrValue       eBorderBottomStyle;
    float               fBorderBottomWidth;
    uint                dwBorderLeftColor<format=hex>;      
    HtmlAttrValue       eBorderLeftStyle;
    float               dwBorderLeftWidth;
    uint                dwBorderRightColor<format=hex>;     
    HtmlAttrValue       eBorderRightStyle;
    float               fBorderRightWidth;
    uint                dwBorderTopColor<format=hex>;       
    HtmlAttrValue       eBorderTopStyle;
    float               fBorderTopWidth;        
    float               fMarginBottom;
    float               fMarginLeft;
    float               fMarginRight;
    float               fMarginTop; 
    float               fPaddingBottom;
    float               fPaddingLeft;
    float               fPaddingRight;
    float               fPaddingTop;
    float               fCellPadding;
    float               fCellSpacing;
    int                 nColSpan;
    int                 nRowSpan;
    uchar               _fB8;
    uchar               _fB9;
    uchar               _BA[2];
    uint                dwAlink<format=hex>;    
    HtmlAttrValue       _fC0;
};


struct CPtrCollection {
    uint    fixupOffset:28;
    uint    fixupType:4;    
    ushort  sCount;
    ushort  sSize;

    if (fixupType == 5) { 
        local int offset1 = FTell ();
        FSeek (fixupOffset);
        pgPtr_DWORD data[sSize > sCount ? sSize : sCount]  <optimize=false>;
        FSeek (offset1);
    }
};


// CssSelectorValue
struct CHtmlCssDeclaration {
    CssProperty m_eProperty;
    DWORD       _f4 <format=hex>; // data1
    DWORD       _f8 <format=hex>; // data2
    DWORD       m_eDataType; // data type (0 - int, 1 - float, .., 3 - color, ..., 6 - unused)    
};

// ### pgSparseArray<CHtmlCssDeclaration> ###
struct pgSparseArray_CHtmlCssDeclaration {
    int offset: 28  <format=hex>;
    int type: 4;
    WORD m_wCount;
    WORD m_wSize;
    if (type == 5) {
        local uint doffset = FTell();
        local WORD dsize = m_wCount > m_wSize ? m_wCount : m_wSize;
        FSeek(offset);
        CHtmlCssDeclaration data[dsize] <optimize=false>;
        FSeek(doffset);        
    }
};

struct pgPtr_CHtmlCssSelector;

// ### CHtmlCssSelector ###
struct CHtmlCssSelector {
    HtmlTag                             m_eTag;
    pgSparseArray_CHtmlCssDeclaration   m_aDeclarations;
    pgPtr_CHtmlCssSelector              _fC;
};

// ### pgPtr<CHtmlCssSelector>
struct pgPtr_CHtmlCssSelector{
    int offset: 28  <format=hex>;
    int type: 4;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);
        CHtmlCssSelector  item;
        FSeek(doffset);        
    }
};

struct pgSparseArray_CHtmlCssSelector {
    int offset: 28  <format=hex>;
    int type: 4;
    WORD m_wSize;
    WORD m_wCount;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);
        pgPtr_CHtmlCssSelector data[m_wSize] <optimize=false>;
        FSeek(doffset);        
    }
};

struct pgPtr_CHtmlStylesheet;

// ### CHtmlStylesheet ###
struct CHtmlStylesheet {
    DWORD           _f0;    // unknown (hash?)
    pgSparseArray_CHtmlCssSelector   _f4;
    BYTE            _padC[3];
    BYTE            _fF;
    pgPtr_CHtmlStylesheet   m_pNext;
};

// ### pgPtr<CHtmlStylesheet> ###
struct pgPtr_CHtmlStylesheet {
    int offset: 28  <format=hex>;
    int type: 4;
    if (type == 5) {
        local uint doffset = FTell();
        FSeek(offset);
        CHtmlStylesheet  item;
        FSeek(doffset);        
    }
};

// ### pgObjectArray<CHtmlStylesheet> ###
struct pgObjectArray_CHtmlStylesheet {
    int offset: 28  <format=hex>;
    int type: 4;
    WORD m_wCount;
    WORD m_wSize;
    if (type == 5) {
        local uint doffset = FTell();
        local WORD dsize = m_wCount > m_wSize ? m_wCount : m_wSize;
        FSeek(offset);
        pgPtr_CHtmlStylesheet data[dsize] <optimize=false>;
        FSeek(doffset);        
    }
};

struct CCharCollection {
    uint    fixupOffset:28;
    uint    fixupType:4;    
    ushort  sCount;
    ushort  sSize;

    if (fixupType == 5) { 
        local int offset1 = FTell ();
        FSeek (fixupOffset);
        char data[sCount] <optimize=false>;
        FSeek (offset1);
    }    
};

// ### pgPtr<CHtmlNode> ###
typedef struct  {
    SetBackColor (0xFFC0C0);
    uint offset: 28 <format=hex>;
    uint type: 4;    
    if (type == 5) {   // RAM location
        //SetBackColor (0xC0C0C0);
        //local uint offset = fixupOffset;
        local uint doffset = FTell();
        FSeek(offset);
        CHtmlNode   node;
        FSeek(doffset);
    }
  // SetBackColor(CurrentStructColor);
} pgPtr_CHtmlNode <read=HtmlNodePtr_Read>;

string HtmlNodePtr_Read (pgPtr_CHtmlNode& f) { 
    if (f.type != 5) 
        return "*NULL*";
    if (f.node.m_eNodeType == Node_HtmlDataNode)
        return "DataNode";
    return EnumToString (f.node.m_eHtmlTag);
}

// ### pgObjectArray<CHtmlNode> ###
struct pgObjectArray_CHtmlNode {
    uint    offset:28 <format=hex>;
    uint    type:4;    
    ushort  count;
    ushort  size;

    if (type == 5) {   // valid pointer => define array
        local uint doffset = FTell();
        FSeek(offset);
        // TODO: check again count/size relations
        pgPtr_CHtmlNode data[size] <optimize=false>;
        FSeek(doffset);
    }    
};

// ### CHtmlNode/CHtmlDataNode/CHtmlElementNode/CHtmlTableNode/CHtmlTableElementNode ###
struct CHtmlNode {  // and all subclasses
    uint                    __vtbl <format=hex>;
    HtmlNodeType            m_eNodeType;
    pgPtr                   m_pParentNode;  // simple pgPtr to avoid circular links
    pgObjectArray_CHtmlNode m_children;    
    HtmlRenderState m_renderState;
    
    if (m_eNodeType != Node_HtmlDataNode) { // CHtmlElementNode or subclass ?
        HtmlTag         m_eHtmlTag;
        pgPtr_String    m_pszTagName;
        CCharCollection m_nodeParam;
        if (m_eNodeType == Node_HtmlTableElementNode) {
            int    _fE8;
            int    _fEC;
        } else {    // CHtmlTableNode ?
            pgPtr   _fE8;
            pgPtr   _fEC;
            pgPtr   _fF0;
            pgPtr   _fF4;
            pgPtr   _fF8;
            DWORD   m_dwCellCount;
            DWORD   _f100;
        }
    } else {
        pgPtr_String m_pData;
    }
};

struct CHtmlDocument {    
    pgPtr_CHtmlNode                 m_pRootElement;   
    pgPtr                           m_pBody;    // simple pgPtr to avoid circular links      
    pgPtr_String                    m_pszTitle;
    pgPtr_pgDictionary_grcTexturePC m_pTxd;
    CPtrCollection                  _f10;
    pgObjectArray_CHtmlNode         m_childNodes;
    pgObjectArray_CHtmlStylesheet   m_pStylesheet;
    BYTE                            _pad[3];
    BYTE                            _f2B;
};

LittleEndian ();
CHtmlDocument document;