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