Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / filter / dif / difimp.cxx
blob1c0adc9ed99981a3a298e684b600bf5b000d633c
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 .
21 #include <math.h>
23 #include <svl/zforlist.hxx>
24 #include "attrib.hxx"
25 #include "dif.hxx"
26 #include "docpool.hxx"
27 #include "document.hxx"
28 #include "filter.hxx"
29 #include "fprogressbar.hxx"
30 #include "ftools.hxx"
31 #include "patattr.hxx"
32 #include "scerrors.hxx"
33 #include "scitems.hxx"
34 #include "stringutil.hxx"
36 const sal_Unicode pKeyTABLE[] = { 'T', 'A', 'B', 'L', 'E', 0 };
37 const sal_Unicode pKeyVECTORS[] = { 'V', 'E', 'C', 'T', 'O', 'R', 'S', 0 };
38 const sal_Unicode pKeyTUPLES[] = { 'T', 'U', 'P', 'L', 'E', 'S', 0 };
39 const sal_Unicode pKeyDATA[] = { 'D', 'A', 'T', 'A', 0 };
40 const sal_Unicode pKeyBOT[] = { 'B', 'O', 'T', 0 };
41 const sal_Unicode pKeyEOD[] = { 'E', 'O', 'D', 0 };
42 const sal_Unicode pKeyERROR[] = { 'E', 'R', 'R', 'O', 'R', 0 };
43 const sal_Unicode pKeyTRUE[] = { 'T', 'R', 'U', 'E', 0 };
44 const sal_Unicode pKeyFALSE[] = { 'F', 'A', 'L', 'S', 'E', 0 };
45 const sal_Unicode pKeyNA[] = { 'N', 'A', 0 };
46 const sal_Unicode pKeyV[] = { 'V', 0 };
47 const sal_Unicode pKey1_0[] = { '1', ',', '0', 0 };
50 FltError ScFormatFilterPluginImpl::ScImportDif( SvStream& rIn, ScDocument* pDoc, const ScAddress& rInsPos,
51 const rtl_TextEncoding eVon, sal_uInt32 nDifOption )
53 DifParser aDifParser( rIn, nDifOption, *pDoc, eVon );
55 const bool bPlain = aDifParser.IsPlain();
57 SCTAB nBaseTab = rInsPos.Tab();
59 TOPIC eTopic = T_UNKNOWN;
60 bool bSyntErrWarn = false;
61 bool bOverflowWarn = false;
63 OUString& aData = aDifParser.aData;
64 bool bData = false;
66 rIn.Seek( 0 );
68 ScfStreamProgressBar aPrgrsBar( rIn, pDoc->GetDocumentShell() );
70 while( eTopic != T_DATA && eTopic != T_END )
72 eTopic = aDifParser.GetNextTopic();
74 aPrgrsBar.Progress();
76 bData = !aData.isEmpty();
78 switch( eTopic )
80 case T_TABLE:
82 if( aDifParser.nVector != 0 || aDifParser.nVal != 1 )
83 bSyntErrWarn = sal_True;
84 if( bData )
85 pDoc->RenameTab( nBaseTab, aData );
87 break;
88 case T_VECTORS:
90 if( aDifParser.nVector != 0 )
91 bSyntErrWarn = true;
93 break;
94 case T_TUPLES:
96 if( aDifParser.nVector != 0 )
97 bSyntErrWarn = true;
99 break;
100 case T_DATA:
102 if( aDifParser.nVector != 0 || aDifParser.nVal != 0 )
103 bSyntErrWarn = sal_True;
105 break;
106 case T_LABEL:
107 case T_COMMENT:
108 case T_SIZE:
109 case T_PERIODICITY:
110 case T_MAJORSTART:
111 case T_MINORSTART:
112 case T_TRUELENGTH:
113 case T_UINITS:
114 case T_DISPLAYUNITS:
115 case T_END:
116 case T_UNKNOWN:
117 break;
118 default:
119 OSL_FAIL( "ScImportDif - missing enum" );
125 if( eTopic == T_DATA )
126 { // Ab hier kommen die Daten
127 SCCOL nBaseCol = rInsPos.Col();
129 SCCOL nColCnt = SCCOL_MAX;
130 SCROW nRowCnt = rInsPos.Row();
131 DifAttrCache aAttrCache( bPlain );
133 DATASET eAkt = D_UNKNOWN;
135 ScSetStringParam aStrParam; // used to set string value without number detection.
136 aStrParam.setTextInput();
138 while( eAkt != D_EOD )
140 eAkt = aDifParser.GetNextDataset();
142 aPrgrsBar.Progress();
143 ScAddress aPos(nColCnt, nRowCnt, nBaseTab);
145 switch( eAkt )
147 case D_BOT:
148 if( nColCnt < SCCOL_MAX )
149 nRowCnt++;
150 nColCnt = nBaseCol;
151 break;
152 case D_EOD:
153 break;
154 case D_NUMERIC: // Numbercell
155 if( nColCnt == SCCOL_MAX )
156 nColCnt = nBaseCol;
158 if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
160 pDoc->EnsureTable(nBaseTab);
162 if( DifParser::IsV( aData.getStr() ) )
164 pDoc->SetValue(aPos, aDifParser.fVal);
165 if( !bPlain )
166 aAttrCache.SetNumFormat( nColCnt, nRowCnt,
167 aDifParser.nNumFormat );
169 else if( aData == pKeyTRUE || aData == pKeyFALSE )
171 pDoc->SetValue(aPos, aDifParser.fVal);
172 if( bPlain )
173 aAttrCache.SetLogical( nColCnt, nRowCnt );
174 else
175 aAttrCache.SetNumFormat( nColCnt, nRowCnt,
176 aDifParser.nNumFormat );
178 else if( aData == pKeyNA || aData == pKeyERROR )
180 pDoc->SetString(aPos, aData, &aStrParam);
182 else
184 OUString aTmp = "#IND:" + aData + "?";
185 pDoc->SetString(aPos, aTmp, &aStrParam);
188 else
189 bOverflowWarn = true;
191 nColCnt++;
192 break;
193 case D_STRING: // Textcell
194 if( nColCnt == SCCOL_MAX )
195 nColCnt = nBaseCol;
197 if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
199 if (!aData.isEmpty())
201 pDoc->EnsureTable(nBaseTab);
202 pDoc->SetTextCell(aPos, aData);
205 else
206 bOverflowWarn = sal_True;
208 nColCnt++;
209 break;
210 case D_UNKNOWN:
211 break;
212 case D_SYNT_ERROR:
213 break;
214 default:
215 OSL_FAIL( "ScImportDif - missing enum" );
219 aAttrCache.Apply( *pDoc, nBaseTab );
221 else
222 return eERR_FORMAT;
224 if( bSyntErrWarn )
225 //###############################################
226 // ACHTUNG: Hier fehlt noch die richtige Warnung!
227 return eERR_RNGOVRFLW;
228 //###############################################
229 else if( bOverflowWarn )
230 return eERR_RNGOVRFLW;
231 else
232 return eERR_OK;
236 DifParser::DifParser( SvStream& rNewIn, const sal_uInt32 nOption, ScDocument& rDoc, rtl_TextEncoding e ) :
237 rIn( rNewIn )
239 eCharSet = e;
240 if ( rIn.GetStreamCharSet() != eCharSet )
242 OSL_FAIL( "CharSet passed overrides and modifies StreamCharSet" );
243 rIn.SetStreamCharSet( eCharSet );
245 rIn.StartReadingUnicodeText( eCharSet );
247 bPlain = ( nOption == SC_DIFOPT_PLAIN );
249 if( bPlain )
250 pNumFormatter = NULL;
251 else
252 pNumFormatter = rDoc.GetFormatTable();
256 TOPIC DifParser::GetNextTopic( void )
258 enum STATE { S_VectorVal, S_Data, S_END, S_START, S_UNKNOWN, S_ERROR_L2 };
260 static const sal_Unicode pKeyLABEL[] = { 'L', 'A', 'B', 'E', 'L', 0 };
261 static const sal_Unicode pKeyCOMMENT[] = { 'C', 'O', 'M', 'M', 'E', 'N', 'T', 0 };
262 static const sal_Unicode pKeySIZE[] = { 'S', 'I', 'Z', 'E', 0 };
263 static const sal_Unicode pKeyPERIODICITY[] = { 'P', 'E', 'R', 'I', 'O', 'D', 'I', 'C', 'I', 'T', 'Y', 0 };
264 static const sal_Unicode pKeyMAJORSTART[] = { 'M', 'A', 'J', 'O', 'R', 'S', 'T', 'A', 'R', 'T', 0 };
265 static const sal_Unicode pKeyMINORSTART[] = { 'M', 'I', 'N', 'O', 'R', 'S', 'T', 'A', 'R', 'T', 0 };
266 static const sal_Unicode pKeyTRUELENGTH[] = { 'T', 'R', 'U', 'E', 'L', 'E', 'N', 'G', 'T', 'H', 0 };
267 static const sal_Unicode pKeyUINITS[] = { 'U', 'I', 'N', 'I', 'T', 'S', 0 };
268 static const sal_Unicode pKeyDISPLAYUNITS[] = { 'D', 'I', 'S', 'P', 'L', 'A', 'Y', 'U', 'N', 'I', 'T', 'S', 0 };
269 static const sal_Unicode pKeyUNKNOWN[] = { 0 };
271 static const sal_Unicode* ppKeys[] =
273 pKeyTABLE, // 0
274 pKeyVECTORS,
275 pKeyTUPLES,
276 pKeyDATA,
277 pKeyLABEL,
278 pKeyCOMMENT, // 5
279 pKeySIZE,
280 pKeyPERIODICITY,
281 pKeyMAJORSTART,
282 pKeyMINORSTART,
283 pKeyTRUELENGTH, // 10
284 pKeyUINITS,
285 pKeyDISPLAYUNITS,
286 pKeyUNKNOWN // 13
289 static const TOPIC pTopics[] =
291 T_TABLE, // 0
292 T_VECTORS,
293 T_TUPLES,
294 T_DATA,
295 T_LABEL,
296 T_COMMENT, // 5
297 T_SIZE,
298 T_PERIODICITY,
299 T_MAJORSTART,
300 T_MINORSTART,
301 T_TRUELENGTH, // 10
302 T_UINITS,
303 T_DISPLAYUNITS,
304 T_UNKNOWN // 13
307 STATE eS = S_START;
308 OUString aLine;
310 nVector = 0;
311 nVal = 0;
312 TOPIC eRet = T_UNKNOWN;
314 while( eS != S_END )
316 if( !ReadNextLine( aLine ) )
318 eS = S_END;
319 eRet = T_END;
322 switch( eS )
324 case S_START:
326 const sal_Unicode* pRef;
327 sal_uInt16 nCnt = 0;
328 sal_Bool bSearch = sal_True;
330 pRef = ppKeys[ nCnt ];
332 while( bSearch )
334 if( aLine == pRef )
336 eRet = pTopics[ nCnt ];
337 bSearch = false;
339 else
341 nCnt++;
342 pRef = ppKeys[ nCnt ];
343 if( !*pRef )
344 bSearch = false;
348 if( *pRef )
349 eS = S_VectorVal;
350 else
351 eS = S_UNKNOWN;
353 break;
354 case S_VectorVal:
356 const sal_Unicode* pCur = aLine.getStr();
358 pCur = ScanIntVal( pCur, nVector );
360 if( pCur && *pCur == ',' )
362 pCur++;
363 ScanIntVal( pCur, nVal );
364 eS = S_Data;
366 else
367 eS = S_ERROR_L2;
369 break;
370 case S_Data:
371 OSL_ENSURE( aLine.getLength() >= 2,
372 "+GetNextTopic(): <String> ist zu kurz!" );
373 if( aLine.getLength() > 2 )
374 aData = aLine.copy( 1, aLine.getLength() - 2 );
375 else
376 aData = OUString();
377 eS = S_END;
378 break;
379 case S_END:
380 OSL_FAIL( "DifParser::GetNextTopic - unexpected state" );
381 break;
382 case S_UNKNOWN:
383 // 2 Zeilen ueberlesen
384 ReadNextLine( aLine );
385 case S_ERROR_L2: // Fehler in Line 2 aufgetreten
386 // eine Zeile ueberlesen
387 ReadNextLine( aLine );
388 eS = S_END;
389 break;
390 default:
391 OSL_FAIL( "DifParser::GetNextTopic - missing enum" );
395 return eRet;
399 static void lcl_DeEscapeQuotesDif( OUString& rString )
401 // Special handling for DIF import: Escaped (duplicated) quotes are resolved.
402 // Single quote characters are left in place because older versions didn't
403 // escape quotes in strings (and Excel doesn't when using the clipboard).
404 // The quotes around the string are removed before this function is called.
406 rString = rString.replaceAll("\"\"", "\"");
409 // Determine if passed in string is numeric data and set fVal/nNumFormat if so
410 DATASET DifParser::GetNumberDataset( const sal_Unicode* pPossibleNumericData )
412 DATASET eRet = D_SYNT_ERROR;
413 if( bPlain )
415 if( ScanFloatVal( pPossibleNumericData ) )
416 eRet = D_NUMERIC;
417 else
418 eRet = D_SYNT_ERROR;
420 else
421 { // ...und zur Strafe mit'm Numberformatter...
422 OSL_ENSURE( pNumFormatter, "-DifParser::GetNextDataset(): No Formatter, more fun!" );
423 OUString aTestVal( pPossibleNumericData );
424 sal_uInt32 nFormat = 0;
425 double fTmpVal;
426 if( pNumFormatter->IsNumberFormat( aTestVal, nFormat, fTmpVal ) )
428 fVal = fTmpVal;
429 nNumFormat = nFormat;
430 eRet = D_NUMERIC;
432 else
433 eRet = D_SYNT_ERROR;
435 return eRet;
438 bool DifParser::ReadNextLine( OUString& rStr )
440 if( aLookAheadLine.isEmpty() )
442 return rIn.ReadUniOrByteStringLine( rStr, rIn.GetStreamCharSet() );
444 else
446 rStr = aLookAheadLine;
447 aLookAheadLine = OUString();
448 return true;
452 // Look ahead in the stream to determine if the next line is the first line of
453 // a valid data record structure
454 bool DifParser::LookAhead()
456 const sal_Unicode* pAktBuffer;
457 bool bValidStructure = false;
459 OSL_ENSURE( aLookAheadLine.isEmpty(), "*DifParser::LookAhead(): LookAhead called twice in a row" );
460 rIn.ReadUniOrByteStringLine( aLookAheadLine, rIn.GetStreamCharSet() );
462 pAktBuffer = aLookAheadLine.getStr();
464 switch( *pAktBuffer )
466 case '-': // Special Datatype
467 pAktBuffer++;
469 if( Is1_0( pAktBuffer ) )
471 bValidStructure = true;
473 break;
474 case '0': // Numeric Data
475 pAktBuffer++;
476 if( *pAktBuffer == ',' )
478 pAktBuffer++;
479 bValidStructure = ( GetNumberDataset(pAktBuffer) != D_SYNT_ERROR );
481 break;
482 case '1': // String Data
483 if( Is1_0( aLookAheadLine.getStr() ) )
485 bValidStructure = true;
487 break;
489 return bValidStructure;
492 DATASET DifParser::GetNextDataset( void )
494 DATASET eRet = D_UNKNOWN;
495 OUString aLine;
496 const sal_Unicode* pAktBuffer;
498 ReadNextLine( aLine );
500 pAktBuffer = aLine.getStr();
502 switch( *pAktBuffer )
504 case '-': // Special Datatype
505 pAktBuffer++;
507 if( Is1_0( pAktBuffer ) )
509 ReadNextLine( aLine );
510 if( IsBOT( aLine.getStr() ) )
511 eRet = D_BOT;
512 else if( IsEOD( aLine.getStr() ) )
513 eRet = D_EOD;
515 break;
516 case '0': // Numeric Data
517 pAktBuffer++; // Wert in fVal, 2. Zeile in aData
518 if( *pAktBuffer == ',' )
520 pAktBuffer++;
521 eRet = GetNumberDataset(pAktBuffer);
522 OUString aTmpLine;
523 ReadNextLine( aTmpLine );
524 if ( eRet == D_SYNT_ERROR )
525 { // for broken records write "#ERR: data" to cell
526 OUStringBuffer aTmp("#ERR: ");
527 aTmp.append(pAktBuffer).append(" (");
528 aTmp.append(aTmpLine).append(')');
529 aData = aTmp.makeStringAndClear();
530 eRet = D_STRING;
532 else
534 aData = aTmpLine;
537 break;
538 case '1': // String Data
539 if( Is1_0( aLine.getStr() ) )
541 ReadNextLine( aLine );
542 sal_Int32 nLineLength = aLine.getLength();
543 const sal_Unicode* pLine = aLine.getStr();
545 if( nLineLength >= 1 && *pLine == '"' )
547 // Quotes are not always escaped (duplicated), see lcl_DeEscapeQuotesDif
548 // A look ahead into the next line is needed in order to deal with
549 // multiline strings containing quotes
550 if( LookAhead() )
552 // Single line string
553 if( nLineLength >= 2 && pLine[nLineLength - 1] == '"' )
555 aData = aLine.copy( 1, nLineLength - 2 );
556 lcl_DeEscapeQuotesDif( aData );
557 eRet = D_STRING;
560 else
562 // Multiline string
563 aData = aLine.copy( 1 );
564 bool bContinue = true;
565 while ( bContinue )
567 aData = aData + "\n";
568 bContinue = !rIn.IsEof() && ReadNextLine( aLine );
569 if( bContinue )
571 nLineLength = aLine.getLength();
572 if( nLineLength >= 1 )
574 pLine = aLine.getStr();
575 bContinue = !LookAhead();
576 if( bContinue )
578 aData = aData + aLine;
580 else if( pLine[nLineLength - 1] == '"' )
582 aData = aData + aLine.copy(0, nLineLength -1 );
583 lcl_DeEscapeQuotesDif( aData );
584 eRet = D_STRING;
592 break;
595 if( eRet == D_UNKNOWN )
596 ReadNextLine( aLine );
598 if( rIn.IsEof() )
599 eRet = D_EOD;
601 return eRet;
605 const sal_Unicode* DifParser::ScanIntVal( const sal_Unicode* pStart, sal_uInt32& rRet )
607 // eat leading whitespace, not specified, but seen in the wild
608 while (*pStart == ' ' || *pStart == '\t')
609 ++pStart;
611 sal_Unicode cAkt = *pStart;
613 if( IsNumber( cAkt ) )
614 rRet = ( sal_uInt32 ) ( cAkt - '0' );
615 else
616 return NULL;
618 pStart++;
619 cAkt = *pStart;
621 while( IsNumber( cAkt ) && rRet < ( 0xFFFFFFFF / 10 ) )
623 rRet *= 10;
624 rRet += ( sal_uInt32 ) ( cAkt - '0' );
626 pStart++;
627 cAkt = *pStart;
630 return pStart;
634 sal_Bool DifParser::ScanFloatVal( const sal_Unicode* pStart )
636 sal_Bool bNeg = false;
637 double fFracPos = 1.0;
638 sal_Int32 nExp = 0;
639 sal_Bool bExpNeg = false;
640 sal_Bool bExpOverflow = false;
641 static const sal_uInt16 nExpLimit = 4096; // ACHTUNG: muss genauer ermittelt werden!
643 sal_Unicode cAkt;
644 sal_Bool bRet = false;
646 enum STATE { S_FIRST, S_PRE, S_POST, S_EXP_FIRST, S_EXP, S_END, S_FINDEND };
648 STATE eS = S_FIRST;
650 double fNewVal = 0.0;
652 while( eS != S_END )
654 cAkt = *pStart;
655 switch( eS )
657 case S_FIRST:
658 if( IsNumber( cAkt ) )
660 fNewVal *= 10;
661 fNewVal += cAkt - '0';
662 eS = S_PRE;
664 else
666 switch( cAkt )
668 case ' ':
669 case '\t':
670 case '+':
671 break;
672 case '-':
673 bNeg = !bNeg;
674 break;
675 case '.':
676 case ',': //!
677 eS = S_POST;
678 fFracPos = 0.1;
679 break;
680 default:
681 eS = S_END;
684 break;
685 case S_PRE:
686 if( IsNumber( cAkt ) )
688 fNewVal *= 10;
689 fNewVal += cAkt - '0';
691 else
693 switch( cAkt )
695 case '.':
696 case ',': //!
697 eS = S_POST;
698 fFracPos = 0.1;
699 break;
700 case 'e':
701 case 'E':
702 eS = S_EXP;
703 break;
704 case 0x00: // IsNumberEnding( cAkt )
705 bRet = sal_True; // no
706 default: // break!
707 eS = S_END;
710 break;
711 case S_POST:
712 if( IsNumber( cAkt ) )
714 fNewVal += fFracPos * ( cAkt - '0' );
715 fFracPos /= 10.0;
717 else
719 switch( cAkt )
721 case 'e':
722 case 'E':
723 eS = S_EXP_FIRST;
724 break;
725 case 0x00: // IsNumberEnding( cAkt )
726 bRet = sal_True; // no
727 default: // break!
728 eS = S_END;
731 break;
732 case S_EXP_FIRST:
733 if( IsNumber( cAkt ) )
735 if( nExp < nExpLimit )
737 nExp *= 10;
738 nExp += ( sal_uInt16 ) ( cAkt - '0' );
740 eS = S_EXP;
742 else
744 switch( cAkt )
746 case '+':
747 break;
748 case '-':
749 bExpNeg = !bExpNeg;
750 break;
751 default:
752 eS = S_END;
755 break;
756 case S_EXP:
757 if( IsNumber( cAkt ) )
759 if( nExp < ( 0xFFFF / 10 ) )
761 nExp *= 10;
762 nExp += ( sal_uInt16 ) ( cAkt - '0' );
764 else
766 bExpOverflow = sal_True;
767 eS = S_FINDEND;
770 else
772 bRet = IsNumberEnding( cAkt );
773 eS = S_END;
775 break;
776 case S_FINDEND:
777 if( IsNumberEnding( cAkt ) )
779 bRet = sal_True; // damit sinnvoll weitergeparst werden kann
780 eS = S_END;
782 break;
783 case S_END:
784 OSL_FAIL( "DifParser::ScanFloatVal - unexpected state" );
785 break;
786 default:
787 OSL_FAIL( "DifParser::ScanFloatVal - missing enum" );
789 pStart++;
792 if( bRet )
794 if( bExpOverflow )
795 return false; // ACHTUNG: hier muss noch differenziert werden
797 if( bNeg )
798 fNewVal *= 1.0;
800 if( bExpNeg )
801 nExp *= -1;
803 if( nExp != 0 )
804 fNewVal *= pow( 10.0, ( double ) nExp );
805 fVal = fNewVal;
808 return bRet;
811 DifColumn::DifColumn ()
812 : pAkt(NULL)
816 void DifColumn::SetLogical( SCROW nRow )
818 OSL_ENSURE( ValidRow(nRow), "*DifColumn::SetLogical(): Row too big!" );
820 if( pAkt )
822 OSL_ENSURE( nRow > 0, "*DifColumn::SetLogical(): more cannot be zero!" );
824 nRow--;
826 if( pAkt->nEnd == nRow )
827 pAkt->nEnd++;
828 else
829 pAkt = NULL;
831 else
833 pAkt = new ENTRY;
834 pAkt->nStart = pAkt->nEnd = nRow;
836 aEntries.push_back(pAkt);
841 void DifColumn::SetNumFormat( SCROW nRow, const sal_uInt32 nNumFormat )
843 OSL_ENSURE( ValidRow(nRow), "*DifColumn::SetNumFormat(): Row too big!" );
845 if( nNumFormat > 0 )
847 if(pAkt)
849 OSL_ENSURE( nRow > 0,
850 "*DifColumn::SetNumFormat(): more cannot be zero!" );
851 OSL_ENSURE( nRow > pAkt->nEnd,
852 "*DifColumn::SetNumFormat(): start from scratch?" );
854 if( pAkt->nNumFormat == nNumFormat && pAkt->nEnd == nRow - 1 )
855 pAkt->nEnd = nRow;
856 else
857 NewEntry( nRow, nNumFormat );
859 else
860 NewEntry(nRow,nNumFormat );
862 else
863 pAkt = NULL;
867 void DifColumn::NewEntry( const SCROW nPos, const sal_uInt32 nNumFormat )
869 pAkt = new ENTRY;
870 pAkt->nStart = pAkt->nEnd = nPos;
871 pAkt->nNumFormat = nNumFormat;
873 aEntries.push_back(pAkt);
877 void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab, const ScPatternAttr& rPattAttr )
879 for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
880 rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, rPattAttr );
884 void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab )
886 ScPatternAttr aAttr( rDoc.GetPool() );
887 SfxItemSet &rItemSet = aAttr.GetItemSet();
889 for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
891 OSL_ENSURE( it->nNumFormat > 0,
892 "+DifColumn::Apply(): Numberformat darf hier nicht 0 sein!" );
894 rItemSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, it->nNumFormat ) );
896 rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, aAttr );
898 rItemSet.ClearItem();
903 DifAttrCache::DifAttrCache( const sal_Bool bNewPlain )
905 bPlain = bNewPlain;
906 ppCols = new DifColumn *[ MAXCOL + 1 ];
907 for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
908 ppCols[ nCnt ] = NULL;
912 DifAttrCache::~DifAttrCache()
914 for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
916 if( ppCols[ nCnt ] )
917 delete ppCols[ nCnt ];
920 delete[] ppCols;
923 void DifAttrCache::SetLogical( const SCCOL nCol, const SCROW nRow )
925 OSL_ENSURE( ValidCol(nCol), "-DifAttrCache::SetLogical(): Col too big!" );
926 OSL_ENSURE( bPlain, "*DifAttrCache::SetLogical(): has to be Plain!" );
928 if( !ppCols[ nCol ] )
929 ppCols[ nCol ] = new DifColumn;
931 ppCols[ nCol ]->SetLogical( nRow );
934 void DifAttrCache::SetNumFormat( const SCCOL nCol, const SCROW nRow, const sal_uInt32 nNumFormat )
936 OSL_ENSURE( ValidCol(nCol), "-DifAttrCache::SetNumFormat(): Col too big!" );
937 OSL_ENSURE( !bPlain, "*DifAttrCache::SetNumFormat(): should not be Plain!" );
939 if( !ppCols[ nCol ] )
940 ppCols[ nCol ] = new DifColumn;
942 ppCols[ nCol ]->SetNumFormat( nRow, nNumFormat );
946 void DifAttrCache::Apply( ScDocument& rDoc, SCTAB nTab )
948 if( bPlain )
950 ScPatternAttr* pPatt = NULL;
952 for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
954 if( ppCols[ nCol ] )
956 if( !pPatt )
958 pPatt = new ScPatternAttr( rDoc.GetPool() );
959 pPatt->GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT,
960 rDoc.GetFormatTable()->GetStandardFormat( NUMBERFORMAT_LOGICAL ) ) );
963 ppCols[ nCol ]->Apply( rDoc, nCol, nTab, *pPatt );
967 if( pPatt )
968 delete pPatt;
970 else
972 for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
974 if( ppCols[ nCol ] )
975 ppCols[ nCol ]->Apply( rDoc, nCol, nTab );
982 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */