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
Paint(const Rectangle & rRect)1236 void SwCrsrShell::Paint( const Rectangle &rRect)
1237 {
1238 SET_CURR_SHELL( this );
1239
1240 // beim Painten immer alle Cursor ausschalten
1241 SwRect aRect( rRect );
1242
1243 sal_Bool bVis = sal_False;
1244 // ist Cursor sichtbar, dann verstecke den SV-Cursor
1245 if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) ) //JP 18.06.97: ???
1246 {
1247 bVis = sal_True;
1248 pVisCrsr->Hide();
1249 }
1250
1251 // Bereich neu painten
1252 ViewShell::Paint( rRect );
1253
1254 if( bHasFocus && !bBasicHideCrsr )
1255 {
1256 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
1257 // pAktCrsr->Invalidate( aRect );
1258 if( !ActionPend() )
1259 {
1260 // damit nicht rechts/unten die Raender abgeschnitten werden
1261 pAktCrsr->Invalidate( VisArea() );
1262 pAktCrsr->Show();
1263 }
1264 else
1265 pAktCrsr->Invalidate( aRect );
1266
1267 }
1268 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
1269 pVisCrsr->Show();
1270 }
1271
1272
1273
VisPortChgd(const SwRect & rRect)1274 void SwCrsrShell::VisPortChgd( const SwRect & rRect )
1275 {
1276 SET_CURR_SHELL( this );
1277 sal_Bool bVis; // beim Scrollen immer alle Cursor ausschalten
1278
1279 // ist Cursor sichtbar, dann verstecke den SV-Cursor
1280 if( sal_True == ( bVis = pVisCrsr->IsVisible() ))
1281 pVisCrsr->Hide();
1282
1283 bVisPortChgd = sal_True;
1284 aOldRBPos.X() = VisArea().Right();
1285 aOldRBPos.Y() = VisArea().Bottom();
1286
1287 //Damit es es keine Probleme mit dem SV-Cursor gibt, wird in
1288 //ViewShell::VisPo.. ein Update() auf das Window gerufen.
1289 //Waehrend des Paintens duerfen aber nun wieder keine Selectionen
1290 //angezeigt werden, deshalb wird der Aufruf hier geklammert.
1291 ViewShell::VisPortChgd( rRect ); // Bereich verschieben
1292
1293 /*
1294 SwRect aRect( rRect );
1295 if( VisArea().IsOver( aRect ) )
1296 pCurCrsr->Invalidate( aRect );
1297 */
1298
1299 if( bSVCrsrVis && bVis ) // auch SV-Cursor wieder anzeigen
1300 pVisCrsr->Show();
1301
1302 if( nCrsrMove )
1303 bInCMvVisportChgd = sal_True;
1304
1305 bVisPortChgd = sal_False;
1306 }
1307
1308 // aktualisiere den Crsrs, d.H. setze ihn wieder in den Content.
1309 // Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim
1310 // Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position
1311 // ergibt sich aus seiner aktuellen Position im Layout !!
1312
1313
UpdateCrsrPos()1314 void SwCrsrShell::UpdateCrsrPos()
1315 {
1316 SET_CURR_SHELL( this );
1317 ++nStartAction;
1318 SwShellCrsr* pShellCrsr = getShellCrsr( true );
1319 Size aOldSz( GetDocSize() );
1320 SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
1321 SwCntntFrm *pFrm = pCNode ?
1322 pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ) :0;
1323 if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) )
1324 {
1325 SwCrsrMoveState aTmpState( MV_NONE );
1326 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1327 GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
1328 &aTmpState );
1329 if( pShellCrsr->HasMark())
1330 pShellCrsr->DeleteMark();
1331 }
1332 IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
1333 if( pGrammarContact )
1334 pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() );
1335 --nStartAction;
1336 if( aOldSz != GetDocSize() )
1337 SizeChgNotify();
1338 }
1339
1340 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1341 // stehen, so mussen diese daraus verschoben werden
lcl_CheckHiddenSection(SwNodeIndex & rIdx)1342 static void lcl_CheckHiddenSection( SwNodeIndex& rIdx )
1343 {
1344 const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
1345 if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
1346 {
1347 SwNodeIndex aTmp( *pSectNd );
1348 #if OSL_DEBUG_LEVEL > 1
1349 const SwNode* pFrmNd =
1350 #endif
1351 rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
1352
1353 #if OSL_DEBUG_LEVEL > 1
1354 (void) pFrmNd;
1355 ASSERT( pFrmNd, "keinen Node mit Frames gefunden" );
1356 #endif
1357 rIdx = aTmp;
1358 }
1359 }
1360
1361 // Try to set the cursor to the next visible content node.
lcl_CheckHiddenPara(SwPosition & rPos)1362 static void lcl_CheckHiddenPara( SwPosition& rPos )
1363 {
1364 SwNodeIndex aTmp( rPos.nNode );
1365 SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
1366 while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
1367 {
1368 SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
1369 if ( pCntnt && pCntnt->IsTxtNode() )
1370 pTxtNd = (SwTxtNode*)pCntnt;
1371 else
1372 pTxtNd = 0;
1373 }
1374
1375 if ( pTxtNd )
1376 rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
1377 }
1378
1379 // --> OD 2005-12-14 #i27301# - helper class, which notifies the accessibility
1380 // about invalid text selections in its destructor
1381 class SwNotifyAccAboutInvalidTextSelections
1382 {
1383 private:
1384 SwCrsrShell& mrCrsrSh;
1385
1386 public:
SwNotifyAccAboutInvalidTextSelections(SwCrsrShell & _rCrsrSh)1387 SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
1388 : mrCrsrSh( _rCrsrSh )
1389 {}
1390
~SwNotifyAccAboutInvalidTextSelections()1391 ~SwNotifyAccAboutInvalidTextSelections()
1392 {
1393 mrCrsrSh.InvalidateAccessibleParaTextSelection();
1394 }
1395 };
1396 // <--
UpdateCrsr(sal_uInt16 eFlags,sal_Bool bIdleEnd)1397 void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd )
1398 {
1399 SET_CURR_SHELL( this );
1400
1401 ClearUpCrsrs();
1402
1403 // erfrage den Count fuer die Start-/End-Actions und ob die Shell
1404 // ueberhaupt den Focus hat
1405 // if( ActionPend() /*|| !bHasFocus*/ )
1406 //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction der
1407 // Cursor geupdatet werden; um z.B. den TabellenCursor zu
1408 // erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen!
1409 if( ActionPend() && BasicActionPend() )
1410 {
1411 if ( eFlags & SwCrsrShell::READONLY )
1412 bIgnoreReadonly = sal_True;
1413 return; // wenn nicht, dann kein Update !!
1414 }
1415
1416 SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
1417
1418 if ( bIgnoreReadonly )
1419 {
1420 bIgnoreReadonly = sal_False;
1421 eFlags |= SwCrsrShell::READONLY;
1422 }
1423
1424 if( eFlags & SwCrsrShell::CHKRANGE ) // alle Cursor-Bewegungen auf
1425 CheckRange( pCurCrsr ); // ueberlappende Bereiche testen
1426
1427 if( !bIdleEnd )
1428 CheckTblBoxCntnt();
1429
1430 // steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen
1431 // (oder ist noch TabellenMode), dann gilt der Tabellen Mode
1432 SwPaM* pTstCrsr = getShellCrsr( true );
1433 if( pTstCrsr->HasMark() && !pBlockCrsr &&
1434 pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
1435 ( pTblCrsr ||
1436 pTstCrsr->GetNode( sal_True )->StartOfSectionNode() !=
1437 pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) )
1438 {
1439 SwShellCrsr* pITmpCrsr = getShellCrsr( true );
1440 Point aTmpPt( pITmpCrsr->GetPtPos() );
1441 Point aTmpMk( pITmpCrsr->GetMkPos() );
1442 SwPosition* pPos = pITmpCrsr->GetPoint();
1443
1444 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1445 // stehen, so mussen diese daraus verschoben werden
1446 lcl_CheckHiddenSection( pPos->nNode );
1447 lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
1448
1449 // Move cursor out of hidden paragraphs
1450 if ( !GetViewOptions()->IsShowHiddenChar() )
1451 {
1452 lcl_CheckHiddenPara( *pPos );
1453 lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
1454 }
1455
1456 SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
1457 getLayoutFrm( GetLayout(), &aTmpPt, pPos, sal_False );
1458
1459 ASSERT( pTblFrm, "Tabelle Crsr nicht im Content ??" );
1460
1461 // --> FME 2005-12-02 #126107# Make code robust. The table
1462 // cursor may point to a table in a currently inactive header.
1463 SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
1464 // <--
1465
1466 if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
1467 {
1468 // First check if point is in repeated headline:
1469 bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
1470
1471 // Second check if mark is in repeated headline:
1472 if ( !bInRepeatedHeadline )
1473 {
1474 SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( sal_False )->
1475 getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), sal_False );
1476 ASSERT( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
1477
1478 if ( pMarkTblFrm )
1479 {
1480 SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
1481 ASSERT( pMarkTab, "Tabelle Crsr nicht im Content ??" );
1482
1483 // --> FME 2005-11-28 #120360# Make code robust:
1484 if ( pMarkTab )
1485 {
1486 bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
1487 }
1488 // <--
1489 }
1490 }
1491
1492 // No table cursor in repeaded headlines:
1493 if ( bInRepeatedHeadline )
1494 {
1495 pTblFrm = 0;
1496
1497 SwPosSection fnPosSect = *pPos < *pITmpCrsr->GetMark()
1498 ? fnSectionStart
1499 : fnSectionEnd;
1500
1501 // dann nur innerhalb der Box selektieren
1502 if( pTblCrsr )
1503 {
1504 pCurCrsr->SetMark();
1505 *pCurCrsr->GetMark() = *pTblCrsr->GetMark();
1506 pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos();
1507 pTblCrsr->DeleteMark();
1508 pTblCrsr->SwSelPaintRects::Hide();
1509 }
1510
1511 *pCurCrsr->GetPoint() = *pCurCrsr->GetMark();
1512 (*fnSectionCurr)( *pCurCrsr, fnPosSect );
1513 }
1514 }
1515
1516 // wir wollen wirklich eine Tabellen-Selektion
1517 if( pTab && pTblFrm )
1518 {
1519 if( !pTblCrsr )
1520 {
1521 pTblCrsr = new SwShellTableCrsr( *this,
1522 *pCurCrsr->GetMark(), pCurCrsr->GetMkPos(),
1523 *pPos, aTmpPt );
1524 pCurCrsr->DeleteMark();
1525 pCurCrsr->SwSelPaintRects::Hide();
1526
1527 CheckTblBoxCntnt();
1528 }
1529
1530 SwCrsrMoveState aTmpState( MV_NONE );
1531 aTmpState.bRealHeight = sal_True;
1532 if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) )
1533 {
1534 Point aCentrPt( aCharRect.Center() );
1535 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1536 pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
1537 #ifndef DBG_UTIL
1538 pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() );
1539 #else
1540 if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) )
1541 ASSERT( !this, "GetCharRect failed." );
1542 #endif
1543 }
1544 // ALIGNRECT( aCharRect );
1545
1546 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
1547 // Curosr in den sichtbaren Bereich scrollen
1548 if( (eFlags & SwCrsrShell::SCROLLWIN) &&
1549 (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1550 !IsCrsrReadonly()) )
1551 {
1552 SwFrm* pBoxFrm = pTblFrm;
1553 while( pBoxFrm && !pBoxFrm->IsCellFrm() )
1554 pBoxFrm = pBoxFrm->GetUpper();
1555 if( pBoxFrm && pBoxFrm->Frm().HasArea() )
1556 MakeVisible( pBoxFrm->Frm() );
1557 else
1558 MakeVisible( aCharRect );
1559 }
1560
1561 // lasse vom Layout die Crsr in den Boxen erzeugen
1562 if( pTblCrsr->IsCrsrMovedUpdt() )
1563 GetLayout()->MakeTblCrsrs( *pTblCrsr );
1564 if( bHasFocus && !bBasicHideCrsr )
1565 pTblCrsr->Show();
1566
1567 // Cursor-Points auf die neuen Positionen setzen
1568 pTblCrsr->GetPtPos().X() = aCharRect.Left();
1569 pTblCrsr->GetPtPos().Y() = aCharRect.Top();
1570
1571 if( bSVCrsrVis )
1572 {
1573 aCrsrHeight.X() = 0;
1574 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1575 -aCharRect.Width() : aCharRect.Height();
1576 pVisCrsr->Show(); // wieder anzeigen
1577 }
1578 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
1579 if( pTblFrm && Imp()->IsAccessible() )
1580 Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
1581 return;
1582 }
1583 }
1584
1585 if( pTblCrsr )
1586 {
1587 // Cursor Ring loeschen
1588 while( pCurCrsr->GetNext() != pCurCrsr )
1589 delete pCurCrsr->GetNext();
1590 pCurCrsr->DeleteMark();
1591 *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
1592 pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
1593 delete pTblCrsr, pTblCrsr = 0;
1594 }
1595
1596 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
1597
1598 // sind wir vielleicht in einer geschuetzten/versteckten Section ?
1599 {
1600 SwShellCrsr* pShellCrsr = getShellCrsr( true );
1601 sal_Bool bChgState = sal_True;
1602 const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode();
1603 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
1604 ( !IsReadOnlyAvailable() &&
1605 pSectNd->GetSection().IsProtectFlag() &&
1606 ( !pDoc->GetDocShell() ||
1607 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) )
1608 {
1609 if( !FindValidCntntNode( !HasDrawView() ||
1610 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1611 {
1612 // alles ist geschuetzt / versteckt -> besonderer Mode
1613 if( bAllProtect && !IsReadOnlyAvailable() &&
1614 pSectNd->GetSection().IsProtectFlag() )
1615 bChgState = sal_False;
1616 else
1617 {
1618 eMvState = MV_NONE; // Status fuers Crsr-Travelling
1619 bAllProtect = sal_True;
1620 if( GetDoc()->GetDocShell() )
1621 {
1622 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1623 CallChgLnk(); // UI bescheid sagen!
1624 }
1625 return;
1626 }
1627 }
1628 }
1629 if( bChgState )
1630 {
1631 sal_Bool bWasAllProtect = bAllProtect;
1632 bAllProtect = sal_False;
1633 if( bWasAllProtect && GetDoc()->GetDocShell() &&
1634 GetDoc()->GetDocShell()->IsReadOnlyUI() )
1635 {
1636 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1637 CallChgLnk(); // UI bescheid sagen!
1638 }
1639 }
1640 }
1641
1642 UpdateCrsrPos();
1643
1644 // #100722# The cursor must always point into content; there's some code
1645 // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
1646 // loops _behind_ the last node in the selection, which always works if you
1647 // are in content.) To achieve this, we'll force cursor(s) to point into
1648 // content, if UpdateCrsrPos() hasn't already done so.
1649 SwPaM* pCmp = pCurCrsr;
1650 do
1651 {
1652 // start will move forwards, end will move backwards
1653 bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
1654
1655 // move point; forward if it's the start, backwards if it's the end
1656 if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
1657 pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
1658 fnGoCntnt );
1659
1660 // move mark (if exists); forward if it's the start, else backwards
1661 if( pCmp->HasMark() )
1662 {
1663 if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
1664 {
1665 pCmp->Exchange();
1666 pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
1667 fnGoCntnt );
1668 pCmp->Exchange();
1669 }
1670 }
1671
1672 // iterate to next PaM in ring
1673 pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
1674 }
1675 while( pCmp != pCurCrsr );
1676
1677
1678 SwRect aOld( aCharRect );
1679 sal_Bool bFirst = sal_True;
1680 SwCntntFrm *pFrm;
1681 int nLoopCnt = 100;
1682 SwShellCrsr* pShellCrsr = getShellCrsr( true );
1683
1684 do {
1685 sal_Bool bAgainst;
1686 do {
1687 bAgainst = sal_False;
1688 pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1689 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1690 // ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout
1691 // erzeugt werden, weil ja mal hier einer vorhanden war !!
1692 if ( !pFrm )
1693 {
1694 do
1695 {
1696 CalcLayout();
1697 pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1698 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1699 } while( !pFrm );
1700 }
1701 else if ( Imp()->IsIdleAction() )
1702 //Wir stellen sicher, dass anstaendig Formatiert wurde #42224#
1703 pFrm->PrepareCrsr();
1704
1705 // im geschuetzten Fly? aber bei Rahmenselektion ignorieren
1706 if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
1707 ( !Imp()->GetDrawView() ||
1708 !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
1709 (!pDoc->GetDocShell() ||
1710 !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) )
1711 {
1712 // dann suche eine gueltige Position
1713 sal_Bool bChgState = sal_True;
1714 if( !FindValidCntntNode(!HasDrawView() ||
1715 0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1716 {
1717 // alles ist geschuetzt / versteckt -> besonderer Mode
1718 if( bAllProtect )
1719 bChgState = sal_False;
1720 else
1721 {
1722 eMvState = MV_NONE; // Status fuers Crsr-Travelling
1723 bAllProtect = sal_True;
1724 if( GetDoc()->GetDocShell() )
1725 {
1726 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1727 CallChgLnk(); // UI bescheid sagen!
1728 }
1729 return;
1730 }
1731 }
1732
1733 if( bChgState )
1734 {
1735 sal_Bool bWasAllProtect = bAllProtect;
1736 bAllProtect = sal_False;
1737 if( bWasAllProtect && GetDoc()->GetDocShell() &&
1738 GetDoc()->GetDocShell()->IsReadOnlyUI() )
1739 {
1740 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1741 CallChgLnk(); // UI bescheid sagen!
1742 }
1743 bAllProtect = sal_False;
1744 bAgainst = sal_True; // nochmal den richigen Frm suchen
1745 }
1746 }
1747 } while( bAgainst );
1748
1749 if( !( eFlags & SwCrsrShell::NOCALRECT ))
1750 {
1751 SwCrsrMoveState aTmpState( eMvState );
1752 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1753 aTmpState.bRealHeight = sal_True;
1754 aTmpState.bRealWidth = IsOverwriteCrsr();
1755 aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
1756
1757 // #i27615#,#i30453#
1758 SwSpecialPos aSpecialPos;
1759 aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
1760 if (pShellCrsr->IsInFrontOfLabel())
1761 {
1762 aTmpState.pSpecialPos = &aSpecialPos;
1763 }
1764
1765 if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
1766 {
1767 Point& rPt = pShellCrsr->GetPtPos();
1768 rPt = aCharRect.Center();
1769 pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
1770 }
1771 // ALIGNRECT( aCharRect );
1772
1773 if( !pShellCrsr->HasMark() )
1774 aCrsrHeight = aTmpState.aRealHeight;
1775 else
1776 {
1777 aCrsrHeight.X() = 0;
1778 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1779 -aCharRect.Width() : aCharRect.Height();
1780 }
1781 }
1782 else
1783 {
1784 aCrsrHeight.X() = 0;
1785 aCrsrHeight.Y() = aCharRect.Height();
1786 }
1787
1788 if( !bFirst && aOld == aCharRect )
1789 break;
1790
1791 // falls das Layout meint, nach dem 100 durchlauf ist man immer noch
1792 // im Fluss, sollte man die akt. Pos. als gegeben hinnehmen!
1793 // siehe Bug: 29658
1794 if( !--nLoopCnt )
1795 {
1796 ASSERT( !this, "Endlosschleife? CharRect != OldCharRect ");
1797 break;
1798 }
1799 aOld = aCharRect;
1800 bFirst = sal_False;
1801
1802 // Cursor-Points auf die neuen Positionen setzen
1803 pShellCrsr->GetPtPos().X() = aCharRect.Left();
1804 pShellCrsr->GetPtPos().Y() = aCharRect.Top();
1805
1806 if( !(eFlags & SwCrsrShell::UPDOWN )) // alte Pos. von Up/Down loeschen
1807 {
1808 pFrm->Calc();
1809 nUpDownX = pFrm->IsVertical() ?
1810 aCharRect.Top() - pFrm->Frm().Top() :
1811 aCharRect.Left() - pFrm->Frm().Left();
1812 }
1813
1814 // Curosr in den sichtbaren Bereich scrollen
1815 if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
1816 (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1817 !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
1818 {
1819 //JP 30.04.99: damit das EndAction, beim evtuellen Scrollen, den
1820 // SV-Crsr nicht wieder sichtbar macht, wird hier das Flag
1821 // gesichert und zurueckgesetzt.
1822 sal_Bool bSav = bSVCrsrVis; bSVCrsrVis = sal_False;
1823 MakeSelVisible();
1824 bSVCrsrVis = bSav;
1825 }
1826
1827 } while( eFlags & SwCrsrShell::SCROLLWIN );
1828
1829 if( pBlockCrsr )
1830 RefreshBlockCursor();
1831
1832 if( !bIdleEnd && bHasFocus && !bBasicHideCrsr )
1833 {
1834 if( pTblCrsr )
1835 pTblCrsr->SwSelPaintRects::Show();
1836 else
1837 {
1838 pCurCrsr->SwSelPaintRects::Show();
1839 if( pBlockCrsr )
1840 {
1841 SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1842 while( pNxt && pNxt != pCurCrsr )
1843 {
1844 pNxt->SwSelPaintRects::Show();
1845 pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
1846 }
1847 }
1848 }
1849 }
1850
1851 eMvState = MV_NONE; // Status fuers Crsr-Travelling - GetCrsrOfst
1852
1853 if( pFrm && Imp()->IsAccessible() )
1854 Imp()->InvalidateAccessibleCursorPosition( pFrm );
1855
1856 // switch from blinking cursor to read-only-text-selection cursor
1857 static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
1858 const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
1859 GetCursorBlinkTime();
1860
1861 if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
1862 ( nBlinkTime != nNoBlinkTime ) )
1863 {
1864 // non blinking cursor in read only - text selection mode
1865 AllSettings aSettings = GetOut()->GetSettings();
1866 StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1867 const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
1868 Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
1869 nNoBlinkTime;
1870 aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
1871 aSettings.SetStyleSettings( aStyleSettings );
1872 GetOut()->SetSettings( aSettings );
1873 }
1874
1875 if( bSVCrsrVis )
1876 pVisCrsr->Show(); // wieder anzeigen
1877 }
1878
RefreshBlockCursor()1879 void SwCrsrShell::RefreshBlockCursor()
1880 {
1881 ASSERT( pBlockCrsr, "Don't call me without a block cursor" );
1882 SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
1883 Point aPt = rBlock.GetPtPos();
1884 SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), sal_False );
1885 Point aMk;
1886 if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() )
1887 {
1888 aPt = *pBlockCrsr->getStartPoint();
1889 aMk = *pBlockCrsr->getEndPoint();
1890 }
1891 else
1892 {
1893 aPt = rBlock.GetPtPos();
1894 if( pFrm )
1895 {
1896 if( pFrm->IsVertical() )
1897 aPt.Y() = pFrm->Frm().Top() + GetUpDownX();
1898 else
1899 aPt.X() = pFrm->Frm().Left() + GetUpDownX();
1900 }
1901 aMk = rBlock.GetMkPos();
1902 }
1903 SwRect aRect( aMk, aPt );
1904 aRect.Justify();
1905 SwSelectionList aSelList( pFrm );
1906
1907 if( GetLayout()->FillSelection( aSelList, aRect ) )
1908 {
1909 SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext();
1910 while( pNxt != pCurCrsr )
1911 {
1912 delete pNxt;
1913 pNxt = (SwCursor*)pCurCrsr->GetNext();
1914 }
1915
1916 std::list<SwPaM*>::iterator pStart = aSelList.getStart();
1917 std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
1918 ASSERT( pPam != pStart, "FillSelection should deliver at least one PaM" )
1919 pCurCrsr->SetMark();
1920 --pPam;
1921 // If there is only one text portion inside the rectangle, a simple
1922 // selection is created
1923 if( pPam == pStart )
1924 {
1925 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
1926 if( (*pPam)->HasMark() )
1927 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1928 else
1929 pCurCrsr->DeleteMark();
1930 delete *pPam;
1931 pCurCrsr->SetColumnSelection( false );
1932 }
1933 else
1934 {
1935 // The order of the SwSelectionList has to be preserved but
1936 // the order inside the ring created by CreateCrsr() is not like
1937 // exspected => First create the selections before the last one
1938 // downto the first selection.
1939 // At least create the cursor for the last selection
1940 --pPam;
1941 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
1942 if( (*pPam)->HasMark() )
1943 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1944 else
1945 pCurCrsr->DeleteMark();
1946 delete *pPam;
1947 pCurCrsr->SetColumnSelection( true );
1948 while( pPam != pStart )
1949 {
1950 --pPam;
1951
1952 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1953 pNew->Insert( pCurCrsr, 0 );
1954 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1955 pCurCrsr->DeleteMark();
1956
1957 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
1958 if( (*pPam)->HasMark() )
1959 {
1960 pCurCrsr->SetMark();
1961 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1962 }
1963 else
1964 pCurCrsr->DeleteMark();
1965 pCurCrsr->SetColumnSelection( true );
1966 delete *pPam;
1967 }
1968 {
1969 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1970 pNew->Insert( pCurCrsr, 0 );
1971 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1972 pCurCrsr->DeleteMark();
1973 }
1974 pPam = aSelList.getEnd();
1975 --pPam;
1976 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
1977 if( (*pPam)->HasMark() )
1978 {
1979 pCurCrsr->SetMark();
1980 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1981 }
1982 else
1983 pCurCrsr->DeleteMark();
1984 pCurCrsr->SetColumnSelection( true );
1985 delete *pPam;
1986 }
1987 }
1988 }
1989
1990 // erzeuge eine Kopie vom Cursor und speicher diese im Stack
1991
1992
Push()1993 void SwCrsrShell::Push()
1994 {
1995 pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(),
1996 pCurCrsr->GetPtPos(), pCrsrStk );
1997
1998 if( pCurCrsr->HasMark() )
1999 {
2000 pCrsrStk->SetMark();
2001 *pCrsrStk->GetMark() = *pCurCrsr->GetMark();
2002 }
2003 }
2004
2005 /*
2006 * Loescht einen Cursor (gesteuert durch bOldCrsr)
2007 * - vom Stack oder ( bOldCrsr = sal_True )
2008 * - den aktuellen und der auf dem Stack stehende wird zum aktuellen
2009 *
2010 * Return: es war auf dem Stack noch einer vorhanden
2011 */
2012
2013
Pop(sal_Bool bOldCrsr)2014 sal_Bool SwCrsrShell::Pop( sal_Bool bOldCrsr )
2015 {
2016 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
2017
2018 // noch weitere vorhanden ?
2019 if( 0 == pCrsrStk )
2020 return sal_False;
2021
2022 SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk;
2023
2024 // der Nachfolger wird der Aktuelle
2025 if( pCrsrStk->GetNext() != pCrsrStk )
2026 {
2027 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
2028 }
2029
2030 if( bOldCrsr ) // loesche vom Stack
2031 delete pCrsrStk; //
2032
2033 pCrsrStk = pTmp; // neu zuweisen
2034
2035 if( !bOldCrsr )
2036 {
2037 SwCrsrSaveState aSaveState( *pCurCrsr );
2038
2039 // wurde die sichtbare SSelection nicht veraendert
2040 if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() ||
2041 pOldStk->GetPtPos() == pCurCrsr->GetMkPos() )
2042 {
2043 // "Selektions-Rechtecke" verschieben
2044 pCurCrsr->Insert( pOldStk, 0 );
2045 pOldStk->Remove( 0, pOldStk->Count() );
2046 }
2047
2048 if( pOldStk->HasMark() )
2049 {
2050 pCurCrsr->SetMark();
2051 *pCurCrsr->GetMark() = *pOldStk->GetMark();
2052 pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
2053 }
2054 else
2055 // keine Selection also alte aufheben und auf die alte Pos setzen
2056 pCurCrsr->DeleteMark();
2057 *pCurCrsr->GetPoint() = *pOldStk->GetPoint();
2058 pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
2059 delete pOldStk;
2060
2061 if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2062 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2063 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2064 UpdateCrsr(); // akt. Cursor Updaten
2065 }
2066 return sal_True;
2067 }
2068
2069 /*
2070 * Verbinde zwei Cursor miteinander.
2071 * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen.
2072 */
2073
2074
Combine()2075 void SwCrsrShell::Combine()
2076 {
2077 // noch weitere vorhanden ?
2078 if( 0 == pCrsrStk )
2079 return;
2080
2081 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
2082 SwCrsrSaveState aSaveState( *pCurCrsr );
2083 if( pCrsrStk->HasMark() ) // nur wenn GetMark gesetzt wurde
2084 {
2085 #ifndef DBG_UTIL
2086 CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True );
2087 #else
2088 if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True ))
2089 ASSERT( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." );
2090 #endif
2091 // kopiere das GetMark
2092 if( !pCurCrsr->HasMark() )
2093 pCurCrsr->SetMark();
2094 *pCurCrsr->GetMark() = *pCrsrStk->GetMark();
2095 pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos();
2096 }
2097
2098 SwShellCrsr * pTmp = 0;
2099 if( pCrsrStk->GetNext() != pCrsrStk )
2100 {
2101 pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
2102 }
2103 delete pCrsrStk;
2104 pCrsrStk = pTmp;
2105 if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2106 !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2107 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2108 UpdateCrsr(); // akt. Cursor Updaten
2109 }
2110
2111
HideCrsrs()2112 void SwCrsrShell::HideCrsrs()
2113 {
2114 if( !bHasFocus || bBasicHideCrsr )
2115 return;
2116
2117 // ist Cursor sichtbar, dann verstecke den SV-Cursor
2118 if( pVisCrsr->IsVisible() )
2119 {
2120 SET_CURR_SHELL( this );
2121 pVisCrsr->Hide();
2122 }
2123 // hebe die Invertierung der SSelection auf
2124 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2125 pAktCrsr->Hide();
2126 }
2127
2128
2129
ShowCrsrs(sal_Bool bCrsrVis)2130 void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis )
2131 {
2132 if( !bHasFocus || bAllProtect || bBasicHideCrsr )
2133 return;
2134
2135 SET_CURR_SHELL( this );
2136 SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2137 pAktCrsr->Show();
2138
2139 if( bSVCrsrVis && bCrsrVis ) // auch SV-Cursor wieder anzeigen
2140 pVisCrsr->Show();
2141 }
2142
2143 // Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors
2144
2145
ShowCrsr()2146 void SwCrsrShell::ShowCrsr()
2147 {
2148 if( !bBasicHideCrsr )
2149 {
2150 bSVCrsrVis = sal_True;
2151 pCurCrsr->SetShowTxtInputFldOverlay( true );
2152 UpdateCrsr();
2153 }
2154 }
2155
2156
HideCrsr()2157 void SwCrsrShell::HideCrsr()
2158 {
2159 if( !bBasicHideCrsr )
2160 {
2161 bSVCrsrVis = sal_False;
2162 // evt. die sel. Bereiche aufheben !!
2163 SET_CURR_SHELL( this );
2164 pCurCrsr->SetShowTxtInputFldOverlay( false );
2165 pVisCrsr->Hide();
2166 }
2167 }
2168
2169
ShLooseFcs()2170 void SwCrsrShell::ShLooseFcs()
2171 {
2172 if( !bBasicHideCrsr )
2173 HideCrsrs();
2174 bHasFocus = sal_False;
2175 }
2176
2177
ShGetFcs(sal_Bool bUpdate)2178 void SwCrsrShell::ShGetFcs( sal_Bool bUpdate )
2179 {
2180 bHasFocus = sal_True;
2181 if( !bBasicHideCrsr && VisArea().Width() )
2182 {
2183 UpdateCrsr( static_cast<sal_uInt16>( bUpdate ?
2184 SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
2185 : SwCrsrShell::CHKRANGE ) );
2186 ShowCrsrs( bSVCrsrVis ? sal_True : sal_False );
2187 }
2188 }
2189
2190 // gebe den aktuellen Frame, in dem der Cursor steht, zurueck
2191
GetCurrFrm(const sal_Bool bCalcFrm) const2192 SwCntntFrm *SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm ) const
2193 {
2194 SET_CURR_SHELL( (ViewShell*)this );
2195 SwCntntFrm *pRet = 0;
2196 SwCntntNode *pNd = pCurCrsr->GetCntntNode();
2197 if ( pNd )
2198 {
2199 if ( bCalcFrm )
2200 {
2201 const sal_uInt16* pST = &nStartAction;
2202 ++(*((sal_uInt16*)pST));
2203 const Size aOldSz( GetDocSize() );
2204 pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() );
2205 --(*((sal_uInt16*)pST));
2206 if( aOldSz != GetDocSize() )
2207 ((SwCrsrShell*)this)->SizeChgNotify();
2208 }
2209 else
2210 pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), sal_False);
2211 }
2212 return pRet;
2213 }
2214
2215
2216 // alle Attribut/Format-Aenderungen am akt. Node werden an den
2217 // Link weitergeleitet.
2218
2219
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)2220 void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2221 {
2222 const sal_uInt16 nWhich = pOld ?
2223 pOld->Which() :
2224 pNew ?
2225 pNew->Which() :
2226 sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN);
2227
2228 if( bCallChgLnk &&
2229 ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
2230 nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
2231 nWhich == RES_ATTRSET_CHG ))
2232 // die Messages werden nicht weitergemeldet
2233 //MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom
2234 //SwTxtNode::Insert(SwTxtHint*, sal_uInt16) abgesetzt; hier wird reagiert und
2235 //vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden.
2236 CallChgLnk();
2237
2238 if( aGrfArrivedLnk.IsSet() &&
2239 ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
2240 aGrfArrivedLnk.Call( this );
2241 }
2242
2243
2244 // Abfrage, ob der aktuelle Cursor eine Selektion aufspannt,
2245 // also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind.
2246
2247
HasSelection() const2248 sal_Bool SwCrsrShell::HasSelection() const
2249 {
2250 const SwPaM* pCrsr = getShellCrsr( true );
2251 return( IsTableMode() || ( pCrsr->HasMark() &&
2252 *pCrsr->GetPoint() != *pCrsr->GetMark())
2253 ? sal_True : sal_False );
2254 }
2255
2256
CallChgLnk()2257 void SwCrsrShell::CallChgLnk()
2258 {
2259 // innerhalb von Start-/End-Action kein Call, sondern nur merken,
2260 // das sich etwas geaendert hat. Wird bei EndAction beachtet.
2261 if( BasicActionPend() )
2262 bChgCallFlag = sal_True; // das Change merken
2263 else if( aChgLnk.IsSet() )
2264 {
2265 if( bCallChgLnk )
2266 aChgLnk.Call( this );
2267 bChgCallFlag = sal_False; // Flag zuruecksetzen
2268 }
2269 }
2270
2271 // returne den am akt.Cursor selektierten Text eines Nodes.
2272
2273
GetSelTxt() const2274 String SwCrsrShell::GetSelTxt() const
2275 {
2276 String aTxt;
2277 if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2278 pCurCrsr->GetMark()->nNode.GetIndex() )
2279 {
2280 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2281 if( pTxtNd )
2282 {
2283 xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex();
2284 aTxt = pTxtNd->GetExpandTxt( nStt,
2285 pCurCrsr->End()->nContent.GetIndex() - nStt );
2286 }
2287 }
2288 return aTxt;
2289 }
2290
2291 // gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde)
2292
2293
GetText() const2294 String SwCrsrShell::GetText() const
2295 {
2296 String aTxt;
2297 if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2298 pCurCrsr->GetMark()->nNode.GetIndex() )
2299 {
2300 SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2301 if( pTxtNd )
2302 aTxt = pTxtNd->GetTxt().Copy(
2303 pCurCrsr->GetPoint()->nContent.GetIndex() );
2304 }
2305 return aTxt;
2306 }
2307
2308 // hole vom Start/Ende der akt. SSelection das nte Zeichen
GetChar(sal_Bool bEnd,long nOffset)2309 sal_Unicode SwCrsrShell::GetChar( sal_Bool bEnd, long nOffset )
2310 {
2311 if( IsTableMode() ) // im TabelleMode nicht moeglich
2312 return 0;
2313
2314 const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint()
2315 : bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2316 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2317 if( !pTxtNd )
2318 return 0;
2319
2320 xub_StrLen nPos = pPos->nContent.GetIndex();
2321 const String& rStr = pTxtNd->GetTxt();
2322 sal_Unicode cCh = 0;
2323
2324 if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() )
2325 cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) );
2326
2327 return cCh;
2328 }
2329
2330 // erweiter die akt. SSelection am Anfang/Ende um n Zeichen
2331
2332
ExtendSelection(sal_Bool bEnd,xub_StrLen nCount)2333 sal_Bool SwCrsrShell::ExtendSelection( sal_Bool bEnd, xub_StrLen nCount )
2334 {
2335 if( !pCurCrsr->HasMark() || IsTableMode() )
2336 return sal_False; // keine Selektion
2337
2338 SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2339 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2340 ASSERT( pTxtNd, "kein TextNode, wie soll erweitert werden?" );
2341
2342 xub_StrLen nPos = pPos->nContent.GetIndex();
2343 if( bEnd )
2344 {
2345 if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() )
2346 nPos = nPos + nCount;
2347 else
2348 return sal_False; // nicht mehr moeglich
2349 }
2350 else if( nPos >= nCount )
2351 nPos = nPos - nCount;
2352 else
2353 return sal_False; // nicht mehr moeglich
2354
2355 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen,
2356
2357 pPos->nContent = nPos;
2358 UpdateCrsr();
2359
2360 return sal_True;
2361 }
2362
2363 // setze nur den sichtbaren Cursor an die angegebene Dokument-Pos.
2364 // returnt sal_False: wenn der SPoint vom Layout korrigiert wurde.
2365
SetVisCrsr(const Point & rPt)2366 sal_Bool SwCrsrShell::SetVisCrsr( const Point &rPt )
2367 {
2368 SET_CURR_SHELL( this );
2369 Point aPt( rPt );
2370 SwPosition aPos( *pCurCrsr->GetPoint() );
2371 SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
2372 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2373 aTmpState.bRealHeight = sal_True;
2374
2375 sal_Bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
2376
2377 SetInFrontOfLabel( sal_False ); // #i27615#
2378
2379 // nur in TextNodes anzeigen !!
2380 SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
2381 if( !pTxtNd )
2382 return sal_False;
2383
2384 const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
2385 if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
2386 ( !IsReadOnlyAvailable() &&
2387 pSectNd->GetSection().IsProtectFlag())) )
2388 return sal_False;
2389
2390 SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos );
2391 if ( Imp()->IsIdleAction() )
2392 pFrm->PrepareCrsr();
2393 SwRect aTmp( aCharRect );
2394
2395 pFrm->GetCharRect( aCharRect, aPos, &aTmpState );
2396 // ALIGNRECT( aCharRect );
2397
2398 if( aTmp == aCharRect && // BUG 10137: bleibt der Cursor auf der
2399 pVisCrsr->IsVisible() ) // Position nicht hidden & showen
2400 return sal_True;
2401
2402 pVisCrsr->Hide(); // sichtbaren Cursor immer verstecken
2403 if( IsScrollMDI( this, aCharRect ))
2404 {
2405 MakeVisible( aCharRect );
2406 pCurCrsr->Show();
2407 }
2408
2409 // Bug 29584: bei Rahmenselektion ist der Cursor versteckt, aber den
2410 // D&D-Cursor will man trotzdem haben
2411 // if( bSVCrsrVis )
2412 {
2413 if( aTmpState.bRealHeight )
2414 aCrsrHeight = aTmpState.aRealHeight;
2415 else
2416 {
2417 aCrsrHeight.X() = 0;
2418 aCrsrHeight.Y() = aCharRect.Height();
2419 }
2420
2421 pVisCrsr->SetDragCrsr( sal_True );
2422 pVisCrsr->Show(); // wieder anzeigen
2423 }
2424 return bRet;
2425 }
2426
IsOverReadOnlyPos(const Point & rPt) const2427 sal_Bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
2428 {
2429 Point aPt( rPt );
2430 SwPaM aPam( *pCurCrsr->GetPoint() );
2431 GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
2432 return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
2433 }
2434
2435
2436 // returne die Anzahl der Cursor im Ring (Flag besagt ob man nur
2437 // aufgepspannte haben will - sprich etwas selektiert ist (Basic))
GetCrsrCnt(sal_Bool bAll) const2438 sal_uInt16 SwCrsrShell::GetCrsrCnt( sal_Bool bAll ) const
2439 {
2440 Ring* pTmp = GetCrsr()->GetNext();
2441 sal_uInt16 n = (bAll || ( pCurCrsr->HasMark() &&
2442 *pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0;
2443 while( pTmp != pCurCrsr )
2444 {
2445 if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
2446 *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
2447 ++n;
2448 pTmp = pTmp->GetNext();
2449 }
2450 return n;
2451 }
2452
2453
IsStartOfDoc() const2454 sal_Bool SwCrsrShell::IsStartOfDoc() const
2455 {
2456 if( pCurCrsr->GetPoint()->nContent.GetIndex() )
2457 return sal_False;
2458
2459 // Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd)
2460 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
2461 if( !aIdx.GetNode().IsCntntNode() )
2462 GetDoc()->GetNodes().GoNext( &aIdx );
2463 return aIdx == pCurCrsr->GetPoint()->nNode;
2464 }
2465
2466
IsEndOfDoc() const2467 sal_Bool SwCrsrShell::IsEndOfDoc() const
2468 {
2469 SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
2470 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
2471 if( !pCNd )
2472 pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
2473
2474 return aIdx == pCurCrsr->GetPoint()->nNode &&
2475 pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex();
2476 }
2477
2478
2479 // loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten
2480 // Cursor auf seinen TextNode (oder StartNode?).
2481 // Beim naechsten ::GetCrsr werden sie wieder alle erzeugt
2482 // Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt.
ParkTblCrsr()2483 sal_Bool SwCrsrShell::ParkTblCrsr()
2484 {
2485 if( !pTblCrsr )
2486 return sal_False;
2487
2488 pTblCrsr->ParkCrsr();
2489
2490 while( pCurCrsr->GetNext() != pCurCrsr )
2491 delete pCurCrsr->GetNext();
2492
2493 // vom Cursor !immer! SPoint und Mark umsetzen
2494 pCurCrsr->SetMark();
2495 *pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
2496 pCurCrsr->DeleteMark();
2497
2498 return sal_True;
2499 }
2500
2501 /***********************************************************************
2502 #* Class : SwCrsrShell
2503 #* Methode : ParkCrsr
2504 #* Beschreibung: Vernichtet Selektionen und zus. Crsr aller Shell der
2505 #* verbleibende Crsr der Shell wird geparkt.
2506 #* Datum : MA 05. Nov. 92
2507 #* Update : JP 19.09.97
2508 #***********************************************************************/
2509
_ParkPams(SwPaM * pDelRg,SwShellCrsr ** ppDelRing)2510 void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
2511 {
2512 const SwPosition *pStt = pDelRg->Start(),
2513 *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
2514
2515 SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
2516
2517 // durchsuche den gesamten Ring
2518 sal_Bool bGoNext;
2519 do {
2520 const SwPosition *pTmpStt = pTmp->Start(),
2521 *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
2522 pTmp->GetMark() : pTmp->GetPoint();
2523 /*
2524 * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
2525 * muss der alte Bereich aufgehoben werden.
2526 * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum
2527 * Bereich gehoert !
2528 */
2529 if( *pStt <= *pTmpStt )
2530 {
2531 if( *pEnd > *pTmpStt ||
2532 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
2533 pTmpDel = pTmp;
2534 }
2535 else
2536 if( *pStt < *pTmpEnd )
2537 pTmpDel = pTmp;
2538
2539 bGoNext = sal_True;
2540 if( pTmpDel ) // ist der Pam im Bereich ?? loesche ihn
2541 {
2542 sal_Bool bDelete = sal_True;
2543 if( *ppDelRing == pTmpDel )
2544 {
2545 if( *ppDelRing == pCurCrsr )
2546 {
2547 if( sal_True == ( bDelete = GoNextCrsr() ))
2548 {
2549 bGoNext = sal_False;
2550 pTmp = (SwPaM*)pTmp->GetNext();
2551 }
2552 }
2553 else
2554 bDelete = sal_False; // StackCrsr nie loeschen !!
2555 }
2556
2557 if( bDelete )
2558 delete pTmpDel; // hebe alten Bereich auf
2559 else
2560 {
2561 pTmpDel->GetPoint()->nContent.Assign( 0, 0 );
2562 pTmpDel->GetPoint()->nNode = 0;
2563 pTmpDel->SetMark();
2564 pTmpDel->DeleteMark();
2565 }
2566 pTmpDel = 0;
2567 }
2568 else if( !pTmp->HasMark() ) // sorge auf jedenfall dafuer, das
2569 { // nicht benutzte Indizies beachtet werden!
2570 pTmp->SetMark(); // SPoint liegt nicht im Bereich,
2571 pTmp->DeleteMark(); // aber vielleicht GetMark, also setzen
2572 }
2573 if( bGoNext )
2574 pTmp = (SwPaM*)pTmp->GetNext();
2575 } while( !bGoNext || *ppDelRing != pTmp );
2576 }
2577
ParkCrsr(const SwNodeIndex & rIdx)2578 void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
2579 {
2580 SwNode *pNode = &rIdx.GetNode();
2581
2582 // erzeuge einen neuen Pam
2583 SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
2584 if( pNode->GetStartNode() )
2585 {
2586 if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
2587 {
2588 // der angegebene Node steht in einer Tabelle, also Parke
2589 // den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle)
2590 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2591 }
2592 else // also auf dem StartNode selbst.
2593 // Dann immer ueber seinen EndNode den StartNode erfragen !!!
2594 // (StartOfSection vom StartNode ist der Parent !)
2595 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
2596 }
2597 else
2598 pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2599 pNew->SetMark();
2600 pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
2601
2602 //Alle Shells wollen etwas davon haben.
2603 ViewShell *pTmp = this;
2604 do {
2605 if( pTmp->IsA( TYPE( SwCrsrShell )))
2606 {
2607 SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
2608 if( pSh->pCrsrStk )
2609 pSh->_ParkPams( pNew, &pSh->pCrsrStk );
2610
2611 pSh->_ParkPams( pNew, &pSh->pCurCrsr );
2612 if( pSh->pTblCrsr )
2613 {
2614 // setze den Tabellen Cursor immer auf 0, den aktuellen
2615 // immer auf den Anfang der Tabelle
2616 SwPaM* pTCrsr = pSh->GetTblCrs();
2617 SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
2618 if ( pTblNd )
2619 {
2620 pTCrsr->GetPoint()->nContent.Assign( 0, 0 );
2621 pTCrsr->GetPoint()->nNode = 0;
2622 pTCrsr->SetMark();
2623 pTCrsr->DeleteMark();
2624 pSh->pCurCrsr->GetPoint()->nNode = *pTblNd;
2625 }
2626 }
2627 }
2628 } while ( this != (pTmp = (ViewShell*)pTmp->GetNext() ));
2629 delete pNew;
2630 }
2631
2632 //=========================================================================
2633
2634 /*
2635 * der Copy-Constructor
2636 * Cursor-Position kopieren, in den Ring eingetragen.
2637 * Alle Ansichten eines Dokumentes stehen im Ring der Shells.
2638 */
2639
SwCrsrShell(SwCrsrShell & rShell,Window * pInitWin)2640 SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin )
2641 : ViewShell( rShell, pInitWin ),
2642 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2643 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2644 eMvState( MV_NONE ),
2645 // --> OD 2008-04-02 #refactorlists#
2646 sMarkedListId(),
2647 nMarkedListLevel( 0 )
2648 // <--
2649 {
2650 SET_CURR_SHELL( this );
2651 // Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen
2652 pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) );
2653 pCurCrsr->GetCntntNode()->Add( this );
2654
2655 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2656 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2657 bOverwriteCrsr = sal_False;
2658 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2659 bSetCrsrInReadOnly = sal_True;
2660 pVisCrsr = new SwVisCrsr( this );
2661 // UpdateCrsr( 0 );
2662 // OD 11.02.2003 #100556#
2663 mbMacroExecAllowed = rShell.IsMacroExecAllowed();
2664 oldColFrm = NULL;
2665 }
2666
2667
2668 /*
2669 * der normale Constructor
2670 */
2671
SwCrsrShell(SwDoc & rDoc,Window * pInitWin,const SwViewOption * pInitOpt)2672 SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin,
2673 const SwViewOption *pInitOpt )
2674 : ViewShell( rDoc, pInitWin, pInitOpt ),
2675 SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2676 pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2677 eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst
2678 // --> OD 2008-04-02 #refactorlists#
2679 sMarkedListId(),
2680 nMarkedListLevel( 0 )
2681 // <--
2682 {
2683 SET_CURR_SHELL( this );
2684 /*
2685 * Erzeugen des initialen Cursors, wird auf die erste
2686 * Inhaltsposition gesetzt
2687 */
2688 SwNodes& rNds = rDoc.GetNodes();
2689
2690 SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
2691 SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode
2692
2693 pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
2694
2695 // melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle
2696 // Attribut-Aenderungen ueber den Link weiter gemeldet werden.
2697 pCNd->Add( this );
2698
2699 bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2700 bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2701 bOverwriteCrsr = sal_False;
2702 bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2703 bSetCrsrInReadOnly = sal_True;
2704
2705 pVisCrsr = new SwVisCrsr( this );
2706 // UpdateCrsr( 0 );
2707 // OD 11.02.2003 #100556#
2708 mbMacroExecAllowed = true;
2709 }
2710
2711
2712
~SwCrsrShell()2713 SwCrsrShell::~SwCrsrShell()
2714 {
2715 // wenn es nicht die letzte View so sollte zu mindest das
2716 // Feld noch geupdatet werden.
2717 if( GetNext() != this )
2718 CheckTblBoxCntnt( pCurCrsr->GetPoint() );
2719 else
2720 ClearTblBoxCntnt();
2721
2722 delete pVisCrsr;
2723 delete pBlockCrsr;
2724 delete pTblCrsr;
2725
2726 /*
2727 * Freigabe der Cursor
2728 */
2729 while(pCurCrsr->GetNext() != pCurCrsr)
2730 delete pCurCrsr->GetNext();
2731 delete pCurCrsr;
2732
2733 // Stack freigeben
2734 if( pCrsrStk )
2735 {
2736 while( pCrsrStk->GetNext() != pCrsrStk )
2737 delete pCrsrStk->GetNext();
2738 delete pCrsrStk;
2739 }
2740
2741 // JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in
2742 // der CursorShell haengt keine Chance geben, sich an den
2743 // TextNode zu haengen.
2744 if( GetRegisteredIn() )
2745 GetRegisteredInNonConst()->Remove( this );
2746 }
2747
getShellCrsr(bool bBlock)2748 SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
2749 {
2750 if( pTblCrsr )
2751 return pTblCrsr;
2752 if( pBlockCrsr && bBlock )
2753 return &pBlockCrsr->getShellCrsr();
2754 return pCurCrsr;
2755 }
2756
2757 //Sollte fuer das Clipboard der WaitPtr geschaltet werden?
2758 //Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen.
2759
ShouldWait() const2760 sal_Bool SwCrsrShell::ShouldWait() const
2761 {
2762 if ( IsTableMode() || GetCrsrCnt() > 1 )
2763 return sal_True;
2764
2765 if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2766 return sal_True;
2767
2768 SwPaM* pPam = GetCrsr();
2769 return pPam->Start()->nNode.GetIndex() + 10 <
2770 pPam->End()->nNode.GetIndex();
2771 }
2772
2773
UpdateTblSelBoxes()2774 sal_uInt16 SwCrsrShell::UpdateTblSelBoxes()
2775 {
2776 if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() ))
2777 GetLayout()->MakeTblCrsrs( *pTblCrsr );
2778 return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0;
2779 }
2780
2781 // zeige das akt. selektierte "Object" an
MakeSelVisible()2782 void SwCrsrShell::MakeSelVisible()
2783 {
2784 ASSERT( bHasFocus, "kein Focus aber Cursor sichtbar machen?" );
2785 if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() )
2786 {
2787 SwRect aTmp( aCharRect );
2788 long nDiff = aCharRect.Height() - VisArea().Height();
2789 if( nDiff < aCrsrHeight.X() )
2790 aTmp.Top( nDiff + aCharRect.Top() );
2791 else
2792 {
2793 aTmp.Top( aCrsrHeight.X() + aCharRect.Top() );
2794 aTmp.Height( aCrsrHeight.Y() );
2795 }
2796 if( !aTmp.HasArea() )
2797 {
2798 aTmp.SSize().Height() += 1;
2799 aTmp.SSize().Width() += 1;
2800 }
2801 MakeVisible( aTmp );
2802 }
2803 else
2804 {
2805 if( aCharRect.HasArea() )
2806 MakeVisible( aCharRect );
2807 else
2808 {
2809 SwRect aTmp( aCharRect );
2810 aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
2811 MakeVisible( aTmp );
2812 }
2813 }
2814 }
2815
2816
2817 // suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt)
FindValidCntntNode(sal_Bool bOnlyText)2818 sal_Bool SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText )
2819 {
2820 if( pTblCrsr ) // was soll ich jetzt machen ??
2821 {
2822 ASSERT( !this, "TabellenSelection nicht aufgehoben!" );
2823 return sal_False;
2824 }
2825
2826 //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
2827 if( !bAllProtect && GetDoc()->GetDocShell() &&
2828 GetDoc()->GetDocShell()->IsReadOnlyUI() )
2829 return sal_True;
2830
2831 // dann raus da!
2832 if( pCurCrsr->HasMark() )
2833 ClearMark();
2834
2835 // als erstes mal auf Rahmen abpruefen
2836 SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode;
2837 sal_uLong nNdIdx = rNdIdx.GetIndex(); // sichern
2838 SwNodes& rNds = pDoc->GetNodes();
2839 SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
2840 const SwCntntFrm * pFrm;
2841
2842 if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(),0,pCurCrsr->GetPoint(),sal_False)) &&
2843 !IsReadOnlyAvailable() && pFrm->IsProtected() &&
2844 nNdIdx < rNds.GetEndOfExtras().GetIndex() )
2845 {
2846 // geschuetzter Rahmen ueberspringen
2847 SwPaM aPam( *pCurCrsr->GetPoint() );
2848 aPam.SetMark();
2849 aPam.GetMark()->nNode = rNds.GetEndOfContent();
2850 aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
2851
2852 sal_Bool bFirst = sal_False;
2853 if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, sal_False )))
2854 {
2855 aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
2856 pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, sal_False );
2857 }
2858
2859 if( !pCNd ) // sollte nie passieren !!!
2860 {
2861 rNdIdx = nNdIdx; // alten Node zurueck
2862 return sal_False;
2863 }
2864 *pCurCrsr->GetPoint() = *aPam.GetPoint();
2865 }
2866 else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
2867 {
2868 // dann auf den Anfang vom Doc stellen
2869 rNdIdx = pDoc->GetNodes().GetEndOfExtras();
2870 pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext(
2871 &rNdIdx ), 0 );
2872 nNdIdx = rNdIdx.GetIndex();
2873 }
2874
2875 sal_Bool bOk = sal_True;
2876
2877 // #i9059# cursor may not stand in protected cells
2878 // (unless cursor in protected areas is OK.)
2879 const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
2880 if( !IsReadOnlyAvailable() &&
2881 pTableNode != NULL && rNdIdx.GetNode().IsProtect() )
2882 {
2883 // we're in a table, and we're in a protected area, so we're
2884 // probably in a protected cell.
2885
2886 // move forward into non-protected area.
2887 SwPaM aPam( rNdIdx.GetNode(), 0 );
2888 while( aPam.GetNode()->IsProtect() &&
2889 aPam.Move( fnMoveForward, fnGoCntnt ) )
2890 ; // nothing to do in the loop; the aPam.Move does the moving!
2891
2892 // didn't work? then go backwards!
2893 if( aPam.GetNode()->IsProtect() )
2894 {
2895 SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
2896 aPam = aTmpPaM;
2897 while( aPam.GetNode()->IsProtect() &&
2898 aPam.Move( fnMoveBackward, fnGoCntnt ) )
2899 ; // nothing to do in the loop; the aPam.Move does the moving!
2900 }
2901
2902 // if we're successful, set the new position
2903 if( ! aPam.GetNode()->IsProtect() )
2904 {
2905 *pCurCrsr->GetPoint() = *aPam.GetPoint();
2906 }
2907 }
2908
2909 // in einem geschuetzten Bereich
2910 const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
2911 if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
2912 ( !IsReadOnlyAvailable() &&
2913 pSectNd->GetSection().IsProtectFlag() )) )
2914 {
2915 typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const;
2916 FNGoSection funcGoSection = &SwNodes::GoNextSection;
2917
2918 bOk = sal_False;
2919
2920 for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
2921 {
2922 sal_Bool bWeiter;
2923 do {
2924 bWeiter = sal_False;
2925 while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
2926 sal_True, !IsReadOnlyAvailable() )) )
2927 {
2928 // in eine Tabelle verschoben -> pruefe ob die
2929 // vielleicht geschuetzt ist
2930 if( pCNd->FindTableNode() )
2931 {
2932 SwCallLink aTmp( *this );
2933 SwCrsrSaveState aSaveState( *pCurCrsr );
2934 aTmp.nNdTyp = 0; // im DTOR nichts machen!
2935 if( !pCurCrsr->IsInProtectTable( sal_True, sal_True ) )
2936 {
2937 const SwSectionNode* pSNd = pCNd->FindSectionNode();
2938 if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
2939 || (!IsReadOnlyAvailable() &&
2940 pSNd->GetSection().IsProtectFlag() ))
2941 {
2942 bOk = sal_True;
2943 break; // eine nicht geschuetzte Zelle gef.
2944 }
2945 continue; // dann weiter suchen
2946 }
2947 }
2948 else
2949 {
2950 bOk = sal_True;
2951 break; // eine nicht geschuetzte Zelle gef.
2952 }
2953 }
2954
2955 if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
2956 {
2957 // Teste mal auf Fly - kann auch noch geschuetzt sein!!
2958 if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(),0,0,sal_False)) ||
2959 ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
2960 ( bOnlyText && pCNd->IsNoTxtNode() ) )
2961 {
2962 // dann weiter suchen!
2963 bOk = sal_False;
2964 bWeiter = sal_True;
2965 }
2966 }
2967 } while( bWeiter );
2968
2969 if( !bOk )
2970 {
2971 if( !nLoopCnt )
2972 funcGoSection = &SwNodes::GoPrevSection;
2973 rNdIdx = nNdIdx;
2974 }
2975 }
2976 }
2977 if( bOk )
2978 {
2979 pCNd = rNdIdx.GetNode().GetCntntNode();
2980 // sal_uInt16 nCntnt = Min( pCNd->Len(), pCurCrsr->GetPoint()->nContent.GetIndex() );
2981 xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
2982 pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
2983 }
2984 else
2985 {
2986 pCNd = rNdIdx.GetNode().GetCntntNode();
2987
2988 // falls Cursor im versteckten Bereich ist, auf jedenfall schon mal
2989 // verschieben!!
2990 if( !pCNd || !pCNd->getLayoutFrm( GetLayout(),0,0,sal_False) )
2991 {
2992 SwCrsrMoveState aTmpState( MV_NONE );
2993 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2994 GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(),
2995 &aTmpState );
2996 }
2997 }
2998 return bOk;
2999 }
3000
3001
IsCrsrReadonly() const3002 sal_Bool SwCrsrShell::IsCrsrReadonly() const
3003 {
3004 if ( GetViewOptions()->IsReadonly() ||
3005 GetViewOptions()->IsFormView() ) // Formular view
3006 {
3007 SwFrm *pFrm = GetCurrFrm( sal_False );
3008 const SwFlyFrm* pFly;
3009 const SwSection* pSection;
3010
3011 if( pFrm && pFrm->IsInFly() &&
3012 (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
3013 pFly->Lower() &&
3014 !pFly->Lower()->IsNoTxtFrm() &&
3015 !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
3016 {
3017 return sal_False;
3018 }
3019 // edit in readonly sections
3020 else if ( pFrm && pFrm->IsInSct() &&
3021 0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
3022 pSection->IsEditInReadonlyFlag() )
3023 {
3024 return sal_False;
3025 }
3026 else if ( !IsMultiSelection() && CrsrInsideInputFld() )
3027 {
3028 return sal_False;
3029 }
3030
3031 return sal_True;
3032 }
3033 return sal_False;
3034 }
3035
3036
3037 // darf der Cursor in ReadOnlyBereiche?
SetReadOnlyAvailable(sal_Bool bFlag)3038 void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag )
3039 {
3040 // im GlobalDoc darf NIE umgeschaltet werden
3041 if( (!GetDoc()->GetDocShell() ||
3042 !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
3043 bFlag != bSetCrsrInReadOnly )
3044 {
3045 // wenn das Flag ausgeschaltet wird, dann muessen erstmal alle
3046 // Selektionen aufgehoben werden. Denn sonst wird sich darauf
3047 // verlassen, das nichts geschuetztes selektiert ist!
3048 if( !bFlag )
3049 {
3050 ClearMark();
3051 }
3052 bSetCrsrInReadOnly = bFlag;
3053 UpdateCrsr();
3054 }
3055 }
3056
HasReadonlySel() const3057 sal_Bool SwCrsrShell::HasReadonlySel() const
3058 {
3059 sal_Bool bRet = sal_False;
3060 if ( IsReadOnlyAvailable() || GetViewOptions()->IsFormView() )
3061 {
3062 if ( pTblCrsr != NULL )
3063 {
3064 bRet = pTblCrsr->HasReadOnlyBoxSel()
3065 || pTblCrsr->HasReadonlySel( GetViewOptions()->IsFormView() );
3066 }
3067 else
3068 {
3069 const SwPaM* pCrsr = pCurCrsr;
3070
3071 do
3072 {
3073 if ( pCrsr->HasReadonlySel( GetViewOptions()->IsFormView() ) )
3074 {
3075 bRet = sal_True;
3076 }
3077
3078 pCrsr = (SwPaM*)pCrsr->GetNext();
3079 } while ( !bRet && pCrsr != pCurCrsr );
3080 }
3081 }
3082 return bRet;
3083 }
3084
IsSelFullPara() const3085 sal_Bool SwCrsrShell::IsSelFullPara() const
3086 {
3087 sal_Bool bRet = sal_False;
3088
3089 if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
3090 pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() )
3091 {
3092 xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(),
3093 nEnd = pCurCrsr->GetMark()->nContent.GetIndex();
3094 if( nStt > nEnd )
3095 {
3096 xub_StrLen nTmp = nStt;
3097 nStt = nEnd;
3098 nEnd = nTmp;
3099 }
3100 const SwCntntNode* pCNd = pCurCrsr->GetCntntNode();
3101 bRet = pCNd && !nStt && nEnd == pCNd->Len();
3102 }
3103 return bRet;
3104 }
3105
GetTextDirection(const Point * pPt) const3106 short SwCrsrShell::GetTextDirection( const Point* pPt ) const
3107 {
3108 SwPosition aPos( *pCurCrsr->GetPoint() );
3109 Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() );
3110 if( pPt )
3111 {
3112 SwCrsrMoveState aTmpState( MV_NONE );
3113 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
3114
3115 GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
3116 }
3117
3118 return pDoc->GetTextDirection( aPos, &aPt );
3119 }
3120
IsInVerticalText(const Point * pPt) const3121 sal_Bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const
3122 {
3123 const short nDir = GetTextDirection( pPt );
3124 return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
3125 }
3126
IsInRightToLeftText(const Point * pPt) const3127 sal_Bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
3128 {
3129 const short nDir = GetTextDirection( pPt );
3130 // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
3131 // vertical environment
3132 return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
3133 }
3134
3135 //
3136 // If the current cursor position is inside a hidden range, the hidden range
3137 // is selected:
3138 //
SelectHiddenRange()3139 bool SwCrsrShell::SelectHiddenRange()
3140 {
3141 bool bRet = false;
3142 if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() )
3143 {
3144 SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint();
3145 const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
3146 if ( pNode )
3147 {
3148 const xub_StrLen nPos = rPt.nContent.GetIndex();
3149
3150 // check if nPos is in hidden range
3151 xub_StrLen nHiddenStart;
3152 xub_StrLen nHiddenEnd;
3153 SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
3154 if ( STRING_LEN != nHiddenStart )
3155 {
3156 // make selection:
3157 pCurCrsr->SetMark();
3158 pCurCrsr->GetMark()->nContent = nHiddenEnd;
3159 bRet = true;
3160 }
3161 }
3162 }
3163
3164 return bRet;
3165 }
3166
3167 /* */
3168
3169 // die Suchfunktionen
Find(const SearchOptions & rSearchOpt,sal_Bool bSearchInNotes,SwDocPositions eStart,SwDocPositions eEnde,sal_Bool & bCancel,FindRanges eRng,int bReplace)3170 sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
3171 SwDocPositions eStart, SwDocPositions eEnde,
3172 sal_Bool& bCancel,
3173 FindRanges eRng, int bReplace )
3174 {
3175 if( pTblCrsr )
3176 GetCrsr();
3177 delete pTblCrsr, pTblCrsr = 0;
3178 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
3179 sal_uLong nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace );
3180 if( nRet || bCancel )
3181 UpdateCrsr();
3182 return nRet;
3183 }
3184
Find(const SwTxtFmtColl & rFmtColl,SwDocPositions eStart,SwDocPositions eEnde,sal_Bool & bCancel,FindRanges eRng,const SwTxtFmtColl * pReplFmt)3185 sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
3186 SwDocPositions eStart, SwDocPositions eEnde,
3187 sal_Bool& bCancel,
3188 FindRanges eRng, const SwTxtFmtColl* pReplFmt )
3189 {
3190 if( pTblCrsr )
3191 GetCrsr();
3192 delete pTblCrsr, pTblCrsr = 0;
3193 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
3194 sal_uLong nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt );
3195 if( nRet )
3196 UpdateCrsr();
3197 return nRet;
3198 }
3199
Find(const SfxItemSet & rSet,sal_Bool bNoCollections,SwDocPositions eStart,SwDocPositions eEnde,sal_Bool & bCancel,FindRanges eRng,const SearchOptions * pSearchOpt,const SfxItemSet * rReplSet)3200 sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
3201 SwDocPositions eStart, SwDocPositions eEnde,
3202 sal_Bool& bCancel,
3203 FindRanges eRng, const SearchOptions* pSearchOpt,
3204 const SfxItemSet* rReplSet )
3205 {
3206 if( pTblCrsr )
3207 GetCrsr();
3208 delete pTblCrsr, pTblCrsr = 0;
3209 SwCallLink aLk( *this ); // Crsr-Moves ueberwachen, evt. Link callen
3210 sal_uLong nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel,
3211 eRng, pSearchOpt, rReplSet );
3212 if( nRet )
3213 UpdateCrsr();
3214 return nRet;
3215 }
3216
SetSelection(const SwPaM & rCrsr)3217 void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
3218 {
3219 StartAction();
3220 SwPaM* pCrsr = GetCrsr();
3221 *pCrsr->GetPoint() = *rCrsr.GetPoint();
3222 if(rCrsr.HasMark())
3223 {
3224 pCrsr->SetMark();
3225 *pCrsr->GetMark() = *rCrsr.GetMark();
3226 }
3227 if((SwPaM*)rCrsr.GetNext() != &rCrsr)
3228 {
3229 const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
3230 do
3231 {
3232 SwPaM* pCurrentCrsr = CreateCrsr();
3233 *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
3234 if(_pStartCrsr->HasMark())
3235 {
3236 pCurrentCrsr->SetMark();
3237 *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
3238 }
3239 } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
3240 }
3241 EndAction();
3242 }
3243
lcl_RemoveMark(SwPaM * pPam)3244 void lcl_RemoveMark( SwPaM* pPam )
3245 {
3246 ASSERT( pPam->HasMark(), "Don't remove pPoint!" )
3247 pPam->GetMark()->nContent.Assign( 0, 0 );
3248 pPam->GetMark()->nNode = 0;
3249 pPam->DeleteMark();
3250 }
3251
lcl_NodeContext(const SwNode & rNode)3252 const SwStartNode* lcl_NodeContext( const SwNode& rNode )
3253 {
3254 const SwStartNode *pRet = rNode.StartOfSectionNode();
3255 while( pRet->IsSectionNode() || pRet->IsTableNode() ||
3256 pRet->GetStartNodeType() == SwTableBoxStartNode )
3257 {
3258 pRet = pRet->StartOfSectionNode();
3259 }
3260 return pRet;
3261 }
3262
3263 /**
3264 Checks if a position is valid. To be valid the position's node must
3265 be a content node and the content must not be unregistered.
3266
3267 @param aPos the position to check.
3268 */
lcl_PosOk(const SwPosition & aPos)3269 bool lcl_PosOk(const SwPosition & aPos)
3270 {
3271 return NULL != aPos.nNode.GetNode().GetCntntNode() &&
3272 SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg();
3273 }
3274
3275 /**
3276 Checks if a PaM is valid. For a PaM to be valid its point must be
3277 valid. Additionaly if the PaM has a mark this has to be valid, too.
3278
3279 @param aPam the PaM to check
3280 */
lcl_CrsrOk(SwPaM & aPam)3281 static bool lcl_CrsrOk(SwPaM & aPam)
3282 {
3283 return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
3284 || lcl_PosOk(*aPam.GetMark()));
3285 }
3286
ClearUpCrsrs()3287 void SwCrsrShell::ClearUpCrsrs()
3288 {
3289 // start of the ring
3290 SwPaM * pStartCrsr = GetCrsr();
3291 // start loop with second entry of the ring
3292 SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
3293 SwPaM * pTmpCrsr;
3294 bool bChanged = false;
3295
3296 /*
3297 For all entries in the ring except the start entry delete the
3298 entry if it is invalid.
3299 */
3300 while (pCrsr != pStartCrsr)
3301 {
3302 pTmpCrsr = (SwPaM *) pCrsr->GetNext();
3303
3304 if ( ! lcl_CrsrOk(*pCrsr))
3305 {
3306 delete pCrsr;
3307
3308 bChanged = true;
3309 }
3310
3311 pCrsr = pTmpCrsr;
3312 }
3313
3314 if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) )
3315 {
3316 lcl_RemoveMark( pStartCrsr );
3317 bChanged = true;
3318 }
3319 if( !lcl_PosOk( *pStartCrsr->GetPoint() ) )
3320 {
3321 SwNodes & aNodes = GetDoc()->GetNodes();
3322 const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
3323 SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
3324 SwNode * pNode = aNodes.GoPrevious(&aIdx);
3325 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3326 aNodes.GoNext( &aIdx );
3327 if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3328 {
3329 /*
3330 If the start entry of the ring is invalid replace it with a
3331 cursor pointing to the beginning of the first content node in
3332 the document.
3333 */
3334 aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
3335 pNode = aNodes.GoNext( &aIdx );
3336 }
3337 bool bFound = (pNode != NULL);
3338
3339 ASSERT(bFound, "no content node found");
3340
3341 if (bFound)
3342 {
3343 SwPaM aTmpPam(*pNode);
3344 *pStartCrsr = aTmpPam;
3345 }
3346
3347 bChanged = true;
3348 }
3349
3350 /*
3351 If at least one of the cursors in the ring have been deleted or
3352 replaced, remove the table cursor.
3353 */
3354 if (pTblCrsr != NULL && bChanged)
3355 TblCrsrToCursor();
3356 }
3357
3358 // #111827#
GetCrsrDescr() const3359 String SwCrsrShell::GetCrsrDescr() const
3360 {
3361 String aResult;
3362
3363 if (IsMultiSelection())
3364 aResult += String(SW_RES(STR_MULTISEL));
3365 else
3366 aResult = GetDoc()->GetPaMDescr(*GetCrsr());
3367
3368 return aResult;
3369 }
3370
3371 // SMARTTAGS
3372
lcl_FillRecognizerData(uno::Sequence<rtl::OUString> & rSmartTagTypes,uno::Sequence<uno::Reference<container::XStringKeyMap>> & rStringKeyMaps,const SwWrongList & rSmartTagList,xub_StrLen nCurrent)3373 void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3374 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3375 const SwWrongList& rSmartTagList, xub_StrLen nCurrent )
3376 {
3377 // Insert smart tag information
3378 std::vector< rtl::OUString > aSmartTagTypes;
3379 std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
3380
3381 for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i )
3382 {
3383 const xub_StrLen nSTPos = rSmartTagList.Pos( i );
3384 const xub_StrLen nSTLen = rSmartTagList.Len( i );
3385
3386 if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
3387 {
3388 const SwWrongArea* pArea = rSmartTagList.GetElement( i );
3389 if ( pArea )
3390 {
3391 aSmartTagTypes.push_back( pArea->maType );
3392 aStringKeyMaps.push_back( pArea->mxPropertyBag );
3393 }
3394 }
3395 }
3396
3397 if ( aSmartTagTypes.size() )
3398 {
3399 rSmartTagTypes.realloc( aSmartTagTypes.size() );
3400 rStringKeyMaps.realloc( aSmartTagTypes.size() );
3401
3402 std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
3403 sal_uInt16 i = 0;
3404 for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
3405 rSmartTagTypes[i++] = *aTypesIter;
3406
3407 std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
3408 i = 0;
3409 for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
3410 rStringKeyMaps[i++] = *aMapsIter;
3411 }
3412 }
3413
lcl_FillTextRange(uno::Reference<text::XTextRange> & rRange,SwTxtNode & rNode,xub_StrLen nBegin,xub_StrLen nLen)3414 void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
3415 SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen )
3416 {
3417 // create SwPosition for nStartIndex
3418 SwIndex aIndex( &rNode, nBegin );
3419 SwPosition aStartPos( rNode, aIndex );
3420
3421 // create SwPosition for nEndIndex
3422 SwPosition aEndPos( aStartPos );
3423 aEndPos.nContent = nBegin + nLen;
3424
3425 const uno::Reference<text::XTextRange> xRange =
3426 SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos);
3427
3428 rRange = xRange;
3429 }
3430
GetSmartTagTerm(uno::Sequence<rtl::OUString> & rSmartTagTypes,uno::Sequence<uno::Reference<container::XStringKeyMap>> & rStringKeyMaps,uno::Reference<text::XTextRange> & rRange) const3431 void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3432 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3433 uno::Reference< text::XTextRange>& rRange ) const
3434 {
3435 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3436 return;
3437
3438 SwPaM* pCrsr = GetCrsr();
3439 SwPosition aPos( *pCrsr->GetPoint() );
3440 SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
3441 if ( pNode && !pNode->IsInProtectSect() )
3442 {
3443 const SwWrongList *pSmartTagList = pNode->GetSmartTags();
3444 if ( pSmartTagList )
3445 {
3446 xub_StrLen nCurrent = aPos.nContent.GetIndex();
3447 xub_StrLen nBegin = nCurrent;
3448 xub_StrLen nLen = 1;
3449
3450 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3451 {
3452 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3453 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3454 if ( pSubList )
3455 {
3456 pSmartTagList = pSubList;
3457 nCurrent = 0;
3458 }
3459
3460 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3461 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3462 }
3463 }
3464 }
3465 }
3466
3467 // 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)3468 void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
3469 uno::Sequence< rtl::OUString >& rSmartTagTypes,
3470 uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3471 uno::Reference<text::XTextRange>& rRange )
3472 {
3473 if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3474 return;
3475
3476 SwPaM* pCrsr = GetCrsr();
3477 SwPosition aPos( *pCrsr->GetPoint() );
3478 Point aPt( rPt );
3479 SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
3480 SwSpecialPos aSpecialPos;
3481 eTmpState.pSpecialPos = &aSpecialPos;
3482 SwTxtNode *pNode;
3483 const SwWrongList *pSmartTagList;
3484
3485 if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
3486 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
3487 0 != (pSmartTagList = pNode->GetSmartTags()) &&
3488 !pNode->IsInProtectSect() )
3489 {
3490 xub_StrLen nCurrent = aPos.nContent.GetIndex();
3491 xub_StrLen nBegin = nCurrent;
3492 xub_StrLen nLen = 1;
3493
3494 if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3495 {
3496 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3497 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3498 if ( pSubList )
3499 {
3500 pSmartTagList = pSubList;
3501 nCurrent = eTmpState.pSpecialPos->nCharOfst;
3502 }
3503
3504 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3505 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3506
3507 // get smarttag word
3508 String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
3509
3510 //save the start and end positons of the line and the starting point
3511 Push();
3512 LeftMargin();
3513 xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
3514 RightMargin();
3515 xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
3516 Pop(sal_False);
3517
3518 // make sure the selection build later from the
3519 // data below does not include footnotes and other
3520 // "in word" character to the left and right in order
3521 // to preserve those. Therefore count those "in words"
3522 // in order to modify the selection accordingly.
3523 const sal_Unicode* pChar = aText.GetBuffer();
3524 xub_StrLen nLeft = 0;
3525 while (pChar && *pChar++ == CH_TXTATR_INWORD)
3526 ++nLeft;
3527 pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
3528 xub_StrLen nRight = 0;
3529 while (pChar && *pChar-- == CH_TXTATR_INWORD)
3530 ++nRight;
3531
3532 aPos.nContent = nBegin + nLeft;
3533 pCrsr = GetCrsr();
3534 *pCrsr->GetPoint() = aPos;
3535 pCrsr->SetMark();
3536 ExtendSelection( sal_True, nLen - nLeft - nRight );
3537 //no determine the rectangle in the current line
3538 xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
3539 //take one less than the line end - otherwise the next line would be calculated
3540 xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight);
3541 Push();
3542 pCrsr->DeleteMark();
3543 SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
3544 rContent = nWordStart;
3545 SwRect aStartRect;
3546 SwCrsrMoveState aState;
3547 aState.bRealWidth = sal_True;
3548 SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
3549 SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), sal_False);
3550
3551 pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
3552 rContent = nWordEnd;
3553 SwRect aEndRect;
3554 pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
3555 rSelectRect = aStartRect.Union( aEndRect );
3556 Pop(sal_False);
3557 }
3558 }
3559 }
3560
3561