1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3efeef26fSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist * or more contributor license agreements. See the NOTICE file
5efeef26fSAndrew Rist * distributed with this work for additional information
6efeef26fSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7efeef26fSAndrew Rist * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11efeef26fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13efeef26fSAndrew Rist * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist * software distributed under the License is distributed on an
15efeef26fSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist * KIND, either express or implied. See the License for the
17efeef26fSAndrew Rist * specific language governing permissions and limitations
18efeef26fSAndrew Rist * under the License.
19cdf0e10cSrcweir *
20efeef26fSAndrew Rist *************************************************************/
21efeef26fSAndrew Rist
22efeef26fSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir
28cdf0e10cSrcweir #include <hintids.hxx>
29cdf0e10cSrcweir
30cdf0e10cSrcweir #include <com/sun/star/i18n/ScriptType.hdl>
31cdf0e10cSrcweir #include <editeng/twolinesitem.hxx>
32cdf0e10cSrcweir #include <editeng/charrotateitem.hxx>
33cdf0e10cSrcweir #include <vcl/outdev.hxx>
34cdf0e10cSrcweir #include <fmtfld.hxx>
35cdf0e10cSrcweir #include <fldbas.hxx> // SwField
36cdf0e10cSrcweir #include <txatbase.hxx>
37cdf0e10cSrcweir #include <fmtruby.hxx> // SwFmtRuby
38cdf0e10cSrcweir #include <txtatr.hxx> // SwTxtRuby
39cdf0e10cSrcweir #include <charfmt.hxx>
40cdf0e10cSrcweir #include <txtinet.hxx>
41cdf0e10cSrcweir #include <fchrfmt.hxx>
42cdf0e10cSrcweir #include <layfrm.hxx> // GetUpper()
43cdf0e10cSrcweir #include <SwPortionHandler.hxx>
44cdf0e10cSrcweir #include <pormulti.hxx> // SwMultiPortion
45cdf0e10cSrcweir #include <inftxt.hxx> // SwTxtSizeInfo
46cdf0e10cSrcweir #include <itrpaint.hxx> // SwTxtPainter
47cdf0e10cSrcweir #include <viewopt.hxx> // SwViewOptions
48cdf0e10cSrcweir #include <itrform2.hxx> // SwTxtFormatter
49cdf0e10cSrcweir #include <porfld.hxx> // SwFldPortion
50cdf0e10cSrcweir #include <porglue.hxx>
51cdf0e10cSrcweir #include <breakit.hxx>
52cdf0e10cSrcweir #include <pagefrm.hxx>
53cdf0e10cSrcweir #include <rowfrm.hxx>
54cdf0e10cSrcweir #include <pagedesc.hxx> // SwPageDesc
55cdf0e10cSrcweir #include <tgrditem.hxx>
56cdf0e10cSrcweir #include <swtable.hxx>
57cdf0e10cSrcweir #include <fmtfsize.hxx>
58cdf0e10cSrcweir
59cdf0e10cSrcweir using namespace ::com::sun::star;
60cdf0e10cSrcweir extern sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt );
61cdf0e10cSrcweir
62cdf0e10cSrcweir /*-----------------10.10.00 15:23-------------------
63cdf0e10cSrcweir * class SwMultiPortion
64cdf0e10cSrcweir *
65cdf0e10cSrcweir * A SwMultiPortion is not a simple portion,
66cdf0e10cSrcweir * it's a container, which contains almost a SwLineLayoutPortion.
67cdf0e10cSrcweir * This SwLineLayout could be followed by other textportions via pPortion
68cdf0e10cSrcweir * and by another SwLineLayout via pNext to realize a doubleline portion.
69cdf0e10cSrcweir * --------------------------------------------------*/
70cdf0e10cSrcweir
~SwMultiPortion()71cdf0e10cSrcweir SwMultiPortion::~SwMultiPortion()
72cdf0e10cSrcweir {
73cdf0e10cSrcweir delete pFldRest;
74cdf0e10cSrcweir }
75cdf0e10cSrcweir
Paint(const SwTxtPaintInfo &) const76cdf0e10cSrcweir void SwMultiPortion::Paint( const SwTxtPaintInfo & ) const
77cdf0e10cSrcweir {
78cdf0e10cSrcweir ASSERT( sal_False,
79cdf0e10cSrcweir "Don't try SwMultiPortion::Paint, try SwTxtPainter::PaintMultiPortion" );
80cdf0e10cSrcweir }
81cdf0e10cSrcweir
82cdf0e10cSrcweir /*-----------------13.10.00 16:21-------------------
83cdf0e10cSrcweir * Summarize the internal lines to calculate the (external) size.
84cdf0e10cSrcweir * The internal line has to calculate first.
85cdf0e10cSrcweir * --------------------------------------------------*/
86cdf0e10cSrcweir
CalcSize(SwTxtFormatter & rLine,SwTxtFormatInfo & rInf)87cdf0e10cSrcweir void SwMultiPortion::CalcSize( SwTxtFormatter& rLine, SwTxtFormatInfo &rInf )
88cdf0e10cSrcweir {
89cdf0e10cSrcweir Width( 0 );
90cdf0e10cSrcweir Height( 0 );
91cdf0e10cSrcweir SetAscent( 0 );
92cdf0e10cSrcweir SetFlyInCntnt( sal_False );
93cdf0e10cSrcweir SwLineLayout *pLay = &GetRoot();
94cdf0e10cSrcweir do
95cdf0e10cSrcweir {
96cdf0e10cSrcweir pLay->CalcLine( rLine, rInf );
97cdf0e10cSrcweir if( rLine.IsFlyInCntBase() )
98cdf0e10cSrcweir SetFlyInCntnt( sal_True );
99cdf0e10cSrcweir if( IsRuby() && ( OnTop() == ( pLay == &GetRoot() ) ) )
100cdf0e10cSrcweir {
101cdf0e10cSrcweir // An empty phonetic line don't need an ascent or a height.
102cdf0e10cSrcweir if( !pLay->Width() )
103cdf0e10cSrcweir {
104cdf0e10cSrcweir pLay->SetAscent( 0 );
105cdf0e10cSrcweir pLay->Height( 0 );
106cdf0e10cSrcweir }
107cdf0e10cSrcweir if( OnTop() )
108cdf0e10cSrcweir SetAscent( GetAscent() + pLay->Height() );
109cdf0e10cSrcweir }
110cdf0e10cSrcweir else
111cdf0e10cSrcweir SetAscent( GetAscent() + pLay->GetAscent() );
112cdf0e10cSrcweir Height( Height() + pLay->Height() );
113cdf0e10cSrcweir if( Width() < pLay->Width() )
114cdf0e10cSrcweir Width( pLay->Width() );
115cdf0e10cSrcweir pLay = pLay->GetNext();
116cdf0e10cSrcweir } while ( pLay );
117cdf0e10cSrcweir if( HasBrackets() )
118cdf0e10cSrcweir {
119cdf0e10cSrcweir KSHORT nTmp = ((SwDoubleLinePortion*)this)->GetBrackets()->nHeight;
120cdf0e10cSrcweir if( nTmp > Height() )
121cdf0e10cSrcweir {
122cdf0e10cSrcweir KSHORT nAdd = ( nTmp - Height() ) / 2;
123cdf0e10cSrcweir GetRoot().SetAscent( GetRoot().GetAscent() + nAdd );
124cdf0e10cSrcweir GetRoot().Height( GetRoot().Height() + nAdd );
125cdf0e10cSrcweir Height( nTmp );
126cdf0e10cSrcweir }
127cdf0e10cSrcweir nTmp = ((SwDoubleLinePortion*)this)->GetBrackets()->nAscent;
128cdf0e10cSrcweir if( nTmp > GetAscent() )
129cdf0e10cSrcweir SetAscent( nTmp );
130cdf0e10cSrcweir }
131cdf0e10cSrcweir }
132cdf0e10cSrcweir
CalcSpacing(long,const SwTxtSizeInfo &) const133cdf0e10cSrcweir long SwMultiPortion::CalcSpacing( long , const SwTxtSizeInfo & ) const
134cdf0e10cSrcweir {
135cdf0e10cSrcweir return 0;
136cdf0e10cSrcweir }
137cdf0e10cSrcweir
ChgSpaceAdd(SwLineLayout *,long) const138cdf0e10cSrcweir sal_Bool SwMultiPortion::ChgSpaceAdd( SwLineLayout*, long ) const
139cdf0e10cSrcweir {
140cdf0e10cSrcweir return sal_False;
141cdf0e10cSrcweir }
142cdf0e10cSrcweir
143cdf0e10cSrcweir /*************************************************************************
144cdf0e10cSrcweir * virtual SwMultiPortion::HandlePortion()
145cdf0e10cSrcweir *************************************************************************/
146cdf0e10cSrcweir
HandlePortion(SwPortionHandler & rPH) const147cdf0e10cSrcweir void SwMultiPortion::HandlePortion( SwPortionHandler& rPH ) const
148cdf0e10cSrcweir {
149cdf0e10cSrcweir rPH.Text( GetLen(), GetWhichPor() );
150cdf0e10cSrcweir }
151cdf0e10cSrcweir
152cdf0e10cSrcweir /*-----------------01.11.00 14:21-------------------
153cdf0e10cSrcweir * SwMultiPortion::ActualizeTabulator()
154cdf0e10cSrcweir * sets the tabulator-flag, if there's any tabulator-portion inside.
155cdf0e10cSrcweir * --------------------------------------------------*/
156cdf0e10cSrcweir
ActualizeTabulator()157cdf0e10cSrcweir void SwMultiPortion::ActualizeTabulator()
158cdf0e10cSrcweir {
159cdf0e10cSrcweir SwLinePortion* pPor = GetRoot().GetFirstPortion();
160cdf0e10cSrcweir // First line
161cdf0e10cSrcweir for( bTab1 = bTab2 = sal_False; pPor; pPor = pPor->GetPortion() )
162cdf0e10cSrcweir if( pPor->InTabGrp() )
163cdf0e10cSrcweir SetTab1( sal_True );
164cdf0e10cSrcweir if( GetRoot().GetNext() )
165cdf0e10cSrcweir {
166cdf0e10cSrcweir // Second line
167cdf0e10cSrcweir pPor = GetRoot().GetNext()->GetFirstPortion();
168cdf0e10cSrcweir do
169cdf0e10cSrcweir {
170cdf0e10cSrcweir if( pPor->InTabGrp() )
171cdf0e10cSrcweir SetTab2( sal_True );
172cdf0e10cSrcweir pPor = pPor->GetPortion();
173cdf0e10cSrcweir } while ( pPor );
174cdf0e10cSrcweir }
175cdf0e10cSrcweir }
176cdf0e10cSrcweir
177cdf0e10cSrcweir /*-----------------16.02.01 12:07-------------------
178cdf0e10cSrcweir * SwRotatedPortion::SwRotatedPortion(..)
179cdf0e10cSrcweir * --------------------------------------------------*/
180cdf0e10cSrcweir
SwRotatedPortion(const SwMultiCreator & rCreate,xub_StrLen nEnd,sal_Bool bRTL)181cdf0e10cSrcweir SwRotatedPortion::SwRotatedPortion( const SwMultiCreator& rCreate,
182cdf0e10cSrcweir xub_StrLen nEnd, sal_Bool bRTL ) : SwMultiPortion( nEnd )
183cdf0e10cSrcweir {
184cdf0e10cSrcweir const SvxCharRotateItem* pRot = (SvxCharRotateItem*)rCreate.pItem;
185cdf0e10cSrcweir if( !pRot )
186cdf0e10cSrcweir {
187cdf0e10cSrcweir const SwTxtAttr& rAttr = *rCreate.pAttr;
188cdf0e10cSrcweir const SfxPoolItem *const pItem =
189cdf0e10cSrcweir CharFmt::GetItem(rAttr, RES_CHRATR_ROTATE);
190cdf0e10cSrcweir if ( pItem )
191cdf0e10cSrcweir {
192cdf0e10cSrcweir pRot = static_cast<const SvxCharRotateItem*>(pItem);
193cdf0e10cSrcweir }
194cdf0e10cSrcweir }
195cdf0e10cSrcweir if( pRot )
196cdf0e10cSrcweir {
197cdf0e10cSrcweir sal_uInt8 nDir;
198cdf0e10cSrcweir if ( bRTL )
199cdf0e10cSrcweir nDir = pRot->IsBottomToTop() ? 3 : 1;
200cdf0e10cSrcweir else
201cdf0e10cSrcweir nDir = pRot->IsBottomToTop() ? 1 : 3;
202cdf0e10cSrcweir
203cdf0e10cSrcweir SetDirection( nDir );
204cdf0e10cSrcweir }
205cdf0e10cSrcweir }
206cdf0e10cSrcweir
207cdf0e10cSrcweir /*---------------------------------------------------
208cdf0e10cSrcweir * SwBidiPortion::SwBidiPortion(..)
209cdf0e10cSrcweir * --------------------------------------------------*/
210cdf0e10cSrcweir
SwBidiPortion(xub_StrLen nEnd,sal_uInt8 nLv)211cdf0e10cSrcweir SwBidiPortion::SwBidiPortion( xub_StrLen nEnd, sal_uInt8 nLv )
212cdf0e10cSrcweir : SwMultiPortion( nEnd ), nLevel( nLv )
213cdf0e10cSrcweir {
214cdf0e10cSrcweir SetBidi();
215cdf0e10cSrcweir
216cdf0e10cSrcweir if ( nLevel % 2 )
217cdf0e10cSrcweir SetDirection( DIR_RIGHT2LEFT );
218cdf0e10cSrcweir else
219cdf0e10cSrcweir SetDirection( DIR_LEFT2RIGHT );
220cdf0e10cSrcweir }
221cdf0e10cSrcweir
222cdf0e10cSrcweir
CalcSpacing(long nSpaceAdd,const SwTxtSizeInfo & rInf) const223cdf0e10cSrcweir long SwBidiPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo& rInf ) const
224cdf0e10cSrcweir {
225cdf0e10cSrcweir return HasTabulator() ? 0 : GetSpaceCnt(rInf) * nSpaceAdd / SPACING_PRECISION_FACTOR;
226cdf0e10cSrcweir }
227cdf0e10cSrcweir
ChgSpaceAdd(SwLineLayout * pCurr,long nSpaceAdd) const228cdf0e10cSrcweir sal_Bool SwBidiPortion::ChgSpaceAdd( SwLineLayout* pCurr, long nSpaceAdd ) const
229cdf0e10cSrcweir {
230cdf0e10cSrcweir sal_Bool bRet = sal_False;
231cdf0e10cSrcweir if( !HasTabulator() && nSpaceAdd > 0 && !pCurr->IsSpaceAdd() )
232cdf0e10cSrcweir {
233cdf0e10cSrcweir pCurr->CreateSpaceAdd();
234cdf0e10cSrcweir pCurr->SetLLSpaceAdd( nSpaceAdd, 0 );
235cdf0e10cSrcweir bRet = sal_True;
236cdf0e10cSrcweir }
237cdf0e10cSrcweir
238cdf0e10cSrcweir return bRet;
239cdf0e10cSrcweir }
240cdf0e10cSrcweir
GetSpaceCnt(const SwTxtSizeInfo & rInf) const241cdf0e10cSrcweir xub_StrLen SwBidiPortion::GetSpaceCnt( const SwTxtSizeInfo &rInf ) const
242cdf0e10cSrcweir {
243cdf0e10cSrcweir // Calculate number of blanks for justified alignment
244cdf0e10cSrcweir SwLinePortion* pPor = GetRoot().GetFirstPortion();
245cdf0e10cSrcweir xub_StrLen nTmpStart = rInf.GetIdx();
246cdf0e10cSrcweir xub_StrLen nNull = 0;
247cdf0e10cSrcweir xub_StrLen nBlanks;
248cdf0e10cSrcweir
249cdf0e10cSrcweir for( nBlanks = 0; pPor; pPor = pPor->GetPortion() )
250cdf0e10cSrcweir {
251cdf0e10cSrcweir if( pPor->InTxtGrp() )
252cdf0e10cSrcweir nBlanks = nBlanks + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
253cdf0e10cSrcweir else if ( pPor->IsMultiPortion() &&
254cdf0e10cSrcweir ((SwMultiPortion*)pPor)->IsBidi() )
255cdf0e10cSrcweir nBlanks = nBlanks + ((SwBidiPortion*)pPor)->GetSpaceCnt( rInf );
256cdf0e10cSrcweir
257cdf0e10cSrcweir ((SwTxtSizeInfo &)rInf).SetIdx( rInf.GetIdx() + pPor->GetLen() );
258cdf0e10cSrcweir }
259cdf0e10cSrcweir ((SwTxtSizeInfo &)rInf).SetIdx( nTmpStart );
260cdf0e10cSrcweir return nBlanks;
261cdf0e10cSrcweir }
262cdf0e10cSrcweir
263cdf0e10cSrcweir /*-----------------01.11.00 14:22-------------------
264cdf0e10cSrcweir * SwDoubleLinePortion::SwDoubleLinePortion(..)
265cdf0e10cSrcweir * This constructor is for the continuation of a doubleline portion
266cdf0e10cSrcweir * in the next line.
267cdf0e10cSrcweir * It takes the same brackets and if the original has no content except
268cdf0e10cSrcweir * brackets, these will be deleted.
269cdf0e10cSrcweir * --------------------------------------------------*/
270cdf0e10cSrcweir
SwDoubleLinePortion(SwDoubleLinePortion & rDouble,xub_StrLen nEnd)271cdf0e10cSrcweir SwDoubleLinePortion::SwDoubleLinePortion( SwDoubleLinePortion& rDouble,
272cdf0e10cSrcweir xub_StrLen nEnd ) :
273cdf0e10cSrcweir SwMultiPortion( nEnd ),
274cdf0e10cSrcweir pBracket( 0 )
275cdf0e10cSrcweir {
276cdf0e10cSrcweir SetDirection( rDouble.GetDirection() );
277cdf0e10cSrcweir SetDouble();
278cdf0e10cSrcweir if( rDouble.GetBrackets() )
279cdf0e10cSrcweir {
280cdf0e10cSrcweir SetBrackets( rDouble );
281cdf0e10cSrcweir // An empty multiportion needs no brackets.
282cdf0e10cSrcweir // Notice: GetLen() might be zero, if the multiportion contains
283cdf0e10cSrcweir // the second part of a field and the width might be zero, if
284cdf0e10cSrcweir // it contains a note only. In this cases the brackets are okay.
285cdf0e10cSrcweir // But if the length and the width are both zero, the portion
286cdf0e10cSrcweir // is really empty.
287cdf0e10cSrcweir if( rDouble.Width() == rDouble.BracketWidth() )
288cdf0e10cSrcweir rDouble.ClearBrackets();
289cdf0e10cSrcweir }
290cdf0e10cSrcweir }
291cdf0e10cSrcweir
292cdf0e10cSrcweir /*-----------------01.11.00 14:22-------------------
293cdf0e10cSrcweir * SwDoubleLinePortion::SwDoubleLinePortion(..)
294cdf0e10cSrcweir * This constructor uses the textattribut to get the right brackets.
295cdf0e10cSrcweir * The textattribut could be a 2-line-attribute or a character- or
296cdf0e10cSrcweir * internetstyle, which contains the 2-line-attribute.
297cdf0e10cSrcweir * --------------------------------------------------*/
298cdf0e10cSrcweir
SwDoubleLinePortion(const SwMultiCreator & rCreate,xub_StrLen nEnd)299cdf0e10cSrcweir SwDoubleLinePortion::SwDoubleLinePortion( const SwMultiCreator& rCreate,
300cdf0e10cSrcweir xub_StrLen nEnd ) : SwMultiPortion( nEnd ), pBracket( new SwBracket() )
301cdf0e10cSrcweir {
302cdf0e10cSrcweir SetDouble();
303cdf0e10cSrcweir const SvxTwoLinesItem* pTwo = (SvxTwoLinesItem*)rCreate.pItem;
304cdf0e10cSrcweir if( pTwo )
305cdf0e10cSrcweir pBracket->nStart = 0;
306cdf0e10cSrcweir else
307cdf0e10cSrcweir {
308cdf0e10cSrcweir const SwTxtAttr& rAttr = *rCreate.pAttr;
309cdf0e10cSrcweir pBracket->nStart = *rAttr.GetStart();
310cdf0e10cSrcweir
311cdf0e10cSrcweir const SfxPoolItem * const pItem =
312cdf0e10cSrcweir CharFmt::GetItem( rAttr, RES_CHRATR_TWO_LINES );
313cdf0e10cSrcweir if ( pItem )
314cdf0e10cSrcweir {
315cdf0e10cSrcweir pTwo = static_cast<const SvxTwoLinesItem*>(pItem);
316cdf0e10cSrcweir }
317cdf0e10cSrcweir }
318cdf0e10cSrcweir if( pTwo )
319cdf0e10cSrcweir {
320cdf0e10cSrcweir pBracket->cPre = pTwo->GetStartBracket();
321cdf0e10cSrcweir pBracket->cPost = pTwo->GetEndBracket();
322cdf0e10cSrcweir }
323cdf0e10cSrcweir else
324cdf0e10cSrcweir {
325cdf0e10cSrcweir pBracket->cPre = 0;
326cdf0e10cSrcweir pBracket->cPost = 0;
327cdf0e10cSrcweir }
328cdf0e10cSrcweir sal_uInt8 nTmp = SW_SCRIPTS;
329cdf0e10cSrcweir if( pBracket->cPre > 255 )
330cdf0e10cSrcweir {
331cdf0e10cSrcweir String aTxt( pBracket->cPre );
332cdf0e10cSrcweir nTmp = SwScriptInfo::WhichFont( 0, &aTxt, 0 );
333cdf0e10cSrcweir }
334cdf0e10cSrcweir pBracket->nPreScript = nTmp;
335cdf0e10cSrcweir nTmp = SW_SCRIPTS;
336cdf0e10cSrcweir if( pBracket->cPost > 255 )
337cdf0e10cSrcweir {
338cdf0e10cSrcweir String aTxt( pBracket->cPost );
339cdf0e10cSrcweir nTmp = SwScriptInfo::WhichFont( 0, &aTxt, 0 );
340cdf0e10cSrcweir }
341cdf0e10cSrcweir pBracket->nPostScript = nTmp;
342cdf0e10cSrcweir
343cdf0e10cSrcweir if( !pBracket->cPre && !pBracket->cPost )
344cdf0e10cSrcweir {
345cdf0e10cSrcweir delete pBracket;
346cdf0e10cSrcweir pBracket = 0;
347cdf0e10cSrcweir }
348cdf0e10cSrcweir
349cdf0e10cSrcweir // double line portions have the same direction as the frame directions
350cdf0e10cSrcweir if ( rCreate.nLevel % 2 )
351cdf0e10cSrcweir SetDirection( DIR_RIGHT2LEFT );
352cdf0e10cSrcweir else
353cdf0e10cSrcweir SetDirection( DIR_LEFT2RIGHT );
354cdf0e10cSrcweir }
355cdf0e10cSrcweir
356cdf0e10cSrcweir
357cdf0e10cSrcweir /*-----------------25.10.00 09:51-------------------
358cdf0e10cSrcweir * SwMultiPortion::PaintBracket paints the wished bracket,
359cdf0e10cSrcweir * if the multiportion has surrounding brackets.
360cdf0e10cSrcweir * The X-position of the SwTxtPaintInfo will be modified:
361cdf0e10cSrcweir * the open bracket sets position behind itself,
362cdf0e10cSrcweir * the close bracket in front of itself.
363cdf0e10cSrcweir * --------------------------------------------------*/
364cdf0e10cSrcweir
PaintBracket(SwTxtPaintInfo & rInf,long nSpaceAdd,sal_Bool bOpen) const365cdf0e10cSrcweir void SwDoubleLinePortion::PaintBracket( SwTxtPaintInfo &rInf,
366cdf0e10cSrcweir long nSpaceAdd,
367cdf0e10cSrcweir sal_Bool bOpen ) const
368cdf0e10cSrcweir {
369cdf0e10cSrcweir sal_Unicode cCh = bOpen ? pBracket->cPre : pBracket->cPost;
370cdf0e10cSrcweir if( !cCh )
371cdf0e10cSrcweir return;
372cdf0e10cSrcweir KSHORT nChWidth = bOpen ? PreWidth() : PostWidth();
373cdf0e10cSrcweir if( !nChWidth )
374cdf0e10cSrcweir return;
375cdf0e10cSrcweir if( !bOpen )
376cdf0e10cSrcweir rInf.X( rInf.X() + Width() - PostWidth() +
377cdf0e10cSrcweir ( nSpaceAdd > 0 ? CalcSpacing( nSpaceAdd, rInf ) : 0 ) );
378cdf0e10cSrcweir
379cdf0e10cSrcweir SwBlankPortion aBlank( cCh, sal_True );
380cdf0e10cSrcweir aBlank.SetAscent( pBracket->nAscent );
381cdf0e10cSrcweir aBlank.Width( nChWidth );
382cdf0e10cSrcweir aBlank.Height( pBracket->nHeight );
383cdf0e10cSrcweir {
384cdf0e10cSrcweir SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
385cdf0e10cSrcweir sal_uInt8 nAct = bOpen ? pBracket->nPreScript : pBracket->nPostScript;
386cdf0e10cSrcweir if( SW_SCRIPTS > nAct )
387cdf0e10cSrcweir pTmpFnt->SetActual( nAct );
388cdf0e10cSrcweir pTmpFnt->SetProportion( 100 );
389cdf0e10cSrcweir SwFontSave aSave( rInf, pTmpFnt );
390cdf0e10cSrcweir aBlank.Paint( rInf );
391cdf0e10cSrcweir delete pTmpFnt;
392cdf0e10cSrcweir }
393cdf0e10cSrcweir if( bOpen )
394cdf0e10cSrcweir rInf.X( rInf.X() + PreWidth() );
395cdf0e10cSrcweir }
396cdf0e10cSrcweir
397cdf0e10cSrcweir /*-----------------25.10.00 16:26-------------------
398cdf0e10cSrcweir * SwDoubleLinePortion::SetBrackets creates the bracket-structur
399cdf0e10cSrcweir * and fills it, if not both characters are 0x00.
400cdf0e10cSrcweir * --------------------------------------------------*/
401cdf0e10cSrcweir
SetBrackets(const SwDoubleLinePortion & rDouble)402cdf0e10cSrcweir void SwDoubleLinePortion::SetBrackets( const SwDoubleLinePortion& rDouble )
403cdf0e10cSrcweir {
404cdf0e10cSrcweir if( rDouble.pBracket )
405cdf0e10cSrcweir {
406cdf0e10cSrcweir pBracket = new SwBracket;
407cdf0e10cSrcweir pBracket->cPre = rDouble.pBracket->cPre;
408cdf0e10cSrcweir pBracket->cPost = rDouble.pBracket->cPost;
409cdf0e10cSrcweir pBracket->nPreScript = rDouble.pBracket->nPreScript;
410cdf0e10cSrcweir pBracket->nPostScript = rDouble.pBracket->nPostScript;
411cdf0e10cSrcweir pBracket->nStart = rDouble.pBracket->nStart;
412cdf0e10cSrcweir }
413cdf0e10cSrcweir }
414cdf0e10cSrcweir
415cdf0e10cSrcweir /*-----------------25.10.00 16:29-------------------
416cdf0e10cSrcweir * SwDoubleLinePortion::FormatBrackets
417cdf0e10cSrcweir * calculates the size of the brackets => pBracket,
418cdf0e10cSrcweir * reduces the nMaxWidth-parameter ( minus bracket-width )
419cdf0e10cSrcweir * and moves the rInf-x-position behind the opening bracket.
420cdf0e10cSrcweir * --------------------------------------------------*/
421cdf0e10cSrcweir
FormatBrackets(SwTxtFormatInfo & rInf,SwTwips & nMaxWidth)422cdf0e10cSrcweir void SwDoubleLinePortion::FormatBrackets( SwTxtFormatInfo &rInf, SwTwips& nMaxWidth )
423cdf0e10cSrcweir {
424cdf0e10cSrcweir nMaxWidth -= rInf.X();
425cdf0e10cSrcweir SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
426cdf0e10cSrcweir pTmpFnt->SetProportion( 100 );
427cdf0e10cSrcweir pBracket->nAscent = 0;
428cdf0e10cSrcweir pBracket->nHeight = 0;
429cdf0e10cSrcweir if( pBracket->cPre )
430cdf0e10cSrcweir {
431cdf0e10cSrcweir String aStr( pBracket->cPre );
432cdf0e10cSrcweir sal_uInt8 nActualScr = pTmpFnt->GetActual();
433cdf0e10cSrcweir if( SW_SCRIPTS > pBracket->nPreScript )
434cdf0e10cSrcweir pTmpFnt->SetActual( pBracket->nPreScript );
435cdf0e10cSrcweir SwFontSave aSave( rInf, pTmpFnt );
436cdf0e10cSrcweir SwPosSize aSize = rInf.GetTxtSize( aStr );
437cdf0e10cSrcweir pBracket->nAscent = rInf.GetAscent();
438cdf0e10cSrcweir pBracket->nHeight = aSize.Height();
439cdf0e10cSrcweir pTmpFnt->SetActual( nActualScr );
440cdf0e10cSrcweir if( nMaxWidth > aSize.Width() )
441cdf0e10cSrcweir {
442cdf0e10cSrcweir pBracket->nPreWidth = aSize.Width();
443cdf0e10cSrcweir nMaxWidth -= aSize.Width();
444cdf0e10cSrcweir rInf.X( rInf.X() + aSize.Width() );
445cdf0e10cSrcweir }
446cdf0e10cSrcweir else
447cdf0e10cSrcweir {
448cdf0e10cSrcweir pBracket->nPreWidth = 0;
449cdf0e10cSrcweir nMaxWidth = 0;
450cdf0e10cSrcweir }
451cdf0e10cSrcweir }
452cdf0e10cSrcweir else
453cdf0e10cSrcweir pBracket->nPreWidth = 0;
454cdf0e10cSrcweir if( pBracket->cPost )
455cdf0e10cSrcweir {
456cdf0e10cSrcweir String aStr( pBracket->cPost );
457cdf0e10cSrcweir if( SW_SCRIPTS > pBracket->nPostScript )
458cdf0e10cSrcweir pTmpFnt->SetActual( pBracket->nPostScript );
459cdf0e10cSrcweir SwFontSave aSave( rInf, pTmpFnt );
460cdf0e10cSrcweir SwPosSize aSize = rInf.GetTxtSize( aStr );
461cdf0e10cSrcweir KSHORT nTmpAsc = rInf.GetAscent();
462cdf0e10cSrcweir if( nTmpAsc > pBracket->nAscent )
463cdf0e10cSrcweir {
464cdf0e10cSrcweir pBracket->nHeight += nTmpAsc - pBracket->nAscent;
465cdf0e10cSrcweir pBracket->nAscent = nTmpAsc;
466cdf0e10cSrcweir }
467cdf0e10cSrcweir if( aSize.Height() > pBracket->nHeight )
468cdf0e10cSrcweir pBracket->nHeight = aSize.Height();
469cdf0e10cSrcweir if( nMaxWidth > aSize.Width() )
470cdf0e10cSrcweir {
471cdf0e10cSrcweir pBracket->nPostWidth = aSize.Width();
472cdf0e10cSrcweir nMaxWidth -= aSize.Width();
473cdf0e10cSrcweir }
474cdf0e10cSrcweir else
475cdf0e10cSrcweir {
476cdf0e10cSrcweir pBracket->nPostWidth = 0;
477cdf0e10cSrcweir nMaxWidth = 0;
478cdf0e10cSrcweir }
479cdf0e10cSrcweir }
480cdf0e10cSrcweir else
481cdf0e10cSrcweir pBracket->nPostWidth = 0;
482cdf0e10cSrcweir nMaxWidth += rInf.X();
483cdf0e10cSrcweir }
484cdf0e10cSrcweir
485cdf0e10cSrcweir /*-----------------26.10.00 10:36-------------------
486cdf0e10cSrcweir * SwDoubleLinePortion::CalcBlanks
487cdf0e10cSrcweir * calculates the number of blanks in each line and
488cdf0e10cSrcweir * the difference of the width of the two lines.
489cdf0e10cSrcweir * These results are used from the text adjustment.
490cdf0e10cSrcweir * --------------------------------------------------*/
491cdf0e10cSrcweir
CalcBlanks(SwTxtFormatInfo & rInf)492cdf0e10cSrcweir void SwDoubleLinePortion::CalcBlanks( SwTxtFormatInfo &rInf )
493cdf0e10cSrcweir {
494cdf0e10cSrcweir SwLinePortion* pPor = GetRoot().GetFirstPortion();
495cdf0e10cSrcweir xub_StrLen nNull = 0;
496cdf0e10cSrcweir xub_StrLen nStart = rInf.GetIdx();
497cdf0e10cSrcweir SetTab1( sal_False );
498cdf0e10cSrcweir SetTab2( sal_False );
499cdf0e10cSrcweir for( nBlank1 = 0; pPor; pPor = pPor->GetPortion() )
500cdf0e10cSrcweir {
501cdf0e10cSrcweir if( pPor->InTxtGrp() )
502cdf0e10cSrcweir nBlank1 = nBlank1 + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
503cdf0e10cSrcweir rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
504cdf0e10cSrcweir if( pPor->InTabGrp() )
505cdf0e10cSrcweir SetTab1( sal_True );
506cdf0e10cSrcweir }
507cdf0e10cSrcweir nLineDiff = GetRoot().Width();
508cdf0e10cSrcweir if( GetRoot().GetNext() )
509cdf0e10cSrcweir {
510cdf0e10cSrcweir pPor = GetRoot().GetNext()->GetFirstPortion();
511cdf0e10cSrcweir nLineDiff -= GetRoot().GetNext()->Width();
512cdf0e10cSrcweir }
513cdf0e10cSrcweir for( nBlank2 = 0; pPor; pPor = pPor->GetPortion() )
514cdf0e10cSrcweir {
515cdf0e10cSrcweir if( pPor->InTxtGrp() )
516cdf0e10cSrcweir nBlank2 = nBlank2 + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
517cdf0e10cSrcweir rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
518cdf0e10cSrcweir if( pPor->InTabGrp() )
519cdf0e10cSrcweir SetTab2( sal_True );
520cdf0e10cSrcweir }
521cdf0e10cSrcweir rInf.SetIdx( nStart );
522cdf0e10cSrcweir }
523cdf0e10cSrcweir
CalcSpacing(long nSpaceAdd,const SwTxtSizeInfo &) const524cdf0e10cSrcweir long SwDoubleLinePortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo & ) const
525cdf0e10cSrcweir {
526cdf0e10cSrcweir return HasTabulator() ? 0 : GetSpaceCnt() * nSpaceAdd / SPACING_PRECISION_FACTOR;
527cdf0e10cSrcweir }
528cdf0e10cSrcweir
529cdf0e10cSrcweir /*-----------------01.11.00 14:29-------------------
530cdf0e10cSrcweir * SwDoubleLinePortion::ChangeSpaceAdd(..)
531cdf0e10cSrcweir * merges the spaces for text adjustment from the inner and outer part.
532cdf0e10cSrcweir * Inside the doubleline portion the wider line has no spaceadd-array, the
533cdf0e10cSrcweir * smaller line has such an array to reach width of the wider line.
534cdf0e10cSrcweir * If the surrounding line has text adjustment and the doubleline portion
535cdf0e10cSrcweir * contains no tabulator, it is necessary to create/manipulate the inner
536cdf0e10cSrcweir * space arrays.
537cdf0e10cSrcweir * --------------------------------------------------*/
538cdf0e10cSrcweir
ChgSpaceAdd(SwLineLayout * pCurr,long nSpaceAdd) const539cdf0e10cSrcweir sal_Bool SwDoubleLinePortion::ChgSpaceAdd( SwLineLayout* pCurr,
540cdf0e10cSrcweir long nSpaceAdd ) const
541cdf0e10cSrcweir {
542cdf0e10cSrcweir sal_Bool bRet = sal_False;
543cdf0e10cSrcweir if( !HasTabulator() && nSpaceAdd > 0 )
544cdf0e10cSrcweir {
545cdf0e10cSrcweir if( !pCurr->IsSpaceAdd() )
546cdf0e10cSrcweir {
547cdf0e10cSrcweir // The wider line gets the spaceadd from the surrounding line direct
548cdf0e10cSrcweir pCurr->CreateSpaceAdd();
549cdf0e10cSrcweir pCurr->SetLLSpaceAdd( nSpaceAdd, 0 );
550cdf0e10cSrcweir bRet = sal_True;
551cdf0e10cSrcweir }
552cdf0e10cSrcweir else
553cdf0e10cSrcweir {
554cdf0e10cSrcweir xub_StrLen nMyBlank = GetSmallerSpaceCnt();
555cdf0e10cSrcweir xub_StrLen nOther = GetSpaceCnt();
556cdf0e10cSrcweir SwTwips nMultiSpace = pCurr->GetLLSpaceAdd( 0 ) * nMyBlank + nOther * nSpaceAdd;
557cdf0e10cSrcweir
558cdf0e10cSrcweir if( nMyBlank )
559cdf0e10cSrcweir nMultiSpace /= nMyBlank;
560cdf0e10cSrcweir
561cdf0e10cSrcweir if( nMultiSpace < KSHRT_MAX * SPACING_PRECISION_FACTOR )
562cdf0e10cSrcweir {
563cdf0e10cSrcweir // pCurr->SetLLSpaceAdd( nMultiSpace, 0 );
564cdf0e10cSrcweir // --> FME 2006-07-11 #i65711# SetLLSpaceAdd replaces the first value,
565cdf0e10cSrcweir // instead we want to insert a new first value:
566cdf0e10cSrcweir std::vector<long>* pVec = pCurr->GetpLLSpaceAdd();
567cdf0e10cSrcweir pVec->insert( pVec->begin(), nMultiSpace );
568cdf0e10cSrcweir // <--
569cdf0e10cSrcweir bRet = sal_True;
570cdf0e10cSrcweir }
571cdf0e10cSrcweir }
572cdf0e10cSrcweir }
573cdf0e10cSrcweir return bRet;
574cdf0e10cSrcweir }
575cdf0e10cSrcweir /*-----------------01.11.00 14:29-------------------
576cdf0e10cSrcweir * SwDoubleLinePortion::ResetSpaceAdd(..)
577cdf0e10cSrcweir * cancels the manipulation from SwDoubleLinePortion::ChangeSpaceAdd(..)
578cdf0e10cSrcweir * --------------------------------------------------*/
579cdf0e10cSrcweir
ResetSpaceAdd(SwLineLayout * pCurr)580cdf0e10cSrcweir void SwDoubleLinePortion::ResetSpaceAdd( SwLineLayout* pCurr )
581cdf0e10cSrcweir {
582cdf0e10cSrcweir pCurr->RemoveFirstLLSpaceAdd();;
583cdf0e10cSrcweir if( !pCurr->GetLLSpaceAddCount() )
584cdf0e10cSrcweir pCurr->FinishSpaceAdd();
585cdf0e10cSrcweir }
586cdf0e10cSrcweir
~SwDoubleLinePortion()587cdf0e10cSrcweir SwDoubleLinePortion::~SwDoubleLinePortion()
588cdf0e10cSrcweir {
589cdf0e10cSrcweir delete pBracket;
590cdf0e10cSrcweir }
591cdf0e10cSrcweir
592cdf0e10cSrcweir /*-----------------13.11.00 14:50-------------------
593cdf0e10cSrcweir * SwRubyPortion::SwRubyPortion(..)
594cdf0e10cSrcweir * constructs a ruby portion, i.e. an additional text is displayed
595cdf0e10cSrcweir * beside the main text, e.g. phonetic characters.
596cdf0e10cSrcweir * --------------------------------------------------*/
597cdf0e10cSrcweir
598cdf0e10cSrcweir
SwRubyPortion(const SwRubyPortion & rRuby,xub_StrLen nEnd)599cdf0e10cSrcweir SwRubyPortion::SwRubyPortion( const SwRubyPortion& rRuby, xub_StrLen nEnd ) :
600cdf0e10cSrcweir SwMultiPortion( nEnd ),
601cdf0e10cSrcweir nRubyOffset( rRuby.GetRubyOffset() ),
602cdf0e10cSrcweir nAdjustment( rRuby.GetAdjustment() )
603cdf0e10cSrcweir {
604cdf0e10cSrcweir SetDirection( rRuby.GetDirection() ),
605cdf0e10cSrcweir SetTop( rRuby.OnTop() );
606cdf0e10cSrcweir SetRuby();
607cdf0e10cSrcweir }
608cdf0e10cSrcweir
609cdf0e10cSrcweir /*-----------------13.11.00 14:50-------------------
610cdf0e10cSrcweir * SwRubyPortion::SwRubyPortion(..)
611cdf0e10cSrcweir * constructs a ruby portion, i.e. an additional text is displayed
612cdf0e10cSrcweir * beside the main text, e.g. phonetic characters.
613cdf0e10cSrcweir * --------------------------------------------------*/
614cdf0e10cSrcweir
SwRubyPortion(const SwMultiCreator & rCreate,const SwFont & rFnt,const IDocumentSettingAccess & rIDocumentSettingAccess,xub_StrLen nEnd,xub_StrLen nOffs,const sal_Bool * pForceRubyPos)615cdf0e10cSrcweir SwRubyPortion::SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt,
616cdf0e10cSrcweir const IDocumentSettingAccess& rIDocumentSettingAccess,
617cdf0e10cSrcweir xub_StrLen nEnd, xub_StrLen nOffs,
618cdf0e10cSrcweir const sal_Bool* pForceRubyPos )
619cdf0e10cSrcweir : SwMultiPortion( nEnd )
620cdf0e10cSrcweir {
621cdf0e10cSrcweir SetRuby();
622cdf0e10cSrcweir ASSERT( SW_MC_RUBY == rCreate.nId, "Ruby expected" );
623cdf0e10cSrcweir ASSERT( RES_TXTATR_CJK_RUBY == rCreate.pAttr->Which(), "Wrong attribute" );
624cdf0e10cSrcweir const SwFmtRuby& rRuby = rCreate.pAttr->GetRuby();
625cdf0e10cSrcweir nAdjustment = rRuby.GetAdjustment();
626cdf0e10cSrcweir nRubyOffset = nOffs;
627cdf0e10cSrcweir
628cdf0e10cSrcweir // in grid mode we force the ruby text to the upper or lower line
629cdf0e10cSrcweir if ( pForceRubyPos )
630cdf0e10cSrcweir SetTop( *pForceRubyPos );
631cdf0e10cSrcweir else
632cdf0e10cSrcweir SetTop( ! rRuby.GetPosition() );
633cdf0e10cSrcweir
634cdf0e10cSrcweir const SwCharFmt* pFmt = ((SwTxtRuby*)rCreate.pAttr)->GetCharFmt();
635cdf0e10cSrcweir SwFont *pRubyFont;
636cdf0e10cSrcweir if( pFmt )
637cdf0e10cSrcweir {
638cdf0e10cSrcweir const SwAttrSet& rSet = pFmt->GetAttrSet();
639cdf0e10cSrcweir pRubyFont = new SwFont( rFnt );
640cdf0e10cSrcweir pRubyFont->SetDiffFnt( &rSet, &rIDocumentSettingAccess );
641cdf0e10cSrcweir
642cdf0e10cSrcweir // we do not allow a vertical font for the ruby text
643cdf0e10cSrcweir pRubyFont->SetVertical( rFnt.GetOrientation() );
644cdf0e10cSrcweir }
645cdf0e10cSrcweir else
646cdf0e10cSrcweir pRubyFont = NULL;
647cdf0e10cSrcweir
648cdf0e10cSrcweir String aStr( rRuby.GetText(), nOffs, STRING_LEN );
649cdf0e10cSrcweir SwFldPortion *pFld = new SwFldPortion( aStr, pRubyFont );
650cdf0e10cSrcweir pFld->SetNextOffset( nOffs );
651cdf0e10cSrcweir pFld->SetFollow( sal_True );
652cdf0e10cSrcweir
653cdf0e10cSrcweir if( OnTop() )
654cdf0e10cSrcweir GetRoot().SetPortion( pFld );
655cdf0e10cSrcweir else
656cdf0e10cSrcweir {
657cdf0e10cSrcweir GetRoot().SetNext( new SwLineLayout() );
658cdf0e10cSrcweir GetRoot().GetNext()->SetPortion( pFld );
659cdf0e10cSrcweir }
660cdf0e10cSrcweir
661cdf0e10cSrcweir // ruby portions have the same direction as the frame directions
662cdf0e10cSrcweir if ( rCreate.nLevel % 2 )
663cdf0e10cSrcweir {
664cdf0e10cSrcweir // switch right and left ruby adjustment in rtl environment
665cdf0e10cSrcweir if ( 0 == nAdjustment )
666cdf0e10cSrcweir nAdjustment = 2;
667cdf0e10cSrcweir else if ( 2 == nAdjustment )
668cdf0e10cSrcweir nAdjustment = 0;
669cdf0e10cSrcweir
670cdf0e10cSrcweir SetDirection( DIR_RIGHT2LEFT );
671cdf0e10cSrcweir }
672cdf0e10cSrcweir else
673cdf0e10cSrcweir SetDirection( DIR_LEFT2RIGHT );
674cdf0e10cSrcweir }
675cdf0e10cSrcweir
676cdf0e10cSrcweir /*-----------------13.11.00 14:56-------------------
677cdf0e10cSrcweir * SwRubyPortion::_Adjust(..)
678cdf0e10cSrcweir * In ruby portion there are different alignments for
679cdf0e10cSrcweir * the ruby text and the main text.
680cdf0e10cSrcweir * Left, right, centered and two possibilities of block adjustment
681cdf0e10cSrcweir * The block adjustment is realized by spacing between the characteres,
682cdf0e10cSrcweir * either with a half space or no space in front of the first letter and
683cdf0e10cSrcweir * a half space at the end of the last letter.
684cdf0e10cSrcweir * Notice: the smaller line will be manipulated, normally it's the ruby line,
685cdf0e10cSrcweir * but it could be the main text, too.
686cdf0e10cSrcweir * If there is a tabulator in smaller line, no adjustment is possible.
687cdf0e10cSrcweir * --------------------------------------------------*/
688cdf0e10cSrcweir
_Adjust(SwTxtFormatInfo & rInf)689cdf0e10cSrcweir void SwRubyPortion::_Adjust( SwTxtFormatInfo &rInf )
690cdf0e10cSrcweir {
691cdf0e10cSrcweir SwTwips nLineDiff = GetRoot().Width() - GetRoot().GetNext()->Width();
692cdf0e10cSrcweir xub_StrLen nOldIdx = rInf.GetIdx();
693cdf0e10cSrcweir if( !nLineDiff )
694cdf0e10cSrcweir return;
695cdf0e10cSrcweir SwLineLayout *pCurr;
696cdf0e10cSrcweir if( nLineDiff < 0 )
697cdf0e10cSrcweir { // The first line has to be adjusted.
698cdf0e10cSrcweir if( GetTab1() )
699cdf0e10cSrcweir return;
700cdf0e10cSrcweir pCurr = &GetRoot();
701cdf0e10cSrcweir nLineDiff = -nLineDiff;
702cdf0e10cSrcweir }
703cdf0e10cSrcweir else
704cdf0e10cSrcweir { // The second line has to be adjusted.
705cdf0e10cSrcweir if( GetTab2() )
706cdf0e10cSrcweir return;
707cdf0e10cSrcweir pCurr = GetRoot().GetNext();
708cdf0e10cSrcweir rInf.SetIdx( nOldIdx + GetRoot().GetLen() );
709cdf0e10cSrcweir }
710cdf0e10cSrcweir KSHORT nLeft = 0; // the space in front of the first letter
711cdf0e10cSrcweir KSHORT nRight = 0; // the space at the end of the last letter
712cdf0e10cSrcweir sal_uInt16 nSub = 0;
713cdf0e10cSrcweir switch ( nAdjustment )
714cdf0e10cSrcweir {
715cdf0e10cSrcweir case 1: nRight = static_cast<sal_uInt16>(nLineDiff / 2); // no break
716cdf0e10cSrcweir case 2: nLeft = static_cast<sal_uInt16>(nLineDiff - nRight); break;
717cdf0e10cSrcweir case 3: nSub = 1; // no break
718cdf0e10cSrcweir case 4:
719cdf0e10cSrcweir {
720cdf0e10cSrcweir xub_StrLen nCharCnt = 0;
721cdf0e10cSrcweir SwLinePortion *pPor;
722cdf0e10cSrcweir for( pPor = pCurr->GetFirstPortion(); pPor; pPor = pPor->GetPortion() )
723cdf0e10cSrcweir {
724cdf0e10cSrcweir if( pPor->InTxtGrp() )
725cdf0e10cSrcweir ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nCharCnt );
726cdf0e10cSrcweir rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
727cdf0e10cSrcweir }
728cdf0e10cSrcweir if( nCharCnt > nSub )
729cdf0e10cSrcweir {
730cdf0e10cSrcweir SwTwips nCalc = nLineDiff / ( nCharCnt - nSub );
731cdf0e10cSrcweir short nTmp;
732cdf0e10cSrcweir if( nCalc < SHRT_MAX )
733cdf0e10cSrcweir nTmp = -short(nCalc);
734cdf0e10cSrcweir else
735cdf0e10cSrcweir nTmp = SHRT_MIN;
736cdf0e10cSrcweir
737cdf0e10cSrcweir pCurr->CreateSpaceAdd( SPACING_PRECISION_FACTOR * nTmp );
738cdf0e10cSrcweir nLineDiff -= nCalc * ( nCharCnt - 1 );
739cdf0e10cSrcweir }
740cdf0e10cSrcweir if( nLineDiff > 1 )
741cdf0e10cSrcweir {
742cdf0e10cSrcweir nRight = static_cast<sal_uInt16>(nLineDiff / 2);
743cdf0e10cSrcweir nLeft = static_cast<sal_uInt16>(nLineDiff - nRight);
744cdf0e10cSrcweir }
745cdf0e10cSrcweir break;
746cdf0e10cSrcweir }
747cdf0e10cSrcweir default: ASSERT( sal_False, "New ruby adjustment" );
748cdf0e10cSrcweir }
749cdf0e10cSrcweir if( nLeft || nRight )
750cdf0e10cSrcweir {
751cdf0e10cSrcweir if( !pCurr->GetPortion() )
752cdf0e10cSrcweir pCurr->SetPortion( new SwTxtPortion( *pCurr ) );
753cdf0e10cSrcweir SwMarginPortion *pMarg = new SwMarginPortion( 0 );
754cdf0e10cSrcweir if( nLeft )
755cdf0e10cSrcweir {
756cdf0e10cSrcweir pMarg->AddPrtWidth( nLeft );
757cdf0e10cSrcweir pMarg->SetPortion( pCurr->GetPortion() );
758cdf0e10cSrcweir pCurr->SetPortion( pMarg );
759cdf0e10cSrcweir }
760cdf0e10cSrcweir if( nRight )
761cdf0e10cSrcweir {
762cdf0e10cSrcweir pMarg = new SwMarginPortion( 0 );
763cdf0e10cSrcweir pMarg->AddPrtWidth( nRight );
764cdf0e10cSrcweir pCurr->FindLastPortion()->Append( pMarg );
765cdf0e10cSrcweir }
766cdf0e10cSrcweir }
767cdf0e10cSrcweir
768cdf0e10cSrcweir pCurr->Width( Width() );
769cdf0e10cSrcweir rInf.SetIdx( nOldIdx );
770cdf0e10cSrcweir }
771cdf0e10cSrcweir
772cdf0e10cSrcweir /*-----------------08.11.00 14:14-------------------
773cdf0e10cSrcweir * CalcRubyOffset()
774cdf0e10cSrcweir * has to change the nRubyOffset, if there's a fieldportion
775cdf0e10cSrcweir * in the phonetic line.
776cdf0e10cSrcweir * The nRubyOffset is the position in the rubystring, where the
777cdf0e10cSrcweir * next SwRubyPortion has start the displaying of the phonetics.
778cdf0e10cSrcweir * --------------------------------------------------*/
779cdf0e10cSrcweir
CalcRubyOffset()780cdf0e10cSrcweir void SwRubyPortion::CalcRubyOffset()
781cdf0e10cSrcweir {
782cdf0e10cSrcweir const SwLineLayout *pCurr = &GetRoot();
783cdf0e10cSrcweir if( !OnTop() )
784cdf0e10cSrcweir {
785cdf0e10cSrcweir pCurr = pCurr->GetNext();
786cdf0e10cSrcweir if( !pCurr )
787cdf0e10cSrcweir return;
788cdf0e10cSrcweir }
789cdf0e10cSrcweir const SwLinePortion *pPor = pCurr->GetFirstPortion();
790cdf0e10cSrcweir const SwFldPortion *pFld = NULL;
791cdf0e10cSrcweir while( pPor )
792cdf0e10cSrcweir {
793cdf0e10cSrcweir if( pPor->InFldGrp() )
794cdf0e10cSrcweir pFld = (SwFldPortion*)pPor;
795cdf0e10cSrcweir pPor = pPor->GetPortion();
796cdf0e10cSrcweir }
797cdf0e10cSrcweir if( pFld )
798cdf0e10cSrcweir {
799cdf0e10cSrcweir if( pFld->HasFollow() )
800cdf0e10cSrcweir nRubyOffset = pFld->GetNextOffset();
801cdf0e10cSrcweir else
802cdf0e10cSrcweir nRubyOffset = STRING_LEN;
803cdf0e10cSrcweir }
804cdf0e10cSrcweir }
805cdf0e10cSrcweir
806cdf0e10cSrcweir /*-----------------13.10.00 16:22-------------------
807cdf0e10cSrcweir * SwTxtSizeInfo::GetMultiCreator(..)
808cdf0e10cSrcweir * If we (e.g. the position rPos) are inside a two-line-attribute or
809cdf0e10cSrcweir * a ruby-attribute, the attribute will be returned in a SwMultiCreator-struct,
810cdf0e10cSrcweir * otherwise the function returns zero.
811cdf0e10cSrcweir * The rPos parameter is set to the end of the multiportion,
812cdf0e10cSrcweir * normally this is the end of the attribute,
813cdf0e10cSrcweir * but sometimes it is the start of another attribute, which finished or
814cdf0e10cSrcweir * interrupts the first attribute.
815cdf0e10cSrcweir * E.g. a ruby portion interrupts a 2-line-attribute, a 2-line-attribute
816cdf0e10cSrcweir * with different brackets interrupts another 2-line-attribute.
817cdf0e10cSrcweir * --------------------------------------------------*/
818cdf0e10cSrcweir
819cdf0e10cSrcweir /*-----------------13.11.00 15:38-------------------
820cdf0e10cSrcweir * lcl_Has2Lines(..)
821cdf0e10cSrcweir * is a little help function for GetMultiCreator(..)
822cdf0e10cSrcweir * It extracts the 2-line-format from a 2-line-attribute or a character style.
823cdf0e10cSrcweir * The rValue is set to sal_True, if the 2-line-attribute's value is set and
824cdf0e10cSrcweir * no 2-line-format reference is passed. If there is a 2-line-format reference,
825cdf0e10cSrcweir * then the rValue is set only, if the 2-line-attribute's value is set _and_
826cdf0e10cSrcweir * the 2-line-formats has the same brackets.
827cdf0e10cSrcweir * --------------------------------------------------*/
828cdf0e10cSrcweir
lcl_Has2Lines(const SwTxtAttr & rAttr,const SvxTwoLinesItem * & rpRef,sal_Bool & rValue)829cdf0e10cSrcweir sal_Bool lcl_Has2Lines( const SwTxtAttr& rAttr, const SvxTwoLinesItem* &rpRef,
830cdf0e10cSrcweir sal_Bool &rValue )
831cdf0e10cSrcweir {
832cdf0e10cSrcweir const SfxPoolItem* pItem = CharFmt::GetItem( rAttr, RES_CHRATR_TWO_LINES );
833cdf0e10cSrcweir if( pItem )
834cdf0e10cSrcweir {
835cdf0e10cSrcweir rValue = ((SvxTwoLinesItem*)pItem)->GetValue();
836cdf0e10cSrcweir if( !rpRef )
837cdf0e10cSrcweir rpRef = (SvxTwoLinesItem*)pItem;
838cdf0e10cSrcweir else if( ((SvxTwoLinesItem*)pItem)->GetEndBracket() !=
839cdf0e10cSrcweir rpRef->GetEndBracket() ||
840cdf0e10cSrcweir ((SvxTwoLinesItem*)pItem)->GetStartBracket() !=
841cdf0e10cSrcweir rpRef->GetStartBracket() )
842cdf0e10cSrcweir rValue = sal_False;
843cdf0e10cSrcweir return sal_True;
844cdf0e10cSrcweir }
845cdf0e10cSrcweir return sal_False;
846cdf0e10cSrcweir }
847cdf0e10cSrcweir
848cdf0e10cSrcweir /*-----------------16.02.01 16:39-------------------
849cdf0e10cSrcweir * lcl_HasRotation(..)
850cdf0e10cSrcweir * is a little help function for GetMultiCreator(..)
851cdf0e10cSrcweir * It extracts the charrotation from a charrotate-attribute or a character style.
852cdf0e10cSrcweir * The rValue is set to sal_True, if the charrotate-attribute's value is set and
853cdf0e10cSrcweir * no charrotate-format reference is passed.
854cdf0e10cSrcweir * If there is a charrotate-format reference, then the rValue is set only,
855cdf0e10cSrcweir * if the charrotate-attribute's value is set _and_ identical
856cdf0e10cSrcweir * to the charrotate-format's value.
857cdf0e10cSrcweir * --------------------------------------------------*/
858cdf0e10cSrcweir
lcl_HasRotation(const SwTxtAttr & rAttr,const SvxCharRotateItem * & rpRef,sal_Bool & rValue)859cdf0e10cSrcweir sal_Bool lcl_HasRotation( const SwTxtAttr& rAttr,
860cdf0e10cSrcweir const SvxCharRotateItem* &rpRef, sal_Bool &rValue )
861cdf0e10cSrcweir {
862cdf0e10cSrcweir const SfxPoolItem* pItem = CharFmt::GetItem( rAttr, RES_CHRATR_ROTATE );
863cdf0e10cSrcweir if ( pItem )
864cdf0e10cSrcweir {
865cdf0e10cSrcweir rValue = 0 != ((SvxCharRotateItem*)pItem)->GetValue();
866cdf0e10cSrcweir if( !rpRef )
867cdf0e10cSrcweir rpRef = (SvxCharRotateItem*)pItem;
868cdf0e10cSrcweir else if( ((SvxCharRotateItem*)pItem)->GetValue() !=
869cdf0e10cSrcweir rpRef->GetValue() )
870cdf0e10cSrcweir rValue = sal_False;
871cdf0e10cSrcweir return sal_True;
872cdf0e10cSrcweir }
873cdf0e10cSrcweir
874cdf0e10cSrcweir return sal_False;
875cdf0e10cSrcweir }
876cdf0e10cSrcweir
GetMultiCreator(xub_StrLen & rPos,SwMultiPortion * pMulti) const877cdf0e10cSrcweir SwMultiCreator* SwTxtSizeInfo::GetMultiCreator( xub_StrLen &rPos,
878cdf0e10cSrcweir SwMultiPortion* pMulti ) const
879cdf0e10cSrcweir {
880cdf0e10cSrcweir SwScriptInfo& rSI = ((SwParaPortion*)GetParaPortion())->GetScriptInfo();
881cdf0e10cSrcweir
882cdf0e10cSrcweir // get the last embedding level
883cdf0e10cSrcweir sal_uInt8 nCurrLevel;
884cdf0e10cSrcweir if ( pMulti )
885cdf0e10cSrcweir {
886cdf0e10cSrcweir ASSERT( pMulti->IsBidi(), "Nested MultiPortion is not BidiPortion" )
887cdf0e10cSrcweir // level associated with bidi-portion;
888cdf0e10cSrcweir nCurrLevel = ((SwBidiPortion*)pMulti)->GetLevel();
889cdf0e10cSrcweir }
890cdf0e10cSrcweir else
891cdf0e10cSrcweir // no nested bidi portion required
892cdf0e10cSrcweir nCurrLevel = GetTxtFrm()->IsRightToLeft() ? 1 : 0;
893cdf0e10cSrcweir
894cdf0e10cSrcweir // check if there is a field at rPos:
895cdf0e10cSrcweir sal_uInt8 nNextLevel = nCurrLevel;
896cdf0e10cSrcweir sal_Bool bFldBidi = sal_False;
897cdf0e10cSrcweir
898cdf0e10cSrcweir if ( CH_TXTATR_BREAKWORD == GetChar( rPos ) )
899cdf0e10cSrcweir {
900cdf0e10cSrcweir bFldBidi = sal_True;
901cdf0e10cSrcweir /*
902cdf0e10cSrcweir // examining the script of the field text should be sufficient
903cdf0e10cSrcweir // for 99% of all cases
904cdf0e10cSrcweir XubString aTxt = GetTxtFrm()->GetTxtNode()->GetExpandTxt( rPos, 1 );
905cdf0e10cSrcweir
906cdf0e10cSrcweir if ( pBreakIt->GetBreakIter().is() && aTxt.Len() )
907cdf0e10cSrcweir {
908cdf0e10cSrcweir sal_Bool bFldDir = ( i18n::ScriptType::COMPLEX ==
909cdf0e10cSrcweir pBreakIt->GetRealScriptOfText( aTxt, 0 ) );
910cdf0e10cSrcweir sal_Bool bCurrDir = ( 0 != ( nCurrLevel % 2 ) );
911cdf0e10cSrcweir if ( bFldDir != bCurrDir )
912cdf0e10cSrcweir {
913cdf0e10cSrcweir nNextLevel = nCurrLevel + 1;
914cdf0e10cSrcweir bFldBidi = sal_True;
915cdf0e10cSrcweir }
916cdf0e10cSrcweir }*/
917cdf0e10cSrcweir }
918cdf0e10cSrcweir else
919cdf0e10cSrcweir nNextLevel = rSI.DirType( rPos );
920cdf0e10cSrcweir
921cdf0e10cSrcweir if ( GetTxt().Len() != rPos && nNextLevel > nCurrLevel )
922cdf0e10cSrcweir {
923cdf0e10cSrcweir rPos = bFldBidi ? rPos + 1 : rSI.NextDirChg( rPos, &nCurrLevel );
924cdf0e10cSrcweir if ( STRING_LEN == rPos )
925cdf0e10cSrcweir return NULL;
926cdf0e10cSrcweir SwMultiCreator *pRet = new SwMultiCreator;
927cdf0e10cSrcweir pRet->pItem = NULL;
928cdf0e10cSrcweir pRet->pAttr = NULL;
929cdf0e10cSrcweir pRet->nId = SW_MC_BIDI;
930cdf0e10cSrcweir pRet->nLevel = nCurrLevel + 1;
931cdf0e10cSrcweir return pRet;
932cdf0e10cSrcweir }
933cdf0e10cSrcweir
934cdf0e10cSrcweir // a bidi portion can only contain other bidi portions
935cdf0e10cSrcweir if ( pMulti )
936cdf0e10cSrcweir return NULL;
937cdf0e10cSrcweir
938cdf0e10cSrcweir const SvxCharRotateItem* pRotate = NULL;
939cdf0e10cSrcweir const SfxPoolItem* pRotItem;
940cdf0e10cSrcweir if( SFX_ITEM_SET == pFrm->GetTxtNode()->GetSwAttrSet().
941cdf0e10cSrcweir GetItemState( RES_CHRATR_ROTATE, sal_True, &pRotItem ) &&
942cdf0e10cSrcweir ((SvxCharRotateItem*)pRotItem)->GetValue() )
943cdf0e10cSrcweir pRotate = (SvxCharRotateItem*)pRotItem;
944cdf0e10cSrcweir else
945cdf0e10cSrcweir pRotItem = NULL;
946cdf0e10cSrcweir const SvxTwoLinesItem* p2Lines = NULL;
947cdf0e10cSrcweir const SfxPoolItem* pItem;
948cdf0e10cSrcweir if( SFX_ITEM_SET == pFrm->GetTxtNode()->GetSwAttrSet().
949cdf0e10cSrcweir GetItemState( RES_CHRATR_TWO_LINES, sal_True, &pItem ) &&
950cdf0e10cSrcweir ((SvxTwoLinesItem*)pItem)->GetValue() )
951cdf0e10cSrcweir p2Lines = (SvxTwoLinesItem*)pItem;
952cdf0e10cSrcweir else
953cdf0e10cSrcweir pItem = NULL;
954cdf0e10cSrcweir
955cdf0e10cSrcweir const SwpHints *pHints = pFrm->GetTxtNode()->GetpSwpHints();
956cdf0e10cSrcweir if( !pHints && !p2Lines && !pRotate )
957cdf0e10cSrcweir return NULL;
958cdf0e10cSrcweir const SwTxtAttr *pRuby = NULL;
959cdf0e10cSrcweir sal_Bool bTwo = sal_False;
960cdf0e10cSrcweir sal_Bool bRot = sal_False;
961cdf0e10cSrcweir sal_uInt16 n2Lines = USHRT_MAX;
962cdf0e10cSrcweir sal_uInt16 nRotate = USHRT_MAX;
963cdf0e10cSrcweir sal_uInt16 nCount = pHints ? pHints->Count() : 0;
964cdf0e10cSrcweir sal_uInt16 i;
965cdf0e10cSrcweir for( i = 0; i < nCount; ++i )
966cdf0e10cSrcweir {
967cdf0e10cSrcweir const SwTxtAttr *pTmp = (*pHints)[i];
968cdf0e10cSrcweir xub_StrLen nStart = *pTmp->GetStart();
969cdf0e10cSrcweir if( rPos < nStart )
970cdf0e10cSrcweir break;
971cdf0e10cSrcweir if( *pTmp->GetAnyEnd() > rPos )
972cdf0e10cSrcweir {
973cdf0e10cSrcweir if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
974cdf0e10cSrcweir pRuby = pTmp;
975cdf0e10cSrcweir else
976cdf0e10cSrcweir {
977cdf0e10cSrcweir const SvxCharRotateItem* pRoTmp = NULL;
978cdf0e10cSrcweir if( lcl_HasRotation( *pTmp, pRoTmp, bRot ) )
979cdf0e10cSrcweir {
980cdf0e10cSrcweir nRotate = bRot ? i : nCount;
981cdf0e10cSrcweir pRotate = pRoTmp;
982cdf0e10cSrcweir }
983cdf0e10cSrcweir const SvxTwoLinesItem* p2Tmp = NULL;
984cdf0e10cSrcweir if( lcl_Has2Lines( *pTmp, p2Tmp, bTwo ) )
985cdf0e10cSrcweir {
986cdf0e10cSrcweir n2Lines = bTwo ? i : nCount;
987cdf0e10cSrcweir p2Lines = p2Tmp;
988cdf0e10cSrcweir }
989cdf0e10cSrcweir }
990cdf0e10cSrcweir }
991cdf0e10cSrcweir }
992cdf0e10cSrcweir if( pRuby )
993cdf0e10cSrcweir { // The winner is ... a ruby attribute and so
994cdf0e10cSrcweir // the end of the multiportion is the end of the ruby attribute.
99569a74367SOliver-Rainer Wittmann rPos = *pRuby->End();
996cdf0e10cSrcweir SwMultiCreator *pRet = new SwMultiCreator;
997cdf0e10cSrcweir pRet->pItem = NULL;
998cdf0e10cSrcweir pRet->pAttr = pRuby;
999cdf0e10cSrcweir pRet->nId = SW_MC_RUBY;
1000cdf0e10cSrcweir pRet->nLevel = GetTxtFrm()->IsRightToLeft() ? 1 : 0;
1001cdf0e10cSrcweir return pRet;
1002cdf0e10cSrcweir }
1003cdf0e10cSrcweir if( n2Lines < nCount || ( pItem && pItem == p2Lines &&
1004cdf0e10cSrcweir rPos < GetTxt().Len() ) )
1005cdf0e10cSrcweir { // The winner is a 2-line-attribute,
1006cdf0e10cSrcweir // the end of the multiportion depends on the following attributes...
1007cdf0e10cSrcweir SwMultiCreator *pRet = new SwMultiCreator;
1008cdf0e10cSrcweir
1009cdf0e10cSrcweir // We note the endpositions of the 2-line attributes in aEnd as stack
1010cdf0e10cSrcweir SvXub_StrLens aEnd;
1011cdf0e10cSrcweir
1012cdf0e10cSrcweir // The bOn flag signs the state of the last 2-line attribute in the
1013cdf0e10cSrcweir // aEnd-stack, it is compatible with the winner-attribute or
1014cdf0e10cSrcweir // it interrupts the other attribute.
1015cdf0e10cSrcweir sal_Bool bOn = sal_True;
1016cdf0e10cSrcweir
1017cdf0e10cSrcweir if( n2Lines < nCount )
1018cdf0e10cSrcweir {
1019cdf0e10cSrcweir pRet->pItem = NULL;
1020cdf0e10cSrcweir pRet->pAttr = (*pHints)[n2Lines];
102169a74367SOliver-Rainer Wittmann aEnd.push_front( *pRet->pAttr->End() );
1022cdf0e10cSrcweir if( pItem )
1023cdf0e10cSrcweir {
1024cdf0e10cSrcweir aEnd.front() = GetTxt().Len();
1025cdf0e10cSrcweir bOn = ((SvxTwoLinesItem*)pItem)->GetEndBracket() ==
1026cdf0e10cSrcweir p2Lines->GetEndBracket() &&
1027cdf0e10cSrcweir ((SvxTwoLinesItem*)pItem)->GetStartBracket() ==
1028cdf0e10cSrcweir p2Lines->GetStartBracket();
1029cdf0e10cSrcweir }
1030cdf0e10cSrcweir }
1031cdf0e10cSrcweir else
1032cdf0e10cSrcweir {
1033cdf0e10cSrcweir pRet->pItem = pItem;
1034cdf0e10cSrcweir pRet->pAttr = NULL;
1035cdf0e10cSrcweir aEnd.push_front( GetTxt().Len() );
1036cdf0e10cSrcweir }
1037cdf0e10cSrcweir pRet->nId = SW_MC_DOUBLE;
1038cdf0e10cSrcweir pRet->nLevel = GetTxtFrm()->IsRightToLeft() ? 1 : 0;
1039cdf0e10cSrcweir
1040cdf0e10cSrcweir // n2Lines is the index of the last 2-line-attribute, which contains
1041cdf0e10cSrcweir // the actual position.
1042cdf0e10cSrcweir i = 0;
1043cdf0e10cSrcweir // At this moment we know that at position rPos the "winner"-attribute
1044cdf0e10cSrcweir // causes a 2-line-portion. The end of the attribute is the end of the
1045cdf0e10cSrcweir // portion, if there's no interrupting attribute.
1046cdf0e10cSrcweir // There are two kinds of interruptors:
1047cdf0e10cSrcweir // - ruby attributes stops the 2-line-attribute, the end of the
1048cdf0e10cSrcweir // multiline is the start of the ruby attribute
1049cdf0e10cSrcweir // - 2-line-attributes with value "Off" or with different brackets,
1050cdf0e10cSrcweir // these attributes may interrupt the winner, but they could be
1051cdf0e10cSrcweir // neutralized by another 2-line-attribute starting at the same
1052cdf0e10cSrcweir // position with the same brackets as the winner-attribute.
1053cdf0e10cSrcweir
1054cdf0e10cSrcweir // In the following loop rPos is the critical position and it will be
1055cdf0e10cSrcweir // evaluated, if at rPos starts a interrupting or a maintaining
1056cdf0e10cSrcweir // continuity attribute.
1057cdf0e10cSrcweir while( i < nCount )
1058cdf0e10cSrcweir {
1059cdf0e10cSrcweir const SwTxtAttr *pTmp = (*pHints)[i++];
1060cdf0e10cSrcweir if( *pTmp->GetAnyEnd() <= rPos )
1061cdf0e10cSrcweir continue;
1062cdf0e10cSrcweir if( rPos < *pTmp->GetStart() )
1063cdf0e10cSrcweir {
1064cdf0e10cSrcweir // If bOn is sal_False and the next attribute starts later than rPos
1065cdf0e10cSrcweir // the winner attribute is interrupted at rPos.
1066cdf0e10cSrcweir // If the start of the next atribute is behind the end of
1067cdf0e10cSrcweir // the last attribute on the aEnd-stack, this is the endposition
1068cdf0e10cSrcweir // on the stack is the end of the 2-line portion.
1069cdf0e10cSrcweir if( !bOn || aEnd.back() < *pTmp->GetStart() )
1070cdf0e10cSrcweir break;
1071cdf0e10cSrcweir // At this moment, bOn is sal_True and the next attribute starts
1072cdf0e10cSrcweir // behind rPos, so we could move rPos to the next startpoint
1073cdf0e10cSrcweir rPos = *pTmp->GetStart();
1074cdf0e10cSrcweir // We clean up the aEnd-stack, endpositions equal to rPos are
1075cdf0e10cSrcweir // superfluous.
1076cdf0e10cSrcweir while( !aEnd.empty() && aEnd.back() <= rPos )
1077cdf0e10cSrcweir {
1078cdf0e10cSrcweir bOn = !bOn;
1079cdf0e10cSrcweir aEnd.pop_back();
1080cdf0e10cSrcweir }
1081cdf0e10cSrcweir // If the endstack is empty, we simulate an attribute with
1082cdf0e10cSrcweir // state sal_True and endposition rPos
1083cdf0e10cSrcweir if( aEnd.empty() )
1084cdf0e10cSrcweir {
1085cdf0e10cSrcweir aEnd.push_front( rPos );
1086cdf0e10cSrcweir bOn = sal_True;
1087cdf0e10cSrcweir }
1088cdf0e10cSrcweir }
1089cdf0e10cSrcweir // A ruby attribute stops the 2-line immediately
1090cdf0e10cSrcweir if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
1091cdf0e10cSrcweir return pRet;
1092cdf0e10cSrcweir if( lcl_Has2Lines( *pTmp, p2Lines, bTwo ) )
1093cdf0e10cSrcweir { // We have an interesting attribute..
1094cdf0e10cSrcweir if( bTwo == bOn )
1095cdf0e10cSrcweir { // .. with the same state, so the last attribute could
1096cdf0e10cSrcweir // be continued.
109769a74367SOliver-Rainer Wittmann if( aEnd.back() < *pTmp->End() )
109869a74367SOliver-Rainer Wittmann aEnd.back() = *pTmp->End();
1099cdf0e10cSrcweir }
1100cdf0e10cSrcweir else
1101cdf0e10cSrcweir { // .. with a different state.
1102cdf0e10cSrcweir bOn = bTwo;
1103cdf0e10cSrcweir // If this is smaller than the last on the stack, we put
1104cdf0e10cSrcweir // it on the stack. If it has the same endposition, the last
1105cdf0e10cSrcweir // could be removed.
110669a74367SOliver-Rainer Wittmann if( aEnd.back() > *pTmp->End() )
110769a74367SOliver-Rainer Wittmann aEnd.push_back( *pTmp->End() );
1108cdf0e10cSrcweir else if( aEnd.size() > 1 )
1109cdf0e10cSrcweir aEnd.pop_back();
1110cdf0e10cSrcweir else
111169a74367SOliver-Rainer Wittmann aEnd.back() = *pTmp->End();
1112cdf0e10cSrcweir }
1113cdf0e10cSrcweir }
1114cdf0e10cSrcweir }
1115cdf0e10cSrcweir if( bOn && !aEnd.empty() )
1116cdf0e10cSrcweir rPos = aEnd.back();
1117cdf0e10cSrcweir return pRet;
1118cdf0e10cSrcweir }
1119cdf0e10cSrcweir if( nRotate < nCount || ( pRotItem && pRotItem == pRotate &&
1120cdf0e10cSrcweir rPos < GetTxt().Len() ) )
1121cdf0e10cSrcweir { // The winner is a rotate-attribute,
1122cdf0e10cSrcweir // the end of the multiportion depends on the following attributes...
1123cdf0e10cSrcweir SwMultiCreator *pRet = new SwMultiCreator;
1124cdf0e10cSrcweir pRet->nId = SW_MC_ROTATE;
1125cdf0e10cSrcweir
1126cdf0e10cSrcweir // We note the endpositions of the 2-line attributes in aEnd as stack
1127cdf0e10cSrcweir SvXub_StrLens aEnd;
1128cdf0e10cSrcweir
1129cdf0e10cSrcweir // The bOn flag signs the state of the last 2-line attribute in the
1130cdf0e10cSrcweir // aEnd-stack, which could interrupts the winning rotation attribute.
1131cdf0e10cSrcweir sal_Bool bOn = pItem ? sal_True : sal_False;
1132cdf0e10cSrcweir aEnd.push_front( GetTxt().Len() );
1133cdf0e10cSrcweir // n2Lines is the index of the last 2-line-attribute, which contains
1134cdf0e10cSrcweir // the actual position.
1135cdf0e10cSrcweir i = 0;
1136cdf0e10cSrcweir xub_StrLen n2Start = rPos;
1137cdf0e10cSrcweir while( i < nCount )
1138cdf0e10cSrcweir {
1139cdf0e10cSrcweir const SwTxtAttr *pTmp = (*pHints)[i++];
1140cdf0e10cSrcweir if( *pTmp->GetAnyEnd() <= n2Start )
1141cdf0e10cSrcweir continue;
1142cdf0e10cSrcweir if( n2Start < *pTmp->GetStart() )
1143cdf0e10cSrcweir {
1144cdf0e10cSrcweir if( bOn || aEnd.back() < *pTmp->GetStart() )
1145cdf0e10cSrcweir break;
1146cdf0e10cSrcweir n2Start = *pTmp->GetStart();
1147cdf0e10cSrcweir while( !aEnd.empty() && aEnd.back() <= n2Start )
1148cdf0e10cSrcweir {
1149cdf0e10cSrcweir bOn = !bOn;
1150cdf0e10cSrcweir aEnd.pop_back();
1151cdf0e10cSrcweir }
1152cdf0e10cSrcweir if( aEnd.empty() )
1153cdf0e10cSrcweir {
1154cdf0e10cSrcweir aEnd.push_front( n2Start );
1155cdf0e10cSrcweir bOn = sal_False;
1156cdf0e10cSrcweir }
1157cdf0e10cSrcweir }
1158cdf0e10cSrcweir // A ruby attribute stops immediately
1159cdf0e10cSrcweir if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
1160cdf0e10cSrcweir {
1161cdf0e10cSrcweir bOn = sal_True;
1162cdf0e10cSrcweir break;
1163cdf0e10cSrcweir }
1164cdf0e10cSrcweir p2Lines = NULL;
1165cdf0e10cSrcweir if( lcl_Has2Lines( *pTmp, p2Lines, bTwo ) )
1166cdf0e10cSrcweir {
1167cdf0e10cSrcweir if( bTwo == bOn )
1168cdf0e10cSrcweir {
116969a74367SOliver-Rainer Wittmann if( aEnd.back() < *pTmp->End() )
117069a74367SOliver-Rainer Wittmann aEnd.back() = *pTmp->End();
1171cdf0e10cSrcweir }
1172cdf0e10cSrcweir else
1173cdf0e10cSrcweir {
1174cdf0e10cSrcweir bOn = bTwo;
117569a74367SOliver-Rainer Wittmann if( aEnd.back() > *pTmp->End() )
117669a74367SOliver-Rainer Wittmann aEnd.push_back( *pTmp->End() );
1177cdf0e10cSrcweir else if( aEnd.size() > 1 )
1178cdf0e10cSrcweir aEnd.pop_back();
1179cdf0e10cSrcweir else
118069a74367SOliver-Rainer Wittmann aEnd.back() = *pTmp->End();
1181cdf0e10cSrcweir }
1182cdf0e10cSrcweir }
1183cdf0e10cSrcweir }
1184cdf0e10cSrcweir if( !bOn && !aEnd.empty() )
1185cdf0e10cSrcweir n2Start = aEnd.back();
1186cdf0e10cSrcweir
1187cdf0e10cSrcweir if( !aEnd.empty() )
1188cdf0e10cSrcweir aEnd.clear();
1189cdf0e10cSrcweir
1190cdf0e10cSrcweir bOn = sal_True;
1191cdf0e10cSrcweir if( nRotate < nCount )
1192cdf0e10cSrcweir {
1193cdf0e10cSrcweir pRet->pItem = NULL;
1194cdf0e10cSrcweir pRet->pAttr = (*pHints)[nRotate];
119569a74367SOliver-Rainer Wittmann aEnd.push_front( *pRet->pAttr->End() );
1196cdf0e10cSrcweir if( pRotItem )
1197cdf0e10cSrcweir {
1198cdf0e10cSrcweir aEnd.front() = GetTxt().Len();
1199cdf0e10cSrcweir bOn = ((SvxCharRotateItem*)pRotItem)->GetValue() ==
1200cdf0e10cSrcweir pRotate->GetValue();
1201cdf0e10cSrcweir }
1202cdf0e10cSrcweir }
1203cdf0e10cSrcweir else
1204cdf0e10cSrcweir {
1205cdf0e10cSrcweir pRet->pItem = pRotItem;
1206cdf0e10cSrcweir pRet->pAttr = NULL;
1207cdf0e10cSrcweir aEnd.push_front( GetTxt().Len() );
1208cdf0e10cSrcweir }
1209cdf0e10cSrcweir i = 0;
1210cdf0e10cSrcweir while( i < nCount )
1211cdf0e10cSrcweir {
1212cdf0e10cSrcweir const SwTxtAttr *pTmp = (*pHints)[i++];
1213cdf0e10cSrcweir if( *pTmp->GetAnyEnd() <= rPos )
1214cdf0e10cSrcweir continue;
1215cdf0e10cSrcweir if( rPos < *pTmp->GetStart() )
1216cdf0e10cSrcweir {
1217cdf0e10cSrcweir if( !bOn || aEnd.back() < *pTmp->GetStart() )
1218cdf0e10cSrcweir break;
1219cdf0e10cSrcweir rPos = *pTmp->GetStart();
1220cdf0e10cSrcweir while( !aEnd.empty() && aEnd.back() <= rPos )
1221cdf0e10cSrcweir {
1222cdf0e10cSrcweir bOn = !bOn;
1223cdf0e10cSrcweir aEnd.pop_back();
1224cdf0e10cSrcweir }
1225cdf0e10cSrcweir if( aEnd.empty() )
1226cdf0e10cSrcweir {
1227cdf0e10cSrcweir aEnd.push_front( rPos );
1228cdf0e10cSrcweir bOn = sal_True;
1229cdf0e10cSrcweir }
1230cdf0e10cSrcweir }
1231cdf0e10cSrcweir if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
1232cdf0e10cSrcweir {
1233cdf0e10cSrcweir bOn = sal_False;
1234cdf0e10cSrcweir break;
1235cdf0e10cSrcweir }
1236cdf0e10cSrcweir if( lcl_HasRotation( *pTmp, pRotate, bTwo ) )
1237cdf0e10cSrcweir {
1238cdf0e10cSrcweir if( bTwo == bOn )
1239cdf0e10cSrcweir {
124069a74367SOliver-Rainer Wittmann if( aEnd.back() < *pTmp->End() )
124169a74367SOliver-Rainer Wittmann aEnd.back() = *pTmp->End();
1242cdf0e10cSrcweir }
1243cdf0e10cSrcweir else
1244cdf0e10cSrcweir {
1245cdf0e10cSrcweir bOn = bTwo;
124669a74367SOliver-Rainer Wittmann if( aEnd.back() > *pTmp->End() )
124769a74367SOliver-Rainer Wittmann aEnd.push_back( *pTmp->End() );
1248cdf0e10cSrcweir else if( aEnd.size() > 1 )
1249cdf0e10cSrcweir aEnd.pop_back();
1250cdf0e10cSrcweir else
125169a74367SOliver-Rainer Wittmann aEnd.back() = *pTmp->End();
1252cdf0e10cSrcweir }
1253cdf0e10cSrcweir }
1254cdf0e10cSrcweir }
1255cdf0e10cSrcweir if( bOn && !aEnd.empty() )
1256cdf0e10cSrcweir rPos = aEnd.back();
1257cdf0e10cSrcweir if( rPos > n2Start )
1258cdf0e10cSrcweir rPos = n2Start;
1259cdf0e10cSrcweir return pRet;
1260cdf0e10cSrcweir }
1261cdf0e10cSrcweir return NULL;
1262cdf0e10cSrcweir }
1263cdf0e10cSrcweir
1264cdf0e10cSrcweir /*-----------------01.11.00 14:52-------------------
1265cdf0e10cSrcweir * SwSpaceManipulator
1266cdf0e10cSrcweir * is a little helper class to manage the spaceadd-arrays of the text adjustment
1267cdf0e10cSrcweir * during a PaintMultiPortion.
1268cdf0e10cSrcweir * The constructor prepares the array for the first line of multiportion,
1269cdf0e10cSrcweir * the SecondLine-function restores the values for the first line and prepares
1270cdf0e10cSrcweir * the second line.
1271cdf0e10cSrcweir * The destructor restores the values of the last manipulation.
1272cdf0e10cSrcweir * --------------------------------------------------*/
1273cdf0e10cSrcweir
1274cdf0e10cSrcweir class SwSpaceManipulator
1275cdf0e10cSrcweir {
1276cdf0e10cSrcweir SwTxtPaintInfo& rInfo;
1277cdf0e10cSrcweir SwMultiPortion& rMulti;
1278cdf0e10cSrcweir std::vector<long>* pOldSpaceAdd;
1279cdf0e10cSrcweir MSHORT nOldSpIdx;
1280cdf0e10cSrcweir long nSpaceAdd;
1281cdf0e10cSrcweir sal_Bool bSpaceChg : 1;
1282cdf0e10cSrcweir sal_uInt8 nOldDir : 2;
1283cdf0e10cSrcweir public:
1284cdf0e10cSrcweir SwSpaceManipulator( SwTxtPaintInfo& rInf, SwMultiPortion& rMult );
1285cdf0e10cSrcweir ~SwSpaceManipulator();
1286cdf0e10cSrcweir void SecondLine();
GetSpaceAdd() const1287cdf0e10cSrcweir inline long GetSpaceAdd() const { return nSpaceAdd; }
1288cdf0e10cSrcweir };
1289cdf0e10cSrcweir
SwSpaceManipulator(SwTxtPaintInfo & rInf,SwMultiPortion & rMult)1290cdf0e10cSrcweir SwSpaceManipulator::SwSpaceManipulator( SwTxtPaintInfo& rInf,
1291cdf0e10cSrcweir SwMultiPortion& rMult ) :
1292cdf0e10cSrcweir rInfo( rInf ), rMulti( rMult )
1293cdf0e10cSrcweir {
1294cdf0e10cSrcweir pOldSpaceAdd = rInfo.GetpSpaceAdd();
1295cdf0e10cSrcweir nOldSpIdx = rInfo.GetSpaceIdx();
1296cdf0e10cSrcweir nOldDir = rInfo.GetDirection();
1297cdf0e10cSrcweir rInfo.SetDirection( rMulti.GetDirection() );
1298cdf0e10cSrcweir bSpaceChg = sal_False;
1299cdf0e10cSrcweir
1300cdf0e10cSrcweir if( rMulti.IsDouble() )
1301cdf0e10cSrcweir {
1302cdf0e10cSrcweir nSpaceAdd = ( pOldSpaceAdd && !rMulti.HasTabulator() ) ?
1303cdf0e10cSrcweir rInfo.GetSpaceAdd() : 0;
1304cdf0e10cSrcweir if( rMulti.GetRoot().IsSpaceAdd() )
1305cdf0e10cSrcweir {
1306cdf0e10cSrcweir rInfo.SetpSpaceAdd( rMulti.GetRoot().GetpLLSpaceAdd() );
1307cdf0e10cSrcweir rInfo.ResetSpaceIdx();
1308cdf0e10cSrcweir bSpaceChg = rMulti.ChgSpaceAdd( &rMulti.GetRoot(), nSpaceAdd );
1309cdf0e10cSrcweir }
1310cdf0e10cSrcweir else if( rMulti.HasTabulator() )
1311cdf0e10cSrcweir rInfo.SetpSpaceAdd( NULL );
1312cdf0e10cSrcweir }
1313cdf0e10cSrcweir else if ( ! rMulti.IsBidi() )
1314cdf0e10cSrcweir {
1315cdf0e10cSrcweir rInfo.SetpSpaceAdd( rMulti.GetRoot().GetpLLSpaceAdd() );
1316cdf0e10cSrcweir rInfo.ResetSpaceIdx();
1317cdf0e10cSrcweir }
1318cdf0e10cSrcweir }
1319cdf0e10cSrcweir
SecondLine()1320cdf0e10cSrcweir void SwSpaceManipulator::SecondLine()
1321cdf0e10cSrcweir {
1322cdf0e10cSrcweir if( bSpaceChg )
1323cdf0e10cSrcweir {
1324cdf0e10cSrcweir rInfo.RemoveFirstSpaceAdd();
1325cdf0e10cSrcweir bSpaceChg = sal_False;
1326cdf0e10cSrcweir }
1327cdf0e10cSrcweir SwLineLayout *pLay = rMulti.GetRoot().GetNext();
1328cdf0e10cSrcweir if( pLay->IsSpaceAdd() )
1329cdf0e10cSrcweir {
1330cdf0e10cSrcweir rInfo.SetpSpaceAdd( pLay->GetpLLSpaceAdd() );
1331cdf0e10cSrcweir rInfo.ResetSpaceIdx();
1332cdf0e10cSrcweir bSpaceChg = rMulti.ChgSpaceAdd( pLay, nSpaceAdd );
1333cdf0e10cSrcweir }
1334cdf0e10cSrcweir else
1335cdf0e10cSrcweir {
1336cdf0e10cSrcweir rInfo.SetpSpaceAdd( (!rMulti.IsDouble() || rMulti.HasTabulator() ) ?
1337cdf0e10cSrcweir 0 : pOldSpaceAdd );
1338cdf0e10cSrcweir rInfo.SetSpaceIdx( nOldSpIdx);
1339cdf0e10cSrcweir }
1340cdf0e10cSrcweir }
1341cdf0e10cSrcweir
~SwSpaceManipulator()1342cdf0e10cSrcweir SwSpaceManipulator::~SwSpaceManipulator()
1343cdf0e10cSrcweir {
1344cdf0e10cSrcweir if( bSpaceChg )
1345cdf0e10cSrcweir {
1346cdf0e10cSrcweir rInfo.RemoveFirstSpaceAdd();
1347cdf0e10cSrcweir bSpaceChg = sal_False;
1348cdf0e10cSrcweir }
1349cdf0e10cSrcweir rInfo.SetpSpaceAdd( pOldSpaceAdd );
1350cdf0e10cSrcweir rInfo.SetSpaceIdx( nOldSpIdx);
1351cdf0e10cSrcweir rInfo.SetDirection( nOldDir );
1352cdf0e10cSrcweir }
1353cdf0e10cSrcweir
1354cdf0e10cSrcweir /*-----------------13.10.00 16:24-------------------
1355cdf0e10cSrcweir * SwTxtPainter::PaintMultiPortion manages the paint for a SwMultiPortion.
1356cdf0e10cSrcweir * External, for the calling function, it seems to be a normal Paint-function,
1357cdf0e10cSrcweir * internal it is like a SwTxtFrm::Paint with multiple DrawTextLines
1358cdf0e10cSrcweir * --------------------------------------------------*/
1359cdf0e10cSrcweir
PaintMultiPortion(const SwRect & rPaint,SwMultiPortion & rMulti,const SwMultiPortion * pEnvPor)1360cdf0e10cSrcweir void SwTxtPainter::PaintMultiPortion( const SwRect &rPaint,
1361cdf0e10cSrcweir SwMultiPortion& rMulti, const SwMultiPortion* pEnvPor )
1362cdf0e10cSrcweir {
1363cdf0e10cSrcweir GETGRID( pFrm->FindPageFrm() )
1364cdf0e10cSrcweir const sal_Bool bHasGrid = pGrid && GetInfo().SnapToGrid();
1365cdf0e10cSrcweir sal_uInt16 nGridWidth = 0;
1366cdf0e10cSrcweir sal_uInt16 nRubyHeight = 0;
1367cdf0e10cSrcweir sal_Bool bRubyTop = sal_False;
1368cdf0e10cSrcweir
1369cdf0e10cSrcweir if ( bHasGrid )
1370cdf0e10cSrcweir {
1371cdf0e10cSrcweir nGridWidth = pGrid->GetBaseHeight();
1372cdf0e10cSrcweir nRubyHeight = pGrid->GetRubyHeight();
1373cdf0e10cSrcweir bRubyTop = ! pGrid->GetRubyTextBelow();
1374cdf0e10cSrcweir }
1375cdf0e10cSrcweir
1376cdf0e10cSrcweir // do not allow grid mode for first line in ruby portion
1377cdf0e10cSrcweir const sal_Bool bRubyInGrid = bHasGrid && rMulti.IsRuby();
1378cdf0e10cSrcweir
1379cdf0e10cSrcweir const sal_uInt16 nOldHeight = rMulti.Height();
1380cdf0e10cSrcweir const sal_Bool bOldGridModeAllowed = GetInfo().SnapToGrid();
1381cdf0e10cSrcweir
1382cdf0e10cSrcweir if ( bRubyInGrid )
1383cdf0e10cSrcweir {
1384cdf0e10cSrcweir GetInfo().SetSnapToGrid( ! bRubyTop );
1385cdf0e10cSrcweir rMulti.Height( pCurr->Height() );
1386cdf0e10cSrcweir }
1387cdf0e10cSrcweir
1388cdf0e10cSrcweir SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
1389cdf0e10cSrcweir sal_uInt8 nEnvDir = 0;
1390cdf0e10cSrcweir sal_uInt8 nThisDir = 0;
1391cdf0e10cSrcweir sal_uInt8 nFrmDir = 0;
1392cdf0e10cSrcweir if ( rMulti.IsBidi() )
1393cdf0e10cSrcweir {
1394cdf0e10cSrcweir // these values are needed for the calculation of the x coordinate
1395cdf0e10cSrcweir // and the layout mode
1396cdf0e10cSrcweir ASSERT( ! pEnvPor || pEnvPor->IsBidi(),
1397cdf0e10cSrcweir "Oh no, I expected a BidiPortion" )
1398cdf0e10cSrcweir nFrmDir = GetInfo().GetTxtFrm()->IsRightToLeft() ? 1 : 0;
1399cdf0e10cSrcweir nEnvDir = pEnvPor ? ((SwBidiPortion*)pEnvPor)->GetLevel() % 2 : nFrmDir;
1400cdf0e10cSrcweir nThisDir = ((SwBidiPortion&)rMulti).GetLevel() % 2;
1401cdf0e10cSrcweir }
1402cdf0e10cSrcweir
1403cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
1404cdf0e10cSrcweir // only paint first level bidi portions
1405cdf0e10cSrcweir if( rMulti.Width() > 1 && ! pEnvPor )
1406cdf0e10cSrcweir GetInfo().DrawViewOpt( rMulti, POR_FLD );
1407cdf0e10cSrcweir #endif
1408cdf0e10cSrcweir
1409cdf0e10cSrcweir if ( bRubyInGrid )
1410cdf0e10cSrcweir rMulti.Height( nOldHeight );
1411cdf0e10cSrcweir
1412cdf0e10cSrcweir // do we have to repaint a post it portion?
1413cdf0e10cSrcweir if( GetInfo().OnWin() && rMulti.GetPortion() &&
1414cdf0e10cSrcweir ! rMulti.GetPortion()->Width() )
1415cdf0e10cSrcweir rMulti.GetPortion()->PrePaint( GetInfo(), &rMulti );
1416cdf0e10cSrcweir
1417cdf0e10cSrcweir // old values must be saved and restored at the end
1418cdf0e10cSrcweir xub_StrLen nOldLen = GetInfo().GetLen();
1419cdf0e10cSrcweir KSHORT nOldX = KSHORT(GetInfo().X());
1420cdf0e10cSrcweir long nOldY = GetInfo().Y();
1421cdf0e10cSrcweir xub_StrLen nOldIdx = GetInfo().GetIdx();
1422cdf0e10cSrcweir
1423cdf0e10cSrcweir SwSpaceManipulator aManip( GetInfo(), rMulti );
1424cdf0e10cSrcweir
1425cdf0e10cSrcweir SwFontSave *pFontSave;
1426cdf0e10cSrcweir SwFont* pTmpFnt;
1427cdf0e10cSrcweir
1428cdf0e10cSrcweir if( rMulti.IsDouble() )
1429cdf0e10cSrcweir {
1430cdf0e10cSrcweir pTmpFnt = new SwFont( *GetInfo().GetFont() );
1431cdf0e10cSrcweir if( rMulti.IsDouble() )
1432cdf0e10cSrcweir {
1433cdf0e10cSrcweir SetPropFont( 50 );
1434cdf0e10cSrcweir pTmpFnt->SetProportion( GetPropFont() );
1435cdf0e10cSrcweir }
1436cdf0e10cSrcweir pFontSave = new SwFontSave( GetInfo(), pTmpFnt, this );
1437cdf0e10cSrcweir }
1438cdf0e10cSrcweir else
1439cdf0e10cSrcweir {
1440cdf0e10cSrcweir pFontSave = NULL;
1441cdf0e10cSrcweir pTmpFnt = NULL;
1442cdf0e10cSrcweir }
1443cdf0e10cSrcweir
1444cdf0e10cSrcweir if( rMulti.HasBrackets() )
1445cdf0e10cSrcweir {
1446cdf0e10cSrcweir xub_StrLen nTmpOldIdx = GetInfo().GetIdx();
1447cdf0e10cSrcweir GetInfo().SetIdx(((SwDoubleLinePortion&)rMulti).GetBrackets()->nStart);
1448cdf0e10cSrcweir SeekAndChg( GetInfo() );
1449cdf0e10cSrcweir ((SwDoubleLinePortion&)rMulti).PaintBracket( GetInfo(), 0, sal_True );
1450cdf0e10cSrcweir GetInfo().SetIdx( nTmpOldIdx );
1451cdf0e10cSrcweir }
1452cdf0e10cSrcweir
1453cdf0e10cSrcweir KSHORT nTmpX = KSHORT(GetInfo().X());
1454cdf0e10cSrcweir
1455cdf0e10cSrcweir SwLineLayout* pLay = &rMulti.GetRoot();// the first line of the multiportion
1456cdf0e10cSrcweir SwLinePortion* pPor = pLay->GetFirstPortion();//first portion of these line
1457cdf0e10cSrcweir SwTwips nOfst = 0;
1458cdf0e10cSrcweir
1459cdf0e10cSrcweir // GetInfo().Y() is the baseline from the surrounding line. We must switch
1460cdf0e10cSrcweir // this temporary to the baseline of the inner lines of the multiportion.
1461cdf0e10cSrcweir if( rMulti.HasRotation() )
1462cdf0e10cSrcweir {
1463cdf0e10cSrcweir if( rMulti.IsRevers() )
1464cdf0e10cSrcweir {
1465cdf0e10cSrcweir GetInfo().Y( nOldY - rMulti.GetAscent() );
1466cdf0e10cSrcweir nOfst = nTmpX + rMulti.Width();
1467cdf0e10cSrcweir }
1468cdf0e10cSrcweir else
1469cdf0e10cSrcweir {
1470cdf0e10cSrcweir GetInfo().Y( nOldY - rMulti.GetAscent() + rMulti.Height() );
1471cdf0e10cSrcweir nOfst = nTmpX;
1472cdf0e10cSrcweir }
1473cdf0e10cSrcweir }
1474cdf0e10cSrcweir else if ( rMulti.IsBidi() )
1475cdf0e10cSrcweir {
1476cdf0e10cSrcweir // does the current bidi portion has the same direction
1477cdf0e10cSrcweir // as its environment?
1478cdf0e10cSrcweir if ( nEnvDir != nThisDir )
1479cdf0e10cSrcweir {
1480cdf0e10cSrcweir // different directions, we have to adjust the x coordinate
1481cdf0e10cSrcweir SwTwips nMultiWidth = rMulti.Width() +
1482cdf0e10cSrcweir rMulti.CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
1483cdf0e10cSrcweir
1484cdf0e10cSrcweir if ( nFrmDir == nThisDir )
1485cdf0e10cSrcweir GetInfo().X( GetInfo().X() - nMultiWidth );
1486cdf0e10cSrcweir else
1487cdf0e10cSrcweir GetInfo().X( GetInfo().X() + nMultiWidth );
1488cdf0e10cSrcweir }
1489cdf0e10cSrcweir
1490cdf0e10cSrcweir nOfst = nOldY - rMulti.GetAscent();
1491cdf0e10cSrcweir
1492cdf0e10cSrcweir // set layout mode
1493cdf0e10cSrcweir aLayoutModeModifier.Modify( nThisDir );
1494cdf0e10cSrcweir }
1495cdf0e10cSrcweir else
1496cdf0e10cSrcweir nOfst = nOldY - rMulti.GetAscent();
1497cdf0e10cSrcweir
1498cdf0e10cSrcweir sal_Bool bRest = pLay->IsRest();
1499cdf0e10cSrcweir sal_Bool bFirst = sal_True;
1500cdf0e10cSrcweir
1501cdf0e10cSrcweir ASSERT( 0 == GetInfo().GetUnderFnt() || rMulti.IsBidi(),
1502cdf0e10cSrcweir " Only BiDi portions are allowed to use the common underlining font" )
1503cdf0e10cSrcweir
1504cdf0e10cSrcweir do
1505cdf0e10cSrcweir {
1506cdf0e10cSrcweir if ( bHasGrid )
1507cdf0e10cSrcweir {
1508cdf0e10cSrcweir if( rMulti.HasRotation() )
1509cdf0e10cSrcweir {
1510cdf0e10cSrcweir const sal_uInt16 nAdjustment = ( pLay->Height() - pPor->Height() ) / 2 +
1511cdf0e10cSrcweir pPor->GetAscent();
1512cdf0e10cSrcweir if( rMulti.IsRevers() )
1513cdf0e10cSrcweir GetInfo().X( nOfst - nAdjustment );
1514cdf0e10cSrcweir else
1515cdf0e10cSrcweir GetInfo().X( nOfst + nAdjustment );
1516cdf0e10cSrcweir }
1517cdf0e10cSrcweir else
1518cdf0e10cSrcweir {
1519cdf0e10cSrcweir // special treatment for ruby portions in grid mode
1520cdf0e10cSrcweir SwTwips nAdjustment = 0;
1521cdf0e10cSrcweir if ( rMulti.IsRuby() )
1522cdf0e10cSrcweir {
1523cdf0e10cSrcweir if ( bRubyTop != ( pLay == &rMulti.GetRoot() ) )
1524cdf0e10cSrcweir // adjust base text
1525cdf0e10cSrcweir nAdjustment = ( pCurr->Height() - nRubyHeight - pPor->Height() ) / 2;
1526cdf0e10cSrcweir else if ( bRubyTop )
1527cdf0e10cSrcweir // adjust upper ruby text
1528cdf0e10cSrcweir nAdjustment = nRubyHeight - pPor->Height();
1529cdf0e10cSrcweir // else adjust lower ruby text
1530cdf0e10cSrcweir }
1531cdf0e10cSrcweir
1532cdf0e10cSrcweir GetInfo().Y( nOfst + nAdjustment + pPor->GetAscent() );
1533cdf0e10cSrcweir }
1534cdf0e10cSrcweir }
1535cdf0e10cSrcweir else if( rMulti.HasRotation() )
1536cdf0e10cSrcweir {
1537cdf0e10cSrcweir if( rMulti.IsRevers() )
1538cdf0e10cSrcweir GetInfo().X( nOfst - AdjustBaseLine( *pLay, pPor, 0, 0, sal_True ) );
1539cdf0e10cSrcweir else
1540cdf0e10cSrcweir GetInfo().X( nOfst + AdjustBaseLine( *pLay, pPor ) );
1541cdf0e10cSrcweir }
1542cdf0e10cSrcweir else
1543cdf0e10cSrcweir GetInfo().Y( nOfst + AdjustBaseLine( *pLay, pPor ) );
1544cdf0e10cSrcweir
1545cdf0e10cSrcweir sal_Bool bSeeked = sal_True;
1546cdf0e10cSrcweir GetInfo().SetLen( pPor->GetLen() );
1547cdf0e10cSrcweir
1548cdf0e10cSrcweir if( bRest && pPor->InFldGrp() && !pPor->GetLen() )
1549cdf0e10cSrcweir {
1550cdf0e10cSrcweir if( ((SwFldPortion*)pPor)->HasFont() )
1551cdf0e10cSrcweir bSeeked = sal_False;
1552cdf0e10cSrcweir else
1553cdf0e10cSrcweir SeekAndChgBefore( GetInfo() );
1554cdf0e10cSrcweir }
1555cdf0e10cSrcweir else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
1556cdf0e10cSrcweir SeekAndChg( GetInfo() );
1557cdf0e10cSrcweir else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
1558cdf0e10cSrcweir {
1559cdf0e10cSrcweir if( GetRedln() )
1560cdf0e10cSrcweir SeekAndChg( GetInfo() );
1561cdf0e10cSrcweir else
1562cdf0e10cSrcweir SeekAndChgBefore( GetInfo() );
1563cdf0e10cSrcweir }
1564cdf0e10cSrcweir else
1565cdf0e10cSrcweir bSeeked = sal_False;
1566cdf0e10cSrcweir
1567cdf0e10cSrcweir SwLinePortion *pNext = pPor->GetPortion();
1568cdf0e10cSrcweir if(GetInfo().OnWin() && pNext && !pNext->Width() )
1569cdf0e10cSrcweir {
1570cdf0e10cSrcweir if ( !bSeeked )
1571cdf0e10cSrcweir SeekAndChg( GetInfo() );
1572cdf0e10cSrcweir pNext->PrePaint( GetInfo(), pPor );
1573cdf0e10cSrcweir }
1574cdf0e10cSrcweir
1575cdf0e10cSrcweir CheckSpecialUnderline( pPor );
1576cdf0e10cSrcweir SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
1577cdf0e10cSrcweir if ( pUnderLineFnt )
1578cdf0e10cSrcweir {
1579cdf0e10cSrcweir if ( rMulti.IsDouble() )
1580cdf0e10cSrcweir pUnderLineFnt->GetFont().SetProportion( 50 );
1581cdf0e10cSrcweir pUnderLineFnt->SetPos( GetInfo().GetPos() );
1582cdf0e10cSrcweir }
1583cdf0e10cSrcweir
1584cdf0e10cSrcweir if ( rMulti.IsBidi() )
1585cdf0e10cSrcweir {
1586cdf0e10cSrcweir // we do not allow any rotation inside a bidi portion
1587cdf0e10cSrcweir SwFont* pTmpFont = GetInfo().GetFont();
1588cdf0e10cSrcweir pTmpFont->SetVertical( 0, GetInfo().GetTxtFrm()->IsVertical() );
1589cdf0e10cSrcweir }
1590cdf0e10cSrcweir
1591cdf0e10cSrcweir if( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsBidi() )
1592cdf0e10cSrcweir {
1593cdf0e10cSrcweir // but we do allow nested bidi portions
1594cdf0e10cSrcweir ASSERT( rMulti.IsBidi(), "Only nesting of bidi portions is allowed" )
1595cdf0e10cSrcweir PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor, &rMulti );
1596cdf0e10cSrcweir }
1597cdf0e10cSrcweir else
1598cdf0e10cSrcweir pPor->Paint( GetInfo() );
1599cdf0e10cSrcweir
1600cdf0e10cSrcweir if( GetFnt()->IsURL() && pPor->InTxtGrp() )
1601cdf0e10cSrcweir GetInfo().NotifyURL( *pPor );
1602cdf0e10cSrcweir
1603cdf0e10cSrcweir bFirst &= !pPor->GetLen();
1604cdf0e10cSrcweir if( pNext || !pPor->IsMarginPortion() )
1605cdf0e10cSrcweir pPor->Move( GetInfo() );
1606cdf0e10cSrcweir
1607cdf0e10cSrcweir pPor = pNext;
1608cdf0e10cSrcweir
1609cdf0e10cSrcweir // If there's no portion left, we go to the next line
1610cdf0e10cSrcweir if( !pPor && pLay->GetNext() )
1611cdf0e10cSrcweir {
1612cdf0e10cSrcweir pLay = pLay->GetNext();
1613cdf0e10cSrcweir pPor = pLay->GetFirstPortion();
1614cdf0e10cSrcweir bRest = pLay->IsRest();
1615cdf0e10cSrcweir aManip.SecondLine();
1616cdf0e10cSrcweir
1617cdf0e10cSrcweir // delete underline font
1618cdf0e10cSrcweir delete GetInfo().GetUnderFnt();
1619cdf0e10cSrcweir GetInfo().SetUnderFnt( 0 );
1620cdf0e10cSrcweir
1621cdf0e10cSrcweir if( rMulti.HasRotation() )
1622cdf0e10cSrcweir {
1623cdf0e10cSrcweir if( rMulti.IsRevers() )
1624cdf0e10cSrcweir {
1625cdf0e10cSrcweir nOfst += pLay->Height();
1626cdf0e10cSrcweir GetInfo().Y( nOldY - rMulti.GetAscent() );
1627cdf0e10cSrcweir }
1628cdf0e10cSrcweir else
1629cdf0e10cSrcweir {
1630cdf0e10cSrcweir nOfst -= pLay->Height();
1631cdf0e10cSrcweir GetInfo().Y( nOldY - rMulti.GetAscent() + rMulti.Height() );
1632cdf0e10cSrcweir }
1633cdf0e10cSrcweir }
1634cdf0e10cSrcweir else if ( bHasGrid && rMulti.IsRuby() )
1635cdf0e10cSrcweir {
1636cdf0e10cSrcweir GetInfo().X( nTmpX );
1637cdf0e10cSrcweir if ( bRubyTop )
1638cdf0e10cSrcweir {
1639cdf0e10cSrcweir nOfst += nRubyHeight;
1640cdf0e10cSrcweir GetInfo().SetSnapToGrid( sal_True );
1641cdf0e10cSrcweir }
1642cdf0e10cSrcweir else
1643cdf0e10cSrcweir {
1644cdf0e10cSrcweir nOfst += pCurr->Height() - nRubyHeight;
1645cdf0e10cSrcweir GetInfo().SetSnapToGrid( sal_False );
1646cdf0e10cSrcweir }
1647cdf0e10cSrcweir } else
1648cdf0e10cSrcweir {
1649cdf0e10cSrcweir GetInfo().X( nTmpX );
1650cdf0e10cSrcweir // We switch to the baseline of the next inner line
1651cdf0e10cSrcweir nOfst += rMulti.GetRoot().Height();
1652cdf0e10cSrcweir }
1653cdf0e10cSrcweir }
1654cdf0e10cSrcweir } while( pPor );
1655cdf0e10cSrcweir
1656cdf0e10cSrcweir if ( bRubyInGrid )
1657cdf0e10cSrcweir GetInfo().SetSnapToGrid( bOldGridModeAllowed );
1658cdf0e10cSrcweir
1659cdf0e10cSrcweir // delete underline font
1660cdf0e10cSrcweir if ( ! rMulti.IsBidi() )
1661cdf0e10cSrcweir {
1662cdf0e10cSrcweir delete GetInfo().GetUnderFnt();
1663cdf0e10cSrcweir GetInfo().SetUnderFnt( 0 );
1664cdf0e10cSrcweir }
1665cdf0e10cSrcweir
1666cdf0e10cSrcweir GetInfo().SetIdx( nOldIdx );
1667cdf0e10cSrcweir GetInfo().Y( nOldY );
1668cdf0e10cSrcweir
1669cdf0e10cSrcweir if( rMulti.HasBrackets() )
1670cdf0e10cSrcweir {
1671cdf0e10cSrcweir xub_StrLen nTmpOldIdx = GetInfo().GetIdx();
1672cdf0e10cSrcweir GetInfo().SetIdx(((SwDoubleLinePortion&)rMulti).GetBrackets()->nStart);
1673cdf0e10cSrcweir SeekAndChg( GetInfo() );
1674cdf0e10cSrcweir GetInfo().X( nOldX );
1675cdf0e10cSrcweir ((SwDoubleLinePortion&)rMulti).PaintBracket( GetInfo(),
1676cdf0e10cSrcweir aManip.GetSpaceAdd(), sal_False );
1677cdf0e10cSrcweir GetInfo().SetIdx( nTmpOldIdx );
1678cdf0e10cSrcweir }
1679cdf0e10cSrcweir // Restore the saved values
1680cdf0e10cSrcweir GetInfo().X( nOldX );
1681cdf0e10cSrcweir GetInfo().SetLen( nOldLen );
1682cdf0e10cSrcweir delete pFontSave;
1683cdf0e10cSrcweir delete pTmpFnt;
1684cdf0e10cSrcweir SetPropFont( 0 );
1685cdf0e10cSrcweir }
1686cdf0e10cSrcweir
lcl_ExtractFieldFollow(SwLineLayout * pLine,SwLinePortion * & rpFld)1687cdf0e10cSrcweir sal_Bool lcl_ExtractFieldFollow( SwLineLayout* pLine, SwLinePortion* &rpFld )
1688cdf0e10cSrcweir {
1689cdf0e10cSrcweir SwLinePortion* pLast = pLine;
1690cdf0e10cSrcweir rpFld = pLine->GetPortion();
1691cdf0e10cSrcweir while( rpFld && !rpFld->InFldGrp() )
1692cdf0e10cSrcweir {
1693cdf0e10cSrcweir pLast = rpFld;
1694cdf0e10cSrcweir rpFld = rpFld->GetPortion();
1695cdf0e10cSrcweir }
1696cdf0e10cSrcweir sal_Bool bRet = rpFld != 0;
1697cdf0e10cSrcweir if( bRet )
1698cdf0e10cSrcweir {
1699cdf0e10cSrcweir if( ((SwFldPortion*)rpFld)->IsFollow() )
1700cdf0e10cSrcweir {
1701cdf0e10cSrcweir rpFld->Truncate();
1702cdf0e10cSrcweir pLast->SetPortion( NULL );
1703cdf0e10cSrcweir }
1704cdf0e10cSrcweir else
1705cdf0e10cSrcweir rpFld = NULL;
1706cdf0e10cSrcweir }
1707cdf0e10cSrcweir pLine->Truncate();
1708cdf0e10cSrcweir return bRet;
1709cdf0e10cSrcweir }
1710cdf0e10cSrcweir
1711cdf0e10cSrcweir /*----------------------------------------------------
1712cdf0e10cSrcweir * lcl_TruncateMultiPortion
1713cdf0e10cSrcweir * If a multi portion completely has to go to the
1714cdf0e10cSrcweir * next line, this function is called to trunctate
1715cdf0e10cSrcweir * the rest of the remaining multi portion
1716cdf0e10cSrcweir * --------------------------------------------------*/
1717cdf0e10cSrcweir
lcl_TruncateMultiPortion(SwMultiPortion & rMulti,SwTxtFormatInfo & rInf,xub_StrLen nStartIdx)1718cdf0e10cSrcweir void lcl_TruncateMultiPortion( SwMultiPortion& rMulti, SwTxtFormatInfo& rInf,
1719cdf0e10cSrcweir xub_StrLen nStartIdx )
1720cdf0e10cSrcweir {
1721cdf0e10cSrcweir rMulti.GetRoot().Truncate();
1722cdf0e10cSrcweir rMulti.GetRoot().SetLen(0);
1723cdf0e10cSrcweir rMulti.GetRoot().Width(0);
1724cdf0e10cSrcweir // rMulti.CalcSize( *this, aInf );
1725cdf0e10cSrcweir if ( rMulti.GetRoot().GetNext() )
1726cdf0e10cSrcweir {
1727cdf0e10cSrcweir rMulti.GetRoot().GetNext()->Truncate();
1728cdf0e10cSrcweir rMulti.GetRoot().GetNext()->SetLen( 0 );
1729cdf0e10cSrcweir rMulti.GetRoot().GetNext()->Width( 0 );
1730cdf0e10cSrcweir }
1731cdf0e10cSrcweir rMulti.Width( 0 );
1732cdf0e10cSrcweir rMulti.SetLen(0);
1733cdf0e10cSrcweir rInf.SetIdx( nStartIdx );
1734cdf0e10cSrcweir }
1735cdf0e10cSrcweir
1736cdf0e10cSrcweir /*-----------------------------------------------------------------------------
1737cdf0e10cSrcweir * SwTxtFormatter::BuildMultiPortion
1738cdf0e10cSrcweir * manages the formatting of a SwMultiPortion. External, for the calling
1739cdf0e10cSrcweir * function, it seems to be a normal Format-function, internal it is like a
1740cdf0e10cSrcweir * SwTxtFrm::_Format with multiple BuildPortions
1741cdf0e10cSrcweir *---------------------------------------------------------------------------*/
1742cdf0e10cSrcweir
BuildMultiPortion(SwTxtFormatInfo & rInf,SwMultiPortion & rMulti)1743cdf0e10cSrcweir sal_Bool SwTxtFormatter::BuildMultiPortion( SwTxtFormatInfo &rInf,
1744cdf0e10cSrcweir SwMultiPortion& rMulti )
1745cdf0e10cSrcweir {
1746cdf0e10cSrcweir SwTwips nMaxWidth = rInf.Width();
1747cdf0e10cSrcweir KSHORT nOldX = 0;
1748cdf0e10cSrcweir
1749cdf0e10cSrcweir if( rMulti.HasBrackets() )
1750cdf0e10cSrcweir {
1751cdf0e10cSrcweir xub_StrLen nOldIdx = rInf.GetIdx();
1752cdf0e10cSrcweir rInf.SetIdx( ((SwDoubleLinePortion&)rMulti).GetBrackets()->nStart );
1753cdf0e10cSrcweir SeekAndChg( rInf );
1754cdf0e10cSrcweir nOldX = KSHORT(GetInfo().X());
1755cdf0e10cSrcweir ((SwDoubleLinePortion&)rMulti).FormatBrackets( rInf, nMaxWidth );
1756cdf0e10cSrcweir rInf.SetIdx( nOldIdx );
1757cdf0e10cSrcweir }
1758cdf0e10cSrcweir
1759cdf0e10cSrcweir SeekAndChg( rInf );
1760cdf0e10cSrcweir SwFontSave *pFontSave;
1761cdf0e10cSrcweir if( rMulti.IsDouble() )
1762cdf0e10cSrcweir {
1763cdf0e10cSrcweir SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
1764cdf0e10cSrcweir if( rMulti.IsDouble() )
1765cdf0e10cSrcweir {
1766cdf0e10cSrcweir SetPropFont( 50 );
1767cdf0e10cSrcweir pTmpFnt->SetProportion( GetPropFont() );
1768cdf0e10cSrcweir }
1769cdf0e10cSrcweir pFontSave = new SwFontSave( rInf, pTmpFnt, this );
1770cdf0e10cSrcweir }
1771cdf0e10cSrcweir else
1772cdf0e10cSrcweir pFontSave = NULL;
1773cdf0e10cSrcweir
1774cdf0e10cSrcweir SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
1775cdf0e10cSrcweir if ( rMulti.IsBidi() )
1776cdf0e10cSrcweir {
1777cdf0e10cSrcweir // set layout mode
1778cdf0e10cSrcweir aLayoutModeModifier.Modify( ! rInf.GetTxtFrm()->IsRightToLeft() );
1779cdf0e10cSrcweir }
1780cdf0e10cSrcweir
1781cdf0e10cSrcweir SwTwips nTmpX = 0;
1782cdf0e10cSrcweir
1783cdf0e10cSrcweir if( rMulti.HasRotation() )
1784cdf0e10cSrcweir {
1785cdf0e10cSrcweir // For nMaxWidth we take the height of the body frame.
1786cdf0e10cSrcweir // #i25067#: If the current frame is inside a table, we restrict
1787cdf0e10cSrcweir // nMaxWidth to the current frame height, unless the frame size
1788cdf0e10cSrcweir // attribute is set to variable size:
1789cdf0e10cSrcweir
1790cdf0e10cSrcweir // We set nTmpX (which is used for portion calculating) to the
1791cdf0e10cSrcweir // current Y value
1792cdf0e10cSrcweir const SwPageFrm* pPage = pFrm->FindPageFrm();
1793cdf0e10cSrcweir ASSERT( pPage, "No page in frame!");
1794cdf0e10cSrcweir const SwLayoutFrm* pUpperFrm = pPage;
1795cdf0e10cSrcweir
1796cdf0e10cSrcweir if ( pFrm->IsInTab() )
1797cdf0e10cSrcweir {
1798cdf0e10cSrcweir pUpperFrm = pFrm->GetUpper();
1799cdf0e10cSrcweir while ( pUpperFrm && !pUpperFrm->IsCellFrm() )
1800cdf0e10cSrcweir pUpperFrm = pUpperFrm->GetUpper();
1801cdf0e10cSrcweir ASSERT( pUpperFrm, "pFrm is in table but does not have an upper cell frame" )
1802cdf0e10cSrcweir const SwTableLine* pLine = ((SwRowFrm*)pUpperFrm->GetUpper())->GetTabLine();
1803cdf0e10cSrcweir const SwFmtFrmSize& rFrmFmtSize = pLine->GetFrmFmt()->GetFrmSize();
1804cdf0e10cSrcweir if ( ATT_VAR_SIZE == rFrmFmtSize.GetHeightSizeType() )
1805cdf0e10cSrcweir pUpperFrm = pPage;
1806cdf0e10cSrcweir }
1807cdf0e10cSrcweir if ( pUpperFrm == pPage && !pFrm->IsInFtn() )
1808cdf0e10cSrcweir pUpperFrm = pPage->FindBodyCont();
1809cdf0e10cSrcweir
1810cdf0e10cSrcweir nMaxWidth = pUpperFrm ?
1811cdf0e10cSrcweir ( rInf.GetTxtFrm()->IsVertical() ?
1812cdf0e10cSrcweir pUpperFrm->Prt().Width() :
1813cdf0e10cSrcweir pUpperFrm->Prt().Height() ) :
1814cdf0e10cSrcweir USHRT_MAX;
1815cdf0e10cSrcweir }
1816cdf0e10cSrcweir else
1817cdf0e10cSrcweir nTmpX = rInf.X();
1818cdf0e10cSrcweir
1819cdf0e10cSrcweir SwMultiPortion* pOldMulti = pMulti;
1820cdf0e10cSrcweir
1821cdf0e10cSrcweir pMulti = &rMulti;
1822cdf0e10cSrcweir SwLineLayout *pOldCurr = pCurr;
1823cdf0e10cSrcweir xub_StrLen nOldStart = GetStart();
1824cdf0e10cSrcweir SwTwips nMinWidth = nTmpX + 1;
1825cdf0e10cSrcweir SwTwips nActWidth = nMaxWidth;
1826cdf0e10cSrcweir const xub_StrLen nStartIdx = rInf.GetIdx();
1827cdf0e10cSrcweir xub_StrLen nMultiLen = rMulti.GetLen();
1828cdf0e10cSrcweir
1829cdf0e10cSrcweir SwLinePortion *pFirstRest;
1830cdf0e10cSrcweir SwLinePortion *pSecondRest;
1831cdf0e10cSrcweir if( rMulti.IsFormatted() )
1832cdf0e10cSrcweir {
1833cdf0e10cSrcweir if( !lcl_ExtractFieldFollow( &rMulti.GetRoot(), pFirstRest )
1834cdf0e10cSrcweir && rMulti.IsDouble() && rMulti.GetRoot().GetNext() )
1835cdf0e10cSrcweir lcl_ExtractFieldFollow( rMulti.GetRoot().GetNext(), pFirstRest );
1836cdf0e10cSrcweir if( !rMulti.IsDouble() && rMulti.GetRoot().GetNext() )
1837cdf0e10cSrcweir lcl_ExtractFieldFollow( rMulti.GetRoot().GetNext(), pSecondRest );
1838cdf0e10cSrcweir else
1839cdf0e10cSrcweir pSecondRest = NULL;
1840cdf0e10cSrcweir }
1841cdf0e10cSrcweir else
1842cdf0e10cSrcweir {
1843cdf0e10cSrcweir pFirstRest = rMulti.GetRoot().GetPortion();
1844cdf0e10cSrcweir pSecondRest = rMulti.GetRoot().GetNext() ?
1845cdf0e10cSrcweir rMulti.GetRoot().GetNext()->GetPortion() : NULL;
1846cdf0e10cSrcweir if( pFirstRest )
1847cdf0e10cSrcweir rMulti.GetRoot().SetPortion( NULL );
1848cdf0e10cSrcweir if( pSecondRest )
1849cdf0e10cSrcweir rMulti.GetRoot().GetNext()->SetPortion( NULL );
1850cdf0e10cSrcweir rMulti.SetFormatted();
1851cdf0e10cSrcweir nMultiLen = nMultiLen - rInf.GetIdx();
1852cdf0e10cSrcweir }
1853cdf0e10cSrcweir
1854cdf0e10cSrcweir // save some values
1855cdf0e10cSrcweir const XubString* pOldTxt = &(rInf.GetTxt());
1856cdf0e10cSrcweir const SwTwips nOldPaintOfst = rInf.GetPaintOfst();
1857cdf0e10cSrcweir
1858cdf0e10cSrcweir XubString aMultiStr( rInf.GetTxt(), 0, nMultiLen + rInf.GetIdx() );
1859cdf0e10cSrcweir rInf.SetTxt( aMultiStr );
1860cdf0e10cSrcweir SwTxtFormatInfo aInf( rInf, rMulti.GetRoot(), nActWidth );
1861cdf0e10cSrcweir // Do we allow break cuts? The FirstMulti-Flag is evaluated during
1862cdf0e10cSrcweir // line break determination.
1863cdf0e10cSrcweir sal_Bool bFirstMulti = rInf.GetIdx() != rInf.GetLineStart();
1864cdf0e10cSrcweir
1865cdf0e10cSrcweir SwLinePortion *pNextFirst = NULL;
1866cdf0e10cSrcweir SwLinePortion *pNextSecond = NULL;
1867cdf0e10cSrcweir sal_Bool bRet = sal_False;
1868cdf0e10cSrcweir
1869cdf0e10cSrcweir GETGRID( pFrm->FindPageFrm() )
1870cdf0e10cSrcweir const sal_Bool bHasGrid = pGrid && GRID_LINES_CHARS == pGrid->GetGridType();
1871cdf0e10cSrcweir
1872cdf0e10cSrcweir sal_uInt16 nGridWidth = 0;
1873cdf0e10cSrcweir sal_uInt16 nRubyHeight = 0;
1874cdf0e10cSrcweir sal_Bool bRubyTop = sal_False;
1875cdf0e10cSrcweir
1876cdf0e10cSrcweir if ( bHasGrid )
1877cdf0e10cSrcweir {
1878cdf0e10cSrcweir nGridWidth = pGrid->GetBaseHeight();
1879cdf0e10cSrcweir nRubyHeight = pGrid->GetRubyHeight();
1880cdf0e10cSrcweir bRubyTop = ! pGrid->GetRubyTextBelow();
1881cdf0e10cSrcweir }
1882cdf0e10cSrcweir
1883cdf0e10cSrcweir do
1884cdf0e10cSrcweir {
1885cdf0e10cSrcweir pCurr = &rMulti.GetRoot();
1886cdf0e10cSrcweir nStart = nStartIdx;
1887cdf0e10cSrcweir bRet = sal_False;
1888cdf0e10cSrcweir FormatReset( aInf );
1889cdf0e10cSrcweir aInf.X( nTmpX );
1890cdf0e10cSrcweir aInf.Width( KSHORT(nActWidth) );
1891cdf0e10cSrcweir aInf.RealWidth( KSHORT(nActWidth) );
1892cdf0e10cSrcweir aInf.SetFirstMulti( bFirstMulti );
1893cdf0e10cSrcweir aInf.SetNumDone( rInf.IsNumDone() );
1894cdf0e10cSrcweir aInf.SetFtnDone( rInf.IsFtnDone() );
1895cdf0e10cSrcweir
1896cdf0e10cSrcweir if( pFirstRest )
1897cdf0e10cSrcweir {
1898cdf0e10cSrcweir ASSERT( pFirstRest->InFldGrp(), "BuildMulti: Fieldrest expected");
1899cdf0e10cSrcweir SwFldPortion *pFld =
1900cdf0e10cSrcweir ((SwFldPortion*)pFirstRest)->Clone(
1901cdf0e10cSrcweir ((SwFldPortion*)pFirstRest)->GetExp() );
1902cdf0e10cSrcweir pFld->SetFollow( sal_True );
1903cdf0e10cSrcweir aInf.SetRest( pFld );
1904cdf0e10cSrcweir }
1905cdf0e10cSrcweir aInf.SetRuby( rMulti.IsRuby() && rMulti.OnTop() );
1906cdf0e10cSrcweir
1907cdf0e10cSrcweir // in grid mode we temporarily have to disable the grid for the ruby line
1908cdf0e10cSrcweir const sal_Bool bOldGridModeAllowed = GetInfo().SnapToGrid();
1909cdf0e10cSrcweir if ( bHasGrid && aInf.IsRuby() && bRubyTop )
1910cdf0e10cSrcweir aInf.SetSnapToGrid( sal_False );
1911cdf0e10cSrcweir
1912cdf0e10cSrcweir // If there's no more rubytext, then buildportion is forbidden
1913cdf0e10cSrcweir if( pFirstRest || !aInf.IsRuby() )
1914cdf0e10cSrcweir BuildPortions( aInf );
1915cdf0e10cSrcweir
1916cdf0e10cSrcweir aInf.SetSnapToGrid( bOldGridModeAllowed );
1917cdf0e10cSrcweir
1918cdf0e10cSrcweir rMulti.CalcSize( *this, aInf );
1919cdf0e10cSrcweir pCurr->SetRealHeight( pCurr->Height() );
1920cdf0e10cSrcweir
1921cdf0e10cSrcweir if( rMulti.IsBidi() )
1922cdf0e10cSrcweir {
1923cdf0e10cSrcweir pNextFirst = aInf.GetRest();
1924cdf0e10cSrcweir break;
1925cdf0e10cSrcweir }
1926cdf0e10cSrcweir
1927cdf0e10cSrcweir if( rMulti.HasRotation() && !rMulti.IsDouble() )
1928cdf0e10cSrcweir break;
1929cdf0e10cSrcweir // second line has to be formatted
1930cdf0e10cSrcweir else if( pCurr->GetLen()<nMultiLen || rMulti.IsRuby() || aInf.GetRest())
1931cdf0e10cSrcweir {
1932cdf0e10cSrcweir xub_StrLen nFirstLen = pCurr->GetLen();
1933cdf0e10cSrcweir delete pCurr->GetNext();
1934cdf0e10cSrcweir pCurr->SetNext( new SwLineLayout() );
1935cdf0e10cSrcweir pCurr = pCurr->GetNext();
1936cdf0e10cSrcweir nStart = aInf.GetIdx();
1937cdf0e10cSrcweir aInf.X( nTmpX );
1938cdf0e10cSrcweir SwTxtFormatInfo aTmp( aInf, *pCurr, nActWidth );
1939cdf0e10cSrcweir if( rMulti.IsRuby() )
1940cdf0e10cSrcweir {
1941cdf0e10cSrcweir aTmp.SetRuby( !rMulti.OnTop() );
1942cdf0e10cSrcweir pNextFirst = aInf.GetRest();
1943cdf0e10cSrcweir if( pSecondRest )
1944cdf0e10cSrcweir {
1945cdf0e10cSrcweir ASSERT( pSecondRest->InFldGrp(), "Fieldrest expected");
1946cdf0e10cSrcweir SwFldPortion *pFld = ((SwFldPortion*)pSecondRest)->Clone(
1947cdf0e10cSrcweir ((SwFldPortion*)pSecondRest)->GetExp() );
1948cdf0e10cSrcweir pFld->SetFollow( sal_True );
1949cdf0e10cSrcweir aTmp.SetRest( pFld );
1950cdf0e10cSrcweir }
1951cdf0e10cSrcweir if( !rMulti.OnTop() && nFirstLen < nMultiLen )
1952cdf0e10cSrcweir bRet = sal_True;
1953cdf0e10cSrcweir }
1954cdf0e10cSrcweir else
1955cdf0e10cSrcweir aTmp.SetRest( aInf.GetRest() );
1956cdf0e10cSrcweir aInf.SetRest( NULL );
1957cdf0e10cSrcweir
1958cdf0e10cSrcweir // in grid mode we temporarily have to disable the grid for the ruby line
1959cdf0e10cSrcweir if ( bHasGrid && aTmp.IsRuby() && ! bRubyTop )
1960cdf0e10cSrcweir aTmp.SetSnapToGrid( sal_False );
1961cdf0e10cSrcweir
1962cdf0e10cSrcweir BuildPortions( aTmp );
1963cdf0e10cSrcweir
1964cdf0e10cSrcweir aTmp.SetSnapToGrid( bOldGridModeAllowed );
1965cdf0e10cSrcweir
1966cdf0e10cSrcweir rMulti.CalcSize( *this, aInf );
1967cdf0e10cSrcweir rMulti.GetRoot().SetRealHeight( rMulti.GetRoot().Height() );
1968cdf0e10cSrcweir pCurr->SetRealHeight( pCurr->Height() );
1969cdf0e10cSrcweir if( rMulti.IsRuby() )
1970cdf0e10cSrcweir {
1971cdf0e10cSrcweir pNextSecond = aTmp.GetRest();
1972cdf0e10cSrcweir if( pNextFirst )
1973cdf0e10cSrcweir bRet = sal_True;
1974cdf0e10cSrcweir }
1975cdf0e10cSrcweir else
1976cdf0e10cSrcweir pNextFirst = aTmp.GetRest();
1977cdf0e10cSrcweir if( ( !aTmp.IsRuby() && nFirstLen + pCurr->GetLen() < nMultiLen )
1978cdf0e10cSrcweir || aTmp.GetRest() )
1979cdf0e10cSrcweir // our guess for width of multiportion was too small,
1980cdf0e10cSrcweir // text did not fit into multiportion
1981cdf0e10cSrcweir bRet = sal_True;
1982cdf0e10cSrcweir }
1983cdf0e10cSrcweir if( rMulti.IsRuby() )
1984cdf0e10cSrcweir break;
1985cdf0e10cSrcweir if( bRet )
1986cdf0e10cSrcweir {
1987cdf0e10cSrcweir // our guess for multiportion width was too small,
1988cdf0e10cSrcweir // we set min to act
1989cdf0e10cSrcweir nMinWidth = nActWidth;
1990cdf0e10cSrcweir nActWidth = ( 3 * nMaxWidth + nMinWidth + 3 ) / 4;
1991cdf0e10cSrcweir if ( nActWidth == nMaxWidth && rInf.GetLineStart() == rInf.GetIdx() )
1992cdf0e10cSrcweir // we have too less space, we must allow break cuts
1993cdf0e10cSrcweir // ( the first multi flag is considered during TxtPortion::_Format() )
1994cdf0e10cSrcweir bFirstMulti = sal_False;
1995cdf0e10cSrcweir if( nActWidth <= nMinWidth )
1996cdf0e10cSrcweir break;
1997cdf0e10cSrcweir }
1998cdf0e10cSrcweir else
1999cdf0e10cSrcweir {
2000cdf0e10cSrcweir // For Solaris, this optimisation can causes trouble:
2001cdf0e10cSrcweir // Setting this to the portion width ( = rMulti.Width() )
2002cdf0e10cSrcweir // can make GetTextBreak inside SwTxtGuess::Guess return to small
2003cdf0e10cSrcweir // values. Therefore we add some extra twips.
2004cdf0e10cSrcweir if( nActWidth > nTmpX + rMulti.Width() + 6 )
2005cdf0e10cSrcweir nActWidth = nTmpX + rMulti.Width() + 6;
2006cdf0e10cSrcweir nMaxWidth = nActWidth;
2007cdf0e10cSrcweir nActWidth = ( 3 * nMaxWidth + nMinWidth + 3 ) / 4;
2008cdf0e10cSrcweir if( nActWidth >= nMaxWidth )
2009cdf0e10cSrcweir break;
2010cdf0e10cSrcweir // we do not allow break cuts during formatting
2011cdf0e10cSrcweir bFirstMulti = sal_True;
2012cdf0e10cSrcweir }
2013cdf0e10cSrcweir delete pNextFirst;
2014cdf0e10cSrcweir pNextFirst = NULL;
2015cdf0e10cSrcweir } while ( sal_True );
2016cdf0e10cSrcweir
2017cdf0e10cSrcweir pMulti = pOldMulti;
2018cdf0e10cSrcweir
2019cdf0e10cSrcweir pCurr = pOldCurr;
2020cdf0e10cSrcweir nStart = nOldStart;
2021cdf0e10cSrcweir SetPropFont( 0 );
2022cdf0e10cSrcweir
2023cdf0e10cSrcweir rMulti.SetLen( rMulti.GetRoot().GetLen() + ( rMulti.GetRoot().GetNext() ?
2024cdf0e10cSrcweir rMulti.GetRoot().GetNext()->GetLen() : 0 ) );
2025cdf0e10cSrcweir
2026cdf0e10cSrcweir if( rMulti.IsDouble() )
2027cdf0e10cSrcweir {
2028cdf0e10cSrcweir ((SwDoubleLinePortion&)rMulti).CalcBlanks( rInf );
2029cdf0e10cSrcweir if( ((SwDoubleLinePortion&)rMulti).GetLineDiff() )
2030cdf0e10cSrcweir {
2031cdf0e10cSrcweir SwLineLayout* pLine = &rMulti.GetRoot();
2032cdf0e10cSrcweir if( ((SwDoubleLinePortion&)rMulti).GetLineDiff() > 0 )
2033cdf0e10cSrcweir {
2034cdf0e10cSrcweir rInf.SetIdx( nStartIdx + pLine->GetLen() );
2035cdf0e10cSrcweir pLine = pLine->GetNext();
2036cdf0e10cSrcweir }
2037cdf0e10cSrcweir if( pLine )
2038cdf0e10cSrcweir {
2039cdf0e10cSrcweir GetInfo().SetMulti( sal_True );
2040cdf0e10cSrcweir CalcNewBlock( pLine, NULL, rMulti.Width() );
2041cdf0e10cSrcweir GetInfo().SetMulti( sal_False );
2042cdf0e10cSrcweir }
2043cdf0e10cSrcweir rInf.SetIdx( nStartIdx );
2044cdf0e10cSrcweir }
2045cdf0e10cSrcweir if( ((SwDoubleLinePortion&)rMulti).GetBrackets() )
2046cdf0e10cSrcweir {
2047cdf0e10cSrcweir rMulti.Width( rMulti.Width() +
2048cdf0e10cSrcweir ((SwDoubleLinePortion&)rMulti).BracketWidth() );
2049cdf0e10cSrcweir GetInfo().X( nOldX );
2050cdf0e10cSrcweir }
2051cdf0e10cSrcweir }
2052cdf0e10cSrcweir else
2053cdf0e10cSrcweir {
2054cdf0e10cSrcweir rMulti.ActualizeTabulator();
2055cdf0e10cSrcweir if( rMulti.IsRuby() )
2056cdf0e10cSrcweir {
2057cdf0e10cSrcweir ((SwRubyPortion&)rMulti).Adjust( rInf );
2058cdf0e10cSrcweir ((SwRubyPortion&)rMulti).CalcRubyOffset();
2059cdf0e10cSrcweir }
2060cdf0e10cSrcweir }
2061cdf0e10cSrcweir if( rMulti.HasRotation() )
2062cdf0e10cSrcweir {
2063cdf0e10cSrcweir SwTwips nH = rMulti.Width();
2064cdf0e10cSrcweir SwTwips nAsc = rMulti.GetAscent() + ( nH - rMulti.Height() )/2;
2065cdf0e10cSrcweir if( nAsc > nH )
2066cdf0e10cSrcweir nAsc = nH;
2067cdf0e10cSrcweir else if( nAsc < 0 )
2068cdf0e10cSrcweir nAsc = 0;
2069cdf0e10cSrcweir rMulti.Width( rMulti.Height() );
2070cdf0e10cSrcweir rMulti.Height( KSHORT(nH) );
2071cdf0e10cSrcweir rMulti.SetAscent( KSHORT(nAsc) );
2072cdf0e10cSrcweir bRet = ( rInf.GetPos().X() + rMulti.Width() > rInf.Width() ) &&
2073cdf0e10cSrcweir nStartIdx != rInf.GetLineStart();
2074cdf0e10cSrcweir }
2075cdf0e10cSrcweir else if ( rMulti.IsBidi() )
2076cdf0e10cSrcweir {
2077cdf0e10cSrcweir bRet = rMulti.GetLen() < nMultiLen || pNextFirst;
2078cdf0e10cSrcweir }
2079cdf0e10cSrcweir
2080cdf0e10cSrcweir // line break has to be performed!
2081cdf0e10cSrcweir if( bRet )
2082cdf0e10cSrcweir {
2083cdf0e10cSrcweir ASSERT( !pNextFirst || pNextFirst->InFldGrp(),
2084cdf0e10cSrcweir "BuildMultiPortion: Surprising restportion, field expected" );
2085cdf0e10cSrcweir SwMultiPortion *pTmp;
2086cdf0e10cSrcweir if( rMulti.IsDouble() )
2087cdf0e10cSrcweir pTmp = new SwDoubleLinePortion( ((SwDoubleLinePortion&)rMulti),
2088cdf0e10cSrcweir nMultiLen + rInf.GetIdx() );
2089cdf0e10cSrcweir else if( rMulti.IsRuby() )
2090cdf0e10cSrcweir {
2091cdf0e10cSrcweir ASSERT( !pNextSecond || pNextSecond->InFldGrp(),
2092cdf0e10cSrcweir "BuildMultiPortion: Surprising restportion, field expected" );
2093cdf0e10cSrcweir
2094cdf0e10cSrcweir if ( rInf.GetIdx() == rInf.GetLineStart() )
2095cdf0e10cSrcweir {
2096cdf0e10cSrcweir // the ruby portion has to be split in two portions
2097cdf0e10cSrcweir pTmp = new SwRubyPortion( ((SwRubyPortion&)rMulti),
2098cdf0e10cSrcweir nMultiLen + rInf.GetIdx() );
2099cdf0e10cSrcweir
2100cdf0e10cSrcweir if( pNextSecond )
2101cdf0e10cSrcweir {
2102cdf0e10cSrcweir pTmp->GetRoot().SetNext( new SwLineLayout() );
2103cdf0e10cSrcweir pTmp->GetRoot().GetNext()->SetPortion( pNextSecond );
2104cdf0e10cSrcweir }
2105cdf0e10cSrcweir pTmp->SetFollowFld();
2106cdf0e10cSrcweir }
2107cdf0e10cSrcweir else
2108cdf0e10cSrcweir {
2109cdf0e10cSrcweir // we try to keep our ruby portion together
2110cdf0e10cSrcweir lcl_TruncateMultiPortion( rMulti, rInf, nStartIdx );
2111cdf0e10cSrcweir pTmp = 0;
2112cdf0e10cSrcweir }
2113cdf0e10cSrcweir }
2114cdf0e10cSrcweir else if( rMulti.HasRotation() )
2115cdf0e10cSrcweir {
2116cdf0e10cSrcweir // we try to keep our rotated portion together
2117cdf0e10cSrcweir lcl_TruncateMultiPortion( rMulti, rInf, nStartIdx );
2118cdf0e10cSrcweir pTmp = new SwRotatedPortion( nMultiLen + rInf.GetIdx(),
2119cdf0e10cSrcweir rMulti.GetDirection() );
2120cdf0e10cSrcweir }
2121cdf0e10cSrcweir // during a recursion of BuildMultiPortions we may not build
2122cdf0e10cSrcweir // a new SwBidiPortion, this would cause a memory leak
2123cdf0e10cSrcweir else if( rMulti.IsBidi() && ! pMulti )
2124cdf0e10cSrcweir {
2125cdf0e10cSrcweir if ( ! rMulti.GetLen() )
2126cdf0e10cSrcweir lcl_TruncateMultiPortion( rMulti, rInf, nStartIdx );
2127cdf0e10cSrcweir
2128cdf0e10cSrcweir // If there is a HolePortion at the end of the bidi portion,
2129cdf0e10cSrcweir // it has to be moved behind the bidi portion. Otherwise
2130cdf0e10cSrcweir // the visual cursor travelling gets into trouble.
2131cdf0e10cSrcweir SwLineLayout& aRoot = rMulti.GetRoot();
2132cdf0e10cSrcweir SwLinePortion* pPor = aRoot.GetFirstPortion();
2133cdf0e10cSrcweir while ( pPor )
2134cdf0e10cSrcweir {
2135cdf0e10cSrcweir if ( pPor->GetPortion() && pPor->GetPortion()->IsHolePortion() )
2136cdf0e10cSrcweir {
2137cdf0e10cSrcweir SwLinePortion* pHolePor = pPor->GetPortion();
2138cdf0e10cSrcweir pPor->SetPortion( NULL );
2139cdf0e10cSrcweir aRoot.SetLen( aRoot.GetLen() - pHolePor->GetLen() );
2140cdf0e10cSrcweir rMulti.SetLen( rMulti.GetLen() - pHolePor->GetLen() );
2141cdf0e10cSrcweir rMulti.SetPortion( pHolePor );
2142cdf0e10cSrcweir break;
2143cdf0e10cSrcweir }
2144cdf0e10cSrcweir pPor = pPor->GetPortion();
2145cdf0e10cSrcweir }
2146cdf0e10cSrcweir
2147cdf0e10cSrcweir pTmp = new SwBidiPortion( nMultiLen + rInf.GetIdx(),
2148cdf0e10cSrcweir ((SwBidiPortion&)rMulti).GetLevel() );
2149cdf0e10cSrcweir }
2150cdf0e10cSrcweir else
2151cdf0e10cSrcweir pTmp = NULL;
2152cdf0e10cSrcweir
2153cdf0e10cSrcweir if ( ! rMulti.GetLen() && rInf.GetLast() )
2154cdf0e10cSrcweir {
2155cdf0e10cSrcweir SeekAndChgBefore( rInf );
2156cdf0e10cSrcweir rInf.GetLast()->FormatEOL( rInf );
2157cdf0e10cSrcweir }
2158cdf0e10cSrcweir
2159cdf0e10cSrcweir if( pNextFirst && pTmp )
2160cdf0e10cSrcweir {
2161cdf0e10cSrcweir pTmp->SetFollowFld();
2162cdf0e10cSrcweir pTmp->GetRoot().SetPortion( pNextFirst );
2163cdf0e10cSrcweir }
2164cdf0e10cSrcweir else
2165cdf0e10cSrcweir // A follow field portion is still waiting. If nobody wants it,
2166cdf0e10cSrcweir // we delete it.
2167cdf0e10cSrcweir delete pNextFirst;
2168cdf0e10cSrcweir
2169cdf0e10cSrcweir rInf.SetRest( pTmp );
2170cdf0e10cSrcweir }
2171cdf0e10cSrcweir
2172cdf0e10cSrcweir rInf.SetTxt( *pOldTxt );
2173cdf0e10cSrcweir rInf.SetPaintOfst( nOldPaintOfst );
2174cdf0e10cSrcweir rInf.SetStop( aInf.IsStop() );
2175cdf0e10cSrcweir rInf.SetNumDone( sal_True );
2176cdf0e10cSrcweir rInf.SetFtnDone( sal_True );
2177cdf0e10cSrcweir SeekAndChg( rInf );
2178cdf0e10cSrcweir delete pFirstRest;
2179cdf0e10cSrcweir delete pSecondRest;
2180cdf0e10cSrcweir delete pFontSave;
2181cdf0e10cSrcweir return bRet;
2182cdf0e10cSrcweir }
2183cdf0e10cSrcweir
2184cdf0e10cSrcweir /*-----------------08.11.00 09:29-------------------
2185cdf0e10cSrcweir * SwTxtFormatter::MakeRestPortion(..)
2186cdf0e10cSrcweir * When a fieldportion at the end of line breaks and needs a following
2187cdf0e10cSrcweir * fieldportion in the next line, then the "restportion" of the formatinfo
2188cdf0e10cSrcweir * has to be set. Normally this happens during the formatting of the first
2189cdf0e10cSrcweir * part of the fieldportion.
2190cdf0e10cSrcweir * But sometimes the formatting starts at the line with the following part,
2191cdf0e10cSrcweir * exspecally when the following part is on the next page.
2192cdf0e10cSrcweir * In this case the MakeRestPortion-function has to create the following part.
2193cdf0e10cSrcweir * The first parameter is the line that contains possibly a first part
2194cdf0e10cSrcweir * of a field. When the function finds such field part, it creates the right
2195cdf0e10cSrcweir * restportion. This may be a multiportion, e.g. if the field is surrounded by
2196cdf0e10cSrcweir * a doubleline- or ruby-portion.
2197cdf0e10cSrcweir * The second parameter is the start index of the line.
2198cdf0e10cSrcweir * --------------------------------------------------*/
2199cdf0e10cSrcweir
MakeRestPortion(const SwLineLayout * pLine,xub_StrLen nPosition)2200cdf0e10cSrcweir SwLinePortion* SwTxtFormatter::MakeRestPortion( const SwLineLayout* pLine,
2201cdf0e10cSrcweir xub_StrLen nPosition )
2202cdf0e10cSrcweir {
2203cdf0e10cSrcweir if( !nPosition )
2204cdf0e10cSrcweir return NULL;
2205cdf0e10cSrcweir xub_StrLen nMultiPos = nPosition - pLine->GetLen();
2206cdf0e10cSrcweir const SwMultiPortion *pTmpMulti = NULL;
2207cdf0e10cSrcweir const SwMultiPortion *pHelpMulti = NULL;
2208cdf0e10cSrcweir const SwLinePortion* pPor = pLine->GetFirstPortion();
2209cdf0e10cSrcweir SwFldPortion *pFld = NULL;
2210cdf0e10cSrcweir while( pPor )
2211cdf0e10cSrcweir {
2212cdf0e10cSrcweir if( pPor->GetLen() )
2213cdf0e10cSrcweir {
2214cdf0e10cSrcweir if( !pHelpMulti )
2215cdf0e10cSrcweir {
2216cdf0e10cSrcweir nMultiPos = nMultiPos + pPor->GetLen();
2217cdf0e10cSrcweir pTmpMulti = NULL;
2218cdf0e10cSrcweir }
2219cdf0e10cSrcweir }
2220cdf0e10cSrcweir if( pPor->InFldGrp() )
2221cdf0e10cSrcweir {
2222cdf0e10cSrcweir if( !pHelpMulti )
2223cdf0e10cSrcweir pTmpMulti = NULL;
2224cdf0e10cSrcweir pFld = (SwFldPortion*)pPor;
2225cdf0e10cSrcweir }
2226cdf0e10cSrcweir else if( pPor->IsMultiPortion() )
2227cdf0e10cSrcweir {
2228cdf0e10cSrcweir ASSERT( !pHelpMulti || pHelpMulti->IsBidi(),
2229cdf0e10cSrcweir "Nested multiportions are forbidden." );
2230cdf0e10cSrcweir
2231cdf0e10cSrcweir pFld = NULL;
2232cdf0e10cSrcweir pTmpMulti = (SwMultiPortion*)pPor;
2233cdf0e10cSrcweir }
2234cdf0e10cSrcweir pPor = pPor->GetPortion();
2235cdf0e10cSrcweir // If the last portion is a multi-portion, we enter it
2236cdf0e10cSrcweir // and look for a field portion inside.
2237cdf0e10cSrcweir // If we are already in a multiportion, we could change to the
2238cdf0e10cSrcweir // next line
2239cdf0e10cSrcweir if( !pPor && pTmpMulti )
2240cdf0e10cSrcweir {
2241cdf0e10cSrcweir if( pHelpMulti )
2242cdf0e10cSrcweir { // We're already inside the multiportion, let's take the second
2243cdf0e10cSrcweir // line, if we are in a double line portion
2244cdf0e10cSrcweir if( !pHelpMulti->IsRuby() )
2245cdf0e10cSrcweir pPor = pHelpMulti->GetRoot().GetNext();
2246cdf0e10cSrcweir pTmpMulti = NULL;
2247cdf0e10cSrcweir }
2248cdf0e10cSrcweir else
2249cdf0e10cSrcweir { // Now we enter a multiportion, in a ruby portion we take the
2250cdf0e10cSrcweir // main line, not the phonetic line, in a doublelineportion we
2251cdf0e10cSrcweir // starts with the first line.
2252cdf0e10cSrcweir pHelpMulti = pTmpMulti;
2253cdf0e10cSrcweir nMultiPos = nMultiPos - pHelpMulti->GetLen();
2254cdf0e10cSrcweir if( pHelpMulti->IsRuby() && pHelpMulti->OnTop() )
2255cdf0e10cSrcweir pPor = pHelpMulti->GetRoot().GetNext();
2256cdf0e10cSrcweir else
2257cdf0e10cSrcweir pPor = pHelpMulti->GetRoot().GetFirstPortion();
2258cdf0e10cSrcweir }
2259cdf0e10cSrcweir }
2260cdf0e10cSrcweir }
2261cdf0e10cSrcweir if( pFld && !pFld->HasFollow() )
2262cdf0e10cSrcweir pFld = NULL;
2263cdf0e10cSrcweir
2264cdf0e10cSrcweir SwLinePortion *pRest = NULL;
2265cdf0e10cSrcweir if( pFld )
2266cdf0e10cSrcweir {
2267cdf0e10cSrcweir const SwTxtAttr *pHint = GetAttr( nPosition - 1 );
2268*dec99bbdSOliver-Rainer Wittmann if ( pHint
2269*dec99bbdSOliver-Rainer Wittmann && ( pHint->Which() == RES_TXTATR_FIELD
2270*dec99bbdSOliver-Rainer Wittmann || pHint->Which() == RES_TXTATR_ANNOTATION ) )
2271cdf0e10cSrcweir {
2272cdf0e10cSrcweir pRest = NewFldPortion( GetInfo(), pHint );
2273cdf0e10cSrcweir if( pRest->InFldGrp() )
2274cdf0e10cSrcweir ((SwFldPortion*)pRest)->TakeNextOffset( pFld );
2275cdf0e10cSrcweir else
2276cdf0e10cSrcweir {
2277cdf0e10cSrcweir delete pRest;
2278cdf0e10cSrcweir pRest = NULL;
2279cdf0e10cSrcweir }
2280cdf0e10cSrcweir }
2281cdf0e10cSrcweir }
2282cdf0e10cSrcweir if( !pHelpMulti )
2283cdf0e10cSrcweir return pRest;
2284cdf0e10cSrcweir
2285cdf0e10cSrcweir nPosition = nMultiPos + pHelpMulti->GetLen();
2286cdf0e10cSrcweir SwMultiCreator* pCreate = GetInfo().GetMultiCreator( nMultiPos, 0 );
2287cdf0e10cSrcweir
2288cdf0e10cSrcweir if ( !pCreate )
2289cdf0e10cSrcweir {
2290cdf0e10cSrcweir ASSERT( !pHelpMulti->GetLen(), "Multiportion without attribut?" );
2291cdf0e10cSrcweir if ( nMultiPos )
2292cdf0e10cSrcweir --nMultiPos;
2293cdf0e10cSrcweir pCreate = GetInfo().GetMultiCreator( --nMultiPos, 0 );
2294cdf0e10cSrcweir }
2295cdf0e10cSrcweir
2296cdf0e10cSrcweir if( pRest || nMultiPos > nPosition || ( pHelpMulti->IsRuby() &&
2297cdf0e10cSrcweir ((SwRubyPortion*)pHelpMulti)->GetRubyOffset() < STRING_LEN ) )
2298cdf0e10cSrcweir {
2299cdf0e10cSrcweir SwMultiPortion* pTmp;
2300cdf0e10cSrcweir if( pHelpMulti->IsDouble() )
2301cdf0e10cSrcweir pTmp = new SwDoubleLinePortion( *pCreate, nMultiPos );
2302cdf0e10cSrcweir else if( pHelpMulti->IsBidi() )
2303cdf0e10cSrcweir pTmp = new SwBidiPortion( nMultiPos, pCreate->nLevel );
2304cdf0e10cSrcweir else if( pHelpMulti->IsRuby() )
2305cdf0e10cSrcweir {
2306cdf0e10cSrcweir sal_Bool bRubyTop;
2307cdf0e10cSrcweir sal_Bool* pRubyPos = 0;
2308cdf0e10cSrcweir
2309cdf0e10cSrcweir if ( GetInfo().SnapToGrid() )
2310cdf0e10cSrcweir {
2311cdf0e10cSrcweir GETGRID( pFrm->FindPageFrm() )
2312cdf0e10cSrcweir if ( pGrid )
2313cdf0e10cSrcweir {
2314cdf0e10cSrcweir bRubyTop = ! pGrid->GetRubyTextBelow();
2315cdf0e10cSrcweir pRubyPos = &bRubyTop;
2316cdf0e10cSrcweir }
2317cdf0e10cSrcweir }
2318cdf0e10cSrcweir
2319cdf0e10cSrcweir pTmp = new SwRubyPortion( *pCreate, *GetInfo().GetFont(),
2320cdf0e10cSrcweir *pFrm->GetTxtNode()->getIDocumentSettingAccess(),
2321cdf0e10cSrcweir nMultiPos, ((SwRubyPortion*)pHelpMulti)->GetRubyOffset(),
2322cdf0e10cSrcweir pRubyPos );
2323cdf0e10cSrcweir }
2324cdf0e10cSrcweir else if( pHelpMulti->HasRotation() )
2325cdf0e10cSrcweir pTmp = new SwRotatedPortion( nMultiPos, pHelpMulti->GetDirection() );
2326cdf0e10cSrcweir else
2327cdf0e10cSrcweir {
2328cdf0e10cSrcweir delete pCreate;
2329cdf0e10cSrcweir return pRest;
2330cdf0e10cSrcweir }
2331cdf0e10cSrcweir delete pCreate;
2332cdf0e10cSrcweir pTmp->SetFollowFld();
2333cdf0e10cSrcweir if( pRest )
2334cdf0e10cSrcweir {
2335cdf0e10cSrcweir SwLineLayout *pLay = &pTmp->GetRoot();
2336cdf0e10cSrcweir if( pTmp->IsRuby() && pTmp->OnTop() )
2337cdf0e10cSrcweir {
2338cdf0e10cSrcweir pLay->SetNext( new SwLineLayout() );
2339cdf0e10cSrcweir pLay = pLay->GetNext();
2340cdf0e10cSrcweir }
2341cdf0e10cSrcweir pLay->SetPortion( pRest );
2342cdf0e10cSrcweir }
2343cdf0e10cSrcweir return pTmp;
2344cdf0e10cSrcweir }
2345cdf0e10cSrcweir return pRest;
2346cdf0e10cSrcweir }
2347cdf0e10cSrcweir
2348cdf0e10cSrcweir
2349cdf0e10cSrcweir
2350cdf0e10cSrcweir /*-----------------23.10.00 10:47-------------------
2351cdf0e10cSrcweir * SwTxtCursorSave notes the start and current line of a SwTxtCursor,
2352cdf0e10cSrcweir * sets them to the values for GetCrsrOfst inside a multiportion
2353cdf0e10cSrcweir * and restores them in the destructor.
2354cdf0e10cSrcweir * --------------------------------------------------*/
2355cdf0e10cSrcweir
SwTxtCursorSave(SwTxtCursor * pTxtCursor,SwMultiPortion * pMulti,SwTwips nY,sal_uInt16 & nX,xub_StrLen nCurrStart,long nSpaceAdd)2356cdf0e10cSrcweir SwTxtCursorSave::SwTxtCursorSave( SwTxtCursor* pTxtCursor,
2357cdf0e10cSrcweir SwMultiPortion* pMulti,
2358cdf0e10cSrcweir SwTwips nY,
2359cdf0e10cSrcweir sal_uInt16& nX,
2360cdf0e10cSrcweir xub_StrLen nCurrStart,
2361cdf0e10cSrcweir long nSpaceAdd )
2362cdf0e10cSrcweir {
2363cdf0e10cSrcweir pTxtCrsr = pTxtCursor;
2364cdf0e10cSrcweir nStart = pTxtCursor->nStart;
2365cdf0e10cSrcweir pTxtCursor->nStart = nCurrStart;
2366cdf0e10cSrcweir pCurr = pTxtCursor->pCurr;
2367cdf0e10cSrcweir pTxtCursor->pCurr = &pMulti->GetRoot();
2368cdf0e10cSrcweir while( pTxtCursor->Y() + pTxtCursor->GetLineHeight() < nY &&
2369cdf0e10cSrcweir pTxtCursor->Next() )
2370cdf0e10cSrcweir ; // nothing
2371cdf0e10cSrcweir nWidth = pTxtCursor->pCurr->Width();
2372cdf0e10cSrcweir nOldProp = pTxtCursor->GetPropFont();
2373cdf0e10cSrcweir
2374cdf0e10cSrcweir if ( pMulti->IsDouble() || pMulti->IsBidi() )
2375cdf0e10cSrcweir {
2376cdf0e10cSrcweir bSpaceChg = pMulti->ChgSpaceAdd( pTxtCursor->pCurr, nSpaceAdd );
2377cdf0e10cSrcweir
2378cdf0e10cSrcweir sal_uInt16 nSpaceCnt;
2379cdf0e10cSrcweir if ( pMulti->IsDouble() )
2380cdf0e10cSrcweir {
2381cdf0e10cSrcweir pTxtCursor->SetPropFont( 50 );
2382cdf0e10cSrcweir nSpaceCnt = ((SwDoubleLinePortion*)pMulti)->GetSpaceCnt();
2383cdf0e10cSrcweir }
2384cdf0e10cSrcweir else
2385cdf0e10cSrcweir {
2386cdf0e10cSrcweir const xub_StrLen nOldIdx = pTxtCursor->GetInfo().GetIdx();
2387cdf0e10cSrcweir pTxtCursor->GetInfo().SetIdx ( nCurrStart );
2388cdf0e10cSrcweir nSpaceCnt = ((SwBidiPortion*)pMulti)->GetSpaceCnt(pTxtCursor->GetInfo());
2389cdf0e10cSrcweir pTxtCursor->GetInfo().SetIdx ( nOldIdx );
2390cdf0e10cSrcweir }
2391cdf0e10cSrcweir
2392cdf0e10cSrcweir if( nSpaceAdd > 0 && !pMulti->HasTabulator() )
2393cdf0e10cSrcweir pTxtCursor->pCurr->Width( static_cast<sal_uInt16>(nWidth + nSpaceAdd * nSpaceCnt / SPACING_PRECISION_FACTOR ) );
2394cdf0e10cSrcweir
2395cdf0e10cSrcweir // For a BidiPortion we have to calculate the offset from the
2396cdf0e10cSrcweir // end of the portion
2397cdf0e10cSrcweir if ( nX && pMulti->IsBidi() )
2398cdf0e10cSrcweir nX = pTxtCursor->pCurr->Width() - nX;
2399cdf0e10cSrcweir }
2400cdf0e10cSrcweir else
2401cdf0e10cSrcweir bSpaceChg = sal_False;
2402cdf0e10cSrcweir }
2403cdf0e10cSrcweir
~SwTxtCursorSave()2404cdf0e10cSrcweir SwTxtCursorSave::~SwTxtCursorSave()
2405cdf0e10cSrcweir {
2406cdf0e10cSrcweir if( bSpaceChg )
2407cdf0e10cSrcweir SwDoubleLinePortion::ResetSpaceAdd( pTxtCrsr->pCurr );
2408cdf0e10cSrcweir pTxtCrsr->pCurr->Width( KSHORT(nWidth) );
2409cdf0e10cSrcweir pTxtCrsr->pCurr = pCurr;
2410cdf0e10cSrcweir pTxtCrsr->nStart = nStart;
2411cdf0e10cSrcweir pTxtCrsr->SetPropFont( nOldProp );
2412cdf0e10cSrcweir }
2413cdf0e10cSrcweir
2414