xref: /aoo42x/main/svl/source/filerec/filerec.cxx (revision cdf0e10c)
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_svl.hxx"
30*cdf0e10cSrcweir #include <svl/filerec.hxx>
31*cdf0e10cSrcweir #include <osl/endian.h>
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir //========================================================================
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir SV_IMPL_VARARR( SfxUINT32s, sal_uInt32 );
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir //========================================================================
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir /*	Die folgenden Makros extrahieren Teilbereiche aus einem sal_uInt32 Wert.
40*cdf0e10cSrcweir 	Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
41*cdf0e10cSrcweir 	um Calls zu sparen.
42*cdf0e10cSrcweir */
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir #define SFX_REC_PRE(n) ( ((n) & 0x000000FF) )
45*cdf0e10cSrcweir #define SFX_REC_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
46*cdf0e10cSrcweir #define SFX_REC_TYP(n) ( ((n) & 0x000000FF) )
47*cdf0e10cSrcweir #define SFX_REC_VER(n) ( ((n) & 0x0000FF00) >> 8 )
48*cdf0e10cSrcweir #define SFX_REC_TAG(n) ( ((n) & 0xFFFF0000) >> 16 )
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir #define SFX_REC_CONTENT_VER(n) ( ((n) & 0x000000FF) )
51*cdf0e10cSrcweir #define SFX_REC_CONTENT_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir //-------------------------------------------------------------------------
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir /*	Die folgenden Makros setzen Teilbereiche zu einem sal_uInt32 Wert zusammen.
56*cdf0e10cSrcweir 	Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
57*cdf0e10cSrcweir 	um Calls zu sparen.
58*cdf0e10cSrcweir */
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir #define SFX_REC_MINI_HEADER(nPreTag,nStartPos,nEndPos) \
61*cdf0e10cSrcweir 					( sal_uInt32(nPreTag) | \
62*cdf0e10cSrcweir 					  sal_uInt32(nEndPos-nStartPos-SFX_REC_HEADERSIZE_MINI) << 8 )
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir #define SFX_REC_HEADER(nRecType,nContentTag,nContentVer) \
65*cdf0e10cSrcweir 					( sal_uInt32(nRecType) | \
66*cdf0e10cSrcweir 					  ( sal_uInt32(nContentVer) << 8 ) | \
67*cdf0e10cSrcweir 					  ( sal_uInt32(nContentTag) << 16 ) )
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir #define SFX_REC_CONTENT_HEADER(nContentVer,n1StStartPos,nCurStartPos) \
70*cdf0e10cSrcweir 					( sal_uInt32(nContentVer) | \
71*cdf0e10cSrcweir 					  sal_uInt32( nCurStartPos - n1StStartPos ) << 8 )
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir //=========================================================================
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir sal_uInt32 SfxMiniRecordWriter::Close
76*cdf0e10cSrcweir (
77*cdf0e10cSrcweir 	FASTBOOL	bSeekToEndOfRec 	/*	sal_True (default)
78*cdf0e10cSrcweir 										Der Stream wird an das Ende des Records
79*cdf0e10cSrcweir 										positioniert.
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir 										sal_False
82*cdf0e10cSrcweir 										Der Stream wird an den Anfang des
83*cdf0e10cSrcweir 										Contents (also hinter den Header)
84*cdf0e10cSrcweir 										positioniert.
85*cdf0e10cSrcweir 									*/
86*cdf0e10cSrcweir )
87*cdf0e10cSrcweir 
88*cdf0e10cSrcweir /*	[Beschreibung]
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir 	Diese Methode schlie\st den Record. Dabei wird haupts"achlich der
91*cdf0e10cSrcweir 	Header geschrieben.
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir 	Wurde der Header bereits geschrieben, hat der Aufruf keine Wirkung.
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir 	[R"uckgabewert]
97*cdf0e10cSrcweir 
98*cdf0e10cSrcweir 	sal_uInt32		!= 0
99*cdf0e10cSrcweir 				Position im Stream, die direkt hinter dem Record liegt.
100*cdf0e10cSrcweir 				'bSeekToEndOfRecord==sal_True'
101*cdf0e10cSrcweir 				=> R"uckgabewert == aktuelle Stream-Position nach Aufruf
102*cdf0e10cSrcweir 
103*cdf0e10cSrcweir 				== 0
104*cdf0e10cSrcweir 				Der Header war bereits geschrieben worden.
105*cdf0e10cSrcweir */
106*cdf0e10cSrcweir 
107*cdf0e10cSrcweir {
108*cdf0e10cSrcweir 	// wurde der Header noch nicht geschrieben?
109*cdf0e10cSrcweir 	if ( !_bHeaderOk )
110*cdf0e10cSrcweir 	{
111*cdf0e10cSrcweir 		// Header an den Anfang des Records schreiben
112*cdf0e10cSrcweir 		sal_uInt32 nEndPos = _pStream->Tell();
113*cdf0e10cSrcweir 		_pStream->Seek( _nStartPos );
114*cdf0e10cSrcweir 		*_pStream << SFX_REC_MINI_HEADER( _nPreTag, _nStartPos, nEndPos );
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir 		// je nachdem ans Ende des Records seeken oder hinter Header bleiben
117*cdf0e10cSrcweir 		if ( bSeekToEndOfRec )
118*cdf0e10cSrcweir 			_pStream->Seek( nEndPos );
119*cdf0e10cSrcweir 
120*cdf0e10cSrcweir 		// Header wurde JETZT geschrieben
121*cdf0e10cSrcweir 		_bHeaderOk = sal_True;
122*cdf0e10cSrcweir 		return nEndPos;
123*cdf0e10cSrcweir 	}
124*cdf0e10cSrcweir #ifdef DBG_UTIL
125*cdf0e10cSrcweir 	// mu\s Fix-Size-Record gepr"uft werden?
126*cdf0e10cSrcweir 	else if ( SFX_BOOL_DONTCARE == _bHeaderOk )
127*cdf0e10cSrcweir 	{
128*cdf0e10cSrcweir 		// Header auslesen, um Soll-Gr"o\se zu bestimmen
129*cdf0e10cSrcweir 		sal_uInt32 nEndPos = _pStream->Tell();
130*cdf0e10cSrcweir 		_pStream->Seek( _nStartPos );
131*cdf0e10cSrcweir 		sal_uInt32 nHeader;
132*cdf0e10cSrcweir 		*_pStream >> nHeader;
133*cdf0e10cSrcweir 		_pStream->Seek( nEndPos );
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir 		// Soll-Gr"o\se mit Ist-Gr"o\se vergleichen
136*cdf0e10cSrcweir 		DBG_ASSERT( nEndPos - SFX_REC_OFS(nHeader) == _nStartPos + sizeof(sal_uInt32),
137*cdf0e10cSrcweir 					"fixed record size incorrect" );
138*cdf0e10cSrcweir 		DbgOutf( "SfxFileRec: written record until %ul", nEndPos );
139*cdf0e10cSrcweir 	}
140*cdf0e10cSrcweir #endif
141*cdf0e10cSrcweir 
142*cdf0e10cSrcweir 	// Record war bereits geschlossen
143*cdf0e10cSrcweir 	return 0;
144*cdf0e10cSrcweir }
145*cdf0e10cSrcweir 
146*cdf0e10cSrcweir //=========================================================================
147*cdf0e10cSrcweir 
148*cdf0e10cSrcweir sal_uInt16 SfxMiniRecordReader::ScanRecordType
149*cdf0e10cSrcweir (
150*cdf0e10cSrcweir 	SvStream*	pStream 		/*	<SvStream> an dessen aktueller Position
151*cdf0e10cSrcweir 									ein Record liegt, dessen Typ erkannt werden
152*cdf0e10cSrcweir 									soll.
153*cdf0e10cSrcweir 								*/
154*cdf0e10cSrcweir )
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir /*	[Beschreibung]
157*cdf0e10cSrcweir 
158*cdf0e10cSrcweir 	Mit dieser statischen Methode kann ermittelt werden, ob sich an der
159*cdf0e10cSrcweir 	aktuellen Position in einem Stream ein Record befindet, und der Typ
160*cdf0e10cSrcweir 	des Records kann ermittelt werden.
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir 	Die Position im Stream ist nach dem Aufruf aufver"andert.
163*cdf0e10cSrcweir 
164*cdf0e10cSrcweir 
165*cdf0e10cSrcweir 	[Anmerkung]
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir 	Die Record-Typen k"onnen zwar (abgesehen vom Drawing-Enginge-Record)
168*cdf0e10cSrcweir 	untereinander eindeutig erkannt werden, es besteht jedoch die Gefahr
169*cdf0e10cSrcweir 	der Verwechslung von Records mit normalen Daten. File-Formate sollten
170*cdf0e10cSrcweir 	darauf R"ucksicht nehmen. Handelt es sich um keinen Record, wird
171*cdf0e10cSrcweir 	am wahrscheinlichsten SFX_REC_TYPE_MINI zur"uckgeliefert, da dieser
172*cdf0e10cSrcweir 	Typ sich aufgrund seines sparsam kurzen Headers durch die k"urzeste
173*cdf0e10cSrcweir 	Kennung auszeichnet.
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir 	[R"uckgabewert]
177*cdf0e10cSrcweir 
178*cdf0e10cSrcweir 	sal_uInt16							SFX_REC_TYPE_EOR
179*cdf0e10cSrcweir 									An der aktuellen Position des Streams
180*cdf0e10cSrcweir 									steht eine End-Of-Records-Kennung.
181*cdf0e10cSrcweir 
182*cdf0e10cSrcweir 									SFX_REC_TYPE_MINI
183*cdf0e10cSrcweir 									Es handelt sich um einen SW3 kompatiblen
184*cdf0e10cSrcweir 									Mini-Record, dessen einzige Kennung sein
185*cdf0e10cSrcweir 									'Mini-Tag' ist.
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir 									SFX_REC_TYPE_SINGLE
188*cdf0e10cSrcweir 									Es handelt sich um einen Extended-Record
189*cdf0e10cSrcweir 									mit einem einzigen Content, der durch eine
190*cdf0e10cSrcweir 									Version und ein Tag n"aher gekennzeichnet
191*cdf0e10cSrcweir 									ist.
192*cdf0e10cSrcweir 
193*cdf0e10cSrcweir 									SFX_REC_TYPE_FIXSIZE
194*cdf0e10cSrcweir 									Es handelt sich um einen Extended-Record
195*cdf0e10cSrcweir 									mit mehreren Contents gleicher Gr"o\se,
196*cdf0e10cSrcweir 									die gemeinsam durch eine einzige Version
197*cdf0e10cSrcweir 									und ein einziges gemeinsames Tag n"aher
198*cdf0e10cSrcweir 									gekennzeichnet sind.
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir 									SFX_REC_TYPE_VARSIZE
201*cdf0e10cSrcweir 									Es handelt sich um einen Extended-Record
202*cdf0e10cSrcweir 									mit mehreren Contents variabler Gr"o\se,
203*cdf0e10cSrcweir 									die gemeinsam durch eine einzige Version
204*cdf0e10cSrcweir 									und ein einziges gemeinsames Tag n"aher
205*cdf0e10cSrcweir 									gekennzeichnet sind.
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir 									SFX_REC_TYPE_MIXTAGS
208*cdf0e10cSrcweir 									Es handelt sich um einen Extended-Record
209*cdf0e10cSrcweir 									mit mehreren Contents variabler Gr"o\se,
210*cdf0e10cSrcweir 									die jeweils durch ein eignes Tag und
211*cdf0e10cSrcweir 									eine eigene Versions-Nummer n"aher
212*cdf0e10cSrcweir 									gekennzeichnet sind.
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir 									SFX_REC_TYPE_DRAWENG
215*cdf0e10cSrcweir 									Es handelt sich wahrscheinlich um einen
216*cdf0e10cSrcweir 									Drawing-Engine-Record. Dieser Record-Typ
217*cdf0e10cSrcweir 									kann von den Klassen dieser Gruppe nicht
218*cdf0e10cSrcweir 									interpretiert werden.
219*cdf0e10cSrcweir */
220*cdf0e10cSrcweir 
221*cdf0e10cSrcweir {
222*cdf0e10cSrcweir 	// die ersten 4 Bytes als Mini-Header lesen
223*cdf0e10cSrcweir 	sal_uInt32 nHeader;
224*cdf0e10cSrcweir 	*pStream >> nHeader;
225*cdf0e10cSrcweir 
226*cdf0e10cSrcweir 	// k"onnte es sich um einen extended-Record handeln?
227*cdf0e10cSrcweir 	sal_uInt16 nPreTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_PRE(nHeader));
228*cdf0e10cSrcweir 	if ( SFX_REC_PRETAG_EXT == nPreTag )
229*cdf0e10cSrcweir 	{
230*cdf0e10cSrcweir 		// die n"achsten 4 Bytes als extended-Header lesen
231*cdf0e10cSrcweir 		*pStream >> nHeader;
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir 		// Stream-Position restaurieren
234*cdf0e10cSrcweir 		pStream->SeekRel(-8);
235*cdf0e10cSrcweir 
236*cdf0e10cSrcweir 		// liegt eine g"ultige Record-Kennung vor?
237*cdf0e10cSrcweir 		sal_uInt16 nType = sal::static_int_cast< sal_uInt16 >(SFX_REC_TYP(nHeader));
238*cdf0e10cSrcweir 		if ( nType >= SFX_REC_TYPE_FIRST && nType <= SFX_REC_TYPE_LAST )
239*cdf0e10cSrcweir 			// entsprechenden extended-Record-Typ zur"uckliefern
240*cdf0e10cSrcweir 			return nType;
241*cdf0e10cSrcweir 
242*cdf0e10cSrcweir 		// sonst ist der Record-Typ unbekannt
243*cdf0e10cSrcweir 		return SFX_REC_TYPE_NONE;
244*cdf0e10cSrcweir 	}
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir 	// Stream-Position restaurieren
247*cdf0e10cSrcweir 	pStream->SeekRel(-4);
248*cdf0e10cSrcweir 
249*cdf0e10cSrcweir 	// liegt eine End-Of-Record-Kennung vor?
250*cdf0e10cSrcweir 	if ( SFX_REC_PRETAG_EOR == nPreTag )
251*cdf0e10cSrcweir 		return nPreTag;
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir 	// liegt ein Drawin-Engine-Record vor?
254*cdf0e10cSrcweir 	if ( nHeader == sal_uInt32(*"DRMD") || nHeader == sal_uInt32(*"DRVW") )
255*cdf0e10cSrcweir 		return SFX_REC_TYPE_DRAWENG;
256*cdf0e10cSrcweir 
257*cdf0e10cSrcweir 	// alle anderen sind grunds"atzlich g"ultige Mini-Records
258*cdf0e10cSrcweir 	return SFX_REC_TYPE_MINI;
259*cdf0e10cSrcweir }
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir //-------------------------------------------------------------------------
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir FASTBOOL SfxMiniRecordReader::SetHeader_Impl( sal_uInt32 nHeader )
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir /*	[Beschreibung]
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir 	Interne Methode zum nachtr"aglichen Verarbeiten eines extern gelesenen
268*cdf0e10cSrcweir 	Headers. Falls der Header eine End-Of-Records-Kennung darstellt,
269*cdf0e10cSrcweir 	wird am Stream ein Errorcode gesetzt und sal_False zur"uckgeliefert. Im
270*cdf0e10cSrcweir 	Fehlerfall wird der Stream jedoch nicht auf den Record-Anfang zur"uck-
271*cdf0e10cSrcweir 	gesetzt.
272*cdf0e10cSrcweir */
273*cdf0e10cSrcweir 
274*cdf0e10cSrcweir {
275*cdf0e10cSrcweir 	FASTBOOL bRet = sal_True;
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir 	// Record-Ende und Pre-Tag aus dem Header ermitteln
278*cdf0e10cSrcweir 	_nEofRec = _pStream->Tell() + SFX_REC_OFS(nHeader);
279*cdf0e10cSrcweir 	_nPreTag = sal::static_int_cast< sal_uInt8 >(SFX_REC_PRE(nHeader));
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir 	// wenn End-Of-Record-Kennung, dann Fehler
282*cdf0e10cSrcweir 	if ( _nPreTag == SFX_REC_PRETAG_EOR )
283*cdf0e10cSrcweir 	{
284*cdf0e10cSrcweir 		_pStream->SetError( ERRCODE_IO_WRONGFORMAT );
285*cdf0e10cSrcweir 		bRet = sal_False;
286*cdf0e10cSrcweir 	}
287*cdf0e10cSrcweir 	return bRet;
288*cdf0e10cSrcweir }
289*cdf0e10cSrcweir 
290*cdf0e10cSrcweir //-------------------------------------------------------------------------
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir SfxMiniRecordReader::SfxMiniRecordReader
293*cdf0e10cSrcweir (
294*cdf0e10cSrcweir 	SvStream*		pStream 		/*	<SvStream>, an dessen aktueller
295*cdf0e10cSrcweir 										Position sich ein <SfxMiniRecord>
296*cdf0e10cSrcweir 										befindet.
297*cdf0e10cSrcweir 									*/
298*cdf0e10cSrcweir )
299*cdf0e10cSrcweir 
300*cdf0e10cSrcweir /*	[Beschreibung]
301*cdf0e10cSrcweir 
302*cdf0e10cSrcweir 	Dieser Ctor liest den Header eines <SfxMiniRecord> ab der aktuellen
303*cdf0e10cSrcweir 	Position von 'pStream'. Da grunds"atzlich fast 4-Byte Kombination ein
304*cdf0e10cSrcweir 	g"ultiger SfxMiniRecord-Header ist, bleiben die einzig m"oglichen
305*cdf0e10cSrcweir 	Fehler der EOF-Status des Streams, und ein SFX_REC_PRETAG_EOR
306*cdf0e10cSrcweir 	als Pre-Tag. Ein entsprechender Error-Code (ERRCODE_IO_EOF bzw.
307*cdf0e10cSrcweir 	ERRCODE_IO_WRONGFORMAT) ist dann am Stream gesetzt, dessen Position
308*cdf0e10cSrcweir 	dann au\serdem unver"andert ist.
309*cdf0e10cSrcweir */
310*cdf0e10cSrcweir 
311*cdf0e10cSrcweir :	_pStream( pStream ),
312*cdf0e10cSrcweir 	_bSkipped( sal_False )
313*cdf0e10cSrcweir {
314*cdf0e10cSrcweir 	// Header einlesen
315*cdf0e10cSrcweir 	sal_uInt32 nStartPos = pStream->Tell(); // um im Fehlerfall zur"uck zu-seeken
316*cdf0e10cSrcweir 	DBG( DbgOutf( "SfxFileRec: reading record at %ul", nStartPos ) );
317*cdf0e10cSrcweir 	sal_uInt32 nHeader;
318*cdf0e10cSrcweir 	*pStream >> nHeader;
319*cdf0e10cSrcweir 
320*cdf0e10cSrcweir 	// Headerdaten extrahieren
321*cdf0e10cSrcweir 	SetHeader_Impl( nHeader );
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir 	// Fehlerbehandlung
324*cdf0e10cSrcweir 	if ( pStream->IsEof() )
325*cdf0e10cSrcweir 		_nPreTag = SFX_REC_PRETAG_EOR;
326*cdf0e10cSrcweir 	else if ( _nPreTag == SFX_REC_PRETAG_EOR )
327*cdf0e10cSrcweir 		pStream->SetError( ERRCODE_IO_WRONGFORMAT );
328*cdf0e10cSrcweir 	if ( !IsValid() )
329*cdf0e10cSrcweir 		pStream->Seek( nStartPos );
330*cdf0e10cSrcweir }
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir //-------------------------------------------------------------------------
333*cdf0e10cSrcweir 
334*cdf0e10cSrcweir SfxMiniRecordReader::SfxMiniRecordReader
335*cdf0e10cSrcweir (
336*cdf0e10cSrcweir 	SvStream*		pStream,		/*	<SvStream>, an dessen aktueller
337*cdf0e10cSrcweir 										Position sich ein <SfxMiniRecord>
338*cdf0e10cSrcweir 										befindet.
339*cdf0e10cSrcweir 									*/
340*cdf0e10cSrcweir 	sal_uInt8			nTag			//	Pre-Tag des gew"unschten Records
341*cdf0e10cSrcweir )
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir /*	[Beschreibung]
344*cdf0e10cSrcweir 
345*cdf0e10cSrcweir 	Dieser Ctor interpretiert 'pStream' ab der aktuellen Position als
346*cdf0e10cSrcweir 	eine l"uckenlose Folge von, von dieser Klassen-Gruppe interpretierbaren,
347*cdf0e10cSrcweir 	Records. Der in dieser Folge erste als <SfxMiniRecord> interpretierbare
348*cdf0e10cSrcweir 	(also ggf. auch ein extended-Record) mit dem PreTag 'nTag' wird ge"offnet
349*cdf0e10cSrcweir 	und durch diese Instanz repr"asentiert.
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir 	Wird das Ende des Streams oder die Kennung SFX_REC_PRETAG_EOR
352*cdf0e10cSrcweir 	erreicht, bevor ein Record mit dem ge"unschten Pre-Tag gefunden wird,
353*cdf0e10cSrcweir 	ist die erzeugte Instanz ung"ultig ('IsValid() == sal_False'). Ein ent-
354*cdf0e10cSrcweir 	sprechender Error-Code (ERRCODE_IO_EOF bzw. ERRCODE_IO_WRONGFORMAT)
355*cdf0e10cSrcweir 	ist dann am Stream gesetzt, dessen Position ist dann au\serdem unver-
356*cdf0e10cSrcweir 	"andert.
357*cdf0e10cSrcweir 
358*cdf0e10cSrcweir 	Bei 'nTag==SFX_FILEREC_PRETAG_EOR' wird nicht versucht, einen Record
359*cdf0e10cSrcweir 	zu lesen, es wird sofort 'IsValid()' auf sal_False gesetzt und kein Error-Code
360*cdf0e10cSrcweir 	am Stream gesetzt. Dies ist dauzu gedacht, ohne 'new' und 'delete'
361*cdf0e10cSrcweir 	abw"rtskompatibel SfxMiniRecords einbauen zu k"onnen. Siehe dazu
362*cdf0e10cSrcweir 	<SfxItemSet::Load()>.
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir 	[Anwendungsvorschlag]
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir 	Wird dieser Ctor in einer bereits ausgelieferten Programmversion
368*cdf0e10cSrcweir 	verwendet, k"onnen in das File-Format jeweils davor kompatibel neue
369*cdf0e10cSrcweir 	Records mit einer anderen Kennung eingef"ugt werden. Diese werden
370*cdf0e10cSrcweir 	schlie\slich automatisch "uberlesen. Erkauft wird diese M"oglichkeit
371*cdf0e10cSrcweir 	allerdings mit etwas schlechterem Laufzeitverhalten im Vergleich mit
372*cdf0e10cSrcweir 	direktem 'drauf-los-lesen', der sich jedoch auf einen Vergleich zweier
373*cdf0e10cSrcweir 	Bytes reduziert, falls der gesuchte Record der erste in der Folge ist.
374*cdf0e10cSrcweir */
375*cdf0e10cSrcweir 
376*cdf0e10cSrcweir :   _pStream( pStream ),
377*cdf0e10cSrcweir 	_bSkipped( nTag == SFX_REC_PRETAG_EOR )
378*cdf0e10cSrcweir {
379*cdf0e10cSrcweir 	// ggf. ignorieren (s.o.)
380*cdf0e10cSrcweir 	if ( _bSkipped )
381*cdf0e10cSrcweir 	{
382*cdf0e10cSrcweir 		_nPreTag = nTag;
383*cdf0e10cSrcweir 		return;
384*cdf0e10cSrcweir 	}
385*cdf0e10cSrcweir 
386*cdf0e10cSrcweir 	// StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
387*cdf0e10cSrcweir 	sal_uInt32 nStartPos = pStream->Tell();
388*cdf0e10cSrcweir 
389*cdf0e10cSrcweir 	// passenden Record suchen
390*cdf0e10cSrcweir 	while(sal_True)
391*cdf0e10cSrcweir 	{
392*cdf0e10cSrcweir 		// Header lesen
393*cdf0e10cSrcweir 		DBG( DbgOutf( "SfxFileRec: searching record at %ul", pStream->Tell() ) );
394*cdf0e10cSrcweir 		sal_uInt32 nHeader;
395*cdf0e10cSrcweir 		*pStream >> nHeader;
396*cdf0e10cSrcweir 
397*cdf0e10cSrcweir 		// Headerdaten von Basisklasse extrahieren lassen
398*cdf0e10cSrcweir 		SetHeader_Impl( nHeader );
399*cdf0e10cSrcweir 
400*cdf0e10cSrcweir 		// ggf. Fehler behandeln
401*cdf0e10cSrcweir 		if ( pStream->IsEof() )
402*cdf0e10cSrcweir 			_nPreTag = SFX_REC_PRETAG_EOR;
403*cdf0e10cSrcweir 		else if ( _nPreTag == SFX_REC_PRETAG_EOR )
404*cdf0e10cSrcweir 			pStream->SetError( ERRCODE_IO_WRONGFORMAT );
405*cdf0e10cSrcweir 		else
406*cdf0e10cSrcweir 		{
407*cdf0e10cSrcweir 			// wenn gefunden, dann Schleife abbrechen
408*cdf0e10cSrcweir 			if ( _nPreTag == nTag )
409*cdf0e10cSrcweir 				break;
410*cdf0e10cSrcweir 
411*cdf0e10cSrcweir 			// sonst skippen und weitersuchen
412*cdf0e10cSrcweir 			pStream->Seek( _nEofRec );
413*cdf0e10cSrcweir 			continue;
414*cdf0e10cSrcweir 		}
415*cdf0e10cSrcweir 
416*cdf0e10cSrcweir 		// Fehler => zur"uck-seeken
417*cdf0e10cSrcweir 		pStream->Seek( nStartPos );
418*cdf0e10cSrcweir 		break;
419*cdf0e10cSrcweir 	}
420*cdf0e10cSrcweir }
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir //=========================================================================
423*cdf0e10cSrcweir 
424*cdf0e10cSrcweir SfxSingleRecordWriter::SfxSingleRecordWriter
425*cdf0e10cSrcweir (
426*cdf0e10cSrcweir 	sal_uInt8			nRecordType,	// f"ur Subklassen
427*cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
428*cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Inhalts-Art-Kennung
429*cdf0e10cSrcweir 	sal_uInt8			nContentVer 	// Inhalts-Versions-Kennung
430*cdf0e10cSrcweir )
431*cdf0e10cSrcweir 
432*cdf0e10cSrcweir /*	[Beschreibung]
433*cdf0e10cSrcweir 
434*cdf0e10cSrcweir 	Interner Ctor f"ur Subklassen.
435*cdf0e10cSrcweir */
436*cdf0e10cSrcweir 
437*cdf0e10cSrcweir :	SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT )
438*cdf0e10cSrcweir {
439*cdf0e10cSrcweir 	// Erweiterten Header hiner den des SfxMiniRec schreiben
440*cdf0e10cSrcweir 	*pStream << SFX_REC_HEADER(nRecordType, nContentTag, nContentVer);
441*cdf0e10cSrcweir }
442*cdf0e10cSrcweir 
443*cdf0e10cSrcweir //-------------------------------------------------------------------------
444*cdf0e10cSrcweir 
445*cdf0e10cSrcweir SfxSingleRecordWriter::SfxSingleRecordWriter
446*cdf0e10cSrcweir (
447*cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
448*cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Inhalts-Art-Kennung
449*cdf0e10cSrcweir 	sal_uInt8			nContentVer 	// Inhalts-Versions-Kennung
450*cdf0e10cSrcweir )
451*cdf0e10cSrcweir 
452*cdf0e10cSrcweir /*	[Beschreibung]
453*cdf0e10cSrcweir 
454*cdf0e10cSrcweir 	Legt in 'pStream' einen 'SfxSingleRecord' an, dessen Content-Gr"o\se
455*cdf0e10cSrcweir 	nicht bekannt ist, sondern nach dam Streamen des Contents errechnet
456*cdf0e10cSrcweir 	werden soll.
457*cdf0e10cSrcweir */
458*cdf0e10cSrcweir 
459*cdf0e10cSrcweir :	SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT )
460*cdf0e10cSrcweir {
461*cdf0e10cSrcweir 	// Erweiterten Header hiner den des SfxMiniRec schreiben
462*cdf0e10cSrcweir 	*pStream << SFX_REC_HEADER( SFX_REC_TYPE_SINGLE, nContentTag, nContentVer);
463*cdf0e10cSrcweir }
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir //-------------------------------------------------------------------------
466*cdf0e10cSrcweir 
467*cdf0e10cSrcweir SfxSingleRecordWriter::SfxSingleRecordWriter
468*cdf0e10cSrcweir (
469*cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
470*cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Inhalts-Art-Kennung
471*cdf0e10cSrcweir 	sal_uInt8			nContentVer,	// Inhalts-Versions-Kennung
472*cdf0e10cSrcweir 	sal_uInt32			nContentSize	// Gr"o\se des Inhalts in Bytes
473*cdf0e10cSrcweir )
474*cdf0e10cSrcweir 
475*cdf0e10cSrcweir /*  [Beschreibung]
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir 	Legt in 'pStream' einen 'SfxSingleRecord' an, dessen Content-Gr"o\se
478*cdf0e10cSrcweir 	von vornherein bekannt ist.
479*cdf0e10cSrcweir */
480*cdf0e10cSrcweir 
481*cdf0e10cSrcweir :	SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT,
482*cdf0e10cSrcweir 						 nContentSize + SFX_REC_HEADERSIZE_SINGLE )
483*cdf0e10cSrcweir {
484*cdf0e10cSrcweir 	// Erweiterten Header hinter den des SfxMiniRec schreiben
485*cdf0e10cSrcweir 	*pStream << SFX_REC_HEADER( SFX_REC_TYPE_SINGLE, nContentTag, nContentVer);
486*cdf0e10cSrcweir }
487*cdf0e10cSrcweir 
488*cdf0e10cSrcweir //=========================================================================
489*cdf0e10cSrcweir 
490*cdf0e10cSrcweir inline FASTBOOL SfxSingleRecordReader::ReadHeader_Impl( sal_uInt16 nTypes )
491*cdf0e10cSrcweir 
492*cdf0e10cSrcweir /*  [Beschreibung]
493*cdf0e10cSrcweir 
494*cdf0e10cSrcweir 	Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
495*cdf0e10cSrcweir 	die Basisklasse bereits initialisiert und deren Header gelesen ist.
496*cdf0e10cSrcweir 	Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
497*cdf0e10cSrcweir 	nicht zur"uckge-seekt.
498*cdf0e10cSrcweir */
499*cdf0e10cSrcweir 
500*cdf0e10cSrcweir {
501*cdf0e10cSrcweir 	FASTBOOL bRet;
502*cdf0e10cSrcweir 
503*cdf0e10cSrcweir 	// Basisklassen-Header einlesen
504*cdf0e10cSrcweir 	sal_uInt32 nHeader=0;
505*cdf0e10cSrcweir 	*_pStream >> nHeader;
506*cdf0e10cSrcweir 	if ( !SetHeader_Impl( nHeader ) )
507*cdf0e10cSrcweir 		bRet = sal_False;
508*cdf0e10cSrcweir 	else
509*cdf0e10cSrcweir 	{
510*cdf0e10cSrcweir 		// eigenen Header einlesen
511*cdf0e10cSrcweir 		*_pStream >> nHeader;
512*cdf0e10cSrcweir 		_nRecordVer = sal::static_int_cast< sal_uInt8 >(SFX_REC_VER(nHeader));
513*cdf0e10cSrcweir 		_nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
514*cdf0e10cSrcweir 
515*cdf0e10cSrcweir 		// falscher Record-Typ?
516*cdf0e10cSrcweir 		_nRecordType = sal::static_int_cast< sal_uInt8 >(SFX_REC_TYP(nHeader));
517*cdf0e10cSrcweir 		bRet = 0 != ( nTypes & _nRecordType);
518*cdf0e10cSrcweir 	}
519*cdf0e10cSrcweir 	return bRet;
520*cdf0e10cSrcweir }
521*cdf0e10cSrcweir 
522*cdf0e10cSrcweir //-------------------------------------------------------------------------
523*cdf0e10cSrcweir 
524*cdf0e10cSrcweir SfxSingleRecordReader::SfxSingleRecordReader( SvStream *pStream )
525*cdf0e10cSrcweir :	SfxMiniRecordReader()
526*cdf0e10cSrcweir {
527*cdf0e10cSrcweir 	// Startposition merken, um im Fehlerfall zur"uck-seeken zu k"onnen
528*cdf0e10cSrcweir     #ifdef DBG_UTIL
529*cdf0e10cSrcweir 	sal_uInt32 nStartPos = pStream->Tell();
530*cdf0e10cSrcweir 	DBG( DbgOutf( "SfxFileRec: reading record at %ul", nStartPos ) );
531*cdf0e10cSrcweir     #endif
532*cdf0e10cSrcweir 
533*cdf0e10cSrcweir 	// Basisklasse initialisieren (nicht via Ctor, da der nur MiniRecs akzept.)
534*cdf0e10cSrcweir 	Construct_Impl( pStream );
535*cdf0e10cSrcweir 
536*cdf0e10cSrcweir 	// nur Header mit korrektem Record-Type akzeptieren
537*cdf0e10cSrcweir 	if ( !ReadHeader_Impl( SFX_REC_TYPE_SINGLE ) )
538*cdf0e10cSrcweir 	{
539*cdf0e10cSrcweir 		// Error-Code setzen und zur"uck-seeken
540*cdf0e10cSrcweir 		pStream->SeekRel( - SFX_REC_HEADERSIZE_SINGLE );
541*cdf0e10cSrcweir 		pStream->SetError( ERRCODE_IO_WRONGFORMAT );
542*cdf0e10cSrcweir 	}
543*cdf0e10cSrcweir }
544*cdf0e10cSrcweir 
545*cdf0e10cSrcweir //-------------------------------------------------------------------------
546*cdf0e10cSrcweir 
547*cdf0e10cSrcweir SfxSingleRecordReader::SfxSingleRecordReader( SvStream *pStream, sal_uInt16 nTag )
548*cdf0e10cSrcweir {
549*cdf0e10cSrcweir 	// StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
550*cdf0e10cSrcweir 	sal_uInt32 nStartPos = pStream->Tell();
551*cdf0e10cSrcweir 
552*cdf0e10cSrcweir 	// richtigen Record suchen, ggf. Error-Code setzen und zur"uck-seeken
553*cdf0e10cSrcweir 	Construct_Impl( pStream );
554*cdf0e10cSrcweir 	if ( !FindHeader_Impl( SFX_REC_TYPE_SINGLE, nTag ) )
555*cdf0e10cSrcweir 	{
556*cdf0e10cSrcweir 		// Error-Code setzen und zur"uck-seeken
557*cdf0e10cSrcweir 		pStream->Seek( nStartPos );
558*cdf0e10cSrcweir 		pStream->SetError( ERRCODE_IO_WRONGFORMAT );
559*cdf0e10cSrcweir 	}
560*cdf0e10cSrcweir }
561*cdf0e10cSrcweir 
562*cdf0e10cSrcweir //-------------------------------------------------------------------------
563*cdf0e10cSrcweir 
564*cdf0e10cSrcweir FASTBOOL SfxSingleRecordReader::FindHeader_Impl
565*cdf0e10cSrcweir (
566*cdf0e10cSrcweir 	sal_uInt16		nTypes, 	// arithm. Veroderung erlaubter Record-Typen
567*cdf0e10cSrcweir 	sal_uInt16		nTag		// zu findende Record-Art-Kennung
568*cdf0e10cSrcweir )
569*cdf0e10cSrcweir 
570*cdf0e10cSrcweir /*	[Beschreibung]
571*cdf0e10cSrcweir 
572*cdf0e10cSrcweir 	Interne Methode zum lesen des Headers des ersten Record, der einem
573*cdf0e10cSrcweir 	der Typen in 'nTypes' entspricht und mit der Art-Kennung 'nTag'
574*cdf0e10cSrcweir 	gekennzeichnet ist.
575*cdf0e10cSrcweir 
576*cdf0e10cSrcweir 	Kann ein solcher Record nicht gefunden werden, wird am Stream ein
577*cdf0e10cSrcweir 	Errorcode gesetzt, zur"uck-geseekt und sal_False zur"uckgeliefert.
578*cdf0e10cSrcweir */
579*cdf0e10cSrcweir 
580*cdf0e10cSrcweir {
581*cdf0e10cSrcweir 	// StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
582*cdf0e10cSrcweir 	sal_uInt32 nStartPos = _pStream->Tell();
583*cdf0e10cSrcweir 
584*cdf0e10cSrcweir 	// richtigen Record suchen
585*cdf0e10cSrcweir 	while ( !_pStream->IsEof() )
586*cdf0e10cSrcweir 	{
587*cdf0e10cSrcweir 		// Header lesen
588*cdf0e10cSrcweir 		sal_uInt32 nHeader;
589*cdf0e10cSrcweir 		DBG( DbgOutf( "SfxFileRec: searching record at %ul", _pStream->Tell() ) );
590*cdf0e10cSrcweir 		*_pStream >> nHeader;
591*cdf0e10cSrcweir 		if ( !SetHeader_Impl( nHeader ) )
592*cdf0e10cSrcweir 			// EOR => Such-Schleife abbreichen
593*cdf0e10cSrcweir 			break;
594*cdf0e10cSrcweir 
595*cdf0e10cSrcweir 		// Extended Record gefunden?
596*cdf0e10cSrcweir 		if ( _nPreTag == SFX_REC_PRETAG_EXT )
597*cdf0e10cSrcweir 		{
598*cdf0e10cSrcweir 			// Extended Header lesen
599*cdf0e10cSrcweir 			*_pStream >> nHeader;
600*cdf0e10cSrcweir 			_nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
601*cdf0e10cSrcweir 
602*cdf0e10cSrcweir 			// richtigen Record gefunden?
603*cdf0e10cSrcweir 			if ( _nRecordTag == nTag )
604*cdf0e10cSrcweir 			{
605*cdf0e10cSrcweir 				// gefundener Record-Typ passend?
606*cdf0e10cSrcweir 				_nRecordType = sal::static_int_cast< sal_uInt8 >(
607*cdf0e10cSrcweir                     SFX_REC_TYP(nHeader));
608*cdf0e10cSrcweir 				if ( nTypes & _nRecordType )
609*cdf0e10cSrcweir 					// ==> gefunden
610*cdf0e10cSrcweir 					return sal_True;
611*cdf0e10cSrcweir 
612*cdf0e10cSrcweir 				// error => Such-Schleife abbrechen
613*cdf0e10cSrcweir 				break;
614*cdf0e10cSrcweir 			}
615*cdf0e10cSrcweir 		}
616*cdf0e10cSrcweir 
617*cdf0e10cSrcweir 		// sonst skippen
618*cdf0e10cSrcweir 		if ( !_pStream->IsEof() )
619*cdf0e10cSrcweir 			_pStream->Seek( _nEofRec );
620*cdf0e10cSrcweir 	}
621*cdf0e10cSrcweir 
622*cdf0e10cSrcweir 	// Fehler setzen und zur"uck-seeken
623*cdf0e10cSrcweir 	_pStream->SetError( ERRCODE_IO_WRONGFORMAT );
624*cdf0e10cSrcweir 	_pStream->Seek( nStartPos );
625*cdf0e10cSrcweir 	return sal_False;
626*cdf0e10cSrcweir }
627*cdf0e10cSrcweir 
628*cdf0e10cSrcweir //=========================================================================
629*cdf0e10cSrcweir 
630*cdf0e10cSrcweir SfxMultiFixRecordWriter::SfxMultiFixRecordWriter
631*cdf0e10cSrcweir (
632*cdf0e10cSrcweir 	sal_uInt8			nRecordType,	// Subklassen Record-Kennung
633*cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
634*cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Content-Art-Kennung
635*cdf0e10cSrcweir 	sal_uInt8			nContentVer,	// Content-Versions-Kennung
636*cdf0e10cSrcweir 	sal_uInt32			              	// Gr"o\se jedes einzelnen Contents in Bytes
637*cdf0e10cSrcweir )
638*cdf0e10cSrcweir 
639*cdf0e10cSrcweir /*  [Beschreibung]
640*cdf0e10cSrcweir 
641*cdf0e10cSrcweir 	Interne Methode f"ur Subklassen.
642*cdf0e10cSrcweir */
643*cdf0e10cSrcweir 
644*cdf0e10cSrcweir :   SfxSingleRecordWriter( nRecordType, pStream, nContentTag, nContentVer ),
645*cdf0e10cSrcweir 	_nContentCount( 0 )
646*cdf0e10cSrcweir {
647*cdf0e10cSrcweir 	// Platz f"ur eigenen Header
648*cdf0e10cSrcweir 	pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI );
649*cdf0e10cSrcweir }
650*cdf0e10cSrcweir 
651*cdf0e10cSrcweir //------------------------------------------------------------------------
652*cdf0e10cSrcweir 
653*cdf0e10cSrcweir SfxMultiFixRecordWriter::SfxMultiFixRecordWriter
654*cdf0e10cSrcweir (
655*cdf0e10cSrcweir 	SvStream*		pStream,		// Stream, in dem der Record angelegt wird
656*cdf0e10cSrcweir 	sal_uInt16			nContentTag,	// Content-Art-Kennung
657*cdf0e10cSrcweir 	sal_uInt8			nContentVer,	// Content-Versions-Kennung
658*cdf0e10cSrcweir 	sal_uInt32			             	// Gr"o\se jedes einzelnen Contents in Bytes
659*cdf0e10cSrcweir )
660*cdf0e10cSrcweir 
661*cdf0e10cSrcweir /*  [Beschreibung]
662*cdf0e10cSrcweir 
663*cdf0e10cSrcweir 	Legt in 'pStream' einen 'SfxMultiFixRecord' an, dessen Content-Gr"o\se
664*cdf0e10cSrcweir 	konstant und von vornherein bekannt ist.
665*cdf0e10cSrcweir */
666*cdf0e10cSrcweir 
667*cdf0e10cSrcweir :   SfxSingleRecordWriter( SFX_REC_TYPE_FIXSIZE,
668*cdf0e10cSrcweir 						   pStream, nContentTag, nContentVer ),
669*cdf0e10cSrcweir 	_nContentCount( 0 )
670*cdf0e10cSrcweir {
671*cdf0e10cSrcweir 	// Platz f"ur eigenen Header
672*cdf0e10cSrcweir 	pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI );
673*cdf0e10cSrcweir }
674*cdf0e10cSrcweir 
675*cdf0e10cSrcweir //------------------------------------------------------------------------
676*cdf0e10cSrcweir 
677*cdf0e10cSrcweir sal_uInt32 SfxMultiFixRecordWriter::Close( FASTBOOL bSeekToEndOfRec )
678*cdf0e10cSrcweir 
679*cdf0e10cSrcweir //	siehe <SfxMiniRecordWriter>
680*cdf0e10cSrcweir 
681*cdf0e10cSrcweir {
682*cdf0e10cSrcweir 	// Header noch nicht geschrieben?
683*cdf0e10cSrcweir 	if ( !_bHeaderOk )
684*cdf0e10cSrcweir 	{
685*cdf0e10cSrcweir 		// Position hinter Record merken, um sie restaurieren zu k"onnen
686*cdf0e10cSrcweir 		sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( sal_False );
687*cdf0e10cSrcweir 
688*cdf0e10cSrcweir 		// gegen"uber SfxSingleRecord erweiterten Header schreiben
689*cdf0e10cSrcweir 		*_pStream << _nContentCount;
690*cdf0e10cSrcweir 		*_pStream << _nContentSize;
691*cdf0e10cSrcweir 
692*cdf0e10cSrcweir 		// je nachdem ans Ende des Records seeken oder hinter Header bleiben
693*cdf0e10cSrcweir 		if ( bSeekToEndOfRec )
694*cdf0e10cSrcweir 			_pStream->Seek(nEndPos);
695*cdf0e10cSrcweir 		return nEndPos;
696*cdf0e10cSrcweir 	}
697*cdf0e10cSrcweir 
698*cdf0e10cSrcweir 	// Record war bereits geschlossen
699*cdf0e10cSrcweir 	return 0;
700*cdf0e10cSrcweir }
701*cdf0e10cSrcweir 
702*cdf0e10cSrcweir //=========================================================================
703*cdf0e10cSrcweir 
704*cdf0e10cSrcweir SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
705*cdf0e10cSrcweir (
706*cdf0e10cSrcweir 	sal_uInt8			nRecordType,	// Record-Kennung der Subklasse
707*cdf0e10cSrcweir 	SvStream*       pStream,        // Stream, in dem der Record angelegt wird
708*cdf0e10cSrcweir 	sal_uInt16			nRecordTag, 	// Gesamt-Art-Kennung
709*cdf0e10cSrcweir 	sal_uInt8			nRecordVer		// Gesamt-Versions-Kennung
710*cdf0e10cSrcweir )
711*cdf0e10cSrcweir 
712*cdf0e10cSrcweir /*  [Beschreibung]
713*cdf0e10cSrcweir 
714*cdf0e10cSrcweir 	Interner Ctor f"ur Subklassen.
715*cdf0e10cSrcweir */
716*cdf0e10cSrcweir 
717*cdf0e10cSrcweir :   SfxMultiFixRecordWriter( nRecordType, pStream, nRecordTag, nRecordVer, 0 ),
718*cdf0e10cSrcweir 	_nContentVer( 0 )
719*cdf0e10cSrcweir {
720*cdf0e10cSrcweir }
721*cdf0e10cSrcweir 
722*cdf0e10cSrcweir //-------------------------------------------------------------------------
723*cdf0e10cSrcweir 
724*cdf0e10cSrcweir SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
725*cdf0e10cSrcweir (
726*cdf0e10cSrcweir 	SvStream*       pStream,        // Stream, in dem der Record angelegt wird
727*cdf0e10cSrcweir 	sal_uInt16			nRecordTag, 	// Gesamt-Art-Kennung
728*cdf0e10cSrcweir 	sal_uInt8			nRecordVer		// Gesamt-Versions-Kennung
729*cdf0e10cSrcweir )
730*cdf0e10cSrcweir 
731*cdf0e10cSrcweir /*  [Beschreibung]
732*cdf0e10cSrcweir 
733*cdf0e10cSrcweir 	Legt in 'pStream' einen 'SfxMultiVarRecord' an, dessen Content-Gr"o\sen
734*cdf0e10cSrcweir 	weder bekannt sind noch identisch sein m"ussen, sondern jeweils nach dem
735*cdf0e10cSrcweir 	Streamen jedes einzelnen Contents errechnet werden sollen.
736*cdf0e10cSrcweir 
737*cdf0e10cSrcweir 
738*cdf0e10cSrcweir 	[Anmerkung]
739*cdf0e10cSrcweir 
740*cdf0e10cSrcweir 	Diese Methode ist nicht inline, da f"ur die Initialisierung eines
741*cdf0e10cSrcweir 	<SvULongs>-Members zu viel Code generiert werden w"urde.
742*cdf0e10cSrcweir */
743*cdf0e10cSrcweir 
744*cdf0e10cSrcweir :   SfxMultiFixRecordWriter( SFX_REC_TYPE_VARSIZE,
745*cdf0e10cSrcweir 							 pStream, nRecordTag, nRecordVer, 0 ),
746*cdf0e10cSrcweir 	_nContentVer( 0 )
747*cdf0e10cSrcweir {
748*cdf0e10cSrcweir }
749*cdf0e10cSrcweir 
750*cdf0e10cSrcweir //-------------------------------------------------------------------------
751*cdf0e10cSrcweir 
752*cdf0e10cSrcweir SfxMultiVarRecordWriter::~SfxMultiVarRecordWriter()
753*cdf0e10cSrcweir 
754*cdf0e10cSrcweir /*	[Beschreibung]
755*cdf0e10cSrcweir 
756*cdf0e10cSrcweir 	Der Dtor der Klasse <SfxMultiVarRecordWriter> schlie\st den Record
757*cdf0e10cSrcweir 	automatisch, falls <SfxMultiVarRecordWriter::Close()> nicht bereits
758*cdf0e10cSrcweir 	explizit gerufen wurde.
759*cdf0e10cSrcweir */
760*cdf0e10cSrcweir 
761*cdf0e10cSrcweir {
762*cdf0e10cSrcweir 	// wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden
763*cdf0e10cSrcweir 	if ( !_bHeaderOk )
764*cdf0e10cSrcweir 		Close();
765*cdf0e10cSrcweir }
766*cdf0e10cSrcweir 
767*cdf0e10cSrcweir //-------------------------------------------------------------------------
768*cdf0e10cSrcweir 
769*cdf0e10cSrcweir void SfxMultiVarRecordWriter::FlushContent_Impl()
770*cdf0e10cSrcweir 
771*cdf0e10cSrcweir /*	[Beschreibung]
772*cdf0e10cSrcweir 
773*cdf0e10cSrcweir 	Interne Methode zum Abschlie\sen eines einzelnen Contents.
774*cdf0e10cSrcweir */
775*cdf0e10cSrcweir 
776*cdf0e10cSrcweir {
777*cdf0e10cSrcweir 	// Versions-Kennung und Positions-Offset des aktuellen Contents merken;
778*cdf0e10cSrcweir 	// das Positions-Offset ist relativ zur Startposition des ersten Contents
779*cdf0e10cSrcweir 	_aContentOfs.Insert(
780*cdf0e10cSrcweir 			SFX_REC_CONTENT_HEADER(_nContentVer,_nStartPos,_nContentStartPos),
781*cdf0e10cSrcweir 			_nContentCount-1 );
782*cdf0e10cSrcweir }
783*cdf0e10cSrcweir 
784*cdf0e10cSrcweir //-------------------------------------------------------------------------
785*cdf0e10cSrcweir 
786*cdf0e10cSrcweir void SfxMultiVarRecordWriter::NewContent()
787*cdf0e10cSrcweir 
788*cdf0e10cSrcweir // siehe <SfxMultiFixRecordWriter>
789*cdf0e10cSrcweir 
790*cdf0e10cSrcweir {
791*cdf0e10cSrcweir 	// schon ein Content geschrieben?
792*cdf0e10cSrcweir 	if ( _nContentCount )
793*cdf0e10cSrcweir 		FlushContent_Impl();
794*cdf0e10cSrcweir 
795*cdf0e10cSrcweir 	// neuen Content beginnen
796*cdf0e10cSrcweir 	_nContentStartPos = _pStream->Tell();
797*cdf0e10cSrcweir 	++_nContentCount;
798*cdf0e10cSrcweir }
799*cdf0e10cSrcweir 
800*cdf0e10cSrcweir //-------------------------------------------------------------------------
801*cdf0e10cSrcweir 
802*cdf0e10cSrcweir sal_uInt32 SfxMultiVarRecordWriter::Close( FASTBOOL bSeekToEndOfRec )
803*cdf0e10cSrcweir 
804*cdf0e10cSrcweir // siehe <SfxMiniRecordWriter>
805*cdf0e10cSrcweir 
806*cdf0e10cSrcweir {
807*cdf0e10cSrcweir 	// Header noch nicht geschrieben?
808*cdf0e10cSrcweir 	if ( !_bHeaderOk )
809*cdf0e10cSrcweir 	{
810*cdf0e10cSrcweir 		// ggf. letzten Content abschlie\sen
811*cdf0e10cSrcweir 		if ( _nContentCount )
812*cdf0e10cSrcweir 			FlushContent_Impl();
813*cdf0e10cSrcweir 
814*cdf0e10cSrcweir 		// Content-Offset-Tabelle schreiben
815*cdf0e10cSrcweir 		sal_uInt32 nContentOfsPos = _pStream->Tell();
816*cdf0e10cSrcweir 		//! darf man das so einr"ucken?
817*cdf0e10cSrcweir 		#if defined(OSL_LITENDIAN)
818*cdf0e10cSrcweir 			_pStream->Write( _aContentOfs.GetData(),
819*cdf0e10cSrcweir 							 sizeof(sal_uInt32)*_nContentCount );
820*cdf0e10cSrcweir 		#else
821*cdf0e10cSrcweir 			for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
822*cdf0e10cSrcweir 				*_pStream << sal_uInt32(_aContentOfs[n]);
823*cdf0e10cSrcweir 		#endif
824*cdf0e10cSrcweir 
825*cdf0e10cSrcweir 		// SfxMultiFixRecordWriter::Close() "uberspringen!
826*cdf0e10cSrcweir 		sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( sal_False );
827*cdf0e10cSrcweir 
828*cdf0e10cSrcweir 		// eigenen Header schreiben
829*cdf0e10cSrcweir 		*_pStream << _nContentCount;
830*cdf0e10cSrcweir 		if ( SFX_REC_TYPE_VARSIZE_RELOC == _nPreTag ||
831*cdf0e10cSrcweir 			 SFX_REC_TYPE_MIXTAGS_RELOC == _nPreTag )
832*cdf0e10cSrcweir 			*_pStream << static_cast<sal_uInt32>(nContentOfsPos - ( _pStream->Tell() + sizeof(sal_uInt32) ));
833*cdf0e10cSrcweir 		else
834*cdf0e10cSrcweir 			*_pStream << nContentOfsPos;
835*cdf0e10cSrcweir 
836*cdf0e10cSrcweir 		// ans Ende des Records seeken bzw. am Ende des Headers bleiben
837*cdf0e10cSrcweir 		if ( bSeekToEndOfRec )
838*cdf0e10cSrcweir 			 _pStream->Seek(nEndPos);
839*cdf0e10cSrcweir 		return nEndPos;
840*cdf0e10cSrcweir 	}
841*cdf0e10cSrcweir 
842*cdf0e10cSrcweir 	// Record war bereits vorher geschlossen
843*cdf0e10cSrcweir 	return 0;
844*cdf0e10cSrcweir }
845*cdf0e10cSrcweir 
846*cdf0e10cSrcweir //=========================================================================
847*cdf0e10cSrcweir 
848*cdf0e10cSrcweir void SfxMultiMixRecordWriter::NewContent
849*cdf0e10cSrcweir (
850*cdf0e10cSrcweir 	sal_uInt16		nContentTag,	// Kennung f"ur die Art des Contents
851*cdf0e10cSrcweir 	sal_uInt8		nContentVer 	// Kennung f"ur die Version des Contents
852*cdf0e10cSrcweir )
853*cdf0e10cSrcweir 
854*cdf0e10cSrcweir /*	[Beschreibung]
855*cdf0e10cSrcweir 
856*cdf0e10cSrcweir 	Mit dieser Methode wird in den Record ein neuer Content eingef"ugt
857*cdf0e10cSrcweir 	und dessen Content-Tag sowie dessen Content-Version angegeben. Jeder,
858*cdf0e10cSrcweir 	auch der 1. Record mu\s durch Aufruf dieser Methode eingeleitet werden.
859*cdf0e10cSrcweir */
860*cdf0e10cSrcweir 
861*cdf0e10cSrcweir {
862*cdf0e10cSrcweir 	// ggf. vorherigen Record abschlie\sen
863*cdf0e10cSrcweir 	if ( _nContentCount )
864*cdf0e10cSrcweir 		FlushContent_Impl();
865*cdf0e10cSrcweir 
866*cdf0e10cSrcweir 	// Tag vor den Content schreiben, Version und Startposition merken
867*cdf0e10cSrcweir 	_nContentStartPos = _pStream->Tell();
868*cdf0e10cSrcweir 	++_nContentCount;
869*cdf0e10cSrcweir 	*_pStream << nContentTag;
870*cdf0e10cSrcweir 	_nContentVer = nContentVer;
871*cdf0e10cSrcweir }
872*cdf0e10cSrcweir 
873*cdf0e10cSrcweir //=========================================================================
874*cdf0e10cSrcweir 
875*cdf0e10cSrcweir FASTBOOL SfxMultiRecordReader::ReadHeader_Impl()
876*cdf0e10cSrcweir 
877*cdf0e10cSrcweir /*  [Beschreibung]
878*cdf0e10cSrcweir 
879*cdf0e10cSrcweir 	Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
880*cdf0e10cSrcweir 	die Basisklasse bereits initialisiert und deren Header gelesen ist.
881*cdf0e10cSrcweir 	Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
882*cdf0e10cSrcweir 	nicht zur"uckge-seekt.
883*cdf0e10cSrcweir */
884*cdf0e10cSrcweir 
885*cdf0e10cSrcweir {
886*cdf0e10cSrcweir 	// eigenen Header lesen
887*cdf0e10cSrcweir 	*_pStream >> _nContentCount;
888*cdf0e10cSrcweir 	*_pStream >> _nContentSize; // Fix: jedes einzelnen, Var|Mix: Tabellen-Pos.
889*cdf0e10cSrcweir 
890*cdf0e10cSrcweir 	// mu\s noch eine Tabelle mit Content-Offsets geladen werden?
891*cdf0e10cSrcweir 	if ( _nRecordType != SFX_REC_TYPE_FIXSIZE )
892*cdf0e10cSrcweir 	{
893*cdf0e10cSrcweir 		// Tabelle aus dem Stream einlesen
894*cdf0e10cSrcweir 		sal_uInt32 nContentPos = _pStream->Tell();
895*cdf0e10cSrcweir 		if ( _nRecordType == SFX_REC_TYPE_VARSIZE_RELOC ||
896*cdf0e10cSrcweir 			 _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
897*cdf0e10cSrcweir 			_pStream->SeekRel( + _nContentSize );
898*cdf0e10cSrcweir 		else
899*cdf0e10cSrcweir 			_pStream->Seek( _nContentSize );
900*cdf0e10cSrcweir 		_pContentOfs = new sal_uInt32[_nContentCount];
901*cdf0e10cSrcweir 		//! darf man jetzt so einr"ucken
902*cdf0e10cSrcweir 		#if defined(OSL_LITENDIAN)
903*cdf0e10cSrcweir 			_pStream->Read( _pContentOfs, sizeof(sal_uInt32)*_nContentCount );
904*cdf0e10cSrcweir 		#else
905*cdf0e10cSrcweir 			for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
906*cdf0e10cSrcweir 				*_pStream >> _pContentOfs[n];
907*cdf0e10cSrcweir 		#endif
908*cdf0e10cSrcweir 		_pStream->Seek( nContentPos );
909*cdf0e10cSrcweir 	}
910*cdf0e10cSrcweir 
911*cdf0e10cSrcweir 	// Header konnte gelesen werden, wenn am Stream kein Error gesetzt ist
912*cdf0e10cSrcweir 	return !_pStream->GetError();
913*cdf0e10cSrcweir }
914*cdf0e10cSrcweir 
915*cdf0e10cSrcweir //-------------------------------------------------------------------------
916*cdf0e10cSrcweir 
917*cdf0e10cSrcweir SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream )
918*cdf0e10cSrcweir :	_pContentOfs( NULL ), _nContentNo(0)
919*cdf0e10cSrcweir {
920*cdf0e10cSrcweir 	// Position im Stream merken, um im Fehlerfall zur"uck-seeken zu k"onnen
921*cdf0e10cSrcweir 	_nStartPos = pStream->Tell();
922*cdf0e10cSrcweir 
923*cdf0e10cSrcweir 	// Basisklasse konstruieren (normaler Ctor w"urde nur SingleRecs lesen)
924*cdf0e10cSrcweir 	SfxSingleRecordReader::Construct_Impl( pStream );
925*cdf0e10cSrcweir 
926*cdf0e10cSrcweir 	// Header der Basisklasse lesen
927*cdf0e10cSrcweir 	if ( !SfxSingleRecordReader::ReadHeader_Impl( SFX_REC_TYPE_FIXSIZE |
928*cdf0e10cSrcweir 				SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC |
929*cdf0e10cSrcweir 				SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC ) ||
930*cdf0e10cSrcweir 		 !ReadHeader_Impl() )
931*cdf0e10cSrcweir 		// als ung"ultig markieren und zur"uck-seeken
932*cdf0e10cSrcweir 		SetInvalid_Impl( _nStartPos );
933*cdf0e10cSrcweir }
934*cdf0e10cSrcweir 
935*cdf0e10cSrcweir //-------------------------------------------------------------------------
936*cdf0e10cSrcweir 
937*cdf0e10cSrcweir SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream, sal_uInt16 nTag )
938*cdf0e10cSrcweir :	_nContentNo(0)
939*cdf0e10cSrcweir {
940*cdf0e10cSrcweir 	// Position im Stream merken, um im Fehlerfall zur"uck-seeken zu k"onnen
941*cdf0e10cSrcweir 	_nStartPos = pStream->Tell();
942*cdf0e10cSrcweir 
943*cdf0e10cSrcweir 	// passenden Record suchen und Basisklasse initialisieren
944*cdf0e10cSrcweir 	SfxSingleRecordReader::Construct_Impl( pStream );
945*cdf0e10cSrcweir 	if ( SfxSingleRecordReader::FindHeader_Impl( SFX_REC_TYPE_FIXSIZE |
946*cdf0e10cSrcweir 			SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC |
947*cdf0e10cSrcweir 			SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC,
948*cdf0e10cSrcweir 			nTag ) )
949*cdf0e10cSrcweir 	{
950*cdf0e10cSrcweir 		// eigenen Header dazu-lesen
951*cdf0e10cSrcweir 		if ( !ReadHeader_Impl() )
952*cdf0e10cSrcweir 			// nicht lesbar => als ung"ultig markieren und zur"uck-seeken
953*cdf0e10cSrcweir 			SetInvalid_Impl( _nStartPos);
954*cdf0e10cSrcweir 	}
955*cdf0e10cSrcweir }
956*cdf0e10cSrcweir 
957*cdf0e10cSrcweir //-------------------------------------------------------------------------
958*cdf0e10cSrcweir 
959*cdf0e10cSrcweir SfxMultiRecordReader::~SfxMultiRecordReader()
960*cdf0e10cSrcweir {
961*cdf0e10cSrcweir 	delete[] _pContentOfs;
962*cdf0e10cSrcweir }
963*cdf0e10cSrcweir 
964*cdf0e10cSrcweir //-------------------------------------------------------------------------
965*cdf0e10cSrcweir 
966*cdf0e10cSrcweir FASTBOOL SfxMultiRecordReader::GetContent()
967*cdf0e10cSrcweir 
968*cdf0e10cSrcweir /*	[Beschreibung]
969*cdf0e10cSrcweir 
970*cdf0e10cSrcweir 	Positioniert den Stream an den Anfang des n"chsten bzw. beim 1. Aufruf
971*cdf0e10cSrcweir 	auf den Anfang des ersten Contents im Record und liest ggf. dessen
972*cdf0e10cSrcweir 	Header ein.
973*cdf0e10cSrcweir 
974*cdf0e10cSrcweir 	Liegt laut Record-Header kein Content mehr vor, wird sal_False zur"uck-
975*cdf0e10cSrcweir 	gegeben. Trotz einem sal_True-Returnwert kann am Stream ein Fehlercode
976*cdf0e10cSrcweir 	gesetzt sein, z.B. falls er unvorhergesehenerweise (kaputtes File)
977*cdf0e10cSrcweir 	zuende ist.
978*cdf0e10cSrcweir */
979*cdf0e10cSrcweir 
980*cdf0e10cSrcweir {
981*cdf0e10cSrcweir 	// noch ein Content vorhanden?
982*cdf0e10cSrcweir 	if ( _nContentNo < _nContentCount )
983*cdf0e10cSrcweir 	{
984*cdf0e10cSrcweir 		// den Stream an den Anfang des Contents positionieren
985*cdf0e10cSrcweir 		sal_uInt32 nOffset = _nRecordType == SFX_REC_TYPE_FIXSIZE
986*cdf0e10cSrcweir 					? _nContentNo * _nContentSize
987*cdf0e10cSrcweir 					: SFX_REC_CONTENT_OFS(_pContentOfs[_nContentNo]);
988*cdf0e10cSrcweir 		sal_uInt32 nNewPos = _nStartPos + nOffset;
989*cdf0e10cSrcweir 		DBG_ASSERT( nNewPos >= _pStream->Tell(), "SfxMultiRecordReader::GetContent() - New position before current, to much data red!" );
990*cdf0e10cSrcweir 
991*cdf0e10cSrcweir 		// #99366#: correct stream pos in every case;
992*cdf0e10cSrcweir         // the if clause was added by MT  a long time ago,
993*cdf0e10cSrcweir         // maybe to 'repair' other corrupt documents; but this
994*cdf0e10cSrcweir         // gives errors when writing with 5.1 and reading with current
995*cdf0e10cSrcweir         // versions, so we decided to remove the if clause (KA-05/17/2002)
996*cdf0e10cSrcweir         // if ( nNewPos > _pStream->Tell() )
997*cdf0e10cSrcweir 		_pStream->Seek( nNewPos );
998*cdf0e10cSrcweir 
999*cdf0e10cSrcweir 		// ggf. Content-Header lesen
1000*cdf0e10cSrcweir 		if ( _nRecordType == SFX_REC_TYPE_MIXTAGS ||
1001*cdf0e10cSrcweir 			 _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
1002*cdf0e10cSrcweir 		{
1003*cdf0e10cSrcweir 			_nContentVer = sal::static_int_cast< sal_uInt8 >(
1004*cdf0e10cSrcweir                 SFX_REC_CONTENT_VER(_pContentOfs[_nContentNo]));
1005*cdf0e10cSrcweir 			*_pStream >> _nContentTag;
1006*cdf0e10cSrcweir 		}
1007*cdf0e10cSrcweir 
1008*cdf0e10cSrcweir 		// ContentNo weiterz"ahlen
1009*cdf0e10cSrcweir 		++_nContentNo;
1010*cdf0e10cSrcweir 		return sal_True;
1011*cdf0e10cSrcweir 	}
1012*cdf0e10cSrcweir 
1013*cdf0e10cSrcweir 	return sal_False;
1014*cdf0e10cSrcweir }
1015*cdf0e10cSrcweir 
1016*cdf0e10cSrcweir 
1017