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