xref: /trunk/main/sw/source/core/crsr/findattr.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
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
10cdf0e10cSrcweir  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
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 <com/sun/star/lang/Locale.hpp>
29cdf0e10cSrcweir #include <com/sun/star/util/SearchOptions.hpp>
30cdf0e10cSrcweir #include <com/sun/star/util/SearchFlags.hpp>
31cdf0e10cSrcweir #include <i18npool/mslangid.hxx>
32cdf0e10cSrcweir #include <hintids.hxx>
33cdf0e10cSrcweir #include <vcl/svapp.hxx>
34cdf0e10cSrcweir #include <svl/itemiter.hxx>
35cdf0e10cSrcweir #include <svl/whiter.hxx>
36cdf0e10cSrcweir #include <editeng/brkitem.hxx>
37cdf0e10cSrcweir #include <editeng/colritem.hxx>
38cdf0e10cSrcweir #include <editeng/fontitem.hxx>
39cdf0e10cSrcweir #include <fmtpdsc.hxx>
40cdf0e10cSrcweir #include <txatbase.hxx>
41cdf0e10cSrcweir #include <fchrfmt.hxx>
42cdf0e10cSrcweir #include <charfmt.hxx>
43cdf0e10cSrcweir #include <doc.hxx>
44cdf0e10cSrcweir #include <IDocumentUndoRedo.hxx>
45cdf0e10cSrcweir #include <swcrsr.hxx>
46cdf0e10cSrcweir #include <editsh.hxx>
47cdf0e10cSrcweir #include <ndtxt.hxx>
48cdf0e10cSrcweir #include <pamtyp.hxx>
49cdf0e10cSrcweir #include <swundo.hxx>
50cdf0e10cSrcweir #include <crsskip.hxx>
51cdf0e10cSrcweir 
52cdf0e10cSrcweir 
53cdf0e10cSrcweir using namespace ::com::sun::star;
54cdf0e10cSrcweir using namespace ::com::sun::star::lang;
55cdf0e10cSrcweir using namespace ::com::sun::star::util;
56cdf0e10cSrcweir 
57cdf0e10cSrcweir SV_DECL_PTRARR_SORT( SwpFmts, SwFmt*, 0, 4 )
SV_IMPL_PTRARR_SORT(SwpFmts,SwFmt *)58cdf0e10cSrcweir SV_IMPL_PTRARR_SORT( SwpFmts, SwFmt* )
59cdf0e10cSrcweir 
60cdf0e10cSrcweir     // Sonderbehandlung fuer SvxFontItem, nur den Namen vergleichen:
61cdf0e10cSrcweir int CmpAttr( const SfxPoolItem& rItem1, const SfxPoolItem& rItem2 )
62cdf0e10cSrcweir {
63cdf0e10cSrcweir     switch( rItem1.Which() )
64cdf0e10cSrcweir     {
65cdf0e10cSrcweir     case RES_CHRATR_FONT:
66cdf0e10cSrcweir         return ((SvxFontItem&)rItem1).GetFamilyName() ==
67cdf0e10cSrcweir                 ((SvxFontItem&)rItem2).GetFamilyName();
68cdf0e10cSrcweir 
69cdf0e10cSrcweir     case RES_CHRATR_COLOR:
70cdf0e10cSrcweir         return ((SvxColorItem&)rItem1).GetValue().IsRGBEqual(
71cdf0e10cSrcweir                                 ((SvxColorItem&)rItem2).GetValue() );
72cdf0e10cSrcweir     case RES_PAGEDESC:
73cdf0e10cSrcweir         return ((SwFmtPageDesc&)rItem1).GetNumOffset() ==
74cdf0e10cSrcweir                         ((SwFmtPageDesc&)rItem2).GetNumOffset() &&
75cdf0e10cSrcweir                 ((SwFmtPageDesc&)rItem1).GetPageDesc() ==
76cdf0e10cSrcweir                         ((SwFmtPageDesc&)rItem2).GetPageDesc();
77cdf0e10cSrcweir     }
78cdf0e10cSrcweir     return rItem1 == rItem2;
79cdf0e10cSrcweir }
80cdf0e10cSrcweir 
81cdf0e10cSrcweir 
GetFrwrdTxtHint(const SwpHints & rHtsArr,sal_uInt16 & rPos,xub_StrLen nCntntPos)82cdf0e10cSrcweir const SwTxtAttr* GetFrwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
83cdf0e10cSrcweir                                     xub_StrLen nCntntPos )
84cdf0e10cSrcweir {
85cdf0e10cSrcweir     while( rPos < rHtsArr.Count() )
86cdf0e10cSrcweir     {
87cdf0e10cSrcweir         const SwTxtAttr *pTxtHt = rHtsArr.GetStart( rPos++ );
88cdf0e10cSrcweir         // der Start vom Attribut muss innerhalb des Bereiches liegen !!
89cdf0e10cSrcweir         if( *pTxtHt->GetStart() >= nCntntPos )
90cdf0e10cSrcweir             return pTxtHt;      // gueltiges TextAttribut
91cdf0e10cSrcweir     }
92cdf0e10cSrcweir     return 0;                   // kein gueltiges TextAttribut
93cdf0e10cSrcweir }
94cdf0e10cSrcweir 
95cdf0e10cSrcweir 
GetBkwrdTxtHint(const SwpHints & rHtsArr,sal_uInt16 & rPos,xub_StrLen nCntntPos)96cdf0e10cSrcweir const SwTxtAttr* GetBkwrdTxtHint( const SwpHints& rHtsArr, sal_uInt16& rPos,
97cdf0e10cSrcweir                                   xub_StrLen nCntntPos )
98cdf0e10cSrcweir {
99cdf0e10cSrcweir     while( rPos > 0 )
100cdf0e10cSrcweir     {
101cdf0e10cSrcweir         //Hack mit cast fuer das Update
102cdf0e10cSrcweir         const SwTxtAttr *pTxtHt = rHtsArr.GetStart( --rPos );
103cdf0e10cSrcweir         // der Start vom Attribut muss innerhalb des Bereiches liegen !!
104cdf0e10cSrcweir         if( *pTxtHt->GetStart() < nCntntPos )
105cdf0e10cSrcweir             return pTxtHt;      // gueltiges TextAttribut
106cdf0e10cSrcweir     }
107cdf0e10cSrcweir     return 0;                   // kein gueltiges TextAttribut
108cdf0e10cSrcweir }
109cdf0e10cSrcweir 
110cdf0e10cSrcweir 
lcl_SetAttrPam(SwPaM & rPam,xub_StrLen nStart,const xub_StrLen * pEnde,const sal_Bool bSaveMark)111cdf0e10cSrcweir void lcl_SetAttrPam( SwPaM & rPam, xub_StrLen nStart, const xub_StrLen* pEnde,
112cdf0e10cSrcweir                         const sal_Bool bSaveMark )
113cdf0e10cSrcweir {
114cdf0e10cSrcweir     xub_StrLen nCntntPos;
115cdf0e10cSrcweir     if( bSaveMark )
116cdf0e10cSrcweir         nCntntPos = rPam.GetMark()->nContent.GetIndex();
117cdf0e10cSrcweir     else
118cdf0e10cSrcweir         nCntntPos = rPam.GetPoint()->nContent.GetIndex();
119cdf0e10cSrcweir     sal_Bool bTstEnde = rPam.GetPoint()->nNode == rPam.GetMark()->nNode;
120cdf0e10cSrcweir 
121cdf0e10cSrcweir     SwCntntNode* pCNd = rPam.GetCntntNode();
122cdf0e10cSrcweir     rPam.GetPoint()->nContent.Assign( pCNd, nStart );
123cdf0e10cSrcweir     rPam.SetMark();     // Point == GetMark
124cdf0e10cSrcweir 
125cdf0e10cSrcweir     // Point zeigt auf das Ende vom SuchBereich oder Ende vom Attribut
126cdf0e10cSrcweir     if( pEnde )
127cdf0e10cSrcweir     {
128cdf0e10cSrcweir         if( bTstEnde && *pEnde > nCntntPos )
129cdf0e10cSrcweir             rPam.GetPoint()->nContent = nCntntPos;
130cdf0e10cSrcweir         else
131cdf0e10cSrcweir             rPam.GetPoint()->nContent = *pEnde;
132cdf0e10cSrcweir     }
133cdf0e10cSrcweir }
134cdf0e10cSrcweir 
135cdf0e10cSrcweir //------------------ Suche nach einem Text Attribut -----------------------
136cdf0e10cSrcweir 
137cdf0e10cSrcweir // diese Funktion sucht in einem TextNode nach dem vorgegebenen Attribut.
138cdf0e10cSrcweir // Wird es gefunden, dann hat der SwPaM den Bereich der das Attribut
139cdf0e10cSrcweir // umspannt, unter Beachtung des Suchbereiches
140cdf0e10cSrcweir 
141cdf0e10cSrcweir 
lcl_Search(const SwTxtNode & rTxtNd,SwPaM & rPam,const SfxPoolItem & rCmpItem,SwMoveFn fnMove,sal_Bool bValue)142cdf0e10cSrcweir sal_Bool lcl_Search( const SwTxtNode& rTxtNd, SwPaM& rPam,
143cdf0e10cSrcweir                     const SfxPoolItem& rCmpItem,
144cdf0e10cSrcweir                     SwMoveFn fnMove, sal_Bool bValue )
145cdf0e10cSrcweir {
146cdf0e10cSrcweir     if ( !rTxtNd.HasHints() )
147cdf0e10cSrcweir         return sal_False;
148cdf0e10cSrcweir     const SwTxtAttr *pTxtHt = 0;
149cdf0e10cSrcweir     sal_Bool bForward = fnMove == fnMoveForward;
150cdf0e10cSrcweir     sal_uInt16 nPos = bForward ? 0 : rTxtNd.GetSwpHints().Count();
151cdf0e10cSrcweir     xub_StrLen nCntntPos = rPam.GetPoint()->nContent.GetIndex();
152cdf0e10cSrcweir 
153cdf0e10cSrcweir     while( 0 != ( pTxtHt=(*fnMove->fnGetHint)(rTxtNd.GetSwpHints(),nPos,nCntntPos)))
154cdf0e10cSrcweir         if( pTxtHt->Which() == rCmpItem.Which() &&
155cdf0e10cSrcweir             ( !bValue || CmpAttr( pTxtHt->GetAttr(), rCmpItem )))
156cdf0e10cSrcweir         {
15769a74367SOliver-Rainer Wittmann             lcl_SetAttrPam( rPam, *pTxtHt->GetStart(), pTxtHt->End(), bForward );
158cdf0e10cSrcweir             return sal_True;
159cdf0e10cSrcweir         }
160cdf0e10cSrcweir     return sal_False;
161cdf0e10cSrcweir }
162cdf0e10cSrcweir 
163cdf0e10cSrcweir 
164cdf0e10cSrcweir //------------------ Suche nach mehren Text Attributen -------------------
165cdf0e10cSrcweir 
166cdf0e10cSrcweir struct _SwSrchChrAttr
167cdf0e10cSrcweir {
168cdf0e10cSrcweir     sal_uInt16 nWhich;
169cdf0e10cSrcweir     xub_StrLen nStt, nEnd;
170cdf0e10cSrcweir 
_SwSrchChrAttr_SwSrchChrAttr171cdf0e10cSrcweir     _SwSrchChrAttr( const SfxPoolItem& rItem,
172cdf0e10cSrcweir                     xub_StrLen nStart, xub_StrLen nAnyEnd )
173cdf0e10cSrcweir         : nWhich( rItem.Which() ), nStt( nStart ), nEnd( nAnyEnd )
174cdf0e10cSrcweir     {}
175cdf0e10cSrcweir };
176cdf0e10cSrcweir 
177cdf0e10cSrcweir class SwAttrCheckArr
178cdf0e10cSrcweir {
179cdf0e10cSrcweir     _SwSrchChrAttr *pFndArr, *pStackArr;
180cdf0e10cSrcweir     xub_StrLen nNdStt, nNdEnd;
181cdf0e10cSrcweir     sal_uInt16 nArrStart, nArrLen;
182cdf0e10cSrcweir     sal_uInt16 nFound, nStackCnt;
183cdf0e10cSrcweir     SfxItemSet aCmpSet;
184cdf0e10cSrcweir     sal_Bool bNoColls;
185cdf0e10cSrcweir     sal_Bool bForward;
186cdf0e10cSrcweir 
187cdf0e10cSrcweir public:
188cdf0e10cSrcweir     SwAttrCheckArr( const SfxItemSet& rSet, int bForward, int bNoCollections );
189cdf0e10cSrcweir     ~SwAttrCheckArr();
190cdf0e10cSrcweir 
191cdf0e10cSrcweir     void SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam );
192cdf0e10cSrcweir 
193cdf0e10cSrcweir     // wieviele Attribute ueberhaupt ??
Count() const194cdf0e10cSrcweir     sal_uInt16 Count() const    { return aCmpSet.Count(); }
Found() const195cdf0e10cSrcweir     int Found() const       { return nFound == aCmpSet.Count(); }
196cdf0e10cSrcweir     int CheckStack();
197cdf0e10cSrcweir 
198cdf0e10cSrcweir     xub_StrLen Start() const;
199cdf0e10cSrcweir     xub_StrLen End() const;
200cdf0e10cSrcweir 
GetNdStt() const201cdf0e10cSrcweir     xub_StrLen GetNdStt() const { return nNdStt; }
GetNdEnd() const202cdf0e10cSrcweir     xub_StrLen GetNdEnd() const { return nNdEnd; }
203cdf0e10cSrcweir 
204cdf0e10cSrcweir     int SetAttrFwd( const SwTxtAttr& rAttr );
205cdf0e10cSrcweir     int SetAttrBwd( const SwTxtAttr& rAttr );
206cdf0e10cSrcweir };
207cdf0e10cSrcweir 
208cdf0e10cSrcweir 
209cdf0e10cSrcweir 
SwAttrCheckArr(const SfxItemSet & rSet,int bFwd,int bNoCollections)210cdf0e10cSrcweir SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, int bFwd,
211cdf0e10cSrcweir                                 int bNoCollections )
212cdf0e10cSrcweir     : aCmpSet( *rSet.GetPool(), RES_CHRATR_BEGIN, RES_TXTATR_END-1 )
213cdf0e10cSrcweir {
214cdf0e10cSrcweir     aCmpSet.Put( rSet, sal_False );
215cdf0e10cSrcweir     bNoColls = 0 != bNoCollections;
216cdf0e10cSrcweir 
217cdf0e10cSrcweir     bForward = 0 != bFwd;
218cdf0e10cSrcweir 
219cdf0e10cSrcweir     // Bestimmen den Bereich des Fnd/Stack-Arrays (Min/Max)
220cdf0e10cSrcweir     SfxItemIter aIter( aCmpSet );
221cdf0e10cSrcweir     nArrStart = aCmpSet.GetWhichByPos( aIter.GetFirstPos() );
222cdf0e10cSrcweir     nArrLen = aCmpSet.GetWhichByPos( aIter.GetLastPos() ) - nArrStart+1;
223cdf0e10cSrcweir 
224cdf0e10cSrcweir     char* pFndChar  = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
225cdf0e10cSrcweir     char* pStackChar = new char[ nArrLen * sizeof(_SwSrchChrAttr) ];
226cdf0e10cSrcweir 
227cdf0e10cSrcweir     pFndArr = (_SwSrchChrAttr*)pFndChar;
228cdf0e10cSrcweir     pStackArr = (_SwSrchChrAttr*)pStackChar;
229cdf0e10cSrcweir }
230cdf0e10cSrcweir 
~SwAttrCheckArr()231cdf0e10cSrcweir SwAttrCheckArr::~SwAttrCheckArr()
232cdf0e10cSrcweir {
233cdf0e10cSrcweir     delete[] (char*)pFndArr;
234cdf0e10cSrcweir     delete[] (char*)pStackArr;
235cdf0e10cSrcweir }
236cdf0e10cSrcweir 
SetNewSet(const SwTxtNode & rTxtNd,const SwPaM & rPam)237cdf0e10cSrcweir void SwAttrCheckArr::SetNewSet( const SwTxtNode& rTxtNd, const SwPaM& rPam )
238cdf0e10cSrcweir {
239cdf0e10cSrcweir     memset( pFndArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
240cdf0e10cSrcweir     memset( pStackArr, 0, nArrLen * sizeof(_SwSrchChrAttr) );
241cdf0e10cSrcweir     nFound = 0;
242cdf0e10cSrcweir     nStackCnt = 0;
243cdf0e10cSrcweir 
244cdf0e10cSrcweir     if( bForward )
245cdf0e10cSrcweir     {
246cdf0e10cSrcweir         nNdStt = rPam.GetPoint()->nContent.GetIndex();
247cdf0e10cSrcweir         nNdEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
248cdf0e10cSrcweir                 ? rPam.GetMark()->nContent.GetIndex()
249cdf0e10cSrcweir                 : rTxtNd.GetTxt().Len();
250cdf0e10cSrcweir     }
251cdf0e10cSrcweir     else
252cdf0e10cSrcweir     {
253cdf0e10cSrcweir         nNdEnd = rPam.GetPoint()->nContent.GetIndex();
254cdf0e10cSrcweir         nNdStt = rPam.GetPoint()->nNode == rPam.GetMark()->nNode
255cdf0e10cSrcweir                 ? rPam.GetMark()->nContent.GetIndex()
256cdf0e10cSrcweir                 : 0;
257cdf0e10cSrcweir     }
258cdf0e10cSrcweir 
259cdf0e10cSrcweir     if( bNoColls && !rTxtNd.HasSwAttrSet() )
260cdf0e10cSrcweir         return ;
261cdf0e10cSrcweir 
262cdf0e10cSrcweir     const SfxItemSet& rSet = rTxtNd.GetSwAttrSet();
263cdf0e10cSrcweir //  if( !rSet.Count() )
264cdf0e10cSrcweir //      return;
265cdf0e10cSrcweir 
266cdf0e10cSrcweir     SfxItemIter aIter( aCmpSet );
267cdf0e10cSrcweir     const SfxPoolItem* pItem = aIter.GetCurItem();
268cdf0e10cSrcweir     const SfxPoolItem* pFndItem;
269cdf0e10cSrcweir     sal_uInt16 nWhich;
270cdf0e10cSrcweir 
271cdf0e10cSrcweir     while( sal_True )
272cdf0e10cSrcweir     {
273cdf0e10cSrcweir         // nur testen, ob vorhanden ist ?
274cdf0e10cSrcweir         if( IsInvalidItem( pItem ) )
275cdf0e10cSrcweir         {
276cdf0e10cSrcweir             nWhich = aCmpSet.GetWhichByPos( aIter.GetCurPos() );
277cdf0e10cSrcweir             if( RES_TXTATR_END <= nWhich )
278cdf0e10cSrcweir                 break;              // Ende der TextAttribute
279cdf0e10cSrcweir 
280cdf0e10cSrcweir             if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
281cdf0e10cSrcweir                 && !CmpAttr( *pFndItem, rSet.GetPool()->GetDefaultItem( nWhich ) ))
282cdf0e10cSrcweir             {
283cdf0e10cSrcweir                 pFndArr[ nWhich - nArrStart ] =
284cdf0e10cSrcweir                     _SwSrchChrAttr( *pFndItem, nNdStt, nNdEnd );
285cdf0e10cSrcweir                 nFound++;
286cdf0e10cSrcweir             }
287cdf0e10cSrcweir         }
288cdf0e10cSrcweir         else
289cdf0e10cSrcweir         {
290cdf0e10cSrcweir             if( RES_TXTATR_END <= (nWhich = pItem->Which() ))
291cdf0e10cSrcweir                 break;              // Ende der TextAttribute
292cdf0e10cSrcweir 
293cdf0e10cSrcweir //JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
294cdf0e10cSrcweir //              runter
295cdf0e10cSrcweir //          if( SFX_ITEM_SET == rSet.GetItemState( nWhich, !bNoColls, &pFndItem )
296cdf0e10cSrcweir //                && *pFndItem == *pItem )
297cdf0e10cSrcweir             if( CmpAttr( rSet.Get( nWhich, !bNoColls ), *pItem ) )
298cdf0e10cSrcweir             {
299cdf0e10cSrcweir                 pFndArr[ nWhich - nArrStart ] =
300cdf0e10cSrcweir                     _SwSrchChrAttr( *pItem, nNdStt, nNdEnd );
301cdf0e10cSrcweir                 nFound++;
302cdf0e10cSrcweir             }
303cdf0e10cSrcweir         }
304cdf0e10cSrcweir 
305cdf0e10cSrcweir         if( aIter.IsAtEnd() )
306cdf0e10cSrcweir             break;
307cdf0e10cSrcweir         pItem = aIter.NextItem();
308cdf0e10cSrcweir     }
309cdf0e10cSrcweir }
310cdf0e10cSrcweir 
311cdf0e10cSrcweir static bool
lcl_IsAttributeIgnorable(xub_StrLen const nNdStart,xub_StrLen const nNdEnd,_SwSrchChrAttr const & rTmp)312cdf0e10cSrcweir lcl_IsAttributeIgnorable(xub_StrLen const nNdStart, xub_StrLen const nNdEnd,
313cdf0e10cSrcweir         _SwSrchChrAttr const& rTmp)
314cdf0e10cSrcweir {
315cdf0e10cSrcweir     // #i115528#: if there is a paragraph attribute, it has been added by the
316cdf0e10cSrcweir     // SwAttrCheckArr ctor, and nFound is 1.
317cdf0e10cSrcweir     // if the paragraph is entirely covered by hints that override the paragraph
318cdf0e10cSrcweir     // attribute, then this function must find an attribute to decrement nFound!
319cdf0e10cSrcweir     // so check for an empty search range, let attributes that start/end there
320cdf0e10cSrcweir     // cover it, and hope for the best...
321cdf0e10cSrcweir     return ((nNdEnd == nNdStart)
322cdf0e10cSrcweir             ? ((rTmp.nEnd <  nNdStart) || (nNdEnd <  rTmp.nStt))
323cdf0e10cSrcweir             : ((rTmp.nEnd <= nNdStart) || (nNdEnd <= rTmp.nStt)));
324cdf0e10cSrcweir }
325cdf0e10cSrcweir 
SetAttrFwd(const SwTxtAttr & rAttr)326cdf0e10cSrcweir int SwAttrCheckArr::SetAttrFwd( const SwTxtAttr& rAttr )
327cdf0e10cSrcweir {
328cdf0e10cSrcweir     _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
329cdf0e10cSrcweir 
330cdf0e10cSrcweir     // ignore all attributes not in search range
331cdf0e10cSrcweir     if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
332cdf0e10cSrcweir     {
333cdf0e10cSrcweir         return Found();
334cdf0e10cSrcweir     }
335cdf0e10cSrcweir 
336cdf0e10cSrcweir     const SfxPoolItem* pItem;
337cdf0e10cSrcweir // --------------------------------------------------------------
338cdf0e10cSrcweir // Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
339cdf0e10cSrcweir // --------------------------------------------------------------
340cdf0e10cSrcweir     sal_uInt16 nWhch = rAttr.Which();
341cdf0e10cSrcweir     SfxWhichIter* pIter = NULL;
342cdf0e10cSrcweir     const SfxPoolItem* pTmpItem = NULL;
343cdf0e10cSrcweir     const SfxItemSet* pSet = NULL;
344cdf0e10cSrcweir     if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
345cdf0e10cSrcweir     {
346cdf0e10cSrcweir         if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
347cdf0e10cSrcweir             return Found();
348cdf0e10cSrcweir         pTmpItem = NULL;
349cdf0e10cSrcweir         pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
350cdf0e10cSrcweir         if ( pSet )
351cdf0e10cSrcweir         {
352cdf0e10cSrcweir             pIter = new SfxWhichIter( *pSet );
353cdf0e10cSrcweir             nWhch = pIter->FirstWhich();
354cdf0e10cSrcweir             while( nWhch &&
355cdf0e10cSrcweir                 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
356cdf0e10cSrcweir                 nWhch = pIter->NextWhich();
357cdf0e10cSrcweir             if( !nWhch )
358cdf0e10cSrcweir                 pTmpItem = NULL;
359cdf0e10cSrcweir         }
360cdf0e10cSrcweir     }
361cdf0e10cSrcweir     else
362cdf0e10cSrcweir         pTmpItem = &rAttr.GetAttr();
363cdf0e10cSrcweir     while( pTmpItem )
364cdf0e10cSrcweir     {
365cdf0e10cSrcweir         SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
366cdf0e10cSrcweir         if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
367cdf0e10cSrcweir         {
368cdf0e10cSrcweir             sal_uInt16 n;
369cdf0e10cSrcweir             _SwSrchChrAttr* pCmp;
370cdf0e10cSrcweir 
371cdf0e10cSrcweir             // loesche erstmal alle, die bis zu der Start Position schon wieder
372cdf0e10cSrcweir             // ungueltig sind:
373cdf0e10cSrcweir 
374cdf0e10cSrcweir             _SwSrchChrAttr* pArrPtr;
375cdf0e10cSrcweir             if( nFound )
376cdf0e10cSrcweir                 for( pArrPtr = pFndArr, n = 0; n < nArrLen;
377cdf0e10cSrcweir                     ++n, ++pArrPtr )
378cdf0e10cSrcweir                     if( pArrPtr->nWhich && pArrPtr->nEnd <= aTmp.nStt )
379cdf0e10cSrcweir                     {
380cdf0e10cSrcweir                         pArrPtr->nWhich = 0;        // geloescht
381cdf0e10cSrcweir                         nFound--;
382cdf0e10cSrcweir                     }
383cdf0e10cSrcweir 
384cdf0e10cSrcweir             // loesche erstmal alle, die bis zu der Start Position schon wieder
385cdf0e10cSrcweir             // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
386cdf0e10cSrcweir             // die Start Position ragen, vom Stack in den FndSet
387cdf0e10cSrcweir 
388cdf0e10cSrcweir             if( nStackCnt )
389cdf0e10cSrcweir                 for( pArrPtr = pStackArr, n=0; n < nArrLen; ++n, ++pArrPtr )
390cdf0e10cSrcweir                 {
391cdf0e10cSrcweir                     if( !pArrPtr->nWhich )
392cdf0e10cSrcweir                         continue;
393cdf0e10cSrcweir 
394cdf0e10cSrcweir                     if( pArrPtr->nEnd <= aTmp.nStt )
395cdf0e10cSrcweir                     {
396cdf0e10cSrcweir                         pArrPtr->nWhich = 0;        // geloescht
397cdf0e10cSrcweir                         if( !--nStackCnt )
398cdf0e10cSrcweir                             break;
399cdf0e10cSrcweir                     }
400cdf0e10cSrcweir                     else if( pArrPtr->nStt <= aTmp.nStt )
401cdf0e10cSrcweir                     {
402cdf0e10cSrcweir                         if( ( pCmp = &pFndArr[ n ])->nWhich )
403cdf0e10cSrcweir                         {
404cdf0e10cSrcweir                             if( pCmp->nEnd < pArrPtr->nEnd )        // erweitern
405cdf0e10cSrcweir                                 pCmp->nEnd = pArrPtr->nEnd;
406cdf0e10cSrcweir                         }
407cdf0e10cSrcweir                         else
408cdf0e10cSrcweir                         {
409cdf0e10cSrcweir                             *pCmp = *pArrPtr;
410cdf0e10cSrcweir                             nFound++;
411cdf0e10cSrcweir                         }
412cdf0e10cSrcweir                         pArrPtr->nWhich = 0;
413cdf0e10cSrcweir                         if( !--nStackCnt )
414cdf0e10cSrcweir                             break;
415cdf0e10cSrcweir                     }
416cdf0e10cSrcweir                 }
417cdf0e10cSrcweir 
418cdf0e10cSrcweir             sal_Bool bContinue = sal_False;
419cdf0e10cSrcweir 
420cdf0e10cSrcweir             if( SFX_ITEM_DONTCARE == eState  )
421cdf0e10cSrcweir             {
422cdf0e10cSrcweir                 // wird Attribut gueltig ?
423cdf0e10cSrcweir                 if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
424cdf0e10cSrcweir                     *pTmpItem ))
425cdf0e10cSrcweir                 {
426cdf0e10cSrcweir                     // suche das Attribut und erweiter es gegebenenfalls
427cdf0e10cSrcweir                     if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
428cdf0e10cSrcweir                     {
429cdf0e10cSrcweir                         *pCmp = aTmp;               // nicht gefunden, eintragen
430cdf0e10cSrcweir                         nFound++;
431cdf0e10cSrcweir                     }
432cdf0e10cSrcweir                     else if( pCmp->nEnd < aTmp.nEnd )       // erweitern ?
433cdf0e10cSrcweir                         pCmp->nEnd = aTmp.nEnd;
434cdf0e10cSrcweir 
435cdf0e10cSrcweir                     bContinue = sal_True;
436cdf0e10cSrcweir                 }
437cdf0e10cSrcweir             }
438cdf0e10cSrcweir             // wird Attribut gueltig ?
439cdf0e10cSrcweir             else if(  CmpAttr( *pItem, *pTmpItem ) )
440cdf0e10cSrcweir             {
441cdf0e10cSrcweir                 pFndArr[ nWhch - nArrStart ] = aTmp;
442cdf0e10cSrcweir                 ++nFound;
443cdf0e10cSrcweir                 bContinue = sal_True;
444cdf0e10cSrcweir             }
445cdf0e10cSrcweir 
446cdf0e10cSrcweir             // tja, dann muss es auf den Stack
447cdf0e10cSrcweir             if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
448cdf0e10cSrcweir             {
449cdf0e10cSrcweir                 // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
450cdf0e10cSrcweir                 if( pCmp->nEnd > aTmp.nEnd )
451cdf0e10cSrcweir                 {
452cdf0e10cSrcweir                     ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich,
453cdf0e10cSrcweir                                     "Stack-Platz ist noch belegt" );
454cdf0e10cSrcweir 
455cdf0e10cSrcweir         // ---------
456cdf0e10cSrcweir         // JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547
457cdf0e10cSrcweir         //          pCmp->nStt = aTmp.nEnd;
458cdf0e10cSrcweir                     if( aTmp.nStt <= pCmp->nStt )
459cdf0e10cSrcweir                         pCmp->nStt = aTmp.nEnd;
460cdf0e10cSrcweir                     else
461cdf0e10cSrcweir                         pCmp->nEnd = aTmp.nStt;
462cdf0e10cSrcweir         // ---------
463cdf0e10cSrcweir 
464cdf0e10cSrcweir                     pStackArr[ nWhch - nArrStart ] = *pCmp;
465cdf0e10cSrcweir                     nStackCnt++;
466cdf0e10cSrcweir                 }
467cdf0e10cSrcweir                 pCmp->nWhich = 0;
468cdf0e10cSrcweir                 nFound--;
469cdf0e10cSrcweir             }
470cdf0e10cSrcweir         }
471cdf0e10cSrcweir         if( pIter )
472cdf0e10cSrcweir         {
473cdf0e10cSrcweir             nWhch = pIter->NextWhich();
474cdf0e10cSrcweir             while( nWhch &&
475cdf0e10cSrcweir                 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
476cdf0e10cSrcweir                 nWhch = pIter->NextWhich();
477cdf0e10cSrcweir             if( !nWhch )
478cdf0e10cSrcweir                 break;
479cdf0e10cSrcweir         }
480cdf0e10cSrcweir         else
481cdf0e10cSrcweir             break;
482cdf0e10cSrcweir     }
483*47d45a94SPedro Giffuni     delete pIter;
484cdf0e10cSrcweir     return Found();
485cdf0e10cSrcweir }
486cdf0e10cSrcweir 
487cdf0e10cSrcweir 
SetAttrBwd(const SwTxtAttr & rAttr)488cdf0e10cSrcweir int SwAttrCheckArr::SetAttrBwd( const SwTxtAttr& rAttr )
489cdf0e10cSrcweir {
490cdf0e10cSrcweir     _SwSrchChrAttr aTmp( rAttr.GetAttr(), *rAttr.GetStart(), *rAttr.GetAnyEnd() );
491cdf0e10cSrcweir 
492cdf0e10cSrcweir     // ignore all attributes not in search range
493cdf0e10cSrcweir     if (lcl_IsAttributeIgnorable(nNdStt, nNdEnd, aTmp))
494cdf0e10cSrcweir     {
495cdf0e10cSrcweir         return Found();
496cdf0e10cSrcweir     }
497cdf0e10cSrcweir 
498cdf0e10cSrcweir     const SfxPoolItem* pItem;
499cdf0e10cSrcweir // --------------------------------------------------------------
500cdf0e10cSrcweir // Hier wird jetzt ausdruecklich auch in Zeichenvorlagen gesucht
501cdf0e10cSrcweir // --------------------------------------------------------------
502cdf0e10cSrcweir     sal_uInt16 nWhch = rAttr.Which();
503cdf0e10cSrcweir     SfxWhichIter* pIter = NULL;
504cdf0e10cSrcweir     const SfxPoolItem* pTmpItem = NULL;
505cdf0e10cSrcweir     const SfxItemSet* pSet = NULL;
506cdf0e10cSrcweir     if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch )
507cdf0e10cSrcweir     {
508cdf0e10cSrcweir         if( bNoColls && RES_TXTATR_CHARFMT == nWhch )
509cdf0e10cSrcweir             return Found();
510cdf0e10cSrcweir 
511cdf0e10cSrcweir         pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
512cdf0e10cSrcweir         if ( pSet )
513cdf0e10cSrcweir         {
514cdf0e10cSrcweir             pIter = new SfxWhichIter( *pSet );
515cdf0e10cSrcweir             nWhch = pIter->FirstWhich();
516cdf0e10cSrcweir             while( nWhch &&
517cdf0e10cSrcweir                 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
518cdf0e10cSrcweir                 nWhch = pIter->NextWhich();
519cdf0e10cSrcweir             if( !nWhch )
520cdf0e10cSrcweir                 pTmpItem = NULL;
521cdf0e10cSrcweir         }
522cdf0e10cSrcweir     }
523cdf0e10cSrcweir     else
524cdf0e10cSrcweir         pTmpItem = &rAttr.GetAttr();
525cdf0e10cSrcweir     while( pTmpItem )
526cdf0e10cSrcweir     {
527cdf0e10cSrcweir         SfxItemState eState = aCmpSet.GetItemState( nWhch, sal_False, &pItem );
528cdf0e10cSrcweir         if( SFX_ITEM_DONTCARE == eState || SFX_ITEM_SET == eState )
529cdf0e10cSrcweir         {
530cdf0e10cSrcweir             sal_uInt16 n;
531cdf0e10cSrcweir             _SwSrchChrAttr* pCmp;
532cdf0e10cSrcweir 
533cdf0e10cSrcweir             // loesche erstmal alle, die bis zu der Start Position schon wieder
534cdf0e10cSrcweir             // ungueltig sind:
535cdf0e10cSrcweir 
536cdf0e10cSrcweir             _SwSrchChrAttr* pArrPtr;
537cdf0e10cSrcweir             if( nFound )
538cdf0e10cSrcweir                 for( pArrPtr = pFndArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
539cdf0e10cSrcweir                     if( pArrPtr->nWhich && pArrPtr->nStt >= aTmp.nEnd )
540cdf0e10cSrcweir                     {
541cdf0e10cSrcweir                         pArrPtr->nWhich = 0;        // geloescht
542cdf0e10cSrcweir                         nFound--;
543cdf0e10cSrcweir                     }
544cdf0e10cSrcweir 
545cdf0e10cSrcweir             // loesche erstmal alle, die bis zu der Start Position schon wieder
546cdf0e10cSrcweir             // ungueltig sind. Und verschiebe alle die "offen" sind, heisst ueber
547cdf0e10cSrcweir             // die Start Position ragen, vom Stack in den FndSet
548cdf0e10cSrcweir 
549cdf0e10cSrcweir             if( nStackCnt )
550cdf0e10cSrcweir                 for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
551cdf0e10cSrcweir                 {
552cdf0e10cSrcweir                     if( !pArrPtr->nWhich )
553cdf0e10cSrcweir                         continue;
554cdf0e10cSrcweir 
555cdf0e10cSrcweir                     if( pArrPtr->nStt >= aTmp.nEnd )
556cdf0e10cSrcweir                     {
557cdf0e10cSrcweir                         pArrPtr->nWhich = 0;        // geloescht
558cdf0e10cSrcweir                         if( !--nStackCnt )
559cdf0e10cSrcweir                             break;
560cdf0e10cSrcweir                     }
561cdf0e10cSrcweir                     else if( pArrPtr->nEnd >= aTmp.nEnd )
562cdf0e10cSrcweir                     {
563cdf0e10cSrcweir                         if( ( pCmp = &pFndArr[ n ])->nWhich )
564cdf0e10cSrcweir                         {
565cdf0e10cSrcweir                             if( pCmp->nStt > pArrPtr->nStt )        // erweitern
566cdf0e10cSrcweir                                 pCmp->nStt = pArrPtr->nStt;
567cdf0e10cSrcweir                         }
568cdf0e10cSrcweir                         else
569cdf0e10cSrcweir                         {
570cdf0e10cSrcweir                             *pCmp = *pArrPtr;
571cdf0e10cSrcweir                             nFound++;
572cdf0e10cSrcweir                     }
573cdf0e10cSrcweir                     pArrPtr->nWhich = 0;
574cdf0e10cSrcweir                     if( !--nStackCnt )
575cdf0e10cSrcweir                         break;
576cdf0e10cSrcweir                 }
577cdf0e10cSrcweir             }
578cdf0e10cSrcweir 
579cdf0e10cSrcweir             sal_Bool bContinue = sal_False;
580cdf0e10cSrcweir             if( SFX_ITEM_DONTCARE == eState  )
581cdf0e10cSrcweir             {
582cdf0e10cSrcweir                 // wird Attribut gueltig ?
583cdf0e10cSrcweir                 if( !CmpAttr( aCmpSet.GetPool()->GetDefaultItem( nWhch ),
584cdf0e10cSrcweir                     *pTmpItem ) )
585cdf0e10cSrcweir                 {
586cdf0e10cSrcweir                     // suche das Attribut und erweiter es gegebenenfalls
587cdf0e10cSrcweir                     if( !( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
588cdf0e10cSrcweir                     {
589cdf0e10cSrcweir                         *pCmp = aTmp;               // nicht gefunden, eintragen
590cdf0e10cSrcweir                         nFound++;
591cdf0e10cSrcweir                     }
592cdf0e10cSrcweir                     else if( pCmp->nStt > aTmp.nStt )       // erweitern ?
593cdf0e10cSrcweir                         pCmp->nStt = aTmp.nStt;
594cdf0e10cSrcweir 
595cdf0e10cSrcweir                     bContinue = sal_True;
596cdf0e10cSrcweir                 }
597cdf0e10cSrcweir             }
598cdf0e10cSrcweir             // wird Attribut gueltig ?
599cdf0e10cSrcweir             else if( CmpAttr( *pItem, *pTmpItem ))
600cdf0e10cSrcweir             {
601cdf0e10cSrcweir                 pFndArr[ nWhch - nArrStart ] = aTmp;
602cdf0e10cSrcweir                 ++nFound;
603cdf0e10cSrcweir                 bContinue = sal_True;
604cdf0e10cSrcweir             }
605cdf0e10cSrcweir 
606cdf0e10cSrcweir             // tja, dann muss es auf den Stack
607cdf0e10cSrcweir             if( !bContinue && ( pCmp = &pFndArr[ nWhch - nArrStart ])->nWhich )
608cdf0e10cSrcweir             {
609cdf0e10cSrcweir                 // vorhanden, auf den Stack. Aber nur wenn es noch grosser ist
610cdf0e10cSrcweir                 if( pCmp->nStt < aTmp.nStt )
611cdf0e10cSrcweir                 {
612cdf0e10cSrcweir                     ASSERT( !pStackArr[ nWhch - nArrStart ].nWhich,
613cdf0e10cSrcweir                             "Stack-Platz ist noch belegt" );
614cdf0e10cSrcweir 
615cdf0e10cSrcweir // ---------
616cdf0e10cSrcweir // JP 22.08.96: nur Ende manipulieren reicht nicht. Bug 30547
617cdf0e10cSrcweir //          pCmp->nEnd = aTmp.nStt;
618cdf0e10cSrcweir                     if( aTmp.nEnd <= pCmp->nEnd )
619cdf0e10cSrcweir                         pCmp->nEnd = aTmp.nStt;
620cdf0e10cSrcweir                     else
621cdf0e10cSrcweir                         pCmp->nStt = aTmp.nEnd;
622cdf0e10cSrcweir // ---------
623cdf0e10cSrcweir 
624cdf0e10cSrcweir                     pStackArr[ nWhch - nArrStart ] = *pCmp;
625cdf0e10cSrcweir                     nStackCnt++;
626cdf0e10cSrcweir                 }
627cdf0e10cSrcweir                 pCmp->nWhich = 0;
628cdf0e10cSrcweir                 nFound--;
629cdf0e10cSrcweir             }
630cdf0e10cSrcweir         }
631cdf0e10cSrcweir         if( pIter )
632cdf0e10cSrcweir         {
633cdf0e10cSrcweir             nWhch = pIter->NextWhich();
634cdf0e10cSrcweir             while( nWhch &&
635cdf0e10cSrcweir                 SFX_ITEM_SET != pSet->GetItemState( nWhch, sal_True, &pTmpItem ) )
636cdf0e10cSrcweir                 nWhch = pIter->NextWhich();
637cdf0e10cSrcweir             if( !nWhch )
638cdf0e10cSrcweir                 break;
639cdf0e10cSrcweir         }
640cdf0e10cSrcweir         else
641cdf0e10cSrcweir             break;
642cdf0e10cSrcweir     }
643*47d45a94SPedro Giffuni     delete pIter;
644cdf0e10cSrcweir     return Found();
645cdf0e10cSrcweir }
646cdf0e10cSrcweir 
647cdf0e10cSrcweir 
Start() const648cdf0e10cSrcweir xub_StrLen SwAttrCheckArr::Start() const
649cdf0e10cSrcweir {
650cdf0e10cSrcweir     xub_StrLen nStart = nNdStt;
651cdf0e10cSrcweir     _SwSrchChrAttr* pArrPtr = pFndArr;
652cdf0e10cSrcweir     for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
653cdf0e10cSrcweir         if( pArrPtr->nWhich && pArrPtr->nStt > nStart )
654cdf0e10cSrcweir             nStart = pArrPtr->nStt;
655cdf0e10cSrcweir 
656cdf0e10cSrcweir     return nStart;
657cdf0e10cSrcweir }
658cdf0e10cSrcweir 
659cdf0e10cSrcweir 
End() const660cdf0e10cSrcweir xub_StrLen SwAttrCheckArr::End() const
661cdf0e10cSrcweir {
662cdf0e10cSrcweir     _SwSrchChrAttr* pArrPtr = pFndArr;
663cdf0e10cSrcweir     xub_StrLen nEnd = nNdEnd;
664cdf0e10cSrcweir     for( sal_uInt16 n = 0; n < nArrLen; ++n, ++pArrPtr )
665cdf0e10cSrcweir         if( pArrPtr->nWhich && pArrPtr->nEnd < nEnd )
666cdf0e10cSrcweir             nEnd = pArrPtr->nEnd;
667cdf0e10cSrcweir 
668cdf0e10cSrcweir     return nEnd;
669cdf0e10cSrcweir }
670cdf0e10cSrcweir 
671cdf0e10cSrcweir 
CheckStack()672cdf0e10cSrcweir int SwAttrCheckArr::CheckStack()
673cdf0e10cSrcweir {
674cdf0e10cSrcweir     if( !nStackCnt )
675cdf0e10cSrcweir         return sal_False;
676cdf0e10cSrcweir 
677cdf0e10cSrcweir     sal_uInt16 n;
678cdf0e10cSrcweir     xub_StrLen nSttPos = Start(), nEndPos = End();
679cdf0e10cSrcweir     _SwSrchChrAttr* pArrPtr;
680cdf0e10cSrcweir     for( pArrPtr = pStackArr, n = 0; n < nArrLen; ++n, ++pArrPtr )
681cdf0e10cSrcweir     {
682cdf0e10cSrcweir         if( !pArrPtr->nWhich )
683cdf0e10cSrcweir             continue;
684cdf0e10cSrcweir 
685cdf0e10cSrcweir         if( bForward ? pArrPtr->nEnd <= nSttPos : pArrPtr->nStt >= nEndPos )
686cdf0e10cSrcweir         {
687cdf0e10cSrcweir             pArrPtr->nWhich = 0;        // geloescht
688cdf0e10cSrcweir             if( !--nStackCnt )
689cdf0e10cSrcweir                 return nFound == aCmpSet.Count();
690cdf0e10cSrcweir         }
691cdf0e10cSrcweir         else if( bForward ? pArrPtr->nStt < nEndPos : pArrPtr->nEnd > nSttPos )
692cdf0e10cSrcweir         {
693cdf0e10cSrcweir             // alle die "offen" sind, heisst ueber die Start Position ragen,
694cdf0e10cSrcweir             // im FndSet setzen
695cdf0e10cSrcweir             ASSERT( !pFndArr[ n ].nWhich, "Array-Platz ist noch belegt" );
696cdf0e10cSrcweir             pFndArr[ n ] = *pArrPtr;
697cdf0e10cSrcweir             pArrPtr->nWhich = 0;
698cdf0e10cSrcweir             nFound++;
699cdf0e10cSrcweir             if( !--nStackCnt )
700cdf0e10cSrcweir                 return nFound == aCmpSet.Count();
701cdf0e10cSrcweir         }
702cdf0e10cSrcweir     }
703cdf0e10cSrcweir     return nFound == aCmpSet.Count();
704cdf0e10cSrcweir }
705cdf0e10cSrcweir 
706cdf0e10cSrcweir 
707cdf0e10cSrcweir 
lcl_SearchForward(const SwTxtNode & rTxtNd,SwAttrCheckArr & rCmpArr,SwPaM & rPam)708cdf0e10cSrcweir int lcl_SearchForward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
709cdf0e10cSrcweir                             SwPaM& rPam )
710cdf0e10cSrcweir {
711cdf0e10cSrcweir     xub_StrLen nEndPos, nSttPos;
712cdf0e10cSrcweir     rCmpArr.SetNewSet( rTxtNd, rPam );
713cdf0e10cSrcweir     if( !rTxtNd.HasHints() )
714cdf0e10cSrcweir     {
715cdf0e10cSrcweir         if( !rCmpArr.Found() )
716cdf0e10cSrcweir             return sal_False;
717cdf0e10cSrcweir         nEndPos = rCmpArr.GetNdEnd();
718cdf0e10cSrcweir         lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
719cdf0e10cSrcweir         return sal_True;
720cdf0e10cSrcweir     }
721cdf0e10cSrcweir 
722cdf0e10cSrcweir     // dann gehe mal durch das nach "Start" sortierte Array
723cdf0e10cSrcweir     const SwpHints& rHtArr = rTxtNd.GetSwpHints();
724cdf0e10cSrcweir     const SwTxtAttr* pAttr;
725cdf0e10cSrcweir     sal_uInt16 nPos = 0;
726cdf0e10cSrcweir 
727cdf0e10cSrcweir     // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
728cdf0e10cSrcweir     // das wieder beendet wird.
729cdf0e10cSrcweir     if( rCmpArr.Found() )
730cdf0e10cSrcweir     {
731cdf0e10cSrcweir         for( ; nPos < rHtArr.Count(); ++nPos )
732cdf0e10cSrcweir             if( !rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
733cdf0e10cSrcweir             {
734cdf0e10cSrcweir                 if( rCmpArr.GetNdStt() < *pAttr->GetStart() )
735cdf0e10cSrcweir                 {
736cdf0e10cSrcweir                     // dann haben wir unser Ende:
737cdf0e10cSrcweir                     lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(),
738cdf0e10cSrcweir                                 pAttr->GetStart(), sal_True );
739cdf0e10cSrcweir                     return sal_True;
740cdf0e10cSrcweir                 }
741cdf0e10cSrcweir                 // ansonsten muessen wir weiter suchen
742cdf0e10cSrcweir                 break;
743cdf0e10cSrcweir             }
744cdf0e10cSrcweir 
745cdf0e10cSrcweir         if( nPos == rHtArr.Count() && rCmpArr.Found() )
746cdf0e10cSrcweir         {
747cdf0e10cSrcweir             // dann haben wir unseren Bereich
748cdf0e10cSrcweir             nEndPos = rCmpArr.GetNdEnd();
749cdf0e10cSrcweir             lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_True );
750cdf0e10cSrcweir             return sal_True;
751cdf0e10cSrcweir         }
752cdf0e10cSrcweir     }
753cdf0e10cSrcweir 
754cdf0e10cSrcweir     for( ; nPos < rHtArr.Count(); ++nPos )
755cdf0e10cSrcweir         if( rCmpArr.SetAttrFwd( *( pAttr = rHtArr.GetStart( nPos )) ) )
756cdf0e10cSrcweir         {
757cdf0e10cSrcweir             // sollten noch mehr auf der gleichen Position anfangen ??
758cdf0e10cSrcweir             // auch die noch mit testen !!
759cdf0e10cSrcweir             nSttPos = *pAttr->GetStart();
760cdf0e10cSrcweir             while( ++nPos < rHtArr.Count() && nSttPos ==
761cdf0e10cSrcweir                     *( pAttr = rHtArr.GetStart( nPos ))->GetStart() &&
762cdf0e10cSrcweir                     rCmpArr.SetAttrFwd( *pAttr ) )
763cdf0e10cSrcweir                 ;
764cdf0e10cSrcweir             if( !rCmpArr.Found() )
765cdf0e10cSrcweir                 continue;
766cdf0e10cSrcweir 
767cdf0e10cSrcweir             // dann haben wir den Bereich zusammen
768cdf0e10cSrcweir             if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
769cdf0e10cSrcweir                 return sal_False;
770cdf0e10cSrcweir             lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
771cdf0e10cSrcweir             return sal_True;
772cdf0e10cSrcweir         }
773cdf0e10cSrcweir 
774cdf0e10cSrcweir     if( !rCmpArr.CheckStack() ||
775cdf0e10cSrcweir         (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
776cdf0e10cSrcweir         return sal_False;
777cdf0e10cSrcweir     lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_True );
778cdf0e10cSrcweir     return sal_True;
779cdf0e10cSrcweir }
780cdf0e10cSrcweir 
781cdf0e10cSrcweir 
lcl_SearchBackward(const SwTxtNode & rTxtNd,SwAttrCheckArr & rCmpArr,SwPaM & rPam)782cdf0e10cSrcweir int lcl_SearchBackward( const SwTxtNode& rTxtNd, SwAttrCheckArr& rCmpArr,
783cdf0e10cSrcweir                             SwPaM& rPam )
784cdf0e10cSrcweir {
785cdf0e10cSrcweir     xub_StrLen nEndPos, nSttPos;
786cdf0e10cSrcweir     rCmpArr.SetNewSet( rTxtNd, rPam );
787cdf0e10cSrcweir     if( !rTxtNd.HasHints() )
788cdf0e10cSrcweir     {
789cdf0e10cSrcweir         if( !rCmpArr.Found() )
790cdf0e10cSrcweir             return sal_False;
791cdf0e10cSrcweir         nEndPos = rCmpArr.GetNdEnd();
792cdf0e10cSrcweir         lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
793cdf0e10cSrcweir         return sal_True;
794cdf0e10cSrcweir     }
795cdf0e10cSrcweir 
796cdf0e10cSrcweir     // dann gehe mal durch das nach "Start" sortierte Array
797cdf0e10cSrcweir     const SwpHints& rHtArr = rTxtNd.GetSwpHints();
798cdf0e10cSrcweir     const SwTxtAttr* pAttr;
799cdf0e10cSrcweir     sal_uInt16 nPos = rHtArr.Count();
800cdf0e10cSrcweir 
801cdf0e10cSrcweir     // sollte jetzt schon alles vorhanden sein, dann teste, mit welchem
802cdf0e10cSrcweir     // das wieder beendet wird.
803cdf0e10cSrcweir     if( rCmpArr.Found() )
804cdf0e10cSrcweir     {
805cdf0e10cSrcweir         while( nPos )
806cdf0e10cSrcweir             if( !rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
807cdf0e10cSrcweir             {
808cdf0e10cSrcweir                 nSttPos = *pAttr->GetAnyEnd();
809cdf0e10cSrcweir                 if( nSttPos < rCmpArr.GetNdEnd() )
810cdf0e10cSrcweir                 {
811cdf0e10cSrcweir                     // dann haben wir unser Ende:
812cdf0e10cSrcweir                     nEndPos = rCmpArr.GetNdEnd();
813cdf0e10cSrcweir                     lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
814cdf0e10cSrcweir                     return sal_True;
815cdf0e10cSrcweir                 }
816cdf0e10cSrcweir 
817cdf0e10cSrcweir                 // ansonsten muessen wir weiter suchen
818cdf0e10cSrcweir                 break;
819cdf0e10cSrcweir             }
820cdf0e10cSrcweir 
821cdf0e10cSrcweir         if( !nPos && rCmpArr.Found() )
822cdf0e10cSrcweir         {
823cdf0e10cSrcweir             // dann haben wir unseren Bereich
824cdf0e10cSrcweir             nEndPos = rCmpArr.GetNdEnd();
825cdf0e10cSrcweir             lcl_SetAttrPam( rPam, rCmpArr.GetNdStt(), &nEndPos, sal_False );
826cdf0e10cSrcweir             return sal_True;
827cdf0e10cSrcweir         }
828cdf0e10cSrcweir     }
829cdf0e10cSrcweir 
830cdf0e10cSrcweir     while( nPos )
831cdf0e10cSrcweir         if( rCmpArr.SetAttrBwd( *( pAttr = rHtArr.GetEnd( --nPos )) ) )
832cdf0e10cSrcweir         {
833cdf0e10cSrcweir             // sollten noch mehr auf der gleichen Position anfangen ??
834cdf0e10cSrcweir             // auch die noch mit testen !!
835cdf0e10cSrcweir             if( nPos )
836cdf0e10cSrcweir             {
837cdf0e10cSrcweir                 nEndPos = *pAttr->GetAnyEnd();
838cdf0e10cSrcweir                 while( --nPos && nEndPos ==
839cdf0e10cSrcweir                         *( pAttr = rHtArr.GetEnd( nPos ))->GetAnyEnd() &&
840cdf0e10cSrcweir                         rCmpArr.SetAttrBwd( *pAttr ) )
841cdf0e10cSrcweir                     ;
842cdf0e10cSrcweir             }
843cdf0e10cSrcweir             if( !rCmpArr.Found() )
844cdf0e10cSrcweir                 continue;
845cdf0e10cSrcweir 
846cdf0e10cSrcweir 
847cdf0e10cSrcweir             // dann haben wir den Bereich zusammen
848cdf0e10cSrcweir             if( (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
849cdf0e10cSrcweir                 return sal_False;
850cdf0e10cSrcweir             lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
851cdf0e10cSrcweir             return sal_True;
852cdf0e10cSrcweir         }
853cdf0e10cSrcweir 
854cdf0e10cSrcweir     if( !rCmpArr.CheckStack() ||
855cdf0e10cSrcweir         (nSttPos = rCmpArr.Start()) > (nEndPos = rCmpArr.End()) )
856cdf0e10cSrcweir         return sal_False;
857cdf0e10cSrcweir     lcl_SetAttrPam( rPam, nSttPos, &nEndPos, sal_False );
858cdf0e10cSrcweir     return sal_True;
859cdf0e10cSrcweir }
860cdf0e10cSrcweir 
861cdf0e10cSrcweir 
lcl_Search(const SwCntntNode & rCNd,const SfxItemSet & rCmpSet,sal_Bool bNoColls)862cdf0e10cSrcweir int lcl_Search( const SwCntntNode& rCNd, const SfxItemSet& rCmpSet, sal_Bool bNoColls )
863cdf0e10cSrcweir {
864cdf0e10cSrcweir     // nur die harte Attributierung suchen ?
865cdf0e10cSrcweir     if( bNoColls && !rCNd.HasSwAttrSet() )
866cdf0e10cSrcweir         return sal_False;
867cdf0e10cSrcweir 
868cdf0e10cSrcweir     const SfxItemSet& rNdSet = rCNd.GetSwAttrSet();
869cdf0e10cSrcweir     SfxItemIter aIter( rCmpSet );
870cdf0e10cSrcweir     const SfxPoolItem* pItem = aIter.GetCurItem();
871cdf0e10cSrcweir     const SfxPoolItem* pNdItem;
872cdf0e10cSrcweir     sal_uInt16 nWhich;
873cdf0e10cSrcweir 
874cdf0e10cSrcweir     while( sal_True )
875cdf0e10cSrcweir     {
876cdf0e10cSrcweir         // nur testen, ob vorhanden ist ?
877cdf0e10cSrcweir         if( IsInvalidItem( pItem ))
878cdf0e10cSrcweir         {
879cdf0e10cSrcweir             nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() );
880cdf0e10cSrcweir             if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
881cdf0e10cSrcweir                 || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) ))
882cdf0e10cSrcweir                 return sal_False;
883cdf0e10cSrcweir         }
884cdf0e10cSrcweir         else
885cdf0e10cSrcweir         {
886cdf0e10cSrcweir             nWhich = pItem->Which();
887cdf0e10cSrcweir //JP 27.02.95: wenn nach defaults gesucht wird, dann muss man bis zum Pool
888cdf0e10cSrcweir //              runter
889cdf0e10cSrcweir //          if( SFX_ITEM_SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem )
890cdf0e10cSrcweir //              || *pNdItem != *pItem )
891cdf0e10cSrcweir             if( !CmpAttr( rNdSet.Get( nWhich, !bNoColls ), *pItem ))
892cdf0e10cSrcweir                 return sal_False;
893cdf0e10cSrcweir         }
894cdf0e10cSrcweir 
895cdf0e10cSrcweir         if( aIter.IsAtEnd() )
896cdf0e10cSrcweir             break;
897cdf0e10cSrcweir         pItem = aIter.NextItem();
898cdf0e10cSrcweir     }
899cdf0e10cSrcweir     return sal_True;            // wurde gefunden
900cdf0e10cSrcweir }
901cdf0e10cSrcweir 
902cdf0e10cSrcweir 
Find(const SfxPoolItem & rAttr,sal_Bool bValue,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)903cdf0e10cSrcweir sal_Bool SwPaM::Find( const SfxPoolItem& rAttr, sal_Bool bValue, SwMoveFn fnMove,
904cdf0e10cSrcweir                     const SwPaM *pRegion, sal_Bool bInReadOnly )
905cdf0e10cSrcweir {
906cdf0e10cSrcweir     // stelle fest welches Attribut gesucht wird:
90769a74367SOliver-Rainer Wittmann     const sal_uInt16 nWhich = rAttr.Which();
908cdf0e10cSrcweir     int bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich);
909cdf0e10cSrcweir 
910cdf0e10cSrcweir     SwPaM* pPam = MakeRegion( fnMove, pRegion );
911cdf0e10cSrcweir 
912cdf0e10cSrcweir     sal_Bool bFound = sal_False;
913cdf0e10cSrcweir     sal_Bool bFirst = sal_True;
914cdf0e10cSrcweir     sal_Bool bSrchForward = fnMove == fnMoveForward;
915cdf0e10cSrcweir     SwCntntNode * pNode;
916cdf0e10cSrcweir     const SfxPoolItem* pItem;
917cdf0e10cSrcweir     SwpFmts aFmtArr;
918cdf0e10cSrcweir 
919cdf0e10cSrcweir     // Wenn am Anfang/Ende, aus dem Node moven
920cdf0e10cSrcweir     if( bSrchForward
921cdf0e10cSrcweir         ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
922cdf0e10cSrcweir         : !pPam->GetPoint()->nContent.GetIndex() )
923cdf0e10cSrcweir     {
924cdf0e10cSrcweir         if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
925cdf0e10cSrcweir         {
926cdf0e10cSrcweir             delete pPam;
927cdf0e10cSrcweir             return sal_False;
928cdf0e10cSrcweir         }
929cdf0e10cSrcweir         SwCntntNode *pNd = pPam->GetCntntNode();
930cdf0e10cSrcweir         xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
931cdf0e10cSrcweir         pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
932cdf0e10cSrcweir     }
933cdf0e10cSrcweir 
934cdf0e10cSrcweir     while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
935cdf0e10cSrcweir     {
936cdf0e10cSrcweir         if( bCharAttr )
937cdf0e10cSrcweir         {
938cdf0e10cSrcweir             if( !pNode->IsTxtNode() )       // CharAttr sind nur in TextNodes
939cdf0e10cSrcweir                 continue;
940cdf0e10cSrcweir 
941cdf0e10cSrcweir             if( ((SwTxtNode*)pNode)->HasHints() &&
942cdf0e10cSrcweir                 lcl_Search( *(SwTxtNode*)pNode, *pPam, rAttr, fnMove,  bValue ))
943cdf0e10cSrcweir             {
944cdf0e10cSrcweir                 // setze auf die Werte vom Attribut
945cdf0e10cSrcweir                 SetMark();
946cdf0e10cSrcweir                 *GetPoint() = *pPam->GetPoint();
947cdf0e10cSrcweir                 *GetMark() = *pPam->GetMark();
948cdf0e10cSrcweir                 bFound = sal_True;
949cdf0e10cSrcweir                 break;
950cdf0e10cSrcweir             }
951cdf0e10cSrcweir             else if (isTXTATR(nWhich))
952cdf0e10cSrcweir                 continue;               // --> also weiter
953cdf0e10cSrcweir         }
954cdf0e10cSrcweir 
955cdf0e10cSrcweir         // keine harte Attributierung, dann pruefe, ob die Vorlage schon
956cdf0e10cSrcweir         // mal nach dem Attribut befragt wurde
957cdf0e10cSrcweir         if( !pNode->HasSwAttrSet() )
958cdf0e10cSrcweir         {
959cdf0e10cSrcweir             const SwFmt* pTmpFmt = pNode->GetFmtColl();
960cdf0e10cSrcweir             if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
961cdf0e10cSrcweir                 continue;   // die Collection wurde schon mal befragt
962cdf0e10cSrcweir             aFmtArr.Insert( pTmpFmt );
963cdf0e10cSrcweir         }
964cdf0e10cSrcweir 
965cdf0e10cSrcweir         if( SFX_ITEM_SET == pNode->GetSwAttrSet().GetItemState( nWhich,
966cdf0e10cSrcweir             sal_True, &pItem ) && ( !bValue || *pItem == rAttr ) )
967cdf0e10cSrcweir         {
968cdf0e10cSrcweir             // FORWARD:  Point an das Ende, GetMark zum Anfanf vom Node
969cdf0e10cSrcweir             // BACKWARD: Point zum Anfang,  GetMark an das Ende vom Node
970cdf0e10cSrcweir             // und immer nach der Logik: inkl. Start, exkl. End !!!
971cdf0e10cSrcweir             *GetPoint() = *pPam->GetPoint();
972cdf0e10cSrcweir             SetMark();
973cdf0e10cSrcweir             pNode->MakeEndIndex( &GetPoint()->nContent );
974cdf0e10cSrcweir             bFound = sal_True;
975cdf0e10cSrcweir             break;
976cdf0e10cSrcweir         }
977cdf0e10cSrcweir     }
978cdf0e10cSrcweir 
979cdf0e10cSrcweir     // beim rueckwaerts Suchen noch Point und Mark vertauschen
980cdf0e10cSrcweir     if( bFound && !bSrchForward )
981cdf0e10cSrcweir         Exchange();
982cdf0e10cSrcweir 
983cdf0e10cSrcweir     delete pPam;
984cdf0e10cSrcweir     return bFound;
985cdf0e10cSrcweir }
986cdf0e10cSrcweir 
987cdf0e10cSrcweir 
988cdf0e10cSrcweir typedef int (*FnSearchAttr)( const SwTxtNode&, SwAttrCheckArr&, SwPaM& );
989cdf0e10cSrcweir 
Find(const SfxItemSet & rSet,sal_Bool bNoColls,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly,sal_Bool bMoveFirst)990cdf0e10cSrcweir sal_Bool SwPaM::Find( const SfxItemSet& rSet, sal_Bool bNoColls, SwMoveFn fnMove,
991cdf0e10cSrcweir                     const SwPaM *pRegion, sal_Bool bInReadOnly, sal_Bool bMoveFirst )
992cdf0e10cSrcweir {
993cdf0e10cSrcweir     SwPaM* pPam = MakeRegion( fnMove, pRegion );
994cdf0e10cSrcweir 
995cdf0e10cSrcweir     sal_Bool bFound = sal_False;
996cdf0e10cSrcweir     sal_Bool bFirst = sal_True;
997cdf0e10cSrcweir     sal_Bool bSrchForward = fnMove == fnMoveForward;
998cdf0e10cSrcweir     SwCntntNode * pNode;
999cdf0e10cSrcweir     SwpFmts aFmtArr;
1000cdf0e10cSrcweir 
1001cdf0e10cSrcweir     // teste doch mal welche Text/Char-Attribute gesucht werden
1002cdf0e10cSrcweir     SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls );
1003cdf0e10cSrcweir     SfxItemSet aOtherSet( GetDoc()->GetAttrPool(),
1004cdf0e10cSrcweir                             RES_PARATR_BEGIN, RES_GRFATR_END-1 );
1005cdf0e10cSrcweir     aOtherSet.Put( rSet, sal_False );   // alle Invalid-Items erhalten!
1006cdf0e10cSrcweir 
1007cdf0e10cSrcweir     FnSearchAttr fnSearch = bSrchForward
1008cdf0e10cSrcweir                                 ? (&::lcl_SearchForward)
1009cdf0e10cSrcweir                                 : (&::lcl_SearchBackward);
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir     // Wenn am Anfang/Ende, aus dem Node moven
1012cdf0e10cSrcweir     // Wenn am Anfang/Ende, aus dem Node moven
1013cdf0e10cSrcweir     if( bMoveFirst &&
1014cdf0e10cSrcweir         ( bSrchForward
1015cdf0e10cSrcweir         ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetCntntNode()->Len()
1016cdf0e10cSrcweir         : !pPam->GetPoint()->nContent.GetIndex() ) )
1017cdf0e10cSrcweir     {
1018cdf0e10cSrcweir         if( !(*fnMove->fnNds)( &pPam->GetPoint()->nNode, sal_False ))
1019cdf0e10cSrcweir         {
1020cdf0e10cSrcweir             delete pPam;
1021cdf0e10cSrcweir             return sal_False;
1022cdf0e10cSrcweir         }
1023cdf0e10cSrcweir         SwCntntNode *pNd = pPam->GetCntntNode();
1024cdf0e10cSrcweir         xub_StrLen nTmpPos = bSrchForward ? 0 : pNd->Len();
1025cdf0e10cSrcweir         pPam->GetPoint()->nContent.Assign( pNd, nTmpPos );
1026cdf0e10cSrcweir     }
1027cdf0e10cSrcweir 
1028cdf0e10cSrcweir 
1029cdf0e10cSrcweir     while( 0 != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
1030cdf0e10cSrcweir     {
1031cdf0e10cSrcweir         if( aCmpArr.Count() )
1032cdf0e10cSrcweir         {
1033cdf0e10cSrcweir             if( !pNode->IsTxtNode() )       // CharAttr sind nur in TextNodes
1034cdf0e10cSrcweir                 continue;
1035cdf0e10cSrcweir 
1036cdf0e10cSrcweir             if( (!aOtherSet.Count() ||
1037cdf0e10cSrcweir                 lcl_Search( *pNode, aOtherSet, bNoColls )) &&
1038cdf0e10cSrcweir                 (*fnSearch)( *(SwTxtNode*)pNode, aCmpArr, *pPam ))
1039cdf0e10cSrcweir             {
1040cdf0e10cSrcweir                 // setze auf die Werte vom Attribut
1041cdf0e10cSrcweir                 SetMark();
1042cdf0e10cSrcweir                 *GetPoint() = *pPam->GetPoint();
1043cdf0e10cSrcweir                 *GetMark() = *pPam->GetMark();
1044cdf0e10cSrcweir                 bFound = sal_True;
1045cdf0e10cSrcweir                 break;
1046cdf0e10cSrcweir             }
1047cdf0e10cSrcweir             continue;       // TextAttribute
1048cdf0e10cSrcweir         }
1049cdf0e10cSrcweir 
1050cdf0e10cSrcweir         if( !aOtherSet.Count() )
1051cdf0e10cSrcweir             continue;
1052cdf0e10cSrcweir 
1053cdf0e10cSrcweir         // keine harte Attributierung, dann pruefe, ob die Vorlage schon
1054cdf0e10cSrcweir         // mal nach dem Attribut befragt wurde
1055cdf0e10cSrcweir         if( !pNode->HasSwAttrSet() )
1056cdf0e10cSrcweir         {
1057cdf0e10cSrcweir             const SwFmt* pTmpFmt = pNode->GetFmtColl();
1058cdf0e10cSrcweir             if( aFmtArr.Count() && aFmtArr.Seek_Entry( pTmpFmt ))
1059cdf0e10cSrcweir                 continue;   // die Collection wurde schon mal befragt
1060cdf0e10cSrcweir             aFmtArr.Insert( pTmpFmt );
1061cdf0e10cSrcweir         }
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir         if( lcl_Search( *pNode, aOtherSet, bNoColls ))
1064cdf0e10cSrcweir         {
1065cdf0e10cSrcweir             // FORWARD:  Point an das Ende, GetMark zum Anfanf vom Node
1066cdf0e10cSrcweir             // BACKWARD: Point zum Anfang,  GetMark an das Ende vom Node
1067cdf0e10cSrcweir             // und immer nach der Logik: inkl. Start, exkl. End !!!
1068cdf0e10cSrcweir             *GetPoint() = *pPam->GetPoint();
1069cdf0e10cSrcweir             SetMark();
1070cdf0e10cSrcweir             pNode->MakeEndIndex( &GetPoint()->nContent );
1071cdf0e10cSrcweir             bFound = sal_True;
1072cdf0e10cSrcweir             break;
1073cdf0e10cSrcweir         }
1074cdf0e10cSrcweir     }
1075cdf0e10cSrcweir 
1076cdf0e10cSrcweir     // beim rueckwaerts Suchen noch Point und Mark vertauschen
1077cdf0e10cSrcweir     if( bFound && !bSrchForward )
1078cdf0e10cSrcweir         Exchange();
1079cdf0e10cSrcweir 
1080cdf0e10cSrcweir     delete pPam;
1081cdf0e10cSrcweir     return bFound;
1082cdf0e10cSrcweir }
1083cdf0e10cSrcweir 
1084cdf0e10cSrcweir //------------------ Methoden vom SwCursor ---------------------------
1085cdf0e10cSrcweir 
1086cdf0e10cSrcweir // Parameter fuer das Suchen vom Attributen
1087cdf0e10cSrcweir struct SwFindParaAttr : public SwFindParas
1088cdf0e10cSrcweir {
1089cdf0e10cSrcweir     sal_Bool bValue;
1090cdf0e10cSrcweir     const SfxItemSet *pSet, *pReplSet;
1091cdf0e10cSrcweir     const SearchOptions *pSearchOpt;
1092cdf0e10cSrcweir     SwCursor& rCursor;
1093cdf0e10cSrcweir     utl::TextSearch* pSTxt;
1094cdf0e10cSrcweir 
SwFindParaAttrSwFindParaAttr1095cdf0e10cSrcweir     SwFindParaAttr( const SfxItemSet& rSet, sal_Bool bNoCollection,
1096cdf0e10cSrcweir                     const SearchOptions* pOpt, const SfxItemSet* pRSet,
1097cdf0e10cSrcweir                     SwCursor& rCrsr )
1098cdf0e10cSrcweir         : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ),
1099cdf0e10cSrcweir           pSearchOpt( pOpt ), rCursor( rCrsr ),pSTxt( 0 ) {}
1100cdf0e10cSrcweir 
~SwFindParaAttrSwFindParaAttr1101cdf0e10cSrcweir     virtual ~SwFindParaAttr()   { delete pSTxt; }
1102cdf0e10cSrcweir 
1103cdf0e10cSrcweir     virtual int Find( SwPaM* , SwMoveFn , const SwPaM*, sal_Bool bInReadOnly );
1104cdf0e10cSrcweir     virtual int IsReplaceMode() const;
1105cdf0e10cSrcweir };
1106cdf0e10cSrcweir 
1107cdf0e10cSrcweir 
Find(SwPaM * pCrsr,SwMoveFn fnMove,const SwPaM * pRegion,sal_Bool bInReadOnly)1108cdf0e10cSrcweir int SwFindParaAttr::Find( SwPaM* pCrsr, SwMoveFn fnMove, const SwPaM* pRegion,
1109cdf0e10cSrcweir                             sal_Bool bInReadOnly )
1110cdf0e10cSrcweir {
1111cdf0e10cSrcweir     // String ersetzen ?? (nur wenn Text angegeben oder nicht attributiert
1112cdf0e10cSrcweir     //                      gesucht wird)
1113cdf0e10cSrcweir     sal_Bool bReplaceTxt = pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
1114cdf0e10cSrcweir                                     !pSet->Count() );
1115cdf0e10cSrcweir     sal_Bool bReplaceAttr = pReplSet && pReplSet->Count();
1116cdf0e10cSrcweir     sal_Bool bMoveFirst = !bReplaceAttr;
1117cdf0e10cSrcweir     if( bInReadOnly && (bReplaceAttr || bReplaceTxt ))
1118cdf0e10cSrcweir         bInReadOnly = sal_False;
1119cdf0e10cSrcweir 
1120cdf0e10cSrcweir     // wir suchen nach Attributen, soll zusaetzlich Text gesucht werden ?
1121cdf0e10cSrcweir     {
1122cdf0e10cSrcweir         SwPaM aRegion( *pRegion->GetMark(), *pRegion->GetPoint() );
1123cdf0e10cSrcweir         SwPaM* pTextRegion = &aRegion;
1124cdf0e10cSrcweir         SwPaM aSrchPam( *pCrsr->GetPoint() );
1125cdf0e10cSrcweir 
1126cdf0e10cSrcweir         while( sal_True )
1127cdf0e10cSrcweir         {
1128cdf0e10cSrcweir             if( pSet->Count() )         // gibts ueberhaupt Attributierung?
1129cdf0e10cSrcweir             {
1130cdf0e10cSrcweir                 // zuerst die Attributierung
1131cdf0e10cSrcweir                 if( !aSrchPam.Find( *pSet, bValue, fnMove, &aRegion, bInReadOnly, bMoveFirst ) )
1132cdf0e10cSrcweir //JP 17.11.95: was ist mit Attributen in leeren Absaetzen !!
1133cdf0e10cSrcweir //                  || *pCrsr->GetMark() == *pCrsr->GetPoint() )    // kein Bereich ??
1134cdf0e10cSrcweir                     return FIND_NOT_FOUND;
1135cdf0e10cSrcweir                 bMoveFirst = sal_True;
1136cdf0e10cSrcweir 
1137cdf0e10cSrcweir                 if( !pSearchOpt )
1138cdf0e10cSrcweir                     break;      // ok, nur Attribute, also gefunden
1139cdf0e10cSrcweir 
1140cdf0e10cSrcweir                 pTextRegion = &aSrchPam;
1141cdf0e10cSrcweir             }
1142cdf0e10cSrcweir             else if( !pSearchOpt )
1143cdf0e10cSrcweir                 return FIND_NOT_FOUND;
1144cdf0e10cSrcweir 
1145cdf0e10cSrcweir             // dann darin den Text
1146cdf0e10cSrcweir             if( !pSTxt )
1147cdf0e10cSrcweir             {
1148cdf0e10cSrcweir                 SearchOptions aTmp( *pSearchOpt );
1149cdf0e10cSrcweir 
1150cdf0e10cSrcweir                 // search in selection
1151cdf0e10cSrcweir                 aTmp.searchFlag |= (SearchFlags::REG_NOT_BEGINOFLINE |
1152cdf0e10cSrcweir                                     SearchFlags::REG_NOT_ENDOFLINE);
1153cdf0e10cSrcweir 
1154cdf0e10cSrcweir                 MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aTmp.Locale );
1155cdf0e10cSrcweir 
1156cdf0e10cSrcweir                 pSTxt = new utl::TextSearch( aTmp );
1157cdf0e10cSrcweir             }
1158cdf0e10cSrcweir 
1159cdf0e10cSrcweir             // todo/mba: searching for attributes in Outliner text?!
1160cdf0e10cSrcweir             sal_Bool bSearchInNotes = sal_False;
1161cdf0e10cSrcweir 
1162cdf0e10cSrcweir             // Bug 24665: suche im richtigen Bereich weiter (pTextRegion!)
1163cdf0e10cSrcweir             if( aSrchPam.Find( *pSearchOpt, bSearchInNotes, *pSTxt, fnMove, pTextRegion, bInReadOnly ) &&
1164cdf0e10cSrcweir                 *aSrchPam.GetMark() != *aSrchPam.GetPoint() )   // gefunden ?
1165cdf0e10cSrcweir                 break;                                      // also raus
1166cdf0e10cSrcweir             else if( !pSet->Count() )
1167cdf0e10cSrcweir                 return FIND_NOT_FOUND;      // nur Text und nicht gefunden
1168cdf0e10cSrcweir 
1169cdf0e10cSrcweir /*          // --> FME 2007-4-12 #i74765 # Why should we move the position?
1170cdf0e10cSrcweir             Moving the position results in bugs when there are two adjacent
1171cdf0e10cSrcweir             portions which both have the requested attributes set. I suspect this
1172cdf0e10cSrcweir             should be only be an optimization. Therefore I boldly remove it now!
1173cdf0e10cSrcweir 
1174cdf0e10cSrcweir             // JP: und wieder neu aufsetzen, aber eine Position weiter
1175cdf0e10cSrcweir             //JP 04.11.97: Bug 44897 - aber den Mark wieder aufheben, damit
1176cdf0e10cSrcweir             //              weiterbewegt werden kann!
1177cdf0e10cSrcweir             {
1178cdf0e10cSrcweir                 sal_Bool bCheckRegion = sal_True;
1179cdf0e10cSrcweir                 SwPosition* pPos = aSrchPam.GetPoint();
1180cdf0e10cSrcweir                 if( !(*fnMove->fnNd)( &pPos->nNode.GetNode(),
1181cdf0e10cSrcweir                                         &pPos->nContent, CRSR_SKIP_CHARS ))
1182cdf0e10cSrcweir                 {
1183cdf0e10cSrcweir                     if( (*fnMove->fnNds)( &pPos->nNode, sal_False ))
1184cdf0e10cSrcweir                     {
1185cdf0e10cSrcweir                         SwCntntNode *pNd = pPos->nNode.GetNode().GetCntntNode();
1186cdf0e10cSrcweir                         xub_StrLen nCPos;
1187cdf0e10cSrcweir                         if( fnMove == fnMoveForward )
1188cdf0e10cSrcweir                             nCPos = 0;
1189cdf0e10cSrcweir                         else
1190cdf0e10cSrcweir                             nCPos = pNd->Len();
1191cdf0e10cSrcweir                         pPos->nContent.Assign( pNd, nCPos );
1192cdf0e10cSrcweir                     }
1193cdf0e10cSrcweir                     else
1194cdf0e10cSrcweir                         bCheckRegion = sal_False;
1195cdf0e10cSrcweir                 }
1196cdf0e10cSrcweir                 if( !bCheckRegion || *aRegion.GetPoint() <= *pPos )
1197cdf0e10cSrcweir                     return FIND_NOT_FOUND;      // nicht gefunden
1198cdf0e10cSrcweir             }*/
1199cdf0e10cSrcweir             *aRegion.GetMark() = *aSrchPam.GetPoint();
1200cdf0e10cSrcweir         }
1201cdf0e10cSrcweir 
1202cdf0e10cSrcweir         *pCrsr->GetPoint() = *aSrchPam.GetPoint();
1203cdf0e10cSrcweir         pCrsr->SetMark();
1204cdf0e10cSrcweir         *pCrsr->GetMark() = *aSrchPam.GetMark();
1205cdf0e10cSrcweir     }
1206cdf0e10cSrcweir 
1207cdf0e10cSrcweir     if( bReplaceTxt )
1208cdf0e10cSrcweir     {
1209cdf0e10cSrcweir         const bool bRegExp(
1210cdf0e10cSrcweir                 SearchAlgorithms_REGEXP == pSearchOpt->algorithmType);
1211cdf0e10cSrcweir         SwIndex& rSttCntIdx = pCrsr->Start()->nContent;
1212cdf0e10cSrcweir         xub_StrLen nSttCnt = rSttCntIdx.GetIndex();
1213cdf0e10cSrcweir 
1214cdf0e10cSrcweir         // damit die Region auch verschoben wird, in den Shell-Cursr-Ring
1215cdf0e10cSrcweir         // mit aufnehmen !!
1216cdf0e10cSrcweir         Ring *pPrevRing = 0;
1217cdf0e10cSrcweir         if( bRegExp )
1218cdf0e10cSrcweir         {
1219cdf0e10cSrcweir             pPrevRing = pRegion->GetPrev();
1220cdf0e10cSrcweir             ((Ring*)pRegion)->MoveRingTo( &rCursor );
1221cdf0e10cSrcweir         }
1222cdf0e10cSrcweir 
1223cdf0e10cSrcweir         ::std::auto_ptr<String> pRepl( (bRegExp) ?
1224cdf0e10cSrcweir                 ReplaceBackReferences( *pSearchOpt, pCrsr ) : 0 );
1225cdf0e10cSrcweir         rCursor.GetDoc()->ReplaceRange( *pCrsr,
1226cdf0e10cSrcweir             (pRepl.get()) ? *pRepl : String(pSearchOpt->replaceString),
1227cdf0e10cSrcweir             bRegExp );
1228cdf0e10cSrcweir         rCursor.SaveTblBoxCntnt( pCrsr->GetPoint() );
1229cdf0e10cSrcweir 
1230cdf0e10cSrcweir         if( bRegExp )
1231cdf0e10cSrcweir         {
1232cdf0e10cSrcweir             // und die Region wieder herausnehmen:
1233cdf0e10cSrcweir             Ring *p, *pNext = (Ring*)pRegion;
1234cdf0e10cSrcweir             do {
1235cdf0e10cSrcweir                 p = pNext;
1236cdf0e10cSrcweir                 pNext = p->GetNext();
1237cdf0e10cSrcweir                 p->MoveTo( (Ring*)pRegion );
1238cdf0e10cSrcweir             } while( p != pPrevRing );
1239cdf0e10cSrcweir         }
1240cdf0e10cSrcweir         rSttCntIdx = nSttCnt;
1241cdf0e10cSrcweir     }
1242cdf0e10cSrcweir 
1243cdf0e10cSrcweir     if( bReplaceAttr )
1244cdf0e10cSrcweir     {
1245cdf0e10cSrcweir         // --- Ist die Selection noch da ??????
1246cdf0e10cSrcweir 
1247cdf0e10cSrcweir         // und noch die Attribute setzen
1248cdf0e10cSrcweir #ifdef OLD
1249cdf0e10cSrcweir         pCrsr->GetDoc()->Insert( *pCrsr, *pReplSet, 0 );
1250cdf0e10cSrcweir #else
1251cdf0e10cSrcweir         //JP 13.07.95: alle gesuchten Attribute werden, wenn nicht im
1252cdf0e10cSrcweir         //              ReplaceSet angegeben, auf Default zurueck gesetzt
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir         if( !pSet->Count() )
1255cdf0e10cSrcweir         {
1256cdf0e10cSrcweir             pCrsr->GetDoc()->InsertItemSet( *pCrsr, *pReplSet, 0 );
1257cdf0e10cSrcweir         }
1258cdf0e10cSrcweir         else
1259cdf0e10cSrcweir         {
1260cdf0e10cSrcweir             SfxItemPool* pPool = pReplSet->GetPool();
1261cdf0e10cSrcweir             SfxItemSet aSet( *pPool, pReplSet->GetRanges() );
1262cdf0e10cSrcweir 
1263cdf0e10cSrcweir             SfxItemIter aIter( *pSet );
1264cdf0e10cSrcweir             const SfxPoolItem* pItem = aIter.GetCurItem();
1265cdf0e10cSrcweir             while( sal_True )
1266cdf0e10cSrcweir             {
1267cdf0e10cSrcweir                 // alle die nicht gesetzt sind mit Pool-Defaults aufuellen
1268cdf0e10cSrcweir                 if( !IsInvalidItem( pItem ) && SFX_ITEM_SET !=
1269cdf0e10cSrcweir                     pReplSet->GetItemState( pItem->Which(), sal_False ))
1270cdf0e10cSrcweir                     aSet.Put( pPool->GetDefaultItem( pItem->Which() ));
1271cdf0e10cSrcweir 
1272cdf0e10cSrcweir                 if( aIter.IsAtEnd() )
1273cdf0e10cSrcweir                     break;
1274cdf0e10cSrcweir                 pItem = aIter.NextItem();
1275cdf0e10cSrcweir             }
1276cdf0e10cSrcweir             aSet.Put( *pReplSet );
1277cdf0e10cSrcweir             pCrsr->GetDoc()->InsertItemSet( *pCrsr, aSet, 0 );
1278cdf0e10cSrcweir         }
1279cdf0e10cSrcweir #endif
1280cdf0e10cSrcweir         return FIND_NO_RING;
1281cdf0e10cSrcweir     }
1282cdf0e10cSrcweir 
1283cdf0e10cSrcweir     else
1284cdf0e10cSrcweir         return FIND_FOUND;
1285cdf0e10cSrcweir }
1286cdf0e10cSrcweir 
1287cdf0e10cSrcweir 
IsReplaceMode() const1288cdf0e10cSrcweir int SwFindParaAttr::IsReplaceMode() const
1289cdf0e10cSrcweir {
1290cdf0e10cSrcweir     return ( pSearchOpt && pSearchOpt->replaceString.getLength() ) ||
1291cdf0e10cSrcweir            ( pReplSet && pReplSet->Count() );
1292cdf0e10cSrcweir }
1293cdf0e10cSrcweir 
1294cdf0e10cSrcweir // Suchen nach Attributen
1295cdf0e10cSrcweir 
1296cdf0e10cSrcweir 
Find(const SfxItemSet & rSet,sal_Bool bNoCollections,SwDocPositions nStart,SwDocPositions nEnde,sal_Bool & bCancel,FindRanges eFndRngs,const SearchOptions * pSearchOpt,const SfxItemSet * pReplSet)1297cdf0e10cSrcweir sal_uLong SwCursor::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
1298cdf0e10cSrcweir                     SwDocPositions nStart, SwDocPositions nEnde, sal_Bool& bCancel,
1299cdf0e10cSrcweir                     FindRanges eFndRngs,
1300cdf0e10cSrcweir                     const SearchOptions* pSearchOpt, const SfxItemSet* pReplSet )
1301cdf0e10cSrcweir {
1302cdf0e10cSrcweir     // OLE-Benachrichtigung abschalten !!
1303cdf0e10cSrcweir     SwDoc* pDoc = GetDoc();
1304cdf0e10cSrcweir     Link aLnk( pDoc->GetOle2Link() );
1305cdf0e10cSrcweir     pDoc->SetOle2Link( Link() );
1306cdf0e10cSrcweir 
1307cdf0e10cSrcweir     sal_Bool bReplace = ( pSearchOpt && ( pSearchOpt->replaceString.getLength() ||
1308cdf0e10cSrcweir                                     !rSet.Count() ) ) ||
1309cdf0e10cSrcweir                     (pReplSet && pReplSet->Count());
1310cdf0e10cSrcweir     bool const bStartUndo = pDoc->GetIDocumentUndoRedo().DoesUndo() && bReplace;
1311cdf0e10cSrcweir     if (bStartUndo)
1312cdf0e10cSrcweir     {
1313cdf0e10cSrcweir         pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_REPLACE, NULL );
1314cdf0e10cSrcweir     }
1315cdf0e10cSrcweir 
1316cdf0e10cSrcweir     SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt,
1317cdf0e10cSrcweir                                     pReplSet, *this );
1318cdf0e10cSrcweir 
1319cdf0e10cSrcweir     sal_uLong nRet = FindAll(aSwFindParaAttr, nStart, nEnde, eFndRngs, bCancel );
1320cdf0e10cSrcweir     pDoc->SetOle2Link( aLnk );
1321cdf0e10cSrcweir     if( nRet && bReplace )
1322cdf0e10cSrcweir         pDoc->SetModified();
1323cdf0e10cSrcweir 
1324cdf0e10cSrcweir     if (bStartUndo)
1325cdf0e10cSrcweir     {
1326cdf0e10cSrcweir         pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_REPLACE, NULL );
1327cdf0e10cSrcweir     }
1328cdf0e10cSrcweir 
1329cdf0e10cSrcweir     return nRet;
1330cdf0e10cSrcweir }
1331