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