xref: /AOO41X/main/editeng/source/editeng/editobj.cxx (revision ba70561f05f4424034cb913f47ab050f4afee5f0)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_editeng.hxx"
26 
27 #include <vcl/wrkwin.hxx>
28 #include <vcl/dialog.hxx>
29 #include <vcl/msgbox.hxx>
30 #include <vcl/svapp.hxx>
31 
32 #define ENABLE_STRING_STREAM_OPERATORS
33 #include <tools/stream.hxx>
34 
35 #include <editobj2.hxx>
36 #include <editeng/editdata.hxx>
37 #include <editattr.hxx>
38 #include <editeng/editeng.hxx>
39 #include <editeng/fontitem.hxx>
40 #include <editeng/cscoitem.hxx>
41 #include <editeng/flditem.hxx>
42 #include <editeng/lrspitem.hxx>
43 #include <editeng/tstpitem.hxx>
44 #include <editeng/bulitem.hxx>
45 #include <editeng/numitem.hxx>
46 #include <editeng/brshitem.hxx>
47 #include <vcl/graph.hxx>
48 #include <svl/intitem.hxx>
49 #include <unotools/fontcvt.hxx>
50 #include <tools/tenccvt.hxx>
51 
52 DBG_NAME( EE_EditTextObject )
DBG_NAME(XEditAttribute)53 DBG_NAME( XEditAttribute )
54 
55 //--------------------------------------------------------------
56 
57 sal_Bool lcl_CreateBulletItem( const SvxNumBulletItem& rNumBullet, sal_uInt16 nLevel, SvxBulletItem& rBullet )
58 {
59     const SvxNumberFormat* pFmt = rNumBullet.GetNumRule()->Get( nLevel );
60     if ( pFmt )
61     {
62         rBullet.SetWidth( (-pFmt->GetFirstLineOffset()) + pFmt->GetCharTextDistance() );
63         rBullet.SetSymbol( pFmt->GetBulletChar() );
64         rBullet.SetPrevText( pFmt->GetPrefix() );
65         rBullet.SetFollowText( pFmt->GetSuffix() );
66         rBullet.SetStart( pFmt->GetStart() );
67         rBullet.SetScale( pFmt->GetBulletRelSize() );
68 
69         Font aBulletFont( rBullet.GetFont() );
70         if ( pFmt->GetBulletFont() )
71             aBulletFont = *pFmt->GetBulletFont();
72         aBulletFont.SetColor( pFmt->GetBulletColor() );
73         rBullet.SetFont( aBulletFont );
74 
75         if ( pFmt->GetBrush() && pFmt->GetBrush()->GetGraphic() )
76         {
77             Bitmap aBmp( pFmt->GetBrush()->GetGraphic()->GetBitmap() );
78             aBmp.SetPrefSize( pFmt->GetGraphicSize() );
79             aBmp.SetPrefMapMode( MAP_100TH_MM );
80             rBullet.SetBitmap( aBmp );
81         }
82 
83         switch ( pFmt->GetNumberingType() )
84         {
85             case SVX_NUM_CHARS_UPPER_LETTER:
86             case SVX_NUM_CHARS_UPPER_LETTER_N:
87                 rBullet.SetStyle( BS_ABC_BIG );
88                 break;
89             case SVX_NUM_CHARS_LOWER_LETTER:
90             case SVX_NUM_CHARS_LOWER_LETTER_N:
91                 rBullet.SetStyle( BS_ABC_SMALL );
92                 break;
93             case SVX_NUM_ROMAN_UPPER:
94                 rBullet.SetStyle( BS_ROMAN_BIG );
95                 break;
96             case SVX_NUM_ROMAN_LOWER:
97                 rBullet.SetStyle( BS_ROMAN_SMALL );
98                 break;
99             case SVX_NUM_ARABIC:
100                 rBullet.SetStyle( BS_123 );
101                 break;
102             case SVX_NUM_NUMBER_NONE:
103                 rBullet.SetStyle( BS_NONE );
104                 break;
105             case SVX_NUM_CHAR_SPECIAL:
106                 rBullet.SetStyle( BS_BULLET );
107                 break;
108             case SVX_NUM_PAGEDESC:
109                 DBG_ERROR( "Unknown: SVX_NUM_PAGEDESC" );
110                 rBullet.SetStyle( BS_BULLET );
111                 break;
112             case SVX_NUM_BITMAP:
113                 rBullet.SetStyle( BS_BMP );
114                 break;
115             default:
116                 DBG_ERROR( "Unknown NumType" );
117         }
118 
119         switch ( pFmt->GetNumAdjust() )
120         {
121             case SVX_ADJUST_LEFT:
122                 rBullet.SetJustification( BJ_VCENTER|BJ_HLEFT );
123                 break;
124             case SVX_ADJUST_RIGHT:
125                 rBullet.SetJustification( BJ_VCENTER|BJ_HRIGHT );
126                 break;
127             case SVX_ADJUST_CENTER:
128                 rBullet.SetJustification( BJ_VCENTER|BJ_HCENTER );
129                 break;
130             default:
131                 DBG_ERROR( "Unknown or invalid NumAdjust" );
132         }
133     }
134     return pFmt ? sal_True : sal_False;
135 }
136 
137 
MakeXEditAttribute(SfxItemPool & rPool,const SfxPoolItem & rItem,sal_uInt16 nStart,sal_uInt16 nEnd)138 XEditAttribute* MakeXEditAttribute( SfxItemPool& rPool, const SfxPoolItem& rItem, sal_uInt16 nStart, sal_uInt16 nEnd )
139 {
140     // das neue Attribut im Pool anlegen
141     const SfxPoolItem& rNew = rPool.Put( rItem );
142 
143     XEditAttribute* pNew = new XEditAttribute( rNew, nStart, nEnd );
144     return pNew;
145 }
146 
147 
XEditAttribute(const SfxPoolItem & rAttr)148 XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr )
149 {
150     DBG_CTOR( XEditAttribute, 0 );
151     pItem = &rAttr;
152     nStart = 0;
153     nEnd = 0;
154 }
155 
XEditAttribute(const SfxPoolItem & rAttr,sal_uInt16 nS,sal_uInt16 nE)156 XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr, sal_uInt16 nS, sal_uInt16 nE )
157 {
158     DBG_CTOR( XEditAttribute, 0 );
159     pItem = &rAttr;
160     nStart = nS;
161     nEnd = nE;
162 }
163 
~XEditAttribute()164 XEditAttribute::~XEditAttribute()
165 {
166     DBG_DTOR( XEditAttribute, 0 );
167     pItem = 0;  // Gehoert dem Pool.
168 }
169 
FindAttrib(sal_uInt16 _nWhich,sal_uInt16 nChar) const170 XEditAttribute* XEditAttributeList::FindAttrib( sal_uInt16 _nWhich, sal_uInt16 nChar ) const
171 {
172     for ( sal_uInt16 n = Count(); n; )
173     {
174         XEditAttribute* pAttr = GetObject( --n );
175         if( ( pAttr->GetItem()->Which() == _nWhich ) && ( pAttr->GetStart() <= nChar ) && ( pAttr->GetEnd() > nChar ) )
176             return pAttr;
177     }
178     return NULL;
179 }
180 
ContentInfo(SfxItemPool & rPool)181 ContentInfo::ContentInfo( SfxItemPool& rPool ) : aParaAttribs( rPool, EE_PARA_START, EE_CHAR_END )
182 {
183     eFamily = SFX_STYLE_FAMILY_PARA;
184     pWrongs = NULL;
185 /* cl removed because not needed anymore since binfilter
186     pTempLoadStoreInfos = NULL;
187 */
188 }
189 
190 // Richtiger CopyCTOR unsinning, weil ich mit einem anderen Pool arbeiten muss!
ContentInfo(const ContentInfo & rCopyFrom,SfxItemPool & rPoolToUse)191 ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse )
192     : aParaAttribs( rPoolToUse, EE_PARA_START, EE_CHAR_END )
193 {
194     pWrongs = NULL;
195 /* cl removed because not needed anymore since binfilter
196     pTempLoadStoreInfos = NULL;
197 */
198     if ( rCopyFrom.GetWrongList() )
199         pWrongs = rCopyFrom.GetWrongList()->Clone();
200     // So sollten die Items im richtigen Pool landen!
201     aParaAttribs.Set( rCopyFrom.GetParaAttribs() );
202     aText = rCopyFrom.GetText();
203     aStyle = rCopyFrom.GetStyle();
204     eFamily = rCopyFrom.GetFamily();
205 
206     // Attribute kopieren...
207     for ( sal_uInt16 n = 0; n < rCopyFrom.GetAttribs().Count(); n++  )
208     {
209         XEditAttribute* pAttr = rCopyFrom.GetAttribs().GetObject( n );
210         XEditAttribute* pMyAttr = MakeXEditAttribute( rPoolToUse, *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() );
211         aAttribs.Insert( pMyAttr, aAttribs.Count()  );
212     }
213 
214     // memory leak #119992: to release pWrongs cloned from rCopyFrom
215     if (pWrongs != NULL)
216         delete pWrongs;
217 
218     // Wrongs
219     pWrongs = NULL;
220 #ifndef SVX_LIGHT
221     if ( rCopyFrom.GetWrongList() )
222         pWrongs = rCopyFrom.GetWrongList()->Clone();
223 #endif // !SVX_LIGHT
224 }
225 
~ContentInfo()226 ContentInfo::~ContentInfo()
227 {
228     for ( sal_uInt16 nAttr = 0; nAttr < aAttribs.Count(); nAttr++ )
229     {
230         XEditAttribute* pAttr = aAttribs.GetObject(nAttr);
231         // Item aus Pool entfernen!
232         aParaAttribs.GetPool()->Remove( *pAttr->GetItem() );
233         delete pAttr;
234     }
235     aAttribs.Remove( 0, aAttribs.Count() );
236 #ifndef SVX_LIGHT
237     delete pWrongs;
238 #endif
239 }
240 
241 /* cl removed because not needed anymore since binfilter
242 void ContentInfo::CreateLoadStoreTempInfos()
243 {
244     delete pTempLoadStoreInfos;
245     pTempLoadStoreInfos = new LoadStoreTempInfos;
246 }
247 
248 void ContentInfo::DestroyLoadStoreTempInfos()
249 {
250     delete pTempLoadStoreInfos;
251     pTempLoadStoreInfos = NULL;
252 }
253 */
254 
255 // #i102062#
isWrongListEqual(const ContentInfo & rCompare) const256 bool ContentInfo::isWrongListEqual(const ContentInfo& rCompare) const
257 {
258     if(GetWrongList() == rCompare.GetWrongList())
259         return true;
260 
261     if(!GetWrongList() || !rCompare.GetWrongList())
262         return false;
263 
264     return (*GetWrongList() == *rCompare.GetWrongList());
265 }
266 
operator ==(const ContentInfo & rCompare) const267 bool ContentInfo::operator==( const ContentInfo& rCompare ) const
268 {
269     if( (aText == rCompare.aText) &&
270             (aStyle == rCompare.aStyle ) &&
271             (aAttribs.Count() == rCompare.aAttribs.Count() ) &&
272             (eFamily == rCompare.eFamily ) &&
273             (aParaAttribs == rCompare.aParaAttribs ) )
274     {
275         const sal_uInt16 nCount = aAttribs.Count();
276         if( nCount == rCompare.aAttribs.Count() )
277         {
278             sal_uInt16 n;
279             for( n = 0; n < nCount; n++ )
280             {
281                 if( !(*aAttribs.GetObject(n) == *rCompare.aAttribs.GetObject(n)) )
282                     return false;
283             }
284 
285             return true;
286         }
287     }
288 
289     return false;
290 }
291 
EditTextObject(sal_uInt16 n)292 EditTextObject::EditTextObject( sal_uInt16 n)
293 {
294     DBG_CTOR( EE_EditTextObject, 0 );
295     nWhich = n;
296 }
297 
EditTextObject(const EditTextObject & r)298 EditTextObject::EditTextObject( const EditTextObject& r )
299 {
300     DBG_CTOR( EE_EditTextObject, 0 );
301     nWhich = r.nWhich;
302 }
303 
~EditTextObject()304 __EXPORT EditTextObject::~EditTextObject()
305 {
306     DBG_DTOR( EE_EditTextObject, 0 );
307 }
308 
GetParagraphCount() const309 sal_uInt16 EditTextObject::GetParagraphCount() const
310 {
311     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
312     return 0;
313 }
314 
GetText(sal_uInt16) const315 XubString EditTextObject::GetText( sal_uInt16 /* nParagraph */ ) const
316 {
317     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
318     return XubString();
319 }
320 
Insert(const EditTextObject &,sal_uInt16)321 void EditTextObject::Insert( const EditTextObject& /* rObj */, sal_uInt16 /* nPara */)
322 {
323     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
324 }
325 
CreateTextObject(sal_uInt16,sal_uInt16) const326 EditTextObject* EditTextObject::CreateTextObject( sal_uInt16 /*nPara*/, sal_uInt16 /*nParas*/ ) const
327 {
328     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
329     return 0;
330 }
331 
RemoveParagraph(sal_uInt16)332 void EditTextObject::RemoveParagraph( sal_uInt16 /*nPara*/ )
333 {
334     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
335 }
336 
HasPortionInfo() const337 sal_Bool EditTextObject::HasPortionInfo() const
338 {
339     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
340     return sal_False;
341 }
342 
ClearPortionInfo()343 void EditTextObject::ClearPortionInfo()
344 {
345     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
346 }
347 
HasOnlineSpellErrors() const348 sal_Bool EditTextObject::HasOnlineSpellErrors() const
349 {
350     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
351     return sal_False;
352 }
353 
HasCharAttribs(sal_uInt16) const354 sal_Bool EditTextObject::HasCharAttribs( sal_uInt16 ) const
355 {
356     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
357     return sal_False;
358 }
359 
GetCharAttribs(sal_uInt16,EECharAttribArray &) const360 void EditTextObject::GetCharAttribs( sal_uInt16 /*nPara*/, EECharAttribArray& /*rLst*/ ) const
361 {
362     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
363 }
364 
MergeParaAttribs(const SfxItemSet &,sal_uInt16,sal_uInt16)365 void EditTextObject::MergeParaAttribs( const SfxItemSet& /*rAttribs*/, sal_uInt16 /*nStart*/, sal_uInt16 /*nEnd*/ )
366 {
367     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
368 }
369 
IsFieldObject() const370 sal_Bool EditTextObject::IsFieldObject() const
371 {
372     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
373     return sal_False;
374 }
375 
GetField() const376 const SvxFieldItem* EditTextObject::GetField() const
377 {
378     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
379     return 0;
380 }
381 
HasField(TypeId) const382 sal_Bool EditTextObject::HasField( TypeId /*aType*/ ) const
383 {
384     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
385     return sal_False;
386 }
387 
GetParaAttribs(sal_uInt16) const388 SfxItemSet EditTextObject::GetParaAttribs( sal_uInt16 /*nPara*/ ) const
389 {
390     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
391     return SfxItemSet( *(SfxItemPool*)NULL );
392 }
393 
SetParaAttribs(sal_uInt16,const SfxItemSet &)394 void EditTextObject::SetParaAttribs( sal_uInt16 /*nPara*/, const SfxItemSet& /*rAttribs*/ )
395 {
396     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
397 }
398 
RemoveCharAttribs(sal_uInt16)399 sal_Bool EditTextObject::RemoveCharAttribs( sal_uInt16 /*nWhich*/ )
400 {
401     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
402     return sal_False;
403 }
404 
RemoveParaAttribs(sal_uInt16)405 sal_Bool EditTextObject::RemoveParaAttribs( sal_uInt16 /*nWhich*/ )
406 {
407     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
408     return sal_False;
409 }
410 
HasStyleSheet(const XubString &,SfxStyleFamily) const411 sal_Bool EditTextObject::HasStyleSheet( const XubString& /*rName*/, SfxStyleFamily /*eFamily*/ ) const
412 {
413     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
414     return sal_False;
415 }
416 
GetStyleSheet(sal_uInt16,XubString &,SfxStyleFamily &) const417 void EditTextObject::GetStyleSheet( sal_uInt16 /*nPara*/, XubString& /*rName*/, SfxStyleFamily& /*eFamily*/ ) const
418 {
419     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
420 }
421 
SetStyleSheet(sal_uInt16,const XubString &,const SfxStyleFamily &)422 void EditTextObject::SetStyleSheet( sal_uInt16 /*nPara*/, const XubString& /*rName*/, const SfxStyleFamily& /*eFamily*/ )
423 {
424     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
425 }
426 
ChangeStyleSheets(const XubString &,SfxStyleFamily,const XubString &,SfxStyleFamily)427 sal_Bool __EXPORT EditTextObject::ChangeStyleSheets( const XubString&, SfxStyleFamily,
428                                             const XubString&, SfxStyleFamily )
429 {
430     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
431     return sal_False;
432 }
433 
ChangeStyleSheetName(SfxStyleFamily,const XubString &,const XubString &)434 void __EXPORT EditTextObject::ChangeStyleSheetName( SfxStyleFamily /*eFamily*/,
435                 const XubString& /*rOldName*/, const XubString& /*rNewName*/ )
436 {
437     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
438 }
439 
GetUserType() const440 sal_uInt16 EditTextObject::GetUserType() const
441 {
442     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
443     return 0;
444 }
445 
SetUserType(sal_uInt16)446 void EditTextObject::SetUserType( sal_uInt16 )
447 {
448     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
449 }
450 
GetObjectSettings() const451 sal_uLong EditTextObject::GetObjectSettings() const
452 {
453     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
454     return 0;
455 }
456 
SetObjectSettings(sal_uLong)457 void EditTextObject::SetObjectSettings( sal_uLong )
458 {
459     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
460 }
461 
IsVertical() const462 sal_Bool EditTextObject::IsVertical() const
463 {
464     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
465     return sal_False;
466 }
467 
SetVertical(sal_Bool bVertical)468 void EditTextObject::SetVertical( sal_Bool bVertical )
469 {
470     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
471     ((BinTextObject*)this)->SetVertical( bVertical );
472 }
473 
GetScriptType() const474 sal_uInt16 EditTextObject::GetScriptType() const
475 {
476     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
477     return ((const BinTextObject*)this)->GetScriptType();
478 }
479 
480 
Store(SvStream & rOStream) const481 sal_Bool EditTextObject::Store( SvStream& rOStream ) const
482 {
483     if ( rOStream.GetError() )
484         return sal_False;
485 
486     // Vorspann:
487     sal_Size nStartPos = rOStream.Tell();
488 
489     rOStream << (sal_uInt16)Which();
490 
491     sal_uInt32 nStructSz = 0;
492     rOStream << nStructSz;
493 
494     // Eigene Daten:
495     StoreData( rOStream );
496 
497     // Nachspann:
498     sal_Size nEndPos = rOStream.Tell();
499     nStructSz = nEndPos - nStartPos - sizeof( nWhich ) - sizeof( nStructSz );
500     rOStream.Seek( nStartPos + sizeof( nWhich ) );
501     rOStream << nStructSz;
502     rOStream.Seek( nEndPos );
503 
504     return rOStream.GetError() ? sal_False : sal_True;
505 }
506 
Create(SvStream & rIStream,SfxItemPool * pGlobalTextObjectPool)507 EditTextObject* EditTextObject::Create( SvStream& rIStream, SfxItemPool* pGlobalTextObjectPool )
508 {
509     sal_uLong nStartPos = rIStream.Tell();
510 
511     // Ertmal sehen, was fuer ein Object...
512     sal_uInt16 nWhich;
513     rIStream >> nWhich;
514 
515     sal_uInt32 nStructSz;
516     rIStream >> nStructSz;
517 
518     DBG_ASSERT( ( nWhich == 0x22 /*EE_FORMAT_BIN300*/ ) || ( nWhich == EE_FORMAT_BIN ), "CreateTextObject: Unbekanntes Objekt!" );
519 
520     if ( rIStream.GetError() )
521         return NULL;
522 
523     EditTextObject* pTxtObj = NULL;
524     switch ( nWhich )
525     {
526         case 0x22 /*BIN300*/:       pTxtObj = new BinTextObject( 0 );
527                                     ((BinTextObject*)pTxtObj)->CreateData300( rIStream );
528                                     break;
529         case EE_FORMAT_BIN:         pTxtObj = new BinTextObject( pGlobalTextObjectPool );
530                                     pTxtObj->CreateData( rIStream );
531                                     break;
532         default:
533         {
534             // Wenn ich das Format nicht kenne, ueberlese ich den Inhalt:
535             rIStream.SetError( EE_READWRITE_WRONGFORMAT );
536         }
537     }
538 
539     // Sicherstellen, dass der Stream an der richtigen Stelle hinterlassen wird.
540     sal_Size nFullSz = sizeof( nWhich ) + sizeof( nStructSz ) + nStructSz;
541     rIStream.Seek( nStartPos + nFullSz );
542     return pTxtObj;
543 }
544 
Skip(SvStream & rIStream)545 void EditTextObject::Skip( SvStream& rIStream )
546 {
547     sal_Size nStartPos = rIStream.Tell();
548 
549     sal_uInt16 _nWhich;
550     rIStream >> _nWhich;
551 
552     sal_uInt32 nStructSz;
553     rIStream >> nStructSz;
554 
555     sal_Size nFullSz = sizeof( _nWhich ) + sizeof( nStructSz ) + nStructSz;
556     rIStream.Seek( nStartPos + nFullSz );
557 }
558 
StoreData(SvStream &) const559 void __EXPORT EditTextObject::StoreData( SvStream& ) const
560 {
561     DBG_ERROR( "StoreData: Basisklasse!" );
562 }
563 
CreateData(SvStream &)564 void __EXPORT EditTextObject::CreateData( SvStream& )
565 {
566     DBG_ERROR( "CreateData: Basisklasse!" );
567 }
568 
GetVersion() const569 sal_uInt16 EditTextObject::GetVersion() const
570 {
571     DBG_ERROR( "V-Methode direkt vom EditTextObject!" );
572     return 0;
573 }
574 
operator ==(const EditTextObject & rCompare) const575 bool EditTextObject::operator==( const EditTextObject& rCompare ) const
576 {
577     return static_cast< const BinTextObject* >( this )->operator==( static_cast< const BinTextObject& >( rCompare ) );
578 }
579 
580 // #i102062#
isWrongListEqual(const EditTextObject & rCompare) const581 bool EditTextObject::isWrongListEqual(const EditTextObject& rCompare) const
582 {
583     return static_cast< const BinTextObject* >(this)->isWrongListEqual(static_cast< const BinTextObject& >(rCompare));
584 }
585 
586 // from SfxItemPoolUser
ObjectInDestruction(const SfxItemPool & rSfxItemPool)587 void BinTextObject::ObjectInDestruction(const SfxItemPool& rSfxItemPool)
588 {
589     if(!bOwnerOfPool && pPool && pPool == &rSfxItemPool)
590     {
591         // The pool we are based on gets destructed; get owner of pool by creating own one.
592         // No need to call RemoveSfxItemPoolUser(), this is done from the pool's destructor
593         // Base new pool on EditEnginePool; it would also be possible to clone the used
594         // pool if needed, but only text attributes should be used.
595         SfxItemPool* pNewPool = EditEngine::CreatePool();
596 
597         if(pPool)
598         {
599             pNewPool->SetDefaultMetric(pPool->GetMetric(DEF_METRIC));
600         }
601 
602         for(sal_uInt16 n(0); n < aContents.Count(); n++)
603         {
604             // clone ContentInfos for new pool
605             ContentInfo* pOrg = aContents.GetObject(n);
606             DBG_ASSERT(pOrg, "NULL-Pointer in ContentList!");
607 
608             ContentInfo* pNew = new ContentInfo(*pOrg, *pNewPool);
609             aContents.Replace(pNew, n);
610             delete pOrg;
611         }
612 
613         // set local variables
614         pPool = pNewPool;
615         bOwnerOfPool = sal_True;
616     }
617 }
618 
getEditEngineItemPool(SfxItemPool * pPool)619 EditEngineItemPool* getEditEngineItemPool(SfxItemPool* pPool)
620 {
621     EditEngineItemPool* pRetval = dynamic_cast< EditEngineItemPool* >(pPool);
622 
623     while(!pRetval && pPool && pPool->GetSecondaryPool())
624     {
625         pPool = pPool->GetSecondaryPool();
626 
627         if(pPool)
628         {
629             pRetval = dynamic_cast< EditEngineItemPool* >(pPool);
630         }
631     }
632 
633     return pRetval;
634 }
635 
BinTextObject(SfxItemPool * pP)636 BinTextObject::BinTextObject( SfxItemPool* pP ) :
637     EditTextObject( EE_FORMAT_BIN ),
638     SfxItemPoolUser()
639 {
640     nVersion = 0;
641     nMetric = 0xFFFF;
642     nUserType = 0;
643     nObjSettings = 0;
644     pPortionInfo = 0;
645 
646     // #i101239# ensure target is a EditEngineItemPool, else
647     // fallback to pool ownership. This is needed to ensure that at
648     // pool destruction time of an alien pool, the pool is still alive.
649     // When registering would happen at an alien pool which just uses an
650     // EditEngineItemPool as some sub-pool, that pool could already
651     // be decoupled and deleted whcih would lead to crashes.
652     pPool = getEditEngineItemPool(pP);
653 
654     if ( pPool )
655     {
656         bOwnerOfPool = sal_False;
657     }
658     else
659     {
660         pPool = EditEngine::CreatePool();
661         bOwnerOfPool =  sal_True;
662     }
663 
664     if(!bOwnerOfPool && pPool)
665     {
666         // it is sure now that the pool is an EditEngineItemPool
667         pPool->AddSfxItemPoolUser(*this);
668     }
669 
670     bVertical = sal_False;
671     bStoreUnicodeStrings = sal_False;
672     nScriptType = 0;
673 }
674 
BinTextObject(const BinTextObject & r)675 BinTextObject::BinTextObject( const BinTextObject& r ) :
676     EditTextObject( r ),
677     SfxItemPoolUser()
678 {
679     nVersion = r.nVersion;
680     nMetric = r.nMetric;
681     nUserType = r.nUserType;
682     nObjSettings = r.nObjSettings;
683     bVertical = r.bVertical;
684     nScriptType = r.nScriptType;
685     pPortionInfo = NULL;    // PortionInfo nicht kopieren
686     bStoreUnicodeStrings = sal_False;
687 
688     if ( !r.bOwnerOfPool )
689     {
690         // reuse alien pool; this must be a EditEngineItemPool
691         // since there is no other way to construct a BinTextObject
692         // than it's regular constructor where that is ensured
693         pPool = r.pPool;
694         bOwnerOfPool = sal_False;
695     }
696     else
697     {
698         pPool = EditEngine::CreatePool();
699         bOwnerOfPool =  sal_True;
700 
701     }
702 
703     if(!bOwnerOfPool && pPool)
704     {
705         // it is sure now that the pool is an EditEngineItemPool
706         pPool->AddSfxItemPoolUser(*this);
707     }
708 
709     if ( bOwnerOfPool && pPool && r.pPool )
710         pPool->SetDefaultMetric( r.pPool->GetMetric( DEF_METRIC ) );
711 
712     for ( sal_uInt16 n = 0; n < r.aContents.Count(); n++ )
713     {
714         ContentInfo* pOrg = r.aContents.GetObject( n );
715         DBG_ASSERT( pOrg, "NULL-Pointer in ContentList!" );
716         ContentInfo* pNew = new ContentInfo( *pOrg, *pPool );
717         aContents.Insert( pNew, aContents.Count() );
718     }
719 }
720 
~BinTextObject()721 __EXPORT BinTextObject::~BinTextObject()
722 {
723     if(!bOwnerOfPool && pPool)
724     {
725         pPool->RemoveSfxItemPoolUser(*this);
726     }
727 
728     ClearPortionInfo();
729     DeleteContents();
730     if ( bOwnerOfPool )
731     {
732         // Nicht mehr, wegen 1xDefItems.
733         // siehe auch ~EditDoc().
734 //      pPool->ReleaseDefaults( sal_True /* bDelete */ );
735         SfxItemPool::Free(pPool);
736     }
737 }
738 
GetUserType() const739 sal_uInt16 BinTextObject::GetUserType() const
740 {
741     return nUserType;
742 }
743 
SetUserType(sal_uInt16 n)744 void BinTextObject::SetUserType( sal_uInt16 n )
745 {
746     nUserType = n;
747 }
748 
GetObjectSettings() const749 sal_uLong BinTextObject::GetObjectSettings() const
750 {
751     return nObjSettings;
752 }
753 
SetObjectSettings(sal_uLong n)754 void BinTextObject::SetObjectSettings( sal_uLong n )
755 {
756     nObjSettings = n;
757 }
758 
IsVertical() const759 sal_Bool BinTextObject::IsVertical() const
760 {
761     return bVertical;
762 }
763 
SetVertical(sal_Bool b)764 void BinTextObject::SetVertical( sal_Bool b )
765 {
766     if ( b != bVertical )
767     {
768         bVertical = b;
769         ClearPortionInfo();
770     }
771 }
772 
GetScriptType() const773 sal_uInt16 BinTextObject::GetScriptType() const
774 {
775     return nScriptType;
776 }
777 
SetScriptType(sal_uInt16 nType)778 void BinTextObject::SetScriptType( sal_uInt16 nType )
779 {
780     nScriptType = nType;
781 }
782 
783 
DeleteContents()784 void BinTextObject::DeleteContents()
785 {
786     for ( sal_uInt16 n = 0; n < aContents.Count(); n++ )
787     {
788         ContentInfo* p = aContents.GetObject( n );
789         DBG_ASSERT( p, "NULL-Pointer in ContentList!" );
790         delete p;
791     }
792     aContents.Remove( 0, aContents.Count() );
793 }
794 
Clone() const795 EditTextObject* __EXPORT BinTextObject::Clone() const
796 {
797     return new BinTextObject( *this );
798 }
799 
CreateAttrib(const SfxPoolItem & rItem,sal_uInt16 nStart,sal_uInt16 nEnd)800 XEditAttribute* BinTextObject::CreateAttrib( const SfxPoolItem& rItem, sal_uInt16 nStart, sal_uInt16 nEnd )
801 {
802     return MakeXEditAttribute( *pPool, rItem, nStart, nEnd );
803 }
804 
DestroyAttrib(XEditAttribute * pAttr)805 void BinTextObject::DestroyAttrib( XEditAttribute* pAttr )
806 {
807     pPool->Remove( *pAttr->GetItem() );
808     delete pAttr;
809 }
810 
CreateAndInsertContent()811 ContentInfo* BinTextObject::CreateAndInsertContent()
812 {
813     ContentInfo* pC = new ContentInfo( *pPool );
814     aContents.Insert( pC, aContents.Count() );
815     return pC;
816 }
817 
GetParagraphCount() const818 sal_uInt16 BinTextObject::GetParagraphCount() const
819 {
820     return aContents.Count();
821 }
822 
GetText(sal_uInt16 nPara) const823 XubString BinTextObject::GetText( sal_uInt16 nPara ) const
824 {
825     DBG_ASSERT( nPara < aContents.Count(), "BinTextObject::GetText: Absatz existiert nicht!" );
826     if ( nPara < aContents.Count() )
827     {
828         ContentInfo* pC = aContents[ nPara ];
829         return pC->GetText();
830     }
831     return XubString();
832 }
833 
Insert(const EditTextObject & rObj,sal_uInt16 nDestPara)834 void BinTextObject::Insert( const EditTextObject& rObj, sal_uInt16 nDestPara )
835 {
836     DBG_ASSERT( rObj.Which() == EE_FORMAT_BIN, "UTO: Unbekanntes Textobjekt" );
837 
838     const BinTextObject& rBinObj = (const BinTextObject&)rObj;
839 
840     if ( nDestPara > aContents.Count() )
841         nDestPara = aContents.Count();
842 
843     const sal_uInt16 nParas = rBinObj.GetContents().Count();
844     for ( sal_uInt16 nP = 0; nP < nParas; nP++ )
845     {
846         ContentInfo* pC = rBinObj.GetContents()[ nP ];
847         ContentInfo* pNew = new ContentInfo( *pC, *GetPool() );
848         aContents.Insert( pNew, nDestPara+nP );
849     }
850     ClearPortionInfo();
851 }
852 
CreateTextObject(sal_uInt16 nPara,sal_uInt16 nParas) const853 EditTextObject* BinTextObject::CreateTextObject( sal_uInt16 nPara, sal_uInt16 nParas ) const
854 {
855     if ( ( nPara >= aContents.Count() ) || !nParas )
856         return NULL;
857 
858     // Pool nur teilen, wenn von aussen eingestellter Pool.
859     BinTextObject* pObj = new BinTextObject( bOwnerOfPool ? 0 : pPool );
860     if ( bOwnerOfPool && pPool )
861         pObj->GetPool()->SetDefaultMetric( pPool->GetMetric( DEF_METRIC ) );
862 
863     // If complete text is only one ScriptType, this is valid.
864     // If text contains different ScriptTypes, this shouldn't be a problem...
865     pObj->nScriptType = nScriptType;
866 
867     const sal_uInt16 nEndPara = nPara+nParas-1;
868     for ( sal_uInt16 nP = nPara; nP <= nEndPara; nP++ )
869     {
870         ContentInfo* pC = aContents[ nP ];
871         ContentInfo* pNew = new ContentInfo( *pC, *pObj->GetPool() );
872         pObj->GetContents().Insert( pNew, pObj->GetContents().Count() );
873     }
874     return pObj;
875 }
876 
RemoveParagraph(sal_uInt16 nPara)877 void BinTextObject::RemoveParagraph( sal_uInt16 nPara )
878 {
879     DBG_ASSERT( nPara < aContents.Count(), "BinTextObject::GetText: Absatz existiert nicht!" );
880     if ( nPara < aContents.Count() )
881     {
882         ContentInfo* pC = aContents[ nPara ];
883         aContents.Remove( nPara );
884         delete pC;
885         ClearPortionInfo();
886     }
887 }
888 
HasPortionInfo() const889 sal_Bool BinTextObject::HasPortionInfo() const
890 {
891     return pPortionInfo ? sal_True : sal_False;
892 }
893 
ClearPortionInfo()894 void BinTextObject::ClearPortionInfo()
895 {
896     if ( pPortionInfo )
897     {
898         for ( sal_uInt16 n = pPortionInfo->Count(); n; )
899             delete pPortionInfo->GetObject( --n );
900         delete pPortionInfo;
901         pPortionInfo = NULL;
902     }
903 }
904 
HasOnlineSpellErrors() const905 sal_Bool BinTextObject::HasOnlineSpellErrors() const
906 {
907 #ifndef SVX_LIGHT
908     for ( sal_uInt16 n = 0; n < aContents.Count(); n++ )
909     {
910         ContentInfo* p = aContents.GetObject( n );
911         if ( p->GetWrongList() && p->GetWrongList()->Count() )
912             return sal_True;
913     }
914 #endif // !SVX_LIGHT
915     return sal_False;
916 
917 }
918 
HasCharAttribs(sal_uInt16 _nWhich) const919 sal_Bool BinTextObject::HasCharAttribs( sal_uInt16 _nWhich ) const
920 {
921     for ( sal_uInt16 nPara = GetContents().Count(); nPara; )
922     {
923         ContentInfo* pC = GetContents().GetObject( --nPara );
924 
925         sal_uInt16 nAttribs = pC->GetAttribs().Count();
926         if ( nAttribs && !_nWhich )
927             return sal_True;
928 
929         for ( sal_uInt16 nAttr = nAttribs; nAttr; )
930         {
931             XEditAttribute* pX = pC->GetAttribs().GetObject( --nAttr );
932             if ( pX->GetItem()->Which() == _nWhich )
933                 return sal_True;
934         }
935     }
936     return sal_False;
937 }
938 
GetCharAttribs(sal_uInt16 nPara,EECharAttribArray & rLst) const939 void BinTextObject::GetCharAttribs( sal_uInt16 nPara, EECharAttribArray& rLst ) const
940 {
941     rLst.Remove( 0, rLst.Count() );
942     ContentInfo* pC = GetContents().GetObject( nPara );
943     if ( pC )
944     {
945         for ( sal_uInt16 nAttr = 0; nAttr < pC->GetAttribs().Count(); nAttr++ )
946         {
947             XEditAttribute* pAttr = pC->GetAttribs().GetObject( nAttr );
948             EECharAttrib aEEAttr;
949             aEEAttr.pAttr = pAttr->GetItem();
950             aEEAttr.nPara = nPara;
951             aEEAttr.nStart = pAttr->GetStart();
952             aEEAttr.nEnd = pAttr->GetEnd();
953             rLst.Insert( aEEAttr, rLst.Count() );
954         }
955     }
956 }
957 
MergeParaAttribs(const SfxItemSet & rAttribs,sal_uInt16 nStart,sal_uInt16 nEnd)958 void BinTextObject::MergeParaAttribs( const SfxItemSet& rAttribs, sal_uInt16 nStart, sal_uInt16 nEnd )
959 {
960     sal_Bool bChanged = sal_False;
961 
962     for ( sal_uInt16 nPara = GetContents().Count(); nPara; )
963     {
964         ContentInfo* pC = GetContents().GetObject( --nPara );
965 
966         for ( sal_uInt16 nW = nStart; nW <= nEnd; nW++ )
967         {
968             if ( ( pC->GetParaAttribs().GetItemState( nW, sal_False ) != SFX_ITEM_ON )
969                     && ( rAttribs.GetItemState( nW, sal_False ) == SFX_ITEM_ON ) )
970             {
971                 pC->GetParaAttribs().Put( rAttribs.Get( nW ) );
972                 bChanged = sal_True;
973             }
974         }
975     }
976 
977     if ( bChanged )
978         ClearPortionInfo();
979 }
980 
IsFieldObject() const981 sal_Bool BinTextObject::IsFieldObject() const
982 {
983     return BinTextObject::GetField() ? sal_True : sal_False;
984 }
985 
GetField() const986 const SvxFieldItem* BinTextObject::GetField() const
987 {
988     if ( GetContents().Count() == 1 )
989     {
990         ContentInfo* pC = GetContents()[0];
991         if ( pC->GetText().Len() == 1 )
992         {
993             sal_uInt16 nAttribs = pC->GetAttribs().Count();
994             for ( sal_uInt16 nAttr = nAttribs; nAttr; )
995             {
996                 XEditAttribute* pX = pC->GetAttribs().GetObject( --nAttr );
997                 if ( pX->GetItem()->Which() == EE_FEATURE_FIELD )
998                     return (const SvxFieldItem*)pX->GetItem();
999             }
1000         }
1001     }
1002     return 0;
1003 }
1004 
HasField(TypeId aType) const1005 sal_Bool BinTextObject::HasField( TypeId aType ) const
1006 {
1007     sal_uInt16 nParagraphs = GetContents().Count();
1008     for ( sal_uInt16 nPara = 0; nPara < nParagraphs; nPara++ )
1009     {
1010         ContentInfo* pC = GetContents().GetObject( nPara );
1011         sal_uInt16 nAttrs = pC->GetAttribs().Count();
1012         for ( sal_uInt16 nAttr = 0; nAttr < nAttrs; nAttr++ )
1013         {
1014             XEditAttribute* pAttr = pC->GetAttribs()[nAttr];
1015             if ( pAttr->GetItem()->Which() == EE_FEATURE_FIELD )
1016             {
1017                 if ( !aType )
1018                     return sal_True;
1019 
1020                 const SvxFieldData* pFldData = ((const SvxFieldItem*)pAttr->GetItem())->GetField();
1021                 if ( pFldData && pFldData->IsA( aType ) )
1022                     return sal_True;
1023             }
1024         }
1025     }
1026     return sal_False;
1027 }
1028 
GetParaAttribs(sal_uInt16 nPara) const1029 SfxItemSet BinTextObject::GetParaAttribs( sal_uInt16 nPara ) const
1030 {
1031     ContentInfo* pC = GetContents().GetObject( nPara );
1032     return pC->GetParaAttribs();
1033 }
1034 
SetParaAttribs(sal_uInt16 nPara,const SfxItemSet & rAttribs)1035 void BinTextObject::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rAttribs )
1036 {
1037     ContentInfo* pC = GetContents().GetObject( nPara );
1038     pC->GetParaAttribs().Set( rAttribs );
1039     ClearPortionInfo();
1040 }
1041 
RemoveCharAttribs(sal_uInt16 _nWhich)1042 sal_Bool BinTextObject::RemoveCharAttribs( sal_uInt16 _nWhich )
1043 {
1044     sal_Bool bChanged = sal_False;
1045 
1046     for ( sal_uInt16 nPara = GetContents().Count(); nPara; )
1047     {
1048         ContentInfo* pC = GetContents().GetObject( --nPara );
1049 
1050         for ( sal_uInt16 nAttr = pC->GetAttribs().Count(); nAttr; )
1051         {
1052             XEditAttribute* pAttr = pC->GetAttribs().GetObject( --nAttr );
1053             if ( !_nWhich || ( pAttr->GetItem()->Which() == _nWhich ) )
1054             {
1055                 pC->GetAttribs().Remove( nAttr );
1056                 DestroyAttrib( pAttr );
1057                 bChanged = sal_True;
1058             }
1059         }
1060     }
1061 
1062     if ( bChanged )
1063         ClearPortionInfo();
1064 
1065     return bChanged;
1066 }
1067 
RemoveParaAttribs(sal_uInt16 _nWhich)1068 sal_Bool BinTextObject::RemoveParaAttribs( sal_uInt16 _nWhich )
1069 {
1070     sal_Bool bChanged = sal_False;
1071 
1072     for ( sal_uInt16 nPara = GetContents().Count(); nPara; )
1073     {
1074         ContentInfo* pC = GetContents().GetObject( --nPara );
1075 
1076         if ( !_nWhich )
1077         {
1078             if( pC->GetParaAttribs().Count() )
1079                 bChanged = sal_True;
1080             pC->GetParaAttribs().ClearItem();
1081         }
1082         else
1083         {
1084             if ( pC->GetParaAttribs().GetItemState( _nWhich ) == SFX_ITEM_ON )
1085             {
1086                 pC->GetParaAttribs().ClearItem( _nWhich );
1087                 bChanged = sal_True;
1088             }
1089         }
1090     }
1091 
1092     if ( bChanged )
1093         ClearPortionInfo();
1094 
1095     return bChanged;
1096 }
1097 
HasStyleSheet(const XubString & rName,SfxStyleFamily eFamily) const1098 sal_Bool BinTextObject::HasStyleSheet( const XubString& rName, SfxStyleFamily eFamily ) const
1099 {
1100     sal_uInt16 nParagraphs = GetContents().Count();
1101     for ( sal_uInt16 nPara = 0; nPara < nParagraphs; nPara++ )
1102     {
1103         ContentInfo* pC = GetContents().GetObject( nPara );
1104         if ( ( pC->GetFamily() == eFamily ) && ( pC->GetStyle() == rName ) )
1105             return sal_True;
1106     }
1107     return sal_False;
1108 }
1109 
GetStyleSheet(sal_uInt16 nPara,XubString & rName,SfxStyleFamily & rFamily) const1110 void BinTextObject::GetStyleSheet( sal_uInt16 nPara, XubString& rName, SfxStyleFamily& rFamily ) const
1111 {
1112     if ( nPara < aContents.Count() )
1113     {
1114         ContentInfo* pC = aContents[ nPara ];
1115         rName = pC->GetStyle();
1116         rFamily = pC->GetFamily();
1117     }
1118 }
1119 
SetStyleSheet(sal_uInt16 nPara,const XubString & rName,const SfxStyleFamily & rFamily)1120 void BinTextObject::SetStyleSheet( sal_uInt16 nPara, const XubString& rName, const SfxStyleFamily& rFamily )
1121 {
1122     if ( nPara < aContents.Count() )
1123     {
1124         ContentInfo* pC = aContents[ nPara ];
1125         pC->GetStyle() = rName;
1126         pC->GetFamily() = rFamily;
1127     }
1128 }
1129 
ImpChangeStyleSheets(const XubString & rOldName,SfxStyleFamily eOldFamily,const XubString & rNewName,SfxStyleFamily eNewFamily)1130 sal_Bool BinTextObject::ImpChangeStyleSheets(
1131                     const XubString& rOldName, SfxStyleFamily eOldFamily,
1132                     const XubString& rNewName, SfxStyleFamily eNewFamily )
1133 {
1134     const sal_uInt16 nParagraphs = GetContents().Count();
1135     sal_Bool bChanges = sal_False;
1136 
1137     for ( sal_uInt16 nPara = 0; nPara < nParagraphs; nPara++ )
1138     {
1139         ContentInfo* pC = GetContents().GetObject( nPara );
1140         if ( pC->GetFamily() == eOldFamily )
1141         {
1142             if ( pC->GetStyle() == rOldName )
1143             {
1144                 pC->GetStyle() = rNewName;
1145                 pC->GetFamily() = eNewFamily;
1146                 bChanges = sal_True;
1147             }
1148         }
1149     }
1150     return bChanges;
1151 }
1152 
ChangeStyleSheets(const XubString & rOldName,SfxStyleFamily eOldFamily,const XubString & rNewName,SfxStyleFamily eNewFamily)1153 sal_Bool __EXPORT BinTextObject::ChangeStyleSheets(
1154                     const XubString& rOldName, SfxStyleFamily eOldFamily,
1155                     const XubString& rNewName, SfxStyleFamily eNewFamily )
1156 {
1157     sal_Bool bChanges = ImpChangeStyleSheets( rOldName, eOldFamily, rNewName, eNewFamily );
1158     if ( bChanges )
1159         ClearPortionInfo();
1160 
1161     return bChanges;
1162 }
1163 
ChangeStyleSheetName(SfxStyleFamily eFamily,const XubString & rOldName,const XubString & rNewName)1164 void __EXPORT BinTextObject::ChangeStyleSheetName( SfxStyleFamily eFamily,
1165                 const XubString& rOldName, const XubString& rNewName )
1166 {
1167     ImpChangeStyleSheets( rOldName, eFamily, rNewName, eFamily );
1168 }
1169 
StoreData(SvStream & rOStream) const1170 void __EXPORT BinTextObject::StoreData( SvStream& rOStream ) const
1171 {
1172     sal_uInt16 nVer = 602;
1173     rOStream << nVer;
1174 
1175     rOStream << bOwnerOfPool;
1176 
1177     // Erst den Pool speichern, spaeter nur noch Surregate
1178     if ( bOwnerOfPool )
1179     {
1180         GetPool()->SetFileFormatVersion( SOFFICE_FILEFORMAT_50 );
1181         GetPool()->Store( rOStream );
1182     }
1183 
1184     // Aktuelle Zeichensatz speichern...
1185     // #90477# GetSOStoreTextEncoding: Bug in 5.2, when default char set is multi byte text encoding
1186     rtl_TextEncoding eEncoding = GetSOStoreTextEncoding( gsl_getSystemTextEncoding(), (sal_uInt16) rOStream.GetVersion() );
1187     rOStream << (sal_uInt16) eEncoding;
1188 
1189     // Die Anzahl der Absaetze...
1190     sal_uInt16 nParagraphs = GetContents().Count();
1191     rOStream << nParagraphs;
1192 
1193     char cFeatureConverted = ByteString( CH_FEATURE, eEncoding ).GetChar(0);
1194 
1195     // Die einzelnen Absaetze...
1196     for ( sal_uInt16 nPara = 0; nPara < nParagraphs; nPara++ )
1197     {
1198         ContentInfo* pC = GetContents().GetObject( nPara );
1199 
1200         // Text...
1201         ByteString aText( pC->GetText(), eEncoding );
1202 
1203         // Symbols?
1204         sal_Bool bSymbolPara = sal_False;
1205         if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON )
1206         {
1207             const SvxFontItem& rFontItem = (const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO );
1208             if ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
1209             {
1210                 aText = ByteString( pC->GetText(), RTL_TEXTENCODING_SYMBOL );
1211                 bSymbolPara = sal_True;
1212             }
1213         }
1214         for ( sal_uInt16 nA = 0; nA < pC->GetAttribs().Count(); nA++ )
1215         {
1216             XEditAttribute* pAttr = pC->GetAttribs().GetObject( nA );
1217 
1218             if ( pAttr->GetItem()->Which() == EE_CHAR_FONTINFO )
1219             {
1220                 const SvxFontItem& rFontItem = (const SvxFontItem&)*pAttr->GetItem();
1221                 if ( ( !bSymbolPara && ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) )
1222                       || ( bSymbolPara && ( rFontItem.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) ) )
1223                 {
1224                     // Not correctly converted
1225                     String aPart( pC->GetText(), pAttr->GetStart(), pAttr->GetEnd() - pAttr->GetStart() );
1226                     ByteString aNew( aPart, rFontItem.GetCharSet() );
1227                     aText.Erase( pAttr->GetStart(), pAttr->GetEnd() - pAttr->GetStart() );
1228                     aText.Insert( aNew, pAttr->GetStart() );
1229                 }
1230 
1231                 // #88414# Convert StarSymbol back to StarBats
1232                 FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
1233                 if ( hConv )
1234                 {
1235                     // Don't create a new Attrib with StarBats font, MBR changed the
1236                     // SvxFontItem::Store() to store StarBats instead of StarSymbol!
1237                     for ( sal_uInt16 nChar = pAttr->GetStart(); nChar < pAttr->GetEnd(); nChar++ )
1238                     {
1239                         sal_Unicode cOld = pC->GetText().GetChar( nChar );
1240                         char cConv = ByteString::ConvertFromUnicode( ConvertFontToSubsFontChar( hConv, cOld ), RTL_TEXTENCODING_SYMBOL );
1241                         if ( cConv )
1242                             aText.SetChar( nChar, cConv );
1243                     }
1244 
1245                     DestroyFontToSubsFontConverter( hConv );
1246                 }
1247             }
1248         }
1249 
1250         // #88414# Convert StarSymbol back to StarBats
1251         // StarSymbol as paragraph attribute or in StyleSheet?
1252 
1253         FontToSubsFontConverter hConv = NULL;
1254         if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON )
1255         {
1256             hConv = CreateFontToSubsFontConverter( ((const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO )).GetFamilyName(), FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
1257         }
1258 /* cl removed because not needed anymore since binfilter
1259 
1260         else if ( pC->GetStyle().Len() && pC->GetLoadStoreTempInfos() )
1261         {
1262             hConv = pC->GetLoadStoreTempInfos()->hOldSymbolConv_Store;
1263         }
1264 */
1265         if ( hConv )
1266         {
1267             for ( sal_uInt16 nChar = 0; nChar < pC->GetText().Len(); nChar++ )
1268             {
1269                 if ( !pC->GetAttribs().FindAttrib( EE_CHAR_FONTINFO, nChar ) )
1270                 {
1271                     sal_Unicode cOld = pC->GetText().GetChar( nChar );
1272                     char cConv = ByteString::ConvertFromUnicode( ConvertFontToSubsFontChar( hConv, cOld ), RTL_TEXTENCODING_SYMBOL );
1273                     if ( cConv )
1274                         aText.SetChar( nChar, cConv );
1275                 }
1276             }
1277 
1278             DestroyFontToSubsFontConverter( hConv );
1279 
1280         }
1281 
1282 
1283         // Convert CH_FEATURE to CH_FEATURE_OLD
1284         aText.SearchAndReplaceAll( cFeatureConverted, CH_FEATURE_OLD );
1285         rOStream.WriteByteString( aText );
1286 
1287         // StyleName und Family...
1288         rOStream.WriteByteString( ByteString( pC->GetStyle(), eEncoding ) );
1289         rOStream << (sal_uInt16)pC->GetFamily();
1290 
1291         // Absatzattribute...
1292         pC->GetParaAttribs().Store( rOStream );
1293 
1294         // Die Anzahl der Attribute...
1295         sal_uInt16 nAttribs = pC->GetAttribs().Count();
1296         rOStream << nAttribs;
1297 
1298         // Und die einzelnen Attribute
1299         // Items als Surregate => immer 8 Byte pro Attrib
1300         // Which = 2; Surregat = 2; Start = 2; End = 2;
1301         for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
1302         {
1303             XEditAttribute* pX = pC->GetAttribs().GetObject( nAttr );
1304 
1305             rOStream << pX->GetItem()->Which();
1306             GetPool()->StoreSurrogate( rOStream, pX->GetItem() );
1307             rOStream << pX->GetStart();
1308             rOStream << pX->GetEnd();
1309         }
1310     }
1311 
1312     // Ab 400:
1313     rOStream << nMetric;
1314 
1315     // Ab 600
1316     rOStream << nUserType;
1317     rOStream << nObjSettings;
1318 
1319     // Ab 601
1320     rOStream << bVertical;
1321 
1322     // Ab 602
1323     rOStream << nScriptType;
1324 
1325     rOStream << bStoreUnicodeStrings;
1326     if ( bStoreUnicodeStrings )
1327     {
1328         for ( sal_uInt16 nPara = 0; nPara < nParagraphs; nPara++ )
1329         {
1330             ContentInfo* pC = GetContents().GetObject( nPara );
1331             sal_uInt16 nL = pC->GetText().Len();
1332             rOStream << nL;
1333             rOStream.Write( pC->GetText().GetBuffer(), nL*sizeof(sal_Unicode) );
1334 
1335             // #91575# StyleSheetName must be Unicode too!
1336             // Copy/Paste from EA3 to BETA or from BETA to EA3 not possible, not needed...
1337             // If needed, change nL back to sal_uLong and increase version...
1338             nL = pC->GetStyle().Len();
1339             rOStream << nL;
1340             rOStream.Write( pC->GetStyle().GetBuffer(), nL*sizeof(sal_Unicode) );
1341         }
1342     }
1343 }
1344 
CreateData(SvStream & rIStream)1345 void __EXPORT BinTextObject::CreateData( SvStream& rIStream )
1346 {
1347     rIStream >> nVersion;
1348 
1349     // Das Textobject wurde erstmal mit der aktuellen Einstellung
1350     // von pTextObjectPool erzeugt.
1351     sal_Bool bOwnerOfCurrent = bOwnerOfPool;
1352     rIStream >> bOwnerOfPool;
1353 
1354     if ( bOwnerOfCurrent && !bOwnerOfPool )
1355     {
1356         // Es wurde ein globaler Pool verwendet, mir jetzt nicht uebergeben,
1357         // aber ich brauche ihn!
1358         DBG_ERROR( "Man gebe mir den globalen TextObjectPool!" );
1359         return;
1360     }
1361     else if ( !bOwnerOfCurrent && bOwnerOfPool )
1362     {
1363         // Es soll ein globaler Pool verwendet werden, aber dieses
1364         // Textobject hat einen eigenen.
1365         pPool = EditEngine::CreatePool();
1366     }
1367 
1368     if ( bOwnerOfPool )
1369         GetPool()->Load( rIStream );
1370 
1371     // CharSet, in dem gespeichert wurde:
1372     sal_uInt16 nCharSet;
1373     rIStream >> nCharSet;
1374 
1375     rtl_TextEncoding eSrcEncoding = GetSOLoadTextEncoding( (rtl_TextEncoding)nCharSet, (sal_uInt16)rIStream.GetVersion() );
1376 
1377     // Die Anzahl der Absaetze...
1378     sal_uInt16 nParagraphs;
1379     rIStream >> nParagraphs;
1380 
1381     // Die einzelnen Absaetze...
1382     for ( sal_uLong nPara = 0; nPara < nParagraphs; nPara++ )
1383     {
1384         ContentInfo* pC = CreateAndInsertContent();
1385 
1386         // Der Text...
1387         ByteString aByteString;
1388         rIStream.ReadByteString( aByteString );
1389         pC->GetText() = String( aByteString, eSrcEncoding );
1390 
1391         // StyleName und Family...
1392         rIStream.ReadByteString( pC->GetStyle(), eSrcEncoding );
1393         sal_uInt16 nStyleFamily;
1394         rIStream >> nStyleFamily;
1395         pC->GetFamily() = (SfxStyleFamily)nStyleFamily;
1396 
1397         // Absatzattribute...
1398         pC->GetParaAttribs().Load( rIStream );
1399 
1400         // Die Anzahl der Attribute...
1401         sal_uInt16 nAttribs;
1402         rIStream >> nAttribs;
1403 
1404         // Und die einzelnen Attribute
1405         // Items als Surregate => immer 8 Byte pro Attrib
1406         // Which = 2; Surregat = 2; Start = 2; End = 2;
1407         sal_uInt16 nAttr;
1408         for ( nAttr = 0; nAttr < nAttribs; nAttr++ )
1409         {
1410             sal_uInt16 _nWhich, nStart, nEnd;
1411             const SfxPoolItem* pItem;
1412 
1413             rIStream >> _nWhich;
1414             _nWhich = pPool->GetNewWhich( _nWhich );
1415             pItem = pPool->LoadSurrogate( rIStream, _nWhich, 0 );
1416             rIStream >> nStart;
1417             rIStream >> nEnd;
1418             if ( pItem )
1419             {
1420                 if ( pItem->Which() == EE_FEATURE_NOTCONV )
1421                 {
1422                     pC->GetText().SetChar( nStart, ByteString::ConvertToUnicode( aByteString.GetChar( nStart ), ((SvxCharSetColorItem*)pItem)->GetCharSet() ) );
1423                 }
1424                 else
1425                 {
1426                     XEditAttribute* pAttr = new XEditAttribute( *pItem, nStart, nEnd );
1427                     pC->GetAttribs().Insert( pAttr, pC->GetAttribs().Count() );
1428 
1429                     if ( ( _nWhich >= EE_FEATURE_START ) && ( _nWhich <= EE_FEATURE_END ) )
1430                     {
1431                         // Convert CH_FEATURE to CH_FEATURE_OLD
1432                         DBG_ASSERT( (sal_uInt8) aByteString.GetChar( nStart ) == CH_FEATURE_OLD, "CreateData: CH_FEATURE expected!" );
1433                         if ( (sal_uInt8) aByteString.GetChar( nStart ) == CH_FEATURE_OLD )
1434                             pC->GetText().SetChar( nStart, CH_FEATURE );
1435                     }
1436                 }
1437             }
1438         }
1439 
1440         // But check for paragraph and character symbol attribs here,
1441         // FinishLoad will not be called in OpenOffice Calc, no StyleSheets...
1442 
1443         sal_Bool bSymbolPara = sal_False;
1444         if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON )
1445         {
1446             const SvxFontItem& rFontItem = (const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO );
1447             if ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
1448             {
1449                 pC->GetText() = String( aByteString, RTL_TEXTENCODING_SYMBOL );
1450                 bSymbolPara = sal_True;
1451             }
1452         }
1453 
1454         for ( nAttr = pC->GetAttribs().Count(); nAttr; )
1455         {
1456             XEditAttribute* pAttr = pC->GetAttribs().GetObject( --nAttr );
1457             if ( pAttr->GetItem()->Which() == EE_CHAR_FONTINFO )
1458             {
1459                 const SvxFontItem& rFontItem = (const SvxFontItem&)*pAttr->GetItem();
1460                 if ( ( !bSymbolPara && ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) )
1461                       || ( bSymbolPara && ( rFontItem.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) ) )
1462                 {
1463                     // Not correctly converted
1464                     ByteString aPart( aByteString, pAttr->GetStart(), pAttr->GetEnd()-pAttr->GetStart() );
1465                     String aNew( aPart, rFontItem.GetCharSet() );
1466                     pC->GetText().Erase( pAttr->GetStart(), pAttr->GetEnd()-pAttr->GetStart() );
1467                     pC->GetText().Insert( aNew, pAttr->GetStart() );
1468                 }
1469 
1470                 // #88414# Convert StarMath and StarBats to StarSymbol
1471                 FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_IMPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
1472                 if ( hConv )
1473                 {
1474                     SvxFontItem aNewFontItem( rFontItem );
1475                     aNewFontItem.SetFamilyName( GetFontToSubsFontName( hConv ) );
1476 
1477                     pC->GetAttribs().Remove( nAttr );
1478                     XEditAttribute* pNewAttr = CreateAttrib( aNewFontItem, pAttr->GetStart(), pAttr->GetEnd() );
1479                     pC->GetAttribs().Insert( pNewAttr, nAttr );
1480                     DestroyAttrib( pAttr );
1481 
1482                     for ( sal_uInt16 nChar = pNewAttr->GetStart(); nChar < pNewAttr->GetEnd(); nChar++ )
1483                     {
1484                         sal_Unicode cOld = pC->GetText().GetChar( nChar );
1485                         DBG_ASSERT( cOld >= 0xF000, "cOld not converted?!" );
1486                         sal_Unicode cConv = ConvertFontToSubsFontChar( hConv, cOld );
1487                         if ( cConv )
1488                             pC->GetText().SetChar( nChar, cConv );
1489                     }
1490 
1491                     DestroyFontToSubsFontConverter( hConv );
1492                 }
1493             }
1494         }
1495 
1496 
1497         // #88414# Convert StarMath and StarBats to StarSymbol
1498         // Maybe old symbol font as paragraph attribute?
1499         if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SFX_ITEM_ON )
1500         {
1501             const SvxFontItem& rFontItem = (const SvxFontItem&)pC->GetParaAttribs().Get( EE_CHAR_FONTINFO );
1502             FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_IMPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
1503             if ( hConv )
1504             {
1505                 SvxFontItem aNewFontItem( rFontItem );
1506                 aNewFontItem.SetFamilyName( GetFontToSubsFontName( hConv ) );
1507                 pC->GetParaAttribs().Put( aNewFontItem );
1508 
1509                 for ( sal_uInt16 nChar = 0; nChar < pC->GetText().Len(); nChar++ )
1510                 {
1511                     if ( !pC->GetAttribs().FindAttrib( EE_CHAR_FONTINFO, nChar ) )
1512                     {
1513                         sal_Unicode cOld = pC->GetText().GetChar( nChar );
1514                         DBG_ASSERT( cOld >= 0xF000, "cOld not converted?!" );
1515                         sal_Unicode cConv = ConvertFontToSubsFontChar( hConv, cOld );
1516                         if ( cConv )
1517                             pC->GetText().SetChar( nChar, cConv );
1518                     }
1519                 }
1520 
1521                 DestroyFontToSubsFontConverter( hConv );
1522             }
1523         }
1524     }
1525 
1526     // Ab 400 auch die DefMetric:
1527     if ( nVersion >= 400 )
1528     {
1529         sal_uInt16 nTmpMetric;
1530         rIStream >> nTmpMetric;
1531         if ( nVersion >= 401 )
1532         {
1533             // In der 400 gab es noch einen Bug bei Textobjekten mit eigenem
1534             // Pool, deshalb erst ab 401 auswerten.
1535             nMetric = nTmpMetric;
1536             if ( bOwnerOfPool && pPool && ( nMetric != 0xFFFF ) )
1537                 pPool->SetDefaultMetric( (SfxMapUnit)nMetric );
1538         }
1539     }
1540 
1541     if ( nVersion >= 600 )
1542     {
1543         rIStream >> nUserType;
1544         rIStream >> nObjSettings;
1545     }
1546 
1547     if ( nVersion >= 601 )
1548     {
1549         rIStream >> bVertical;
1550     }
1551 
1552     if ( nVersion >= 602 )
1553     {
1554         rIStream >> nScriptType;
1555 
1556         sal_Bool bUnicodeStrings;
1557         rIStream >> bUnicodeStrings;
1558         if ( bUnicodeStrings )
1559         {
1560             for ( sal_uInt16 nPara = 0; nPara < nParagraphs; nPara++ )
1561             {
1562                 ContentInfo* pC = GetContents().GetObject( nPara );
1563                 sal_uInt16 nL;
1564 
1565                 // Text
1566                 rIStream >> nL;
1567                 if ( nL )
1568                 {
1569                     pC->GetText().AllocBuffer( nL );
1570                     rIStream.Read( pC->GetText().GetBufferAccess(), nL*sizeof(sal_Unicode) );
1571                     pC->GetText().ReleaseBufferAccess( (sal_uInt16)nL );
1572                 }
1573 
1574                 // StyleSheetName
1575                 rIStream >> nL;
1576                 if ( nL )
1577                 {
1578                     pC->GetStyle().AllocBuffer( nL );
1579                     rIStream.Read( pC->GetStyle().GetBufferAccess(), nL*sizeof(sal_Unicode) );
1580                     pC->GetStyle().ReleaseBufferAccess( (sal_uInt16)nL );
1581                 }
1582             }
1583         }
1584     }
1585 
1586 
1587     // Ab 500 werden die Tabs anders interpretiert: TabPos + LI, vorher nur TabPos.
1588     // Wirkt nur wenn auch Tab-Positionen eingestellt wurden, nicht beim DefTab.
1589     if ( nVersion < 500 )
1590     {
1591         for ( sal_uInt16 n = 0; n < aContents.Count(); n++ )
1592         {
1593             ContentInfo* pC = aContents.GetObject( n );
1594             const SvxLRSpaceItem& rLRSpace = (const SvxLRSpaceItem&) pC->GetParaAttribs().Get( EE_PARA_LRSPACE );
1595             if ( rLRSpace.GetTxtLeft() && ( pC->GetParaAttribs().GetItemState( EE_PARA_TABS ) == SFX_ITEM_ON ) )
1596             {
1597                 const SvxTabStopItem& rTabs = (const SvxTabStopItem&) pC->GetParaAttribs().Get( EE_PARA_TABS );
1598                 SvxTabStopItem aNewTabs( 0, 0, SVX_TAB_ADJUST_LEFT, EE_PARA_TABS );
1599                 for ( sal_uInt16 t = 0; t < rTabs.Count(); t++ )
1600                 {
1601                     const SvxTabStop& rT = rTabs[ t ];
1602                     aNewTabs.Insert( SvxTabStop( rT.GetTabPos() - rLRSpace.GetTxtLeft(),
1603                                 rT.GetAdjustment(), rT.GetDecimal(), rT.GetFill() ) );
1604                 }
1605                 pC->GetParaAttribs().Put( aNewTabs );
1606             }
1607         }
1608     }
1609 }
1610 
GetVersion() const1611 sal_uInt16 BinTextObject::GetVersion() const
1612 {
1613     return nVersion;
1614 }
1615 
operator ==(const BinTextObject & rCompare) const1616 bool BinTextObject::operator==( const BinTextObject& rCompare ) const
1617 {
1618     if( this == &rCompare )
1619         return true;
1620 
1621     if( ( aContents.Count() != rCompare.aContents.Count() ) ||
1622             ( pPool != rCompare.pPool ) ||
1623             ( nMetric != rCompare.nMetric ) ||
1624             ( nUserType!= rCompare.nUserType ) ||
1625             ( nScriptType != rCompare.nScriptType ) ||
1626             ( bVertical != rCompare.bVertical ) )
1627         return false;
1628 
1629     sal_uInt16 n;
1630     for( n = 0; n < aContents.Count(); n++ )
1631     {
1632         if( !( *aContents.GetObject( n ) == *rCompare.aContents.GetObject( n ) ) )
1633             return false;
1634     }
1635 
1636     return true;
1637 }
1638 
1639 // #i102062#
isWrongListEqual(const BinTextObject & rCompare) const1640 bool BinTextObject::isWrongListEqual(const BinTextObject& rCompare) const
1641 {
1642     if(GetContents().Count() != rCompare.GetContents().Count())
1643     {
1644         return false;
1645     }
1646 
1647     for(sal_uInt16 a(0); a < GetContents().Count(); a++)
1648     {
1649         const ContentInfo& rCandA(*GetContents().GetObject(a));
1650         const ContentInfo& rCandB(*rCompare.GetContents().GetObject(a));
1651 
1652         if(!rCandA.isWrongListEqual(rCandB))
1653         {
1654             return false;
1655         }
1656     }
1657 
1658     return true;
1659 }
1660 
1661 #define CHARSETMARKER   0x9999
1662 
CreateData300(SvStream & rIStream)1663 void __EXPORT BinTextObject::CreateData300( SvStream& rIStream )
1664 {
1665     // Fuer Aufwaertskompatibilitaet.
1666 
1667     // Erst den Pool laden...
1668     // Ist in der 300 immer gespeichert worden!
1669     GetPool()->Load( rIStream );
1670 
1671     // Die Anzahl der Absaetze...
1672     sal_uInt32 nParagraphs;
1673     rIStream >> nParagraphs;
1674 
1675     // Die einzelnen Absaetze...
1676     for ( sal_uLong nPara = 0; nPara < nParagraphs; nPara++ )
1677     {
1678         ContentInfo* pC = CreateAndInsertContent();
1679 
1680         // Der Text...
1681         rIStream.ReadByteString( pC->GetText() );
1682 
1683         // StyleName und Family...
1684         rIStream.ReadByteString( pC->GetStyle() );
1685         sal_uInt16 nStyleFamily;
1686         rIStream >> nStyleFamily;
1687         pC->GetFamily() = (SfxStyleFamily)nStyleFamily;
1688 
1689         // Absatzattribute...
1690         pC->GetParaAttribs().Load( rIStream );
1691 
1692         // Die Anzahl der Attribute...
1693         sal_uInt32 nAttribs;
1694         rIStream >> nAttribs;
1695 
1696         // Und die einzelnen Attribute
1697         // Items als Surregate => immer 8 Byte pro Attrib
1698         // Which = 2; Surregat = 2; Start = 2; End = 2;
1699         for ( sal_uLong nAttr = 0; nAttr < nAttribs; nAttr++ )
1700         {
1701             sal_uInt16 _nWhich, nStart, nEnd;
1702             const SfxPoolItem* pItem;
1703 
1704             rIStream >> _nWhich;
1705             _nWhich = pPool->GetNewWhich( _nWhich );
1706             pItem = pPool->LoadSurrogate( rIStream, _nWhich, 0 );
1707             rIStream >> nStart;
1708             rIStream >> nEnd;
1709             if ( pItem )
1710             {
1711                 XEditAttribute* pAttr = new XEditAttribute( *pItem, nStart, nEnd );
1712                 pC->GetAttribs().Insert( pAttr, pC->GetAttribs().Count() );
1713             }
1714         }
1715     }
1716 
1717     // Prueffen, ob ein Zeichensatz gespeichert wurde
1718     sal_uInt16 nCharSetMarker;
1719     rIStream >> nCharSetMarker;
1720     if ( nCharSetMarker == CHARSETMARKER )
1721     {
1722         sal_uInt16 nCharSet;
1723         rIStream >> nCharSet;
1724     }
1725 }
1726