1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: thints.cxx,v $
10 * $Revision: 1.65.62.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <sot/factory.hxx>
37 #include <svx/xmlcnitm.hxx>
38 #include <svtools/whiter.hxx>
39 #include <svtools/itemiter.hxx>
40 #include <svtools/stylepool.hxx>
41 #include <svx/fontitem.hxx>
42 #include <svx/langitem.hxx>
43 #include <svx/emphitem.hxx>
44 #include <svx/charscaleitem.hxx>
45 #include <svx/charrotateitem.hxx>
46 // --> OD 2008-01-16 #newlistlevelattrs#
47 #include <svx/lrspitem.hxx>
49 #include <txtinet.hxx>
50 #include <txtflcnt.hxx>
52 #include <fmtanchr.hxx>
53 #include <fmtinfmt.hxx>
55 #include <fchrfmt.hxx>
56 #include <fmtautofmt.hxx>
57 #include <fmtflcnt.hxx>
59 #include <txttxmrk.hxx>
60 #include <txtrfmrk.hxx>
63 #include <charatr.hxx>
64 #include <charfmt.hxx>
67 #include <fmtruby.hxx>
68 #include <breakit.hxx>
75 #include <rolbck.hxx> // fuer SwRegHistory
77 #include <docufld.hxx>
80 #include <poolfmt.hxx>
82 #include <istyleaccess.hxx>
83 // OD 26.06.2003 #108784#
84 #include <dcontact.hxx>
86 #include <svtools/smplhint.hxx>
91 #define CHECK Check();
96 using namespace ::com::sun::star::i18n
;
101 , m_bFontChange(true)
102 , m_bInSplitNode(false)
103 , m_bCalcHiddenParaField(false)
104 , m_bHasHiddenParaField(false)
106 , m_bDDEFields(false)
111 // This function takes care for the following text attribute:
112 // RES_TXTATR_CHARFMT, RES_TXTATR_INETFMT, RES_TXTATR_AUTOFMT, and
113 // RES_TXTATR_CJK_RUBY. These attributes have to be handled in a
114 // special way (Portion building).
115 // 1. New attribute is RES_TXTATR_AUTOFMT or RES_TXTATR_CHARFMT:
116 // The new attribute will be split by any existing RES_TXTATR_AUTOFMT,
117 // RES_TXTATR_CHARFMT or RES_TXTATR_INETFMT. The new attribute itself will
118 // split any existing RES_TXTATR_AUTOFMT or RES_TXTATR_CHARFMT.
119 // 2. New attribute is RES_TXTATR_INETFMT:
120 // The new attribute will split any existing RES_TXTATR_AUTOFMT or RES_TXTATR_CHARFMT.
121 // The new attribute will suppress any existing RES_TXTATR_INETFMT.
122 // 3. New attribute is RES_TXTATR_CJK_RUBY:
123 // The new attribute will suppress any existing RES_TXTATR_CJK_RUBY.
125 void SwpHints::BuildPortions( SwTxtNode
& rNode
, SwTxtAttr
& rNewHint
, USHORT nMode
)
127 ASSERT( RES_TXTATR_CHARFMT
== rNewHint
.Which() ||
128 RES_TXTATR_INETFMT
== rNewHint
.Which() ||
129 RES_TXTATR_AUTOFMT
== rNewHint
.Which() ||
130 RES_TXTATR_CJK_RUBY
== rNewHint
.Which(),
131 "Expecting CHARFMT or AUTOFMT or INETFMT or RUBY" )
133 const USHORT nWhich
= rNewHint
.Which();
135 const xub_StrLen nThisStart
= *rNewHint
.GetStart();
136 const xub_StrLen nThisEnd
= *rNewHint
.GetEnd();
137 const bool bNoLengthAttribute
= nThisStart
== nThisEnd
;
139 std::vector
<SwTxtAttr
*> aInsDelHints
;
140 std::vector
<SwTxtAttr
*>::iterator aIter
;
143 // 1. Some attributes are not allowed to overlap.
144 // They should displace attributes of the same kind.
145 // This is a special case for RES_TXTATR_INETFMT and
146 // RES_TXTATR_CJK_RUBY.
148 if ( RES_TXTATR_INETFMT
== nWhich
|| RES_TXTATR_CJK_RUBY
== nWhich
)
150 for ( USHORT i
= 0; i
< Count(); ++i
)
152 SwTxtAttr
* pOther
= GetTextHint(i
);
154 if ( nWhich
== pOther
->Which() )
156 xub_StrLen nOtherStart
= *pOther
->GetStart();
157 const xub_StrLen nOtherEnd
= *pOther
->GetEnd();
159 // Check if start of new attribute overlaps with pOther.
160 // Split pOther if necessary:
161 if ( nOtherStart
< nThisStart
&& nThisStart
< nOtherEnd
)
163 SwTxtAttr
* pNewAttr
= rNode
.MakeTxtAttr( pOther
->GetAttr(), nOtherStart
, nThisStart
);
164 aInsDelHints
.push_back( pNewAttr
);
166 NoteInHistory( pOther
);
167 *pOther
->GetStart() = nThisStart
;
168 NoteInHistory( pOther
, true );
169 nOtherStart
= nThisStart
;
172 // Check if end of new attribute overlaps with pOther:
173 // Split pOther if necessary:
174 if ( nOtherStart
< nThisEnd
&& nThisEnd
< nOtherEnd
)
176 SwTxtAttr
* pNewAttr
= rNode
.MakeTxtAttr( pOther
->GetAttr(),
177 nOtherStart
, nThisEnd
);
178 aInsDelHints
.push_back( pNewAttr
);
180 NoteInHistory( pOther
);
181 *pOther
->GetStart() = nThisEnd
;
182 NoteInHistory( pOther
, true );
187 // Insert the newly created attributes:
188 const sal_uInt16 nCharFmtID
= static_cast<sal_uInt16
>( RES_TXTATR_INETFMT
== nWhich
?
189 RES_POOLCHR_INET_NORMAL
:
190 RES_POOLCHR_RUBYTEXT
);
191 SwCharFmt
* pFmt
= rNode
.GetDoc()->GetCharFmtFromPool( nCharFmtID
);
193 for ( aIter
= aInsDelHints
.begin(); aIter
!= aInsDelHints
.end(); ++aIter
)
195 if ( RES_TXTATR_INETFMT
== nWhich
)
197 SwTxtINetFmt
* pInetAttr
= static_cast<SwTxtINetFmt
*>(*aIter
);
198 pInetAttr
->ChgTxtNode( &rNode
);
199 pFmt
->Add( pInetAttr
);
205 SwTxtRuby
* pRubyAttr
= static_cast<SwTxtRuby
*>(*aIter
);
206 pRubyAttr
->ChgTxtNode( &rNode
);
207 pFmt
->Add( pRubyAttr
);
211 SwpHintsArray::Insert( *aIter
);
212 NoteInHistory( *aIter
, true );
215 aInsDelHints
.clear();
217 // Now delete all attributes of the same type as the new one
218 // which are fully covered by the new attribute:
219 for ( USHORT i
= 0; i
< Count(); ++i
)
221 SwTxtAttr
* pOther
= GetTextHint(i
);
222 if ( nWhich
== pOther
->Which() )
224 const xub_StrLen nOtherStart
= *pOther
->GetStart();
225 const xub_StrLen nOtherEnd
= *pOther
->GetEnd();
227 if ( nOtherStart
>= nThisStart
&& nOtherEnd
<= nThisEnd
)
228 aInsDelHints
.push_back( pOther
);
231 for ( aIter
= aInsDelHints
.begin(); aIter
!= aInsDelHints
.end(); ++aIter
)
234 rNode
.DestroyAttr( *aIter
);
237 SwpHintsArray::Insert( &rNewHint
);
238 NoteInHistory( &rNewHint
, true );
243 ASSERT( RES_TXTATR_CHARFMT
== rNewHint
.Which() ||
244 RES_TXTATR_AUTOFMT
== rNewHint
.Which(),
245 "Expecting CHARFMT or AUTOFMT" )
248 // 2. Find the hints which cover the start and end position
249 // of the new hint. These hints have to be split into two portions:
251 if ( !bNoLengthAttribute
) // nothing to do for no length attributes
253 for ( USHORT i
= 0; i
< Count(); ++i
)
255 SwTxtAttr
* pOther
= GetTextHint(i
);
257 if ( RES_TXTATR_CHARFMT
!= pOther
->Which() &&
258 RES_TXTATR_AUTOFMT
!= pOther
->Which() )
261 xub_StrLen nOtherStart
= *pOther
->GetStart();
262 const xub_StrLen nOtherEnd
= *pOther
->GetEnd();
264 // Check if start of new attribute overlaps with pOther:
265 // Split pOther if necessary:
266 if ( nOtherStart
< nThisStart
&& nThisStart
< nOtherEnd
)
268 SwTxtAttr
* pNewAttr
= rNode
.MakeTxtAttr( pOther
->GetAttr(), nOtherStart
, nThisStart
);
269 if ( RES_TXTATR_CHARFMT
== pOther
->Which() )
270 static_cast<SwTxtCharFmt
*>(pNewAttr
)->SetSortNumber( static_cast<SwTxtCharFmt
*>(pOther
)->GetSortNumber() );
271 aInsDelHints
.push_back( pNewAttr
);
273 NoteInHistory( pOther
);
274 *pOther
->GetStart() = nThisStart
;
275 NoteInHistory( pOther
, true );
277 nOtherStart
= nThisStart
;
280 // Check if end of new attribute overlaps with pOther:
281 // Split pOther if necessary:
282 if ( nOtherStart
< nThisEnd
&& nThisEnd
< nOtherEnd
)
284 SwTxtAttr
* pNewAttr
= rNode
.MakeTxtAttr( pOther
->GetAttr(), nOtherStart
, nThisEnd
);
285 if ( RES_TXTATR_CHARFMT
== pOther
->Which() )
286 static_cast<SwTxtCharFmt
*>(pNewAttr
)->SetSortNumber( static_cast<SwTxtCharFmt
*>(pOther
)->GetSortNumber() );
287 aInsDelHints
.push_back( pNewAttr
);
289 NoteInHistory( pOther
);
290 *pOther
->GetStart() = nThisEnd
;
291 NoteInHistory( pOther
, true );
295 // Insert the newly created attributes:
296 for ( aIter
= aInsDelHints
.begin(); aIter
!= aInsDelHints
.end(); ++aIter
)
298 SwpHintsArray::Insert( *aIter
);
299 NoteInHistory( *aIter
, true );
304 if( !rNode
.GetDoc()->IsInReading() )
309 // 4. Split rNewHint into 1 ... n new hints:
311 std::set
<xub_StrLen
> aBounds
;
312 aBounds
.insert( nThisStart
);
313 aBounds
.insert( nThisEnd
);
315 if ( !bNoLengthAttribute
) // nothing to do for no length attributes
317 for ( USHORT i
= 0; i
< Count(); ++i
)
319 const SwTxtAttr
* pOther
= GetTextHint(i
);
321 if ( RES_TXTATR_CHARFMT
!= pOther
->Which() &&
322 RES_TXTATR_AUTOFMT
!= pOther
->Which() )
325 const xub_StrLen nOtherStart
= *pOther
->GetStart();
326 const xub_StrLen nOtherEnd
= *pOther
->GetEnd();
328 aBounds
.insert( nOtherStart
);
329 aBounds
.insert( nOtherEnd
);
333 std::set
<xub_StrLen
>::iterator aStartIter
= aBounds
.lower_bound( nThisStart
);
334 std::set
<xub_StrLen
>::iterator aEndIter
= aBounds
.upper_bound( nThisEnd
);
335 xub_StrLen nPorStart
= *aStartIter
;
337 bool bDestroyHint
= true;
340 // Insert the 1...n new parts of the new attribute:
342 while ( aStartIter
!= aEndIter
|| bNoLengthAttribute
)
344 ASSERT( bNoLengthAttribute
|| nPorStart
< *aStartIter
, "AUTOSTYLES: BuildPortion trouble" )
346 const xub_StrLen nPorEnd
= bNoLengthAttribute
? nPorStart
: *aStartIter
;
347 aInsDelHints
.clear();
349 // Get all hints that are in [nPorStart, nPorEnd[:
350 for ( USHORT i
= 0; i
< Count(); ++i
)
352 SwTxtAttr
*pOther
= GetTextHint(i
);
354 if ( RES_TXTATR_CHARFMT
!= pOther
->Which() &&
355 RES_TXTATR_AUTOFMT
!= pOther
->Which() )
358 const xub_StrLen nOtherStart
= *pOther
->GetStart();
360 if ( nOtherStart
> nPorStart
)
363 if ( pOther
->GetEnd() && *pOther
->GetEnd() == nPorEnd
&& nOtherStart
== nPorStart
)
365 ASSERT( *pOther
->GetEnd() == nPorEnd
, "AUTOSTYLES: BuildPortion trouble" )
366 aInsDelHints
.push_back( pOther
);
370 SwTxtAttr
* pNewAttr
= 0;
371 if ( RES_TXTATR_CHARFMT
== nWhich
)
373 // pNewHint can be inserted after calculating the sort value.
374 // This should ensure, that pNewHint comes behind the already present
376 USHORT nCharStyleCount
= 0;
377 aIter
= aInsDelHints
.begin();
378 while ( aIter
!= aInsDelHints
.end() )
380 if ( RES_TXTATR_CHARFMT
== (*aIter
)->Which() )
382 // --> FME 2007-02-16 #i74589#
383 const SwFmtCharFmt
& rOtherCharFmt
= (*aIter
)->GetCharFmt();
384 const SwFmtCharFmt
& rThisCharFmt
= rNewHint
.GetCharFmt();
385 const bool bSameCharFmt
= rOtherCharFmt
.GetCharFmt() == rThisCharFmt
.GetCharFmt();
388 // --> OD 2009-03-24 #i90311#
389 // Do not remove existing character format hint during XML import
390 if ( !rNode
.GetDoc()->IsInXMLImport() &&
391 ( !( nsSetAttrMode::SETATTR_DONTREPLACE
& nMode
) ||
392 bNoLengthAttribute
||
398 rNode
.DestroyAttr( *aIter
);
405 // remove all attributes from auto styles, which are explicitely set in
406 // the new character format:
407 ASSERT( RES_TXTATR_AUTOFMT
== (*aIter
)->Which(), "AUTOSTYLES - Misc trouble" )
408 SwTxtAttr
* pOther
= *aIter
;
409 boost::shared_ptr
<SfxItemSet
> pOldStyle
= static_cast<const SwFmtAutoFmt
&>(pOther
->GetAttr()).GetStyleHandle();
411 // For each attribute in the automatic style check if it
412 // is also set the the new character style:
413 SfxItemSet
aNewSet( *pOldStyle
->GetPool(), RES_CHRATR_BEGIN
, RES_CHRATR_END
);
414 SfxItemIter
aItemIter( *pOldStyle
);
415 const SfxPoolItem
* pItem
= aItemIter
.GetCurItem();
418 if ( !CharFmt::IsItemIncluded( pItem
->Which(), &rNewHint
) )
420 aNewSet
.Put( *pItem
);
423 if( aItemIter
.IsAtEnd() )
426 pItem
= aItemIter
.NextItem();
431 rNode
.DestroyAttr( pOther
);
433 // Create new AutoStyle
434 if ( aNewSet
.Count() )
436 pNewAttr
= rNode
.MakeTxtAttr( aNewSet
,
437 nPorStart
, nPorEnd
);
438 SwpHintsArray::Insert( pNewAttr
);
439 NoteInHistory( pNewAttr
, true );
445 // If there is no current hint and start and end of rNewHint
446 // is ok, we do not need to create a new txtattr.
447 if ( nPorStart
== nThisStart
&&
448 nPorEnd
== nThisEnd
&&
451 pNewAttr
= &rNewHint
;
452 bDestroyHint
= false;
456 pNewAttr
= rNode
.MakeTxtAttr( rNewHint
.GetAttr(), nPorStart
, nPorEnd
);
457 static_cast<SwTxtCharFmt
*>(pNewAttr
)->SetSortNumber( nCharStyleCount
);
462 // Find the current autostyle. Mix attributes if necessary.
463 SwTxtAttr
* pCurrentAutoStyle
= 0;
464 SwTxtAttr
* pCurrentCharFmt
= 0;
465 aIter
= aInsDelHints
.begin();
466 while ( aIter
!= aInsDelHints
.end() )
468 if ( RES_TXTATR_AUTOFMT
== (*aIter
)->Which() )
469 pCurrentAutoStyle
= *aIter
;
470 else if ( RES_TXTATR_CHARFMT
== (*aIter
)->Which() )
471 pCurrentCharFmt
= *aIter
;
475 boost::shared_ptr
<SfxItemSet
> pNewStyle
= static_cast<const SwFmtAutoFmt
&>(rNewHint
.GetAttr()).GetStyleHandle();
476 if ( pCurrentAutoStyle
)
478 boost::shared_ptr
<SfxItemSet
> pCurrentStyle
= static_cast<const SwFmtAutoFmt
&>(pCurrentAutoStyle
->GetAttr()).GetStyleHandle();
481 SfxItemSet
aNewSet( *pCurrentStyle
);
482 aNewSet
.Put( *pNewStyle
);
484 // --> FME 2007-4-11 #i75750# Remove attributes already set at whole paragraph
485 // --> FME 2007-09-24 #i81764# This should not be applied for no length attributes!!! <--
486 if ( !bNoLengthAttribute
&& rNode
.HasSwAttrSet() && aNewSet
.Count() )
488 SfxItemIter
aIter2( aNewSet
);
489 const SfxPoolItem
* pItem
= aIter2
.GetCurItem();
490 const SfxItemSet
& rWholeParaAttrSet
= rNode
.GetSwAttrSet();
494 const SfxPoolItem
* pTmpItem
= 0;
495 if ( SFX_ITEM_SET
== rWholeParaAttrSet
.GetItemState( pItem
->Which(), FALSE
, &pTmpItem
) &&
498 // Do not clear item if the attribute is set in a character format:
499 if ( !pCurrentCharFmt
|| 0 == CharFmt::GetItem( *pCurrentCharFmt
, pItem
->Which() ) )
500 aNewSet
.ClearItem( pItem
->Which() );
503 while (!aIter2
.IsAtEnd() && 0 != (pItem
= aIter2
.NextItem()));
508 Delete( pCurrentAutoStyle
);
509 rNode
.DestroyAttr( pCurrentAutoStyle
);
511 // Create new AutoStyle
512 if ( aNewSet
.Count() )
513 pNewAttr
= rNode
.MakeTxtAttr( aNewSet
, nPorStart
, nPorEnd
);
517 // Remove any attributes which are already set at the whole paragraph:
518 bool bOptimizeAllowed
= true;
520 SfxItemSet
* pNewSet
= 0;
521 // --> FME 2007-4-11 #i75750# Remove attributes already set at whole paragraph
522 // --> FME 2007-09-24 #i81764# This should not be applied for no length attributes!!! <--
523 if ( !bNoLengthAttribute
&& rNode
.HasSwAttrSet() && pNewStyle
->Count() )
525 SfxItemIter
aIter2( *pNewStyle
);
526 const SfxPoolItem
* pItem
= aIter2
.GetCurItem();
527 const SfxItemSet
& rWholeParaAttrSet
= rNode
.GetSwAttrSet();
531 const SfxPoolItem
* pTmpItem
= 0;
532 if ( SFX_ITEM_SET
== rWholeParaAttrSet
.GetItemState( pItem
->Which(), FALSE
, &pTmpItem
) &&
535 // Do not clear item if the attribute is set in a character format:
536 if ( !pCurrentCharFmt
|| 0 == CharFmt::GetItem( *pCurrentCharFmt
, pItem
->Which() ) )
539 pNewSet
= pNewStyle
->Clone( TRUE
);
540 pNewSet
->ClearItem( pItem
->Which() );
544 while (!aIter2
.IsAtEnd() && 0 != (pItem
= aIter2
.NextItem()));
548 bOptimizeAllowed
= false;
549 if ( pNewSet
->Count() )
550 pNewStyle
= rNode
.getIDocumentStyleAccess().getAutomaticStyle( *pNewSet
, IStyleAccess::AUTO_STYLE_CHAR
);
559 // Create new AutoStyle
560 // If there is no current hint and start and end of rNewHint
561 // is ok, we do not need to create a new txtattr.
562 if ( bOptimizeAllowed
&&
563 nPorStart
== nThisStart
&&
564 nPorEnd
== nThisEnd
)
566 pNewAttr
= &rNewHint
;
567 bDestroyHint
= false;
569 else if ( pNewStyle
.get() )
571 pNewAttr
= rNode
.MakeTxtAttr( *pNewStyle
, nPorStart
, nPorEnd
);
578 SwpHintsArray::Insert( pNewAttr
);
579 // if ( bDestroyHint )
580 NoteInHistory( pNewAttr
, true );
583 if ( !bNoLengthAttribute
)
585 nPorStart
= *aStartIter
;
593 rNode
.DestroyAttr( &rNewHint
);
596 /*************************************************************************
597 * SwTxtNode::MakeTxtAttr()
598 *************************************************************************/
600 // create new text attribute
601 SwTxtAttr
* SwTxtNode::MakeTxtAttr( const SfxPoolItem
& rAttr
,
602 xub_StrLen nStt
, xub_StrLen nEnd
, bool bRedlineAttr
)
604 SwDoc
* pDoc
= GetDoc();
606 if ( !bRedlineAttr
&& isCHRATR(rAttr
.Which()) )
608 // Somebody wants to build a SwTxtAttr for a character attribute (and
609 // this attribute is not meant for redlining). Sorry, this is not allowed
610 // any longer. You'll get a brand new autostyle attribute:
611 SfxItemSet
aItemSet( pDoc
->GetAttrPool(), RES_CHRATR_BEGIN
, RES_CHRATR_END
);
612 aItemSet
.Put( rAttr
);
613 return MakeTxtAttr( aItemSet
, nStt
, nEnd
);
615 else if ( RES_TXTATR_AUTOFMT
== rAttr
.Which() &&
616 static_cast<const SwFmtAutoFmt
&>(rAttr
).GetStyleHandle()->GetPool() != &pDoc
->GetAttrPool() )
618 // If the attribut is an autostyle which referes to a pool that is different from
619 // pDoc's pool, we have to correct this:
620 const StylePool::SfxItemSet_Pointer_t pAutoStyle
= static_cast<const SwFmtAutoFmt
&>(rAttr
).GetStyleHandle();
621 const SfxItemSet
* pNewSet
= pAutoStyle
->SfxItemSet::Clone( TRUE
, &pDoc
->GetAttrPool() );
622 SwTxtAttr
* pNew
= MakeTxtAttr( *pNewSet
, nStt
, nEnd
);
627 // Put new attribute into pool unless we are asked to build a redline attribute
628 const SfxPoolItem
& rNew
= !bRedlineAttr
? GetDoc()->GetAttrPool().Put( rAttr
) : rAttr
;
631 switch( rNew
.Which() )
633 case RES_TXTATR_CHARFMT
:
635 SwFmtCharFmt
&rFmtCharFmt
= (SwFmtCharFmt
&) rNew
;
636 if( !rFmtCharFmt
.GetCharFmt() )
637 rFmtCharFmt
.SetCharFmt( GetDoc()->GetDfltCharFmt() );
639 pNew
= new SwTxtCharFmt( rFmtCharFmt
, nStt
, nEnd
);
642 case RES_TXTATR_INETFMT
:
643 pNew
= new SwTxtINetFmt( (SwFmtINetFmt
&)rNew
, nStt
, nEnd
);
645 case RES_TXTATR_FIELD
:
646 pNew
= new SwTxtFld( (SwFmtFld
&)rNew
, nStt
);
648 case RES_TXTATR_FLYCNT
:
650 // erst hier wird das Frame-Format kopiert (mit Inhalt) !!
651 pNew
= new SwTxtFlyCnt( (SwFmtFlyCnt
&)rNew
, nStt
);
652 // Kopie von einem Text-Attribut
653 if( ((SwFmtFlyCnt
&)rAttr
).GetTxtFlyCnt() )
654 // dann muss das Format Kopiert werden
655 ((SwTxtFlyCnt
*)pNew
)->CopyFlyFmt( GetDoc() );
659 pNew
= new SwTxtFtn( (SwFmtFtn
&)rNew
, nStt
);
660 // ggfs. SeqNo kopieren
661 if( ((SwFmtFtn
&)rAttr
).GetTxtFtn() )
662 ((SwTxtFtn
*)pNew
)->SetSeqNo( ((SwFmtFtn
&)rAttr
).GetTxtFtn()->GetSeqRefNo() );
664 case RES_TXTATR_HARDBLANK
:
665 pNew
= new SwTxtHardBlank( (SwFmtHardBlank
&)rNew
, nStt
);
667 case RES_CHRATR_TWO_LINES
:
668 pNew
= new SwTxt2Lines( (SvxTwoLinesItem
&)rNew
, nStt
, nEnd
);
670 case RES_TXTATR_REFMARK
:
672 ? new SwTxtRefMark( (SwFmtRefMark
&)rNew
, nStt
)
673 : new SwTxtRefMark( (SwFmtRefMark
&)rNew
, nStt
, &nEnd
);
675 case RES_TXTATR_TOXMARK
:
676 pNew
= new SwTxtTOXMark( (SwTOXMark
&)rNew
, nStt
, &nEnd
);
678 case RES_UNKNOWNATR_CONTAINER
:
679 case RES_TXTATR_UNKNOWN_CONTAINER
:
680 pNew
= new SwTxtXMLAttrContainer( (SvXMLAttrContainerItem
&)rNew
,
683 case RES_TXTATR_CJK_RUBY
:
684 pNew
= new SwTxtRuby( (SwFmtRuby
&)rNew
, nStt
, nEnd
);
687 pNew
= new SwTxtAttrEnd( rNew
, nStt
, nEnd
);
694 SwTxtAttr
* SwTxtNode::MakeTxtAttr( const SfxItemSet
& rSet
, xub_StrLen nStt
, xub_StrLen nEnd
)
696 IStyleAccess
& rStyleAccess
= getIDocumentStyleAccess();
697 const StylePool::SfxItemSet_Pointer_t pAutoStyle
= rStyleAccess
.getAutomaticStyle( rSet
, IStyleAccess::AUTO_STYLE_CHAR
);
698 SwFmtAutoFmt aNewAutoFmt
;
699 aNewAutoFmt
.SetStyleHandle( pAutoStyle
);
700 SwTxtAttr
* pNew
= MakeTxtAttr( aNewAutoFmt
, nStt
, nEnd
);
705 // loesche das Text-Attribut (muss beim Pool abgemeldet werden!)
706 void SwTxtNode::DestroyAttr( SwTxtAttr
* pAttr
)
710 // einige Sachen muessen vorm Loeschen der "Format-Attribute" erfolgen
711 SwDoc
* pDoc
= GetDoc();
713 switch( pAttr
->Which() )
715 case RES_TXTATR_FLYCNT
:
717 // siehe auch die Anmerkung "Loeschen von Formaten
718 // zeichengebundener Frames" in fesh.cxx, SwFEShell::DelFmt()
719 SwFrmFmt
* pFmt
= pAttr
->GetFlyCnt().GetFrmFmt();
720 if( pFmt
) // vom Undo auf 0 gesetzt ??
721 pDoc
->DelLayoutFmt( (SwFlyFrmFmt
*)pFmt
);
725 case RES_CHRATR_HIDDEN
:
726 SetCalcHiddenCharFlags();
730 ((SwTxtFtn
*)pAttr
)->SetStartNode( 0 );
731 nDelMsg
= RES_FOOTNOTE_DELETED
;
734 case RES_TXTATR_FIELD
:
735 if( !pDoc
->IsInDtor() )
737 // Wenn wir ein HiddenParaField sind, dann muessen wir
738 // ggf. fuer eine Neuberechnung des Visible-Flags sorgen.
739 const SwField
* pFld
= pAttr
->GetFld().GetFld();
741 //JP 06-08-95: DDE-Felder bilden eine Ausnahme
742 ASSERT( RES_DDEFLD
== pFld
->GetTyp()->Which() ||
743 this == ((SwTxtFld
*)pAttr
)->GetpTxtNode(),
744 "Wo steht denn dieses Feld?" )
746 // bestimmte Felder mussen am Doc das Calculations-Flag updaten
747 switch( pFld
->GetTyp()->Which() )
749 case RES_HIDDENPARAFLD
:
750 SetCalcHiddenParaField();
752 case RES_DBSETNUMBERFLD
:
756 case RES_HIDDENTXTFLD
:
757 case RES_DBNUMSETFLD
:
758 case RES_DBNEXTSETFLD
:
759 if( !pDoc
->IsNewFldLst() && GetNodes().IsDocNodes() )
760 pDoc
->InsDelFldInFldLst( FALSE
, *(SwTxtFld
*)pAttr
);
763 if( GetNodes().IsDocNodes() &&
764 ((SwTxtFld
*)pAttr
)->GetpTxtNode() )
765 ((SwDDEFieldType
*)pFld
->GetTyp())->DecRefCnt();
769 const_cast<SwFmtFld
&>(pAttr
->GetFld()).Broadcast( SwFmtFldHint( &((SwTxtFld
*)pAttr
)->GetFld(), SWFMTFLD_REMOVED
) );
774 nDelMsg
= RES_FIELD_DELETED
;
777 case RES_TXTATR_TOXMARK
:
778 nDelMsg
= RES_TOXMARK_DELETED
;
781 case RES_TXTATR_REFMARK
:
782 nDelMsg
= RES_REFMARK_DELETED
;
786 if( nDelMsg
&& !pDoc
->IsInDtor() && GetNodes().IsDocNodes() )
788 SwPtrMsgPoolItem
aMsgHint( nDelMsg
, (void*)&pAttr
->GetAttr() );
789 pDoc
->GetUnoCallBack()->Modify( &aMsgHint
, &aMsgHint
);
792 pAttr
->RemoveFromPool( pDoc
->GetAttrPool() );
797 /*************************************************************************
798 * SwTxtNode::Insert()
799 *************************************************************************/
801 // lege ein neues TextAttribut an und fuege es ins SwpHints-Array ein
802 SwTxtAttr
* SwTxtNode::InsertItem( const SfxPoolItem
& rAttr
,
803 xub_StrLen nStt
, xub_StrLen nEnd
, USHORT nMode
)
805 // character attributes will be inserted as automatic styles:
806 ASSERT( !isCHRATR(rAttr
.Which()), "AUTOSTYLES - "
807 "SwTxtNode::InsertItem should not be called with character attributes");
809 SwTxtAttr
* pNew
= MakeTxtAttr( rAttr
, nStt
, nEnd
);
812 Insert( pNew
, nMode
);
817 // uebernehme den Pointer auf das Text-Attribut
818 BOOL
SwTxtNode::Insert( SwTxtAttr
*pAttr
, USHORT nMode
)
820 BOOL bHiddenPara
= FALSE
;
822 ASSERT( pAttr
&& *pAttr
->GetStart() <= Len(), "StartIdx hinter Len!" );
824 if( !pAttr
->GetEnd() )
826 USHORT nInsMode
= nMode
;
827 switch( pAttr
->Which() )
829 case RES_TXTATR_FLYCNT
:
831 SwTxtFlyCnt
*pFly
= (SwTxtFlyCnt
*)pAttr
;
832 SwFrmFmt
* pFmt
= pAttr
->GetFlyCnt().GetFrmFmt();
833 if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR
& nInsMode
) )
835 // Wir muessen zuerst einfuegen, da in SetAnchor()
836 // dem FlyFrm GetStart() uebermittelt wird.
837 //JP 11.05.98: falls das Anker-Attribut schon richtig
838 // gesetzt ist, dann korrigiere dieses nach dem Einfuegen
839 // des Zeichens. Sonst muesste das immer ausserhalb
840 // erfolgen (Fehleranfaellig !)
841 const SwFmtAnchor
* pAnchor
= 0;
842 pFmt
->GetItemState( RES_ANCHOR
, FALSE
,
843 (const SfxPoolItem
**)&pAnchor
);
845 SwIndex
aIdx( this, *pAttr
->GetStart() );
846 Insert( GetCharOfTxtAttr(*pAttr
), aIdx
);
847 nInsMode
|= nsSetAttrMode::SETATTR_NOTXTATRCHR
;
849 if( pAnchor
&& FLY_IN_CNTNT
== pAnchor
->GetAnchorId() &&
850 pAnchor
->GetCntntAnchor() &&
851 pAnchor
->GetCntntAnchor()->nNode
== *this &&
852 pAnchor
->GetCntntAnchor()->nContent
== aIdx
)
853 ((SwIndex
&)pAnchor
->GetCntntAnchor()->nContent
)--;
855 pFly
->SetAnchor( this );
857 // Format-Pointer kann sich im SetAnchor geaendert haben!
858 // (Kopieren in andere Docs!)
859 pFmt
= pAttr
->GetFlyCnt().GetFrmFmt();
860 SwDoc
*pDoc
= pFmt
->GetDoc();
862 // OD 26.06.2003 #108784# - allow drawing objects in header/footer.
863 // But don't allow control objects in header/footer
864 if( RES_DRAWFRMFMT
== pFmt
->Which() &&
865 pDoc
->IsInHeaderFooter( pFmt
->GetAnchor().GetCntntAnchor()->nNode
) )
867 SwDrawContact
* pDrawContact
=
868 static_cast<SwDrawContact
*>(pFmt
->FindContactObj());
870 pDrawContact
->GetMaster() &&
871 ::CheckControlLayer( pDrawContact
->GetMaster() ) )
873 // das soll nicht meoglich sein; hier verhindern
874 // Der Dtor des TxtHints loescht nicht das Zeichen.
875 // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
876 // dieses explizit loeschen
877 if( nsSetAttrMode::SETATTR_NOTXTATRCHR
& nInsMode
)
879 // loesche das Zeichen aus dem String !
880 ASSERT( ( CH_TXTATR_BREAKWORD
==
881 m_Text
.GetChar(*pAttr
->GetStart() ) ||
883 m_Text
.GetChar(*pAttr
->GetStart())),
884 "where is my attribute character?" );
885 m_Text
.Erase( *pAttr
->GetStart(), 1 );
887 SwIndex
aTmpIdx( this, *pAttr
->GetStart() );
888 Update( aTmpIdx
, 1, TRUE
);
890 // Format loeschen nicht ins Undo aufnehmen!!
891 BOOL bUndo
= pDoc
->DoesUndo();
892 pDoc
->DoUndo( FALSE
);
893 DestroyAttr( pAttr
);
894 pDoc
->DoUndo( bUndo
);
901 case RES_TXTATR_FTN
:
903 // Fussnoten, man kommt an alles irgendwie heran.
904 // CntntNode erzeugen und in die Inserts-Section stellen
905 SwDoc
*pDoc
= GetDoc();
906 SwNodes
&rNodes
= pDoc
->GetNodes();
908 // FussNote in nicht Content-/Redline-Bereich einfuegen ??
909 if( StartOfSectionIndex() < rNodes
.GetEndOfAutotext().GetIndex() )
911 // das soll nicht meoglich sein; hier verhindern
912 // Der Dtor des TxtHints loescht nicht das Zeichen.
913 // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
914 // dieses explizit loeschen
915 if( nsSetAttrMode::SETATTR_NOTXTATRCHR
& nInsMode
)
917 // loesche das Zeichen aus dem String !
918 ASSERT( ( CH_TXTATR_BREAKWORD
==
919 m_Text
.GetChar(*pAttr
->GetStart() ) ||
921 m_Text
.GetChar(*pAttr
->GetStart())),
922 "where is my attribute character?" );
923 m_Text
.Erase( *pAttr
->GetStart(), 1 );
925 SwIndex
aTmpIdx( this, *pAttr
->GetStart() );
926 Update( aTmpIdx
, 1, TRUE
);
928 DestroyAttr( pAttr
);
932 // wird eine neue Fussnote eingefuegt ??
933 BOOL bNewFtn
= 0 == ((SwTxtFtn
*)pAttr
)->GetStartNode();
936 ((SwTxtFtn
*)pAttr
)->MakeNewTextSection( GetNodes() );
937 SwRegHistory
* pHist
= GetpSwpHints()
938 ? GetpSwpHints()->GetHistory() : 0;
940 pHist
->ChangeNodeIndex( GetIndex() );
942 else if ( !GetpSwpHints() || !GetpSwpHints()->IsInSplitNode() )
944 // loesche alle Frames der Section, auf die der StartNode zeigt
946 ((SwTxtFtn
*)pAttr
)->GetStartNode()->GetIndex();
947 ULONG nEndIdx
= rNodes
[ nSttIdx
++ ]->EndOfSectionIndex();
949 for( ; nSttIdx
< nEndIdx
; ++nSttIdx
)
950 if( 0 != ( pCNd
= rNodes
[ nSttIdx
]->GetCntntNode() ))
954 if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR
& nInsMode
) )
956 // Wir muessen zuerst einfuegen, da sonst gleiche Indizes
957 // entstehen koennen und das Attribut im _SortArr_ am
958 // Dokument nicht eingetrage wird.
959 SwIndex
aNdIdx( this, *pAttr
->GetStart() );
960 Insert( GetCharOfTxtAttr(*pAttr
), aNdIdx
);
961 nInsMode
|= nsSetAttrMode::SETATTR_NOTXTATRCHR
;
964 // Wir tragen uns am FtnIdx-Array des Docs ein ...
965 SwTxtFtn
* pTxtFtn
= 0;
968 // eine alte Ftn wird umgehaengt (z.B. SplitNode)
969 for( USHORT n
= 0; n
< pDoc
->GetFtnIdxs().Count(); ++n
)
970 if( pAttr
== pDoc
->GetFtnIdxs()[n
] )
972 // neuen Index zuweisen, dafuer aus dem SortArray
973 // loeschen und neu eintragen
974 pTxtFtn
= pDoc
->GetFtnIdxs()[n
];
975 pDoc
->GetFtnIdxs().Remove( n
);
978 // wenn ueber Undo der StartNode gesetzt wurde, kann
979 // der Index noch gar nicht in der Verwaltung stehen !!
982 pTxtFtn
= (SwTxtFtn
*)pAttr
;
984 // fuers Update der Nummern und zum Sortieren
985 // muss der Node gesetzt sein.
986 ((SwTxtFtn
*)pAttr
)->ChgTxtNode( this );
988 // FussNote im Redline-Bereich NICHT ins FtnArray einfuegen!
989 if( StartOfSectionIndex() > rNodes
.GetEndOfRedlines().GetIndex() )
992 const BOOL bSuccess
=
994 pDoc
->GetFtnIdxs().Insert( pTxtFtn
);
996 ASSERT( bSuccess
, "FtnIdx nicht eingetragen." );
999 SwNodeIndex
aTmpIndex( *this );
1000 pDoc
->GetFtnIdxs().UpdateFtn( aTmpIndex
);
1001 ((SwTxtFtn
*)pAttr
)->SetSeqRefNo();
1005 case RES_TXTATR_FIELD
:
1007 // fuer HiddenParaFields Benachrichtigungsmechanismus
1009 if( RES_HIDDENPARAFLD
==
1010 pAttr
->GetFld().GetFld()->GetTyp()->Which() )
1016 // Fuer SwTxtHints ohne Endindex werden CH_TXTATR_..
1017 // eingefuegt, aStart muss danach um einen zurueckgesetzt werden.
1018 // Wenn wir im SwTxtNode::Copy stehen, so wurde das Zeichen bereits
1019 // mitkopiert. In solchem Fall ist SETATTR_NOTXTATRCHR angegeben worden.
1020 if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR
& nInsMode
) )
1022 SwIndex
aIdx( this, *pAttr
->GetStart() );
1023 Insert( GetCharOfTxtAttr(*pAttr
), aIdx
);
1027 ASSERT( *pAttr
->GetEnd() <= Len(), "EndIdx hinter Len!" );
1030 GetOrCreateSwpHints();
1032 // 4263: AttrInsert durch TextInsert => kein Adjust
1033 m_pSwpHints
->Insert( pAttr
, *this, nMode
);
1035 // 47375: In pSwpHints->Insert wird u.a. Merge gerufen und das Hints-Array
1036 // von ueberfluessigen Hints befreit, dies kann u.U. sogar der frisch
1037 // eingefuegte Hint pAttr sein, der dann zerstoert wird!!
1038 if ( USHRT_MAX
== m_pSwpHints
->GetPos( pAttr
) )
1044 SetCalcHiddenParaField();
1050 /*************************************************************************
1051 * SwTxtNode::Delete()
1052 *************************************************************************/
1054 void SwTxtNode::Delete( SwTxtAttr
*pAttr
, BOOL bThisOnly
)
1061 xub_StrLen
* pEndIdx
= pAttr
->GetEnd();
1064 // hat es kein Ende kann es nur das sein, was hier steht!
1065 // Unbedingt Copy-konstruieren!
1066 const SwIndex
aIdx( this, *pAttr
->GetStart() );
1071 // den MsgHint jetzt fuettern, weil gleich sind
1072 // Start und End weg.
1073 SwUpdateAttr
aHint( *pAttr
->GetStart(), *pEndIdx
, pAttr
->Which() );
1074 m_pSwpHints
->Delete( pAttr
);
1075 pAttr
->RemoveFromPool( GetDoc()->GetAttrPool() );
1077 SwModify::Modify( 0, &aHint
); // die Frames benachrichtigen
1079 TryDeleteSwpHints();
1084 Delete( pAttr
->Which(), *pAttr
->GetStart(), *pAttr
->GetAnyEnd() );
1087 /*************************************************************************
1088 * SwTxtNode::Delete()
1089 *************************************************************************/
1091 void SwTxtNode::Delete( USHORT nTxtWhich
, xub_StrLen nStt
, xub_StrLen nEnd
)
1096 const xub_StrLen
*pEndIdx
;
1097 const xub_StrLen
*pSttIdx
;
1100 for ( USHORT nPos
= 0; m_pSwpHints
&& nPos
< m_pSwpHints
->Count(); nPos
++ )
1102 pTxtHt
= m_pSwpHints
->GetTextHint( nPos
);
1103 const USHORT nWhich
= pTxtHt
->Which();
1104 if( nWhich
== nTxtWhich
&&
1105 *( pSttIdx
= pTxtHt
->GetStart()) == nStt
)
1107 if ( nWhich
== RES_CHRATR_HIDDEN
)
1108 SetCalcHiddenCharFlags();
1109 else if ( nWhich
== RES_TXTATR_CHARFMT
)
1111 // Check if character format contains hidden attribute:
1112 const SwCharFmt
* pFmt
= pTxtHt
->GetCharFmt().GetCharFmt();
1113 const SfxPoolItem
* pItem
;
1114 if ( SFX_ITEM_SET
== pFmt
->GetItemState( RES_CHRATR_HIDDEN
, TRUE
, &pItem
) )
1115 SetCalcHiddenCharFlags();
1117 // --> FME 2007-03-16 #i75430# Recalc hidden flags if necessary
1118 else if ( nWhich
== RES_TXTATR_AUTOFMT
)
1120 // Check if auto style contains hidden attribute:
1121 const SfxPoolItem
* pHiddenItem
= CharFmt::GetItem( *pTxtHt
, RES_CHRATR_HIDDEN
);
1123 SetCalcHiddenCharFlags();
1127 pEndIdx
= pTxtHt
->GetEnd();
1129 // Text-Attribute sind voellig dynamisch, so dass diese nur
1130 // mit ihrer Start-Position verglichen werden.
1133 // Unbedingt Copy-konstruieren!
1134 const SwIndex
aIdx( this, *pSttIdx
);
1138 else if( *pEndIdx
== nEnd
)
1140 // den MsgHint jetzt fuettern, weil gleich sind
1141 // Start und End weg.
1142 // Das CalcVisibleFlag bei HiddenParaFields entfaellt,
1143 // da dies das Feld im Dtor selbst erledigt.
1144 SwUpdateAttr
aHint( *pSttIdx
, *pEndIdx
, nTxtWhich
);
1145 m_pSwpHints
->DeleteAtPos( nPos
); // gefunden, loeschen,
1146 pTxtHt
->RemoveFromPool( GetDoc()->GetAttrPool() );
1148 SwModify::Modify( 0, &aHint
); // die Frames benachrichtigen
1153 TryDeleteSwpHints();
1156 /*************************************************************************
1157 * SwTxtNode::DelSoftHyph()
1158 *************************************************************************/
1160 void SwTxtNode::DelSoftHyph( const xub_StrLen nStt
, const xub_StrLen nEnd
)
1162 xub_StrLen nFndPos
= nStt
, nEndPos
= nEnd
;
1163 while( STRING_NOTFOUND
!=
1164 ( nFndPos
= m_Text
.Search( CHAR_SOFTHYPHEN
, nFndPos
)) &&
1167 const SwIndex
aIdx( this, nFndPos
);
1173 // setze diese Attribute am TextNode. Wird der gesamte Bereich umspannt,
1174 // dann setze sie nur im AutoAttrSet (SwCntntNode:: SetAttr)
1175 BOOL
SwTxtNode::SetAttr( const SfxItemSet
& rSet
, xub_StrLen nStt
,
1176 xub_StrLen nEnd
, USHORT nMode
)
1181 // teil die Sets auf (fuer Selektion in Nodes)
1182 const SfxItemSet
* pSet
= &rSet
;
1183 SfxItemSet
aTxtSet( *rSet
.GetPool(), RES_TXTATR_BEGIN
, RES_TXTATR_END
-1 );
1186 if ( !nStt
&& (nEnd
== m_Text
.Len()) &&
1187 !(nMode
& nsSetAttrMode::SETATTR_NOFORMATATTR
) )
1189 // sind am Node schon Zeichenvorlagen gesetzt, muss man diese Attribute
1190 // (rSet) immer als TextAttribute setzen, damit sie angezeigt werden.
1191 int bHasCharFmts
= FALSE
;
1194 for ( USHORT n
= 0; n
< m_pSwpHints
->Count(); ++n
)
1196 if ( (*m_pSwpHints
)[ n
]->IsCharFmtAttr() )
1198 bHasCharFmts
= TRUE
;
1206 aTxtSet
.Put( rSet
);
1207 // If there are any character attributes in rSet,
1208 // we want to set them at the paragraph:
1209 if( aTxtSet
.Count() != rSet
.Count() )
1211 BOOL bRet
= SetAttr( rSet
);
1212 if( !aTxtSet
.Count() )
1216 // check for auto style:
1217 const SfxPoolItem
* pItem
;
1218 const bool bAutoStyle
= SFX_ITEM_SET
== aTxtSet
.GetItemState( RES_TXTATR_AUTOFMT
, FALSE
, &pItem
);
1221 boost::shared_ptr
<SfxItemSet
> pAutoStyleSet
= static_cast<const SwFmtAutoFmt
*>(pItem
)->GetStyleHandle();
1222 BOOL bRet
= SetAttr( *pAutoStyleSet
);
1223 if( 1 == aTxtSet
.Count() )
1227 // Continue with the text attributes:
1232 GetOrCreateSwpHints();
1234 SfxItemSet
aCharSet( *rSet
.GetPool(), aCharAutoFmtSetRange
);
1236 USHORT nWhich
, nCount
= 0;
1238 SfxItemIter
aIter( *pSet
);
1239 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1243 if ( pItem
&& (reinterpret_cast<SfxPoolItem
*>(-1) != pItem
))
1245 nWhich
= pItem
->Which();
1246 if ( isCHRATR(nWhich
) || isTXTATR(nWhich
) || isUNKNOWNATR(nWhich
) )
1248 if ((RES_TXTATR_CHARFMT
== nWhich
) &&
1249 (GetDoc()->GetDfltCharFmt() ==
1250 static_cast<const SwFmtCharFmt
*>(pItem
)->GetCharFmt()))
1252 SwIndex
aIndex( this, nStt
);
1253 RstAttr( aIndex
, nEnd
- nStt
, RES_TXTATR_CHARFMT
, 0 );
1254 DontExpandFmt( aIndex
);
1258 if (isCHRATR(nWhich
) ||
1259 (RES_TXTATR_UNKNOWN_CONTAINER
== nWhich
))
1261 aCharSet
.Put( *pItem
);
1265 pNew
= MakeTxtAttr( *pItem
, nStt
, nEnd
);
1268 if ( nEnd
!= nStt
&& !pNew
->GetEnd() )
1271 "Attribut without end, but area marked");
1272 DestroyAttr( pNew
); // do not insert
1274 else if ( Insert( pNew
, nMode
) )
1283 if ( aIter
.IsAtEnd() )
1285 pItem
= aIter
.NextItem();
1288 if ( aCharSet
.Count() )
1290 SwTxtAttr
* pTmpNew
= MakeTxtAttr( aCharSet
, nStt
, nEnd
);
1291 if ( Insert( pTmpNew
, nMode
) )
1295 TryDeleteSwpHints();
1297 return nCount
? TRUE
: FALSE
;
1300 void lcl_MergeAttr( SfxItemSet
& rSet
, const SfxPoolItem
& rAttr
)
1302 if ( RES_TXTATR_AUTOFMT
== rAttr
.Which() )
1304 const SfxItemSet
* pCFSet
= CharFmt::GetItemSet( rAttr
);
1307 SfxWhichIter
aIter( *pCFSet
);
1308 USHORT nWhich
= aIter
.FirstWhich();
1311 if( ( nWhich
< RES_CHRATR_END
||
1312 RES_TXTATR_UNKNOWN_CONTAINER
== nWhich
) &&
1313 ( SFX_ITEM_SET
== pCFSet
->GetItemState( nWhich
, TRUE
) ) )
1314 rSet
.Put( pCFSet
->Get( nWhich
) );
1315 nWhich
= aIter
.NextWhich();
1322 void lcl_MergeAttr_ExpandChrFmt( SfxItemSet
& rSet
, const SfxPoolItem
& rAttr
)
1324 if( RES_TXTATR_CHARFMT
== rAttr
.Which() ||
1325 RES_TXTATR_INETFMT
== rAttr
.Which() ||
1326 RES_TXTATR_AUTOFMT
== rAttr
.Which() )
1328 const SfxItemSet
* pCFSet
= CharFmt::GetItemSet( rAttr
);
1332 SfxWhichIter
aIter( *pCFSet
);
1333 USHORT nWhich
= aIter
.FirstWhich();
1336 if( ( nWhich
< RES_CHRATR_END
||
1337 ( RES_TXTATR_AUTOFMT
== rAttr
.Which() && RES_TXTATR_UNKNOWN_CONTAINER
== nWhich
) ) &&
1338 ( SFX_ITEM_SET
== pCFSet
->GetItemState( nWhich
, TRUE
) ) )
1339 rSet
.Put( pCFSet
->Get( nWhich
) );
1340 nWhich
= aIter
.NextWhich();
1345 // aufnehmen als MergeWert (falls noch nicht gesetzt neu setzen!)
1347 /* wenn mehrere Attribute ueberlappen gewinnt der letze !!
1350 |------------| Font1
1353 |--| Abfragebereich: -> Gueltig ist Font2
1358 struct SwPoolItemEndPair
1361 const SfxPoolItem
* mpItem
;
1362 xub_StrLen mnEndPos
;
1364 SwPoolItemEndPair() : mpItem( 0 ), mnEndPos( 0 ) {};
1367 // --> OD 2008-01-16 #newlistlevelattrs#
1368 void lcl_MergeListLevelIndentAsLRSpaceItem( const SwTxtNode
& rTxtNode
,
1371 if ( rTxtNode
.AreListLevelIndentsApplicable() )
1373 const SwNumRule
* pRule
= rTxtNode
.GetNumRule();
1374 if ( pRule
&& rTxtNode
.GetActualListLevel() >= 0 )
1376 const SwNumFmt
& rFmt
= pRule
->Get(static_cast<USHORT
>(rTxtNode
.GetActualListLevel()));
1377 if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
)
1379 SvxLRSpaceItem
aLR( RES_LR_SPACE
);
1380 aLR
.SetTxtLeft( rFmt
.GetIndentAt() );
1381 aLR
.SetTxtFirstLineOfst( static_cast<short>(rFmt
.GetFirstLineIndent()) );
1388 // erfrage die Attribute vom TextNode ueber den Bereich
1389 // --> OD 2008-01-16 #newlistlevelattrs#
1390 BOOL
SwTxtNode::GetAttr( SfxItemSet
& rSet
, xub_StrLen nStt
, xub_StrLen nEnd
,
1391 BOOL bOnlyTxtAttr
, BOOL bGetFromChrFmt
,
1392 const bool bMergeIndentValuesOfNumRule
) const
1396 /* stelle erstmal fest, welche Text-Attribut in dem Bereich gueltig
1397 * sind. Dabei gibt es folgende Faelle:
1398 * UnEindeutig wenn: (wenn != Format-Attribut)
1399 * - das Attribut liegt vollstaendig im Bereich
1400 * - das Attributende liegt im Bereich
1401 * - der Attributanfang liegt im Bereich:
1402 * Eindeutig (im Set mergen):
1403 * - das Attrib umfasst den Bereich
1405 * das Attribut liegt ausserhalb des Bereiches
1408 void (*fnMergeAttr
)( SfxItemSet
&, const SfxPoolItem
& )
1409 = bGetFromChrFmt
? &lcl_MergeAttr_ExpandChrFmt
1412 // dann besorge mal die Auto-(Fmt)Attribute
1413 SfxItemSet
aFmtSet( *rSet
.GetPool(), rSet
.GetRanges() );
1416 SwCntntNode::GetAttr( aFmtSet
);
1417 // --> OD 2008-01-16 #newlistlevelattrs#
1418 if ( bMergeIndentValuesOfNumRule
)
1420 lcl_MergeListLevelIndentAsLRSpaceItem( *this, aFmtSet
);
1425 const USHORT nSize
= m_pSwpHints
->Count();
1427 xub_StrLen nAttrStart
;
1428 const xub_StrLen
* pAttrEnd
;
1430 if( nStt
== nEnd
) // kein Bereich:
1432 for( n
= 0; n
< nSize
; ++n
) //
1434 const SwTxtAttr
* pHt
= (*m_pSwpHints
)[n
];
1435 nAttrStart
= *pHt
->GetStart();
1436 if( nAttrStart
> nEnd
) // ueber den Bereich hinaus
1439 if( 0 == ( pAttrEnd
= pHt
->GetEnd() )) // nie Attribute ohne Ende
1442 if( ( nAttrStart
< nStt
&&
1443 ( pHt
->DontExpand() ? nStt
< *pAttrEnd
1444 : nStt
<= *pAttrEnd
)) ||
1445 ( nStt
== nAttrStart
&&
1446 ( nAttrStart
== *pAttrEnd
|| !nStt
)))
1447 (*fnMergeAttr
)( rSet
, pHt
->GetAttr() );
1450 else // es ist ein Bereich definiert
1452 // --> FME 2007-03-13 #i75299#
1453 std::vector
< SwPoolItemEndPair
>* pAttrArr
= 0;
1456 const USHORT coArrSz
= static_cast<USHORT
>(RES_TXTATR_WITHEND_END
) -
1457 static_cast<USHORT
>(RES_CHRATR_BEGIN
) +
1458 static_cast<USHORT
>(RES_UNKNOWNATR_END
) -
1459 static_cast<USHORT
>(RES_UNKNOWNATR_BEGIN
);
1461 for( n
= 0; n
< nSize
; ++n
)
1463 const SwTxtAttr
* pHt
= (*m_pSwpHints
)[n
];
1464 nAttrStart
= *pHt
->GetStart();
1465 if( nAttrStart
> nEnd
) // ueber den Bereich hinaus
1468 if( 0 == ( pAttrEnd
= pHt
->GetEnd() )) // nie Attribute ohne Ende
1471 BOOL bChkInvalid
= FALSE
;
1472 if( nAttrStart
<= nStt
) // vor oder genau Start
1474 if( *pAttrEnd
<= nStt
) // liegt davor
1477 if( nEnd
<= *pAttrEnd
) // hinter oder genau Ende
1478 (*fnMergeAttr
)( aFmtSet
, pHt
->GetAttr() );
1480 // else if( pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
1484 else if( nAttrStart
< nEnd
// reicht in den Bereich
1485 )// && pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
1491 SfxItemIter
* pItemIter
= 0;
1492 const SfxPoolItem
* pItem
= 0;
1494 if ( RES_TXTATR_AUTOFMT
== pHt
->Which() )
1496 const SfxItemSet
* pAutoSet
= CharFmt::GetItemSet( pHt
->GetAttr() );
1499 pItemIter
= new SfxItemIter( *pAutoSet
);
1500 pItem
= pItemIter
->GetCurItem();
1504 pItem
= &pHt
->GetAttr();
1506 const USHORT nHintEnd
= *pAttrEnd
;
1510 const USHORT nHintWhich
= pItem
->Which();
1513 pAttrArr
= new std::vector
< SwPoolItemEndPair
>( coArrSz
);
1515 std::vector
< SwPoolItemEndPair
>::iterator pPrev
= pAttrArr
->begin();
1516 if (isCHRATR(nHintWhich
) ||
1517 isTXTATR_WITHEND(nHintWhich
))
1519 pPrev
+= nHintWhich
- RES_CHRATR_BEGIN
;
1521 else if (isUNKNOWNATR(nHintWhich
))
1523 pPrev
+= nHintWhich
- RES_UNKNOWNATR_BEGIN
+ (
1524 static_cast< USHORT
>(RES_TXTATR_WITHEND_END
) -
1525 static_cast< USHORT
>(RES_CHRATR_BEGIN
) );
1529 pPrev
= pAttrArr
->end();
1532 #if OSL_DEBUG_LEVEL > 1
1533 SwPoolItemEndPair aTmp
= *pPrev
;
1536 if( pPrev
!= pAttrArr
->end() )
1538 if( !pPrev
->mpItem
)
1540 if ( bOnlyTxtAttr
|| *pItem
!= aFmtSet
.Get( nHintWhich
) )
1542 if( nAttrStart
> nStt
)
1544 rSet
.InvalidateItem( nHintWhich
);
1545 pPrev
->mpItem
= (SfxPoolItem
*)-1;
1549 pPrev
->mpItem
= pItem
;
1550 pPrev
->mnEndPos
= nHintEnd
;
1554 else if( (SfxPoolItem
*)-1 != pPrev
->mpItem
)
1556 if( pPrev
->mnEndPos
== nAttrStart
&&
1557 *pPrev
->mpItem
== *pItem
)
1559 pPrev
->mpItem
= pItem
;
1560 pPrev
->mnEndPos
= nHintEnd
;
1564 rSet
.InvalidateItem( nHintWhich
);
1565 pPrev
->mpItem
= (SfxPoolItem
*)-1;
1570 pItem
= ( pItemIter
&& !pItemIter
->IsAtEnd() ) ? pItemIter
->NextItem() : 0;
1579 for( n
= 0; n
< coArrSz
; ++n
)
1581 const SwPoolItemEndPair
& rItemPair
= (*pAttrArr
)[ n
];
1582 if( (0 != rItemPair
.mpItem
) && ((SfxPoolItem
*)-1 != rItemPair
.mpItem
) )
1585 if( n
< static_cast<USHORT
>( static_cast<USHORT
>(RES_TXTATR_WITHEND_END
) -
1586 static_cast<USHORT
>(RES_CHRATR_BEGIN
) ) )
1587 nWh
= static_cast<USHORT
>(n
+ RES_CHRATR_BEGIN
);
1589 nWh
= n
- static_cast<USHORT
>( static_cast<USHORT
>(RES_TXTATR_WITHEND_END
) -
1590 static_cast<USHORT
>(RES_CHRATR_BEGIN
) +
1591 static_cast<USHORT
>(RES_UNKNOWNATR_BEGIN
) );
1593 if( nEnd
<= rItemPair
.mnEndPos
) // hinter oder genau Ende
1595 if( *rItemPair
.mpItem
!= aFmtSet
.Get( nWh
) )
1596 (*fnMergeAttr
)( rSet
, *rItemPair
.mpItem
);
1600 rSet
.InvalidateItem( nWh
);
1607 if( aFmtSet
.Count() )
1609 // aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind
1610 aFmtSet
.Differentiate( rSet
);
1611 // jetzt alle zusammen "mergen"
1612 rSet
.Put( aFmtSet
);
1615 else if( !bOnlyTxtAttr
)
1617 // dann besorge mal die Auto-(Fmt)Attribute
1618 SwCntntNode::GetAttr( rSet
);
1619 // --> OD 2008-01-16 #newlistlevelattrs#
1620 if ( bMergeIndentValuesOfNumRule
)
1622 lcl_MergeListLevelIndentAsLRSpaceItem( *this, rSet
);
1627 return rSet
.Count() ? TRUE
: FALSE
;
1630 int lcl_IsNewAttrInSet( const SwpHints
& rHints
, const SfxPoolItem
& rItem
,
1631 const xub_StrLen nEnd
)
1634 for( USHORT i
= 0; i
< rHints
.Count(); ++i
)
1636 const SwTxtAttr
*pOther
= rHints
[ i
];
1637 if( *pOther
->GetStart() )
1640 if( pOther
->GetEnd() &&
1641 *pOther
->GetEnd() == nEnd
&&
1642 ( pOther
->IsCharFmtAttr() || pOther
->Which() == rItem
.Which() ) )
1651 void SwTxtNode::FmtToTxtAttr( SwTxtNode
* pNd
)
1653 SfxItemSet
aThisSet( GetDoc()->GetAttrPool(), aCharFmtSetRange
);
1654 if( HasSwAttrSet() && GetpSwAttrSet()->Count() )
1655 aThisSet
.Put( *GetpSwAttrSet() );
1657 GetOrCreateSwpHints();
1661 if( aThisSet
.Count() )
1663 SfxItemIter
aIter( aThisSet
);
1664 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1665 std::vector
<USHORT
> aClearWhichIds
;
1669 if (lcl_IsNewAttrInSet( *m_pSwpHints
, *pItem
, GetTxt().Len() ))
1671 m_pSwpHints
->SwpHintsArray::Insert(
1672 MakeTxtAttr( *pItem
, 0, GetTxt().Len() ) );
1673 aClearWhichIds
.push_back( pItem
->Which() );
1676 if( aIter
.IsAtEnd() )
1678 pItem
= aIter
.NextItem();
1681 ClearItemsFromAttrSet( aClearWhichIds
);
1686 SfxItemSet
aNdSet( pNd
->GetDoc()->GetAttrPool(), aCharFmtSetRange
);
1687 if( pNd
->HasSwAttrSet() && pNd
->GetpSwAttrSet()->Count() )
1688 aNdSet
.Put( *pNd
->GetpSwAttrSet() );
1690 pNd
->GetOrCreateSwpHints();
1692 if( aThisSet
.Count() )
1694 SfxItemIter
aIter( aThisSet
);
1695 const SfxPoolItem
* pItem
= aIter
.GetCurItem(), *pNdItem
;
1696 std::vector
<USHORT
> aClearWhichIds
;
1700 if( ( SFX_ITEM_SET
!= aNdSet
.GetItemState( pItem
->Which(), FALSE
,
1701 &pNdItem
) || *pItem
!= *pNdItem
) &&
1702 lcl_IsNewAttrInSet( *m_pSwpHints
, *pItem
, GetTxt().Len() ) )
1704 m_pSwpHints
->SwpHintsArray::Insert(
1705 MakeTxtAttr( *pItem
, 0, GetTxt().Len() ) );
1706 aClearWhichIds
.push_back( pItem
->Which() );
1708 aNdSet
.ClearItem( pItem
->Which() );
1710 if( aIter
.IsAtEnd() )
1712 pItem
= aIter
.NextItem();
1714 ClearItemsFromAttrSet( aClearWhichIds
);
1717 if( aNdSet
.Count() )
1719 SfxItemIter
aIter( aNdSet
);
1720 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
1721 std::vector
<USHORT
> aClearWhichIds
;
1725 if ( lcl_IsNewAttrInSet( *pNd
->m_pSwpHints
, *pItem
,
1726 pNd
->GetTxt().Len() ) )
1728 pNd
->m_pSwpHints
->SwpHintsArray::Insert(
1729 pNd
->MakeTxtAttr( *pItem
, 0, pNd
->GetTxt().Len() ) );
1731 aClearWhichIds
.push_back( pItem
->Which() );
1733 if( aIter
.IsAtEnd() )
1735 pItem
= aIter
.NextItem();
1738 pNd
->ClearItemsFromAttrSet( aClearWhichIds
);
1739 SwFmtChg
aTmp1( pNd
->GetFmtColl() );
1740 pNd
->SwModify::Modify( &aTmp1
, &aTmp1
);
1744 SetCalcHiddenCharFlags();
1746 pNd
->TryDeleteSwpHints();
1749 /*************************************************************************
1750 * SwpHints::CalcFlags()
1751 *************************************************************************/
1753 void SwpHints::CalcFlags()
1755 m_bDDEFields
= m_bFootnote
= false;
1756 const USHORT nSize
= Count();
1757 const SwTxtAttr
* pAttr
;
1758 for( USHORT nPos
= 0; nPos
< nSize
; ++nPos
)
1760 switch( ( pAttr
= (*this)[ nPos
])->Which() )
1762 case RES_TXTATR_FTN
:
1767 case RES_TXTATR_FIELD
:
1769 const SwField
* pFld
= pAttr
->GetFld().GetFld();
1770 if( RES_DDEFLD
== pFld
->GetTyp()->Which() )
1772 m_bDDEFields
= true;
1782 /*************************************************************************
1783 * SwpHints::CalcVisibleFlag()
1784 *************************************************************************/
1786 bool SwpHints::CalcHiddenParaField()
1788 m_bCalcHiddenParaField
= false;
1789 bool bOldHasHiddenParaField
= m_bHasHiddenParaField
;
1790 bool bNewHasHiddenParaField
= false;
1791 const USHORT nSize
= Count();
1792 const SwTxtAttr
*pTxtHt
;
1794 for( USHORT nPos
= 0; nPos
< nSize
; ++nPos
)
1796 pTxtHt
= (*this)[ nPos
];
1797 const USHORT nWhich
= pTxtHt
->Which();
1799 if( RES_TXTATR_FIELD
== nWhich
)
1801 const SwFmtFld
& rFld
= pTxtHt
->GetFld();
1802 if( RES_HIDDENPARAFLD
== rFld
.GetFld()->GetTyp()->Which() )
1804 if( !((SwHiddenParaField
*)rFld
.GetFld())->IsHidden() )
1806 SetHiddenParaField(false);
1807 return bOldHasHiddenParaField
!= bNewHasHiddenParaField
;
1811 bNewHasHiddenParaField
= true;
1816 SetHiddenParaField( bNewHasHiddenParaField
);
1817 return bOldHasHiddenParaField
!= bNewHasHiddenParaField
;
1821 /*************************************************************************
1822 * SwpHints::NoteInHistory()
1823 *************************************************************************/
1825 void SwpHints::NoteInHistory( SwTxtAttr
*pAttr
, const bool bNew
)
1827 if ( m_pHistory
) { m_pHistory
->AddHint( pAttr
, bNew
); }
1830 /*************************************************************************
1831 * SwpHints::MergePortions( )
1832 *************************************************************************/
1834 bool SwpHints::MergePortions( SwTxtNode
& rNode
)
1839 // sort before merging
1840 SwpHintsArray::Resort();
1843 typedef std::multimap
< int, SwTxtAttr
* > PortionMap
;
1844 PortionMap aPortionMap
;
1845 xub_StrLen nLastPorStart
= STRING_LEN
;
1849 // get portions by start position:
1850 for ( i
= 0; i
< Count(); ++i
)
1852 SwTxtAttr
*pHt
= GetTextHint( i
);
1853 if ( RES_TXTATR_CHARFMT
!= pHt
->Which() &&
1854 RES_TXTATR_AUTOFMT
!= pHt
->Which() )
1856 //RES_TXTATR_INETFMT != pHt->Which() )
1859 const xub_StrLen nPorStart
= *pHt
->GetStart();
1860 if ( nPorStart
!= nLastPorStart
&& nLastPorStart
!= STRING_LEN
)
1862 nLastPorStart
= nPorStart
;
1863 aPortionMap
.insert( std::pair
< const int, SwTxtAttr
* >( nKey
, pHt
) );
1866 // check if portion i can be merged with portion i+1:
1871 std::pair
< PortionMap::iterator
, PortionMap::iterator
> aRange1
= aPortionMap
.equal_range( i
);
1872 std::pair
< PortionMap::iterator
, PortionMap::iterator
> aRange2
= aPortionMap
.equal_range( j
);
1873 PortionMap::iterator aIter1
= aRange1
.first
;
1874 PortionMap::iterator aIter2
= aRange2
.first
;
1877 const USHORT nAttributesInPor1
= static_cast<USHORT
>(std::distance( aRange1
.first
, aRange1
.second
));
1878 const USHORT nAttributesInPor2
= static_cast<USHORT
>(std::distance( aRange2
.first
, aRange2
.second
));
1880 if ( nAttributesInPor1
== nAttributesInPor2
&& nAttributesInPor1
!= 0 )
1882 while ( aIter1
!= aRange1
.second
)
1884 const SwTxtAttr
* p1
= (*aIter1
).second
;
1885 const SwTxtAttr
* p2
= (*aIter2
).second
;
1886 if ( *p1
->GetEnd() < *p2
->GetStart() || p1
->Which() != p2
->Which() || !(*p1
== *p2
) )
1902 // erase all elements with key i + 1
1903 xub_StrLen nNewPortionEnd
= 0;
1904 for ( aIter2
= aRange2
.first
; aIter2
!= aRange2
.second
; ++aIter2
)
1906 SwTxtAttr
* p2
= (*aIter2
).second
;
1907 nNewPortionEnd
= *p2
->GetEnd();
1909 const USHORT nCountBeforeDelete
= Count();
1912 // robust: check if deletion actually took place before destroying attribute:
1913 if ( Count() < nCountBeforeDelete
)
1914 rNode
.DestroyAttr( p2
);
1916 aPortionMap
.erase( aRange2
.first
, aRange2
.second
);
1919 // change all attributes with key i
1920 aRange1
= aPortionMap
.equal_range( i
);
1921 for ( aIter1
= aRange1
.first
; aIter1
!= aRange1
.second
; ++aIter1
)
1923 SwTxtAttr
* p1
= (*aIter1
).second
;
1924 NoteInHistory( p1
);
1925 *p1
->GetEnd() = nNewPortionEnd
;
1926 NoteInHistory( p1
, true );
1939 SwpHintsArray::Resort();
1945 // check if there is already a character format and adjust the sort numbers
1946 void lcl_CheckSortNumber( const SwpHints
& rHints
, SwTxtCharFmt
& rNewCharFmt
)
1948 const xub_StrLen nHtStart
= *rNewCharFmt
.GetStart();
1949 const xub_StrLen nHtEnd
= *rNewCharFmt
.GetEnd();
1950 USHORT nSortNumber
= 0;
1952 for ( USHORT i
= 0; i
< rHints
.Count(); ++i
)
1954 const SwTxtAttr
* pOtherHt
= rHints
[i
];
1956 const xub_StrLen nOtherStart
= *pOtherHt
->GetStart();
1958 if ( nOtherStart
> nHtStart
)
1961 if ( RES_TXTATR_CHARFMT
== pOtherHt
->Which() )
1963 const xub_StrLen nOtherEnd
= *pOtherHt
->GetEnd();
1965 if ( nOtherStart
== nHtStart
&& nOtherEnd
== nHtEnd
)
1967 const USHORT nOtherSortNum
= static_cast<const SwTxtCharFmt
*>(pOtherHt
)->GetSortNumber();
1968 nSortNumber
= nOtherSortNum
+ 1;
1973 if ( nSortNumber
> 0 )
1974 rNewCharFmt
.SetSortNumber( nSortNumber
);
1977 /*************************************************************************
1978 * SwpHints::Insert()
1979 *************************************************************************/
1982 * Insert: Der neue Hint wird immer eingefuegt. Wenn dabei ein
1983 * ueberlappender oder gleicher Hintbereich mit gleichem Attribut
1984 * und Wert gefunden, wird der neue Hint entsprechend veraendert
1985 * und der alte herausgenommen (und zerstoert:
1986 * SwpHints::Destroy()).
1989 void SwpHints::Insert( SwTxtAttr
* pHint
, SwTxtNode
&rNode
, USHORT nMode
)
1991 // Irgendwann ist immer Schluss
1992 if( USHRT_MAX
== Count() )
1995 // Felder bilden eine Ausnahme:
1996 // 1) Sie koennen nie ueberlappen
1997 // 2) Wenn zwei Felder genau aneinander liegen,
1998 // sollen sie nicht zu einem verschmolzen werden.
1999 // Wir koennen also auf die while-Schleife verzichten
2001 xub_StrLen
*pHtEnd
= pHint
->GetEnd();
2002 USHORT nWhich
= pHint
->Which();
2006 case RES_TXTATR_CHARFMT
:
2008 // Check if character format contains hidden attribute:
2009 const SwCharFmt
* pFmt
= pHint
->GetCharFmt().GetCharFmt();
2010 const SfxPoolItem
* pItem
;
2011 if ( SFX_ITEM_SET
== pFmt
->GetItemState( RES_CHRATR_HIDDEN
, TRUE
, &pItem
) )
2012 rNode
.SetCalcHiddenCharFlags();
2014 ((SwTxtCharFmt
*)pHint
)->ChgTxtNode( &rNode
);
2017 // --> FME 2007-03-16 #i75430# Recalc hidden flags if necessary
2018 case RES_TXTATR_AUTOFMT
:
2020 // Check if auto style contains hidden attribute:
2021 const SfxPoolItem
* pHiddenItem
= CharFmt::GetItem( *pHint
, RES_CHRATR_HIDDEN
);
2023 rNode
.SetCalcHiddenCharFlags();
2027 case RES_TXTATR_INETFMT
:
2029 ((SwTxtINetFmt
*)pHint
)->ChgTxtNode( &rNode
);
2030 SwCharFmt
* pFmt
= rNode
.GetDoc()->GetCharFmtFromPool( RES_POOLCHR_INET_NORMAL
);
2031 pFmt
->Add( (SwTxtINetFmt
*)pHint
);
2034 case RES_TXTATR_FIELD
:
2036 BOOL bDelFirst
= 0 != ((SwTxtFld
*)pHint
)->GetpTxtNode();
2037 ((SwTxtFld
*)pHint
)->ChgTxtNode( &rNode
);
2038 SwDoc
* pDoc
= rNode
.GetDoc();
2039 const SwField
* pFld
= ((SwTxtFld
*)pHint
)->GetFld().GetFld();
2041 if( !pDoc
->IsNewFldLst() )
2043 // was fuer ein Feld ist es denn ??
2044 // bestimmte Felder mussen am Doc das Calculations-Flag updaten
2045 switch( pFld
->GetTyp()->Which() )
2049 case RES_HIDDENPARAFLD
:
2050 case RES_HIDDENTXTFLD
:
2051 case RES_DBNUMSETFLD
:
2052 case RES_DBNEXTSETFLD
:
2055 pDoc
->InsDelFldInFldLst( FALSE
, *(SwTxtFld
*)pHint
);
2056 if( rNode
.GetNodes().IsDocNodes() )
2057 pDoc
->InsDelFldInFldLst( TRUE
, *(SwTxtFld
*)pHint
);
2061 if( rNode
.GetNodes().IsDocNodes() )
2062 ((SwDDEFieldType
*)pFld
->GetTyp())->IncRefCnt();
2067 // gehts ins normale Nodes-Array?
2068 if( rNode
.GetNodes().IsDocNodes() )
2070 BOOL bInsFldType
= FALSE
;
2071 switch( pFld
->GetTyp()->Which() )
2074 bInsFldType
= ((SwSetExpFieldType
*)pFld
->GetTyp())->IsDeleted();
2075 if( nsSwGetSetExpType::GSE_SEQ
& ((SwSetExpFieldType
*)pFld
->GetTyp())->GetType() )
2077 // bevor die ReferenzNummer gesetzt wird, sollte
2078 // das Feld am richtigen FeldTypen haengen!
2079 SwSetExpFieldType
* pFldType
= (SwSetExpFieldType
*)
2080 pDoc
->InsertFldType( *pFld
->GetTyp() );
2081 if( pFldType
!= pFld
->GetTyp() )
2083 SwFmtFld
* pFmtFld
= (SwFmtFld
*)&((SwTxtFld
*)pHint
)
2085 pFldType
->Add( pFmtFld
); // ummelden
2086 pFmtFld
->GetFld()->ChgTyp( pFldType
);
2088 pFldType
->SetSeqRefNo( *(SwSetExpField
*)pFld
);
2092 bInsFldType
= ((SwUserFieldType
*)pFld
->GetTyp())->IsDeleted();
2096 if( pDoc
->IsNewFldLst() )
2097 ((SwDDEFieldType
*)pFld
->GetTyp())->IncRefCnt();
2098 bInsFldType
= ((SwDDEFieldType
*)pFld
->GetTyp())->IsDeleted();
2102 if ( pDoc
->GetDocShell() )
2103 pDoc
->GetDocShell()->Broadcast( SwFmtFldHint( &((SwTxtFld
*)pHint
)->GetFld(), SWFMTFLD_INSERTED
) );
2107 pDoc
->InsDeletedFldType( *pFld
->GetTyp() );
2111 case RES_TXTATR_FTN
:
2112 ((SwTxtFtn
*)pHint
)->ChgTxtNode( &rNode
);
2114 case RES_TXTATR_REFMARK
:
2115 ((SwTxtRefMark
*)pHint
)->ChgTxtNode( &rNode
);
2116 if( rNode
.GetNodes().IsDocNodes() )
2118 // search for a reference with the same name
2120 xub_StrLen
*pTmpHtEnd
, *pTmpHintEnd
;
2121 for( USHORT n
= 0, nEnd
= Count(); n
< nEnd
; ++n
)
2123 if (RES_TXTATR_REFMARK
== (pTmpHt
= GetTextHint(n
))->Which() &&
2124 pHint
->GetAttr() == pTmpHt
->GetAttr() &&
2125 0 != ( pTmpHtEnd
= pTmpHt
->GetEnd() ) &&
2126 0 != ( pTmpHintEnd
= pHint
->GetEnd() ) )
2128 SwComparePosition eCmp
= ::ComparePosition(
2129 *pTmpHt
->GetStart(), *pTmpHtEnd
,
2130 *pHint
->GetStart(), *pTmpHintEnd
);
2131 BOOL bDelOld
= TRUE
, bChgStart
= FALSE
, bChgEnd
= FALSE
;
2135 case POS_BEHIND
: bDelOld
= FALSE
; break;
2137 case POS_OUTSIDE
: bChgStart
= bChgEnd
= TRUE
; break;
2139 case POS_COLLIDE_END
:
2140 case POS_OVERLAP_BEFORE
: bChgStart
= TRUE
; break;
2141 case POS_COLLIDE_START
:
2142 case POS_OVERLAP_BEHIND
: bChgEnd
= TRUE
; break;
2147 *pHint
->GetStart() = *pTmpHt
->GetStart();
2149 *pTmpHintEnd
= *pTmpHtEnd
;
2153 NoteInHistory( pTmpHt
);
2154 rNode
.DestroyAttr( Cut( n
-- ) );
2161 case RES_TXTATR_TOXMARK
:
2162 ((SwTxtTOXMark
*)pHint
)->ChgTxtNode( &rNode
);
2165 case RES_TXTATR_CJK_RUBY
:
2167 ((SwTxtRuby
*)pHint
)->ChgTxtNode( &rNode
);
2168 SwCharFmt
* pFmt
= rNode
.GetDoc()->GetCharFmtFromPool(
2169 RES_POOLCHR_RUBYTEXT
);
2170 pFmt
->Add( (SwTxtRuby
*)pHint
);
2174 case RES_CHRATR_HIDDEN
:
2175 rNode
.SetCalcHiddenCharFlags();
2179 if( nsSetAttrMode::SETATTR_DONTEXPAND
& nMode
)
2180 pHint
->SetDontExpand( TRUE
);
2182 // SwTxtAttrs ohne Ende werden sonderbehandelt:
2183 // Sie werden natuerlich in das Array insertet, aber sie werden nicht
2184 // in die pPrev/Next/On/Off-Verkettung aufgenommen.
2185 // Der Formatierer erkennt diese TxtHints an dem CH_TXTATR_.. im Text !
2186 xub_StrLen nHtStart
= *pHint
->GetStart();
2189 SwpHintsArray::Insert( pHint
);
2192 if( !rNode
.GetDoc()->IsInReading() )
2195 // ... und die Abhaengigen benachrichtigen
2196 if ( rNode
.GetDepends() )
2198 SwUpdateAttr
aHint( nHtStart
, nHtStart
, nWhich
);
2199 rNode
.Modify( 0, &aHint
);
2204 // ----------------------------------------------------------------
2205 // Ab hier gibt es nur noch pHint mit einem EndIdx !!!
2207 if( *pHtEnd
< nHtStart
)
2209 ASSERT( *pHtEnd
>= nHtStart
,
2210 "+SwpHints::Insert: invalid hint, end < start" );
2212 // Wir drehen den Quatsch einfach um:
2213 *pHint
->GetStart() = *pHtEnd
;
2215 nHtStart
= *pHint
->GetStart();
2218 // I need this value later on for notification but the pointer may become invalid
2219 const xub_StrLen nHintEnd
= *pHtEnd
;
2220 const bool bNoHintAdjustMode
= (nsSetAttrMode::SETATTR_NOHINTADJUST
& nMode
);
2222 // Currently REFMARK and TOXMARK have OverlapAllowed set to true.
2223 // These attributes may be inserted directly.
2224 // Also attributes without length may be inserted directly.
2225 // SETATTR_NOHINTADJUST is set e.g., during undo.
2226 // Portion building in not necessary during XML import.
2227 if ( !bNoHintAdjustMode
&&
2228 !pHint
->IsOverlapAllowedAttr() &&
2229 !rNode
.GetDoc()->IsInXMLImport() &&
2230 ( RES_TXTATR_AUTOFMT
== nWhich
||
2231 RES_TXTATR_INETFMT
== nWhich
||
2232 RES_TXTATR_CHARFMT
== nWhich
||
2233 RES_TXTATR_CJK_RUBY
== nWhich
) )
2235 ASSERT( nWhich
!= RES_TXTATR_AUTOFMT
||
2236 static_cast<const SwFmtAutoFmt
&>(pHint
->GetAttr()).GetStyleHandle()->GetPool() ==
2237 &rNode
.GetDoc()->GetAttrPool(),
2238 "AUTOSTYLES - Pool mismatch" )
2240 BuildPortions( rNode
, *pHint
, nMode
);
2242 if ( nHtStart
< nHintEnd
) // skip merging for 0-length attributes
2243 MergePortions( rNode
);
2247 // There may be more than one character style at the current position.
2248 // Take care of the sort number.
2249 // Special case ruby portion: During import, the ruby attribute is set
2251 // Special case hyperlink: During import, the ruby attribute is set
2253 // FME 2007-11-08 #i82989# in NOHINTADJUST mode, we want to insert
2254 // character attributes directly
2255 if ( ( RES_TXTATR_CHARFMT
== nWhich
&& !bNoHintAdjustMode
) ||
2256 RES_TXTATR_CJK_RUBY
== nWhich
||
2257 RES_TXTATR_INETFMT
== nWhich
)
2258 BuildPortions( rNode
, *pHint
, nMode
);
2261 // --> FME 2007-11-08 #i82989# Check sort numbers in NoHintAdjustMode
2262 if ( RES_TXTATR_CHARFMT
== nWhich
)
2263 lcl_CheckSortNumber( *this, *static_cast<SwTxtCharFmt
*>(pHint
) );
2266 SwpHintsArray::Insert( pHint
);
2267 NoteInHistory( pHint
, true );
2271 // ... und die Abhaengigen benachrichtigen
2272 if ( rNode
.GetDepends() )
2274 SwUpdateAttr
aHint( nHtStart
, nHtStart
== nHintEnd
? nHintEnd
+ 1 : nHintEnd
, nWhich
);
2275 rNode
.Modify( 0, &aHint
);
2279 if( !bNoHintAdjustMode
&& !rNode
.GetDoc()->IsInReading() )
2286 /*************************************************************************
2287 * SwpHints::DeleteAtPos()
2288 *************************************************************************/
2290 void SwpHints::DeleteAtPos( const USHORT nPos
)
2292 SwTxtAttr
*pHint
= GetTextHint(nPos
);
2293 // ChainDelete( pHint );
2294 NoteInHistory( pHint
);
2295 SwpHintsArray::DeleteAtPos( nPos
);
2297 if( RES_TXTATR_FIELD
== pHint
->Which() )
2299 SwFieldType
* pFldTyp
= ((SwTxtFld
*)pHint
)->GetFld().GetFld()->GetTyp();
2300 if( RES_DDEFLD
== pFldTyp
->Which() )
2302 const SwTxtNode
* pNd
= ((SwTxtFld
*)pHint
)->GetpTxtNode();
2303 if( pNd
&& pNd
->GetNodes().IsDocNodes() )
2304 ((SwDDEFieldType
*)pFldTyp
)->DecRefCnt();
2305 ((SwTxtFld
*)pHint
)->ChgTxtNode( 0 );
2307 else if( RES_POSTITFLD
== pFldTyp
->Which() )
2309 const_cast<SwFmtFld
&>(((SwTxtFld
*)pHint
)->GetFld()).Broadcast( SwFmtFldHint( &((SwTxtFld
*)pHint
)->GetFld(), SWFMTFLD_REMOVED
) );
2311 else if ( m_bHasHiddenParaField
&&
2312 RES_HIDDENPARAFLD
== pFldTyp
->Which() )
2314 m_bCalcHiddenParaField
= true;
2322 // Ist der Hint schon bekannt, dann suche die Position und loesche ihn.
2323 // Ist er nicht im Array, so gibt es ein ASSERT !!
2325 void SwpHints::Delete( SwTxtAttr
* pTxtHt
)
2327 // Attr 2.0: SwpHintsArr::Delete( pTxtHt );
2328 const USHORT nPos
= GetStartOf( pTxtHt
);
2329 ASSERT( USHRT_MAX
!= nPos
, "Attribut nicht im Attribut-Array!" );
2330 if( USHRT_MAX
!= nPos
)
2331 DeleteAtPos( nPos
);
2334 void SwTxtNode::ClearSwpHintsArr( bool bDelFields
)
2339 while ( nPos
< m_pSwpHints
->Count() )
2341 SwTxtAttr
* pDel
= m_pSwpHints
->GetTextHint( nPos
);
2344 switch( pDel
->Which() )
2346 case RES_TXTATR_FLYCNT
:
2347 case RES_TXTATR_FTN
:
2350 case RES_TXTATR_FIELD
:
2351 case RES_TXTATR_HARDBLANK
:
2361 m_pSwpHints
->SwpHintsArray::DeleteAtPos( nPos
);
2362 DestroyAttr( pDel
);
2370 USHORT
SwTxtNode::GetLang( const xub_StrLen nBegin
, const xub_StrLen nLen
,
2371 USHORT nScript
) const
2373 USHORT nRet
= LANGUAGE_DONTKNOW
;
2377 nScript
= pBreakIt
->GetRealScriptOfText( m_Text
, nBegin
);
2380 // --> FME 2008-09-29 #i91465# hennerdrewes: Consider nScript if pSwpHints == 0
2381 const USHORT nWhichId
= GetWhichOfScript( RES_CHRATR_LANGUAGE
, nScript
);
2386 const xub_StrLen nEnd
= nBegin
+ nLen
;
2387 for ( USHORT i
= 0, nSize
= m_pSwpHints
->Count(); i
< nSize
; ++i
)
2389 // ist der Attribut-Anfang schon groesser als der Idx ?
2390 const SwTxtAttr
*pHt
= m_pSwpHints
->operator[](i
);
2391 const xub_StrLen nAttrStart
= *pHt
->GetStart();
2392 if( nEnd
< nAttrStart
)
2395 const USHORT nWhich
= pHt
->Which();
2397 if( nWhichId
== nWhich
||
2398 ( ( pHt
->IsCharFmtAttr() || RES_TXTATR_AUTOFMT
== nWhich
) && CharFmt::IsItemIncluded( nWhichId
, pHt
) ) )
2400 const xub_StrLen
*pEndIdx
= pHt
->GetEnd();
2401 // Ueberlappt das Attribut den Bereich?
2404 nLen
? ( nAttrStart
< nEnd
&& nBegin
< *pEndIdx
)
2405 : (( nAttrStart
< nBegin
&&
2406 ( pHt
->DontExpand() ? nBegin
< *pEndIdx
2407 : nBegin
<= *pEndIdx
)) ||
2408 ( nBegin
== nAttrStart
&&
2409 ( nAttrStart
== *pEndIdx
|| !nBegin
))) )
2411 const SfxPoolItem
* pItem
= CharFmt::GetItem( *pHt
, nWhichId
);
2412 USHORT nLng
= ((SvxLanguageItem
*)pItem
)->GetLanguage();
2414 // Umfasst das Attribut den Bereich komplett?
2415 if( nAttrStart
<= nBegin
&& nEnd
<= *pEndIdx
)
2417 else if( LANGUAGE_DONTKNOW
== nRet
)
2418 nRet
= nLng
; // partielle Ueberlappung, der 1. gewinnt
2423 if( LANGUAGE_DONTKNOW
== nRet
)
2425 nRet
= ((SvxLanguageItem
&)GetSwAttrSet().Get( nWhichId
)).GetLanguage();
2426 if( LANGUAGE_DONTKNOW
== nRet
)
2427 nRet
= static_cast<USHORT
>(GetAppLanguage());
2433 sal_Unicode
GetCharOfTxtAttr( const SwTxtAttr
& rAttr
)
2435 sal_Unicode cRet
= CH_TXTATR_BREAKWORD
;
2436 switch ( rAttr
.Which() )
2438 case RES_TXTATR_REFMARK
:
2439 case RES_TXTATR_TOXMARK
:
2441 // case RES_TXTATR_FIELD: ??????
2442 // case RES_TXTATR_FLYCNT, // 29
2444 case RES_TXTATR_FTN
:
2445 cRet
= CH_TXTATR_INWORD
;
2448 // depends on the character ??
2449 // case RES_TXTATR_HARDBLANK:
2450 // cRet = CH_TXTATR_INWORD;