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