1efeef26fSAndrew Rist /**************************************************************
2efeef26fSAndrew Rist *
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
10efeef26fSAndrew Rist *
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.
19efeef26fSAndrew Rist *
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 #include "hintids.hxx"
28cdf0e10cSrcweir #include <editeng/lrspitem.hxx>
29cdf0e10cSrcweir #ifndef _SVX_TSTPITEM_HXX //autogen
30cdf0e10cSrcweir #include <editeng/tstpitem.hxx>
31cdf0e10cSrcweir #endif
32cdf0e10cSrcweir #include <IDocumentSettingAccess.hxx>
33cdf0e10cSrcweir #include <frmatr.hxx>
34cdf0e10cSrcweir #include <SwPortionHandler.hxx>
35cdf0e10cSrcweir
36cdf0e10cSrcweir #include "viewopt.hxx" // SwViewOptions
37cdf0e10cSrcweir #include "txtcfg.hxx"
38cdf0e10cSrcweir #include "portab.hxx"
39cdf0e10cSrcweir #include "inftxt.hxx"
40cdf0e10cSrcweir #include "itrform2.hxx"
41cdf0e10cSrcweir #include "txtfrm.hxx"
42cdf0e10cSrcweir #include <numrule.hxx>
43cdf0e10cSrcweir // --> OD 2008-06-05 #i89179#
44cdf0e10cSrcweir #include <porfld.hxx>
45cdf0e10cSrcweir // <--
46cdf0e10cSrcweir
47cdf0e10cSrcweir
48cdf0e10cSrcweir /*************************************************************************
49cdf0e10cSrcweir * SwLineInfo::GetTabStop()
50cdf0e10cSrcweir *************************************************************************/
51cdf0e10cSrcweir
52cdf0e10cSrcweir //#i24363# tab stops relative to indent
53cdf0e10cSrcweir /* Return the first tab stop that is > nSearchPos.
54cdf0e10cSrcweir * If the tab stop is outside the print area, we
55cdf0e10cSrcweir * return 0 if it is not the first tab stop.*/
GetTabStop(const SwTwips nSearchPos,const SwTwips nRight) const56cdf0e10cSrcweir const SvxTabStop *SwLineInfo::GetTabStop( const SwTwips nSearchPos,
57cdf0e10cSrcweir const SwTwips nRight ) const
58cdf0e10cSrcweir {
59cdf0e10cSrcweir for( MSHORT i = 0; i < pRuler->Count(); ++i )
60cdf0e10cSrcweir {
61cdf0e10cSrcweir const SvxTabStop &rTabStop = pRuler->operator[](i);
62cdf0e10cSrcweir if( rTabStop.GetTabPos() > SwTwips(nRight) )
63cdf0e10cSrcweir return i ? 0 : &rTabStop;
64cdf0e10cSrcweir
65cdf0e10cSrcweir if( rTabStop.GetTabPos() > nSearchPos )
66cdf0e10cSrcweir return &rTabStop;
67cdf0e10cSrcweir }
68cdf0e10cSrcweir return 0;
69cdf0e10cSrcweir }
70cdf0e10cSrcweir
71cdf0e10cSrcweir /*************************************************************************
72cdf0e10cSrcweir * SwLineInfo::NumberOfTabStops()
73cdf0e10cSrcweir *************************************************************************/
74cdf0e10cSrcweir
NumberOfTabStops() const75cdf0e10cSrcweir sal_uInt16 SwLineInfo::NumberOfTabStops() const
76cdf0e10cSrcweir {
77cdf0e10cSrcweir return pRuler->Count();
78cdf0e10cSrcweir }
79cdf0e10cSrcweir
80cdf0e10cSrcweir /*************************************************************************
81cdf0e10cSrcweir * SwTxtFormatter::NewTabPortion()
82cdf0e10cSrcweir *************************************************************************/
NewTabPortion(SwTxtFormatInfo & rInf,bool bAuto) const83cdf0e10cSrcweir SwTabPortion *SwTxtFormatter::NewTabPortion( SwTxtFormatInfo &rInf, bool bAuto ) const
84cdf0e10cSrcweir {
850244f9a7SOliver-Rainer Wittmann {
860244f9a7SOliver-Rainer Wittmann SwTabPortion *pLastTab = rInf.GetLastTab();
870244f9a7SOliver-Rainer Wittmann if( pLastTab && ( pLastTab->IsTabCntPortion() || pLastTab->IsTabDecimalPortion() ) )
880244f9a7SOliver-Rainer Wittmann if( pLastTab->PostFormat( rInf ) )
890244f9a7SOliver-Rainer Wittmann return 0;
900244f9a7SOliver-Rainer Wittmann }
91cdf0e10cSrcweir
92cdf0e10cSrcweir xub_Unicode cFill = 0;
93cdf0e10cSrcweir xub_Unicode cDec = 0;
940244f9a7SOliver-Rainer Wittmann SvxTabAdjust eAdj;
95cdf0e10cSrcweir
960244f9a7SOliver-Rainer Wittmann KSHORT nNewTabPos;
970244f9a7SOliver-Rainer Wittmann {
98cdf0e10cSrcweir const bool bRTL = pFrm->IsRightToLeft();
99cdf0e10cSrcweir // #i24363# tab stops relative to indent
100cdf0e10cSrcweir // nTabLeft: The absolute value, the tab stops are relative to: Tabs origin.
101cdf0e10cSrcweir //
102cdf0e10cSrcweir // --> OD 2008-07-01 #i91133#
103cdf0e10cSrcweir const bool bTabsRelativeToIndent =
104cdf0e10cSrcweir pFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT);
105cdf0e10cSrcweir const SwTwips nTabLeft = bRTL
106cdf0e10cSrcweir ? pFrm->Frm().Right() -
107cdf0e10cSrcweir ( bTabsRelativeToIndent ? GetTabLeft() : 0 )
108cdf0e10cSrcweir : pFrm->Frm().Left() +
109cdf0e10cSrcweir ( bTabsRelativeToIndent ? GetTabLeft() : 0 );
110cdf0e10cSrcweir // <--
111cdf0e10cSrcweir
112cdf0e10cSrcweir //
113cdf0e10cSrcweir // nLinePos: The absolute position, where we started the line formatting.
114cdf0e10cSrcweir //
115cdf0e10cSrcweir SwTwips nLinePos = GetLeftMargin();
116cdf0e10cSrcweir if ( bRTL )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir Point aPoint( nLinePos, 0 );
119cdf0e10cSrcweir pFrm->SwitchLTRtoRTL( aPoint );
120cdf0e10cSrcweir nLinePos = aPoint.X();
121cdf0e10cSrcweir }
122cdf0e10cSrcweir
123cdf0e10cSrcweir //
124cdf0e10cSrcweir // nTabPos: The current position, relative to the line start.
125cdf0e10cSrcweir //
126cdf0e10cSrcweir SwTwips nTabPos = rInf.GetLastTab() ? rInf.GetLastTab()->GetTabPos() : 0;
127cdf0e10cSrcweir if( nTabPos < rInf.X() )
128cdf0e10cSrcweir {
129cdf0e10cSrcweir nTabPos = rInf.X();
130cdf0e10cSrcweir }
131cdf0e10cSrcweir
132cdf0e10cSrcweir //
133cdf0e10cSrcweir // nCurrentAbsPos: The current position in absolute coordinates.
134cdf0e10cSrcweir //
135cdf0e10cSrcweir const SwTwips nCurrentAbsPos = bRTL ?
136cdf0e10cSrcweir nLinePos - nTabPos :
137cdf0e10cSrcweir nLinePos + nTabPos;
138cdf0e10cSrcweir
139cdf0e10cSrcweir //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
140cdf0e10cSrcweir SwTwips nMyRight;
141cdf0e10cSrcweir if ( pFrm->IsVertLR() )
142cdf0e10cSrcweir nMyRight = Left();
143cdf0e10cSrcweir else
144cdf0e10cSrcweir nMyRight = Right();
145cdf0e10cSrcweir
146cdf0e10cSrcweir if ( pFrm->IsVertical() )
147cdf0e10cSrcweir {
148cdf0e10cSrcweir Point aRightTop( nMyRight, pFrm->Frm().Top() );
149cdf0e10cSrcweir pFrm->SwitchHorizontalToVertical( aRightTop );
150cdf0e10cSrcweir nMyRight = aRightTop.Y();
151cdf0e10cSrcweir }
152cdf0e10cSrcweir
1530244f9a7SOliver-Rainer Wittmann SwTwips nNextPos = 0;
154cdf0e10cSrcweir
155cdf0e10cSrcweir // #i24363# tab stops relative to indent
156cdf0e10cSrcweir // nSearchPos: The current position relative to the tabs origin.
157cdf0e10cSrcweir //
158cdf0e10cSrcweir const SwTwips nSearchPos = bRTL ?
159cdf0e10cSrcweir nTabLeft - nCurrentAbsPos :
160cdf0e10cSrcweir nCurrentAbsPos - nTabLeft;
161cdf0e10cSrcweir
162cdf0e10cSrcweir //
163cdf0e10cSrcweir // First, we examine the tab stops set at the paragraph style or
164cdf0e10cSrcweir // any hard set tab stops:
165cdf0e10cSrcweir // Note: If there are no user defined tab stops, there is always a
166cdf0e10cSrcweir // default tab stop.
167cdf0e10cSrcweir //
1680244f9a7SOliver-Rainer Wittmann const SvxTabStop* pTabStop = aLineInf.GetTabStop( nSearchPos, nMyRight );
1690244f9a7SOliver-Rainer Wittmann if ( pTabStop )
1700244f9a7SOliver-Rainer Wittmann {
1710244f9a7SOliver-Rainer Wittmann cFill = ' ' != pTabStop->GetFill() ? pTabStop->GetFill() : 0;
1720244f9a7SOliver-Rainer Wittmann cDec = pTabStop->GetDecimal();
1730244f9a7SOliver-Rainer Wittmann eAdj = pTabStop->GetAdjustment();
174cdf0e10cSrcweir nNextPos = pTabStop->GetTabPos();
175cdf0e10cSrcweir if(!bTabsRelativeToIndent && eAdj == SVX_TAB_ADJUST_DEFAULT && nSearchPos < 0)
176cdf0e10cSrcweir {
177cdf0e10cSrcweir //calculate default tab position of default tabs in negative indent
178cdf0e10cSrcweir nNextPos = ( nSearchPos / nNextPos ) * nNextPos;
179cdf0e10cSrcweir }
1800244f9a7SOliver-Rainer Wittmann }
1810244f9a7SOliver-Rainer Wittmann else
1820244f9a7SOliver-Rainer Wittmann {
1830244f9a7SOliver-Rainer Wittmann KSHORT nDefTabDist = aLineInf.GetDefTabStop();
1840244f9a7SOliver-Rainer Wittmann if( KSHRT_MAX == nDefTabDist )
1850244f9a7SOliver-Rainer Wittmann {
1860244f9a7SOliver-Rainer Wittmann const SvxTabStopItem& rTab =
1870244f9a7SOliver-Rainer Wittmann (const SvxTabStopItem &)pFrm->GetAttrSet()->
1880244f9a7SOliver-Rainer Wittmann GetPool()->GetDefaultItem( RES_PARATR_TABSTOP );
1890244f9a7SOliver-Rainer Wittmann if( rTab.Count() )
1900244f9a7SOliver-Rainer Wittmann nDefTabDist = (KSHORT)rTab.GetStart()->GetTabPos();
1910244f9a7SOliver-Rainer Wittmann else
1920244f9a7SOliver-Rainer Wittmann nDefTabDist = SVX_TAB_DEFDIST;
1930244f9a7SOliver-Rainer Wittmann aLineInf.SetDefTabStop( nDefTabDist );
1940244f9a7SOliver-Rainer Wittmann }
195cdf0e10cSrcweir SwTwips nCount = nSearchPos;
196cdf0e10cSrcweir
1970244f9a7SOliver-Rainer Wittmann // Minimum tab stop width is 1
1980244f9a7SOliver-Rainer Wittmann if (nDefTabDist <= 0)
1990244f9a7SOliver-Rainer Wittmann nDefTabDist = 1;
200cdf0e10cSrcweir
2010244f9a7SOliver-Rainer Wittmann nCount /= nDefTabDist;
2020244f9a7SOliver-Rainer Wittmann nNextPos = ( nCount < 0 || ( !nCount && nSearchPos <= 0 ) )
2030244f9a7SOliver-Rainer Wittmann ? ( nCount * nDefTabDist )
2040244f9a7SOliver-Rainer Wittmann : ( ( nCount + 1 ) * nDefTabDist );
205cdf0e10cSrcweir // --> FME 2004-09-21 #117919 Minimum tab stop width is 1 or 51 twips:
206cdf0e10cSrcweir const SwTwips nMinimumTabWidth = pFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) ? 0 : 50;
207cdf0e10cSrcweir // <--
2080244f9a7SOliver-Rainer Wittmann if ( ( bRTL && nTabLeft - nNextPos >= nCurrentAbsPos - nMinimumTabWidth ) ||
209cdf0e10cSrcweir ( !bRTL && nNextPos + nTabLeft <= nCurrentAbsPos + nMinimumTabWidth ) )
210cdf0e10cSrcweir {
211cdf0e10cSrcweir nNextPos += nDefTabDist;
212cdf0e10cSrcweir }
2130244f9a7SOliver-Rainer Wittmann cFill = 0;
2140244f9a7SOliver-Rainer Wittmann eAdj = SVX_TAB_ADJUST_LEFT;
2150244f9a7SOliver-Rainer Wittmann }
216cdf0e10cSrcweir
217cdf0e10cSrcweir // --> OD #i115705# - correction and refactoring:
218cdf0e10cSrcweir // overrule determined next tab stop position in order to apply
219cdf0e10cSrcweir // a tab stop at the left margin under the following conditions:
220cdf0e10cSrcweir // - the new tab portion is inside the hanging indent
221cdf0e10cSrcweir // - a tab stop at the left margin is allowed
222cdf0e10cSrcweir // - the determined next tab stop is a default tab stop position OR
223cdf0e10cSrcweir // the determined next tab stop is beyond the left margin
224cdf0e10cSrcweir {
225cdf0e10cSrcweir long nLeftMarginTabPos = 0;
226cdf0e10cSrcweir {
227cdf0e10cSrcweir if ( !bTabsRelativeToIndent )
228cdf0e10cSrcweir {
229cdf0e10cSrcweir if ( bRTL )
230cdf0e10cSrcweir {
231cdf0e10cSrcweir Point aPoint( Left(), 0 );
232cdf0e10cSrcweir pFrm->SwitchLTRtoRTL( aPoint );
233cdf0e10cSrcweir nLeftMarginTabPos = pFrm->Frm().Right() - aPoint.X();
234cdf0e10cSrcweir }
235cdf0e10cSrcweir else
236cdf0e10cSrcweir {
237cdf0e10cSrcweir nLeftMarginTabPos = Left() - pFrm->Frm().Left();
238cdf0e10cSrcweir }
239cdf0e10cSrcweir }
240cdf0e10cSrcweir if( pCurr->HasForcedLeftMargin() )
241cdf0e10cSrcweir {
242cdf0e10cSrcweir SwLinePortion* pPor = pCurr->GetPortion();
243cdf0e10cSrcweir while( pPor && !pPor->IsFlyPortion() )
244cdf0e10cSrcweir {
245cdf0e10cSrcweir pPor = pPor->GetPortion();
246cdf0e10cSrcweir }
247cdf0e10cSrcweir if ( pPor )
248cdf0e10cSrcweir {
249cdf0e10cSrcweir nLeftMarginTabPos += pPor->Width();
250cdf0e10cSrcweir }
251cdf0e10cSrcweir }
252cdf0e10cSrcweir }
253cdf0e10cSrcweir const bool bNewTabPortionInsideHangingIndent =
254cdf0e10cSrcweir bRTL ? nCurrentAbsPos > nTabLeft - nLeftMarginTabPos
255cdf0e10cSrcweir : nCurrentAbsPos < nTabLeft + nLeftMarginTabPos;
256cdf0e10cSrcweir if ( bNewTabPortionInsideHangingIndent )
257cdf0e10cSrcweir {
258cdf0e10cSrcweir // If the paragraph is not inside a list having a list tab stop following
259cdf0e10cSrcweir // the list label or no further tab stop found in such a paragraph or
260cdf0e10cSrcweir // the next tab stop position does not equal the list tab stop,
261cdf0e10cSrcweir // a tab stop at the left margin can be applied. If this condition is
262cdf0e10cSrcweir // not hold, it is overruled by compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST.
263cdf0e10cSrcweir const bool bTabAtLeftMarginAllowed =
264cdf0e10cSrcweir ( !aLineInf.IsListTabStopIncluded() ||
265cdf0e10cSrcweir !pTabStop ||
266cdf0e10cSrcweir nNextPos != aLineInf.GetListTabStopPosition() ) ||
267cdf0e10cSrcweir // compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
268cdf0e10cSrcweir pFrm->GetTxtNode()->getIDocumentSettingAccess()->
269cdf0e10cSrcweir get(IDocumentSettingAccess::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST);
270cdf0e10cSrcweir if ( bTabAtLeftMarginAllowed )
271cdf0e10cSrcweir {
272cdf0e10cSrcweir if ( !pTabStop || eAdj == SVX_TAB_ADJUST_DEFAULT ||
273cdf0e10cSrcweir ( nNextPos > nLeftMarginTabPos ) )
274cdf0e10cSrcweir {
275cdf0e10cSrcweir eAdj = SVX_TAB_ADJUST_DEFAULT;
276cdf0e10cSrcweir cFill = 0;
277cdf0e10cSrcweir nNextPos = nLeftMarginTabPos;
278cdf0e10cSrcweir }
279cdf0e10cSrcweir }
280cdf0e10cSrcweir }
281cdf0e10cSrcweir }
282cdf0e10cSrcweir // <--
283cdf0e10cSrcweir
284cdf0e10cSrcweir nNextPos += bRTL ? nLinePos - nTabLeft : nTabLeft - nLinePos;
2850244f9a7SOliver-Rainer Wittmann ASSERT( nNextPos >= 0, "GetTabStop: Don't go back!" );
2860244f9a7SOliver-Rainer Wittmann nNewTabPos = KSHORT(nNextPos);
2870244f9a7SOliver-Rainer Wittmann }
288cdf0e10cSrcweir
2890244f9a7SOliver-Rainer Wittmann SwTabPortion *pTabPor = 0;
290cdf0e10cSrcweir if ( bAuto )
291cdf0e10cSrcweir {
292cdf0e10cSrcweir if ( SVX_TAB_ADJUST_DECIMAL == eAdj &&
293cdf0e10cSrcweir // --> FME 2005-12-19 #127428#
294cdf0e10cSrcweir 1 == aLineInf.NumberOfTabStops() )
295cdf0e10cSrcweir // <--
296cdf0e10cSrcweir pTabPor = new SwAutoTabDecimalPortion( nNewTabPos, cDec, cFill );
297cdf0e10cSrcweir }
298cdf0e10cSrcweir else
299cdf0e10cSrcweir {
300cdf0e10cSrcweir switch( eAdj )
301cdf0e10cSrcweir {
3020244f9a7SOliver-Rainer Wittmann case SVX_TAB_ADJUST_RIGHT :
3030244f9a7SOliver-Rainer Wittmann {
3040244f9a7SOliver-Rainer Wittmann pTabPor = new SwTabRightPortion( nNewTabPos, cFill );
3050244f9a7SOliver-Rainer Wittmann break;
3060244f9a7SOliver-Rainer Wittmann }
3070244f9a7SOliver-Rainer Wittmann case SVX_TAB_ADJUST_CENTER :
3080244f9a7SOliver-Rainer Wittmann {
3090244f9a7SOliver-Rainer Wittmann pTabPor = new SwTabCenterPortion( nNewTabPos, cFill );
3100244f9a7SOliver-Rainer Wittmann break;
3110244f9a7SOliver-Rainer Wittmann }
3120244f9a7SOliver-Rainer Wittmann case SVX_TAB_ADJUST_DECIMAL :
3130244f9a7SOliver-Rainer Wittmann {
3140244f9a7SOliver-Rainer Wittmann pTabPor = new SwTabDecimalPortion( nNewTabPos, cDec, cFill );
3150244f9a7SOliver-Rainer Wittmann break;
3160244f9a7SOliver-Rainer Wittmann }
3170244f9a7SOliver-Rainer Wittmann default:
3180244f9a7SOliver-Rainer Wittmann {
3190244f9a7SOliver-Rainer Wittmann ASSERT( SVX_TAB_ADJUST_LEFT == eAdj || SVX_TAB_ADJUST_DEFAULT == eAdj,
3200244f9a7SOliver-Rainer Wittmann "+SwTxtFormatter::NewTabPortion: unknown adjustment" );
3210244f9a7SOliver-Rainer Wittmann pTabPor = new SwTabLeftPortion( nNewTabPos, cFill );
3220244f9a7SOliver-Rainer Wittmann break;
3230244f9a7SOliver-Rainer Wittmann }
324cdf0e10cSrcweir }
325cdf0e10cSrcweir }
326cdf0e10cSrcweir
3270244f9a7SOliver-Rainer Wittmann return pTabPor;
328cdf0e10cSrcweir }
329cdf0e10cSrcweir
330cdf0e10cSrcweir /*************************************************************************
331cdf0e10cSrcweir * SwTabPortion::SwTabPortion()
332cdf0e10cSrcweir *************************************************************************/
333cdf0e10cSrcweir
334cdf0e10cSrcweir // Die Basisklasse wird erstmal ohne alles initialisiert.
335cdf0e10cSrcweir
336cdf0e10cSrcweir
SwTabPortion(const KSHORT nTabPosition,const xub_Unicode cFillChar)337cdf0e10cSrcweir SwTabPortion::SwTabPortion( const KSHORT nTabPosition, const xub_Unicode cFillChar )
338cdf0e10cSrcweir : SwFixPortion( 0, 0 ), nTabPos(nTabPosition), cFill(cFillChar)
339cdf0e10cSrcweir {
340cdf0e10cSrcweir nLineLength = 1;
341cdf0e10cSrcweir #ifdef DBG_UTIL
342cdf0e10cSrcweir if( IsFilled() )
343cdf0e10cSrcweir {
344cdf0e10cSrcweir ASSERT( ' ' != cFill, "SwTabPortion::CTOR: blanks ?!" );
345cdf0e10cSrcweir }
346cdf0e10cSrcweir #endif
347cdf0e10cSrcweir SetWhichPor( POR_TAB );
348cdf0e10cSrcweir }
349cdf0e10cSrcweir
350cdf0e10cSrcweir /*************************************************************************
351cdf0e10cSrcweir * virtual SwTabPortion::Format()
352cdf0e10cSrcweir *************************************************************************/
353cdf0e10cSrcweir
354cdf0e10cSrcweir
355cdf0e10cSrcweir
Format(SwTxtFormatInfo & rInf)356cdf0e10cSrcweir sal_Bool SwTabPortion::Format( SwTxtFormatInfo &rInf )
357cdf0e10cSrcweir {
358cdf0e10cSrcweir SwTabPortion *pLastTab = rInf.GetLastTab();
359cdf0e10cSrcweir if( pLastTab == this )
360cdf0e10cSrcweir return PostFormat( rInf );
361cdf0e10cSrcweir if( pLastTab )
362cdf0e10cSrcweir pLastTab->PostFormat( rInf );
363cdf0e10cSrcweir return PreFormat( rInf );
364cdf0e10cSrcweir }
365cdf0e10cSrcweir
366cdf0e10cSrcweir /*************************************************************************
367cdf0e10cSrcweir * virtual SwTabPortion::FormatEOL()
368cdf0e10cSrcweir *************************************************************************/
369cdf0e10cSrcweir
370cdf0e10cSrcweir
371cdf0e10cSrcweir
FormatEOL(SwTxtFormatInfo & rInf)372cdf0e10cSrcweir void SwTabPortion::FormatEOL( SwTxtFormatInfo &rInf )
373cdf0e10cSrcweir {
374cdf0e10cSrcweir if( rInf.GetLastTab() == this && !IsTabLeftPortion() )
375cdf0e10cSrcweir PostFormat( rInf );
376cdf0e10cSrcweir }
377cdf0e10cSrcweir
378cdf0e10cSrcweir /*************************************************************************
379cdf0e10cSrcweir * SwTabPortion::PreFormat()
380cdf0e10cSrcweir *************************************************************************/
381cdf0e10cSrcweir
382cdf0e10cSrcweir
383cdf0e10cSrcweir
PreFormat(SwTxtFormatInfo & rInf)384cdf0e10cSrcweir sal_Bool SwTabPortion::PreFormat( SwTxtFormatInfo &rInf )
385cdf0e10cSrcweir {
386cdf0e10cSrcweir ASSERT( rInf.X() <= GetTabPos(), "SwTabPortion::PreFormat: rush hour" );
387cdf0e10cSrcweir
388cdf0e10cSrcweir // Hier lassen wir uns nieder...
389cdf0e10cSrcweir Fix( static_cast<sal_uInt16>(rInf.X()) );
390cdf0e10cSrcweir
391cdf0e10cSrcweir const bool bTabCompat = rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
392cdf0e10cSrcweir
393cdf0e10cSrcweir // Die Mindestbreite eines Tabs ist immer mindestens ein Blank
394cdf0e10cSrcweir // --> FME 2004-11-25 #i37686# In compatibility mode, the minimum width
395cdf0e10cSrcweir // should be 1, even for non-left tab stops.
396cdf0e10cSrcweir sal_uInt16 nMinimumTabWidth = 1;
397cdf0e10cSrcweir // <--
398cdf0e10cSrcweir if ( !bTabCompat )
399cdf0e10cSrcweir {
400cdf0e10cSrcweir // --> OD 2008-06-05 #i89179#
401cdf0e10cSrcweir // tab portion representing the list tab of a list label gets the
402cdf0e10cSrcweir // same font as the corresponding number portion
403cdf0e10cSrcweir std::auto_ptr< SwFontSave > pSave( 0 );
404cdf0e10cSrcweir if ( GetLen() == 0 &&
405cdf0e10cSrcweir rInf.GetLast() && rInf.GetLast()->InNumberGrp() &&
406cdf0e10cSrcweir static_cast<SwNumberPortion*>(rInf.GetLast())->HasFont() )
407cdf0e10cSrcweir {
408cdf0e10cSrcweir const SwFont* pNumberPortionFont =
409cdf0e10cSrcweir static_cast<SwNumberPortion*>(rInf.GetLast())->GetFont();
410cdf0e10cSrcweir pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) );
411cdf0e10cSrcweir }
412cdf0e10cSrcweir // <--
413cdf0e10cSrcweir XubString aTmp( ' ' );
414cdf0e10cSrcweir SwTxtSizeInfo aInf( rInf, aTmp );
415cdf0e10cSrcweir nMinimumTabWidth = aInf.GetTxtSize().Width();
416cdf0e10cSrcweir }
417cdf0e10cSrcweir PrtWidth( nMinimumTabWidth );
418cdf0e10cSrcweir
419cdf0e10cSrcweir // Break tab stop to next line if:
420*9f5514e7Smseidel // 1. Minimal width does not fit to line anymore.
421cdf0e10cSrcweir // 2. An underflow event was called for the tab portion.
422cdf0e10cSrcweir sal_Bool bFull = ( bTabCompat && rInf.IsUnderFlow() ) ||
423cdf0e10cSrcweir rInf.Width() <= rInf.X() + PrtWidth();
424cdf0e10cSrcweir
425cdf0e10cSrcweir // #95477# Rotated tab stops get the width of one blank
426cdf0e10cSrcweir const sal_uInt16 nDir = rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
427cdf0e10cSrcweir
428cdf0e10cSrcweir if( ! bFull && 0 == nDir )
429cdf0e10cSrcweir {
430cdf0e10cSrcweir const MSHORT nWhich = GetWhichPor();
431cdf0e10cSrcweir switch( nWhich )
432cdf0e10cSrcweir {
433cdf0e10cSrcweir case POR_TABRIGHT:
434cdf0e10cSrcweir case POR_TABDECIMAL:
435cdf0e10cSrcweir case POR_TABCENTER:
436cdf0e10cSrcweir {
437cdf0e10cSrcweir if( POR_TABDECIMAL == nWhich )
438cdf0e10cSrcweir rInf.SetTabDecimal(
439cdf0e10cSrcweir ((SwTabDecimalPortion*)this)->GetTabDecimal());
440cdf0e10cSrcweir rInf.SetLastTab( this );
441cdf0e10cSrcweir break;
442cdf0e10cSrcweir }
443cdf0e10cSrcweir case POR_TABLEFT:
444cdf0e10cSrcweir {
445cdf0e10cSrcweir PrtWidth( static_cast<sal_uInt16>(GetTabPos() - rInf.X()) );
446cdf0e10cSrcweir bFull = rInf.Width() <= rInf.X() + PrtWidth();
447cdf0e10cSrcweir
448cdf0e10cSrcweir // In tabulator compatibility mode, we reset the bFull flag
449cdf0e10cSrcweir // if the tabulator is at the end of the paragraph and the
450cdf0e10cSrcweir // tab stop position is outside the frame:
451cdf0e10cSrcweir if ( bFull && bTabCompat &&
452cdf0e10cSrcweir rInf.GetIdx() + GetLen() == rInf.GetTxt().Len() &&
453cdf0e10cSrcweir GetTabPos() >= rInf.GetTxtFrm()->Frm().Width() )
454cdf0e10cSrcweir bFull = sal_False;
455cdf0e10cSrcweir
456cdf0e10cSrcweir break;
457cdf0e10cSrcweir }
458870262e3SDon Lewis default: ASSERT( sal_False, "SwTabPortion::PreFormat: unknown adjustment" );
459cdf0e10cSrcweir }
460cdf0e10cSrcweir }
461cdf0e10cSrcweir
462cdf0e10cSrcweir if( bFull )
463cdf0e10cSrcweir {
464cdf0e10cSrcweir // Wir muessen aufpassen, dass wir nicht endlos schleifen,
465cdf0e10cSrcweir // wenn die Breite kleiner ist, als ein Blank ...
466cdf0e10cSrcweir if( rInf.GetIdx() == rInf.GetLineStart() &&
467cdf0e10cSrcweir // --> FME 2005-01-19 #119175# TabStop should be forced to current
468cdf0e10cSrcweir // line if there is a fly reducing the line width:
469cdf0e10cSrcweir !rInf.GetFly() )
470cdf0e10cSrcweir // <--
471cdf0e10cSrcweir {
472cdf0e10cSrcweir PrtWidth( static_cast<sal_uInt16>(rInf.Width() - rInf.X()) );
473cdf0e10cSrcweir SetFixWidth( PrtWidth() );
474cdf0e10cSrcweir }
475cdf0e10cSrcweir else
476cdf0e10cSrcweir {
477cdf0e10cSrcweir Height( 0 );
478cdf0e10cSrcweir Width( 0 );
479cdf0e10cSrcweir SetLen( 0 );
480cdf0e10cSrcweir SetAscent( 0 );
481cdf0e10cSrcweir SetPortion( NULL ); //?????
482cdf0e10cSrcweir }
483cdf0e10cSrcweir return sal_True;
484cdf0e10cSrcweir }
485cdf0e10cSrcweir else
486cdf0e10cSrcweir {
487cdf0e10cSrcweir // Ein Kunstgriff mit Effekt: Die neuen Tabportions verhalten sich nun
488cdf0e10cSrcweir // so, wie FlyFrms, die in der Zeile stehen - inklusive Adjustment !
489cdf0e10cSrcweir SetFixWidth( PrtWidth() );
490cdf0e10cSrcweir return sal_False;
491cdf0e10cSrcweir }
492cdf0e10cSrcweir }
493cdf0e10cSrcweir
494cdf0e10cSrcweir /*************************************************************************
495cdf0e10cSrcweir * SwTabPortion::PostFormat()
496cdf0e10cSrcweir *************************************************************************/
497cdf0e10cSrcweir
498cdf0e10cSrcweir
499cdf0e10cSrcweir
PostFormat(SwTxtFormatInfo & rInf)500cdf0e10cSrcweir sal_Bool SwTabPortion::PostFormat( SwTxtFormatInfo &rInf )
501cdf0e10cSrcweir {
502cdf0e10cSrcweir const KSHORT nRight = Min( GetTabPos(), rInf.Width() );
503cdf0e10cSrcweir const SwLinePortion *pPor = GetPortion();
504cdf0e10cSrcweir
505cdf0e10cSrcweir KSHORT nPorWidth = 0;
506cdf0e10cSrcweir while( pPor )
507cdf0e10cSrcweir {
508cdf0e10cSrcweir DBG_LOOP;
509cdf0e10cSrcweir nPorWidth = nPorWidth + pPor->Width();
510cdf0e10cSrcweir pPor = pPor->GetPortion();
511cdf0e10cSrcweir }
512cdf0e10cSrcweir
513cdf0e10cSrcweir const MSHORT nWhich = GetWhichPor();
514cdf0e10cSrcweir ASSERT( POR_TABLEFT != nWhich, "SwTabPortion::PostFormat: already formatted" );
515cdf0e10cSrcweir const bool bTabCompat = rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
516cdf0e10cSrcweir
517cdf0e10cSrcweir // --> FME 2005-12-19 #127428# Abandon dec. tab position if line is full:
518cdf0e10cSrcweir if ( bTabCompat && POR_TABDECIMAL == nWhich )
519cdf0e10cSrcweir {
520cdf0e10cSrcweir KSHORT nPrePorWidth = static_cast<const SwTabDecimalPortion*>(this)->GetWidthOfPortionsUpToDecimalPosition();
521cdf0e10cSrcweir
522cdf0e10cSrcweir // no value was set => no decimal character was found
523cdf0e10cSrcweir if ( USHRT_MAX != nPrePorWidth )
524cdf0e10cSrcweir {
525cdf0e10cSrcweir if ( nPrePorWidth && nPorWidth - nPrePorWidth > rInf.Width() - nRight )
526cdf0e10cSrcweir {
527cdf0e10cSrcweir nPrePorWidth += nPorWidth - nPrePorWidth - ( rInf.Width() - nRight );
528cdf0e10cSrcweir }
529cdf0e10cSrcweir
530cdf0e10cSrcweir nPorWidth = nPrePorWidth - 1;
531cdf0e10cSrcweir }
532cdf0e10cSrcweir }
533cdf0e10cSrcweir // <--
534cdf0e10cSrcweir
535cdf0e10cSrcweir if( POR_TABCENTER == nWhich )
536cdf0e10cSrcweir {
537cdf0e10cSrcweir // zentrierte Tabs bereiten Probleme:
538cdf0e10cSrcweir // Wir muessen den Anteil herausfinden, der noch auf die Zeile passt.
539cdf0e10cSrcweir KSHORT nNewWidth = nPorWidth /2;
540cdf0e10cSrcweir if( nNewWidth > rInf.Width() - nRight )
541cdf0e10cSrcweir nNewWidth = nPorWidth - (rInf.Width() - nRight);
542cdf0e10cSrcweir nPorWidth = nNewWidth;
543cdf0e10cSrcweir }
544cdf0e10cSrcweir
545cdf0e10cSrcweir const KSHORT nDiffWidth = nRight - Fix();
546cdf0e10cSrcweir
547cdf0e10cSrcweir if( nDiffWidth > nPorWidth )
548cdf0e10cSrcweir {
549cdf0e10cSrcweir const KSHORT nOldWidth = GetFixWidth();
550cdf0e10cSrcweir const KSHORT nAdjDiff = nDiffWidth - nPorWidth;
551cdf0e10cSrcweir if( nAdjDiff > GetFixWidth() )
552cdf0e10cSrcweir PrtWidth( nAdjDiff );
553cdf0e10cSrcweir // Nicht erschrecken: wir muessen rInf weiterschieben.
554cdf0e10cSrcweir // Immerhin waren wir als Rechtstab bislang nur ein Blank breit.
555cdf0e10cSrcweir // Da wir uns jetzt aufgespannt haben, muss der Differenzbetrag
556cdf0e10cSrcweir // auf rInf.X() addiert werden !
557cdf0e10cSrcweir rInf.X( rInf.X() + PrtWidth() - nOldWidth );
558cdf0e10cSrcweir }
559cdf0e10cSrcweir SetFixWidth( PrtWidth() );
560cdf0e10cSrcweir // letzte Werte zuruecksetzen
561cdf0e10cSrcweir rInf.SetLastTab(0);
562cdf0e10cSrcweir if( POR_TABDECIMAL == nWhich )
563cdf0e10cSrcweir rInf.SetTabDecimal(0);
564cdf0e10cSrcweir
565cdf0e10cSrcweir return rInf.Width() <= rInf.X();
566cdf0e10cSrcweir }
567cdf0e10cSrcweir
568cdf0e10cSrcweir /*************************************************************************
569cdf0e10cSrcweir * virtual SwTabPortion::Paint()
570cdf0e10cSrcweir *
571cdf0e10cSrcweir * Ex: LineIter::DrawTab()
572cdf0e10cSrcweir *************************************************************************/
573cdf0e10cSrcweir
Paint(const SwTxtPaintInfo & rInf) const574cdf0e10cSrcweir void SwTabPortion::Paint( const SwTxtPaintInfo &rInf ) const
575cdf0e10cSrcweir {
576cdf0e10cSrcweir #ifdef DBG_UTIL
577cdf0e10cSrcweir // Wir wollen uns die Fixbreite anzeigen
578cdf0e10cSrcweir if( rInf.OnWin() && OPTDBG( rInf ) &&
579cdf0e10cSrcweir !rInf.GetOpt().IsPagePreview() && \
580cdf0e10cSrcweir !rInf.GetOpt().IsReadonly() && \
581cdf0e10cSrcweir SwViewOption::IsFieldShadings() )
582cdf0e10cSrcweir {
583cdf0e10cSrcweir const KSHORT nTmpWidth = PrtWidth();
584cdf0e10cSrcweir ((SwTabPortion*)this)->PrtWidth( GetFixWidth() );
585cdf0e10cSrcweir rInf.DrawViewOpt( *this, POR_TAB );
586cdf0e10cSrcweir ((SwTabPortion*)this)->PrtWidth( nTmpWidth );
587cdf0e10cSrcweir }
588cdf0e10cSrcweir #endif
589cdf0e10cSrcweir
590cdf0e10cSrcweir // --> OD 2008-06-05 #i89179#
591cdf0e10cSrcweir // tab portion representing the list tab of a list label gets the
592cdf0e10cSrcweir // same font as the corresponding number portion
593cdf0e10cSrcweir std::auto_ptr< SwFontSave > pSave( 0 );
594cdf0e10cSrcweir if ( GetLen() == 0 )
595cdf0e10cSrcweir {
596cdf0e10cSrcweir const SwLinePortion* pPrevPortion =
597cdf0e10cSrcweir const_cast<SwTabPortion*>(this)->FindPrevPortion( rInf.GetParaPortion() );
598cdf0e10cSrcweir if ( pPrevPortion &&
599cdf0e10cSrcweir pPrevPortion->InNumberGrp() &&
600cdf0e10cSrcweir static_cast<const SwNumberPortion*>(pPrevPortion)->HasFont() )
601cdf0e10cSrcweir {
602cdf0e10cSrcweir const SwFont* pNumberPortionFont =
603cdf0e10cSrcweir static_cast<const SwNumberPortion*>(pPrevPortion)->GetFont();
604cdf0e10cSrcweir pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) );
605cdf0e10cSrcweir }
606cdf0e10cSrcweir }
607cdf0e10cSrcweir // <--
608cdf0e10cSrcweir rInf.DrawBackBrush( *this );
609cdf0e10cSrcweir
610cdf0e10cSrcweir // do we have to repaint a post it portion?
611cdf0e10cSrcweir if( rInf.OnWin() && pPortion && !pPortion->Width() )
612cdf0e10cSrcweir pPortion->PrePaint( rInf, this );
613cdf0e10cSrcweir
614cdf0e10cSrcweir // Darstellung von Sonderzeichen
615cdf0e10cSrcweir if( rInf.OnWin() && rInf.GetOpt().IsTab() )
616cdf0e10cSrcweir {
617cdf0e10cSrcweir // gefuellte Tabs werden grau hinterlegt.
618cdf0e10cSrcweir if( IsFilled() )
619cdf0e10cSrcweir rInf.DrawViewOpt( *this, POR_TAB );
620cdf0e10cSrcweir else
621cdf0e10cSrcweir rInf.DrawTab( *this );
622cdf0e10cSrcweir }
623cdf0e10cSrcweir
624cdf0e10cSrcweir // 6842: Tabs sollen auf einmal wieder unterstrichen werden.
625cdf0e10cSrcweir if( rInf.GetFont()->IsPaintBlank() )
626cdf0e10cSrcweir {
627cdf0e10cSrcweir // Tabs mit Fuellung
628cdf0e10cSrcweir XubString aTxt( ' ' );
629cdf0e10cSrcweir const KSHORT nCharWidth = rInf.GetTxtSize( aTxt ).Width();
630cdf0e10cSrcweir // robust:
631cdf0e10cSrcweir if( nCharWidth )
632cdf0e10cSrcweir {
633cdf0e10cSrcweir // 6864: immer mit Kerning, auch auf dem Drucker!
634cdf0e10cSrcweir KSHORT nChar = Width() / nCharWidth;
635cdf0e10cSrcweir rInf.DrawText( aTxt.Fill( nChar, ' ' ), *this, 0, nChar, sal_True );
636cdf0e10cSrcweir }
637cdf0e10cSrcweir }
638cdf0e10cSrcweir
639cdf0e10cSrcweir // Ausgabe von Fuellzeichen
640cdf0e10cSrcweir if( IsFilled() )
641cdf0e10cSrcweir {
642cdf0e10cSrcweir // Tabs mit Fuellung
643cdf0e10cSrcweir XubString aTxt( cFill );
644cdf0e10cSrcweir const KSHORT nCharWidth = rInf.GetTxtSize( aTxt ).Width();
645cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
646cdf0e10cSrcweir ASSERT( nCharWidth, "!SwTabPortion::Paint: sophisticated tabchar" );
647cdf0e10cSrcweir #endif
648cdf0e10cSrcweir // robust:
649cdf0e10cSrcweir if( nCharWidth )
650cdf0e10cSrcweir {
651cdf0e10cSrcweir // 6864: immer mit Kerning, auch auf dem Drucker!
652cdf0e10cSrcweir KSHORT nChar = Width() / nCharWidth;
653cdf0e10cSrcweir if ( cFill == '_' )
654cdf0e10cSrcweir ++nChar; // damit keine Luecken entstehen (Bug 13430)
655cdf0e10cSrcweir rInf.DrawText( aTxt.Fill( nChar, cFill ), *this, 0, nChar, sal_True );
656cdf0e10cSrcweir }
657cdf0e10cSrcweir }
658cdf0e10cSrcweir }
659cdf0e10cSrcweir
660cdf0e10cSrcweir /*************************************************************************
661cdf0e10cSrcweir * virtual SwAutoTabDecimalPortion::Paint()
662cdf0e10cSrcweir *************************************************************************/
663cdf0e10cSrcweir
Paint(const SwTxtPaintInfo &) const664cdf0e10cSrcweir void SwAutoTabDecimalPortion::Paint( const SwTxtPaintInfo & ) const
665cdf0e10cSrcweir {
666cdf0e10cSrcweir }
667cdf0e10cSrcweir
668cdf0e10cSrcweir /*************************************************************************
669cdf0e10cSrcweir * virtual SwTabPortion::HandlePortion()
670cdf0e10cSrcweir *************************************************************************/
671cdf0e10cSrcweir
HandlePortion(SwPortionHandler & rPH) const672cdf0e10cSrcweir void SwTabPortion::HandlePortion( SwPortionHandler& rPH ) const
673cdf0e10cSrcweir {
674cdf0e10cSrcweir rPH.Text( GetLen(), GetWhichPor() );
675cdf0e10cSrcweir }
676cdf0e10cSrcweir
677