fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / dif / difimp.cxx
blobf46d25c8d324ccfcc3603febb45e6be78670fcba
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 .
20 #include <math.h>
22 #include <svl/zforlist.hxx>
23 #include <osl/diagnose.h>
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"
35 #include <boost/scoped_ptr.hpp>
37 const sal_Unicode pKeyTABLE[] = { 'T', 'A', 'B', 'L', 'E', 0 };
38 const sal_Unicode pKeyVECTORS[] = { 'V', 'E', 'C', 'T', 'O', 'R', 'S', 0 };
39 const sal_Unicode pKeyTUPLES[] = { 'T', 'U', 'P', 'L', 'E', 'S', 0 };
40 const sal_Unicode pKeyDATA[] = { 'D', 'A', 'T', 'A', 0 };
41 const sal_Unicode pKeyBOT[] = { 'B', 'O', 'T', 0 };
42 const sal_Unicode pKeyEOD[] = { 'E', 'O', 'D', 0 };
43 const sal_Unicode pKeyERROR[] = { 'E', 'R', 'R', 'O', 'R', 0 };
44 const sal_Unicode pKeyTRUE[] = { 'T', 'R', 'U', 'E', 0 };
45 const sal_Unicode pKeyFALSE[] = { 'F', 'A', 'L', 'S', 'E', 0 };
46 const sal_Unicode pKeyNA[] = { 'N', 'A', 0 };
47 const sal_Unicode pKeyV[] = { 'V', 0 };
48 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;
65 rIn.Seek( 0 );
67 ScfStreamProgressBar aPrgrsBar( rIn, pDoc->GetDocumentShell() );
69 while( eTopic != T_DATA && eTopic != T_END )
71 eTopic = aDifParser.GetNextTopic();
73 aPrgrsBar.Progress();
75 const bool bData = !aData.isEmpty();
77 switch( eTopic )
79 case T_TABLE:
81 if( aDifParser.nVector != 0 || aDifParser.nVal != 1 )
82 bSyntErrWarn = true;
83 if( bData )
84 pDoc->RenameTab( nBaseTab, aData );
86 break;
87 case T_VECTORS:
89 if( aDifParser.nVector != 0 )
90 bSyntErrWarn = true;
92 break;
93 case T_TUPLES:
95 if( aDifParser.nVector != 0 )
96 bSyntErrWarn = true;
98 break;
99 case T_DATA:
101 if( aDifParser.nVector != 0 || aDifParser.nVal != 0 )
102 bSyntErrWarn = true;
104 break;
105 case T_LABEL:
106 case T_COMMENT:
107 case T_SIZE:
108 case T_PERIODICITY:
109 case T_MAJORSTART:
110 case T_MINORSTART:
111 case T_TRUELENGTH:
112 case T_UINITS:
113 case T_DISPLAYUNITS:
114 case T_END:
115 case T_UNKNOWN:
116 break;
117 default:
118 OSL_FAIL( "ScImportDif - missing enum" );
123 if( eTopic == T_DATA )
124 { // data starts here
125 SCCOL nBaseCol = rInsPos.Col();
127 SCCOL nColCnt = SCCOL_MAX;
128 SCROW nRowCnt = rInsPos.Row();
129 DifAttrCache aAttrCache( bPlain );
131 DATASET eAkt = D_UNKNOWN;
133 ScSetStringParam aStrParam; // used to set string value without number detection.
134 aStrParam.setTextInput();
136 while( eAkt != D_EOD )
138 eAkt = aDifParser.GetNextDataset();
140 aPrgrsBar.Progress();
141 ScAddress aPos(nColCnt, nRowCnt, nBaseTab);
143 switch( eAkt )
145 case D_BOT:
146 if( nColCnt < SCCOL_MAX )
147 nRowCnt++;
148 nColCnt = nBaseCol;
149 break;
150 case D_EOD:
151 break;
152 case D_NUMERIC: // Number cell
153 if( nColCnt == SCCOL_MAX )
154 nColCnt = nBaseCol;
156 if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
158 pDoc->EnsureTable(nBaseTab);
160 if( DifParser::IsV( aData.getStr() ) )
162 pDoc->SetValue(aPos, aDifParser.fVal);
163 if( !bPlain )
164 aAttrCache.SetNumFormat( nColCnt, nRowCnt,
165 aDifParser.nNumFormat );
167 else if( aData == pKeyTRUE || aData == pKeyFALSE )
169 pDoc->SetValue(aPos, aDifParser.fVal);
170 if( bPlain )
171 aAttrCache.SetLogical( nColCnt, nRowCnt );
172 else
173 aAttrCache.SetNumFormat( nColCnt, nRowCnt,
174 aDifParser.nNumFormat );
176 else if( aData == pKeyNA || aData == pKeyERROR )
178 pDoc->SetString(aPos, aData, &aStrParam);
180 else
182 OUString aTmp = "#IND:" + aData + "?";
183 pDoc->SetString(aPos, aTmp, &aStrParam);
186 else
187 bOverflowWarn = true;
189 nColCnt++;
190 break;
191 case D_STRING: // Text cell
192 if( nColCnt == SCCOL_MAX )
193 nColCnt = nBaseCol;
195 if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
197 if (!aData.isEmpty())
199 pDoc->EnsureTable(nBaseTab);
200 pDoc->SetTextCell(aPos, aData);
203 else
204 bOverflowWarn = true;
206 nColCnt++;
207 break;
208 case D_UNKNOWN:
209 break;
210 case D_SYNT_ERROR:
211 break;
212 default:
213 OSL_FAIL( "ScImportDif - missing enum" );
217 aAttrCache.Apply( *pDoc, nBaseTab );
219 else
220 return eERR_FORMAT;
222 if( bSyntErrWarn )
224 // FIXME: Add proper Warnung!
225 return eERR_RNGOVRFLW;
227 else if( bOverflowWarn )
228 return eERR_RNGOVRFLW;
229 else
230 return eERR_OK;
233 DifParser::DifParser( SvStream& rNewIn, const sal_uInt32 nOption, ScDocument& rDoc, rtl_TextEncoding e )
234 : fVal(0.0)
235 , nVector(0)
236 , nVal(0)
237 , nNumFormat(0)
238 , eCharSet(e)
239 , rIn(rNewIn)
241 if ( rIn.GetStreamCharSet() != eCharSet )
243 OSL_FAIL( "CharSet passed overrides and modifies StreamCharSet" );
244 rIn.SetStreamCharSet( eCharSet );
246 rIn.StartReadingUnicodeText( eCharSet );
248 bPlain = ( nOption == SC_DIFOPT_PLAIN );
250 if( bPlain )
251 pNumFormatter = NULL;
252 else
253 pNumFormatter = rDoc.GetFormatTable();
256 TOPIC DifParser::GetNextTopic()
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 bool bSearch = 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> is too short!" );
373 if( aLine.getLength() > 2 )
374 aData = aLine.copy( 1, aLine.getLength() - 2 );
375 else
376 aData.clear();
377 eS = S_END;
378 break;
379 case S_END:
380 OSL_FAIL( "DifParser::GetNextTopic - unexpected state" );
381 break;
382 case S_UNKNOWN:
383 // skip 2 lines
384 ReadNextLine( aLine );
385 // fall-through
386 case S_ERROR_L2: // error happened in line 2
387 // skip 1 line
388 ReadNextLine( aLine );
389 eS = S_END;
390 break;
391 default:
392 OSL_FAIL( "DifParser::GetNextTopic - missing enum" );
396 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 { // ...and for punishment, with number formatting...
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.clear();
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()
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++; // value in fVal, 2. line 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;
604 const sal_Unicode* DifParser::ScanIntVal( const sal_Unicode* pStart, sal_uInt32& rRet )
606 // eat leading whitespace, not specified, but seen in the wild
607 while (*pStart == ' ' || *pStart == '\t')
608 ++pStart;
610 sal_Unicode cAkt = *pStart;
612 if( IsNumber( cAkt ) )
613 rRet = ( sal_uInt32 ) ( cAkt - '0' );
614 else
615 return NULL;
617 pStart++;
618 cAkt = *pStart;
620 while( IsNumber( cAkt ) && rRet < ( 0xFFFFFFFF / 10 ) )
622 rRet *= 10;
623 rRet += ( sal_uInt32 ) ( cAkt - '0' );
625 pStart++;
626 cAkt = *pStart;
629 return pStart;
632 bool DifParser::ScanFloatVal( const sal_Unicode* pStart )
634 bool bNeg = false;
635 double fFracPos = 1.0;
636 sal_Int32 nExp = 0;
637 bool bExpNeg = false;
638 bool bExpOverflow = false;
639 static const sal_uInt16 nExpLimit = 4096; // FIXME: has to be set more accurately!
641 sal_Unicode cAkt;
642 bool bRet = false;
644 enum STATE { S_FIRST, S_PRE, S_POST, S_EXP_FIRST, S_EXP, S_END, S_FINDEND };
646 STATE eS = S_FIRST;
648 double fNewVal = 0.0;
650 while( eS != S_END )
652 cAkt = *pStart;
653 switch( eS )
655 case S_FIRST:
656 if( IsNumber( cAkt ) )
658 fNewVal *= 10;
659 fNewVal += cAkt - '0';
660 eS = S_PRE;
662 else
664 switch( cAkt )
666 case ' ':
667 case '\t':
668 case '+':
669 break;
670 case '-':
671 bNeg = !bNeg;
672 break;
673 case '.':
674 case ',':
675 eS = S_POST;
676 fFracPos = 0.1;
677 break;
678 default:
679 eS = S_END;
682 break;
683 case S_PRE:
684 if( IsNumber( cAkt ) )
686 fNewVal *= 10;
687 fNewVal += cAkt - '0';
689 else
691 switch( cAkt )
693 case '.':
694 case ',':
695 eS = S_POST;
696 fFracPos = 0.1;
697 break;
698 case 'e':
699 case 'E':
700 eS = S_EXP;
701 break;
702 case 0x00: // IsNumberEnding( cAkt )
703 bRet = true; // no
704 default: // break!
705 eS = S_END;
708 break;
709 case S_POST:
710 if( IsNumber( cAkt ) )
712 fNewVal += fFracPos * ( cAkt - '0' );
713 fFracPos /= 10.0;
715 else
717 switch( cAkt )
719 case 'e':
720 case 'E':
721 eS = S_EXP_FIRST;
722 break;
723 case 0x00: // IsNumberEnding( cAkt )
724 bRet = true; // no
725 default: // break!
726 eS = S_END;
729 break;
730 case S_EXP_FIRST:
731 if( IsNumber( cAkt ) )
733 if( nExp < nExpLimit )
735 nExp *= 10;
736 nExp += ( sal_uInt16 ) ( cAkt - '0' );
738 eS = S_EXP;
740 else
742 switch( cAkt )
744 case '+':
745 break;
746 case '-':
747 bExpNeg = !bExpNeg;
748 break;
749 default:
750 eS = S_END;
753 break;
754 case S_EXP:
755 if( IsNumber( cAkt ) )
757 if( nExp < ( 0xFFFF / 10 ) )
759 nExp *= 10;
760 nExp += ( sal_uInt16 ) ( cAkt - '0' );
762 else
764 bExpOverflow = true;
765 eS = S_FINDEND;
768 else
770 bRet = IsNumberEnding( cAkt );
771 eS = S_END;
773 break;
774 case S_FINDEND:
775 if( IsNumberEnding( cAkt ) )
777 bRet = true; // to continue parsing
778 eS = S_END;
780 break;
781 case S_END:
782 OSL_FAIL( "DifParser::ScanFloatVal - unexpected state" );
783 break;
784 default:
785 OSL_FAIL( "DifParser::ScanFloatVal - missing enum" );
787 pStart++;
790 if( bRet )
792 if( bExpOverflow )
793 return false; // FIXME: add special cases here
795 if( bNeg )
796 fNewVal *= 1.0;
798 if( bExpNeg )
799 nExp *= -1;
801 if( nExp != 0 )
802 fNewVal *= pow( 10.0, ( double ) nExp );
803 fVal = fNewVal;
806 return bRet;
809 DifColumn::DifColumn ()
810 : pAkt(NULL)
814 void DifColumn::SetLogical( SCROW nRow )
816 OSL_ENSURE( ValidRow(nRow), "*DifColumn::SetLogical(): Row too big!" );
818 if( pAkt )
820 OSL_ENSURE( nRow > 0, "*DifColumn::SetLogical(): more cannot be zero!" );
822 nRow--;
824 if( pAkt->nEnd == nRow )
825 pAkt->nEnd++;
826 else
827 pAkt = NULL;
829 else
831 pAkt = new ENTRY;
832 pAkt->nStart = pAkt->nEnd = nRow;
834 aEntries.push_back(pAkt);
838 void DifColumn::SetNumFormat( SCROW nRow, const sal_uInt32 nNumFormat )
840 OSL_ENSURE( ValidRow(nRow), "*DifColumn::SetNumFormat(): Row too big!" );
842 if( nNumFormat > 0 )
844 if(pAkt)
846 OSL_ENSURE( nRow > 0,
847 "*DifColumn::SetNumFormat(): more cannot be zero!" );
848 OSL_ENSURE( nRow > pAkt->nEnd,
849 "*DifColumn::SetNumFormat(): start from scratch?" );
851 if( pAkt->nNumFormat == nNumFormat && pAkt->nEnd == nRow - 1 )
852 pAkt->nEnd = nRow;
853 else
854 NewEntry( nRow, nNumFormat );
856 else
857 NewEntry(nRow,nNumFormat );
859 else
860 pAkt = NULL;
863 void DifColumn::NewEntry( const SCROW nPos, const sal_uInt32 nNumFormat )
865 pAkt = new ENTRY;
866 pAkt->nStart = pAkt->nEnd = nPos;
867 pAkt->nNumFormat = nNumFormat;
869 aEntries.push_back(pAkt);
872 void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab, const ScPatternAttr& rPattAttr )
874 for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
875 rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, rPattAttr );
878 void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab )
880 ScPatternAttr aAttr( rDoc.GetPool() );
881 SfxItemSet &rItemSet = aAttr.GetItemSet();
883 for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
885 OSL_ENSURE( it->nNumFormat > 0,
886 "+DifColumn::Apply(): Number format must not be 0!" );
888 rItemSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, it->nNumFormat ) );
890 rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, aAttr );
892 rItemSet.ClearItem();
896 DifAttrCache::DifAttrCache( const bool bNewPlain )
898 bPlain = bNewPlain;
899 ppCols = new DifColumn *[ MAXCOL + 1 ];
900 for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
901 ppCols[ nCnt ] = NULL;
904 DifAttrCache::~DifAttrCache()
906 for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
908 if( ppCols[ nCnt ] )
909 delete ppCols[ nCnt ];
912 delete[] ppCols;
915 void DifAttrCache::SetLogical( const SCCOL nCol, const SCROW nRow )
917 OSL_ENSURE( ValidCol(nCol), "-DifAttrCache::SetLogical(): Col too big!" );
918 OSL_ENSURE( bPlain, "*DifAttrCache::SetLogical(): has to be Plain!" );
920 if( !ppCols[ nCol ] )
921 ppCols[ nCol ] = new DifColumn;
923 ppCols[ nCol ]->SetLogical( nRow );
926 void DifAttrCache::SetNumFormat( const SCCOL nCol, const SCROW nRow, const sal_uInt32 nNumFormat )
928 OSL_ENSURE( ValidCol(nCol), "-DifAttrCache::SetNumFormat(): Col too big!" );
929 OSL_ENSURE( !bPlain, "*DifAttrCache::SetNumFormat(): should not be Plain!" );
931 if( !ppCols[ nCol ] )
932 ppCols[ nCol ] = new DifColumn;
934 ppCols[ nCol ]->SetNumFormat( nRow, nNumFormat );
937 void DifAttrCache::Apply( ScDocument& rDoc, SCTAB nTab )
939 if( bPlain )
941 boost::scoped_ptr<ScPatternAttr> pPatt;
943 for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
945 if( ppCols[ nCol ] )
947 if( !pPatt )
949 pPatt.reset(new ScPatternAttr( rDoc.GetPool() ));
950 pPatt->GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT,
951 rDoc.GetFormatTable()->GetStandardFormat( css::util::NumberFormat::LOGICAL ) ) );
954 ppCols[ nCol ]->Apply( rDoc, nCol, nTab, *pPatt );
958 else
960 for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
962 if( ppCols[ nCol ] )
963 ppCols[ nCol ]->Apply( rDoc, nCol, nTab );
968 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */