LCOV - code coverage report
Current view: top level - libreoffice/sc/source/filter/xml - xmlcelli.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 455 545 83.5 %
Date: 2012-12-27 Functions: 28 29 96.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "xmlcelli.hxx"
      21             : #include "xmlimprt.hxx"
      22             : #include "xmltabi.hxx"
      23             : #include "xmlstyli.hxx"
      24             : #include "xmlannoi.hxx"
      25             : #include "global.hxx"
      26             : #include "document.hxx"
      27             : #include "cellsuno.hxx"
      28             : #include "docuno.hxx"
      29             : #include "unonames.hxx"
      30             : #include "postit.hxx"
      31             : #include "sheetdata.hxx"
      32             : #include "docsh.hxx"
      33             : #include "cellform.hxx"
      34             : #include "validat.hxx"
      35             : #include "patattr.hxx"
      36             : #include "scitems.hxx"
      37             : #include "docpool.hxx"
      38             : 
      39             : #include "XMLTableShapeImportHelper.hxx"
      40             : #include "XMLTextPContext.hxx"
      41             : #include "XMLStylesImportHelper.hxx"
      42             : 
      43             : #include "arealink.hxx"
      44             : #include <sfx2/linkmgr.hxx>
      45             : #include "convuno.hxx"
      46             : #include "XMLConverter.hxx"
      47             : #include "scerrors.hxx"
      48             : #include "editutil.hxx"
      49             : #include "cell.hxx"
      50             : 
      51             : 
      52             : #include <xmloff/xmltkmap.hxx>
      53             : #include <xmloff/xmltoken.hxx>
      54             : #include <xmloff/nmspmap.hxx>
      55             : #include <xmloff/xmluconv.hxx>
      56             : #include <xmloff/families.hxx>
      57             : #include <xmloff/numehelp.hxx>
      58             : #include <xmloff/xmlnmspe.hxx>
      59             : #include <svl/zforlist.hxx>
      60             : #include <svx/svdocapt.hxx>
      61             : #include <editeng/outlobj.hxx>
      62             : #include <editeng/editobj.hxx>
      63             : #include <svx/unoapi.hxx>
      64             : #include <svl/languageoptions.hxx>
      65             : #include <sax/tools/converter.hxx>
      66             : 
      67             : #include <com/sun/star/frame/XModel.hpp>
      68             : #include <com/sun/star/text/XText.hpp>
      69             : #include <com/sun/star/sheet/XSpreadsheets.hpp>
      70             : #include <com/sun/star/sheet/XSpreadsheet.hpp>
      71             : #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
      72             : 
      73             : #include <com/sun/star/sheet/XSheetCondition.hpp>
      74             : #include <com/sun/star/table/XCellRange.hpp>
      75             : #include <com/sun/star/table/CellAddress.hpp>
      76             : #include <com/sun/star/util/NumberFormat.hpp>
      77             : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
      78             : #include <com/sun/star/util/XNumberFormatTypes.hpp>
      79             : #include <com/sun/star/util/Date.hpp>
      80             : #include <com/sun/star/lang/Locale.hpp>
      81             : #include <com/sun/star/text/ControlCharacter.hpp>
      82             : 
      83             : #include <com/sun/star/sheet/ValidationType.hpp>
      84             : #include <com/sun/star/sheet/ValidationAlertStyle.hpp>
      85             : #include <com/sun/star/sheet/ConditionOperator.hpp>
      86             : 
      87             : #include <rtl/ustrbuf.hxx>
      88             : #include <tools/date.hxx>
      89             : #include <i18npool/lang.h>
      90             : #include <comphelper/extract.hxx>
      91             : #include <tools/string.hxx>
      92             : 
      93             : using namespace com::sun::star;
      94             : using namespace xmloff::token;
      95             : 
      96             : using rtl::OUString;
      97             : 
      98             : //------------------------------------------------------------------
      99             : 
     100        3232 : ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
     101             :                                       sal_uInt16 nPrfx,
     102             :                                       const ::rtl::OUString& rLName,
     103             :                                       const ::com::sun::star::uno::Reference<
     104             :                                       ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
     105             :                                       const bool bTempIsCovered,
     106             :                                       const sal_Int32 nTempRepeatedRows ) :
     107             :     SvXMLImportContext( rImport, nPrfx, rLName ),
     108             :     pContentValidationName(NULL),
     109             :     pDetectiveObjVec(NULL),
     110             :     pCellRangeSource(NULL),
     111             :     fValue(0.0),
     112             :     nMergedRows(1),
     113             :     nRepeatedRows(nTempRepeatedRows),
     114             :     nMergedCols(1),
     115             :     nColsRepeated(1),
     116             :     rXMLImport((ScXMLImport&)rImport),
     117             :     eGrammar( formula::FormulaGrammar::GRAM_STORAGE_DEFAULT),
     118             :     nCellType(util::NumberFormat::TEXT),
     119             :     bIsMerged(false),
     120             :     bIsMatrix(false),
     121             :     bIsCovered(bTempIsCovered),
     122             :     bIsEmpty(true),
     123             :     bHasTextImport(false),
     124             :     bIsFirstTextImport(false),
     125             :     bSolarMutexLocked(false),
     126        3232 :     bFormulaTextResult(false)
     127             : {
     128        3232 :     rtl::math::setNan(&fValue); // NaN by default
     129             : 
     130        3232 :     rXMLImport.SetRemoveLastChar(false);
     131        3232 :     rXMLImport.GetTables().AddColumn(bTempIsCovered);
     132        3232 :     const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
     133        3232 :     rtl::OUString aLocalName;
     134        3232 :     rtl::OUString* pStyleName = NULL;
     135        3232 :     rtl::OUString* pCurrencySymbol = NULL;
     136        3232 :     const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
     137        7461 :     for (sal_Int16 i = 0; i < nAttrCount; ++i)
     138             :     {
     139        4229 :         sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
     140        8458 :             xAttrList->getNameByIndex(i), &aLocalName);
     141             : 
     142        4229 :         const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
     143        4229 :         sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
     144        4229 :         switch (nToken)
     145             :         {
     146             :             case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
     147         128 :                 pStyleName = new rtl::OUString(sValue);
     148         128 :             break;
     149             :             case XML_TOK_TABLE_ROW_CELL_ATTR_CONTENT_VALIDATION_NAME:
     150             :                 OSL_ENSURE(!pContentValidationName, "here should be only one Validation Name");
     151          14 :                 pContentValidationName = new rtl::OUString(sValue);
     152          14 :             break;
     153             :             case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_ROWS:
     154           5 :                 bIsMerged = true;
     155           5 :                 nMergedRows = static_cast<SCROW>(sValue.toInt32());
     156           5 :             break;
     157             :             case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_COLS:
     158           5 :                 bIsMerged = true;
     159           5 :                 nMergedCols = static_cast<SCCOL>(sValue.toInt32());
     160           5 :             break;
     161             :             case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_COLS:
     162          25 :                 bIsMatrix = true;
     163          25 :                 nMatrixCols = static_cast<SCCOL>(sValue.toInt32());
     164          25 :             break;
     165             :             case XML_TOK_TABLE_ROW_CELL_ATTR_SPANNED_MATRIX_ROWS:
     166          25 :                 bIsMatrix = true;
     167          25 :                 nMatrixRows = static_cast<SCROW>(sValue.toInt32());
     168          25 :             break;
     169             :             case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
     170         303 :                 nColsRepeated = static_cast<SCCOL>(std::max( sValue.toInt32(), static_cast<sal_Int32>(1) ));
     171         303 :             break;
     172             :             case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
     173        1805 :                 nCellType = GetScImport().GetCellType(sValue);
     174        1805 :                 bIsEmpty = false;
     175        1805 :             break;
     176             :             case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
     177             :             {
     178        1387 :                 if (!sValue.isEmpty())
     179             :                 {
     180        1387 :                     ::sax::Converter::convertDouble(fValue, sValue);
     181        1387 :                     bIsEmpty = false;
     182             : 
     183             :                     //if office:value="0", let's get the text:p in case this is
     184             :                     //a special case in HasSpecialCaseFormulaText(). If it
     185             :                     //turns out not to be a special case, we'll use the 0 value.
     186        1387 :                     if(fValue == 0.0)
     187          47 :                         bFormulaTextResult = true;
     188             :                 }
     189             :             }
     190        1387 :             break;
     191             :             case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
     192             :             {
     193           2 :                 if (!sValue.isEmpty() && rXMLImport.SetNullDateOnUnitConverter())
     194             :                 {
     195           2 :                     rXMLImport.GetMM100UnitConverter().convertDateTime(fValue, sValue);
     196           2 :                     bIsEmpty = false;
     197             :                 }
     198             :             }
     199           2 :             break;
     200             :             case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
     201             :             {
     202           1 :                 if (!sValue.isEmpty())
     203             :                 {
     204           1 :                     ::sax::Converter::convertDuration(fValue, sValue);
     205           1 :                     bIsEmpty = false;
     206             :                 }
     207             :             }
     208           1 :             break;
     209             :             case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
     210             :             {
     211          28 :                 if (!sValue.isEmpty())
     212             :                 {
     213             :                     OSL_ENSURE(!pOUTextValue, "here should be only one string value");
     214          28 :                     pOUTextValue.reset(sValue);
     215          28 :                     bIsEmpty = false;
     216             :                 }
     217             :             }
     218          28 :             break;
     219             :             case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
     220             :             {
     221         140 :                 if (!sValue.isEmpty())
     222             :                 {
     223         140 :                     if ( IsXMLToken(sValue, XML_TRUE) )
     224          65 :                         fValue = 1.0;
     225          75 :                     else if ( IsXMLToken(sValue, XML_FALSE) )
     226          75 :                         fValue = 0.0;
     227             :                     else
     228           0 :                         ::sax::Converter::convertDouble(fValue, sValue);
     229         140 :                     bIsEmpty = false;
     230             :                 }
     231             :             }
     232         140 :             break;
     233             :             case XML_TOK_TABLE_ROW_CELL_ATTR_FORMULA:
     234             :             {
     235         359 :                 if (!sValue.isEmpty())
     236             :                 {
     237             :                     OSL_ENSURE(!pOUFormula, "here should be only one formula");
     238         359 :                     rtl::OUString aFormula, aFormulaNmsp;
     239         359 :                     rXMLImport.ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eGrammar, sValue );
     240         359 :                     pOUFormula.reset( FormulaWithNamespace( aFormula, aFormulaNmsp ) );
     241             :                 }
     242             :             }
     243         359 :             break;
     244             :             case XML_TOK_TABLE_ROW_CELL_ATTR_CURRENCY:
     245           2 :                 pCurrencySymbol = new rtl::OUString(sValue);
     246           2 :             break;
     247             :             default:
     248             :                 ;
     249             :         }
     250        4229 :     }
     251        3232 :     if (pOUFormula)
     252             :     {
     253         359 :         if (nCellType == util::NumberFormat::TEXT)
     254          28 :             bFormulaTextResult = true;
     255         359 :         if(nCellType == util::NumberFormat::DATETIME)
     256           2 :             nCellType = util::NumberFormat::UNDEFINED;
     257             :         //if bIsEmpty is true at this point, then there is no office value.
     258             :         //we must get the text:p (even if it is empty) in case this a special
     259             :         //case in HasSpecialCaseFormulaText().
     260         359 :         if(bIsEmpty)
     261           0 :             bFormulaTextResult = true;
     262             :     }
     263        3232 :     rXMLImport.GetStylesImportHelper()->SetAttributes(pStyleName, pCurrencySymbol, nCellType);
     264        3232 : }
     265             : 
     266        9696 : ScXMLTableRowCellContext::~ScXMLTableRowCellContext()
     267             : {
     268        3232 :     delete pContentValidationName;
     269        3232 :     delete pDetectiveObjVec;
     270        3232 :     delete pCellRangeSource;
     271        6464 : }
     272             : 
     273           1 : void ScXMLTableRowCellContext::LockSolarMutex()
     274             : {
     275           1 :     if (!bSolarMutexLocked)
     276             :     {
     277           1 :         GetScImport().LockSolarMutex();
     278           1 :         bSolarMutexLocked = true;
     279             :     }
     280           1 : }
     281             : 
     282        3232 : void ScXMLTableRowCellContext::UnlockSolarMutex()
     283             : {
     284        3232 :     if (bSolarMutexLocked)
     285             :     {
     286           1 :         GetScImport().UnlockSolarMutex();
     287           1 :         bSolarMutexLocked = false;
     288             :     }
     289        3232 : }
     290             : 
     291             : namespace {
     292             : 
     293        9762 : bool cellExists( const ScAddress& rCellPos )
     294             : {
     295       19524 :     return( rCellPos.Col() >= 0 && rCellPos.Row() >= 0 &&
     296       19524 :             rCellPos.Col() <= MAXCOL && rCellPos.Row() <= MAXROW );
     297             : }
     298             : 
     299             : }
     300             : 
     301           2 : void ScXMLTableRowCellContext::SetCursorOnTextImport(const rtl::OUString& rOUTempText)
     302             : {
     303           2 :     ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
     304           2 :     if (cellExists(aCellPos))
     305             :     {
     306           2 :         sal_Int32 nCol = static_cast<sal_Int32>( aCellPos.Col() );
     307           2 :         sal_Int32 nRow = static_cast<sal_Int32>( aCellPos.Row() );
     308           2 :         uno::Reference<table::XCellRange> xCellRange(rXMLImport.GetTables().GetCurrentXCellRange());
     309           2 :         if (xCellRange.is())
     310             :         {
     311           2 :             xBaseCell.set( xCellRange->getCellByPosition(nCol, nRow) );
     312           2 :             if (xBaseCell.is())
     313             :             {
     314           2 :                 xLockable.set(xBaseCell, uno::UNO_QUERY);
     315           2 :                 if (xLockable.is())
     316           2 :                     xLockable->addActionLock();
     317           2 :                 uno::Reference<text::XText> xText(xBaseCell, uno::UNO_QUERY);
     318           2 :                 if (xText.is())
     319             :                 {
     320           2 :                     uno::Reference<text::XTextCursor> xTextCursor(xText->createTextCursor());
     321           2 :                     if (xTextCursor.is())
     322             :                     {
     323           2 :                         xTextCursor->setString(rOUTempText);
     324           2 :                         xTextCursor->gotoEnd(false);
     325           2 :                         rXMLImport.GetTextImport()->SetCursor(xTextCursor);
     326           2 :                     }
     327           2 :                 }
     328             :             }
     329           2 :         }
     330             :     }
     331             :     else
     332             :     {
     333             :         OSL_FAIL("this method should only be called for a existing cell");
     334             :     }
     335           2 : }
     336             : 
     337        1809 : SvXMLImportContext *ScXMLTableRowCellContext::CreateChildContext( sal_uInt16 nPrefix,
     338             :                                             const ::rtl::OUString& rLName,
     339             :                                             const ::com::sun::star::uno::Reference<
     340             :                                           ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
     341             : {
     342        1809 :     SvXMLImportContext *pContext = 0;
     343             : 
     344        1809 :     const SvXMLTokenMap& rTokenMap = rXMLImport.GetTableRowCellElemTokenMap();
     345        1809 :     bool bTextP(false);
     346        1809 :     switch( rTokenMap.Get( nPrefix, rLName ) )
     347             :     {
     348             :         case XML_TOK_TABLE_ROW_CELL_P:
     349             :         {
     350        1806 :             bIsEmpty = false;
     351        1806 :             bTextP = true;
     352             : 
     353        1806 :             ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
     354             : 
     355        1806 :             if( ((nCellType == util::NumberFormat::TEXT) || bFormulaTextResult) )
     356             :             {
     357         323 :                 if (!bHasTextImport)
     358             :                 {
     359         322 :                     bIsFirstTextImport = true;
     360         322 :                     bHasTextImport = true;
     361         322 :                     pContext = new ScXMLTextPContext(rXMLImport, nPrefix, rLName, xAttrList, this);
     362             :                 }
     363             :                 else
     364             :                 {
     365           1 :                     if (cellExists(aCellPos))
     366             :                     {
     367           1 :                         if (bIsFirstTextImport && !rXMLImport.GetRemoveLastChar())
     368             :                         {
     369           1 :                             if (pOUTextContent)
     370             :                             {
     371           1 :                                 SetCursorOnTextImport(*pOUTextContent);
     372           1 :                                 pOUTextContent.reset();
     373             :                             }
     374             :                             else
     375           0 :                                 SetCursorOnTextImport(rtl::OUString());
     376           1 :                             rXMLImport.SetRemoveLastChar(true);
     377           1 :                             uno::Reference < text::XTextCursor > xTextCursor(rXMLImport.GetTextImport()->GetCursor());
     378           1 :                             if (xTextCursor.is())
     379             :                             {
     380           1 :                                 uno::Reference < text::XText > xText (xTextCursor->getText());
     381           1 :                                 uno::Reference < text::XTextRange > xTextRange (xTextCursor, uno::UNO_QUERY);
     382           1 :                                 if (xText.is() && xTextRange.is())
     383           1 :                                     xText->insertControlCharacter(xTextRange, text::ControlCharacter::PARAGRAPH_BREAK, false);
     384           1 :                             }
     385             :                         }
     386             :                         pContext = rXMLImport.GetTextImport()->CreateTextChildContext(
     387           1 :                             rXMLImport, nPrefix, rLName, xAttrList);
     388           1 :                         bIsFirstTextImport = false;
     389             :                     }
     390             :                 }
     391             :             }
     392             :         }
     393        1806 :         break;
     394             :         case XML_TOK_TABLE_ROW_CELL_TABLE:
     395             :         {
     396             :             SAL_WARN("sc", "ScXMLTableRowCellContext::CreateChildContext: subtables are not supported");
     397             :         }
     398           0 :         break;
     399             :         case XML_TOK_TABLE_ROW_CELL_ANNOTATION:
     400             :         {
     401           1 :             bIsEmpty = false;
     402             :             OSL_ENSURE( !mxAnnotationData.get(), "ScXMLTableRowCellContext::CreateChildContext - multiple annotations in one cell" );
     403           1 :             mxAnnotationData.reset( new ScXMLAnnotationData );
     404             :             pContext = new ScXMLAnnotationContext( rXMLImport, nPrefix, rLName,
     405           1 :                                                     xAttrList, *mxAnnotationData, this);
     406             :         }
     407           1 :         break;
     408             :         case XML_TOK_TABLE_ROW_CELL_DETECTIVE:
     409             :         {
     410           0 :             bIsEmpty = false;
     411           0 :             if (!pDetectiveObjVec)
     412           0 :                 pDetectiveObjVec = new ScMyImpDetectiveObjVec();
     413             :             pContext = new ScXMLDetectiveContext(
     414           0 :                 rXMLImport, nPrefix, rLName, pDetectiveObjVec );
     415             :         }
     416           0 :         break;
     417             :         case XML_TOK_TABLE_ROW_CELL_CELL_RANGE_SOURCE:
     418             :         {
     419           0 :             bIsEmpty = false;
     420           0 :             if (!pCellRangeSource)
     421           0 :                 pCellRangeSource = new ScMyImpCellRangeSource();
     422             :             pContext = new ScXMLCellRangeSourceContext(
     423           0 :                 rXMLImport, nPrefix, rLName, xAttrList, pCellRangeSource );
     424             :         }
     425           0 :         break;
     426             :     }
     427             : 
     428        1809 :     if (!pContext && !bTextP)
     429             :     {
     430           2 :         ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
     431           2 :         uno::Reference<drawing::XShapes> xShapes (rXMLImport.GetTables().GetCurrentXShapes());
     432           2 :         if (xShapes.is())
     433             :         {
     434           2 :             if (aCellPos.Col() > MAXCOL)
     435           0 :                 aCellPos.SetCol(MAXCOL);
     436           2 :             if (aCellPos.Row() > MAXROW)
     437           0 :                 aCellPos.SetRow(MAXROW);
     438             :             XMLTableShapeImportHelper* pTableShapeImport =
     439           2 :                     static_cast< XMLTableShapeImportHelper* >( rXMLImport.GetShapeImport().get() );
     440           2 :             pTableShapeImport->SetOnTable(false);
     441           2 :             com::sun::star::table::CellAddress aCellAddress;
     442           2 :             ScUnoConversion::FillApiAddress( aCellAddress, aCellPos );
     443           2 :             pTableShapeImport->SetCell(aCellAddress);
     444             :             pContext = rXMLImport.GetShapeImport()->CreateGroupChildContext(
     445           2 :                 rXMLImport, nPrefix, rLName, xAttrList, xShapes);
     446           2 :             if (pContext)
     447             :             {
     448           2 :                 bIsEmpty = false;
     449           2 :                 rXMLImport.ProgressBarIncrement(false);
     450             :             }
     451           2 :         }
     452             :     }
     453             : 
     454        1809 :     if( !pContext )
     455        1483 :         pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
     456             : 
     457        1809 :     return pContext;
     458             : }
     459             : 
     460           5 : void ScXMLTableRowCellContext::DoMerge( const ScAddress& rScAddress, const SCCOL nCols, const SCROW nRows )
     461             : {
     462           5 :     SCCOL mergeToCol = rScAddress.Col() + nCols;
     463           5 :     SCROW mergeToRow = rScAddress.Row() + nRows;
     464          10 :     bool bInBounds = rScAddress.Col() <= MAXCOL && rScAddress.Row() <= MAXROW &&
     465          10 :                        mergeToCol <= MAXCOL && mergeToRow <= MAXROW;
     466           5 :     if( bInBounds )
     467             :     {
     468           5 :         rXMLImport.GetDocument()->DoMerge( rScAddress.Tab(),
     469          10 :             rScAddress.Col(), rScAddress.Row(), mergeToCol, mergeToRow );
     470             :     }
     471           5 : }
     472             : 
     473             : namespace {
     474             : 
     475          14 : ScValidationMode validationTypeToMode( const sheet::ValidationType eVType )
     476             : {
     477             :     ScValidationMode eMode;
     478          14 :     switch( eVType )
     479             :     {
     480          10 :         case sheet::ValidationType_WHOLE:               eMode = SC_VALID_WHOLE;     break;
     481           4 :         case sheet::ValidationType_DECIMAL:             eMode = SC_VALID_DECIMAL;   break;
     482           0 :         case sheet::ValidationType_DATE:                eMode = SC_VALID_DATE;      break;
     483           0 :         case sheet::ValidationType_TIME:                eMode = SC_VALID_TIME;      break;
     484           0 :         case sheet::ValidationType_TEXT_LEN:            eMode = SC_VALID_TEXTLEN;   break;
     485           0 :         case sheet::ValidationType_LIST:                eMode = SC_VALID_LIST;      break;
     486           0 :         case sheet::ValidationType_CUSTOM:              eMode = SC_VALID_CUSTOM;    break;
     487           0 :         default:                                        eMode = SC_VALID_ANY;       break;
     488             :     }
     489          14 :     return eMode;
     490             : }
     491             : 
     492          14 : ScValidErrorStyle validAlertToValidError( const sheet::ValidationAlertStyle eVAlertStyle )
     493             : {
     494             :     ScValidErrorStyle eVErrStyle;
     495          14 :     switch( eVAlertStyle )
     496             :     {
     497          10 :         case sheet::ValidationAlertStyle_STOP:          eVErrStyle = SC_VALERR_STOP;      break;
     498           4 :         case sheet::ValidationAlertStyle_WARNING:       eVErrStyle = SC_VALERR_WARNING;   break;
     499           0 :         case sheet::ValidationAlertStyle_MACRO:         eVErrStyle = SC_VALERR_MACRO;     break;
     500           0 :         default:                                        eVErrStyle = SC_VALERR_INFO;      break;
     501             :         //should INFO be the default?  seems to be the most unobtrusive choice.
     502             :     }
     503          14 :     return eVErrStyle;
     504             : }
     505             : 
     506             : }
     507             : 
     508        3232 : void ScXMLTableRowCellContext::SetContentValidation( const ScRange& rScRange )
     509             : {
     510        3232 :     if( pContentValidationName && !pContentValidationName->isEmpty() )
     511             :     {
     512          14 :         ScDocument* pDoc = rXMLImport.GetDocument();
     513          14 :         ScMyImportValidation aValidation;
     514          14 :         aValidation.eGrammar1 = aValidation.eGrammar2 = pDoc->GetStorageGrammar();
     515          14 :         if( rXMLImport.GetValidation(*pContentValidationName, aValidation) )
     516             :         {
     517             :             ScValidationData aScValidationData(
     518             :                 validationTypeToMode(aValidation.aValidationType),
     519             :                 ScConditionEntry::GetModeFromApi(static_cast<sal_Int32>(aValidation.aOperator)),
     520             :                 aValidation.sFormula1, aValidation.sFormula2, pDoc, ScAddress(),
     521             :                 aValidation.sFormulaNmsp1, aValidation.sFormulaNmsp2,
     522             :                 aValidation.eGrammar1, aValidation.eGrammar2
     523          14 :             );
     524             : 
     525          14 :             aScValidationData.SetIgnoreBlank( aValidation.bIgnoreBlanks );
     526          14 :             aScValidationData.SetListType( aValidation.nShowList );
     527             : 
     528             :             // set strings for error / input even if disabled (and disable afterwards)
     529          14 :             aScValidationData.SetInput( aValidation.sImputTitle, aValidation.sImputMessage );
     530          14 :             if( !aValidation.bShowImputMessage )
     531          14 :                 aScValidationData.ResetInput();
     532          14 :             aScValidationData.SetError( aValidation.sErrorTitle, aValidation.sErrorMessage, validAlertToValidError(aValidation.aAlertStyle) );
     533          14 :             if( !aValidation.bShowErrorMessage )
     534           0 :                 aScValidationData.ResetError();
     535             : 
     536          14 :             if( !aValidation.sBaseCellAddress.isEmpty() )
     537          14 :                 aScValidationData.SetSrcString( aValidation.sBaseCellAddress );
     538             : 
     539          14 :             sal_uLong nIndex = pDoc->AddValidationEntry( aScValidationData );
     540             : 
     541          14 :             ScPatternAttr aPattern( pDoc->GetPool() );
     542          14 :             aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nIndex ) );
     543          14 :             if( rScRange.aStart == rScRange.aEnd )  //for a single cell
     544             :             {
     545           9 :                 pDoc->ApplyPattern( rScRange.aStart.Col(), rScRange.aStart.Row(),
     546          18 :                                     rScRange.aStart.Tab(), aPattern );
     547             :             }
     548             :             else  //for repeating cells
     549             :             {
     550           5 :                 pDoc->ApplyPatternAreaTab( rScRange.aStart.Col(), rScRange.aStart.Row(),
     551           5 :                                        rScRange.aEnd.Col(), rScRange.aEnd.Row(),
     552          15 :                                        rScRange.aStart.Tab(), aPattern );
     553             :             }
     554             : 
     555             :             // is the below still needed?
     556             :             // For now, any sheet with validity is blocked from stream-copying.
     557             :             // Later, the validation names could be stored along with the style names.
     558          14 :             ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetImport().GetModel())->GetSheetSaveData();
     559          14 :             pSheetData->BlockSheet( GetScImport().GetTables().GetCurrentSheet() );
     560          14 :         }
     561             :     }
     562        3232 : }
     563             : 
     564        2923 : void ScXMLTableRowCellContext::SetContentValidation( const ScAddress& rCellPos )
     565             : {
     566        2923 :     SetContentValidation( ScRange(rCellPos, rCellPos) );
     567        2923 : }
     568             : 
     569        1837 : void ScXMLTableRowCellContext::SetAnnotation(const ScAddress& rPos)
     570             : {
     571        1837 :     ScDocument* pDoc = rXMLImport.GetDocument();
     572        1837 :     if( !pDoc || !mxAnnotationData.get() )
     573        1837 :         return;
     574             : 
     575           1 :     LockSolarMutex();
     576             : 
     577           1 :     ScPostIt* pNote = 0;
     578             : 
     579           1 :     uno::Reference< drawing::XShapes > xShapes = rXMLImport.GetTables().GetCurrentXShapes();
     580           1 :     uno::Reference< container::XIndexAccess > xShapesIA( xShapes, uno::UNO_QUERY );
     581           1 :     sal_Int32 nOldShapeCount = xShapesIA.is() ? xShapesIA->getCount() : 0;
     582             : 
     583             :     OSL_ENSURE( !mxAnnotationData->mxShape.is() || mxAnnotationData->mxShapes.is(),
     584             :         "ScXMLTableRowCellContext::SetAnnotation - shape without drawing page" );
     585           1 :     if( mxAnnotationData->mxShape.is() && mxAnnotationData->mxShapes.is() )
     586             :     {
     587             :         OSL_ENSURE( mxAnnotationData->mxShapes.get() == xShapes.get(), "ScXMLTableRowCellContext::SetAnnotation - diffenet drawing pages" );
     588           1 :         SdrObject* pObject = ::GetSdrObjectFromXShape( mxAnnotationData->mxShape );
     589             :         OSL_ENSURE( pObject, "ScXMLTableRowCellContext::SetAnnotation - cannot get SdrObject from shape" );
     590             : 
     591             :         /*  Try to reuse the drawing object already created (but only if the
     592             :             note is visible, and the object is a caption object). */
     593           1 :         if( mxAnnotationData->mbShown && mxAnnotationData->mbUseShapePos )
     594             :         {
     595           0 :             if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) )
     596             :             {
     597             :                 OSL_ENSURE( !pCaption->GetLogicRect().IsEmpty(), "ScXMLTableRowCellContext::SetAnnotation - invalid caption rectangle" );
     598             :                 // create the cell note with the caption object
     599           0 :                 pNote = ScNoteUtil::CreateNoteFromCaption( *pDoc, rPos, *pCaption, true );
     600             :                 // forget pointer to object (do not create note again below)
     601           0 :                 pObject = 0;
     602             :             }
     603             :         }
     604             : 
     605             :         // drawing object has not been used to create a note -> use shape data
     606           1 :         if( pObject )
     607             :         {
     608             :             // rescue settings from drawing object before the shape is removed
     609           1 :             ::std::auto_ptr< SfxItemSet > xItemSet( new SfxItemSet( pObject->GetMergedItemSet() ) );
     610           1 :             ::std::auto_ptr< OutlinerParaObject > xOutlinerObj;
     611           1 :             if( OutlinerParaObject* pOutlinerObj = pObject->GetOutlinerParaObject() )
     612           1 :                 xOutlinerObj.reset( new OutlinerParaObject( *pOutlinerObj ) );
     613           1 :             Rectangle aCaptionRect;
     614           1 :             if( mxAnnotationData->mbUseShapePos )
     615           1 :                 aCaptionRect = pObject->GetLogicRect();
     616             :             // remove the shape from the drawing page, this invalidates pObject
     617           1 :             mxAnnotationData->mxShapes->remove( mxAnnotationData->mxShape );
     618           1 :             pObject = 0;
     619             :             // update current number of existing objects
     620           1 :             if( xShapesIA.is() )
     621           1 :                 nOldShapeCount = xShapesIA->getCount();
     622             : 
     623             :             // an outliner object is required (empty note captions not allowed)
     624           1 :             if( xOutlinerObj.get() )
     625             :             {
     626             :                 // create cell note with all data from drawing object
     627             :                 pNote = ScNoteUtil::CreateNoteFromObjectData( *pDoc, rPos,
     628             :                     xItemSet.release(), xOutlinerObj.release(),
     629           1 :                     aCaptionRect, mxAnnotationData->mbShown, false );
     630           1 :             }
     631             :         }
     632             :     }
     633           0 :     else if( !mxAnnotationData->maSimpleText.isEmpty() )
     634             :     {
     635             :         // create note from simple text
     636             :         pNote = ScNoteUtil::CreateNoteFromString( *pDoc, rPos,
     637           0 :             mxAnnotationData->maSimpleText, mxAnnotationData->mbShown, false );
     638             :     }
     639             : 
     640             :     // set author and date
     641           1 :     if( pNote )
     642             :     {
     643             :         double fDate;
     644           1 :         rXMLImport.GetMM100UnitConverter().convertDateTime( fDate, mxAnnotationData->maCreateDate );
     645           1 :         SvNumberFormatter* pNumForm = pDoc->GetFormatTable();
     646           1 :         sal_uInt32 nfIndex = pNumForm->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM );
     647           1 :         String aDate;
     648           1 :         Color* pColor = 0;
     649           1 :         Color** ppColor = &pColor;
     650           1 :         pNumForm->GetOutputString( fDate, nfIndex, aDate, ppColor );
     651           1 :         pNote->SetDate( aDate );
     652           1 :         pNote->SetAuthor( mxAnnotationData->maAuthor );
     653             :     }
     654             : 
     655             :     // register a shape that has been newly created in the ScNoteUtil functions
     656           1 :     if( xShapesIA.is() && (nOldShapeCount < xShapesIA->getCount()) )
     657             :     {
     658           0 :         uno::Reference< drawing::XShape > xShape;
     659           0 :         rXMLImport.GetShapeImport()->shapeWithZIndexAdded( xShape, xShapesIA->getCount() );
     660             :     }
     661             : 
     662             :     // store the style names for stream copying
     663           1 :     ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rXMLImport.GetModel())->GetSheetSaveData();
     664           1 :     pSheetData->HandleNoteStyles( mxAnnotationData->maStyleName, mxAnnotationData->maTextStyle, rPos );
     665             : 
     666           1 :     std::vector<ScXMLAnnotationStyleEntry>::const_iterator aIter = mxAnnotationData->maContentStyles.begin();
     667           1 :     std::vector<ScXMLAnnotationStyleEntry>::const_iterator aEnd = mxAnnotationData->maContentStyles.end();
     668           3 :     while (aIter != aEnd)
     669             :     {
     670           1 :         pSheetData->AddNoteContentStyle( aIter->mnFamily, aIter->maName, rPos, aIter->maSelection );
     671           1 :         ++aIter;
     672           1 :     }
     673             : }
     674             : 
     675             : // core implementation
     676        1837 : void ScXMLTableRowCellContext::SetDetectiveObj( const ScAddress& rPosition )
     677             : {
     678        1837 :     if( cellExists(rPosition) && pDetectiveObjVec && pDetectiveObjVec->size() )
     679             :     {
     680           0 :         LockSolarMutex();
     681           0 :         ScDetectiveFunc aDetFunc( rXMLImport.GetDocument(), rPosition.Tab() );
     682           0 :         uno::Reference<container::XIndexAccess> xShapesIndex (rXMLImport.GetTables().GetCurrentXShapes(), uno::UNO_QUERY); // make draw page
     683           0 :         ScMyImpDetectiveObjVec::iterator aItr(pDetectiveObjVec->begin());
     684           0 :         ScMyImpDetectiveObjVec::iterator aEndItr(pDetectiveObjVec->end());
     685           0 :         while(aItr != aEndItr)
     686             :         {
     687           0 :             aDetFunc.InsertObject( aItr->eObjType, rPosition, aItr->aSourceRange, aItr->bHasError );
     688           0 :             if (xShapesIndex.is())
     689             :             {
     690           0 :                 sal_Int32 nShapes = xShapesIndex->getCount();
     691           0 :                 uno::Reference < drawing::XShape > xShape;
     692           0 :                 rXMLImport.GetShapeImport()->shapeWithZIndexAdded(xShape, nShapes);
     693             :             }
     694           0 :             ++aItr;
     695           0 :         }
     696             :     }
     697        1837 : }
     698             : 
     699             : // core implementation
     700        1837 : void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
     701             : {
     702        1837 :     if( cellExists(rPosition) && pCellRangeSource  && !pCellRangeSource->sSourceStr.isEmpty() &&
     703           0 :         !pCellRangeSource->sFilterName.isEmpty() && !pCellRangeSource->sURL.isEmpty() )
     704             :     {
     705           0 :         ScDocument* pDoc = rXMLImport.GetDocument();
     706           0 :         if (pDoc)
     707             :         {
     708           0 :             LockSolarMutex();
     709           0 :             ScRange aDestRange( rPosition.Col(), rPosition.Row(), rPosition.Tab(),
     710           0 :                 rPosition.Col() + static_cast<SCCOL>(pCellRangeSource->nColumns - 1),
     711           0 :                 rPosition.Row() + static_cast<SCROW>(pCellRangeSource->nRows - 1), rPosition.Tab() );
     712           0 :             String sFilterName( pCellRangeSource->sFilterName );
     713           0 :             String sSourceStr( pCellRangeSource->sSourceStr );
     714             :             ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
     715           0 :                 sFilterName, pCellRangeSource->sFilterOptions, sSourceStr, aDestRange, pCellRangeSource->nRefresh );
     716           0 :             sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
     717           0 :             pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, pCellRangeSource->sURL, &sFilterName, &sSourceStr );
     718             :         }
     719             :     }
     720        1837 : }
     721             : 
     722         394 : void ScXMLTableRowCellContext::SetFormulaCell(ScFormulaCell* pFCell) const
     723             : {
     724         394 :     if(pFCell)
     725             :     {
     726         394 :         if( bFormulaTextResult && pOUTextValue )
     727             :         {
     728          48 :             pFCell->SetHybridString( *pOUTextValue );
     729          48 :             pFCell->ResetDirty();
     730             :         }
     731         346 :         else if (!rtl::math::isNan(fValue))
     732             :         {
     733         346 :             pFCell->SetHybridDouble(fValue);
     734         346 :             pFCell->ResetDirty();
     735             :         }
     736             : 
     737             :         // Leave the cell dirty when the cached result is not given.
     738             :     }
     739         394 : }
     740             : 
     741         281 : void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos,
     742             :         const SCCOL nCurrentCol, const ::boost::optional< rtl::OUString >& pOUText )
     743             : {
     744         281 :     bool bDoIncrement = true;
     745             :     //matrix reference cells that contain text formula results;
     746             :     //cell was already put in document, just need to set text here.
     747         281 :     if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
     748             :     {
     749          10 :         ScBaseCell* pCell = rXMLImport.GetDocument()->GetCell( rCurrentPos );
     750          10 :         bDoIncrement = ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA );
     751          10 :         if ( bDoIncrement )
     752             :         {
     753          10 :             ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
     754          10 :             if (pOUTextValue && !pOUTextValue->isEmpty())
     755           8 :                 pFCell->SetHybridString( *pOUTextValue );
     756           2 :             else if (pOUTextContent && !pOUTextContent->isEmpty())
     757           0 :                 pFCell->SetHybridString( *pOUTextContent );
     758           2 :             else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
     759           0 :                 pFCell->SetHybridString( *pOUText );
     760             :             else
     761           2 :                 bDoIncrement = false;
     762          10 :             pFCell->ResetDirty();
     763             :         }
     764             :     }
     765             :     else //regular text cells
     766             :     {
     767         271 :         ScBaseCell* pNewCell = NULL;
     768         271 :         ScDocument* pDoc = rXMLImport.GetDocument();
     769         271 :         if (pOUTextValue && !pOUTextValue->isEmpty())
     770           0 :             pNewCell = ScBaseCell::CreateTextCell( *pOUTextValue, pDoc );
     771         271 :         else if (pOUTextContent && !pOUTextContent->isEmpty())
     772         250 :             pNewCell = ScBaseCell::CreateTextCell( *pOUTextContent, pDoc );
     773          21 :         else if ( nCurrentCol > 0 && pOUText && !pOUText->isEmpty() )
     774           0 :             pNewCell = ScBaseCell::CreateTextCell( *pOUText, pDoc );
     775             : 
     776         271 :         bDoIncrement = pNewCell != NULL;
     777         271 :         if ( bDoIncrement )
     778         250 :             pDoc->PutCell( rCurrentPos, pNewCell );
     779             :     }
     780             :     // #i56027# This is about setting simple text, not edit cells,
     781             :     // so ProgressBarIncrement must be called with bEditCell = FALSE.
     782             :     // Formatted text that is put into the cell by the child context
     783             :     // is handled in AddCellsToTable() (bIsEmpty is true then).
     784         281 :     if (bDoIncrement || bHasTextImport)
     785         260 :         rXMLImport.ProgressBarIncrement(false);
     786         281 : }
     787             : 
     788        1197 : void ScXMLTableRowCellContext::PutValueCell( const ScAddress& rCurrentPos )
     789             : {
     790             :     //matrix reference cells that contain value formula results;
     791             :     //cell was already put in document, just need to set value here.
     792        1197 :     if( rXMLImport.GetTables().IsPartOfMatrix(rCurrentPos) )
     793             :     {
     794          35 :         ScBaseCell* pCell = rXMLImport.GetDocument()->GetCell( rCurrentPos );
     795          35 :         if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
     796             :         {
     797          35 :             ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
     798          35 :             SetFormulaCell(pFCell);
     799             :         }
     800             :     }
     801             :     else  //regular value cell
     802             :     {
     803             :         // #i62435# Initialize the value cell's script type
     804             :         // if the default style's number format is latin-only.
     805             :         // If the cell uses a different format, the script type
     806             :         // will be reset when the style is applied.
     807             : 
     808        1162 :         ScBaseCell* pNewCell = new ScValueCell(fValue);
     809        1162 :         if ( rXMLImport.IsLatinDefaultStyle() )
     810        1162 :             pNewCell->SetScriptType( SCRIPTTYPE_LATIN );
     811             :         rXMLImport.GetDocument()->PutCell(
     812        1162 :             rCurrentPos.Col(), rCurrentPos.Row(),
     813        2324 :             rCurrentPos.Tab(), pNewCell );
     814             :     }
     815        1197 :     rXMLImport.ProgressBarIncrement(false);
     816        1197 : }
     817             : 
     818             : namespace {
     819             : 
     820           0 : bool isEmptyOrNote( ScDocument* pDoc, const ScAddress& rCurrentPos )
     821             : {
     822           0 :     ScBaseCell* pCell = pDoc->GetCell( rCurrentPos );
     823           0 :     return ( !pCell || pCell->GetCellType() == CELLTYPE_NOTE );
     824             : }
     825             : 
     826             : }
     827             : 
     828        2873 : void ScXMLTableRowCellContext::AddTextAndValueCells( const ScAddress& rCellPos,
     829             :         const ::boost::optional< rtl::OUString >& pOUText, ScAddress& rCurrentPos )
     830             : {
     831        2873 :     ScMyTables& rTables = rXMLImport.GetTables();
     832        2873 :     bool bWasEmpty = bIsEmpty;
     833        6873 :     for (SCCOL i = 0; i < nColsRepeated; ++i)
     834             :     {
     835        4000 :         rCurrentPos.SetCol( rCellPos.Col() + i );
     836        4000 :         if (i > 0)
     837        1127 :             rTables.AddColumn(false);
     838        4000 :         if (!bIsEmpty)
     839             :         {
     840        2950 :             for (SCROW j = 0; j < nRepeatedRows; ++j)
     841             :             {
     842        1478 :                 rCurrentPos.SetRow( rCellPos.Row() + j );
     843        1478 :                 if( (rCurrentPos.Col() == 0) && (j > 0) )
     844             :                 {
     845           0 :                     rTables.AddRow();
     846           0 :                     rTables.AddColumn(false);
     847             :                 }
     848        1478 :                 if( cellExists(rCurrentPos) )
     849             :                 {
     850        1478 :                     if(  ( !(bIsCovered) || isEmptyOrNote(rXMLImport.GetDocument(), rCurrentPos) )  )
     851             :                     {
     852        1478 :                         switch (nCellType)
     853             :                         {
     854             :                             case util::NumberFormat::TEXT:
     855             :                             {
     856         281 :                                 PutTextCell( rCurrentPos, i, pOUText );
     857             :                             }
     858         281 :                             break;
     859             :                             case util::NumberFormat::NUMBER:
     860             :                             case util::NumberFormat::PERCENT:
     861             :                             case util::NumberFormat::CURRENCY:
     862             :                             case util::NumberFormat::TIME:
     863             :                             case util::NumberFormat::DATETIME:
     864             :                             case util::NumberFormat::LOGICAL:
     865             :                             {
     866        1197 :                                 PutValueCell( rCurrentPos );
     867             :                             }
     868        1197 :                             break;
     869             :                             default:
     870             :                             {
     871             :                                 OSL_FAIL("no cell type given");
     872             :                             }
     873           0 :                             break;
     874             :                         }
     875             :                     }
     876             : 
     877        1478 :                     SetAnnotation( rCurrentPos );
     878        1478 :                     SetDetectiveObj( rCurrentPos );
     879        1478 :                     SetCellRangeSource( rCurrentPos );
     880             :                 }
     881             :                 else
     882             :                 {
     883           0 :                     if (!bWasEmpty || mxAnnotationData.get())
     884             :                     {
     885           0 :                         if (rCurrentPos.Row() > MAXROW)
     886           0 :                             rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
     887             :                         else
     888           0 :                             rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
     889             :                     }
     890             :                 }
     891             :             }
     892             :         }
     893             :         else
     894             :         {
     895             :             // #i56027# If the child context put formatted text into the cell,
     896             :             // bIsEmpty is true and ProgressBarIncrement has to be called
     897             :             // with bEditCell = TRUE.
     898        2528 :             if (bHasTextImport)
     899           2 :                 rXMLImport.ProgressBarIncrement(true);
     900        2528 :             if ((i == 0) && (rCellPos.Col() == 0))
     901             :             {
     902     3145843 :                 for (sal_Int32 j = 1; j < nRepeatedRows; ++j)
     903             :                 {
     904     3145723 :                     rTables.AddRow();
     905     3145723 :                     rTables.AddColumn(false);
     906             :                 }
     907             :             }
     908             :         }
     909             :     }
     910        2873 : }
     911             : 
     912        2873 : bool ScXMLTableRowCellContext::HasSpecialContent() const
     913             : {
     914          14 :     return ( (pContentValidationName && !pContentValidationName->isEmpty()) ||
     915        2887 :               mxAnnotationData.get() || pDetectiveObjVec || pCellRangeSource );
     916             : }
     917             : 
     918        4557 : bool ScXMLTableRowCellContext::CellsAreRepeated() const
     919             : {
     920        4557 :     return ( (nColsRepeated > 1) || (nRepeatedRows > 1) );
     921             : }
     922             : 
     923             : namespace {
     924             : 
     925             : // from ScCellObj::GetOutputString_Imp().  all of it may not be necessary.
     926         305 : rtl::OUString getOutputString(ScDocument* pDoc, const ScAddress& aCellPos)
     927             : {
     928         305 :     rtl::OUString aVal;
     929         305 :     if ( pDoc )
     930             :     {
     931         305 :         ScBaseCell* pCell = pDoc->GetCell( aCellPos );
     932         305 :         if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
     933             :         {
     934           0 :             if ( pCell->GetCellType() == CELLTYPE_EDIT )
     935             :             {
     936             :                 //  GetString an der EditCell macht Leerzeichen aus Umbruechen,
     937             :                 //  hier werden die Umbrueche aber gebraucht
     938           0 :                 const EditTextObject* pData = ( static_cast< ScEditCell* >(pCell) )->GetData();
     939           0 :                 if (pData)
     940             :                 {
     941           0 :                     EditEngine& rEngine = pDoc->GetEditEngine();
     942           0 :                     rEngine.SetText( *pData );
     943           0 :                     aVal = rEngine.GetText( LINEEND_LF );
     944             :                 }
     945             :                 //  Edit-Zellen auch nicht per NumberFormatter formatieren
     946             :                 //  (passend zur Ausgabe)
     947             :             }
     948             :             else
     949             :             {
     950             :                 //  wie in GetString am Dokument (column)
     951             :                 Color* pColor;
     952           0 :                 sal_uLong nNumFmt = pDoc->GetNumberFormat( aCellPos );
     953           0 :                 ScCellFormat::GetString( pCell, nNumFmt, aVal, &pColor, *pDoc->GetFormatTable() );
     954             :             }
     955             :         }
     956             :     }
     957         305 :     return aVal;
     958             : }
     959             : 
     960             : }
     961             : 
     962        2873 : void ScXMLTableRowCellContext::AddNonFormulaCells( const ScAddress& rCellPos )
     963             : {
     964        2873 :     ::boost::optional< rtl::OUString > pOUText;
     965             : 
     966        2873 :     if( nCellType == util::NumberFormat::TEXT )
     967             :     {
     968        1684 :         if( cellExists(rCellPos) && CellsAreRepeated() )
     969         305 :             pOUText.reset( getOutputString(rXMLImport.GetDocument(), rCellPos) );
     970             : 
     971        1684 :         if( !pOUTextContent && !pOUText && !pOUTextValue )
     972        1125 :                 bIsEmpty = true;
     973             :     }
     974             : 
     975        2873 :     ScAddress aCurrentPos( rCellPos );
     976        2873 :     if( HasSpecialContent() )
     977          15 :         bIsEmpty = false;
     978             : 
     979        2873 :     AddTextAndValueCells( rCellPos, pOUText, aCurrentPos );
     980             : 
     981        2873 :     if( CellsAreRepeated() )
     982             :     {
     983         309 :         SCCOL nStartCol( rCellPos.Col() < MAXCOL ? rCellPos.Col() : MAXCOL );
     984         309 :         SCROW nStartRow( rCellPos.Row() < MAXROW ? rCellPos.Row() : MAXROW );
     985         309 :         SCCOL nEndCol( rCellPos.Col() + nColsRepeated - 1 < MAXCOL ? rCellPos.Col() + nColsRepeated - 1 : MAXCOL );
     986         309 :         SCROW nEndRow( rCellPos.Row() + nRepeatedRows - 1 < MAXROW ? rCellPos.Row() + nRepeatedRows - 1 : MAXROW );
     987         309 :         ScRange aScRange( nStartCol, nStartRow, rCellPos.Tab(), nEndCol, nEndRow, rCellPos.Tab() );
     988         309 :         SetContentValidation( aScRange );
     989         309 :         rXMLImport.GetStylesImportHelper()->AddRange( aScRange );
     990             :     }
     991        2564 :     else if( cellExists(rCellPos) )
     992             :     {
     993        2564 :         rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
     994        2564 :         SetContentValidation( rCellPos );
     995        2873 :     }
     996        2873 : }
     997             : 
     998         334 : void ScXMLTableRowCellContext::PutFormulaCell( const ScAddress& rCellPos )
     999             : {
    1000         334 :     ScDocument* pDoc = rXMLImport.GetDocument();
    1001             : 
    1002         334 :     rtl::OUString aText = pOUFormula->first;
    1003         334 :     rtl::OUString aFormulaNmsp = pOUFormula->second;
    1004             : 
    1005         334 :     ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard;
    1006         334 :     pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc));
    1007             : 
    1008         334 :     ScBaseCell* pNewCell = NULL;
    1009             : 
    1010         334 :     if ( !aText.isEmpty() )
    1011             :     {
    1012         334 :         if ( aText[0] == '=' && aText.getLength() > 1 )
    1013             :         {
    1014             :             // temporary formula string as string tokens
    1015         334 :             ScTokenArray* pCode = new ScTokenArray;
    1016         334 :             pCode->AddStringXML( aText );
    1017         334 :             if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && !aFormulaNmsp.isEmpty() )
    1018           0 :                 pCode->AddStringXML( aFormulaNmsp );
    1019             : 
    1020         334 :             pDoc->IncXMLImportedFormulaCount( aText.getLength() );
    1021         334 :             pNewCell = new ScFormulaCell( pDoc, rCellPos, pCode, eGrammar, MM_NONE );
    1022         334 :             delete pCode;
    1023             : 
    1024         334 :             ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pNewCell);
    1025         334 :             SetFormulaCell(pFCell);
    1026             :         }
    1027           0 :         else if ( aText[0] == '\'' && aText.getLength() > 1 )
    1028             :         {
    1029             :             //  for bEnglish, "'" at the beginning is always interpreted as text
    1030             :             //  marker and stripped
    1031           0 :             pNewCell = ScBaseCell::CreateTextCell( aText.copy( 1 ), pDoc );
    1032             :         }
    1033             :         else
    1034             :         {
    1035           0 :             SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
    1036           0 :             sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
    1037             :             double fVal;
    1038           0 :             if ( pFormatter->IsNumberFormat( aText, nEnglish, fVal ) )
    1039           0 :                 pNewCell = new ScValueCell( fVal );
    1040             :             //the (english) number format will not be set
    1041             :             //search matching local format and apply it
    1042             :             else
    1043           0 :                 pNewCell = ScBaseCell::CreateTextCell( aText, pDoc );
    1044             :         }
    1045         334 :         pDoc->PutCell( rCellPos, pNewCell );
    1046         334 :     }
    1047         334 : }
    1048             : 
    1049         359 : void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos )
    1050             : {
    1051         359 :     if( cellExists(rCellPos) )
    1052             :     {
    1053         359 :         SetContentValidation( rCellPos );
    1054             :         OSL_ENSURE(((nColsRepeated == 1) && (nRepeatedRows == 1)), "repeated cells with formula not possible now");
    1055         359 :         rXMLImport.GetStylesImportHelper()->AddCell(rCellPos);
    1056             : 
    1057             :         //add matrix
    1058         359 :         if(bIsMatrix)
    1059             :         {
    1060          25 :             if (nMatrixCols > 0 && nMatrixRows > 0)
    1061             :             {
    1062             :                 //matrix cells are put in the document, but we must set the
    1063             :                 //value/text of each matrix cell later
    1064          25 :                 rXMLImport.GetTables().AddMatrixRange(
    1065          25 :                         rCellPos.Col(), rCellPos.Row(),
    1066          25 :                         rCellPos.Col() + nMatrixCols - 1,
    1067          25 :                         rCellPos.Row() + nMatrixRows - 1,
    1068         125 :                         pOUFormula->first, pOUFormula->second, eGrammar);
    1069             : 
    1070             :                 //set the value/text of the first matrix position (top-left).
    1071             :                 //the value/text of the matrix reference cells will be set later.
    1072             :                 ScFormulaCell* pFCell =
    1073          25 :                     static_cast<ScFormulaCell*>( rXMLImport.GetDocument()->GetCell(rCellPos) );
    1074          25 :                 SetFormulaCell(pFCell);
    1075             :             }
    1076             :         }
    1077             :         else
    1078         334 :             PutFormulaCell( rCellPos );
    1079             : 
    1080         359 :         SetAnnotation( rCellPos );
    1081         359 :         SetDetectiveObj( rCellPos );
    1082         359 :         SetCellRangeSource( rCellPos );
    1083         359 :         rXMLImport.ProgressBarIncrement(false);
    1084             :     }
    1085             :     else
    1086             :     {
    1087           0 :         if (rCellPos.Row() > MAXROW)
    1088           0 :             rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW);
    1089             :         else
    1090           0 :             rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW);
    1091             :     }
    1092         359 : }
    1093             : 
    1094             : //There are cases where a formula cell is exported with an office:value of 0 or
    1095             : //no office:value at all, but the formula cell will have a text:p value which
    1096             : //contains the intended formula result.
    1097             : //These cases include when a formula result:
    1098             : // - is blank
    1099             : // - has a constant error value beginning with "#" (such as "#VALUE!" or "#N/A")
    1100             : // - has an "Err:[###]" (where "[###]" is an error number)
    1101          75 : bool ScXMLTableRowCellContext::HasSpecialCaseFormulaText() const
    1102             : {
    1103         286 :     if(  pOUTextContent &&
    1104         148 :          ( pOUTextContent->isEmpty() || (pOUTextContent->indexOf("#") > -1) ||
    1105         138 :            (pOUTextContent->indexOf("Err:")  > -1) )
    1106             :       )
    1107          30 :         return true;
    1108          45 :     return false;
    1109             : }
    1110             : 
    1111             : 
    1112        3232 : void ScXMLTableRowCellContext::EndElement()
    1113             : {
    1114        3232 :     if( bHasTextImport && rXMLImport.GetRemoveLastChar() )
    1115             :     {
    1116           2 :         UniReference< XMLTextImportHelper > aTextImport = rXMLImport.GetTextImport();
    1117           2 :         if( aTextImport->GetCursor().is() )
    1118             :         {
    1119           2 :             if( aTextImport->GetCursor()->goLeft(1, true) )
    1120             :             {
    1121           2 :                 aTextImport->GetText()->insertString(
    1122           2 :                     aTextImport->GetCursorAsRange(), rtl::OUString(), true );
    1123             :             }
    1124           2 :             aTextImport->ResetCursor();
    1125           2 :         }
    1126             :     }
    1127             : 
    1128        3232 :     if( bFormulaTextResult && HasSpecialCaseFormulaText() )
    1129             :     {
    1130          30 :         pOUTextValue.reset(*pOUTextContent);
    1131          30 :         nCellType = util::NumberFormat::TEXT;
    1132             :     }
    1133             : 
    1134        3232 :     ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos();
    1135        3232 :     if( aCellPos.Col() > 0 && nRepeatedRows > 1 )
    1136           9 :         aCellPos.SetRow( aCellPos.Row() - (nRepeatedRows - 1) );
    1137        3232 :     if( bIsMerged )
    1138           5 :         DoMerge( aCellPos, nMergedCols - 1, nMergedRows - 1 );
    1139        3232 :     if( !pOUFormula )
    1140        2873 :         AddNonFormulaCells( aCellPos );
    1141             :     else // if ( pOUFormula )
    1142         359 :         AddFormulaCell( aCellPos );
    1143             : 
    1144        3232 :     UnlockSolarMutex(); //if LockSolarMutex got used, we presumably need to ensure an UnlockSolarMutex
    1145             : 
    1146        3232 :     bIsMerged = false;
    1147        3232 :     nMergedCols = 1;
    1148        3232 :     nMergedRows = 1;
    1149        3232 :     nColsRepeated = 1;
    1150        3232 : }
    1151             : 
    1152             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10