xref: /AOO41X/main/sw/source/core/text/portxt.cxx (revision b8d31f9f3f25a926c81c4e32e3ff83e72ddce41a)
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 <ctype.h>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
31cdf0e10cSrcweir #include <com/sun/star/i18n/ScriptType.hdl>
32cdf0e10cSrcweir #endif
33cdf0e10cSrcweir #include <hintids.hxx>     // CH_TXTATR
34cdf0e10cSrcweir #include <errhdl.hxx>   // ASSERT
35cdf0e10cSrcweir #include <SwPortionHandler.hxx>
36cdf0e10cSrcweir #include <txtcfg.hxx>
37cdf0e10cSrcweir #include <porlay.hxx>
38cdf0e10cSrcweir #include <inftxt.hxx>
39cdf0e10cSrcweir #include <guess.hxx>    // SwTxtGuess, Zeilenumbruch
40cdf0e10cSrcweir #include <porglue.hxx>
41cdf0e10cSrcweir #include <portab.hxx>       // pLastTab->
42cdf0e10cSrcweir #include <porfld.hxx>       // SwFldPortion
43cdf0e10cSrcweir #include <wrong.hxx>
44cdf0e10cSrcweir #include <viewsh.hxx>
45cdf0e10cSrcweir #include <IDocumentSettingAccess.hxx>
46cdf0e10cSrcweir #include <viewopt.hxx>  // SwViewOptions
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include <IMark.hxx>
49cdf0e10cSrcweir #include <pam.hxx>
50cdf0e10cSrcweir #include <doc.hxx>
51cdf0e10cSrcweir #include <xmloff/odffields.hxx>
52e272a9c9SHerbert Dürr #include <vcl/pdfextoutdevdata.hxx>
53cdf0e10cSrcweir 
54cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
55cdf0e10cSrcweir const sal_Char *GetLangName( const MSHORT nLang );
56cdf0e10cSrcweir #endif
57cdf0e10cSrcweir 
58cdf0e10cSrcweir using namespace ::sw::mark;
59cdf0e10cSrcweir using namespace ::com::sun::star;
60cdf0e10cSrcweir using namespace ::com::sun::star::i18n::ScriptType;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir /*************************************************************************
63cdf0e10cSrcweir  *                          lcl_AddSpace
64cdf0e10cSrcweir  * Returns for how many characters an extra space has to be added
65cdf0e10cSrcweir  * (for justified alignment).
66cdf0e10cSrcweir  *************************************************************************/
67cdf0e10cSrcweir 
lcl_AddSpace(const SwTxtSizeInfo & rInf,const XubString * pStr,const SwLinePortion & rPor)68cdf0e10cSrcweir sal_uInt16 lcl_AddSpace( const SwTxtSizeInfo &rInf, const XubString* pStr,
69cdf0e10cSrcweir                      const SwLinePortion& rPor )
70cdf0e10cSrcweir {
71cdf0e10cSrcweir     xub_StrLen nPos, nEnd;
72cdf0e10cSrcweir     const SwScriptInfo* pSI = 0;
73cdf0e10cSrcweir 
74cdf0e10cSrcweir     if ( pStr )
75cdf0e10cSrcweir     {
76cdf0e10cSrcweir         // passing a string means we are inside a field
77cdf0e10cSrcweir         nPos = 0;
78cdf0e10cSrcweir         nEnd = pStr->Len();
79cdf0e10cSrcweir     }
80cdf0e10cSrcweir     else
81cdf0e10cSrcweir     {
82cdf0e10cSrcweir         nPos = rInf.GetIdx();
83cdf0e10cSrcweir         nEnd = rInf.GetIdx() + rPor.GetLen();
84cdf0e10cSrcweir         pStr = &rInf.GetTxt();
85cdf0e10cSrcweir         pSI = &((SwParaPortion*)rInf.GetParaPortion())->GetScriptInfo();
86cdf0e10cSrcweir     }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir     sal_uInt16 nCnt = 0;
89cdf0e10cSrcweir     sal_uInt8 nScript = 0;
90cdf0e10cSrcweir 
91cdf0e10cSrcweir     // If portion consists of Asian characters and language is not
92cdf0e10cSrcweir     // Korean, we add extra space to each character.
93cdf0e10cSrcweir     // first we get the script type
94cdf0e10cSrcweir     if ( pSI )
95cdf0e10cSrcweir         nScript = pSI->ScriptType( nPos );
96cdf0e10cSrcweir     else if ( pBreakIt->GetBreakIter().is() )
97cdf0e10cSrcweir         nScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( *pStr, nPos );
98cdf0e10cSrcweir 
99cdf0e10cSrcweir     // Note: rInf.GetIdx() can differ from nPos,
100cdf0e10cSrcweir     // e.g., when rPor is a field portion. nPos referes to the string passed
101cdf0e10cSrcweir     // to the function, rInf.GetIdx() referes to the original string.
102cdf0e10cSrcweir 
103cdf0e10cSrcweir     // We try to find out which justification mode is required. This is done by
104cdf0e10cSrcweir     // evaluating the script type and the language attribute set for this portion
105cdf0e10cSrcweir 
106cdf0e10cSrcweir     // Asian Justification: Each character get some extra space
107cdf0e10cSrcweir     if ( nEnd > nPos && ASIAN == nScript )
108cdf0e10cSrcweir     {
109cdf0e10cSrcweir         LanguageType aLang =
110cdf0e10cSrcweir             rInf.GetTxtFrm()->GetTxtNode()->GetLang( rInf.GetIdx(), 1, nScript );
111cdf0e10cSrcweir 
112cdf0e10cSrcweir         if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
113cdf0e10cSrcweir         {
114cdf0e10cSrcweir             const SwLinePortion* pPor = rPor.GetPortion();
115cdf0e10cSrcweir             if ( pPor && ( pPor->IsKernPortion() ||
116cdf0e10cSrcweir                            pPor->IsControlCharPortion() ||
117cdf0e10cSrcweir                            pPor->IsPostItsPortion() ) )
118cdf0e10cSrcweir                 pPor = pPor->GetPortion();
119cdf0e10cSrcweir 
120cdf0e10cSrcweir             nCnt += nEnd - nPos;
121cdf0e10cSrcweir 
122cdf0e10cSrcweir             if ( !pPor || pPor->IsHolePortion() || pPor->InFixMargGrp() ||
123cdf0e10cSrcweir                   pPor->IsBreakPortion() )
124cdf0e10cSrcweir                 --nCnt;
125cdf0e10cSrcweir 
126cdf0e10cSrcweir             return nCnt;
127cdf0e10cSrcweir         }
128cdf0e10cSrcweir     }
129cdf0e10cSrcweir 
130cdf0e10cSrcweir     // Kashida Justification: Insert Kashidas
131cdf0e10cSrcweir     if ( nEnd > nPos && pSI && COMPLEX == nScript )
132cdf0e10cSrcweir     {
133cdf0e10cSrcweir         if ( SwScriptInfo::IsArabicText( *pStr, nPos, nEnd - nPos ) && pSI->CountKashida() )
134cdf0e10cSrcweir         {
135cdf0e10cSrcweir             const sal_uInt16 nKashRes = pSI->KashidaJustify( 0, 0, nPos, nEnd - nPos );
136cdf0e10cSrcweir             // i60591: need to check result of KashidaJustify
137cdf0e10cSrcweir             // determine if kashida justification is applicable
138cdf0e10cSrcweir             if( nKashRes != STRING_LEN )
139cdf0e10cSrcweir                 return nKashRes;
140cdf0e10cSrcweir         }
141cdf0e10cSrcweir     }
142cdf0e10cSrcweir 
143cdf0e10cSrcweir     // Thai Justification: Each character cell gets some extra space
144cdf0e10cSrcweir     if ( nEnd > nPos && COMPLEX == nScript )
145cdf0e10cSrcweir     {
146cdf0e10cSrcweir         LanguageType aLang =
147cdf0e10cSrcweir             rInf.GetTxtFrm()->GetTxtNode()->GetLang( rInf.GetIdx(), 1, nScript );
148cdf0e10cSrcweir 
149cdf0e10cSrcweir         if ( LANGUAGE_THAI == aLang )
150cdf0e10cSrcweir         {
151cdf0e10cSrcweir             nCnt = SwScriptInfo::ThaiJustify( *pStr, 0, 0, nPos, nEnd - nPos );
152cdf0e10cSrcweir 
153cdf0e10cSrcweir             const SwLinePortion* pPor = rPor.GetPortion();
154cdf0e10cSrcweir             if ( pPor && ( pPor->IsKernPortion() ||
155cdf0e10cSrcweir                            pPor->IsControlCharPortion() ||
156cdf0e10cSrcweir                            pPor->IsPostItsPortion() ) )
157cdf0e10cSrcweir                 pPor = pPor->GetPortion();
158cdf0e10cSrcweir 
159cdf0e10cSrcweir             if ( nCnt && ( ! pPor || pPor->IsHolePortion() || pPor->InFixMargGrp() ) )
160cdf0e10cSrcweir                 --nCnt;
161cdf0e10cSrcweir 
162cdf0e10cSrcweir             return nCnt;
163cdf0e10cSrcweir         }
164cdf0e10cSrcweir     }
165cdf0e10cSrcweir 
166cdf0e10cSrcweir     // Here starts the good old "Look for blanks and add space to them" part.
167cdf0e10cSrcweir     // Note: We do not want to add space to an isolated latin blank in front
168cdf0e10cSrcweir     // of some complex characters in RTL environment
169cdf0e10cSrcweir     const sal_Bool bDoNotAddSpace =
170cdf0e10cSrcweir             LATIN == nScript && ( nEnd == nPos + 1 ) && pSI &&
171cdf0e10cSrcweir             ( i18n::ScriptType::COMPLEX ==
172cdf0e10cSrcweir               pSI->ScriptType( nPos + 1 ) ) &&
173cdf0e10cSrcweir             rInf.GetTxtFrm() && rInf.GetTxtFrm()->IsRightToLeft();
174cdf0e10cSrcweir 
175cdf0e10cSrcweir     if ( bDoNotAddSpace )
176cdf0e10cSrcweir         return nCnt;
177cdf0e10cSrcweir 
178cdf0e10cSrcweir     for ( ; nPos < nEnd; ++nPos )
179cdf0e10cSrcweir     {
180cdf0e10cSrcweir         if( CH_BLANK == pStr->GetChar( nPos ) )
181cdf0e10cSrcweir             ++nCnt;
182cdf0e10cSrcweir     }
183cdf0e10cSrcweir 
184cdf0e10cSrcweir     // We still have to examine the next character:
185cdf0e10cSrcweir     // If the next character is ASIAN and not KOREAN we have
186cdf0e10cSrcweir     // to add an extra space
187cdf0e10cSrcweir     // nPos referes to the original string, even if a field string has
188cdf0e10cSrcweir     // been passed to this function
189cdf0e10cSrcweir     nPos = rInf.GetIdx() + rPor.GetLen();
190cdf0e10cSrcweir     if ( nPos < rInf.GetTxt().Len() )
191cdf0e10cSrcweir     {
192cdf0e10cSrcweir         sal_uInt8 nNextScript = 0;
193cdf0e10cSrcweir         const SwLinePortion* pPor = rPor.GetPortion();
194cdf0e10cSrcweir         if ( pPor && pPor->IsKernPortion() )
195cdf0e10cSrcweir             pPor = pPor->GetPortion();
196cdf0e10cSrcweir 
197cdf0e10cSrcweir         if ( ! pBreakIt->GetBreakIter().is() || ! pPor || pPor->InFixMargGrp() )
198cdf0e10cSrcweir             return nCnt;
199cdf0e10cSrcweir 
200cdf0e10cSrcweir         // next character is inside a field?
201cdf0e10cSrcweir         if ( CH_TXTATR_BREAKWORD == rInf.GetChar( nPos ) && pPor->InExpGrp() )
202cdf0e10cSrcweir         {
203cdf0e10cSrcweir             sal_Bool bOldOnWin = rInf.OnWin();
204cdf0e10cSrcweir             ((SwTxtSizeInfo &)rInf).SetOnWin( sal_False );
205cdf0e10cSrcweir 
206cdf0e10cSrcweir             XubString aStr( aEmptyStr );
207cdf0e10cSrcweir             pPor->GetExpTxt( rInf, aStr );
208cdf0e10cSrcweir             ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
209cdf0e10cSrcweir 
210cdf0e10cSrcweir             nNextScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( aStr, 0 );
211cdf0e10cSrcweir         }
212cdf0e10cSrcweir         else
213cdf0e10cSrcweir             nNextScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( rInf.GetTxt(), nPos );
214cdf0e10cSrcweir 
215cdf0e10cSrcweir         if( ASIAN == nNextScript )
216cdf0e10cSrcweir         {
217cdf0e10cSrcweir             LanguageType aLang =
218cdf0e10cSrcweir                 rInf.GetTxtFrm()->GetTxtNode()->GetLang( nPos, 1, nNextScript );
219cdf0e10cSrcweir 
220cdf0e10cSrcweir             if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
221cdf0e10cSrcweir                 ++nCnt;
222cdf0e10cSrcweir         }
223cdf0e10cSrcweir     }
224cdf0e10cSrcweir 
225cdf0e10cSrcweir     return nCnt;
226cdf0e10cSrcweir }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir /*************************************************************************
229cdf0e10cSrcweir  *                      class SwTxtPortion
230cdf0e10cSrcweir  *************************************************************************/
231cdf0e10cSrcweir 
SwTxtPortion(const SwLinePortion & rPortion)232cdf0e10cSrcweir SwTxtPortion::SwTxtPortion( const SwLinePortion &rPortion )
233cdf0e10cSrcweir   : SwLinePortion( rPortion )
234cdf0e10cSrcweir {
235cdf0e10cSrcweir     SetWhichPor( POR_TXT );
236cdf0e10cSrcweir }
237cdf0e10cSrcweir 
238cdf0e10cSrcweir /*************************************************************************
239cdf0e10cSrcweir  *                      SwTxtPortion::BreakCut()
240cdf0e10cSrcweir  *************************************************************************/
241cdf0e10cSrcweir 
BreakCut(SwTxtFormatInfo & rInf,const SwTxtGuess & rGuess)242cdf0e10cSrcweir void SwTxtPortion::BreakCut( SwTxtFormatInfo &rInf, const SwTxtGuess &rGuess )
243cdf0e10cSrcweir {
244cdf0e10cSrcweir     // Das Wort/Zeichen ist groesser als die Zeile
245cdf0e10cSrcweir     // Sonderfall Nr.1: Das Wort ist groesser als die Zeile
246cdf0e10cSrcweir     // Wir kappen...
247cdf0e10cSrcweir     const KSHORT nLineWidth = (KSHORT)(rInf.Width() - rInf.X());
248cdf0e10cSrcweir     xub_StrLen nLen = rGuess.CutPos() - rInf.GetIdx();
249cdf0e10cSrcweir     if( nLen )
250cdf0e10cSrcweir     {
251cdf0e10cSrcweir         // special case: guess does not always provide the correct
252cdf0e10cSrcweir         // width, only in common cases.
253cdf0e10cSrcweir         if ( !rGuess.BreakWidth() )
254cdf0e10cSrcweir         {
255cdf0e10cSrcweir             rInf.SetLen( nLen );
256cdf0e10cSrcweir             SetLen( nLen );
257cdf0e10cSrcweir             CalcTxtSize( rInf );
258cdf0e10cSrcweir 
259cdf0e10cSrcweir             // changing these values requires also changing them in
260cdf0e10cSrcweir             // guess.cxx
261cdf0e10cSrcweir             KSHORT nItalic = 0;
262cdf0e10cSrcweir             if( ITALIC_NONE != rInf.GetFont()->GetItalic() && !rInf.NotEOL() )
263cdf0e10cSrcweir             {
264cdf0e10cSrcweir                 nItalic = Height() / 12;
265cdf0e10cSrcweir             }
266cdf0e10cSrcweir             Width( Width() + nItalic );
267cdf0e10cSrcweir         }
268cdf0e10cSrcweir         else
269cdf0e10cSrcweir         {
270cdf0e10cSrcweir             Width( rGuess.BreakWidth() );
271cdf0e10cSrcweir             SetLen( nLen );
272cdf0e10cSrcweir         }
273cdf0e10cSrcweir     }
274cdf0e10cSrcweir     // special case: first character does not fit to line
275cdf0e10cSrcweir     else if ( rGuess.CutPos() == rInf.GetLineStart() )
276cdf0e10cSrcweir     {
277cdf0e10cSrcweir         SetLen( 1 );
278cdf0e10cSrcweir         Width( nLineWidth );
279cdf0e10cSrcweir     }
280cdf0e10cSrcweir     else
281cdf0e10cSrcweir     {
282cdf0e10cSrcweir         SetLen( 0 );
283cdf0e10cSrcweir         Width( 0 );
284cdf0e10cSrcweir     }
285cdf0e10cSrcweir }
286cdf0e10cSrcweir 
287cdf0e10cSrcweir /*************************************************************************
288cdf0e10cSrcweir  *                      SwTxtPortion::BreakUnderflow()
289cdf0e10cSrcweir  *************************************************************************/
290cdf0e10cSrcweir 
BreakUnderflow(SwTxtFormatInfo & rInf)291cdf0e10cSrcweir void SwTxtPortion::BreakUnderflow( SwTxtFormatInfo &rInf )
292cdf0e10cSrcweir {
293cdf0e10cSrcweir     Truncate();
294cdf0e10cSrcweir     Height( 0 );
295cdf0e10cSrcweir     Width( 0 );
296cdf0e10cSrcweir     SetLen( 0 );
297cdf0e10cSrcweir     SetAscent( 0 );
298cdf0e10cSrcweir     rInf.SetUnderFlow( this );
299cdf0e10cSrcweir }
300cdf0e10cSrcweir 
301cdf0e10cSrcweir  /*************************************************************************
302cdf0e10cSrcweir  *                      SwTxtPortion::_Format()
303cdf0e10cSrcweir  *************************************************************************/
304cdf0e10cSrcweir 
lcl_HasContent(const SwFldPortion & rFld,SwTxtFormatInfo & rInf)305cdf0e10cSrcweir sal_Bool lcl_HasContent( const SwFldPortion& rFld, SwTxtFormatInfo &rInf )
306cdf0e10cSrcweir {
307cdf0e10cSrcweir     String aTxt;
308cdf0e10cSrcweir     return rFld.GetExpTxt( rInf, aTxt ) && aTxt.Len();
309cdf0e10cSrcweir }
310cdf0e10cSrcweir 
_Format(SwTxtFormatInfo & rInf)311cdf0e10cSrcweir sal_Bool SwTxtPortion::_Format( SwTxtFormatInfo &rInf )
312cdf0e10cSrcweir {
313cdf0e10cSrcweir     // 5744: wenn nur der Trennstrich nicht mehr passt,
314cdf0e10cSrcweir     // muss trotzdem das Wort umgebrochen werden, ansonsten return sal_True!
315cdf0e10cSrcweir     if( rInf.IsUnderFlow() && rInf.GetSoftHyphPos() )
316cdf0e10cSrcweir     {
317cdf0e10cSrcweir         // soft hyphen portion has triggered an underflow event because
318cdf0e10cSrcweir         // of an alternative spelling position
319cdf0e10cSrcweir         sal_Bool bFull = sal_False;
320cdf0e10cSrcweir         const sal_Bool bHyph = rInf.ChgHyph( sal_True );
321cdf0e10cSrcweir         if( rInf.IsHyphenate() )
322cdf0e10cSrcweir         {
323cdf0e10cSrcweir             SwTxtGuess aGuess;
324cdf0e10cSrcweir             // check for alternative spelling left from the soft hyphen
325cdf0e10cSrcweir             // this should usually be true but
326cdf0e10cSrcweir             aGuess.AlternativeSpelling( rInf, rInf.GetSoftHyphPos() - 1 );
327cdf0e10cSrcweir             bFull = CreateHyphen( rInf, aGuess );
328cdf0e10cSrcweir             ASSERT( bFull, "Problem with hyphenation!!!" );
329cdf0e10cSrcweir         }
330cdf0e10cSrcweir         rInf.ChgHyph( bHyph );
331cdf0e10cSrcweir         rInf.SetSoftHyphPos( 0 );
332cdf0e10cSrcweir         return bFull;
333cdf0e10cSrcweir     }
334cdf0e10cSrcweir 
335cdf0e10cSrcweir     SwTxtGuess aGuess;
336cdf0e10cSrcweir     const sal_Bool bFull = !aGuess.Guess( *this, rInf, Height() );
337cdf0e10cSrcweir 
338cdf0e10cSrcweir     // these are the possible cases:
339cdf0e10cSrcweir     // A Portion fits to current line
340cdf0e10cSrcweir     // B Portion does not fit to current line but a possible line break
341cdf0e10cSrcweir     //   within the portion has been found by the break iterator, 2 subcases
342cdf0e10cSrcweir     //   B1 break is hyphen
343cdf0e10cSrcweir     //   B2 break is word end
344cdf0e10cSrcweir     // C Portion does not fit to current line and no possible line break
345cdf0e10cSrcweir     //   has been found by break iterator, 2 subcases:
346cdf0e10cSrcweir     //   C1 break iterator found a possible line break in portion before us
347cdf0e10cSrcweir     //      ==> this break is used (underflow)
348cdf0e10cSrcweir     //   C2 break iterator does not found a possible line break at all:
349cdf0e10cSrcweir     //      ==> line break
350cdf0e10cSrcweir 
351cdf0e10cSrcweir     // case A: line not yet full
352cdf0e10cSrcweir     if ( !bFull )
353cdf0e10cSrcweir     {
354cdf0e10cSrcweir         Width( aGuess.BreakWidth() );
355cdf0e10cSrcweir         // Vorsicht !
356cdf0e10cSrcweir         if( !InExpGrp() || InFldGrp() )
357cdf0e10cSrcweir             SetLen( rInf.GetLen() );
358cdf0e10cSrcweir 
359cdf0e10cSrcweir         short nKern = rInf.GetFont()->CheckKerning();
360cdf0e10cSrcweir         if( nKern > 0 && rInf.Width() < rInf.X() + Width() + nKern )
361cdf0e10cSrcweir         {
362cdf0e10cSrcweir             nKern = (short)(rInf.Width() - rInf.X() - Width() - 1);
363cdf0e10cSrcweir             if( nKern < 0 )
364cdf0e10cSrcweir                 nKern = 0;
365cdf0e10cSrcweir         }
366cdf0e10cSrcweir         if( nKern )
367cdf0e10cSrcweir             new SwKernPortion( *this, nKern );
368cdf0e10cSrcweir     }
369cdf0e10cSrcweir     // special case: hanging portion
370cdf0e10cSrcweir     else if( bFull && aGuess.GetHangingPortion() )
371cdf0e10cSrcweir     {
372cdf0e10cSrcweir         Width( aGuess.BreakWidth() );
373cdf0e10cSrcweir         SetLen( aGuess.BreakPos() - rInf.GetIdx() );
374cdf0e10cSrcweir         Insert( aGuess.GetHangingPortion() );
375cdf0e10cSrcweir         aGuess.GetHangingPortion()->SetAscent( GetAscent() );
376cdf0e10cSrcweir         aGuess.ClearHangingPortion();
377cdf0e10cSrcweir     }
378cdf0e10cSrcweir     // breakPos >= index
379cdf0e10cSrcweir     else if ( aGuess.BreakPos() >= rInf.GetIdx() && aGuess.BreakPos() != STRING_LEN )
380cdf0e10cSrcweir     {
381cdf0e10cSrcweir         // case B1
382cdf0e10cSrcweir         if( aGuess.HyphWord().is() && aGuess.BreakPos() > rInf.GetLineStart()
383cdf0e10cSrcweir             && ( aGuess.BreakPos() > rInf.GetIdx() ||
384cdf0e10cSrcweir                ( rInf.GetLast() && ! rInf.GetLast()->IsFlyPortion() ) ) )
385cdf0e10cSrcweir         {
386cdf0e10cSrcweir             CreateHyphen( rInf, aGuess );
387cdf0e10cSrcweir             if ( rInf.GetFly() )
388cdf0e10cSrcweir                 rInf.GetRoot()->SetMidHyph( sal_True );
389cdf0e10cSrcweir             else
390cdf0e10cSrcweir                 rInf.GetRoot()->SetEndHyph( sal_True );
391cdf0e10cSrcweir         }
392cdf0e10cSrcweir         // case C1
393cdf0e10cSrcweir         // - Footnote portions with fake line start (i.e., not at beginning of line)
394cdf0e10cSrcweir         //   should keep together with the text portion. (Note: no keep together
395cdf0e10cSrcweir         //   with only footnote portions.
396cdf0e10cSrcweir         // - TabPortions not at beginning of line should keep together with the
397cdf0e10cSrcweir         //   text portion, if they are not followed by a blank
398cdf0e10cSrcweir         //   (work around different definition of tab stop character - breaking or
399cdf0e10cSrcweir         //   non breaking character - in compatibility mode)
400cdf0e10cSrcweir         else if ( ( IsFtnPortion() && rInf.IsFakeLineStart() &&
401cdf0e10cSrcweir                     // --> OD 2010-01-29 #b6921213#
402cdf0e10cSrcweir                     rInf.IsOtherThanFtnInside() ) ||
403cdf0e10cSrcweir                     // <--
404cdf0e10cSrcweir                   ( rInf.GetLast() &&
405cdf0e10cSrcweir                     rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) &&
406cdf0e10cSrcweir                     rInf.GetLast()->InTabGrp() &&
407cdf0e10cSrcweir                     rInf.GetLineStart() + rInf.GetLast()->GetLen() < rInf.GetIdx() &&
408cdf0e10cSrcweir                     aGuess.BreakPos() == rInf.GetIdx()  &&
409cdf0e10cSrcweir                     CH_BLANK != rInf.GetChar( rInf.GetIdx() ) &&
410cdf0e10cSrcweir                     0x3000 != rInf.GetChar( rInf.GetIdx() ) ) )
411cdf0e10cSrcweir             BreakUnderflow( rInf );
412cdf0e10cSrcweir         // case B2
413cdf0e10cSrcweir         else if( rInf.GetIdx() > rInf.GetLineStart() ||
414cdf0e10cSrcweir                  aGuess.BreakPos() > rInf.GetIdx() ||
415cdf0e10cSrcweir                  // this is weird: during formatting the follow of a field
416cdf0e10cSrcweir                  // the values rInf.GetIdx and rInf.GetLineStart are replaced
417cdf0e10cSrcweir                  // IsFakeLineStart indicates GetIdx > GetLineStart
418cdf0e10cSrcweir                  rInf.IsFakeLineStart() ||
419cdf0e10cSrcweir                  rInf.GetFly() ||
420cdf0e10cSrcweir                  rInf.IsFirstMulti() ||
421cdf0e10cSrcweir                  ( rInf.GetLast() &&
422cdf0e10cSrcweir                     ( rInf.GetLast()->IsFlyPortion() ||
423cdf0e10cSrcweir                         ( rInf.GetLast()->InFldGrp() &&
424cdf0e10cSrcweir                           ! rInf.GetLast()->InNumberGrp() &&
425cdf0e10cSrcweir                           ! rInf.GetLast()->IsErgoSumPortion() &&
426cdf0e10cSrcweir                           lcl_HasContent(*((SwFldPortion*)rInf.GetLast()),rInf ) ) ) ) )
427cdf0e10cSrcweir         {
428cdf0e10cSrcweir             if ( rInf.X() + aGuess.BreakWidth() <= rInf.Width() )
429cdf0e10cSrcweir                 Width( aGuess.BreakWidth() );
430cdf0e10cSrcweir             else
431cdf0e10cSrcweir                 // this actually should not happen
432cdf0e10cSrcweir                 Width( KSHORT(rInf.Width() - rInf.X()) );
433cdf0e10cSrcweir 
434cdf0e10cSrcweir             SetLen( aGuess.BreakPos() - rInf.GetIdx() );
435cdf0e10cSrcweir 
436cdf0e10cSrcweir             ASSERT( aGuess.BreakStart() >= aGuess.FieldDiff(),
437cdf0e10cSrcweir                     "Trouble with expanded field portions during line break" );
438cdf0e10cSrcweir             const xub_StrLen nRealStart = aGuess.BreakStart() - aGuess.FieldDiff();
439cdf0e10cSrcweir             if( aGuess.BreakPos() < nRealStart && !InExpGrp() )
440cdf0e10cSrcweir             {
441cdf0e10cSrcweir                 SwHolePortion *pNew = new SwHolePortion( *this );
442cdf0e10cSrcweir                 pNew->SetLen( nRealStart - aGuess.BreakPos() );
443cdf0e10cSrcweir                 Insert( pNew );
444cdf0e10cSrcweir             }
445cdf0e10cSrcweir         }
446cdf0e10cSrcweir         else    // case C2, last exit
447cdf0e10cSrcweir             BreakCut( rInf, aGuess );
448cdf0e10cSrcweir     }
449cdf0e10cSrcweir     // breakPos < index or no breakpos at all
450cdf0e10cSrcweir     else
451cdf0e10cSrcweir     {
452cdf0e10cSrcweir         sal_Bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
453cdf0e10cSrcweir         if( aGuess.BreakPos() != STRING_LEN &&
454cdf0e10cSrcweir             aGuess.BreakPos() != rInf.GetLineStart() &&
455cdf0e10cSrcweir             ( !bFirstPor || rInf.GetFly() || rInf.GetLast()->IsFlyPortion() ||
456cdf0e10cSrcweir               rInf.IsFirstMulti() ) &&
457cdf0e10cSrcweir             ( !rInf.GetLast()->IsBlankPortion() ||  ((SwBlankPortion*)
458cdf0e10cSrcweir               rInf.GetLast())->MayUnderFlow( rInf, rInf.GetIdx()-1, sal_True )))
459cdf0e10cSrcweir         {       // case C1 (former BreakUnderflow())
460cdf0e10cSrcweir             BreakUnderflow( rInf );
461cdf0e10cSrcweir         }
462cdf0e10cSrcweir         else
463cdf0e10cSrcweir              // case C2, last exit
464cdf0e10cSrcweir             BreakCut( rInf, aGuess );
465cdf0e10cSrcweir     }
466cdf0e10cSrcweir 
467cdf0e10cSrcweir     return bFull;
468cdf0e10cSrcweir }
469cdf0e10cSrcweir 
470cdf0e10cSrcweir /*************************************************************************
471cdf0e10cSrcweir  *                 virtual SwTxtPortion::Format()
472cdf0e10cSrcweir  *************************************************************************/
473cdf0e10cSrcweir 
474cdf0e10cSrcweir 
475cdf0e10cSrcweir 
Format(SwTxtFormatInfo & rInf)476cdf0e10cSrcweir sal_Bool SwTxtPortion::Format( SwTxtFormatInfo &rInf )
477cdf0e10cSrcweir {
478cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
479cdf0e10cSrcweir     const XubString aDbgTxt( rInf.GetTxt().Copy( rInf.GetIdx(), rInf.GetLen() ) );
480cdf0e10cSrcweir #endif
481cdf0e10cSrcweir 
482cdf0e10cSrcweir     if( rInf.X() > rInf.Width() || (!GetLen() && !InExpGrp()) )
483cdf0e10cSrcweir     {
484cdf0e10cSrcweir         Height( 0 );
485cdf0e10cSrcweir         Width( 0 );
486cdf0e10cSrcweir         SetLen( 0 );
487cdf0e10cSrcweir         SetAscent( 0 );
488cdf0e10cSrcweir         SetPortion( NULL );  // ????
489cdf0e10cSrcweir         return sal_True;
490cdf0e10cSrcweir     }
491cdf0e10cSrcweir 
492cdf0e10cSrcweir     ASSERT( rInf.RealWidth() || (rInf.X() == rInf.Width()),
493cdf0e10cSrcweir         "SwTxtPortion::Format: missing real width" );
494cdf0e10cSrcweir     ASSERT( Height(), "SwTxtPortion::Format: missing height" );
495cdf0e10cSrcweir 
496cdf0e10cSrcweir     return _Format( rInf );
497cdf0e10cSrcweir }
498cdf0e10cSrcweir 
499cdf0e10cSrcweir /*************************************************************************
500cdf0e10cSrcweir  *                 virtual SwTxtPortion::FormatEOL()
501cdf0e10cSrcweir  *************************************************************************/
502cdf0e10cSrcweir 
503cdf0e10cSrcweir // Format end of line
504cdf0e10cSrcweir // 5083: Es kann schon manchmal unguenstige Faelle geben...
505cdf0e10cSrcweir // "vom {Nikolaus}", Nikolaus bricht um "vom " wird im Blocksatz
506cdf0e10cSrcweir // zu "vom" und " ", wobei der Glue expandiert wird, statt in die
507cdf0e10cSrcweir // MarginPortion aufzugehen.
508cdf0e10cSrcweir // rInf.nIdx steht auf dem naechsten Wort, nIdx-1 ist der letzte
509cdf0e10cSrcweir // Buchstabe der Portion.
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 
512cdf0e10cSrcweir 
FormatEOL(SwTxtFormatInfo & rInf)513cdf0e10cSrcweir void SwTxtPortion::FormatEOL( SwTxtFormatInfo &rInf )
514cdf0e10cSrcweir {
515cdf0e10cSrcweir     if( ( !GetPortion() || ( GetPortion()->IsKernPortion() &&
516cdf0e10cSrcweir         !GetPortion()->GetPortion() ) ) && GetLen() &&
517cdf0e10cSrcweir         rInf.GetIdx() < rInf.GetTxt().Len() &&
518cdf0e10cSrcweir         1 < rInf.GetIdx() && ' ' == rInf.GetChar( rInf.GetIdx() - 1 )
519cdf0e10cSrcweir         && !rInf.GetLast()->IsHolePortion() )
520cdf0e10cSrcweir     {
521cdf0e10cSrcweir         // calculate number of blanks
522cdf0e10cSrcweir         xub_StrLen nX = rInf.GetIdx() - 1;
523cdf0e10cSrcweir         sal_uInt16 nHoleLen = 1;
524cdf0e10cSrcweir         while( nX && nHoleLen < GetLen() && CH_BLANK == rInf.GetChar( --nX ) )
525cdf0e10cSrcweir             nHoleLen++;
526cdf0e10cSrcweir 
527cdf0e10cSrcweir         // Erst uns einstellen und dann Inserten, weil wir ja auch ein
528cdf0e10cSrcweir         // SwLineLayout sein koennten.
529cdf0e10cSrcweir         KSHORT nBlankSize;
530cdf0e10cSrcweir         if( nHoleLen == GetLen() )
531cdf0e10cSrcweir             nBlankSize = Width();
532cdf0e10cSrcweir         else
533cdf0e10cSrcweir             nBlankSize = nHoleLen * rInf.GetTxtSize( ' ' ).Width();
534cdf0e10cSrcweir         Width( Width() - nBlankSize );
535cdf0e10cSrcweir         rInf.X( rInf.X() - nBlankSize );
536cdf0e10cSrcweir         SetLen( GetLen() - nHoleLen );
537cdf0e10cSrcweir         SwLinePortion *pHole = new SwHolePortion( *this );
538cdf0e10cSrcweir         ( (SwHolePortion *)pHole )->SetBlankWidth( nBlankSize );
539cdf0e10cSrcweir         ( (SwHolePortion *)pHole )->SetLen( nHoleLen );
540cdf0e10cSrcweir         Insert( pHole );
541cdf0e10cSrcweir     }
542cdf0e10cSrcweir }
543cdf0e10cSrcweir 
544cdf0e10cSrcweir /*************************************************************************
545cdf0e10cSrcweir  *               virtual SwTxtPortion::GetCrsrOfst()
546cdf0e10cSrcweir  *************************************************************************/
547cdf0e10cSrcweir 
548cdf0e10cSrcweir 
549cdf0e10cSrcweir 
GetCrsrOfst(const KSHORT nOfst) const550cdf0e10cSrcweir xub_StrLen SwTxtPortion::GetCrsrOfst( const KSHORT nOfst ) const
551cdf0e10cSrcweir {
552cdf0e10cSrcweir     ASSERT( !this, "SwTxtPortion::GetCrsrOfst: don't use this method!" );
553cdf0e10cSrcweir     return SwLinePortion::GetCrsrOfst( nOfst );
554cdf0e10cSrcweir }
555cdf0e10cSrcweir 
556cdf0e10cSrcweir /*************************************************************************
557cdf0e10cSrcweir  *                virtual SwTxtPortion::GetTxtSize()
558cdf0e10cSrcweir  *************************************************************************/
559cdf0e10cSrcweir // Das GetTxtSize() geht davon aus, dass die eigene Laenge korrekt ist
560cdf0e10cSrcweir 
GetTxtSize(const SwTxtSizeInfo & rInf) const561cdf0e10cSrcweir SwPosSize SwTxtPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
562cdf0e10cSrcweir {
563cdf0e10cSrcweir     return rInf.GetTxtSize();
564cdf0e10cSrcweir }
565cdf0e10cSrcweir 
566cdf0e10cSrcweir /*************************************************************************
567cdf0e10cSrcweir  *               virtual SwTxtPortion::Paint()
568cdf0e10cSrcweir  *************************************************************************/
569cdf0e10cSrcweir 
570cdf0e10cSrcweir 
571cdf0e10cSrcweir 
Paint(const SwTxtPaintInfo & rInf) const572cdf0e10cSrcweir void SwTxtPortion::Paint( const SwTxtPaintInfo &rInf ) const
573cdf0e10cSrcweir {
574cdf0e10cSrcweir     if (rInf.OnWin() && 1==rInf.GetLen() && CH_TXT_ATR_FIELDEND==rInf.GetTxt().GetChar(rInf.GetIdx()))
575cdf0e10cSrcweir     {
576cdf0e10cSrcweir         rInf.DrawBackBrush( *this );
577cdf0e10cSrcweir         const XubString aTxt = XubString::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDEND);
578cdf0e10cSrcweir         rInf.DrawText( aTxt, *this, 0, aTxt.Len(), false );
579cdf0e10cSrcweir     }
580cdf0e10cSrcweir     else if (rInf.OnWin() && 1==rInf.GetLen() && CH_TXT_ATR_FIELDSTART==rInf.GetTxt().GetChar(rInf.GetIdx()))
581cdf0e10cSrcweir     {
582cdf0e10cSrcweir         rInf.DrawBackBrush( *this );
583cdf0e10cSrcweir         const XubString aTxt = XubString::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDSTART);
584cdf0e10cSrcweir         rInf.DrawText( aTxt, *this, 0, aTxt.Len(), false );
585cdf0e10cSrcweir     }
586cdf0e10cSrcweir     else if( GetLen() )
587cdf0e10cSrcweir     {
588cdf0e10cSrcweir         rInf.DrawBackBrush( *this );
589cdf0e10cSrcweir 
590cdf0e10cSrcweir         // do we have to repaint a post it portion?
591cdf0e10cSrcweir         if( rInf.OnWin() && pPortion && !pPortion->Width() )
592cdf0e10cSrcweir             pPortion->PrePaint( rInf, this );
593cdf0e10cSrcweir 
594cdf0e10cSrcweir         const SwWrongList *pWrongList = rInf.GetpWrongList();
595cdf0e10cSrcweir         const SwWrongList *pGrammarCheckList = rInf.GetGrammarCheckList();
596cdf0e10cSrcweir         // SMARTTAGS
597cdf0e10cSrcweir         const SwWrongList *pSmarttags = rInf.GetSmartTags();
598cdf0e10cSrcweir 
599cdf0e10cSrcweir         const bool bWrong = 0 != pWrongList;
600cdf0e10cSrcweir         const bool bGrammarCheck = 0 != pGrammarCheckList;
601cdf0e10cSrcweir         const bool bSmartTags = 0 != pSmarttags;
602cdf0e10cSrcweir 
603cdf0e10cSrcweir         if ( bWrong || bSmartTags || bGrammarCheck )
604cdf0e10cSrcweir             rInf.DrawMarkedText( *this, rInf.GetLen(), sal_False, bWrong, bSmartTags, bGrammarCheck );
605cdf0e10cSrcweir         else
606cdf0e10cSrcweir             rInf.DrawText( *this, rInf.GetLen(), sal_False );
607cdf0e10cSrcweir     }
608cdf0e10cSrcweir }
609cdf0e10cSrcweir 
610cdf0e10cSrcweir /*************************************************************************
611cdf0e10cSrcweir  *              virtual SwTxtPortion::GetExpTxt()
612cdf0e10cSrcweir  *************************************************************************/
613cdf0e10cSrcweir 
614cdf0e10cSrcweir 
615cdf0e10cSrcweir 
GetExpTxt(const SwTxtSizeInfo &,XubString &) const616cdf0e10cSrcweir sal_Bool SwTxtPortion::GetExpTxt( const SwTxtSizeInfo &, XubString & ) const
617cdf0e10cSrcweir {
618cdf0e10cSrcweir     return sal_False;
619cdf0e10cSrcweir }
620cdf0e10cSrcweir 
621cdf0e10cSrcweir /*************************************************************************
622cdf0e10cSrcweir  *        xub_StrLen SwTxtPortion::GetSpaceCnt()
623cdf0e10cSrcweir  *              long SwTxtPortion::CalcSpacing()
624cdf0e10cSrcweir  * sind fuer den Blocksatz zustaendig und ermitteln die Anzahl der Blanks
625cdf0e10cSrcweir  * und den daraus resultierenden zusaetzlichen Zwischenraum
626cdf0e10cSrcweir  *************************************************************************/
627cdf0e10cSrcweir 
GetSpaceCnt(const SwTxtSizeInfo & rInf,xub_StrLen & rCharCnt) const628cdf0e10cSrcweir xub_StrLen SwTxtPortion::GetSpaceCnt( const SwTxtSizeInfo &rInf,
629cdf0e10cSrcweir                                       xub_StrLen& rCharCnt ) const
630cdf0e10cSrcweir {
631cdf0e10cSrcweir     xub_StrLen nCnt = 0;
632cdf0e10cSrcweir     xub_StrLen nPos = 0;
633cdf0e10cSrcweir     if ( InExpGrp() )
634cdf0e10cSrcweir     {
635cdf0e10cSrcweir         if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
636cdf0e10cSrcweir         {
637cdf0e10cSrcweir             // Bei OnWin() wird anstatt eines Leerstrings gern mal ein Blank
638cdf0e10cSrcweir             // zurueckgeliefert, das koennen wir hier aber gar nicht gebrauchen
639cdf0e10cSrcweir             sal_Bool bOldOnWin = rInf.OnWin();
640cdf0e10cSrcweir             ((SwTxtSizeInfo &)rInf).SetOnWin( sal_False );
641cdf0e10cSrcweir 
642cdf0e10cSrcweir             XubString aStr( aEmptyStr );
643cdf0e10cSrcweir             GetExpTxt( rInf, aStr );
644cdf0e10cSrcweir             ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
645cdf0e10cSrcweir 
646cdf0e10cSrcweir             nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
647cdf0e10cSrcweir             nPos = aStr.Len();
648cdf0e10cSrcweir         }
649cdf0e10cSrcweir     }
650cdf0e10cSrcweir     else if( !IsDropPortion() )
651cdf0e10cSrcweir     {
652cdf0e10cSrcweir         nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
653cdf0e10cSrcweir         nPos = GetLen();
654cdf0e10cSrcweir     }
655cdf0e10cSrcweir     rCharCnt = rCharCnt + nPos;
656cdf0e10cSrcweir     return nCnt;
657cdf0e10cSrcweir }
658cdf0e10cSrcweir 
CalcSpacing(long nSpaceAdd,const SwTxtSizeInfo & rInf) const659cdf0e10cSrcweir long SwTxtPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const
660cdf0e10cSrcweir {
661cdf0e10cSrcweir     xub_StrLen nCnt = 0;
662cdf0e10cSrcweir 
663cdf0e10cSrcweir     if ( InExpGrp() )
664cdf0e10cSrcweir     {
665cdf0e10cSrcweir         if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
666cdf0e10cSrcweir         {
667cdf0e10cSrcweir             // Bei OnWin() wird anstatt eines Leerstrings gern mal ein Blank
668cdf0e10cSrcweir             // zurueckgeliefert, das koennen wir hier aber gar nicht gebrauchen
669cdf0e10cSrcweir             sal_Bool bOldOnWin = rInf.OnWin();
670cdf0e10cSrcweir             ((SwTxtSizeInfo &)rInf).SetOnWin( sal_False );
671cdf0e10cSrcweir 
672cdf0e10cSrcweir             XubString aStr( aEmptyStr );
673cdf0e10cSrcweir             GetExpTxt( rInf, aStr );
674cdf0e10cSrcweir             ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
675cdf0e10cSrcweir             if( nSpaceAdd > 0 )
676cdf0e10cSrcweir                 nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
677cdf0e10cSrcweir             else
678cdf0e10cSrcweir             {
679cdf0e10cSrcweir                 nSpaceAdd = -nSpaceAdd;
680cdf0e10cSrcweir                 nCnt = aStr.Len();
681cdf0e10cSrcweir             }
682cdf0e10cSrcweir         }
683cdf0e10cSrcweir     }
684cdf0e10cSrcweir     else if( !IsDropPortion() )
685cdf0e10cSrcweir     {
686cdf0e10cSrcweir         if( nSpaceAdd > 0 )
687cdf0e10cSrcweir             nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
688cdf0e10cSrcweir         else
689cdf0e10cSrcweir         {
690cdf0e10cSrcweir             nSpaceAdd = -nSpaceAdd;
691cdf0e10cSrcweir             nCnt = GetLen();
692cdf0e10cSrcweir             SwLinePortion* pPor = GetPortion();
693cdf0e10cSrcweir 
694cdf0e10cSrcweir             // we do not want an extra space in front of margin portions
695cdf0e10cSrcweir             if ( nCnt )
696cdf0e10cSrcweir             {
697cdf0e10cSrcweir                 while ( pPor && !pPor->Width() && ! pPor->IsHolePortion() )
698cdf0e10cSrcweir                     pPor = pPor->GetPortion();
699cdf0e10cSrcweir 
700cdf0e10cSrcweir                 if ( !pPor || pPor->InFixMargGrp() || pPor->IsHolePortion() )
701cdf0e10cSrcweir                     --nCnt;
702cdf0e10cSrcweir             }
703cdf0e10cSrcweir         }
704cdf0e10cSrcweir     }
705cdf0e10cSrcweir 
706cdf0e10cSrcweir     return nCnt * nSpaceAdd / SPACING_PRECISION_FACTOR;
707cdf0e10cSrcweir }
708cdf0e10cSrcweir 
709cdf0e10cSrcweir /*************************************************************************
710cdf0e10cSrcweir  *              virtual SwTxtPortion::HandlePortion()
711cdf0e10cSrcweir  *************************************************************************/
712cdf0e10cSrcweir 
HandlePortion(SwPortionHandler & rPH) const713cdf0e10cSrcweir void SwTxtPortion::HandlePortion( SwPortionHandler& rPH ) const
714cdf0e10cSrcweir {
715cdf0e10cSrcweir     rPH.Text( GetLen(), GetWhichPor() );
716cdf0e10cSrcweir }
717cdf0e10cSrcweir 
71869a74367SOliver-Rainer Wittmann 
SwTxtInputFldPortion()71969a74367SOliver-Rainer Wittmann SwTxtInputFldPortion::SwTxtInputFldPortion()
72069a74367SOliver-Rainer Wittmann     : SwTxtPortion()
72169a74367SOliver-Rainer Wittmann     , mbContainsInputFieldStart( false )
72269a74367SOliver-Rainer Wittmann     , mbContainsInputFieldEnd( false )
72369a74367SOliver-Rainer Wittmann {
72469a74367SOliver-Rainer Wittmann     SetWhichPor( POR_INPUTFLD );
72569a74367SOliver-Rainer Wittmann }
72669a74367SOliver-Rainer Wittmann 
72769a74367SOliver-Rainer Wittmann 
Format(SwTxtFormatInfo & rInf)72869a74367SOliver-Rainer Wittmann sal_Bool SwTxtInputFldPortion::Format( SwTxtFormatInfo &rInf )
72969a74367SOliver-Rainer Wittmann {
73069a74367SOliver-Rainer Wittmann     mbContainsInputFieldStart =
73169a74367SOliver-Rainer Wittmann         rInf.GetChar( rInf.GetIdx() ) == CH_TXT_ATR_INPUTFIELDSTART;
73269a74367SOliver-Rainer Wittmann     mbContainsInputFieldEnd =
73369a74367SOliver-Rainer Wittmann         rInf.GetChar( rInf.GetIdx() + rInf.GetLen() - 1 ) == CH_TXT_ATR_INPUTFIELDEND;
73469a74367SOliver-Rainer Wittmann 
73569a74367SOliver-Rainer Wittmann     sal_Bool bRet = sal_False;
73669a74367SOliver-Rainer Wittmann     if ( rInf.GetLen() == 1
73769a74367SOliver-Rainer Wittmann          && ( mbContainsInputFieldStart || mbContainsInputFieldEnd ) )
73869a74367SOliver-Rainer Wittmann     {
73969a74367SOliver-Rainer Wittmann         Width( 0 );
74069a74367SOliver-Rainer Wittmann     }
74169a74367SOliver-Rainer Wittmann     else
74269a74367SOliver-Rainer Wittmann     {
74369a74367SOliver-Rainer Wittmann         SwTxtSlot aFormatTxt( &rInf, this, true, true, 0 );
74469a74367SOliver-Rainer Wittmann         if ( rInf.GetLen() == 0 )
74569a74367SOliver-Rainer Wittmann         {
74669a74367SOliver-Rainer Wittmann             Width( 0 );
74769a74367SOliver-Rainer Wittmann         }
74869a74367SOliver-Rainer Wittmann         else
74969a74367SOliver-Rainer Wittmann         {
750*b8d31f9fSOliver-Rainer Wittmann             const xub_StrLen nFormerLineStart = rInf.GetLineStart();
751*b8d31f9fSOliver-Rainer Wittmann             if ( !mbContainsInputFieldStart )
752*b8d31f9fSOliver-Rainer Wittmann             {
753*b8d31f9fSOliver-Rainer Wittmann                 rInf.SetLineStart( 0 );
754*b8d31f9fSOliver-Rainer Wittmann             }
755*b8d31f9fSOliver-Rainer Wittmann 
75669a74367SOliver-Rainer Wittmann             bRet = SwTxtPortion::Format( rInf );
75769a74367SOliver-Rainer Wittmann 
75869a74367SOliver-Rainer Wittmann             if ( mbContainsInputFieldEnd )
75969a74367SOliver-Rainer Wittmann             {
76069a74367SOliver-Rainer Wittmann                 // adjust portion length accordingly, if complete text fits into the portion
76169a74367SOliver-Rainer Wittmann                 if ( GetLen() == rInf.GetLen() )
76269a74367SOliver-Rainer Wittmann                 {
76369a74367SOliver-Rainer Wittmann                     SetLen( GetLen() + 1 );
76469a74367SOliver-Rainer Wittmann                 }
76569a74367SOliver-Rainer Wittmann             }
76669a74367SOliver-Rainer Wittmann 
76769a74367SOliver-Rainer Wittmann             if ( mbContainsInputFieldStart )
76869a74367SOliver-Rainer Wittmann             {
76969a74367SOliver-Rainer Wittmann                 // adjust portion length accordingly
77069a74367SOliver-Rainer Wittmann                 SetLen( GetLen() + 1 );
77169a74367SOliver-Rainer Wittmann             }
772*b8d31f9fSOliver-Rainer Wittmann             else
773*b8d31f9fSOliver-Rainer Wittmann             {
774*b8d31f9fSOliver-Rainer Wittmann                 rInf.SetLineStart( nFormerLineStart );
775*b8d31f9fSOliver-Rainer Wittmann             }
77669a74367SOliver-Rainer Wittmann         }
77769a74367SOliver-Rainer Wittmann     }
77869a74367SOliver-Rainer Wittmann 
77969a74367SOliver-Rainer Wittmann     return bRet;
78069a74367SOliver-Rainer Wittmann }
78169a74367SOliver-Rainer Wittmann 
Paint(const SwTxtPaintInfo & rInf) const78269a74367SOliver-Rainer Wittmann void SwTxtInputFldPortion::Paint( const SwTxtPaintInfo &rInf ) const
78369a74367SOliver-Rainer Wittmann {
78469a74367SOliver-Rainer Wittmann     if ( Width() )
78569a74367SOliver-Rainer Wittmann     {
78669a74367SOliver-Rainer Wittmann         rInf.DrawViewOpt( *this, POR_INPUTFLD );
78769a74367SOliver-Rainer Wittmann         static sal_Char sSpace = ' ';
78869a74367SOliver-Rainer Wittmann         SwTxtSlot aPaintTxt( &rInf, this, true, true,
78969a74367SOliver-Rainer Wittmann                             ContainsOnlyDummyChars() ? &sSpace : 0 );
79069a74367SOliver-Rainer Wittmann         SwTxtPortion::Paint( rInf );
79169a74367SOliver-Rainer Wittmann     }
79269a74367SOliver-Rainer Wittmann }
79369a74367SOliver-Rainer Wittmann 
GetExpTxt(const SwTxtSizeInfo & rInf,XubString & rTxt) const79469a74367SOliver-Rainer Wittmann sal_Bool SwTxtInputFldPortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
79569a74367SOliver-Rainer Wittmann {
79669a74367SOliver-Rainer Wittmann     xub_StrLen nIdx = rInf.GetIdx();
79769a74367SOliver-Rainer Wittmann     xub_StrLen nLen = rInf.GetLen();
79869a74367SOliver-Rainer Wittmann     if ( rInf.GetChar( rInf.GetIdx() ) == CH_TXT_ATR_INPUTFIELDSTART )
79969a74367SOliver-Rainer Wittmann     {
80069a74367SOliver-Rainer Wittmann         ++nIdx;
80169a74367SOliver-Rainer Wittmann         --nLen;
80269a74367SOliver-Rainer Wittmann     }
80369a74367SOliver-Rainer Wittmann     if ( rInf.GetChar( rInf.GetIdx() + rInf.GetLen() - 1 ) == CH_TXT_ATR_INPUTFIELDEND )
80469a74367SOliver-Rainer Wittmann     {
80569a74367SOliver-Rainer Wittmann         --nLen;
80669a74367SOliver-Rainer Wittmann     }
80769a74367SOliver-Rainer Wittmann     rTxt = rInf.GetTxt().Copy( nIdx, nLen );
80869a74367SOliver-Rainer Wittmann 
80969a74367SOliver-Rainer Wittmann     return sal_True;
81069a74367SOliver-Rainer Wittmann }
81169a74367SOliver-Rainer Wittmann 
81269a74367SOliver-Rainer Wittmann 
GetTxtSize(const SwTxtSizeInfo & rInf) const81369a74367SOliver-Rainer Wittmann SwPosSize SwTxtInputFldPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
81469a74367SOliver-Rainer Wittmann {
81569a74367SOliver-Rainer Wittmann     SwTxtSlot aFormatTxt( &rInf, this, true, false, 0 );
81669a74367SOliver-Rainer Wittmann     if ( rInf.GetLen() == 0 )
81769a74367SOliver-Rainer Wittmann     {
81869a74367SOliver-Rainer Wittmann         return SwPosSize( 0, 0 );
81969a74367SOliver-Rainer Wittmann     }
82069a74367SOliver-Rainer Wittmann 
82169a74367SOliver-Rainer Wittmann     return rInf.GetTxtSize();
82269a74367SOliver-Rainer Wittmann }
82369a74367SOliver-Rainer Wittmann 
82469a74367SOliver-Rainer Wittmann 
GetViewWidth(const SwTxtSizeInfo & rInf) const82569a74367SOliver-Rainer Wittmann KSHORT SwTxtInputFldPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
82669a74367SOliver-Rainer Wittmann {
82769a74367SOliver-Rainer Wittmann     if( !Width()
82869a74367SOliver-Rainer Wittmann         && ContainsOnlyDummyChars()
82969a74367SOliver-Rainer Wittmann         && !rInf.GetOpt().IsPagePreview()
83069a74367SOliver-Rainer Wittmann         && !rInf.GetOpt().IsReadonly()
83169a74367SOliver-Rainer Wittmann         && SwViewOption::IsFieldShadings() )
83269a74367SOliver-Rainer Wittmann     {
83369a74367SOliver-Rainer Wittmann         return rInf.GetTxtSize( ' ' ).Width();
83469a74367SOliver-Rainer Wittmann     }
83569a74367SOliver-Rainer Wittmann 
83669a74367SOliver-Rainer Wittmann     return SwTxtPortion::GetViewWidth( rInf );
83769a74367SOliver-Rainer Wittmann }
83869a74367SOliver-Rainer Wittmann 
ContainsOnlyDummyChars() const83969a74367SOliver-Rainer Wittmann bool SwTxtInputFldPortion::ContainsOnlyDummyChars() const
84069a74367SOliver-Rainer Wittmann {
84169a74367SOliver-Rainer Wittmann     return GetLen() <= 2
84269a74367SOliver-Rainer Wittmann            && mbContainsInputFieldStart
84369a74367SOliver-Rainer Wittmann            && mbContainsInputFieldEnd;
84469a74367SOliver-Rainer Wittmann }
84569a74367SOliver-Rainer Wittmann 
846cdf0e10cSrcweir /*************************************************************************
847cdf0e10cSrcweir  *                      class SwHolePortion
848cdf0e10cSrcweir  *************************************************************************/
849cdf0e10cSrcweir 
850cdf0e10cSrcweir 
851cdf0e10cSrcweir 
SwHolePortion(const SwTxtPortion & rPor)852cdf0e10cSrcweir SwHolePortion::SwHolePortion( const SwTxtPortion &rPor )
853cdf0e10cSrcweir     : nBlankWidth( 0 )
854cdf0e10cSrcweir {
855cdf0e10cSrcweir     SetLen( 1 );
856cdf0e10cSrcweir     Height( rPor.Height() );
857cdf0e10cSrcweir     SetAscent( rPor.GetAscent() );
858cdf0e10cSrcweir     SetWhichPor( POR_HOLE );
859cdf0e10cSrcweir }
860cdf0e10cSrcweir 
Compress()861cdf0e10cSrcweir SwLinePortion *SwHolePortion::Compress() { return this; }
862cdf0e10cSrcweir 
863cdf0e10cSrcweir /*************************************************************************
864cdf0e10cSrcweir  *               virtual SwHolePortion::Paint()
865cdf0e10cSrcweir  *************************************************************************/
866cdf0e10cSrcweir 
867cdf0e10cSrcweir 
868cdf0e10cSrcweir 
Paint(const SwTxtPaintInfo & rInf) const869cdf0e10cSrcweir void SwHolePortion::Paint( const SwTxtPaintInfo &rInf ) const
870cdf0e10cSrcweir {
871e272a9c9SHerbert Dürr     if( !rInf.GetOut() )
872e272a9c9SHerbert Dürr         return;
873e272a9c9SHerbert Dürr 
874e272a9c9SHerbert Dürr     // #i16816# export stuff only needed for tagged pdf support
875e272a9c9SHerbert Dürr     const vcl::PDFExtOutDevData* pPDFExt = dynamic_cast<const vcl::PDFExtOutDevData*>( rInf.GetOut()->GetExtOutDevData() );
876e272a9c9SHerbert Dürr     if( !pPDFExt || !pPDFExt->GetIsExportTaggedPDF())
877e272a9c9SHerbert Dürr         return;
878e272a9c9SHerbert Dürr 
879e272a9c9SHerbert Dürr     // #i68503# the hole must have no decoration for a consistent visual appearance
880e272a9c9SHerbert Dürr     const SwFont* pOrigFont = rInf.GetFont();
881e272a9c9SHerbert Dürr     SwFont* pHoleFont = NULL;
882e272a9c9SHerbert Dürr     SwFontSave* pFontSave = NULL;
883e272a9c9SHerbert Dürr     if( pOrigFont->GetUnderline() != UNDERLINE_NONE
884e272a9c9SHerbert Dürr     ||  pOrigFont->GetOverline() != UNDERLINE_NONE
885e272a9c9SHerbert Dürr     ||  pOrigFont->GetStrikeout() != STRIKEOUT_NONE )
886cdf0e10cSrcweir     {
887e272a9c9SHerbert Dürr         pHoleFont = new SwFont( *pOrigFont );
888e272a9c9SHerbert Dürr         pHoleFont->SetUnderline( UNDERLINE_NONE );
889e272a9c9SHerbert Dürr         pHoleFont->SetOverline( UNDERLINE_NONE );
890e272a9c9SHerbert Dürr         pHoleFont->SetStrikeout( STRIKEOUT_NONE );
891e272a9c9SHerbert Dürr         pFontSave = new SwFontSave( rInf, pHoleFont );
892e272a9c9SHerbert Dürr     }
893e272a9c9SHerbert Dürr 
894cdf0e10cSrcweir     const XubString aTxt( ' ' );
895cdf0e10cSrcweir     rInf.DrawText( aTxt, *this, 0, 1, false );
896e272a9c9SHerbert Dürr 
897e272a9c9SHerbert Dürr     delete pFontSave;
898e272a9c9SHerbert Dürr     delete pHoleFont;
899cdf0e10cSrcweir }
900cdf0e10cSrcweir 
901cdf0e10cSrcweir /*************************************************************************
902cdf0e10cSrcweir  *                 virtual SwHolePortion::Format()
903cdf0e10cSrcweir  *************************************************************************/
904cdf0e10cSrcweir 
905cdf0e10cSrcweir 
906cdf0e10cSrcweir 
Format(SwTxtFormatInfo & rInf)907cdf0e10cSrcweir sal_Bool SwHolePortion::Format( SwTxtFormatInfo &rInf )
908cdf0e10cSrcweir {
909cdf0e10cSrcweir     return rInf.IsFull() || rInf.X() >= rInf.Width();
910cdf0e10cSrcweir }
911cdf0e10cSrcweir 
912cdf0e10cSrcweir /*************************************************************************
913cdf0e10cSrcweir  *              virtual SwHolePortion::HandlePortion()
914cdf0e10cSrcweir  *************************************************************************/
915cdf0e10cSrcweir 
HandlePortion(SwPortionHandler & rPH) const916cdf0e10cSrcweir void SwHolePortion::HandlePortion( SwPortionHandler& rPH ) const
917cdf0e10cSrcweir {
918cdf0e10cSrcweir     rPH.Text( GetLen(), GetWhichPor() );
919cdf0e10cSrcweir }
920cdf0e10cSrcweir 
Paint(const SwTxtPaintInfo &) const921cdf0e10cSrcweir void SwFieldMarkPortion::Paint( const SwTxtPaintInfo & /*rInf*/) const
922cdf0e10cSrcweir {
923cdf0e10cSrcweir     // These shouldn't be painted!
924cdf0e10cSrcweir     //SwTxtPortion::Paint(rInf);
925cdf0e10cSrcweir }
926cdf0e10cSrcweir 
Format(SwTxtFormatInfo &)927cdf0e10cSrcweir sal_Bool SwFieldMarkPortion::Format( SwTxtFormatInfo & )
928cdf0e10cSrcweir {
929cdf0e10cSrcweir     sal_Bool ret=0;
930cdf0e10cSrcweir     Width(0);
931cdf0e10cSrcweir     return ret;
932cdf0e10cSrcweir }
933cdf0e10cSrcweir 
934cdf0e10cSrcweir namespace {
getCurrentListIndex(IFieldmark * pBM,::rtl::OUString * io_pCurrentText=NULL)935cdf0e10cSrcweir     static sal_Int32 getCurrentListIndex( IFieldmark* pBM,
936cdf0e10cSrcweir             ::rtl::OUString* io_pCurrentText = NULL )
937cdf0e10cSrcweir     {
938cdf0e10cSrcweir         const IFieldmark::parameter_map_t* const pParameters = pBM->GetParameters();
939cdf0e10cSrcweir         sal_Int32 nCurrentIdx = 0;
940cdf0e10cSrcweir         const IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find(::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN_RESULT));
941cdf0e10cSrcweir         if(pResult != pParameters->end())
942cdf0e10cSrcweir             pResult->second >>= nCurrentIdx;
943cdf0e10cSrcweir         if(io_pCurrentText)
944cdf0e10cSrcweir         {
945cdf0e10cSrcweir             const IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN_LISTENTRY));
946cdf0e10cSrcweir             if(pListEntries != pParameters->end())
947cdf0e10cSrcweir             {
948cdf0e10cSrcweir                 uno::Sequence< ::rtl::OUString > vListEntries;
949cdf0e10cSrcweir                 pListEntries->second >>= vListEntries;
950cdf0e10cSrcweir                 if(nCurrentIdx < vListEntries.getLength())
951cdf0e10cSrcweir                     *io_pCurrentText = vListEntries[nCurrentIdx];
952cdf0e10cSrcweir             }
953cdf0e10cSrcweir         }
954cdf0e10cSrcweir         return nCurrentIdx;
955cdf0e10cSrcweir     }
956cdf0e10cSrcweir }
957cdf0e10cSrcweir 
958cdf0e10cSrcweir //FIXME Fieldbk
Paint(const SwTxtPaintInfo & rInf) const959cdf0e10cSrcweir void SwFieldFormPortion::Paint( const SwTxtPaintInfo& rInf ) const
960cdf0e10cSrcweir {
961cdf0e10cSrcweir     SwTxtNode* pNd = const_cast<SwTxtNode*>(rInf.GetTxtFrm()->GetTxtNode());
962cdf0e10cSrcweir     const SwDoc *doc=pNd->GetDoc();
963cdf0e10cSrcweir     SwIndex aIndex( pNd, rInf.GetIdx() );
964cdf0e10cSrcweir     SwPosition aPosition(*pNd, aIndex);
965cdf0e10cSrcweir 
966cdf0e10cSrcweir     IFieldmark* pBM = doc->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition );
967cdf0e10cSrcweir 
968cdf0e10cSrcweir     OSL_ENSURE( pBM,
969cdf0e10cSrcweir         "SwFieldFormPortion::Paint(..)"
970cdf0e10cSrcweir         " - Where is my form field bookmark???");
971cdf0e10cSrcweir 
972cdf0e10cSrcweir     if ( pBM != NULL )
973cdf0e10cSrcweir     {
974cdf0e10cSrcweir         if ( pBM->GetFieldname( ).equalsAscii( ODF_FORMCHECKBOX ) )
975cdf0e10cSrcweir         { // a checkbox...
976cdf0e10cSrcweir             ICheckboxFieldmark* pCheckboxFm = dynamic_cast< ICheckboxFieldmark* >(pBM);
977cdf0e10cSrcweir             bool checked = pCheckboxFm->IsChecked();
978cdf0e10cSrcweir             rInf.DrawCheckBox(*this, checked);
979cdf0e10cSrcweir         }
980cdf0e10cSrcweir         else if ( pBM->GetFieldname( ).equalsAscii(  ODF_FORMDROPDOWN ) )
981cdf0e10cSrcweir         { // a list...
982cdf0e10cSrcweir             rtl::OUString aTxt;
983cdf0e10cSrcweir             rInf.DrawViewOpt( *this, POR_FLD );
984cdf0e10cSrcweir             rInf.DrawText( aTxt, *this, 0, 0/*aTxt.getLength()*/, false );
985cdf0e10cSrcweir         }
986cdf0e10cSrcweir         else
987cdf0e10cSrcweir         {
988cdf0e10cSrcweir             assert(0); // unknown type...
989cdf0e10cSrcweir         }
990cdf0e10cSrcweir     }
991cdf0e10cSrcweir }
992cdf0e10cSrcweir 
Format(SwTxtFormatInfo & rInf)993cdf0e10cSrcweir sal_Bool SwFieldFormPortion::Format( SwTxtFormatInfo & rInf )
994cdf0e10cSrcweir {
995cdf0e10cSrcweir     sal_Bool ret = 0;
996cdf0e10cSrcweir     SwTxtNode *pNd = const_cast < SwTxtNode * >( rInf.GetTxtFrm(  )->GetTxtNode(  ) );
997cdf0e10cSrcweir     const SwDoc *doc = pNd->GetDoc(  );
998cdf0e10cSrcweir     SwIndex aIndex( pNd, rInf.GetIdx(  ) );
999cdf0e10cSrcweir     SwPosition aPosition( *pNd, aIndex );
1000cdf0e10cSrcweir     IFieldmark *pBM = doc->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition );
1001cdf0e10cSrcweir     ASSERT( pBM != NULL, "Where is my form field bookmark???" );
1002cdf0e10cSrcweir     if ( pBM != NULL )
1003cdf0e10cSrcweir     {
1004cdf0e10cSrcweir         if ( pBM->GetFieldname( ).equalsAscii( ODF_FORMCHECKBOX ) )
1005cdf0e10cSrcweir         {
1006cdf0e10cSrcweir             Width( rInf.GetTxtHeight(  ) );
1007cdf0e10cSrcweir             Height( rInf.GetTxtHeight(  ) );
1008cdf0e10cSrcweir             SetAscent( rInf.GetAscent(  ) );
1009cdf0e10cSrcweir         }
1010cdf0e10cSrcweir         else if ( pBM->GetFieldname( ).equalsAscii( ODF_FORMDROPDOWN ) )
1011cdf0e10cSrcweir         {
1012cdf0e10cSrcweir             ::rtl::OUString aTxt;
1013cdf0e10cSrcweir             getCurrentListIndex( pBM, &aTxt );
1014cdf0e10cSrcweir             SwPosSize aPosSize = rInf.GetTxtSize( aTxt );
1015cdf0e10cSrcweir             Width( aPosSize.Width(  ) );
1016cdf0e10cSrcweir             Height( aPosSize.Height(  ) );
1017cdf0e10cSrcweir             SetAscent( rInf.GetAscent(  ) );
1018cdf0e10cSrcweir         }
1019cdf0e10cSrcweir         else
1020cdf0e10cSrcweir         {
1021cdf0e10cSrcweir             assert( 0 );        // unknown type...
1022cdf0e10cSrcweir         }
1023cdf0e10cSrcweir     }
1024cdf0e10cSrcweir     return ret;
1025cdf0e10cSrcweir }
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir 
1028