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