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