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