Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / lotus / tool.cxx
blob5c5d307198a3b0775fd11300a45d1e9904fa11e5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <scitems.hxx>
21 #include <editeng/justifyitem.hxx>
22 #include <svl/zforlist.hxx>
23 #include <sal/log.hxx>
25 #include <attrib.hxx>
26 #include <document.hxx>
28 #include <tool.h>
29 #include <root.hxx>
30 #include <lotrange.hxx>
31 #include <namebuff.hxx>
32 #include <stringutil.hxx>
33 #include <tokenarray.hxx>
34 #include "lotfilter.hxx"
36 #include <math.h>
38 void PutFormString(LotusContext& rContext, SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Char* pString)
40 // evaluate Label-Format
41 SAL_WARN_IF( pString == nullptr, "sc.filter", "PutFormString(): pString == NULL" );
42 if (!pString)
43 return;
45 sal_Char cForm;
46 SvxHorJustifyItem* pJustify = nullptr;
48 cForm = *pString;
50 switch( cForm )
52 case '"': // align-right
53 pJustify = rContext.pAttrRight;
54 pString++;
55 break;
56 case '\'': // align-left
57 pJustify = rContext.pAttrLeft;
58 pString++;
59 break;
60 case '^': // centered
61 pJustify = rContext.pAttrCenter;
62 pString++;
63 break;
64 case '|': // printer command
65 pString = nullptr;
66 break;
67 case '\\': // repetition
68 pJustify = rContext.pAttrRepeat;
69 pString++;
70 break;
71 default: // undefined case!
72 pJustify = rContext.pAttrStandard;
75 if (!pString)
76 return;
78 nCol = SanitizeCol(nCol);
79 nRow = SanitizeRow(nRow);
80 nTab = SanitizeTab(nTab);
82 rContext.pDoc->ApplyAttr( nCol, nRow, nTab, *pJustify );
83 ScSetStringParam aParam;
84 aParam.setTextInput();
85 rContext.pDoc->SetString(ScAddress(nCol,nRow,nTab), OUString(pString, strlen(pString), rContext.pLotusRoot->eCharsetQ), &aParam);
88 void SetFormat(LotusContext& rContext, SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt8 nFormat, sal_uInt8 nSt)
90 nCol = SanitizeCol(nCol);
91 nRow = SanitizeRow(nRow);
92 nTab = SanitizeTab(nTab);
94 // PREC: nSt = default number of decimal places
95 rContext.pDoc->ApplyAttr(nCol, nRow, nTab, *(rContext.pValueFormCache->GetAttr(nFormat, nSt)));
97 ScProtectionAttr aAttr;
99 aAttr.SetProtection( nFormat & 0x80 );
101 rContext.pDoc->ApplyAttr( nCol, nRow, nTab, aAttr );
104 double SnumToDouble( sal_Int16 nVal )
106 const double pFacts[ 8 ] = {
107 5000.0,
108 500.0,
109 0.05,
110 0.005,
111 0.0005,
112 0.00005,
113 0.0625,
114 0.015625 };
116 double fVal;
118 if( nVal & 0x0001 )
120 fVal = pFacts[ ( nVal >> 1 ) & 0x0007 ];
121 fVal *= static_cast<sal_Int16>( nVal >> 4 );
123 else
124 fVal = static_cast<sal_Int16>( nVal >> 1 );
126 return fVal;
129 double Snum32ToDouble( sal_uInt32 nValue )
131 double fValue, temp;
133 fValue = nValue >> 6;
134 temp = nValue & 0x0f;
135 if (temp)
137 if (nValue & 0x00000010)
138 fValue /= pow(double(10), temp);
139 else
140 fValue *= pow(double(10), temp);
143 if (nValue & 0x00000020)
144 fValue = -fValue;
145 return fValue;
148 FormCache::FormCache( const ScDocument* pDoc1 )
149 : nIndex(0)
151 pFormTable = pDoc1->GetFormatTable();
152 for(bool & rb : bValid)
153 rb = false;
154 eLanguage = ScGlobal::eLnge;
157 FormCache::~FormCache()
161 SfxUInt32Item* FormCache::NewAttr( sal_uInt8 nFormat, sal_uInt8 nSt )
163 // setup new Format
164 sal_uInt8 nL, nH; // Low-/High-Nibble
165 OUString aFormString;
166 SvNumFormatType eType = SvNumFormatType::ALL;
167 sal_uInt32 nIndex1;
168 sal_uInt32 nHandle;
169 NfIndexTableOffset eIndexTableOffset = NF_NUMERIC_START;
170 bool bDefault = false;
172 // split into Low and High byte
173 nL = nFormat & 0x0F;
174 nH = ( nFormat & 0xF0 ) / 16;
176 nH &= 0x07; // extract bits 4-6
177 switch( nH )
179 case 0x00: // fixed-point number
180 //fStandard;nL;
181 nIndex1 = pFormTable->GetStandardFormat(
182 SvNumFormatType::NUMBER, eLanguage );
183 aFormString = pFormTable->GenerateFormat(nIndex1,
184 eLanguage, false, false, nL);
185 break;
186 case 0x01: // scientific notation
187 //fExponent;nL;
188 nIndex1 = pFormTable->GetStandardFormat(
189 SvNumFormatType::SCIENTIFIC, eLanguage );
190 aFormString = pFormTable->GenerateFormat(nIndex1,
191 eLanguage, false, false, nL);
192 break;
193 case 0x02: // currency
194 //fMoney;nL;
195 nIndex1 = pFormTable->GetStandardFormat(
196 SvNumFormatType::CURRENCY, eLanguage );
197 aFormString = pFormTable->GenerateFormat(nIndex1,
198 eLanguage, false, false, nL);
199 break;
200 case 0x03: // percentage
201 //fPercent;nL;
202 nIndex1 = pFormTable->GetStandardFormat(
203 SvNumFormatType::PERCENT, eLanguage );
204 aFormString = pFormTable->GenerateFormat(nIndex1,
205 eLanguage, false, false, nL);
206 break;
207 case 0x04: // Decimal
208 //fStandard;nL;
209 nIndex1 = pFormTable->GetStandardFormat(
210 SvNumFormatType::NUMBER, eLanguage );
211 aFormString = pFormTable->GenerateFormat(nIndex1,
212 eLanguage, true, false, nL);
213 break;
214 case 0x05: // unspecified
215 //fStandard;nL;
216 nIndex1 = pFormTable->GetStandardFormat(
217 SvNumFormatType::NUMBER, eLanguage );
218 aFormString = pFormTable->GenerateFormat(nIndex1,
219 eLanguage, false, false, nL);
220 break;
221 case 0x06: // unspecified
222 //fStandard;nL;
223 nIndex1 = pFormTable->GetStandardFormat(
224 SvNumFormatType::NUMBER, eLanguage );
225 aFormString = pFormTable->GenerateFormat(nIndex1,
226 eLanguage, false, false, nL);
227 break;
228 case 0x07: // Special format
229 switch( nL )
231 case 0x00: // +/-
232 //fStandard;nSt;
233 nIndex1 = pFormTable->GetStandardFormat(
234 SvNumFormatType::NUMBER, eLanguage );
235 aFormString = pFormTable->GenerateFormat(nIndex1,
236 eLanguage, false, true, nSt);
237 break;
238 case 0x01: // general Format
239 //fStandard;nSt;
240 nIndex1 = pFormTable->GetStandardFormat(
241 SvNumFormatType::NUMBER, eLanguage );
242 aFormString = pFormTable->GenerateFormat(nIndex1,
243 eLanguage, false, false, nSt);
244 break;
245 case 0x02: // Date: Day, Month, Year
246 //fDate;dfDayMonthYearLong;
247 eType = SvNumFormatType::DATE;
248 eIndexTableOffset = NF_DATE_SYS_DDMMYYYY;
249 break;
250 case 0x03: // Date: Day, Month
251 //fDate;dfDayMonthLong;
252 eType = SvNumFormatType::DATE;
253 aFormString = pFormTable->GetKeyword( eLanguage, NF_KEY_DD) +
254 pFormTable->GetDateSep() + // matches last eLanguage
255 pFormTable->GetKeyword( eLanguage, NF_KEY_MMMM);
256 break;
257 case 0x04: // Date: Month, Year
258 //fDate;dfMonthYearLong;
259 eType = SvNumFormatType::DATE;
260 aFormString = pFormTable->GetKeyword( eLanguage, NF_KEY_MM) +
261 pFormTable->GetDateSep() + // matches last eLanguage
262 pFormTable->GetKeyword( eLanguage, NF_KEY_YYYY);
263 break;
264 case 0x05: // Text formats
265 //fString;nSt;
266 eType = SvNumFormatType::TEXT;
267 eIndexTableOffset = NF_TEXT;
268 break;
269 case 0x06: // hidden
270 //wFlag |= paHideAll;bSetFormat = sal_False;
271 eType = SvNumFormatType::NUMBER;
272 aFormString = "\"\"";
273 break;
274 case 0x07: // Time: hour, min, sec
275 //fTime;tfHourMinSec24;
276 eType = SvNumFormatType::TIME;
277 eIndexTableOffset = NF_TIME_HHMMSS;
278 break;
279 case 0x08: // Time: hour, min
280 //fTime;tfHourMin24;
281 eType = SvNumFormatType::TIME;
282 eIndexTableOffset = NF_TIME_HHMM;
283 break;
284 case 0x09: // Date, intern sal_Int32 1
285 //fDate;dfDayMonthYearLong;
286 eType = SvNumFormatType::DATE;
287 eIndexTableOffset = NF_DATE_SYS_DDMMYYYY;
288 break;
289 case 0x0A: // Date, intern sal_Int32 2
290 //fDate;dfDayMonthYearLong;
291 eType = SvNumFormatType::DATE;
292 eIndexTableOffset = NF_DATE_SYS_DDMMYYYY;
293 break;
294 case 0x0B: // Time, intern sal_Int32 1
295 //fTime;tfHourMinSec24;
296 eType = SvNumFormatType::TIME;
297 eIndexTableOffset = NF_TIME_HHMMSS;
298 break;
299 case 0x0C: // Time, intern sal_Int32 2
300 //fTime;tfHourMinSec24;
301 eType = SvNumFormatType::TIME;
302 eIndexTableOffset = NF_TIME_HHMMSS;
303 break;
304 case 0x0F: // Default
305 //fStandard;nSt;
306 bDefault = true;
307 break;
308 default:
309 //fStandard;nSt;
310 bDefault = true;
311 break;
313 break;
316 // push Format into table
317 if( bDefault )
318 nHandle = 0;
319 else if (eIndexTableOffset != NF_NUMERIC_START)
320 nHandle = pFormTable->GetFormatIndex( eIndexTableOffset, eLanguage);
321 else
323 sal_Int32 nDummy;
324 pFormTable->PutEntry( aFormString, nDummy, eType, nHandle, eLanguage );
327 return new SfxUInt32Item( ATTR_VALUE_FORMAT, nHandle );
330 void LotusRange::MakeHash()
332 // 33222222222211111111110000000000
333 // 10987654321098765432109876543210
334 // ******** nColS
335 // ******** nColE
336 // **************** nRowS
337 // **************** nRowE
338 nHash = static_cast<sal_uInt32>(nColStart);
339 nHash += static_cast<sal_uInt32>(nColEnd) << 6;
340 nHash += static_cast<sal_uInt32>(nRowStart) << 12;
341 nHash += static_cast<sal_uInt32>(nRowEnd ) << 16;
344 LotusRange::LotusRange( SCCOL nCol, SCROW nRow )
346 nColStart = nColEnd = nCol;
347 nRowStart = nRowEnd = nRow;
348 nId = ID_FAIL;
349 MakeHash();
352 LotusRange::LotusRange( SCCOL nCS, SCROW nRS, SCCOL nCE, SCROW nRE )
354 nColStart = nCS;
355 nColEnd = nCE;
356 nRowStart = nRS;
357 nRowEnd = nRE;
358 nId = ID_FAIL;
359 MakeHash();
362 LotusRange::LotusRange( const LotusRange& rCpy )
364 Copy( rCpy );
367 LotusRangeList::LotusRangeList()
369 aComplRef.InitFlags();
371 ScSingleRefData* pSingRef;
372 nIdCnt = 1;
374 pSingRef = &aComplRef.Ref1;
375 pSingRef->SetRelTab(0);
376 pSingRef->SetColRel( false );
377 pSingRef->SetRowRel( false );
378 pSingRef->SetFlag3D( false );
380 pSingRef = &aComplRef.Ref2;
381 pSingRef->SetRelTab(0);
382 pSingRef->SetColRel( false );
383 pSingRef->SetRowRel( false );
384 pSingRef->SetFlag3D( false );
387 LotusRangeList::~LotusRangeList ()
391 LR_ID LotusRangeList::GetIndex( const LotusRange &rRef )
393 auto pIter = std::find_if(maRanges.begin(), maRanges.end(),
394 [&rRef](const std::unique_ptr<LotusRange>& pRange) { return rRef == *pRange; });
395 if (pIter != maRanges.end())
396 return (*pIter)->nId;
398 return ID_FAIL;
401 void LotusRangeList::Append( std::unique_ptr<LotusRange> pLR )
403 assert( pLR );
404 auto pLRTmp = pLR.get();
405 maRanges.push_back(std::move(pLR));
407 ScTokenArray aTokArray;
409 ScSingleRefData* pSingRef = &aComplRef.Ref1;
411 pSingRef->SetAbsCol(pLRTmp->nColStart);
412 pSingRef->SetAbsRow(pLRTmp->nRowStart);
414 if( pLRTmp->IsSingle() )
415 aTokArray.AddSingleReference( *pSingRef );
416 else
418 pSingRef = &aComplRef.Ref2;
419 pSingRef->SetAbsCol(pLRTmp->nColEnd);
420 pSingRef->SetAbsRow(pLRTmp->nRowEnd);
421 aTokArray.AddDoubleReference( aComplRef );
424 pLRTmp->SetId( nIdCnt );
426 nIdCnt++;
429 RangeNameBufferWK3::RangeNameBufferWK3()
430 : pScTokenArray( new ScTokenArray )
432 nIntCount = 1;
435 RangeNameBufferWK3::~RangeNameBufferWK3()
439 void RangeNameBufferWK3::Add( const OUString& rOrgName, const ScComplexRefData& rCRD )
441 Entry aInsert( rOrgName, rCRD );
443 pScTokenArray->Clear();
445 const ScSingleRefData& rRef1 = rCRD.Ref1;
446 const ScSingleRefData& rRef2 = rCRD.Ref2;
447 ScAddress aAbs1 = rRef1.toAbs(ScAddress());
448 ScAddress aAbs2 = rRef2.toAbs(ScAddress());
449 if (aAbs1 == aAbs2)
451 pScTokenArray->AddSingleReference( rCRD.Ref1 );
452 aInsert.bSingleRef = true;
454 else
456 pScTokenArray->AddDoubleReference( rCRD );
457 aInsert.bSingleRef = false;
460 aInsert.nRelInd = nIntCount;
461 nIntCount++;
463 maEntries.push_back( aInsert );
466 bool RangeNameBufferWK3::FindRel( const OUString& rRef, sal_uInt16& rIndex )
468 StringHashEntry aRef( rRef );
470 std::vector<Entry>::const_iterator itr = std::find_if(maEntries.begin(), maEntries.end(),
471 [&aRef](const Entry& rEntry) { return aRef == rEntry.aStrHashEntry; });
472 if (itr != maEntries.end())
474 rIndex = itr->nRelInd;
475 return true;
478 return false;
481 bool RangeNameBufferWK3::FindAbs( const OUString& rRef, sal_uInt16& rIndex )
483 if (rRef.isEmpty())
484 return false;
485 StringHashEntry aRef(rRef.copy(1)); // search w/o '$'!
487 std::vector<Entry>::iterator itr = std::find_if(maEntries.begin(), maEntries.end(),
488 [&aRef](const Entry& rEntry) { return aRef == rEntry.aStrHashEntry; });
489 if (itr != maEntries.end())
491 // setup new range if needed
492 if( itr->nAbsInd )
493 rIndex = itr->nAbsInd;
494 else
496 ScSingleRefData* pRef = &itr->aScComplexRefDataRel.Ref1;
497 pScTokenArray->Clear();
499 pRef->SetColRel( false );
500 pRef->SetRowRel( false );
501 pRef->SetTabRel( true );
503 if( itr->bSingleRef )
504 pScTokenArray->AddSingleReference( *pRef );
505 else
507 pRef = &itr->aScComplexRefDataRel.Ref2;
508 pRef->SetColRel( false );
509 pRef->SetRowRel( false );
510 pRef->SetTabRel( true );
511 pScTokenArray->AddDoubleReference( itr->aScComplexRefDataRel );
514 rIndex = itr->nAbsInd = nIntCount;
515 nIntCount++;
518 return true;
521 return false;
524 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */