1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/numformat.hxx>
23 #include <svl/zforlist.hxx>
24 #include <sal/log.hxx>
27 #include <document.hxx>
30 #include <lotrange.hxx>
31 #include <namebuff.hxx>
32 #include <stringutil.hxx>
33 #include <tokenarray.hxx>
34 #include "lotfilter.hxx"
38 void PutFormString(LotusContext
& rContext
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
, char* pString
)
40 // evaluate Label-Format
41 SAL_WARN_IF( pString
== nullptr, "sc.filter", "PutFormString(): pString == NULL" );
46 SvxHorJustifyItem
* pJustify
= nullptr;
52 case '"': // align-right
53 pJustify
= rContext
.xAttrRight
.get();
56 case '\'': // align-left
57 pJustify
= rContext
.xAttrLeft
.get();
61 pJustify
= rContext
.xAttrCenter
.get();
64 case '|': // printer command
67 case '\\': // repetition
68 pJustify
= rContext
.xAttrRepeat
.get();
71 default: // undefined case!
72 pJustify
= rContext
.xAttrStandard
.get();
78 nCol
= rContext
.rDoc
.SanitizeCol(nCol
);
79 nRow
= rContext
.rDoc
.SanitizeRow(nRow
);
80 nTab
= SanitizeTab(nTab
);
82 rContext
.rDoc
.ApplyAttr( nCol
, nRow
, nTab
, *pJustify
);
83 ScSetStringParam aParam
;
84 aParam
.setTextInput();
85 rContext
.rDoc
.SetString(ScAddress(nCol
,nRow
,nTab
), OUString(pString
, strlen(pString
), rContext
.eCharset
), &aParam
);
88 void SetFormat(LotusContext
& rContext
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
, sal_uInt8 nFormat
, sal_uInt8 nSt
)
90 nCol
= rContext
.rDoc
.SanitizeCol(nCol
);
91 nRow
= rContext
.rDoc
.SanitizeRow(nRow
);
92 nTab
= SanitizeTab(nTab
);
94 // PREC: nSt = default number of decimal places
95 rContext
.rDoc
.ApplyAttr(nCol
, nRow
, nTab
, *(rContext
.xValueFormCache
->GetAttr(nFormat
, nSt
)));
97 ScProtectionAttr aAttr
;
99 aAttr
.SetProtection( nFormat
& 0x80 );
101 rContext
.rDoc
.ApplyAttr( nCol
, nRow
, nTab
, aAttr
);
104 double SnumToDouble( sal_Int16 nVal
)
106 const double pFacts
[ 8 ] = {
120 fVal
= pFacts
[ ( nVal
>> 1 ) & 0x0007 ];
121 fVal
*= static_cast<sal_Int16
>( nVal
>> 4 );
124 fVal
= static_cast<sal_Int16
>( nVal
>> 1 );
129 double Snum32ToDouble( sal_uInt32 nValue
)
133 fValue
= nValue
>> 6;
134 temp
= nValue
& 0x0f;
137 if (nValue
& 0x00000010)
138 fValue
/= pow(double(10), temp
);
140 fValue
*= pow(double(10), temp
);
143 if (nValue
& 0x00000020)
148 FormCache::FormCache( const ScDocument
* pDoc1
)
151 pFormTable
= pDoc1
->GetFormatTable();
152 for(bool & rb
: bValid
)
154 eLanguage
= ScGlobal::eLnge
;
157 FormCache::~FormCache()
161 SfxUInt32Item
* FormCache::NewAttr( sal_uInt8 nFormat
, sal_uInt8 nSt
)
164 sal_uInt8 nL
, nH
; // Low-/High-Nibble
165 OUString aFormString
;
166 SvNumFormatType eType
= SvNumFormatType::ALL
;
169 NfIndexTableOffset eIndexTableOffset
= NF_NUMERIC_START
;
170 bool bDefault
= false;
172 // split into Low and High byte
174 nH
= ( nFormat
& 0xF0 ) / 16;
176 nH
&= 0x07; // extract bits 4-6
179 case 0x00: // fixed-point number
181 nIndex1
= pFormTable
->GetStandardFormat(
182 SvNumFormatType::NUMBER
, eLanguage
);
183 aFormString
= pFormTable
->GenerateFormat(nIndex1
,
184 eLanguage
, false, false, nL
);
186 case 0x01: // scientific notation
188 nIndex1
= pFormTable
->GetStandardFormat(
189 SvNumFormatType::SCIENTIFIC
, eLanguage
);
190 aFormString
= pFormTable
->GenerateFormat(nIndex1
,
191 eLanguage
, false, false, nL
);
193 case 0x02: // currency
195 nIndex1
= pFormTable
->GetStandardFormat(
196 SvNumFormatType::CURRENCY
, eLanguage
);
197 aFormString
= pFormTable
->GenerateFormat(nIndex1
,
198 eLanguage
, false, false, nL
);
200 case 0x03: // percentage
202 nIndex1
= pFormTable
->GetStandardFormat(
203 SvNumFormatType::PERCENT
, eLanguage
);
204 aFormString
= pFormTable
->GenerateFormat(nIndex1
,
205 eLanguage
, false, false, nL
);
207 case 0x04: // Decimal
209 nIndex1
= pFormTable
->GetStandardFormat(
210 SvNumFormatType::NUMBER
, eLanguage
);
211 aFormString
= pFormTable
->GenerateFormat(nIndex1
,
212 eLanguage
, true, false, nL
);
214 case 0x05: // unspecified
216 nIndex1
= pFormTable
->GetStandardFormat(
217 SvNumFormatType::NUMBER
, eLanguage
);
218 aFormString
= pFormTable
->GenerateFormat(nIndex1
,
219 eLanguage
, false, false, nL
);
221 case 0x06: // unspecified
223 nIndex1
= pFormTable
->GetStandardFormat(
224 SvNumFormatType::NUMBER
, eLanguage
);
225 aFormString
= pFormTable
->GenerateFormat(nIndex1
,
226 eLanguage
, false, false, nL
);
228 case 0x07: // Special format
233 nIndex1
= pFormTable
->GetStandardFormat(
234 SvNumFormatType::NUMBER
, eLanguage
);
235 aFormString
= pFormTable
->GenerateFormat(nIndex1
,
236 eLanguage
, false, true, nSt
);
238 case 0x01: // general Format
240 nIndex1
= pFormTable
->GetStandardFormat(
241 SvNumFormatType::NUMBER
, eLanguage
);
242 aFormString
= pFormTable
->GenerateFormat(nIndex1
,
243 eLanguage
, false, false, nSt
);
245 case 0x02: // Date: Day, Month, Year
246 //fDate;dfDayMonthYearLong;
247 eType
= SvNumFormatType::DATE
;
248 eIndexTableOffset
= NF_DATE_SYS_DDMMYYYY
;
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
);
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
);
264 case 0x05: // Text formats
266 eType
= SvNumFormatType::TEXT
;
267 eIndexTableOffset
= NF_TEXT
;
270 //wFlag |= paHideAll;bSetFormat = sal_False;
271 eType
= SvNumFormatType::NUMBER
;
272 aFormString
= "\"\"";
274 case 0x07: // Time: hour, min, sec
275 //fTime;tfHourMinSec24;
276 eType
= SvNumFormatType::TIME
;
277 eIndexTableOffset
= NF_TIME_HHMMSS
;
279 case 0x08: // Time: hour, min
281 eType
= SvNumFormatType::TIME
;
282 eIndexTableOffset
= NF_TIME_HHMM
;
284 case 0x09: // Date, intern sal_Int32 1
285 //fDate;dfDayMonthYearLong;
286 eType
= SvNumFormatType::DATE
;
287 eIndexTableOffset
= NF_DATE_SYS_DDMMYYYY
;
289 case 0x0A: // Date, intern sal_Int32 2
290 //fDate;dfDayMonthYearLong;
291 eType
= SvNumFormatType::DATE
;
292 eIndexTableOffset
= NF_DATE_SYS_DDMMYYYY
;
294 case 0x0B: // Time, intern sal_Int32 1
295 //fTime;tfHourMinSec24;
296 eType
= SvNumFormatType::TIME
;
297 eIndexTableOffset
= NF_TIME_HHMMSS
;
299 case 0x0C: // Time, intern sal_Int32 2
300 //fTime;tfHourMinSec24;
301 eType
= SvNumFormatType::TIME
;
302 eIndexTableOffset
= NF_TIME_HHMMSS
;
304 case 0x0F: // Default
316 // push Format into table
319 else if (eIndexTableOffset
!= NF_NUMERIC_START
)
320 nHandle
= pFormTable
->GetFormatIndex( eIndexTableOffset
, eLanguage
);
324 pFormTable
->PutEntry( aFormString
, nDummy
, eType
, nHandle
, eLanguage
);
327 return new SfxUInt32Item( ATTR_VALUE_FORMAT
, nHandle
);
330 void LotusRange::MakeHash()
332 // 33222222222211111111110000000000
333 // 10987654321098765432109876543210
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
;
352 LotusRange::LotusRange( SCCOL nCS
, SCROW nRS
, SCCOL nCE
, SCROW nRE
)
362 LotusRange::LotusRange( const LotusRange
& rCpy
)
367 LotusRangeList::LotusRangeList()
369 aComplRef
.InitFlags();
371 ScSingleRefData
* pSingRef
;
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
;
401 void LotusRangeList::Append( const ScDocument
* pDoc
, std::unique_ptr
<LotusRange
> pLR
)
404 auto pLRTmp
= pLR
.get();
405 maRanges
.push_back(std::move(pLR
));
407 ScTokenArray
aTokArray(*pDoc
);
409 ScSingleRefData
* pSingRef
= &aComplRef
.Ref1
;
411 pSingRef
->SetAbsCol(pLRTmp
->nColStart
);
412 pSingRef
->SetAbsRow(pLRTmp
->nRowStart
);
414 if( pLRTmp
->IsSingle() )
415 aTokArray
.AddSingleReference( *pSingRef
);
418 pSingRef
= &aComplRef
.Ref2
;
419 pSingRef
->SetAbsCol(pLRTmp
->nColEnd
);
420 pSingRef
->SetAbsRow(pLRTmp
->nRowEnd
);
421 aTokArray
.AddDoubleReference( aComplRef
);
424 pLRTmp
->SetId( nIdCnt
);
429 RangeNameBufferWK3::RangeNameBufferWK3(const ScDocument
& rDoc
)
430 : pScTokenArray( new ScTokenArray(rDoc
) )
435 RangeNameBufferWK3::~RangeNameBufferWK3()
439 void RangeNameBufferWK3::Add( const ScDocument
& rDoc
, 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(rDoc
, ScAddress());
448 ScAddress aAbs2
= rRef2
.toAbs(rDoc
, ScAddress());
451 pScTokenArray
->AddSingleReference( rCRD
.Ref1
);
452 aInsert
.bSingleRef
= true;
456 pScTokenArray
->AddDoubleReference( rCRD
);
457 aInsert
.bSingleRef
= false;
460 aInsert
.nRelInd
= 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
;
481 bool RangeNameBufferWK3::FindAbs( const OUString
& rRef
, sal_uInt16
& rIndex
)
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
493 rIndex
= itr
->nAbsInd
;
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
);
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
;
524 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */