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