xref: /aoo41x/main/tools/source/generic/config.cxx (revision 89b56da7)
1*89b56da7SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*89b56da7SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*89b56da7SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*89b56da7SAndrew Rist  * distributed with this work for additional information
6*89b56da7SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*89b56da7SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*89b56da7SAndrew Rist  * "License"); you may not use this file except in compliance
9*89b56da7SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*89b56da7SAndrew Rist  *
11*89b56da7SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*89b56da7SAndrew Rist  *
13*89b56da7SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*89b56da7SAndrew Rist  * software distributed under the License is distributed on an
15*89b56da7SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*89b56da7SAndrew Rist  * KIND, either express or implied.  See the License for the
17*89b56da7SAndrew Rist  * specific language governing permissions and limitations
18*89b56da7SAndrew Rist  * under the License.
19*89b56da7SAndrew Rist  *
20*89b56da7SAndrew Rist  *************************************************************/
21*89b56da7SAndrew Rist 
22*89b56da7SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_tools.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #define _CONFIG_CXX
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <cstddef>
30cdf0e10cSrcweir #include <cstdlib>
31cdf0e10cSrcweir #include <limits>
32cdf0e10cSrcweir #include <new>
33cdf0e10cSrcweir #include <string.h>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #ifdef WNT
36cdf0e10cSrcweir #include "stdlib.h"
37cdf0e10cSrcweir #endif
38cdf0e10cSrcweir #include <osl/file.hxx>
39cdf0e10cSrcweir #include <tools/stream.hxx>
40cdf0e10cSrcweir #include <tools/debug.hxx>
41cdf0e10cSrcweir #include <tools/config.hxx>
42cdf0e10cSrcweir #include <osl/security.h>
43cdf0e10cSrcweir 
44cdf0e10cSrcweir #define MAXBUFLEN	1024		// Fuer Buffer bei VOS-Funktionen
45cdf0e10cSrcweir 
46cdf0e10cSrcweir // -----------------
47cdf0e10cSrcweir // - ImplConfigData -
48cdf0e10cSrcweir // -----------------
49cdf0e10cSrcweir 
50cdf0e10cSrcweir struct ImplKeyData
51cdf0e10cSrcweir {
52cdf0e10cSrcweir 	ImplKeyData*	mpNext;
53cdf0e10cSrcweir 	ByteString		maKey;
54cdf0e10cSrcweir 	ByteString		maValue;
55cdf0e10cSrcweir 	sal_Bool			mbIsComment;
56cdf0e10cSrcweir };
57cdf0e10cSrcweir 
58cdf0e10cSrcweir struct ImplGroupData
59cdf0e10cSrcweir {
60cdf0e10cSrcweir 	ImplGroupData*	mpNext;
61cdf0e10cSrcweir 	ImplKeyData*	mpFirstKey;
62cdf0e10cSrcweir 	ByteString		maGroupName;
63cdf0e10cSrcweir 	sal_uInt16			mnEmptyLines;
64cdf0e10cSrcweir };
65cdf0e10cSrcweir 
66cdf0e10cSrcweir struct ImplConfigData
67cdf0e10cSrcweir {
68cdf0e10cSrcweir 	ImplGroupData*	mpFirstGroup;
69cdf0e10cSrcweir 	XubString		maFileName;
70cdf0e10cSrcweir 	sal_uIntPtr			mnDataUpdateId;
71cdf0e10cSrcweir 	sal_uIntPtr			mnTimeStamp;
72cdf0e10cSrcweir 	LineEnd 		meLineEnd;
73cdf0e10cSrcweir 	sal_uInt16			mnRefCount;
74cdf0e10cSrcweir 	sal_Bool			mbModified;
75cdf0e10cSrcweir 	sal_Bool			mbRead;
76cdf0e10cSrcweir 	sal_Bool			mbIsUTF8BOM;
77cdf0e10cSrcweir };
78cdf0e10cSrcweir 
79cdf0e10cSrcweir // =======================================================================
80cdf0e10cSrcweir 
getEmptyByteString()81cdf0e10cSrcweir static ByteString& getEmptyByteString()
82cdf0e10cSrcweir {
83cdf0e10cSrcweir 	static ByteString aEmpty;
84cdf0e10cSrcweir 	return aEmpty;
85cdf0e10cSrcweir }
86cdf0e10cSrcweir 
87cdf0e10cSrcweir // =======================================================================
88cdf0e10cSrcweir 
toUncPath(const String & rPath)89cdf0e10cSrcweir static String toUncPath( const String& rPath )
90cdf0e10cSrcweir {
91cdf0e10cSrcweir 	::rtl::OUString aFileURL;
92cdf0e10cSrcweir 
93cdf0e10cSrcweir 	// check if rFileName is already a URL; if not make it so
94cdf0e10cSrcweir 	if( rPath.CompareToAscii( "file://", 7 ) == COMPARE_EQUAL )
95cdf0e10cSrcweir 		aFileURL = rPath;
96cdf0e10cSrcweir 	else if( ::osl::FileBase::getFileURLFromSystemPath( rPath, aFileURL ) != ::osl::FileBase::E_None )
97cdf0e10cSrcweir 		aFileURL = rPath;
98cdf0e10cSrcweir 
99cdf0e10cSrcweir 	return aFileURL;
100cdf0e10cSrcweir }
101cdf0e10cSrcweir 
ImplSysGetConfigTimeStamp(const XubString & rFileName)102cdf0e10cSrcweir static sal_uIntPtr ImplSysGetConfigTimeStamp( const XubString& rFileName )
103cdf0e10cSrcweir {
104cdf0e10cSrcweir 	sal_uIntPtr nTimeStamp = 0;
105cdf0e10cSrcweir 	::osl::DirectoryItem aItem;
106cdf0e10cSrcweir 	::osl::FileStatus aStatus( osl_FileStatus_Mask_ModifyTime );
107cdf0e10cSrcweir 
108cdf0e10cSrcweir 	int nError = 0;
109cdf0e10cSrcweir 	if( ( nError = ::osl::DirectoryItem::get( rFileName, aItem ) ) == ::osl::FileBase::E_None &&
110cdf0e10cSrcweir 		aItem.getFileStatus( aStatus ) == ::osl::FileBase::E_None )
111cdf0e10cSrcweir 	{
112cdf0e10cSrcweir 		nTimeStamp = aStatus.getModifyTime().Seconds;
113cdf0e10cSrcweir 	}
114cdf0e10cSrcweir 
115cdf0e10cSrcweir 	return nTimeStamp;
116cdf0e10cSrcweir }
117cdf0e10cSrcweir 
118cdf0e10cSrcweir // -----------------------------------------------------------------------
119cdf0e10cSrcweir 
ImplSysReadConfig(const XubString & rFileName,sal_uInt64 & rRead,sal_Bool & rbRead,sal_Bool & rbIsUTF8BOM,sal_uIntPtr & rTimeStamp)120cdf0e10cSrcweir static sal_uInt8* ImplSysReadConfig( const XubString& rFileName,
121cdf0e10cSrcweir 								sal_uInt64& rRead, sal_Bool& rbRead, sal_Bool& rbIsUTF8BOM, sal_uIntPtr& rTimeStamp )
122cdf0e10cSrcweir {
123cdf0e10cSrcweir 	sal_uInt8*			pBuf = NULL;
124cdf0e10cSrcweir 	::osl::File aFile( rFileName );
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 	if( aFile.open( osl_File_OpenFlag_Read ) == ::osl::FileBase::E_None )
127cdf0e10cSrcweir 	{
128cdf0e10cSrcweir 		sal_uInt64 nPos = 0, nRead = 0;
129cdf0e10cSrcweir 		if( aFile.getSize( nPos ) == ::osl::FileBase::E_None )
130cdf0e10cSrcweir 		{
131cdf0e10cSrcweir             if (nPos > std::numeric_limits< std::size_t >::max()) {
132cdf0e10cSrcweir                 aFile.close();
133cdf0e10cSrcweir                 return 0;
134cdf0e10cSrcweir             }
135cdf0e10cSrcweir 			pBuf = new sal_uInt8[static_cast< std::size_t >(nPos)];
136cdf0e10cSrcweir 			if( aFile.read( pBuf, nPos, nRead ) == ::osl::FileBase::E_None && nRead == nPos )
137cdf0e10cSrcweir 			{
138cdf0e10cSrcweir 				//skip the byte-order-mark 0xEF 0xBB 0xBF, if it was UTF8 files
139cdf0e10cSrcweir 				unsigned char BOM[3] = {0xEF, 0xBB, 0xBF};
140cdf0e10cSrcweir 				if (nRead > 2 && memcmp(pBuf, BOM, 3) == 0)
141cdf0e10cSrcweir 				{
142cdf0e10cSrcweir 					nRead -= 3;
143cdf0e10cSrcweir 					rtl_moveMemory(pBuf, pBuf + 3, sal::static_int_cast<sal_Size>(nRead * sizeof(sal_uInt8)) );
144cdf0e10cSrcweir 					rbIsUTF8BOM = sal_True;
145cdf0e10cSrcweir 				}
146cdf0e10cSrcweir 
147cdf0e10cSrcweir 				rTimeStamp = ImplSysGetConfigTimeStamp( rFileName );
148cdf0e10cSrcweir 				rbRead = sal_True;
149cdf0e10cSrcweir 				rRead = nRead;
150cdf0e10cSrcweir 			}
151cdf0e10cSrcweir 			else
152cdf0e10cSrcweir 			{
153cdf0e10cSrcweir 				delete[] pBuf;
154cdf0e10cSrcweir 				pBuf = NULL;
155cdf0e10cSrcweir 			}
156cdf0e10cSrcweir 		}
157cdf0e10cSrcweir         aFile.close();
158cdf0e10cSrcweir 	}
159cdf0e10cSrcweir 
160cdf0e10cSrcweir 	return pBuf;
161cdf0e10cSrcweir }
162cdf0e10cSrcweir 
163cdf0e10cSrcweir // -----------------------------------------------------------------------
164cdf0e10cSrcweir 
ImplSysWriteConfig(const XubString & rFileName,const sal_uInt8 * pBuf,sal_uIntPtr nBufLen,sal_Bool rbIsUTF8BOM,sal_uIntPtr & rTimeStamp)165cdf0e10cSrcweir static sal_Bool ImplSysWriteConfig( const XubString& rFileName,
166cdf0e10cSrcweir 								const sal_uInt8* pBuf, sal_uIntPtr nBufLen, sal_Bool rbIsUTF8BOM, sal_uIntPtr& rTimeStamp )
167cdf0e10cSrcweir {
168cdf0e10cSrcweir 	sal_Bool bSuccess = sal_False;
169cdf0e10cSrcweir 	sal_Bool bUTF8BOMSuccess = sal_False;
170cdf0e10cSrcweir 
171cdf0e10cSrcweir 	::osl::File aFile( rFileName );
172cdf0e10cSrcweir 	::osl::FileBase::RC eError = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
173cdf0e10cSrcweir 	if( eError != ::osl::FileBase::E_None )
174cdf0e10cSrcweir 		eError = aFile.open( osl_File_OpenFlag_Write );
175cdf0e10cSrcweir 	if( eError == ::osl::FileBase::E_None )
176cdf0e10cSrcweir 	{
177cdf0e10cSrcweir 		// truncate
178cdf0e10cSrcweir 		aFile.setSize( 0 );
179cdf0e10cSrcweir 		sal_uInt64 nWritten;
180cdf0e10cSrcweir 
181cdf0e10cSrcweir 		//write the the byte-order-mark 0xEF 0xBB 0xBF first , if it was UTF8 files
182cdf0e10cSrcweir 		if ( rbIsUTF8BOM )
183cdf0e10cSrcweir 		{
184cdf0e10cSrcweir 			unsigned char BOM[3] = {0xEF, 0xBB, 0xBF};
185cdf0e10cSrcweir 			sal_uInt64 nUTF8BOMWritten;
186cdf0e10cSrcweir 			if( aFile.write( BOM, 3, nUTF8BOMWritten ) == ::osl::FileBase::E_None && 3 == nUTF8BOMWritten )
187cdf0e10cSrcweir 			{
188cdf0e10cSrcweir 				bUTF8BOMSuccess = sal_True;
189cdf0e10cSrcweir 			}
190cdf0e10cSrcweir 		}
191cdf0e10cSrcweir 
192cdf0e10cSrcweir 		if( aFile.write( pBuf, nBufLen, nWritten ) == ::osl::FileBase::E_None && nWritten == nBufLen )
193cdf0e10cSrcweir 		{
194cdf0e10cSrcweir 			bSuccess = sal_True;
195cdf0e10cSrcweir 		}
196cdf0e10cSrcweir 		if ( rbIsUTF8BOM ? bSuccess && bUTF8BOMSuccess : bSuccess )
197cdf0e10cSrcweir 		{
198cdf0e10cSrcweir 			rTimeStamp = ImplSysGetConfigTimeStamp( rFileName );
199cdf0e10cSrcweir 		}
200cdf0e10cSrcweir 	}
201cdf0e10cSrcweir 
202cdf0e10cSrcweir 	return rbIsUTF8BOM ? bSuccess && bUTF8BOMSuccess : bSuccess;
203cdf0e10cSrcweir }
204cdf0e10cSrcweir 
205cdf0e10cSrcweir // -----------------------------------------------------------------------
206cdf0e10cSrcweir 
ImplMakeConfigName(const XubString * pFileName,const XubString * pPathName)207cdf0e10cSrcweir static String ImplMakeConfigName( const XubString* pFileName,
208cdf0e10cSrcweir 								  const XubString* pPathName )
209cdf0e10cSrcweir {
210cdf0e10cSrcweir 	::rtl::OUString aFileName;
211cdf0e10cSrcweir 	::rtl::OUString aPathName;
212cdf0e10cSrcweir 	if ( pFileName )
213cdf0e10cSrcweir 	{
214cdf0e10cSrcweir #ifdef UNX
215cdf0e10cSrcweir 		aFileName = ::rtl::OUString::createFromAscii( "." );
216cdf0e10cSrcweir 		aFileName += *pFileName;
217cdf0e10cSrcweir 		aFileName += ::rtl::OUString::createFromAscii( "rc" );
218cdf0e10cSrcweir #else
219cdf0e10cSrcweir 		aFileName = *pFileName;
220cdf0e10cSrcweir 		aFileName += ::rtl::OUString::createFromAscii( ".ini" );
221cdf0e10cSrcweir #endif
222cdf0e10cSrcweir 	}
223cdf0e10cSrcweir 	else
224cdf0e10cSrcweir 	{
225cdf0e10cSrcweir #ifdef UNX
226cdf0e10cSrcweir 		aFileName = ::rtl::OUString::createFromAscii( ".sversionrc" );
227cdf0e10cSrcweir #else
228cdf0e10cSrcweir 		aFileName = ::rtl::OUString::createFromAscii( "sversion.ini" );
229cdf0e10cSrcweir #endif
230cdf0e10cSrcweir 	}
231cdf0e10cSrcweir 
232cdf0e10cSrcweir     // #88208# in case pPathName is set but empty and pFileName is set
233cdf0e10cSrcweir     // and not empty just return the filename; on the default case
234cdf0e10cSrcweir     // prepend default path as usual
235cdf0e10cSrcweir 	if ( pPathName && pPathName->Len() )
236cdf0e10cSrcweir 		aPathName = toUncPath( *pPathName );
237cdf0e10cSrcweir     else if( pPathName && pFileName && pFileName->Len() )
238cdf0e10cSrcweir         return aFileName;
239cdf0e10cSrcweir 	else
240cdf0e10cSrcweir 	{
241cdf0e10cSrcweir 		oslSecurity aSec = osl_getCurrentSecurity();
242cdf0e10cSrcweir 		osl_getConfigDir( aSec, &aPathName.pData );
243cdf0e10cSrcweir 		osl_freeSecurityHandle( aSec );
244cdf0e10cSrcweir 	}
245cdf0e10cSrcweir 
246cdf0e10cSrcweir 	::rtl::OUString aName( aPathName );
247cdf0e10cSrcweir 	aName += ::rtl::OUString::createFromAscii( "/" );
248cdf0e10cSrcweir 	aName += aFileName;
249cdf0e10cSrcweir 
250cdf0e10cSrcweir 	return aName;
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir // -----------------------------------------------------------------------
254cdf0e10cSrcweir 
255cdf0e10cSrcweir namespace {
256cdf0e10cSrcweir 
makeByteString(sal_uInt8 const * p,sal_uInt64 n)257cdf0e10cSrcweir ByteString makeByteString(sal_uInt8 const * p, sal_uInt64 n) {
258cdf0e10cSrcweir     if (n > STRING_MAXLEN) {
259cdf0e10cSrcweir         #ifdef WNT
260cdf0e10cSrcweir         abort();
261cdf0e10cSrcweir         #else
262cdf0e10cSrcweir         ::std::abort(); //TODO: handle this gracefully
263cdf0e10cSrcweir         #endif
264cdf0e10cSrcweir     }
265cdf0e10cSrcweir     return ByteString(
266cdf0e10cSrcweir         reinterpret_cast< char const * >(p),
267cdf0e10cSrcweir         sal::static_int_cast< xub_StrLen >(n));
268cdf0e10cSrcweir }
269cdf0e10cSrcweir 
270cdf0e10cSrcweir }
271cdf0e10cSrcweir 
ImplMakeConfigList(ImplConfigData * pData,const sal_uInt8 * pBuf,sal_uInt64 nLen)272cdf0e10cSrcweir static void ImplMakeConfigList( ImplConfigData* pData,
273cdf0e10cSrcweir 								const sal_uInt8* pBuf, sal_uInt64 nLen )
274cdf0e10cSrcweir {
275cdf0e10cSrcweir 	// kein Buffer, keine Daten
276cdf0e10cSrcweir 	if ( !nLen )
277cdf0e10cSrcweir 		return;
278cdf0e10cSrcweir 
279cdf0e10cSrcweir 	// Buffer parsen und Liste zusammenbauen
280cdf0e10cSrcweir 	sal_uInt64 nStart;
281cdf0e10cSrcweir 	sal_uInt64 nLineLen;
282cdf0e10cSrcweir 	xub_StrLen      nNameLen;
283cdf0e10cSrcweir     xub_StrLen      nKeyLen;
284cdf0e10cSrcweir 	sal_uInt64 i;
285cdf0e10cSrcweir 	const sal_uInt8* 	pLine;
286cdf0e10cSrcweir 	ImplKeyData*	pPrevKey = NULL;
287cdf0e10cSrcweir 	ImplKeyData*	pKey;
288cdf0e10cSrcweir 	ImplGroupData*	pPrevGroup = NULL;
289cdf0e10cSrcweir 	ImplGroupData*	pGroup = NULL;
290cdf0e10cSrcweir 	i = 0;
291cdf0e10cSrcweir 	while ( i < nLen )
292cdf0e10cSrcweir 	{
293cdf0e10cSrcweir 		// Ctrl+Z
294cdf0e10cSrcweir 		if ( pBuf[i] == 0x1A )
295cdf0e10cSrcweir 			break;
296cdf0e10cSrcweir 
297cdf0e10cSrcweir 		// Spaces und Tabs entfernen
298cdf0e10cSrcweir 		while ( (pBuf[i] == ' ') || (pBuf[i] == '\t') )
299cdf0e10cSrcweir 			i++;
300cdf0e10cSrcweir 
301cdf0e10cSrcweir 		// Zeilenanfang merken
302cdf0e10cSrcweir 		nStart = i;
303cdf0e10cSrcweir 		pLine = pBuf+i;
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 		// Zeilenende suchen
306cdf0e10cSrcweir 		while (  (i < nLen) && pBuf[i] && (pBuf[i] != '\r') && (pBuf[i] != '\n') &&
307cdf0e10cSrcweir 				(pBuf[i] != 0x1A) )
308cdf0e10cSrcweir 			i++;
309cdf0e10cSrcweir 
310cdf0e10cSrcweir 		nLineLen = i-nStart;
311cdf0e10cSrcweir 
312cdf0e10cSrcweir 		// Wenn Zeilenende (CR/LF), dann noch einen weiterschalten
313cdf0e10cSrcweir 		if ( (i+1 < nLen) &&
314cdf0e10cSrcweir 			 (pBuf[i] != pBuf[i+1]) &&
315cdf0e10cSrcweir 			 ((pBuf[i+1] == '\r') || (pBuf[i+1] == '\n')) )
316cdf0e10cSrcweir 			i++;
317cdf0e10cSrcweir 		i++;
318cdf0e10cSrcweir 
319cdf0e10cSrcweir 		// Zeile auswerten
320cdf0e10cSrcweir 		if ( *pLine == '[' )
321cdf0e10cSrcweir 		{
322cdf0e10cSrcweir 			pGroup				 = new ImplGroupData;
323cdf0e10cSrcweir 			pGroup->mpNext		 = NULL;
324cdf0e10cSrcweir 			pGroup->mpFirstKey	 = NULL;
325cdf0e10cSrcweir 			pGroup->mnEmptyLines = 0;
326cdf0e10cSrcweir 			if ( pPrevGroup )
327cdf0e10cSrcweir 				pPrevGroup->mpNext = pGroup;
328cdf0e10cSrcweir 			else
329cdf0e10cSrcweir 				pData->mpFirstGroup = pGroup;
330cdf0e10cSrcweir 			pPrevGroup	= pGroup;
331cdf0e10cSrcweir 			pPrevKey	= NULL;
332cdf0e10cSrcweir 			pKey		= NULL;
333cdf0e10cSrcweir 
334cdf0e10cSrcweir 			// Gruppennamen rausfiltern
335cdf0e10cSrcweir 			pLine++;
336cdf0e10cSrcweir 			nLineLen--;
337cdf0e10cSrcweir 			// Spaces und Tabs entfernen
338cdf0e10cSrcweir 			while ( (*pLine == ' ') || (*pLine == '\t') )
339cdf0e10cSrcweir 			{
340cdf0e10cSrcweir 				nLineLen--;
341cdf0e10cSrcweir 				pLine++;
342cdf0e10cSrcweir 			}
343cdf0e10cSrcweir 			nNameLen = 0;
344cdf0e10cSrcweir 			while ( (nNameLen < nLineLen) && (pLine[nNameLen] != ']') )
345cdf0e10cSrcweir 				nNameLen++;
346cdf0e10cSrcweir 			if ( nNameLen )
347cdf0e10cSrcweir 			{
348cdf0e10cSrcweir 				while ( (pLine[nNameLen-1] == ' ') || (pLine[nNameLen-1] == '\t') )
349cdf0e10cSrcweir 					nNameLen--;
350cdf0e10cSrcweir 			}
351cdf0e10cSrcweir 			pGroup->maGroupName = ByteString( (const sal_Char*)pLine, nNameLen );
352cdf0e10cSrcweir 		}
353cdf0e10cSrcweir 		else
354cdf0e10cSrcweir 		{
355cdf0e10cSrcweir 			if ( nLineLen )
356cdf0e10cSrcweir 			{
357cdf0e10cSrcweir 				// Wenn noch keine Gruppe existiert, dann alle Keys in die
358cdf0e10cSrcweir 				// Default-Gruppe
359cdf0e10cSrcweir 				if ( !pGroup )
360cdf0e10cSrcweir 				{
361cdf0e10cSrcweir 					pGroup				= new ImplGroupData;
362cdf0e10cSrcweir 					pGroup->mpNext		= NULL;
363cdf0e10cSrcweir 					pGroup->mpFirstKey	= NULL;
364cdf0e10cSrcweir 					pGroup->mnEmptyLines = 0;
365cdf0e10cSrcweir 					if ( pPrevGroup )
366cdf0e10cSrcweir 						pPrevGroup->mpNext = pGroup;
367cdf0e10cSrcweir 					else
368cdf0e10cSrcweir 						pData->mpFirstGroup = pGroup;
369cdf0e10cSrcweir 					pPrevGroup	= pGroup;
370cdf0e10cSrcweir 					pPrevKey	= NULL;
371cdf0e10cSrcweir 				}
372cdf0e10cSrcweir 
373cdf0e10cSrcweir 				// Falls Leerzeile vorhanden, dann anhaengen
374cdf0e10cSrcweir 				if ( pPrevKey )
375cdf0e10cSrcweir 				{
376cdf0e10cSrcweir 					while ( pGroup->mnEmptyLines )
377cdf0e10cSrcweir 					{
378cdf0e10cSrcweir 						pKey				= new ImplKeyData;
379cdf0e10cSrcweir 						pKey->mbIsComment	= sal_True;
380cdf0e10cSrcweir 						pPrevKey->mpNext	= pKey;
381cdf0e10cSrcweir 						pPrevKey			= pKey;
382cdf0e10cSrcweir 						pGroup->mnEmptyLines--;
383cdf0e10cSrcweir 					}
384cdf0e10cSrcweir 				}
385cdf0e10cSrcweir 
386cdf0e10cSrcweir 				// Neuen Key erzeugen
387cdf0e10cSrcweir 				pKey		= new ImplKeyData;
388cdf0e10cSrcweir 				pKey->mpNext = NULL;
389cdf0e10cSrcweir 				if ( pPrevKey )
390cdf0e10cSrcweir 					pPrevKey->mpNext = pKey;
391cdf0e10cSrcweir 				else
392cdf0e10cSrcweir 					pGroup->mpFirstKey = pKey;
393cdf0e10cSrcweir 				pPrevKey = pKey;
394cdf0e10cSrcweir 				if ( pLine[0] == ';' )
395cdf0e10cSrcweir 				{
396cdf0e10cSrcweir 					pKey->maValue = makeByteString(pLine, nLineLen);
397cdf0e10cSrcweir 					pKey->mbIsComment = sal_True;
398cdf0e10cSrcweir 				}
399cdf0e10cSrcweir 				else
400cdf0e10cSrcweir 				{
401cdf0e10cSrcweir 					pKey->mbIsComment = sal_False;
402cdf0e10cSrcweir 					nNameLen = 0;
403cdf0e10cSrcweir 					while ( (nNameLen < nLineLen) && (pLine[nNameLen] != '=') )
404cdf0e10cSrcweir 						nNameLen++;
405cdf0e10cSrcweir 					nKeyLen = nNameLen;
406cdf0e10cSrcweir 					// Spaces und Tabs entfernen
407cdf0e10cSrcweir 					if ( nNameLen )
408cdf0e10cSrcweir 					{
409cdf0e10cSrcweir 						while ( (pLine[nNameLen-1] == ' ') || (pLine[nNameLen-1] == '\t') )
410cdf0e10cSrcweir 							nNameLen--;
411cdf0e10cSrcweir 					}
412cdf0e10cSrcweir 					pKey->maKey = ByteString( (const sal_Char*)pLine, nNameLen );
413cdf0e10cSrcweir 					nKeyLen++;
414cdf0e10cSrcweir 					if ( nKeyLen < nLineLen )
415cdf0e10cSrcweir 					{
416cdf0e10cSrcweir 						pLine += nKeyLen;
417cdf0e10cSrcweir 						nLineLen -= nKeyLen;
418cdf0e10cSrcweir 						// Spaces und Tabs entfernen
419cdf0e10cSrcweir 						while ( (*pLine == ' ') || (*pLine == '\t') )
420cdf0e10cSrcweir 						{
421cdf0e10cSrcweir 							nLineLen--;
422cdf0e10cSrcweir 							pLine++;
423cdf0e10cSrcweir 						}
424cdf0e10cSrcweir 						if ( nLineLen )
425cdf0e10cSrcweir 						{
426cdf0e10cSrcweir 							while ( (pLine[nLineLen-1] == ' ') || (pLine[nLineLen-1] == '\t') )
427cdf0e10cSrcweir 								nLineLen--;
428cdf0e10cSrcweir 							pKey->maValue = makeByteString(pLine, nLineLen);
429cdf0e10cSrcweir 						}
430cdf0e10cSrcweir 					}
431cdf0e10cSrcweir 				}
432cdf0e10cSrcweir 			}
433cdf0e10cSrcweir 			else
434cdf0e10cSrcweir 			{
435cdf0e10cSrcweir 				// Leerzeilen werden nur gezaehlt und beim Erzeugen des
436cdf0e10cSrcweir 				// naechsten Keys angehaengt, da wir Leerzeilen am Ende
437cdf0e10cSrcweir 				// einer Gruppe auch nach hinzufuegen von neuen Keys nur
438cdf0e10cSrcweir 				// am Ende der Gruppe wieder speichern wollen
439cdf0e10cSrcweir 				if ( pGroup )
440cdf0e10cSrcweir 					pGroup->mnEmptyLines++;
441cdf0e10cSrcweir 			}
442cdf0e10cSrcweir 		}
443cdf0e10cSrcweir 	}
444cdf0e10cSrcweir }
445cdf0e10cSrcweir 
446cdf0e10cSrcweir // -----------------------------------------------------------------------
447cdf0e10cSrcweir 
ImplGetConfigBuffer(const ImplConfigData * pData,sal_uIntPtr & rLen)448cdf0e10cSrcweir static sal_uInt8* ImplGetConfigBuffer( const ImplConfigData* pData, sal_uIntPtr& rLen )
449cdf0e10cSrcweir {
450cdf0e10cSrcweir 	sal_uInt8*			pWriteBuf;
451cdf0e10cSrcweir 	sal_uInt8*			pBuf;
452cdf0e10cSrcweir 	sal_uInt8			aLineEndBuf[2] = {0, 0};
453cdf0e10cSrcweir 	ImplKeyData*	pKey;
454cdf0e10cSrcweir 	ImplGroupData*	pGroup;
455cdf0e10cSrcweir 	unsigned int	nBufLen;
456cdf0e10cSrcweir 	sal_uInt16			nValueLen;
457cdf0e10cSrcweir 	sal_uInt16			nKeyLen;
458cdf0e10cSrcweir 	sal_uInt16			nLineEndLen;
459cdf0e10cSrcweir 
460cdf0e10cSrcweir 	if ( pData->meLineEnd == LINEEND_CR )
461cdf0e10cSrcweir 	{
462cdf0e10cSrcweir 		aLineEndBuf[0] = _CR;
463cdf0e10cSrcweir 		nLineEndLen = 1;
464cdf0e10cSrcweir 	}
465cdf0e10cSrcweir 	else if ( pData->meLineEnd == LINEEND_LF )
466cdf0e10cSrcweir 	{
467cdf0e10cSrcweir 		aLineEndBuf[0] = _LF;
468cdf0e10cSrcweir 		nLineEndLen = 1;
469cdf0e10cSrcweir 	}
470cdf0e10cSrcweir 	else
471cdf0e10cSrcweir 	{
472cdf0e10cSrcweir 		aLineEndBuf[0] = _CR;
473cdf0e10cSrcweir 		aLineEndBuf[1] = _LF;
474cdf0e10cSrcweir 		nLineEndLen = 2;
475cdf0e10cSrcweir 	}
476cdf0e10cSrcweir 
477cdf0e10cSrcweir 	// Buffergroesse ermitteln
478cdf0e10cSrcweir 	nBufLen = 0;
479cdf0e10cSrcweir 	pGroup = pData->mpFirstGroup;
480cdf0e10cSrcweir 	while ( pGroup )
481cdf0e10cSrcweir 	{
482cdf0e10cSrcweir 		// Leere Gruppen werden nicht geschrieben
483cdf0e10cSrcweir 		if ( pGroup->mpFirstKey )
484cdf0e10cSrcweir 		{
485cdf0e10cSrcweir 			nBufLen += pGroup->maGroupName.Len() + nLineEndLen + 2;
486cdf0e10cSrcweir 			pKey = pGroup->mpFirstKey;
487cdf0e10cSrcweir 			while ( pKey )
488cdf0e10cSrcweir 			{
489cdf0e10cSrcweir 				nValueLen = pKey->maValue.Len();
490cdf0e10cSrcweir 				if ( pKey->mbIsComment )
491cdf0e10cSrcweir 					nBufLen += nValueLen + nLineEndLen;
492cdf0e10cSrcweir 				else
493cdf0e10cSrcweir 					nBufLen += pKey->maKey.Len() + nValueLen + nLineEndLen + 1;
494cdf0e10cSrcweir 
495cdf0e10cSrcweir 				pKey = pKey->mpNext;
496cdf0e10cSrcweir 			}
497cdf0e10cSrcweir 
498cdf0e10cSrcweir 			// Leerzeile nach jeder Gruppe auch wieder speichern
499cdf0e10cSrcweir 			if ( !pGroup->mnEmptyLines )
500cdf0e10cSrcweir 				pGroup->mnEmptyLines = 1;
501cdf0e10cSrcweir 			nBufLen += nLineEndLen * pGroup->mnEmptyLines;
502cdf0e10cSrcweir 		}
503cdf0e10cSrcweir 
504cdf0e10cSrcweir 		pGroup = pGroup->mpNext;
505cdf0e10cSrcweir 	}
506cdf0e10cSrcweir 
507cdf0e10cSrcweir 	// Laenge dem Aufrufer mitteilen
508cdf0e10cSrcweir 	rLen = nBufLen;
509cdf0e10cSrcweir 	if ( !nBufLen )
510cdf0e10cSrcweir 	{
511cdf0e10cSrcweir 		pWriteBuf = new sal_uInt8[nLineEndLen];
512cdf0e10cSrcweir 		if ( pWriteBuf )
513cdf0e10cSrcweir 		{
514cdf0e10cSrcweir 			pWriteBuf[0] = aLineEndBuf[0];
515cdf0e10cSrcweir 			if ( nLineEndLen == 2 )
516cdf0e10cSrcweir 				pWriteBuf[1] = aLineEndBuf[1];
517cdf0e10cSrcweir 			return pWriteBuf;
518cdf0e10cSrcweir 		}
519cdf0e10cSrcweir 		else
520cdf0e10cSrcweir 			return 0;
521cdf0e10cSrcweir 	}
522cdf0e10cSrcweir 
523cdf0e10cSrcweir 	// Schreibbuffer anlegen (wird vom Aufrufer zerstoert)
524cdf0e10cSrcweir 	pWriteBuf = new sal_uInt8[nBufLen];
525cdf0e10cSrcweir 	if ( !pWriteBuf )
526cdf0e10cSrcweir 		return 0;
527cdf0e10cSrcweir 
528cdf0e10cSrcweir 	// Buffer fuellen
529cdf0e10cSrcweir 	pBuf = pWriteBuf;
530cdf0e10cSrcweir 	pGroup = pData->mpFirstGroup;
531cdf0e10cSrcweir 	while ( pGroup )
532cdf0e10cSrcweir 	{
533cdf0e10cSrcweir 		// Leere Gruppen werden nicht geschrieben
534cdf0e10cSrcweir 		if ( pGroup->mpFirstKey )
535cdf0e10cSrcweir 		{
536cdf0e10cSrcweir 			*pBuf = '[';    pBuf++;
537cdf0e10cSrcweir 			memcpy( pBuf, pGroup->maGroupName.GetBuffer(), pGroup->maGroupName.Len() );
538cdf0e10cSrcweir 			pBuf += pGroup->maGroupName.Len();
539cdf0e10cSrcweir 			*pBuf = ']';    pBuf++;
540cdf0e10cSrcweir 			*pBuf = aLineEndBuf[0]; pBuf++;
541cdf0e10cSrcweir 			if ( nLineEndLen == 2 )
542cdf0e10cSrcweir 			{
543cdf0e10cSrcweir 				*pBuf = aLineEndBuf[1]; pBuf++;
544cdf0e10cSrcweir 			}
545cdf0e10cSrcweir 			pKey = pGroup->mpFirstKey;
546cdf0e10cSrcweir 			while ( pKey )
547cdf0e10cSrcweir 			{
548cdf0e10cSrcweir 				nValueLen = pKey->maValue.Len();
549cdf0e10cSrcweir 				if ( pKey->mbIsComment )
550cdf0e10cSrcweir 				{
551cdf0e10cSrcweir 					if ( nValueLen )
552cdf0e10cSrcweir 					{
553cdf0e10cSrcweir 						memcpy( pBuf, pKey->maValue.GetBuffer(), nValueLen );
554cdf0e10cSrcweir 						pBuf += nValueLen;
555cdf0e10cSrcweir 					}
556cdf0e10cSrcweir 					*pBuf = aLineEndBuf[0]; pBuf++;
557cdf0e10cSrcweir 					if ( nLineEndLen == 2 )
558cdf0e10cSrcweir 					{
559cdf0e10cSrcweir 						*pBuf = aLineEndBuf[1]; pBuf++;
560cdf0e10cSrcweir 					}
561cdf0e10cSrcweir 				}
562cdf0e10cSrcweir 				else
563cdf0e10cSrcweir 				{
564cdf0e10cSrcweir 					nKeyLen = pKey->maKey.Len();
565cdf0e10cSrcweir 					memcpy( pBuf, pKey->maKey.GetBuffer(), nKeyLen );
566cdf0e10cSrcweir 					pBuf += nKeyLen;
567cdf0e10cSrcweir 					*pBuf = '=';    pBuf++;
568cdf0e10cSrcweir 					memcpy( pBuf, pKey->maValue.GetBuffer(), nValueLen );
569cdf0e10cSrcweir 					pBuf += nValueLen;
570cdf0e10cSrcweir 					*pBuf = aLineEndBuf[0]; pBuf++;
571cdf0e10cSrcweir 					if ( nLineEndLen == 2 )
572cdf0e10cSrcweir 					{
573cdf0e10cSrcweir 						*pBuf = aLineEndBuf[1]; pBuf++;
574cdf0e10cSrcweir 					}
575cdf0e10cSrcweir 				}
576cdf0e10cSrcweir 
577cdf0e10cSrcweir 				pKey = pKey->mpNext;
578cdf0e10cSrcweir 			}
579cdf0e10cSrcweir 
580cdf0e10cSrcweir 			// Leerzeile nach jeder Gruppe auch wieder speichern
581cdf0e10cSrcweir 			sal_uInt16 nEmptyLines = pGroup->mnEmptyLines;
582cdf0e10cSrcweir 			while ( nEmptyLines )
583cdf0e10cSrcweir 			{
584cdf0e10cSrcweir 				*pBuf = aLineEndBuf[0]; pBuf++;
585cdf0e10cSrcweir 				if ( nLineEndLen == 2 )
586cdf0e10cSrcweir 				{
587cdf0e10cSrcweir 					*pBuf = aLineEndBuf[1]; pBuf++;
588cdf0e10cSrcweir 				}
589cdf0e10cSrcweir 				nEmptyLines--;
590cdf0e10cSrcweir 			}
591cdf0e10cSrcweir 		}
592cdf0e10cSrcweir 
593cdf0e10cSrcweir 		pGroup = pGroup->mpNext;
594cdf0e10cSrcweir 	}
595cdf0e10cSrcweir 
596cdf0e10cSrcweir 	return pWriteBuf;
597cdf0e10cSrcweir }
598cdf0e10cSrcweir 
599cdf0e10cSrcweir // -----------------------------------------------------------------------
600cdf0e10cSrcweir 
ImplReadConfig(ImplConfigData * pData)601cdf0e10cSrcweir static void ImplReadConfig( ImplConfigData* pData )
602cdf0e10cSrcweir {
603cdf0e10cSrcweir 	sal_uIntPtr			nTimeStamp = 0;
604cdf0e10cSrcweir 	sal_uInt64 nRead = 0;
605cdf0e10cSrcweir 	sal_Bool			bRead = sal_False;
606cdf0e10cSrcweir 	sal_Bool            	bIsUTF8BOM =sal_False;
607cdf0e10cSrcweir 	sal_uInt8*			pBuf = ImplSysReadConfig( pData->maFileName, nRead, bRead, bIsUTF8BOM, nTimeStamp );
608cdf0e10cSrcweir 
609cdf0e10cSrcweir 	// Aus dem Buffer die Config-Verwaltungsliste aufbauen
610cdf0e10cSrcweir 	if ( pBuf )
611cdf0e10cSrcweir 	{
612cdf0e10cSrcweir 		ImplMakeConfigList( pData, pBuf, nRead );
613cdf0e10cSrcweir 		delete[] pBuf;
614cdf0e10cSrcweir 	}
615cdf0e10cSrcweir 	pData->mnTimeStamp = nTimeStamp;
616cdf0e10cSrcweir 	pData->mbModified  = sal_False;
617cdf0e10cSrcweir 	if ( bRead )
618cdf0e10cSrcweir 		pData->mbRead = sal_True;
619cdf0e10cSrcweir 	if ( bIsUTF8BOM )
620cdf0e10cSrcweir 		pData->mbIsUTF8BOM = sal_True;
621cdf0e10cSrcweir }
622cdf0e10cSrcweir 
623cdf0e10cSrcweir // -----------------------------------------------------------------------
624cdf0e10cSrcweir 
ImplWriteConfig(ImplConfigData * pData)625cdf0e10cSrcweir static void ImplWriteConfig( ImplConfigData* pData )
626cdf0e10cSrcweir {
627cdf0e10cSrcweir #ifdef DBG_UTIL
628cdf0e10cSrcweir 	if ( DbgIsAssert() )
629cdf0e10cSrcweir 	{
630cdf0e10cSrcweir 		if ( pData->mnTimeStamp != ImplSysGetConfigTimeStamp( pData->maFileName ) )
631cdf0e10cSrcweir 		{
632cdf0e10cSrcweir 			DBG_ERROR1( "Config overwrites modified configfile:\n %s", ByteString( pData->maFileName, RTL_TEXTENCODING_UTF8 ).GetBuffer() );
633cdf0e10cSrcweir 		}
634cdf0e10cSrcweir 	}
635cdf0e10cSrcweir #endif
636cdf0e10cSrcweir 
637cdf0e10cSrcweir 	// Aus der Config-Liste einen Buffer zusammenbauen
638cdf0e10cSrcweir 	sal_uIntPtr	nBufLen;
639cdf0e10cSrcweir 	sal_uInt8*	pBuf = ImplGetConfigBuffer( pData, nBufLen );
640cdf0e10cSrcweir 	if ( pBuf )
641cdf0e10cSrcweir 	{
642cdf0e10cSrcweir 		if ( ImplSysWriteConfig( pData->maFileName, pBuf, nBufLen, pData->mbIsUTF8BOM, pData->mnTimeStamp ) )
643cdf0e10cSrcweir 			pData->mbModified = sal_False;
644cdf0e10cSrcweir 		delete[] pBuf;
645cdf0e10cSrcweir 	}
646cdf0e10cSrcweir 	else
647cdf0e10cSrcweir 		pData->mbModified = sal_False;
648cdf0e10cSrcweir }
649cdf0e10cSrcweir 
650cdf0e10cSrcweir // -----------------------------------------------------------------------
651cdf0e10cSrcweir 
ImplDeleteConfigData(ImplConfigData * pData)652cdf0e10cSrcweir static void ImplDeleteConfigData( ImplConfigData* pData )
653cdf0e10cSrcweir {
654cdf0e10cSrcweir 	ImplKeyData*	pTempKey;
655cdf0e10cSrcweir 	ImplKeyData*	pKey;
656cdf0e10cSrcweir 	ImplGroupData*	pTempGroup;
657cdf0e10cSrcweir 	ImplGroupData*	pGroup = pData->mpFirstGroup;
658cdf0e10cSrcweir 	while ( pGroup )
659cdf0e10cSrcweir 	{
660cdf0e10cSrcweir 		pTempGroup = pGroup->mpNext;
661cdf0e10cSrcweir 
662cdf0e10cSrcweir 		// Alle Keys loeschen
663cdf0e10cSrcweir 		pKey = pGroup->mpFirstKey;
664cdf0e10cSrcweir 		while ( pKey )
665cdf0e10cSrcweir 		{
666cdf0e10cSrcweir 			pTempKey = pKey->mpNext;
667cdf0e10cSrcweir 			delete pKey;
668cdf0e10cSrcweir 			pKey = pTempKey;
669cdf0e10cSrcweir 		}
670cdf0e10cSrcweir 
671cdf0e10cSrcweir 		// Gruppe loeschen und weiterschalten
672cdf0e10cSrcweir 		delete pGroup;
673cdf0e10cSrcweir 		pGroup = pTempGroup;
674cdf0e10cSrcweir 	}
675cdf0e10cSrcweir 
676cdf0e10cSrcweir 	pData->mpFirstGroup = NULL;
677cdf0e10cSrcweir }
678cdf0e10cSrcweir 
679cdf0e10cSrcweir // =======================================================================
680cdf0e10cSrcweir 
ImplGetConfigData(const XubString & rFileName)681cdf0e10cSrcweir static ImplConfigData* ImplGetConfigData( const XubString& rFileName )
682cdf0e10cSrcweir {
683cdf0e10cSrcweir 	ImplConfigData* pData;
684cdf0e10cSrcweir 
685cdf0e10cSrcweir 	pData					= new ImplConfigData;
686cdf0e10cSrcweir 	pData->maFileName		= rFileName;
687cdf0e10cSrcweir 	pData->mpFirstGroup 	= NULL;
688cdf0e10cSrcweir 	pData->mnDataUpdateId	= 0;
689cdf0e10cSrcweir 	pData->meLineEnd		= LINEEND_CRLF;
690cdf0e10cSrcweir 	pData->mnRefCount		= 0;
691cdf0e10cSrcweir 	pData->mbRead			= sal_False;
692cdf0e10cSrcweir     pData->mbIsUTF8BOM      = sal_False;
693cdf0e10cSrcweir 	ImplReadConfig( pData );
694cdf0e10cSrcweir 
695cdf0e10cSrcweir 	return pData;
696cdf0e10cSrcweir }
697cdf0e10cSrcweir 
698cdf0e10cSrcweir // -----------------------------------------------------------------------
699cdf0e10cSrcweir 
ImplFreeConfigData(ImplConfigData * pDelData)700cdf0e10cSrcweir static void ImplFreeConfigData( ImplConfigData* pDelData )
701cdf0e10cSrcweir {
702cdf0e10cSrcweir 	ImplDeleteConfigData( pDelData );
703cdf0e10cSrcweir 	delete pDelData;
704cdf0e10cSrcweir }
705cdf0e10cSrcweir 
706cdf0e10cSrcweir // =======================================================================
707cdf0e10cSrcweir 
ImplUpdateConfig() const708cdf0e10cSrcweir sal_Bool Config::ImplUpdateConfig() const
709cdf0e10cSrcweir {
710cdf0e10cSrcweir 	// Wenn sich TimeStamp unterscheidet, dann Datei neu einlesen
711cdf0e10cSrcweir 	if ( mpData->mnTimeStamp != ImplSysGetConfigTimeStamp( maFileName ) )
712cdf0e10cSrcweir 	{
713cdf0e10cSrcweir 		ImplDeleteConfigData( mpData );
714cdf0e10cSrcweir 		ImplReadConfig( mpData );
715cdf0e10cSrcweir 		mpData->mnDataUpdateId++;
716cdf0e10cSrcweir 		return sal_True;
717cdf0e10cSrcweir 	}
718cdf0e10cSrcweir 	else
719cdf0e10cSrcweir 		return sal_False;
720cdf0e10cSrcweir }
721cdf0e10cSrcweir 
722cdf0e10cSrcweir // -----------------------------------------------------------------------
723cdf0e10cSrcweir 
ImplGetGroup() const724cdf0e10cSrcweir ImplGroupData* Config::ImplGetGroup() const
725cdf0e10cSrcweir {
726cdf0e10cSrcweir 	if ( !mpActGroup || (mnDataUpdateId != mpData->mnDataUpdateId) )
727cdf0e10cSrcweir 	{
728cdf0e10cSrcweir 		ImplGroupData* pPrevGroup = NULL;
729cdf0e10cSrcweir 		ImplGroupData* pGroup = mpData->mpFirstGroup;
730cdf0e10cSrcweir 		while ( pGroup )
731cdf0e10cSrcweir 		{
732cdf0e10cSrcweir 			if ( pGroup->maGroupName.EqualsIgnoreCaseAscii( maGroupName ) )
733cdf0e10cSrcweir 				break;
734cdf0e10cSrcweir 
735cdf0e10cSrcweir 			pPrevGroup = pGroup;
736cdf0e10cSrcweir 			pGroup = pGroup->mpNext;
737cdf0e10cSrcweir 		}
738cdf0e10cSrcweir 
739cdf0e10cSrcweir 		// Falls Gruppe noch nicht existiert, dann dazufuegen
740cdf0e10cSrcweir 		if ( !pGroup )
741cdf0e10cSrcweir 		{
742cdf0e10cSrcweir 			pGroup				 = new ImplGroupData;
743cdf0e10cSrcweir 			pGroup->mpNext		 = NULL;
744cdf0e10cSrcweir 			pGroup->mpFirstKey	 = NULL;
745cdf0e10cSrcweir 			pGroup->mnEmptyLines = 1;
746cdf0e10cSrcweir 			if ( pPrevGroup )
747cdf0e10cSrcweir 				pPrevGroup->mpNext = pGroup;
748cdf0e10cSrcweir 			else
749cdf0e10cSrcweir 				mpData->mpFirstGroup = pGroup;
750cdf0e10cSrcweir 		}
751cdf0e10cSrcweir 
752cdf0e10cSrcweir 		// Gruppenname immer uebernehmen, da er auch in dieser Form
753cdf0e10cSrcweir 		// geschrieben werden soll. Ausserdem die Cache-Members der
754cdf0e10cSrcweir 		// Config-Klasse updaten
755cdf0e10cSrcweir 		pGroup->maGroupName 			= maGroupName;
756cdf0e10cSrcweir 		((Config*)this)->mnDataUpdateId = mpData->mnDataUpdateId;
757cdf0e10cSrcweir 		((Config*)this)->mpActGroup 	= pGroup;
758cdf0e10cSrcweir 	}
759cdf0e10cSrcweir 
760cdf0e10cSrcweir 	return mpActGroup;
761cdf0e10cSrcweir }
762cdf0e10cSrcweir 
763cdf0e10cSrcweir // =======================================================================
764cdf0e10cSrcweir 
Config()765cdf0e10cSrcweir Config::Config()
766cdf0e10cSrcweir {
767cdf0e10cSrcweir 	// Daten initialisieren und einlesen
768cdf0e10cSrcweir 	maFileName		= ImplMakeConfigName( NULL, NULL );
769cdf0e10cSrcweir 	mpData			= ImplGetConfigData( maFileName );
770cdf0e10cSrcweir 	mpActGroup		= NULL;
771cdf0e10cSrcweir 	mnDataUpdateId	= 0;
772cdf0e10cSrcweir 	mnLockCount 	= 1;
773cdf0e10cSrcweir 	mbPersistence	= sal_True;
774cdf0e10cSrcweir 
775cdf0e10cSrcweir #ifdef DBG_UTIL
776cdf0e10cSrcweir 	DBG_TRACE( "Config::Config()" );
777cdf0e10cSrcweir #endif
778cdf0e10cSrcweir }
779cdf0e10cSrcweir 
780cdf0e10cSrcweir // -----------------------------------------------------------------------
781cdf0e10cSrcweir 
Config(const XubString & rFileName)782cdf0e10cSrcweir Config::Config( const XubString& rFileName )
783cdf0e10cSrcweir {
784cdf0e10cSrcweir 	// Daten initialisieren und einlesen
785cdf0e10cSrcweir 	maFileName		= toUncPath( rFileName );
786cdf0e10cSrcweir 	mpData			= ImplGetConfigData( maFileName );
787cdf0e10cSrcweir 	mpActGroup		= NULL;
788cdf0e10cSrcweir 	mnDataUpdateId	= 0;
789cdf0e10cSrcweir 	mnLockCount 	= 1;
790cdf0e10cSrcweir 	mbPersistence	= sal_True;
791cdf0e10cSrcweir 
792cdf0e10cSrcweir #ifdef DBG_UTIL
793cdf0e10cSrcweir 	ByteString aTraceStr( "Config::Config( " );
794cdf0e10cSrcweir 	aTraceStr += ByteString( maFileName, RTL_TEXTENCODING_UTF8 );
795cdf0e10cSrcweir 	aTraceStr += " )";
796cdf0e10cSrcweir 	DBG_TRACE( aTraceStr.GetBuffer() );
797cdf0e10cSrcweir #endif
798cdf0e10cSrcweir }
799cdf0e10cSrcweir 
800cdf0e10cSrcweir // -----------------------------------------------------------------------
801cdf0e10cSrcweir 
~Config()802cdf0e10cSrcweir Config::~Config()
803cdf0e10cSrcweir {
804cdf0e10cSrcweir #ifdef DBG_UTIL
805cdf0e10cSrcweir 	DBG_TRACE( "Config::~Config()" );
806cdf0e10cSrcweir #endif
807cdf0e10cSrcweir 
808cdf0e10cSrcweir 	Flush();
809cdf0e10cSrcweir 	ImplFreeConfigData( mpData );
810cdf0e10cSrcweir }
811cdf0e10cSrcweir 
812cdf0e10cSrcweir // -----------------------------------------------------------------------
813cdf0e10cSrcweir 
GetDefDirectory()814cdf0e10cSrcweir String Config::GetDefDirectory()
815cdf0e10cSrcweir {
816cdf0e10cSrcweir     ::rtl::OUString aDefConfig;
817cdf0e10cSrcweir     oslSecurity aSec = osl_getCurrentSecurity();
818cdf0e10cSrcweir     osl_getConfigDir( aSec, &aDefConfig.pData );
819cdf0e10cSrcweir     osl_freeSecurityHandle( aSec );
820cdf0e10cSrcweir 
821cdf0e10cSrcweir 	return aDefConfig;
822cdf0e10cSrcweir }
823cdf0e10cSrcweir 
824cdf0e10cSrcweir // -----------------------------------------------------------------------
825cdf0e10cSrcweir 
GetConfigName(const XubString & rPath,const XubString & rBaseName)826cdf0e10cSrcweir XubString Config::GetConfigName( const XubString& rPath,
827cdf0e10cSrcweir 								 const XubString& rBaseName )
828cdf0e10cSrcweir {
829cdf0e10cSrcweir 	return ImplMakeConfigName( &rBaseName, &rPath );
830cdf0e10cSrcweir }
831cdf0e10cSrcweir 
832cdf0e10cSrcweir // -----------------------------------------------------------------------
833cdf0e10cSrcweir 
SetGroup(const ByteString & rGroup)834cdf0e10cSrcweir void Config::SetGroup( const ByteString& rGroup )
835cdf0e10cSrcweir {
836cdf0e10cSrcweir 	// Wenn neue Gruppe gesetzt wird, muss beim naechsten mal die
837cdf0e10cSrcweir 	// Gruppe neu ermittelt werden
838cdf0e10cSrcweir 	if ( maGroupName != rGroup )
839cdf0e10cSrcweir 	{
840cdf0e10cSrcweir 		maGroupName 	= rGroup;
841cdf0e10cSrcweir 		mnDataUpdateId	= mpData->mnDataUpdateId-1;
842cdf0e10cSrcweir 	}
843cdf0e10cSrcweir }
844cdf0e10cSrcweir 
845cdf0e10cSrcweir // -----------------------------------------------------------------------
846cdf0e10cSrcweir 
DeleteGroup(const ByteString & rGroup)847cdf0e10cSrcweir void Config::DeleteGroup( const ByteString& rGroup )
848cdf0e10cSrcweir {
849cdf0e10cSrcweir 	// Config-Daten evt. updaten
850cdf0e10cSrcweir 	if ( !mnLockCount || !mpData->mbRead )
851cdf0e10cSrcweir 	{
852cdf0e10cSrcweir 		ImplUpdateConfig();
853cdf0e10cSrcweir 		mpData->mbRead = sal_True;
854cdf0e10cSrcweir 	}
855cdf0e10cSrcweir 
856cdf0e10cSrcweir 	ImplGroupData* pPrevGroup = NULL;
857cdf0e10cSrcweir 	ImplGroupData* pGroup = mpData->mpFirstGroup;
858cdf0e10cSrcweir 	while ( pGroup )
859cdf0e10cSrcweir 	{
860cdf0e10cSrcweir 		if ( pGroup->maGroupName.EqualsIgnoreCaseAscii( rGroup ) )
861cdf0e10cSrcweir 			break;
862cdf0e10cSrcweir 
863cdf0e10cSrcweir 		pPrevGroup = pGroup;
864cdf0e10cSrcweir 		pGroup = pGroup->mpNext;
865cdf0e10cSrcweir 	}
866cdf0e10cSrcweir 
867cdf0e10cSrcweir 	if ( pGroup )
868cdf0e10cSrcweir 	{
869cdf0e10cSrcweir 		// Alle Keys loeschen
870cdf0e10cSrcweir 		ImplKeyData* pTempKey;
871cdf0e10cSrcweir 		ImplKeyData* pKey = pGroup->mpFirstKey;
872cdf0e10cSrcweir 		while ( pKey )
873cdf0e10cSrcweir 		{
874cdf0e10cSrcweir 			pTempKey = pKey->mpNext;
875cdf0e10cSrcweir 			delete pKey;
876cdf0e10cSrcweir 			pKey = pTempKey;
877cdf0e10cSrcweir 		}
878cdf0e10cSrcweir 
879cdf0e10cSrcweir 		// Gruppe weiterschalten und loeschen
880cdf0e10cSrcweir 		if ( pPrevGroup )
881cdf0e10cSrcweir 			pPrevGroup->mpNext = pGroup->mpNext;
882cdf0e10cSrcweir 		else
883cdf0e10cSrcweir 			mpData->mpFirstGroup = pGroup->mpNext;
884cdf0e10cSrcweir 		delete pGroup;
885cdf0e10cSrcweir 
886cdf0e10cSrcweir 		// Config-Datei neu schreiben
887cdf0e10cSrcweir 		if ( !mnLockCount && mbPersistence )
888cdf0e10cSrcweir 			ImplWriteConfig( mpData );
889cdf0e10cSrcweir 		else
890cdf0e10cSrcweir 		{
891cdf0e10cSrcweir 			mpData->mbModified = sal_True;
892cdf0e10cSrcweir 		}
893cdf0e10cSrcweir 
894cdf0e10cSrcweir 		// Gruppen auf ungluetig setzen
895cdf0e10cSrcweir 		mnDataUpdateId = mpData->mnDataUpdateId;
896cdf0e10cSrcweir 		mpData->mnDataUpdateId++;
897cdf0e10cSrcweir 	}
898cdf0e10cSrcweir }
899cdf0e10cSrcweir 
900cdf0e10cSrcweir // -----------------------------------------------------------------------
901cdf0e10cSrcweir 
GetGroupName(sal_uInt16 nGroup) const902cdf0e10cSrcweir ByteString Config::GetGroupName( sal_uInt16 nGroup ) const
903cdf0e10cSrcweir {
904cdf0e10cSrcweir 	// Config-Daten evt. updaten
905cdf0e10cSrcweir 	if ( !mnLockCount )
906cdf0e10cSrcweir 		ImplUpdateConfig();
907cdf0e10cSrcweir 
908cdf0e10cSrcweir 	ImplGroupData*	pGroup = mpData->mpFirstGroup;
909cdf0e10cSrcweir 	sal_uInt16			nGroupCount = 0;
910cdf0e10cSrcweir 	ByteString		aGroupName;
911cdf0e10cSrcweir 	while ( pGroup )
912cdf0e10cSrcweir 	{
913cdf0e10cSrcweir 		if ( nGroup == nGroupCount )
914cdf0e10cSrcweir 		{
915cdf0e10cSrcweir 			aGroupName = pGroup->maGroupName;
916cdf0e10cSrcweir 			break;
917cdf0e10cSrcweir 		}
918cdf0e10cSrcweir 
919cdf0e10cSrcweir 		nGroupCount++;
920cdf0e10cSrcweir 		pGroup = pGroup->mpNext;
921cdf0e10cSrcweir 	}
922cdf0e10cSrcweir 
923cdf0e10cSrcweir 	return aGroupName;
924cdf0e10cSrcweir }
925cdf0e10cSrcweir 
926cdf0e10cSrcweir // -----------------------------------------------------------------------
927cdf0e10cSrcweir 
GetGroupCount() const928cdf0e10cSrcweir sal_uInt16 Config::GetGroupCount() const
929cdf0e10cSrcweir {
930cdf0e10cSrcweir 	// Config-Daten evt. updaten
931cdf0e10cSrcweir 	if ( !mnLockCount )
932cdf0e10cSrcweir 		ImplUpdateConfig();
933cdf0e10cSrcweir 
934cdf0e10cSrcweir 	ImplGroupData*	pGroup = mpData->mpFirstGroup;
935cdf0e10cSrcweir 	sal_uInt16			nGroupCount = 0;
936cdf0e10cSrcweir 	while ( pGroup )
937cdf0e10cSrcweir 	{
938cdf0e10cSrcweir 		nGroupCount++;
939cdf0e10cSrcweir 		pGroup = pGroup->mpNext;
940cdf0e10cSrcweir 	}
941cdf0e10cSrcweir 
942cdf0e10cSrcweir 	return nGroupCount;
943cdf0e10cSrcweir }
944cdf0e10cSrcweir 
945cdf0e10cSrcweir // -----------------------------------------------------------------------
946cdf0e10cSrcweir 
HasGroup(const ByteString & rGroup) const947cdf0e10cSrcweir sal_Bool Config::HasGroup( const ByteString& rGroup ) const
948cdf0e10cSrcweir {
949cdf0e10cSrcweir 	// Config-Daten evt. updaten
950cdf0e10cSrcweir 	if ( !mnLockCount )
951cdf0e10cSrcweir 		ImplUpdateConfig();
952cdf0e10cSrcweir 
953cdf0e10cSrcweir 	ImplGroupData*	pGroup = mpData->mpFirstGroup;
954cdf0e10cSrcweir 	sal_Bool			bRet = sal_False;
955cdf0e10cSrcweir 
956cdf0e10cSrcweir 	while( pGroup )
957cdf0e10cSrcweir 	{
958cdf0e10cSrcweir 		if( pGroup->maGroupName.EqualsIgnoreCaseAscii( rGroup ) )
959cdf0e10cSrcweir 		{
960cdf0e10cSrcweir 			bRet = sal_True;
961cdf0e10cSrcweir 			break;
962cdf0e10cSrcweir 		}
963cdf0e10cSrcweir 
964cdf0e10cSrcweir 		pGroup = pGroup->mpNext;
965cdf0e10cSrcweir 	}
966cdf0e10cSrcweir 
967cdf0e10cSrcweir 	return bRet;
968cdf0e10cSrcweir }
969cdf0e10cSrcweir 
970cdf0e10cSrcweir // -----------------------------------------------------------------------
971cdf0e10cSrcweir 
ReadKey(const ByteString & rKey) const972cdf0e10cSrcweir ByteString Config::ReadKey( const ByteString& rKey ) const
973cdf0e10cSrcweir {
974cdf0e10cSrcweir 	return ReadKey( rKey, getEmptyByteString() );
975cdf0e10cSrcweir }
976cdf0e10cSrcweir 
977cdf0e10cSrcweir // -----------------------------------------------------------------------
978cdf0e10cSrcweir 
ReadKey(const ByteString & rKey,rtl_TextEncoding eEncoding) const979cdf0e10cSrcweir UniString Config::ReadKey( const ByteString& rKey, rtl_TextEncoding eEncoding ) const
980cdf0e10cSrcweir {
981cdf0e10cSrcweir 	if ( mpData->mbIsUTF8BOM )
982cdf0e10cSrcweir 		eEncoding = RTL_TEXTENCODING_UTF8;
983cdf0e10cSrcweir 	return UniString( ReadKey( rKey ), eEncoding );
984cdf0e10cSrcweir }
985cdf0e10cSrcweir 
986cdf0e10cSrcweir // -----------------------------------------------------------------------
987cdf0e10cSrcweir 
ReadKey(const ByteString & rKey,const ByteString & rDefault) const988cdf0e10cSrcweir ByteString Config::ReadKey( const ByteString& rKey, const ByteString& rDefault ) const
989cdf0e10cSrcweir {
990cdf0e10cSrcweir #ifdef DBG_UTIL
991cdf0e10cSrcweir 	ByteString aTraceStr( "Config::ReadKey( " );
992cdf0e10cSrcweir 	aTraceStr += rKey;
993cdf0e10cSrcweir 	aTraceStr += " ) from ";
994cdf0e10cSrcweir 	aTraceStr += GetGroup();
995cdf0e10cSrcweir 	aTraceStr += " in ";
996cdf0e10cSrcweir 	aTraceStr += ByteString( maFileName, RTL_TEXTENCODING_UTF8 );
997cdf0e10cSrcweir 	DBG_TRACE( aTraceStr.GetBuffer() );
998cdf0e10cSrcweir #endif
999cdf0e10cSrcweir 
1000cdf0e10cSrcweir 	// Config-Daten evt. updaten
1001cdf0e10cSrcweir 	if ( !mnLockCount )
1002cdf0e10cSrcweir 		ImplUpdateConfig();
1003cdf0e10cSrcweir 
1004cdf0e10cSrcweir 	// Key suchen und Value zurueckgeben
1005cdf0e10cSrcweir 	ImplGroupData* pGroup = ImplGetGroup();
1006cdf0e10cSrcweir 	if ( pGroup )
1007cdf0e10cSrcweir 	{
1008cdf0e10cSrcweir 		ImplKeyData* pKey = pGroup->mpFirstKey;
1009cdf0e10cSrcweir 		while ( pKey )
1010cdf0e10cSrcweir 		{
1011cdf0e10cSrcweir 			if ( !pKey->mbIsComment && pKey->maKey.EqualsIgnoreCaseAscii( rKey ) )
1012cdf0e10cSrcweir 				return pKey->maValue;
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir 			pKey = pKey->mpNext;
1015cdf0e10cSrcweir 		}
1016cdf0e10cSrcweir 	}
1017cdf0e10cSrcweir 
1018cdf0e10cSrcweir 	return rDefault;
1019cdf0e10cSrcweir }
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir // -----------------------------------------------------------------------
1022cdf0e10cSrcweir 
WriteKey(const ByteString & rKey,const ByteString & rStr)1023cdf0e10cSrcweir void Config::WriteKey( const ByteString& rKey, const ByteString& rStr )
1024cdf0e10cSrcweir {
1025cdf0e10cSrcweir #ifdef DBG_UTIL
1026cdf0e10cSrcweir 	ByteString aTraceStr( "Config::WriteKey( " );
1027cdf0e10cSrcweir 	aTraceStr += rKey;
1028cdf0e10cSrcweir 	aTraceStr += ", ";
1029cdf0e10cSrcweir 	aTraceStr += rStr;
1030cdf0e10cSrcweir 	aTraceStr += " ) to ";
1031cdf0e10cSrcweir 	aTraceStr += GetGroup();
1032cdf0e10cSrcweir 	aTraceStr += " in ";
1033cdf0e10cSrcweir 	aTraceStr += ByteString( maFileName, RTL_TEXTENCODING_UTF8 );
1034cdf0e10cSrcweir 	DBG_TRACE( aTraceStr.GetBuffer() );
1035cdf0e10cSrcweir 	DBG_ASSERTWARNING( rStr != ReadKey( rKey ), "Config::WriteKey() with the same Value" );
1036cdf0e10cSrcweir #endif
1037cdf0e10cSrcweir 
1038cdf0e10cSrcweir 	// Config-Daten evt. updaten
1039cdf0e10cSrcweir 	if ( !mnLockCount || !mpData->mbRead )
1040cdf0e10cSrcweir 	{
1041cdf0e10cSrcweir 		ImplUpdateConfig();
1042cdf0e10cSrcweir 		mpData->mbRead = sal_True;
1043cdf0e10cSrcweir 	}
1044cdf0e10cSrcweir 
1045cdf0e10cSrcweir 	// Key suchen und Value setzen
1046cdf0e10cSrcweir 	ImplGroupData* pGroup = ImplGetGroup();
1047cdf0e10cSrcweir 	if ( pGroup )
1048cdf0e10cSrcweir 	{
1049cdf0e10cSrcweir 		ImplKeyData* pPrevKey = NULL;
1050cdf0e10cSrcweir 		ImplKeyData* pKey = pGroup->mpFirstKey;
1051cdf0e10cSrcweir 		while ( pKey )
1052cdf0e10cSrcweir 		{
1053cdf0e10cSrcweir 			if ( !pKey->mbIsComment && pKey->maKey.EqualsIgnoreCaseAscii( rKey ) )
1054cdf0e10cSrcweir 				break;
1055cdf0e10cSrcweir 
1056cdf0e10cSrcweir 			pPrevKey = pKey;
1057cdf0e10cSrcweir 			pKey = pKey->mpNext;
1058cdf0e10cSrcweir 		}
1059cdf0e10cSrcweir 
1060cdf0e10cSrcweir 		sal_Bool bNewValue;
1061cdf0e10cSrcweir 		if ( !pKey )
1062cdf0e10cSrcweir 		{
1063cdf0e10cSrcweir 			pKey			  = new ImplKeyData;
1064cdf0e10cSrcweir 			pKey->mpNext	  = NULL;
1065cdf0e10cSrcweir 			pKey->maKey 	  = rKey;
1066cdf0e10cSrcweir 			pKey->mbIsComment = sal_False;
1067cdf0e10cSrcweir 			if ( pPrevKey )
1068cdf0e10cSrcweir 				pPrevKey->mpNext = pKey;
1069cdf0e10cSrcweir 			else
1070cdf0e10cSrcweir 				pGroup->mpFirstKey = pKey;
1071cdf0e10cSrcweir 			bNewValue = sal_True;
1072cdf0e10cSrcweir 		}
1073cdf0e10cSrcweir 		else
1074cdf0e10cSrcweir 			bNewValue = pKey->maValue != rStr;
1075cdf0e10cSrcweir 
1076cdf0e10cSrcweir 		if ( bNewValue )
1077cdf0e10cSrcweir 		{
1078cdf0e10cSrcweir 			pKey->maValue = rStr;
1079cdf0e10cSrcweir 
1080cdf0e10cSrcweir 			if ( !mnLockCount && mbPersistence )
1081cdf0e10cSrcweir 				ImplWriteConfig( mpData );
1082cdf0e10cSrcweir 			else
1083cdf0e10cSrcweir 			{
1084cdf0e10cSrcweir 				mpData->mbModified = sal_True;
1085cdf0e10cSrcweir 			}
1086cdf0e10cSrcweir 		}
1087cdf0e10cSrcweir 	}
1088cdf0e10cSrcweir }
1089cdf0e10cSrcweir 
1090cdf0e10cSrcweir // -----------------------------------------------------------------------
1091cdf0e10cSrcweir 
WriteKey(const ByteString & rKey,const UniString & rValue,rtl_TextEncoding eEncoding)1092cdf0e10cSrcweir void Config::WriteKey( const ByteString& rKey, const UniString& rValue, rtl_TextEncoding eEncoding )
1093cdf0e10cSrcweir {
1094cdf0e10cSrcweir 	if ( mpData->mbIsUTF8BOM  )
1095cdf0e10cSrcweir 		eEncoding = RTL_TEXTENCODING_UTF8;
1096cdf0e10cSrcweir 	WriteKey( rKey, ByteString( rValue, eEncoding ) );
1097cdf0e10cSrcweir }
1098cdf0e10cSrcweir 
1099cdf0e10cSrcweir // -----------------------------------------------------------------------
1100cdf0e10cSrcweir 
DeleteKey(const ByteString & rKey)1101cdf0e10cSrcweir void Config::DeleteKey( const ByteString& rKey )
1102cdf0e10cSrcweir {
1103cdf0e10cSrcweir 	// Config-Daten evt. updaten
1104cdf0e10cSrcweir 	if ( !mnLockCount || !mpData->mbRead )
1105cdf0e10cSrcweir 	{
1106cdf0e10cSrcweir 		ImplUpdateConfig();
1107cdf0e10cSrcweir 		mpData->mbRead = sal_True;
1108cdf0e10cSrcweir 	}
1109cdf0e10cSrcweir 
1110cdf0e10cSrcweir 	// Key suchen und Value setzen
1111cdf0e10cSrcweir 	ImplGroupData* pGroup = ImplGetGroup();
1112cdf0e10cSrcweir 	if ( pGroup )
1113cdf0e10cSrcweir 	{
1114cdf0e10cSrcweir 		ImplKeyData* pPrevKey = NULL;
1115cdf0e10cSrcweir 		ImplKeyData* pKey = pGroup->mpFirstKey;
1116cdf0e10cSrcweir 		while ( pKey )
1117cdf0e10cSrcweir 		{
1118cdf0e10cSrcweir 			if ( !pKey->mbIsComment && pKey->maKey.EqualsIgnoreCaseAscii( rKey ) )
1119cdf0e10cSrcweir 				break;
1120cdf0e10cSrcweir 
1121cdf0e10cSrcweir 			pPrevKey = pKey;
1122cdf0e10cSrcweir 			pKey = pKey->mpNext;
1123cdf0e10cSrcweir 		}
1124cdf0e10cSrcweir 
1125cdf0e10cSrcweir 		if ( pKey )
1126cdf0e10cSrcweir 		{
1127cdf0e10cSrcweir 			// Gruppe weiterschalten und loeschen
1128cdf0e10cSrcweir 			if ( pPrevKey )
1129cdf0e10cSrcweir 				pPrevKey->mpNext = pKey->mpNext;
1130cdf0e10cSrcweir 			else
1131cdf0e10cSrcweir 				pGroup->mpFirstKey = pKey->mpNext;
1132cdf0e10cSrcweir 			delete pKey;
1133cdf0e10cSrcweir 
1134cdf0e10cSrcweir 			// Config-Datei neu schreiben
1135cdf0e10cSrcweir 			if ( !mnLockCount && mbPersistence )
1136cdf0e10cSrcweir 				ImplWriteConfig( mpData );
1137cdf0e10cSrcweir 			else
1138cdf0e10cSrcweir 			{
1139cdf0e10cSrcweir 				mpData->mbModified = sal_True;
1140cdf0e10cSrcweir 			}
1141cdf0e10cSrcweir 		}
1142cdf0e10cSrcweir 	}
1143cdf0e10cSrcweir }
1144cdf0e10cSrcweir 
1145cdf0e10cSrcweir // -----------------------------------------------------------------------
1146cdf0e10cSrcweir 
GetKeyCount() const1147cdf0e10cSrcweir sal_uInt16 Config::GetKeyCount() const
1148cdf0e10cSrcweir {
1149cdf0e10cSrcweir #ifdef DBG_UTIL
1150cdf0e10cSrcweir 	ByteString aTraceStr( "Config::GetKeyCount()" );
1151cdf0e10cSrcweir 	aTraceStr += " from ";
1152cdf0e10cSrcweir 	aTraceStr += GetGroup();
1153cdf0e10cSrcweir 	aTraceStr += " in ";
1154cdf0e10cSrcweir 	aTraceStr += ByteString( maFileName, RTL_TEXTENCODING_UTF8 );
1155cdf0e10cSrcweir 	DBG_TRACE( aTraceStr.GetBuffer() );
1156cdf0e10cSrcweir #endif
1157cdf0e10cSrcweir 
1158cdf0e10cSrcweir 	// Config-Daten evt. updaten
1159cdf0e10cSrcweir 	if ( !mnLockCount )
1160cdf0e10cSrcweir 		ImplUpdateConfig();
1161cdf0e10cSrcweir 
1162cdf0e10cSrcweir 	// Key suchen und Value zurueckgeben
1163cdf0e10cSrcweir 	sal_uInt16 nCount = 0;
1164cdf0e10cSrcweir 	ImplGroupData* pGroup = ImplGetGroup();
1165cdf0e10cSrcweir 	if ( pGroup )
1166cdf0e10cSrcweir 	{
1167cdf0e10cSrcweir 		ImplKeyData* pKey = pGroup->mpFirstKey;
1168cdf0e10cSrcweir 		while ( pKey )
1169cdf0e10cSrcweir 		{
1170cdf0e10cSrcweir 			if ( !pKey->mbIsComment )
1171cdf0e10cSrcweir 				nCount++;
1172cdf0e10cSrcweir 
1173cdf0e10cSrcweir 			pKey = pKey->mpNext;
1174cdf0e10cSrcweir 		}
1175cdf0e10cSrcweir 	}
1176cdf0e10cSrcweir 
1177cdf0e10cSrcweir 	return nCount;
1178cdf0e10cSrcweir }
1179cdf0e10cSrcweir 
1180cdf0e10cSrcweir // -----------------------------------------------------------------------
1181cdf0e10cSrcweir 
GetKeyName(sal_uInt16 nKey) const1182cdf0e10cSrcweir ByteString Config::GetKeyName( sal_uInt16 nKey ) const
1183cdf0e10cSrcweir {
1184cdf0e10cSrcweir #ifdef DBG_UTIL
1185cdf0e10cSrcweir 	ByteString aTraceStr( "Config::GetKeyName( " );
1186cdf0e10cSrcweir 	aTraceStr += ByteString::CreateFromInt32(nKey);
1187cdf0e10cSrcweir 	aTraceStr += " ) from ";
1188cdf0e10cSrcweir 	aTraceStr += GetGroup();
1189cdf0e10cSrcweir 	aTraceStr += " in ";
1190cdf0e10cSrcweir 	aTraceStr += ByteString( maFileName, RTL_TEXTENCODING_UTF8 );
1191cdf0e10cSrcweir 	DBG_TRACE( aTraceStr.GetBuffer() );
1192cdf0e10cSrcweir #endif
1193cdf0e10cSrcweir 
1194cdf0e10cSrcweir 	// Key suchen und Name zurueckgeben
1195cdf0e10cSrcweir 	ImplGroupData* pGroup = ImplGetGroup();
1196cdf0e10cSrcweir 	if ( pGroup )
1197cdf0e10cSrcweir 	{
1198cdf0e10cSrcweir 		ImplKeyData* pKey = pGroup->mpFirstKey;
1199cdf0e10cSrcweir 		while ( pKey )
1200cdf0e10cSrcweir 		{
1201cdf0e10cSrcweir 			if ( !pKey->mbIsComment )
1202cdf0e10cSrcweir 			{
1203cdf0e10cSrcweir 				if ( !nKey )
1204cdf0e10cSrcweir 					return pKey->maKey;
1205cdf0e10cSrcweir 				nKey--;
1206cdf0e10cSrcweir 			}
1207cdf0e10cSrcweir 
1208cdf0e10cSrcweir 			pKey = pKey->mpNext;
1209cdf0e10cSrcweir 		}
1210cdf0e10cSrcweir 	}
1211cdf0e10cSrcweir 
1212cdf0e10cSrcweir 	return getEmptyByteString();
1213cdf0e10cSrcweir }
1214cdf0e10cSrcweir 
1215cdf0e10cSrcweir // -----------------------------------------------------------------------
1216cdf0e10cSrcweir 
ReadKey(sal_uInt16 nKey) const1217cdf0e10cSrcweir ByteString Config::ReadKey( sal_uInt16 nKey ) const
1218cdf0e10cSrcweir {
1219cdf0e10cSrcweir #ifdef DBG_UTIL
1220cdf0e10cSrcweir 	ByteString aTraceStr( "Config::ReadKey( " );
1221cdf0e10cSrcweir 	aTraceStr += ByteString::CreateFromInt32( nKey );
1222cdf0e10cSrcweir 	aTraceStr += " ) from ";
1223cdf0e10cSrcweir 	aTraceStr += GetGroup();
1224cdf0e10cSrcweir 	aTraceStr += " in ";
1225cdf0e10cSrcweir 	aTraceStr += ByteString( maFileName, RTL_TEXTENCODING_UTF8 );
1226cdf0e10cSrcweir 	DBG_TRACE( aTraceStr.GetBuffer() );
1227cdf0e10cSrcweir #endif
1228cdf0e10cSrcweir 
1229cdf0e10cSrcweir 	// Key suchen und Value zurueckgeben
1230cdf0e10cSrcweir 	ImplGroupData* pGroup = ImplGetGroup();
1231cdf0e10cSrcweir 	if ( pGroup )
1232cdf0e10cSrcweir 	{
1233cdf0e10cSrcweir 		ImplKeyData* pKey = pGroup->mpFirstKey;
1234cdf0e10cSrcweir 		while ( pKey )
1235cdf0e10cSrcweir 		{
1236cdf0e10cSrcweir 			if ( !pKey->mbIsComment )
1237cdf0e10cSrcweir 			{
1238cdf0e10cSrcweir 				if ( !nKey )
1239cdf0e10cSrcweir 					return pKey->maValue;
1240cdf0e10cSrcweir 				nKey--;
1241cdf0e10cSrcweir 			}
1242cdf0e10cSrcweir 
1243cdf0e10cSrcweir 			pKey = pKey->mpNext;
1244cdf0e10cSrcweir 		}
1245cdf0e10cSrcweir 	}
1246cdf0e10cSrcweir 
1247cdf0e10cSrcweir 	return getEmptyByteString();
1248cdf0e10cSrcweir }
1249cdf0e10cSrcweir 
1250cdf0e10cSrcweir // -----------------------------------------------------------------------
1251cdf0e10cSrcweir 
EnterLock()1252cdf0e10cSrcweir void Config::EnterLock()
1253cdf0e10cSrcweir {
1254cdf0e10cSrcweir 	// Config-Daten evt. updaten
1255cdf0e10cSrcweir 	if ( !mnLockCount )
1256cdf0e10cSrcweir 		ImplUpdateConfig();
1257cdf0e10cSrcweir 
1258cdf0e10cSrcweir 	mnLockCount++;
1259cdf0e10cSrcweir }
1260cdf0e10cSrcweir 
1261cdf0e10cSrcweir // -----------------------------------------------------------------------
1262cdf0e10cSrcweir 
LeaveLock()1263cdf0e10cSrcweir void Config::LeaveLock()
1264cdf0e10cSrcweir {
1265cdf0e10cSrcweir 	DBG_ASSERT( mnLockCount, "Config::LeaveLook() without Config::EnterLook()" );
1266cdf0e10cSrcweir 	mnLockCount--;
1267cdf0e10cSrcweir 
1268cdf0e10cSrcweir 	if ( (mnLockCount == 0) && mpData->mbModified && mbPersistence )
1269cdf0e10cSrcweir 		ImplWriteConfig( mpData );
1270cdf0e10cSrcweir }
1271cdf0e10cSrcweir 
1272cdf0e10cSrcweir // -----------------------------------------------------------------------
1273cdf0e10cSrcweir 
Update()1274cdf0e10cSrcweir sal_Bool Config::Update()
1275cdf0e10cSrcweir {
1276cdf0e10cSrcweir 	return ImplUpdateConfig();
1277cdf0e10cSrcweir }
1278cdf0e10cSrcweir 
1279cdf0e10cSrcweir // -----------------------------------------------------------------------
1280cdf0e10cSrcweir 
Flush()1281cdf0e10cSrcweir void Config::Flush()
1282cdf0e10cSrcweir {
1283cdf0e10cSrcweir 	if ( mpData->mbModified && mbPersistence )
1284cdf0e10cSrcweir 		ImplWriteConfig( mpData );
1285cdf0e10cSrcweir }
1286cdf0e10cSrcweir 
1287cdf0e10cSrcweir // -----------------------------------------------------------------------
1288cdf0e10cSrcweir 
SetLineEnd(LineEnd eLineEnd)1289cdf0e10cSrcweir void Config::SetLineEnd( LineEnd eLineEnd )
1290cdf0e10cSrcweir {
1291cdf0e10cSrcweir 	mpData->meLineEnd = eLineEnd;
1292cdf0e10cSrcweir }
1293cdf0e10cSrcweir 
1294cdf0e10cSrcweir // -----------------------------------------------------------------------
1295cdf0e10cSrcweir 
GetLineEnd() const1296cdf0e10cSrcweir LineEnd Config::GetLineEnd() const
1297cdf0e10cSrcweir {
1298cdf0e10cSrcweir 	return mpData->meLineEnd;
1299cdf0e10cSrcweir }
1300cdf0e10cSrcweir 
1301