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