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