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