xref: /aoo41x/main/sw/source/core/txtnode/thints.cxx (revision e91b5f92)
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                 {
768cdf0e10cSrcweir                     // remove all attributes from auto styles, which are explicitely 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
775cdf0e10cSrcweir                     // is also set the 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:
1052*e91b5f92SOliver-Rainer Wittmann         pNew =
1053*e91b5f92SOliver-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         {
1058*e91b5f92SOliver-Rainer Wittmann             pNew =
1059*e91b5f92SOliver-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:
1072*e91b5f92SOliver-Rainer Wittmann         pNew =
1073*e91b5f92SOliver-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,
1259cdf0e10cSrcweir         // because hints of certain types may be merged after succesful
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(
1683cdf0e10cSrcweir                 *pAttr->GetStart(), *pAttr->GetEnd(), pAttr->Which() );
1684cdf0e10cSrcweir         m_pSwpHints->Delete( pAttr );
1685cdf0e10cSrcweir         SwTxtAttr::Destroy( pAttr, GetDoc()->GetAttrPool() );
1686cdf0e10cSrcweir         NotifyClients( 0, &aHint );
1687cdf0e10cSrcweir 
1688cdf0e10cSrcweir         TryDeleteSwpHints();
1689cdf0e10cSrcweir     }
1690cdf0e10cSrcweir }
1691cdf0e10cSrcweir 
1692cdf0e10cSrcweir /*************************************************************************
1693cdf0e10cSrcweir  *                        SwTxtNode::DeleteAttributes()
1694cdf0e10cSrcweir  *************************************************************************/
1695cdf0e10cSrcweir 
1696cdf0e10cSrcweir //FIXME: this does NOT respect SORT NUMBER (for CHARFMT)!
DeleteAttributes(const sal_uInt16 nWhich,const xub_StrLen nStart,const xub_StrLen nEnd)169769a74367SOliver-Rainer Wittmann void SwTxtNode::DeleteAttributes(
169869a74367SOliver-Rainer Wittmann     const sal_uInt16 nWhich,
169969a74367SOliver-Rainer Wittmann     const xub_StrLen nStart,
170069a74367SOliver-Rainer Wittmann     const xub_StrLen nEnd )
1701cdf0e10cSrcweir {
1702cdf0e10cSrcweir     if ( !HasHints() )
1703cdf0e10cSrcweir         return;
1704cdf0e10cSrcweir 
1705cdf0e10cSrcweir     for ( sal_uInt16 nPos = 0; m_pSwpHints && nPos < m_pSwpHints->Count(); nPos++ )
1706cdf0e10cSrcweir     {
1707cdf0e10cSrcweir         SwTxtAttr * const pTxtHt = m_pSwpHints->GetTextHint( nPos );
1708cdf0e10cSrcweir         const xub_StrLen nHintStart = *(pTxtHt->GetStart());
1709cdf0e10cSrcweir         if (nStart < nHintStart)
1710cdf0e10cSrcweir         {
1711cdf0e10cSrcweir             break; // sorted by start
1712cdf0e10cSrcweir         }
1713cdf0e10cSrcweir         else if ( (nStart == nHintStart) && (nWhich == pTxtHt->Which()) )
1714cdf0e10cSrcweir         {
1715cdf0e10cSrcweir             if ( nWhich == RES_CHRATR_HIDDEN  )
1716cdf0e10cSrcweir             {
1717cdf0e10cSrcweir                 ASSERT(false, "hey, that's a CHRATR! how did that get in?");
1718cdf0e10cSrcweir                 SetCalcHiddenCharFlags();
1719cdf0e10cSrcweir             }
1720cdf0e10cSrcweir             else if ( nWhich == RES_TXTATR_CHARFMT )
1721cdf0e10cSrcweir             {
1722cdf0e10cSrcweir                 // Check if character format contains hidden attribute:
1723cdf0e10cSrcweir                 const SwCharFmt* pFmt = pTxtHt->GetCharFmt().GetCharFmt();
1724cdf0e10cSrcweir                 const SfxPoolItem* pItem;
1725cdf0e10cSrcweir                 if ( SFX_ITEM_SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
1726cdf0e10cSrcweir                     SetCalcHiddenCharFlags();
1727cdf0e10cSrcweir             }
172869a74367SOliver-Rainer Wittmann             // Recalc hidden flags if necessary
1729cdf0e10cSrcweir             else if ( nWhich == RES_TXTATR_AUTOFMT )
1730cdf0e10cSrcweir             {
1731cdf0e10cSrcweir                 // Check if auto style contains hidden attribute:
1732cdf0e10cSrcweir                 const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pTxtHt, RES_CHRATR_HIDDEN );
1733cdf0e10cSrcweir                 if ( pHiddenItem )
1734cdf0e10cSrcweir                     SetCalcHiddenCharFlags();
1735cdf0e10cSrcweir             }
1736cdf0e10cSrcweir 
1737cdf0e10cSrcweir             xub_StrLen const * const pEndIdx = pTxtHt->GetEnd();
1738cdf0e10cSrcweir 
1739cdf0e10cSrcweir             if ( pTxtHt->HasDummyChar() )
1740cdf0e10cSrcweir             {
174169a74367SOliver-Rainer Wittmann                 // Unbedingt Copy-konstruieren!
1742cdf0e10cSrcweir                 const SwIndex aIdx( this, nStart );
1743cdf0e10cSrcweir                 // erase the CH_TXTATR, which will also delete pTxtHt
1744cdf0e10cSrcweir                 EraseText( aIdx, 1 );
174569a74367SOliver-Rainer Wittmann             }
174669a74367SOliver-Rainer Wittmann             else if ( pTxtHt->HasContent() )
174769a74367SOliver-Rainer Wittmann             {
174869a74367SOliver-Rainer Wittmann                 const SwIndex aIdx( this, nStart );
174969a74367SOliver-Rainer Wittmann                 ASSERT( pTxtHt->End() != NULL, "<SwTxtNode::DeleteAttributes(..)> - missing End() at <SwTxtAttr> instance which has content" );
175069a74367SOliver-Rainer Wittmann                 EraseText( aIdx, *pTxtHt->End() - nStart );
175169a74367SOliver-Rainer Wittmann             }
175269a74367SOliver-Rainer Wittmann             else if( *pEndIdx == nEnd )
175369a74367SOliver-Rainer Wittmann             {
175469a74367SOliver-Rainer Wittmann                 // den MsgHint jetzt fuettern, weil gleich sind
175569a74367SOliver-Rainer Wittmann                 // Start und End weg.
175669a74367SOliver-Rainer Wittmann                 // Das CalcVisibleFlag bei HiddenParaFields entfaellt,
175769a74367SOliver-Rainer Wittmann                 // da dies das Feld im Dtor selbst erledigt.
1758cdf0e10cSrcweir                 SwUpdateAttr aHint( nStart, *pEndIdx, nWhich );
1759cdf0e10cSrcweir                 m_pSwpHints->DeleteAtPos( nPos );    // gefunden, loeschen,
1760cdf0e10cSrcweir                 SwTxtAttr::Destroy( pTxtHt, GetDoc()->GetAttrPool() );
176169a74367SOliver-Rainer Wittmann                 NotifyClients( 0, &aHint );
176269a74367SOliver-Rainer Wittmann             }
176369a74367SOliver-Rainer Wittmann         }
176469a74367SOliver-Rainer Wittmann     }
1765cdf0e10cSrcweir     TryDeleteSwpHints();
1766cdf0e10cSrcweir }
1767cdf0e10cSrcweir 
1768cdf0e10cSrcweir /*************************************************************************
1769cdf0e10cSrcweir  *						SwTxtNode::DelSoftHyph()
1770cdf0e10cSrcweir  *************************************************************************/
1771cdf0e10cSrcweir 
DelSoftHyph(const xub_StrLen nStt,const xub_StrLen nEnd)1772cdf0e10cSrcweir void SwTxtNode::DelSoftHyph( const xub_StrLen nStt, const xub_StrLen nEnd )
1773cdf0e10cSrcweir {
1774cdf0e10cSrcweir     xub_StrLen nFndPos = nStt, nEndPos = nEnd;
1775cdf0e10cSrcweir 	while( STRING_NOTFOUND !=
1776cdf0e10cSrcweir             ( nFndPos = m_Text.Search( CHAR_SOFTHYPHEN, nFndPos )) &&
1777cdf0e10cSrcweir 			nFndPos < nEndPos )
1778cdf0e10cSrcweir 	{
1779cdf0e10cSrcweir 		const SwIndex aIdx( this, nFndPos );
1780cdf0e10cSrcweir         EraseText( aIdx, 1 );
1781cdf0e10cSrcweir 		--nEndPos;
1782cdf0e10cSrcweir 	}
1783cdf0e10cSrcweir }
1784cdf0e10cSrcweir 
1785abbaf3ecSJian Hong Cheng //Modify here for #119405, by easyfan, 2012-05-24
1786abbaf3ecSJian Hong Cheng //In MS Word, the font underline setting of the paragraph end position wont affect the formatting of numbering, so we ignore it
lcl_IsIgnoredCharFmtForNumbering(const sal_uInt16 nWhich)1787abbaf3ecSJian Hong Cheng bool lcl_IsIgnoredCharFmtForNumbering(const sal_uInt16 nWhich)
1788abbaf3ecSJian Hong Cheng {
1789abbaf3ecSJian Hong Cheng 	return (nWhich ==  RES_CHRATR_UNDERLINE);
1790abbaf3ecSJian Hong Cheng }
1791abbaf3ecSJian Hong Cheng 
1792abbaf3ecSJian Hong Cheng //In MS Word, following properties of the paragraph end position wont affect the formatting of bullets, so we ignore them:
1793abbaf3ecSJian Hong Cheng //Font underline;
1794abbaf3ecSJian Hong Cheng //Font Italic of Western, CJK and CTL;
1795abbaf3ecSJian Hong Cheng //Font Bold of Wertern, CJK and CTL;
lcl_IsIgnoredCharFmtForBullets(const sal_uInt16 nWhich)1796abbaf3ecSJian Hong Cheng bool lcl_IsIgnoredCharFmtForBullets(const sal_uInt16 nWhich)
1797abbaf3ecSJian Hong Cheng {
1798abbaf3ecSJian Hong Cheng 	return (nWhich ==  RES_CHRATR_UNDERLINE || nWhich ==  RES_CHRATR_POSTURE || nWhich ==  RES_CHRATR_WEIGHT
1799abbaf3ecSJian Hong Cheng 		|| nWhich == RES_CHRATR_CJK_POSTURE || nWhich == RES_CHRATR_CJK_WEIGHT
1800abbaf3ecSJian Hong Cheng 		|| nWhich == RES_CHRATR_CTL_POSTURE || nWhich == RES_CHRATR_CTL_WEIGHT);
1801abbaf3ecSJian Hong Cheng }
1802abbaf3ecSJian Hong Cheng 
1803abbaf3ecSJian Hong Cheng //Condition for expanding char set to character style of specified number rule level:
1804abbaf3ecSJian Hong Cheng //The item inside the set should not conflict to any exist and non-default item inside paragraph properties set (SwCntntNode::SwPAttrSet);
1805abbaf3ecSJian Hong Cheng //The node should have applied a number rule;
1806abbaf3ecSJian Hong Cheng //The node should be counted in a list, if not, make it to be;
1807abbaf3ecSJian Hong Cheng //The item should not conflict to any exist and non-default item inside the character of specified number rule level;
1808abbaf3ecSJian Hong Cheng //The item should not be ignored depend on the exact number rule type;
TryCharSetExpandToNum(const SfxItemSet & aCharSet)1809abbaf3ecSJian Hong Cheng bool SwTxtNode::TryCharSetExpandToNum(const SfxItemSet& aCharSet)
1810abbaf3ecSJian Hong Cheng {
1811abbaf3ecSJian Hong Cheng 	bool bRet = false;
1812abbaf3ecSJian Hong Cheng 	SfxItemIter aIter( aCharSet );
1813abbaf3ecSJian Hong Cheng         const SfxPoolItem* pItem = aIter.FirstItem();
1814abbaf3ecSJian Hong Cheng         const sal_uInt16 nWhich = pItem->Which();
1815abbaf3ecSJian Hong Cheng 
1816abbaf3ecSJian Hong Cheng 	const SfxPoolItem& rInnerItem = GetAttr(nWhich,false);
1817abbaf3ecSJian Hong Cheng 
1818abbaf3ecSJian Hong Cheng 	if (!IsDefaultItem(&rInnerItem) &&  !IsInvalidItem(&rInnerItem))
1819abbaf3ecSJian Hong Cheng 		return bRet;
1820abbaf3ecSJian Hong Cheng 
1821abbaf3ecSJian Hong Cheng 	if ( !IsInList() && GetNumRule() && GetListId().Len() > 0 )
1822abbaf3ecSJian Hong Cheng 	{
1823abbaf3ecSJian Hong Cheng 		return bRet;
1824abbaf3ecSJian Hong Cheng 	}
1825abbaf3ecSJian Hong Cheng 
1826abbaf3ecSJian Hong Cheng 	SwNumRule* pCurrNum = GetNumRule(false);
1827abbaf3ecSJian Hong Cheng 
1828abbaf3ecSJian Hong Cheng 	int nLevel = GetActualListLevel();
1829abbaf3ecSJian Hong Cheng 
1830abbaf3ecSJian Hong Cheng 	if (nLevel != -1 && pCurrNum)
1831abbaf3ecSJian Hong Cheng 	{
1832abbaf3ecSJian Hong Cheng 		const SwNumFmt* pCurrNumFmt = pCurrNum->GetNumFmt(static_cast<sal_uInt16>(nLevel));
1833abbaf3ecSJian Hong Cheng 		if (pCurrNumFmt)
1834abbaf3ecSJian Hong Cheng 		{
1835abbaf3ecSJian Hong Cheng 			if (pCurrNumFmt->IsItemize() && lcl_IsIgnoredCharFmtForBullets(nWhich))
1836abbaf3ecSJian Hong Cheng 				return bRet;
1837abbaf3ecSJian Hong Cheng 			if (pCurrNumFmt->IsEnumeration() && lcl_IsIgnoredCharFmtForNumbering(nWhich))
1838abbaf3ecSJian Hong Cheng 				return bRet;
1839abbaf3ecSJian Hong Cheng 			SwCharFmt* pCurrCharFmt =pCurrNumFmt->GetCharFmt();
1840abbaf3ecSJian Hong Cheng 
1841abbaf3ecSJian Hong Cheng 			if (pCurrCharFmt && pCurrCharFmt->GetItemState(nWhich,false) != SFX_ITEM_SET)
1842abbaf3ecSJian Hong Cheng 			{
1843abbaf3ecSJian Hong Cheng 				pCurrCharFmt->SetFmtAttr(*pItem);
1844abbaf3ecSJian Hong Cheng 				SwNumFmt aNewNumFmt(*pCurrNumFmt);
1845abbaf3ecSJian Hong Cheng 				aNewNumFmt.SetCharFmt(pCurrCharFmt);
1846abbaf3ecSJian Hong Cheng 				pCurrNum->Set(nLevel,aNewNumFmt);
1847abbaf3ecSJian Hong Cheng 				bRet = true;
1848abbaf3ecSJian Hong Cheng 			}
1849abbaf3ecSJian Hong Cheng 		}
1850abbaf3ecSJian Hong Cheng 	}
1851abbaf3ecSJian Hong Cheng 
1852abbaf3ecSJian Hong Cheng 
1853abbaf3ecSJian Hong Cheng 	return bRet;
1854abbaf3ecSJian Hong Cheng }
1855abbaf3ecSJian Hong Cheng //End of modification, by easyfan
1856abbaf3ecSJian Hong Cheng 
1857cdf0e10cSrcweir // setze diese Attribute am TextNode. Wird der gesamte Bereich umspannt,
1858cdf0e10cSrcweir // dann setze sie nur im AutoAttrSet (SwCntntNode:: SetAttr)
SetAttr(const SfxItemSet & rSet,const xub_StrLen nStt,const xub_StrLen nEnd,const SetAttrMode nMode)185969a74367SOliver-Rainer Wittmann sal_Bool SwTxtNode::SetAttr(
186069a74367SOliver-Rainer Wittmann     const SfxItemSet& rSet,
186169a74367SOliver-Rainer Wittmann     const xub_StrLen nStt,
186269a74367SOliver-Rainer Wittmann     const xub_StrLen nEnd,
186369a74367SOliver-Rainer Wittmann     const SetAttrMode nMode )
1864cdf0e10cSrcweir {
1865cdf0e10cSrcweir 	if( !rSet.Count() )
1866cdf0e10cSrcweir 		return sal_False;
1867cdf0e10cSrcweir 
1868cdf0e10cSrcweir 	// teil die Sets auf (fuer Selektion in Nodes)
1869cdf0e10cSrcweir 	const SfxItemSet* pSet = &rSet;
1870cdf0e10cSrcweir 	SfxItemSet aTxtSet( *rSet.GetPool(), RES_TXTATR_BEGIN, RES_TXTATR_END-1 );
1871cdf0e10cSrcweir 
1872cdf0e10cSrcweir 	// gesamter Bereich
1873cdf0e10cSrcweir     if ( !nStt && (nEnd == m_Text.Len()) &&
1874cdf0e10cSrcweir          !(nMode & nsSetAttrMode::SETATTR_NOFORMATATTR ) )
1875cdf0e10cSrcweir 	{
1876cdf0e10cSrcweir 		// sind am Node schon Zeichenvorlagen gesetzt, muss man diese Attribute
1877cdf0e10cSrcweir 		// (rSet) immer als TextAttribute setzen, damit sie angezeigt werden.
1878cdf0e10cSrcweir 		int bHasCharFmts = sal_False;
1879cdf0e10cSrcweir         if ( HasHints() )
1880cdf0e10cSrcweir         {
1881cdf0e10cSrcweir             for ( sal_uInt16 n = 0; n < m_pSwpHints->Count(); ++n )
1882cdf0e10cSrcweir             {
1883cdf0e10cSrcweir                 if ( (*m_pSwpHints)[ n ]->IsCharFmtAttr() )
1884cdf0e10cSrcweir                 {
1885cdf0e10cSrcweir 					bHasCharFmts = sal_True;
1886cdf0e10cSrcweir 					break;
1887cdf0e10cSrcweir                 }
1888cdf0e10cSrcweir             }
1889cdf0e10cSrcweir         }
1890cdf0e10cSrcweir 
1891cdf0e10cSrcweir 		if( !bHasCharFmts )
1892cdf0e10cSrcweir 		{
1893cdf0e10cSrcweir             aTxtSet.Put( rSet );
1894cdf0e10cSrcweir             // If there are any character attributes in rSet,
1895cdf0e10cSrcweir             // we want to set them at the paragraph:
1896cdf0e10cSrcweir 			if( aTxtSet.Count() != rSet.Count() )
1897cdf0e10cSrcweir 			{
1898cdf0e10cSrcweir                 sal_Bool bRet = SetAttr( rSet );
1899cdf0e10cSrcweir           		if( !aTxtSet.Count() )
1900cdf0e10cSrcweir 		    		return bRet;
1901cdf0e10cSrcweir 			}
1902cdf0e10cSrcweir 
1903cdf0e10cSrcweir             // check for auto style:
1904cdf0e10cSrcweir             const SfxPoolItem* pItem;
1905cdf0e10cSrcweir             const bool bAutoStyle = SFX_ITEM_SET == aTxtSet.GetItemState( RES_TXTATR_AUTOFMT, sal_False, &pItem );
1906cdf0e10cSrcweir             if ( bAutoStyle )
1907cdf0e10cSrcweir             {
1908cdf0e10cSrcweir                 boost::shared_ptr<SfxItemSet> pAutoStyleSet = static_cast<const SwFmtAutoFmt*>(pItem)->GetStyleHandle();
1909cdf0e10cSrcweir                 sal_Bool bRet = SetAttr( *pAutoStyleSet );
1910cdf0e10cSrcweir           		if( 1 == aTxtSet.Count() )
1911cdf0e10cSrcweir 		    		return bRet;
1912cdf0e10cSrcweir             }
1913cdf0e10cSrcweir 
1914cdf0e10cSrcweir             // Continue with the text attributes:
1915cdf0e10cSrcweir 			pSet = &aTxtSet;
1916cdf0e10cSrcweir 		}
1917cdf0e10cSrcweir 	}
1918cdf0e10cSrcweir 
1919cdf0e10cSrcweir     GetOrCreateSwpHints();
1920cdf0e10cSrcweir 
1921cdf0e10cSrcweir     SfxItemSet aCharSet( *rSet.GetPool(), aCharAutoFmtSetRange );
1922cdf0e10cSrcweir 
1923cdf0e10cSrcweir     sal_uInt16 nCount = 0;
1924cdf0e10cSrcweir 	SfxItemIter aIter( *pSet );
1925cdf0e10cSrcweir 	const SfxPoolItem* pItem = aIter.GetCurItem();
1926cdf0e10cSrcweir 
1927cdf0e10cSrcweir     do
1928cdf0e10cSrcweir     {
1929cdf0e10cSrcweir         if ( pItem && (reinterpret_cast<SfxPoolItem*>(-1) != pItem))
1930cdf0e10cSrcweir         {
1931cdf0e10cSrcweir             const sal_uInt16 nWhich = pItem->Which();
1932cdf0e10cSrcweir             ASSERT( isCHRATR(nWhich) || isTXTATR(nWhich),
1933cdf0e10cSrcweir                     "SwTxtNode::SetAttr(): unknown attribute" );
1934cdf0e10cSrcweir             if ( isCHRATR(nWhich) || isTXTATR(nWhich) )
1935cdf0e10cSrcweir             {
1936cdf0e10cSrcweir                 if ((RES_TXTATR_CHARFMT == nWhich) &&
1937cdf0e10cSrcweir                     (GetDoc()->GetDfltCharFmt() ==
1938cdf0e10cSrcweir                      static_cast<const SwFmtCharFmt*>(pItem)->GetCharFmt()))
1939cdf0e10cSrcweir                 {
1940cdf0e10cSrcweir                     SwIndex aIndex( this, nStt );
194169a74367SOliver-Rainer Wittmann                     RstTxtAttr( aIndex, nEnd - nStt, RES_TXTATR_CHARFMT, 0 );
1942cdf0e10cSrcweir                     DontExpandFmt( aIndex );
1943cdf0e10cSrcweir                 }
1944cdf0e10cSrcweir                 else
1945cdf0e10cSrcweir                 {
1946cdf0e10cSrcweir                     if (isCHRATR(nWhich) ||
1947cdf0e10cSrcweir                         (RES_TXTATR_UNKNOWN_CONTAINER == nWhich))
1948cdf0e10cSrcweir                     {
1949cdf0e10cSrcweir                         aCharSet.Put( *pItem );
1950cdf0e10cSrcweir                     }
1951cdf0e10cSrcweir                     else
1952cdf0e10cSrcweir                     {
1953cdf0e10cSrcweir 
1954cdf0e10cSrcweir                         SwTxtAttr *const pNew = MakeTxtAttr( *GetDoc(),
1955cdf0e10cSrcweir                                 const_cast<SfxPoolItem&>(*pItem), nStt, nEnd );
1956cdf0e10cSrcweir                         if ( pNew )
1957cdf0e10cSrcweir                         {
1958cdf0e10cSrcweir                             if ( nEnd != nStt && !pNew->GetEnd() )
1959cdf0e10cSrcweir                             {
1960cdf0e10cSrcweir                                 ASSERT(false,
1961cdf0e10cSrcweir                                     "Attribut without end, but area marked");
1962cdf0e10cSrcweir                                 DestroyAttr( pNew ); // do not insert
1963cdf0e10cSrcweir                             }
1964cdf0e10cSrcweir                             else if ( InsertHint( pNew, nMode ) )
1965cdf0e10cSrcweir                             {
1966cdf0e10cSrcweir                                 ++nCount;
1967cdf0e10cSrcweir                             }
1968cdf0e10cSrcweir                         }
1969cdf0e10cSrcweir                     }
1970cdf0e10cSrcweir                 }
1971cdf0e10cSrcweir             }
1972cdf0e10cSrcweir         }
1973cdf0e10cSrcweir         if ( aIter.IsAtEnd() )
1974cdf0e10cSrcweir             break;
1975cdf0e10cSrcweir         pItem = aIter.NextItem();
1976cdf0e10cSrcweir     } while( true );
1977cdf0e10cSrcweir 
1978cdf0e10cSrcweir     if ( aCharSet.Count() )
1979cdf0e10cSrcweir     {
1980cdf0e10cSrcweir         SwTxtAttr* pTmpNew = MakeTxtAttr( *GetDoc(), aCharSet, nStt, nEnd );
1981cdf0e10cSrcweir         if ( InsertHint( pTmpNew, nMode ) )
1982cdf0e10cSrcweir         {
1983cdf0e10cSrcweir             ++nCount;
1984cdf0e10cSrcweir         }
1985cdf0e10cSrcweir     }
1986cdf0e10cSrcweir 
1987cdf0e10cSrcweir     TryDeleteSwpHints();
1988cdf0e10cSrcweir 
1989cdf0e10cSrcweir 	return nCount ? sal_True : sal_False;
1990cdf0e10cSrcweir }
1991cdf0e10cSrcweir 
lcl_MergeAttr(SfxItemSet & rSet,const SfxPoolItem & rAttr)1992cdf0e10cSrcweir void lcl_MergeAttr( SfxItemSet& rSet, const SfxPoolItem& rAttr )
1993cdf0e10cSrcweir {
1994cdf0e10cSrcweir     if ( RES_TXTATR_AUTOFMT == rAttr.Which() )
1995cdf0e10cSrcweir 	{
1996cdf0e10cSrcweir         const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
1997cdf0e10cSrcweir         if ( !pCFSet )
1998cdf0e10cSrcweir             return;
1999cdf0e10cSrcweir         SfxWhichIter aIter( *pCFSet );
2000cdf0e10cSrcweir         sal_uInt16 nWhich = aIter.FirstWhich();
2001cdf0e10cSrcweir         while( nWhich )
2002cdf0e10cSrcweir         {
2003cdf0e10cSrcweir             if( ( nWhich < RES_CHRATR_END ||
2004cdf0e10cSrcweir                   RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) &&
2005cdf0e10cSrcweir                 ( SFX_ITEM_SET == pCFSet->GetItemState( nWhich, sal_True ) ) )
2006cdf0e10cSrcweir                 rSet.Put( pCFSet->Get( nWhich ) );
2007cdf0e10cSrcweir             nWhich = aIter.NextWhich();
2008cdf0e10cSrcweir         }
2009cdf0e10cSrcweir     }
2010cdf0e10cSrcweir     else
2011cdf0e10cSrcweir     	rSet.Put( rAttr );
2012cdf0e10cSrcweir }
2013cdf0e10cSrcweir 
lcl_MergeAttr_ExpandChrFmt(SfxItemSet & rSet,const SfxPoolItem & rAttr)2014cdf0e10cSrcweir void lcl_MergeAttr_ExpandChrFmt( SfxItemSet& rSet, const SfxPoolItem& rAttr )
2015cdf0e10cSrcweir {
2016cdf0e10cSrcweir 	if( RES_TXTATR_CHARFMT == rAttr.Which() ||
2017cdf0e10cSrcweir 		RES_TXTATR_INETFMT == rAttr.Which() ||
2018cdf0e10cSrcweir         RES_TXTATR_AUTOFMT == rAttr.Which() )
2019cdf0e10cSrcweir 	{
2020cdf0e10cSrcweir         const SfxItemSet* pCFSet = CharFmt::GetItemSet( rAttr );
2021cdf0e10cSrcweir 
2022cdf0e10cSrcweir         if ( pCFSet )
2023cdf0e10cSrcweir         {
2024cdf0e10cSrcweir             SfxWhichIter aIter( *pCFSet );
2025cdf0e10cSrcweir             sal_uInt16 nWhich = aIter.FirstWhich();
2026cdf0e10cSrcweir             while( nWhich )
2027cdf0e10cSrcweir             {
2028cdf0e10cSrcweir                 if( ( nWhich < RES_CHRATR_END ||
2029cdf0e10cSrcweir                       ( RES_TXTATR_AUTOFMT == rAttr.Which() && RES_TXTATR_UNKNOWN_CONTAINER == nWhich ) ) &&
2030cdf0e10cSrcweir                     ( SFX_ITEM_SET == pCFSet->GetItemState( nWhich, sal_True ) ) )
2031cdf0e10cSrcweir                     rSet.Put( pCFSet->Get( nWhich ) );
2032cdf0e10cSrcweir                 nWhich = aIter.NextWhich();
2033cdf0e10cSrcweir             }
2034cdf0e10cSrcweir         }
2035cdf0e10cSrcweir     }
2036cdf0e10cSrcweir 
2037cdf0e10cSrcweir 	// aufnehmen als MergeWert (falls noch nicht gesetzt neu setzen!)
2038cdf0e10cSrcweir 
2039cdf0e10cSrcweir /* wenn mehrere Attribute ueberlappen gewinnt der letze !!
2040cdf0e10cSrcweir  z.B
2041cdf0e10cSrcweir 			1234567890123456789
2042cdf0e10cSrcweir 			  |------------| 		Font1
2043cdf0e10cSrcweir 				 |------|			Font2
2044cdf0e10cSrcweir 					^  ^
2045cdf0e10cSrcweir 					|--|		Abfragebereich: -> Gueltig ist Font2
2046cdf0e10cSrcweir */
2047cdf0e10cSrcweir     rSet.Put( rAttr );
2048cdf0e10cSrcweir }
2049cdf0e10cSrcweir 
2050cdf0e10cSrcweir struct SwPoolItemEndPair
2051cdf0e10cSrcweir {
2052cdf0e10cSrcweir public:
2053cdf0e10cSrcweir     const SfxPoolItem* mpItem;
2054cdf0e10cSrcweir     xub_StrLen mnEndPos;
2055cdf0e10cSrcweir 
SwPoolItemEndPairSwPoolItemEndPair2056cdf0e10cSrcweir     SwPoolItemEndPair() : mpItem( 0 ), mnEndPos( 0 ) {};
2057cdf0e10cSrcweir };
2058cdf0e10cSrcweir 
2059cdf0e10cSrcweir // --> OD 2008-01-16 #newlistlevelattrs#
lcl_MergeListLevelIndentAsLRSpaceItem(const SwTxtNode & rTxtNode,SfxItemSet & rSet)2060cdf0e10cSrcweir void lcl_MergeListLevelIndentAsLRSpaceItem( const SwTxtNode& rTxtNode,
2061cdf0e10cSrcweir                                             SfxItemSet& rSet )
2062cdf0e10cSrcweir {
2063cdf0e10cSrcweir     if ( rTxtNode.AreListLevelIndentsApplicable() )
2064cdf0e10cSrcweir     {
2065cdf0e10cSrcweir         const SwNumRule* pRule = rTxtNode.GetNumRule();
2066cdf0e10cSrcweir         if ( pRule && rTxtNode.GetActualListLevel() >= 0 )
2067cdf0e10cSrcweir         {
2068cdf0e10cSrcweir             const SwNumFmt& rFmt = pRule->Get(static_cast<sal_uInt16>(rTxtNode.GetActualListLevel()));
2069cdf0e10cSrcweir             if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2070cdf0e10cSrcweir             {
2071cdf0e10cSrcweir                 SvxLRSpaceItem aLR( RES_LR_SPACE );
2072cdf0e10cSrcweir                 aLR.SetTxtLeft( rFmt.GetIndentAt() );
2073cdf0e10cSrcweir                 aLR.SetTxtFirstLineOfst( static_cast<short>(rFmt.GetFirstLineIndent()) );
2074cdf0e10cSrcweir                 rSet.Put( aLR );
2075cdf0e10cSrcweir             }
2076cdf0e10cSrcweir         }
2077cdf0e10cSrcweir     }
2078cdf0e10cSrcweir }
2079cdf0e10cSrcweir 
2080cdf0e10cSrcweir // erfrage die Attribute vom TextNode ueber den Bereich
2081cdf0e10cSrcweir // --> OD 2008-01-16 #newlistlevelattrs#
GetAttr(SfxItemSet & rSet,xub_StrLen nStt,xub_StrLen nEnd,sal_Bool bOnlyTxtAttr,sal_Bool bGetFromChrFmt,const bool bMergeIndentValuesOfNumRule) const2082cdf0e10cSrcweir sal_Bool SwTxtNode::GetAttr( SfxItemSet& rSet, xub_StrLen nStt, xub_StrLen nEnd,
2083cdf0e10cSrcweir                          sal_Bool bOnlyTxtAttr, sal_Bool bGetFromChrFmt,
2084cdf0e10cSrcweir                          const bool bMergeIndentValuesOfNumRule ) const
2085cdf0e10cSrcweir {
2086cdf0e10cSrcweir     if( HasHints() )
2087cdf0e10cSrcweir     {
2088cdf0e10cSrcweir 		/* stelle erstmal fest, welche Text-Attribut in dem Bereich gueltig
2089cdf0e10cSrcweir 		 * sind. Dabei gibt es folgende Faelle:
2090cdf0e10cSrcweir 		 * 	UnEindeutig wenn: (wenn != Format-Attribut)
2091cdf0e10cSrcweir 		 * 		- das Attribut liegt vollstaendig im Bereich
2092cdf0e10cSrcweir 		 * 		- das Attributende liegt im Bereich
2093cdf0e10cSrcweir 		 * 		- der Attributanfang liegt im Bereich:
2094cdf0e10cSrcweir 		 * Eindeutig (im Set mergen):
2095cdf0e10cSrcweir 		 *		- das Attrib umfasst den Bereich
2096cdf0e10cSrcweir 		 * nichts tun:
2097cdf0e10cSrcweir 		 * 		das Attribut liegt ausserhalb des Bereiches
2098cdf0e10cSrcweir 		 */
2099cdf0e10cSrcweir 
2100cdf0e10cSrcweir 		void (*fnMergeAttr)( SfxItemSet&, const SfxPoolItem& )
2101cdf0e10cSrcweir 			= bGetFromChrFmt ? &lcl_MergeAttr_ExpandChrFmt
2102cdf0e10cSrcweir 							 : &lcl_MergeAttr;
2103cdf0e10cSrcweir 
2104cdf0e10cSrcweir 		// dann besorge mal die Auto-(Fmt)Attribute
2105cdf0e10cSrcweir 		SfxItemSet aFmtSet( *rSet.GetPool(), rSet.GetRanges() );
2106cdf0e10cSrcweir 		if( !bOnlyTxtAttr )
2107cdf0e10cSrcweir         {
2108cdf0e10cSrcweir 			SwCntntNode::GetAttr( aFmtSet );
2109cdf0e10cSrcweir             // --> OD 2008-01-16 #newlistlevelattrs#
2110cdf0e10cSrcweir             if ( bMergeIndentValuesOfNumRule )
2111cdf0e10cSrcweir             {
2112cdf0e10cSrcweir                 lcl_MergeListLevelIndentAsLRSpaceItem( *this, aFmtSet );
2113cdf0e10cSrcweir             }
2114cdf0e10cSrcweir             // <--
2115cdf0e10cSrcweir         }
2116cdf0e10cSrcweir 
2117cdf0e10cSrcweir         const sal_uInt16 nSize = m_pSwpHints->Count();
2118cdf0e10cSrcweir 
2119cdf0e10cSrcweir         if( nStt == nEnd )             // kein Bereich:
2120cdf0e10cSrcweir 		{
2121cdf0e10cSrcweir             for (sal_uInt16 n = 0; n < nSize; ++n)
2122cdf0e10cSrcweir             {
2123cdf0e10cSrcweir                 const SwTxtAttr* pHt = (*m_pSwpHints)[n];
2124cdf0e10cSrcweir                 const xub_StrLen nAttrStart = *pHt->GetStart();
2125cdf0e10cSrcweir 				if( nAttrStart > nEnd ) 		// ueber den Bereich hinaus
2126cdf0e10cSrcweir 					break;
2127cdf0e10cSrcweir 
212869a74367SOliver-Rainer Wittmann                 const xub_StrLen* pAttrEnd = pHt->End();
2129cdf0e10cSrcweir                 if ( ! pAttrEnd ) // no attributes without end
2130cdf0e10cSrcweir 					continue;
2131cdf0e10cSrcweir 
2132cdf0e10cSrcweir                 if( ( nAttrStart < nStt &&
2133cdf0e10cSrcweir                         ( pHt->DontExpand() ? nStt < *pAttrEnd
2134cdf0e10cSrcweir                                             : nStt <= *pAttrEnd )) ||
2135cdf0e10cSrcweir                     ( nStt == nAttrStart &&
2136cdf0e10cSrcweir                         ( nAttrStart == *pAttrEnd || !nStt )))
2137cdf0e10cSrcweir 					(*fnMergeAttr)( rSet, pHt->GetAttr() );
2138cdf0e10cSrcweir 			}
2139cdf0e10cSrcweir 		}
2140cdf0e10cSrcweir 		else							// es ist ein Bereich definiert
2141cdf0e10cSrcweir 		{
2142cdf0e10cSrcweir             // --> FME 2007-03-13 #i75299#
2143cdf0e10cSrcweir             ::std::auto_ptr< std::vector< SwPoolItemEndPair > > pAttrArr;
2144cdf0e10cSrcweir             // <--
2145cdf0e10cSrcweir 
2146cdf0e10cSrcweir 			const sal_uInt16 coArrSz = static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
2147cdf0e10cSrcweir                                    static_cast<sal_uInt16>(RES_CHRATR_BEGIN);
2148cdf0e10cSrcweir 
2149cdf0e10cSrcweir             for (sal_uInt16 n = 0; n < nSize; ++n)
2150cdf0e10cSrcweir             {
2151cdf0e10cSrcweir                 const SwTxtAttr* pHt = (*m_pSwpHints)[n];
2152cdf0e10cSrcweir                 const xub_StrLen nAttrStart = *pHt->GetStart();
2153cdf0e10cSrcweir 				if( nAttrStart > nEnd ) 		// ueber den Bereich hinaus
2154cdf0e10cSrcweir 					break;
2155cdf0e10cSrcweir 
215669a74367SOliver-Rainer Wittmann                 const xub_StrLen* pAttrEnd = pHt->End();
2157cdf0e10cSrcweir                 if ( ! pAttrEnd ) // no attributes without end
2158cdf0e10cSrcweir 					continue;
2159cdf0e10cSrcweir 
2160cdf0e10cSrcweir 				sal_Bool bChkInvalid = sal_False;
2161cdf0e10cSrcweir                 if( nAttrStart <= nStt )       // vor oder genau Start
2162cdf0e10cSrcweir 				{
2163cdf0e10cSrcweir                     if( *pAttrEnd <= nStt )    // liegt davor
2164cdf0e10cSrcweir 						continue;
2165cdf0e10cSrcweir 
2166cdf0e10cSrcweir 					if( nEnd <= *pAttrEnd )		// hinter oder genau Ende
2167cdf0e10cSrcweir 						(*fnMergeAttr)( aFmtSet, pHt->GetAttr() );
2168cdf0e10cSrcweir 					else
2169cdf0e10cSrcweir //					else if( pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
2170cdf0e10cSrcweir 						// uneindeutig
2171cdf0e10cSrcweir 						bChkInvalid = sal_True;
2172cdf0e10cSrcweir 				}
2173cdf0e10cSrcweir 				else if( nAttrStart < nEnd 		// reicht in den Bereich
2174cdf0e10cSrcweir )//						 && pHt->GetAttr() != aFmtSet.Get( pHt->Which() ) )
2175cdf0e10cSrcweir 					bChkInvalid = sal_True;
2176cdf0e10cSrcweir 
2177cdf0e10cSrcweir 				if( bChkInvalid )
2178cdf0e10cSrcweir 				{
2179cdf0e10cSrcweir 					// uneindeutig ?
2180cdf0e10cSrcweir                     ::std::auto_ptr< SfxItemIter > pItemIter;
2181cdf0e10cSrcweir                     const SfxPoolItem* pItem = 0;
2182cdf0e10cSrcweir 
2183cdf0e10cSrcweir                     if ( RES_TXTATR_AUTOFMT == pHt->Which() )
2184cdf0e10cSrcweir                     {
2185cdf0e10cSrcweir                         const SfxItemSet* pAutoSet = CharFmt::GetItemSet( pHt->GetAttr() );
2186cdf0e10cSrcweir                         if ( pAutoSet )
2187cdf0e10cSrcweir                         {
2188cdf0e10cSrcweir                             pItemIter.reset( new SfxItemIter( *pAutoSet ) );
2189cdf0e10cSrcweir                             pItem = pItemIter->GetCurItem();
2190cdf0e10cSrcweir                         }
2191cdf0e10cSrcweir                     }
2192cdf0e10cSrcweir                     else
2193cdf0e10cSrcweir                         pItem = &pHt->GetAttr();
2194cdf0e10cSrcweir 
2195cdf0e10cSrcweir                     const sal_uInt16 nHintEnd = *pAttrEnd;
2196cdf0e10cSrcweir 
2197cdf0e10cSrcweir                     while ( pItem )
2198cdf0e10cSrcweir                     {
2199cdf0e10cSrcweir                         const sal_uInt16 nHintWhich = pItem->Which();
2200cdf0e10cSrcweir                         ASSERT(!isUNKNOWNATR(nHintWhich),
2201cdf0e10cSrcweir                                 "SwTxtNode::GetAttr(): unkonwn attribute?");
2202cdf0e10cSrcweir 
2203cdf0e10cSrcweir                         if ( !pAttrArr.get() )
2204cdf0e10cSrcweir                         {
2205cdf0e10cSrcweir                             pAttrArr.reset(
2206cdf0e10cSrcweir                                 new std::vector< SwPoolItemEndPair >(coArrSz));
2207cdf0e10cSrcweir                         }
2208cdf0e10cSrcweir 
2209cdf0e10cSrcweir                         std::vector< SwPoolItemEndPair >::iterator pPrev = pAttrArr->begin();
2210cdf0e10cSrcweir                         if (isCHRATR(nHintWhich) ||
2211cdf0e10cSrcweir                             isTXTATR_WITHEND(nHintWhich))
2212cdf0e10cSrcweir                         {
2213cdf0e10cSrcweir                             pPrev += nHintWhich - RES_CHRATR_BEGIN;
2214cdf0e10cSrcweir                         }
2215cdf0e10cSrcweir                         else
2216cdf0e10cSrcweir                         {
2217cdf0e10cSrcweir                             pPrev = pAttrArr->end();
2218cdf0e10cSrcweir                         }
2219cdf0e10cSrcweir 
2220cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
2221cdf0e10cSrcweir                         SwPoolItemEndPair aTmp = *pPrev;
2222cdf0e10cSrcweir #endif
2223cdf0e10cSrcweir 
2224cdf0e10cSrcweir                         if( pPrev != pAttrArr->end() )
2225cdf0e10cSrcweir                         {
2226cdf0e10cSrcweir                             if( !pPrev->mpItem )
2227cdf0e10cSrcweir                             {
2228cdf0e10cSrcweir                                 if ( bOnlyTxtAttr || *pItem != aFmtSet.Get( nHintWhich ) )
2229cdf0e10cSrcweir                                 {
2230cdf0e10cSrcweir                                     if( nAttrStart > nStt )
2231cdf0e10cSrcweir                                     {
2232cdf0e10cSrcweir                                         rSet.InvalidateItem( nHintWhich );
2233cdf0e10cSrcweir                                         pPrev->mpItem = (SfxPoolItem*)-1;
2234cdf0e10cSrcweir                                     }
2235cdf0e10cSrcweir                                     else
2236cdf0e10cSrcweir                                     {
2237cdf0e10cSrcweir                                         pPrev->mpItem = pItem;
2238cdf0e10cSrcweir                                         pPrev->mnEndPos = nHintEnd;
2239cdf0e10cSrcweir                                     }
2240cdf0e10cSrcweir                                 }
2241cdf0e10cSrcweir                             }
2242cdf0e10cSrcweir                             else if( (SfxPoolItem*)-1 != pPrev->mpItem )
2243cdf0e10cSrcweir                             {
2244cdf0e10cSrcweir                                 if( pPrev->mnEndPos == nAttrStart &&
2245cdf0e10cSrcweir                                     *pPrev->mpItem == *pItem )
2246cdf0e10cSrcweir                                 {
2247cdf0e10cSrcweir                                     pPrev->mpItem = pItem;
2248cdf0e10cSrcweir                                     pPrev->mnEndPos = nHintEnd;
2249cdf0e10cSrcweir                                 }
2250cdf0e10cSrcweir                                 else
2251cdf0e10cSrcweir                                 {
2252cdf0e10cSrcweir                                     rSet.InvalidateItem( nHintWhich );
2253cdf0e10cSrcweir                                     pPrev->mpItem = (SfxPoolItem*)-1;
2254cdf0e10cSrcweir                                 }
2255cdf0e10cSrcweir                             }
2256cdf0e10cSrcweir                         }
2257cdf0e10cSrcweir 
2258cdf0e10cSrcweir                         pItem = ( pItemIter.get() && !pItemIter->IsAtEnd() )
2259cdf0e10cSrcweir                                     ? pItemIter->NextItem() : 0;
2260cdf0e10cSrcweir                     } // end while
2261cdf0e10cSrcweir                 }
2262cdf0e10cSrcweir 			}
2263cdf0e10cSrcweir 
2264cdf0e10cSrcweir             if ( pAttrArr.get() )
2265cdf0e10cSrcweir 			{
2266cdf0e10cSrcweir                 for (sal_uInt16 n = 0; n < coArrSz; ++n)
2267cdf0e10cSrcweir                 {
2268cdf0e10cSrcweir                     const SwPoolItemEndPair& rItemPair = (*pAttrArr)[ n ];
2269cdf0e10cSrcweir                     if( (0 != rItemPair.mpItem) && ((SfxPoolItem*)-1 != rItemPair.mpItem) )
2270cdf0e10cSrcweir                     {
2271cdf0e10cSrcweir                         const sal_uInt16 nWh =
2272cdf0e10cSrcweir                             static_cast<sal_uInt16>(n + RES_CHRATR_BEGIN);
2273cdf0e10cSrcweir 
2274cdf0e10cSrcweir                         if( nEnd <= rItemPair.mnEndPos ) // hinter oder genau Ende
2275cdf0e10cSrcweir                         {
2276cdf0e10cSrcweir                             if( *rItemPair.mpItem != aFmtSet.Get( nWh ) )
2277cdf0e10cSrcweir                                 (*fnMergeAttr)( rSet, *rItemPair.mpItem );
2278cdf0e10cSrcweir                         }
2279cdf0e10cSrcweir                         else
2280cdf0e10cSrcweir                             // uneindeutig
2281cdf0e10cSrcweir                             rSet.InvalidateItem( nWh );
2282cdf0e10cSrcweir                     }
2283cdf0e10cSrcweir                 }
2284cdf0e10cSrcweir 			}
2285cdf0e10cSrcweir 		}
2286cdf0e10cSrcweir 		if( aFmtSet.Count() )
2287cdf0e10cSrcweir 		{
2288cdf0e10cSrcweir 			// aus dem Format-Set alle entfernen, die im TextSet auch gesetzt sind
2289cdf0e10cSrcweir 			aFmtSet.Differentiate( rSet );
2290cdf0e10cSrcweir 			// jetzt alle zusammen "mergen"
2291cdf0e10cSrcweir 			rSet.Put( aFmtSet );
2292cdf0e10cSrcweir 		}
2293cdf0e10cSrcweir 	}
2294cdf0e10cSrcweir 	else if( !bOnlyTxtAttr )
2295cdf0e10cSrcweir     {
2296cdf0e10cSrcweir 		// dann besorge mal die Auto-(Fmt)Attribute
2297cdf0e10cSrcweir 		SwCntntNode::GetAttr( rSet );
2298cdf0e10cSrcweir         // --> OD 2008-01-16 #newlistlevelattrs#
2299cdf0e10cSrcweir         if ( bMergeIndentValuesOfNumRule )
2300cdf0e10cSrcweir         {
2301cdf0e10cSrcweir             lcl_MergeListLevelIndentAsLRSpaceItem( *this, rSet );
2302cdf0e10cSrcweir         }
2303cdf0e10cSrcweir         // <--
2304cdf0e10cSrcweir     }
2305cdf0e10cSrcweir 
2306cdf0e10cSrcweir 	return rSet.Count() ? sal_True : sal_False;
2307cdf0e10cSrcweir }
2308cdf0e10cSrcweir 
2309cdf0e10cSrcweir 
2310cdf0e10cSrcweir namespace
2311cdf0e10cSrcweir {
2312cdf0e10cSrcweir 
2313cdf0e10cSrcweir typedef std::pair<sal_uInt16, sal_uInt16> AttrSpan_t;
2314cdf0e10cSrcweir typedef std::multimap<AttrSpan_t, const SwTxtAttr*> AttrSpanMap_t;
2315cdf0e10cSrcweir 
2316cdf0e10cSrcweir 
2317cdf0e10cSrcweir struct IsAutoStyle
2318cdf0e10cSrcweir {
2319cdf0e10cSrcweir     bool
operator ()__anonede8ea370111::IsAutoStyle2320cdf0e10cSrcweir     operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
2321cdf0e10cSrcweir     const
2322cdf0e10cSrcweir     {
2323cdf0e10cSrcweir         return i_rAttrSpan.second && i_rAttrSpan.second->Which() == RES_TXTATR_AUTOFMT;
2324cdf0e10cSrcweir     }
2325cdf0e10cSrcweir };
2326cdf0e10cSrcweir 
2327cdf0e10cSrcweir 
2328cdf0e10cSrcweir /** Removes from io_rAttrSet all items that are set by style on the
2329cdf0e10cSrcweir     given span.
2330cdf0e10cSrcweir   */
2331cdf0e10cSrcweir struct RemovePresentAttrs
2332cdf0e10cSrcweir {
RemovePresentAttrs__anonede8ea370111::RemovePresentAttrs2333cdf0e10cSrcweir     RemovePresentAttrs(SfxItemSet& io_rAttrSet)
2334cdf0e10cSrcweir         : m_rAttrSet(io_rAttrSet)
2335cdf0e10cSrcweir     {
2336cdf0e10cSrcweir     }
2337cdf0e10cSrcweir 
2338cdf0e10cSrcweir     void
operator ()__anonede8ea370111::RemovePresentAttrs2339cdf0e10cSrcweir     operator()(const AttrSpanMap_t::value_type& i_rAttrSpan)
2340cdf0e10cSrcweir     const
2341cdf0e10cSrcweir     {
2342cdf0e10cSrcweir         if (!i_rAttrSpan.second)
2343cdf0e10cSrcweir         {
2344cdf0e10cSrcweir             return;
2345cdf0e10cSrcweir         }
2346cdf0e10cSrcweir 
2347cdf0e10cSrcweir         const SwTxtAttr* const pAutoStyle(i_rAttrSpan.second);
2348cdf0e10cSrcweir         SfxItemIter aIter(m_rAttrSet);
2349cdf0e10cSrcweir         const SfxPoolItem* pItem(aIter.GetCurItem());
2350cdf0e10cSrcweir         while (pItem)
2351cdf0e10cSrcweir         {
2352cdf0e10cSrcweir             const sal_uInt16 nWhich(pItem->Which());
2353cdf0e10cSrcweir             if (CharFmt::IsItemIncluded(nWhich, pAutoStyle))
2354cdf0e10cSrcweir             {
2355cdf0e10cSrcweir                 m_rAttrSet.ClearItem(nWhich);
2356cdf0e10cSrcweir             }
2357cdf0e10cSrcweir 
2358cdf0e10cSrcweir             if (aIter.IsAtEnd())
2359cdf0e10cSrcweir             {
2360cdf0e10cSrcweir                 break;
2361cdf0e10cSrcweir             }
2362cdf0e10cSrcweir             pItem = aIter.NextItem();
2363cdf0e10cSrcweir         }
2364cdf0e10cSrcweir     }
2365cdf0e10cSrcweir 
2366cdf0e10cSrcweir private:
2367cdf0e10cSrcweir     SfxItemSet& m_rAttrSet;
2368cdf0e10cSrcweir };
2369cdf0e10cSrcweir 
2370cdf0e10cSrcweir 
2371cdf0e10cSrcweir /** Collects all style-covered spans from i_rHints to o_rSpanMap. In
2372cdf0e10cSrcweir     addition inserts dummy spans with pointer to format equal to 0 for
2373cdf0e10cSrcweir     all gaps (i.e. spans not covered by any style). This simplifies
2374cdf0e10cSrcweir     creation of autostyles for all needed spans, but it means all code
2375cdf0e10cSrcweir     that tries to access the pointer has to check if it's non-null!
2376cdf0e10cSrcweir  */
2377cdf0e10cSrcweir void
lcl_CollectHintSpans(const SwpHints & i_rHints,const sal_uInt16 nLength,AttrSpanMap_t & o_rSpanMap)2378cdf0e10cSrcweir lcl_CollectHintSpans(const SwpHints& i_rHints, const sal_uInt16 nLength,
2379cdf0e10cSrcweir         AttrSpanMap_t& o_rSpanMap)
2380cdf0e10cSrcweir {
2381cdf0e10cSrcweir     sal_uInt16 nLastEnd(0);
2382cdf0e10cSrcweir 
2383cdf0e10cSrcweir     for (sal_uInt16 i(0); i != i_rHints.Count(); ++i)
2384cdf0e10cSrcweir     {
2385cdf0e10cSrcweir         const SwTxtAttr* const pHint(i_rHints[i]);
2386cdf0e10cSrcweir         const sal_uInt16 nWhich(pHint->Which());
2387cdf0e10cSrcweir         if (nWhich == RES_TXTATR_CHARFMT || nWhich == RES_TXTATR_AUTOFMT)
2388cdf0e10cSrcweir         {
238969a74367SOliver-Rainer Wittmann             const AttrSpan_t aSpan(*pHint->GetStart(), *pHint->End());
2390cdf0e10cSrcweir             o_rSpanMap.insert(AttrSpanMap_t::value_type(aSpan, pHint));
2391cdf0e10cSrcweir 
2392cdf0e10cSrcweir             // < not != because there may be multiple CHARFMT at same range
2393cdf0e10cSrcweir             if (nLastEnd < aSpan.first)
2394cdf0e10cSrcweir             {
2395cdf0e10cSrcweir                 // insert dummy span covering the gap
2396cdf0e10cSrcweir                 o_rSpanMap.insert(AttrSpanMap_t::value_type(
2397cdf0e10cSrcweir                             AttrSpan_t(nLastEnd, aSpan.first), 0));
2398cdf0e10cSrcweir             }
2399cdf0e10cSrcweir 
2400cdf0e10cSrcweir             nLastEnd = aSpan.second;
2401cdf0e10cSrcweir         }
2402cdf0e10cSrcweir     }
2403cdf0e10cSrcweir 
2404cdf0e10cSrcweir     // no hints at the end (special case: no hints at all in i_rHints)
2405cdf0e10cSrcweir     if (nLastEnd != nLength && nLength != 0)
2406cdf0e10cSrcweir     {
2407cdf0e10cSrcweir         o_rSpanMap.insert(
2408cdf0e10cSrcweir             AttrSpanMap_t::value_type(AttrSpan_t(nLastEnd, nLength), 0));
2409cdf0e10cSrcweir     }
2410cdf0e10cSrcweir }
2411cdf0e10cSrcweir 
2412cdf0e10cSrcweir 
2413cdf0e10cSrcweir void
lcl_FillWhichIds(const SfxItemSet & i_rAttrSet,std::vector<sal_uInt16> & o_rClearIds)2414cdf0e10cSrcweir lcl_FillWhichIds(const SfxItemSet& i_rAttrSet, std::vector<sal_uInt16>& o_rClearIds)
2415cdf0e10cSrcweir {
2416cdf0e10cSrcweir     o_rClearIds.reserve(i_rAttrSet.Count());
2417cdf0e10cSrcweir     SfxItemIter aIter(i_rAttrSet);
2418cdf0e10cSrcweir     const SfxPoolItem* pItem(aIter.GetCurItem());
2419cdf0e10cSrcweir     while (true)
2420cdf0e10cSrcweir     {
2421cdf0e10cSrcweir         o_rClearIds.push_back(pItem->Which());
2422cdf0e10cSrcweir 
2423cdf0e10cSrcweir         if (aIter.IsAtEnd())
2424cdf0e10cSrcweir         {
2425cdf0e10cSrcweir             break;
2426cdf0e10cSrcweir         }
2427cdf0e10cSrcweir         pItem = aIter.NextItem();
2428cdf0e10cSrcweir     }
2429cdf0e10cSrcweir }
2430cdf0e10cSrcweir 
2431cdf0e10cSrcweir struct SfxItemSetClearer
2432cdf0e10cSrcweir {
2433cdf0e10cSrcweir     SfxItemSet & m_rItemSet;
SfxItemSetClearer__anonede8ea370111::SfxItemSetClearer2434cdf0e10cSrcweir     SfxItemSetClearer(SfxItemSet & rItemSet) : m_rItemSet(rItemSet) { }
operator ()__anonede8ea370111::SfxItemSetClearer2435cdf0e10cSrcweir     void operator()(sal_uInt16 const nWhich) { m_rItemSet.ClearItem(nWhich); }
2436cdf0e10cSrcweir };
2437cdf0e10cSrcweir 
2438cdf0e10cSrcweir }
2439cdf0e10cSrcweir 
2440cdf0e10cSrcweir 
2441cdf0e10cSrcweir /** Does the hard work of SwTxtNode::FmtToTxtAttr: the real conversion
2442cdf0e10cSrcweir     of items to automatic styles.
2443cdf0e10cSrcweir  */
2444cdf0e10cSrcweir void
impl_FmtToTxtAttr(const SfxItemSet & i_rAttrSet)2445cdf0e10cSrcweir SwTxtNode::impl_FmtToTxtAttr(const SfxItemSet& i_rAttrSet)
2446cdf0e10cSrcweir {
2447cdf0e10cSrcweir     typedef AttrSpanMap_t::iterator AttrSpanMap_iterator_t;
2448cdf0e10cSrcweir     AttrSpanMap_t aAttrSpanMap;
2449cdf0e10cSrcweir 
2450cdf0e10cSrcweir     if (i_rAttrSet.Count() == 0)
2451cdf0e10cSrcweir     {
2452cdf0e10cSrcweir         return;
2453cdf0e10cSrcweir     }
2454cdf0e10cSrcweir 
2455cdf0e10cSrcweir     // 1. Identify all spans in hints' array
2456cdf0e10cSrcweir 
2457cdf0e10cSrcweir     lcl_CollectHintSpans(*m_pSwpHints, m_Text.Len(), aAttrSpanMap);
2458cdf0e10cSrcweir 
2459cdf0e10cSrcweir     // 2. Go through all spans and insert new attrs
2460cdf0e10cSrcweir 
2461cdf0e10cSrcweir     AttrSpanMap_iterator_t aCurRange(aAttrSpanMap.begin());
2462cdf0e10cSrcweir     const AttrSpanMap_iterator_t aEnd(aAttrSpanMap.end());
2463cdf0e10cSrcweir     while (aCurRange != aEnd)
2464cdf0e10cSrcweir     {
2465cdf0e10cSrcweir         typedef std::pair<AttrSpanMap_iterator_t, AttrSpanMap_iterator_t>
2466cdf0e10cSrcweir             AttrSpanMapRange_t;
2467cdf0e10cSrcweir         AttrSpanMapRange_t aRange(aAttrSpanMap.equal_range(aCurRange->first));
2468cdf0e10cSrcweir 
2469cdf0e10cSrcweir         // 2a. Collect attributes to insert
2470cdf0e10cSrcweir 
2471cdf0e10cSrcweir         SfxItemSet aCurSet(i_rAttrSet);
2472cdf0e10cSrcweir         std::for_each(aRange.first, aRange.second, RemovePresentAttrs(aCurSet));
2473cdf0e10cSrcweir 
2474cdf0e10cSrcweir         // 2b. Insert automatic style containing the collected attributes
2475cdf0e10cSrcweir 
2476cdf0e10cSrcweir         if (aCurSet.Count() != 0)
2477cdf0e10cSrcweir         {
2478cdf0e10cSrcweir             AttrSpanMap_iterator_t aAutoStyleIt(
2479cdf0e10cSrcweir                     std::find_if(aRange.first, aRange.second, IsAutoStyle()));
2480cdf0e10cSrcweir             if (aAutoStyleIt != aRange.second)
2481cdf0e10cSrcweir             {
2482cdf0e10cSrcweir                 // there already is an automatic style on that span:
2483cdf0e10cSrcweir                 // create new one and remove the original one
2484cdf0e10cSrcweir                 SwTxtAttr* const pAutoStyle(const_cast<SwTxtAttr*>(aAutoStyleIt->second));
2485cdf0e10cSrcweir                 const boost::shared_ptr<SfxItemSet> pOldStyle(
2486cdf0e10cSrcweir                         static_cast<const SwFmtAutoFmt&>(
2487cdf0e10cSrcweir                             pAutoStyle->GetAttr()).GetStyleHandle());
2488cdf0e10cSrcweir                 aCurSet.Put(*pOldStyle);
2489cdf0e10cSrcweir 
2490cdf0e10cSrcweir                 // remove the old hint
2491cdf0e10cSrcweir                 m_pSwpHints->Delete(pAutoStyle);
2492cdf0e10cSrcweir                 DestroyAttr(pAutoStyle);
2493cdf0e10cSrcweir             }
2494cdf0e10cSrcweir             m_pSwpHints->Insert(
2495cdf0e10cSrcweir                     MakeTxtAttr(*GetDoc(), aCurSet,
2496cdf0e10cSrcweir                         aCurRange->first.first, aCurRange->first.second));
2497cdf0e10cSrcweir         }
2498cdf0e10cSrcweir 
2499cdf0e10cSrcweir         aCurRange = aRange.second;
2500cdf0e10cSrcweir     }
2501cdf0e10cSrcweir 
2502cdf0e10cSrcweir     // 3. Clear items from the node
2503cdf0e10cSrcweir     std::vector<sal_uInt16> aClearedIds;
2504cdf0e10cSrcweir     lcl_FillWhichIds(i_rAttrSet, aClearedIds);
2505cdf0e10cSrcweir     ClearItemsFromAttrSet(aClearedIds);
2506cdf0e10cSrcweir }
2507cdf0e10cSrcweir 
FmtToTxtAttr(SwTxtNode * pNd)2508cdf0e10cSrcweir void SwTxtNode::FmtToTxtAttr( SwTxtNode* pNd )
2509cdf0e10cSrcweir {
2510cdf0e10cSrcweir 	SfxItemSet aThisSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
2511cdf0e10cSrcweir     if( HasSwAttrSet() && GetpSwAttrSet()->Count() )
2512cdf0e10cSrcweir 		aThisSet.Put( *GetpSwAttrSet() );
2513cdf0e10cSrcweir 
2514cdf0e10cSrcweir     GetOrCreateSwpHints();
2515cdf0e10cSrcweir 
2516cdf0e10cSrcweir 	if( pNd == this )
2517cdf0e10cSrcweir 	{
2518cdf0e10cSrcweir         impl_FmtToTxtAttr(aThisSet);
2519cdf0e10cSrcweir     }
2520cdf0e10cSrcweir 	else
2521cdf0e10cSrcweir 	{
2522cdf0e10cSrcweir         // There are five possible combinations of items from this and
2523cdf0e10cSrcweir         // pNd (pNd is the 'main' node):
2524cdf0e10cSrcweir         //
2525cdf0e10cSrcweir         //  case    pNd     this     action
2526cdf0e10cSrcweir         //  ----------------------------------------------------
2527cdf0e10cSrcweir         //     1     -       -      do nothing
2528cdf0e10cSrcweir         //     2     -       a      convert item to attr of this
2529cdf0e10cSrcweir         //     3     a       -      convert item to attr of pNd
2530cdf0e10cSrcweir         //     4     a       a      clear item in this
2531cdf0e10cSrcweir         //     5     a       b      convert item to attr of this
2532cdf0e10cSrcweir 
2533cdf0e10cSrcweir 		SfxItemSet aNdSet( pNd->GetDoc()->GetAttrPool(), aCharFmtSetRange );
2534cdf0e10cSrcweir         if( pNd->HasSwAttrSet() && pNd->GetpSwAttrSet()->Count() )
2535cdf0e10cSrcweir 			aNdSet.Put( *pNd->GetpSwAttrSet() );
2536cdf0e10cSrcweir 
2537cdf0e10cSrcweir         pNd->GetOrCreateSwpHints();
2538cdf0e10cSrcweir 
2539cdf0e10cSrcweir         std::vector<sal_uInt16> aProcessedIds;
2540cdf0e10cSrcweir 
2541cdf0e10cSrcweir 		if( aThisSet.Count() )
2542cdf0e10cSrcweir 		{
2543cdf0e10cSrcweir 			SfxItemIter aIter( aThisSet );
2544cdf0e10cSrcweir 			const SfxPoolItem* pItem = aIter.GetCurItem(), *pNdItem = 0;
2545cdf0e10cSrcweir             SfxItemSet aConvertSet( GetDoc()->GetAttrPool(), aCharFmtSetRange );
2546cdf0e10cSrcweir             std::vector<sal_uInt16> aClearWhichIds;
2547cdf0e10cSrcweir 
2548cdf0e10cSrcweir 			while( true )
2549cdf0e10cSrcweir 			{
2550cdf0e10cSrcweir 				if( SFX_ITEM_SET == aNdSet.GetItemState( pItem->Which(), sal_False, &pNdItem ) )
2551cdf0e10cSrcweir                 {
2552cdf0e10cSrcweir                     if (*pItem == *pNdItem) // 4
2553cdf0e10cSrcweir                     {
2554cdf0e10cSrcweir                         aClearWhichIds.push_back( pItem->Which() );
2555cdf0e10cSrcweir                     }
2556cdf0e10cSrcweir                     else    // 5
2557cdf0e10cSrcweir                     {
2558cdf0e10cSrcweir                         aConvertSet.Put(*pItem);
2559cdf0e10cSrcweir                     }
2560cdf0e10cSrcweir                     aProcessedIds.push_back(pItem->Which());
2561cdf0e10cSrcweir                 }
2562cdf0e10cSrcweir                 else    // 2
2563cdf0e10cSrcweir                 {
2564cdf0e10cSrcweir                     aConvertSet.Put(*pItem);
2565cdf0e10cSrcweir                 }
2566cdf0e10cSrcweir 
2567cdf0e10cSrcweir 				if( aIter.IsAtEnd() )
2568cdf0e10cSrcweir 					break;
2569cdf0e10cSrcweir 				pItem = aIter.NextItem();
2570cdf0e10cSrcweir 			}
2571cdf0e10cSrcweir 
2572cdf0e10cSrcweir             // 4/ clear items of this that are set with the same value on pNd
2573cdf0e10cSrcweir             ClearItemsFromAttrSet( aClearWhichIds );
2574cdf0e10cSrcweir 
2575cdf0e10cSrcweir             // 2, 5/ convert all other items to attrs
2576cdf0e10cSrcweir             impl_FmtToTxtAttr(aConvertSet);
2577cdf0e10cSrcweir         }
2578cdf0e10cSrcweir 
2579cdf0e10cSrcweir         {
2580cdf0e10cSrcweir             std::for_each(aProcessedIds.begin(), aProcessedIds.end(),
2581cdf0e10cSrcweir                     SfxItemSetClearer(aNdSet));
2582cdf0e10cSrcweir 
2583cdf0e10cSrcweir             // 3/ convert items to attrs
2584cdf0e10cSrcweir             pNd->impl_FmtToTxtAttr(aNdSet);
2585cdf0e10cSrcweir 
2586cdf0e10cSrcweir             if( aNdSet.Count() )
2587cdf0e10cSrcweir             {
2588cdf0e10cSrcweir                 SwFmtChg aTmp1( pNd->GetFmtColl() );
2589cdf0e10cSrcweir                 pNd->NotifyClients( &aTmp1, &aTmp1 );
2590cdf0e10cSrcweir             }
2591cdf0e10cSrcweir         }
2592cdf0e10cSrcweir     }
2593cdf0e10cSrcweir 
2594cdf0e10cSrcweir     SetCalcHiddenCharFlags();
2595cdf0e10cSrcweir 
2596cdf0e10cSrcweir     pNd->TryDeleteSwpHints();
2597cdf0e10cSrcweir }
2598cdf0e10cSrcweir 
2599cdf0e10cSrcweir /*************************************************************************
2600cdf0e10cSrcweir  *						SwpHints::CalcFlags()
2601cdf0e10cSrcweir  *************************************************************************/
2602cdf0e10cSrcweir 
CalcFlags()2603cdf0e10cSrcweir void SwpHints::CalcFlags()
2604cdf0e10cSrcweir {
2605cdf0e10cSrcweir     m_bDDEFields = m_bFootnote = false;
2606c0286415SOliver-Rainer Wittmann     const sal_uInt16 nSize = Count();
2607c0286415SOliver-Rainer Wittmann     const SwTxtAttr* pAttr;
2608c0286415SOliver-Rainer Wittmann     for( sal_uInt16 nPos = 0; nPos < nSize; ++nPos )
2609cdf0e10cSrcweir     {
2610c0286415SOliver-Rainer Wittmann         switch( ( pAttr = (*this)[ nPos ])->Which() )
2611c0286415SOliver-Rainer Wittmann         {
2612c0286415SOliver-Rainer Wittmann         case RES_TXTATR_FTN:
2613cdf0e10cSrcweir             m_bFootnote = true;
2614cdf0e10cSrcweir             if ( m_bDDEFields )
2615cdf0e10cSrcweir                 return;
2616c0286415SOliver-Rainer Wittmann             break;
2617c0286415SOliver-Rainer Wittmann         case RES_TXTATR_FIELD:
2618c0286415SOliver-Rainer Wittmann             {
2619c0286415SOliver-Rainer Wittmann                 const SwField* pFld = pAttr->GetFmtFld().GetField();
2620c0286415SOliver-Rainer Wittmann                 if( RES_DDEFLD == pFld->GetTyp()->Which() )
2621cdf0e10cSrcweir                 {
2622cdf0e10cSrcweir                     m_bDDEFields = true;
2623cdf0e10cSrcweir                     if ( m_bFootnote )
2624cdf0e10cSrcweir                         return;
2625cdf0e10cSrcweir                 }
2626cdf0e10cSrcweir             }
2627cdf0e10cSrcweir             break;
2628cdf0e10cSrcweir         }
2629cdf0e10cSrcweir     }
2630cdf0e10cSrcweir }
2631cdf0e10cSrcweir 
2632cdf0e10cSrcweir /*************************************************************************
2633cdf0e10cSrcweir  *						SwpHints::CalcVisibleFlag()
2634cdf0e10cSrcweir  *************************************************************************/
2635cdf0e10cSrcweir 
CalcHiddenParaField()2636cdf0e10cSrcweir bool SwpHints::CalcHiddenParaField()
2637cdf0e10cSrcweir {
2638cdf0e10cSrcweir     m_bCalcHiddenParaField = false;
2639cdf0e10cSrcweir     bool bOldHasHiddenParaField = m_bHasHiddenParaField;
2640cdf0e10cSrcweir     bool bNewHasHiddenParaField  = false;
2641dec99bbdSOliver-Rainer Wittmann     const sal_uInt16	nSize = Count();
2642dec99bbdSOliver-Rainer Wittmann     const SwTxtAttr *pTxtHt;
2643cdf0e10cSrcweir 
2644dec99bbdSOliver-Rainer Wittmann     for( sal_uInt16 nPos = 0; nPos < nSize; ++nPos )
2645dec99bbdSOliver-Rainer Wittmann     {
2646dec99bbdSOliver-Rainer Wittmann         pTxtHt = (*this)[ nPos ];
2647dec99bbdSOliver-Rainer Wittmann         const sal_uInt16 nWhich = pTxtHt->Which();
2648cdf0e10cSrcweir 
2649dec99bbdSOliver-Rainer Wittmann         if( RES_TXTATR_FIELD == nWhich )
2650dec99bbdSOliver-Rainer Wittmann         {
2651dec99bbdSOliver-Rainer Wittmann             const SwFmtFld& rFld = pTxtHt->GetFmtFld();
2652c0286415SOliver-Rainer Wittmann             if( RES_HIDDENPARAFLD == rFld.GetField()->GetTyp()->Which() )
2653dec99bbdSOliver-Rainer Wittmann             {
2654dec99bbdSOliver-Rainer Wittmann                 if( !((SwHiddenParaField*)rFld.GetField())->IsHidden() )
2655cdf0e10cSrcweir                 {
2656cdf0e10cSrcweir                     SetHiddenParaField(false);
2657cdf0e10cSrcweir                     return bOldHasHiddenParaField != bNewHasHiddenParaField;
2658cdf0e10cSrcweir                 }
2659cdf0e10cSrcweir                 else
2660cdf0e10cSrcweir                 {
2661cdf0e10cSrcweir                     bNewHasHiddenParaField = true;
2662cdf0e10cSrcweir                 }
2663cdf0e10cSrcweir             }
2664cdf0e10cSrcweir         }
2665cdf0e10cSrcweir     }
2666cdf0e10cSrcweir     SetHiddenParaField( bNewHasHiddenParaField );
2667cdf0e10cSrcweir     return bOldHasHiddenParaField != bNewHasHiddenParaField;
2668cdf0e10cSrcweir }
2669cdf0e10cSrcweir 
2670cdf0e10cSrcweir 
2671cdf0e10cSrcweir /*************************************************************************
2672cdf0e10cSrcweir  *						SwpHints::NoteInHistory()
2673cdf0e10cSrcweir  *************************************************************************/
2674cdf0e10cSrcweir 
NoteInHistory(SwTxtAttr * pAttr,const bool bNew)2675cdf0e10cSrcweir void SwpHints::NoteInHistory( SwTxtAttr *pAttr, const bool bNew )
2676cdf0e10cSrcweir {
2677cdf0e10cSrcweir     if ( m_pHistory ) { m_pHistory->AddHint( pAttr, bNew ); }
2678cdf0e10cSrcweir }
2679cdf0e10cSrcweir 
2680cdf0e10cSrcweir /*************************************************************************
2681cdf0e10cSrcweir  *                      SwpHints::MergePortions( )
2682cdf0e10cSrcweir  *************************************************************************/
2683cdf0e10cSrcweir 
MergePortions(SwTxtNode & rNode)2684cdf0e10cSrcweir bool SwpHints::MergePortions( SwTxtNode& rNode )
2685cdf0e10cSrcweir {
2686cdf0e10cSrcweir     if ( !Count() )
2687cdf0e10cSrcweir         return false;
2688cdf0e10cSrcweir 
2689cdf0e10cSrcweir     // sort before merging
2690cdf0e10cSrcweir     SwpHintsArray::Resort();
2691cdf0e10cSrcweir 
2692cdf0e10cSrcweir     bool bRet = false;
2693cdf0e10cSrcweir     typedef std::multimap< int, SwTxtAttr* > PortionMap;
2694cdf0e10cSrcweir     PortionMap aPortionMap;
2695cdf0e10cSrcweir     xub_StrLen nLastPorStart = STRING_LEN;
2696cdf0e10cSrcweir     sal_uInt16 i = 0;
2697cdf0e10cSrcweir     int nKey = 0;
2698cdf0e10cSrcweir 
2699cdf0e10cSrcweir     // get portions by start position:
2700cdf0e10cSrcweir     for ( i = 0; i < Count(); ++i )
2701cdf0e10cSrcweir     {
2702cdf0e10cSrcweir         SwTxtAttr *pHt = GetTextHint( i );
2703cdf0e10cSrcweir         if ( RES_TXTATR_CHARFMT != pHt->Which() &&
2704cdf0e10cSrcweir              RES_TXTATR_AUTOFMT != pHt->Which() )
2705cdf0e10cSrcweir              //&&
2706cdf0e10cSrcweir              //RES_TXTATR_INETFMT != pHt->Which() )
2707cdf0e10cSrcweir             continue;
2708cdf0e10cSrcweir 
2709cdf0e10cSrcweir         const xub_StrLen nPorStart = *pHt->GetStart();
2710cdf0e10cSrcweir         if ( nPorStart != nLastPorStart && nLastPorStart != STRING_LEN )
2711cdf0e10cSrcweir             ++nKey;
2712cdf0e10cSrcweir         nLastPorStart = nPorStart;
2713cdf0e10cSrcweir         aPortionMap.insert( std::pair< const int, SwTxtAttr* >( nKey, pHt ) );
2714cdf0e10cSrcweir     }
2715cdf0e10cSrcweir 
2716cdf0e10cSrcweir     // check if portion i can be merged with portion i+1:
2717cdf0e10cSrcweir     i = 0;
2718cdf0e10cSrcweir     int j = i + 1;
2719cdf0e10cSrcweir     while ( i <= nKey )
2720cdf0e10cSrcweir     {
2721cdf0e10cSrcweir         std::pair< PortionMap::iterator, PortionMap::iterator > aRange1 = aPortionMap.equal_range( i );
2722cdf0e10cSrcweir         std::pair< PortionMap::iterator, PortionMap::iterator > aRange2 = aPortionMap.equal_range( j );
2723cdf0e10cSrcweir         PortionMap::iterator aIter1 = aRange1.first;
2724cdf0e10cSrcweir         PortionMap::iterator aIter2 = aRange2.first;
2725cdf0e10cSrcweir 
2726cdf0e10cSrcweir         bool bMerge = true;
2727cdf0e10cSrcweir         const sal_uInt16 nAttributesInPor1  = static_cast<sal_uInt16>(std::distance( aRange1.first, aRange1.second ));
2728cdf0e10cSrcweir         const sal_uInt16 nAttributesInPor2  = static_cast<sal_uInt16>(std::distance( aRange2.first, aRange2.second ));
2729cdf0e10cSrcweir 
2730cdf0e10cSrcweir         if ( nAttributesInPor1 == nAttributesInPor2 && nAttributesInPor1 != 0 )
2731cdf0e10cSrcweir         {
2732cdf0e10cSrcweir             while ( aIter1 != aRange1.second )
2733cdf0e10cSrcweir             {
2734cdf0e10cSrcweir                 const SwTxtAttr* p1 = (*aIter1).second;
2735cdf0e10cSrcweir                 const SwTxtAttr* p2 = (*aIter2).second;
273669a74367SOliver-Rainer Wittmann                 if ( *p1->End() < *p2->GetStart() || p1->Which() != p2->Which() || !(*p1 == *p2) )
2737cdf0e10cSrcweir                 {
2738cdf0e10cSrcweir                     bMerge = false;
2739cdf0e10cSrcweir                     break;
2740cdf0e10cSrcweir                 }
2741cdf0e10cSrcweir                 ++aIter1;
2742cdf0e10cSrcweir                 ++aIter2;
2743cdf0e10cSrcweir             }
2744cdf0e10cSrcweir         }
2745cdf0e10cSrcweir         else
2746cdf0e10cSrcweir         {
2747cdf0e10cSrcweir             bMerge = false;
2748cdf0e10cSrcweir         }
2749cdf0e10cSrcweir 
2750cdf0e10cSrcweir         if ( bMerge )
2751cdf0e10cSrcweir         {
2752cdf0e10cSrcweir             // erase all elements with key i + 1
2753cdf0e10cSrcweir             xub_StrLen nNewPortionEnd = 0;
2754cdf0e10cSrcweir             for ( aIter2 = aRange2.first; aIter2 != aRange2.second; ++aIter2 )
2755cdf0e10cSrcweir             {
2756cdf0e10cSrcweir                 SwTxtAttr* p2 = (*aIter2).second;
2757cdf0e10cSrcweir                 nNewPortionEnd = *p2->GetEnd();
2758cdf0e10cSrcweir 
2759cdf0e10cSrcweir                 const sal_uInt16 nCountBeforeDelete = Count();
2760cdf0e10cSrcweir                 Delete( p2 );
2761cdf0e10cSrcweir 
2762cdf0e10cSrcweir                 // robust: check if deletion actually took place before destroying attribute:
2763cdf0e10cSrcweir                 if ( Count() < nCountBeforeDelete )
2764cdf0e10cSrcweir                     rNode.DestroyAttr( p2 );
2765cdf0e10cSrcweir             }
2766cdf0e10cSrcweir             aPortionMap.erase( aRange2.first, aRange2.second );
2767cdf0e10cSrcweir             ++j;
2768cdf0e10cSrcweir 
2769cdf0e10cSrcweir             // change all attributes with key i
2770cdf0e10cSrcweir             aRange1 = aPortionMap.equal_range( i );
2771cdf0e10cSrcweir             for ( aIter1 = aRange1.first; aIter1 != aRange1.second; ++aIter1 )
2772cdf0e10cSrcweir             {
2773cdf0e10cSrcweir                 SwTxtAttr* p1 = (*aIter1).second;
2774cdf0e10cSrcweir                 NoteInHistory( p1 );
2775cdf0e10cSrcweir                 *p1->GetEnd() = nNewPortionEnd;
2776cdf0e10cSrcweir                 NoteInHistory( p1, true );
2777cdf0e10cSrcweir                 bRet = true;
2778cdf0e10cSrcweir             }
2779cdf0e10cSrcweir         }
2780cdf0e10cSrcweir         else
2781cdf0e10cSrcweir         {
2782cdf0e10cSrcweir             ++i;
2783cdf0e10cSrcweir             j = i + 1;
2784cdf0e10cSrcweir         }
2785cdf0e10cSrcweir     }
2786cdf0e10cSrcweir 
2787cdf0e10cSrcweir     if ( bRet )
2788cdf0e10cSrcweir     {
2789cdf0e10cSrcweir         SwpHintsArray::Resort();
2790cdf0e10cSrcweir     }
2791cdf0e10cSrcweir 
2792cdf0e10cSrcweir     return bRet;
2793cdf0e10cSrcweir }
2794cdf0e10cSrcweir 
2795cdf0e10cSrcweir // check if there is already a character format and adjust the sort numbers
lcl_CheckSortNumber(const SwpHints & rHints,SwTxtCharFmt & rNewCharFmt)2796cdf0e10cSrcweir void lcl_CheckSortNumber( const SwpHints& rHints, SwTxtCharFmt& rNewCharFmt )
2797cdf0e10cSrcweir {
2798cdf0e10cSrcweir     const xub_StrLen nHtStart = *rNewCharFmt.GetStart();
2799cdf0e10cSrcweir     const xub_StrLen nHtEnd   = *rNewCharFmt.GetEnd();
2800cdf0e10cSrcweir     sal_uInt16 nSortNumber = 0;
2801cdf0e10cSrcweir 
2802cdf0e10cSrcweir     for ( sal_uInt16 i = 0; i < rHints.Count(); ++i )
2803cdf0e10cSrcweir     {
2804cdf0e10cSrcweir         const SwTxtAttr* pOtherHt = rHints[i];
2805cdf0e10cSrcweir 
2806cdf0e10cSrcweir         const xub_StrLen nOtherStart = *pOtherHt->GetStart();
2807cdf0e10cSrcweir 
2808cdf0e10cSrcweir         if ( nOtherStart > nHtStart )
2809cdf0e10cSrcweir             break;
2810cdf0e10cSrcweir 
2811cdf0e10cSrcweir         if ( RES_TXTATR_CHARFMT == pOtherHt->Which() )
2812cdf0e10cSrcweir         {
281369a74367SOliver-Rainer Wittmann             const xub_StrLen nOtherEnd = *pOtherHt->End();
2814cdf0e10cSrcweir 
2815cdf0e10cSrcweir             if ( nOtherStart == nHtStart && nOtherEnd == nHtEnd )
2816cdf0e10cSrcweir             {
2817cdf0e10cSrcweir                 const sal_uInt16 nOtherSortNum = static_cast<const SwTxtCharFmt*>(pOtherHt)->GetSortNumber();
2818cdf0e10cSrcweir                 nSortNumber = nOtherSortNum + 1;
2819cdf0e10cSrcweir             }
2820cdf0e10cSrcweir         }
2821cdf0e10cSrcweir     }
2822cdf0e10cSrcweir 
2823cdf0e10cSrcweir     if ( nSortNumber > 0 )
2824cdf0e10cSrcweir         rNewCharFmt.SetSortNumber( nSortNumber );
2825cdf0e10cSrcweir }
2826cdf0e10cSrcweir 
2827cdf0e10cSrcweir /*************************************************************************
2828cdf0e10cSrcweir  *						SwpHints::Insert()
2829cdf0e10cSrcweir  *************************************************************************/
2830cdf0e10cSrcweir 
2831cdf0e10cSrcweir /*
2832cdf0e10cSrcweir  * Try to insert the new hint.
2833cdf0e10cSrcweir  * Depending on the type of the hint, this either always succeeds, or may fail.
2834cdf0e10cSrcweir  * Depending on the type of the hint, other hints may be deleted or
2835cdf0e10cSrcweir  * overwritten.
2836cdf0e10cSrcweir  * The return value indicates successful insertion.
2837cdf0e10cSrcweir  */
TryInsertHint(SwTxtAttr * const pHint,SwTxtNode & rNode,const SetAttrMode nMode)2838dec99bbdSOliver-Rainer Wittmann bool SwpHints::TryInsertHint(
2839dec99bbdSOliver-Rainer Wittmann     SwTxtAttr* const pHint,
2840dec99bbdSOliver-Rainer Wittmann     SwTxtNode &rNode,
2841dec99bbdSOliver-Rainer Wittmann     const SetAttrMode nMode )
2842cdf0e10cSrcweir {
2843cdf0e10cSrcweir     if ( USHRT_MAX == Count() ) // we're sorry, this flight is overbooked...
2844cdf0e10cSrcweir     {
2845cdf0e10cSrcweir         ASSERT(false, "hints array full :-(");
2846cdf0e10cSrcweir         return false;
2847cdf0e10cSrcweir     }
2848cdf0e10cSrcweir 
2849cdf0e10cSrcweir 	// Felder bilden eine Ausnahme:
2850cdf0e10cSrcweir 	// 1) Sie koennen nie ueberlappen
2851cdf0e10cSrcweir 	// 2) Wenn zwei Felder genau aneinander liegen,
2852cdf0e10cSrcweir 	//	  sollen sie nicht zu einem verschmolzen werden.
2853cdf0e10cSrcweir 	// Wir koennen also auf die while-Schleife verzichten
2854cdf0e10cSrcweir 
2855cdf0e10cSrcweir     xub_StrLen *pHtEnd = pHint->GetEnd();
2856cdf0e10cSrcweir     sal_uInt16 nWhich = pHint->Which();
2857cdf0e10cSrcweir 
2858cdf0e10cSrcweir 	switch( nWhich )
2859cdf0e10cSrcweir 	{
2860cdf0e10cSrcweir 	case RES_TXTATR_CHARFMT:
2861cdf0e10cSrcweir     {
2862cdf0e10cSrcweir         // Check if character format contains hidden attribute:
2863cdf0e10cSrcweir         const SwCharFmt* pFmt = pHint->GetCharFmt().GetCharFmt();
2864cdf0e10cSrcweir         const SfxPoolItem* pItem;
2865cdf0e10cSrcweir         if ( SFX_ITEM_SET == pFmt->GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
2866cdf0e10cSrcweir             rNode.SetCalcHiddenCharFlags();
2867cdf0e10cSrcweir 
2868cdf0e10cSrcweir         ((SwTxtCharFmt*)pHint)->ChgTxtNode( &rNode );
2869cdf0e10cSrcweir 		break;
2870cdf0e10cSrcweir     }
2871cdf0e10cSrcweir     // --> FME 2007-03-16 #i75430# Recalc hidden flags if necessary
2872cdf0e10cSrcweir     case RES_TXTATR_AUTOFMT:
2873cdf0e10cSrcweir     {
2874cdf0e10cSrcweir         // Check if auto style contains hidden attribute:
2875cdf0e10cSrcweir         const SfxPoolItem* pHiddenItem = CharFmt::GetItem( *pHint, RES_CHRATR_HIDDEN );
2876cdf0e10cSrcweir         if ( pHiddenItem )
2877cdf0e10cSrcweir             rNode.SetCalcHiddenCharFlags();
2878cdf0e10cSrcweir         break;
2879cdf0e10cSrcweir     }
2880cdf0e10cSrcweir     // <--
2881dec99bbdSOliver-Rainer Wittmann 
2882cdf0e10cSrcweir     case RES_TXTATR_INETFMT:
2883cdf0e10cSrcweir         static_cast<SwTxtINetFmt*>(pHint)->InitINetFmt(rNode);
2884dec99bbdSOliver-Rainer Wittmann         break;
2885dec99bbdSOliver-Rainer Wittmann 
2886cdf0e10cSrcweir 	case RES_TXTATR_FIELD:
2887dec99bbdSOliver-Rainer Wittmann 	case RES_TXTATR_ANNOTATION:
288869a74367SOliver-Rainer Wittmann 	case RES_TXTATR_INPUTFIELD:
2889cdf0e10cSrcweir 		{
2890cdf0e10cSrcweir 			sal_Bool bDelFirst = 0 != ((SwTxtFld*)pHint)->GetpTxtNode();
2891cdf0e10cSrcweir 			((SwTxtFld*)pHint)->ChgTxtNode( &rNode );
2892cdf0e10cSrcweir 			SwDoc* pDoc = rNode.GetDoc();
2893c0286415SOliver-Rainer Wittmann 			const SwField* pFld = ((SwTxtFld*)pHint)->GetFmtFld().GetField();
2894cdf0e10cSrcweir 
2895cdf0e10cSrcweir 			if( !pDoc->IsNewFldLst() )
2896cdf0e10cSrcweir 			{
2897cdf0e10cSrcweir 				// was fuer ein Feld ist es denn ??
2898cdf0e10cSrcweir 				// bestimmte Felder mussen am Doc das Calculations-Flag updaten
2899cdf0e10cSrcweir 				switch( pFld->GetTyp()->Which() )
2900cdf0e10cSrcweir 				{
2901cdf0e10cSrcweir 				case RES_DBFLD:
2902cdf0e10cSrcweir 				case RES_SETEXPFLD:
2903cdf0e10cSrcweir 				case RES_HIDDENPARAFLD:
2904cdf0e10cSrcweir 				case RES_HIDDENTXTFLD:
2905cdf0e10cSrcweir 				case RES_DBNUMSETFLD:
2906cdf0e10cSrcweir 				case RES_DBNEXTSETFLD:
2907cdf0e10cSrcweir 					{
2908cdf0e10cSrcweir 						if( bDelFirst )
2909cdf0e10cSrcweir 							pDoc->InsDelFldInFldLst( sal_False, *(SwTxtFld*)pHint );
2910cdf0e10cSrcweir 						if( rNode.GetNodes().IsDocNodes() )
2911cdf0e10cSrcweir 							pDoc->InsDelFldInFldLst( sal_True, *(SwTxtFld*)pHint );
2912cdf0e10cSrcweir 					}
2913cdf0e10cSrcweir 					break;
2914cdf0e10cSrcweir 				case RES_DDEFLD:
2915cdf0e10cSrcweir 					if( rNode.GetNodes().IsDocNodes() )
2916cdf0e10cSrcweir 						((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
2917cdf0e10cSrcweir 					break;
2918cdf0e10cSrcweir 				}
2919cdf0e10cSrcweir 			}
2920cdf0e10cSrcweir 
2921c0286415SOliver-Rainer Wittmann             // gehts ins normale Nodes-Array?
2922c0286415SOliver-Rainer Wittmann             if( rNode.GetNodes().IsDocNodes() )
2923c0286415SOliver-Rainer Wittmann             {
2924c0286415SOliver-Rainer Wittmann                 sal_Bool bInsFldType = sal_False;
2925c0286415SOliver-Rainer Wittmann                 switch( pFld->GetTyp()->Which() )
2926c0286415SOliver-Rainer Wittmann                 {
2927c0286415SOliver-Rainer Wittmann                 case RES_SETEXPFLD:
2928c0286415SOliver-Rainer Wittmann                     bInsFldType = ((SwSetExpFieldType*)pFld->GetTyp())->IsDeleted();
2929c0286415SOliver-Rainer Wittmann                     if( nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFld->GetTyp())->GetType() )
2930c0286415SOliver-Rainer Wittmann                     {
2931c0286415SOliver-Rainer Wittmann                         // bevor die ReferenzNummer gesetzt wird, sollte
2932c0286415SOliver-Rainer Wittmann                         // das Feld am richtigen FeldTypen haengen!
2933c0286415SOliver-Rainer Wittmann                         SwSetExpFieldType* pFldType = (SwSetExpFieldType*)
2934c0286415SOliver-Rainer Wittmann                                     pDoc->InsertFldType( *pFld->GetTyp() );
2935c0286415SOliver-Rainer Wittmann                         if( pFldType != pFld->GetTyp() )
2936c0286415SOliver-Rainer Wittmann                         {
2937c0286415SOliver-Rainer Wittmann                             SwFmtFld* pFmtFld = (SwFmtFld*)&((SwTxtFld*)pHint)->GetFmtFld();
2938cdf0e10cSrcweir                             pFmtFld->RegisterToFieldType( *pFldType );
2939c0286415SOliver-Rainer Wittmann                             pFmtFld->GetField()->ChgTyp( pFldType );
2940c0286415SOliver-Rainer Wittmann                         }
2941c0286415SOliver-Rainer Wittmann                         pFldType->SetSeqRefNo( *(SwSetExpField*)pFld );
2942c0286415SOliver-Rainer Wittmann                     }
2943c0286415SOliver-Rainer Wittmann                     break;
2944c0286415SOliver-Rainer Wittmann                 case RES_USERFLD:
2945c0286415SOliver-Rainer Wittmann                     bInsFldType = ((SwUserFieldType*)pFld->GetTyp())->IsDeleted();
2946c0286415SOliver-Rainer Wittmann                     break;
2947cdf0e10cSrcweir 
2948c0286415SOliver-Rainer Wittmann                 case RES_DDEFLD:
2949c0286415SOliver-Rainer Wittmann                     if( pDoc->IsNewFldLst() )
2950c0286415SOliver-Rainer Wittmann                         ((SwDDEFieldType*)pFld->GetTyp())->IncRefCnt();
2951c0286415SOliver-Rainer Wittmann                     bInsFldType = ((SwDDEFieldType*)pFld->GetTyp())->IsDeleted();
2952c0286415SOliver-Rainer Wittmann                     break;
2953cdf0e10cSrcweir 
2954c0286415SOliver-Rainer Wittmann                 case RES_POSTITFLD:
2955c0286415SOliver-Rainer Wittmann                     if ( pDoc->GetDocShell() )
2956c0286415SOliver-Rainer Wittmann                         pDoc->GetDocShell()->Broadcast( SwFmtFldHint( &((SwTxtFld*)pHint)->GetFmtFld(), SWFMTFLD_INSERTED ) );
2957c0286415SOliver-Rainer Wittmann                     break;
2958c0286415SOliver-Rainer Wittmann                 }
2959c0286415SOliver-Rainer Wittmann                 if( bInsFldType )
2960c0286415SOliver-Rainer Wittmann                     pDoc->InsDeletedFldType( *pFld->GetTyp() );
2961c0286415SOliver-Rainer Wittmann             }
2962c0286415SOliver-Rainer Wittmann         }
2963c0286415SOliver-Rainer Wittmann         break;
2964c0286415SOliver-Rainer Wittmann     case RES_TXTATR_FTN :
2965cdf0e10cSrcweir 		((SwTxtFtn*)pHint)->ChgTxtNode( &rNode );
2966cdf0e10cSrcweir 		break;
2967cdf0e10cSrcweir 	case RES_TXTATR_REFMARK:
2968cdf0e10cSrcweir 		((SwTxtRefMark*)pHint)->ChgTxtNode( &rNode );
2969cdf0e10cSrcweir 		if( rNode.GetNodes().IsDocNodes() )
2970cdf0e10cSrcweir 		{
2971cdf0e10cSrcweir             // search for a reference with the same name
2972cdf0e10cSrcweir 			SwTxtAttr* pTmpHt;
2973cdf0e10cSrcweir 			xub_StrLen *pTmpHtEnd, *pTmpHintEnd;
2974cdf0e10cSrcweir 			for( sal_uInt16 n = 0, nEnd = Count(); n < nEnd; ++n )
2975cdf0e10cSrcweir             {
2976cdf0e10cSrcweir                 if (RES_TXTATR_REFMARK == (pTmpHt = GetTextHint(n))->Which() &&
2977cdf0e10cSrcweir 					pHint->GetAttr() == pTmpHt->GetAttr() &&
2978cdf0e10cSrcweir 					0 != ( pTmpHtEnd = pTmpHt->GetEnd() ) &&
2979cdf0e10cSrcweir 					0 != ( pTmpHintEnd = pHint->GetEnd() ) )
2980cdf0e10cSrcweir 				{
2981cdf0e10cSrcweir 					SwComparePosition eCmp = ::ComparePosition(
2982cdf0e10cSrcweir 							*pTmpHt->GetStart(), *pTmpHtEnd,
2983cdf0e10cSrcweir 							*pHint->GetStart(), *pTmpHintEnd );
2984cdf0e10cSrcweir 					sal_Bool bDelOld = sal_True, bChgStart = sal_False, bChgEnd = sal_False;
2985cdf0e10cSrcweir 					switch( eCmp )
2986cdf0e10cSrcweir 					{
2987cdf0e10cSrcweir 					case POS_BEFORE:
2988cdf0e10cSrcweir 					case POS_BEHIND:	bDelOld = sal_False; break;
2989cdf0e10cSrcweir 
2990cdf0e10cSrcweir 					case POS_OUTSIDE:	bChgStart = bChgEnd = sal_True; break;
2991cdf0e10cSrcweir 
2992cdf0e10cSrcweir 					case POS_COLLIDE_END:
2993cdf0e10cSrcweir 					case POS_OVERLAP_BEFORE:	bChgStart = sal_True; break;
2994cdf0e10cSrcweir 					case POS_COLLIDE_START:
2995cdf0e10cSrcweir 					case POS_OVERLAP_BEHIND:    bChgEnd = sal_True; break;
2996cdf0e10cSrcweir                     default: break;
2997cdf0e10cSrcweir 					}
2998cdf0e10cSrcweir 
2999cdf0e10cSrcweir 					if( bChgStart )
3000cdf0e10cSrcweir 						*pHint->GetStart() = *pTmpHt->GetStart();
3001cdf0e10cSrcweir 					if( bChgEnd )
3002cdf0e10cSrcweir 						*pTmpHintEnd = *pTmpHtEnd;
3003cdf0e10cSrcweir 
3004cdf0e10cSrcweir 					if( bDelOld )
3005cdf0e10cSrcweir                     {
3006cdf0e10cSrcweir                         NoteInHistory( pTmpHt );
3007cdf0e10cSrcweir 						rNode.DestroyAttr( Cut( n-- ) );
3008cdf0e10cSrcweir 						--nEnd;
3009cdf0e10cSrcweir 					}
3010cdf0e10cSrcweir 				}
3011cdf0e10cSrcweir             }
3012cdf0e10cSrcweir 		}
3013cdf0e10cSrcweir 		break;
3014cdf0e10cSrcweir 	case RES_TXTATR_TOXMARK:
3015cdf0e10cSrcweir 		((SwTxtTOXMark*)pHint)->ChgTxtNode( &rNode );
3016cdf0e10cSrcweir 		break;
3017cdf0e10cSrcweir 
3018cdf0e10cSrcweir 	case RES_TXTATR_CJK_RUBY:
3019cdf0e10cSrcweir         static_cast<SwTxtRuby*>(pHint)->InitRuby(rNode);
3020cdf0e10cSrcweir 		break;
3021cdf0e10cSrcweir 
3022cdf0e10cSrcweir     case RES_TXTATR_META:
3023cdf0e10cSrcweir     case RES_TXTATR_METAFIELD:
3024cdf0e10cSrcweir         static_cast<SwTxtMeta *>(pHint)->ChgTxtNode( &rNode );
3025cdf0e10cSrcweir         break;
3026cdf0e10cSrcweir 
3027cdf0e10cSrcweir     case RES_CHRATR_HIDDEN:
3028cdf0e10cSrcweir         rNode.SetCalcHiddenCharFlags();
3029cdf0e10cSrcweir         break;
3030cdf0e10cSrcweir 	}
3031cdf0e10cSrcweir 
3032cdf0e10cSrcweir 	if( nsSetAttrMode::SETATTR_DONTEXPAND & nMode )
3033cdf0e10cSrcweir 		pHint->SetDontExpand( sal_True );
3034cdf0e10cSrcweir 
3035cdf0e10cSrcweir 	// SwTxtAttrs ohne Ende werden sonderbehandelt:
3036cdf0e10cSrcweir 	// Sie werden natuerlich in das Array insertet, aber sie werden nicht
3037cdf0e10cSrcweir 	// in die pPrev/Next/On/Off-Verkettung aufgenommen.
3038cdf0e10cSrcweir 	// Der Formatierer erkennt diese TxtHints an dem CH_TXTATR_.. im Text !
3039cdf0e10cSrcweir 	xub_StrLen nHtStart = *pHint->GetStart();
3040cdf0e10cSrcweir 	if( !pHtEnd )
3041cdf0e10cSrcweir     {
3042cdf0e10cSrcweir         SwpHintsArray::Insert( pHint );
3043cdf0e10cSrcweir 		CalcFlags();
3044cdf0e10cSrcweir #ifdef DBG_UTIL
3045cdf0e10cSrcweir         if( !rNode.GetDoc()->IsInReading() )
3046cdf0e10cSrcweir             CHECK;
3047cdf0e10cSrcweir #endif
3048cdf0e10cSrcweir 		// ... und die Abhaengigen benachrichtigen
3049cdf0e10cSrcweir 		if ( rNode.GetDepends() )
3050cdf0e10cSrcweir 		{
3051cdf0e10cSrcweir 			SwUpdateAttr aHint( nHtStart, nHtStart, nWhich );
3052cdf0e10cSrcweir 			rNode.ModifyNotification( 0, &aHint );
3053cdf0e10cSrcweir         }
3054cdf0e10cSrcweir         return true;
3055cdf0e10cSrcweir     }
3056cdf0e10cSrcweir 
3057cdf0e10cSrcweir 	// ----------------------------------------------------------------
3058cdf0e10cSrcweir 	// Ab hier gibt es nur noch pHint mit einem EndIdx !!!
3059cdf0e10cSrcweir 
3060cdf0e10cSrcweir     if( *pHtEnd < nHtStart )
3061cdf0e10cSrcweir 	{
3062cdf0e10cSrcweir 		ASSERT( *pHtEnd >= nHtStart,
3063cdf0e10cSrcweir 					"+SwpHints::Insert: invalid hint, end < start" );
3064cdf0e10cSrcweir 
3065cdf0e10cSrcweir 		// Wir drehen den Quatsch einfach um:
3066cdf0e10cSrcweir 		*pHint->GetStart() = *pHtEnd;
3067cdf0e10cSrcweir 		*pHtEnd = nHtStart;
3068cdf0e10cSrcweir 		nHtStart = *pHint->GetStart();
3069cdf0e10cSrcweir 	}
3070cdf0e10cSrcweir 
3071cdf0e10cSrcweir     // I need this value later on for notification but the pointer may become invalid
3072cdf0e10cSrcweir     const xub_StrLen nHintEnd = *pHtEnd;
3073cdf0e10cSrcweir     const bool bNoHintAdjustMode = (nsSetAttrMode::SETATTR_NOHINTADJUST & nMode);
3074cdf0e10cSrcweir 
3075cdf0e10cSrcweir     // handle nesting attributes: inserting may fail due to overlap!
3076cdf0e10cSrcweir     if (pHint->IsNesting())
3077cdf0e10cSrcweir     {
3078cdf0e10cSrcweir         const bool bRet(
3079cdf0e10cSrcweir             TryInsertNesting(rNode, *static_cast<SwTxtAttrNesting*>(pHint)));
3080cdf0e10cSrcweir         if (!bRet) return false;
3081cdf0e10cSrcweir     }
3082cdf0e10cSrcweir     // Currently REFMARK and TOXMARK have OverlapAllowed set to true.
3083cdf0e10cSrcweir     // These attributes may be inserted directly.
3084cdf0e10cSrcweir     // Also attributes without length may be inserted directly.
3085cdf0e10cSrcweir     // SETATTR_NOHINTADJUST is set e.g., during undo.
3086cdf0e10cSrcweir     // Portion building in not necessary during XML import.
3087cdf0e10cSrcweir     else
3088cdf0e10cSrcweir     if ( !bNoHintAdjustMode &&
3089cdf0e10cSrcweir          !pHint->IsOverlapAllowedAttr() &&
3090cdf0e10cSrcweir          !rNode.GetDoc()->IsInXMLImport() &&
3091cdf0e10cSrcweir          ( RES_TXTATR_AUTOFMT == nWhich ||
3092cdf0e10cSrcweir            RES_TXTATR_CHARFMT == nWhich ) )
3093cdf0e10cSrcweir     {
3094cdf0e10cSrcweir         ASSERT( nWhich != RES_TXTATR_AUTOFMT ||
3095cdf0e10cSrcweir                 static_cast<const SwFmtAutoFmt&>(pHint->GetAttr()).GetStyleHandle()->GetPool() ==
3096cdf0e10cSrcweir                 &rNode.GetDoc()->GetAttrPool(),
3097cdf0e10cSrcweir                 "AUTOSTYLES - Pool mismatch" )
3098cdf0e10cSrcweir 
3099cdf0e10cSrcweir         BuildPortions( rNode, *pHint, nMode );
3100cdf0e10cSrcweir 
3101cdf0e10cSrcweir         if ( nHtStart < nHintEnd ) // skip merging for 0-length attributes
3102cdf0e10cSrcweir             MergePortions( rNode );
3103cdf0e10cSrcweir     }
3104cdf0e10cSrcweir     else
3105cdf0e10cSrcweir     {
3106cdf0e10cSrcweir         // There may be more than one character style at the current position.
3107cdf0e10cSrcweir         // Take care of the sort number.
3108cdf0e10cSrcweir         // Special case ruby portion: During import, the ruby attribute is set
3109cdf0e10cSrcweir         // multiple times
3110cdf0e10cSrcweir         // Special case hyperlink: During import, the ruby attribute is set
3111cdf0e10cSrcweir         // multiple times
3112cdf0e10cSrcweir         // FME 2007-11-08 #i82989# in NOHINTADJUST mode, we want to insert
3113cdf0e10cSrcweir         // character attributes directly
3114cdf0e10cSrcweir         if ( ( RES_TXTATR_CHARFMT  == nWhich && !bNoHintAdjustMode ) )
3115cdf0e10cSrcweir         {
3116cdf0e10cSrcweir             BuildPortions( rNode, *pHint, nMode );
3117cdf0e10cSrcweir         }
3118cdf0e10cSrcweir         else
3119cdf0e10cSrcweir         {
3120cdf0e10cSrcweir             // --> FME 2007-11-08 #i82989# Check sort numbers in NoHintAdjustMode
3121cdf0e10cSrcweir             if ( RES_TXTATR_CHARFMT == nWhich )
3122cdf0e10cSrcweir                 lcl_CheckSortNumber( *this, *static_cast<SwTxtCharFmt*>(pHint) );
3123cdf0e10cSrcweir             // <--
3124cdf0e10cSrcweir 
3125cdf0e10cSrcweir             SwpHintsArray::Insert( pHint );
3126cdf0e10cSrcweir             NoteInHistory( pHint, true );
3127cdf0e10cSrcweir         }
3128cdf0e10cSrcweir     }
3129cdf0e10cSrcweir 
3130cdf0e10cSrcweir     // ... und die Abhaengigen benachrichtigen
3131cdf0e10cSrcweir 	if ( rNode.GetDepends() )
3132cdf0e10cSrcweir 	{
3133cdf0e10cSrcweir 		SwUpdateAttr aHint( nHtStart, nHtStart == nHintEnd ? nHintEnd + 1 : nHintEnd, nWhich );
3134cdf0e10cSrcweir 		rNode.ModifyNotification( 0, &aHint );
3135cdf0e10cSrcweir 	}
3136cdf0e10cSrcweir 
3137cdf0e10cSrcweir #ifdef DBG_UTIL
3138cdf0e10cSrcweir     if( !bNoHintAdjustMode && !rNode.GetDoc()->IsInReading() )
3139cdf0e10cSrcweir         CHECK;
3140cdf0e10cSrcweir #endif
3141cdf0e10cSrcweir 
3142cdf0e10cSrcweir     return true;
3143cdf0e10cSrcweir }
3144cdf0e10cSrcweir 
3145cdf0e10cSrcweir /*************************************************************************
3146cdf0e10cSrcweir  *						SwpHints::DeleteAtPos()
3147cdf0e10cSrcweir  *************************************************************************/
3148cdf0e10cSrcweir 
DeleteAtPos(const sal_uInt16 nPos)3149cdf0e10cSrcweir void SwpHints::DeleteAtPos( const sal_uInt16 nPos )
3150cdf0e10cSrcweir {
3151cdf0e10cSrcweir     SwTxtAttr *pHint = GetTextHint(nPos);
3152c0286415SOliver-Rainer Wittmann     // ChainDelete( pHint );
3153cdf0e10cSrcweir     NoteInHistory( pHint );
3154c0286415SOliver-Rainer Wittmann     SwpHintsArray::DeleteAtPos( nPos );
3155cdf0e10cSrcweir 
3156dec99bbdSOliver-Rainer Wittmann     if( pHint->Which() == RES_TXTATR_FIELD )
3157c0286415SOliver-Rainer Wittmann     {
3158c0286415SOliver-Rainer Wittmann         const SwFieldType* pFldTyp = ((SwTxtFld*)pHint)->GetFmtFld().GetField()->GetTyp();
3159c0286415SOliver-Rainer Wittmann         if( RES_DDEFLD == pFldTyp->Which() )
3160c0286415SOliver-Rainer Wittmann         {
3161c0286415SOliver-Rainer Wittmann             const SwTxtNode* pNd = ((SwTxtFld*)pHint)->GetpTxtNode();
3162c0286415SOliver-Rainer Wittmann             if( pNd && pNd->GetNodes().IsDocNodes() )
3163c0286415SOliver-Rainer Wittmann                 ((SwDDEFieldType*)pFldTyp)->DecRefCnt();
3164c0286415SOliver-Rainer Wittmann             ((SwTxtFld*)pHint)->ChgTxtNode( 0 );
3165c0286415SOliver-Rainer Wittmann         }
3166cdf0e10cSrcweir         else if ( m_bHasHiddenParaField &&
3167cdf0e10cSrcweir                  RES_HIDDENPARAFLD == pFldTyp->Which() )
3168cdf0e10cSrcweir         {
3169cdf0e10cSrcweir             m_bCalcHiddenParaField = true;
3170cdf0e10cSrcweir         }
3171cdf0e10cSrcweir     }
3172dec99bbdSOliver-Rainer Wittmann     else if ( pHint->Which() == RES_TXTATR_ANNOTATION )
3173dec99bbdSOliver-Rainer Wittmann     {
3174dec99bbdSOliver-Rainer Wittmann         const_cast<SwFmtFld&>(((SwTxtFld*)pHint)->GetFmtFld()).Broadcast( SwFmtFldHint( &((SwTxtFld*)pHint)->GetFmtFld(), SWFMTFLD_REMOVED ) );
3175dec99bbdSOliver-Rainer Wittmann     }
3176cdf0e10cSrcweir 
3177c0286415SOliver-Rainer Wittmann     CalcFlags();
3178c0286415SOliver-Rainer Wittmann     CHECK;
3179cdf0e10cSrcweir }
3180cdf0e10cSrcweir 
3181cdf0e10cSrcweir // Ist der Hint schon bekannt, dann suche die Position und loesche ihn.
3182cdf0e10cSrcweir // Ist er nicht im Array, so gibt es ein ASSERT !!
3183cdf0e10cSrcweir 
Delete(SwTxtAttr * pTxtHt)3184cdf0e10cSrcweir void SwpHints::Delete( SwTxtAttr* pTxtHt )
3185cdf0e10cSrcweir {
3186cdf0e10cSrcweir 	// Attr 2.0: SwpHintsArr::Delete( pTxtHt );
3187cdf0e10cSrcweir 	const sal_uInt16 nPos = GetStartOf( pTxtHt );
3188cdf0e10cSrcweir 	ASSERT( USHRT_MAX != nPos, "Attribut nicht im Attribut-Array!" );
3189cdf0e10cSrcweir 	if( USHRT_MAX != nPos )
3190cdf0e10cSrcweir 		DeleteAtPos( nPos );
3191cdf0e10cSrcweir }
3192cdf0e10cSrcweir 
ClearSwpHintsArr(bool bDelFields)3193cdf0e10cSrcweir void SwTxtNode::ClearSwpHintsArr( bool bDelFields )
3194cdf0e10cSrcweir {
3195cdf0e10cSrcweir     if ( HasHints() )
3196cdf0e10cSrcweir     {
3197cdf0e10cSrcweir         sal_uInt16 nPos = 0;
3198cdf0e10cSrcweir         while ( nPos < m_pSwpHints->Count() )
3199cdf0e10cSrcweir         {
3200cdf0e10cSrcweir             SwTxtAttr* pDel = m_pSwpHints->GetTextHint( nPos );
3201cdf0e10cSrcweir             bool bDel = false;
3202cdf0e10cSrcweir 
3203cdf0e10cSrcweir             switch( pDel->Which() )
3204cdf0e10cSrcweir             {
3205cdf0e10cSrcweir             case RES_TXTATR_FLYCNT:
3206cdf0e10cSrcweir             case RES_TXTATR_FTN:
3207cdf0e10cSrcweir                 break;
3208cdf0e10cSrcweir 
3209cdf0e10cSrcweir             case RES_TXTATR_FIELD:
3210dec99bbdSOliver-Rainer Wittmann             case RES_TXTATR_ANNOTATION:
321169a74367SOliver-Rainer Wittmann             case RES_TXTATR_INPUTFIELD:
3212cdf0e10cSrcweir                 if( bDelFields )
3213cdf0e10cSrcweir                     bDel = true;
3214cdf0e10cSrcweir                 break;
3215cdf0e10cSrcweir             default:
3216cdf0e10cSrcweir                 bDel = true; break;
3217cdf0e10cSrcweir             }
3218cdf0e10cSrcweir 
3219cdf0e10cSrcweir             if( bDel )
3220cdf0e10cSrcweir             {
3221cdf0e10cSrcweir                 m_pSwpHints->SwpHintsArray::DeleteAtPos( nPos );
3222cdf0e10cSrcweir 				DestroyAttr( pDel );
3223cdf0e10cSrcweir 			}
3224cdf0e10cSrcweir 			else
3225cdf0e10cSrcweir 				++nPos;
3226cdf0e10cSrcweir 		}
3227cdf0e10cSrcweir 	}
3228cdf0e10cSrcweir }
3229cdf0e10cSrcweir 
GetLang(const xub_StrLen nBegin,const xub_StrLen nLen,sal_uInt16 nScript) const3230cdf0e10cSrcweir sal_uInt16 SwTxtNode::GetLang( const xub_StrLen nBegin, const xub_StrLen nLen,
3231cdf0e10cSrcweir                            sal_uInt16 nScript ) const
3232cdf0e10cSrcweir {
3233cdf0e10cSrcweir 	sal_uInt16 nRet = LANGUAGE_DONTKNOW;
3234cdf0e10cSrcweir 
3235cdf0e10cSrcweir     if ( ! nScript )
3236cdf0e10cSrcweir     {
3237cdf0e10cSrcweir         nScript = pBreakIt->GetRealScriptOfText( m_Text, nBegin );
3238cdf0e10cSrcweir     }
3239cdf0e10cSrcweir 
3240cdf0e10cSrcweir     // --> FME 2008-09-29 #i91465# hennerdrewes: Consider nScript if pSwpHints == 0
3241cdf0e10cSrcweir     const sal_uInt16 nWhichId = GetWhichOfScript( RES_CHRATR_LANGUAGE, nScript );
3242cdf0e10cSrcweir     // <--
3243cdf0e10cSrcweir 
3244cdf0e10cSrcweir     if ( HasHints() )
3245cdf0e10cSrcweir     {
3246cdf0e10cSrcweir         const xub_StrLen nEnd = nBegin + nLen;
3247cdf0e10cSrcweir         for ( sal_uInt16 i = 0, nSize = m_pSwpHints->Count(); i < nSize; ++i )
3248cdf0e10cSrcweir         {
3249cdf0e10cSrcweir 			// ist der Attribut-Anfang schon groesser als der Idx ?
3250cdf0e10cSrcweir             const SwTxtAttr *pHt = m_pSwpHints->operator[](i);
3251cdf0e10cSrcweir             const xub_StrLen nAttrStart = *pHt->GetStart();
3252cdf0e10cSrcweir 			if( nEnd < nAttrStart )
3253cdf0e10cSrcweir 				break;
3254cdf0e10cSrcweir 
3255cdf0e10cSrcweir 			const sal_uInt16 nWhich = pHt->Which();
3256cdf0e10cSrcweir 
3257cdf0e10cSrcweir             if( nWhichId == nWhich ||
3258cdf0e10cSrcweir                     ( ( pHt->IsCharFmtAttr() || RES_TXTATR_AUTOFMT == nWhich ) && CharFmt::IsItemIncluded( nWhichId, pHt ) ) )
3259cdf0e10cSrcweir             {
326069a74367SOliver-Rainer Wittmann 				const xub_StrLen *pEndIdx = pHt->End();
3261cdf0e10cSrcweir 				// Ueberlappt das Attribut den Bereich?
3262cdf0e10cSrcweir 
3263cdf0e10cSrcweir 				if( pEndIdx &&
3264cdf0e10cSrcweir 					nLen ? ( nAttrStart < nEnd && nBegin < *pEndIdx )
3265cdf0e10cSrcweir 					 	: (( nAttrStart < nBegin &&
3266cdf0e10cSrcweir 								( pHt->DontExpand() ? nBegin < *pEndIdx
3267cdf0e10cSrcweir 													: nBegin <= *pEndIdx )) ||
3268cdf0e10cSrcweir 							( nBegin == nAttrStart &&
3269cdf0e10cSrcweir 								( nAttrStart == *pEndIdx || !nBegin ))) )
3270cdf0e10cSrcweir 				{
3271cdf0e10cSrcweir                     const SfxPoolItem* pItem = CharFmt::GetItem( *pHt, nWhichId );
3272cdf0e10cSrcweir                     sal_uInt16 nLng = ((SvxLanguageItem*)pItem)->GetLanguage();
3273cdf0e10cSrcweir 
3274cdf0e10cSrcweir 					// Umfasst das Attribut den Bereich komplett?
3275cdf0e10cSrcweir 					if( nAttrStart <= nBegin && nEnd <= *pEndIdx )
3276cdf0e10cSrcweir 						nRet = nLng;
3277cdf0e10cSrcweir 					else if( LANGUAGE_DONTKNOW == nRet )
3278cdf0e10cSrcweir 						nRet = nLng; // partielle Ueberlappung, der 1. gewinnt
3279cdf0e10cSrcweir 				}
3280cdf0e10cSrcweir 			}
3281cdf0e10cSrcweir 		}
3282cdf0e10cSrcweir 	}
3283cdf0e10cSrcweir 	if( LANGUAGE_DONTKNOW == nRet )
3284cdf0e10cSrcweir 	{
3285cdf0e10cSrcweir 		nRet = ((SvxLanguageItem&)GetSwAttrSet().Get( nWhichId )).GetLanguage();
3286cdf0e10cSrcweir 		if( LANGUAGE_DONTKNOW == nRet )
3287cdf0e10cSrcweir             nRet = static_cast<sal_uInt16>(GetAppLanguage());
3288cdf0e10cSrcweir 	}
3289cdf0e10cSrcweir 	return nRet;
3290cdf0e10cSrcweir }
3291cdf0e10cSrcweir 
3292cdf0e10cSrcweir 
GetCharOfTxtAttr(const SwTxtAttr & rAttr)3293cdf0e10cSrcweir sal_Unicode GetCharOfTxtAttr( const SwTxtAttr& rAttr )
3294cdf0e10cSrcweir {
3295cdf0e10cSrcweir     sal_Unicode cRet = CH_TXTATR_BREAKWORD;
3296cdf0e10cSrcweir     switch ( rAttr.Which() )
3297cdf0e10cSrcweir     {
3298cdf0e10cSrcweir         case RES_TXTATR_FTN:
3299cdf0e10cSrcweir         case RES_TXTATR_REFMARK:
3300cdf0e10cSrcweir         case RES_TXTATR_TOXMARK:
3301cdf0e10cSrcweir         case RES_TXTATR_META:
3302cdf0e10cSrcweir         case RES_TXTATR_METAFIELD:
3303dec99bbdSOliver-Rainer Wittmann         case RES_TXTATR_ANNOTATION:
3304cdf0e10cSrcweir             cRet = CH_TXTATR_INWORD;
3305cdf0e10cSrcweir         break;
3306cdf0e10cSrcweir 
3307cdf0e10cSrcweir         case RES_TXTATR_FIELD:
3308cdf0e10cSrcweir         case RES_TXTATR_FLYCNT:
3309cdf0e10cSrcweir         {
3310cdf0e10cSrcweir             cRet = CH_TXTATR_BREAKWORD;
3311cdf0e10cSrcweir         }
3312cdf0e10cSrcweir         break;
3313cdf0e10cSrcweir 
3314cdf0e10cSrcweir         default:
3315cdf0e10cSrcweir             ASSERT(false, "GetCharOfTxtAttr: unknown attr");
3316cdf0e10cSrcweir             break;
3317cdf0e10cSrcweir     }
3318cdf0e10cSrcweir     return cRet;
3319cdf0e10cSrcweir }
3320cdf0e10cSrcweir 
3321cdf0e10cSrcweir 
3322