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