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