summaryrefslogtreecommitdiffstats
path: root/sc/source/filter/lotus/tool.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/lotus/tool.cxx')
-rw-r--r--sc/source/filter/lotus/tool.cxx524
1 files changed, 524 insertions, 0 deletions
diff --git a/sc/source/filter/lotus/tool.cxx b/sc/source/filter/lotus/tool.cxx
new file mode 100644
index 000000000..c3bf46b4f
--- /dev/null
+++ b/sc/source/filter/lotus/tool.cxx
@@ -0,0 +1,524 @@
+/* -*- 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 <scitems.hxx>
+#include <editeng/justifyitem.hxx>
+#include <svl/numformat.hxx>
+#include <svl/zforlist.hxx>
+#include <sal/log.hxx>
+
+#include <attrib.hxx>
+#include <document.hxx>
+
+#include <tool.h>
+#include <lotrange.hxx>
+#include <namebuff.hxx>
+#include <stringutil.hxx>
+#include <tokenarray.hxx>
+#include "lotfilter.hxx"
+
+#include <math.h>
+
+void PutFormString(LotusContext& rContext, SCCOL nCol, SCROW nRow, SCTAB nTab, char* pString)
+{
+ // evaluate Label-Format
+ SAL_WARN_IF( pString == nullptr, "sc.filter", "PutFormString(): pString == NULL" );
+ if (!pString)
+ return;
+
+ char cForm;
+ SvxHorJustifyItem* pJustify = nullptr;
+
+ cForm = *pString;
+
+ switch( cForm )
+ {
+ case '"': // align-right
+ pJustify = rContext.xAttrRight.get();
+ pString++;
+ break;
+ case '\'': // align-left
+ pJustify = rContext.xAttrLeft.get();
+ pString++;
+ break;
+ case '^': // centered
+ pJustify = rContext.xAttrCenter.get();
+ pString++;
+ break;
+ case '|': // printer command
+ pString = nullptr;
+ break;
+ case '\\': // repetition
+ pJustify = rContext.xAttrRepeat.get();
+ pString++;
+ break;
+ default: // undefined case!
+ pJustify = rContext.xAttrStandard.get();
+ }
+
+ if (!pString)
+ return;
+
+ nCol = rContext.rDoc.SanitizeCol(nCol);
+ nRow = rContext.rDoc.SanitizeRow(nRow);
+ nTab = SanitizeTab(nTab);
+
+ rContext.rDoc.ApplyAttr( nCol, nRow, nTab, *pJustify );
+ ScSetStringParam aParam;
+ aParam.setTextInput();
+ rContext.rDoc.SetString(ScAddress(nCol,nRow,nTab), OUString(pString, strlen(pString), rContext.eCharset), &aParam);
+}
+
+void SetFormat(LotusContext& rContext, SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt8 nFormat, sal_uInt8 nSt)
+{
+ nCol = rContext.rDoc.SanitizeCol(nCol);
+ nRow = rContext.rDoc.SanitizeRow(nRow);
+ nTab = SanitizeTab(nTab);
+
+ // PREC: nSt = default number of decimal places
+ rContext.rDoc.ApplyAttr(nCol, nRow, nTab, *(rContext.xValueFormCache->GetAttr(nFormat, nSt)));
+
+ ScProtectionAttr aAttr;
+
+ aAttr.SetProtection( nFormat & 0x80 );
+
+ rContext.rDoc.ApplyAttr( nCol, nRow, nTab, aAttr );
+}
+
+double SnumToDouble( sal_Int16 nVal )
+{
+ const double pFacts[ 8 ] = {
+ 5000.0,
+ 500.0,
+ 0.05,
+ 0.005,
+ 0.0005,
+ 0.00005,
+ 0.0625,
+ 0.015625 };
+
+ double fVal;
+
+ if( nVal & 0x0001 )
+ {
+ fVal = pFacts[ ( nVal >> 1 ) & 0x0007 ];
+ fVal *= static_cast<sal_Int16>( nVal >> 4 );
+ }
+ else
+ fVal = static_cast<sal_Int16>( nVal >> 1 );
+
+ return fVal;
+}
+
+double Snum32ToDouble( sal_uInt32 nValue )
+{
+ double fValue, temp;
+
+ fValue = nValue >> 6;
+ temp = nValue & 0x0f;
+ if (temp)
+ {
+ if (nValue & 0x00000010)
+ fValue /= pow(double(10), temp);
+ else
+ fValue *= pow(double(10), temp);
+ }
+
+ if (nValue & 0x00000020)
+ fValue = -fValue;
+ return fValue;
+}
+
+FormCache::FormCache( const ScDocument* pDoc1 )
+ : nIndex(0)
+{
+ pFormTable = pDoc1->GetFormatTable();
+ for(bool & rb : bValid)
+ rb = false;
+ eLanguage = ScGlobal::eLnge;
+}
+
+FormCache::~FormCache()
+{
+}
+
+SfxUInt32Item* FormCache::NewAttr( sal_uInt8 nFormat, sal_uInt8 nSt )
+{
+ // setup new Format
+ sal_uInt8 nL, nH; // Low-/High-Nibble
+ OUString aFormString;
+ SvNumFormatType eType = SvNumFormatType::ALL;
+ sal_uInt32 nIndex1;
+ sal_uInt32 nHandle;
+ NfIndexTableOffset eIndexTableOffset = NF_NUMERIC_START;
+ bool bDefault = false;
+
+ // split into Low and High byte
+ nL = nFormat & 0x0F;
+ nH = ( nFormat & 0xF0 ) / 16;
+
+ nH &= 0x07; // extract bits 4-6
+ switch( nH )
+ {
+ case 0x00: // fixed-point number
+ //fStandard;nL;
+ nIndex1 = pFormTable->GetStandardFormat(
+ SvNumFormatType::NUMBER, eLanguage );
+ aFormString = pFormTable->GenerateFormat(nIndex1,
+ eLanguage, false, false, nL);
+ break;
+ case 0x01: // scientific notation
+ //fExponent;nL;
+ nIndex1 = pFormTable->GetStandardFormat(
+ SvNumFormatType::SCIENTIFIC, eLanguage );
+ aFormString = pFormTable->GenerateFormat(nIndex1,
+ eLanguage, false, false, nL);
+ break;
+ case 0x02: // currency
+ //fMoney;nL;
+ nIndex1 = pFormTable->GetStandardFormat(
+ SvNumFormatType::CURRENCY, eLanguage );
+ aFormString = pFormTable->GenerateFormat(nIndex1,
+ eLanguage, false, false, nL);
+ break;
+ case 0x03: // percentage
+ //fPercent;nL;
+ nIndex1 = pFormTable->GetStandardFormat(
+ SvNumFormatType::PERCENT, eLanguage );
+ aFormString = pFormTable->GenerateFormat(nIndex1,
+ eLanguage, false, false, nL);
+ break;
+ case 0x04: // Decimal
+ //fStandard;nL;
+ nIndex1 = pFormTable->GetStandardFormat(
+ SvNumFormatType::NUMBER, eLanguage );
+ aFormString = pFormTable->GenerateFormat(nIndex1,
+ eLanguage, true, false, nL);
+ break;
+ case 0x05: // unspecified
+ //fStandard;nL;
+ nIndex1 = pFormTable->GetStandardFormat(
+ SvNumFormatType::NUMBER, eLanguage );
+ aFormString = pFormTable->GenerateFormat(nIndex1,
+ eLanguage, false, false, nL);
+ break;
+ case 0x06: // unspecified
+ //fStandard;nL;
+ nIndex1 = pFormTable->GetStandardFormat(
+ SvNumFormatType::NUMBER, eLanguage );
+ aFormString = pFormTable->GenerateFormat(nIndex1,
+ eLanguage, false, false, nL);
+ break;
+ case 0x07: // Special format
+ switch( nL )
+ {
+ case 0x00: // +/-
+ //fStandard;nSt;
+ nIndex1 = pFormTable->GetStandardFormat(
+ SvNumFormatType::NUMBER, eLanguage );
+ aFormString = pFormTable->GenerateFormat(nIndex1,
+ eLanguage, false, true, nSt);
+ break;
+ case 0x01: // general Format
+ //fStandard;nSt;
+ nIndex1 = pFormTable->GetStandardFormat(
+ SvNumFormatType::NUMBER, eLanguage );
+ aFormString = pFormTable->GenerateFormat(nIndex1,
+ eLanguage, false, false, nSt);
+ break;
+ case 0x02: // Date: Day, Month, Year
+ //fDate;dfDayMonthYearLong;
+ eType = SvNumFormatType::DATE;
+ eIndexTableOffset = NF_DATE_SYS_DDMMYYYY;
+ break;
+ case 0x03: // Date: Day, Month
+ //fDate;dfDayMonthLong;
+ eType = SvNumFormatType::DATE;
+ aFormString = pFormTable->GetKeyword( eLanguage, NF_KEY_DD) +
+ pFormTable->GetDateSep() + // matches last eLanguage
+ pFormTable->GetKeyword( eLanguage, NF_KEY_MMMM);
+ break;
+ case 0x04: // Date: Month, Year
+ //fDate;dfMonthYearLong;
+ eType = SvNumFormatType::DATE;
+ aFormString = pFormTable->GetKeyword( eLanguage, NF_KEY_MM) +
+ pFormTable->GetDateSep() + // matches last eLanguage
+ pFormTable->GetKeyword( eLanguage, NF_KEY_YYYY);
+ break;
+ case 0x05: // Text formats
+ //fString;nSt;
+ eType = SvNumFormatType::TEXT;
+ eIndexTableOffset = NF_TEXT;
+ break;
+ case 0x06: // hidden
+ //wFlag |= paHideAll;bSetFormat = sal_False;
+ eType = SvNumFormatType::NUMBER;
+ aFormString = "\"\"";
+ break;
+ case 0x07: // Time: hour, min, sec
+ //fTime;tfHourMinSec24;
+ eType = SvNumFormatType::TIME;
+ eIndexTableOffset = NF_TIME_HHMMSS;
+ break;
+ case 0x08: // Time: hour, min
+ //fTime;tfHourMin24;
+ eType = SvNumFormatType::TIME;
+ eIndexTableOffset = NF_TIME_HHMM;
+ break;
+ case 0x09: // Date, intern sal_Int32 1
+ //fDate;dfDayMonthYearLong;
+ eType = SvNumFormatType::DATE;
+ eIndexTableOffset = NF_DATE_SYS_DDMMYYYY;
+ break;
+ case 0x0A: // Date, intern sal_Int32 2
+ //fDate;dfDayMonthYearLong;
+ eType = SvNumFormatType::DATE;
+ eIndexTableOffset = NF_DATE_SYS_DDMMYYYY;
+ break;
+ case 0x0B: // Time, intern sal_Int32 1
+ //fTime;tfHourMinSec24;
+ eType = SvNumFormatType::TIME;
+ eIndexTableOffset = NF_TIME_HHMMSS;
+ break;
+ case 0x0C: // Time, intern sal_Int32 2
+ //fTime;tfHourMinSec24;
+ eType = SvNumFormatType::TIME;
+ eIndexTableOffset = NF_TIME_HHMMSS;
+ break;
+ case 0x0F: // Default
+ //fStandard;nSt;
+ bDefault = true;
+ break;
+ default:
+ //fStandard;nSt;
+ bDefault = true;
+ break;
+ }
+ break;
+ }
+
+ // push Format into table
+ if( bDefault )
+ nHandle = 0;
+ else if (eIndexTableOffset != NF_NUMERIC_START)
+ nHandle = pFormTable->GetFormatIndex( eIndexTableOffset, eLanguage);
+ else
+ {
+ sal_Int32 nDummy;
+ pFormTable->PutEntry( aFormString, nDummy, eType, nHandle, eLanguage );
+ }
+
+ return new SfxUInt32Item( ATTR_VALUE_FORMAT, nHandle );
+}
+
+void LotusRange::MakeHash()
+{
+ // 33222222222211111111110000000000
+ // 10987654321098765432109876543210
+ // ******** nColS
+ // ******** nColE
+ // **************** nRowS
+ // **************** nRowE
+ nHash = static_cast<sal_uInt32>(nColStart);
+ nHash += static_cast<sal_uInt32>(nColEnd) << 6;
+ nHash += static_cast<sal_uInt32>(nRowStart) << 12;
+ nHash += static_cast<sal_uInt32>(nRowEnd ) << 16;
+}
+
+LotusRange::LotusRange( SCCOL nCol, SCROW nRow )
+{
+ nColStart = nColEnd = nCol;
+ nRowStart = nRowEnd = nRow;
+ nId = ID_FAIL;
+ MakeHash();
+}
+
+LotusRange::LotusRange( SCCOL nCS, SCROW nRS, SCCOL nCE, SCROW nRE )
+{
+ nColStart = nCS;
+ nColEnd = nCE;
+ nRowStart = nRS;
+ nRowEnd = nRE;
+ nId = ID_FAIL;
+ MakeHash();
+}
+
+LotusRange::LotusRange( const LotusRange& rCpy )
+{
+ Copy( rCpy );
+}
+
+LotusRangeList::LotusRangeList()
+{
+ aComplRef.InitFlags();
+
+ ScSingleRefData* pSingRef;
+ nIdCnt = 1;
+
+ pSingRef = &aComplRef.Ref1;
+ pSingRef->SetRelTab(0);
+ pSingRef->SetColRel( false );
+ pSingRef->SetRowRel( false );
+ pSingRef->SetFlag3D( false );
+
+ pSingRef = &aComplRef.Ref2;
+ pSingRef->SetRelTab(0);
+ pSingRef->SetColRel( false );
+ pSingRef->SetRowRel( false );
+ pSingRef->SetFlag3D( false );
+}
+
+LotusRangeList::~LotusRangeList ()
+{
+}
+
+LR_ID LotusRangeList::GetIndex( const LotusRange &rRef )
+{
+ auto pIter = std::find_if(maRanges.begin(), maRanges.end(),
+ [&rRef](const std::unique_ptr<LotusRange>& pRange) { return rRef == *pRange; });
+ if (pIter != maRanges.end())
+ return (*pIter)->nId;
+
+ return ID_FAIL;
+}
+
+void LotusRangeList::Append( const ScDocument* pDoc, std::unique_ptr<LotusRange> pLR )
+{
+ assert( pLR );
+ auto pLRTmp = pLR.get();
+ maRanges.push_back(std::move(pLR));
+
+ ScTokenArray aTokArray(*pDoc);
+
+ ScSingleRefData* pSingRef = &aComplRef.Ref1;
+
+ pSingRef->SetAbsCol(pLRTmp->nColStart);
+ pSingRef->SetAbsRow(pLRTmp->nRowStart);
+
+ if( pLRTmp->IsSingle() )
+ aTokArray.AddSingleReference( *pSingRef );
+ else
+ {
+ pSingRef = &aComplRef.Ref2;
+ pSingRef->SetAbsCol(pLRTmp->nColEnd);
+ pSingRef->SetAbsRow(pLRTmp->nRowEnd);
+ aTokArray.AddDoubleReference( aComplRef );
+ }
+
+ pLRTmp->SetId( nIdCnt );
+
+ nIdCnt++;
+}
+
+RangeNameBufferWK3::RangeNameBufferWK3(const ScDocument& rDoc)
+ : pScTokenArray( new ScTokenArray(rDoc) )
+{
+ nIntCount = 1;
+}
+
+RangeNameBufferWK3::~RangeNameBufferWK3()
+{
+}
+
+void RangeNameBufferWK3::Add( const ScDocument& rDoc, const OUString& rOrgName, const ScComplexRefData& rCRD )
+{
+ Entry aInsert( rOrgName, rCRD );
+
+ pScTokenArray->Clear();
+
+ const ScSingleRefData& rRef1 = rCRD.Ref1;
+ const ScSingleRefData& rRef2 = rCRD.Ref2;
+ ScAddress aAbs1 = rRef1.toAbs(rDoc, ScAddress());
+ ScAddress aAbs2 = rRef2.toAbs(rDoc, ScAddress());
+ if (aAbs1 == aAbs2)
+ {
+ pScTokenArray->AddSingleReference( rCRD.Ref1 );
+ aInsert.bSingleRef = true;
+ }
+ else
+ {
+ pScTokenArray->AddDoubleReference( rCRD );
+ aInsert.bSingleRef = false;
+ }
+
+ aInsert.nRelInd = nIntCount;
+ nIntCount++;
+
+ maEntries.push_back( aInsert );
+}
+
+bool RangeNameBufferWK3::FindRel( const OUString& rRef, sal_uInt16& rIndex )
+{
+ StringHashEntry aRef( rRef );
+
+ std::vector<Entry>::const_iterator itr = std::find_if(maEntries.begin(), maEntries.end(),
+ [&aRef](const Entry& rEntry) { return aRef == rEntry.aStrHashEntry; });
+ if (itr != maEntries.end())
+ {
+ rIndex = itr->nRelInd;
+ return true;
+ }
+
+ return false;
+}
+
+bool RangeNameBufferWK3::FindAbs( std::u16string_view rRef, sal_uInt16& rIndex )
+{
+ if (rRef.empty())
+ return false;
+ StringHashEntry aRef(OUString(rRef.substr(1))); // search w/o '$'!
+
+ std::vector<Entry>::iterator itr = std::find_if(maEntries.begin(), maEntries.end(),
+ [&aRef](const Entry& rEntry) { return aRef == rEntry.aStrHashEntry; });
+ if (itr != maEntries.end())
+ {
+ // setup new range if needed
+ if( itr->nAbsInd )
+ rIndex = itr->nAbsInd;
+ else
+ {
+ ScSingleRefData* pRef = &itr->aScComplexRefDataRel.Ref1;
+ pScTokenArray->Clear();
+
+ pRef->SetColRel( false );
+ pRef->SetRowRel( false );
+ pRef->SetTabRel( true );
+
+ if( itr->bSingleRef )
+ pScTokenArray->AddSingleReference( *pRef );
+ else
+ {
+ pRef = &itr->aScComplexRefDataRel.Ref2;
+ pRef->SetColRel( false );
+ pRef->SetRowRel( false );
+ pRef->SetTabRel( true );
+ pScTokenArray->AddDoubleReference( itr->aScComplexRefDataRel );
+ }
+
+ rIndex = itr->nAbsInd = nIntCount;
+ nIntCount++;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */