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