LCOV - code coverage report
Current view: top level - libreoffice/sc/source/filter/html - htmlpars.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 445 1666 26.7 %
Date: 2012-12-27 Functions: 83 159 52.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             : 
      21             : #include <boost/shared_ptr.hpp>
      22             : #include <comphelper/string.hxx>
      23             : 
      24             : #define SC_HTMLPARS_CXX
      25             : #include "scitems.hxx"
      26             : #include <editeng/eeitem.hxx>
      27             : 
      28             : #include <svtools/htmlcfg.hxx>
      29             : #include <svx/algitem.hxx>
      30             : #include <editeng/colritem.hxx>
      31             : #include <editeng/brshitem.hxx>
      32             : #include <editeng/editeng.hxx>
      33             : #include <editeng/fhgtitem.hxx>
      34             : #include <editeng/fontitem.hxx>
      35             : #include <editeng/postitem.hxx>
      36             : #include <editeng/udlnitem.hxx>
      37             : #include <editeng/wghtitem.hxx>
      38             : #include <editeng/boxitem.hxx>
      39             : #include <editeng/justifyitem.hxx>
      40             : #include <sfx2/objsh.hxx>
      41             : #include <svl/eitem.hxx>
      42             : #include <svl/intitem.hxx>
      43             : #include <svtools/filter.hxx>
      44             : #include <svtools/parhtml.hxx>
      45             : #include <svtools/htmlkywd.hxx>
      46             : #include <svtools/htmltokn.h>
      47             : #include <sfx2/docfile.hxx>
      48             : 
      49             : #include <vcl/svapp.hxx>
      50             : #include <tools/urlobj.hxx>
      51             : #include <tools/tenccvt.hxx>
      52             : 
      53             : #include "htmlpars.hxx"
      54             : #include "global.hxx"
      55             : #include "document.hxx"
      56             : #include "rangelst.hxx"
      57             : 
      58             : #include <orcus/css_parser.hpp>
      59             : 
      60             : #include <com/sun/star/document/XDocumentProperties.hpp>
      61             : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
      62             : 
      63             : using ::editeng::SvxBorderLine;
      64             : using namespace ::com::sun::star;
      65             : 
      66           1 : ScHTMLStyles::ScHTMLStyles() : maEmpty() {}
      67             : 
      68           0 : void ScHTMLStyles::add(const char* pElemName, size_t nElemName, const char* pClassName, size_t nClassName,
      69             :                        const rtl::OUString& aProp, const rtl::OUString& aValue)
      70             : {
      71           0 :     if (pElemName)
      72             :     {
      73           0 :         rtl::OUString aElem(pElemName, nElemName, RTL_TEXTENCODING_UTF8);
      74           0 :         aElem = aElem.toAsciiLowerCase();
      75           0 :         if (pClassName)
      76             :         {
      77             :             // Both element and class names given.
      78             : 
      79           0 :             ElemsType::iterator itrElem = maElemProps.find(aElem);
      80           0 :             if (itrElem == maElemProps.end())
      81             :             {
      82             :                 // new element
      83             :                 SAL_WNODEPRECATED_DECLARATIONS_PUSH
      84           0 :                 std::auto_ptr<NamePropsType> p(new NamePropsType);
      85             :                 SAL_WNODEPRECATED_DECLARATIONS_POP
      86           0 :                 std::pair<ElemsType::iterator, bool> r = maElemProps.insert(aElem, p);
      87           0 :                 if (!r.second)
      88             :                     // insertion failed.
      89           0 :                     return;
      90           0 :                 itrElem = r.first;
      91             :             }
      92             : 
      93           0 :             NamePropsType* pClsProps = itrElem->second;
      94           0 :             rtl::OUString aClass(pClassName, nClassName, RTL_TEXTENCODING_UTF8);
      95           0 :             aClass = aClass.toAsciiLowerCase();
      96           0 :             insertProp(*pClsProps, aClass, aProp, aValue);
      97             :         }
      98             :         else
      99             :         {
     100             :             // Element name only. Add it to the element global.
     101           0 :             insertProp(maElemGlobalProps, aElem, aProp, aValue);
     102           0 :         }
     103             :     }
     104             :     else
     105             :     {
     106           0 :         if (pClassName)
     107             :         {
     108             :             // Class name only. Add it to the global.
     109           0 :             rtl::OUString aClass(pClassName, nClassName, RTL_TEXTENCODING_UTF8);
     110           0 :             aClass = aClass.toAsciiLowerCase();
     111           0 :             insertProp(maGlobalProps, aClass, aProp, aValue);
     112             :         }
     113             :     }
     114             : }
     115             : 
     116           0 : const rtl::OUString& ScHTMLStyles::getPropertyValue(
     117             :     const rtl::OUString& rElem, const rtl::OUString& rClass, const rtl::OUString& rPropName) const
     118             : {
     119             :     // First, look into the element-class storage.
     120             :     {
     121           0 :         ElemsType::const_iterator itr = maElemProps.find(rElem);
     122           0 :         if (itr != maElemProps.end())
     123             :         {
     124           0 :             const NamePropsType* pClasses = itr->second;
     125           0 :             NamePropsType::const_iterator itr2 = pClasses->find(rClass);
     126           0 :             if (itr2 != pClasses->end())
     127             :             {
     128           0 :                 const PropsType* pProps = itr2->second;
     129           0 :                 PropsType::const_iterator itr3 = pProps->find(rPropName);
     130           0 :                 if (itr3 != pProps->end())
     131           0 :                     return itr3->second;
     132             :             }
     133             :         }
     134             :     }
     135             :     // Next, look into the class global storage.
     136             :     {
     137           0 :         NamePropsType::const_iterator itr = maGlobalProps.find(rClass);
     138           0 :         if (itr != maGlobalProps.end())
     139             :         {
     140           0 :             const PropsType* pProps = itr->second;
     141           0 :             PropsType::const_iterator itr2 = pProps->find(rPropName);
     142           0 :             if (itr2 != pProps->end())
     143           0 :                 return itr2->second;
     144             :         }
     145             :     }
     146             :     // As the last resort, look into the element global storage.
     147             :     {
     148           0 :         NamePropsType::const_iterator itr = maElemGlobalProps.find(rClass);
     149           0 :         if (itr != maElemGlobalProps.end())
     150             :         {
     151           0 :             const PropsType* pProps = itr->second;
     152           0 :             PropsType::const_iterator itr2 = pProps->find(rPropName);
     153           0 :             if (itr2 != pProps->end())
     154           0 :                 return itr2->second;
     155             :         }
     156             :     }
     157             : 
     158           0 :     return maEmpty; // nothing found.
     159             : }
     160             : 
     161           0 : void ScHTMLStyles::insertProp(
     162             :     NamePropsType& rStore, const rtl::OUString& aName,
     163             :     const rtl::OUString& aProp, const rtl::OUString& aValue)
     164             : {
     165           0 :     NamePropsType::iterator itr = rStore.find(aName);
     166           0 :     if (itr == rStore.end())
     167             :     {
     168             :         // new element
     169             :         SAL_WNODEPRECATED_DECLARATIONS_PUSH
     170           0 :         std::auto_ptr<PropsType> p(new PropsType);
     171             :         SAL_WNODEPRECATED_DECLARATIONS_POP
     172           0 :         std::pair<NamePropsType::iterator, bool> r = rStore.insert(aName, p);
     173           0 :         if (!r.second)
     174             :             // insertion failed.
     175           0 :             return;
     176             : 
     177           0 :         itr = r.first;
     178             :     }
     179             : 
     180           0 :     PropsType* pProps = itr->second;
     181           0 :     pProps->insert(PropsType::value_type(aProp, aValue));
     182             : }
     183             : 
     184             : // ============================================================================
     185             : // BASE class for HTML parser classes
     186             : // ============================================================================
     187             : 
     188           1 : ScHTMLParser::ScHTMLParser( EditEngine* pEditEngine, ScDocument* pDoc ) :
     189             :     ScEEParser( pEditEngine ),
     190           1 :     mpDoc( pDoc )
     191             : {
     192           1 :     SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
     193           8 :     for( sal_uInt16 nIndex = 0; nIndex < SC_HTML_FONTSIZES; ++nIndex )
     194           7 :         maFontHeights[ nIndex ] = rHtmlOptions.GetFontSize( nIndex ) * 20;
     195           1 : }
     196             : 
     197           1 : ScHTMLParser::~ScHTMLParser()
     198             : {
     199           1 : }
     200             : 
     201           0 : ScHTMLStyles& ScHTMLParser::GetStyles()
     202             : {
     203           0 :     return maStyles;
     204             : }
     205             : 
     206           0 : ScDocument& ScHTMLParser::GetDoc()
     207             : {
     208           0 :     return *mpDoc;
     209             : }
     210             : 
     211             : // ============================================================================
     212             : 
     213           0 : ScHTMLLayoutParser::ScHTMLLayoutParser(
     214             :     EditEngine* pEditP, const String& rBaseURL, const Size& aPageSizeP,
     215             :     ScDocument* pDocP ) :
     216             :         ScHTMLParser( pEditP, pDocP ),
     217             :         aPageSize( aPageSizeP ),
     218             :         aBaseURL( rBaseURL ),
     219           0 :         xLockedList( new ScRangeList ),
     220             :         pTables( NULL ),
     221           0 :         pColOffset( new ScHTMLColOffset ),
     222           0 :         pLocalColOffset( new ScHTMLColOffset ),
     223             :         nFirstTableCell(0),
     224             :         nTableLevel(0),
     225             :         nTable(0),
     226             :         nMaxTable(0),
     227             :         nColCntStart(0),
     228             :         nMaxCol(0),
     229             :         nTableWidth(0),
     230             :         nColOffset(0),
     231             :         nColOffsetStart(0),
     232             :         nOffsetTolerance( SC_HTML_OFFSET_TOLERANCE_SMALL ),
     233             :         bTabInTabCell( false ),
     234             :         bFirstRow( true ),
     235             :         bInCell( false ),
     236           0 :         bInTitle( false )
     237             : {
     238           0 :     MakeColNoRef( pLocalColOffset, 0, 0, 0, 0 );
     239           0 :     MakeColNoRef( pColOffset, 0, 0, 0, 0 );
     240           0 : }
     241             : 
     242             : 
     243           0 : ScHTMLLayoutParser::~ScHTMLLayoutParser()
     244             : {
     245           0 :     while ( !aTableStack.empty() )
     246             :     {
     247           0 :         ScHTMLTableStackEntry* pS = aTableStack.top();
     248           0 :         aTableStack.pop();
     249             : 
     250           0 :         bool found = false;
     251           0 :         for ( size_t i = 0, nListSize = maList.size(); i < nListSize; ++i )
     252             :         {
     253           0 :             if ( pS->pCellEntry == maList[ i ] )
     254             :             {
     255           0 :                 found = true;
     256           0 :                 break;
     257             :             }
     258             :         }
     259           0 :         if ( !found )
     260           0 :             delete pS->pCellEntry;
     261           0 :         if ( pS->pLocalColOffset != pLocalColOffset )
     262           0 :             delete pS->pLocalColOffset;
     263           0 :         delete pS;
     264             :     }
     265           0 :     if ( pLocalColOffset )
     266           0 :         delete pLocalColOffset;
     267           0 :     if ( pColOffset )
     268           0 :         delete pColOffset;
     269           0 :     if ( pTables )
     270             :     {
     271           0 :         for( OuterMap::const_iterator it = pTables->begin(); it != pTables->end(); ++it)
     272           0 :             delete it->second;
     273           0 :         delete pTables;
     274             :     }
     275           0 : }
     276             : 
     277             : 
     278           0 : sal_uLong ScHTMLLayoutParser::Read( SvStream& rStream, const String& rBaseURL )
     279             : {
     280           0 :     Link aOldLink = pEdit->GetImportHdl();
     281           0 :     pEdit->SetImportHdl( LINK( this, ScHTMLLayoutParser, HTMLImportHdl ) );
     282             : 
     283           0 :     SfxObjectShell* pObjSh = mpDoc->GetDocumentShell();
     284           0 :     bool bLoading = pObjSh && pObjSh->IsLoading();
     285             : 
     286           0 :     SvKeyValueIteratorRef xValues;
     287           0 :     SvKeyValueIterator* pAttributes = NULL;
     288           0 :     if ( bLoading )
     289           0 :         pAttributes = pObjSh->GetHeaderAttributes();
     290             :     else
     291             :     {
     292             :         //  When not loading, set up fake http headers to force the SfxHTMLParser to use UTF8
     293             :         //  (used when pasting from clipboard)
     294             : 
     295           0 :         const sal_Char* pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 );
     296           0 :         if( pCharSet )
     297             :         {
     298           0 :             String aContentType = rtl::OUString( "text/html; charset=" );
     299           0 :             aContentType.AppendAscii( pCharSet );
     300             : 
     301           0 :             xValues = new SvKeyValueIterator;
     302           0 :             xValues->Append( SvKeyValue( rtl::OUString( OOO_STRING_SVTOOLS_HTML_META_content_type ), aContentType ) );
     303           0 :             pAttributes = xValues;
     304             :         }
     305             :     }
     306             : 
     307           0 :     sal_uLong nErr = pEdit->Read( rStream, rBaseURL, EE_FORMAT_HTML, pAttributes );
     308             : 
     309           0 :     pEdit->SetImportHdl( aOldLink );
     310             :     // Spaltenbreiten erzeugen
     311           0 :     Adjust();
     312           0 :     OutputDevice* pDefaultDev = Application::GetDefaultDevice();
     313           0 :     sal_uInt16 nCount = pColOffset->size();
     314           0 :     sal_uLong nOff = (*pColOffset)[0];
     315           0 :     Size aSize;
     316           0 :     for ( sal_uInt16 j = 1; j < nCount; j++ )
     317             :     {
     318           0 :         aSize.Width() = (*pColOffset)[j] - nOff;
     319           0 :         aSize = pDefaultDev->PixelToLogic( aSize, MapMode( MAP_TWIP ) );
     320           0 :         maColWidths[ j-1 ] = aSize.Width();
     321           0 :         nOff = (*pColOffset)[j];
     322             :     }
     323           0 :     return nErr;
     324             : }
     325             : 
     326             : 
     327           0 : const ScHTMLTable* ScHTMLLayoutParser::GetGlobalTable() const
     328             : {
     329           0 :     return 0;
     330             : }
     331             : 
     332             : 
     333           0 : void ScHTMLLayoutParser::NewActEntry( ScEEParseEntry* pE )
     334             : {
     335           0 :     ScEEParser::NewActEntry( pE );
     336           0 :     if ( pE )
     337             :     {
     338           0 :         if ( !pE->aSel.HasRange() )
     339             :         {   // komplett leer, nachfolgender Text landet im gleichen Absatz!
     340           0 :             pActEntry->aSel.nStartPara = pE->aSel.nEndPara;
     341           0 :             pActEntry->aSel.nStartPos = pE->aSel.nEndPos;
     342             :         }
     343             :     }
     344           0 :     pActEntry->aSel.nEndPara = pActEntry->aSel.nStartPara;
     345           0 :     pActEntry->aSel.nEndPos = pActEntry->aSel.nStartPos;
     346           0 : }
     347             : 
     348             : 
     349           0 : void ScHTMLLayoutParser::EntryEnd( ScEEParseEntry* pE, const ESelection& rSel )
     350             : {
     351           0 :     if ( rSel.nEndPara >= pE->aSel.nStartPara )
     352             :     {
     353           0 :         pE->aSel.nEndPara = rSel.nEndPara;
     354           0 :         pE->aSel.nEndPos = rSel.nEndPos;
     355             :     }
     356           0 :     else if ( rSel.nStartPara == pE->aSel.nStartPara - 1 && !pE->aSel.HasRange() )
     357             :     {   // kein Absatz angehaengt aber leer, nichts tun
     358             :     }
     359             :     else
     360             :     {
     361             :         OSL_FAIL( "EntryEnd: EditEngine ESelection End < Start" );
     362             :     }
     363           0 : }
     364             : 
     365             : 
     366           0 : void ScHTMLLayoutParser::NextRow( ImportInfo* pInfo )
     367             : {
     368           0 :     if ( bInCell )
     369           0 :         CloseEntry( pInfo );
     370           0 :     if ( nRowMax < ++nRowCnt )
     371           0 :         nRowMax = nRowCnt;
     372           0 :     nColCnt = nColCntStart;
     373           0 :     nColOffset = nColOffsetStart;
     374           0 :     bFirstRow = false;
     375           0 : }
     376             : 
     377             : 
     378           0 : bool ScHTMLLayoutParser::SeekOffset( ScHTMLColOffset* pOffset, sal_uInt16 nOffset,
     379             :         SCCOL* pCol, sal_uInt16 nOffsetTol )
     380             : {
     381             :     OSL_ENSURE( pOffset, "ScHTMLLayoutParser::SeekOffset - illegal call" );
     382           0 :     ScHTMLColOffset::const_iterator it = pOffset->find( nOffset );
     383           0 :     bool bFound = it != pOffset->end();
     384           0 :     sal_uInt16 nPos = it - pOffset->begin();
     385           0 :     *pCol = static_cast<SCCOL>(nPos);
     386           0 :     if ( bFound )
     387           0 :         return true;
     388           0 :     sal_uInt16 nCount = pOffset->size();
     389           0 :     if ( !nCount )
     390           0 :         return false;
     391             :     // nPos ist Einfuegeposition, da liegt der Naechsthoehere (oder auch nicht)
     392           0 :     if ( nPos < nCount && (((*pOffset)[nPos] - nOffsetTol) <= nOffset) )
     393           0 :         return true;
     394             :     // nicht kleiner als alles andere? dann mit Naechstniedrigerem vergleichen
     395           0 :     else if ( nPos && (((*pOffset)[nPos-1] + nOffsetTol) >= nOffset) )
     396             :     {
     397           0 :         (*pCol)--;
     398           0 :         return true;
     399             :     }
     400           0 :     return false;
     401             : }
     402             : 
     403             : 
     404           0 : void ScHTMLLayoutParser::MakeCol( ScHTMLColOffset* pOffset, sal_uInt16& nOffset,
     405             :         sal_uInt16& nWidth, sal_uInt16 nOffsetTol, sal_uInt16 nWidthTol )
     406             : {
     407             :     OSL_ENSURE( pOffset, "ScHTMLLayoutParser::MakeCol - illegal call" );
     408             :     SCCOL nPos;
     409           0 :     if ( SeekOffset( pOffset, nOffset, &nPos, nOffsetTol ) )
     410           0 :         nOffset = (sal_uInt16)(*pOffset)[nPos];
     411             :     else
     412           0 :         pOffset->insert( nOffset );
     413           0 :     if ( nWidth )
     414             :     {
     415           0 :         if ( SeekOffset( pOffset, nOffset + nWidth, &nPos, nWidthTol ) )
     416           0 :             nWidth = (sal_uInt16)(*pOffset)[nPos] - nOffset;
     417             :         else
     418           0 :             pOffset->insert( nOffset + nWidth );
     419             :     }
     420           0 : }
     421             : 
     422             : 
     423           0 : void ScHTMLLayoutParser::MakeColNoRef( ScHTMLColOffset* pOffset, sal_uInt16 nOffset,
     424             :         sal_uInt16 nWidth, sal_uInt16 nOffsetTol, sal_uInt16 nWidthTol )
     425             : {
     426             :     OSL_ENSURE( pOffset, "ScHTMLLayoutParser::MakeColNoRef - illegal call" );
     427             :     SCCOL nPos;
     428           0 :     if ( SeekOffset( pOffset, nOffset, &nPos, nOffsetTol ) )
     429           0 :         nOffset = (sal_uInt16)(*pOffset)[nPos];
     430             :     else
     431           0 :         pOffset->insert( nOffset );
     432           0 :     if ( nWidth )
     433             :     {
     434           0 :         if ( !SeekOffset( pOffset, nOffset + nWidth, &nPos, nWidthTol ) )
     435           0 :             pOffset->insert( nOffset + nWidth );
     436             :     }
     437           0 : }
     438             : 
     439             : 
     440           0 : void ScHTMLLayoutParser::ModifyOffset( ScHTMLColOffset* pOffset, sal_uInt16& nOldOffset,
     441             :             sal_uInt16& nNewOffset, sal_uInt16 nOffsetTol )
     442             : {
     443             :     OSL_ENSURE( pOffset, "ScHTMLLayoutParser::ModifyOffset - illegal call" );
     444             :     SCCOL nPos;
     445           0 :     if ( !SeekOffset( pOffset, nOldOffset, &nPos, nOffsetTol ) )
     446             :     {
     447           0 :         if ( SeekOffset( pOffset, nNewOffset, &nPos, nOffsetTol ) )
     448           0 :             nNewOffset = (sal_uInt16)(*pOffset)[nPos];
     449             :         else
     450           0 :             pOffset->insert( nNewOffset );
     451             :         return ;
     452             :     }
     453           0 :     nOldOffset = (sal_uInt16)(*pOffset)[nPos];
     454             :     SCCOL nPos2;
     455           0 :     if ( SeekOffset( pOffset, nNewOffset, &nPos2, nOffsetTol ) )
     456             :     {
     457           0 :         nNewOffset = (sal_uInt16)(*pOffset)[nPos2];
     458             :         return ;
     459             :     }
     460           0 :     long nDiff = nNewOffset - nOldOffset;
     461           0 :     if ( nDiff < 0 )
     462             :     {
     463           0 :         do
     464             :         {
     465           0 :             const_cast<sal_uLong&>((*pOffset)[nPos]) += nDiff;
     466             :         } while ( nPos-- );
     467             :     }
     468             :     else
     469             :     {
     470           0 :         do
     471             :         {
     472           0 :             const_cast<sal_uLong&>((*pOffset)[nPos]) += nDiff;
     473           0 :         } while ( ++nPos < (sal_uInt16)pOffset->size() );
     474             :     }
     475             : }
     476             : 
     477             : 
     478           0 : void ScHTMLLayoutParser::SkipLocked( ScEEParseEntry* pE, bool bJoin )
     479             : {
     480           0 :     if ( ValidCol(pE->nCol) )
     481             :     {   // wuerde sonst bei ScAddress falschen Wert erzeugen, evtl. Endlosschleife!
     482           0 :         bool bBadCol = false;
     483             :         bool bAgain;
     484             :         ScRange aRange( pE->nCol, pE->nRow, 0,
     485           0 :             pE->nCol + pE->nColOverlap - 1, pE->nRow + pE->nRowOverlap - 1, 0 );
     486           0 :         do
     487             :         {
     488           0 :             bAgain = false;
     489           0 :             for ( size_t i =  0, nRanges = xLockedList->size(); i < nRanges; ++i )
     490             :             {
     491           0 :                 ScRange* pR = (*xLockedList)[i];
     492           0 :                 if ( pR->Intersects( aRange ) )
     493             :                 {
     494           0 :                     pE->nCol = pR->aEnd.Col() + 1;
     495           0 :                     SCCOL nTmp = pE->nCol + pE->nColOverlap - 1;
     496           0 :                     if ( pE->nCol > MAXCOL || nTmp > MAXCOL )
     497           0 :                         bBadCol = true;
     498             :                     else
     499             :                     {
     500           0 :                         bAgain = true;
     501           0 :                         aRange.aStart.SetCol( pE->nCol );
     502           0 :                         aRange.aEnd.SetCol( nTmp );
     503             :                     }
     504           0 :                     break;
     505             :                 }
     506             :             }
     507             :         } while ( bAgain );
     508           0 :         if ( bJoin && !bBadCol )
     509           0 :             xLockedList->Join( aRange );
     510             :     }
     511           0 : }
     512             : 
     513             : 
     514           0 : void ScHTMLLayoutParser::Adjust()
     515             : {
     516           0 :     xLockedList->RemoveAll();
     517             : 
     518           0 :     ScHTMLAdjustStack aStack;
     519           0 :     ScHTMLAdjustStackEntry* pS = NULL;
     520           0 :     sal_uInt16 nTab = 0;
     521           0 :     SCCOL nLastCol = SCCOL_MAX;
     522           0 :     SCROW nNextRow = 0;
     523           0 :     SCROW nCurRow = 0;
     524           0 :     sal_uInt16 nPageWidth = (sal_uInt16) aPageSize.Width();
     525           0 :     InnerMap* pTab = NULL;
     526           0 :     for ( size_t i = 0, nListSize = maList.size(); i < nListSize; ++i )
     527             :     {
     528           0 :         ScEEParseEntry* pE = maList[ i ];
     529           0 :         if ( pE->nTab < nTab )
     530             :         {   // Table beendet
     531           0 :             if ( !aStack.empty() )
     532             :             {
     533           0 :                 pS = aStack.top();
     534           0 :                 aStack.pop();
     535             : 
     536           0 :                 nLastCol = pS->nLastCol;
     537           0 :                 nNextRow = pS->nNextRow;
     538           0 :                 nCurRow = pS->nCurRow;
     539             :             }
     540           0 :             delete pS;
     541           0 :             pS = NULL;
     542           0 :             nTab = pE->nTab;
     543           0 :             if (pTables)
     544             :             {
     545           0 :                 OuterMap::const_iterator it = pTables->find( nTab );
     546           0 :                 if ( it != pTables->end() )
     547           0 :                     pTab = it->second;
     548             :             }
     549             : 
     550             :         }
     551           0 :         SCROW nRow = pE->nRow;
     552           0 :         if ( pE->nCol <= nLastCol )
     553             :         {   // naechste Zeile
     554           0 :             if ( pE->nRow < nNextRow )
     555           0 :                 pE->nRow = nCurRow = nNextRow;
     556             :             else
     557           0 :                 nCurRow = nNextRow = pE->nRow;
     558           0 :             SCROW nR = 0;
     559           0 :             if ( pTab )
     560             :             {
     561           0 :                 InnerMap::const_iterator it = pTab->find( nCurRow );
     562           0 :                 if ( it != pTab->end() )
     563           0 :                     nR = it->second;
     564             :             }
     565           0 :             if ( nR )
     566           0 :                 nNextRow += nR;
     567             :             else
     568           0 :                 nNextRow++;
     569             :         }
     570             :         else
     571           0 :             pE->nRow = nCurRow;
     572           0 :         nLastCol = pE->nCol;    // eingelesene Col
     573           0 :         if ( pE->nTab > nTab )
     574             :         {   // neue Table
     575             :             aStack.push( new ScHTMLAdjustStackEntry(
     576           0 :                 nLastCol, nNextRow, nCurRow ) );
     577           0 :             nTab = pE->nTab;
     578           0 :             if ( pTables )
     579             :             {
     580           0 :                 OuterMap::const_iterator it = pTables->find( nTab );
     581           0 :                 if ( it != pTables->end() )
     582           0 :                     pTab = it->second;
     583             :             }
     584             :             // neuer Zeilenabstand
     585           0 :             SCROW nR = 0;
     586           0 :             if ( pTab )
     587             :             {
     588           0 :                 InnerMap::const_iterator it = pTab->find( nCurRow );
     589           0 :                 if ( it != pTab->end() )
     590           0 :                     nR = it->second;
     591             :             }
     592           0 :             if ( nR )
     593           0 :                 nNextRow = nCurRow + nR;
     594             :             else
     595           0 :                 nNextRow = nCurRow + 1;
     596             :         }
     597           0 :         if ( nTab == 0 )
     598           0 :             pE->nWidth = nPageWidth;
     599             :         else
     600             :         {   // echte Table, keine Absaetze auf der Wiese
     601           0 :             if ( pTab )
     602             :             {
     603           0 :                 SCROW nRowSpan = pE->nRowOverlap;
     604           0 :                 for ( SCROW j=0; j < nRowSpan; j++ )
     605             :                 {   // aus merged Zeilen resultierendes RowSpan
     606           0 :                     SCROW nRows = 0;
     607           0 :                     InnerMap::const_iterator it = pTab->find( nRow+j );
     608           0 :                     if ( it != pTab->end() )
     609           0 :                         nRows = it->second;
     610           0 :                     if ( nRows > 1 )
     611             :                     {
     612           0 :                         pE->nRowOverlap += nRows - 1;
     613           0 :                         if ( j == 0 )
     614             :                         {   // merged Zeilen verschieben die naechste Zeile
     615           0 :                             SCROW nTmp = nCurRow + nRows;
     616           0 :                             if ( nNextRow < nTmp )
     617           0 :                                 nNextRow = nTmp;
     618             :                         }
     619             :                     }
     620             :                 }
     621             :             }
     622             :         }
     623             :         // echte Col
     624           0 :         SeekOffset( pColOffset, pE->nOffset, &pE->nCol, nOffsetTolerance );
     625           0 :         SCCOL nColBeforeSkip = pE->nCol;
     626           0 :         SkipLocked( pE, false );
     627           0 :         if ( pE->nCol != nColBeforeSkip )
     628             :         {
     629           0 :             SCCOL nCount = (SCCOL)pColOffset->size();
     630           0 :             if ( nCount <= pE->nCol )
     631             :             {
     632           0 :                 pE->nOffset = (sal_uInt16) (*pColOffset)[nCount-1];
     633           0 :                 MakeCol( pColOffset, pE->nOffset, pE->nWidth, nOffsetTolerance, nOffsetTolerance );
     634             :             }
     635             :             else
     636             :             {
     637           0 :                 pE->nOffset = (sal_uInt16) (*pColOffset)[pE->nCol];
     638             :             }
     639             :         }
     640             :         SCCOL nPos;
     641           0 :         if ( pE->nWidth && SeekOffset( pColOffset, pE->nOffset + pE->nWidth, &nPos, nOffsetTolerance ) )
     642           0 :             pE->nColOverlap = (nPos > pE->nCol ? nPos - pE->nCol : 1);
     643             :         else
     644             :         {
     645             : //2do: das muss nicht korrekt sein, ist aber..
     646           0 :             pE->nColOverlap = 1;
     647             :         }
     648             :         xLockedList->Join( ScRange( pE->nCol, pE->nRow, 0,
     649           0 :             pE->nCol + pE->nColOverlap - 1, pE->nRow + pE->nRowOverlap - 1, 0 ) );
     650             :         // MaxDimensions mitfuehren
     651           0 :         SCCOL nColTmp = pE->nCol + pE->nColOverlap;
     652           0 :         if ( nColMax < nColTmp )
     653           0 :             nColMax = nColTmp;
     654           0 :         SCROW nRowTmp = pE->nRow + pE->nRowOverlap;
     655           0 :         if ( nRowMax < nRowTmp )
     656           0 :             nRowMax = nRowTmp;
     657             :     }
     658           0 :     while ( !aStack.empty() )
     659             :     {
     660           0 :         delete aStack.top();
     661           0 :         aStack.pop();
     662           0 :     }
     663           0 : }
     664             : 
     665             : 
     666           0 : sal_uInt16 ScHTMLLayoutParser::GetWidth( ScEEParseEntry* pE )
     667             : {
     668           0 :     if ( pE->nWidth )
     669           0 :         return pE->nWidth;
     670             :     sal_Int32 nTmp = ::std::min( static_cast<sal_Int32>( pE->nCol -
     671             :                 nColCntStart + pE->nColOverlap),
     672           0 :             static_cast<sal_Int32>( pLocalColOffset->size() - 1));
     673           0 :     SCCOL nPos = (nTmp < 0 ? 0 : static_cast<SCCOL>(nTmp));
     674           0 :     sal_uInt16 nOff2 = (sal_uInt16) (*pLocalColOffset)[nPos];
     675           0 :     if ( pE->nOffset < nOff2 )
     676           0 :         return nOff2 - pE->nOffset;
     677           0 :     return 0;
     678             : }
     679             : 
     680             : 
     681           0 : void ScHTMLLayoutParser::SetWidths()
     682             : {
     683             :     ScEEParseEntry* pE;
     684             :     SCCOL nCol;
     685           0 :     if ( !nTableWidth )
     686           0 :         nTableWidth = (sal_uInt16) aPageSize.Width();
     687           0 :     SCCOL nColsPerRow = nMaxCol - nColCntStart;
     688           0 :     if ( nColsPerRow <= 0 )
     689           0 :         nColsPerRow = 1;
     690           0 :     if ( pLocalColOffset->size() <= 2 )
     691             :     {   // nur PageSize, es gab keine Width-Angabe
     692           0 :         sal_uInt16 nWidth = nTableWidth / static_cast<sal_uInt16>(nColsPerRow);
     693           0 :         sal_uInt16 nOff = nColOffsetStart;
     694           0 :         pLocalColOffset->clear();
     695           0 :         for ( nCol = 0; nCol <= nColsPerRow; ++nCol, nOff = nOff + nWidth )
     696             :         {
     697           0 :             MakeColNoRef( pLocalColOffset, nOff, 0, 0, 0 );
     698             :         }
     699           0 :         nTableWidth = (sal_uInt16)(pLocalColOffset->back() - pLocalColOffset->front());
     700           0 :         for ( size_t i = nFirstTableCell, nListSize = maList.size(); i < nListSize; ++i )
     701             :         {
     702           0 :             pE = maList[ i ];
     703           0 :             if ( pE->nTab == nTable )
     704             :             {
     705           0 :                 pE->nOffset = (sal_uInt16) (*pLocalColOffset)[pE->nCol - nColCntStart];
     706           0 :                 pE->nWidth = 0;     // to be recalculated later
     707             :             }
     708             :         }
     709             :     }
     710             :     else
     711             :     {   // einige mit einige ohne Width
     712             :         // wieso eigentlich kein pE ?!?
     713           0 :         if ( nFirstTableCell < maList.size() )
     714             :         {
     715           0 :             sal_uInt16* pOffsets = new sal_uInt16[ nColsPerRow+1 ];
     716           0 :             memset( pOffsets, 0, (nColsPerRow+1) * sizeof(sal_uInt16) );
     717           0 :             sal_uInt16* pWidths = new sal_uInt16[ nColsPerRow ];
     718           0 :             memset( pWidths, 0, nColsPerRow * sizeof(sal_uInt16) );
     719           0 :             pOffsets[0] = nColOffsetStart;
     720           0 :             for ( size_t i = nFirstTableCell, nListSize = maList.size(); i < nListSize; ++i )
     721             :             {
     722           0 :                 pE = maList[ i ];
     723           0 :                 if ( pE->nTab == nTable && pE->nWidth )
     724             :                 {
     725           0 :                     nCol = pE->nCol - nColCntStart;
     726           0 :                     if ( nCol < nColsPerRow )
     727             :                     {
     728           0 :                         if ( pE->nColOverlap == 1 )
     729             :                         {
     730           0 :                             if ( pWidths[nCol] < pE->nWidth )
     731           0 :                                 pWidths[nCol] = pE->nWidth;
     732             :                         }
     733             :                         else
     734             :                         {   // try to find a single undefined width
     735           0 :                             sal_uInt16 nTotal = 0;
     736           0 :                             bool bFound = false;
     737           0 :                             SCCOL nHere = 0;
     738           0 :                             SCCOL nStop = Min( static_cast<SCCOL>(nCol + pE->nColOverlap), nColsPerRow );
     739           0 :                             for ( ; nCol < nStop; nCol++ )
     740             :                             {
     741           0 :                                 if ( pWidths[nCol] )
     742           0 :                                     nTotal = nTotal + pWidths[nCol];
     743             :                                 else
     744             :                                 {
     745           0 :                                     if ( bFound )
     746             :                                     {
     747           0 :                                         bFound = false;
     748           0 :                                         break;  // for
     749             :                                     }
     750           0 :                                     bFound = true;
     751           0 :                                     nHere = nCol;
     752             :                                 }
     753             :                             }
     754           0 :                             if ( bFound && pE->nWidth > nTotal )
     755           0 :                                 pWidths[nHere] = pE->nWidth - nTotal;
     756             :                         }
     757             :                     }
     758             :                 }
     759             :             }
     760           0 :             sal_uInt16 nWidths = 0;
     761           0 :             sal_uInt16 nUnknown = 0;
     762           0 :             for ( nCol = 0; nCol < nColsPerRow; nCol++ )
     763             :             {
     764           0 :                 if ( pWidths[nCol] )
     765           0 :                     nWidths = nWidths + pWidths[nCol];
     766             :                 else
     767           0 :                     nUnknown++;
     768             :             }
     769           0 :             if ( nUnknown )
     770             :             {
     771             :                 sal_uInt16 nW = ((nWidths < nTableWidth) ?
     772             :                     ((nTableWidth - nWidths) / nUnknown) :
     773           0 :                     (nTableWidth / nUnknown));
     774           0 :                 for ( nCol = 0; nCol < nColsPerRow; nCol++ )
     775             :                 {
     776           0 :                     if ( !pWidths[nCol] )
     777           0 :                         pWidths[nCol] = nW;
     778             :                 }
     779             :             }
     780           0 :             for ( nCol = 1; nCol <= nColsPerRow; nCol++ )
     781             :             {
     782           0 :                 pOffsets[nCol] = pOffsets[nCol-1] + pWidths[nCol-1];
     783             :             }
     784           0 :             pLocalColOffset->clear();
     785           0 :             for ( nCol = 0; nCol <= nColsPerRow; nCol++ )
     786             :             {
     787           0 :                 MakeColNoRef( pLocalColOffset, pOffsets[nCol], 0, 0, 0 );
     788             :             }
     789           0 :             nTableWidth = pOffsets[nColsPerRow] - pOffsets[0];
     790             : 
     791           0 :             for ( size_t i = nFirstTableCell, nListSize = maList.size(); i < nListSize; ++i )
     792             :             {
     793           0 :                 pE = maList[ i ];
     794           0 :                 if ( pE->nTab == nTable )
     795             :                 {
     796           0 :                     nCol = pE->nCol - nColCntStart;
     797             :                     OSL_ENSURE( nCol < nColsPerRow, "ScHTMLLayoutParser::SetWidths: column overflow" );
     798           0 :                     if ( nCol < nColsPerRow )
     799             :                     {
     800           0 :                         pE->nOffset = pOffsets[nCol];
     801           0 :                         nCol = nCol + pE->nColOverlap;
     802           0 :                         if ( nCol > nColsPerRow )
     803           0 :                             nCol = nColsPerRow;
     804           0 :                         pE->nWidth = pOffsets[nCol] - pE->nOffset;
     805             :                     }
     806             :                 }
     807             :             }
     808             : 
     809           0 :             delete [] pWidths;
     810           0 :             delete [] pOffsets;
     811             :         }
     812             :     }
     813           0 :     if ( !pLocalColOffset->empty() )
     814             :     {
     815           0 :         sal_uInt16 nMax = (sal_uInt16) pLocalColOffset->back();
     816           0 :         if ( aPageSize.Width() < nMax )
     817           0 :             aPageSize.Width() = nMax;
     818             :     }
     819           0 :     for ( size_t i = nFirstTableCell, nListSize = maList.size(); i < nListSize; ++i )
     820             :     {
     821           0 :         pE = maList[ i ];
     822           0 :         if ( pE->nTab == nTable )
     823             :         {
     824           0 :             if ( !pE->nWidth )
     825             :             {
     826           0 :                 pE->nWidth = GetWidth( pE );
     827             :                 OSL_ENSURE( pE->nWidth, "SetWidths: pE->nWidth == 0" );
     828             :             }
     829           0 :             MakeCol( pColOffset, pE->nOffset, pE->nWidth, nOffsetTolerance, nOffsetTolerance );
     830             :         }
     831             :     }
     832           0 : }
     833             : 
     834             : 
     835           0 : void ScHTMLLayoutParser::Colonize( ScEEParseEntry* pE )
     836             : {
     837           0 :     if ( pE->nCol == SCCOL_MAX )
     838           0 :         pE->nCol = nColCnt;
     839           0 :     if ( pE->nRow == SCROW_MAX )
     840           0 :         pE->nRow = nRowCnt;
     841           0 :     SCCOL nCol = pE->nCol;
     842           0 :     SkipLocked( pE );       // Spaltenverdraengung nach rechts
     843             : 
     844           0 :     if ( nCol < pE->nCol )
     845             :     {   // verdraengt
     846           0 :         nCol = pE->nCol - nColCntStart;
     847           0 :         SCCOL nCount = static_cast<SCCOL>(pLocalColOffset->size());
     848           0 :         if ( nCol < nCount )
     849           0 :             nColOffset = (sal_uInt16) (*pLocalColOffset)[nCol];
     850             :         else
     851           0 :             nColOffset = (sal_uInt16) (*pLocalColOffset)[nCount - 1];
     852             :     }
     853           0 :     pE->nOffset = nColOffset;
     854           0 :     sal_uInt16 nWidth = GetWidth( pE );
     855           0 :     MakeCol( pLocalColOffset, pE->nOffset, nWidth, nOffsetTolerance, nOffsetTolerance );
     856           0 :     if ( pE->nWidth )
     857           0 :         pE->nWidth = nWidth;
     858           0 :     nColOffset = pE->nOffset + nWidth;
     859           0 :     if ( nTableWidth < nColOffset - nColOffsetStart )
     860           0 :         nTableWidth = nColOffset - nColOffsetStart;
     861           0 : }
     862             : 
     863             : 
     864           0 : void ScHTMLLayoutParser::CloseEntry( ImportInfo* pInfo )
     865             : {
     866           0 :     bInCell = false;
     867           0 :     if ( bTabInTabCell )
     868             :     {   // in TableOff vom Stack geholt
     869           0 :         bTabInTabCell = false;
     870           0 :         bool found = false;
     871           0 :         for ( size_t i = 0, nListSize = maList.size(); i < nListSize; ++i )
     872             :         {
     873           0 :             if ( pActEntry == maList[ i ] )
     874             :             {
     875           0 :                 found = true;
     876           0 :                 break;
     877             :             }
     878             :         }
     879           0 :         if ( !found )
     880           0 :             delete pActEntry;
     881           0 :         NewActEntry( maList.back() );   // neuer freifliegender pActEntry
     882           0 :         return ;
     883             :     }
     884           0 :     if ( pActEntry->nTab == 0 )
     885           0 :         pActEntry->nWidth = (sal_uInt16) aPageSize.Width();
     886           0 :     Colonize( pActEntry );
     887           0 :     nColCnt = pActEntry->nCol + pActEntry->nColOverlap;
     888           0 :     if ( nMaxCol < nColCnt )
     889           0 :         nMaxCol = nColCnt;          // TableStack MaxCol
     890           0 :     if ( nColMax < nColCnt )
     891           0 :         nColMax = nColCnt;      // globales MaxCol fuer ScEEParser GetDimensions!
     892           0 :     EntryEnd( pActEntry, pInfo->aSelection );
     893           0 :     ESelection& rSel = pActEntry->aSel;
     894           0 :     while ( rSel.nStartPara < rSel.nEndPara
     895           0 :             && pEdit->GetTextLen( rSel.nStartPara ) == 0 )
     896             :     {   // vorgehaengte Leerabsaetze strippen
     897           0 :         rSel.nStartPara++;
     898             :     }
     899           0 :     while ( rSel.nEndPos == 0 && rSel.nEndPara > rSel.nStartPara )
     900             :     {   // angehaengte Leerabsaetze strippen
     901           0 :         rSel.nEndPara--;
     902           0 :         rSel.nEndPos = pEdit->GetTextLen( rSel.nEndPara );
     903             :     }
     904           0 :     if ( rSel.nStartPara > rSel.nEndPara )
     905             :     {   // gibt GPF in CreateTextObject
     906             :         OSL_FAIL( "CloseEntry: EditEngine ESelection Start > End" );
     907           0 :         rSel.nEndPara = rSel.nStartPara;
     908             :     }
     909           0 :     if ( rSel.HasRange() )
     910           0 :         pActEntry->aItemSet.Put( SfxBoolItem( ATTR_LINEBREAK, true ) );
     911           0 :     maList.push_back( pActEntry );
     912           0 :     NewActEntry( pActEntry );   // neuer freifliegender pActEntry
     913             : }
     914             : 
     915             : 
     916           0 : IMPL_LINK( ScHTMLLayoutParser, HTMLImportHdl, ImportInfo*, pInfo )
     917             : {
     918           0 :     switch ( pInfo->eState )
     919             :     {
     920             :         case HTMLIMP_NEXTTOKEN:
     921           0 :             ProcToken( pInfo );
     922           0 :             break;
     923             :         case HTMLIMP_UNKNOWNATTR:
     924           0 :             ProcToken( pInfo );
     925           0 :             break;
     926             :         case HTMLIMP_START:
     927           0 :             break;
     928             :         case HTMLIMP_END:
     929           0 :             if ( pInfo->aSelection.nEndPos )
     930             :             {
     931             :                 // If text remains: create paragraph, without calling CloseEntry().
     932           0 :                 if( bInCell )   // ...but only in opened table cells.
     933             :                 {
     934           0 :                     bInCell = false;
     935           0 :                     NextRow( pInfo );
     936           0 :                     bInCell = true;
     937             :                 }
     938           0 :                 CloseEntry( pInfo );
     939             :             }
     940           0 :             while ( nTableLevel > 0 )
     941           0 :                 TableOff( pInfo );      // close tables, if </TABLE> missing
     942           0 :             break;
     943             :         case HTMLIMP_SETATTR:
     944           0 :             break;
     945             :         case HTMLIMP_INSERTTEXT:
     946           0 :             break;
     947             :         case HTMLIMP_INSERTPARA:
     948           0 :             if ( nTableLevel < 1 )
     949             :             {
     950           0 :                 CloseEntry( pInfo );
     951           0 :                 NextRow( pInfo );
     952             :             }
     953           0 :             break;
     954             :         case HTMLIMP_INSERTFIELD:
     955           0 :             break;
     956             :         default:
     957             :             OSL_FAIL("HTMLImportHdl: unknown ImportInfo.eState");
     958             :     }
     959           0 :     return 0;
     960             : }
     961             : 
     962             : 
     963             : // Groesster Gemeinsamer Teiler nach Euklid (Kettendivision)
     964             : // Sonderfall: 0 und irgendwas geben 1
     965           0 : static SCROW lcl_GGT( SCROW a, SCROW b )
     966             : {
     967           0 :     if ( !a || !b )
     968           0 :         return 1;
     969           0 :     do
     970             :     {
     971           0 :         if ( a > b )
     972           0 :             a -= SCROW(a / b) * b;
     973             :         else
     974           0 :             b -= SCROW(b / a) * a;
     975             :     } while ( a && b );
     976           0 :     return ((a != 0) ? a : b);
     977             : }
     978             : 
     979             : 
     980             : // Kleinstes Gemeinsames Vielfaches: a * b / GGT(a,b)
     981           0 : static SCROW lcl_KGV( SCROW a, SCROW b )
     982             : {
     983           0 :     if ( a > b )    // Ueberlauf unwahrscheinlicher machen
     984           0 :         return (a / lcl_GGT(a,b)) * b;
     985             :     else
     986           0 :         return (b / lcl_GGT(a,b)) * a;
     987             : }
     988             : 
     989             : 
     990           0 : void ScHTMLLayoutParser::TableDataOn( ImportInfo* pInfo )
     991             : {
     992           0 :     if ( bInCell )
     993           0 :         CloseEntry( pInfo );
     994           0 :     if ( !nTableLevel )
     995             :     {
     996             :         OSL_FAIL( "Dummbatz-Dok! <TH> oder <TD> ohne vorheriges <TABLE>" );
     997           0 :         TableOn( pInfo );
     998             :     }
     999           0 :     bInCell = true;
    1000           0 :     bool bHorJustifyCenterTH = (pInfo->nToken == HTML_TABLEHEADER_ON);
    1001           0 :     const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
    1002           0 :     for (size_t i = 0, n = rOptions.size(); i < n; ++i)
    1003             :     {
    1004           0 :         const HTMLOption& rOption = rOptions[i];
    1005           0 :         switch( rOption.GetToken() )
    1006             :         {
    1007             :             case HTML_O_COLSPAN:
    1008             :             {
    1009           0 :                 pActEntry->nColOverlap = ( SCCOL ) rOption.GetString().ToInt32();
    1010             :             }
    1011           0 :             break;
    1012             :             case HTML_O_ROWSPAN:
    1013             :             {
    1014           0 :                 pActEntry->nRowOverlap = ( SCROW ) rOption.GetString().ToInt32();
    1015             :             }
    1016           0 :             break;
    1017             :             case HTML_O_ALIGN:
    1018             :             {
    1019           0 :                 bHorJustifyCenterTH = false;
    1020             :                 SvxCellHorJustify eVal;
    1021           0 :                 const String& rOptVal = rOption.GetString();
    1022           0 :                 if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) == COMPARE_EQUAL )
    1023           0 :                     eVal = SVX_HOR_JUSTIFY_RIGHT;
    1024           0 :                 else if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_center ) == COMPARE_EQUAL )
    1025           0 :                     eVal = SVX_HOR_JUSTIFY_CENTER;
    1026           0 :                 else if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_left ) == COMPARE_EQUAL )
    1027           0 :                     eVal = SVX_HOR_JUSTIFY_LEFT;
    1028             :                 else
    1029           0 :                     eVal = SVX_HOR_JUSTIFY_STANDARD;
    1030           0 :                 if ( eVal != SVX_HOR_JUSTIFY_STANDARD )
    1031           0 :                     pActEntry->aItemSet.Put( SvxHorJustifyItem( eVal, ATTR_HOR_JUSTIFY) );
    1032             :             }
    1033           0 :             break;
    1034             :             case HTML_O_VALIGN:
    1035             :             {
    1036             :                 SvxCellVerJustify eVal;
    1037           0 :                 const String& rOptVal = rOption.GetString();
    1038           0 :                 if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_VA_top ) == COMPARE_EQUAL )
    1039           0 :                     eVal = SVX_VER_JUSTIFY_TOP;
    1040           0 :                 else if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_VA_middle ) == COMPARE_EQUAL )
    1041           0 :                     eVal = SVX_VER_JUSTIFY_CENTER;
    1042           0 :                 else if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_VA_bottom ) == COMPARE_EQUAL )
    1043           0 :                     eVal = SVX_VER_JUSTIFY_BOTTOM;
    1044             :                 else
    1045           0 :                     eVal = SVX_VER_JUSTIFY_STANDARD;
    1046           0 :                 pActEntry->aItemSet.Put( SvxVerJustifyItem( eVal, ATTR_VER_JUSTIFY) );
    1047             :             }
    1048           0 :             break;
    1049             :             case HTML_O_WIDTH:
    1050             :             {
    1051           0 :                 pActEntry->nWidth = GetWidthPixel( rOption );
    1052             :             }
    1053           0 :             break;
    1054             :             case HTML_O_BGCOLOR:
    1055             :             {
    1056           0 :                 Color aColor;
    1057           0 :                 rOption.GetColor( aColor );
    1058             :                 pActEntry->aItemSet.Put(
    1059           0 :                     SvxBrushItem( aColor, ATTR_BACKGROUND ) );
    1060             :             }
    1061           0 :             break;
    1062             :             case HTML_O_SDVAL:
    1063             :             {
    1064           0 :                 pActEntry->pValStr = new rtl::OUString( rOption.GetString() );
    1065             :             }
    1066           0 :             break;
    1067             :             case HTML_O_SDNUM:
    1068             :             {
    1069           0 :                 pActEntry->pNumStr = new rtl::OUString( rOption.GetString() );
    1070             :             }
    1071           0 :             break;
    1072             :         }
    1073             :     }
    1074           0 :     pActEntry->nCol = nColCnt;
    1075           0 :     pActEntry->nRow = nRowCnt;
    1076           0 :     pActEntry->nTab = nTable;
    1077             : 
    1078           0 :     if ( bHorJustifyCenterTH )
    1079             :         pActEntry->aItemSet.Put(
    1080           0 :             SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY) );
    1081           0 : }
    1082             : 
    1083             : 
    1084           0 : void ScHTMLLayoutParser::TableRowOn( ImportInfo* pInfo )
    1085             : {
    1086           0 :     if ( nColCnt > nColCntStart )
    1087           0 :         NextRow( pInfo );       // das optionale TableRowOff war nicht
    1088           0 :     nColOffset = nColOffsetStart;
    1089           0 : }
    1090             : 
    1091             : 
    1092           0 : void ScHTMLLayoutParser::TableRowOff( ImportInfo* pInfo )
    1093             : {
    1094           0 :     NextRow( pInfo );
    1095           0 : }
    1096             : 
    1097             : 
    1098           0 : void ScHTMLLayoutParser::TableDataOff( ImportInfo* pInfo )
    1099             : {
    1100           0 :     if ( bInCell )
    1101           0 :         CloseEntry( pInfo );    // aber nur wenn's auch eine war
    1102           0 : }
    1103             : 
    1104             : 
    1105           0 : void ScHTMLLayoutParser::TableOn( ImportInfo* pInfo )
    1106             : {
    1107           0 :     String aTabName;
    1108             : 
    1109           0 :     if ( ++nTableLevel > 1 )
    1110             :     {   // Table in Table
    1111           0 :         sal_uInt16 nTmpColOffset = nColOffset;  // wird in Colonize noch angepasst
    1112           0 :         Colonize( pActEntry );
    1113             :         aTableStack.push( new ScHTMLTableStackEntry(
    1114             :             pActEntry, xLockedList, pLocalColOffset, nFirstTableCell,
    1115             :             nColCnt, nRowCnt, nColCntStart, nMaxCol, nTable,
    1116             :             nTableWidth, nColOffset, nColOffsetStart,
    1117           0 :             bFirstRow ) );
    1118           0 :         sal_uInt16 nLastWidth = nTableWidth;
    1119           0 :         nTableWidth = GetWidth( pActEntry );
    1120           0 :         if ( nTableWidth == nLastWidth && nMaxCol - nColCntStart > 1 )
    1121             :         {   // es muss mehr als einen geben, also kann dieser nicht alles sein
    1122           0 :             nTableWidth = nLastWidth / static_cast<sal_uInt16>((nMaxCol - nColCntStart));
    1123             :         }
    1124           0 :         nLastWidth = nTableWidth;
    1125           0 :         if ( pInfo->nToken == HTML_TABLE_ON )
    1126             :         {   // es kann auch TD oder TH sein, wenn es vorher kein TABLE gab
    1127           0 :             const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
    1128           0 :             for (size_t i = 0, n = rOptions.size(); i < n; ++i)
    1129             :             {
    1130           0 :                 const HTMLOption& rOption = rOptions[i];
    1131           0 :                 switch( rOption.GetToken() )
    1132             :                 {
    1133             :                     case HTML_O_WIDTH:
    1134             :                     {   // Prozent: von Dokumentbreite bzw. aeusserer Zelle
    1135           0 :                         nTableWidth = GetWidthPixel( rOption );
    1136             :                     }
    1137           0 :                     break;
    1138             :                     case HTML_O_BORDER:
    1139             :                         // Border is: ((pOption->GetString().Len() == 0) || (pOption->GetNumber() != 0));
    1140           0 :                     break;
    1141             :                     case HTML_O_ID:
    1142           0 :                         aTabName.Assign( rOption.GetString() );
    1143           0 :                     break;
    1144             :                 }
    1145             :             }
    1146             :         }
    1147           0 :         bInCell = false;
    1148           0 :         if ( bTabInTabCell && !(nTableWidth < nLastWidth) )
    1149             :         {   // mehrere Tabellen in einer Zelle, untereinander
    1150           0 :             bTabInTabCell = false;
    1151           0 :             NextRow( pInfo );
    1152             :         }
    1153             :         else
    1154             :         {   // in dieser Zelle geht's los, oder nebeneinander
    1155           0 :             bTabInTabCell = false;
    1156           0 :             nColCntStart = nColCnt;
    1157           0 :             nColOffset = nTmpColOffset;
    1158           0 :             nColOffsetStart = nColOffset;
    1159             :         }
    1160             : 
    1161           0 :         ScEEParseEntry* pE = NULL;
    1162           0 :         if (maList.size())
    1163           0 :             pE = maList.back();
    1164           0 :         NewActEntry( pE );      // neuer freifliegender pActEntry
    1165           0 :         xLockedList = new ScRangeList;
    1166             :     }
    1167             :     else
    1168             :     {   // einfache Table auf Dokumentebene
    1169           0 :         EntryEnd( pActEntry, pInfo->aSelection );
    1170           0 :         if ( pActEntry->aSel.HasRange() )
    1171             :         {   // noch fliegender Text
    1172           0 :             CloseEntry( pInfo );
    1173           0 :             NextRow( pInfo );
    1174             :         }
    1175             :         aTableStack.push( new ScHTMLTableStackEntry(
    1176             :             pActEntry, xLockedList, pLocalColOffset, nFirstTableCell,
    1177             :             nColCnt, nRowCnt, nColCntStart, nMaxCol, nTable,
    1178             :             nTableWidth, nColOffset, nColOffsetStart,
    1179           0 :             bFirstRow ) );
    1180             :         // As soon as we have multiple tables we need to be tolerant with the offsets.
    1181           0 :         if (nMaxTable > 0)
    1182           0 :             nOffsetTolerance = SC_HTML_OFFSET_TOLERANCE_LARGE;
    1183           0 :         nTableWidth = 0;
    1184           0 :         if ( pInfo->nToken == HTML_TABLE_ON )
    1185             :         {   // es kann auch TD oder TH sein, wenn es vorher kein TABLE gab
    1186           0 :             const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
    1187           0 :             for (size_t i = 0, n = rOptions.size(); i < n; ++i)
    1188             :             {
    1189           0 :                 const HTMLOption& rOption = rOptions[i];
    1190           0 :                 switch( rOption.GetToken() )
    1191             :                 {
    1192             :                     case HTML_O_WIDTH:
    1193             :                     {   // Prozent: von Dokumentbreite bzw. aeusserer Zelle
    1194           0 :                         nTableWidth = GetWidthPixel( rOption );
    1195             :                     }
    1196           0 :                     break;
    1197             :                     case HTML_O_BORDER:
    1198             :                         //BorderOn is: ((pOption->GetString().Len() == 0) || (pOption->GetNumber() != 0));
    1199           0 :                     break;
    1200             :                     case HTML_O_ID:
    1201           0 :                         aTabName.Assign( rOption.GetString() );
    1202           0 :                     break;
    1203             :                 }
    1204             :             }
    1205             :         }
    1206             :     }
    1207           0 :     nTable = ++nMaxTable;
    1208           0 :     bFirstRow = true;
    1209           0 :     nFirstTableCell = maList.size();
    1210             : 
    1211           0 :     pLocalColOffset = new ScHTMLColOffset;
    1212           0 :     MakeColNoRef( pLocalColOffset, nColOffsetStart, 0, 0, 0 );
    1213           0 : }
    1214             : 
    1215             : 
    1216           0 : void ScHTMLLayoutParser::TableOff( ImportInfo* pInfo )
    1217             : {
    1218           0 :     if ( bInCell )
    1219           0 :         CloseEntry( pInfo );
    1220           0 :     if ( nColCnt > nColCntStart )
    1221           0 :         TableRowOff( pInfo );      // das optionale TableRowOff war nicht
    1222           0 :     if ( !nTableLevel )
    1223             :     {
    1224             :         OSL_FAIL( "Dummbatz-Dok! </TABLE> ohne oeffnendes <TABLE>" );
    1225           0 :         return ;
    1226             :     }
    1227           0 :     if ( --nTableLevel > 0 )
    1228             :     {   // Table in Table beendet
    1229           0 :         if ( !aTableStack.empty() )
    1230             :         {
    1231           0 :             ScHTMLTableStackEntry* pS = aTableStack.top();
    1232           0 :             aTableStack.pop();
    1233             : 
    1234           0 :             ScEEParseEntry* pE = pS->pCellEntry;
    1235           0 :             SCROW nRows = nRowCnt - pS->nRowCnt;
    1236           0 :             if ( nRows > 1 )
    1237             :             {   // Groesse der Tabelle an dieser Position eintragen
    1238           0 :                 SCROW nRow = pS->nRowCnt;
    1239           0 :                 sal_uInt16 nTab = pS->nTable;
    1240           0 :                 if ( !pTables )
    1241           0 :                     pTables = new OuterMap;
    1242             :                 // Hoehen der aeusseren Table
    1243           0 :                 OuterMap::const_iterator it = pTables->find( nTab );
    1244             :                 InnerMap* pTab1;
    1245           0 :                 if ( it == pTables->end() )
    1246             :                 {
    1247           0 :                     pTab1 = new InnerMap;
    1248           0 :                     (*pTables)[ nTab ] = pTab1;
    1249             :                 }
    1250             :                 else
    1251           0 :                     pTab1 = it->second;
    1252           0 :                 SCROW nRowSpan = pE->nRowOverlap;
    1253             :                 SCROW nRowKGV;
    1254             :                 SCROW nRowsPerRow1;    // aeussere Table
    1255             :                 SCROW nRowsPerRow2;    // innere Table
    1256           0 :                 if ( nRowSpan > 1 )
    1257             :                 {   // KGV auf das sich aussere und innere Zeilen
    1258             :                     // abbilden lassen
    1259           0 :                     nRowKGV = lcl_KGV( nRowSpan, nRows );
    1260           0 :                     nRowsPerRow1 = nRowKGV / nRowSpan;
    1261           0 :                     nRowsPerRow2 = nRowKGV / nRows;
    1262             :                 }
    1263             :                 else
    1264             :                 {
    1265           0 :                     nRowKGV = nRowsPerRow1 = nRows;
    1266           0 :                     nRowsPerRow2 = 1;
    1267             :                 }
    1268           0 :                 InnerMap* pTab2 = NULL;
    1269           0 :                 if ( nRowsPerRow2 > 1 )
    1270             :                 {   // Hoehen der inneren Table
    1271           0 :                     pTab2 = new InnerMap;
    1272           0 :                     (*pTables)[ nTable ] = pTab2;
    1273             :                 }
    1274             :                 // void* Data-Entry der Table-Class fuer das
    1275             :                 // Hoehen-Mapping missbrauchen
    1276           0 :                 if ( nRowKGV > 1 )
    1277             :                 {
    1278           0 :                     if ( nRowsPerRow1 > 1 )
    1279             :                     {   // aussen
    1280           0 :                         for ( SCROW j=0; j < nRowSpan; j++ )
    1281             :                         {
    1282           0 :                             sal_uLong nRowKey = nRow + j;
    1283           0 :                             SCROW nR = (*pTab1)[ nRowKey ];
    1284           0 :                             if ( !nR )
    1285           0 :                                 (*pTab1)[ nRowKey ] = nRowsPerRow1;
    1286           0 :                             else if ( nRowsPerRow1 > nR )
    1287           0 :                                 (*pTab1)[ nRowKey ] = nRowsPerRow1;
    1288             :                                 //2do: wie geht das noch besser?
    1289           0 :                             else if ( nRowsPerRow1 < nR && nRowSpan == 1
    1290             :                               && nTable == nMaxTable )
    1291             :                             {   // Platz uebrig, evtl. besser mergen
    1292           0 :                                 SCROW nAdd = nRowsPerRow1 - (nR % nRowsPerRow1);
    1293           0 :                                 nR += nAdd;
    1294           0 :                                 if ( (nR % nRows) == 0 )
    1295             :                                 {   // nur wenn abbildbar
    1296           0 :                                     SCROW nR2 = (*pTab1)[ nRowKey+1 ];
    1297           0 :                                     if ( nR2 > nAdd )
    1298             :                                     {   // nur wenn wirklich Platz
    1299           0 :                                         (*pTab1)[ nRowKey ] = nR;
    1300           0 :                                         (*pTab1)[ nRowKey+1 ] = nR2 - nAdd;
    1301           0 :                                         nRowsPerRow2 = nR / nRows;
    1302             :                                     }
    1303             :                                 }
    1304             :                             }
    1305             :                         }
    1306             :                     }
    1307           0 :                     if ( nRowsPerRow2 > 1 )
    1308             :                     {   // innen
    1309           0 :                         if ( !pTab2 )
    1310             :                         {   // nRowsPerRow2 kann erhoeht worden sein
    1311           0 :                             pTab2 = new InnerMap;
    1312           0 :                             (*pTables)[ nTable ] = pTab2;
    1313             :                         }
    1314           0 :                         for ( SCROW j=0; j < nRows; j++ )
    1315             :                         {
    1316           0 :                             sal_uLong nRowKey = nRow + j;
    1317           0 :                             (*pTab2)[ nRowKey ] = nRowsPerRow2;
    1318             :                         }
    1319             :                     }
    1320             :                 }
    1321             :             }
    1322             : 
    1323           0 :             SetWidths();
    1324             : 
    1325           0 :             if ( !pE->nWidth )
    1326           0 :                 pE->nWidth = nTableWidth;
    1327           0 :             else if ( pE->nWidth < nTableWidth )
    1328             :             {
    1329           0 :                 sal_uInt16 nOldOffset = pE->nOffset + pE->nWidth;
    1330           0 :                 sal_uInt16 nNewOffset = pE->nOffset + nTableWidth;
    1331           0 :                 ModifyOffset( pS->pLocalColOffset, nOldOffset, nNewOffset, nOffsetTolerance );
    1332           0 :                 sal_uInt16 nTmp = nNewOffset - pE->nOffset - pE->nWidth;
    1333           0 :                 pE->nWidth = nNewOffset - pE->nOffset;
    1334           0 :                 pS->nTableWidth = pS->nTableWidth + nTmp;
    1335           0 :                 if ( pS->nColOffset >= nOldOffset )
    1336           0 :                     pS->nColOffset = pS->nColOffset + nTmp;
    1337             :             }
    1338             : 
    1339           0 :             nColCnt = pE->nCol + pE->nColOverlap;
    1340           0 :             nRowCnt = pS->nRowCnt;
    1341           0 :             nColCntStart = pS->nColCntStart;
    1342           0 :             nMaxCol = pS->nMaxCol;
    1343           0 :             nTable = pS->nTable;
    1344           0 :             nTableWidth = pS->nTableWidth;
    1345           0 :             nFirstTableCell = pS->nFirstTableCell;
    1346           0 :             nColOffset = pS->nColOffset;
    1347           0 :             nColOffsetStart = pS->nColOffsetStart;
    1348           0 :             bFirstRow = pS->bFirstRow;
    1349           0 :             xLockedList = pS->xLockedList;
    1350           0 :             if ( pLocalColOffset )
    1351           0 :                 delete pLocalColOffset;
    1352           0 :             pLocalColOffset = pS->pLocalColOffset;
    1353           0 :             delete pActEntry;
    1354             :             // pActEntry bleibt erstmal erhalten falls da noch 'ne Table in
    1355             :             // der gleichen Zelle aufgemacht werden sollte (in HTML ist ja
    1356             :             // alles moeglich..) und wird in CloseEntry deleted
    1357           0 :             pActEntry = pE;
    1358           0 :             delete pS;
    1359             :         }
    1360           0 :         bTabInTabCell = true;
    1361           0 :         bInCell = true;
    1362             :     }
    1363             :     else
    1364             :     {   // einfache Table beendet
    1365           0 :         SetWidths();
    1366           0 :         nMaxCol = 0;
    1367           0 :         nTable = 0;
    1368           0 :         if ( !aTableStack.empty() )
    1369             :         {
    1370           0 :             ScHTMLTableStackEntry* pS = aTableStack.top();
    1371           0 :             aTableStack.pop();
    1372           0 :             if ( pLocalColOffset )
    1373           0 :                 delete pLocalColOffset;
    1374           0 :             pLocalColOffset = pS->pLocalColOffset;
    1375           0 :             delete pS;
    1376             :         }
    1377             :     }
    1378             : }
    1379             : 
    1380             : 
    1381           0 : void ScHTMLLayoutParser::Image( ImportInfo* pInfo )
    1382             : {
    1383           0 :     ScHTMLImage* pImage = new ScHTMLImage;
    1384           0 :     pActEntry->maImageList.push_back( pImage );
    1385           0 :     const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
    1386           0 :     for (size_t i = 0, n = rOptions.size(); i < n; ++i)
    1387             :     {
    1388           0 :         const HTMLOption& rOption = rOptions[i];
    1389           0 :         switch( rOption.GetToken() )
    1390             :         {
    1391             :             case HTML_O_SRC:
    1392             :             {
    1393           0 :                 pImage->aURL = INetURLObject::GetAbsURL( aBaseURL, rOption.GetString() );
    1394             :             }
    1395           0 :             break;
    1396             :             case HTML_O_ALT:
    1397             :             {
    1398           0 :                 if ( !pActEntry->bHasGraphic )
    1399             :                 {   // ALT text only if not any image loaded
    1400           0 :                     if (!pActEntry->aAltText.isEmpty())
    1401           0 :                         pActEntry->aAltText += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("; "));
    1402             : 
    1403           0 :                     pActEntry->aAltText += rOption.GetString();
    1404             :                 }
    1405             :             }
    1406           0 :             break;
    1407             :             case HTML_O_WIDTH:
    1408             :             {
    1409           0 :                 pImage->aSize.Width() = (long)rOption.GetNumber();
    1410             :             }
    1411           0 :             break;
    1412             :             case HTML_O_HEIGHT:
    1413             :             {
    1414           0 :                 pImage->aSize.Height() = (long)rOption.GetNumber();
    1415             :             }
    1416           0 :             break;
    1417             :             case HTML_O_HSPACE:
    1418             :             {
    1419           0 :                 pImage->aSpace.X() = (long)rOption.GetNumber();
    1420             :             }
    1421           0 :             break;
    1422             :             case HTML_O_VSPACE:
    1423             :             {
    1424           0 :                 pImage->aSpace.Y() = (long)rOption.GetNumber();
    1425             :             }
    1426           0 :             break;
    1427             :         }
    1428             :     }
    1429           0 :     if (pImage->aURL.isEmpty())
    1430             :     {
    1431             :         OSL_FAIL( "Image: Grafik ohne URL ?!?" );
    1432             :         return ;
    1433             :     }
    1434             : 
    1435             :     sal_uInt16 nFormat;
    1436           0 :     Graphic* pGraphic = new Graphic;
    1437           0 :     GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
    1438           0 :     if ( GRFILTER_OK != GraphicFilter::LoadGraphic( pImage->aURL, pImage->aFilterName,
    1439           0 :             *pGraphic, &rFilter, &nFormat ) )
    1440             :     {
    1441           0 :         delete pGraphic;
    1442             :         return ;        // dumm gelaufen
    1443             :     }
    1444           0 :     if ( !pActEntry->bHasGraphic )
    1445             :     {   // discard any ALT text in this cell if we have any image
    1446           0 :         pActEntry->bHasGraphic = true;
    1447           0 :         pActEntry->aAltText = rtl::OUString();
    1448             :     }
    1449           0 :     pImage->aFilterName = rFilter.GetImportFormatName( nFormat );
    1450           0 :     pImage->pGraphic = pGraphic;
    1451           0 :     if ( !(pImage->aSize.Width() && pImage->aSize.Height()) )
    1452             :     {
    1453           0 :         OutputDevice* pDefaultDev = Application::GetDefaultDevice();
    1454             :         pImage->aSize = pDefaultDev->LogicToPixel( pGraphic->GetPrefSize(),
    1455           0 :             pGraphic->GetPrefMapMode() );
    1456             :     }
    1457           0 :     if ( pActEntry->maImageList.size() > 0 )
    1458             :     {
    1459           0 :         long nWidth = 0;
    1460           0 :         for ( sal_uInt32 i=0; i < pActEntry->maImageList.size(); ++i )
    1461             :         {
    1462           0 :             ScHTMLImage* pI = &pActEntry->maImageList[ i ];
    1463           0 :             if ( pI->nDir & nHorizontal )
    1464           0 :                 nWidth += pI->aSize.Width() + 2 * pI->aSpace.X();
    1465             :             else
    1466           0 :                 nWidth = 0;
    1467             :         }
    1468           0 :         if ( pActEntry->nWidth
    1469           0 :           && (nWidth + pImage->aSize.Width() + 2 * pImage->aSpace.X()
    1470             :                 >= pActEntry->nWidth) )
    1471           0 :             pActEntry->maImageList.back().nDir = nVertical;
    1472             :     }
    1473             : }
    1474             : 
    1475             : 
    1476           0 : void ScHTMLLayoutParser::ColOn( ImportInfo* pInfo )
    1477             : {
    1478           0 :     const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
    1479           0 :     for (size_t i = 0, n = rOptions.size(); i < n; ++i)
    1480             :     {
    1481           0 :         const HTMLOption& rOption = rOptions[i];
    1482           0 :         switch( rOption.GetToken() )
    1483             :         {
    1484             :             case HTML_O_WIDTH:
    1485             :             {
    1486           0 :                 sal_uInt16 nVal = GetWidthPixel( rOption );
    1487           0 :                 MakeCol( pLocalColOffset, nColOffset, nVal, 0, 0 );
    1488           0 :                 nColOffset = nColOffset + nVal;
    1489             :             }
    1490           0 :             break;
    1491             :         }
    1492             :     }
    1493           0 : }
    1494             : 
    1495             : 
    1496           0 : sal_uInt16 ScHTMLLayoutParser::GetWidthPixel( const HTMLOption& rOption )
    1497             : {
    1498           0 :     const String& rOptVal = rOption.GetString();
    1499           0 :     if ( rOptVal.Search('%') != STRING_NOTFOUND )
    1500             :     {   // Prozent
    1501           0 :         sal_uInt16 nW = (nTableWidth ? nTableWidth : (sal_uInt16) aPageSize.Width());
    1502           0 :         return (sal_uInt16)((rOption.GetNumber() * nW) / 100);
    1503             :     }
    1504             :     else
    1505             :     {
    1506           0 :         if ( rOptVal.Search('*') != STRING_NOTFOUND )
    1507             :         {   // relativ zu was?!?
    1508             :             //todo: ColArray aller relativen Werte sammeln und dann MakeCol
    1509           0 :             return 0;
    1510             :         }
    1511             :         else
    1512           0 :             return (sal_uInt16)rOption.GetNumber();    // Pixel
    1513             :     }
    1514             : }
    1515             : 
    1516             : 
    1517           0 : void ScHTMLLayoutParser::AnchorOn( ImportInfo* pInfo )
    1518             : {
    1519           0 :     const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
    1520           0 :     for (size_t i = 0, n = rOptions.size(); i < n; ++i)
    1521             :     {
    1522           0 :         const HTMLOption& rOption = rOptions[i];
    1523           0 :         switch( rOption.GetToken() )
    1524             :         {
    1525             :             case HTML_O_NAME:
    1526             :             {
    1527           0 :                 pActEntry->pName = new rtl::OUString(rOption.GetString());
    1528             :             }
    1529           0 :             break;
    1530             :         }
    1531             :     }
    1532           0 : }
    1533             : 
    1534             : 
    1535           0 : bool ScHTMLLayoutParser::IsAtBeginningOfText( ImportInfo* pInfo )
    1536             : {
    1537           0 :     ESelection& rSel = pActEntry->aSel;
    1538             :     return rSel.nStartPara == rSel.nEndPara &&
    1539             :         rSel.nStartPara <= pInfo->aSelection.nEndPara &&
    1540           0 :         pEdit->GetTextLen( rSel.nStartPara ) == 0;
    1541             : }
    1542             : 
    1543             : 
    1544           0 : void ScHTMLLayoutParser::FontOn( ImportInfo* pInfo )
    1545             : {
    1546           0 :     if ( IsAtBeginningOfText( pInfo ) )
    1547             :     {   // nur am Anfang des Textes, gilt dann fuer gesamte Zelle
    1548           0 :         const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
    1549           0 :         for (size_t i = 0, n = rOptions.size(); i < n; ++i)
    1550             :         {
    1551           0 :             const HTMLOption& rOption = rOptions[i];
    1552           0 :             switch( rOption.GetToken() )
    1553             :             {
    1554             :                 case HTML_O_FACE :
    1555             :                 {
    1556           0 :                     const String& rFace = rOption.GetString();
    1557           0 :                     String aFontName;
    1558           0 :                     xub_StrLen nPos = 0;
    1559           0 :                     while( nPos != STRING_NOTFOUND )
    1560             :                     {
    1561             :                         // Fontliste, VCL: Semikolon als Separator, HTML: Komma
    1562           0 :                         String aFName = rFace.GetToken( 0, ',', nPos );
    1563           0 :                         aFName = comphelper::string::strip(aFName, ' ');
    1564           0 :                         if( aFontName.Len() )
    1565           0 :                             aFontName += ';';
    1566           0 :                         aFontName += aFName;
    1567           0 :                     }
    1568           0 :                     if ( aFontName.Len() )
    1569             :                         pActEntry->aItemSet.Put( SvxFontItem( FAMILY_DONTKNOW,
    1570           0 :                             aFontName, EMPTY_STRING, PITCH_DONTKNOW,
    1571           0 :                             RTL_TEXTENCODING_DONTKNOW, ATTR_FONT ) );
    1572             :                 }
    1573           0 :                 break;
    1574             :                 case HTML_O_SIZE :
    1575             :                 {
    1576           0 :                     sal_uInt16 nSize = (sal_uInt16) rOption.GetNumber();
    1577           0 :                     if ( nSize == 0 )
    1578           0 :                         nSize = 1;
    1579           0 :                     else if ( nSize > SC_HTML_FONTSIZES )
    1580           0 :                         nSize = SC_HTML_FONTSIZES;
    1581             :                     pActEntry->aItemSet.Put( SvxFontHeightItem(
    1582           0 :                         maFontHeights[nSize-1], 100, ATTR_FONT_HEIGHT ) );
    1583             :                 }
    1584           0 :                 break;
    1585             :                 case HTML_O_COLOR :
    1586             :                 {
    1587           0 :                     Color aColor;
    1588           0 :                     rOption.GetColor( aColor );
    1589           0 :                     pActEntry->aItemSet.Put( SvxColorItem( aColor, ATTR_FONT_COLOR ) );
    1590             :                 }
    1591           0 :                 break;
    1592             :             }
    1593             :         }
    1594             :     }
    1595           0 : }
    1596             : 
    1597             : 
    1598           0 : void ScHTMLLayoutParser::ProcToken( ImportInfo* pInfo )
    1599             : {
    1600           0 :     bool bSetLastToken = true;
    1601           0 :     switch ( pInfo->nToken )
    1602             :     {
    1603             :         case HTML_META:
    1604             :         {
    1605           0 :             HTMLParser* pParser = static_cast<HTMLParser*>(pInfo->pParser);
    1606             :             uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
    1607           0 :                 mpDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW);
    1608             :             pParser->ParseMetaOptions(
    1609           0 :                 xDPS->getDocumentProperties(),
    1610           0 :                 mpDoc->GetDocumentShell()->GetHeaderAttributes() );
    1611             :         }
    1612           0 :         break;
    1613             :         case HTML_TITLE_ON:
    1614             :         {
    1615           0 :             bInTitle = true;
    1616           0 :             aString = rtl::OUString();
    1617             :         }
    1618           0 :         break;
    1619             :         case HTML_TITLE_OFF:
    1620             :         {
    1621           0 :             if ( bInTitle && !aString.isEmpty() )
    1622             :             {
    1623             :                 // Leerzeichen von Zeilenumbruechen raus
    1624           0 :                 aString = aString.trim();
    1625             :                 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
    1626             :                     mpDoc->GetDocumentShell()->GetModel(),
    1627           0 :                     uno::UNO_QUERY_THROW);
    1628           0 :                 xDPS->getDocumentProperties()->setTitle(aString);
    1629             :             }
    1630           0 :             bInTitle = false;
    1631             :         }
    1632           0 :         break;
    1633             :         case HTML_TABLE_ON:
    1634             :         {
    1635           0 :             TableOn( pInfo );
    1636             :         }
    1637           0 :         break;
    1638             :         case HTML_COL_ON:
    1639             :         {
    1640           0 :             ColOn( pInfo );
    1641             :         }
    1642           0 :         break;
    1643             :         case HTML_TABLEHEADER_ON:       // oeffnet Zelle
    1644             :         {
    1645           0 :             if ( bInCell )
    1646           0 :                 CloseEntry( pInfo );
    1647             :             // bInCell nicht true setzen, das macht TableDataOn
    1648             :             pActEntry->aItemSet.Put(
    1649           0 :                 SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT) );
    1650             :         }   // fall thru
    1651             :         case HTML_TABLEDATA_ON:         // oeffnet Zelle
    1652             :         {
    1653           0 :             TableDataOn( pInfo );
    1654             :         }
    1655           0 :         break;
    1656             :         case HTML_TABLEHEADER_OFF:
    1657             :         case HTML_TABLEDATA_OFF:        // schliesst Zelle
    1658             :         {
    1659           0 :             TableDataOff( pInfo );
    1660             :         }
    1661           0 :         break;
    1662             :         case HTML_TABLEROW_ON:          // vor erster Zelle in Row
    1663             :         {
    1664           0 :             TableRowOn( pInfo );
    1665             :         }
    1666           0 :         break;
    1667             :         case HTML_TABLEROW_OFF:         // nach letzter Zelle in Row
    1668             :         {
    1669           0 :             TableRowOff( pInfo );
    1670             :         }
    1671           0 :         break;
    1672             :         case HTML_TABLE_OFF:
    1673             :         {
    1674           0 :             TableOff( pInfo );
    1675             :         }
    1676           0 :         break;
    1677             :         case HTML_IMAGE:
    1678             :         {
    1679           0 :             Image( pInfo );
    1680             :         }
    1681           0 :         break;
    1682             :         case HTML_PARABREAK_OFF:
    1683             :         {   // nach einem Image geht es vertikal weiter
    1684           0 :             if ( pActEntry->maImageList.size() > 0 )
    1685           0 :                 pActEntry->maImageList.back().nDir = nVertical;
    1686             :         }
    1687           0 :         break;
    1688             :         case HTML_ANCHOR_ON:
    1689             :         {
    1690           0 :             AnchorOn( pInfo );
    1691             :         }
    1692           0 :         break;
    1693             :         case HTML_FONT_ON :
    1694             :         {
    1695           0 :             FontOn( pInfo );
    1696             :         }
    1697           0 :         break;
    1698             :         case HTML_BIGPRINT_ON :
    1699             :         {
    1700             :             //tpdo: aktuelle Fontgroesse merken und einen groesser
    1701           0 :             if ( IsAtBeginningOfText( pInfo ) )
    1702             :                 pActEntry->aItemSet.Put( SvxFontHeightItem(
    1703           0 :                     maFontHeights[3], 100, ATTR_FONT_HEIGHT ) );
    1704             :         }
    1705           0 :         break;
    1706             :         case HTML_SMALLPRINT_ON :
    1707             :         {
    1708             :             //todo: aktuelle Fontgroesse merken und einen kleiner
    1709           0 :             if ( IsAtBeginningOfText( pInfo ) )
    1710             :                 pActEntry->aItemSet.Put( SvxFontHeightItem(
    1711           0 :                     maFontHeights[0], 100, ATTR_FONT_HEIGHT ) );
    1712             :         }
    1713           0 :         break;
    1714             :         case HTML_BOLD_ON :
    1715             :         case HTML_STRONG_ON :
    1716             :         {
    1717           0 :             if ( IsAtBeginningOfText( pInfo ) )
    1718             :                 pActEntry->aItemSet.Put( SvxWeightItem( WEIGHT_BOLD,
    1719           0 :                     ATTR_FONT_WEIGHT ) );
    1720             :         }
    1721           0 :         break;
    1722             :         case HTML_ITALIC_ON :
    1723             :         case HTML_EMPHASIS_ON :
    1724             :         case HTML_ADDRESS_ON :
    1725             :         case HTML_BLOCKQUOTE_ON :
    1726             :         case HTML_BLOCKQUOTE30_ON :
    1727             :         case HTML_CITIATION_ON :
    1728             :         case HTML_VARIABLE_ON :
    1729             :         {
    1730           0 :             if ( IsAtBeginningOfText( pInfo ) )
    1731             :                 pActEntry->aItemSet.Put( SvxPostureItem( ITALIC_NORMAL,
    1732           0 :                     ATTR_FONT_POSTURE ) );
    1733             :         }
    1734           0 :         break;
    1735             :         case HTML_DEFINSTANCE_ON :
    1736             :         {
    1737           0 :             if ( IsAtBeginningOfText( pInfo ) )
    1738             :             {
    1739             :                 pActEntry->aItemSet.Put( SvxWeightItem( WEIGHT_BOLD,
    1740           0 :                     ATTR_FONT_WEIGHT ) );
    1741             :                 pActEntry->aItemSet.Put( SvxPostureItem( ITALIC_NORMAL,
    1742           0 :                     ATTR_FONT_POSTURE ) );
    1743             :             }
    1744             :         }
    1745           0 :         break;
    1746             :         case HTML_UNDERLINE_ON :
    1747             :         {
    1748           0 :             if ( IsAtBeginningOfText( pInfo ) )
    1749             :                 pActEntry->aItemSet.Put( SvxUnderlineItem( UNDERLINE_SINGLE,
    1750           0 :                     ATTR_FONT_UNDERLINE ) );
    1751             :         }
    1752           0 :         break;
    1753             :         case HTML_TEXTTOKEN:
    1754             :         {
    1755           0 :             if ( bInTitle )
    1756           0 :                 aString += pInfo->aText;
    1757             :         }
    1758           0 :         break;
    1759             :         default:
    1760             :         {   // nLastToken nicht setzen!
    1761           0 :             bSetLastToken = false;
    1762             :         }
    1763             :     }
    1764           0 :     if ( bSetLastToken )
    1765           0 :         nLastToken = pInfo->nToken;
    1766           0 : }
    1767             : 
    1768             : 
    1769             : 
    1770             : // ============================================================================
    1771             : // HTML DATA QUERY PARSER
    1772             : // ============================================================================
    1773             : 
    1774             : template< typename Type >
    1775           0 : inline Type getLimitedValue( const Type& rValue, const Type& rMin, const Type& rMax )
    1776           0 : { return ::std::max( ::std::min( rValue, rMax ), rMin ); }
    1777             : 
    1778          28 : ScHTMLEntry::ScHTMLEntry( const SfxItemSet& rItemSet, ScHTMLTableId nTableId ) :
    1779             :     ScEEParseEntry( rItemSet ),
    1780          28 :     mbImportAlways( false )
    1781             : {
    1782          28 :     nTab = nTableId;
    1783          28 :     bEntirePara = false;
    1784          28 : }
    1785             : 
    1786          40 : bool ScHTMLEntry::HasContents() const
    1787             : {
    1788          40 :      return mbImportAlways || aSel.HasRange() || !aAltText.isEmpty() || IsTable();
    1789             : }
    1790             : 
    1791           7 : void ScHTMLEntry::AdjustStart( const ImportInfo& rInfo )
    1792             : {
    1793             :     // set start position
    1794           7 :     aSel.nStartPara = rInfo.aSelection.nStartPara;
    1795           7 :     aSel.nStartPos = rInfo.aSelection.nStartPos;
    1796             :     // adjust end position
    1797           7 :     if( (aSel.nEndPara < aSel.nStartPara) || ((aSel.nEndPara == aSel.nStartPara) && (aSel.nEndPos < aSel.nStartPos)) )
    1798             :     {
    1799           0 :         aSel.nEndPara = aSel.nStartPara;
    1800           0 :         aSel.nEndPos = aSel.nStartPos;
    1801             :     }
    1802           7 : }
    1803             : 
    1804          32 : void ScHTMLEntry::AdjustEnd( const ImportInfo& rInfo )
    1805             : {
    1806             :     OSL_ENSURE( (aSel.nEndPara < rInfo.aSelection.nEndPara) ||
    1807             :                 ((aSel.nEndPara == rInfo.aSelection.nEndPara) && (aSel.nEndPos <= rInfo.aSelection.nEndPos)),
    1808             :                 "ScHTMLQueryParser::AdjustEntryEnd - invalid end position" );
    1809             :     // set end position
    1810          32 :     aSel.nEndPara = rInfo.aSelection.nEndPara;
    1811          32 :     aSel.nEndPos = rInfo.aSelection.nEndPos;
    1812          32 : }
    1813             : 
    1814          26 : void ScHTMLEntry::Strip( const EditEngine& rEditEngine )
    1815             : {
    1816             :     // strip leading empty paragraphs
    1817          58 :     while( (aSel.nStartPara < aSel.nEndPara) && (rEditEngine.GetTextLen( aSel.nStartPara ) <= aSel.nStartPos) )
    1818             :     {
    1819           6 :         ++aSel.nStartPara;
    1820           6 :         aSel.nStartPos = 0;
    1821             :     }
    1822             :     // strip trailing empty paragraphs
    1823          52 :     while( (aSel.nStartPara < aSel.nEndPara) && (aSel.nEndPos == 0) )
    1824             :     {
    1825           0 :         --aSel.nEndPara;
    1826           0 :         aSel.nEndPos = rEditEngine.GetTextLen( aSel.nEndPara );
    1827             :     }
    1828          26 : }
    1829             : 
    1830             : // ============================================================================
    1831             : 
    1832             : /** A map of ScHTMLTable objects.
    1833             : 
    1834             :     Organizes the tables with a unique table key. Stores nested tables inside
    1835             :     the parent table and forms in this way a tree structure of tables. An
    1836             :     instance of this class ownes the contained table objects and deletes them
    1837             :     on destruction.
    1838             :  */
    1839             : class ScHTMLTableMap
    1840             : {
    1841             : private:
    1842             :     typedef ::boost::shared_ptr< ScHTMLTable >          ScHTMLTablePtr;
    1843             :     typedef ::std::map< ScHTMLTableId, ScHTMLTablePtr > ScHTMLTableStdMap;
    1844             : 
    1845             : public:
    1846             :     typedef ScHTMLTableStdMap::iterator             iterator;
    1847             :     typedef ScHTMLTableStdMap::const_iterator       const_iterator;
    1848             : 
    1849             : private:
    1850             :     ScHTMLTable&        mrParentTable;      /// Reference to parent table.
    1851             :     ScHTMLTableStdMap   maTables;           /// Container for all table objects.
    1852             :     mutable ScHTMLTable* mpCurrTable;       /// Current table, used for fast search.
    1853             : 
    1854             : public:
    1855             :     explicit            ScHTMLTableMap( ScHTMLTable& rParentTable );
    1856             :     virtual             ~ScHTMLTableMap();
    1857             : 
    1858             :     inline iterator     begin() { return maTables.begin(); }
    1859           4 :     inline const_iterator begin() const { return maTables.begin(); }
    1860             :     inline iterator     end() { return maTables.end(); }
    1861           4 :     inline const_iterator end() const { return maTables.end(); }
    1862             :     inline bool         empty() const { return maTables.empty(); }
    1863             : 
    1864             :     /** Returns the specified table.
    1865             :         @param nTableId  Unique identifier of the table.
    1866             :         @param bDeep  true = searches deep in all nested table; false = only in this container. */
    1867             :     ScHTMLTable*        FindTable( ScHTMLTableId nTableId, bool bDeep = true ) const;
    1868             : 
    1869             :     /** Inserts a new table into the container. This container owns the created table.
    1870             :         @param bPreFormText  true = New table is based on preformatted text (<pre> tag). */
    1871             :     ScHTMLTable*        CreateTable( const ImportInfo& rInfo, bool bPreFormText );
    1872             : 
    1873             : private:
    1874             :     /** Sets a working table with its index for search optimization. */
    1875           5 :     inline void         SetCurrTable( ScHTMLTable* pTable ) const
    1876           5 :                             { if( pTable ) mpCurrTable = pTable; }
    1877             : };
    1878             : 
    1879             : // ----------------------------------------------------------------------------
    1880             : 
    1881           1 : ScHTMLTableMap::ScHTMLTableMap( ScHTMLTable& rParentTable ) :
    1882             :     mrParentTable(rParentTable),
    1883           1 :     mpCurrTable(NULL)
    1884             : {
    1885           1 : }
    1886             : 
    1887           2 : ScHTMLTableMap::~ScHTMLTableMap()
    1888             : {
    1889           2 : }
    1890             : 
    1891           4 : ScHTMLTable* ScHTMLTableMap::FindTable( ScHTMLTableId nTableId, bool bDeep ) const
    1892             : {
    1893           4 :     ScHTMLTable* pResult = 0;
    1894           4 :     if( mpCurrTable && (nTableId == mpCurrTable->GetTableId()) )
    1895           3 :         pResult = mpCurrTable;              // cached table
    1896             :     else
    1897             :     {
    1898           1 :         const_iterator aFind = maTables.find( nTableId );
    1899           1 :         if( aFind != maTables.end() )
    1900           0 :             pResult = aFind->second.get();  // table from this container
    1901             :     }
    1902             : 
    1903             :     // not found -> search deep in nested tables
    1904           4 :     if( !pResult && bDeep )
    1905           2 :         for( const_iterator aIter = begin(), aEnd = end(); !pResult && (aIter != aEnd); ++aIter )
    1906           1 :             pResult = aIter->second->FindNestedTable( nTableId );
    1907             : 
    1908           4 :     SetCurrTable( pResult );
    1909           4 :     return pResult;
    1910             : }
    1911             : 
    1912           1 : ScHTMLTable* ScHTMLTableMap::CreateTable( const ImportInfo& rInfo, bool bPreFormText )
    1913             : {
    1914           1 :     ScHTMLTable* pTable = new ScHTMLTable( mrParentTable, rInfo, bPreFormText );
    1915           1 :     maTables[ pTable->GetTableId() ].reset( pTable );
    1916           1 :     SetCurrTable( pTable );
    1917           1 :     return pTable;
    1918             : }
    1919             : 
    1920             : // ----------------------------------------------------------------------------
    1921             : 
    1922             : /** Simplified forward iterator for convenience.
    1923             : 
    1924             :     Before the iterator can be dereferenced, it must be tested with the is()
    1925             :     method. The iterator may be invalid directly after construction (e.g. empty
    1926             :     container).
    1927             :  */
    1928             : class ScHTMLTableIterator
    1929             : {
    1930             : public:
    1931             :     /** Constructs the iterator for the passed table map.
    1932             :         @param pTableMap  Pointer to the table map (is allowed to be NULL). */
    1933             :     explicit            ScHTMLTableIterator( const ScHTMLTableMap* pTableMap );
    1934             : 
    1935           9 :     inline bool         is() const { return mpTableMap && maIter != maEnd; }
    1936           3 :     inline ScHTMLTable* operator->() { return maIter->second.get(); }
    1937             :     inline ScHTMLTable& operator*() { return *maIter->second; }
    1938           3 :     inline ScHTMLTableIterator& operator++() { ++maIter; return *this; }
    1939             : 
    1940             : private:
    1941             :     ScHTMLTableMap::const_iterator maIter;
    1942             :     ScHTMLTableMap::const_iterator maEnd;
    1943             :     const ScHTMLTableMap* mpTableMap;
    1944             : };
    1945             : 
    1946           6 : ScHTMLTableIterator::ScHTMLTableIterator( const ScHTMLTableMap* pTableMap ) :
    1947           6 :     mpTableMap(pTableMap)
    1948             : {
    1949           6 :     if( pTableMap )
    1950             :     {
    1951           3 :         maIter = pTableMap->begin();
    1952           3 :         maEnd = pTableMap->end();
    1953             :     }
    1954           6 : }
    1955             : 
    1956             : // ============================================================================
    1957             : 
    1958           2 : ScHTMLTableAutoId::ScHTMLTableAutoId( ScHTMLTableId& rnUnusedId ) :
    1959             :     mnTableId( rnUnusedId ),
    1960           2 :     mrnUnusedId( rnUnusedId )
    1961             : {
    1962           2 :     ++mrnUnusedId;
    1963           2 : }
    1964             : 
    1965             : // ----------------------------------------------------------------------------
    1966             : 
    1967           1 : ScHTMLTable::ScHTMLTable( ScHTMLTable& rParentTable, const ImportInfo& rInfo, bool bPreFormText ) :
    1968             :     mpParentTable( &rParentTable ),
    1969             :     maTableId( rParentTable.maTableId.mrnUnusedId ),
    1970           1 :     maTableItemSet( rParentTable.GetCurrItemSet() ),
    1971             :     mrEditEngine( rParentTable.mrEditEngine ),
    1972             :     mrEEParseList( rParentTable.mrEEParseList ),
    1973             :     mpCurrEntryList( 0 ),
    1974             :     maSize( 1, 1 ),
    1975             :     mpParser(rParentTable.mpParser),
    1976             :     mbBorderOn( false ),
    1977             :     mbPreFormText( bPreFormText ),
    1978             :     mbRowOn( false ),
    1979             :     mbDataOn( false ),
    1980           2 :     mbPushEmptyLine( false )
    1981             : {
    1982           1 :     if( mbPreFormText )
    1983             :     {
    1984           0 :         ImplRowOn();
    1985           0 :         ImplDataOn( ScHTMLSize( 1, 1 ) );
    1986             :     }
    1987             :     else
    1988             :     {
    1989           1 :         ProcessFormatOptions( maTableItemSet, rInfo );
    1990           1 :         const HTMLOptions& rOptions = static_cast<HTMLParser*>(rInfo.pParser)->GetOptions();
    1991           1 :         HTMLOptions::const_iterator itr = rOptions.begin(), itrEnd = rOptions.end();
    1992           1 :         for (; itr != itrEnd; ++itr)
    1993             :         {
    1994           0 :             switch( itr->GetToken() )
    1995             :             {
    1996             :                 case HTML_O_BORDER:
    1997           0 :                     mbBorderOn = ((itr->GetString().Len() == 0) || (itr->GetNumber() != 0));
    1998           0 :                 break;
    1999             :                 case HTML_O_ID:
    2000           0 :                     maTableName = itr->GetString();
    2001           0 :                 break;
    2002             :             }
    2003             :         }
    2004             :     }
    2005             : 
    2006           1 :     CreateNewEntry( rInfo );
    2007           1 : }
    2008             : 
    2009           1 : ScHTMLTable::ScHTMLTable(
    2010             :     SfxItemPool& rPool,
    2011             :     EditEngine& rEditEngine,
    2012             :     ::std::vector< ScEEParseEntry* >& rEEParseList,
    2013             :     ScHTMLTableId& rnUnusedId, ScHTMLParser* pParser
    2014             : ) :
    2015             :     mpParentTable( 0 ),
    2016             :     maTableId( rnUnusedId ),
    2017             :     maTableItemSet( rPool ),
    2018             :     mrEditEngine( rEditEngine ),
    2019             :     mrEEParseList( rEEParseList ),
    2020             :     mpCurrEntryList( 0 ),
    2021             :     maSize( 1, 1 ),
    2022             :     mpParser(pParser),
    2023             :     mbBorderOn( false ),
    2024             :     mbPreFormText( false ),
    2025             :     mbRowOn( false ),
    2026             :     mbDataOn( false ),
    2027           1 :     mbPushEmptyLine( false )
    2028             : {
    2029             :     // open the first "cell" of the document
    2030           1 :     ImplRowOn();
    2031           1 :     ImplDataOn( ScHTMLSize( 1, 1 ) );
    2032           1 :     mxCurrEntry = CreateEntry();
    2033           1 : }
    2034             : 
    2035           9 : ScHTMLTable::~ScHTMLTable()
    2036             : {
    2037           9 : }
    2038             : 
    2039          28 : const SfxItemSet& ScHTMLTable::GetCurrItemSet() const
    2040             : {
    2041             :     // first try cell item set, then row item set, then table item set
    2042          28 :     return mxDataItemSet.get() ? *mxDataItemSet : (mxRowItemSet.get() ? *mxRowItemSet : maTableItemSet);
    2043             : }
    2044             : 
    2045          21 : ScHTMLSize ScHTMLTable::GetSpan( const ScHTMLPos& rCellPos ) const
    2046             : {
    2047          21 :     ScHTMLSize aSpan( 1, 1 );
    2048          21 :     const ScRange* pRange = NULL;
    2049          84 :     if(  ( (pRange = maVMergedCells.Find( rCellPos.MakeAddr() ) ) != 0)
    2050          63 :       || ( (pRange = maHMergedCells.Find( rCellPos.MakeAddr() ) ) != 0)
    2051             :       )
    2052           0 :         aSpan.Set( pRange->aEnd.Col() - pRange->aStart.Col() + 1, pRange->aEnd.Row() - pRange->aStart.Row() + 1 );
    2053          21 :     return aSpan;
    2054             : }
    2055             : 
    2056           3 : ScHTMLTable* ScHTMLTable::FindNestedTable( ScHTMLTableId nTableId ) const
    2057             : {
    2058           3 :     return mxNestedTables.get() ? mxNestedTables->FindTable( nTableId, true ) : 0;
    2059             : }
    2060             : 
    2061           0 : void ScHTMLTable::PutItem( const SfxPoolItem& rItem )
    2062             : {
    2063             :     OSL_ENSURE( mxCurrEntry.get(), "ScHTMLTable::PutItem - no current entry" );
    2064           0 :     if( mxCurrEntry.get() && mxCurrEntry->IsEmpty() )
    2065           0 :         mxCurrEntry->GetItemSet().Put( rItem );
    2066           0 : }
    2067             : 
    2068          13 : void ScHTMLTable::PutText( const ImportInfo& rInfo )
    2069             : {
    2070             :     OSL_ENSURE( mxCurrEntry.get(), "ScHTMLTable::PutText - no current entry" );
    2071          13 :     if( mxCurrEntry.get() )
    2072             :     {
    2073          13 :         if( !mxCurrEntry->HasContents() && IsSpaceCharInfo( rInfo ) )
    2074           7 :             mxCurrEntry->AdjustStart( rInfo );
    2075             :         else
    2076           6 :             mxCurrEntry->AdjustEnd( rInfo );
    2077             :     }
    2078          13 : }
    2079             : 
    2080           6 : void ScHTMLTable::InsertPara( const ImportInfo& rInfo )
    2081             : {
    2082           6 :     if( mxCurrEntry.get() && mbDataOn && !IsEmptyCell() )
    2083           0 :         mxCurrEntry->SetImportAlways();
    2084           6 :     PushEntry( rInfo );
    2085           6 :     CreateNewEntry( rInfo );
    2086           6 :     InsertLeadingEmptyLine();
    2087           6 : }
    2088             : 
    2089           0 : void ScHTMLTable::BreakOn()
    2090             : {
    2091             :     // empty line, if <br> is at start of cell
    2092           0 :     mbPushEmptyLine = !mbPreFormText && mbDataOn && IsEmptyCell();
    2093           0 : }
    2094             : 
    2095           0 : void ScHTMLTable::HeadingOn()
    2096             : {
    2097             :     // call directly, InsertPara() has not been called before
    2098           0 :     InsertLeadingEmptyLine();
    2099           0 : }
    2100             : 
    2101           6 : void ScHTMLTable::InsertLeadingEmptyLine()
    2102             : {
    2103             :     // empty line, if <p>, </p>, <h?>, or </h*> are not at start of cell
    2104           6 :     mbPushEmptyLine = !mbPreFormText && mbDataOn && !IsEmptyCell();
    2105           6 : }
    2106             : 
    2107           0 : void ScHTMLTable::AnchorOn()
    2108             : {
    2109             :     OSL_ENSURE( mxCurrEntry.get(), "ScHTMLTable::AnchorOn - no current entry" );
    2110             :     // don't skip entries with single hyperlinks
    2111           0 :     if( mxCurrEntry.get() )
    2112           0 :         mxCurrEntry->SetImportAlways();
    2113           0 : }
    2114             : 
    2115           1 : ScHTMLTable* ScHTMLTable::TableOn( const ImportInfo& rInfo )
    2116             : {
    2117           1 :     PushEntry( rInfo );
    2118           1 :     return InsertNestedTable( rInfo, false );
    2119             : }
    2120             : 
    2121           1 : ScHTMLTable* ScHTMLTable::TableOff( const ImportInfo& rInfo )
    2122             : {
    2123           1 :     return mbPreFormText ? this : CloseTable( rInfo );
    2124             : }
    2125             : 
    2126           0 : ScHTMLTable* ScHTMLTable::PreOn( const ImportInfo& rInfo )
    2127             : {
    2128           0 :     PushEntry( rInfo );
    2129           0 :     return InsertNestedTable( rInfo, true );
    2130             : }
    2131             : 
    2132           0 : ScHTMLTable* ScHTMLTable::PreOff( const ImportInfo& rInfo )
    2133             : {
    2134           0 :     return mbPreFormText ? CloseTable( rInfo ) : this;
    2135             : }
    2136             : 
    2137           2 : void ScHTMLTable::RowOn( const ImportInfo& rInfo )
    2138             : {
    2139           2 :     PushEntry( rInfo, true );
    2140           2 :     if( mpParentTable && !mbPreFormText )   // no rows allowed in global and preformatted tables
    2141             :     {
    2142           2 :         ImplRowOn();
    2143           2 :         ProcessFormatOptions( *mxRowItemSet, rInfo );
    2144             :     }
    2145           2 :     CreateNewEntry( rInfo );
    2146           2 : }
    2147             : 
    2148           2 : void ScHTMLTable::RowOff( const ImportInfo& rInfo )
    2149             : {
    2150           2 :     PushEntry( rInfo, true );
    2151           2 :     if( mpParentTable && !mbPreFormText )   // no rows allowed in global and preformatted tables
    2152           2 :         ImplRowOff();
    2153           2 :     CreateNewEntry( rInfo );
    2154           2 : }
    2155             : 
    2156             : namespace {
    2157             : 
    2158             : /**
    2159             :  * Decode a numbert format string stored in Excel-generated HTML's CSS
    2160             :  * region.
    2161             :  */
    2162           0 : rtl::OUString decodeNumberFormat(const rtl::OUString& rFmt)
    2163             : {
    2164           0 :     rtl::OUStringBuffer aBuf;
    2165           0 :     const sal_Unicode* p = rFmt.getStr();
    2166           0 :     sal_Int32 n = rFmt.getLength();
    2167           0 :     for (sal_Int32 i = 0; i < n; ++i, ++p)
    2168             :     {
    2169           0 :         if (*p == '\\')
    2170             :         {
    2171             :             // Skip '\'.
    2172           0 :             ++i;
    2173           0 :             ++p;
    2174             : 
    2175             :             // Parse all subsequent digits until first non-digit is found.
    2176           0 :             sal_Int32 nDigitCount = 0;
    2177           0 :             const sal_Unicode* p1 = p;
    2178           0 :             for (; i < n; ++i, ++p, ++nDigitCount)
    2179             :             {
    2180           0 :                 if (*p < '0' || '9' < *p)
    2181             :                 {
    2182           0 :                     --i;
    2183           0 :                     --p;
    2184           0 :                     break;
    2185             :                 }
    2186             : 
    2187             :             }
    2188           0 :             if (nDigitCount)
    2189             :             {
    2190           0 :                 sal_Int32 nVal = rtl::OUString(p1, nDigitCount).toInt32(16);
    2191           0 :                 aBuf.append(static_cast<sal_Unicode>(nVal));
    2192             :             }
    2193             :         }
    2194             :         else
    2195           0 :             aBuf.append(*p);
    2196             :     }
    2197           0 :     return aBuf.makeStringAndClear();
    2198             : }
    2199             : 
    2200             : }
    2201             : 
    2202           6 : void ScHTMLTable::DataOn( const ImportInfo& rInfo )
    2203             : {
    2204           6 :     PushEntry( rInfo, true );
    2205           6 :     if( mpParentTable && !mbPreFormText )   // no cells allowed in global and preformatted tables
    2206             :     {
    2207             :         // read needed options from the <td> tag
    2208           6 :         ScHTMLSize aSpanSize( 1, 1 );
    2209             :         SAL_WNODEPRECATED_DECLARATIONS_PUSH
    2210           6 :         ::std::auto_ptr<rtl::OUString> pValStr, pNumStr;
    2211             :         SAL_WNODEPRECATED_DECLARATIONS_POP
    2212           6 :         const HTMLOptions& rOptions = static_cast<HTMLParser*>(rInfo.pParser)->GetOptions();
    2213           6 :         HTMLOptions::const_iterator itr = rOptions.begin(), itrEnd = rOptions.end();
    2214           6 :         sal_uInt32 nNumberFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
    2215           6 :         for (; itr != itrEnd; ++itr)
    2216             :         {
    2217           0 :             switch (itr->GetToken())
    2218             :             {
    2219             :                 case HTML_O_COLSPAN:
    2220           0 :                     aSpanSize.mnCols = static_cast<SCCOL>( getLimitedValue<sal_Int32>( itr->GetString().ToInt32(), 1, 256 ) );
    2221           0 :                 break;
    2222             :                 case HTML_O_ROWSPAN:
    2223           0 :                     aSpanSize.mnRows = static_cast<SCROW>( getLimitedValue<sal_Int32>( itr->GetString().ToInt32(), 1, 256 ) );
    2224           0 :                 break;
    2225             :                 case HTML_O_SDVAL:
    2226           0 :                     pValStr.reset(new rtl::OUString(itr->GetString()));
    2227           0 :                 break;
    2228             :                 case HTML_O_SDNUM:
    2229           0 :                     pNumStr.reset(new rtl::OUString(itr->GetString()));
    2230           0 :                 break;
    2231             :                 case HTML_O_CLASS:
    2232             :                 {
    2233             :                     // Pick up the number format associated with this class (if
    2234             :                     // any).
    2235           0 :                     rtl::OUString aElem(RTL_CONSTASCII_USTRINGPARAM("td"));
    2236           0 :                     rtl::OUString aClass = itr->GetString();
    2237           0 :                     rtl::OUString aProp(RTL_CONSTASCII_USTRINGPARAM("mso-number-format"));
    2238           0 :                     const ScHTMLStyles& rStyles = mpParser->GetStyles();
    2239           0 :                     const rtl::OUString& rVal = rStyles.getPropertyValue(aElem, aClass, aProp);
    2240           0 :                     rtl::OUString aNumFmt = decodeNumberFormat(rVal);
    2241             : 
    2242           0 :                     nNumberFormat = GetFormatTable()->GetEntryKey(aNumFmt);
    2243           0 :                     if (nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
    2244             :                     {
    2245           0 :                         sal_Int32 nErrPos  = 0;
    2246             :                         short nDummy;
    2247           0 :                         bool bValidFmt = GetFormatTable()->PutEntry(aNumFmt, nErrPos, nDummy, nNumberFormat);
    2248           0 :                         if (!bValidFmt)
    2249           0 :                             nNumberFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
    2250           0 :                     }
    2251             :                 }
    2252           0 :                 break;
    2253             :             }
    2254             :         }
    2255             : 
    2256           6 :         ImplDataOn( aSpanSize );
    2257             : 
    2258           6 :         if (nNumberFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
    2259           0 :             mxDataItemSet->Put( SfxUInt32Item(ATTR_VALUE_FORMAT, nNumberFormat) );
    2260             : 
    2261           6 :         ProcessFormatOptions( *mxDataItemSet, rInfo );
    2262           6 :         CreateNewEntry( rInfo );
    2263           6 :         mxCurrEntry->pValStr = pValStr.release();
    2264           6 :         mxCurrEntry->pNumStr = pNumStr.release();
    2265             :     }
    2266             :     else
    2267           0 :         CreateNewEntry( rInfo );
    2268           6 : }
    2269             : 
    2270           6 : void ScHTMLTable::DataOff( const ImportInfo& rInfo )
    2271             : {
    2272           6 :     PushEntry( rInfo, true );
    2273           6 :     if( mpParentTable && !mbPreFormText )   // no cells allowed in global and preformatted tables
    2274           6 :         ImplDataOff();
    2275           6 :     CreateNewEntry( rInfo );
    2276           6 : }
    2277             : 
    2278           1 : void ScHTMLTable::BodyOn( const ImportInfo& rInfo )
    2279             : {
    2280           1 :     bool bPushed = PushEntry( rInfo );
    2281           1 :     if( !mpParentTable )
    2282             :     {
    2283             :         // do not start new row, if nothing (no title) precedes the body.
    2284           1 :         if( bPushed || !mbRowOn )
    2285           0 :             ImplRowOn();
    2286           1 :         if( bPushed || !mbDataOn )
    2287           0 :             ImplDataOn( ScHTMLSize( 1, 1 ) );
    2288           1 :         ProcessFormatOptions( *mxDataItemSet, rInfo );
    2289             :     }
    2290           1 :     CreateNewEntry( rInfo );
    2291           1 : }
    2292             : 
    2293           1 : void ScHTMLTable::BodyOff( const ImportInfo& rInfo )
    2294             : {
    2295           1 :     PushEntry( rInfo );
    2296           1 :     if( !mpParentTable )
    2297             :     {
    2298           1 :         ImplDataOff();
    2299           1 :         ImplRowOff();
    2300             :     }
    2301           1 :     CreateNewEntry( rInfo );
    2302           1 : }
    2303             : 
    2304           1 : ScHTMLTable* ScHTMLTable::CloseTable( const ImportInfo& rInfo )
    2305             : {
    2306           1 :     if( mpParentTable )     // not allowed to close global table
    2307             :     {
    2308           1 :         PushEntry( rInfo, mbDataOn );
    2309           1 :         ImplDataOff();
    2310           1 :         ImplRowOff();
    2311           1 :         mpParentTable->PushTableEntry( GetTableId() );
    2312           1 :         mpParentTable->CreateNewEntry( rInfo );
    2313           1 :         if( mbPreFormText ) // enclose preformatted table with empty lines in parent table
    2314           0 :             mpParentTable->InsertLeadingEmptyLine();
    2315           1 :         return mpParentTable;
    2316             :     }
    2317           0 :     return this;
    2318             : }
    2319             : 
    2320           0 : SCCOLROW ScHTMLTable::GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos ) const
    2321             : {
    2322           0 :     const ScSizeVec& rSizes = maCumSizes[ eOrient ];
    2323           0 :     size_t nIndex = static_cast< size_t >( nCellPos );
    2324           0 :     if( nIndex >= rSizes.size() ) return 0;
    2325           0 :     return (nIndex == 0) ? rSizes.front() : (rSizes[ nIndex ] - rSizes[ nIndex - 1 ]);
    2326             : }
    2327             : 
    2328          28 : SCCOLROW ScHTMLTable::GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellBegin, SCCOLROW nCellEnd ) const
    2329             : {
    2330          28 :     const ScSizeVec& rSizes = maCumSizes[ eOrient ];
    2331          28 :     size_t nBeginIdx = static_cast< size_t >( ::std::max< SCCOLROW >( nCellBegin, 0 ) );
    2332          28 :     size_t nEndIdx = static_cast< size_t >( ::std::min< SCCOLROW >( nCellEnd, static_cast< SCCOLROW >( rSizes.size() ) ) );
    2333          28 :     if (nBeginIdx >= nEndIdx ) return 0;
    2334          21 :     return rSizes[ nEndIdx - 1 ] - ((nBeginIdx == 0) ? 0 : rSizes[ nBeginIdx - 1 ]);
    2335             : }
    2336             : 
    2337           9 : SCCOLROW ScHTMLTable::GetDocSize( ScHTMLOrient eOrient ) const
    2338             : {
    2339           9 :     const ScSizeVec& rSizes = maCumSizes[ eOrient ];
    2340           9 :     return rSizes.empty() ? 0 : rSizes.back();
    2341             : }
    2342             : 
    2343           7 : ScHTMLSize ScHTMLTable::GetDocSize( const ScHTMLPos& rCellPos ) const
    2344             : {
    2345           7 :     ScHTMLSize aCellSpan = GetSpan( rCellPos );
    2346             :     return ScHTMLSize(
    2347           7 :         static_cast< SCCOL >( GetDocSize( tdCol, rCellPos.mnCol, rCellPos.mnCol + aCellSpan.mnCols ) ),
    2348          14 :         static_cast< SCROW >( GetDocSize( tdRow, rCellPos.mnRow, rCellPos.mnRow + aCellSpan.mnRows ) ) );
    2349             : }
    2350             : 
    2351          14 : SCCOLROW ScHTMLTable::GetDocPos( ScHTMLOrient eOrient, SCCOLROW nCellPos ) const
    2352             : {
    2353          14 :     return maDocBasePos.Get( eOrient ) + GetDocSize( eOrient, 0, nCellPos );
    2354             : }
    2355             : 
    2356           7 : ScHTMLPos ScHTMLTable::GetDocPos( const ScHTMLPos& rCellPos ) const
    2357             : {
    2358             :     return ScHTMLPos(
    2359           7 :         static_cast< SCCOL >( GetDocPos( tdCol, rCellPos.mnCol ) ),
    2360          14 :         static_cast< SCROW >( GetDocPos( tdRow, rCellPos.mnRow ) ) );
    2361             : }
    2362             : 
    2363           1 : void ScHTMLTable::GetDocRange( ScRange& rRange ) const
    2364             : {
    2365           1 :     rRange.aStart = rRange.aEnd = maDocBasePos.MakeAddr();
    2366           1 :     rRange.aEnd.Move( static_cast< SCsCOL >( GetDocSize( tdCol ) ) - 1, static_cast< SCsROW >( GetDocSize( tdRow ) ) - 1, 0 );
    2367           1 : }
    2368             : 
    2369           2 : void ScHTMLTable::ApplyCellBorders( ScDocument* pDoc, const ScAddress& rFirstPos ) const
    2370             : {
    2371             :     OSL_ENSURE( pDoc, "ScHTMLTable::ApplyCellBorders - no document" );
    2372           2 :     if( pDoc && mbBorderOn )
    2373             :     {
    2374           0 :         const SCCOL nLastCol = maSize.mnCols - 1;
    2375           0 :         const SCROW nLastRow = maSize.mnRows - 1;
    2376           0 :         const long nOuterLine = DEF_LINE_WIDTH_2;
    2377           0 :         const long nInnerLine = DEF_LINE_WIDTH_0;
    2378           0 :         SvxBorderLine aOuterLine(0, nOuterLine, table::BorderLineStyle::SOLID);
    2379           0 :         SvxBorderLine aInnerLine(0, nInnerLine, table::BorderLineStyle::SOLID);
    2380           0 :         SvxBoxItem aBorderItem( ATTR_BORDER );
    2381             : 
    2382           0 :         for( SCCOL nCol = 0; nCol <= nLastCol; ++nCol )
    2383             :         {
    2384           0 :             SvxBorderLine* pLeftLine = (nCol == 0) ? &aOuterLine : &aInnerLine;
    2385           0 :             SvxBorderLine* pRightLine = (nCol == nLastCol) ? &aOuterLine : &aInnerLine;
    2386           0 :             SCCOL nCellCol1 = static_cast< SCCOL >( GetDocPos( tdCol, nCol ) ) + rFirstPos.Col();
    2387           0 :             SCCOL nCellCol2 = nCellCol1 + static_cast< SCCOL >( GetDocSize( tdCol, nCol ) ) - 1;
    2388           0 :             for( SCROW nRow = 0; nRow <= nLastRow; ++nRow )
    2389             :             {
    2390           0 :                 SvxBorderLine* pTopLine = (nRow == 0) ? &aOuterLine : &aInnerLine;
    2391           0 :                 SvxBorderLine* pBottomLine = (nRow == nLastRow) ? &aOuterLine : &aInnerLine;
    2392           0 :                 SCROW nCellRow1 = GetDocPos( tdRow, nRow ) + rFirstPos.Row();
    2393           0 :                 SCROW nCellRow2 = nCellRow1 + GetDocSize( tdRow, nRow ) - 1;
    2394           0 :                 for( SCCOL nCellCol = nCellCol1; nCellCol <= nCellCol2; ++nCellCol )
    2395             :                 {
    2396           0 :                     aBorderItem.SetLine( (nCellCol == nCellCol1) ? pLeftLine : 0, BOX_LINE_LEFT );
    2397           0 :                     aBorderItem.SetLine( (nCellCol == nCellCol2) ? pRightLine : 0, BOX_LINE_RIGHT );
    2398           0 :                     for( SCROW nCellRow = nCellRow1; nCellRow <= nCellRow2; ++nCellRow )
    2399             :                     {
    2400           0 :                         aBorderItem.SetLine( (nCellRow == nCellRow1) ? pTopLine : 0, BOX_LINE_TOP );
    2401           0 :                         aBorderItem.SetLine( (nCellRow == nCellRow2) ? pBottomLine : 0, BOX_LINE_BOTTOM );
    2402           0 :                         pDoc->ApplyAttr( nCellCol, nCellRow, rFirstPos.Tab(), aBorderItem );
    2403             :                     }
    2404             :                 }
    2405             :             }
    2406           0 :         }
    2407             :     }
    2408             : 
    2409           3 :     for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter )
    2410           1 :         aIter->ApplyCellBorders( pDoc, rFirstPos );
    2411           2 : }
    2412             : 
    2413           0 : SvNumberFormatter* ScHTMLTable::GetFormatTable()
    2414             : {
    2415           0 :     return mpParser->GetDoc().GetFormatTable();
    2416             : }
    2417             : 
    2418             : // ----------------------------------------------------------------------------
    2419             : 
    2420          28 : bool ScHTMLTable::IsEmptyCell() const
    2421             : {
    2422          28 :     return mpCurrEntryList && mpCurrEntryList->empty();
    2423             : }
    2424             : 
    2425          13 : bool ScHTMLTable::IsSpaceCharInfo( const ImportInfo& rInfo )
    2426             : {
    2427          13 :     return (rInfo.nToken == HTML_TEXTTOKEN) && (rInfo.aText.Len() == 1) && (rInfo.aText.GetChar( 0 ) == ' ');
    2428             : }
    2429             : 
    2430          27 : ScHTMLTable::ScHTMLEntryPtr ScHTMLTable::CreateEntry() const
    2431             : {
    2432          27 :     return ScHTMLEntryPtr( new ScHTMLEntry( GetCurrItemSet() ) );
    2433             : }
    2434             : 
    2435          26 : void ScHTMLTable::CreateNewEntry( const ImportInfo& rInfo )
    2436             : {
    2437             :     OSL_ENSURE( !mxCurrEntry.get(), "ScHTMLTable::CreateNewEntry - old entry still present" );
    2438          26 :     mxCurrEntry = CreateEntry();
    2439          26 :     mxCurrEntry->aSel = rInfo.aSelection;
    2440          26 : }
    2441             : 
    2442             : SAL_WNODEPRECATED_DECLARATIONS_PUSH
    2443           7 : void ScHTMLTable::ImplPushEntryToList( ScHTMLEntryList& rEntryList, ScHTMLEntryPtr& rxEntry )
    2444             : {
    2445             :     // HTML entry list does not own the entries
    2446           7 :     rEntryList.push_back( rxEntry.get() );
    2447             :     // mrEEParseList (reference to member of ScEEParser) owns the entries
    2448           7 :     mrEEParseList.push_back( rxEntry.release() );
    2449           7 : }
    2450             : SAL_WNODEPRECATED_DECLARATIONS_POP
    2451             : 
    2452             : SAL_WNODEPRECATED_DECLARATIONS_PUSH
    2453          27 : bool ScHTMLTable::PushEntry( ScHTMLEntryPtr& rxEntry )
    2454             : {
    2455          27 :     bool bPushed = false;
    2456          27 :     if( rxEntry.get() && rxEntry->HasContents() )
    2457             :     {
    2458           7 :         if( mpCurrEntryList )
    2459             :         {
    2460           7 :             if( mbPushEmptyLine )
    2461             :             {
    2462           0 :                 ScHTMLEntryPtr xEmptyEntry = CreateEntry();
    2463           0 :                 ImplPushEntryToList( *mpCurrEntryList, xEmptyEntry );
    2464           0 :                 mbPushEmptyLine = false;
    2465             :             }
    2466           7 :             ImplPushEntryToList( *mpCurrEntryList, rxEntry );
    2467           7 :             bPushed = true;
    2468             :         }
    2469           0 :         else if( mpParentTable )
    2470             :         {
    2471           0 :             bPushed = mpParentTable->PushEntry( rxEntry );
    2472             :         }
    2473             :         else
    2474             :         {
    2475             :             OSL_FAIL( "ScHTMLTable::PushEntry - cannot push entry, no parent found" );
    2476             :         }
    2477             :     }
    2478          27 :     return bPushed;
    2479             : }
    2480             : SAL_WNODEPRECATED_DECLARATIONS_POP
    2481             : 
    2482          26 : bool ScHTMLTable::PushEntry( const ImportInfo& rInfo, bool bLastInCell )
    2483             : {
    2484             :     OSL_ENSURE( mxCurrEntry.get(), "ScHTMLTable::PushEntry - no current entry" );
    2485          26 :     bool bPushed = false;
    2486          26 :     if( mxCurrEntry.get() )
    2487             :     {
    2488          26 :         mxCurrEntry->AdjustEnd( rInfo );
    2489          26 :         mxCurrEntry->Strip( mrEditEngine );
    2490             : 
    2491             :         // import entry always, if it is the last in cell, and cell is still empty
    2492          26 :         if( bLastInCell && IsEmptyCell() )
    2493             :         {
    2494           0 :             mxCurrEntry->SetImportAlways();
    2495             :             // don't insert empty lines before single empty entries
    2496           0 :             if( mxCurrEntry->IsEmpty() )
    2497           0 :                 mbPushEmptyLine = false;
    2498             :         }
    2499             : 
    2500          26 :         bPushed = PushEntry( mxCurrEntry );
    2501          26 :         mxCurrEntry.reset();
    2502             :     }
    2503          26 :     return bPushed;
    2504             : }
    2505             : 
    2506           1 : bool ScHTMLTable::PushTableEntry( ScHTMLTableId nTableId )
    2507             : {
    2508             :     OSL_ENSURE( nTableId != SC_HTML_GLOBAL_TABLE, "ScHTMLTable::PushTableEntry - cannot push global table" );
    2509           1 :     bool bPushed = false;
    2510           1 :     if( nTableId != SC_HTML_GLOBAL_TABLE )
    2511             :     {
    2512           1 :         ScHTMLEntryPtr xEntry( new ScHTMLEntry( maTableItemSet, nTableId ) );
    2513           1 :         bPushed = PushEntry( xEntry );
    2514             :     }
    2515           1 :     return bPushed;
    2516             : }
    2517             : 
    2518          14 : ScHTMLTable* ScHTMLTable::GetExistingTable( ScHTMLTableId nTableId ) const
    2519             : {
    2520           2 :     ScHTMLTable* pTable = ((nTableId != SC_HTML_GLOBAL_TABLE) && mxNestedTables.get()) ?
    2521          16 :         mxNestedTables->FindTable( nTableId, false ) : 0;
    2522             :     OSL_ENSURE( pTable || (nTableId == SC_HTML_GLOBAL_TABLE), "ScHTMLTable::GetExistingTable - table not found" );
    2523          14 :     return pTable;
    2524             : }
    2525             : 
    2526           1 : ScHTMLTable* ScHTMLTable::InsertNestedTable( const ImportInfo& rInfo, bool bPreFormText )
    2527             : {
    2528           1 :     if( !mxNestedTables.get() )
    2529           1 :         mxNestedTables.reset( new ScHTMLTableMap( *this ) );
    2530           1 :     if( bPreFormText )      // enclose new preformatted table with empty lines
    2531           0 :         InsertLeadingEmptyLine();
    2532           1 :     return mxNestedTables->CreateTable( rInfo, bPreFormText );
    2533             : }
    2534             : 
    2535           7 : void ScHTMLTable::InsertNewCell( const ScHTMLSize& rSpanSize )
    2536             : {
    2537             :     ScRange* pRange;
    2538             : 
    2539             :     /*  Find an unused cell by skipping all merged ranges that cover the
    2540             :         current cell position stored in maCurrCell. */
    2541          14 :     while( ((pRange = maVMergedCells.Find( maCurrCell.MakeAddr() )) != 0) || ((pRange = maHMergedCells.Find( maCurrCell.MakeAddr() )) != 0) )
    2542           0 :         maCurrCell.mnCol = pRange->aEnd.Col() + 1;
    2543           7 :     mpCurrEntryList = &maEntryMap[ maCurrCell ];
    2544             : 
    2545             :     /*  If the new cell is merged horizontally, try to find collisions with
    2546             :         other vertically merged ranges. In this case, shrink existing
    2547             :         vertically merged ranges (do not shrink the new cell). */
    2548           7 :     SCCOL nColEnd = maCurrCell.mnCol + rSpanSize.mnCols;
    2549          14 :     for( ScAddress aAddr( maCurrCell.MakeAddr() ); aAddr.Col() < nColEnd; aAddr.IncCol() )
    2550           7 :         if( (pRange = maVMergedCells.Find( aAddr )) != 0 )
    2551           0 :             pRange->aEnd.SetRow( maCurrCell.mnRow - 1 );
    2552             : 
    2553             :     // insert the new range into the cell lists
    2554           7 :     ScRange aNewRange( maCurrCell.MakeAddr() );
    2555           7 :     aNewRange.aEnd.Move( rSpanSize.mnCols - 1, rSpanSize.mnRows - 1, 0 );
    2556           7 :     if( rSpanSize.mnRows > 1 )
    2557             :     {
    2558           0 :         maVMergedCells.Append( aNewRange );
    2559             :         /*  Do not insert vertically merged ranges into maUsedCells yet,
    2560             :             because they may be shrunken (see above). The final vertically
    2561             :             merged ranges are inserted in FillEmptyCells(). */
    2562             :     }
    2563             :     else
    2564             :     {
    2565           7 :         if( rSpanSize.mnCols > 1 )
    2566           0 :             maHMergedCells.Append( aNewRange );
    2567             :         /*  Insert horizontally merged ranges and single cells into
    2568             :             maUsedCells, they will not be changed anymore. */
    2569           7 :         maUsedCells.Join( aNewRange );
    2570             :     }
    2571             : 
    2572             :     // adjust table size
    2573           7 :     maSize.mnCols = ::std::max< SCCOL >( maSize.mnCols, aNewRange.aEnd.Col() + 1 );
    2574           7 :     maSize.mnRows = ::std::max< SCROW >( maSize.mnRows, aNewRange.aEnd.Row() + 1 );
    2575           7 : }
    2576             : 
    2577           3 : void ScHTMLTable::ImplRowOn()
    2578             : {
    2579           3 :     if( mbRowOn )
    2580           0 :         ImplRowOff();
    2581           3 :     mxRowItemSet.reset( new SfxItemSet( maTableItemSet ) );
    2582           3 :     maCurrCell.mnCol = 0;
    2583           3 :     mbRowOn = true;
    2584           3 :     mbDataOn = false;
    2585           3 : }
    2586             : 
    2587           4 : void ScHTMLTable::ImplRowOff()
    2588             : {
    2589           4 :     if( mbDataOn )
    2590           0 :         ImplDataOff();
    2591           4 :     if( mbRowOn )
    2592             :     {
    2593           3 :         mxRowItemSet.reset();
    2594           3 :         ++maCurrCell.mnRow;
    2595           3 :         mbRowOn = mbDataOn = false;
    2596             :     }
    2597           4 : }
    2598             : 
    2599           7 : void ScHTMLTable::ImplDataOn( const ScHTMLSize& rSpanSize )
    2600             : {
    2601           7 :     if( mbDataOn )
    2602           0 :         ImplDataOff();
    2603           7 :     if( !mbRowOn )
    2604           0 :         ImplRowOn();
    2605           7 :     mxDataItemSet.reset( new SfxItemSet( *mxRowItemSet ) );
    2606           7 :     InsertNewCell( rSpanSize );
    2607           7 :     mbDataOn = true;
    2608           7 :     mbPushEmptyLine = false;
    2609           7 : }
    2610             : 
    2611           8 : void ScHTMLTable::ImplDataOff()
    2612             : {
    2613           8 :     if( mbDataOn )
    2614             :     {
    2615           7 :         mxDataItemSet.reset();
    2616           7 :         ++maCurrCell.mnCol;
    2617           7 :         mpCurrEntryList = 0;
    2618           7 :         mbDataOn = false;
    2619             :     }
    2620           8 : }
    2621             : 
    2622          10 : void ScHTMLTable::ProcessFormatOptions( SfxItemSet& rItemSet, const ImportInfo& rInfo )
    2623             : {
    2624             :     // special handling for table header cells
    2625          10 :     if( rInfo.nToken == HTML_TABLEHEADER_ON )
    2626             :     {
    2627           0 :         rItemSet.Put( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
    2628           0 :         rItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) );
    2629             :     }
    2630             : 
    2631          10 :     const HTMLOptions& rOptions = static_cast<HTMLParser*>(rInfo.pParser)->GetOptions();
    2632          10 :     HTMLOptions::const_iterator itr = rOptions.begin(), itrEnd = rOptions.end();
    2633          10 :     for (; itr != itrEnd; ++itr)
    2634             :     {
    2635           0 :         switch( itr->GetToken() )
    2636             :         {
    2637             :             case HTML_O_ALIGN:
    2638             :             {
    2639           0 :                 SvxCellHorJustify eVal = SVX_HOR_JUSTIFY_STANDARD;
    2640           0 :                 const String& rOptVal = itr->GetString();
    2641           0 :                 if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) )
    2642           0 :                     eVal = SVX_HOR_JUSTIFY_RIGHT;
    2643           0 :                 else if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_center ) )
    2644           0 :                     eVal = SVX_HOR_JUSTIFY_CENTER;
    2645           0 :                 else if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_left ) )
    2646           0 :                     eVal = SVX_HOR_JUSTIFY_LEFT;
    2647           0 :                 if( eVal != SVX_HOR_JUSTIFY_STANDARD )
    2648           0 :                     rItemSet.Put( SvxHorJustifyItem( eVal, ATTR_HOR_JUSTIFY ) );
    2649             :             }
    2650           0 :             break;
    2651             : 
    2652             :             case HTML_O_VALIGN:
    2653             :             {
    2654           0 :                 SvxCellVerJustify eVal = SVX_VER_JUSTIFY_STANDARD;
    2655           0 :                 const String& rOptVal = itr->GetString();
    2656           0 :                 if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_VA_top ) )
    2657           0 :                     eVal = SVX_VER_JUSTIFY_TOP;
    2658           0 :                 else if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_VA_middle ) )
    2659           0 :                     eVal = SVX_VER_JUSTIFY_CENTER;
    2660           0 :                 else if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_VA_bottom ) )
    2661           0 :                     eVal = SVX_VER_JUSTIFY_BOTTOM;
    2662           0 :                 if( eVal != SVX_VER_JUSTIFY_STANDARD )
    2663           0 :                     rItemSet.Put( SvxVerJustifyItem( eVal, ATTR_VER_JUSTIFY ) );
    2664             :             }
    2665           0 :             break;
    2666             : 
    2667             :             case HTML_O_BGCOLOR:
    2668             :             {
    2669           0 :                 Color aColor;
    2670           0 :                 itr->GetColor( aColor );
    2671           0 :                 rItemSet.Put( SvxBrushItem( aColor, ATTR_BACKGROUND ) );
    2672             :             }
    2673           0 :             break;
    2674             :         }
    2675             :     }
    2676          10 : }
    2677             : 
    2678          14 : void ScHTMLTable::SetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos, SCCOLROW nSize )
    2679             : {
    2680             :     OSL_ENSURE( nCellPos >= 0, "ScHTMLTable::SetDocSize - unexpected negative position" );
    2681          14 :     ScSizeVec& rSizes = maCumSizes[ eOrient ];
    2682          14 :     size_t nIndex = static_cast< size_t >( nCellPos );
    2683             :     // expand with height/width == 1
    2684          35 :     while( nIndex >= rSizes.size() )
    2685           7 :         rSizes.push_back( rSizes.empty() ? 1 : (rSizes.back() + 1) );
    2686             :     // update size of passed position and all following
    2687             :     // #i109987# only grow, don't shrink - use the largest needed size
    2688          14 :     SCsCOLROW nDiff = nSize - ((nIndex == 0) ? rSizes.front() : (rSizes[ nIndex ] - rSizes[ nIndex - 1 ]));
    2689          14 :     if( nDiff > 0 )
    2690           4 :         for( ScSizeVec::iterator aIt = rSizes.begin() + nIndex, aEnd = rSizes.end(); aIt != aEnd; ++aIt )
    2691           2 :             *aIt += nDiff;
    2692          14 : }
    2693             : 
    2694          14 : void ScHTMLTable::CalcNeededDocSize(
    2695             :         ScHTMLOrient eOrient, SCCOLROW nCellPos, SCCOLROW nCellSpan, SCCOLROW nRealDocSize )
    2696             : {
    2697          14 :     SCCOLROW nDiffSize = 0;
    2698             :     // in merged columns/rows: reduce needed size by size of leading columns
    2699          28 :     while( nCellSpan > 1 )
    2700             :     {
    2701           0 :         nDiffSize += GetDocSize( eOrient, nCellPos );
    2702           0 :         --nCellSpan;
    2703           0 :         ++nCellPos;
    2704             :     }
    2705             :     // set remaining needed size to last column/row
    2706          14 :     nRealDocSize -= ::std::min< SCCOLROW >( nRealDocSize - 1, nDiffSize );
    2707          14 :     SetDocSize( eOrient, nCellPos, nRealDocSize );
    2708          14 : }
    2709             : 
    2710             : // ----------------------------------------------------------------------------
    2711             : 
    2712           2 : void ScHTMLTable::FillEmptyCells()
    2713             : {
    2714           3 :     for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter )
    2715           1 :         aIter->FillEmptyCells();
    2716             : 
    2717             :     // insert the final vertically merged ranges into maUsedCells
    2718           2 :     for ( size_t i = 0, nRanges = maVMergedCells.size(); i < nRanges; ++i )
    2719             :     {
    2720           0 :         ScRange* pRange = maVMergedCells[ i ];
    2721           0 :         maUsedCells.Join( *pRange );
    2722             :     }
    2723             : 
    2724           5 :     for( ScAddress aAddr; aAddr.Row() < maSize.mnRows; aAddr.IncRow() )
    2725             :     {
    2726          10 :         for( aAddr.SetCol( 0 ); aAddr.Col() < maSize.mnCols; aAddr.IncCol() )
    2727             :         {
    2728           7 :             if( !maUsedCells.Find( aAddr ) )
    2729             :             {
    2730             :                 // create a range for the lock list (used to calc. cell span)
    2731           0 :                 ScRange aRange( aAddr );
    2732           0 :                 do
    2733             :                 {
    2734           0 :                     aRange.aEnd.IncCol();
    2735             :                 }
    2736           0 :                 while( (aRange.aEnd.Col() < maSize.mnCols) && !maUsedCells.Find( aRange.aEnd ) );
    2737           0 :                 aRange.aEnd.IncCol( -1 );
    2738           0 :                 maUsedCells.Join( aRange );
    2739             : 
    2740             :                 // insert a dummy entry
    2741           0 :                 ScHTMLEntryPtr xEntry = CreateEntry();
    2742           0 :                 ImplPushEntryToList( maEntryMap[ ScHTMLPos( aAddr ) ], xEntry );
    2743             :             }
    2744             :         }
    2745             :     }
    2746           2 : }
    2747             : 
    2748           2 : void ScHTMLTable::RecalcDocSize()
    2749             : {
    2750             :     // recalc table sizes recursively from inner to outer
    2751           3 :     for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter )
    2752           1 :         aIter->RecalcDocSize();
    2753             : 
    2754             :     /*  Two passes: first calculates the sizes of single columns/rows, then
    2755             :         the sizes of spanned columns/rows. This allows to fill nested tables
    2756             :         into merged cells optimally. */
    2757             :     static const sal_uInt16 PASS_SINGLE = 0;
    2758             :     static const sal_uInt16 PASS_SPANNED = 1;
    2759           6 :     for( sal_uInt16 nPass = PASS_SINGLE; nPass <= PASS_SPANNED; ++nPass )
    2760             :     {
    2761             :         // iterate through every table cell
    2762           4 :         ScHTMLEntryMap::const_iterator aMapIterEnd = maEntryMap.end();
    2763          18 :         for( ScHTMLEntryMap::const_iterator aMapIter = maEntryMap.begin(); aMapIter != aMapIterEnd; ++aMapIter )
    2764             :         {
    2765          14 :             const ScHTMLPos& rCellPos = aMapIter->first;
    2766          14 :             ScHTMLSize aCellSpan = GetSpan( rCellPos );
    2767             : 
    2768          14 :             const ScHTMLEntryList& rEntryList = aMapIter->second;
    2769          14 :             ScHTMLEntryList::const_iterator aListIter;
    2770          14 :             ScHTMLEntryList::const_iterator aListIterEnd = rEntryList.end();
    2771             : 
    2772             :             // process the dimension of the current cell in this pass?
    2773             :             // (pass is single and span is 1) or (pass is not single and span is not 1)
    2774          14 :             bool bProcessColWidth = ((nPass == PASS_SINGLE) == (aCellSpan.mnCols == 1));
    2775          14 :             bool bProcessRowHeight = ((nPass == PASS_SINGLE) == (aCellSpan.mnRows == 1));
    2776          14 :             if( bProcessColWidth || bProcessRowHeight )
    2777             :             {
    2778           7 :                 ScHTMLSize aDocSize( 1, 0 );    // resulting size of the cell in document
    2779             : 
    2780             :                 // expand the cell size for each cell parse entry
    2781          14 :                 for( aListIter = rEntryList.begin(); aListIter != aListIterEnd; ++aListIter )
    2782             :                 {
    2783           7 :                     ScHTMLTable* pTable = GetExistingTable( (*aListIter)->GetTableId() );
    2784             :                     // find entry with maximum width
    2785           7 :                     if( bProcessColWidth && pTable )
    2786           1 :                         aDocSize.mnCols = ::std::max( aDocSize.mnCols, static_cast< SCCOL >( pTable->GetDocSize( tdCol ) ) );
    2787             :                     // add up height of each entry
    2788           7 :                     if( bProcessRowHeight )
    2789           7 :                         aDocSize.mnRows += pTable ? pTable->GetDocSize( tdRow ) : 1;
    2790             :                 }
    2791           7 :                 if( !aDocSize.mnRows )
    2792           0 :                     aDocSize.mnRows = 1;
    2793             : 
    2794           7 :                 if( bProcessColWidth )
    2795           7 :                     CalcNeededDocSize( tdCol, rCellPos.mnCol, aCellSpan.mnCols, aDocSize.mnCols );
    2796           7 :                 if( bProcessRowHeight )
    2797           7 :                     CalcNeededDocSize( tdRow, rCellPos.mnRow, aCellSpan.mnRows, aDocSize.mnRows );
    2798             :             }
    2799             :         }
    2800             :     }
    2801           2 : }
    2802             : 
    2803           2 : void ScHTMLTable::RecalcDocPos( const ScHTMLPos& rBasePos )
    2804             : {
    2805           2 :     maDocBasePos = rBasePos;
    2806             :     // after the previous assignment it is allowed to call GetDocPos() methods
    2807             : 
    2808             :     // iterate through every table cell
    2809           2 :     ScHTMLEntryMap::iterator aMapIterEnd = maEntryMap.end();
    2810           9 :     for( ScHTMLEntryMap::iterator aMapIter = maEntryMap.begin(); aMapIter != aMapIterEnd; ++aMapIter )
    2811             :     {
    2812             :         // fixed doc position of the entire cell (first entry)
    2813           7 :         const ScHTMLPos aCellDocPos( GetDocPos( aMapIter->first ) );
    2814             :         // fixed doc size of the entire cell
    2815           7 :         const ScHTMLSize aCellDocSize( GetDocSize( aMapIter->first ) );
    2816             : 
    2817             :         // running doc position for single entries
    2818           7 :         ScHTMLPos aEntryDocPos( aCellDocPos );
    2819             : 
    2820           7 :         ScHTMLEntryList& rEntryList = aMapIter->second;
    2821           7 :         ScHTMLEntry* pEntry = 0;
    2822           7 :         ScHTMLEntryList::iterator aListIterEnd = rEntryList.end();
    2823          14 :         for( ScHTMLEntryList::iterator aListIter = rEntryList.begin(); aListIter != aListIterEnd; ++aListIter )
    2824             :         {
    2825           7 :             pEntry = *aListIter;
    2826           7 :             if( ScHTMLTable* pTable = GetExistingTable( pEntry->GetTableId() ) )
    2827             :             {
    2828           1 :                 pTable->RecalcDocPos( aEntryDocPos );   // recalc nested table
    2829           1 :                 pEntry->nCol = SCCOL_MAX;
    2830           1 :                 pEntry->nRow = SCROW_MAX;
    2831           1 :                 SCROW nTableRows = static_cast< SCROW >( pTable->GetDocSize( tdRow ) );
    2832             : 
    2833             :                 // use this entry to pad empty space right of table
    2834           1 :                 if( mpParentTable )     // ... but not in global table
    2835             :                 {
    2836           0 :                     SCCOL nStartCol = aEntryDocPos.mnCol + static_cast< SCCOL >( pTable->GetDocSize( tdCol ) );
    2837           0 :                     SCCOL nNextCol = aEntryDocPos.mnCol + aCellDocSize.mnCols;
    2838           0 :                     if( nStartCol < nNextCol )
    2839             :                     {
    2840           0 :                         pEntry->nCol = nStartCol;
    2841           0 :                         pEntry->nRow = aEntryDocPos.mnRow;
    2842           0 :                         pEntry->nColOverlap = nNextCol - nStartCol;
    2843           0 :                         pEntry->nRowOverlap = nTableRows;
    2844             :                     }
    2845             :                 }
    2846           1 :                 aEntryDocPos.mnRow += nTableRows;
    2847             :             }
    2848             :             else
    2849             :             {
    2850           6 :                 pEntry->nCol = aEntryDocPos.mnCol;
    2851           6 :                 pEntry->nRow = aEntryDocPos.mnRow;
    2852           6 :                 if( mpParentTable )    // do not merge in global table
    2853           6 :                     pEntry->nColOverlap = aCellDocSize.mnCols;
    2854           6 :                 ++aEntryDocPos.mnRow;
    2855             :             }
    2856             :         }
    2857             : 
    2858             :         // pEntry points now to last entry.
    2859           7 :         if( pEntry )
    2860             :         {
    2861           7 :             if( (pEntry == rEntryList.front()) && (pEntry->GetTableId() == SC_HTML_NO_TABLE) )
    2862             :             {
    2863             :                 // pEntry is the only entry in this cell - merge rows of cell with single non-table entry.
    2864           6 :                 pEntry->nRowOverlap = aCellDocSize.mnRows;
    2865             :             }
    2866             :             else
    2867             :             {
    2868             :                 // fill up incomplete entry lists
    2869           1 :                 SCROW nFirstUnusedRow = aCellDocPos.mnRow + aCellDocSize.mnRows;
    2870           2 :                 while( aEntryDocPos.mnRow < nFirstUnusedRow )
    2871             :                 {
    2872           0 :                     ScHTMLEntryPtr xDummyEntry( new ScHTMLEntry( pEntry->GetItemSet() ) );
    2873           0 :                     xDummyEntry->nCol = aEntryDocPos.mnCol;
    2874           0 :                     xDummyEntry->nRow = aEntryDocPos.mnRow;
    2875           0 :                     xDummyEntry->nColOverlap = aCellDocSize.mnCols;
    2876           0 :                     ImplPushEntryToList( rEntryList, xDummyEntry );
    2877           0 :                     ++aEntryDocPos.mnRow;
    2878           0 :                 }
    2879             :             }
    2880             :         }
    2881             :     }
    2882           2 : }
    2883             : 
    2884             : // ============================================================================
    2885             : 
    2886           1 : ScHTMLGlobalTable::ScHTMLGlobalTable(
    2887             :     SfxItemPool& rPool,
    2888             :     EditEngine& rEditEngine,
    2889             :     ::std::vector< ScEEParseEntry* >& rEEParseList,
    2890             :     ScHTMLTableId& rnUnusedId,
    2891             :     ScHTMLParser* pParser
    2892             : ) :
    2893           1 :     ScHTMLTable( rPool, rEditEngine, rEEParseList, rnUnusedId, pParser )
    2894             : {
    2895           1 : }
    2896             : 
    2897           2 : ScHTMLGlobalTable::~ScHTMLGlobalTable()
    2898             : {
    2899           2 : }
    2900             : 
    2901           1 : void ScHTMLGlobalTable::Recalc()
    2902             : {
    2903             :     // Fills up empty cells with a dummy entry. */
    2904           1 :     FillEmptyCells();
    2905             :     // recalc table sizes of all nested tables and this table
    2906           1 :     RecalcDocSize();
    2907             :     // recalc document positions of all entries in this table and in nested tables
    2908           1 :     RecalcDocPos( GetDocPos() );
    2909           1 : }
    2910             : 
    2911             : // ============================================================================
    2912             : 
    2913           1 : ScHTMLQueryParser::ScHTMLQueryParser( EditEngine* pEditEngine, ScDocument* pDoc ) :
    2914             :     ScHTMLParser( pEditEngine, pDoc ),
    2915             :     mnUnusedId( SC_HTML_GLOBAL_TABLE ),
    2916           1 :     mbTitleOn( false )
    2917             : {
    2918             :     mxGlobTable.reset(
    2919           1 :         new ScHTMLGlobalTable(*pPool, *pEdit, maList, mnUnusedId, this));
    2920           1 :     mpCurrTable = mxGlobTable.get();
    2921           1 : }
    2922             : 
    2923           2 : ScHTMLQueryParser::~ScHTMLQueryParser()
    2924             : {
    2925           2 : }
    2926             : 
    2927           1 : sal_uLong ScHTMLQueryParser::Read( SvStream& rStrm, const String& rBaseURL  )
    2928             : {
    2929           1 :     SvKeyValueIteratorRef xValues;
    2930           1 :     SvKeyValueIterator* pAttributes = 0;
    2931             : 
    2932           1 :     SfxObjectShell* pObjSh = mpDoc->GetDocumentShell();
    2933           1 :     if( pObjSh && pObjSh->IsLoading() )
    2934             :     {
    2935           1 :         pAttributes = pObjSh->GetHeaderAttributes();
    2936             :     }
    2937             :     else
    2938             :     {
    2939             :         /*  When not loading, set up fake HTTP headers to force the SfxHTMLParser
    2940             :             to use UTF8 (used when pasting from clipboard) */
    2941           0 :         const sal_Char* pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 );
    2942           0 :         if( pCharSet )
    2943             :         {
    2944           0 :             String aContentType = rtl::OUString( "text/html; charset=" );
    2945           0 :             aContentType.AppendAscii( pCharSet );
    2946             : 
    2947           0 :             xValues = new SvKeyValueIterator;
    2948           0 :             xValues->Append( SvKeyValue( rtl::OUString( OOO_STRING_SVTOOLS_HTML_META_content_type ), aContentType ) );
    2949           0 :             pAttributes = xValues;
    2950             :         }
    2951             :     }
    2952             : 
    2953           1 :     Link aOldLink = pEdit->GetImportHdl();
    2954           1 :     pEdit->SetImportHdl( LINK( this, ScHTMLQueryParser, HTMLImportHdl ) );
    2955           1 :     sal_uLong nErr = pEdit->Read( rStrm, rBaseURL, EE_FORMAT_HTML, pAttributes );
    2956           1 :     pEdit->SetImportHdl( aOldLink );
    2957             : 
    2958           1 :     mxGlobTable->Recalc();
    2959           1 :     nColMax = static_cast< SCCOL >( mxGlobTable->GetDocSize( tdCol ) - 1 );
    2960           1 :     nRowMax = static_cast< SCROW >( mxGlobTable->GetDocSize( tdRow ) - 1 );
    2961             : 
    2962           1 :     return nErr;
    2963             : }
    2964             : 
    2965           1 : const ScHTMLTable* ScHTMLQueryParser::GetGlobalTable() const
    2966             : {
    2967           1 :     return mxGlobTable.get();
    2968             : }
    2969             : 
    2970          34 : void ScHTMLQueryParser::ProcessToken( const ImportInfo& rInfo )
    2971             : {
    2972          34 :     switch( rInfo.nToken )
    2973             :     {
    2974             : // --- meta data ---
    2975           0 :         case HTML_META:             MetaOn( rInfo );                break;  // <meta>
    2976             : 
    2977             : // --- title handling ---
    2978           0 :         case HTML_TITLE_ON:         TitleOn( rInfo );               break;  // <title>
    2979           0 :         case HTML_TITLE_OFF:        TitleOff( rInfo );              break;  // </title>
    2980             : 
    2981           0 :         case HTML_STYLE_ON:                                         break;
    2982           0 :         case HTML_STYLE_OFF:        ParseStyle(rInfo.aText);        break;
    2983             : 
    2984             : // --- body handling ---
    2985           1 :         case HTML_BODY_ON:          mpCurrTable->BodyOn( rInfo );   break;  // <body>
    2986           1 :         case HTML_BODY_OFF:         mpCurrTable->BodyOff( rInfo );  break;  // </body>
    2987             : 
    2988             : // --- insert text ---
    2989          13 :         case HTML_TEXTTOKEN:        InsertText( rInfo );            break;  // any text
    2990           0 :         case HTML_LINEBREAK:        mpCurrTable->BreakOn();         break;  // <br>
    2991             :         case HTML_HEAD1_ON:                                                 // <h1>
    2992             :         case HTML_HEAD2_ON:                                                 // <h2>
    2993             :         case HTML_HEAD3_ON:                                                 // <h3>
    2994             :         case HTML_HEAD4_ON:                                                 // <h4>
    2995             :         case HTML_HEAD5_ON:                                                 // <h5>
    2996             :         case HTML_HEAD6_ON:                                                 // <h6>
    2997           0 :         case HTML_PARABREAK_ON:     mpCurrTable->HeadingOn();       break;  // <p>
    2998             : 
    2999             : // --- misc. contents ---
    3000           0 :         case HTML_ANCHOR_ON:        mpCurrTable->AnchorOn();        break;  // <a>
    3001             : 
    3002             : // --- table handling ---
    3003           1 :         case HTML_TABLE_ON:         TableOn( rInfo );               break;  // <table>
    3004           1 :         case HTML_TABLE_OFF:        TableOff( rInfo );              break;  // </table>
    3005           2 :         case HTML_TABLEROW_ON:      mpCurrTable->RowOn( rInfo );    break;  // <tr>
    3006           2 :         case HTML_TABLEROW_OFF:     mpCurrTable->RowOff( rInfo );   break;  // </tr>
    3007             :         case HTML_TABLEHEADER_ON:                                           // <th>
    3008           6 :         case HTML_TABLEDATA_ON:     mpCurrTable->DataOn( rInfo );   break;  // <td>
    3009             :         case HTML_TABLEHEADER_OFF:                                          // </th>
    3010           6 :         case HTML_TABLEDATA_OFF:    mpCurrTable->DataOff( rInfo );  break;  // </td>
    3011           0 :         case HTML_PREFORMTXT_ON:    PreOn( rInfo );                 break;  // <pre>
    3012           0 :         case HTML_PREFORMTXT_OFF:   PreOff( rInfo );                break;  // </pre>
    3013             : 
    3014             : // --- formatting ---
    3015           0 :         case HTML_FONT_ON:          FontOn( rInfo );                break;  // <font>
    3016             : 
    3017             :         case HTML_BIGPRINT_ON:      // <big>
    3018             :             //! TODO: store current font size, use following size
    3019           0 :             mpCurrTable->PutItem( SvxFontHeightItem( maFontHeights[ 3 ], 100, ATTR_FONT_HEIGHT ) );
    3020           0 :         break;
    3021             :         case HTML_SMALLPRINT_ON:    // <small>
    3022             :             //! TODO: store current font size, use preceding size
    3023           0 :             mpCurrTable->PutItem( SvxFontHeightItem( maFontHeights[ 0 ], 100, ATTR_FONT_HEIGHT ) );
    3024           0 :         break;
    3025             : 
    3026             :         case HTML_BOLD_ON:          // <b>
    3027             :         case HTML_STRONG_ON:        // <strong>
    3028           0 :             mpCurrTable->PutItem( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
    3029           0 :         break;
    3030             : 
    3031             :         case HTML_ITALIC_ON:        // <i>
    3032             :         case HTML_EMPHASIS_ON:      // <em>
    3033             :         case HTML_ADDRESS_ON:       // <address>
    3034             :         case HTML_BLOCKQUOTE_ON:    // <blockquote>
    3035             :         case HTML_BLOCKQUOTE30_ON:  // <bq>
    3036             :         case HTML_CITIATION_ON:     // <cite>
    3037             :         case HTML_VARIABLE_ON:      // <var>
    3038           0 :             mpCurrTable->PutItem( SvxPostureItem( ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
    3039           0 :         break;
    3040             : 
    3041             :         case HTML_DEFINSTANCE_ON:   // <dfn>
    3042           0 :             mpCurrTable->PutItem( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
    3043           0 :             mpCurrTable->PutItem( SvxPostureItem( ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
    3044           0 :         break;
    3045             : 
    3046             :         case HTML_UNDERLINE_ON:     // <u>
    3047           0 :             mpCurrTable->PutItem( SvxUnderlineItem( UNDERLINE_SINGLE, ATTR_FONT_UNDERLINE ) );
    3048           0 :         break;
    3049             :     }
    3050          34 : }
    3051             : 
    3052          13 : void ScHTMLQueryParser::InsertText( const ImportInfo& rInfo )
    3053             : {
    3054          13 :     mpCurrTable->PutText( rInfo );
    3055          13 :     if( mbTitleOn )
    3056           0 :         maTitle.append(rInfo.aText);
    3057          13 : }
    3058             : 
    3059           0 : void ScHTMLQueryParser::FontOn( const ImportInfo& rInfo )
    3060             : {
    3061           0 :     const HTMLOptions& rOptions = static_cast<HTMLParser*>(rInfo.pParser)->GetOptions();
    3062           0 :     HTMLOptions::const_iterator itr = rOptions.begin(), itrEnd = rOptions.end();
    3063           0 :     for (; itr != itrEnd; ++itr)
    3064             :     {
    3065           0 :         switch( itr->GetToken() )
    3066             :         {
    3067             :             case HTML_O_FACE :
    3068             :             {
    3069           0 :                 const String& rFace = itr->GetString();
    3070           0 :                 String aFontName;
    3071           0 :                 xub_StrLen nPos = 0;
    3072           0 :                 while( nPos != STRING_NOTFOUND )
    3073             :                 {
    3074             :                     // font list separator: VCL = ';' HTML = ','
    3075           0 :                     String aFName = comphelper::string::strip(rFace.GetToken(0, ',', nPos), ' ');
    3076           0 :                     aFontName = ScGlobal::addToken(aFontName, aFName, ';');
    3077           0 :                 }
    3078           0 :                 if ( aFontName.Len() )
    3079             :                     mpCurrTable->PutItem( SvxFontItem( FAMILY_DONTKNOW,
    3080           0 :                         aFontName, EMPTY_STRING, PITCH_DONTKNOW,
    3081           0 :                         RTL_TEXTENCODING_DONTKNOW, ATTR_FONT ) );
    3082             :             }
    3083           0 :             break;
    3084             :             case HTML_O_SIZE :
    3085             :             {
    3086           0 :                 sal_uInt32 nSize = getLimitedValue< sal_uInt32 >( itr->GetNumber(), 1, SC_HTML_FONTSIZES );
    3087           0 :                 mpCurrTable->PutItem( SvxFontHeightItem( maFontHeights[ nSize - 1 ], 100, ATTR_FONT_HEIGHT ) );
    3088             :             }
    3089           0 :             break;
    3090             :             case HTML_O_COLOR :
    3091             :             {
    3092           0 :                 Color aColor;
    3093           0 :                 itr->GetColor( aColor );
    3094           0 :                 mpCurrTable->PutItem( SvxColorItem( aColor, ATTR_FONT_COLOR ) );
    3095             :             }
    3096           0 :             break;
    3097             :         }
    3098             :     }
    3099           0 : }
    3100             : 
    3101           0 : void ScHTMLQueryParser::MetaOn( const ImportInfo& rInfo )
    3102             : {
    3103           0 :     if( mpDoc->GetDocumentShell() )
    3104             :     {
    3105           0 :         HTMLParser* pParser = static_cast< HTMLParser* >( rInfo.pParser );
    3106             : 
    3107             :         uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
    3108           0 :             mpDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW);
    3109             :         pParser->ParseMetaOptions(
    3110           0 :             xDPS->getDocumentProperties(),
    3111           0 :             mpDoc->GetDocumentShell()->GetHeaderAttributes() );
    3112             :     }
    3113           0 : }
    3114             : 
    3115           0 : void ScHTMLQueryParser::TitleOn( const ImportInfo& /*rInfo*/ )
    3116             : {
    3117           0 :     mbTitleOn = true;
    3118           0 :     maTitle.makeStringAndClear();
    3119           0 : }
    3120             : 
    3121           0 : void ScHTMLQueryParser::TitleOff( const ImportInfo& rInfo )
    3122             : {
    3123           0 :     if( mbTitleOn )
    3124             :     {
    3125           0 :         rtl::OUString aTitle = maTitle.makeStringAndClear().trim();
    3126           0 :         if (!aTitle.isEmpty() && mpDoc->GetDocumentShell())
    3127             :         {
    3128             :             uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
    3129           0 :                 mpDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW);
    3130             : 
    3131           0 :             xDPS->getDocumentProperties()->setTitle(aTitle);
    3132             :         }
    3133           0 :         InsertText( rInfo );
    3134           0 :         mbTitleOn = false;
    3135             :     }
    3136           0 : }
    3137             : 
    3138           1 : void ScHTMLQueryParser::TableOn( const ImportInfo& rInfo )
    3139             : {
    3140           1 :     mpCurrTable = mpCurrTable->TableOn( rInfo );
    3141           1 : }
    3142             : 
    3143           1 : void ScHTMLQueryParser::TableOff( const ImportInfo& rInfo )
    3144             : {
    3145           1 :     mpCurrTable = mpCurrTable->TableOff( rInfo );
    3146           1 : }
    3147             : 
    3148           0 : void ScHTMLQueryParser::PreOn( const ImportInfo& rInfo )
    3149             : {
    3150           0 :     mpCurrTable = mpCurrTable->PreOn( rInfo );
    3151           0 : }
    3152             : 
    3153           0 : void ScHTMLQueryParser::PreOff( const ImportInfo& rInfo )
    3154             : {
    3155           0 :     mpCurrTable = mpCurrTable->PreOff( rInfo );
    3156           0 : }
    3157             : 
    3158           0 : void ScHTMLQueryParser::CloseTable( const ImportInfo& rInfo )
    3159             : {
    3160           0 :     mpCurrTable = mpCurrTable->CloseTable( rInfo );
    3161           0 : }
    3162             : 
    3163             : namespace {
    3164             : 
    3165             : /**
    3166             :  * Handler class for the CSS parser.
    3167             :  */
    3168           0 : class CSSHandler
    3169             : {
    3170             :     struct MemStr
    3171             :     {
    3172             :         const char* mp;
    3173             :         size_t      mn;
    3174             : 
    3175           0 :         MemStr() : mp(NULL), mn(0) {}
    3176           0 :         MemStr(const char* p, size_t n) : mp(p), mn(n) {}
    3177           0 :         MemStr(const MemStr& r) : mp(r.mp), mn(r.mn) {}
    3178           0 :         MemStr& operator=(const MemStr& r)
    3179             :         {
    3180           0 :             mp = r.mp;
    3181           0 :             mn = r.mn;
    3182           0 :             return *this;
    3183             :         }
    3184             :     };
    3185             : 
    3186             :     typedef std::pair<MemStr, MemStr> SelectorName; // element : class
    3187             :     typedef std::vector<SelectorName> SelectorNames;
    3188             :     SelectorNames maSelectorNames; /// current selector names.
    3189             :     MemStr maPropName;  /// current property name.
    3190             :     MemStr maPropValue; /// current property value.
    3191             : 
    3192             :     ScHTMLStyles& mrStyles;
    3193             : public:
    3194           0 :     CSSHandler(ScHTMLStyles& rStyles) : mrStyles(rStyles) {}
    3195             : 
    3196           0 :     void at_rule_name(const char* /*p*/, size_t /*n*/)
    3197             :     {
    3198             :         // For now, we ignore at-rule properties.
    3199           0 :     }
    3200             : 
    3201           0 :     void selector_name(const char* p_elem, size_t n_elem, const char* p_class, size_t n_class)
    3202             :     {
    3203           0 :         MemStr aElem(p_elem, n_elem), aClass(p_class, n_class);
    3204           0 :         SelectorName aName(aElem, aClass);
    3205           0 :         maSelectorNames.push_back(aName);
    3206           0 :     }
    3207             : 
    3208           0 :     void property_name(const char* p, size_t n)
    3209             :     {
    3210           0 :         maPropName = MemStr(p, n);
    3211           0 :     }
    3212             : 
    3213           0 :     void value(const char* p, size_t n)
    3214             :     {
    3215           0 :         maPropValue = MemStr(p, n);
    3216           0 :     }
    3217             : 
    3218           0 :     void begin_parse() {}
    3219             : 
    3220           0 :     void end_parse() {}
    3221             : 
    3222           0 :     void begin_block() {}
    3223             : 
    3224           0 :     void end_block()
    3225             :     {
    3226           0 :         maSelectorNames.clear();
    3227           0 :     }
    3228             : 
    3229           0 :     void begin_property() {}
    3230             : 
    3231           0 :     void end_property()
    3232             :     {
    3233           0 :         SelectorNames::const_iterator itr = maSelectorNames.begin(), itrEnd = maSelectorNames.end();
    3234           0 :         for (; itr != itrEnd; ++itr)
    3235             :         {
    3236             :             // Add this property to the collection for each selector.
    3237           0 :             const SelectorName& rSelName = *itr;
    3238           0 :             const MemStr& rElem = rSelName.first;
    3239           0 :             const MemStr& rClass = rSelName.second;
    3240           0 :             rtl::OUString aName(maPropName.mp, maPropName.mn, RTL_TEXTENCODING_UTF8);
    3241           0 :             rtl::OUString aValue(maPropValue.mp, maPropValue.mn, RTL_TEXTENCODING_UTF8);
    3242           0 :             mrStyles.add(rElem.mp, rElem.mn, rClass.mp, rClass.mn, aName, aValue);
    3243           0 :         }
    3244           0 :         maPropName = MemStr();
    3245           0 :         maPropValue = MemStr();
    3246           0 :     }
    3247             : };
    3248             : 
    3249             : }
    3250             : 
    3251           0 : void ScHTMLQueryParser::ParseStyle(const rtl::OUString& rStrm)
    3252             : {
    3253           0 :     rtl::OString aStr = rtl::OUStringToOString(rStrm, RTL_TEXTENCODING_UTF8);
    3254           0 :     CSSHandler aHdl(GetStyles());
    3255           0 :     orcus::css_parser<CSSHandler> aParser(aStr.getStr(), aStr.getLength(), aHdl);
    3256             :     try
    3257             :     {
    3258           0 :         aParser.parse();
    3259             :     }
    3260           0 :     catch (const orcus::css_parse_error&)
    3261             :     {
    3262             :         // Parsing of CSS failed.  Do nothing for now.
    3263           0 :     }
    3264           0 : }
    3265             : 
    3266             : // ----------------------------------------------------------------------------
    3267             : 
    3268         110 : IMPL_LINK( ScHTMLQueryParser, HTMLImportHdl, const ImportInfo*, pInfo )
    3269             : {
    3270          55 :     switch( pInfo->eState )
    3271             :     {
    3272             :         case HTMLIMP_START:
    3273           1 :         break;
    3274             : 
    3275             :         case HTMLIMP_NEXTTOKEN:
    3276             :         case HTMLIMP_UNKNOWNATTR:
    3277          34 :             ProcessToken( *pInfo );
    3278          34 :         break;
    3279             : 
    3280             :         case HTMLIMP_INSERTPARA:
    3281           6 :             mpCurrTable->InsertPara( *pInfo );
    3282           6 :         break;
    3283             : 
    3284             :         case HTMLIMP_SETATTR:
    3285             :         case HTMLIMP_INSERTTEXT:
    3286             :         case HTMLIMP_INSERTFIELD:
    3287          13 :         break;
    3288             : 
    3289             :         case HTMLIMP_END:
    3290           2 :             while( mpCurrTable->GetTableId() != SC_HTML_GLOBAL_TABLE )
    3291           0 :                 CloseTable( *pInfo );
    3292           1 :         break;
    3293             : 
    3294             :         default:
    3295             :             OSL_FAIL( "ScHTMLQueryParser::HTMLImportHdl - unknown ImportInfo::eState" );
    3296             :     }
    3297          55 :     return 0;
    3298             : }
    3299             : 
    3300             : // ============================================================================
    3301             : 
    3302             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10