xref: /trunk/main/sw/source/core/crsr/trvlfnfl.cxx (revision efeef26f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include <svx/svdmodel.hxx>
29 #include <svx/svdpage.hxx>
30 #include <crsrsh.hxx>
31 #include <doc.hxx>
32 #include <pagefrm.hxx>
33 #include <cntfrm.hxx>
34 #include <ftnfrm.hxx>
35 #include <viewimp.hxx>
36 #include <swcrsr.hxx>
37 #include <dflyobj.hxx>
38 #include <ndtxt.hxx>
39 #include <flyfrm.hxx>
40 #include <txtfrm.hxx>
41 #include <txtftn.hxx>
42 #include <ftnidx.hxx>
43 #include <viscrs.hxx>
44 #include <callnk.hxx>
45 
CallCrsrFN(FNCrsr fnCrsr)46 sal_Bool SwCrsrShell::CallCrsrFN( FNCrsr fnCrsr )
47 {
48 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
49 	SwCursor* pCrsr = getShellCrsr( true );
50 	sal_Bool bRet = (pCrsr->*fnCrsr)();
51 	if( bRet )
52 		UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
53 					SwCrsrShell::READONLY );
54 	return bRet;
55 }
56 
GotoFtnTxt()57 sal_Bool SwCursor::GotoFtnTxt()
58 {
59 	// springe aus dem Content zur Fussnote
60 	sal_Bool bRet = sal_False;
61 	SwTxtNode* pTxtNd = GetPoint()->nNode.GetNode().GetTxtNode();
62 
63     SwTxtAttr *const pFtn( (pTxtNd)
64         ? pTxtNd->GetTxtAttrForCharAt(
65             GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN)
66         : 0);
67     if (pFtn)
68     {
69 		SwCrsrSaveState aSaveState( *this );
70 		GetPoint()->nNode = *((SwTxtFtn*)pFtn)->GetStartNode();
71 
72 		SwCntntNode* pCNd = GetDoc()->GetNodes().GoNextSection(
73 											&GetPoint()->nNode,
74 											sal_True, !IsReadOnlyAvailable() );
75 		if( pCNd )
76 		{
77 			GetPoint()->nContent.Assign( pCNd, 0 );
78             bRet = !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
79                               nsSwCursorSelOverFlags::SELOVER_TOGGLE );
80 		}
81 	}
82 	return bRet;
83 }
84 
GotoFtnTxt()85 sal_Bool SwCrsrShell::GotoFtnTxt()
86 {
87     sal_Bool bRet = CallCrsrFN( &SwCursor::GotoFtnTxt );
88     if( !bRet )
89     {
90         SwTxtNode* pTxtNd = _GetCrsr() ?
91                    _GetCrsr()->GetPoint()->nNode.GetNode().GetTxtNode() : NULL;
92         if( pTxtNd )
93         {
94             const SwFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &_GetCrsr()->GetSttPos(),
95                                                  _GetCrsr()->Start() );
96             const SwFtnBossFrm* pFtnBoss;
97             sal_Bool bSkip = pFrm && pFrm->IsInFtn();
98             while( pFrm && 0 != ( pFtnBoss = pFrm->FindFtnBossFrm() ) )
99             {
100                 if( 0 != ( pFrm = pFtnBoss->FindFtnCont() ) )
101                 {
102                     if( bSkip )
103                         bSkip = sal_False;
104                     else
105                     {
106                         const SwCntntFrm* pCnt = static_cast<const SwLayoutFrm*>
107                                                         (pFrm)->ContainsCntnt();
108                         if( pCnt )
109                         {
110                             const SwCntntNode* pNode = pCnt->GetNode();
111                             _GetCrsr()->GetPoint()->nNode = *pNode;
112                             _GetCrsr()->GetPoint()->nContent.Assign(
113                                 const_cast<SwCntntNode*>(pNode),
114                                 static_cast<const SwTxtFrm*>(pCnt)->GetOfst() );
115                             UpdateCrsr( SwCrsrShell::SCROLLWIN |
116                                 SwCrsrShell::CHKRANGE | SwCrsrShell::READONLY );
117                             bRet = sal_True;
118                             break;
119                         }
120                     }
121                 }
122                 if( pFtnBoss->GetNext() && !pFtnBoss->IsPageFrm() )
123                     pFrm = pFtnBoss->GetNext();
124                 else
125                     pFrm = pFtnBoss->GetUpper();
126             }
127         }
128     }
129     return bRet;
130 }
131 
132 
GotoFtnAnchor()133 sal_Bool SwCursor::GotoFtnAnchor()
134 {
135 	// springe aus der Fussnote zum Anker
136 	const SwNode* pSttNd = GetNode()->FindFootnoteStartNode();
137 	if( pSttNd )
138 	{
139 		// durchsuche alle Fussnoten im Dokument nach diesem StartIndex
140 		const SwTxtFtn* pTxtFtn;
141 		const SwFtnIdxs& rFtnArr = pSttNd->GetDoc()->GetFtnIdxs();
142 		for( sal_uInt16 n = 0; n < rFtnArr.Count(); ++n )
143 			if( 0 != ( pTxtFtn = rFtnArr[ n ])->GetStartNode() &&
144 				pSttNd == &pTxtFtn->GetStartNode()->GetNode() )
145 			{
146 				SwCrsrSaveState aSaveState( *this );
147 
148 				SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
149 
150 				GetPoint()->nNode = rTNd;
151 				GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
152 
153                 return !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION |
154                                   nsSwCursorSelOverFlags::SELOVER_TOGGLE );
155 			}
156 	}
157 	return sal_False;
158 }
159 
GotoFtnAnchor()160 sal_Bool SwCrsrShell::GotoFtnAnchor()
161 {
162 	// springe aus der Fussnote zum Anker
163 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
164 	sal_Bool bRet = pCurCrsr->GotoFtnAnchor();
165 	if( bRet )
166 	{
167 		// BUG 5996: Tabellen-Kopfzeile sonderbehandeln
168 		pCurCrsr->GetPtPos() = Point();
169 		UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
170 					SwCrsrShell::READONLY );
171 	}
172 	return bRet;
173 }
174 
CmpLE(const SwTxtFtn & rFtn,sal_uLong nNd,xub_StrLen nCnt)175 inline sal_Bool CmpLE( const SwTxtFtn& rFtn, sal_uLong nNd, xub_StrLen nCnt )
176 {
177 	sal_uLong nTNd = rFtn.GetTxtNode().GetIndex();
178 	return nTNd < nNd || ( nTNd == nNd && *rFtn.GetStart() <= nCnt );
179 }
CmpL(const SwTxtFtn & rFtn,sal_uLong nNd,xub_StrLen nCnt)180 inline sal_Bool CmpL( const SwTxtFtn& rFtn, sal_uLong nNd, xub_StrLen nCnt )
181 {
182 	sal_uLong nTNd = rFtn.GetTxtNode().GetIndex();
183 	return nTNd < nNd || ( nTNd == nNd && *rFtn.GetStart() < nCnt );
184 }
185 
GotoNextFtnAnchor()186 sal_Bool SwCursor::GotoNextFtnAnchor()
187 {
188 	const SwFtnIdxs& rFtnArr = GetDoc()->GetFtnIdxs();
189 	const SwTxtFtn* pTxtFtn = 0;
190 	sal_uInt16 nPos;
191 
192 	if( rFtnArr.SeekEntry( GetPoint()->nNode, &nPos ))
193 	{
194 		// es gibt eine Fussnote mit dem Index, suche also die
195 		// naechstgelegene
196 		if( nPos < rFtnArr.Count() )
197 		{
198 			sal_uLong nNdPos = GetPoint()->nNode.GetIndex();
199 			xub_StrLen nCntPos = GetPoint()->nContent.GetIndex();
200 
201 			pTxtFtn = rFtnArr[ nPos ];
202 			// suche vorewaerts zur naechsten
203 			if( CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
204 			{
205 				pTxtFtn = 0;
206 				for( ++nPos; nPos < rFtnArr.Count(); ++nPos )
207 				{
208 					pTxtFtn = rFtnArr[ nPos ];
209 					if( !CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
210 						break;		// gefunden
211 					pTxtFtn = 0;
212 				}
213 			}
214 			else if( nPos )
215 			{
216 				// suche rueckwaerts zur vorherigen
217 				pTxtFtn = 0;
218 				while( nPos )
219 				{
220 					pTxtFtn = rFtnArr[ --nPos ];
221 					if( CmpLE( *pTxtFtn, nNdPos, nCntPos ) )
222 					{
223 						pTxtFtn = rFtnArr[ ++nPos ];
224 						break;		// gefunden
225 					}
226 //					pTxtFtn = 0;
227 				}
228 			}
229 		}
230 	}
231 	else if( nPos < rFtnArr.Count() )
232 		pTxtFtn = rFtnArr[ nPos ];
233 
234 	sal_Bool bRet = 0 != pTxtFtn;
235 	if( bRet )
236 	{
237 		SwCrsrSaveState aSaveState( *this );
238 
239 		SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
240 		GetPoint()->nNode = rTNd;
241 		GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
242 		bRet = !IsSelOvr();
243 	}
244 	return bRet;
245 }
246 
GotoPrevFtnAnchor()247 sal_Bool SwCursor::GotoPrevFtnAnchor()
248 {
249 	const SwFtnIdxs& rFtnArr = GetDoc()->GetFtnIdxs();
250 	const SwTxtFtn* pTxtFtn = 0;
251 	sal_uInt16 nPos;
252 
253 	if( rFtnArr.SeekEntry( GetPoint()->nNode, &nPos ) )
254 	{
255 		// es gibt eine Fussnote mit dem Index, suche also die
256 		// naechstgelegene
257 		sal_uLong nNdPos = GetPoint()->nNode.GetIndex();
258 		xub_StrLen nCntPos = GetPoint()->nContent.GetIndex();
259 
260 		pTxtFtn = rFtnArr[ nPos ];
261 		// suche vorwaerts zur naechsten
262 		if( CmpL( *pTxtFtn, nNdPos, nCntPos ))
263 		{
264 			for( ++nPos; nPos < rFtnArr.Count(); ++nPos )
265 			{
266 				pTxtFtn = rFtnArr[ nPos ];
267 				if( !CmpL( *pTxtFtn, nNdPos, nCntPos ) )
268 				{
269 					pTxtFtn = rFtnArr[ nPos-1 ];
270 					break;
271 				}
272 			}
273 		}
274 		else if( nPos )
275 		{
276 			// suche rueckwaerts zur vorherigen
277 			pTxtFtn = 0;
278 			while( nPos )
279 			{
280 				pTxtFtn = rFtnArr[ --nPos ];
281 				if( CmpL( *pTxtFtn, nNdPos, nCntPos ))
282 					break;		// gefunden
283 				pTxtFtn = 0;
284 			}
285 		}
286 		else
287 			pTxtFtn = 0;
288 	}
289 	else if( nPos )
290 		pTxtFtn = rFtnArr[ nPos-1 ];
291 
292 	sal_Bool bRet = 0 != pTxtFtn;
293 	if( bRet )
294 	{
295 		SwCrsrSaveState aSaveState( *this );
296 
297 		SwTxtNode& rTNd = (SwTxtNode&)pTxtFtn->GetTxtNode();
298 		GetPoint()->nNode = rTNd;
299 		GetPoint()->nContent.Assign( &rTNd, *pTxtFtn->GetStart() );
300 		bRet = !IsSelOvr();
301 	}
302 	return bRet;
303 }
304 
GotoNextFtnAnchor()305 sal_Bool SwCrsrShell::GotoNextFtnAnchor()
306 {
307 	return CallCrsrFN( &SwCursor::GotoNextFtnAnchor );
308 }
309 
GotoPrevFtnAnchor()310 sal_Bool SwCrsrShell::GotoPrevFtnAnchor()
311 {
312 	return CallCrsrFN( &SwCursor::GotoPrevFtnAnchor );
313 }
314 
315 // springe aus dem Rahmen zum Anker
316 
317 
GotoFlyAnchor()318 sal_Bool SwCrsrShell::GotoFlyAnchor()
319 {
320 	SET_CURR_SHELL( this );
321 	const SwFrm* pFrm = GetCurrFrm();
322 	do {
323 		pFrm = pFrm->GetUpper();
324 	} while( pFrm && !pFrm->IsFlyFrm() );
325 
326 	if( !pFrm )		// ist kein FlyFrame
327 		return sal_False;
328 
329 	SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
330 	SwCrsrSaveState aSaveState( *pCurCrsr );
331 
332 	// springe in den BodyFrame, der am naechsten vom Fly liegt
333 	SwRect aTmpRect( aCharRect );
334 	if( !pFrm->Frm().IsInside( aTmpRect ))
335 		aTmpRect = pFrm->Frm();
336 	Point aPt( aTmpRect.Left(), aTmpRect.Top() +
337 				( aTmpRect.Bottom() - aTmpRect.Top() ) / 2 );
338 	aPt.X() = aPt.X() > (pFrm->Frm().Left() + (pFrm->Frm().SSize().Width() / 2 ))
339 				? pFrm->Frm().Right()
340 				: pFrm->Frm().Left();
341 
342 	const SwPageFrm* pPageFrm = pFrm->FindPageFrm();
343 	const SwCntntFrm* pFndFrm = pPageFrm->GetCntntPos( aPt, sal_False, sal_True );
344 	pFndFrm->GetCrsrOfst( pCurCrsr->GetPoint(), aPt );
345 
346 	sal_Bool bRet = !pCurCrsr->IsInProtectTable() && !pCurCrsr->IsSelOvr();
347 	if( bRet )
348 		UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE |
349 					SwCrsrShell::READONLY );
350 	return bRet;
351 }
352 
353 
354 
355 
356