Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/util/SearchOptions.hpp>
21 : #include <com/sun/star/text/XTextRange.hpp>
22 :
23 : #include <hintids.hxx>
24 : #include <svx/svdmodel.hxx>
25 : #include <editeng/frmdiritem.hxx>
26 : #include <SwSmartTagMgr.hxx>
27 : #include <doc.hxx>
28 : #include <rootfrm.hxx>
29 : #include <pagefrm.hxx>
30 : #include <cntfrm.hxx>
31 : #include <viewimp.hxx>
32 : #include <pam.hxx>
33 : #include <swselectionlist.hxx>
34 : #include <IBlockCursor.hxx>
35 : #include "BlockCursor.hxx"
36 : #include <ndtxt.hxx>
37 : #include <flyfrm.hxx>
38 : #include <dview.hxx>
39 : #include <viewopt.hxx>
40 : #include <frmtool.hxx>
41 : #include <crsrsh.hxx>
42 : #include <tabfrm.hxx>
43 : #include <txtfrm.hxx>
44 : #include <sectfrm.hxx>
45 : #include <swtable.hxx>
46 : #include <callnk.hxx>
47 : #include <viscrs.hxx>
48 : #include <section.hxx>
49 : #include <docsh.hxx>
50 : #include <scriptinfo.hxx>
51 : #include <globdoc.hxx>
52 : #include <pamtyp.hxx>
53 : #include <mdiexp.hxx>
54 : #include <fmteiro.hxx>
55 : #include <wrong.hxx>
56 : #include <unotextrange.hxx>
57 : #include <vcl/svapp.hxx>
58 : #include <vcl/settings.hxx>
59 : #include <numrule.hxx>
60 : #include <IGrammarContact.hxx>
61 : #include <comphelper/flagguard.hxx>
62 : #include <globals.hrc>
63 : #include <comcore.hrc>
64 : #include <IDocumentLayoutAccess.hxx>
65 :
66 : #if defined(ANDROID) || defined(IOS)
67 : #include <touch/touch.h>
68 : #endif
69 :
70 : using namespace com::sun::star;
71 : using namespace util;
72 :
73 782720 : TYPEINIT2(SwCrsrShell,SwViewShell,SwModify);
74 :
75 : /**
76 : * Delete all overlapping Cursors from a Cursor ring.
77 : * @param pointer to SwCursor (ring)
78 : */
79 : void CheckRange( SwCursor* );
80 :
81 : /**
82 : * Check if pCurCrsr points into already existing ranges and delete those.
83 : * @param Pointer to SwCursor object
84 : */
85 76252 : void CheckRange( SwCursor* pCurCrsr )
86 : {
87 76252 : const SwPosition *pStt = pCurCrsr->Start(),
88 76252 : *pEnd = pCurCrsr->GetPoint() == pStt ? pCurCrsr->GetMark() : pCurCrsr->GetPoint();
89 :
90 76252 : SwPaM *pTmpDel = 0,
91 76252 : *pTmp = (SwPaM*)pCurCrsr->GetNext();
92 :
93 : // Search the complete ring
94 152528 : while( pTmp != pCurCrsr )
95 : {
96 24 : const SwPosition *pTmpStt = pTmp->Start(),
97 24 : *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
98 24 : pTmp->GetMark() : pTmp->GetPoint();
99 24 : if( *pStt <= *pTmpStt )
100 : {
101 48 : if( *pEnd > *pTmpStt ||
102 22 : ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
103 2 : pTmpDel = pTmp;
104 : }
105 : else
106 0 : if( *pStt < *pTmpEnd )
107 0 : pTmpDel = pTmp;
108 :
109 : // If Point or Mark is within the Crsr range, we need to remove the old
110 : // range. Take note that Point does not belong to the range anymore.
111 24 : pTmp = (SwPaM*)pTmp->GetNext();
112 24 : delete pTmpDel; // Remove old range
113 24 : pTmpDel = 0;
114 : }
115 76252 : }
116 :
117 : // SwCrsrShell
118 :
119 0 : SwPaM * SwCrsrShell::CreateCrsr()
120 : {
121 : // don't create Crsr in a table Selection (sic!)
122 : OSL_ENSURE( !IsTableMode(), "in table Selection" );
123 :
124 : // New cursor as copy of current one. Add to the ring.
125 : // Links point to previously created one, ie forward.
126 0 : SwShellCrsr* pNew = new SwShellCrsr( *m_pCurCrsr );
127 :
128 : // Hide PaM logically, to avoid undoing the inverting from
129 : // copied PaM (#i75172#)
130 0 : pNew->swapContent(*m_pCurCrsr);
131 :
132 0 : m_pCurCrsr->DeleteMark();
133 :
134 0 : UpdateCrsr( SwCrsrShell::SCROLLWIN );
135 0 : return pNew;
136 : }
137 :
138 : /**
139 : * Delete current Cursor, making the following one the current.
140 : * Note, this function does not delete anything if there is no other cursor.
141 : * @return - returns true if there was another cursor and we deleted one.
142 : */
143 0 : bool SwCrsrShell::DestroyCrsr()
144 : {
145 : // don't delete Crsr within table selection
146 : OSL_ENSURE( !IsTableMode(), "in table Selection" );
147 :
148 : // Is there a next one? Don't do anything if not.
149 0 : if(m_pCurCrsr->GetNext() == m_pCurCrsr)
150 0 : return false;
151 :
152 0 : SwCallLink aLk( *this ); // watch Crsr-Moves
153 0 : SwCursor* pNextCrsr = (SwCursor*)m_pCurCrsr->GetNext();
154 0 : delete m_pCurCrsr;
155 0 : m_pCurCrsr = dynamic_cast<SwShellCrsr*>(pNextCrsr);
156 0 : UpdateCrsr();
157 0 : return true;
158 : }
159 :
160 : /**
161 : * Create and return a new shell cursor.
162 : * Simply returns the current shell cursor if there is no selection
163 : * (HasSelection()).
164 : */
165 18 : SwPaM & SwCrsrShell::CreateNewShellCursor()
166 : {
167 18 : if (HasSelection())
168 : {
169 0 : (void) CreateCrsr(); // n.b. returns old cursor
170 : }
171 18 : return *GetCrsr();
172 : }
173 :
174 : /**
175 : * Return the current shell cursor
176 : * @return - returns current `SwPaM` shell cursor
177 : */
178 0 : SwPaM & SwCrsrShell::GetCurrentShellCursor()
179 : {
180 0 : return *GetCrsr();
181 : }
182 :
183 : /**
184 : * Return pointer to the current shell cursor
185 : * @return - returns pointer to current `SwPaM` shell cursor
186 : */
187 589245 : SwPaM* SwCrsrShell::GetCrsr( bool bMakeTblCrsr ) const
188 : {
189 589245 : if( m_pTblCrsr )
190 : {
191 384 : if( bMakeTblCrsr && m_pTblCrsr->IsCrsrMovedUpdt() )
192 : {
193 : //don't re-create 'parked' cursors
194 : const SwCntntNode* pCNd;
195 42 : if( m_pTblCrsr->GetPoint()->nNode.GetIndex() &&
196 28 : m_pTblCrsr->GetMark()->nNode.GetIndex() &&
197 42 : 0 != ( pCNd = m_pTblCrsr->GetCntntNode() ) && pCNd->getLayoutFrm( GetLayout() ) &&
198 42 : 0 != ( pCNd = m_pTblCrsr->GetCntntNode(false) ) && pCNd->getLayoutFrm( GetLayout() ) )
199 : {
200 14 : SwShellTableCrsr* pTC = (SwShellTableCrsr*)m_pTblCrsr;
201 14 : GetLayout()->MakeTblCrsrs( *pTC );
202 : }
203 : }
204 :
205 384 : if( m_pTblCrsr->IsChgd() )
206 : {
207 : const_cast<SwCrsrShell*>(this)->m_pCurCrsr =
208 16 : dynamic_cast<SwShellCrsr*>(m_pTblCrsr->MakeBoxSels( m_pCurCrsr ));
209 : }
210 : }
211 589245 : return m_pCurCrsr;
212 : }
213 :
214 110058 : void SwCrsrShell::StartAction()
215 : {
216 110058 : if( !ActionPend() )
217 : {
218 : // save for update of the ribbon bar
219 71312 : const SwNode& rNd = m_pCurCrsr->GetPoint()->nNode.GetNode();
220 71312 : m_nAktNode = rNd.GetIndex();
221 71312 : m_nAktCntnt = m_pCurCrsr->GetPoint()->nContent.GetIndex();
222 71312 : m_nAktNdTyp = rNd.GetNodeType();
223 71312 : m_bAktSelection = *m_pCurCrsr->GetPoint() != *m_pCurCrsr->GetMark();
224 71312 : if( rNd.IsTxtNode() )
225 71312 : m_nLeftFrmPos = SwCallLink::getLayoutFrm( GetLayout(), (SwTxtNode&)rNd, m_nAktCntnt, true );
226 : else
227 0 : m_nLeftFrmPos = 0;
228 : }
229 110058 : SwViewShell::StartAction(); // to the SwViewShell
230 110058 : }
231 :
232 110058 : void SwCrsrShell::EndAction( const bool bIdleEnd, const bool DoSetPosX )
233 : {
234 110058 : comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll(/*bFootnotes =*/ false));
235 110058 : bool bVis = m_bSVCrsrVis;
236 :
237 110058 : sal_uInt16 eFlags = SwCrsrShell::CHKRANGE;
238 110058 : if ( !DoSetPosX )
239 110032 : eFlags |= SwCrsrShell::UPDOWN;
240 :
241 :
242 : // Idle-formatting?
243 110058 : if( bIdleEnd && Imp()->GetRegion() )
244 : {
245 0 : m_pCurCrsr->Hide();
246 : }
247 :
248 : // Update all invalid numberings before the last action
249 110058 : if( 1 == mnStartAction )
250 71312 : GetDoc()->UpdateNumRule();
251 :
252 : // #i76923#: Don't show the cursor in the SwViewShell::EndAction() - call.
253 : // Only the UpdateCrsr shows the cursor.
254 110058 : bool bSavSVCrsrVis = m_bSVCrsrVis;
255 110058 : m_bSVCrsrVis = false;
256 :
257 110058 : SwViewShell::EndAction( bIdleEnd ); // have SwViewShell go first
258 :
259 110058 : m_bSVCrsrVis = bSavSVCrsrVis;
260 :
261 110058 : if( ActionPend() )
262 : {
263 38746 : if( bVis ) // display SV-Cursor again
264 37354 : m_pVisCrsr->Show();
265 :
266 : // If there is still a ChgCall and just the "basic
267 : // parenthiszing(?) (Basic-Klammerung)" exists, call it. This
268 : // decouples the internal with the Basic-parenthising, the
269 : // Shells are switched.
270 38746 : if( !BasicActionPend() )
271 : {
272 : // Within a Basic action, one needs to update the cursor,
273 : // to e.g. create the table cursor. This is being done in
274 : // UpdateCrsr.
275 0 : UpdateCrsr( eFlags, bIdleEnd );
276 :
277 : {
278 : // watch Crsr-Moves, call Link if needed, the DTOR is key here!
279 : SwCallLink aLk( *this, m_nAktNode, m_nAktCntnt, (sal_uInt8)m_nAktNdTyp,
280 0 : m_nLeftFrmPos, m_bAktSelection );
281 :
282 : }
283 0 : if( m_bCallChgLnk && m_bChgCallFlag && m_aChgLnk.IsSet() )
284 : {
285 0 : m_aChgLnk.Call( this );
286 0 : m_bChgCallFlag = false; // reset flag
287 : }
288 : }
289 148804 : return;
290 : }
291 :
292 71312 : if ( !bIdleEnd )
293 66658 : eFlags |= SwCrsrShell::SCROLLWIN;
294 :
295 71312 : UpdateCrsr( eFlags, bIdleEnd ); // Show Cursor changes
296 :
297 : {
298 71312 : SwCallLink aLk( *this ); // watch Crsr-Moves
299 71312 : aLk.nNode = m_nAktNode; // call Link if needed
300 71312 : aLk.nNdTyp = (sal_uInt8)m_nAktNdTyp;
301 71312 : aLk.nCntnt = m_nAktCntnt;
302 71312 : aLk.nLeftFrmPos = m_nLeftFrmPos;
303 :
304 71340 : if( !m_nCrsrMove ||
305 56 : ( 1 == m_nCrsrMove && m_bInCMvVisportChgd ) )
306 : // display Cursor & Selektions again
307 71290 : ShowCrsrs( m_bSVCrsrVis ? sal_True : sal_False );
308 : }
309 : // call ChgCall if there is still one
310 71312 : if( m_bCallChgLnk && m_bChgCallFlag && m_aChgLnk.IsSet() )
311 : {
312 1242 : m_aChgLnk.Call( this );
313 1242 : m_bChgCallFlag = false; // reset flag
314 71312 : }
315 : }
316 :
317 : #ifdef DBG_UTIL
318 : void SwCrsrShell::SttCrsrMove()
319 : {
320 : OSL_ENSURE( m_nCrsrMove < USHRT_MAX, "To many nested CrsrMoves." );
321 : ++m_nCrsrMove;
322 : StartAction();
323 : }
324 :
325 : void SwCrsrShell::EndCrsrMove( const bool bIdleEnd )
326 : {
327 : OSL_ENSURE( m_nCrsrMove, "EndCrsrMove() without SttCrsrMove()." );
328 : EndAction( bIdleEnd, true );
329 : if( !--m_nCrsrMove )
330 : m_bInCMvVisportChgd = false;
331 : }
332 : #endif
333 :
334 52 : bool SwCrsrShell::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
335 : bool bVisualAllowed )
336 : {
337 52 : if( IsTableMode() )
338 0 : return bLeft ? GoPrevCell() : GoNextCell();
339 :
340 52 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
341 52 : bool bRet = false;
342 :
343 : // #i27615# Handle cursor in front of label.
344 52 : const SwTxtNode* pTxtNd = 0;
345 :
346 52 : if( m_pBlockCrsr )
347 0 : m_pBlockCrsr->clearPoints();
348 :
349 : // 1. CASE: Cursor is in front of label. A move to the right
350 : // will simply reset the bInFrontOfLabel flag:
351 52 : SwShellCrsr* pShellCrsr = getShellCrsr( true );
352 52 : if ( !bLeft && pShellCrsr->IsInFrontOfLabel() )
353 : {
354 0 : SetInFrontOfLabel( false );
355 0 : bRet = true;
356 : }
357 : // 2. CASE: Cursor is at beginning of numbered paragraph. A move
358 : // to the left will simply set the bInFrontOfLabel flag:
359 74 : else if ( bLeft && 0 == pShellCrsr->GetPoint()->nContent.GetIndex() &&
360 6 : !pShellCrsr->IsInFrontOfLabel() && !pShellCrsr->HasMark() &&
361 56 : 0 != ( pTxtNd = pShellCrsr->GetNode().GetTxtNode() ) &&
362 2 : pTxtNd->HasVisibleNumberingOrBullet() )
363 : {
364 0 : SetInFrontOfLabel( true );
365 0 : bRet = true;
366 : }
367 : // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
368 : else
369 : {
370 52 : const bool bSkipHidden = !GetViewOptions()->IsShowHiddenChar();
371 : // #i107447#
372 : // To avoid loop the reset of <bInFrontOfLabel> flag is no longer
373 : // reflected in the return value <bRet>.
374 52 : const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( false );
375 : bRet = pShellCrsr->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
376 52 : bSkipHidden, !IsOverwriteCrsr() );
377 52 : if ( !bRet && bLeft && bResetOfInFrontOfLabel )
378 : {
379 : // undo reset of <bInFrontOfLabel> flag
380 0 : SetInFrontOfLabel( true );
381 : }
382 : }
383 :
384 52 : if( bRet )
385 : {
386 46 : UpdateCrsr();
387 : }
388 :
389 52 : return bRet;
390 : }
391 :
392 0 : void SwCrsrShell::MarkListLevel( const OUString& sListId,
393 : const int nListLevel )
394 : {
395 0 : if ( sListId != m_sMarkedListId ||
396 0 : nListLevel != m_nMarkedListLevel)
397 : {
398 0 : if ( !m_sMarkedListId.isEmpty() )
399 0 : mpDoc->MarkListLevel( m_sMarkedListId, m_nMarkedListLevel, false );
400 :
401 0 : if ( !sListId.isEmpty() )
402 : {
403 0 : mpDoc->MarkListLevel( sListId, nListLevel, true );
404 : }
405 :
406 0 : m_sMarkedListId = sListId;
407 0 : m_nMarkedListLevel = nListLevel;
408 : }
409 0 : }
410 :
411 0 : void SwCrsrShell::UpdateMarkedListLevel()
412 : {
413 0 : SwTxtNode * pTxtNd = _GetCrsr()->GetNode().GetTxtNode();
414 :
415 0 : if ( pTxtNd )
416 : {
417 0 : if ( !pTxtNd->IsNumbered() )
418 : {
419 0 : m_pCurCrsr->_SetInFrontOfLabel( false );
420 0 : MarkListLevel( OUString(), 0 );
421 : }
422 0 : else if ( m_pCurCrsr->IsInFrontOfLabel() )
423 : {
424 0 : if ( pTxtNd->IsInList() )
425 : {
426 : OSL_ENSURE( pTxtNd->GetActualListLevel() >= 0 &&
427 : pTxtNd->GetActualListLevel() < MAXLEVEL, "Which level?");
428 : MarkListLevel( pTxtNd->GetListId(),
429 0 : pTxtNd->GetActualListLevel() );
430 : }
431 : }
432 : else
433 : {
434 0 : MarkListLevel( OUString(), 0 );
435 : }
436 : }
437 0 : }
438 :
439 8 : void SwCrsrShell::FirePageChangeEvent(sal_uInt16 nOldPage, sal_uInt16 nNewPage)
440 : {
441 : #ifdef ACCESSIBLE_LAYOUT
442 : if( Imp()->IsAccessible() )
443 : Imp()->FirePageChangeEvent( nOldPage, nNewPage );
444 : #else
445 : (void)nOldPage;
446 : (void)nNewPage;
447 : #endif
448 8 : }
449 :
450 0 : void SwCrsrShell::FireColumnChangeEvent(sal_uInt16 nOldColumn, sal_uInt16 nNewColumn)
451 : {
452 : #ifdef ACCESSIBLE_LAYOUT
453 : if( Imp()->IsAccessible() )
454 : Imp()->FireColumnChangeEvent( nOldColumn, nNewColumn);
455 : #else
456 : (void)nOldColumn;
457 : (void)nNewColumn;
458 : #endif
459 0 : }
460 :
461 3 : void SwCrsrShell::FireSectionChangeEvent(sal_uInt16 nOldSection, sal_uInt16 nNewSection)
462 : {
463 : #ifdef ACCESSIBLE_LAYOUT
464 : if( Imp()->IsAccessible() )
465 : Imp()->FireSectionChangeEvent( nOldSection, nNewSection );
466 : #else
467 : (void)nOldSection;
468 : (void)nNewSection;
469 : #endif
470 3 : }
471 :
472 10311 : bool SwCrsrShell::bColumnChange()
473 : {
474 10311 : SwFrm* pCurrFrm = GetCurrFrm(false);
475 :
476 10311 : if (pCurrFrm == NULL)
477 : {
478 0 : return false;
479 : }
480 :
481 10311 : SwFrm* pCurrCol=((SwFrm*)pCurrFrm)->FindColFrm();
482 :
483 51602 : while(pCurrCol== NULL && pCurrFrm!=NULL )
484 : {
485 41291 : SwLayoutFrm* pParent = pCurrFrm->GetUpper();
486 41291 : if(pParent!=NULL)
487 : {
488 30980 : pCurrCol=((SwFrm*)pParent)->FindColFrm();
489 30980 : pCurrFrm = (SwFrm*)pParent;
490 : }
491 : else
492 : {
493 10311 : break;
494 : }
495 : }
496 :
497 10311 : if(m_oldColFrm == pCurrCol)
498 10311 : return false;
499 : else
500 : {
501 0 : m_oldColFrm = pCurrCol;
502 0 : return true;
503 : }
504 : }
505 :
506 0 : bool SwCrsrShell::UpDown( bool bUp, sal_uInt16 nCnt )
507 : {
508 0 : SET_CURR_SHELL( this );
509 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
510 :
511 0 : bool bTableMode = IsTableMode();
512 0 : SwShellCrsr* pTmpCrsr = getShellCrsr( true );
513 :
514 0 : bool bRet = pTmpCrsr->UpDown( bUp, nCnt );
515 : // #i40019# UpDown should always reset the bInFrontOfLabel flag:
516 0 : bRet |= SetInFrontOfLabel(false);
517 :
518 0 : if( m_pBlockCrsr )
519 0 : m_pBlockCrsr->clearPoints();
520 :
521 0 : if( bRet )
522 : {
523 0 : m_eMvState = MV_UPDOWN; // status for Crsr travelling - GetCrsrOfst
524 0 : if( !ActionPend() )
525 : {
526 0 : CrsrFlag eUpdtMode = SwCrsrShell::SCROLLWIN;
527 0 : if( !bTableMode )
528 : eUpdtMode = (CrsrFlag) (eUpdtMode
529 0 : | SwCrsrShell::UPDOWN | SwCrsrShell::CHKRANGE);
530 0 : UpdateCrsr( static_cast<sal_uInt16>(eUpdtMode) );
531 : }
532 : }
533 0 : return bRet;
534 : }
535 :
536 0 : bool SwCrsrShell::LRMargin( bool bLeft, bool bAPI)
537 : {
538 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
539 0 : SET_CURR_SHELL( this );
540 0 : m_eMvState = MV_LEFTMARGIN; // status for Crsr travelling - GetCrsrOfst
541 :
542 0 : const bool bTableMode = IsTableMode();
543 0 : SwShellCrsr* pTmpCrsr = getShellCrsr( true );
544 :
545 0 : if( m_pBlockCrsr )
546 0 : m_pBlockCrsr->clearPoints();
547 :
548 : const bool bWasAtLM =
549 0 : ( 0 == _GetCrsr()->GetPoint()->nContent.GetIndex() );
550 :
551 0 : bool bRet = pTmpCrsr->LeftRightMargin( bLeft, bAPI );
552 :
553 0 : if ( bLeft && !bTableMode && bRet && bWasAtLM && !_GetCrsr()->HasMark() )
554 : {
555 0 : const SwTxtNode * pTxtNd = _GetCrsr()->GetNode().GetTxtNode();
556 0 : if ( pTxtNd && pTxtNd->HasVisibleNumberingOrBullet() )
557 0 : SetInFrontOfLabel( true );
558 : }
559 0 : else if ( !bLeft )
560 : {
561 0 : bRet = SetInFrontOfLabel( false ) || bRet;
562 : }
563 :
564 0 : if( bRet )
565 : {
566 0 : UpdateCrsr();
567 : }
568 0 : return bRet;
569 : }
570 :
571 0 : bool SwCrsrShell::IsAtLRMargin( bool bLeft, bool bAPI ) const
572 : {
573 0 : const SwShellCrsr* pTmpCrsr = getShellCrsr( true );
574 0 : return pTmpCrsr->IsAtLeftRightMargin( bLeft, bAPI );
575 : }
576 :
577 124 : bool SwCrsrShell::SttEndDoc( bool bStt )
578 : {
579 124 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
580 :
581 124 : SwShellCrsr* pTmpCrsr = m_pBlockCrsr ? &m_pBlockCrsr->getShellCrsr() : m_pCurCrsr;
582 124 : bool bRet = pTmpCrsr->SttEndDoc( bStt );
583 124 : if( bRet )
584 : {
585 124 : if( bStt )
586 30 : pTmpCrsr->GetPtPos().Y() = 0; // set to 0 explicitly (table header)
587 124 : if( m_pBlockCrsr )
588 : {
589 0 : m_pBlockCrsr->clearPoints();
590 0 : RefreshBlockCursor();
591 : }
592 :
593 124 : UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
594 : }
595 124 : return bRet;
596 : }
597 :
598 16 : void SwCrsrShell::ExtendedSelectAll(bool bFootnotes)
599 : {
600 16 : SwNodes& rNodes = GetDoc()->GetNodes();
601 16 : SwPosition* pPos = m_pCurCrsr->GetPoint();
602 16 : pPos->nNode = bFootnotes ? rNodes.GetEndOfPostIts() : rNodes.GetEndOfAutotext();
603 16 : pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 );
604 16 : pPos = m_pCurCrsr->GetMark();
605 16 : pPos->nNode = rNodes.GetEndOfContent();
606 16 : SwCntntNode* pCNd = rNodes.GoPrevious( &pPos->nNode );
607 16 : pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
608 16 : }
609 :
610 6306 : bool SwCrsrShell::ExtendedSelectedAll(bool bFootnotes)
611 : {
612 6306 : SwNodes& rNodes = GetDoc()->GetNodes();
613 6306 : SwNodeIndex nNode = bFootnotes ? rNodes.GetEndOfPostIts() : rNodes.GetEndOfAutotext();
614 6306 : SwCntntNode* pStart = rNodes.GoNext(&nNode);
615 :
616 6306 : nNode = rNodes.GetEndOfContent();
617 6306 : SwCntntNode* pEnd = rNodes.GoPrevious(&nNode);
618 :
619 6306 : if (!pStart || !pEnd)
620 0 : return false;
621 :
622 12612 : SwPosition aStart(*pStart, 0);
623 12612 : SwPosition aEnd(*pEnd, pEnd->Len());
624 6306 : SwShellCrsr* pShellCrsr = getShellCrsr(false);
625 12612 : return aStart == *pShellCrsr->Start() && aEnd == *pShellCrsr->End();
626 : }
627 :
628 116887 : bool SwCrsrShell::StartsWithTable()
629 : {
630 116887 : SwNodes& rNodes = GetDoc()->GetNodes();
631 116887 : SwNodeIndex nNode(rNodes.GetEndOfExtras());
632 116887 : SwCntntNode* pCntntNode = rNodes.GoNext(&nNode);
633 116887 : return pCntntNode->FindTableNode();
634 : }
635 :
636 70 : bool SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
637 : {
638 70 : bool bRet = false;
639 :
640 : // never jump of section borders at selection
641 70 : if( !m_pCurCrsr->HasMark() || !m_pCurCrsr->IsNoCntnt() )
642 : {
643 70 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
644 140 : SET_CURR_SHELL( this );
645 :
646 140 : SwCrsrSaveState aSaveState( *m_pCurCrsr );
647 70 : Point& rPt = m_pCurCrsr->GetPtPos();
648 : SwCntntFrm * pFrm = m_pCurCrsr->GetCntntNode()->
649 70 : getLayoutFrm( GetLayout(), &rPt, m_pCurCrsr->GetPoint(), false );
650 140 : if( pFrm && ( bRet = GetFrmInPage( pFrm, fnWhichPage,
651 140 : fnPosPage, m_pCurCrsr ) ) &&
652 : !m_pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
653 70 : nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
654 70 : UpdateCrsr();
655 : else
656 70 : bRet = false;
657 : }
658 70 : return bRet;
659 : }
660 :
661 76236 : bool SwCrsrShell::isInHiddenTxtFrm(SwShellCrsr* pShellCrsr)
662 : {
663 76236 : SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
664 : SwCntntFrm *pFrm = pCNode ?
665 76236 : pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), false ) : 0;
666 76236 : return !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow());
667 : }
668 :
669 0 : bool SwCrsrShell::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
670 : {
671 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
672 0 : SwShellCrsr* pTmpCrsr = getShellCrsr( true );
673 0 : bool bRet = pTmpCrsr->MovePara( fnWhichPara, fnPosPara );
674 0 : if( bRet )
675 : {
676 : //keep going until we get something visible, i.e. skip
677 : //over hidden paragraphs, don't get stuck at the start
678 : //which is what SwCrsrShell::UpdateCrsrPos will reset
679 : //the position to if we pass it a position in an
680 : //invisible hidden paragraph field
681 0 : while (isInHiddenTxtFrm(pTmpCrsr))
682 : {
683 0 : if (!pTmpCrsr->MovePara(fnWhichPara, fnPosPara))
684 0 : break;
685 : }
686 :
687 0 : UpdateCrsr();
688 : }
689 0 : return bRet;
690 : }
691 :
692 62 : bool SwCrsrShell::MoveSection( SwWhichSection fnWhichSect,
693 : SwPosSection fnPosSect)
694 : {
695 62 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
696 62 : SwCursor* pTmpCrsr = getShellCrsr( true );
697 62 : bool bRet = pTmpCrsr->MoveSection( fnWhichSect, fnPosSect );
698 62 : if( bRet )
699 30 : UpdateCrsr();
700 62 : return bRet;
701 :
702 : }
703 :
704 : // position cursor
705 :
706 6 : static SwFrm* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
707 : {
708 6 : SwFrm* pFrm = 0;
709 6 : SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
710 6 : if( pCNd )
711 : {
712 6 : SwCntntFrm *pCntFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &rPt, 0, false );
713 6 : pFrm = pCntFrm ? pCntFrm->GetUpper() : NULL;
714 30 : while( pFrm && !pFrm->IsHeaderFrm() && !pFrm->IsFooterFrm() )
715 18 : pFrm = pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->AnchorFrm()
716 18 : : pFrm->GetUpper();
717 : }
718 6 : return pFrm;
719 : }
720 :
721 0 : bool SwCrsrShell::IsInHeaderFooter( bool* pbInHeader ) const
722 : {
723 0 : Point aPt;
724 0 : SwFrm* pFrm = ::lcl_IsInHeaderFooter( m_pCurCrsr->GetPoint()->nNode, aPt );
725 0 : if( pFrm && pbInHeader )
726 0 : *pbInHeader = pFrm->IsHeaderFrm();
727 0 : return 0 != pFrm;
728 : }
729 :
730 6 : int SwCrsrShell::SetCrsr( const Point &rLPt, bool bOnlyText, bool bBlock )
731 : {
732 6 : SET_CURR_SHELL( this );
733 :
734 6 : SwShellCrsr* pCrsr = getShellCrsr( bBlock );
735 12 : SwPosition aPos( *pCrsr->GetPoint() );
736 6 : Point aPt( rLPt );
737 6 : Point & rAktCrsrPt = pCrsr->GetPtPos();
738 6 : SwCrsrMoveState aTmpState( IsTableMode() ? MV_TBLSEL :
739 6 : bOnlyText ? MV_SETONLYTEXT : MV_NONE );
740 6 : aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
741 :
742 6 : SwTxtNode * pTxtNd = pCrsr->GetNode().GetTxtNode();
743 :
744 18 : if ( pTxtNd && !IsTableMode() &&
745 : // #i37515# No bInFrontOfLabel during selection
746 18 : !pCrsr->HasMark() &&
747 6 : pTxtNd->HasVisibleNumberingOrBullet() )
748 : {
749 0 : aTmpState.bInFrontOfLabel = true; // #i27615#
750 : }
751 : else
752 : {
753 6 : aTmpState.bInFrontOfLabel = false;
754 : }
755 :
756 6 : int bRet = CRSR_POSOLD |
757 6 : ( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState )
758 6 : ? 0 : CRSR_POSCHG );
759 :
760 6 : const bool bOldInFrontOfLabel = IsInFrontOfLabel();
761 6 : const bool bNewInFrontOfLabel = aTmpState.bInFrontOfLabel;
762 :
763 6 : pCrsr->SetCrsrBidiLevel( aTmpState.nCursorBidiLevel );
764 :
765 6 : if( MV_RIGHTMARGIN == aTmpState.eState )
766 0 : m_eMvState = MV_RIGHTMARGIN;
767 : // is the new position in header or footer?
768 6 : SwFrm* pFrm = lcl_IsInHeaderFooter( aPos.nNode, aPt );
769 6 : if( IsTableMode() && !pFrm && aPos.nNode.GetNode().StartOfSectionNode() ==
770 0 : pCrsr->GetPoint()->nNode.GetNode().StartOfSectionNode() )
771 : // same table column and not in header/footer -> back
772 0 : return bRet;
773 :
774 6 : if( m_pBlockCrsr && bBlock )
775 : {
776 0 : m_pBlockCrsr->setEndPoint( rLPt );
777 0 : if( !pCrsr->HasMark() )
778 0 : m_pBlockCrsr->setStartPoint( rLPt );
779 0 : else if( !m_pBlockCrsr->getStartPoint() )
780 0 : m_pBlockCrsr->setStartPoint( pCrsr->GetMkPos() );
781 : }
782 6 : if( !pCrsr->HasMark() )
783 : {
784 : // is at the same position and if in header/footer -> in the same
785 6 : if( aPos == *pCrsr->GetPoint() &&
786 : bOldInFrontOfLabel == bNewInFrontOfLabel )
787 : {
788 0 : if( pFrm )
789 : {
790 0 : if( pFrm->Frm().IsInside( rAktCrsrPt ))
791 0 : return bRet;
792 : }
793 0 : else if( aPos.nNode.GetNode().IsCntntNode() )
794 : {
795 : // in the same frame?
796 0 : SwFrm* pOld = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
797 0 : GetLayout(), &m_aCharRect.Pos(), 0, false );
798 0 : SwFrm* pNew = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
799 0 : GetLayout(), &aPt, 0, false );
800 0 : if( pNew == pOld )
801 0 : return bRet;
802 : }
803 : }
804 : }
805 : else
806 : {
807 : // SSelection over not allowed sections or if in header/footer -> different
808 0 : if( !CheckNodesRange( aPos.nNode, pCrsr->GetMark()->nNode, true )
809 0 : || ( pFrm && !pFrm->Frm().IsInside( pCrsr->GetMkPos() ) ))
810 0 : return bRet;
811 :
812 : // is at same position but not in header/footer
813 0 : if( aPos == *pCrsr->GetPoint() )
814 0 : return bRet;
815 : }
816 :
817 12 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
818 12 : SwCrsrSaveState aSaveState( *pCrsr );
819 :
820 6 : *pCrsr->GetPoint() = aPos;
821 6 : rAktCrsrPt = aPt;
822 :
823 : // #i41424# Only update the marked number levels if necessary
824 : // Force update of marked number levels if necessary.
825 6 : if ( bNewInFrontOfLabel || bOldInFrontOfLabel )
826 0 : m_pCurCrsr->_SetInFrontOfLabel( !bNewInFrontOfLabel );
827 6 : SetInFrontOfLabel( bNewInFrontOfLabel );
828 :
829 6 : if( !pCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
830 : {
831 6 : sal_uInt16 nFlag = SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE;
832 6 : UpdateCrsr( nFlag );
833 6 : bRet &= ~CRSR_POSOLD;
834 : }
835 0 : else if( bOnlyText && !m_pCurCrsr->HasMark() )
836 : {
837 0 : if( FindValidCntntNode( bOnlyText ) )
838 : {
839 : // position cursor in a valid content
840 0 : if( aPos == *pCrsr->GetPoint() )
841 0 : bRet = CRSR_POSOLD;
842 : else
843 : {
844 0 : UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE );
845 0 : bRet &= ~CRSR_POSOLD;
846 : }
847 : }
848 : else
849 : {
850 : // there is no valid content -> hide cursor
851 0 : m_pVisCrsr->Hide(); // always hide visible cursor
852 0 : m_eMvState = MV_NONE; // status for Crsr travelling
853 0 : m_bAllProtect = true;
854 0 : if( GetDoc()->GetDocShell() )
855 : {
856 0 : GetDoc()->GetDocShell()->SetReadOnlyUI( true );
857 0 : CallChgLnk(); // notify UI
858 : }
859 : }
860 : }
861 12 : return bRet;
862 : }
863 :
864 2 : void SwCrsrShell::TblCrsrToCursor()
865 : {
866 : OSL_ENSURE( m_pTblCrsr, "TblCrsrToCursor: Why?" );
867 2 : delete m_pTblCrsr, m_pTblCrsr = 0;
868 2 : }
869 :
870 0 : void SwCrsrShell::BlockCrsrToCrsr()
871 : {
872 : OSL_ENSURE( m_pBlockCrsr, "BlockCrsrToCrsr: Why?" );
873 0 : if( m_pBlockCrsr && !HasSelection() )
874 : {
875 0 : SwPaM& rPam = m_pBlockCrsr->getShellCrsr();
876 0 : m_pCurCrsr->SetMark();
877 0 : *m_pCurCrsr->GetPoint() = *rPam.GetPoint();
878 0 : if( rPam.HasMark() )
879 0 : *m_pCurCrsr->GetMark() = *rPam.GetMark();
880 : else
881 0 : m_pCurCrsr->DeleteMark();
882 : }
883 0 : delete m_pBlockCrsr, m_pBlockCrsr = 0;
884 0 : }
885 :
886 0 : void SwCrsrShell::CrsrToBlockCrsr()
887 : {
888 0 : if( !m_pBlockCrsr )
889 : {
890 0 : SwPosition aPos( *m_pCurCrsr->GetPoint() );
891 0 : m_pBlockCrsr = createBlockCursor( *this, aPos );
892 0 : SwShellCrsr &rBlock = m_pBlockCrsr->getShellCrsr();
893 0 : rBlock.GetPtPos() = m_pCurCrsr->GetPtPos();
894 0 : if( m_pCurCrsr->HasMark() )
895 : {
896 0 : rBlock.SetMark();
897 0 : *rBlock.GetMark() = *m_pCurCrsr->GetMark();
898 0 : rBlock.GetMkPos() = m_pCurCrsr->GetMkPos();
899 0 : }
900 : }
901 0 : m_pBlockCrsr->clearPoints();
902 0 : RefreshBlockCursor();
903 0 : }
904 :
905 320 : void SwCrsrShell::ClearMark()
906 : {
907 : // is there any GetMark?
908 320 : if( m_pTblCrsr )
909 : {
910 10 : while( m_pCurCrsr->GetNext() != m_pCurCrsr )
911 6 : delete m_pCurCrsr->GetNext();
912 2 : m_pTblCrsr->DeleteMark();
913 :
914 2 : m_pCurCrsr->DeleteMark();
915 :
916 2 : *m_pCurCrsr->GetPoint() = *m_pTblCrsr->GetPoint();
917 2 : m_pCurCrsr->GetPtPos() = m_pTblCrsr->GetPtPos();
918 2 : delete m_pTblCrsr, m_pTblCrsr = 0;
919 2 : m_pCurCrsr->SwSelPaintRects::Show();
920 : }
921 : else
922 : {
923 318 : if( !m_pCurCrsr->HasMark() )
924 542 : return;
925 96 : m_pCurCrsr->DeleteMark();
926 96 : if( !m_nCrsrMove )
927 94 : m_pCurCrsr->SwSelPaintRects::Show();
928 : }
929 : }
930 :
931 0 : void SwCrsrShell::NormalizePam(bool bPointFirst)
932 : {
933 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
934 0 : m_pCurCrsr->Normalize(bPointFirst);
935 0 : }
936 :
937 18 : void SwCrsrShell::SwapPam()
938 : {
939 18 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
940 18 : m_pCurCrsr->Exchange();
941 18 : }
942 :
943 : //TODO: provide documentation
944 : /** Search in the selected area for a Selection that covers the given point.
945 :
946 : If only a test run is made, then it checks if a SSelection exists but does
947 : not move the current cursor. In a normal run the cursor will be moved to the
948 : chosen SSelection.
949 :
950 : @param rPt The point to search at.
951 : @param bTstOnly Should I only do a test run? If true so do not move cursor.
952 : @param bTstHit ???
953 : */
954 0 : bool SwCrsrShell::ChgCurrPam(
955 : const Point & rPt,
956 : bool bTstOnly,
957 : bool bTstHit )
958 : {
959 0 : SET_CURR_SHELL( this );
960 :
961 : // check if the SPoint is in a table selection
962 0 : if( bTstOnly && m_pTblCrsr )
963 0 : return m_pTblCrsr->IsInside( rPt );
964 :
965 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
966 : // search position <rPt> in document
967 0 : SwPosition aPtPos( *m_pCurCrsr->GetPoint() );
968 0 : Point aPt( rPt );
969 :
970 0 : SwCrsrMoveState aTmpState( MV_NONE );
971 0 : aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
972 0 : if ( !GetLayout()->GetCrsrOfst( &aPtPos, aPt, &aTmpState ) && bTstHit )
973 0 : return false;
974 :
975 : // search in all selections for this position
976 0 : SwShellCrsr* pCmp = (SwShellCrsr*)m_pCurCrsr; // keep the pointer on cursor
977 0 : do {
978 0 : if( pCmp && pCmp->HasMark() &&
979 0 : *pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos )
980 : {
981 0 : if( bTstOnly || m_pCurCrsr == pCmp ) // is the current
982 0 : return true; // return without update
983 :
984 0 : m_pCurCrsr = pCmp;
985 0 : UpdateCrsr(); // cursor is already at the right position
986 0 : return true;
987 : }
988 0 : } while( m_pCurCrsr !=
989 0 : ( pCmp = dynamic_cast<SwShellCrsr*>(pCmp->GetNext()) ) );
990 0 : return false;
991 : }
992 :
993 324 : void SwCrsrShell::KillPams()
994 : {
995 : // Does any exist for deletion?
996 324 : if( !m_pTblCrsr && !m_pBlockCrsr && m_pCurCrsr->GetNext() == m_pCurCrsr )
997 642 : return;
998 :
999 18 : while( m_pCurCrsr->GetNext() != m_pCurCrsr )
1000 6 : delete m_pCurCrsr->GetNext();
1001 6 : m_pCurCrsr->SetColumnSelection( false );
1002 :
1003 6 : if( m_pTblCrsr )
1004 : {
1005 : // delete the ring of cursors
1006 6 : m_pCurCrsr->DeleteMark();
1007 6 : *m_pCurCrsr->GetPoint() = *m_pTblCrsr->GetPoint();
1008 6 : m_pCurCrsr->GetPtPos() = m_pTblCrsr->GetPtPos();
1009 6 : delete m_pTblCrsr;
1010 6 : m_pTblCrsr = 0;
1011 : }
1012 0 : else if( m_pBlockCrsr )
1013 : {
1014 : // delete the ring of cursors
1015 0 : m_pCurCrsr->DeleteMark();
1016 0 : SwShellCrsr &rBlock = m_pBlockCrsr->getShellCrsr();
1017 0 : *m_pCurCrsr->GetPoint() = *rBlock.GetPoint();
1018 0 : m_pCurCrsr->GetPtPos() = rBlock.GetPtPos();
1019 0 : rBlock.DeleteMark();
1020 0 : m_pBlockCrsr->clearPoints();
1021 : }
1022 6 : UpdateCrsr( SwCrsrShell::SCROLLWIN );
1023 : }
1024 :
1025 0 : int SwCrsrShell::CompareCursor( CrsrCompareType eType ) const
1026 : {
1027 0 : int nRet = 0;
1028 0 : const SwPosition *pFirst = 0, *pSecond = 0;
1029 0 : const SwPaM *pCur = GetCrsr(), *pStk = m_pCrsrStk;
1030 : // cursor on stack is needed if we compare against stack
1031 0 : if( pStk || ( eType == CurrPtCurrMk ) )
1032 : {
1033 0 : switch ( eType)
1034 : {
1035 : case StackPtStackMk:
1036 0 : pFirst = pStk->GetPoint();
1037 0 : pSecond = pStk->GetMark();
1038 0 : break;
1039 : case StackPtCurrPt:
1040 0 : pFirst = pStk->GetPoint();
1041 0 : pSecond = pCur->GetPoint();
1042 0 : break;
1043 : case StackPtCurrMk:
1044 0 : pFirst = pStk->GetPoint();
1045 0 : pSecond = pCur->GetMark();
1046 0 : break;
1047 : case StackMkCurrPt:
1048 0 : pFirst = pStk->GetMark();
1049 0 : pSecond = pCur->GetPoint();
1050 0 : break;
1051 : case StackMkCurrMk:
1052 0 : pFirst = pStk->GetMark();
1053 0 : pSecond = pStk->GetMark();
1054 0 : break;
1055 : case CurrPtCurrMk:
1056 0 : pFirst = pCur->GetPoint();
1057 0 : pSecond = pCur->GetMark();
1058 0 : break;
1059 : }
1060 : }
1061 0 : if( !pFirst || !pSecond )
1062 0 : nRet = INT_MAX;
1063 0 : else if( *pFirst < *pSecond )
1064 0 : nRet = -1;
1065 0 : else if( *pFirst == *pSecond )
1066 0 : nRet = 0;
1067 : else
1068 0 : nRet = 1;
1069 0 : return nRet;
1070 : }
1071 :
1072 0 : bool SwCrsrShell::IsSttPara() const
1073 0 : { return m_pCurCrsr->GetPoint()->nContent == 0; }
1074 :
1075 0 : bool SwCrsrShell::IsEndPara() const
1076 0 : { return m_pCurCrsr->GetPoint()->nContent == m_pCurCrsr->GetCntntNode()->Len(); }
1077 :
1078 0 : bool SwCrsrShell::IsEndOfTable() const
1079 : {
1080 0 : if (IsTableMode() || IsBlockMode() || !IsEndPara())
1081 : {
1082 0 : return false;
1083 : }
1084 0 : SwTableNode const*const pTableNode( IsCrsrInTbl() );
1085 0 : if (!pTableNode)
1086 : {
1087 0 : return false;
1088 : }
1089 0 : SwEndNode const*const pEndTableNode(pTableNode->EndOfSectionNode());
1090 0 : SwNodeIndex const lastNode(*pEndTableNode, -2);
1091 : SAL_WARN_IF(!lastNode.GetNode().GetTxtNode(), "sw.core",
1092 : "text node expected");
1093 0 : return (lastNode == m_pCurCrsr->GetPoint()->nNode);
1094 : }
1095 :
1096 82 : bool SwCrsrShell::IsInFrontOfLabel() const
1097 : {
1098 82 : return m_pCurCrsr->IsInFrontOfLabel();
1099 : }
1100 :
1101 76 : bool SwCrsrShell::SetInFrontOfLabel( bool bNew )
1102 : {
1103 76 : if ( bNew != IsInFrontOfLabel() )
1104 : {
1105 0 : m_pCurCrsr->_SetInFrontOfLabel( bNew );
1106 0 : UpdateMarkedListLevel();
1107 0 : return true;
1108 : }
1109 76 : return false;
1110 : }
1111 :
1112 6 : bool SwCrsrShell::GotoPage( sal_uInt16 nPage )
1113 : {
1114 6 : SET_CURR_SHELL( this );
1115 12 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
1116 12 : SwCrsrSaveState aSaveState( *m_pCurCrsr );
1117 12 : bool bRet = GetLayout()->SetCurrPage( m_pCurCrsr, nPage ) &&
1118 : !m_pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1119 12 : nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1120 6 : if( bRet )
1121 6 : UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
1122 12 : return bRet;
1123 : }
1124 :
1125 0 : bool SwCrsrShell::GetCharRectAt(SwRect& rRect, const SwPosition* pPos)
1126 : {
1127 0 : SwCntntFrm* pFrm = GetCurrFrm();
1128 0 : return pFrm->GetCharRect( rRect, *pPos );
1129 : }
1130 :
1131 1689 : void SwCrsrShell::GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum,
1132 : bool bAtCrsrPos, const bool bCalcFrm )
1133 : {
1134 1689 : SET_CURR_SHELL( this );
1135 : // page number: first visible page or the one at the cursor
1136 : const SwCntntFrm* pCFrm;
1137 1689 : const SwPageFrm *pPg = 0;
1138 :
1139 3378 : if( !bAtCrsrPos || 0 == (pCFrm = GetCurrFrm( bCalcFrm )) ||
1140 1689 : 0 == (pPg = pCFrm->FindPageFrm()) )
1141 : {
1142 0 : pPg = Imp()->GetFirstVisPage();
1143 0 : while( pPg && pPg->IsEmptyPage() )
1144 0 : pPg = (const SwPageFrm *)pPg->GetNext();
1145 : }
1146 : // pPg has to exist with a default of 1 for the special case "Writerstart"
1147 1689 : rnPhyNum = pPg? pPg->GetPhyPageNum() : 1;
1148 1689 : rnVirtNum = pPg? pPg->GetVirtPageNum() : 1;
1149 1689 : }
1150 :
1151 0 : sal_uInt16 SwCrsrShell::GetNextPrevPageNum( bool bNext )
1152 : {
1153 0 : SET_CURR_SHELL( this );
1154 : // page number: first visible page or the one at the cursor
1155 0 : const SwPageFrm *pPg = Imp()->GetFirstVisPage();
1156 0 : if( pPg )
1157 : {
1158 0 : const SwTwips nPageTop = pPg->Frm().Top();
1159 :
1160 0 : if( bNext )
1161 : {
1162 : // go to next view layout row:
1163 0 : do
1164 : {
1165 0 : pPg = (const SwPageFrm *)pPg->GetNext();
1166 : }
1167 0 : while( pPg && pPg->Frm().Top() == nPageTop );
1168 :
1169 0 : while( pPg && pPg->IsEmptyPage() )
1170 0 : pPg = (const SwPageFrm *)pPg->GetNext();
1171 : }
1172 : else
1173 : {
1174 : // go to previous view layout row:
1175 0 : do
1176 : {
1177 0 : pPg = (const SwPageFrm *)pPg->GetPrev();
1178 : }
1179 0 : while( pPg && pPg->Frm().Top() == nPageTop );
1180 :
1181 0 : while( pPg && pPg->IsEmptyPage() )
1182 0 : pPg = (const SwPageFrm *)pPg->GetPrev();
1183 : }
1184 : }
1185 : // pPg has to exist with a default of 1 for the special case "Writerstart"
1186 0 : return pPg ? pPg->GetPhyPageNum() : USHRT_MAX;
1187 : }
1188 :
1189 2608 : sal_uInt16 SwCrsrShell::GetPageCnt()
1190 : {
1191 2608 : SET_CURR_SHELL( this );
1192 : // return number of pages
1193 2608 : return GetLayout()->GetPageNum();
1194 : }
1195 :
1196 : /// go to the next SSelection
1197 0 : bool SwCrsrShell::GoNextCrsr()
1198 : {
1199 : // is there a ring of cursors?
1200 0 : if( m_pCurCrsr->GetNext() == m_pCurCrsr )
1201 0 : return false;
1202 :
1203 0 : SET_CURR_SHELL( this );
1204 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
1205 0 : m_pCurCrsr = dynamic_cast<SwShellCrsr*>(m_pCurCrsr->GetNext());
1206 :
1207 : // #i24086#: show also all others
1208 0 : if( !ActionPend() )
1209 : {
1210 0 : UpdateCrsr();
1211 0 : m_pCurCrsr->Show();
1212 : }
1213 0 : return true;
1214 : }
1215 :
1216 : /// go to the previous SSelection
1217 0 : bool SwCrsrShell::GoPrevCrsr()
1218 : {
1219 : // is there a ring of cursors?
1220 0 : if( m_pCurCrsr->GetNext() == m_pCurCrsr )
1221 0 : return false;
1222 :
1223 0 : SET_CURR_SHELL( this );
1224 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
1225 0 : m_pCurCrsr = dynamic_cast<SwShellCrsr*>(m_pCurCrsr->GetPrev());
1226 :
1227 : // #i24086#: show also all others
1228 0 : if( !ActionPend() )
1229 : {
1230 0 : UpdateCrsr();
1231 0 : m_pCurCrsr->Show();
1232 : }
1233 0 : return true;
1234 : }
1235 :
1236 6795 : void SwCrsrShell::Paint( const Rectangle &rRect)
1237 : {
1238 6795 : comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll(/*bFootnotes =*/ false));
1239 13590 : SET_CURR_SHELL( this );
1240 :
1241 : // always switch off all cursors when painting
1242 6795 : SwRect aRect( rRect );
1243 :
1244 6795 : bool bVis = false;
1245 : // if a cursor is visible then hide the SV cursor
1246 6795 : if( m_pVisCrsr->IsVisible() && !aRect.IsOver( m_aCharRect ) )
1247 : {
1248 1902 : bVis = true;
1249 1902 : m_pVisCrsr->Hide();
1250 : }
1251 :
1252 : // re-paint area
1253 6795 : SwViewShell::Paint( rRect );
1254 :
1255 6795 : if( m_bHasFocus && !m_bBasicHideCrsr )
1256 : {
1257 6768 : SwShellCrsr* pAktCrsr = m_pTblCrsr ? m_pTblCrsr : m_pCurCrsr;
1258 :
1259 6768 : if( !ActionPend() )
1260 : {
1261 : // so that right/bottom borders will not be cropped
1262 2529 : pAktCrsr->Invalidate( VisArea() );
1263 2529 : pAktCrsr->Show();
1264 : }
1265 : else
1266 4239 : pAktCrsr->Invalidate( aRect );
1267 :
1268 : }
1269 6795 : if( m_bSVCrsrVis && bVis ) // also show SV cursor again
1270 8601 : m_pVisCrsr->Show();
1271 6795 : }
1272 :
1273 22066 : void SwCrsrShell::VisPortChgd( const SwRect & rRect )
1274 : {
1275 22066 : SET_CURR_SHELL( this );
1276 : bool bVis; // switch off all cursors when scrolling
1277 :
1278 : // if a cursor is visible then hide the SV cursor
1279 22066 : if( ( bVis = m_pVisCrsr->IsVisible() ) )
1280 17124 : m_pVisCrsr->Hide();
1281 :
1282 22066 : m_bVisPortChgd = true;
1283 22066 : m_aOldRBPos.setX(VisArea().Right());
1284 22066 : m_aOldRBPos.setY(VisArea().Bottom());
1285 :
1286 : // For not having problems with the SV cursor, Update() is called for the
1287 : // Window in SwViewShell::VisPo...
1288 : // During painting no selections should be shown, thus the call is encapsulated. <- TODO: old artefact?
1289 22066 : SwViewShell::VisPortChgd( rRect ); // move area
1290 :
1291 22066 : if( m_bSVCrsrVis && bVis ) // show SV cursor again
1292 17118 : m_pVisCrsr->Show();
1293 :
1294 22066 : if( m_nCrsrMove )
1295 2 : m_bInCMvVisportChgd = true;
1296 :
1297 22066 : m_bVisPortChgd = false;
1298 22066 : }
1299 :
1300 : /** Set the cursor back into content.
1301 :
1302 : This should only be called if the cursor was move somewhere else (e.g. when
1303 : deleting a border). The new position is calculated from its current position
1304 : in the layout.
1305 : */
1306 76236 : void SwCrsrShell::UpdateCrsrPos()
1307 : {
1308 76236 : SET_CURR_SHELL( this );
1309 76236 : ++mnStartAction;
1310 76236 : SwShellCrsr* pShellCrsr = getShellCrsr( true );
1311 76236 : Size aOldSz( GetDocSize() );
1312 :
1313 76236 : if( isInHiddenTxtFrm(pShellCrsr) )
1314 : {
1315 57 : SwCrsrMoveState aTmpState( MV_NONE );
1316 57 : aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1317 114 : GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
1318 114 : &aTmpState );
1319 57 : pShellCrsr->DeleteMark();
1320 : }
1321 76236 : IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
1322 76236 : if( pGrammarContact )
1323 76236 : pGrammarContact->updateCursorPosition( *m_pCurCrsr->GetPoint() );
1324 76236 : --mnStartAction;
1325 76236 : if( aOldSz != GetDocSize() )
1326 0 : SizeChgNotify();
1327 76236 : }
1328 :
1329 : // #i65475# - if Point/Mark in hidden sections, move them out
1330 44 : static bool lcl_CheckHiddenSection( SwNodeIndex& rIdx )
1331 : {
1332 44 : bool bOk = true;
1333 44 : const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
1334 44 : if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
1335 : {
1336 0 : SwNodeIndex aTmp( *pSectNd );
1337 : const SwNode* pFrmNd =
1338 0 : rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
1339 0 : bOk = pFrmNd != NULL;
1340 : SAL_WARN_IF(!bOk, "sw", "found no Node with Frames");
1341 0 : rIdx = aTmp;
1342 : }
1343 44 : return bOk;
1344 : }
1345 :
1346 : /// Try to set the cursor to the next visible content node.
1347 44 : static void lcl_CheckHiddenPara( SwPosition& rPos )
1348 : {
1349 44 : SwNodeIndex aTmp( rPos.nNode );
1350 44 : SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
1351 88 : while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
1352 : {
1353 0 : SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
1354 0 : if ( pCntnt && pCntnt->IsTxtNode() )
1355 0 : pTxtNd = (SwTxtNode*)pCntnt;
1356 : else
1357 0 : pTxtNd = 0;
1358 : }
1359 :
1360 44 : if ( pTxtNd )
1361 44 : rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
1362 44 : }
1363 :
1364 : // #i27301# - helper class that notifies the accessibility about invalid text
1365 : // selections in its destructor
1366 : class SwNotifyAccAboutInvalidTextSelections
1367 : {
1368 : private:
1369 : SwCrsrShell& mrCrsrSh;
1370 :
1371 : public:
1372 76258 : SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
1373 76258 : : mrCrsrSh( _rCrsrSh )
1374 76258 : {}
1375 :
1376 76258 : ~SwNotifyAccAboutInvalidTextSelections()
1377 : {
1378 76258 : mrCrsrSh.InvalidateAccessibleParaTextSelection();
1379 76258 : }
1380 : };
1381 :
1382 77814 : void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, bool bIdleEnd )
1383 : {
1384 77814 : SET_CURR_SHELL( this );
1385 77814 : ClearUpCrsrs();
1386 :
1387 : // In a BasicAction the cursor must be updated, e.g. to create the
1388 : // TableCursor. EndAction now calls UpdateCrsr!
1389 77814 : if( ActionPend() && BasicActionPend() )
1390 : {
1391 1556 : if ( eFlags & SwCrsrShell::READONLY )
1392 24 : m_bIgnoreReadonly = true;
1393 1556 : return; // if not then no update
1394 : }
1395 :
1396 152494 : SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
1397 :
1398 76258 : if ( m_bIgnoreReadonly )
1399 : {
1400 20 : m_bIgnoreReadonly = false;
1401 20 : eFlags |= SwCrsrShell::READONLY;
1402 : }
1403 :
1404 76258 : if( eFlags & SwCrsrShell::CHKRANGE ) // check all cursor moves for
1405 76252 : CheckRange( m_pCurCrsr ); // overlapping ranges
1406 :
1407 76258 : if( !bIdleEnd )
1408 71604 : CheckTblBoxCntnt();
1409 :
1410 : // If the current cursor is in a table and point/mark in different boxes,
1411 : // then the table mode is active (also if it is already active: m_pTblCrsr)
1412 76258 : SwPaM* pTstCrsr = getShellCrsr( true );
1413 153106 : if( pTstCrsr->HasMark() && !m_pBlockCrsr &&
1414 343 : mpDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
1415 32 : ( m_pTblCrsr ||
1416 32 : pTstCrsr->GetNode( true ).StartOfSectionNode() !=
1417 76338 : pTstCrsr->GetNode( false ).StartOfSectionNode() ) && !mbSelectAll)
1418 : {
1419 22 : SwShellCrsr* pITmpCrsr = getShellCrsr( true );
1420 22 : Point aTmpPt( pITmpCrsr->GetPtPos() );
1421 22 : Point aTmpMk( pITmpCrsr->GetMkPos() );
1422 22 : SwPosition* pPos = pITmpCrsr->GetPoint();
1423 :
1424 : // Bug 65475 (1999) - if Point/Mark in hidden sections, move them out
1425 22 : lcl_CheckHiddenSection( pPos->nNode );
1426 22 : lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
1427 :
1428 : // Move cursor out of hidden paragraphs
1429 22 : if ( !GetViewOptions()->IsShowHiddenChar() )
1430 : {
1431 22 : lcl_CheckHiddenPara( *pPos );
1432 22 : lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
1433 : }
1434 :
1435 22 : SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
1436 44 : getLayoutFrm( GetLayout(), &aTmpPt, pPos, false );
1437 :
1438 : OSL_ENSURE( pTblFrm, "Tabelle Crsr nicht im Content ??" );
1439 :
1440 : // --> Make code robust. The table cursor may point
1441 : // to a table in a currently inactive header.
1442 22 : SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
1443 :
1444 22 : if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
1445 : {
1446 : // First check if point is in repeated headline:
1447 0 : bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
1448 :
1449 : // Second check if mark is in repeated headline:
1450 0 : if ( !bInRepeatedHeadline )
1451 : {
1452 : SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( false )->
1453 0 : getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), false );
1454 : OSL_ENSURE( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
1455 :
1456 0 : if ( pMarkTblFrm )
1457 : {
1458 0 : SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
1459 : OSL_ENSURE( pMarkTab, "Tabelle Crsr nicht im Content ??" );
1460 :
1461 : // Make code robust:
1462 0 : if ( pMarkTab )
1463 : {
1464 0 : bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
1465 : }
1466 : }
1467 : }
1468 :
1469 : // No table cursor in repeated headlines:
1470 0 : if ( bInRepeatedHeadline )
1471 : {
1472 0 : pTblFrm = 0;
1473 :
1474 0 : SwPosSection fnPosSect = *pPos < *pITmpCrsr->GetMark()
1475 : ? fnSectionStart
1476 0 : : fnSectionEnd;
1477 :
1478 : // then only select inside the Box
1479 0 : if( m_pTblCrsr )
1480 : {
1481 0 : m_pCurCrsr->SetMark();
1482 0 : *m_pCurCrsr->GetMark() = *m_pTblCrsr->GetMark();
1483 0 : m_pCurCrsr->GetMkPos() = m_pTblCrsr->GetMkPos();
1484 0 : m_pTblCrsr->DeleteMark();
1485 0 : m_pTblCrsr->SwSelPaintRects::Hide();
1486 : }
1487 :
1488 0 : *m_pCurCrsr->GetPoint() = *m_pCurCrsr->GetMark();
1489 0 : (*fnSectionCurr)( *m_pCurCrsr, fnPosSect );
1490 : }
1491 : }
1492 :
1493 : // we really want a table selection
1494 22 : if( pTab && pTblFrm )
1495 : {
1496 22 : if( !m_pTblCrsr )
1497 : {
1498 : m_pTblCrsr = new SwShellTableCrsr( *this,
1499 12 : *m_pCurCrsr->GetMark(), m_pCurCrsr->GetMkPos(),
1500 12 : *pPos, aTmpPt );
1501 6 : m_pCurCrsr->DeleteMark();
1502 6 : m_pCurCrsr->SwSelPaintRects::Hide();
1503 :
1504 6 : CheckTblBoxCntnt();
1505 6 : if(!m_pTblCrsr)
1506 : {
1507 : SAL_WARN("sw", "fdo#74854: "
1508 : "this should not happen, but better lose the selection "
1509 : "rather than crashing");
1510 0 : return;
1511 : }
1512 : }
1513 :
1514 22 : SwCrsrMoveState aTmpState( MV_NONE );
1515 22 : aTmpState.bRealHeight = true;
1516 22 : if( !pTblFrm->GetCharRect( m_aCharRect, *m_pTblCrsr->GetPoint(), &aTmpState ) )
1517 : {
1518 0 : Point aCentrPt( m_aCharRect.Center() );
1519 0 : aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1520 0 : pTblFrm->GetCrsrOfst( m_pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
1521 : bool const bResult =
1522 0 : pTblFrm->GetCharRect( m_aCharRect, *m_pTblCrsr->GetPoint() );
1523 : OSL_ENSURE( bResult, "GetCharRect failed." );
1524 : (void) bResult; // non-debug: unused
1525 : }
1526 :
1527 22 : m_pVisCrsr->Hide(); // always hide visible Cursor
1528 : // scroll Cursor to visible area
1529 66 : if( (eFlags & SwCrsrShell::SCROLLWIN) &&
1530 22 : (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1531 0 : !IsCrsrReadonly()) )
1532 : {
1533 22 : SwFrm* pBoxFrm = pTblFrm;
1534 66 : while( pBoxFrm && !pBoxFrm->IsCellFrm() )
1535 22 : pBoxFrm = pBoxFrm->GetUpper();
1536 22 : if( pBoxFrm && pBoxFrm->Frm().HasArea() )
1537 22 : MakeVisible( pBoxFrm->Frm() );
1538 : else
1539 0 : MakeVisible( m_aCharRect );
1540 : }
1541 :
1542 : // let Layout create the Cursors in the Boxes
1543 22 : if( m_pTblCrsr->IsCrsrMovedUpdt() )
1544 2 : GetLayout()->MakeTblCrsrs( *m_pTblCrsr );
1545 22 : if( m_bHasFocus && !m_bBasicHideCrsr )
1546 22 : m_pTblCrsr->Show();
1547 :
1548 : // set Cursor-Points to the new Positions
1549 22 : m_pTblCrsr->GetPtPos().setX(m_aCharRect.Left());
1550 22 : m_pTblCrsr->GetPtPos().setY(m_aCharRect.Top());
1551 :
1552 22 : if( m_bSVCrsrVis )
1553 : {
1554 22 : m_aCrsrHeight.setX(0);
1555 22 : m_aCrsrHeight.setY(aTmpState.aRealHeight.getY() < 0 ?
1556 22 : -m_aCharRect.Width() : m_aCharRect.Height());
1557 22 : m_pVisCrsr->Show(); // show again
1558 : }
1559 22 : m_eMvState = MV_NONE; // state for cursor travelling - GetCrsrOfst
1560 22 : if( pTblFrm && Imp()->IsAccessible() )
1561 16 : Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
1562 22 : return;
1563 : }
1564 : }
1565 :
1566 76236 : if( m_pTblCrsr )
1567 : {
1568 : // delete Ring
1569 0 : while( m_pCurCrsr->GetNext() != m_pCurCrsr )
1570 0 : delete m_pCurCrsr->GetNext();
1571 0 : m_pCurCrsr->DeleteMark();
1572 0 : *m_pCurCrsr->GetPoint() = *m_pTblCrsr->GetPoint();
1573 0 : m_pCurCrsr->GetPtPos() = m_pTblCrsr->GetPtPos();
1574 0 : delete m_pTblCrsr, m_pTblCrsr = 0;
1575 : }
1576 :
1577 76236 : m_pVisCrsr->Hide(); // always hide visible Cursor
1578 :
1579 : // are we perhaps in a protected / hidden Section ?
1580 : {
1581 76236 : SwShellCrsr* pShellCrsr = getShellCrsr( true );
1582 76236 : bool bChgState = true;
1583 76236 : const SwSectionNode* pSectNd = pShellCrsr->GetNode().FindSectionNode();
1584 77469 : if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
1585 1233 : ( !IsReadOnlyAvailable() &&
1586 0 : pSectNd->GetSection().IsProtectFlag() &&
1587 0 : ( !mpDoc->GetDocShell() ||
1588 0 : !mpDoc->GetDocShell()->IsReadOnly() || m_bAllProtect )) ) )
1589 : {
1590 0 : if( !FindValidCntntNode( !HasDrawView() ||
1591 0 : 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1592 : {
1593 : // everything protected/hidden -> special mode
1594 0 : if( m_bAllProtect && !IsReadOnlyAvailable() &&
1595 0 : pSectNd->GetSection().IsProtectFlag() )
1596 0 : bChgState = false;
1597 : else
1598 : {
1599 0 : m_eMvState = MV_NONE; // state for cursor travelling
1600 0 : m_bAllProtect = true;
1601 0 : if( GetDoc()->GetDocShell() )
1602 : {
1603 0 : GetDoc()->GetDocShell()->SetReadOnlyUI( true );
1604 0 : CallChgLnk(); // notify UI!
1605 : }
1606 0 : return;
1607 : }
1608 : }
1609 : }
1610 76236 : if( bChgState )
1611 : {
1612 76236 : bool bWasAllProtect = m_bAllProtect;
1613 76236 : m_bAllProtect = false;
1614 76236 : if( bWasAllProtect && GetDoc()->GetDocShell() &&
1615 0 : GetDoc()->GetDocShell()->IsReadOnlyUI() )
1616 : {
1617 0 : GetDoc()->GetDocShell()->SetReadOnlyUI( false );
1618 0 : CallChgLnk(); // notify UI!
1619 : }
1620 : }
1621 : }
1622 :
1623 76236 : UpdateCrsrPos();
1624 :
1625 : // The cursor must always point into content; there's some code
1626 : // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
1627 : // loops _behind_ the last node in the selection, which always works if you
1628 : // are in content.) To achieve this, we'll force cursor(s) to point into
1629 : // content, if UpdateCrsrPos() hasn't already done so.
1630 76236 : SwPaM* pCmp = m_pCurCrsr;
1631 76236 : do
1632 : {
1633 : // start will move forwards, end will move backwards
1634 76236 : bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
1635 :
1636 : // move point; forward if it's the start, backwards if it's the end
1637 76236 : if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
1638 : pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
1639 0 : fnGoCntnt );
1640 :
1641 : // move mark (if exists); forward if it's the start, else backwards
1642 76236 : if( pCmp->HasMark() )
1643 : {
1644 270 : if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
1645 : {
1646 0 : pCmp->Exchange();
1647 0 : pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
1648 0 : fnGoCntnt );
1649 0 : pCmp->Exchange();
1650 : }
1651 : }
1652 :
1653 : // iterate to next PaM in ring
1654 76236 : pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
1655 : }
1656 76236 : while( pCmp != m_pCurCrsr );
1657 :
1658 76236 : SwRect aOld( m_aCharRect );
1659 76236 : bool bFirst = true;
1660 : SwCntntFrm *pFrm;
1661 76236 : int nLoopCnt = 100;
1662 76236 : SwShellCrsr* pShellCrsr = getShellCrsr( true );
1663 :
1664 76252 : do {
1665 : bool bAgainst;
1666 144240 : do {
1667 144240 : bAgainst = false;
1668 144240 : pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1669 288480 : &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), false );
1670 : // if the Frm doesn't exist anymore, the complete Layout has to be
1671 : // created, because there used to be a Frm here!
1672 144240 : if ( !pFrm )
1673 : {
1674 0 : do
1675 : {
1676 0 : CalcLayout();
1677 0 : pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1678 0 : &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), false );
1679 : } while( !pFrm );
1680 : }
1681 144240 : else if ( Imp()->IsIdleAction() )
1682 : // Guarantee everything's properly formatted
1683 14 : pFrm->PrepareCrsr();
1684 :
1685 : // In protected Fly? but ignore in case of frame selection
1686 288480 : if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
1687 0 : ( !Imp()->GetDrawView() ||
1688 144240 : !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
1689 0 : (!mpDoc->GetDocShell() ||
1690 0 : !mpDoc->GetDocShell()->IsReadOnly() || m_bAllProtect ) )
1691 : {
1692 : // look for a valid position
1693 0 : bool bChgState = true;
1694 0 : if( !FindValidCntntNode(!HasDrawView() ||
1695 0 : 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1696 : {
1697 : // everything is protected / hidden -> special Mode
1698 0 : if( m_bAllProtect )
1699 0 : bChgState = false;
1700 : else
1701 : {
1702 0 : m_eMvState = MV_NONE; // state for crusor travelling
1703 0 : m_bAllProtect = true;
1704 0 : if( GetDoc()->GetDocShell() )
1705 : {
1706 0 : GetDoc()->GetDocShell()->SetReadOnlyUI( true );
1707 0 : CallChgLnk(); // notify UI!
1708 : }
1709 0 : return;
1710 : }
1711 : }
1712 :
1713 0 : if( bChgState )
1714 : {
1715 0 : bool bWasAllProtect = m_bAllProtect;
1716 0 : m_bAllProtect = false;
1717 0 : if( bWasAllProtect && GetDoc()->GetDocShell() &&
1718 0 : GetDoc()->GetDocShell()->IsReadOnlyUI() )
1719 : {
1720 0 : GetDoc()->GetDocShell()->SetReadOnlyUI( false );
1721 0 : CallChgLnk(); // notify UI!
1722 : }
1723 0 : m_bAllProtect = false;
1724 0 : bAgainst = true; // look for the right Frm again
1725 : }
1726 : }
1727 : } while( bAgainst );
1728 :
1729 144240 : if( !( eFlags & SwCrsrShell::NOCALRECT ))
1730 : {
1731 144240 : SwCrsrMoveState aTmpState( m_eMvState );
1732 144240 : aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1733 144240 : aTmpState.bRealHeight = true;
1734 144240 : aTmpState.bRealWidth = IsOverwriteCrsr();
1735 144240 : aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
1736 :
1737 : // #i27615#,#i30453#
1738 144240 : SwSpecialPos aSpecialPos;
1739 144240 : aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
1740 144240 : if (pShellCrsr->IsInFrontOfLabel())
1741 : {
1742 0 : aTmpState.pSpecialPos = &aSpecialPos;
1743 : }
1744 :
1745 144240 : if( !pFrm->GetCharRect( m_aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
1746 : {
1747 254 : Point& rPt = pShellCrsr->GetPtPos();
1748 254 : rPt = m_aCharRect.Center();
1749 254 : pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
1750 : }
1751 :
1752 144240 : if( !pShellCrsr->HasMark() )
1753 143704 : m_aCrsrHeight = aTmpState.aRealHeight;
1754 : else
1755 : {
1756 536 : m_aCrsrHeight.setX(0);
1757 536 : m_aCrsrHeight.setY(aTmpState.aRealHeight.getY() < 0 ?
1758 536 : -m_aCharRect.Width() : m_aCharRect.Height());
1759 : }
1760 : }
1761 : else
1762 : {
1763 0 : m_aCrsrHeight.setX(0);
1764 0 : m_aCrsrHeight.setY(m_aCharRect.Height());
1765 : }
1766 :
1767 144240 : if( !bFirst && aOld == m_aCharRect )
1768 67988 : break;
1769 :
1770 : // if the layout says that we are after the 100th iteration still in
1771 : // flow then we should always take the current position for granted.
1772 : // (see bug: 29658)
1773 76252 : if( !--nLoopCnt )
1774 : {
1775 : OSL_ENSURE( false, "endless loop? CharRect != OldCharRect ");
1776 0 : break;
1777 : }
1778 76252 : aOld = m_aCharRect;
1779 76252 : bFirst = false;
1780 :
1781 : // update cursor Points to the new Positions
1782 76252 : pShellCrsr->GetPtPos().setX(m_aCharRect.Left());
1783 76252 : pShellCrsr->GetPtPos().setY(m_aCharRect.Top());
1784 :
1785 76252 : if( !(eFlags & SwCrsrShell::UPDOWN )) // delete old Pos. of Up/Down
1786 : {
1787 4972 : pFrm->Calc();
1788 4972 : m_nUpDownX = pFrm->IsVertical() ?
1789 0 : m_aCharRect.Top() - pFrm->Frm().Top() :
1790 4972 : m_aCharRect.Left() - pFrm->Frm().Left();
1791 : }
1792 :
1793 : // scroll Cursor to visible area
1794 211995 : if( m_bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
1795 203004 : (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1796 67515 : !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
1797 : {
1798 : // in case of scrolling this EndAction doesn't show the SV cursor
1799 : // again, thus save and reset the flag here
1800 67863 : bool bSav = m_bSVCrsrVis;
1801 67863 : m_bSVCrsrVis = false;
1802 67863 : MakeSelVisible();
1803 67863 : m_bSVCrsrVis = bSav;
1804 : }
1805 :
1806 76252 : } while( eFlags & SwCrsrShell::SCROLLWIN );
1807 :
1808 76236 : if( m_pBlockCrsr )
1809 0 : RefreshBlockCursor();
1810 :
1811 76236 : if( !bIdleEnd && m_bHasFocus && !m_bBasicHideCrsr )
1812 : {
1813 71458 : if( m_pTblCrsr )
1814 0 : m_pTblCrsr->SwSelPaintRects::Show();
1815 : else
1816 : {
1817 71458 : m_pCurCrsr->SwSelPaintRects::Show();
1818 71458 : if( m_pBlockCrsr )
1819 : {
1820 0 : SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(m_pCurCrsr->GetNext());
1821 0 : while( pNxt && pNxt != m_pCurCrsr )
1822 : {
1823 0 : pNxt->SwSelPaintRects::Show();
1824 0 : pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
1825 : }
1826 : }
1827 : }
1828 : }
1829 :
1830 76236 : m_eMvState = MV_NONE; // state for cursor tavelling - GetCrsrOfst
1831 :
1832 76236 : if( pFrm && Imp()->IsAccessible() )
1833 143 : Imp()->InvalidateAccessibleCursorPosition( pFrm );
1834 :
1835 : // switch from blinking cursor to read-only-text-selection cursor
1836 : static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
1837 76236 : const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
1838 76236 : GetCursorBlinkTime();
1839 :
1840 152472 : if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
1841 76236 : ( nBlinkTime != nNoBlinkTime ) )
1842 : {
1843 : // non blinking cursor in read only - text selection mode
1844 76236 : AllSettings aSettings = GetOut()->GetSettings();
1845 152472 : StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1846 : const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
1847 76236 : Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
1848 152472 : nNoBlinkTime;
1849 76236 : aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
1850 76236 : aSettings.SetStyleSettings( aStyleSettings );
1851 152472 : GetOut()->SetSettings( aSettings );
1852 : }
1853 :
1854 76236 : if( m_bSVCrsrVis )
1855 151402 : m_pVisCrsr->Show(); // show again
1856 : }
1857 :
1858 0 : void SwCrsrShell::RefreshBlockCursor()
1859 : {
1860 : OSL_ENSURE( m_pBlockCrsr, "Don't call me without a block cursor" );
1861 0 : SwShellCrsr &rBlock = m_pBlockCrsr->getShellCrsr();
1862 0 : Point aPt = rBlock.GetPtPos();
1863 0 : SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), false );
1864 0 : Point aMk;
1865 0 : if( m_pBlockCrsr->getEndPoint() && m_pBlockCrsr->getStartPoint() )
1866 : {
1867 0 : aPt = *m_pBlockCrsr->getStartPoint();
1868 0 : aMk = *m_pBlockCrsr->getEndPoint();
1869 : }
1870 : else
1871 : {
1872 0 : aPt = rBlock.GetPtPos();
1873 0 : if( pFrm )
1874 : {
1875 0 : if( pFrm->IsVertical() )
1876 0 : aPt.setY(pFrm->Frm().Top() + GetUpDownX());
1877 : else
1878 0 : aPt.setX(pFrm->Frm().Left() + GetUpDownX());
1879 : }
1880 0 : aMk = rBlock.GetMkPos();
1881 : }
1882 0 : SwRect aRect( aMk, aPt );
1883 0 : aRect.Justify();
1884 0 : SwSelectionList aSelList( pFrm );
1885 :
1886 0 : if( GetLayout()->FillSelection( aSelList, aRect ) )
1887 : {
1888 0 : SwCursor* pNxt = (SwCursor*)m_pCurCrsr->GetNext();
1889 0 : while( pNxt != m_pCurCrsr )
1890 : {
1891 0 : delete pNxt;
1892 0 : pNxt = (SwCursor*)m_pCurCrsr->GetNext();
1893 : }
1894 :
1895 0 : std::list<SwPaM*>::iterator pStart = aSelList.getStart();
1896 0 : std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
1897 : OSL_ENSURE( pPam != pStart, "FillSelection should deliver at least one PaM" );
1898 0 : m_pCurCrsr->SetMark();
1899 0 : --pPam;
1900 : // If there is only one text portion inside the rectangle, a simple
1901 : // selection is created
1902 0 : if( pPam == pStart )
1903 : {
1904 0 : *m_pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
1905 0 : if( (*pPam)->HasMark() )
1906 0 : *m_pCurCrsr->GetMark() = *(*pPam)->GetMark();
1907 : else
1908 0 : m_pCurCrsr->DeleteMark();
1909 0 : delete *pPam;
1910 0 : m_pCurCrsr->SetColumnSelection( false );
1911 : }
1912 : else
1913 : {
1914 : // The order of the SwSelectionList has to be preserved but
1915 : // the order inside the ring created by CreateCrsr() is not like
1916 : // expected => First create the selections before the last one
1917 : // downto the first selection.
1918 : // At least create the cursor for the last selection
1919 0 : --pPam;
1920 0 : *m_pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
1921 0 : if( (*pPam)->HasMark() )
1922 0 : *m_pCurCrsr->GetMark() = *(*pPam)->GetMark();
1923 : else
1924 0 : m_pCurCrsr->DeleteMark();
1925 0 : delete *pPam;
1926 0 : m_pCurCrsr->SetColumnSelection( true );
1927 0 : while( pPam != pStart )
1928 : {
1929 0 : --pPam;
1930 :
1931 0 : SwShellCrsr* pNew = new SwShellCrsr( *m_pCurCrsr );
1932 0 : pNew->insert( pNew->begin(), m_pCurCrsr->begin(), m_pCurCrsr->end());
1933 0 : m_pCurCrsr->clear();
1934 0 : m_pCurCrsr->DeleteMark();
1935 :
1936 0 : *m_pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
1937 0 : if( (*pPam)->HasMark() )
1938 : {
1939 0 : m_pCurCrsr->SetMark();
1940 0 : *m_pCurCrsr->GetMark() = *(*pPam)->GetMark();
1941 : }
1942 : else
1943 0 : m_pCurCrsr->DeleteMark();
1944 0 : m_pCurCrsr->SetColumnSelection( true );
1945 0 : delete *pPam;
1946 : }
1947 : {
1948 0 : SwShellCrsr* pNew = new SwShellCrsr( *m_pCurCrsr );
1949 0 : pNew->insert( pNew->begin(), m_pCurCrsr->begin(), m_pCurCrsr->end() );
1950 0 : m_pCurCrsr->clear();
1951 0 : m_pCurCrsr->DeleteMark();
1952 : }
1953 0 : pPam = aSelList.getEnd();
1954 0 : --pPam;
1955 0 : *m_pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
1956 0 : if( (*pPam)->HasMark() )
1957 : {
1958 0 : m_pCurCrsr->SetMark();
1959 0 : *m_pCurCrsr->GetMark() = *(*pPam)->GetMark();
1960 : }
1961 : else
1962 0 : m_pCurCrsr->DeleteMark();
1963 0 : m_pCurCrsr->SetColumnSelection( true );
1964 0 : delete *pPam;
1965 : }
1966 0 : }
1967 0 : }
1968 :
1969 : /// create a copy of the cursor and save it in the stack
1970 948 : void SwCrsrShell::Push()
1971 : {
1972 : // fdo#60513: if we have a table cursor, copy that; else copy current.
1973 : // This seems to work because UpdateCrsr() will fix this up on Pop(),
1974 : // then MakeBoxSels() will re-create the current m_pCurCrsr cell ring.
1975 948 : SwShellCrsr *const pCurrent((m_pTblCrsr) ? m_pTblCrsr : m_pCurCrsr);
1976 948 : m_pCrsrStk = new SwShellCrsr( *this, *pCurrent->GetPoint(),
1977 948 : pCurrent->GetPtPos(), m_pCrsrStk );
1978 :
1979 948 : if (pCurrent->HasMark())
1980 : {
1981 10 : m_pCrsrStk->SetMark();
1982 10 : *m_pCrsrStk->GetMark() = *pCurrent->GetMark();
1983 : }
1984 948 : }
1985 :
1986 : /** delete cursor
1987 :
1988 : @param bOldCrsr If <true> so delete from stack, if <false> delete current
1989 : and assign the one from stack as the new current cursor.
1990 : @return <true> if there was one on the stack, <false> otherwise
1991 : */
1992 948 : bool SwCrsrShell::Pop( bool bOldCrsr )
1993 : {
1994 948 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
1995 :
1996 : // are there any left?
1997 948 : if( 0 == m_pCrsrStk )
1998 0 : return false;
1999 :
2000 948 : SwShellCrsr *pTmp = 0, *pOldStk = m_pCrsrStk;
2001 :
2002 : // the successor becomes the current one
2003 948 : if( m_pCrsrStk->GetNext() != m_pCrsrStk )
2004 : {
2005 6 : pTmp = dynamic_cast<SwShellCrsr*>(m_pCrsrStk->GetNext());
2006 : }
2007 :
2008 948 : if( bOldCrsr ) // delete from stack
2009 906 : delete m_pCrsrStk;
2010 :
2011 948 : m_pCrsrStk = pTmp; // assign new one
2012 :
2013 948 : if( !bOldCrsr )
2014 : {
2015 42 : SwCrsrSaveState aSaveState( *m_pCurCrsr );
2016 :
2017 : // If the visible SSelection was not changed
2018 42 : const Point& rPoint = pOldStk->GetPtPos();
2019 42 : if (rPoint == m_pCurCrsr->GetPtPos() || rPoint == m_pCurCrsr->GetMkPos())
2020 : {
2021 : // move "Selections Rectangles"
2022 42 : m_pCurCrsr->insert( m_pCurCrsr->begin(), pOldStk->begin(), pOldStk->end() );
2023 42 : pOldStk->clear();
2024 : }
2025 :
2026 42 : if( pOldStk->HasMark() )
2027 : {
2028 8 : m_pCurCrsr->SetMark();
2029 8 : *m_pCurCrsr->GetMark() = *pOldStk->GetMark();
2030 8 : m_pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
2031 : }
2032 : else
2033 : // no selection so revoke old one and set to old position
2034 34 : m_pCurCrsr->DeleteMark();
2035 42 : *m_pCurCrsr->GetPoint() = *pOldStk->GetPoint();
2036 42 : m_pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
2037 42 : delete pOldStk;
2038 :
2039 84 : if( !m_pCurCrsr->IsInProtectTable( true ) &&
2040 : !m_pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2041 42 : nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2042 42 : UpdateCrsr(); // update current cursor
2043 : }
2044 948 : return true;
2045 : }
2046 :
2047 : /** Combine two cursors
2048 :
2049 : Delete topmost from stack and use its GetMark in the current.
2050 : */
2051 0 : void SwCrsrShell::Combine()
2052 : {
2053 : // any others left?
2054 0 : if( 0 == m_pCrsrStk )
2055 0 : return;
2056 :
2057 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
2058 : // rhbz#689053: IsSelOvr must restore the saved stack position, not the
2059 : // current one, because current point + stack mark may be invalid PaM
2060 0 : SwCrsrSaveState aSaveState(*m_pCrsrStk);
2061 : // stack cursor & current cursor in same Section?
2062 : assert(!m_pCrsrStk->HasMark() ||
2063 : CheckNodesRange(m_pCrsrStk->GetMark()->nNode,
2064 : m_pCurCrsr->GetPoint()->nNode, true));
2065 0 : *m_pCrsrStk->GetPoint() = *m_pCurCrsr->GetPoint();
2066 0 : m_pCrsrStk->GetPtPos() = m_pCurCrsr->GetPtPos();
2067 :
2068 0 : SwShellCrsr * pTmp = 0;
2069 0 : if( m_pCrsrStk->GetNext() != m_pCrsrStk )
2070 : {
2071 0 : pTmp = dynamic_cast<SwShellCrsr*>(m_pCrsrStk->GetNext());
2072 : }
2073 0 : delete m_pCurCrsr;
2074 0 : m_pCurCrsr = m_pCrsrStk;
2075 0 : m_pCrsrStk->MoveTo(0); // remove from ring
2076 0 : m_pCrsrStk = pTmp;
2077 0 : if( !m_pCurCrsr->IsInProtectTable( true ) &&
2078 : !m_pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2079 0 : nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2080 : {
2081 0 : UpdateCrsr(); // update current cursor
2082 0 : }
2083 : }
2084 :
2085 13652 : void SwCrsrShell::HideCrsrs()
2086 : {
2087 13652 : if( !m_bHasFocus || m_bBasicHideCrsr )
2088 13672 : return;
2089 :
2090 : // if cursor is visible then hide SV cursor
2091 13632 : if( m_pVisCrsr->IsVisible() )
2092 : {
2093 12060 : SET_CURR_SHELL( this );
2094 12060 : m_pVisCrsr->Hide();
2095 : }
2096 : // revoke inversion of SSelection
2097 13632 : SwShellCrsr* pAktCrsr = m_pTblCrsr ? m_pTblCrsr : m_pCurCrsr;
2098 13632 : pAktCrsr->Hide();
2099 : }
2100 :
2101 83880 : void SwCrsrShell::ShowCrsrs( bool bCrsrVis )
2102 : {
2103 83880 : if( !m_bHasFocus || m_bAllProtect || m_bBasicHideCrsr )
2104 84022 : return;
2105 :
2106 83738 : SET_CURR_SHELL( this );
2107 83738 : SwShellCrsr* pAktCrsr = m_pTblCrsr ? m_pTblCrsr : m_pCurCrsr;
2108 83738 : pAktCrsr->Show();
2109 :
2110 83738 : if( m_bSVCrsrVis && bCrsrVis ) // also show SV cursor again
2111 73723 : m_pVisCrsr->Show();
2112 : }
2113 :
2114 2550 : void SwCrsrShell::ShowCrsr()
2115 : {
2116 2550 : if( !m_bBasicHideCrsr )
2117 : {
2118 2550 : m_bSVCrsrVis = true;
2119 2550 : m_pCurCrsr->SetShowTxtInputFldOverlay( true );
2120 : #if defined(ANDROID) || defined(IOS)
2121 : touch_ui_show_keyboard();
2122 : #endif
2123 2550 : UpdateCrsr();
2124 : }
2125 2550 : }
2126 :
2127 1071 : void SwCrsrShell::HideCrsr()
2128 : {
2129 1071 : if( !m_bBasicHideCrsr )
2130 : {
2131 1071 : m_bSVCrsrVis = false;
2132 : // possibly reverse selected areas!!
2133 1071 : SET_CURR_SHELL( this );
2134 1071 : m_pCurCrsr->SetShowTxtInputFldOverlay( false );
2135 1071 : m_pVisCrsr->Hide();
2136 : #if defined(ANDROID) || defined(IOS)
2137 : touch_ui_hide_keyboard();
2138 : #endif
2139 : }
2140 1071 : }
2141 :
2142 4656 : void SwCrsrShell::ShLooseFcs()
2143 : {
2144 4656 : if( !m_bBasicHideCrsr )
2145 4656 : HideCrsrs();
2146 4656 : m_bHasFocus = false;
2147 4656 : }
2148 :
2149 4656 : void SwCrsrShell::ShGetFcs( bool bUpdate )
2150 : {
2151 4656 : m_bHasFocus = true;
2152 4656 : if( !m_bBasicHideCrsr && VisArea().Width() )
2153 : {
2154 : UpdateCrsr( static_cast<sal_uInt16>( bUpdate ?
2155 : SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
2156 3594 : : SwCrsrShell::CHKRANGE ) );
2157 3594 : ShowCrsrs( m_bSVCrsrVis ? sal_True : sal_False );
2158 : }
2159 4656 : }
2160 :
2161 : /** Get current frame in which the cursor is positioned. */
2162 35129 : SwCntntFrm *SwCrsrShell::GetCurrFrm( const bool bCalcFrm ) const
2163 : {
2164 35129 : SET_CURR_SHELL( (SwViewShell*)this );
2165 35129 : SwCntntFrm *pRet = 0;
2166 35129 : SwCntntNode *pNd = m_pCurCrsr->GetCntntNode();
2167 35129 : if ( pNd )
2168 : {
2169 35129 : if ( bCalcFrm )
2170 : {
2171 13742 : const sal_uInt16* pST = &mnStartAction;
2172 13742 : ++(*((sal_uInt16*)pST));
2173 13742 : const Size aOldSz( GetDocSize() );
2174 13742 : pRet = pNd->getLayoutFrm( GetLayout(), &m_pCurCrsr->GetPtPos(), m_pCurCrsr->GetPoint() );
2175 13742 : --(*((sal_uInt16*)pST));
2176 13742 : if( aOldSz != GetDocSize() )
2177 12 : ((SwCrsrShell*)this)->SizeChgNotify();
2178 : }
2179 : else
2180 21387 : pRet = pNd->getLayoutFrm( GetLayout(), &m_pCurCrsr->GetPtPos(), m_pCurCrsr->GetPoint(), false);
2181 : }
2182 35129 : return pRet;
2183 : }
2184 :
2185 : //TODO: provide documentation
2186 : /** forward all attribute/format changes at the current node to the Link
2187 :
2188 : @param pOld ???
2189 : @param pNew ???
2190 : */
2191 7734 : void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2192 : {
2193 : const sal_uInt16 nWhich = pOld ?
2194 : pOld->Which() :
2195 : pNew ?
2196 : pNew->Which() :
2197 7734 : sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN);
2198 :
2199 7734 : if( m_bCallChgLnk &&
2200 7538 : ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
2201 7344 : nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
2202 : nWhich == RES_ATTRSET_CHG ))
2203 : // messages are not forwarded
2204 : // #i6681#: RES_UPDATE_ATTR is implicitly unset in
2205 : // SwTxtNode::Insert(SwTxtHint*, sal_uInt16); we react here and thus do
2206 : // not need to send the expensive RES_FMT_CHG in Insert.
2207 3222 : CallChgLnk();
2208 :
2209 7734 : if( m_aGrfArrivedLnk.IsSet() &&
2210 7644 : ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
2211 0 : m_aGrfArrivedLnk.Call( this );
2212 7734 : }
2213 :
2214 : /** Does the current cursor create a selection?
2215 :
2216 : This means checking if GetMark is set and if SPoint and GetMark differ.
2217 : */
2218 78866 : bool SwCrsrShell::HasSelection() const
2219 : {
2220 78866 : const SwPaM* pCrsr = getShellCrsr( true );
2221 158014 : return( IsTableMode() || ( pCrsr->HasMark() &&
2222 320 : *pCrsr->GetPoint() != *pCrsr->GetMark())
2223 158038 : ? sal_True : sal_False );
2224 : }
2225 :
2226 51914 : void SwCrsrShell::CallChgLnk()
2227 : {
2228 : // Do not make any call in start/end action but just remember the change.
2229 : // This will be taken care of in the end action.
2230 51914 : if( BasicActionPend() )
2231 33216 : m_bChgCallFlag = true; // remember change
2232 18698 : else if( m_aChgLnk.IsSet() )
2233 : {
2234 18696 : if( m_bCallChgLnk )
2235 18696 : m_aChgLnk.Call( this );
2236 18696 : m_bChgCallFlag = false; // reset flag
2237 : }
2238 51914 : }
2239 :
2240 : /// get selected text of a node at current cursor
2241 4 : OUString SwCrsrShell::GetSelTxt() const
2242 : {
2243 4 : OUString aTxt;
2244 8 : if( m_pCurCrsr->GetPoint()->nNode.GetIndex() ==
2245 4 : m_pCurCrsr->GetMark()->nNode.GetIndex() )
2246 : {
2247 4 : SwTxtNode* pTxtNd = m_pCurCrsr->GetNode().GetTxtNode();
2248 4 : if( pTxtNd )
2249 : {
2250 4 : const sal_Int32 nStt = m_pCurCrsr->Start()->nContent.GetIndex();
2251 8 : aTxt = pTxtNd->GetExpandTxt( nStt,
2252 8 : m_pCurCrsr->End()->nContent.GetIndex() - nStt );
2253 : }
2254 : }
2255 4 : return aTxt;
2256 : }
2257 :
2258 : /// get text only from current cursor position (until end of node)
2259 0 : OUString SwCrsrShell::GetText() const
2260 : {
2261 0 : OUString aTxt;
2262 0 : if( m_pCurCrsr->GetPoint()->nNode.GetIndex() ==
2263 0 : m_pCurCrsr->GetMark()->nNode.GetIndex() )
2264 : {
2265 0 : SwTxtNode* pTxtNd = m_pCurCrsr->GetNode().GetTxtNode();
2266 0 : if( pTxtNd )
2267 0 : aTxt = pTxtNd->GetTxt().copy(
2268 0 : m_pCurCrsr->GetPoint()->nContent.GetIndex() );
2269 : }
2270 0 : return aTxt;
2271 : }
2272 :
2273 : /** get the nth character of the current SSelection
2274 :
2275 : @param bEnd Start counting from the end? From start otherwise.
2276 : @param nOffset position of the character
2277 : */
2278 4 : sal_Unicode SwCrsrShell::GetChar( bool bEnd, long nOffset )
2279 : {
2280 4 : if( IsTableMode() ) // not possible in table mode
2281 0 : return 0;
2282 :
2283 4 : const SwPosition* pPos = !m_pCurCrsr->HasMark() ? m_pCurCrsr->GetPoint()
2284 4 : : bEnd ? m_pCurCrsr->End() : m_pCurCrsr->Start();
2285 4 : SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2286 4 : if( !pTxtNd )
2287 0 : return 0;
2288 :
2289 4 : const sal_Int32 nPos = pPos->nContent.GetIndex();
2290 4 : const OUString& rStr = pTxtNd->GetTxt();
2291 4 : sal_Unicode cCh = 0;
2292 :
2293 4 : if (((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.getLength())
2294 4 : cCh = rStr[nPos + nOffset];
2295 :
2296 4 : return cCh;
2297 : }
2298 :
2299 : /** extend current SSelection by n characters
2300 :
2301 : @param bEnd Start counting from the end? From start otherwise.
2302 : @param nCount Number of characters.
2303 : */
2304 0 : bool SwCrsrShell::ExtendSelection( bool bEnd, sal_Int32 nCount )
2305 : {
2306 0 : if( !m_pCurCrsr->HasMark() || IsTableMode() )
2307 0 : return false; // no selection
2308 :
2309 0 : SwPosition* pPos = bEnd ? m_pCurCrsr->End() : m_pCurCrsr->Start();
2310 0 : SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2311 : OSL_ENSURE( pTxtNd, "no text node; how should this then be extended?" );
2312 :
2313 0 : sal_Int32 nPos = pPos->nContent.GetIndex();
2314 0 : if( bEnd )
2315 : {
2316 0 : if ((nPos + nCount) <= pTxtNd->GetTxt().getLength())
2317 0 : nPos = nPos + nCount;
2318 : else
2319 0 : return false; // not possible
2320 : }
2321 0 : else if( nPos >= nCount )
2322 0 : nPos = nPos - nCount;
2323 : else
2324 0 : return false; // not possible anymore
2325 :
2326 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
2327 :
2328 0 : pPos->nContent = nPos;
2329 0 : UpdateCrsr();
2330 :
2331 0 : return true;
2332 : }
2333 :
2334 : /** Move visible cursor to given position in document.
2335 :
2336 : @param rPt The position to move the visible cursor to.
2337 : @return <sal_False> if SPoint was corrected by the layout.
2338 : */
2339 0 : bool SwCrsrShell::SetVisCrsr( const Point &rPt )
2340 : {
2341 0 : SET_CURR_SHELL( this );
2342 0 : Point aPt( rPt );
2343 0 : SwPosition aPos( *m_pCurCrsr->GetPoint() );
2344 0 : SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
2345 0 : aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2346 0 : aTmpState.bRealHeight = true;
2347 :
2348 0 : const bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
2349 :
2350 0 : SetInFrontOfLabel( false ); // #i27615#
2351 :
2352 : // show only in TextNodes
2353 0 : SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
2354 0 : if( !pTxtNd )
2355 0 : return false;
2356 :
2357 0 : const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
2358 0 : if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
2359 0 : ( !IsReadOnlyAvailable() &&
2360 0 : pSectNd->GetSection().IsProtectFlag())) )
2361 0 : return false;
2362 :
2363 0 : SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos );
2364 0 : if ( Imp()->IsIdleAction() )
2365 0 : pFrm->PrepareCrsr();
2366 0 : SwRect aTmp( m_aCharRect );
2367 :
2368 0 : pFrm->GetCharRect( m_aCharRect, aPos, &aTmpState );
2369 :
2370 : // #i10137#
2371 0 : if( aTmp == m_aCharRect && m_pVisCrsr->IsVisible() )
2372 0 : return true;
2373 :
2374 0 : m_pVisCrsr->Hide(); // always hide visible cursor
2375 0 : if( IsScrollMDI( this, m_aCharRect ))
2376 : {
2377 0 : MakeVisible( m_aCharRect );
2378 0 : m_pCurCrsr->Show();
2379 : }
2380 :
2381 : {
2382 0 : if( aTmpState.bRealHeight )
2383 0 : m_aCrsrHeight = aTmpState.aRealHeight;
2384 : else
2385 : {
2386 0 : m_aCrsrHeight.setX(0);
2387 0 : m_aCrsrHeight.setY(m_aCharRect.Height());
2388 : }
2389 :
2390 0 : m_pVisCrsr->SetDragCrsr( true );
2391 0 : m_pVisCrsr->Show(); // show again
2392 : }
2393 0 : return bRet;
2394 : }
2395 :
2396 0 : bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
2397 : {
2398 0 : Point aPt( rPt );
2399 0 : SwPaM aPam( *m_pCurCrsr->GetPoint() );
2400 0 : GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
2401 : // Formular view
2402 0 : return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
2403 : }
2404 :
2405 : /** Get the number of elements in the ring of cursors
2406 :
2407 : @param bAll If <false> get only spanned ones (= with selections) (Basic).
2408 : */
2409 44968 : sal_uInt16 SwCrsrShell::GetCrsrCnt( bool bAll ) const
2410 : {
2411 44968 : Ring* pTmp = GetCrsr()->GetNext();
2412 0 : sal_uInt16 n = (bAll || ( m_pCurCrsr->HasMark() &&
2413 89936 : *m_pCurCrsr->GetPoint() != *m_pCurCrsr->GetMark())) ? 1 : 0;
2414 90038 : while( pTmp != m_pCurCrsr )
2415 : {
2416 102 : if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
2417 0 : *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
2418 102 : ++n;
2419 102 : pTmp = pTmp->GetNext();
2420 : }
2421 44968 : return n;
2422 : }
2423 :
2424 0 : bool SwCrsrShell::IsStartOfDoc() const
2425 : {
2426 0 : if( m_pCurCrsr->GetPoint()->nContent.GetIndex() )
2427 0 : return false;
2428 :
2429 : // after EndOfIcons comes the content selection (EndNd+StNd+CntntNd)
2430 0 : SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
2431 0 : if( !aIdx.GetNode().IsCntntNode() )
2432 0 : GetDoc()->GetNodes().GoNext( &aIdx );
2433 0 : return aIdx == m_pCurCrsr->GetPoint()->nNode;
2434 : }
2435 :
2436 0 : bool SwCrsrShell::IsEndOfDoc() const
2437 : {
2438 0 : SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
2439 0 : SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
2440 0 : if( !pCNd )
2441 0 : pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
2442 :
2443 0 : return aIdx == m_pCurCrsr->GetPoint()->nNode &&
2444 0 : pCNd->Len() == m_pCurCrsr->GetPoint()->nContent.GetIndex();
2445 : }
2446 :
2447 : /** Invalidate cursors
2448 :
2449 : Delete all created cursors, set table crsr and last crsr to their TextNode
2450 : (or StartNode?). They will then all re-created at the next ::GetCrsr() call.
2451 :
2452 : This is needed for Drag&Drop/ Clipboard-paste in tables.
2453 : */
2454 0 : bool SwCrsrShell::ParkTblCrsr()
2455 : {
2456 0 : if( !m_pTblCrsr )
2457 0 : return false;
2458 :
2459 0 : m_pTblCrsr->ParkCrsr();
2460 :
2461 0 : while( m_pCurCrsr->GetNext() != m_pCurCrsr )
2462 0 : delete m_pCurCrsr->GetNext();
2463 :
2464 : // *always* move cursor's Point and Mark
2465 0 : m_pCurCrsr->DeleteMark();
2466 0 : *m_pCurCrsr->GetPoint() = *m_pTblCrsr->GetPoint();
2467 :
2468 0 : return true;
2469 : }
2470 :
2471 0 : void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
2472 : {
2473 0 : const SwPosition *pStt = pDelRg->Start(),
2474 0 : *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
2475 :
2476 0 : SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
2477 :
2478 : // search over the whole ring
2479 : bool bGoNext;
2480 0 : do {
2481 0 : const SwPosition *pTmpStt = pTmp->Start(),
2482 0 : *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
2483 0 : pTmp->GetMark() : pTmp->GetPoint();
2484 : // If a SPoint or GetMark are in a cursor area than cancel the old area.
2485 : // During comparison keep in mind that End() is outside the area.
2486 0 : if( *pStt <= *pTmpStt )
2487 : {
2488 0 : if( *pEnd > *pTmpStt ||
2489 0 : ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
2490 0 : pTmpDel = pTmp;
2491 : }
2492 : else
2493 0 : if( *pStt < *pTmpEnd )
2494 0 : pTmpDel = pTmp;
2495 :
2496 0 : bGoNext = true;
2497 0 : if (pTmpDel) // is the pam in the range -> delete
2498 : {
2499 0 : bool bDelete = true;
2500 0 : if( *ppDelRing == pTmpDel )
2501 : {
2502 0 : if( *ppDelRing == m_pCurCrsr )
2503 : {
2504 0 : if( ( bDelete = GoNextCrsr() ) )
2505 : {
2506 0 : bGoNext = false;
2507 0 : pTmp = (SwPaM*)pTmp->GetNext();
2508 : }
2509 : }
2510 : else
2511 0 : bDelete = false; // never delete the StackCrsr
2512 : }
2513 :
2514 0 : if( bDelete )
2515 0 : delete pTmpDel; // invalidate old area
2516 : else
2517 : {
2518 0 : pTmpDel->DeleteMark();
2519 : }
2520 0 : pTmpDel = 0;
2521 : }
2522 0 : if( bGoNext && pTmp )
2523 0 : pTmp = (SwPaM*)pTmp->GetNext();
2524 :
2525 0 : } while( !bGoNext || *ppDelRing != pTmp );
2526 0 : }
2527 :
2528 : //TODO: provide documentation
2529 : /** Remove selections and additional cursors of all shells.
2530 :
2531 : The remaining cursor of the shell is parked.
2532 :
2533 : @param rIdx ???
2534 : */
2535 0 : void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
2536 : {
2537 0 : SwNode *pNode = &rIdx.GetNode();
2538 :
2539 : // create a new PaM
2540 0 : SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
2541 0 : if( pNode->GetStartNode() )
2542 : {
2543 0 : if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
2544 : {
2545 : // the given node is in a table, thus park cursor to table node
2546 : // (outside of the table)
2547 0 : pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2548 : }
2549 : else
2550 : // Also on the start node itself. Then we need to request the start
2551 : // node always via its end node! (StartOfSelection of StartNode is
2552 : // the parent)
2553 0 : pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
2554 : }
2555 : else
2556 0 : pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2557 0 : pNew->SetMark();
2558 0 : pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
2559 :
2560 : // take care of all shells
2561 0 : SwViewShell *pTmp = this;
2562 0 : do {
2563 0 : if( pTmp->IsA( TYPE( SwCrsrShell )))
2564 : {
2565 0 : SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
2566 0 : if( pSh->m_pCrsrStk )
2567 0 : pSh->_ParkPams( pNew, &pSh->m_pCrsrStk );
2568 :
2569 0 : pSh->_ParkPams( pNew, &pSh->m_pCurCrsr );
2570 0 : if( pSh->m_pTblCrsr )
2571 : {
2572 : // set table cursor always to 0 and the current one always to
2573 : // the beginning of the table
2574 0 : SwPaM* pTCrsr = pSh->GetTblCrs();
2575 0 : SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
2576 0 : if ( pTblNd )
2577 : {
2578 0 : pTCrsr->DeleteMark();
2579 0 : pSh->m_pCurCrsr->GetPoint()->nNode = *pTblNd;
2580 : }
2581 : }
2582 : }
2583 0 : } while ( this != (pTmp = (SwViewShell*)pTmp->GetNext() ));
2584 0 : delete pNew;
2585 0 : }
2586 :
2587 : /** Copy constructor
2588 :
2589 : Copy cursor position and add it to the ring.
2590 : All views of a document are in the ring of the shell.
2591 : */
2592 0 : SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, vcl::Window *pInitWin )
2593 : : SwViewShell( rShell, pInitWin )
2594 : , SwModify( 0 )
2595 : , m_pCrsrStk( 0 )
2596 : , m_pBlockCrsr( 0 )
2597 : , m_pTblCrsr( 0 )
2598 : , m_pBoxIdx( 0 )
2599 : , m_pBoxPtr( 0 )
2600 : , m_nUpDownX(0)
2601 : , m_nLeftFrmPos(0)
2602 : , m_nAktNode(0)
2603 : , m_nAktCntnt(0)
2604 : , m_nAktNdTyp(0)
2605 : , m_bAktSelection(false)
2606 : , m_nCrsrMove( 0 )
2607 : , m_nBasicActionCnt( 0 )
2608 : , m_eMvState( MV_NONE )
2609 : , m_sMarkedListId()
2610 : , m_nMarkedListLevel( 0 )
2611 0 : , m_oldColFrm(0)
2612 : {
2613 0 : SET_CURR_SHELL( this );
2614 : // only keep the position of the current cursor of the copy shell
2615 0 : m_pCurCrsr = new SwShellCrsr( *this, *(rShell.m_pCurCrsr->GetPoint()) );
2616 0 : m_pCurCrsr->GetCntntNode()->Add( this );
2617 :
2618 : m_bAllProtect = m_bVisPortChgd = m_bChgCallFlag = m_bInCMvVisportChgd =
2619 : m_bGCAttr = m_bIgnoreReadonly = m_bSelTblCells = m_bBasicHideCrsr =
2620 0 : m_bOverwriteCrsr = false;
2621 0 : m_bCallChgLnk = m_bHasFocus = m_bAutoUpdateCells = true;
2622 0 : m_bSVCrsrVis = true;
2623 0 : m_bSetCrsrInReadOnly = true;
2624 0 : m_pVisCrsr = new SwVisCrsr( this );
2625 0 : m_bMacroExecAllowed = rShell.IsMacroExecAllowed();
2626 :
2627 : #if defined(ANDROID) || defined(IOS)
2628 : HideCrsr();
2629 : #endif
2630 0 : }
2631 :
2632 : /// default constructor
2633 4708 : SwCrsrShell::SwCrsrShell( SwDoc& rDoc, vcl::Window *pInitWin,
2634 : const SwViewOption *pInitOpt )
2635 : : SwViewShell( rDoc, pInitWin, pInitOpt )
2636 : , SwModify( 0 )
2637 : , m_pCrsrStk( 0 )
2638 : , m_pBlockCrsr( 0 )
2639 : , m_pTblCrsr( 0 )
2640 : , m_pBoxIdx( 0 )
2641 : , m_pBoxPtr( 0 )
2642 : , m_nUpDownX(0)
2643 : , m_nLeftFrmPos(0)
2644 : , m_nAktNode(0)
2645 : , m_nAktCntnt(0)
2646 : , m_nAktNdTyp(0)
2647 : , m_bAktSelection(false)
2648 : , m_nCrsrMove( 0 )
2649 : , m_nBasicActionCnt( 0 )
2650 : , m_eMvState( MV_NONE ) // state for crsr-travelling - GetCrsrOfst
2651 : , m_sMarkedListId()
2652 : , m_nMarkedListLevel( 0 )
2653 4708 : , m_oldColFrm(0)
2654 : {
2655 4708 : SET_CURR_SHELL( this );
2656 : // create initial cursor and set it to first content position
2657 4708 : SwNodes& rNds = rDoc.GetNodes();
2658 :
2659 9416 : SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
2660 4708 : SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // go to the first ContentNode
2661 :
2662 4708 : m_pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
2663 :
2664 : // Register shell as dependent at current node. As a result all attribute
2665 : // changes can be forwarded via the Link.
2666 4708 : pCNd->Add( this );
2667 :
2668 : m_bAllProtect = m_bVisPortChgd = m_bChgCallFlag = m_bInCMvVisportChgd =
2669 : m_bGCAttr = m_bIgnoreReadonly = m_bSelTblCells = m_bBasicHideCrsr =
2670 4708 : m_bOverwriteCrsr = false;
2671 4708 : m_bCallChgLnk = m_bHasFocus = m_bAutoUpdateCells = true;
2672 4708 : m_bSVCrsrVis = true;
2673 4708 : m_bSetCrsrInReadOnly = true;
2674 :
2675 4708 : m_pVisCrsr = new SwVisCrsr( this );
2676 9416 : m_bMacroExecAllowed = true;
2677 :
2678 : #if defined(ANDROID) || defined(IOS)
2679 : HideCrsr();
2680 : #endif
2681 4708 : }
2682 :
2683 9412 : SwCrsrShell::~SwCrsrShell()
2684 : {
2685 : // if it is not the last view then at least the field should be updated
2686 4706 : if( GetNext() != this )
2687 0 : CheckTblBoxCntnt( m_pCurCrsr->GetPoint() );
2688 : else
2689 4706 : ClearTblBoxCntnt();
2690 :
2691 4706 : delete m_pVisCrsr;
2692 4706 : delete m_pBlockCrsr;
2693 4706 : delete m_pTblCrsr;
2694 :
2695 : // release cursors
2696 9414 : while(m_pCurCrsr->GetNext() != m_pCurCrsr)
2697 2 : delete m_pCurCrsr->GetNext();
2698 4706 : delete m_pCurCrsr;
2699 :
2700 : // free stack
2701 4706 : if( m_pCrsrStk )
2702 : {
2703 0 : while( m_pCrsrStk->GetNext() != m_pCrsrStk )
2704 0 : delete m_pCrsrStk->GetNext();
2705 0 : delete m_pCrsrStk;
2706 : }
2707 :
2708 : // #i54025# - do not give a HTML parser that might potentially hang as
2709 : // a client at the cursor shell the chance to hang itself on a TextNode
2710 4706 : if( GetRegisteredIn() )
2711 4706 : GetRegisteredInNonConst()->Remove( this );
2712 4706 : }
2713 :
2714 390538 : SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
2715 : {
2716 390538 : if( m_pTblCrsr )
2717 136 : return m_pTblCrsr;
2718 390402 : if( m_pBlockCrsr && bBlock )
2719 0 : return &m_pBlockCrsr->getShellCrsr();
2720 390402 : return m_pCurCrsr;
2721 : }
2722 :
2723 : /** Should WaitPtr be switched on for the clipboard?
2724 :
2725 : Wait for TableMode, multiple selections and more than x selected paragraphs.
2726 : */
2727 2 : bool SwCrsrShell::ShouldWait() const
2728 : {
2729 2 : if ( IsTableMode() || GetCrsrCnt() > 1 )
2730 0 : return true;
2731 :
2732 2 : if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2733 0 : return true;
2734 :
2735 2 : SwPaM* pPam = GetCrsr();
2736 2 : return pPam->Start()->nNode.GetIndex() + 10 <
2737 2 : pPam->End()->nNode.GetIndex();
2738 : }
2739 :
2740 0 : size_t SwCrsrShell::UpdateTblSelBoxes()
2741 : {
2742 0 : if (m_pTblCrsr && (m_pTblCrsr->IsChgd() || !m_pTblCrsr->GetSelectedBoxesCount()))
2743 : {
2744 0 : GetLayout()->MakeTblCrsrs( *m_pTblCrsr );
2745 : }
2746 0 : return (m_pTblCrsr) ? m_pTblCrsr->GetSelectedBoxesCount() : 0;
2747 : }
2748 :
2749 : /// show the current selected "object"
2750 67851 : void SwCrsrShell::MakeSelVisible()
2751 : {
2752 : OSL_ENSURE( m_bHasFocus, "no focus but cursor should be made visible?" );
2753 67851 : if( m_aCrsrHeight.Y() < m_aCharRect.Height() && m_aCharRect.Height() > VisArea().Height() )
2754 : {
2755 52 : SwRect aTmp( m_aCharRect );
2756 52 : long nDiff = m_aCharRect.Height() - VisArea().Height();
2757 52 : if( nDiff < m_aCrsrHeight.getX() )
2758 0 : aTmp.Top( nDiff + m_aCharRect.Top() );
2759 : else
2760 : {
2761 52 : aTmp.Top( m_aCrsrHeight.getX() + m_aCharRect.Top() );
2762 52 : aTmp.Height( m_aCrsrHeight.getY() );
2763 : }
2764 52 : if( !aTmp.HasArea() )
2765 : {
2766 0 : aTmp.SSize().Height() += 1;
2767 0 : aTmp.SSize().Width() += 1;
2768 : }
2769 52 : MakeVisible( aTmp );
2770 : }
2771 : else
2772 : {
2773 67799 : if( m_aCharRect.HasArea() )
2774 67689 : MakeVisible( m_aCharRect );
2775 : else
2776 : {
2777 110 : SwRect aTmp( m_aCharRect );
2778 110 : aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
2779 110 : MakeVisible( aTmp );
2780 : }
2781 : }
2782 67851 : }
2783 :
2784 : /// search a valid content position (not protected/hidden)
2785 0 : bool SwCrsrShell::FindValidCntntNode( bool bOnlyText )
2786 : {
2787 0 : if( m_pTblCrsr )
2788 : {
2789 : OSL_ENSURE( false, "Did not remove table selection!" );
2790 0 : return false;
2791 : }
2792 :
2793 : // #i45129# - everything is allowed in UI-readonly
2794 0 : if( !m_bAllProtect && GetDoc()->GetDocShell() &&
2795 0 : GetDoc()->GetDocShell()->IsReadOnlyUI() )
2796 0 : return true;
2797 :
2798 0 : if( m_pCurCrsr->HasMark() )
2799 0 : ClearMark();
2800 :
2801 : // first check for frames
2802 0 : SwNodeIndex& rNdIdx = m_pCurCrsr->GetPoint()->nNode;
2803 0 : sal_uLong nNdIdx = rNdIdx.GetIndex(); // keep backup
2804 0 : SwNodes& rNds = mpDoc->GetNodes();
2805 0 : SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
2806 : const SwCntntFrm * pFrm;
2807 :
2808 0 : if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(), 0, m_pCurCrsr->GetPoint(), false)) &&
2809 0 : !IsReadOnlyAvailable() && pFrm->IsProtected() &&
2810 0 : nNdIdx < rNds.GetEndOfExtras().GetIndex() )
2811 : {
2812 : // skip protected frame
2813 0 : SwPaM aPam( *m_pCurCrsr->GetPoint() );
2814 0 : aPam.SetMark();
2815 0 : aPam.GetMark()->nNode = rNds.GetEndOfContent();
2816 0 : aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
2817 :
2818 0 : bool bFirst = false;
2819 0 : if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, false )))
2820 : {
2821 0 : aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
2822 0 : pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, false );
2823 : }
2824 :
2825 0 : if( !pCNd ) // should *never* happen
2826 : {
2827 0 : rNdIdx = nNdIdx; // back to old node
2828 0 : return false;
2829 : }
2830 0 : *m_pCurCrsr->GetPoint() = *aPam.GetPoint();
2831 : }
2832 0 : else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
2833 : {
2834 : // set to beginning of document
2835 0 : rNdIdx = mpDoc->GetNodes().GetEndOfExtras();
2836 0 : m_pCurCrsr->GetPoint()->nContent.Assign( mpDoc->GetNodes().GoNext(
2837 0 : &rNdIdx ), 0 );
2838 0 : nNdIdx = rNdIdx.GetIndex();
2839 : }
2840 :
2841 0 : bool bOk = true;
2842 :
2843 : // #i9059# cursor may not stand in protected cells
2844 : // (unless cursor in protected areas is OK.)
2845 0 : const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
2846 0 : if( !IsReadOnlyAvailable() &&
2847 0 : pTableNode != NULL && rNdIdx.GetNode().IsProtect() )
2848 : {
2849 : // we're in a table, and we're in a protected area, so we're
2850 : // probably in a protected cell.
2851 :
2852 : // move forward into non-protected area.
2853 0 : SwPaM aPam( rNdIdx.GetNode(), 0 );
2854 0 : while( aPam.GetNode().IsProtect() &&
2855 0 : aPam.Move( fnMoveForward, fnGoCntnt ) )
2856 : ; // nothing to do in the loop; the aPam.Move does the moving!
2857 :
2858 : // didn't work? then go backwards!
2859 0 : if( aPam.GetNode().IsProtect() )
2860 : {
2861 0 : SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
2862 0 : aPam = aTmpPaM;
2863 0 : while( aPam.GetNode().IsProtect() &&
2864 0 : aPam.Move( fnMoveBackward, fnGoCntnt ) )
2865 0 : ; // nothing to do in the loop; the aPam.Move does the moving!
2866 : }
2867 :
2868 : // if we're successful, set the new position
2869 0 : if( ! aPam.GetNode().IsProtect() )
2870 : {
2871 0 : *m_pCurCrsr->GetPoint() = *aPam.GetPoint();
2872 0 : }
2873 : }
2874 :
2875 : // in a protected frame
2876 0 : const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
2877 0 : if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
2878 0 : ( !IsReadOnlyAvailable() &&
2879 0 : pSectNd->GetSection().IsProtectFlag() )) )
2880 : {
2881 : typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, bool, bool ) const;
2882 0 : FNGoSection funcGoSection = &SwNodes::GoNextSection;
2883 :
2884 0 : bOk = false;
2885 :
2886 0 : for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
2887 : {
2888 : bool bContinue;
2889 0 : do {
2890 0 : bContinue = false;
2891 0 : while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
2892 0 : true, !IsReadOnlyAvailable() )) )
2893 : {
2894 : // moved inside a table -> check if it is protected
2895 0 : if( pCNd->FindTableNode() )
2896 : {
2897 0 : SwCallLink aTmp( *this );
2898 0 : SwCrsrSaveState aSaveState( *m_pCurCrsr );
2899 0 : aTmp.nNdTyp = 0; // don't do anything in DTOR
2900 0 : if( !m_pCurCrsr->IsInProtectTable( true, true ) )
2901 : {
2902 0 : const SwSectionNode* pSNd = pCNd->FindSectionNode();
2903 0 : if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
2904 0 : || (!IsReadOnlyAvailable() &&
2905 0 : pSNd->GetSection().IsProtectFlag() ))
2906 : {
2907 0 : bOk = true;
2908 0 : break; // found non-protected cell
2909 : }
2910 0 : continue; // continue search
2911 0 : }
2912 : }
2913 : else
2914 : {
2915 0 : bOk = true;
2916 0 : break; // found non-protected cell
2917 : }
2918 : }
2919 :
2920 0 : if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
2921 : {
2922 : // also check for Fly - might be protected as well
2923 0 : if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(), 0, 0, false)) ||
2924 0 : ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
2925 0 : ( bOnlyText && pCNd->IsNoTxtNode() ) )
2926 : {
2927 : // continue search
2928 0 : bOk = false;
2929 0 : bContinue = true;
2930 : }
2931 : }
2932 : } while( bContinue );
2933 :
2934 0 : if( !bOk )
2935 : {
2936 0 : if( !nLoopCnt )
2937 0 : funcGoSection = &SwNodes::GoPrevSection;
2938 0 : rNdIdx = nNdIdx;
2939 : }
2940 : }
2941 : }
2942 0 : if( bOk )
2943 : {
2944 0 : pCNd = rNdIdx.GetNode().GetCntntNode();
2945 0 : const sal_Int32 nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
2946 0 : m_pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
2947 : }
2948 : else
2949 : {
2950 0 : pCNd = rNdIdx.GetNode().GetCntntNode();
2951 : // if cursor in hidden frame, always move it
2952 0 : if( !pCNd || !pCNd->getLayoutFrm( GetLayout(), 0, 0, false) )
2953 : {
2954 0 : SwCrsrMoveState aTmpState( MV_NONE );
2955 0 : aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2956 0 : GetLayout()->GetCrsrOfst( m_pCurCrsr->GetPoint(), m_pCurCrsr->GetPtPos(),
2957 0 : &aTmpState );
2958 : }
2959 : }
2960 0 : return bOk;
2961 : }
2962 :
2963 230813 : bool SwCrsrShell::IsCrsrReadonly() const
2964 : {
2965 461549 : if ( GetViewOptions()->IsReadonly() ||
2966 230736 : GetViewOptions()->IsFormView() /* Formula view */ )
2967 : {
2968 77 : SwFrm *pFrm = GetCurrFrm( false );
2969 : const SwFlyFrm* pFly;
2970 : const SwSection* pSection;
2971 :
2972 154 : if( pFrm && pFrm->IsInFly() &&
2973 0 : (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
2974 0 : pFly->Lower() &&
2975 77 : !pFly->Lower()->IsNoTxtFrm() &&
2976 0 : !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2977 : {
2978 0 : return false;
2979 : }
2980 : // edit in readonly sections
2981 154 : else if ( pFrm && pFrm->IsInSct() &&
2982 77 : 0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
2983 0 : pSection->IsEditInReadonlyFlag() )
2984 : {
2985 0 : return false;
2986 : }
2987 77 : else if ( !IsMultiSelection() && CrsrInsideInputFld() )
2988 : {
2989 0 : return false;
2990 : }
2991 :
2992 77 : return true;
2993 : }
2994 230736 : return false;
2995 : }
2996 :
2997 : /// is the cursor allowed to enter ReadOnly sections?
2998 4844 : void SwCrsrShell::SetReadOnlyAvailable( bool bFlag )
2999 : {
3000 : // *never* switch in GlobalDoc
3001 14532 : if( (!GetDoc()->GetDocShell() ||
3002 9688 : !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
3003 4844 : bFlag != m_bSetCrsrInReadOnly )
3004 : {
3005 : // If the flag is switched off then all selections need to be
3006 : // invalidated. Otherwise we would trust that nothing protected is selected.
3007 0 : if( !bFlag )
3008 : {
3009 0 : ClearMark();
3010 : }
3011 0 : m_bSetCrsrInReadOnly = bFlag;
3012 0 : UpdateCrsr();
3013 : }
3014 4844 : }
3015 :
3016 32224 : bool SwCrsrShell::HasReadonlySel(bool bAnnotationMode) const
3017 : {
3018 32224 : bool bRet = false;
3019 32224 : if ( IsReadOnlyAvailable() || GetViewOptions()->IsFormView() )
3020 : {
3021 32224 : if ( m_pTblCrsr != NULL )
3022 : {
3023 36 : bRet = m_pTblCrsr->HasReadOnlyBoxSel()
3024 36 : || m_pTblCrsr->HasReadonlySel( GetViewOptions()->IsFormView() );
3025 : }
3026 : else
3027 : {
3028 32188 : const SwPaM* pCrsr = m_pCurCrsr;
3029 :
3030 32188 : do
3031 : {
3032 32188 : if( pCrsr->HasReadonlySel( GetViewOptions()->IsFormView(), bAnnotationMode ) )
3033 : {
3034 34 : bRet = true;
3035 : }
3036 :
3037 32188 : pCrsr = (SwPaM*)pCrsr->GetNext();
3038 64342 : } while ( !bRet && pCrsr != m_pCurCrsr );
3039 : }
3040 : }
3041 32224 : return bRet;
3042 : }
3043 :
3044 0 : bool SwCrsrShell::IsSelFullPara() const
3045 : {
3046 0 : bool bRet = false;
3047 :
3048 0 : if( m_pCurCrsr->GetPoint()->nNode.GetIndex() ==
3049 0 : m_pCurCrsr->GetMark()->nNode.GetIndex() && m_pCurCrsr == m_pCurCrsr->GetNext() )
3050 : {
3051 0 : sal_Int32 nStt = m_pCurCrsr->GetPoint()->nContent.GetIndex();
3052 0 : sal_Int32 nEnd = m_pCurCrsr->GetMark()->nContent.GetIndex();
3053 0 : if( nStt > nEnd )
3054 : {
3055 0 : sal_Int32 nTmp = nStt;
3056 0 : nStt = nEnd;
3057 0 : nEnd = nTmp;
3058 : }
3059 0 : const SwCntntNode* pCNd = m_pCurCrsr->GetCntntNode();
3060 0 : bRet = pCNd && !nStt && nEnd == pCNd->Len();
3061 : }
3062 0 : return bRet;
3063 : }
3064 :
3065 17690 : short SwCrsrShell::GetTextDirection( const Point* pPt ) const
3066 : {
3067 17690 : SwPosition aPos( *m_pCurCrsr->GetPoint() );
3068 17690 : Point aPt( pPt ? *pPt : m_pCurCrsr->GetPtPos() );
3069 17690 : if( pPt )
3070 : {
3071 6 : SwCrsrMoveState aTmpState( MV_NONE );
3072 6 : aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
3073 :
3074 6 : GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
3075 : }
3076 :
3077 17690 : return mpDoc->GetTextDirection( aPos, &aPt );
3078 : }
3079 :
3080 8645 : bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const
3081 : {
3082 8645 : const short nDir = GetTextDirection( pPt );
3083 8645 : return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
3084 : }
3085 :
3086 9045 : bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
3087 : {
3088 9045 : const short nDir = GetTextDirection( pPt );
3089 : // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
3090 : // vertical environment
3091 9045 : return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
3092 : }
3093 :
3094 : /// If the current cursor position is inside a hidden range, the hidden range
3095 : /// is selected.
3096 898 : bool SwCrsrShell::SelectHiddenRange()
3097 : {
3098 898 : bool bRet = false;
3099 898 : if ( !GetViewOptions()->IsShowHiddenChar() && !m_pCurCrsr->HasMark() )
3100 : {
3101 896 : SwPosition& rPt = *(SwPosition*)m_pCurCrsr->GetPoint();
3102 896 : const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
3103 896 : if ( pNode )
3104 : {
3105 896 : const sal_Int32 nPos = rPt.nContent.GetIndex();
3106 :
3107 : // check if nPos is in hidden range
3108 : sal_Int32 nHiddenStart;
3109 : sal_Int32 nHiddenEnd;
3110 896 : SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
3111 896 : if ( COMPLETE_STRING != nHiddenStart )
3112 : {
3113 : // make selection:
3114 1 : m_pCurCrsr->SetMark();
3115 1 : m_pCurCrsr->GetMark()->nContent = nHiddenEnd;
3116 1 : bRet = true;
3117 : }
3118 : }
3119 : }
3120 :
3121 898 : return bRet;
3122 : }
3123 :
3124 0 : sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt,
3125 : bool bSearchInNotes,
3126 : SwDocPositions eStart, SwDocPositions eEnd,
3127 : bool& bCancel,
3128 : FindRanges eRng,
3129 : bool bReplace )
3130 : {
3131 0 : if( m_pTblCrsr )
3132 0 : GetCrsr();
3133 0 : delete m_pTblCrsr, m_pTblCrsr = 0;
3134 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
3135 : sal_uLong nRet = m_pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnd,
3136 0 : bCancel, eRng, bReplace );
3137 0 : if( nRet || bCancel )
3138 0 : UpdateCrsr();
3139 0 : return nRet;
3140 : }
3141 :
3142 0 : sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
3143 : SwDocPositions eStart, SwDocPositions eEnd,
3144 : bool& bCancel,
3145 : FindRanges eRng,
3146 : const SwTxtFmtColl* pReplFmt )
3147 : {
3148 0 : if( m_pTblCrsr )
3149 0 : GetCrsr();
3150 0 : delete m_pTblCrsr, m_pTblCrsr = 0;
3151 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
3152 : sal_uLong nRet = m_pCurCrsr->Find( rFmtColl, eStart, eEnd, bCancel, eRng,
3153 0 : pReplFmt );
3154 0 : if( nRet )
3155 0 : UpdateCrsr();
3156 0 : return nRet;
3157 : }
3158 :
3159 0 : sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet,
3160 : bool bNoCollections,
3161 : SwDocPositions eStart, SwDocPositions eEnd,
3162 : bool& bCancel,
3163 : FindRanges eRng,
3164 : const SearchOptions* pSearchOpt,
3165 : const SfxItemSet* rReplSet )
3166 : {
3167 0 : if( m_pTblCrsr )
3168 0 : GetCrsr();
3169 0 : delete m_pTblCrsr, m_pTblCrsr = 0;
3170 0 : SwCallLink aLk( *this ); // watch Crsr-Moves; call Link if needed
3171 : sal_uLong nRet = m_pCurCrsr->Find( rSet, bNoCollections, eStart, eEnd,
3172 0 : bCancel, eRng, pSearchOpt, rReplSet );
3173 0 : if( nRet )
3174 0 : UpdateCrsr();
3175 0 : return nRet;
3176 : }
3177 :
3178 24 : void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
3179 : {
3180 24 : StartAction();
3181 24 : SwPaM* pCrsr = GetCrsr();
3182 24 : *pCrsr->GetPoint() = *rCrsr.GetPoint();
3183 24 : if(rCrsr.HasMark())
3184 : {
3185 10 : pCrsr->SetMark();
3186 10 : *pCrsr->GetMark() = *rCrsr.GetMark();
3187 : }
3188 24 : if((SwPaM*)rCrsr.GetNext() != &rCrsr)
3189 : {
3190 0 : const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
3191 0 : do
3192 : {
3193 0 : SwPaM* pCurrentCrsr = CreateCrsr();
3194 0 : *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
3195 0 : if(_pStartCrsr->HasMark())
3196 : {
3197 0 : pCurrentCrsr->SetMark();
3198 0 : *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
3199 : }
3200 0 : } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
3201 : }
3202 24 : EndAction();
3203 24 : }
3204 :
3205 0 : static const SwStartNode* lcl_NodeContext( const SwNode& rNode )
3206 : {
3207 0 : const SwStartNode *pRet = rNode.StartOfSectionNode();
3208 0 : while( pRet->IsSectionNode() || pRet->IsTableNode() ||
3209 0 : pRet->GetStartNodeType() == SwTableBoxStartNode )
3210 : {
3211 0 : pRet = pRet->StartOfSectionNode();
3212 : }
3213 0 : return pRet;
3214 : }
3215 :
3216 : /**
3217 : Checks if a position is valid. To be valid the position's node must
3218 : be a content node and the content must not be unregistered.
3219 :
3220 : @param aPos the position to check.
3221 : */
3222 78221 : bool sw_PosOk(const SwPosition & aPos)
3223 : {
3224 156442 : return NULL != aPos.nNode.GetNode().GetCntntNode() &&
3225 156442 : aPos.nContent.GetIdxReg();
3226 : }
3227 :
3228 : /**
3229 : Checks if a PaM is valid. For a PaM to be valid its point must be
3230 : valid. Additionally if the PaM has a mark this has to be valid, too.
3231 :
3232 : @param aPam the PaM to check
3233 : */
3234 38 : static bool lcl_CrsrOk(SwPaM & aPam)
3235 : {
3236 76 : return sw_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
3237 76 : || sw_PosOk(*aPam.GetMark()));
3238 : }
3239 :
3240 77814 : void SwCrsrShell::ClearUpCrsrs()
3241 : {
3242 : // start of the ring
3243 77814 : SwPaM * pStartCrsr = GetCrsr();
3244 : // start loop with second entry of the ring
3245 77814 : SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
3246 : SwPaM * pTmpCrsr;
3247 77814 : bool bChanged = false;
3248 :
3249 : // For all entries in the ring except the start entry delete the entry if
3250 : // it is invalid.
3251 155666 : while (pCrsr != pStartCrsr)
3252 : {
3253 38 : pTmpCrsr = (SwPaM *) pCrsr->GetNext();
3254 38 : if ( ! lcl_CrsrOk(*pCrsr))
3255 : {
3256 0 : delete pCrsr;
3257 0 : bChanged = true;
3258 : }
3259 38 : pCrsr = pTmpCrsr;
3260 : }
3261 :
3262 77814 : if( pStartCrsr->HasMark() && !sw_PosOk( *pStartCrsr->GetMark() ) )
3263 : {
3264 0 : pStartCrsr->DeleteMark();
3265 0 : bChanged = true;
3266 : }
3267 77814 : if( !sw_PosOk( *pStartCrsr->GetPoint() ) )
3268 : {
3269 0 : SwNodes & aNodes = GetDoc()->GetNodes();
3270 0 : const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
3271 0 : SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
3272 0 : SwNode * pNode = aNodes.GoPrevious(&aIdx);
3273 0 : if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3274 0 : aNodes.GoNext( &aIdx );
3275 0 : if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3276 : {
3277 : // If the start entry of the ring is invalid replace it with a
3278 : // cursor pointing to the beginning of the first content node in the
3279 : // document.
3280 0 : aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
3281 0 : pNode = aNodes.GoNext( &aIdx );
3282 : }
3283 0 : bool bFound = (pNode != NULL);
3284 :
3285 : OSL_ENSURE(bFound, "no content node found");
3286 :
3287 0 : if (bFound)
3288 : {
3289 0 : SwPaM aTmpPam(*pNode);
3290 0 : *pStartCrsr = aTmpPam;
3291 : }
3292 :
3293 0 : bChanged = true;
3294 : }
3295 :
3296 : // If at least one of the cursors in the ring have been deleted or replaced,
3297 : // remove the table cursor.
3298 77814 : if (m_pTblCrsr != NULL && bChanged)
3299 0 : TblCrsrToCursor();
3300 77814 : }
3301 :
3302 0 : OUString SwCrsrShell::GetCrsrDescr() const
3303 : {
3304 0 : OUString aResult;
3305 :
3306 0 : if (IsMultiSelection())
3307 0 : aResult += SW_RES(STR_MULTISEL);
3308 : else
3309 0 : aResult = GetDoc()->GetPaMDescr(*GetCrsr());
3310 :
3311 0 : return aResult;
3312 : }
3313 :
3314 0 : static void lcl_FillRecognizerData( uno::Sequence< OUString >& rSmartTagTypes,
3315 : uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3316 : const SwWrongList& rSmartTagList, sal_Int32 nCurrent )
3317 : {
3318 : // Insert smart tag information
3319 0 : std::vector< OUString > aSmartTagTypes;
3320 0 : std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
3321 :
3322 0 : for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i )
3323 : {
3324 0 : const sal_Int32 nSTPos = rSmartTagList.Pos( i );
3325 0 : const sal_Int32 nSTLen = rSmartTagList.Len( i );
3326 :
3327 0 : if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
3328 : {
3329 0 : const SwWrongArea* pArea = rSmartTagList.GetElement( i );
3330 0 : if ( pArea )
3331 : {
3332 0 : aSmartTagTypes.push_back( pArea->maType );
3333 0 : aStringKeyMaps.push_back( pArea->mxPropertyBag );
3334 : }
3335 : }
3336 : }
3337 :
3338 0 : if ( !aSmartTagTypes.empty() )
3339 : {
3340 0 : rSmartTagTypes.realloc( aSmartTagTypes.size() );
3341 0 : rStringKeyMaps.realloc( aSmartTagTypes.size() );
3342 :
3343 0 : std::vector< OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
3344 0 : sal_uInt16 i = 0;
3345 0 : for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
3346 0 : rSmartTagTypes[i++] = *aTypesIter;
3347 :
3348 0 : std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
3349 0 : i = 0;
3350 0 : for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
3351 0 : rStringKeyMaps[i++] = *aMapsIter;
3352 0 : }
3353 0 : }
3354 :
3355 0 : static void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
3356 : SwTxtNode& rNode, sal_Int32 nBegin, sal_Int32 nLen )
3357 : {
3358 : // create SwPosition for nStartIndex
3359 0 : SwIndex aIndex( &rNode, nBegin );
3360 0 : SwPosition aStartPos( rNode, aIndex );
3361 :
3362 : // create SwPosition for nEndIndex
3363 0 : SwPosition aEndPos( aStartPos );
3364 0 : aEndPos.nContent = nBegin + nLen;
3365 :
3366 : const uno::Reference<text::XTextRange> xRange =
3367 0 : SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos);
3368 :
3369 0 : rRange = xRange;
3370 0 : }
3371 :
3372 0 : void SwCrsrShell::GetSmartTagTerm( uno::Sequence< OUString >& rSmartTagTypes,
3373 : uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3374 : uno::Reference< text::XTextRange>& rRange ) const
3375 : {
3376 0 : if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3377 0 : return;
3378 :
3379 0 : SwPaM* pCrsr = GetCrsr();
3380 0 : SwPosition aPos( *pCrsr->GetPoint() );
3381 0 : SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
3382 0 : if ( pNode && !pNode->IsInProtectSect() )
3383 : {
3384 0 : const SwWrongList *pSmartTagList = pNode->GetSmartTags();
3385 0 : if ( pSmartTagList )
3386 : {
3387 0 : sal_Int32 nCurrent = aPos.nContent.GetIndex();
3388 0 : sal_Int32 nBegin = nCurrent;
3389 0 : sal_Int32 nLen = 1;
3390 :
3391 0 : if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3392 : {
3393 0 : const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3394 0 : const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3395 0 : if ( pSubList )
3396 : {
3397 0 : pSmartTagList = pSubList;
3398 0 : nCurrent = 0;
3399 : }
3400 :
3401 0 : lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3402 0 : lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3403 : }
3404 : }
3405 0 : }
3406 : }
3407 :
3408 : // see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
3409 0 : void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
3410 : uno::Sequence< OUString >& rSmartTagTypes,
3411 : uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3412 : uno::Reference<text::XTextRange>& rRange )
3413 : {
3414 0 : if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3415 0 : return;
3416 :
3417 0 : SwPaM* pCrsr = GetCrsr();
3418 0 : SwPosition aPos( *pCrsr->GetPoint() );
3419 0 : Point aPt( rPt );
3420 0 : SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
3421 0 : SwSpecialPos aSpecialPos;
3422 0 : eTmpState.pSpecialPos = &aSpecialPos;
3423 : SwTxtNode *pNode;
3424 : const SwWrongList *pSmartTagList;
3425 :
3426 0 : if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
3427 0 : 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
3428 0 : 0 != (pSmartTagList = pNode->GetSmartTags()) &&
3429 0 : !pNode->IsInProtectSect() )
3430 : {
3431 0 : sal_Int32 nCurrent = aPos.nContent.GetIndex();
3432 0 : sal_Int32 nBegin = nCurrent;
3433 0 : sal_Int32 nLen = 1;
3434 :
3435 0 : if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3436 : {
3437 0 : const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3438 0 : const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3439 0 : if ( pSubList )
3440 : {
3441 0 : pSmartTagList = pSubList;
3442 0 : nCurrent = eTmpState.pSpecialPos->nCharOfst;
3443 : }
3444 :
3445 0 : lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3446 0 : lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3447 :
3448 : // get smarttag word
3449 0 : OUString aText( pNode->GetTxt().copy(nBegin, nLen) );
3450 :
3451 : //save the start and end positons of the line and the starting point
3452 0 : Push();
3453 0 : LeftMargin();
3454 0 : const sal_Int32 nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
3455 0 : RightMargin();
3456 0 : const sal_Int32 nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
3457 0 : Pop(false);
3458 :
3459 : // make sure the selection build later from the data below does not
3460 : // include "in word" character to the left and right in order to
3461 : // preserve those. Therefore count those "in words" in order to
3462 : // modify the selection accordingly.
3463 0 : const sal_Unicode* pChar = aText.getStr();
3464 0 : sal_Int32 nLeft = 0;
3465 0 : while (pChar && *pChar++ == CH_TXTATR_INWORD)
3466 0 : ++nLeft;
3467 0 : pChar = aText.getLength() ? aText.getStr() + aText.getLength() - 1 : 0;
3468 0 : sal_Int32 nRight = 0;
3469 0 : while (pChar && *pChar-- == CH_TXTATR_INWORD)
3470 0 : ++nRight;
3471 :
3472 0 : aPos.nContent = nBegin + nLeft;
3473 0 : pCrsr = GetCrsr();
3474 0 : *pCrsr->GetPoint() = aPos;
3475 0 : pCrsr->SetMark();
3476 0 : ExtendSelection( true, nLen - nLeft - nRight );
3477 : // do not determine the rectangle in the current line
3478 0 : const sal_Int32 nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
3479 : // take one less than the line end - otherwise the next line would
3480 : // be calculated
3481 0 : const sal_Int32 nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd : (nBegin + nLen - nLeft - nRight);
3482 0 : Push();
3483 0 : pCrsr->DeleteMark();
3484 0 : SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
3485 0 : rContent = nWordStart;
3486 0 : SwRect aStartRect;
3487 0 : SwCrsrMoveState aState;
3488 0 : aState.bRealWidth = true;
3489 0 : SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
3490 0 : SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), false);
3491 :
3492 0 : pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
3493 0 : rContent = nWordEnd - 1;
3494 0 : SwRect aEndRect;
3495 0 : pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
3496 0 : rSelectRect = aStartRect.Union( aEndRect );
3497 0 : Pop(false);
3498 : }
3499 0 : }
3500 270 : }
3501 :
3502 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|