Commits

Vladimir Glazunov  committed f2a4741 Merge

CWS-TOOLING: integrate CWS hb33tablebylayout

  • Participants
  • Parent commits 4b025d3, 4b51bbd

Comments (0)

Files changed (8)

File sw/inc/swtable.hxx

         { return const_cast<SwTableBox*>(this)->FindEndOfRowSpan( rTable, nMaxStep ); }
 };
 
+class SwCellFrm;
+class SW_DLLPUBLIC SwTableCellInfo : public ::boost::noncopyable
+{
+    struct Impl;
+    ::std::auto_ptr<Impl> m_pImpl;
+
+    const SwCellFrm * getCellFrm() const ;
+
+public:
+    SwTableCellInfo(const SwTable * pTable);
+    ~SwTableCellInfo();
+
+    bool getNext();
+    SwRect getRect() const;
+    const SwTableBox * getTableBox() const;
+};
+
 #endif	//_SWTABLE_HXX

File sw/source/core/table/swtable.cxx

 	}
 }
 
+struct SwTableCellInfo::Impl
+{
+    const SwTable * m_pTable;
+    const SwCellFrm * m_pCellFrm;
+    const SwTabFrm * m_pTabFrm;
+    typedef ::std::set<const SwTableBox *> TableBoxes_t;
+    TableBoxes_t m_HandledTableBoxes;
+
+public:
+    Impl()
+        : m_pTable(NULL), m_pCellFrm(NULL), m_pTabFrm(NULL)
+    {
+    }
+    
+    ~Impl() {}
+
+    void setTable(const SwTable * pTable) { 
+        m_pTable = pTable; 
+        SwFrmFmt * pFrmFmt = m_pTable->GetFrmFmt();
+        SwClientIter aIter(*pFrmFmt);
+        
+        m_pTabFrm = 
+            static_cast<const SwTabFrm *>(aIter.First(TYPE(SwTabFrm)));
+
+        if (m_pTabFrm->IsFollow())
+            m_pTabFrm = m_pTabFrm->FindMaster(true);
+    }
+    const SwTable * getTable() const { return m_pTable; }
+    
+    const SwCellFrm * getCellFrm() const { return m_pCellFrm; }
+
+    const SwFrm * getNextFrmInTable(const SwFrm * pFrm);
+    const SwCellFrm * getNextCellFrm(const SwFrm * pFrm);
+    const SwCellFrm * getNextTableBoxsCellFrm(const SwFrm * pFrm);
+    bool getNext();
+};
+
+const SwFrm * SwTableCellInfo::Impl::getNextFrmInTable(const SwFrm * pFrm)
+{
+    const SwFrm * pResult = NULL;
+
+    if (((! pFrm->IsTabFrm()) || pFrm == m_pTabFrm) && pFrm->GetLower())
+        pResult = pFrm->GetLower();
+    else if (pFrm->GetNext())
+        pResult = pFrm->GetNext();
+    else 
+    {
+        while (pFrm->GetUpper() != NULL)
+        {
+            pFrm = pFrm->GetUpper();
+            
+            if (pFrm->IsTabFrm())
+            {
+                m_pTabFrm = static_cast<const SwTabFrm *>(pFrm)->GetFollow();
+                pResult = m_pTabFrm;
+                break;
+            }
+            else if (pFrm->GetNext())
+            {
+                pResult = pFrm->GetNext();
+                break;
+            }
+        }
+    }
+
+    return pResult;
+}
+
+const SwCellFrm * SwTableCellInfo::Impl::getNextCellFrm(const SwFrm * pFrm)
+{
+    const SwCellFrm * pResult = NULL;
+
+    while ((pFrm = getNextFrmInTable(pFrm)) != NULL)
+    {
+        if (pFrm->IsCellFrm())
+        {
+            pResult = static_cast<const SwCellFrm *>(pFrm);
+            break;
+        }
+    }
+
+    return pResult;
+}
+
+const SwCellFrm * SwTableCellInfo::Impl::getNextTableBoxsCellFrm(const SwFrm * pFrm)
+{
+    const SwCellFrm * pResult = NULL;
+
+    while ((pFrm = getNextCellFrm(pFrm)) != NULL)
+    {
+        const SwCellFrm * pCellFrm = static_cast<const SwCellFrm *>(pFrm);        
+        const SwTableBox * pTabBox = pCellFrm->GetTabBox();
+        TableBoxes_t::const_iterator aIt = m_HandledTableBoxes.find(pTabBox);
+
+        if (aIt == m_HandledTableBoxes.end())
+        {
+            pResult = pCellFrm;
+            m_HandledTableBoxes.insert(pTabBox);
+            break;
+        }
+    }
+
+    return pResult;
+}
+
+const SwCellFrm * SwTableCellInfo::getCellFrm() const
+{
+    return m_pImpl->getCellFrm();
+}
+
+bool SwTableCellInfo::Impl::getNext()
+{
+    if (m_pCellFrm == NULL)
+    {
+        if (m_pTabFrm != NULL)
+            m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pTabFrm);
+    }
+    else
+        m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pCellFrm);
+
+    return m_pCellFrm != NULL;
+}
+
+SwTableCellInfo::SwTableCellInfo(const SwTable * pTable)
+{
+    m_pImpl.reset(new Impl());
+    m_pImpl->setTable(pTable);
+}
+
+SwTableCellInfo::~SwTableCellInfo()
+{    
+}
+
+bool SwTableCellInfo::getNext()
+{
+    return m_pImpl->getNext();
+}
+
+SwRect SwTableCellInfo::getRect() const
+{
+    SwRect aRet;
+
+    if (getCellFrm() != NULL)
+        aRet = getCellFrm()->Frm();
+
+    return aRet;
+}
+
+const SwTableBox * SwTableCellInfo::getTableBox() const
+{
+    const SwTableBox * pRet = NULL;
+
+    if (getCellFrm() != NULL)
+        pRet = getCellFrm()->GetTabBox();
+
+    return pRet;
+}

File sw/source/filter/ww8/WW8TableInfo.cxx

 #include "precompiled_sw.hxx"
 
 #include <iostream> 
+#include <set>
 #include <stdio.h> 
 #include "WW8TableInfo.hxx"
+#include "fmtfsize.hxx"
+#include "attributeoutputbase.hxx"
 #include "swtable.hxx"
+#include "frmfmt.hxx"
 #include "pam.hxx"
 #include "ndtxt.hxx"
 #include "dbgoutsw.hxx"
 : mpParent(pParent)
 , mnCell(0)
 , mnRow(0)
+, mnShadowsBefore(0)
+, mnShadowsAfter(0)
 , mbEndOfLine(false)
 , mbEndOfCell(false)
+, mbVertMerge(false)
 , mpTableBox(NULL)
 , mpTable(NULL)
 {
     mnRow = nRow;
 }
 
+void WW8TableNodeInfoInner::setShadowsBefore(sal_uInt32 nShadowsBefore)
+{
+    mnShadowsBefore = nShadowsBefore;
+}
+
+void WW8TableNodeInfoInner::setShadowsAfter(sal_uInt32 nShadowsAfter)
+{
+    mnShadowsAfter = nShadowsAfter;
+}
+
 void WW8TableNodeInfoInner::setEndOfLine(bool bEndOfLine)
 {
     mbEndOfLine = bEndOfLine;    
     mbEndOfCell = bEndOfCell;
 }
 
+void WW8TableNodeInfoInner::setVertMerge(bool bVertMerge)
+{
+    mbVertMerge = bVertMerge;
+}
+
 void WW8TableNodeInfoInner::setTableBox(const SwTableBox * pTableBox)
 {
     mpTableBox = pTableBox;
     mpTable = pTable;
 }
 
+void WW8TableNodeInfoInner::setRect(const SwRect & rRect)
+{
+    maRect = rRect;
+}
+
 sal_uInt32 WW8TableNodeInfoInner::getDepth() const
 {
     return mnDepth;
     return mnRow;
 }
 
+sal_uInt32 WW8TableNodeInfoInner::getShadowsBefore() const
+{
+    return mnShadowsBefore;
+}
+
+sal_uInt32 WW8TableNodeInfoInner::getShadowsAfter() const
+{
+    return mnShadowsAfter;
+}
+
 bool WW8TableNodeInfoInner::isEndOfCell() const
 {
     return mbEndOfCell;
     return pResult;
 }
 
+TableBoxVectorPtr WW8TableNodeInfoInner::getTableBoxesOfRow()
+{
+    TableBoxVectorPtr pResult(new TableBoxVector);
+
+    WW8TableCellGrid::Pointer_t pCellGrid = 
+        mpParent->getParent()->getCellGridForTable(getTable(), false);
+
+    if (pCellGrid.get() == NULL)
+    {
+        const SwTableLine * pTabLine = getTableBox()->GetUpper();
+        const SwTableBoxes & rTblBoxes = pTabLine->GetTabBoxes();
+        
+        sal_uInt8 nBoxes = rTblBoxes.Count();
+        for ( sal_uInt8 n = 0; n < nBoxes; n++ )
+        {
+            pResult->push_back(rTblBoxes[n]);
+        }
+    }
+    else
+        pResult = pCellGrid->getTableBoxesOfRow(this);
+
+    return pResult;
+}
+
+GridColsPtr WW8TableNodeInfoInner::getGridColsOfRow(AttributeOutputBase & rBase)
+{
+    GridColsPtr pResult(new GridCols);
+    WidthsPtr pWidths(getWidthsOfRow());
+
+    const SwFrmFmt *pFmt = getTable()->GetFrmFmt();
+    ASSERT(pFmt,"Impossible");
+    if (!pFmt)
+        return pResult;
+    
+    const SwFmtFrmSize &rSize = pFmt->GetFrmSize();
+    unsigned long nTblSz = static_cast<unsigned long>(rSize.GetWidth());
+    
+    sal_uInt32 nPageSize = 0;
+    bool bRelBoxSize = false;
+    
+    rBase.GetTablePageSize
+        ( this, nPageSize, bRelBoxSize );
+        
+    SwTwips nSz = 0;
+    Widths::const_iterator aWidthsEnd = pWidths->end();    
+    for ( Widths::const_iterator aIt = pWidths->begin(); 
+          aIt != aWidthsEnd; 
+          aIt++)
+    {
+        nSz += *aIt;
+        SwTwips nCalc = nSz;
+        if ( bRelBoxSize )
+            nCalc = ( nCalc * nPageSize ) / nTblSz;
+        
+        pResult->push_back( nCalc );
+    }
+
+    return pResult;
+}
+
+WidthsPtr WW8TableNodeInfoInner::getWidthsOfRow()
+{
+    WidthsPtr pWidths;
+
+    WW8TableCellGrid::Pointer_t pCellGrid = 
+        mpParent->getParent()->getCellGridForTable(getTable(), false);
+
+    if (pCellGrid.get() == NULL)
+    {       
+        const SwTableBox * pTabBox = getTableBox();
+        const SwTableLine * pTabLine = pTabBox->GetUpper();
+        const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
+
+        pWidths = WidthsPtr(new Widths);
+        // number of cell written
+        sal_uInt32 nBoxes = rTabBoxes.Count();
+        if ( nBoxes > 32 )
+            nBoxes = 32;
+        
+        for (sal_uInt32 n = 0; n < nBoxes; n++)
+        {
+            const SwFrmFmt* pBoxFmt = rTabBoxes[ n ]->GetFrmFmt();
+            const SwFmtFrmSize& rLSz = pBoxFmt->GetFrmSize();
+
+            pWidths->push_back(rLSz.GetWidth());
+        }
+    }
+    else
+        pWidths = pCellGrid->getWidthsOfRow(this);
+
+    return pWidths;
+}
+
+RowSpansPtr WW8TableNodeInfoInner::getRowSpansOfRow()
+{
+    RowSpansPtr pResult(new RowSpans);
+
+    WW8TableCellGrid::Pointer_t pCellGrid = 
+        mpParent->getParent()->getCellGridForTable(getTable(), false);
+    
+    if (pCellGrid.get() == NULL)
+    {
+        const SwTableBox * pTabBox = getTableBox();
+        const SwTableLine * pTabLine = pTabBox->GetUpper();
+        const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
+
+        sal_uInt32 nBoxes = rTabBoxes.Count();
+        if (nBoxes > 32)
+            nBoxes = 32;
+        
+        for (sal_uInt32 n = 0; n < nBoxes; ++n)
+        {
+            pResult->push_back(rTabBoxes[n]->getRowSpan());
+        }
+    }
+    else
+        pResult = pCellGrid->getRowSpansOfRow(this);
+
+    return pResult;
+ }
+
 const SwTableBox * WW8TableNodeInfoInner::getTableBox() const
 {
     return mpTableBox;
     return mpTable;
 }
 
+const SwRect & WW8TableNodeInfoInner::getRect() const
+{
+    return maRect;
+}
+
 string WW8TableNodeInfoInner::toString() const
 {
     static char buffer[256];
     snprintf(buffer, sizeof(buffer), 
-             "<tableinner depth=\"%" SAL_PRIxUINT32 "\""
-             " cell=\"%" SAL_PRIxUINT32 "\""
-             " row=\"%" SAL_PRIxUINT32 "\""
+             "<tableinner depth=\"%" SAL_PRIuUINT32 "\""
+             " cell=\"%" SAL_PRIuUINT32 "\""
+             " row=\"%" SAL_PRIuUINT32 "\""
              " endOfCell=\"%s\""
-             " endOfLine=\"%s\"/>",
+             " endOfLine=\"%s\""
+             " shadowsBefore=\"%" SAL_PRIuUINT32 "\""
+             " shadowsAfter=\"%" SAL_PRIuUINT32 "\""
+             " vertMerge=\"%s\"/>",
              mnDepth, mnCell, mnRow,
              mbEndOfCell ? "yes" : "no",
-             mbEndOfLine ? "yes" : "no");
+             mbEndOfLine ? "yes" : "no",
+             mnShadowsBefore,
+             mnShadowsAfter,
+             mbVertMerge ? "yes" : "no");
     
     return string(buffer);
 }
 
 // WW8TableTextNodeInfo
 
-WW8TableNodeInfo::WW8TableNodeInfo(const SwNode * pNode)
-:
-    mnDepth(0), 
-    mpNode(pNode),
-    mpNext(NULL),
-    mpNextNode(NULL)
+WW8TableNodeInfo::WW8TableNodeInfo(WW8TableInfo * pParent, 
+                                   const SwNode * pNode)
+: mpParent(pParent),
+  mnDepth(0), 
+  mpNode(pNode),
+  mpNext(NULL),
+  mpNextNode(NULL)
 {
 }
 
 {
     static char buffer[1024];
     snprintf(buffer, sizeof(buffer), 
-             "<tableNodeInfo depth=\"%" SAL_PRIxUINT32 "\">"
-             , getDepth());
+             "<tableNodeInfo p=\"%p\" depth=\"%" SAL_PRIuUINT32 "\">"
+             ,this, getDepth());
 
     ::std::string sResult(buffer);
     
     sResult += dbg_out(*mpNode);
 #endif
 
-    sResult +="</tableNodeInfo>";
+    sResult += "</tableNodeInfo>";
     
     return sResult;
 }
 #endif
 }
 
+void WW8TableNodeInfo::setVertMerge(bool bVertMerge)
+{
+    WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
+    pInner->setVertMerge(bVertMerge);
+    
+#ifdef DEBUG
+    ::std::clog << "<vertMerge depth=\"" << mnDepth << "\">" 
+    << toString() << "</vertMerge>" << ::std::endl;
+#endif
+}
+
 void WW8TableNodeInfo::setTableBox(const SwTableBox * pTableBox)
 {
     getInnerForDepth(mnDepth)->setTableBox(pTableBox);
 #endif
 }
 
-void WW8TableNodeInfo::setNextNode(SwNode * pNode)
+void WW8TableNodeInfo::setNextNode(const SwNode * pNode)
 {
-    mpNode = pNode;
+    mpNextNode = pNode;
+}
+
+void WW8TableNodeInfo::setRect(const SwRect & rRect)
+{
+    getInnerForDepth(mnDepth)->setRect(rRect);
 }
 
 void WW8TableNodeInfo::setCell(sal_uInt32 nCell)
     getInnerForDepth(mnDepth)->setRow(nRow);
 }
 
+void WW8TableNodeInfo::setShadowsBefore(sal_uInt32 nShadowsBefore)
+{
+    getInnerForDepth(mnDepth)->setShadowsBefore(nShadowsBefore);
+}
+
+void WW8TableNodeInfo::setShadowsAfter(sal_uInt32 nShadowsAfter)
+{
+    getInnerForDepth(mnDepth)->setShadowsAfter(nShadowsAfter);
+}
+
+WW8TableInfo * WW8TableNodeInfo::getParent() const
+{
+    return mpParent;
+}
+
 sal_uInt32 WW8TableNodeInfo::getDepth() const
 {
     if (mInners.size() > 0)
     return mpNext;
 }
 
-SwNode * WW8TableNodeInfo::getNextNode() const
+const SwNode * WW8TableNodeInfo::getNextNode() const
 {
     return mpNextNode;
 }
 
+const SwRect & WW8TableNodeInfo::getRect() const
+{
+    return getInnerForDepth(mnDepth)->getRect();
+}
+
 bool WW8TableNodeInfo::isEndOfLine() const
 {
     return getInnerForDepth(mnDepth)->isEndOfLine();
 {
 }
 
+WW8TableNodeInfo *
+WW8TableInfo::processSwTableByLayout(const SwTable * pTable)
+{
+    SwTableCellInfo aTableCellInfo(pTable);
+    WW8TableNodeInfo * pPrev = NULL;
+
+    while (aTableCellInfo.getNext())
+    {
+        SwRect aRect = aTableCellInfo.getRect();
+
+#ifdef DEBUG
+        static char sBuffer[1024];        
+        ::std::clog << "<CellFrm>" << ::std::endl;
+
+        snprintf(sBuffer, sizeof(sBuffer), 
+                 "<rect top=\"%ld\" bottom=\"%ld\" left=\"%ld\" right=\"%ld\"/>",
+                 aRect.Top(), aRect.Bottom(), aRect.Left(), aRect.Right());
+        ::std::clog << sBuffer << ::std::endl;
+#endif
+        const SwTableBox * pTableBox = aTableCellInfo.getTableBox();
+        const SwStartNode * pSttNd = pTableBox->GetSttNd();
+        
+        if (pSttNd != NULL)
+        {
+            SwPaM aPam(*pSttNd, 0);
+            
+            bool bDone = false;
+            do
+            {
+                SwNode & rNode = aPam.GetPoint()->nNode.GetNode();
+
+                insertTableNodeInfo(&rNode, pTable, pTableBox, 0, 0, 1, & aRect);
+                
+                if (rNode.IsEndNode())
+                {
+                    SwEndNode * pEndNode = rNode.GetEndNode();
+                    SwStartNode * pTmpSttNd = pEndNode->StartOfSectionNode();
+                    
+                    if (pTmpSttNd == pSttNd)
+                        bDone = true;                    
+                }
+                
+                aPam.GetPoint()->nNode++;
+            }
+            while (!bDone);
+        }
+
+#ifdef DEBUG
+        ::std::clog << "</CellFrm>" << ::std::endl;
+#endif
+    }
+
+    pPrev = reorderByLayout(pTable);
+
+    return pPrev;
+}
+
 void WW8TableInfo::processSwTable(const SwTable * pTable)
 {
 #ifdef DEBUG 
     ::std::clog << "<processSwTable>" << ::std::endl;
 #endif
 
-    const SwTableLines & rLines = pTable->GetTabLines();
-    
     WW8TableNodeInfo * pPrev = NULL;
-    
-    for (USHORT n = 0; n < rLines.Count(); n++)
+        
+    SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
+    if (pFrmFmt != NULL && pTable->IsTblComplex())
     {
-        const SwTableLine * pLine = rLines[n];
+        pPrev = processSwTableByLayout(pTable);
+
+#ifdef DEBUG
+        WW8TableCellGrid::Pointer_t pCellGrid(getCellGridForTable(pTable));
+        ::std::clog << pCellGrid->toString() << ::std::endl;
+#endif
+    }
+    else
+    {
+        const SwTableLines & rLines = pTable->GetTabLines();
         
-        pPrev = processTableLine(pTable, pLine, n, 1, pPrev);
+        for (USHORT n = 0; n < rLines.Count(); n++)
+        {
+            const SwTableLine * pLine = rLines[n];
+            
+            pPrev = processTableLine(pTable, pLine, n, 1, pPrev);
+        }
+        
     }
 
     if (pPrev != NULL)
     {
         SwTableNode * pTableNode = pTable->GetTableNode();
         SwEndNode * pEndNode = pTableNode->EndOfSectionNode();
-
+        
         pPrev->setNextNode(pEndNode);
     }
-
 #ifdef DEBUG
     ::std::clog << "</processSwTable>" << ::std::endl;
 #endif
 #endif
 
     return pPrev;
-} 
+}
 
 WW8TableNodeInfo::Pointer_t
 WW8TableInfo::processTableBoxLines(const SwTableBox * pBox,
     return pNodeInfo;
 }
 
-
 WW8TableNodeInfo *
 WW8TableInfo::processTableBox(const SwTable * pTable, 
                               const SwTableBox * pBox, 
  const SwTableBox * pTableBox,
  sal_uInt32 nRow,
  sal_uInt32 nCell,
- sal_uInt32 nDepth)
+ sal_uInt32 nDepth,
+ SwRect * pRect)
 {
     WW8TableNodeInfo::Pointer_t pNodeInfo = getTableNodeInfo(pNode);
     
     if (pNodeInfo.get() == NULL)
     {
-        pNodeInfo = WW8TableNodeInfo::Pointer_t(new WW8TableNodeInfo(pNode));
+        pNodeInfo = 
+            WW8TableNodeInfo::Pointer_t(new WW8TableNodeInfo(this, pNode));
         mMap.insert(Map_t::value_type(pNode, pNodeInfo));
     }
 
 
     pNodeInfo->setCell(nCell);
     pNodeInfo->setRow(nRow);
-    
+
+    if (pRect)
+    {
+        WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable);
+        
+        pCellGrid->insert(*pRect, pNodeInfo.get());
+        pNodeInfo->setRect(*pRect);
+    }
+
 #ifdef DEBUG
     ::std::clog << pNodeInfo->toString() << ::std::endl;
 #endif
     return pNodeInfo;
 }
 
+WW8TableCellGrid::Pointer_t WW8TableInfo::getCellGridForTable
+(const SwTable * pTable, bool bCreate)
+{
+    WW8TableCellGrid::Pointer_t pResult;
+    CellGridMap_t::iterator aIt = mCellGridMap.find(pTable);
+
+    if (aIt == mCellGridMap.end())
+    {
+        if (bCreate)
+        {
+            pResult = WW8TableCellGrid::Pointer_t(new WW8TableCellGrid);
+            mCellGridMap[pTable] = pResult;
+        }
+    }
+    else
+        pResult = mCellGridMap[pTable];
+
+    return pResult;
+}
+
 WW8TableNodeInfo::Pointer_t WW8TableInfo::getTableNodeInfo
 (const SwNode * pNode)
 {
             pResult = pNextInfo->getNode();
         else 
         {
-            SwNode * pNextNode = pNodeInfo->getNextNode();
+            const SwNode * pNextNode = pNodeInfo->getNextNode();
 
             if (pNextNode != NULL)
                 pResult = pNextNode;
     return pResult;
 }
 
+bool WW8TableNodeInfo::operator < (const WW8TableNodeInfo & rInfo) const
+{
+    bool bRet = false;
+
+    if (rInfo.mpNode != NULL)
+    {
+        if (mpNode == NULL)
+        {
+            bRet = true;
+        }
+        else
+        {
+            if (mpNode->GetIndex() < rInfo.mpNode->GetIndex())
+                bRet = true;
+        }
+    }
+
+    return bRet;
 }
+
+bool CellInfo::operator < (const CellInfo & aCellInfo) const
+{
+    bool aRet = false;
+
+    if (top() < aCellInfo.top())
+        aRet = true;
+    else if (top() == aCellInfo.top())
+    {
+        if (left() < aCellInfo.left())
+            aRet = true;
+        else if (left() == aCellInfo.left())
+        {
+            if (width() < aCellInfo.width())
+                aRet = true;
+            else if (width() == aCellInfo.width())
+            {
+                if (height() < aCellInfo.height())
+                    aRet = true;
+                else if (height() == aCellInfo.height())
+                {
+                    if (aCellInfo.getTableNodeInfo() != NULL)
+                    {
+                        if (m_pNodeInfo == NULL)
+                            aRet = true;
+                        else
+                        {
+                            aRet = *m_pNodeInfo < *aCellInfo.getTableNodeInfo();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return aRet;
+}
+
+::std::string CellInfo::toString() const
+{
+    static char sBuffer[256];
+    
+    snprintf(sBuffer, sizeof(sBuffer), 
+             "<cellinfo left=\"%ld\""
+             " right=\"%ld\""
+             " top=\"%ld\""
+             " bottom=\"%ld\""
+             " node=\"%p\"/>",
+             left(),
+             right(),
+             top(),
+             bottom(),
+             m_pNodeInfo);
+    
+    return sBuffer;
+}
+
+WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable)
+{
+    WW8TableNodeInfo * pPrev = NULL;
+    WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable);
+
+#ifdef DEBUG
+    ::std::clog << pCellGrid->toString() << ::std::endl;
+#endif
+
+    pCellGrid->addShadowCells();
+    pPrev = pCellGrid->connectCells();
+
+    return pPrev;
+}
+
+WW8TableCellGrid::WW8TableCellGrid()
+{
+}
+
+WW8TableCellGrid::~WW8TableCellGrid()
+{
+}
+
+WW8TableCellGridRow::Pointer_t WW8TableCellGrid::getRow(long nTop, bool bCreate)
+{
+    WW8TableCellGridRow::Pointer_t pResult;
+
+    RowTops_t::iterator aIt = m_aRowTops.find(nTop);
+
+    if (aIt == m_aRowTops.end())
+    {
+        if (bCreate)
+        {
+            pResult = WW8TableCellGridRow::Pointer_t(new WW8TableCellGridRow);
+            m_aRows[nTop] = pResult;
+            m_aRowTops.insert(nTop);
+        }
+    }
+    else
+        pResult = m_aRows[nTop];    
+
+    return pResult;
+}
+
+WW8TableCellGrid::RowTops_t::const_iterator WW8TableCellGrid::getRowTopsBegin() const
+{
+    return m_aRowTops.begin();
+}
+
+WW8TableCellGrid::RowTops_t::const_iterator WW8TableCellGrid::getRowTopsEnd() const
+{
+    return m_aRowTops.end();
+}
+
+CellInfoMultiSet::const_iterator WW8TableCellGrid::getCellsBegin(long nTop)
+{
+    return getRow(nTop)->begin();
+}
+
+CellInfoMultiSet::const_iterator WW8TableCellGrid::getCellsEnd(long nTop)
+{
+    return getRow(nTop)->end();
+}
+
+void WW8TableCellGrid::insert(const SwRect & rRect, 
+                              WW8TableNodeInfo * pNodeInfo,
+                              unsigned long * pFmtFrmWidth)
+{
+    CellInfo aCellInfo(rRect, pNodeInfo);
+
+    if (pFmtFrmWidth != NULL)
+        aCellInfo.setFmtFrmWidth(*pFmtFrmWidth);
+
+    WW8TableCellGridRow::Pointer_t pRow = getRow(rRect.Top());
+    pRow->insert(aCellInfo);
+}
+
+void WW8TableCellGrid::addShadowCells()
+{
+#ifdef DEBUG
+    ::std::clog << "<addShadowCells>" << ::std::endl;
+#endif
+
+    RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
+
+    while (aTopsIt != getRowTopsEnd())
+    {
+#ifdef DEBUG
+        long nTop = *aTopsIt;
+        (void) nTop;
+#endif
+        CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
+        CellInfoMultiSet::const_iterator aCellEndIt = getCellsEnd(*aTopsIt);
+
+        RowSpansPtr pRowSpans(new RowSpans);
+
+        bool bBeginningOfCell = true;
+        bool bVertMerge = false;
+        SwRect aRect = aCellIt->getRect();
+        long nRowSpan = 1;
+        while (aCellIt != aCellEndIt)
+        {           
+            WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo();
+
+            if (bBeginningOfCell)
+            {
+                RowTops_t::const_iterator aRowSpanIt(aTopsIt);
+                aRowSpanIt++;                
+            
+                if (aRowSpanIt != getRowTopsEnd() && 
+                    *aRowSpanIt < aCellIt->bottom())
+                {
+                    aRect.Top(*aRowSpanIt);
+                    unsigned long nFmtFrmWidth = aCellIt->getFmtFrmWidth();
+                    insert(aRect, NULL, &nFmtFrmWidth);
+
+                    bVertMerge = true;
+                }
+                else
+                    bVertMerge = false;
+
+                nRowSpan = 1;
+                while (aRowSpanIt != getRowTopsEnd() && 
+                       *aRowSpanIt < aCellIt->bottom())
+                {
+                    aRowSpanIt++;
+                    nRowSpan++;
+                }
+                
+                if (pNodeInfo != NULL)
+                    pRowSpans->push_back(nRowSpan);
+                else
+                    pRowSpans->push_back(-nRowSpan);
+            }
+            
+            if (pNodeInfo != NULL)
+            {
+                pNodeInfo->setVertMerge(bVertMerge);
+            }
+
+            aCellIt++;
+            
+            bBeginningOfCell = (aRect.Left() != aCellIt->left());
+            aRect = aCellIt->getRect();
+        }
+        
+        WW8TableCellGridRow::Pointer_t pRow = getRow(*aTopsIt);
+        if (pRow.get() != NULL)
+            pRow->setRowSpans(pRowSpans);
+
+        aTopsIt++;
+    }
+#ifdef DEBUG
+    ::std::clog << "</addShadowCells>" << ::std::endl;
+#endif
+}
+
+WW8TableNodeInfo * WW8TableCellGrid::connectCells()
+{
+    RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
+    sal_uInt32 nRow = 0;
+    WW8TableNodeInfo * pLastNodeInfo = NULL;
+
+    while (aTopsIt != getRowTopsEnd())
+    {
+        CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
+        CellInfoMultiSet::const_iterator aCellEndIt = getCellsEnd(*aTopsIt);
+        GridColsPtr pWidths(new Widths);
+        TableBoxVectorPtr pTableBoxes(new TableBoxVector);
+        
+        sal_uInt32 nShadows = 0;
+        sal_uInt32 nCell = 0;
+        bool bBeginningOfCell = true;
+        WW8TableNodeInfo * pEndOfCellInfo = NULL;
+        sal_uInt32 nDepthInCell = 0;
+        while (aCellIt != aCellEndIt)
+        {
+            long nCellX = aCellIt->left();
+            WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo();
+            if (pNodeInfo != NULL)
+            {
+                const SwNode * pNode = pNodeInfo->getNode();
+
+                if (pNode->IsStartNode())
+                {
+                    nDepthInCell++;
+                    pEndOfCellInfo = NULL;
+                }
+
+                if (nDepthInCell == 1 && pNode->IsTxtNode())
+                    pEndOfCellInfo = pNodeInfo;
+
+                pNodeInfo->setShadowsBefore(nShadows);
+                pNodeInfo->setCell(nCell);
+                pNodeInfo->setRow(nRow);
+                if (pLastNodeInfo != NULL)
+                {
+                    pLastNodeInfo->setNext(pNodeInfo);
+                    pLastNodeInfo->setNextNode(pNode);
+                }
+                pLastNodeInfo = pNodeInfo;
+                nShadows = 0;
+
+                if (pNode->IsEndNode())
+                {
+                    nDepthInCell--;
+
+                    if (nDepthInCell == 0 && pEndOfCellInfo == NULL)
+                        pEndOfCellInfo = pNodeInfo;
+                }
+            }
+            else
+            {
+                nShadows++;
+            }
+
+            if (bBeginningOfCell)
+            {
+                pWidths->push_back(aCellIt->getFmtFrmWidth());
+                
+                if (pNodeInfo != NULL)
+                    pTableBoxes->push_back(pNodeInfo->getTableBox());
+                else
+                    pTableBoxes->push_back(NULL);
+            }
+
+            aCellIt++;
+            bBeginningOfCell = false;
+
+            if (aCellIt != aCellEndIt && aCellIt->left() != nCellX)
+            {
+                nCell++;
+                bBeginningOfCell = true;
+
+                if (pEndOfCellInfo != NULL)
+                {
+                    pEndOfCellInfo->setEndOfCell(true);
+                }
+
+                pEndOfCellInfo = NULL;
+            }
+        }
+
+        pLastNodeInfo->setShadowsAfter(nShadows);
+        
+        if (pEndOfCellInfo == NULL)
+        {
+            pEndOfCellInfo = pLastNodeInfo;
+        }
+
+        pEndOfCellInfo->setEndOfCell(true);
+        pLastNodeInfo->setEndOfLine(true);
+        
+        WW8TableCellGridRow::Pointer_t pRow(getRow(*aTopsIt));
+        pRow->setTableBoxVector(pTableBoxes);
+        pRow->setWidths(pWidths);
+
+        nShadows = 0;
+
+        aTopsIt++;
+        nRow++;
+    }
+
+    return pLastNodeInfo;
+}
+
+string WW8TableCellGrid::toString()
+{
+    string sResult = "<WW8TableCellGrid>";
+
+    RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
+    static char sBuffer[1024];
+    while (aTopsIt != getRowTopsEnd())
+    {
+        sprintf(sBuffer, "<row y=\"%ld\">", *aTopsIt);
+        sResult += sBuffer;
+
+        CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
+        CellInfoMultiSet::const_iterator aCellsEnd = getCellsEnd(*aTopsIt);
+
+        while (aCellIt != aCellsEnd)
+        {
+            snprintf(sBuffer, sizeof(sBuffer), "<cellInfo top=\"%ld\" bottom=\"%ld\" left=\"%ld\" right=\"%ld\">",
+                     aCellIt->top(), aCellIt->bottom(), aCellIt->left(), aCellIt->right());
+            sResult += sBuffer;
+
+            WW8TableNodeInfo * pInfo = aCellIt->getTableNodeInfo();
+            if (pInfo != NULL)
+                sResult += pInfo->toString();
+            else
+                sResult += "<shadow/>\n";
+
+            sResult += "</cellInfo>\n";
+            aCellIt++;
+        }
+
+        WW8TableCellGridRow::Pointer_t pRow = getRow(*aTopsIt);
+        WidthsPtr pWidths = pRow->getWidths();
+        if (pWidths != NULL)
+        {
+            sResult += "<widths>";
+
+            Widths::const_iterator aItEnd = pWidths->end();
+            for (Widths::const_iterator aIt = pWidths->begin();
+                 aIt != aItEnd;
+                 aIt++)
+            {
+                if (aIt != pWidths->begin())
+                    sResult += ", ";
+
+                snprintf(sBuffer, sizeof(sBuffer), "%" SAL_PRIxUINT32 "", *aIt);
+                sResult += sBuffer;
+            }
+
+            sResult += "</widths>";
+        }
+
+        RowSpansPtr pRowSpans = pRow->getRowSpans();
+        if (pRowSpans.get() != NULL)
+        {
+            sResult += "<rowspans>";
+
+            RowSpans::const_iterator aItEnd = pRowSpans->end();
+            for (RowSpans::const_iterator aIt = pRowSpans->begin();
+                 aIt != aItEnd;
+                 aIt++)
+            {
+                if (aIt != pRowSpans->begin())
+                    sResult += ", ";
+
+                snprintf(sBuffer, sizeof(sBuffer), "%" SAL_PRIxUINT32 "", *aIt);
+                sResult += sBuffer;
+            }
+
+            sResult += "</rowspans>";
+        }
+
+        sResult += "</row>\n";
+        aTopsIt++;
+    }
+
+    sResult += "</WW8TableCellGrid>\n";
+    
+    return sResult;
+}
+
+TableBoxVectorPtr WW8TableCellGrid::getTableBoxesOfRow
+(WW8TableNodeInfoInner * pNodeInfoInner)
+{
+    TableBoxVectorPtr pResult;
+    WW8TableCellGridRow::Pointer_t pRow = 
+        getRow(pNodeInfoInner->getRect().Top(), false);
+
+    if (pRow.get() != NULL)
+    {
+        pResult = pRow->getTableBoxVector();
+    }
+
+    return pResult;
+}
+
+WidthsPtr WW8TableCellGrid::getWidthsOfRow
+(WW8TableNodeInfoInner * pNodeInfoInner)
+{
+    GridColsPtr pResult;
+
+    WW8TableCellGridRow::Pointer_t pRow = 
+        getRow(pNodeInfoInner->getRect().Top(), false);
+
+    if (pRow.get() != NULL)
+    {
+        pResult = pRow->getWidths();
+    }
+
+    return pResult;
+} 
+
+RowSpansPtr WW8TableCellGrid::getRowSpansOfRow
+(WW8TableNodeInfoInner * pNodeInfoInner)
+{
+    RowSpansPtr pResult;
+    
+    WW8TableCellGridRow::Pointer_t pRow = 
+        getRow(pNodeInfoInner->getRect().Top(), false);
+
+    if (pRow.get() != NULL)
+    {
+        pResult = pRow->getRowSpans();
+    }
+    
+    return pResult;
+}
+
+WW8TableCellGridRow::WW8TableCellGridRow()
+: m_pCellInfos(new CellInfoMultiSet)
+{    
+}
+
+WW8TableCellGridRow::~WW8TableCellGridRow()
+{
+}
+
+void WW8TableCellGridRow::insert(const CellInfo & rCellInfo)
+{
+    m_pCellInfos->insert(rCellInfo);
+
+#ifdef DEBUG
+    ::std::clog << "<gridRowInsert>" 
+                << rCellInfo.toString() 
+                << "</gridRowInsert>"
+                << ::std::endl;
+#endif
+}
+
+CellInfoMultiSet::const_iterator WW8TableCellGridRow::begin() const
+{
+    return m_pCellInfos->begin();
+}
+
+CellInfoMultiSet::const_iterator WW8TableCellGridRow::end() const
+{
+    return m_pCellInfos->end();
+}
+
+void WW8TableCellGridRow::setTableBoxVector(TableBoxVectorPtr pTableBoxVector)
+{
+    m_pTableBoxVector = pTableBoxVector;
+}
+
+void WW8TableCellGridRow::setWidths(WidthsPtr pWidths)
+{
+    m_pWidths = pWidths;        
+}
+    
+void WW8TableCellGridRow::setRowSpans(RowSpansPtr pRowSpans)
+{
+    m_pRowSpans = pRowSpans;
+}
+
+TableBoxVectorPtr WW8TableCellGridRow::getTableBoxVector() const
+{
+    return m_pTableBoxVector;
+}
+
+WidthsPtr WW8TableCellGridRow::getWidths() const
+{
+    return m_pWidths;
+}
+
+RowSpansPtr WW8TableCellGridRow::getRowSpans() const
+{
+    return m_pRowSpans;
+}
+
+CellInfo::CellInfo(const SwRect & aRect, WW8TableNodeInfo * pNodeInfo)
+: m_aRect(aRect), m_pNodeInfo(pNodeInfo), m_nFmtFrmWidth(0)
+{
+    if (pNodeInfo != NULL)
+    {
+        const SwTableBox * pBox = pNodeInfo->getTableBox();
+        const SwFrmFmt * pFrmFmt = pBox->GetFrmFmt();
+        const SwFmtFrmSize & rSize = pFrmFmt->GetFrmSize();
+
+        m_nFmtFrmWidth = rSize.GetWidth();
+    }
+}
+
+}

File sw/source/filter/ww8/WW8TableInfo.hxx

 #include <functional>
 #include <boost/shared_ptr.hpp>
 #include <sal/types.h>
+#include <swrect.hxx>
 
 class SwTable;
 class SwTableLine;
 class SwTableBox;
 class SwNode;
 class SwWW8Writer;
+class AttributeOutputBase;
 
 namespace ww8
 {
 using namespace ::std;
 
 class WW8TableNodeInfo;
+typedef boost::shared_ptr<SwRect> SwRectPtr; 
+typedef ::std::vector<const SwTableBox *> TableBoxVector;
+typedef boost::shared_ptr<TableBoxVector> TableBoxVectorPtr;
+typedef ::std::vector<sal_uInt32> GridCols;
+typedef boost::shared_ptr<GridCols> GridColsPtr;
+typedef ::std::vector<sal_uInt32> RowSpans;
+typedef boost::shared_ptr<RowSpans> RowSpansPtr;
+typedef ::std::vector<sal_uInt32> Widths;
+typedef boost::shared_ptr<Widths> WidthsPtr;
 
 class WW8TableNodeInfoInner
 {
     sal_uInt32 mnDepth;
     sal_uInt32 mnCell;
     sal_uInt32 mnRow;
+    sal_uInt32 mnShadowsBefore;
+    sal_uInt32 mnShadowsAfter;
     bool mbEndOfLine;
     bool mbEndOfCell;
+    bool mbVertMerge;
     const SwTableBox * mpTableBox;
     const SwTable * mpTable;
+    SwRect maRect;
     
 public:
     typedef boost::shared_ptr<WW8TableNodeInfoInner> Pointer_t;
     void setDepth(sal_uInt32 nDepth);
     void setCell(sal_uInt32 nCell);
     void setRow(sal_uInt32 nRow);
+    void setShadowsBefore(sal_uInt32 nShadowsBefore);
+    void setShadowsAfter(sal_uInt32 nShadowsAfter);
     void setEndOfLine(bool bEndOfLine);
     void setEndOfCell(bool bEndOfCell);
+    void setVertMerge(bool bVertMErge);
     void setTableBox(const SwTableBox * pTableBox);
     void setTable(const SwTable * pTable);
+    void setRect(const SwRect & rRect);
     
     sal_uInt32 getDepth() const;
     sal_uInt32 getCell() const;
     sal_uInt32 getRow() const;
+    sal_uInt32 getShadowsBefore() const;
+    sal_uInt32 getShadowsAfter() const;
     bool isEndOfCell() const;
     bool isEndOfLine() const;
+    bool isVertMerge() const;
     const SwTableBox * getTableBox() const;
     const SwTable * getTable() const;
+    const SwRect & getRect() const;
     
     const SwNode * getNode() const;
 
+    TableBoxVectorPtr getTableBoxesOfRow();
+    WidthsPtr getWidthsOfRow();
+    GridColsPtr getGridColsOfRow(AttributeOutputBase & rBase);
+    RowSpansPtr getRowSpansOfRow();
+
     string toString() const;
 };
- 
+
+class CellInfo;
+typedef ::std::multiset<CellInfo, less<CellInfo> > CellInfoMultiSet;
+typedef boost::shared_ptr<CellInfoMultiSet> CellInfoMultiSetPtr;
+
+class WW8TableInfo;
 class WW8TableNodeInfo
 {
 public:
-    typedef map<sal_uInt32, WW8TableNodeInfoInner::Pointer_t, greater<sal_uInt32> > Inners_t;
+    typedef map<sal_uInt32, WW8TableNodeInfoInner::Pointer_t, 
+                greater<sal_uInt32> > Inners_t;
     
 private:
+    WW8TableInfo * mpParent;
     sal_uInt32 mnDepth;
     const SwNode * mpNode;
     Inners_t mInners;
     WW8TableNodeInfo * mpNext;
-    SwNode * mpNextNode;
-    
+    const SwNode * mpNextNode;
+
 public:
     typedef boost::shared_ptr<WW8TableNodeInfo> Pointer_t;
 
-    WW8TableNodeInfo(const SwNode * pTxtNode);
+    WW8TableNodeInfo(WW8TableInfo * pParent, const SwNode * pTxtNode);
     virtual ~WW8TableNodeInfo();
     
     void setDepth(sal_uInt32 nDepth);
     void setEndOfLine(bool bEndOfLine);
     void setEndOfCell(bool bEndOfCell);
+    void setVertMerge(bool bVertMerge);
     void setTableBox(const SwTableBox *pTableBox);
     void setTable(const SwTable * pTable);
     void setCell(sal_uInt32 nCell);
     void setRow(sal_uInt32 nRow);
+    void setShadowsBefore(sal_uInt32 nShadowsBefore);
+    void setShadowsAfter(sal_uInt32 nShadowsAfter);
     void setNext(WW8TableNodeInfo * pNext);
-    void setNextNode(SwNode * pNode);
+    void setNextNode(const SwNode * pNode);
+    void setRect(const SwRect & rRect);
     
+    WW8TableInfo * getParent() const;
     sal_uInt32 getDepth() const;
     bool isEndOfLine() const;
     bool isEndOfCell() const;
     const SwTableBox * getTableBox() const;
     const SwTable * getTable() const;
     WW8TableNodeInfo * getNext() const;
-    SwNode * getNextNode() const;
+    const SwNode * getNextNode() const;
+    const SwRect & getRect() const;
 
     const Inners_t & getInners() const;
     const WW8TableNodeInfoInner::Pointer_t getFirstInner() const;
     sal_uInt32 getRow() const;
 
     ::std::string toString() const;
+
+    bool operator < (const WW8TableNodeInfo & rInfo) const;
 };
  
 struct hashNode
     { return reinterpret_cast<size_t>(pNode); }
 };
     
+struct hashTable
+{
+    size_t operator()(const SwTable * pTable) const 
+    { return reinterpret_cast<size_t>(pTable); }
+};
+
+class WW8TableCellGridRow
+{
+    CellInfoMultiSetPtr m_pCellInfos;
+    TableBoxVectorPtr m_pTableBoxVector;
+    WidthsPtr m_pWidths;
+    RowSpansPtr m_pRowSpans;
+
+public:
+    typedef boost::shared_ptr<WW8TableCellGridRow> Pointer_t;
+    WW8TableCellGridRow();
+    ~WW8TableCellGridRow();
+
+    void insert(const CellInfo & rCellInfo);
+    CellInfoMultiSet::const_iterator begin() const;
+    CellInfoMultiSet::const_iterator end() const;
+
+    void setTableBoxVector(TableBoxVectorPtr pTableBoxVector);
+    void setWidths(WidthsPtr pGridCols);    
+    void setRowSpans(RowSpansPtr pRowSpans);
+
+    TableBoxVectorPtr getTableBoxVector() const;
+    WidthsPtr getWidths() const;
+    RowSpansPtr getRowSpans() const;
+};
+    
+class WW8TableCellGrid
+{
+    typedef ::std::set<long> RowTops_t;
+    typedef ::std::map<long, WW8TableCellGridRow::Pointer_t> Rows_t;
+
+    RowTops_t m_aRowTops;
+    Rows_t m_aRows;
+    
+    WW8TableCellGridRow::Pointer_t getRow(long nTop, bool bCreate = true);
+    RowTops_t::const_iterator getRowTopsBegin() const;
+    RowTops_t::const_iterator getRowTopsEnd() const;
+    CellInfoMultiSet::const_iterator getCellsBegin(long nTop);
+    CellInfoMultiSet::const_iterator getCellsEnd(long nTop);
+
+public:
+    typedef ::boost::shared_ptr<WW8TableCellGrid> Pointer_t;
+
+    WW8TableCellGrid();
+    ~WW8TableCellGrid();
+
+    void insert(const SwRect & rRect, WW8TableNodeInfo * pNodeInfo, 
+                unsigned long * pFmtFrmWidth = NULL);
+    void addShadowCells();
+    WW8TableNodeInfo * connectCells();
+
+    string toString();
+
+    TableBoxVectorPtr getTableBoxesOfRow(WW8TableNodeInfoInner * pNodeInfo);
+    WidthsPtr getWidthsOfRow(WW8TableNodeInfoInner * pNodeInfo);
+    RowSpansPtr getRowSpansOfRow(WW8TableNodeInfoInner * pNodeInfo);
+}; 
+
 class WW8TableInfo
 {
+    friend class WW8TableNodeInfoInner;
     typedef hash_map<const SwNode *, WW8TableNodeInfo::Pointer_t, hashNode > Map_t;
+    typedef hash_map<const SwTable *, WW8TableCellGrid::Pointer_t, hashTable > CellGridMap_t;
+
     Map_t mMap;
+    CellGridMap_t mCellGridMap;
 
     WW8TableNodeInfo *
     processTableLine(const SwTable * pTable, 
                         const SwTableBox * pTableBox,
                         sal_uInt32 nRow,
                         sal_uInt32 nCell,
-                        sal_uInt32 nDepth);
+                        sal_uInt32 nDepth,
+                        SwRect * pRect = NULL);
+
+    WW8TableCellGrid::Pointer_t getCellGridForTable(const SwTable * pTable, 
+                                                    bool bCreate = true);
     
 public: 
     typedef boost::shared_ptr<WW8TableInfo> Pointer_t;
     virtual ~WW8TableInfo();
     
     void processSwTable(const SwTable * pTable);
+    WW8TableNodeInfo * processSwTableByLayout(const SwTable * pTable);
     WW8TableNodeInfo::Pointer_t getTableNodeInfo(const SwNode * pNode);
     const SwNode * getNextNode(const SwNode * pNode);
+
+    WW8TableNodeInfo * reorderByLayout(const SwTable * pTable);
 };
  
+class CellInfo
+{
+    SwRect m_aRect;
+    WW8TableNodeInfo * m_pNodeInfo;
+    unsigned long m_nFmtFrmWidth;
+
+public:
+    CellInfo(const SwRect & aRect, WW8TableNodeInfo * pNodeInfo);
+
+    CellInfo(const CellInfo & aRectAndTableInfo)
+        : m_aRect(aRectAndTableInfo.m_aRect), 
+          m_pNodeInfo(aRectAndTableInfo.m_pNodeInfo),
+          m_nFmtFrmWidth(aRectAndTableInfo.m_nFmtFrmWidth)
+    {
+    }
+
+    ~CellInfo() {}
+
+    bool operator < (const CellInfo & aCellInfo) const;
+
+    long top() const { return m_aRect.Top(); }
+    long bottom() const { return m_aRect.Bottom(); }
+    long left() const { return m_aRect.Left(); }
+    long right() const { return m_aRect.Right(); }
+    long width() const { return m_aRect.Width(); }
+    long height() const { return m_aRect.Height(); }
+    SwRect getRect() const { return m_aRect; }
+    WW8TableNodeInfo * getTableNodeInfo() const 
+    { return m_pNodeInfo; }
+    unsigned long getFmtFrmWidth() const
+    {
+        return m_nFmtFrmWidth;
+    }
+
+    void setFmtFrmWidth(unsigned long nFmtFrmWidth)
+    {
+        m_nFmtFrmWidth = nFmtFrmWidth;
+    }
+
+    ::std::string toString() const;
+};
+
 }
 #endif // WW8_TABLE_INFO_HXX

File sw/source/filter/ww8/attributeoutputbase.hxx

 
     virtual bool AnalyzeURL( const String& rUrl, const String& rTarget, String* pLinkURL, String* pMark );
 
-    std::vector<SwTwips> GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
-
-    void GetTablePageSize( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner, sal_uInt32& rPageSize, bool& rRelBoxSize );
+    ww8::GridColsPtr GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
 
 public:
     AttributeOutputBase() {}
 
     /// Output frames.
     void OutputFlyFrame( const sw::Frame& rFmt );
+
+    void GetTablePageSize
+    ( ww8::WW8TableNodeInfoInner * pTableTextNodeInfoInner, 
+      sal_uInt32& rPageSize, bool& rRelBoxSize );
+    
 };
 
 #endif // _ATTRIBUTEOUTPUTBASE_HXX_

File sw/source/filter/ww8/wrtww8.cxx

     }
 }
 
-static sal_uInt16 lcl_TCFlags(const SwTableBox * pBox)
+static sal_uInt16 lcl_TCFlags(const SwTableBox * pBox, long nRowSpan)
 {
     sal_uInt16 nFlags = 0;
 
-    long nRowSpan = pBox->getRowSpan();
-
     if (nRowSpan > 1)
         nFlags |= (3 << 5);
     else if (nRowSpan < 0)
         nFlags |= (1 << 5);
 
-    const SwFrmFmt * pFmt = pBox->GetFrmFmt();
-    switch (pFmt->GetVertOrient().GetVertOrient())
+    if (pBox != NULL)
     {
-        case text::VertOrientation::CENTER:
-            nFlags |= (1 << 7);
-            break;
-        case text::VertOrientation::BOTTOM:
-            nFlags |= (2 << 7);
-            break;
-        default:
-            break;
+        const SwFrmFmt * pFmt = pBox->GetFrmFmt();
+        switch (pFmt->GetVertOrient().GetVertOrient())
+        {
+            case text::VertOrientation::CENTER:
+                nFlags |= (1 << 7);
+                break;
+            case text::VertOrientation::BOTTOM:
+                nFlags |= (2 << 7);
+                break;
+            default:
+                break;
+        }
     }
 
     return nFlags;
 
 void WW8AttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
 {
-    const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
-    const SwTableLine * pTabLine = pTabBox->GetUpper();
-    const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
     const SwTable * pTable = pTableTextNodeInfoInner->getTable();
     
     if ( pTable->GetRowsToRepeat() > pTableTextNodeInfoInner->getRow() )
         m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
     }
 
+    ww8::TableBoxVectorPtr pTableBoxes = 
+        pTableTextNodeInfoInner->getTableBoxesOfRow();
     // number of cell written
-    sal_uInt32 nBoxes = rTabBoxes.Count();
-    if ( nBoxes > 32 )
-        nBoxes = 32;
-        
+    sal_uInt32 nBoxes = pTableBoxes->size();
+    
     // sprm header
     m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTable );
     sal_uInt16 nSprmSize = 2 + (nBoxes + 1) * 2 + nBoxes * 20;
         }
     }
     
-    sal_uInt32 n = 0;
-    m_rWW8Export.InsUInt16( nTblOffset ); 
-   
-    std::vector<SwTwips> gridCols = GetGridCols( pTableTextNodeInfoInner );
-    for ( std::vector<SwTwips>::const_iterator it = gridCols.begin(), end = gridCols.end(); it != end; ++it )
-    {
-        m_rWW8Export.InsUInt16( static_cast<USHORT>( *it ) + nTblOffset );
-    }
+     m_rWW8Export.InsUInt16( nTblOffset );
+ 
+    ww8::GridColsPtr pGridCols = GetGridCols( pTableTextNodeInfoInner );
+    for ( ww8::GridCols::const_iterator it = pGridCols->begin(), 
+              end = pGridCols->end(); it != end; ++it )
+     {
+         m_rWW8Export.InsUInt16( static_cast<USHORT>( *it ) + nTblOffset );
+     }
+ 
+     /* TCs */
+    ww8::RowSpansPtr pRowSpans = pTableTextNodeInfoInner->getRowSpansOfRow();
+    ww8::RowSpans::const_iterator aItRowSpans = pRowSpans->begin();
+    ww8::TableBoxVector::const_iterator aIt;
+    ww8::TableBoxVector::const_iterator aItEnd = pTableBoxes->end();
     
-    /* TCs */
-    for ( n = 0; n < nBoxes; n++ )
+#ifdef DEBUG
+    size_t nRowSpans = pRowSpans->size();
+    size_t nTableBoxes = pTableBoxes->size();
+    (void) nRowSpans;
+    (void) nTableBoxes;
+#endif
+    
+    for( aIt = pTableBoxes->begin(); aIt != aItEnd; ++aIt, ++aItRowSpans)
     {
 #ifdef DEBUG
         sal_uInt16 npOCount = m_rWW8Export.pO->Count();
 #endif
         
-        SwTableBox * pTabBox1 = rTabBoxes[n];
-        const SwFrmFmt & rBoxFmt = *(pTabBox1->GetFrmFmt());
+        const SwTableBox * pTabBox1 = *aIt;
+        const SwFrmFmt * pBoxFmt = NULL;
+        if (pTabBox1 != NULL)
+            pBoxFmt = pTabBox1->GetFrmFmt();
+        
         if ( m_rWW8Export.bWrtWW8 )
         {
-            sal_uInt16 nFlags = lcl_TCFlags(pTabBox1);            
-            m_rWW8Export.InsUInt16( nFlags );
+            sal_uInt16 nFlags = 
+                lcl_TCFlags(pTabBox1, *aItRowSpans);
+             m_rWW8Export.InsUInt16( nFlags );
         }
         
         static BYTE aNullBytes[] = { 0x0, 0x0 };
         
         m_rWW8Export.pO->Insert( aNullBytes, 2, m_rWW8Export.pO->Count() );   // dummy
-        m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, rBoxFmt.GetBox() ); // 8/16 Byte
+        if (pBoxFmt != NULL)
+        {
+            const SvxBoxItem & rBoxItem = pBoxFmt->GetBox();
+            
+            m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, &rBoxItem ); // 8/16 Byte
+        }
+        else
+            m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, NULL); // 8/16 Byte
         
 #ifdef DEBUG
-        ::std::clog << "<tclength>" << m_rWW8Export.pO->Count() - npOCount << "</tclength>"
-        << ::std::endl;
+        ::std::clog << "<tclength>" << m_rWW8Export.pO->Count() - npOCount << "</tclength>" 
+                    << ::std::endl;
 #endif
     }
 }
 
-std::vector<SwTwips> AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+ww8::GridColsPtr AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
 {
-    std::vector<SwTwips> gridCols;
-
-    const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
-    const SwTableLine * pTabLine = pTabBox->GetUpper();
-    const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
-    const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
-    
-    // number of cell written
-    sal_uInt32 nBoxes = rTabBoxes.Count();
-    if ( nBoxes > 32 )
-        nBoxes = 32;
-
-    const SwFrmFmt *pFmt = pTable->GetFrmFmt();
-    ASSERT(pFmt,"Impossible");
-    if (!pFmt)
-        return gridCols;
-
-    const SwFmtFrmSize &rSize = pFmt->GetFrmSize();
-    unsigned long nTblSz = static_cast<unsigned long>(rSize.GetWidth());
-
-    sal_uInt32 nPageSize = 0;
-    bool bRelBoxSize = false;
-
-    GetTablePageSize( pTableTextNodeInfoInner, nPageSize, bRelBoxSize );
-
-    SwTwips nSz = 0;
-    for ( sal_uInt32 n = 0; n < nBoxes; n++ )
-    {
-        const SwFrmFmt* pBoxFmt = rTabBoxes[ n ]->GetFrmFmt();
-        const SwFmtFrmSize& rLSz = pBoxFmt->GetFrmSize();
-        nSz += rLSz.GetWidth();
-        SwTwips nCalc = nSz;
-        if ( bRelBoxSize )
-            nCalc = ( nCalc * nPageSize ) / nTblSz;
-
-        gridCols.push_back( nCalc );
-    }
-
-    return gridCols;
+    return pTableTextNodeInfoInner->getGridColsOfRow(*this);
 }
-
-void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner, sal_uInt32& rPageSize, bool& rRelBoxSize )
+ 
+void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner * pTableTextNodeInfoInner, sal_uInt32& rPageSize, bool& rRelBoxSize )
 {
     sal_uInt32 nPageSize = 0;
 
         }
         else
         {
-            ::std::clog << "<already-done><which>" << dbg_out(*pNd) 
-                        << "</which><nodes>" << ::std::endl;
-            
-            SwNodeDeque::const_iterator aEnd = aNodeDeque.end();
-            
-            for (SwNodeDeque::const_iterator aIt = aNodeDeque.begin();
-                 aIt != aEnd; aIt++)
-            {
-                ::std::clog << dbg_out(**aIt) << ::std::endl;
-            }
-
-            ::std::clog << "</nodes></already-done>" << ::std::endl;
+            ::std::clog << "<already-done>" << dbg_out(*pNd) << "</already-done>" << ::std::endl;
         }
 #endif
 
                 AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
             }
         }
+        else if ( pNd->IsStartNode() )
+        {
+            OutputStartNode( *pNd->GetStartNode() );
+        }
         else if ( pNd->IsEndNode() )
         {
             OutputEndNode( *pNd->GetEndNode() );
 
     m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );                       // leeren
     
+    sal_uInt32 nShadowsBefore = pNodeInfoInner->getShadowsBefore();
+    if (nShadowsBefore > 0)
+    {
+        ww8::WW8TableNodeInfoInner::Pointer_t
+            pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL));
+
+        pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
+        pTmpNodeInfoInner->setEndOfCell(true);
+
+        for (sal_uInt32 n = 0; n < nShadowsBefore; ++n)
+        {
+            m_rWW8Export.WriteCR(pTmpNodeInfoInner);
+            
+            m_rWW8Export.pO->Insert( (BYTE*)&nStyle, 2, 
+                                     m_rWW8Export.pO->Count() );     // Style #
+            TableInfoCell(pTmpNodeInfoInner);
+            m_rWW8Export.pPapPlc->AppendFkpEntry
+                ( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+                  m_rWW8Export.pO->GetData() );
+            
+            m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );                       // leeren
+        }
+    }
+
     if (pNodeInfoInner->isEndOfCell())
     {
 #ifdef DEBUG
         m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );                       // leeren
     }
     
+    sal_uInt32 nShadowsAfter = pNodeInfoInner->getShadowsAfter();
+    if (nShadowsAfter > 0)
+    {
+        ww8::WW8TableNodeInfoInner::Pointer_t
+            pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL));
+        
+        pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
+        pTmpNodeInfoInner->setEndOfCell(true);
+
+        for (sal_uInt32 n = 0; n < nShadowsAfter; ++n)
+        {
+            m_rWW8Export.WriteCR(pTmpNodeInfoInner);
+            
+            m_rWW8Export.pO->Insert( (BYTE*)&nStyle, 2, m_rWW8Export.pO->Count() );     // Style #
+            TableInfoCell(pTmpNodeInfoInner);
+            m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+                                                  m_rWW8Export.pO->GetData() );
+            
+            m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );                       // leeren
+        }
+    }
+
     if (pNodeInfoInner->isEndOfLine())
     {
 #ifdef DEBUG
 #endif
 }
 
+void MSWordExportBase::OutputStartNode( const SwStartNode & rNode)
+{
+#ifdef DEBUG
+    ::std::clog << "<OutWW8_SwStartNode>" << dbg_out(&rNode) << ::std::endl;
+#endif
+
+    ww8::WW8TableNodeInfo::Pointer_t pNodeInfo = 
+        mpTableInfo->getTableNodeInfo( &rNode );
+
+    if (pNodeInfo.get() != NULL)
+    {
+#ifdef DEBUG
+        ::std::clog << pNodeInfo->toString() << ::std::endl;
+#endif
+        
+        const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
+        ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aIt(aInners.rbegin());
+        ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aEnd(aInners.rend());
+        while (aIt != aEnd)
+        {
+            ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
+                        
+            AttrOutput().TableNodeInfoInner(pInner);
+            aIt++;
+        }
+    }
+#ifdef DEBUG
+    ::std::clog << "</OutWW8_SwStartNode>" << ::std::endl;
+#endif
+}
+
 void MSWordExportBase::OutputEndNode( const SwEndNode &rNode )
 {
 #ifdef DEBUG
 
     ww8::WW8TableNodeInfo::Pointer_t pNodeInfo = mpTableInfo->getTableNodeInfo( &rNode );
     
-    if (pNodeInfo)
-    {        
-        if (pNodeInfo.get() != NULL)
-        { 
-#ifdef DEBUG            
-            ::std::clog << pNodeInfo->toString() << ::std::endl;
+    if (pNodeInfo.get() != NULL)
+     {
+#ifdef DEBUG
+        ::std::clog << pNodeInfo->toString() << ::std::endl;
 #endif
-            
-            const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
-            ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt(aInners.begin());
-            ww8::WW8TableNodeInfo::Inners_t::const_iterator aEnd(aInners.end());
-            while (aIt != aEnd)
-            {
-                ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
-                AttrOutput().TableNodeInfoInner(pInner);
-                aIt++;
-            }
-        }        
-    }
+        
+        const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
+        ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt(aInners.begin());
+        ww8::WW8TableNodeInfo::Inners_t::const_iterator aEnd(aInners.end());
+        while (aIt != aEnd)
+         {
+            ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
+            AttrOutput().TableNodeInfoInner(pInner);
+            aIt++;
+         }
+     }
 #ifdef DEBUG
     ::std::clog << "</OutWW8_SwEndNode>" << ::std::endl;
 #endif

File sw/source/filter/ww8/wrtww8.hxx

     virtual bool DisallowInheritingOutlineNumbering(const SwFmt &rFmt) = 0;
 
 protected:
+    /// Output SwStartNode
+    virtual void OutputStartNode( const SwStartNode& );
+
     /// Output SwEndNode
     virtual void OutputEndNode( const SwEndNode& );
 
                                      const SwPageDesc* pNewPgDesc = 0 );
 
     void Out_SwFmtBox(const SvxBoxItem& rBox, bool bShadow);
-    void Out_SwFmtTableBox( WW8Bytes& rO, const SvxBoxItem& rBox );
+    void Out_SwFmtTableBox( WW8Bytes& rO, const SvxBoxItem * rBox );
     BYTE TransCol( const Color& rCol );
     bool TransBrush(const Color& rCol, WW8_SHD& rShd);
     WW8_BRC TranslateBorderLine(const SvxBorderLine& pLine,

File sw/source/filter/ww8/ww8atr.cxx

 // ( Tabellenumrandungen fransen sonst aus )
 // Ein WW8Bytes-Ptr wird als Ausgabe-Parameter uebergeben
 
-void WW8Export::Out_SwFmtTableBox( WW8Bytes& rO, const SvxBoxItem& rBox )
+void WW8Export::Out_SwFmtTableBox( WW8Bytes& rO, const SvxBoxItem * pBox )
 {
     // moeglich und vielleicht besser waere 0xffff
     static const USHORT aBorders[] =
     {
         BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
     };
+    static const SvxBorderLine aBorderLine;
+
     const USHORT* pBrd = aBorders;
     for( int i = 0; i < 4; ++i, ++pBrd )
     {