Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <comphelper/string.hxx>
21 : #include <rtl/strbuf.hxx>
22 : #include <vcl/wrkwin.hxx>
23 : #include <vcl/dialog.hxx>
24 : #include <vcl/msgbox.hxx>
25 : #include <vcl/svapp.hxx>
26 :
27 : #include <tools/stream.hxx>
28 :
29 : #include "editeng/fieldupdater.hxx"
30 : #include "editeng/macros.hxx"
31 : #include "editeng/section.hxx"
32 : #include <editobj2.hxx>
33 : #include <editeng/editdata.hxx>
34 : #include <editattr.hxx>
35 : #include <editeng/editeng.hxx>
36 : #include <editeng/fontitem.hxx>
37 : #include <editeng/charsetcoloritem.hxx>
38 : #include <editeng/flditem.hxx>
39 : #include <editeng/lrspitem.hxx>
40 : #include <editeng/tstpitem.hxx>
41 : #include <editeng/bulletitem.hxx>
42 : #include <editeng/numitem.hxx>
43 : #include <editeng/brushitem.hxx>
44 :
45 : #include <vcl/graph.hxx>
46 : #include <svl/intitem.hxx>
47 : #include "svl/sharedstringpool.hxx"
48 : #include <unotools/fontcvt.hxx>
49 : #include <tools/tenccvt.hxx>
50 :
51 : #if DEBUG_EDIT_ENGINE
52 : #include <iostream>
53 : using std::cout;
54 : using std::endl;
55 : #endif
56 :
57 : using namespace com::sun::star;
58 :
59 :
60 :
61 :
62 675844 : XEditAttribute* MakeXEditAttribute( SfxItemPool& rPool, const SfxPoolItem& rItem, sal_uInt16 nStart, sal_uInt16 nEnd )
63 : {
64 : // Create thw new attribute in the pool
65 675844 : const SfxPoolItem& rNew = rPool.Put( rItem );
66 :
67 675844 : XEditAttribute* pNew = new XEditAttribute( rNew, nStart, nEnd );
68 675844 : return pNew;
69 : }
70 :
71 675844 : XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr, sal_uInt16 nS, sal_uInt16 nE )
72 : {
73 675844 : pItem = &rAttr;
74 675844 : nStart = nS;
75 675844 : nEnd = nE;
76 675844 : }
77 :
78 675756 : XEditAttribute::~XEditAttribute()
79 : {
80 675756 : pItem = 0; // belongs to the Pool.
81 675756 : }
82 :
83 0 : bool XEditAttribute::IsFeature() const
84 : {
85 0 : sal_uInt16 nWhich = pItem->Which();
86 0 : return ((nWhich >= EE_FEATURE_START) && (nWhich <= EE_FEATURE_END));
87 : }
88 :
89 0 : void XEditAttribute::SetItem(const SfxPoolItem& rNew)
90 : {
91 0 : pItem = &rNew;
92 0 : }
93 :
94 0 : XParaPortionList::XParaPortionList(
95 : OutputDevice* pRefDev, sal_uLong nPW, sal_uInt16 _nStretchX, sal_uInt16 _nStretchY) :
96 0 : aRefMapMode(pRefDev->GetMapMode()), nStretchX(_nStretchX), nStretchY(_nStretchY)
97 : {
98 0 : nRefDevPtr = reinterpret_cast<sal_uIntPtr>(pRefDev);
99 0 : nPaperWidth = nPW;
100 0 : eRefDevType = pRefDev->GetOutDevType();
101 0 : }
102 :
103 0 : void XParaPortionList::push_back(XParaPortion* p)
104 : {
105 0 : maList.push_back(p);
106 0 : }
107 :
108 0 : const XParaPortion& XParaPortionList::operator [](size_t i) const
109 : {
110 0 : return maList[i];
111 : }
112 :
113 136685 : ContentInfo::ContentInfo( SfxItemPool& rPool ) :
114 : eFamily(SFX_STYLE_FAMILY_PARA),
115 136685 : aParaAttribs(rPool, EE_PARA_START, EE_CHAR_END)
116 : {
117 136685 : }
118 :
119 : // the real Copy constructor is nonsens, since I have to work with another Pool!
120 280612 : ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse ) :
121 : maText(rCopyFrom.maText),
122 : aStyle(rCopyFrom.aStyle),
123 : eFamily(rCopyFrom.eFamily),
124 280612 : aParaAttribs(rPoolToUse, EE_PARA_START, EE_CHAR_END)
125 : {
126 : // this should ensure that the Items end up in the correct Pool!
127 280612 : aParaAttribs.Set( rCopyFrom.GetParaAttribs() );
128 :
129 725706 : for (size_t i = 0; i < rCopyFrom.aAttribs.size(); ++i)
130 : {
131 445094 : const XEditAttribute& rAttr = rCopyFrom.aAttribs[i];
132 : XEditAttribute* pMyAttr = MakeXEditAttribute(
133 445094 : rPoolToUse, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd());
134 445094 : aAttribs.push_back(pMyAttr);
135 : }
136 :
137 280612 : if ( rCopyFrom.GetWrongList() )
138 90612 : mpWrongs.reset(rCopyFrom.GetWrongList()->Clone());
139 280612 : }
140 :
141 833858 : ContentInfo::~ContentInfo()
142 : {
143 416929 : XEditAttributesType::iterator it = aAttribs.begin(), itEnd = aAttribs.end();
144 1092685 : for (; it != itEnd; ++it)
145 675756 : aParaAttribs.GetPool()->Remove(*it->GetItem());
146 416929 : aAttribs.clear();
147 416929 : }
148 :
149 1520 : void ContentInfo::NormalizeString( svl::SharedStringPool& rPool )
150 : {
151 1520 : maText = rPool.intern(OUString(maText.getData()));
152 1520 : }
153 :
154 :
155 561977 : OUString ContentInfo::GetText() const
156 : {
157 561977 : rtl_uString* p = const_cast<rtl_uString*>(maText.getData());
158 561977 : return OUString(p);
159 : }
160 :
161 136685 : void ContentInfo::SetText( const OUString& rStr )
162 : {
163 136685 : maText = svl::SharedString(rStr.pData, NULL);
164 136685 : }
165 :
166 497109 : const WrongList* ContentInfo::GetWrongList() const
167 : {
168 497109 : return mpWrongs.get();
169 : }
170 :
171 34848 : void ContentInfo::SetWrongList( WrongList* p )
172 : {
173 34848 : mpWrongs.reset(p);
174 34848 : }
175 :
176 : // #i102062#
177 2145 : bool ContentInfo::isWrongListEqual(const ContentInfo& rCompare) const
178 : {
179 2145 : if(GetWrongList() == rCompare.GetWrongList())
180 2145 : return true;
181 :
182 0 : if(!GetWrongList() || !rCompare.GetWrongList())
183 0 : return false;
184 :
185 0 : return (*GetWrongList() == *rCompare.GetWrongList());
186 : }
187 :
188 : #if DEBUG_EDIT_ENGINE
189 : void ContentInfo::Dump() const
190 : {
191 : cout << "--" << endl;
192 : cout << "text: '" << OUString(const_cast<rtl_uString*>(maText.getData())) << "'" << endl;
193 : cout << "style: '" << aStyle << "'" << endl;
194 :
195 : XEditAttributesType::const_iterator it = aAttribs.begin(), itEnd = aAttribs.end();
196 : for (; it != itEnd; ++it)
197 : {
198 : const XEditAttribute& rAttr = *it;
199 : cout << "attribute: " << endl;
200 : cout << " span: [begin=" << rAttr.GetStart() << ", end=" << rAttr.GetEnd() << "]" << endl;
201 : cout << " feature: " << (rAttr.IsFeature() ? "yes":"no") << endl;
202 : }
203 : }
204 : #endif
205 :
206 4587 : bool ContentInfo::operator==( const ContentInfo& rCompare ) const
207 : {
208 13537 : if( (maText == rCompare.maText) &&
209 7934 : (aStyle == rCompare.aStyle ) &&
210 6934 : (aAttribs.size() == rCompare.aAttribs.size()) &&
211 11313 : (eFamily == rCompare.eFamily ) &&
212 3363 : (aParaAttribs == rCompare.aParaAttribs ) )
213 : {
214 19985 : for (size_t i = 0, n = aAttribs.size(); i < n; ++i)
215 : {
216 17470 : if (aAttribs[i] != rCompare.aAttribs[i])
217 116 : return false;
218 : }
219 :
220 2515 : return true;
221 : }
222 :
223 1956 : return false;
224 : }
225 :
226 4587 : bool ContentInfo::operator!=(const ContentInfo& rCompare) const
227 : {
228 4587 : return !operator==(rCompare);
229 : }
230 :
231 120264 : EditTextObject::EditTextObject( SfxItemPool* pPool ) :
232 120264 : mpImpl(new EditTextObjectImpl(this, pPool))
233 : {
234 120264 : }
235 :
236 252708 : EditTextObject::EditTextObject( const EditTextObject& r ) :
237 : SfxItemPoolUser(),
238 252708 : mpImpl(new EditTextObjectImpl(this, *r.mpImpl))
239 : {
240 252708 : }
241 :
242 1117818 : EditTextObject::~EditTextObject()
243 : {
244 372606 : delete mpImpl;
245 745212 : }
246 :
247 166598 : sal_Int32 EditTextObject::GetParagraphCount() const
248 : {
249 166598 : return mpImpl->GetParagraphCount();
250 : }
251 :
252 127516 : OUString EditTextObject::GetText(sal_Int32 nPara) const
253 : {
254 127516 : return mpImpl->GetText(nPara);
255 : }
256 :
257 6 : void EditTextObject::ClearPortionInfo()
258 : {
259 6 : mpImpl->ClearPortionInfo();
260 6 : }
261 :
262 20 : bool EditTextObject::HasOnlineSpellErrors() const
263 : {
264 20 : return mpImpl->HasOnlineSpellErrors();
265 : }
266 :
267 610 : void EditTextObject::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const
268 : {
269 610 : mpImpl->GetCharAttribs(nPara, rLst);
270 610 : }
271 :
272 0 : bool EditTextObject::IsFieldObject() const
273 : {
274 0 : return mpImpl->IsFieldObject();
275 : }
276 :
277 0 : const SvxFieldItem* EditTextObject::GetField() const
278 : {
279 0 : return mpImpl->GetField();
280 : }
281 :
282 2 : const SvxFieldData* EditTextObject::GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const
283 : {
284 2 : return mpImpl->GetFieldData(nPara, nPos, nType);
285 : }
286 :
287 364561 : bool EditTextObject::HasField( sal_Int32 nType ) const
288 : {
289 364561 : return mpImpl->HasField(nType);
290 : }
291 :
292 1892 : const SfxItemSet& EditTextObject::GetParaAttribs(sal_Int32 nPara) const
293 : {
294 1892 : return mpImpl->GetParaAttribs(nPara);
295 : }
296 :
297 0 : bool EditTextObject::RemoveCharAttribs( sal_uInt16 nWhich )
298 : {
299 0 : return mpImpl->RemoveCharAttribs(nWhich);
300 : }
301 :
302 70 : void EditTextObject::GetAllSections( std::vector<editeng::Section>& rAttrs ) const
303 : {
304 70 : mpImpl->GetAllSections(rAttrs);
305 70 : }
306 :
307 32712 : void EditTextObject::GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& eFamily) const
308 : {
309 32712 : mpImpl->GetStyleSheet(nPara, rName, eFamily);
310 32712 : }
311 :
312 0 : void EditTextObject::SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& eFamily)
313 : {
314 0 : mpImpl->SetStyleSheet(nPara, rName, eFamily);
315 0 : }
316 :
317 20580 : bool EditTextObject::ChangeStyleSheets(
318 : const OUString& rOldName, SfxStyleFamily eOldFamily, const OUString& rNewName, SfxStyleFamily eNewFamily)
319 : {
320 20580 : return mpImpl->ChangeStyleSheets(rOldName, eOldFamily, rNewName, eNewFamily);
321 : }
322 :
323 0 : void EditTextObject::ChangeStyleSheetName(
324 : SfxStyleFamily eFamily, const OUString& rOldName, const OUString& rNewName)
325 : {
326 0 : mpImpl->ChangeStyleSheetName(eFamily, rOldName, rNewName);
327 0 : }
328 :
329 48 : editeng::FieldUpdater EditTextObject::GetFieldUpdater()
330 : {
331 48 : return mpImpl->GetFieldUpdater();
332 : }
333 :
334 1328 : void EditTextObject::NormalizeString( svl::SharedStringPool& rPool )
335 : {
336 1328 : mpImpl->NormalizeString(rPool);
337 1328 : }
338 :
339 6 : std::vector<svl::SharedString> EditTextObject::GetSharedStrings() const
340 : {
341 6 : return mpImpl->GetSharedStrings();
342 : }
343 :
344 2 : const SfxItemPool* EditTextObject::GetPool() const
345 : {
346 2 : return mpImpl->GetPool();
347 : }
348 :
349 259000 : sal_uInt16 EditTextObject::GetUserType() const
350 : {
351 259000 : return mpImpl->GetUserType();
352 : }
353 :
354 95626 : void EditTextObject::SetUserType( sal_uInt16 n )
355 : {
356 95626 : mpImpl->SetUserType(n);
357 95626 : }
358 :
359 421185 : bool EditTextObject::IsVertical() const
360 : {
361 421185 : return mpImpl->IsVertical();
362 : }
363 :
364 120346 : void EditTextObject::SetVertical( bool bVertical )
365 : {
366 120346 : return mpImpl->SetVertical(bVertical);
367 : }
368 :
369 0 : sal_uInt16 EditTextObject::GetScriptType() const
370 : {
371 0 : return mpImpl->GetScriptType();
372 : }
373 :
374 :
375 10752 : bool EditTextObject::Store( SvStream& rOStream ) const
376 : {
377 10752 : if ( rOStream.GetError() )
378 0 : return false;
379 :
380 10752 : sal_Size nStartPos = rOStream.Tell();
381 :
382 10752 : sal_uInt16 nWhich = static_cast<sal_uInt16>(EE_FORMAT_BIN);
383 10752 : rOStream.WriteUInt16( nWhich );
384 :
385 10752 : sal_uInt32 nStructSz = 0;
386 10752 : rOStream.WriteUInt32( nStructSz );
387 :
388 10752 : StoreData( rOStream );
389 :
390 10752 : sal_Size nEndPos = rOStream.Tell();
391 10752 : nStructSz = nEndPos - nStartPos - sizeof( nWhich ) - sizeof( nStructSz );
392 10752 : rOStream.Seek( nStartPos + sizeof( nWhich ) );
393 10752 : rOStream.WriteUInt32( nStructSz );
394 10752 : rOStream.Seek( nEndPos );
395 :
396 10752 : return rOStream.GetError() ? false : true;
397 : }
398 :
399 0 : EditTextObject* EditTextObject::Create( SvStream& rIStream, SfxItemPool* pGlobalTextObjectPool )
400 : {
401 0 : sal_Size nStartPos = rIStream.Tell();
402 :
403 : // First check what type of Object...
404 : sal_uInt16 nWhich;
405 0 : rIStream.ReadUInt16( nWhich );
406 :
407 : sal_uInt32 nStructSz;
408 0 : rIStream.ReadUInt32( nStructSz );
409 :
410 0 : if (nWhich != EE_FORMAT_BIN)
411 : {
412 : // Unknown object we no longer support.
413 0 : rIStream.SetError(EE_READWRITE_WRONGFORMAT);
414 0 : return NULL;
415 : }
416 :
417 0 : if ( rIStream.GetError() )
418 0 : return NULL;
419 :
420 0 : EditTextObject* pTxtObj = new EditTextObject(pGlobalTextObjectPool);;
421 0 : pTxtObj->CreateData(rIStream);
422 :
423 : // Make sure that the stream is left at the correct place.
424 0 : sal_Size nFullSz = sizeof( nWhich ) + sizeof( nStructSz ) + nStructSz;
425 0 : rIStream.Seek( nStartPos + nFullSz );
426 0 : return pTxtObj;
427 : }
428 :
429 10752 : void EditTextObject::StoreData( SvStream& rStrm ) const
430 : {
431 10752 : mpImpl->StoreData(rStrm);
432 10752 : }
433 :
434 0 : void EditTextObject::CreateData( SvStream& rStrm )
435 : {
436 0 : mpImpl->CreateData(rStrm);
437 0 : }
438 :
439 252708 : EditTextObject* EditTextObject::Clone() const
440 : {
441 252708 : return new EditTextObject(*this);
442 : }
443 :
444 3960 : bool EditTextObject::operator==( const EditTextObject& rCompare ) const
445 : {
446 3960 : return mpImpl->operator==(*rCompare.mpImpl);
447 : }
448 :
449 : // #i102062#
450 1818 : bool EditTextObject::isWrongListEqual(const EditTextObject& rCompare) const
451 : {
452 1818 : return mpImpl->isWrongListEqual(*rCompare.mpImpl);
453 : }
454 :
455 1386 : void EditTextObject::ObjectInDestruction(const SfxItemPool& rSfxItemPool)
456 : {
457 1386 : mpImpl->ObjectInDestruction(rSfxItemPool);
458 1386 : }
459 :
460 : #if DEBUG_EDIT_ENGINE
461 : void EditTextObject::Dump() const
462 : {
463 : mpImpl->Dump();
464 : }
465 : #endif
466 :
467 : // from SfxItemPoolUser
468 1386 : void EditTextObjectImpl::ObjectInDestruction(const SfxItemPool& rSfxItemPool)
469 : {
470 1386 : if(!bOwnerOfPool && pPool && pPool == &rSfxItemPool)
471 : {
472 : // The pool we are based on gets destructed; get owner of pool by creating own one.
473 : // No need to call RemoveSfxItemPoolUser(), this is done from the pool's destructor
474 : // Base new pool on EditEnginePool; it would also be possible to clone the used
475 : // pool if needed, but only text attributes should be used.
476 1386 : SfxItemPool* pNewPool = EditEngine::CreatePool();
477 :
478 1386 : if(pPool)
479 : {
480 1386 : pNewPool->SetDefaultMetric(pPool->GetMetric(DEF_METRIC));
481 : }
482 :
483 1386 : ContentInfosType aReplaced;
484 1386 : aReplaced.reserve(aContents.size());
485 1386 : ContentInfosType::const_iterator it = aContents.begin(), itEnd = aContents.end();
486 2784 : for (; it != itEnd; ++it)
487 1398 : aReplaced.push_back(new ContentInfo(*it, *pNewPool));
488 1386 : aReplaced.swap(aContents);
489 :
490 : // set local variables
491 1386 : pPool = pNewPool;
492 1386 : bOwnerOfPool = true;
493 : }
494 1386 : }
495 :
496 : #if DEBUG_EDIT_ENGINE
497 : void EditTextObjectImpl::Dump() const
498 : {
499 : ContentInfosType::const_iterator it = aContents.begin(), itEnd = aContents.end();
500 : for (; it != itEnd; ++it)
501 : it->Dump();
502 : }
503 : #endif
504 :
505 120264 : EditEngineItemPool* getEditEngineItemPool(SfxItemPool* pPool)
506 : {
507 120264 : EditEngineItemPool* pRetval = dynamic_cast< EditEngineItemPool* >(pPool);
508 :
509 345576 : while(!pRetval && pPool && pPool->GetSecondaryPool())
510 : {
511 105048 : pPool = pPool->GetSecondaryPool();
512 :
513 105048 : if(pPool)
514 : {
515 105048 : pRetval = dynamic_cast< EditEngineItemPool* >(pPool);
516 : }
517 : }
518 :
519 120264 : return pRetval;
520 : }
521 :
522 120264 : EditTextObjectImpl::EditTextObjectImpl( EditTextObject* pFront, SfxItemPool* pP ) :
523 120264 : mpFront(pFront)
524 : {
525 120264 : nVersion = 0;
526 120264 : nMetric = 0xFFFF;
527 120264 : nUserType = 0;
528 120264 : nObjSettings = 0;
529 120264 : pPortionInfo = 0;
530 :
531 : // #i101239# ensure target is a EditEngineItemPool, else
532 : // fallback to pool ownership. This is needed to ensure that at
533 : // pool destruction time of an alien pool, the pool is still alive.
534 : // When registering would happen at an alien pool which just uses an
535 : // EditEngineItemPool as some sub-pool, that pool could already
536 : // be decoupled and deleted which would lead to crashes.
537 120264 : pPool = getEditEngineItemPool(pP);
538 :
539 120264 : if ( pPool )
540 : {
541 96806 : bOwnerOfPool = false;
542 : }
543 : else
544 : {
545 23458 : pPool = EditEngine::CreatePool();
546 23458 : bOwnerOfPool = true;
547 : }
548 :
549 120264 : if(!bOwnerOfPool && pPool)
550 : {
551 : // it is sure now that the pool is an EditEngineItemPool
552 96806 : pPool->AddSfxItemPoolUser(*mpFront);
553 : }
554 :
555 120264 : bVertical = false;
556 120264 : bStoreUnicodeStrings = false;
557 120264 : nScriptType = 0;
558 120264 : }
559 :
560 252708 : EditTextObjectImpl::EditTextObjectImpl( EditTextObject* pFront, const EditTextObjectImpl& r ) :
561 252708 : mpFront(pFront)
562 : {
563 252708 : nVersion = r.nVersion;
564 252708 : nMetric = r.nMetric;
565 252708 : nUserType = r.nUserType;
566 252708 : nObjSettings = r.nObjSettings;
567 252708 : bVertical = r.bVertical;
568 252708 : nScriptType = r.nScriptType;
569 252708 : pPortionInfo = NULL; // Do not copy PortionInfo
570 252708 : bStoreUnicodeStrings = false;
571 :
572 252708 : if ( !r.bOwnerOfPool )
573 : {
574 : // reuse alien pool; this must be a EditEngineItemPool
575 : // since there is no other way to construct a BinTextObject
576 : // than it's regular constructor where that is ensured
577 213010 : pPool = r.pPool;
578 213010 : bOwnerOfPool = false;
579 : }
580 : else
581 : {
582 39698 : pPool = EditEngine::CreatePool();
583 39698 : bOwnerOfPool = true;
584 :
585 : }
586 :
587 252708 : if (!bOwnerOfPool)
588 : {
589 : // it is sure now that the pool is an EditEngineItemPool
590 213010 : pPool->AddSfxItemPoolUser(*mpFront);
591 : }
592 :
593 252708 : if (bOwnerOfPool && r.pPool)
594 39698 : pPool->SetDefaultMetric( r.pPool->GetMetric( DEF_METRIC ) );
595 :
596 252708 : aContents.reserve(r.aContents.size());
597 252708 : ContentInfosType::const_iterator it = r.aContents.begin(), itEnd = r.aContents.end();
598 531922 : for (; it != itEnd; ++it)
599 279214 : aContents.push_back(new ContentInfo(*it, *pPool));
600 252708 : }
601 :
602 745212 : EditTextObjectImpl::~EditTextObjectImpl()
603 : {
604 372606 : if(!bOwnerOfPool && pPool)
605 : {
606 308096 : pPool->RemoveSfxItemPoolUser(*mpFront);
607 : }
608 :
609 372606 : ClearPortionInfo();
610 :
611 : // Remove contents before deleting the pool instance since each content
612 : // has to access the pool instance in its destructor.
613 372606 : aContents.clear();
614 372606 : if ( bOwnerOfPool )
615 : {
616 64510 : SfxItemPool::Free(pPool);
617 : }
618 372606 : }
619 :
620 :
621 95626 : void EditTextObjectImpl::SetUserType( sal_uInt16 n )
622 : {
623 95626 : nUserType = n;
624 95626 : }
625 :
626 1328 : void EditTextObjectImpl::NormalizeString( svl::SharedStringPool& rPool )
627 : {
628 1328 : ContentInfosType::iterator it = aContents.begin(), itEnd = aContents.end();
629 2848 : for (; it != itEnd; ++it)
630 : {
631 1520 : ContentInfo& rInfo = *it;
632 1520 : rInfo.NormalizeString(rPool);
633 : }
634 1328 : }
635 :
636 6 : std::vector<svl::SharedString> EditTextObjectImpl::GetSharedStrings() const
637 : {
638 6 : std::vector<svl::SharedString> aSSs;
639 6 : aSSs.reserve(aContents.size());
640 6 : ContentInfosType::const_iterator it = aContents.begin(), itEnd = aContents.end();
641 12 : for (; it != itEnd; ++it)
642 : {
643 6 : const ContentInfo& rInfo = *it;
644 6 : aSSs.push_back(rInfo.GetSharedString());
645 : }
646 6 : return aSSs;
647 : }
648 :
649 :
650 120346 : void EditTextObjectImpl::SetVertical( bool b )
651 : {
652 120346 : if ( b != bVertical )
653 : {
654 28 : bVertical = b;
655 28 : ClearPortionInfo();
656 : }
657 120346 : }
658 :
659 :
660 120264 : void EditTextObjectImpl::SetScriptType( sal_uInt16 nType )
661 : {
662 120264 : nScriptType = nType;
663 120264 : }
664 :
665 230750 : XEditAttribute* EditTextObjectImpl::CreateAttrib( const SfxPoolItem& rItem, sal_uInt16 nStart, sal_uInt16 nEnd )
666 : {
667 230750 : return MakeXEditAttribute( *pPool, rItem, nStart, nEnd );
668 : }
669 :
670 0 : void EditTextObjectImpl::DestroyAttrib( XEditAttribute* pAttr )
671 : {
672 0 : pPool->Remove( *pAttr->GetItem() );
673 0 : delete pAttr;
674 0 : }
675 :
676 :
677 :
678 136685 : ContentInfo* EditTextObjectImpl::CreateAndInsertContent()
679 : {
680 136685 : aContents.push_back(new ContentInfo(*pPool));
681 136685 : return &aContents.back();
682 : }
683 :
684 166598 : sal_Int32 EditTextObjectImpl::GetParagraphCount() const
685 : {
686 166598 : size_t nSize = aContents.size();
687 166598 : if (nSize > EE_PARA_MAX_COUNT)
688 : {
689 : SAL_WARN( "editeng", "EditTextObjectImpl::GetParagraphCount - overflow " << nSize);
690 0 : return EE_PARA_MAX_COUNT;
691 : }
692 166598 : return static_cast<sal_Int32>(nSize);
693 : }
694 :
695 127516 : OUString EditTextObjectImpl::GetText(sal_Int32 nPara) const
696 : {
697 127516 : if (nPara < 0 || static_cast<size_t>(nPara) >= aContents.size())
698 0 : return OUString();
699 :
700 127516 : return aContents[nPara].GetText();
701 : }
702 :
703 373734 : void EditTextObjectImpl::ClearPortionInfo()
704 : {
705 373734 : if ( pPortionInfo )
706 : {
707 0 : delete pPortionInfo;
708 0 : pPortionInfo = NULL;
709 : }
710 373734 : }
711 :
712 20 : bool EditTextObjectImpl::HasOnlineSpellErrors() const
713 : {
714 20 : ContentInfosType::const_iterator it = aContents.begin(), itEnd = aContents.end();
715 60 : for (; it != itEnd; ++it)
716 : {
717 40 : if ( it->GetWrongList() && !it->GetWrongList()->empty() )
718 0 : return true;
719 : }
720 20 : return false;
721 : }
722 :
723 610 : void EditTextObjectImpl::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const
724 : {
725 610 : if (nPara < 0 || static_cast<size_t>(nPara) >= aContents.size())
726 610 : return;
727 :
728 610 : rLst.clear();
729 610 : const ContentInfo& rC = aContents[nPara];
730 4296 : for (size_t nAttr = 0; nAttr < rC.aAttribs.size(); ++nAttr)
731 : {
732 3686 : const XEditAttribute& rAttr = rC.aAttribs[nAttr];
733 : EECharAttrib aEEAttr;
734 3686 : aEEAttr.pAttr = rAttr.GetItem();
735 3686 : aEEAttr.nPara = nPara;
736 3686 : aEEAttr.nStart = rAttr.GetStart();
737 3686 : aEEAttr.nEnd = rAttr.GetEnd();
738 3686 : rLst.push_back(aEEAttr);
739 : }
740 : }
741 :
742 0 : bool EditTextObjectImpl::IsFieldObject() const
743 : {
744 0 : return GetField() ? true : false;
745 : }
746 :
747 0 : const SvxFieldItem* EditTextObjectImpl::GetField() const
748 : {
749 0 : if (aContents.size() == 1)
750 : {
751 0 : const ContentInfo& rC = aContents[0];
752 0 : if (rC.GetText().getLength() == 1)
753 : {
754 0 : size_t nAttribs = rC.aAttribs.size();
755 0 : for (size_t nAttr = nAttribs; nAttr; )
756 : {
757 0 : const XEditAttribute& rX = rC.aAttribs[--nAttr];
758 0 : if (rX.GetItem()->Which() == EE_FEATURE_FIELD)
759 0 : return static_cast<const SvxFieldItem*>(rX.GetItem());
760 : }
761 : }
762 : }
763 0 : return 0;
764 : }
765 :
766 2 : const SvxFieldData* EditTextObjectImpl::GetFieldData(sal_Int32 nPara, size_t nPos, sal_Int32 nType) const
767 : {
768 2 : if (nPara < 0 || static_cast<size_t>(nPara) >= aContents.size())
769 0 : return NULL;
770 :
771 2 : const ContentInfo& rC = aContents[nPara];
772 2 : if (nPos >= rC.aAttribs.size())
773 : // URL position is out-of-bound.
774 0 : return NULL;
775 :
776 2 : ContentInfo::XEditAttributesType::const_iterator it = rC.aAttribs.begin(), itEnd = rC.aAttribs.end();
777 2 : size_t nCurPos = 0;
778 2 : for (; it != itEnd; ++it)
779 : {
780 2 : const XEditAttribute& rAttr = *it;
781 2 : if (rAttr.GetItem()->Which() != EE_FEATURE_FIELD)
782 : // Skip attributes that are not fields.
783 0 : continue;
784 :
785 2 : const SvxFieldItem* pField = static_cast<const SvxFieldItem*>(rAttr.GetItem());
786 2 : const SvxFieldData* pFldData = pField->GetField();
787 2 : if (nType != text::textfield::Type::UNSPECIFIED && nType != pFldData->GetClassId())
788 : // Field type doesn't match. Skip it. UNSPECIFIED matches all field types.
789 0 : continue;
790 :
791 2 : if (nCurPos == nPos)
792 : // Found it!
793 2 : return pFldData;
794 :
795 0 : ++nCurPos;
796 : }
797 :
798 0 : return NULL; // field not found.
799 : }
800 :
801 364561 : bool EditTextObjectImpl::HasField( sal_Int32 nType ) const
802 : {
803 364561 : size_t nParagraphs = aContents.size();
804 765231 : for (size_t nPara = 0; nPara < nParagraphs; ++nPara)
805 : {
806 411291 : const ContentInfo& rC = aContents[nPara];
807 411291 : size_t nAttrs = rC.aAttribs.size();
808 1117789 : for (size_t nAttr = 0; nAttr < nAttrs; ++nAttr)
809 : {
810 717119 : const XEditAttribute& rAttr = rC.aAttribs[nAttr];
811 717119 : if (rAttr.GetItem()->Which() != EE_FEATURE_FIELD)
812 686026 : continue;
813 :
814 31093 : if (nType == text::textfield::Type::UNSPECIFIED)
815 : // Match any field type.
816 0 : return true;
817 :
818 31093 : const SvxFieldData* pFldData = static_cast<const SvxFieldItem*>(rAttr.GetItem())->GetField();
819 31093 : if (pFldData && pFldData->GetClassId() == nType)
820 10621 : return true;
821 : }
822 : }
823 353940 : return false;
824 : }
825 :
826 1892 : const SfxItemSet& EditTextObjectImpl::GetParaAttribs(sal_Int32 nPara) const
827 : {
828 1892 : const ContentInfo& rC = aContents[nPara];
829 1892 : return rC.GetParaAttribs();
830 : }
831 :
832 0 : bool EditTextObjectImpl::RemoveCharAttribs( sal_uInt16 _nWhich )
833 : {
834 0 : bool bChanged = false;
835 :
836 0 : for ( size_t nPara = aContents.size(); nPara; )
837 : {
838 0 : ContentInfo& rC = aContents[--nPara];
839 :
840 0 : for (size_t nAttr = rC.aAttribs.size(); nAttr; )
841 : {
842 0 : XEditAttribute& rAttr = rC.aAttribs[--nAttr];
843 0 : if ( !_nWhich || (rAttr.GetItem()->Which() == _nWhich) )
844 : {
845 0 : pPool->Remove(*rAttr.GetItem());
846 0 : rC.aAttribs.erase(rC.aAttribs.begin()+nAttr);
847 0 : bChanged = true;
848 : }
849 : }
850 : }
851 :
852 0 : if ( bChanged )
853 0 : ClearPortionInfo();
854 :
855 0 : return bChanged;
856 : }
857 :
858 : namespace {
859 :
860 : class FindByParagraph : std::unary_function<editeng::Section, bool>
861 : {
862 : sal_Int32 mnPara;
863 : public:
864 118 : FindByParagraph(sal_Int32 nPara) : mnPara(nPara) {}
865 166 : bool operator() (const editeng::Section& rAttr) const
866 : {
867 166 : return rAttr.mnParagraph == mnPara;
868 : }
869 : };
870 :
871 : class FindBySectionStart : std::unary_function<editeng::Section, bool>
872 : {
873 : sal_Int32 mnPara;
874 : sal_Int32 mnStart;
875 : public:
876 94 : FindBySectionStart(sal_Int32 nPara, sal_Int32 nStart) : mnPara(nPara), mnStart(nStart) {}
877 168 : bool operator() (const editeng::Section& rAttr) const
878 : {
879 168 : return rAttr.mnParagraph == mnPara && rAttr.mnStart == mnStart;
880 : }
881 : };
882 :
883 : }
884 :
885 70 : void EditTextObjectImpl::GetAllSections( std::vector<editeng::Section>& rAttrs ) const
886 : {
887 : typedef std::vector<size_t> SectionBordersType;
888 : typedef std::vector<SectionBordersType> ParagraphsType;
889 70 : ParagraphsType aParaBorders(aContents.size());
890 :
891 : // First pass: determine section borders for each paragraph.
892 188 : for (size_t nPara = 0; nPara < aContents.size(); ++nPara)
893 : {
894 118 : const ContentInfo& rC = aContents[nPara];
895 118 : SectionBordersType& rBorders = aParaBorders[nPara];
896 118 : rBorders.push_back(0);
897 118 : rBorders.push_back(rC.GetText().getLength());
898 212 : for (size_t nAttr = 0; nAttr < rC.aAttribs.size(); ++nAttr)
899 : {
900 94 : const XEditAttribute& rAttr = rC.aAttribs[nAttr];
901 94 : const SfxPoolItem* pItem = rAttr.GetItem();
902 94 : if (!pItem)
903 0 : continue;
904 :
905 94 : rBorders.push_back(rAttr.GetStart());
906 94 : rBorders.push_back(rAttr.GetEnd());
907 : }
908 : }
909 :
910 : // Sort and remove duplicates for each paragraph.
911 70 : ParagraphsType::iterator it = aParaBorders.begin(), itEnd = aParaBorders.end();
912 188 : for (; it != itEnd; ++it)
913 : {
914 118 : SectionBordersType& rBorders = *it;
915 118 : std::sort(rBorders.begin(), rBorders.end());
916 118 : SectionBordersType::iterator itUniqueEnd = std::unique(rBorders.begin(), rBorders.end());
917 118 : rBorders.erase(itUniqueEnd, rBorders.end());
918 : }
919 :
920 140 : std::vector<editeng::Section> aAttrs;
921 :
922 : // Create storage for each section. Note that this creates storage even
923 : // for unformatted sections. The entries are sorted first by paragraph,
924 : // then by section positions. They don't overlap with each other.
925 70 : it = aParaBorders.begin();
926 188 : for (; it != itEnd; ++it)
927 : {
928 118 : size_t nPara = distance(aParaBorders.begin(), it);
929 118 : const SectionBordersType& rBorders = *it;
930 118 : if (rBorders.size() == 1 && rBorders[0] == 0)
931 : {
932 : // Empty paragraph. Push an empty section.
933 16 : aAttrs.push_back(editeng::Section(nPara, 0, 0));
934 16 : continue;
935 : }
936 :
937 102 : SectionBordersType::const_iterator itBorder = rBorders.begin(), itBorderEnd = rBorders.end();
938 102 : size_t nPrev = *itBorder;
939 : size_t nCur;
940 288 : for (++itBorder; itBorder != itBorderEnd; ++itBorder, nPrev = nCur)
941 : {
942 186 : nCur = *itBorder;
943 186 : aAttrs.push_back(editeng::Section(nPara, nPrev, nCur));
944 : }
945 : }
946 :
947 70 : if (aAttrs.empty())
948 0 : return;
949 :
950 : // Go through all formatted paragraphs, and store format items.
951 70 : std::vector<editeng::Section>::iterator itAttr = aAttrs.begin();
952 188 : for (sal_Int32 nPara = 0; nPara < (sal_Int32)aContents.size(); ++nPara)
953 : {
954 118 : const ContentInfo& rC = aContents[nPara];
955 :
956 118 : itAttr = std::find_if(itAttr, aAttrs.end(), FindByParagraph(nPara));
957 118 : if (itAttr == aAttrs.end())
958 : // This should never happen. There is a logic error somewhere...
959 0 : return;
960 :
961 212 : for (size_t i = 0; i < rC.aAttribs.size(); ++i)
962 : {
963 94 : const XEditAttribute& rXAttr = rC.aAttribs[i];
964 94 : const SfxPoolItem* pItem = rXAttr.GetItem();
965 94 : if (!pItem)
966 0 : continue;
967 :
968 94 : sal_Int32 nStart = rXAttr.GetStart(), nEnd = rXAttr.GetEnd();
969 94 : std::vector<editeng::Section>::iterator itCurAttr = itAttr;
970 :
971 : // Find the container whose start position matches.
972 94 : itCurAttr = std::find_if(itCurAttr, aAttrs.end(), FindBySectionStart(nPara, nStart));
973 94 : if (itCurAttr == aAttrs.end())
974 : // This should never happen. There is a logic error somewhere...
975 0 : return;
976 :
977 192 : for (; itCurAttr != aAttrs.end() && itCurAttr->mnParagraph == nPara && itCurAttr->mnEnd <= nEnd; ++itCurAttr)
978 : {
979 98 : editeng::Section& rSecAttr = *itCurAttr;
980 98 : rSecAttr.maAttributes.push_back(pItem);
981 : }
982 : }
983 : }
984 :
985 140 : rAttrs.swap(aAttrs);
986 : }
987 :
988 32712 : void EditTextObjectImpl::GetStyleSheet(sal_Int32 nPara, OUString& rName, SfxStyleFamily& rFamily) const
989 : {
990 32712 : if (nPara < 0 || static_cast<size_t>(nPara) >= aContents.size())
991 32712 : return;
992 :
993 32712 : const ContentInfo& rC = aContents[nPara];
994 32712 : rName = rC.GetStyle();
995 32712 : rFamily = rC.GetFamily();
996 : }
997 :
998 0 : void EditTextObjectImpl::SetStyleSheet(sal_Int32 nPara, const OUString& rName, const SfxStyleFamily& rFamily)
999 : {
1000 0 : if (nPara < 0 || static_cast<size_t>(nPara) >= aContents.size())
1001 0 : return;
1002 :
1003 0 : ContentInfo& rC = aContents[nPara];
1004 0 : rC.GetStyle() = rName;
1005 0 : rC.GetFamily() = rFamily;
1006 : }
1007 :
1008 20580 : bool EditTextObjectImpl::ImpChangeStyleSheets(
1009 : const OUString& rOldName, SfxStyleFamily eOldFamily,
1010 : const OUString& rNewName, SfxStyleFamily eNewFamily )
1011 : {
1012 20580 : const size_t nParagraphs = aContents.size();
1013 20580 : bool bChanges = false;
1014 :
1015 41832 : for (size_t nPara = 0; nPara < nParagraphs; ++nPara)
1016 : {
1017 21252 : ContentInfo& rC = aContents[nPara];
1018 21252 : if ( rC.GetFamily() == eOldFamily )
1019 : {
1020 15316 : if ( rC.GetStyle() == rOldName )
1021 : {
1022 1094 : rC.GetStyle() = rNewName;
1023 1094 : rC.GetFamily() = eNewFamily;
1024 1094 : bChanges = true;
1025 : }
1026 : }
1027 : }
1028 20580 : return bChanges;
1029 : }
1030 :
1031 20580 : bool EditTextObjectImpl::ChangeStyleSheets(
1032 : const OUString& rOldName, SfxStyleFamily eOldFamily,
1033 : const OUString& rNewName, SfxStyleFamily eNewFamily)
1034 : {
1035 20580 : bool bChanges = ImpChangeStyleSheets( rOldName, eOldFamily, rNewName, eNewFamily );
1036 20580 : if ( bChanges )
1037 1094 : ClearPortionInfo();
1038 :
1039 20580 : return bChanges;
1040 : }
1041 :
1042 0 : void EditTextObjectImpl::ChangeStyleSheetName( SfxStyleFamily eFamily,
1043 : const OUString& rOldName, const OUString& rNewName )
1044 : {
1045 0 : ImpChangeStyleSheets( rOldName, eFamily, rNewName, eFamily );
1046 0 : }
1047 :
1048 :
1049 : namespace {
1050 :
1051 : class FindAttribByChar : public std::unary_function<XEditAttribute, bool>
1052 : {
1053 : sal_uInt16 mnWhich;
1054 : sal_uInt16 mnChar;
1055 : public:
1056 0 : FindAttribByChar(sal_uInt16 nWhich, sal_uInt16 nChar) : mnWhich(nWhich), mnChar(nChar) {}
1057 0 : bool operator() (const XEditAttribute& rAttr) const
1058 : {
1059 0 : return (rAttr.GetItem()->Which() == mnWhich) && (rAttr.GetStart() <= mnChar) && (rAttr.GetEnd() > mnChar);
1060 : }
1061 : };
1062 :
1063 : }
1064 :
1065 10752 : void EditTextObjectImpl::StoreData( SvStream& rOStream ) const
1066 : {
1067 10752 : sal_uInt16 nVer = 602;
1068 10752 : rOStream.WriteUInt16( nVer );
1069 :
1070 10752 : rOStream.WriteUChar( bOwnerOfPool );
1071 :
1072 : // First store the pool, later only the Surregate
1073 10752 : if ( bOwnerOfPool )
1074 : {
1075 10704 : GetPool()->SetFileFormatVersion( SOFFICE_FILEFORMAT_50 );
1076 10704 : GetPool()->Store( rOStream );
1077 : }
1078 :
1079 : // Store Current text encoding ...
1080 10752 : rtl_TextEncoding eEncoding = GetSOStoreTextEncoding( osl_getThreadTextEncoding() );
1081 10752 : rOStream.WriteUInt16( eEncoding );
1082 :
1083 : // The number of paragraphs ...
1084 10752 : size_t nParagraphs = aContents.size();
1085 : // FIXME: this truncates, check usage of stream and if it can be changed,
1086 : // i.e. is not persistent, adapt this and reader.
1087 10752 : sal_uInt16 nParagraphs_Stream = static_cast<sal_uInt16>(nParagraphs);
1088 10752 : rOStream.WriteUInt16( nParagraphs_Stream );
1089 :
1090 10752 : sal_Unicode nUniChar = CH_FEATURE;
1091 10752 : char cFeatureConverted = OString(&nUniChar, 1, eEncoding).toChar();
1092 :
1093 : // The individual paragraphs ...
1094 21528 : for (size_t nPara = 0; nPara < nParagraphs_Stream; ++nPara)
1095 : {
1096 10776 : const ContentInfo& rC = aContents[nPara];
1097 :
1098 : // Text...
1099 10776 : OStringBuffer aBuffer(OUStringToOString(rC.GetText(), eEncoding));
1100 :
1101 : // Symbols?
1102 10776 : bool bSymbolPara = false;
1103 10776 : if (rC.GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SfxItemState::SET)
1104 : {
1105 656 : const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(rC.GetParaAttribs().Get(EE_CHAR_FONTINFO));
1106 656 : if ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
1107 : {
1108 0 : aBuffer = OStringBuffer(OUStringToOString(rC.GetText(), RTL_TEXTENCODING_SYMBOL));
1109 0 : bSymbolPara = true;
1110 : }
1111 : }
1112 21666 : for (size_t nA = 0; nA < rC.aAttribs.size(); ++nA)
1113 : {
1114 10890 : const XEditAttribute& rAttr = rC.aAttribs[nA];
1115 :
1116 10890 : if (rAttr.GetItem()->Which() == EE_CHAR_FONTINFO)
1117 : {
1118 602 : const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(*rAttr.GetItem());
1119 1806 : if ( ( !bSymbolPara && ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) )
1120 1204 : || ( bSymbolPara && ( rFontItem.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) ) )
1121 : {
1122 : // Not correctly converted
1123 0 : OUString aPart = rC.GetText().copy( rAttr.GetStart(), rAttr.GetEnd() - rAttr.GetStart() );
1124 0 : OString aNew(OUStringToOString(aPart, rFontItem.GetCharSet()));
1125 0 : aBuffer.remove(rAttr.GetStart(), rAttr.GetEnd() - rAttr.GetStart());
1126 0 : aBuffer.insert(rAttr.GetStart(), aNew);
1127 : }
1128 :
1129 : // Convert StarSymbol back to StarBats
1130 602 : FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
1131 602 : if ( hConv )
1132 : {
1133 : // Don't create a new Attrib with StarBats font, MBR changed the
1134 : // SvxFontItem::Store() to store StarBats instead of StarSymbol!
1135 0 : for (sal_uInt16 nChar = rAttr.GetStart(); nChar < rAttr.GetEnd(); ++nChar)
1136 : {
1137 0 : sal_Unicode cOld = rC.GetText()[ nChar ];
1138 0 : char cConv = OUStringToOString(OUString(ConvertFontToSubsFontChar(hConv, cOld)), RTL_TEXTENCODING_SYMBOL).toChar();
1139 0 : if ( cConv )
1140 0 : aBuffer[nChar] = cConv;
1141 : }
1142 :
1143 0 : DestroyFontToSubsFontConverter( hConv );
1144 : }
1145 : }
1146 : }
1147 :
1148 : // Convert StarSymbol back to StarBats
1149 : // StarSymbol as paragraph attribute or in StyleSheet?
1150 :
1151 10776 : FontToSubsFontConverter hConv = NULL;
1152 10776 : if (rC.GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SfxItemState::SET)
1153 : {
1154 656 : hConv = CreateFontToSubsFontConverter( static_cast<const SvxFontItem&>(rC.GetParaAttribs().Get( EE_CHAR_FONTINFO )).GetFamilyName(), FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
1155 : }
1156 10776 : if ( hConv )
1157 : {
1158 0 : for ( sal_uInt16 nChar = 0; nChar < rC.GetText().getLength(); nChar++ )
1159 : {
1160 0 : const ContentInfo::XEditAttributesType& rAttribs = rC.aAttribs;
1161 : ContentInfo::XEditAttributesType::const_iterator it =
1162 : std::find_if(rAttribs.begin(), rAttribs.end(),
1163 0 : FindAttribByChar(EE_CHAR_FONTINFO, nChar));
1164 :
1165 0 : if (it == rAttribs.end())
1166 : {
1167 0 : sal_Unicode cOld = rC.GetText()[ nChar ];
1168 0 : char cConv = OUStringToOString(OUString(ConvertFontToSubsFontChar(hConv, cOld)), RTL_TEXTENCODING_SYMBOL).toChar();
1169 0 : if ( cConv )
1170 0 : aBuffer[nChar] = cConv;
1171 : }
1172 : }
1173 :
1174 0 : DestroyFontToSubsFontConverter( hConv );
1175 :
1176 : }
1177 :
1178 :
1179 : // Convert CH_FEATURE to CH_FEATURE_OLD
1180 21552 : OString aText = aBuffer.makeStringAndClear().replace(cFeatureConverted, CH_FEATURE_OLD);
1181 10776 : write_uInt16_lenPrefixed_uInt8s_FromOString(rOStream, aText);
1182 :
1183 : // StyleName and Family...
1184 10776 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStream, rC.GetStyle(), eEncoding);
1185 10776 : rOStream.WriteUInt16( rC.GetFamily() );
1186 :
1187 : // Paragraph attributes ...
1188 10776 : rC.GetParaAttribs().Store( rOStream );
1189 :
1190 : // The number of attributes ...
1191 10776 : size_t nAttribs = rC.aAttribs.size();
1192 10776 : rOStream.WriteUInt16( nAttribs );
1193 :
1194 : // And the individual attributes
1195 : // Items as Surregate => always 8 bytes per Attribute
1196 : // Which = 2; Surregat = 2; Start = 2; End = 2;
1197 21666 : for (size_t nAttr = 0; nAttr < nAttribs; ++nAttr)
1198 : {
1199 10890 : const XEditAttribute& rX = rC.aAttribs[nAttr];
1200 :
1201 10890 : rOStream.WriteUInt16( rX.GetItem()->Which() );
1202 10890 : GetPool()->StoreSurrogate(rOStream, rX.GetItem());
1203 10890 : rOStream.WriteUInt16( rX.GetStart() );
1204 10890 : rOStream.WriteUInt16( rX.GetEnd() );
1205 : }
1206 10776 : }
1207 :
1208 10752 : rOStream.WriteUInt16( nMetric );
1209 :
1210 10752 : rOStream.WriteUInt16( nUserType );
1211 10752 : rOStream.WriteUInt32( nObjSettings );
1212 :
1213 10752 : rOStream.WriteUChar( bVertical );
1214 10752 : rOStream.WriteUInt16( nScriptType );
1215 :
1216 10752 : rOStream.WriteUChar( bStoreUnicodeStrings );
1217 10752 : if ( bStoreUnicodeStrings )
1218 : {
1219 0 : for ( size_t nPara = 0; nPara < nParagraphs_Stream; nPara++ )
1220 : {
1221 0 : const ContentInfo& rC = aContents[nPara];
1222 0 : sal_uInt16 nL = rC.GetText().getLength();
1223 0 : rOStream.WriteUInt16( nL );
1224 0 : rOStream.Write(rC.GetText().getStr(), nL*sizeof(sal_Unicode));
1225 :
1226 : // StyleSheetName must be Unicode too!
1227 : // Copy/Paste from EA3 to BETA or from BETA to EA3 not possible, not needed...
1228 : // If needed, change nL back to sal_uLong and increase version...
1229 0 : nL = rC.GetStyle().getLength();
1230 0 : rOStream.WriteUInt16( nL );
1231 0 : rOStream.Write(rC.GetStyle().getStr(), nL*sizeof(sal_Unicode));
1232 : }
1233 : }
1234 10752 : }
1235 :
1236 0 : void EditTextObjectImpl::CreateData( SvStream& rIStream )
1237 : {
1238 0 : rIStream.ReadUInt16( nVersion );
1239 :
1240 : // The text object was first created with the current setting of
1241 : // pTextObjectPool.
1242 0 : bool bOwnerOfCurrent = bOwnerOfPool;
1243 : bool b;
1244 0 : rIStream.ReadCharAsBool( b );
1245 0 : bOwnerOfPool = b;
1246 :
1247 0 : if ( bOwnerOfCurrent && !bOwnerOfPool )
1248 : {
1249 : // A global Pool was used, but not handed over to me, but I need it!
1250 : OSL_FAIL( "Give me the global TextObjectPool!" );
1251 0 : return;
1252 : }
1253 0 : else if ( !bOwnerOfCurrent && bOwnerOfPool )
1254 : {
1255 : // A global Pool should be used, but this Textobject has its own.
1256 0 : pPool = EditEngine::CreatePool();
1257 : }
1258 :
1259 0 : if ( bOwnerOfPool )
1260 0 : GetPool()->Load( rIStream );
1261 :
1262 : // CharSet, in which it was saved:
1263 : sal_uInt16 nCharSet;
1264 0 : rIStream.ReadUInt16( nCharSet );
1265 :
1266 0 : rtl_TextEncoding eSrcEncoding = GetSOLoadTextEncoding( (rtl_TextEncoding)nCharSet );
1267 :
1268 : // The number of paragraphs ...
1269 : sal_uInt16 nParagraphs;
1270 0 : rIStream.ReadUInt16( nParagraphs );
1271 :
1272 : // The individual paragraphs ...
1273 0 : for ( sal_uLong nPara = 0; nPara < nParagraphs; nPara++ )
1274 : {
1275 0 : ContentInfo* pC = CreateAndInsertContent();
1276 :
1277 : // The Text...
1278 0 : OString aByteString = read_uInt16_lenPrefixed_uInt8s_ToOString(rIStream);
1279 0 : pC->SetText(OStringToOUString(aByteString, eSrcEncoding));
1280 :
1281 : // StyleName and Family...
1282 0 : pC->GetStyle() = rIStream.ReadUniOrByteString(eSrcEncoding);
1283 : sal_uInt16 nStyleFamily;
1284 0 : rIStream.ReadUInt16( nStyleFamily );
1285 0 : pC->GetFamily() = (SfxStyleFamily)nStyleFamily;
1286 :
1287 : // Paragraph attributes ...
1288 0 : pC->GetParaAttribs().Load( rIStream );
1289 :
1290 : // The number of attributes ...
1291 : sal_uInt16 nTmp16;
1292 0 : rIStream.ReadUInt16( nTmp16 );
1293 0 : size_t nAttribs = nTmp16;
1294 :
1295 : // And the individual attributes
1296 : // Items as Surregate => always 8 bytes per Attributes
1297 : // Which = 2; Surregat = 2; Start = 2; End = 2;
1298 : size_t nAttr;
1299 0 : for (nAttr = 0; nAttr < nAttribs; ++nAttr)
1300 : {
1301 : sal_uInt16 _nWhich, nStart, nEnd;
1302 : const SfxPoolItem* pItem;
1303 :
1304 0 : rIStream.ReadUInt16( _nWhich );
1305 0 : _nWhich = pPool->GetNewWhich( _nWhich );
1306 0 : pItem = pPool->LoadSurrogate( rIStream, _nWhich, 0 );
1307 0 : rIStream.ReadUInt16( nStart );
1308 0 : rIStream.ReadUInt16( nEnd );
1309 0 : if ( pItem )
1310 : {
1311 0 : if ( pItem->Which() == EE_FEATURE_NOTCONV )
1312 : {
1313 0 : sal_Char cEncodedChar = aByteString[nStart];
1314 : sal_Unicode cChar = OUString(&cEncodedChar, 1,
1315 0 : static_cast<const SvxCharSetColorItem*>(pItem)->GetCharSet()).toChar();
1316 0 : pC->SetText(pC->GetText().replaceAt(nStart, 1, OUString(cChar)));
1317 : }
1318 : else
1319 : {
1320 0 : XEditAttribute* pAttr = new XEditAttribute( *pItem, nStart, nEnd );
1321 0 : pC->aAttribs.push_back(pAttr);
1322 :
1323 0 : if ( ( _nWhich >= EE_FEATURE_START ) && ( _nWhich <= EE_FEATURE_END ) )
1324 : {
1325 : // Convert CH_FEATURE to CH_FEATURE_OLD
1326 : DBG_ASSERT( (sal_uInt8) aByteString[nStart] == CH_FEATURE_OLD, "CreateData: CH_FEATURE expected!" );
1327 0 : if ( (sal_uInt8) aByteString[nStart] == CH_FEATURE_OLD )
1328 0 : pC->SetText(pC->GetText().replaceAt(nStart, 1, OUString(CH_FEATURE)));
1329 : }
1330 : }
1331 : }
1332 : }
1333 :
1334 : // But check for paragraph and character symbol attribs here,
1335 : // FinishLoad will not be called in OpenOffice Calc, no StyleSheets...
1336 :
1337 0 : bool bSymbolPara = false;
1338 0 : if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SfxItemState::SET )
1339 : {
1340 0 : const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(pC->GetParaAttribs().Get( EE_CHAR_FONTINFO ));
1341 0 : if ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
1342 : {
1343 0 : pC->SetText(OStringToOUString(aByteString, RTL_TEXTENCODING_SYMBOL));
1344 0 : bSymbolPara = true;
1345 : }
1346 : }
1347 :
1348 0 : for (nAttr = pC->aAttribs.size(); nAttr; )
1349 : {
1350 0 : const XEditAttribute& rAttr = pC->aAttribs[--nAttr];
1351 0 : if ( rAttr.GetItem()->Which() == EE_CHAR_FONTINFO )
1352 : {
1353 0 : const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(*rAttr.GetItem());
1354 0 : if ( ( !bSymbolPara && ( rFontItem.GetCharSet() == RTL_TEXTENCODING_SYMBOL ) )
1355 0 : || ( bSymbolPara && ( rFontItem.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) ) )
1356 : {
1357 : // Not correctly converted
1358 0 : OString aPart(aByteString.copy(rAttr.GetStart(), rAttr.GetEnd()-rAttr.GetStart()));
1359 0 : OUString aNew(OStringToOUString(aPart, rFontItem.GetCharSet()));
1360 0 : pC->SetText(pC->GetText().replaceAt(rAttr.GetStart(), rAttr.GetEnd()-rAttr.GetStart(), aNew));
1361 : }
1362 :
1363 : // Convert StarMath and StarBats to StarSymbol
1364 0 : FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_IMPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
1365 0 : if ( hConv )
1366 : {
1367 0 : SvxFontItem aNewFontItem( rFontItem );
1368 0 : aNewFontItem.SetFamilyName( GetFontToSubsFontName( hConv ) );
1369 :
1370 : // Replace the existing attribute with a new one.
1371 0 : XEditAttribute* pNewAttr = CreateAttrib(aNewFontItem, rAttr.GetStart(), rAttr.GetEnd());
1372 :
1373 0 : pPool->Remove(*rAttr.GetItem());
1374 0 : pC->aAttribs.erase(pC->aAttribs.begin()+nAttr);
1375 0 : pC->aAttribs.insert(pC->aAttribs.begin()+nAttr, pNewAttr);
1376 :
1377 0 : for ( sal_uInt16 nChar = pNewAttr->GetStart(); nChar < pNewAttr->GetEnd(); nChar++ )
1378 : {
1379 0 : sal_Unicode cOld = pC->GetText()[ nChar ];
1380 : DBG_ASSERT( cOld >= 0xF000, "cOld not converted?!" );
1381 0 : sal_Unicode cConv = ConvertFontToSubsFontChar( hConv, cOld );
1382 0 : if ( cConv )
1383 0 : pC->SetText(pC->GetText().replaceAt(nChar, 1, OUString(cConv)));
1384 : }
1385 :
1386 0 : DestroyFontToSubsFontConverter( hConv );
1387 : }
1388 : }
1389 : }
1390 :
1391 :
1392 : // Convert StarMath and StarBats to StarSymbol
1393 : // Maybe old symbol font as paragraph attribute?
1394 0 : if ( pC->GetParaAttribs().GetItemState( EE_CHAR_FONTINFO ) == SfxItemState::SET )
1395 : {
1396 0 : const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(pC->GetParaAttribs().Get( EE_CHAR_FONTINFO ));
1397 0 : FontToSubsFontConverter hConv = CreateFontToSubsFontConverter( rFontItem.GetFamilyName(), FONTTOSUBSFONT_IMPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS );
1398 0 : if ( hConv )
1399 : {
1400 0 : SvxFontItem aNewFontItem( rFontItem );
1401 0 : aNewFontItem.SetFamilyName( GetFontToSubsFontName( hConv ) );
1402 0 : pC->GetParaAttribs().Put( aNewFontItem );
1403 :
1404 0 : for ( sal_uInt16 nChar = 0; nChar < pC->GetText().getLength(); nChar++ )
1405 : {
1406 0 : const ContentInfo::XEditAttributesType& rAttribs = pC->aAttribs;
1407 : ContentInfo::XEditAttributesType::const_iterator it =
1408 : std::find_if(rAttribs.begin(), rAttribs.end(),
1409 0 : FindAttribByChar(EE_CHAR_FONTINFO, nChar));
1410 :
1411 0 : if (it == rAttribs.end())
1412 : {
1413 0 : sal_Unicode cOld = pC->GetText()[ nChar ];
1414 : DBG_ASSERT( cOld >= 0xF000, "cOld not converted?!" );
1415 0 : sal_Unicode cConv = ConvertFontToSubsFontChar( hConv, cOld );
1416 0 : if ( cConv )
1417 0 : pC->SetText(pC->GetText().replaceAt(nChar, 1, OUString(cConv)));
1418 : }
1419 : }
1420 :
1421 0 : DestroyFontToSubsFontConverter( hConv );
1422 : }
1423 : }
1424 0 : }
1425 :
1426 : // From 400 also the DefMetric:
1427 0 : if ( nVersion >= 400 )
1428 : {
1429 : sal_uInt16 nTmpMetric;
1430 0 : rIStream.ReadUInt16( nTmpMetric );
1431 0 : if ( nVersion >= 401 )
1432 : {
1433 : // In the 400 there was a bug in text objects with the own Pool,
1434 : // therefore evaluate only from 401
1435 0 : nMetric = nTmpMetric;
1436 0 : if ( bOwnerOfPool && pPool && ( nMetric != 0xFFFF ) )
1437 0 : pPool->SetDefaultMetric( (SfxMapUnit)nMetric );
1438 : }
1439 : }
1440 :
1441 0 : if ( nVersion >= 600 )
1442 : {
1443 0 : rIStream.ReadUInt16( nUserType );
1444 0 : rIStream.ReadUInt32( nObjSettings );
1445 : }
1446 :
1447 0 : if ( nVersion >= 601 )
1448 : {
1449 : bool bTmp;
1450 0 : rIStream.ReadCharAsBool( bTmp );
1451 0 : bVertical = bTmp;
1452 : }
1453 :
1454 0 : if ( nVersion >= 602 )
1455 : {
1456 0 : rIStream.ReadUInt16( nScriptType );
1457 :
1458 : bool bUnicodeStrings;
1459 0 : rIStream.ReadCharAsBool( bUnicodeStrings );
1460 0 : if ( bUnicodeStrings )
1461 : {
1462 0 : for ( sal_uInt16 nPara = 0; nPara < nParagraphs; nPara++ )
1463 : {
1464 0 : ContentInfo& rC = aContents[nPara];
1465 : sal_uInt16 nL;
1466 :
1467 : // Text
1468 0 : rIStream.ReadUInt16( nL );
1469 0 : if ( nL )
1470 : {
1471 0 : rtl_uString *pStr = rtl_uString_alloc(nL);
1472 0 : rIStream.Read(pStr->buffer, nL*sizeof(sal_Unicode));
1473 0 : rC.SetText((OUString(pStr, SAL_NO_ACQUIRE)));
1474 : }
1475 :
1476 : // StyleSheetName
1477 0 : rIStream.ReadUInt16( nL );
1478 0 : if ( nL )
1479 : {
1480 0 : rtl_uString *pStr = rtl_uString_alloc(nL);
1481 0 : rIStream.Read(pStr->buffer, nL*sizeof(sal_Unicode) );
1482 0 : rC.GetStyle() = OUString(pStr, SAL_NO_ACQUIRE);
1483 : }
1484 : }
1485 : }
1486 : }
1487 :
1488 :
1489 : // from 500 the tabs are interpreted differently: TabPos + LI, previously only TabPos.
1490 : // Works only if tab positions are set, not when DefTab.
1491 0 : if ( nVersion < 500 )
1492 : {
1493 0 : for (size_t i = 0, n = aContents.size(); i < n; ++i)
1494 : {
1495 0 : ContentInfo& rC = aContents[i];
1496 0 : const SvxLRSpaceItem& rLRSpace = static_cast<const SvxLRSpaceItem&>(rC.GetParaAttribs().Get(EE_PARA_LRSPACE));
1497 0 : if ( rLRSpace.GetTxtLeft() && ( rC.GetParaAttribs().GetItemState( EE_PARA_TABS ) == SfxItemState::SET ) )
1498 : {
1499 0 : const SvxTabStopItem& rTabs = static_cast<const SvxTabStopItem&>(rC.GetParaAttribs().Get(EE_PARA_TABS));
1500 0 : SvxTabStopItem aNewTabs( 0, 0, SVX_TAB_ADJUST_LEFT, EE_PARA_TABS );
1501 0 : for ( sal_uInt16 t = 0; t < rTabs.Count(); t++ )
1502 : {
1503 0 : const SvxTabStop& rT = rTabs[ t ];
1504 0 : aNewTabs.Insert( SvxTabStop( rT.GetTabPos() - rLRSpace.GetTxtLeft(),
1505 0 : rT.GetAdjustment(), rT.GetDecimal(), rT.GetFill() ) );
1506 : }
1507 0 : rC.GetParaAttribs().Put( aNewTabs );
1508 : }
1509 : }
1510 : }
1511 : }
1512 :
1513 3960 : bool EditTextObjectImpl::operator==( const EditTextObjectImpl& rCompare ) const
1514 : {
1515 3960 : if( this == &rCompare )
1516 0 : return true;
1517 :
1518 11818 : if( ( aContents.size() != rCompare.aContents.size() ) ||
1519 7796 : ( pPool != rCompare.pPool ) ||
1520 7796 : ( nMetric != rCompare.nMetric ) ||
1521 7796 : ( nUserType!= rCompare.nUserType ) ||
1522 11756 : ( nScriptType != rCompare.nScriptType ) ||
1523 3898 : ( bVertical != rCompare.bVertical ) )
1524 62 : return false;
1525 :
1526 6413 : for (size_t i = 0, n = aContents.size(); i < n; ++i)
1527 : {
1528 4587 : if (aContents[i] != rCompare.aContents[i])
1529 2072 : return false;
1530 : }
1531 :
1532 1826 : return true;
1533 : }
1534 :
1535 : // #i102062#
1536 1818 : bool EditTextObjectImpl::isWrongListEqual(const EditTextObjectImpl& rCompare) const
1537 : {
1538 1818 : if (aContents.size() != rCompare.aContents.size())
1539 : {
1540 0 : return false;
1541 : }
1542 :
1543 3963 : for (size_t i = 0, n = aContents.size(); i < n; ++i)
1544 : {
1545 2145 : const ContentInfo& rCandA = aContents[i];
1546 2145 : const ContentInfo& rCandB = rCompare.aContents[i];
1547 :
1548 2145 : if(!rCandA.isWrongListEqual(rCandB))
1549 : {
1550 0 : return false;
1551 : }
1552 : }
1553 :
1554 1818 : return true;
1555 669 : }
1556 :
1557 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|