xref: /AOO41X/main/svtools/source/svrtf/svparser.cxx (revision 5900e8ec128faec89519683efce668ccd8cc6084)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
27 
28 #include <stdio.h>
29 #include <svtools/svparser.hxx>
30 #include <tools/stream.hxx>
31 #include <tools/debug.hxx>
32 #define _SVSTDARR_USHORTS
33 #include <svl/svstdarr.hxx>
34 #include <rtl/textcvt.h>
35 #include <rtl/tencinfo.h>
36 
37 #define SVPAR_CSM_
38 
39 #define SVPAR_CSM_ANSI      0x0001U
40 #define SVPAR_CSM_UTF8      0x0002U
41 #define SVPAR_CSM_UCS2B     0x0004U
42 #define SVPAR_CSM_UCS2L     0x0008U
43 #define SVPAR_CSM_SWITCH    0x8000U
44 
45 // Struktur, um sich die akt. Daten zumerken
46 struct SvParser_Impl
47 {
48     String          aToken;             // gescanntes Token
49     sal_uLong           nFilePos;           // akt. Position im Stream
50     sal_uLong           nlLineNr;           // akt. Zeilen Nummer
51     sal_uLong           nlLinePos;          // akt. Spalten Nummer
52     long            nTokenValue;        // zusaetzlicher Wert (RTF)
53     sal_Bool            bTokenHasValue;     // indicates whether nTokenValue is valid
54     int             nToken;             // akt. Token
55     sal_Unicode     nNextCh;            // akt. Zeichen
56 
57     int             nSaveToken;         // das Token vom Continue
58 
59     rtl_TextToUnicodeConverter hConv;
60     rtl_TextToUnicodeContext   hContext;
61 
62 #ifdef DBG_UTIL
63     SvFileStream aOut;
64 #endif
65 
SvParser_ImplSvParser_Impl66     SvParser_Impl() :
67         nSaveToken(0), hConv( 0 ), hContext( (rtl_TextToUnicodeContext)1 )
68     {
69     }
70 
71 };
72 
73 
74 
75 // Konstruktor
SvParser(SvStream & rIn,sal_uInt8 nStackSize)76 SvParser::SvParser( SvStream& rIn, sal_uInt8 nStackSize )
77     : rInput( rIn )
78     , nlLineNr( 1 )
79     , nlLinePos( 1 )
80     , pImplData( 0 )
81     , nTokenValue( 0 )
82     , bTokenHasValue( false )
83     , eState( SVPAR_NOTSTARTED )
84     , eSrcEnc( RTL_TEXTENCODING_DONTKNOW )
85     , bDownloadingFile( sal_False )
86     , nTokenStackSize( nStackSize )
87     , nTokenStackPos( 0 )
88 {
89     bUCS2BSrcEnc = bSwitchToUCS2 = sal_False;
90     eState = SVPAR_NOTSTARTED;
91     if( nTokenStackSize < 3 )
92         nTokenStackSize = 3;
93     pTokenStack = new TokenStackType[ nTokenStackSize ];
94     pTokenStackPos = pTokenStack;
95 
96 #ifdef DBG_UTIL
97 
98     // wenn die Datei schon existiert, dann Anhaengen:
99     if( !pImplData )
100         pImplData = new SvParser_Impl;
101     pImplData->aOut.Open( String::CreateFromAscii( "\\parser.dmp" ),
102                           STREAM_STD_WRITE | STREAM_NOCREATE );
103     if( pImplData->aOut.GetError() || !pImplData->aOut.IsOpen() )
104         pImplData->aOut.Close();
105     else
106     {
107         pImplData->aOut.Seek( STREAM_SEEK_TO_END );
108         pImplData->aOut << "\x0c\n\n >>>>>>>>>>>>>>> Dump Start <<<<<<<<<<<<<<<\n";
109     }
110 #endif
111 }
112 
~SvParser()113 SvParser::~SvParser()
114 {
115 #ifdef DBG_UTIL
116     if( pImplData->aOut.IsOpen() )
117         pImplData->aOut << "\n\n >>>>>>>>>>>>>>> Dump Ende <<<<<<<<<<<<<<<\n";
118     pImplData->aOut.Close();
119 #endif
120 
121     if( pImplData && pImplData->hConv )
122     {
123         rtl_destroyTextToUnicodeContext( pImplData->hConv,
124                                          pImplData->hContext );
125         rtl_destroyTextToUnicodeConverter( pImplData->hConv );
126     }
127 
128     delete pImplData;
129 
130     delete [] pTokenStack;
131 }
132 
ClearTxtConvContext()133 void SvParser::ClearTxtConvContext()
134 {
135     if( pImplData && pImplData->hConv )
136         rtl_resetTextToUnicodeContext( pImplData->hConv, pImplData->hContext );
137 }
138 
SetSrcEncoding(rtl_TextEncoding eEnc)139 void SvParser::SetSrcEncoding( rtl_TextEncoding eEnc )
140 {
141 
142     if( eEnc != eSrcEnc )
143     {
144         if( pImplData && pImplData->hConv )
145         {
146             rtl_destroyTextToUnicodeContext( pImplData->hConv,
147                                              pImplData->hContext );
148             rtl_destroyTextToUnicodeConverter( pImplData->hConv );
149             pImplData->hConv = 0;
150             pImplData->hContext = (rtl_TextToUnicodeContext )1;
151         }
152 
153         if( rtl_isOctetTextEncoding(eEnc) ||
154             RTL_TEXTENCODING_UCS2 == eEnc  )
155         {
156             eSrcEnc = eEnc;
157             if( !pImplData )
158                 pImplData = new SvParser_Impl;
159             pImplData->hConv = rtl_createTextToUnicodeConverter( eSrcEnc );
160             DBG_ASSERT( pImplData->hConv,
161                         "SvParser::SetSrcEncoding: no converter for source encoding" );
162             if( !pImplData->hConv )
163                 eSrcEnc = RTL_TEXTENCODING_DONTKNOW;
164             else
165                 pImplData->hContext =
166                     rtl_createTextToUnicodeContext( pImplData->hConv );
167         }
168         else
169         {
170             DBG_ASSERT( !this,
171                         "SvParser::SetSrcEncoding: invalid source encoding" );
172             eSrcEnc = RTL_TEXTENCODING_DONTKNOW;
173         }
174     }
175 }
176 
RereadLookahead()177 void SvParser::RereadLookahead()
178 {
179     rInput.Seek(nNextChPos);
180     nNextCh = GetNextChar();
181 }
182 
GetNextChar()183 sal_Unicode SvParser::GetNextChar()
184 {
185     sal_Unicode c = 0U;
186 
187     // When reading muliple bytes, we don't have to care about the file
188     // position when we run inti the pending state. The file position is
189     // maintained by SaveState/RestoreState.
190     sal_Bool bErr;
191     if( bSwitchToUCS2 && 0 == rInput.Tell() )
192     {
193         sal_uChar c1, c2;
194         sal_Bool bSeekBack = sal_True;
195 
196         rInput >> c1;
197         bErr = rInput.IsEof() || rInput.GetError();
198         if( !bErr )
199         {
200             if( 0xff == c1 || 0xfe == c1 )
201             {
202                 rInput >> c2;
203                 bErr = rInput.IsEof() || rInput.GetError();
204                 if( !bErr )
205                 {
206                     if( 0xfe == c1 && 0xff == c2 )
207                     {
208                         eSrcEnc = RTL_TEXTENCODING_UCS2;
209                         bUCS2BSrcEnc = sal_True;
210                         bSeekBack = sal_False;
211                     }
212                     else if( 0xff == c1 && 0xfe == c2 )
213                     {
214                         eSrcEnc = RTL_TEXTENCODING_UCS2;
215                         bUCS2BSrcEnc = sal_False;
216                         bSeekBack = sal_False;
217                     }
218                 }
219             }
220         }
221         if( bSeekBack )
222             rInput.Seek( 0 );
223 
224         bSwitchToUCS2 = sal_False;
225     }
226 
227     nNextChPos = rInput.Tell();
228 
229     if( RTL_TEXTENCODING_UCS2 == eSrcEnc )
230     {
231         sal_Unicode cUC = USHRT_MAX;
232         sal_uChar c1, c2;
233 
234         rInput >> c1 >> c2;
235         if( 2 == rInput.Tell() &&
236             !(rInput.IsEof() || rInput.GetError()) &&
237             ( (bUCS2BSrcEnc && 0xfe == c1 && 0xff == c2) ||
238               (!bUCS2BSrcEnc && 0xff == c1 && 0xfe == c2) ) )
239             rInput >> c1 >> c2;
240 
241         bErr = rInput.IsEof() || rInput.GetError();
242         if( !bErr )
243         {
244             if( bUCS2BSrcEnc )
245                 cUC = (sal_Unicode(c1) << 8) | c2;
246             else
247                 cUC = (sal_Unicode(c2) << 8) | c1;
248         }
249 
250         if( !bErr )
251         {
252             c = cUC;
253         }
254     }
255     else
256     {
257         sal_Size nChars = 0;
258         do
259         {
260             sal_Char c1;    // signed, that's the text converter expects
261             rInput >> c1;
262             bErr = rInput.IsEof() || rInput.GetError();
263             if( !bErr )
264             {
265                 if (
266                      RTL_TEXTENCODING_DONTKNOW == eSrcEnc ||
267                      RTL_TEXTENCODING_SYMBOL == eSrcEnc
268                    )
269                 {
270                     // no convserion shall take place
271                     c = (sal_Unicode)c1;
272                     nChars = 1;
273                 }
274                 else
275                 {
276                     DBG_ASSERT( pImplData && pImplData->hConv,
277                                 "no text converter!" );
278 
279                     sal_Unicode cUC;
280                     sal_uInt32 nInfo = 0;
281                     sal_Size nCvtBytes;
282                     nChars = rtl_convertTextToUnicode(
283                                 pImplData->hConv, pImplData->hContext,
284                                 &c1, 1, &cUC, 1,
285                                 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
286                                 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
287                                 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
288                                 &nInfo, &nCvtBytes);
289                     if( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 )
290                     {
291                         // The conversion wasn't successfull because we haven't
292                         // read enough characters.
293                         if( pImplData->hContext != (rtl_TextToUnicodeContext)1 )
294                         {
295                             while( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 )
296                             {
297                                 rInput >> c1;
298                                 bErr = rInput.IsEof() || rInput.GetError();
299                                 if( bErr )
300                                     break;
301 
302                                 nChars = rtl_convertTextToUnicode(
303                                             pImplData->hConv, pImplData->hContext,
304                                             &c1, 1, &cUC, 1,
305                                             RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
306                                             RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
307                                             RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
308                                             &nInfo, &nCvtBytes);
309                             }
310                             if( !bErr )
311                             {
312                                 if( 1 == nChars && 0 == nInfo )
313                                 {
314                                     c = cUC;
315                                 }
316                                 else if( 0 != nChars || 0 != nInfo )
317                                 {
318                                     DBG_ASSERT( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) == 0,
319                                         "source buffer is to small" );
320                                     DBG_ASSERT( (nInfo&~(RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL)) == 0,
321                                         "there is a conversion error" );
322                                     DBG_ASSERT( 0 == nChars,
323                                        "there is a converted character, but an error" );
324                                     // There are still errors, but nothing we can
325                                     // do
326                                     c = (sal_Unicode)'?';
327                                     nChars = 1;
328                                 }
329                             }
330                         }
331                         else
332                         {
333                             sal_Char sBuffer[10];
334                             sBuffer[0] = c1;
335                             sal_uInt16 nLen = 1;
336                             while( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 &&
337                                     nLen < 10 )
338                             {
339                                 rInput >> c1;
340                                 bErr = rInput.IsEof() || rInput.GetError();
341                                 if( bErr )
342                                     break;
343 
344                                 sBuffer[nLen++] = c1;
345                                 nChars = rtl_convertTextToUnicode(
346                                             pImplData->hConv, 0, sBuffer, nLen, &cUC, 1,
347                                             RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
348                                             RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
349                                             RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
350                                             &nInfo, &nCvtBytes);
351                             }
352                             if( !bErr )
353                             {
354                                 if( 1 == nChars && 0 == nInfo )
355                                 {
356                                     DBG_ASSERT( nCvtBytes == nLen,
357                                                 "no all bytes have been converted!" );
358                                     c = cUC;
359                                 }
360                                 else
361                                 {
362                                     DBG_ASSERT( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) == 0,
363                                         "source buffer is to small" );
364                                     DBG_ASSERT( (nInfo&~(RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL)) == 0,
365                                         "there is a conversion error" );
366                                     DBG_ASSERT( 0 == nChars,
367                                        "there is a converted character, but an error" );
368 
369                                     // There are still errors, so we use the first
370                                     // character and restart after that.
371                                     c = (sal_Unicode)sBuffer[0];
372                                     rInput.SeekRel( -(nLen-1) );
373                                     nChars = 1;
374                                 }
375                             }
376                         }
377                     }
378                     else if( 1 == nChars && 0 == nInfo )
379                     {
380                         // The conversion was successfull
381                         DBG_ASSERT( nCvtBytes == 1,
382                                     "no all bytes have been converted!" );
383                         c = cUC;
384                     }
385                     else if( 0 != nChars || 0 != nInfo )
386                     {
387                         DBG_ASSERT( 0 == nChars,
388                                 "there is a converted character, but an error" );
389                         DBG_ASSERT( 0 != nInfo,
390                                 "there is no converted character and no error" );
391                         // #73398#: If the character could not be converted,
392                         // because a conversion is not available, do no conversion at all.
393                         c = (sal_Unicode)c1;
394                         nChars = 1;
395 
396                     }
397                 }
398             }
399         }
400         while( 0 == nChars  && !bErr );
401     }
402     if( bErr )
403     {
404         if( ERRCODE_IO_PENDING == rInput.GetError() )
405         {
406             eState = SVPAR_PENDING;
407             return c;
408         }
409         else
410             return sal_Unicode(EOF);
411     }
412 
413 #ifdef DBG_UTIL
414     if( pImplData->aOut.IsOpen() )
415         pImplData->aOut << ByteString::ConvertFromUnicode( c,
416                                                 RTL_TEXTENCODING_MS_1251 );
417 #endif
418 
419     if( c == '\n' )
420     {
421         IncLineNr();
422         SetLinePos( 1L );
423     }
424     else
425         IncLinePos();
426     return c;
427 }
428 
GetNextToken()429 int SvParser::GetNextToken()
430 {
431     int nRet = 0;
432 
433     if( !nTokenStackPos )
434     {
435         aToken.Erase();     // Token-Buffer loeschen
436         nTokenValue = -1;   // Kennzeichen fuer kein Value gelesen
437         bTokenHasValue = false;
438 
439         nRet = _GetNextToken();
440         if( SVPAR_PENDING == eState )
441             return nRet;
442     }
443 
444     ++pTokenStackPos;
445     if( pTokenStackPos == pTokenStack + nTokenStackSize )
446         pTokenStackPos = pTokenStack;
447 
448     // vom Stack holen ??
449     if( nTokenStackPos )
450     {
451         --nTokenStackPos;
452         nTokenValue = pTokenStackPos->nTokenValue;
453         bTokenHasValue = pTokenStackPos->bTokenHasValue;
454         aToken = pTokenStackPos->sToken;
455         nRet = pTokenStackPos->nTokenId;
456     }
457     // nein, dann das aktuelle auf den Stack
458     else if( SVPAR_WORKING == eState )
459     {
460         pTokenStackPos->sToken = aToken;
461         pTokenStackPos->nTokenValue = nTokenValue;
462         pTokenStackPos->bTokenHasValue = bTokenHasValue;
463         pTokenStackPos->nTokenId = nRet;
464     }
465     else if( SVPAR_ACCEPTED != eState && SVPAR_PENDING != eState )
466         eState = SVPAR_ERROR;       // irgend ein Fehler
467 
468     return nRet;
469 }
470 
SkipToken(short nCnt)471 int SvParser::SkipToken( short nCnt )       // n Tokens zurueck "skippen"
472 {
473     pTokenStackPos = GetStackPtr( nCnt );
474     short nTmp = nTokenStackPos - nCnt;
475     if( nTmp < 0 )
476         nTmp = 0;
477     else if( nTmp > nTokenStackSize )
478         nTmp = nTokenStackSize;
479     nTokenStackPos = sal_uInt8(nTmp);
480 
481     // und die Werte zurueck
482     aToken = pTokenStackPos->sToken;
483     nTokenValue = pTokenStackPos->nTokenValue;
484     bTokenHasValue = pTokenStackPos->bTokenHasValue;
485 
486     return pTokenStackPos->nTokenId;
487 }
488 
GetStackPtr(short nCnt)489 SvParser::TokenStackType* SvParser::GetStackPtr( short nCnt )
490 {
491     sal_uInt8 nAktPos = sal_uInt8(pTokenStackPos - pTokenStack );
492     if( nCnt > 0 )
493     {
494         if( nCnt >= nTokenStackSize )
495             nCnt = (nTokenStackSize-1);
496         if( nAktPos + nCnt < nTokenStackSize )
497             nAktPos = sal::static_int_cast< sal_uInt8 >(nAktPos + nCnt);
498         else
499             nAktPos = sal::static_int_cast< sal_uInt8 >(
500                 nAktPos + (nCnt - nTokenStackSize));
501     }
502     else if( nCnt < 0 )
503     {
504         if( -nCnt >= nTokenStackSize )
505             nCnt = -nTokenStackSize+1;
506         if( -nCnt <= nAktPos )
507             nAktPos = sal::static_int_cast< sal_uInt8 >(nAktPos + nCnt);
508         else
509             nAktPos = sal::static_int_cast< sal_uInt8 >(
510                 nAktPos + (nCnt + nTokenStackSize));
511     }
512     return pTokenStack + nAktPos;
513 }
514 
515 // wird fuer jedes Token gerufen, das in CallParser erkannt wird
NextToken(int)516 void SvParser::NextToken( int )
517 {
518 }
519 
520 
521 // fuers asynchrone lesen aus dem SvStream
522 
GetSaveToken() const523 int SvParser::GetSaveToken() const
524 {
525     return pImplData ? pImplData->nSaveToken : 0;
526 }
527 
SaveState(int nToken)528 void SvParser::SaveState( int nToken )
529 {
530     // aktuellen Status merken
531     if( !pImplData )
532     {
533         pImplData = new SvParser_Impl;
534         pImplData->nSaveToken = 0;
535     }
536 
537     pImplData->nFilePos = rInput.Tell();
538     pImplData->nToken = nToken;
539 
540     pImplData->aToken = aToken;
541     pImplData->nlLineNr = nlLineNr;
542     pImplData->nlLinePos = nlLinePos;
543     pImplData->nTokenValue= nTokenValue;
544     pImplData->bTokenHasValue = bTokenHasValue;
545     pImplData->nNextCh = nNextCh;
546 }
547 
RestoreState()548 void SvParser::RestoreState()
549 {
550     // alten Status wieder zurueck setzen
551     if( pImplData )
552     {
553         if( ERRCODE_IO_PENDING == rInput.GetError() )
554             rInput.ResetError();
555         aToken = pImplData->aToken;
556         nlLineNr = pImplData->nlLineNr;
557         nlLinePos = pImplData->nlLinePos;
558         nTokenValue= pImplData->nTokenValue;
559         bTokenHasValue=pImplData->bTokenHasValue;
560         nNextCh = pImplData->nNextCh;
561 
562         pImplData->nSaveToken = pImplData->nToken;
563 
564         rInput.Seek( pImplData->nFilePos );
565     }
566 }
567 
Continue(int)568 void SvParser::Continue( int )
569 {
570 }
571 
BuildWhichTbl(SvUShorts & rWhichMap,sal_uInt16 * pWhichIds,sal_uInt16 nWhichIds)572 void SvParser::BuildWhichTbl( SvUShorts &rWhichMap,
573                               sal_uInt16 *pWhichIds,
574                               sal_uInt16 nWhichIds )
575 {
576     sal_uInt16 aNewRange[2];
577 
578     for( sal_uInt16 nCnt = 0; nCnt < nWhichIds; ++nCnt, ++pWhichIds )
579         if( *pWhichIds )
580         {
581             aNewRange[0] = aNewRange[1] = *pWhichIds;
582             sal_Bool bIns = sal_True;
583 
584             // Position suchen
585             for ( sal_uInt16 nOfs = 0; rWhichMap[nOfs]; nOfs += 2 )
586             {
587                 if( *pWhichIds < rWhichMap[nOfs] - 1 )
588                 {
589                     // neuen Range davor
590                     rWhichMap.Insert( aNewRange, 2, nOfs );
591                     bIns = sal_False;
592                     break;
593                 }
594                 else if( *pWhichIds == rWhichMap[nOfs] - 1 )
595                 {
596                     // diesen Range nach unten erweitern
597                     rWhichMap[nOfs] = *pWhichIds;
598                     bIns = sal_False;
599                     break;
600                 }
601                 else if( *pWhichIds == rWhichMap[nOfs+1] + 1 )
602                 {
603                     if( rWhichMap[nOfs+2] != 0 && rWhichMap[nOfs+2] == *pWhichIds + 1 )
604                     {
605                         // mit dem naechsten Bereich mergen
606                         rWhichMap[nOfs+1] = rWhichMap[nOfs+3];
607                         rWhichMap.Remove( nOfs+2, 2 );
608                     }
609                     else
610                         // diesen Range nach oben erweitern
611                         rWhichMap[nOfs+1] = *pWhichIds;
612                     bIns = sal_False;
613                     break;
614                 }
615             }
616 
617             // einen Range hinten anhaengen
618             if( bIns )
619                 rWhichMap.Insert( aNewRange, 2, rWhichMap.Count()-1 );
620         }
621 }
622 
623 
IMPL_STATIC_LINK(SvParser,NewDataRead,void *,EMPTYARG)624 IMPL_STATIC_LINK( SvParser, NewDataRead, void*, EMPTYARG )
625 {
626     switch( pThis->eState )
627     {
628     case SVPAR_PENDING:
629         // Wenn gerade ein File geladen wird duerfen wir nicht weiterlaufen,
630         // sondern muessen den Aufruf ignorieren.
631         if( pThis->IsDownloadingFile() )
632             break;
633 
634         pThis->eState = SVPAR_WORKING;
635         pThis->RestoreState();
636 
637         pThis->Continue( pThis->pImplData->nToken );
638 
639         if( ERRCODE_IO_PENDING == pThis->rInput.GetError() )
640             pThis->rInput.ResetError();
641 
642         if( SVPAR_PENDING != pThis->eState )
643             pThis->ReleaseRef();                    // ansonsten sind wir fertig!
644         break;
645 
646     case SVPAR_WAITFORDATA:
647         pThis->eState = SVPAR_WORKING;
648         break;
649 
650     case SVPAR_NOTSTARTED:
651     case SVPAR_WORKING:
652         break;
653 
654     default:
655         pThis->ReleaseRef();                    // ansonsten sind wir fertig!
656         break;
657     }
658 
659     return 0;
660 }
661 
662 /*========================================================================
663  *
664  * SvKeyValueIterator.
665  *
666  *======================================================================*/
667 SV_DECL_PTRARR_DEL(SvKeyValueList_Impl, SvKeyValue*, 0, 4)
668 SV_IMPL_PTRARR(SvKeyValueList_Impl, SvKeyValue*);
669 
670 /*
671  * SvKeyValueIterator.
672  */
SvKeyValueIterator(void)673 SvKeyValueIterator::SvKeyValueIterator (void)
674     : m_pList (new SvKeyValueList_Impl),
675       m_nPos  (0)
676 {
677 }
678 
679 /*
680  * ~SvKeyValueIterator.
681  */
~SvKeyValueIterator(void)682 SvKeyValueIterator::~SvKeyValueIterator (void)
683 {
684     delete m_pList;
685 }
686 
687 /*
688  * GetFirst.
689  */
GetFirst(SvKeyValue & rKeyVal)690 sal_Bool SvKeyValueIterator::GetFirst (SvKeyValue &rKeyVal)
691 {
692     m_nPos = m_pList->Count();
693     return GetNext (rKeyVal);
694 }
695 
696 /*
697  * GetNext.
698  */
GetNext(SvKeyValue & rKeyVal)699 sal_Bool SvKeyValueIterator::GetNext (SvKeyValue &rKeyVal)
700 {
701     if (m_nPos > 0)
702     {
703         rKeyVal = *m_pList->GetObject(--m_nPos);
704         return sal_True;
705     }
706     else
707     {
708         // Nothing to do.
709         return sal_False;
710     }
711 }
712 
713 /*
714  * Append.
715  */
Append(const SvKeyValue & rKeyVal)716 void SvKeyValueIterator::Append (const SvKeyValue &rKeyVal)
717 {
718     SvKeyValue *pKeyVal = new SvKeyValue (rKeyVal);
719     m_pList->C40_INSERT(SvKeyValue, pKeyVal, m_pList->Count());
720 }
721 
722 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
723