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