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