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