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