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