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