Line data Source code
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 :
21 : #include <math.h>
22 :
23 : #include <svl/zforlist.hxx>
24 :
25 : #include "attrib.hxx"
26 : #include "cell.hxx"
27 : #include "dif.hxx"
28 : #include "docpool.hxx"
29 : #include "document.hxx"
30 : #include "filter.hxx"
31 : #include "fprogressbar.hxx"
32 : #include "ftools.hxx"
33 : #include "patattr.hxx"
34 : #include "scerrors.hxx"
35 : #include "scitems.hxx"
36 :
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 };
49 :
50 :
51 0 : FltError ScFormatFilterPluginImpl::ScImportDif( SvStream& rIn, ScDocument* pDoc, const ScAddress& rInsPos,
52 : const CharSet eVon, sal_uInt32 nDifOption )
53 : {
54 0 : DifParser aDifParser( rIn, nDifOption, *pDoc, eVon );
55 :
56 0 : const sal_Bool bPlain = aDifParser.IsPlain();
57 :
58 0 : SCTAB nBaseTab = rInsPos.Tab();
59 :
60 0 : TOPIC eTopic = T_UNKNOWN;
61 0 : sal_Bool bSyntErrWarn = false;
62 0 : sal_Bool bOverflowWarn = false;
63 :
64 0 : rtl::OUString aData = aDifParser.aData;
65 0 : sal_Bool bData = false;
66 :
67 0 : rIn.Seek( 0 );
68 :
69 0 : ScfStreamProgressBar aPrgrsBar( rIn, pDoc->GetDocumentShell() );
70 :
71 0 : while( eTopic != T_DATA && eTopic != T_END )
72 : {
73 0 : eTopic = aDifParser.GetNextTopic();
74 :
75 0 : aPrgrsBar.Progress();
76 :
77 0 : bData = !aData.isEmpty();
78 :
79 0 : switch( eTopic )
80 : {
81 : case T_TABLE:
82 : {
83 0 : if( aDifParser.nVector != 0 || aDifParser.nVal != 1 )
84 0 : bSyntErrWarn = sal_True;
85 0 : if( bData )
86 0 : pDoc->RenameTab( nBaseTab, aData );
87 : }
88 0 : break;
89 : case T_VECTORS:
90 : {
91 0 : if( aDifParser.nVector != 0 )
92 0 : bSyntErrWarn = true;
93 : }
94 0 : break;
95 : case T_TUPLES:
96 : {
97 0 : if( aDifParser.nVector != 0 )
98 0 : bSyntErrWarn = true;
99 : }
100 0 : break;
101 : case T_DATA:
102 : {
103 0 : if( aDifParser.nVector != 0 || aDifParser.nVal != 0 )
104 0 : bSyntErrWarn = sal_True;
105 : }
106 0 : break;
107 : case T_LABEL:
108 : case T_COMMENT:
109 : case T_SIZE:
110 : case T_PERIODICITY:
111 : case T_MAJORSTART:
112 : case T_MINORSTART:
113 : case T_TRUELENGTH:
114 : case T_UINITS:
115 : case T_DISPLAYUNITS:
116 : case T_END:
117 : case T_UNKNOWN:
118 0 : break;
119 : default:
120 : OSL_FAIL( "ScImportDif - missing enum" );
121 : }
122 :
123 : }
124 :
125 :
126 0 : if( eTopic == T_DATA )
127 : { // Ab hier kommen die Daten
128 0 : SCCOL nBaseCol = rInsPos.Col();
129 :
130 0 : SCCOL nColCnt = SCCOL_MAX;
131 0 : SCROW nRowCnt = rInsPos.Row();
132 0 : DifAttrCache aAttrCache( bPlain );
133 :
134 0 : DATASET eAkt = D_UNKNOWN;
135 :
136 0 : while( eAkt != D_EOD )
137 : {
138 0 : eAkt = aDifParser.GetNextDataset();
139 :
140 0 : aPrgrsBar.Progress();
141 :
142 0 : switch( eAkt )
143 : {
144 : case D_BOT:
145 0 : if( nColCnt < SCCOL_MAX )
146 0 : nRowCnt++;
147 0 : nColCnt = nBaseCol;
148 0 : break;
149 : case D_EOD:
150 0 : break;
151 : case D_NUMERIC: // Numbercell
152 0 : if( nColCnt == SCCOL_MAX )
153 0 : nColCnt = nBaseCol;
154 :
155 0 : if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
156 : {
157 : ScBaseCell* pCell;
158 0 : if( DifParser::IsV( aData.getStr() ) )
159 : {
160 0 : pCell = new ScValueCell( aDifParser.fVal );
161 0 : if( !bPlain )
162 : aAttrCache.SetNumFormat( nColCnt, nRowCnt,
163 0 : aDifParser.nNumFormat );
164 : }
165 0 : else if( aData == pKeyTRUE || aData == pKeyFALSE )
166 : {
167 0 : pCell = new ScValueCell( aDifParser.fVal );
168 0 : if( bPlain )
169 0 : aAttrCache.SetLogical( nColCnt, nRowCnt );
170 : else
171 : aAttrCache.SetNumFormat( nColCnt, nRowCnt,
172 0 : aDifParser.nNumFormat );
173 : }
174 0 : else if( aData == pKeyNA || aData == pKeyERROR )
175 0 : pCell = new ScStringCell( aData );
176 : else
177 : {
178 0 : String aTmp( RTL_CONSTASCII_USTRINGPARAM( "#IND: " ));
179 0 : aTmp += aData;
180 0 : aTmp += sal_Unicode('?');
181 0 : pCell = new ScStringCell( aTmp );
182 : }
183 :
184 0 : pDoc->PutCell( nColCnt, nRowCnt, nBaseTab, pCell, true );
185 : }
186 : else
187 0 : bOverflowWarn = sal_True;
188 :
189 0 : nColCnt++;
190 0 : break;
191 : case D_STRING: // Textcell
192 0 : if( nColCnt == SCCOL_MAX )
193 0 : nColCnt = nBaseCol;
194 :
195 0 : if( ValidCol(nColCnt) && ValidRow(nRowCnt) )
196 : {
197 0 : if (!aData.isEmpty())
198 : {
199 : pDoc->PutCell( nColCnt, nRowCnt, nBaseTab,
200 0 : ScBaseCell::CreateTextCell( aData, pDoc ), true );
201 : }
202 : }
203 : else
204 0 : bOverflowWarn = sal_True;
205 :
206 0 : nColCnt++;
207 0 : break;
208 : case D_UNKNOWN:
209 0 : break;
210 : case D_SYNT_ERROR:
211 0 : break;
212 : default:
213 : OSL_FAIL( "ScImportDif - missing enum" );
214 : }
215 : }
216 :
217 0 : aAttrCache.Apply( *pDoc, nBaseTab );
218 : }
219 : else
220 0 : return eERR_FORMAT;
221 :
222 0 : if( bSyntErrWarn )
223 : //###############################################
224 : // ACHTUNG: Hier fehlt noch die richtige Warnung!
225 0 : return eERR_RNGOVRFLW;
226 : //###############################################
227 0 : else if( bOverflowWarn )
228 0 : return eERR_RNGOVRFLW;
229 : else
230 0 : return eERR_OK;
231 : }
232 :
233 :
234 0 : DifParser::DifParser( SvStream& rNewIn, const sal_uInt32 nOption, ScDocument& rDoc, CharSet e ) :
235 0 : rIn( rNewIn )
236 : {
237 0 : eCharSet = e;
238 0 : if ( rIn.GetStreamCharSet() != eCharSet )
239 : {
240 : OSL_FAIL( "CharSet passed overrides and modifies StreamCharSet" );
241 0 : rIn.SetStreamCharSet( eCharSet );
242 : }
243 0 : rIn.StartReadingUnicodeText( eCharSet );
244 :
245 0 : bPlain = ( nOption == SC_DIFOPT_PLAIN );
246 :
247 0 : if( bPlain )
248 0 : pNumFormatter = NULL;
249 : else
250 0 : pNumFormatter = rDoc.GetFormatTable();
251 0 : }
252 :
253 :
254 0 : TOPIC DifParser::GetNextTopic( void )
255 : {
256 : enum STATE { S_VectorVal, S_Data, S_END, S_START, S_UNKNOWN, S_ERROR_L2 };
257 :
258 : static const sal_Unicode pKeyLABEL[] = { 'L', 'A', 'B', 'E', 'L', 0 };
259 : static const sal_Unicode pKeyCOMMENT[] = { 'C', 'O', 'M', 'M', 'E', 'N', 'T', 0 };
260 : static const sal_Unicode pKeySIZE[] = { 'S', 'I', 'Z', 'E', 0 };
261 : static const sal_Unicode pKeyPERIODICITY[] = { 'P', 'E', 'R', 'I', 'O', 'D', 'I', 'C', 'I', 'T', 'Y', 0 };
262 : static const sal_Unicode pKeyMAJORSTART[] = { 'M', 'A', 'J', 'O', 'R', 'S', 'T', 'A', 'R', 'T', 0 };
263 : static const sal_Unicode pKeyMINORSTART[] = { 'M', 'I', 'N', 'O', 'R', 'S', 'T', 'A', 'R', 'T', 0 };
264 : static const sal_Unicode pKeyTRUELENGTH[] = { 'T', 'R', 'U', 'E', 'L', 'E', 'N', 'G', 'T', 'H', 0 };
265 : static const sal_Unicode pKeyUINITS[] = { 'U', 'I', 'N', 'I', 'T', 'S', 0 };
266 : static const sal_Unicode pKeyDISPLAYUNITS[] = { 'D', 'I', 'S', 'P', 'L', 'A', 'Y', 'U', 'N', 'I', 'T', 'S', 0 };
267 : static const sal_Unicode pKeyUNKNOWN[] = { 0 };
268 :
269 : static const sal_Unicode* ppKeys[] =
270 : {
271 : pKeyTABLE, // 0
272 : pKeyVECTORS,
273 : pKeyTUPLES,
274 : pKeyDATA,
275 : pKeyLABEL,
276 : pKeyCOMMENT, // 5
277 : pKeySIZE,
278 : pKeyPERIODICITY,
279 : pKeyMAJORSTART,
280 : pKeyMINORSTART,
281 : pKeyTRUELENGTH, // 10
282 : pKeyUINITS,
283 : pKeyDISPLAYUNITS,
284 : pKeyUNKNOWN // 13
285 : };
286 :
287 : static const TOPIC pTopics[] =
288 : {
289 : T_TABLE, // 0
290 : T_VECTORS,
291 : T_TUPLES,
292 : T_DATA,
293 : T_LABEL,
294 : T_COMMENT, // 5
295 : T_SIZE,
296 : T_PERIODICITY,
297 : T_MAJORSTART,
298 : T_MINORSTART,
299 : T_TRUELENGTH, // 10
300 : T_UINITS,
301 : T_DISPLAYUNITS,
302 : T_UNKNOWN // 13
303 : };
304 :
305 0 : STATE eS = S_START;
306 0 : rtl::OUString aLine;
307 :
308 0 : nVector = 0;
309 0 : nVal = 0;
310 0 : TOPIC eRet = T_UNKNOWN;
311 :
312 0 : while( eS != S_END )
313 : {
314 0 : if( !ReadNextLine( aLine ) )
315 : {
316 0 : eS = S_END;
317 0 : eRet = T_END;
318 : }
319 :
320 0 : switch( eS )
321 : {
322 : case S_START:
323 : {
324 : const sal_Unicode* pRef;
325 0 : sal_uInt16 nCnt = 0;
326 0 : sal_Bool bSearch = sal_True;
327 :
328 0 : pRef = ppKeys[ nCnt ];
329 :
330 0 : while( bSearch )
331 : {
332 0 : if( aLine == pRef )
333 : {
334 0 : eRet = pTopics[ nCnt ];
335 0 : bSearch = false;
336 : }
337 : else
338 : {
339 0 : nCnt++;
340 0 : pRef = ppKeys[ nCnt ];
341 0 : if( !*pRef )
342 0 : bSearch = false;
343 : }
344 : }
345 :
346 0 : if( *pRef )
347 0 : eS = S_VectorVal;
348 : else
349 0 : eS = S_UNKNOWN;
350 : }
351 0 : break;
352 : case S_VectorVal:
353 : {
354 0 : const sal_Unicode* pCur = aLine.getStr();
355 :
356 0 : pCur = ScanIntVal( pCur, nVector );
357 :
358 0 : if( pCur && *pCur == ',' )
359 : {
360 0 : pCur++;
361 0 : ScanIntVal( pCur, nVal );
362 0 : eS = S_Data;
363 : }
364 : else
365 0 : eS = S_ERROR_L2;
366 : }
367 0 : break;
368 : case S_Data:
369 : OSL_ENSURE( aLine.getLength() >= 2,
370 : "+GetNextTopic(): <String> ist zu kurz!" );
371 : OSL_ENSURE( aLine.getLength() - 2 <= STRING_MAXLEN, "GetNextTopic(): line doesn't fit into data");
372 0 : if( aLine.getLength() > 2 )
373 0 : aData = aLine.copy( 1, aLine.getLength() - 2 );
374 : else
375 0 : aData.Erase();
376 0 : eS = S_END;
377 0 : break;
378 : case S_END:
379 : OSL_FAIL( "DifParser::GetNextTopic - unexpected state" );
380 0 : break;
381 : case S_UNKNOWN:
382 : // 2 Zeilen ueberlesen
383 0 : ReadNextLine( aLine );
384 : case S_ERROR_L2: // Fehler in Line 2 aufgetreten
385 : // eine Zeile ueberlesen
386 0 : ReadNextLine( aLine );
387 0 : eS = S_END;
388 0 : break;
389 : default:
390 : OSL_FAIL( "DifParser::GetNextTopic - missing enum" );
391 : }
392 : }
393 :
394 0 : return eRet;
395 : }
396 :
397 :
398 0 : static void lcl_DeEscapeQuotesDif( String& rString )
399 : {
400 : // Special handling for DIF import: Escaped (duplicated) quotes are resolved.
401 : // Single quote characters are left in place because older versions didn't
402 : // escape quotes in strings (and Excel doesn't when using the clipboard).
403 : // The quotes around the string are removed before this function is called.
404 :
405 : static const sal_Unicode aDQ[] = { '"', '"', 0 };
406 0 : xub_StrLen nPos = 0;
407 0 : while ( (nPos = rString.Search( aDQ, nPos )) != STRING_NOTFOUND )
408 : {
409 0 : rString.Erase( nPos, 1 );
410 0 : ++nPos;
411 : }
412 0 : }
413 :
414 : // Determine if passed in string is numeric data and set fVal/nNumFormat if so
415 0 : DATASET DifParser::GetNumberDataset( const sal_Unicode* pPossibleNumericData )
416 : {
417 0 : DATASET eRet = D_SYNT_ERROR;
418 0 : if( bPlain )
419 : {
420 0 : if( ScanFloatVal( pPossibleNumericData ) )
421 0 : eRet = D_NUMERIC;
422 : else
423 0 : eRet = D_SYNT_ERROR;
424 : }
425 : else
426 : { // ...und zur Strafe mit'm Numberformatter...
427 : OSL_ENSURE( pNumFormatter, "-DifParser::GetNextDataset(): No Formatter, more fun!" );
428 0 : rtl::OUString aTestVal( pPossibleNumericData );
429 0 : sal_uInt32 nFormat = 0;
430 : double fTmpVal;
431 0 : if( pNumFormatter->IsNumberFormat( aTestVal, nFormat, fTmpVal ) )
432 : {
433 0 : fVal = fTmpVal;
434 0 : nNumFormat = nFormat;
435 0 : eRet = D_NUMERIC;
436 : }
437 : else
438 0 : eRet = D_SYNT_ERROR;
439 : }
440 0 : return eRet;
441 : }
442 :
443 0 : bool DifParser::ReadNextLine( rtl::OUString& rStr )
444 : {
445 0 : if( aLookAheadLine.isEmpty() )
446 : {
447 0 : return rIn.ReadUniOrByteStringLine( rStr, rIn.GetStreamCharSet() );
448 : }
449 : else
450 : {
451 0 : rStr = aLookAheadLine;
452 0 : aLookAheadLine = rtl::OUString();
453 0 : return true;
454 : }
455 : }
456 :
457 : // Look ahead in the stream to determine if the next line is the first line of
458 : // a valid data record structure
459 0 : bool DifParser::LookAhead()
460 : {
461 : const sal_Unicode* pAktBuffer;
462 0 : bool bValidStructure = false;
463 :
464 : OSL_ENSURE( aLookAheadLine.isEmpty(), "*DifParser::LookAhead(): LookAhead called twice in a row" );
465 0 : rIn.ReadUniOrByteStringLine( aLookAheadLine, rIn.GetStreamCharSet() );
466 :
467 0 : pAktBuffer = aLookAheadLine.getStr();
468 :
469 0 : switch( *pAktBuffer )
470 : {
471 : case '-': // Special Datatype
472 0 : pAktBuffer++;
473 :
474 0 : if( Is1_0( pAktBuffer ) )
475 : {
476 0 : bValidStructure = true;
477 : }
478 0 : break;
479 : case '0': // Numeric Data
480 0 : pAktBuffer++;
481 0 : if( *pAktBuffer == ',' )
482 : {
483 0 : pAktBuffer++;
484 0 : bValidStructure = ( GetNumberDataset(pAktBuffer) != D_SYNT_ERROR );
485 : }
486 0 : break;
487 : case '1': // String Data
488 0 : if( Is1_0( aLookAheadLine.getStr() ) )
489 : {
490 0 : bValidStructure = true;
491 : }
492 0 : break;
493 : }
494 0 : return bValidStructure;
495 : }
496 :
497 0 : DATASET DifParser::GetNextDataset( void )
498 : {
499 0 : DATASET eRet = D_UNKNOWN;
500 0 : rtl::OUString aLine;
501 : const sal_Unicode* pAktBuffer;
502 :
503 0 : ReadNextLine( aLine );
504 :
505 0 : pAktBuffer = aLine.getStr();
506 :
507 0 : switch( *pAktBuffer )
508 : {
509 : case '-': // Special Datatype
510 0 : pAktBuffer++;
511 :
512 0 : if( Is1_0( pAktBuffer ) )
513 : {
514 0 : ReadNextLine( aLine );
515 0 : if( IsBOT( aLine.getStr() ) )
516 0 : eRet = D_BOT;
517 0 : else if( IsEOD( aLine.getStr() ) )
518 0 : eRet = D_EOD;
519 : }
520 0 : break;
521 : case '0': // Numeric Data
522 0 : pAktBuffer++; // Wert in fVal, 2. Zeile in aData
523 0 : if( *pAktBuffer == ',' )
524 : {
525 0 : pAktBuffer++;
526 0 : eRet = GetNumberDataset(pAktBuffer);
527 0 : rtl::OUString aTmpLine;
528 0 : ReadNextLine( aTmpLine );
529 0 : if ( eRet == D_SYNT_ERROR )
530 : { // for broken records write "#ERR: data" to cell
531 0 : String aTmp( RTL_CONSTASCII_USTRINGPARAM( "#ERR: " ));
532 0 : aTmp += pAktBuffer;
533 0 : aTmp.AppendAscii( " (" );
534 : OSL_ENSURE( aTmpLine.getLength() <= STRING_MAXLEN - aTmp.Len() - 1, "GetNextDataset(): line doesn't fit into data");
535 0 : aTmp += aTmpLine;
536 0 : aTmp += sal_Unicode(')');
537 0 : aData = aTmp;
538 0 : eRet = D_STRING;
539 : }
540 : else
541 : {
542 : OSL_ENSURE( aTmpLine.getLength() <= STRING_MAXLEN, "GetNextDataset(): line doesn't fit into data");
543 0 : aData = aTmpLine;
544 0 : }
545 : }
546 0 : break;
547 : case '1': // String Data
548 0 : if( Is1_0( aLine.getStr() ) )
549 : {
550 0 : ReadNextLine( aLine );
551 0 : sal_Int32 nLineLength = aLine.getLength();
552 0 : const sal_Unicode* pLine = aLine.getStr();
553 :
554 0 : if( nLineLength >= 1 && *pLine == '"' )
555 : {
556 : // Quotes are not always escaped (duplicated), see lcl_DeEscapeQuotesDif
557 : // A look ahead into the next line is needed in order to deal with
558 : // multiline strings containing quotes
559 0 : if( LookAhead() )
560 : {
561 : // Single line string
562 0 : if( nLineLength >= 2 && pLine[nLineLength - 1] == '"' )
563 : {
564 : OSL_ENSURE( aLine.getLength() - 2 <= STRING_MAXLEN, "GetNextDataset(): line doesn't fit into data");
565 0 : aData = aLine.copy( 1, nLineLength - 2 );
566 0 : lcl_DeEscapeQuotesDif( aData );
567 0 : eRet = D_STRING;
568 : }
569 : }
570 : else
571 : {
572 : // Multiline string
573 : OSL_ENSURE( aLine.getLength() - 1 <= STRING_MAXLEN, "GetNextDataset(): line doesn't fit into data");
574 0 : aData = aLine.copy( 1 );
575 0 : bool bContinue = true;
576 0 : while ( bContinue )
577 : {
578 0 : aData.Append( '\n' );
579 0 : bContinue = !rIn.IsEof() && ReadNextLine( aLine );
580 0 : if( bContinue )
581 : {
582 0 : nLineLength = aLine.getLength();
583 0 : if( nLineLength >= 1 )
584 : {
585 0 : pLine = aLine.getStr();
586 0 : bContinue = !LookAhead();
587 0 : if( bContinue )
588 : {
589 : OSL_ENSURE( aLine.getLength() <= STRING_MAXLEN - aData.Len(), "GetNextDataset(): line doesn't fit into data");
590 0 : aData.Append( aLine );
591 : }
592 0 : else if( pLine[nLineLength - 1] == '"' )
593 : {
594 : OSL_ENSURE( nLineLength - 1 <= STRING_MAXLEN - aData.Len(), "GetNextDataset(): line doesn't fit into data");
595 0 : aData.Append( pLine, nLineLength - 1 );
596 0 : lcl_DeEscapeQuotesDif( aData );
597 0 : eRet = D_STRING;
598 : }
599 : }
600 : }
601 : };
602 : }
603 : }
604 : }
605 0 : break;
606 : }
607 :
608 0 : if( eRet == D_UNKNOWN )
609 0 : ReadNextLine( aLine );
610 :
611 0 : if( rIn.IsEof() )
612 0 : eRet = D_EOD;
613 :
614 0 : return eRet;
615 : }
616 :
617 :
618 0 : const sal_Unicode* DifParser::ScanIntVal( const sal_Unicode* pStart, sal_uInt32& rRet )
619 : {
620 : // eat leading whitespace, not specified, but seen in the wild
621 0 : while (*pStart == ' ' || *pStart == '\t')
622 0 : ++pStart;
623 :
624 0 : sal_Unicode cAkt = *pStart;
625 :
626 0 : if( IsNumber( cAkt ) )
627 0 : rRet = ( sal_uInt32 ) ( cAkt - '0' );
628 : else
629 0 : return NULL;
630 :
631 0 : pStart++;
632 0 : cAkt = *pStart;
633 :
634 0 : while( IsNumber( cAkt ) && rRet < ( 0xFFFFFFFF / 10 ) )
635 : {
636 0 : rRet *= 10;
637 0 : rRet += ( sal_uInt32 ) ( cAkt - '0' );
638 :
639 0 : pStart++;
640 0 : cAkt = *pStart;
641 : }
642 :
643 0 : return pStart;
644 : }
645 :
646 :
647 0 : sal_Bool DifParser::ScanFloatVal( const sal_Unicode* pStart )
648 : {
649 0 : sal_Bool bNeg = false;
650 0 : double fFracPos = 1.0;
651 0 : sal_Int32 nExp = 0;
652 0 : sal_Bool bExpNeg = false;
653 0 : sal_Bool bExpOverflow = false;
654 : static const sal_uInt16 nExpLimit = 4096; // ACHTUNG: muss genauer ermittelt werden!
655 :
656 : sal_Unicode cAkt;
657 0 : sal_Bool bRet = false;
658 :
659 : enum STATE { S_FIRST, S_PRE, S_POST, S_EXP_FIRST, S_EXP, S_END, S_FINDEND };
660 :
661 0 : STATE eS = S_FIRST;
662 :
663 0 : double fNewVal = 0.0;
664 :
665 0 : while( eS != S_END )
666 : {
667 0 : cAkt = *pStart;
668 0 : switch( eS )
669 : {
670 : case S_FIRST:
671 0 : if( IsNumber( cAkt ) )
672 : {
673 0 : fNewVal *= 10;
674 0 : fNewVal += cAkt - '0';
675 0 : eS = S_PRE;
676 : }
677 : else
678 : {
679 0 : switch( cAkt )
680 : {
681 : case ' ':
682 : case '\t':
683 : case '+':
684 0 : break;
685 : case '-':
686 0 : bNeg = !bNeg;
687 0 : break;
688 : case '.':
689 : case ',': //!
690 0 : eS = S_POST;
691 0 : fFracPos = 0.1;
692 0 : break;
693 : default:
694 0 : eS = S_END;
695 : }
696 : }
697 0 : break;
698 : case S_PRE:
699 0 : if( IsNumber( cAkt ) )
700 : {
701 0 : fNewVal *= 10;
702 0 : fNewVal += cAkt - '0';
703 : }
704 : else
705 : {
706 0 : switch( cAkt )
707 : {
708 : case '.':
709 : case ',': //!
710 0 : eS = S_POST;
711 0 : fFracPos = 0.1;
712 0 : break;
713 : case 'e':
714 : case 'E':
715 0 : eS = S_EXP;
716 0 : break;
717 : case 0x00: // IsNumberEnding( cAkt )
718 0 : bRet = sal_True; // no
719 : default: // break!
720 0 : eS = S_END;
721 : }
722 : }
723 0 : break;
724 : case S_POST:
725 0 : if( IsNumber( cAkt ) )
726 : {
727 0 : fNewVal += fFracPos * ( cAkt - '0' );
728 0 : fFracPos /= 10.0;
729 : }
730 : else
731 : {
732 0 : switch( cAkt )
733 : {
734 : case 'e':
735 : case 'E':
736 0 : eS = S_EXP_FIRST;
737 0 : break;
738 : case 0x00: // IsNumberEnding( cAkt )
739 0 : bRet = sal_True; // no
740 : default: // break!
741 0 : eS = S_END;
742 : }
743 : }
744 0 : break;
745 : case S_EXP_FIRST:
746 0 : if( IsNumber( cAkt ) )
747 : {
748 0 : if( nExp < nExpLimit )
749 : {
750 0 : nExp *= 10;
751 0 : nExp += ( sal_uInt16 ) ( cAkt - '0' );
752 : }
753 0 : eS = S_EXP;
754 : }
755 : else
756 : {
757 0 : switch( cAkt )
758 : {
759 : case '+':
760 0 : break;
761 : case '-':
762 0 : bExpNeg = !bExpNeg;
763 0 : break;
764 : default:
765 0 : eS = S_END;
766 : }
767 : }
768 0 : break;
769 : case S_EXP:
770 0 : if( IsNumber( cAkt ) )
771 : {
772 0 : if( nExp < ( 0xFFFF / 10 ) )
773 : {
774 0 : nExp *= 10;
775 0 : nExp += ( sal_uInt16 ) ( cAkt - '0' );
776 : }
777 : else
778 : {
779 0 : bExpOverflow = sal_True;
780 0 : eS = S_FINDEND;
781 : }
782 : }
783 : else
784 : {
785 0 : bRet = IsNumberEnding( cAkt );
786 0 : eS = S_END;
787 : }
788 0 : break;
789 : case S_FINDEND:
790 0 : if( IsNumberEnding( cAkt ) )
791 : {
792 0 : bRet = sal_True; // damit sinnvoll weitergeparst werden kann
793 0 : eS = S_END;
794 : }
795 0 : break;
796 : case S_END:
797 : OSL_FAIL( "DifParser::ScanFloatVal - unexpected state" );
798 0 : break;
799 : default:
800 : OSL_FAIL( "DifParser::ScanFloatVal - missing enum" );
801 : }
802 0 : pStart++;
803 : }
804 :
805 0 : if( bRet )
806 : {
807 0 : if( bExpOverflow )
808 0 : return false; // ACHTUNG: hier muss noch differenziert werden
809 :
810 0 : if( bNeg )
811 0 : fNewVal *= 1.0;
812 :
813 0 : if( bExpNeg )
814 0 : nExp *= -1;
815 :
816 0 : if( nExp != 0 )
817 0 : fNewVal *= pow( 10.0, ( double ) nExp );
818 0 : fVal = fNewVal;
819 : }
820 :
821 0 : return bRet;
822 : }
823 :
824 0 : DifColumn::DifColumn ()
825 0 : : pAkt(NULL)
826 : {
827 0 : }
828 :
829 0 : void DifColumn::SetLogical( SCROW nRow )
830 : {
831 : OSL_ENSURE( ValidRow(nRow), "*DifColumn::SetLogical(): Row zu gross!" );
832 :
833 0 : if( pAkt )
834 : {
835 : OSL_ENSURE( nRow > 0, "*DifColumn::SetLogical(): weitere koennen nicht 0 sein!" );
836 :
837 0 : nRow--;
838 :
839 0 : if( pAkt->nEnd == nRow )
840 0 : pAkt->nEnd++;
841 : else
842 0 : pAkt = NULL;
843 : }
844 : else
845 : {
846 0 : pAkt = new ENTRY;
847 0 : pAkt->nStart = pAkt->nEnd = nRow;
848 :
849 0 : aEntries.push_back(pAkt);
850 : }
851 0 : }
852 :
853 :
854 0 : void DifColumn::SetNumFormat( SCROW nRow, const sal_uInt32 nNumFormat )
855 : {
856 : OSL_ENSURE( ValidRow(nRow), "*DifColumn::SetNumFormat(): Row zu gross!" );
857 :
858 0 : if( nNumFormat > 0 )
859 : {
860 0 : if(pAkt)
861 : {
862 : OSL_ENSURE( nRow > 0,
863 : "*DifColumn::SetNumFormat(): weitere koennen nicht 0 sein!" );
864 : OSL_ENSURE( nRow > pAkt->nEnd,
865 : "*DifColumn::SetNumFormat(): Noch 'mal von vorne?" );
866 :
867 0 : if( pAkt->nNumFormat == nNumFormat && pAkt->nEnd == nRow - 1 )
868 0 : pAkt->nEnd = nRow;
869 : else
870 0 : NewEntry( nRow, nNumFormat );
871 : }
872 : else
873 0 : NewEntry(nRow,nNumFormat );
874 : }
875 : else
876 0 : pAkt = NULL;
877 0 : }
878 :
879 :
880 0 : void DifColumn::NewEntry( const SCROW nPos, const sal_uInt32 nNumFormat )
881 : {
882 0 : pAkt = new ENTRY;
883 0 : pAkt->nStart = pAkt->nEnd = nPos;
884 0 : pAkt->nNumFormat = nNumFormat;
885 :
886 0 : aEntries.push_back(pAkt);
887 0 : }
888 :
889 :
890 0 : void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab, const ScPatternAttr& rPattAttr )
891 : {
892 0 : for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
893 0 : rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, rPattAttr );
894 0 : }
895 :
896 :
897 0 : void DifColumn::Apply( ScDocument& rDoc, const SCCOL nCol, const SCTAB nTab )
898 : {
899 0 : ScPatternAttr aAttr( rDoc.GetPool() );
900 0 : SfxItemSet &rItemSet = aAttr.GetItemSet();
901 :
902 0 : for (boost::ptr_vector<ENTRY>::const_iterator it = aEntries.begin(); it != aEntries.end(); ++it)
903 : {
904 : OSL_ENSURE( it->nNumFormat > 0,
905 : "+DifColumn::Apply(): Numberformat darf hier nicht 0 sein!" );
906 :
907 0 : rItemSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, it->nNumFormat ) );
908 :
909 0 : rDoc.ApplyPatternAreaTab( nCol, it->nStart, nCol, it->nEnd, nTab, aAttr );
910 :
911 0 : rItemSet.ClearItem();
912 0 : }
913 0 : }
914 :
915 :
916 0 : DifAttrCache::DifAttrCache( const sal_Bool bNewPlain )
917 : {
918 0 : bPlain = bNewPlain;
919 0 : ppCols = new DifColumn *[ MAXCOL + 1 ];
920 0 : for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
921 0 : ppCols[ nCnt ] = NULL;
922 0 : }
923 :
924 :
925 0 : DifAttrCache::~DifAttrCache()
926 : {
927 0 : for( SCCOL nCnt = 0 ; nCnt <= MAXCOL ; nCnt++ )
928 : {
929 0 : if( ppCols[ nCnt ] )
930 0 : delete ppCols[ nCnt ];
931 : }
932 0 : }
933 :
934 0 : void DifAttrCache::SetLogical( const SCCOL nCol, const SCROW nRow )
935 : {
936 : OSL_ENSURE( ValidCol(nCol), "-DifAttrCache::SetLogical(): Col zu gross!" );
937 : OSL_ENSURE( bPlain, "*DifAttrCache::SetLogical(): muss Plain sein!" );
938 :
939 0 : if( !ppCols[ nCol ] )
940 0 : ppCols[ nCol ] = new DifColumn;
941 :
942 0 : ppCols[ nCol ]->SetLogical( nRow );
943 0 : }
944 :
945 0 : void DifAttrCache::SetNumFormat( const SCCOL nCol, const SCROW nRow, const sal_uInt32 nNumFormat )
946 : {
947 : OSL_ENSURE( ValidCol(nCol), "-DifAttrCache::SetNumFormat(): Col zu gross!" );
948 : OSL_ENSURE( !bPlain, "*DifAttrCache::SetNumFormat(): sollte nicht Plain sein!" );
949 :
950 0 : if( !ppCols[ nCol ] )
951 0 : ppCols[ nCol ] = new DifColumn;
952 :
953 0 : ppCols[ nCol ]->SetNumFormat( nRow, nNumFormat );
954 0 : }
955 :
956 :
957 0 : void DifAttrCache::Apply( ScDocument& rDoc, SCTAB nTab )
958 : {
959 0 : if( bPlain )
960 : {
961 0 : ScPatternAttr* pPatt = NULL;
962 :
963 0 : for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
964 : {
965 0 : if( ppCols[ nCol ] )
966 : {
967 0 : if( !pPatt )
968 : {
969 0 : pPatt = new ScPatternAttr( rDoc.GetPool() );
970 0 : pPatt->GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT,
971 0 : rDoc.GetFormatTable()->GetStandardFormat( NUMBERFORMAT_LOGICAL ) ) );
972 : }
973 :
974 0 : ppCols[ nCol ]->Apply( rDoc, nCol, nTab, *pPatt );
975 : }
976 : }
977 :
978 0 : if( pPatt )
979 0 : delete pPatt;
980 : }
981 : else
982 : {
983 0 : for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
984 : {
985 0 : if( ppCols[ nCol ] )
986 0 : ppCols[ nCol ]->Apply( rDoc, nCol, nTab );
987 : }
988 : }
989 0 : }
990 :
991 :
992 :
993 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|