xref: /aoo42x/main/sw/source/core/text/itratr.cxx (revision 86e1cf34)
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
10efeef26fSAndrew Rist  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12efeef26fSAndrew Rist  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19efeef26fSAndrew Rist  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <hintids.hxx>
29cdf0e10cSrcweir #include <editeng/charscaleitem.hxx>
30cdf0e10cSrcweir #include <txtatr.hxx>
31cdf0e10cSrcweir #include <sfx2/printer.hxx>
32cdf0e10cSrcweir #include <svx/svdobj.hxx>
33cdf0e10cSrcweir #include <vcl/window.hxx>
34cdf0e10cSrcweir #include <vcl/svapp.hxx>
35cdf0e10cSrcweir #include <fmtanchr.hxx>
36cdf0e10cSrcweir #include <fmtfsize.hxx>
37cdf0e10cSrcweir #include <fmtornt.hxx>
38cdf0e10cSrcweir #include <fmtflcnt.hxx>
39cdf0e10cSrcweir #include <fmtcntnt.hxx>
40cdf0e10cSrcweir #include <fmtftn.hxx>
41cdf0e10cSrcweir #include <frmatr.hxx>
42cdf0e10cSrcweir #include <frmfmt.hxx>
43cdf0e10cSrcweir #include <fmtfld.hxx>
44cdf0e10cSrcweir #include <doc.hxx>
45cdf0e10cSrcweir #include <viewsh.hxx>	// ViewShell
46cdf0e10cSrcweir #include <rootfrm.hxx>
47cdf0e10cSrcweir #include <docary.hxx>
48cdf0e10cSrcweir #include <ndtxt.hxx>
49cdf0e10cSrcweir #include <dcontact.hxx>
50cdf0e10cSrcweir #include <fldbas.hxx>      // SwField
51cdf0e10cSrcweir #include <pam.hxx>         // SwPosition		(lcl_MinMaxNode)
52cdf0e10cSrcweir #include <itratr.hxx>
53cdf0e10cSrcweir #include <htmltbl.hxx>
54cdf0e10cSrcweir #include <swtable.hxx>
55cdf0e10cSrcweir #include <redlnitr.hxx>
56cdf0e10cSrcweir #include <fmtsrnd.hxx>
57cdf0e10cSrcweir #include <itrtxt.hxx>
58cdf0e10cSrcweir #include <breakit.hxx>
59cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hpp>
60cdf0e10cSrcweir #include <com/sun/star/i18n/ScriptType.hdl>
61cdf0e10cSrcweir #include <editeng/lrspitem.hxx>
62cdf0e10cSrcweir #include <switerator.hxx>
63cdf0e10cSrcweir 
64cdf0e10cSrcweir using namespace ::com::sun::star::i18n;
65cdf0e10cSrcweir using namespace ::com::sun::star;
66cdf0e10cSrcweir 
67cdf0e10cSrcweir /*************************************************************************
68cdf0e10cSrcweir  *						SwAttrIter::Chg()
69cdf0e10cSrcweir  *************************************************************************/
70cdf0e10cSrcweir 
Chg(SwTxtAttr * pHt)71cdf0e10cSrcweir void SwAttrIter::Chg( SwTxtAttr *pHt )
72cdf0e10cSrcweir {
73cdf0e10cSrcweir     ASSERT( pHt && pFnt, "No attribute of font available for change");
74cdf0e10cSrcweir     if( pRedln && pRedln->IsOn() )
75cdf0e10cSrcweir         pRedln->ChangeTxtAttr( pFnt, *pHt, sal_True );
76cdf0e10cSrcweir 	else
77cdf0e10cSrcweir         aAttrHandler.PushAndChg( *pHt, *pFnt );
78cdf0e10cSrcweir 	nChgCnt++;
79cdf0e10cSrcweir }
80cdf0e10cSrcweir 
81cdf0e10cSrcweir /*************************************************************************
82cdf0e10cSrcweir  *						SwAttrIter::Rst()
83cdf0e10cSrcweir  *************************************************************************/
84cdf0e10cSrcweir 
Rst(SwTxtAttr * pHt)85cdf0e10cSrcweir void SwAttrIter::Rst( SwTxtAttr *pHt )
86cdf0e10cSrcweir {
87cdf0e10cSrcweir     ASSERT( pHt && pFnt, "No attribute of font available for reset");
88cdf0e10cSrcweir     // get top from stack after removing pHt
89cdf0e10cSrcweir     if( pRedln && pRedln->IsOn() )
90cdf0e10cSrcweir         pRedln->ChangeTxtAttr( pFnt, *pHt, sal_False );
91cdf0e10cSrcweir 	else
92cdf0e10cSrcweir         aAttrHandler.PopAndChg( *pHt, *pFnt );
93cdf0e10cSrcweir 	nChgCnt--;
94cdf0e10cSrcweir }
95cdf0e10cSrcweir 
96cdf0e10cSrcweir /*************************************************************************
97cdf0e10cSrcweir  *				virtual SwAttrIter::~SwAttrIter()
98cdf0e10cSrcweir  *************************************************************************/
99cdf0e10cSrcweir 
~SwAttrIter()100cdf0e10cSrcweir SwAttrIter::~SwAttrIter()
101cdf0e10cSrcweir {
102cdf0e10cSrcweir 	delete pRedln;
103cdf0e10cSrcweir 	delete pFnt;
104cdf0e10cSrcweir }
105cdf0e10cSrcweir 
106cdf0e10cSrcweir /*************************************************************************
107cdf0e10cSrcweir  *						SwAttrIter::GetAttr()
108cdf0e10cSrcweir  *
109cdf0e10cSrcweir  * Liefert fuer eine Position das Attribut, wenn das Attribut genau auf
110cdf0e10cSrcweir  * der Position nPos liegt und kein EndIndex besitzt.
111cdf0e10cSrcweir  * GetAttr() wird fuer Attribute benoetigt, die die Formatierung beeinflussen
112cdf0e10cSrcweir  * sollen, ohne dabei den Inhalt des Strings zu veraendern. Solche "entarteten"
113cdf0e10cSrcweir  * Attribute sind z.B. Felder (die expandierten Text bereit halten) und
114cdf0e10cSrcweir  * zeilengebundene Frames. Um Mehrdeutigkeiten zwischen verschiedenen
115cdf0e10cSrcweir  * solcher Attribute zu vermeiden, werden beim Anlegen eines Attributs
116cdf0e10cSrcweir  * an der Startposition ein Sonderzeichen in den String einfuegt.
117cdf0e10cSrcweir  * Der Formatierer stoesst auf das Sonderzeichen und holt sich per
118cdf0e10cSrcweir  * GetAttr() das entartete Attribut.
119cdf0e10cSrcweir  *************************************************************************/
120cdf0e10cSrcweir 
GetAttr(const xub_StrLen nPosition) const121cdf0e10cSrcweir SwTxtAttr *SwAttrIter::GetAttr( const xub_StrLen nPosition ) const
122cdf0e10cSrcweir {
123cdf0e10cSrcweir     return (m_pTxtNode) ? m_pTxtNode->GetTxtAttrForCharAt(nPosition) : 0;
124cdf0e10cSrcweir }
125cdf0e10cSrcweir 
126cdf0e10cSrcweir /*************************************************************************
127cdf0e10cSrcweir  *						  SwAttrIter::SeekAndChg()
128cdf0e10cSrcweir  *************************************************************************/
129cdf0e10cSrcweir 
SeekAndChgAttrIter(const xub_StrLen nNewPos,OutputDevice * pOut)130cdf0e10cSrcweir sal_Bool SwAttrIter::SeekAndChgAttrIter( const xub_StrLen nNewPos, OutputDevice* pOut )
131cdf0e10cSrcweir {
132cdf0e10cSrcweir 	sal_Bool bChg = nStartIndex && nNewPos == nPos ? pFnt->IsFntChg() : Seek( nNewPos );
133cdf0e10cSrcweir 	if ( pLastOut != pOut )
134cdf0e10cSrcweir 	{
135cdf0e10cSrcweir 		pLastOut = pOut;
136cdf0e10cSrcweir 		pFnt->SetFntChg( sal_True );
137cdf0e10cSrcweir 		bChg = sal_True;
138cdf0e10cSrcweir 	}
139cdf0e10cSrcweir 	if( bChg )
140cdf0e10cSrcweir 	{
141cdf0e10cSrcweir 		// wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
142cdf0e10cSrcweir 		// des gewuenschten Fonts ...
143cdf0e10cSrcweir 		if ( !nChgCnt && !nPropFont )
144cdf0e10cSrcweir 			pFnt->SetMagic( aMagicNo[ pFnt->GetActual() ],
145cdf0e10cSrcweir 				aFntIdx[ pFnt->GetActual() ], pFnt->GetActual() );
146cdf0e10cSrcweir         pFnt->ChgPhysFnt( pShell, *pOut );
147cdf0e10cSrcweir 	}
148cdf0e10cSrcweir 	return bChg;
149cdf0e10cSrcweir }
150cdf0e10cSrcweir 
IsSymbol(const xub_StrLen nNewPos)151cdf0e10cSrcweir sal_Bool SwAttrIter::IsSymbol( const xub_StrLen nNewPos )
152cdf0e10cSrcweir {
153cdf0e10cSrcweir 	Seek( nNewPos );
154cdf0e10cSrcweir 	if ( !nChgCnt && !nPropFont )
155cdf0e10cSrcweir 		pFnt->SetMagic( aMagicNo[ pFnt->GetActual() ],
156cdf0e10cSrcweir 			aFntIdx[ pFnt->GetActual() ], pFnt->GetActual() );
157cdf0e10cSrcweir 	return pFnt->IsSymbol( pShell );
158cdf0e10cSrcweir }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir /*************************************************************************
161cdf0e10cSrcweir  *						  SwAttrIter::SeekStartAndChg()
162cdf0e10cSrcweir  *************************************************************************/
163cdf0e10cSrcweir 
SeekStartAndChgAttrIter(OutputDevice * pOut,const sal_Bool bParaFont)164cdf0e10cSrcweir sal_Bool SwAttrIter::SeekStartAndChgAttrIter( OutputDevice* pOut, const sal_Bool bParaFont )
165cdf0e10cSrcweir {
166cdf0e10cSrcweir     if ( pRedln && pRedln->ExtOn() )
167cdf0e10cSrcweir         pRedln->LeaveExtend( *pFnt, 0 );
168cdf0e10cSrcweir 
169cdf0e10cSrcweir     // reset font to its original state
170cdf0e10cSrcweir     aAttrHandler.Reset();
171cdf0e10cSrcweir     aAttrHandler.ResetFont( *pFnt );
172cdf0e10cSrcweir 
173cdf0e10cSrcweir     nStartIndex = nEndIndex = nPos = nChgCnt = 0;
174cdf0e10cSrcweir 	if( nPropFont )
175cdf0e10cSrcweir 		pFnt->SetProportion( nPropFont );
176cdf0e10cSrcweir     if( pRedln )
177cdf0e10cSrcweir 	{
178cdf0e10cSrcweir 		pRedln->Clear( pFnt );
179cdf0e10cSrcweir 		if( !bParaFont )
180cdf0e10cSrcweir 			nChgCnt = nChgCnt + pRedln->Seek( *pFnt, 0, STRING_LEN );
181cdf0e10cSrcweir 		else
182cdf0e10cSrcweir 			pRedln->Reset();
183cdf0e10cSrcweir 	}
184cdf0e10cSrcweir 
185cdf0e10cSrcweir 	if ( pHints && !bParaFont )
186cdf0e10cSrcweir 	{
187cdf0e10cSrcweir 		SwTxtAttr *pTxtAttr;
188cdf0e10cSrcweir 		// Solange wir noch nicht am Ende des StartArrays angekommen sind &&
189cdf0e10cSrcweir 		// das TextAttribut an Position 0 beginnt ...
190cdf0e10cSrcweir 		while ( ( nStartIndex < pHints->GetStartCount() ) &&
191cdf0e10cSrcweir 				!(*(pTxtAttr=pHints->GetStart(nStartIndex))->GetStart()) )
192cdf0e10cSrcweir 		{
193cdf0e10cSrcweir 			// oeffne die TextAttribute
194cdf0e10cSrcweir 			Chg( pTxtAttr );
195cdf0e10cSrcweir 			nStartIndex++;
196cdf0e10cSrcweir 		}
197cdf0e10cSrcweir 	}
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 	sal_Bool bChg = pFnt->IsFntChg();
200cdf0e10cSrcweir 	if ( pLastOut != pOut )
201cdf0e10cSrcweir 	{
202cdf0e10cSrcweir 		pLastOut = pOut;
203cdf0e10cSrcweir 		pFnt->SetFntChg( sal_True );
204cdf0e10cSrcweir 		bChg = sal_True;
205cdf0e10cSrcweir 	}
206cdf0e10cSrcweir 	if( bChg )
207cdf0e10cSrcweir 	{
208cdf0e10cSrcweir 		// wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
209cdf0e10cSrcweir 		// des gewuenschten Fonts ...
210cdf0e10cSrcweir 		if ( !nChgCnt && !nPropFont )
211cdf0e10cSrcweir 			pFnt->SetMagic( aMagicNo[ pFnt->GetActual() ],
212cdf0e10cSrcweir 				aFntIdx[ pFnt->GetActual() ], pFnt->GetActual() );
213cdf0e10cSrcweir         pFnt->ChgPhysFnt( pShell, *pOut );
214cdf0e10cSrcweir 	}
215cdf0e10cSrcweir 	return bChg;
216cdf0e10cSrcweir }
217cdf0e10cSrcweir 
218cdf0e10cSrcweir /*************************************************************************
219cdf0e10cSrcweir  *						 SwAttrIter::SeekFwd()
220cdf0e10cSrcweir  *************************************************************************/
221cdf0e10cSrcweir 
222cdf0e10cSrcweir // AMA: Neuer AttrIter Nov 94
223cdf0e10cSrcweir 
SeekFwd(const xub_StrLen nNewPos)224cdf0e10cSrcweir void SwAttrIter::SeekFwd( const xub_StrLen nNewPos )
225cdf0e10cSrcweir {
226cdf0e10cSrcweir 	SwTxtAttr *pTxtAttr;
227cdf0e10cSrcweir 
228cdf0e10cSrcweir 	if ( nStartIndex ) // wenn ueberhaupt schon Attribute geoeffnet wurden...
229cdf0e10cSrcweir 	{
230cdf0e10cSrcweir 		// Schliesse Attr, die z. Z. geoeffnet sind, vor nNewPos+1 aber enden.
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 		// Solange wir noch nicht am Ende des EndArrays angekommen sind &&
233cdf0e10cSrcweir 		// das TextAttribut vor oder an der neuen Position endet ...
234cdf0e10cSrcweir 		while ( ( nEndIndex < pHints->GetEndCount() ) &&
235cdf0e10cSrcweir 				(*(pTxtAttr=pHints->GetEnd(nEndIndex))->GetAnyEnd()<=nNewPos))
236cdf0e10cSrcweir 		{
237cdf0e10cSrcweir 			// schliesse die TextAttribute, deren StartPos vor
238cdf0e10cSrcweir 			// oder an der alten nPos lag, die z.Z. geoeffnet sind.
239cdf0e10cSrcweir 			if (*pTxtAttr->GetStart() <= nPos)	Rst( pTxtAttr );
240cdf0e10cSrcweir 			nEndIndex++;
241cdf0e10cSrcweir 		}
242cdf0e10cSrcweir 	}
243cdf0e10cSrcweir 	else // ueberlies die nicht geoeffneten Enden
244cdf0e10cSrcweir 	{
245cdf0e10cSrcweir 		while ( ( nEndIndex < pHints->GetEndCount() ) &&
246cdf0e10cSrcweir 				(*(pTxtAttr=pHints->GetEnd(nEndIndex))->GetAnyEnd()<=nNewPos))
247cdf0e10cSrcweir 		{
248cdf0e10cSrcweir 			nEndIndex++;
249cdf0e10cSrcweir 		}
250cdf0e10cSrcweir 	}
251cdf0e10cSrcweir 	// Solange wir noch nicht am Ende des StartArrays angekommen sind &&
252cdf0e10cSrcweir 	// das TextAttribut vor oder an der neuen Position beginnt ...
253cdf0e10cSrcweir 	while ( ( nStartIndex < pHints->GetStartCount() ) &&
254cdf0e10cSrcweir 		   (*(pTxtAttr=pHints->GetStart(nStartIndex))->GetStart()<=nNewPos))
255cdf0e10cSrcweir 	{
256cdf0e10cSrcweir 		// oeffne die TextAttribute, deren Ende hinter der neuen Position liegt
257cdf0e10cSrcweir 		if ( *pTxtAttr->GetAnyEnd() > nNewPos )  Chg( pTxtAttr );
258cdf0e10cSrcweir 		nStartIndex++;
259cdf0e10cSrcweir 	}
260cdf0e10cSrcweir 
261cdf0e10cSrcweir }
262cdf0e10cSrcweir 
263cdf0e10cSrcweir /*************************************************************************
264cdf0e10cSrcweir  *						 SwAttrIter::Seek()
265cdf0e10cSrcweir  *************************************************************************/
266cdf0e10cSrcweir 
Seek(const xub_StrLen nNewPos)267cdf0e10cSrcweir sal_Bool SwAttrIter::Seek( const xub_StrLen nNewPos )
268cdf0e10cSrcweir {
269cdf0e10cSrcweir     if ( pRedln && pRedln->ExtOn() )
270cdf0e10cSrcweir         pRedln->LeaveExtend( *pFnt, nNewPos );
271cdf0e10cSrcweir 
272cdf0e10cSrcweir 	if( pHints )
273cdf0e10cSrcweir 	{
274cdf0e10cSrcweir 		if( !nNewPos || nNewPos < nPos )
275cdf0e10cSrcweir 		{
276cdf0e10cSrcweir             if( pRedln )
277cdf0e10cSrcweir 				pRedln->Clear( NULL );
278cdf0e10cSrcweir 
279cdf0e10cSrcweir             // reset font to its original state
280cdf0e10cSrcweir             aAttrHandler.Reset();
281cdf0e10cSrcweir             aAttrHandler.ResetFont( *pFnt );
282cdf0e10cSrcweir 
283cdf0e10cSrcweir             if( nPropFont )
284cdf0e10cSrcweir 				pFnt->SetProportion( nPropFont );
285cdf0e10cSrcweir 			nStartIndex = nEndIndex = nPos = 0;
286cdf0e10cSrcweir 			nChgCnt = 0;
287cdf0e10cSrcweir 
288cdf0e10cSrcweir             // Achtung!
289cdf0e10cSrcweir             // resetting the font here makes it necessary to apply any
290cdf0e10cSrcweir             // changes for extended input directly to the font
291cdf0e10cSrcweir             if ( pRedln && pRedln->ExtOn() )
292cdf0e10cSrcweir             {
293cdf0e10cSrcweir                 pRedln->UpdateExtFont( *pFnt );
294cdf0e10cSrcweir                 ++nChgCnt;
295cdf0e10cSrcweir             }
296cdf0e10cSrcweir 		}
297cdf0e10cSrcweir 		SeekFwd( nNewPos );
298cdf0e10cSrcweir 	}
299cdf0e10cSrcweir 
300cdf0e10cSrcweir     pFnt->SetActual( SwScriptInfo::WhichFont( nNewPos, 0, pScriptInfo ) );
301cdf0e10cSrcweir 
302cdf0e10cSrcweir     if( pRedln )
303cdf0e10cSrcweir 		nChgCnt = nChgCnt + pRedln->Seek( *pFnt, nNewPos, nPos );
304cdf0e10cSrcweir 	nPos = nNewPos;
305cdf0e10cSrcweir 
306cdf0e10cSrcweir 	if( nPropFont )
307cdf0e10cSrcweir 		pFnt->SetProportion( nPropFont );
308cdf0e10cSrcweir 
309cdf0e10cSrcweir 	return pFnt->IsFntChg();
310cdf0e10cSrcweir }
311cdf0e10cSrcweir 
312cdf0e10cSrcweir /*************************************************************************
313cdf0e10cSrcweir  *						SwAttrIter::GetNextAttr()
314cdf0e10cSrcweir  *************************************************************************/
315cdf0e10cSrcweir 
GetNextAttr() const316cdf0e10cSrcweir xub_StrLen SwAttrIter::GetNextAttr( ) const
317cdf0e10cSrcweir {
318cdf0e10cSrcweir 	xub_StrLen nNext = STRING_LEN;
319cdf0e10cSrcweir 	if( pHints )
320cdf0e10cSrcweir 	{
321cdf0e10cSrcweir 		if (pHints->GetStartCount() > nStartIndex) // Gibt es noch Starts?
322cdf0e10cSrcweir 		   nNext = (*pHints->GetStart(nStartIndex)->GetStart());
323cdf0e10cSrcweir 		if (pHints->GetEndCount() > nEndIndex) // Gibt es noch Enden?
324cdf0e10cSrcweir 		{
325cdf0e10cSrcweir 			xub_StrLen nNextEnd = (*pHints->GetEnd(nEndIndex)->GetAnyEnd());
326cdf0e10cSrcweir 			if ( nNextEnd<nNext ) nNext = nNextEnd; // Wer ist naeher?
327cdf0e10cSrcweir 		}
328cdf0e10cSrcweir 	}
329cdf0e10cSrcweir 	if (m_pTxtNode!=NULL) {
330cdf0e10cSrcweir 	    //TODO maybe use hints like FieldHints for this instead of looking at the text...
331cdf0e10cSrcweir 	    int l=(nNext<m_pTxtNode->Len()?nNext:m_pTxtNode->Len());
332cdf0e10cSrcweir 	    sal_uInt16 p=nPos;
333cdf0e10cSrcweir 	    const sal_Unicode *txt=m_pTxtNode->GetTxt().GetBuffer();
334cdf0e10cSrcweir 	    while(p<l && txt[p]!=CH_TXT_ATR_FIELDSTART && txt[p]!=CH_TXT_ATR_FIELDEND && txt[p]!=CH_TXT_ATR_FORMELEMENT) p++;
335cdf0e10cSrcweir 	    if ((p<l && p>nPos) || nNext<=p)
336cdf0e10cSrcweir 		nNext=p;
337cdf0e10cSrcweir 	    else
338cdf0e10cSrcweir 		nNext=p+1;
339cdf0e10cSrcweir 	}
340cdf0e10cSrcweir     if( pRedln )
341cdf0e10cSrcweir 		return pRedln->GetNextRedln( nNext );
342cdf0e10cSrcweir 	return nNext;
343cdf0e10cSrcweir }
344cdf0e10cSrcweir 
345cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
346cdf0e10cSrcweir /*************************************************************************
347cdf0e10cSrcweir  *						SwAttrIter::Dump()
348cdf0e10cSrcweir  *************************************************************************/
349cdf0e10cSrcweir 
Dump(SvStream &) const350cdf0e10cSrcweir void SwAttrIter::Dump( SvStream &/*rOS*/ ) const
351cdf0e10cSrcweir {
352cdf0e10cSrcweir // Noch nicht an den neuen Attributiterator angepasst ...
353cdf0e10cSrcweir }
354cdf0e10cSrcweir 
355cdf0e10cSrcweir #endif
356cdf0e10cSrcweir 
357cdf0e10cSrcweir class SwMinMaxArgs
358cdf0e10cSrcweir {
359cdf0e10cSrcweir public:
360cdf0e10cSrcweir     OutputDevice* pOut;
361cdf0e10cSrcweir     ViewShell* pSh;
362cdf0e10cSrcweir 	sal_uLong &rMin;
363cdf0e10cSrcweir 	sal_uLong &rMax;
364cdf0e10cSrcweir 	sal_uLong &rAbsMin;
365cdf0e10cSrcweir 	long nRowWidth;
366cdf0e10cSrcweir 	long nWordWidth;
367cdf0e10cSrcweir 	long nWordAdd;
368cdf0e10cSrcweir     xub_StrLen nNoLineBreak;
SwMinMaxArgs(OutputDevice * pOutI,ViewShell * pShI,sal_uLong & rMinI,sal_uLong & rMaxI,sal_uLong & rAbsI)369cdf0e10cSrcweir     SwMinMaxArgs( OutputDevice* pOutI, ViewShell* pShI, sal_uLong& rMinI, sal_uLong &rMaxI, sal_uLong &rAbsI )
370cdf0e10cSrcweir 		: pOut( pOutI ), pSh( pShI ), rMin( rMinI ), rMax( rMaxI ), rAbsMin( rAbsI )
371cdf0e10cSrcweir         { nRowWidth = nWordWidth = nWordAdd = 0; nNoLineBreak = STRING_LEN; }
Minimum(long nNew)372cdf0e10cSrcweir 	void Minimum( long nNew ) { if( (long)rMin < nNew ) rMin = nNew; }
NewWord()373cdf0e10cSrcweir 	void NewWord() { nWordAdd = nWordWidth = 0; }
374cdf0e10cSrcweir };
375cdf0e10cSrcweir 
lcl_MinMaxString(SwMinMaxArgs & rArg,SwFont * pFnt,const XubString & rTxt,xub_StrLen nIdx,xub_StrLen nEnd)376cdf0e10cSrcweir sal_Bool lcl_MinMaxString( SwMinMaxArgs& rArg, SwFont* pFnt, const XubString &rTxt,
377cdf0e10cSrcweir 	xub_StrLen nIdx, xub_StrLen nEnd )
378cdf0e10cSrcweir {
379cdf0e10cSrcweir 	sal_Bool bRet = sal_False;
380cdf0e10cSrcweir 	while( nIdx < nEnd )
381cdf0e10cSrcweir 	{
382cdf0e10cSrcweir 		xub_StrLen nStop = nIdx;
383cdf0e10cSrcweir         sal_Bool bClear;
384cdf0e10cSrcweir         LanguageType eLang = pFnt->GetLanguage();
385cdf0e10cSrcweir         if( pBreakIt->GetBreakIter().is() )
386cdf0e10cSrcweir         {
387cdf0e10cSrcweir             bClear = CH_BLANK == rTxt.GetChar( nStop );
388cdf0e10cSrcweir             Boundary aBndry( pBreakIt->GetBreakIter()->getWordBoundary( rTxt, nIdx,
389cdf0e10cSrcweir                              pBreakIt->GetLocale( eLang ),
390cdf0e10cSrcweir                              WordType::DICTIONARY_WORD, sal_True ) );
391cdf0e10cSrcweir             nStop = (xub_StrLen)aBndry.endPos;
392cdf0e10cSrcweir             if( nIdx <= aBndry.startPos && nIdx && nIdx-1 != rArg.nNoLineBreak )
393cdf0e10cSrcweir                 rArg.NewWord();
394cdf0e10cSrcweir             if( nStop == nIdx )
395cdf0e10cSrcweir                 ++nStop;
396cdf0e10cSrcweir             if( nStop > nEnd )
397cdf0e10cSrcweir                 nStop = nEnd;
398cdf0e10cSrcweir         }
399cdf0e10cSrcweir         else
400cdf0e10cSrcweir         {
401cdf0e10cSrcweir             while( nStop < nEnd && CH_BLANK != rTxt.GetChar( nStop ) )
402cdf0e10cSrcweir                 ++nStop;
403cdf0e10cSrcweir             bClear = nStop == nIdx;
404cdf0e10cSrcweir             if ( bClear )
405cdf0e10cSrcweir             {
406cdf0e10cSrcweir                 rArg.NewWord();
407cdf0e10cSrcweir                 while( nStop < nEnd && CH_BLANK == rTxt.GetChar( nStop ) )
408cdf0e10cSrcweir                     ++nStop;
409cdf0e10cSrcweir             }
410cdf0e10cSrcweir         }
411cdf0e10cSrcweir 
412cdf0e10cSrcweir         SwDrawTextInfo aDrawInf( rArg.pSh, *rArg.pOut, 0, rTxt, nIdx, nStop - nIdx );
413cdf0e10cSrcweir         long nAktWidth = pFnt->_GetTxtSize( aDrawInf ).Width();
414cdf0e10cSrcweir 		rArg.nRowWidth += nAktWidth;
415cdf0e10cSrcweir 		if( bClear )
416cdf0e10cSrcweir 			rArg.NewWord();
417cdf0e10cSrcweir 		else
418cdf0e10cSrcweir 		{
419cdf0e10cSrcweir 			rArg.nWordWidth += nAktWidth;
420cdf0e10cSrcweir 			if( (long)rArg.rAbsMin < rArg.nWordWidth )
421cdf0e10cSrcweir 				rArg.rAbsMin = rArg.nWordWidth;
422cdf0e10cSrcweir 			rArg.Minimum( rArg.nWordWidth + rArg.nWordAdd );
423cdf0e10cSrcweir 			bRet = sal_True;
424cdf0e10cSrcweir 		}
425cdf0e10cSrcweir 		nIdx = nStop;
426cdf0e10cSrcweir     }
427cdf0e10cSrcweir 	return bRet;
428cdf0e10cSrcweir }
429cdf0e10cSrcweir 
IsSymbol(const xub_StrLen nBegin) const430cdf0e10cSrcweir sal_Bool SwTxtNode::IsSymbol( const xub_StrLen nBegin ) const//swmodtest 080307
431cdf0e10cSrcweir {
432cdf0e10cSrcweir 	SwScriptInfo aScriptInfo;
433cdf0e10cSrcweir     SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
434cdf0e10cSrcweir     aIter.Seek( nBegin );
435cdf0e10cSrcweir     return aIter.GetFnt()->IsSymbol(
436cdf0e10cSrcweir 		const_cast<ViewShell *>(getIDocumentLayoutAccess()->GetCurrentViewShell()) );//swmod 080311
437cdf0e10cSrcweir }
438cdf0e10cSrcweir 
439cdf0e10cSrcweir class SwMinMaxNodeArgs
440cdf0e10cSrcweir {
441cdf0e10cSrcweir public:
442cdf0e10cSrcweir 	sal_uLong nMaxWidth;    // Summe aller Rahmenbreite
443cdf0e10cSrcweir 	long nMinWidth;		// Breitester Rahmen
444cdf0e10cSrcweir 	long nLeftRest;     // noch nicht von Rahmen ueberdeckter Platz im l. Rand
445cdf0e10cSrcweir 	long nRightRest;    // noch nicht von Rahmen ueberdeckter Platz im r. Rand
446cdf0e10cSrcweir 	long nLeftDiff;		// Min/Max-Differenz des Rahmens im linken Rand
447cdf0e10cSrcweir 	long nRightDiff;    // Min/Max-Differenz des Rahmens im rechten Rand
448cdf0e10cSrcweir 	sal_uLong nIndx;		// Indexnummer des Nodes
Minimum(long nNew)449cdf0e10cSrcweir 	void Minimum( long nNew ) { if( nNew > nMinWidth ) nMinWidth = nNew; }
450cdf0e10cSrcweir };
451cdf0e10cSrcweir 
lcl_MinMaxNode(const SwFrmFmtPtr & rpNd,void * pArgs)452cdf0e10cSrcweir sal_Bool lcl_MinMaxNode( const SwFrmFmtPtr& rpNd, void* pArgs )
453cdf0e10cSrcweir {
454cdf0e10cSrcweir 	const SwFmtAnchor& rFmtA = ((SwFrmFmt*)rpNd)->GetAnchor();
455cdf0e10cSrcweir 
456cdf0e10cSrcweir 	bool bCalculate = false;
457cdf0e10cSrcweir     if ((FLY_AT_PARA == rFmtA.GetAnchorId()) ||
458cdf0e10cSrcweir         (FLY_AT_CHAR == rFmtA.GetAnchorId()))
459cdf0e10cSrcweir 	{
460cdf0e10cSrcweir 		bCalculate = true;
461cdf0e10cSrcweir 	}
462cdf0e10cSrcweir 
463cdf0e10cSrcweir 	if (bCalculate)
464cdf0e10cSrcweir 	{
465cdf0e10cSrcweir 		const SwMinMaxNodeArgs *pIn = (const SwMinMaxNodeArgs*)pArgs;
466cdf0e10cSrcweir 		const SwPosition *pPos = rFmtA.GetCntntAnchor();
467cdf0e10cSrcweir 		ASSERT(pPos && pIn, "Unexpected NULL arguments");
468cdf0e10cSrcweir 		if (!pPos || !pIn || pIn->nIndx != pPos->nNode.GetIndex())
469cdf0e10cSrcweir 			bCalculate = false;
470cdf0e10cSrcweir 	}
471cdf0e10cSrcweir 
472cdf0e10cSrcweir 	if (bCalculate)
473cdf0e10cSrcweir 	{
474cdf0e10cSrcweir 		long nMin, nMax;
475cdf0e10cSrcweir 		SwHTMLTableLayout *pLayout = 0;
476cdf0e10cSrcweir 		MSHORT nWhich = ((SwFrmFmt*)rpNd)->Which();
477cdf0e10cSrcweir 		if( RES_DRAWFRMFMT != nWhich )
478cdf0e10cSrcweir 		{
479cdf0e10cSrcweir 			// Enthaelt der Rahmen zu Beginn oder am Ende eine Tabelle?
480cdf0e10cSrcweir             const SwNodes& rNodes = static_cast<SwFrmFmt*>(rpNd)->GetDoc()->GetNodes();
481cdf0e10cSrcweir             const SwFmtCntnt& rFlyCntnt = ((SwFrmFmt*)rpNd)->GetCntnt();
482cdf0e10cSrcweir 			sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex();
483cdf0e10cSrcweir             SwTableNode* pTblNd = rNodes[nStt+1]->GetTableNode();
484cdf0e10cSrcweir 			if( !pTblNd )
485cdf0e10cSrcweir 			{
486cdf0e10cSrcweir                 SwNode *pNd = rNodes[nStt];
487cdf0e10cSrcweir                 pNd = rNodes[pNd->EndOfSectionIndex()-1];
488cdf0e10cSrcweir 				if( pNd->IsEndNode() )
489cdf0e10cSrcweir 					pTblNd = pNd->StartOfSectionNode()->GetTableNode();
490cdf0e10cSrcweir 			}
491cdf0e10cSrcweir 
492cdf0e10cSrcweir 			if( pTblNd )
493cdf0e10cSrcweir 				pLayout = pTblNd->GetTable().GetHTMLTableLayout();
494cdf0e10cSrcweir 		}
495cdf0e10cSrcweir 
496cdf0e10cSrcweir 		const SwFmtHoriOrient& rOrient = ((SwFrmFmt*)rpNd)->GetHoriOrient();
497cdf0e10cSrcweir         sal_Int16 eHoriOri = rOrient.GetHoriOrient();
498cdf0e10cSrcweir 
499cdf0e10cSrcweir 		long nDiff;
500cdf0e10cSrcweir 		if( pLayout )
501cdf0e10cSrcweir 		{
502cdf0e10cSrcweir 			nMin = pLayout->GetMin();
503cdf0e10cSrcweir 			nMax = pLayout->GetMax();
504cdf0e10cSrcweir 			nDiff = nMax - nMin;
505cdf0e10cSrcweir 		}
506cdf0e10cSrcweir 		else
507cdf0e10cSrcweir 		{
508cdf0e10cSrcweir 			if( RES_DRAWFRMFMT == nWhich )
509cdf0e10cSrcweir 			{
510cdf0e10cSrcweir 				const SdrObject* pSObj = rpNd->FindSdrObject();
511cdf0e10cSrcweir 				if( pSObj )
512cdf0e10cSrcweir 					nMin = pSObj->GetCurrentBoundRect().GetWidth();
513cdf0e10cSrcweir 				else
514cdf0e10cSrcweir 				nMin = 0;
515cdf0e10cSrcweir 
516cdf0e10cSrcweir 			}
517cdf0e10cSrcweir 			else
518cdf0e10cSrcweir 			{
519cdf0e10cSrcweir 				const SwFmtFrmSize &rSz = ( (SwFrmFmt*)rpNd )->GetFrmSize();
520cdf0e10cSrcweir 				nMin = rSz.GetWidth();
521cdf0e10cSrcweir 			}
522cdf0e10cSrcweir 			nMax = nMin;
523cdf0e10cSrcweir 			nDiff = 0;
524cdf0e10cSrcweir 		}
525cdf0e10cSrcweir 
526cdf0e10cSrcweir 		const SvxLRSpaceItem &rLR = ( (SwFrmFmt*)rpNd )->GetLRSpace();
527cdf0e10cSrcweir 		nMin += rLR.GetLeft();
528cdf0e10cSrcweir 		nMin += rLR.GetRight();
529cdf0e10cSrcweir 		nMax += rLR.GetLeft();
530cdf0e10cSrcweir 		nMax += rLR.GetRight();
531cdf0e10cSrcweir 
532cdf0e10cSrcweir 		if( SURROUND_THROUGHT == ((SwFrmFmt*)rpNd)->GetSurround().GetSurround() )
533cdf0e10cSrcweir 		{
534cdf0e10cSrcweir 			( (SwMinMaxNodeArgs*)pArgs )->Minimum( nMin );
535cdf0e10cSrcweir 			return sal_True;
536cdf0e10cSrcweir 		}
537cdf0e10cSrcweir 
538cdf0e10cSrcweir 		// Rahmen, die recht bzw. links ausgerichtet sind, gehen nur
539cdf0e10cSrcweir 		// teilweise in die Max-Berechnung ein, da der Rand schon berueck-
540cdf0e10cSrcweir 		// sichtigt wird. Nur wenn die Rahmen in den Textkoerper ragen,
541cdf0e10cSrcweir 		// wird dieser Teil hinzuaddiert.
542cdf0e10cSrcweir 		switch( eHoriOri )
543cdf0e10cSrcweir 		{
544cdf0e10cSrcweir             case text::HoriOrientation::RIGHT:
545cdf0e10cSrcweir 			{
546cdf0e10cSrcweir 				if( nDiff )
547cdf0e10cSrcweir 				{
548cdf0e10cSrcweir 					((SwMinMaxNodeArgs*)pArgs)->nRightRest -=
549cdf0e10cSrcweir 						((SwMinMaxNodeArgs*)pArgs)->nRightDiff;
550cdf0e10cSrcweir 					((SwMinMaxNodeArgs*)pArgs)->nRightDiff = nDiff;
551cdf0e10cSrcweir 				}
552cdf0e10cSrcweir                 if( text::RelOrientation::FRAME != rOrient.GetRelationOrient() )
553cdf0e10cSrcweir 				{
554cdf0e10cSrcweir 					if( ((SwMinMaxNodeArgs*)pArgs)->nRightRest > 0 )
555cdf0e10cSrcweir 						((SwMinMaxNodeArgs*)pArgs)->nRightRest = 0;
556cdf0e10cSrcweir 				}
557cdf0e10cSrcweir 				((SwMinMaxNodeArgs*)pArgs)->nRightRest -= nMin;
558cdf0e10cSrcweir 				break;
559cdf0e10cSrcweir 			}
560cdf0e10cSrcweir             case text::HoriOrientation::LEFT:
561cdf0e10cSrcweir 			{
562cdf0e10cSrcweir 				if( nDiff )
563cdf0e10cSrcweir 				{
564cdf0e10cSrcweir 					((SwMinMaxNodeArgs*)pArgs)->nLeftRest -=
565cdf0e10cSrcweir 						((SwMinMaxNodeArgs*)pArgs)->nLeftDiff;
566cdf0e10cSrcweir 					((SwMinMaxNodeArgs*)pArgs)->nLeftDiff = nDiff;
567cdf0e10cSrcweir 				}
568cdf0e10cSrcweir                 if( text::RelOrientation::FRAME != rOrient.GetRelationOrient() &&
569cdf0e10cSrcweir 					((SwMinMaxNodeArgs*)pArgs)->nLeftRest < 0 )
570cdf0e10cSrcweir 					((SwMinMaxNodeArgs*)pArgs)->nLeftRest = 0;
571cdf0e10cSrcweir 				((SwMinMaxNodeArgs*)pArgs)->nLeftRest -= nMin;
572cdf0e10cSrcweir 				break;
573cdf0e10cSrcweir 			}
574cdf0e10cSrcweir 			default:
575cdf0e10cSrcweir 			{
576cdf0e10cSrcweir 				( (SwMinMaxNodeArgs*)pArgs )->nMaxWidth += nMax;
577cdf0e10cSrcweir 				( (SwMinMaxNodeArgs*)pArgs )->Minimum( nMin );
578cdf0e10cSrcweir 			}
579cdf0e10cSrcweir 		}
580cdf0e10cSrcweir 	}
581cdf0e10cSrcweir 	return sal_True;
582cdf0e10cSrcweir }
583cdf0e10cSrcweir 
584cdf0e10cSrcweir #define FLYINCNT_MIN_WIDTH 284
585cdf0e10cSrcweir 
586cdf0e10cSrcweir // changing this method very likely requires changing of
587cdf0e10cSrcweir // "GetScalingOfSelectedText"
GetMinMaxSize(sal_uLong nIndex,sal_uLong & rMin,sal_uLong & rMax,sal_uLong & rAbsMin,OutputDevice * pOut) const588cdf0e10cSrcweir void SwTxtNode::GetMinMaxSize( sal_uLong nIndex, sal_uLong& rMin, sal_uLong &rMax,
589cdf0e10cSrcweir 							   sal_uLong& rAbsMin, OutputDevice* pOut ) const
590cdf0e10cSrcweir {
591cdf0e10cSrcweir     ViewShell* pSh = 0;
592cdf0e10cSrcweir 	GetDoc()->GetEditShell( &pSh );
593cdf0e10cSrcweir 	if( !pOut )
594cdf0e10cSrcweir 	{
595cdf0e10cSrcweir         if( pSh )
596cdf0e10cSrcweir 			pOut = pSh->GetWin();
597cdf0e10cSrcweir 		if( !pOut )
598cdf0e10cSrcweir 			pOut = GetpApp()->GetDefaultDevice();
599cdf0e10cSrcweir 	}
600cdf0e10cSrcweir 
601cdf0e10cSrcweir 	MapMode aOldMap( pOut->GetMapMode() );
602cdf0e10cSrcweir 	pOut->SetMapMode( MapMode( MAP_TWIP ) );
603cdf0e10cSrcweir 
604cdf0e10cSrcweir 	rMin = 0;
605cdf0e10cSrcweir 	rMax = 0;
606cdf0e10cSrcweir 	rAbsMin = 0;
607cdf0e10cSrcweir 
608cdf0e10cSrcweir 	const SvxLRSpaceItem &rSpace = GetSwAttrSet().GetLRSpace();
609cdf0e10cSrcweir 	long nLROffset = rSpace.GetTxtLeft() + GetLeftMarginWithNum( sal_True );
610cdf0e10cSrcweir 	short nFLOffs;
611cdf0e10cSrcweir 	// Bei Numerierung ist ein neg. Erstzeileneinzug vermutlich
612cdf0e10cSrcweir 	// bereits gefuellt...
613cdf0e10cSrcweir 	if( !GetFirstLineOfsWithNum( nFLOffs ) || nFLOffs > nLROffset )
614cdf0e10cSrcweir 		nLROffset = nFLOffs;
615cdf0e10cSrcweir 
616cdf0e10cSrcweir 	SwMinMaxNodeArgs aNodeArgs;
617cdf0e10cSrcweir 	aNodeArgs.nMinWidth = 0;
618cdf0e10cSrcweir 	aNodeArgs.nMaxWidth = 0;
619cdf0e10cSrcweir 	aNodeArgs.nLeftRest = nLROffset;
620cdf0e10cSrcweir 	aNodeArgs.nRightRest = rSpace.GetRight();
621cdf0e10cSrcweir 	aNodeArgs.nLeftDiff = 0;
622cdf0e10cSrcweir 	aNodeArgs.nRightDiff = 0;
623cdf0e10cSrcweir 	if( nIndex )
624cdf0e10cSrcweir 	{
625cdf0e10cSrcweir 		SwSpzFrmFmts* pTmp = (SwSpzFrmFmts*)GetDoc()->GetSpzFrmFmts();
626cdf0e10cSrcweir 		if( pTmp )
627cdf0e10cSrcweir 		{
628cdf0e10cSrcweir 			aNodeArgs.nIndx = nIndex;
629cdf0e10cSrcweir 			pTmp->ForEach( &lcl_MinMaxNode, &aNodeArgs );
630cdf0e10cSrcweir 		}
631cdf0e10cSrcweir 	}
632cdf0e10cSrcweir 	if( aNodeArgs.nLeftRest < 0 )
633cdf0e10cSrcweir 		aNodeArgs.Minimum( nLROffset - aNodeArgs.nLeftRest );
634cdf0e10cSrcweir 	aNodeArgs.nLeftRest -= aNodeArgs.nLeftDiff;
635cdf0e10cSrcweir 	if( aNodeArgs.nLeftRest < 0 )
636cdf0e10cSrcweir 		aNodeArgs.nMaxWidth -= aNodeArgs.nLeftRest;
637cdf0e10cSrcweir 
638cdf0e10cSrcweir 	if( aNodeArgs.nRightRest < 0 )
639cdf0e10cSrcweir 		aNodeArgs.Minimum( rSpace.GetRight() - aNodeArgs.nRightRest );
640cdf0e10cSrcweir 	aNodeArgs.nRightRest -= aNodeArgs.nRightDiff;
641cdf0e10cSrcweir 	if( aNodeArgs.nRightRest < 0 )
642cdf0e10cSrcweir 		aNodeArgs.nMaxWidth -= aNodeArgs.nRightRest;
643cdf0e10cSrcweir 
644cdf0e10cSrcweir 	SwScriptInfo aScriptInfo;
645cdf0e10cSrcweir     SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
646cdf0e10cSrcweir 	xub_StrLen nIdx = 0;
647cdf0e10cSrcweir 	aIter.SeekAndChgAttrIter( nIdx, pOut );
648cdf0e10cSrcweir     xub_StrLen nLen = m_Text.Len();
649cdf0e10cSrcweir 	long nAktWidth = 0;
650cdf0e10cSrcweir 	MSHORT nAdd = 0;
651cdf0e10cSrcweir     SwMinMaxArgs aArg( pOut, pSh, rMin, rMax, rAbsMin );
652cdf0e10cSrcweir 	while( nIdx < nLen )
653cdf0e10cSrcweir 	{
654cdf0e10cSrcweir 		xub_StrLen nNextChg = aIter.GetNextAttr();
655cdf0e10cSrcweir 		xub_StrLen nStop = aScriptInfo.NextScriptChg( nIdx );
656cdf0e10cSrcweir 		if( nNextChg > nStop )
657cdf0e10cSrcweir 			nNextChg = nStop;
658cdf0e10cSrcweir 		SwTxtAttr *pHint = NULL;
659cdf0e10cSrcweir 		xub_Unicode cChar = CH_BLANK;
660cdf0e10cSrcweir 		nStop = nIdx;
661cdf0e10cSrcweir 		while( nStop < nLen && nStop < nNextChg &&
662cdf0e10cSrcweir                CH_TAB != ( cChar = m_Text.GetChar( nStop ) ) &&
663cdf0e10cSrcweir                CH_BREAK != cChar && CHAR_HARDBLANK != cChar &&
664cdf0e10cSrcweir                CHAR_HARDHYPHEN != cChar && CHAR_SOFTHYPHEN != cChar &&
665cdf0e10cSrcweir                !pHint )
666cdf0e10cSrcweir 		{
667cdf0e10cSrcweir 			if( ( CH_TXTATR_BREAKWORD != cChar && CH_TXTATR_INWORD != cChar )
668cdf0e10cSrcweir 				|| ( 0 == ( pHint = aIter.GetAttr( nStop ) ) ) )
669cdf0e10cSrcweir 				++nStop;
670cdf0e10cSrcweir 		}
671cdf0e10cSrcweir         if ( lcl_MinMaxString( aArg, aIter.GetFnt(), m_Text, nIdx, nStop ) )
672cdf0e10cSrcweir         {
673cdf0e10cSrcweir 			nAdd = 20;
674cdf0e10cSrcweir         }
675cdf0e10cSrcweir 		nIdx = nStop;
676cdf0e10cSrcweir 		aIter.SeekAndChgAttrIter( nIdx, pOut );
677cdf0e10cSrcweir 		switch( cChar )
678cdf0e10cSrcweir 		{
679cdf0e10cSrcweir 			case CH_BREAK  :
680cdf0e10cSrcweir 			{
681cdf0e10cSrcweir 				if( (long)rMax < aArg.nRowWidth )
682cdf0e10cSrcweir 					rMax = aArg.nRowWidth;
683cdf0e10cSrcweir 				aArg.nRowWidth = 0;
684cdf0e10cSrcweir 				aArg.NewWord();
685cdf0e10cSrcweir 				aIter.SeekAndChgAttrIter( ++nIdx, pOut );
686cdf0e10cSrcweir 			}
687cdf0e10cSrcweir 			break;
688cdf0e10cSrcweir 			case CH_TAB    :
689cdf0e10cSrcweir 			{
690cdf0e10cSrcweir 				aArg.NewWord();
691cdf0e10cSrcweir 				aIter.SeekAndChgAttrIter( ++nIdx, pOut );
692cdf0e10cSrcweir 			}
693cdf0e10cSrcweir 			break;
694cdf0e10cSrcweir             case CHAR_SOFTHYPHEN:
695cdf0e10cSrcweir                 ++nIdx;
696cdf0e10cSrcweir             break;
697cdf0e10cSrcweir             case CHAR_HARDBLANK:
698cdf0e10cSrcweir             case CHAR_HARDHYPHEN:
699cdf0e10cSrcweir             {
700cdf0e10cSrcweir                 XubString sTmp( cChar );
701cdf0e10cSrcweir                 SwDrawTextInfo aDrawInf( const_cast<ViewShell *>(getIDocumentLayoutAccess()->GetCurrentViewShell()),
702cdf0e10cSrcweir 					*pOut, 0, sTmp, 0, 1, 0, sal_False );//swmod 080311
703cdf0e10cSrcweir                 nAktWidth = aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
704cdf0e10cSrcweir                 aArg.nWordWidth += nAktWidth;
705cdf0e10cSrcweir                 aArg.nRowWidth += nAktWidth;
706cdf0e10cSrcweir                 if( (long)rAbsMin < aArg.nWordWidth )
707cdf0e10cSrcweir                     rAbsMin = aArg.nWordWidth;
708cdf0e10cSrcweir                 aArg.Minimum( aArg.nWordWidth + aArg.nWordAdd );
709cdf0e10cSrcweir                 aArg.nNoLineBreak = nIdx++;
710cdf0e10cSrcweir             }
711cdf0e10cSrcweir             break;
712cdf0e10cSrcweir 			case CH_TXTATR_BREAKWORD:
713cdf0e10cSrcweir 			case CH_TXTATR_INWORD:
714cdf0e10cSrcweir 			{
715cdf0e10cSrcweir 				if( !pHint )
716cdf0e10cSrcweir 					break;
717cdf0e10cSrcweir 				long nOldWidth = aArg.nWordWidth;
718cdf0e10cSrcweir 				long nOldAdd = aArg.nWordAdd;
719cdf0e10cSrcweir 				aArg.NewWord();
720cdf0e10cSrcweir 
721cdf0e10cSrcweir 				switch( pHint->Which() )
722cdf0e10cSrcweir 				{
723cdf0e10cSrcweir 					case RES_TXTATR_FLYCNT :
724cdf0e10cSrcweir 					{
725cdf0e10cSrcweir 						SwFrmFmt *pFrmFmt = pHint->GetFlyCnt().GetFrmFmt();
726cdf0e10cSrcweir 						const SvxLRSpaceItem &rLR = pFrmFmt->GetLRSpace();
727cdf0e10cSrcweir 						if( RES_DRAWFRMFMT == pFrmFmt->Which() )
728cdf0e10cSrcweir 						{
729cdf0e10cSrcweir 							const SdrObject* pSObj = pFrmFmt->FindSdrObject();
730cdf0e10cSrcweir 							if( pSObj )
731cdf0e10cSrcweir 								nAktWidth = pSObj->GetCurrentBoundRect().GetWidth();
732cdf0e10cSrcweir 							else
733cdf0e10cSrcweir 								nAktWidth = 0;
734cdf0e10cSrcweir 						}
735cdf0e10cSrcweir 						else
736cdf0e10cSrcweir 						{
737cdf0e10cSrcweir 							const SwFmtFrmSize& rTmpSize = pFrmFmt->GetFrmSize();
738cdf0e10cSrcweir 							if( RES_FLYFRMFMT == pFrmFmt->Which()
739cdf0e10cSrcweir 								&& rTmpSize.GetWidthPercent() )
740cdf0e10cSrcweir 							{
741cdf0e10cSrcweir /*-----------------24.01.97 14:09----------------------------------------------
742cdf0e10cSrcweir  * Hier ein HACK fuer folgende Situation: In dem Absatz befindet sich
743cdf0e10cSrcweir  * ein Textrahmen mit relativer Groesse. Dann nehmen wir mal als minimale
744cdf0e10cSrcweir  * Breite 0,5 cm und als maximale KSHRT_MAX.
745cdf0e10cSrcweir  * Sauberer und vielleicht spaeter notwendig waere es, ueber den Inhalt
746cdf0e10cSrcweir  * des Textrahmens zu iterieren und GetMinMaxSize rekursiv zu rufen.
747cdf0e10cSrcweir  * --------------------------------------------------------------------------*/
748cdf0e10cSrcweir 								nAktWidth = FLYINCNT_MIN_WIDTH; // 0,5 cm
749cdf0e10cSrcweir 								if( (long)rMax < KSHRT_MAX )
750cdf0e10cSrcweir 									rMax = KSHRT_MAX;
751cdf0e10cSrcweir 							}
752cdf0e10cSrcweir 							else
753cdf0e10cSrcweir 								nAktWidth = pFrmFmt->GetFrmSize().GetWidth();
754cdf0e10cSrcweir 						}
755cdf0e10cSrcweir 						nAktWidth += rLR.GetLeft();
756cdf0e10cSrcweir 						nAktWidth += rLR.GetRight();
757cdf0e10cSrcweir 						aArg.nWordAdd = nOldWidth + nOldAdd;
758cdf0e10cSrcweir 						aArg.nWordWidth = nAktWidth;
759cdf0e10cSrcweir 						aArg.nRowWidth += nAktWidth;
760cdf0e10cSrcweir 						if( (long)rAbsMin < aArg.nWordWidth )
761cdf0e10cSrcweir 							rAbsMin = aArg.nWordWidth;
762cdf0e10cSrcweir 						aArg.Minimum( aArg.nWordWidth + aArg.nWordAdd );
763cdf0e10cSrcweir 						break;
764cdf0e10cSrcweir 					}
765cdf0e10cSrcweir 					case RES_TXTATR_FTN :
766cdf0e10cSrcweir 					{
767cdf0e10cSrcweir 						const XubString aTxt = pHint->GetFtn().GetNumStr();
768cdf0e10cSrcweir 						if( lcl_MinMaxString( aArg, aIter.GetFnt(),	aTxt, 0,
769cdf0e10cSrcweir 							aTxt.Len() ) )
770cdf0e10cSrcweir 							nAdd = 20;
771cdf0e10cSrcweir 						break;
772cdf0e10cSrcweir 					}
773dec99bbdSOliver-Rainer Wittmann 
774dec99bbdSOliver-Rainer Wittmann                     case RES_TXTATR_FIELD :
775dec99bbdSOliver-Rainer Wittmann                     case RES_TXTATR_ANNOTATION :
776dec99bbdSOliver-Rainer Wittmann                         {
777dec99bbdSOliver-Rainer Wittmann                             SwField *pFld = (SwField*)pHint->GetFmtFld().GetField();
778dec99bbdSOliver-Rainer Wittmann                             const String aTxt = pFld->ExpandField(true);
779dec99bbdSOliver-Rainer Wittmann                             if( lcl_MinMaxString( aArg, aIter.GetFnt(),	aTxt, 0,
780dec99bbdSOliver-Rainer Wittmann                                 aTxt.Len() ) )
781dec99bbdSOliver-Rainer Wittmann                                 nAdd = 20;
782dec99bbdSOliver-Rainer Wittmann                             break;
783dec99bbdSOliver-Rainer Wittmann                         }
784dec99bbdSOliver-Rainer Wittmann 
785dec99bbdSOliver-Rainer Wittmann                     default: aArg.nWordWidth = nOldWidth;
786dec99bbdSOliver-Rainer Wittmann                         aArg.nWordAdd = nOldAdd;
787cdf0e10cSrcweir 
788cdf0e10cSrcweir 				}
789cdf0e10cSrcweir 				aIter.SeekAndChgAttrIter( ++nIdx, pOut );
790cdf0e10cSrcweir 			}
791cdf0e10cSrcweir 			break;
792cdf0e10cSrcweir 		}
793cdf0e10cSrcweir 	}
794cdf0e10cSrcweir 	if( (long)rMax < aArg.nRowWidth )
795cdf0e10cSrcweir 		rMax = aArg.nRowWidth;
796cdf0e10cSrcweir 
797cdf0e10cSrcweir 	nLROffset += rSpace.GetRight();
798cdf0e10cSrcweir 
799cdf0e10cSrcweir 	rAbsMin += nLROffset;
800cdf0e10cSrcweir 	rAbsMin += nAdd;
801cdf0e10cSrcweir 	rMin += nLROffset;
802cdf0e10cSrcweir 	rMin += nAdd;
803cdf0e10cSrcweir 	if( (long)rMin < aNodeArgs.nMinWidth )
804cdf0e10cSrcweir 		rMin = aNodeArgs.nMinWidth;
805cdf0e10cSrcweir 	if( (long)rAbsMin < aNodeArgs.nMinWidth )
806cdf0e10cSrcweir 		rAbsMin = aNodeArgs.nMinWidth;
807cdf0e10cSrcweir 	rMax += aNodeArgs.nMaxWidth;
808cdf0e10cSrcweir 	rMax += nLROffset;
809cdf0e10cSrcweir 	rMax += nAdd;
810cdf0e10cSrcweir 	if( rMax < rMin ) // z.B. Rahmen mit Durchlauf gehen zunaechst nur
811cdf0e10cSrcweir 		rMax = rMin;  // in das Minimum ein
812cdf0e10cSrcweir 	pOut->SetMapMode( aOldMap );
813cdf0e10cSrcweir }
814cdf0e10cSrcweir 
815cdf0e10cSrcweir /*************************************************************************
816cdf0e10cSrcweir  *						SwTxtNode::GetScalingOfSelectedText()
817cdf0e10cSrcweir  *
818cdf0e10cSrcweir  * Calculates the width of the text part specified by nStt and nEnd,
819*86e1cf34SPedro Giffuni  * the height of the line containing nStt is divided by this width,
820cdf0e10cSrcweir  * indicating the scaling factor, if the text part is rotated.
821cdf0e10cSrcweir  * Having CH_BREAKs in the text part, this method returns the scaling
822cdf0e10cSrcweir  * factor for the longest of the text parts separated by the CH_BREAKs.
823cdf0e10cSrcweir  *
824cdf0e10cSrcweir  * changing this method very likely requires changing of "GetMinMaxSize"
825cdf0e10cSrcweir  *************************************************************************/
826cdf0e10cSrcweir 
GetScalingOfSelectedText(xub_StrLen nStt,xub_StrLen nEnd) const827cdf0e10cSrcweir sal_uInt16 SwTxtNode::GetScalingOfSelectedText(	xub_StrLen nStt, xub_StrLen nEnd )
828cdf0e10cSrcweir 	const
829cdf0e10cSrcweir {
830cdf0e10cSrcweir     ViewShell* pSh = NULL;
831cdf0e10cSrcweir     OutputDevice* pOut = NULL;
832cdf0e10cSrcweir 	GetDoc()->GetEditShell( &pSh );
833cdf0e10cSrcweir 
834cdf0e10cSrcweir     if ( pSh )
835cdf0e10cSrcweir         pOut = &pSh->GetRefDev();
836cdf0e10cSrcweir     else
837cdf0e10cSrcweir     {
838cdf0e10cSrcweir         //Zugriff ueber StarONE, es muss keine Shell existieren oder aktiv sein.
839cdf0e10cSrcweir         if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) )
840cdf0e10cSrcweir             pOut = GetpApp()->GetDefaultDevice();
841cdf0e10cSrcweir         else
842cdf0e10cSrcweir             pOut = getIDocumentDeviceAccess()->getReferenceDevice( true );
843cdf0e10cSrcweir     }
844cdf0e10cSrcweir 
845cdf0e10cSrcweir     ASSERT( pOut, "GetScalingOfSelectedText without outdev" )
846cdf0e10cSrcweir 
847cdf0e10cSrcweir     MapMode aOldMap( pOut->GetMapMode() );
848cdf0e10cSrcweir 	pOut->SetMapMode( MapMode( MAP_TWIP ) );
849cdf0e10cSrcweir 
850cdf0e10cSrcweir     if ( nStt == nEnd )
851cdf0e10cSrcweir     {
852cdf0e10cSrcweir         if ( !pBreakIt->GetBreakIter().is() )
853cdf0e10cSrcweir             return 100;
854cdf0e10cSrcweir 
855cdf0e10cSrcweir         SwScriptInfo aScriptInfo;
856cdf0e10cSrcweir         SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
857cdf0e10cSrcweir         aIter.SeekAndChgAttrIter( nStt, pOut );
858cdf0e10cSrcweir 
859cdf0e10cSrcweir         Boundary aBound =
860cdf0e10cSrcweir             pBreakIt->GetBreakIter()->getWordBoundary( GetTxt(), nStt,
861cdf0e10cSrcweir             pBreakIt->GetLocale( aIter.GetFnt()->GetLanguage() ),
862cdf0e10cSrcweir             WordType::DICTIONARY_WORD, sal_True );
863cdf0e10cSrcweir 
864cdf0e10cSrcweir         if ( nStt == aBound.startPos )
865cdf0e10cSrcweir         {
866cdf0e10cSrcweir             // cursor is at left or right border of word
867cdf0e10cSrcweir             pOut->SetMapMode( aOldMap );
868cdf0e10cSrcweir             return 100;
869cdf0e10cSrcweir         }
870cdf0e10cSrcweir 
871cdf0e10cSrcweir         nStt = (xub_StrLen)aBound.startPos;
872cdf0e10cSrcweir         nEnd = (xub_StrLen)aBound.endPos;
873cdf0e10cSrcweir 
874cdf0e10cSrcweir         if ( nStt == nEnd )
875cdf0e10cSrcweir         {
876cdf0e10cSrcweir             pOut->SetMapMode( aOldMap );
877cdf0e10cSrcweir             return 100;
878cdf0e10cSrcweir         }
879cdf0e10cSrcweir     }
880cdf0e10cSrcweir 
881cdf0e10cSrcweir     SwScriptInfo aScriptInfo;
882cdf0e10cSrcweir 	SwAttrIter aIter( *(SwTxtNode*)this, aScriptInfo );
883cdf0e10cSrcweir 
884cdf0e10cSrcweir     // We do not want scaling attributes to be considered during this
885cdf0e10cSrcweir     // calculation. For this, we push a temporary scaling attribute with
886cdf0e10cSrcweir     // scaling value 100 and priority flag on top of the scaling stack
887cdf0e10cSrcweir     SwAttrHandler& rAH = aIter.GetAttrHandler();
888cdf0e10cSrcweir     SvxCharScaleWidthItem aItem(100, RES_CHRATR_SCALEW);
889cdf0e10cSrcweir     SwTxtAttrEnd aAttr( aItem, nStt, nEnd );
890cdf0e10cSrcweir     aAttr.SetPriorityAttr( sal_True );
891cdf0e10cSrcweir     rAH.PushAndChg( aAttr, *(aIter.GetFnt()) );
892cdf0e10cSrcweir 
893cdf0e10cSrcweir     xub_StrLen nIdx = nStt;
894cdf0e10cSrcweir 
895cdf0e10cSrcweir 	sal_uLong nWidth = 0;
896cdf0e10cSrcweir 	sal_uLong nProWidth = 0;
897cdf0e10cSrcweir 
898cdf0e10cSrcweir 	while( nIdx < nEnd )
899cdf0e10cSrcweir 	{
900cdf0e10cSrcweir 		aIter.SeekAndChgAttrIter( nIdx, pOut );
901cdf0e10cSrcweir 
902cdf0e10cSrcweir 		// scan for end of portion
903cdf0e10cSrcweir 		xub_StrLen nNextChg = aIter.GetNextAttr();
904cdf0e10cSrcweir 		xub_StrLen nStop = aScriptInfo.NextScriptChg( nIdx );
905cdf0e10cSrcweir 		if( nNextChg > nStop )
906cdf0e10cSrcweir 			nNextChg = nStop;
907cdf0e10cSrcweir 
908cdf0e10cSrcweir 		nStop = nIdx;
909cdf0e10cSrcweir 		xub_Unicode cChar = CH_BLANK;
910cdf0e10cSrcweir         SwTxtAttr* pHint = NULL;
911cdf0e10cSrcweir 
912cdf0e10cSrcweir         // stop at special characters in [ nIdx, nNextChg ]
913cdf0e10cSrcweir         while( nStop < nEnd && nStop < nNextChg )
914cdf0e10cSrcweir         {
915cdf0e10cSrcweir             cChar = m_Text.GetChar( nStop );
916cdf0e10cSrcweir             if (
917cdf0e10cSrcweir                 CH_TAB == cChar ||
918cdf0e10cSrcweir                 CH_BREAK == cChar ||
919cdf0e10cSrcweir                 CHAR_HARDBLANK == cChar ||
920cdf0e10cSrcweir                 CHAR_HARDHYPHEN == cChar ||
921cdf0e10cSrcweir                 CHAR_SOFTHYPHEN == cChar ||
922cdf0e10cSrcweir                 (
923cdf0e10cSrcweir                   (CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar) &&
924cdf0e10cSrcweir                   (0 == (pHint = aIter.GetAttr(nStop)))
925cdf0e10cSrcweir                 )
926cdf0e10cSrcweir                )
927cdf0e10cSrcweir             {
928cdf0e10cSrcweir                 break;
929cdf0e10cSrcweir             }
930cdf0e10cSrcweir             else
931cdf0e10cSrcweir                 ++nStop;
932cdf0e10cSrcweir         }
933cdf0e10cSrcweir 
934cdf0e10cSrcweir 		// calculate text widths up to cChar
935cdf0e10cSrcweir         if ( nStop > nIdx )
936cdf0e10cSrcweir         {
937cdf0e10cSrcweir             SwDrawTextInfo aDrawInf( pSh, *pOut, 0, GetTxt(), nIdx, nStop - nIdx );
938cdf0e10cSrcweir             nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
939cdf0e10cSrcweir         }
940cdf0e10cSrcweir 
941cdf0e10cSrcweir 		nIdx = nStop;
942cdf0e10cSrcweir 		aIter.SeekAndChgAttrIter( nIdx, pOut );
943cdf0e10cSrcweir 
944cdf0e10cSrcweir 		if ( cChar == CH_BREAK )
945cdf0e10cSrcweir 		{
946cdf0e10cSrcweir 			nWidth = Max( nWidth, nProWidth );
947cdf0e10cSrcweir 			nProWidth = 0;
948cdf0e10cSrcweir 			nIdx++;
949cdf0e10cSrcweir 		}
950cdf0e10cSrcweir 		else if ( cChar == CH_TAB )
951cdf0e10cSrcweir 		{
952cdf0e10cSrcweir 			// tab receives width of one space
953cdf0e10cSrcweir             XubString sTmp( CH_BLANK );
954cdf0e10cSrcweir             SwDrawTextInfo aDrawInf( pSh, *pOut, 0, sTmp, 0, 1 );
955cdf0e10cSrcweir             nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
956cdf0e10cSrcweir 			nIdx++;
957cdf0e10cSrcweir 		}
958cdf0e10cSrcweir         else if ( cChar == CHAR_SOFTHYPHEN )
959cdf0e10cSrcweir             ++nIdx;
960cdf0e10cSrcweir         else if ( cChar == CHAR_HARDBLANK || cChar == CHAR_HARDHYPHEN )
961cdf0e10cSrcweir         {
962cdf0e10cSrcweir             XubString sTmp( cChar );
963cdf0e10cSrcweir             SwDrawTextInfo aDrawInf( pSh, *pOut, 0, sTmp, 0, 1 );
964cdf0e10cSrcweir             nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
965dec99bbdSOliver-Rainer Wittmann             nIdx++;
966cdf0e10cSrcweir         }
967dec99bbdSOliver-Rainer Wittmann         else if ( pHint && ( cChar == CH_TXTATR_BREAKWORD || CH_TXTATR_INWORD ) )
968dec99bbdSOliver-Rainer Wittmann         {
969dec99bbdSOliver-Rainer Wittmann             switch( pHint->Which() )
970dec99bbdSOliver-Rainer Wittmann             {
971dec99bbdSOliver-Rainer Wittmann             case RES_TXTATR_FTN :
972dec99bbdSOliver-Rainer Wittmann                 {
973dec99bbdSOliver-Rainer Wittmann                     const XubString aTxt = pHint->GetFtn().GetNumStr();
974cdf0e10cSrcweir                     SwDrawTextInfo aDrawInf( pSh, *pOut, 0, aTxt, 0, aTxt.Len() );
975cdf0e10cSrcweir 
976cdf0e10cSrcweir                     nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
977dec99bbdSOliver-Rainer Wittmann                     break;
978dec99bbdSOliver-Rainer Wittmann                 }
979dec99bbdSOliver-Rainer Wittmann 
980dec99bbdSOliver-Rainer Wittmann             case RES_TXTATR_FIELD :
981dec99bbdSOliver-Rainer Wittmann             case RES_TXTATR_ANNOTATION :
982dec99bbdSOliver-Rainer Wittmann                 {
983dec99bbdSOliver-Rainer Wittmann                     SwField *pFld = (SwField*)pHint->GetFmtFld().GetField();
984cdf0e10cSrcweir                     String const aTxt = pFld->ExpandField(true);
985cdf0e10cSrcweir                     SwDrawTextInfo aDrawInf( pSh, *pOut, 0, aTxt, 0, aTxt.Len() );
986cdf0e10cSrcweir 
987cdf0e10cSrcweir                     nProWidth += aIter.GetFnt()->_GetTxtSize( aDrawInf ).Width();
988dec99bbdSOliver-Rainer Wittmann                     break;
989dec99bbdSOliver-Rainer Wittmann                 }
990dec99bbdSOliver-Rainer Wittmann 
991dec99bbdSOliver-Rainer Wittmann             default:
992dec99bbdSOliver-Rainer Wittmann                 {
993dec99bbdSOliver-Rainer Wittmann                     // any suggestions for a default action?
994dec99bbdSOliver-Rainer Wittmann                 }
995dec99bbdSOliver-Rainer Wittmann             } // end of switch
996dec99bbdSOliver-Rainer Wittmann             nIdx++;
997dec99bbdSOliver-Rainer Wittmann         } // end of while
998dec99bbdSOliver-Rainer Wittmann     }
999cdf0e10cSrcweir 
1000cdf0e10cSrcweir 	nWidth = Max( nWidth, nProWidth );
1001cdf0e10cSrcweir 
1002cdf0e10cSrcweir 	// search for a text frame this node belongs to
1003cdf0e10cSrcweir 	SwIterator<SwTxtFrm,SwTxtNode> aFrmIter( *this );
1004cdf0e10cSrcweir     SwTxtFrm* pFrm = 0;
1005cdf0e10cSrcweir     for( SwTxtFrm* pTmpFrm = aFrmIter.First(); pTmpFrm; pTmpFrm = aFrmIter.Next() )
1006cdf0e10cSrcweir 	{
1007cdf0e10cSrcweir 			if ( pTmpFrm->GetOfst() <= nStt &&
1008cdf0e10cSrcweir 				( !pTmpFrm->GetFollow() ||
1009cdf0e10cSrcweir 				   pTmpFrm->GetFollow()->GetOfst() > nStt )	)
1010cdf0e10cSrcweir 			{
1011cdf0e10cSrcweir 				pFrm = pTmpFrm;
1012cdf0e10cSrcweir 				break;
1013cdf0e10cSrcweir 			}
1014cdf0e10cSrcweir 		}
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir 	// search for the line containing nStt
1017cdf0e10cSrcweir     if ( pFrm && pFrm->HasPara() )
1018cdf0e10cSrcweir 	{
1019cdf0e10cSrcweir 		SwTxtInfo aInf( pFrm );
1020cdf0e10cSrcweir         SwTxtIter aLine( pFrm, &aInf );
1021cdf0e10cSrcweir 		aLine.CharToLine( nStt );
1022cdf0e10cSrcweir         pOut->SetMapMode( aOldMap );
1023cdf0e10cSrcweir         return (sal_uInt16)( nWidth ?
1024cdf0e10cSrcweir 			( ( 100 * aLine.GetCurr()->Height() ) / nWidth ) : 0 );
1025cdf0e10cSrcweir 	}
1026cdf0e10cSrcweir 	// no frame or no paragraph, we take the height of the character
1027cdf0e10cSrcweir 	// at nStt as line height
1028cdf0e10cSrcweir 
1029cdf0e10cSrcweir     aIter.SeekAndChgAttrIter( nStt, pOut );
1030cdf0e10cSrcweir     pOut->SetMapMode( aOldMap );
1031cdf0e10cSrcweir 
1032cdf0e10cSrcweir     SwDrawTextInfo aDrawInf( pSh, *pOut, 0, GetTxt(), nStt, 1 );
1033cdf0e10cSrcweir     return (sal_uInt16)
1034cdf0e10cSrcweir            ( nWidth ? ((100 * aIter.GetFnt()->_GetTxtSize( aDrawInf ).Height()) / nWidth ) : 0 );
1035cdf0e10cSrcweir }
1036cdf0e10cSrcweir 
GetWidthOfLeadingTabs() const1037cdf0e10cSrcweir sal_uInt16 SwTxtNode::GetWidthOfLeadingTabs() const
1038cdf0e10cSrcweir {
1039cdf0e10cSrcweir     sal_uInt16 nRet = 0;
1040cdf0e10cSrcweir 
1041cdf0e10cSrcweir     xub_StrLen nIdx = 0;
1042cdf0e10cSrcweir     sal_Unicode cCh;
1043cdf0e10cSrcweir 
1044cdf0e10cSrcweir     while ( nIdx < GetTxt().Len() &&
1045cdf0e10cSrcweir              ( '\t' == ( cCh = GetTxt().GetChar( nIdx ) ) ||
1046cdf0e10cSrcweir                 ' ' == cCh ) )
1047cdf0e10cSrcweir         ++nIdx;
1048cdf0e10cSrcweir 
1049cdf0e10cSrcweir     if ( nIdx > 0 )
1050cdf0e10cSrcweir     {
1051cdf0e10cSrcweir         SwPosition aPos( *this );
1052cdf0e10cSrcweir         aPos.nContent += nIdx;
1053cdf0e10cSrcweir 
1054cdf0e10cSrcweir         // Find the non-follow text frame:
1055cdf0e10cSrcweir 	    SwIterator<SwTxtFrm,SwTxtNode> aIter( *this );
1056cdf0e10cSrcweir         for( SwTxtFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
1057cdf0e10cSrcweir         {
1058cdf0e10cSrcweir             // Only consider master frames:
1059cdf0e10cSrcweir             if ( !pFrm->IsFollow() )
1060cdf0e10cSrcweir             {
1061cdf0e10cSrcweir                 SWRECTFN( pFrm )
1062cdf0e10cSrcweir                 SwRect aRect;
1063cdf0e10cSrcweir                 pFrm->GetCharRect( aRect, aPos );
1064cdf0e10cSrcweir                 nRet = (sal_uInt16)
1065cdf0e10cSrcweir                        ( pFrm->IsRightToLeft() ?
1066cdf0e10cSrcweir                             (pFrm->*fnRect->fnGetPrtRight)() - (aRect.*fnRect->fnGetRight)() :
1067cdf0e10cSrcweir                             (aRect.*fnRect->fnGetLeft)() - (pFrm->*fnRect->fnGetPrtLeft)() );
1068cdf0e10cSrcweir                 break;
1069cdf0e10cSrcweir             }
1070cdf0e10cSrcweir         }
1071cdf0e10cSrcweir     }
1072cdf0e10cSrcweir 
1073cdf0e10cSrcweir     return nRet;
1074cdf0e10cSrcweir }
1075