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