Update ooo320-m1
[ooovba.git] / sw / source / ui / wrtsh / move.cxx
blobe44305ef14d61471498c1451be1522967b13eef1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: move.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <sfx2/bindings.hxx>
36 #include <wrtsh.hxx>
37 #ifndef _VIEW_HXX
38 #include <view.hxx>
39 #endif
40 #include <viewopt.hxx>
41 #include <crsskip.hxx>
43 /* Immer:
44 - Zuruecksetzen des Cursorstacks
45 - Timer nachtriggern
46 - gfs. GCAttr
48 bei Selektion
49 - SttSelect()
51 sonst
52 - EndSelect()
55 const long nReadOnlyScrollOfst = 10;
57 class ShellMoveCrsr
59 SwWrtShell* pSh;
60 BOOL bAct;
61 public:
62 inline ShellMoveCrsr( SwWrtShell* pWrtSh, BOOL bSel )
64 bAct = !pWrtSh->ActionPend() && (pWrtSh->GetFrmType(0,FALSE) & FRMTYPE_FLY_ANY);
65 ( pSh = pWrtSh )->MoveCrsr( BOOL(bSel) );
66 pWrtSh->GetView().GetViewFrame()->GetBindings().Invalidate(SID_HYPERLINK_GETLINK);
68 inline ~ShellMoveCrsr()
70 if( bAct )
72 //Die Action wird fuer das Scrollen in "einabsaetzigen" Rahmen mit
73 //fester Hoehe gebraucht.
74 pSh->StartAllAction();
75 pSh->EndAllAction();
80 void SwWrtShell::MoveCrsr( BOOL bWithSelect )
82 ResetCursorStack();
83 if ( IsGCAttr() )
85 GCAttr();
86 ClearGCAttr();
88 if ( bWithSelect )
89 SttSelect();
90 else
92 EndSelect();
93 (this->*fnKillSel)( 0, FALSE );
97 BOOL SwWrtShell::SimpleMove( FNSimpleMove FnSimpleMove, BOOL bSelect )
99 BOOL nRet;
100 if( bSelect )
102 SttCrsrMove();
103 MoveCrsr( TRUE );
104 nRet = (this->*FnSimpleMove)();
105 EndCrsrMove();
107 else if( 0 != ( nRet = (this->*FnSimpleMove)() ) )
108 MoveCrsr( FALSE );
109 return nRet;
113 BOOL SwWrtShell::Left( USHORT nMode, BOOL bSelect,
114 USHORT nCount, BOOL bBasicCall, BOOL bVisual )
116 if ( !bSelect && !bBasicCall && IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly())
118 Point aTmp( VisArea().Pos() );
119 aTmp.X() -= VisArea().Width() * nReadOnlyScrollOfst / 100;
120 rView.SetVisArea( aTmp );
121 return TRUE;
123 else
125 ShellMoveCrsr aTmp( this, bSelect );
126 return SwCrsrShell::Left( nCount, nMode, bVisual );
132 BOOL SwWrtShell::Right( USHORT nMode, BOOL bSelect,
133 USHORT nCount, BOOL bBasicCall, BOOL bVisual )
135 if ( !bSelect && !bBasicCall && IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly() )
137 Point aTmp( VisArea().Pos() );
138 aTmp.X() += VisArea().Width() * nReadOnlyScrollOfst / 100;
139 aTmp.X() = rView.SetHScrollMax( aTmp.X() );
140 rView.SetVisArea( aTmp );
141 return TRUE;
143 else
145 ShellMoveCrsr aTmp( this, bSelect );
146 return SwCrsrShell::Right( nCount, nMode, bVisual );
152 BOOL SwWrtShell::Up( BOOL bSelect, USHORT nCount, BOOL bBasicCall )
154 if ( !bSelect && !bBasicCall && IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly())
156 Point aTmp( VisArea().Pos() );
157 aTmp.Y() -= VisArea().Height() * nReadOnlyScrollOfst / 100;
158 rView.SetVisArea( aTmp );
159 return TRUE;
161 else
163 ShellMoveCrsr aTmp( this, bSelect );
164 return SwCrsrShell::Up( nCount );
170 BOOL SwWrtShell::Down( BOOL bSelect, USHORT nCount, BOOL bBasicCall )
172 if ( !bSelect && !bBasicCall && IsCrsrReadonly() && !GetViewOptions()->IsSelectionInReadonly())
174 Point aTmp( VisArea().Pos() );
175 aTmp.Y() += VisArea().Height() * nReadOnlyScrollOfst / 100;
176 aTmp.Y() = rView.SetVScrollMax( aTmp.Y() );
177 rView.SetVisArea( aTmp );
178 return TRUE;
180 else
182 ShellMoveCrsr aTmp( this, bSelect );
183 return SwCrsrShell::Down( nCount );
189 BOOL SwWrtShell::LeftMargin( BOOL bSelect, BOOL bBasicCall )
191 if ( !bSelect && !bBasicCall && IsCrsrReadonly() )
193 Point aTmp( VisArea().Pos() );
194 aTmp.X() = DOCUMENTBORDER;
195 rView.SetVisArea( aTmp );
196 return TRUE;
198 else
200 ShellMoveCrsr aTmp( this, bSelect );
201 return SwCrsrShell::LeftMargin();
207 BOOL SwWrtShell::RightMargin( BOOL bSelect, BOOL bBasicCall )
209 if ( !bSelect && !bBasicCall && IsCrsrReadonly() )
211 Point aTmp( VisArea().Pos() );
212 aTmp.X() = GetDocSize().Width() - VisArea().Width() + DOCUMENTBORDER;
213 if( DOCUMENTBORDER > aTmp.X() )
214 aTmp.X() = DOCUMENTBORDER;
215 rView.SetVisArea( aTmp );
216 return TRUE;
218 else
220 ShellMoveCrsr aTmp( this, bSelect );
221 return SwCrsrShell::RightMargin(bBasicCall);
227 BOOL SwWrtShell::GoStart( BOOL bKeepArea, BOOL *pMoveTable,
228 BOOL bSelect, BOOL bDontMoveRegion )
230 if ( IsCrsrInTbl() )
232 const BOOL bBoxSelection = HasBoxSelection();
233 if( !bBlockMode )
235 if ( !bSelect )
236 EnterStdMode();
237 else
238 SttSelect();
240 // Tabellenzelle?
241 if ( !bBoxSelection && (MoveSection( fnSectionCurr, fnSectionStart)
242 || bDontMoveRegion))
244 if ( pMoveTable )
245 *pMoveTable = FALSE;
246 return TRUE;
248 if( MoveTable( fnTableCurr, fnTableStart ) || bDontMoveRegion )
250 if ( pMoveTable )
251 *pMoveTable = TRUE;
252 return TRUE;
254 else if( bBoxSelection && pMoveTable )
256 // JP 09.01.96: wir haben eine Boxselektion (oder leere Zelle)
257 // und wollen selektieren (pMoveTable wird im
258 // SelAll gesetzt). Dann darf die Tabelle nicht
259 // verlassen werden; sonst ist keine Selektion der
260 // gesamten Tabelle moeglich!
261 *pMoveTable = TRUE;
262 return TRUE;
266 if( !bBlockMode )
268 if ( !bSelect )
269 EnterStdMode();
270 else
271 SttSelect();
273 const USHORT nFrmType = GetFrmType(0,FALSE);
274 if ( FRMTYPE_FLY_ANY & nFrmType )
276 if( MoveSection( fnSectionCurr, fnSectionStart ) )
277 return TRUE;
278 else if ( FRMTYPE_FLY_FREE & nFrmType || bDontMoveRegion )
279 return FALSE;
281 if(( FRMTYPE_HEADER | FRMTYPE_FOOTER | FRMTYPE_FOOTNOTE ) & nFrmType )
283 if ( MoveSection( fnSectionCurr, fnSectionStart ) )
284 return TRUE;
285 else if ( bKeepArea )
286 return TRUE;
288 // Bereiche ???
289 return SwCrsrShell::MoveRegion( fnRegionCurrAndSkip, fnRegionStart ) ||
290 SwCrsrShell::SttEndDoc(TRUE);
295 BOOL SwWrtShell::GoEnd(BOOL bKeepArea, BOOL *pMoveTable)
297 if ( pMoveTable && *pMoveTable )
298 return MoveTable( fnTableCurr, fnTableEnd );
300 if ( IsCrsrInTbl() )
302 if ( MoveSection( fnSectionCurr, fnSectionEnd ) ||
303 MoveTable( fnTableCurr, fnTableEnd ) )
304 return TRUE;
306 else
308 const USHORT nFrmType = GetFrmType(0,FALSE);
309 if ( FRMTYPE_FLY_ANY & nFrmType )
311 if ( MoveSection( fnSectionCurr, fnSectionEnd ) )
312 return TRUE;
313 else if ( FRMTYPE_FLY_FREE & nFrmType )
314 return FALSE;
316 if(( FRMTYPE_HEADER | FRMTYPE_FOOTER | FRMTYPE_FOOTNOTE ) & nFrmType )
318 if ( MoveSection( fnSectionCurr, fnSectionEnd) )
319 return TRUE;
320 else if ( bKeepArea )
321 return TRUE;
324 // Bereiche ???
325 return SwCrsrShell::MoveRegion( fnRegionCurrAndSkip, fnRegionEnd ) ||
326 SwCrsrShell::SttEndDoc(FALSE);
331 BOOL SwWrtShell::SttDoc( BOOL bSelect )
333 ShellMoveCrsr aTmp( this, bSelect );
334 return GoStart(FALSE, 0, bSelect );
339 BOOL SwWrtShell::EndDoc( BOOL bSelect)
341 ShellMoveCrsr aTmp( this, bSelect );
342 return GoEnd();
346 BOOL SwWrtShell::SttNxtPg( BOOL bSelect )
348 ShellMoveCrsr aTmp( this, bSelect );
349 return MovePage( fnPageNext, fnPageStart );
354 BOOL SwWrtShell::SttPrvPg( BOOL bSelect )
356 ShellMoveCrsr aTmp( this, bSelect );
357 return MovePage( fnPagePrev, fnPageStart );
362 BOOL SwWrtShell::EndNxtPg( BOOL bSelect )
364 ShellMoveCrsr aTmp( this, bSelect );
365 return MovePage( fnPageNext, fnPageEnd );
370 BOOL SwWrtShell::EndPrvPg( BOOL bSelect )
372 ShellMoveCrsr aTmp( this, bSelect );
373 return MovePage( fnPagePrev, fnPageEnd );
378 BOOL SwWrtShell::SttPg( BOOL bSelect )
380 ShellMoveCrsr aTmp( this, bSelect );
381 return MovePage( fnPageCurr, fnPageStart );
386 BOOL SwWrtShell::EndPg( BOOL bSelect )
388 ShellMoveCrsr aTmp( this, bSelect );
389 return MovePage( fnPageCurr, fnPageEnd );
394 BOOL SwWrtShell::SttPara( BOOL bSelect )
396 ShellMoveCrsr aTmp( this, bSelect );
397 return MovePara( fnParaCurr, fnParaStart );
402 BOOL SwWrtShell::EndPara( BOOL bSelect )
404 ShellMoveCrsr aTmp( this, bSelect );
405 return MovePara(fnParaCurr,fnParaEnd);
409 /*------------------------------------------------------------------------
410 Beschreibung: Spaltenweises Springen
411 Parameter: mit oder ohne SSelection
412 Return: Erfolg oder Misserfolg
413 ------------------------------------------------------------------------*/
417 BOOL SwWrtShell::StartOfColumn( BOOL bSelect )
419 ShellMoveCrsr aTmp( this, bSelect);
420 return MoveColumn(fnColumnCurr, fnColumnStart);
425 BOOL SwWrtShell::EndOfColumn( BOOL bSelect )
427 ShellMoveCrsr aTmp( this, bSelect);
428 return MoveColumn(fnColumnCurr, fnColumnEnd);
433 BOOL SwWrtShell::StartOfNextColumn( BOOL bSelect )
435 ShellMoveCrsr aTmp( this, bSelect);
436 return MoveColumn( fnColumnNext, fnColumnStart);
441 BOOL SwWrtShell::EndOfNextColumn( BOOL bSelect )
443 ShellMoveCrsr aTmp( this, bSelect);
444 return MoveColumn(fnColumnNext, fnColumnEnd);
449 BOOL SwWrtShell::StartOfPrevColumn( BOOL bSelect )
451 ShellMoveCrsr aTmp( this, bSelect);
452 return MoveColumn(fnColumnPrev, fnColumnStart);
457 BOOL SwWrtShell::EndOfPrevColumn( BOOL bSelect )
459 ShellMoveCrsr aTmp( this, bSelect);
460 return MoveColumn(fnColumnPrev, fnColumnEnd);
465 BOOL SwWrtShell::PushCrsr(SwTwips lOffset, BOOL bSelect)
467 BOOL bDiff = FALSE;
468 SwRect aOldRect( GetCharRect() ), aTmpArea( VisArea() );
470 //bDestOnStack besagt, ob ich den Cursor nicht an die aktuelle Position
471 //setzen konnte, da in diesem Bereich kein Inhalt vorhanden ist.
472 if( !bDestOnStack )
474 Point aPt( aOldRect.Center() );
476 if( !IsCrsrVisible() )
477 // set CrsrPos to top-/bottom left pos. So the pagescroll is not
478 // be dependent on the current cursor, but on the visarea.
479 aPt.Y() = aTmpArea.Top() + aTmpArea.Height() / 2;
481 aPt.Y() += lOffset;
482 aDest = GetCntntPos(aPt,lOffset > 0);
483 aDest.X() = aPt.X();
484 bDestOnStack = TRUE;
487 //falls wir eine Rahmenselektion hatten, muss diese nach dem
488 //fnSetCrsr entfernt werden und damit wir da wieder hinkommen
489 //auf dem Stack gemerkt werden.
490 BOOL bIsFrmSel = FALSE;
492 BOOL bIsObjSel = FALSE;
494 //Zielposition liegt jetzt innerhalb des sichtbaren Bereiches -->
495 //Cursor an die Zielposition setzen; merken, dass keine Ziel-
496 //position mehr auf dem Stack steht.
497 //Der neue sichtbare Bereich wird zuvor ermittelt.
498 aTmpArea.Pos().Y() += lOffset;
499 if( aTmpArea.IsInside(aDest) )
501 if( bSelect )
502 SttSelect();
503 else
504 EndSelect();
506 bIsFrmSel = IsFrmSelected();
507 bIsObjSel = 0 != IsObjSelected();
509 // Rahmenselektion aufheben
510 if( bIsFrmSel || bIsObjSel )
512 UnSelectFrm();
513 LeaveSelFrmMode();
514 if ( bIsObjSel )
516 GetView().SetDrawFuncPtr( NULL );
517 GetView().LeaveDrawCreate();
520 CallChgLnk();
523 (this->*fnSetCrsr)( &aDest, TRUE );
525 bDiff = aOldRect != GetCharRect();
527 if( bIsFrmSel )
529 // CallChgLnk();
530 // bei Frames immer nur die obere Ecke nehmen, damit dieser
531 // wieder selektiert werden kann
532 aOldRect.SSize( 5, 5 );
535 // Zuruecksetzen des Dest. SPoint Flags
536 bDestOnStack = FALSE;
539 // Position auf den Stack; bDiff besagt, ob ein Unterschied zwischen
540 // der alten und der neuen Cursorposition besteht.
541 pCrsrStack = new CrsrStack( bDiff, bIsFrmSel, aOldRect.Center(),
542 lOffset, pCrsrStack );
543 return !bDestOnStack && bDiff;
548 BOOL SwWrtShell::PopCrsr(BOOL bUpdate, BOOL bSelect)
550 if( 0 == pCrsrStack)
551 return FALSE;
553 const BOOL bValidPos = pCrsrStack->bValidCurPos;
554 if( bUpdate && bValidPos )
556 // falls ein Vorgaenger auf dem Stack steht, dessen Flag fuer eine
557 // gueltige Position verwenden.
558 SwRect aTmpArea(VisArea());
559 aTmpArea.Pos().Y() -= pCrsrStack->lOffset;
560 if( aTmpArea.IsInside( pCrsrStack->aDocPos ) )
562 if( bSelect )
563 SttSelect();
564 else
565 EndSelect();
567 (this->*fnSetCrsr)(&pCrsrStack->aDocPos, !pCrsrStack->bIsFrmSel);
568 if( pCrsrStack->bIsFrmSel && IsObjSelectable(pCrsrStack->aDocPos))
570 HideCrsr();
571 SelectObj( pCrsrStack->aDocPos );
572 EnterSelFrmMode( &pCrsrStack->aDocPos );
575 // Falls eine Verschiebung zwischen dem sichtbaren Bereich
576 // und der gemerkten Cursorpositionen auftritt, werden
577 // alle gemerkten Positionen weggeschmissen
578 else
580 _ResetCursorStack();
581 return FALSE;
584 CrsrStack *pTmp = pCrsrStack;
585 pCrsrStack = pCrsrStack->pNext;
586 delete pTmp;
587 if( 0 == pCrsrStack )
589 ePageMove = MV_NO;
590 bDestOnStack = FALSE;
592 return bValidPos;
596 * Zuruecksetzen aller gepushten Cursorpositionen; dieser werden nicht
597 * zur Anzeige gebracht ( --> Kein Start-/EndAction!!)
602 void SwWrtShell::_ResetCursorStack()
604 CrsrStack *pTmp = pCrsrStack;
605 while(pCrsrStack)
607 pTmp = pCrsrStack->pNext;
608 delete pCrsrStack;
609 pCrsrStack = pTmp;
611 ePageMove = MV_NO;
612 bDestOnStack = FALSE;
614 /**************
616 falls kein Stack existiert --> Selektionen aufheben
617 falls Stack && Richtungswechsel
618 --> Cursor poppen und return
619 sonst
620 --> Cursor pushen
621 Cursor umsetzen
623 ***************/
627 BOOL SwWrtShell::PageCrsr(SwTwips lOffset, BOOL bSelect)
629 // nichts tun, wenn ein Offset von 0 angegeben wurde
630 if(!lOffset) return FALSE;
631 // Diente mal dazu, eine Neuformatierung fuer das Layout
632 // zu erzwingen.
633 // Hat so nicht funktioniert, da der Cursor nicht gesetzt
634 // wurde, da dies innerhalb einer Start- / EndActionklammerung
635 // nicht geschieht.
636 // Da am Ende nur ViewShell::EndAction() gerufen wird,
637 // findet auch hier keine Aktualisierung der Anzeige
638 // der Cursorposition statt.
639 // Die CrsrShell- Actionklammerung kann nicht verwendet werden,
640 // da sie immer zu einer Anzeige des Cursors fuehrt, also auch,
641 // wenn nach dem Blaettern in einen Bereich ohne gueltige Position
642 // geblaettert wurde.
643 // ViewShell::StartAction();
644 PageMove eDir = lOffset > 0? MV_PAGE_DOWN: MV_PAGE_UP;
645 // Richtungswechsel und Stack vorhanden
646 if( eDir != ePageMove && ePageMove != MV_NO && PopCrsr( TRUE, bSelect ))
647 return TRUE;
649 const BOOL bRet = PushCrsr(lOffset, bSelect);
650 ePageMove = eDir;
651 return bRet;
656 BOOL SwWrtShell::GotoPage(USHORT nPage, BOOL bRecord)
658 ShellMoveCrsr aTmp( this, FALSE);
659 if( SwCrsrShell::GotoPage(nPage) && bRecord)
661 if(IsSelFrmMode())
663 UnSelectFrm();
664 LeaveSelFrmMode();
666 return TRUE;
668 return FALSE;
673 BOOL SwWrtShell::GotoMark( const ::sw::mark::IMark* const pMark, BOOL bSelect, BOOL bStart )
675 ShellMoveCrsr aTmp( this, bSelect );
676 return SwCrsrShell::GotoMark( pMark, bStart );
681 BOOL SwWrtShell::SelectTxtAttr( USHORT nWhich, const SwTxtAttr* pAttr )
683 BOOL bRet;
685 MV_KONTEXT(this);
686 SttSelect();
687 bRet = SwCrsrShell::SelectTxtAttr( nWhich, FALSE, pAttr );
689 EndSelect();
690 return bRet;