xref: /aoo4110/main/sw/source/core/crsr/swcrsr.cxx (revision b1cdbd2c)
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