xref: /trunk/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