Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <hintids.hxx>
30 : : #include <hints.hxx>
31 : : #include <tools/bigint.hxx>
32 : : #include <editeng/opaqitem.hxx>
33 : : #include <editeng/protitem.hxx>
34 : : #include <vcl/settings.hxx>
35 : : #include <vcl/outdev.hxx>
36 : : #include <fmtpdsc.hxx>
37 : : #include <fmtsrnd.hxx>
38 : : #include <pagedesc.hxx>
39 : : #include <pagefrm.hxx>
40 : : #include <rootfrm.hxx>
41 : : #include <cntfrm.hxx>
42 : : #include <ftnfrm.hxx>
43 : : #include <flyfrm.hxx>
44 : : #include <tabfrm.hxx>
45 : : #include <rowfrm.hxx>
46 : : #include <cellfrm.hxx>
47 : : #include <txtfrm.hxx>
48 : : #include <viewsh.hxx>
49 : : #include <viewopt.hxx>
50 : : #include <doc.hxx>
51 : : #include <viscrs.hxx>
52 : : #include <frmfmt.hxx>
53 : : #include <swtable.hxx>
54 : : #include <dflyobj.hxx>
55 : : #include <crstate.hxx>
56 : : #include <frmtool.hxx>
57 : : #include <ndtxt.hxx>
58 : : #include <dcontact.hxx>
59 : : // OD 2004-05-24 #i28701#
60 : : #include <sortedobjs.hxx>
61 : :
62 : : // FLT_MAX
63 : : #include <cfloat>
64 : : #include <swselectionlist.hxx>
65 : :
66 : : namespace {
67 : 0 : bool lcl_GetCrsrOfst_Objects( const SwPageFrm* pPageFrm, bool bSearchBackground,
68 : : SwPosition *pPos, Point& rPoint, SwCrsrMoveState* pCMS, long& rSurface )
69 : : {
70 : 0 : bool bRet = false;
71 : 0 : Point aPoint( rPoint );
72 [ # # ]: 0 : SwOrderIter aIter( pPageFrm );
73 [ # # ]: 0 : aIter.Top();
74 [ # # ]: 0 : while ( aIter() )
75 : : {
76 : : const SwVirtFlyDrawObj* pObj =
77 : 0 : static_cast<const SwVirtFlyDrawObj*>(aIter());
78 [ # # ][ # # ]: 0 : const SwAnchoredObject* pAnchoredObj = GetUserCall( aIter() )->GetAnchoredObj( aIter() );
79 [ # # ][ # # ]: 0 : const SwFmtSurround& rSurround = pAnchoredObj->GetFrmFmt().GetSurround();
80 [ # # ][ # # ]: 0 : const SvxOpaqueItem& rOpaque = pAnchoredObj->GetFrmFmt().GetOpaque();
81 [ # # ][ # # ]: 0 : bool bInBackground = ( rSurround.GetSurround() == SURROUND_THROUGHT ) && !rOpaque.GetValue();
82 : :
83 : : bool bBackgroundMatches = ( bInBackground && bSearchBackground ) ||
84 [ # # ][ # # ]: 0 : ( !bInBackground && !bSearchBackground );
[ # # ][ # # ]
85 : :
86 [ # # ]: 0 : const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
87 [ # # ][ # # ]: 0 : if ( pFly && bBackgroundMatches &&
[ # # ][ # # ]
[ # # ][ # # ]
88 : : ( ( pCMS ? pCMS->bSetInReadOnly : false ) ||
89 [ # # ][ # # ]: 0 : !pFly->IsProtected() ) &&
90 [ # # ]: 0 : pFly->GetCrsrOfst( pPos, aPoint, pCMS ) )
91 : : {
92 : 0 : rSurface = pFly->Frm().Width() * pFly->Frm().Height();
93 : 0 : bRet = true;
94 : 0 : break;
95 : : }
96 : :
97 [ # # ][ # # ]: 0 : if ( pCMS && pCMS->bStop )
98 : 0 : return false;
99 [ # # ]: 0 : aIter.Prev();
100 : : }
101 : 0 : return bRet;
102 : : }
103 : :
104 : 216 : long lcl_GetSurface( SwPosition* pPos )
105 : : {
106 : 216 : SwRect aArea;
107 : :
108 : 216 : SwNode& rNode = pPos->nNode.GetNode();
109 : :
110 [ + - ]: 216 : if ( rNode.IsCntntNode() )
111 [ + - ]: 216 : aArea = rNode.GetCntntNode()->FindLayoutRect();
112 : :
113 : : // FIXME Handle the other kinds of nodes?
114 : :
115 : 216 : return aArea.Height() * aArea.Width();
116 : : }
117 : : }
118 : :
119 : :
120 : : //Fuer SwFlyFrm::GetCrsrOfst
121 : : class SwCrsrOszControl
122 : : {
123 : : public:
124 : : // damit schon der Compiler die Klasse initialisieren kann, keinen
125 : : // DTOR und member als publics:
126 : : const SwFlyFrm *pEntry;
127 : : const SwFlyFrm *pStk1;
128 : : const SwFlyFrm *pStk2;
129 : :
130 : : //public:
131 : : // SwCrsrOszControl() : pStk1( 0 ), pStk2( 0 ) {}; // ; <- ????
132 : :
133 : 0 : sal_Bool ChkOsz( const SwFlyFrm *pFly )
134 : : {
135 : 0 : sal_Bool bRet = sal_True;
136 [ # # ][ # # ]: 0 : if ( pFly != pStk1 && pFly != pStk2 )
137 : : {
138 : 0 : pStk1 = pStk2;
139 : 0 : pStk2 = pFly;
140 : 0 : bRet = sal_False;
141 : : }
142 : 0 : return bRet;
143 : : }
144 : 0 : void Entry( const SwFlyFrm *pFly )
145 : : {
146 [ # # ]: 0 : if ( !pEntry )
147 : 0 : pEntry = pStk1 = pFly;
148 : 0 : }
149 : 0 : void Exit( const SwFlyFrm *pFly )
150 : : {
151 [ # # ]: 0 : if ( pFly == pEntry )
152 : 0 : pEntry = pStk1 = pStk2 = 0;
153 : 0 : }
154 : : };
155 : :
156 : : static SwCrsrOszControl aOszCtrl = { 0, 0, 0 };
157 : :
158 : : /*************************************************************************
159 : : |*
160 : : |* SwLayoutFrm::GetCrsrOfst()
161 : : |*
162 : : |* Beschreibung: Sucht denjenigen CntntFrm, innerhalb dessen
163 : : |* PrtArea der Point liegt.
164 : : |*
165 : : |*************************************************************************/
166 : 950 : sal_Bool SwLayoutFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
167 : : SwCrsrMoveState* pCMS ) const
168 : : {
169 : 950 : sal_Bool bRet = sal_False;
170 : 950 : const SwFrm *pFrm = Lower();
171 [ + + ][ + + ]: 1900 : while ( !bRet && pFrm )
[ + + ]
172 : : {
173 [ + - ]: 950 : pFrm->Calc();
174 : :
175 : : // #i43742# New function
176 [ + + ][ + - ]: 950 : const bool bCntntCheck = pFrm->IsTxtFrm() && pCMS && pCMS->bCntntCheck;
[ - + ]
177 : : const SwRect aPaintRect( bCntntCheck ?
178 : : pFrm->UnionFrm() :
179 [ - + ][ # # ]: 950 : pFrm->PaintArea() );
[ + - ]
180 : :
181 [ + - ][ + + ]: 1644 : if ( aPaintRect.IsInside( rPoint ) &&
[ + - ][ + + ]
[ + + ]
182 [ + - ]: 694 : ( bCntntCheck || pFrm->GetCrsrOfst( pPos, rPoint, pCMS ) ) )
183 : 432 : bRet = sal_True;
184 : : else
185 : 518 : pFrm = pFrm->GetNext();
186 [ + - ][ - + ]: 950 : if ( pCMS && pCMS->bStop )
187 : 950 : return sal_False;
188 : : }
189 : 950 : return bRet;
190 : : }
191 : :
192 : : /*************************************************************************
193 : : |*
194 : : |* SwPageFrm::GetCrsrOfst()
195 : : |*
196 : : |* Beschreibung: Sucht die Seite, innerhalb der der gesuchte Point
197 : : |* liegt.
198 : : |*
199 : : |*************************************************************************/
200 : :
201 : 478 : sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
202 : : SwCrsrMoveState* pCMS ) const
203 : : {
204 : 478 : sal_Bool bRet = sal_False;
205 : 478 : Point aPoint( rPoint );
206 : :
207 : : // check, if we have to adjust the point
208 [ + - ][ + + ]: 478 : if ( !Frm().IsInside( aPoint ) )
209 : : {
210 : 2 : aPoint.X() = Max( aPoint.X(), Frm().Left() );
211 : 2 : aPoint.X() = Min( aPoint.X(), Frm().Right() );
212 : 2 : aPoint.Y() = Max( aPoint.Y(), Frm().Top() );
213 : 2 : aPoint.Y() = Min( aPoint.Y(), Frm().Bottom() );
214 : : }
215 : :
216 : 478 : sal_Bool bTextRet, bBackRet = sal_False;
217 : :
218 : : //Koennte ein Freifliegender gemeint sein?
219 : : //Wenn sein Inhalt geschuetzt werden soll, so ist nix mit Crsr
220 : : //hineinsetzen, dadurch sollten alle Aenderungen unmoeglich sein.
221 [ - + ]: 478 : if ( GetSortedObjs() )
222 : : {
223 : 0 : long nObjSurface = 0; // Unused
224 [ # # ]: 0 : bRet = lcl_GetCrsrOfst_Objects( this, false, pPos, rPoint, pCMS, nObjSurface );
225 : : }
226 : :
227 [ + - ]: 478 : if ( !bRet )
228 : : {
229 : 478 : long nTextSurface = 0;
230 : 478 : long nBackSurface = 0;
231 [ + - ]: 478 : SwPosition aBackPos( *pPos );
232 [ + - ]: 478 : SwPosition aTextPos( *pPos );
233 : :
234 : : //Wenn kein Cntnt unterhalb der Seite 'antwortet', so korrigieren
235 : : //wir den StartPoint und fangen nochmal eine Seite vor der
236 : : //aktuellen an. Mit Flys ist es dann allerdings vorbei.
237 [ + - ][ + + ]: 478 : if ( SwLayoutFrm::GetCrsrOfst( &aTextPos, aPoint, pCMS ) )
238 : : {
239 [ + - ]: 216 : nTextSurface = lcl_GetSurface( &aTextPos );
240 : 216 : bTextRet = sal_True;
241 : : }
242 : : else
243 : : {
244 [ + - ][ + - ]: 262 : if ( pCMS && (pCMS->bStop || pCMS->bExactOnly) )
[ - + ]
245 : : {
246 : 0 : ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
247 : 0 : return sal_False;
248 : : }
249 [ + - ]: 262 : const SwCntntFrm *pCnt = GetCntntPos( aPoint, sal_False, sal_False, sal_False, pCMS, sal_False );
250 [ + - ][ - + ]: 262 : if ( pCMS && pCMS->bStop )
251 : 0 : return sal_False;
252 : :
253 : 262 : nTextSurface = pCnt->Frm().Height() * pCnt->Frm().Width();
254 : :
255 : : OSL_ENSURE( pCnt, "Crsr is gone to a Black hole" );
256 [ - + ][ # # ]: 262 : if( pCMS && pCMS->pFill && pCnt->IsTxtFrm() )
[ - + ][ + - ]
257 [ # # ]: 0 : bTextRet = pCnt->GetCrsrOfst( &aTextPos, rPoint, pCMS );
258 : : else
259 [ + - ]: 262 : bTextRet = pCnt->GetCrsrOfst( &aTextPos, aPoint, pCMS );
260 : :
261 [ + + ]: 262 : if ( !bTextRet )
262 : : {
263 : : // Set point to pCnt, delete mark
264 : : // this may happen, if pCnt is hidden
265 [ + - ][ + - ]: 20 : aTextPos = SwPosition( *pCnt->GetNode(), SwIndex( (SwTxtNode*)pCnt->GetNode(), 0 ) );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
266 : 20 : bTextRet = sal_True;
267 : : }
268 : : }
269 : :
270 : : // Check objects in the background if nothing else matched
271 [ - + ]: 478 : if ( GetSortedObjs() )
272 : : {
273 [ # # ]: 0 : bBackRet = lcl_GetCrsrOfst_Objects( this, true, &aBackPos, rPoint, pCMS, nBackSurface );
274 : : }
275 : :
276 : : // TODO Pick up the best approaching selection
277 [ + - ][ - + ]: 478 : if ( bTextRet && bBackRet && ( nTextSurface > nBackSurface ) )
[ # # ]
278 : : {
279 : 0 : bRet = bBackRet;
280 [ # # ]: 0 : pPos->nNode = aBackPos.nNode;
281 [ # # ]: 0 : pPos->nContent = aBackPos.nContent;
282 : : }
283 : : else
284 : : {
285 : 478 : bRet = bTextRet;
286 [ + - ]: 478 : pPos->nNode = aTextPos.nNode;
287 [ + - ]: 478 : pPos->nContent = aTextPos.nContent;
288 [ + - ][ - + ]: 478 : }
[ + - ][ + - ]
289 : : }
290 : :
291 [ + - ]: 478 : if ( bRet )
292 : 478 : rPoint = aPoint;
293 : :
294 : 478 : return bRet;
295 : : }
296 : :
297 : 0 : bool SwLayoutFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
298 : : {
299 : 0 : bool bRet = false;
300 [ # # ][ # # ]: 0 : if( rRect.IsOver(PaintArea()) )
301 : : {
302 : 0 : const SwFrm* pFrm = Lower();
303 [ # # ]: 0 : while( pFrm )
304 : : {
305 : 0 : pFrm->FillSelection( rList, rRect );
306 : 0 : pFrm = pFrm->GetNext();
307 : : }
308 : : }
309 : 0 : return bRet;
310 : : }
311 : :
312 : 0 : bool SwPageFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
313 : : {
314 : 0 : bool bRet = false;
315 [ # # ][ # # ]: 0 : if( rRect.IsOver(PaintArea()) )
316 : : {
317 : 0 : bRet = SwLayoutFrm::FillSelection( rList, rRect );
318 [ # # ]: 0 : if( GetSortedObjs() )
319 : : {
320 : 0 : const SwSortedObjs &rObjs = *GetSortedObjs();
321 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
322 : : {
323 : 0 : const SwAnchoredObject* pAnchoredObj = rObjs[i];
324 [ # # ]: 0 : if( !pAnchoredObj->ISA(SwFlyFrm) )
325 : 0 : continue;
326 [ # # ]: 0 : const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
327 [ # # ]: 0 : if( pFly->FillSelection( rList, rRect ) )
328 : 0 : bRet = true;
329 : : }
330 : : }
331 : : }
332 : 0 : return bRet;
333 : : }
334 : :
335 : 0 : bool SwRootFrm::FillSelection( SwSelectionList& aSelList, const SwRect& rRect) const
336 : : {
337 : 0 : const SwFrm *pPage = Lower();
338 : 0 : const long nBottom = rRect.Bottom();
339 [ # # ]: 0 : while( pPage )
340 : : {
341 [ # # ]: 0 : if( pPage->Frm().Top() < nBottom )
342 : : {
343 [ # # ]: 0 : if( pPage->Frm().Bottom() > rRect.Top() )
344 : 0 : pPage->FillSelection( aSelList, rRect );
345 : 0 : pPage = pPage->GetNext();
346 : : }
347 : : else
348 : 0 : pPage = 0;
349 : : }
350 : 0 : return !aSelList.isEmpty();
351 : : }
352 : :
353 : : /*************************************************************************
354 : : |*
355 : : |* SwRootFrm::GetCrsrOfst()
356 : : |*
357 : : |* Beschreibung: Reicht Primaer den Aufruf an die erste Seite weiter.
358 : : |* Wenn der 'reingereichte Point veraendert wird,
359 : : |* so wird sal_False zurueckgegeben.
360 : : |*
361 : : |*************************************************************************/
362 : 478 : sal_Bool SwRootFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
363 : : SwCrsrMoveState* pCMS ) const
364 : : {
365 : 478 : sal_Bool bOldAction = IsCallbackActionEnabled();
366 : 478 : ((SwRootFrm*)this)->SetCallbackActionEnabled( sal_False );
367 : : OSL_ENSURE( (Lower() && Lower()->IsPageFrm()), "Keinen PageFrm gefunden." );
368 [ - + ][ + - ]: 478 : if( pCMS && pCMS->pFill )
369 : 0 : ((SwCrsrMoveState*)pCMS)->bFillRet = sal_False;
370 : 478 : Point aOldPoint = rPoint;
371 : :
372 : : // PAGES01
373 : : // search for page containing rPoint. The borders around the pages are considerd
374 [ + - ]: 478 : const SwPageFrm* pPage = GetPageAtPos( rPoint, 0, true );
375 : :
376 : : // #i95626#
377 : : // special handling for <rPoint> beyond root frames area
378 [ - + # # : 478 : if ( !pPage &&
# # ][ - + ]
379 : 0 : rPoint.X() > Frm().Right() &&
380 : 0 : rPoint.Y() > Frm().Bottom() )
381 : : {
382 [ # # ]: 0 : pPage = dynamic_cast<const SwPageFrm*>(Lower());
383 [ # # ][ # # ]: 0 : while ( pPage && pPage->GetNext() )
[ # # ]
384 : : {
385 [ # # ]: 0 : pPage = dynamic_cast<const SwPageFrm*>(pPage->GetNext());
386 : : }
387 : : }
388 [ + - ]: 478 : if ( pPage )
389 : : {
390 [ + - ]: 478 : pPage->SwPageFrm::GetCrsrOfst( pPos, rPoint, pCMS );
391 : : }
392 : :
393 : 478 : ((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
394 [ + - ]: 478 : if( pCMS )
395 : : {
396 [ - + ]: 478 : if( pCMS->bStop )
397 : 0 : return sal_False;
398 [ - + ]: 478 : if( pCMS->pFill )
399 : 0 : return pCMS->bFillRet;
400 : : }
401 : 478 : return aOldPoint == rPoint;
402 : : }
403 : :
404 : : /*************************************************************************
405 : : |*
406 : : |* SwCellFrm::GetCrsrOfst()
407 : : |*
408 : : |* Beschreibung Wenn es sich um eine Cntnt-tragende Cell handelt wird
409 : : |* der Crsr notfalls mit Gewalt in einen der CntntFrms
410 : : |* gesetzt.
411 : : |* In geschuetzte Zellen gibt es hier keinen Eingang.
412 : : |*
413 : : |*************************************************************************/
414 : 0 : sal_Bool SwCellFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
415 : : SwCrsrMoveState* pCMS ) const
416 : : {
417 : : // cell frame does not necessarily have a lower (split table cell)
418 [ # # ]: 0 : if ( !Lower() )
419 : 0 : return sal_False;
420 : :
421 [ # # ]: 0 : if ( !(pCMS?pCMS->bSetInReadOnly:sal_False) &&
[ # # # # ]
[ # # ]
422 : 0 : GetFmt()->GetProtect().IsCntntProtected() )
423 : 0 : return sal_False;
424 : :
425 [ # # ][ # # ]: 0 : if ( pCMS && pCMS->eState == MV_TBLSEL )
426 : : {
427 : 0 : const SwTabFrm *pTab = FindTabFrm();
428 [ # # ][ # # ]: 0 : if ( pTab->IsFollow() && pTab->IsInHeadline( *this ) )
[ # # ]
429 : : {
430 : 0 : ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
431 : 0 : return sal_False;
432 : : }
433 : : }
434 : :
435 [ # # ]: 0 : if ( Lower() )
436 : : {
437 [ # # ]: 0 : if ( Lower()->IsLayoutFrm() )
438 : 0 : return SwLayoutFrm::GetCrsrOfst( pPos, rPoint, pCMS );
439 : : else
440 : : {
441 : 0 : Calc();
442 : 0 : sal_Bool bRet = sal_False;
443 : :
444 : 0 : const SwFrm *pFrm = Lower();
445 [ # # ][ # # ]: 0 : while ( pFrm && !bRet )
[ # # ]
446 : : {
447 : 0 : pFrm->Calc();
448 [ # # ]: 0 : if ( pFrm->Frm().IsInside( rPoint ) )
449 : : {
450 : 0 : bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
451 [ # # ][ # # ]: 0 : if ( pCMS && pCMS->bStop )
452 : 0 : return sal_False;
453 : : }
454 : 0 : pFrm = pFrm->GetNext();
455 : : }
456 [ # # ]: 0 : if ( !bRet )
457 : : {
458 [ # # ][ # # ]: 0 : Point *pPoint = pCMS && pCMS->pFill ? new Point( rPoint ) : NULL;
459 : 0 : const SwCntntFrm *pCnt = GetCntntPos( rPoint, sal_True );
460 [ # # ][ # # ]: 0 : if( pPoint && pCnt->IsTxtFrm() )
[ # # ]
461 : : {
462 : 0 : pCnt->GetCrsrOfst( pPos, *pPoint, pCMS );
463 : 0 : rPoint = *pPoint;
464 : : }
465 : : else
466 : 0 : pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
467 : 0 : delete pPoint;
468 : : }
469 : 0 : return sal_True;
470 : : }
471 : : }
472 : :
473 : 0 : return sal_False;
474 : : }
475 : :
476 : : /*************************************************************************
477 : : |*
478 : : |* SwFlyFrm::GetCrsrOfst()
479 : : |*
480 : : |*************************************************************************/
481 : : //Problem: Wenn zwei Flys genau gleich gross sind und auf derselben
482 : : //Position stehen, so liegt jeder innerhalb des anderen.
483 : : //Da jeweils geprueft wird, ob der Point nicht zufaellig innerhalb eines
484 : : //anderen Flys liegt, der sich vollstaendig innerhalb des aktuellen befindet
485 : : //und ggf. ein rekursiver Aufruf erfolgt wuerde o.g. Situation zu einer
486 : : //endlosen Rekursion fuehren.
487 : : //Mit der Hilfsklasse SwCrsrOszControl unterbinden wir die Rekursion. Das
488 : : //GetCrsrOfst entscheidet sich bei einer Rekursion fuer denjenigen der
489 : : //am weitesten oben liegt.
490 : :
491 : 0 : sal_Bool SwFlyFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
492 : : SwCrsrMoveState* pCMS ) const
493 : : {
494 : 0 : aOszCtrl.Entry( this );
495 : :
496 : : //Wenn der Point innerhalb des Fly sitzt wollen wir energisch
497 : : //versuchen den Crsr hineinzusetzen.
498 : : //Wenn der Point allerdings in einem Flys sitzt, der sich vollstaendig
499 : : //innerhalb des aktuellen befindet, so wird fuer diesen das
500 : : //GetCrsrOfst gerufen.
501 : 0 : Calc();
502 [ # # ][ # # ]: 0 : sal_Bool bInside = Frm().IsInside( rPoint ) && Lower(),
503 : 0 : bRet = sal_False;
504 : :
505 : : //Wenn der Frm eine Grafik enthaelt, aber nur Text gewuenscht ist, so
506 : : //nimmt er den Crsr grundsaetzlich nicht an.
507 [ # # ][ # # ]: 0 : if ( bInside && pCMS && pCMS->eState == MV_SETONLYTEXT &&
[ # # # #
# # ][ # # ]
508 : 0 : (!Lower() || Lower()->IsNoTxtFrm()) )
509 : 0 : bInside = sal_False;
510 : :
511 : 0 : const SwPageFrm *pPage = FindPageFrm();
512 [ # # ][ # # ]: 0 : if ( bInside && pPage && pPage->GetSortedObjs() )
[ # # ][ # # ]
513 : : {
514 [ # # ]: 0 : SwOrderIter aIter( pPage );
515 [ # # ]: 0 : aIter.Top();
516 [ # # ][ # # ]: 0 : while ( aIter() && !bRet )
[ # # ]
517 : : {
518 : 0 : const SwVirtFlyDrawObj* pObj = static_cast<const SwVirtFlyDrawObj*>(aIter());
519 [ # # ]: 0 : const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
520 [ # # ][ # # ]: 0 : if ( pFly && pFly->Frm().IsInside( rPoint ) &&
[ # # ][ # # ]
[ # # ]
521 [ # # ]: 0 : Frm().IsInside( pFly->Frm() ) )
522 : : {
523 [ # # ][ # # ]: 0 : if ( aOszCtrl.ChkOsz( pFly ) ||
[ # # ][ # # ]
524 : 0 : sal_True == (bRet = pFly->GetCrsrOfst( pPos, rPoint, pCMS )))
525 : 0 : break;
526 [ # # ][ # # ]: 0 : if ( pCMS && pCMS->bStop )
527 : 0 : return sal_False;
528 : : }
529 [ # # ]: 0 : aIter.Next();
530 : : }
531 : : }
532 : :
533 [ # # ][ # # ]: 0 : while ( bInside && !bRet )
[ # # ]
534 : : {
535 : 0 : const SwFrm *pFrm = Lower();
536 [ # # ][ # # ]: 0 : while ( pFrm && !bRet )
[ # # ]
537 : : {
538 : 0 : pFrm->Calc();
539 [ # # ]: 0 : if ( pFrm->Frm().IsInside( rPoint ) )
540 : : {
541 : 0 : bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
542 [ # # ][ # # ]: 0 : if ( pCMS && pCMS->bStop )
543 : 0 : return sal_False;
544 : : }
545 : 0 : pFrm = pFrm->GetNext();
546 : : }
547 [ # # ]: 0 : if ( !bRet )
548 : : {
549 [ # # ][ # # ]: 0 : Point *pPoint = pCMS && pCMS->pFill ? new Point( rPoint ) : NULL;
550 : : const SwCntntFrm *pCnt = GetCntntPos(
551 : 0 : rPoint, sal_True, sal_False, sal_False, pCMS );
552 [ # # ][ # # ]: 0 : if ( pCMS && pCMS->bStop )
553 : 0 : return sal_False;
554 [ # # ][ # # ]: 0 : if( pPoint && pCnt->IsTxtFrm() )
[ # # ]
555 : : {
556 : 0 : pCnt->GetCrsrOfst( pPos, *pPoint, pCMS );
557 : 0 : rPoint = *pPoint;
558 : : }
559 : : else
560 : 0 : pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
561 : 0 : delete pPoint;
562 : 0 : bRet = sal_True;
563 : : }
564 : : }
565 : 0 : aOszCtrl.Exit( this );
566 : 0 : return bRet;
567 : : }
568 : :
569 : : /*************************************************************************
570 : : |*
571 : : |* Beschreibung Layoutabhaengiges Cursortravelling
572 : : |*
573 : : |*************************************************************************/
574 : 0 : sal_Bool SwCntntFrm::LeftMargin(SwPaM *pPam) const
575 : : {
576 [ # # ][ # # ]: 0 : if( pPam->GetNode() != (SwCntntNode*)GetNode() )
577 : 0 : return sal_False;
578 : 0 : ((SwCntntNode*)GetNode())->
579 : 0 : MakeStartIndex((SwIndex *) &pPam->GetPoint()->nContent);
580 : 0 : return sal_True;
581 : : }
582 : :
583 : 0 : sal_Bool SwCntntFrm::RightMargin(SwPaM *pPam, sal_Bool) const
584 : : {
585 [ # # ][ # # ]: 0 : if( pPam->GetNode() != (SwCntntNode*)GetNode() )
586 : 0 : return sal_False;
587 : 0 : ((SwCntntNode*)GetNode())->
588 : 0 : MakeEndIndex((SwIndex *) &pPam->GetPoint()->nContent);
589 : 0 : return sal_True;
590 : : }
591 : :
592 : 4 : const SwCntntFrm *lcl_GetNxtCnt( const SwCntntFrm* pCnt )
593 : : {
594 : 4 : return pCnt->GetNextCntntFrm();
595 : : }
596 : :
597 : 8 : const SwCntntFrm *lcl_GetPrvCnt( const SwCntntFrm* pCnt )
598 : : {
599 : 8 : return pCnt->GetPrevCntntFrm();
600 : : }
601 : :
602 : : typedef const SwCntntFrm *(*GetNxtPrvCnt)( const SwCntntFrm* );
603 : :
604 : : //Frame in wiederholter Headline?
605 : 12 : sal_Bool lcl_IsInRepeatedHeadline( const SwFrm *pFrm,
606 : : const SwTabFrm** ppTFrm = 0 )
607 : : {
608 : 12 : const SwTabFrm *pTab = pFrm->FindTabFrm();
609 [ - + ]: 12 : if( ppTFrm )
610 : 0 : *ppTFrm = pTab;
611 [ + - ][ - + ]: 12 : return pTab && pTab->IsFollow() && pTab->IsInHeadline( *pFrm );
[ # # ]
612 : : }
613 : :
614 : :
615 : : //Ueberspringen geschuetzter Tabellenzellen. Optional auch
616 : : //Ueberspringen von wiederholten Headlines.
617 : : //MA 26. Jan. 98: Chg auch andere Geschuetzte Bereiche ueberspringen.
618 : : // FME: Skip follow flow cells
619 : 276 : const SwCntntFrm * lcl_MissProtectedFrames( const SwCntntFrm *pCnt,
620 : : GetNxtPrvCnt fnNxtPrv,
621 : : sal_Bool bMissHeadline,
622 : : sal_Bool bInReadOnly,
623 : : sal_Bool bMissFollowFlowLine )
624 : : {
625 [ + - ][ + + ]: 276 : if ( pCnt && pCnt->IsInTab() )
[ + + ]
626 : : {
627 : 12 : sal_Bool bProtect = sal_True;
628 [ + - ][ + + ]: 24 : while ( pCnt && bProtect )
[ + + ]
629 : : {
630 : 12 : const SwLayoutFrm *pCell = pCnt->GetUpper();
631 [ + - ][ - + ]: 12 : while ( pCell && !pCell->IsCellFrm() )
[ - + ]
632 : 0 : pCell = pCell->GetUpper();
633 [ + - ]: 36 : if ( !pCell ||
[ - + # # ]
[ + - + - ]
[ - + # #
+ - ][ + - ]
634 : 0 : (( ( bInReadOnly || !pCell->GetFmt()->GetProtect().IsCntntProtected() ) &&
635 : 12 : ( !bMissHeadline || !lcl_IsInRepeatedHeadline( pCell ) ) &&
636 : 0 : ( !bMissFollowFlowLine || !pCell->IsInFollowFlowRow() ) &&
637 : 12 : !pCell->IsCoveredCell()) ) )
638 : 12 : bProtect = sal_False;
639 : : else
640 : 0 : pCnt = (*fnNxtPrv)( pCnt );
641 : : }
642 : : }
643 [ + + ]: 264 : else if ( !bInReadOnly )
644 [ + - ][ - + ]: 246 : while ( pCnt && pCnt->IsProtected() )
[ - + ]
645 : 0 : pCnt = (*fnNxtPrv)( pCnt );
646 : :
647 : 276 : return pCnt;
648 : : }
649 : :
650 : 6 : sal_Bool lcl_UpDown( SwPaM *pPam, const SwCntntFrm *pStart,
651 : : GetNxtPrvCnt fnNxtPrv, sal_Bool bInReadOnly )
652 : : {
653 : : OSL_ENSURE( pPam->GetNode() == (SwCntntNode*)pStart->GetNode(),
654 : : "lcl_UpDown arbeitet nicht fuer andere." );
655 : :
656 : 6 : const SwCntntFrm *pCnt = 0;
657 : :
658 : : //Wenn gerade eine Tabellenselection laeuft muss ein bischen getricktst
659 : : //werden: Beim hochlaufen an den Anfang der Zelle gehen, beim runterlaufen
660 : : //an das Ende der Zelle gehen.
661 : 6 : sal_Bool bTblSel = false;
662 [ + - - + ]: 12 : if ( pStart->IsInTab() &&
[ - + ]
663 : 6 : pPam->GetNode( sal_True )->StartOfSectionNode() !=
664 : 6 : pPam->GetNode( sal_False )->StartOfSectionNode() )
665 : : {
666 : 0 : bTblSel = true;
667 : 0 : const SwLayoutFrm *pCell = pStart->GetUpper();
668 [ # # ]: 0 : while ( !pCell->IsCellFrm() )
669 : 0 : pCell = pCell->GetUpper();
670 : :
671 : : //
672 : : // Check, if cell has a Prev/Follow cell:
673 : : //
674 : 0 : const bool bFwd = ( fnNxtPrv == lcl_GetNxtCnt );
675 : : const SwLayoutFrm* pTmpCell = bFwd ?
676 : : ((SwCellFrm*)pCell)->GetFollowCell() :
677 [ # # ]: 0 : ((SwCellFrm*)pCell)->GetPreviousCell();
678 : :
679 : 0 : const SwCntntFrm* pTmpStart = pStart;
680 [ # # ][ # # ]: 0 : while ( pTmpCell && 0 != ( pTmpStart = pTmpCell->ContainsCntnt() ) )
[ # # ]
681 : : {
682 : 0 : pCell = pTmpCell;
683 : : pTmpCell = bFwd ?
684 : : ((SwCellFrm*)pCell)->GetFollowCell() :
685 [ # # ]: 0 : ((SwCellFrm*)pCell)->GetPreviousCell();
686 : : }
687 : 0 : const SwCntntFrm *pNxt = pCnt = pTmpStart;
688 : :
689 [ # # ]: 0 : while ( pCell->IsAnLower( pNxt ) )
690 : : {
691 : 0 : pCnt = pNxt;
692 : 0 : pNxt = (*fnNxtPrv)( pNxt );
693 : : }
694 : : }
695 : :
696 [ - + ]: 6 : pCnt = (*fnNxtPrv)( pCnt ? pCnt : pStart );
697 : 6 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
698 : :
699 : :
700 : 6 : const SwTabFrm *pStTab = pStart->FindTabFrm();
701 : 6 : const SwTabFrm *pTable = 0;
702 [ # # ][ # # ]: 6 : const sal_Bool bTab = pStTab || (pCnt && pCnt->IsInTab()) ? sal_True : sal_False;
[ - + ]
703 : 6 : sal_Bool bEnd = bTab ? sal_False : sal_True;
704 : :
705 : 6 : const SwFrm* pVertRefFrm = pStart;
706 [ - + ][ # # ]: 6 : if ( bTblSel && pStTab )
707 : 0 : pVertRefFrm = pStTab;
708 [ - + ][ # # ]: 6 : SWRECTFN( pVertRefFrm )
[ # # ][ - + ]
709 : :
710 : 6 : SwTwips nX = 0;
711 [ + - ]: 6 : if ( bTab )
712 : : {
713 : : //
714 : : // pStart or pCnt is inside a table. nX will be used for travelling:
715 : : //
716 : 6 : SwRect aRect( pStart->Frm() );
717 [ + - ]: 6 : pStart->GetCharRect( aRect, *pPam->GetPoint() );
718 [ + - ]: 6 : Point aCenter = aRect.Center();
719 [ - + ]: 6 : nX = bVert ? aCenter.Y() : aCenter.X();
720 : :
721 [ + - ][ + - ]: 6 : pTable = pCnt ? pCnt->FindTabFrm() : 0;
722 [ - + ]: 6 : if ( !pTable )
723 : 0 : pTable = pStTab;
724 : :
725 [ + - ][ + - ]: 18 : if ( pStTab &&
[ + - ][ + - ]
726 [ + - ]: 6 : !pStTab->GetUpper()->IsInTab() &&
727 [ + - ]: 6 : !pTable->GetUpper()->IsInTab() )
728 : : {
729 : 6 : const SwFrm *pCell = pStart->GetUpper();
730 [ + - ][ - + ]: 6 : while ( pCell && !pCell->IsCellFrm() )
[ - + ]
731 : 0 : pCell = pCell->GetUpper();
732 : : OSL_ENSURE( pCell, "Zelle nicht gefunden." );
733 [ + - ][ + - ]: 6 : nX = (pCell->Frm().*fnRect->fnGetLeft)() +
734 [ + - ][ + - ]: 6 : (pCell->Frm().*fnRect->fnGetWidth)() / 2;
735 : :
736 : : //Der Fluss fuehrt von einer Tabelle in die nachste. Der X-Wert
737 : : //muss ausgehend von der Mitte der Startzelle um die Verschiebung
738 : : //der Tabellen korrigiert werden.
739 [ - + ]: 6 : if ( pStTab != pTable )
740 : : {
741 [ # # ][ # # ]: 0 : nX += (pTable->Frm().*fnRect->fnGetLeft)() -
742 [ # # ][ # # ]: 0 : (pStTab->Frm().*fnRect->fnGetLeft)();
743 : : }
744 : : }
745 : :
746 : : //
747 : : // Restrict nX to the left and right borders of pTab:
748 : : // (is this really necessary?)
749 : : //
750 [ + - ][ + - ]: 6 : if ( !pTable->GetUpper()->IsInTab() )
751 : : {
752 [ + - ]: 6 : const sal_Bool bRTL = pTable->IsRightToLeft();
753 : : const long nPrtLeft = bRTL ?
754 [ # # ]: 0 : (pTable->*fnRect->fnGetPrtRight)() :
755 [ - + ][ # # ]: 6 : (pTable->*fnRect->fnGetPrtLeft)();
[ + - ][ + - ]
756 [ - + ]: 6 : if ( bRTL != (nX < nPrtLeft) )
757 : 0 : nX = nPrtLeft;
758 : : else
759 : : {
760 : : const long nPrtRight = bRTL ?
761 [ # # ]: 0 : (pTable->*fnRect->fnGetPrtLeft)() :
762 [ - + ][ # # ]: 6 : (pTable->*fnRect->fnGetPrtRight)();
[ + - ][ + - ]
763 [ - + ]: 6 : if ( bRTL != (nX > nPrtRight) )
764 : 6 : nX = nPrtRight;
765 : : }
766 : : }
767 : : }
768 : :
769 [ + + ][ + - : 24 : do
+ - - + ]
[ + + ]
770 : : {
771 : : //Wenn ich im DokumentBody bin, so will ich da auch bleiben
772 [ + - ]: 12 : if ( pStart->IsInDocBody() )
773 : : {
774 [ + - ][ + - : 36 : while ( pCnt && (!pCnt->IsInDocBody() ||
+ - - + ]
[ - + ]
775 : 24 : (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
776 : : {
777 : 0 : pCnt = (*fnNxtPrv)( pCnt );
778 : 0 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
779 : : }
780 : : }
781 : :
782 : : //Wenn ich im Fussnotenbereich bin, so versuche ich notfalls den naechsten
783 : : //Fussnotenbereich zu erreichen.
784 [ # # ]: 0 : else if ( pStart->IsInFtn() )
785 : : {
786 [ # # ][ # # : 0 : while ( pCnt && (!pCnt->IsInFtn() ||
# # # # ]
[ # # ]
787 : 0 : (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
788 : : {
789 : 0 : pCnt = (*fnNxtPrv)( pCnt );
790 : 0 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
791 : : }
792 : : }
793 : :
794 : : //In Flys kann es Blind weitergehen solange ein Cntnt
795 : : //gefunden wird.
796 [ # # ]: 0 : else if ( pStart->IsInFly() )
797 : : {
798 [ # # ][ # # ]: 0 : if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() )
[ # # ][ # # ]
799 : : {
800 : 0 : pCnt = (*fnNxtPrv)( pCnt );
801 : 0 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
802 : : }
803 : : }
804 : :
805 : : //Andernfalls weigere ich mich einfach den derzeitigen Bereich zu
806 : : //verlassen.
807 [ # # ]: 0 : else if ( pCnt )
808 : : {
809 : 0 : const SwFrm *pUp = pStart->GetUpper(); //Head/Foot
810 [ # # ][ # # ]: 0 : while ( pUp && pUp->GetUpper() && !(pUp->GetType() & 0x0018 ) )
[ # # ][ # # ]
811 : 0 : pUp = pUp->GetUpper();
812 : 0 : sal_Bool bSame = sal_False;
813 : 0 : const SwFrm *pCntUp = pCnt->GetUpper();
814 [ # # ][ # # ]: 0 : while ( pCntUp && !bSame )
[ # # ]
815 [ # # ]: 0 : { if ( pUp == pCntUp )
816 : 0 : bSame = sal_True;
817 : : else
818 : 0 : pCntUp = pCntUp->GetUpper();
819 : : }
820 [ # # ]: 0 : if ( !bSame )
821 : 0 : pCnt = 0;
822 [ # # ][ # # ]: 0 : else if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() ) // i73332
[ # # ][ # # ]
823 : : {
824 : 0 : pCnt = (*fnNxtPrv)( pCnt );
825 : 0 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
826 : : }
827 : : }
828 : :
829 [ + - ]: 12 : if ( bTab )
830 : : {
831 [ - + ]: 12 : if ( !pCnt )
832 : 0 : bEnd = sal_True;
833 : : else
834 : 12 : { const SwTabFrm *pTab = pCnt->FindTabFrm();
835 [ - + ]: 12 : if( !pTab )
836 : 0 : bEnd = sal_True;
837 : : else
838 : : {
839 [ - + ]: 12 : if ( pTab != pTable )
840 : : {
841 : : //Der Fluss fuehrt von einer Tabelle in die nachste. Der
842 : : //X-Wert muss um die Verschiebung der Tabellen korrigiert
843 : : //werden.
844 [ # # ][ # # ]: 0 : if ( pTable &&
[ # # ][ # # ]
845 [ # # ]: 0 : !pTab->GetUpper()->IsInTab() &&
846 [ # # ]: 0 : !pTable->GetUpper()->IsInTab() )
847 : 0 : nX += pTab->Frm().Left() - pTable->Frm().Left();
848 : 0 : pTable = pTab;
849 : : }
850 [ + - ]: 12 : const SwLayoutFrm *pCell = pTable ? pCnt->GetUpper() : 0;
851 [ + - ][ - + ]: 12 : while ( pCell && !pCell->IsCellFrm() )
[ - + ]
852 : 0 : pCell = pCell->GetUpper();
853 : :
854 : 12 : Point aInsideCell;
855 : 12 : Point aInsideCnt;
856 [ + - ]: 12 : if ( pCell )
857 : : {
858 [ + - ][ + - ]: 12 : long nTmpTop = (pCell->Frm().*fnRect->fnGetTop)();
859 [ - + ]: 12 : if ( bVert )
860 : : {
861 [ # # ]: 0 : if ( nTmpTop )
862 : 0 : --nTmpTop;
863 : :
864 : 0 : aInsideCell = Point( nTmpTop, nX );
865 : : }
866 : : else
867 : 12 : aInsideCell = Point( nX, nTmpTop );
868 : : }
869 : :
870 [ + - ][ + - ]: 12 : long nTmpTop = (pCnt->Frm().*fnRect->fnGetTop)();
871 [ - + ]: 12 : if ( bVert )
872 : : {
873 [ # # ]: 0 : if ( nTmpTop )
874 : 0 : --nTmpTop;
875 : :
876 : 0 : aInsideCnt = Point( nTmpTop, nX );
877 : : }
878 : : else
879 : 12 : aInsideCnt = Point( nX, nTmpTop );
880 : :
881 [ + - ][ + - ]: 12 : if ( pCell && pCell->Frm().IsInside( aInsideCell ) )
[ + + ][ + + ]
882 : : {
883 : 6 : bEnd = sal_True;
884 : : //Jetzt noch schnell den richtigen Cntnt in der Zelle
885 : : //greifen.
886 [ + - ][ - + ]: 6 : if ( !pCnt->Frm().IsInside( aInsideCnt ) )
887 : : {
888 [ # # ]: 0 : pCnt = pCell->ContainsCntnt();
889 [ # # ]: 0 : if ( fnNxtPrv == lcl_GetPrvCnt )
890 [ # # ][ # # ]: 0 : while ( pCell->IsAnLower(pCnt->GetNextCntntFrm()) )
[ # # ]
891 [ # # ]: 0 : pCnt = pCnt->GetNextCntntFrm();
892 : : }
893 : : }
894 [ + - ][ - + ]: 6 : else if ( pCnt->Frm().IsInside( aInsideCnt ) )
895 : 12 : bEnd = sal_True;
896 : : }
897 : : }
898 [ + + ]: 12 : if ( !bEnd )
899 : : {
900 : 6 : pCnt = (*fnNxtPrv)( pCnt );
901 : 6 : pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, sal_True, bInReadOnly, bTblSel );
902 : : }
903 : : }
904 : :
905 : : } while ( !bEnd ||
906 : 12 : (pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow()));
907 : :
908 [ + - ]: 6 : if( pCnt )
909 : : { // setze den Point auf den Content-Node
910 : 6 : SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
911 : 6 : pPam->GetPoint()->nNode = *pCNd;
912 [ + + ]: 6 : if ( fnNxtPrv == lcl_GetPrvCnt )
913 : 4 : pCNd->MakeEndIndex( (SwIndex*)&pPam->GetPoint()->nContent );
914 : : else
915 : 2 : pCNd->MakeStartIndex( (SwIndex*)&pPam->GetPoint()->nContent );
916 : 6 : return sal_True;
917 : : }
918 : 6 : return sal_False;
919 : : }
920 : :
921 : 4 : sal_Bool SwCntntFrm::UnitUp( SwPaM* pPam, const SwTwips, sal_Bool bInReadOnly ) const
922 : : {
923 : 4 : return ::lcl_UpDown( pPam, this, lcl_GetPrvCnt, bInReadOnly );
924 : : }
925 : :
926 : 2 : sal_Bool SwCntntFrm::UnitDown( SwPaM* pPam, const SwTwips, sal_Bool bInReadOnly ) const
927 : : {
928 : 2 : return ::lcl_UpDown( pPam, this, lcl_GetNxtCnt, bInReadOnly );
929 : : }
930 : :
931 : : /*************************************************************************
932 : : |*
933 : : |* SwRootFrm::GetCurrPage()
934 : : |*
935 : : |* Beschreibung: Liefert die Nummer der aktuellen Seite.
936 : : |* Wenn die Methode einen PaM bekommt, so ist die aktuelle Seite
937 : : |* diejenige in der der PaM sitzt. Anderfalls ist die aktuelle
938 : : |* Seite die erste Seite innerhalb der VisibleArea.
939 : : |* Es wird nur auf den vorhandenen Seiten gearbeitet!
940 : : |*
941 : : |*************************************************************************/
942 : 0 : sal_uInt16 SwRootFrm::GetCurrPage( const SwPaM *pActualCrsr ) const
943 : : {
944 : : OSL_ENSURE( pActualCrsr, "Welche Seite soll's denn sein?" );
945 : 0 : SwFrm const*const pActFrm = pActualCrsr->GetPoint()->nNode.GetNode().
946 : : GetCntntNode()->getLayoutFrm( this, 0,
947 : : pActualCrsr->GetPoint(),
948 : 0 : sal_False );
949 : 0 : return pActFrm->FindPageFrm()->GetPhyPageNum();
950 : : }
951 : :
952 : : /*************************************************************************
953 : : |*
954 : : |* SwRootFrm::SetCurrPage()
955 : : |*
956 : : |* Beschreibung: Liefert einen PaM der am Anfang der gewuenschten
957 : : |* Seite sitzt.
958 : : |* Formatiert wird soweit notwendig
959 : : |* Liefert Null, wenn die Operation nicht moeglich ist.
960 : : |* Der PaM sitzt in der letzten Seite, wenn die Seitenzahl zu gross
961 : : |* gewaehlt wurde.
962 : : |*
963 : : |*************************************************************************/
964 : 2 : sal_uInt16 SwRootFrm::SetCurrPage( SwCursor* pToSet, sal_uInt16 nPageNum )
965 : : {
966 : : OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
967 : :
968 : 2 : SwPageFrm *pPage = (SwPageFrm*)Lower();
969 : 2 : sal_Bool bEnd =sal_False;
970 [ + - ][ - + ]: 2 : while ( !bEnd && pPage->GetPhyPageNum() != nPageNum )
[ - + ]
971 [ # # ]: 0 : { if ( pPage->GetNext() )
972 : 0 : pPage = (SwPageFrm*)pPage->GetNext();
973 : : else
974 : : { //Ersten CntntFrm Suchen, und solange Formatieren bis
975 : : //eine neue Seite angefangen wird oder bis die CntntFrm's alle
976 : : //sind.
977 : 0 : const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
978 [ # # ][ # # ]: 0 : while ( pCntnt && pPage->IsAnLower( pCntnt ) )
[ # # ]
979 : : {
980 : 0 : pCntnt->Calc();
981 : 0 : pCntnt = pCntnt->GetNextCntntFrm();
982 : : }
983 : : //Jetzt ist entweder eine neue Seite da, oder die letzte Seite
984 : : //ist gefunden.
985 [ # # ]: 0 : if ( pPage->GetNext() )
986 : 0 : pPage = (SwPageFrm*)pPage->GetNext();
987 : : else
988 : 0 : bEnd = sal_True;
989 : : }
990 : : }
991 : : //pPage zeigt jetzt auf die 'gewuenschte' Seite. Jetzt muss noch der
992 : : //PaM auf den Anfang des ersten CntntFrm im Body-Text erzeugt werden.
993 : : //Wenn es sich um eine Fussnotenseite handelt, wird der PaM in die erste
994 : : //Fussnote gesetzt.
995 : 2 : const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
996 [ - + ]: 2 : if ( pPage->IsFtnPage() )
997 [ # # ][ # # ]: 0 : while ( pCntnt && !pCntnt->IsInFtn() )
[ # # ]
998 : 0 : pCntnt = pCntnt->GetNextCntntFrm();
999 : : else
1000 [ + - ][ - + ]: 2 : while ( pCntnt && !pCntnt->IsInDocBody() )
[ - + ]
1001 : 0 : pCntnt = pCntnt->GetNextCntntFrm();
1002 [ + - ]: 2 : if ( pCntnt )
1003 : : {
1004 : 2 : SwCntntNode* pCNd = (SwCntntNode*)pCntnt->GetNode();
1005 : 2 : pToSet->GetPoint()->nNode = *pCNd;
1006 : 2 : pCNd->MakeStartIndex( (SwIndex*)&pToSet->GetPoint()->nContent );
1007 : 2 : pToSet->GetPoint()->nContent = ((SwTxtFrm*)pCntnt)->GetOfst();
1008 : :
1009 [ - + ]: 2 : SwShellCrsr* pSCrsr = dynamic_cast<SwShellCrsr*>(pToSet);
1010 [ + - ]: 2 : if( pSCrsr )
1011 : : {
1012 : 2 : Point &rPt = pSCrsr->GetPtPos();
1013 : 2 : rPt = pCntnt->Frm().Pos();
1014 : 2 : rPt += pCntnt->Prt().Pos();
1015 : : }
1016 : 2 : return pPage->GetPhyPageNum();
1017 : : }
1018 : 2 : return 0;
1019 : : }
1020 : :
1021 : : /*************************************************************************
1022 : : |*
1023 : : |* SwCntntFrm::StartxxPage(), EndxxPage()
1024 : : |*
1025 : : |* Beschreibung Cursor an Anfang/Ende der aktuellen/vorherigen/
1026 : : |* naechsten Seite. Alle sechs Methoden rufen GetFrmInPage() mit der
1027 : : |* entsprechenden Parametrisierung.
1028 : : |* Zwei Parameter steuern die Richtung: einer bestimmt die Seite, der
1029 : : |* andere Anfang/Ende.
1030 : : |* Fuer die Bestimmung der Seite und des Cntnt (Anfang/Ende) werden
1031 : : |* die im folgenden definierten Funktionen benutzt.
1032 : : |*
1033 : : |*************************************************************************/
1034 : 17 : SwCntntFrm *GetFirstSub( const SwLayoutFrm *pLayout )
1035 : : {
1036 : 17 : return ((SwPageFrm*)pLayout)->FindFirstBodyCntnt();
1037 : : }
1038 : :
1039 : 4 : SwCntntFrm *GetLastSub( const SwLayoutFrm *pLayout )
1040 : : {
1041 : 4 : return ((SwPageFrm*)pLayout)->FindLastBodyCntnt();
1042 : : }
1043 : :
1044 : 2 : SwLayoutFrm *GetNextFrm( const SwLayoutFrm *pFrm )
1045 : : {
1046 : : SwLayoutFrm *pNext =
1047 : 4 : (pFrm->GetNext() && pFrm->GetNext()->IsLayoutFrm()) ?
1048 [ + - + - ]: 4 : (SwLayoutFrm*)pFrm->GetNext() : 0;
1049 : : // #i39402# in case of an empty page
1050 [ + - ][ - + ]: 2 : if(pNext && !pNext->ContainsCntnt())
[ - + ]
1051 : 0 : pNext = (pNext->GetNext() && pNext->GetNext()->IsLayoutFrm()) ?
1052 [ # # # # ]: 0 : (SwLayoutFrm*)pNext->GetNext() : 0;
1053 : 2 : return pNext;
1054 : : }
1055 : :
1056 : 17 : SwLayoutFrm *GetThisFrm( const SwLayoutFrm *pFrm )
1057 : : {
1058 : 17 : return (SwLayoutFrm*)pFrm;
1059 : : }
1060 : :
1061 : 2 : SwLayoutFrm *GetPrevFrm( const SwLayoutFrm *pFrm )
1062 : : {
1063 : : SwLayoutFrm *pPrev =
1064 : 4 : (pFrm->GetPrev() && pFrm->GetPrev()->IsLayoutFrm()) ?
1065 [ + - + - ]: 4 : (SwLayoutFrm*)pFrm->GetPrev() : 0;
1066 : : // #i39402# in case of an empty page
1067 [ + - ][ - + ]: 2 : if(pPrev && !pPrev->ContainsCntnt())
[ - + ]
1068 : 0 : pPrev = (pPrev->GetPrev() && pPrev->GetPrev()->IsLayoutFrm()) ?
1069 [ # # # # ]: 0 : (SwLayoutFrm*)pPrev->GetPrev() : 0;
1070 : 2 : return pPrev;
1071 : : }
1072 : :
1073 : : //Jetzt koennen auch die Funktionspointer initalisiert werden;
1074 : : //sie sind in cshtyp.hxx declariert.
1075 : : SwPosPage fnPageStart = GetFirstSub;
1076 : : SwPosPage fnPageEnd = GetLastSub;
1077 : : SwWhichPage fnPagePrev = GetPrevFrm;
1078 : : SwWhichPage fnPageCurr = GetThisFrm;
1079 : : SwWhichPage fnPageNext = GetNextFrm;
1080 : :
1081 : : //Liefert den ersten/den letzten Contentframe (gesteuert ueber
1082 : : //den Parameter fnPosPage) in der
1083 : : //aktuellen/vorhergehenden/folgenden Seite (gesteuert durch den
1084 : : //Parameter fnWhichPage).
1085 : 21 : sal_Bool GetFrmInPage( const SwCntntFrm *pCnt, SwWhichPage fnWhichPage,
1086 : : SwPosPage fnPosPage, SwPaM *pPam )
1087 : : {
1088 : : //Erstmal die gewuenschte Seite besorgen, anfangs die aktuelle, dann
1089 : : //die die per fnWichPage gewuenscht wurde
1090 : 21 : const SwLayoutFrm *pLayoutFrm = pCnt->FindPageFrm();
1091 [ - + ][ - + ]: 21 : if ( !pLayoutFrm || (0 == (pLayoutFrm = (*fnWhichPage)(pLayoutFrm))) )
[ + - ]
1092 : 0 : return sal_False;
1093 : :
1094 : : //Jetzt den gewuenschen CntntFrm unterhalb der Seite
1095 [ - + ]: 21 : if( 0 == (pCnt = (*fnPosPage)(pLayoutFrm)) )
1096 : 0 : return sal_False;
1097 : : else
1098 : : {
1099 : : // repeated headlines in tables
1100 [ - + ][ # # ]: 21 : if ( pCnt->IsInTab() && fnPosPage == GetFirstSub )
[ - + ]
1101 : : {
1102 : 0 : const SwTabFrm* pTab = pCnt->FindTabFrm();
1103 [ # # ]: 0 : if ( pTab->IsFollow() )
1104 : : {
1105 [ # # ]: 0 : if ( pTab->IsInHeadline( *pCnt ) )
1106 : : {
1107 : 0 : SwLayoutFrm* pRow = pTab->GetFirstNonHeadlineRow();
1108 [ # # ]: 0 : if ( pRow )
1109 : : {
1110 : : // We are in the first line of a follow table
1111 : : // with repeated headings.
1112 : : // To actually make a "real" move we take the first content
1113 : : // of the next row
1114 : 0 : pCnt = pRow->ContainsCntnt();
1115 [ # # ]: 0 : if ( ! pCnt )
1116 : 0 : return sal_False;
1117 : : }
1118 : : }
1119 : : }
1120 : : }
1121 : :
1122 : 21 : SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
1123 : 21 : pPam->GetPoint()->nNode = *pCNd;
1124 : : xub_StrLen nIdx;
1125 [ + + ]: 21 : if( fnPosPage == GetFirstSub )
1126 : 17 : nIdx = ((SwTxtFrm*)pCnt)->GetOfst();
1127 : : else
1128 : 4 : nIdx = pCnt->GetFollow() ?
1129 [ + - ]: 4 : ((SwTxtFrm*)pCnt)->GetFollow()->GetOfst()-1 : pCNd->Len();
1130 [ + - ]: 21 : pPam->GetPoint()->nContent.Assign( pCNd, nIdx );
1131 : 21 : return sal_True;
1132 : : }
1133 : : }
1134 : :
1135 : : /*************************************************************************
1136 : : |*
1137 : : |* SwLayoutFrm::GetCntntPos()
1138 : : |*
1139 : : |* Beschreibung Es wird der nachstliegende Cntnt zum uebergebenen
1140 : : |* gesucht. Betrachtet werden die vorhergehende, die
1141 : : |* aktuelle und die folgende Seite.
1142 : : |* Wenn kein Inhalt gefunden wird, so wird der Bereich
1143 : : * erweitert bis einer gefunden wird.
1144 : : |* Zurueckgegeben wird die 'Semantisch richtige' Position
1145 : : |* innerhalb der PrtArea des gefundenen CntntFrm
1146 : : |*
1147 : : |*************************************************************************/
1148 : 246 : sal_uLong CalcDiff( const Point &rPt1, const Point &rPt2 )
1149 : : {
1150 : : //Jetzt die Entfernung zwischen den beiden Punkten berechnen.
1151 : : //'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2
1152 : 246 : sal_uInt32 dX = Max( rPt1.X(), rPt2.X() ) -
1153 : 246 : Min( rPt1.X(), rPt2.X() ),
1154 : 246 : dY = Max( rPt1.Y(), rPt2.Y() ) -
1155 : 246 : Min( rPt1.Y(), rPt2.Y() );
1156 [ + - ][ + - ]: 246 : BigInt dX1( dX ), dY1( dY );
1157 [ + - ][ + - ]: 246 : dX1 *= dX1; dY1 *= dY1;
1158 [ + - ][ + - ]: 246 : return ::SqRt( dX1 + dY1 );
1159 : : }
1160 : :
1161 : : // lcl_Inside ueberprueft, ob der Punkt innerhalb des Seitenteils liegt, in dem
1162 : : // auch der CntntFrame liegt. Als Seitenteile gelten in diesem Zusammenhang
1163 : : // Kopfzeile, Seitenbody, Fusszeile und FussnotenContainer.
1164 : : // Dies dient dazu, dass ein CntntFrm, der im "richtigen" Seitenteil liegt,
1165 : : // eher akzeptiert wird als ein anderer, der nicht dort liegt, auch wenn
1166 : : // dessen Abstand zum Punkt geringer ist.
1167 : :
1168 : 246 : const SwLayoutFrm* lcl_Inside( const SwCntntFrm *pCnt, Point& rPt )
1169 : : {
1170 : 246 : const SwLayoutFrm* pUp = pCnt->GetUpper();
1171 [ + - ]: 246 : while( pUp )
1172 : : {
1173 [ - + ][ # # ]: 246 : if( pUp->IsPageBodyFrm() || pUp->IsFooterFrm() || pUp->IsHeaderFrm() )
[ # # ][ + - ]
1174 : : {
1175 [ + + ][ + - ]: 246 : if( rPt.Y() >= pUp->Frm().Top() && rPt.Y() <= pUp->Frm().Bottom() )
[ + + ]
1176 : 240 : return pUp;
1177 : 6 : return NULL;
1178 : : }
1179 [ # # ]: 0 : if( pUp->IsFtnContFrm() )
1180 [ # # ]: 0 : return pUp->Frm().IsInside( rPt ) ? pUp : NULL;
1181 : 0 : pUp = pUp->GetUpper();
1182 : : }
1183 : 246 : return NULL;
1184 : : }
1185 : :
1186 : 266 : const SwCntntFrm *SwLayoutFrm::GetCntntPos( Point& rPoint,
1187 : : const sal_Bool bDontLeave,
1188 : : const sal_Bool bBodyOnly,
1189 : : const sal_Bool bCalc,
1190 : : const SwCrsrMoveState *pCMS,
1191 : : const sal_Bool bDefaultExpand ) const
1192 : : {
1193 : : //Ersten CntntFrm ermitteln.
1194 : 4 : const SwLayoutFrm *pStart = (!bDontLeave && bDefaultExpand && GetPrev()) ?
1195 [ + - ]: 270 : (SwLayoutFrm*)GetPrev() : this;
[ + + - + ]
1196 [ + - ]: 266 : const SwCntntFrm *pCntnt = pStart->ContainsCntnt();
1197 : :
1198 [ - + ][ # # ]: 266 : if ( !pCntnt && (GetPrev() && !bDontLeave) )
[ # # ][ - + ]
1199 [ # # ]: 0 : pCntnt = ContainsCntnt();
1200 : :
1201 [ + + ][ + - ]: 266 : if ( bBodyOnly && pCntnt && !pCntnt->IsInDocBody() )
[ + - ][ - + ]
[ - + ]
1202 [ # # ][ # # ]: 0 : while ( pCntnt && !pCntnt->IsInDocBody() )
[ # # ][ # # ]
1203 [ # # ]: 0 : pCntnt = pCntnt->GetNextCntntFrm();
1204 : :
1205 : 266 : const SwCntntFrm *pActual= pCntnt;
1206 : 266 : const SwLayoutFrm *pInside = NULL;
1207 [ + - ][ + + ]: 266 : sal_uInt16 nMaxPage = GetPhyPageNum() + (bDefaultExpand ? 1 : 0);
1208 : 266 : Point aPoint = rPoint;
1209 : 266 : sal_uLong nDistance = ULONG_MAX;
1210 : :
1211 : 0 : while ( sal_True ) //Sicherheitsschleifchen, damit immer einer gefunden wird.
1212 : : {
1213 [ + + ][ - + ]: 798 : while ( pCntnt &&
[ # # ][ + - ]
[ + + ]
1214 [ # # ]: 0 : ((!bDontLeave || IsAnLower( pCntnt )) &&
1215 [ + - ]: 266 : (pCntnt->GetPhyPageNum() <= nMaxPage)) )
1216 : : {
1217 [ + - ][ + + ]: 268 : if ( ( bCalc || pCntnt->Frm().Width() ) &&
[ + + ][ + - ]
[ + + ]
1218 [ + - ]: 2 : ( !bBodyOnly || pCntnt->IsInDocBody() ) )
1219 : : {
1220 : : //Wenn der Cntnt in einem geschuetzen Bereich (Zelle, Ftn, Section)
1221 : : //liegt, wird der nachste Cntnt der nicht geschuetzt ist gesucht.
1222 : 264 : const SwCntntFrm *pComp = pCntnt;
1223 : : pCntnt = ::lcl_MissProtectedFrames( pCntnt, lcl_GetNxtCnt, sal_False,
1224 [ + + ][ + - ]: 264 : pCMS ? pCMS->bSetInReadOnly : sal_False, sal_False );
1225 [ - + ]: 264 : if ( pComp != pCntnt )
1226 : 0 : continue;
1227 : :
1228 [ + - ][ + - ]: 264 : if ( !pCntnt->IsTxtFrm() || !((SwTxtFrm*)pCntnt)->IsHiddenNow() )
[ + + ][ + + ]
1229 : : {
1230 [ - + ]: 246 : if ( bCalc )
1231 [ # # ]: 0 : pCntnt->Calc();
1232 : :
1233 [ + - ]: 246 : SwRect aCntFrm( pCntnt->UnionFrm() );
1234 [ + - ][ - + ]: 246 : if ( aCntFrm.IsInside( rPoint ) )
1235 : : {
1236 : 0 : pActual = pCntnt;
1237 : 0 : aPoint = rPoint;
1238 : : break;
1239 : : }
1240 : : //Die Strecke von rPoint zum dichtesten Punkt von pCntnt wird
1241 : : //jetzt berechnet.
1242 : 246 : Point aCntntPoint( rPoint );
1243 : :
1244 : : //Erst die Vertikale Position einstellen
1245 [ + + ]: 246 : if ( aCntFrm.Top() > aCntntPoint.Y() )
1246 : 6 : aCntntPoint.Y() = aCntFrm.Top();
1247 [ + - ]: 240 : else if ( aCntFrm.Bottom() < aCntntPoint.Y() )
1248 : 240 : aCntntPoint.Y() = aCntFrm.Bottom();
1249 : :
1250 : : //Jetzt die Horizontale Position
1251 [ + + ]: 246 : if ( aCntFrm.Left() > aCntntPoint.X() )
1252 : 4 : aCntntPoint.X() = aCntFrm.Left();
1253 [ - + ]: 242 : else if ( aCntFrm.Right() < aCntntPoint.X() )
1254 : 0 : aCntntPoint.X() = aCntFrm.Right();
1255 : :
1256 : : // pInside ist ein Seitenbereich, in dem der Punkt liegt,
1257 : : // sobald pInside!=0 ist, werden nur noch Frames akzeptiert,
1258 : : // die innerhalb liegen.
1259 [ - + ][ # # ]: 246 : if( !pInside || ( pInside->IsAnLower( pCntnt ) &&
[ # # ]
[ # # # # ]
[ + - ]
1260 [ # # ]: 0 : ( !pCntnt->IsInFtn() || pInside->IsFtnContFrm() ) ) )
1261 : : {
1262 [ + - ]: 246 : const sal_uLong nDiff = ::CalcDiff( aCntntPoint, rPoint );
1263 : 246 : sal_Bool bBetter = nDiff < nDistance; // Dichter dran
1264 [ + - ]: 246 : if( !pInside )
1265 : : {
1266 [ + - ]: 246 : pInside = lcl_Inside( pCntnt, rPoint );
1267 [ + + ]: 246 : if( pInside ) // Im "richtigen" Seitenteil
1268 : 240 : bBetter = sal_True;
1269 : : }
1270 [ + - ]: 246 : if( bBetter )
1271 : : {
1272 : 246 : aPoint = aCntntPoint;
1273 : 246 : nDistance = nDiff;
1274 : 246 : pActual = pCntnt;
1275 : : }
1276 : : }
1277 : : }
1278 : : }
1279 [ + - ]: 266 : pCntnt = pCntnt->GetNextCntntFrm();
1280 [ + + ]: 266 : if ( bBodyOnly )
1281 [ - + ][ # # ]: 2 : while ( pCntnt && !pCntnt->IsInDocBody() )
[ # # ][ - + ]
1282 [ # # ]: 0 : pCntnt = pCntnt->GetNextCntntFrm();
1283 : : }
1284 [ - + ]: 266 : if ( !pActual )
1285 : : { //Wenn noch keiner gefunden wurde muss der Suchbereich erweitert
1286 : : //werden, irgenwann muessen wir einen Finden!
1287 : : //MA 09. Jan. 97: Opt fuer viele leere Seiten, wenn wir nur im
1288 : : //Body suchen, koennen wir den Suchbereich gleich in einem
1289 : : //Schritt hinreichend erweitern.
1290 [ # # ]: 0 : if ( bBodyOnly )
1291 : : {
1292 [ # # ][ # # ]: 0 : while ( !pCntnt && pStart->GetPrev() )
[ # # ]
1293 : : {
1294 : 0 : ++nMaxPage;
1295 [ # # ]: 0 : if( !pStart->GetPrev()->IsLayoutFrm() )
1296 : 0 : return 0;
1297 : 0 : pStart = (SwLayoutFrm*)pStart->GetPrev();
1298 [ # # ]: 0 : pCntnt = pStart->IsInDocBody()
1299 : : ? pStart->ContainsCntnt()
1300 [ # # ][ # # ]: 0 : : pStart->FindPageFrm()->FindFirstBodyCntnt();
[ # # ][ # # ]
1301 : : }
1302 [ # # ]: 0 : if ( !pCntnt ) //irgendwann muessen wir mit irgendeinem Anfangen!
1303 : : {
1304 [ # # ][ # # ]: 0 : pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
1305 [ # # ][ # # ]: 0 : while ( pCntnt && !pCntnt->IsInDocBody() )
[ # # ][ # # ]
1306 [ # # ]: 0 : pCntnt = pCntnt->GetNextCntntFrm();
1307 [ # # ]: 0 : if ( !pCntnt )
1308 : 0 : return 0; //Es gibt noch keine Dokumentinhalt!
1309 : : }
1310 : : }
1311 : : else
1312 : : {
1313 : 0 : ++nMaxPage;
1314 [ # # ]: 0 : if ( pStart->GetPrev() )
1315 : : {
1316 [ # # ]: 0 : if( !pStart->GetPrev()->IsLayoutFrm() )
1317 : 0 : return 0;
1318 : 0 : pStart = (SwLayoutFrm*)pStart->GetPrev();
1319 [ # # ]: 0 : pCntnt = pStart->ContainsCntnt();
1320 : : }
1321 : : else //irgendwann muessen wir mit irgendeinem Anfangen!
1322 [ # # ][ # # ]: 0 : pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
1323 : : }
1324 : 0 : pActual = pCntnt;
1325 : : }
1326 : : else
1327 : 266 : break;
1328 : : }
1329 : :
1330 : : OSL_ENSURE( pActual, "no Cntnt found." );
1331 : : OSL_ENSURE( !bBodyOnly || pActual->IsInDocBody(), "Cntnt not in Body." );
1332 : :
1333 : : //Spezialfall fuer das selektieren von Tabellen, nicht in wiederholte
1334 : : //TblHedlines.
1335 [ + - ][ - + ]: 266 : if ( pActual->IsInTab() && pCMS && pCMS->eState == MV_TBLSEL )
[ # # ][ # # ]
[ - + ]
1336 : : {
1337 [ # # ]: 0 : const SwTabFrm *pTab = pActual->FindTabFrm();
1338 [ # # ][ # # ]: 0 : if ( pTab->IsFollow() && pTab->IsInHeadline( *pActual ) )
[ # # ][ # # ]
1339 : : {
1340 : 0 : ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
1341 : 0 : return 0;
1342 : : }
1343 : : }
1344 : :
1345 : : //Jetzt noch eine kleine Korrektur beim ersten/letzten
1346 : 266 : Size aActualSize( pActual->Prt().SSize() );
1347 [ - + ]: 266 : if ( aActualSize.Height() > pActual->GetUpper()->Prt().Height() )
1348 : 0 : aActualSize.Height() = pActual->GetUpper()->Prt().Height();
1349 : :
1350 [ + - ][ + + ]: 266 : SWRECTFN( pActual )
[ + - ][ - + ]
[ - + ]
1351 [ + - ][ + + ]: 532 : if ( !pActual->GetPrev() &&
[ + + ]
1352 : 532 : (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtTop)(),
1353 [ + + ][ + - ]: 266 : bVert ? rPoint.X() : rPoint.Y() ) > 0 )
[ + - ][ + - ]
1354 : : {
1355 : 6 : aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Top();
1356 : 6 : aPoint.X() = pActual->Frm().Left() +
1357 [ + - ]: 6 : ( pActual->IsRightToLeft() || bVert ?
1358 : 0 : pActual->Prt().Right() :
1359 [ + - ][ - + ]: 6 : pActual->Prt().Left() );
1360 : : }
1361 [ + - ][ + + ]: 520 : else if ( !pActual->GetNext() &&
[ + + ]
1362 : 520 : (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtBottom)(),
1363 [ + + ][ + - ]: 260 : bVert ? rPoint.X() : rPoint.Y() ) < 0 )
[ + - ][ + - ]
1364 : : {
1365 : 254 : aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Bottom();
1366 : 254 : aPoint.X() = pActual->Frm().Left() +
1367 [ + - ]: 254 : ( pActual->IsRightToLeft() || bVert ?
1368 : 0 : pActual->Prt().Left() :
1369 [ + - ][ - + ]: 254 : pActual->Prt().Right() );
1370 : : }
1371 : :
1372 : : //Und den Point in die PrtArea bringen
1373 [ - + ]: 266 : if ( bCalc )
1374 [ # # ]: 0 : pActual->Calc();
1375 : 266 : const SwRect aRect( pActual->Frm().Pos() + pActual->Prt().Pos(),
1376 : 266 : aActualSize );
1377 [ - + ]: 266 : if ( aPoint.Y() < aRect.Top() )
1378 : 0 : aPoint.Y() = aRect.Top();
1379 [ - + ]: 266 : else if ( aPoint.Y() > aRect.Bottom() )
1380 : 0 : aPoint.Y() = aRect.Bottom();
1381 [ - + ]: 266 : if ( aPoint.X() < aRect.Left() )
1382 : 0 : aPoint.X() = aRect.Left();
1383 [ - + ]: 266 : else if ( aPoint.X() > aRect.Right() )
1384 : 0 : aPoint.X() = aRect.Right();
1385 : 266 : rPoint = aPoint;
1386 : 266 : return pActual;
1387 : : }
1388 : :
1389 : : /*************************************************************************
1390 : : |*
1391 : : |* SwPageFrm::GetCntntPosition()
1392 : : |*
1393 : : |* Beschreibung Analog zu SwLayoutFrm::GetCntntPos().
1394 : : |* Spezialisiert fuer Felder in Rahmen.
1395 : : |*
1396 : : |*************************************************************************/
1397 : 0 : void SwPageFrm::GetCntntPosition( const Point &rPt, SwPosition &rPos ) const
1398 : : {
1399 : : //Ersten CntntFrm ermitteln.
1400 [ # # ]: 0 : const SwCntntFrm *pCntnt = ContainsCntnt();
1401 [ # # ]: 0 : if ( pCntnt )
1402 : : {
1403 : : //Einen weiter zurueck schauen (falls moeglich).
1404 [ # # ]: 0 : const SwCntntFrm *pTmp = pCntnt->GetPrevCntntFrm();
1405 [ # # ][ # # ]: 0 : while ( pTmp && !pTmp->IsInDocBody() )
[ # # ][ # # ]
1406 [ # # ]: 0 : pTmp = pTmp->GetPrevCntntFrm();
1407 [ # # ]: 0 : if ( pTmp )
1408 : 0 : pCntnt = pTmp;
1409 : : }
1410 : : else
1411 [ # # ]: 0 : pCntnt = GetUpper()->ContainsCntnt();
1412 : :
1413 : 0 : const SwCntntFrm *pAct = pCntnt;
1414 : 0 : Point aAct = rPt;
1415 : 0 : sal_uLong nDist = ULONG_MAX;
1416 : :
1417 [ # # ]: 0 : while ( pCntnt )
1418 : : {
1419 [ # # ]: 0 : SwRect aCntFrm( pCntnt->UnionFrm() );
1420 [ # # ][ # # ]: 0 : if ( aCntFrm.IsInside( rPt ) )
1421 : : {
1422 : : //dichter gehts nimmer.
1423 : 0 : pAct = pCntnt;
1424 : : break;
1425 : : }
1426 : :
1427 : : //Die Strecke von rPt zum dichtesten Punkt von pCntnt berechnen.
1428 : 0 : Point aPoint( rPt );
1429 : :
1430 : : //Erst die vertikale Position einstellen
1431 [ # # ]: 0 : if ( aCntFrm.Top() > rPt.Y() )
1432 : 0 : aPoint.Y() = aCntFrm.Top();
1433 [ # # ]: 0 : else if ( aCntFrm.Bottom() < rPt.Y() )
1434 : 0 : aPoint.Y() = aCntFrm.Bottom();
1435 : :
1436 : : //Jetzt die horizontale Position
1437 [ # # ]: 0 : if ( aCntFrm.Left() > rPt.X() )
1438 : 0 : aPoint.X() = aCntFrm.Left();
1439 [ # # ]: 0 : else if ( aCntFrm.Right() < rPt.X() )
1440 : 0 : aPoint.X() = aCntFrm.Right();
1441 : :
1442 [ # # ]: 0 : const sal_uLong nDiff = ::CalcDiff( aPoint, rPt );
1443 [ # # ]: 0 : if ( nDiff < nDist )
1444 : : {
1445 : 0 : aAct = aPoint;
1446 : 0 : nDist = nDiff;
1447 : 0 : pAct = pCntnt;
1448 : : }
1449 [ # # ]: 0 : else if ( aCntFrm.Top() > Frm().Bottom() )
1450 : : //Dichter wirds im Sinne der Felder nicht mehr!
1451 : : break;
1452 : :
1453 [ # # ]: 0 : pCntnt = pCntnt->GetNextCntntFrm();
1454 [ # # ][ # # ]: 0 : while ( pCntnt && !pCntnt->IsInDocBody() )
[ # # ][ # # ]
1455 [ # # ]: 0 : pCntnt = pCntnt->GetNextCntntFrm();
1456 : : }
1457 : :
1458 : : //Und den Point in die PrtArea bringen
1459 : 0 : const SwRect aRect( pAct->Frm().Pos() + pAct->Prt().Pos(), pAct->Prt().SSize() );
1460 [ # # ]: 0 : if ( aAct.Y() < aRect.Top() )
1461 : 0 : aAct.Y() = aRect.Top();
1462 [ # # ]: 0 : else if ( aAct.Y() > aRect.Bottom() )
1463 : 0 : aAct.Y() = aRect.Bottom();
1464 [ # # ]: 0 : if ( aAct.X() < aRect.Left() )
1465 : 0 : aAct.X() = aRect.Left();
1466 [ # # ]: 0 : else if ( aAct.X() > aRect.Right() )
1467 : 0 : aAct.X() = aRect.Right();
1468 : :
1469 [ # # ]: 0 : if( !pAct->IsValid() )
1470 : : {
1471 : : // CntntFrm nicht formatiert -> immer auf Node-Anfang
1472 : 0 : SwCntntNode* pCNd = (SwCntntNode*)pAct->GetNode();
1473 : : OSL_ENSURE( pCNd, "Wo ist mein CntntNode?" );
1474 [ # # ]: 0 : rPos.nNode = *pCNd;
1475 [ # # ][ # # ]: 0 : rPos.nContent.Assign( pCNd, 0 );
1476 : : }
1477 : : else
1478 : : {
1479 : 0 : SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
1480 [ # # ]: 0 : pAct->GetCrsrOfst( &rPos, aAct, &aTmpState );
1481 : : }
1482 : 0 : }
1483 : :
1484 : : /*************************************************************************
1485 : : |*
1486 : : |* SwRootFrm::GetNextPrevCntntPos()
1487 : : |*
1488 : : |* Beschreibung Es wird der naechstliegende Cntnt zum uebergebenen
1489 : : |* Point gesucht. Es wird nur im BodyText gesucht.
1490 : : |*
1491 : : |*************************************************************************/
1492 : :
1493 : : // #123110# - helper class to disable creation of an action
1494 : : // by a callback event - e.g., change event from a drawing object
1495 : : class DisableCallbackAction
1496 : : {
1497 : : private:
1498 : : SwRootFrm& mrRootFrm;
1499 : : sal_Bool mbOldCallbackActionState;
1500 : :
1501 : : public:
1502 : 0 : DisableCallbackAction( const SwRootFrm& _rRootFrm ) :
1503 : : mrRootFrm( const_cast<SwRootFrm&>(_rRootFrm) ),
1504 : 0 : mbOldCallbackActionState( _rRootFrm.IsCallbackActionEnabled() )
1505 : : {
1506 : 0 : mrRootFrm.SetCallbackActionEnabled( sal_False );
1507 : 0 : }
1508 : :
1509 : 0 : ~DisableCallbackAction()
1510 : : {
1511 : 0 : mrRootFrm.SetCallbackActionEnabled( mbOldCallbackActionState );
1512 : 0 : }
1513 : : };
1514 : :
1515 : : //!!!!! Es wird nur der vertikal naechstliegende gesucht.
1516 : : //JP 11.10.2001: only in tables we try to find the right column - Bug 72294
1517 : 0 : Point SwRootFrm::GetNextPrevCntntPos( const Point& rPoint, sal_Bool bNext ) const
1518 : : {
1519 : : // #123110# - disable creation of an action by a callback
1520 : : // event during processing of this method. Needed because formatting is
1521 : : // triggered by this method.
1522 : 0 : DisableCallbackAction aDisableCallbackAction( *this );
1523 : : //Ersten CntntFrm und seinen Nachfolger im Body-Bereich suchen
1524 : : //Damit wir uns nicht tot suchen (und vor allem nicht zuviel formatieren)
1525 : : //gehen wir schon mal von der richtigen Seite aus.
1526 : 0 : SwLayoutFrm *pPage = (SwLayoutFrm*)Lower();
1527 [ # # ]: 0 : if( pPage )
1528 [ # # ][ # # ]: 0 : while( pPage->GetNext() && pPage->Frm().Bottom() < rPoint.Y() )
[ # # ]
1529 : 0 : pPage = (SwLayoutFrm*)pPage->GetNext();
1530 : :
1531 [ # # ][ # # ]: 0 : const SwCntntFrm *pCnt = pPage ? pPage->ContainsCntnt() : ContainsCntnt();
[ # # ]
1532 [ # # ][ # # ]: 0 : while ( pCnt && !pCnt->IsInDocBody() )
[ # # ][ # # ]
1533 [ # # ]: 0 : pCnt = pCnt->GetNextCntntFrm();
1534 : :
1535 [ # # ]: 0 : if ( !pCnt )
1536 : 0 : return Point( 0, 0 );
1537 : :
1538 [ # # ]: 0 : pCnt->Calc();
1539 [ # # ]: 0 : if( !bNext )
1540 : : {
1541 : : // Solange der Point vor dem ersten CntntFrm liegt und es noch
1542 : : // vorhergehende Seiten gibt gehe ich jeweils eine Seite nach vorn.
1543 [ # # ][ # # ]: 0 : while ( rPoint.Y() < pCnt->Frm().Top() && pPage->GetPrev() )
[ # # ]
1544 : : {
1545 : 0 : pPage = (SwLayoutFrm*)pPage->GetPrev();
1546 [ # # ]: 0 : pCnt = pPage->ContainsCntnt();
1547 [ # # ]: 0 : while ( !pCnt )
1548 : : {
1549 : 0 : pPage = (SwLayoutFrm*)pPage->GetPrev();
1550 [ # # ]: 0 : if ( pPage )
1551 [ # # ]: 0 : pCnt = pPage->ContainsCntnt();
1552 : : else
1553 [ # # ][ # # ]: 0 : return ContainsCntnt()->UnionFrm().Pos();
1554 : : }
1555 [ # # ]: 0 : pCnt->Calc();
1556 : : }
1557 : : }
1558 : :
1559 : : //Liegt der Point ueber dem ersten CntntFrm?
1560 [ # # ][ # # ]: 0 : if ( rPoint.Y() < pCnt->Frm().Top() && !lcl_IsInRepeatedHeadline( pCnt ) )
[ # # ][ # # ]
1561 [ # # ]: 0 : return pCnt->UnionFrm().Pos();
1562 : :
1563 [ # # ]: 0 : while ( pCnt )
1564 : : {
1565 : : //Liegt der Point im aktuellen CntntFrm?
1566 [ # # ]: 0 : SwRect aCntFrm( pCnt->UnionFrm() );
1567 [ # # ][ # # ]: 0 : if ( aCntFrm.IsInside( rPoint ) && !lcl_IsInRepeatedHeadline( pCnt ))
[ # # ][ # # ]
[ # # ]
1568 : 0 : return rPoint;
1569 : :
1570 : : //Ist der aktuelle der letzte CntntFrm? ||
1571 : : //Wenn der naechste CntntFrm hinter dem Point liegt, ist der
1572 : : //aktuelle der gesuchte.
1573 [ # # ]: 0 : const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
1574 [ # # ][ # # ]: 0 : while ( pNxt && !pNxt->IsInDocBody() )
[ # # ][ # # ]
1575 [ # # ]: 0 : pNxt = pNxt->GetNextCntntFrm();
1576 : :
1577 : : //Liegt der Point hinter dem letzten CntntFrm?
1578 [ # # ]: 0 : if ( !pNxt )
1579 : 0 : return Point( aCntFrm.Right(), aCntFrm.Bottom() );
1580 : :
1581 : : //Wenn der naechste CntntFrm hinter dem Point liegt ist er der
1582 : : //gesuchte.
1583 : : const SwTabFrm* pTFrm;
1584 [ # # ]: 0 : pNxt->Calc();
1585 [ # # ][ # # ]: 0 : if( pNxt->Frm().Top() > rPoint.Y() &&
[ # # # # ]
[ # # ]
1586 [ # # ]: 0 : !lcl_IsInRepeatedHeadline( pCnt, &pTFrm ) &&
1587 : 0 : ( !pTFrm || pNxt->Frm().Left() > rPoint.X() ))
1588 : : {
1589 [ # # ]: 0 : if( bNext )
1590 : 0 : return pNxt->Frm().Pos();
1591 : 0 : return Point( aCntFrm.Right(), aCntFrm.Bottom() );
1592 : : }
1593 : 0 : pCnt = pNxt;
1594 : : }
1595 : 0 : return Point( 0, 0 );
1596 : : }
1597 : :
1598 : : /*************************************************************************
1599 : : |*
1600 : : |* SwRootFrm::GetPagePos()
1601 : : |*
1602 : : |* Beschreibung: Liefert die absolute Dokumentpositon der gewuenschten
1603 : : |* Seite.
1604 : : |* Formatiert wird nur soweit notwendig und nur dann wenn bFormat=sal_True
1605 : : |* Liefert Null, wenn die Operation nicht moeglich ist.
1606 : : |* Die Pos ist die der letzten Seite, wenn die Seitenzahl zu gross
1607 : : |* gewaehlt wurde.
1608 : : |*
1609 : : |*************************************************************************/
1610 : 0 : Point SwRootFrm::GetPagePos( sal_uInt16 nPageNum ) const
1611 : : {
1612 : : OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "Keine Seite vorhanden." );
1613 : :
1614 : 0 : const SwPageFrm *pPage = (const SwPageFrm*)Lower();
1615 : 0 : while ( sal_True )
1616 : : {
1617 [ # # ][ # # ]: 0 : if ( pPage->GetPhyPageNum() >= nPageNum || !pPage->GetNext() )
[ # # ]
1618 : 0 : break;
1619 : 0 : pPage = (const SwPageFrm*)pPage->GetNext();
1620 : : }
1621 : 0 : return pPage->Frm().Pos();
1622 : : }
1623 : :
1624 : : /** get page frame by phyiscal page number
1625 : :
1626 : : OD 14.01.2003 #103492#
1627 : :
1628 : : @return pointer to the page frame with the given physical page number
1629 : : */
1630 : 0 : SwPageFrm* SwRootFrm::GetPageByPageNum( sal_uInt16 _nPageNum ) const
1631 : : {
1632 : 0 : const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>( Lower() );
1633 [ # # ][ # # ]: 0 : while ( pPageFrm && pPageFrm->GetPhyPageNum() < _nPageNum )
[ # # ]
1634 : : {
1635 : 0 : pPageFrm = static_cast<const SwPageFrm*>( pPageFrm->GetNext() );
1636 : : }
1637 : :
1638 [ # # ][ # # ]: 0 : if ( pPageFrm && pPageFrm->GetPhyPageNum() == _nPageNum )
[ # # ]
1639 : : {
1640 : 0 : return const_cast<SwPageFrm*>( pPageFrm );
1641 : : }
1642 : : else
1643 : : {
1644 : 0 : return 0;
1645 : : }
1646 : : }
1647 : :
1648 : : /*************************************************************************
1649 : : |*
1650 : : |* SwRootFrm::IsDummyPage(sal_uInt16)
1651 : : |*
1652 : : |* Description: Returns sal_True, when the given physical pagenumber does't exist
1653 : : |* or this page is an empty page.
1654 : : |*************************************************************************/
1655 : 0 : sal_Bool SwRootFrm::IsDummyPage( sal_uInt16 nPageNum ) const
1656 : : {
1657 [ # # ][ # # ]: 0 : if( !Lower() || !nPageNum || nPageNum > GetPageNum() )
[ # # ][ # # ]
1658 : 0 : return sal_True;
1659 : :
1660 : 0 : const SwPageFrm *pPage = (const SwPageFrm*)Lower();
1661 [ # # ][ # # ]: 0 : while( pPage && nPageNum < pPage->GetPhyPageNum() )
[ # # ]
1662 : 0 : pPage = (const SwPageFrm*)pPage->GetNext();
1663 [ # # ]: 0 : return pPage ? pPage->IsEmptyPage() : sal_True;
1664 : : }
1665 : :
1666 : :
1667 : : /*************************************************************************
1668 : : |*
1669 : : |* SwFrm::IsProtected()
1670 : : |*
1671 : : |* Beschreibung Ist der Frm bzw. die Section in der er steht
1672 : : |* geschuetzt?
1673 : : |* Auch Fly in Fly in ... und Fussnoten
1674 : : |*
1675 : : |*
1676 : : |*************************************************************************/
1677 : 24263 : sal_Bool SwFrm::IsProtected() const
1678 : : {
1679 [ + + ][ + - ]: 24263 : if (this->IsCntntFrm() && ((SwCntntFrm*)this)->GetNode())
[ + + ]
1680 : : {
1681 : 24241 : const SwDoc *pDoc=((SwCntntFrm*)this)->GetNode()->GetDoc();
1682 : 24241 : bool isFormProtected=pDoc->get(IDocumentSettingAccess::PROTECT_FORM );
1683 [ - + ]: 24241 : if (isFormProtected)
1684 : : {
1685 : 0 : return sal_False; // TODO a hack for now, well deal with it laster, I we return true here we have a "double" locking
1686 : : }
1687 : : }
1688 : : //Der Frm kann in Rahmen, Zellen oder Bereichen geschuetzt sein.
1689 : : //Geht auch FlyFrms rekursiv hoch. Geht auch von Fussnoten zum Anker.
1690 : 24263 : const SwFrm *pFrm = this;
1691 [ + + ]: 98036 : do
1692 : : {
1693 [ + + ]: 98036 : if ( pFrm->IsCntntFrm() )
1694 : : {
1695 [ + - - + ]: 48514 : if ( ((SwCntntFrm*)pFrm)->GetNode() &&
[ - + ]
1696 : 24257 : ((SwCntntFrm*)pFrm)->GetNode()->IsInProtectSect() )
1697 : 0 : return sal_True;
1698 : : }
1699 : : else
1700 : : {
1701 [ + - - + ]: 147558 : if ( ((SwLayoutFrm*)pFrm)->GetFmt() &&
[ - + ]
1702 : 73779 : ((SwLayoutFrm*)pFrm)->GetFmt()->
1703 : 73779 : GetProtect().IsCntntProtected() )
1704 : 0 : return sal_True;
1705 [ - + ]: 73779 : if ( pFrm->IsCoveredCell() )
1706 : 0 : return sal_True;
1707 : : }
1708 [ + + ]: 98036 : if ( pFrm->IsFlyFrm() )
1709 : : {
1710 : : //Der Schutz des Inhaltes kann bei Verkettung vom Master der Kette
1711 : : //vorgegeben werden.
1712 [ - + ]: 10 : if ( ((SwFlyFrm*)pFrm)->GetPrevLink() )
1713 : : {
1714 : 0 : SwFlyFrm *pMaster = (SwFlyFrm*)pFrm;
1715 [ # # ]: 0 : do
1716 : 0 : { pMaster = pMaster->GetPrevLink();
1717 : 0 : } while ( pMaster->GetPrevLink() );
1718 [ # # ]: 0 : if ( pMaster->IsProtected() )
1719 : 0 : return sal_True;
1720 : : }
1721 : 10 : pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
1722 : : }
1723 [ + + ]: 98026 : else if ( pFrm->IsFtnFrm() )
1724 : 10 : pFrm = ((SwFtnFrm*)pFrm)->GetRef();
1725 : : else
1726 : 98016 : pFrm = pFrm->GetUpper();
1727 : :
1728 : : } while ( pFrm );
1729 : :
1730 : 24263 : return sal_False;
1731 : : }
1732 : :
1733 : : /*************************************************************************
1734 : : |*
1735 : : |* SwFrm::GetPhyPageNum()
1736 : : |* Beschreibung: Liefert die physikalische Seitennummer
1737 : : |*
1738 : : |*
1739 : : |*************************************************************************/
1740 : 1702 : sal_uInt16 SwFrm::GetPhyPageNum() const
1741 : : {
1742 : 1702 : const SwPageFrm *pPage = FindPageFrm();
1743 [ + - ]: 1702 : return pPage ? pPage->GetPhyPageNum() : 0;
1744 : : }
1745 : :
1746 : : /*--------------------------------------------------
1747 : : * SwFrm::WannaRightPage()
1748 : : * decides if the page want to be a rightpage or not.
1749 : : * If the first content of the page has a page descriptor,
1750 : : * we take the follow of the page descriptor of the last not empty page.
1751 : : * If this descriptor allows only right(left) pages and the page
1752 : : * isn't an empty page then it wanna be such right(left) page.
1753 : : * If the descriptor allows right and left pages, we look for a number offset
1754 : : * in the first content. If there is one, odd number results right pages,
1755 : : * even number results left pages.
1756 : : * If there is no number offset, we take the physical page number instead,
1757 : : * but a previous empty page don't count.
1758 : : * --------------------------------------------------*/
1759 : :
1760 : 169 : sal_Bool SwFrm::WannaRightPage() const
1761 : : {
1762 : 169 : const SwPageFrm *pPage = FindPageFrm();
1763 [ - + ][ - + ]: 169 : if ( !pPage || !pPage->GetUpper() )
[ + - ]
1764 : 0 : return sal_True;
1765 : :
1766 : 169 : const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
1767 : 169 : const SwPageDesc *pDesc = 0;
1768 : 169 : sal_uInt16 nPgNum = 0;
1769 [ + + ]: 169 : if ( pFlow )
1770 : : {
1771 [ + + ]: 163 : if ( pFlow->IsInTab() )
1772 : 32 : pFlow = pFlow->FindTabFrm();
1773 : 163 : const SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
1774 [ + - ]: 163 : if ( !pTmp->IsFollow() )
1775 : : {
1776 : 163 : const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc();
1777 : 163 : pDesc = rPgDesc.GetPageDesc();
1778 : 163 : nPgNum = rPgDesc.GetNumOffset();
1779 : : }
1780 : : }
1781 [ + + ]: 169 : if ( !pDesc )
1782 : : {
1783 : 128 : SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
1784 [ - + ][ - + ]: 128 : if( pPrv && pPrv->IsEmptyPage() )
[ + + ]
1785 : 0 : pPrv = (SwPageFrm*)pPrv->GetPrev();
1786 [ + + ]: 128 : if( pPrv )
1787 : 6 : pDesc = pPrv->GetPageDesc()->GetFollow();
1788 : : else
1789 : : {
1790 : 122 : const SwDoc* pDoc = pPage->GetFmt()->GetDoc();
1791 : 122 : pDesc = &pDoc->GetPageDesc( 0 );
1792 : : }
1793 : : }
1794 : : OSL_ENSURE( pDesc, "No pagedescriptor" );
1795 : : sal_Bool bOdd;
1796 [ + + ]: 169 : if( nPgNum )
1797 : 2 : bOdd = (nPgNum % 2) ? sal_True : sal_False;
1798 : : else
1799 : : {
1800 : 167 : bOdd = pPage->OnRightPage();
1801 [ - + ][ - + ]: 167 : if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
[ + + ]
1802 : 0 : bOdd = !bOdd;
1803 : : }
1804 [ + - ]: 169 : if( !pPage->IsEmptyPage() )
1805 : : {
1806 [ - + ]: 169 : if( !pDesc->GetRightFmt() )
1807 : 0 : bOdd = sal_False;
1808 [ - + ]: 169 : else if( !pDesc->GetLeftFmt() )
1809 : 0 : bOdd = sal_True;
1810 : : }
1811 : 169 : return bOdd;
1812 : : }
1813 : :
1814 : 286 : bool SwFrm::OnFirstPage() const
1815 : : {
1816 : 286 : bool bRet = false;
1817 : 286 : const SwPageFrm *pPage = FindPageFrm();
1818 : :
1819 [ + - ]: 286 : if (pPage)
1820 : : {
1821 [ + + ]: 286 : const SwPageFrm* pPrevFrm = dynamic_cast<const SwPageFrm*>(pPage->GetPrev());
1822 [ + + ]: 286 : if (pPrevFrm)
1823 : : {
1824 : 126 : const SwPageDesc* pDesc = pPage->GetPageDesc();
1825 [ + + ][ + + ]: 126 : bRet = pPrevFrm->GetPageDesc() != pDesc && !pDesc->IsFirstShared();
1826 : : }
1827 : : }
1828 : 286 : return bRet;
1829 : : }
1830 : :
1831 : : /*************************************************************************
1832 : : |*
1833 : : |* SwFrm::GetVirtPageNum()
1834 : : |* Beschreibung: Liefert die virtuelle Seitennummer mit Offset
1835 : : |*
1836 : : |*************************************************************************/
1837 : 2231 : sal_uInt16 SwFrm::GetVirtPageNum() const
1838 : : {
1839 : 2231 : const SwPageFrm *pPage = FindPageFrm();
1840 [ - + ][ - + ]: 2231 : if ( !pPage || !pPage->GetUpper() )
[ + - ]
1841 : 0 : return 0;
1842 : :
1843 : 2231 : sal_uInt16 nPhyPage = pPage->GetPhyPageNum();
1844 [ + + ]: 2231 : if ( !((SwRootFrm*)pPage->GetUpper())->IsVirtPageNum() )
1845 : 2227 : return nPhyPage;
1846 : :
1847 : : //Den am naechsten stehenden Absatz mit virtueller Seitennummer suchen.
1848 : : //Da das rueckwaertsuchen insgesamt sehr viel Zeit verschlingt suchen
1849 : : //wir jetzt gezielt ueber die Abhaengigkeiten.
1850 : : //von den PageDescs bekommen wir die Attribute, von den Attributen
1851 : : //wiederum bekommen wir die Absaetze.
1852 : 4 : const SwPageFrm *pVirtPage = 0;
1853 : 4 : const SwFrm *pFrm = 0;
1854 : 4 : const SfxItemPool &rPool = pPage->GetFmt()->GetDoc()->GetAttrPool();
1855 : : const SfxPoolItem* pItem;
1856 : 4 : sal_uInt32 nMaxItems = rPool.GetItemCount2( RES_PAGEDESC );
1857 [ + + ]: 46 : for( sal_uInt32 n = 0; n < nMaxItems; ++n )
1858 : : {
1859 [ + + ]: 42 : if( 0 == (pItem = rPool.GetItem2( RES_PAGEDESC, n ) ))
1860 : 16 : continue;
1861 : :
1862 : 26 : const SwFmtPageDesc *pDesc = (SwFmtPageDesc*)pItem;
1863 [ + + ][ - + ]: 26 : if ( pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
[ - + ]
1864 : : {
1865 : 0 : const SwModify *pMod = pDesc->GetDefinedIn();
1866 [ # # ]: 0 : SwVirtPageNumInfo aInfo( pPage );
1867 [ # # ]: 0 : pMod->GetInfo( aInfo );
1868 [ # # ]: 0 : if ( aInfo.GetPage() )
1869 : : {
1870 [ # # ]: 0 : if( !pVirtPage || ( pVirtPage && aInfo.GetPage()->
[ # # # # ]
[ # # ]
1871 : 0 : GetPhyPageNum() > pVirtPage->GetPhyPageNum() ) )
1872 : : {
1873 : 0 : pVirtPage = aInfo.GetPage();
1874 : 0 : pFrm = aInfo.GetFrm();
1875 : : }
1876 [ # # ]: 0 : }
1877 : : }
1878 : : }
1879 [ - + ]: 4 : if ( pFrm )
1880 : 0 : return nPhyPage - pFrm->GetPhyPageNum() +
1881 : 0 : pFrm->GetAttrSet()->GetPageDesc().GetNumOffset();
1882 : 2231 : return nPhyPage;
1883 : : }
1884 : :
1885 : : /*************************************************************************
1886 : : |*
1887 : : |* SwRootFrm::MakeTblCrsrs()
1888 : : |*
1889 : : |*************************************************************************/
1890 : : //Ermitteln und einstellen derjenigen Zellen die von der Selektion
1891 : : //eingeschlossen sind.
1892 : :
1893 : 675 : bool SwRootFrm::MakeTblCrsrs( SwTableCursor& rTblCrsr )
1894 : : {
1895 : : //Union-Rects und Tabellen (Follows) der Selektion besorgen.
1896 : : OSL_ENSURE( rTblCrsr.GetCntntNode() && rTblCrsr.GetCntntNode( sal_False ),
1897 : : "Tabselection nicht auf Cnt." );
1898 : :
1899 : 675 : bool bRet = false;
1900 : :
1901 : : // For new table models there's no need to ask the layout..
1902 [ + - ][ + - ]: 675 : if( rTblCrsr.NewTableSelection() )
1903 : 675 : return true;
1904 : :
1905 : 0 : Point aPtPt, aMkPt;
1906 : : {
1907 [ # # ]: 0 : SwShellCrsr* pShCrsr = dynamic_cast<SwShellCrsr*>(&rTblCrsr);
1908 : :
1909 [ # # ]: 0 : if( pShCrsr )
1910 : : {
1911 : 0 : aPtPt = pShCrsr->GetPtPos();
1912 : 0 : aMkPt = pShCrsr->GetMkPos();
1913 : : }
1914 : : }
1915 : :
1916 : : // #151012# Made code robust here
1917 : 0 : const SwCntntNode* pTmpStartNode = rTblCrsr.GetCntntNode();
1918 : 0 : const SwCntntNode* pTmpEndNode = rTblCrsr.GetCntntNode(sal_False);
1919 : :
1920 [ # # ][ # # ]: 0 : const SwFrm* pTmpStartFrm = pTmpStartNode ? pTmpStartNode->getLayoutFrm( this, &aPtPt, 0, sal_False ) : 0;
1921 [ # # ][ # # ]: 0 : const SwFrm* pTmpEndFrm = pTmpEndNode ? pTmpEndNode->getLayoutFrm( this, &aMkPt, 0, sal_False ) : 0;
1922 : :
1923 [ # # ]: 0 : const SwLayoutFrm* pStart = pTmpStartFrm ? pTmpStartFrm->GetUpper() : 0;
1924 [ # # ]: 0 : const SwLayoutFrm* pEnd = pTmpEndFrm ? pTmpEndFrm->GetUpper() : 0;
1925 : :
1926 : : OSL_ENSURE( pStart && pEnd, "MakeTblCrsrs: Good to have the code robust here!" );
1927 : :
1928 : : /* #109590# Only change table boxes if the frames are
1929 : : valid. Needed because otherwise the table cursor after moving
1930 : : table cells by dnd resulted in an empty tables cursor. */
1931 [ # # ][ # # ]: 0 : if ( pStart && pEnd && pStart->IsValid() && pEnd->IsValid())
[ # # ][ # # ]
[ # # ]
1932 : : {
1933 [ # # ]: 0 : SwSelUnions aUnions;
1934 [ # # ]: 0 : ::MakeSelUnions( aUnions, pStart, pEnd );
1935 : :
1936 [ # # ]: 0 : SwSelBoxes aNew;
1937 : :
1938 [ # # ]: 0 : const sal_Bool bReadOnlyAvailable = rTblCrsr.IsReadOnlyAvailable();
1939 : :
1940 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < aUnions.size(); ++i )
1941 : : {
1942 [ # # ]: 0 : SwSelUnion *pUnion = &aUnions[i];
1943 : 0 : const SwTabFrm *pTable = pUnion->GetTable();
1944 : :
1945 : : // Skip any repeated headlines in the follow:
1946 : 0 : SwLayoutFrm* pRow = pTable->IsFollow() ?
1947 : : pTable->GetFirstNonHeadlineRow() :
1948 [ # # ][ # # ]: 0 : (SwLayoutFrm*)pTable->Lower();
1949 : :
1950 [ # # ]: 0 : while ( pRow )
1951 : : {
1952 [ # # ][ # # ]: 0 : if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
1953 : : {
1954 [ # # ]: 0 : const SwLayoutFrm *pCell = pRow->FirstCell();
1955 : :
1956 [ # # ][ # # ]: 0 : while ( pCell && pRow->IsAnLower( pCell ) )
[ # # ][ # # ]
1957 : : {
1958 : : OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
1959 [ # # ][ # # ]: 0 : if( IsFrmInTblSel( pUnion->GetUnion(), pCell ) &&
[ # # # # ]
[ # # ]
1960 : : (bReadOnlyAvailable ||
1961 [ # # ][ # # ]: 0 : !pCell->GetFmt()->GetProtect().IsCntntProtected()))
1962 : : {
1963 : : SwTableBox* pInsBox = (SwTableBox*)
1964 : 0 : ((SwCellFrm*)pCell)->GetTabBox();
1965 [ # # ]: 0 : aNew.insert( pInsBox );
1966 : : }
1967 [ # # ]: 0 : if ( pCell->GetNext() )
1968 : : {
1969 : 0 : pCell = (const SwLayoutFrm*)pCell->GetNext();
1970 [ # # ][ # # ]: 0 : if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
[ # # ]
1971 [ # # ]: 0 : pCell = pCell->FirstCell();
1972 : : }
1973 : : else
1974 : : {
1975 : 0 : const SwLayoutFrm* pLastCell = pCell;
1976 [ # # ][ # # ]: 0 : do
[ # # ]
1977 : : {
1978 [ # # ]: 0 : pCell = pCell->GetNextLayoutLeaf();
1979 [ # # ]: 0 : } while ( pCell && pLastCell->IsAnLower( pCell ) );
1980 : : // Fuer (spaltige) Bereiche...
1981 [ # # ][ # # ]: 0 : if( pCell && pCell->IsInTab() )
[ # # ][ # # ]
1982 : : {
1983 [ # # ]: 0 : while( !pCell->IsCellFrm() )
1984 : : {
1985 : 0 : pCell = pCell->GetUpper();
1986 : : OSL_ENSURE( pCell, "Where's my cell?" );
1987 : : }
1988 : : }
1989 : : }
1990 : : }
1991 : : }
1992 : 0 : pRow = (SwLayoutFrm*)pRow->GetNext();
1993 : : }
1994 : : }
1995 : :
1996 [ # # ]: 0 : rTblCrsr.ActualizeSelection( aNew );
1997 [ # # ]: 0 : bRet = true;
1998 : : }
1999 : :
2000 : 675 : return bRet;
2001 : : }
2002 : :
2003 : :
2004 : : /*************************************************************************
2005 : : |*
2006 : : |* SwRootFrm::CalcFrmRects
2007 : : |*
2008 : : |*************************************************************************/
2009 : :
2010 : : /*
2011 : : * nun koennen folgende Situationen auftreten:
2012 : : * 1. Start und Ende liegen in einer Bildschirm - Zeile und im
2013 : : * gleichen Node
2014 : : * -> aus Start und End ein Rectangle, dann Ok
2015 : : * 2. Start und Ende liegen in einem Frame (dadurch im gleichen Node!)
2016 : : * -> Start nach rechts, End nach links erweitern,
2017 : : * und bei mehr als 2 Bildschirm - Zeilen, das dazwischen
2018 : : * liegende berechnen
2019 : : * 3. Start und Ende liegen in verschiedenen Frames
2020 : : * -> Start nach rechts erweitern, bis Frame-Ende Rect berechnen
2021 : : * Ende nach links erweitern, bis Frame-Start Rect berechnen
2022 : : * und bei mehr als 2 Frames von allen dazwischen liegenden
2023 : : * Frames die PrtArea dazu.
2024 : : * 4. Wenn es sich um eine Tabellenselektion handelt wird fuer jeden
2025 : : * PaM im Ring der CellFrm besorgt, dessen PrtArea wird zu den
2026 : : * Rechtecken addiert.
2027 : : *
2028 : : * Grosser Umbau wg. der FlyFrm; denn diese muessen ausgespart werden.
2029 : : * Ausnahmen: - Der Fly in dem die Selektion stattfindet (wenn sie in einem Fly
2030 : : * stattfindet).
2031 : : * - Die Flys, die vom Text unterlaufen werden.
2032 : : * Arbeitsweise: Zuerst wird eine SwRegion mit der Root initialisiert.
2033 : : * Aus der Region werden die zu invertierenden Bereiche
2034 : : * ausgestantzt. Die Region wird Komprimiert und letztlich
2035 : : * invertiert. Damit liegen dann die zu invertierenden
2036 : : * Rechtecke vor.
2037 : : * Am Ende werden die Flys aus der Region ausgestanzt.
2038 : : */
2039 : :
2040 : 707 : inline void Sub( SwRegionRects& rRegion, const SwRect& rRect )
2041 : : {
2042 [ + + ]: 1375 : if( rRect.Width() > 1 && rRect.Height() > 1 &&
[ + - + + ]
[ + + ]
2043 : 668 : rRect.IsOver( rRegion.GetOrigin() ))
2044 : 638 : rRegion -= rRect;
2045 : 707 : }
2046 : :
2047 : 467 : void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode )
2048 : : {
2049 [ + - ]: 467 : SwPosition *pStartPos = rCrsr.Start(),
2050 : 467 : *pEndPos = rCrsr.GetPoint() == pStartPos ?
2051 [ + + ]: 467 : rCrsr.GetMark() : rCrsr.GetPoint();
2052 : :
2053 : 467 : ViewShell *pSh = GetCurrShell();
2054 : :
2055 : : // #i12836# enhanced pdf
2056 : 467 : SwRegionRects aRegion( pSh && !pSh->GetViewOptions()->IsPDFExport() ?
2057 : : pSh->VisArea() :
2058 [ + - ]: 934 : Frm() );
[ + - + - ]
2059 [ + - ][ + - : 1425 : if( !pStartPos->nNode.GetNode().IsCntntNode() ||
+ + + - ]
[ - + ][ - + ]
2060 [ + - ]: 467 : !pStartPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ||
2061 : 467 : ( pStartPos->nNode != pEndPos->nNode &&
2062 : 12 : ( !pEndPos->nNode.GetNode().IsCntntNode() ||
2063 [ + - ]: 12 : !pEndPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ) ) )
2064 : : {
2065 : 467 : return;
2066 : : }
2067 : :
2068 : : //Erstmal die CntntFrms zum Start und End besorgen, die brauch ich auf
2069 : : //jedenfall.
2070 : 467 : SwCntntFrm const* pStartFrm = pStartPos->nNode.GetNode().
2071 [ + - + - ]: 934 : GetCntntNode()->getLayoutFrm( this, &rCrsr.GetSttPos(), pStartPos );
2072 : :
2073 : 467 : SwCntntFrm const* pEndFrm = pEndPos->nNode.GetNode().
2074 [ + - + - ]: 934 : GetCntntNode()->getLayoutFrm( this, &rCrsr.GetEndPos(), pEndPos );
2075 : :
2076 : : OSL_ENSURE( (pStartFrm && pEndFrm), "Keine CntntFrms gefunden." );
2077 : :
2078 : : //Damit die FlyFrms, in denen selektierte Frames stecken, nicht
2079 : : //abgezogen werden
2080 [ + - ]: 467 : SwSortedObjs aSortObjs;
2081 [ + - ][ - + ]: 467 : if ( pStartFrm->IsInFly() )
2082 : : {
2083 [ # # ][ # # ]: 0 : const SwAnchoredObject* pObj = pStartFrm->FindFlyFrm();
2084 : : OSL_ENSURE( pObj, "No Start Object." );
2085 [ # # ][ # # ]: 0 : if (pObj) aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
2086 [ # # ][ # # ]: 0 : const SwAnchoredObject* pObj2 = pEndFrm->FindFlyFrm();
2087 : : OSL_ENSURE( pObj2, "No Start Object." );
2088 [ # # ][ # # ]: 0 : if (pObj2) aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj2)) );
2089 : : }
2090 : :
2091 : : //Fall 4: Tabellenselection
2092 [ - + ]: 467 : if( bIsTblMode )
2093 : : {
2094 : 0 : const SwFrm *pCell = pStartFrm->GetUpper();
2095 [ # # ]: 0 : while ( !pCell->IsCellFrm() )
2096 : 0 : pCell = pCell->GetUpper();
2097 : 0 : SwRect aTmp( pCell->Prt() );
2098 : 0 : aTmp.Pos() += pCell->Frm().Pos();
2099 : 0 : aRegion.ChangeOrigin( aTmp );
2100 : 0 : aRegion.clear();
2101 [ # # ]: 0 : aRegion.push_back( aTmp);
2102 : : }
2103 : : else
2104 : : {
2105 : : // falls eine nicht erlaubte Selection besteht, dann korrigiere das
2106 : : // nicht erlaubt ist Header/Footer/TableHeadline ueber 2 Seiten
2107 : : do { // middle check loop
2108 : 467 : const SwLayoutFrm* pSttLFrm = pStartFrm->GetUpper();
2109 : 467 : const sal_uInt16 cHdFtTblHd = FRM_HEADER | FRM_FOOTER | FRM_TAB;
2110 [ + + + + ]: 3268 : while( pSttLFrm &&
[ + + ]
2111 : 1401 : ! (cHdFtTblHd & pSttLFrm->GetType() ))
2112 : 1400 : pSttLFrm = pSttLFrm->GetUpper();
2113 [ + + ]: 467 : if( !pSttLFrm )
2114 : 466 : break;
2115 : 1 : const SwLayoutFrm* pEndLFrm = pEndFrm->GetUpper();
2116 [ + - + + ]: 6 : while( pEndLFrm &&
[ + + ]
2117 : 3 : ! (cHdFtTblHd & pEndLFrm->GetType() ))
2118 : 2 : pEndLFrm = pEndLFrm->GetUpper();
2119 [ - + ]: 1 : if( !pEndLFrm )
2120 : 0 : break;
2121 : :
2122 : : OSL_ENSURE( pEndLFrm->GetType() == pSttLFrm->GetType(),
2123 : : "Selection ueber unterschiedliche Inhalte" );
2124 [ - + - ]: 1 : switch( pSttLFrm->GetType() )
2125 : : {
2126 : : case FRM_HEADER:
2127 : : case FRM_FOOTER:
2128 : : // auf unterschiedlichen Seiten ??
2129 : : // dann immer auf die Start-Seite
2130 [ # # ][ # # ]: 0 : if( pEndLFrm->FindPageFrm() != pSttLFrm->FindPageFrm() )
[ # # ]
2131 : : {
2132 : : // End- auf den Start-CntntFrame setzen
2133 [ # # ]: 0 : if( pStartPos == rCrsr.GetPoint() )
2134 : 0 : pEndFrm = pStartFrm;
2135 : : else
2136 : 0 : pStartFrm = pEndFrm;
2137 : : }
2138 : 0 : break;
2139 : : case FRM_TAB:
2140 : : // auf unterschiedlichen Seiten ??
2141 : : // existiert
2142 : : // dann teste auf Tabelle-Headline
2143 : : {
2144 : 1 : const SwTabFrm* pTabFrm = (SwTabFrm*)pSttLFrm;
2145 [ + - - + ]: 2 : if( ( pTabFrm->GetFollow() ||
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ]
2146 : 1 : ((SwTabFrm*)pEndLFrm)->GetFollow() ) &&
2147 [ # # ]: 0 : pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
2148 [ # # ][ # # ]: 0 : pTabFrm->GetLower() != ((SwTabFrm*)pEndLFrm)->GetLower() &&
2149 [ # # ]: 0 : ( lcl_IsInRepeatedHeadline( pStartFrm ) ||
2150 [ # # ]: 0 : lcl_IsInRepeatedHeadline( pEndFrm ) ) )
2151 : : {
2152 : : // End- auf den Start-CntntFrame setzen
2153 [ # # ]: 0 : if( pStartPos == rCrsr.GetPoint() )
2154 : 0 : pEndFrm = pStartFrm;
2155 : : else
2156 : 0 : pStartFrm = pEndFrm;
2157 : : }
2158 : : }
2159 : 1 : break;
2160 : : }
2161 : : } while( sal_False );
2162 : :
2163 : 467 : SwCrsrMoveState aTmpState( MV_NONE );
2164 : 467 : aTmpState.b2Lines = sal_True;
2165 : 467 : aTmpState.bNoScroll = sal_True;
2166 [ - + ][ + - ]: 467 : aTmpState.nCursorBidiLevel = pStartFrm->IsRightToLeft() ? 1 : 0;
2167 : :
2168 : : //CntntRects zu Start- und EndFrms.
2169 : 467 : SwRect aStRect, aEndRect;
2170 [ + - ]: 467 : pStartFrm->GetCharRect( aStRect, *pStartPos, &aTmpState );
2171 : 467 : Sw2LinesPos *pSt2Pos = aTmpState.p2Lines;
2172 : 467 : aTmpState.p2Lines = NULL;
2173 [ + - ][ - + ]: 467 : aTmpState.nCursorBidiLevel = pEndFrm->IsRightToLeft() ? 1 : 0;
2174 : :
2175 [ + - ]: 467 : pEndFrm->GetCharRect ( aEndRect, *pEndPos, &aTmpState );
2176 : 467 : Sw2LinesPos *pEnd2Pos = aTmpState.p2Lines;
2177 : :
2178 [ + - ]: 467 : SwRect aStFrm ( pStartFrm->UnionFrm( sal_True ) );
2179 [ + - ][ + - ]: 467 : aStFrm.Intersection( pStartFrm->PaintArea() );
2180 : : SwRect aEndFrm( pStartFrm == pEndFrm ? aStFrm :
2181 [ + + ][ + - ]: 467 : pEndFrm->UnionFrm( sal_True ) );
2182 [ + + ]: 467 : if( pStartFrm != pEndFrm )
2183 [ + - ][ + - ]: 18 : aEndFrm.Intersection( pEndFrm->PaintArea() );
2184 [ + - ][ - + ]: 467 : SWRECTFN( pStartFrm )
[ # # ][ # # ]
[ - + ]
2185 [ + - ]: 467 : const sal_Bool bR2L = pStartFrm->IsRightToLeft();
2186 [ + - ]: 467 : const sal_Bool bEndR2L = pEndFrm->IsRightToLeft();
2187 : :
2188 : : // If there's no doubleline portion involved or start and end are both
2189 : : // in the same doubleline portion, all works fine, but otherwise
2190 : : // we need the following...
2191 [ + + ][ - + ]: 467 : if( pSt2Pos != pEnd2Pos && ( !pSt2Pos || !pEnd2Pos ||
[ # # # # ]
[ + + ]
2192 : 0 : pSt2Pos->aPortion != pEnd2Pos->aPortion ) )
2193 : : {
2194 : : // If we have a start(end) position inside a doubleline portion
2195 : : // the surrounded part of the doubleline portion is subtracted
2196 : : // from the region and the aStRect(aEndRect) is set to the
2197 : : // end(start) of the doubleline portion.
2198 [ - + ]: 136 : if( pSt2Pos )
2199 : : {
2200 : 0 : SwRect aTmp( aStRect );
2201 : :
2202 : : // BiDi-Portions are swimming against the current.
2203 : : const sal_Bool bPorR2L = ( MT_BIDI == pSt2Pos->nMultiType ) ?
2204 : 0 : ! bR2L :
2205 [ # # ]: 0 : bR2L;
2206 : :
2207 [ # # ][ # # ]: 0 : if( MT_BIDI == pSt2Pos->nMultiType &&
[ # # ]
2208 [ # # ][ # # ]: 0 : (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
2209 : : {
2210 : : // nested bidi portion
2211 [ # # ][ # # ]: 0 : long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
2212 [ # # ][ # # ]: 0 : nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
2213 [ # # ][ # # ]: 0 : long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
2214 : :
2215 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetRight)( nRightAbs );
2216 : :
2217 [ # # ][ # # ]: 0 : if ( ! pEnd2Pos || pEnd2Pos->aPortion != pSt2Pos->aPortion )
[ # # ]
2218 : : {
2219 : 0 : SwRect aTmp2( pSt2Pos->aPortion );
2220 [ # # ][ # # ]: 0 : (aTmp2.*fnRect->fnSetRight)( nLeftAbs );
2221 [ # # ]: 0 : aTmp2.Intersection( aEndFrm );
2222 [ # # ]: 0 : Sub( aRegion, aTmp2 );
2223 : : }
2224 : : }
2225 : : else
2226 : : {
2227 [ # # ]: 0 : if( bPorR2L )
2228 : : (aTmp.*fnRect->fnSetLeft)(
2229 [ # # ][ # # ]: 0 : (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
[ # # ][ # # ]
2230 : : else
2231 : : (aTmp.*fnRect->fnSetRight)(
2232 [ # # ][ # # ]: 0 : (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
[ # # ][ # # ]
2233 : : }
2234 : :
2235 [ # # ][ # # ]: 0 : if( MT_ROT_90 == pSt2Pos->nMultiType ||
[ # # ]
2236 [ # # ][ # # ]: 0 : (pSt2Pos->aPortion.*fnRect->fnGetTop)() ==
2237 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnGetTop)() )
2238 : : {
2239 : : (aTmp.*fnRect->fnSetTop)(
2240 [ # # ][ # # ]: 0 : (pSt2Pos->aLine.*fnRect->fnGetTop)() );
[ # # ][ # # ]
2241 : : }
2242 : :
2243 [ # # ]: 0 : aTmp.Intersection( aStFrm );
2244 [ # # ]: 0 : Sub( aRegion, aTmp );
2245 : :
2246 [ # # ][ # # ]: 0 : SwTwips nTmp = (pSt2Pos->aLine.*fnRect->fnGetBottom)();
2247 [ # # ][ # # ]: 0 : if( MT_ROT_90 != pSt2Pos->nMultiType &&
[ # # ]
2248 [ # # ][ # # ]: 0 : (aStRect.*fnRect->fnBottomDist)( nTmp ) > 0 )
2249 : : {
2250 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetTop)( (aTmp.*fnRect->fnGetBottom)() );
[ # # ][ # # ]
2251 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetBottom)( nTmp );
2252 [ # # ]: 0 : if( (aStRect.*fnRect->fnBottomDist)(
2253 [ # # ][ # # ]: 0 : (pSt2Pos->aPortion.*fnRect->fnGetBottom)() ) > 0 )
[ # # ][ # # ]
2254 : : {
2255 [ # # ]: 0 : if( bPorR2L )
2256 : : (aTmp.*fnRect->fnSetRight)(
2257 [ # # ][ # # ]: 0 : (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
[ # # ][ # # ]
2258 : : else
2259 : : (aTmp.*fnRect->fnSetLeft)(
2260 [ # # ][ # # ]: 0 : (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
[ # # ][ # # ]
2261 : : }
2262 [ # # ]: 0 : aTmp.Intersection( aStFrm );
2263 [ # # ]: 0 : Sub( aRegion, aTmp );
2264 : : }
2265 : :
2266 : 0 : aStRect = pSt2Pos->aLine;
2267 : : (aStRect.*fnRect->fnSetLeft)( bR2L ?
2268 [ # # ]: 0 : (pSt2Pos->aPortion.*fnRect->fnGetLeft)() :
2269 [ # # ][ # # ]: 0 : (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
[ # # ][ # # ]
[ # # ][ # # ]
2270 [ # # ][ # # ]: 0 : (aStRect.*fnRect->fnSetWidth)( 1 );
2271 : : }
2272 : :
2273 [ + - ]: 136 : if( pEnd2Pos )
2274 : : {
2275 [ + - ][ - + ]: 136 : SWRECTFNX( pEndFrm )
[ # # ][ # # ]
[ - + ]
2276 : 136 : SwRect aTmp( aEndRect );
2277 : :
2278 : : // BiDi-Portions are swimming against the current.
2279 : : const sal_Bool bPorR2L = ( MT_BIDI == pEnd2Pos->nMultiType ) ?
2280 : 0 : ! bEndR2L :
2281 [ - + ]: 136 : bEndR2L;
2282 : :
2283 [ - + ][ # # ]: 136 : if( MT_BIDI == pEnd2Pos->nMultiType &&
[ - + ]
2284 [ # # ][ # # ]: 0 : (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
2285 : : {
2286 : : // nested bidi portion
2287 [ # # ][ # # ]: 0 : long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
2288 [ # # ][ # # ]: 0 : nRightAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
2289 [ # # ][ # # ]: 0 : long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
2290 : :
2291 [ # # ][ # # ]: 0 : (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
2292 : :
2293 [ # # ][ # # ]: 0 : if ( ! pSt2Pos || pSt2Pos->aPortion != pEnd2Pos->aPortion )
[ # # ]
2294 : : {
2295 : 0 : SwRect aTmp2( pEnd2Pos->aPortion );
2296 [ # # ][ # # ]: 0 : (aTmp2.*fnRectX->fnSetLeft)( nRightAbs );
2297 [ # # ]: 0 : aTmp2.Intersection( aEndFrm );
2298 [ # # ]: 0 : Sub( aRegion, aTmp2 );
2299 : : }
2300 : : }
2301 : : else
2302 : : {
2303 [ - + ]: 136 : if ( bPorR2L )
2304 : : (aTmp.*fnRectX->fnSetRight)(
2305 [ # # ][ # # ]: 0 : (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
[ # # ][ # # ]
2306 : : else
2307 : : (aTmp.*fnRectX->fnSetLeft)(
2308 [ + - ][ + - ]: 136 : (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
[ + - ][ + - ]
2309 : : }
2310 : :
2311 [ + - ][ + + ]: 272 : if( MT_ROT_90 == pEnd2Pos->nMultiType ||
[ + + ]
2312 [ + - ][ + - ]: 136 : (pEnd2Pos->aPortion.*fnRectX->fnGetBottom)() ==
2313 [ + - ][ + - ]: 136 : (aEndRect.*fnRectX->fnGetBottom)() )
2314 : : {
2315 : : (aTmp.*fnRectX->fnSetBottom)(
2316 [ + - ][ + - ]: 48 : (pEnd2Pos->aLine.*fnRectX->fnGetBottom)() );
[ + - ][ + - ]
2317 : : }
2318 : :
2319 [ + - ]: 136 : aTmp.Intersection( aEndFrm );
2320 [ + - ]: 136 : Sub( aRegion, aTmp );
2321 : :
2322 : : // The next statement means neither ruby nor rotate(90):
2323 [ + + ]: 136 : if( !( MT_RUBY & pEnd2Pos->nMultiType ) )
2324 : : {
2325 [ + - ][ + - ]: 30 : SwTwips nTmp = (pEnd2Pos->aLine.*fnRectX->fnGetTop)();
2326 [ + - ][ + - ]: 30 : if( (aEndRect.*fnRectX->fnGetTop)() != nTmp )
[ + - ]
2327 : : {
2328 : : (aTmp.*fnRectX->fnSetBottom)(
2329 [ + - ][ + - ]: 30 : (aTmp.*fnRectX->fnGetTop)() );
[ + - ][ + - ]
2330 [ + - ][ + - ]: 30 : (aTmp.*fnRectX->fnSetTop)( nTmp );
2331 [ + - ][ + - ]: 60 : if( (aEndRect.*fnRectX->fnGetTop)() !=
[ + - ]
2332 [ + - ][ + - ]: 30 : (pEnd2Pos->aPortion.*fnRectX->fnGetTop)() )
2333 : : {
2334 [ - + ]: 30 : if( bPorR2L )
2335 : : (aTmp.*fnRectX->fnSetLeft)(
2336 [ # # ][ # # ]: 0 : (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
[ # # ][ # # ]
2337 : : else
2338 : : (aTmp.*fnRectX->fnSetRight)(
2339 [ + - ][ + - ]: 30 : (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
[ + - ][ + - ]
2340 : : }
2341 [ + - ]: 30 : aTmp.Intersection( aEndFrm );
2342 [ + - ]: 30 : Sub( aRegion, aTmp );
2343 : : }
2344 : : }
2345 : :
2346 : 136 : aEndRect = pEnd2Pos->aLine;
2347 : : (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ?
2348 [ # # ]: 0 : (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() :
2349 [ - + ][ # # ]: 136 : (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
[ + - ][ + - ]
[ + - ][ + - ]
2350 [ + - ][ + - ]: 136 : (aEndRect.*fnRectX->fnSetWidth)( 1 );
2351 : : }
2352 : : }
2353 [ - + ][ # # ]: 331 : else if( pSt2Pos && pEnd2Pos &&
[ # # ][ # #
# # # # ]
[ - + ]
2354 : : MT_BIDI == pSt2Pos->nMultiType &&
2355 : : MT_BIDI == pEnd2Pos->nMultiType &&
2356 : 0 : pSt2Pos->aPortion == pEnd2Pos->aPortion &&
2357 : 0 : pSt2Pos->aPortion2 != pEnd2Pos->aPortion2 )
2358 : : {
2359 : : // This is the ugly special case, where the selection starts and
2360 : : // ends in the same bidi portion but one start or end is inside a
2361 : : // nested bidi portion.
2362 : :
2363 [ # # ][ # # ]: 0 : if ( (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
[ # # ]
2364 : : {
2365 : 0 : SwRect aTmp( aStRect );
2366 [ # # ][ # # ]: 0 : long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
2367 [ # # ][ # # ]: 0 : nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
2368 [ # # ][ # # ]: 0 : long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
2369 : :
2370 [ # # ][ # # ]: 0 : (aTmp.*fnRect->fnSetRight)( nRightAbs );
2371 [ # # ]: 0 : aTmp.Intersection( aStFrm );
2372 [ # # ]: 0 : Sub( aRegion, aTmp );
2373 : :
2374 : 0 : aStRect = pSt2Pos->aLine;
2375 [ # # ][ # # ]: 0 : (aStRect.*fnRect->fnSetLeft)( bR2L ? nRightAbs : nLeftAbs );
[ # # ]
2376 [ # # ][ # # ]: 0 : (aStRect.*fnRect->fnSetWidth)( 1 );
2377 : : }
2378 : :
2379 [ # # ][ # # ]: 0 : SWRECTFNX( pEndFrm )
[ # # ][ # # ]
[ # # ]
2380 [ # # ][ # # ]: 0 : if ( (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
[ # # ]
2381 : : {
2382 : 0 : SwRect aTmp( aEndRect );
2383 [ # # ][ # # ]: 0 : long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
2384 [ # # ][ # # ]: 0 : nRightAbs -= (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
2385 [ # # ][ # # ]: 0 : long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
2386 : :
2387 [ # # ][ # # ]: 0 : (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
2388 [ # # ]: 0 : aTmp.Intersection( aEndFrm );
2389 [ # # ]: 0 : Sub( aRegion, aTmp );
2390 : :
2391 : 0 : aEndRect = pEnd2Pos->aLine;
2392 [ # # ][ # # ]: 0 : (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ? nLeftAbs : nRightAbs );
[ # # ]
2393 [ # # ][ # # ]: 0 : (aEndRect.*fnRectX->fnSetWidth)( 1 );
2394 : : }
2395 : : }
2396 : :
2397 : : // The charrect may be outside the paintarea (for cursortravelling)
2398 : : // but the selection has to be restricted to the paintarea
2399 [ + + ]: 467 : if( aStRect.Left() < aStFrm.Left() )
2400 : 2 : aStRect.Left( aStFrm.Left() );
2401 [ - + ]: 465 : else if( aStRect.Left() > aStFrm.Right() )
2402 : 0 : aStRect.Left( aStFrm.Right() );
2403 : 467 : SwTwips nTmp = aStRect.Right();
2404 [ + + ]: 467 : if( nTmp < aStFrm.Left() )
2405 : 2 : aStRect.Right( aStFrm.Left() );
2406 [ - + ]: 465 : else if( nTmp > aStFrm.Right() )
2407 : 0 : aStRect.Right( aStFrm.Right() );
2408 [ + + ]: 467 : if( aEndRect.Left() < aEndFrm.Left() )
2409 : 2 : aEndRect.Left( aEndFrm.Left() );
2410 [ - + ]: 465 : else if( aEndRect.Left() > aEndFrm.Right() )
2411 : 0 : aEndRect.Left( aEndFrm.Right() );
2412 : 467 : nTmp = aEndRect.Right();
2413 [ + + ]: 467 : if( nTmp < aEndFrm.Left() )
2414 : 2 : aEndRect.Right( aEndFrm.Left() );
2415 [ - + ]: 465 : else if( nTmp > aEndFrm.Right() )
2416 : 0 : aEndRect.Right( aEndFrm.Right() );
2417 : :
2418 [ + + ]: 467 : if( pStartFrm == pEndFrm )
2419 : : {
2420 : : sal_Bool bSameRotatedOrBidi = pSt2Pos && pEnd2Pos &&
2421 : : ( MT_BIDI & pSt2Pos->nMultiType ) &&
2422 [ - + ][ # # ]: 449 : pSt2Pos->aPortion == pEnd2Pos->aPortion;
[ # # ][ # # ]
2423 : : //case 1: (Same frame and same row)
2424 [ + - ][ + + ]: 898 : if( bSameRotatedOrBidi ||
[ + + ]
2425 [ + - ][ + - ]: 449 : (aStRect.*fnRect->fnGetTop)() == (aEndRect.*fnRect->fnGetTop)() )
[ + - ][ + - ]
2426 : : {
2427 : 439 : Point aTmpSt( aStRect.Pos() );
2428 : 439 : Point aTmpEnd( aEndRect.Right(), aEndRect.Bottom() );
2429 [ - + ][ + - ]: 439 : if( bSameRotatedOrBidi || bR2L )
2430 : : {
2431 [ # # ]: 0 : if( aTmpSt.Y() > aTmpEnd.Y() )
2432 : : {
2433 : 0 : long nTmpY = aTmpEnd.Y();
2434 : 0 : aTmpEnd.Y() = aTmpSt.Y();
2435 : 0 : aTmpSt.Y() = nTmpY;
2436 : : }
2437 [ # # ]: 0 : if( aTmpSt.X() > aTmpEnd.X() )
2438 : : {
2439 : 0 : long nTmpX = aTmpEnd.X();
2440 : 0 : aTmpEnd.X() = aTmpSt.X();
2441 : 0 : aTmpSt.X() = nTmpX;
2442 : : }
2443 : : }
2444 : :
2445 : 439 : SwRect aTmp = SwRect( aTmpSt, aTmpEnd );
2446 : : // Bug 34888: falls Inhalt selektiert ist, der keinen Platz
2447 : : // einnimmt (z.B. PostIts,RefMarks, TOXMarks),
2448 : : // dann mindestens die Breite des Crsr setzen.
2449 [ + - ]: 590 : if( 1 == (aTmp.*fnRect->fnGetWidth)() &&
[ + + + + ]
[ + + ][ + - ]
2450 : 151 : pStartPos->nContent.GetIndex() !=
2451 : 151 : pEndPos->nContent.GetIndex() )
2452 : : {
2453 : 138 : OutputDevice* pOut = pSh->GetOut();
2454 : 138 : long nCrsrWidth = pOut->GetSettings().GetStyleSettings().
2455 : 138 : GetCursorSize();
2456 : : (aTmp.*fnRect->fnSetWidth)( pOut->PixelToLogic(
2457 [ + - ][ + - ]: 138 : Size( nCrsrWidth, 0 ) ).Width() );
[ + - ]
2458 : : }
2459 [ + - ]: 439 : aTmp.Intersection( aStFrm );
2460 [ + - ]: 439 : Sub( aRegion, aTmp );
2461 : : }
2462 : : //case 2: (Same frame, but not the same line)
2463 : : else
2464 : : {
2465 : : SwTwips lLeft, lRight;
2466 [ - + ][ # # ]: 10 : if( pSt2Pos && pEnd2Pos && pSt2Pos->aPortion == pEnd2Pos->aPortion )
[ # # ][ - + ]
2467 : : {
2468 [ # # ][ # # ]: 0 : lLeft = (pSt2Pos->aPortion.*fnRect->fnGetLeft)();
2469 [ # # ][ # # ]: 0 : lRight = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
2470 : : }
2471 : : else
2472 : : {
2473 [ + - ][ + - ]: 10 : lLeft = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
2474 [ + - ][ + - ]: 10 : (pStartFrm->Prt().*fnRect->fnGetLeft)();
2475 [ + - ][ + - ]: 10 : lRight = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
2476 [ + - ][ + - ]: 10 : (pStartFrm->Prt().*fnRect->fnGetRight)();
2477 : : }
2478 [ + - ][ + - ]: 10 : if( lLeft < (aStFrm.*fnRect->fnGetLeft)() )
[ - + ]
2479 [ # # ][ # # ]: 0 : lLeft = (aStFrm.*fnRect->fnGetLeft)();
2480 [ + - ][ + - ]: 10 : if( lRight > (aStFrm.*fnRect->fnGetRight)() )
[ - + ]
2481 [ # # ][ # # ]: 0 : lRight = (aStFrm.*fnRect->fnGetRight)();
2482 : 10 : SwRect aSubRect( aStRect );
2483 : : //First line
2484 [ - + ]: 10 : if( bR2L )
2485 [ # # ][ # # ]: 0 : (aSubRect.*fnRect->fnSetLeft)( lLeft );
2486 : : else
2487 [ + - ][ + - ]: 10 : (aSubRect.*fnRect->fnSetRight)( lRight );
2488 [ + - ]: 10 : Sub( aRegion, aSubRect );
2489 : :
2490 : : //If there's at least a twips between start- and endline,
2491 : : //so the whole area between will be added.
2492 [ + - ][ + - ]: 10 : SwTwips aTmpBottom = (aStRect.*fnRect->fnGetBottom)();
2493 [ + - ][ + - ]: 10 : SwTwips aTmpTop = (aEndRect.*fnRect->fnGetTop)();
2494 [ + - ]: 10 : if( aTmpBottom != aTmpTop )
2495 : : {
2496 [ + - ][ + - ]: 10 : (aSubRect.*fnRect->fnSetLeft)( lLeft );
2497 [ + - ][ + - ]: 10 : (aSubRect.*fnRect->fnSetRight)( lRight );
2498 [ + - ][ + - ]: 10 : (aSubRect.*fnRect->fnSetTop)( aTmpBottom );
2499 [ + - ][ + - ]: 10 : (aSubRect.*fnRect->fnSetBottom)( aTmpTop );
2500 [ + - ]: 10 : Sub( aRegion, aSubRect );
2501 : : }
2502 : : //and the last line
2503 : 10 : aSubRect = aEndRect;
2504 [ - + ]: 10 : if( bR2L )
2505 [ # # ][ # # ]: 0 : (aSubRect.*fnRect->fnSetRight)( lRight );
2506 : : else
2507 [ + - ][ + - ]: 10 : (aSubRect.*fnRect->fnSetLeft)( lLeft );
2508 [ + - ]: 10 : Sub( aRegion, aSubRect );
2509 : : }
2510 : : }
2511 : : //case 3: (Different frames, maybe with ohther frames between
2512 : : else
2513 : : {
2514 : : //The startframe first...
2515 : 18 : SwRect aSubRect( aStRect );
2516 [ - + ]: 18 : if( bR2L )
2517 [ # # ][ # # ]: 0 : (aSubRect.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)());
[ # # ][ # # ]
2518 : : else
2519 [ + - ][ + - ]: 18 : (aSubRect.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)());
[ + - ][ + - ]
2520 [ + - ]: 18 : Sub( aRegion, aSubRect );
2521 [ + - ][ + - ]: 18 : SwTwips nTmpTwips = (aStRect.*fnRect->fnGetBottom)();
2522 [ + - ][ + - ]: 18 : if( (aStFrm.*fnRect->fnGetBottom)() != nTmpTwips )
[ + + ]
2523 : : {
2524 : 14 : aSubRect = aStFrm;
2525 [ + - ][ + - ]: 14 : (aSubRect.*fnRect->fnSetTop)( nTmpTwips );
2526 [ + - ]: 14 : Sub( aRegion, aSubRect );
2527 : : }
2528 : :
2529 : : //Now the frames between, if there are any
2530 [ + - ]: 18 : sal_Bool bBody = pStartFrm->IsInDocBody();
2531 : 18 : const SwTableBox* pCellBox = pStartFrm->GetUpper()->IsCellFrm() ?
2532 [ - + ]: 18 : ((SwCellFrm*)pStartFrm->GetUpper())->GetTabBox() : 0;
2533 [ + - ]: 18 : const SwCntntFrm *pCntnt = pStartFrm->GetNextCntntFrm();
2534 : 18 : SwRect aPrvRect;
2535 : :
2536 : : // #123908# - introduce robust code
2537 : : // The stacktrace issue reveals that <pCntnt> could be NULL.
2538 : : // One root cause found by AMA - see #130650#
2539 : : OSL_ENSURE( pCntnt,
2540 : : "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
2541 [ + - ][ + + ]: 116 : while ( pCntnt && pCntnt != pEndFrm )
[ + + ]
2542 : : {
2543 [ + - ][ - + ]: 98 : if ( pCntnt->IsInFly() )
2544 : : {
2545 [ # # ][ # # ]: 0 : const SwAnchoredObject* pObj = pCntnt->FindFlyFrm();
2546 [ # # ]: 0 : aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
2547 : : }
2548 : :
2549 : : // Consider only frames which have the same IsInDocBody value like pStartFrm
2550 : : // If pStartFrm is inside a SwCellFrm, consider only frames which are inside the
2551 : : // same cell frame (or its follow cell)
2552 : 98 : const SwTableBox* pTmpCellBox = pCntnt->GetUpper()->IsCellFrm() ?
2553 [ - + ]: 98 : ((SwCellFrm*)pCntnt->GetUpper())->GetTabBox() : 0;
2554 [ + - ][ + - ]: 98 : if ( bBody == pCntnt->IsInDocBody() &&
[ - + ][ # # ]
[ + - ]
2555 : : ( !pCellBox || pCellBox == pTmpCellBox ) )
2556 : : {
2557 [ + - ]: 98 : SwRect aCRect( pCntnt->UnionFrm( sal_True ) );
2558 [ + - ][ + - ]: 98 : aCRect.Intersection( pCntnt->PaintArea() );
2559 [ + - ][ + + ]: 98 : if( aCRect.IsOver( aRegion.GetOrigin() ))
2560 : : {
2561 : 16 : SwRect aTmp( aPrvRect );
2562 [ + - ]: 16 : aTmp.Union( aCRect );
2563 [ - + ]: 32 : if ( (aPrvRect.Height() * aPrvRect.Width() +
2564 : 16 : aCRect.Height() * aCRect.Width()) ==
2565 : 16 : (aTmp.Height() * aTmp.Width()) )
2566 : : {
2567 [ # # ]: 0 : aPrvRect.Union( aCRect );
2568 : : }
2569 : : else
2570 : : {
2571 [ + - ][ + + ]: 16 : if ( aPrvRect.HasArea() )
2572 [ + - ]: 8 : Sub( aRegion, aPrvRect );
2573 : 98 : aPrvRect = aCRect;
2574 : : }
2575 : : }
2576 : : }
2577 [ + - ]: 98 : pCntnt = pCntnt->GetNextCntntFrm();
2578 : : // #123908#
2579 : : OSL_ENSURE( pCntnt,
2580 : : "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
2581 : : }
2582 [ + - ][ + + ]: 18 : if ( aPrvRect.HasArea() )
2583 [ + - ]: 8 : Sub( aRegion, aPrvRect );
2584 : :
2585 : : //At least the endframe...
2586 [ + - ]: 18 : bVert = pEndFrm->IsVertical();
2587 : 18 : bRev = pEndFrm->IsReverse();
2588 : : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
2589 : 0 : fnRect = bVert ? ( bRev ? fnRectVL2R : ( pEndFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) ) :
2590 [ # # # # ]: 18 : ( bRev ? fnRectB2T : fnRectHori );
[ - + ][ - + ]
2591 [ + - ][ + - ]: 18 : nTmpTwips = (aEndRect.*fnRect->fnGetTop)();
2592 [ + - ][ + - ]: 18 : if( (aEndFrm.*fnRect->fnGetTop)() != nTmpTwips )
[ + + ]
2593 : : {
2594 : 6 : aSubRect = aEndFrm;
2595 [ + - ][ + - ]: 6 : (aSubRect.*fnRect->fnSetBottom)( nTmpTwips );
2596 [ + - ]: 6 : Sub( aRegion, aSubRect );
2597 : : }
2598 : 18 : aSubRect = aEndRect;
2599 [ - + ]: 18 : if( bEndR2L )
2600 [ # # ][ # # ]: 0 : (aSubRect.*fnRect->fnSetRight)((aEndFrm.*fnRect->fnGetRight)());
[ # # ][ # # ]
2601 : : else
2602 [ + - ][ + - ]: 18 : (aSubRect.*fnRect->fnSetLeft)( (aEndFrm.*fnRect->fnGetLeft)() );
[ + - ][ + - ]
2603 [ + - ]: 18 : Sub( aRegion, aSubRect );
2604 : : }
2605 : :
2606 : : // aRegion.Compress( sal_False );
2607 [ + - ]: 467 : aRegion.Invert();
2608 : 467 : delete pSt2Pos;
2609 : 467 : delete pEnd2Pos;
2610 : : }
2611 : :
2612 : : //Flys mit Durchlauf ausstanzen. Nicht ausgestanzt werden Flys:
2613 : : //- die Lower des StartFrm/EndFrm sind (FlyInCnt und alle Flys die wiederum
2614 : : // darin sitzen)
2615 : : //- in der Z-Order ueber denjenigen Flys stehen in denen sich der StartFrm
2616 : : // befindet.
2617 [ + - ]: 467 : const SwPageFrm *pPage = pStartFrm->FindPageFrm();
2618 [ + - ]: 467 : const SwPageFrm *pEndPage = pEndFrm->FindPageFrm();
2619 : :
2620 [ + - ]: 495 : while ( pPage )
2621 : : {
2622 [ - + ]: 495 : if ( pPage->GetSortedObjs() )
2623 : : {
2624 : 0 : const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
2625 [ # # ][ # # ]: 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2626 : : {
2627 [ # # ]: 0 : SwAnchoredObject* pAnchoredObj = rObjs[i];
2628 [ # # ][ # # ]: 0 : if ( !pAnchoredObj->ISA(SwFlyFrm) )
[ # # ]
2629 : 0 : continue;
2630 [ # # ]: 0 : const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
2631 [ # # ]: 0 : const SwVirtFlyDrawObj* pObj = pFly->GetVirtDrawObj();
2632 [ # # ][ # # ]: 0 : const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
2633 [ # # ][ # # : 0 : if ( !pFly->IsAnLower( pStartFrm ) &&
# # # # ]
[ # # ]
2634 : 0 : (rSur.GetSurround() != SURROUND_THROUGHT &&
2635 : 0 : !rSur.IsContour()) )
2636 : : {
2637 [ # # ][ # # ]: 0 : if ( aSortObjs.Contains( *pAnchoredObj ) )
2638 : 0 : continue;
2639 : :
2640 : 0 : sal_Bool bSub = sal_True;
2641 [ # # ]: 0 : const sal_uInt32 nPos = pObj->GetOrdNum();
2642 [ # # ][ # # ]: 0 : for ( sal_uInt16 k = 0; bSub && k < aSortObjs.Count(); ++k )
[ # # ][ # # ]
2643 : : {
2644 : : OSL_ENSURE( aSortObjs[k]->ISA(SwFlyFrm),
2645 : : "<SwRootFrm::CalcFrmRects(..)> - object in <aSortObjs> of unexcepted type" );
2646 [ # # ][ # # ]: 0 : const SwFlyFrm* pTmp = static_cast<SwFlyFrm*>(aSortObjs[k]);
2647 [ # # ][ # # ]: 0 : do
[ # # ]
2648 [ # # ][ # # ]: 0 : { if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() )
[ # # ]
2649 : 0 : bSub = sal_False;
2650 : : else
2651 [ # # ][ # # ]: 0 : pTmp = pTmp->GetAnchorFrm()->FindFlyFrm();
2652 : : } while ( bSub && pTmp );
2653 : : }
2654 [ # # ]: 0 : if ( bSub )
2655 [ # # ]: 0 : Sub( aRegion, pFly->Frm() );
2656 : : }
2657 : : }
2658 : : }
2659 [ + + ]: 495 : if ( pPage == pEndPage )
2660 : 467 : break;
2661 : : else
2662 : 28 : pPage = (SwPageFrm*)pPage->GetNext();
2663 : : }
2664 : :
2665 : : //Weil's besser aussieht noch die DropCaps ausschliessen.
2666 : 467 : SwRect aDropRect;
2667 [ + - ]: 467 : if ( pStartFrm->IsTxtFrm() )
2668 : : {
2669 [ + - ][ - + ]: 467 : if ( ((SwTxtFrm*)pStartFrm)->GetDropRect( aDropRect ) )
2670 [ # # ]: 0 : Sub( aRegion, aDropRect );
2671 : : }
2672 [ + + ][ + - ]: 467 : if ( pEndFrm != pStartFrm && pEndFrm->IsTxtFrm() )
[ + + ]
2673 : : {
2674 [ + - ][ - + ]: 18 : if ( ((SwTxtFrm*)pEndFrm)->GetDropRect( aDropRect ) )
2675 [ # # ]: 0 : Sub( aRegion, aDropRect );
2676 : : }
2677 : :
2678 [ + - ][ + - ]: 467 : rCrsr.assign( aRegion.begin(), aRegion.end() );
[ + - ]
2679 : : }
2680 : :
2681 : :
2682 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|