1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 #include <com/sun/star/util/SearchOptions.hpp>
27 #include <com/sun/star/text/XTextRange.hpp>
28 #include <hintids.hxx>
29 #include <svx/svdmodel.hxx>
30 #include <editeng/frmdiritem.hxx>
31
32 #include <SwSmartTagMgr.hxx>
33 #include <doc.hxx>
34 #include <rootfrm.hxx>
35 #include <pagefrm.hxx>
36 #include <cntfrm.hxx>
37 #include <viewimp.hxx>
38 #include <pam.hxx>
39 #include <swselectionlist.hxx>
40 #include <IBlockCursor.hxx>
41 #include "BlockCursor.hxx"
42 #include <ndtxt.hxx>
43 #include <flyfrm.hxx>
44 #include <dview.hxx>
45 #include <viewopt.hxx>
46 #include <frmtool.hxx>
47 #include <crsrsh.hxx>
48 #include <tabfrm.hxx>
49 #include <txtfrm.hxx>
50 #include <sectfrm.hxx>
51 #include <swtable.hxx>
52 #include <callnk.hxx>
53 #include <viscrs.hxx>
54 #include <section.hxx>
55 #include <docsh.hxx>
56 #include <scriptinfo.hxx>
57 #include <globdoc.hxx>
58 #include <pamtyp.hxx>
59 #include <mdiexp.hxx> // ...Percent()
60 #include <fmteiro.hxx>
61 #include <wrong.hxx> // SMARTTAGS
62 #include <unotextrange.hxx> // SMARTTAGS
63 #include <vcl/svapp.hxx>
64 #include <numrule.hxx>
65 #include <IGrammarContact.hxx>
66
67 #include <globals.hrc>
68
69 #include <comcore.hrc>
70
71 using namespace com::sun::star;
72 using namespace util;
73
74 TYPEINIT2(SwCrsrShell,ViewShell,SwModify);
75
76
77 // Funktion loescht, alle ueberlappenden Cursor aus einem Cursor-Ring
78 void CheckRange( SwCursor* );
79
80 //-----------------------------------------------------------------------
81
82 /*
83 * Ueberpruefe ob der pCurCrsr in einen schon bestehenden Bereich zeigt.
84 * Wenn ja, dann hebe den alten Bereich auf.
85 */
86
87
CheckRange(SwCursor * pCurCrsr)88 void CheckRange( SwCursor* pCurCrsr )
89 {
90 const SwPosition *pStt = pCurCrsr->Start(),
91 *pEnd = pCurCrsr->GetPoint() == pStt ? pCurCrsr->GetMark() : pCurCrsr->GetPoint();
92
93 SwPaM *pTmpDel = 0,
94 *pTmp = (SwPaM*)pCurCrsr->GetNext();
95
96 // durchsuche den gesamten Ring
97 while( pTmp != pCurCrsr )
98 {
99 const SwPosition *pTmpStt = pTmp->Start(),
100 *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
101 pTmp->GetMark() : pTmp->GetPoint();
102 if( *pStt <= *pTmpStt )
103 {
104 if( *pEnd > *pTmpStt ||
105 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
106 pTmpDel = pTmp;
107 }
108 else
109 if( *pStt < *pTmpEnd )
110 pTmpDel = pTmp;
111 /*
112 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
113 * muss der alte Bereich aufgehoben werden.
114 * Beim Vergleich ist darauf zu achten, das SPoint nicht mehr zum
115 * Bereich gehoert !
116 */
117 pTmp = (SwPaM*)pTmp->GetNext();
118 if( pTmpDel )
119 {
120 delete pTmpDel; // hebe alten Bereich auf
121 pTmpDel = 0;
122 }
123 }
124 }
125
126 // -------------- Methoden von der SwCrsrShell -------------
127
CreateCrsr()128 SwPaM * SwCrsrShell::CreateCrsr()
129 {
130 // Innerhalb der Tabellen-SSelection keinen neuen Crsr anlegen
131 ASSERT( !IsTableMode(), "in Tabellen SSelection" );
132
133 // neuen Cursor als Kopie vom akt. und in den Ring aufnehmen
134 // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
135 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
136
137 // hier den akt. Pam nur logisch Hiden, weil sonst die Invertierung
138 // vom kopierten Pam aufgehoben wird !!
139
140 // #i75172# to be able to make a complete content swap, i moved this to a method
141 // pNew->Insert( pCurCrsr, 0 );
142 // pCurCrsr->Remove( 0, pCurCrsr->Count() );
143 pNew->swapContent(*pCurCrsr);
144
145 pCurCrsr->DeleteMark();
146
147 UpdateCrsr( SwCrsrShell::SCROLLWIN );
148 // return pCurCrsr;
149 return pNew;
150 }
151
152 // loesche den aktuellen Cursor und der folgende wird zum Aktuellen
153
154
DestroyCrsr()155 sal_Bool SwCrsrShell::DestroyCrsr()
156 {
157 // Innerhalb der Tabellen-SSelection keinen neuen Crsr loeschen
158 ASSERT( !IsTableMode(), "in Tabellen SSelection" );
159
160 // ist ueberhaupt ein naechtser vorhanden ?
161 if(pCurCrsr->GetNext() == pCurCrsr)
162 return sal_False;
163
164 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
165 SwCursor* pNextCrsr = (SwCursor*)pCurCrsr->GetNext();
166 delete pCurCrsr;
167 pCurCrsr = dynamic_cast<SwShellCrsr*>(pNextCrsr);
168 UpdateCrsr();
169 return sal_True;
170 }
171
172
CreateNewShellCursor()173 SwPaM & SwCrsrShell::CreateNewShellCursor()
174 {
175 if (HasSelection())
176 {
177 (void) CreateCrsr(); // n.b. returns old cursor
178 }
179 return *GetCrsr();
180 }
181
GetCurrentShellCursor()182 SwPaM & SwCrsrShell::GetCurrentShellCursor()
183 {
184 return *GetCrsr();
185 }
186
187
188 // gebe den aktuellen zurueck
189
GetCrsr(sal_Bool bMakeTblCrsr) const190 SwPaM* SwCrsrShell::GetCrsr( sal_Bool bMakeTblCrsr ) const
191 {
192 if( pTblCrsr )
193 {
194 if( bMakeTblCrsr && pTblCrsr->IsCrsrMovedUpdt() )
195 {
196 // geparkte Cursor werden nicht wieder erzeugt
197 const SwCntntNode* pCNd;
198 if( pTblCrsr->GetPoint()->nNode.GetIndex() &&
199 pTblCrsr->GetMark()->nNode.GetIndex() &&
200 0 != ( pCNd = pTblCrsr->GetCntntNode() ) && pCNd->getLayoutFrm( GetLayout() ) &&
201 0 != ( pCNd = pTblCrsr->GetCntntNode(sal_False) ) && pCNd->getLayoutFrm( GetLayout() ) )
202 {
203 SwShellTableCrsr* pTC = (SwShellTableCrsr*)pTblCrsr;
204 GetLayout()->MakeTblCrsrs( *pTC );
205 }
206 }
207
208 if( pTblCrsr->IsChgd() )
209 {
210 const_cast<SwCrsrShell*>(this)->pCurCrsr =
211 dynamic_cast<SwShellCrsr*>(pTblCrsr->MakeBoxSels( pCurCrsr ));
212 }
213 }
214 return pCurCrsr;
215 }
216
217
StartAction()218 void SwCrsrShell::StartAction()
219 {
220 if( !ActionPend() )
221 {
222 // fuer das Update des Ribbon-Bars merken
223 const SwNode& rNd = pCurCrsr->GetPoint()->nNode.GetNode();
224 nAktNode = rNd.GetIndex();
225 nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
226 nAktNdTyp = rNd.GetNodeType();
227 bAktSelection = *pCurCrsr->GetPoint() != *pCurCrsr->GetMark();
228 if( ND_TEXTNODE & nAktNdTyp )
229 nLeftFrmPos = SwCallLink::getLayoutFrm( GetLayout(), (SwTxtNode&)rNd, nAktCntnt, sal_True );
230 else
231 nLeftFrmPos = 0;
232 }
233 ViewShell::StartAction(); // zur ViewShell
234 }
235
236
EndAction(const sal_Bool bIdleEnd)237 void SwCrsrShell::EndAction( const sal_Bool bIdleEnd )
238 {
239 /*
240 //OS: Wird z.B. eine Basic-Action im Hintergrund ausgefuehrt, geht es so nicht
241 if( !bHasFocus )
242 {
243 // hat die Shell nicht den Focus, dann nur das EndAction an
244 // die ViewShell weitergeben.
245 ViewShell::EndAction( bIdleEnd );
246 return;
247 }
248 */
249
250 sal_Bool bVis = bSVCrsrVis;
251
252 // Idle-Formatierung ?
253 if( bIdleEnd && Imp()->GetRegion() )
254 {
255 pCurCrsr->Hide();
256
257 #ifdef SHOW_IDLE_REGION
258 if( GetWin() )
259 {
260 GetWin()->Push();
261 GetWin()->ChangePen( Pen( Color( COL_YELLOW )));
262 for( sal_uInt16 n = 0; n < aPntReg.Count(); ++n )
263 {
264 SwRect aIRect( aPntReg[n] );
265 GetWin()->DrawRect( aIRect.SVRect() );
266 }
267 GetWin()->Pop();
268 }
269 #endif
270
271 }
272
273 // vor der letzten Action alle invaliden Numerierungen updaten
274 if( 1 == nStartAction )
275 GetDoc()->UpdateNumRule();
276
277 // Task: 76923: dont show the cursor in the ViewShell::EndAction() - call.
278 // Only the UpdateCrsr shows the cursor.
279 sal_Bool bSavSVCrsrVis = bSVCrsrVis;
280 bSVCrsrVis = sal_False;
281
282 ViewShell::EndAction( bIdleEnd ); //der ViewShell den Vortritt lassen
283
284 bSVCrsrVis = bSavSVCrsrVis;
285
286 if( ActionPend() )
287 {
288 if( bVis ) // auch SV-Cursor wieder anzeigen
289 pVisCrsr->Show();
290
291 // falls noch ein ChgCall vorhanden ist und nur noch die Basic
292 // Klammerung vorhanden ist, dann rufe ihn. Dadurch wird die interne
293 // mit der Basic-Klammerung entkoppelt; die Shells werden umgeschaltet
294 if( !BasicActionPend() )
295 {
296 //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction
297 // der Cursor geupdatet werden; um z.B. den
298 // TabellenCursor zu erzeugen. Im UpdateCrsr wird
299 // das jetzt beruecksichtigt!
300 UpdateCrsr( SwCrsrShell::CHKRANGE, bIdleEnd );
301
302 {
303 // Crsr-Moves ueberwachen, evt. Link callen
304 // der DTOR ist das interressante!!
305 SwCallLink aLk( *this, nAktNode, nAktCntnt, (sal_uInt8)nAktNdTyp,
306 nLeftFrmPos, bAktSelection );
307
308 }
309 if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
310 {
311 aChgLnk.Call( this );
312 bChgCallFlag = sal_False; // Flag zuruecksetzen
313 }
314 }
315 return;
316 }
317
318 sal_uInt16 nParm = SwCrsrShell::CHKRANGE;
319 if ( !bIdleEnd )
320 nParm |= SwCrsrShell::SCROLLWIN;
321 // if( !IsViewLocked() )
322 UpdateCrsr( nParm, bIdleEnd ); // Cursor-Aenderungen anzeigen
323
324 {
325 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
326 aLk.nNode = nAktNode; // evt. Link callen
327 aLk.nNdTyp = (sal_uInt8)nAktNdTyp;
328 aLk.nCntnt = nAktCntnt;
329 aLk.nLeftFrmPos = nLeftFrmPos;
330
331 if( !nCrsrMove ||
332 ( 1 == nCrsrMove && bInCMvVisportChgd ) )
333 ShowCrsrs( bSVCrsrVis ? sal_True : sal_False ); // Cursor & Selektionen wieder anzeigen
334 }
335 // falls noch ein ChgCall vorhanden ist, dann rufe ihn
336 if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
337 {
338 aChgLnk.Call( this );
339 bChgCallFlag = sal_False; // Flag zuruecksetzen
340 }
341 }
342
343
344 #if defined(DBG_UTIL)
345
SttCrsrMove()346 void SwCrsrShell::SttCrsrMove()
347 {
348 ASSERT( nCrsrMove < USHRT_MAX, "To many nested CrsrMoves." );
349 ++nCrsrMove;
350 StartAction();
351 }
352
EndCrsrMove(const sal_Bool bIdleEnd)353 void SwCrsrShell::EndCrsrMove( const sal_Bool bIdleEnd )
354 {
355 ASSERT( nCrsrMove, "EndCrsrMove() ohne SttCrsrMove()." );
356 EndAction( bIdleEnd );
357 if( !--nCrsrMove )
358 bInCMvVisportChgd = sal_False;
359 }
360
361 #endif
362
363
LeftRight(sal_Bool bLeft,sal_uInt16 nCnt,sal_uInt16 nMode,sal_Bool bVisualAllowed)364 sal_Bool SwCrsrShell::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
365 sal_Bool bVisualAllowed )
366 {
367 if( IsTableMode() )
368 return bLeft ? GoPrevCell() : GoNextCell();
369
370 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
371 sal_Bool bRet = sal_False;
372
373 // #i27615# Handle cursor in front of label.
374 const SwTxtNode* pTxtNd = 0;
375
376 if( pBlockCrsr )
377 pBlockCrsr->clearPoints();
378
379 //
380 // 1. CASE: Cursor is in front of label. A move to the right
381 // will simply reset the bInFrontOfLabel flag:
382 //
383 SwShellCrsr* pShellCrsr = getShellCrsr( true );
384 if ( !bLeft && pShellCrsr->IsInFrontOfLabel() )
385 {
386 SetInFrontOfLabel( sal_False );
387 bRet = sal_True;
388 }
389 //
390 // 2. CASE: Cursor is at beginning of numbered paragraph. A move
391 // to the left will simply set the bInFrontOfLabel flag:
392 //
393 else if ( bLeft && 0 == pShellCrsr->GetPoint()->nContent.GetIndex() &&
394 !pShellCrsr->IsInFrontOfLabel() && !pShellCrsr->HasMark() &&
395 0 != ( pTxtNd = pShellCrsr->GetNode()->GetTxtNode() ) &&
396 pTxtNd->HasVisibleNumberingOrBullet() )
397 {
398 SetInFrontOfLabel( sal_True );
399 bRet = sal_True;
400 }
401 //
402 // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
403 //
404 else
405 {
406 const sal_Bool bSkipHidden = !GetViewOptions()->IsShowHiddenChar();
407 // --> OD 2009-12-30 #i107447#
408 // To avoid loop the reset of <bInFrontOfLabel> flag is no longer
409 // reflected in the return value <bRet>.
410 const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( sal_False );
411 bRet = pShellCrsr->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
412 bSkipHidden, !IsOverwriteCrsr() );
413 if ( !bRet && bLeft && bResetOfInFrontOfLabel )
414 {
415 // undo reset of <bInFrontOfLabel> flag
416 SetInFrontOfLabel( sal_True );
417 }
418 // <--
419 }
420
421 if( bRet )
422 {
423 UpdateCrsr();
424 }
425 return bRet;
426 }
FirePageChangeEvent(sal_uInt16 nOldPage,sal_uInt16 nNewPage)427 void SwCrsrShell::FirePageChangeEvent(sal_uInt16 nOldPage, sal_uInt16 nNewPage)
428 {
429 #ifdef ACCESSIBLE_LAYOUT
430 if( Imp()->IsAccessible() )
431 Imp()->FirePageChangeEvent( nOldPage, nNewPage );
432 #endif
433 }
434
FireColumnChangeEvent(sal_uInt16 nOldColumn,sal_uInt16 nNewColumn)435 void SwCrsrShell::FireColumnChangeEvent(sal_uInt16 nOldColumn, sal_uInt16 nNewColumn)
436 {
437 #ifdef ACCESSIBLE_LAYOUT
438 if( Imp()->IsAccessible() )
439 Imp()->FireColumnChangeEvent( nOldColumn, nNewColumn);
440 #endif
441 }
442
443
FireSectionChangeEvent(sal_uInt16 nOldSection,sal_uInt16 nNewSection)444 void SwCrsrShell::FireSectionChangeEvent(sal_uInt16 nOldSection, sal_uInt16 nNewSection)
445 {
446 #ifdef ACCESSIBLE_LAYOUT
447 if( Imp()->IsAccessible() )
448 Imp()->FireSectionChangeEvent( nOldSection, nNewSection );
449 #endif
450 }
bColumnChange()451 bool SwCrsrShell::bColumnChange()
452 {
453
454 SwFrm* pCurrFrm = GetCurrFrm(sal_False);
455
456 if (pCurrFrm == NULL)
457 {
458 return sal_False;
459 }
460
461 SwFrm* pCurrCol=((SwFrm*)pCurrFrm)->FindColFrm();
462
463 while(pCurrCol== NULL && pCurrFrm!=NULL )
464 {
465 SwLayoutFrm* pParent = pCurrFrm->GetUpper();
466 if(pParent!=NULL)
467 {
468 pCurrCol=((SwFrm*)pParent)->FindColFrm();
469 pCurrFrm = (SwFrm*)pParent;
470 }
471 else
472 {
473 break;
474 }
475 }
476 if(oldColFrm == pCurrCol)
477 return sal_False;
478 else
479 {
480 oldColFrm = pCurrCol;
481 return sal_True;
482 }
483 }
484
485 // --> OD 2008-04-02 #refactorlists#
MarkListLevel(const String & sListId,const int nListLevel)486 void SwCrsrShell::MarkListLevel( const String& sListId,
487 const int nListLevel )
488 {
489 if ( sListId != sMarkedListId ||
490 nListLevel != nMarkedListLevel)
491 {
492 if ( sMarkedListId.Len() > 0 )
493 pDoc->MarkListLevel( sMarkedListId, nMarkedListLevel, sal_False );
494
495 if ( sListId.Len() > 0 )
496 {
497 pDoc->MarkListLevel( sListId, nListLevel, sal_True );
498 }
499
500 sMarkedListId = sListId;
501 nMarkedListLevel = nListLevel;
502 }
503 }
504
UpdateMarkedListLevel()505 void SwCrsrShell::UpdateMarkedListLevel()
506 {
507 SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
508
509 if ( pTxtNd )
510 {
511 if ( !pTxtNd->IsNumbered() )
512 {
513 pCurCrsr->_SetInFrontOfLabel( sal_False );
514 MarkListLevel( String(), 0 );
515 }
516 else if ( pCurCrsr->IsInFrontOfLabel() )
517 {
518 if ( pTxtNd->IsInList() )
519 {
520 ASSERT( pTxtNd->GetActualListLevel() >= 0 &&
521 pTxtNd->GetActualListLevel() < MAXLEVEL, "Which level?")
522 MarkListLevel( pTxtNd->GetListId(),
523 pTxtNd->GetActualListLevel() );
524 }
525 }
526 else
527 {
528 MarkListLevel( String(), 0 );
529 }
530 }
531 }
532 // <--
533
UpDown(sal_Bool bUp,sal_uInt16 nCnt)534 sal_Bool SwCrsrShell::UpDown( sal_Bool bUp, sal_uInt16 nCnt )
535 {
536 SET_CURR_SHELL( this );
537 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
538
539 sal_Bool bTableMode = IsTableMode();
540 SwShellCrsr* pTmpCrsr = getShellCrsr( true );
541
542 sal_Bool bRet = pTmpCrsr->UpDown( bUp, nCnt );
543 // --> FME 2005-01-10 #i40019# UpDown should always reset the
544 // bInFrontOfLabel flag:
545 bRet = SetInFrontOfLabel(sal_False) || bRet;
546 // <--
547
548 if( pBlockCrsr )
549 pBlockCrsr->clearPoints();
550
551 if( bRet )
552 {
553 eMvState = MV_UPDOWN; // Status fuers Crsr-Travelling - GetCrsrOfst
554 if( !ActionPend() )
555 {
556 CrsrFlag eUpdtMode = SwCrsrShell::SCROLLWIN;
557 if( !bTableMode )
558 eUpdtMode = (CrsrFlag) (eUpdtMode
559 | SwCrsrShell::UPDOWN | SwCrsrShell::CHKRANGE);
560 UpdateCrsr( static_cast<sal_uInt16>(eUpdtMode) );
561 }
562 }
563 return bRet;
564 }
565
566
LRMargin(sal_Bool bLeft,sal_Bool bAPI)567 sal_Bool SwCrsrShell::LRMargin( sal_Bool bLeft, sal_Bool bAPI)
568 {
569 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
570 SET_CURR_SHELL( this );
571 eMvState = MV_LEFTMARGIN; // Status fuers Crsr-Travelling - GetCrsrOfst
572
573 const sal_Bool bTableMode = IsTableMode();
574 SwShellCrsr* pTmpCrsr = getShellCrsr( true );
575
576 if( pBlockCrsr )
577 pBlockCrsr->clearPoints();
578
579 const sal_Bool bWasAtLM =
580 ( 0 == _GetCrsr()->GetPoint()->nContent.GetIndex() );
581
582 sal_Bool bRet = pTmpCrsr->LeftRightMargin( bLeft, bAPI );
583
584 if ( bLeft && !bTableMode && bRet && bWasAtLM && !_GetCrsr()->HasMark() )
585 {
586 const SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
587 if ( pTxtNd && pTxtNd->HasVisibleNumberingOrBullet() )
588 SetInFrontOfLabel( sal_True );
589 }
590 else if ( !bLeft )
591 {
592 bRet = SetInFrontOfLabel( sal_False ) || bRet;
593 }
594
595 if( bRet )
596 {
597 UpdateCrsr();
598 }
599 return bRet;
600 }
601
IsAtLRMargin(sal_Bool bLeft,sal_Bool bAPI) const602 sal_Bool SwCrsrShell::IsAtLRMargin( sal_Bool bLeft, sal_Bool bAPI ) const
603 {
604 const SwShellCrsr* pTmpCrsr = getShellCrsr( true );
605 return pTmpCrsr->IsAtLeftRightMargin( bLeft, bAPI );
606 }
607
608
SttEndDoc(sal_Bool bStt)609 sal_Bool SwCrsrShell::SttEndDoc( sal_Bool bStt )
610 {
611 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
612
613 SwShellCrsr* pTmpCrsr = pBlockCrsr ? &pBlockCrsr->getShellCrsr() : pCurCrsr;
614 sal_Bool bRet = pTmpCrsr->SttEndDoc( bStt );
615 if( bRet )
616 {
617 if( bStt )
618 pTmpCrsr->GetPtPos().Y() = 0; // expl. 0 setzen (TabellenHeader)
619 if( pBlockCrsr )
620 {
621 pBlockCrsr->clearPoints();
622 RefreshBlockCursor();
623 }
624
625 UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
626 }
627 return bRet;
628 }
629
ExtendedSelectAll()630 void SwCrsrShell::ExtendedSelectAll()
631 {
632 SwNodes& rNodes = GetDoc()->GetNodes();
633 SwPosition* pPos = pCurCrsr->GetPoint();
634 pPos->nNode = rNodes.GetEndOfPostIts();
635 pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 );
636 pPos = pCurCrsr->GetMark();
637 pPos->nNode = rNodes.GetEndOfContent();
638 SwCntntNode* pCNd = rNodes.GoPrevious( &pPos->nNode );
639 pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
640 }
641
MovePage(SwWhichPage fnWhichPage,SwPosPage fnPosPage)642 sal_Bool SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
643 {
644 sal_Bool bRet = sal_False;
645
646 // Springe beim Selektieren nie ueber Section-Grenzen !!
647 if( !pCurCrsr->HasMark() || !pCurCrsr->IsNoCntnt() )
648 {
649 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
650 SET_CURR_SHELL( this );
651
652 SwCrsrSaveState aSaveState( *pCurCrsr );
653 Point& rPt = pCurCrsr->GetPtPos();
654 SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->
655 getLayoutFrm( GetLayout(), &rPt, pCurCrsr->GetPoint(), sal_False );
656 if( pFrm && sal_True == ( bRet = GetFrmInPage( pFrm, fnWhichPage,
657 fnPosPage, pCurCrsr ) ) &&
658 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
659 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
660 UpdateCrsr();
661 else
662 bRet = sal_False;
663 }
664 return bRet;
665 }
666
667
MovePara(SwWhichPara fnWhichPara,SwPosPara fnPosPara)668 sal_Bool SwCrsrShell::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
669 {
670 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
671 SwCursor* pTmpCrsr = getShellCrsr( true );
672 sal_Bool bRet = pTmpCrsr->MovePara( fnWhichPara, fnPosPara );
673 if( bRet )
674 UpdateCrsr();
675 return bRet;
676 }
677
678
MoveSection(SwWhichSection fnWhichSect,SwPosSection fnPosSect)679 sal_Bool SwCrsrShell::MoveSection( SwWhichSection fnWhichSect,
680 SwPosSection fnPosSect)
681 {
682 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
683 SwCursor* pTmpCrsr = getShellCrsr( true );
684 sal_Bool bRet = pTmpCrsr->MoveSection( fnWhichSect, fnPosSect );
685 if( bRet )
686 UpdateCrsr();
687 return bRet;
688
689 }
690
691
692 // Positionieren des Cursors
693
694
lcl_IsInHeaderFooter(const SwNodeIndex & rIdx,Point & rPt)695 SwFrm* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
696 {
697 SwFrm* pFrm = 0;
698 SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
699 if( pCNd )
700 {
701 pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &rPt, 0, sal_False )->GetUpper();
702 while( pFrm && !pFrm->IsHeaderFrm() && !pFrm->IsFooterFrm() )
703 pFrm = pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->AnchorFrm()
704 : pFrm->GetUpper();
705 }
706 return pFrm;
707 }
708
IsInHeaderFooter(sal_Bool * pbInHeader) const709 sal_Bool SwCrsrShell::IsInHeaderFooter( sal_Bool* pbInHeader ) const
710 {
711 Point aPt;
712 SwFrm* pFrm = ::lcl_IsInHeaderFooter( pCurCrsr->GetPoint()->nNode, aPt );
713 if( pFrm && pbInHeader )
714 *pbInHeader = pFrm->IsHeaderFrm();
715 return 0 != pFrm;
716 }
717
SetCrsr(const Point & rLPt,sal_Bool bOnlyText,bool bBlock)718 int SwCrsrShell::SetCrsr( const Point &rLPt, sal_Bool bOnlyText, bool bBlock )
719 {
720 SET_CURR_SHELL( this );
721
722 SwShellCrsr* pCrsr = getShellCrsr( bBlock );
723 SwPosition aPos( *pCrsr->GetPoint() );
724 Point aPt( rLPt );
725 Point & rAktCrsrPt = pCrsr->GetPtPos();
726 SwCrsrMoveState aTmpState( IsTableMode() ? MV_TBLSEL :
727 bOnlyText ? MV_SETONLYTEXT : MV_NONE );
728 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
729
730 SwTxtNode * pTxtNd = pCrsr->GetNode()->GetTxtNode();
731
732 if ( pTxtNd && !IsTableMode() &&
733 // --> FME 2004-11-25 #i37515# No bInFrontOfLabel during selection
734 !pCrsr->HasMark() &&
735 // <--
736 pTxtNd->HasVisibleNumberingOrBullet() )
737 {
738 aTmpState.bInFrontOfLabel = sal_True; // #i27615#
739 }
740 else
741 {
742 aTmpState.bInFrontOfLabel = sal_False;
743 }
744
745 int bRet = CRSR_POSOLD |
746 ( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState )
747 ? 0 : CRSR_POSCHG );
748
749 const bool bOldInFrontOfLabel = IsInFrontOfLabel();
750 const bool bNewInFrontOfLabel = aTmpState.bInFrontOfLabel;
751
752 pCrsr->SetCrsrBidiLevel( aTmpState.nCursorBidiLevel );
753
754 if( MV_RIGHTMARGIN == aTmpState.eState )
755 eMvState = MV_RIGHTMARGIN;
756 // steht neu Pos im Header/Footer ?
757 SwFrm* pFrm = lcl_IsInHeaderFooter( aPos.nNode, aPt );
758 if( IsTableMode() && !pFrm && aPos.nNode.GetNode().StartOfSectionNode() ==
759 pCrsr->GetPoint()->nNode.GetNode().StartOfSectionNode() )
760 // gleiche Tabellenzelle und nicht im Header/Footer
761 // -> zurueck
762 return bRet;
763
764 if( pBlockCrsr && bBlock )
765 {
766 pBlockCrsr->setEndPoint( rLPt );
767 if( !pCrsr->HasMark() )
768 pBlockCrsr->setStartPoint( rLPt );
769 else if( !pBlockCrsr->getStartPoint() )
770 pBlockCrsr->setStartPoint( pCrsr->GetMkPos() );
771 }
772 if( !pCrsr->HasMark() )
773 {
774 // steht an der gleichen Position und wenn im Header/Footer,
775 // dann im gleichen
776 if( aPos == *pCrsr->GetPoint() &&
777 bOldInFrontOfLabel == bNewInFrontOfLabel )
778 {
779 if( pFrm )
780 {
781 if( pFrm->Frm().IsInside( rAktCrsrPt ))
782 return bRet;
783 }
784 else if( aPos.nNode.GetNode().IsCntntNode() )
785 {
786 // im gleichen Frame gelandet?
787 SwFrm* pOld = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
788 GetLayout(), &aCharRect.Pos(), 0, sal_False );
789 SwFrm* pNew = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
790 GetLayout(), &aPt, 0, sal_False );
791 if( pNew == pOld )
792 return bRet;
793 }
794 }
795 }
796 else
797 {
798 // SSelection ueber nicht erlaubte Sections oder wenn im Header/Footer
799 // dann in verschiedene
800 if( !CheckNodesRange( aPos.nNode, pCrsr->GetMark()->nNode, sal_True )
801 || ( pFrm && !pFrm->Frm().IsInside( pCrsr->GetMkPos() ) ))
802 return bRet;
803
804 // steht an der gleichen Position und nicht im Header/Footer
805 if( aPos == *pCrsr->GetPoint() )
806 return bRet;
807 }
808
809 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
810 SwCrsrSaveState aSaveState( *pCrsr );
811
812 *pCrsr->GetPoint() = aPos;
813 rAktCrsrPt = aPt;
814
815 // --> FME 2005-01-31 #i41424# Only update the marked number levels if necessary
816 // Force update of marked number levels if necessary.
817 if ( bNewInFrontOfLabel || bOldInFrontOfLabel )
818 pCurCrsr->_SetInFrontOfLabel( !bNewInFrontOfLabel );
819 SetInFrontOfLabel( bNewInFrontOfLabel );
820 // <--
821
822 if( !pCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
823 {
824 sal_uInt16 nFlag = SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE;
825 UpdateCrsr( nFlag );
826 bRet &= ~CRSR_POSOLD;
827 }
828 else if( bOnlyText && !pCurCrsr->HasMark() )
829 {
830 if( FindValidCntntNode( bOnlyText ) )
831 {
832 // Cursor in einen gueltigen Content stellen
833 if( aPos == *pCrsr->GetPoint() )
834 bRet = CRSR_POSOLD;
835 else
836 {
837 UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE );
838 bRet &= ~CRSR_POSOLD;
839 }
840 }
841 else
842 {
843 // es gibt keinen gueltigen Inhalt -> Cursor verstecken
844 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
845 eMvState = MV_NONE; // Status fuers Crsr-Travelling
846 bAllProtect = sal_True;
847 if( GetDoc()->GetDocShell() )
848 {
849 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
850 CallChgLnk(); // UI bescheid sagen!
851 }
852 }
853 }
854
855 return bRet;
856 }
857
858
TblCrsrToCursor()859 void SwCrsrShell::TblCrsrToCursor()
860 {
861 ASSERT( pTblCrsr, "TblCrsrToCursor: Why?" );
862 delete pTblCrsr, pTblCrsr = 0;
863 }
864
BlockCrsrToCrsr()865 void SwCrsrShell::BlockCrsrToCrsr()
866 {
867 ASSERT( pBlockCrsr, "BlockCrsrToCrsr: Why?" );
868 if( pBlockCrsr && !HasSelection() )
869 {
870 SwPaM& rPam = pBlockCrsr->getShellCrsr();
871 pCurCrsr->SetMark();
872 *pCurCrsr->GetPoint() = *rPam.GetPoint();
873 if( rPam.HasMark() )
874 *pCurCrsr->GetMark() = *rPam.GetMark();
875 else
876 pCurCrsr->DeleteMark();
877 }
878 delete pBlockCrsr, pBlockCrsr = 0;
879 }
880
CrsrToBlockCrsr()881 void SwCrsrShell::CrsrToBlockCrsr()
882 {
883 if( !pBlockCrsr )
884 {
885 SwPosition aPos( *pCurCrsr->GetPoint() );
886 pBlockCrsr = createBlockCursor( *this, aPos );
887 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
888 rBlock.GetPtPos() = pCurCrsr->GetPtPos();
889 if( pCurCrsr->HasMark() )
890 {
891 rBlock.SetMark();
892 *rBlock.GetMark() = *pCurCrsr->GetMark();
893 rBlock.GetMkPos() = pCurCrsr->GetMkPos();
894 }
895 }
896 pBlockCrsr->clearPoints();
897 RefreshBlockCursor();
898 }
899
ClearMark()900 void SwCrsrShell::ClearMark()
901 {
902 // ist ueberhaupt ein GetMark gesetzt ?
903 if( pTblCrsr )
904 {
905 while( pCurCrsr->GetNext() != pCurCrsr )
906 delete pCurCrsr->GetNext();
907 pTblCrsr->DeleteMark();
908
909 if( pCurCrsr->HasMark() )
910 {
911 // falls doch nicht alle Indizies richtig verschoben werden
912 // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
913 // Mark aufs Nodes-Array setzen
914 SwPosition& rPos = *pCurCrsr->GetMark();
915 rPos.nNode.Assign( pDoc->GetNodes(), 0 );
916 rPos.nContent.Assign( 0, 0 );
917 pCurCrsr->DeleteMark();
918 }
919
920 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
921 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
922 delete pTblCrsr, pTblCrsr = 0;
923 pCurCrsr->SwSelPaintRects::Show();
924 }
925 else
926 {
927 if( !pCurCrsr->HasMark() )
928 return;
929 // falls doch nicht alle Indizies richtig verschoben werden
930 // (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
931 // Mark aufs Nodes-Array setzen
932 SwPosition& rPos = *pCurCrsr->GetMark();
933 rPos.nNode.Assign( pDoc->GetNodes(), 0 );
934 rPos.nContent.Assign( 0, 0 );
935 pCurCrsr->DeleteMark();
936 if( !nCrsrMove )
937 pCurCrsr->SwSelPaintRects::Show();
938 }
939 }
940
941
NormalizePam(sal_Bool bPointFirst)942 void SwCrsrShell::NormalizePam(sal_Bool bPointFirst)
943 {
944 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
945 pCurCrsr->Normalize(bPointFirst);
946 }
947
SwapPam()948 void SwCrsrShell::SwapPam()
949 {
950 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
951 pCurCrsr->Exchange();
952 }
953
954
955 // suche innerhalb der Selektierten-Bereiche nach einer Selektion, die
956 // den angebenen SPoint umschliesst
957 // Ist das Flag bTstOnly gesetzt, dann wird nur getestet, ob dort eine
958 // SSelection besteht; des akt. Cursr wird nicht umgesetzt!
959 // Ansonsten wird er auf die gewaehlte SSelection gesetzt.
960
961
ChgCurrPam(const Point & rPt,sal_Bool bTstOnly,sal_Bool bTstHit)962 sal_Bool SwCrsrShell::ChgCurrPam(
963 const Point & rPt,
964 sal_Bool bTstOnly,
965 sal_Bool bTstHit )
966 {
967 SET_CURR_SHELL( this );
968
969 // Pruefe ob der SPoint in einer Tabellen-Selektion liegt
970 if( bTstOnly && pTblCrsr )
971 return pTblCrsr->IsInside( rPt );
972
973 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
974 // Suche die Position rPt im Dokument
975 SwPosition aPtPos( *pCurCrsr->GetPoint() );
976 Point aPt( rPt );
977
978 SwCrsrMoveState aTmpState( MV_NONE );
979 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
980 if ( !GetLayout()->GetCrsrOfst( &aPtPos, aPt, &aTmpState ) && bTstHit )
981 return sal_False;
982
983 // suche in allen Selektionen nach dieser Position
984 SwShellCrsr* pCmp = (SwShellCrsr*)pCurCrsr; // sicher den Pointer auf Cursor
985 do {
986 if( pCmp->HasMark() &&
987 *pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos )
988 {
989 if( bTstOnly || pCurCrsr == pCmp ) // ist der aktuelle.
990 return sal_True; // return ohne Update
991
992 pCurCrsr = pCmp;
993 UpdateCrsr(); // Cursor steht schon richtig
994 return sal_True;
995 }
996 } while( pCurCrsr !=
997 ( pCmp = dynamic_cast<SwShellCrsr*>(pCmp->GetNext()) ) );
998 return sal_False;
999 }
1000
1001
KillPams()1002 void SwCrsrShell::KillPams()
1003 {
1004 // keiner zum loeschen vorhanden?
1005 if( !pTblCrsr && !pBlockCrsr && pCurCrsr->GetNext() == pCurCrsr )
1006 return;
1007
1008 while( pCurCrsr->GetNext() != pCurCrsr )
1009 delete pCurCrsr->GetNext();
1010 pCurCrsr->SetColumnSelection( false );
1011
1012 if( pTblCrsr )
1013 {
1014 // Cursor Ring loeschen
1015 pCurCrsr->DeleteMark();
1016 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
1017 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
1018 delete pTblCrsr;
1019 pTblCrsr = 0;
1020 }
1021 else if( pBlockCrsr )
1022 {
1023 // delete the ring of cursors
1024 pCurCrsr->DeleteMark();
1025 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
1026 *pCurCrsr->GetPoint() = *rBlock.GetPoint();
1027 pCurCrsr->GetPtPos() = rBlock.GetPtPos();
1028 rBlock.DeleteMark();
1029 pBlockCrsr->clearPoints();
1030 }
1031 UpdateCrsr( SwCrsrShell::SCROLLWIN );
1032 }
1033
1034
CompareCursor(CrsrCompareType eType) const1035 int SwCrsrShell::CompareCursor( CrsrCompareType eType ) const
1036 {
1037 int nRet = 0;
1038 const SwPosition *pFirst = 0, *pSecond = 0;
1039 const SwPaM *pCur = GetCrsr(), *pStk = pCrsrStk;
1040 if( CurrPtCurrMk != eType && pStk )
1041 {
1042 switch ( eType)
1043 {
1044 case StackPtStackMk:
1045 pFirst = pStk->GetPoint();
1046 pSecond = pStk->GetMark();
1047 break;
1048 case StackPtCurrPt:
1049 pFirst = pStk->GetPoint();
1050 pSecond = pCur->GetPoint();
1051 break;
1052 case StackPtCurrMk:
1053 pFirst = pStk->GetPoint();
1054 pSecond = pCur->GetMark();
1055 break;
1056 case StackMkCurrPt:
1057 pFirst = pStk->GetMark();
1058 pSecond = pCur->GetPoint();
1059 break;
1060 case StackMkCurrMk:
1061 pFirst = pStk->GetMark();
1062 pSecond = pStk->GetMark();
1063 break;
1064 case CurrPtCurrMk:
1065 pFirst = pCur->GetPoint();
1066 pSecond = pCur->GetMark();
1067 break;
1068 }
1069 }
1070 if( !pFirst || !pSecond )
1071 nRet = INT_MAX;
1072 else if( *pFirst < *pSecond )
1073 nRet = -1;
1074 else if( *pFirst == *pSecond )
1075 nRet = 0;
1076 else
1077 nRet = 1;
1078 return nRet;
1079 }
1080
1081
IsSttPara() const1082 sal_Bool SwCrsrShell::IsSttPara() const
1083 { return( pCurCrsr->GetPoint()->nContent == 0 ? sal_True : sal_False ); }
1084
1085
IsEndPara() const1086 sal_Bool SwCrsrShell::IsEndPara() const
1087 { return( pCurCrsr->GetPoint()->nContent == pCurCrsr->GetCntntNode()->Len() ? sal_True : sal_False ); }
1088
1089
IsInFrontOfLabel() const1090 sal_Bool SwCrsrShell::IsInFrontOfLabel() const
1091 {
1092 return pCurCrsr->IsInFrontOfLabel();
1093 }
1094
SetInFrontOfLabel(sal_Bool bNew)1095 bool SwCrsrShell::SetInFrontOfLabel( sal_Bool bNew )
1096 {
1097 if ( bNew != IsInFrontOfLabel() )
1098 {
1099 pCurCrsr->_SetInFrontOfLabel( bNew );
1100 UpdateMarkedListLevel();
1101 return true;
1102 }
1103 return false;
1104 }
1105
GotoPage(sal_uInt16 nPage)1106 sal_Bool SwCrsrShell::GotoPage( sal_uInt16 nPage )
1107 {
1108 SET_CURR_SHELL( this );
1109 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
1110 SwCrsrSaveState aSaveState( *pCurCrsr );
1111 sal_Bool bRet = GetLayout()->SetCurrPage( pCurCrsr, nPage ) &&
1112 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1113 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1114 if( bRet )
1115 UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
1116 return bRet;
1117 }
1118
1119
GetPageNum(sal_uInt16 & rnPhyNum,sal_uInt16 & rnVirtNum,sal_Bool bAtCrsrPos,const sal_Bool bCalcFrm)1120 void SwCrsrShell::GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum,
1121 sal_Bool bAtCrsrPos, const sal_Bool bCalcFrm )
1122 {
1123 SET_CURR_SHELL( this );
1124 // Seitennummer: die erste sichtbare Seite oder die am Cursor
1125 const SwCntntFrm* pCFrm;
1126 const SwPageFrm *pPg = 0;
1127
1128 if( !bAtCrsrPos || 0 == (pCFrm = GetCurrFrm( bCalcFrm )) ||
1129 0 == (pPg = pCFrm->FindPageFrm()) )
1130 {
1131 pPg = Imp()->GetFirstVisPage();
1132 while( pPg && pPg->IsEmptyPage() )
1133 pPg = (const SwPageFrm *)pPg->GetNext();
1134 }
1135 // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
1136 // standard.vor sein.
1137 rnPhyNum = pPg? pPg->GetPhyPageNum() : 1;
1138 rnVirtNum = pPg? pPg->GetVirtPageNum() : 1;
1139 }
1140
1141
GetNextPrevPageNum(sal_Bool bNext)1142 sal_uInt16 SwCrsrShell::GetNextPrevPageNum( sal_Bool bNext )
1143 {
1144 SET_CURR_SHELL( this );
1145
1146 // Seitennummer: die erste sichtbare Seite oder die am Cursor
1147 const SwPageFrm *pPg = Imp()->GetFirstVisPage();
1148 if( pPg )
1149 {
1150 const SwTwips nPageTop = pPg->Frm().Top();
1151
1152 if( bNext )
1153 {
1154 // go to next view layout row:
1155 do
1156 {
1157 pPg = (const SwPageFrm *)pPg->GetNext();
1158 }
1159 while( pPg && pPg->Frm().Top() == nPageTop );
1160
1161 while( pPg && pPg->IsEmptyPage() )
1162 pPg = (const SwPageFrm *)pPg->GetNext();
1163 }
1164 else
1165 {
1166 // go to previous view layout row:
1167 do
1168 {
1169 pPg = (const SwPageFrm *)pPg->GetPrev();
1170 }
1171 while( pPg && pPg->Frm().Top() == nPageTop );
1172
1173 while( pPg && pPg->IsEmptyPage() )
1174 pPg = (const SwPageFrm *)pPg->GetPrev();
1175 }
1176 }
1177 // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
1178 // standard.vor sein.
1179 return pPg ? pPg->GetPhyPageNum() : USHRT_MAX;
1180 }
1181
1182
GetPageCnt()1183 sal_uInt16 SwCrsrShell::GetPageCnt()
1184 {
1185 SET_CURR_SHELL( this );
1186 // gebe die Anzahl der Seiten zurueck
1187 return GetLayout()->GetPageNum();
1188 }
1189
1190 // Gehe zur naechsten SSelection
1191
1192
GoNextCrsr()1193 sal_Bool SwCrsrShell::GoNextCrsr()
1194 {
1195 // besteht ueberhaupt ein Ring ?
1196 if( pCurCrsr->GetNext() == pCurCrsr )
1197 return sal_False;
1198
1199 SET_CURR_SHELL( this );
1200 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
1201 pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1202
1203 // Bug 24086: auch alle anderen anzeigen
1204 if( !ActionPend() )
1205 {
1206 UpdateCrsr();
1207 pCurCrsr->Show();
1208 }
1209 return sal_True;
1210 }
1211
1212 // gehe zur vorherigen SSelection
1213
1214
GoPrevCrsr()1215 sal_Bool SwCrsrShell::GoPrevCrsr()
1216 {
1217 // besteht ueberhaupt ein Ring ?
1218 if( pCurCrsr->GetNext() == pCurCrsr )
1219 return sal_False;
1220
1221 SET_CURR_SHELL( this );
1222 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
1223 pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetPrev());
1224
1225 // Bug 24086: auch alle anderen anzeigen
1226 if( !ActionPend() )
1227 {
1228 UpdateCrsr();
1229 pCurCrsr->Show();
1230 }
1231
1232 return sal_True;
1233 }
1234
1235
GetCharRectAt(SwRect & rOrig,const SwPosition & rPos,SwCrsrMoveState * pCMS) const1236 sal_Bool SwCrsrShell::GetCharRectAt( SwRect& rOrig, const SwPosition& rPos,
1237 SwCrsrMoveState* pCMS ) const
1238 {
1239 SwCntntFrm * pFrm = GetCurrFrm();
1240 return pFrm ? pFrm->GetCharRect( rOrig, rPos, pCMS ) : sal_False;
1241 }
1242
1243
Paint(const Rectangle & rRect)1244 void SwCrsrShell::Paint( const Rectangle &rRect)
1245 {
1246 SET_CURR_SHELL( this );
1247
1248 // beim Painten immer alle Cursor ausschalten
1249 SwRect aRect( rRect );
1250
1251 sal_Bool bVis = sal_False;
1252 // ist Cursor sichtbar, dann verstecke den SV-Cursor
1253 if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) ) //JP 18.06.97: ???
1254 {
1255 bVis = sal_True;
1256 pVisCrsr->Hide();
1257 }
1258
1259 // Bereich neu painten
1260 ViewShell::Paint( rRect );
1261
1262 if( bHasFocus && !bBasicHideCrsr )
1263 {
1264 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
1265 // pAktCrsr->Invalidate( aRect );
1266 if( !ActionPend() )
1267 {
1268 // damit nicht rechts/unten die Raender abgeschnitten werden
1269 pAktCrsr->Invalidate( VisArea() );
1270 pAktCrsr->Show();
1271 }
1272 else
1273 pAktCrsr->Invalidate( aRect );
1274
1275 }
1276 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
1277 pVisCrsr->Show();
1278 }
1279
1280
1281
VisPortChgd(const SwRect & rRect)1282 void SwCrsrShell::VisPortChgd( const SwRect & rRect )
1283 {
1284 SET_CURR_SHELL( this );
1285 sal_Bool bVis; // beim Scrollen immer alle Cursor ausschalten
1286
1287 // ist Cursor sichtbar, dann verstecke den SV-Cursor
1288 if( sal_True == ( bVis = pVisCrsr->IsVisible() ))
1289 pVisCrsr->Hide();
1290
1291 bVisPortChgd = sal_True;
1292 aOldRBPos.X() = VisArea().Right();
1293 aOldRBPos.Y() = VisArea().Bottom();
1294
1295 //Damit es es keine Probleme mit dem SV-Cursor gibt, wird in
1296 //ViewShell::VisPo.. ein Update() auf das Window gerufen.
1297 //Waehrend des Paintens duerfen aber nun wieder keine Selectionen
1298 //angezeigt werden, deshalb wird der Aufruf hier geklammert.
1299 ViewShell::VisPortChgd( rRect ); // Bereich verschieben
1300
1301 /*
1302 SwRect aRect( rRect );
1303 if( VisArea().IsOver( aRect ) )
1304 pCurCrsr->Invalidate( aRect );
1305 */
1306
1307 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
1308 pVisCrsr->Show();
1309
1310 if( nCrsrMove )
1311 bInCMvVisportChgd = sal_True;
1312
1313 bVisPortChgd = sal_False;
1314 }
1315
1316 // aktualisiere den Crsrs, d.H. setze ihn wieder in den Content.
1317 // Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim
1318 // Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position
1319 // ergibt sich aus seiner aktuellen Position im Layout !!
1320
1321
UpdateCrsrPos()1322 void SwCrsrShell::UpdateCrsrPos()
1323 {
1324 SET_CURR_SHELL( this );
1325 ++nStartAction;
1326 SwShellCrsr* pShellCrsr = getShellCrsr( true );
1327 Size aOldSz( GetDocSize() );
1328 SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
1329 SwCntntFrm *pFrm = pCNode ?
1330 pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ) :0;
1331 if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) )
1332 {
1333 SwCrsrMoveState aTmpState( MV_NONE );
1334 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1335 GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
1336 &aTmpState );
1337 if( pShellCrsr->HasMark())
1338 pShellCrsr->DeleteMark();
1339 }
1340 IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
1341 if( pGrammarContact )
1342 pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() );
1343 --nStartAction;
1344 if( aOldSz != GetDocSize() )
1345 SizeChgNotify();
1346 }
1347
1348 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1349 // stehen, so mussen diese daraus verschoben werden
lcl_CheckHiddenSection(SwNodeIndex & rIdx)1350 static void lcl_CheckHiddenSection( SwNodeIndex& rIdx )
1351 {
1352 const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
1353 if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
1354 {
1355 SwNodeIndex aTmp( *pSectNd );
1356 #if OSL_DEBUG_LEVEL > 1
1357 const SwNode* pFrmNd =
1358 #endif
1359 rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
1360
1361 #if OSL_DEBUG_LEVEL > 1
1362 (void) pFrmNd;
1363 ASSERT( pFrmNd, "keinen Node mit Frames gefunden" );
1364 #endif
1365 rIdx = aTmp;
1366 }
1367 }
1368
1369 // Try to set the cursor to the next visible content node.
lcl_CheckHiddenPara(SwPosition & rPos)1370 static void lcl_CheckHiddenPara( SwPosition& rPos )
1371 {
1372 SwNodeIndex aTmp( rPos.nNode );
1373 SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
1374 while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
1375 {
1376 SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
1377 if ( pCntnt && pCntnt->IsTxtNode() )
1378 pTxtNd = (SwTxtNode*)pCntnt;
1379 else
1380 pTxtNd = 0;
1381 }
1382
1383 if ( pTxtNd )
1384 rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
1385 }
1386
1387 // --> OD 2005-12-14 #i27301# - helper class, which notifies the accessibility
1388 // about invalid text selections in its destructor
1389 class SwNotifyAccAboutInvalidTextSelections
1390 {
1391 private:
1392 SwCrsrShell& mrCrsrSh;
1393
1394 public:
SwNotifyAccAboutInvalidTextSelections(SwCrsrShell & _rCrsrSh)1395 SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
1396 : mrCrsrSh( _rCrsrSh )
1397 {}
1398
~SwNotifyAccAboutInvalidTextSelections()1399 ~SwNotifyAccAboutInvalidTextSelections()
1400 {
1401 mrCrsrSh.InvalidateAccessibleParaTextSelection();
1402 }
1403 };
1404 // <--
UpdateCrsr(sal_uInt16 eFlags,sal_Bool bIdleEnd)1405 void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd )
1406 {
1407 SET_CURR_SHELL( this );
1408
1409 ClearUpCrsrs();
1410
1411 // erfrage den Count fuer die Start-/End-Actions und ob die Shell
1412 // ueberhaupt den Focus hat
1413 // if( ActionPend() /*|| !bHasFocus*/ )
1414 //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction der
1415 // Cursor geupdatet werden; um z.B. den TabellenCursor zu
1416 // erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen!
1417 if( ActionPend() && BasicActionPend() )
1418 {
1419 if ( eFlags & SwCrsrShell::READONLY )
1420 bIgnoreReadonly = sal_True;
1421 return; // wenn nicht, dann kein Update !!
1422 }
1423
1424 SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
1425
1426 if ( bIgnoreReadonly )
1427 {
1428 bIgnoreReadonly = sal_False;
1429 eFlags |= SwCrsrShell::READONLY;
1430 }
1431
1432 if( eFlags & SwCrsrShell::CHKRANGE ) // alle Cursor-Bewegungen auf
1433 CheckRange( pCurCrsr ); // ueberlappende Bereiche testen
1434
1435 if( !bIdleEnd )
1436 CheckTblBoxCntnt();
1437
1438 // steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen
1439 // (oder ist noch TabellenMode), dann gilt der Tabellen Mode
1440 SwPaM* pTstCrsr = getShellCrsr( true );
1441 if( pTstCrsr->HasMark() && !pBlockCrsr &&
1442 pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
1443 ( pTblCrsr ||
1444 pTstCrsr->GetNode( sal_True )->StartOfSectionNode() !=
1445 pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) )
1446 {
1447 SwShellCrsr* pITmpCrsr = getShellCrsr( true );
1448 Point aTmpPt( pITmpCrsr->GetPtPos() );
1449 Point aTmpMk( pITmpCrsr->GetMkPos() );
1450 SwPosition* pPos = pITmpCrsr->GetPoint();
1451
1452 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1453 // stehen, so mussen diese daraus verschoben werden
1454 lcl_CheckHiddenSection( pPos->nNode );
1455 lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
1456
1457 // Move cursor out of hidden paragraphs
1458 if ( !GetViewOptions()->IsShowHiddenChar() )
1459 {
1460 lcl_CheckHiddenPara( *pPos );
1461 lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
1462 }
1463
1464 SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
1465 getLayoutFrm( GetLayout(), &aTmpPt, pPos, sal_False );
1466
1467 ASSERT( pTblFrm, "Tabelle Crsr nicht im Content ??" );
1468
1469 // --> FME 2005-12-02 #126107# Make code robust. The table
1470 // cursor may point to a table in a currently inactive header.
1471 SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
1472 // <--
1473
1474 if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
1475 {
1476 // First check if point is in repeated headline:
1477 bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
1478
1479 // Second check if mark is in repeated headline:
1480 if ( !bInRepeatedHeadline )
1481 {
1482 SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( sal_False )->
1483 getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), sal_False );
1484 ASSERT( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
1485
1486 if ( pMarkTblFrm )
1487 {
1488 SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
1489 ASSERT( pMarkTab, "Tabelle Crsr nicht im Content ??" );
1490
1491 // --> FME 2005-11-28 #120360# Make code robust:
1492 if ( pMarkTab )
1493 {
1494 bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
1495 }
1496 // <--
1497 }
1498 }
1499
1500 // No table cursor in repeaded headlines:
1501 if ( bInRepeatedHeadline )
1502 {
1503 pTblFrm = 0;
1504
1505 SwPosSection fnPosSect = *pPos < *pITmpCrsr->GetMark()
1506 ? fnSectionStart
1507 : fnSectionEnd;
1508
1509 // dann nur innerhalb der Box selektieren
1510 if( pTblCrsr )
1511 {
1512 pCurCrsr->SetMark();
1513 *pCurCrsr->GetMark() = *pTblCrsr->GetMark();
1514 pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos();
1515 pTblCrsr->DeleteMark();
1516 pTblCrsr->SwSelPaintRects::Hide();
1517 }
1518
1519 *pCurCrsr->GetPoint() = *pCurCrsr->GetMark();
1520 (*fnSectionCurr)( *pCurCrsr, fnPosSect );
1521 }
1522 }
1523
1524 // wir wollen wirklich eine Tabellen-Selektion
1525 if( pTab && pTblFrm )
1526 {
1527 if( !pTblCrsr )
1528 {
1529 pTblCrsr = new SwShellTableCrsr( *this,
1530 *pCurCrsr->GetMark(), pCurCrsr->GetMkPos(),
1531 *pPos, aTmpPt );
1532 pCurCrsr->DeleteMark();
1533 pCurCrsr->SwSelPaintRects::Hide();
1534
1535 CheckTblBoxCntnt();
1536 }
1537
1538 SwCrsrMoveState aTmpState( MV_NONE );
1539 aTmpState.bRealHeight = sal_True;
1540 if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) )
1541 {
1542 Point aCentrPt( aCharRect.Center() );
1543 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1544 pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
1545 #ifndef DBG_UTIL
1546 pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() );
1547 #else
1548 if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) )
1549 ASSERT( sal_False, "GetCharRect failed." );
1550 #endif
1551 }
1552 // ALIGNRECT( aCharRect );
1553
1554 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
1555 // Curosr in den sichtbaren Bereich scrollen
1556 if( (eFlags & SwCrsrShell::SCROLLWIN) &&
1557 (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1558 !IsCrsrReadonly()) )
1559 {
1560 SwFrm* pBoxFrm = pTblFrm;
1561 while( pBoxFrm && !pBoxFrm->IsCellFrm() )
1562 pBoxFrm = pBoxFrm->GetUpper();
1563 if( pBoxFrm && pBoxFrm->Frm().HasArea() )
1564 MakeVisible( pBoxFrm->Frm() );
1565 else
1566 MakeVisible( aCharRect );
1567 }
1568
1569 // lasse vom Layout die Crsr in den Boxen erzeugen
1570 if( pTblCrsr->IsCrsrMovedUpdt() )
1571 GetLayout()->MakeTblCrsrs( *pTblCrsr );
1572 if( bHasFocus && !bBasicHideCrsr )
1573 pTblCrsr->Show();
1574
1575 // Cursor-Points auf die neuen Positionen setzen
1576 pTblCrsr->GetPtPos().X() = aCharRect.Left();
1577 pTblCrsr->GetPtPos().Y() = aCharRect.Top();
1578
1579 if( bSVCrsrVis )
1580 {
1581 aCrsrHeight.X() = 0;
1582 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1583 -aCharRect.Width() : aCharRect.Height();
1584 pVisCrsr->Show(); // wieder anzeigen
1585 }
1586 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
1587 if( pTblFrm && Imp()->IsAccessible() )
1588 Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
1589 return;
1590 }
1591 }
1592
1593 if( pTblCrsr )
1594 {
1595 // Cursor Ring loeschen
1596 while( pCurCrsr->GetNext() != pCurCrsr )
1597 delete pCurCrsr->GetNext();
1598 pCurCrsr->DeleteMark();
1599 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
1600 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
1601 delete pTblCrsr, pTblCrsr = 0;
1602 }
1603
1604 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
1605
1606 // sind wir vielleicht in einer geschuetzten/versteckten Section ?
1607 {
1608 SwShellCrsr* pShellCrsr = getShellCrsr( true );
1609 sal_Bool bChgState = sal_True;
1610 const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode();
1611 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
1612 ( !IsReadOnlyAvailable() &&
1613 pSectNd->GetSection().IsProtectFlag() &&
1614 ( !pDoc->GetDocShell() ||
1615 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) )
1616 {
1617 if( !FindValidCntntNode( !HasDrawView() ||
1618 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1619 {
1620 // alles ist geschuetzt / versteckt -> besonderer Mode
1621 if( bAllProtect && !IsReadOnlyAvailable() &&
1622 pSectNd->GetSection().IsProtectFlag() )
1623 bChgState = sal_False;
1624 else
1625 {
1626 eMvState = MV_NONE; // Status fuers Crsr-Travelling
1627 bAllProtect = sal_True;
1628 if( GetDoc()->GetDocShell() )
1629 {
1630 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1631 CallChgLnk(); // UI bescheid sagen!
1632 }
1633 return;
1634 }
1635 }
1636 }
1637 if( bChgState )
1638 {
1639 sal_Bool bWasAllProtect = bAllProtect;
1640 bAllProtect = sal_False;
1641 if( bWasAllProtect && GetDoc()->GetDocShell() &&
1642 GetDoc()->GetDocShell()->IsReadOnlyUI() )
1643 {
1644 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1645 CallChgLnk(); // UI bescheid sagen!
1646 }
1647 }
1648 }
1649
1650 UpdateCrsrPos();
1651
1652 // #100722# The cursor must always point into content; there's some code
1653 // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
1654 // loops _behind_ the last node in the selection, which always works if you
1655 // are in content.) To achieve this, we'll force cursor(s) to point into
1656 // content, if UpdateCrsrPos() hasn't already done so.
1657 SwPaM* pCmp = pCurCrsr;
1658 do
1659 {
1660 // start will move forwards, end will move backwards
1661 bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
1662
1663 // move point; forward if it's the start, backwards if it's the end
1664 if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
1665 pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
1666 fnGoCntnt );
1667
1668 // move mark (if exists); forward if it's the start, else backwards
1669 if( pCmp->HasMark() )
1670 {
1671 if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
1672 {
1673 pCmp->Exchange();
1674 pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
1675 fnGoCntnt );
1676 pCmp->Exchange();
1677 }
1678 }
1679
1680 // iterate to next PaM in ring
1681 pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
1682 }
1683 while( pCmp != pCurCrsr );
1684
1685
1686 SwRect aOld( aCharRect );
1687 sal_Bool bFirst = sal_True;
1688 SwCntntFrm *pFrm;
1689 int nLoopCnt = 100;
1690 SwShellCrsr* pShellCrsr = getShellCrsr( true );
1691
1692 do {
1693 sal_Bool bAgainst;
1694 do {
1695 bAgainst = sal_False;
1696 pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1697 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1698 // ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout
1699 // erzeugt werden, weil ja mal hier einer vorhanden war !!
1700 if ( !pFrm )
1701 {
1702 do
1703 {
1704 CalcLayout();
1705 pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1706 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1707 } while( !pFrm );
1708 }
1709 else if ( Imp()->IsIdleAction() )
1710 //Wir stellen sicher, dass anstaendig Formatiert wurde #42224#
1711 pFrm->PrepareCrsr();
1712
1713 // im geschuetzten Fly? aber bei Rahmenselektion ignorieren
1714 if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
1715 ( !Imp()->GetDrawView() ||
1716 !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
1717 (!pDoc->GetDocShell() ||
1718 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) )
1719 {
1720 // dann suche eine gueltige Position
1721 sal_Bool bChgState = sal_True;
1722 if( !FindValidCntntNode(!HasDrawView() ||
1723 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1724 {
1725 // alles ist geschuetzt / versteckt -> besonderer Mode
1726 if( bAllProtect )
1727 bChgState = sal_False;
1728 else
1729 {
1730 eMvState = MV_NONE; // Status fuers Crsr-Travelling
1731 bAllProtect = sal_True;
1732 if( GetDoc()->GetDocShell() )
1733 {
1734 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1735 CallChgLnk(); // UI bescheid sagen!
1736 }
1737 return;
1738 }
1739 }
1740
1741 if( bChgState )
1742 {
1743 sal_Bool bWasAllProtect = bAllProtect;
1744 bAllProtect = sal_False;
1745 if( bWasAllProtect && GetDoc()->GetDocShell() &&
1746 GetDoc()->GetDocShell()->IsReadOnlyUI() )
1747 {
1748 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1749 CallChgLnk(); // UI bescheid sagen!
1750 }
1751 bAllProtect = sal_False;
1752 bAgainst = sal_True; // nochmal den richigen Frm suchen
1753 }
1754 }
1755 } while( bAgainst );
1756
1757 if( !( eFlags & SwCrsrShell::NOCALRECT ))
1758 {
1759 SwCrsrMoveState aTmpState( eMvState );
1760 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1761 aTmpState.bRealHeight = sal_True;
1762 aTmpState.bRealWidth = IsOverwriteCrsr();
1763 aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
1764
1765 // #i27615#,#i30453#
1766 SwSpecialPos aSpecialPos;
1767 aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
1768 if (pShellCrsr->IsInFrontOfLabel())
1769 {
1770 aTmpState.pSpecialPos = &aSpecialPos;
1771 }
1772
1773 if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
1774 {
1775 Point& rPt = pShellCrsr->GetPtPos();
1776 rPt = aCharRect.Center();
1777 pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
1778 }
1779 // ALIGNRECT( aCharRect );
1780
1781 if( !pShellCrsr->HasMark() )
1782 aCrsrHeight = aTmpState.aRealHeight;
1783 else
1784 {
1785 aCrsrHeight.X() = 0;
1786 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1787 -aCharRect.Width() : aCharRect.Height();
1788 }
1789 }
1790 else
1791 {
1792 aCrsrHeight.X() = 0;
1793 aCrsrHeight.Y() = aCharRect.Height();
1794 }
1795
1796 if( !bFirst && aOld == aCharRect )
1797 break;
1798
1799 // falls das Layout meint, nach dem 100 durchlauf ist man immer noch
1800 // im Fluss, sollte man die akt. Pos. als gegeben hinnehmen!
1801 // siehe Bug: 29658
1802 if( !--nLoopCnt )
1803 {
1804 ASSERT( sal_False, "Endless loop? CharRect != OldCharRect ");
1805 break;
1806 }
1807 aOld = aCharRect;
1808 bFirst = sal_False;
1809
1810 // Cursor-Points auf die neuen Positionen setzen
1811 pShellCrsr->GetPtPos().X() = aCharRect.Left();
1812 pShellCrsr->GetPtPos().Y() = aCharRect.Top();
1813
1814 if( !(eFlags & SwCrsrShell::UPDOWN )) // alte Pos. von Up/Down loeschen
1815 {
1816 pFrm->Calc();
1817 nUpDownX = pFrm->IsVertical() ?
1818 aCharRect.Top() - pFrm->Frm().Top() :
1819 aCharRect.Left() - pFrm->Frm().Left();
1820 }
1821
1822 // Curosr in den sichtbaren Bereich scrollen
1823 if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
1824 (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1825 !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
1826 {
1827 //JP 30.04.99: damit das EndAction, beim evtuellen Scrollen, den
1828 // SV-Crsr nicht wieder sichtbar macht, wird hier das Flag
1829 // gesichert und zurueckgesetzt.
1830 sal_Bool bSav = bSVCrsrVis; bSVCrsrVis = sal_False;
1831 MakeSelVisible();
1832 bSVCrsrVis = bSav;
1833 }
1834
1835 } while( eFlags & SwCrsrShell::SCROLLWIN );
1836
1837 if( pBlockCrsr )
1838 RefreshBlockCursor();
1839
1840 if( !bIdleEnd && bHasFocus && !bBasicHideCrsr )
1841 {
1842 if( pTblCrsr )
1843 pTblCrsr->SwSelPaintRects::Show();
1844 else
1845 {
1846 pCurCrsr->SwSelPaintRects::Show();
1847 if( pBlockCrsr )
1848 {
1849 SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1850 while( pNxt && pNxt != pCurCrsr )
1851 {
1852 pNxt->SwSelPaintRects::Show();
1853 pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
1854 }
1855 }
1856 }
1857 }
1858
1859 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
1860
1861 if( pFrm && Imp()->IsAccessible() )
1862 Imp()->InvalidateAccessibleCursorPosition( pFrm );
1863
1864 // switch from blinking cursor to read-only-text-selection cursor
1865 static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
1866 const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
1867 GetCursorBlinkTime();
1868
1869 if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
1870 ( nBlinkTime != nNoBlinkTime ) )
1871 {
1872 // non blinking cursor in read only - text selection mode
1873 AllSettings aSettings = GetOut()->GetSettings();
1874 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1875 const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
1876 Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
1877 nNoBlinkTime;
1878 aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
1879 aSettings.SetStyleSettings( aStyleSettings );
1880 GetOut()->SetSettings( aSettings );
1881 }
1882
1883 if( bSVCrsrVis )
1884 pVisCrsr->Show(); // wieder anzeigen
1885 }
1886
RefreshBlockCursor()1887 void SwCrsrShell::RefreshBlockCursor()
1888 {
1889 ASSERT( pBlockCrsr, "Don't call me without a block cursor" );
1890 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
1891 Point aPt = rBlock.GetPtPos();
1892 SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), sal_False );
1893 Point aMk;
1894 if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() )
1895 {
1896 aPt = *pBlockCrsr->getStartPoint();
1897 aMk = *pBlockCrsr->getEndPoint();
1898 }
1899 else
1900 {
1901 aPt = rBlock.GetPtPos();
1902 if( pFrm )
1903 {
1904 if( pFrm->IsVertical() )
1905 aPt.Y() = pFrm->Frm().Top() + GetUpDownX();
1906 else
1907 aPt.X() = pFrm->Frm().Left() + GetUpDownX();
1908 }
1909 aMk = rBlock.GetMkPos();
1910 }
1911 SwRect aRect( aMk, aPt );
1912 aRect.Justify();
1913 SwSelectionList aSelList( pFrm );
1914
1915 if( GetLayout()->FillSelection( aSelList, aRect ) )
1916 {
1917 SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext();
1918 while( pNxt != pCurCrsr )
1919 {
1920 delete pNxt;
1921 pNxt = (SwCursor*)pCurCrsr->GetNext();
1922 }
1923
1924 std::list<SwPaM*>::iterator pStart = aSelList.getStart();
1925 std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
1926 ASSERT( pPam != pStart, "FillSelection should deliver at least one PaM" )
1927 pCurCrsr->SetMark();
1928 --pPam;
1929 // If there is only one text portion inside the rectangle, a simple
1930 // selection is created
1931 if( pPam == pStart )
1932 {
1933 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
1934 if( (*pPam)->HasMark() )
1935 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1936 else
1937 pCurCrsr->DeleteMark();
1938 delete *pPam;
1939 pCurCrsr->SetColumnSelection( false );
1940 }
1941 else
1942 {
1943 // The order of the SwSelectionList has to be preserved but
1944 // the order inside the ring created by CreateCrsr() is not like
1945 // exspected => First create the selections before the last one
1946 // downto the first selection.
1947 // At least create the cursor for the last selection
1948 --pPam;
1949 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
1950 if( (*pPam)->HasMark() )
1951 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1952 else
1953 pCurCrsr->DeleteMark();
1954 delete *pPam;
1955 pCurCrsr->SetColumnSelection( true );
1956 while( pPam != pStart )
1957 {
1958 --pPam;
1959
1960 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1961 pNew->Insert( pCurCrsr, 0 );
1962 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1963 pCurCrsr->DeleteMark();
1964
1965 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
1966 if( (*pPam)->HasMark() )
1967 {
1968 pCurCrsr->SetMark();
1969 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1970 }
1971 else
1972 pCurCrsr->DeleteMark();
1973 pCurCrsr->SetColumnSelection( true );
1974 delete *pPam;
1975 }
1976 {
1977 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1978 pNew->Insert( pCurCrsr, 0 );
1979 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1980 pCurCrsr->DeleteMark();
1981 }
1982 pPam = aSelList.getEnd();
1983 --pPam;
1984 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
1985 if( (*pPam)->HasMark() )
1986 {
1987 pCurCrsr->SetMark();
1988 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1989 }
1990 else
1991 pCurCrsr->DeleteMark();
1992 pCurCrsr->SetColumnSelection( true );
1993 delete *pPam;
1994 }
1995 }
1996 }
1997
1998 // erzeuge eine Kopie vom Cursor und speicher diese im Stack
1999
2000
Push()2001 void SwCrsrShell::Push()
2002 {
2003 pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(),
2004 pCurCrsr->GetPtPos(), pCrsrStk );
2005
2006 if( pCurCrsr->HasMark() )
2007 {
2008 pCrsrStk->SetMark();
2009 *pCrsrStk->GetMark() = *pCurCrsr->GetMark();
2010 }
2011 }
2012
2013 /*
2014 * Loescht einen Cursor (gesteuert durch bOldCrsr)
2015 * - vom Stack oder ( bOldCrsr = sal_True )
2016 * - den aktuellen und der auf dem Stack stehende wird zum aktuellen
2017 *
2018 * Return: es war auf dem Stack noch einer vorhanden
2019 */
2020
2021
Pop(sal_Bool bOldCrsr)2022 sal_Bool SwCrsrShell::Pop( sal_Bool bOldCrsr )
2023 {
2024 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
2025
2026 // noch weitere vorhanden ?
2027 if( 0 == pCrsrStk )
2028 return sal_False;
2029
2030 SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk;
2031
2032 // der Nachfolger wird der Aktuelle
2033 if( pCrsrStk->GetNext() != pCrsrStk )
2034 {
2035 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
2036 }
2037
2038 if( bOldCrsr ) // loesche vom Stack
2039 delete pCrsrStk; //
2040
2041 pCrsrStk = pTmp; // neu zuweisen
2042
2043 if( !bOldCrsr )
2044 {
2045 SwCrsrSaveState aSaveState( *pCurCrsr );
2046
2047 // wurde die sichtbare SSelection nicht veraendert
2048 if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() ||
2049 pOldStk->GetPtPos() == pCurCrsr->GetMkPos() )
2050 {
2051 // "Selektions-Rechtecke" verschieben
2052 pCurCrsr->Insert( pOldStk, 0 );
2053 pOldStk->Remove( 0, pOldStk->Count() );
2054 }
2055
2056 if( pOldStk->HasMark() )
2057 {
2058 pCurCrsr->SetMark();
2059 *pCurCrsr->GetMark() = *pOldStk->GetMark();
2060 pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
2061 }
2062 else
2063 // keine Selection also alte aufheben und auf die alte Pos setzen
2064 pCurCrsr->DeleteMark();
2065 *pCurCrsr->GetPoint() = *pOldStk->GetPoint();
2066 pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
2067 delete pOldStk;
2068
2069 if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2070 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2071 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2072 UpdateCrsr(); // akt. Cursor Updaten
2073 }
2074 return sal_True;
2075 }
2076
2077 /*
2078 * Verbinde zwei Cursor miteinander.
2079 * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen.
2080 */
2081
2082
Combine()2083 void SwCrsrShell::Combine()
2084 {
2085 // noch weitere vorhanden ?
2086 if( 0 == pCrsrStk )
2087 return;
2088
2089 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
2090 SwCrsrSaveState aSaveState( *pCurCrsr );
2091 if( pCrsrStk->HasMark() ) // nur wenn GetMark gesetzt wurde
2092 {
2093 #ifndef DBG_UTIL
2094 CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True );
2095 #else
2096 if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True ))
2097 ASSERT( sal_False, "StackCrsr & act. Crsr not in the same section." );
2098 #endif
2099 // kopiere das GetMark
2100 if( !pCurCrsr->HasMark() )
2101 pCurCrsr->SetMark();
2102 *pCurCrsr->GetMark() = *pCrsrStk->GetMark();
2103 pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos();
2104 }
2105
2106 SwShellCrsr * pTmp = 0;
2107 if( pCrsrStk->GetNext() != pCrsrStk )
2108 {
2109 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
2110 }
2111 delete pCrsrStk;
2112 pCrsrStk = pTmp;
2113 if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2114 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2115 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2116 UpdateCrsr(); // akt. Cursor Updaten
2117 }
2118
2119
HideCrsrs()2120 void SwCrsrShell::HideCrsrs()
2121 {
2122 if( !bHasFocus || bBasicHideCrsr )
2123 return;
2124
2125 // ist Cursor sichtbar, dann verstecke den SV-Cursor
2126 if( pVisCrsr->IsVisible() )
2127 {
2128 SET_CURR_SHELL( this );
2129 pVisCrsr->Hide();
2130 }
2131 // hebe die Invertierung der SSelection auf
2132 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2133 pAktCrsr->Hide();
2134 }
2135
2136
2137
ShowCrsrs(sal_Bool bCrsrVis)2138 void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis )
2139 {
2140 if( !bHasFocus || bAllProtect || bBasicHideCrsr )
2141 return;
2142
2143 SET_CURR_SHELL( this );
2144 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2145 pAktCrsr->Show();
2146
2147 if( bSVCrsrVis && bCrsrVis ) // auch SV-Cursor wieder anzeigen
2148 pVisCrsr->Show();
2149 }
2150
2151 // Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors
2152
2153
ShowCrsr()2154 void SwCrsrShell::ShowCrsr()
2155 {
2156 if( !bBasicHideCrsr )
2157 {
2158 bSVCrsrVis = sal_True;
2159 pCurCrsr->SetShowTxtInputFldOverlay( true );
2160 UpdateCrsr();
2161 }
2162 }
2163
2164
HideCrsr()2165 void SwCrsrShell::HideCrsr()
2166 {
2167 if( !bBasicHideCrsr )
2168 {
2169 bSVCrsrVis = sal_False;
2170 // evt. die sel. Bereiche aufheben !!
2171 SET_CURR_SHELL( this );
2172 pCurCrsr->SetShowTxtInputFldOverlay( false );
2173 pVisCrsr->Hide();
2174 }
2175 }
2176
2177
ShLooseFcs()2178 void SwCrsrShell::ShLooseFcs()
2179 {
2180 if( !bBasicHideCrsr )
2181 HideCrsrs();
2182 bHasFocus = sal_False;
2183 }
2184
2185
ShGetFcs(sal_Bool bUpdate)2186 void SwCrsrShell::ShGetFcs( sal_Bool bUpdate )
2187 {
2188 bHasFocus = sal_True;
2189 if( !bBasicHideCrsr && VisArea().Width() )
2190 {
2191 UpdateCrsr( static_cast<sal_uInt16>( bUpdate ?
2192 SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
2193 : SwCrsrShell::CHKRANGE ) );
2194 ShowCrsrs( bSVCrsrVis ? sal_True : sal_False );
2195 }
2196 }
2197
2198 // gebe den aktuellen Frame, in dem der Cursor steht, zurueck
2199
GetCurrFrm(const sal_Bool bCalcFrm) const2200 SwCntntFrm *SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm ) const
2201 {
2202 SET_CURR_SHELL( (ViewShell*)this );
2203 SwCntntFrm *pRet = 0;
2204 SwCntntNode *pNd = pCurCrsr->GetCntntNode();
2205 if ( pNd )
2206 {
2207 if ( bCalcFrm )
2208 {
2209 const sal_uInt16* pST = &nStartAction;
2210 ++(*((sal_uInt16*)pST));
2211 const Size aOldSz( GetDocSize() );
2212 pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() );
2213 --(*((sal_uInt16*)pST));
2214 if( aOldSz != GetDocSize() )
2215 ((SwCrsrShell*)this)->SizeChgNotify();
2216 }
2217 else
2218 pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), sal_False);
2219 }
2220 return pRet;
2221 }
2222
2223
2224 // alle Attribut/Format-Aenderungen am akt. Node werden an den
2225 // Link weitergeleitet.
2226
2227
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)2228 void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2229 {
2230 const sal_uInt16 nWhich = pOld ?
2231 pOld->Which() :
2232 pNew ?
2233 pNew->Which() :
2234 sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN);
2235
2236 if( bCallChgLnk &&
2237 ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
2238 nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
2239 nWhich == RES_ATTRSET_CHG ))
2240 // die Messages werden nicht weitergemeldet
2241 //MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom
2242 //SwTxtNode::Insert(SwTxtHint*, sal_uInt16) abgesetzt; hier wird reagiert und
2243 //vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden.
2244 CallChgLnk();
2245
2246 if( aGrfArrivedLnk.IsSet() &&
2247 ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
2248 aGrfArrivedLnk.Call( this );
2249 }
2250
2251
2252 // Abfrage, ob der aktuelle Cursor eine Selektion aufspannt,
2253 // also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind.
2254
2255
HasSelection() const2256 sal_Bool SwCrsrShell::HasSelection() const
2257 {
2258 const SwPaM* pCrsr = getShellCrsr( true );
2259 return( IsTableMode() || ( pCrsr->HasMark() &&
2260 *pCrsr->GetPoint() != *pCrsr->GetMark())
2261 ? sal_True : sal_False );
2262 }
2263
2264
CallChgLnk()2265 void SwCrsrShell::CallChgLnk()
2266 {
2267 // innerhalb von Start-/End-Action kein Call, sondern nur merken,
2268 // das sich etwas geaendert hat. Wird bei EndAction beachtet.
2269 if( BasicActionPend() )
2270 bChgCallFlag = sal_True; // das Change merken
2271 else if( aChgLnk.IsSet() )
2272 {
2273 if( bCallChgLnk )
2274 aChgLnk.Call( this );
2275 bChgCallFlag = sal_False; // Flag zuruecksetzen
2276 }
2277 }
2278
2279 // returne den am akt.Cursor selektierten Text eines Nodes.
2280
2281
GetSelTxt() const2282 String SwCrsrShell::GetSelTxt() const
2283 {
2284 String aTxt;
2285 if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2286 pCurCrsr->GetMark()->nNode.GetIndex() )
2287 {
2288 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2289 if( pTxtNd )
2290 {
2291 xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex();
2292 aTxt = pTxtNd->GetExpandTxt( nStt,
2293 pCurCrsr->End()->nContent.GetIndex() - nStt );
2294 }
2295 }
2296 return aTxt;
2297 }
2298
2299 // gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde)
2300
2301
GetText() const2302 String SwCrsrShell::GetText() const
2303 {
2304 String aTxt;
2305 if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2306 pCurCrsr->GetMark()->nNode.GetIndex() )
2307 {
2308 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2309 if( pTxtNd )
2310 aTxt = pTxtNd->GetTxt().Copy(
2311 pCurCrsr->GetPoint()->nContent.GetIndex() );
2312 }
2313 return aTxt;
2314 }
2315
2316 // hole vom Start/Ende der akt. SSelection das nte Zeichen
GetChar(sal_Bool bEnd,long nOffset)2317 sal_Unicode SwCrsrShell::GetChar( sal_Bool bEnd, long nOffset )
2318 {
2319 if( IsTableMode() ) // im TabelleMode nicht moeglich
2320 return 0;
2321
2322 const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint()
2323 : bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2324 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2325 if( !pTxtNd )
2326 return 0;
2327
2328 xub_StrLen nPos = pPos->nContent.GetIndex();
2329 const String& rStr = pTxtNd->GetTxt();
2330 sal_Unicode cCh = 0;
2331
2332 if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() )
2333 cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) );
2334
2335 return cCh;
2336 }
2337
2338 // erweiter die akt. SSelection am Anfang/Ende um n Zeichen
2339
2340
ExtendSelection(sal_Bool bEnd,xub_StrLen nCount)2341 sal_Bool SwCrsrShell::ExtendSelection( sal_Bool bEnd, xub_StrLen nCount )
2342 {
2343 if( !pCurCrsr->HasMark() || IsTableMode() )
2344 return sal_False; // keine Selektion
2345
2346 SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2347 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2348 ASSERT( pTxtNd, "kein TextNode, wie soll erweitert werden?" );
2349
2350 xub_StrLen nPos = pPos->nContent.GetIndex();
2351 if( bEnd )
2352 {
2353 if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() )
2354 nPos = nPos + nCount;
2355 else
2356 return sal_False; // nicht mehr moeglich
2357 }
2358 else if( nPos >= nCount )
2359 nPos = nPos - nCount;
2360 else
2361 return sal_False; // nicht mehr moeglich
2362
2363 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
2364
2365 pPos->nContent = nPos;
2366 UpdateCrsr();
2367
2368 return sal_True;
2369 }
2370
2371 // setze nur den sichtbaren Cursor an die angegebene Dokument-Pos.
2372 // returnt sal_False: wenn der SPoint vom Layout korrigiert wurde.
2373
SetVisCrsr(const Point & rPt)2374 sal_Bool SwCrsrShell::SetVisCrsr( const Point &rPt )
2375 {
2376 SET_CURR_SHELL( this );
2377 Point aPt( rPt );
2378 SwPosition aPos( *pCurCrsr->GetPoint() );
2379 SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
2380 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2381 aTmpState.bRealHeight = sal_True;
2382
2383 sal_Bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
2384
2385 SetInFrontOfLabel( sal_False ); // #i27615#
2386
2387 // nur in TextNodes anzeigen !!
2388 SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
2389 if( !pTxtNd )
2390 return sal_False;
2391
2392 const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
2393 if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
2394 ( !IsReadOnlyAvailable() &&
2395 pSectNd->GetSection().IsProtectFlag())) )
2396 return sal_False;
2397
2398 SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos );
2399 if ( Imp()->IsIdleAction() )
2400 pFrm->PrepareCrsr();
2401 SwRect aTmp( aCharRect );
2402
2403 pFrm->GetCharRect( aCharRect, aPos, &aTmpState );
2404 // ALIGNRECT( aCharRect );
2405
2406 if( aTmp == aCharRect && // BUG 10137: bleibt der Cursor auf der
2407 pVisCrsr->IsVisible() ) // Position nicht hidden & showen
2408 return sal_True;
2409
2410 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
2411 if( IsScrollMDI( this, aCharRect ))
2412 {
2413 MakeVisible( aCharRect );
2414 pCurCrsr->Show();
2415 }
2416
2417 // Bug 29584: bei Rahmenselektion ist der Cursor versteckt, aber den
2418 // D&D-Cursor will man trotzdem haben
2419 // if( bSVCrsrVis )
2420 {
2421 if( aTmpState.bRealHeight )
2422 aCrsrHeight = aTmpState.aRealHeight;
2423 else
2424 {
2425 aCrsrHeight.X() = 0;
2426 aCrsrHeight.Y() = aCharRect.Height();
2427 }
2428
2429 pVisCrsr->SetDragCrsr( sal_True );
2430 pVisCrsr->Show(); // wieder anzeigen
2431 }
2432 return bRet;
2433 }
2434
IsOverReadOnlyPos(const Point & rPt) const2435 sal_Bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
2436 {
2437 Point aPt( rPt );
2438 SwPaM aPam( *pCurCrsr->GetPoint() );
2439 GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
2440 return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
2441 }
2442
2443
2444 // returne die Anzahl der Cursor im Ring (Flag besagt ob man nur
2445 // aufgepspannte haben will - sprich etwas selektiert ist (Basic))
GetCrsrCnt(sal_Bool bAll) const2446 sal_uInt16 SwCrsrShell::GetCrsrCnt( sal_Bool bAll ) const
2447 {
2448 Ring* pTmp = GetCrsr()->GetNext();
2449 sal_uInt16 n = (bAll || ( pCurCrsr->HasMark() &&
2450 *pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0;
2451 while( pTmp != pCurCrsr )
2452 {
2453 if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
2454 *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
2455 ++n;
2456 pTmp = pTmp->GetNext();
2457 }
2458 return n;
2459 }
2460
2461
IsStartOfDoc() const2462 sal_Bool SwCrsrShell::IsStartOfDoc() const
2463 {
2464 if( pCurCrsr->GetPoint()->nContent.GetIndex() )
2465 return sal_False;
2466
2467 // Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd)
2468 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
2469 if( !aIdx.GetNode().IsCntntNode() )
2470 GetDoc()->GetNodes().GoNext( &aIdx );
2471 return aIdx == pCurCrsr->GetPoint()->nNode;
2472 }
2473
2474
IsEndOfDoc() const2475 sal_Bool SwCrsrShell::IsEndOfDoc() const
2476 {
2477 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
2478 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
2479 if( !pCNd )
2480 pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
2481
2482 return aIdx == pCurCrsr->GetPoint()->nNode &&
2483 pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex();
2484 }
2485
2486
2487 // loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten
2488 // Cursor auf seinen TextNode (oder StartNode?).
2489 // Beim naechsten ::GetCrsr werden sie wieder alle erzeugt
2490 // Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt.
ParkTblCrsr()2491 sal_Bool SwCrsrShell::ParkTblCrsr()
2492 {
2493 if( !pTblCrsr )
2494 return sal_False;
2495
2496 pTblCrsr->ParkCrsr();
2497
2498 while( pCurCrsr->GetNext() != pCurCrsr )
2499 delete pCurCrsr->GetNext();
2500
2501 // vom Cursor !immer! SPoint und Mark umsetzen
2502 pCurCrsr->SetMark();
2503 *pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
2504 pCurCrsr->DeleteMark();
2505
2506 return sal_True;
2507 }
2508
2509 /***********************************************************************
2510 #* Class : SwCrsrShell
2511 #* Methode : ParkCrsr
2512 #* Beschreibung: Vernichtet Selektionen und zus. Crsr aller Shell der
2513 #* verbleibende Crsr der Shell wird geparkt.
2514 #* Datum : MA 05. Nov. 92
2515 #* Update : JP 19.09.97
2516 #***********************************************************************/
2517
_ParkPams(SwPaM * pDelRg,SwShellCrsr ** ppDelRing)2518 void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
2519 {
2520 const SwPosition *pStt = pDelRg->Start(),
2521 *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
2522
2523 SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
2524
2525 // durchsuche den gesamten Ring
2526 sal_Bool bGoNext;
2527 do {
2528 const SwPosition *pTmpStt = pTmp->Start(),
2529 *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
2530 pTmp->GetMark() : pTmp->GetPoint();
2531 /*
2532 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
2533 * muss der alte Bereich aufgehoben werden.
2534 * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum
2535 * Bereich gehoert !
2536 */
2537 if( *pStt <= *pTmpStt )
2538 {
2539 if( *pEnd > *pTmpStt ||
2540 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
2541 pTmpDel = pTmp;
2542 }
2543 else
2544 if( *pStt < *pTmpEnd )
2545 pTmpDel = pTmp;
2546
2547 bGoNext = sal_True;
2548 if( pTmpDel ) // ist der Pam im Bereich ?? loesche ihn
2549 {
2550 sal_Bool bDelete = sal_True;
2551 if( *ppDelRing == pTmpDel )
2552 {
2553 if( *ppDelRing == pCurCrsr )
2554 {
2555 if( sal_True == ( bDelete = GoNextCrsr() ))
2556 {
2557 bGoNext = sal_False;
2558 pTmp = (SwPaM*)pTmp->GetNext();
2559 }
2560 }
2561 else
2562 bDelete = sal_False; // StackCrsr nie loeschen !!
2563 }
2564
2565 if( bDelete )
2566 delete pTmpDel; // hebe alten Bereich auf
2567 else
2568 {
2569 pTmpDel->GetPoint()->nContent.Assign( 0, 0 );
2570 pTmpDel->GetPoint()->nNode = 0;
2571 pTmpDel->SetMark();
2572 pTmpDel->DeleteMark();
2573 }
2574 pTmpDel = 0;
2575 }
2576 else if( !pTmp->HasMark() ) // sorge auf jedenfall dafuer, das
2577 { // nicht benutzte Indizies beachtet werden!
2578 pTmp->SetMark(); // SPoint liegt nicht im Bereich,
2579 pTmp->DeleteMark(); // aber vielleicht GetMark, also setzen
2580 }
2581 if( bGoNext )
2582 pTmp = (SwPaM*)pTmp->GetNext();
2583 } while( !bGoNext || *ppDelRing != pTmp );
2584 }
2585
ParkCrsr(const SwNodeIndex & rIdx)2586 void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
2587 {
2588 SwNode *pNode = &rIdx.GetNode();
2589
2590 // erzeuge einen neuen Pam
2591 SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
2592 if( pNode->GetStartNode() )
2593 {
2594 if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
2595 {
2596 // der angegebene Node steht in einer Tabelle, also Parke
2597 // den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle)
2598 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2599 }
2600 else // also auf dem StartNode selbst.
2601 // Dann immer ueber seinen EndNode den StartNode erfragen !!!
2602 // (StartOfSection vom StartNode ist der Parent !)
2603 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
2604 }
2605 else
2606 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2607 pNew->SetMark();
2608 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
2609
2610 //Alle Shells wollen etwas davon haben.
2611 ViewShell *pTmp = this;
2612 do {
2613 if( pTmp->IsA( TYPE( SwCrsrShell )))
2614 {
2615 SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
2616 if( pSh->pCrsrStk )
2617 pSh->_ParkPams( pNew, &pSh->pCrsrStk );
2618
2619 pSh->_ParkPams( pNew, &pSh->pCurCrsr );
2620 if( pSh->pTblCrsr )
2621 {
2622 // setze den Tabellen Cursor immer auf 0, den aktuellen
2623 // immer auf den Anfang der Tabelle
2624 SwPaM* pTCrsr = pSh->GetTblCrs();
2625 SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
2626 if ( pTblNd )
2627 {
2628 pTCrsr->GetPoint()->nContent.Assign( 0, 0 );
2629 pTCrsr->GetPoint()->nNode = 0;
2630 pTCrsr->SetMark();
2631 pTCrsr->DeleteMark();
2632 pSh->pCurCrsr->GetPoint()->nNode = *pTblNd;
2633 }
2634 }
2635 }
2636 } while ( this != (pTmp = (ViewShell*)pTmp->GetNext() ));
2637 delete pNew;
2638 }
2639
2640 //=========================================================================
2641
2642 /*
2643 * der Copy-Constructor
2644 * Cursor-Position kopieren, in den Ring eingetragen.
2645 * Alle Ansichten eines Dokumentes stehen im Ring der Shells.
2646 */
2647
SwCrsrShell(SwCrsrShell & rShell,Window * pInitWin)2648 SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin )
2649 : ViewShell( rShell, pInitWin ),
2650 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2651 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2652 eMvState( MV_NONE ),
2653 // --> OD 2008-04-02 #refactorlists#
2654 sMarkedListId(),
2655 nMarkedListLevel( 0 )
2656 // <--
2657 {
2658 SET_CURR_SHELL( this );
2659 // Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen
2660 pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) );
2661 pCurCrsr->GetCntntNode()->Add( this );
2662
2663 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2664 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2665 bOverwriteCrsr = sal_False;
2666 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2667 bSetCrsrInReadOnly = sal_True;
2668 pVisCrsr = new SwVisCrsr( this );
2669 // UpdateCrsr( 0 );
2670 // OD 11.02.2003 #100556#
2671 mbMacroExecAllowed = rShell.IsMacroExecAllowed();
2672 oldColFrm = NULL;
2673 }
2674
2675
2676 /*
2677 * der normale Constructor
2678 */
2679
SwCrsrShell(SwDoc & rDoc,Window * pInitWin,const SwViewOption * pInitOpt)2680 SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin,
2681 const SwViewOption *pInitOpt )
2682 : ViewShell( rDoc, pInitWin, pInitOpt ),
2683 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2684 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2685 eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst
2686 // --> OD 2008-04-02 #refactorlists#
2687 sMarkedListId(),
2688 nMarkedListLevel( 0 )
2689 // <--
2690 {
2691 SET_CURR_SHELL( this );
2692 /*
2693 * Erzeugen des initialen Cursors, wird auf die erste
2694 * Inhaltsposition gesetzt
2695 */
2696 SwNodes& rNds = rDoc.GetNodes();
2697
2698 SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
2699 SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode
2700
2701 pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
2702
2703 // melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle
2704 // Attribut-Aenderungen ueber den Link weiter gemeldet werden.
2705 pCNd->Add( this );
2706
2707 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2708 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2709 bOverwriteCrsr = sal_False;
2710 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2711 bSetCrsrInReadOnly = sal_True;
2712
2713 pVisCrsr = new SwVisCrsr( this );
2714 // UpdateCrsr( 0 );
2715 // OD 11.02.2003 #100556#
2716 mbMacroExecAllowed = true;
2717 }
2718
2719
2720
~SwCrsrShell()2721 SwCrsrShell::~SwCrsrShell()
2722 {
2723 // wenn es nicht die letzte View so sollte zu mindest das
2724 // Feld noch geupdatet werden.
2725 if( GetNext() != this )
2726 CheckTblBoxCntnt( pCurCrsr->GetPoint() );
2727 else
2728 ClearTblBoxCntnt();
2729
2730 delete pVisCrsr;
2731 delete pBlockCrsr;
2732 delete pTblCrsr;
2733
2734 /*
2735 * Freigabe der Cursor
2736 */
2737 while(pCurCrsr->GetNext() != pCurCrsr)
2738 delete pCurCrsr->GetNext();
2739 delete pCurCrsr;
2740
2741 // Stack freigeben
2742 if( pCrsrStk )
2743 {
2744 while( pCrsrStk->GetNext() != pCrsrStk )
2745 delete pCrsrStk->GetNext();
2746 delete pCrsrStk;
2747 }
2748
2749 // JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in
2750 // der CursorShell haengt keine Chance geben, sich an den
2751 // TextNode zu haengen.
2752 if( GetRegisteredIn() )
2753 GetRegisteredInNonConst()->Remove( this );
2754 }
2755
getShellCrsr(bool bBlock)2756 SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
2757 {
2758 if( pTblCrsr )
2759 return pTblCrsr;
2760 if( pBlockCrsr && bBlock )
2761 return &pBlockCrsr->getShellCrsr();
2762 return pCurCrsr;
2763 }
2764
2765 //Sollte fuer das Clipboard der WaitPtr geschaltet werden?
2766 //Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen.
2767
ShouldWait() const2768 sal_Bool SwCrsrShell::ShouldWait() const
2769 {
2770 if ( IsTableMode() || GetCrsrCnt() > 1 )
2771 return sal_True;
2772
2773 if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2774 return sal_True;
2775
2776 SwPaM* pPam = GetCrsr();
2777 return pPam->Start()->nNode.GetIndex() + 10 <
2778 pPam->End()->nNode.GetIndex();
2779 }
2780
2781
UpdateTblSelBoxes()2782 sal_uInt16 SwCrsrShell::UpdateTblSelBoxes()
2783 {
2784 if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() ))
2785 GetLayout()->MakeTblCrsrs( *pTblCrsr );
2786 return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0;
2787 }
2788
2789 // zeige das akt. selektierte "Object" an
MakeSelVisible()2790 void SwCrsrShell::MakeSelVisible()
2791 {
2792 ASSERT( bHasFocus, "kein Focus aber Cursor sichtbar machen?" );
2793 if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() )
2794 {
2795 SwRect aTmp( aCharRect );
2796 long nDiff = aCharRect.Height() - VisArea().Height();
2797 if( nDiff < aCrsrHeight.X() )
2798 aTmp.Top( nDiff + aCharRect.Top() );
2799 else
2800 {
2801 aTmp.Top( aCrsrHeight.X() + aCharRect.Top() );
2802 aTmp.Height( aCrsrHeight.Y() );
2803 }
2804 if( !aTmp.HasArea() )
2805 {
2806 aTmp.SSize().Height() += 1;
2807 aTmp.SSize().Width() += 1;
2808 }
2809 MakeVisible( aTmp );
2810 }
2811 else
2812 {
2813 if( aCharRect.HasArea() )
2814 MakeVisible( aCharRect );
2815 else
2816 {
2817 SwRect aTmp( aCharRect );
2818 aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
2819 MakeVisible( aTmp );
2820 }
2821 }
2822 }
2823
2824
2825 // suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt)
FindValidCntntNode(sal_Bool bOnlyText)2826 sal_Bool SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText )
2827 {
2828 if( pTblCrsr ) // was soll ich jetzt machen ??
2829 {
2830 ASSERT( sal_False, "Table Selection not canceled!" );
2831 return sal_False;
2832 }
2833
2834 //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
2835 if( !bAllProtect && GetDoc()->GetDocShell() &&
2836 GetDoc()->GetDocShell()->IsReadOnlyUI() )
2837 return sal_True;
2838
2839 // dann raus da!
2840 if( pCurCrsr->HasMark() )
2841 ClearMark();
2842
2843 // als erstes mal auf Rahmen abpruefen
2844 SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode;
2845 sal_uLong nNdIdx = rNdIdx.GetIndex(); // sichern
2846 SwNodes& rNds = pDoc->GetNodes();
2847 SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
2848 const SwCntntFrm * pFrm;
2849
2850 if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(),0,pCurCrsr->GetPoint(),sal_False)) &&
2851 !IsReadOnlyAvailable() && pFrm->IsProtected() &&
2852 nNdIdx < rNds.GetEndOfExtras().GetIndex() )
2853 {
2854 // geschuetzter Rahmen ueberspringen
2855 SwPaM aPam( *pCurCrsr->GetPoint() );
2856 aPam.SetMark();
2857 aPam.GetMark()->nNode = rNds.GetEndOfContent();
2858 aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
2859
2860 sal_Bool bFirst = sal_False;
2861 if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, sal_False )))
2862 {
2863 aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
2864 pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, sal_False );
2865 }
2866
2867 if( !pCNd ) // sollte nie passieren !!!
2868 {
2869 rNdIdx = nNdIdx; // alten Node zurueck
2870 return sal_False;
2871 }
2872 *pCurCrsr->GetPoint() = *aPam.GetPoint();
2873 }
2874 else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
2875 {
2876 // dann auf den Anfang vom Doc stellen
2877 rNdIdx = pDoc->GetNodes().GetEndOfExtras();
2878 pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext(
2879 &rNdIdx ), 0 );
2880 nNdIdx = rNdIdx.GetIndex();
2881 }
2882
2883 sal_Bool bOk = sal_True;
2884
2885 // #i9059# cursor may not stand in protected cells
2886 // (unless cursor in protected areas is OK.)
2887 const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
2888 if( !IsReadOnlyAvailable() &&
2889 pTableNode != NULL && rNdIdx.GetNode().IsProtect() )
2890 {
2891 // we're in a table, and we're in a protected area, so we're
2892 // probably in a protected cell.
2893
2894 // move forward into non-protected area.
2895 SwPaM aPam( rNdIdx.GetNode(), 0 );
2896 while( aPam.GetNode()->IsProtect() &&
2897 aPam.Move( fnMoveForward, fnGoCntnt ) )
2898 ; // nothing to do in the loop; the aPam.Move does the moving!
2899
2900 // didn't work? then go backwards!
2901 if( aPam.GetNode()->IsProtect() )
2902 {
2903 SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
2904 aPam = aTmpPaM;
2905 while( aPam.GetNode()->IsProtect() &&
2906 aPam.Move( fnMoveBackward, fnGoCntnt ) )
2907 ; // nothing to do in the loop; the aPam.Move does the moving!
2908 }
2909
2910 // if we're successful, set the new position
2911 if( ! aPam.GetNode()->IsProtect() )
2912 {
2913 *pCurCrsr->GetPoint() = *aPam.GetPoint();
2914 }
2915 }
2916
2917 // in einem geschuetzten Bereich
2918 const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
2919 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
2920 ( !IsReadOnlyAvailable() &&
2921 pSectNd->GetSection().IsProtectFlag() )) )
2922 {
2923 typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const;
2924 FNGoSection funcGoSection = &SwNodes::GoNextSection;
2925
2926 bOk = sal_False;
2927
2928 for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
2929 {
2930 sal_Bool bWeiter;
2931 do {
2932 bWeiter = sal_False;
2933 while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
2934 sal_True, !IsReadOnlyAvailable() )) )
2935 {
2936 // in eine Tabelle verschoben -> pruefe ob die
2937 // vielleicht geschuetzt ist
2938 if( pCNd->FindTableNode() )
2939 {
2940 SwCallLink aTmp( *this );
2941 SwCrsrSaveState aSaveState( *pCurCrsr );
2942 aTmp.nNdTyp = 0; // im DTOR nichts machen!
2943 if( !pCurCrsr->IsInProtectTable( sal_True, sal_True ) )
2944 {
2945 const SwSectionNode* pSNd = pCNd->FindSectionNode();
2946 if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
2947 || (!IsReadOnlyAvailable() &&
2948 pSNd->GetSection().IsProtectFlag() ))
2949 {
2950 bOk = sal_True;
2951 break; // eine nicht geschuetzte Zelle gef.
2952 }
2953 continue; // dann weiter suchen
2954 }
2955 }
2956 else
2957 {
2958 bOk = sal_True;
2959 break; // eine nicht geschuetzte Zelle gef.
2960 }
2961 }
2962
2963 if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
2964 {
2965 // Teste mal auf Fly - kann auch noch geschuetzt sein!!
2966 if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(),0,0,sal_False)) ||
2967 ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
2968 ( bOnlyText && pCNd->IsNoTxtNode() ) )
2969 {
2970 // dann weiter suchen!
2971 bOk = sal_False;
2972 bWeiter = sal_True;
2973 }
2974 }
2975 } while( bWeiter );
2976
2977 if( !bOk )
2978 {
2979 if( !nLoopCnt )
2980 funcGoSection = &SwNodes::GoPrevSection;
2981 rNdIdx = nNdIdx;
2982 }
2983 }
2984 }
2985 if( bOk )
2986 {
2987 pCNd = rNdIdx.GetNode().GetCntntNode();
2988 // sal_uInt16 nCntnt = Min( pCNd->Len(), pCurCrsr->GetPoint()->nContent.GetIndex() );
2989 xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
2990 pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
2991 }
2992 else
2993 {
2994 pCNd = rNdIdx.GetNode().GetCntntNode();
2995
2996 // falls Cursor im versteckten Bereich ist, auf jedenfall schon mal
2997 // verschieben!!
2998 if( !pCNd || !pCNd->getLayoutFrm( GetLayout(),0,0,sal_False) )
2999 {
3000 SwCrsrMoveState aTmpState( MV_NONE );
3001 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
3002 GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(),
3003 &aTmpState );
3004 }
3005 }
3006 return bOk;
3007 }
3008
3009
IsCrsrReadonly() const3010 sal_Bool SwCrsrShell::IsCrsrReadonly() const
3011 {
3012 if ( GetViewOptions()->IsReadonly() ||
3013 GetViewOptions()->IsFormView() ) // Formular view
3014 {
3015 SwFrm *pFrm = GetCurrFrm( sal_False );
3016 const SwFlyFrm* pFly;
3017 const SwSection* pSection;
3018
3019 if( pFrm && pFrm->IsInFly() &&
3020 (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
3021 pFly->Lower() &&
3022 !pFly->Lower()->IsNoTxtFrm() &&
3023 !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
3024 {
3025 return sal_False;
3026 }
3027 // edit in readonly sections
3028 else if ( pFrm && pFrm->IsInSct() &&
3029 0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
3030 pSection->IsEditInReadonlyFlag() )
3031 {
3032 return sal_False;
3033 }
3034 else if ( !IsMultiSelection() && CrsrInsideInputFld() )
3035 {
3036 return sal_False;
3037 }
3038
3039 return sal_True;
3040 }
3041 return sal_False;
3042 }
3043
3044
3045 // darf der Cursor in ReadOnlyBereiche?
SetReadOnlyAvailable(sal_Bool bFlag)3046 void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag )
3047 {
3048 // im GlobalDoc darf NIE umgeschaltet werden
3049 if( (!GetDoc()->GetDocShell() ||
3050 !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
3051 bFlag != bSetCrsrInReadOnly )
3052 {
3053 // wenn das Flag ausgeschaltet wird, dann muessen erstmal alle
3054 // Selektionen aufgehoben werden. Denn sonst wird sich darauf
3055 // verlassen, das nichts geschuetztes selektiert ist!
3056 if( !bFlag )
3057 {
3058 ClearMark();
3059 }
3060 bSetCrsrInReadOnly = bFlag;
3061 UpdateCrsr();
3062 }
3063 }
3064
HasReadonlySel() const3065 sal_Bool SwCrsrShell::HasReadonlySel() const
3066 {
3067 sal_Bool bRet = sal_False;
3068 if ( IsReadOnlyAvailable() || GetViewOptions()->IsFormView() )
3069 {
3070 if ( pTblCrsr != NULL )
3071 {
3072 bRet = pTblCrsr->HasReadOnlyBoxSel()
3073 || pTblCrsr->HasReadonlySel( GetViewOptions()->IsFormView() );
3074 }
3075 else
3076 {
3077 const SwPaM* pCrsr = pCurCrsr;
3078
3079 do
3080 {
3081 if ( pCrsr->HasReadonlySel( GetViewOptions()->IsFormView() ) )
3082 {
3083 bRet = sal_True;
3084 }
3085
3086 pCrsr = (SwPaM*)pCrsr->GetNext();
3087 } while ( !bRet && pCrsr != pCurCrsr );
3088 }
3089 }
3090 return bRet;
3091 }
3092
IsSelFullPara() const3093 sal_Bool SwCrsrShell::IsSelFullPara() const
3094 {
3095 sal_Bool bRet = sal_False;
3096
3097 if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
3098 pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() )
3099 {
3100 xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(),
3101 nEnd = pCurCrsr->GetMark()->nContent.GetIndex();
3102 if( nStt > nEnd )
3103 {
3104 xub_StrLen nTmp = nStt;
3105 nStt = nEnd;
3106 nEnd = nTmp;
3107 }
3108 const SwCntntNode* pCNd = pCurCrsr->GetCntntNode();
3109 bRet = pCNd && !nStt && nEnd == pCNd->Len();
3110 }
3111 return bRet;
3112 }
3113
GetTextDirection(const Point * pPt) const3114 short SwCrsrShell::GetTextDirection( const Point* pPt ) const
3115 {
3116 SwPosition aPos( *pCurCrsr->GetPoint() );
3117 Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() );
3118 if( pPt )
3119 {
3120 SwCrsrMoveState aTmpState( MV_NONE );
3121 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
3122
3123 GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
3124 }
3125
3126 return pDoc->GetTextDirection( aPos, &aPt );
3127 }
3128
IsInVerticalText(const Point * pPt) const3129 sal_Bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const
3130 {
3131 const short nDir = GetTextDirection( pPt );
3132 return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
3133 }
3134
IsInRightToLeftText(const Point * pPt) const3135 sal_Bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
3136 {
3137 const short nDir = GetTextDirection( pPt );
3138 // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
3139 // vertical environment
3140 return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
3141 }
3142
3143 //
3144 // If the current cursor position is inside a hidden range, the hidden range
3145 // is selected:
3146 //
SelectHiddenRange()3147 bool SwCrsrShell::SelectHiddenRange()
3148 {
3149 bool bRet = false;
3150 if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() )
3151 {
3152 SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint();
3153 const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
3154 if ( pNode )
3155 {
3156 const xub_StrLen nPos = rPt.nContent.GetIndex();
3157
3158 // check if nPos is in hidden range
3159 xub_StrLen nHiddenStart;
3160 xub_StrLen nHiddenEnd;
3161 SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
3162 if ( STRING_LEN != nHiddenStart )
3163 {
3164 // make selection:
3165 pCurCrsr->SetMark();
3166 pCurCrsr->GetMark()->nContent = nHiddenEnd;
3167 bRet = true;
3168 }
3169 }
3170 }
3171
3172 return bRet;
3173 }
3174
3175 /* */
3176
3177 // die Suchfunktionen
Find(const SearchOptions & rSearchOpt,sal_Bool bSearchInNotes,SwDocPositions eStart,SwDocPositions eEnde,sal_Bool & bCancel,FindRanges eRng,int bReplace)3178 sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
3179 SwDocPositions eStart, SwDocPositions eEnde,
3180 sal_Bool& bCancel,
3181 FindRanges eRng, int bReplace )
3182 {
3183 if( pTblCrsr )
3184 GetCrsr();
3185 delete pTblCrsr, pTblCrsr = 0;
3186 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
3187 sal_uLong nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace );
3188 if( nRet || bCancel )
3189 UpdateCrsr();
3190 return nRet;
3191 }
3192
Find(const SwTxtFmtColl & rFmtColl,SwDocPositions eStart,SwDocPositions eEnde,sal_Bool & bCancel,FindRanges eRng,const SwTxtFmtColl * pReplFmt)3193 sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
3194 SwDocPositions eStart, SwDocPositions eEnde,
3195 sal_Bool& bCancel,
3196 FindRanges eRng, const SwTxtFmtColl* pReplFmt )
3197 {
3198 if( pTblCrsr )
3199 GetCrsr();
3200 delete pTblCrsr, pTblCrsr = 0;
3201 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
3202 sal_uLong nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt );
3203 if( nRet )
3204 UpdateCrsr();
3205 return nRet;
3206 }
3207
Find(const SfxItemSet & rSet,sal_Bool bNoCollections,SwDocPositions eStart,SwDocPositions eEnde,sal_Bool & bCancel,FindRanges eRng,const SearchOptions * pSearchOpt,const SfxItemSet * rReplSet)3208 sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
3209 SwDocPositions eStart, SwDocPositions eEnde,
3210 sal_Bool& bCancel,
3211 FindRanges eRng, const SearchOptions* pSearchOpt,
3212 const SfxItemSet* rReplSet )
3213 {
3214 if( pTblCrsr )
3215 GetCrsr();
3216 delete pTblCrsr, pTblCrsr = 0;
3217 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
3218 sal_uLong nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel,
3219 eRng, pSearchOpt, rReplSet );
3220 if( nRet )
3221 UpdateCrsr();
3222 return nRet;
3223 }
3224
SetSelection(const SwPaM & rCrsr)3225 void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
3226 {
3227 StartAction();
3228 SwPaM* pCrsr = GetCrsr();
3229 *pCrsr->GetPoint() = *rCrsr.GetPoint();
3230 if(rCrsr.HasMark())
3231 {
3232 pCrsr->SetMark();
3233 *pCrsr->GetMark() = *rCrsr.GetMark();
3234 }
3235 if((SwPaM*)rCrsr.GetNext() != &rCrsr)
3236 {
3237 const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
3238 do
3239 {
3240 SwPaM* pCurrentCrsr = CreateCrsr();
3241 *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
3242 if(_pStartCrsr->HasMark())
3243 {
3244 pCurrentCrsr->SetMark();
3245 *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
3246 }
3247 } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
3248 }
3249 EndAction();
3250 }
3251
lcl_RemoveMark(SwPaM * pPam)3252 void lcl_RemoveMark( SwPaM* pPam )
3253 {
3254 ASSERT( pPam->HasMark(), "Don't remove pPoint!" )
3255 pPam->GetMark()->nContent.Assign( 0, 0 );
3256 pPam->GetMark()->nNode = 0;
3257 pPam->DeleteMark();
3258 }
3259
lcl_NodeContext(const SwNode & rNode)3260 const SwStartNode* lcl_NodeContext( const SwNode& rNode )
3261 {
3262 const SwStartNode *pRet = rNode.StartOfSectionNode();
3263 while( pRet->IsSectionNode() || pRet->IsTableNode() ||
3264 pRet->GetStartNodeType() == SwTableBoxStartNode )
3265 {
3266 pRet = pRet->StartOfSectionNode();
3267 }
3268 return pRet;
3269 }
3270
3271 /**
3272 Checks if a position is valid. To be valid the position's node must
3273 be a content node and the content must not be unregistered.
3274
3275 @param aPos the position to check.
3276 */
lcl_PosOk(const SwPosition & aPos)3277 bool lcl_PosOk(const SwPosition & aPos)
3278 {
3279 return NULL != aPos.nNode.GetNode().GetCntntNode() &&
3280 SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg();
3281 }
3282
3283 /**
3284 Checks if a PaM is valid. For a PaM to be valid its point must be
3285 valid. Additionally if the PaM has a mark this has to be valid, too.
3286
3287 @param aPam the PaM to check
3288 */
lcl_CrsrOk(SwPaM & aPam)3289 static bool lcl_CrsrOk(SwPaM & aPam)
3290 {
3291 return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
3292 || lcl_PosOk(*aPam.GetMark()));
3293 }
3294
ClearUpCrsrs()3295 void SwCrsrShell::ClearUpCrsrs()
3296 {
3297 // start of the ring
3298 SwPaM * pStartCrsr = GetCrsr();
3299 // start loop with second entry of the ring
3300 SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
3301 SwPaM * pTmpCrsr;
3302 bool bChanged = false;
3303
3304 /*
3305 For all entries in the ring except the start entry delete the
3306 entry if it is invalid.
3307 */
3308 while (pCrsr != pStartCrsr)
3309 {
3310 pTmpCrsr = (SwPaM *) pCrsr->GetNext();
3311
3312 if ( ! lcl_CrsrOk(*pCrsr))
3313 {
3314 delete pCrsr;
3315
3316 bChanged = true;
3317 }
3318
3319 pCrsr = pTmpCrsr;
3320 }
3321
3322 if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) )
3323 {
3324 lcl_RemoveMark( pStartCrsr );
3325 bChanged = true;
3326 }
3327 if( !lcl_PosOk( *pStartCrsr->GetPoint() ) )
3328 {
3329 SwNodes & aNodes = GetDoc()->GetNodes();
3330 const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
3331 SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
3332 SwNode * pNode = aNodes.GoPrevious(&aIdx);
3333 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3334 aNodes.GoNext( &aIdx );
3335 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3336 {
3337 /*
3338 If the start entry of the ring is invalid replace it with a
3339 cursor pointing to the beginning of the first content node in
3340 the document.
3341 */
3342 aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
3343 pNode = aNodes.GoNext( &aIdx );
3344 }
3345 bool bFound = (pNode != NULL);
3346
3347 ASSERT(bFound, "no content node found");
3348
3349 if (bFound)
3350 {
3351 SwPaM aTmpPam(*pNode);
3352 *pStartCrsr = aTmpPam;
3353 }
3354
3355 bChanged = true;
3356 }
3357
3358 /*
3359 If at least one of the cursors in the ring have been deleted or
3360 replaced, remove the table cursor.
3361 */
3362 if (pTblCrsr != NULL && bChanged)
3363 TblCrsrToCursor();
3364 }
3365
3366 // #111827#
GetCrsrDescr() const3367 String SwCrsrShell::GetCrsrDescr() const
3368 {
3369 String aResult;
3370
3371 if (IsMultiSelection())
3372 aResult += String(SW_RES(STR_MULTISEL));
3373 else
3374 aResult = GetDoc()->GetPaMDescr(*GetCrsr());
3375
3376 return aResult;
3377 }
3378
3379 // SMARTTAGS
3380
lcl_FillRecognizerData(uno::Sequence<rtl::OUString> & rSmartTagTypes,uno::Sequence<uno::Reference<container::XStringKeyMap>> & rStringKeyMaps,const SwWrongList & rSmartTagList,xub_StrLen nCurrent)3381 void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3382 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3383 const SwWrongList& rSmartTagList, xub_StrLen nCurrent )
3384 {
3385 // Insert smart tag information
3386 std::vector< rtl::OUString > aSmartTagTypes;
3387 std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
3388
3389 for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i )
3390 {
3391 const xub_StrLen nSTPos = rSmartTagList.Pos( i );
3392 const xub_StrLen nSTLen = rSmartTagList.Len( i );
3393
3394 if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
3395 {
3396 const SwWrongArea* pArea = rSmartTagList.GetElement( i );
3397 if ( pArea )
3398 {
3399 aSmartTagTypes.push_back( pArea->maType );
3400 aStringKeyMaps.push_back( pArea->mxPropertyBag );
3401 }
3402 }
3403 }
3404
3405 if ( aSmartTagTypes.size() )
3406 {
3407 rSmartTagTypes.realloc( aSmartTagTypes.size() );
3408 rStringKeyMaps.realloc( aSmartTagTypes.size() );
3409
3410 std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
3411 sal_uInt16 i = 0;
3412 for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
3413 rSmartTagTypes[i++] = *aTypesIter;
3414
3415 std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
3416 i = 0;
3417 for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
3418 rStringKeyMaps[i++] = *aMapsIter;
3419 }
3420 }
3421
lcl_FillTextRange(uno::Reference<text::XTextRange> & rRange,SwTxtNode & rNode,xub_StrLen nBegin,xub_StrLen nLen)3422 void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
3423 SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen )
3424 {
3425 // create SwPosition for nStartIndex
3426 SwIndex aIndex( &rNode, nBegin );
3427 SwPosition aStartPos( rNode, aIndex );
3428
3429 // create SwPosition for nEndIndex
3430 SwPosition aEndPos( aStartPos );
3431 aEndPos.nContent = nBegin + nLen;
3432
3433 const uno::Reference<text::XTextRange> xRange =
3434 SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos);
3435
3436 rRange = xRange;
3437 }
3438
GetSmartTagTerm(uno::Sequence<rtl::OUString> & rSmartTagTypes,uno::Sequence<uno::Reference<container::XStringKeyMap>> & rStringKeyMaps,uno::Reference<text::XTextRange> & rRange) const3439 void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3440 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3441 uno::Reference< text::XTextRange>& rRange ) const
3442 {
3443 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3444 return;
3445
3446 SwPaM* pCrsr = GetCrsr();
3447 SwPosition aPos( *pCrsr->GetPoint() );
3448 SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
3449 if ( pNode && !pNode->IsInProtectSect() )
3450 {
3451 const SwWrongList *pSmartTagList = pNode->GetSmartTags();
3452 if ( pSmartTagList )
3453 {
3454 xub_StrLen nCurrent = aPos.nContent.GetIndex();
3455 xub_StrLen nBegin = nCurrent;
3456 xub_StrLen nLen = 1;
3457
3458 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3459 {
3460 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3461 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3462 if ( pSubList )
3463 {
3464 pSmartTagList = pSubList;
3465 nCurrent = 0;
3466 }
3467
3468 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3469 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3470 }
3471 }
3472 }
3473 }
3474
3475 // see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
GetSmartTagTerm(const Point & rPt,SwRect & rSelectRect,uno::Sequence<rtl::OUString> & rSmartTagTypes,uno::Sequence<uno::Reference<container::XStringKeyMap>> & rStringKeyMaps,uno::Reference<text::XTextRange> & rRange)3476 void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
3477 uno::Sequence< rtl::OUString >& rSmartTagTypes,
3478 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3479 uno::Reference<text::XTextRange>& rRange )
3480 {
3481 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3482 return;
3483
3484 SwPaM* pCrsr = GetCrsr();
3485 SwPosition aPos( *pCrsr->GetPoint() );
3486 Point aPt( rPt );
3487 SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
3488 SwSpecialPos aSpecialPos;
3489 eTmpState.pSpecialPos = &aSpecialPos;
3490 SwTxtNode *pNode;
3491 const SwWrongList *pSmartTagList;
3492
3493 if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
3494 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
3495 0 != (pSmartTagList = pNode->GetSmartTags()) &&
3496 !pNode->IsInProtectSect() )
3497 {
3498 xub_StrLen nCurrent = aPos.nContent.GetIndex();
3499 xub_StrLen nBegin = nCurrent;
3500 xub_StrLen nLen = 1;
3501
3502 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3503 {
3504 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3505 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3506 if ( pSubList )
3507 {
3508 pSmartTagList = pSubList;
3509 nCurrent = eTmpState.pSpecialPos->nCharOfst;
3510 }
3511
3512 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3513 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3514
3515 // get smarttag word
3516 String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
3517
3518 //save the start and end positons of the line and the starting point
3519 Push();
3520 LeftMargin();
3521 xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
3522 RightMargin();
3523 xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
3524 Pop(sal_False);
3525
3526 // make sure the selection build later from the
3527 // data below does not include footnotes and other
3528 // "in word" character to the left and right in order
3529 // to preserve those. Therefore count those "in words"
3530 // in order to modify the selection accordingly.
3531 const sal_Unicode* pChar = aText.GetBuffer();
3532 xub_StrLen nLeft = 0;
3533 while (pChar && *pChar++ == CH_TXTATR_INWORD)
3534 ++nLeft;
3535 pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
3536 xub_StrLen nRight = 0;
3537 while (pChar && *pChar-- == CH_TXTATR_INWORD)
3538 ++nRight;
3539
3540 aPos.nContent = nBegin + nLeft;
3541 pCrsr = GetCrsr();
3542 *pCrsr->GetPoint() = aPos;
3543 pCrsr->SetMark();
3544 ExtendSelection( sal_True, nLen - nLeft - nRight );
3545 //no determine the rectangle in the current line
3546 xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
3547 //take one less than the line end - otherwise the next line would be calculated
3548 xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight);
3549 Push();
3550 pCrsr->DeleteMark();
3551 SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
3552 rContent = nWordStart;
3553 SwRect aStartRect;
3554 SwCrsrMoveState aState;
3555 aState.bRealWidth = sal_True;
3556 SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
3557 SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), sal_False);
3558
3559 pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
3560 rContent = nWordEnd;
3561 SwRect aEndRect;
3562 pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
3563 rSelectRect = aStartRect.Union( aEndRect );
3564 Pop(sal_False);
3565 }
3566 }
3567 }
3568
3569