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