xref: /aoo42x/main/sw/source/core/text/txttab.cxx (revision 9f5514e7)
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