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