xref: /aoo41x/main/sw/source/core/text/frmcrsr.cxx (revision efeef26f)
1*efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*efeef26fSAndrew Rist  * distributed with this work for additional information
6*efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9*efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*efeef26fSAndrew Rist  *
11*efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*efeef26fSAndrew Rist  *
13*efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15*efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17*efeef26fSAndrew Rist  * specific language governing permissions and limitations
18*efeef26fSAndrew Rist  * under the License.
19*efeef26fSAndrew Rist  *
20*efeef26fSAndrew Rist  *************************************************************/
21*efeef26fSAndrew Rist 
22*efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include "ndtxt.hxx"		// GetNode()
29cdf0e10cSrcweir #include "pam.hxx"			// SwPosition
30cdf0e10cSrcweir #include "frmtool.hxx"
31cdf0e10cSrcweir #include "viewopt.hxx"
32cdf0e10cSrcweir #include "paratr.hxx"
33cdf0e10cSrcweir #include "rootfrm.hxx"
34cdf0e10cSrcweir #include "pagefrm.hxx"
35cdf0e10cSrcweir #include "colfrm.hxx"
36cdf0e10cSrcweir #include "txttypes.hxx"
37cdf0e10cSrcweir #include <sfx2/printer.hxx>
38cdf0e10cSrcweir #include <editeng/lrspitem.hxx>
39cdf0e10cSrcweir #include <editeng/tstpitem.hxx>
40cdf0e10cSrcweir #include <editeng/ulspitem.hxx>
41cdf0e10cSrcweir #include <editeng/lspcitem.hxx>
42cdf0e10cSrcweir #include <pormulti.hxx>     // SwMultiPortion
43cdf0e10cSrcweir #include <doc.hxx>
44cdf0e10cSrcweir #include <sortedobjs.hxx>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir #include <unicode/ubidi.h>
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include "txtcfg.hxx"
49cdf0e10cSrcweir #include "txtfrm.hxx"		// SwTxtFrm
50cdf0e10cSrcweir #include "inftxt.hxx"		// SwTxtSizeInfo
51cdf0e10cSrcweir #include "itrtxt.hxx"		// SwTxtCursor
52cdf0e10cSrcweir #include "crstate.hxx"		// SwTxtCursor
53cdf0e10cSrcweir #include "viewsh.hxx"		// InvalidateWindows
54cdf0e10cSrcweir #include "swfntcch.hxx"		// SwFontAccess
55cdf0e10cSrcweir #include "flyfrm.hxx"
56cdf0e10cSrcweir 
57cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
58cdf0e10cSrcweir #include "txtpaint.hxx"
59cdf0e10cSrcweir #endif
60cdf0e10cSrcweir 
61cdf0e10cSrcweir #define MIN_OFFSET_STEP 10
62cdf0e10cSrcweir 
63cdf0e10cSrcweir using namespace ::com::sun::star;
64cdf0e10cSrcweir 
65cdf0e10cSrcweir 
66cdf0e10cSrcweir /*
67cdf0e10cSrcweir  * 1170-SurvivalKit: Wie gelangt man hinter das letzte Zeichen der Zeile.
68cdf0e10cSrcweir  * - RightMargin verzichtet auf den Positionsausgleich mit -1
69cdf0e10cSrcweir  * - GetCharRect liefert bei MV_RIGHTMARGIN ein GetEndCharRect
70cdf0e10cSrcweir  * - GetEndCharRect setzt bRightMargin auf sal_True
71cdf0e10cSrcweir  * - SwTxtCursor::bRightMargin wird per CharCrsrToLine auf sal_False gesetzt
72cdf0e10cSrcweir  */
73cdf0e10cSrcweir 
74cdf0e10cSrcweir /*************************************************************************
75cdf0e10cSrcweir  *						GetAdjFrmAtPos()
76cdf0e10cSrcweir  *************************************************************************/
77cdf0e10cSrcweir 
GetAdjFrmAtPos(SwTxtFrm * pFrm,const SwPosition & rPos,const sal_Bool bRightMargin,const sal_Bool bNoScroll=sal_True)78cdf0e10cSrcweir SwTxtFrm *GetAdjFrmAtPos( SwTxtFrm *pFrm, const SwPosition &rPos,
79cdf0e10cSrcweir                           const sal_Bool bRightMargin, const sal_Bool bNoScroll = sal_True )
80cdf0e10cSrcweir {
81cdf0e10cSrcweir 	// 8810: vgl. 1170, RightMargin in der letzten Masterzeile...
82cdf0e10cSrcweir 	const xub_StrLen nOffset = rPos.nContent.GetIndex();
83cdf0e10cSrcweir     SwTxtFrm *pFrmAtPos = pFrm;
84cdf0e10cSrcweir     if( !bNoScroll || pFrm->GetFollow() )
85cdf0e10cSrcweir     {
86cdf0e10cSrcweir         pFrmAtPos = pFrm->GetFrmAtPos( rPos );
87cdf0e10cSrcweir         if( nOffset < pFrmAtPos->GetOfst() &&
88cdf0e10cSrcweir             !pFrmAtPos->IsFollow() )
89cdf0e10cSrcweir         {
90cdf0e10cSrcweir             xub_StrLen nNew = nOffset;
91cdf0e10cSrcweir             if( nNew < MIN_OFFSET_STEP )
92cdf0e10cSrcweir                 nNew = 0;
93cdf0e10cSrcweir             else
94cdf0e10cSrcweir                 nNew -= MIN_OFFSET_STEP;
95cdf0e10cSrcweir             lcl_ChangeOffset( pFrmAtPos, nNew );
96cdf0e10cSrcweir         }
97cdf0e10cSrcweir     }
98cdf0e10cSrcweir 	while( pFrm != pFrmAtPos )
99cdf0e10cSrcweir 	{
100cdf0e10cSrcweir 		pFrm = pFrmAtPos;
101cdf0e10cSrcweir 		pFrm->GetFormatted();
102cdf0e10cSrcweir 		pFrmAtPos = (SwTxtFrm*)pFrm->GetFrmAtPos( rPos );
103cdf0e10cSrcweir 	}
104cdf0e10cSrcweir 
105cdf0e10cSrcweir 	if( nOffset && bRightMargin )
106cdf0e10cSrcweir 	{
107cdf0e10cSrcweir         while( pFrmAtPos && pFrmAtPos->GetOfst() == nOffset &&
108cdf0e10cSrcweir                pFrmAtPos->IsFollow() )
109cdf0e10cSrcweir 		{
110cdf0e10cSrcweir 			pFrmAtPos->GetFormatted();
111cdf0e10cSrcweir 			pFrmAtPos = pFrmAtPos->FindMaster();
112cdf0e10cSrcweir 		}
113cdf0e10cSrcweir 		ASSERT( pFrmAtPos, "+GetCharRect: no frame with my rightmargin" );
114cdf0e10cSrcweir 	}
115cdf0e10cSrcweir 	return pFrmAtPos ? pFrmAtPos : pFrm;
116cdf0e10cSrcweir }
117cdf0e10cSrcweir 
lcl_ChangeOffset(SwTxtFrm * pFrm,xub_StrLen nNew)118cdf0e10cSrcweir sal_Bool lcl_ChangeOffset( SwTxtFrm* pFrm, xub_StrLen nNew )
119cdf0e10cSrcweir {
120cdf0e10cSrcweir 	// In Bereichen und ausserhalb von Flies wird nicht mehr gescrollt.
121cdf0e10cSrcweir 	ASSERT( !pFrm->IsFollow(), "Illegal Scrolling by Follow!" );
122cdf0e10cSrcweir 	if( pFrm->GetOfst() != nNew && !pFrm->IsInSct() )
123cdf0e10cSrcweir 	{
124cdf0e10cSrcweir 		SwFlyFrm *pFly = pFrm->FindFlyFrm();
125cdf0e10cSrcweir 		// Vorsicht, wenn z.B. bei einem spaltigen Rahmen die Groesse noch invalide ist,
126cdf0e10cSrcweir 		// duerfen wir nicht mal eben herumscrollen
127cdf0e10cSrcweir 		if ( ( pFly && pFly->IsValid() &&
128cdf0e10cSrcweir 			 !pFly->GetNextLink() && !pFly->GetPrevLink() ) ||
129cdf0e10cSrcweir 			 ( !pFly && pFrm->IsInTab() ) )
130cdf0e10cSrcweir 		{
131cdf0e10cSrcweir 			ViewShell* pVsh = pFrm->getRootFrm()->GetCurrShell();
132cdf0e10cSrcweir 			if( pVsh )
133cdf0e10cSrcweir 			{
134cdf0e10cSrcweir 				if( pVsh->GetNext() != pVsh ||
135cdf0e10cSrcweir 					( pFrm->GetDrawObjs() && pFrm->GetDrawObjs()->Count() ) )
136cdf0e10cSrcweir 				{
137cdf0e10cSrcweir 					if( !pFrm->GetOfst() )
138cdf0e10cSrcweir 						return sal_False;
139cdf0e10cSrcweir 					nNew = 0;
140cdf0e10cSrcweir 				}
141cdf0e10cSrcweir 				pFrm->SetOfst( nNew );
142cdf0e10cSrcweir 				pFrm->SetPara( 0 );
143cdf0e10cSrcweir 				pFrm->GetFormatted();
144cdf0e10cSrcweir 				if( pFrm->Frm().HasArea() )
145cdf0e10cSrcweir 					pFrm->getRootFrm()->GetCurrShell()->InvalidateWindows( pFrm->Frm() );
146cdf0e10cSrcweir 				return sal_True;
147cdf0e10cSrcweir 			}
148cdf0e10cSrcweir 		}
149cdf0e10cSrcweir 	}
150cdf0e10cSrcweir 	return sal_False;
151cdf0e10cSrcweir }
152cdf0e10cSrcweir 
153cdf0e10cSrcweir /*************************************************************************
154cdf0e10cSrcweir  *						GetFrmAtOfst(), GetFrmAtPos()
155cdf0e10cSrcweir  *************************************************************************/
156cdf0e10cSrcweir 
157cdf0e10cSrcweir // OD 07.10.2003 #110978#
GetFrmAtOfst(const xub_StrLen nWhere)158cdf0e10cSrcweir SwTxtFrm& SwTxtFrm::GetFrmAtOfst( const xub_StrLen nWhere )
159cdf0e10cSrcweir {
160cdf0e10cSrcweir     SwTxtFrm* pRet = this;
161cdf0e10cSrcweir 	while( pRet->HasFollow() && nWhere >= pRet->GetFollow()->GetOfst() )
162cdf0e10cSrcweir 		pRet = pRet->GetFollow();
163cdf0e10cSrcweir     return *pRet;
164cdf0e10cSrcweir }
165cdf0e10cSrcweir 
GetFrmAtPos(const SwPosition & rPos)166cdf0e10cSrcweir SwTxtFrm *SwTxtFrm::GetFrmAtPos( const SwPosition &rPos )
167cdf0e10cSrcweir {
168cdf0e10cSrcweir 	SwTxtFrm *pFoll = (SwTxtFrm*)this;
169cdf0e10cSrcweir 	while( pFoll->GetFollow() )
170cdf0e10cSrcweir 	{
171cdf0e10cSrcweir 		if( rPos.nContent.GetIndex() > pFoll->GetFollow()->GetOfst() )
172cdf0e10cSrcweir 			pFoll = pFoll->GetFollow();
173cdf0e10cSrcweir 		else
174cdf0e10cSrcweir 		{
175cdf0e10cSrcweir 			if( rPos.nContent.GetIndex() == pFoll->GetFollow()->GetOfst()
176cdf0e10cSrcweir 				 && !SwTxtCursor::IsRightMargin() )
177cdf0e10cSrcweir 				 pFoll = pFoll->GetFollow();
178cdf0e10cSrcweir 			else
179cdf0e10cSrcweir 				break;
180cdf0e10cSrcweir 		}
181cdf0e10cSrcweir 	}
182cdf0e10cSrcweir 	return pFoll;
183cdf0e10cSrcweir }
184cdf0e10cSrcweir 
185cdf0e10cSrcweir /*************************************************************************
186cdf0e10cSrcweir  *						SwTxtFrm::GetCharRect()
187cdf0e10cSrcweir  *************************************************************************/
188cdf0e10cSrcweir 
189cdf0e10cSrcweir /*
190cdf0e10cSrcweir  * GetCharRect() findet die Characterzelle des Characters, dass
191cdf0e10cSrcweir  * durch aPos beschrieben wird. GetCrsrOfst() findet den
192cdf0e10cSrcweir  * umgekehrten Weg: Von einer Dokumentkoordinate zu einem Pam.
193cdf0e10cSrcweir  * Beide sind virtuell in der Framebasisklasse und werden deshalb
194cdf0e10cSrcweir  * immer angezogen.
195cdf0e10cSrcweir  */
196cdf0e10cSrcweir 
GetCharRect(SwRect & rOrig,const SwPosition & rPos,SwCrsrMoveState * pCMS) const197cdf0e10cSrcweir sal_Bool SwTxtFrm::GetCharRect( SwRect& rOrig, const SwPosition &rPos,
198cdf0e10cSrcweir 							SwCrsrMoveState *pCMS ) const
199cdf0e10cSrcweir {
200cdf0e10cSrcweir     ASSERT( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::GetCharRect with swapped frame" );
201cdf0e10cSrcweir 
202cdf0e10cSrcweir     if( IsLocked() || IsHiddenNow() )
203cdf0e10cSrcweir 		return sal_False;
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 	//Erstmal den richtigen Frm finden, dabei muss beachtet werden, dass:
206cdf0e10cSrcweir 	//- die gecachten Informationen verworfen sein koennen (GetPara() == 0)
207cdf0e10cSrcweir 	//- das ein Follow gemeint sein kann
208cdf0e10cSrcweir 	//- das die Kette der Follows dynamisch waechst; der in den wir
209cdf0e10cSrcweir 	//	schliesslich gelangen muss aber Formatiert sein.
210cdf0e10cSrcweir 
211cdf0e10cSrcweir 	// opt: reading ahead erspart uns ein GetAdjFrmAtPos
212cdf0e10cSrcweir 	const sal_Bool bRightMargin = pCMS && ( MV_RIGHTMARGIN == pCMS->eState );
213cdf0e10cSrcweir     const sal_Bool bNoScroll = pCMS && pCMS->bNoScroll;
214cdf0e10cSrcweir     SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, rPos, bRightMargin,
215cdf0e10cSrcweir                                      bNoScroll );
216cdf0e10cSrcweir 	pFrm->GetFormatted();
217cdf0e10cSrcweir 	const SwFrm* pTmpFrm = (SwFrm*)pFrm->GetUpper();
218cdf0e10cSrcweir 
219cdf0e10cSrcweir     SWRECTFN ( pFrm )
220cdf0e10cSrcweir     const SwTwips nUpperMaxY = (pTmpFrm->*fnRect->fnGetPrtBottom)();
221cdf0e10cSrcweir     const SwTwips nFrmMaxY = (pFrm->*fnRect->fnGetPrtBottom)();
222cdf0e10cSrcweir 
223cdf0e10cSrcweir     // nMaxY is an absolute value
224cdf0e10cSrcweir     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
225cdf0e10cSrcweir 	SwTwips nMaxY = bVert ?
226cdf0e10cSrcweir                     ( bVertL2R ? Min( nFrmMaxY, nUpperMaxY ) : Max( nFrmMaxY, nUpperMaxY ) ) :
227cdf0e10cSrcweir                     Min( nFrmMaxY, nUpperMaxY );
228cdf0e10cSrcweir 
229cdf0e10cSrcweir     sal_Bool bRet = sal_False;
230cdf0e10cSrcweir 
231cdf0e10cSrcweir     if ( pFrm->IsEmpty() || ! (pFrm->Prt().*fnRect->fnGetHeight)() )
232cdf0e10cSrcweir 	{
233cdf0e10cSrcweir 		Point aPnt1 = pFrm->Frm().Pos() + pFrm->Prt().Pos();
234cdf0e10cSrcweir 		SwTxtNode* pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
235cdf0e10cSrcweir 		short nFirstOffset;
236cdf0e10cSrcweir 		pTxtNd->GetFirstLineOfsWithNum( nFirstOffset );
237cdf0e10cSrcweir 
238cdf0e10cSrcweir         Point aPnt2;
239cdf0e10cSrcweir         if ( bVert )
240cdf0e10cSrcweir         {
241cdf0e10cSrcweir             if( nFirstOffset > 0 )
242cdf0e10cSrcweir                 aPnt1.Y() += nFirstOffset;
243cdf0e10cSrcweir 			//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
244cdf0e10cSrcweir             if ( aPnt1.X() < nMaxY && !bVertL2R )
245cdf0e10cSrcweir                 aPnt1.X() = nMaxY;
246cdf0e10cSrcweir             aPnt2.X() = aPnt1.X() + pFrm->Prt().Width();
247cdf0e10cSrcweir             aPnt2.Y() = aPnt1.Y();
248cdf0e10cSrcweir             if( aPnt2.X() < nMaxY )
249cdf0e10cSrcweir                 aPnt2.X() = nMaxY;
250cdf0e10cSrcweir         }
251cdf0e10cSrcweir         else
252cdf0e10cSrcweir         {
253cdf0e10cSrcweir             if( nFirstOffset > 0 )
254cdf0e10cSrcweir                 aPnt1.X() += nFirstOffset;
255cdf0e10cSrcweir 
256cdf0e10cSrcweir             if( aPnt1.Y() > nMaxY )
257cdf0e10cSrcweir                 aPnt1.Y() = nMaxY;
258cdf0e10cSrcweir             aPnt2.X() = aPnt1.X();
259cdf0e10cSrcweir             aPnt2.Y() = aPnt1.Y() + pFrm->Prt().Height();
260cdf0e10cSrcweir             if( aPnt2.Y() > nMaxY )
261cdf0e10cSrcweir                 aPnt2.Y() = nMaxY;
262cdf0e10cSrcweir         }
263cdf0e10cSrcweir 
264cdf0e10cSrcweir         rOrig = SwRect( aPnt1, aPnt2 );
265cdf0e10cSrcweir 
266cdf0e10cSrcweir         if ( pCMS )
267cdf0e10cSrcweir 		{
268cdf0e10cSrcweir 			pCMS->aRealHeight.X() = 0;
269cdf0e10cSrcweir             pCMS->aRealHeight.Y() = bVert ? -rOrig.Width() : rOrig.Height();
270cdf0e10cSrcweir 		}
271cdf0e10cSrcweir 
272cdf0e10cSrcweir         if ( pFrm->IsRightToLeft() )
273cdf0e10cSrcweir             pFrm->SwitchLTRtoRTL( rOrig );
274cdf0e10cSrcweir 
275cdf0e10cSrcweir         bRet = sal_True;
276cdf0e10cSrcweir 	}
277cdf0e10cSrcweir 	else
278cdf0e10cSrcweir 	{
279cdf0e10cSrcweir 		if( !pFrm->HasPara() )
280cdf0e10cSrcweir 			return sal_False;
281cdf0e10cSrcweir 
282cdf0e10cSrcweir         SwFrmSwapper aSwapper( pFrm, sal_True );
283cdf0e10cSrcweir         if ( bVert )
284cdf0e10cSrcweir             nMaxY = pFrm->SwitchVerticalToHorizontal( nMaxY );
285cdf0e10cSrcweir 
286cdf0e10cSrcweir         sal_Bool bGoOn = sal_True;
287cdf0e10cSrcweir 		xub_StrLen nOffset = rPos.nContent.GetIndex();
288cdf0e10cSrcweir 		xub_StrLen nNextOfst;
289cdf0e10cSrcweir 
290cdf0e10cSrcweir 		do
291cdf0e10cSrcweir 		{
292cdf0e10cSrcweir 			{
293cdf0e10cSrcweir 				SwTxtSizeInfo aInf( pFrm );
294cdf0e10cSrcweir 				SwTxtCursor  aLine( pFrm, &aInf );
295cdf0e10cSrcweir 				nNextOfst = aLine.GetEnd();
296cdf0e10cSrcweir 				// Siehe Kommentar in AdjustFrm
297cdf0e10cSrcweir 				// 1170: das letzte Zeichen der Zeile mitnehmen?
298cdf0e10cSrcweir 				bRet = bRightMargin ? aLine.GetEndCharRect( &rOrig, nOffset, pCMS, nMaxY )
299cdf0e10cSrcweir 								: aLine.GetCharRect( &rOrig, nOffset, pCMS, nMaxY );
300cdf0e10cSrcweir 			}
301cdf0e10cSrcweir 
302cdf0e10cSrcweir             if ( pFrm->IsRightToLeft() )
303cdf0e10cSrcweir                 pFrm->SwitchLTRtoRTL( rOrig );
304cdf0e10cSrcweir 
305cdf0e10cSrcweir             if ( bVert )
306cdf0e10cSrcweir                 pFrm->SwitchHorizontalToVertical( rOrig );
307cdf0e10cSrcweir 
308cdf0e10cSrcweir             if( pFrm->IsUndersized() && pCMS && !pFrm->GetNext() &&
309cdf0e10cSrcweir                 (rOrig.*fnRect->fnGetBottom)() == nUpperMaxY &&
310cdf0e10cSrcweir                 pFrm->GetOfst() < nOffset &&
311cdf0e10cSrcweir                 !pFrm->IsFollow() && !bNoScroll &&
312cdf0e10cSrcweir                 pFrm->GetTxtNode()->GetTxt().Len() != nNextOfst )
313cdf0e10cSrcweir 				bGoOn = lcl_ChangeOffset( pFrm, nNextOfst );
314cdf0e10cSrcweir 			else
315cdf0e10cSrcweir 				bGoOn = sal_False;
316cdf0e10cSrcweir 		} while ( bGoOn );
317cdf0e10cSrcweir 
318cdf0e10cSrcweir         if ( pCMS )
319cdf0e10cSrcweir         {
320cdf0e10cSrcweir             if ( pFrm->IsRightToLeft() )
321cdf0e10cSrcweir             {
322cdf0e10cSrcweir                 if( pCMS->b2Lines && pCMS->p2Lines)
323cdf0e10cSrcweir                 {
324cdf0e10cSrcweir                     pFrm->SwitchLTRtoRTL( pCMS->p2Lines->aLine );
325cdf0e10cSrcweir                     pFrm->SwitchLTRtoRTL( pCMS->p2Lines->aPortion );
326cdf0e10cSrcweir                 }
327cdf0e10cSrcweir             }
328cdf0e10cSrcweir 
329cdf0e10cSrcweir             if ( bVert )
330cdf0e10cSrcweir             {
331cdf0e10cSrcweir                 if ( pCMS->bRealHeight )
332cdf0e10cSrcweir                 {
333cdf0e10cSrcweir                     pCMS->aRealHeight.Y() = -pCMS->aRealHeight.Y();
334cdf0e10cSrcweir                     if ( pCMS->aRealHeight.Y() < 0 )
335cdf0e10cSrcweir                     {
336cdf0e10cSrcweir                         // writing direction is from top to bottom
337cdf0e10cSrcweir                         pCMS->aRealHeight.X() =  ( rOrig.Width() -
338cdf0e10cSrcweir                                                     pCMS->aRealHeight.X() +
339cdf0e10cSrcweir                                                     pCMS->aRealHeight.Y() );
340cdf0e10cSrcweir                     }
341cdf0e10cSrcweir                 }
342cdf0e10cSrcweir                 if( pCMS->b2Lines && pCMS->p2Lines)
343cdf0e10cSrcweir                 {
344cdf0e10cSrcweir                     pFrm->SwitchHorizontalToVertical( pCMS->p2Lines->aLine );
345cdf0e10cSrcweir                     pFrm->SwitchHorizontalToVertical( pCMS->p2Lines->aPortion );
346cdf0e10cSrcweir                 }
347cdf0e10cSrcweir             }
348cdf0e10cSrcweir 
349cdf0e10cSrcweir         }
350cdf0e10cSrcweir     }
351cdf0e10cSrcweir     if( bRet )
352cdf0e10cSrcweir     {
353cdf0e10cSrcweir         SwPageFrm *pPage = pFrm->FindPageFrm();
354cdf0e10cSrcweir         ASSERT( pPage, "Text esaped from page?" );
355cdf0e10cSrcweir         const SwTwips nOrigTop = (rOrig.*fnRect->fnGetTop)();
356cdf0e10cSrcweir         const SwTwips nPageTop = (pPage->Frm().*fnRect->fnGetTop)();
357cdf0e10cSrcweir         const SwTwips nPageBott = (pPage->Frm().*fnRect->fnGetBottom)();
358cdf0e10cSrcweir 
359cdf0e10cSrcweir         // Following situation: if the frame is in an invalid sectionframe,
360cdf0e10cSrcweir         // it's possible that the frame is outside the page. If we restrict
361cdf0e10cSrcweir         // the cursor position to the page area, we enforce the formatting
362cdf0e10cSrcweir         // of the page, of the section frame and the frame himself.
363cdf0e10cSrcweir         if( (*fnRect->fnYDiff)( nPageTop, nOrigTop ) > 0 )
364cdf0e10cSrcweir             (rOrig.*fnRect->fnSetTop)( nPageTop );
365cdf0e10cSrcweir 
366cdf0e10cSrcweir         if ( (*fnRect->fnYDiff)( nOrigTop, nPageBott ) > 0 )
367cdf0e10cSrcweir             (rOrig.*fnRect->fnSetTop)( nPageBott );
368cdf0e10cSrcweir     }
369cdf0e10cSrcweir 
370cdf0e10cSrcweir     return bRet;
371cdf0e10cSrcweir }
372cdf0e10cSrcweir 
373cdf0e10cSrcweir /*************************************************************************
374cdf0e10cSrcweir  *						SwTxtFrm::GetAutoPos()
375cdf0e10cSrcweir  *************************************************************************/
376cdf0e10cSrcweir 
377cdf0e10cSrcweir /*
378cdf0e10cSrcweir  * GetAutoPos() findet die Characterzelle des Characters, dass
379cdf0e10cSrcweir  * durch aPos beschrieben wird und wird von autopositionierten Rahmen genutzt.
380cdf0e10cSrcweir  */
381cdf0e10cSrcweir 
GetAutoPos(SwRect & rOrig,const SwPosition & rPos) const382cdf0e10cSrcweir sal_Bool SwTxtFrm::GetAutoPos( SwRect& rOrig, const SwPosition &rPos ) const
383cdf0e10cSrcweir {
384cdf0e10cSrcweir 	if( IsHiddenNow() )
385cdf0e10cSrcweir 		return sal_False;
386cdf0e10cSrcweir 
387cdf0e10cSrcweir 	xub_StrLen nOffset = rPos.nContent.GetIndex();
388cdf0e10cSrcweir     SwTxtFrm* pFrm = &(const_cast<SwTxtFrm*>(this)->GetFrmAtOfst( nOffset ));
389cdf0e10cSrcweir 
390cdf0e10cSrcweir 	pFrm->GetFormatted();
391cdf0e10cSrcweir 	const SwFrm* pTmpFrm = (SwFrm*)pFrm->GetUpper();
392cdf0e10cSrcweir 
393cdf0e10cSrcweir     SWRECTFN( pTmpFrm )
394cdf0e10cSrcweir     SwTwips nUpperMaxY = (pTmpFrm->*fnRect->fnGetPrtBottom)();
395cdf0e10cSrcweir 
396cdf0e10cSrcweir     // nMaxY is in absolute value
397cdf0e10cSrcweir     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
398cdf0e10cSrcweir 	SwTwips nMaxY = bVert ?
399cdf0e10cSrcweir                     ( bVertL2R ? Min( (pFrm->*fnRect->fnGetPrtBottom)(), nUpperMaxY ) : Max( (pFrm->*fnRect->fnGetPrtBottom)(), nUpperMaxY ) ) :
400cdf0e10cSrcweir                     Min( (pFrm->*fnRect->fnGetPrtBottom)(), nUpperMaxY );
401cdf0e10cSrcweir 
402cdf0e10cSrcweir     if ( pFrm->IsEmpty() || ! (pFrm->Prt().*fnRect->fnGetHeight)() )
403cdf0e10cSrcweir 	{
404cdf0e10cSrcweir 		Point aPnt1 = pFrm->Frm().Pos() + pFrm->Prt().Pos();
405cdf0e10cSrcweir         Point aPnt2;
406cdf0e10cSrcweir         if ( bVert )
407cdf0e10cSrcweir         {
408cdf0e10cSrcweir             if ( aPnt1.X() < nMaxY && !bVertL2R )
409cdf0e10cSrcweir                 aPnt1.X() = nMaxY;
410cdf0e10cSrcweir 
411cdf0e10cSrcweir             aPnt2.X() = aPnt1.X() + pFrm->Prt().Width();
412cdf0e10cSrcweir             aPnt2.Y() = aPnt1.Y();
413cdf0e10cSrcweir             if( aPnt2.X() < nMaxY )
414cdf0e10cSrcweir                 aPnt2.X() = nMaxY;
415cdf0e10cSrcweir         }
416cdf0e10cSrcweir         else
417cdf0e10cSrcweir         {
418cdf0e10cSrcweir             if( aPnt1.Y() > nMaxY )
419cdf0e10cSrcweir                 aPnt1.Y() = nMaxY;
420cdf0e10cSrcweir             aPnt2.X() = aPnt1.X();
421cdf0e10cSrcweir             aPnt2.Y() = aPnt1.Y() + pFrm->Prt().Height();
422cdf0e10cSrcweir             if( aPnt2.Y() > nMaxY )
423cdf0e10cSrcweir                 aPnt2.Y() = nMaxY;
424cdf0e10cSrcweir         }
425cdf0e10cSrcweir 		rOrig = SwRect( aPnt1, aPnt2 );
426cdf0e10cSrcweir 		return sal_True;
427cdf0e10cSrcweir 	}
428cdf0e10cSrcweir 	else
429cdf0e10cSrcweir 	{
430cdf0e10cSrcweir 		if( !pFrm->HasPara() )
431cdf0e10cSrcweir 			return sal_False;
432cdf0e10cSrcweir 
433cdf0e10cSrcweir         SwFrmSwapper aSwapper( pFrm, sal_True );
434cdf0e10cSrcweir         if ( bVert )
435cdf0e10cSrcweir             nMaxY = pFrm->SwitchVerticalToHorizontal( nMaxY );
436cdf0e10cSrcweir 
437cdf0e10cSrcweir         SwTxtSizeInfo aInf( pFrm );
438cdf0e10cSrcweir         SwTxtCursor aLine( pFrm, &aInf );
439cdf0e10cSrcweir         SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
440cdf0e10cSrcweir         aTmpState.bRealHeight = sal_True;
441cdf0e10cSrcweir         if( aLine.GetCharRect( &rOrig, nOffset, &aTmpState, nMaxY ) )
442cdf0e10cSrcweir         {
443cdf0e10cSrcweir             if( aTmpState.aRealHeight.X() >= 0 )
444cdf0e10cSrcweir             {
445cdf0e10cSrcweir                 rOrig.Pos().Y() += aTmpState.aRealHeight.X();
446cdf0e10cSrcweir                 rOrig.Height( aTmpState.aRealHeight.Y() );
447cdf0e10cSrcweir             }
448cdf0e10cSrcweir 
449cdf0e10cSrcweir             if ( pFrm->IsRightToLeft() )
450cdf0e10cSrcweir                 pFrm->SwitchLTRtoRTL( rOrig );
451cdf0e10cSrcweir 
452cdf0e10cSrcweir             if ( bVert )
453cdf0e10cSrcweir                 pFrm->SwitchHorizontalToVertical( rOrig );
454cdf0e10cSrcweir 
455cdf0e10cSrcweir             return sal_True;
456cdf0e10cSrcweir         }
457cdf0e10cSrcweir         return sal_False;
458cdf0e10cSrcweir 	}
459cdf0e10cSrcweir }
460cdf0e10cSrcweir 
461cdf0e10cSrcweir /** determine top of line for given position in the text frame
462cdf0e10cSrcweir 
463cdf0e10cSrcweir     OD 11.11.2003 #i22341#
464cdf0e10cSrcweir     OD 2004-03-18 #114789# - corrections:
465cdf0e10cSrcweir     - Top of first paragraph line is the top of the printing area of the text frame
466cdf0e10cSrcweir     - If a proportional line spacing is applied use top of anchor character as
467cdf0e10cSrcweir       top of the line.
468cdf0e10cSrcweir 
469cdf0e10cSrcweir     @author OD
470cdf0e10cSrcweir */
GetTopOfLine(SwTwips & _onTopOfLine,const SwPosition & _rPos) const471cdf0e10cSrcweir bool SwTxtFrm::GetTopOfLine( SwTwips& _onTopOfLine,
472cdf0e10cSrcweir                              const SwPosition& _rPos ) const
473cdf0e10cSrcweir {
474cdf0e10cSrcweir     bool bRet = true;
475cdf0e10cSrcweir 
476cdf0e10cSrcweir     // get position offset
477cdf0e10cSrcweir     xub_StrLen nOffset = _rPos.nContent.GetIndex();
478cdf0e10cSrcweir 
479cdf0e10cSrcweir     if ( GetTxt().Len() < nOffset )
480cdf0e10cSrcweir     {
481cdf0e10cSrcweir         bRet = false;
482cdf0e10cSrcweir     }
483cdf0e10cSrcweir     else
484cdf0e10cSrcweir     {
485cdf0e10cSrcweir         SWRECTFN( this )
486cdf0e10cSrcweir         if ( IsEmpty() || !(Prt().*fnRect->fnGetHeight)() )
487cdf0e10cSrcweir         {
488cdf0e10cSrcweir             // OD 2004-03-18 #i11860# - consider upper space amount considered
489cdf0e10cSrcweir             // for previous frame and the page grid.
490cdf0e10cSrcweir             _onTopOfLine = (this->*fnRect->fnGetPrtTop)();
491cdf0e10cSrcweir         }
492cdf0e10cSrcweir         else
493cdf0e10cSrcweir         {
494cdf0e10cSrcweir             // determine formatted text frame that contains the requested position
495cdf0e10cSrcweir             SwTxtFrm* pFrm = &(const_cast<SwTxtFrm*>(this)->GetFrmAtOfst( nOffset ));
496cdf0e10cSrcweir             pFrm->GetFormatted();
497cdf0e10cSrcweir             SWREFRESHFN( pFrm )
498cdf0e10cSrcweir             // OD 2004-03-18 #114789# - If proportional line spacing is applied
499cdf0e10cSrcweir             // to the text frame, the top of the anchor character is also the
500cdf0e10cSrcweir             // top of the line.
501cdf0e10cSrcweir             // Otherwise the line layout determines the top of the line
502cdf0e10cSrcweir             const SvxLineSpacingItem& rSpace = GetAttrSet()->GetLineSpacing();
503cdf0e10cSrcweir             if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
504cdf0e10cSrcweir             {
505cdf0e10cSrcweir                 SwRect aCharRect;
506cdf0e10cSrcweir                 if ( GetAutoPos( aCharRect, _rPos ) )
507cdf0e10cSrcweir                 {
508cdf0e10cSrcweir                     _onTopOfLine = (aCharRect.*fnRect->fnGetTop)();
509cdf0e10cSrcweir                 }
510cdf0e10cSrcweir                 else
511cdf0e10cSrcweir                 {
512cdf0e10cSrcweir                     bRet = false;
513cdf0e10cSrcweir                 }
514cdf0e10cSrcweir             }
515cdf0e10cSrcweir             else
516cdf0e10cSrcweir             {
517cdf0e10cSrcweir                 // assure that text frame is in a horizontal layout
518cdf0e10cSrcweir                 SwFrmSwapper aSwapper( pFrm, sal_True );
519cdf0e10cSrcweir                 // determine text line that contains the requested position
520cdf0e10cSrcweir                 SwTxtSizeInfo aInf( pFrm );
521cdf0e10cSrcweir                 SwTxtCursor aLine( pFrm, &aInf );
522cdf0e10cSrcweir                 aLine.CharCrsrToLine( nOffset );
523cdf0e10cSrcweir                 // determine top of line
524cdf0e10cSrcweir                 _onTopOfLine = aLine.Y();
525cdf0e10cSrcweir                 if ( bVert )
526cdf0e10cSrcweir                 {
527cdf0e10cSrcweir                     _onTopOfLine = pFrm->SwitchHorizontalToVertical( _onTopOfLine );
528cdf0e10cSrcweir                 }
529cdf0e10cSrcweir             }
530cdf0e10cSrcweir         }
531cdf0e10cSrcweir     }
532cdf0e10cSrcweir 
533cdf0e10cSrcweir     return bRet;
534cdf0e10cSrcweir }
535cdf0e10cSrcweir 
536cdf0e10cSrcweir /*************************************************************************
537cdf0e10cSrcweir  *						SwTxtFrm::_GetCrsrOfst()
538cdf0e10cSrcweir  *************************************************************************/
539cdf0e10cSrcweir 
540cdf0e10cSrcweir // Minimaler Abstand von nichtleeren Zeilen etwas weniger als 2 cm
541cdf0e10cSrcweir #define FILL_MIN_DIST 1100
542cdf0e10cSrcweir 
543cdf0e10cSrcweir struct SwFillData
544cdf0e10cSrcweir {
545cdf0e10cSrcweir 	SwRect aFrm;
546cdf0e10cSrcweir 	const SwCrsrMoveState *pCMS;
547cdf0e10cSrcweir 	SwPosition* pPos;
548cdf0e10cSrcweir 	const Point& rPoint;
549cdf0e10cSrcweir 	SwTwips nLineWidth;
550cdf0e10cSrcweir 	sal_Bool bFirstLine : 1;
551cdf0e10cSrcweir 	sal_Bool bInner		: 1;
552cdf0e10cSrcweir 	sal_Bool bColumn	: 1;
553cdf0e10cSrcweir 	sal_Bool bEmpty		: 1;
SwFillDataSwFillData554cdf0e10cSrcweir 	SwFillData( const SwCrsrMoveState *pC, SwPosition* pP, const SwRect& rR,
555cdf0e10cSrcweir 		const Point& rPt ) : aFrm( rR ), pCMS( pC ), pPos( pP ), rPoint( rPt ),
556cdf0e10cSrcweir 		nLineWidth( 0 ), bFirstLine( sal_True ), bInner( sal_False ), bColumn( sal_False ),
557cdf0e10cSrcweir 		bEmpty( sal_True ){}
ModeSwFillData558cdf0e10cSrcweir 	SwFillMode Mode() const { return pCMS->pFill->eMode; }
XSwFillData559cdf0e10cSrcweir 	long X() const { return rPoint.X(); }
YSwFillData560cdf0e10cSrcweir 	long Y() const { return rPoint.Y(); }
LeftSwFillData561cdf0e10cSrcweir 	long Left() const { return aFrm.Left(); }
RightSwFillData562cdf0e10cSrcweir 	long Right() const { return aFrm.Right(); }
BottomSwFillData563cdf0e10cSrcweir 	long Bottom() const { return aFrm.Bottom(); }
FrmSwFillData564cdf0e10cSrcweir     SwRect& Frm() { return aFrm; }
FillSwFillData565cdf0e10cSrcweir 	SwFillCrsrPos &Fill() const { return *pCMS->pFill; }
SetTabSwFillData566cdf0e10cSrcweir 	void SetTab( MSHORT nNew ) { pCMS->pFill->nTabCnt = nNew; }
SetSpaceSwFillData567cdf0e10cSrcweir 	void SetSpace( MSHORT nNew ) { pCMS->pFill->nSpaceCnt = nNew; }
SetOrientSwFillData568cdf0e10cSrcweir     void SetOrient( const sal_Int16 eNew ){ pCMS->pFill->eOrient = eNew; }
569cdf0e10cSrcweir };
570cdf0e10cSrcweir 
_GetCrsrOfst(SwPosition * pPos,const Point & rPoint,const sal_Bool bChgFrm,SwCrsrMoveState * pCMS) const571cdf0e10cSrcweir sal_Bool SwTxtFrm::_GetCrsrOfst(SwPosition* pPos, const Point& rPoint,
572cdf0e10cSrcweir 					const sal_Bool bChgFrm, SwCrsrMoveState* pCMS ) const
573cdf0e10cSrcweir {
574cdf0e10cSrcweir 	// 8804: _GetCrsrOfst wird vom GetCrsrOfst und GetKeyCrsrOfst gerufen.
575cdf0e10cSrcweir 	// In keinem Fall nur ein return sal_False.
576cdf0e10cSrcweir 
577cdf0e10cSrcweir 	if( IsLocked() || IsHiddenNow() )
578cdf0e10cSrcweir 		return sal_False;
579cdf0e10cSrcweir 
580cdf0e10cSrcweir 	((SwTxtFrm*)this)->GetFormatted();
581cdf0e10cSrcweir 
582cdf0e10cSrcweir     Point aOldPoint( rPoint );
583cdf0e10cSrcweir 
584cdf0e10cSrcweir     if ( IsVertical() )
585cdf0e10cSrcweir     {
586cdf0e10cSrcweir         SwitchVerticalToHorizontal( (Point&)rPoint );
587cdf0e10cSrcweir         ((SwTxtFrm*)this)->SwapWidthAndHeight();
588cdf0e10cSrcweir     }
589cdf0e10cSrcweir 
590cdf0e10cSrcweir     if ( IsRightToLeft() )
591cdf0e10cSrcweir         SwitchRTLtoLTR( (Point&)rPoint );
592cdf0e10cSrcweir 
593cdf0e10cSrcweir     SwFillData *pFillData = ( pCMS && pCMS->pFill ) ?
594cdf0e10cSrcweir                         new SwFillData( pCMS, pPos, Frm(), rPoint ) : NULL;
595cdf0e10cSrcweir 
596cdf0e10cSrcweir     if ( IsEmpty() )
597cdf0e10cSrcweir 	{
598cdf0e10cSrcweir 		SwTxtNode* pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
599cdf0e10cSrcweir 		pPos->nNode = *pTxtNd;
600cdf0e10cSrcweir 		pPos->nContent.Assign( pTxtNd, 0 );
601cdf0e10cSrcweir 		if( pCMS && pCMS->bFieldInfo )
602cdf0e10cSrcweir 		{
603cdf0e10cSrcweir 			SwTwips nDiff = rPoint.X() - Frm().Left() - Prt().Left();
604cdf0e10cSrcweir 			if( nDiff > 50 || nDiff < 0 )
605cdf0e10cSrcweir 				((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
606cdf0e10cSrcweir 		}
607cdf0e10cSrcweir 	}
608cdf0e10cSrcweir 	else
609cdf0e10cSrcweir 	{
610cdf0e10cSrcweir 		SwTxtSizeInfo aInf( (SwTxtFrm*)this );
611cdf0e10cSrcweir 		SwTxtCursor  aLine( ((SwTxtFrm*)this), &aInf );
612cdf0e10cSrcweir 
613cdf0e10cSrcweir 		// Siehe Kommentar in AdjustFrm()
614cdf0e10cSrcweir 		SwTwips nMaxY = Frm().Top() + Prt().Top() + Prt().Height();
615cdf0e10cSrcweir 		aLine.TwipsToLine( rPoint.Y() );
616cdf0e10cSrcweir 		while( aLine.Y() + aLine.GetLineHeight() > nMaxY )
617cdf0e10cSrcweir 		{
618cdf0e10cSrcweir 			DBG_LOOP;
619cdf0e10cSrcweir 			if( !aLine.Prev() )
620cdf0e10cSrcweir 				break;
621cdf0e10cSrcweir 		}
622cdf0e10cSrcweir 
623cdf0e10cSrcweir 		if( aLine.GetDropLines() >= aLine.GetLineNr() && 1 != aLine.GetLineNr()
624cdf0e10cSrcweir 			&& rPoint.X() < aLine.FirstLeft() + aLine.GetDropLeft() )
625cdf0e10cSrcweir 			while( aLine.GetLineNr() > 1 )
626cdf0e10cSrcweir 				aLine.Prev();
627cdf0e10cSrcweir 
628cdf0e10cSrcweir         xub_StrLen nOffset = aLine.GetCrsrOfst( pPos, rPoint, bChgFrm, pCMS );
629cdf0e10cSrcweir 
630cdf0e10cSrcweir         if( pCMS && pCMS->eState == MV_NONE && aLine.GetEnd() == nOffset )
631cdf0e10cSrcweir             ((SwCrsrMoveState*)pCMS)->eState = MV_RIGHTMARGIN;
632cdf0e10cSrcweir 
633cdf0e10cSrcweir 	// 6776: pPos ist ein reiner IN-Parameter, der nicht ausgewertet werden darf.
634cdf0e10cSrcweir 	// Das pIter->GetCrsrOfst returnt aus einer Verschachtelung mit STRING_LEN.
635cdf0e10cSrcweir 	// Wenn SwTxtIter::GetCrsrOfst von sich aus weitere GetCrsrOfst
636cdf0e10cSrcweir 	// ruft, so aendert sich nNode der Position. In solchen Faellen
637cdf0e10cSrcweir 	// darf pPos nicht berechnet werden.
638cdf0e10cSrcweir 		if( STRING_LEN != nOffset )
639cdf0e10cSrcweir 		{
640cdf0e10cSrcweir 			SwTxtNode* pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
641cdf0e10cSrcweir 			pPos->nNode = *pTxtNd;
642cdf0e10cSrcweir 			pPos->nContent.Assign( pTxtNd, nOffset );
643cdf0e10cSrcweir 			if( pFillData )
644cdf0e10cSrcweir 			{
645cdf0e10cSrcweir 				if( pTxtNd->GetTxt().Len() > nOffset ||
646cdf0e10cSrcweir 					rPoint.Y() < Frm().Top() )
647cdf0e10cSrcweir 					pFillData->bInner = sal_True;
648cdf0e10cSrcweir 				pFillData->bFirstLine = aLine.GetLineNr() < 2;
649cdf0e10cSrcweir 				if( pTxtNd->GetTxt().Len() )
650cdf0e10cSrcweir 				{
651cdf0e10cSrcweir 					pFillData->bEmpty = sal_False;
652cdf0e10cSrcweir 					pFillData->nLineWidth = aLine.GetCurr()->Width();
653cdf0e10cSrcweir                 }
654cdf0e10cSrcweir 			}
655cdf0e10cSrcweir 		}
656cdf0e10cSrcweir 	}
657cdf0e10cSrcweir     sal_Bool bChgFillData = sal_False;
658cdf0e10cSrcweir     if( pFillData && FindPageFrm()->Frm().IsInside( aOldPoint ) )
659cdf0e10cSrcweir     {
660cdf0e10cSrcweir 		FillCrsrPos( *pFillData );
661cdf0e10cSrcweir         bChgFillData = sal_True;
662cdf0e10cSrcweir     }
663cdf0e10cSrcweir 
664cdf0e10cSrcweir     if ( IsVertical() )
665cdf0e10cSrcweir     {
666cdf0e10cSrcweir         if ( bChgFillData )
667cdf0e10cSrcweir             SwitchHorizontalToVertical( pFillData->Fill().aCrsr.Pos() );
668cdf0e10cSrcweir         ((SwTxtFrm*)this)->SwapWidthAndHeight();
669cdf0e10cSrcweir     }
670cdf0e10cSrcweir 
671cdf0e10cSrcweir     if ( IsRightToLeft() && bChgFillData )
672cdf0e10cSrcweir     {
673cdf0e10cSrcweir             SwitchLTRtoRTL( pFillData->Fill().aCrsr.Pos() );
674cdf0e10cSrcweir             const sal_Int16 eOrient = pFillData->pCMS->pFill->eOrient;
675cdf0e10cSrcweir 
676cdf0e10cSrcweir             if ( text::HoriOrientation::LEFT == eOrient )
677cdf0e10cSrcweir                 pFillData->SetOrient( text::HoriOrientation::RIGHT );
678cdf0e10cSrcweir             else if ( text::HoriOrientation::RIGHT == eOrient )
679cdf0e10cSrcweir                 pFillData->SetOrient( text::HoriOrientation::LEFT );
680cdf0e10cSrcweir     }
681cdf0e10cSrcweir 
682cdf0e10cSrcweir     (Point&)rPoint = aOldPoint;
683cdf0e10cSrcweir     delete pFillData;
684cdf0e10cSrcweir 
685cdf0e10cSrcweir 	return sal_True;
686cdf0e10cSrcweir }
687cdf0e10cSrcweir 
688cdf0e10cSrcweir /*************************************************************************
689cdf0e10cSrcweir  *				   virtual SwTxtFrm::GetCrsrOfst()
690cdf0e10cSrcweir  *************************************************************************/
691cdf0e10cSrcweir 
GetCrsrOfst(SwPosition * pPos,Point & rPoint,SwCrsrMoveState * pCMS) const692cdf0e10cSrcweir sal_Bool SwTxtFrm::GetCrsrOfst(SwPosition* pPos, Point& rPoint,
693cdf0e10cSrcweir                                SwCrsrMoveState* pCMS ) const
694cdf0e10cSrcweir {
695cdf0e10cSrcweir 	MSHORT nChgFrm = 2;
696cdf0e10cSrcweir 	if( pCMS )
697cdf0e10cSrcweir 	{
698cdf0e10cSrcweir 		if( MV_UPDOWN == pCMS->eState )
699cdf0e10cSrcweir 			nChgFrm = 0;
700cdf0e10cSrcweir 		else if( MV_SETONLYTEXT == pCMS->eState ||
701cdf0e10cSrcweir 				 MV_TBLSEL == pCMS->eState )
702cdf0e10cSrcweir 			nChgFrm = 1;
703cdf0e10cSrcweir 	}
704cdf0e10cSrcweir     return _GetCrsrOfst( pPos, rPoint, nChgFrm != 0, pCMS );
705cdf0e10cSrcweir }
706cdf0e10cSrcweir 
707cdf0e10cSrcweir /*************************************************************************
708cdf0e10cSrcweir  *						SwTxtFrm::LeftMargin()
709cdf0e10cSrcweir  *************************************************************************/
710cdf0e10cSrcweir 
711cdf0e10cSrcweir /*
712cdf0e10cSrcweir  * Layout-orientierte Cursorbewegungen
713cdf0e10cSrcweir  */
714cdf0e10cSrcweir 
715cdf0e10cSrcweir /*
716cdf0e10cSrcweir  * an den Zeilenanfang
717cdf0e10cSrcweir  */
718cdf0e10cSrcweir 
LeftMargin(SwPaM * pPam) const719cdf0e10cSrcweir sal_Bool SwTxtFrm::LeftMargin(SwPaM *pPam) const
720cdf0e10cSrcweir {
721cdf0e10cSrcweir 	if( ((const SwNode*)pPam->GetNode()) != GetNode() )
722cdf0e10cSrcweir 		pPam->GetPoint()->nNode = *((SwTxtFrm*)this)->GetTxtNode();
723cdf0e10cSrcweir 
724cdf0e10cSrcweir 	SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, *pPam->GetPoint(),
725cdf0e10cSrcweir 									 SwTxtCursor::IsRightMargin() );
726cdf0e10cSrcweir 	pFrm->GetFormatted();
727cdf0e10cSrcweir 	xub_StrLen nIndx;
728cdf0e10cSrcweir 	if ( pFrm->IsEmpty() )
729cdf0e10cSrcweir 		nIndx = 0;
730cdf0e10cSrcweir 	else
731cdf0e10cSrcweir 	{
732cdf0e10cSrcweir 		SwTxtSizeInfo aInf( pFrm );
733cdf0e10cSrcweir 		SwTxtCursor  aLine( pFrm, &aInf );
734cdf0e10cSrcweir 
735cdf0e10cSrcweir 		aLine.CharCrsrToLine(pPam->GetPoint()->nContent.GetIndex());
736cdf0e10cSrcweir 		nIndx = aLine.GetStart();
737cdf0e10cSrcweir 		if( pFrm->GetOfst() && !pFrm->IsFollow() && !aLine.GetPrev() )
738cdf0e10cSrcweir 		{
739cdf0e10cSrcweir 			lcl_ChangeOffset( pFrm, 0 );
740cdf0e10cSrcweir 			nIndx = 0;
741cdf0e10cSrcweir 		}
742cdf0e10cSrcweir 	}
743cdf0e10cSrcweir 	pPam->GetPoint()->nContent = SwIndex( pFrm->GetTxtNode(), nIndx );
744cdf0e10cSrcweir 	SwTxtCursor::SetRightMargin( sal_False );
745cdf0e10cSrcweir 	return sal_True;
746cdf0e10cSrcweir }
747cdf0e10cSrcweir 
748cdf0e10cSrcweir /*************************************************************************
749cdf0e10cSrcweir  *						SwTxtFrm::RightMargin()
750cdf0e10cSrcweir  *************************************************************************/
751cdf0e10cSrcweir 
752cdf0e10cSrcweir /*
753cdf0e10cSrcweir  * An das Zeilenende:Das ist die Position vor dem letzten
754cdf0e10cSrcweir  * Character in der Zeile. Ausnahme: In der letzten Zeile soll
755cdf0e10cSrcweir  * der Cursor auch hinter dem letzten Character stehen koennen,
756cdf0e10cSrcweir  * um Text anhaengen zu koennen.
757cdf0e10cSrcweir  *
758cdf0e10cSrcweir  */
759cdf0e10cSrcweir 
RightMargin(SwPaM * pPam,sal_Bool bAPI) const760cdf0e10cSrcweir sal_Bool SwTxtFrm::RightMargin(SwPaM *pPam, sal_Bool bAPI) const
761cdf0e10cSrcweir {
762cdf0e10cSrcweir 	if( ((const SwNode*)pPam->GetNode()) != GetNode() )
763cdf0e10cSrcweir 		pPam->GetPoint()->nNode = *((SwTxtFrm*)this)->GetTxtNode();
764cdf0e10cSrcweir 
765cdf0e10cSrcweir 	SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, *pPam->GetPoint(),
766cdf0e10cSrcweir 									 SwTxtCursor::IsRightMargin() );
767cdf0e10cSrcweir 	pFrm->GetFormatted();
768cdf0e10cSrcweir 	xub_StrLen nRightMargin;
769cdf0e10cSrcweir 	if ( IsEmpty() )
770cdf0e10cSrcweir 		nRightMargin = 0;
771cdf0e10cSrcweir 	else
772cdf0e10cSrcweir 	{
773cdf0e10cSrcweir 		SwTxtSizeInfo aInf( pFrm );
774cdf0e10cSrcweir 		SwTxtCursor  aLine( pFrm, &aInf );
775cdf0e10cSrcweir 
776cdf0e10cSrcweir 		aLine.CharCrsrToLine(pPam->GetPoint()->nContent.GetIndex());
777cdf0e10cSrcweir 		nRightMargin = aLine.GetStart() + aLine.GetCurr()->GetLen();
778cdf0e10cSrcweir 
779cdf0e10cSrcweir 		// Harte Zeilenumbrueche lassen wir hinter uns.
780cdf0e10cSrcweir 		if( aLine.GetCurr()->GetLen() &&
781cdf0e10cSrcweir 			CH_BREAK == aInf.GetTxt().GetChar( nRightMargin - 1 ) )
782cdf0e10cSrcweir 			--nRightMargin;
783cdf0e10cSrcweir 		else if( !bAPI && (aLine.GetNext() || pFrm->GetFollow()) )
784cdf0e10cSrcweir 		{
785cdf0e10cSrcweir 			while( nRightMargin > aLine.GetStart() &&
786cdf0e10cSrcweir 				' ' == aInf.GetTxt().GetChar( nRightMargin - 1 ) )
787cdf0e10cSrcweir 				--nRightMargin;
788cdf0e10cSrcweir 		}
789cdf0e10cSrcweir 	}
790cdf0e10cSrcweir 	pPam->GetPoint()->nContent = SwIndex( pFrm->GetTxtNode(), nRightMargin );
791cdf0e10cSrcweir 	SwTxtCursor::SetRightMargin( !bAPI );
792cdf0e10cSrcweir 	return sal_True;
793cdf0e10cSrcweir }
794cdf0e10cSrcweir 
795cdf0e10cSrcweir /*************************************************************************
796cdf0e10cSrcweir  *						SwTxtFrm::_UnitUp()
797cdf0e10cSrcweir  *************************************************************************/
798cdf0e10cSrcweir 
799cdf0e10cSrcweir //Die beiden folgenden Methoden versuchen zunaechst den Crsr in die
800cdf0e10cSrcweir //nachste/folgende Zeile zu setzen. Gibt es im Frame keine vorhergehende/
801cdf0e10cSrcweir //folgende Zeile, so wird der Aufruf an die Basisklasse weitergeleitet.
802cdf0e10cSrcweir //Die Horizontale Ausrichtung des Crsr wird hinterher von der CrsrShell
803cdf0e10cSrcweir //vorgenommen.
804cdf0e10cSrcweir 
805cdf0e10cSrcweir class SwSetToRightMargin
806cdf0e10cSrcweir {
807cdf0e10cSrcweir 	sal_Bool bRight;
808cdf0e10cSrcweir public:
SwSetToRightMargin()809cdf0e10cSrcweir 	inline SwSetToRightMargin() : bRight( sal_False ) { }
~SwSetToRightMargin()810cdf0e10cSrcweir 	inline ~SwSetToRightMargin() { SwTxtCursor::SetRightMargin( bRight ); }
SetRight(const sal_Bool bNew)811cdf0e10cSrcweir 	inline void SetRight( const sal_Bool bNew ) { bRight = bNew; }
812cdf0e10cSrcweir };
813cdf0e10cSrcweir 
_UnitUp(SwPaM * pPam,const SwTwips nOffset,sal_Bool bSetInReadOnly) const814cdf0e10cSrcweir sal_Bool SwTxtFrm::_UnitUp( SwPaM *pPam, const SwTwips nOffset,
815cdf0e10cSrcweir 							sal_Bool bSetInReadOnly ) const
816cdf0e10cSrcweir {
817cdf0e10cSrcweir 	// 8626: Im Notfall den RightMargin setzen.
818cdf0e10cSrcweir 	SwSetToRightMargin aSet;
819cdf0e10cSrcweir 
820cdf0e10cSrcweir 	if( IsInTab() &&
821cdf0e10cSrcweir 		pPam->GetNode( sal_True )->StartOfSectionNode() !=
822cdf0e10cSrcweir 		pPam->GetNode( sal_False )->StartOfSectionNode() )
823cdf0e10cSrcweir 	{
824cdf0e10cSrcweir 		//Wenn der PaM in unterschiedlichen Boxen sitzt, so handelt es sich um
825cdf0e10cSrcweir 		//eine Tabellenselektion; diese wird von der Basisklasse abgearbeitet.
826cdf0e10cSrcweir 		return SwCntntFrm::UnitUp( pPam, nOffset, bSetInReadOnly );
827cdf0e10cSrcweir 	}
828cdf0e10cSrcweir 
829cdf0e10cSrcweir 	((SwTxtFrm*)this)->GetFormatted();
830cdf0e10cSrcweir 	const xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex();
831cdf0e10cSrcweir 	SwRect aCharBox;
832cdf0e10cSrcweir 
833cdf0e10cSrcweir 	if( !IsEmpty() && !IsHiddenNow() )
834cdf0e10cSrcweir 	{
835cdf0e10cSrcweir 		xub_StrLen nFormat = STRING_LEN;
836cdf0e10cSrcweir 		do
837cdf0e10cSrcweir 		{
838cdf0e10cSrcweir 			if( nFormat != STRING_LEN && !IsFollow() )
839cdf0e10cSrcweir 				lcl_ChangeOffset( ((SwTxtFrm*)this), nFormat );
840cdf0e10cSrcweir 
841cdf0e10cSrcweir 			SwTxtSizeInfo aInf( (SwTxtFrm*)this );
842cdf0e10cSrcweir 			SwTxtCursor  aLine( ((SwTxtFrm*)this), &aInf );
843cdf0e10cSrcweir 
844cdf0e10cSrcweir 			// 8116: Flys ohne Umlauf und IsDummy(); hier wegoptimiert
845cdf0e10cSrcweir 			if( nPos )
846cdf0e10cSrcweir 				aLine.CharCrsrToLine( nPos );
847cdf0e10cSrcweir 			else
848cdf0e10cSrcweir 				aLine.Top();
849cdf0e10cSrcweir 
850cdf0e10cSrcweir 			const SwLineLayout *pPrevLine = aLine.GetPrevLine();
851cdf0e10cSrcweir             const xub_StrLen nStart = aLine.GetStart();
852cdf0e10cSrcweir             aLine.GetCharRect( &aCharBox, nPos );
853cdf0e10cSrcweir 
854cdf0e10cSrcweir             sal_Bool bSecondOfDouble = ( aInf.IsMulti() && ! aInf.IsFirstMulti() );
855cdf0e10cSrcweir             sal_Bool bPrevLine = ( pPrevLine && pPrevLine != aLine.GetCurr() );
856cdf0e10cSrcweir 
857cdf0e10cSrcweir             if( !pPrevLine && !bSecondOfDouble && GetOfst() && !IsFollow() )
858cdf0e10cSrcweir 			{
859cdf0e10cSrcweir 				nFormat = GetOfst();
860cdf0e10cSrcweir 				xub_StrLen nDiff = aLine.GetLength();
861cdf0e10cSrcweir 				if( !nDiff )
862cdf0e10cSrcweir 					nDiff = MIN_OFFSET_STEP;
863cdf0e10cSrcweir 				if( nFormat > nDiff )
864cdf0e10cSrcweir 					nFormat = nFormat - nDiff;
865cdf0e10cSrcweir 				else
866cdf0e10cSrcweir 					nFormat = 0;
867cdf0e10cSrcweir 				continue;
868cdf0e10cSrcweir 			}
869cdf0e10cSrcweir 
870cdf0e10cSrcweir             // we select the target line for the cursor, in case we are in a
871cdf0e10cSrcweir             // double line portion, prev line = curr line
872cdf0e10cSrcweir             if( bPrevLine && !bSecondOfDouble )
873cdf0e10cSrcweir             {
874cdf0e10cSrcweir                 aLine.PrevLine();
875cdf0e10cSrcweir                 while ( aLine.GetStart() == nStart &&
876cdf0e10cSrcweir                         0 != ( pPrevLine = aLine.GetPrevLine() ) &&
877cdf0e10cSrcweir                         pPrevLine != aLine.GetCurr() )
878cdf0e10cSrcweir                     aLine.PrevLine();
879cdf0e10cSrcweir             }
880cdf0e10cSrcweir 
881cdf0e10cSrcweir             if ( bPrevLine || bSecondOfDouble )
882cdf0e10cSrcweir             {
883cdf0e10cSrcweir                 aCharBox.SSize().Width() /= 2;
884cdf0e10cSrcweir                 aCharBox.Pos().X() = aCharBox.Pos().X() - 150;
885cdf0e10cSrcweir 
886cdf0e10cSrcweir 				// siehe Kommentar in SwTxtFrm::GetCrsrOfst()
887cdf0e10cSrcweir #ifdef DBG_UTIL
888cdf0e10cSrcweir                 const sal_uLong nOldNode = pPam->GetPoint()->nNode.GetIndex();
889cdf0e10cSrcweir #endif
890cdf0e10cSrcweir 				// Der Node soll nicht gewechselt werden
891cdf0e10cSrcweir                 xub_StrLen nTmpOfst = aLine.GetCrsrOfst( pPam->GetPoint(),
892cdf0e10cSrcweir                                                          aCharBox.Pos(), sal_False );
893cdf0e10cSrcweir 				ASSERT( nOldNode == pPam->GetPoint()->nNode.GetIndex(),
894cdf0e10cSrcweir 						"SwTxtFrm::UnitUp: illegal node change" )
895cdf0e10cSrcweir 
896cdf0e10cSrcweir 				// 7684: Wir stellen sicher, dass wir uns nach oben bewegen.
897cdf0e10cSrcweir                 if( nTmpOfst >= nStart && nStart && !bSecondOfDouble )
898cdf0e10cSrcweir 				{
899cdf0e10cSrcweir                     nTmpOfst = nStart;
900cdf0e10cSrcweir 					aSet.SetRight( sal_True );
901cdf0e10cSrcweir 				}
902cdf0e10cSrcweir 				pPam->GetPoint()->nContent =
903cdf0e10cSrcweir                       SwIndex( ((SwTxtFrm*)this)->GetTxtNode(), nTmpOfst );
904cdf0e10cSrcweir 				return sal_True;
905cdf0e10cSrcweir 			}
906cdf0e10cSrcweir 
907cdf0e10cSrcweir             if ( IsFollow() )
908cdf0e10cSrcweir 			{
909cdf0e10cSrcweir 				aLine.GetCharRect( &aCharBox, nPos );
910cdf0e10cSrcweir 				aCharBox.SSize().Width() /= 2;
911cdf0e10cSrcweir 			}
912cdf0e10cSrcweir 			break;
913cdf0e10cSrcweir 		} while ( sal_True );
914cdf0e10cSrcweir 	}
915cdf0e10cSrcweir 	/* Wenn this ein Follow ist und ein Prev miszlang, so
916cdf0e10cSrcweir 	 * muessen wir in die letzte Zeile des Master ... und der sind wir.
917cdf0e10cSrcweir 	 * Oder wir sind ein Follow mit Follow, dann muessen wir uns den
918cdf0e10cSrcweir 	 * Master extra besorgen...
919cdf0e10cSrcweir 	 */
920cdf0e10cSrcweir 	if ( IsFollow() )
921cdf0e10cSrcweir     {
922cdf0e10cSrcweir         const SwTxtFrm *pTmpPrev = FindMaster();
923cdf0e10cSrcweir 		xub_StrLen nOffs = GetOfst();
924cdf0e10cSrcweir         if( pTmpPrev )
925cdf0e10cSrcweir 		{
926cdf0e10cSrcweir 			ViewShell *pSh = getRootFrm()->GetCurrShell();
927cdf0e10cSrcweir 			sal_Bool bProtectedAllowed = pSh && pSh->GetViewOptions()->IsCursorInProtectedArea();
928cdf0e10cSrcweir             const SwTxtFrm *pPrevPrev = pTmpPrev;
929cdf0e10cSrcweir 			// Hier werden geschuetzte Frames und Frame ohne Inhalt ausgelassen
930cdf0e10cSrcweir 			while( pPrevPrev && ( pPrevPrev->GetOfst() == nOffs ||
931cdf0e10cSrcweir 				   ( !bProtectedAllowed && pPrevPrev->IsProtected() ) ) )
932cdf0e10cSrcweir 			{
933cdf0e10cSrcweir                 pTmpPrev = pPrevPrev;
934cdf0e10cSrcweir                 nOffs = pTmpPrev->GetOfst();
935cdf0e10cSrcweir 				if ( pPrevPrev->IsFollow() )
936cdf0e10cSrcweir                     pPrevPrev = pTmpPrev->FindMaster();
937cdf0e10cSrcweir 				else
938cdf0e10cSrcweir 					pPrevPrev = NULL;
939cdf0e10cSrcweir 			}
940cdf0e10cSrcweir 			if ( !pPrevPrev )
941cdf0e10cSrcweir                 return pTmpPrev->SwCntntFrm::UnitUp( pPam, nOffset, bSetInReadOnly );
942cdf0e10cSrcweir 			aCharBox.Pos().Y() = pPrevPrev->Frm().Bottom() - 1;
943cdf0e10cSrcweir 			return pPrevPrev->GetKeyCrsrOfst( pPam->GetPoint(), aCharBox.Pos() );
944cdf0e10cSrcweir 		}
945cdf0e10cSrcweir 	}
946cdf0e10cSrcweir 	return SwCntntFrm::UnitUp( pPam, nOffset, bSetInReadOnly );
947cdf0e10cSrcweir }
948cdf0e10cSrcweir 
949cdf0e10cSrcweir //
950cdf0e10cSrcweir // Used for Bidi. nPos is the logical position in the string, bLeft indicates
951cdf0e10cSrcweir // if left arrow or right arrow was pressed. The return values are:
952cdf0e10cSrcweir // nPos: the new visual position
953cdf0e10cSrcweir // bLeft: whether the break iterator has to add or subtract from the
954cdf0e10cSrcweir //          current position
lcl_VisualMoveRecursion(const SwLineLayout & rCurrLine,xub_StrLen nIdx,xub_StrLen & nPos,sal_Bool & bRight,sal_uInt8 & nCrsrLevel,sal_uInt8 nDefaultDir)955cdf0e10cSrcweir void lcl_VisualMoveRecursion( const SwLineLayout& rCurrLine, xub_StrLen nIdx,
956cdf0e10cSrcweir                               xub_StrLen& nPos, sal_Bool& bRight,
957cdf0e10cSrcweir                               sal_uInt8& nCrsrLevel, sal_uInt8 nDefaultDir )
958cdf0e10cSrcweir {
959cdf0e10cSrcweir     const SwLinePortion* pPor = rCurrLine.GetFirstPortion();
960cdf0e10cSrcweir     const SwLinePortion* pLast = 0;
961cdf0e10cSrcweir 
962cdf0e10cSrcweir     // what's the current portion
963cdf0e10cSrcweir     while ( pPor && nIdx + pPor->GetLen() <= nPos )
964cdf0e10cSrcweir     {
965cdf0e10cSrcweir         nIdx = nIdx + pPor->GetLen();
966cdf0e10cSrcweir         pLast = pPor;
967cdf0e10cSrcweir         pPor = pPor->GetPortion();
968cdf0e10cSrcweir     }
969cdf0e10cSrcweir 
970cdf0e10cSrcweir     if ( bRight )
971cdf0e10cSrcweir     {
972cdf0e10cSrcweir         sal_Bool bRecurse = pPor && pPor->IsMultiPortion() &&
973cdf0e10cSrcweir                            ((SwMultiPortion*)pPor)->IsBidi();
974cdf0e10cSrcweir 
975cdf0e10cSrcweir         // 1. special case: at beginning of bidi portion
976cdf0e10cSrcweir         if ( bRecurse && nIdx == nPos )
977cdf0e10cSrcweir         {
978cdf0e10cSrcweir             nPos = nPos + pPor->GetLen();
979cdf0e10cSrcweir 
980cdf0e10cSrcweir             // leave bidi portion
981cdf0e10cSrcweir             if ( nCrsrLevel != nDefaultDir )
982cdf0e10cSrcweir             {
983cdf0e10cSrcweir                 bRecurse = sal_False;
984cdf0e10cSrcweir             }
985cdf0e10cSrcweir             else
986cdf0e10cSrcweir                 // special case:
987cdf0e10cSrcweir                 // buffer: abcXYZ123 in LTR paragraph
988cdf0e10cSrcweir                 // view:   abc123ZYX
989cdf0e10cSrcweir                 // cursor is between c and X in the buffer and cursor level = 0
990cdf0e10cSrcweir                 nCrsrLevel++;
991cdf0e10cSrcweir         }
992cdf0e10cSrcweir 
993cdf0e10cSrcweir         // 2. special case: at beginning of portion after bidi portion
994cdf0e10cSrcweir         else if ( pLast && pLast->IsMultiPortion() &&
995cdf0e10cSrcweir                  ((SwMultiPortion*)pLast)->IsBidi() && nIdx == nPos )
996cdf0e10cSrcweir         {
997cdf0e10cSrcweir             // enter bidi portion
998cdf0e10cSrcweir             if ( nCrsrLevel != nDefaultDir )
999cdf0e10cSrcweir             {
1000cdf0e10cSrcweir                 bRecurse = sal_True;
1001cdf0e10cSrcweir                 nIdx = nIdx - pLast->GetLen();
1002cdf0e10cSrcweir                 pPor = pLast;
1003cdf0e10cSrcweir             }
1004cdf0e10cSrcweir         }
1005cdf0e10cSrcweir 
1006cdf0e10cSrcweir         // Recursion
1007cdf0e10cSrcweir         if ( bRecurse )
1008cdf0e10cSrcweir         {
1009cdf0e10cSrcweir             const SwLineLayout& rLine = ((SwMultiPortion*)pPor)->GetRoot();
1010cdf0e10cSrcweir             xub_StrLen nTmpPos = nPos - nIdx;
1011cdf0e10cSrcweir             sal_Bool bTmpForward = ! bRight;
1012cdf0e10cSrcweir             sal_uInt8 nTmpCrsrLevel = nCrsrLevel;
1013cdf0e10cSrcweir             lcl_VisualMoveRecursion( rLine, 0, nTmpPos, bTmpForward,
1014cdf0e10cSrcweir                                      nTmpCrsrLevel, nDefaultDir + 1 );
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir             nPos = nTmpPos + nIdx;
1017cdf0e10cSrcweir             bRight = bTmpForward;
1018cdf0e10cSrcweir             nCrsrLevel = nTmpCrsrLevel;
1019cdf0e10cSrcweir         }
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir         // go forward
1022cdf0e10cSrcweir         else
1023cdf0e10cSrcweir         {
1024cdf0e10cSrcweir             bRight = sal_True;
1025cdf0e10cSrcweir             nCrsrLevel = nDefaultDir;
1026cdf0e10cSrcweir         }
1027cdf0e10cSrcweir 
1028cdf0e10cSrcweir     }
1029cdf0e10cSrcweir     else
1030cdf0e10cSrcweir     {
1031cdf0e10cSrcweir         sal_Bool bRecurse = pPor && pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsBidi();
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir         // 1. special case: at beginning of bidi portion
1034cdf0e10cSrcweir         if ( bRecurse && nIdx == nPos )
1035cdf0e10cSrcweir         {
1036cdf0e10cSrcweir             // leave bidi portion
1037cdf0e10cSrcweir             if ( nCrsrLevel == nDefaultDir )
1038cdf0e10cSrcweir             {
1039cdf0e10cSrcweir                 bRecurse = sal_False;
1040cdf0e10cSrcweir             }
1041cdf0e10cSrcweir         }
1042cdf0e10cSrcweir 
1043cdf0e10cSrcweir         // 2. special case: at beginning of portion after bidi portion
1044cdf0e10cSrcweir         else if ( pLast && pLast->IsMultiPortion() &&
1045cdf0e10cSrcweir                  ((SwMultiPortion*)pLast)->IsBidi() && nIdx == nPos )
1046cdf0e10cSrcweir         {
1047cdf0e10cSrcweir             nPos = nPos - pLast->GetLen();
1048cdf0e10cSrcweir 
1049cdf0e10cSrcweir             // enter bidi portion
1050cdf0e10cSrcweir             if ( nCrsrLevel % 2 == nDefaultDir % 2 )
1051cdf0e10cSrcweir             {
1052cdf0e10cSrcweir                 bRecurse = sal_True;
1053cdf0e10cSrcweir                 nIdx = nIdx - pLast->GetLen();
1054cdf0e10cSrcweir                 pPor = pLast;
1055cdf0e10cSrcweir 
1056cdf0e10cSrcweir                 // special case:
1057cdf0e10cSrcweir                 // buffer: abcXYZ123 in LTR paragraph
1058cdf0e10cSrcweir                 // view:   abc123ZYX
1059cdf0e10cSrcweir                 // cursor is behind 3 in the buffer and cursor level = 2
1060cdf0e10cSrcweir                 if ( nDefaultDir + 2 == nCrsrLevel )
1061cdf0e10cSrcweir                     nPos = nPos + pLast->GetLen();
1062cdf0e10cSrcweir             }
1063cdf0e10cSrcweir         }
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir         // go forward
1066cdf0e10cSrcweir         if ( bRecurse )
1067cdf0e10cSrcweir         {
1068cdf0e10cSrcweir             const SwLineLayout& rLine = ((SwMultiPortion*)pPor)->GetRoot();
1069cdf0e10cSrcweir             xub_StrLen nTmpPos = nPos - nIdx;
1070cdf0e10cSrcweir             sal_Bool bTmpForward = ! bRight;
1071cdf0e10cSrcweir             sal_uInt8 nTmpCrsrLevel = nCrsrLevel;
1072cdf0e10cSrcweir             lcl_VisualMoveRecursion( rLine, 0, nTmpPos, bTmpForward,
1073cdf0e10cSrcweir                                      nTmpCrsrLevel, nDefaultDir + 1 );
1074cdf0e10cSrcweir 
1075cdf0e10cSrcweir             // special case:
1076cdf0e10cSrcweir             // buffer: abcXYZ123 in LTR paragraph
1077cdf0e10cSrcweir             // view:   abc123ZYX
1078cdf0e10cSrcweir             // cursor is between Z and 1 in the buffer and cursor level = 2
1079cdf0e10cSrcweir             if ( nTmpPos == pPor->GetLen() && nTmpCrsrLevel == nDefaultDir + 1 )
1080cdf0e10cSrcweir             {
1081cdf0e10cSrcweir                 nTmpPos = nTmpPos - pPor->GetLen();
1082cdf0e10cSrcweir                 nTmpCrsrLevel = nDefaultDir;
1083cdf0e10cSrcweir                 bTmpForward = ! bTmpForward;
1084cdf0e10cSrcweir             }
1085cdf0e10cSrcweir 
1086cdf0e10cSrcweir             nPos = nTmpPos + nIdx;
1087cdf0e10cSrcweir             bRight = bTmpForward;
1088cdf0e10cSrcweir             nCrsrLevel = nTmpCrsrLevel;
1089cdf0e10cSrcweir         }
1090cdf0e10cSrcweir 
1091cdf0e10cSrcweir         // go backward
1092cdf0e10cSrcweir         else
1093cdf0e10cSrcweir         {
1094cdf0e10cSrcweir             bRight = sal_False;
1095cdf0e10cSrcweir             nCrsrLevel = nDefaultDir;
1096cdf0e10cSrcweir         }
1097cdf0e10cSrcweir     }
1098cdf0e10cSrcweir }
1099cdf0e10cSrcweir 
PrepareVisualMove(xub_StrLen & nPos,sal_uInt8 & nCrsrLevel,sal_Bool & bForward,sal_Bool bInsertCrsr)1100cdf0e10cSrcweir void SwTxtFrm::PrepareVisualMove( xub_StrLen& nPos, sal_uInt8& nCrsrLevel,
1101cdf0e10cSrcweir                                   sal_Bool& bForward, sal_Bool bInsertCrsr )
1102cdf0e10cSrcweir {
1103cdf0e10cSrcweir     if( IsEmpty() || IsHiddenNow() )
1104cdf0e10cSrcweir         return;
1105cdf0e10cSrcweir 
1106cdf0e10cSrcweir     ((SwTxtFrm*)this)->GetFormatted();
1107cdf0e10cSrcweir 
1108cdf0e10cSrcweir     SwTxtSizeInfo aInf( (SwTxtFrm*)this );
1109cdf0e10cSrcweir     SwTxtCursor  aLine( ((SwTxtFrm*)this), &aInf );
1110cdf0e10cSrcweir 
1111cdf0e10cSrcweir     if( nPos )
1112cdf0e10cSrcweir         aLine.CharCrsrToLine( nPos );
1113cdf0e10cSrcweir     else
1114cdf0e10cSrcweir         aLine.Top();
1115cdf0e10cSrcweir 
1116cdf0e10cSrcweir     const SwLineLayout* pLine = aLine.GetCurr();
1117cdf0e10cSrcweir     const xub_StrLen nStt = aLine.GetStart();
1118cdf0e10cSrcweir     const xub_StrLen nLen = pLine->GetLen();
1119cdf0e10cSrcweir 
1120cdf0e10cSrcweir     // We have to distinguish between an insert and overwrite cursor:
1121cdf0e10cSrcweir     // The insert cursor position depends on the cursor level:
1122cdf0e10cSrcweir     // buffer:  abcXYZdef in LTR paragraph
1123cdf0e10cSrcweir     // display: abcZYXdef
1124cdf0e10cSrcweir     // If cursor is between c and X in the buffer and cursor level is 0,
1125cdf0e10cSrcweir     // the cursor blinks between c and Z and -> sets the cursor between Z and Y.
1126cdf0e10cSrcweir     // If the cursor level is 1, the cursor blinks between X and d and
1127cdf0e10cSrcweir     // -> sets the cursor between d and e.
1128cdf0e10cSrcweir     // The overwrite cursor simply travels to the next visual character.
1129cdf0e10cSrcweir     if ( bInsertCrsr )
1130cdf0e10cSrcweir     {
1131cdf0e10cSrcweir         lcl_VisualMoveRecursion( *pLine, nStt, nPos, bForward,
1132cdf0e10cSrcweir                                  nCrsrLevel, IsRightToLeft() ? 1 : 0 );
1133cdf0e10cSrcweir         return;
1134cdf0e10cSrcweir     }
1135cdf0e10cSrcweir 
1136cdf0e10cSrcweir     const sal_uInt8 nDefaultDir = static_cast<sal_uInt8>(IsRightToLeft() ? UBIDI_RTL : UBIDI_LTR);
1137cdf0e10cSrcweir     const sal_Bool bVisualRight = ( nDefaultDir == UBIDI_LTR && bForward ) ||
1138cdf0e10cSrcweir                                   ( nDefaultDir == UBIDI_RTL && ! bForward );
1139cdf0e10cSrcweir 
1140cdf0e10cSrcweir     //
1141cdf0e10cSrcweir     // Bidi functions from icu 2.0
1142cdf0e10cSrcweir     //
1143cdf0e10cSrcweir     const sal_Unicode* pLineString = GetTxtNode()->GetTxt().GetBuffer();
1144cdf0e10cSrcweir     pLine += nStt;
1145cdf0e10cSrcweir 
1146cdf0e10cSrcweir     UErrorCode nError = U_ZERO_ERROR;
1147cdf0e10cSrcweir     UBiDi* pBidi = ubidi_openSized( nLen, 0, &nError );
1148cdf0e10cSrcweir     ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), nLen, nDefaultDir, NULL, &nError );	// UChar != sal_Unicode in MinGW
1149cdf0e10cSrcweir 
1150cdf0e10cSrcweir     xub_StrLen nTmpPos;
1151cdf0e10cSrcweir     sal_Bool bOutOfBounds = sal_False;
1152cdf0e10cSrcweir 
1153cdf0e10cSrcweir     if ( nPos < nStt + nLen )
1154cdf0e10cSrcweir     {
1155cdf0e10cSrcweir         nTmpPos = (xub_StrLen)ubidi_getVisualIndex( pBidi, nPos, &nError );
1156cdf0e10cSrcweir 
1157cdf0e10cSrcweir         // visual indices are always LTR aligned
1158cdf0e10cSrcweir         if ( bVisualRight )
1159cdf0e10cSrcweir         {
1160cdf0e10cSrcweir             if ( nTmpPos + 1 < nStt + nLen )
1161cdf0e10cSrcweir                 ++nTmpPos;
1162cdf0e10cSrcweir             else
1163cdf0e10cSrcweir             {
1164cdf0e10cSrcweir                 nPos = nDefaultDir == UBIDI_RTL ? 0 : nStt + nLen;
1165cdf0e10cSrcweir                 bOutOfBounds = sal_True;
1166cdf0e10cSrcweir             }
1167cdf0e10cSrcweir         }
1168cdf0e10cSrcweir         else
1169cdf0e10cSrcweir         {
1170cdf0e10cSrcweir             if ( nTmpPos )
1171cdf0e10cSrcweir                 --nTmpPos;
1172cdf0e10cSrcweir             else
1173cdf0e10cSrcweir             {
1174cdf0e10cSrcweir                 nPos = nDefaultDir == UBIDI_RTL ? nStt + nLen : 0;
1175cdf0e10cSrcweir                 bOutOfBounds = sal_True;
1176cdf0e10cSrcweir             }
1177cdf0e10cSrcweir         }
1178cdf0e10cSrcweir     }
1179cdf0e10cSrcweir     else
1180cdf0e10cSrcweir     {
1181cdf0e10cSrcweir         nTmpPos = nDefaultDir == UBIDI_LTR ? nPos - 1 : 0;
1182cdf0e10cSrcweir     }
1183cdf0e10cSrcweir 
1184cdf0e10cSrcweir     if ( ! bOutOfBounds )
1185cdf0e10cSrcweir     {
1186cdf0e10cSrcweir         nPos = (xub_StrLen)ubidi_getLogicalIndex( pBidi, nTmpPos, &nError );
1187cdf0e10cSrcweir 
1188cdf0e10cSrcweir         if ( bForward )
1189cdf0e10cSrcweir         {
1190cdf0e10cSrcweir             if ( nPos )
1191cdf0e10cSrcweir                 --nPos;
1192cdf0e10cSrcweir             else
1193cdf0e10cSrcweir             {
1194cdf0e10cSrcweir                 ++nPos;
1195cdf0e10cSrcweir                 bForward = ! bForward;
1196cdf0e10cSrcweir             }
1197cdf0e10cSrcweir         }
1198cdf0e10cSrcweir         else
1199cdf0e10cSrcweir             ++nPos;
1200cdf0e10cSrcweir     }
1201cdf0e10cSrcweir 
1202cdf0e10cSrcweir     ubidi_close( pBidi );
1203cdf0e10cSrcweir }
1204cdf0e10cSrcweir 
1205cdf0e10cSrcweir /*************************************************************************
1206cdf0e10cSrcweir  *						SwTxtFrm::_UnitDown()
1207cdf0e10cSrcweir  *************************************************************************/
1208cdf0e10cSrcweir 
_UnitDown(SwPaM * pPam,const SwTwips nOffset,sal_Bool bSetInReadOnly) const1209cdf0e10cSrcweir sal_Bool SwTxtFrm::_UnitDown(SwPaM *pPam, const SwTwips nOffset,
1210cdf0e10cSrcweir 							sal_Bool bSetInReadOnly ) const
1211cdf0e10cSrcweir {
1212cdf0e10cSrcweir 
1213cdf0e10cSrcweir 	if ( IsInTab() &&
1214cdf0e10cSrcweir 		pPam->GetNode( sal_True )->StartOfSectionNode() !=
1215cdf0e10cSrcweir 		pPam->GetNode( sal_False )->StartOfSectionNode() )
1216cdf0e10cSrcweir 	{
1217cdf0e10cSrcweir 		//Wenn der PaM in unterschiedlichen Boxen sitzt, so handelt es sich um
1218cdf0e10cSrcweir 		//eine Tabellenselektion; diese wird von der Basisklasse abgearbeitet.
1219cdf0e10cSrcweir 		return SwCntntFrm::UnitDown( pPam, nOffset, bSetInReadOnly );
1220cdf0e10cSrcweir 	}
1221cdf0e10cSrcweir 	((SwTxtFrm*)this)->GetFormatted();
1222cdf0e10cSrcweir 	const xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex();
1223cdf0e10cSrcweir 	SwRect aCharBox;
1224cdf0e10cSrcweir     const SwCntntFrm *pTmpFollow = 0;
1225cdf0e10cSrcweir 
1226cdf0e10cSrcweir     if ( IsVertical() )
1227cdf0e10cSrcweir         ((SwTxtFrm*)this)->SwapWidthAndHeight();
1228cdf0e10cSrcweir 
1229cdf0e10cSrcweir 	if ( !IsEmpty() && !IsHiddenNow() )
1230cdf0e10cSrcweir 	{
1231cdf0e10cSrcweir 		xub_StrLen nFormat = STRING_LEN;
1232cdf0e10cSrcweir 		do
1233cdf0e10cSrcweir 		{
1234cdf0e10cSrcweir 			if( nFormat != STRING_LEN && !IsFollow() &&
1235cdf0e10cSrcweir 				!lcl_ChangeOffset( ((SwTxtFrm*)this), nFormat ) )
1236cdf0e10cSrcweir 				break;
1237cdf0e10cSrcweir 
1238cdf0e10cSrcweir 			SwTxtSizeInfo aInf( (SwTxtFrm*)this );
1239cdf0e10cSrcweir 			SwTxtCursor  aLine( ((SwTxtFrm*)this), &aInf );
1240cdf0e10cSrcweir 			nFormat = aLine.GetEnd();
1241cdf0e10cSrcweir 
1242cdf0e10cSrcweir 			aLine.CharCrsrToLine( nPos );
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir             const SwLineLayout* pNextLine = aLine.GetNextLine();
1245cdf0e10cSrcweir             const xub_StrLen nStart = aLine.GetStart();
1246cdf0e10cSrcweir             aLine.GetCharRect( &aCharBox, nPos );
1247cdf0e10cSrcweir 
1248cdf0e10cSrcweir             sal_Bool bFirstOfDouble = ( aInf.IsMulti() && aInf.IsFirstMulti() );
1249cdf0e10cSrcweir 
1250cdf0e10cSrcweir             if( pNextLine || bFirstOfDouble )
1251cdf0e10cSrcweir 			{
1252cdf0e10cSrcweir                 aCharBox.SSize().Width() /= 2;
1253cdf0e10cSrcweir #ifdef DBG_UTIL
1254cdf0e10cSrcweir 				// siehe Kommentar in SwTxtFrm::GetCrsrOfst()
1255cdf0e10cSrcweir                 const sal_uLong nOldNode = pPam->GetPoint()->nNode.GetIndex();
1256cdf0e10cSrcweir #endif
1257cdf0e10cSrcweir                 if ( pNextLine && ! bFirstOfDouble )
1258cdf0e10cSrcweir                     aLine.NextLine();
1259cdf0e10cSrcweir 
1260cdf0e10cSrcweir                 xub_StrLen nTmpOfst = aLine.GetCrsrOfst( pPam->GetPoint(),
1261cdf0e10cSrcweir 								 aCharBox.Pos(), sal_False );
1262cdf0e10cSrcweir 				ASSERT( nOldNode == pPam->GetPoint()->nNode.GetIndex(),
1263cdf0e10cSrcweir 					"SwTxtFrm::UnitDown: illegal node change" )
1264cdf0e10cSrcweir 
1265cdf0e10cSrcweir 				// 7684: Wir stellen sicher, dass wir uns nach unten bewegen.
1266cdf0e10cSrcweir                 if( nTmpOfst <= nStart && ! bFirstOfDouble )
1267cdf0e10cSrcweir                     nTmpOfst = nStart + 1;
1268cdf0e10cSrcweir 				pPam->GetPoint()->nContent =
1269cdf0e10cSrcweir                       SwIndex( ((SwTxtFrm*)this)->GetTxtNode(), nTmpOfst );
1270cdf0e10cSrcweir 
1271cdf0e10cSrcweir                 if ( IsVertical() )
1272cdf0e10cSrcweir                     ((SwTxtFrm*)this)->SwapWidthAndHeight();
1273cdf0e10cSrcweir 
1274cdf0e10cSrcweir 				return sal_True;
1275cdf0e10cSrcweir 			}
1276cdf0e10cSrcweir             if( 0 != ( pTmpFollow = GetFollow() ) )
1277cdf0e10cSrcweir 			{   // geschuetzte Follows auslassen
1278cdf0e10cSrcweir                 const SwCntntFrm* pTmp = pTmpFollow;
1279cdf0e10cSrcweir 				ViewShell *pSh = getRootFrm()->GetCurrShell();
1280cdf0e10cSrcweir 				if( !pSh || !pSh->GetViewOptions()->IsCursorInProtectedArea() )
1281cdf0e10cSrcweir 				{
1282cdf0e10cSrcweir                     while( pTmpFollow && pTmpFollow->IsProtected() )
1283cdf0e10cSrcweir 					{
1284cdf0e10cSrcweir                         pTmp = pTmpFollow;
1285cdf0e10cSrcweir                         pTmpFollow = pTmpFollow->GetFollow();
1286cdf0e10cSrcweir 					}
1287cdf0e10cSrcweir 				}
1288cdf0e10cSrcweir                 if( !pTmpFollow ) // nur noch geschuetzte
1289cdf0e10cSrcweir                 {
1290cdf0e10cSrcweir                     if ( IsVertical() )
1291cdf0e10cSrcweir                         ((SwTxtFrm*)this)->SwapWidthAndHeight();
1292cdf0e10cSrcweir                     return pTmp->SwCntntFrm::UnitDown( pPam, nOffset, bSetInReadOnly );
1293cdf0e10cSrcweir                 }
1294cdf0e10cSrcweir 
1295cdf0e10cSrcweir                 aLine.GetCharRect( &aCharBox, nPos );
1296cdf0e10cSrcweir 				aCharBox.SSize().Width() /= 2;
1297cdf0e10cSrcweir 			}
1298cdf0e10cSrcweir 			else if( !IsFollow() )
1299cdf0e10cSrcweir 			{
1300cdf0e10cSrcweir 				xub_StrLen nTmpLen = aInf.GetTxt().Len();
1301cdf0e10cSrcweir 				if( aLine.GetEnd() < nTmpLen )
1302cdf0e10cSrcweir 				{
1303cdf0e10cSrcweir 					if( nFormat <= GetOfst() )
1304cdf0e10cSrcweir 					{
1305cdf0e10cSrcweir 						nFormat = Min( xub_StrLen( GetOfst() + MIN_OFFSET_STEP ),
1306cdf0e10cSrcweir 									   nTmpLen );
1307cdf0e10cSrcweir 						if( nFormat <= GetOfst() )
1308cdf0e10cSrcweir 							break;
1309cdf0e10cSrcweir 					}
1310cdf0e10cSrcweir 					continue;
1311cdf0e10cSrcweir 				}
1312cdf0e10cSrcweir 			}
1313cdf0e10cSrcweir 			break;
1314cdf0e10cSrcweir 		} while( sal_True );
1315cdf0e10cSrcweir 	}
1316cdf0e10cSrcweir 	else
1317cdf0e10cSrcweir         pTmpFollow = GetFollow();
1318cdf0e10cSrcweir 
1319cdf0e10cSrcweir     if ( IsVertical() )
1320cdf0e10cSrcweir         ((SwTxtFrm*)this)->SwapWidthAndHeight();
1321cdf0e10cSrcweir 
1322cdf0e10cSrcweir 	// Bei Follows schlagen wir eine Abkuerzung
1323cdf0e10cSrcweir     if( pTmpFollow )
1324cdf0e10cSrcweir 	{
1325cdf0e10cSrcweir         aCharBox.Pos().Y() = pTmpFollow->Frm().Top() + 1;
1326cdf0e10cSrcweir         return ((SwTxtFrm*)pTmpFollow)->GetKeyCrsrOfst( pPam->GetPoint(),
1327cdf0e10cSrcweir 													 aCharBox.Pos() );
1328cdf0e10cSrcweir 	}
1329cdf0e10cSrcweir 	return SwCntntFrm::UnitDown( pPam, nOffset, bSetInReadOnly );
1330cdf0e10cSrcweir }
1331cdf0e10cSrcweir 
1332cdf0e10cSrcweir /*************************************************************************
1333cdf0e10cSrcweir  *					 virtual SwTxtFrm::UnitUp()
1334cdf0e10cSrcweir  *************************************************************************/
1335cdf0e10cSrcweir 
UnitUp(SwPaM * pPam,const SwTwips nOffset,sal_Bool bSetInReadOnly) const1336cdf0e10cSrcweir sal_Bool SwTxtFrm::UnitUp(SwPaM *pPam, const SwTwips nOffset,
1337cdf0e10cSrcweir 							sal_Bool bSetInReadOnly ) const
1338cdf0e10cSrcweir {
1339cdf0e10cSrcweir 	/* Im CrsrSh::Up() wird CntntNode::GetFrm() gerufen.
1340cdf0e10cSrcweir 	 * Dies liefert _immer_ den Master zurueck.
1341cdf0e10cSrcweir 	 * Um das Cursortravelling nicht zu belasten, korrigieren wir
1342cdf0e10cSrcweir 	 * hier im SwTxtFrm.
1343cdf0e10cSrcweir 	 * Wir ermittelt UnitUp fuer pFrm, pFrm ist entweder ein Master (=this)
1344cdf0e10cSrcweir 	 * oder ein Follow (!=this)
1345cdf0e10cSrcweir 	 */
1346cdf0e10cSrcweir 	const SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, *(pPam->GetPoint()),
1347cdf0e10cSrcweir 										   SwTxtCursor::IsRightMargin() );
1348cdf0e10cSrcweir 	const sal_Bool bRet = pFrm->_UnitUp( pPam, nOffset, bSetInReadOnly );
1349cdf0e10cSrcweir 
1350cdf0e10cSrcweir 	// 8626: kein SwTxtCursor::SetRightMargin( sal_False );
1351cdf0e10cSrcweir 	// statt dessen steht ein SwSetToRightMargin im _UnitUp
1352cdf0e10cSrcweir 	return bRet;
1353cdf0e10cSrcweir }
1354cdf0e10cSrcweir 
1355cdf0e10cSrcweir /*************************************************************************
1356cdf0e10cSrcweir  *					 virtual SwTxtFrm::UnitDown()
1357cdf0e10cSrcweir  *************************************************************************/
1358cdf0e10cSrcweir 
UnitDown(SwPaM * pPam,const SwTwips nOffset,sal_Bool bSetInReadOnly) const1359cdf0e10cSrcweir sal_Bool SwTxtFrm::UnitDown(SwPaM *pPam, const SwTwips nOffset,
1360cdf0e10cSrcweir 							sal_Bool bSetInReadOnly ) const
1361cdf0e10cSrcweir {
1362cdf0e10cSrcweir 	const SwTxtFrm *pFrm = GetAdjFrmAtPos((SwTxtFrm*)this, *(pPam->GetPoint()),
1363cdf0e10cSrcweir 										   SwTxtCursor::IsRightMargin() );
1364cdf0e10cSrcweir 	const sal_Bool bRet = pFrm->_UnitDown( pPam, nOffset, bSetInReadOnly );
1365cdf0e10cSrcweir 	SwTxtCursor::SetRightMargin( sal_False );
1366cdf0e10cSrcweir 	return bRet;
1367cdf0e10cSrcweir }
1368cdf0e10cSrcweir 
FillCrsrPos(SwFillData & rFill) const1369cdf0e10cSrcweir void SwTxtFrm::FillCrsrPos( SwFillData& rFill ) const
1370cdf0e10cSrcweir {
1371cdf0e10cSrcweir 	if( !rFill.bColumn && GetUpper()->IsColBodyFrm() ) // ColumnFrms jetzt mit BodyFrm
1372cdf0e10cSrcweir 	{
1373cdf0e10cSrcweir 		const SwColumnFrm* pTmp =
1374cdf0e10cSrcweir 			(SwColumnFrm*)GetUpper()->GetUpper()->GetUpper()->Lower(); // die 1. Spalte
1375cdf0e10cSrcweir 		// der erste SwFrm im BodyFrm der ersten Spalte
1376cdf0e10cSrcweir 		const SwFrm* pFrm = ((SwLayoutFrm*)pTmp->Lower())->Lower();
1377cdf0e10cSrcweir 		MSHORT nNextCol = 0;
1378cdf0e10cSrcweir 		// In welcher Spalte landen wir?
1379cdf0e10cSrcweir 		while( rFill.X() > pTmp->Frm().Right() && pTmp->GetNext() )
1380cdf0e10cSrcweir 		{
1381cdf0e10cSrcweir 			pTmp = (SwColumnFrm*)pTmp->GetNext();
1382cdf0e10cSrcweir 			if( ((SwLayoutFrm*)pTmp->Lower())->Lower() ) // ColumnFrms jetzt mit BodyFrm
1383cdf0e10cSrcweir 			{
1384cdf0e10cSrcweir 				pFrm = ((SwLayoutFrm*)pTmp->Lower())->Lower();
1385cdf0e10cSrcweir 				nNextCol = 0;
1386cdf0e10cSrcweir 			}
1387cdf0e10cSrcweir 			else
1388cdf0e10cSrcweir 				++nNextCol; // leere Spalten erfordern Spaltenumbrueche
1389cdf0e10cSrcweir 		}
1390cdf0e10cSrcweir 		if( pTmp != GetUpper()->GetUpper() ) // Sind wir in einer anderen Spalte gelandet?
1391cdf0e10cSrcweir 		{
1392cdf0e10cSrcweir 			if( !pFrm )
1393cdf0e10cSrcweir 				return;
1394cdf0e10cSrcweir 			if( nNextCol )
1395cdf0e10cSrcweir 			{
1396cdf0e10cSrcweir 				while( pFrm->GetNext() )
1397cdf0e10cSrcweir 					pFrm = pFrm->GetNext();
1398cdf0e10cSrcweir 			}
1399cdf0e10cSrcweir 			else
1400cdf0e10cSrcweir 			{
1401cdf0e10cSrcweir 				while( pFrm->GetNext() && pFrm->Frm().Bottom() < rFill.Y() )
1402cdf0e10cSrcweir 					pFrm = pFrm->GetNext();
1403cdf0e10cSrcweir 			}
1404cdf0e10cSrcweir 			// Kein Fuellen, wenn als letzter Frame in der anvisierten
1405cdf0e10cSrcweir 			// Spalte kein Absatz, sondern z.B. eine Tabelle steht
1406cdf0e10cSrcweir 			if( pFrm->IsTxtFrm() )
1407cdf0e10cSrcweir 			{
1408cdf0e10cSrcweir 				rFill.Fill().nColumnCnt = nNextCol;
1409cdf0e10cSrcweir 				rFill.bColumn = sal_True;
1410cdf0e10cSrcweir 				if( rFill.pPos )
1411cdf0e10cSrcweir 				{
1412cdf0e10cSrcweir 					SwTxtNode* pTxtNd = ((SwTxtFrm*)pFrm)->GetTxtNode();
1413cdf0e10cSrcweir 					rFill.pPos->nNode = *pTxtNd;
1414cdf0e10cSrcweir 					rFill.pPos->nContent.Assign( pTxtNd, pTxtNd->GetTxt().Len() );
1415cdf0e10cSrcweir 				}
1416cdf0e10cSrcweir 				if( nNextCol )
1417cdf0e10cSrcweir 				{
1418cdf0e10cSrcweir 					rFill.aFrm = pTmp->Prt();
1419cdf0e10cSrcweir 					rFill.aFrm += pTmp->Frm().Pos();
1420cdf0e10cSrcweir 				}
1421cdf0e10cSrcweir 				else
1422cdf0e10cSrcweir 					rFill.aFrm = pFrm->Frm();
1423cdf0e10cSrcweir 				((SwTxtFrm*)pFrm)->FillCrsrPos( rFill );
1424cdf0e10cSrcweir 			}
1425cdf0e10cSrcweir 			return;
1426cdf0e10cSrcweir 		}
1427cdf0e10cSrcweir 	}
1428cdf0e10cSrcweir 	sal_Bool bFill = sal_True;
1429cdf0e10cSrcweir 	SwFont *pFnt;
1430cdf0e10cSrcweir 	SwTxtFmtColl* pColl = GetTxtNode()->GetTxtColl();
1431cdf0e10cSrcweir 	MSHORT nFirst = GetTxtNode()->GetSwAttrSet().GetULSpace().GetLower();
1432cdf0e10cSrcweir 	SwTwips nDiff = rFill.Y() - Frm().Bottom();
1433cdf0e10cSrcweir 	if( nDiff < nFirst )
1434cdf0e10cSrcweir 		nDiff = -1;
1435cdf0e10cSrcweir 	else
1436cdf0e10cSrcweir 		pColl = &pColl->GetNextTxtFmtColl();
1437cdf0e10cSrcweir 	SwAttrSet aSet( ((SwDoc*)GetTxtNode()->GetDoc())->GetAttrPool(), aTxtFmtCollSetRange );
1438cdf0e10cSrcweir 	const SwAttrSet* pSet = &pColl->GetAttrSet();
1439cdf0e10cSrcweir 	ViewShell *pSh = getRootFrm()->GetCurrShell();
1440cdf0e10cSrcweir 	if( GetTxtNode()->HasSwAttrSet() )
1441cdf0e10cSrcweir 	{
1442cdf0e10cSrcweir 		aSet.Put( *GetTxtNode()->GetpSwAttrSet() );
1443cdf0e10cSrcweir 		aSet.SetParent( pSet );
1444cdf0e10cSrcweir 		pSet = &aSet;
1445cdf0e10cSrcweir         pFnt = new SwFont( pSet, GetNode()->getIDocumentSettingAccess() );
1446cdf0e10cSrcweir     }
1447cdf0e10cSrcweir 	else
1448cdf0e10cSrcweir 	{
1449cdf0e10cSrcweir 		SwFontAccess aFontAccess( pColl, pSh );
1450cdf0e10cSrcweir 		pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
1451cdf0e10cSrcweir 		pFnt->ChkMagic( pSh, pFnt->GetActual() );
1452cdf0e10cSrcweir 	}
1453cdf0e10cSrcweir     OutputDevice* pOut = pSh->GetOut();
1454cdf0e10cSrcweir     if( !pSh->GetViewOptions()->getBrowseMode() || pSh->GetViewOptions()->IsPrtFormat() )
1455cdf0e10cSrcweir         pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
1456cdf0e10cSrcweir 
1457cdf0e10cSrcweir     pFnt->SetFntChg( sal_True );
1458cdf0e10cSrcweir     pFnt->ChgPhysFnt( pSh, *pOut );
1459cdf0e10cSrcweir 
1460cdf0e10cSrcweir     SwTwips nLineHeight = pFnt->GetHeight( pSh, *pOut );
1461cdf0e10cSrcweir 
1462cdf0e10cSrcweir 	if( nLineHeight )
1463cdf0e10cSrcweir 	{
1464cdf0e10cSrcweir 		const SvxULSpaceItem &rUL = pSet->GetULSpace();
1465cdf0e10cSrcweir 		SwTwips nDist = Max( rUL.GetLower(), rUL.GetUpper() );
1466cdf0e10cSrcweir 		if( rFill.Fill().nColumnCnt )
1467cdf0e10cSrcweir 		{
1468cdf0e10cSrcweir 			rFill.aFrm.Height( nLineHeight );
1469cdf0e10cSrcweir 			nDiff = rFill.Y() - rFill.Bottom();
1470cdf0e10cSrcweir 			nFirst = 0;
1471cdf0e10cSrcweir 		}
1472cdf0e10cSrcweir 		else if( nDist < nFirst )
1473cdf0e10cSrcweir             nFirst = nFirst - (sal_uInt16)nDist;
1474cdf0e10cSrcweir 		else
1475cdf0e10cSrcweir 			nFirst = 0;
1476cdf0e10cSrcweir 		nDist = Max( nDist, long( GetLineSpace() ) );
1477cdf0e10cSrcweir 		nDist += nLineHeight;
1478cdf0e10cSrcweir 		nDiff -= nFirst;
1479cdf0e10cSrcweir 
1480cdf0e10cSrcweir 		if( nDiff > 0 )
1481cdf0e10cSrcweir 		{
1482cdf0e10cSrcweir 			nDiff /= nDist;
1483cdf0e10cSrcweir             rFill.Fill().nParaCnt = static_cast<sal_uInt16>(nDiff + 1);
1484cdf0e10cSrcweir 			rFill.nLineWidth = 0;
1485cdf0e10cSrcweir 			rFill.bInner = sal_False;
1486cdf0e10cSrcweir 			rFill.bEmpty = sal_True;
1487cdf0e10cSrcweir             rFill.SetOrient( text::HoriOrientation::LEFT );
1488cdf0e10cSrcweir 		}
1489cdf0e10cSrcweir 		else
1490cdf0e10cSrcweir 			nDiff = -1;
1491cdf0e10cSrcweir 		if( rFill.bInner )
1492cdf0e10cSrcweir 			bFill = sal_False;
1493cdf0e10cSrcweir 		else
1494cdf0e10cSrcweir 		{
1495cdf0e10cSrcweir 			const SvxTabStopItem &rRuler = pSet->GetTabStops();
1496cdf0e10cSrcweir 			const SvxLRSpaceItem &rLRSpace = pSet->GetLRSpace();
1497cdf0e10cSrcweir 
1498cdf0e10cSrcweir 			SwRect &rRect = rFill.Fill().aCrsr;
1499cdf0e10cSrcweir 			rRect.Top( rFill.Bottom() + (nDiff+1) * nDist - nLineHeight );
1500cdf0e10cSrcweir 			if( nFirst && nDiff > -1 )
1501cdf0e10cSrcweir 				rRect.Top( rRect.Top() + nFirst );
1502cdf0e10cSrcweir 			rRect.Height( nLineHeight );
1503cdf0e10cSrcweir 			SwTwips nLeft = rFill.Left() + rLRSpace.GetLeft() +
1504cdf0e10cSrcweir 							GetTxtNode()->GetLeftMarginWithNum( sal_False );
1505cdf0e10cSrcweir 			SwTwips nRight = rFill.Right() - rLRSpace.GetRight();
1506cdf0e10cSrcweir 			SwTwips nCenter = ( nLeft + nRight ) / 2;
1507cdf0e10cSrcweir 			rRect.Left( nLeft );
1508cdf0e10cSrcweir 			if( FILL_MARGIN == rFill.Mode() )
1509cdf0e10cSrcweir 			{
1510cdf0e10cSrcweir 				if( rFill.bEmpty )
1511cdf0e10cSrcweir 				{
1512cdf0e10cSrcweir                     rFill.SetOrient( text::HoriOrientation::LEFT );
1513cdf0e10cSrcweir 					if( rFill.X() < nCenter )
1514cdf0e10cSrcweir 					{
1515cdf0e10cSrcweir 						if( rFill.X() > ( nLeft + 2 * nCenter ) / 3 )
1516cdf0e10cSrcweir 						{
1517cdf0e10cSrcweir                             rFill.SetOrient( text::HoriOrientation::CENTER );
1518cdf0e10cSrcweir 							rRect.Left( nCenter );
1519cdf0e10cSrcweir 						}
1520cdf0e10cSrcweir 					}
1521cdf0e10cSrcweir 					else if( rFill.X() > ( nRight + 2 * nCenter ) / 3 )
1522cdf0e10cSrcweir 					{
1523cdf0e10cSrcweir                         rFill.SetOrient( text::HoriOrientation::RIGHT );
1524cdf0e10cSrcweir 						rRect.Left( nRight );
1525cdf0e10cSrcweir 					}
1526cdf0e10cSrcweir 					else
1527cdf0e10cSrcweir 					{
1528cdf0e10cSrcweir                         rFill.SetOrient( text::HoriOrientation::CENTER );
1529cdf0e10cSrcweir 						rRect.Left( nCenter );
1530cdf0e10cSrcweir 					}
1531cdf0e10cSrcweir 				}
1532cdf0e10cSrcweir 				else
1533cdf0e10cSrcweir 					bFill = sal_False;
1534cdf0e10cSrcweir 			}
1535cdf0e10cSrcweir 			else
1536cdf0e10cSrcweir 			{
1537cdf0e10cSrcweir                 SwTwips nSpace = 0;
1538cdf0e10cSrcweir 				if( FILL_TAB != rFill.Mode() )
1539cdf0e10cSrcweir 				{
1540cdf0e10cSrcweir static sal_Char __READONLY_DATA sDoubleSpace[] = "  ";
1541cdf0e10cSrcweir 					const XubString aTmp( sDoubleSpace, RTL_TEXTENCODING_MS_1252 );
1542cdf0e10cSrcweir 
1543cdf0e10cSrcweir                     SwDrawTextInfo aDrawInf( pSh, *pOut, 0, aTmp, 0, 2 );
1544cdf0e10cSrcweir                     nSpace = pFnt->_GetTxtSize( aDrawInf ).Width()/2;
1545cdf0e10cSrcweir 				}
1546cdf0e10cSrcweir 				if( rFill.X() >= nRight )
1547cdf0e10cSrcweir 				{
1548cdf0e10cSrcweir 					if( FILL_INDENT != rFill.Mode() && ( rFill.bEmpty ||
1549cdf0e10cSrcweir 						rFill.X() >	rFill.nLineWidth + FILL_MIN_DIST ) )
1550cdf0e10cSrcweir 					{
1551cdf0e10cSrcweir                         rFill.SetOrient( text::HoriOrientation::RIGHT );
1552cdf0e10cSrcweir 						rRect.Left( nRight );
1553cdf0e10cSrcweir 					}
1554cdf0e10cSrcweir 					else
1555cdf0e10cSrcweir 						bFill = sal_False;
1556cdf0e10cSrcweir 				}
1557cdf0e10cSrcweir 				else if( FILL_INDENT == rFill.Mode() )
1558cdf0e10cSrcweir 				{
1559cdf0e10cSrcweir 					SwTwips nIndent = rFill.X();
1560cdf0e10cSrcweir 					if( !rFill.bEmpty || nIndent > nRight )
1561cdf0e10cSrcweir 						bFill = sal_False;
1562cdf0e10cSrcweir 					else
1563cdf0e10cSrcweir 					{
1564cdf0e10cSrcweir 						nIndent -= rFill.Left();
1565cdf0e10cSrcweir 						if( nIndent >= 0 && nSpace )
1566cdf0e10cSrcweir 						{
1567cdf0e10cSrcweir 							nIndent /= nSpace;
1568cdf0e10cSrcweir 							nIndent *= nSpace;
1569cdf0e10cSrcweir 							rFill.SetTab( MSHORT( nIndent ) );
1570cdf0e10cSrcweir 							rRect.Left( nIndent + rFill.Left() );
1571cdf0e10cSrcweir 						}
1572cdf0e10cSrcweir 						else
1573cdf0e10cSrcweir 							bFill = sal_False;
1574cdf0e10cSrcweir 					}
1575cdf0e10cSrcweir 				}
1576cdf0e10cSrcweir 				else if( rFill.X() > nLeft )
1577cdf0e10cSrcweir 				{
1578cdf0e10cSrcweir 					SwTwips nTxtLeft = rFill.Left() + rLRSpace.GetTxtLeft() +
1579cdf0e10cSrcweir 									GetTxtNode()->GetLeftMarginWithNum( sal_True );
1580cdf0e10cSrcweir 					rFill.nLineWidth += rFill.bFirstLine ? nLeft : nTxtLeft;
1581cdf0e10cSrcweir 					SwTwips nLeftTab = nLeft;
1582cdf0e10cSrcweir 					SwTwips nRightTab = nLeft;
1583cdf0e10cSrcweir 					MSHORT nSpaceCnt = 0;
1584cdf0e10cSrcweir 					MSHORT nTabCnt = 0;
1585cdf0e10cSrcweir 					MSHORT nIdx = 0;
1586cdf0e10cSrcweir 					do
1587cdf0e10cSrcweir 					{
1588cdf0e10cSrcweir 						nLeftTab = nRightTab;
1589cdf0e10cSrcweir 						if( nIdx < rRuler.Count() )
1590cdf0e10cSrcweir 						{
1591cdf0e10cSrcweir 							const SvxTabStop &rTabStop = rRuler.operator[](nIdx);
1592cdf0e10cSrcweir 							nRightTab = nTxtLeft + rTabStop.GetTabPos();
1593cdf0e10cSrcweir 							if( nLeftTab < nTxtLeft && nRightTab > nTxtLeft )
1594cdf0e10cSrcweir 								nRightTab = nTxtLeft;
1595cdf0e10cSrcweir 							else
1596cdf0e10cSrcweir 								++nIdx;
1597cdf0e10cSrcweir 							if( nRightTab > rFill.nLineWidth )
1598cdf0e10cSrcweir 								++nTabCnt;
1599cdf0e10cSrcweir 						}
1600cdf0e10cSrcweir 						else
1601cdf0e10cSrcweir 						{
1602cdf0e10cSrcweir 							const SvxTabStopItem& rTab =
1603cdf0e10cSrcweir 								(const SvxTabStopItem &)pSet->
1604cdf0e10cSrcweir 								GetPool()->GetDefaultItem( RES_PARATR_TABSTOP );
1605cdf0e10cSrcweir 							MSHORT nDefTabDist = (MSHORT)rTab.GetStart()->GetTabPos();
1606cdf0e10cSrcweir 							nRightTab = nLeftTab - nTxtLeft;
1607cdf0e10cSrcweir 							nRightTab /= nDefTabDist;
1608cdf0e10cSrcweir 							nRightTab = nRightTab * nDefTabDist + nTxtLeft;
1609cdf0e10cSrcweir 							while ( nRightTab <= nLeftTab )
1610cdf0e10cSrcweir 								nRightTab += nDefTabDist;
1611cdf0e10cSrcweir 							if( nRightTab > rFill.nLineWidth )
1612cdf0e10cSrcweir 								++nTabCnt;
1613cdf0e10cSrcweir 							while ( nRightTab < rFill.X() )
1614cdf0e10cSrcweir 							{
1615cdf0e10cSrcweir 								nRightTab += nDefTabDist;
1616cdf0e10cSrcweir 								if( nRightTab > rFill.nLineWidth )
1617cdf0e10cSrcweir 									++nTabCnt;
1618cdf0e10cSrcweir 							}
1619cdf0e10cSrcweir 							if( nLeftTab < nRightTab - nDefTabDist )
1620cdf0e10cSrcweir 								nLeftTab = nRightTab - nDefTabDist;
1621cdf0e10cSrcweir 						}
1622cdf0e10cSrcweir 						if( nRightTab > nRight )
1623cdf0e10cSrcweir 							nRightTab = nRight;
1624cdf0e10cSrcweir 					}
1625cdf0e10cSrcweir 					while( rFill.X() > nRightTab );
1626cdf0e10cSrcweir 					--nTabCnt;
1627cdf0e10cSrcweir 					if( FILL_TAB != rFill.Mode() )
1628cdf0e10cSrcweir 					{
1629cdf0e10cSrcweir 						if( nSpace > 0 )
1630cdf0e10cSrcweir 						{
1631cdf0e10cSrcweir 							if( !nTabCnt )
1632cdf0e10cSrcweir 								nLeftTab = rFill.nLineWidth;
1633cdf0e10cSrcweir 							while( nLeftTab < rFill.X() )
1634cdf0e10cSrcweir 							{
1635cdf0e10cSrcweir 								nLeftTab += nSpace;
1636cdf0e10cSrcweir 								++nSpaceCnt;
1637cdf0e10cSrcweir 							}
1638cdf0e10cSrcweir 							if( nSpaceCnt )
1639cdf0e10cSrcweir 							{
1640cdf0e10cSrcweir 								nLeftTab -= nSpace;
1641cdf0e10cSrcweir 								--nSpaceCnt;
1642cdf0e10cSrcweir 							}
1643cdf0e10cSrcweir 							if( rFill.X() - nLeftTab > nRightTab - rFill.X() )
1644cdf0e10cSrcweir 							{
1645cdf0e10cSrcweir 								nSpaceCnt = 0;
1646cdf0e10cSrcweir 								++nTabCnt;
1647cdf0e10cSrcweir 								rRect.Left( nRightTab );
1648cdf0e10cSrcweir 							}
1649cdf0e10cSrcweir 							else
1650cdf0e10cSrcweir 							{
1651cdf0e10cSrcweir 								if( rFill.X() - nLeftTab > nSpace/2 )
1652cdf0e10cSrcweir 								{
1653cdf0e10cSrcweir 									++nSpaceCnt;
1654cdf0e10cSrcweir 									rRect.Left( nLeftTab + nSpace );
1655cdf0e10cSrcweir 								}
1656cdf0e10cSrcweir 								else
1657cdf0e10cSrcweir 									rRect.Left( nLeftTab );
1658cdf0e10cSrcweir 							}
1659cdf0e10cSrcweir 						}
1660cdf0e10cSrcweir 						else if( rFill.X() - nLeftTab < nRightTab - rFill.X() )
1661cdf0e10cSrcweir 							rRect.Left( nLeftTab );
1662cdf0e10cSrcweir 						else
1663cdf0e10cSrcweir 						{
1664cdf0e10cSrcweir 							if( nRightTab >= nRight )
1665cdf0e10cSrcweir 							{
1666cdf0e10cSrcweir                                 rFill.SetOrient( text::HoriOrientation::RIGHT );
1667cdf0e10cSrcweir 								rRect.Left( nRight );
1668cdf0e10cSrcweir 								nTabCnt = 0;
1669cdf0e10cSrcweir 								nSpaceCnt = 0;
1670cdf0e10cSrcweir 							}
1671cdf0e10cSrcweir 							else
1672cdf0e10cSrcweir 							{
1673cdf0e10cSrcweir 								rRect.Left( nRightTab );
1674cdf0e10cSrcweir 								++nTabCnt;
1675cdf0e10cSrcweir 							}
1676cdf0e10cSrcweir 						}
1677cdf0e10cSrcweir 					}
1678cdf0e10cSrcweir 					else
1679cdf0e10cSrcweir 					{
1680cdf0e10cSrcweir 						if( rFill.X() - nLeftTab < nRightTab - rFill.X() )
1681cdf0e10cSrcweir 							rRect.Left( nLeftTab );
1682cdf0e10cSrcweir 						else
1683cdf0e10cSrcweir 						{
1684cdf0e10cSrcweir 							if( nRightTab >= nRight )
1685cdf0e10cSrcweir 							{
1686cdf0e10cSrcweir                                 rFill.SetOrient( text::HoriOrientation::RIGHT );
1687cdf0e10cSrcweir 								rRect.Left( nRight );
1688cdf0e10cSrcweir 								nTabCnt = 0;
1689cdf0e10cSrcweir 								nSpaceCnt = 0;
1690cdf0e10cSrcweir 							}
1691cdf0e10cSrcweir 							else
1692cdf0e10cSrcweir 							{
1693cdf0e10cSrcweir 								rRect.Left( nRightTab );
1694cdf0e10cSrcweir 								++nTabCnt;
1695cdf0e10cSrcweir 							}
1696cdf0e10cSrcweir 						}
1697cdf0e10cSrcweir 					}
1698cdf0e10cSrcweir 					rFill.SetTab( nTabCnt );
1699cdf0e10cSrcweir 					rFill.SetSpace( nSpaceCnt );
1700cdf0e10cSrcweir 					if( bFill )
1701cdf0e10cSrcweir 					{
1702cdf0e10cSrcweir 						if( Abs( rFill.X() - nCenter ) <=
1703cdf0e10cSrcweir 							Abs( rFill.X() - rRect.Left() ) )
1704cdf0e10cSrcweir 						{
1705cdf0e10cSrcweir                             rFill.SetOrient( text::HoriOrientation::CENTER );
1706cdf0e10cSrcweir 							rFill.SetTab( 0 );
1707cdf0e10cSrcweir 							rFill.SetSpace( 0 );
1708cdf0e10cSrcweir 							rRect.Left( nCenter );
1709cdf0e10cSrcweir 						}
1710cdf0e10cSrcweir 						if( !rFill.bEmpty )
1711cdf0e10cSrcweir 							rFill.nLineWidth += FILL_MIN_DIST;
1712cdf0e10cSrcweir 						if( rRect.Left() < rFill.nLineWidth )
1713cdf0e10cSrcweir 							bFill = sal_False;
1714cdf0e10cSrcweir 					}
1715cdf0e10cSrcweir 				}
1716cdf0e10cSrcweir 			}
1717cdf0e10cSrcweir 			// Gehen wir ueber die Unterkante der Seite/Spalte etc. hinaus?
1718cdf0e10cSrcweir 			const SwFrm* pUp = GetUpper();
1719cdf0e10cSrcweir 			if( pUp->IsInSct() )
1720cdf0e10cSrcweir 			{
1721cdf0e10cSrcweir 				if( pUp->IsSctFrm() )
1722cdf0e10cSrcweir 					pUp = pUp->GetUpper();
1723cdf0e10cSrcweir 				else if( pUp->IsColBodyFrm() &&
1724cdf0e10cSrcweir 						 pUp->GetUpper()->GetUpper()->IsSctFrm() )
1725cdf0e10cSrcweir 					pUp = pUp->GetUpper()->GetUpper()->GetUpper();
1726cdf0e10cSrcweir 			}
1727cdf0e10cSrcweir             SWRECTFN( this )
1728cdf0e10cSrcweir             SwTwips nLimit = (pUp->*fnRect->fnGetPrtBottom)();
1729cdf0e10cSrcweir             SwTwips nRectBottom = rRect.Bottom();
1730cdf0e10cSrcweir             if ( bVert )
1731cdf0e10cSrcweir                 nRectBottom = SwitchHorizontalToVertical( nRectBottom );
1732cdf0e10cSrcweir 
1733cdf0e10cSrcweir             if( (*fnRect->fnYDiff)( nLimit, nRectBottom ) < 0 )
1734cdf0e10cSrcweir 				bFill = sal_False;
1735cdf0e10cSrcweir 			else
1736cdf0e10cSrcweir 				rRect.Width( 1 );
1737cdf0e10cSrcweir 		}
1738cdf0e10cSrcweir 	}
1739cdf0e10cSrcweir 	else
1740cdf0e10cSrcweir 		bFill = sal_False;
1741cdf0e10cSrcweir 	((SwCrsrMoveState*)rFill.pCMS)->bFillRet = bFill;
1742cdf0e10cSrcweir 	delete pFnt;
1743cdf0e10cSrcweir }
1744