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 <hintids.hxx>
21 : #include <hints.hxx>
22 :
23 : #include <editeng/fontitem.hxx>
24 : #include <editeng/formatbreakitem.hxx>
25 : #include <editeng/escapementitem.hxx>
26 : #include <editeng/lrspitem.hxx>
27 : #include <editeng/rsiditem.hxx>
28 : #include <editeng/tstpitem.hxx>
29 : #include <svl/urihelper.hxx>
30 : #include <svl/ctloptions.hxx>
31 : #include <tools/multisel.hxx>
32 : #include <swmodule.hxx>
33 : #include <txtfld.hxx>
34 : #include <txtinet.hxx>
35 : #include <fmtinfmt.hxx>
36 : #include <fmtpdsc.hxx>
37 : #include <txtatr.hxx>
38 : #include <fmtrfmrk.hxx>
39 : #include <txttxmrk.hxx>
40 : #include <fchrfmt.hxx>
41 : #include <txtftn.hxx>
42 : #include <fmtflcnt.hxx>
43 : #include <fmtfld.hxx>
44 : #include <frmatr.hxx>
45 : #include <charatr.hxx>
46 : #include <ftnidx.hxx>
47 : #include <ftninfo.hxx>
48 : #include <fmtftn.hxx>
49 : #include <fmtmeta.hxx>
50 : #include <charfmt.hxx>
51 : #include <ndtxt.hxx>
52 : #include <doc.hxx>
53 : #include <IDocumentUndoRedo.hxx>
54 : #include <docary.hxx>
55 : #include <pam.hxx> // fuer SwPosition
56 : #include <fldbas.hxx>
57 : #include <paratr.hxx>
58 : #include <txtfrm.hxx>
59 : #include <ftnfrm.hxx>
60 : #include <ftnboss.hxx>
61 : #include <rootfrm.hxx>
62 : #include <pagedesc.hxx> // fuer SwPageDesc
63 : #include <expfld.hxx> // fuer SwTblField
64 : #include <section.hxx> // fuer SwSection
65 : #include <mvsave.hxx>
66 : #include <swcache.hxx>
67 : #include <SwGrammarMarkUp.hxx>
68 : #include <dcontact.hxx>
69 : #include <redline.hxx>
70 : #include <doctxm.hxx>
71 : #include <IMark.hxx>
72 : #include <scriptinfo.hxx>
73 : #include <istyleaccess.hxx>
74 : #include <SwStyleNameMapper.hxx>
75 : #include <numrule.hxx>
76 : #include <swtable.hxx>
77 : #include <docsh.hxx>
78 : #include <SwNodeNum.hxx>
79 : #include <svl/intitem.hxx>
80 : #include <list.hxx>
81 : #include <switerator.hxx>
82 : #include <attrhint.hxx>
83 :
84 :
85 : using namespace ::com::sun::star;
86 :
87 :
88 : typedef std::vector<SwTxtAttr*> SwpHts;
89 :
90 157659 : TYPEINIT1( SwTxtNode, SwCntntNode )
91 :
92 : // Leider ist das SwpHints nicht ganz wasserdicht:
93 : // Jeder darf an den Hints rumfummeln, ohne die Sortierreihenfolge
94 : // und Verkettung sicherstellen zu muessen.
95 : #ifdef DBG_UTIL
96 : #define CHECK_SWPHINTS(pNd) { if( pNd->GetpSwpHints() && \
97 : !pNd->GetDoc()->IsInReading() ) \
98 : pNd->GetpSwpHints()->Check(true); }
99 : #else
100 : #define CHECK_SWPHINTS(pNd)
101 : #endif
102 :
103 871 : SwTxtNode *SwNodes::MakeTxtNode( const SwNodeIndex & rWhere,
104 : SwTxtFmtColl *pColl,
105 : SwAttrSet* pAutoAttr )
106 : {
107 : OSL_ENSURE( pColl, "Collectionpointer ist 0." );
108 :
109 871 : SwTxtNode *pNode = new SwTxtNode( rWhere, pColl, pAutoAttr );
110 :
111 871 : SwNodeIndex aIdx( *pNode );
112 :
113 : // #125329#
114 : // call method <UpdateOutlineNode(..)> only for the document nodes array
115 871 : if ( IsDocNodes() )
116 871 : UpdateOutlineNode(*pNode);
117 :
118 : //Wenn es noch kein Layout gibt oder in einer versteckten Section
119 : // stehen, brauchen wir uns um das MakeFrms nicht bemuehen.
120 : const SwSectionNode* pSectNd;
121 1765 : if( !GetDoc()->GetCurrentViewShell() || //swmod 071108//swmod 071225
122 164 : ( 0 != (pSectNd = pNode->FindSectionNode()) &&
123 29 : pSectNd->GetSection().IsHiddenFlag() ))
124 759 : return pNode;
125 :
126 224 : SwNodeIndex aTmp( rWhere );
127 : do {
128 : // max. 2 Durchlaeufe:
129 : // 1. den Nachfolger nehmen
130 : // 2. den Vorgaenger
131 :
132 186 : SwNode * pNd = & aTmp.GetNode();
133 186 : switch (pNd->GetNodeType())
134 : {
135 : case ND_TABLENODE:
136 3 : ((SwTableNode*)pNd)->MakeFrms( aIdx );
137 3 : return pNode;
138 :
139 : case ND_SECTIONNODE:
140 4 : if( ((SwSectionNode*)pNd)->GetSection().IsHidden() ||
141 2 : ((SwSectionNode*)pNd)->IsCntntHidden() )
142 : {
143 0 : SwNodeIndex aTmpIdx( *pNode );
144 0 : pNd = FindPrvNxtFrmNode( aTmpIdx, pNode );
145 0 : if( !pNd )
146 0 : return pNode;
147 0 : aTmp = *pNd;
148 0 : break;
149 : }
150 2 : ((SwSectionNode*)pNd)->MakeFrms( aIdx );
151 2 : return pNode;
152 :
153 : case ND_TEXTNODE:
154 : case ND_GRFNODE:
155 : case ND_OLENODE:
156 33 : ((SwCntntNode*)pNd)->MakeFrms( *pNode );
157 33 : return pNode;
158 :
159 : case ND_ENDNODE:
160 95 : if( pNd->StartOfSectionNode()->IsSectionNode() &&
161 0 : aTmp.GetIndex() < rWhere.GetIndex() )
162 : {
163 0 : if( pNd->StartOfSectionNode()->GetSectionNode()->GetSection().IsHiddenFlag())
164 : {
165 0 : if( !GoPrevSection( &aTmp, sal_True, sal_False ) ||
166 0 : aTmp.GetNode().FindTableNode() !=
167 0 : pNode->FindTableNode() )
168 0 : return pNode; // schade, das wars
169 : }
170 : else
171 0 : aTmp = *pNd->StartOfSectionNode();
172 0 : break;
173 : }
174 95 : else if( pNd->StartOfSectionNode()->IsTableNode() &&
175 0 : aTmp.GetIndex() < rWhere.GetIndex() )
176 : {
177 : // wir stehen hinter einem TabellenNode
178 0 : aTmp = *pNd->StartOfSectionNode();
179 0 : break;
180 : }
181 : // kein break !!!
182 : default:
183 148 : if( rWhere == aTmp )
184 74 : aTmp -= 2;
185 : else
186 74 : return pNode;
187 74 : break;
188 : }
189 871 : } while( true );
190 : }
191 :
192 : // --------------------
193 : // SwTxtNode
194 : // --------------------
195 :
196 8981 : SwTxtNode::SwTxtNode( const SwNodeIndex &rWhere,
197 : SwTxtFmtColl *pTxtColl,
198 : const SfxItemSet* pAutoAttr )
199 : : SwCntntNode( rWhere, ND_TEXTNODE, pTxtColl ),
200 : m_pSwpHints( 0 ),
201 : mpNodeNum( 0 ),
202 : m_bLastOutlineState( false ),
203 : m_bNotifiable( false ),
204 : // #i70748#
205 : mbEmptyListStyleSetDueToSetOutlineLevelAttr( false ),
206 : mbInSetOrResetAttr( false ),
207 8981 : mpList( 0 )
208 : {
209 8981 : InitSwParaStatistics( true );
210 :
211 : // soll eine Harte-Attributierung gesetzt werden?
212 8981 : if( pAutoAttr )
213 1139 : SetAttr( *pAutoAttr );
214 :
215 8981 : if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
216 : {
217 : // #i101516#
218 : // apply paragraph style's assigned outline style list level as
219 : // list level of the paragraph, if it has none set already.
220 154 : if ( !HasAttrListLevel() &&
221 77 : pTxtColl && pTxtColl->IsAssignedToListLevelOfOutlineStyle() )
222 : {
223 0 : SetAttrListLevel( pTxtColl->GetAssignedOutlineStyleLevel() );
224 : }
225 77 : AddToList();
226 : }
227 8981 : GetNodes().UpdateOutlineNode(*this);
228 :
229 8981 : m_bNotifiable = true;
230 :
231 8981 : m_bContainsHiddenChars = m_bHiddenCharsHidePara = false;
232 8981 : m_bRecalcHiddenCharFlags = true;
233 8981 : }
234 :
235 26823 : SwTxtNode::~SwTxtNode()
236 : {
237 : // delete loescht nur die Pointer, nicht die Arrayelemente!
238 8941 : if ( m_pSwpHints )
239 : {
240 : // damit Attribute die ihren Inhalt entfernen nicht doppelt
241 : // geloescht werden.
242 1561 : SwpHints* pTmpHints = m_pSwpHints;
243 1561 : m_pSwpHints = 0;
244 :
245 7327 : for( sal_uInt16 j = pTmpHints->Count(); j; )
246 : // erst muss das Attribut aus dem Array entfernt werden,
247 : // denn sonst wuerde es sich selbst loeschen (Felder) !!!!
248 4205 : DestroyAttr( pTmpHints->GetTextHint( --j ) );
249 :
250 1561 : delete pTmpHints;
251 : }
252 :
253 : // must be removed from outline nodes by now
254 : #if OSL_DEBUG_LEVEL > 0
255 : sal_uInt16 foo;
256 : assert(!GetNodes().GetOutLineNds().Seek_Entry(this, &foo));
257 : #endif
258 :
259 8941 : RemoveFromList();
260 :
261 8941 : InitSwParaStatistics( false );
262 17882 : }
263 :
264 4202 : SwCntntFrm *SwTxtNode::MakeFrm( SwFrm* pSib )
265 : {
266 : // fdo#52028: ODF file import does not result in MergePortions being called
267 : // for every attribute, since that would be inefficient. So call it here.
268 4202 : if (m_pSwpHints)
269 : {
270 714 : m_pSwpHints->MergePortions(*this);
271 : }
272 4202 : SwCntntFrm *pFrm = new SwTxtFrm( this, pSib );
273 4202 : return pFrm;
274 : }
275 :
276 188456 : xub_StrLen SwTxtNode::Len() const
277 : {
278 188456 : return m_Text.getLength();
279 : }
280 :
281 : /*---------------------------------------------------------------------------
282 : * lcl_ChangeFtnRef
283 : * After a split node, it's necessary to actualize the ref-pointer of the
284 : * ftnfrms.
285 : * --------------------------------------------------------------------------*/
286 :
287 507 : static void lcl_ChangeFtnRef( SwTxtNode &rNode )
288 : {
289 507 : SwpHints *pSwpHints = rNode.GetpSwpHints();
290 507 : if( pSwpHints && rNode.GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225
291 : {
292 : SwTxtAttr* pHt;
293 0 : SwCntntFrm* pFrm = NULL;
294 : // OD 07.11.2002 #104840# - local variable to remember first footnote
295 : // of node <rNode> in order to invalidate position of its first content.
296 : // Thus, in its <MakeAll()> it will checked its position relative to its reference.
297 0 : SwFtnFrm* pFirstFtnOfNode = 0;
298 0 : for( sal_uInt16 j = pSwpHints->Count(); j; )
299 : {
300 0 : pHt = pSwpHints->GetTextHint(--j);
301 0 : if (RES_TXTATR_FTN == pHt->Which())
302 : {
303 0 : if( !pFrm )
304 : {
305 0 : pFrm = SwIterator<SwCntntFrm,SwTxtNode>::FirstElement( rNode );
306 0 : if( !pFrm )
307 507 : return;
308 : }
309 0 : SwTxtFtn *pAttr = (SwTxtFtn*)pHt;
310 : OSL_ENSURE( pAttr->GetStartNode(), "FtnAtr ohne StartNode." );
311 0 : SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
312 0 : SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
313 0 : if ( !pNd )
314 : pNd = pFrm->GetAttrSet()->GetDoc()->
315 0 : GetNodes().GoNextSection( &aIdx, sal_True, sal_False );
316 0 : if ( !pNd )
317 0 : continue;
318 :
319 0 : SwIterator<SwCntntFrm,SwCntntNode> aIter( *pNd );
320 0 : SwCntntFrm* pCntnt = aIter.First();
321 0 : if( pCntnt )
322 : {
323 : OSL_ENSURE( pCntnt->getRootFrm() == pFrm->getRootFrm(),
324 : "lcl_ChangeFtnRef: Layout double?" );
325 0 : SwFtnFrm *pFtn = pCntnt->FindFtnFrm();
326 0 : if( pFtn && pFtn->GetAttr() == pAttr )
327 : {
328 0 : while( pFtn->GetMaster() )
329 0 : pFtn = pFtn->GetMaster();
330 : // #104840# - remember footnote frame
331 0 : pFirstFtnOfNode = pFtn;
332 0 : while ( pFtn )
333 : {
334 0 : pFtn->SetRef( pFrm );
335 0 : pFtn = pFtn->GetFollow();
336 0 : ((SwTxtFrm*)pFrm)->SetFtn( sal_True );
337 : }
338 : }
339 : #if OSL_DEBUG_LEVEL > 0
340 : while( 0 != (pCntnt = aIter.Next()) )
341 : {
342 : SwFtnFrm *pDbgFtn = pCntnt->FindFtnFrm();
343 : OSL_ENSURE( !pDbgFtn || pDbgFtn->GetRef() == pFrm,
344 : "lcl_ChangeFtnRef: Who's that guy?" );
345 : }
346 : #endif
347 0 : }
348 : }
349 : } // end of for-loop on <SwpHints>
350 : // #104840# - invalidate
351 0 : if ( pFirstFtnOfNode )
352 : {
353 0 : SwCntntFrm* pCntnt = pFirstFtnOfNode->ContainsCntnt();
354 0 : if ( pCntnt )
355 : {
356 0 : pCntnt->_InvalidatePos();
357 : }
358 : }
359 : }
360 : }
361 :
362 507 : SwCntntNode *SwTxtNode::SplitCntntNode( const SwPosition &rPos )
363 : {
364 507 : bool parentIsOutline = IsOutline();
365 :
366 : // lege den Node "vor" mir an
367 507 : const xub_StrLen nSplitPos = rPos.nContent.GetIndex();
368 507 : const xub_StrLen nTxtLen = m_Text.getLength();
369 : SwTxtNode* const pNode =
370 507 : _MakeNewTxtNode( rPos.nNode, sal_False, nSplitPos==nTxtLen );
371 :
372 : // the first paragraph gets the XmlId,
373 : // _except_ if it is empty and the second is not empty
374 507 : if (nSplitPos != 0) {
375 402 : pNode->RegisterAsCopyOf(*this, true);
376 402 : if (nSplitPos == nTxtLen)
377 : {
378 362 : this->RemoveMetadataReference();
379 : // NB: SwUndoSplitNode will call pNode->JoinNext,
380 : // which is sufficient even in this case!
381 : }
382 : }
383 :
384 507 : ResetAttr( RES_PARATR_LIST_ISRESTART );
385 507 : ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
386 507 : ResetAttr( RES_PARATR_LIST_ISCOUNTED );
387 507 : if ( GetNumRule() == 0 || (parentIsOutline && !IsOutline()) )
388 : {
389 507 : ResetAttr( RES_PARATR_LIST_ID );
390 507 : ResetAttr( RES_PARATR_LIST_LEVEL );
391 : }
392 :
393 507 : if ( GetDepends() && !m_Text.isEmpty() && (nTxtLen / 2) < nSplitPos )
394 : {
395 : // JP 25.04.95: Optimierung fuer SplitNode:
396 : // Wird am Ende vom Node gesplittet, dann verschiebe die
397 : // Frames vom akt. auf den neuen und erzeuge fuer den akt.
398 : // neue. Dadurch entfaellt das neu aufbauen vom Layout.
399 :
400 104 : LockModify(); // Benachrichtigungen abschalten
401 :
402 : // werden FlyFrames mit verschoben, so muessen diese nicht ihre
403 : // Frames zerstoeren. Im SwTxtFly::SetAnchor wird es abgefragt!
404 104 : if ( HasHints() )
405 : {
406 2 : pNode->GetOrCreateSwpHints().SetInSplitNode(true);
407 : }
408 :
409 : //Ersten Teil des Inhalts in den neuen Node uebertragen und
410 : //im alten Node loeschen.
411 104 : SwIndex aIdx( this );
412 104 : CutText( pNode, aIdx, nSplitPos );
413 :
414 104 : if( GetWrong() )
415 : {
416 47 : pNode->SetWrong( GetWrong()->SplitList( nSplitPos ) );
417 : }
418 104 : SetWrongDirty( true );
419 :
420 104 : if( GetGrammarCheck() )
421 : {
422 0 : pNode->SetGrammarCheck( GetGrammarCheck()->SplitGrammarList( nSplitPos ) );
423 : }
424 104 : SetGrammarCheckDirty( true );
425 :
426 104 : SetWordCountDirty( true );
427 :
428 : // SMARTTAGS
429 104 : if( GetSmartTags() )
430 : {
431 0 : pNode->SetSmartTags( GetSmartTags()->SplitList( nSplitPos ) );
432 : }
433 104 : SetSmartTagDirty( true );
434 :
435 104 : if ( pNode->HasHints() )
436 : {
437 2 : if ( pNode->m_pSwpHints->CanBeDeleted() )
438 : {
439 0 : delete pNode->m_pSwpHints;
440 0 : pNode->m_pSwpHints = 0;
441 : }
442 : else
443 : {
444 2 : pNode->m_pSwpHints->SetInSplitNode(false);
445 : }
446 :
447 : // alle zeichengebundenen Rahmen, die im neuen Absatz laden
448 : // muessen aus den alten Frame entfernt werden:
449 : // JP 01.10.96: alle leeren und nicht zu expandierenden
450 : // Attribute loeschen
451 2 : if ( HasHints() )
452 : {
453 0 : for ( sal_uInt16 j = m_pSwpHints->Count(); j; )
454 : {
455 0 : SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
456 0 : if ( RES_TXTATR_FLYCNT == pHt ->Which() )
457 : {
458 0 : pHt->GetFlyCnt().GetFrmFmt()->DelFrms();
459 : }
460 0 : else if ( pHt->DontExpand() )
461 : {
462 0 : const xub_StrLen* const pEnd = pHt->GetEnd();
463 0 : if (pEnd && *pHt->GetStart() == *pEnd )
464 : {
465 : // delete it!
466 0 : m_pSwpHints->DeleteAtPos( j );
467 0 : DestroyAttr( pHt );
468 : }
469 : }
470 : }
471 : }
472 :
473 : }
474 :
475 208 : SwIterator<SwCntntFrm,SwTxtNode> aIter( *this );
476 210 : for( SwCntntFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
477 : {
478 106 : pFrm->RegisterToNode( *pNode );
479 106 : if( pFrm->IsTxtFrm() && !pFrm->IsFollow() && ((SwTxtFrm*)pFrm)->GetOfst() )
480 0 : ((SwTxtFrm*)pFrm)->SetOfst( 0 );
481 : }
482 :
483 104 : if ( IsInCache() )
484 : {
485 92 : SwFrm::GetCache().Delete( this );
486 92 : SetInCache( sal_False );
487 : }
488 :
489 104 : UnlockModify(); // Benachrichtigungen wieder freischalten
490 :
491 : // If there is an accessible layout we must call modify even
492 : // with length zero, because we have to notify about the changed
493 : // text node.
494 : const SwRootFrm *pRootFrm;
495 208 : if ( (nTxtLen != nSplitPos) ||
496 202 : ( (pRootFrm = pNode->GetDoc()->GetCurrentLayout()) != 0 &&
497 101 : pRootFrm->IsAnyShellAccessible() ) ) //swmod 080218
498 : {
499 : // dann sage den Frames noch, das am Ende etwas "geloescht" wurde
500 3 : if( 1 == nTxtLen - nSplitPos )
501 : {
502 0 : SwDelChr aHint( nSplitPos );
503 0 : pNode->NotifyClients( 0, &aHint );
504 : }
505 : else
506 : {
507 3 : SwDelTxt aHint( nSplitPos, nTxtLen - nSplitPos );
508 3 : pNode->NotifyClients( 0, &aHint );
509 : }
510 : }
511 104 : if ( HasHints() )
512 : {
513 0 : MoveTxtAttr_To_AttrSet();
514 : }
515 104 : pNode->MakeFrms( *this ); // neue Frames anlegen.
516 208 : lcl_ChangeFtnRef( *this );
517 : }
518 : else
519 : {
520 403 : SwWrongList *pList = GetWrong();
521 403 : SetWrong( 0, false );
522 403 : SetWrongDirty( true );
523 :
524 403 : SwGrammarMarkUp *pList3 = GetGrammarCheck();
525 403 : SetGrammarCheck( 0, false );
526 403 : SetGrammarCheckDirty( true );
527 :
528 403 : SetWordCountDirty( true );
529 :
530 : // SMARTTAGS
531 403 : SwWrongList *pList2 = GetSmartTags();
532 403 : SetSmartTags( 0, false );
533 403 : SetSmartTagDirty( true );
534 :
535 403 : SwIndex aIdx( this );
536 403 : CutText( pNode, aIdx, nSplitPos );
537 :
538 : // JP 01.10.96: alle leeren und nicht zu expandierenden
539 : // Attribute loeschen
540 403 : if ( HasHints() )
541 : {
542 0 : for ( sal_uInt16 j = m_pSwpHints->Count(); j; )
543 : {
544 0 : SwTxtAttr* const pHt = m_pSwpHints->GetTextHint( --j );
545 0 : const xub_StrLen* const pEnd = pHt->GetEnd();
546 0 : if ( pHt->DontExpand() && pEnd && (*pHt->GetStart() == *pEnd) )
547 : {
548 : // delete it!
549 0 : m_pSwpHints->DeleteAtPos( j );
550 0 : DestroyAttr( pHt );
551 : }
552 : }
553 0 : MoveTxtAttr_To_AttrSet();
554 : }
555 :
556 403 : if( pList )
557 : {
558 13 : pNode->SetWrong( pList->SplitList( nSplitPos ) );
559 13 : SetWrong( pList, false );
560 : }
561 :
562 403 : if( pList3 )
563 : {
564 0 : pNode->SetGrammarCheck( pList3->SplitGrammarList( nSplitPos ) );
565 0 : SetGrammarCheck( pList3, false );
566 : }
567 :
568 : // SMARTTAGS
569 403 : if( pList2 )
570 : {
571 0 : pNode->SetSmartTags( pList2->SplitList( nSplitPos ) );
572 0 : SetSmartTags( pList2, false );
573 : }
574 :
575 403 : if ( GetDepends() )
576 : {
577 133 : MakeFrms( *pNode ); // neue Frames anlegen.
578 : }
579 403 : lcl_ChangeFtnRef( *pNode );
580 : }
581 :
582 : {
583 : //Hint fuer Pagedesc versenden. Das mueste eigntlich das Layout im
584 : //Paste der Frames selbst erledigen, aber das fuehrt dann wiederum
585 : //zu weiteren Folgefehlern, die mit Laufzeitkosten geloest werden
586 : //muesten. #56977# #55001# #56135#
587 : const SfxPoolItem *pItem;
588 744 : if( GetDepends() && SFX_ITEM_SET == pNode->GetSwAttrSet().
589 237 : GetItemState( RES_PAGEDESC, sal_True, &pItem ) )
590 : {
591 0 : pNode->ModifyNotification( (SfxPoolItem*)pItem, (SfxPoolItem*)pItem );
592 : }
593 : }
594 507 : return pNode;
595 : }
596 :
597 0 : void SwTxtNode::MoveTxtAttr_To_AttrSet()
598 : {
599 : OSL_ENSURE( m_pSwpHints, "MoveTxtAttr_To_AttrSet without SwpHints?" );
600 0 : for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
601 : {
602 0 : SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);
603 :
604 0 : if( *pHt->GetStart() )
605 0 : break;
606 :
607 0 : const xub_StrLen* pHtEndIdx = pHt->GetEnd();
608 :
609 0 : if( !pHtEndIdx )
610 0 : continue;
611 :
612 0 : if (*pHtEndIdx < m_Text.getLength() || pHt->IsCharFmtAttr())
613 0 : break;
614 :
615 0 : if( !pHt->IsDontMoveAttr() &&
616 0 : SetAttr( pHt->GetAttr() ) )
617 : {
618 0 : m_pSwpHints->DeleteAtPos(i);
619 0 : DestroyAttr( pHt );
620 0 : --i;
621 : }
622 : }
623 :
624 0 : }
625 :
626 551 : SwCntntNode *SwTxtNode::JoinNext()
627 : {
628 551 : SwNodes& rNds = GetNodes();
629 551 : SwNodeIndex aIdx( *this );
630 551 : if( SwCntntNode::CanJoinNext( &aIdx ) )
631 : {
632 551 : SwDoc* pDoc = rNds.GetDoc();
633 551 : std::vector<sal_uLong> aBkmkArr;
634 551 : _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
635 551 : SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
636 551 : xub_StrLen nOldLen = m_Text.getLength();
637 :
638 : // METADATA: merge
639 551 : this->JoinMetadatable(*pTxtNode, !this->Len(), !pTxtNode->Len());
640 :
641 551 : SwWrongList *pList = GetWrong();
642 551 : if( pList )
643 : {
644 6 : pList->JoinList( pTxtNode->GetWrong(), nOldLen );
645 6 : SetWrongDirty( true );
646 6 : SetWrong( 0, false );
647 : }
648 : else
649 : {
650 545 : pList = pTxtNode->GetWrong();
651 545 : if( pList )
652 : {
653 5 : pList->Move( 0, nOldLen );
654 5 : SetWrongDirty( true );
655 5 : pTxtNode->SetWrong( 0, false );
656 : }
657 : }
658 :
659 551 : SwGrammarMarkUp *pList3 = GetGrammarCheck();
660 551 : if( pList3 )
661 : {
662 0 : pList3->JoinGrammarList( pTxtNode->GetGrammarCheck(), nOldLen );
663 0 : SetGrammarCheckDirty( true );
664 0 : SetGrammarCheck( 0, false );
665 : }
666 : else
667 : {
668 551 : pList3 = pTxtNode->GetGrammarCheck();
669 551 : if( pList3 )
670 : {
671 0 : pList3->MoveGrammar( 0, nOldLen );
672 0 : SetGrammarCheckDirty( true );
673 0 : pTxtNode->SetGrammarCheck( 0, false );
674 : }
675 : }
676 :
677 : // SMARTTAGS
678 551 : SwWrongList *pList2 = GetSmartTags();
679 551 : if( pList2 )
680 : {
681 0 : pList2->JoinList( pTxtNode->GetSmartTags(), nOldLen );
682 0 : SetSmartTagDirty( true );
683 0 : SetSmartTags( 0, false );
684 : }
685 : else
686 : {
687 551 : pList2 = pTxtNode->GetSmartTags();
688 551 : if( pList2 )
689 : {
690 0 : pList2->Move( 0, nOldLen );
691 0 : SetSmartTagDirty( true );
692 0 : pTxtNode->SetSmartTags( 0, false );
693 : }
694 : }
695 :
696 : { // wg. SwIndex
697 551 : pTxtNode->CutText( this, SwIndex(pTxtNode), pTxtNode->Len() );
698 : }
699 : // verschiebe noch alle Bookmarks/TOXMarks
700 551 : if( !aBkmkArr.empty() )
701 0 : _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex(), nOldLen );
702 :
703 551 : if( pTxtNode->HasAnyIndex() )
704 : {
705 : // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
706 0 : pDoc->CorrAbs( aIdx, SwPosition( *this ), nOldLen, sal_True );
707 : }
708 551 : rNds.Delete(aIdx);
709 551 : SetWrong( pList, false );
710 551 : SetGrammarCheck( pList3, false );
711 551 : SetSmartTags( pList2, false ); // SMARTTAGS
712 551 : InvalidateNumRule();
713 : }
714 : else {
715 : OSL_FAIL( "kein TxtNode." );
716 : }
717 :
718 551 : return this;
719 : }
720 :
721 2 : SwCntntNode *SwTxtNode::JoinPrev()
722 : {
723 2 : SwNodes& rNds = GetNodes();
724 2 : SwNodeIndex aIdx( *this );
725 2 : if( SwCntntNode::CanJoinPrev( &aIdx ) )
726 : {
727 2 : SwDoc* pDoc = rNds.GetDoc();
728 2 : std::vector<sal_uLong> aBkmkArr;
729 2 : _SaveCntntIdx( pDoc, aIdx.GetIndex(), USHRT_MAX, aBkmkArr, SAVEFLY );
730 2 : SwTxtNode *pTxtNode = aIdx.GetNode().GetTxtNode();
731 2 : xub_StrLen nLen = pTxtNode->Len();
732 :
733 2 : SwWrongList *pList = pTxtNode->GetWrong();
734 2 : if( pList )
735 : {
736 1 : pList->JoinList( GetWrong(), Len() );
737 1 : SetWrongDirty( true );
738 1 : pTxtNode->SetWrong( 0, false );
739 1 : SetWrong( NULL );
740 : }
741 : else
742 : {
743 1 : pList = GetWrong();
744 1 : if( pList )
745 : {
746 0 : pList->Move( 0, nLen );
747 0 : SetWrongDirty( true );
748 0 : SetWrong( 0, false );
749 : }
750 : }
751 :
752 2 : SwGrammarMarkUp *pList3 = pTxtNode->GetGrammarCheck();
753 2 : if( pList3 )
754 : {
755 0 : pList3->JoinGrammarList( GetGrammarCheck(), Len() );
756 0 : SetGrammarCheckDirty( true );
757 0 : pTxtNode->SetGrammarCheck( 0, false );
758 0 : SetGrammarCheck( NULL );
759 : }
760 : else
761 : {
762 2 : pList3 = GetGrammarCheck();
763 2 : if( pList3 )
764 : {
765 0 : pList3->MoveGrammar( 0, nLen );
766 0 : SetGrammarCheckDirty( true );
767 0 : SetGrammarCheck( 0, false );
768 : }
769 : }
770 :
771 : // SMARTTAGS
772 2 : SwWrongList *pList2 = pTxtNode->GetSmartTags();
773 2 : if( pList2 )
774 : {
775 0 : pList2->JoinList( GetSmartTags(), Len() );
776 0 : SetSmartTagDirty( true );
777 0 : pTxtNode->SetSmartTags( 0, false );
778 0 : SetSmartTags( NULL );
779 : }
780 : else
781 : {
782 2 : pList2 = GetSmartTags();
783 2 : if( pList2 )
784 : {
785 0 : pList2->Move( 0, nLen );
786 0 : SetSmartTagDirty( true );
787 0 : SetSmartTags( 0, false );
788 : }
789 : }
790 :
791 : { // wg. SwIndex
792 2 : pTxtNode->CutText( this, SwIndex(this), SwIndex(pTxtNode), nLen );
793 : }
794 : // verschiebe noch alle Bookmarks/TOXMarks
795 2 : if( !aBkmkArr.empty() )
796 0 : _RestoreCntntIdx( pDoc, aBkmkArr, GetIndex() );
797 :
798 2 : if( pTxtNode->HasAnyIndex() )
799 : {
800 : // alle Crsr/StkCrsr/UnoCrsr aus dem Loeschbereich verschieben
801 0 : pDoc->CorrAbs( aIdx, SwPosition( *this ), nLen, sal_True );
802 : }
803 2 : rNds.Delete(aIdx);
804 2 : SetWrong( pList, false );
805 2 : SetGrammarCheck( pList3, false );
806 2 : SetSmartTags( pList2, false );
807 2 : InvalidateNumRule();
808 : }
809 : else {
810 : OSL_FAIL( "kein TxtNode." );
811 : }
812 :
813 2 : return this;
814 : }
815 :
816 : // erzeugt einen AttrSet mit Bereichen fuer Frame-/Para/Char-Attributen
817 5545 : void SwTxtNode::NewAttrSet( SwAttrPool& rPool )
818 : {
819 : OSL_ENSURE( !mpAttrSet.get(), "AttrSet ist doch gesetzt" );
820 5545 : SwAttrSet aNewAttrSet( rPool, aTxtNodeSetRange );
821 :
822 : // put names of parent style and conditional style:
823 5545 : const SwFmtColl* pAnyFmtColl = &GetAnyFmtColl();
824 5545 : const SwFmtColl* pFmtColl = GetFmtColl();
825 11090 : String sVal;
826 5545 : SwStyleNameMapper::FillProgName( pAnyFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, true );
827 11090 : SfxStringItem aAnyFmtColl( RES_FRMATR_STYLE_NAME, sVal );
828 5545 : if ( pFmtColl != pAnyFmtColl )
829 0 : SwStyleNameMapper::FillProgName( pFmtColl->GetName(), sVal, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL, true );
830 11090 : SfxStringItem aFmtColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal );
831 5545 : aNewAttrSet.Put( aAnyFmtColl );
832 5545 : aNewAttrSet.Put( aFmtColl );
833 :
834 5545 : aNewAttrSet.SetParent( &pAnyFmtColl->GetAttrSet() );
835 11090 : mpAttrSet = GetDoc()->GetIStyleAccess().getAutomaticStyle( aNewAttrSet, IStyleAccess::AUTO_STYLE_PARA );
836 5545 : }
837 :
838 :
839 : // override SwIndexReg::Update => text hints do not need SwIndex for start/end!
840 62358 : void SwTxtNode::Update( SwIndex const & rPos, const xub_StrLen nChangeLen,
841 : const bool bNegative, const bool bDelete )
842 : {
843 62358 : SetAutoCompleteWordDirty( sal_True );
844 :
845 62358 : ::std::auto_ptr<SwpHts> pCollector;
846 62358 : const xub_StrLen nChangePos = rPos.GetIndex();
847 :
848 62358 : if ( HasHints() )
849 : {
850 1437 : if ( bNegative )
851 : {
852 97 : const xub_StrLen nChangeEnd = nChangePos + nChangeLen;
853 220 : for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
854 : {
855 123 : SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
856 123 : xub_StrLen * const pStart = pHint->GetStart();
857 123 : if ( *pStart > nChangePos )
858 : {
859 35 : if ( *pStart > nChangeEnd )
860 : {
861 16 : *pStart = *pStart - nChangeLen;
862 : }
863 : else
864 : {
865 19 : *pStart = nChangePos;
866 : }
867 : }
868 :
869 123 : xub_StrLen * const pEnd = pHint->GetEnd();
870 123 : if (pEnd)
871 : {
872 82 : if ( *pEnd > nChangePos )
873 : {
874 76 : if( *pEnd > nChangeEnd )
875 : {
876 16 : *pEnd = *pEnd - nChangeLen;
877 : }
878 : else
879 : {
880 60 : *pEnd = nChangePos;
881 : }
882 : }
883 : }
884 : }
885 :
886 97 : m_pSwpHints->MergePortions( *this );
887 : }
888 : else
889 : {
890 1340 : bool bNoExp = false;
891 1340 : bool bResort = false;
892 1340 : bool bMergePortionsNeeded = false;
893 : const sal_uInt16 coArrSz = static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
894 1340 : static_cast<sal_uInt16>(RES_CHRATR_BEGIN);
895 :
896 : sal_Bool aDontExp[ coArrSz ];
897 1340 : memset( &aDontExp, 0, coArrSz * sizeof(sal_Bool) );
898 :
899 116026 : for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
900 : {
901 114686 : SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(n);
902 114686 : xub_StrLen * const pStart = pHint->GetStart();
903 114686 : xub_StrLen * const pEnd = pHint->GetEnd();
904 114686 : if ( *pStart >= nChangePos )
905 : {
906 65 : *pStart = *pStart + nChangeLen;
907 65 : if ( pEnd )
908 : {
909 38 : *pEnd = *pEnd + nChangeLen;
910 : }
911 : }
912 114621 : else if ( pEnd && (*pEnd >= nChangePos) )
913 : {
914 574 : if ( (*pEnd > nChangePos) || IsIgnoreDontExpand() )
915 : {
916 124 : *pEnd = *pEnd + nChangeLen;
917 : }
918 : else // *pEnd == nChangePos
919 : {
920 : sal_uInt16 nWhPos;
921 450 : const sal_uInt16 nWhich = pHint->Which();
922 :
923 : OSL_ENSURE(!isCHRATR(nWhich), "Update: char attr hint?");
924 450 : if (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich))
925 : {
926 : nWhPos = static_cast<sal_uInt16>(nWhich -
927 450 : RES_CHRATR_BEGIN);
928 : }
929 : else
930 0 : continue;
931 :
932 450 : if( aDontExp[ nWhPos ] )
933 27 : continue;
934 :
935 423 : if ( pHint->DontExpand() )
936 : {
937 414 : pHint->SetDontExpand( false );
938 414 : bResort = true;
939 : // could have a continuation with IgnoreStart()...
940 414 : if (pHint->IsFormatIgnoreEnd())
941 : {
942 0 : bMergePortionsNeeded = true;
943 : }
944 414 : if ( pHint->IsCharFmtAttr() )
945 : {
946 18 : bNoExp = true;
947 : aDontExp[ static_cast<sal_uInt16>(RES_TXTATR_CHARFMT) - static_cast<sal_uInt16>(RES_CHRATR_BEGIN) ]
948 18 : = sal_True;
949 : aDontExp[ static_cast<sal_uInt16>(RES_TXTATR_INETFMT) - static_cast<sal_uInt16>(RES_CHRATR_BEGIN) ]
950 18 : = sal_True;
951 : }
952 : else
953 396 : aDontExp[ nWhPos ] = sal_True;
954 : }
955 9 : else if( bNoExp )
956 : {
957 0 : if ( !pCollector.get() )
958 : {
959 0 : pCollector.reset( new SwpHts );
960 : }
961 0 : for(SwpHts::iterator it = pCollector->begin(); it != pCollector->end(); ++it)
962 : {
963 0 : SwTxtAttr *pTmp = *it;
964 0 : if( nWhich == pTmp->Which() )
965 : {
966 0 : pCollector->erase( it );
967 : SwTxtAttr::Destroy( pTmp,
968 0 : GetDoc()->GetAttrPool() );
969 0 : break;
970 : }
971 : }
972 0 : SwTxtAttr * const pTmp = MakeTxtAttr( *GetDoc(),
973 0 : pHint->GetAttr(),
974 0 : nChangePos, nChangePos + nChangeLen);
975 0 : pCollector->push_back( pTmp );
976 : }
977 : else
978 : {
979 9 : *pEnd = *pEnd + nChangeLen;
980 : }
981 : }
982 : }
983 : }
984 1340 : if (bMergePortionsNeeded)
985 : {
986 0 : m_pSwpHints->MergePortions(*this); // does Resort too
987 : }
988 1340 : else if (bResort)
989 : {
990 362 : m_pSwpHints->Resort();
991 : }
992 : }
993 : }
994 :
995 124716 : SwIndexReg aTmpIdxReg;
996 62358 : if ( !bNegative && !bDelete )
997 : {
998 61184 : const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();
999 74855 : for ( sal_uInt16 i = 0; i < rTbl.size(); ++i )
1000 : {
1001 13671 : SwRedline *const pRedl = rTbl[ i ];
1002 13671 : if ( pRedl->HasMark() )
1003 : {
1004 13660 : SwPosition* const pEnd = pRedl->End();
1005 27313 : if ( this == &pEnd->nNode.GetNode() &&
1006 13653 : *pRedl->GetPoint() != *pRedl->GetMark() )
1007 : {
1008 13653 : SwIndex & rIdx = pEnd->nContent;
1009 13653 : if (nChangePos == rIdx.GetIndex())
1010 : {
1011 451 : rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1012 : }
1013 : }
1014 : }
1015 11 : else if ( this == &pRedl->GetPoint()->nNode.GetNode() )
1016 : {
1017 0 : SwIndex & rIdx = pRedl->GetPoint()->nContent;
1018 0 : if (nChangePos == rIdx.GetIndex())
1019 : {
1020 0 : rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1021 : // mst: FIXME: why does this adjust the unused position???
1022 : SwIndex * pIdx;
1023 0 : if ( &pRedl->GetBound( true ) == pRedl->GetPoint() )
1024 : {
1025 0 : pRedl->GetBound( false ) = pRedl->GetBound( true );
1026 0 : pIdx = &pRedl->GetBound( false ).nContent;
1027 : }
1028 : else
1029 : {
1030 0 : pRedl->GetBound( true ) = pRedl->GetBound( false );
1031 0 : pIdx = &pRedl->GetBound( true ).nContent;
1032 : }
1033 0 : pIdx->Assign( &aTmpIdxReg, pIdx->GetIndex() );
1034 : }
1035 : }
1036 : }
1037 :
1038 61184 : const IDocumentMarkAccess* const pMarkAccess = getIDocumentMarkAccess();
1039 7625661 : for(IDocumentMarkAccess::const_iterator_t ppMark =
1040 61184 : pMarkAccess->getMarksBegin();
1041 5083774 : ppMark != pMarkAccess->getMarksEnd();
1042 : ++ppMark)
1043 : {
1044 : // Bookmarks must never grow to either side, when
1045 : // editing (directly) to the left or right (#i29942#)!
1046 : // And a bookmark with same start and end must remain
1047 : // to the left of the inserted text (used in XML import).
1048 2480703 : const ::sw::mark::IMark* const pMark = ppMark->get();
1049 2480703 : const SwPosition* pEnd = &pMark->GetMarkEnd();
1050 2480703 : SwIndex & rIdx = const_cast<SwIndex&>(pEnd->nContent);
1051 2783380 : if( this == &pEnd->nNode.GetNode() &&
1052 302677 : rPos.GetIndex() == rIdx.GetIndex() )
1053 : {
1054 2877 : rIdx.Assign( &aTmpIdxReg, rIdx.GetIndex() );
1055 : }
1056 : }
1057 : }
1058 :
1059 : // base class
1060 62358 : SwIndexReg::Update( rPos, nChangeLen, bNegative, bDelete );
1061 :
1062 62358 : if ( pCollector.get() )
1063 : {
1064 0 : const sal_uInt16 nCount = pCollector->size();
1065 0 : for ( sal_uInt16 i = 0; i < nCount; ++i )
1066 : {
1067 0 : m_pSwpHints->TryInsertHint( (*pCollector)[ i ], *this );
1068 : }
1069 : }
1070 :
1071 124716 : aTmpIdxReg.MoveTo( *this );
1072 62358 : }
1073 :
1074 13615 : void SwTxtNode::_ChgTxtCollUpdateNum( const SwTxtFmtColl *pOldColl,
1075 : const SwTxtFmtColl *pNewColl)
1076 : {
1077 13615 : SwDoc* pDoc = GetDoc();
1078 : OSL_ENSURE( pDoc, "Kein Doc?" );
1079 : // erfrage die OutlineLevel und update gegebenenfalls das Nodes-Array,
1080 : // falls sich die Level geaendert haben !
1081 8559 : const int nOldLevel = pOldColl && pOldColl->IsAssignedToListLevelOfOutlineStyle() ?
1082 13915 : pOldColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
1083 13615 : const int nNewLevel = pNewColl && pNewColl->IsAssignedToListLevelOfOutlineStyle() ?
1084 14085 : pNewColl->GetAssignedOutlineStyleLevel() : MAXLEVEL;
1085 :
1086 13615 : if ( MAXLEVEL != nNewLevel && -1 != nNewLevel )
1087 : {
1088 469 : SetAttrListLevel(nNewLevel);
1089 : }
1090 13615 : if (pDoc)
1091 : {
1092 13615 : pDoc->GetNodes().UpdateOutlineNode(*this);
1093 : }
1094 :
1095 :
1096 13615 : SwNodes& rNds = GetNodes();
1097 : // Update beim Level 0 noch die Fussnoten !!
1098 27048 : if( ( !nNewLevel || !nOldLevel) && !pDoc->GetFtnIdxs().empty() &&
1099 13615 : FTNNUM_CHAPTER == pDoc->GetFtnInfo().eNum &&
1100 0 : rNds.IsDocNodes() )
1101 : {
1102 0 : SwNodeIndex aTmpIndex( rNds, GetIndex());
1103 :
1104 0 : pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
1105 : }
1106 :
1107 13615 : if( RES_CONDTXTFMTCOLL == pNewColl->Which() )
1108 : {
1109 : // Erfrage die akt. Condition des TextNodes:
1110 26 : ChkCondColl();
1111 : }
1112 13615 : }
1113 :
1114 : // Wenn man sich genau am Ende einer Text- bzw. INetvorlage befindet,
1115 : // bekommt diese das DontExpand-Flag verpasst
1116 :
1117 2735 : bool SwTxtNode::DontExpandFmt( const SwIndex& rIdx, bool bFlag,
1118 : bool bFmtToTxtAttributes )
1119 : {
1120 2735 : const xub_StrLen nIdx = rIdx.GetIndex();
1121 2735 : if (bFmtToTxtAttributes && nIdx == m_Text.getLength())
1122 : {
1123 2657 : FmtToTxtAttr( this );
1124 : }
1125 :
1126 2735 : bool bRet = false;
1127 2735 : if ( HasHints() )
1128 : {
1129 321 : const sal_uInt16 nEndCnt = m_pSwpHints->GetEndCount();
1130 321 : sal_uInt16 nPos = nEndCnt;
1131 1073 : while( nPos )
1132 : {
1133 431 : SwTxtAttr *pTmp = m_pSwpHints->GetEnd( --nPos );
1134 431 : xub_StrLen *pEnd = pTmp->GetEnd();
1135 431 : if( !pEnd || *pEnd > nIdx )
1136 12 : continue;
1137 419 : if( nIdx != *pEnd )
1138 117 : nPos = 0;
1139 900 : else if( bFlag != pTmp->DontExpand() && !pTmp->IsLockExpandFlag()
1140 598 : && *pEnd > *pTmp->GetStart())
1141 : {
1142 296 : bRet = true;
1143 296 : m_pSwpHints->NoteInHistory( pTmp );
1144 296 : pTmp->SetDontExpand( bFlag );
1145 : }
1146 : }
1147 : }
1148 2735 : return bRet;
1149 : }
1150 :
1151 122 : static bool lcl_GetTxtAttrDefault(xub_StrLen const nIndex,
1152 : xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
1153 : {
1154 122 : return ((nHintStart <= nIndex) && (nIndex < nHintEnd));
1155 : }
1156 59 : static bool lcl_GetTxtAttrExpand(xub_StrLen const nIndex,
1157 : xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
1158 : {
1159 59 : return ((nHintStart < nIndex) && (nIndex <= nHintEnd));
1160 : }
1161 21 : static bool lcl_GetTxtAttrParent(xub_StrLen const nIndex,
1162 : xub_StrLen const nHintStart, xub_StrLen const nHintEnd)
1163 : {
1164 21 : return ((nHintStart < nIndex) && (nIndex < nHintEnd));
1165 : }
1166 :
1167 : static void
1168 3356 : lcl_GetTxtAttrs(
1169 : ::std::vector<SwTxtAttr *> *const pVector, SwTxtAttr **const ppTxtAttr,
1170 : SwpHints *const pSwpHints,
1171 : xub_StrLen const nIndex, RES_TXTATR const nWhich,
1172 : enum SwTxtNode::GetTxtAttrMode const eMode)
1173 : {
1174 3356 : sal_uInt16 const nSize = (pSwpHints) ? pSwpHints->Count() : 0;
1175 3356 : xub_StrLen nPreviousIndex(0); // index of last hint with nWhich
1176 3356 : bool (*pMatchFunc)(xub_StrLen const, xub_StrLen const, xub_StrLen const)=0;
1177 3356 : switch (eMode)
1178 : {
1179 3312 : case SwTxtNode::DEFAULT: pMatchFunc = &lcl_GetTxtAttrDefault; break;
1180 32 : case SwTxtNode::EXPAND: pMatchFunc = &lcl_GetTxtAttrExpand; break;
1181 12 : case SwTxtNode::PARENT: pMatchFunc = &lcl_GetTxtAttrParent; break;
1182 : default: assert(false);
1183 : }
1184 :
1185 4892 : for( sal_uInt16 i = 0; i < nSize; ++i )
1186 : {
1187 1583 : SwTxtAttr *const pHint = pSwpHints->GetTextHint(i);
1188 1583 : xub_StrLen const nHintStart( *(pHint->GetStart()) );
1189 1583 : if (nIndex < nHintStart)
1190 : {
1191 3403 : return; // hints are sorted by start, so we are done...
1192 : }
1193 :
1194 1536 : if (pHint->Which() != nWhich)
1195 : {
1196 1324 : continue;
1197 : }
1198 :
1199 212 : xub_StrLen const*const pEndIdx = pHint->GetEnd();
1200 : // cannot have hint with no end and no dummy char
1201 : assert(pEndIdx || pHint->HasDummyChar());
1202 : // Wenn bExpand gesetzt ist, wird das Verhalten bei Eingabe
1203 : // simuliert, d.h. der Start wuede verschoben, das Ende expandiert,
1204 : bool const bContained( (pEndIdx)
1205 202 : ? (*pMatchFunc)(nIndex, nHintStart, *pEndIdx)
1206 414 : : (nHintStart == nIndex) );
1207 212 : if (bContained)
1208 : {
1209 101 : if (pVector)
1210 : {
1211 70 : if (nPreviousIndex < nHintStart)
1212 : {
1213 8 : pVector->clear(); // clear hints that are outside pHint
1214 8 : nPreviousIndex = nHintStart;
1215 : }
1216 70 : pVector->push_back(pHint);
1217 : }
1218 : else
1219 : {
1220 31 : *ppTxtAttr = pHint; // and possibly overwrite outer hint
1221 : }
1222 101 : if (!pEndIdx)
1223 : {
1224 0 : break;
1225 : }
1226 : }
1227 : }
1228 : }
1229 :
1230 : ::std::vector<SwTxtAttr *>
1231 56 : SwTxtNode::GetTxtAttrsAt(xub_StrLen const nIndex, RES_TXTATR const nWhich,
1232 : enum GetTxtAttrMode const eMode) const
1233 : {
1234 56 : ::std::vector<SwTxtAttr *> ret;
1235 56 : lcl_GetTxtAttrs(& ret, 0, m_pSwpHints, nIndex, nWhich, eMode);
1236 56 : return ret;
1237 : }
1238 :
1239 : SwTxtAttr *
1240 3300 : SwTxtNode::GetTxtAttrAt(xub_StrLen const nIndex, RES_TXTATR const nWhich,
1241 : enum GetTxtAttrMode const eMode) const
1242 : {
1243 : assert( (nWhich == RES_TXTATR_META)
1244 : || (nWhich == RES_TXTATR_METAFIELD)
1245 : || (nWhich == RES_TXTATR_AUTOFMT)
1246 : || (nWhich == RES_TXTATR_INETFMT)
1247 : || (nWhich == RES_TXTATR_CJK_RUBY)
1248 : || (nWhich == RES_TXTATR_UNKNOWN_CONTAINER));
1249 : // "GetTxtAttrAt() will give wrong result for this hint!")
1250 :
1251 3300 : SwTxtAttr * pRet(0);
1252 3300 : lcl_GetTxtAttrs(0, & pRet, m_pSwpHints, nIndex, nWhich, eMode);
1253 3300 : return pRet;
1254 : }
1255 :
1256 : /*************************************************************************
1257 : * CopyHint()
1258 : *************************************************************************/
1259 :
1260 0 : static SwCharFmt* lcl_FindCharFmt( const SwCharFmts* pCharFmts, const XubString& rName )
1261 : {
1262 0 : if( rName.Len() )
1263 : {
1264 : SwCharFmt* pFmt;
1265 0 : sal_uInt16 nArrLen = pCharFmts->size();
1266 0 : for( sal_uInt16 i = 1; i < nArrLen; i++ )
1267 : {
1268 0 : pFmt = (*pCharFmts)[ i ];
1269 0 : if( pFmt->GetName().CompareTo( rName ) == COMPARE_EQUAL )
1270 0 : return pFmt;
1271 : }
1272 : }
1273 0 : return NULL;
1274 : }
1275 :
1276 50 : static void lcl_CopyHint( const sal_uInt16 nWhich, const SwTxtAttr * const pHt,
1277 : SwTxtAttr *const pNewHt, SwDoc *const pOtherDoc, SwTxtNode *const pDest )
1278 : {
1279 : assert(nWhich == pHt->Which()); // wrong hint-id
1280 50 : switch( nWhich )
1281 : {
1282 : // copy nodesarray section with footnote content
1283 : case RES_TXTATR_FTN :
1284 : assert(pDest); // "lcl_CopyHint: no destination text node?"
1285 : static_cast<const SwTxtFtn*>(pHt)->CopyFtn(
1286 0 : *static_cast<SwTxtFtn*>(pNewHt), *pDest);
1287 0 : break;
1288 :
1289 : // Beim Kopieren von Feldern in andere Dokumente
1290 : // muessen die Felder bei ihren neuen Feldtypen angemeldet werden.
1291 :
1292 : // TabellenFormel muessen relativ kopiert werden.
1293 : case RES_TXTATR_FIELD :
1294 : {
1295 1 : const SwFmtFld& rFld = pHt->GetFld();
1296 1 : if( pOtherDoc )
1297 : {
1298 : static_cast<const SwTxtFld*>(pHt)->CopyFld(
1299 0 : static_cast<SwTxtFld*>(pNewHt) );
1300 : }
1301 :
1302 : // Tabellenformel ??
1303 2 : if( RES_TABLEFLD == rFld.GetFld()->GetTyp()->Which()
1304 1 : && static_cast<const SwTblField*>(rFld.GetFld())->IsIntrnlName())
1305 : {
1306 : // wandel die interne in eine externe Formel um
1307 : const SwTableNode* const pDstTblNd =
1308 : static_cast<const SwTxtFld*>(pHt)->
1309 0 : GetTxtNode().FindTableNode();
1310 0 : if( pDstTblNd )
1311 : {
1312 : SwTblField* const pTblFld = const_cast<SwTblField*>(
1313 : static_cast<const SwTblField*>(
1314 0 : pNewHt->GetFld().GetFld()));
1315 0 : pTblFld->PtrToBoxNm( &pDstTblNd->GetTable() );
1316 : }
1317 : }
1318 : }
1319 1 : break;
1320 :
1321 : case RES_TXTATR_TOXMARK :
1322 0 : if( pOtherDoc && pDest && pDest->GetpSwpHints()
1323 0 : && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
1324 : {
1325 : // Beim Kopieren von TOXMarks(Client) in andere Dokumente
1326 : // muss der Verzeichnis (Modify) ausgetauscht werden
1327 0 : static_cast<SwTxtTOXMark*>(pNewHt)->CopyTOXMark( pOtherDoc );
1328 : }
1329 0 : break;
1330 :
1331 : case RES_TXTATR_CHARFMT :
1332 : // Wenn wir es mit einer Zeichenvorlage zu tun haben,
1333 : // muessen wir natuerlich auch die Formate kopieren.
1334 0 : if( pDest && pDest->GetpSwpHints()
1335 0 : && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
1336 : {
1337 : SwCharFmt* pFmt =
1338 0 : static_cast<SwCharFmt*>(pHt->GetCharFmt().GetCharFmt());
1339 :
1340 0 : if( pFmt && pOtherDoc )
1341 : {
1342 0 : pFmt = pOtherDoc->CopyCharFmt( *pFmt );
1343 : }
1344 : const_cast<SwFmtCharFmt&>( static_cast<const SwFmtCharFmt&>(
1345 0 : pNewHt->GetCharFmt() ) ).SetCharFmt( pFmt );
1346 : }
1347 0 : break;
1348 : case RES_TXTATR_INETFMT :
1349 : {
1350 : // Wenn wir es mit benutzerdefinierten INet-Zeichenvorlagen
1351 : // zu tun haben, muessen wir natuerlich auch die Formate kopieren.
1352 0 : if( pOtherDoc && pDest && pDest->GetpSwpHints()
1353 0 : && USHRT_MAX != pDest->GetpSwpHints()->GetPos( pNewHt ) )
1354 : {
1355 : const SwDoc* const pDoc = static_cast<const SwTxtINetFmt*>(pHt)
1356 0 : ->GetTxtNode().GetDoc();
1357 0 : if ( pDoc )
1358 : {
1359 0 : const SwCharFmts* pCharFmts = pDoc->GetCharFmts();
1360 0 : const SwFmtINetFmt& rFmt = pHt->GetINetFmt();
1361 : SwCharFmt* pFmt;
1362 0 : pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetINetFmt() );
1363 0 : if( pFmt )
1364 0 : pOtherDoc->CopyCharFmt( *pFmt );
1365 0 : pFmt = lcl_FindCharFmt( pCharFmts, rFmt.GetVisitedFmt() );
1366 0 : if( pFmt )
1367 0 : pOtherDoc->CopyCharFmt( *pFmt );
1368 : }
1369 : }
1370 : //JP 24.04.98: Bug 49753 - ein TextNode muss am Attribut
1371 : // gesetzt sein, damit die Vorlagen erzeugt
1372 : // werden koenne
1373 0 : SwTxtINetFmt* const pINetHt = static_cast<SwTxtINetFmt*>(pNewHt);
1374 0 : if ( !pINetHt->GetpTxtNode() )
1375 : {
1376 0 : pINetHt->ChgTxtNode( pDest );
1377 : }
1378 :
1379 : //JP 22.10.97: Bug 44875 - Verbindung zum Format herstellen
1380 0 : pINetHt->GetCharFmt();
1381 0 : break;
1382 : }
1383 : case RES_TXTATR_META:
1384 : case RES_TXTATR_METAFIELD:
1385 : OSL_ENSURE(pNewHt, "copying Meta should not fail!");
1386 : OSL_ENSURE(pDest && (CH_TXTATR_BREAKWORD ==
1387 : pDest->GetTxt()[*pNewHt->GetStart()]),
1388 : "missing CH_TXTATR?");
1389 0 : break;
1390 : }
1391 50 : }
1392 :
1393 : /*************************************************************************
1394 : |* SwTxtNode::CopyAttr()
1395 : |* Beschreibung kopiert Attribute an der Position nStart in pDest.
1396 : |* BP 7.6.93: Es werden mit Absicht nur die Attribute _mit_ EndIdx
1397 : |* kopiert! CopyAttr wird vornehmlich dann gerufen,
1398 : |* wenn Attribute fuer einen Node mit leerem String
1399 : |* gesetzt werden sollen.
1400 : *************************************************************************/
1401 :
1402 822 : void SwTxtNode::CopyAttr( SwTxtNode *pDest, const xub_StrLen nTxtStartIdx,
1403 : const xub_StrLen nOldPos )
1404 : {
1405 822 : if ( HasHints() ) // keine Attribute, keine Kekse
1406 : {
1407 274 : SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
1408 274 : pDest->GetDoc() : 0;
1409 :
1410 277 : for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ )
1411 : {
1412 3 : SwTxtAttr *const pHt = m_pSwpHints->GetTextHint(i);
1413 3 : xub_StrLen const nAttrStartIdx = *pHt->GetStart();
1414 3 : if ( nTxtStartIdx < nAttrStartIdx )
1415 0 : break; // ueber das Textende, da nLen == 0
1416 :
1417 3 : const xub_StrLen *const pEndIdx = pHt->GetEnd();
1418 3 : if ( pEndIdx && !pHt->HasDummyChar() )
1419 : {
1420 6 : if( ( *pEndIdx > nTxtStartIdx ||
1421 6 : ( *pEndIdx == nTxtStartIdx &&
1422 : nAttrStartIdx == nTxtStartIdx ) ) )
1423 : {
1424 3 : sal_uInt16 const nWhich = pHt->Which();
1425 3 : if ( RES_TXTATR_REFMARK != nWhich )
1426 : {
1427 : // attribute in the area => copy
1428 : SwTxtAttr *const pNewHt = pDest->InsertItem(
1429 3 : pHt->GetAttr(), nOldPos, nOldPos,
1430 6 : nsSetAttrMode::SETATTR_IS_COPY);
1431 3 : if ( pNewHt )
1432 : {
1433 : lcl_CopyHint( nWhich, pHt, pNewHt,
1434 0 : pOtherDoc, pDest );
1435 : }
1436 : }
1437 0 : else if( !pOtherDoc ? GetDoc()->IsCopyIsMove()
1438 : : 0 == pOtherDoc->GetRefMark(
1439 0 : pHt->GetRefMark().GetRefName() ) )
1440 : {
1441 0 : pDest->InsertItem( pHt->GetAttr(), nOldPos, nOldPos,
1442 0 : nsSetAttrMode::SETATTR_IS_COPY);
1443 : }
1444 : }
1445 : }
1446 : }
1447 : }
1448 :
1449 822 : if( this != pDest )
1450 : {
1451 : // Frames benachrichtigen, sonst verschwinden die Ftn-Nummern
1452 822 : SwUpdateAttr aHint( nOldPos, nOldPos, 0 );
1453 822 : pDest->ModifyNotification( 0, &aHint );
1454 : }
1455 822 : }
1456 :
1457 : /*************************************************************************
1458 : |* SwTxtNode::Copy()
1459 : |* Beschreibung kopiert Zeichen und Attibute in pDest,
1460 : |* wird angehaengt
1461 : *************************************************************************/
1462 :
1463 : // #i96213#
1464 : // introduction of new optional parameter to control, if all attributes have to be copied.
1465 312 : void SwTxtNode::CopyText( SwTxtNode *const pDest,
1466 : const SwIndex &rStart,
1467 : const xub_StrLen nLen,
1468 : const bool bForceCopyOfAllAttrs )
1469 : {
1470 312 : SwIndex const aIdx( pDest, pDest->m_Text.getLength() );
1471 312 : CopyText( pDest, aIdx, rStart, nLen, bForceCopyOfAllAttrs );
1472 312 : }
1473 :
1474 : // #i96213#
1475 : // introduction of new optional parameter to control, if all attributes have to be copied.
1476 341 : void SwTxtNode::CopyText( SwTxtNode *const pDest,
1477 : const SwIndex &rDestStart,
1478 : const SwIndex &rStart,
1479 : xub_StrLen nLen,
1480 : const bool bForceCopyOfAllAttrs )
1481 : {
1482 341 : xub_StrLen nTxtStartIdx = rStart.GetIndex();
1483 341 : xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken
1484 :
1485 341 : if (pDest->GetDoc()->IsClipBoard() && this->GetNum())
1486 : {
1487 : // #i111677# cache expansion of source (for clipboard)
1488 : pDest->m_pNumStringCache.reset( (nTxtStartIdx != 0)
1489 0 : ? new OUString // fdo#49076: numbering only if copy from para start
1490 0 : : new OUString(this->GetNumString()));
1491 : }
1492 :
1493 341 : if( !nLen )
1494 : {
1495 : // wurde keine Laenge angegeben, dann Kopiere die Attribute
1496 : // an der Position rStart.
1497 134 : CopyAttr( pDest, nTxtStartIdx, nDestStart );
1498 :
1499 : // harte Absatz umspannende Attribute kopieren
1500 134 : if( HasSwAttrSet() )
1501 : {
1502 : // alle, oder nur die CharAttribute ?
1503 : // #i96213#
1504 31 : if ( !bForceCopyOfAllAttrs &&
1505 12 : ( nDestStart ||
1506 24 : pDest->HasSwAttrSet() ||
1507 12 : nLen != pDest->GetTxt().getLength()))
1508 : {
1509 0 : SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
1510 : RES_CHRATR_BEGIN, RES_CHRATR_END-1,
1511 : RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
1512 : RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
1513 : RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
1514 0 : 0 );
1515 0 : aCharSet.Put( *GetpSwAttrSet() );
1516 0 : if( aCharSet.Count() )
1517 : {
1518 0 : pDest->SetAttr( aCharSet, nDestStart, nDestStart );
1519 0 : }
1520 : }
1521 : else
1522 : {
1523 31 : GetpSwAttrSet()->CopyToModify( *pDest );
1524 : }
1525 : }
1526 268 : return;
1527 : }
1528 :
1529 : // 1. Text kopieren
1530 207 : const xub_StrLen oldLen = pDest->m_Text.getLength();
1531 : //JP 15.02.96: Bug 25537 - Attributbehandlung am Ende fehlt! Darum
1532 : // ueber die InsertMethode den Text einfuegen und nicht
1533 : // selbst direkt
1534 : pDest->InsertText( m_Text.copy(nTxtStartIdx, nLen), rDestStart,
1535 207 : IDocumentContentOperations::INS_EMPTYEXPAND );
1536 :
1537 : // um reale Groesse Updaten !
1538 207 : nLen = pDest->m_Text.getLength() - oldLen;
1539 207 : if ( !nLen ) // string not longer?
1540 0 : return;
1541 :
1542 207 : SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc()) ?
1543 207 : pDest->GetDoc() : 0;
1544 :
1545 : // harte Absatz umspannende Attribute kopieren
1546 207 : if( HasSwAttrSet() )
1547 : {
1548 : // alle, oder nur die CharAttribute ?
1549 : // #i96213#
1550 48 : if ( !bForceCopyOfAllAttrs &&
1551 3 : ( nDestStart ||
1552 6 : pDest->HasSwAttrSet() ||
1553 3 : nLen != pDest->GetTxt().getLength()))
1554 : {
1555 0 : SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
1556 : RES_CHRATR_BEGIN, RES_CHRATR_END-1,
1557 : RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
1558 : RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
1559 : RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
1560 0 : 0 );
1561 0 : aCharSet.Put( *GetpSwAttrSet() );
1562 0 : if( aCharSet.Count() )
1563 : {
1564 0 : pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
1565 0 : }
1566 : }
1567 : else
1568 : {
1569 48 : GetpSwAttrSet()->CopyToModify( *pDest );
1570 : }
1571 : }
1572 :
1573 : bool const bUndoNodes = !pOtherDoc
1574 207 : && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
1575 :
1576 : // Ende erst jetzt holen, weil beim Kopieren in sich selbst der
1577 : // Start-Index und alle Attribute vorher aktualisiert werden.
1578 207 : nTxtStartIdx = rStart.GetIndex();
1579 207 : const xub_StrLen nEnd = nTxtStartIdx + nLen;
1580 :
1581 : // 2. Attribute kopieren
1582 : // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
1583 : // des Attributs hinter dem zu kopierenden Bereich liegt
1584 207 : const sal_uInt16 nSize = m_pSwpHints ? m_pSwpHints->Count() : 0;
1585 :
1586 : // wird in sich selbst kopiert, dann kann beim Einfuegen ein
1587 : // Attribut geloescht werden. Darum erst ins Tmp-Array kopieren und
1588 : // dann erst ins eigene uebertragen.
1589 207 : SwpHts aArr;
1590 :
1591 : // Del-Array fuer alle RefMarks ohne Ausdehnung
1592 414 : SwpHts aRefMrkArr;
1593 :
1594 207 : sal_uInt16 nDeletedDummyChars(0);
1595 : //Achtung: kann ungueltig sein!!
1596 257 : for (sal_uInt16 n = 0; ( n < nSize ); ++n)
1597 : {
1598 72 : const xub_StrLen nAttrStartIdx = *(*m_pSwpHints)[n]->GetStart();
1599 72 : if (!( nAttrStartIdx < nEnd))
1600 22 : break;
1601 :
1602 50 : SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(n);
1603 50 : const xub_StrLen * const pEndIdx = pHt->GetEnd();
1604 50 : const sal_uInt16 nWhich = pHt->Which();
1605 :
1606 : // JP 26.04.94: REFMARK's werden nie kopiert. Hat das Refmark aber
1607 : // keinen Bereich umspannt, so steht im Text ein 255
1608 : // dieses muss entfernt werden. Trick: erst kopieren,
1609 : // erkennen und sammeln, nach dem kopieren Loeschen.
1610 : // Nimmt sein Zeichen mit ins Grab !!
1611 : // JP 14.08.95: Duerfen RefMarks gemovt werden?
1612 50 : int bCopyRefMark = RES_TXTATR_REFMARK == nWhich && ( bUndoNodes ||
1613 0 : (!pOtherDoc ? GetDoc()->IsCopyIsMove()
1614 : : 0 == pOtherDoc->GetRefMark(
1615 50 : pHt->GetRefMark().GetRefName() )));
1616 :
1617 50 : if( pEndIdx && RES_TXTATR_REFMARK == nWhich && !bCopyRefMark )
1618 : {
1619 0 : continue;
1620 : }
1621 :
1622 : xub_StrLen nAttrStt;
1623 : xub_StrLen nAttrEnd;
1624 :
1625 50 : if( nAttrStartIdx < nTxtStartIdx )
1626 : {
1627 : // start is before selection
1628 : // copy hints with end and CH_TXTATR only if dummy char is copied
1629 0 : if ( pEndIdx && (*pEndIdx > nTxtStartIdx) && !pHt->HasDummyChar() )
1630 : {
1631 : // attribute with extent and the end is in the selection
1632 0 : nAttrStt = nDestStart;
1633 0 : nAttrEnd = (*pEndIdx > nEnd)
1634 : ? rDestStart.GetIndex()
1635 0 : : nDestStart + (*pEndIdx) - nTxtStartIdx;
1636 : }
1637 : else
1638 : {
1639 0 : continue;
1640 : }
1641 : }
1642 : else
1643 : {
1644 : // start is in the selection
1645 50 : nAttrStt = nDestStart + ( nAttrStartIdx - nTxtStartIdx );
1646 50 : if( pEndIdx )
1647 : {
1648 47 : nAttrEnd = *pEndIdx > nEnd
1649 : ? rDestStart.GetIndex()
1650 47 : : nDestStart + ( *pEndIdx - nTxtStartIdx );
1651 : }
1652 : else
1653 : {
1654 3 : nAttrEnd = nAttrStt;
1655 : }
1656 : }
1657 :
1658 50 : SwTxtAttr * pNewHt = 0;
1659 :
1660 50 : if( pDest == this )
1661 : {
1662 : // copy the hint here, but insert it later
1663 0 : pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
1664 0 : nAttrStt, nAttrEnd, COPY, pDest );
1665 :
1666 0 : lcl_CopyHint(nWhich, pHt, pNewHt, 0, pDest);
1667 0 : aArr.push_back( pNewHt );
1668 : }
1669 : else
1670 : {
1671 50 : pNewHt = pDest->InsertItem( pHt->GetAttr(), nAttrStt - nDeletedDummyChars,
1672 : nAttrEnd - nDeletedDummyChars,
1673 : nsSetAttrMode::SETATTR_NOTXTATRCHR
1674 100 : | nsSetAttrMode::SETATTR_IS_COPY);
1675 50 : if (pNewHt)
1676 : {
1677 50 : lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
1678 : }
1679 0 : else if (pHt->HasDummyChar())
1680 : {
1681 : // The attribute that has failed to be copied would insert
1682 : // dummy char, so positions of the following attributes have
1683 : // to be shifted by one to compensate for that missing char.
1684 0 : ++nDeletedDummyChars;
1685 : }
1686 : }
1687 :
1688 50 : if( RES_TXTATR_REFMARK == nWhich && !pEndIdx && !bCopyRefMark )
1689 : {
1690 0 : aRefMrkArr.push_back( pNewHt );
1691 : }
1692 : }
1693 :
1694 : // nur falls im Array Attribute stehen (kann nur beim Kopieren
1695 : // sich selbst passieren!!)
1696 207 : for ( sal_uInt16 i = 0; i < aArr.size(); ++i )
1697 : {
1698 0 : InsertHint( aArr[ i ], nsSetAttrMode::SETATTR_NOTXTATRCHR );
1699 : }
1700 :
1701 207 : if( pDest->GetpSwpHints() )
1702 : {
1703 37 : for ( sal_uInt16 i = 0; i < aRefMrkArr.size(); ++i )
1704 : {
1705 0 : SwTxtAttr * const pNewHt = aRefMrkArr[i];
1706 0 : if( pNewHt->GetEnd() )
1707 : {
1708 0 : pDest->GetpSwpHints()->Delete( pNewHt );
1709 0 : pDest->DestroyAttr( pNewHt );
1710 : }
1711 : else
1712 : {
1713 0 : const SwIndex aIdx( pDest, *pNewHt->GetStart() );
1714 0 : pDest->EraseText( aIdx, 1 );
1715 : }
1716 : }
1717 : }
1718 :
1719 207 : CHECK_SWPHINTS(this);
1720 : }
1721 :
1722 :
1723 61359 : OUString SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
1724 : const IDocumentContentOperations::InsertFlags nMode )
1725 : {
1726 : assert(rIdx <= m_Text.getLength()); // invalid index
1727 :
1728 61359 : xub_StrLen aPos = rIdx.GetIndex();
1729 61359 : xub_StrLen nLen = m_Text.getLength() - aPos;
1730 61359 : long const nOverflow(static_cast<long>(m_Text.getLength())
1731 61359 : + static_cast<long>(rStr.Len()) - TXTNODE_MAX);
1732 : SAL_WARN_IF(nOverflow > 0, "sw.core",
1733 : "SwTxtNode::InsertText: node text with insertion > TXTNODE_MAX.");
1734 : OUString const sInserted(
1735 61359 : (nOverflow > 0) ? rStr.Copy(0, rStr.Len() - nOverflow) : rStr);
1736 61359 : if (sInserted.isEmpty())
1737 : {
1738 219 : return sInserted;
1739 : }
1740 61140 : m_Text = m_Text.replaceAt(aPos, 0, sInserted);
1741 : assert(m_Text.getLength() <= TXTNODE_MAX);
1742 61140 : nLen = m_Text.getLength() - aPos - nLen;
1743 : assert(nLen != 0);
1744 :
1745 61140 : bool bOldExpFlg = IsIgnoreDontExpand();
1746 61140 : if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
1747 : {
1748 64 : SetIgnoreDontExpand( true );
1749 : }
1750 :
1751 61140 : Update( rIdx, nLen ); // text content changed!
1752 :
1753 61140 : if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
1754 : {
1755 64 : SetIgnoreDontExpand( bOldExpFlg );
1756 : }
1757 :
1758 : // analog zu Insert(char) in txtedt.cxx:
1759 : // 1) bei bHintExp leere Hints an rIdx.GetIndex suchen und aufspannen
1760 : // 2) bei bHintExp == sal_False mitgezogene Feldattribute zuruecksetzen
1761 :
1762 61140 : if ( HasHints() )
1763 : {
1764 1340 : bool bMergePortionsNeeded(false);
1765 230692 : for ( sal_uInt16 i = 0; i < m_pSwpHints->Count() &&
1766 114683 : rIdx >= *(*m_pSwpHints)[i]->GetStart(); ++i )
1767 : {
1768 114669 : SwTxtAttr * const pHt = m_pSwpHints->GetTextHint( i );
1769 114669 : xub_StrLen * const pEndIdx = pHt->GetEnd();
1770 114669 : if( !pEndIdx )
1771 112932 : continue;
1772 :
1773 1737 : if( rIdx == *pEndIdx )
1774 : {
1775 159 : if ( (nMode & IDocumentContentOperations::INS_NOHINTEXPAND) ||
1776 77 : (!(nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
1777 14 : && pHt->DontExpand()) )
1778 : {
1779 : // bei leeren Attributen auch Start veraendern
1780 5 : if( rIdx == *pHt->GetStart() )
1781 5 : *pHt->GetStart() = *pHt->GetStart() - nLen;
1782 5 : *pEndIdx = *pEndIdx - nLen;
1783 5 : m_pSwpHints->DeleteAtPos(i);
1784 : // could be that pHt has IsFormatIgnoreEnd set, and it's
1785 : // not a RSID-only hint - now we have the inserted text
1786 : // between pHt and its continuation... which we don't know.
1787 : // punt the job to MergePortions below.
1788 5 : if (pHt->IsFormatIgnoreEnd())
1789 : {
1790 0 : bMergePortionsNeeded = true;
1791 : }
1792 5 : InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
1793 : }
1794 : // empty hints at insert position?
1795 144 : else if ( (nMode & IDocumentContentOperations::INS_EMPTYEXPAND)
1796 72 : && (*pEndIdx == *pHt->GetStart()) )
1797 : {
1798 0 : *pHt->GetStart() = *pHt->GetStart() - nLen;
1799 0 : const sal_uInt16 nAktLen = m_pSwpHints->Count();
1800 0 : m_pSwpHints->DeleteAtPos(i);
1801 0 : InsertHint( pHt/* AUTOSTYLES:, nsSetAttrMode::SETATTR_NOHINTADJUST*/ );
1802 0 : if ( nAktLen > m_pSwpHints->Count() && i )
1803 : {
1804 0 : --i;
1805 : }
1806 0 : continue;
1807 : }
1808 : else
1809 : {
1810 72 : continue;
1811 : }
1812 : }
1813 4995 : if ( !(nMode & IDocumentContentOperations::INS_NOHINTEXPAND) &&
1814 1677 : rIdx == nLen && *pHt->GetStart() == rIdx.GetIndex() &&
1815 4 : !pHt->IsDontExpandStartAttr() )
1816 : {
1817 : // Kein Feld, am Absatzanfang, HintExpand
1818 3 : m_pSwpHints->DeleteAtPos(i);
1819 3 : *pHt->GetStart() = *pHt->GetStart() - nLen;
1820 : // no effect on format ignore flags here (para start)
1821 3 : InsertHint( pHt, nsSetAttrMode::SETATTR_NOHINTADJUST );
1822 : }
1823 : }
1824 1340 : if (bMergePortionsNeeded)
1825 : {
1826 0 : m_pSwpHints->MergePortions(*this);
1827 : }
1828 1340 : TryDeleteSwpHints();
1829 : }
1830 :
1831 61140 : if ( GetDepends() )
1832 : {
1833 4767 : SwInsTxt aHint( aPos, nLen );
1834 4767 : NotifyClients( 0, &aHint );
1835 : }
1836 :
1837 : // By inserting a character, the hidden flags
1838 : // at the TxtNode can become invalid:
1839 61140 : SetCalcHiddenCharFlags();
1840 :
1841 : CHECK_SWPHINTS(this);
1842 61140 : return sInserted;
1843 : }
1844 :
1845 : /*************************************************************************
1846 : |*
1847 : |* SwTxtNode::Cut()
1848 : |*
1849 : |* Beschreibung text.doc
1850 : |*
1851 : *************************************************************************/
1852 :
1853 1058 : void SwTxtNode::CutText( SwTxtNode * const pDest,
1854 : const SwIndex & rStart, const xub_StrLen nLen )
1855 : {
1856 1058 : if(pDest)
1857 : {
1858 1058 : SwIndex aDestStt(pDest, pDest->GetTxt().getLength());
1859 1058 : CutImpl( pDest, aDestStt, rStart, nLen, false );
1860 : }
1861 : else
1862 : {
1863 : OSL_FAIL("mst: entering dead and bitrotted code; fasten your seatbelts!");
1864 : assert(false);
1865 0 : EraseText( rStart, nLen );
1866 : }
1867 1058 : }
1868 :
1869 :
1870 1094 : void SwTxtNode::CutImpl( SwTxtNode * const pDest, const SwIndex & rDestStart,
1871 : const SwIndex & rStart, xub_StrLen nLen, const bool bUpdate )
1872 : {
1873 1094 : if(!pDest)
1874 : {
1875 : OSL_FAIL("mst: entering dead and bitrotted code; fasten your seatbelts!");
1876 : assert(false);
1877 0 : EraseText( rStart, nLen );
1878 686 : return;
1879 : }
1880 :
1881 : // nicht im Dokument verschieben ?
1882 1094 : if( GetDoc() != pDest->GetDoc() )
1883 : {
1884 : OSL_FAIL("mst: entering dead and bitrotted code; fasten your seatbelts!");
1885 : assert(false);
1886 0 : CopyText( pDest, rDestStart, rStart, nLen);
1887 0 : EraseText(rStart, nLen);
1888 0 : return;
1889 : }
1890 :
1891 1094 : if( !nLen )
1892 : {
1893 : // wurde keine Laenge angegeben, dann Kopiere die Attribute
1894 : // an der Position rStart.
1895 686 : CopyAttr( pDest, rStart.GetIndex(), rDestStart.GetIndex() );
1896 686 : return;
1897 : }
1898 :
1899 408 : xub_StrLen nTxtStartIdx = rStart.GetIndex();
1900 408 : xub_StrLen nDestStart = rDestStart.GetIndex(); // alte Pos merken
1901 408 : const xub_StrLen nInitSize = pDest->m_Text.getLength();
1902 :
1903 : // wird in sich selbst verschoben, muss es gesondert behandelt werden !!
1904 408 : if( pDest == this )
1905 : {
1906 : OSL_FAIL("mst: entering dead and bitrotted code; fasten your seatbelts!");
1907 : assert(false);
1908 0 : OUStringBuffer buf(m_Text);
1909 0 : buf.insert(nDestStart, m_Text.copy(nTxtStartIdx, nLen));
1910 : buf.remove(
1911 0 : nTxtStartIdx + ((nDestStart < nTxtStartIdx) ? nLen : 0), nLen);
1912 0 : m_Text = buf.makeStringAndClear();
1913 :
1914 0 : const xub_StrLen nEnd = rStart.GetIndex() + nLen;
1915 :
1916 : // dann suche mal alle Attribute zusammen, die im verschobenen
1917 : // Bereich liegen. Diese werden in das extra Array verschoben,
1918 : // damit sich die Indizies beim Updaten nicht veraendern !!!
1919 0 : SwpHts aArr;
1920 :
1921 : // 2. Attribute verschieben
1922 : // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
1923 : // des Attributs hinter dem zu verschiebenden Bereich liegt
1924 0 : sal_uInt16 nAttrCnt = 0;
1925 0 : while ( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
1926 : {
1927 0 : SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
1928 0 : const xub_StrLen nAttrStartIdx = *pHt->GetStart();
1929 0 : if (!( nAttrStartIdx < nEnd ))
1930 0 : break;
1931 0 : const xub_StrLen * const pEndIdx = pHt->GetEnd();
1932 0 : const sal_uInt16 nWhich = pHt->Which();
1933 0 : SwTxtAttr *pNewHt = 0;
1934 :
1935 0 : if(nAttrStartIdx < nTxtStartIdx)
1936 : {
1937 : // Anfang liegt vor dem Bereich
1938 0 : if ( RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar() &&
1939 0 : pEndIdx && *pEndIdx > nTxtStartIdx )
1940 : {
1941 : // Attribut mit einem Bereich
1942 : // und das Ende des Attribut liegt im Bereich
1943 0 : pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(), 0,
1944 0 : *pEndIdx > nEnd
1945 : ? nLen
1946 0 : : *pEndIdx - nTxtStartIdx );
1947 : }
1948 : }
1949 : else
1950 : {
1951 : // der Anfang liegt vollstaendig im Bereich
1952 0 : if( !pEndIdx || *pEndIdx < nEnd )
1953 : {
1954 : // Attribut verschieben
1955 0 : m_pSwpHints->Delete( pHt );
1956 : // die Start/End Indicies neu setzen
1957 0 : *pHt->GetStart() = nAttrStartIdx - nTxtStartIdx;
1958 0 : if( pEndIdx )
1959 0 : *pHt->GetEnd() = *pEndIdx - nTxtStartIdx;
1960 0 : aArr.push_back( pHt );
1961 0 : continue; // while-Schleife weiter, ohne ++ !
1962 : }
1963 : // das Ende liegt dahinter
1964 0 : else if (RES_TXTATR_REFMARK != nWhich && !pHt->HasDummyChar())
1965 : {
1966 0 : pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
1967 : nAttrStartIdx - nTxtStartIdx,
1968 : !pEndIdx ? 0
1969 0 : : ( *pEndIdx > nEnd
1970 : ? nLen
1971 0 : : *pEndIdx - nTxtStartIdx ));
1972 : }
1973 : }
1974 0 : if( pNewHt )
1975 : {
1976 : // die Daten kopieren
1977 0 : lcl_CopyHint( nWhich, pHt, pNewHt, 0, this );
1978 0 : aArr.push_back( pNewHt );
1979 : }
1980 0 : ++nAttrCnt;
1981 : }
1982 :
1983 0 : if( bUpdate )
1984 : {
1985 : // Update aller Indizies
1986 0 : Update( rDestStart, nLen, sal_False, sal_True );
1987 : }
1988 :
1989 : CHECK_SWPHINTS(this);
1990 :
1991 0 : Update( rStart, nLen, sal_True, sal_True );
1992 :
1993 : CHECK_SWPHINTS(this);
1994 :
1995 : // dann setze die kopierten/geloeschten Attribute in den Node
1996 0 : if( nDestStart <= nTxtStartIdx )
1997 : {
1998 0 : nTxtStartIdx = nTxtStartIdx + nLen;
1999 : }
2000 : else
2001 : {
2002 0 : nDestStart = nDestStart - nLen;
2003 : }
2004 :
2005 0 : for ( sal_uInt16 n = 0; n < aArr.size(); ++n )
2006 : {
2007 0 : SwTxtAttr *const pNewHt = aArr[n];
2008 0 : *pNewHt->GetStart() = nDestStart + *pNewHt->GetStart();
2009 0 : xub_StrLen * const pEndIdx = pNewHt->GetEnd();
2010 0 : if ( pEndIdx )
2011 : {
2012 0 : *pEndIdx = nDestStart + *pEndIdx;
2013 : }
2014 0 : InsertHint( pNewHt, nsSetAttrMode::SETATTR_NOTXTATRCHR );
2015 0 : }
2016 : }
2017 : else
2018 : {
2019 816 : pDest->m_Text = pDest->m_Text.replaceAt(nDestStart, 0,
2020 408 : m_Text.copy(nTxtStartIdx, nLen));
2021 408 : m_Text = m_Text.replaceAt(nTxtStartIdx, nLen, "");
2022 408 : if (m_Text.getLength() > TXTNODE_MAX)
2023 : { // FIXME: could only happen when called from SwRedline::Show.
2024 : // unfortunately can't really do anything here to handle that...
2025 0 : abort();
2026 : }
2027 408 : nLen = pDest->m_Text.getLength() - nInitSize; // update w/ current size!
2028 408 : if( !nLen ) // String nicht gewachsen ??
2029 0 : return;
2030 :
2031 408 : if( bUpdate )
2032 : {
2033 : // Update aller Indizies
2034 1 : pDest->Update( rDestStart, nLen, sal_False, sal_True);
2035 : }
2036 :
2037 : CHECK_SWPHINTS(pDest);
2038 :
2039 408 : const xub_StrLen nEnd = rStart.GetIndex() + nLen;
2040 408 : SwDoc* const pOtherDoc = (pDest->GetDoc() != GetDoc())
2041 408 : ? pDest->GetDoc() : 0;
2042 : bool const bUndoNodes = !pOtherDoc
2043 408 : && GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
2044 :
2045 : OSL_ENSURE(!pOtherDoc,
2046 : "mst: entering dead and bitrotted code; fasten your seatbelts!");
2047 : assert(!pOtherDoc);
2048 :
2049 : // harte Absatz umspannende Attribute kopieren
2050 408 : if( HasSwAttrSet() )
2051 : {
2052 : // alle, oder nur die CharAttribute ?
2053 310 : if( nInitSize || pDest->HasSwAttrSet() ||
2054 0 : nLen != pDest->GetTxt().getLength())
2055 : {
2056 310 : SfxItemSet aCharSet( pDest->GetDoc()->GetAttrPool(),
2057 : RES_CHRATR_BEGIN, RES_CHRATR_END-1,
2058 : RES_TXTATR_INETFMT, RES_TXTATR_INETFMT,
2059 : RES_TXTATR_CHARFMT, RES_TXTATR_CHARFMT,
2060 : RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
2061 310 : 0 );
2062 310 : aCharSet.Put( *GetpSwAttrSet() );
2063 310 : if( aCharSet.Count() )
2064 261 : pDest->SetAttr( aCharSet, nDestStart, nDestStart + nLen );
2065 : }
2066 : else
2067 : {
2068 0 : GetpSwAttrSet()->CopyToModify( *pDest );
2069 : }
2070 : }
2071 :
2072 : // 2. Attribute verschieben
2073 : // durch das Attribute-Array, bis der Anfang des Geltungsbereiches
2074 : // des Attributs hinter dem zu verschiebenden Bereich liegt
2075 408 : bool bMergePortionsNeeded(false);
2076 408 : sal_uInt16 nAttrCnt = 0;
2077 818 : while ( m_pSwpHints && (nAttrCnt < m_pSwpHints->Count()) )
2078 : {
2079 2 : SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
2080 2 : const xub_StrLen nAttrStartIdx = *pHt->GetStart();
2081 2 : if (!( nAttrStartIdx < nEnd ))
2082 0 : break;
2083 2 : const xub_StrLen * const pEndIdx = pHt->GetEnd();
2084 2 : const sal_uInt16 nWhich = pHt->Which();
2085 2 : SwTxtAttr *pNewHt = 0;
2086 :
2087 : // if the hint has a dummy character, then it must not be split!
2088 2 : if(nAttrStartIdx < nTxtStartIdx)
2089 : {
2090 : // Anfang liegt vor dem Bereich
2091 0 : if( !pHt->HasDummyChar() && ( RES_TXTATR_REFMARK != nWhich
2092 0 : || bUndoNodes ) && pEndIdx && *pEndIdx > nTxtStartIdx )
2093 : {
2094 : // Attribut mit einem Bereich
2095 : // und das Ende des Attribut liegt im Bereich
2096 0 : pNewHt = MakeTxtAttr( *pDest->GetDoc(), pHt->GetAttr(),
2097 : nDestStart,
2098 : nDestStart + (
2099 0 : *pEndIdx > nEnd
2100 : ? nLen
2101 0 : : *pEndIdx - nTxtStartIdx ) );
2102 : }
2103 : }
2104 : else
2105 : {
2106 : // der Anfang liegt vollstaendig im Bereich
2107 2 : if( !pEndIdx || *pEndIdx < nEnd ||
2108 0 : (!pOtherDoc && !bUndoNodes && RES_TXTATR_REFMARK == nWhich)
2109 2 : || pHt->HasDummyChar() )
2110 : {
2111 : // do not delete note and later add it -> sidebar flickering
2112 2 : if ( GetDoc()->GetDocShell() )
2113 : {
2114 2 : GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
2115 : }
2116 : // Attribut verschieben
2117 2 : m_pSwpHints->Delete( pHt );
2118 : // die Start/End Indicies neu setzen
2119 2 : if (pHt->IsFormatIgnoreStart() || pHt->IsFormatIgnoreEnd())
2120 : {
2121 0 : bMergePortionsNeeded = true;
2122 : }
2123 2 : *pHt->GetStart() =
2124 2 : nDestStart + (nAttrStartIdx - nTxtStartIdx);
2125 2 : if( pEndIdx )
2126 : {
2127 0 : *pHt->GetEnd() = nDestStart + (
2128 0 : *pEndIdx > nEnd
2129 : ? nLen
2130 0 : : *pEndIdx - nTxtStartIdx );
2131 : }
2132 : pDest->InsertHint( pHt,
2133 : nsSetAttrMode::SETATTR_NOTXTATRCHR
2134 2 : | nsSetAttrMode::SETATTR_DONTREPLACE );
2135 2 : if ( GetDoc()->GetDocShell() )
2136 : {
2137 2 : GetDoc()->GetDocShell()->Broadcast( SfxSimpleHint(SFX_HINT_USER04));
2138 : }
2139 2 : continue; // while-Schleife weiter, ohne ++ !
2140 : }
2141 : // das Ende liegt dahinter
2142 0 : else if( RES_TXTATR_REFMARK != nWhich || bUndoNodes )
2143 : {
2144 0 : pNewHt = MakeTxtAttr( *GetDoc(), pHt->GetAttr(),
2145 : nDestStart + (nAttrStartIdx - nTxtStartIdx),
2146 : !pEndIdx ? 0
2147 0 : : nDestStart + ( *pEndIdx > nEnd
2148 : ? nLen
2149 0 : : *pEndIdx - nTxtStartIdx ));
2150 : }
2151 : }
2152 0 : if ( pNewHt )
2153 : {
2154 : const bool bSuccess( pDest->InsertHint( pNewHt,
2155 : nsSetAttrMode::SETATTR_NOTXTATRCHR
2156 : | nsSetAttrMode::SETATTR_DONTREPLACE
2157 0 : | nsSetAttrMode::SETATTR_IS_COPY) );
2158 0 : if (bSuccess)
2159 : {
2160 0 : lcl_CopyHint( nWhich, pHt, pNewHt, pOtherDoc, pDest );
2161 : }
2162 : }
2163 0 : ++nAttrCnt;
2164 : }
2165 : // sollten jetzt noch leere Attribute rumstehen, dann haben diese
2166 : // eine hoehere Praezedenz. Also herausholen und das Array updaten.
2167 : // Die dabei entstehenden leeren Hints werden von den gesicherten
2168 : // "uebergeplaettet". (Bug: 6977)
2169 408 : if( m_pSwpHints && nAttrCnt < m_pSwpHints->Count() )
2170 : {
2171 0 : SwpHts aArr;
2172 0 : while ( nAttrCnt < m_pSwpHints->Count() )
2173 : {
2174 0 : SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(nAttrCnt);
2175 0 : if ( nEnd != *pHt->GetStart() )
2176 0 : break;
2177 0 : const xub_StrLen * const pEndIdx = pHt->GetEnd();
2178 0 : if ( pEndIdx && *pEndIdx == nEnd )
2179 : {
2180 0 : aArr.push_back( pHt );
2181 0 : m_pSwpHints->Delete( pHt );
2182 : }
2183 : else
2184 : {
2185 0 : ++nAttrCnt;
2186 : }
2187 : }
2188 0 : Update( rStart, nLen, sal_True, sal_True );
2189 :
2190 0 : for ( sal_uInt16 n = 0; n < aArr.size(); ++n )
2191 : {
2192 0 : SwTxtAttr * const pHt = aArr[ n ];
2193 0 : *pHt->GetStart() = *pHt->GetEnd() = rStart.GetIndex();
2194 0 : InsertHint( pHt );
2195 0 : }
2196 : }
2197 : else
2198 : {
2199 408 : Update( rStart, nLen, sal_True, sal_True );
2200 : }
2201 :
2202 408 : if (bMergePortionsNeeded)
2203 : {
2204 0 : m_pSwpHints->MergePortions(*this);
2205 : }
2206 :
2207 : CHECK_SWPHINTS(this);
2208 : }
2209 :
2210 408 : TryDeleteSwpHints();
2211 :
2212 : // Frames benachrichtigen;
2213 408 : SwInsTxt aInsHint( nDestStart, nLen );
2214 408 : pDest->ModifyNotification( 0, &aInsHint );
2215 816 : SwDelTxt aDelHint( nTxtStartIdx, nLen );
2216 816 : ModifyNotification( 0, &aDelHint );
2217 : }
2218 :
2219 :
2220 721 : void SwTxtNode::EraseText(const SwIndex &rIdx, const xub_StrLen nCount,
2221 : const IDocumentContentOperations::InsertFlags nMode )
2222 : {
2223 : assert(rIdx <= m_Text.getLength()); // invalid index
2224 :
2225 721 : const xub_StrLen nStartIdx = rIdx.GetIndex();
2226 : const xub_StrLen nCnt = (STRING_LEN == nCount)
2227 721 : ? m_Text.getLength() - nStartIdx : nCount;
2228 721 : const xub_StrLen nEndIdx = nStartIdx + nCnt;
2229 721 : m_Text = m_Text.replaceAt(nStartIdx, nCnt, "");
2230 :
2231 : /* GCAttr(); alle leeren weggwerfen ist zu brutal.
2232 : * Es duerfen nur die wegggeworfen werden,
2233 : * die im Bereich liegen und nicht am Ende des Bereiches liegen
2234 : */
2235 :
2236 968 : for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
2237 : {
2238 263 : SwTxtAttr *pHt = m_pSwpHints->GetTextHint(i);
2239 :
2240 263 : const xub_StrLen nHintStart = *pHt->GetStart();
2241 :
2242 263 : if ( nHintStart < nStartIdx )
2243 70 : continue;
2244 :
2245 193 : if ( nHintStart > nEndIdx )
2246 16 : break; // hints are sorted by end, so break here
2247 :
2248 177 : const xub_StrLen* pHtEndIdx = pHt->GetEnd();
2249 177 : const sal_uInt16 nWhich = pHt->Which();
2250 :
2251 177 : if( !pHtEndIdx )
2252 : {
2253 : // attribute with neither end nor CH_TXTATR?
2254 : assert(pHt->HasDummyChar());
2255 306 : if (isTXTATR(nWhich) &&
2256 204 : (nHintStart >= nStartIdx) && (nHintStart < nEndIdx))
2257 : {
2258 88 : m_pSwpHints->DeleteAtPos(i);
2259 88 : DestroyAttr( pHt );
2260 88 : --i;
2261 : }
2262 102 : continue;
2263 : }
2264 :
2265 : assert(!( (nHintStart < nEndIdx) && (*pHtEndIdx > nEndIdx)
2266 : && pHt->HasDummyChar() )
2267 : // next line: deleting exactly dummy char: DeleteAttributes
2268 : || ((nHintStart == nStartIdx) && (nHintStart + 1 == nEndIdx)));
2269 : // "ERROR: deleting left-overlapped attribute with CH_TXTATR");
2270 :
2271 : // Delete the hint if:
2272 : // 1. The hint ends before the deletion end position or
2273 : // 2. The hint ends at the deletion end position and
2274 : // we are not in empty expand mode and
2275 : // the hint is a [toxmark|refmark|ruby] text attribute
2276 : // 3. deleting exactly the dummy char of an hint with end and dummy
2277 : // char deletes the hint
2278 150 : if ( (*pHtEndIdx < nEndIdx)
2279 55 : || ( (*pHtEndIdx == nEndIdx) &&
2280 52 : !(IDocumentContentOperations::INS_EMPTYEXPAND & nMode) &&
2281 26 : ( (RES_TXTATR_TOXMARK == nWhich) ||
2282 26 : (RES_TXTATR_REFMARK == nWhich) ||
2283 : // #i62668# Ruby text attribute must be
2284 : // treated just like toxmark and refmarks
2285 : (RES_TXTATR_CJK_RUBY == nWhich) ) )
2286 126 : || ( (nHintStart < nEndIdx) &&
2287 23 : pHt->HasDummyChar() )
2288 : )
2289 : {
2290 52 : m_pSwpHints->DeleteAtPos(i);
2291 52 : DestroyAttr( pHt );
2292 52 : --i;
2293 : }
2294 : }
2295 :
2296 : OSL_ENSURE(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
2297 :
2298 721 : TryDeleteSwpHints();
2299 :
2300 721 : Update( rIdx, nCnt, sal_True );
2301 :
2302 721 : if( 1 == nCnt )
2303 : {
2304 232 : SwDelChr aHint( nStartIdx );
2305 232 : NotifyClients( 0, &aHint );
2306 : }
2307 : else
2308 : {
2309 489 : SwDelTxt aHint( nStartIdx, nCnt );
2310 489 : NotifyClients( 0, &aHint );
2311 : }
2312 :
2313 : OSL_ENSURE(rIdx.GetIndex() == nStartIdx, "huh? start index has changed?");
2314 :
2315 : // By deleting a character, the hidden flags
2316 : // at the TxtNode can become invalid:
2317 721 : SetCalcHiddenCharFlags();
2318 :
2319 : CHECK_SWPHINTS(this);
2320 721 : }
2321 :
2322 : /***********************************************************************
2323 : #* Class : SwTxtNode
2324 : #* Methode : GCAttr
2325 : #*
2326 : #* Beschreibung
2327 : #* text.doc
2328 : #***********************************************************************/
2329 :
2330 0 : void SwTxtNode::GCAttr()
2331 : {
2332 0 : if ( !HasHints() )
2333 0 : return;
2334 :
2335 0 : bool bChanged = false;
2336 0 : sal_uInt16 nMin = m_Text.getLength(),
2337 0 : nMax = 0;
2338 0 : bool bAll = nMin != 0; // Bei leeren Absaetzen werden nur die
2339 : // INet-Formate entfernt.
2340 :
2341 0 : for ( sal_uInt16 i = 0; m_pSwpHints && i < m_pSwpHints->Count(); ++i )
2342 : {
2343 0 : SwTxtAttr * const pHt = m_pSwpHints->GetTextHint(i);
2344 :
2345 : // wenn Ende und Start gleich sind --> loeschen
2346 0 : const xub_StrLen * const pEndIdx = pHt->GetEnd();
2347 0 : if (pEndIdx && !pHt->HasDummyChar() && (*pEndIdx == *pHt->GetStart())
2348 0 : && ( bAll || pHt->Which() == RES_TXTATR_INETFMT ) )
2349 : {
2350 0 : bChanged = true;
2351 0 : nMin = std::min( nMin, *pHt->GetStart() );
2352 0 : nMax = std::max( nMax, *pHt->GetEnd() );
2353 0 : DestroyAttr( m_pSwpHints->Cut(i) );
2354 0 : --i;
2355 : }
2356 : else
2357 : {
2358 0 : pHt->SetDontExpand( false );
2359 : }
2360 : }
2361 0 : TryDeleteSwpHints();
2362 :
2363 0 : if(bChanged)
2364 : {
2365 : //TxtFrm's reagieren auf aHint, andere auf aNew
2366 0 : SwUpdateAttr aHint( nMin, nMax, 0 );
2367 0 : NotifyClients( 0, &aHint );
2368 0 : SwFmtChg aNew( GetTxtColl() );
2369 0 : NotifyClients( 0, &aNew );
2370 : }
2371 : }
2372 :
2373 : // #i23726#
2374 127724 : SwNumRule* SwTxtNode::_GetNumRule(sal_Bool bInParent) const
2375 : {
2376 127724 : SwNumRule* pRet = 0;
2377 :
2378 127724 : const SfxPoolItem* pItem = GetNoCondAttr( RES_PARATR_NUMRULE, bInParent );
2379 127724 : bool bNoNumRule = false;
2380 127724 : if ( pItem )
2381 : {
2382 13593 : String sNumRuleName = static_cast<const SwNumRuleItem *>(pItem)->GetValue();
2383 13593 : if (sNumRuleName.Len() > 0)
2384 : {
2385 13189 : pRet = GetDoc()->FindNumRulePtr( sNumRuleName );
2386 : }
2387 : else // numbering is turned off
2388 404 : bNoNumRule = true;
2389 : }
2390 :
2391 127724 : if ( !bNoNumRule )
2392 : {
2393 130798 : if ( pRet && pRet == GetDoc()->GetOutlineNumRule() &&
2394 3335 : ( !HasSwAttrSet() ||
2395 : SFX_ITEM_SET !=
2396 1596 : GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) ) )
2397 : {
2398 1739 : SwTxtFmtColl* pColl = GetTxtColl();
2399 1739 : if ( pColl )
2400 : {
2401 1739 : const SwNumRuleItem& rDirectItem = pColl->GetNumRule( sal_False );
2402 1739 : if ( rDirectItem.GetValue().isEmpty() )
2403 : {
2404 0 : pRet = 0L;
2405 : }
2406 : }
2407 : }
2408 : }
2409 :
2410 127724 : return pRet;
2411 : }
2412 :
2413 127724 : SwNumRule* SwTxtNode::GetNumRule(sal_Bool bInParent) const
2414 : {
2415 127724 : return _GetNumRule(bInParent);
2416 : }
2417 :
2418 875 : void SwTxtNode::NumRuleChgd()
2419 : {
2420 875 : if ( IsInList() )
2421 : {
2422 875 : SwNumRule* pNumRule = GetNumRule();
2423 875 : if ( pNumRule && pNumRule != GetNum()->GetNumRule() )
2424 : {
2425 0 : mpNodeNum->ChangeNumRule( *pNumRule );
2426 : }
2427 : }
2428 :
2429 875 : if( IsInCache() )
2430 : {
2431 2 : SwFrm::GetCache().Delete( this );
2432 2 : SetInCache( sal_False );
2433 : }
2434 875 : SetInSwFntCache( sal_False );
2435 :
2436 : // Sending "noop" modify in order to cause invalidations of registered
2437 : // <SwTxtFrm> instances to get the list style change respectively the change
2438 : // in the list tree reflected in the layout.
2439 : // Important note:
2440 : {
2441 875 : SvxLRSpaceItem& rLR = (SvxLRSpaceItem&)GetSwAttrSet().GetLRSpace();
2442 875 : NotifyClients( &rLR, &rLR );
2443 : }
2444 :
2445 875 : SetWordCountDirty( true );
2446 875 : }
2447 :
2448 : // -> #i27615#
2449 16549 : sal_Bool SwTxtNode::IsNumbered() const
2450 : {
2451 16549 : sal_Bool bResult = sal_False;
2452 :
2453 16549 : SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2454 16549 : if ( pRule && IsCountedInList() )
2455 730 : bResult = sal_True;
2456 :
2457 16549 : return bResult;
2458 : }
2459 :
2460 43 : bool SwTxtNode::HasMarkedLabel() const
2461 : {
2462 43 : bool bResult = false;
2463 :
2464 43 : if ( IsInList() )
2465 : {
2466 : bResult =
2467 39 : GetDoc()->getListByName( GetListId() )->IsListLevelMarked( GetActualListLevel() );
2468 : }
2469 :
2470 43 : return bResult;
2471 : }
2472 : // <- #i27615#
2473 :
2474 5056 : SwTxtNode* SwTxtNode::_MakeNewTxtNode( const SwNodeIndex& rPos, sal_Bool bNext,
2475 : sal_Bool bChgFollow )
2476 : {
2477 : /* hartes PageBreak/PageDesc/ColumnBreak aus AUTO-Set ignorieren */
2478 5056 : SwAttrSet* pNewAttrSet = 0;
2479 : // #i75353#
2480 5056 : bool bClearHardSetNumRuleWhenFmtCollChanges( false );
2481 5056 : if( HasSwAttrSet() )
2482 : {
2483 1139 : pNewAttrSet = new SwAttrSet( *GetpSwAttrSet() );
2484 1139 : const SfxItemSet* pTmpSet = GetpSwAttrSet();
2485 :
2486 1139 : if( bNext ) // der naechste erbt keine Breaks!
2487 819 : pTmpSet = pNewAttrSet;
2488 :
2489 : // PageBreaks/PageDesc/ColBreak rausschmeissen.
2490 1139 : bool bRemoveFromCache = false;
2491 1139 : std::vector<sal_uInt16> aClearWhichIds;
2492 1139 : if ( bNext )
2493 819 : bRemoveFromCache = ( 0 != pNewAttrSet->ClearItem( RES_PAGEDESC ) );
2494 : else
2495 320 : aClearWhichIds.push_back( RES_PAGEDESC );
2496 :
2497 1139 : if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_BREAK, sal_False ) )
2498 : {
2499 38 : if ( bNext )
2500 38 : pNewAttrSet->ClearItem( RES_BREAK );
2501 : else
2502 0 : aClearWhichIds.push_back( RES_BREAK );
2503 38 : bRemoveFromCache = true;
2504 : }
2505 1139 : if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_KEEP, sal_False ) )
2506 : {
2507 0 : if ( bNext )
2508 0 : pNewAttrSet->ClearItem( RES_KEEP );
2509 : else
2510 0 : aClearWhichIds.push_back( RES_KEEP );
2511 0 : bRemoveFromCache = true;
2512 : }
2513 1139 : if( SFX_ITEM_SET == pTmpSet->GetItemState( RES_PARATR_SPLIT, sal_False ) )
2514 : {
2515 0 : if ( bNext )
2516 0 : pNewAttrSet->ClearItem( RES_PARATR_SPLIT );
2517 : else
2518 0 : aClearWhichIds.push_back( RES_PARATR_SPLIT );
2519 0 : bRemoveFromCache = true;
2520 : }
2521 1139 : if(SFX_ITEM_SET == pTmpSet->GetItemState(RES_PARATR_NUMRULE, sal_False))
2522 : {
2523 267 : SwNumRule * pRule = GetNumRule();
2524 :
2525 267 : if (pRule && IsOutline())
2526 : {
2527 0 : if ( bNext )
2528 0 : pNewAttrSet->ClearItem(RES_PARATR_NUMRULE);
2529 : else
2530 : {
2531 : // #i75353#
2532 : // No clear of hard set numbering rule at an outline paragraph at this point.
2533 : // Only if the paragraph style changes - see below.
2534 0 : bClearHardSetNumRuleWhenFmtCollChanges = true;
2535 : }
2536 0 : bRemoveFromCache = true;
2537 : }
2538 : }
2539 :
2540 1139 : if ( !aClearWhichIds.empty() )
2541 320 : bRemoveFromCache = 0 != ClearItemsFromAttrSet( aClearWhichIds );
2542 :
2543 1139 : if( !bNext && bRemoveFromCache && IsInCache() )
2544 : {
2545 0 : SwFrm::GetCache().Delete( this );
2546 0 : SetInCache( sal_False );
2547 1139 : }
2548 : }
2549 5056 : SwNodes& rNds = GetNodes();
2550 :
2551 5056 : SwTxtFmtColl* pColl = GetTxtColl();
2552 :
2553 5056 : SwTxtNode *pNode = new SwTxtNode( rPos, pColl, pNewAttrSet );
2554 :
2555 5056 : delete pNewAttrSet;
2556 :
2557 5056 : const SwNumRule* pRule = GetNumRule();
2558 5056 : if( pRule && pRule == pNode->GetNumRule() && rNds.IsDocNodes() ) // #115901#
2559 : {
2560 : // #i55459#
2561 : // - correction: parameter <bNext> has to be checked, as it was in the
2562 : // previous implementation.
2563 310 : if ( !bNext && !IsCountedInList() )
2564 0 : SetCountedInList(true);
2565 : }
2566 :
2567 : // jetzt kann es sein, das durch die Nummerierung dem neuen Node eine
2568 : // Vorlage aus dem Pool zugewiesen wurde. Dann darf diese nicht
2569 : // nochmal uebergeplaettet werden !!
2570 5056 : if( pColl != pNode->GetTxtColl() ||
2571 5002 : ( bChgFollow && pColl != GetTxtColl() ))
2572 0 : return pNode; // mehr duerfte nicht gemacht werden oder ????
2573 :
2574 5056 : pNode->_ChgTxtCollUpdateNum( 0, pColl ); // fuer Nummerierung/Gliederung
2575 5056 : if( bNext || !bChgFollow )
2576 4603 : return pNode;
2577 :
2578 453 : SwTxtFmtColl *pNextColl = &pColl->GetNextTxtFmtColl();
2579 : // #i101870#
2580 : // perform action on different paragraph styles before applying the new paragraph style
2581 453 : if (pNextColl != pColl)
2582 : {
2583 : // #i75353#
2584 2 : if ( bClearHardSetNumRuleWhenFmtCollChanges )
2585 : {
2586 0 : std::vector<sal_uInt16> aClearWhichIds;
2587 0 : aClearWhichIds.push_back( RES_PARATR_NUMRULE );
2588 0 : if ( ClearItemsFromAttrSet( aClearWhichIds ) != 0 && IsInCache() )
2589 : {
2590 0 : SwFrm::GetCache().Delete( this );
2591 0 : SetInCache( sal_False );
2592 0 : }
2593 : }
2594 : }
2595 453 : ChgFmtColl( pNextColl );
2596 :
2597 453 : return pNode;
2598 : }
2599 :
2600 4549 : SwCntntNode* SwTxtNode::AppendNode( const SwPosition & rPos )
2601 : {
2602 : // Position hinter dem eingefuegt wird
2603 4549 : SwNodeIndex aIdx( rPos.nNode, 1 );
2604 4549 : SwTxtNode* pNew = _MakeNewTxtNode( aIdx, sal_True );
2605 :
2606 : // reset list attributes at appended text node
2607 4549 : pNew->ResetAttr( RES_PARATR_LIST_ISRESTART );
2608 4549 : pNew->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
2609 4549 : pNew->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
2610 4549 : if ( pNew->GetNumRule() == 0 )
2611 : {
2612 4241 : pNew->ResetAttr( RES_PARATR_LIST_ID );
2613 4241 : pNew->ResetAttr( RES_PARATR_LIST_LEVEL );
2614 : }
2615 :
2616 4549 : if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
2617 : {
2618 0 : AddToList();
2619 : }
2620 :
2621 4549 : if( GetDepends() )
2622 22 : MakeFrms( *pNew );
2623 4549 : return pNew;
2624 : }
2625 :
2626 : /*************************************************************************
2627 : * SwTxtNode::GetTxtAttr
2628 : *************************************************************************/
2629 :
2630 14479 : SwTxtAttr * SwTxtNode::GetTxtAttrForCharAt( const xub_StrLen nIndex,
2631 : const RES_TXTATR nWhich ) const
2632 : {
2633 14479 : if ( HasHints() )
2634 : {
2635 12172 : for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); ++i )
2636 : {
2637 10539 : SwTxtAttr * const pHint = m_pSwpHints->GetTextHint(i);
2638 10539 : const xub_StrLen nStartPos = *pHint->GetStart();
2639 10539 : if ( nIndex < nStartPos )
2640 : {
2641 160 : return 0;
2642 : }
2643 10379 : if ( (nIndex == nStartPos) && pHint->HasDummyChar() )
2644 : {
2645 513 : return ( RES_TXTATR_END == nWhich || nWhich == pHint->Which() )
2646 8323 : ? pHint : 0;
2647 : }
2648 : }
2649 : }
2650 10078 : return 0;
2651 : }
2652 :
2653 : // -> #i29560#
2654 1595 : sal_Bool SwTxtNode::HasNumber() const
2655 : {
2656 1595 : sal_Bool bResult = sal_False;
2657 :
2658 1595 : const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2659 1595 : if ( pRule )
2660 : {
2661 954 : SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel())));
2662 :
2663 : // #i40041#
2664 1847 : bResult = aFmt.IsEnumeration() &&
2665 1847 : SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType();
2666 : }
2667 :
2668 1595 : return bResult;
2669 : }
2670 :
2671 4236 : sal_Bool SwTxtNode::HasBullet() const
2672 : {
2673 4236 : sal_Bool bResult = sal_False;
2674 :
2675 4236 : const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2676 4236 : if ( pRule )
2677 : {
2678 520 : SwNumFmt aFmt(pRule->Get( static_cast<sal_uInt16>(GetActualListLevel())));
2679 :
2680 520 : bResult = aFmt.IsItemize();
2681 : }
2682 :
2683 4236 : return bResult;
2684 : }
2685 : // <- #i29560#
2686 :
2687 : // #128041# - introduce parameter <_bInclPrefixAndSuffixStrings>
2688 : //i53420 added max outline parameter
2689 3676 : XubString SwTxtNode::GetNumString( const bool _bInclPrefixAndSuffixStrings, const unsigned int _nRestrictToThisLevel ) const
2690 : {
2691 3676 : if (GetDoc()->IsClipBoard() && m_pNumStringCache.get())
2692 : {
2693 : // #i111677# do not expand number strings in clipboard documents
2694 0 : return *m_pNumStringCache;
2695 : }
2696 3676 : const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2697 4262 : if ( pRule &&
2698 586 : IsCountedInList() )
2699 : {
2700 : SvxNumberType const& rNumberType(
2701 586 : pRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) ) );
2702 688 : if (rNumberType.IsTxtFmt() ||
2703 : //
2704 102 : (style::NumberingType::NUMBER_NONE == rNumberType.GetNumberingType()))
2705 : {
2706 508 : return pRule->MakeNumString( GetNum()->GetNumberVector(),
2707 : _bInclPrefixAndSuffixStrings ? sal_True : sal_False,
2708 : sal_False,
2709 1016 : _nRestrictToThisLevel );
2710 : }
2711 : }
2712 :
2713 3168 : return aEmptyStr;
2714 : }
2715 :
2716 123425 : long SwTxtNode::GetLeftMarginWithNum( sal_Bool bTxtLeft ) const
2717 : {
2718 123425 : long nRet = 0;
2719 123425 : const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2720 123425 : if( pRule )
2721 : {
2722 2207 : const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2723 :
2724 2207 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
2725 : {
2726 460 : nRet = rFmt.GetAbsLSpace();
2727 :
2728 460 : if( !bTxtLeft )
2729 : {
2730 724 : if( 0 > rFmt.GetFirstLineOffset() &&
2731 362 : nRet > -rFmt.GetFirstLineOffset() )
2732 303 : nRet = nRet + rFmt.GetFirstLineOffset();
2733 : else
2734 59 : nRet = 0;
2735 : }
2736 :
2737 460 : if( pRule->IsAbsSpaces() )
2738 0 : nRet = nRet - GetSwAttrSet().GetLRSpace().GetLeft();
2739 : }
2740 1747 : else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2741 : {
2742 1747 : if ( AreListLevelIndentsApplicable() )
2743 : {
2744 954 : nRet = rFmt.GetIndentAt();
2745 : // #i90401#
2746 : // Only negative first line indents have consider for the left margin
2747 1641 : if ( !bTxtLeft &&
2748 687 : rFmt.GetFirstLineIndent() < 0 )
2749 : {
2750 687 : nRet = nRet + rFmt.GetFirstLineIndent();
2751 : }
2752 : }
2753 : }
2754 : }
2755 :
2756 123425 : return nRet;
2757 : }
2758 :
2759 46453 : sal_Bool SwTxtNode::GetFirstLineOfsWithNum( short& rFLOffset ) const
2760 : {
2761 46453 : sal_Bool bRet( sal_False );
2762 : // #i95907#
2763 46453 : rFLOffset = 0;
2764 :
2765 : // #i51089#
2766 46453 : const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2767 46453 : if ( pRule )
2768 : {
2769 562 : if ( IsCountedInList() )
2770 : {
2771 562 : const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2772 562 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
2773 : {
2774 98 : rFLOffset = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() )).GetFirstLineOffset();
2775 :
2776 98 : if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2777 : {
2778 98 : SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
2779 98 : rFLOffset = rFLOffset + aItem.GetTxtFirstLineOfst();
2780 : }
2781 : }
2782 464 : else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2783 : {
2784 464 : if ( AreListLevelIndentsApplicable() )
2785 : {
2786 267 : rFLOffset = static_cast<sal_uInt16>(rFmt.GetFirstLineIndent());
2787 : }
2788 197 : else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2789 : {
2790 197 : SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
2791 197 : rFLOffset = aItem.GetTxtFirstLineOfst();
2792 : }
2793 : }
2794 : }
2795 :
2796 562 : bRet = sal_True;
2797 : }
2798 : else
2799 : {
2800 45891 : rFLOffset = GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
2801 : }
2802 :
2803 46453 : return bRet;
2804 : }
2805 :
2806 : //
2807 0 : SwTwips SwTxtNode::GetAdditionalIndentForStartingNewList() const
2808 : {
2809 0 : SwTwips nAdditionalIndent = 0;
2810 :
2811 0 : const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
2812 0 : if ( pRule )
2813 : {
2814 0 : const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2815 0 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
2816 : {
2817 0 : nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
2818 :
2819 0 : if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2820 : {
2821 0 : nAdditionalIndent = nAdditionalIndent -
2822 0 : GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
2823 : }
2824 : }
2825 0 : else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2826 : {
2827 0 : if ( AreListLevelIndentsApplicable() )
2828 : {
2829 0 : nAdditionalIndent = rFmt.GetIndentAt() + rFmt.GetFirstLineIndent();
2830 : }
2831 : else
2832 : {
2833 0 : nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
2834 0 : if (getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
2835 : {
2836 0 : nAdditionalIndent = nAdditionalIndent -
2837 0 : GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst();
2838 : }
2839 : }
2840 : }
2841 : }
2842 : else
2843 : {
2844 0 : nAdditionalIndent = GetSwAttrSet().GetLRSpace().GetLeft();
2845 : }
2846 :
2847 0 : return nAdditionalIndent;
2848 : }
2849 :
2850 : // #i96772#
2851 5606 : void SwTxtNode::ClearLRSpaceItemDueToListLevelIndents( SvxLRSpaceItem& o_rLRSpaceItem ) const
2852 : {
2853 5606 : if ( AreListLevelIndentsApplicable() )
2854 : {
2855 58 : const SwNumRule* pRule = GetNumRule();
2856 58 : if ( pRule && GetActualListLevel() >= 0 )
2857 : {
2858 58 : const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2859 58 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2860 : {
2861 37 : SvxLRSpaceItem aLR( RES_LR_SPACE );
2862 37 : o_rLRSpaceItem = aLR;
2863 : }
2864 : }
2865 : }
2866 5606 : }
2867 :
2868 : // #i91133#
2869 48448 : long SwTxtNode::GetLeftMarginForTabCalculation() const
2870 : {
2871 48448 : long nLeftMarginForTabCalc = 0;
2872 :
2873 48448 : bool bLeftMarginForTabCalcSetToListLevelIndent( false );
2874 48448 : const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0;
2875 48448 : if( pRule )
2876 : {
2877 562 : const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(GetActualListLevel()));
2878 562 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2879 : {
2880 464 : if ( AreListLevelIndentsApplicable() )
2881 : {
2882 267 : nLeftMarginForTabCalc = rFmt.GetIndentAt();
2883 267 : bLeftMarginForTabCalcSetToListLevelIndent = true;
2884 : }
2885 : }
2886 : }
2887 48448 : if ( !bLeftMarginForTabCalcSetToListLevelIndent )
2888 : {
2889 48181 : nLeftMarginForTabCalc = GetSwAttrSet().GetLRSpace().GetTxtLeft();
2890 : }
2891 :
2892 48448 : return nLeftMarginForTabCalc;
2893 : }
2894 :
2895 2459 : void SwTxtNode::Replace0xFF( XubString& rTxt, xub_StrLen& rTxtStt,
2896 : xub_StrLen nEndPos, sal_Bool bExpandFlds ) const
2897 : {
2898 2459 : if( GetpSwpHints() )
2899 : {
2900 521 : sal_Unicode cSrchChr = CH_TXTATR_BREAKWORD;
2901 1563 : for( int nSrchIter = 0; 2 > nSrchIter; ++nSrchIter,
2902 : cSrchChr = CH_TXTATR_INWORD )
2903 : {
2904 1042 : xub_StrLen nPos = rTxt.Search( cSrchChr );
2905 2085 : while( STRING_NOTFOUND != nPos && nPos < nEndPos )
2906 : {
2907 : const SwTxtAttr* const pAttr =
2908 1 : GetTxtAttrForCharAt( rTxtStt + nPos );
2909 1 : if( pAttr )
2910 : {
2911 1 : switch( pAttr->Which() )
2912 : {
2913 : case RES_TXTATR_FIELD:
2914 1 : rTxt.Erase( nPos, 1 );
2915 1 : if( bExpandFlds )
2916 : {
2917 : const XubString aExpand(
2918 1 : static_cast<SwTxtFld const*>(pAttr)->GetFld()
2919 1 : .GetFld()->ExpandField(true));
2920 1 : rTxt.Insert( aExpand, nPos );
2921 1 : nPos = nPos + aExpand.Len();
2922 1 : nEndPos = nEndPos + aExpand.Len();
2923 1 : rTxtStt = rTxtStt - aExpand.Len();
2924 : }
2925 1 : ++rTxtStt;
2926 1 : break;
2927 : case RES_TXTATR_FTN:
2928 0 : rTxt.Erase( nPos, 1 );
2929 0 : if( bExpandFlds )
2930 : {
2931 0 : const SwFmtFtn& rFtn = pAttr->GetFtn();
2932 0 : XubString sExpand;
2933 0 : if( rFtn.GetNumStr().Len() )
2934 0 : sExpand = rFtn.GetNumStr();
2935 0 : else if( rFtn.IsEndNote() )
2936 0 : sExpand = GetDoc()->GetEndNoteInfo().aFmt.
2937 0 : GetNumStr( rFtn.GetNumber() );
2938 : else
2939 0 : sExpand = GetDoc()->GetFtnInfo().aFmt.
2940 0 : GetNumStr( rFtn.GetNumber() );
2941 0 : rTxt.Insert( sExpand, nPos );
2942 0 : nPos = nPos + sExpand.Len();
2943 0 : nEndPos = nEndPos + sExpand.Len();
2944 0 : rTxtStt = rTxtStt - sExpand.Len();
2945 : }
2946 0 : ++rTxtStt;
2947 0 : break;
2948 : default:
2949 0 : rTxt.Erase( nPos, 1 );
2950 0 : ++rTxtStt;
2951 : }
2952 : }
2953 : else
2954 0 : ++nPos, ++nEndPos;
2955 1 : nPos = rTxt.Search( cSrchChr, nPos );
2956 : }
2957 : }
2958 : }
2959 2459 : }
2960 :
2961 : /*************************************************************************
2962 : * SwTxtNode::GetExpandTxt
2963 : * Expand fields
2964 : *************************************************************************/
2965 : // #i83479# - handling of new parameters
2966 2459 : XubString SwTxtNode::GetExpandTxt( const xub_StrLen nIdx,
2967 : const xub_StrLen nLen,
2968 : const bool bWithNum,
2969 : const bool bAddSpaceAfterListLabelStr,
2970 : const bool bWithSpacesForLevel ) const
2971 : {
2972 : XubString aTxt(
2973 2459 : (STRING_LEN == nLen) ? GetTxt().copy(nIdx) : GetTxt().copy(nIdx, nLen));
2974 2459 : xub_StrLen nTxtStt = nIdx;
2975 2459 : Replace0xFF( aTxt, nTxtStt, aTxt.Len(), sal_True );
2976 2459 : if( bWithNum )
2977 : {
2978 0 : XubString aListLabelStr = GetNumString();
2979 0 : if ( aListLabelStr.Len() > 0 )
2980 : {
2981 0 : if ( bAddSpaceAfterListLabelStr )
2982 : {
2983 0 : const sal_Unicode aSpace = ' ';
2984 0 : aTxt.Insert( aSpace, 0 );
2985 : }
2986 0 : aTxt.Insert( GetNumString(), 0 );
2987 0 : }
2988 : }
2989 :
2990 2459 : if (bWithSpacesForLevel)
2991 : {
2992 0 : const sal_Unicode aSpace = ' ';
2993 0 : for (int nLevel = GetActualListLevel(); nLevel > 0; --nLevel)
2994 : {
2995 0 : aTxt.Insert( aSpace , 0 );
2996 0 : aTxt.Insert( aSpace , 0 );
2997 : }
2998 : }
2999 :
3000 2459 : return aTxt;
3001 : }
3002 :
3003 6 : sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx,
3004 : xub_StrLen nIdx, xub_StrLen nLen, sal_Bool bWithNum,
3005 : sal_Bool bWithFtn, sal_Bool bReplaceTabsWithSpaces ) const
3006 : {
3007 6 : if( &rDestNd == this )
3008 0 : return sal_False;
3009 :
3010 6 : SwIndex aDestIdx(&rDestNd, rDestNd.GetTxt().getLength());
3011 6 : if( pDestIdx )
3012 6 : aDestIdx = *pDestIdx;
3013 6 : xub_StrLen nDestStt = aDestIdx.GetIndex();
3014 :
3015 : // Text einfuegen
3016 12 : OUStringBuffer buf(GetTxt());
3017 6 : if( bReplaceTabsWithSpaces )
3018 6 : buf.replace('\t', ' ');
3019 :
3020 : // mask hidden characters
3021 6 : const sal_Unicode cChar = CH_TXTATR_BREAKWORD;
3022 6 : SwScriptInfo::MaskHiddenRanges(*this, buf, 0, buf.getLength(), cChar);
3023 :
3024 6 : buf.remove(0, nIdx);
3025 6 : if (STRING_LEN != nLen)
3026 : {
3027 0 : buf.truncate(nLen);
3028 : }
3029 6 : rDestNd.InsertText(buf.makeStringAndClear(), aDestIdx);
3030 6 : nLen = aDestIdx.GetIndex() - nDestStt;
3031 :
3032 : // alle FontAttribute mit CHARSET Symbol in dem Bereich setzen
3033 6 : if ( HasHints() )
3034 : {
3035 0 : xub_StrLen nInsPos = nDestStt - nIdx;
3036 0 : for ( sal_uInt16 i = 0; i < m_pSwpHints->Count(); i++ )
3037 : {
3038 0 : const SwTxtAttr* pHt = (*m_pSwpHints)[i];
3039 0 : const xub_StrLen nAttrStartIdx = *pHt->GetStart();
3040 0 : const sal_uInt16 nWhich = pHt->Which();
3041 0 : if (nIdx + nLen <= nAttrStartIdx)
3042 0 : break; // ueber das Textende
3043 :
3044 0 : const xub_StrLen *pEndIdx = pHt->GetEnd();
3045 0 : if( pEndIdx && *pEndIdx > nIdx &&
3046 0 : ( RES_CHRATR_FONT == nWhich ||
3047 0 : RES_TXTATR_CHARFMT == nWhich ||
3048 : RES_TXTATR_AUTOFMT == nWhich ))
3049 : {
3050 : const SvxFontItem* const pFont =
3051 : static_cast<const SvxFontItem*>(
3052 0 : CharFmt::GetItem( *pHt, RES_CHRATR_FONT ));
3053 0 : if ( pFont && RTL_TEXTENCODING_SYMBOL == pFont->GetCharSet() )
3054 : {
3055 : // attribute in area => copy
3056 : rDestNd.InsertItem( *const_cast<SvxFontItem*>(pFont),
3057 0 : nInsPos + nAttrStartIdx, nInsPos + *pEndIdx );
3058 0 : }
3059 : }
3060 0 : else if ( pHt->HasDummyChar() && (nAttrStartIdx >= nIdx) )
3061 : {
3062 0 : aDestIdx = nInsPos + nAttrStartIdx;
3063 0 : switch( nWhich )
3064 : {
3065 : case RES_TXTATR_FIELD:
3066 : {
3067 : XubString const aExpand(
3068 0 : static_cast<SwTxtFld const*>(pHt)->GetFld().GetFld()
3069 0 : ->ExpandField(true));
3070 0 : if( aExpand.Len() )
3071 : {
3072 0 : ++aDestIdx; // dahinter einfuegen;
3073 : OUString const ins(
3074 0 : rDestNd.InsertText( aExpand, aDestIdx));
3075 : SAL_INFO_IF(ins.getLength() != aExpand.Len(),
3076 : "sw.core", "GetExpandTxt lossage");
3077 0 : aDestIdx = nInsPos + nAttrStartIdx;
3078 0 : nInsPos = nInsPos + ins.getLength();
3079 : }
3080 0 : rDestNd.EraseText( aDestIdx, 1 );
3081 0 : --nInsPos;
3082 : }
3083 0 : break;
3084 :
3085 : case RES_TXTATR_FTN:
3086 : {
3087 0 : if ( bWithFtn )
3088 : {
3089 0 : const SwFmtFtn& rFtn = pHt->GetFtn();
3090 0 : XubString sExpand;
3091 0 : if( rFtn.GetNumStr().Len() )
3092 0 : sExpand = rFtn.GetNumStr();
3093 0 : else if( rFtn.IsEndNote() )
3094 0 : sExpand = GetDoc()->GetEndNoteInfo().aFmt.
3095 0 : GetNumStr( rFtn.GetNumber() );
3096 : else
3097 0 : sExpand = GetDoc()->GetFtnInfo().aFmt.
3098 0 : GetNumStr( rFtn.GetNumber() );
3099 0 : if( sExpand.Len() )
3100 : {
3101 0 : ++aDestIdx; // insert behind
3102 : SvxEscapementItem aItem(
3103 0 : SVX_ESCAPEMENT_SUPERSCRIPT );
3104 : rDestNd.InsertItem(aItem,
3105 0 : aDestIdx.GetIndex(),
3106 0 : aDestIdx.GetIndex() );
3107 : OUString const ins( rDestNd.InsertText(sExpand,
3108 : aDestIdx,
3109 0 : IDocumentContentOperations::INS_EMPTYEXPAND));
3110 : SAL_INFO_IF(ins.getLength() != sExpand.Len(),
3111 : "sw.core", "GetExpandTxt lossage");
3112 0 : aDestIdx = nInsPos + nAttrStartIdx;
3113 0 : nInsPos = nInsPos + ins.getLength();
3114 0 : }
3115 : }
3116 0 : rDestNd.EraseText( aDestIdx, 1 );
3117 0 : --nInsPos;
3118 : }
3119 0 : break;
3120 :
3121 : default:
3122 0 : rDestNd.EraseText( aDestIdx, 1 );
3123 0 : --nInsPos;
3124 : }
3125 : }
3126 : }
3127 : }
3128 :
3129 6 : if( bWithNum )
3130 : {
3131 0 : aDestIdx = nDestStt;
3132 0 : rDestNd.InsertText( GetNumString(), aDestIdx );
3133 : }
3134 :
3135 6 : aDestIdx = 0;
3136 6 : sal_Int32 nStartDelete(-1);
3137 86 : while (aDestIdx < rDestNd.GetTxt().getLength())
3138 : {
3139 74 : sal_Unicode const cur(rDestNd.GetTxt()[aDestIdx.GetIndex()]);
3140 74 : if ( (cChar == cur) // filter substituted hidden text
3141 74 : || (CH_TXT_ATR_FIELDSTART == cur) // filter all fieldmarks
3142 74 : || (CH_TXT_ATR_FIELDEND == cur)
3143 74 : || (CH_TXT_ATR_FORMELEMENT == cur))
3144 : {
3145 0 : if (-1 == nStartDelete)
3146 : {
3147 0 : nStartDelete = aDestIdx.GetIndex(); // start deletion range
3148 : }
3149 0 : ++aDestIdx;
3150 0 : if (aDestIdx < rDestNd.GetTxt().getLength())
3151 : {
3152 0 : continue;
3153 : } // else: end of paragraph => delete, see below
3154 : }
3155 : else
3156 : {
3157 74 : if (-1 == nStartDelete)
3158 : {
3159 74 : ++aDestIdx;
3160 74 : continue;
3161 : } // else: delete, see below
3162 : }
3163 : assert(-1 != nStartDelete); // without delete range, would have contined
3164 : rDestNd.EraseText(
3165 : SwIndex(&rDestNd, static_cast<xub_StrLen>(nStartDelete)),
3166 0 : aDestIdx.GetIndex() - nStartDelete);
3167 : assert(aDestIdx.GetIndex() == nStartDelete);
3168 0 : nStartDelete = -1; // reset
3169 : }
3170 :
3171 12 : return sal_True;
3172 : }
3173 :
3174 2891 : struct block
3175 : {
3176 : sal_Int32 m_nStart;
3177 : sal_Int32 m_nLen;
3178 : bool m_bVisible;
3179 : std::vector<const SwTxtAttr*> m_aAttrs;
3180 951 : block(sal_Int32 nStart, sal_Int32 nLen, bool bVisible)
3181 951 : : m_nStart(nStart), m_nLen(nLen), m_bVisible(bVisible)
3182 : {
3183 951 : }
3184 : };
3185 :
3186 : struct containsPos
3187 : {
3188 : const sal_Int32 m_nPos;
3189 797 : containsPos(const sal_Int32 nPos)
3190 797 : : m_nPos(nPos)
3191 : {
3192 797 : }
3193 805 : bool operator() (const block& rIn) const
3194 : {
3195 805 : return m_nPos >= rIn.m_nStart && m_nPos < rIn.m_nStart + rIn.m_nLen;
3196 : }
3197 : };
3198 :
3199 940 : ModelToViewHelper::ModelToViewHelper(const SwTxtNode &rNode, int eMode)
3200 : {
3201 940 : const OUString& rNodeText = rNode.GetTxt();
3202 940 : m_aRetText = rNodeText;
3203 :
3204 940 : if (eMode == PASSTHROUGH)
3205 941 : return;
3206 :
3207 939 : Range aRange( 0, rNodeText.isEmpty() ? 0 : rNodeText.getLength() - 1);
3208 939 : MultiSelection aHiddenMulti(aRange);
3209 :
3210 939 : if (eMode & HIDEINVISIBLE)
3211 936 : SwScriptInfo::selectHiddenTextProperty(rNode, aHiddenMulti);
3212 :
3213 939 : if (eMode & HIDEREDLINED)
3214 936 : SwScriptInfo::selectRedLineDeleted(rNode, aHiddenMulti);
3215 :
3216 1878 : std::vector<block> aBlocks;
3217 :
3218 939 : sal_Int32 nShownStart = 0;
3219 946 : for (size_t i = 0; i < aHiddenMulti.GetRangeCount(); ++i)
3220 : {
3221 7 : const Range& rRange = aHiddenMulti.GetRange(i);
3222 7 : sal_Int32 nHiddenStart = rRange.Min();
3223 7 : sal_Int32 nHiddenEnd = rRange.Max() + 1;
3224 7 : sal_Int32 nHiddenLen = nHiddenEnd - nHiddenStart;
3225 :
3226 7 : sal_Int32 nShownEnd = nHiddenStart;
3227 7 : sal_Int32 nShownLen = nShownEnd - nShownStart;
3228 :
3229 7 : if (nShownLen)
3230 7 : aBlocks.push_back(block(nShownStart, nShownLen, true));
3231 :
3232 7 : if (nHiddenLen)
3233 7 : aBlocks.push_back(block(nHiddenStart, nHiddenLen, false));
3234 :
3235 7 : nShownStart = nHiddenEnd;
3236 : }
3237 :
3238 939 : sal_Int32 nTrailingShownLen = rNodeText.getLength() - nShownStart;
3239 939 : if (nTrailingShownLen)
3240 937 : aBlocks.push_back(block(nShownStart, nTrailingShownLen, true));
3241 :
3242 939 : if (eMode & EXPANDFIELDS)
3243 : {
3244 936 : const SwpHints* pSwpHints2 = rNode.GetpSwpHints();
3245 1953 : for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i )
3246 : {
3247 1017 : const SwTxtAttr* pAttr = (*pSwpHints2)[i];
3248 1017 : if (pAttr->HasDummyChar())
3249 : {
3250 799 : xub_StrLen nDummyCharPos = *pAttr->GetStart();
3251 799 : if (aHiddenMulti.IsSelected(nDummyCharPos))
3252 2 : continue;
3253 797 : std::vector<block>::iterator aFind = std::find_if(aBlocks.begin(), aBlocks.end(), containsPos(nDummyCharPos));
3254 797 : if (aFind != aBlocks.end())
3255 : {
3256 797 : aFind->m_aAttrs.push_back(pAttr);
3257 : }
3258 : }
3259 : }
3260 : }
3261 :
3262 939 : sal_Int32 nOffset = 0;
3263 1890 : for (std::vector<block>::iterator i = aBlocks.begin(); i != aBlocks.end(); ++i)
3264 : {
3265 951 : if (!i->m_bVisible)
3266 : {
3267 7 : const sal_Int32 nHiddenStart = i->m_nStart;
3268 7 : const sal_Int32 nHiddenLen = i->m_nLen;
3269 :
3270 7 : m_aRetText = m_aRetText.replaceAt( nOffset + nHiddenStart, nHiddenLen, OUString() );
3271 7 : m_aMap.push_back( ConversionMapEntry( nHiddenStart, nOffset + nHiddenStart ) );
3272 7 : nOffset -= nHiddenLen;
3273 : }
3274 : else
3275 : {
3276 1741 : for (std::vector<const SwTxtAttr*>::iterator j = i->m_aAttrs.begin(); j != i->m_aAttrs.end(); ++j)
3277 : {
3278 797 : const SwTxtAttr* pAttr = *j;
3279 797 : xub_StrLen nFieldPos = *pAttr->GetStart();
3280 797 : OUString aExpand;
3281 797 : switch (pAttr->Which())
3282 : {
3283 : case RES_TXTATR_FIELD:
3284 48 : aExpand =
3285 24 : static_cast<SwTxtFld const*>(pAttr)->GetFld().GetFld()
3286 24 : ->ExpandField(true);
3287 24 : break;
3288 : case RES_TXTATR_FTN:
3289 : {
3290 30 : const SwFmtFtn& rFtn = static_cast<SwTxtFtn const*>(pAttr)->GetFtn();
3291 30 : const SwDoc *pDoc = rNode.GetDoc();
3292 30 : aExpand = rFtn.GetViewNumStr(*pDoc);
3293 : }
3294 30 : break;
3295 : default:
3296 743 : break;
3297 : }
3298 797 : m_aRetText = m_aRetText.replaceAt( nOffset + nFieldPos, 1, aExpand );
3299 797 : m_aMap.push_back( ConversionMapEntry( nFieldPos, nOffset + nFieldPos ) );
3300 797 : nOffset += ( aExpand.getLength() - 1 );
3301 797 : }
3302 : }
3303 : }
3304 :
3305 939 : if ( !m_aMap.empty() )
3306 1412 : m_aMap.push_back( ConversionMapEntry( rNodeText.getLength()+1, m_aRetText.getLength()+1 ) );
3307 : }
3308 :
3309 0 : XubString SwTxtNode::GetRedlineTxt( xub_StrLen nIdx, xub_StrLen nLen,
3310 : sal_Bool bExpandFlds, sal_Bool bWithNum ) const
3311 : {
3312 0 : std::vector<sal_uInt16> aRedlArr;
3313 0 : const SwDoc* pDoc = GetDoc();
3314 0 : sal_uInt16 nRedlPos = pDoc->GetRedlinePos( *this, nsRedlineType_t::REDLINE_DELETE );
3315 0 : if( USHRT_MAX != nRedlPos )
3316 : {
3317 : // es existiert fuer den Node irgendein Redline-Delete-Object
3318 0 : const sal_uLong nNdIdx = GetIndex();
3319 0 : for( ; nRedlPos < pDoc->GetRedlineTbl().size() ; ++nRedlPos )
3320 : {
3321 0 : const SwRedline* pTmp = pDoc->GetRedlineTbl()[ nRedlPos ];
3322 0 : if( nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
3323 : {
3324 0 : const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
3325 0 : if( pRStt->nNode < nNdIdx )
3326 : {
3327 0 : if( pREnd->nNode > nNdIdx )
3328 : // Absatz ist komplett geloescht
3329 0 : return aEmptyStr;
3330 0 : else if( pREnd->nNode == nNdIdx )
3331 : {
3332 : // von 0 bis nContent ist alles geloescht
3333 0 : aRedlArr.push_back( xub_StrLen(0) );
3334 0 : aRedlArr.push_back( pREnd->nContent.GetIndex() );
3335 : }
3336 : }
3337 0 : else if( pRStt->nNode == nNdIdx )
3338 : {
3339 : //aRedlArr.Insert( pRStt->nContent.GetIndex(), aRedlArr.Count() );
3340 0 : aRedlArr.push_back( pRStt->nContent.GetIndex() );
3341 0 : if( pREnd->nNode == nNdIdx )
3342 0 : aRedlArr.push_back( pREnd->nContent.GetIndex() );
3343 : else
3344 : {
3345 0 : aRedlArr.push_back(GetTxt().getLength());
3346 0 : break; // mehr kann nicht kommen
3347 : }
3348 : }
3349 : else
3350 0 : break; // mehr kann nicht kommen
3351 : }
3352 : }
3353 : }
3354 :
3355 0 : XubString aTxt(nLen > GetTxt().getLength() ? GetTxt().copy(nIdx) : GetTxt().copy(nIdx, nLen));
3356 :
3357 0 : xub_StrLen nTxtStt = nIdx, nIdxEnd = nIdx + aTxt.Len();
3358 0 : for( sal_uInt16 n = 0; n < aRedlArr.size(); n += 2 )
3359 : {
3360 0 : xub_StrLen nStt = aRedlArr[ n ], nEnd = aRedlArr[ n+1 ];
3361 0 : if( ( nIdx <= nStt && nStt <= nIdxEnd ) ||
3362 0 : ( nIdx <= nEnd && nEnd <= nIdxEnd ))
3363 : {
3364 0 : if( nStt < nIdx ) nStt = nIdx;
3365 0 : if( nIdxEnd < nEnd ) nEnd = nIdxEnd;
3366 0 : xub_StrLen nDelCnt = nEnd - nStt;
3367 0 : aTxt.Erase( nStt - nTxtStt, nDelCnt );
3368 0 : Replace0xFF( aTxt, nTxtStt, nStt - nTxtStt, bExpandFlds );
3369 0 : nTxtStt = nTxtStt + nDelCnt;
3370 : }
3371 0 : else if( nStt >= nIdxEnd )
3372 0 : break;
3373 : }
3374 0 : Replace0xFF( aTxt, nTxtStt, aTxt.Len(), bExpandFlds );
3375 :
3376 0 : if( bWithNum )
3377 0 : aTxt.Insert( GetNumString(), 0 );
3378 0 : return aTxt;
3379 : }
3380 :
3381 : /*************************************************************************
3382 : * SwTxtNode::ReplaceText
3383 : *************************************************************************/
3384 :
3385 44 : void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
3386 : const XubString& rStr)
3387 : {
3388 : assert( rStart.GetIndex() < m_Text.getLength() // index out of bounds
3389 : && rStart.GetIndex() + nDelLen <= m_Text.getLength());
3390 :
3391 44 : long const nOverflow(static_cast<long>(m_Text.getLength())
3392 44 : + static_cast<long>(rStr.Len()) - nDelLen - TXTNODE_MAX);
3393 : SAL_WARN_IF(nOverflow > 0, "sw.core",
3394 : "SwTxtNode::ReplaceText: node text with insertion > TXTNODE_MAX.");
3395 : OUString const sInserted(
3396 44 : (nOverflow > 0) ? rStr.Copy(0, rStr.Len() - nOverflow) : rStr);
3397 44 : if (sInserted.isEmpty() && 0 == nDelLen)
3398 : {
3399 44 : return; // nothing to do
3400 : }
3401 :
3402 44 : const xub_StrLen nStartPos = rStart.GetIndex();
3403 44 : xub_StrLen nEndPos = nStartPos + nDelLen;
3404 44 : xub_StrLen nLen = nDelLen;
3405 462 : for ( xub_StrLen nPos = nStartPos; nPos < nEndPos; ++nPos )
3406 : {
3407 836 : if ((CH_TXTATR_BREAKWORD == m_Text[nPos]) ||
3408 418 : (CH_TXTATR_INWORD == m_Text[nPos]))
3409 : {
3410 0 : SwTxtAttr *const pHint = GetTxtAttrForCharAt( nPos );
3411 0 : if (pHint)
3412 : {
3413 : assert(!( pHint->GetEnd() && pHint->HasDummyChar()
3414 : && (*pHint->GetStart() < nEndPos)
3415 : && (*pHint->GetEnd() > nEndPos) ));
3416 : // "deleting left-overlapped attribute with CH_TXTATR"
3417 0 : DeleteAttribute( pHint );
3418 0 : --nEndPos;
3419 0 : --nLen;
3420 : }
3421 : }
3422 : }
3423 :
3424 44 : bool bOldExpFlg = IsIgnoreDontExpand();
3425 44 : SetIgnoreDontExpand( true );
3426 :
3427 44 : if (nLen && sInserted.getLength())
3428 : {
3429 : // dann das 1. Zeichen ersetzen den Rest loschen und einfuegen
3430 : // Dadurch wird die Attributierung des 1. Zeichen expandiert!
3431 44 : m_Text = m_Text.replaceAt(nStartPos, 1, sInserted.copy(0, 1));
3432 :
3433 44 : ++((SwIndex&)rStart);
3434 44 : m_Text = m_Text.replaceAt(rStart.GetIndex(), nLen - 1, "");
3435 44 : Update( rStart, nLen - 1, true );
3436 :
3437 44 : XubString aTmpTxt(sInserted); aTmpTxt.Erase( 0, 1 );
3438 44 : m_Text = m_Text.replaceAt(rStart.GetIndex(), 0, aTmpTxt);
3439 44 : Update( rStart, aTmpTxt.Len(), false );
3440 : }
3441 : else
3442 : {
3443 0 : m_Text = m_Text.replaceAt(nStartPos, nLen, "");
3444 0 : Update( rStart, nLen, true );
3445 :
3446 0 : m_Text = m_Text.replaceAt(nStartPos, 0, sInserted);
3447 0 : Update( rStart, sInserted.getLength(), false );
3448 : }
3449 :
3450 44 : SetIgnoreDontExpand( bOldExpFlg );
3451 88 : SwDelTxt aDelHint( nStartPos, nDelLen );
3452 44 : NotifyClients( 0, &aDelHint );
3453 :
3454 88 : SwInsTxt aHint( nStartPos, sInserted.getLength() );
3455 88 : NotifyClients( 0, &aHint );
3456 : }
3457 :
3458 : namespace {
3459 33 : static void lcl_ResetParAttrs( SwTxtNode &rTxtNode )
3460 : {
3461 33 : std::set<sal_uInt16> aAttrs;
3462 33 : aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_ID );
3463 33 : aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_LEVEL );
3464 33 : aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_ISRESTART );
3465 33 : aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_RESTARTVALUE );
3466 33 : aAttrs.insert( aAttrs.end(), RES_PARATR_LIST_ISCOUNTED );
3467 66 : SwPaM aPam( rTxtNode );
3468 : // #i96644#
3469 : // suppress side effect "send data changed events"
3470 66 : rTxtNode.GetDoc()->ResetAttrs( aPam, false, aAttrs, false );
3471 33 : }
3472 :
3473 : // Helper method for special handling of modified attributes at text node.
3474 : // The following is handled:
3475 : // (1) on changing the paragraph style - RES_FMT_CHG:
3476 : // Check, if list style of the text node is changed. If yes, add respectively
3477 : // remove the text node to the corresponding list.
3478 : // (2) on changing the attributes - RES_ATTRSET_CHG:
3479 : // Same as (1).
3480 : // (3) on changing the list style - RES_PARATR_NUMRULE:
3481 : // Same as (1).
3482 60740 : void HandleModifyAtTxtNode( SwTxtNode& rTxtNode,
3483 : const SfxPoolItem* pOldValue,
3484 : const SfxPoolItem* pNewValue )
3485 : {
3486 : const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
3487 60740 : pNewValue ? pNewValue->Which() : 0 ;
3488 60740 : bool bNumRuleSet = false;
3489 60740 : bool bParagraphStyleChanged = false;
3490 60740 : String sNumRule;
3491 121480 : String sOldNumRule;
3492 60740 : switch ( nWhich )
3493 : {
3494 : case RES_FMT_CHG:
3495 : {
3496 4095 : bParagraphStyleChanged = true;
3497 4095 : if( rTxtNode.GetNodes().IsDocNodes() )
3498 : {
3499 : // #i70748#
3500 : const SwNumRule* pFormerNumRuleAtTxtNode =
3501 2905 : rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
3502 2905 : if ( pFormerNumRuleAtTxtNode )
3503 : {
3504 51 : sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
3505 : }
3506 : // #i70748#
3507 2905 : if ( rTxtNode.IsEmptyListStyleDueToSetOutlineLevelAttr() )
3508 : {
3509 0 : const SwNumRuleItem& rNumRuleItem = rTxtNode.GetTxtColl()->GetNumRule();
3510 0 : if ( !rNumRuleItem.GetValue().isEmpty() )
3511 : {
3512 0 : rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
3513 : }
3514 : }
3515 :
3516 2905 : const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
3517 2905 : if ( pNumRuleAtTxtNode )
3518 : {
3519 77 : bNumRuleSet = true;
3520 77 : sNumRule = pNumRuleAtTxtNode->GetName();
3521 : }
3522 : }
3523 4095 : break;
3524 : }
3525 : case RES_ATTRSET_CHG:
3526 : {
3527 43525 : const SfxPoolItem* pItem = 0;
3528 : // #i70748#
3529 : const SwNumRule* pFormerNumRuleAtTxtNode =
3530 43525 : rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
3531 43525 : if ( pFormerNumRuleAtTxtNode )
3532 : {
3533 1397 : sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
3534 : }
3535 :
3536 43525 : if ( dynamic_cast<const SwAttrSetChg*>(pNewValue)->GetChgSet()->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) ==
3537 : SFX_ITEM_SET )
3538 : {
3539 : // #i70748#
3540 142 : rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
3541 142 : bNumRuleSet = true;
3542 : }
3543 : // #i70748#
3544 : // The new list style set at the paragraph.
3545 43525 : const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
3546 43525 : if ( pNumRuleAtTxtNode )
3547 : {
3548 1541 : sNumRule = pNumRuleAtTxtNode->GetName();
3549 : }
3550 43525 : break;
3551 : }
3552 : case RES_PARATR_NUMRULE:
3553 : {
3554 0 : if ( rTxtNode.GetNodes().IsDocNodes() )
3555 : {
3556 : const SwNumRule* pFormerNumRuleAtTxtNode =
3557 0 : rTxtNode.GetNum() ? rTxtNode.GetNum()->GetNumRule() : 0;
3558 0 : if ( pFormerNumRuleAtTxtNode )
3559 : {
3560 0 : sOldNumRule = pFormerNumRuleAtTxtNode->GetName();
3561 : }
3562 :
3563 0 : if ( pNewValue )
3564 : {
3565 : // #i70748#
3566 0 : rTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
3567 0 : bNumRuleSet = true;
3568 : }
3569 : // #i70748#
3570 : // The new list style set at the paragraph.
3571 0 : const SwNumRule* pNumRuleAtTxtNode = rTxtNode.GetNumRule();
3572 0 : if ( pNumRuleAtTxtNode )
3573 : {
3574 0 : sNumRule = pNumRuleAtTxtNode->GetName();
3575 : }
3576 : }
3577 0 : break;
3578 : }
3579 : }
3580 60740 : if ( sNumRule != sOldNumRule )
3581 : {
3582 236 : if ( bNumRuleSet )
3583 : {
3584 201 : if ( sNumRule.Len() == 0 )
3585 : {
3586 0 : rTxtNode.RemoveFromList();
3587 0 : if ( bParagraphStyleChanged )
3588 : {
3589 0 : lcl_ResetParAttrs(rTxtNode);
3590 : }
3591 : }
3592 : else
3593 : {
3594 201 : rTxtNode.RemoveFromList();
3595 : // If new list style is the outline style, apply outline
3596 : // level as the list level.
3597 201 : if ( sNumRule.EqualsAscii(SwNumRule::GetOutlineRuleName()) )
3598 : {
3599 : // #i70748#
3600 : OSL_ENSURE( rTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle(),
3601 : "<HandleModifyAtTxtNode()> - text node with outline style, but its paragraph style is not assigned to outline style." );
3602 : int nNewListLevel =
3603 168 : rTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
3604 168 : if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
3605 : {
3606 167 : rTxtNode.SetAttrListLevel( nNewListLevel );
3607 : }
3608 : }
3609 201 : rTxtNode.AddToList();
3610 : }
3611 : }
3612 : else // <sNumRule.Len() == 0 && sOldNumRule.Len() != 0>
3613 : {
3614 35 : rTxtNode.RemoveFromList();
3615 35 : if ( bParagraphStyleChanged )
3616 : {
3617 33 : lcl_ResetParAttrs(rTxtNode);
3618 : // #i70748#
3619 33 : if ( dynamic_cast<const SfxUInt16Item &>(rTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 )
3620 : {
3621 0 : rTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
3622 : }
3623 : }
3624 : }
3625 : }
3626 60504 : else if ( sNumRule.Len() > 0 && !rTxtNode.IsInList() )
3627 : {
3628 0 : rTxtNode.AddToList();
3629 60740 : }
3630 60740 : }
3631 : // End of method <HandleModifyAtTxtNode>
3632 : }
3633 :
3634 66520 : void SwTxtNode::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
3635 : {
3636 66520 : bool bWasNotifiable = m_bNotifiable;
3637 66520 : m_bNotifiable = false;
3638 :
3639 : // Bug 24616/24617:
3640 : // Modify ueberladen, damit beim Loeschen von Vorlagen diese
3641 : // wieder richtig verwaltet werden (Outline-Numerierung!!)
3642 : // Bug25481:
3643 : // bei Nodes im Undo nie _ChgTxtCollUpdateNum rufen.
3644 123459 : if( pOldValue && pNewValue && RES_FMT_CHG == pOldValue->Which() &&
3645 68963 : GetRegisteredIn() == ((SwFmtChg*)pNewValue)->pChangedFmt &&
3646 30 : GetNodes().IsDocNodes() )
3647 : {
3648 : _ChgTxtCollUpdateNum(
3649 : (SwTxtFmtColl*)((SwFmtChg*)pOldValue)->pChangedFmt,
3650 30 : (SwTxtFmtColl*)((SwFmtChg*)pNewValue)->pChangedFmt );
3651 : }
3652 :
3653 66520 : if ( !mbInSetOrResetAttr )
3654 : {
3655 59058 : HandleModifyAtTxtNode( *this, pOldValue, pNewValue );
3656 : }
3657 :
3658 66520 : SwCntntNode::Modify( pOldValue, pNewValue );
3659 :
3660 66520 : SwDoc * pDoc = GetDoc();
3661 : // #125329# - assure that text node is in document nodes array
3662 66520 : if ( pDoc && !pDoc->IsInDtor() && &pDoc->GetNodes() == &GetNodes() )
3663 : {
3664 52677 : pDoc->GetNodes().UpdateOutlineNode(*this);
3665 : }
3666 :
3667 66520 : m_bNotifiable = bWasNotifiable;
3668 :
3669 66520 : if (pOldValue && (RES_REMOVE_UNO_OBJECT == pOldValue->Which()))
3670 : { // invalidate cached uno object
3671 : SetXParagraph(::com::sun::star::uno::Reference<
3672 0 : ::com::sun::star::text::XTextContent>(0));
3673 : }
3674 66520 : }
3675 :
3676 8529 : SwFmtColl* SwTxtNode::ChgFmtColl( SwFmtColl *pNewColl )
3677 : {
3678 : OSL_ENSURE( pNewColl,"ChgFmtColl: Collectionpointer has value 0." );
3679 : OSL_ENSURE( HAS_BASE( SwTxtFmtColl, pNewColl ),
3680 : "ChgFmtColl: is not a Text Collection pointer." );
3681 :
3682 8529 : SwTxtFmtColl *pOldColl = GetTxtColl();
3683 8529 : if( pNewColl != pOldColl )
3684 : {
3685 1682 : SetCalcHiddenCharFlags();
3686 1682 : SwCntntNode::ChgFmtColl( pNewColl );
3687 : OSL_ENSURE( !mbInSetOrResetAttr,
3688 : "DEBUG OSL_ENSURE(ON - <SwTxtNode::ChgFmtColl(..)> called during <Set/ResetAttr(..)>" );
3689 1682 : if ( !mbInSetOrResetAttr )
3690 : {
3691 1682 : SwFmtChg aTmp1( pOldColl );
3692 3364 : SwFmtChg aTmp2( pNewColl );
3693 3364 : HandleModifyAtTxtNode( *this, &aTmp1, &aTmp2 );
3694 : }
3695 : }
3696 :
3697 : // nur wenn im normalen Nodes-Array
3698 8529 : if( GetNodes().IsDocNodes() )
3699 : {
3700 8529 : _ChgTxtCollUpdateNum( pOldColl, static_cast<SwTxtFmtColl *>(pNewColl) );
3701 : }
3702 :
3703 8529 : GetNodes().UpdateOutlineNode(*this);
3704 :
3705 8529 : return pOldColl;
3706 : }
3707 :
3708 1412 : SwNodeNum* SwTxtNode::CreateNum() const
3709 : {
3710 1412 : if ( !mpNodeNum )
3711 : {
3712 1412 : mpNodeNum = new SwNodeNum( const_cast<SwTxtNode*>(this) );
3713 : }
3714 1412 : return mpNodeNum;
3715 : }
3716 :
3717 0 : SwNumberTree::tNumberVector SwTxtNode::GetNumberVector() const
3718 : {
3719 0 : if ( GetNum() )
3720 : {
3721 0 : return GetNum()->GetNumberVector();
3722 : }
3723 : else
3724 : {
3725 0 : SwNumberTree::tNumberVector aResult;
3726 0 : return aResult;
3727 : }
3728 : }
3729 :
3730 88285 : bool SwTxtNode::IsOutline() const
3731 : {
3732 88285 : bool bResult = false;
3733 :
3734 88285 : if ( GetAttrOutlineLevel() > 0 )
3735 : {
3736 4001 : bResult = !IsInRedlines();
3737 : }
3738 : else
3739 : {
3740 84284 : const SwNumRule* pRule( GetNum() ? GetNum()->GetNumRule() : 0L );
3741 84284 : if ( pRule && pRule->IsOutlineRule() )
3742 : {
3743 9 : bResult = !IsInRedlines();
3744 : }
3745 : }
3746 :
3747 88285 : return bResult;
3748 : }
3749 :
3750 84677 : bool SwTxtNode::IsOutlineStateChanged() const
3751 : {
3752 84677 : return IsOutline() != m_bLastOutlineState;
3753 : }
3754 :
3755 430 : void SwTxtNode::UpdateOutlineState()
3756 : {
3757 430 : m_bLastOutlineState = IsOutline();
3758 430 : }
3759 :
3760 : //#outline level, zhaojianwei
3761 95137 : int SwTxtNode::GetAttrOutlineLevel() const
3762 : {
3763 95137 : return ((const SfxUInt16Item &)GetAttr(RES_PARATR_OUTLINELEVEL)).GetValue();
3764 : }
3765 0 : void SwTxtNode::SetAttrOutlineLevel(int nLevel)
3766 : {
3767 : assert(0 <= nLevel && nLevel <= MAXLEVEL); // Level Out Of Range
3768 0 : if ( 0 <= nLevel && nLevel <= MAXLEVEL )
3769 : {
3770 : SetAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL,
3771 0 : static_cast<sal_uInt16>(nLevel) ) );
3772 : }
3773 0 : }
3774 : //<-end
3775 :
3776 : // #i70748#
3777 2905 : bool SwTxtNode::IsEmptyListStyleDueToSetOutlineLevelAttr()
3778 : {
3779 2905 : return mbEmptyListStyleSetDueToSetOutlineLevelAttr;
3780 : }
3781 :
3782 0 : void SwTxtNode::SetEmptyListStyleDueToSetOutlineLevelAttr()
3783 : {
3784 0 : if ( !mbEmptyListStyleSetDueToSetOutlineLevelAttr )
3785 : {
3786 0 : SetAttr( SwNumRuleItem() );
3787 0 : mbEmptyListStyleSetDueToSetOutlineLevelAttr = true;
3788 : }
3789 0 : }
3790 :
3791 2493 : void SwTxtNode::ResetEmptyListStyleDueToResetOutlineLevelAttr()
3792 : {
3793 2493 : if ( mbEmptyListStyleSetDueToSetOutlineLevelAttr )
3794 : {
3795 0 : ResetAttr( RES_PARATR_NUMRULE );
3796 0 : mbEmptyListStyleSetDueToSetOutlineLevelAttr = false;
3797 : }
3798 2493 : }
3799 :
3800 :
3801 1488 : void SwTxtNode::SetAttrListLevel( int nLevel )
3802 : {
3803 1488 : if ( nLevel < 0 || nLevel >= MAXLEVEL )
3804 : {
3805 : assert(false); // invalid level
3806 1488 : return;
3807 : }
3808 :
3809 : SfxInt16Item aNewListLevelItem( RES_PARATR_LIST_LEVEL,
3810 1488 : static_cast<sal_Int16>(nLevel) );
3811 1488 : SetAttr( aNewListLevelItem );
3812 : }
3813 :
3814 5990 : bool SwTxtNode::HasAttrListLevel() const
3815 : {
3816 7833 : return GetpSwAttrSet() &&
3817 7833 : GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_LEVEL, sal_False ) == SFX_ITEM_SET;
3818 : }
3819 :
3820 4648 : int SwTxtNode::GetAttrListLevel() const
3821 : {
3822 4648 : int nAttrListLevel = 0;
3823 :
3824 : const SfxInt16Item& aListLevelItem =
3825 4648 : dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_LEVEL ));
3826 4648 : nAttrListLevel = static_cast<int>(aListLevelItem.GetValue());
3827 :
3828 4648 : return nAttrListLevel;
3829 : }
3830 :
3831 11420 : int SwTxtNode::GetActualListLevel() const
3832 : {
3833 11420 : return GetNum() ? GetNum()->GetLevelInListTree() : -1;
3834 : }
3835 :
3836 1 : void SwTxtNode::SetListRestart( bool bRestart )
3837 : {
3838 : // CreateNum()->SetRestart(bRestart);
3839 1 : if ( !bRestart )
3840 : {
3841 : // attribute not contained in paragraph style's attribute set. Thus,
3842 : // it can be reset to the attribute pool default by resetting the attribute.
3843 0 : ResetAttr( RES_PARATR_LIST_ISRESTART );
3844 : }
3845 : else
3846 : {
3847 : SfxBoolItem aNewIsRestartItem( RES_PARATR_LIST_ISRESTART,
3848 1 : sal_True );
3849 1 : SetAttr( aNewIsRestartItem );
3850 : }
3851 1 : }
3852 :
3853 5793 : bool SwTxtNode::IsListRestart() const
3854 : {
3855 : // return GetNum() ? GetNum()->IsRestart() : false;
3856 : const SfxBoolItem& aIsRestartItem =
3857 5793 : dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISRESTART ));
3858 :
3859 5793 : return aIsRestartItem.GetValue() ? true : false;
3860 : }
3861 :
3862 : /** Returns if the paragraph has a visible numbering or bullet.
3863 : This includes all kinds of numbering/bullet/outlines.
3864 : The concrete list label string has to be checked, too.
3865 : */
3866 729 : bool SwTxtNode::HasVisibleNumberingOrBullet() const
3867 : {
3868 729 : bool bRet = false;
3869 :
3870 729 : const SwNumRule* pRule = GetNum() ? GetNum()->GetNumRule() : 0L;
3871 729 : if ( pRule && IsCountedInList())
3872 : {
3873 : // #i87154#
3874 : // Correction of #newlistlevelattrs#:
3875 : // The numbering type has to be checked for bullet lists.
3876 728 : const SwNumFmt& rFmt = pRule->Get( static_cast<sal_uInt16>(GetActualListLevel() ));
3877 2275 : if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() ||
3878 1001 : pRule->MakeNumString( *(GetNum()) ).Len() > 0 )
3879 : {
3880 637 : bRet = true;
3881 : }
3882 : }
3883 :
3884 729 : return bRet;
3885 : }
3886 :
3887 2 : void SwTxtNode::SetAttrListRestartValue( SwNumberTree::tSwNumTreeNumber nNumber )
3888 : {
3889 : // CreateNum()->SetStart(nNumber);
3890 2 : const bool bChanged( HasAttrListRestartValue()
3891 0 : ? GetAttrListRestartValue() != nNumber
3892 2 : : nNumber != USHRT_MAX );
3893 :
3894 2 : if ( bChanged || !HasAttrListRestartValue() )
3895 : {
3896 2 : if ( nNumber == USHRT_MAX )
3897 : {
3898 0 : ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
3899 : }
3900 : else
3901 : {
3902 : SfxInt16Item aNewListRestartValueItem( RES_PARATR_LIST_RESTARTVALUE,
3903 2 : static_cast<sal_Int16>(nNumber) );
3904 2 : SetAttr( aNewListRestartValueItem );
3905 : }
3906 : }
3907 2 : }
3908 :
3909 5097 : bool SwTxtNode::HasAttrListRestartValue() const
3910 : {
3911 6273 : return GetpSwAttrSet() &&
3912 6273 : GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False ) == SFX_ITEM_SET;
3913 : }
3914 1 : SwNumberTree::tSwNumTreeNumber SwTxtNode::GetAttrListRestartValue() const
3915 : {
3916 : OSL_ENSURE( HasAttrListRestartValue(),
3917 : "<SwTxtNode::GetAttrListRestartValue()> - only ask for list restart value, if attribute is set at text node." );
3918 :
3919 : const SfxInt16Item& aListRestartValueItem =
3920 1 : dynamic_cast<const SfxInt16Item&>(GetAttr( RES_PARATR_LIST_RESTARTVALUE ));
3921 1 : return static_cast<SwNumberTree::tSwNumTreeNumber>(aListRestartValueItem.GetValue());
3922 : }
3923 :
3924 1 : SwNumberTree::tSwNumTreeNumber SwTxtNode::GetActualListStartValue() const
3925 : {
3926 : // return GetNum() ? GetNum()->GetStart() : 1;
3927 1 : SwNumberTree::tSwNumTreeNumber nListRestartValue = 1;
3928 :
3929 1 : if ( IsListRestart() && HasAttrListRestartValue() )
3930 : {
3931 1 : nListRestartValue = GetAttrListRestartValue();
3932 : }
3933 : else
3934 : {
3935 0 : SwNumRule* pRule = GetNumRule();
3936 0 : if ( pRule )
3937 : {
3938 : const SwNumFmt* pFmt =
3939 0 : pRule->GetNumFmt( static_cast<sal_uInt16>(GetAttrListLevel()) );
3940 0 : if ( pFmt )
3941 : {
3942 0 : nListRestartValue = pFmt->GetStart();
3943 : }
3944 : }
3945 : }
3946 :
3947 1 : return nListRestartValue;
3948 : }
3949 :
3950 10304 : bool SwTxtNode::IsNotifiable() const
3951 : {
3952 10304 : return m_bNotifiable && IsNotificationEnabled();
3953 : }
3954 :
3955 11749 : bool SwTxtNode::IsNotificationEnabled() const
3956 : {
3957 11749 : bool bResult = false;
3958 11749 : const SwDoc * pDoc = GetDoc();
3959 11749 : if( pDoc )
3960 : {
3961 11749 : bResult = pDoc->IsInReading() || pDoc->IsInDtor() ? false : true;
3962 : }
3963 11749 : return bResult;
3964 : }
3965 :
3966 479 : void SwTxtNode::SetCountedInList( bool bCounted )
3967 : {
3968 479 : if ( bCounted )
3969 : {
3970 : // attribute not contained in paragraph style's attribute set. Thus,
3971 : // it can be reset to the attribute pool default by resetting the attribute.
3972 479 : ResetAttr( RES_PARATR_LIST_ISCOUNTED );
3973 : }
3974 : else
3975 : {
3976 0 : SfxBoolItem aIsCountedInListItem( RES_PARATR_LIST_ISCOUNTED, sal_False );
3977 0 : SetAttr( aIsCountedInListItem );
3978 : }
3979 479 : }
3980 :
3981 11173 : bool SwTxtNode::IsCountedInList() const
3982 : {
3983 : const SfxBoolItem& aIsCountedInListItem =
3984 11173 : dynamic_cast<const SfxBoolItem&>(GetAttr( RES_PARATR_LIST_ISCOUNTED ));
3985 :
3986 11173 : return aIsCountedInListItem.GetValue() ? true : false;
3987 : }
3988 :
3989 1505 : void SwTxtNode::AddToList()
3990 : {
3991 1505 : if ( IsInList() )
3992 : {
3993 : OSL_FAIL( "<SwTxtNode::AddToList()> - the text node is already added to a list. Serious defect -> please inform OD" );
3994 1505 : return;
3995 : }
3996 :
3997 1505 : const String sListId = GetListId();
3998 1505 : if ( sListId.Len() > 0 )
3999 : {
4000 1412 : SwList* pList = GetDoc()->getListByName( sListId );
4001 1412 : if ( pList == 0 )
4002 : {
4003 : // Create corresponding list.
4004 0 : SwNumRule* pNumRule = GetNumRule();
4005 0 : if ( pNumRule )
4006 : {
4007 0 : pList = GetDoc()->createList( sListId, GetNumRule()->GetName() );
4008 : }
4009 : }
4010 : OSL_ENSURE( pList != 0,
4011 : "<SwTxtNode::AddToList()> - no list for given list id. Serious defect -> please inform OD" );
4012 1412 : if ( pList )
4013 : {
4014 1412 : pList->InsertListItem( *CreateNum(), GetAttrListLevel() );
4015 1412 : mpList = pList;
4016 : }
4017 1505 : }
4018 : }
4019 :
4020 19987 : void SwTxtNode::RemoveFromList()
4021 : {
4022 19987 : if ( IsInList() )
4023 : {
4024 1411 : mpList->RemoveListItem( *mpNodeNum );
4025 1411 : mpList = 0;
4026 1411 : delete mpNodeNum;
4027 1411 : mpNodeNum = 0L;
4028 :
4029 1411 : SetWordCountDirty( true );
4030 : }
4031 19987 : }
4032 :
4033 86431 : bool SwTxtNode::IsInList() const
4034 : {
4035 86431 : return GetNum() != 0 && GetNum()->GetParent() != 0;
4036 : }
4037 :
4038 0 : bool SwTxtNode::IsFirstOfNumRule() const
4039 : {
4040 0 : bool bResult = false;
4041 :
4042 0 : if ( GetNum() && GetNum()->GetNumRule())
4043 0 : bResult = GetNum()->IsFirst();
4044 :
4045 0 : return bResult;
4046 : }
4047 :
4048 30 : void SwTxtNode::SetListId( const String sListId )
4049 : {
4050 : const SfxStringItem& rListIdItem =
4051 30 : dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
4052 30 : if ( rListIdItem.GetValue() != sListId )
4053 : {
4054 30 : if ( sListId.Len() == 0 )
4055 : {
4056 0 : ResetAttr( RES_PARATR_LIST_ID );
4057 : }
4058 : else
4059 : {
4060 30 : SfxStringItem aNewListIdItem( RES_PARATR_LIST_ID, sListId );
4061 30 : SetAttr( aNewListIdItem );
4062 : }
4063 : }
4064 30 : }
4065 :
4066 3033 : String SwTxtNode::GetListId() const
4067 : {
4068 3033 : String sListId;
4069 :
4070 : const SfxStringItem& rListIdItem =
4071 3033 : dynamic_cast<const SfxStringItem&>(GetAttr( RES_PARATR_LIST_ID ));
4072 3033 : sListId = rListIdItem.GetValue();
4073 :
4074 : // As long as no explicit list id attribute is set, use the list id of
4075 : // the list, which has been created for the applied list style.
4076 3033 : if ( sListId.Len() == 0 )
4077 : {
4078 2942 : SwNumRule* pRule = GetNumRule();
4079 2942 : if ( pRule )
4080 : {
4081 2849 : sListId = pRule->GetDefaultListId();
4082 : }
4083 : }
4084 :
4085 3033 : return sListId;
4086 : }
4087 :
4088 : /** Determines, if the list level indent attributes can be applied to the
4089 : paragraph.
4090 :
4091 : The list level indents can be applied to the paragraph under the one
4092 : of following conditions:
4093 : - the list style is directly applied to the paragraph and the paragraph
4094 : has no own indent attributes.
4095 : - the list style is applied to the paragraph through one of its paragraph
4096 : styles, the paragraph has no own indent attributes and on the paragraph
4097 : style hierarchy from the paragraph to the paragraph style with the
4098 : list style no indent attributes are found.
4099 :
4100 : @author OD
4101 :
4102 : @return boolean
4103 : */
4104 58441 : bool SwTxtNode::AreListLevelIndentsApplicable() const
4105 : {
4106 58441 : bool bAreListLevelIndentsApplicable( true );
4107 :
4108 58441 : if ( !GetNum() || !GetNum()->GetNumRule() )
4109 : {
4110 : // no list style applied to paragraph
4111 54938 : bAreListLevelIndentsApplicable = false;
4112 : }
4113 7006 : else if ( HasSwAttrSet() &&
4114 3503 : GetpSwAttrSet()->GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
4115 : {
4116 : // paragraph has hard-set indent attributes
4117 1491 : bAreListLevelIndentsApplicable = false;
4118 : }
4119 4024 : else if ( HasSwAttrSet() &&
4120 2012 : GetpSwAttrSet()->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
4121 : {
4122 : // list style is directly applied to paragraph and paragraph has no
4123 : // hard-set indent attributes
4124 1546 : bAreListLevelIndentsApplicable = true;
4125 : }
4126 : else
4127 : {
4128 : // list style is applied through one of the paragraph styles and
4129 : // paragraph has no hard-set indent attributes
4130 :
4131 : // check, paragraph's
4132 466 : const SwTxtFmtColl* pColl = GetTxtColl();
4133 932 : while ( pColl )
4134 : {
4135 466 : if ( pColl->GetAttrSet().GetItemState( RES_LR_SPACE, sal_False ) == SFX_ITEM_SET )
4136 : {
4137 : // indent attributes found in the paragraph style hierarchy.
4138 0 : bAreListLevelIndentsApplicable = false;
4139 0 : break;
4140 : }
4141 :
4142 466 : if ( pColl->GetAttrSet().GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
4143 : {
4144 : // paragraph style with the list style found and until now no
4145 : // indent attributes are found in the paragraph style hierarchy.
4146 466 : bAreListLevelIndentsApplicable = true;
4147 466 : break;
4148 : }
4149 :
4150 0 : pColl = dynamic_cast<const SwTxtFmtColl*>(pColl->DerivedFrom());
4151 : OSL_ENSURE( pColl,
4152 : "<SwTxtNode::AreListLevelIndentsApplicable()> - something wrong in paragraph's style hierarchy. The applied list style is not found." );
4153 : }
4154 : }
4155 :
4156 58441 : return bAreListLevelIndentsApplicable;
4157 : }
4158 :
4159 : /** Retrieves the list tab stop position, if the paragraph's list level defines
4160 : one and this list tab stop has to merged into the tap stops of the paragraph
4161 :
4162 : @author OD
4163 :
4164 : @param nListTabStopPosition
4165 : output parameter - containing the list tab stop position
4166 :
4167 : @return boolean - indicating, if a list tab stop position is provided
4168 : */
4169 48573 : bool SwTxtNode::GetListTabStopPosition( long& nListTabStopPosition ) const
4170 : {
4171 48573 : bool bListTanStopPositionProvided( false );
4172 :
4173 48573 : const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
4174 48573 : if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
4175 : {
4176 471 : const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) );
4177 844 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT &&
4178 373 : rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
4179 : {
4180 373 : bListTanStopPositionProvided = true;
4181 373 : nListTabStopPosition = rFmt.GetListtabPos();
4182 :
4183 373 : if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
4184 : {
4185 : // tab stop position are treated to be relative to the "before text"
4186 : // indent value of the paragraph. Thus, adjust <nListTabStopPos>.
4187 26 : if ( AreListLevelIndentsApplicable() )
4188 : {
4189 26 : nListTabStopPosition -= rFmt.GetIndentAt();
4190 : }
4191 0 : else if (!getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING))
4192 : {
4193 0 : SvxLRSpaceItem aItem = GetSwAttrSet().GetLRSpace();
4194 0 : nListTabStopPosition -= aItem.GetTxtLeft();
4195 : }
4196 : }
4197 : }
4198 : }
4199 :
4200 48573 : return bListTanStopPositionProvided;
4201 : }
4202 :
4203 : /** Retrieves the character following the list label, if the paragraph's
4204 : list level defines one.
4205 :
4206 : @author OD
4207 :
4208 : @return XubString - the list tab stop position
4209 : */
4210 166 : XubString SwTxtNode::GetLabelFollowedBy() const
4211 : {
4212 166 : XubString aLabelFollowedBy;
4213 :
4214 166 : const SwNumRule* pNumRule = GetNum() ? GetNum()->GetNumRule() : 0;
4215 166 : if ( pNumRule && HasVisibleNumberingOrBullet() && GetActualListLevel() >= 0 )
4216 : {
4217 166 : const SwNumFmt& rFmt = pNumRule->Get( static_cast<sal_uInt16>(GetActualListLevel()) );
4218 166 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
4219 : {
4220 136 : switch ( rFmt.GetLabelFollowedBy() )
4221 : {
4222 : case SvxNumberFormat::LISTTAB:
4223 : {
4224 136 : const sal_Unicode aTab = '\t';
4225 136 : aLabelFollowedBy.Insert( aTab, 0 );
4226 : }
4227 136 : break;
4228 : case SvxNumberFormat::SPACE:
4229 : {
4230 0 : const sal_Unicode aSpace = ' ';
4231 0 : aLabelFollowedBy.Insert( aSpace, 0 );
4232 : }
4233 0 : break;
4234 : case SvxNumberFormat::NOTHING:
4235 : {
4236 : // intentionally left blank.
4237 : }
4238 0 : break;
4239 : default:
4240 : {
4241 : OSL_FAIL( "<SwTxtNode::GetLabelFollowedBy()> - unknown SvxNumberFormat::GetLabelFollowedBy() return value" );
4242 : }
4243 : }
4244 : }
4245 : }
4246 :
4247 166 : return aLabelFollowedBy;
4248 : }
4249 :
4250 7946 : void SwTxtNode::CalcHiddenCharFlags() const
4251 : {
4252 : xub_StrLen nStartPos;
4253 : xub_StrLen nEndPos;
4254 : // Update of the flags is done inside GetBoundsOfHiddenRange()
4255 7946 : SwScriptInfo::GetBoundsOfHiddenRange( *this, 0, nStartPos, nEndPos );
4256 7946 : }
4257 :
4258 : // #i12836# enhanced pdf export
4259 3580 : bool SwTxtNode::IsHidden() const
4260 : {
4261 3580 : if ( HasHiddenParaField() || HasHiddenCharAttribute( true ) )
4262 20 : return true;
4263 :
4264 3560 : const SwSectionNode* pSectNd = FindSectionNode();
4265 3560 : if ( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
4266 0 : return true;
4267 :
4268 3560 : return false;
4269 : }
4270 :
4271 : namespace {
4272 : // Helper class for special handling of setting attributes at text node:
4273 : // In constructor an instance of the helper class recognize whose attributes
4274 : // are set and perform corresponding actions before the intrinsic set of
4275 : // attributes has been taken place.
4276 : // In the destructor - after the attributes have been set at the text
4277 : // node - corresponding actions are performed.
4278 : // The following is handled:
4279 : // (1) When the list style attribute - RES_PARATR_NUMRULE - is set,
4280 : // (A) list style attribute is empty -> the text node is removed from
4281 : // its list.
4282 : // (B) list style attribute is not empty
4283 : // (a) text node has no list style -> add text node to its list after
4284 : // the attributes have been set.
4285 : // (b) text node has list style -> change of list style is notified
4286 : // after the attributes have been set.
4287 : // (2) When the list id attribute - RES_PARATR_LIST_ID - is set and changed,
4288 : // the text node is removed from its current list before the attributes
4289 : // are set and added to its new list after the attributes have been set.
4290 : // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is set
4291 : // and changed after the attributes have been set
4292 : // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is set
4293 : // and changed after the attributes have been set
4294 : // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE -
4295 : // is set and changed after the attributes have been set
4296 : // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is set
4297 : // and changed after the attributes have been set
4298 : // (7) Set or Reset emtpy list style due to changed outline level - RES_PARATR_OUTLINELEVEL.
4299 : class HandleSetAttrAtTxtNode
4300 : {
4301 : public:
4302 : HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4303 : const SfxPoolItem& pItem );
4304 : HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4305 : const SfxItemSet& rItemSet );
4306 : ~HandleSetAttrAtTxtNode();
4307 :
4308 : private:
4309 : SwTxtNode& mrTxtNode;
4310 : bool mbAddTxtNodeToList;
4311 : bool mbUpdateListLevel;
4312 : bool mbUpdateListRestart;
4313 : bool mbUpdateListCount;
4314 : // #i70748#
4315 : bool mbOutlineLevelSet;
4316 : };
4317 :
4318 3097 : HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4319 : const SfxPoolItem& pItem )
4320 : : mrTxtNode( rTxtNode ),
4321 : mbAddTxtNodeToList( false ),
4322 : mbUpdateListLevel( false ),
4323 : mbUpdateListRestart( false ),
4324 : mbUpdateListCount( false ),
4325 : // #i70748#
4326 3097 : mbOutlineLevelSet( false )
4327 : {
4328 3097 : switch ( pItem.Which() )
4329 : {
4330 : // handle RES_PARATR_NUMRULE
4331 : case RES_PARATR_NUMRULE:
4332 : {
4333 273 : mrTxtNode.RemoveFromList();
4334 :
4335 : const SwNumRuleItem& pNumRuleItem =
4336 273 : dynamic_cast<const SwNumRuleItem&>(pItem);
4337 273 : if ( !pNumRuleItem.GetValue().isEmpty() )
4338 : {
4339 233 : mbAddTxtNodeToList = true;
4340 : // #i105562#
4341 : //
4342 233 : mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4343 : }
4344 : }
4345 273 : break;
4346 :
4347 : // handle RES_PARATR_LIST_ID
4348 : case RES_PARATR_LIST_ID:
4349 : {
4350 : const SfxStringItem& pListIdItem =
4351 30 : dynamic_cast<const SfxStringItem&>(pItem);
4352 : OSL_ENSURE( pListIdItem.GetValue().getLength() > 0,
4353 : "<HandleSetAttrAtTxtNode(..)> - empty list id attribute not excepted. Serious defect -> please inform OD." );
4354 30 : const String sListIdOfTxtNode = rTxtNode.GetListId();
4355 30 : if ( pListIdItem.GetValue() != sListIdOfTxtNode )
4356 : {
4357 0 : mbAddTxtNodeToList = true;
4358 0 : if ( mrTxtNode.IsInList() )
4359 : {
4360 0 : mrTxtNode.RemoveFromList();
4361 : }
4362 30 : }
4363 : }
4364 30 : break;
4365 :
4366 : // handle RES_PARATR_LIST_LEVEL
4367 : case RES_PARATR_LIST_LEVEL:
4368 : {
4369 : const SfxInt16Item& aListLevelItem =
4370 1488 : dynamic_cast<const SfxInt16Item&>(pItem);
4371 1488 : if ( aListLevelItem.GetValue() != mrTxtNode.GetAttrListLevel() )
4372 : {
4373 332 : mbUpdateListLevel = true;
4374 : }
4375 : }
4376 1488 : break;
4377 :
4378 : // handle RES_PARATR_LIST_ISRESTART
4379 : case RES_PARATR_LIST_ISRESTART:
4380 : {
4381 : const SfxBoolItem& aListIsRestartItem =
4382 1 : dynamic_cast<const SfxBoolItem&>(pItem);
4383 2 : if ( aListIsRestartItem.GetValue() !=
4384 1 : (mrTxtNode.IsListRestart() ? sal_True : sal_False) )
4385 : {
4386 1 : mbUpdateListRestart = true;
4387 : }
4388 : }
4389 1 : break;
4390 :
4391 : // handle RES_PARATR_LIST_RESTARTVALUE
4392 : case RES_PARATR_LIST_RESTARTVALUE:
4393 : {
4394 : const SfxInt16Item& aListRestartValueItem =
4395 2 : dynamic_cast<const SfxInt16Item&>(pItem);
4396 2 : if ( !mrTxtNode.HasAttrListRestartValue() ||
4397 0 : aListRestartValueItem.GetValue() != mrTxtNode.GetAttrListRestartValue() )
4398 : {
4399 2 : mbUpdateListRestart = true;
4400 : }
4401 : }
4402 2 : break;
4403 :
4404 : // handle RES_PARATR_LIST_ISCOUNTED
4405 : case RES_PARATR_LIST_ISCOUNTED:
4406 : {
4407 : const SfxBoolItem& aIsCountedInListItem =
4408 0 : dynamic_cast<const SfxBoolItem&>(pItem);
4409 0 : if ( aIsCountedInListItem.GetValue() !=
4410 0 : (mrTxtNode.IsCountedInList() ? sal_True : sal_False) )
4411 : {
4412 0 : mbUpdateListCount = true;
4413 : }
4414 : }
4415 0 : break;
4416 :
4417 : // #i70748#
4418 : // handle RES_PARATR_OUTLINELEVEL
4419 : case RES_PARATR_OUTLINELEVEL:
4420 : {
4421 : const SfxUInt16Item& aOutlineLevelItem =
4422 0 : dynamic_cast<const SfxUInt16Item&>(pItem);
4423 0 : if ( aOutlineLevelItem.GetValue() != mrTxtNode.GetAttrOutlineLevel() )
4424 : {
4425 0 : mbOutlineLevelSet = true;
4426 : }
4427 : }
4428 0 : break;
4429 : }
4430 :
4431 3097 : }
4432 :
4433 15100 : HandleSetAttrAtTxtNode::HandleSetAttrAtTxtNode( SwTxtNode& rTxtNode,
4434 : const SfxItemSet& rItemSet )
4435 : : mrTxtNode( rTxtNode ),
4436 : mbAddTxtNodeToList( false ),
4437 : mbUpdateListLevel( false ),
4438 : mbUpdateListRestart( false ),
4439 : mbUpdateListCount( false ),
4440 : // #i70748#
4441 15100 : mbOutlineLevelSet( false )
4442 : {
4443 15100 : const SfxPoolItem* pItem = 0;
4444 : // handle RES_PARATR_NUMRULE
4445 15100 : if ( rItemSet.GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem ) == SFX_ITEM_SET )
4446 : {
4447 568 : mrTxtNode.RemoveFromList();
4448 :
4449 : const SwNumRuleItem* pNumRuleItem =
4450 568 : dynamic_cast<const SwNumRuleItem*>(pItem);
4451 568 : if ( !pNumRuleItem->GetValue().isEmpty() )
4452 : {
4453 534 : mbAddTxtNodeToList = true;
4454 : // #i70748#
4455 534 : mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4456 : }
4457 : }
4458 :
4459 : // handle RES_PARATR_LIST_ID
4460 15100 : if ( rItemSet.GetItemState( RES_PARATR_LIST_ID, sal_False, &pItem ) == SFX_ITEM_SET )
4461 : {
4462 : const SfxStringItem* pListIdItem =
4463 0 : dynamic_cast<const SfxStringItem*>(pItem);
4464 0 : const String sListIdOfTxtNode = mrTxtNode.GetListId();
4465 0 : if ( pListIdItem &&
4466 0 : pListIdItem->GetValue() != sListIdOfTxtNode )
4467 : {
4468 0 : mbAddTxtNodeToList = true;
4469 0 : if ( mrTxtNode.IsInList() )
4470 : {
4471 0 : mrTxtNode.RemoveFromList();
4472 : }
4473 0 : }
4474 : }
4475 :
4476 : // handle RES_PARATR_LIST_LEVEL
4477 15100 : if ( rItemSet.GetItemState( RES_PARATR_LIST_LEVEL, sal_False, &pItem ) == SFX_ITEM_SET )
4478 : {
4479 : const SfxInt16Item* pListLevelItem =
4480 1538 : dynamic_cast<const SfxInt16Item*>(pItem);
4481 1538 : if ( pListLevelItem->GetValue() != mrTxtNode.GetAttrListLevel() )
4482 : {
4483 907 : mbUpdateListLevel = true;
4484 : }
4485 : }
4486 :
4487 : // handle RES_PARATR_LIST_ISRESTART
4488 15100 : if ( rItemSet.GetItemState( RES_PARATR_LIST_ISRESTART, sal_False, &pItem ) == SFX_ITEM_SET )
4489 : {
4490 : const SfxBoolItem* pListIsRestartItem =
4491 0 : dynamic_cast<const SfxBoolItem*>(pItem);
4492 0 : if ( pListIsRestartItem->GetValue() !=
4493 0 : (mrTxtNode.IsListRestart() ? sal_True : sal_False) )
4494 : {
4495 0 : mbUpdateListRestart = true;
4496 : }
4497 : }
4498 :
4499 : // handle RES_PARATR_LIST_RESTARTVALUE
4500 15100 : if ( rItemSet.GetItemState( RES_PARATR_LIST_RESTARTVALUE, sal_False, &pItem ) == SFX_ITEM_SET )
4501 : {
4502 : const SfxInt16Item* pListRestartValueItem =
4503 0 : dynamic_cast<const SfxInt16Item*>(pItem);
4504 0 : if ( !mrTxtNode.HasAttrListRestartValue() ||
4505 0 : pListRestartValueItem->GetValue() != mrTxtNode.GetAttrListRestartValue() )
4506 : {
4507 0 : mbUpdateListRestart = true;
4508 : }
4509 : }
4510 :
4511 : // handle RES_PARATR_LIST_ISCOUNTED
4512 15100 : if ( rItemSet.GetItemState( RES_PARATR_LIST_ISCOUNTED, sal_False, &pItem ) == SFX_ITEM_SET )
4513 : {
4514 : const SfxBoolItem* pIsCountedInListItem =
4515 0 : dynamic_cast<const SfxBoolItem*>(pItem);
4516 0 : if ( pIsCountedInListItem->GetValue() !=
4517 0 : (mrTxtNode.IsCountedInList() ? sal_True : sal_False) )
4518 : {
4519 0 : mbUpdateListCount = true;
4520 : }
4521 : }
4522 :
4523 : // #i70748#
4524 : // handle RES_PARATR_OUTLINELEVEL
4525 15100 : if ( rItemSet.GetItemState( RES_PARATR_OUTLINELEVEL, sal_False, &pItem ) == SFX_ITEM_SET )
4526 : {
4527 : const SfxUInt16Item* pOutlineLevelItem =
4528 2 : dynamic_cast<const SfxUInt16Item*>(pItem);
4529 2 : if ( pOutlineLevelItem->GetValue() != mrTxtNode.GetAttrOutlineLevel() )
4530 : {
4531 2 : mbOutlineLevelSet = true;
4532 : }
4533 : }
4534 15100 : }
4535 :
4536 18197 : HandleSetAttrAtTxtNode::~HandleSetAttrAtTxtNode()
4537 : {
4538 18197 : if ( mbAddTxtNodeToList )
4539 : {
4540 767 : SwNumRule* pNumRuleAtTxtNode = mrTxtNode.GetNumRule();
4541 767 : if ( pNumRuleAtTxtNode )
4542 : {
4543 767 : mrTxtNode.AddToList();
4544 : }
4545 : }
4546 : else
4547 : {
4548 17430 : if ( mbUpdateListLevel && mrTxtNode.IsInList() )
4549 : {
4550 30 : const_cast<SwNodeNum*>(mrTxtNode.GetNum())->SetLevelInListTree(
4551 60 : mrTxtNode.GetAttrListLevel() );
4552 : }
4553 :
4554 17430 : if ( mbUpdateListRestart && mrTxtNode.IsInList() )
4555 : {
4556 2 : SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4557 2 : pNodeNum->InvalidateMe();
4558 2 : pNodeNum->NotifyInvalidSiblings();
4559 : }
4560 :
4561 17430 : if ( mbUpdateListCount && mrTxtNode.IsInList() )
4562 : {
4563 0 : const_cast<SwNodeNum*>(mrTxtNode.GetNum())->InvalidateAndNotifyTree();
4564 : }
4565 : }
4566 :
4567 : // #i70748#
4568 18197 : if ( mbOutlineLevelSet )
4569 : {
4570 2 : if ( mrTxtNode.GetAttrOutlineLevel() == 0 )
4571 : {
4572 0 : mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4573 : }
4574 : else
4575 : {
4576 2 : const SfxPoolItem* pItem = 0;
4577 4 : if ( mrTxtNode.GetSwAttrSet().GetItemState( RES_PARATR_NUMRULE,
4578 2 : sal_True, &pItem )
4579 : != SFX_ITEM_SET )
4580 : {
4581 0 : mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
4582 : }
4583 : }
4584 : }
4585 18197 : }
4586 : // End of class <HandleSetAttrAtTxtNode>
4587 : }
4588 :
4589 3097 : sal_Bool SwTxtNode::SetAttr( const SfxPoolItem& pItem )
4590 : {
4591 3097 : const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4592 3097 : mbInSetOrResetAttr = true;
4593 :
4594 3097 : HandleSetAttrAtTxtNode aHandleSetAttr( *this, pItem );
4595 :
4596 3097 : sal_Bool bRet = SwCntntNode::SetAttr( pItem );
4597 :
4598 3097 : mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4599 :
4600 3097 : return bRet;
4601 : }
4602 :
4603 15100 : sal_Bool SwTxtNode::SetAttr( const SfxItemSet& rSet )
4604 : {
4605 15100 : const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4606 15100 : mbInSetOrResetAttr = true;
4607 :
4608 15100 : HandleSetAttrAtTxtNode aHandleSetAttr( *this, rSet );
4609 :
4610 15100 : sal_Bool bRet = SwCntntNode::SetAttr( rSet );
4611 :
4612 15100 : mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4613 :
4614 15100 : return bRet;
4615 : }
4616 :
4617 : namespace {
4618 : // Helper class for special handling of resetting attributes at text node:
4619 : // In constructor an instance of the helper class recognize whose attributes
4620 : // are reset and perform corresponding actions before the intrinsic reset of
4621 : // attributes has been taken place.
4622 : // In the destructor - after the attributes have been reset at the text
4623 : // node - corresponding actions are performed.
4624 : // The following is handled:
4625 : // (1) When the list style attribute - RES_PARATR_NUMRULE - is reset,
4626 : // the text is removed from its list before the attributes have been reset.
4627 : // (2) When the list id attribute - RES_PARATR_LIST_ID - is reset,
4628 : // the text is removed from its list before the attributes have been reset.
4629 : // (3) Notify list tree, if list level - RES_PARATR_LIST_LEVEL - is reset.
4630 : // (4) Notify list tree, if list restart - RES_PARATR_LIST_ISRESTART - is reset.
4631 : // (5) Notify list tree, if list restart value - RES_PARATR_LIST_RESTARTVALUE - is reset.
4632 : // (6) Notify list tree, if count in list - RES_PARATR_LIST_ISCOUNTED - is reset.
4633 : // (7) Reset empty list style, if outline level attribute - RES_PARATR_OUTLINELEVEL - is reset.
4634 : class HandleResetAttrAtTxtNode
4635 : {
4636 : public:
4637 : HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4638 : const sal_uInt16 nWhich1,
4639 : const sal_uInt16 nWhich2 );
4640 : HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4641 : const std::vector<sal_uInt16>& rWhichArr );
4642 : HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode );
4643 :
4644 : ~HandleResetAttrAtTxtNode();
4645 :
4646 : private:
4647 : SwTxtNode& mrTxtNode;
4648 : bool mbListStyleOrIdReset;
4649 : bool mbUpdateListLevel;
4650 : bool mbUpdateListRestart;
4651 : bool mbUpdateListCount;
4652 : };
4653 :
4654 30500 : HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4655 : const sal_uInt16 nWhich1,
4656 : const sal_uInt16 nWhich2 )
4657 : : mrTxtNode( rTxtNode ),
4658 : mbListStyleOrIdReset( false ),
4659 : mbUpdateListLevel( false ),
4660 : mbUpdateListRestart( false ),
4661 30500 : mbUpdateListCount( false )
4662 : {
4663 30500 : bool bRemoveFromList( false );
4664 30500 : if ( nWhich2 != 0 && nWhich2 > nWhich1 )
4665 : {
4666 : // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
4667 0 : if ( nWhich1 <= RES_PARATR_NUMRULE && RES_PARATR_NUMRULE <= nWhich2 )
4668 : {
4669 0 : bRemoveFromList = mrTxtNode.GetNumRule() != 0;
4670 0 : mbListStyleOrIdReset = true;
4671 : }
4672 0 : else if ( nWhich1 <= RES_PARATR_LIST_ID && RES_PARATR_LIST_ID <= nWhich2 )
4673 : {
4674 0 : bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
4675 0 : mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET;
4676 : // #i92898#
4677 0 : mbListStyleOrIdReset = true;
4678 : }
4679 :
4680 0 : if ( !bRemoveFromList )
4681 : {
4682 : // RES_PARATR_LIST_LEVEL
4683 0 : mbUpdateListLevel = ( nWhich1 <= RES_PARATR_LIST_LEVEL &&
4684 0 : RES_PARATR_LIST_LEVEL <= nWhich2 &&
4685 0 : mrTxtNode.HasAttrListLevel() );
4686 :
4687 : // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
4688 : mbUpdateListRestart =
4689 0 : ( nWhich1 <= RES_PARATR_LIST_ISRESTART && RES_PARATR_LIST_ISRESTART <= nWhich2 &&
4690 0 : mrTxtNode.IsListRestart() ) ||
4691 0 : ( nWhich1 <= RES_PARATR_LIST_RESTARTVALUE && RES_PARATR_LIST_RESTARTVALUE <= nWhich2 &&
4692 0 : mrTxtNode.HasAttrListRestartValue() );
4693 :
4694 : // RES_PARATR_LIST_ISCOUNTED
4695 : mbUpdateListCount =
4696 0 : ( nWhich1 <= RES_PARATR_LIST_ISCOUNTED && RES_PARATR_LIST_ISCOUNTED <= nWhich2 &&
4697 0 : !mrTxtNode.IsCountedInList() );
4698 : }
4699 :
4700 : // #i70748#
4701 : // RES_PARATR_OUTLINELEVEL
4702 0 : if ( nWhich1 <= RES_PARATR_OUTLINELEVEL && RES_PARATR_OUTLINELEVEL <= nWhich2 )
4703 : {
4704 0 : mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4705 : }
4706 : }
4707 : else
4708 : {
4709 : // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
4710 30500 : if ( nWhich1 == RES_PARATR_NUMRULE )
4711 : {
4712 5133 : bRemoveFromList = mrTxtNode.GetNumRule() != 0;
4713 5133 : mbListStyleOrIdReset = true;
4714 : }
4715 25367 : else if ( nWhich1 == RES_PARATR_LIST_ID )
4716 : {
4717 5644 : bRemoveFromList = mrTxtNode.GetpSwAttrSet() &&
4718 5644 : mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET;
4719 : // #i92898#
4720 4781 : mbListStyleOrIdReset = true;
4721 : }
4722 : // #i70748#
4723 : // RES_PARATR_OUTLINELEVEL
4724 20586 : else if ( nWhich1 == RES_PARATR_OUTLINELEVEL )
4725 : {
4726 1 : mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4727 : }
4728 :
4729 30500 : if ( !bRemoveFromList )
4730 : {
4731 : // RES_PARATR_LIST_LEVEL
4732 34884 : mbUpdateListLevel = nWhich1 == RES_PARATR_LIST_LEVEL &&
4733 34884 : mrTxtNode.HasAttrListLevel();
4734 :
4735 : // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
4736 5089 : mbUpdateListRestart = ( nWhich1 == RES_PARATR_LIST_ISRESTART &&
4737 60207 : mrTxtNode.IsListRestart() ) ||
4738 5089 : ( nWhich1 == RES_PARATR_LIST_RESTARTVALUE &&
4739 35192 : mrTxtNode.HasAttrListRestartValue() );
4740 :
4741 : // RES_PARATR_LIST_ISCOUNTED
4742 35671 : mbUpdateListCount = nWhich1 == RES_PARATR_LIST_ISCOUNTED &&
4743 35671 : !mrTxtNode.IsCountedInList();
4744 : }
4745 : }
4746 :
4747 30500 : if ( bRemoveFromList && mrTxtNode.IsInList() )
4748 : {
4749 397 : mrTxtNode.RemoveFromList();
4750 : }
4751 30500 : }
4752 :
4753 1487 : HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode,
4754 : const std::vector<sal_uInt16>& rWhichArr )
4755 : : mrTxtNode( rTxtNode ),
4756 : mbListStyleOrIdReset( false ),
4757 : mbUpdateListLevel( false ),
4758 : mbUpdateListRestart( false ),
4759 1487 : mbUpdateListCount( false )
4760 : {
4761 1487 : bool bRemoveFromList( false );
4762 : {
4763 1487 : std::vector<sal_uInt16>::const_iterator it;
4764 9164 : for ( it = rWhichArr.begin(); it != rWhichArr.end(); ++it)
4765 : {
4766 : // RES_PARATR_NUMRULE and RES_PARATR_LIST_ID
4767 7677 : if ( *it == RES_PARATR_NUMRULE )
4768 : {
4769 466 : bRemoveFromList = bRemoveFromList ||
4770 466 : mrTxtNode.GetNumRule() != 0;
4771 233 : mbListStyleOrIdReset = true;
4772 : }
4773 7444 : else if ( *it == RES_PARATR_LIST_ID )
4774 : {
4775 0 : bRemoveFromList = bRemoveFromList ||
4776 0 : ( mrTxtNode.GetpSwAttrSet() &&
4777 0 : mrTxtNode.GetpSwAttrSet()->GetItemState( RES_PARATR_LIST_ID, sal_False ) == SFX_ITEM_SET );
4778 : // #i92898#
4779 0 : mbListStyleOrIdReset = true;
4780 : }
4781 : // #i70748#
4782 : // RES_PARATR_OUTLINELEVEL
4783 7444 : else if ( *it == RES_PARATR_OUTLINELEVEL )
4784 : {
4785 0 : mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4786 : }
4787 :
4788 7677 : if ( !bRemoveFromList )
4789 : {
4790 : // RES_PARATR_LIST_LEVEL
4791 15654 : mbUpdateListLevel = mbUpdateListLevel ||
4792 8208 : ( *it == RES_PARATR_LIST_LEVEL &&
4793 8210 : mrTxtNode.HasAttrListLevel() );
4794 :
4795 : // RES_PARATR_LIST_ISRESTART and RES_PARATR_LIST_RESTARTVALUE
4796 7444 : mbUpdateListRestart = mbUpdateListRestart ||
4797 7444 : ( *it == RES_PARATR_LIST_ISRESTART &&
4798 14888 : mrTxtNode.IsListRestart() ) ||
4799 7444 : ( *it == RES_PARATR_LIST_RESTARTVALUE &&
4800 7444 : mrTxtNode.HasAttrListRestartValue() );
4801 :
4802 : // RES_PARATR_LIST_ISCOUNTED
4803 14888 : mbUpdateListCount = mbUpdateListCount ||
4804 7444 : ( *it == RES_PARATR_LIST_ISCOUNTED &&
4805 7444 : !mrTxtNode.IsCountedInList() );
4806 : }
4807 : }
4808 : }
4809 :
4810 1487 : if ( bRemoveFromList && mrTxtNode.IsInList() )
4811 : {
4812 233 : mrTxtNode.RemoveFromList();
4813 : }
4814 1487 : }
4815 :
4816 1583 : HandleResetAttrAtTxtNode::HandleResetAttrAtTxtNode( SwTxtNode& rTxtNode )
4817 : : mrTxtNode( rTxtNode ),
4818 : mbListStyleOrIdReset( false ),
4819 : mbUpdateListLevel( false ),
4820 : mbUpdateListRestart( false ),
4821 1583 : mbUpdateListCount( false )
4822 : {
4823 1583 : mbListStyleOrIdReset = true;
4824 1583 : if ( rTxtNode.IsInList() )
4825 : {
4826 180 : rTxtNode.RemoveFromList();
4827 : }
4828 : // #i70748#
4829 1583 : mrTxtNode.ResetEmptyListStyleDueToResetOutlineLevelAttr();
4830 1583 : }
4831 :
4832 33570 : HandleResetAttrAtTxtNode::~HandleResetAttrAtTxtNode()
4833 : {
4834 33570 : if ( mbListStyleOrIdReset && !mrTxtNode.IsInList() )
4835 : {
4836 : // check, if in spite of the reset of the list style or the list id
4837 : // the paragraph still has to be added to a list.
4838 35556 : if ( mrTxtNode.GetNumRule() &&
4839 12828 : mrTxtNode.GetListId().Len() > 0 )
4840 : {
4841 : // #i96062#
4842 : // If paragraph has no list level attribute set and list style
4843 : // is the outline style, apply outline level as the list level.
4844 962 : if ( !mrTxtNode.HasAttrListLevel() &&
4845 230 : mrTxtNode.GetNumRule()->GetName().EqualsAscii(
4846 634 : SwNumRule::GetOutlineRuleName()) &&
4847 38 : mrTxtNode.GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() )
4848 : {
4849 38 : int nNewListLevel = mrTxtNode.GetTxtColl()->GetAssignedOutlineStyleLevel();
4850 38 : if ( 0 <= nNewListLevel && nNewListLevel < MAXLEVEL )
4851 : {
4852 38 : mrTxtNode.SetAttrListLevel( nNewListLevel );
4853 : }
4854 : }
4855 366 : mrTxtNode.AddToList();
4856 : }
4857 : // #i70748#
4858 : // #i105562#
4859 13216 : else if ( mrTxtNode.GetpSwAttrSet() &&
4860 1852 : dynamic_cast<const SfxUInt16Item &>(mrTxtNode.GetAttr( RES_PARATR_OUTLINELEVEL, sal_False )).GetValue() > 0 )
4861 : {
4862 0 : mrTxtNode.SetEmptyListStyleDueToSetOutlineLevelAttr();
4863 : }
4864 : }
4865 :
4866 33570 : if ( mrTxtNode.IsInList() )
4867 : {
4868 1867 : if ( mbUpdateListLevel )
4869 : {
4870 180 : SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4871 180 : pNodeNum->SetLevelInListTree( mrTxtNode.GetAttrListLevel() );
4872 : }
4873 :
4874 1867 : if ( mbUpdateListRestart )
4875 : {
4876 0 : SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4877 0 : pNodeNum->InvalidateMe();
4878 0 : pNodeNum->NotifyInvalidSiblings();
4879 : }
4880 :
4881 1867 : if ( mbUpdateListCount )
4882 : {
4883 0 : SwNodeNum* pNodeNum = const_cast<SwNodeNum*>(mrTxtNode.GetNum());
4884 0 : pNodeNum->InvalidateAndNotifyTree();
4885 : }
4886 : }
4887 33570 : }
4888 : // End of class <HandleResetAttrAtTxtNode>
4889 : }
4890 :
4891 30500 : sal_Bool SwTxtNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
4892 : {
4893 30500 : const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4894 30500 : mbInSetOrResetAttr = true;
4895 :
4896 30500 : HandleResetAttrAtTxtNode aHandleResetAttr( *this, nWhich1, nWhich2 );
4897 :
4898 30500 : sal_Bool bRet = SwCntntNode::ResetAttr( nWhich1, nWhich2 );
4899 :
4900 30500 : mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4901 :
4902 30500 : return bRet;
4903 : }
4904 :
4905 1487 : sal_Bool SwTxtNode::ResetAttr( const std::vector<sal_uInt16>& rWhichArr )
4906 : {
4907 1487 : const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4908 1487 : mbInSetOrResetAttr = true;
4909 :
4910 1487 : HandleResetAttrAtTxtNode aHandleResetAttr( *this, rWhichArr );
4911 :
4912 1487 : sal_Bool bRet = SwCntntNode::ResetAttr( rWhichArr );
4913 :
4914 1487 : mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4915 :
4916 1487 : return bRet;
4917 : }
4918 :
4919 1583 : sal_uInt16 SwTxtNode::ResetAllAttr()
4920 : {
4921 1583 : const bool bOldIsSetOrResetAttr( mbInSetOrResetAttr );
4922 1583 : mbInSetOrResetAttr = true;
4923 :
4924 1583 : HandleResetAttrAtTxtNode aHandleResetAttr( *this );
4925 :
4926 1583 : sal_uInt16 nRet = SwCntntNode::ResetAllAttr();
4927 :
4928 1583 : mbInSetOrResetAttr = bOldIsSetOrResetAttr;
4929 :
4930 1583 : return nRet;
4931 : }
4932 :
4933 :
4934 0 : sal_uInt32 SwTxtNode::GetRsid( xub_StrLen nStt, xub_StrLen nEnd ) const
4935 : {
4936 0 : SfxItemSet aSet( (SfxItemPool&) (GetDoc()->GetAttrPool()), RES_CHRATR_RSID, RES_CHRATR_RSID );
4937 0 : if ( GetAttr(aSet, nStt, nEnd) )
4938 : {
4939 0 : SvxRsidItem* pRsid = (SvxRsidItem*)aSet.GetItem(RES_CHRATR_RSID);
4940 0 : if( pRsid )
4941 0 : return pRsid->GetValue();
4942 : }
4943 :
4944 0 : return 0;
4945 : }
4946 :
4947 228 : sal_uInt32 SwTxtNode::GetParRsid() const
4948 : {
4949 228 : return reinterpret_cast<const SvxRsidItem&>(GetAttr( RES_PARATR_RSID )).GetValue();
4950 : }
4951 :
4952 0 : bool SwTxtNode::CompareParRsid( const SwTxtNode &rTxtNode ) const
4953 : {
4954 0 : sal_uInt32 nThisRsid = GetParRsid();
4955 0 : sal_uInt32 nRsid = rTxtNode.GetParRsid();
4956 :
4957 0 : return nThisRsid == nRsid;
4958 : }
4959 :
4960 0 : bool SwTxtNode::CompareRsid( const SwTxtNode &rTxtNode, xub_StrLen nStt1, xub_StrLen nStt2,
4961 : xub_StrLen nEnd1, xub_StrLen nEnd2 ) const
4962 :
4963 : {
4964 0 : sal_uInt32 nThisRsid = GetRsid( nStt1, nEnd1 ? nEnd1 : nStt1 );
4965 0 : sal_uInt32 nRsid = rTxtNode.GetRsid( nStt2, nEnd2 ? nEnd2 : nStt2 );
4966 :
4967 0 : return nThisRsid == nRsid;
4968 : }
4969 :
4970 : // sw::Metadatable
4971 124 : ::sfx2::IXmlIdRegistry& SwTxtNode::GetRegistry()
4972 : {
4973 124 : return GetDoc()->GetXmlIdRegistry();
4974 : }
4975 :
4976 1224 : bool SwTxtNode::IsInClipboard() const
4977 : {
4978 1224 : return GetDoc()->IsClipBoard();
4979 : }
4980 :
4981 1234 : bool SwTxtNode::IsInUndo() const
4982 : {
4983 1234 : return GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(GetNodes());
4984 : }
4985 :
4986 158 : bool SwTxtNode::IsInContent() const
4987 : {
4988 158 : return !GetDoc()->IsInHeaderFooter( SwNodeIndex(*this) );
4989 : }
4990 :
4991 1 : void SwTxtNode::SwClientNotify( const SwModify& rModify, const SfxHint& rHint )
4992 : {
4993 1 : const SwAttrHint* pHint = dynamic_cast<const SwAttrHint*>(&rHint);
4994 1 : if ( pHint && pHint->GetId() == RES_CONDTXTFMTCOLL && &rModify == GetRegisteredIn() )
4995 1 : ChkCondColl();
4996 1 : }
4997 :
4998 : #include <unoparagraph.hxx>
4999 :
5000 : uno::Reference< rdf::XMetadatable >
5001 1 : SwTxtNode::MakeUnoObject()
5002 : {
5003 : const uno::Reference<rdf::XMetadatable> xMeta(
5004 1 : SwXParagraph::CreateXParagraph(*GetDoc(), *this), uno::UNO_QUERY);
5005 1 : return xMeta;
5006 99 : }
5007 :
5008 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|