# HG changeset patch
# User Michael Stahl <mst@openoffice.org>
# Date 1288088575 -7200
# Node ID c6e5d8f80513e0f64d1135de58c4d958f2a71fe6
# Parent  d80c9a92e571b0a2eee1c0f0479c332649c5e9ee
rtftok01: attributes within sprms within sprms, argh...

diff --git a/writerfilter/source/rtftok/RTFDestination.hxx b/writerfilter/source/rtftok/RTFDestination.hxx
--- a/writerfilter/source/rtftok/RTFDestination.hxx
+++ b/writerfilter/source/rtftok/RTFDestination.hxx
@@ -325,9 +325,13 @@
     void SetTableRowSprm(Id const id, RTFValue::Pointer_t const& pValue);
     void SetTableRowNestedSprm(Id const parent, Id const id,
             RTFValue::Pointer_t const& pValue);
+    void SetTableRowDoubleNestedAttribute(Id const grandparent,
+            Id const parent, Id const id, RTFValue::Pointer_t const& pValue);
     void SetTableCellSprm(Id const id, RTFValue::Pointer_t const& pValue);
     void SetTableCellNestedSprm(Id const parent, Id const id,
             RTFValue::Pointer_t const& pValue);
+    void SetTableCellDoubleNestedAttribute(Id const grandparent,
+            Id const parent, Id const id, RTFValue::Pointer_t const& pValue);
     void ResetCharacterProperties();
     void ResetParagraphProperties();
     void ResetSectionProperties();
@@ -344,6 +348,9 @@
     RTFScannerHandlerImpl & m_rHandler;
 };
 
+
+sal_Int32 MapTblWidthUnit(sal_Int32 const n);
+
 } // namespace writerfilter
 } // namespace rtftok
 
diff --git a/writerfilter/source/rtftok/RTFDocumentImpl.cxx b/writerfilter/source/rtftok/RTFDocumentImpl.cxx
--- a/writerfilter/source/rtftok/RTFDocumentImpl.cxx
+++ b/writerfilter/source/rtftok/RTFDocumentImpl.cxx
@@ -42,6 +42,7 @@
 
 #include <doctok/resourceids.hxx>
 #include <doctok/sprmids.hxx>
+#include <ooxml/resourceids.hxx>
 
 #include <rtftok/RTFScanner.hxx>
 #include <rtftok/RTFScannerHandler.hxx>
@@ -67,6 +68,20 @@
 
 
 
+sal_Int32 MapTblWidthUnit(sal_Int32 const n)
+{
+    switch (n)
+    {
+        case 0:
+            return NS_ooxml::LN_Value_ST_TblWidth_nil;
+        case 3:
+            return NS_ooxml::LN_Value_ST_TblWidth_dxa;
+        default:
+            OSL_TRACE("MapTblWidthUnit: unknown: %" SAL_PRIdINT32, n);
+            return 0;
+    }
+}
+
 
 /** Implementation of Reference<Properties>.
  */
@@ -210,11 +225,85 @@
     {
         m_Value[id] = pValue;
     }
+    Attributes_t & GetSprms() { return m_Value; }
 
 private:
     Attributes_t m_Value;
 };
 
+/** Value class for Attributes.
+ */
+class RTFValueAttributes
+    : public RTFValue
+{
+
+public:
+    typedef ::std::map<Id, RTFValue::Pointer_t > Attributes_t;
+    explicit RTFValueAttributes()
+        : m_Value()
+    { }
+    explicit RTFValueAttributes(Attributes_t const& rValue)
+        : m_Value(rValue)
+    { }
+    virtual ~RTFValueAttributes() { }
+    virtual RTFValue * Clone() { return new RTFValueAttributes(m_Value); }
+
+    // don't throw exceptions, just return null values
+    virtual int getInt() const
+    {
+        return 0;
+    }
+    virtual ::rtl::OUString getString() const
+    {
+        return ::rtl::OUString();
+    }
+    virtual uno::Any getAny() const
+    {
+        uno::Any ret;
+//        ret <<= m_Value;
+        return ret;
+    }
+    virtual writerfilter::Reference<Properties>::Pointer_t getProperties()
+    {
+        RTFRefProperties::Attributes_t const dummy;
+        writerfilter::Reference<Properties>::Pointer_t pRet(
+                new RTFRefProperties(m_Value, dummy));
+        return writerfilter::Reference<Properties>::Pointer_t();
+    }
+    virtual writerfilter::Reference<Stream>::Pointer_t getStream()
+    {
+        return writerfilter::Reference<Stream>::Pointer_t();
+    }
+    virtual writerfilter::Reference<BinaryObj>::Pointer_t getBinary()
+    {
+        return writerfilter::Reference<BinaryObj>::Pointer_t();
+    }
+    virtual ::std::string toString() const
+    {
+        ::std::string ret("[");
+        for (Attributes_t::const_iterator iter = m_Value.begin();
+                iter < m_Value.end(); ++iter)
+        {
+            ret += iter->first;
+            ret += ::std::string(" -> ");
+            ret += iter->second->toString();
+            ret += ::std::string(",");
+        }
+        ret += ::std::string("]");
+        return ret;
+    }
+
+    void SetAttribute(Id const id, RTFValue::Pointer_t const& pValue)
+    {
+        m_Value[id] = pValue;
+    }
+    Attributes_t const& GetSprms() const { return m_Value; }
+
+private:
+    Attributes_t m_Value;
+};
+
+
 
 
 class RTFInputStream
@@ -674,7 +763,38 @@
     RTFGroup & rGroup( GetHandler().GetCurrentGroup() );
     RTFValue::Pointer_t const pParent( lcl_SetNestedSprm(
         rGroup.m_TableRowProperties.m_Sprms, parent, id, pValue) );
-    GetHandler().SetTableRowSprm(id, pParent);
+    GetHandler().SetTableRowSprm(parent, pParent);
+}
+
+static RTFValue::Pointer_t
+lcl_SetDoubleNestedAttribute(RTFGroup::Attributes_t rSprms,
+        Id const grandparent, Id const parent,
+        Id const id, RTFValue::Pointer_t const& pValue)
+{
+    RTFGroup::Attributes_t::iterator const iter2(rSprms.find(grandparent));
+    RTFValue::Pointer_t const pGrandParent( (iter2 != rSprms.end())
+        ?   iter2->second
+        :   RTFValue::Pointer_t(new RTFValueSprms()) );
+    RTFGroup::Attributes_t & rParentSprms(
+        dynamic_cast<RTFValueSprms *>(pGrandParent.get())->GetSprms());
+    RTFGroup::Attributes_t::iterator const iter(rParentSprms.find(parent));
+    RTFValue::Pointer_t const pParent( (iter != rParentSprms.end())
+        ?   iter->second
+        :   RTFValue::Pointer_t(new RTFValueAttributes()) );
+    dynamic_cast<RTFValueAttributes *>(pParent.get())->SetAttribute(id, pValue);
+    dynamic_cast<RTFValueSprms *>(pGrandParent.get())->SetSprm(parent, pParent);
+    return pGrandParent;
+}
+
+void
+RTFDestination::SetTableRowDoubleNestedAttribute(Id const grandparent,
+        Id const parent, Id const id, RTFValue::Pointer_t const& pValue)
+{
+    RTFGroup & rGroup( GetHandler().GetCurrentGroup() );
+    RTFValue::Pointer_t const pGrandParent( lcl_SetDoubleNestedAttribute(
+        rGroup.m_TableRowProperties.m_Sprms,
+        grandparent, parent, id, pValue) );
+    GetHandler().SetTableRowSprm(grandparent, pGrandParent);
 }
 
 void
@@ -690,10 +810,22 @@
     RTFGroup & rGroup( GetHandler().GetCurrentGroup() );
     RTFValue::Pointer_t const pParent( lcl_SetNestedSprm(
         rGroup.m_TableCellProperties.m_Sprms, parent, id, pValue) );
-    GetHandler().SetTableCellSprm(id, pValue);
+    GetHandler().SetTableCellSprm(parent, pParent);
 }
 
 void
+RTFDestination::SetTableCellDoubleNestedAttribute(Id const grandparent,
+        Id const parent, Id const id, RTFValue::Pointer_t const& pValue)
+{
+    RTFGroup & rGroup( GetHandler().GetCurrentGroup() );
+    RTFValue::Pointer_t const pGrandParent( lcl_SetDoubleNestedAttribute(
+        rGroup.m_TableCellProperties.m_Sprms,
+        grandparent, parent, id, pValue) );
+    GetHandler().SetTableCellSprm(grandparent, pGrandParent);
+}
+
+
+void
 RTFDestination::ResetCharacterProperties()
 {
     GetHandler().ResetCharacterProperties();
diff --git a/writerfilter/source/rtftok/rtfactions.xml b/writerfilter/source/rtftok/rtfactions.xml
--- a/writerfilter/source/rtftok/rtfactions.xml
+++ b/writerfilter/source/rtftok/rtfactions.xml
@@ -719,15 +719,26 @@
 
     <!-- <ref name="clFitText"/> -->
     <!-- <ref name="clNoWrap"/> -->
-    <!-- <ref name="clpadl" tokenid="ooxml:CT_TblPrBase_tblCellMar" "ooxml:CT_TblCellMar_left"/> -->
-    <!-- <ref name="clpadt" tokenid="ooxml:CT_TblPrBase_tblCellMar" "ooxml:CT_TblCellMar_top"/> -->
-    <!-- <ref name="clpadb" tokenid="ooxml:CT_TblPrBase_tblCellMar" "ooxml:CT_TblCellMar_bottom"/> -->
-    <!-- <ref name="clpadr" tokenid="ooxml:CT_TblPrBase_tblCellMar" "ooxml:CT_TblCellMar_right
-"/> -->
-    <!-- <ref name="clpadfl"/> -->
-    <!-- <ref name="clpadft"/> -->
-    <!-- <ref name="clpadfb"/> -->
-    <!-- <ref name="clpadfr"/> -->
+    <ref name="clpadl" grandparent="ooxml:CT_TblPrBase_tblCellMar"
+      parent="ooxml:CT_TblCellMar_left" tokenid="ooxml:CT_TblWidth_w"/>
+    <ref name="clpadt" grandparent="ooxml:CT_TblPrBase_tblCellMar"
+      parent="ooxml:CT_TblCellMar_top" tokenid="ooxml:CT_TblWidth_w"/>
+    <ref name="clpadb" grandparent="ooxml:CT_TblPrBase_tblCellMar"
+      parent="ooxml:CT_TblCellMar_bottom" tokenid="ooxml:CT_TblWidth_w"/>
+    <ref name="clpadr" grandparent="ooxml:CT_TblPrBase_tblCellMar"
+      parent="ooxml:CT_TblCellMar_right" tokenid="ooxml:CT_TblWidth_w"/>
+    <ref name="clpadfl" grandparent="ooxml:CT_TblPrBase_tblCellMar"
+      parent="ooxml:CT_TblCellMar_left" tokenid="ooxml:CT_TblWidth_type"
+      tblwidthunit="true"/>
+    <ref name="clpadft" grandparent="ooxml:CT_TblPrBase_tblCellMar"
+      parent="ooxml:CT_TblCellMar_top" tokenid="ooxml:CT_TblWidth_type"
+      tblwidthunit="true"/>
+    <ref name="clpadfb" grandparent="ooxml:CT_TblPrBase_tblCellMar"
+      parent="ooxml:CT_TblCellMar_bottom" tokenid="ooxml:CT_TblWidth_type"
+      tblwidthunit="true"/>
+    <ref name="clpadfr" grandparent="ooxml:CT_TblPrBase_tblCellMar"
+      parent="ooxml:CT_TblCellMar_right" tokenid="ooxml:CT_TblWidth_type"
+      tblwidthunit="true"/>
     <!-- <ref name="clspl"/> -->
     <!-- <ref name="clspt"/> -->
     <!-- <ref name="clspb"/> -->
diff --git a/writerfilter/source/rtftok/rtfcontrols.xsl b/writerfilter/source/rtftok/rtfcontrols.xsl
--- a/writerfilter/source/rtftok/rtfcontrols.xsl
+++ b/writerfilter/source/rtftok/rtfcontrols.xsl
@@ -117,6 +117,10 @@
               <xsl:text>sal_uInt32 const color(rDestination.GetColorTableEntry(n));&#xA;</xsl:text>
               <xsl:text>RTFValue::Pointer_t const pValue(new RTFValueInt(color));&#xA;</xsl:text>
             </xsl:when>
+            <xsl:when test="@tblwidthunit">
+              <xsl:text>sal_uInt32 const unit(MapTblWidthUnit(n));&#xA;</xsl:text>
+              <xsl:text>RTFValue::Pointer_t const pValue(new RTFValueInt(unit));&#xA;</xsl:text>
+            </xsl:when>
             <xsl:otherwise>
               <xsl:text>RTFValue::Pointer_t const pValue(new RTFValueInt(n));&#xA;</xsl:text>
             </xsl:otherwise>
@@ -133,6 +137,36 @@
         </xsl:otherwise>
       </xsl:choose>
       <xsl:choose>
+        <xsl:when test="@grandparent">
+          <xsl:variable name="grandparent">
+            <xsl:call-template name="token-to-enum">
+              <xsl:with-param name="token" select="@grandparent"/>
+            </xsl:call-template>
+          </xsl:variable>
+          <xsl:variable name="parent">
+            <xsl:call-template name="token-to-enum">
+              <xsl:with-param name="token" select="@parent"/>
+            </xsl:call-template>
+          </xsl:variable>
+          <xsl:choose>
+            <xsl:when test="$kind='tablerow'">
+              <xsl:text>rDestination.SetTableRowDoubleNestedAttribute(</xsl:text>
+            </xsl:when>
+            <xsl:when test="$kind='tablecell'">
+              <xsl:text>rDestination.SetTableCellDoubleNestedAttribute(</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:text>UNKNOWN KIND: </xsl:text>
+              <xsl:value-of select="$kind"/>
+            </xsl:otherwise>
+          </xsl:choose>
+          <xsl:value-of select="$grandparent"/>
+          <xsl:text>, </xsl:text>
+          <xsl:value-of select="$parent"/>
+          <xsl:text>, </xsl:text>
+          <xsl:value-of select="$token"/>
+          <xsl:text>, pValue);&#xA;</xsl:text>
+        </xsl:when>
         <xsl:when test="@parent">
           <xsl:variable name="parent">
             <xsl:call-template name="token-to-enum">
