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