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