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

Generated by: LCOV version 1.11