xref: /aoo42x/main/sw/source/core/txtnode/thints.cxx (revision 7a164331)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10efeef26fSAndrew Rist  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19efeef26fSAndrew Rist  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <hintids.hxx>
29cdf0e10cSrcweir #include <sot/factory.hxx>
30cdf0e10cSrcweir #include <editeng/xmlcnitm.hxx>
31cdf0e10cSrcweir #include <svl/whiter.hxx>
32cdf0e10cSrcweir #include <svl/itemiter.hxx>
33cdf0e10cSrcweir #include <svl/stylepool.hxx>
34cdf0e10cSrcweir #include <editeng/fontitem.hxx>
35cdf0e10cSrcweir #include <editeng/langitem.hxx>
36cdf0e10cSrcweir #include <editeng/emphitem.hxx>
37cdf0e10cSrcweir #include <editeng/charscaleitem.hxx>
38cdf0e10cSrcweir #include <editeng/charrotateitem.hxx>
39cdf0e10cSrcweir // --> OD 2008-01-16 #newlistlevelattrs#
40cdf0e10cSrcweir #include <editeng/lrspitem.hxx>
41cdf0e10cSrcweir // <--
42cdf0e10cSrcweir #include <txtinet.hxx>
43cdf0e10cSrcweir #include <txtflcnt.hxx>
44cdf0e10cSrcweir #include <fmtfld.hxx>
45cdf0e10cSrcweir #include <fmtanchr.hxx>
46cdf0e10cSrcweir #include <fmtinfmt.hxx>
47cdf0e10cSrcweir #include <txtatr.hxx>
48cdf0e10cSrcweir #include <fchrfmt.hxx>
49cdf0e10cSrcweir #include <fmtautofmt.hxx>
50cdf0e10cSrcweir #include <fmtflcnt.hxx>
51cdf0e10cSrcweir #include <fmtftn.hxx>
52cdf0e10cSrcweir #include <txttxmrk.hxx>
53cdf0e10cSrcweir #include <txtrfmrk.hxx>
54cdf0e10cSrcweir #include <txtftn.hxx>
55cdf0e10cSrcweir #include <txtfld.hxx>
56dec99bbdSOliver-Rainer Wittmann #include <txtannotationfld.hxx>
57cdf0e10cSrcweir #include <charatr.hxx>
58cdf0e10cSrcweir #include <charfmt.hxx>
59cdf0e10cSrcweir #include <frmfmt.hxx>
60cdf0e10cSrcweir #include <ftnidx.hxx>
61cdf0e10cSrcweir #include <fmtruby.hxx>
62cdf0e10cSrcweir #include <fmtmeta.hxx>
63cdf0e10cSrcweir #include <breakit.hxx>
64cdf0e10cSrcweir #include <doc.hxx>
65cdf0e10cSrcweir #include <IDocumentUndoRedo.hxx>
66cdf0e10cSrcweir #include <errhdl.hxx>
67cdf0e10cSrcweir #include <fldbas.hxx>
68cdf0e10cSrcweir #include <pam.hxx>
69cdf0e10cSrcweir #include <ndtxt.hxx>
70cdf0e10cSrcweir #include <txtfrm.hxx>
71cdf0e10cSrcweir #include <rolbck.hxx>			// fuer	SwRegHistory
72cdf0e10cSrcweir #include <ddefld.hxx>
73cdf0e10cSrcweir #include <docufld.hxx>
74cdf0e10cSrcweir #include <expfld.hxx>
75cdf0e10cSrcweir #include <usrfld.hxx>
76cdf0e10cSrcweir #include <poolfmt.hxx>
77cdf0e10cSrcweir #include <swfont.hxx>
78cdf0e10cSrcweir #include <istyleaccess.hxx>
79cdf0e10cSrcweir // OD 26.06.2003 #108784#
80cdf0e10cSrcweir #include <dcontact.hxx>
81cdf0e10cSrcweir #include <docsh.hxx>
82cdf0e10cSrcweir #include <svl/smplhint.hxx>
83cdf0e10cSrcweir #include <algorithm>
84cdf0e10cSrcweir #include <map>
85cdf0e10cSrcweir 
86cdf0e10cSrcweir #ifdef DBG_UTIL
87cdf0e10cSrcweir #define CHECK    Check();
88cdf0e10cSrcweir #else
89cdf0e10cSrcweir #define CHECK
90cdf0e10cSrcweir #endif
91cdf0e10cSrcweir 
92cdf0e10cSrcweir using namespace ::com::sun::star::i18n;
93cdf0e10cSrcweir 
94cdf0e10cSrcweir 
SwpHints()95cdf0e10cSrcweir SwpHints::SwpHints()
96cdf0e10cSrcweir     : m_pHistory(0)
97cdf0e10cSrcweir     , m_bFontChange(true)
98cdf0e10cSrcweir     , m_bInSplitNode(false)
99cdf0e10cSrcweir     , m_bCalcHiddenParaField(false)
100cdf0e10cSrcweir     , m_bHasHiddenParaField(false)
101cdf0e10cSrcweir     , m_bFootnote(false)
102cdf0e10cSrcweir     , m_bDDEFields(false)
103cdf0e10cSrcweir {
104cdf0e10cSrcweir }
105cdf0e10cSrcweir 
106cdf0e10cSrcweir struct TxtAttrDeleter
107cdf0e10cSrcweir {
108cdf0e10cSrcweir     SwAttrPool & m_rPool;
TxtAttrDeleterTxtAttrDeleter109cdf0e10cSrcweir     TxtAttrDeleter( SwDoc & rDoc ) : m_rPool( rDoc.GetAttrPool() ) { }
operator ()TxtAttrDeleter110cdf0e10cSrcweir     void operator() (SwTxtAttr * const pAttr)
111cdf0e10cSrcweir     {
112cdf0e10cSrcweir         if (RES_TXTATR_META == pAttr->Which() ||
113cdf0e10cSrcweir             RES_TXTATR_METAFIELD == pAttr->Which())
114cdf0e10cSrcweir         {
115cdf0e10cSrcweir             static_cast<SwTxtMeta *>(pAttr)->ChgTxtNode(0); // prevents ASSERT
116cdf0e10cSrcweir         }
117cdf0e10cSrcweir         SwTxtAttr::Destroy( pAttr, m_rPool );
118cdf0e10cSrcweir     }
119cdf0e10cSrcweir };
120cdf0e10cSrcweir 
121cdf0e10cSrcweir struct TxtAttrContains
122cdf0e10cSrcweir {
123cdf0e10cSrcweir     xub_StrLen m_nPos;
TxtAttrContainsTxtAttrContains124cdf0e10cSrcweir     TxtAttrContains( const xub_StrLen nPos ) : m_nPos( nPos ) { }
operator ()TxtAttrContains125cdf0e10cSrcweir     bool operator() (SwTxtAttrEnd * const pAttr)
126cdf0e10cSrcweir     {
12769a74367SOliver-Rainer Wittmann         return (*pAttr->GetStart() < m_nPos) && (m_nPos < *pAttr->End());
128cdf0e10cSrcweir     }
129cdf0e10cSrcweir };
130cdf0e10cSrcweir 
131cdf0e10cSrcweir // a:       |-----|
132cdf0e10cSrcweir // b:
133cdf0e10cSrcweir //    |---|               => valid: b before a
134cdf0e10cSrcweir //    |-----|             => valid: start == end; b before a
135cdf0e10cSrcweir //    |---------|         => invalid: overlap (1)
136cdf0e10cSrcweir //    |-----------|       => valid: same end; b around a
137cdf0e10cSrcweir //    |-----------------| => valid: b around a
138cdf0e10cSrcweir //          |---|         => valid; same start; b within a
139cdf0e10cSrcweir //          |-----|       => valid; same start and end; b around or within a?
140cdf0e10cSrcweir //          |-----------| => valid: same start: b around a
141cdf0e10cSrcweir //            |-|         => valid: b within a
142cdf0e10cSrcweir //            |---|       => valid: same end; b within a
143cdf0e10cSrcweir //            |---------| => invalid: overlap (2)
144cdf0e10cSrcweir //                |-----| => valid: end == start; b after a
145cdf0e10cSrcweir //                  |---| => valid: b after a
146cdf0e10cSrcweir // ===> 2 invalid overlap cases
147cdf0e10cSrcweir static
isOverlap(const xub_StrLen nStart1,const xub_StrLen nEnd1,const xub_StrLen nStart2,const xub_StrLen nEnd2)148cdf0e10cSrcweir bool isOverlap(const xub_StrLen nStart1, const xub_StrLen nEnd1,
149cdf0e10cSrcweir                const xub_StrLen nStart2, const xub_StrLen nEnd2)
150cdf0e10cSrcweir {
151cdf0e10cSrcweir     return
152cdf0e10cSrcweir         ((nStart1 > nStart2) && (nStart1 < nEnd2) && (nEnd1 > nEnd2))  // (1)
153cdf0e10cSrcweir      || ((nStart1 < nStart2) && (nStart2 < nEnd1) && (nEnd1 < nEnd2)); // (2)
154cdf0e10cSrcweir }
155cdf0e10cSrcweir 
156cdf0e10cSrcweir /// #i106930#: now asymmetric: empty hint1 is _not_ nested, but empty hint2 is
157cdf0e10cSrcweir static
isNestedAny(const xub_StrLen nStart1,const xub_StrLen nEnd1,const xub_StrLen nStart2,const xub_StrLen nEnd2)158cdf0e10cSrcweir bool isNestedAny(const xub_StrLen nStart1, const xub_StrLen nEnd1,
159cdf0e10cSrcweir                  const xub_StrLen nStart2, const xub_StrLen nEnd2)
160cdf0e10cSrcweir {
161cdf0e10cSrcweir     return ((nStart1 == nStart2) || (nEnd1 == nEnd2))
162cdf0e10cSrcweir         // same start/end: nested except if hint1 empty and hint2 not empty
163cdf0e10cSrcweir         ? (nStart1 != nEnd1) || (nStart2 == nEnd2)
164cdf0e10cSrcweir         : ((nStart1 < nStart2) ? (nEnd1 >= nEnd2) : (nEnd1 <= nEnd2));
165cdf0e10cSrcweir }
166cdf0e10cSrcweir 
167cdf0e10cSrcweir static
isSelfNestable(const sal_uInt16 nWhich)168cdf0e10cSrcweir bool isSelfNestable(const sal_uInt16 nWhich)
169cdf0e10cSrcweir {
170cdf0e10cSrcweir     if ((RES_TXTATR_INETFMT  == nWhich) ||
17169a74367SOliver-Rainer Wittmann         (RES_TXTATR_CJK_RUBY == nWhich) ||
17269a74367SOliver-Rainer Wittmann         (RES_TXTATR_INPUTFIELD == nWhich))
173cdf0e10cSrcweir         return false;
174cdf0e10cSrcweir     ASSERT((RES_TXTATR_META  == nWhich) ||
175cdf0e10cSrcweir            (RES_TXTATR_METAFIELD  == nWhich), "???");
176cdf0e10cSrcweir     return true;
177cdf0e10cSrcweir }
178cdf0e10cSrcweir 
179cdf0e10cSrcweir static
isSplittable(const sal_uInt16 nWhich)180cdf0e10cSrcweir bool isSplittable(const sal_uInt16 nWhich)
181cdf0e10cSrcweir {
182cdf0e10cSrcweir     if ((RES_TXTATR_INETFMT  == nWhich) ||
183cdf0e10cSrcweir         (RES_TXTATR_CJK_RUBY == nWhich))
184cdf0e10cSrcweir         return true;
185cdf0e10cSrcweir     ASSERT((RES_TXTATR_META  == nWhich) ||
18669a74367SOliver-Rainer Wittmann            (RES_TXTATR_METAFIELD  == nWhich) ||
18769a74367SOliver-Rainer Wittmann            (RES_TXTATR_INPUTFIELD  == nWhich), "???");
188cdf0e10cSrcweir     return false;
189cdf0e10cSrcweir }
190cdf0e10cSrcweir 
191cdf0e10cSrcweir enum Split_t { FAIL, SPLIT_NEW, SPLIT_OTHER };
192cdf0e10cSrcweir /**
193cdf0e10cSrcweir   Calculate splitting policy for overlapping hints, based on what kind of
194cdf0e10cSrcweir   hint is inserted, and what kind of existing hint overlaps.
195cdf0e10cSrcweir   */
196cdf0e10cSrcweir static Split_t
splitPolicy(const sal_uInt16 nWhichNew,const sal_uInt16 nWhichOther)197cdf0e10cSrcweir splitPolicy(const sal_uInt16 nWhichNew, const sal_uInt16 nWhichOther)
198cdf0e10cSrcweir {
199cdf0e10cSrcweir     if (!isSplittable(nWhichOther))
200cdf0e10cSrcweir     {
201cdf0e10cSrcweir         if (!isSplittable(nWhichNew))
202cdf0e10cSrcweir             return FAIL;
203cdf0e10cSrcweir         else
204cdf0e10cSrcweir             return SPLIT_NEW;
205cdf0e10cSrcweir     }
206cdf0e10cSrcweir     else
207cdf0e10cSrcweir     {
20869a74367SOliver-Rainer Wittmann         if ( RES_TXTATR_INPUTFIELD == nWhichNew )
20969a74367SOliver-Rainer Wittmann             return FAIL;
21069a74367SOliver-Rainer Wittmann         else if ( (RES_TXTATR_INETFMT  == nWhichNew) &&
21169a74367SOliver-Rainer Wittmann                   (RES_TXTATR_CJK_RUBY == nWhichOther) )
212cdf0e10cSrcweir             return SPLIT_NEW;
213cdf0e10cSrcweir         else
214cdf0e10cSrcweir             return SPLIT_OTHER;
215cdf0e10cSrcweir     }
216cdf0e10cSrcweir }
217cdf0e10cSrcweir 
InitINetFmt(SwTxtNode & rNode)218cdf0e10cSrcweir void SwTxtINetFmt::InitINetFmt(SwTxtNode & rNode)
219cdf0e10cSrcweir {
220cdf0e10cSrcweir     ChgTxtNode(&rNode);
221cdf0e10cSrcweir     SwCharFmt * const pFmt(
222cdf0e10cSrcweir          rNode.GetDoc()->GetCharFmtFromPool(RES_POOLCHR_INET_NORMAL) );
223cdf0e10cSrcweir     pFmt->Add( this );
224cdf0e10cSrcweir }
225cdf0e10cSrcweir 
InitRuby(SwTxtNode & rNode)226cdf0e10cSrcweir void SwTxtRuby::InitRuby(SwTxtNode & rNode)
227cdf0e10cSrcweir {
228cdf0e10cSrcweir     ChgTxtNode(&rNode);
229cdf0e10cSrcweir     SwCharFmt * const pFmt(
230cdf0e10cSrcweir         rNode.GetDoc()->GetCharFmtFromPool(RES_POOLCHR_RUBYTEXT) );
231cdf0e10cSrcweir     pFmt->Add( this );
232cdf0e10cSrcweir }
233cdf0e10cSrcweir 
234cdf0e10cSrcweir /**
235cdf0e10cSrcweir   Create a new nesting text hint.
236cdf0e10cSrcweir  */
237cdf0e10cSrcweir static SwTxtAttrNesting *
MakeTxtAttrNesting(SwTxtNode & rNode,SwTxtAttrNesting & rNesting,const xub_StrLen nStart,const xub_StrLen nEnd)238cdf0e10cSrcweir MakeTxtAttrNesting(SwTxtNode & rNode, SwTxtAttrNesting & rNesting,
239cdf0e10cSrcweir         const xub_StrLen nStart, const xub_StrLen nEnd)
240cdf0e10cSrcweir {
241cdf0e10cSrcweir     SwTxtAttr * const pNew( MakeTxtAttr(
242cdf0e10cSrcweir             *rNode.GetDoc(), rNesting.GetAttr(), nStart, nEnd ) );
243cdf0e10cSrcweir     switch (pNew->Which())
244cdf0e10cSrcweir     {
245cdf0e10cSrcweir         case RES_TXTATR_INETFMT:
246cdf0e10cSrcweir         {
247cdf0e10cSrcweir             static_cast<SwTxtINetFmt*>(pNew)->InitINetFmt(rNode);
248cdf0e10cSrcweir             break;
249cdf0e10cSrcweir         }
250cdf0e10cSrcweir         case RES_TXTATR_CJK_RUBY:
251cdf0e10cSrcweir         {
252cdf0e10cSrcweir             static_cast<SwTxtRuby*>(pNew)->InitRuby(rNode);
253cdf0e10cSrcweir             break;
254cdf0e10cSrcweir         }
255cdf0e10cSrcweir         default:
256cdf0e10cSrcweir             ASSERT(false, "MakeTxtAttrNesting: what the hell is that?");
257cdf0e10cSrcweir             break;
258cdf0e10cSrcweir     }
259cdf0e10cSrcweir     return static_cast<SwTxtAttrNesting*>(pNew);
260cdf0e10cSrcweir }
261cdf0e10cSrcweir 
262cdf0e10cSrcweir typedef ::std::vector<SwTxtAttrNesting *> NestList_t;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir static void
lcl_DoSplitNew(NestList_t & rSplits,SwTxtNode & rNode,const xub_StrLen nNewStart,const xub_StrLen nOtherStart,const xub_StrLen nOtherEnd,bool bOtherDummy)265cdf0e10cSrcweir lcl_DoSplitNew(NestList_t & rSplits, SwTxtNode & rNode,
266cdf0e10cSrcweir     const xub_StrLen nNewStart,
267cdf0e10cSrcweir     const xub_StrLen nOtherStart, const xub_StrLen nOtherEnd, bool bOtherDummy)
268cdf0e10cSrcweir {
269cdf0e10cSrcweir     const bool bSplitAtStart(nNewStart < nOtherStart);
270cdf0e10cSrcweir     const xub_StrLen nSplitPos( (bSplitAtStart) ? nOtherStart : nOtherEnd );
271cdf0e10cSrcweir     // first find the portion that is split (not necessarily the last one!)
272cdf0e10cSrcweir     NestList_t::iterator const iter(
273cdf0e10cSrcweir         ::std::find_if( rSplits.begin(), rSplits.end(),
274cdf0e10cSrcweir             TxtAttrContains(nSplitPos) ) );
275cdf0e10cSrcweir     if (iter != rSplits.end()) // already split here?
276cdf0e10cSrcweir     {
277cdf0e10cSrcweir         const xub_StrLen nStartPos( // skip other's dummy character!
278cdf0e10cSrcweir             (bSplitAtStart && bOtherDummy) ? nSplitPos + 1 : nSplitPos );
279cdf0e10cSrcweir         SwTxtAttrNesting * const pNew( MakeTxtAttrNesting(
280cdf0e10cSrcweir                 rNode, **iter, nStartPos, *(*iter)->GetEnd() ) );
281cdf0e10cSrcweir         *(*iter)->GetEnd() = nSplitPos;
282cdf0e10cSrcweir         rSplits.insert(iter + 1, pNew);
283cdf0e10cSrcweir     }
284cdf0e10cSrcweir }
285cdf0e10cSrcweir 
286cdf0e10cSrcweir /**
287cdf0e10cSrcweir   Insert nesting hint into the hints array. Also calls NoteInHistory.
288cdf0e10cSrcweir   @param    rNewHint    the hint to be inserted (must not overlap existing!)
289cdf0e10cSrcweir  */
InsertNesting(SwTxtAttrNesting & rNewHint)290cdf0e10cSrcweir void SwpHints::InsertNesting(SwTxtAttrNesting & rNewHint)
291cdf0e10cSrcweir {
292cdf0e10cSrcweir     SwpHintsArray::Insert(& rNewHint);
293cdf0e10cSrcweir     NoteInHistory( & rNewHint, true );
294cdf0e10cSrcweir }
295cdf0e10cSrcweir 
296cdf0e10cSrcweir /**
297cdf0e10cSrcweir 
298cdf0e10cSrcweir The following hints correspond to well-formed XML elements in ODF:
299cdf0e10cSrcweir RES_TXTATR_INETFMT, RES_TXTATR_CJK_RUBY, RES_TXTATR_META, RES_TXTATR_METAFIELD
300cdf0e10cSrcweir 
301cdf0e10cSrcweir The writer core must ensure that these do not overlap; if they did,
302cdf0e10cSrcweir the document would not be storable as ODF.
303cdf0e10cSrcweir 
304cdf0e10cSrcweir Also, a Hyperlink must not be nested within another Hyperlink,
305cdf0e10cSrcweir and a Ruby must not be nested within another Ruby.
306cdf0e10cSrcweir 
307cdf0e10cSrcweir The ODF export in xmloff will only put a hyperlink into a ruby, never a ruby
308cdf0e10cSrcweir into a hyperlink.
309cdf0e10cSrcweir 
310cdf0e10cSrcweir Unfortunately the UNO API for Hyperlink and Ruby consists of the properties
311cdf0e10cSrcweir Hyperlink* and Ruby* of the css.text.CharacterProperties service.  In other
312cdf0e10cSrcweir words, they are treated as formatting attributes, not as content entites.
313cdf0e10cSrcweir Furthermore, for API users it is not possible to easily test whether a certain
314cdf0e10cSrcweir range would be overlapping with other nested attributes, and most importantly,
315cdf0e10cSrcweir <em>which ones</em>, so we can hardly refuse to insert these in cases of
316cdf0e10cSrcweir overlap.
317cdf0e10cSrcweir 
318cdf0e10cSrcweir It is possible to split Hyperlink and Ruby into multiple portions, such that
319cdf0e10cSrcweir the result is properly nested.
320cdf0e10cSrcweir 
321cdf0e10cSrcweir meta and meta-field must not be split, because they have xml:id.
322cdf0e10cSrcweir 
323cdf0e10cSrcweir These constraints result in the following design:
324cdf0e10cSrcweir 
325cdf0e10cSrcweir RES_TXTATR_INETFMT:
326cdf0e10cSrcweir     always succeeds
327cdf0e10cSrcweir     inserts n attributes split at RES_TXTATR_CJK_RUBY, RES_TXTATR_META,
328cdf0e10cSrcweir         RES_TXTATR_METAFIELD
329cdf0e10cSrcweir     may replace existing RES_TXTATR_INETFMT at overlap
330cdf0e10cSrcweir RES_TXTATR_CJK_RUBY:
331cdf0e10cSrcweir     always succeeds
332cdf0e10cSrcweir     inserts n attributes split at RES_TXTATR_META, RES_TXTATR_METAFIELD
333cdf0e10cSrcweir     may replace existing RES_TXTATR_CJK_RUBY at overlap
334cdf0e10cSrcweir     may split existing overlapping RES_TXTATR_INETFMT
335cdf0e10cSrcweir RES_TXTATR_META:
336cdf0e10cSrcweir     may fail if overlapping existing RES_TXTATR_META/RES_TXTATR_METAFIELD
337cdf0e10cSrcweir     may split existing overlapping RES_TXTATR_INETFMT or RES_TXTATR_CJK_RUBY
338cdf0e10cSrcweir     inserts 1 attribute
339cdf0e10cSrcweir RES_TXTATR_METAFIELD:
340cdf0e10cSrcweir     may fail if overlapping existing RES_TXTATR_META/RES_TXTATR_METAFIELD
341cdf0e10cSrcweir     may split existing overlapping RES_TXTATR_INETFMT or RES_TXTATR_CJK_RUBY
342cdf0e10cSrcweir     inserts 1 attribute
343cdf0e10cSrcweir 
344cdf0e10cSrcweir The nesting is expressed by the position of the hints.
345cdf0e10cSrcweir RES_TXTATR_META and RES_TXTATR_METAFIELD have a CH_TXTATR, and there can
346cdf0e10cSrcweir only be one such hint starting and ending at a given position.
347cdf0e10cSrcweir Only RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY lack a CH_TXTATR.
348cdf0e10cSrcweir The interpretation given is that RES_TXTATR_CJK_RUBY is always around
349cdf0e10cSrcweir a RES_TXTATR_INETFMT at the same start and end position (which corresponds
350cdf0e10cSrcweir with the UNO API).
351cdf0e10cSrcweir Both of these are always around a nesting hint with CH_TXTATR at the same
352cdf0e10cSrcweir start and end position (if they should be inside, then the start should be
353cdf0e10cSrcweir after the CH_TXTATR).
354cdf0e10cSrcweir It would probably be a bad idea to add another nesting hint without
355cdf0e10cSrcweir CH_TXTATR; on the other hand, it would be difficult adding a CH_TXTATR to
356cdf0e10cSrcweir RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY, due to the overwriting and
357cdf0e10cSrcweir splitting of exising hints that is necessary for backward compatibility.
358cdf0e10cSrcweir 
359cdf0e10cSrcweir     @param rNode    the text node
360cdf0e10cSrcweir     @param rHint    the hint to be inserted
361cdf0e10cSrcweir     @returns        true iff hint was successfully inserted
362cdf0e10cSrcweir */
363cdf0e10cSrcweir bool
TryInsertNesting(SwTxtNode & rNode,SwTxtAttrNesting & rNewHint)364cdf0e10cSrcweir SwpHints::TryInsertNesting( SwTxtNode & rNode, SwTxtAttrNesting & rNewHint )
365cdf0e10cSrcweir {
366cdf0e10cSrcweir //    INVARIANT:  the nestable hints in the array are properly nested
367cdf0e10cSrcweir     const sal_uInt16 nNewWhich( rNewHint.Which() );
368cdf0e10cSrcweir     const xub_StrLen nNewStart( *rNewHint.GetStart() );
369cdf0e10cSrcweir     const xub_StrLen nNewEnd  ( *rNewHint.GetEnd()   );
370cdf0e10cSrcweir     const bool bNewSelfNestable( isSelfNestable(nNewWhich) );
371cdf0e10cSrcweir 
372cdf0e10cSrcweir     ASSERT( (RES_TXTATR_INETFMT   == nNewWhich) ||
373cdf0e10cSrcweir             (RES_TXTATR_CJK_RUBY  == nNewWhich) ||
374cdf0e10cSrcweir             (RES_TXTATR_META      == nNewWhich) ||
37569a74367SOliver-Rainer Wittmann             (RES_TXTATR_METAFIELD == nNewWhich) ||
37669a74367SOliver-Rainer Wittmann             (RES_TXTATR_INPUTFIELD == nNewWhich),
37769a74367SOliver-Rainer Wittmann         "TryInsertNesting: Expecting INETFMT or RUBY or META or METAFIELD or INPUTFIELD" );
378cdf0e10cSrcweir 
379cdf0e10cSrcweir     NestList_t OverlappingExisting; // existing hints to be split
380cdf0e10cSrcweir     NestList_t OverwrittenExisting; // existing hints to be replaced
381cdf0e10cSrcweir     NestList_t SplitNew;            // new hints to be inserted
382cdf0e10cSrcweir 
383cdf0e10cSrcweir     SplitNew.push_back(& rNewHint);
384cdf0e10cSrcweir 
385cdf0e10cSrcweir     // pass 1: split the inserted hint into fragments if necessary
386cdf0e10cSrcweir     for ( sal_uInt16 i = 0; i < GetEndCount(); ++i )
387cdf0e10cSrcweir     {
388cdf0e10cSrcweir         SwTxtAttr * const pOther = GetEnd(i);
389cdf0e10cSrcweir 
390cdf0e10cSrcweir         if (pOther->IsNesting())
391cdf0e10cSrcweir         {
392cdf0e10cSrcweir             const sal_uInt16 nOtherWhich( pOther->Which() );
393cdf0e10cSrcweir             const xub_StrLen nOtherStart( *(pOther)->GetStart() );
394cdf0e10cSrcweir             const xub_StrLen nOtherEnd  ( *(pOther)->GetEnd()   );
395cdf0e10cSrcweir             if (isOverlap(nNewStart, nNewEnd, nOtherStart, nOtherEnd ))
396cdf0e10cSrcweir             {
397cdf0e10cSrcweir                 switch (splitPolicy(nNewWhich, nOtherWhich))
398cdf0e10cSrcweir                 {
399cdf0e10cSrcweir                     case FAIL:
400cdf0e10cSrcweir                         OSL_TRACE("cannot insert hint: overlap detected");
401cdf0e10cSrcweir                         ::std::for_each(SplitNew.begin(), SplitNew.end(),
402cdf0e10cSrcweir                             TxtAttrDeleter(*rNode.GetDoc()));
403cdf0e10cSrcweir                         return false;
404cdf0e10cSrcweir                     case SPLIT_NEW:
405cdf0e10cSrcweir                         lcl_DoSplitNew(SplitNew, rNode, nNewStart,
406cdf0e10cSrcweir                             nOtherStart, nOtherEnd, pOther->HasDummyChar());
407cdf0e10cSrcweir                         break;
408cdf0e10cSrcweir                     case SPLIT_OTHER:
409cdf0e10cSrcweir                         OverlappingExisting.push_back(
410cdf0e10cSrcweir                             static_cast<SwTxtAttrNesting*>(pOther));
411cdf0e10cSrcweir                         break;
412cdf0e10cSrcweir                     default:
413cdf0e10cSrcweir                         ASSERT(false, "bad code monkey");
414cdf0e10cSrcweir                         break;
415cdf0e10cSrcweir                 }
416cdf0e10cSrcweir             }
417cdf0e10cSrcweir             else if (isNestedAny(nNewStart, nNewEnd, nOtherStart, nOtherEnd))
418cdf0e10cSrcweir             {
419cdf0e10cSrcweir                 if (!bNewSelfNestable && (nNewWhich == nOtherWhich))
420cdf0e10cSrcweir                 {
421cdf0e10cSrcweir                 // ruby and hyperlink: if there is nesting, _overwrite_
422cdf0e10cSrcweir                 OverwrittenExisting.push_back(
423cdf0e10cSrcweir                     static_cast<SwTxtAttrNesting*>(pOther));
424cdf0e10cSrcweir                 }
425cdf0e10cSrcweir                 else if ((nNewStart == nOtherStart) && pOther->HasDummyChar())
426cdf0e10cSrcweir                 {
427cdf0e10cSrcweir                     if (rNewHint.HasDummyChar())
428cdf0e10cSrcweir                     {
429cdf0e10cSrcweir                         ASSERT(false,
430cdf0e10cSrcweir                                 "ERROR: inserting duplicate CH_TXTATR hint");
431cdf0e10cSrcweir                         return false;
432cdf0e10cSrcweir                     } else if (nNewEnd < nOtherEnd) {
433cdf0e10cSrcweir                         // other has dummy char, new is inside other, but
434cdf0e10cSrcweir                         // new contains the other's dummy char?
435cdf0e10cSrcweir                         // should be corrected because it may lead to problems
436cdf0e10cSrcweir                         // in SwXMeta::createEnumeration
437cdf0e10cSrcweir                         // SplitNew is sorted, so this is the first split
438cdf0e10cSrcweir                         xub_StrLen *const pStart(SplitNew.front()->GetStart());
439cdf0e10cSrcweir                         ASSERT(*pStart == nNewStart, "how did that happen?");
440cdf0e10cSrcweir                         *pStart = nNewStart + 1;
441cdf0e10cSrcweir                     }
442cdf0e10cSrcweir                 }
443cdf0e10cSrcweir             }
444cdf0e10cSrcweir         }
445cdf0e10cSrcweir     }
446cdf0e10cSrcweir 
447cdf0e10cSrcweir     ASSERT (isSplittable(nNewWhich) || SplitNew.size() == 1,
448cdf0e10cSrcweir             "splitting the unsplittable ???");
449cdf0e10cSrcweir 
450cdf0e10cSrcweir     // pass 2: split existing hints that overlap/nest with new hint
451cdf0e10cSrcweir     // do not iterate over hints array, but over remembered set of overlapping
452cdf0e10cSrcweir     // hints, to keep things simple w.r.t. insertion/removal
453cdf0e10cSrcweir     // N.B: if there is a hint that splits the inserted hint, then
454cdf0e10cSrcweir     // that hint would also have already split any hint in OverlappingExisting
455cdf0e10cSrcweir     // so any hint in OverlappingExisting can be split at most by one hint
456cdf0e10cSrcweir     // in SplitNew, or even not at all (this is not true for existing hints
457cdf0e10cSrcweir     // that go _around_ new hint, which is the raison d'^etre for pass 4)
458cdf0e10cSrcweir     for (NestList_t::iterator itOther = OverlappingExisting.begin();
459cdf0e10cSrcweir             itOther != OverlappingExisting.end(); ++itOther)
460cdf0e10cSrcweir     {
461cdf0e10cSrcweir         const xub_StrLen nOtherStart( *(*itOther)->GetStart() );
462cdf0e10cSrcweir         const xub_StrLen nOtherEnd  ( *(*itOther)->GetEnd()   );
463cdf0e10cSrcweir 
464cdf0e10cSrcweir         for (NestList_t::iterator itNew = SplitNew.begin();
465cdf0e10cSrcweir                 itNew != SplitNew.end(); ++itNew)
466cdf0e10cSrcweir         {
467cdf0e10cSrcweir             const xub_StrLen nSplitNewStart( *(*itNew)->GetStart() );
468cdf0e10cSrcweir             const xub_StrLen nSplitNewEnd  ( *(*itNew)->GetEnd()   );
469cdf0e10cSrcweir             // 4 cases: within, around, overlap l, overlap r, (OTHER: no action)
470cdf0e10cSrcweir             const bool bRemoveOverlap(
471cdf0e10cSrcweir                 !bNewSelfNestable && (nNewWhich == (*itOther)->Which()) );
472cdf0e10cSrcweir 
473cdf0e10cSrcweir             switch (ComparePosition(nSplitNewStart, nSplitNewEnd,
474cdf0e10cSrcweir                                     nOtherStart,    nOtherEnd))
475cdf0e10cSrcweir             {
476cdf0e10cSrcweir                 case POS_INSIDE:
477cdf0e10cSrcweir                     {
478cdf0e10cSrcweir                         ASSERT(!bRemoveOverlap,
479cdf0e10cSrcweir                             "this one should be in OverwrittenExisting?");
480cdf0e10cSrcweir                     }
481cdf0e10cSrcweir                     break;
482cdf0e10cSrcweir                 case POS_OUTSIDE:
483cdf0e10cSrcweir                 case POS_EQUAL:
484cdf0e10cSrcweir                     {
485cdf0e10cSrcweir                         ASSERT(false, "existing hint inside new hint: why?");
486cdf0e10cSrcweir                     }
487cdf0e10cSrcweir                     break;
488cdf0e10cSrcweir                 case POS_OVERLAP_BEFORE:
489cdf0e10cSrcweir                     {
490cdf0e10cSrcweir                         Delete( *itOther ); // this also does NoteInHistory!
491cdf0e10cSrcweir                         *(*itOther)->GetStart() = nSplitNewEnd;
492cdf0e10cSrcweir                         InsertNesting( **itOther );
493cdf0e10cSrcweir                         if (!bRemoveOverlap)
494cdf0e10cSrcweir                         {
495cdf0e10cSrcweir                             if ( USHRT_MAX == Count() )
496cdf0e10cSrcweir                             {
497cdf0e10cSrcweir                                 ASSERT(false, "hints array full :-(");
498cdf0e10cSrcweir                                 return false;
499cdf0e10cSrcweir                             }
500cdf0e10cSrcweir                             SwTxtAttrNesting * const pOtherLeft(
501cdf0e10cSrcweir                                 MakeTxtAttrNesting( rNode, **itOther,
502cdf0e10cSrcweir                                     nOtherStart, nSplitNewEnd ) );
503cdf0e10cSrcweir                             InsertNesting( *pOtherLeft );
504cdf0e10cSrcweir                         }
505cdf0e10cSrcweir                     }
506cdf0e10cSrcweir                     break;
507cdf0e10cSrcweir                 case POS_OVERLAP_BEHIND:
508cdf0e10cSrcweir                     {
509cdf0e10cSrcweir                         Delete( *itOther ); // this also does NoteInHistory!
510cdf0e10cSrcweir                         *(*itOther)->GetEnd() = nSplitNewStart;
511cdf0e10cSrcweir                         InsertNesting( **itOther );
512cdf0e10cSrcweir                         if (!bRemoveOverlap)
513cdf0e10cSrcweir                         {
514cdf0e10cSrcweir                             if ( USHRT_MAX == Count() )
515cdf0e10cSrcweir                             {
516cdf0e10cSrcweir                                 ASSERT(false, "hints array full :-(");
517cdf0e10cSrcweir                                 return false;
518cdf0e10cSrcweir                             }
519cdf0e10cSrcweir                             SwTxtAttrNesting * const pOtherRight(
520cdf0e10cSrcweir                                 MakeTxtAttrNesting( rNode, **itOther,
521cdf0e10cSrcweir                                     nSplitNewStart, nOtherEnd ) );
522cdf0e10cSrcweir                             InsertNesting( *pOtherRight );
523cdf0e10cSrcweir                         }
524cdf0e10cSrcweir                     }
525cdf0e10cSrcweir                     break;
526cdf0e10cSrcweir                 default:
527cdf0e10cSrcweir                     break; // overlap resolved by splitting new: nothing to do
528cdf0e10cSrcweir             }
529cdf0e10cSrcweir         }
530cdf0e10cSrcweir     }
531cdf0e10cSrcweir 
532cdf0e10cSrcweir     if ( USHRT_MAX - SplitNew.size() <= Count() )
533cdf0e10cSrcweir     {
534cdf0e10cSrcweir         ASSERT(false, "hints array full :-(");
535cdf0e10cSrcweir         return false;
536cdf0e10cSrcweir     }
537cdf0e10cSrcweir 
538cdf0e10cSrcweir     // pass 3: insert new hints
539cdf0e10cSrcweir     for (NestList_t::iterator iter = SplitNew.begin();
540cdf0e10cSrcweir             iter != SplitNew.end(); ++iter)
541cdf0e10cSrcweir     {
542cdf0e10cSrcweir         InsertNesting(**iter);
543cdf0e10cSrcweir     }
544cdf0e10cSrcweir 
545cdf0e10cSrcweir     // pass 4: handle overwritten hints
546cdf0e10cSrcweir     // RES_TXTATR_INETFMT and RES_TXTATR_CJK_RUBY should displace attributes
547cdf0e10cSrcweir     // of the same kind.
548cdf0e10cSrcweir     for (NestList_t::iterator itOther = OverwrittenExisting.begin();
549cdf0e10cSrcweir             itOther != OverwrittenExisting.end(); ++itOther)
550cdf0e10cSrcweir     {
551cdf0e10cSrcweir         const xub_StrLen nOtherStart( *(*itOther)->GetStart() );
552cdf0e10cSrcweir         const xub_StrLen nOtherEnd  ( *(*itOther)->GetEnd()   );
553cdf0e10cSrcweir 
554cdf0e10cSrcweir         // overwritten portion is given by start/end of inserted hint
555cdf0e10cSrcweir         if ((nNewStart <= nOtherStart) && (nOtherEnd <= nNewEnd))
556cdf0e10cSrcweir         {
557cdf0e10cSrcweir             Delete(*itOther);
558cdf0e10cSrcweir             rNode.DestroyAttr( *itOther );
559cdf0e10cSrcweir         }
560cdf0e10cSrcweir         else
561cdf0e10cSrcweir         {
562cdf0e10cSrcweir             ASSERT((nOtherStart < nNewStart) && (nNewEnd < nOtherEnd), "huh?");
563cdf0e10cSrcweir         // scenario: there is a RUBY, and contained within that a META;
564cdf0e10cSrcweir         // now a RUBY is inserted within the META => the exising RUBY is split:
565cdf0e10cSrcweir         // here it is not possible to simply insert the left/right fragment
566cdf0e10cSrcweir         // of the existing RUBY because they <em>overlap</em> with the META!
567cdf0e10cSrcweir             Delete( *itOther ); // this also does NoteInHistory!
568cdf0e10cSrcweir             *(*itOther)->GetEnd() = nNewStart;
569cdf0e10cSrcweir             bool bSuccess( TryInsertNesting(rNode, **itOther) );
570cdf0e10cSrcweir             ASSERT(bSuccess, "recursive call 1 failed?");
571cdf0e10cSrcweir             SwTxtAttrNesting * const pOtherRight(
572cdf0e10cSrcweir                 MakeTxtAttrNesting(
573cdf0e10cSrcweir                     rNode, **itOther, nNewEnd, nOtherEnd ) );
574cdf0e10cSrcweir             bSuccess = TryInsertNesting(rNode, *pOtherRight);
575cdf0e10cSrcweir             ASSERT(bSuccess, "recursive call 2 failed?");
576cdf0e10cSrcweir         }
577cdf0e10cSrcweir 
578cdf0e10cSrcweir     }
579cdf0e10cSrcweir 
580cdf0e10cSrcweir     return true;
581cdf0e10cSrcweir }
582cdf0e10cSrcweir 
583cdf0e10cSrcweir 
584cdf0e10cSrcweir // This function takes care for the following text attribute:
585cdf0e10cSrcweir // RES_TXTATR_CHARFMT, RES_TXTATR_AUTOFMT
586cdf0e10cSrcweir // These attributes have to be handled in a special way (Portion building).
587cdf0e10cSrcweir //
588cdf0e10cSrcweir // The new attribute will be split by any existing RES_TXTATR_AUTOFMT or
589cdf0e10cSrcweir // RES_TXTATR_CHARFMT. The new attribute itself will
590cdf0e10cSrcweir // split any existing RES_TXTATR_AUTOFMT or RES_TXTATR_CHARFMT.
591cdf0e10cSrcweir 
BuildPortions(SwTxtNode & rNode,SwTxtAttr & rNewHint,const SetAttrMode nMode)592cdf0e10cSrcweir void SwpHints::BuildPortions( SwTxtNode& rNode, SwTxtAttr& rNewHint,
593cdf0e10cSrcweir         const SetAttrMode nMode )
594cdf0e10cSrcweir {
595cdf0e10cSrcweir     const sal_uInt16 nWhich = rNewHint.Which();
596cdf0e10cSrcweir 
597cdf0e10cSrcweir     const xub_StrLen nThisStart = *rNewHint.GetStart();
598cdf0e10cSrcweir     const xub_StrLen nThisEnd =   *rNewHint.GetEnd();
599cdf0e10cSrcweir     const bool bNoLengthAttribute = nThisStart == nThisEnd;
600cdf0e10cSrcweir 
601cdf0e10cSrcweir     std::vector<SwTxtAttr*> aInsDelHints;
602cdf0e10cSrcweir     std::vector<SwTxtAttr*>::iterator aIter;
603cdf0e10cSrcweir 
604cdf0e10cSrcweir     ASSERT( RES_TXTATR_CHARFMT == rNewHint.Which() ||
605cdf0e10cSrcweir             RES_TXTATR_AUTOFMT == rNewHint.Which(),
606cdf0e10cSrcweir             "Expecting CHARFMT or AUTOFMT" );
607cdf0e10cSrcweir 
608cdf0e10cSrcweir     //
609cdf0e10cSrcweir     // 2. Find the hints which cover the start and end position
610cdf0e10cSrcweir     // of the new hint. These hints have to be split into two portions:
611cdf0e10cSrcweir     //
612cdf0e10cSrcweir     if ( !bNoLengthAttribute ) // nothing to do for no length attributes
613cdf0e10cSrcweir     {
614cdf0e10cSrcweir         for ( sal_uInt16 i = 0; i < Count(); ++i )
615cdf0e10cSrcweir         {
616cdf0e10cSrcweir             SwTxtAttr* pOther = GetTextHint(i);
617cdf0e10cSrcweir 
618cdf0e10cSrcweir             if ( RES_TXTATR_CHARFMT != pOther->Which() &&
619cdf0e10cSrcweir                  RES_TXTATR_AUTOFMT != pOther->Which() )
620cdf0e10cSrcweir                 continue;
621cdf0e10cSrcweir 
622cdf0e10cSrcweir             xub_StrLen nOtherStart = *pOther->GetStart();
623cdf0e10cSrcweir             const xub_StrLen nOtherEnd = *pOther->GetEnd();
624cdf0e10cSrcweir 
625cdf0e10cSrcweir             // Check if start of new attribute overlaps with pOther:
626cdf0e10cSrcweir             // Split pOther if necessary:
627cdf0e10cSrcweir             if ( nOtherStart < nThisStart && nThisStart < nOtherEnd )
628cdf0e10cSrcweir             {
629cdf0e10cSrcweir                 SwTxtAttr* pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
630cdf0e10cSrcweir                         pOther->GetAttr(), nOtherStart, nThisStart );
631cdf0e10cSrcweir                 if ( RES_TXTATR_CHARFMT == pOther->Which() )
632cdf0e10cSrcweir                     static_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber( static_cast<SwTxtCharFmt*>(pOther)->GetSortNumber() );
633cdf0e10cSrcweir                 aInsDelHints.push_back( pNewAttr );
634cdf0e10cSrcweir 
635cdf0e10cSrcweir                 NoteInHistory( pOther );
636cdf0e10cSrcweir                 *pOther->GetStart() = nThisStart;
637cdf0e10cSrcweir                 NoteInHistory( pOther, true );
638cdf0e10cSrcweir 
639cdf0e10cSrcweir                 nOtherStart = nThisStart;
640cdf0e10cSrcweir             }
641cdf0e10cSrcweir 
642cdf0e10cSrcweir             // Check if end of new attribute overlaps with pOther:
643cdf0e10cSrcweir             // Split pOther if necessary:
644cdf0e10cSrcweir             if ( nOtherStart < nThisEnd && nThisEnd < nOtherEnd )
645cdf0e10cSrcweir             {
646cdf0e10cSrcweir                 SwTxtAttr* pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
647cdf0e10cSrcweir                         pOther->GetAttr(), nOtherStart, nThisEnd );
648cdf0e10cSrcweir                 if ( RES_TXTATR_CHARFMT == pOther->Which() )
649cdf0e10cSrcweir                     static_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber( static_cast<SwTxtCharFmt*>(pOther)->GetSortNumber() );
650cdf0e10cSrcweir                 aInsDelHints.push_back( pNewAttr );
651cdf0e10cSrcweir 
652cdf0e10cSrcweir                 NoteInHistory( pOther );
653cdf0e10cSrcweir                 *pOther->GetStart() = nThisEnd;
654cdf0e10cSrcweir                 NoteInHistory( pOther, true );
655cdf0e10cSrcweir             }
656cdf0e10cSrcweir         }
657cdf0e10cSrcweir 
658cdf0e10cSrcweir         // Insert the newly created attributes:
659cdf0e10cSrcweir         for ( aIter = aInsDelHints.begin(); aIter != aInsDelHints.end(); ++aIter )
660cdf0e10cSrcweir         {
661cdf0e10cSrcweir             SwpHintsArray::Insert( *aIter );
662cdf0e10cSrcweir             NoteInHistory( *aIter, true );
663cdf0e10cSrcweir         }
664cdf0e10cSrcweir     }
665cdf0e10cSrcweir 
666cdf0e10cSrcweir #ifdef DBG_UTIL
667cdf0e10cSrcweir     if( !rNode.GetDoc()->IsInReading() )
668cdf0e10cSrcweir         CHECK;
669cdf0e10cSrcweir #endif
670cdf0e10cSrcweir 
671cdf0e10cSrcweir     //
672cdf0e10cSrcweir     // 4. Split rNewHint into 1 ... n new hints:
673cdf0e10cSrcweir     //
674cdf0e10cSrcweir     std::set<xub_StrLen> aBounds;
675cdf0e10cSrcweir     aBounds.insert( nThisStart );
676cdf0e10cSrcweir     aBounds.insert( nThisEnd );
677cdf0e10cSrcweir 
678cdf0e10cSrcweir     if ( !bNoLengthAttribute ) // nothing to do for no length attributes
679cdf0e10cSrcweir     {
680cdf0e10cSrcweir         for ( sal_uInt16 i = 0; i < Count(); ++i )
681cdf0e10cSrcweir         {
682cdf0e10cSrcweir             const SwTxtAttr* pOther = GetTextHint(i);
683cdf0e10cSrcweir 
684cdf0e10cSrcweir             if ( RES_TXTATR_CHARFMT != pOther->Which() &&
685cdf0e10cSrcweir                  RES_TXTATR_AUTOFMT != pOther->Which() )
686cdf0e10cSrcweir                 continue;
687cdf0e10cSrcweir 
688cdf0e10cSrcweir             const xub_StrLen nOtherStart = *pOther->GetStart();
68969a74367SOliver-Rainer Wittmann             const xub_StrLen nOtherEnd = *pOther->End();
690cdf0e10cSrcweir 
691cdf0e10cSrcweir             aBounds.insert( nOtherStart );
692cdf0e10cSrcweir             aBounds.insert( nOtherEnd );
693cdf0e10cSrcweir         }
694cdf0e10cSrcweir     }
695cdf0e10cSrcweir 
696cdf0e10cSrcweir     std::set<xub_StrLen>::iterator aStartIter = aBounds.lower_bound( nThisStart );
697cdf0e10cSrcweir     std::set<xub_StrLen>::iterator aEndIter = aBounds.upper_bound( nThisEnd );
698cdf0e10cSrcweir     xub_StrLen nPorStart = *aStartIter;
699cdf0e10cSrcweir     ++aStartIter;
700cdf0e10cSrcweir     bool bDestroyHint = true;
701cdf0e10cSrcweir 
702cdf0e10cSrcweir     //
703cdf0e10cSrcweir     // Insert the 1...n new parts of the new attribute:
704cdf0e10cSrcweir     //
705cdf0e10cSrcweir     while ( aStartIter != aEndIter || bNoLengthAttribute )
706cdf0e10cSrcweir     {
707cdf0e10cSrcweir         ASSERT( bNoLengthAttribute || nPorStart < *aStartIter, "AUTOSTYLES: BuildPortion trouble" )
708cdf0e10cSrcweir 
709cdf0e10cSrcweir         const xub_StrLen nPorEnd = bNoLengthAttribute ? nPorStart : *aStartIter;
710cdf0e10cSrcweir         aInsDelHints.clear();
711cdf0e10cSrcweir 
712cdf0e10cSrcweir         // Get all hints that are in [nPorStart, nPorEnd[:
713cdf0e10cSrcweir         for ( sal_uInt16 i = 0; i < Count(); ++i )
714cdf0e10cSrcweir         {
715cdf0e10cSrcweir             SwTxtAttr *pOther = GetTextHint(i);
716cdf0e10cSrcweir 
717cdf0e10cSrcweir             if ( RES_TXTATR_CHARFMT != pOther->Which() &&
718cdf0e10cSrcweir                  RES_TXTATR_AUTOFMT != pOther->Which() )
719cdf0e10cSrcweir                 continue;
720cdf0e10cSrcweir 
721cdf0e10cSrcweir             const xub_StrLen nOtherStart = *pOther->GetStart();
722cdf0e10cSrcweir 
723cdf0e10cSrcweir             if ( nOtherStart > nPorStart )
724cdf0e10cSrcweir                 break;
725cdf0e10cSrcweir 
726cdf0e10cSrcweir             if ( pOther->GetEnd() && *pOther->GetEnd() == nPorEnd && nOtherStart == nPorStart )
727cdf0e10cSrcweir             {
728cdf0e10cSrcweir                 ASSERT( *pOther->GetEnd() == nPorEnd, "AUTOSTYLES: BuildPortion trouble" )
729cdf0e10cSrcweir                 aInsDelHints.push_back( pOther );
730cdf0e10cSrcweir             }
731cdf0e10cSrcweir         }
732cdf0e10cSrcweir 
733cdf0e10cSrcweir         SwTxtAttr* pNewAttr = 0;
734cdf0e10cSrcweir         if ( RES_TXTATR_CHARFMT == nWhich )
735cdf0e10cSrcweir         {
736cdf0e10cSrcweir             // pNewHint can be inserted after calculating the sort value.
737cdf0e10cSrcweir             // This should ensure, that pNewHint comes behind the already present
738cdf0e10cSrcweir             // character style
739cdf0e10cSrcweir             sal_uInt16 nCharStyleCount = 0;
740cdf0e10cSrcweir             aIter = aInsDelHints.begin();
741cdf0e10cSrcweir             while ( aIter != aInsDelHints.end() )
742cdf0e10cSrcweir             {
743cdf0e10cSrcweir                 if ( RES_TXTATR_CHARFMT == (*aIter)->Which() )
744cdf0e10cSrcweir                 {
745cdf0e10cSrcweir                     // --> FME 2007-02-16 #i74589#
746cdf0e10cSrcweir                     const SwFmtCharFmt& rOtherCharFmt = (*aIter)->GetCharFmt();
747cdf0e10cSrcweir                     const SwFmtCharFmt& rThisCharFmt = rNewHint.GetCharFmt();
748cdf0e10cSrcweir                     const bool bSameCharFmt = rOtherCharFmt.GetCharFmt() == rThisCharFmt.GetCharFmt();
749cdf0e10cSrcweir                     // <--
750cdf0e10cSrcweir 
751cdf0e10cSrcweir                     // --> OD 2009-03-24 #i90311#
752cdf0e10cSrcweir                     // Do not remove existing character format hint during XML import
753cdf0e10cSrcweir                     if ( !rNode.GetDoc()->IsInXMLImport() &&
754cdf0e10cSrcweir                          ( !( nsSetAttrMode::SETATTR_DONTREPLACE & nMode ) ||
755cdf0e10cSrcweir                            bNoLengthAttribute ||
756cdf0e10cSrcweir                            bSameCharFmt ) )
757cdf0e10cSrcweir                     // <--
758cdf0e10cSrcweir                     {
759cdf0e10cSrcweir                         // Remove old hint
760cdf0e10cSrcweir                         Delete( *aIter );
761cdf0e10cSrcweir                         rNode.DestroyAttr( *aIter );
762cdf0e10cSrcweir                     }
763cdf0e10cSrcweir                     else
764cdf0e10cSrcweir                         ++nCharStyleCount;
765cdf0e10cSrcweir                 }
766cdf0e10cSrcweir                 else
767cdf0e10cSrcweir                 {
7686d53c851Smseidel                     // remove all attributes from auto styles, which are explicitly set in
769cdf0e10cSrcweir                     // the new character format:
770cdf0e10cSrcweir                     ASSERT( RES_TXTATR_AUTOFMT == (*aIter)->Which(), "AUTOSTYLES - Misc trouble" )
771cdf0e10cSrcweir                     SwTxtAttr* pOther = *aIter;
772cdf0e10cSrcweir                     boost::shared_ptr<SfxItemSet> pOldStyle = static_cast<const SwFmtAutoFmt&>(pOther->GetAttr()).GetStyleHandle();
773cdf0e10cSrcweir 
774cdf0e10cSrcweir                     // For each attribute in the automatic style check if it
775fb0b81f5Smseidel                     // is also set to the new character style:
776cdf0e10cSrcweir                     SfxItemSet aNewSet( *pOldStyle->GetPool(),
777cdf0e10cSrcweir                         aCharAutoFmtSetRange);
778cdf0e10cSrcweir                     SfxItemIter aItemIter( *pOldStyle );
779cdf0e10cSrcweir                     const SfxPoolItem* pItem = aItemIter.GetCurItem();
780cdf0e10cSrcweir                     while( sal_True )
781cdf0e10cSrcweir                     {
782cdf0e10cSrcweir                         if ( !CharFmt::IsItemIncluded( pItem->Which(), &rNewHint ) )
783cdf0e10cSrcweir                         {
784cdf0e10cSrcweir                             aNewSet.Put( *pItem );
785cdf0e10cSrcweir                         }
786cdf0e10cSrcweir 
787cdf0e10cSrcweir                         if( aItemIter.IsAtEnd() )
788cdf0e10cSrcweir                             break;
789cdf0e10cSrcweir 
790cdf0e10cSrcweir                         pItem = aItemIter.NextItem();
791cdf0e10cSrcweir                     }
792cdf0e10cSrcweir 
793cdf0e10cSrcweir                     // Remove old hint
794cdf0e10cSrcweir                     Delete( pOther );
795cdf0e10cSrcweir                     rNode.DestroyAttr( pOther );
796cdf0e10cSrcweir 
797cdf0e10cSrcweir                     // Create new AutoStyle
798cdf0e10cSrcweir                     if ( aNewSet.Count() )
799cdf0e10cSrcweir                     {
800cdf0e10cSrcweir                         pNewAttr = MakeTxtAttr( *rNode.GetDoc(),
801cdf0e10cSrcweir                                 aNewSet, nPorStart, nPorEnd );
802cdf0e10cSrcweir                         SwpHintsArray::Insert( pNewAttr );
803cdf0e10cSrcweir                         NoteInHistory( pNewAttr, true );
804cdf0e10cSrcweir                     }
805cdf0e10cSrcweir                 }
806cdf0e10cSrcweir                 ++aIter;
807cdf0e10cSrcweir             }
808cdf0e10cSrcweir 
809cdf0e10cSrcweir             // If there is no current hint and start and end of rNewHint
810cdf0e10cSrcweir             // is ok, we do not need to create a new txtattr.
811cdf0e10cSrcweir             if ( nPorStart == nThisStart &&
812cdf0e10cSrcweir                  nPorEnd == nThisEnd &&
813cdf0e10cSrcweir                  !nCharStyleCount )
814cdf0e10cSrcweir             {
815cdf0e10cSrcweir                 pNewAttr = &rNewHint;
816cdf0e10cSrcweir                 bDestroyHint = false;
817cdf0e10cSrcweir             }
818cdf0e10cSrcweir             else
819cdf0e10cSrcweir             {
820cdf0e10cSrcweir                 pNewAttr = MakeTxtAttr( *rNode.GetDoc(), rNewHint.GetAttr(),
821cdf0e10cSrcweir                         nPorStart, nPorEnd );
822cdf0e10cSrcweir                 static_cast<SwTxtCharFmt*>(pNewAttr)->SetSortNumber( nCharStyleCount );
823cdf0e10cSrcweir             }
824cdf0e10cSrcweir         }
825cdf0e10cSrcweir         else
826cdf0e10cSrcweir         {
827cdf0e10cSrcweir             // Find the current autostyle. Mix attributes if necessary.
828cdf0e10cSrcweir             SwTxtAttr* pCurrentAutoStyle = 0;
829cdf0e10cSrcweir             SwTxtAttr* pCurrentCharFmt = 0;
830cdf0e10cSrcweir             aIter = aInsDelHints.begin();
831cdf0e10cSrcweir             while ( aIter != aInsDelHints.end() )
832cdf0e10cSrcweir             {
833cdf0e10cSrcweir                 if ( RES_TXTATR_AUTOFMT == (*aIter)->Which() )
834cdf0e10cSrcweir                     pCurrentAutoStyle = *aIter;
835cdf0e10cSrcweir                 else if ( RES_TXTATR_CHARFMT == (*aIter)->Which() )
836cdf0e10cSrcweir                     pCurrentCharFmt = *aIter;
837cdf0e10cSrcweir                 ++aIter;
838cdf0e10cSrcweir             }
839cdf0e10cSrcweir 
840cdf0e10cSrcweir             boost::shared_ptr<SfxItemSet> pNewStyle = static_cast<const SwFmtAutoFmt&>(rNewHint.GetAttr()).GetStyleHandle();
841cdf0e10cSrcweir             if ( pCurrentAutoStyle )
842cdf0e10cSrcweir             {
843cdf0e10cSrcweir                 boost::shared_ptr<SfxItemSet> pCurrentStyle = static_cast<const SwFmtAutoFmt&>(pCurrentAutoStyle->GetAttr()).GetStyleHandle();
844cdf0e10cSrcweir 
845cdf0e10cSrcweir                 // Merge attributes
846cdf0e10cSrcweir                 SfxItemSet aNewSet( *pCurrentStyle );
847cdf0e10cSrcweir                 aNewSet.Put( *pNewStyle );
848cdf0e10cSrcweir 
849cdf0e10cSrcweir                 // --> FME 2007-4-11 #i75750# Remove attributes already set at whole paragraph
850cdf0e10cSrcweir                 // --> FME 2007-09-24 #i81764# This should not be applied for no length attributes!!! <--
851cdf0e10cSrcweir                 if ( !bNoLengthAttribute && rNode.HasSwAttrSet() && aNewSet.Count() )
852cdf0e10cSrcweir                 {
853cdf0e10cSrcweir                     SfxItemIter aIter2( aNewSet );
854cdf0e10cSrcweir                     const SfxPoolItem* pItem = aIter2.GetCurItem();
855cdf0e10cSrcweir                     const SfxItemSet& rWholeParaAttrSet = rNode.GetSwAttrSet();
856cdf0e10cSrcweir 
857cdf0e10cSrcweir                     do
858cdf0e10cSrcweir                     {
859cdf0e10cSrcweir                         const SfxPoolItem* pTmpItem = 0;
860cdf0e10cSrcweir                         if ( SFX_ITEM_SET == rWholeParaAttrSet.GetItemState( pItem->Which(), sal_False, &pTmpItem ) &&
861cdf0e10cSrcweir                              pTmpItem == pItem )
862cdf0e10cSrcweir                         {
863cdf0e10cSrcweir                             // Do not clear item if the attribute is set in a character format:
864cdf0e10cSrcweir                             if ( !pCurrentCharFmt || 0 == CharFmt::GetItem( *pCurrentCharFmt, pItem->Which() ) )
865cdf0e10cSrcweir                                 aNewSet.ClearItem( pItem->Which() );
866cdf0e10cSrcweir                         }
867cdf0e10cSrcweir                     }
868cdf0e10cSrcweir                     while (!aIter2.IsAtEnd() && 0 != (pItem = aIter2.NextItem()));
869cdf0e10cSrcweir                 }
870cdf0e10cSrcweir                 // <--
871cdf0e10cSrcweir 
872cdf0e10cSrcweir                 // Remove old hint
873cdf0e10cSrcweir                 Delete( pCurrentAutoStyle );
874cdf0e10cSrcweir                 rNode.DestroyAttr( pCurrentAutoStyle );
875cdf0e10cSrcweir 
876cdf0e10cSrcweir                 // Create new AutoStyle
877cdf0e10cSrcweir                 if ( aNewSet.Count() )
878cdf0e10cSrcweir                     pNewAttr = MakeTxtAttr( *rNode.GetDoc(), aNewSet,
879cdf0e10cSrcweir                             nPorStart, nPorEnd );
880cdf0e10cSrcweir             }
881cdf0e10cSrcweir             else
882cdf0e10cSrcweir             {
883cdf0e10cSrcweir                 // Remove any attributes which are already set at the whole paragraph:
884cdf0e10cSrcweir                 bool bOptimizeAllowed = true;
885cdf0e10cSrcweir 
886cdf0e10cSrcweir                 SfxItemSet* pNewSet = 0;
887cdf0e10cSrcweir                 // --> FME 2007-4-11 #i75750# Remove attributes already set at whole paragraph
888cdf0e10cSrcweir                 // --> FME 2007-09-24 #i81764# This should not be applied for no length attributes!!! <--
889cdf0e10cSrcweir                 if ( !bNoLengthAttribute && rNode.HasSwAttrSet() && pNewStyle->Count() )
890cdf0e10cSrcweir                 {
891cdf0e10cSrcweir                     SfxItemIter aIter2( *pNewStyle );
892cdf0e10cSrcweir                     const SfxPoolItem* pItem = aIter2.GetCurItem();
893cdf0e10cSrcweir                     const SfxItemSet& rWholeParaAttrSet = rNode.GetSwAttrSet();
894cdf0e10cSrcweir 
895cdf0e10cSrcweir                     do
896cdf0e10cSrcweir                     {
897cdf0e10cSrcweir                         const SfxPoolItem* pTmpItem = 0;
898cdf0e10cSrcweir                         if ( SFX_ITEM_SET == rWholeParaAttrSet.GetItemState( pItem->Which(), sal_False, &pTmpItem ) &&
899cdf0e10cSrcweir                              pTmpItem == pItem )
900cdf0e10cSrcweir                         {
901cdf0e10cSrcweir                             // Do not clear item if the attribute is set in a character format:
902cdf0e10cSrcweir                             if ( !pCurrentCharFmt || 0 == CharFmt::GetItem( *pCurrentCharFmt, pItem->Which() ) )
903cdf0e10cSrcweir                             {
904cdf0e10cSrcweir                                 if ( !pNewSet )
905cdf0e10cSrcweir                                     pNewSet = pNewStyle->Clone( sal_True );
906cdf0e10cSrcweir                                 pNewSet->ClearItem( pItem->Which() );
907cdf0e10cSrcweir                             }
908cdf0e10cSrcweir                         }
909cdf0e10cSrcweir                     }
910cdf0e10cSrcweir                     while (!aIter2.IsAtEnd() && 0 != (pItem = aIter2.NextItem()));
911cdf0e10cSrcweir 
912cdf0e10cSrcweir                     if ( pNewSet )
913cdf0e10cSrcweir                     {
914cdf0e10cSrcweir                         bOptimizeAllowed = false;
915cdf0e10cSrcweir                         if ( pNewSet->Count() )
916cdf0e10cSrcweir                             pNewStyle = rNode.getIDocumentStyleAccess().getAutomaticStyle( *pNewSet, IStyleAccess::AUTO_STYLE_CHAR );
917cdf0e10cSrcweir                         else
918cdf0e10cSrcweir                             pNewStyle.reset();
919cdf0e10cSrcweir 
920cdf0e10cSrcweir                         delete pNewSet;
921cdf0e10cSrcweir                     }
922cdf0e10cSrcweir                 }
923cdf0e10cSrcweir                 // <--
924cdf0e10cSrcweir 
925cdf0e10cSrcweir                 // Create new AutoStyle
926cdf0e10cSrcweir                 // If there is no current hint and start and end of rNewHint
927cdf0e10cSrcweir                 // is ok, we do not need to create a new txtattr.
928cdf0e10cSrcweir                 if ( bOptimizeAllowed &&
929cdf0e10cSrcweir                      nPorStart == nThisStart &&
930cdf0e10cSrcweir                      nPorEnd == nThisEnd )
931cdf0e10cSrcweir                 {
932cdf0e10cSrcweir                     pNewAttr = &rNewHint;
933cdf0e10cSrcweir                     bDestroyHint = false;
934cdf0e10cSrcweir                 }
935cdf0e10cSrcweir                 else if ( pNewStyle.get() )
936cdf0e10cSrcweir                 {
937cdf0e10cSrcweir                     pNewAttr = MakeTxtAttr( *rNode.GetDoc(), *pNewStyle,
938cdf0e10cSrcweir                             nPorStart, nPorEnd );
939cdf0e10cSrcweir                 }
940cdf0e10cSrcweir             }
941cdf0e10cSrcweir         }
942cdf0e10cSrcweir 
943cdf0e10cSrcweir         if ( pNewAttr )
944cdf0e10cSrcweir         {
945cdf0e10cSrcweir             SwpHintsArray::Insert( pNewAttr );
946cdf0e10cSrcweir //            if ( bDestroyHint )
947cdf0e10cSrcweir                 NoteInHistory( pNewAttr, true );
948cdf0e10cSrcweir         }
949cdf0e10cSrcweir 
950cdf0e10cSrcweir         if ( !bNoLengthAttribute )
951cdf0e10cSrcweir         {
952cdf0e10cSrcweir             nPorStart = *aStartIter;
953cdf0e10cSrcweir             ++aStartIter;
954cdf0e10cSrcweir         }
955cdf0e10cSrcweir         else
956cdf0e10cSrcweir             break;
957cdf0e10cSrcweir     }
958cdf0e10cSrcweir 
959cdf0e10cSrcweir     if ( bDestroyHint )
960cdf0e10cSrcweir         rNode.DestroyAttr( &rNewHint );
961cdf0e10cSrcweir }
962cdf0e10cSrcweir 
963cdf0e10cSrcweir /*************************************************************************
964cdf0e10cSrcweir  *						SwTxtNode::MakeTxtAttr()
965cdf0e10cSrcweir  *************************************************************************/
966cdf0e10cSrcweir 
MakeRedlineTxtAttr(SwDoc & rDoc,SfxPoolItem & rAttr)967cdf0e10cSrcweir SwTxtAttr* MakeRedlineTxtAttr( SwDoc & rDoc, SfxPoolItem & rAttr )
968cdf0e10cSrcweir {
969cdf0e10cSrcweir     // this is intended _only_ for special-purpose redline attributes!
970cdf0e10cSrcweir     switch (rAttr.Which())
971cdf0e10cSrcweir     {
972cdf0e10cSrcweir         case RES_CHRATR_COLOR:
973cdf0e10cSrcweir         case RES_CHRATR_WEIGHT:
974cdf0e10cSrcweir         case RES_CHRATR_CJK_WEIGHT:
975cdf0e10cSrcweir         case RES_CHRATR_CTL_WEIGHT:
976cdf0e10cSrcweir         case RES_CHRATR_POSTURE:
977cdf0e10cSrcweir         case RES_CHRATR_CJK_POSTURE:
978cdf0e10cSrcweir         case RES_CHRATR_CTL_POSTURE:
979cdf0e10cSrcweir         case RES_CHRATR_UNDERLINE:
980cdf0e10cSrcweir         case RES_CHRATR_CROSSEDOUT:
981cdf0e10cSrcweir         case RES_CHRATR_CASEMAP:
982cdf0e10cSrcweir         case RES_CHRATR_BACKGROUND:
983cdf0e10cSrcweir             break;
984cdf0e10cSrcweir         default:
985cdf0e10cSrcweir             ASSERT(false, "unsupported redline attribute");
986cdf0e10cSrcweir             break;
987cdf0e10cSrcweir     }
988cdf0e10cSrcweir 
989cdf0e10cSrcweir     // Put new attribute into pool
990cdf0e10cSrcweir     // FIXME: this const_cast is evil!
991cdf0e10cSrcweir     SfxPoolItem& rNew =
992cdf0e10cSrcweir         const_cast<SfxPoolItem&>( rDoc.GetAttrPool().Put( rAttr ) );
993cdf0e10cSrcweir     return new SwTxtAttrEnd( rNew, 0, 0 );
994cdf0e10cSrcweir }
995cdf0e10cSrcweir 
996cdf0e10cSrcweir // create new text attribute
MakeTxtAttr(SwDoc & rDoc,SfxPoolItem & rAttr,xub_StrLen const nStt,xub_StrLen const nEnd,CopyOrNew_t const bIsCopy,SwTxtNode * const pTxtNode)99769a74367SOliver-Rainer Wittmann SwTxtAttr* MakeTxtAttr(
99869a74367SOliver-Rainer Wittmann     SwDoc & rDoc,
99969a74367SOliver-Rainer Wittmann     SfxPoolItem& rAttr,
100069a74367SOliver-Rainer Wittmann     xub_StrLen const nStt,
100169a74367SOliver-Rainer Wittmann     xub_StrLen const nEnd,
100269a74367SOliver-Rainer Wittmann     CopyOrNew_t const bIsCopy,
100369a74367SOliver-Rainer Wittmann     SwTxtNode *const pTxtNode )
1004cdf0e10cSrcweir {
1005cdf0e10cSrcweir     if ( isCHRATR(rAttr.Which()) )
1006cdf0e10cSrcweir     {
1007cdf0e10cSrcweir         // Somebody wants to build a SwTxtAttr for a character attribute.
1008cdf0e10cSrcweir         // Sorry, this is not allowed any longer.
1009cdf0e10cSrcweir         // You'll get a brand new autostyle attribute:
1010cdf0e10cSrcweir         SfxItemSet aItemSet( rDoc.GetAttrPool(),
1011cdf0e10cSrcweir                 RES_CHRATR_BEGIN, RES_CHRATR_END );
1012cdf0e10cSrcweir         aItemSet.Put( rAttr );
1013cdf0e10cSrcweir         return MakeTxtAttr( rDoc, aItemSet, nStt, nEnd );
1014cdf0e10cSrcweir     }
1015cdf0e10cSrcweir     else if ( RES_TXTATR_AUTOFMT == rAttr.Which() &&
1016cdf0e10cSrcweir               static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle()->
1017cdf0e10cSrcweir                 GetPool() != &rDoc.GetAttrPool() )
1018cdf0e10cSrcweir     {
1019cdf0e10cSrcweir         // If the attribute is an auto-style which refers to a pool that is
1020cdf0e10cSrcweir         // different from rDoc's pool, we have to correct this:
1021cdf0e10cSrcweir         const StylePool::SfxItemSet_Pointer_t pAutoStyle = static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle();
1022cdf0e10cSrcweir         ::std::auto_ptr<const SfxItemSet> pNewSet(
1023cdf0e10cSrcweir                 pAutoStyle->SfxItemSet::Clone( sal_True, &rDoc.GetAttrPool() ));
1024cdf0e10cSrcweir         SwTxtAttr* pNew = MakeTxtAttr( rDoc, *pNewSet, nStt, nEnd );
1025cdf0e10cSrcweir         return pNew;
1026cdf0e10cSrcweir     }
1027cdf0e10cSrcweir 
1028cdf0e10cSrcweir     // Put new attribute into pool
1029cdf0e10cSrcweir     // FIXME: this const_cast is evil!
1030cdf0e10cSrcweir     SfxPoolItem& rNew =
1031cdf0e10cSrcweir         const_cast<SfxPoolItem&>( rDoc.GetAttrPool().Put( rAttr ) );
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir 	SwTxtAttr* pNew = 0;
1034cdf0e10cSrcweir 	switch( rNew.Which() )
1035cdf0e10cSrcweir 	{
1036cdf0e10cSrcweir     case RES_TXTATR_CHARFMT:
1037cdf0e10cSrcweir 		{
1038cdf0e10cSrcweir 			SwFmtCharFmt &rFmtCharFmt = (SwFmtCharFmt&) rNew;
1039cdf0e10cSrcweir 			if( !rFmtCharFmt.GetCharFmt() )
1040cdf0e10cSrcweir             {
1041cdf0e10cSrcweir                 rFmtCharFmt.SetCharFmt( rDoc.GetDfltCharFmt() );
1042cdf0e10cSrcweir             }
1043cdf0e10cSrcweir 
1044cdf0e10cSrcweir 			pNew = new SwTxtCharFmt( rFmtCharFmt, nStt, nEnd );
1045cdf0e10cSrcweir 		}
1046cdf0e10cSrcweir 		break;
1047cdf0e10cSrcweir 	case RES_TXTATR_INETFMT:
1048cdf0e10cSrcweir 		pNew = new SwTxtINetFmt( (SwFmtINetFmt&)rNew, nStt, nEnd );
1049cdf0e10cSrcweir 		break;
1050dec99bbdSOliver-Rainer Wittmann 
105169a74367SOliver-Rainer Wittmann     case RES_TXTATR_FIELD:
10527887cc2eSOliver-Rainer Wittmann         pNew =
10537887cc2eSOliver-Rainer Wittmann             new SwTxtFld( static_cast<SwFmtFld &>(rNew), nStt, rDoc.IsClipBoard() );
105469a74367SOliver-Rainer Wittmann         break;
1055dec99bbdSOliver-Rainer Wittmann 
1056dec99bbdSOliver-Rainer Wittmann     case RES_TXTATR_ANNOTATION:
1057dec99bbdSOliver-Rainer Wittmann         {
10587887cc2eSOliver-Rainer Wittmann             pNew =
10597887cc2eSOliver-Rainer Wittmann                 new SwTxtAnnotationFld( static_cast<SwFmtFld &>(rNew), nStt, rDoc.IsClipBoard() );
1060dec99bbdSOliver-Rainer Wittmann             if ( bIsCopy == COPY )
1061dec99bbdSOliver-Rainer Wittmann             {
1062dec99bbdSOliver-Rainer Wittmann                 // On copy of the annotation field do not keep the annotated text range by removing
1063dec99bbdSOliver-Rainer Wittmann                 // the relation to its annotation mark (relation established via annotation field's name).
1064dec99bbdSOliver-Rainer Wittmann                 // If the annotation mark is also copied, the relation and thus the annotated text range will be reestablished,
1065dec99bbdSOliver-Rainer Wittmann                 // when the annotation mark is created and inserted into the document.
1066dec99bbdSOliver-Rainer Wittmann                 const_cast<SwPostItField*>(dynamic_cast< const SwPostItField* >(pNew->GetFmtFld().GetField()))->SetName( String() );
1067dec99bbdSOliver-Rainer Wittmann             }
1068dec99bbdSOliver-Rainer Wittmann         }
1069dec99bbdSOliver-Rainer Wittmann         break;
1070dec99bbdSOliver-Rainer Wittmann 
107169a74367SOliver-Rainer Wittmann     case RES_TXTATR_INPUTFIELD:
10727887cc2eSOliver-Rainer Wittmann         pNew =
10737887cc2eSOliver-Rainer Wittmann             new SwTxtInputFld( static_cast<SwFmtFld &>(rNew), nStt, nEnd, rDoc.IsClipBoard() );
107469a74367SOliver-Rainer Wittmann         break;
1075dec99bbdSOliver-Rainer Wittmann 
1076cdf0e10cSrcweir 	case RES_TXTATR_FLYCNT:
1077cdf0e10cSrcweir 		{
1078cdf0e10cSrcweir 			// erst hier wird das Frame-Format kopiert (mit Inhalt) !!
1079cdf0e10cSrcweir 			pNew = new SwTxtFlyCnt( (SwFmtFlyCnt&)rNew, nStt );
1080cdf0e10cSrcweir 			// Kopie von einem Text-Attribut
1081cdf0e10cSrcweir             if ( static_cast<const SwFmtFlyCnt &>(rAttr).GetTxtFlyCnt() )
1082cdf0e10cSrcweir             {
1083cdf0e10cSrcweir                 // then the format must be copied
1084cdf0e10cSrcweir                 static_cast<SwTxtFlyCnt *>(pNew)->CopyFlyFmt( &rDoc );
1085cdf0e10cSrcweir             }
1086cdf0e10cSrcweir         }
1087cdf0e10cSrcweir         break;
1088cdf0e10cSrcweir 	case RES_TXTATR_FTN:
1089cdf0e10cSrcweir 		pNew = new SwTxtFtn( (SwFmtFtn&)rNew, nStt );
1090cdf0e10cSrcweir 		// ggfs. SeqNo kopieren
1091cdf0e10cSrcweir 		if( ((SwFmtFtn&)rAttr).GetTxtFtn() )
1092cdf0e10cSrcweir 			((SwTxtFtn*)pNew)->SetSeqNo( ((SwFmtFtn&)rAttr).GetTxtFtn()->GetSeqRefNo() );
1093cdf0e10cSrcweir 		break;
1094cdf0e10cSrcweir 	case RES_TXTATR_REFMARK:
1095cdf0e10cSrcweir 		pNew = nStt == nEnd
1096cdf0e10cSrcweir 				? new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt )
1097cdf0e10cSrcweir 				: new SwTxtRefMark( (SwFmtRefMark&)rNew, nStt, &nEnd );
1098cdf0e10cSrcweir 		break;
1099cdf0e10cSrcweir 	case RES_TXTATR_TOXMARK:
1100cdf0e10cSrcweir 		pNew = new SwTxtTOXMark( (SwTOXMark&)rNew, nStt, &nEnd );
1101cdf0e10cSrcweir 		break;
1102cdf0e10cSrcweir 	case RES_TXTATR_CJK_RUBY:
1103cdf0e10cSrcweir 		pNew = new SwTxtRuby( (SwFmtRuby&)rNew, nStt, nEnd );
1104cdf0e10cSrcweir 		break;
1105cdf0e10cSrcweir     case RES_TXTATR_META:
1106cdf0e10cSrcweir     case RES_TXTATR_METAFIELD:
1107cdf0e10cSrcweir         pNew = SwTxtMeta::CreateTxtMeta( rDoc.GetMetaFieldManager(), pTxtNode,
1108cdf0e10cSrcweir                 static_cast<SwFmtMeta&>(rNew), nStt, nEnd, bIsCopy );
1109cdf0e10cSrcweir         break;
1110cdf0e10cSrcweir     default:
1111cdf0e10cSrcweir         ASSERT(RES_TXTATR_AUTOFMT == rNew.Which(), "unknown attribute");
1112cdf0e10cSrcweir         pNew = new SwTxtAttrEnd( rNew, nStt, nEnd );
1113cdf0e10cSrcweir         break;
1114cdf0e10cSrcweir     }
1115cdf0e10cSrcweir 
1116cdf0e10cSrcweir     return pNew;
1117cdf0e10cSrcweir }
1118cdf0e10cSrcweir 
MakeTxtAttr(SwDoc & rDoc,const SfxItemSet & rSet,xub_StrLen nStt,xub_StrLen nEnd)1119cdf0e10cSrcweir SwTxtAttr* MakeTxtAttr( SwDoc & rDoc, const SfxItemSet& rSet,
1120cdf0e10cSrcweir                         xub_StrLen nStt, xub_StrLen nEnd )
1121cdf0e10cSrcweir {
1122cdf0e10cSrcweir     IStyleAccess& rStyleAccess = rDoc.GetIStyleAccess();
1123cdf0e10cSrcweir     const StylePool::SfxItemSet_Pointer_t pAutoStyle = rStyleAccess.getAutomaticStyle( rSet, IStyleAccess::AUTO_STYLE_CHAR );
1124cdf0e10cSrcweir     SwFmtAutoFmt aNewAutoFmt;
1125cdf0e10cSrcweir     aNewAutoFmt.SetStyleHandle( pAutoStyle );
1126cdf0e10cSrcweir     SwTxtAttr* pNew = MakeTxtAttr( rDoc, aNewAutoFmt, nStt, nEnd );
1127cdf0e10cSrcweir     return pNew;
1128cdf0e10cSrcweir }
1129cdf0e10cSrcweir 
1130cdf0e10cSrcweir 
1131cdf0e10cSrcweir // loesche das Text-Attribut (muss beim Pool abgemeldet werden!)
DestroyAttr(SwTxtAttr * pAttr)1132cdf0e10cSrcweir void SwTxtNode::DestroyAttr( SwTxtAttr* pAttr )
1133cdf0e10cSrcweir {
1134cdf0e10cSrcweir 	if( pAttr )
1135cdf0e10cSrcweir 	{
1136cdf0e10cSrcweir 		// einige Sachen muessen vorm Loeschen der "Format-Attribute" erfolgen
1137cdf0e10cSrcweir 		SwDoc* pDoc = GetDoc();
1138cdf0e10cSrcweir 		sal_uInt16 nDelMsg = 0;
1139cdf0e10cSrcweir 		switch( pAttr->Which() )
1140cdf0e10cSrcweir 		{
1141cdf0e10cSrcweir 		case RES_TXTATR_FLYCNT:
1142cdf0e10cSrcweir 			{
1143cdf0e10cSrcweir 				// siehe auch die Anmerkung "Loeschen von Formaten
1144cdf0e10cSrcweir 				// zeichengebundener Frames" in fesh.cxx, SwFEShell::DelFmt()
1145cdf0e10cSrcweir 				SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt();
1146cdf0e10cSrcweir 				if( pFmt )		// vom Undo auf 0 gesetzt ??
1147cdf0e10cSrcweir 					pDoc->DelLayoutFmt( (SwFlyFrmFmt*)pFmt );
1148cdf0e10cSrcweir 			}
1149cdf0e10cSrcweir 			break;
1150cdf0e10cSrcweir 
1151cdf0e10cSrcweir         case RES_CHRATR_HIDDEN:
1152cdf0e10cSrcweir             SetCalcHiddenCharFlags();
1153cdf0e10cSrcweir             break;
1154cdf0e10cSrcweir 
1155cdf0e10cSrcweir 		case RES_TXTATR_FTN:
1156cdf0e10cSrcweir 			((SwTxtFtn*)pAttr)->SetStartNode( 0 );
1157cdf0e10cSrcweir 			nDelMsg = RES_FOOTNOTE_DELETED;
1158cdf0e10cSrcweir 			break;
1159cdf0e10cSrcweir 
1160cdf0e10cSrcweir 		case RES_TXTATR_FIELD:
1161dec99bbdSOliver-Rainer Wittmann 		case RES_TXTATR_ANNOTATION:
116269a74367SOliver-Rainer Wittmann 		case RES_TXTATR_INPUTFIELD:
1163cdf0e10cSrcweir 			if( !pDoc->IsInDtor() )
1164cdf0e10cSrcweir 			{
1165cdf0e10cSrcweir 				// Wenn wir ein HiddenParaField sind, dann muessen wir
1166cdf0e10cSrcweir 				// ggf. fuer eine Neuberechnung des Visible-Flags sorgen.
1167c0286415SOliver-Rainer Wittmann 				const SwField* pFld = pAttr->GetFmtFld().GetField();
1168cdf0e10cSrcweir 
1169cdf0e10cSrcweir 				//JP 06-08-95: DDE-Felder bilden eine Ausnahme
1170cdf0e10cSrcweir 				ASSERT( RES_DDEFLD == pFld->GetTyp()->Which() ||
1171cdf0e10cSrcweir 						this == ((SwTxtFld*)pAttr)->GetpTxtNode(),
1172cdf0e10cSrcweir 						"Wo steht denn dieses Feld?" )
1173cdf0e10cSrcweir 
1174cdf0e10cSrcweir 				// bestimmte Felder mussen am Doc das Calculations-Flag updaten
1175cdf0e10cSrcweir 				switch( pFld->GetTyp()->Which() )
1176cdf0e10cSrcweir 				{
1177cdf0e10cSrcweir 				case RES_HIDDENPARAFLD:
1178cdf0e10cSrcweir                     SetCalcHiddenParaField();
1179cdf0e10cSrcweir 					// kein break !
1180cdf0e10cSrcweir 				case RES_DBSETNUMBERFLD:
1181cdf0e10cSrcweir 				case RES_GETEXPFLD:
1182cdf0e10cSrcweir 				case RES_DBFLD:
1183cdf0e10cSrcweir 				case RES_SETEXPFLD:
1184cdf0e10cSrcweir 				case RES_HIDDENTXTFLD:
1185cdf0e10cSrcweir 				case RES_DBNUMSETFLD:
1186cdf0e10cSrcweir 				case RES_DBNEXTSETFLD:
1187cdf0e10cSrcweir 					if( !pDoc->IsNewFldLst() && GetNodes().IsDocNodes() )
1188cdf0e10cSrcweir 						pDoc->InsDelFldInFldLst( sal_False, *(SwTxtFld*)pAttr );
1189cdf0e10cSrcweir 					break;
1190cdf0e10cSrcweir 				case RES_DDEFLD:
1191cdf0e10cSrcweir 					if( GetNodes().IsDocNodes() &&
1192cdf0e10cSrcweir 						((SwTxtFld*)pAttr)->GetpTxtNode() )
1193cdf0e10cSrcweir 						((SwDDEFieldType*)pFld->GetTyp())->DecRefCnt();
1194cdf0e10cSrcweir 					break;
1195cdf0e10cSrcweir 				case RES_POSTITFLD:
1196cdf0e10cSrcweir 					{
1197c0286415SOliver-Rainer Wittmann 						const_cast<SwFmtFld&>(pAttr->GetFmtFld()).Broadcast( SwFmtFldHint( &((SwTxtFld*)pAttr)->GetFmtFld(), SWFMTFLD_REMOVED ) );
1198cdf0e10cSrcweir 						break;
1199cdf0e10cSrcweir 					}
1200cdf0e10cSrcweir 				}
1201cdf0e10cSrcweir 			}
1202cdf0e10cSrcweir 			nDelMsg = RES_FIELD_DELETED;
1203cdf0e10cSrcweir 			break;
1204cdf0e10cSrcweir 
1205cdf0e10cSrcweir 		case RES_TXTATR_TOXMARK:
1206cdf0e10cSrcweir             static_cast<SwTOXMark&>(pAttr->GetAttr()).InvalidateTOXMark();
1207cdf0e10cSrcweir 			break;
1208cdf0e10cSrcweir 
1209cdf0e10cSrcweir 		case RES_TXTATR_REFMARK:
1210cdf0e10cSrcweir 			nDelMsg = RES_REFMARK_DELETED;
1211cdf0e10cSrcweir 			break;
1212cdf0e10cSrcweir 
1213cdf0e10cSrcweir         case RES_TXTATR_META:
1214cdf0e10cSrcweir         case RES_TXTATR_METAFIELD:
1215cdf0e10cSrcweir             static_cast<SwTxtMeta*>(pAttr)->ChgTxtNode(0);
1216cdf0e10cSrcweir             break;
1217cdf0e10cSrcweir 
1218cdf0e10cSrcweir         default:
1219cdf0e10cSrcweir             break;
1220cdf0e10cSrcweir 		}
1221cdf0e10cSrcweir 
1222cdf0e10cSrcweir 		if( nDelMsg && !pDoc->IsInDtor() && GetNodes().IsDocNodes() )
1223cdf0e10cSrcweir 		{
1224cdf0e10cSrcweir 			SwPtrMsgPoolItem aMsgHint( nDelMsg, (void*)&pAttr->GetAttr() );
1225cdf0e10cSrcweir 			pDoc->GetUnoCallBack()->ModifyNotification( &aMsgHint, &aMsgHint );
1226cdf0e10cSrcweir 		}
1227cdf0e10cSrcweir 
1228cdf0e10cSrcweir         SwTxtAttr::Destroy( pAttr, pDoc->GetAttrPool() );
1229cdf0e10cSrcweir     }
1230cdf0e10cSrcweir }
1231cdf0e10cSrcweir 
1232cdf0e10cSrcweir /*************************************************************************
1233cdf0e10cSrcweir  *						SwTxtNode::Insert()
1234cdf0e10cSrcweir  *************************************************************************/
1235cdf0e10cSrcweir 
InsertItem(SfxPoolItem & rAttr,const xub_StrLen nStart,const xub_StrLen nEnd,const SetAttrMode nMode)1236dec99bbdSOliver-Rainer Wittmann SwTxtAttr* SwTxtNode::InsertItem(
1237dec99bbdSOliver-Rainer Wittmann     SfxPoolItem& rAttr,
1238dec99bbdSOliver-Rainer Wittmann     const xub_StrLen nStart,
1239dec99bbdSOliver-Rainer Wittmann     const xub_StrLen nEnd,
1240dec99bbdSOliver-Rainer Wittmann     const SetAttrMode nMode )
1241cdf0e10cSrcweir {
1242cdf0e10cSrcweir    // character attributes will be inserted as automatic styles:
1243cdf0e10cSrcweir     ASSERT( !isCHRATR(rAttr.Which()), "AUTOSTYLES - "
1244cdf0e10cSrcweir         "SwTxtNode::InsertItem should not be called with character attributes");
1245cdf0e10cSrcweir 
1246dec99bbdSOliver-Rainer Wittmann     SwTxtAttr *const pNew =
1247dec99bbdSOliver-Rainer Wittmann         MakeTxtAttr(
1248dec99bbdSOliver-Rainer Wittmann             *GetDoc(),
1249dec99bbdSOliver-Rainer Wittmann             rAttr,
1250dec99bbdSOliver-Rainer Wittmann             nStart,
1251dec99bbdSOliver-Rainer Wittmann             nEnd,
1252dec99bbdSOliver-Rainer Wittmann             (nMode & nsSetAttrMode::SETATTR_IS_COPY) ? COPY : NEW,
1253dec99bbdSOliver-Rainer Wittmann             this );
1254cdf0e10cSrcweir 
1255cdf0e10cSrcweir     if ( pNew )
1256cdf0e10cSrcweir     {
1257cdf0e10cSrcweir         const bool bSuccess( InsertHint( pNew, nMode ) );
1258cdf0e10cSrcweir         // N.B.: also check that the hint is actually in the hints array,
125986e1cf34SPedro Giffuni         // because hints of certain types may be merged after successful
1260cdf0e10cSrcweir         // insertion, and thus destroyed!
1261cdf0e10cSrcweir         if (!bSuccess || ( USHRT_MAX == m_pSwpHints->GetPos( pNew ) ))
1262cdf0e10cSrcweir         {
1263cdf0e10cSrcweir             return 0;
1264cdf0e10cSrcweir         }
1265cdf0e10cSrcweir     }
1266cdf0e10cSrcweir 
1267cdf0e10cSrcweir     return pNew;
1268cdf0e10cSrcweir }
1269cdf0e10cSrcweir 
1270cdf0e10cSrcweir // take ownership of pAttr; if insertion fails, delete pAttr
InsertHint(SwTxtAttr * const pAttr,const SetAttrMode nMode)1271cdf0e10cSrcweir bool SwTxtNode::InsertHint( SwTxtAttr * const pAttr, const SetAttrMode nMode )
1272cdf0e10cSrcweir {
127369a74367SOliver-Rainer Wittmann     bool bHiddenPara = false;
1274cdf0e10cSrcweir 
1275cdf0e10cSrcweir     ASSERT( pAttr && *pAttr->GetStart() <= Len(), "StartIdx out of bounds!" );
1276cdf0e10cSrcweir     ASSERT( !pAttr->GetEnd() || (*pAttr->GetEnd() <= Len()),
1277cdf0e10cSrcweir             "EndIdx out of bounds!" );
1278cdf0e10cSrcweir 
1279cdf0e10cSrcweir     // translate from SetAttrMode to InsertMode (for hints with CH_TXTATR)
1280cdf0e10cSrcweir     const enum IDocumentContentOperations::InsertFlags nInsertFlags =
1281cdf0e10cSrcweir         (nMode & nsSetAttrMode::SETATTR_FORCEHINTEXPAND)
1282cdf0e10cSrcweir         ? static_cast<IDocumentContentOperations::InsertFlags>(
1283cdf0e10cSrcweir                 IDocumentContentOperations::INS_FORCEHINTEXPAND |
1284cdf0e10cSrcweir                 IDocumentContentOperations::INS_EMPTYEXPAND)
1285cdf0e10cSrcweir         : IDocumentContentOperations::INS_EMPTYEXPAND;
1286cdf0e10cSrcweir 
1287cdf0e10cSrcweir     // need this after TryInsertHint, when pAttr may be deleted
1288cdf0e10cSrcweir     const xub_StrLen nStart( *pAttr->GetStart() );
1289cdf0e10cSrcweir     const bool bDummyChar( pAttr->HasDummyChar() );
1290cdf0e10cSrcweir     if (bDummyChar)
1291cdf0e10cSrcweir     {
129269a74367SOliver-Rainer Wittmann         sal_uInt16 nInsMode = nMode;
129369a74367SOliver-Rainer Wittmann         switch( pAttr->Which() )
129469a74367SOliver-Rainer Wittmann         {
129569a74367SOliver-Rainer Wittmann         case RES_TXTATR_FLYCNT:
129669a74367SOliver-Rainer Wittmann             {
129769a74367SOliver-Rainer Wittmann                 SwTxtFlyCnt *pFly = (SwTxtFlyCnt *)pAttr;
129869a74367SOliver-Rainer Wittmann                 SwFrmFmt* pFmt = pAttr->GetFlyCnt().GetFrmFmt();
129969a74367SOliver-Rainer Wittmann                 if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
130069a74367SOliver-Rainer Wittmann                 {
130169a74367SOliver-Rainer Wittmann                     // Wir muessen zuerst einfuegen, da in SetAnchor()
130269a74367SOliver-Rainer Wittmann                     // dem FlyFrm GetStart() uebermittelt wird.
130369a74367SOliver-Rainer Wittmann                     //JP 11.05.98: falls das Anker-Attribut schon richtig
130469a74367SOliver-Rainer Wittmann                     // gesetzt ist, dann korrigiere dieses nach dem Einfuegen
130569a74367SOliver-Rainer Wittmann                     // des Zeichens. Sonst muesste das immer  ausserhalb
130669a74367SOliver-Rainer Wittmann                     // erfolgen (Fehleranfaellig !)
130769a74367SOliver-Rainer Wittmann                     const SwFmtAnchor* pAnchor = 0;
130869a74367SOliver-Rainer Wittmann                     pFmt->GetItemState( RES_ANCHOR, sal_False,
130969a74367SOliver-Rainer Wittmann                         (const SfxPoolItem**)&pAnchor );
131069a74367SOliver-Rainer Wittmann 
131169a74367SOliver-Rainer Wittmann                     SwIndex aIdx( this, *pAttr->GetStart() );
1312cdf0e10cSrcweir                     const sal_Unicode c = GetCharOfTxtAttr(*pAttr);
1313cdf0e10cSrcweir                     InsertText( c, aIdx, nInsertFlags );
131469a74367SOliver-Rainer Wittmann                     nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
1315cdf0e10cSrcweir 
1316cdf0e10cSrcweir                     if (pAnchor &&
1317cdf0e10cSrcweir                         (FLY_AS_CHAR == pAnchor->GetAnchorId()) &&
131869a74367SOliver-Rainer Wittmann                         pAnchor->GetCntntAnchor() &&
131969a74367SOliver-Rainer Wittmann                         pAnchor->GetCntntAnchor()->nNode == *this &&
132069a74367SOliver-Rainer Wittmann                         pAnchor->GetCntntAnchor()->nContent == aIdx )
1321cdf0e10cSrcweir                     {
1322cdf0e10cSrcweir                         const_cast<SwIndex&>(
1323cdf0e10cSrcweir                             pAnchor->GetCntntAnchor()->nContent)--;
1324cdf0e10cSrcweir                     }
132569a74367SOliver-Rainer Wittmann                 }
132669a74367SOliver-Rainer Wittmann                 pFly->SetAnchor( this );
1327cdf0e10cSrcweir 
132869a74367SOliver-Rainer Wittmann                 // Format-Pointer kann sich im SetAnchor geaendert haben!
132969a74367SOliver-Rainer Wittmann                 // (Kopieren in andere Docs!)
133069a74367SOliver-Rainer Wittmann                 pFmt = pAttr->GetFlyCnt().GetFrmFmt();
133169a74367SOliver-Rainer Wittmann                 SwDoc *pDoc = pFmt->GetDoc();
1332cdf0e10cSrcweir 
1333cdf0e10cSrcweir                 // OD 26.06.2003 #108784# - allow drawing objects in header/footer.
1334cdf0e10cSrcweir                 // But don't allow control objects in header/footer
1335cdf0e10cSrcweir                 if( RES_DRAWFRMFMT == pFmt->Which() &&
1336cdf0e10cSrcweir                     pDoc->IsInHeaderFooter( pFmt->GetAnchor().GetCntntAnchor()->nNode ) )
133769a74367SOliver-Rainer Wittmann                 {
1338cdf0e10cSrcweir                     SwDrawContact* pDrawContact =
1339cdf0e10cSrcweir                         static_cast<SwDrawContact*>(pFmt->FindContactObj());
1340cdf0e10cSrcweir                     if ( pDrawContact &&
1341cdf0e10cSrcweir                          pDrawContact->GetMaster() &&
1342cdf0e10cSrcweir                          ::CheckControlLayer( pDrawContact->GetMaster() ) )
1343cdf0e10cSrcweir                     {
1344cdf0e10cSrcweir                         // das soll nicht meoglich sein; hier verhindern
1345cdf0e10cSrcweir                         // Der Dtor des TxtHints loescht nicht das Zeichen.
1346cdf0e10cSrcweir                         // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
1347cdf0e10cSrcweir                         // dieses explizit loeschen
1348cdf0e10cSrcweir                         if( nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode )
1349cdf0e10cSrcweir                         {
1350cdf0e10cSrcweir                             // loesche das Zeichen aus dem String !
1351cdf0e10cSrcweir                             ASSERT( ( CH_TXTATR_BREAKWORD ==
1352cdf0e10cSrcweir                                         m_Text.GetChar(*pAttr->GetStart() ) ||
1353cdf0e10cSrcweir                                       CH_TXTATR_INWORD ==
1354cdf0e10cSrcweir                                         m_Text.GetChar(*pAttr->GetStart())),
1355cdf0e10cSrcweir                                     "where is my attribute character?" );
1356cdf0e10cSrcweir                             m_Text.Erase( *pAttr->GetStart(), 1 );
1357cdf0e10cSrcweir                             // Indizies Updaten
1358cdf0e10cSrcweir                             SwIndex aTmpIdx( this, *pAttr->GetStart() );
1359cdf0e10cSrcweir                             Update( aTmpIdx, 1, sal_True );
1360cdf0e10cSrcweir                         }
1361cdf0e10cSrcweir                         // do not record deletion of Format!
1362cdf0e10cSrcweir                         ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
1363cdf0e10cSrcweir                         DestroyAttr( pAttr );
1364cdf0e10cSrcweir                         return false;
1365cdf0e10cSrcweir                     }
1366cdf0e10cSrcweir                 }
136769a74367SOliver-Rainer Wittmann                 break;
136869a74367SOliver-Rainer Wittmann             }
1369cdf0e10cSrcweir 
137069a74367SOliver-Rainer Wittmann         case RES_TXTATR_FTN :
137169a74367SOliver-Rainer Wittmann             {
137269a74367SOliver-Rainer Wittmann                 // Fussnoten, man kommt an alles irgendwie heran.
137369a74367SOliver-Rainer Wittmann                 // CntntNode erzeugen und in die Inserts-Section stellen
137469a74367SOliver-Rainer Wittmann                 SwDoc *pDoc = GetDoc();
137569a74367SOliver-Rainer Wittmann                 SwNodes &rNodes = pDoc->GetNodes();
1376cdf0e10cSrcweir 
137769a74367SOliver-Rainer Wittmann                 // FussNote in nicht Content-/Redline-Bereich einfuegen ??
137869a74367SOliver-Rainer Wittmann                 if( StartOfSectionIndex() < rNodes.GetEndOfAutotext().GetIndex() )
137969a74367SOliver-Rainer Wittmann                 {
138069a74367SOliver-Rainer Wittmann                     // das soll nicht meoglich sein; hier verhindern
138169a74367SOliver-Rainer Wittmann                     // Der Dtor des TxtHints loescht nicht das Zeichen.
138269a74367SOliver-Rainer Wittmann                     // Wenn ein CH_TXTATR_.. vorliegt, dann muss man
138369a74367SOliver-Rainer Wittmann                     // dieses explizit loeschen
138469a74367SOliver-Rainer Wittmann                     if( nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode )
138569a74367SOliver-Rainer Wittmann                     {
138669a74367SOliver-Rainer Wittmann                         // loesche das Zeichen aus dem String !
138769a74367SOliver-Rainer Wittmann                         ASSERT( ( CH_TXTATR_BREAKWORD ==
138869a74367SOliver-Rainer Wittmann                             m_Text.GetChar(*pAttr->GetStart() ) ||
138969a74367SOliver-Rainer Wittmann                             CH_TXTATR_INWORD ==
139069a74367SOliver-Rainer Wittmann                             m_Text.GetChar(*pAttr->GetStart())),
139169a74367SOliver-Rainer Wittmann                             "where is my attribute character?" );
1392cdf0e10cSrcweir                         m_Text.Erase( *pAttr->GetStart(), 1 );
139369a74367SOliver-Rainer Wittmann                         // Indizies Updaten
139469a74367SOliver-Rainer Wittmann                         SwIndex aTmpIdx( this, *pAttr->GetStart() );
139569a74367SOliver-Rainer Wittmann                         Update( aTmpIdx, 1, sal_True );
139669a74367SOliver-Rainer Wittmann                     }
139769a74367SOliver-Rainer Wittmann                     DestroyAttr( pAttr );
1398cdf0e10cSrcweir                     return false;
1399cdf0e10cSrcweir                 }
1400cdf0e10cSrcweir 
140169a74367SOliver-Rainer Wittmann                 // wird eine neue Fussnote eingefuegt ??
140269a74367SOliver-Rainer Wittmann                 sal_Bool bNewFtn = 0 == ((SwTxtFtn*)pAttr)->GetStartNode();
140369a74367SOliver-Rainer Wittmann                 if( bNewFtn )
1404cdf0e10cSrcweir                 {
140569a74367SOliver-Rainer Wittmann                     ((SwTxtFtn*)pAttr)->MakeNewTextSection( GetNodes() );
1406cdf0e10cSrcweir                     SwRegHistory* pHist = GetpSwpHints()
1407cdf0e10cSrcweir                         ? GetpSwpHints()->GetHistory() : 0;
1408cdf0e10cSrcweir                     if( pHist )
1409cdf0e10cSrcweir                         pHist->ChangeNodeIndex( GetIndex() );
1410cdf0e10cSrcweir                 }
141169a74367SOliver-Rainer Wittmann                 else if ( !GetpSwpHints() || !GetpSwpHints()->IsInSplitNode() )
141269a74367SOliver-Rainer Wittmann                 {
141369a74367SOliver-Rainer Wittmann                     // loesche alle Frames der Section, auf die der StartNode zeigt
141469a74367SOliver-Rainer Wittmann                     sal_uLong nSttIdx =
141569a74367SOliver-Rainer Wittmann                         ((SwTxtFtn*)pAttr)->GetStartNode()->GetIndex();
141669a74367SOliver-Rainer Wittmann                     sal_uLong nEndIdx = rNodes[ nSttIdx++ ]->EndOfSectionIndex();
141769a74367SOliver-Rainer Wittmann                     SwCntntNode* pCNd;
141869a74367SOliver-Rainer Wittmann                     for( ; nSttIdx < nEndIdx; ++nSttIdx )
141969a74367SOliver-Rainer Wittmann                         if( 0 != ( pCNd = rNodes[ nSttIdx ]->GetCntntNode() ))
142069a74367SOliver-Rainer Wittmann                             pCNd->DelFrms();
142169a74367SOliver-Rainer Wittmann                 }
1422cdf0e10cSrcweir 
142369a74367SOliver-Rainer Wittmann                 if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
142469a74367SOliver-Rainer Wittmann                 {
142569a74367SOliver-Rainer Wittmann                     // Wir muessen zuerst einfuegen, da sonst gleiche Indizes
142669a74367SOliver-Rainer Wittmann                     // entstehen koennen und das Attribut im _SortArr_ am
142769a74367SOliver-Rainer Wittmann                     // Dokument nicht eingetrage wird.
142869a74367SOliver-Rainer Wittmann                     SwIndex aNdIdx( this, *pAttr->GetStart() );
1429cdf0e10cSrcweir                     const sal_Unicode c = GetCharOfTxtAttr(*pAttr);
1430cdf0e10cSrcweir                     InsertText( c, aNdIdx, nInsertFlags );
143169a74367SOliver-Rainer Wittmann                     nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
143269a74367SOliver-Rainer Wittmann                 }
1433cdf0e10cSrcweir 
143469a74367SOliver-Rainer Wittmann                 // Wir tragen uns am FtnIdx-Array des Docs ein ...
143569a74367SOliver-Rainer Wittmann                 SwTxtFtn* pTxtFtn = 0;
143669a74367SOliver-Rainer Wittmann                 if( !bNewFtn )
143769a74367SOliver-Rainer Wittmann                 {
143869a74367SOliver-Rainer Wittmann                     // eine alte Ftn wird umgehaengt (z.B. SplitNode)
143969a74367SOliver-Rainer Wittmann                     for( sal_uInt16 n = 0; n < pDoc->GetFtnIdxs().Count(); ++n )
144069a74367SOliver-Rainer Wittmann                         if( pAttr == pDoc->GetFtnIdxs()[n] )
144169a74367SOliver-Rainer Wittmann                         {
144269a74367SOliver-Rainer Wittmann                             // neuen Index zuweisen, dafuer aus dem SortArray
144369a74367SOliver-Rainer Wittmann                             // loeschen und neu eintragen
144469a74367SOliver-Rainer Wittmann                             pTxtFtn = pDoc->GetFtnIdxs()[n];
144569a74367SOliver-Rainer Wittmann                             pDoc->GetFtnIdxs().Remove( n );
144669a74367SOliver-Rainer Wittmann                             break;
144769a74367SOliver-Rainer Wittmann                         }
144869a74367SOliver-Rainer Wittmann                         // wenn ueber Undo der StartNode gesetzt wurde, kann
144969a74367SOliver-Rainer Wittmann                         // der Index noch gar nicht in der Verwaltung stehen !!
145069a74367SOliver-Rainer Wittmann                 }
145169a74367SOliver-Rainer Wittmann                 if( !pTxtFtn )
145269a74367SOliver-Rainer Wittmann                     pTxtFtn = (SwTxtFtn*)pAttr;
1453cdf0e10cSrcweir 
145469a74367SOliver-Rainer Wittmann                 // fuers Update der Nummern und zum Sortieren
145569a74367SOliver-Rainer Wittmann                 // muss der Node gesetzt sein.
145669a74367SOliver-Rainer Wittmann                 ((SwTxtFtn*)pAttr)->ChgTxtNode( this );
1457cdf0e10cSrcweir 
145869a74367SOliver-Rainer Wittmann                 // FussNote im Redline-Bereich NICHT ins FtnArray einfuegen!
145969a74367SOliver-Rainer Wittmann                 if( StartOfSectionIndex() > rNodes.GetEndOfRedlines().GetIndex() )
146069a74367SOliver-Rainer Wittmann                 {
1461cdf0e10cSrcweir #ifdef DBG_UTIL
146269a74367SOliver-Rainer Wittmann                     const sal_Bool bSuccess =
1463cdf0e10cSrcweir #endif
146469a74367SOliver-Rainer Wittmann                         pDoc->GetFtnIdxs().Insert( pTxtFtn );
1465cdf0e10cSrcweir #ifdef DBG_UTIL
146669a74367SOliver-Rainer Wittmann                     ASSERT( bSuccess, "FtnIdx nicht eingetragen." );
1467cdf0e10cSrcweir #endif
146869a74367SOliver-Rainer Wittmann                 }
146969a74367SOliver-Rainer Wittmann                 SwNodeIndex aTmpIndex( *this );
147069a74367SOliver-Rainer Wittmann                 pDoc->GetFtnIdxs().UpdateFtn( aTmpIndex);
147169a74367SOliver-Rainer Wittmann                 ((SwTxtFtn*)pAttr)->SetSeqRefNo();
147269a74367SOliver-Rainer Wittmann             }
147369a74367SOliver-Rainer Wittmann             break;
1474cdf0e10cSrcweir 
147569a74367SOliver-Rainer Wittmann             case RES_TXTATR_FIELD:
147669a74367SOliver-Rainer Wittmann                 {
147769a74367SOliver-Rainer Wittmann                     // fuer HiddenParaFields Benachrichtigungsmechanismus
147869a74367SOliver-Rainer Wittmann                     // anwerfen
147969a74367SOliver-Rainer Wittmann                     if( RES_HIDDENPARAFLD == pAttr->GetFmtFld().GetField()->GetTyp()->Which() )
148069a74367SOliver-Rainer Wittmann                     {
148169a74367SOliver-Rainer Wittmann                         bHiddenPara = true;
148269a74367SOliver-Rainer Wittmann                     }
148369a74367SOliver-Rainer Wittmann                 }
148469a74367SOliver-Rainer Wittmann                 break;
1485cdf0e10cSrcweir 
148669a74367SOliver-Rainer Wittmann         }
148769a74367SOliver-Rainer Wittmann         // Fuer SwTxtHints ohne Endindex werden CH_TXTATR_..
148869a74367SOliver-Rainer Wittmann         // eingefuegt, aStart muss danach um einen zurueckgesetzt werden.
148969a74367SOliver-Rainer Wittmann         // Wenn wir im SwTxtNode::Copy stehen, so wurde das Zeichen bereits
149069a74367SOliver-Rainer Wittmann         // mitkopiert. In solchem Fall ist SETATTR_NOTXTATRCHR angegeben worden.
149169a74367SOliver-Rainer Wittmann         if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
149269a74367SOliver-Rainer Wittmann         {
149369a74367SOliver-Rainer Wittmann             SwIndex aIdx( this, *pAttr->GetStart() );
1494cdf0e10cSrcweir             InsertText( GetCharOfTxtAttr(*pAttr), aIdx, nInsertFlags );
1495cdf0e10cSrcweir 
1496cdf0e10cSrcweir             // adjust end of hint to account for inserted CH_TXTATR
1497cdf0e10cSrcweir             xub_StrLen * const pEnd(pAttr->GetEnd());
1498cdf0e10cSrcweir             if (pEnd)
1499cdf0e10cSrcweir             {
1500cdf0e10cSrcweir                 *pEnd = *pEnd + 1;
1501cdf0e10cSrcweir             }
1502cdf0e10cSrcweir         }
1503cdf0e10cSrcweir     }
1504cdf0e10cSrcweir 
150569a74367SOliver-Rainer Wittmann     // handle attributes which provide content
150669a74367SOliver-Rainer Wittmann     xub_StrLen nEnd = nStart;
150769a74367SOliver-Rainer Wittmann     bool bInputFieldStartCharInserted = false;
150869a74367SOliver-Rainer Wittmann     bool bInputFieldEndCharInserted = false;
150969a74367SOliver-Rainer Wittmann     const bool bHasContent( pAttr->HasContent() );
151069a74367SOliver-Rainer Wittmann     if ( bHasContent )
151169a74367SOliver-Rainer Wittmann     {
151269a74367SOliver-Rainer Wittmann         switch( pAttr->Which() )
151369a74367SOliver-Rainer Wittmann         {
151469a74367SOliver-Rainer Wittmann         case RES_TXTATR_INPUTFIELD:
151569a74367SOliver-Rainer Wittmann             {
151669a74367SOliver-Rainer Wittmann                 SwTxtInputFld* pTxtInputFld = dynamic_cast<SwTxtInputFld*>(pAttr);
151769a74367SOliver-Rainer Wittmann                 if ( pTxtInputFld )
151869a74367SOliver-Rainer Wittmann                 {
151969a74367SOliver-Rainer Wittmann                     if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nMode) )
152069a74367SOliver-Rainer Wittmann                     {
152169a74367SOliver-Rainer Wittmann                         SwIndex aIdx( this, *pAttr->GetStart() );
152269a74367SOliver-Rainer Wittmann                         InsertText( CH_TXT_ATR_INPUTFIELDSTART, aIdx, nInsertFlags );
152369a74367SOliver-Rainer Wittmann                         const String aContent = pTxtInputFld->GetFieldContent();
152469a74367SOliver-Rainer Wittmann                         InsertText( aContent, aIdx, nInsertFlags );
152569a74367SOliver-Rainer Wittmann                         InsertText( CH_TXT_ATR_INPUTFIELDEND, aIdx, nInsertFlags );
152669a74367SOliver-Rainer Wittmann 
152769a74367SOliver-Rainer Wittmann                         xub_StrLen * const pEnd(pAttr->GetEnd());
152869a74367SOliver-Rainer Wittmann                         ASSERT( pEnd != NULL, "<SwTxtNode::InsertHint(..)> - missing end of RES_TXTATR_INPUTFIELD!" );
152969a74367SOliver-Rainer Wittmann                         if ( pEnd != NULL )
153069a74367SOliver-Rainer Wittmann                         {
153169a74367SOliver-Rainer Wittmann                             *pEnd = *pEnd + 2 + aContent.Len();
153269a74367SOliver-Rainer Wittmann                             nEnd = *pEnd;
153369a74367SOliver-Rainer Wittmann                         }
153469a74367SOliver-Rainer Wittmann                     }
153569a74367SOliver-Rainer Wittmann                     else
153669a74367SOliver-Rainer Wittmann                     {
153769a74367SOliver-Rainer Wittmann                         // assure that CH_TXT_ATR_INPUTFIELDSTART and CH_TXT_ATR_INPUTFIELDEND are inserted.
153869a74367SOliver-Rainer Wittmann                         if ( m_Text.GetChar( *(pAttr->GetStart()) ) != CH_TXT_ATR_INPUTFIELDSTART )
153969a74367SOliver-Rainer Wittmann                         {
154069a74367SOliver-Rainer Wittmann                             SwIndex aIdx( this, *pAttr->GetStart() );
154169a74367SOliver-Rainer Wittmann                             InsertText( CH_TXT_ATR_INPUTFIELDSTART, aIdx, nInsertFlags );
154269a74367SOliver-Rainer Wittmann                             bInputFieldStartCharInserted = true;
154369a74367SOliver-Rainer Wittmann                             xub_StrLen * const pEnd(pAttr->GetEnd());
154469a74367SOliver-Rainer Wittmann                             ASSERT( pEnd != NULL, "<SwTxtNode::InsertHint(..)> - missing end of RES_TXTATR_INPUTFIELD!" );
154569a74367SOliver-Rainer Wittmann                             if ( pEnd != NULL )
154669a74367SOliver-Rainer Wittmann                             {
154769a74367SOliver-Rainer Wittmann                                 *pEnd = *pEnd + 1;
154869a74367SOliver-Rainer Wittmann                                 nEnd = *pEnd;
154969a74367SOliver-Rainer Wittmann                             }
155069a74367SOliver-Rainer Wittmann                         }
155169a74367SOliver-Rainer Wittmann 
155269a74367SOliver-Rainer Wittmann                         xub_StrLen * const pEnd(pAttr->GetEnd());
155369a74367SOliver-Rainer Wittmann                         ASSERT( pEnd != NULL, "<SwTxtNode::InsertHint(..)> - missing end of RES_TXTATR_INPUTFIELD!" );
155469a74367SOliver-Rainer Wittmann                         if ( pEnd != NULL
155569a74367SOliver-Rainer Wittmann                              && m_Text.GetChar( *(pEnd) - 1 ) != CH_TXT_ATR_INPUTFIELDEND )
155669a74367SOliver-Rainer Wittmann                         {
155769a74367SOliver-Rainer Wittmann                             SwIndex aIdx( this, *(pEnd) );
155869a74367SOliver-Rainer Wittmann                             InsertText( CH_TXT_ATR_INPUTFIELDEND, aIdx, nInsertFlags );
155969a74367SOliver-Rainer Wittmann                             bInputFieldEndCharInserted = true;
156069a74367SOliver-Rainer Wittmann                             *pEnd = *pEnd + 1;
156169a74367SOliver-Rainer Wittmann                             nEnd = *pEnd;
156269a74367SOliver-Rainer Wittmann                         }
156369a74367SOliver-Rainer Wittmann                     }
156469a74367SOliver-Rainer Wittmann                 }
156569a74367SOliver-Rainer Wittmann             }
156669a74367SOliver-Rainer Wittmann             break;
156769a74367SOliver-Rainer Wittmann         default:
156869a74367SOliver-Rainer Wittmann             break;
156969a74367SOliver-Rainer Wittmann         }
157069a74367SOliver-Rainer Wittmann     }
157169a74367SOliver-Rainer Wittmann 
1572cdf0e10cSrcweir     GetOrCreateSwpHints();
1573cdf0e10cSrcweir 
157469a74367SOliver-Rainer Wittmann     // handle overlap with an existing InputField
157569a74367SOliver-Rainer Wittmann     bool bInsertHint = true;
157669a74367SOliver-Rainer Wittmann     {
157769a74367SOliver-Rainer Wittmann         const SwTxtInputFld* pTxtInputFld = GetOverlappingInputFld( *pAttr );
157869a74367SOliver-Rainer Wittmann         if ( pTxtInputFld != NULL )
157969a74367SOliver-Rainer Wittmann         {
158069a74367SOliver-Rainer Wittmann             if ( pAttr->End() == NULL )
158169a74367SOliver-Rainer Wittmann             {
158269a74367SOliver-Rainer Wittmann                 bInsertHint = false;
158369a74367SOliver-Rainer Wittmann             }
158469a74367SOliver-Rainer Wittmann             else
158569a74367SOliver-Rainer Wittmann             {
158669a74367SOliver-Rainer Wittmann                 if ( *(pAttr->GetStart()) > *(pTxtInputFld->GetStart()) )
158769a74367SOliver-Rainer Wittmann                 {
158869a74367SOliver-Rainer Wittmann                     *(pAttr->GetStart()) = *(pTxtInputFld->GetStart());
158969a74367SOliver-Rainer Wittmann                 }
159069a74367SOliver-Rainer Wittmann                 if ( *(pAttr->End()) < *(pTxtInputFld->End()) )
159169a74367SOliver-Rainer Wittmann                 {
159269a74367SOliver-Rainer Wittmann                     *(pAttr->GetEnd()) = *(pTxtInputFld->End());
159369a74367SOliver-Rainer Wittmann                 }
159469a74367SOliver-Rainer Wittmann             }
159569a74367SOliver-Rainer Wittmann         }
159669a74367SOliver-Rainer Wittmann     }
1597cdf0e10cSrcweir 
159869a74367SOliver-Rainer Wittmann     // 4263: AttrInsert durch TextInsert => kein Adjust
159969a74367SOliver-Rainer Wittmann     const bool bRet = bInsertHint
160069a74367SOliver-Rainer Wittmann                       ? m_pSwpHints->TryInsertHint( pAttr, *this, nMode )
160169a74367SOliver-Rainer Wittmann                       : false;
160269a74367SOliver-Rainer Wittmann 
160369a74367SOliver-Rainer Wittmann     if ( !bRet )
1604cdf0e10cSrcweir     {
160569a74367SOliver-Rainer Wittmann         if ( bDummyChar
160669a74367SOliver-Rainer Wittmann              && !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nMode) )
1607cdf0e10cSrcweir         {
160869a74367SOliver-Rainer Wittmann             // undo insertion of dummy character
160969a74367SOliver-Rainer Wittmann             // N.B. cannot insert the dummy character after inserting the hint,
161069a74367SOliver-Rainer Wittmann             // because if the hint has no extent it will be moved in InsertText,
161169a74367SOliver-Rainer Wittmann             // resulting in infinite recursion
1612cdf0e10cSrcweir             ASSERT( ( CH_TXTATR_BREAKWORD == m_Text.GetChar(nStart) ||
161369a74367SOliver-Rainer Wittmann                 CH_TXTATR_INWORD    == m_Text.GetChar(nStart) ),
161469a74367SOliver-Rainer Wittmann                 "where is my attribute character?" );
1615cdf0e10cSrcweir             SwIndex aIdx( this, nStart );
1616cdf0e10cSrcweir             EraseText( aIdx, 1 );
1617cdf0e10cSrcweir         }
161869a74367SOliver-Rainer Wittmann 
161969a74367SOliver-Rainer Wittmann         if ( bHasContent )
162069a74367SOliver-Rainer Wittmann         {
162169a74367SOliver-Rainer Wittmann             if ( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nMode)
162269a74367SOliver-Rainer Wittmann                  && (nEnd - nStart) > 0 )
162369a74367SOliver-Rainer Wittmann             {
162469a74367SOliver-Rainer Wittmann                 SwIndex aIdx( this, nStart );
162569a74367SOliver-Rainer Wittmann                 EraseText( aIdx, (nEnd - nStart) );
162669a74367SOliver-Rainer Wittmann             }
162769a74367SOliver-Rainer Wittmann             else
162869a74367SOliver-Rainer Wittmann             {
162969a74367SOliver-Rainer Wittmann                 if ( bInputFieldEndCharInserted
163069a74367SOliver-Rainer Wittmann                      && (nEnd - nStart) > 0 )
163169a74367SOliver-Rainer Wittmann                 {
163269a74367SOliver-Rainer Wittmann                     SwIndex aIdx( this, nEnd - 1 );
163369a74367SOliver-Rainer Wittmann                     EraseText( aIdx, 1 );
163469a74367SOliver-Rainer Wittmann                 }
163569a74367SOliver-Rainer Wittmann 
163669a74367SOliver-Rainer Wittmann                 if ( bInputFieldStartCharInserted )
163769a74367SOliver-Rainer Wittmann                 {
163869a74367SOliver-Rainer Wittmann                     SwIndex aIdx( this, nStart );
163969a74367SOliver-Rainer Wittmann                     EraseText( aIdx, 1 );
164069a74367SOliver-Rainer Wittmann                 }
164169a74367SOliver-Rainer Wittmann             }
164269a74367SOliver-Rainer Wittmann         }
1643cdf0e10cSrcweir     }
1644cdf0e10cSrcweir 
1645cdf0e10cSrcweir     if ( bHiddenPara )
1646cdf0e10cSrcweir     {
1647cdf0e10cSrcweir         SetCalcHiddenParaField();
1648cdf0e10cSrcweir     }
1649cdf0e10cSrcweir 
1650cdf0e10cSrcweir     return bRet;
1651cdf0e10cSrcweir }
1652cdf0e10cSrcweir 
1653cdf0e10cSrcweir 
1654cdf0e10cSrcweir /*************************************************************************
1655cdf0e10cSrcweir  *                        SwTxtNode::DeleteAttribute()
1656cdf0e10cSrcweir  *************************************************************************/
1657cdf0e10cSrcweir 
DeleteAttribute(SwTxtAttr * const pAttr)1658cdf0e10cSrcweir void SwTxtNode::DeleteAttribute( SwTxtAttr * const pAttr )
1659cdf0e10cSrcweir {
1660cdf0e10cSrcweir     if ( !HasHints() )
1661cdf0e10cSrcweir     {
1662cdf0e10cSrcweir         ASSERT(false, "DeleteAttribute called, but text node without hints?");
1663cdf0e10cSrcweir         return;
1664cdf0e10cSrcweir     }
1665cdf0e10cSrcweir 
1666cdf0e10cSrcweir     if ( pAttr->HasDummyChar() )
1667cdf0e10cSrcweir     {
1668cdf0e10cSrcweir         // Unbedingt Copy-konstruieren!
1669cdf0e10cSrcweir         const SwIndex aIdx( this, *pAttr->GetStart() );
1670cdf0e10cSrcweir         // erase the CH_TXTATR, which will also delete pAttr
1671cdf0e10cSrcweir         EraseText( aIdx, 1 );
1672cdf0e10cSrcweir     }
167369a74367SOliver-Rainer Wittmann     else if ( pAttr->HasContent() )
167469a74367SOliver-Rainer Wittmann     {
167569a74367SOliver-Rainer Wittmann         const SwIndex aIdx( this, *pAttr->GetStart() );
167669a74367SOliver-Rainer Wittmann         ASSERT( pAttr->End() != NULL, "<SwTxtNode::DeleteAttribute(..)> - missing End() at <SwTxtAttr> instance which has content" );
167769a74367SOliver-Rainer Wittmann         EraseText( aIdx, *pAttr->End() - *pAttr->GetStart() );
167869a74367SOliver-Rainer Wittmann     }
1679cdf0e10cSrcweir     else
1680cdf0e10cSrcweir     {
1681cdf0e10cSrcweir         // create MsgHint before start/end become invalid
1682cdf0e10cSrcweir         SwUpdateAttr aHint(
168356b35d86SArmin Le Grand             *pAttr->GetStart(),
168456b35d86SArmin Le Grand             *pAttr->GetEnd(),
168556b35d86SArmin Le Grand             pAttr->Which());
168656b35d86SArmin Le Grand 
1687cdf0e10cSrcweir         m_pSwpHints->Delete( pAttr );
1688cdf0e10cSrcweir         SwTxtAttr::Destroy( pAttr, GetDoc()->GetAttrPool() );
1689cdf0e10cSrcweir         NotifyClients( 0, &aHint );
1690cdf0e10cSrcweir 
1691cdf0e10cSrcweir         TryDeleteSwpHints();
1692cdf0e10cSrcweir     }
1693cdf0e10cSrcweir }
1694cdf0e10cSrcweir 
1695cdf0e10cSrcweir /*************************************************************************
1696cdf0e10cSrcweir  *                        SwTxtNode::DeleteAttributes()
1697cdf0e10cSrcweir  *************************************************************************/
1698cdf0e10cSrcweir 
1699cdf0e10cSrcweir //FIXME: this does NOT respect SORT NUMBER (for CHARFMT)!
DeleteAttributes(const sal_uInt16 nWhich,const xub_StrLen nStart,const xub_StrLen nEnd)170069a74367SOliver-Rainer Wittmann void SwTxtNode::DeleteAttributes(
170169a74367SOliver-Rainer Wittmann     const sal_uInt16 nWhich,
170269a74367SOliver-Rainer Wittmann     const xub_StrLen nStart,
170369a74367SOliver-Rainer Wittmann     const xub_StrLen nEnd )
1704cdf0e10cSrcweir {
1705cdf0e10cSrcweir     if ( !HasHints() )
1706cdf0e10cSrcweir         return;
1707cdf0e10cSrcweir 
1708cdf0e10cSrcweir     for ( sal_uInt16 nPos = 0; m_pSwpHints && nPos < m_pSwpHints->Count(); nPos++ )
1709cdf0e10cSrcweir     {
1710cdf0e10cSrcweir         SwTxtAttr * const pTxtHt = m_pSwpHints->GetTextHint( nPos );
1711cdf0e10cSrcweir         const xub_StrLen nHintStart = *(pTxtHt->GetStart());
1712cdf0e10cSrcweir         if (nStart < nHintStart)
1713cdf0e10cSrcweir         {
1714cdf0e10cSrcweir             break; // sorted by start
1715cdf0e10cSrcweir         }
1716cdf0e10cSrcweir         else if ( (nStart == nHintStart) && (nWhich == pTxtHt->Which()) )
1717cdf0e10cSrcweir         {
1718cdf0e10cSrcweir             if ( nWhich == RES_CHRATR_HIDDEN  )
1719cdf0e10cSrcweir             {
1720cdf0e10cSrcweir                 ASSERT(false, "hey, that's a CHRATR! how did that get in?");
1721cdf0e10cSrcweir                 SetCalcHiddenCharFlags();
1722cdf0e10cSrcweir             }
1723cdf0e10cSrcweir             else if ( nWhich == RES_TXTATR_CHARFMT )
1724cdf0e10cSrcweir             {
1725cdf0e10cSrcweir                 // Check if character format contains hidden attribute:
1726cdf0e10cSrcweir                 const SwCharFmt* pFmt = pTxtHt->GetCharFmt().GetCharFmt();
1727cdf0e10cSrcweir                 const SfxPoolItem* pItem;
1728cdf0e10cSrcweir                 if ( SFX_ITEM_SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
1729cdf0e10cSrcweir                     SetCalcHiddenCharFlags();
1730cdf0e10cSrcweir             }
173169a74367SOliver-Rainer Wittmann             // Recalc hidden flags if necessary
1732cdf0e10cSrcweir             else if ( nWhich == RES_TXTATR_AUTOFMT )
1733cdf0e10cSrcweir             {
1734cdf0e10cSrcweir                 // Check if auto style contains hidden attribute:
1735cdf0e10cSrcweir                 const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pTxtHt, RES_CHRATR_HIDDEN );
1736cdf0e10cSrcweir                 if ( pHiddenItem )
1737cdf0e10cSrcweir                     SetCalcHiddenCharFlags();
1738cdf0e10cSrcweir             }
1739cdf0e10cSrcweir 
1740cdf0e10cSrcweir             xub_StrLen const * const pEndIdx = pTxtHt->GetEnd();
1741cdf0e10cSrcweir 
1742cdf0e10cSrcweir             if ( pTxtHt->HasDummyChar() )
1743cdf0e10cSrcweir             {
174469a74367SOliver-Rainer Wittmann                 // Unbedingt Copy-konstruieren!
1745cdf0e10cSrcweir                 const SwIndex aIdx( this, nStart );
1746cdf0e10cSrcweir                 // erase the CH_TXTATR, which will also delete pTxtHt
1747cdf0e10cSrcweir                 EraseText( aIdx, 1 );
174869a74367SOliver-Rainer Wittmann             }
174969a74367SOliver-Rainer Wittmann             else if ( pTxtHt->HasContent() )
175069a74367SOliver-Rainer Wittmann             {
175169a74367SOliver-Rainer Wittmann                 const SwIndex aIdx( this, nStart );
175269a74367SOliver-Rainer Wittmann                 ASSERT( pTxtHt->End() != NULL, "<SwTxtNode::DeleteAttributes(..)> - missing End() at <SwTxtAttr> instance which has content" );
175369a74367SOliver-Rainer Wittmann                 EraseText( aIdx, *pTxtHt->End() - nStart );
175469a74367SOliver-Rainer Wittmann             }
175569a74367SOliver-Rainer Wittmann             else if( *pEndIdx == nEnd )
175669a74367SOliver-Rainer Wittmann             {
175769a74367SOliver-Rainer Wittmann                 // den MsgHint jetzt fuettern, weil gleich sind
175869a74367SOliver-Rainer Wittmann                 // Start und End weg.
175969a74367SOliver-Rainer Wittmann                 // Das CalcVisibleFlag bei HiddenParaFields entfaellt,
176069a74367SOliver-Rainer Wittmann                 // da dies das Feld im Dtor selbst erledigt.
176156b35d86SArmin Le Grand                 SwUpdateAttr aHint(
176256b35d86SArmin Le Grand                     nStart,
176356b35d86SArmin Le Grand                     *pEndIdx,
176456b35d86SArmin Le Grand                     nWhich);
176556b35d86SArmin Le Grand 
1766cdf0e10cSrcweir                 m_pSwpHints->DeleteAtPos( nPos );    // gefunden, loeschen,
1767cdf0e10cSrcweir                 SwTxtAttr::Destroy( pTxtHt, GetDoc()->GetAttrPool() );
176869a74367SOliver-Rainer Wittmann                 NotifyClients( 0, &aHint );
176969a74367SOliver-Rainer Wittmann             }
177069a74367SOliver-Rainer Wittmann         }
177169a74367SOliver-Rainer Wittmann     }
1772cdf0e10cSrcweir     TryDeleteSwpHints();
1773cdf0e10cSrcweir }
1774cdf0e10cSrcweir 
1775cdf0e10cSrcweir /*************************************************************************
1776cdf0e10cSrcweir  *						SwTxtNode::DelSoftHyph()
1777cdf0e10cSrcweir  *************************************************************************/
1778cdf0e10cSrcweir 
DelSoftHyph(const xub_StrLen nStt,const xub_StrLen nEnd)1779cdf0e10cSrcweir void SwTxtNode::DelSoftHyph( const xub_StrLen nStt, const xub_StrLen nEnd )
1780cdf0e10cSrcweir {
1781cdf0e10cSrcweir     xub_StrLen nFndPos = nStt, nEndPos = nEnd;
1782cdf0e10cSrcweir 	while( STRING_NOTFOUND !=
1783cdf0e10cSrcweir             ( nFndPos = m_Text.Search( CHAR_SOFTHYPHEN, nFndPos )) &&
1784cdf0e10cSrcweir 			nFndPos < nEndPos )
1785cdf0e10cSrcweir 	{
1786cdf0e10cSrcweir 		const SwIndex aIdx( this, nFndPos );
1787cdf0e10cSrcweir         EraseText( aIdx, 1 );
1788cdf0e10cSrcweir 		--nEndPos;
1789cdf0e10cSrcweir 	}
1790cdf0e10cSrcweir }
1791cdf0e10cSrcweir 
1792abbaf3ecSJian Hong Cheng //Modify here for #119405, by easyfan, 2012-05-24
1793*7a164331Smseidel //In MS Word, the font underline setting of the paragraph end position won't affect the formatting of numbering, escapement, etc, so we ignore them
lcl_IsIgnoredCharFmtForNumbering(const sal_uInt16 nWhich)1794abbaf3ecSJian Hong Cheng bool lcl_IsIgnoredCharFmtForNumbering(const sal_uInt16 nWhich)
1795abbaf3ecSJian Hong Cheng {
17969f231f76SClarence Guo 	return (nWhich == RES_CHRATR_UNDERLINE || nWhich == RES_CHRATR_ESCAPEMENT);
1797abbaf3ecSJian Hong Cheng }
1798abbaf3ecSJian Hong Cheng 
1799*7a164331Smseidel //In MS Word, following properties of the paragraph end position won't affect the formatting of bullets, so we ignore them:
1800abbaf3ecSJian Hong Cheng //Font underline;
1801abbaf3ecSJian Hong Cheng //Font Italic of Western, CJK and CTL;
1802abbaf3ecSJian Hong Cheng //Font Bold of Wertern, CJK and CTL;
lcl_IsIgnoredCharFmtForBullets(const sal_uInt16 nWhich)1803abbaf3ecSJian Hong Cheng bool lcl_IsIgnoredCharFmtForBullets(const sal_uInt16 nWhich)
1804abbaf3ecSJian Hong Cheng {
18059f231f76SClarence Guo 	return (nWhich == RES_CHRATR_UNDERLINE || nWhich == RES_CHRATR_POSTURE || nWhich == RES_CHRATR_WEIGHT
1806abbaf3ecSJian Hong Cheng 		|| nWhich == RES_CHRATR_CJK_POSTURE || nWhich == RES_CHRATR_CJK_WEIGHT
1807abbaf3ecSJian Hong Cheng 		|| nWhich == RES_CHRATR_CTL_POSTURE || nWhich == RES_CHRATR_CTL_WEIGHT);
1808abbaf3ecSJian Hong Cheng }
1809abbaf3ecSJian Hong Cheng 
1810abbaf3ecSJian Hong Cheng //Condition for expanding char set to character style of specified number rule level:
1811abbaf3ecSJian Hong Cheng //The item inside the set should not conflict to any exist and non-default item inside paragraph properties set (SwCntntNode::SwPAttrSet);
1812abbaf3ecSJian Hong Cheng //The node should have applied a number rule;
1813abbaf3ecSJian Hong Cheng //The node should be counted in a list, if not, make it to be;
1814abbaf3ecSJian Hong Cheng //The item should not conflict to any exist and non-default item inside the character of specified number rule level;
1815abbaf3ecSJian Hong Cheng //The item should not be ignored depend on the exact number rule type;
TryCharSetExpandToNum(const SfxItemSet & aCharSet)1816abbaf3ecSJian Hong Cheng bool SwTxtNode::TryCharSetExpandToNum(const SfxItemSet& aCharSet)
1817abbaf3ecSJian Hong Cheng {
1818abbaf3ecSJian Hong Cheng 	bool bRet = false;
1819abbaf3ecSJian Hong Cheng 	SfxItemIter aIter( aCharSet );
1820abbaf3ecSJian Hong Cheng         const SfxPoolItem* pItem = aIter.FirstItem();
1821abbaf3ecSJian Hong Cheng         const sal_uInt16 nWhich = pItem->Which();
1822abbaf3ecSJian Hong Cheng 
1823abbaf3ecSJian Hong Cheng 	const SfxPoolItem& rInnerItem = GetAttr(nWhich,false);
1824abbaf3ecSJian Hong Cheng 
1825abbaf3ecSJian Hong Cheng 	if (!IsDefaultItem(&rInnerItem) &&  !IsInvalidItem(&rInnerItem))
1826abbaf3ecSJian Hong Cheng 		return bRet;
1827abbaf3ecSJian Hong Cheng 
1828abbaf3ecSJian Hong Cheng 	if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
1829abbaf3ecSJian Hong Cheng 	{
1830abbaf3ecSJian Hong Cheng 		return bRet;
1831abbaf3ecSJian Hong Cheng 	}
1832abbaf3ecSJian Hong Cheng 
1833abbaf3ecSJian Hong Cheng 	SwNumRule* pCurrNum = GetNumRule(false);
1834abbaf3ecSJian Hong Cheng 
1835abbaf3ecSJian Hong Cheng 	int nLevel = GetActualListLevel();
1836abbaf3ecSJian Hong Cheng 
1837abbaf3ecSJian Hong Cheng 	if (nLevel != -1 && pCurrNum)
1838abbaf3ecSJian Hong Cheng 	{
1839abbaf3ecSJian Hong Cheng 		const SwNumFmt* pCurrNumFmt = pCurrNum->GetNumFmt(static_cast<sal_uInt16>(nLevel));
1840abbaf3ecSJian Hong Cheng 		if (pCurrNumFmt)
1841abbaf3ecSJian Hong Cheng 		{
1842abbaf3ecSJian Hong Cheng 			if (pCurrNumFmt->IsItemize() && lcl_IsIgnoredCharFmtForBullets(nWhich))
1843abbaf3ecSJian Hong Cheng 				return bRet;
1844abbaf3ecSJian Hong Cheng 			if (pCurrNumFmt->IsEnumeration() && lcl_IsIgnoredCharFmtForNumbering(nWhich))
1845abbaf3ecSJian Hong Cheng 				return bRet;
1846abbaf3ecSJian Hong Cheng 			SwCharFmt* pCurrCharFmt =pCurrNumFmt->GetCharFmt();
1847abbaf3ecSJian Hong Cheng 
1848abbaf3ecSJian Hong Cheng 			if (pCurrCharFmt && pCurrCharFmt->GetItemState(nWhich,false) != SFX_ITEM_SET)
1849abbaf3ecSJian Hong Cheng 			{
1850abbaf3ecSJian Hong Cheng 				pCurrCharFmt->SetFmtAttr(*pItem);
1851abbaf3ecSJian Hong Cheng 				SwNumFmt aNewNumFmt(*pCurrNumFmt);
1852abbaf3ecSJian Hong Cheng 				aNewNumFmt.SetCharFmt(pCurrCharFmt);
1853abbaf3ecSJian Hong Cheng 				pCurrNum->Set(nLevel,aNewNumFmt);
1854abbaf3ecSJian Hong Cheng 				bRet = true;
1855abbaf3ecSJian Hong Cheng 			}
1856abbaf3ecSJian Hong Cheng 		}
1857abbaf3ecSJian Hong Cheng 	}
1858abbaf3ecSJian Hong Cheng 
1859abbaf3ecSJian Hong Cheng 
1860abbaf3ecSJian Hong Cheng 	return bRet;
1861abbaf3ecSJian Hong Cheng }
1862abbaf3ecSJian Hong Cheng //End of modification, by easyfan
1863abbaf3ecSJian Hong Cheng 
1864cdf0e10cSrcweir // setze diese Attribute am TextNode. Wird der gesamte Bereich umspannt,
1865cdf0e10cSrcweir // dann setze sie nur im AutoAttrSet (SwCntntNode:: SetAttr)
SetAttr(const SfxItemSet & rSet,const xub_StrLen nStt,const xub_StrLen nEnd,const SetAttrMode nMode)186669a74367SOliver-Rainer Wittmann sal_Bool SwTxtNode::SetAttr(
186769a74367SOliver-Rainer Wittmann     const SfxItemSet& rSet,
186869a74367SOliver-Rainer Wittmann     const xub_StrLen nStt,
186969a74367SOliver-Rainer Wittmann     const xub_StrLen nEnd,
187069a74367SOliver-Rainer Wittmann     const SetAttrMode nMode )
1871cdf0e10cSrcweir {
1872cdf0e10cSrcweir 	if( !rSet.Count() )
1873cdf0e10cSrcweir 		return sal_False;
1874cdf0e10cSrcweir 
1875cdf0e10cSrcweir 	// teil die Sets auf (fuer Selektion in Nodes)
1876cdf0e10cSrcweir 	const SfxItemSet* pSet = &rSet;
1877cdf0e10cSrcweir 	SfxItemSet aTxtSet( *rSet.GetPool(), RES_TXTATR_BEGIN, RES_TXTATR_END-1 );
1878cdf0e10cSrcweir 
1879cdf0e10cSrcweir 	// gesamter Bereich
1880cdf0e10cSrcweir     if ( !nStt && (nEnd == m_Text.Len()) &&
1881cdf0e10cSrcweir          !(nMode & nsSetAttrMode::SETATTR_NOFORMATATTR ) )
1882cdf0e10cSrcweir 	{
1883cdf0e10cSrcweir 		// sind am Node schon Zeichenvorlagen gesetzt, muss man diese Attribute
1884cdf0e10cSrcweir 		// (rSet) immer als TextAttribute setzen, damit sie angezeigt werden.
1885cdf0e10cSrcweir 		int bHasCharFmts = sal_False;
1886cdf0e10cSrcweir         if ( HasHints() )
1887cdf0e10cSrcweir         {
1888cdf0e10cSrcweir             for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
1889cdf0e10cSrcweir             {
1890cdf0e10cSrcweir                 if ( (*m_pSwpHints)[ n ]->IsCharFmtAttr() )
1891cdf0e10cSrcweir                 {
1892cdf0e10cSrcweir 					bHasCharFmts = sal_True;
1893cdf0e10cSrcweir 					break;
1894cdf0e10cSrcweir                 }
1895cdf0e10cSrcweir             }
1896cdf0e10cSrcweir         }
1897cdf0e10cSrcweir 
1898cdf0e10cSrcweir 		if( !bHasCharFmts )
1899cdf0e10cSrcweir 		{
1900cdf0e10cSrcweir             aTxtSet.Put( rSet );
1901cdf0e10cSrcweir             // If there are any character attributes in rSet,
1902cdf0e10cSrcweir             // we want to set them at the paragraph:
1903cdf0e10cSrcweir 			if( aTxtSet.Count() != rSet.Count() )
1904cdf0e10cSrcweir 			{
1905cdf0e10cSrcweir                 sal_Bool bRet = SetAttr( rSet );
1906cdf0e10cSrcweir           		if( !aTxtSet.Count() )
1907cdf0e10cSrcweir 		    		return bRet;
1908cdf0e10cSrcweir 			}
1909cdf0e10cSrcweir 
1910cdf0e10cSrcweir             // check for auto style:
1911cdf0e10cSrcweir             const SfxPoolItem* pItem;
1912cdf0e10cSrcweir             const bool bAutoStyle = SFX_ITEM_SET == aTxtSet.GetItemState( RES_TXTATR_AUTOFMT, sal_False, &pItem );
1913cdf0e10cSrcweir             if ( bAutoStyle )
1914cdf0e10cSrcweir             {
1915cdf0e10cSrcweir                 boost::shared_ptr<SfxItemSet> pAutoStyleSet = static_cast<const SwFmtAutoFmt*>(pItem)->GetStyleHandle();
1916cdf0e10cSrcweir                 sal_Bool bRet = SetAttr( *pAutoStyleSet );
1917cdf0e10cSrcweir           		if( 1 == aTxtSet.Count() )
1918cdf0e10cSrcweir 		    		return bRet;
1919cdf0e10cSrcweir             }
1920cdf0e10cSrcweir 
1921cdf0e10cSrcweir             // Continue with the text attributes:
1922cdf0e10cSrcweir 			pSet = &aTxtSet;
1923cdf0e10cSrcweir 		}
1924cdf0e10cSrcweir 	}
1925cdf0e10cSrcweir 
1926cdf0e10cSrcweir     GetOrCreateSwpHints();
1927cdf0e10cSrcweir 
1928cdf0e10cSrcweir     SfxItemSet aCharSet( *rSet.GetPool(), aCharAutoFmtSetRange );
1929cdf0e10cSrcweir 
1930cdf0e10cSrcweir     sal_uInt16 nCount = 0;
1931cdf0e10cSrcweir 	SfxItemIter aIter( *pSet );
1932cdf0e10cSrcweir 	const SfxPoolItem* pItem = aIter.GetCurItem();
1933cdf0e10cSrcweir 
1934cdf0e10cSrcweir     do
1935cdf0e10cSrcweir     {
1936cdf0e10cSrcweir         if ( pItem && (reinterpret_cast<SfxPoolItem*>(-1) != pItem))
1937cdf0e10cSrcweir         {
1938cdf0e10cSrcweir             const sal_uInt16 nWhich = pItem->Which();
1939cdf0e10cSrcweir             ASSERT( isCHRATR(nWhich) || isTXTATR(nWhich),
1940cdf0e10cSrcweir                     "SwTxtNode::SetAttr(): unknown attribute" );
1941cdf0e10cSrcweir             if ( isCHRATR(nWhich) || isTXTATR(nWhich) )
1942cdf0e10cSrcweir             {
1943cdf0e10cSrcweir                 if ((RES_TXTATR_CHARFMT == nWhich) &&
1944cdf0e10cSrcweir                     (GetDoc()->GetDfltCharFmt() ==
1945cdf0e10cSrcweir                      static_cast<const SwFmtCharFmt*>(pItem)->GetCharFmt()))
1946cdf0e10cSrcweir                 {
1947cdf0e10cSrcweir                     SwIndex aIndex( this, nStt );
194869a74367SOliver-Rainer Wittmann                     RstTxtAttr( aIndex, nEnd - nStt, RES_TXTATR_CHARFMT, 0 );
1949cdf0e10cSrcweir                     DontExpandFmt( aIndex );
1950cdf0e10cSrcweir                 }
1951cdf0e10cSrcweir                 else
1952cdf0e10cSrcweir                 {
1953cdf0e10cSrcweir                     if (isCHRATR(nWhich) ||
1954cdf0e10cSrcweir                         (RES_TXTATR_UNKNOWN_CONTAINER == nWhich))
1955cdf0e10cSrcweir                     {
1956cdf0e10cSrcweir                         aCharSet.Put( *pItem );
1957cdf0e10cSrcweir                     }
1958cdf0e10cSrcweir                     else
1959cdf0e10cSrcweir                     {
1960cdf0e10cSrcweir 
1961cdf0e10cSrcweir                         SwTxtAttr *const pNew = MakeTxtAttr( *GetDoc(),
1962cdf0e10cSrcweir                                 const_cast<SfxPoolItem&>(*pItem), nStt, nEnd );
1963cdf0e10cSrcweir                         if ( pNew )
1964cdf0e10cSrcweir                         {
1965cdf0e10cSrcweir                             if ( nEnd != nStt && !pNew->GetEnd() )
1966cdf0e10cSrcweir                             {
1967cdf0e10cSrcweir                                 ASSERT(false,
1968cdf0e10cSrcweir                                     "Attribut without end, but area marked");
1969cdf0e10cSrcweir                                 DestroyAttr( pNew ); // do not insert
1970cdf0e10cSrcweir                             }
1971cdf0e10cSrcweir                             else if ( InsertHint( pNew, nMode ) )
1972cdf0e10cSrcweir                             {
1973cdf0e10cSrcweir                                 ++nCount;
1974cdf0e10cSrcweir                             }
1975cdf0e10cSrcweir                         }
1976cdf0e10cSrcweir                     }
1977cdf0e10cSrcweir                 }
1978cdf0e10cSrcweir             }
1979cdf0e10cSrcweir         }
1980cdf0e10cSrcweir         if ( aIter.IsAtEnd() )
1981cdf0e10cSrcweir             break;
1982cdf0e10cSrcweir         pItem = aIter.NextItem();
1983cdf0e10cSrcweir     } while( true );
1984cdf0e10cSrcweir 
1985cdf0e10cSrcweir     if ( aCharSet.Count() )
1986cdf0e10cSrcweir     {
1987cdf0e10cSrcweir         SwTxtAttr* pTmpNew = MakeTxtAttr( *GetDoc(), aCharSet, nStt, nEnd );
1988cdf0e10cSrcweir         if ( InsertHint( pTmpNew, nMode ) )
1989cdf0e10cSrcweir         {
1990cdf0e10cSrcweir             ++nCount;
1991cdf0e10cSrcweir         }
1992cdf0e10cSrcweir     }
1993cdf0e10cSrcweir 
1994cdf0e10cSrcweir     TryDeleteSwpHints();
1995cdf0e10cSrcweir 
1996cdf0e10cSrcweir 	return nCount ? sal_True : sal_False;
1997cdf0e10cSrcweir }
1998cdf0e10cSrcweir 
lcl_MergeAttr(SfxItemSet & rSet,const SfxPoolItem & rAttr)1999cdf0e10cSrcweir void lcl_MergeAttr( SfxItemSet& rSet, const SfxPoolItem& rAttr )
2000cdf0e10cSrcweir {
2001cdf0e10cSrcweir     if ( RES_TXTATR_AUTOFMT == rAttr.Which() )
2002cdf0e10cSrcweir 	{
2003cdf0e10cSrcweir         const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
2004cdf0e10cSrcweir         if ( !pCFSet )
2005cdf0e10cSrcweir             return;
2006cdf0e10cSrcweir         SfxWhichIter aIter( *pCFSet );
2007cdf0e10cSrcweir         sal_uInt16 nWhich = aIter.FirstWhich();
2008cdf0e10cSrcweir         while( nWhich )
2009cdf0e10cSrcweir         {
2010cdf0e10cSrcweir             if( ( nWhich < RES_CHRATR_END ||
2011cdf0e10cSrcweir                   RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) &&
2012cdf0e10cSrcweir                 ( SFX_ITEM_SET == pCFSet->GetItemState( nWhich, sal_True ) ) )
2013cdf0e10cSrcweir                 rSet.Put( pCFSet->Get( nWhich ) );
2014cdf0e10cSrcweir             nWhich = aIter.NextWhich();
2015cdf0e10cSrcweir         }
2016cdf0e10cSrcweir     }
2017cdf0e10cSrcweir     else
2018cdf0e10cSrcweir     	rSet.Put( rAttr );
2019cdf0e10cSrcweir }
2020cdf0e10cSrcweir 
lcl_MergeAttr_ExpandChrFmt(SfxItemSet & rSet,const SfxPoolItem & rAttr)2021cdf0e10cSrcweir void lcl_MergeAttr_ExpandChrFmt( SfxItemSet& rSet, const SfxPoolItem& rAttr )
2022cdf0e10cSrcweir {
2023cdf0e10cSrcweir 	if( RES_TXTATR_CHARFMT == rAttr.Which() ||
2024cdf0e10cSrcweir 		RES_TXTATR_INETFMT == rAttr.Which() ||
2025cdf0e10cSrcweir         RES_TXTATR_AUTOFMT == rAttr.Which() )
2026cdf0e10cSrcweir 	{
2027cdf0e10cSrcweir         const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
2028cdf0e10cSrcweir 
2029cdf0e10cSrcweir         if ( pCFSet )
2030cdf0e10cSrcweir         {
2031cdf0e10cSrcweir             SfxWhichIter aIter( *pCFSet );
2032cdf0e10cSrcweir             sal_uInt16 nWhich = aIter.FirstWhich();
2033cdf0e10cSrcweir             while( nWhich )
2034cdf0e10cSrcweir             {
2035cdf0e10cSrcweir                 if( ( nWhich < RES_CHRATR_END ||
2036cdf0e10cSrcweir                       ( RES_TXTATR_AUTOFMT == rAttr.Which() && RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) ) &&
2037cdf0e10cSrcweir                     ( SFX_ITEM_SET == pCFSet->GetItemState( nWhich, sal_True ) ) )
2038cdf0e10cSrcweir                     rSet.Put( pCFSet->Get( nWhich ) );
2039cdf0e10cSrcweir                 nWhich = aIter.NextWhich();
2040cdf0e10cSrcweir             }
2041cdf0e10cSrcweir         }
2042cdf0e10cSrcweir     }
2043cdf0e10cSrcweir 
2044cdf0e10cSrcweir 	// aufnehmen als MergeWert (falls noch nicht gesetzt neu setzen!)
2045cdf0e10cSrcweir 
2046cdf0e10cSrcweir /* wenn mehrere Attribute ueberlappen gewinnt der letze !!
2047cdf0e10cSrcweir  z.B
2048cdf0e10cSrcweir 			1234567890123456789
2049cdf0e10cSrcweir 			  |------------| 		Font1
2050cdf0e10cSrcweir 				 |------|			Font2
2051cdf0e10cSrcweir 					^  ^
2052cdf0e10cSrcweir 					|--|		Abfragebereich: -> Gueltig ist Font2
2053cdf0e10cSrcweir */
2054cdf0e10cSrcweir     rSet.Put( rAttr );
2055cdf0e10cSrcweir }
2056cdf0e10cSrcweir 
2057cdf0e10cSrcweir struct SwPoolItemEndPair
2058cdf0e10cSrcweir {
2059cdf0e10cSrcweir public:
2060cdf0e10cSrcweir     const SfxPoolItem* mpItem;
2061cdf0e10cSrcweir     xub_StrLen mnEndPos;
2062cdf0e10cSrcweir 
SwPoolItemEndPairSwPoolItemEndPair2063cdf0e10cSrcweir     SwPoolItemEndPair() : mpItem( 0 ), mnEndPos( 0 ) {};
2064cdf0e10cSrcweir };
2065cdf0e10cSrcweir 
2066cdf0e10cSrcweir // --> OD 2008-01-16 #newlistlevelattrs#
lcl_MergeListLevelIndentAsLRSpaceItem(const SwTxtNode & rTxtNode,SfxItemSet & rSet)2067cdf0e10cSrcweir void lcl_MergeListLevelIndentAsLRSpaceItem( const SwTxtNode& rTxtNode,
2068cdf0e10cSrcweir                                             SfxItemSet& rSet )
2069cdf0e10cSrcweir {
2070cdf0e10cSrcweir     if ( rTxtNode.AreListLevelIndentsApplicable() )
2071cdf0e10cSrcweir     {
2072cdf0e10cSrcweir         const SwNumRule* pRule = rTxtNode.GetNumRule();
2073cdf0e10cSrcweir         if ( pRule && rTxtNode.GetActualListLevel() >= 0 )
2074cdf0e10cSrcweir         {
2075cdf0e10cSrcweir             const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(rTxtNode.GetActualListLevel()));
2076cdf0e10cSrcweir             if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2077cdf0e10cSrcweir             {
2078cdf0e10cSrcweir                 SvxLRSpaceItem aLR( RES_LR_SPACE );
2079cdf0e10cSrcweir                 aLR.SetTxtLeft( rFmt.GetIndentAt() );
2080cdf0e10cSrcweir                 aLR.SetTxtFirstLineOfst( static_cast<short>(rFmt.GetFirstLineIndent()) );
2081cdf0e10cSrcweir                 rSet.Put( aLR );
2082cdf0e10cSrcweir             }
2083cdf0e10cSrcweir         }
2084cdf0e10cSrcweir     }
2085cdf0e10cSrcweir }
2086cdf0e10cSrcweir 
2087cdf0e10cSrcweir // erfrage die Attribute vom TextNode ueber den Bereich
2088cdf0e10cSrcweir // --> OD 2008-01-16 #newlistlevelattrs#
GetAttr(SfxItemSet & rSet,xub_StrLen nStt,xub_StrLen nEnd,sal_Bool bOnlyTxtAttr,sal_Bool bGetFromChrFmt,const bool bMergeIndentValuesOfNumRule) const2089cdf0e10cSrcweir sal_Bool SwTxtNode::GetAttr( SfxItemSet& rSet, xub_StrLen nStt, xub_StrLen nEnd,
2090cdf0e10cSrcweir                          sal_Bool bOnlyTxtAttr, sal_Bool bGetFromChrFmt,
2091cdf0e10cSrcweir                          const bool bMergeIndentValuesOfNumRule ) const
2092cdf0e10cSrcweir {
2093cdf0e10cSrcweir     if( HasHints() )
2094cdf0e10cSrcweir     {
2095cdf0e10cSrcweir 		/* stelle erstmal fest, welche Text-Attribut in dem Bereich gueltig
2096cdf0e10cSrcweir 		 * sind. Dabei gibt es folgende Faelle:
2097cdf0e10cSrcweir 		 * 	UnEindeutig wenn: (wenn != Format-Attribut)
2098cdf0e10cSrcweir 		 * 		- das Attribut liegt vollstaendig im Bereich
2099cdf0e10cSrcweir 		 * 		- das Attributende liegt im Bereich
2100cdf0e10cSrcweir 		 * 		- der Attributanfang liegt im Bereich:
2101cdf0e10cSrcweir 		 * Eindeutig (im Set mergen):
2102cdf0e10cSrcweir 		 *		- das Attrib umfasst den Bereich
2103cdf0e10cSrcweir 		 * nichts tun:
2104cdf0e10cSrcweir 		 * 		das Attribut liegt ausserhalb des Bereiches
2105cdf0e10cSrcweir 		 */
2106cdf0e10cSrcweir 
2107cdf0e10cSrcweir 		void (*fnMergeAttr)( SfxItemSet&, const SfxPoolItem& )
2108cdf0e10cSrcweir 			= bGetFromChrFmt ? &lcl_MergeAttr_ExpandChrFmt
2109cdf0e10cSrcweir 							 : &lcl_MergeAttr;
2110cdf0e10cSrcweir 
2111cdf0e10cSrcweir 		// dann besorge mal die Auto-(Fmt)Attribute
2112cdf0e10cSrcweir 		SfxItemSet aFmtSet( *rSet.GetPool(), rSet.GetRanges() );
2113cdf0e10cSrcweir 		if( !bOnlyTxtAttr )
2114cdf0e10cSrcweir         {
2115cdf0e10cSrcweir 			SwCntntNode::GetAttr( aFmtSet );
2116cdf0e10cSrcweir             // --> OD 2008-01-16 #newlistlevelattrs#
2117cdf0e10cSrcweir             if ( bMergeIndentValuesOfNumRule )
2118cdf0e10cSrcweir             {
2119cdf0e10cSrcweir                 lcl_MergeListLevelIndentAsLRSpaceItem( *this, aFmtSet );
2120cdf0e10cSrcweir             }
2121cdf0e10cSrcweir             // <--
2122cdf0e10cSrcweir         }
2123cdf0e10cSrcweir 
2124cdf0e10cSrcweir         const sal_uInt16 nSize = m_pSwpHints->Count();
2125cdf0e10cSrcweir 
2126cdf0e10cSrcweir         if( nStt == nEnd )             // kein Bereich:
2127cdf0e10cSrcweir 		{
2128cdf0e10cSrcweir             for (sal_uInt16 n = 0; n < nSize; ++n)
2129cdf0e10cSrcweir             {
2130cdf0e10cSrcweir                 const SwTxtAttr* pHt = (*m_pSwpHints)[n];
2131cdf0e10cSrcweir                 const xub_StrLen nAttrStart = *pHt->GetStart();
2132cdf0e10cSrcweir 				if( nAttrStart > nEnd ) 		// ueber den Bereich hinaus
2133cdf0e10cSrcweir 					break;
2134cdf0e10cSrcweir 
213569a74367SOliver-Rainer Wittmann                 const xub_StrLen* pAttrEnd = pHt->End();
2136cdf0e10cSrcweir                 if ( ! pAttrEnd ) // no attributes without end
2137cdf0e10cSrcweir 					continue;
2138cdf0e10cSrcweir 
2139cdf0e10cSrcweir                 if( ( nAttrStart < nStt &&
2140cdf0e10cSrcweir                         ( pHt->DontExpand() ? nStt < *pAttrEnd
2141cdf0e10cSrcweir                                             : nStt <= *pAttrEnd )) ||
2142cdf0e10cSrcweir                     ( nStt == nAttrStart &&
2143cdf0e10cSrcweir                         ( nAttrStart == *pAttrEnd || !nStt )))
2144cdf0e10cSrcweir 					(*fnMergeAttr)( rSet, pHt->GetAttr() );
2145cdf0e10cSrcweir 			}
2146cdf0e10cSrcweir 		}
2147cdf0e10cSrcweir 		else							// es ist ein Bereich definiert
2148cdf0e10cSrcweir 		{
2149cdf0e10cSrcweir             // --> FME 2007-03-13 #i75299#
2150cdf0e10cSrcweir             ::std::auto_ptr< std::vector< SwPoolItemEndPair > > pAttrArr;
2151cdf0e10cSrcweir             // <--
2152cdf0e10cSrcweir 
2153cdf0e10cSrcweir 			const sal_uInt16 coArrSz = static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
2154cdf0e10cSrcweir                                    static_cast<sal_uInt16>(RES_CHRATR_BEGIN);
2155cdf0e10cSrcweir 
2156cdf0e10cSrcweir             for (sal_uInt16 n = 0; n < nSize; ++n)
2157cdf0e10cSrcweir             {
2158cdf0e10cSrcweir                 const SwTxtAttr* pHt = (*m_pSwpHints)[n];
2159cdf0e10cSrcweir                 const xub_StrLen nAttrStart = *pHt->GetStart();
2160cdf0e10cSrcweir 				if( nAttrStart > nEnd ) 		// ueber den Bereich hinaus
2161cdf0e10cSrcweir 					break;
2162cdf0e10cSrcweir 
216369a74367SOliver-Rainer Wittmann                 const xub_StrLen* pAttrEnd = pHt->End();
2164cdf0e10cSrcweir                 if ( ! pAttrEnd ) // no attributes without end
2165cdf0e10cSrcweir 					continue;
2166cdf0e10cSrcweir 
2167cdf0e10cSrcweir 				sal_Bool bChkInvalid = sal_False;
2168cdf0e10cSrcweir                 if( nAttrStart <= nStt )       // vor oder genau Start
2169cdf0e10cSrcweir 				{
2170cdf0e10cSrcweir                     if( *pAttrEnd <= nStt )    // liegt davor
2171cdf0e10cSrcweir 						continue;
2172cdf0e10cSrcweir 
2173cdf0e10cSrcweir 					if( nEnd <= *pAttrEnd )		// hinter oder genau Ende
2174cdf0e10cSrcweir 						(*fnMergeAttr)( aFmtSet, pHt->GetAttr() );
2175cdf0e10cSrcweir 					else
2176cdf0e10cSrcweir //					else if( pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
2177cdf0e10cSrcweir 						// uneindeutig
2178cdf0e10cSrcweir 						bChkInvalid = sal_True;
2179cdf0e10cSrcweir 				}
2180cdf0e10cSrcweir 				else if( nAttrStart < nEnd 		// reicht in den Bereich
2181cdf0e10cSrcweir )//						 && pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
2182cdf0e10cSrcweir 					bChkInvalid = sal_True;
2183cdf0e10cSrcweir 
2184cdf0e10cSrcweir 				if( bChkInvalid )
2185cdf0e10cSrcweir 				{
2186cdf0e10cSrcweir 					// uneindeutig ?
2187cdf0e10cSrcweir                     ::std::auto_ptr< SfxItemIter > pItemIter;
2188cdf0e10cSrcweir                     const SfxPoolItem* pItem = 0;
2189cdf0e10cSrcweir 
2190cdf0e10cSrcweir                     if ( RES_TXTATR_AUTOFMT == pHt->Which() )
2191cdf0e10cSrcweir                     {
2192cdf0e10cSrcweir                         const SfxItemSet* pAutoSet = CharFmt::GetItemSet( pHt->GetAttr() );
2193cdf0e10cSrcweir                         if ( pAutoSet )
2194cdf0e10cSrcweir                         {
2195cdf0e10cSrcweir                             pItemIter.reset( new SfxItemIter( *pAutoSet ) );
2196cdf0e10cSrcweir                             pItem = pItemIter->GetCurItem();
2197cdf0e10cSrcweir                         }
2198cdf0e10cSrcweir                     }
2199cdf0e10cSrcweir                     else
2200cdf0e10cSrcweir                         pItem = &pHt->GetAttr();
2201cdf0e10cSrcweir 
2202cdf0e10cSrcweir                     const sal_uInt16 nHintEnd = *pAttrEnd;
2203cdf0e10cSrcweir 
2204cdf0e10cSrcweir                     while ( pItem )
2205cdf0e10cSrcweir                     {
2206cdf0e10cSrcweir                         const sal_uInt16 nHintWhich = pItem->Which();
2207cdf0e10cSrcweir                         ASSERT(!isUNKNOWNATR(nHintWhich),
220886e1cf34SPedro Giffuni                                 "SwTxtNode::GetAttr(): unknown attribute?");
2209cdf0e10cSrcweir 
2210cdf0e10cSrcweir                         if ( !pAttrArr.get() )
2211cdf0e10cSrcweir                         {
2212cdf0e10cSrcweir                             pAttrArr.reset(
2213cdf0e10cSrcweir                                 new std::vector< SwPoolItemEndPair >(coArrSz));
2214cdf0e10cSrcweir                         }
2215cdf0e10cSrcweir 
2216cdf0e10cSrcweir                         std::vector< SwPoolItemEndPair >::iterator pPrev = pAttrArr->begin();
2217cdf0e10cSrcweir                         if (isCHRATR(nHintWhich) ||
2218cdf0e10cSrcweir                             isTXTATR_WITHEND(nHintWhich))
2219cdf0e10cSrcweir                         {
2220cdf0e10cSrcweir                             pPrev += nHintWhich - RES_CHRATR_BEGIN;
2221cdf0e10cSrcweir                         }
2222cdf0e10cSrcweir                         else
2223cdf0e10cSrcweir                         {
2224cdf0e10cSrcweir                             pPrev = pAttrArr->end();
2225cdf0e10cSrcweir                         }
2226cdf0e10cSrcweir 
2227cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2228cdf0e10cSrcweir                         SwPoolItemEndPair aTmp = *pPrev;
2229cdf0e10cSrcweir #endif
2230cdf0e10cSrcweir 
2231cdf0e10cSrcweir                         if( pPrev != pAttrArr->end() )
2232cdf0e10cSrcweir                         {
2233cdf0e10cSrcweir                             if( !pPrev->mpItem )
2234cdf0e10cSrcweir                             {
2235cdf0e10cSrcweir                                 if ( bOnlyTxtAttr || *pItem != aFmtSet.Get( nHintWhich ) )
2236cdf0e10cSrcweir                                 {
2237cdf0e10cSrcweir                                     if( nAttrStart > nStt )
2238cdf0e10cSrcweir                                     {
2239cdf0e10cSrcweir                                         rSet.InvalidateItem( nHintWhich );
2240cdf0e10cSrcweir                                         pPrev->mpItem = (SfxPoolItem*)-1;
2241cdf0e10cSrcweir                                     }
2242cdf0e10cSrcweir                                     else
2243cdf0e10cSrcweir                                     {
2244cdf0e10cSrcweir                                         pPrev->mpItem = pItem;
2245cdf0e10cSrcweir                                         pPrev->mnEndPos = nHintEnd;
2246cdf0e10cSrcweir                                     }
2247cdf0e10cSrcweir                                 }
2248cdf0e10cSrcweir                             }
2249cdf0e10cSrcweir                             else if( (SfxPoolItem*)-1 != pPrev->mpItem )
2250cdf0e10cSrcweir                             {
2251cdf0e10cSrcweir                                 if( pPrev->mnEndPos == nAttrStart &&
2252cdf0e10cSrcweir                                     *pPrev->mpItem == *pItem )
2253cdf0e10cSrcweir                                 {
2254cdf0e10cSrcweir                                     pPrev->mpItem = pItem;
2255cdf0e10cSrcweir                                     pPrev->mnEndPos = nHintEnd;
2256cdf0e10cSrcweir                                 }
2257cdf0e10cSrcweir                                 else
2258cdf0e10cSrcweir                                 {
2259cdf0e10cSrcweir                                     rSet.InvalidateItem( nHintWhich );
2260cdf0e10cSrcweir                                     pPrev->mpItem = (SfxPoolItem*)-1;
2261cdf0e10cSrcweir                                 }
2262cdf0e10cSrcweir                             }
2263cdf0e10cSrcweir                         }
2264cdf0e10cSrcweir 
2265cdf0e10cSrcweir                         pItem = ( pItemIter.get() && !pItemIter->IsAtEnd() )
2266cdf0e10cSrcweir                                     ? pItemIter->NextItem() : 0;
2267cdf0e10cSrcweir                     } // end while
2268cdf0e10cSrcweir                 }
2269cdf0e10cSrcweir 			}
2270cdf0e10cSrcweir 
2271cdf0e10cSrcweir             if ( pAttrArr.get() )
2272cdf0e10cSrcweir 			{
2273cdf0e10cSrcweir                 for (sal_uInt16 n = 0; n < coArrSz; ++n)
2274cdf0e10cSrcweir                 {
2275cdf0e10cSrcweir                     const SwPoolItemEndPair& rItemPair = (*pAttrArr)[ n ];
2276cdf0e10cSrcweir                     if( (0 != rItemPair.mpItem) && ((SfxPoolItem*)-1 != rItemPair.mpItem) )
2277cdf0e10cSrcweir                     {
2278cdf0e10cSrcweir                         const sal_uInt16 nWh =
2279cdf0e10cSrcweir                             static_cast<sal_uInt16>(n + RES_CHRATR_BEGIN);
2280cdf0e10cSrcweir 
2281cdf0e10cSrcweir                         if( nEnd <= rItemPair.mnEndPos ) // hinter oder genau Ende
2282cdf0e10cSrcweir                         {
2283cdf0e10cSrcweir                             if( *rItemPair.mpItem != aFmtSet.Get( nWh ) )
2284cdf0e10cSrcweir                                 (*fnMergeAttr)( rSet, *rItemPair.mpItem );
2285cdf0e10cSrcweir                         }
2286cdf0e10cSrcweir                         else
2287cdf0e10cSrcweir                             // uneindeutig
2288cdf0e10cSrcweir                             rSet.InvalidateItem( nWh );
2289cdf0e10cSrcweir                     }
2290cdf0e10cSrcweir                 }
2291cdf0e10cSrcweir 			}
2292cdf0e10cSrcweir 		}
2293cdf0e10cSrcweir 		if( aFmtSet.Count() )
2294cdf0e10cSrcweir 		{
2295cdf0e10cSrcweir 			// aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind
2296cdf0e10cSrcweir 			aFmtSet.Differentiate( rSet );
2297cdf0e10cSrcweir 			// jetzt alle zusammen "mergen"
2298cdf0e10cSrcweir 			rSet.Put( aFmtSet );
2299cdf0e10cSrcweir 		}
2300cdf0e10cSrcweir 	}
2301cdf0e10cSrcweir 	else if( !bOnlyTxtAttr )
2302cdf0e10cSrcweir     {
2303cdf0e10cSrcweir 		// dann besorge mal die Auto-(Fmt)Attribute
2304cdf0e10cSrcweir 		SwCntntNode::GetAttr( rSet );
2305cdf0e10cSrcweir         // --> OD 2008-01-16 #newlistlevelattrs#
2306cdf0e10cSrcweir         if ( bMergeIndentValuesOfNumRule )
2307cdf0e10cSrcweir         {
2308cdf0e10cSrcweir             lcl_MergeListLevelIndentAsLRSpaceItem( *this, rSet );
2309cdf0e10cSrcweir         }
2310cdf0e10cSrcweir         // <--
2311cdf0e10cSrcweir     }
2312cdf0e10cSrcweir 
2313cdf0e10cSrcweir 	return rSet.Count() ? sal_True : sal_False;
2314cdf0e10cSrcweir }
2315cdf0e10cSrcweir 
2316cdf0e10cSrcweir 
2317cdf0e10cSrcweir namespace
2318cdf0e10cSrcweir {
2319cdf0e10cSrcweir 
2320cdf0e10cSrcweir typedef std::pair<sal_uInt16, sal_uInt16> AttrSpan_t;
2321cdf0e10cSrcweir typedef std::multimap<AttrSpan_t, const SwTxtAttr*> AttrSpanMap_t;
2322cdf0e10cSrcweir 
2323cdf0e10cSrcweir 
2324cdf0e10cSrcweir struct IsAutoStyle
2325cdf0e10cSrcweir {
2326cdf0e10cSrcweir     bool
operator ()__anon01211f380111::IsAutoStyle2327cdf0e10cSrcweir     operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
2328cdf0e10cSrcweir     const
2329cdf0e10cSrcweir     {
2330cdf0e10cSrcweir         return i_rAttrSpan.second && i_rAttrSpan.second->Which() == RES_TXTATR_AUTOFMT;
2331cdf0e10cSrcweir     }
2332cdf0e10cSrcweir };
2333cdf0e10cSrcweir 
2334cdf0e10cSrcweir 
2335cdf0e10cSrcweir /** Removes from io_rAttrSet all items that are set by style on the
2336cdf0e10cSrcweir     given span.
2337cdf0e10cSrcweir   */
2338cdf0e10cSrcweir struct RemovePresentAttrs
2339cdf0e10cSrcweir {
RemovePresentAttrs__anon01211f380111::RemovePresentAttrs2340cdf0e10cSrcweir     RemovePresentAttrs(SfxItemSet& io_rAttrSet)
2341cdf0e10cSrcweir         : m_rAttrSet(io_rAttrSet)
2342cdf0e10cSrcweir     {
2343cdf0e10cSrcweir     }
2344cdf0e10cSrcweir 
2345cdf0e10cSrcweir     void
operator ()__anon01211f380111::RemovePresentAttrs2346cdf0e10cSrcweir     operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
2347cdf0e10cSrcweir     const
2348cdf0e10cSrcweir     {
2349cdf0e10cSrcweir         if (!i_rAttrSpan.second)
2350cdf0e10cSrcweir         {
2351cdf0e10cSrcweir             return;
2352cdf0e10cSrcweir         }
2353cdf0e10cSrcweir 
2354cdf0e10cSrcweir         const SwTxtAttr* const pAutoStyle(i_rAttrSpan.second);
2355cdf0e10cSrcweir         SfxItemIter aIter(m_rAttrSet);
2356cdf0e10cSrcweir         const SfxPoolItem* pItem(aIter.GetCurItem());
2357cdf0e10cSrcweir         while (pItem)
2358cdf0e10cSrcweir         {
2359cdf0e10cSrcweir             const sal_uInt16 nWhich(pItem->Which());
2360cdf0e10cSrcweir             if (CharFmt::IsItemIncluded(nWhich, pAutoStyle))
2361cdf0e10cSrcweir             {
2362cdf0e10cSrcweir                 m_rAttrSet.ClearItem(nWhich);
2363cdf0e10cSrcweir             }
2364cdf0e10cSrcweir 
2365cdf0e10cSrcweir             if (aIter.IsAtEnd())
2366cdf0e10cSrcweir             {
2367cdf0e10cSrcweir                 break;
2368cdf0e10cSrcweir             }
2369cdf0e10cSrcweir             pItem = aIter.NextItem();
2370cdf0e10cSrcweir         }
2371cdf0e10cSrcweir     }
2372cdf0e10cSrcweir 
2373cdf0e10cSrcweir private:
2374cdf0e10cSrcweir     SfxItemSet& m_rAttrSet;
2375cdf0e10cSrcweir };
2376cdf0e10cSrcweir 
2377cdf0e10cSrcweir 
2378cdf0e10cSrcweir /** Collects all style-covered spans from i_rHints to o_rSpanMap. In
2379cdf0e10cSrcweir     addition inserts dummy spans with pointer to format equal to 0 for
2380cdf0e10cSrcweir     all gaps (i.e. spans not covered by any style). This simplifies
2381cdf0e10cSrcweir     creation of autostyles for all needed spans, but it means all code
2382cdf0e10cSrcweir     that tries to access the pointer has to check if it's non-null!
2383cdf0e10cSrcweir  */
2384cdf0e10cSrcweir void
lcl_CollectHintSpans(const SwpHints & i_rHints,const sal_uInt16 nLength,AttrSpanMap_t & o_rSpanMap)2385cdf0e10cSrcweir lcl_CollectHintSpans(const SwpHints& i_rHints, const sal_uInt16 nLength,
2386cdf0e10cSrcweir         AttrSpanMap_t& o_rSpanMap)
2387cdf0e10cSrcweir {
2388cdf0e10cSrcweir     sal_uInt16 nLastEnd(0);
2389cdf0e10cSrcweir 
2390cdf0e10cSrcweir     for (sal_uInt16 i(0); i != i_rHints.Count(); ++i)
2391cdf0e10cSrcweir     {
2392cdf0e10cSrcweir         const SwTxtAttr* const pHint(i_rHints[i]);
2393cdf0e10cSrcweir         const sal_uInt16 nWhich(pHint->Which());
2394cdf0e10cSrcweir         if (nWhich == RES_TXTATR_CHARFMT || nWhich == RES_TXTATR_AUTOFMT)
2395cdf0e10cSrcweir         {
239669a74367SOliver-Rainer Wittmann             const AttrSpan_t aSpan(*pHint->GetStart(), *pHint->End());
2397cdf0e10cSrcweir             o_rSpanMap.insert(AttrSpanMap_t::value_type(aSpan, pHint));
2398cdf0e10cSrcweir 
2399cdf0e10cSrcweir             // < not != because there may be multiple CHARFMT at same range
2400cdf0e10cSrcweir             if (nLastEnd < aSpan.first)
2401cdf0e10cSrcweir             {
2402cdf0e10cSrcweir                 // insert dummy span covering the gap
2403cdf0e10cSrcweir                 o_rSpanMap.insert(AttrSpanMap_t::value_type(
2404cdf0e10cSrcweir                             AttrSpan_t(nLastEnd, aSpan.first), 0));
2405cdf0e10cSrcweir             }
2406cdf0e10cSrcweir 
2407cdf0e10cSrcweir             nLastEnd = aSpan.second;
2408cdf0e10cSrcweir         }
2409cdf0e10cSrcweir     }
2410cdf0e10cSrcweir 
2411cdf0e10cSrcweir     // no hints at the end (special case: no hints at all in i_rHints)
2412cdf0e10cSrcweir     if (nLastEnd != nLength && nLength != 0)
2413cdf0e10cSrcweir     {
2414cdf0e10cSrcweir         o_rSpanMap.insert(
2415cdf0e10cSrcweir             AttrSpanMap_t::value_type(AttrSpan_t(nLastEnd, nLength), 0));
2416cdf0e10cSrcweir     }
2417cdf0e10cSrcweir }
2418cdf0e10cSrcweir 
2419cdf0e10cSrcweir 
2420cdf0e10cSrcweir void
lcl_FillWhichIds(const SfxItemSet & i_rAttrSet,std::vector<sal_uInt16> & o_rClearIds)2421cdf0e10cSrcweir lcl_FillWhichIds(const SfxItemSet& i_rAttrSet, std::vector<sal_uInt16>& o_rClearIds)
2422cdf0e10cSrcweir {
2423cdf0e10cSrcweir     o_rClearIds.reserve(i_rAttrSet.Count());
2424cdf0e10cSrcweir     SfxItemIter aIter(i_rAttrSet);
2425cdf0e10cSrcweir     const SfxPoolItem* pItem(aIter.GetCurItem());
2426cdf0e10cSrcweir     while (true)
2427cdf0e10cSrcweir     {
2428cdf0e10cSrcweir         o_rClearIds.push_back(pItem->Which());
2429cdf0e10cSrcweir 
2430cdf0e10cSrcweir         if (aIter.IsAtEnd())
2431cdf0e10cSrcweir         {
2432cdf0e10cSrcweir             break;
2433cdf0e10cSrcweir         }
2434cdf0e10cSrcweir         pItem = aIter.NextItem();
2435cdf0e10cSrcweir     }
2436cdf0e10cSrcweir }
2437cdf0e10cSrcweir 
2438cdf0e10cSrcweir struct SfxItemSetClearer
2439cdf0e10cSrcweir {
2440cdf0e10cSrcweir     SfxItemSet & m_rItemSet;
SfxItemSetClearer__anon01211f380111::SfxItemSetClearer2441cdf0e10cSrcweir     SfxItemSetClearer(SfxItemSet & rItemSet) : m_rItemSet(rItemSet) { }
operator ()__anon01211f380111::SfxItemSetClearer2442cdf0e10cSrcweir     void operator()(sal_uInt16 const nWhich) { m_rItemSet.ClearItem(nWhich); }
2443cdf0e10cSrcweir };
2444cdf0e10cSrcweir 
2445cdf0e10cSrcweir }
2446cdf0e10cSrcweir 
2447cdf0e10cSrcweir 
2448cdf0e10cSrcweir /** Does the hard work of SwTxtNode::FmtToTxtAttr: the real conversion
2449cdf0e10cSrcweir     of items to automatic styles.
2450cdf0e10cSrcweir  */
2451cdf0e10cSrcweir void
impl_FmtToTxtAttr(const SfxItemSet & i_rAttrSet)2452cdf0e10cSrcweir SwTxtNode::impl_FmtToTxtAttr(const SfxItemSet& i_rAttrSet)
2453cdf0e10cSrcweir {
2454cdf0e10cSrcweir     typedef AttrSpanMap_t::iterator AttrSpanMap_iterator_t;
2455cdf0e10cSrcweir     AttrSpanMap_t aAttrSpanMap;
2456cdf0e10cSrcweir 
2457cdf0e10cSrcweir     if (i_rAttrSet.Count() == 0)
2458cdf0e10cSrcweir     {
2459cdf0e10cSrcweir         return;
2460cdf0e10cSrcweir     }
2461cdf0e10cSrcweir 
2462cdf0e10cSrcweir     // 1. Identify all spans in hints' array
2463cdf0e10cSrcweir 
2464cdf0e10cSrcweir     lcl_CollectHintSpans(*m_pSwpHints, m_Text.Len(), aAttrSpanMap);
2465cdf0e10cSrcweir 
2466cdf0e10cSrcweir     // 2. Go through all spans and insert new attrs
2467cdf0e10cSrcweir 
2468cdf0e10cSrcweir     AttrSpanMap_iterator_t aCurRange(aAttrSpanMap.begin());
2469cdf0e10cSrcweir     const AttrSpanMap_iterator_t aEnd(aAttrSpanMap.end());
2470cdf0e10cSrcweir     while (aCurRange != aEnd)
2471cdf0e10cSrcweir     {
2472cdf0e10cSrcweir         typedef std::pair<AttrSpanMap_iterator_t, AttrSpanMap_iterator_t>
2473cdf0e10cSrcweir             AttrSpanMapRange_t;
2474cdf0e10cSrcweir         AttrSpanMapRange_t aRange(aAttrSpanMap.equal_range(aCurRange->first));
2475cdf0e10cSrcweir 
2476cdf0e10cSrcweir         // 2a. Collect attributes to insert
2477cdf0e10cSrcweir 
2478cdf0e10cSrcweir         SfxItemSet aCurSet(i_rAttrSet);
2479cdf0e10cSrcweir         std::for_each(aRange.first, aRange.second, RemovePresentAttrs(aCurSet));
2480cdf0e10cSrcweir 
2481cdf0e10cSrcweir         // 2b. Insert automatic style containing the collected attributes
2482cdf0e10cSrcweir 
2483cdf0e10cSrcweir         if (aCurSet.Count() != 0)
2484cdf0e10cSrcweir         {
2485cdf0e10cSrcweir             AttrSpanMap_iterator_t aAutoStyleIt(
2486cdf0e10cSrcweir                     std::find_if(aRange.first, aRange.second, IsAutoStyle()));
2487cdf0e10cSrcweir             if (aAutoStyleIt != aRange.second)
2488cdf0e10cSrcweir             {
2489cdf0e10cSrcweir                 // there already is an automatic style on that span:
2490cdf0e10cSrcweir                 // create new one and remove the original one
2491cdf0e10cSrcweir                 SwTxtAttr* const pAutoStyle(const_cast<SwTxtAttr*>(aAutoStyleIt->second));
2492cdf0e10cSrcweir                 const boost::shared_ptr<SfxItemSet> pOldStyle(
2493cdf0e10cSrcweir                         static_cast<const SwFmtAutoFmt&>(
2494cdf0e10cSrcweir                             pAutoStyle->GetAttr()).GetStyleHandle());
2495cdf0e10cSrcweir                 aCurSet.Put(*pOldStyle);
2496cdf0e10cSrcweir 
2497cdf0e10cSrcweir                 // remove the old hint
2498cdf0e10cSrcweir                 m_pSwpHints->Delete(pAutoStyle);
2499cdf0e10cSrcweir                 DestroyAttr(pAutoStyle);
2500cdf0e10cSrcweir             }
2501cdf0e10cSrcweir             m_pSwpHints->Insert(
2502cdf0e10cSrcweir                     MakeTxtAttr(*GetDoc(), aCurSet,
2503cdf0e10cSrcweir                         aCurRange->first.first, aCurRange->first.second));
2504cdf0e10cSrcweir         }
2505cdf0e10cSrcweir 
2506cdf0e10cSrcweir         aCurRange = aRange.second;
2507cdf0e10cSrcweir     }
2508cdf0e10cSrcweir 
2509cdf0e10cSrcweir     // 3. Clear items from the node
2510cdf0e10cSrcweir     std::vector<sal_uInt16> aClearedIds;
2511cdf0e10cSrcweir     lcl_FillWhichIds(i_rAttrSet, aClearedIds);
2512cdf0e10cSrcweir     ClearItemsFromAttrSet(aClearedIds);
2513cdf0e10cSrcweir }
2514cdf0e10cSrcweir 
FmtToTxtAttr(SwTxtNode * pNd)2515cdf0e10cSrcweir void SwTxtNode::FmtToTxtAttr( SwTxtNode* pNd )
2516cdf0e10cSrcweir {
2517cdf0e10cSrcweir 	SfxItemSet aThisSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
2518cdf0e10cSrcweir     if( HasSwAttrSet() && GetpSwAttrSet()->Count() )
2519cdf0e10cSrcweir 		aThisSet.Put( *GetpSwAttrSet() );
2520cdf0e10cSrcweir 
2521cdf0e10cSrcweir     GetOrCreateSwpHints();
2522cdf0e10cSrcweir 
2523cdf0e10cSrcweir 	if( pNd == this )
2524cdf0e10cSrcweir 	{
2525cdf0e10cSrcweir         impl_FmtToTxtAttr(aThisSet);
2526cdf0e10cSrcweir     }
2527cdf0e10cSrcweir 	else
2528cdf0e10cSrcweir 	{
2529cdf0e10cSrcweir         // There are five possible combinations of items from this and
2530cdf0e10cSrcweir         // pNd (pNd is the 'main' node):
2531cdf0e10cSrcweir         //
2532cdf0e10cSrcweir         //  case    pNd     this     action
2533cdf0e10cSrcweir         //  ----------------------------------------------------
2534cdf0e10cSrcweir         //     1     -       -      do nothing
2535cdf0e10cSrcweir         //     2     -       a      convert item to attr of this
2536cdf0e10cSrcweir         //     3     a       -      convert item to attr of pNd
2537cdf0e10cSrcweir         //     4     a       a      clear item in this
2538cdf0e10cSrcweir         //     5     a       b      convert item to attr of this
2539cdf0e10cSrcweir 
2540cdf0e10cSrcweir 		SfxItemSet aNdSet( pNd->GetDoc()->GetAttrPool(), aCharFmtSetRange );
2541cdf0e10cSrcweir         if( pNd->HasSwAttrSet() && pNd->GetpSwAttrSet()->Count() )
2542cdf0e10cSrcweir 			aNdSet.Put( *pNd->GetpSwAttrSet() );
2543cdf0e10cSrcweir 
2544cdf0e10cSrcweir         pNd->GetOrCreateSwpHints();
2545cdf0e10cSrcweir 
2546cdf0e10cSrcweir         std::vector<sal_uInt16> aProcessedIds;
2547cdf0e10cSrcweir 
2548cdf0e10cSrcweir 		if( aThisSet.Count() )
2549cdf0e10cSrcweir 		{
2550cdf0e10cSrcweir 			SfxItemIter aIter( aThisSet );
2551cdf0e10cSrcweir 			const SfxPoolItem* pItem = aIter.GetCurItem(), *pNdItem = 0;
2552cdf0e10cSrcweir             SfxItemSet aConvertSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
2553cdf0e10cSrcweir             std::vector<sal_uInt16> aClearWhichIds;
2554cdf0e10cSrcweir 
2555cdf0e10cSrcweir 			while( true )
2556cdf0e10cSrcweir 			{
2557cdf0e10cSrcweir 				if( SFX_ITEM_SET == aNdSet.GetItemState( pItem->Which(), sal_False, &pNdItem ) )
2558cdf0e10cSrcweir                 {
2559cdf0e10cSrcweir                     if (*pItem == *pNdItem) // 4
2560cdf0e10cSrcweir                     {
2561cdf0e10cSrcweir                         aClearWhichIds.push_back( pItem->Which() );
2562cdf0e10cSrcweir                     }
2563cdf0e10cSrcweir                     else    // 5
2564cdf0e10cSrcweir                     {
2565cdf0e10cSrcweir                         aConvertSet.Put(*pItem);
2566cdf0e10cSrcweir                     }
2567cdf0e10cSrcweir                     aProcessedIds.push_back(pItem->Which());
2568cdf0e10cSrcweir                 }
2569cdf0e10cSrcweir                 else    // 2
2570cdf0e10cSrcweir                 {
2571cdf0e10cSrcweir                     aConvertSet.Put(*pItem);
2572cdf0e10cSrcweir                 }
2573cdf0e10cSrcweir 
2574cdf0e10cSrcweir 				if( aIter.IsAtEnd() )
2575cdf0e10cSrcweir 					break;
2576cdf0e10cSrcweir 				pItem = aIter.NextItem();
2577cdf0e10cSrcweir 			}
2578cdf0e10cSrcweir 
2579cdf0e10cSrcweir             // 4/ clear items of this that are set with the same value on pNd
2580cdf0e10cSrcweir             ClearItemsFromAttrSet( aClearWhichIds );
2581cdf0e10cSrcweir 
2582cdf0e10cSrcweir             // 2, 5/ convert all other items to attrs
2583cdf0e10cSrcweir             impl_FmtToTxtAttr(aConvertSet);
2584cdf0e10cSrcweir         }
2585cdf0e10cSrcweir 
2586cdf0e10cSrcweir         {
2587cdf0e10cSrcweir             std::for_each(aProcessedIds.begin(), aProcessedIds.end(),
2588cdf0e10cSrcweir                     SfxItemSetClearer(aNdSet));
2589cdf0e10cSrcweir 
2590cdf0e10cSrcweir             // 3/ convert items to attrs
2591cdf0e10cSrcweir             pNd->impl_FmtToTxtAttr(aNdSet);
2592cdf0e10cSrcweir 
2593cdf0e10cSrcweir             if( aNdSet.Count() )
2594cdf0e10cSrcweir             {
2595cdf0e10cSrcweir                 SwFmtChg aTmp1( pNd->GetFmtColl() );
2596cdf0e10cSrcweir                 pNd->NotifyClients( &aTmp1, &aTmp1 );
2597cdf0e10cSrcweir             }
2598cdf0e10cSrcweir         }
2599cdf0e10cSrcweir     }
2600cdf0e10cSrcweir 
2601cdf0e10cSrcweir     SetCalcHiddenCharFlags();
2602cdf0e10cSrcweir 
2603cdf0e10cSrcweir     pNd->TryDeleteSwpHints();
2604cdf0e10cSrcweir }
2605cdf0e10cSrcweir 
2606cdf0e10cSrcweir /*************************************************************************
2607cdf0e10cSrcweir  *						SwpHints::CalcFlags()
2608cdf0e10cSrcweir  *************************************************************************/
2609cdf0e10cSrcweir 
CalcFlags()2610cdf0e10cSrcweir void SwpHints::CalcFlags()
2611cdf0e10cSrcweir {
2612cdf0e10cSrcweir     m_bDDEFields = m_bFootnote = false;
2613c0286415SOliver-Rainer Wittmann     const sal_uInt16 nSize = Count();
2614c0286415SOliver-Rainer Wittmann     const SwTxtAttr* pAttr;
2615c0286415SOliver-Rainer Wittmann     for( sal_uInt16 nPos = 0; nPos < nSize; ++nPos )
2616cdf0e10cSrcweir     {
2617c0286415SOliver-Rainer Wittmann         switch( ( pAttr = (*this)[ nPos ])->Which() )
2618c0286415SOliver-Rainer Wittmann         {
2619c0286415SOliver-Rainer Wittmann         case RES_TXTATR_FTN:
2620cdf0e10cSrcweir             m_bFootnote = true;
2621cdf0e10cSrcweir             if ( m_bDDEFields )
2622cdf0e10cSrcweir                 return;
2623c0286415SOliver-Rainer Wittmann             break;
2624c0286415SOliver-Rainer Wittmann         case RES_TXTATR_FIELD:
2625c0286415SOliver-Rainer Wittmann             {
2626c0286415SOliver-Rainer Wittmann                 const SwField* pFld = pAttr->GetFmtFld().GetField();
2627c0286415SOliver-Rainer Wittmann                 if( RES_DDEFLD == pFld->GetTyp()->Which() )
2628cdf0e10cSrcweir                 {
2629cdf0e10cSrcweir                     m_bDDEFields = true;
2630cdf0e10cSrcweir                     if ( m_bFootnote )
2631cdf0e10cSrcweir                         return;
2632cdf0e10cSrcweir                 }
2633cdf0e10cSrcweir             }
2634cdf0e10cSrcweir             break;
2635cdf0e10cSrcweir         }
2636cdf0e10cSrcweir     }
2637cdf0e10cSrcweir }
2638cdf0e10cSrcweir 
2639cdf0e10cSrcweir /*************************************************************************
2640cdf0e10cSrcweir  *						SwpHints::CalcVisibleFlag()
2641cdf0e10cSrcweir  *************************************************************************/
2642cdf0e10cSrcweir 
CalcHiddenParaField()2643cdf0e10cSrcweir bool SwpHints::CalcHiddenParaField()
2644cdf0e10cSrcweir {
2645cdf0e10cSrcweir     m_bCalcHiddenParaField = false;
2646cdf0e10cSrcweir     bool bOldHasHiddenParaField = m_bHasHiddenParaField;
2647cdf0e10cSrcweir     bool bNewHasHiddenParaField  = false;
2648dec99bbdSOliver-Rainer Wittmann     const sal_uInt16	nSize = Count();
2649dec99bbdSOliver-Rainer Wittmann     const SwTxtAttr *pTxtHt;
2650cdf0e10cSrcweir 
2651dec99bbdSOliver-Rainer Wittmann     for( sal_uInt16 nPos = 0; nPos < nSize; ++nPos )
2652dec99bbdSOliver-Rainer Wittmann     {
2653dec99bbdSOliver-Rainer Wittmann         pTxtHt = (*this)[ nPos ];
2654dec99bbdSOliver-Rainer Wittmann         const sal_uInt16 nWhich = pTxtHt->Which();
2655cdf0e10cSrcweir 
2656dec99bbdSOliver-Rainer Wittmann         if( RES_TXTATR_FIELD == nWhich )
2657dec99bbdSOliver-Rainer Wittmann         {
2658dec99bbdSOliver-Rainer Wittmann             const SwFmtFld& rFld = pTxtHt->GetFmtFld();
2659c0286415SOliver-Rainer Wittmann             if( RES_HIDDENPARAFLD == rFld.GetField()->GetTyp()->Which() )
2660dec99bbdSOliver-Rainer Wittmann             {
2661dec99bbdSOliver-Rainer Wittmann                 if( !((SwHiddenParaField*)rFld.GetField())->IsHidden() )
2662cdf0e10cSrcweir                 {
2663cdf0e10cSrcweir                     SetHiddenParaField(false);
2664cdf0e10cSrcweir                     return bOldHasHiddenParaField != bNewHasHiddenParaField;
2665cdf0e10cSrcweir                 }
2666cdf0e10cSrcweir                 else
2667cdf0e10cSrcweir                 {
2668cdf0e10cSrcweir                     bNewHasHiddenParaField = true;
2669cdf0e10cSrcweir                 }
2670cdf0e10cSrcweir             }
2671cdf0e10cSrcweir         }
2672cdf0e10cSrcweir     }
2673cdf0e10cSrcweir     SetHiddenParaField( bNewHasHiddenParaField );
2674cdf0e10cSrcweir     return bOldHasHiddenParaField != bNewHasHiddenParaField;
2675cdf0e10cSrcweir }
2676cdf0e10cSrcweir 
2677cdf0e10cSrcweir 
2678cdf0e10cSrcweir /*************************************************************************
2679cdf0e10cSrcweir  *						SwpHints::NoteInHistory()
2680cdf0e10cSrcweir  *************************************************************************/
2681cdf0e10cSrcweir 
NoteInHistory(SwTxtAttr * pAttr,const bool bNew)2682cdf0e10cSrcweir void SwpHints::NoteInHistory( SwTxtAttr *pAttr, const bool bNew )
2683cdf0e10cSrcweir {
2684cdf0e10cSrcweir     if ( m_pHistory ) { m_pHistory->AddHint( pAttr, bNew ); }
2685cdf0e10cSrcweir }
2686cdf0e10cSrcweir 
2687cdf0e10cSrcweir /*************************************************************************
2688cdf0e10cSrcweir  *                      SwpHints::MergePortions( )
2689cdf0e10cSrcweir  *************************************************************************/
2690cdf0e10cSrcweir 
MergePortions(SwTxtNode & rNode)2691cdf0e10cSrcweir bool SwpHints::MergePortions( SwTxtNode& rNode )
2692cdf0e10cSrcweir {
2693cdf0e10cSrcweir     if ( !Count() )
2694cdf0e10cSrcweir         return false;
2695cdf0e10cSrcweir 
2696cdf0e10cSrcweir     // sort before merging
2697cdf0e10cSrcweir     SwpHintsArray::Resort();
2698cdf0e10cSrcweir 
2699cdf0e10cSrcweir     bool bRet = false;
2700cdf0e10cSrcweir     typedef std::multimap< int, SwTxtAttr* > PortionMap;
2701cdf0e10cSrcweir     PortionMap aPortionMap;
2702cdf0e10cSrcweir     xub_StrLen nLastPorStart = STRING_LEN;
2703cdf0e10cSrcweir     sal_uInt16 i = 0;
2704cdf0e10cSrcweir     int nKey = 0;
2705cdf0e10cSrcweir 
2706cdf0e10cSrcweir     // get portions by start position:
2707cdf0e10cSrcweir     for ( i = 0; i < Count(); ++i )
2708cdf0e10cSrcweir     {
2709cdf0e10cSrcweir         SwTxtAttr *pHt = GetTextHint( i );
2710cdf0e10cSrcweir         if ( RES_TXTATR_CHARFMT != pHt->Which() &&
2711cdf0e10cSrcweir              RES_TXTATR_AUTOFMT != pHt->Which() )
2712cdf0e10cSrcweir              //&&
2713cdf0e10cSrcweir              //RES_TXTATR_INETFMT != pHt->Which() )
2714cdf0e10cSrcweir             continue;
2715cdf0e10cSrcweir 
2716cdf0e10cSrcweir         const xub_StrLen nPorStart = *pHt->GetStart();
2717cdf0e10cSrcweir         if ( nPorStart != nLastPorStart && nLastPorStart != STRING_LEN )
2718cdf0e10cSrcweir             ++nKey;
2719cdf0e10cSrcweir         nLastPorStart = nPorStart;
2720cdf0e10cSrcweir         aPortionMap.insert( std::pair< const int, SwTxtAttr* >( nKey, pHt ) );
2721cdf0e10cSrcweir     }
2722cdf0e10cSrcweir 
2723cdf0e10cSrcweir     // check if portion i can be merged with portion i+1:
2724cdf0e10cSrcweir     i = 0;
2725cdf0e10cSrcweir     int j = i + 1;
2726cdf0e10cSrcweir     while ( i <= nKey )
2727cdf0e10cSrcweir     {
2728cdf0e10cSrcweir         std::pair< PortionMap::iterator, PortionMap::iterator > aRange1 = aPortionMap.equal_range( i );
2729cdf0e10cSrcweir         std::pair< PortionMap::iterator, PortionMap::iterator > aRange2 = aPortionMap.equal_range( j );
2730cdf0e10cSrcweir         PortionMap::iterator aIter1 = aRange1.first;
2731cdf0e10cSrcweir         PortionMap::iterator aIter2 = aRange2.first;
2732cdf0e10cSrcweir 
2733cdf0e10cSrcweir         bool bMerge = true;
2734cdf0e10cSrcweir         const sal_uInt16 nAttributesInPor1  = static_cast<sal_uInt16>(std::distance( aRange1.first, aRange1.second ));
2735cdf0e10cSrcweir         const sal_uInt16 nAttributesInPor2  = static_cast<sal_uInt16>(std::distance( aRange2.first, aRange2.second ));
2736cdf0e10cSrcweir 
2737cdf0e10cSrcweir         if ( nAttributesInPor1 == nAttributesInPor2 && nAttributesInPor1 != 0 )
2738cdf0e10cSrcweir         {
2739cdf0e10cSrcweir             while ( aIter1 != aRange1.second )
2740cdf0e10cSrcweir             {
2741cdf0e10cSrcweir                 const SwTxtAttr* p1 = (*aIter1).second;
2742cdf0e10cSrcweir                 const SwTxtAttr* p2 = (*aIter2).second;
274369a74367SOliver-Rainer Wittmann                 if ( *p1->End() < *p2->GetStart() || p1->Which() != p2->Which() || !(*p1 == *p2) )
2744cdf0e10cSrcweir                 {
2745cdf0e10cSrcweir                     bMerge = false;
2746cdf0e10cSrcweir                     break;
2747cdf0e10cSrcweir                 }
2748cdf0e10cSrcweir                 ++aIter1;
2749cdf0e10cSrcweir                 ++aIter2;
2750cdf0e10cSrcweir             }
2751cdf0e10cSrcweir         }
2752cdf0e10cSrcweir         else
2753cdf0e10cSrcweir         {
2754cdf0e10cSrcweir             bMerge = false;
2755cdf0e10cSrcweir         }
2756cdf0e10cSrcweir 
2757cdf0e10cSrcweir         if ( bMerge )
2758cdf0e10cSrcweir         {
2759cdf0e10cSrcweir             // erase all elements with key i + 1
2760cdf0e10cSrcweir             xub_StrLen nNewPortionEnd = 0;
2761cdf0e10cSrcweir             for ( aIter2 = aRange2.first; aIter2 != aRange2.second; ++aIter2 )
2762cdf0e10cSrcweir             {
2763cdf0e10cSrcweir                 SwTxtAttr* p2 = (*aIter2).second;
2764cdf0e10cSrcweir                 nNewPortionEnd = *p2->GetEnd();
2765cdf0e10cSrcweir 
2766cdf0e10cSrcweir                 const sal_uInt16 nCountBeforeDelete = Count();
2767cdf0e10cSrcweir                 Delete( p2 );
2768cdf0e10cSrcweir 
2769cdf0e10cSrcweir                 // robust: check if deletion actually took place before destroying attribute:
2770cdf0e10cSrcweir                 if ( Count() < nCountBeforeDelete )
2771cdf0e10cSrcweir                     rNode.DestroyAttr( p2 );
2772cdf0e10cSrcweir             }
2773cdf0e10cSrcweir             aPortionMap.erase( aRange2.first, aRange2.second );
2774cdf0e10cSrcweir             ++j;
2775cdf0e10cSrcweir 
2776cdf0e10cSrcweir             // change all attributes with key i
2777cdf0e10cSrcweir             aRange1 = aPortionMap.equal_range( i );
2778cdf0e10cSrcweir             for ( aIter1 = aRange1.first; aIter1 != aRange1.second; ++aIter1 )
2779cdf0e10cSrcweir             {
2780cdf0e10cSrcweir                 SwTxtAttr* p1 = (*aIter1).second;
2781cdf0e10cSrcweir                 NoteInHistory( p1 );
2782cdf0e10cSrcweir                 *p1->GetEnd() = nNewPortionEnd;
2783cdf0e10cSrcweir                 NoteInHistory( p1, true );
2784cdf0e10cSrcweir                 bRet = true;
2785cdf0e10cSrcweir             }
2786cdf0e10cSrcweir         }
2787cdf0e10cSrcweir         else
2788cdf0e10cSrcweir         {
2789cdf0e10cSrcweir             ++i;
2790cdf0e10cSrcweir             j = i + 1;
2791cdf0e10cSrcweir         }
2792cdf0e10cSrcweir     }
2793cdf0e10cSrcweir 
2794cdf0e10cSrcweir     if ( bRet )
2795cdf0e10cSrcweir     {
2796cdf0e10cSrcweir         SwpHintsArray::Resort();
2797cdf0e10cSrcweir     }
2798cdf0e10cSrcweir 
2799cdf0e10cSrcweir     return bRet;
2800cdf0e10cSrcweir }
2801cdf0e10cSrcweir 
2802cdf0e10cSrcweir // check if there is already a character format and adjust the sort numbers
lcl_CheckSortNumber(const SwpHints & rHints,SwTxtCharFmt & rNewCharFmt)2803cdf0e10cSrcweir void lcl_CheckSortNumber( const SwpHints& rHints, SwTxtCharFmt& rNewCharFmt )
2804cdf0e10cSrcweir {
2805cdf0e10cSrcweir     const xub_StrLen nHtStart = *rNewCharFmt.GetStart();
2806cdf0e10cSrcweir     const xub_StrLen nHtEnd   = *rNewCharFmt.GetEnd();
2807cdf0e10cSrcweir     sal_uInt16 nSortNumber = 0;
2808cdf0e10cSrcweir 
2809cdf0e10cSrcweir     for ( sal_uInt16 i = 0; i < rHints.Count(); ++i )
2810cdf0e10cSrcweir     {
2811cdf0e10cSrcweir         const SwTxtAttr* pOtherHt = rHints[i];
2812cdf0e10cSrcweir 
2813cdf0e10cSrcweir         const xub_StrLen nOtherStart = *pOtherHt->GetStart();
2814cdf0e10cSrcweir 
2815cdf0e10cSrcweir         if ( nOtherStart > nHtStart )
2816cdf0e10cSrcweir             break;
2817cdf0e10cSrcweir 
2818cdf0e10cSrcweir         if ( RES_TXTATR_CHARFMT == pOtherHt->Which() )
2819cdf0e10cSrcweir         {
282069a74367SOliver-Rainer Wittmann             const xub_StrLen nOtherEnd = *pOtherHt->End();
2821cdf0e10cSrcweir 
2822cdf0e10cSrcweir             if ( nOtherStart == nHtStart && nOtherEnd == nHtEnd )
2823cdf0e10cSrcweir             {
2824cdf0e10cSrcweir                 const sal_uInt16 nOtherSortNum = static_cast<const SwTxtCharFmt*>(pOtherHt)->GetSortNumber();
2825cdf0e10cSrcweir                 nSortNumber = nOtherSortNum + 1;
2826cdf0e10cSrcweir             }
2827cdf0e10cSrcweir         }
2828cdf0e10cSrcweir     }
2829cdf0e10cSrcweir 
2830cdf0e10cSrcweir     if ( nSortNumber > 0 )
2831cdf0e10cSrcweir         rNewCharFmt.SetSortNumber( nSortNumber );
2832cdf0e10cSrcweir }
2833cdf0e10cSrcweir 
2834cdf0e10cSrcweir /*************************************************************************
2835cdf0e10cSrcweir  *						SwpHints::Insert()
2836cdf0e10cSrcweir  *************************************************************************/
2837cdf0e10cSrcweir 
2838cdf0e10cSrcweir /*
2839cdf0e10cSrcweir  * Try to insert the new hint.
2840cdf0e10cSrcweir  * Depending on the type of the hint, this either always succeeds, or may fail.
2841cdf0e10cSrcweir  * Depending on the type of the hint, other hints may be deleted or
2842cdf0e10cSrcweir  * overwritten.
2843cdf0e10cSrcweir  * The return value indicates successful insertion.
2844cdf0e10cSrcweir  */
TryInsertHint(SwTxtAttr * const pHint,SwTxtNode & rNode,const SetAttrMode nMode)2845dec99bbdSOliver-Rainer Wittmann bool SwpHints::TryInsertHint(
2846dec99bbdSOliver-Rainer Wittmann     SwTxtAttr* const pHint,
2847dec99bbdSOliver-Rainer Wittmann     SwTxtNode &rNode,
2848dec99bbdSOliver-Rainer Wittmann     const SetAttrMode nMode )
2849cdf0e10cSrcweir {
2850cdf0e10cSrcweir     if ( USHRT_MAX == Count() ) // we're sorry, this flight is overbooked...
2851cdf0e10cSrcweir     {
2852cdf0e10cSrcweir         ASSERT(false, "hints array full :-(");
2853cdf0e10cSrcweir         return false;
2854cdf0e10cSrcweir     }
2855cdf0e10cSrcweir 
2856cdf0e10cSrcweir 	// Felder bilden eine Ausnahme:
2857cdf0e10cSrcweir 	// 1) Sie koennen nie ueberlappen
2858cdf0e10cSrcweir 	// 2) Wenn zwei Felder genau aneinander liegen,
2859cdf0e10cSrcweir 	//	  sollen sie nicht zu einem verschmolzen werden.
2860cdf0e10cSrcweir 	// Wir koennen also auf die while-Schleife verzichten
2861cdf0e10cSrcweir 
2862cdf0e10cSrcweir     xub_StrLen *pHtEnd = pHint->GetEnd();
2863cdf0e10cSrcweir     sal_uInt16 nWhich = pHint->Which();
2864cdf0e10cSrcweir 
2865cdf0e10cSrcweir 	switch( nWhich )
2866cdf0e10cSrcweir 	{
2867cdf0e10cSrcweir 	case RES_TXTATR_CHARFMT:
2868cdf0e10cSrcweir     {
2869cdf0e10cSrcweir         // Check if character format contains hidden attribute:
2870cdf0e10cSrcweir         const SwCharFmt* pFmt = pHint->GetCharFmt().GetCharFmt();
2871cdf0e10cSrcweir         const SfxPoolItem* pItem;
2872cdf0e10cSrcweir         if ( SFX_ITEM_SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
2873cdf0e10cSrcweir             rNode.SetCalcHiddenCharFlags();
2874cdf0e10cSrcweir 
2875cdf0e10cSrcweir         ((SwTxtCharFmt*)pHint)->ChgTxtNode( &rNode );
2876cdf0e10cSrcweir 		break;
2877cdf0e10cSrcweir     }
2878cdf0e10cSrcweir     // --> FME 2007-03-16 #i75430# Recalc hidden flags if necessary
2879cdf0e10cSrcweir     case RES_TXTATR_AUTOFMT:
2880cdf0e10cSrcweir     {
2881cdf0e10cSrcweir         // Check if auto style contains hidden attribute:
2882cdf0e10cSrcweir         const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pHint, RES_CHRATR_HIDDEN );
2883cdf0e10cSrcweir         if ( pHiddenItem )
2884cdf0e10cSrcweir             rNode.SetCalcHiddenCharFlags();
2885cdf0e10cSrcweir         break;
2886cdf0e10cSrcweir     }
2887cdf0e10cSrcweir     // <--
2888dec99bbdSOliver-Rainer Wittmann 
2889cdf0e10cSrcweir     case RES_TXTATR_INETFMT:
2890cdf0e10cSrcweir         static_cast<SwTxtINetFmt*>(pHint)->InitINetFmt(rNode);
2891dec99bbdSOliver-Rainer Wittmann         break;
2892dec99bbdSOliver-Rainer Wittmann 
2893cdf0e10cSrcweir 	case RES_TXTATR_FIELD:
2894dec99bbdSOliver-Rainer Wittmann 	case RES_TXTATR_ANNOTATION:
289569a74367SOliver-Rainer Wittmann 	case RES_TXTATR_INPUTFIELD:
2896cdf0e10cSrcweir 		{
2897cdf0e10cSrcweir 			sal_Bool bDelFirst = 0 != ((SwTxtFld*)pHint)->GetpTxtNode();
2898cdf0e10cSrcweir 			((SwTxtFld*)pHint)->ChgTxtNode( &rNode );
2899cdf0e10cSrcweir 			SwDoc* pDoc = rNode.GetDoc();
2900c0286415SOliver-Rainer Wittmann 			const SwField* pFld = ((SwTxtFld*)pHint)->GetFmtFld().GetField();
2901cdf0e10cSrcweir 
2902cdf0e10cSrcweir 			if( !pDoc->IsNewFldLst() )
2903cdf0e10cSrcweir 			{
2904cdf0e10cSrcweir 				// was fuer ein Feld ist es denn ??
2905cdf0e10cSrcweir 				// bestimmte Felder mussen am Doc das Calculations-Flag updaten
2906cdf0e10cSrcweir 				switch( pFld->GetTyp()->Which() )
2907cdf0e10cSrcweir 				{
2908cdf0e10cSrcweir 				case RES_DBFLD:
2909cdf0e10cSrcweir 				case RES_SETEXPFLD:
2910cdf0e10cSrcweir 				case RES_HIDDENPARAFLD:
2911cdf0e10cSrcweir 				case RES_HIDDENTXTFLD:
2912cdf0e10cSrcweir 				case RES_DBNUMSETFLD:
2913cdf0e10cSrcweir 				case RES_DBNEXTSETFLD:
2914cdf0e10cSrcweir 					{
2915cdf0e10cSrcweir 						if( bDelFirst )
2916cdf0e10cSrcweir 							pDoc->InsDelFldInFldLst( sal_False, *(SwTxtFld*)pHint );
2917cdf0e10cSrcweir 						if( rNode.GetNodes().IsDocNodes() )
2918cdf0e10cSrcweir 							pDoc->InsDelFldInFldLst( sal_True, *(SwTxtFld*)pHint );
2919cdf0e10cSrcweir 					}
2920cdf0e10cSrcweir 					break;
2921cdf0e10cSrcweir 				case RES_DDEFLD:
2922cdf0e10cSrcweir 					if( rNode.GetNodes().IsDocNodes() )
2923cdf0e10cSrcweir 						((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
2924cdf0e10cSrcweir 					break;
2925cdf0e10cSrcweir 				}
2926cdf0e10cSrcweir 			}
2927cdf0e10cSrcweir 
2928c0286415SOliver-Rainer Wittmann             // gehts ins normale Nodes-Array?
2929c0286415SOliver-Rainer Wittmann             if( rNode.GetNodes().IsDocNodes() )
2930c0286415SOliver-Rainer Wittmann             {
2931c0286415SOliver-Rainer Wittmann                 sal_Bool bInsFldType = sal_False;
2932c0286415SOliver-Rainer Wittmann                 switch( pFld->GetTyp()->Which() )
2933c0286415SOliver-Rainer Wittmann                 {
2934c0286415SOliver-Rainer Wittmann                 case RES_SETEXPFLD:
2935c0286415SOliver-Rainer Wittmann                     bInsFldType = ((SwSetExpFieldType*)pFld->GetTyp())->IsDeleted();
2936c0286415SOliver-Rainer Wittmann                     if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFld->GetTyp())->GetType() )
2937c0286415SOliver-Rainer Wittmann                     {
2938c0286415SOliver-Rainer Wittmann                         // bevor die ReferenzNummer gesetzt wird, sollte
2939c0286415SOliver-Rainer Wittmann                         // das Feld am richtigen FeldTypen haengen!
2940c0286415SOliver-Rainer Wittmann                         SwSetExpFieldType* pFldType = (SwSetExpFieldType*)
2941c0286415SOliver-Rainer Wittmann                                     pDoc->InsertFldType( *pFld->GetTyp() );
2942c0286415SOliver-Rainer Wittmann                         if( pFldType != pFld->GetTyp() )
2943c0286415SOliver-Rainer Wittmann                         {
2944c0286415SOliver-Rainer Wittmann                             SwFmtFld* pFmtFld = (SwFmtFld*)&((SwTxtFld*)pHint)->GetFmtFld();
2945cdf0e10cSrcweir                             pFmtFld->RegisterToFieldType( *pFldType );
2946c0286415SOliver-Rainer Wittmann                             pFmtFld->GetField()->ChgTyp( pFldType );
2947c0286415SOliver-Rainer Wittmann                         }
2948c0286415SOliver-Rainer Wittmann                         pFldType->SetSeqRefNo( *(SwSetExpField*)pFld );
2949c0286415SOliver-Rainer Wittmann                     }
2950c0286415SOliver-Rainer Wittmann                     break;
2951c0286415SOliver-Rainer Wittmann                 case RES_USERFLD:
2952c0286415SOliver-Rainer Wittmann                     bInsFldType = ((SwUserFieldType*)pFld->GetTyp())->IsDeleted();
2953c0286415SOliver-Rainer Wittmann                     break;
2954cdf0e10cSrcweir 
2955c0286415SOliver-Rainer Wittmann                 case RES_DDEFLD:
2956c0286415SOliver-Rainer Wittmann                     if( pDoc->IsNewFldLst() )
2957c0286415SOliver-Rainer Wittmann                         ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
2958c0286415SOliver-Rainer Wittmann                     bInsFldType = ((SwDDEFieldType*)pFld->GetTyp())->IsDeleted();
2959c0286415SOliver-Rainer Wittmann                     break;
2960cdf0e10cSrcweir 
2961c0286415SOliver-Rainer Wittmann                 case RES_POSTITFLD:
2962c0286415SOliver-Rainer Wittmann                     if ( pDoc->GetDocShell() )
2963c0286415SOliver-Rainer Wittmann                         pDoc->GetDocShell()->Broadcast( SwFmtFldHint( &((SwTxtFld*)pHint)->GetFmtFld(), SWFMTFLD_INSERTED ) );
2964c0286415SOliver-Rainer Wittmann                     break;
2965c0286415SOliver-Rainer Wittmann                 }
2966c0286415SOliver-Rainer Wittmann                 if( bInsFldType )
2967c0286415SOliver-Rainer Wittmann                     pDoc->InsDeletedFldType( *pFld->GetTyp() );
2968c0286415SOliver-Rainer Wittmann             }
2969c0286415SOliver-Rainer Wittmann         }
2970c0286415SOliver-Rainer Wittmann         break;
2971c0286415SOliver-Rainer Wittmann     case RES_TXTATR_FTN :
2972cdf0e10cSrcweir 		((SwTxtFtn*)pHint)->ChgTxtNode( &rNode );
2973cdf0e10cSrcweir 		break;
2974cdf0e10cSrcweir 	case RES_TXTATR_REFMARK:
2975cdf0e10cSrcweir 		((SwTxtRefMark*)pHint)->ChgTxtNode( &rNode );
2976cdf0e10cSrcweir 		if( rNode.GetNodes().IsDocNodes() )
2977cdf0e10cSrcweir 		{
2978cdf0e10cSrcweir             // search for a reference with the same name
2979cdf0e10cSrcweir 			SwTxtAttr* pTmpHt;
2980cdf0e10cSrcweir 			xub_StrLen *pTmpHtEnd, *pTmpHintEnd;
2981cdf0e10cSrcweir 			for( sal_uInt16 n = 0, nEnd = Count(); n < nEnd; ++n )
2982cdf0e10cSrcweir             {
2983cdf0e10cSrcweir                 if (RES_TXTATR_REFMARK == (pTmpHt = GetTextHint(n))->Which() &&
2984cdf0e10cSrcweir 					pHint->GetAttr() == pTmpHt->GetAttr() &&
2985cdf0e10cSrcweir 					0 != ( pTmpHtEnd = pTmpHt->GetEnd() ) &&
2986cdf0e10cSrcweir 					0 != ( pTmpHintEnd = pHint->GetEnd() ) )
2987cdf0e10cSrcweir 				{
2988cdf0e10cSrcweir 					SwComparePosition eCmp = ::ComparePosition(
2989cdf0e10cSrcweir 							*pTmpHt->GetStart(), *pTmpHtEnd,
2990cdf0e10cSrcweir 							*pHint->GetStart(), *pTmpHintEnd );
2991cdf0e10cSrcweir 					sal_Bool bDelOld = sal_True, bChgStart = sal_False, bChgEnd = sal_False;
2992cdf0e10cSrcweir 					switch( eCmp )
2993cdf0e10cSrcweir 					{
2994cdf0e10cSrcweir 					case POS_BEFORE:
2995cdf0e10cSrcweir 					case POS_BEHIND:	bDelOld = sal_False; break;
2996cdf0e10cSrcweir 
2997cdf0e10cSrcweir 					case POS_OUTSIDE:	bChgStart = bChgEnd = sal_True; break;
2998cdf0e10cSrcweir 
2999cdf0e10cSrcweir 					case POS_COLLIDE_END:
3000cdf0e10cSrcweir 					case POS_OVERLAP_BEFORE:	bChgStart = sal_True; break;
3001cdf0e10cSrcweir 					case POS_COLLIDE_START:
3002cdf0e10cSrcweir 					case POS_OVERLAP_BEHIND:    bChgEnd = sal_True; break;
3003cdf0e10cSrcweir                     default: break;
3004cdf0e10cSrcweir 					}
3005cdf0e10cSrcweir 
3006cdf0e10cSrcweir 					if( bChgStart )
3007cdf0e10cSrcweir 						*pHint->GetStart() = *pTmpHt->GetStart();
3008cdf0e10cSrcweir 					if( bChgEnd )
3009cdf0e10cSrcweir 						*pTmpHintEnd = *pTmpHtEnd;
3010cdf0e10cSrcweir 
3011cdf0e10cSrcweir 					if( bDelOld )
3012cdf0e10cSrcweir                     {
3013cdf0e10cSrcweir                         NoteInHistory( pTmpHt );
3014cdf0e10cSrcweir 						rNode.DestroyAttr( Cut( n-- ) );
3015cdf0e10cSrcweir 						--nEnd;
3016cdf0e10cSrcweir 					}
3017cdf0e10cSrcweir 				}
3018cdf0e10cSrcweir             }
3019cdf0e10cSrcweir 		}
3020cdf0e10cSrcweir 		break;
3021cdf0e10cSrcweir 	case RES_TXTATR_TOXMARK:
3022cdf0e10cSrcweir 		((SwTxtTOXMark*)pHint)->ChgTxtNode( &rNode );
3023cdf0e10cSrcweir 		break;
3024cdf0e10cSrcweir 
3025cdf0e10cSrcweir 	case RES_TXTATR_CJK_RUBY:
3026cdf0e10cSrcweir         static_cast<SwTxtRuby*>(pHint)->InitRuby(rNode);
3027cdf0e10cSrcweir 		break;
3028cdf0e10cSrcweir 
3029cdf0e10cSrcweir     case RES_TXTATR_META:
3030cdf0e10cSrcweir     case RES_TXTATR_METAFIELD:
3031cdf0e10cSrcweir         static_cast<SwTxtMeta *>(pHint)->ChgTxtNode( &rNode );
3032cdf0e10cSrcweir         break;
3033cdf0e10cSrcweir 
3034cdf0e10cSrcweir     case RES_CHRATR_HIDDEN:
3035cdf0e10cSrcweir         rNode.SetCalcHiddenCharFlags();
3036cdf0e10cSrcweir         break;
3037cdf0e10cSrcweir 	}
3038cdf0e10cSrcweir 
3039cdf0e10cSrcweir 	if( nsSetAttrMode::SETATTR_DONTEXPAND & nMode )
3040cdf0e10cSrcweir 		pHint->SetDontExpand( sal_True );
3041cdf0e10cSrcweir 
3042cdf0e10cSrcweir 	// SwTxtAttrs ohne Ende werden sonderbehandelt:
3043cdf0e10cSrcweir 	// Sie werden natuerlich in das Array insertet, aber sie werden nicht
3044cdf0e10cSrcweir 	// in die pPrev/Next/On/Off-Verkettung aufgenommen.
3045cdf0e10cSrcweir 	// Der Formatierer erkennt diese TxtHints an dem CH_TXTATR_.. im Text !
3046cdf0e10cSrcweir 	xub_StrLen nHtStart = *pHint->GetStart();
3047cdf0e10cSrcweir 	if( !pHtEnd )
3048cdf0e10cSrcweir     {
3049cdf0e10cSrcweir         SwpHintsArray::Insert( pHint );
3050cdf0e10cSrcweir 		CalcFlags();
3051cdf0e10cSrcweir #ifdef DBG_UTIL
3052cdf0e10cSrcweir         if( !rNode.GetDoc()->IsInReading() )
3053cdf0e10cSrcweir             CHECK;
3054cdf0e10cSrcweir #endif
305556b35d86SArmin Le Grand         // ... und die Abhaengigen benachrichtigen
305656b35d86SArmin Le Grand         if(rNode.GetDepends())
305756b35d86SArmin Le Grand         {
305856b35d86SArmin Le Grand             SwUpdateAttr aHint(
305956b35d86SArmin Le Grand                 nHtStart,
306056b35d86SArmin Le Grand                 nHtStart,
306156b35d86SArmin Le Grand                 nWhich);
306256b35d86SArmin Le Grand 
306356b35d86SArmin Le Grand             rNode.ModifyNotification(0,&aHint);
3064cdf0e10cSrcweir         }
306556b35d86SArmin Le Grand 
3066cdf0e10cSrcweir         return true;
3067cdf0e10cSrcweir     }
3068cdf0e10cSrcweir 
3069cdf0e10cSrcweir 	// ----------------------------------------------------------------
3070cdf0e10cSrcweir 	// Ab hier gibt es nur noch pHint mit einem EndIdx !!!
3071cdf0e10cSrcweir 
3072cdf0e10cSrcweir     if( *pHtEnd < nHtStart )
3073cdf0e10cSrcweir 	{
3074cdf0e10cSrcweir 		ASSERT( *pHtEnd >= nHtStart,
3075cdf0e10cSrcweir 					"+SwpHints::Insert: invalid hint, end < start" );
3076cdf0e10cSrcweir 
3077cdf0e10cSrcweir 		// Wir drehen den Quatsch einfach um:
3078cdf0e10cSrcweir 		*pHint->GetStart() = *pHtEnd;
3079cdf0e10cSrcweir 		*pHtEnd = nHtStart;
3080cdf0e10cSrcweir 		nHtStart = *pHint->GetStart();
3081cdf0e10cSrcweir 	}
3082cdf0e10cSrcweir 
3083cdf0e10cSrcweir     // I need this value later on for notification but the pointer may become invalid
3084cdf0e10cSrcweir     const xub_StrLen nHintEnd = *pHtEnd;
3085cdf0e10cSrcweir     const bool bNoHintAdjustMode = (nsSetAttrMode::SETATTR_NOHINTADJUST & nMode);
3086cdf0e10cSrcweir 
3087cdf0e10cSrcweir     // handle nesting attributes: inserting may fail due to overlap!
3088cdf0e10cSrcweir     if (pHint->IsNesting())
3089cdf0e10cSrcweir     {
3090cdf0e10cSrcweir         const bool bRet(
3091cdf0e10cSrcweir             TryInsertNesting(rNode, *static_cast<SwTxtAttrNesting*>(pHint)));
3092cdf0e10cSrcweir         if (!bRet) return false;
3093cdf0e10cSrcweir     }
3094cdf0e10cSrcweir     // Currently REFMARK and TOXMARK have OverlapAllowed set to true.
3095cdf0e10cSrcweir     // These attributes may be inserted directly.
3096cdf0e10cSrcweir     // Also attributes without length may be inserted directly.
3097cdf0e10cSrcweir     // SETATTR_NOHINTADJUST is set e.g., during undo.
3098cdf0e10cSrcweir     // Portion building in not necessary during XML import.
3099cdf0e10cSrcweir     else
3100cdf0e10cSrcweir     if ( !bNoHintAdjustMode &&
3101cdf0e10cSrcweir          !pHint->IsOverlapAllowedAttr() &&
3102cdf0e10cSrcweir          !rNode.GetDoc()->IsInXMLImport() &&
3103cdf0e10cSrcweir          ( RES_TXTATR_AUTOFMT == nWhich ||
3104cdf0e10cSrcweir            RES_TXTATR_CHARFMT == nWhich ) )
3105cdf0e10cSrcweir     {
3106cdf0e10cSrcweir         ASSERT( nWhich != RES_TXTATR_AUTOFMT ||
3107cdf0e10cSrcweir                 static_cast<const SwFmtAutoFmt&>(pHint->GetAttr()).GetStyleHandle()->GetPool() ==
3108cdf0e10cSrcweir                 &rNode.GetDoc()->GetAttrPool(),
3109cdf0e10cSrcweir                 "AUTOSTYLES - Pool mismatch" )
3110cdf0e10cSrcweir 
3111cdf0e10cSrcweir         BuildPortions( rNode, *pHint, nMode );
3112cdf0e10cSrcweir 
3113cdf0e10cSrcweir         if ( nHtStart < nHintEnd ) // skip merging for 0-length attributes
3114cdf0e10cSrcweir             MergePortions( rNode );
3115cdf0e10cSrcweir     }
3116cdf0e10cSrcweir     else
3117cdf0e10cSrcweir     {
3118cdf0e10cSrcweir         // There may be more than one character style at the current position.
3119cdf0e10cSrcweir         // Take care of the sort number.
3120cdf0e10cSrcweir         // Special case ruby portion: During import, the ruby attribute is set
3121cdf0e10cSrcweir         // multiple times
3122cdf0e10cSrcweir         // Special case hyperlink: During import, the ruby attribute is set
3123cdf0e10cSrcweir         // multiple times
3124cdf0e10cSrcweir         // FME 2007-11-08 #i82989# in NOHINTADJUST mode, we want to insert
3125cdf0e10cSrcweir         // character attributes directly
3126cdf0e10cSrcweir         if ( ( RES_TXTATR_CHARFMT  == nWhich && !bNoHintAdjustMode ) )
3127cdf0e10cSrcweir         {
3128cdf0e10cSrcweir             BuildPortions( rNode, *pHint, nMode );
3129cdf0e10cSrcweir         }
3130cdf0e10cSrcweir         else
3131cdf0e10cSrcweir         {
3132cdf0e10cSrcweir             // --> FME 2007-11-08 #i82989# Check sort numbers in NoHintAdjustMode
3133cdf0e10cSrcweir             if ( RES_TXTATR_CHARFMT == nWhich )
3134cdf0e10cSrcweir                 lcl_CheckSortNumber( *this, *static_cast<SwTxtCharFmt*>(pHint) );
3135cdf0e10cSrcweir             // <--
3136cdf0e10cSrcweir 
3137cdf0e10cSrcweir             SwpHintsArray::Insert( pHint );
3138cdf0e10cSrcweir             NoteInHistory( pHint, true );
3139cdf0e10cSrcweir         }
3140cdf0e10cSrcweir     }
3141cdf0e10cSrcweir 
3142cdf0e10cSrcweir     // ... und die Abhaengigen benachrichtigen
314356b35d86SArmin Le Grand     if ( rNode.GetDepends() )
314456b35d86SArmin Le Grand     {
314556b35d86SArmin Le Grand         SwUpdateAttr aHint(
314656b35d86SArmin Le Grand             // rNode.GetDoc()->GetAttrPool(),
314756b35d86SArmin Le Grand             nHtStart,
314856b35d86SArmin Le Grand             nHtStart == nHintEnd ? nHintEnd + 1 : nHintEnd,
314956b35d86SArmin Le Grand             nWhich);
315056b35d86SArmin Le Grand 
315156b35d86SArmin Le Grand         rNode.ModifyNotification( 0, &aHint );
315256b35d86SArmin Le Grand     }
3153cdf0e10cSrcweir 
3154cdf0e10cSrcweir #ifdef DBG_UTIL
3155cdf0e10cSrcweir     if( !bNoHintAdjustMode && !rNode.GetDoc()->IsInReading() )
3156cdf0e10cSrcweir         CHECK;
3157cdf0e10cSrcweir #endif
3158cdf0e10cSrcweir 
3159cdf0e10cSrcweir     return true;
3160cdf0e10cSrcweir }
3161cdf0e10cSrcweir 
3162cdf0e10cSrcweir /*************************************************************************
3163cdf0e10cSrcweir  *						SwpHints::DeleteAtPos()
3164cdf0e10cSrcweir  *************************************************************************/
3165cdf0e10cSrcweir 
DeleteAtPos(const sal_uInt16 nPos)3166cdf0e10cSrcweir void SwpHints::DeleteAtPos( const sal_uInt16 nPos )
3167cdf0e10cSrcweir {
3168cdf0e10cSrcweir     SwTxtAttr *pHint = GetTextHint(nPos);
3169c0286415SOliver-Rainer Wittmann     // ChainDelete( pHint );
3170cdf0e10cSrcweir     NoteInHistory( pHint );
3171c0286415SOliver-Rainer Wittmann     SwpHintsArray::DeleteAtPos( nPos );
3172cdf0e10cSrcweir 
3173dec99bbdSOliver-Rainer Wittmann     if( pHint->Which() == RES_TXTATR_FIELD )
3174c0286415SOliver-Rainer Wittmann     {
3175c0286415SOliver-Rainer Wittmann         const SwFieldType* pFldTyp = ((SwTxtFld*)pHint)->GetFmtFld().GetField()->GetTyp();
3176c0286415SOliver-Rainer Wittmann         if( RES_DDEFLD == pFldTyp->Which() )
3177c0286415SOliver-Rainer Wittmann         {
3178c0286415SOliver-Rainer Wittmann             const SwTxtNode* pNd = ((SwTxtFld*)pHint)->GetpTxtNode();
3179c0286415SOliver-Rainer Wittmann             if( pNd && pNd->GetNodes().IsDocNodes() )
3180c0286415SOliver-Rainer Wittmann                 ((SwDDEFieldType*)pFldTyp)->DecRefCnt();
3181c0286415SOliver-Rainer Wittmann             ((SwTxtFld*)pHint)->ChgTxtNode( 0 );
3182c0286415SOliver-Rainer Wittmann         }
3183cdf0e10cSrcweir         else if ( m_bHasHiddenParaField &&
3184cdf0e10cSrcweir                  RES_HIDDENPARAFLD == pFldTyp->Which() )
3185cdf0e10cSrcweir         {
3186cdf0e10cSrcweir             m_bCalcHiddenParaField = true;
3187cdf0e10cSrcweir         }
3188cdf0e10cSrcweir     }
3189dec99bbdSOliver-Rainer Wittmann     else if ( pHint->Which() == RES_TXTATR_ANNOTATION )
3190dec99bbdSOliver-Rainer Wittmann     {
3191dec99bbdSOliver-Rainer Wittmann         const_cast<SwFmtFld&>(((SwTxtFld*)pHint)->GetFmtFld()).Broadcast( SwFmtFldHint( &((SwTxtFld*)pHint)->GetFmtFld(), SWFMTFLD_REMOVED ) );
3192dec99bbdSOliver-Rainer Wittmann     }
3193cdf0e10cSrcweir 
3194c0286415SOliver-Rainer Wittmann     CalcFlags();
3195c0286415SOliver-Rainer Wittmann     CHECK;
3196cdf0e10cSrcweir }
3197cdf0e10cSrcweir 
3198cdf0e10cSrcweir // Ist der Hint schon bekannt, dann suche die Position und loesche ihn.
3199cdf0e10cSrcweir // Ist er nicht im Array, so gibt es ein ASSERT !!
3200cdf0e10cSrcweir 
Delete(SwTxtAttr * pTxtHt)3201cdf0e10cSrcweir void SwpHints::Delete( SwTxtAttr* pTxtHt )
3202cdf0e10cSrcweir {
3203cdf0e10cSrcweir 	// Attr 2.0: SwpHintsArr::Delete( pTxtHt );
3204cdf0e10cSrcweir 	const sal_uInt16 nPos = GetStartOf( pTxtHt );
3205cdf0e10cSrcweir 	ASSERT( USHRT_MAX != nPos, "Attribut nicht im Attribut-Array!" );
3206cdf0e10cSrcweir 	if( USHRT_MAX != nPos )
3207cdf0e10cSrcweir 		DeleteAtPos( nPos );
3208cdf0e10cSrcweir }
3209cdf0e10cSrcweir 
ClearSwpHintsArr(bool bDelFields)3210cdf0e10cSrcweir void SwTxtNode::ClearSwpHintsArr( bool bDelFields )
3211cdf0e10cSrcweir {
3212cdf0e10cSrcweir     if ( HasHints() )
3213cdf0e10cSrcweir     {
3214cdf0e10cSrcweir         sal_uInt16 nPos = 0;
3215cdf0e10cSrcweir         while ( nPos < m_pSwpHints->Count() )
3216cdf0e10cSrcweir         {
3217cdf0e10cSrcweir             SwTxtAttr* pDel = m_pSwpHints->GetTextHint( nPos );
3218cdf0e10cSrcweir             bool bDel = false;
3219cdf0e10cSrcweir 
3220cdf0e10cSrcweir             switch( pDel->Which() )
3221cdf0e10cSrcweir             {
3222cdf0e10cSrcweir             case RES_TXTATR_FLYCNT:
3223cdf0e10cSrcweir             case RES_TXTATR_FTN:
3224cdf0e10cSrcweir                 break;
3225cdf0e10cSrcweir 
3226cdf0e10cSrcweir             case RES_TXTATR_FIELD:
3227dec99bbdSOliver-Rainer Wittmann             case RES_TXTATR_ANNOTATION:
322869a74367SOliver-Rainer Wittmann             case RES_TXTATR_INPUTFIELD:
3229cdf0e10cSrcweir                 if( bDelFields )
3230cdf0e10cSrcweir                     bDel = true;
3231cdf0e10cSrcweir                 break;
3232cdf0e10cSrcweir             default:
3233cdf0e10cSrcweir                 bDel = true; break;
3234cdf0e10cSrcweir             }
3235cdf0e10cSrcweir 
3236cdf0e10cSrcweir             if( bDel )
3237cdf0e10cSrcweir             {
3238cdf0e10cSrcweir                 m_pSwpHints->SwpHintsArray::DeleteAtPos( nPos );
3239cdf0e10cSrcweir 				DestroyAttr( pDel );
3240cdf0e10cSrcweir 			}
3241cdf0e10cSrcweir 			else
3242cdf0e10cSrcweir 				++nPos;
3243cdf0e10cSrcweir 		}
3244cdf0e10cSrcweir 	}
3245cdf0e10cSrcweir }
3246cdf0e10cSrcweir 
GetLang(const xub_StrLen nBegin,const xub_StrLen nLen,sal_uInt16 nScript) const3247cdf0e10cSrcweir sal_uInt16 SwTxtNode::GetLang( const xub_StrLen nBegin, const xub_StrLen nLen,
3248cdf0e10cSrcweir                            sal_uInt16 nScript ) const
3249cdf0e10cSrcweir {
3250cdf0e10cSrcweir 	sal_uInt16 nRet = LANGUAGE_DONTKNOW;
3251cdf0e10cSrcweir 
3252cdf0e10cSrcweir     if ( ! nScript )
3253cdf0e10cSrcweir     {
3254cdf0e10cSrcweir         nScript = pBreakIt->GetRealScriptOfText( m_Text, nBegin );
3255cdf0e10cSrcweir     }
3256cdf0e10cSrcweir 
3257cdf0e10cSrcweir     // --> FME 2008-09-29 #i91465# hennerdrewes: Consider nScript if pSwpHints == 0
3258cdf0e10cSrcweir     const sal_uInt16 nWhichId = GetWhichOfScript( RES_CHRATR_LANGUAGE, nScript );
3259cdf0e10cSrcweir     // <--
3260cdf0e10cSrcweir 
3261cdf0e10cSrcweir     if ( HasHints() )
3262cdf0e10cSrcweir     {
3263cdf0e10cSrcweir         const xub_StrLen nEnd = nBegin + nLen;
3264cdf0e10cSrcweir         for ( sal_uInt16 i = 0, nSize = m_pSwpHints->Count(); i < nSize; ++i )
3265cdf0e10cSrcweir         {
3266cdf0e10cSrcweir 			// ist der Attribut-Anfang schon groesser als der Idx ?
3267cdf0e10cSrcweir             const SwTxtAttr *pHt = m_pSwpHints->operator[](i);
3268cdf0e10cSrcweir             const xub_StrLen nAttrStart = *pHt->GetStart();
3269cdf0e10cSrcweir 			if( nEnd < nAttrStart )
3270cdf0e10cSrcweir 				break;
3271cdf0e10cSrcweir 
3272cdf0e10cSrcweir 			const sal_uInt16 nWhich = pHt->Which();
3273cdf0e10cSrcweir 
3274cdf0e10cSrcweir             if( nWhichId == nWhich ||
3275cdf0e10cSrcweir                     ( ( pHt->IsCharFmtAttr() || RES_TXTATR_AUTOFMT == nWhich ) && CharFmt::IsItemIncluded( nWhichId, pHt ) ) )
3276cdf0e10cSrcweir             {
327769a74367SOliver-Rainer Wittmann 				const xub_StrLen *pEndIdx = pHt->End();
3278cdf0e10cSrcweir 				// Ueberlappt das Attribut den Bereich?
3279cdf0e10cSrcweir 
3280cdf0e10cSrcweir 				if( pEndIdx &&
3281cdf0e10cSrcweir 					nLen ? ( nAttrStart < nEnd && nBegin < *pEndIdx )
3282cdf0e10cSrcweir 					 	: (( nAttrStart < nBegin &&
3283cdf0e10cSrcweir 								( pHt->DontExpand() ? nBegin < *pEndIdx
3284cdf0e10cSrcweir 													: nBegin <= *pEndIdx )) ||
3285cdf0e10cSrcweir 							( nBegin == nAttrStart &&
3286cdf0e10cSrcweir 								( nAttrStart == *pEndIdx || !nBegin ))) )
3287cdf0e10cSrcweir 				{
3288cdf0e10cSrcweir                     const SfxPoolItem* pItem = CharFmt::GetItem( *pHt, nWhichId );
3289cdf0e10cSrcweir                     sal_uInt16 nLng = ((SvxLanguageItem*)pItem)->GetLanguage();
3290cdf0e10cSrcweir 
3291cdf0e10cSrcweir 					// Umfasst das Attribut den Bereich komplett?
3292cdf0e10cSrcweir 					if( nAttrStart <= nBegin && nEnd <= *pEndIdx )
3293cdf0e10cSrcweir 						nRet = nLng;
3294cdf0e10cSrcweir 					else if( LANGUAGE_DONTKNOW == nRet )
3295cdf0e10cSrcweir 						nRet = nLng; // partielle Ueberlappung, der 1. gewinnt
3296cdf0e10cSrcweir 				}
3297cdf0e10cSrcweir 			}
3298cdf0e10cSrcweir 		}
3299cdf0e10cSrcweir 	}
3300cdf0e10cSrcweir 	if( LANGUAGE_DONTKNOW == nRet )
3301cdf0e10cSrcweir 	{
3302cdf0e10cSrcweir 		nRet = ((SvxLanguageItem&)GetSwAttrSet().Get( nWhichId )).GetLanguage();
3303cdf0e10cSrcweir 		if( LANGUAGE_DONTKNOW == nRet )
3304cdf0e10cSrcweir             nRet = static_cast<sal_uInt16>(GetAppLanguage());
3305cdf0e10cSrcweir 	}
3306cdf0e10cSrcweir 	return nRet;
3307cdf0e10cSrcweir }
3308cdf0e10cSrcweir 
3309cdf0e10cSrcweir 
GetCharOfTxtAttr(const SwTxtAttr & rAttr)3310cdf0e10cSrcweir sal_Unicode GetCharOfTxtAttr( const SwTxtAttr& rAttr )
3311cdf0e10cSrcweir {
3312cdf0e10cSrcweir     sal_Unicode cRet = CH_TXTATR_BREAKWORD;
3313cdf0e10cSrcweir     switch ( rAttr.Which() )
3314cdf0e10cSrcweir     {
3315cdf0e10cSrcweir         case RES_TXTATR_FTN:
3316cdf0e10cSrcweir         case RES_TXTATR_REFMARK:
3317cdf0e10cSrcweir         case RES_TXTATR_TOXMARK:
3318cdf0e10cSrcweir         case RES_TXTATR_META:
3319cdf0e10cSrcweir         case RES_TXTATR_METAFIELD:
3320dec99bbdSOliver-Rainer Wittmann         case RES_TXTATR_ANNOTATION:
3321cdf0e10cSrcweir             cRet = CH_TXTATR_INWORD;
3322cdf0e10cSrcweir         break;
3323cdf0e10cSrcweir 
3324cdf0e10cSrcweir         case RES_TXTATR_FIELD:
3325cdf0e10cSrcweir         case RES_TXTATR_FLYCNT:
3326cdf0e10cSrcweir         {
3327cdf0e10cSrcweir             cRet = CH_TXTATR_BREAKWORD;
3328cdf0e10cSrcweir         }
3329cdf0e10cSrcweir         break;
3330cdf0e10cSrcweir 
3331cdf0e10cSrcweir         default:
3332cdf0e10cSrcweir             ASSERT(false, "GetCharOfTxtAttr: unknown attr");
3333cdf0e10cSrcweir             break;
3334cdf0e10cSrcweir     }
3335cdf0e10cSrcweir     return cRet;
3336cdf0e10cSrcweir }
3337cdf0e10cSrcweir 
3338cdf0e10cSrcweir 
3339