LCOV - code coverage report
Current view: top level - sw/source/filter/xml - xmltbli.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 737 1180 62.5 %
Date: 2014-11-03 Functions: 90 123 73.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "hintids.hxx"
      21             : 
      22             : #include <limits.h>
      23             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      24             : #include <com/sun/star/text/XTextTable.hpp>
      25             : #include <com/sun/star/table/XCellRange.hpp>
      26             : #include <svl/itemset.hxx>
      27             : #include <svl/zformat.hxx>
      28             : #include <sax/tools/converter.hxx>
      29             : #include <xmloff/xmlnmspe.hxx>
      30             : #include <xmloff/xmltkmap.hxx>
      31             : #include <xmloff/nmspmap.hxx>
      32             : 
      33             : #include <xmloff/families.hxx>
      34             : #include <xmloff/xmluconv.hxx>
      35             : #include <xmloff/i18nmap.hxx>
      36             : #include <editeng/protitem.hxx>
      37             : #include "poolfmt.hxx"
      38             : #include "fmtfsize.hxx"
      39             : #include "fmtornt.hxx"
      40             : #include "fmtfordr.hxx"
      41             : #include "doc.hxx"
      42             : #include <IDocumentFieldsAccess.hxx>
      43             : #include <IDocumentLayoutAccess.hxx>
      44             : #include <IDocumentStylePoolAccess.hxx>
      45             : #include "swtable.hxx"
      46             : #include "swtblfmt.hxx"
      47             : #include "pam.hxx"
      48             : #include "unotbl.hxx"
      49             : #include "unotextrange.hxx"
      50             : #include "unocrsr.hxx"
      51             : #include "cellatr.hxx"
      52             : #include "swddetbl.hxx"
      53             : #include "ddefld.hxx"
      54             : #include <sfx2/linkmgr.hxx>
      55             : #include "xmlimp.hxx"
      56             : #include "xmltbli.hxx"
      57             : #include <vcl/svapp.hxx>
      58             : #include <osl/mutex.hxx>
      59             : #include "ndtxt.hxx"
      60             : 
      61             : using namespace ::com::sun::star;
      62             : using namespace ::com::sun::star::uno;
      63             : using namespace ::com::sun::star::lang;
      64             : using namespace ::com::sun::star::text;
      65             : using namespace ::com::sun::star::frame;
      66             : using namespace ::com::sun::star::table;
      67             : using namespace ::com::sun::star::xml::sax;
      68             : using namespace ::xmloff::token;
      69             : using ::boost::unordered_map;
      70             : 
      71             : enum SwXMLTableElemTokens
      72             : {
      73             :     XML_TOK_TABLE_HEADER_COLS,
      74             :     XML_TOK_TABLE_COLS,
      75             :     XML_TOK_TABLE_COL,
      76             :     XML_TOK_TABLE_HEADER_ROWS,
      77             :     XML_TOK_TABLE_ROWS,
      78             :     XML_TOK_TABLE_ROW,
      79             :     XML_TOK_OFFICE_DDE_SOURCE,
      80             :     XML_TOK_TABLE_ELEM_END=XML_TOK_UNKNOWN
      81             : };
      82             : 
      83             : enum SwXMLTableCellAttrTokens
      84             : {
      85             :     XML_TOK_TABLE_XMLID,
      86             :     XML_TOK_TABLE_STYLE_NAME,
      87             :     XML_TOK_TABLE_NUM_COLS_SPANNED,
      88             :     XML_TOK_TABLE_NUM_ROWS_SPANNED,
      89             :     XML_TOK_TABLE_NUM_COLS_REPEATED,
      90             :     XML_TOK_TABLE_FORMULA,
      91             :     XML_TOK_TABLE_VALUE,
      92             :     XML_TOK_TABLE_TIME_VALUE,
      93             :     XML_TOK_TABLE_DATE_VALUE,
      94             :     XML_TOK_TABLE_BOOLEAN_VALUE,
      95             :     XML_TOK_TABLE_PROTECTED,
      96             :     XML_TOK_TABLE_STRING_VALUE,
      97             :     XML_TOK_TABLE_VALUE_TYPE,
      98             :     XML_TOK_TABLE_CELL_ATTR_END=XML_TOK_UNKNOWN
      99             : };
     100             : 
     101             : static SvXMLTokenMapEntry aTableElemTokenMap[] =
     102             : {
     103             :     { XML_NAMESPACE_TABLE, XML_TABLE_HEADER_COLUMNS,
     104             :             XML_TOK_TABLE_HEADER_COLS },
     105             :     { XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS,           XML_TOK_TABLE_COLS },
     106             :     { XML_NAMESPACE_TABLE, XML_TABLE_COLUMN,            XML_TOK_TABLE_COL },
     107             :     { XML_NAMESPACE_TABLE, XML_TABLE_HEADER_ROWS,
     108             :             XML_TOK_TABLE_HEADER_ROWS },
     109             :     { XML_NAMESPACE_TABLE, XML_TABLE_ROWS,              XML_TOK_TABLE_ROWS },
     110             :     { XML_NAMESPACE_TABLE, XML_TABLE_ROW,               XML_TOK_TABLE_ROW },
     111             :     { XML_NAMESPACE_OFFICE, XML_DDE_SOURCE,
     112             :             XML_TOK_OFFICE_DDE_SOURCE },
     113             : 
     114             :     // There are slight differences between <table:table-columns> and
     115             :     // <table:table-columns-groups>. However, none of these are
     116             :     // supported in Writer (they are Calc-only features), so we
     117             :     // support column groups by simply using the <table:table-columns>
     118             :     // token for column groups, too.
     119             :     { XML_NAMESPACE_TABLE, XML_TABLE_COLUMN_GROUP,      XML_TOK_TABLE_COLS },
     120             : 
     121             :     XML_TOKEN_MAP_END
     122             : };
     123             : 
     124             : static SvXMLTokenMapEntry aTableCellAttrTokenMap[] =
     125             : {
     126             :     { XML_NAMESPACE_XML, XML_ID, XML_TOK_TABLE_XMLID },
     127             :     { XML_NAMESPACE_TABLE, XML_STYLE_NAME, XML_TOK_TABLE_STYLE_NAME },
     128             :     { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_SPANNED, XML_TOK_TABLE_NUM_COLS_SPANNED },
     129             :     { XML_NAMESPACE_TABLE, XML_NUMBER_ROWS_SPANNED, XML_TOK_TABLE_NUM_ROWS_SPANNED },
     130             :     { XML_NAMESPACE_TABLE, XML_NUMBER_COLUMNS_REPEATED, XML_TOK_TABLE_NUM_COLS_REPEATED },
     131             :     { XML_NAMESPACE_TABLE, XML_FORMULA, XML_TOK_TABLE_FORMULA },
     132             :     { XML_NAMESPACE_OFFICE, XML_VALUE, XML_TOK_TABLE_VALUE },
     133             :     { XML_NAMESPACE_OFFICE, XML_TIME_VALUE, XML_TOK_TABLE_TIME_VALUE },
     134             :     { XML_NAMESPACE_OFFICE, XML_DATE_VALUE, XML_TOK_TABLE_DATE_VALUE },
     135             :     { XML_NAMESPACE_OFFICE, XML_BOOLEAN_VALUE, XML_TOK_TABLE_BOOLEAN_VALUE },
     136             :     { XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TOK_TABLE_PROTECTED },
     137             :     { XML_NAMESPACE_TABLE, XML_PROTECT, XML_TOK_TABLE_PROTECTED }, // for backwards compatibility with SRC629 (and before)
     138             :     { XML_NAMESPACE_OFFICE, XML_STRING_VALUE, XML_TOK_TABLE_STRING_VALUE },
     139             :     { XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_TOK_TABLE_VALUE_TYPE },
     140             :     XML_TOKEN_MAP_END
     141             : };
     142             : 
     143         526 : const SvXMLTokenMap& SwXMLImport::GetTableElemTokenMap()
     144             : {
     145         526 :     if( !pTableElemTokenMap )
     146          54 :         pTableElemTokenMap = new SvXMLTokenMap( aTableElemTokenMap );
     147             : 
     148         526 :     return *pTableElemTokenMap;
     149             : }
     150             : 
     151        2156 : const SvXMLTokenMap& SwXMLImport::GetTableCellAttrTokenMap()
     152             : {
     153        2156 :     if( !pTableCellAttrTokenMap )
     154          54 :         pTableCellAttrTokenMap = new SvXMLTokenMap( aTableCellAttrTokenMap );
     155             : 
     156        2156 :     return *pTableCellAttrTokenMap;
     157             : }
     158             : 
     159        1058 : class SwXMLTableCell_Impl
     160             : {
     161             :     OUString aStyleName;
     162             : 
     163             :     OUString mXmlId;
     164             :     OUString m_StringValue;
     165             : 
     166             :     OUString sFormula;  // cell formula; valid if length > 0
     167             :     double dValue;      // formula value
     168             : 
     169             :     SvXMLImportContextRef   xSubTable;
     170             : 
     171             :     const SwStartNode *pStartNode;
     172             :     sal_uInt32 nRowSpan;
     173             :     sal_uInt32 nColSpan;
     174             : 
     175             :     bool bProtected : 1;
     176             :     bool bHasValue; // determines whether dValue attribute is valid
     177             :     bool mbCovered;
     178             :     bool m_bHasStringValue;
     179             : 
     180             : public:
     181             : 
     182        1058 :     SwXMLTableCell_Impl( sal_uInt32 nRSpan=1UL, sal_uInt32 nCSpan=1UL ) :
     183             :         dValue( 0.0 ),
     184             :         pStartNode( 0 ),
     185             :         nRowSpan( nRSpan ),
     186             :         nColSpan( nCSpan ),
     187             :         bProtected( false ),
     188             :         bHasValue( false ),
     189             :         mbCovered( false )
     190        1058 :         , m_bHasStringValue(false)
     191        1058 :         {}
     192             : 
     193             :     inline void Set( const OUString& rStyleName,
     194             :                       sal_uInt32 nRSpan, sal_uInt32 nCSpan,
     195             :                      const SwStartNode *pStNd, SwXMLTableContext *pTable,
     196             :                      bool bProtect,
     197             :                      const OUString* pFormula,
     198             :                      bool bHasValue,
     199             :                      bool bCovered,
     200             :                      double dVal,
     201             :                      OUString const*const pStringValue,
     202             :                      OUString const& i_rXmlId);
     203             : 
     204        2008 :     bool IsUsed() const { return pStartNode!=0 ||
     205        2008 :                                      xSubTable.Is() || bProtected;}
     206             : 
     207        1010 :     sal_uInt32 GetRowSpan() const { return nRowSpan; }
     208           0 :     void SetRowSpan( sal_uInt32 nSet ) { nRowSpan = nSet; }
     209        2080 :     sal_uInt32 GetColSpan() const { return nColSpan; }
     210        1010 :     const OUString& GetStyleName() const { return aStyleName; }
     211        2020 :     const OUString& GetFormula() const { return sFormula; }
     212          24 :     double GetValue() const { return dValue; }
     213        4040 :     bool HasValue() const { return bHasValue; }
     214        2020 :     bool IsProtected() const { return bProtected; }
     215        1010 :     bool IsCovered() const { return mbCovered; }
     216        2008 :     bool HasStringValue() const { return m_bHasStringValue; }
     217           2 :     OUString const* GetStringValue() const {
     218           2 :         return (m_bHasStringValue) ? &m_StringValue : 0;
     219             :     }
     220             : 
     221        5526 :     const SwStartNode *GetStartNode() const { return pStartNode; }
     222             :     inline void SetStartNode( const SwStartNode *pSttNd );
     223             : 
     224             :     inline SwXMLTableContext *GetSubTable() const;
     225             : 
     226             :     inline void Dispose();
     227             : };
     228             : 
     229        1058 : inline void SwXMLTableCell_Impl::Set( const OUString& rStyleName,
     230             :                                       sal_uInt32 nRSpan, sal_uInt32 nCSpan,
     231             :                                       const SwStartNode *pStNd,
     232             :                                       SwXMLTableContext *pTable,
     233             :                                       bool bProtect,
     234             :                                       const OUString* pFormula,
     235             :                                       bool bHasVal,
     236             :                                       bool bCov,
     237             :                                       double dVal,
     238             :                                       OUString const*const pStringValue,
     239             :                                       OUString const& i_rXmlId )
     240             : {
     241        1058 :     aStyleName = rStyleName;
     242        1058 :     nRowSpan = nRSpan;
     243        1058 :     nColSpan = nCSpan;
     244        1058 :     pStartNode = pStNd;
     245        1058 :     xSubTable = pTable;
     246        1058 :     dValue = dVal;
     247        1058 :     bHasValue = bHasVal;
     248        1058 :     mbCovered = bCov;
     249        1058 :     if (pStringValue)
     250             :     {
     251           2 :         m_StringValue = *pStringValue;
     252             :     }
     253        1058 :     m_bHasStringValue = (pStringValue != 0);
     254        1058 :     bProtected = bProtect;
     255             : 
     256        1058 :     if (!mbCovered) // ensure uniqueness
     257             :     {
     258         998 :         mXmlId = i_rXmlId;
     259             :     }
     260             : 
     261             :     // set formula, if valid
     262        1058 :     if (pFormula != NULL)
     263             :     {
     264        1058 :         sFormula = *pFormula;
     265             :     }
     266        1058 : }
     267             : 
     268          12 : inline void SwXMLTableCell_Impl::SetStartNode( const SwStartNode *pSttNd )
     269             : {
     270          12 :     pStartNode = pSttNd;
     271          12 :     xSubTable = 0;
     272          12 : }
     273             : 
     274           0 : inline SwXMLTableContext *SwXMLTableCell_Impl::GetSubTable() const
     275             : {
     276           0 :     return (SwXMLTableContext *)&xSubTable;
     277             : }
     278             : 
     279        1058 : inline void SwXMLTableCell_Impl::Dispose()
     280             : {
     281        1058 :     if( xSubTable.Is() )
     282           0 :         xSubTable = 0;
     283        1058 : }
     284             : 
     285             : typedef boost::ptr_vector<SwXMLTableCell_Impl> SwXMLTableCells_Impl;
     286             : 
     287             : class SwXMLTableRow_Impl
     288             : {
     289             :     OUString aStyleName;
     290             :     OUString aDfltCellStyleName;
     291             :     OUString mXmlId;
     292             : 
     293             :     SwXMLTableCells_Impl aCells;
     294             : 
     295             :     bool bSplitable;
     296             : 
     297             : public:
     298             : 
     299             :     SwXMLTableRow_Impl( const OUString& rStyleName, sal_uInt32 nCells,
     300             :                         const OUString *pDfltCellStyleName = 0,
     301             :                         const OUString& i_rXmlId = OUString() );
     302         258 :     ~SwXMLTableRow_Impl() {}
     303             : 
     304             :     inline SwXMLTableCell_Impl *GetCell( sal_uInt32 nCol );
     305             : 
     306             :     inline void Set( const OUString& rStyleName,
     307             :                      const OUString& rDfltCellStyleName,
     308             :                      const OUString& i_rXmlId );
     309             : 
     310             :     void Expand( sal_uInt32 nCells, bool bOneCell );
     311             : 
     312        1010 :     void SetSplitable( bool bSet ) { bSplitable = bSet; }
     313           0 :     bool IsSplitable() const { return bSplitable; }
     314             : 
     315         258 :     const OUString& GetStyleName() const { return aStyleName; }
     316         204 :     const OUString& GetDefaultCellStyleName() const { return aDfltCellStyleName; }
     317             : 
     318             :     void Dispose();
     319             : };
     320             : 
     321         258 : SwXMLTableRow_Impl::SwXMLTableRow_Impl( const OUString& rStyleName,
     322             :                                         sal_uInt32 nCells,
     323             :                                         const OUString *pDfltCellStyleName,
     324             :                                         const OUString& i_rXmlId ) :
     325             :     aStyleName( rStyleName ),
     326             :     mXmlId( i_rXmlId ),
     327         258 :     bSplitable( false )
     328             : {
     329         258 :     if( pDfltCellStyleName  )
     330         252 :         aDfltCellStyleName = *pDfltCellStyleName;
     331             :     OSL_ENSURE( nCells <= USHRT_MAX,
     332             :             "SwXMLTableRow_Impl::SwXMLTableRow_Impl: too many cells" );
     333         258 :     if( nCells > USHRT_MAX )
     334           0 :         nCells = USHRT_MAX;
     335             : 
     336        1316 :     for( sal_uInt32 i=0U; i<nCells; ++i )
     337             :     {
     338        1058 :         aCells.push_back( new SwXMLTableCell_Impl );
     339             :     }
     340         258 : }
     341             : 
     342        4172 : inline SwXMLTableCell_Impl *SwXMLTableRow_Impl::GetCell( sal_uInt32 nCol )
     343             : {
     344             :     OSL_ENSURE( nCol < USHRT_MAX,
     345             :             "SwXMLTableRow_Impl::GetCell: column number is to big" );
     346             :     // #i95726# - some fault tolerance
     347             :     OSL_ENSURE( nCol < aCells.size(),
     348             :             "SwXMLTableRow_Impl::GetCell: column number is out of bound" );
     349        4172 :     return nCol < aCells.size() ? &aCells[nCol] : 0;
     350             : }
     351             : 
     352           0 : void SwXMLTableRow_Impl::Expand( sal_uInt32 nCells, bool bOneCell )
     353             : {
     354             :     OSL_ENSURE( nCells <= USHRT_MAX,
     355             :             "SwXMLTableRow_Impl::Expand: too many cells" );
     356           0 :     if( nCells > USHRT_MAX )
     357           0 :         nCells = USHRT_MAX;
     358             : 
     359           0 :     sal_uInt32 nColSpan = nCells - aCells.size();
     360           0 :     for( size_t i=aCells.size(); i<nCells; ++i )
     361             :     {
     362             :         aCells.push_back( new SwXMLTableCell_Impl( 1UL,
     363           0 :                                                 bOneCell ? nColSpan : 1UL ) );
     364           0 :         nColSpan--;
     365             :     }
     366             : 
     367             :     OSL_ENSURE( nCells<=aCells.size(),
     368             :             "SwXMLTableRow_Impl::Expand: wrong number of cells" );
     369           0 : }
     370             : 
     371           6 : inline void SwXMLTableRow_Impl::Set( const OUString& rStyleName,
     372             :                                      const OUString& rDfltCellStyleName,
     373             :                                      const OUString& i_rXmlId )
     374             : {
     375           6 :     aStyleName = rStyleName;
     376           6 :     aDfltCellStyleName = rDfltCellStyleName;
     377           6 :     mXmlId = i_rXmlId;
     378           6 : }
     379             : 
     380         258 : void SwXMLTableRow_Impl::Dispose()
     381             : {
     382        1316 :     for( size_t i=0; i < aCells.size(); ++i )
     383        1058 :         aCells[i].Dispose();
     384         258 : }
     385             : 
     386             : class SwXMLTableCellContext_Impl : public SvXMLImportContext
     387             : {
     388             :     OUString aStyleName;
     389             :     OUString sFormula;
     390             :     OUString sSaveParaDefault;
     391             :     OUString mXmlId;
     392             :     OUString m_StringValue;
     393             : 
     394             :     SvXMLImportContextRef   xMyTable;
     395             : 
     396             :     double fValue;
     397             :     bool bHasValue;
     398             :     bool     m_bHasStringValue;
     399             :     bool     m_bValueTypeIsString;
     400             :     bool bProtect;
     401             : 
     402             :     sal_uInt32                  nRowSpan;
     403             :     sal_uInt32                  nColSpan;
     404             :     sal_uInt32                  nColRepeat;
     405             : 
     406             :     bool                    bHasTextContent : 1;
     407             :     bool                    bHasTableContent : 1;
     408             : 
     409        4026 :     SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
     410             : 
     411        1032 :     bool HasContent() const { return bHasTextContent || bHasTableContent; }
     412             :     inline void _InsertContent();
     413             :     inline void InsertContent();
     414             :     inline void InsertContentIfNotThere();
     415             :     inline void InsertContent( SwXMLTableContext *pTable );
     416             : 
     417             : public:
     418             : 
     419             :     SwXMLTableCellContext_Impl(
     420             :             SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
     421             :             const Reference< xml::sax::XAttributeList > & xAttrList,
     422             :             SwXMLTableContext *pTable );
     423             : 
     424             :     virtual ~SwXMLTableCellContext_Impl();
     425             : 
     426             :     virtual SvXMLImportContext *CreateChildContext(
     427             :             sal_uInt16 nPrefix, const OUString& rLocalName,
     428             :             const Reference< xml::sax::XAttributeList > & xAttrList ) SAL_OVERRIDE;
     429             :     virtual void EndElement() SAL_OVERRIDE;
     430             : 
     431        2156 :     SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
     432             : };
     433             : 
     434         998 : SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl(
     435             :         SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
     436             :         const Reference< xml::sax::XAttributeList > & xAttrList,
     437             :         SwXMLTableContext *pTable ) :
     438             :     SvXMLImportContext( rImport, nPrfx, rLName ),
     439             :     sFormula(),
     440             :     xMyTable( pTable ),
     441             :     fValue( 0.0 ),
     442             :     bHasValue( false ),
     443             :     m_bHasStringValue(false),
     444             :     m_bValueTypeIsString(false),
     445             :     bProtect( false ),
     446             :     nRowSpan( 1UL ),
     447             :     nColSpan( 1UL ),
     448             :     nColRepeat( 1UL ),
     449             :     bHasTextContent( false ),
     450         998 :     bHasTableContent( false )
     451             : {
     452         998 :     sSaveParaDefault = GetImport().GetTextImport()->GetCellParaStyleDefault();
     453         998 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     454        3154 :     for( sal_Int16 i=0; i < nAttrCount; i++ )
     455             :     {
     456        2156 :         const OUString& rAttrName = xAttrList->getNameByIndex( i );
     457             : 
     458        4312 :         OUString aLocalName;
     459             :         const sal_uInt16 nPrefix =
     460        2156 :             GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
     461        2156 :                                                             &aLocalName );
     462        4312 :         const OUString& rValue = xAttrList->getValueByIndex( i );
     463             :         const SvXMLTokenMap& rTokenMap =
     464        2156 :             GetSwImport().GetTableCellAttrTokenMap();
     465        2156 :         switch( rTokenMap.Get( nPrefix, aLocalName ) )
     466             :         {
     467             :         case XML_TOK_TABLE_XMLID:
     468           0 :             mXmlId = rValue;
     469           0 :             break;
     470             :         case XML_TOK_TABLE_STYLE_NAME:
     471         794 :             aStyleName = rValue;
     472         794 :             GetImport().GetTextImport()->SetCellParaStyleDefault(rValue);
     473         794 :             break;
     474             :         case XML_TOK_TABLE_NUM_COLS_SPANNED:
     475         350 :             nColSpan = (sal_uInt32)rValue.toInt32();
     476         350 :             if( nColSpan < 1UL )
     477           0 :                 nColSpan = 1UL;
     478         350 :             break;
     479             :         case XML_TOK_TABLE_NUM_ROWS_SPANNED:
     480         330 :             nRowSpan = (sal_uInt32)rValue.toInt32();
     481         330 :             if( nRowSpan < 1UL )
     482           0 :                 nRowSpan = 1UL;
     483         330 :             break;
     484             :         case XML_TOK_TABLE_NUM_COLS_REPEATED:
     485           0 :             nColRepeat = (sal_uInt32)rValue.toInt32();
     486           0 :             if( nColRepeat < 1UL )
     487           0 :                 nColRepeat = 1UL;
     488           0 :             break;
     489             :         case XML_TOK_TABLE_FORMULA:
     490             :             {
     491           0 :                 OUString sTmp;
     492           0 :                 const sal_uInt16 nPrefix2 = GetImport().GetNamespaceMap().
     493           0 :                         _GetKeyByAttrName( rValue, &sTmp, false );
     494           0 :                 sFormula = XML_NAMESPACE_OOOW == nPrefix2 ? sTmp : rValue;
     495             :             }
     496           0 :             break;
     497             :         case XML_TOK_TABLE_VALUE:
     498             :             {
     499             :                 double fTmp;
     500           4 :                 if (::sax::Converter::convertDouble(fTmp, rValue))
     501             :                 {
     502           4 :                     fValue = fTmp;
     503           4 :                     bHasValue = true;
     504             :                 }
     505             :             }
     506           4 :             break;
     507             :         case XML_TOK_TABLE_TIME_VALUE:
     508             :             {
     509             :                 double fTmp;
     510           0 :                 if (::sax::Converter::convertDuration(fTmp, rValue))
     511             :                 {
     512           0 :                     fValue = fTmp;
     513           0 :                     bHasValue = true;
     514             :                 }
     515             :             }
     516           0 :             break;
     517             :         case XML_TOK_TABLE_DATE_VALUE:
     518             :             {
     519             :                 double fTmp;
     520           8 :                 if (GetImport().GetMM100UnitConverter().convertDateTime(fTmp,
     521             :                                                                       rValue))
     522             :                 {
     523           8 :                     fValue = fTmp;
     524           8 :                     bHasValue = true;
     525             :                 }
     526             :             }
     527           8 :             break;
     528             :         case XML_TOK_TABLE_BOOLEAN_VALUE:
     529             :             {
     530           0 :                 bool bTmp(false);
     531           0 :                 if (::sax::Converter::convertBool(bTmp, rValue))
     532             :                 {
     533           0 :                     fValue = (bTmp ? 1.0 : 0.0);
     534           0 :                     bHasValue = true;
     535             :                 }
     536             :             }
     537           0 :             break;
     538             :         case XML_TOK_TABLE_PROTECTED:
     539             :             {
     540           0 :                 bool bTmp(false);
     541           0 :                 if (::sax::Converter::convertBool(bTmp, rValue))
     542             :                 {
     543           0 :                     bProtect = bTmp;
     544             :                 }
     545             :             }
     546           0 :             break;
     547             :         case XML_TOK_TABLE_STRING_VALUE:
     548             :             {
     549           2 :                 m_StringValue = rValue;
     550           2 :                 m_bHasStringValue = true;
     551             :             }
     552           2 :             break;
     553             :         case XML_TOK_TABLE_VALUE_TYPE:
     554             :             {
     555         668 :                 if ("string" == rValue)
     556             :                 {
     557         656 :                     m_bValueTypeIsString = true;
     558             :                 }
     559             :                 // ignore other types - it would be correct to require
     560             :                 // matching value-type and $type-value attributes,
     561             :                 // but we've been reading those without checking forever.
     562             :             }
     563         668 :             break;
     564             :         }
     565        2156 :     }
     566         998 : }
     567             : 
     568        1996 : SwXMLTableCellContext_Impl::~SwXMLTableCellContext_Impl()
     569             : {
     570        1996 : }
     571             : 
     572         998 : inline void SwXMLTableCellContext_Impl::_InsertContent()
     573             : {
     574             :     SwStartNode const*const pStartNode( GetTable()->InsertTableSection(0,
     575           4 :             (m_bHasStringValue && m_bValueTypeIsString &&
     576        1002 :              !aStyleName.isEmpty()) ? & aStyleName : 0) );
     577             :     GetTable()->InsertCell( aStyleName, nRowSpan, nColSpan,
     578             :                             pStartNode,
     579             :                             mXmlId,
     580             :                             NULL, bProtect, &sFormula, bHasValue, fValue,
     581         998 :             (m_bHasStringValue && m_bValueTypeIsString) ? &m_StringValue : 0);
     582         998 : }
     583             : 
     584         998 : inline void SwXMLTableCellContext_Impl::InsertContent()
     585             : {
     586             :     OSL_ENSURE( !HasContent(), "content already there" );
     587         998 :     bHasTextContent = true;
     588         998 :     _InsertContent();
     589         998 : }
     590             : 
     591        1032 : inline void SwXMLTableCellContext_Impl::InsertContentIfNotThere()
     592             : {
     593        1032 :     if( !HasContent() )
     594         974 :         InsertContent();
     595        1032 : }
     596             : 
     597           0 : inline void SwXMLTableCellContext_Impl::InsertContent(
     598             :                                                 SwXMLTableContext *pTable )
     599             : {
     600           0 :     GetTable()->InsertCell( aStyleName, nRowSpan, nColSpan, 0, mXmlId, pTable, bProtect );
     601           0 :     bHasTableContent = true;
     602           0 : }
     603             : 
     604        1032 : SvXMLImportContext *SwXMLTableCellContext_Impl::CreateChildContext(
     605             :         sal_uInt16 nPrefix,
     606             :         const OUString& rLocalName,
     607             :         const Reference< xml::sax::XAttributeList > & xAttrList )
     608             : {
     609        1032 :     SvXMLImportContext *pContext = 0;
     610             : 
     611        1032 :     OUString sXmlId;
     612        1032 :     bool bSubTable = false;
     613        1032 :     if( XML_NAMESPACE_TABLE == nPrefix &&
     614           0 :         IsXMLToken( rLocalName, XML_TABLE ) )
     615             :     {
     616           0 :         sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     617           0 :         for( sal_Int16 i=0; i < nAttrCount; i++ )
     618             :         {
     619           0 :             const OUString& rAttrName = xAttrList->getNameByIndex( i );
     620             : 
     621           0 :             OUString aLocalName;
     622             :             const sal_uInt16 nPrefix2 =
     623           0 :                 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
     624           0 :                                                                 &aLocalName );
     625           0 :             if( XML_NAMESPACE_TABLE == nPrefix2 &&
     626           0 :                  IsXMLToken( aLocalName, XML_IS_SUB_TABLE ) &&
     627           0 :                  IsXMLToken( xAttrList->getValueByIndex( i ), XML_TRUE ) )
     628             :             {
     629           0 :                 bSubTable = true;
     630             :             }
     631           0 :             else if ( (XML_NAMESPACE_XML == nPrefix2) &&
     632           0 :                      IsXMLToken( aLocalName, XML_ID ) )
     633             :             {
     634           0 :                 sXmlId = xAttrList->getValueByIndex( i );
     635             :             }
     636             :         //FIXME: RDFa
     637           0 :         }
     638             :     }
     639             : 
     640        1032 :     if( bSubTable )
     641             :     {
     642           0 :         if( !HasContent() )
     643             :         {
     644             :             SwXMLTableContext *pTblContext =
     645             :                 new SwXMLTableContext( GetSwImport(), nPrefix, rLocalName,
     646           0 :                                        xAttrList, GetTable() );
     647           0 :             pContext = pTblContext;
     648           0 :             if( GetTable()->IsValid() )
     649           0 :                 InsertContent( pTblContext );
     650             : 
     651           0 :             GetTable()->SetHasSubTables( true );
     652             :         }
     653             :     }
     654             :     else
     655             :     {
     656        1032 :         if( GetTable()->IsValid() )
     657        1032 :             InsertContentIfNotThere();
     658             :         // fdo#60842: "office:string-value" overrides text content -> no import
     659        1032 :         if (!(m_bValueTypeIsString && m_bHasStringValue))
     660             :         {
     661        1030 :             pContext = GetImport().GetTextImport()->CreateTextChildContext(
     662        1030 :                         GetImport(), nPrefix, rLocalName, xAttrList,
     663        2060 :                         XML_TEXT_TYPE_CELL  );
     664             :         }
     665             :     }
     666             : 
     667        1032 :     if( !pContext )
     668           2 :         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
     669             : 
     670        1032 :     return pContext;
     671             : }
     672             : 
     673         998 : void SwXMLTableCellContext_Impl::EndElement()
     674             : {
     675         998 :     if( GetTable()->IsValid() )
     676             :     {
     677         998 :         if( bHasTextContent )
     678             :         {
     679         974 :             GetImport().GetTextImport()->DeleteParagraph();
     680         974 :             if( nColRepeat > 1 && nColSpan == 1 )
     681             :             {
     682             :                 // The original text is invalid after deleting the last
     683             :                 // paragraph
     684             :                 Reference < XTextCursor > xSrcTxtCursor =
     685           0 :                     GetImport().GetTextImport()->GetText()->createTextCursor();
     686           0 :                 xSrcTxtCursor->gotoEnd( sal_True );
     687             : 
     688             :                 // Until we have an API for copying we have to use the core.
     689           0 :                 Reference<XUnoTunnel> xSrcCrsrTunnel( xSrcTxtCursor, UNO_QUERY);
     690             :                 OSL_ENSURE( xSrcCrsrTunnel.is(), "missing XUnoTunnel for Cursor" );
     691             :                 OTextCursorHelper *pSrcTxtCrsr = reinterpret_cast< OTextCursorHelper * >(
     692           0 :                         sal::static_int_cast< sal_IntPtr >( xSrcCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() )));
     693             :                 OSL_ENSURE( pSrcTxtCrsr, "SwXTextCursor missing" );
     694           0 :                 SwDoc *pDoc = pSrcTxtCrsr->GetDoc();
     695           0 :                 const SwPaM *pSrcPaM = pSrcTxtCrsr->GetPaM();
     696             : 
     697           0 :                 while( nColRepeat > 1 && GetTable()->IsInsertCellPossible() )
     698             :                 {
     699           0 :                     _InsertContent();
     700             : 
     701             :                     Reference<XUnoTunnel> xDstCrsrTunnel(
     702           0 :                         GetImport().GetTextImport()->GetCursor(), UNO_QUERY);
     703             :                     OSL_ENSURE( xDstCrsrTunnel.is(),
     704             :                             "missing XUnoTunnel for Cursor" );
     705             :                     OTextCursorHelper *pDstTxtCrsr = reinterpret_cast< OTextCursorHelper * >(
     706           0 :                             sal::static_int_cast< sal_IntPtr >( xDstCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() )) );
     707             :                     assert(pDstTxtCrsr && "SwXTextCursor missing");
     708           0 :                     SwPaM aSrcPaM( *pSrcPaM->GetPoint(),
     709           0 :                                    *pSrcPaM->GetMark() );
     710           0 :                     SwPosition aDstPos( *pDstTxtCrsr->GetPaM()->GetPoint() );
     711           0 :                     pDoc->getIDocumentContentOperations().CopyRange( aSrcPaM, aDstPos, false );
     712             : 
     713           0 :                     nColRepeat--;
     714           0 :                 }
     715             :             }
     716             :         }
     717          24 :         else if( !bHasTableContent )
     718             :         {
     719          24 :             InsertContent();
     720          24 :             if( nColRepeat > 1 && nColSpan == 1 )
     721             :             {
     722           0 :                 while( nColRepeat > 1 && GetTable()->IsInsertCellPossible() )
     723             :                 {
     724           0 :                     _InsertContent();
     725           0 :                     nColRepeat--;
     726             :                 }
     727             :             }
     728             :         }
     729             :     }
     730         998 :     GetImport().GetTextImport()->SetCellParaStyleDefault(sSaveParaDefault);
     731         998 : }
     732             : 
     733             : class SwXMLTableColContext_Impl : public SvXMLImportContext
     734             : {
     735             :     SvXMLImportContextRef   xMyTable;
     736             : 
     737         632 :     SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
     738             : 
     739             : public:
     740             : 
     741             :     SwXMLTableColContext_Impl(
     742             :             SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
     743             :             const Reference< xml::sax::XAttributeList > & xAttrList,
     744             :             SwXMLTableContext *pTable );
     745             : 
     746             :     virtual ~SwXMLTableColContext_Impl();
     747             : 
     748         284 :     SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
     749             : };
     750             : 
     751         284 : SwXMLTableColContext_Impl::SwXMLTableColContext_Impl(
     752             :         SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
     753             :         const Reference< xml::sax::XAttributeList > & xAttrList,
     754             :         SwXMLTableContext *pTable ) :
     755             :     SvXMLImportContext( rImport, nPrfx, rLName ),
     756         284 :     xMyTable( pTable )
     757             : {
     758         284 :     sal_uInt32 nColRep = 1UL;
     759         568 :     OUString aStyleName, aDfltCellStyleName;
     760             : 
     761         284 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     762         592 :     for( sal_Int16 i=0; i < nAttrCount; i++ )
     763             :     {
     764         308 :         const OUString& rAttrName = xAttrList->getNameByIndex( i );
     765             : 
     766         616 :         OUString aLocalName;
     767             :         const sal_uInt16 nPrefix =
     768         308 :             GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
     769         308 :                                                             &aLocalName );
     770         616 :         const OUString& rValue = xAttrList->getValueByIndex( i );
     771         308 :         if( XML_NAMESPACE_TABLE == nPrefix )
     772             :         {
     773         308 :             if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
     774         284 :                 aStyleName = rValue;
     775          24 :             else if( IsXMLToken( aLocalName, XML_NUMBER_COLUMNS_REPEATED ) )
     776          24 :                 nColRep = (sal_uInt32)rValue.toInt32();
     777           0 :             else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
     778           0 :                 aDfltCellStyleName = rValue;
     779             :         }
     780           0 :         else if ( (XML_NAMESPACE_XML == nPrefix) &&
     781           0 :                  IsXMLToken( aLocalName, XML_ID ) )
     782             :         {
     783             :             (void) rValue;
     784             :         //FIXME where to put this??? columns do not actually exist in writer...
     785             :         }
     786         308 :     }
     787             : 
     788         284 :     sal_Int32 nWidth = MINLAY;
     789         284 :     bool bRelWidth = true;
     790         284 :     if( !aStyleName.isEmpty() )
     791             :     {
     792             :         const SfxPoolItem *pItem;
     793         284 :         const SfxItemSet *pAutoItemSet = 0;
     794         568 :         if( GetSwImport().FindAutomaticStyle(
     795             :                     XML_STYLE_FAMILY_TABLE_COLUMN,
     796         568 :                                               aStyleName, &pAutoItemSet ) &&
     797         568 :             pAutoItemSet &&
     798             :             SfxItemState::SET == pAutoItemSet->GetItemState( RES_FRM_SIZE, false,
     799         284 :                                                         &pItem ) )
     800             :         {
     801         284 :             const SwFmtFrmSize *pSize = ((const SwFmtFrmSize *)pItem);
     802         284 :             nWidth = pSize->GetWidth();
     803         284 :             bRelWidth = ATT_VAR_SIZE == pSize->GetHeightSizeType();
     804             :         }
     805             :     }
     806             : 
     807         284 :     if( nWidth )
     808             :     {
     809         884 :         while( nColRep-- && GetTable()->IsInsertColPossible() )
     810         316 :             GetTable()->InsertColumn( nWidth, bRelWidth, &aDfltCellStyleName );
     811         284 :     }
     812         284 : }
     813             : 
     814         568 : SwXMLTableColContext_Impl::~SwXMLTableColContext_Impl()
     815             : {
     816         568 : }
     817             : 
     818             : class SwXMLTableColsContext_Impl : public SvXMLImportContext
     819             : {
     820             :     SvXMLImportContextRef   xMyTable;
     821             : 
     822          44 :     SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
     823             : 
     824             : public:
     825             : 
     826             :     SwXMLTableColsContext_Impl(
     827             :             SwXMLImport& rImport, sal_uInt16 nPrfx,
     828             :             const OUString& rLName,
     829             :             const Reference< xml::sax::XAttributeList > & xAttrList,
     830             :             SwXMLTableContext *pTable );
     831             : 
     832             :     virtual ~SwXMLTableColsContext_Impl();
     833             : 
     834             :     virtual SvXMLImportContext *CreateChildContext(
     835             :             sal_uInt16 nPrefix, const OUString& rLocalName,
     836             :             const Reference< xml::sax::XAttributeList > & xAttrList ) SAL_OVERRIDE;
     837             : 
     838          22 :     SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
     839             : };
     840             : 
     841           6 : SwXMLTableColsContext_Impl::SwXMLTableColsContext_Impl(
     842             :         SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
     843             :         const Reference< xml::sax::XAttributeList > &,
     844             :         SwXMLTableContext *pTable ) :
     845             :     SvXMLImportContext( rImport, nPrfx, rLName ),
     846           6 :     xMyTable( pTable )
     847             : {
     848           6 : }
     849             : 
     850          12 : SwXMLTableColsContext_Impl::~SwXMLTableColsContext_Impl()
     851             : {
     852          12 : }
     853             : 
     854          22 : SvXMLImportContext *SwXMLTableColsContext_Impl::CreateChildContext(
     855             :         sal_uInt16 nPrefix,
     856             :         const OUString& rLocalName,
     857             :         const Reference< xml::sax::XAttributeList > & xAttrList )
     858             : {
     859          22 :     SvXMLImportContext *pContext = 0;
     860             : 
     861          44 :     if( XML_NAMESPACE_TABLE == nPrefix &&
     862          44 :         IsXMLToken( rLocalName, XML_TABLE_COLUMN ) &&
     863          22 :         GetTable()->IsInsertColPossible() )
     864             :         pContext = new SwXMLTableColContext_Impl( GetSwImport(), nPrefix,
     865             :                                                   rLocalName, xAttrList,
     866          22 :                                                   GetTable() );
     867             : 
     868          22 :     if( !pContext )
     869           0 :         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
     870             : 
     871          22 :     return pContext;
     872             : }
     873             : 
     874             : class SwXMLTableRowContext_Impl : public SvXMLImportContext
     875             : {
     876             :     SvXMLImportContextRef   xMyTable;
     877             : 
     878             :     sal_uInt32                  nRowRepeat;
     879             : 
     880        4026 :     SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
     881             : 
     882             : public:
     883             : 
     884             :     SwXMLTableRowContext_Impl(
     885             :             SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName,
     886             :             const Reference< xml::sax::XAttributeList > & xAttrList,
     887             :             SwXMLTableContext *pTable, bool bInHead=false );
     888             : 
     889             :     virtual ~SwXMLTableRowContext_Impl();
     890             : 
     891             :     virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
     892             :             const OUString& rLocalName,
     893             :             const Reference< xml::sax::XAttributeList > & xAttrList ) SAL_OVERRIDE;
     894             : 
     895             :     virtual void EndElement() SAL_OVERRIDE;
     896             : 
     897         998 :     SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
     898             : };
     899             : 
     900         258 : SwXMLTableRowContext_Impl::SwXMLTableRowContext_Impl( SwXMLImport& rImport,
     901             :         sal_uInt16 nPrfx,
     902             :         const OUString& rLName,
     903             :         const Reference< xml::sax::XAttributeList > & xAttrList,
     904             :         SwXMLTableContext *pTable,
     905             :         bool bInHead ) :
     906             :     SvXMLImportContext( rImport, nPrfx, rLName ),
     907             :     xMyTable( pTable ),
     908         258 :     nRowRepeat( 1 )
     909             : {
     910         516 :     OUString aStyleName, aDfltCellStyleName;
     911         516 :     OUString sXmlId;
     912             : 
     913         258 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     914         366 :     for( sal_Int16 i=0; i < nAttrCount; i++ )
     915             :     {
     916         108 :         const OUString& rAttrName = xAttrList->getNameByIndex( i );
     917             : 
     918         216 :         OUString aLocalName;
     919             :         const sal_uInt16 nPrefix =
     920         108 :             GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
     921         108 :                                                             &aLocalName );
     922         216 :         const OUString& rValue = xAttrList->getValueByIndex( i );
     923         108 :         if( XML_NAMESPACE_TABLE == nPrefix )
     924             :         {
     925         108 :             if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
     926             :             {
     927         108 :                 aStyleName = rValue;
     928             :             }
     929           0 :             else if( IsXMLToken( aLocalName, XML_NUMBER_ROWS_REPEATED ) )
     930             :             {
     931           0 :                 nRowRepeat = (sal_uInt32)rValue.toInt32();
     932           0 :                 if( nRowRepeat < 1UL )
     933           0 :                     nRowRepeat = 1UL;
     934             :             }
     935           0 :             else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
     936             :             {
     937           0 :                 aDfltCellStyleName = rValue;
     938             :             }
     939             :         }
     940           0 :         else if ( (XML_NAMESPACE_XML == nPrefix) &&
     941           0 :                  IsXMLToken( aLocalName, XML_ID ) )
     942             :         {
     943           0 :             sXmlId = rValue;
     944             :         }
     945         108 :     }
     946         258 :     if( GetTable()->IsValid() )
     947             :         GetTable()->InsertRow( aStyleName, aDfltCellStyleName, bInHead,
     948         516 :                                sXmlId );
     949         258 : }
     950             : 
     951         258 : void SwXMLTableRowContext_Impl::EndElement()
     952             : {
     953         258 :     if( GetTable()->IsValid() )
     954             :     {
     955         258 :         GetTable()->FinishRow();
     956             : 
     957         258 :         if( nRowRepeat > 1UL )
     958           0 :             GetTable()->InsertRepRows( nRowRepeat );
     959             :     }
     960         258 : }
     961             : 
     962         516 : SwXMLTableRowContext_Impl::~SwXMLTableRowContext_Impl()
     963             : {
     964         516 : }
     965             : 
     966        1046 : SvXMLImportContext *SwXMLTableRowContext_Impl::CreateChildContext(
     967             :         sal_uInt16 nPrefix, const OUString& rLocalName,
     968             :         const Reference< xml::sax::XAttributeList > & xAttrList )
     969             : {
     970        1046 :     SvXMLImportContext *pContext = 0;
     971             : 
     972        1046 :     if( XML_NAMESPACE_TABLE == nPrefix )
     973             :     {
     974        1046 :         if( IsXMLToken( rLocalName, XML_TABLE_CELL ) )
     975             :         {
     976         998 :             if( !GetTable()->IsValid() || GetTable()->IsInsertCellPossible() )
     977             :                 pContext = new SwXMLTableCellContext_Impl( GetSwImport(),
     978             :                                                            nPrefix,
     979             :                                                            rLocalName,
     980             :                                                            xAttrList,
     981         998 :                                                            GetTable() );
     982             :         }
     983          48 :         else if( IsXMLToken( rLocalName, XML_COVERED_TABLE_CELL ) )
     984          48 :             pContext = new SvXMLImportContext( GetImport(), nPrefix,
     985          48 :                                                rLocalName );
     986             :     }
     987             : 
     988        1046 :     if( !pContext )
     989           0 :         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
     990             : 
     991        1046 :     return pContext;
     992             : }
     993             : 
     994             : class SwXMLTableRowsContext_Impl : public SvXMLImportContext
     995             : {
     996             :     SvXMLImportContextRef   xMyTable;
     997             : 
     998             :     bool bHeader;
     999             : 
    1000          16 :     SwXMLTableContext *GetTable() { return (SwXMLTableContext *)&xMyTable; }
    1001             : 
    1002             : public:
    1003             : 
    1004             :     SwXMLTableRowsContext_Impl( SwXMLImport& rImport, sal_uInt16 nPrfx,
    1005             :             const OUString& rLName,
    1006             :             const Reference< xml::sax::XAttributeList > & xAttrList,
    1007             :             SwXMLTableContext *pTable,
    1008             :             bool bHead );
    1009             : 
    1010             :     virtual ~SwXMLTableRowsContext_Impl();
    1011             : 
    1012             :     virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
    1013             :             const OUString& rLocalName,
    1014             :             const Reference< xml::sax::XAttributeList > & xAttrList ) SAL_OVERRIDE;
    1015             : 
    1016           8 :     SwXMLImport& GetSwImport() { return (SwXMLImport&)GetImport(); }
    1017             : };
    1018             : 
    1019           8 : SwXMLTableRowsContext_Impl::SwXMLTableRowsContext_Impl( SwXMLImport& rImport,
    1020             :         sal_uInt16 nPrfx,
    1021             :         const OUString& rLName,
    1022             :         const Reference< xml::sax::XAttributeList > &,
    1023             :         SwXMLTableContext *pTable,
    1024             :         bool bHead ) :
    1025             :     SvXMLImportContext( rImport, nPrfx, rLName ),
    1026             :     xMyTable( pTable ),
    1027           8 :     bHeader( bHead )
    1028             : {
    1029           8 : }
    1030             : 
    1031          16 : SwXMLTableRowsContext_Impl::~SwXMLTableRowsContext_Impl()
    1032             : {
    1033          16 : }
    1034             : 
    1035           8 : SvXMLImportContext *SwXMLTableRowsContext_Impl::CreateChildContext(
    1036             :         sal_uInt16 nPrefix,
    1037             :         const OUString& rLocalName,
    1038             :         const Reference< xml::sax::XAttributeList > & xAttrList )
    1039             : {
    1040           8 :     SvXMLImportContext *pContext = 0;
    1041             : 
    1042          16 :     if( XML_NAMESPACE_TABLE == nPrefix &&
    1043          16 :         IsXMLToken( rLocalName, XML_TABLE_ROW ) &&
    1044           8 :         GetTable()->IsInsertRowPossible() )
    1045             :         pContext = new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix,
    1046             :                                                   rLocalName, xAttrList,
    1047             :                                                   GetTable(),
    1048           8 :                                                   bHeader );
    1049             : 
    1050           8 :     if( !pContext )
    1051           0 :         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
    1052             : 
    1053           8 :     return pContext;
    1054             : }
    1055             : 
    1056             : class SwXMLDDETableContext_Impl : public SvXMLImportContext
    1057             : {
    1058             :     OUString sConnectionName;
    1059             :     OUString sDDEApplication;
    1060             :     OUString sDDEItem;
    1061             :     OUString sDDETopic;
    1062             :     bool bIsAutomaticUpdate;
    1063             : 
    1064             : public:
    1065             : 
    1066             :     TYPEINFO_OVERRIDE();
    1067             : 
    1068             :     SwXMLDDETableContext_Impl(
    1069             :         SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName);
    1070             : 
    1071             :     virtual ~SwXMLDDETableContext_Impl();
    1072             : 
    1073             :     virtual void StartElement(
    1074             :         const Reference<xml::sax::XAttributeList> & xAttrList) SAL_OVERRIDE;
    1075             : 
    1076           0 :     OUString& GetConnectionName()   { return sConnectionName; }
    1077           0 :     OUString& GetDDEApplication()   { return sDDEApplication; }
    1078           0 :     OUString& GetDDEItem()          { return sDDEItem; }
    1079           0 :     OUString& GetDDETopic()         { return sDDETopic; }
    1080           0 :     bool GetIsAutomaticUpdate() { return bIsAutomaticUpdate; }
    1081             : };
    1082             : 
    1083           0 : TYPEINIT1( SwXMLDDETableContext_Impl, SvXMLImportContext );
    1084             : 
    1085           0 : SwXMLDDETableContext_Impl::SwXMLDDETableContext_Impl(
    1086             :     SwXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName) :
    1087             :         SvXMLImportContext(rImport, nPrfx, rLName),
    1088             :         sConnectionName(),
    1089             :         sDDEApplication(),
    1090             :         sDDEItem(),
    1091             :         sDDETopic(),
    1092           0 :         bIsAutomaticUpdate(false)
    1093             : {
    1094           0 : }
    1095             : 
    1096           0 : SwXMLDDETableContext_Impl::~SwXMLDDETableContext_Impl()
    1097             : {
    1098           0 : }
    1099             : 
    1100           0 : void SwXMLDDETableContext_Impl::StartElement(
    1101             :     const Reference<xml::sax::XAttributeList> & xAttrList)
    1102             : {
    1103           0 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    1104           0 :     for( sal_Int16 i = 0; i < nAttrCount; i++ )
    1105             :     {
    1106           0 :         const OUString& rAttrName = xAttrList->getNameByIndex( i );
    1107             : 
    1108           0 :         OUString aLocalName;
    1109             :         const sal_uInt16 nPrefix =
    1110           0 :             GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
    1111           0 :                                                             &aLocalName );
    1112           0 :         const OUString& rValue = xAttrList->getValueByIndex( i );
    1113             : 
    1114           0 :         if (XML_NAMESPACE_OFFICE == nPrefix)
    1115             :         {
    1116           0 :             if ( IsXMLToken( aLocalName, XML_DDE_APPLICATION ) )
    1117             :             {
    1118           0 :                 sDDEApplication = rValue;
    1119             :             }
    1120           0 :             else if ( IsXMLToken( aLocalName, XML_DDE_TOPIC ) )
    1121             :             {
    1122           0 :                 sDDETopic = rValue;
    1123             :             }
    1124           0 :             else if ( IsXMLToken( aLocalName, XML_DDE_ITEM ) )
    1125             :             {
    1126           0 :                 sDDEItem = rValue;
    1127             :             }
    1128           0 :             else if ( IsXMLToken( aLocalName, XML_NAME ) )
    1129             :             {
    1130           0 :                 sConnectionName = rValue;
    1131             :             }
    1132           0 :             else if ( IsXMLToken( aLocalName, XML_AUTOMATIC_UPDATE ) )
    1133             :             {
    1134           0 :                 bool bTmp(false);
    1135           0 :                 if (::sax::Converter::convertBool(bTmp, rValue))
    1136             :                 {
    1137           0 :                     bIsAutomaticUpdate = bTmp;
    1138             :                 }
    1139             :             }
    1140             :             // else: unknown attribute
    1141             :         }
    1142             :         // else: unknown attribute namespace
    1143           0 :     }
    1144           0 : }
    1145             : 
    1146             : // generate a new name for DDE field type (called by lcl_GetDDEFieldType below)
    1147           0 : static OUString lcl_GenerateFldTypeName(const OUString& sPrefix, SwTableNode* pTableNode)
    1148             : {
    1149           0 :     const OUString sPrefixStr(sPrefix.isEmpty() ? OUString("_") : sPrefix);
    1150             : 
    1151             :     // increase count until we find a name that is not yet taken
    1152           0 :     OUString sName;
    1153           0 :     sal_Int32 nCount = 0;
    1154           0 :     do
    1155             :     {
    1156             :         // this is crazy, but just in case all names are taken: exit gracefully
    1157           0 :         if (nCount == SAL_MAX_INT32)
    1158           0 :             return sName;
    1159             : 
    1160           0 :         ++nCount;
    1161           0 :         sName = sPrefixStr + OUString::number(nCount);
    1162             :     }
    1163           0 :     while (NULL != pTableNode->GetDoc()->getIDocumentFieldsAccess().GetFldType(RES_DDEFLD, sName, false));
    1164             : 
    1165           0 :     return sName;
    1166             : }
    1167             : 
    1168             : // set table properties
    1169           0 : static SwDDEFieldType* lcl_GetDDEFieldType(SwXMLDDETableContext_Impl* pContext,
    1170             :                                     SwTableNode* pTableNode)
    1171             : {
    1172             :     // make command string
    1173           0 :     const OUString sCommand(pContext->GetDDEApplication()
    1174           0 :         + OUString(sfx2::cTokenSeparator)
    1175           0 :         + pContext->GetDDEItem()
    1176           0 :         + OUString(sfx2::cTokenSeparator)
    1177           0 :         + pContext->GetDDETopic());
    1178             : 
    1179             :     const sal_uInt16 nType = static_cast< sal_uInt16 >(
    1180           0 :         pContext->GetIsAutomaticUpdate()
    1181             :         ? sfx2::LINKUPDATE_ALWAYS
    1182           0 :         : sfx2::LINKUPDATE_ONCALL);
    1183             : 
    1184           0 :     OUString sName(pContext->GetConnectionName());
    1185             : 
    1186             :     // field type to be returned
    1187           0 :     SwDDEFieldType* pType = NULL;
    1188             : 
    1189             :     // valid name?
    1190           0 :     if (sName.isEmpty())
    1191             :     {
    1192           0 :         sName = lcl_GenerateFldTypeName(pContext->GetDDEApplication(),
    1193           0 :                                         pTableNode);
    1194             :     }
    1195             :     else
    1196             :     {
    1197             :         // check for existing DDE field type with the same name
    1198           0 :         SwDDEFieldType* pOldType = (SwDDEFieldType*)pTableNode->GetDoc()->getIDocumentFieldsAccess().GetFldType(RES_DDEFLD, sName, false);
    1199           0 :         if (NULL != pOldType)
    1200             :         {
    1201             :             // same values -> return old type
    1202           0 :             if ( (pOldType->GetCmd() == sCommand) &&
    1203           0 :                  (pOldType->GetType() == nType) )
    1204             :             {
    1205             :                 // same name, same values -> return old type!
    1206           0 :                 pType = pOldType;
    1207             :             }
    1208             :             else
    1209             :             {
    1210             :                 // same name, different values -> think of new name
    1211           0 :                 sName = lcl_GenerateFldTypeName(pContext->GetDDEApplication(),
    1212           0 :                                                 pTableNode);
    1213             :             }
    1214             :         }
    1215             :         // no old type -> create new one
    1216             :     }
    1217             : 
    1218             :     // create new field type (unless we already have one)
    1219           0 :     if (NULL == pType)
    1220             :     {
    1221             :         // create new field type and return
    1222           0 :         SwDDEFieldType aDDEFieldType(sName, sCommand, nType);
    1223             :         pType = (SwDDEFieldType*)pTableNode->
    1224           0 :             GetDoc()->getIDocumentFieldsAccess().InsertFldType(aDDEFieldType);
    1225             :     }
    1226             : 
    1227             :     OSL_ENSURE(NULL != pType, "We really want a SwDDEFieldType here!");
    1228           0 :     return pType;
    1229             : }
    1230             : 
    1231        2762 : class TableBoxIndex
    1232             : {
    1233             : public:
    1234             :     OUString msName;
    1235             :     sal_Int32 mnWidth;
    1236             :     bool mbProtected;
    1237             : 
    1238        1010 :     TableBoxIndex( const OUString& rName, sal_Int32 nWidth,
    1239             :                    bool bProtected ) :
    1240             :         msName( rName ),
    1241             :         mnWidth( nWidth ),
    1242        1010 :         mbProtected( bProtected )
    1243        1010 :     { }
    1244             : 
    1245         604 :     bool operator== ( const TableBoxIndex& rArg ) const
    1246             :     {
    1247        1164 :         return (rArg.mnWidth == mnWidth) &&
    1248        1164 :             (rArg.mbProtected == mbProtected) &&
    1249        1164 :             (rArg.msName == msName);
    1250             :     }
    1251             : };
    1252             : 
    1253             : class TableBoxIndexHasher
    1254             : {
    1255             : public:
    1256        1448 :     size_t operator() (const TableBoxIndex& rArg) const
    1257             :     {
    1258        1448 :         return rArg.msName.hashCode() + rArg.mnWidth + (rArg.mbProtected ? 1 : 0);
    1259             :     }
    1260             : };
    1261             : 
    1262             : typedef boost::ptr_vector<SwXMLTableRow_Impl> SwXMLTableRows_Impl;
    1263             : 
    1264          12 : const SwXMLTableCell_Impl *SwXMLTableContext::GetCell( sal_uInt32 nRow,
    1265             :                                                  sal_uInt32 nCol ) const
    1266             : {
    1267          12 :     return (*pRows)[nRow].GetCell( nCol );
    1268             : }
    1269             : 
    1270        4148 : SwXMLTableCell_Impl *SwXMLTableContext::GetCell( sal_uInt32 nRow,
    1271             :                                                  sal_uInt32 nCol )
    1272             : {
    1273        4148 :     return (*pRows)[nRow].GetCell( nCol );
    1274             : }
    1275             : 
    1276           0 : TYPEINIT1( SwXMLTableContext, XMLTextTableContext );
    1277             : 
    1278         102 : SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport,
    1279             :         sal_uInt16 nPrfx,
    1280             :         const OUString& rLName,
    1281             :         const Reference< xml::sax::XAttributeList > & xAttrList ) :
    1282             :     XMLTextTableContext( rImport, nPrfx, rLName ),
    1283             :     pColumnDefaultCellStyleNames( 0 ),
    1284         102 :     pRows( new SwXMLTableRows_Impl ),
    1285             :     pTableNode( 0 ),
    1286             :     pBox1( 0 ),
    1287             :     pSttNd1( 0 ),
    1288             :     pBoxFmt( 0 ),
    1289             :     pLineFmt( 0 ),
    1290             :     pSharedBoxFormats(NULL),
    1291             :     pDDESource(NULL),
    1292             :     bFirstSection( true ),
    1293             :     bRelWidth( true ),
    1294             :     bHasSubTables( false ),
    1295             :     nHeaderRows( 0 ),
    1296             :     nCurRow( 0UL ),
    1297             :     nCurCol( 0UL ),
    1298         204 :     nWidth( 0UL )
    1299             : {
    1300         102 :     OUString aName;
    1301         204 :     OUString sXmlId;
    1302             : 
    1303             :     // this method will modify the document directly -> lock SolarMutex
    1304         204 :     SolarMutexGuard aGuard;
    1305             : 
    1306         102 :     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    1307         306 :     for( sal_Int16 i=0; i < nAttrCount; i++ )
    1308             :     {
    1309         204 :         const OUString& rAttrName = xAttrList->getNameByIndex( i );
    1310             : 
    1311         408 :         OUString aLocalName;
    1312             :         const sal_uInt16 nPrefix =
    1313         204 :             GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
    1314         204 :                                                             &aLocalName );
    1315         408 :         const OUString& rValue = xAttrList->getValueByIndex( i );
    1316         204 :         if( XML_NAMESPACE_TABLE == nPrefix )
    1317             :         {
    1318         204 :             if( IsXMLToken( aLocalName, XML_STYLE_NAME ) )
    1319         102 :                 aStyleName = rValue;
    1320         102 :             else if( IsXMLToken( aLocalName, XML_NAME ) )
    1321         102 :                 aName = rValue;
    1322           0 :             else if( IsXMLToken( aLocalName, XML_DEFAULT_CELL_STYLE_NAME ) )
    1323           0 :                 aDfltCellStyleName = rValue;
    1324             :         }
    1325           0 :         else if ( (XML_NAMESPACE_XML == nPrefix) &&
    1326           0 :                  IsXMLToken( aLocalName, XML_ID ) )
    1327             :         {
    1328           0 :             sXmlId = rValue;
    1329             :         }
    1330         204 :     }
    1331             : 
    1332         102 :     SwDoc *pDoc = SwImport::GetDocFromXMLImport( GetSwImport() );
    1333             : 
    1334         204 :     OUString sTblName;
    1335         102 :     if( !aName.isEmpty() )
    1336             :     {
    1337         102 :         const SwTableFmt *pTblFmt = pDoc->FindTblFmtByName( aName );
    1338         102 :         if( !pTblFmt )
    1339         102 :             sTblName = aName;
    1340             :     }
    1341         102 :     if( sTblName.isEmpty() )
    1342             :     {
    1343           0 :         sTblName = pDoc->GetUniqueTblName();
    1344           0 :         GetImport().GetTextImport()
    1345           0 :             ->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_TABLE, aName, sTblName );
    1346             :     }
    1347             : 
    1348         204 :     Reference< XTextTable > xTable;
    1349         102 :     const SwXTextTable *pXTable = 0;
    1350         102 :     Reference<XMultiServiceFactory> xFactory( GetImport().GetModel(),
    1351         204 :                                               UNO_QUERY );
    1352             :     OSL_ENSURE( xFactory.is(), "factory missing" );
    1353         102 :     if( xFactory.is() )
    1354             :     {
    1355         102 :         Reference<XInterface> xIfc = xFactory->createInstance( "com.sun.star.text.TextTable" );
    1356             :         OSL_ENSURE( xIfc.is(), "Couldn't create a table" );
    1357             : 
    1358         102 :         if( xIfc.is() )
    1359         102 :             xTable = Reference< XTextTable > ( xIfc, UNO_QUERY );
    1360             :     }
    1361             : 
    1362         102 :     if( xTable.is() )
    1363             :     {
    1364         102 :         xTable->initialize( 1, 1 );
    1365             : 
    1366             :         try
    1367             :         {
    1368         102 :             xTextContent = xTable;
    1369         102 :             GetImport().GetTextImport()->InsertTextContent( xTextContent );
    1370             :         }
    1371           0 :         catch( IllegalArgumentException& )
    1372             :         {
    1373           0 :             xTable = 0;
    1374             :         }
    1375             :     }
    1376             : 
    1377         102 :     if( xTable.is() )
    1378             :     {
    1379             :         //FIXME
    1380             :         // xml:id for RDF metadata
    1381         102 :         GetImport().SetXmlId(xTable, sXmlId);
    1382             : 
    1383         102 :         Reference<XUnoTunnel> xTableTunnel( xTable, UNO_QUERY);
    1384         102 :         if( xTableTunnel.is() )
    1385             :         {
    1386             :             pXTable = reinterpret_cast< SwXTextTable * >(
    1387         102 :                     sal::static_int_cast< sal_IntPtr >( xTableTunnel->getSomething( SwXTextTable::getUnoTunnelId() )));
    1388             :             OSL_ENSURE( pXTable, "SwXTextTable missing" );
    1389             :         }
    1390             : 
    1391         204 :         Reference < XCellRange > xCellRange( xTable, UNO_QUERY );
    1392         204 :         Reference < XCell > xCell = xCellRange->getCellByPosition( 0, 0 );
    1393         204 :         Reference < XText> xText( xCell, UNO_QUERY );
    1394         102 :         xOldCursor = GetImport().GetTextImport()->GetCursor();
    1395         102 :         GetImport().GetTextImport()->SetCursor( xText->createTextCursor() );
    1396             : 
    1397             :         // take care of open redlines for tables
    1398         204 :         GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(true);
    1399             :     }
    1400         102 :     if( pXTable )
    1401             :     {
    1402         102 :         SwFrmFmt *pTblFrmFmt = pXTable->GetFrmFmt();
    1403             :         OSL_ENSURE( pTblFrmFmt, "table format missing" );
    1404         102 :         SwTable *pTbl = SwTable::FindTable( pTblFrmFmt );
    1405             :         OSL_ENSURE( pTbl, "table missing" );
    1406         102 :         pTableNode = pTbl->GetTableNode();
    1407             :         OSL_ENSURE( pTableNode, "table node missing" );
    1408             : 
    1409         102 :         pTblFrmFmt->SetName( sTblName );
    1410             : 
    1411         102 :         SwTableLine *pLine1 = pTableNode->GetTable().GetTabLines()[0U];
    1412         102 :         pBox1 = pLine1->GetTabBoxes()[0U];
    1413         102 :         pSttNd1 = pBox1->GetSttNd();
    1414         102 :     }
    1415         102 : }
    1416             : 
    1417           0 : SwXMLTableContext::SwXMLTableContext( SwXMLImport& rImport,
    1418             :         sal_uInt16 nPrfx,
    1419             :         const OUString& rLName,
    1420             :         const Reference< xml::sax::XAttributeList > &,
    1421             :         SwXMLTableContext *pTable ) :
    1422             :     XMLTextTableContext( rImport, nPrfx, rLName ),
    1423             :     pColumnDefaultCellStyleNames( 0 ),
    1424           0 :     pRows( new SwXMLTableRows_Impl ),
    1425             :     pTableNode( pTable->pTableNode ),
    1426             :     pBox1( 0 ),
    1427             :     pSttNd1( 0 ),
    1428             :     pBoxFmt( 0 ),
    1429             :     pLineFmt( 0 ),
    1430             :     pSharedBoxFormats(NULL),
    1431             :     xParentTable( pTable ),
    1432             :     pDDESource(NULL),
    1433             :     bFirstSection( false ),
    1434             :     bRelWidth( true ),
    1435             :     bHasSubTables( false ),
    1436             :     nHeaderRows( 0 ),
    1437             :     nCurRow( 0UL ),
    1438             :     nCurCol( 0UL ),
    1439           0 :     nWidth( 0UL )
    1440             : {
    1441           0 : }
    1442             : 
    1443         306 : SwXMLTableContext::~SwXMLTableContext()
    1444             : {
    1445         102 :     delete pColumnDefaultCellStyleNames;
    1446         102 :     delete pSharedBoxFormats;
    1447         102 :     delete pRows;
    1448             : 
    1449             :     // close redlines on table end nodes
    1450         102 :     GetImport().GetTextImport()->RedlineAdjustStartNodeCursor(false);
    1451         204 : }
    1452             : 
    1453         526 : SvXMLImportContext *SwXMLTableContext::CreateChildContext( sal_uInt16 nPrefix,
    1454             :         const OUString& rLocalName,
    1455             :         const Reference< xml::sax::XAttributeList > & xAttrList )
    1456             : {
    1457         526 :     SvXMLImportContext *pContext = 0;
    1458             : 
    1459         526 :     const SvXMLTokenMap& rTokenMap = GetSwImport().GetTableElemTokenMap();
    1460         526 :     bool bHeader = false;
    1461         526 :     switch( rTokenMap.Get( nPrefix, rLocalName ) )
    1462             :     {
    1463             :     case XML_TOK_TABLE_HEADER_COLS:
    1464             :     case XML_TOK_TABLE_COLS:
    1465           6 :         if( IsValid() )
    1466             :             pContext = new SwXMLTableColsContext_Impl( GetSwImport(), nPrefix,
    1467             :                                                        rLocalName, xAttrList,
    1468           6 :                                                        this );
    1469           6 :         break;
    1470             :     case XML_TOK_TABLE_COL:
    1471         262 :         if( IsValid() && IsInsertColPossible() )
    1472             :             pContext = new SwXMLTableColContext_Impl( GetSwImport(), nPrefix,
    1473             :                                                       rLocalName, xAttrList,
    1474         262 :                                                       this );
    1475         262 :         break;
    1476             :     case XML_TOK_TABLE_HEADER_ROWS:
    1477           8 :         bHeader = true;
    1478             :         //fall-through
    1479             :     case XML_TOK_TABLE_ROWS:
    1480             :         pContext = new SwXMLTableRowsContext_Impl( GetSwImport(), nPrefix,
    1481             :                                                    rLocalName, xAttrList,
    1482           8 :                                                    this, bHeader );
    1483           8 :         break;
    1484             :     case XML_TOK_TABLE_ROW:
    1485         250 :         if( IsInsertRowPossible() )
    1486             :             pContext = new SwXMLTableRowContext_Impl( GetSwImport(), nPrefix,
    1487             :                                                       rLocalName, xAttrList,
    1488         250 :                                                       this );
    1489         250 :         break;
    1490             :     case XML_TOK_OFFICE_DDE_SOURCE:
    1491             :         // save context for later processing (discard old context, if approp.)
    1492           0 :         if( IsValid() )
    1493             :         {
    1494           0 :             if (pDDESource != NULL)
    1495             :             {
    1496           0 :                 pDDESource->ReleaseRef();
    1497             :             }
    1498             :             pDDESource = new SwXMLDDETableContext_Impl( GetSwImport(), nPrefix,
    1499           0 :                                                         rLocalName );
    1500           0 :             pDDESource->AddFirstRef();
    1501           0 :             pContext = pDDESource;
    1502             :         }
    1503           0 :         break;
    1504             :     }
    1505             : 
    1506         526 :     if( !pContext )
    1507           0 :         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
    1508             : 
    1509         526 :     return pContext;
    1510             : }
    1511             : 
    1512         316 : void SwXMLTableContext::InsertColumn( sal_Int32 nWidth2, bool bRelWidth2,
    1513             :                                          const OUString *pDfltCellStyleName )
    1514             : {
    1515             :     OSL_ENSURE( nCurCol < USHRT_MAX,
    1516             :             "SwXMLTableContext::InsertColumn: no space left" );
    1517         316 :     if( nCurCol >= USHRT_MAX )
    1518         316 :         return;
    1519             : 
    1520         316 :     if( nWidth2 < MINLAY )
    1521           0 :         nWidth2 = MINLAY;
    1522         316 :     else if( nWidth2 > USHRT_MAX )
    1523           0 :         nWidth2 = USHRT_MAX;
    1524         316 :     aColumnWidths.push_back( ColumnWidthInfo(nWidth2, bRelWidth2) );
    1525         316 :     if( (pDfltCellStyleName && !pDfltCellStyleName->isEmpty()) ||
    1526             :         pColumnDefaultCellStyleNames )
    1527             :     {
    1528           0 :         if( !pColumnDefaultCellStyleNames )
    1529             :         {
    1530           0 :             pColumnDefaultCellStyleNames = new std::vector<OUString>;
    1531           0 :             sal_uLong nCount = aColumnWidths.size() - 1;
    1532           0 :             while( nCount-- )
    1533           0 :                 pColumnDefaultCellStyleNames->push_back(OUString());
    1534             :         }
    1535             : 
    1536           0 :         if(pDfltCellStyleName)
    1537           0 :             pColumnDefaultCellStyleNames->push_back(*pDfltCellStyleName);
    1538             :         else
    1539           0 :             pColumnDefaultCellStyleNames->push_back(OUString());
    1540             :     }
    1541             : }
    1542             : 
    1543        1010 : sal_Int32 SwXMLTableContext::GetColumnWidth( sal_uInt32 nCol,
    1544             :                                              sal_uInt32 nColSpan ) const
    1545             : {
    1546        1010 :     sal_uInt32 nLast = nCol+nColSpan;
    1547        1010 :     if( nLast > aColumnWidths.size() )
    1548           0 :         nLast = aColumnWidths.size();
    1549             : 
    1550        1010 :     sal_Int32 nWidth2 = 0L;
    1551        2068 :     for( sal_uInt32 i=nCol; i < nLast; ++i )
    1552        1058 :         nWidth2 += aColumnWidths[i].width;
    1553             : 
    1554        1010 :     return nWidth2;
    1555             : }
    1556             : 
    1557           0 : OUString SwXMLTableContext::GetColumnDefaultCellStyleName( sal_uInt32 nCol ) const
    1558             : {
    1559           0 :     if( pColumnDefaultCellStyleNames && nCol < pColumnDefaultCellStyleNames->size())
    1560           0 :         return (*pColumnDefaultCellStyleNames)[static_cast<size_t>(nCol)];
    1561             : 
    1562           0 :     return OUString();
    1563             : }
    1564             : 
    1565         998 : void SwXMLTableContext::InsertCell( const OUString& rStyleName,
    1566             :                                     sal_uInt32 nRowSpan, sal_uInt32 nColSpan,
    1567             :                                     const SwStartNode *pStartNode,
    1568             :                                     const OUString & i_rXmlId,
    1569             :                                     SwXMLTableContext *pTable,
    1570             :                                     bool bProtect,
    1571             :                                     const OUString* pFormula,
    1572             :                                     bool bHasValue,
    1573             :                                     double fValue,
    1574             :                                     OUString const*const pStringValue )
    1575             : {
    1576             :     OSL_ENSURE( nCurCol < GetColumnCount(),
    1577             :             "SwXMLTableContext::InsertCell: row is full" );
    1578             :     OSL_ENSURE( nCurRow < USHRT_MAX,
    1579             :             "SwXMLTableContext::InsertCell: table is full" );
    1580         998 :     if( nCurCol >= USHRT_MAX || nCurRow > USHRT_MAX )
    1581         998 :         return;
    1582             : 
    1583             :     OSL_ENSURE( nRowSpan >=1UL, "SwXMLTableContext::InsertCell: row span is 0" );
    1584         998 :     if( 0UL == nRowSpan )
    1585           0 :         nRowSpan = 1UL;
    1586             :     OSL_ENSURE( nColSpan >=1UL, "SwXMLTableContext::InsertCell: col span is 0" );
    1587         998 :     if( 0UL == nColSpan )
    1588           0 :         nColSpan = 1UL;
    1589             : 
    1590             :     // Until it is possible to add columns here, fix the column span.
    1591         998 :     sal_uInt32 nColsReq = nCurCol + nColSpan;
    1592         998 :     if( nColsReq > GetColumnCount() )
    1593             :     {
    1594           0 :         nColSpan = GetColumnCount() - nCurCol;
    1595           0 :         nColsReq = GetColumnCount();
    1596             :     }
    1597             : 
    1598             :     // Check whether there are cells from a previous line already that reach
    1599             :     // into the current row.
    1600         998 :     if( nCurRow > 0UL && nColSpan > 1UL )
    1601             :     {
    1602           0 :         SwXMLTableRow_Impl *pCurRow = &(*pRows)[nCurRow];
    1603           0 :         sal_uInt32 nLastCol = GetColumnCount() < nColsReq ? GetColumnCount()
    1604           0 :                                                      : nColsReq;
    1605           0 :         for( sal_uInt32 i=nCurCol+1UL; i<nLastCol; ++i )
    1606             :         {
    1607           0 :             if( pCurRow->GetCell(i)->IsUsed() )
    1608             :             {
    1609             :                 // If this cell is used, the column span is truncated
    1610           0 :                 nColSpan = i - nCurCol;
    1611           0 :                 nColsReq = i;
    1612           0 :                 break;
    1613             :             }
    1614             :         }
    1615             :     }
    1616             : 
    1617         998 :     sal_uInt32 nRowsReq = nCurRow + nRowSpan;
    1618         998 :     if( nRowsReq > USHRT_MAX )
    1619             :     {
    1620           0 :         nRowSpan = USHRT_MAX - nCurRow;
    1621           0 :         nRowsReq = USHRT_MAX;
    1622             :     }
    1623             : 
    1624             :     // Add columns (if # required columns greater than # columns):
    1625             :     // This should never happen, since we require column definitions!
    1626         998 :     if ( nColsReq > GetColumnCount() )
    1627             :     {
    1628           0 :         for( sal_uInt32 i=GetColumnCount(); i<nColsReq; ++i )
    1629             :         {
    1630           0 :             aColumnWidths.push_back( ColumnWidthInfo(MINLAY, true) );
    1631             :         }
    1632             :         // adjust columns in *all* rows, if columns must be inserted
    1633           0 :         for( size_t i=0; i<pRows->size(); ++i )
    1634           0 :             (*pRows)[i].Expand( nColsReq, i<nCurRow );
    1635             :     }
    1636             : 
    1637             :     // Add rows
    1638         998 :     if( pRows->size() < nRowsReq )
    1639             :     {
    1640          12 :         for( size_t i = pRows->size(); i < nRowsReq; ++i )
    1641           6 :             pRows->push_back( new SwXMLTableRow_Impl("", GetColumnCount()));
    1642             :     }
    1643             : 
    1644         998 :     OUString sStyleName( rStyleName );
    1645         998 :     if( sStyleName.isEmpty() )
    1646             :     {
    1647         204 :         sStyleName = (*pRows)[nCurRow].GetDefaultCellStyleName();
    1648         204 :         if( sStyleName.isEmpty() && HasColumnDefaultCellStyleNames() )
    1649             :         {
    1650           0 :             sStyleName = GetColumnDefaultCellStyleName( nCurCol );
    1651           0 :             if( sStyleName.isEmpty() )
    1652           0 :                 sStyleName = aDfltCellStyleName;
    1653             :         }
    1654             :     }
    1655             : 
    1656             :     // Fill the cells
    1657        2044 :     for( sal_uInt32 i=nColSpan; i>0UL; --i )
    1658             :     {
    1659        2104 :         for( sal_uInt32 j=nRowSpan; j>0UL; --j )
    1660             :         {
    1661        1058 :             const bool bCovered = i != nColSpan || j != nRowSpan;
    1662             :             GetCell( nRowsReq-j, nColsReq-i )
    1663             :                 ->Set( sStyleName, j, i, pStartNode,
    1664             :                        pTable, bProtect, pFormula, bHasValue, bCovered, fValue,
    1665        1058 :                        pStringValue, i_rXmlId );
    1666             :         }
    1667             :     }
    1668             : 
    1669             :     // Set current col to the next (free) column
    1670         998 :     nCurCol = nColsReq;
    1671        2006 :     while( nCurCol<GetColumnCount() && GetCell(nCurRow,nCurCol)->IsUsed() )
    1672        1008 :         nCurCol++;
    1673             : }
    1674             : 
    1675         258 : void SwXMLTableContext::InsertRow( const OUString& rStyleName,
    1676             :                                    const OUString& rDfltCellStyleName,
    1677             :                                    bool bInHead,
    1678             :                                    const OUString & i_rXmlId )
    1679             : {
    1680             :     OSL_ENSURE( nCurRow < USHRT_MAX,
    1681             :             "SwXMLTableContext::InsertRow: no space left" );
    1682         258 :     if( nCurRow >= USHRT_MAX )
    1683         258 :         return;
    1684             : 
    1685             :     // Make sure there is at least one column.
    1686         258 :     if( 0==nCurRow && 0UL == GetColumnCount()  )
    1687           0 :         InsertColumn( USHRT_MAX, true );
    1688             : 
    1689         258 :     if( nCurRow < pRows->size() )
    1690             :     {
    1691             :         // The current row has already been inserted because of a row span
    1692             :         // of a previous row.
    1693           6 :         (*pRows)[nCurRow].Set(
    1694           6 :             rStyleName, rDfltCellStyleName, i_rXmlId );
    1695             :     }
    1696             :     else
    1697             :     {
    1698             :         // add a new row
    1699             :         pRows->push_back( new SwXMLTableRow_Impl( rStyleName, GetColumnCount(),
    1700         252 :                                                &rDfltCellStyleName, i_rXmlId ) );
    1701             :     }
    1702             : 
    1703             :     // We start at the first column ...
    1704         258 :     nCurCol=0UL;
    1705             : 
    1706             :     // ... but this cell may be occupied already.
    1707         518 :     while( nCurCol<GetColumnCount() && GetCell(nCurRow,nCurCol)->IsUsed() )
    1708           2 :         nCurCol++;
    1709             : 
    1710         258 :     if( bInHead  &&  nHeaderRows == nCurRow )
    1711           8 :         nHeaderRows++;
    1712             : }
    1713             : 
    1714           0 : void SwXMLTableContext::InsertRepRows( sal_uInt32 nCount )
    1715             : {
    1716           0 :     const SwXMLTableRow_Impl *pSrcRow = &(*pRows)[nCurRow-1];
    1717           0 :     while( nCount > 1 && IsInsertRowPossible() )
    1718             :     {
    1719           0 :         InsertRow( pSrcRow->GetStyleName(), pSrcRow->GetDefaultCellStyleName(),
    1720           0 :                    false );
    1721           0 :         while( nCurCol < GetColumnCount() )
    1722             :         {
    1723           0 :             if( !GetCell(nCurRow,nCurCol)->IsUsed() )
    1724             :             {
    1725             :                 const SwXMLTableCell_Impl *pSrcCell =
    1726           0 :                     GetCell( nCurRow-1, nCurCol );
    1727           0 :                 InsertCell( pSrcCell->GetStyleName(), 1U,
    1728             :                             pSrcCell->GetColSpan(),
    1729             :                             InsertTableSection(),
    1730             :                             OUString(),
    1731           0 :                             0, pSrcCell->IsProtected(),
    1732           0 :                             &pSrcCell->GetFormula(),
    1733           0 :                             pSrcCell->HasValue(), pSrcCell->GetValue(),
    1734           0 :                             pSrcCell->GetStringValue() );
    1735             :             }
    1736             :         }
    1737           0 :         FinishRow();
    1738           0 :         nCount--;
    1739             :     }
    1740           0 : }
    1741             : 
    1742         258 : void SwXMLTableContext::FinishRow()
    1743             : {
    1744             :     // Insert an empty cell at the end of the line if the row is not complete
    1745         258 :     if( nCurCol < GetColumnCount() )
    1746             :     {
    1747           0 :         InsertCell( "", 1U, GetColumnCount() - nCurCol,
    1748           0 :                     InsertTableSection() );
    1749             :     }
    1750             : 
    1751             :     // Move to the next row.
    1752         258 :     nCurRow++;
    1753         258 : }
    1754             : 
    1755          12 : const SwStartNode *SwXMLTableContext::GetPrevStartNode( sal_uInt32 nRow,
    1756             :                                                         sal_uInt32 nCol ) const
    1757             : {
    1758          12 :     const SwXMLTableCell_Impl *pPrevCell = 0;
    1759          12 :     if( GetColumnCount() == nCol )
    1760             :     {
    1761             :         // The last cell is the right one here.
    1762           0 :         pPrevCell = GetCell( pRows->size()-1U, GetColumnCount()-1UL );
    1763             :     }
    1764          12 :     else if( nCol > 0UL )
    1765             :     {
    1766             :         // The previous cell in this row.
    1767          10 :         pPrevCell = GetCell( nRow, nCol-1UL );
    1768             :     }
    1769           2 :     else if( nRow > 0UL )
    1770             :     {
    1771             :         // The last cell from the previous row.
    1772           2 :         pPrevCell = GetCell( nRow-1UL, GetColumnCount()-1UL );
    1773             :     }
    1774             : 
    1775          12 :     const SwStartNode *pSttNd = 0;
    1776          12 :     if( pPrevCell )
    1777             :     {
    1778          12 :         if( pPrevCell->GetStartNode() )
    1779          12 :             pSttNd = pPrevCell->GetStartNode();
    1780             :         // #i95726# - Some fault tolerance
    1781             : //        else
    1782           0 :         else if ( pPrevCell->GetSubTable() )
    1783           0 :             pSttNd = pPrevCell->GetSubTable()->GetLastStartNode();
    1784             : 
    1785             :         OSL_ENSURE( pSttNd != 0,
    1786             :                 "table corrupt" );
    1787             :     }
    1788             : 
    1789          12 :     return pSttNd;
    1790             : }
    1791             : 
    1792           0 : void SwXMLTableContext::FixRowSpan( sal_uInt32 nRow, sal_uInt32 nCol,
    1793             :                                     sal_uInt32 nColSpan )
    1794             : {
    1795           0 :     sal_uInt32 nLastCol = nCol + nColSpan;
    1796           0 :     for( sal_uInt32 i = nCol; i < nLastCol; i++ )
    1797             :     {
    1798           0 :         sal_uInt32 j = nRow;
    1799           0 :         sal_uInt32 nRowSpan = 1UL;
    1800           0 :         SwXMLTableCell_Impl *pCell = GetCell( j, i );
    1801           0 :         while( pCell && pCell->GetRowSpan() > 1UL )
    1802             :         {
    1803           0 :             pCell->SetRowSpan( nRowSpan++ );
    1804           0 :             pCell = j > 0UL ? GetCell( --j, i ) : 0;
    1805             :         }
    1806             :     }
    1807           0 : }
    1808             : 
    1809          12 : void SwXMLTableContext::ReplaceWithEmptyCell( sal_uInt32 nRow, sal_uInt32 nCol, bool bRows )
    1810             : {
    1811          12 :     const SwStartNode *pPrevSttNd = GetPrevStartNode( nRow, nCol );
    1812          12 :     const SwStartNode *pSttNd = InsertTableSection( pPrevSttNd );
    1813             : 
    1814          12 :     const SwXMLTableCell_Impl *pCell = GetCell( nRow, nCol );
    1815          12 :     sal_uInt32 nLastRow = bRows ? nRow + pCell->GetRowSpan() : nRow + 1;
    1816          12 :     sal_uInt32 nLastCol = nCol + pCell->GetColSpan();
    1817             : 
    1818          24 :     for( sal_uInt32 i=nRow; i<nLastRow; i++ )
    1819             :     {
    1820          12 :         SwXMLTableRow_Impl *pRow = &(*pRows)[i];
    1821          24 :         for( sal_uInt32 j=nCol; j<nLastCol; j++ )
    1822          12 :             pRow->GetCell( j )->SetStartNode( pSttNd );
    1823             :     }
    1824             : 
    1825          12 : }
    1826             : 
    1827        1010 : SwTableBox *SwXMLTableContext::NewTableBox( const SwStartNode *pStNd,
    1828             :                                              SwTableLine *pUpper )
    1829             : {
    1830             :     // The topmost table is the only table that maintains the two members
    1831             :     // pBox1 and bFirstSection.
    1832        1010 :     if( xParentTable.Is() )
    1833           0 :         return ((SwXMLTableContext *)&xParentTable)->NewTableBox( pStNd,
    1834           0 :                                                                   pUpper );
    1835             : 
    1836             :     SwTableBox *pBox;
    1837             : 
    1838        1112 :     if( pBox1 &&
    1839         102 :         pBox1->GetSttNd() == pStNd )
    1840             :     {
    1841             :         // if the StartNode is equal to the StartNode of the initially
    1842             :         // created box, we use this box
    1843         102 :         pBox = pBox1;
    1844         102 :         pBox->SetUpper( pUpper );
    1845         102 :         pBox1 = 0;
    1846             :     }
    1847             :     else
    1848         908 :         pBox = new SwTableBox( pBoxFmt, *pStNd, pUpper );
    1849             : 
    1850        1010 :     return pBox;
    1851             : }
    1852             : 
    1853        1010 : SwTableBoxFmt* SwXMLTableContext::GetSharedBoxFormat(
    1854             :     SwTableBox* pBox,
    1855             :     const OUString& rStyleName,
    1856             :     sal_Int32 nColumnWidth,
    1857             :     bool bProtected,
    1858             :     bool bMayShare,
    1859             :     bool& bNew,
    1860             :     bool* pModifyLocked )
    1861             : {
    1862        1010 :     if ( pSharedBoxFormats == NULL )
    1863         102 :         pSharedBoxFormats = new map_BoxFmt();
    1864             : 
    1865             :     SwTableBoxFmt* pBoxFmt2;
    1866             : 
    1867        1010 :     TableBoxIndex aKey( rStyleName, nColumnWidth, bProtected );
    1868        1010 :     map_BoxFmt::iterator aIter = pSharedBoxFormats->find( aKey );
    1869        1010 :     if ( aIter == pSharedBoxFormats->end() )
    1870             :     {
    1871             :         // unknown format so far -> construct a new one
    1872             : 
    1873             :         // get the old format, and reset all attributes
    1874             :         // (but preserve FillOrder)
    1875         450 :         pBoxFmt2 = (SwTableBoxFmt*)pBox->ClaimFrmFmt();
    1876         450 :         SwFmtFillOrder aFillOrder( pBoxFmt2->GetFillOrder() );
    1877         450 :         pBoxFmt2->ResetAllFmtAttr(); // #i73790# - method renamed
    1878         450 :         pBoxFmt2->SetFmtAttr( aFillOrder );
    1879         450 :         bNew = true;    // it's a new format now
    1880             : 
    1881             :         // share this format, if allowed
    1882         450 :         if ( bMayShare )
    1883         438 :             (*pSharedBoxFormats)[ aKey ] = pBoxFmt2;
    1884             :     }
    1885             :     else
    1886             :     {
    1887             :         // set the shared format
    1888         560 :         pBoxFmt2 = aIter->second;
    1889         560 :         pBox->ChgFrmFmt( pBoxFmt2 );
    1890         560 :         bNew = false;   // copied from an existing format
    1891             : 
    1892             :         // claim it, if we are not allowed to share
    1893         560 :         if ( !bMayShare )
    1894           0 :             pBoxFmt2 = (SwTableBoxFmt*)pBox->ClaimFrmFmt();
    1895             :     }
    1896             : 
    1897             :     // lock format (if so desired)
    1898        1010 :     if ( pModifyLocked != NULL )
    1899             :     {
    1900        1010 :         (*pModifyLocked) = pBoxFmt2->IsModifyLocked();
    1901        1010 :         pBoxFmt2->LockModify();
    1902             :     }
    1903             : 
    1904        1010 :     return pBoxFmt2;
    1905             : }
    1906             : 
    1907           0 : SwTableBox *SwXMLTableContext::MakeTableBox( SwTableLine *pUpper,
    1908             :                                              sal_uInt32 nTopRow,
    1909             :                                              sal_uInt32 nLeftCol,
    1910             :                                              sal_uInt32 nBottomRow,
    1911             :                                              sal_uInt32 nRightCol )
    1912             : {
    1913             :     //FIXME: here would be a great place to handle XmlId for cell
    1914           0 :     SwTableBox *pBox = new SwTableBox( pBoxFmt, 0, pUpper );
    1915             : 
    1916           0 :     sal_uInt32 nColSpan = nRightCol - nLeftCol;
    1917           0 :     sal_Int32 nColWidth = GetColumnWidth( nLeftCol, nColSpan );
    1918             : 
    1919             :     // TODO: Share formats!
    1920           0 :     SwFrmFmt *pFrmFmt = pBox->ClaimFrmFmt();
    1921           0 :     SwFmtFillOrder aFillOrder( pFrmFmt->GetFillOrder() );
    1922           0 :     pFrmFmt->ResetAllFmtAttr(); // #i73790# - method renamed
    1923           0 :     pFrmFmt->SetFmtAttr( aFillOrder );
    1924             : 
    1925           0 :     pFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nColWidth ) );
    1926             : 
    1927           0 :     SwTableLines& rLines = pBox->GetTabLines();
    1928           0 :     bool bSplitted = false;
    1929             : 
    1930           0 :     while( !bSplitted )
    1931             :     {
    1932           0 :         sal_uInt32 nStartRow = nTopRow;
    1933             :         sal_uInt32 i;
    1934             : 
    1935           0 :         for( i = nTopRow; i < nBottomRow; i++ )
    1936             :         {
    1937             :             // Could the table be splitted behind the current row?
    1938           0 :             bool bSplit = true;
    1939           0 :             SwXMLTableRow_Impl *pRow = &(*pRows)[(sal_uInt16)i];
    1940           0 :             for( sal_uInt32 j=nLeftCol; j<nRightCol; j++ )
    1941             :             {
    1942           0 :                 bSplit = ( 1UL == pRow->GetCell(j)->GetRowSpan() );
    1943           0 :                 if( !bSplit )
    1944           0 :                     break;
    1945             :             }
    1946           0 :             if( bSplit && (nStartRow>nTopRow || i+1UL<nBottomRow) )
    1947             :             {
    1948             :                 SwTableLine *pLine =
    1949             :                     MakeTableLine( pBox, nStartRow, nLeftCol, i+1UL,
    1950           0 :                                    nRightCol );
    1951             : 
    1952           0 :                 rLines.push_back( pLine );
    1953             : 
    1954           0 :                 nStartRow = i+1UL;
    1955           0 :                 bSplitted = true;
    1956             :             }
    1957             :         }
    1958           0 :         if( !bSplitted )
    1959             :         {
    1960             :             // No splitting was possible. That for, we have to force it.
    1961             :             // Ruthless!
    1962             : 
    1963           0 :             nStartRow = nTopRow;
    1964           0 :             while( nStartRow < nBottomRow )
    1965             :             {
    1966           0 :                 sal_uInt32 nMaxRowSpan = 0UL;
    1967           0 :                 SwXMLTableRow_Impl *pStartRow = &(*pRows)[nStartRow];
    1968             :                 const SwXMLTableCell_Impl *pCell;
    1969           0 :                 for( i=nLeftCol; i<nRightCol; i++ )
    1970           0 :                     if( ( pCell=pStartRow->GetCell(i),
    1971           0 :                           pCell->GetRowSpan() > nMaxRowSpan ) )
    1972           0 :                         nMaxRowSpan = pCell->GetRowSpan();
    1973             : 
    1974           0 :                 nStartRow += nMaxRowSpan;
    1975           0 :                 if( nStartRow<nBottomRow )
    1976             :                 {
    1977           0 :                     SwXMLTableRow_Impl *pPrevRow = &(*pRows)[nStartRow-1U];
    1978           0 :                     i = nLeftCol;
    1979           0 :                     while( i < nRightCol )
    1980             :                     {
    1981           0 :                         if( pPrevRow->GetCell(i)->GetRowSpan() > 1UL )
    1982             :                         {
    1983             :                             const SwXMLTableCell_Impl *pCell2 =
    1984           0 :                                 GetCell( nStartRow, i );
    1985           0 :                             const sal_uInt32 nColSpan2 = pCell2->GetColSpan();
    1986           0 :                             FixRowSpan( nStartRow-1UL, i, nColSpan2 );
    1987           0 :                             ReplaceWithEmptyCell( nStartRow, i, true );
    1988           0 :                             i += nColSpan2;
    1989             :                         }
    1990             :                         else
    1991             :                         {
    1992           0 :                             i++;
    1993             :                         }
    1994             :                     }
    1995             :                 }
    1996             :             }
    1997             :             // und jetzt nochmal von vorne ...
    1998             :         }
    1999             :     }
    2000             : 
    2001           0 :     return pBox;
    2002             : }
    2003             : 
    2004        1010 : SwTableBox *SwXMLTableContext::MakeTableBox(
    2005             :         SwTableLine *pUpper, const SwXMLTableCell_Impl *pCell,
    2006             :         sal_uInt32 /*nTopRow*/, sal_uInt32 nLeftCol, sal_uInt32 /*nBottomRow*/,
    2007             :         sal_uInt32 nRightCol )
    2008             : {
    2009             :     //FIXME: here would be a great place to handle XmlId for cell
    2010             :     SwTableBox *pBox;
    2011        1010 :     sal_uInt32 nColSpan = nRightCol - nLeftCol;
    2012        1010 :     sal_Int32 nColWidth = GetColumnWidth( nLeftCol, nColSpan );
    2013             : 
    2014        1010 :     if( pCell->GetStartNode() )
    2015             :     {
    2016        1010 :         pBox = NewTableBox( pCell->GetStartNode(), pUpper );
    2017             :     }
    2018             :     else
    2019             :     {
    2020             :         // and it is a table: therefore we build a new box and
    2021             :         // put the rows of the table into the rows of the box
    2022           0 :         pBox = new SwTableBox( pBoxFmt, 0, pUpper );
    2023           0 :         pCell->GetSubTable()->MakeTable( pBox, nColWidth );
    2024             :     }
    2025             : 
    2026             :     // Share formats!
    2027        1010 :     const OUString sStyleName = pCell->GetStyleName();
    2028             :     bool bModifyLocked;
    2029             :     bool bNew;
    2030             :     SwTableBoxFmt *pBoxFmt2 = GetSharedBoxFormat(
    2031        1010 :         pBox, sStyleName, nColWidth, pCell->IsProtected(),
    2032        2020 :         pCell->GetStartNode() && pCell->GetFormula().isEmpty() &&
    2033        1010 :             ! pCell->HasValue(),
    2034        2020 :         bNew, &bModifyLocked  );
    2035             : 
    2036             :     // if a new format was created, then we need to set the style
    2037        1010 :     if ( bNew )
    2038             :     {
    2039             :         // set style
    2040         450 :         const SfxItemSet *pAutoItemSet = 0;
    2041         890 :         if( pCell->GetStartNode() && !sStyleName.isEmpty() &&
    2042         440 :             GetSwImport().FindAutomaticStyle(
    2043         440 :                 XML_STYLE_FAMILY_TABLE_CELL, sStyleName, &pAutoItemSet ) )
    2044             :         {
    2045         440 :             if( pAutoItemSet )
    2046         440 :                 pBoxFmt2->SetFmtAttr( *pAutoItemSet );
    2047             :         }
    2048             :     }
    2049             : 
    2050        1010 :     if( pCell->GetStartNode() )
    2051             :     {
    2052        1010 :         if (pCell->HasStringValue())
    2053             :         {
    2054           2 :             SwNodeIndex const aNodeIndex(*(pCell->GetStartNode()), 1);
    2055           2 :             SwTxtNode *const pTxtNode(aNodeIndex.GetNode().GetTxtNode());
    2056             :             SAL_WARN_IF(!pTxtNode, "sw", "Should have a text node in cell?");
    2057           2 :             if (pTxtNode)
    2058             :             {
    2059             :                 SAL_WARN_IF(!pTxtNode->GetTxt().isEmpty(), "sw",
    2060             :                         "why text here?");
    2061           2 :                 pTxtNode->InsertText(*pCell->GetStringValue(),
    2062           4 :                         SwIndex(pTxtNode, 0));
    2063           2 :             }
    2064             :         }
    2065             : 
    2066             :         // try to rescue broken documents with a certain pattern
    2067             :         // if: 1) the cell has a default number format (number 0)
    2068             :         //     2) the call has no formula
    2069             :         //     3) the value is 0.0
    2070             :         //     4) the text doesn't look anything like 0.0
    2071             :         //        [read: length > 10, or length smaller 10 and no 0 in it]
    2072             :         // then make it a text cell!
    2073        1010 :         bool bSuppressNumericContent = false;
    2074        2032 :         if( pCell->HasValue() && (pCell->GetValue() == 0.0) &&
    2075        1010 :             pCell->GetFormula().isEmpty() &&
    2076           0 :             !sStyleName.isEmpty() )
    2077             :         {
    2078             :             // default num format?
    2079           0 :             const SfxPoolItem* pItem = NULL;
    2080           0 :             if( pBoxFmt2->GetItemState( RES_BOXATR_FORMAT, false, &pItem )
    2081             :                             == SfxItemState::SET )
    2082             :             {
    2083             :                 const SwTblBoxNumFormat* pNumFormat =
    2084           0 :                     static_cast<const SwTblBoxNumFormat*>( pItem );
    2085           0 :                 if( ( pNumFormat != NULL ) && ( pNumFormat->GetValue() == 0 ) )
    2086             :                 {
    2087             :                     // only one text node?
    2088           0 :                     SwNodeIndex aNodeIndex( *(pCell->GetStartNode()), 1 );
    2089           0 :                     if( ( aNodeIndex.GetNode().EndOfSectionIndex() -
    2090           0 :                           aNodeIndex.GetNode().StartOfSectionIndex() ) == 2 )
    2091             :                     {
    2092           0 :                         SwTxtNode* pTxtNode= aNodeIndex.GetNode().GetTxtNode();
    2093           0 :                         if( pTxtNode != NULL )
    2094             :                         {
    2095             :                             // check text: does it look like some form of 0.0?
    2096           0 :                             const OUString& rText = pTxtNode->GetTxt();
    2097           0 :                             if( ( rText.getLength() > 10 ) ||
    2098           0 :                                 ( rText.indexOf( '0' ) == -1 ) )
    2099             :                             {
    2100           0 :                                 bSuppressNumericContent = true;
    2101             :                             }
    2102             :                         }
    2103             :                     }
    2104             :                     else
    2105           0 :                         bSuppressNumericContent = true; // several nodes
    2106             :                 }
    2107             :             }
    2108             :         }
    2109             : 
    2110        1010 :         if( bSuppressNumericContent )
    2111             :         {
    2112             :             // suppress numeric content? Then reset number format!
    2113           0 :             pBoxFmt2->ResetFmtAttr( RES_BOXATR_FORMULA );
    2114           0 :             pBoxFmt2->ResetFmtAttr( RES_BOXATR_FORMAT );
    2115           0 :             pBoxFmt2->ResetFmtAttr( RES_BOXATR_VALUE );
    2116             :         }
    2117             :         else
    2118             :         {
    2119             :             // the normal case: set formula and value (if available)
    2120             : 
    2121        1010 :             const OUString& rFormula = pCell->GetFormula();
    2122        1010 :             if (!rFormula.isEmpty())
    2123             :             {
    2124             :                 // formula cell: insert formula if valid
    2125           0 :                 SwTblBoxFormula aFormulaItem( rFormula );
    2126           0 :                 pBoxFmt2->SetFmtAttr( aFormulaItem );
    2127             :             }
    2128        1010 :             else if (!pCell->HasValue() && pCell->HasStringValue())
    2129             :             {
    2130             :                 // Check for another inconsistency:
    2131             :                 // No value but a non-textual format, i.e. a number format
    2132             :                 // Solution: the number format will be removed,
    2133             :                 // the cell gets the default text format.
    2134           2 :                 const SfxPoolItem* pItem = NULL;
    2135           2 :                 if( pBoxFmt->GetItemState( RES_BOXATR_FORMAT, false, &pItem )
    2136             :                     == SfxItemState::SET )
    2137             :                 {
    2138           0 :                     const SwDoc* pDoc = pBoxFmt->GetDoc();
    2139             :                     const SvNumberFormatter* pNumberFormatter = pDoc ?
    2140           0 :                         pDoc->GetNumberFormatter() : 0;
    2141             :                     const SwTblBoxNumFormat* pNumFormat =
    2142           0 :                         static_cast<const SwTblBoxNumFormat*>( pItem );
    2143           0 :                     if( pNumFormat != NULL && pNumberFormatter &&
    2144           0 :                         !pNumberFormatter->GetEntry( pNumFormat->GetValue() )->IsTextFormat() )
    2145           0 :                         pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT );
    2146             :                 }
    2147             :             }
    2148             :             // always insert value, even if default
    2149        1010 :             if( pCell->HasValue() )
    2150             :             {
    2151          12 :                 SwTblBoxValue aValueItem( pCell->GetValue() );
    2152          12 :                 pBoxFmt2->SetFmtAttr( aValueItem );
    2153             :             }
    2154             :         }
    2155             : 
    2156             :         // update cell content depend on the default language
    2157        1010 :         pBox->ActualiseValueBox();
    2158             :     }
    2159             : 
    2160             :     // table cell protection
    2161        1010 :     if( pCell->IsProtected() )
    2162             :     {
    2163           0 :         SvxProtectItem aProtectItem( RES_PROTECT );
    2164           0 :         aProtectItem.SetCntntProtect( true );
    2165           0 :         pBoxFmt2->SetFmtAttr( aProtectItem );
    2166             :     }
    2167             : 
    2168             :     // restore old modify-lock state
    2169        1010 :     if (! bModifyLocked)
    2170        1010 :         pBoxFmt2->UnlockModify();
    2171             : 
    2172        1010 :     pBoxFmt2->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nColWidth ) );
    2173             : 
    2174        1010 :     return pBox;
    2175             : }
    2176             : 
    2177         258 : SwTableLine *SwXMLTableContext::MakeTableLine( SwTableBox *pUpper,
    2178             :                                                sal_uInt32 nTopRow,
    2179             :                                                sal_uInt32 nLeftCol,
    2180             :                                                sal_uInt32 nBottomRow,
    2181             :                                                sal_uInt32 nRightCol )
    2182             : {
    2183             :     //FIXME: here would be a great place to handle XmlId for row
    2184             :     SwTableLine *pLine;
    2185         258 :     if( !pUpper && 0UL==nTopRow )
    2186             :     {
    2187         102 :         pLine = pTableNode->GetTable().GetTabLines()[0U];
    2188             :     }
    2189             :     else
    2190             :     {
    2191         156 :         pLine = new SwTableLine( pLineFmt, 0, pUpper );
    2192             :     }
    2193             : 
    2194             :     // TODO: Share formats!
    2195         258 :     SwFrmFmt *pFrmFmt = pLine->ClaimFrmFmt();
    2196         258 :     SwFmtFillOrder aFillOrder( pFrmFmt->GetFillOrder() );
    2197         258 :     pFrmFmt->ResetAllFmtAttr(); // #i73790# - method renamed
    2198         258 :     pFrmFmt->SetFmtAttr( aFillOrder );
    2199             : 
    2200         258 :     const SfxItemSet *pAutoItemSet = 0;
    2201         258 :     const OUString& rStyleName = (*pRows)[nTopRow].GetStyleName();
    2202         774 :     if( 1UL == (nBottomRow - nTopRow) &&
    2203         366 :         !rStyleName.isEmpty() &&
    2204         108 :         GetSwImport().FindAutomaticStyle(
    2205         108 :             XML_STYLE_FAMILY_TABLE_ROW, rStyleName, &pAutoItemSet ) )
    2206             :     {
    2207         108 :         if( pAutoItemSet )
    2208         108 :             pFrmFmt->SetFmtAttr( *pAutoItemSet );
    2209             :     }
    2210             : 
    2211         258 :     SwTableBoxes& rBoxes = pLine->GetTabBoxes();
    2212             : 
    2213         258 :     sal_uInt32 nStartCol = nLeftCol;
    2214        1526 :     while( nStartCol < nRightCol )
    2215             :     {
    2216        2020 :         for( sal_uInt32 nRow=nTopRow; nRow<nBottomRow; nRow++ )
    2217        1010 :             (*pRows)[nRow].SetSplitable( true );
    2218             : 
    2219        1010 :         sal_uInt32 nCol = nStartCol;
    2220        1010 :         sal_uInt32 nSplitCol = nRightCol;
    2221        1010 :         bool bSplitted = false;
    2222        3078 :         while( !bSplitted )
    2223             :         {
    2224             :             OSL_ENSURE( nCol < nRightCol, "Zu weit gelaufen" );
    2225             : 
    2226             :             // Can be split after current HTML table column?
    2227             :             // If yes, can the created region still be split to
    2228             :             // rows if the next column is added to it?
    2229        1058 :             bool bSplit = true;
    2230        1058 :             bool bHoriSplitMayContinue = false;
    2231        1058 :             bool bHoriSplitPossible = false;
    2232             : 
    2233        1058 :             if ( bHasSubTables )
    2234             :             {
    2235             :                 // Convert row spans if the table has subtables:
    2236           0 :                 for( sal_uInt32 nRow=nTopRow; nRow<nBottomRow; nRow++ )
    2237             :                 {
    2238           0 :                     SwXMLTableCell_Impl *pCell = GetCell(nRow,nCol);
    2239             :                     // Could the table fragment be splitted horizontally behind
    2240             :                     // the current line?
    2241           0 :                     bool bHoriSplit = (*pRows)[nRow].IsSplitable() &&
    2242           0 :                                       nRow+1UL < nBottomRow &&
    2243           0 :                                       1UL == pCell->GetRowSpan();
    2244           0 :                     (*pRows)[nRow].SetSplitable( bHoriSplit );
    2245             : 
    2246             :                     // Could the table fragment be splitted vertically behind the
    2247             :                     // current column (uptp the current line?
    2248           0 :                     bSplit &= ( 1UL == pCell->GetColSpan() );
    2249           0 :                     if( bSplit )
    2250             :                     {
    2251           0 :                         bHoriSplitPossible |= bHoriSplit;
    2252             : 
    2253             :                         // Could the current table fragment be splitted
    2254             :                         // horizontally behind the next collumn, too?
    2255           0 :                         bHoriSplit &= (nCol+1UL < nRightCol &&
    2256           0 :                                        1UL == GetCell(nRow,nCol+1UL)->GetRowSpan());
    2257           0 :                         bHoriSplitMayContinue |= bHoriSplit;
    2258             :                     }
    2259             :                 }
    2260             :             }
    2261             :             else
    2262             :             {
    2263             :                 // No subtabels: We use the new table model.
    2264        1058 :                 SwXMLTableCell_Impl *pCell = GetCell(nTopRow,nCol);
    2265             : 
    2266             :                 // #i95726# - some fault tolerance
    2267        1058 :                 if ( pCell == 0 )
    2268             :                 {
    2269             :                     OSL_FAIL( "table seems to be corrupt." );
    2270           0 :                     break;
    2271             :                 }
    2272             : 
    2273             :                 // Could the table fragment be splitted vertically behind the
    2274             :                 // current column (uptp the current line?
    2275        1058 :                 bSplit = 1UL == pCell->GetColSpan();
    2276             :             }
    2277             : 
    2278             : #if OSL_DEBUG_LEVEL > 0
    2279             :             if( nCol == nRightCol-1UL )
    2280             :             {
    2281             :                 OSL_ENSURE( bSplit, "Split-Flag falsch" );
    2282             :                 if ( bHasSubTables )
    2283             :                 {
    2284             :                     OSL_ENSURE( !bHoriSplitMayContinue,
    2285             :                             "HoriSplitMayContinue-Flag falsch" );
    2286             :                     SwXMLTableCell_Impl *pTmpCell = GetCell( nTopRow, nStartCol );
    2287             :                     OSL_ENSURE( pTmpCell->GetRowSpan() != (nBottomRow-nTopRow) ||
    2288             :                             !bHoriSplitPossible, "HoriSplitPossible-Flag falsch" );
    2289             :                 }
    2290             :             }
    2291             : #endif
    2292             : 
    2293             :             OSL_ENSURE( !bHasSubTables || !bHoriSplitMayContinue || bHoriSplitPossible,
    2294             :                     "bHoriSplitMayContinue, aber nicht bHoriSplitPossible" );
    2295             : 
    2296        1058 :             if( bSplit )
    2297             :             {
    2298        1010 :                 SwTableBox* pBox = 0;
    2299        1010 :                 SwXMLTableCell_Impl *pCell = GetCell( nTopRow, nStartCol );
    2300             :                 // #i95726# - some fault tolerance
    2301        3030 :                 if( ( !bHasSubTables || ( pCell->GetRowSpan() == (nBottomRow-nTopRow) ) ) &&
    2302        4040 :                     pCell->GetColSpan() == (nCol+1UL-nStartCol) &&
    2303        1010 :                     ( pCell->GetStartNode() || pCell->GetSubTable() ) )
    2304             :                 {
    2305             :                     // insert new empty cell for covered cells:
    2306        1010 :                     long nBoxRowSpan = 1;
    2307        1010 :                     if ( !bHasSubTables )
    2308             :                     {
    2309        1010 :                         nBoxRowSpan = pCell->GetRowSpan();
    2310        1010 :                         if ( pCell->IsCovered() )
    2311             :                         {
    2312          12 :                             nBoxRowSpan = -1 * nBoxRowSpan;
    2313          12 :                             ReplaceWithEmptyCell( nTopRow, nStartCol, false );
    2314             :                         }
    2315             :                     }
    2316             : 
    2317             :                     // The remaining box neither contains lines nor rows (i.e.
    2318             :                     // is a content box
    2319        1010 :                     nSplitCol = nCol + 1UL;
    2320             : 
    2321             :                     pBox = MakeTableBox( pLine, pCell,
    2322             :                                          nTopRow, nStartCol,
    2323        1010 :                                          nBottomRow, nSplitCol );
    2324             : 
    2325        1010 :                     if ( 1 != nBoxRowSpan )
    2326          24 :                         pBox->setRowSpan( nBoxRowSpan );
    2327             : 
    2328        1010 :                     bSplitted = true;
    2329             :                 }
    2330           0 :                 else if( bHasSubTables && bHoriSplitPossible && bHoriSplitMayContinue )
    2331             :                 {
    2332             :                     // The table fragment could be splitted behind the current
    2333             :                     // column, and the remaining fragment could be divided
    2334             :                     // into lines. Anyway, it could be that this applies to
    2335             :                     // the next column, too. That for, we check the next
    2336             :                     // column but rememeber the current one as a good place to
    2337             :                     // split.
    2338           0 :                     nSplitCol = nCol + 1UL;
    2339             :                 }
    2340           0 :                 else if ( bHasSubTables )
    2341             :                 {
    2342             :                     // If the table resulting table fragment could be divided
    2343             :                     // into lines if spllitting behind the current column, but
    2344             :                     // this doesn't apply for thr next column, we split begind
    2345             :                     // the current column. This applies for the last column,
    2346             :                     // too.
    2347             :                     // If the resulting box cannot be splitted into rows,
    2348             :                     // the split at the last split position we remembered.
    2349           0 :                     if( bHoriSplitPossible || nSplitCol > nCol+1 )
    2350             :                     {
    2351             :                         OSL_ENSURE( !bHoriSplitMayContinue,
    2352             :                                 "bHoriSplitMayContinue==sal_True" );
    2353             :                         OSL_ENSURE( bHoriSplitPossible || nSplitCol == nRightCol,
    2354             :                                 "bHoriSplitPossible-Flag sollte gesetzt sein" );
    2355             : 
    2356           0 :                         nSplitCol = nCol + 1UL;
    2357             :                     }
    2358             : 
    2359             :                     pBox = MakeTableBox( pLine, nTopRow, nStartCol,
    2360           0 :                                          nBottomRow, nSplitCol );
    2361           0 :                     bSplitted = true;
    2362             :                 }
    2363             : 
    2364             :                 OSL_ENSURE( bHasSubTables || pBox, "Colspan trouble" );
    2365             : 
    2366        1010 :                 if( pBox )
    2367        1010 :                     rBoxes.push_back( pBox );
    2368             :             }
    2369        1058 :             nCol++;
    2370             :         }
    2371        1010 :         nStartCol = nSplitCol;
    2372             :     }
    2373             : 
    2374         258 :     return pLine;
    2375             : }
    2376             : 
    2377         102 : void SwXMLTableContext::_MakeTable( SwTableBox *pBox )
    2378             : {
    2379             :     // fix column widths
    2380         102 :     std::vector<ColumnWidthInfo>::iterator colIter;
    2381         102 :     sal_uInt32 nCols = GetColumnCount();
    2382             : 
    2383             :     // If there are empty rows (because of some row span of previous rows)
    2384             :     // the have to be deleted. The previous rows have to be truncated.
    2385             : 
    2386         102 :     if( pRows->size() > nCurRow )
    2387             :     {
    2388           0 :         SwXMLTableRow_Impl *pPrevRow = &(*pRows)[nCurRow-1U];
    2389             :         const SwXMLTableCell_Impl *pCell;
    2390           0 :         for( sal_uLong i = 0; i < aColumnWidths.size(); ++i )
    2391             :         {
    2392           0 :             if( ( pCell=pPrevRow->GetCell(i), pCell->GetRowSpan() > 1UL ) )
    2393             :             {
    2394           0 :                 FixRowSpan( nCurRow-1UL, i, 1UL );
    2395             :             }
    2396             :         }
    2397           0 :         for( sal_uLong i = pRows->size()-1UL; i>=nCurRow; --i )
    2398           0 :             pRows->pop_back();
    2399             :     }
    2400             : 
    2401         102 :     if( pRows->empty() )
    2402             :     {
    2403           0 :         InsertCell( "", 1U, nCols, InsertTableSection() );
    2404             :     }
    2405             : 
    2406             :     // TODO: Do we have to keep both values, the relative and the absolute
    2407             :     // width?
    2408         102 :     sal_Int32 nAbsWidth = 0L;
    2409         102 :     sal_Int32 nMinAbsColWidth = 0L;
    2410         102 :     sal_Int32 nRelWidth = 0L;
    2411         102 :     sal_Int32 nMinRelColWidth = 0L;
    2412         102 :     sal_uInt32 nRelCols = 0UL;
    2413         418 :     for( colIter = aColumnWidths.begin(); colIter < aColumnWidths.end(); ++colIter)
    2414             :     {
    2415         316 :         if( colIter->isRelative )
    2416             :         {
    2417          90 :             nRelWidth += colIter->width;
    2418          90 :             if( 0L == nMinRelColWidth || colIter->width < nMinRelColWidth )
    2419          50 :                 nMinRelColWidth = colIter->width;
    2420          90 :             nRelCols++;
    2421             :         }
    2422             :         else
    2423             :         {
    2424         226 :             nAbsWidth += colIter->width;
    2425         226 :             if( 0L == nMinAbsColWidth || colIter->width < nMinAbsColWidth )
    2426          64 :                 nMinAbsColWidth = colIter->width;
    2427             :         }
    2428             :     }
    2429         102 :     sal_uInt32 nAbsCols = nCols - nRelCols;
    2430             : 
    2431         102 :     if( bRelWidth )
    2432             :     {
    2433             :         // If there a columns that have an absolute width, we have to
    2434             :         // calculate a relative one for them.
    2435          48 :         if( nAbsCols > 0UL )
    2436             :         {
    2437             :             // All column that have absolute widths get relative widths;
    2438             :             // these widths relate to each over like the original absolute
    2439             :             // widths. The smallest column gets a width that hat the same
    2440             :             // value as the smallest column that has an relative width
    2441             :             // already.
    2442           6 :             if( 0L == nMinRelColWidth )
    2443           6 :                 nMinRelColWidth = nMinAbsColWidth;
    2444             : 
    2445          28 :             for( colIter = aColumnWidths.begin(); nAbsCols > 0UL && colIter < aColumnWidths.end(); ++colIter)
    2446             :             {
    2447          22 :                 if( !colIter->isRelative )
    2448             :                 {
    2449          22 :                     sal_Int32 nRelCol = ( colIter->width * nMinRelColWidth) / nMinAbsColWidth;
    2450          22 :                     colIter->width = nRelCol;
    2451          22 :                     colIter->isRelative = true;
    2452          22 :                     nRelWidth += nRelCol;
    2453          22 :                     nAbsCols--;
    2454             :                 }
    2455             :             }
    2456             :         }
    2457             : 
    2458          48 :         if( !nWidth )
    2459             :         {
    2460             :             // This happens only for percentage values for the table itself.
    2461             :             // In this case, the columns get the correct width even if the
    2462             :             // the sum of the relative withs is smaller than the available
    2463             :             // width in TWIP. Therfore, we can use the relative width.
    2464           0 :             nWidth = nRelWidth > USHRT_MAX ? USHRT_MAX : nRelWidth;
    2465             :         }
    2466          48 :         if( nRelWidth != nWidth && nRelWidth && nCols )
    2467             :         {
    2468          10 :             double n = (double)nWidth / (double)nRelWidth;
    2469          10 :             nRelWidth = 0L;
    2470          30 :             for( colIter = aColumnWidths.begin(); colIter < aColumnWidths.end() - 1; ++colIter)
    2471             :             {
    2472          20 :                 sal_Int32 nW = (sal_Int32)( colIter->width * n);
    2473          20 :                 colIter->width = (sal_uInt16)nW;
    2474          20 :                 nRelWidth += nW;
    2475             :             }
    2476          10 :             aColumnWidths.back().width = (nWidth-nRelWidth);
    2477             :         }
    2478             :     }
    2479             :     else
    2480             :     {
    2481             :         // If there are columns that have relative widths, we have to
    2482             :         // calculate a absolute widths for them.
    2483          54 :         if( nRelCols > 0UL )
    2484             :         {
    2485             :             // The absolute space that is available for all columns with a
    2486             :             // relative width.
    2487             :             sal_Int32 nAbsForRelWidth =
    2488           0 :                     nWidth > nAbsWidth ? nWidth - nAbsWidth : (sal_Int32)0L;
    2489             : 
    2490             :             // The relative width that has to be distributed in addition to
    2491             :             // equally widthed columns.
    2492           0 :             sal_Int32 nExtraRel = nRelWidth - (nRelCols * nMinRelColWidth);
    2493             : 
    2494             :             // The absolute space that may be distributed in addition to
    2495             :             // minimum widthed columns.
    2496           0 :             sal_Int32 nMinAbs = nRelCols * MINLAY;
    2497             :             sal_Int32 nExtraAbs =
    2498           0 :                     nAbsForRelWidth > nMinAbs ? nAbsForRelWidth - nMinAbs : (sal_Int32)0L;
    2499             : 
    2500           0 :             bool bMin = false;      // Do all columns get the mininum width?
    2501           0 :             bool bMinExtra = false; // Do all columns get the minimum width plus
    2502             :                                     // some extra space?
    2503             : 
    2504           0 :             if( nAbsForRelWidth <= nMinAbs )
    2505             :             {
    2506             :                 // If there is not enough space left for all columns to
    2507             :                 // get the minimum width, they get the minimum width, anyway.
    2508           0 :                 nAbsForRelWidth = nMinAbs;
    2509           0 :                 bMin = true;
    2510             :             }
    2511           0 :             else if( nAbsForRelWidth <= (nRelWidth * MINLAY) /
    2512             :                                         nMinRelColWidth )
    2513             :             {
    2514             :                 // If there is enougth space for all columns to get the
    2515             :                 // minimum width, but not to get a width that takes the
    2516             :                 // relative width into account, each column gets the minimum
    2517             :                 // width plus some extra space that is based on the additional
    2518             :                 // space that is available.
    2519           0 :                 bMinExtra = true;
    2520             :             }
    2521             :             // Otherwise, if there is enouth space for every column, every
    2522             :             // column gets this space.
    2523             : 
    2524           0 :             for( colIter = aColumnWidths.begin(); nRelCols > 0UL && colIter < aColumnWidths.end(); ++colIter )
    2525             :             {
    2526           0 :                 if( colIter->isRelative )
    2527             :                 {
    2528             :                     sal_Int32 nAbsCol;
    2529           0 :                     if( 1UL == nRelCols )
    2530             :                     {
    2531             :                         // The last column that has a relative width gets
    2532             :                         // all absolute space that is left.
    2533           0 :                         nAbsCol = nAbsForRelWidth;
    2534             :                     }
    2535             :                     else
    2536             :                     {
    2537           0 :                         if( bMin )
    2538             :                         {
    2539           0 :                             nAbsCol = MINLAY;
    2540             :                         }
    2541           0 :                         else if( bMinExtra )
    2542             :                         {
    2543           0 :                             sal_Int32 nExtraRelCol = colIter->width - nMinRelColWidth;
    2544           0 :                             nAbsCol = MINLAY + (nExtraRelCol * nExtraAbs) /
    2545           0 :                                                  nExtraRel;
    2546             :                         }
    2547             :                         else
    2548             :                         {
    2549           0 :                             nAbsCol = ( colIter->width * nAbsForRelWidth) / nRelWidth;
    2550             :                         }
    2551             :                     }
    2552           0 :                     colIter->width = nAbsCol;
    2553           0 :                     colIter->isRelative = false;
    2554           0 :                     nAbsForRelWidth -= nAbsCol;
    2555           0 :                     nAbsWidth += nAbsCol;
    2556           0 :                     nRelCols--;
    2557             :                 }
    2558             :             }
    2559             :         }
    2560             : 
    2561          54 :         if( nCols && nAbsWidth )
    2562             :         {
    2563          54 :             if( nAbsWidth < nWidth )
    2564             :             {
    2565             :                 // If the table's width is larger than the sum of the absolute
    2566             :                 // column widths, every column get some extra width.
    2567           0 :                 sal_Int32 nExtraAbs = nWidth - nAbsWidth;
    2568           0 :                 sal_Int32 nAbsLastCol = aColumnWidths.back().width + nExtraAbs;
    2569           0 :                 for( colIter = aColumnWidths.begin(); colIter < aColumnWidths.end()-1UL; ++colIter )
    2570             :                 {
    2571           0 :                     sal_Int32 nAbsCol = colIter->width;
    2572           0 :                     sal_Int32 nExtraAbsCol = (nAbsCol * nExtraAbs) /
    2573           0 :                                              nAbsWidth;
    2574           0 :                     nAbsCol += nExtraAbsCol;
    2575           0 :                     colIter->width = nAbsCol;
    2576           0 :                     nAbsLastCol -= nExtraAbsCol;
    2577             :                 }
    2578           0 :                 aColumnWidths.back().width = nAbsLastCol;
    2579             :             }
    2580          54 :             else if( nAbsWidth > nWidth )
    2581             :             {
    2582             :                 // If the table's width is smaller than the sum of the absolute
    2583             :                 // column widths, every column needs to shrink.
    2584             :                 // Every column gets the minimum width plus some extra width.
    2585           2 :                 sal_Int32 nExtraAbs = nWidth - (nCols * MINLAY);
    2586           2 :                 sal_Int32 nAbsLastCol = MINLAY + nExtraAbs;
    2587          16 :                 for( colIter = aColumnWidths.begin(); colIter < aColumnWidths.end()-1UL; ++colIter )
    2588             :                 {
    2589          14 :                     sal_Int32 nAbsCol = colIter->width;
    2590          14 :                     sal_Int32 nExtraAbsCol = (nAbsCol * nExtraAbs) /
    2591          14 :                                              nAbsWidth;
    2592          14 :                     nAbsCol = MINLAY + nExtraAbsCol;
    2593          14 :                     colIter->width = nAbsCol;
    2594          14 :                     nAbsLastCol -= nExtraAbsCol;
    2595             :                 }
    2596           2 :                 aColumnWidths.back().width = nAbsLastCol;
    2597             :             }
    2598             :         }
    2599             :     }
    2600             : 
    2601             :     SwTableLines& rLines =
    2602             :         pBox ? pBox->GetTabLines()
    2603         102 :              : pTableNode->GetTable().GetTabLines();
    2604             : 
    2605         102 :     sal_uInt32 nStartRow = 0UL;
    2606         102 :     sal_uInt32 nRows = pRows->size();
    2607         360 :     for(sal_uInt32 i=0UL; i<nRows; ++i )
    2608             :     {
    2609             :         // Could we split the table behind the current line?
    2610         258 :         bool bSplit = true;
    2611         258 :         if ( bHasSubTables )
    2612             :         {
    2613           0 :             SwXMLTableRow_Impl *pRow = &(*pRows)[i];
    2614           0 :             for( sal_uInt32 j=0UL; j<nCols; j++ )
    2615             :             {
    2616           0 :                 bSplit = ( 1UL == pRow->GetCell(j)->GetRowSpan() );
    2617           0 :                 if( !bSplit )
    2618           0 :                     break;
    2619             :             }
    2620             :         }
    2621             : 
    2622         258 :         if( bSplit )
    2623             :         {
    2624             :             SwTableLine *pLine =
    2625         258 :                 MakeTableLine( pBox, nStartRow, 0UL, i+1UL, nCols );
    2626         258 :             if( pBox || nStartRow>0UL )
    2627         156 :                 rLines.push_back( pLine );
    2628         258 :             nStartRow = i+1UL;
    2629             :         }
    2630             :     }
    2631         102 : }
    2632             : 
    2633         102 : void SwXMLTableContext::MakeTable()
    2634             : {
    2635             :     // this method will modify the document directly -> lock SolarMutex
    2636             :     // This will call all other MakeTable*(..) methods, so
    2637             :     // those don't need to be locked separately.
    2638         102 :     SolarMutexGuard aGuard;
    2639             : 
    2640             :     // #i97274# handle invalid tables
    2641         102 :     if (!pRows || pRows->empty() || !GetColumnCount())
    2642             :     {
    2643             :         OSL_FAIL("invalid table: no cells; deleting...");
    2644           0 :         pTableNode->GetDoc()->getIDocumentContentOperations().DeleteSection( pTableNode );
    2645           0 :         pTableNode = 0;
    2646           0 :         pBox1 = 0;
    2647           0 :         pSttNd1 = 0;
    2648         102 :         return;
    2649             :     }
    2650             : 
    2651         102 :     SwXMLImport& rSwImport = GetSwImport();
    2652             : 
    2653         102 :     SwFrmFmt *pFrmFmt = pTableNode->GetTable().GetFrmFmt();
    2654             : 
    2655         102 :     sal_Int16 eHoriOrient = text::HoriOrientation::FULL;
    2656         102 :     bool bSetHoriOrient = false;
    2657             : 
    2658         102 :     sal_uInt8 nPrcWidth = 0U;
    2659             : 
    2660         102 :     pTableNode->GetTable().SetRowsToRepeat( nHeaderRows );
    2661         102 :     pTableNode->GetTable().SetTableModel( !bHasSubTables );
    2662             : 
    2663         102 :     const SfxItemSet *pAutoItemSet = 0;
    2664         306 :     if( !aStyleName.isEmpty() &&
    2665             :         rSwImport.FindAutomaticStyle(
    2666         204 :             XML_STYLE_FAMILY_TABLE_TABLE, aStyleName, &pAutoItemSet ) &&
    2667             :          pAutoItemSet )
    2668             :     {
    2669             :         const SfxPoolItem *pItem;
    2670         102 :         const SvxLRSpaceItem *pLRSpace = 0;
    2671         102 :         if( SfxItemState::SET == pAutoItemSet->GetItemState( RES_LR_SPACE, false,
    2672         102 :                                                         &pItem ) )
    2673          46 :             pLRSpace = (const SvxLRSpaceItem *)pItem;
    2674             : 
    2675         102 :         if( SfxItemState::SET == pAutoItemSet->GetItemState( RES_HORI_ORIENT, false,
    2676         102 :                                                         &pItem ) )
    2677             :         {
    2678          96 :             eHoriOrient = ((const SwFmtHoriOrient *)pItem)->GetHoriOrient();
    2679          96 :             switch( eHoriOrient )
    2680             :             {
    2681             :             case text::HoriOrientation::FULL:
    2682          42 :                 if( pLRSpace )
    2683             :                 {
    2684          12 :                     eHoriOrient = text::HoriOrientation::NONE;
    2685          12 :                     bSetHoriOrient = true;
    2686             :                 }
    2687          42 :                 break;
    2688             :             case text::HoriOrientation::LEFT:
    2689          54 :                 if( pLRSpace )
    2690             :                 {
    2691          34 :                     eHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH;
    2692          34 :                     bSetHoriOrient = true;
    2693             :                 }
    2694          54 :                 break;
    2695             :             default:
    2696             :                 ;
    2697             :             }
    2698             :         }
    2699             :         else
    2700             :         {
    2701           6 :             bSetHoriOrient = true;
    2702             :         }
    2703             : 
    2704         102 :         const SwFmtFrmSize *pSize = 0;
    2705         102 :         if( SfxItemState::SET == pAutoItemSet->GetItemState( RES_FRM_SIZE, false,
    2706         102 :                                                         &pItem ) )
    2707          90 :             pSize = (const SwFmtFrmSize *)pItem;
    2708             : 
    2709         102 :         switch( eHoriOrient )
    2710             :         {
    2711             :         case text::HoriOrientation::FULL:
    2712             :         case text::HoriOrientation::NONE:
    2713             :             // For text::HoriOrientation::NONE we would prefer to use the sum
    2714             :             // of the relative column widths as reference width.
    2715             :             // Unfortunately this works only if this sum interpreted as
    2716             :             // twip value is larger than the space that is available.
    2717             :             // We don't know that space, so we have to use USHRT_MAX, too.
    2718             :             // Even if a size is specified, it will be ignored!
    2719          48 :             nWidth = USHRT_MAX;
    2720          48 :             break;
    2721             :         default:
    2722          54 :             if( pSize )
    2723             :             {
    2724          54 :                 if( pSize->GetWidthPercent() )
    2725             :                 {
    2726             :                     // The width will be set in _MakeTable
    2727           0 :                     nPrcWidth = pSize->GetWidthPercent();
    2728             :                 }
    2729             :                 else
    2730             :                 {
    2731          54 :                     nWidth = pSize->GetWidth();
    2732          54 :                     if( nWidth < (sal_Int32)GetColumnCount() * MINLAY )
    2733             :                     {
    2734           0 :                         nWidth = GetColumnCount() * MINLAY;
    2735             :                     }
    2736          54 :                     else if( nWidth > USHRT_MAX )
    2737             :                     {
    2738           0 :                         nWidth = USHRT_MAX;
    2739             :                     }
    2740          54 :                     bRelWidth = false;
    2741             :                 }
    2742             :             }
    2743             :             else
    2744             :             {
    2745             :                 eHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH == eHoriOrient
    2746           0 :                                     ? text::HoriOrientation::NONE : text::HoriOrientation::FULL;
    2747           0 :                 bSetHoriOrient = true;
    2748           0 :                 nWidth = USHRT_MAX;
    2749             :             }
    2750          54 :             break;
    2751             :         }
    2752             : 
    2753         102 :         pFrmFmt->SetFmtAttr( *pAutoItemSet );
    2754             :     }
    2755             :     else
    2756             :     {
    2757           0 :         bSetHoriOrient = true;
    2758           0 :         nWidth = USHRT_MAX;
    2759             :     }
    2760             : 
    2761         102 :     SwTableLine *pLine1 = pTableNode->GetTable().GetTabLines()[0U];
    2762             :     OSL_ENSURE( pBox1 == pLine1->GetTabBoxes()[0U],
    2763             :                 "Why is box 1 change?" );
    2764         102 :     pBox1->pSttNd = pSttNd1;
    2765         102 :     pLine1->GetTabBoxes().erase( pLine1->GetTabBoxes().begin() );
    2766             : 
    2767         102 :     pLineFmt = (SwTableLineFmt*)pLine1->GetFrmFmt();
    2768         102 :     pBoxFmt = (SwTableBoxFmt*)pBox1->GetFrmFmt();
    2769             : 
    2770         102 :     _MakeTable( 0 );
    2771             : 
    2772         102 :     if( bSetHoriOrient )
    2773          52 :         pFrmFmt->SetFmtAttr( SwFmtHoriOrient( 0, eHoriOrient ) );
    2774             : 
    2775             :     // This must be after the call to _MakeTable, because nWidth might be
    2776             :     // changed there.
    2777         102 :     pFrmFmt->LockModify();
    2778         102 :     SwFmtFrmSize aSize( ATT_VAR_SIZE, nWidth );
    2779         102 :     aSize.SetWidthPercent( nPrcWidth );
    2780         102 :     pFrmFmt->SetFmtAttr( aSize );
    2781         102 :     pFrmFmt->UnlockModify();
    2782             : 
    2783         360 :     for( size_t i=0; i<pRows->size(); i++ )
    2784         258 :         (*pRows)[i].Dispose();
    2785             : 
    2786             :     // now that table is complete, change into DDE table (if appropriate)
    2787         102 :     if (NULL != pDDESource)
    2788             :     {
    2789             :         // change existing table into DDE table:
    2790             :         // 1) Get DDE field type (get data from dde-source context),
    2791             :         SwDDEFieldType* pFldType = lcl_GetDDEFieldType( pDDESource,
    2792           0 :                                                         pTableNode );
    2793             : 
    2794             :         // 2) release the DDE source context,
    2795           0 :         pDDESource->ReleaseRef();
    2796             : 
    2797             :         // 3) create new DDE table, and
    2798           0 :         SwDDETable* pDDETable = new SwDDETable( pTableNode->GetTable(),
    2799           0 :                                                 pFldType, false );
    2800             : 
    2801             :         // 4) set new (DDE)table at node.
    2802           0 :         pTableNode->SetNewTable(pDDETable, false);
    2803             :     }
    2804             : 
    2805             :     // ??? this is always false: root frame is only created in SwViewShell::Init
    2806         102 :     if( pTableNode->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell() )
    2807             :     {
    2808          32 :         pTableNode->DelFrms();
    2809          32 :         SwNodeIndex aIdx( *pTableNode->EndOfSectionNode(), 1 );
    2810          32 :         pTableNode->MakeFrms( &aIdx );
    2811         102 :     }
    2812             : }
    2813             : 
    2814           0 : void SwXMLTableContext::MakeTable( SwTableBox *pBox, sal_Int32 nW )
    2815             : {
    2816             :     //FIXME: here would be a great place to handle XmlId for subtable
    2817           0 :     pLineFmt = GetParentTable()->pLineFmt;
    2818           0 :     pBoxFmt = GetParentTable()->pBoxFmt;
    2819           0 :     nWidth = nW;
    2820           0 :     bRelWidth = GetParentTable()->bRelWidth;
    2821             : 
    2822           0 :     _MakeTable( pBox );
    2823             : 
    2824           0 :     for (size_t i=0; i < pRows->size(); ++i) // i113600, to break the cyclic reference to SwXMLTableContext object
    2825           0 :         (*pRows)[i].Dispose();
    2826           0 : }
    2827             : 
    2828        1010 : const SwStartNode *SwXMLTableContext::InsertTableSection(
    2829             :         const SwStartNode *const pPrevSttNd,
    2830             :         OUString const*const pStringValueStyleName)
    2831             : {
    2832             :     // The topmost table is the only table that maintains the two members
    2833             :     // pBox1 and bFirstSection.
    2834        1010 :     if( xParentTable.Is() )
    2835           0 :         return static_cast<SwXMLTableContext *>(&xParentTable)
    2836           0 :                     ->InsertTableSection(pPrevSttNd, pStringValueStyleName);
    2837             : 
    2838             :     const SwStartNode *pStNd;
    2839        2020 :     Reference<XUnoTunnel> xCrsrTunnel( GetImport().GetTextImport()->GetCursor(),
    2840        1010 :                                        UNO_QUERY);
    2841             :     OSL_ENSURE( xCrsrTunnel.is(), "missing XUnoTunnel for Cursor" );
    2842             :     OTextCursorHelper *pTxtCrsr = reinterpret_cast< OTextCursorHelper * >(
    2843        1010 :             sal::static_int_cast< sal_IntPtr >( xCrsrTunnel->getSomething( OTextCursorHelper::getUnoTunnelId() )));
    2844             :     OSL_ENSURE( pTxtCrsr, "SwXTextCursor missing" );
    2845             : 
    2846        1010 :     if( bFirstSection )
    2847             :     {
    2848             :         // The Cursor already is in the first section
    2849         102 :         pStNd = pTxtCrsr->GetPaM()->GetNode().FindTableBoxStartNode();
    2850         102 :         bFirstSection = false;
    2851         102 :         GetImport().GetTextImport()->SetStyleAndAttrs( GetImport(),
    2852         204 :             GetImport().GetTextImport()->GetCursor(), "Standard", true );
    2853             :     }
    2854             :     else
    2855             :     {
    2856         908 :         SwDoc* pDoc = SwImport::GetDocFromXMLImport( GetSwImport() );
    2857          12 :         const SwEndNode *pEndNd = pPrevSttNd ? pPrevSttNd->EndOfSectionNode()
    2858         920 :                                              : pTableNode->EndOfSectionNode();
    2859             :         // #i78921# - make code robust
    2860             :         OSL_ENSURE( pDoc, "<SwXMLTableContext::InsertTableSection(..)> - no <pDoc> at <SwXTextCursor> instance - <SwXTextCurosr> doesn't seem to be registered at a <SwUnoCrsr> instance." );
    2861         908 :         if ( !pDoc )
    2862             :         {
    2863           0 :             pDoc = const_cast<SwDoc*>(pEndNd->GetDoc());
    2864             :         }
    2865         908 :         sal_uInt32 nOffset = pPrevSttNd ? 1UL : 0UL;
    2866         908 :         SwNodeIndex aIdx( *pEndNd, nOffset );
    2867             :         SwTxtFmtColl *pColl =
    2868         908 :             pDoc->getIDocumentStylePoolAccess().GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false );
    2869         908 :         pStNd = pDoc->GetNodes().MakeTextSection( aIdx, SwTableBoxStartNode,
    2870         908 :                                                  pColl );
    2871             :         // Consider the case that a table is defined without a row.
    2872         908 :         if( !pPrevSttNd && pBox1 != NULL )
    2873             : 
    2874             :         {
    2875         896 :             pBox1->pSttNd = pStNd;
    2876        1792 :             SwCntntNode *pCNd = pDoc->GetNodes()[ pStNd->GetIndex() + 1 ]
    2877        1792 :                                                             ->GetCntntNode();
    2878         896 :             SwPosition aPos( *pCNd );
    2879         896 :             aPos.nContent.Assign( pCNd, 0U );
    2880             : 
    2881             :             const uno::Reference< text::XTextRange > xTextRange =
    2882        1792 :                 SwXTextRange::CreateXTextRange( *pDoc, aPos, 0 );
    2883        1792 :             Reference < XText > xText = xTextRange->getText();
    2884             :             Reference < XTextCursor > xTextCursor =
    2885        1792 :                 xText->createTextCursorByRange( xTextRange );
    2886        1792 :             GetImport().GetTextImport()->SetCursor( xTextCursor );
    2887         908 :         }
    2888             :     }
    2889             : 
    2890        1010 :     if (pStringValueStyleName)
    2891             :     {   // fdo#62147: apply style to paragraph on string-value cell
    2892           2 :         GetImport().GetTextImport()->SetStyleAndAttrs( GetImport(),
    2893           4 :             GetImport().GetTextImport()->GetCursor(), *pStringValueStyleName,
    2894           2 :             true, false, -1, false); // parameters same as sCellParaStyleName
    2895             :     }
    2896             : 
    2897        1010 :     return pStNd;
    2898             : }
    2899             : 
    2900         102 : void SwXMLTableContext::EndElement()
    2901             : {
    2902         102 :     if( IsValid() && !xParentTable.Is() )
    2903             :     {
    2904         102 :         MakeTable();
    2905         102 :         GetImport().GetTextImport()->SetCursor( xOldCursor );
    2906             :     }
    2907         102 : }
    2908             : 
    2909           0 : Reference < XTextContent > SwXMLTableContext::GetXTextContent() const
    2910             : {
    2911           0 :     return xTextContent;
    2912         270 : }
    2913             : 
    2914             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10