bump product version to 4.2.0.1
[LibreOffice.git] / svl / source / filerec / filerec.cxx
blob697c5229e910d24c1e039a77ee373d3fc0e7b74b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svl/filerec.hxx>
21 #include <osl/endian.h>
24 /* Die folgenden Makros extrahieren Teilbereiche aus einem sal_uInt32 Wert.
25 Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
26 um Calls zu sparen.
29 #define SFX_REC_PRE(n) ( ((n) & 0x000000FF) )
30 #define SFX_REC_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
31 #define SFX_REC_TYP(n) ( ((n) & 0x000000FF) )
32 #define SFX_REC_VER(n) ( ((n) & 0x0000FF00) >> 8 )
33 #define SFX_REC_TAG(n) ( ((n) & 0xFFFF0000) >> 16 )
35 #define SFX_REC_CONTENT_VER(n) ( ((n) & 0x000000FF) )
36 #define SFX_REC_CONTENT_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
39 /* Die folgenden Makros setzen Teilbereiche zu einem sal_uInt32 Wert zusammen.
40 Diese sal_uInt32-Werte werden anstelle der einzelnen Werte gestreamt,
41 um Calls zu sparen.
44 #define SFX_REC_MINI_HEADER(nPreTag,nStartPos,nEndPos) \
45 ( sal_uInt32(nPreTag) | \
46 sal_uInt32(nEndPos-nStartPos-SFX_REC_HEADERSIZE_MINI) << 8 )
48 #define SFX_REC_HEADER(nRecType,nContentTag,nContentVer) \
49 ( sal_uInt32(nRecType) | \
50 ( sal_uInt32(nContentVer) << 8 ) | \
51 ( sal_uInt32(nContentTag) << 16 ) )
53 #define SFX_REC_CONTENT_HEADER(nContentVer,n1StStartPos,nCurStartPos) \
54 ( sal_uInt32(nContentVer) | \
55 sal_uInt32( nCurStartPos - n1StStartPos ) << 8 )
58 sal_uInt32 SfxMiniRecordWriter::Close
60 bool bSeekToEndOfRec /* true (default)
61 Der Stream wird an das Ende des Records
62 positioniert.
64 false
65 Der Stream wird an den Anfang des
66 Contents (also hinter den Header)
67 positioniert.
71 /* [Beschreibung]
73 Diese Methode schlie\st den Record. Dabei wird haupts"achlich der
74 Header geschrieben.
76 Wurde der Header bereits geschrieben, hat der Aufruf keine Wirkung.
79 [R"uckgabewert]
81 sal_uInt32 != 0
82 Position im Stream, die direkt hinter dem Record liegt.
83 'bSeekToEndOfRecord==sal_True'
84 => R"uckgabewert == aktuelle Stream-Position nach Aufruf
86 == 0
87 Der Header war bereits geschrieben worden.
91 // wurde der Header noch nicht geschrieben?
92 if ( !_bHeaderOk )
94 // Header an den Anfang des Records schreiben
95 sal_uInt32 nEndPos = _pStream->Tell();
96 _pStream->Seek( _nStartPos );
97 *_pStream << SFX_REC_MINI_HEADER( _nPreTag, _nStartPos, nEndPos );
99 // je nachdem ans Ende des Records seeken oder hinter Header bleiben
100 if ( bSeekToEndOfRec )
101 _pStream->Seek( nEndPos );
103 // Header wurde JETZT geschrieben
104 _bHeaderOk = true;
105 return nEndPos;
108 // Record war bereits geschlossen
109 return 0;
112 bool SfxMiniRecordReader::SetHeader_Impl( sal_uInt32 nHeader )
114 /* [Beschreibung]
116 Interne Methode zum nachtr"aglichen Verarbeiten eines extern gelesenen
117 Headers. Falls der Header eine End-Of-Records-Kennung darstellt,
118 wird am Stream ein Errorcode gesetzt und sal_False zur"uckgeliefert. Im
119 Fehlerfall wird der Stream jedoch nicht auf den Record-Anfang zur"uck-
120 gesetzt.
124 bool bRet = true;
126 // Record-Ende und Pre-Tag aus dem Header ermitteln
127 _nEofRec = _pStream->Tell() + SFX_REC_OFS(nHeader);
128 _nPreTag = sal::static_int_cast< sal_uInt8 >(SFX_REC_PRE(nHeader));
130 // wenn End-Of-Record-Kennung, dann Fehler
131 if ( _nPreTag == SFX_REC_PRETAG_EOR )
133 _pStream->SetError( ERRCODE_IO_WRONGFORMAT );
134 bRet = true;
136 return bRet;
139 SfxMiniRecordReader::SfxMiniRecordReader
141 SvStream* pStream, /* <SvStream>, an dessen aktueller
142 Position sich ein <SfxMiniRecord>
143 befindet.
145 sal_uInt8 nTag // Pre-Tag des gew"unschten Records
148 /* [Beschreibung]
150 Dieser Ctor interpretiert 'pStream' ab der aktuellen Position als
151 eine l"uckenlose Folge von, von dieser Klassen-Gruppe interpretierbaren,
152 Records. Der in dieser Folge erste als <SfxMiniRecord> interpretierbare
153 (also ggf. auch ein extended-Record) mit dem PreTag 'nTag' wird ge"offnet
154 und durch diese Instanz repr"asentiert.
156 Wird das Ende des Streams oder die Kennung SFX_REC_PRETAG_EOR
157 erreicht, bevor ein Record mit dem ge"unschten Pre-Tag gefunden wird,
158 ist die erzeugte Instanz ung"ultig ('IsValid() == sal_False'). Ein ent-
159 sprechender Error-Code (ERRCODE_IO_EOF bzw. ERRCODE_IO_WRONGFORMAT)
160 ist dann am Stream gesetzt, dessen Position ist dann au\serdem unver-
161 "andert.
163 Bei 'nTag==SFX_FILEREC_PRETAG_EOR' wird nicht versucht, einen Record
164 zu lesen, es wird sofort 'IsValid()' auf sal_False gesetzt und kein Error-Code
165 am Stream gesetzt. Dies ist dauzu gedacht, ohne 'new' und 'delete'
166 abw"rtskompatibel SfxMiniRecords einbauen zu k"onnen. Siehe dazu
167 <SfxItemSet::Load()>.
170 [Anwendungsvorschlag]
172 Wird dieser Ctor in einer bereits ausgelieferten Programmversion
173 verwendet, k"onnen in das File-Format jeweils davor kompatibel neue
174 Records mit einer anderen Kennung eingef"ugt werden. Diese werden
175 schlie\slich automatisch "uberlesen. Erkauft wird diese M"oglichkeit
176 allerdings mit etwas schlechterem Laufzeitverhalten im Vergleich mit
177 direktem 'drauf-los-lesen', der sich jedoch auf einen Vergleich zweier
178 Bytes reduziert, falls der gesuchte Record der erste in der Folge ist.
181 : _pStream( pStream ),
182 _bSkipped( nTag == SFX_REC_PRETAG_EOR )
184 // ggf. ignorieren (s.o.)
185 if ( _bSkipped )
187 _nPreTag = nTag;
188 return;
191 // StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
192 sal_uInt32 nStartPos = pStream->Tell();
194 // passenden Record suchen
195 while(true)
197 // Header lesen
198 DBG( DbgOutf( "SfxFileRec: searching record at %ul", pStream->Tell() ) );
199 sal_uInt32 nHeader;
200 *pStream >> nHeader;
202 // Headerdaten von Basisklasse extrahieren lassen
203 SetHeader_Impl( nHeader );
205 // ggf. Fehler behandeln
206 if ( pStream->IsEof() )
207 _nPreTag = SFX_REC_PRETAG_EOR;
208 else if ( _nPreTag == SFX_REC_PRETAG_EOR )
209 pStream->SetError( ERRCODE_IO_WRONGFORMAT );
210 else
212 // wenn gefunden, dann Schleife abbrechen
213 if ( _nPreTag == nTag )
214 break;
216 // sonst skippen und weitersuchen
217 pStream->Seek( _nEofRec );
218 continue;
221 // Fehler => zur"uck-seeken
222 pStream->Seek( nStartPos );
223 break;
228 SfxSingleRecordWriter::SfxSingleRecordWriter
230 sal_uInt8 nRecordType, // f"ur Subklassen
231 SvStream* pStream, // Stream, in dem der Record angelegt wird
232 sal_uInt16 nContentTag, // Inhalts-Art-Kennung
233 sal_uInt8 nContentVer // Inhalts-Versions-Kennung
236 /* [Beschreibung]
238 Interner Ctor f"ur Subklassen.
241 : SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT )
243 // Erweiterten Header hiner den des SfxMiniRec schreiben
244 *pStream << SFX_REC_HEADER(nRecordType, nContentTag, nContentVer);
248 inline bool SfxSingleRecordReader::ReadHeader_Impl( sal_uInt16 nTypes )
250 /* [Beschreibung]
252 Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
253 die Basisklasse bereits initialisiert und deren Header gelesen ist.
254 Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
255 nicht zur"uckge-seekt.
259 bool bRet;
261 // Basisklassen-Header einlesen
262 sal_uInt32 nHeader=0;
263 *_pStream >> nHeader;
264 if ( !SetHeader_Impl( nHeader ) )
265 bRet = false;
266 else
268 // eigenen Header einlesen
269 *_pStream >> nHeader;
270 _nRecordVer = sal::static_int_cast< sal_uInt8 >(SFX_REC_VER(nHeader));
271 _nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
273 // falscher Record-Typ?
274 _nRecordType = sal::static_int_cast< sal_uInt8 >(SFX_REC_TYP(nHeader));
275 bRet = 0 != ( nTypes & _nRecordType);
277 return bRet;
281 bool SfxSingleRecordReader::FindHeader_Impl
283 sal_uInt16 nTypes, // arithm. Veroderung erlaubter Record-Typen
284 sal_uInt16 nTag // zu findende Record-Art-Kennung
287 /* [Beschreibung]
289 Interne Methode zum lesen des Headers des ersten Record, der einem
290 der Typen in 'nTypes' entspricht und mit der Art-Kennung 'nTag'
291 gekennzeichnet ist.
293 Kann ein solcher Record nicht gefunden werden, wird am Stream ein
294 Errorcode gesetzt, zur"uck-geseekt und sal_False zur"uckgeliefert.
298 // StartPos merken, um im Fehlerfall zur"uck-seeken zu k"onnen
299 sal_uInt32 nStartPos = _pStream->Tell();
301 // richtigen Record suchen
302 while ( !_pStream->IsEof() )
304 // Header lesen
305 sal_uInt32 nHeader;
306 DBG( DbgOutf( "SfxFileRec: searching record at %ul", _pStream->Tell() ) );
307 *_pStream >> nHeader;
308 if ( !SetHeader_Impl( nHeader ) )
309 // EOR => Such-Schleife abbreichen
310 break;
312 // Extended Record gefunden?
313 if ( _nPreTag == SFX_REC_PRETAG_EXT )
315 // Extended Header lesen
316 *_pStream >> nHeader;
317 _nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
319 // richtigen Record gefunden?
320 if ( _nRecordTag == nTag )
322 // gefundener Record-Typ passend?
323 _nRecordType = sal::static_int_cast< sal_uInt8 >(
324 SFX_REC_TYP(nHeader));
325 if ( nTypes & _nRecordType )
326 // ==> gefunden
327 return sal_True;
329 // error => Such-Schleife abbrechen
330 break;
334 // sonst skippen
335 if ( !_pStream->IsEof() )
336 _pStream->Seek( _nEofRec );
339 // Fehler setzen und zur"uck-seeken
340 _pStream->SetError( ERRCODE_IO_WRONGFORMAT );
341 _pStream->Seek( nStartPos );
342 return sal_False;
346 SfxMultiFixRecordWriter::SfxMultiFixRecordWriter
348 sal_uInt8 nRecordType, // Subklassen Record-Kennung
349 SvStream* pStream, // Stream, in dem der Record angelegt wird
350 sal_uInt16 nContentTag, // Content-Art-Kennung
351 sal_uInt8 nContentVer // Content-Versions-Kennung
354 /* [Beschreibung]
356 Interne Methode f"ur Subklassen.
359 : SfxSingleRecordWriter( nRecordType, pStream, nContentTag, nContentVer ),
360 _nContentCount( 0 )
362 // Platz f"ur eigenen Header
363 pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI );
367 sal_uInt32 SfxMultiFixRecordWriter::Close( bool bSeekToEndOfRec )
369 // siehe <SfxMiniRecordWriter>
372 // Header noch nicht geschrieben?
373 if ( !_bHeaderOk )
375 // Position hinter Record merken, um sie restaurieren zu k"onnen
376 sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( sal_False );
378 // gegen"uber SfxSingleRecord erweiterten Header schreiben
379 *_pStream << _nContentCount;
380 *_pStream << _nContentSize;
382 // je nachdem ans Ende des Records seeken oder hinter Header bleiben
383 if ( bSeekToEndOfRec )
384 _pStream->Seek(nEndPos);
385 return nEndPos;
388 // Record war bereits geschlossen
389 return 0;
393 SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
395 sal_uInt8 nRecordType, // Record-Kennung der Subklasse
396 SvStream* pStream, // Stream, in dem der Record angelegt wird
397 sal_uInt16 nRecordTag, // Gesamt-Art-Kennung
398 sal_uInt8 nRecordVer // Gesamt-Versions-Kennung
401 /* [Beschreibung]
403 Interner Ctor f"ur Subklassen.
406 : SfxMultiFixRecordWriter( nRecordType, pStream, nRecordTag, nRecordVer ),
407 _nContentVer( 0 )
412 SfxMultiVarRecordWriter::SfxMultiVarRecordWriter
414 SvStream* pStream, // Stream, in dem der Record angelegt wird
415 sal_uInt16 nRecordTag, // Gesamt-Art-Kennung
416 sal_uInt8 nRecordVer // Gesamt-Versions-Kennung
419 /* [Beschreibung]
421 Legt in 'pStream' einen 'SfxMultiVarRecord' an, dessen Content-Gr"o\sen
422 weder bekannt sind noch identisch sein m"ussen, sondern jeweils nach dem
423 Streamen jedes einzelnen Contents errechnet werden sollen.
426 [Anmerkung]
428 Diese Methode ist nicht inline, da f"ur die Initialisierung eines
429 <SvULongs>-Members zu viel Code generiert werden w"urde.
432 : SfxMultiFixRecordWriter( SFX_REC_TYPE_VARSIZE,
433 pStream, nRecordTag, nRecordVer ),
434 _nContentVer( 0 )
439 SfxMultiVarRecordWriter::~SfxMultiVarRecordWriter()
441 /* [Beschreibung]
443 Der Dtor der Klasse <SfxMultiVarRecordWriter> schlie\st den Record
444 automatisch, falls <SfxMultiVarRecordWriter::Close()> nicht bereits
445 explizit gerufen wurde.
449 // wurde der Header noch nicht geschrieben oder mu\s er gepr"uft werden
450 if ( !_bHeaderOk )
451 Close();
455 void SfxMultiVarRecordWriter::FlushContent_Impl()
457 /* [Beschreibung]
459 Interne Methode zum Abschlie\sen eines einzelnen Contents.
463 // Versions-Kennung und Positions-Offset des aktuellen Contents merken;
464 // das Positions-Offset ist relativ zur Startposition des ersten Contents
465 assert(_aContentOfs.size() == static_cast<size_t>(_nContentCount)-1);
466 _aContentOfs.resize(_nContentCount-1);
467 _aContentOfs.push_back(
468 SFX_REC_CONTENT_HEADER(_nContentVer,_nStartPos,_nContentStartPos));
472 void SfxMultiVarRecordWriter::NewContent()
474 // siehe <SfxMultiFixRecordWriter>
477 // schon ein Content geschrieben?
478 if ( _nContentCount )
479 FlushContent_Impl();
481 // neuen Content beginnen
482 _nContentStartPos = _pStream->Tell();
483 ++_nContentCount;
487 sal_uInt32 SfxMultiVarRecordWriter::Close( bool bSeekToEndOfRec )
489 // siehe <SfxMiniRecordWriter>
492 // Header noch nicht geschrieben?
493 if ( !_bHeaderOk )
495 // ggf. letzten Content abschlie\sen
496 if ( _nContentCount )
497 FlushContent_Impl();
499 // Content-Offset-Tabelle schreiben
500 sal_uInt32 nContentOfsPos = _pStream->Tell();
501 //! darf man das so einr"ucken?
502 for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
503 *_pStream << _aContentOfs[n];
505 // SfxMultiFixRecordWriter::Close() "uberspringen!
506 sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( sal_False );
508 // eigenen Header schreiben
509 *_pStream << _nContentCount;
510 if ( SFX_REC_TYPE_VARSIZE_RELOC == _nPreTag ||
511 SFX_REC_TYPE_MIXTAGS_RELOC == _nPreTag )
512 *_pStream << static_cast<sal_uInt32>(nContentOfsPos - ( _pStream->Tell() + sizeof(sal_uInt32) ));
513 else
514 *_pStream << nContentOfsPos;
516 // ans Ende des Records seeken bzw. am Ende des Headers bleiben
517 if ( bSeekToEndOfRec )
518 _pStream->Seek(nEndPos);
519 return nEndPos;
522 // Record war bereits vorher geschlossen
523 return 0;
527 void SfxMultiMixRecordWriter::NewContent
529 sal_uInt16 nContentTag, // Kennung f"ur die Art des Contents
530 sal_uInt8 nContentVer // Kennung f"ur die Version des Contents
533 /* [Beschreibung]
535 Mit dieser Methode wird in den Record ein neuer Content eingef"ugt
536 und dessen Content-Tag sowie dessen Content-Version angegeben. Jeder,
537 auch der 1. Record mu\s durch Aufruf dieser Methode eingeleitet werden.
541 // ggf. vorherigen Record abschlie\sen
542 if ( _nContentCount )
543 FlushContent_Impl();
545 // Tag vor den Content schreiben, Version und Startposition merken
546 _nContentStartPos = _pStream->Tell();
547 ++_nContentCount;
548 *_pStream << nContentTag;
549 _nContentVer = nContentVer;
553 bool SfxMultiRecordReader::ReadHeader_Impl()
555 /* [Beschreibung]
557 Interne Methode zum Einlesen eines SfxMultiRecord-Headers, nachdem
558 die Basisklasse bereits initialisiert und deren Header gelesen ist.
559 Ggf. ist ein Error-Code am Stream gesetzt, im Fehlerfall wird jedoch
560 nicht zur"uckge-seekt.
564 // eigenen Header lesen
565 *_pStream >> _nContentCount;
566 *_pStream >> _nContentSize; // Fix: jedes einzelnen, Var|Mix: Tabellen-Pos.
568 // mu\s noch eine Tabelle mit Content-Offsets geladen werden?
569 if ( _nRecordType != SFX_REC_TYPE_FIXSIZE )
571 // Tabelle aus dem Stream einlesen
572 sal_uInt32 nContentPos = _pStream->Tell();
573 if ( _nRecordType == SFX_REC_TYPE_VARSIZE_RELOC ||
574 _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
575 _pStream->SeekRel( + _nContentSize );
576 else
577 _pStream->Seek( _nContentSize );
578 _pContentOfs = new sal_uInt32[_nContentCount];
579 memset(_pContentOfs, 0, _nContentCount*sizeof(sal_uInt32));
580 //! darf man jetzt so einr"ucken
581 #if defined(OSL_LITENDIAN)
582 _pStream->Read( _pContentOfs, sizeof(sal_uInt32)*_nContentCount );
583 #else
584 for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
585 *_pStream >> _pContentOfs[n];
586 #endif
587 _pStream->Seek( nContentPos );
590 // Header konnte gelesen werden, wenn am Stream kein Error gesetzt ist
591 return !_pStream->GetError();
595 SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream, sal_uInt16 nTag )
596 : _pContentOfs(0)
597 , _nContentSize(0)
598 , _nContentCount(0)
599 , _nContentNo(0)
601 // Position im Stream merken, um im Fehlerfall zur"uck-seeken zu k"onnen
602 _nStartPos = pStream->Tell();
604 // passenden Record suchen und Basisklasse initialisieren
605 SfxSingleRecordReader::Construct_Impl( pStream );
606 if ( SfxSingleRecordReader::FindHeader_Impl( SFX_REC_TYPE_FIXSIZE |
607 SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC |
608 SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC,
609 nTag ) )
611 // eigenen Header dazu-lesen
612 if ( !ReadHeader_Impl() )
613 // nicht lesbar => als ung"ultig markieren und zur"uck-seeken
614 SetInvalid_Impl( _nStartPos);
619 SfxMultiRecordReader::~SfxMultiRecordReader()
621 delete[] _pContentOfs;
625 bool SfxMultiRecordReader::GetContent()
627 /* [Beschreibung]
629 Positioniert den Stream an den Anfang des n"chsten bzw. beim 1. Aufruf
630 auf den Anfang des ersten Contents im Record und liest ggf. dessen
631 Header ein.
633 Liegt laut Record-Header kein Content mehr vor, wird sal_False zur"uck-
634 gegeben. Trotz einem sal_True-Returnwert kann am Stream ein Fehlercode
635 gesetzt sein, z.B. falls er unvorhergesehenerweise (kaputtes File)
636 zuende ist.
640 // noch ein Content vorhanden?
641 if ( _nContentNo < _nContentCount )
643 // den Stream an den Anfang des Contents positionieren
644 sal_uInt32 nOffset = _nRecordType == SFX_REC_TYPE_FIXSIZE
645 ? _nContentNo * _nContentSize
646 : SFX_REC_CONTENT_OFS(_pContentOfs[_nContentNo]);
647 sal_uInt32 nNewPos = _nStartPos + nOffset;
648 DBG_ASSERT( nNewPos >= _pStream->Tell(), "SfxMultiRecordReader::GetContent() - New position before current, to much data red!" );
650 // #99366#: correct stream pos in every case;
651 // the if clause was added by MT a long time ago,
652 // maybe to 'repair' other corrupt documents; but this
653 // gives errors when writing with 5.1 and reading with current
654 // versions, so we decided to remove the if clause (KA-05/17/2002)
655 // if ( nNewPos > _pStream->Tell() )
656 _pStream->Seek( nNewPos );
658 // ggf. Content-Header lesen
659 if ( _nRecordType == SFX_REC_TYPE_MIXTAGS ||
660 _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
662 _nContentVer = sal::static_int_cast< sal_uInt8 >(
663 SFX_REC_CONTENT_VER(_pContentOfs[_nContentNo]));
664 *_pStream >> _nContentTag;
667 // ContentNo weiterz"ahlen
668 ++_nContentNo;
669 return sal_True;
672 return sal_False;
676 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */