diff options
Diffstat (limited to 'sc/source/filter/xml/XMLStylesExportHelper.cxx')
-rw-r--r-- | sc/source/filter/xml/XMLStylesExportHelper.cxx | 1066 |
1 files changed, 1066 insertions, 0 deletions
diff --git a/sc/source/filter/xml/XMLStylesExportHelper.cxx b/sc/source/filter/xml/XMLStylesExportHelper.cxx new file mode 100644 index 000000000..81c30e424 --- /dev/null +++ b/sc/source/filter/xml/XMLStylesExportHelper.cxx @@ -0,0 +1,1066 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "XMLStylesExportHelper.hxx" +#include <tools/lineend.hxx> +#include <unonames.hxx> +#include "xmlexprt.hxx" +#include <document.hxx> +#include <rangeutl.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/XMLEventExport.hxx> +#include <xmloff/namespacemap.hxx> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sheet/XSheetCondition.hpp> +#include <com/sun/star/sheet/TableValidationVisibility.hpp> +#include <comphelper/extract.hxx> +#include <comphelper/propertysequence.hxx> +#include <sfx2/app.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <osl/diagnose.h> + +using namespace com::sun::star; +using namespace xmloff::token; + +ScMyValidation::ScMyValidation() + : aAlertStyle(sheet::ValidationAlertStyle_STOP), + aValidationType(sheet::ValidationType_ANY), + aOperator(sheet::ConditionOperator_NONE), + nShowList(0), + bShowErrorMessage(false), + bShowInputMessage(false), + bIgnoreBlanks(false) +{ +} + +bool ScMyValidation::IsEqual(const ScMyValidation& aVal) const +{ + return aVal.bIgnoreBlanks == bIgnoreBlanks && + aVal.bShowInputMessage == bShowInputMessage && + aVal.bShowErrorMessage == bShowErrorMessage && + aVal.aBaseCell == aBaseCell && + aVal.aAlertStyle == aAlertStyle && + aVal.aValidationType == aValidationType && + aVal.aOperator == aOperator && + aVal.sErrorTitle == sErrorTitle && + aVal.sInputTitle == sInputTitle && + aVal.sErrorMessage == sErrorMessage && + aVal.sInputMessage == sInputMessage && + aVal.sFormula1 == sFormula1 && + aVal.sFormula2 == sFormula2; +} + +ScMyValidationsContainer::ScMyValidationsContainer() +{ +} + +ScMyValidationsContainer::~ScMyValidationsContainer() +{ +} + +void ScMyValidationsContainer::AddValidation(const uno::Any& aTempAny, + sal_Int32& nValidationIndex) +{ + uno::Reference<beans::XPropertySet> xPropertySet(aTempAny, uno::UNO_QUERY); + if (!xPropertySet.is()) + return; + + OUString sErrorMessage; + xPropertySet->getPropertyValue(SC_UNONAME_ERRMESS) >>= sErrorMessage; + OUString sErrorTitle; + xPropertySet->getPropertyValue(SC_UNONAME_ERRTITLE) >>= sErrorTitle; + OUString sInputMessage; + xPropertySet->getPropertyValue(SC_UNONAME_INPMESS) >>= sInputMessage; + OUString sInputTitle; + xPropertySet->getPropertyValue(SC_UNONAME_INPTITLE) >>= sInputTitle; + bool bShowErrorMessage = ::cppu::any2bool(xPropertySet->getPropertyValue(SC_UNONAME_SHOWERR)); + bool bShowInputMessage = ::cppu::any2bool(xPropertySet->getPropertyValue(SC_UNONAME_SHOWINP)); + sheet::ValidationType aValidationType; + xPropertySet->getPropertyValue(SC_UNONAME_TYPE) >>= aValidationType; + if (!bShowErrorMessage && !bShowInputMessage && aValidationType == sheet::ValidationType_ANY && + sErrorMessage.isEmpty() && sErrorTitle.isEmpty() && sInputMessage.isEmpty() && sInputTitle.isEmpty()) + return; + + ScMyValidation aValidation; + aValidation.sErrorMessage = sErrorMessage; + aValidation.sErrorTitle = sErrorTitle; + aValidation.sInputMessage = sInputMessage; + aValidation.sInputTitle = sInputTitle; + aValidation.bShowErrorMessage = bShowErrorMessage; + aValidation.bShowInputMessage = bShowInputMessage; + aValidation.aValidationType = aValidationType; + aValidation.bIgnoreBlanks = ::cppu::any2bool(xPropertySet->getPropertyValue(SC_UNONAME_IGNOREBL)); + xPropertySet->getPropertyValue(SC_UNONAME_SHOWLIST) >>= aValidation.nShowList; + xPropertySet->getPropertyValue(SC_UNONAME_ERRALSTY) >>= aValidation.aAlertStyle; + uno::Reference<sheet::XSheetCondition> xCondition(xPropertySet, uno::UNO_QUERY); + if (xCondition.is()) + { + aValidation.sFormula1 = xCondition->getFormula1(); + aValidation.sFormula2 = xCondition->getFormula2(); + aValidation.aOperator = xCondition->getOperator(); + table::CellAddress aCellAddress= xCondition->getSourcePosition(); + aValidation.aBaseCell = ScAddress( static_cast<SCCOL>(aCellAddress.Column), static_cast<SCROW>(aCellAddress.Row), aCellAddress.Sheet ); + } + //ScMyValidationRange aValidationRange; + bool bEqualFound(false); + sal_Int32 i(0); + sal_Int32 nCount(aValidationVec.size()); + while (i < nCount && !bEqualFound) + { + bEqualFound = aValidationVec[i].IsEqual(aValidation); + if (!bEqualFound) + ++i; + } + if (bEqualFound) + nValidationIndex = i; + else + { + sal_Int32 nNameIndex(nCount + 1); + OUString sCount(OUString::number(nNameIndex)); + aValidation.sName += "val"; + aValidation.sName += sCount; + aValidationVec.push_back(aValidation); + nValidationIndex = nCount; + } +} + +OUString ScMyValidationsContainer::GetCondition(ScXMLExport& rExport, const ScMyValidation& aValidation) +{ + /* ATTENTION! Should the condition to not write sheet::ValidationType_ANY + * ever be changed, adapt the conditional call of + * MarkUsedExternalReferences() in + * ScTableValidationObj::ScTableValidationObj() accordingly! */ + OUString sCondition; + if (aValidation.aValidationType != sheet::ValidationType_ANY) + { + switch (aValidation.aValidationType) + { + //case sheet::ValidationType_CUSTOM + case sheet::ValidationType_DATE : + sCondition += "cell-content-is-date()"; + break; + case sheet::ValidationType_DECIMAL : + sCondition += "cell-content-is-decimal-number()"; + break; + case sheet::ValidationType_LIST : + sCondition += "cell-content-is-in-list(" + aValidation.sFormula1 + ")"; + break; + case sheet::ValidationType_TEXT_LEN : + if (aValidation.aOperator != sheet::ConditionOperator_BETWEEN && + aValidation.aOperator != sheet::ConditionOperator_NOT_BETWEEN) + sCondition += "cell-content-text-length()"; + break; + case sheet::ValidationType_TIME : + sCondition += "cell-content-is-time()"; + break; + case sheet::ValidationType_WHOLE : + sCondition += "cell-content-is-whole-number()"; + break; + case sheet::ValidationType_CUSTOM : + sCondition += "is-true-formula(" + aValidation.sFormula1 + ")"; + break; + default: + { + // added to avoid warnings + } + } + if (aValidation.aValidationType != sheet::ValidationType_LIST && + aValidation.aValidationType != sheet::ValidationType_CUSTOM && + (!aValidation.sFormula1.isEmpty() || + ((aValidation.aOperator == sheet::ConditionOperator_BETWEEN || + aValidation.aOperator == sheet::ConditionOperator_NOT_BETWEEN) && + !aValidation.sFormula2.isEmpty()))) + { + if (aValidation.aValidationType != sheet::ValidationType_TEXT_LEN) + sCondition += " and "; + if (aValidation.aOperator != sheet::ConditionOperator_BETWEEN && + aValidation.aOperator != sheet::ConditionOperator_NOT_BETWEEN) + { + if (aValidation.aValidationType != sheet::ValidationType_TEXT_LEN) + sCondition += "cell-content()"; + switch (aValidation.aOperator) + { + case sheet::ConditionOperator_EQUAL : + sCondition += "="; + break; + case sheet::ConditionOperator_GREATER : + sCondition += ">"; + break; + case sheet::ConditionOperator_GREATER_EQUAL : + sCondition += ">="; + break; + case sheet::ConditionOperator_LESS : + sCondition += "<"; + break; + case sheet::ConditionOperator_LESS_EQUAL : + sCondition += "<="; + break; + case sheet::ConditionOperator_NOT_EQUAL : + sCondition += "!="; + break; + default: + { + // added to avoid warnings + } + } + sCondition += aValidation.sFormula1; + } + else + { + if (aValidation.aValidationType == sheet::ValidationType_TEXT_LEN) + { + if (aValidation.aOperator == sheet::ConditionOperator_BETWEEN) + sCondition += "cell-content-text-length-is-between("; + else + sCondition += "cell-content-text-length-is-not-between("; + } + else + { + if (aValidation.aOperator == sheet::ConditionOperator_BETWEEN) + sCondition += "cell-content-is-between("; + else + sCondition += "cell-content-is-not-between("; + } + sCondition += aValidation.sFormula1 + "," + aValidation.sFormula2 + ")"; + } + } + else + if (aValidation.aValidationType == sheet::ValidationType_TEXT_LEN) + sCondition.clear(); + } + if (!sCondition.isEmpty()) + { + const formula::FormulaGrammar::Grammar eGrammar = rExport.GetDocument()->GetStorageGrammar(); + sal_uInt16 nNamespacePrefix = (eGrammar == formula::FormulaGrammar::GRAM_ODFF ? XML_NAMESPACE_OF : XML_NAMESPACE_OOOC); + sCondition = rExport.GetNamespaceMap().GetQNameByKey( nNamespacePrefix, sCondition, false ); + } + + return sCondition; +} + +OUString ScMyValidationsContainer::GetBaseCellAddress(const ScDocument* pDoc, const ScAddress& aCell) +{ + OUString sAddress; + ScRangeStringConverter::GetStringFromAddress( sAddress, aCell, pDoc, ::formula::FormulaGrammar::CONV_OOO ); + return sAddress; +} + +void ScMyValidationsContainer::WriteMessage(ScXMLExport& rExport, + const OUString& sTitle, const OUString& sOUMessage, + const bool bShowMessage, const bool bIsHelpMessage) +{ + if (!sTitle.isEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TITLE, sTitle); + if (bShowMessage) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, XML_TRUE); + else + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, XML_FALSE); + std::unique_ptr<SvXMLElementExport> pMessage; + if (bIsHelpMessage) + pMessage.reset(new SvXMLElementExport(rExport, XML_NAMESPACE_TABLE, XML_HELP_MESSAGE, true, true)); + else + pMessage.reset(new SvXMLElementExport(rExport, XML_NAMESPACE_TABLE, XML_ERROR_MESSAGE, true, true)); + if (sOUMessage.isEmpty()) + return; + + sal_Int32 i(0); + OUStringBuffer sTemp; + OUString sText(convertLineEnd(sOUMessage, LINEEND_LF)); + bool bPrevCharWasSpace(true); + while(i < sText.getLength()) + { + if( sText[i] == '\n') + { + SvXMLElementExport aElemP(rExport, XML_NAMESPACE_TEXT, XML_P, true, false); + rExport.GetTextParagraphExport()->exportCharacterData(sTemp.makeStringAndClear(), bPrevCharWasSpace); + bPrevCharWasSpace = true; // reset for start of next paragraph + } + else + sTemp.append(sText[i]); + ++i; + } + if (!sTemp.isEmpty()) + { + SvXMLElementExport aElemP(rExport, XML_NAMESPACE_TEXT, XML_P, true, false); + rExport.GetTextParagraphExport()->exportCharacterData(sTemp.makeStringAndClear(), bPrevCharWasSpace); + } +} + +void ScMyValidationsContainer::WriteValidations(ScXMLExport& rExport) +{ + if (aValidationVec.empty()) + return; + + SvXMLElementExport aElemVs(rExport, XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATIONS, true, true); + for (const auto& rValidation : aValidationVec) + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, rValidation.sName); + OUString sCondition(GetCondition(rExport, rValidation)); + if (!sCondition.isEmpty()) + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONDITION, sCondition); + if (rValidation.bIgnoreBlanks) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ALLOW_EMPTY_CELL, XML_TRUE); + else + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ALLOW_EMPTY_CELL, XML_FALSE); + if (rValidation.aValidationType == sheet::ValidationType_LIST) + { + switch (rValidation.nShowList) + { + case sheet::TableValidationVisibility::INVISIBLE: + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_LIST, XML_NO); + break; + case sheet::TableValidationVisibility::UNSORTED: + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_LIST, XML_UNSORTED); + break; + case sheet::TableValidationVisibility::SORTEDASCENDING: + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_LIST, XML_SORT_ASCENDING); + break; + default: + OSL_FAIL("unknown ListType"); + } + } + } + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BASE_CELL_ADDRESS, GetBaseCellAddress(rExport.GetDocument(), rValidation.aBaseCell)); + SvXMLElementExport aElemV(rExport, XML_NAMESPACE_TABLE, XML_CONTENT_VALIDATION, true, true); + if (rValidation.bShowInputMessage || !rValidation.sInputMessage.isEmpty() || !rValidation.sInputTitle.isEmpty()) + { + WriteMessage(rExport, rValidation.sInputTitle, rValidation.sInputMessage, rValidation.bShowInputMessage, true); + } + if (rValidation.bShowErrorMessage || !rValidation.sErrorMessage.isEmpty() || !rValidation.sErrorTitle.isEmpty()) + { + switch (rValidation.aAlertStyle) + { + case sheet::ValidationAlertStyle_INFO : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MESSAGE_TYPE, XML_INFORMATION); + WriteMessage(rExport, rValidation.sErrorTitle, rValidation.sErrorMessage, rValidation.bShowErrorMessage, false); + } + break; + case sheet::ValidationAlertStyle_WARNING : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MESSAGE_TYPE, XML_WARNING); + WriteMessage(rExport, rValidation.sErrorTitle, rValidation.sErrorMessage, rValidation.bShowErrorMessage, false); + } + break; + case sheet::ValidationAlertStyle_STOP : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MESSAGE_TYPE, XML_STOP); + WriteMessage(rExport, rValidation.sErrorTitle, rValidation.sErrorMessage, rValidation.bShowErrorMessage, false); + } + break; + case sheet::ValidationAlertStyle_MACRO : + { + { + //rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, aItr->sErrorTitle); + if (rValidation.bShowErrorMessage) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_EXECUTE, XML_TRUE); + else + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_EXECUTE, XML_FALSE); + SvXMLElementExport aEMElem(rExport, XML_NAMESPACE_TABLE, XML_ERROR_MACRO, true, true); + } + { + // #i47525# for a script URL the type and the property name for the URL + // are both "Script", for a simple macro name the type is "StarBasic" + // and the property name is "MacroName". + bool bScriptURL = SfxApplication::IsXScriptURL( rValidation.sErrorTitle ); + + static const OUStringLiteral sScript(u"Script"); + uno::Sequence<beans::PropertyValue> aSeq( comphelper::InitPropertySequence({ + { "EventType", uno::Any(bScriptURL ? sScript : OUString("StarBasic")) }, + { "Library", uno::Any(OUString()) }, + { bScriptURL ? sScript : OUString("MacroName"), uno::Any(rValidation.sErrorTitle) } + })); + // 2) export the sequence + rExport.GetEventExport().ExportSingleEvent( aSeq, "OnError"); + } + } + break; + default: + { + // added to avoid warnings + } + } + } + } +} + +const OUString& ScMyValidationsContainer::GetValidationName(const sal_Int32 nIndex) +{ + OSL_ENSURE( o3tl::make_unsigned(nIndex) < aValidationVec.size(), "out of range" ); + return aValidationVec[nIndex].sName; +} + +sal_Int32 ScMyDefaultStyles::GetStyleNameIndex(const ScFormatRangeStyles* pCellStyles, + const sal_Int32 nTable, const sal_Int32 nPos, + const sal_Int32 i, bool& bIsAutoStyle) +{ + return pCellStyles->GetStyleNameIndex(nTable, i, nPos, bIsAutoStyle); +} + +void ScMyDefaultStyles::FillDefaultStyles(const sal_Int32 nTable, + const sal_Int32 nLastRow, const sal_Int32 nLastCol, + const ScFormatRangeStyles* pCellStyles, ScDocument* pDoc) +{ + maColDefaults.clear(); + maColDefaults.resize(nLastCol + 1); + if (!pDoc) + return ; + + SCTAB nTab = static_cast<SCTAB>(nTable); + pDoc->CreateColumnIfNotExists(nTab, nLastCol); + sal_Int32 nPos; + ScMyDefaultStyleList* pDefaults = &maColDefaults; + bool bPrevAutoStyle(false); + bool bIsAutoStyle; + sal_Int32 nPrevIndex(0); + sal_Int32 nRepeat(0); + for (sal_Int32 i = nLastCol; i >= 0; --i) + { + pDoc->GetColDefault(nTab, static_cast<SCCOL>(i), static_cast<SCROW>(nLastRow), nPos); + if (!nRepeat) + { + nPrevIndex = GetStyleNameIndex(pCellStyles, nTab, nPos, i, bPrevAutoStyle); + (*pDefaults)[i].nIndex = nPrevIndex; + (*pDefaults)[i].bIsAutoStyle = bPrevAutoStyle; + nRepeat = 1; + } + else + { + sal_Int32 nIndex = GetStyleNameIndex(pCellStyles, nTab, nPos, i, bIsAutoStyle); + if ((nIndex != nPrevIndex) || (bIsAutoStyle != bPrevAutoStyle)) + { + nRepeat = 1; + nPrevIndex = GetStyleNameIndex(pCellStyles, nTab, nPos, i, bPrevAutoStyle); + (*pDefaults)[i].nIndex = nPrevIndex; + (*pDefaults)[i].bIsAutoStyle = bPrevAutoStyle; + } + else + { + (*pDefaults)[i].nIndex = nPrevIndex; + (*pDefaults)[i].bIsAutoStyle = bPrevAutoStyle; + ++nRepeat; + if (nRepeat > 1) + (*pDefaults)[i].nRepeat = nRepeat; + } + } + } +} + +ScMyRowFormatRange::ScMyRowFormatRange() + : nStartColumn(0), + nRepeatColumns(0), + nRepeatRows(0), + nIndex(-1), + nValidationIndex(-1), + bIsAutoStyle(true) +{ +} + +bool ScMyRowFormatRange::operator< (const ScMyRowFormatRange& rRange) const +{ + return (nStartColumn < rRange.nStartColumn); +} + +ScRowFormatRanges::ScRowFormatRanges() + : pColDefaults(nullptr), + nSize(0) +{ +} + +ScRowFormatRanges::ScRowFormatRanges(const ScRowFormatRanges* pRanges) + : aRowFormatRanges(pRanges->aRowFormatRanges), + pColDefaults(pRanges->pColDefaults), + nSize(pRanges->nSize) +{ +} + +ScRowFormatRanges::~ScRowFormatRanges() +{ +} + +void ScRowFormatRanges::Clear() +{ + aRowFormatRanges.clear(); + nSize = 0; +} + +void ScRowFormatRanges::AddRange(const sal_Int32 nPrevStartCol, const sal_Int32 nRepeat, const sal_Int32 nPrevIndex, + const bool bPrevAutoStyle, const ScMyRowFormatRange& rFormatRange) +{ + sal_Int32 nIndex(-1); + if ((nPrevIndex != rFormatRange.nIndex) || + (bPrevAutoStyle != rFormatRange.bIsAutoStyle)) + nIndex = rFormatRange.nIndex; + + bool bInserted(false); + if (!aRowFormatRanges.empty()) + { + ScMyRowFormatRange& rRange(aRowFormatRanges.back()); + if ((nPrevStartCol == (rRange.nStartColumn + rRange.nRepeatColumns)) + && (rRange.bIsAutoStyle == rFormatRange.bIsAutoStyle) && (rRange.nIndex == nIndex) + && (rRange.nValidationIndex == rFormatRange.nValidationIndex)) + { + if (rFormatRange.nRepeatRows < rRange.nRepeatRows) + rRange.nRepeatRows = rFormatRange.nRepeatRows; + rRange.nRepeatColumns += nRepeat; + bInserted = true; + } + } + if (!bInserted) + { + ScMyRowFormatRange aRange; + aRange.nStartColumn = nPrevStartCol; + aRange.nRepeatColumns = nRepeat; + aRange.nRepeatRows = rFormatRange.nRepeatRows; + aRange.nValidationIndex = rFormatRange.nValidationIndex; + aRange.bIsAutoStyle = rFormatRange.bIsAutoStyle; + aRange.nIndex = nIndex; + aRowFormatRanges.push_back(aRange); + ++nSize; + } +} + +void ScRowFormatRanges::AddRange(const ScMyRowFormatRange& rFormatRange) +{ + OSL_ENSURE(pColDefaults, "no column defaults"); + if (!pColDefaults) + return; + sal_Int32 nPrevIndex = -1; + bool bPrevAutoStyle = true; + + sal_uInt32 nPrevStartCol(rFormatRange.nStartColumn); + OSL_ENSURE( static_cast<size_t>(nPrevStartCol) < pColDefaults->size(), "nPrevStartCol out of bounds"); + sal_uInt32 nRepeat; + if (static_cast<size_t>(nPrevStartCol) < pColDefaults->size()) + { + nRepeat = (*pColDefaults)[nPrevStartCol].nRepeat; + nPrevIndex = (*pColDefaults)[nPrevStartCol].nIndex; + bPrevAutoStyle = (*pColDefaults)[nPrevStartCol].bIsAutoStyle; + } + else + { + /* Again, this is to prevent out-of-bounds accesses, so FIXME + * elsewhere! */ + if (pColDefaults->empty()) + { + nRepeat = 1; + nPrevIndex = -1; + bPrevAutoStyle = false; + } + else + { + nRepeat = (*pColDefaults)[pColDefaults->size()-1].nRepeat; + nPrevIndex = (*pColDefaults)[pColDefaults->size()-1].nIndex; + bPrevAutoStyle = (*pColDefaults)[pColDefaults->size()-1].bIsAutoStyle; + } + } + sal_uInt32 nEnd = nPrevStartCol + rFormatRange.nRepeatColumns; + for(sal_uInt32 i = nPrevStartCol + nRepeat; i < nEnd && i < pColDefaults->size(); i += (*pColDefaults)[i].nRepeat) + { + OSL_ENSURE(sal_uInt32(nPrevStartCol + nRepeat) <= nEnd, "something went wrong"); + if ((nPrevIndex != (*pColDefaults)[i].nIndex) || + (bPrevAutoStyle != (*pColDefaults)[i].bIsAutoStyle)) + { + AddRange(nPrevStartCol, nRepeat, nPrevIndex, bPrevAutoStyle, rFormatRange); + nPrevStartCol = i; + nRepeat = (*pColDefaults)[i].nRepeat; + nPrevIndex = (*pColDefaults)[i].nIndex; + bPrevAutoStyle = (*pColDefaults)[i].bIsAutoStyle; + } + else + nRepeat += (*pColDefaults)[i].nRepeat; + } + if (sal_uInt32(nPrevStartCol + nRepeat) > nEnd) + nRepeat = nEnd - nPrevStartCol; + AddRange(nPrevStartCol, nRepeat, nPrevIndex, bPrevAutoStyle, rFormatRange); + +} + +bool ScRowFormatRanges::GetNext(ScMyRowFormatRange& aFormatRange) +{ + ScMyRowFormatRangesList::iterator aItr(aRowFormatRanges.begin()); + if (aItr != aRowFormatRanges.end()) + { + aFormatRange = *aItr; + aRowFormatRanges.erase(aItr); + --nSize; + return true; + } + return false; +} + +sal_Int32 ScRowFormatRanges::GetMaxRows() const +{ + sal_Int32 nMaxRows(0); + if (!aRowFormatRanges.empty()) + { + auto aItr = std::min_element(aRowFormatRanges.begin(), aRowFormatRanges.end(), + [](const ScMyRowFormatRange& a, const ScMyRowFormatRange& b) { return a.nRepeatRows < b.nRepeatRows; }); + nMaxRows = (*aItr).nRepeatRows; + } + else + { + OSL_FAIL("no ranges found"); + } + return nMaxRows; +} + +void ScRowFormatRanges::Sort() +{ + aRowFormatRanges.sort(); +} + +ScMyFormatRange::ScMyFormatRange() + : nStyleNameIndex(-1) + , nValidationIndex(-1) + , nNumberFormat(0) + , bIsAutoStyle(true) +{ +} + +bool ScMyFormatRange::operator<(const ScMyFormatRange& rRange) const +{ + if (aRangeAddress.StartRow < rRange.aRangeAddress.StartRow) + return true; + else + if (aRangeAddress.StartRow == rRange.aRangeAddress.StartRow) + return (aRangeAddress.StartColumn < rRange.aRangeAddress.StartColumn); + else + return false; +} + +ScFormatRangeStyles::ScFormatRangeStyles() + : pColDefaults(nullptr) +{ +} + +ScFormatRangeStyles::~ScFormatRangeStyles() +{ +} + +void ScFormatRangeStyles::AddNewTable(const sal_Int32 nTable) +{ + sal_Int32 nSize = aTables.size() - 1; + if (nTable > nSize) + for (sal_Int32 i = nSize; i < nTable; ++i) + { + aTables.emplace_back(); + } +} + +bool ScFormatRangeStyles::AddStyleName(OUString const & rString, sal_Int32& rIndex, const bool bIsAutoStyle) +{ + if (bIsAutoStyle) + { + aAutoStyleNames.push_back(rString); + rIndex = aAutoStyleNames.size() - 1; + return true; + } + else + { + sal_Int32 nCount(aStyleNames.size()); + bool bFound(false); + sal_Int32 i(nCount - 1); + while ((i >= 0) && (!bFound)) + { + if (aStyleNames.at(i) == rString) + bFound = true; + else + i--; + } + if (bFound) + { + rIndex = i; + return false; + } + else + { + aStyleNames.push_back(rString); + rIndex = aStyleNames.size() - 1; + return true; + } + } +} + +sal_Int32 ScFormatRangeStyles::GetIndexOfStyleName(std::u16string_view rString, const OUString& rPrefix, bool& bIsAutoStyle) +{ + sal_Int32 nPrefixLength(rPrefix.getLength()); + std::u16string_view sTemp(rString.substr(nPrefixLength)); + sal_Int32 nIndex(o3tl::toInt32(sTemp)); + if (nIndex > 0 && o3tl::make_unsigned(nIndex-1) < aAutoStyleNames.size() && aAutoStyleNames.at(nIndex - 1) == rString) + { + bIsAutoStyle = true; + return nIndex - 1; + } + else + { + sal_Int32 i(0); + bool bFound(false); + while (!bFound && o3tl::make_unsigned(i) < aStyleNames.size()) + { + if (aStyleNames[i] == rString) + bFound = true; + else + ++i; + } + if (bFound) + { + bIsAutoStyle = false; + return i; + } + else + { + i = 0; + while (!bFound && o3tl::make_unsigned(i) < aAutoStyleNames.size()) + { + if (aAutoStyleNames[i] == rString) + bFound = true; + else + ++i; + } + if (bFound) + { + bIsAutoStyle = true; + return i; + } + else + return -1; + } + } +} + +sal_Int32 ScFormatRangeStyles::GetStyleNameIndex(const sal_Int32 nTable, + const sal_Int32 nColumn, const sal_Int32 nRow, bool& bIsAutoStyle) const +{ + OSL_ENSURE(o3tl::make_unsigned(nTable) < aTables.size(), "wrong table"); + bIsAutoStyle = false; + if (o3tl::make_unsigned(nTable) >= aTables.size()) + return -1; + for (const ScMyFormatRange & rFormatRange : aTables[nTable]) + { + if ((rFormatRange.aRangeAddress.StartColumn <= nColumn) && + (rFormatRange.aRangeAddress.EndColumn >= nColumn) && + (rFormatRange.aRangeAddress.StartRow <= nRow) && + (rFormatRange.aRangeAddress.EndRow >= nRow)) + { + bIsAutoStyle = rFormatRange.bIsAutoStyle; + return rFormatRange.nStyleNameIndex; + } + } + return -1; +} + +sal_Int32 ScFormatRangeStyles::GetStyleNameIndex(const sal_Int32 nTable, const sal_Int32 nColumn, const sal_Int32 nRow, + bool& bIsAutoStyle, sal_Int32& nValidationIndex, sal_Int32& nNumberFormat, const sal_Int32 nRemoveBeforeRow) +{ + OSL_ENSURE(o3tl::make_unsigned(nTable) < aTables.size(), "wrong table"); + if (o3tl::make_unsigned(nTable) >= aTables.size()) + return -1; + ScMyFormatRangeAddresses& rFormatRanges(aTables[nTable]); + ScMyFormatRangeAddresses::iterator aItr(rFormatRanges.begin()); + ScMyFormatRangeAddresses::iterator aEndItr(rFormatRanges.end()); + while (aItr != aEndItr) + { + if (((*aItr).aRangeAddress.StartColumn <= nColumn) && + ((*aItr).aRangeAddress.EndColumn >= nColumn) && + ((*aItr).aRangeAddress.StartRow <= nRow) && + ((*aItr).aRangeAddress.EndRow >= nRow)) + { + bIsAutoStyle = aItr->bIsAutoStyle; + nValidationIndex = aItr->nValidationIndex; + nNumberFormat = aItr->nNumberFormat; + OSL_ENSURE( o3tl::make_unsigned(nColumn) < pColDefaults->size(), "nColumn out of bounds"); + if (o3tl::make_unsigned(nColumn) < pColDefaults->size() && + ((*pColDefaults)[nColumn].nIndex != -1) && + ((*pColDefaults)[nColumn].nIndex == (*aItr).nStyleNameIndex) && + ((*pColDefaults)[nColumn].bIsAutoStyle == (*aItr).bIsAutoStyle)) + return -1; + else + return (*aItr).nStyleNameIndex; + } + else + { + if ((*aItr).aRangeAddress.EndRow < nRemoveBeforeRow) + aItr = rFormatRanges.erase(aItr); + else + ++aItr; + } + } + return -1; +} + +void ScFormatRangeStyles::GetFormatRanges(const sal_Int32 nStartColumn, const sal_Int32 nEndColumn, const sal_Int32 nRow, + const sal_Int32 nTable, ScRowFormatRanges* pRowFormatRanges) +{ + sal_Int32 nTotalColumns(nEndColumn - nStartColumn + 1); + OSL_ENSURE(o3tl::make_unsigned(nTable) < aTables.size(), "wrong table"); + ScMyFormatRangeAddresses& rFormatRanges(aTables[nTable]); + ScMyFormatRangeAddresses::iterator aItr(rFormatRanges.begin()); + ScMyFormatRangeAddresses::iterator aEndItr(rFormatRanges.end()); + sal_Int32 nColumns = 0; + while (aItr != aEndItr && nColumns < nTotalColumns) + { + if (((*aItr).aRangeAddress.StartRow <= nRow) && + ((*aItr).aRangeAddress.EndRow >= nRow)) + { + if ((((*aItr).aRangeAddress.StartColumn <= nStartColumn) && + ((*aItr).aRangeAddress.EndColumn >= nStartColumn)) || + (((*aItr).aRangeAddress.StartColumn <= nEndColumn) && + ((*aItr).aRangeAddress.EndColumn >= nEndColumn)) || + (((*aItr).aRangeAddress.StartColumn >= nStartColumn) && + ((*aItr).aRangeAddress.EndColumn <= nEndColumn))) + { + ScMyRowFormatRange aRange; + aRange.nIndex = aItr->nStyleNameIndex; + aRange.nValidationIndex = aItr->nValidationIndex; + aRange.bIsAutoStyle = aItr->bIsAutoStyle; + if ((aItr->aRangeAddress.StartColumn < nStartColumn) && + (aItr->aRangeAddress.EndColumn >= nStartColumn)) + { + if (aItr->aRangeAddress.EndColumn >= nEndColumn) + aRange.nRepeatColumns = nTotalColumns; + else + aRange.nRepeatColumns = aItr->aRangeAddress.EndColumn - nStartColumn + 1; + aRange.nStartColumn = nStartColumn; + } + else if ((aItr->aRangeAddress.StartColumn >= nStartColumn) && + (aItr->aRangeAddress.EndColumn <= nEndColumn)) + { + aRange.nRepeatColumns = aItr->aRangeAddress.EndColumn - aItr->aRangeAddress.StartColumn + 1; + aRange.nStartColumn = aItr->aRangeAddress.StartColumn; + } + else if ((aItr->aRangeAddress.StartColumn >= nStartColumn) && + (aItr->aRangeAddress.StartColumn <= nEndColumn) && + (aItr->aRangeAddress.EndColumn > nEndColumn)) + { + aRange.nRepeatColumns = nEndColumn - aItr->aRangeAddress.StartColumn + 1; + aRange.nStartColumn = aItr->aRangeAddress.StartColumn; + } + aRange.nRepeatRows = aItr->aRangeAddress.EndRow - nRow + 1; + pRowFormatRanges->AddRange(aRange); + nColumns += aRange.nRepeatColumns; + } + ++aItr; + } + else + if(aItr->aRangeAddress.EndRow < nRow) + aItr = rFormatRanges.erase(aItr); + else + ++aItr; + } + pRowFormatRanges->Sort(); +} + +void ScFormatRangeStyles::AddRangeStyleName(const table::CellRangeAddress& rCellRangeAddress, + const sal_Int32 nStringIndex, const bool bIsAutoStyle, const sal_Int32 nValidationIndex, + const sal_Int32 nNumberFormat) +{ + ScMyFormatRange aFormatRange; + aFormatRange.aRangeAddress = rCellRangeAddress; + aFormatRange.nStyleNameIndex = nStringIndex; + aFormatRange.nValidationIndex = nValidationIndex; + aFormatRange.nNumberFormat = nNumberFormat; + aFormatRange.bIsAutoStyle = bIsAutoStyle; + OSL_ENSURE(o3tl::make_unsigned(rCellRangeAddress.Sheet) < aTables.size(), "wrong table"); + ScMyFormatRangeAddresses& rFormatRanges(aTables[rCellRangeAddress.Sheet]); + rFormatRanges.push_back(aFormatRange); +} + +OUString & ScFormatRangeStyles::GetStyleNameByIndex(const sal_Int32 nIndex, const bool bIsAutoStyle) +{ + if (bIsAutoStyle) + return aAutoStyleNames[nIndex]; + else + return aStyleNames[nIndex]; +} + +void ScFormatRangeStyles::Sort() +{ + for (auto & rTable : aTables) + rTable.sort(); +} + +ScColumnRowStylesBase::ScColumnRowStylesBase() +{ +} + +ScColumnRowStylesBase::~ScColumnRowStylesBase() +{ +} + +sal_Int32 ScColumnRowStylesBase::AddStyleName(const OUString & rString) +{ + aStyleNames.push_back(rString); + return aStyleNames.size() - 1; +} + +sal_Int32 ScColumnRowStylesBase::GetIndexOfStyleName(std::u16string_view rString, const OUString& rPrefix) +{ + sal_Int32 nPrefixLength(rPrefix.getLength()); + std::u16string_view sTemp(rString.substr(nPrefixLength)); + sal_Int32 nIndex(o3tl::toInt32(sTemp)); + if (nIndex > 0 && o3tl::make_unsigned(nIndex-1) < aStyleNames.size() && aStyleNames.at(nIndex - 1) == rString) + return nIndex - 1; + else + { + sal_Int32 i(0); + bool bFound(false); + while (!bFound && o3tl::make_unsigned(i) < aStyleNames.size()) + { + if (aStyleNames.at(i) == rString) + bFound = true; + else + ++i; + } + if (bFound) + return i; + else + return -1; + } +} + +OUString& ScColumnRowStylesBase::GetStyleNameByIndex(const sal_Int32 nIndex) +{ + return aStyleNames[nIndex]; +} + +ScColumnStyles::ScColumnStyles() +{ +} + +ScColumnStyles::~ScColumnStyles() +{ +} + +void ScColumnStyles::AddNewTable(const sal_Int32 nTable, const sal_Int32 nFields) +{ + sal_Int32 nSize(aTables.size() - 1); + if (nTable > nSize) + for (sal_Int32 i = nSize; i < nTable; ++i) + { + ScMyColumnStyleVec aFieldsVec(nFields + 1, ScColumnStyle()); + aTables.push_back(aFieldsVec); + } +} + +sal_Int32 ScColumnStyles::GetStyleNameIndex(const sal_Int32 nTable, const sal_Int32 nField, + bool& bIsVisible) +{ + OSL_ENSURE(o3tl::make_unsigned(nTable) < aTables.size(), "wrong table"); + if (o3tl::make_unsigned(nField) < aTables[nTable].size()) + { + bIsVisible = aTables[nTable][nField].bIsVisible; + return aTables[nTable][nField].nIndex; + } + else + { + bIsVisible = aTables[nTable][aTables[nTable].size() - 1].bIsVisible; + return aTables[nTable][aTables[nTable].size() - 1].nIndex; + } +} + +void ScColumnStyles::AddFieldStyleName(const sal_Int32 nTable, const sal_Int32 nField, + const sal_Int32 nStringIndex, const bool bIsVisible) +{ + OSL_ENSURE(o3tl::make_unsigned(nTable) < aTables.size(), "wrong table"); + OSL_ENSURE(aTables[nTable].size() >= o3tl::make_unsigned(nField), "wrong field"); + ScColumnStyle aStyle; + aStyle.nIndex = nStringIndex; + aStyle.bIsVisible = bIsVisible; + if (aTables[nTable].size() == static_cast<sal_uInt32>(nField)) + aTables[nTable].push_back(aStyle); + aTables[nTable][nField] = aStyle; +} + +ScRowStyles::Cache::Cache() : + mnTable(-1), mnStart(-1), mnEnd(-1), mnStyle(-1) {} + +bool ScRowStyles::Cache::hasCache(sal_Int32 nTable, sal_Int32 nField) const +{ + return mnTable == nTable && mnStart <= nField && nField < mnEnd; +} + +ScRowStyles::ScRowStyles() +{ +} + +ScRowStyles::~ScRowStyles() +{ +} + +void ScRowStyles::AddNewTable(const sal_Int32 nTable, const sal_Int32 nFields) +{ + sal_Int32 nSize(aTables.size() - 1); + if (nTable > nSize) + for (sal_Int32 i = nSize; i < nTable; ++i) + { + aTables.push_back(std::make_unique<StylesType>(0, nFields+1, -1)); + } +} + +sal_Int32 ScRowStyles::GetStyleNameIndex(const sal_Int32 nTable, const sal_Int32 nField) +{ + OSL_ENSURE(o3tl::make_unsigned(nTable) < aTables.size(), "wrong table"); + if (o3tl::make_unsigned(nTable) >= aTables.size()) + return -1; + + if (maCache.hasCache(nTable, nField)) + // Cache hit ! + return maCache.mnStyle; + + StylesType& r = *aTables[nTable]; + if (!r.is_tree_valid()) + r.build_tree(); + sal_Int32 nStyle(0); + sal_Int32 nStart(0), nEnd(0); + if (r.search_tree(nField, nStyle, &nStart, &nEnd).second) + { + // Cache this value for better performance. + maCache.mnTable = nTable; + maCache.mnStart = nStart; + maCache.mnEnd = nEnd; + maCache.mnStyle = nStyle; + return nStyle; + } + + return -1; +} + +void ScRowStyles::AddFieldStyleName(const sal_Int32 nTable, const sal_Int32 nField, + const sal_Int32 nStringIndex) +{ + OSL_ENSURE(o3tl::make_unsigned(nTable) < aTables.size(), "wrong table"); + StylesType& r = *aTables[nTable]; + r.insert_back(nField, nField+1, nStringIndex); +} + +void ScRowStyles::AddFieldStyleName(const sal_Int32 nTable, const sal_Int32 nStartField, + const sal_Int32 nStringIndex, const sal_Int32 nEndField) +{ + OSL_ENSURE( nStartField <= nEndField, "bad field range"); + OSL_ENSURE(o3tl::make_unsigned(nTable) < aTables.size(), "wrong table"); + StylesType& r = *aTables[nTable]; + r.insert_back(nStartField, nEndField+1, nStringIndex); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |