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
27
28 #include <hintids.hxx>
29 #include <editeng/protitem.hxx>
30 #include <com/sun/star/i18n/WordType.hdl>
31 #include <com/sun/star/i18n/CharType.hdl>
32 #include <unotools/charclass.hxx>
33 #include <svl/ctloptions.hxx>
34 #include <swmodule.hxx>
35 #include <fmtcntnt.hxx>
36 #include <swtblfmt.hxx>
37 #include <swcrsr.hxx>
38 #include <unocrsr.hxx>
39 #include <doc.hxx>
40 #include <IDocumentUndoRedo.hxx>
41 #include <docary.hxx>
42 #include <ndtxt.hxx>
43 #include <section.hxx>
44 #include <swtable.hxx>
45 #include <cntfrm.hxx>
46 #include <rootfrm.hxx>
47 #include <txtfrm.hxx>
48 #include <scriptinfo.hxx>
49 #include <crstate.hxx>
50 #include <docsh.hxx>
51 #include <viewsh.hxx>
52 #include <frmatr.hxx>
53 #include <breakit.hxx>
54 #include <crsskip.hxx>
55 #include <vcl/msgbox.hxx>
56 #include <mdiexp.hxx> // ...Percent()
57 #include <statstr.hrc> // ResId fuer Statusleiste
58 #include <redline.hxx> // SwRedline
59 #include <txatbase.hxx>
60
61
62 using namespace ::com::sun::star::i18n;
63
64
65 static const sal_uInt16 coSrchRplcThreshold = 60000;
66
67 struct _PercentHdl
68 {
69 SwDocShell* pDSh;
70 sal_uLong nActPos;
71 sal_Bool bBack, bNodeIdx;
72
_PercentHdl_PercentHdl73 _PercentHdl( sal_uLong nStt, sal_uLong nEnd, SwDocShell* pSh )
74 : pDSh( pSh )
75 {
76 nActPos = nStt;
77 if( 0 != ( bBack = (nStt > nEnd )) )
78 {
79 sal_uLong n = nStt; nStt = nEnd; nEnd = n;
80 }
81 ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, 0 );
82 }
83
_PercentHdl_PercentHdl84 _PercentHdl( const SwPaM& rPam )
85 : pDSh( (SwDocShell*)rPam.GetDoc()->GetDocShell() )
86 {
87 sal_uLong nStt, nEnd;
88 if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
89 {
90 bNodeIdx = sal_False;
91 nStt = rPam.GetMark()->nContent.GetIndex();
92 nEnd = rPam.GetPoint()->nContent.GetIndex();
93 }
94 else
95 {
96 bNodeIdx = sal_True;
97 nStt = rPam.GetMark()->nNode.GetIndex();
98 nEnd = rPam.GetPoint()->nNode.GetIndex();
99 }
100 nActPos = nStt;
101 if( 0 != ( bBack = (nStt > nEnd )) )
102 {
103 sal_uLong n = nStt; nStt = nEnd; nEnd = n;
104 }
105 ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, pDSh );
106 }
107
~_PercentHdl_PercentHdl108 ~_PercentHdl() { ::EndProgress( pDSh ); }
109
NextPos_PercentHdl110 void NextPos( sal_uLong nPos ) const
111 { ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh ); }
112
NextPos_PercentHdl113 void NextPos( SwPosition& rPos ) const
114 {
115 sal_uLong nPos;
116 if( bNodeIdx )
117 nPos = rPos.nNode.GetIndex();
118 else
119 nPos = rPos.nContent.GetIndex();
120 ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh );
121 }
122 };
123
SwCursor(const SwPosition & rPos,SwPaM * pRing,bool bColumnSel)124 SwCursor::SwCursor( const SwPosition &rPos, SwPaM* pRing, bool bColumnSel )
125 : SwPaM( rPos, pRing ), pSavePos( 0 ), mnRowSpanOffset( 0 ), nCursorBidiLevel( 0 ),
126 mbColumnSelection( bColumnSel )
127 {
128 }
129
130 // @@@ semantic: no copy ctor.
SwCursor(SwCursor & rCpy)131 SwCursor::SwCursor( SwCursor& rCpy )
132 : SwPaM( rCpy ), pSavePos( 0 ), mnRowSpanOffset( rCpy.mnRowSpanOffset ),
133 nCursorBidiLevel( rCpy.nCursorBidiLevel ), mbColumnSelection( rCpy.mbColumnSelection )
134 {
135 }
136
~SwCursor()137 SwCursor::~SwCursor()
138 {
139 while( pSavePos )
140 {
141 _SwCursor_SavePos* pNxt = pSavePos->pNext;
142 delete pSavePos;
143 pSavePos = pNxt;
144 }
145 }
146
Create(SwPaM * pRing) const147 SwCursor* SwCursor::Create( SwPaM* pRing ) const
148 {
149 return new SwCursor( *GetPoint(), pRing, false );
150 }
151
IsReadOnlyAvailable() const152 bool SwCursor::IsReadOnlyAvailable() const
153 {
154 return false;
155 }
156
IsSkipOverHiddenSections() const157 sal_Bool SwCursor::IsSkipOverHiddenSections() const
158 {
159 return sal_True;
160 }
161
IsSkipOverProtectSections() const162 sal_Bool SwCursor::IsSkipOverProtectSections() const
163 {
164 return !IsReadOnlyAvailable();
165 }
166
167
168 // Sicher die aktuelle Position, damit ggfs. auf diese zurueck
169 // gefallen werden kann. Die SavePos Objekte werden als Stack verwaltet,
170 // damit das auch alles bei verschachtelten Aufrufen funktioniert.
171 // Das CreateNewSavePos ist virtual, damit abgeleitete Klassen vom Cursor
172 // gegebenenfalls eigene SaveObjecte anlegen und in den virtuellen
173 // Check-Routinen verwenden koennen.
174
SaveState()175 void SwCursor::SaveState()
176 {
177 _SwCursor_SavePos* pNew = CreateNewSavePos();
178 pNew->pNext = pSavePos;
179 pSavePos = pNew;
180 }
181
RestoreState()182 void SwCursor::RestoreState()
183 {
184 if( pSavePos ) // Robust
185 {
186 _SwCursor_SavePos* pDel = pSavePos;
187 pSavePos = pSavePos->pNext;
188 delete pDel;
189 }
190 }
191
CreateNewSavePos() const192 _SwCursor_SavePos* SwCursor::CreateNewSavePos() const
193 {
194 return new _SwCursor_SavePos( *this );
195 }
196
197 // stelle fest, ob sich der Point ausserhalb des Content-Bereichs
198 // vom Nodes-Array befindet
IsNoCntnt() const199 sal_Bool SwCursor::IsNoCntnt() const
200 {
201 return GetPoint()->nNode.GetIndex() <
202 GetDoc()->GetNodes().GetEndOfExtras().GetIndex();
203 }
204
IsSelOvrCheck(int)205 bool SwCursor::IsSelOvrCheck(int)
206 {
207 return false;
208 }
209
210 // extracted from IsSelOvr()
IsSelOvrCheck(int eFlags)211 bool SwTableCursor::IsSelOvrCheck(int eFlags)
212 {
213 SwNodes& rNds = GetDoc()->GetNodes();
214 // check sections of nodes array
215 if( (nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION & eFlags)
216 && HasMark() )
217 {
218 SwNodeIndex aOldPos( rNds, GetSavePos()->nNode );
219 if( !CheckNodesRange( aOldPos, GetPoint()->nNode, sal_True ))
220 {
221 GetPoint()->nNode = aOldPos;
222 GetPoint()->nContent.Assign( GetCntntNode(), GetSavePos()->nCntnt );
223 return true;
224 }
225 }
226 return SwCursor::IsSelOvrCheck(eFlags);
227 }
228
IsSelOvr(int eFlags)229 sal_Bool SwCursor::IsSelOvr( int eFlags )
230 {
231 SwDoc* pDoc = GetDoc();
232 SwNodes& rNds = pDoc->GetNodes();
233
234 sal_Bool bSkipOverHiddenSections = IsSkipOverHiddenSections();
235 sal_Bool bSkipOverProtectSections = IsSkipOverProtectSections();
236
237 if ( IsSelOvrCheck( eFlags ) )
238 {
239 return sal_True;
240 }
241
242 if( pSavePos->nNode != GetPoint()->nNode.GetIndex()
243 && ( !pDoc->GetDocShell()
244 || !pDoc->GetDocShell()->IsReadOnlyUI() ) )
245 {
246 // teste doch mal die neuen Sections:
247 SwNodeIndex& rPtIdx = GetPoint()->nNode;
248 const SwSectionNode* pSectNd = rPtIdx.GetNode().FindSectionNode();
249 if( pSectNd &&
250 ((bSkipOverHiddenSections && pSectNd->GetSection().IsHiddenFlag() ) ||
251 (bSkipOverProtectSections && pSectNd->GetSection().IsProtectFlag() )))
252 {
253 if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
254 {
255 // dann wars das schon
256 RestoreSavePos();
257 return sal_True;
258 }
259
260 // dann setze den Cursor auf die neue Position:
261 SwNodeIndex aIdx( rPtIdx );
262 xub_StrLen nCntntPos = pSavePos->nCntnt;
263 int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
264 SwCntntNode* pCNd = bGoNxt
265 ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
266 : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
267 if( !pCNd && ( nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION & eFlags ))
268 {
269 bGoNxt = !bGoNxt;
270 pCNd = bGoNxt ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
271 : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
272 }
273
274 int bIsValidPos = 0 != pCNd;
275 sal_Bool bValidNodesRange = bIsValidPos &&
276 ::CheckNodesRange( rPtIdx, aIdx, sal_True );
277 if( !bValidNodesRange )
278 {
279 rPtIdx = pSavePos->nNode;
280 if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
281 {
282 bIsValidPos = sal_False;
283 nCntntPos = 0;
284 rPtIdx = aIdx;
285 if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
286 {
287 // dann auf den Anfang vom Doc
288 rPtIdx = rNds.GetEndOfExtras();
289 pCNd = rNds.GoNext( &rPtIdx );
290 }
291 }
292 }
293
294 // ContentIndex noch anmelden:
295 xub_StrLen nTmpPos = bIsValidPos ? (bGoNxt ? 0 : pCNd->Len()) : nCntntPos;
296 GetPoint()->nContent.Assign( pCNd, nTmpPos );
297 if( !bIsValidPos || !bValidNodesRange ||
298 // sollten wir in einer Tabelle gelandet sein?
299 IsInProtectTable( sal_True ) )
300 return sal_True;
301 }
302
303 // oder sollte eine geschuetzte Section innerhalb der Selektion liegen?
304 if( HasMark() && bSkipOverProtectSections)
305 {
306 sal_uLong nSttIdx = GetMark()->nNode.GetIndex(),
307 nEndIdx = GetPoint()->nNode.GetIndex();
308 if( nEndIdx <= nSttIdx )
309 {
310 sal_uLong nTmp = nSttIdx;
311 nSttIdx = nEndIdx;
312 nEndIdx = nTmp;
313 }
314
315 const SwSectionFmts& rFmts = pDoc->GetSections();
316 for( sal_uInt16 n = 0; n < rFmts.Count(); ++n )
317 {
318 const SwSectionFmt* pFmt = rFmts[n];
319 const SvxProtectItem& rProtect = pFmt->GetProtect();
320 if( rProtect.IsCntntProtected() )
321 {
322 const SwFmtCntnt& rCntnt = pFmt->GetCntnt(sal_False);
323 ASSERT( rCntnt.GetCntntIdx(), "wo ist der SectionNode?" );
324 sal_uLong nIdx = rCntnt.GetCntntIdx()->GetIndex();
325 if( nSttIdx <= nIdx && nEndIdx >= nIdx )
326 {
327 // ist es keine gelinkte Section, dann kann sie auch
328 // nicht mitselektiert werden
329 const SwSection& rSect = *pFmt->GetSection();
330 if( CONTENT_SECTION == rSect.GetType() )
331 {
332 RestoreSavePos();
333 return sal_True;
334 }
335 }
336 }
337 }
338 }
339
340 }
341
342 const SwNode* pNd = &GetPoint()->nNode.GetNode();
343 if( pNd->IsCntntNode() && !dynamic_cast<SwUnoCrsr*>(this) )
344 {
345 const SwCntntFrm* pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() );
346 if( pFrm && pFrm->IsValid()
347 && 0 == pFrm->Frm().Height()
348 && 0 != ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
349 {
350 // skip to the next / prev valid paragraph with a layout
351 SwNodeIndex& rPtIdx = GetPoint()->nNode;
352 int bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
353 while( 0 != ( pFrm = ( bGoNxt ? pFrm->GetNextCntntFrm() : pFrm->GetPrevCntntFrm() ))
354 && 0 == pFrm->Frm().Height() )
355 ;
356
357 // --> LIJIAN/FME 2007-11-27 #i72394# skip to prev /next valid paragraph
358 // with a layout in case the first search did not succeed:
359 if( !pFrm )
360 {
361 bGoNxt = !bGoNxt;
362 pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() );
363 while ( pFrm && 0 == pFrm->Frm().Height() )
364 {
365 pFrm = bGoNxt ? pFrm->GetNextCntntFrm()
366 : pFrm->GetPrevCntntFrm();
367 }
368 }
369 // <--
370
371 SwCntntNode* pCNd;
372 if( pFrm && 0 != (pCNd = (SwCntntNode*)pFrm->GetNode()) )
373 {
374 // set this cntntNode as new position
375 rPtIdx = *pCNd;
376 pNd = pCNd;
377
378 // ContentIndex noch anmelden:
379 xub_StrLen nTmpPos = bGoNxt ? 0 : pCNd->Len();
380 GetPoint()->nContent.Assign( pCNd, nTmpPos );
381
382 // sollten wir in einer Tabelle gelandet sein?
383 if( IsInProtectTable( sal_True ) )
384 pFrm = 0;
385 }
386 }
387
388 if( !pFrm )
389 {
390 DeleteMark();
391 RestoreSavePos();
392 return sal_True; // ohne Frames geht gar nichts!
393 }
394 }
395
396 // darf der Cursor in geschuetzen "Nodes" stehen?
397 if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) && !IsAtValidPos() )
398 {
399 DeleteMark();
400 RestoreSavePos();
401 return sal_True;
402 }
403
404 if( !HasMark() )
405 return sal_False;
406
407 //JP 19.08.98: teste mal auf ungueltige Selektion - sprich ueber
408 // GrundSections:
409 if( !::CheckNodesRange( GetMark()->nNode, GetPoint()->nNode, sal_True ))
410 {
411 DeleteMark();
412 RestoreSavePos();
413 return sal_True; // ohne Frames geht gar nichts!
414 }
415
416 if( (pNd = &GetMark()->nNode.GetNode())->IsCntntNode()
417 && !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() )
418 && !dynamic_cast<SwUnoCrsr*>(this) )
419 {
420 DeleteMark();
421 RestoreSavePos();
422 return sal_True; // ohne Frames geht gar nichts!
423 }
424
425 // assure that selection is only inside an InputField or contains the InputField completely
426 {
427 const SwTxtAttr* pInputFldTxtAttrAtPoint = NULL;
428 SwTxtNode* pTxtNdAtPoint = GetPoint()->nNode.GetNode().GetTxtNode();
429 if ( pTxtNdAtPoint != NULL )
430 {
431 pInputFldTxtAttrAtPoint =
432 pTxtNdAtPoint->GetTxtAttrAt( GetPoint()->nContent.GetIndex(), RES_TXTATR_INPUTFIELD, SwTxtNode::PARENT );
433 }
434
435 const SwTxtAttr* pInputFldTxtAttrAtMark = NULL;
436 SwTxtNode* pTxtNdAtMark = GetMark()->nNode.GetNode().GetTxtNode();
437 if ( pTxtNdAtMark != NULL )
438 {
439 pInputFldTxtAttrAtMark =
440 pTxtNdAtMark->GetTxtAttrAt( GetMark()->nContent.GetIndex(), RES_TXTATR_INPUTFIELD, SwTxtNode::PARENT );
441 }
442
443 if ( pInputFldTxtAttrAtPoint != pInputFldTxtAttrAtMark )
444 {
445 const sal_uLong nRefNodeIdx =
446 ( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags )
447 ? pSavePos->nNode
448 : GetMark()->nNode.GetIndex();
449 const xub_StrLen nRefContentIdx =
450 ( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags )
451 ? pSavePos->nCntnt
452 : GetMark()->nContent.GetIndex();
453 const bool bIsForwardSelection =
454 nRefNodeIdx < GetPoint()->nNode.GetIndex()
455 || ( nRefNodeIdx == GetPoint()->nNode.GetIndex()
456 && nRefContentIdx < GetPoint()->nContent.GetIndex() );
457
458 if ( pInputFldTxtAttrAtPoint != NULL )
459 {
460 const xub_StrLen nNewPointPos =
461 bIsForwardSelection ? *(pInputFldTxtAttrAtPoint->End()) : *(pInputFldTxtAttrAtPoint->GetStart());
462 GetPoint()->nContent.Assign( pTxtNdAtPoint, nNewPointPos );
463 }
464
465 if ( pInputFldTxtAttrAtMark != NULL )
466 {
467 const xub_StrLen nNewMarkPos =
468 bIsForwardSelection ? *(pInputFldTxtAttrAtMark->GetStart()) : *(pInputFldTxtAttrAtMark->End());
469 GetMark()->nContent.Assign( pTxtNdAtMark, nNewMarkPos );
470 }
471 }
472 }
473
474 const SwTableNode* pPtNd = GetPoint()->nNode.GetNode().FindTableNode();
475 const SwTableNode* pMrkNd = GetMark()->nNode.GetNode().FindTableNode();
476 // beide in keinem oder beide im gleichen TableNode
477 if( ( !pMrkNd && !pPtNd ) || pPtNd == pMrkNd )
478 return sal_False;
479
480 // in unterschiedlichen Tabellen oder nur Mark in der Tabelle
481 if( ( pPtNd && pMrkNd ) || pMrkNd )
482 {
483 // dann lasse das nicht zu, alte Pos zurueck
484 RestoreSavePos();
485 // Crsr bleibt an der alten Position
486 return sal_True;
487 }
488
489 // ACHTUNG: dieses kann nicht im TableMode geschehen !!
490 if( pPtNd ) // nur Point in Tabelle, dann gehe hinter/vor diese
491 {
492 if( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags )
493 {
494 sal_Bool bSelTop = GetPoint()->nNode.GetIndex() <
495 (( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags ) ? pSavePos->nNode
496 : GetMark()->nNode.GetIndex());
497
498 do {
499 // in Schleife fuer Tabelle hinter Tabelle
500 sal_uLong nSEIdx = pPtNd->EndOfSectionIndex();
501 sal_uLong nSttEndTbl = nSEIdx + 1; // dflt. Sel. nach unten
502
503 if( bSelTop ) // Sel. nach oben
504 nSttEndTbl = rNds[ nSEIdx ]->StartOfSectionIndex() - 1;
505
506 GetPoint()->nNode = nSttEndTbl;
507 const SwNode* pMyNd = GetNode();
508
509 if( pMyNd->IsSectionNode() || ( pMyNd->IsEndNode() &&
510 pMyNd->StartOfSectionNode()->IsSectionNode() ) )
511 {
512 // die lassen wir zu:
513 pMyNd = bSelTop
514 ? rNds.GoPrevSection( &GetPoint()->nNode,sal_True,sal_False )
515 : rNds.GoNextSection( &GetPoint()->nNode,sal_True,sal_False );
516
517 /* #i12312# Handle failure of Go{Prev|Next}Section */
518 if ( 0 == pMyNd)
519 break;
520
521 if( 0 != ( pPtNd = pMyNd->FindTableNode() ))
522 continue;
523 }
524
525 if( pMyNd->IsCntntNode() && // ist es ein ContentNode ??
526 ::CheckNodesRange( GetMark()->nNode,
527 GetPoint()->nNode, sal_True ))
528 {
529 // TABLE IN TABLE
530 const SwTableNode* pOuterTableNd = pMyNd->FindTableNode();
531 if ( pOuterTableNd )
532 pMyNd = pOuterTableNd;
533 else
534 {
535 SwCntntNode* pCNd = (SwCntntNode*)pMyNd;
536 xub_StrLen nTmpPos = bSelTop ? pCNd->Len() : 0;
537 GetPoint()->nContent.Assign( pCNd, nTmpPos );
538 return sal_False;
539 }
540 }
541 if( bSelTop
542 ? ( !pMyNd->IsEndNode() || 0 == ( pPtNd = pMyNd->FindTableNode() ))
543 : 0 == ( pPtNd = pMyNd->GetTableNode() ))
544 break;
545 } while( sal_True );
546 }
547
548 // dann verbleibe auf der alten Position
549 RestoreSavePos();
550 return sal_True; // Crsr bleibt an der alten Position
551 }
552
553 return sal_False;
554 }
555
556 #if defined( UNX )
557 #define IDX (*pCellStt)
558 #else
559 #define IDX aCellStt
560 #endif
561
562
IsInProtectTable(sal_Bool bMove,sal_Bool bChgCrsr)563 sal_Bool SwCursor::IsInProtectTable( sal_Bool bMove, sal_Bool bChgCrsr )
564 {
565 SwCntntNode* pCNd = GetCntntNode();
566 if( !pCNd )
567 return sal_False;
568
569 // No table, no protected cell:
570 const SwTableNode* pTableNode = pCNd->FindTableNode();
571 if ( !pTableNode )
572 return sal_False;
573
574 // Current position == last save position?
575 if ( pSavePos->nNode == GetPoint()->nNode.GetIndex() )
576 return sal_False;
577
578 // Check for convered cell:
579 bool bInCoveredCell = false;
580 const SwStartNode* pTmpSttNode = pCNd->FindTableBoxStartNode();
581 ASSERT( pTmpSttNode, "In table, therefore I expect to get a SwTableBoxStartNode" )
582 const SwTableBox* pBox = pTmpSttNode ? pTableNode->GetTable().GetTblBox( pTmpSttNode->GetIndex() ) : 0; //Robust #151355
583 if ( pBox && pBox->getRowSpan() < 1 ) // Robust #151270
584 bInCoveredCell = true;
585
586 // Positions of covered cells are not acceptable:
587 if ( !bInCoveredCell )
588 {
589 // Position not protected?
590 if ( !pCNd->IsProtect() )
591 return sal_False;
592
593 // Cursor in protected cells allowed?
594 if ( IsReadOnlyAvailable() )
595 return sal_False;
596 }
597
598 // If we reach this point, we are in a protected or covered table cell!
599
600 if( !bMove )
601 {
602 if( bChgCrsr )
603 // restore the last save position
604 RestoreSavePos();
605 return sal_True; // Crsr bleibt an der alten Position
606 }
607
608 // wir stehen in einer geschuetzten TabellenZelle
609 // von Oben nach Unten Traveln ?
610 if( pSavePos->nNode < GetPoint()->nNode.GetIndex() )
611 {
612 // suche die naechste "gueltige" Box
613
614 // folgt nach dem EndNode der Zelle ein weiterer StartNode, dann
615 // gibt es auch eine naechste Zelle
616 #if defined( UNX )
617 SwNodeIndex* pCellStt = new SwNodeIndex( *GetNode()->
618 FindTableBoxStartNode()->EndOfSectionNode(), 1 );
619 #else
620 SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
621 #endif
622 sal_Bool bProt = sal_True;
623 GoNextCell:
624 do {
625 if( !IDX.GetNode().IsStartNode() )
626 break;
627 IDX++;
628 if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() ))
629 pCNd = IDX.GetNodes().GoNext( &IDX );
630 if( 0 == ( bProt = pCNd->IsProtect() ))
631 break;
632 IDX.Assign( *pCNd->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
633 } while( bProt );
634
635 SetNextCrsr:
636 if( !bProt ) // eine freie Zelle gefunden
637 {
638 GetPoint()->nNode = IDX;
639 #if defined( UNX )
640 delete pCellStt;
641 #endif
642 SwCntntNode* pTmpCNd = GetCntntNode();
643 if( pTmpCNd )
644 {
645 GetPoint()->nContent.Assign( pTmpCNd, 0 );
646 return sal_False;
647 }
648 return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
649 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
650 }
651 // am Ende der Tabelle, also setze hinter diese
652 IDX++; // auf den naechsten Node
653 SwNode* pNd;
654 if( ( pNd = &IDX.GetNode())->IsEndNode() || HasMark())
655 {
656 // Tabelle allein in einem FlyFrame oder SSelection,
657 // dann verbleibe auf der alten Position
658 if( bChgCrsr )
659 RestoreSavePos();
660 #if defined( UNX )
661 delete pCellStt;
662 #endif
663 return sal_True; // Crsr bleibt an der alten Position
664 }
665 else if( pNd->IsTableNode() && IDX++ )
666 goto GoNextCell;
667
668 bProt = sal_False; // Index steht jetzt auf einem ContentNode
669 goto SetNextCrsr;
670 }
671
672 // suche die vorherige "gueltige" Box
673 {
674 // liegt vor dem StartNode der Zelle ein weiterer EndNode, dann
675 // gibt es auch eine vorherige Zelle
676 #if defined( UNX )
677 SwNodeIndex* pCellStt = new SwNodeIndex(
678 *GetNode()->FindTableBoxStartNode(), -1 );
679 #else
680 SwNodeIndex aCellStt( *GetNode()->FindTableBoxStartNode(), -1 );
681 #endif
682 SwNode* pNd;
683 sal_Bool bProt = sal_True;
684 GoPrevCell:
685 do {
686 if( !( pNd = &IDX.GetNode())->IsEndNode() )
687 break;
688 IDX.Assign( *pNd->StartOfSectionNode(), +1 );
689 if( 0 == ( pCNd = IDX.GetNode().GetCntntNode() ))
690 pCNd = pNd->GetNodes().GoNext( &IDX );
691 if( 0 == ( bProt = pCNd->IsProtect() ))
692 break;
693 IDX.Assign( *pNd->FindTableBoxStartNode(), -1 );
694 } while( bProt );
695
696 SetPrevCrsr:
697 if( !bProt ) // eine freie Zelle gefunden
698 {
699 GetPoint()->nNode = IDX;
700 #if defined( UNX )
701 delete pCellStt;
702 #endif
703 SwCntntNode* pTmpCNd = GetCntntNode();
704 if( pTmpCNd )
705 {
706 GetPoint()->nContent.Assign( pTmpCNd, 0 );
707 return sal_False;
708 }
709 return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
710 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
711 }
712 // am Start der Tabelle, also setze vor diese
713 IDX--; // auf den naechsten Node
714 if( ( pNd = &IDX.GetNode())->IsStartNode() || HasMark() )
715 {
716 // Tabelle allein in einem FlyFrame oder Selektion,
717 // dann verbleibe auf der alten Position
718 if( bChgCrsr )
719 RestoreSavePos();
720 #if defined( UNX )
721 delete pCellStt;
722 #endif
723 return sal_True; // Crsr bleibt an der alten Position
724 }
725 else if( pNd->StartOfSectionNode()->IsTableNode() && IDX-- )
726 goto GoPrevCell;
727
728 bProt = sal_False; // Index steht jetzt auf einem ContentNode
729 goto SetPrevCrsr;
730 }
731 }
732
733 // sal_True: an die Position kann der Cursor gesetzt werden
IsAtValidPos(sal_Bool bPoint) const734 sal_Bool SwCursor::IsAtValidPos( sal_Bool bPoint ) const
735 {
736 const SwDoc* pDoc = GetDoc();
737 const SwPosition* pPos = bPoint ? GetPoint() : GetMark();
738 const SwNode* pNd = &pPos->nNode.GetNode();
739
740 if( pNd->IsCntntNode() && !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->GetCurrentLayout() ) &&
741 !dynamic_cast<const SwUnoCrsr*>(this) )
742 {
743 return sal_False;
744 }
745
746 //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
747 if( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() )
748 return sal_True;
749
750 sal_Bool bCrsrInReadOnly = IsReadOnlyAvailable();
751 if( !bCrsrInReadOnly && pNd->IsProtect() )
752 return sal_False;
753
754 const SwSectionNode* pSectNd = pNd->FindSectionNode();
755 if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
756 ( !bCrsrInReadOnly && pSectNd->GetSection().IsProtectFlag() )))
757 return sal_False;
758
759 return sal_True;
760 }
761
SaveTblBoxCntnt(const SwPosition *)762 void SwCursor::SaveTblBoxCntnt( const SwPosition* ) {}
763
764 // setze den SRange fuer das Suchen im Dokument
MakeFindRange(SwDocPositions nStart,SwDocPositions nEnd,SwPaM * pRange) const765 SwMoveFnCollection* SwCursor::MakeFindRange( SwDocPositions nStart,
766 SwDocPositions nEnd, SwPaM* pRange ) const
767 {
768 pRange->SetMark();
769 FillFindPos( nStart, *pRange->GetMark() );
770 FillFindPos( nEnd, *pRange->GetPoint() );
771
772 // bestimme die Richtung, in der zu suchen ist
773 // ( GetPoint > GetMark -> vorwaerts, sonst rueckwaerts )
774 return ( DOCPOS_START == nStart || DOCPOS_OTHERSTART == nStart ||
775 (DOCPOS_CURR == nStart &&
776 (DOCPOS_END == nEnd || DOCPOS_OTHEREND == nEnd ) ))
777 ? fnMoveForward : fnMoveBackward;
778 }
779
780
lcl_FindSelection(SwFindParas & rParas,SwCursor * pCurCrsr,SwMoveFn fnMove,SwCursor * & pFndRing,SwPaM & aRegion,FindRanges eFndRngs,sal_Bool bInReadOnly,sal_Bool & bCancel)781 sal_uLong lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurCrsr,
782 SwMoveFn fnMove, SwCursor*& pFndRing,
783 SwPaM& aRegion, FindRanges eFndRngs,
784 sal_Bool bInReadOnly, sal_Bool& bCancel )
785 {
786 SwDoc* pDoc = pCurCrsr->GetDoc();
787 bool const bDoesUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
788 int nFndRet = 0;
789 sal_uLong nFound = 0;
790 int bSrchBkwrd = fnMove == fnMoveBackward, bEnde = sal_False;
791 SwPaM *pTmpCrsr = pCurCrsr, *pSaveCrsr = pCurCrsr;
792
793 // only create progress-bar for ShellCrsr
794 bool bIsUnoCrsr = 0 != dynamic_cast<SwUnoCrsr*>(pCurCrsr);
795 _PercentHdl* pPHdl = 0;
796 sal_uInt16 nCrsrCnt = 0;
797 if( FND_IN_SEL & eFndRngs )
798 {
799 while( pCurCrsr != ( pTmpCrsr = (SwPaM*)pTmpCrsr->GetNext() ))
800 ++nCrsrCnt;
801 if( nCrsrCnt && !bIsUnoCrsr )
802 pPHdl = new _PercentHdl( 0, nCrsrCnt, pDoc->GetDocShell() );
803 }
804 else
805 pSaveCrsr = (SwPaM*)pSaveCrsr->GetPrev();
806
807 do {
808 aRegion.SetMark();
809 // egal in welche Richtung, SPoint ist immer groesser als Mark,
810 // wenn der Suchbereich gueltig ist !!
811 SwPosition *pSttPos = aRegion.GetMark(),
812 *pEndPos = aRegion.GetPoint();
813 *pSttPos = *pTmpCrsr->Start();
814 *pEndPos = *pTmpCrsr->End();
815 if( bSrchBkwrd )
816 aRegion.Exchange();
817
818 if( !nCrsrCnt && !pPHdl && !bIsUnoCrsr )
819 pPHdl = new _PercentHdl( aRegion );
820
821 // solange gefunden und nicht auf gleicher Position haengen bleibt
822 while( *pSttPos <= *pEndPos &&
823 0 != ( nFndRet = rParas.Find( pCurCrsr, fnMove,
824 &aRegion, bInReadOnly )) &&
825 ( !pFndRing ||
826 *pFndRing->GetPoint() != *pCurCrsr->GetPoint() ||
827 *pFndRing->GetMark() != *pCurCrsr->GetMark() ))
828 {
829 if( !( FIND_NO_RING & nFndRet ))
830 {
831 // Bug 24084: Ring richtig herum aufbauen -> gleiche Mimik
832 // wie beim CreateCrsr !!!!
833
834 SwCursor* pNew = pCurCrsr->Create( pFndRing );
835 if( !pFndRing )
836 pFndRing = pNew;
837
838 pNew->SetMark();
839 *pNew->GetMark() = *pCurCrsr->GetMark();
840 }
841
842 ++nFound;
843
844 if( !( eFndRngs & FND_IN_SELALL) )
845 {
846 bEnde = sal_True;
847 break;
848 }
849
850 if ((coSrchRplcThreshold == nFound)
851 && pDoc->GetIDocumentUndoRedo().DoesUndo()
852 && rParas.IsReplaceMode())
853 {
854 short nRet = pCurCrsr->MaxReplaceArived();
855 if( RET_YES == nRet )
856 {
857 pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
858 pDoc->GetIDocumentUndoRedo().DoUndo(false);
859 }
860 else
861 {
862 bEnde = sal_True;
863 if(RET_CANCEL == nRet)
864 {
865 bCancel = sal_True;
866 //unwind() ??
867 }
868 break;
869 }
870 }
871
872 if( bSrchBkwrd )
873 // bewege pEndPos vor den gefundenen Bereich
874 *pEndPos = *pCurCrsr->Start();
875 else
876 // bewege pSttPos hinter den gefundenen Bereich
877 *pSttPos = *pCurCrsr->End();
878
879 if( *pSttPos == *pEndPos ) // im Bereich, aber am Ende
880 break; // fertig
881
882 if( !nCrsrCnt && pPHdl )
883 {
884 pPHdl->NextPos( *aRegion.GetMark() );
885 }
886 }
887
888 if( bEnde || !( eFndRngs & ( FND_IN_SELALL | FND_IN_SEL )) )
889 break;
890
891 pTmpCrsr = ((SwPaM*)pTmpCrsr->GetNext());
892 if( nCrsrCnt && pPHdl )
893 {
894 pPHdl->NextPos( ++pPHdl->nActPos );
895 }
896
897 } while( pTmpCrsr != pSaveCrsr );
898
899 if( nFound && !pFndRing ) // falls kein Ring aufgebaut werden soll
900 pFndRing = pCurCrsr->Create();
901
902 delete pPHdl;
903 pDoc->GetIDocumentUndoRedo().DoUndo(bDoesUndo);
904 return nFound;
905 }
906
907
lcl_MakeSelFwrd(const SwNode & rSttNd,const SwNode & rEndNd,SwPaM & rPam,int bFirst)908 int lcl_MakeSelFwrd( const SwNode& rSttNd, const SwNode& rEndNd,
909 SwPaM& rPam, int bFirst )
910 {
911 if( rSttNd.GetIndex() + 1 == rEndNd.GetIndex() )
912 return sal_False;
913
914 SwNodes& rNds = rPam.GetDoc()->GetNodes();
915 rPam.DeleteMark();
916 SwCntntNode* pCNd;
917 if( !bFirst )
918 {
919 rPam.GetPoint()->nNode = rSttNd;
920 pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
921 if( !pCNd )
922 return sal_False;
923 pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
924 }
925 else if( rSttNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
926 rPam.GetPoint()->nNode.GetIndex() >= rEndNd.GetIndex() )
927 return sal_False; // steht nicht in dieser Section
928
929 rPam.SetMark();
930 rPam.GetPoint()->nNode = rEndNd;
931 pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
932 if( !pCNd )
933 return sal_False;
934 pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
935
936 return *rPam.GetMark() < *rPam.GetPoint();
937 }
938
939
lcl_MakeSelBkwrd(const SwNode & rSttNd,const SwNode & rEndNd,SwPaM & rPam,int bFirst)940 int lcl_MakeSelBkwrd( const SwNode& rSttNd, const SwNode& rEndNd,
941 SwPaM& rPam, int bFirst )
942 {
943 if( rEndNd.GetIndex() + 1 == rSttNd.GetIndex() )
944 return sal_False;
945
946 SwNodes& rNds = rPam.GetDoc()->GetNodes();
947 rPam.DeleteMark();
948 SwCntntNode* pCNd;
949 if( !bFirst )
950 {
951 rPam.GetPoint()->nNode = rSttNd;
952 pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
953 if( !pCNd )
954 return sal_False;
955 pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
956 }
957 else if( rEndNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
958 rPam.GetPoint()->nNode.GetIndex() >= rSttNd.GetIndex() )
959 return sal_False; // steht nicht in dieser Section
960
961 rPam.SetMark();
962 rPam.GetPoint()->nNode = rEndNd;
963 pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
964 if( !pCNd )
965 return sal_False;
966 pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
967
968 return *rPam.GetPoint() < *rPam.GetMark();
969 }
970
971
972 // diese Methode "sucht" fuer alle Anwendungsfaelle, denn in SwFindParas
973 // steht immer die richtigen Parameter und die entsprechende Find-Methode
974
FindAll(SwFindParas & rParas,SwDocPositions nStart,SwDocPositions nEnde,FindRanges eFndRngs,sal_Bool & bCancel)975 sal_uLong SwCursor::FindAll( SwFindParas& rParas,
976 SwDocPositions nStart, SwDocPositions nEnde,
977 FindRanges eFndRngs, sal_Bool& bCancel )
978 {
979 bCancel = sal_False;
980 SwCrsrSaveState aSaveState( *this );
981
982 // Region erzeugen, ohne das diese in den Ring aufgenommen wird !
983 SwPaM aRegion( *GetPoint() );
984 SwMoveFn fnMove = MakeFindRange( nStart, nEnde, &aRegion );
985
986 sal_uLong nFound = 0;
987 int bMvBkwrd = fnMove == fnMoveBackward;
988 sal_Bool bInReadOnly = IsReadOnlyAvailable();
989
990 SwCursor* pFndRing = 0;
991 SwNodes& rNds = GetDoc()->GetNodes();
992
993 // suche in Bereichen ?
994 if( FND_IN_SEL & eFndRngs )
995 {
996 // String nicht im Bereich gefunden, dann erhalte alle Bereiche,
997 // der Cursor beleibt unveraendert
998 if( 0 == ( nFound = lcl_FindSelection( rParas, this, fnMove,
999 pFndRing, aRegion, eFndRngs,
1000 bInReadOnly, bCancel ) ))
1001 return nFound;
1002
1003 // der String wurde ein- bis mehrmals gefunden. Das steht alles
1004 // im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf
1005 while( GetNext() != this )
1006 delete GetNext();
1007
1008 *GetPoint() = *pFndRing->GetPoint();
1009 SetMark();
1010 *GetMark() = *pFndRing->GetMark();
1011 pFndRing->MoveRingTo( this );
1012 delete pFndRing;
1013 }
1014 else if( FND_IN_OTHER & eFndRngs )
1015 {
1016 // Cursor als Kopie vom akt. und in den Ring aufnehmen
1017 // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
1018 std::auto_ptr< SwCursor > pSav( Create( this ) ); // save the current cursor
1019
1020 // wenn schon ausserhalb vom Bodytext, suche von der Position,
1021 // ansonsten beginne mit der 1. GrundSection
1022 if( bMvBkwrd
1023 ? lcl_MakeSelBkwrd( rNds.GetEndOfExtras(),
1024 *rNds.GetEndOfPostIts().StartOfSectionNode(),
1025 *this, rNds.GetEndOfExtras().GetIndex() >=
1026 GetPoint()->nNode.GetIndex() )
1027 : lcl_MakeSelFwrd( *rNds.GetEndOfPostIts().StartOfSectionNode(),
1028 rNds.GetEndOfExtras(), *this,
1029 rNds.GetEndOfExtras().GetIndex() >=
1030 GetPoint()->nNode.GetIndex() ))
1031 {
1032 nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
1033 aRegion, eFndRngs, bInReadOnly, bCancel );
1034 }
1035
1036 if( !nFound )
1037 {
1038 // den alten wieder zurueck
1039 *GetPoint() = *pSav->GetPoint();
1040 if( pSav->HasMark() )
1041 {
1042 SetMark();
1043 *GetMark() = *pSav->GetMark();
1044 }
1045 else
1046 DeleteMark();
1047 return 0;
1048 }
1049 pSav.release();
1050
1051 if( !( FND_IN_SELALL & eFndRngs ))
1052 {
1053 // es sollte nur einer gesucht werden, also fuege in dazu
1054 // egal in welche Richtung, SPoint ist immer groesser als Mark,
1055 // wenn der Suchbereich gueltig ist !!
1056 *GetPoint() = *pFndRing->GetPoint();
1057 SetMark();
1058 *GetMark() = *pFndRing->GetMark();
1059 }
1060 else
1061 {
1062 // es wurde ein- bis mehrmals gefunden. Das steht alles
1063 // im neuen Crsr-Ring. Darum hebe erstmal den alten Ring auf
1064 while( GetNext() != this )
1065 delete GetNext();
1066
1067 *GetPoint() = *pFndRing->GetPoint();
1068 SetMark();
1069 *GetMark() = *pFndRing->GetMark();
1070 pFndRing->MoveRingTo( this );
1071 }
1072 delete pFndRing;
1073 }
1074 else if( FND_IN_SELALL & eFndRngs )
1075 {
1076 ::std::auto_ptr< SwCursor> pSav( Create( this ) ); // save the current cursor
1077
1078 const SwNode* pSttNd = ( FND_IN_BODYONLY & eFndRngs )
1079 ? rNds.GetEndOfContent().StartOfSectionNode()
1080 : rNds.GetEndOfPostIts().StartOfSectionNode();
1081
1082 if( bMvBkwrd
1083 ? lcl_MakeSelBkwrd( rNds.GetEndOfContent(), *pSttNd,*this, sal_False )
1084 : lcl_MakeSelFwrd( *pSttNd, rNds.GetEndOfContent(), *this, sal_False ))
1085 {
1086 nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
1087 aRegion, eFndRngs, bInReadOnly, bCancel );
1088 }
1089
1090 if( !nFound )
1091 {
1092 // den alten wieder zurueck
1093 *GetPoint() = *pSav->GetPoint();
1094 if( pSav->HasMark() )
1095 {
1096 SetMark();
1097 *GetMark() = *pSav->GetMark();
1098 }
1099 else
1100 DeleteMark();
1101 return 0;
1102 }
1103 pSav.release();
1104 while( GetNext() != this )
1105 delete GetNext();
1106
1107 *GetPoint() = *pFndRing->GetPoint();
1108 SetMark();
1109 *GetMark() = *pFndRing->GetMark();
1110 pFndRing->MoveRingTo( this );
1111 delete pFndRing;
1112 }
1113 else
1114 {
1115 // ist ein GetMark gesetzt, dann wird bei gefundenem Object
1116 // der GetMark beibehalten !! Dadurch kann ein Bereich mit der Suche
1117 // aufgespannt werden.
1118 SwPosition aMarkPos( *GetMark() );
1119 int bMarkPos = HasMark() && !eFndRngs;
1120
1121 if( 0 != (nFound = rParas.Find( this, fnMove,
1122 &aRegion, bInReadOnly ) ? 1 : 0)
1123 && bMarkPos )
1124 *GetMark() = aMarkPos;
1125 }
1126
1127 if( nFound && SwCursor::IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE ) )
1128 nFound = 0;
1129 return nFound;
1130 }
1131
1132
FillFindPos(SwDocPositions ePos,SwPosition & rPos) const1133 void SwCursor::FillFindPos( SwDocPositions ePos, SwPosition& rPos ) const
1134 {
1135 sal_Bool bIsStart = sal_True;
1136 SwCntntNode* pCNd = 0;
1137 SwNodes& rNds = GetDoc()->GetNodes();
1138
1139 switch( ePos )
1140 {
1141 case DOCPOS_START:
1142 rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
1143 pCNd = rNds.GoNext( &rPos.nNode );
1144 break;
1145
1146 case DOCPOS_END:
1147 rPos.nNode = rNds.GetEndOfContent();
1148 pCNd = rNds.GoPrevious( &rPos.nNode );
1149 bIsStart = sal_False;
1150 break;
1151
1152 case DOCPOS_OTHERSTART:
1153 rPos.nNode = *rNds[ sal_uLong(0) ];
1154 pCNd = rNds.GoNext( &rPos.nNode );
1155 break;
1156
1157 case DOCPOS_OTHEREND:
1158 rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
1159 pCNd = rNds.GoPrevious( &rPos.nNode );
1160 bIsStart = sal_False;
1161 break;
1162
1163 // case DOCPOS_CURR:
1164 default:
1165 rPos = *GetPoint();
1166 }
1167
1168 if( pCNd )
1169 {
1170 xub_StrLen nCPos = 0;
1171 if( !bIsStart )
1172 nCPos = pCNd->Len();
1173 rPos.nContent.Assign( pCNd, nCPos );
1174 }
1175 }
1176
MaxReplaceArived()1177 short SwCursor::MaxReplaceArived()
1178 {
1179 return RET_YES;
1180 }
1181
1182
IsStartWord(sal_Int16 nWordType) const1183 sal_Bool SwCursor::IsStartWord( sal_Int16 nWordType ) const
1184 {
1185 return IsStartWordWT( nWordType );
1186 }
1187
IsEndWord(sal_Int16 nWordType) const1188 sal_Bool SwCursor::IsEndWord( sal_Int16 nWordType ) const
1189 {
1190 return IsEndWordWT( nWordType );
1191 }
1192
IsInWord(sal_Int16 nWordType) const1193 sal_Bool SwCursor::IsInWord( sal_Int16 nWordType ) const
1194 {
1195 return IsInWordWT( nWordType );
1196 }
1197
GoStartWord()1198 sal_Bool SwCursor::GoStartWord()
1199 {
1200 return GoStartWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
1201 }
1202
GoEndWord()1203 sal_Bool SwCursor::GoEndWord()
1204 {
1205 return GoEndWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
1206 }
1207
GoNextWord()1208 sal_Bool SwCursor::GoNextWord()
1209 {
1210 return GoNextWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
1211 }
1212
GoPrevWord()1213 sal_Bool SwCursor::GoPrevWord()
1214 {
1215 return GoPrevWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
1216 }
1217
SelectWord(ViewShell * pViewShell,const Point * pPt)1218 sal_Bool SwCursor::SelectWord( ViewShell* pViewShell, const Point* pPt )
1219 {
1220 return SelectWordWT( pViewShell, WordType::ANYWORD_IGNOREWHITESPACES, pPt );
1221 }
1222
IsStartWordWT(sal_Int16 nWordType) const1223 sal_Bool SwCursor::IsStartWordWT( sal_Int16 nWordType ) const
1224 {
1225 sal_Bool bRet = sal_False;
1226 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1227 if( pTxtNd && pBreakIt->GetBreakIter().is() )
1228 {
1229 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1230 bRet = pBreakIt->GetBreakIter()->isBeginWord(
1231 pTxtNd->GetTxt(), nPtPos,
1232 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos )),
1233 nWordType );
1234 }
1235 return bRet;
1236 }
1237
IsEndWordWT(sal_Int16 nWordType) const1238 sal_Bool SwCursor::IsEndWordWT( sal_Int16 nWordType ) const
1239 {
1240 sal_Bool bRet = sal_False;
1241 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1242 if( pTxtNd && pBreakIt->GetBreakIter().is() )
1243 {
1244 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1245 bRet = pBreakIt->GetBreakIter()->isEndWord(
1246 pTxtNd->GetTxt(), nPtPos,
1247 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1248 nWordType );
1249
1250 }
1251 return bRet;
1252 }
1253
IsInWordWT(sal_Int16 nWordType) const1254 sal_Bool SwCursor::IsInWordWT( sal_Int16 nWordType ) const
1255 {
1256 sal_Bool bRet = sal_False;
1257 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1258 if( pTxtNd && pBreakIt->GetBreakIter().is() )
1259 {
1260 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1261 Boundary aBoundary = pBreakIt->GetBreakIter()->getWordBoundary(
1262 pTxtNd->GetTxt(), nPtPos,
1263 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1264 nWordType,
1265 sal_True );
1266
1267 bRet = aBoundary.startPos != aBoundary.endPos &&
1268 aBoundary.startPos <= nPtPos &&
1269 nPtPos <= aBoundary.endPos;
1270 if(bRet)
1271 {
1272 const CharClass& rCC = GetAppCharClass();
1273 bRet = rCC.isLetterNumeric( pTxtNd->GetTxt(), static_cast<xub_StrLen>(aBoundary.startPos) );
1274 }
1275 }
1276 return bRet;
1277 }
1278
IsStartEndSentence(bool bEnd) const1279 sal_Bool SwCursor::IsStartEndSentence( bool bEnd ) const
1280 {
1281 sal_Bool bRet = bEnd ?
1282 GetCntntNode() && GetPoint()->nContent == GetCntntNode()->Len() :
1283 GetPoint()->nContent.GetIndex() == 0;
1284
1285 if( !bRet )
1286 {
1287 SwCursor aCrsr(*GetPoint(), 0, false);
1288 SwPosition aOrigPos = *aCrsr.GetPoint();
1289 aCrsr.GoSentence( bEnd ? SwCursor::END_SENT : SwCursor::START_SENT );
1290 bRet = aOrigPos == *aCrsr.GetPoint();
1291 }
1292
1293 return bRet;
1294 }
1295
GoStartWordWT(sal_Int16 nWordType)1296 sal_Bool SwCursor::GoStartWordWT( sal_Int16 nWordType )
1297 {
1298 sal_Bool bRet = sal_False;
1299 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1300 if( pTxtNd && pBreakIt->GetBreakIter().is() )
1301 {
1302 SwCrsrSaveState aSave( *this );
1303 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1304 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary(
1305 pTxtNd->GetTxt(), nPtPos,
1306 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1307 nWordType,
1308 sal_False ).startPos;
1309
1310 if( nPtPos < pTxtNd->GetTxt().Len() )
1311 {
1312 GetPoint()->nContent = nPtPos;
1313 if( !IsSelOvr() )
1314 bRet = sal_True;
1315 }
1316 }
1317 return bRet;
1318 }
1319
GoEndWordWT(sal_Int16 nWordType)1320 sal_Bool SwCursor::GoEndWordWT( sal_Int16 nWordType )
1321 {
1322 sal_Bool bRet = sal_False;
1323 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1324 if( pTxtNd && pBreakIt->GetBreakIter().is() )
1325 {
1326 SwCrsrSaveState aSave( *this );
1327 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1328 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->getWordBoundary(
1329 pTxtNd->GetTxt(), nPtPos,
1330 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1331 nWordType,
1332 sal_True ).endPos;
1333
1334 if( nPtPos <= pTxtNd->GetTxt().Len() &&
1335 GetPoint()->nContent.GetIndex() != nPtPos )
1336 {
1337 GetPoint()->nContent = nPtPos;
1338 if( !IsSelOvr() )
1339 bRet = sal_True;
1340 }
1341 }
1342 return bRet;
1343 }
1344
GoNextWordWT(sal_Int16 nWordType)1345 sal_Bool SwCursor::GoNextWordWT( sal_Int16 nWordType )
1346 {
1347 sal_Bool bRet = sal_False;
1348 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1349 if( pTxtNd && pBreakIt->GetBreakIter().is() )
1350 {
1351 SwCrsrSaveState aSave( *this );
1352 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1353
1354 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->nextWord(
1355 pTxtNd->GetTxt(), nPtPos,
1356 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
1357 nWordType ).startPos;
1358
1359 if( nPtPos < pTxtNd->GetTxt().Len() )
1360 {
1361 GetPoint()->nContent = nPtPos;
1362 if( !IsSelOvr() )
1363 bRet = sal_True;
1364 }
1365 }
1366 return bRet;
1367 }
1368
GoPrevWordWT(sal_Int16 nWordType)1369 sal_Bool SwCursor::GoPrevWordWT( sal_Int16 nWordType )
1370 {
1371 sal_Bool bRet = sal_False;
1372 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1373 if( pTxtNd && pBreakIt->GetBreakIter().is() )
1374 {
1375 SwCrsrSaveState aSave( *this );
1376 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1377 const xub_StrLen nPtStart = nPtPos;
1378
1379 if( nPtPos )
1380 --nPtPos;
1381 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->previousWord(
1382 pTxtNd->GetTxt(), nPtStart,
1383 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
1384 nWordType ).startPos;
1385
1386 if( nPtPos < pTxtNd->GetTxt().Len() )
1387 {
1388 GetPoint()->nContent = nPtPos;
1389 if( !IsSelOvr() )
1390 bRet = sal_True;
1391 }
1392 }
1393 return bRet;
1394 }
1395
SelectWordWT(ViewShell * pViewShell,sal_Int16 nWordType,const Point * pPt)1396 sal_Bool SwCursor::SelectWordWT( ViewShell* pViewShell, sal_Int16 nWordType, const Point* pPt )
1397 {
1398 SwCrsrSaveState aSave( *this );
1399
1400 sal_Bool bRet = sal_False;
1401 sal_Bool bForward = sal_True;
1402 DeleteMark();
1403 const SwRootFrm* pLayout = pViewShell->GetLayout();
1404 if( pPt && 0 != pLayout )
1405 {
1406 // set the cursor to the layout position
1407 Point aPt( *pPt );
1408 pLayout->GetCrsrOfst( GetPoint(), aPt );
1409 } //swmod 071107//swmod 071225
1410
1411 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1412 if( pTxtNd && pBreakIt->GetBreakIter().is() )
1413 {
1414 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1415 Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary(
1416 pTxtNd->GetTxt(), nPtPos,
1417 pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
1418 nWordType,
1419 bForward ));
1420
1421 if( aBndry.startPos != aBndry.endPos )
1422 {
1423 GetPoint()->nContent = (xub_StrLen)aBndry.endPos;
1424 if( !IsSelOvr() )
1425 {
1426 SetMark();
1427 GetMark()->nContent = (xub_StrLen)aBndry.startPos;
1428 if( !IsSelOvr() )
1429 bRet = sal_True;
1430 }
1431 }
1432 }
1433
1434 if( !bRet )
1435 {
1436 DeleteMark();
1437 RestoreSavePos();
1438 }
1439 return bRet;
1440 }
1441
1442 //-----------------------------------------------------------------------------
1443
lcl_MaskDeletedRedlines(const SwTxtNode * pTxtNd)1444 static String lcl_MaskDeletedRedlines( const SwTxtNode* pTxtNd )
1445 {
1446 String aRes;
1447 if (pTxtNd)
1448 {
1449 //mask deleted redlines
1450 String sNodeText(pTxtNd->GetTxt());
1451 const SwDoc& rDoc = *pTxtNd->GetDoc();
1452 const bool nShowChg = IDocumentRedlineAccess::IsShowChanges( rDoc.GetRedlineMode() );
1453 if ( nShowChg )
1454 {
1455 sal_uInt16 nAct = rDoc.GetRedlinePos( *pTxtNd, USHRT_MAX );
1456 for ( ; nAct < rDoc.GetRedlineTbl().Count(); nAct++ )
1457 {
1458 const SwRedline* pRed = rDoc.GetRedlineTbl()[ nAct ];
1459 if ( pRed->Start()->nNode > pTxtNd->GetIndex() )
1460 break;
1461
1462 if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() )
1463 {
1464 xub_StrLen nStart, nEnd;
1465 pRed->CalcStartEnd( pTxtNd->GetIndex(), nStart, nEnd );
1466
1467 while ( nStart < nEnd && nStart < sNodeText.Len() )
1468 sNodeText.SetChar( nStart++, CH_TXTATR_INWORD );
1469 }
1470 }
1471 }
1472 aRes = sNodeText;
1473 }
1474 return aRes;
1475 }
1476
GoSentence(SentenceMoveType eMoveType)1477 sal_Bool SwCursor::GoSentence( SentenceMoveType eMoveType )
1478 {
1479 sal_Bool bRet = sal_False;
1480 const SwTxtNode* pTxtNd = GetNode()->GetTxtNode();
1481 if( pTxtNd && pBreakIt->GetBreakIter().is() )
1482 {
1483 String sNodeText( lcl_MaskDeletedRedlines( pTxtNd ) );
1484
1485 SwCrsrSaveState aSave( *this );
1486 xub_StrLen nPtPos = GetPoint()->nContent.GetIndex();
1487 switch ( eMoveType )
1488 {
1489 case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
1490 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
1491 sNodeText,
1492 nPtPos, pBreakIt->GetLocale(
1493 pTxtNd->GetLang( nPtPos ) ));
1494 break;
1495 case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
1496 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
1497 sNodeText,
1498 nPtPos, pBreakIt->GetLocale(
1499 pTxtNd->GetLang( nPtPos ) ));
1500 break;
1501 case NEXT_SENT:
1502 {
1503 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
1504 sNodeText,
1505 nPtPos, pBreakIt->GetLocale(
1506 pTxtNd->GetLang( nPtPos ) ));
1507 while (nPtPos != (sal_uInt16) -1 && ++nPtPos < sNodeText.Len()
1508 && sNodeText.GetChar(nPtPos)== ' ' /*isWhiteSpace( aTxt.GetChar(nPtPos)*/ )
1509 ;
1510 break;
1511 }
1512 case PREV_SENT:
1513 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
1514 sNodeText,
1515 nPtPos, pBreakIt->GetLocale(
1516 pTxtNd->GetLang( nPtPos ) ));
1517 if (nPtPos == 0)
1518 return sal_False; // the previous sentence is not in this paragraph
1519 if (nPtPos > 0)
1520 nPtPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
1521 sNodeText,
1522 nPtPos - 1, pBreakIt->GetLocale(
1523 pTxtNd->GetLang( nPtPos ) ));
1524 break;
1525 }
1526
1527 // it is allowed to place the PaM just behind the last
1528 // character in the text thus <= ...Len
1529 if( nPtPos <= pTxtNd->GetTxt().Len() )
1530 {
1531 GetPoint()->nContent = nPtPos;
1532 if( !IsSelOvr() )
1533 bRet = sal_True;
1534 }
1535 }
1536 return bRet;
1537 }
1538
1539
ExpandToSentenceBorders()1540 sal_Bool SwCursor::ExpandToSentenceBorders()
1541 {
1542 sal_Bool bRes = sal_False;
1543 const SwTxtNode* pStartNd = Start()->nNode.GetNode().GetTxtNode();
1544 const SwTxtNode* pEndNd = End()->nNode.GetNode().GetTxtNode();
1545 if (pStartNd && pEndNd && pBreakIt->GetBreakIter().is())
1546 {
1547 if (!HasMark())
1548 SetMark();
1549
1550 String sStartText( lcl_MaskDeletedRedlines( pStartNd ) );
1551 String sEndText( pStartNd == pEndNd? sStartText : lcl_MaskDeletedRedlines( pEndNd ) );
1552
1553 SwCrsrSaveState aSave( *this );
1554 xub_StrLen nStartPos = Start()->nContent.GetIndex();
1555 xub_StrLen nEndPos = End()->nContent.GetIndex();
1556
1557 nStartPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfSentence(
1558 sStartText, nStartPos,
1559 pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) );
1560 nEndPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfSentence(
1561 sEndText, nEndPos,
1562 pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) );
1563
1564 // it is allowed to place the PaM just behind the last
1565 // character in the text thus <= ...Len
1566 bool bChanged = false;
1567 if (nStartPos <= pStartNd->GetTxt().Len())
1568 {
1569 GetMark()->nContent = nStartPos;
1570 bChanged = true;
1571 }
1572 if (nEndPos <= pEndNd->GetTxt().Len())
1573 {
1574 GetPoint()->nContent = nEndPos;
1575 bChanged = true;
1576 }
1577 if (bChanged && !IsSelOvr())
1578 bRes = sal_True;
1579 }
1580 return bRes;
1581 }
1582
1583
LeftRight(sal_Bool bLeft,sal_uInt16 nCnt,sal_uInt16,sal_Bool,sal_Bool,sal_Bool)1584 sal_Bool SwTableCursor::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 /*nMode*/,
1585 sal_Bool /*bVisualAllowed*/, sal_Bool /*bSkipHidden*/, sal_Bool /*bInsertCrsr*/ )
1586 {
1587 return bLeft ? GoPrevCell( nCnt )
1588 : GoNextCell( nCnt );
1589 }
1590
1591
1592 // calculate cursor bidi level: extracted from LeftRight()
1593 const SwCntntFrm*
DoSetBidiLevelLeftRight(sal_Bool & io_rbLeft,sal_Bool bVisualAllowed,sal_Bool bInsertCrsr)1594 SwCursor::DoSetBidiLevelLeftRight(
1595 sal_Bool & io_rbLeft, sal_Bool bVisualAllowed, sal_Bool bInsertCrsr)
1596 {
1597 // calculate cursor bidi level
1598 const SwCntntFrm* pSttFrm = NULL;
1599 SwNode& rNode = GetPoint()->nNode.GetNode();
1600
1601 if( rNode.IsTxtNode() )
1602 {
1603 const SwTxtNode& rTNd = *rNode.GetTxtNode();
1604 SwIndex& rIdx = GetPoint()->nContent;
1605 xub_StrLen nPos = rIdx.GetIndex();
1606
1607 const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
1608 if ( bVisualAllowed && rCTLOptions.IsCTLFontEnabled() &&
1609 SvtCTLOptions::MOVEMENT_VISUAL ==
1610 rCTLOptions.GetCTLCursorMovement() )
1611 {
1612 // for visual cursor travelling (used in bidi layout)
1613 // we first have to convert the logic to a visual position
1614 Point aPt;
1615 pSttFrm = rTNd.getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1616 if( pSttFrm )
1617 {
1618 sal_uInt8 nCrsrLevel = GetCrsrBidiLevel();
1619 sal_Bool bForward = ! io_rbLeft;
1620 ((SwTxtFrm*)pSttFrm)->PrepareVisualMove( nPos, nCrsrLevel,
1621 bForward, bInsertCrsr );
1622 rIdx = nPos;
1623 SetCrsrBidiLevel( nCrsrLevel );
1624 io_rbLeft = ! bForward;
1625 }
1626 }
1627 else
1628 {
1629 const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rTNd );
1630 if ( pSI )
1631 {
1632 const xub_StrLen nMoveOverPos = io_rbLeft ?
1633 ( nPos ? nPos - 1 : 0 ) :
1634 nPos;
1635 SetCrsrBidiLevel( pSI->DirType( nMoveOverPos ) );
1636 }
1637 }
1638 }
1639 return pSttFrm;
1640 }
1641
LeftRight(sal_Bool bLeft,sal_uInt16 nCnt,sal_uInt16 nMode,sal_Bool bVisualAllowed,sal_Bool bSkipHidden,sal_Bool bInsertCrsr)1642 sal_Bool SwCursor::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
1643 sal_Bool bVisualAllowed,sal_Bool bSkipHidden, sal_Bool bInsertCrsr )
1644 {
1645 // calculate cursor bidi level
1646 SwNode& rNode = GetPoint()->nNode.GetNode();
1647 const SwCntntFrm* pSttFrm = // may side-effect bLeft!
1648 DoSetBidiLevelLeftRight(bLeft, bVisualAllowed, bInsertCrsr);
1649
1650 // kann der Cursor n-mal weiterverschoben werden ?
1651 SwCrsrSaveState aSave( *this );
1652 SwMoveFn fnMove = bLeft ? fnMoveBackward : fnMoveForward;
1653
1654 SwGoInDoc fnGo;
1655 if ( bSkipHidden )
1656 fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCellsSkipHidden : fnGoCntntSkipHidden;
1657 else
1658 fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCells : fnGoCntnt;
1659
1660 // ASSERT( not in covered cell )
1661
1662 while( nCnt )
1663 {
1664 SwNodeIndex aOldNodeIdx( GetPoint()->nNode );
1665
1666 bool bSuccess = Move( fnMove, fnGo );
1667 if ( !bSuccess )
1668 break;
1669
1670 // If we were located inside a covered cell but our position has been
1671 // corrected, we check if the last move has moved the cursor to a different
1672 // table cell. In this case we set the cursor to the stored covered position
1673 // and redo the move:
1674 if ( mnRowSpanOffset )
1675 {
1676 const SwNode* pOldTabBoxSttNode = aOldNodeIdx.GetNode().FindTableBoxStartNode();
1677 const SwTableNode* pOldTabSttNode = pOldTabBoxSttNode ? pOldTabBoxSttNode->FindTableNode() : 0;
1678 const SwNode* pNewTabBoxSttNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
1679 const SwTableNode* pNewTabSttNode = pNewTabBoxSttNode ? pNewTabBoxSttNode->FindTableNode() : 0;
1680
1681 const bool bCellChanged = pOldTabSttNode && pNewTabSttNode &&
1682 pOldTabSttNode == pNewTabSttNode &&
1683 pOldTabBoxSttNode && pNewTabBoxSttNode &&
1684 pOldTabBoxSttNode != pNewTabBoxSttNode;
1685
1686 if ( bCellChanged )
1687 {
1688 // Set cursor to start/end of covered cell:
1689 SwTableBox* pTableBox = pOldTabBoxSttNode->GetTblBox();
1690 const long nRowSpan = pTableBox->getRowSpan();
1691 if ( nRowSpan > 1 )
1692 {
1693 pTableBox = & pTableBox->FindEndOfRowSpan( pOldTabSttNode->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset ) );
1694 SwNodeIndex& rPtIdx = GetPoint()->nNode;
1695 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
1696 rPtIdx = aNewIdx;
1697
1698 GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_False, sal_False );
1699 SwCntntNode* pCntntNode = GetCntntNode();
1700 if ( pCntntNode )
1701 {
1702 const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0;
1703 GetPoint()->nContent.Assign( pCntntNode, nTmpPos );
1704
1705 // Redo the move:
1706 bSuccess = Move( fnMove, fnGo );
1707 if ( !bSuccess )
1708 break;
1709 }
1710 }
1711
1712 mnRowSpanOffset = 0;
1713 }
1714 }
1715
1716 // Check if I'm inside a covered cell. Correct cursor if necessary and
1717 // store covered cell:
1718 const SwNode* pTableBoxStartNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
1719 if ( pTableBoxStartNode )
1720 {
1721 const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
1722 if ( pTableBox->getRowSpan() < 1 )
1723 {
1724 // Store the row span offset:
1725 mnRowSpanOffset = pTableBox->getRowSpan();
1726
1727 // Move cursor to non-covered cell:
1728 const SwTableNode* pTblNd = pTableBoxStartNode->FindTableNode();
1729 pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
1730 SwNodeIndex& rPtIdx = GetPoint()->nNode;
1731 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
1732 rPtIdx = aNewIdx;
1733
1734 GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_False, sal_False );
1735 SwCntntNode* pCntntNode = GetCntntNode();
1736 if ( pCntntNode )
1737 {
1738 const xub_StrLen nTmpPos = bLeft ? pCntntNode->Len() : 0;
1739 GetPoint()->nContent.Assign( pCntntNode, nTmpPos );
1740 }
1741 }
1742 }
1743
1744 --nCnt;
1745 }
1746
1747 // here come some special rules for visual cursor travelling
1748 if ( pSttFrm )
1749 {
1750 SwNode& rTmpNode = GetPoint()->nNode.GetNode();
1751 if ( &rTmpNode != &rNode && rTmpNode.IsTxtNode() )
1752 {
1753 Point aPt;
1754 const SwCntntFrm* pEndFrm = ((SwTxtNode&)rTmpNode).getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1755 if ( pEndFrm )
1756 {
1757 if ( ! pEndFrm->IsRightToLeft() != ! pSttFrm->IsRightToLeft() )
1758 {
1759 if ( ! bLeft )
1760 pEndFrm->RightMargin( this );
1761 else
1762 pEndFrm->LeftMargin( this );
1763 }
1764 }
1765 }
1766 }
1767
1768 return 0 == nCnt && !IsInProtectTable( sal_True ) &&
1769 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1770 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1771 }
1772
1773 // calculate cursor bidi level: extracted from UpDown()
DoSetBidiLevelUpDown()1774 void SwCursor::DoSetBidiLevelUpDown()
1775 {
1776 SwNode& rNode = GetPoint()->nNode.GetNode();
1777 if ( rNode.IsTxtNode() )
1778 {
1779 const SwScriptInfo* pSI =
1780 SwScriptInfo::GetScriptInfo( (SwTxtNode&)rNode );
1781 if ( pSI )
1782 {
1783 SwIndex& rIdx = GetPoint()->nContent;
1784 xub_StrLen nPos = rIdx.GetIndex();
1785
1786 if( nPos && nPos < ((SwTxtNode&)rNode).GetTxt().Len() )
1787 {
1788 const sal_uInt8 nCurrLevel = pSI->DirType( nPos );
1789 const sal_uInt8 nPrevLevel = pSI->DirType( nPos - 1 );
1790
1791 if ( nCurrLevel % 2 != nPrevLevel % 2 )
1792 {
1793 // set cursor level to the lower of the two levels
1794 SetCrsrBidiLevel( Min( nCurrLevel, nPrevLevel ) );
1795 }
1796 else
1797 SetCrsrBidiLevel( nCurrLevel );
1798 }
1799 }
1800 }
1801 }
1802
UpDown(sal_Bool bUp,sal_uInt16 nCnt,Point * pPt,long nUpDownX)1803 sal_Bool SwCursor::UpDown( sal_Bool bUp, sal_uInt16 nCnt,
1804 Point* pPt, long nUpDownX )
1805 {
1806 SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this);
1807 sal_Bool bAdjustTableCrsr = sal_False;
1808
1809 // vom Tabellen Crsr Point/Mark in der gleichen Box ??
1810 // dann stelle den Point an den Anfang der Box
1811 if( pTblCrsr && GetNode( sal_True )->StartOfSectionNode() ==
1812 GetNode( sal_False )->StartOfSectionNode() )
1813 {
1814 if ( End() != GetPoint() )
1815 Exchange();
1816 bAdjustTableCrsr = sal_True;
1817 }
1818
1819 sal_Bool bRet = sal_False;
1820 Point aPt;
1821 if( pPt )
1822 aPt = *pPt;
1823 SwCntntFrm* pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1824
1825 if( pFrm )
1826 {
1827 SwCrsrSaveState aSave( *this );
1828
1829 if( !pPt )
1830 {
1831 SwRect aTmpRect;
1832 pFrm->GetCharRect( aTmpRect, *GetPoint() );
1833 aPt = aTmpRect.Pos();
1834
1835 nUpDownX = pFrm->IsVertical() ?
1836 aPt.Y() - pFrm->Frm().Top() :
1837 aPt.X() - pFrm->Frm().Left();
1838 }
1839
1840 // Bei Fussnoten ist auch die Bewegung in eine andere Fussnote erlaubt.
1841 // aber keine Selection!!
1842 const sal_Bool bChkRange = pFrm->IsInFtn() && !HasMark()
1843 ? sal_False : sal_True;
1844 const SwPosition aOldPos( *GetPoint() );
1845 sal_Bool bInReadOnly = IsReadOnlyAvailable();
1846
1847 if ( bAdjustTableCrsr && !bUp )
1848 {
1849 // Special case: We have a table cursor but the start box
1850 // has more than one paragraph. If we want to go down, we have to
1851 // set the point to the last frame in the table box. This is
1852 // only necessary if we do not already have a table selection
1853 const SwStartNode* pTblNd = GetNode( sal_True )->FindTableBoxStartNode();
1854 ASSERT( pTblNd, "pTblCrsr without SwTableNode?" )
1855
1856 if ( pTblNd ) // safety first
1857 {
1858 const SwNode* pEndNd = pTblNd->EndOfSectionNode();
1859 GetPoint()->nNode = *pEndNd;
1860 pTblCrsr->Move( fnMoveBackward, fnGoNode );
1861 pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1862 }
1863 }
1864
1865 while( nCnt &&
1866 (bUp ? pFrm->UnitUp( this, nUpDownX, bInReadOnly )
1867 : pFrm->UnitDown( this, nUpDownX, bInReadOnly ) ) &&
1868 CheckNodesRange( aOldPos.nNode, GetPoint()->nNode, bChkRange ))
1869 {
1870 pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1871 --nCnt;
1872 }
1873
1874 if( !nCnt && !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1875 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) ) // die gesamte Anzahl durchlaufen ?
1876 {
1877 if( !pTblCrsr )
1878 {
1879 // dann versuche den Cursor auf die Position zu setzen,
1880 // auf halber Heohe vom Char-Rectangle
1881 pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1882 SwCrsrMoveState eTmpState( MV_UPDOWN );
1883 eTmpState.bSetInReadOnly = bInReadOnly;
1884 SwRect aTmpRect;
1885 pFrm->GetCharRect( aTmpRect, *GetPoint(), &eTmpState );
1886 if ( pFrm->IsVertical() )
1887 {
1888 aPt.X() = aTmpRect.Center().X();
1889 pFrm->Calc();
1890 aPt.Y() = pFrm->Frm().Top() + nUpDownX;
1891 }
1892 else
1893 {
1894 aPt.Y() = aTmpRect.Center().Y();
1895 pFrm->Calc();
1896 aPt.X() = pFrm->Frm().Left() + nUpDownX;
1897 }
1898 pFrm->GetCrsrOfst( GetPoint(), aPt, &eTmpState );
1899 }
1900 bRet = !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1901 }
1902 else
1903 *GetPoint() = aOldPos;
1904
1905 DoSetBidiLevelUpDown(); // calculate cursor bidi level
1906 }
1907
1908 return bRet;
1909 }
1910
LeftRightMargin(sal_Bool bLeft,sal_Bool bAPI)1911 sal_Bool SwCursor::LeftRightMargin( sal_Bool bLeft, sal_Bool bAPI )
1912 {
1913 Point aPt;
1914 SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1915
1916 // calculate cursor bidi level
1917 if ( pFrm )
1918 SetCrsrBidiLevel( pFrm->IsRightToLeft() ? 1 : 0 );
1919
1920 SwCrsrSaveState aSave( *this );
1921 return pFrm
1922 && (bLeft ? pFrm->LeftMargin( this ) : pFrm->RightMargin( this, bAPI ) )
1923 && !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1924 }
1925
IsAtLeftRightMargin(sal_Bool bLeft,sal_Bool bAPI) const1926 sal_Bool SwCursor::IsAtLeftRightMargin( sal_Bool bLeft, sal_Bool bAPI ) const
1927 {
1928 sal_Bool bRet = sal_False;
1929 Point aPt;
1930 SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->GetCurrentLayout(), &aPt, GetPoint() );
1931 if( pFrm )
1932 {
1933 SwPaM aPam( *GetPoint() );
1934 if( !bLeft && aPam.GetPoint()->nContent.GetIndex() )
1935 aPam.GetPoint()->nContent--;
1936 bRet = (bLeft ? pFrm->LeftMargin( &aPam )
1937 : pFrm->RightMargin( &aPam, bAPI ))
1938 && *aPam.GetPoint() == *GetPoint();
1939 }
1940 return bRet;
1941 }
1942
SttEndDoc(sal_Bool bStt)1943 sal_Bool SwCursor::SttEndDoc( sal_Bool bStt )
1944 {
1945 SwCrsrSaveState aSave( *this );
1946
1947 // Springe beim Selektieren nie ueber Section-Grenzen !!
1948 // kann der Cursor weiterverschoben werden ?
1949 SwMoveFn fnMove = bStt ? fnMoveBackward : fnMoveForward;
1950 sal_Bool bRet = (!HasMark() || !IsNoCntnt() ) &&
1951 Move( fnMove, fnGoDoc ) &&
1952 !IsInProtectTable( sal_True ) &&
1953 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1954 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS |
1955 nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION );
1956
1957 return bRet;
1958 }
1959
GoPrevNextCell(sal_Bool bNext,sal_uInt16 nCnt)1960 sal_Bool SwCursor::GoPrevNextCell( sal_Bool bNext, sal_uInt16 nCnt )
1961 {
1962 const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
1963 if( !pTblNd )
1964 return sal_False;
1965
1966 // liegt vor dem StartNode der Cell ein weiterer EndNode, dann
1967 // gibt es auch eine vorherige Celle
1968 SwCrsrSaveState aSave( *this );
1969 SwNodeIndex& rPtIdx = GetPoint()->nNode;
1970
1971 while( nCnt-- )
1972 {
1973 const SwNode* pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
1974 const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
1975
1976 // Check if we have to move the cursor to a covered cell before
1977 // proceeding:
1978 if ( mnRowSpanOffset )
1979 {
1980 if ( pTableBox->getRowSpan() > 1 )
1981 {
1982 pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset) );
1983 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
1984 rPtIdx = aNewIdx;
1985 pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
1986 }
1987 mnRowSpanOffset = 0;
1988 }
1989
1990 const SwNode* pTmpNode = bNext ?
1991 pTableBoxStartNode->EndOfSectionNode() :
1992 pTableBoxStartNode;
1993
1994 SwNodeIndex aCellIdx( *pTmpNode, bNext ? 1 : -1 );
1995 if( (bNext && !aCellIdx.GetNode().IsStartNode()) ||
1996 (!bNext && !aCellIdx.GetNode().IsEndNode()) )
1997 return sal_False;
1998
1999 rPtIdx = bNext ? aCellIdx : SwNodeIndex(*aCellIdx.GetNode().StartOfSectionNode());
2000
2001 pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
2002 pTableBox = pTableBoxStartNode->GetTblBox();
2003 if ( pTableBox->getRowSpan() < 1 )
2004 {
2005 mnRowSpanOffset = pTableBox->getRowSpan();
2006 // move cursor to non-covered cell:
2007 pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
2008 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
2009 rPtIdx = aNewIdx;
2010 }
2011 }
2012
2013 rPtIdx++;
2014 if( !rPtIdx.GetNode().IsCntntNode() )
2015 GetDoc()->GetNodes().GoNextSection( &rPtIdx, sal_True, sal_False );
2016 GetPoint()->nContent.Assign( GetCntntNode(), 0 );
2017
2018 return !IsInProtectTable( sal_True );
2019 }
2020
GotoTable(const String &)2021 sal_Bool SwTableCursor::GotoTable( const String& /*rName*/ )
2022 {
2023 return sal_False; // invalid action
2024 }
2025
GotoTable(const String & rName)2026 sal_Bool SwCursor::GotoTable( const String& rName )
2027 {
2028 sal_Bool bRet = sal_False;
2029 if ( !HasMark() )
2030 {
2031 SwTable* pTmpTbl = SwTable::FindTable( GetDoc()->FindTblFmtByName( rName ) );
2032 if( pTmpTbl )
2033 {
2034 // eine Tabelle im normalen NodesArr
2035 SwCrsrSaveState aSave( *this );
2036 GetPoint()->nNode = *pTmpTbl->GetTabSortBoxes()[ 0 ]->
2037 GetSttNd()->FindTableNode();
2038 Move( fnMoveForward, fnGoCntnt );
2039 bRet = !IsSelOvr();
2040 }
2041 }
2042 return bRet;
2043 }
2044
GotoTblBox(const String & rName)2045 sal_Bool SwCursor::GotoTblBox( const String& rName )
2046 {
2047 sal_Bool bRet = sal_False;
2048 const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
2049 if( pTblNd )
2050 {
2051 // erfrage die Box, mit dem Nanen
2052 const SwTableBox* pTblBox = pTblNd->GetTable().GetTblBox( rName );
2053 if( pTblBox && pTblBox->GetSttNd() &&
2054 ( !pTblBox->GetFrmFmt()->GetProtect().IsCntntProtected() ||
2055 IsReadOnlyAvailable() ) )
2056 {
2057 SwCrsrSaveState aSave( *this );
2058 GetPoint()->nNode = *pTblBox->GetSttNd();
2059 Move( fnMoveForward, fnGoCntnt );
2060 bRet = !IsSelOvr();
2061 }
2062 }
2063 return bRet;
2064 }
2065
MovePara(SwWhichPara fnWhichPara,SwPosPara fnPosPara)2066 sal_Bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
2067 {
2068 //JP 28.8.2001: for optimization test something before
2069 const SwNode* pNd = &GetPoint()->nNode.GetNode();
2070 bool bShortCut = false;
2071 if ( fnWhichPara == fnParaCurr )
2072 {
2073 // --> FME 2005-02-21 #i41048#
2074 // If fnWhichPara == fnParaCurr, (*fnWhichPara)( *this, fnPosPara )
2075 // can already move the cursor to a different text node. In this case
2076 // we better check if IsSelOvr().
2077 const SwCntntNode* pCntntNd = pNd->GetCntntNode();
2078 if ( pCntntNd )
2079 {
2080 const xub_StrLen nSttEnd = fnPosPara == fnMoveForward ? 0 : pCntntNd->Len();
2081 if ( GetPoint()->nContent.GetIndex() != nSttEnd )
2082 bShortCut = true;
2083 }
2084 // <--
2085 }
2086 else
2087 {
2088 if ( pNd->IsTxtNode() &&
2089 pNd->GetNodes()[ pNd->GetIndex() +
2090 (fnWhichPara == fnParaNext ? 1 : -1 ) ]->IsTxtNode() )
2091 bShortCut = true;
2092 }
2093
2094 if ( bShortCut )
2095 return (*fnWhichPara)( *this, fnPosPara );
2096
2097 // else we must use the SaveStructure, because the next/prev is not
2098 // a same node type.
2099 SwCrsrSaveState aSave( *this );
2100 return (*fnWhichPara)( *this, fnPosPara ) &&
2101 !IsInProtectTable( sal_True ) &&
2102 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2103 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
2104 }
2105
2106
MoveSection(SwWhichSection fnWhichSect,SwPosSection fnPosSect)2107 sal_Bool SwCursor::MoveSection( SwWhichSection fnWhichSect,
2108 SwPosSection fnPosSect)
2109 {
2110 SwCrsrSaveState aSave( *this );
2111 return (*fnWhichSect)( *this, fnPosSect ) &&
2112 !IsInProtectTable( sal_True ) &&
2113 !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2114 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
2115 }
2116
2117 /*
2118 sal_Bool MoveTable( SwWhichTable, SwPosTable );
2119 sal_Bool MoveColumn( SwWhichColumn, SwPosColumn );
2120 sal_Bool MoveRegion( SwWhichRegion, SwPosRegion );
2121 */
2122
RestoreSavePos()2123 void SwCursor::RestoreSavePos() // Point auf die SavePos setzen
2124 {
2125 if( pSavePos )
2126 {
2127 GetPoint()->nNode = pSavePos->nNode;
2128 GetPoint()->nContent.Assign( GetCntntNode(), pSavePos->nCntnt );
2129 }
2130 }
2131
2132
2133 /* */
2134
SwTableCursor(const SwPosition & rPos,SwPaM * pRing)2135 SwTableCursor::SwTableCursor( const SwPosition &rPos, SwPaM* pRing )
2136 : SwCursor( rPos, pRing, false )
2137 {
2138 bParked = sal_False;
2139 bChg = sal_False;
2140 nTblPtNd = 0, nTblMkNd = 0;
2141 nTblPtCnt = 0, nTblMkCnt = 0;
2142 }
2143
~SwTableCursor()2144 SwTableCursor::~SwTableCursor() {}
2145
2146
lcl_SeekEntry(const SwSelBoxes & rTmp,const SwStartNode * pSrch,sal_uInt16 & rFndPos)2147 sal_Bool lcl_SeekEntry( const SwSelBoxes& rTmp, const SwStartNode* pSrch, sal_uInt16& rFndPos )
2148 {
2149 sal_uLong nIdx = pSrch->GetIndex();
2150
2151 sal_uInt16 nO = rTmp.Count(), nM, nU = 0;
2152 if( nO > 0 )
2153 {
2154 nO--;
2155 while( nU <= nO )
2156 {
2157 nM = nU + ( nO - nU ) / 2;
2158 if( rTmp[ nM ]->GetSttNd() == pSrch )
2159 {
2160 rFndPos = nM;
2161 return sal_True;
2162 }
2163 else if( rTmp[ nM ]->GetSttIdx() < nIdx )
2164 nU = nM + 1;
2165 else if( nM == 0 )
2166 return sal_False;
2167 else
2168 nO = nM - 1;
2169 }
2170 }
2171 return sal_False;
2172 }
2173
2174
MakeBoxSels(SwCursor * pAktCrsr)2175 SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pAktCrsr )
2176 {
2177 if( bChg ) // ???
2178 {
2179 if( bParked )
2180 {
2181 // wieder in den Inhalt schieben
2182 Exchange();
2183 Move( fnMoveForward );
2184 Exchange();
2185 Move( fnMoveForward );
2186 bParked = sal_False;
2187 }
2188
2189 bChg = sal_False;
2190
2191 // temp Kopie anlegen, damit alle Boxen, fuer die schon Cursor
2192 // existieren, entfernt werden koennen.
2193 SwSelBoxes aTmp;
2194 aTmp.Insert( &aSelBoxes );
2195
2196 //Jetzt die Alten und die neuen abgleichen.
2197 SwNodes& rNds = pAktCrsr->GetDoc()->GetNodes();
2198 sal_uInt16 nPos;
2199 const SwStartNode* pSttNd;
2200 SwPaM* pCur = pAktCrsr;
2201 do {
2202 sal_Bool bDel = sal_False;
2203 pSttNd = pCur->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
2204 if( !pCur->HasMark() || !pSttNd ||
2205 pSttNd != pCur->GetMark()->nNode.GetNode().FindTableBoxStartNode() )
2206 bDel = sal_True;
2207
2208 else if( lcl_SeekEntry( aTmp, pSttNd, nPos ))
2209 {
2210 SwNodeIndex aIdx( *pSttNd, 1 );
2211 const SwNode* pNd = &aIdx.GetNode();
2212 if( !pNd->IsCntntNode() )
2213 pNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
2214
2215 SwPosition* pPos = pCur->GetMark();
2216 if( pNd != &pPos->nNode.GetNode() )
2217 pPos->nNode = *pNd;
2218 pPos->nContent.Assign( (SwCntntNode*)pNd, 0 );
2219
2220 aIdx.Assign( *pSttNd->EndOfSectionNode(), - 1 );
2221 if( !( pNd = &aIdx.GetNode())->IsCntntNode() )
2222 pNd = rNds.GoPrevSection( &aIdx, sal_True, sal_False );
2223
2224 pPos = pCur->GetPoint();
2225 if( pNd != &pPos->nNode.GetNode() )
2226 pPos->nNode = *pNd;
2227 pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() );
2228
2229 aTmp.Remove( nPos );
2230 }
2231 else
2232 bDel = sal_True;
2233
2234 pCur = (SwPaM*)pCur->GetNext();
2235 if( bDel )
2236 {
2237 SwPaM* pDel = (SwPaM*)pCur->GetPrev();
2238 /*
2239 JP 20.07.98: der alte Code geht mit dem UNO-TableCrsr nicht
2240 if( pDel == pAktCrsr )
2241 {
2242 if( pAktCrsr->GetNext() == pAktCrsr )
2243 {
2244 pAktCrsr->DeleteMark();
2245 break; // es gibt nichts mehr zu loeschen!
2246 }
2247 pAktCrsr = (SwCursor*)pDel->GetPrev();
2248 }
2249 delete pDel;
2250 */
2251
2252 if( pDel == pAktCrsr )
2253 pAktCrsr->DeleteMark();
2254 else
2255 delete pDel;
2256 }
2257 } while ( pAktCrsr != pCur );
2258
2259 for( nPos = 0; nPos < aTmp.Count(); ++nPos )
2260 {
2261 pSttNd = aTmp[ nPos ]->GetSttNd();
2262
2263 SwNodeIndex aIdx( *pSttNd, 1 );
2264 if( &aIdx.GetNodes() != &rNds )
2265 break;
2266 const SwNode* pNd = &aIdx.GetNode();
2267 if( !pNd->IsCntntNode() )
2268 pNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
2269
2270 SwPaM* pNew;
2271 if( pAktCrsr->GetNext() == pAktCrsr && !pAktCrsr->HasMark() )
2272 {
2273 pNew = pAktCrsr;
2274 pNew->GetPoint()->nNode = *pNd;
2275 pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
2276 }
2277 else
2278 {
2279 pNew = pAktCrsr->Create( pAktCrsr );
2280 pNew->GetPoint()->nNode = *pNd;
2281 pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
2282 }
2283 pNew->SetMark();
2284
2285 SwPosition* pPos = pNew->GetPoint();
2286 pPos->nNode.Assign( *pSttNd->EndOfSectionNode(), - 1 );
2287 if( !( pNd = &pPos->nNode.GetNode())->IsCntntNode() )
2288 pNd = rNds.GoPrevSection( &pPos->nNode, sal_True, sal_False );
2289
2290 pPos->nContent.Assign( (SwCntntNode*)pNd, ((SwCntntNode*)pNd)->Len() );
2291 }
2292 }
2293 return pAktCrsr;
2294 }
2295
2296
InsertBox(const SwTableBox & rTblBox)2297 void SwTableCursor::InsertBox( const SwTableBox& rTblBox )
2298 {
2299 SwTableBox* pBox = (SwTableBox*)&rTblBox;
2300 aSelBoxes.Insert( pBox );
2301 bChg = sal_True;
2302 }
2303
NewTableSelection()2304 bool SwTableCursor::NewTableSelection()
2305 {
2306 bool bRet = false;
2307 const SwNode *pStart = GetCntntNode()->FindTableBoxStartNode();
2308 const SwNode *pEnd = GetCntntNode(sal_False)->FindTableBoxStartNode();
2309 if( pStart && pEnd )
2310 {
2311 const SwTableNode *pTableNode = pStart->FindTableNode();
2312 if( pTableNode == pEnd->FindTableNode() &&
2313 pTableNode->GetTable().IsNewModel() )
2314 {
2315 bRet = true;
2316 SwSelBoxes aNew;
2317 aNew.Insert( &aSelBoxes );
2318 pTableNode->GetTable().CreateSelection( pStart, pEnd, aNew,
2319 SwTable::SEARCH_NONE, false );
2320 ActualizeSelection( aNew );
2321 }
2322 }
2323 return bRet;
2324 }
2325
ActualizeSelection(const SwSelBoxes & rNew)2326 void SwTableCursor::ActualizeSelection( const SwSelBoxes &rNew )
2327 {
2328 sal_uInt16 nOld = 0, nNew = 0;
2329 while ( nOld < aSelBoxes.Count() && nNew < rNew.Count() )
2330 {
2331 const SwTableBox* pPOld = *( aSelBoxes.GetData() + nOld );
2332 const SwTableBox* pPNew = *( rNew.GetData() + nNew );
2333 if( pPOld == pPNew )
2334 { // this box will stay
2335 ++nOld;
2336 ++nNew;
2337 }
2338 else if( pPOld->GetSttIdx() < pPNew->GetSttIdx() )
2339 DeleteBox( nOld ); // this box has to go
2340 else
2341 {
2342 InsertBox( *pPNew ); // this is a new one
2343 ++nOld;
2344 ++nNew;
2345 }
2346 }
2347
2348 while( nOld < aSelBoxes.Count() )
2349 DeleteBox( nOld ); // some more to delete
2350
2351 for( ; nNew < rNew.Count(); ++nNew ) // some more to insert
2352 InsertBox( **( rNew.GetData() + nNew ) );
2353 }
2354
IsCrsrMovedUpdt()2355 sal_Bool SwTableCursor::IsCrsrMovedUpdt()
2356 {
2357 if( !IsCrsrMoved() )
2358 return sal_False;
2359
2360 nTblMkNd = GetMark()->nNode.GetIndex();
2361 nTblPtNd = GetPoint()->nNode.GetIndex();
2362 nTblMkCnt = GetMark()->nContent.GetIndex();
2363 nTblPtCnt = GetPoint()->nContent.GetIndex();
2364 return sal_True;
2365 }
2366
2367
2368 // Parke den Tabellen-Cursor auf dem StartNode der Boxen.
ParkCrsr()2369 void SwTableCursor::ParkCrsr()
2370 {
2371 // Index aus dem TextNode abmelden
2372 SwNode* pNd = &GetPoint()->nNode.GetNode();
2373 if( !pNd->IsStartNode() )
2374 pNd = pNd->StartOfSectionNode();
2375 GetPoint()->nNode = *pNd;
2376 GetPoint()->nContent.Assign( 0, 0 );
2377
2378 pNd = &GetMark()->nNode.GetNode();
2379 if( !pNd->IsStartNode() )
2380 pNd = pNd->StartOfSectionNode();
2381 GetMark()->nNode = *pNd;
2382 GetMark()->nContent.Assign( 0, 0 );
2383
2384 bChg = sal_True;
2385 bParked = sal_True;
2386 }
2387
2388
HasReadOnlyBoxSel() const2389 sal_Bool SwTableCursor::HasReadOnlyBoxSel() const
2390 {
2391 sal_Bool bRet = sal_False;
2392 for( sal_uInt16 n = aSelBoxes.Count(); n; )
2393 if( aSelBoxes[ --n ]->GetFrmFmt()->GetProtect().IsCntntProtected() )
2394 {
2395 bRet = sal_True;
2396 break;
2397 }
2398 return bRet;
2399 }
2400
2401
2402