xref: /AOO41X/main/sc/source/filter/lotus/tool.cxx (revision 3ee7c2db59af3948da1f0fe563f557d5b49b2c39)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 //------------------------------------------------------------------------
30 
31 #include "scitems.hxx"
32 #include <svx/algitem.hxx>
33 #include <svl/zforlist.hxx>
34 #include <tools/solar.h>
35 
36 #include "cell.hxx"
37 #include "rangenam.hxx"
38 #include "compiler.hxx"
39 
40 #include "tool.h"
41 #include "decl.h"
42 #include "root.hxx"
43 #include "lotrange.hxx"
44 #include "namebuff.hxx"
45 #include "ftools.hxx"
46 
47 #include <math.h>
48 
49 #ifdef _MSC_VER
50 #pragma optimize("",off)
51 #endif
52 
53 //--------------------------------------------------------- EXTERNE VARIABLEN -
54 extern WKTYP                eTyp;           // -> filter.cxx, aktueller Dateityp
55 extern ScDocument*          pDoc;           // -> filter.cxx, Aufhaenger zum Dokumentzugriff
56 
57 //--------------------------------------------------------- GLOBALE VARIABLEN -
58 sal_uInt8                       nDefaultFormat; // -> op.cpp, Standard-Zellenformat
59 
60 extern SvxHorJustifyItem    *pAttrRight, *pAttrLeft, *pAttrCenter, *pAttrRepeat, *pAttrStandard;
61 extern ScProtectionAttr*    pAttrUnprot;
62 extern SfxUInt32Item**      pAttrValForms;
63 
64 SvxHorJustifyItem           *pAttrRight, *pAttrLeft, *pAttrCenter, *pAttrRepeat, *pAttrStandard;
65                                                     // -> in memory.cxx initialisiert
66 ScProtectionAttr*           pAttrUnprot;            // ->  " memory.cxx    "
67 
68 extern FormCache*           pValueFormCache;        // -> in memory.cxx initialisiert
69 FormCache*                  pValueFormCache;
70 
71 SCCOL                       LotusRangeList::nEingCol;
72 SCROW                       LotusRangeList::nEingRow;
73 
74 
75 
76 
PutFormString(SCCOL nCol,SCROW nRow,SCTAB nTab,sal_Char * pString)77 void PutFormString( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Char* pString )
78 {
79     // Label-Format-Auswertung
80     DBG_ASSERT( pString != NULL, "PutFormString(): pString == NULL" );
81     if (!pString)
82         return;
83 
84     sal_Char            cForm;
85     SvxHorJustifyItem*  pJustify = NULL;
86 
87     cForm = *pString;
88 
89     switch( cForm )
90     {
91         case '"':   // rechtsbuendig
92             pJustify = pAttrRight;
93             pString++;
94             break;
95         case '\'':  // linksbuendig
96             pJustify = pAttrLeft;
97             pString++;
98             break;
99         case '^':   // zentriert
100             pJustify = pAttrCenter;
101             pString++;
102             break;
103         case '|':   // printer command
104             pString = NULL;
105             break;
106         case '\\':  // Wiederholung
107             pJustify = pAttrRepeat;
108             pString++;
109             break;
110         default:    // kenn' ich nicht!
111             pJustify = pAttrStandard;
112     }
113 
114     pDoc->ApplyAttr( nCol, nRow, nTab, *pJustify );
115     ScStringCell*   pZelle = new ScStringCell( String( pString, pLotusRoot->eCharsetQ ) );
116     pDoc->PutCell( nCol, nRow, nTab, pZelle, ( sal_Bool ) sal_True );
117 }
118 
119 
120 
121 
SetFormat(SCCOL nCol,SCROW nRow,SCTAB nTab,sal_uInt8 nFormat,sal_uInt8 nSt)122 void SetFormat( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt8 nFormat, sal_uInt8 nSt )
123 {
124     //  PREC:   nSt = Standard-Dezimalstellenanzahl
125     pDoc->ApplyAttr( nCol, nRow, nTab, *( pValueFormCache->GetAttr( nFormat, nSt ) ) );
126 
127     ScProtectionAttr aAttr;
128 
129     aAttr.SetProtection( nFormat & 0x80 );
130 
131     pDoc->ApplyAttr( nCol, nRow, nTab, aAttr );
132 }
133 
InitPage(void)134 void InitPage( void )
135 {   // Seitenformat initialisieren, d.h. Default-Werte von SC holen
136     //scGetPageFormat( 0, &aPage );
137 }
138 
139 
SnumToDouble(sal_Int16 nVal)140 double SnumToDouble( sal_Int16 nVal )
141 {
142     const double pFacts[ 8 ] = {
143         5000.0,
144         500.0,
145         0.05,
146         0.005,
147         0.0005,
148         0.00005,
149         0.0625,
150         0.015625 };
151 
152     double      fVal;
153 
154     if( nVal & 0x0001 )
155     {
156         fVal = pFacts[ ( nVal >> 1 ) & 0x0007 ];
157         fVal *= ( sal_Int16 ) ( nVal >> 4 );
158     }
159     else
160         fVal = ( sal_Int16 ) ( nVal >> 1 );
161 
162     return fVal;
163 }
164 
Snum32ToDouble(sal_uInt32 nValue)165 double Snum32ToDouble( sal_uInt32 nValue )
166 {
167     double fValue, temp;
168 
169     fValue = nValue >> 6;
170     temp = nValue & 0x0f;
171     if (temp)
172     {
173         if (nValue & 0x00000010)
174                 fValue /= pow((double)10, temp);
175         else
176         fValue *= pow((double)10, temp);
177     }
178 
179     if ((nValue & 0x00000020))
180         fValue = -fValue;
181     return fValue;
182 }
183 
184 
FormCache(ScDocument * pDoc1,sal_uInt8 nNewDefaultFormat)185 FormCache::FormCache( ScDocument* pDoc1, sal_uInt8 nNewDefaultFormat )
186 {   // Default-Format ist 'Default'
187     nDefaultFormat = nNewDefaultFormat;
188     pFormTable = pDoc1->GetFormatTable();
189     for( sal_uInt16 nC = 0 ; nC < __nSize ; nC++ )
190         bValid[ nC ] = sal_False;
191     eLanguage = ScGlobal::eLnge;
192 }
193 
194 
~FormCache()195 FormCache::~FormCache()
196 {
197     for( sal_uInt16 nC = 0 ; nC < __nSize ; nC++ )
198         delete aIdents[ nC ].GetAttr();
199 }
200 
201 
NewAttr(sal_uInt8 nFormat,sal_uInt8 nSt)202 SfxUInt32Item* FormCache::NewAttr( sal_uInt8 nFormat, sal_uInt8 nSt )
203 {
204     // neues Format erzeugen
205     sal_uInt8       nL, nH; // Low-/High-Nibble
206     sal_uInt8       nForm = nFormat;
207     String      aFormString;
208     const sal_Char* pFormString = 0;
209     sal_Int16       eType = NUMBERFORMAT_ALL;
210     sal_uInt32      nIndex1;
211     sal_uInt32      nHandle;
212     sal_Bool        bDefault = sal_False;
213     //void GenerateFormat( aFormString, eType, COUNTRY_SYSTEM, LANGUAGE_SYSTEM,
214     //  sal_Bool bThousand, sal_Bool IsRed, sal_uInt16 nPrecision, sal_uInt16 nAnzLeading );
215 
216     if( nForm == 0xFF ) // Default-Format?
217         nForm = nDefaultFormat;
218 
219     // Aufdroeseln in Low- und High-Nibble
220     nL = nFormat & 0x0F;
221     nH = ( nFormat & 0xF0 ) / 16;
222 
223     nH &= 0x07;     // Bits 4-6 'rausziehen
224     switch( nH )
225     {
226         case 0x00:  // Festkommaformat (fixed)
227             //fStandard;nL;
228             nIndex1 = pFormTable->GetStandardFormat(
229                 NUMBERFORMAT_NUMBER, eLanguage );
230             pFormTable->GenerateFormat( aFormString, nIndex1,
231                 eLanguage, sal_False, sal_False, nL, 1 );
232             break;
233         case 0x01:  // Exponentdarstellung (scientific notation)
234             //fExponent;nL;
235             nIndex1 = pFormTable->GetStandardFormat(
236                 NUMBERFORMAT_SCIENTIFIC, eLanguage );
237             pFormTable->GenerateFormat( aFormString, nIndex1,
238                 eLanguage, sal_False, sal_False, nL, 1 );
239             break;
240         case 0x02:  // Waehrungsdarstellung (currency)
241             //fMoney;nL;
242             nIndex1 = pFormTable->GetStandardFormat(
243                 NUMBERFORMAT_CURRENCY, eLanguage );
244             pFormTable->GenerateFormat( aFormString, nIndex1,
245                 eLanguage, sal_False, sal_False, nL, 1 );
246             break;
247         case 0x03:  // Prozent
248             //fPercent;nL;
249             nIndex1 = pFormTable->GetStandardFormat(
250                 NUMBERFORMAT_PERCENT, eLanguage );
251             pFormTable->GenerateFormat( aFormString, nIndex1,
252                 eLanguage, sal_False, sal_False, nL, 1 );
253             break;
254         case 0x04:  // Komma
255             //fStandard;nL;
256             nIndex1 = pFormTable->GetStandardFormat(
257                 NUMBERFORMAT_NUMBER, eLanguage );
258             pFormTable->GenerateFormat( aFormString, nIndex1,
259                 eLanguage, sal_True, sal_False, nL, 1 );
260             break;
261         case 0x05:  // frei
262             //fStandard;nL;
263             nIndex1 = pFormTable->GetStandardFormat(
264                 NUMBERFORMAT_NUMBER, eLanguage );
265             pFormTable->GenerateFormat( aFormString, nIndex1,
266                 eLanguage, sal_False, sal_False, nL, 1 );
267             break;
268         case 0x06:  // frei
269             //fStandard;nL;
270             nIndex1 = pFormTable->GetStandardFormat(
271                 NUMBERFORMAT_NUMBER, eLanguage );
272             pFormTable->GenerateFormat( aFormString, nIndex1,
273                 eLanguage, sal_False, sal_False, nL, 1 );
274             nIndex1 = 0;
275             break;
276         case 0x07:  // Spezialformat
277             switch( nL )
278             {
279                 case 0x00:  // +/-
280                     //fStandard;nSt;
281                     nIndex1 = pFormTable->GetStandardFormat(
282                         NUMBERFORMAT_NUMBER, eLanguage );
283                     pFormTable->GenerateFormat( aFormString, nIndex1,
284                         eLanguage, sal_False, sal_True, nSt, 1 );
285                     break;
286                 case 0x01:  // generelles Format
287                     //fStandard;nSt;
288                     nIndex1 = pFormTable->GetStandardFormat(
289                         NUMBERFORMAT_NUMBER, eLanguage );
290                     pFormTable->GenerateFormat( aFormString, nIndex1,
291                         eLanguage, sal_False, sal_False, nSt, 1 );
292                     break;
293                 case 0x02:  // Datum: Tag, Monat, Jahr
294                     //fDate;dfDayMonthYearLong;
295                     eType = NUMBERFORMAT_DATE;
296                     pFormString = "TT.MM.JJJJ";
297                     break;
298                 case 0x03:  // Datum: Tag, Monat
299                     //fDate;dfDayMonthLong;
300                     eType = NUMBERFORMAT_DATE;
301                     pFormString = "TT.MMMM";
302                     break;
303                 case 0x04:  // Datum: Monat, Jahr
304                     //fDate;dfMonthYearLong;
305                     eType = NUMBERFORMAT_DATE;
306                     pFormString = "MM.JJJJ";
307                     break;
308                 case 0x05:  // Textformate
309                     //fString;nSt;
310                     eType = NUMBERFORMAT_TEXT;
311                     pFormString = "@";
312                     break;
313                 case 0x06:  // versteckt
314                     //wFlag |= paHideAll;bSetFormat = sal_False;
315                     eType = NUMBERFORMAT_NUMBER;
316                     pFormString = "";
317                     break;
318                 case 0x07:  // Time: hour, min, sec
319                     //fTime;tfHourMinSec24;
320                     eType = NUMBERFORMAT_TIME;
321                     pFormString = "HH:MM:SS";
322                     break;
323                 case 0x08:  // Time: hour, min
324                     //fTime;tfHourMin24;
325                     eType = NUMBERFORMAT_TIME;
326                     pFormString = "HH:MM";
327                     break;
328                 case 0x09:  // Date, intern sal_Int32 1
329                     //fDate;dfDayMonthYearLong;
330                     eType = NUMBERFORMAT_DATE;
331                     pFormString = "TT.MM.JJJJ";
332                     break;
333                 case 0x0A:  // Date, intern sal_Int32 2
334                     //fDate;dfDayMonthYearLong;
335                     eType = NUMBERFORMAT_DATE;
336                     pFormString = "TT.MM.JJJJ";
337                     break;
338                 case 0x0B:  // Time, intern sal_Int32 1
339                     //fTime;tfHourMinSec24;
340                     eType = NUMBERFORMAT_TIME;
341                     pFormString = "HH:MM:SS";
342                     break;
343                 case 0x0C:  // Time, intern sal_Int32 2
344                     //fTime;tfHourMinSec24;
345                     eType = NUMBERFORMAT_TIME;
346                     pFormString = "HH:MM:SS";
347                     break;
348                 case 0x0F:  // Standardeinstellung
349                     //fStandard;nSt;
350                     bDefault = sal_True;
351                     break;
352                 default:
353                     //fStandard;nSt;
354                     bDefault = sal_True;
355                     break;
356             }
357             break;
358         default:
359             //fStandard;nL;
360             nIndex1 = pFormTable->GetStandardFormat(
361                 NUMBERFORMAT_NUMBER, eLanguage );
362             pFormTable->GenerateFormat( aFormString, nIndex1,
363                 eLanguage, sal_False, sal_False, nL, 1 );
364             nIndex1 = 0;
365             break;
366     }
367 
368     // Format in Table schieben
369     if( bDefault )
370         nHandle = 0;
371     else
372     {
373         if( pFormString )
374             aFormString.AssignAscii( pFormString );
375 
376         xub_StrLen  nDummy;
377         pFormTable->PutEntry( aFormString, nDummy, eType, nHandle, eLanguage );
378     }
379 
380     return new SfxUInt32Item( ATTR_VALUE_FORMAT, ( sal_uInt32 ) nHandle );
381 }
382 
383 
384 
385 
MakeHash(void)386 void LotusRange::MakeHash( void )
387 {
388     // 33222222222211111111110000000000
389     // 10987654321098765432109876543210
390     //                         ******** nColS
391     //                   ********       nColE
392     //     ****************             nRowS
393     // ****************                 nRowE
394     nHash =  static_cast<sal_uInt32>(nColStart);
395     nHash += static_cast<sal_uInt32>(nColEnd) << 6;
396     nHash += static_cast<sal_uInt32>(nRowStart) << 12;
397     nHash += static_cast<sal_uInt32>(nRowEnd ) << 16;
398 }
399 
400 
LotusRange(SCCOL nCol,SCROW nRow)401 LotusRange::LotusRange( SCCOL nCol, SCROW nRow )
402 {
403     nColStart = nColEnd = nCol;
404     nRowStart = nRowEnd = nRow;
405     nId = ID_FAIL;
406     MakeHash();
407 }
408 
409 
LotusRange(SCCOL nCS,SCROW nRS,SCCOL nCE,SCROW nRE)410 LotusRange::LotusRange( SCCOL nCS, SCROW nRS, SCCOL nCE, SCROW nRE )
411 {
412     nColStart = nCS;
413     nColEnd = nCE;
414     nRowStart = nRS;
415     nRowEnd = nRE;
416     nId = ID_FAIL;
417     MakeHash();
418 }
419 
420 
LotusRange(const LotusRange & rCpy)421 LotusRange::LotusRange( const LotusRange& rCpy )
422 {
423     Copy( rCpy );
424 }
425 
426 
427 
428 
429 
LotusRangeList(void)430 LotusRangeList::LotusRangeList( void )
431 {
432     aComplRef.InitFlags();
433 
434     ScSingleRefData*    pSingRef;
435     nIdCnt = 1;
436 
437     pSingRef = &aComplRef.Ref1;
438     pSingRef->nTab = pSingRef->nRelTab = 0;
439     pSingRef->SetColRel( sal_False );
440     pSingRef->SetRowRel( sal_False );
441     pSingRef->SetTabRel( sal_True );
442     pSingRef->SetFlag3D( sal_False );
443 
444     pSingRef = &aComplRef.Ref2;
445     pSingRef->nTab = pSingRef->nRelTab = 0;
446     pSingRef->SetColRel( sal_False );
447     pSingRef->SetRowRel( sal_False );
448     pSingRef->SetTabRel( sal_True );
449     pSingRef->SetFlag3D( sal_False );
450 }
451 
452 
~LotusRangeList(void)453 LotusRangeList::~LotusRangeList( void )
454     {
455     LotusRange *pDel = ( LotusRange * ) List::First();
456 
457     while( pDel )
458         {
459         delete pDel;
460         pDel = ( LotusRange * ) List::Next();
461         }
462     }
463 
464 
GetIndex(const LotusRange & rRef)465 LR_ID LotusRangeList::GetIndex( const LotusRange &rRef )
466 {
467     LotusRange*     pComp = ( LotusRange* ) List::First();
468 
469     while( pComp )
470     {
471         if( *pComp == rRef )
472             return pComp->nId;
473         pComp = ( LotusRange* ) List::Next();
474     }
475 
476     return ID_FAIL;
477 }
478 
479 
Append(LotusRange * pLR,const String & rName)480 void LotusRangeList::Append( LotusRange* pLR, const String& rName )
481 {
482     DBG_ASSERT( pLR, "*LotusRangeList::Append(): das wird nichts!" );
483     List::Insert( pLR, CONTAINER_APPEND );
484 
485     ScTokenArray    aTokArray;
486 
487     ScSingleRefData*    pSingRef = &aComplRef.Ref1;
488 
489     pSingRef->nCol = pLR->nColStart;
490     pSingRef->nRow = pLR->nRowStart;
491 
492     if( pLR->IsSingle() )
493         aTokArray.AddSingleReference( *pSingRef );
494     else
495     {
496         pSingRef = &aComplRef.Ref2;
497         pSingRef->nCol = pLR->nColEnd;
498         pSingRef->nRow = pLR->nRowEnd;
499         aTokArray.AddDoubleReference( aComplRef );
500     }
501 
502     ScRangeData*    pData = new ScRangeData(
503         pLotusRoot->pDoc, rName, aTokArray );
504 
505     pLotusRoot->pScRangeName->Insert( pData );
506 
507     pLR->SetId( nIdCnt );
508 
509     nIdCnt++;
510 }
511 
512 
513 
514 
RangeNameBufferWK3(void)515 RangeNameBufferWK3::RangeNameBufferWK3( void )
516 {
517     pScTokenArray = new ScTokenArray;
518     nIntCount = 1;
519 }
520 
521 
~RangeNameBufferWK3()522 RangeNameBufferWK3::~RangeNameBufferWK3()
523 {
524     ENTRY*      pDel = ( ENTRY* ) List::First();
525 
526     while( pDel )
527     {
528         delete pDel;
529         pDel = ( ENTRY* ) List::Next();
530     }
531 
532     delete pScTokenArray;
533 }
534 
535 
Add(const String & rOrgName,const ScComplexRefData & rCRD)536 void RangeNameBufferWK3::Add( const String& rOrgName, const ScComplexRefData& rCRD )
537 {
538     String              aScName( rOrgName );
539     ScfTools::ConvertToScDefinedName( aScName );
540 
541     register ENTRY*     pInsert = new ENTRY( rOrgName, aScName, rCRD );
542 
543     List::Insert( pInsert, CONTAINER_APPEND );
544 
545     pScTokenArray->Clear();
546 
547     register const ScSingleRefData& rRef1 = rCRD.Ref1;
548     register const ScSingleRefData& rRef2 = rCRD.Ref2;
549 
550     if( rRef1.nCol == rRef2.nCol && rRef1.nRow == rRef2.nRow && rRef1.nTab == rRef2.nTab )
551     {
552         pScTokenArray->AddSingleReference( rCRD.Ref1 );
553         pInsert->bSingleRef = sal_True;
554     }
555     else
556     {
557         pScTokenArray->AddDoubleReference( rCRD );
558         pInsert->bSingleRef = sal_False;
559     }
560 
561     ScRangeData*        pData = new ScRangeData( pLotusRoot->pDoc, aScName, *pScTokenArray );
562 
563     pInsert->nRelInd = nIntCount;
564     pData->SetIndex( nIntCount );
565     nIntCount++;
566 
567     pLotusRoot->pScRangeName->Insert( pData );
568 }
569 
570 
FindRel(const String & rRef,sal_uInt16 & rIndex)571 sal_Bool RangeNameBufferWK3::FindRel( const String& rRef, sal_uInt16& rIndex )
572 {
573     StringHashEntry     aRef( rRef );
574 
575     ENTRY*              pFind = ( ENTRY* ) List::First();
576 
577     while( pFind )
578     {
579         if( aRef == pFind->aStrHashEntry )
580         {
581             rIndex = pFind->nRelInd;
582             return sal_True;
583         }
584         pFind = ( ENTRY* ) List::Next();
585     }
586 
587     return sal_False;
588 }
589 
590 
FindAbs(const String & rRef,sal_uInt16 & rIndex)591 sal_Bool RangeNameBufferWK3::FindAbs( const String& rRef, sal_uInt16& rIndex )
592 {
593     String              aTmp( rRef );
594     StringHashEntry     aRef( aTmp.Erase( 0, 1 ) ); // ohne '$' suchen!
595 
596     ENTRY*              pFind = ( ENTRY* ) List::First();
597 
598     while( pFind )
599     {
600         if( aRef == pFind->aStrHashEntry )
601         {
602             // eventuell neuen Range Name aufbauen
603             if( pFind->nAbsInd )
604                 rIndex = pFind->nAbsInd;
605             else
606             {
607                 ScSingleRefData*        pRef = &pFind->aScComplexRefDataRel.Ref1;
608                 pScTokenArray->Clear();
609 
610                 pRef->SetColRel( sal_False );
611                 pRef->SetRowRel( sal_False );
612                 pRef->SetTabRel( sal_True );
613 
614                 if( pFind->bSingleRef )
615                     pScTokenArray->AddSingleReference( *pRef );
616                 else
617                 {
618                     pRef = &pFind->aScComplexRefDataRel.Ref2;
619                     pRef->SetColRel( sal_False );
620                     pRef->SetRowRel( sal_False );
621                     pRef->SetTabRel( sal_True );
622                     pScTokenArray->AddDoubleReference( pFind->aScComplexRefDataRel );
623                 }
624 
625                 ScRangeData*    pData = new ScRangeData( pLotusRoot->pDoc, pFind->aScAbsName, *pScTokenArray );
626 
627                 rIndex = pFind->nAbsInd = nIntCount;
628                 pData->SetIndex( rIndex );
629                 nIntCount++;
630 
631                 pLotusRoot->pScRangeName->Insert( pData );
632             }
633 
634             return sal_True;
635         }
636         pFind = ( ENTRY* ) List::Next();
637     }
638 
639     return sal_False;
640 }
641 
642 
643