xref: /aoo42x/main/sw/source/core/text/itrcrsr.cxx (revision ebe15e47)
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 #include "hintids.hxx"
28cdf0e10cSrcweir #include "errhdl.hxx"
29cdf0e10cSrcweir #include "ndtxt.hxx"
30cdf0e10cSrcweir #include "frmfmt.hxx"
31cdf0e10cSrcweir #include "paratr.hxx"
32cdf0e10cSrcweir #include "flyfrm.hxx"
33cdf0e10cSrcweir #include "pam.hxx"
34cdf0e10cSrcweir #include "swselectionlist.hxx"
35cdf0e10cSrcweir #include <sortedobjs.hxx>
36cdf0e10cSrcweir #include <editeng/protitem.hxx>
37cdf0e10cSrcweir #include <editeng/adjitem.hxx>
38cdf0e10cSrcweir #include <editeng/lspcitem.hxx>
39cdf0e10cSrcweir #include <editeng/lrspitem.hxx>
40cdf0e10cSrcweir #include <frmatr.hxx>
41cdf0e10cSrcweir #include <pagedesc.hxx> // SwPageDesc
42cdf0e10cSrcweir #include <tgrditem.hxx>
43cdf0e10cSrcweir #include <IDocumentSettingAccess.hxx>
44cdf0e10cSrcweir #include <pagefrm.hxx>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir #include "txtcfg.hxx"
47cdf0e10cSrcweir #include "itrtxt.hxx"
48cdf0e10cSrcweir #include "txtfrm.hxx"
49cdf0e10cSrcweir #include "flyfrms.hxx"
50cdf0e10cSrcweir #include "porglue.hxx"		// SwFlyCnt
51cdf0e10cSrcweir #include "porfld.hxx"		// SwFldPortion::IsFollow()
52cdf0e10cSrcweir #include "porfly.hxx"		// GetFlyCrsrOfst()
53cdf0e10cSrcweir #include "pordrop.hxx"
54cdf0e10cSrcweir #include "crstate.hxx"      // SwCrsrMoveState
55cdf0e10cSrcweir #include <pormulti.hxx> 	// SwMultiPortion
56cdf0e10cSrcweir // --> OD 2010-05-05 #i111284#
57cdf0e10cSrcweir #include <numrule.hxx>
58cdf0e10cSrcweir // <--
5929092756SKay Schenk #include <com/sun/star/i18n/ScriptType.hpp>
60cdf0e10cSrcweir 
61cdf0e10cSrcweir // Nicht reentrant !!!
62cdf0e10cSrcweir // wird in GetCharRect gesetzt und im UnitUp/Down ausgewertet.
63cdf0e10cSrcweir sal_Bool SwTxtCursor::bRightMargin = sal_False;
64cdf0e10cSrcweir 
65cdf0e10cSrcweir 
66cdf0e10cSrcweir /*************************************************************************
67cdf0e10cSrcweir  *                    lcl_GetCharRectInsideField
68cdf0e10cSrcweir  *
69cdf0e10cSrcweir  * After calculating the position of a character during GetCharRect
70cdf0e10cSrcweir  * this function allows to find the coordinates of a position (defined
71cdf0e10cSrcweir  * in pCMS->pSpecialPos) inside a special portion (e.g., a field)
72cdf0e10cSrcweir  *************************************************************************/
lcl_GetCharRectInsideField(SwTxtSizeInfo & rInf,SwRect & rOrig,const SwCrsrMoveState & rCMS,const SwLinePortion & rPor)73cdf0e10cSrcweir void lcl_GetCharRectInsideField( SwTxtSizeInfo& rInf, SwRect& rOrig,
74cdf0e10cSrcweir                                  const SwCrsrMoveState& rCMS,
75cdf0e10cSrcweir                                  const SwLinePortion& rPor )
76cdf0e10cSrcweir {
77cdf0e10cSrcweir     ASSERT( rCMS.pSpecialPos, "Information about special pos missing" )
78cdf0e10cSrcweir 
79cdf0e10cSrcweir     if ( rPor.InFldGrp() && ((SwFldPortion&)rPor).GetExp().Len() )
80cdf0e10cSrcweir     {
81cdf0e10cSrcweir         const sal_uInt16 nCharOfst = rCMS.pSpecialPos->nCharOfst;
82cdf0e10cSrcweir         sal_uInt16 nFldIdx = 0;
83cdf0e10cSrcweir         sal_uInt16 nFldLen = 0;
84cdf0e10cSrcweir 
85cdf0e10cSrcweir         const XubString* pString = 0;
86cdf0e10cSrcweir         const SwLinePortion* pPor = &rPor;
87cdf0e10cSrcweir         do
88cdf0e10cSrcweir         {
89cdf0e10cSrcweir             if ( pPor->InFldGrp() )
90cdf0e10cSrcweir             {
91cdf0e10cSrcweir                 pString = &((SwFldPortion*)pPor)->GetExp();
92cdf0e10cSrcweir                 nFldLen = pString->Len();
93cdf0e10cSrcweir             }
94cdf0e10cSrcweir             else
95cdf0e10cSrcweir             {
96cdf0e10cSrcweir                 pString = 0;
97cdf0e10cSrcweir                 nFldLen = 0;
98cdf0e10cSrcweir             }
99cdf0e10cSrcweir 
100cdf0e10cSrcweir             if ( ! pPor->GetPortion() || nFldIdx + nFldLen > nCharOfst )
101cdf0e10cSrcweir                 break;
102cdf0e10cSrcweir 
103cdf0e10cSrcweir             nFldIdx = nFldIdx + nFldLen;
104cdf0e10cSrcweir             rOrig.Pos().X() += pPor->Width();
105cdf0e10cSrcweir             pPor = pPor->GetPortion();
106cdf0e10cSrcweir 
107cdf0e10cSrcweir         } while ( sal_True );
108cdf0e10cSrcweir 
109cdf0e10cSrcweir         ASSERT( nCharOfst >= nFldIdx, "Request of position inside field failed" )
110cdf0e10cSrcweir         sal_uInt16 nLen = nCharOfst - nFldIdx + 1;
111cdf0e10cSrcweir 
112cdf0e10cSrcweir         if ( pString )
113cdf0e10cSrcweir         {
114cdf0e10cSrcweir             // get script for field portion
115cdf0e10cSrcweir             rInf.GetFont()->SetActual( SwScriptInfo::WhichFont( 0, pString, 0 ) );
116cdf0e10cSrcweir 
117cdf0e10cSrcweir             xub_StrLen nOldLen = pPor->GetLen();
118cdf0e10cSrcweir             ((SwLinePortion*)pPor)->SetLen( nLen - 1 );
119cdf0e10cSrcweir             const SwTwips nX1 = pPor->GetLen() ?
120cdf0e10cSrcweir                                 pPor->GetTxtSize( rInf ).Width() :
121cdf0e10cSrcweir                                 0;
122cdf0e10cSrcweir 
123cdf0e10cSrcweir             SwTwips nX2 = 0;
124cdf0e10cSrcweir             if ( rCMS.bRealWidth )
125cdf0e10cSrcweir             {
126cdf0e10cSrcweir                 ((SwLinePortion*)pPor)->SetLen( nLen );
127cdf0e10cSrcweir                 nX2 = pPor->GetTxtSize( rInf ).Width();
128cdf0e10cSrcweir             }
129cdf0e10cSrcweir 
130cdf0e10cSrcweir             ((SwLinePortion*)pPor)->SetLen( nOldLen );
131cdf0e10cSrcweir 
132cdf0e10cSrcweir             rOrig.Pos().X() += nX1;
133cdf0e10cSrcweir             rOrig.Width( ( nX2 > nX1 ) ?
134cdf0e10cSrcweir                          ( nX2 - nX1 ) :
135cdf0e10cSrcweir                            1 );
136cdf0e10cSrcweir         }
137cdf0e10cSrcweir     }
138cdf0e10cSrcweir     else
139cdf0e10cSrcweir     {
140cdf0e10cSrcweir         // special cases: no common fields, e.g., graphic number portion,
141cdf0e10cSrcweir         // FlyInCntPortions, Notes
142cdf0e10cSrcweir         rOrig.Width( rCMS.bRealWidth && rPor.Width() ? rPor.Width() : 1 );
143cdf0e10cSrcweir     }
144cdf0e10cSrcweir }
145cdf0e10cSrcweir 
146cdf0e10cSrcweir // --> OD 2010-05-05 #i111284#
147cdf0e10cSrcweir namespace {
AreListLevelIndentsApplicableAndLabelAlignmentActive(const SwTxtNode & rTxtNode)148cdf0e10cSrcweir     bool AreListLevelIndentsApplicableAndLabelAlignmentActive( const SwTxtNode& rTxtNode )
149cdf0e10cSrcweir     {
150cdf0e10cSrcweir         bool bRet( false );
151cdf0e10cSrcweir 
152cdf0e10cSrcweir         if ( rTxtNode.AreListLevelIndentsApplicable() )
153cdf0e10cSrcweir         {
154cdf0e10cSrcweir             const SwNumFmt& rNumFmt =
155cdf0e10cSrcweir                     rTxtNode.GetNumRule()->Get( static_cast<sal_uInt16>(rTxtNode.GetActualListLevel()) );
156cdf0e10cSrcweir             if ( rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
157cdf0e10cSrcweir             {
158cdf0e10cSrcweir                 bRet = true;
159cdf0e10cSrcweir             }
160cdf0e10cSrcweir         }
161cdf0e10cSrcweir 
162cdf0e10cSrcweir         return bRet;
163cdf0e10cSrcweir     }
164cdf0e10cSrcweir } // end of anonymous namespace
165cdf0e10cSrcweir // <--
166cdf0e10cSrcweir 
167cdf0e10cSrcweir /*************************************************************************
168cdf0e10cSrcweir  *				  SwTxtMargin::CtorInitTxtMargin()
169cdf0e10cSrcweir  *************************************************************************/
CtorInitTxtMargin(SwTxtFrm * pNewFrm,SwTxtSizeInfo * pNewInf)170cdf0e10cSrcweir void SwTxtMargin::CtorInitTxtMargin( SwTxtFrm *pNewFrm, SwTxtSizeInfo *pNewInf )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir 	CtorInitTxtIter( pNewFrm, pNewInf );
173cdf0e10cSrcweir 
174cdf0e10cSrcweir 	pInf = pNewInf;
175cdf0e10cSrcweir 	GetInfo().SetFont( GetFnt() );
176cdf0e10cSrcweir 	const SwTxtNode *pNode = pFrm->GetTxtNode();
177cdf0e10cSrcweir 
178cdf0e10cSrcweir     const SvxLRSpaceItem &rSpace = pFrm->GetTxtNode()->GetSwAttrSet().GetLRSpace();
179cdf0e10cSrcweir     // --> OD 2009-09-08 #i95907#, #b6879723#
180cdf0e10cSrcweir     // --> OD 2010-05-05 #i111284#
181cdf0e10cSrcweir     const bool bListLevelIndentsApplicableAndLabelAlignmentActive(
182cdf0e10cSrcweir         AreListLevelIndentsApplicableAndLabelAlignmentActive( *(pFrm->GetTxtNode()) ) );
183cdf0e10cSrcweir     // <--
184cdf0e10cSrcweir 
185cdf0e10cSrcweir     //
186cdf0e10cSrcweir     // Carefully adjust the text formatting ranges.
187cdf0e10cSrcweir     //
188cdf0e10cSrcweir     // This whole area desperately needs some rework. There are
189cdf0e10cSrcweir     // quite a couple of values that need to be considered:
190cdf0e10cSrcweir     // 1. paragraph indent
191cdf0e10cSrcweir     // 2. paragraph first line indent
192cdf0e10cSrcweir     // 3. numbering indent
193cdf0e10cSrcweir     // 4. numbering spacing to text
194cdf0e10cSrcweir     // 5. paragraph border
195cdf0e10cSrcweir     // Note: These values have already been used during calculation
196cdf0e10cSrcweir     // of the printing area of the paragraph.
197cdf0e10cSrcweir     const int nLMWithNum = pNode->GetLeftMarginWithNum( sal_True );
198cdf0e10cSrcweir     if ( pFrm->IsRightToLeft() )
199cdf0e10cSrcweir     {
200cdf0e10cSrcweir         // --> OD 2008-01-23 #newlistlevelattrs#
201cdf0e10cSrcweir         // this calculation is identical this the calculation for L2R layout - see below
202cdf0e10cSrcweir         nLeft = pFrm->Frm().Left() +
203cdf0e10cSrcweir                 pFrm->Prt().Left() +
204cdf0e10cSrcweir                 nLMWithNum -
205cdf0e10cSrcweir                 pNode->GetLeftMarginWithNum( sal_False ) -
206cdf0e10cSrcweir                 // --> OD 2009-09-08 #i95907#, #b6879723#
207cdf0e10cSrcweir                 // --> OD 2010-05-05 #i111284#
208cdf0e10cSrcweir //                rSpace.GetLeft() +
209cdf0e10cSrcweir //                rSpace.GetTxtLeft();
210cdf0e10cSrcweir                 ( bListLevelIndentsApplicableAndLabelAlignmentActive
211cdf0e10cSrcweir                   ? 0
212cdf0e10cSrcweir                   : ( rSpace.GetLeft() - rSpace.GetTxtLeft() ) );
213cdf0e10cSrcweir                 // <--
214cdf0e10cSrcweir     }
215cdf0e10cSrcweir     else
216cdf0e10cSrcweir     {
217cdf0e10cSrcweir         // --> OD 2009-09-08 #i95907#, #b6879723#
218cdf0e10cSrcweir         // --> OD 2010-05-05 #i111284#
219cdf0e10cSrcweir //        if ( !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
220cdf0e10cSrcweir         if ( bListLevelIndentsApplicableAndLabelAlignmentActive ||
221cdf0e10cSrcweir              !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
222cdf0e10cSrcweir         // <--
223cdf0e10cSrcweir         {
224cdf0e10cSrcweir             // this calculation is identical this the calculation for R2L layout - see above
225cdf0e10cSrcweir             nLeft = pFrm->Frm().Left() +
226cdf0e10cSrcweir                     pFrm->Prt().Left() +
227cdf0e10cSrcweir                     nLMWithNum -
228cdf0e10cSrcweir                     pNode->GetLeftMarginWithNum( sal_False ) -
229cdf0e10cSrcweir                     // --> OD 2009-09-08 #i95907#, #b6879723#
230cdf0e10cSrcweir                     // --> OD 2010-05-05 #i111284#
231cdf0e10cSrcweir //                    rSpace.GetLeft() +
232cdf0e10cSrcweir //                    rSpace.GetTxtLeft();
233cdf0e10cSrcweir                     ( bListLevelIndentsApplicableAndLabelAlignmentActive
234cdf0e10cSrcweir                       ? 0
235cdf0e10cSrcweir                       : ( rSpace.GetLeft() - rSpace.GetTxtLeft() ) );
236cdf0e10cSrcweir                     // <--
237cdf0e10cSrcweir         }
238cdf0e10cSrcweir         else
239cdf0e10cSrcweir         {
240cdf0e10cSrcweir             nLeft = pFrm->Frm().Left() +
241cdf0e10cSrcweir                     Max( long( rSpace.GetTxtLeft() + nLMWithNum ),
242cdf0e10cSrcweir                          pFrm->Prt().Left() );
243cdf0e10cSrcweir         }
244cdf0e10cSrcweir     }
245cdf0e10cSrcweir 
246cdf0e10cSrcweir     nRight = pFrm->Frm().Left() + pFrm->Prt().Left() + pFrm->Prt().Width();
247cdf0e10cSrcweir 
248cdf0e10cSrcweir 	if( nLeft >= nRight &&
249cdf0e10cSrcweir          // --> FME 2005-08-10 #i53066# Omit adjustment of nLeft for numbered
250cdf0e10cSrcweir          // paras inside cells inside new documents:
251cdf0e10cSrcweir         ( pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) ||
252cdf0e10cSrcweir           !pFrm->IsInTab() ||
253cdf0e10cSrcweir           !nLMWithNum ) )
254cdf0e10cSrcweir          // <--
255cdf0e10cSrcweir     {
256cdf0e10cSrcweir 		nLeft = pFrm->Prt().Left() + pFrm->Frm().Left();
257cdf0e10cSrcweir 	    if( nLeft >= nRight )   // z.B. bei grossen Absatzeinzuegen in schmalen Tabellenspalten
258cdf0e10cSrcweir 		    nRight = nLeft + 1; // einen goennen wir uns immer
259cdf0e10cSrcweir     }
260cdf0e10cSrcweir 
261cdf0e10cSrcweir 	if( pFrm->IsFollow() && pFrm->GetOfst() )
262cdf0e10cSrcweir 		nFirst = nLeft;
263cdf0e10cSrcweir 	else
264cdf0e10cSrcweir 	{
265cdf0e10cSrcweir         short nFLOfst = 0;
266cdf0e10cSrcweir         long nFirstLineOfs = 0;
267cdf0e10cSrcweir 		if( !pNode->GetFirstLineOfsWithNum( nFLOfst ) &&
268cdf0e10cSrcweir 			rSpace.IsAutoFirst() )
269cdf0e10cSrcweir 		{
270cdf0e10cSrcweir 			nFirstLineOfs = GetFnt()->GetSize( GetFnt()->GetActual() ).Height();
27129092756SKay Schenk                         LanguageType aLang = pNode->GetLang( 0, 1, i18n::ScriptType::ASIAN);
27229092756SKay Schenk                         if (aLang != LANGUAGE_KOREAN && aLang != LANGUAGE_JAPANESE)
27329092756SKay Schenk                             nFirstLineOfs<<=1;
274cdf0e10cSrcweir 			const SvxLineSpacingItem *pSpace = aLineInf.GetLineSpacing();
275cdf0e10cSrcweir 			if( pSpace )
276cdf0e10cSrcweir 			{
277cdf0e10cSrcweir 				switch( pSpace->GetLineSpaceRule() )
278cdf0e10cSrcweir 				{
279cdf0e10cSrcweir 					case SVX_LINE_SPACE_AUTO:
280cdf0e10cSrcweir 					break;
281cdf0e10cSrcweir 					case SVX_LINE_SPACE_MIN:
282cdf0e10cSrcweir 					{
283cdf0e10cSrcweir 						if( nFirstLineOfs < KSHORT( pSpace->GetLineHeight() ) )
284cdf0e10cSrcweir 							nFirstLineOfs = pSpace->GetLineHeight();
285cdf0e10cSrcweir 						break;
286cdf0e10cSrcweir 					}
287cdf0e10cSrcweir 					case SVX_LINE_SPACE_FIX:
288cdf0e10cSrcweir 						nFirstLineOfs = pSpace->GetLineHeight();
289cdf0e10cSrcweir 					break;
290cdf0e10cSrcweir 					default: ASSERT( sal_False, ": unknown LineSpaceRule" );
291cdf0e10cSrcweir 				}
292cdf0e10cSrcweir 				switch( pSpace->GetInterLineSpaceRule() )
293cdf0e10cSrcweir 				{
294cdf0e10cSrcweir 					case SVX_INTER_LINE_SPACE_OFF:
295cdf0e10cSrcweir 					break;
296cdf0e10cSrcweir 					case SVX_INTER_LINE_SPACE_PROP:
297cdf0e10cSrcweir 					{
298cdf0e10cSrcweir 						long nTmp = pSpace->GetPropLineSpace();
299cdf0e10cSrcweir 						// 50% ist das Minimum, bei 0% schalten wir auf
300cdf0e10cSrcweir 						// den Defaultwert 100% um ...
301cdf0e10cSrcweir 						if( nTmp < 50 )
302cdf0e10cSrcweir 							nTmp = nTmp ? 50 : 100;
303cdf0e10cSrcweir 
304cdf0e10cSrcweir 						nTmp *= nFirstLineOfs;
305cdf0e10cSrcweir 						nTmp /= 100;
306cdf0e10cSrcweir 						if( !nTmp )
307cdf0e10cSrcweir 							++nTmp;
308cdf0e10cSrcweir 						nFirstLineOfs = (KSHORT)nTmp;
309cdf0e10cSrcweir 						break;
310cdf0e10cSrcweir 					}
311cdf0e10cSrcweir 					case SVX_INTER_LINE_SPACE_FIX:
312cdf0e10cSrcweir 					{
313cdf0e10cSrcweir 						nFirstLineOfs += pSpace->GetInterLineSpace();
314cdf0e10cSrcweir 						break;
315cdf0e10cSrcweir 					}
316cdf0e10cSrcweir 					default: ASSERT( sal_False, ": unknown InterLineSpaceRule" );
317cdf0e10cSrcweir 				}
318cdf0e10cSrcweir 			}
319cdf0e10cSrcweir 		}
320cdf0e10cSrcweir 		else
321cdf0e10cSrcweir 			nFirstLineOfs = nFLOfst;
322cdf0e10cSrcweir 
323cdf0e10cSrcweir         // --> OD 2009-09-08 #i95907#, #b6879723#
324cdf0e10cSrcweir         // --> OD 2010-05-05 #i111284#
325cdf0e10cSrcweir //        if ( pFrm->IsRightToLeft() ||
326cdf0e10cSrcweir //             !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
327cdf0e10cSrcweir         if ( pFrm->IsRightToLeft() ||
328cdf0e10cSrcweir              bListLevelIndentsApplicableAndLabelAlignmentActive ||
329cdf0e10cSrcweir              !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
330cdf0e10cSrcweir         // <--
331cdf0e10cSrcweir         {
332cdf0e10cSrcweir             nFirst = nLeft + nFirstLineOfs;
333cdf0e10cSrcweir         }
334cdf0e10cSrcweir         else
335cdf0e10cSrcweir         {
336cdf0e10cSrcweir       	    nFirst = pFrm->Frm().Left() +
337cdf0e10cSrcweir                      Max( rSpace.GetTxtLeft() + nLMWithNum+ nFirstLineOfs,
338cdf0e10cSrcweir                           pFrm->Prt().Left() );
339cdf0e10cSrcweir         }
340cdf0e10cSrcweir 
341cdf0e10cSrcweir         // --> OD 2008-01-31 #newlistlevelattrs#
342cdf0e10cSrcweir         // Note: <SwTxtFrm::GetAdditionalFirstLineOffset()> returns a negative
343*ebe15e47SJohn Bampton         //       value for the new list label position and space mode LABEL_ALIGNMENT
344cdf0e10cSrcweir         //       and label alignment CENTER and RIGHT in L2R layout respectively
345cdf0e10cSrcweir         //       label alignment LEFT and CENTER in R2L layout
346cdf0e10cSrcweir         nFirst += pFrm->GetAdditionalFirstLineOffset();
347cdf0e10cSrcweir         // <--
348cdf0e10cSrcweir 
349cdf0e10cSrcweir 		if( nFirst >= nRight )
350cdf0e10cSrcweir 			nFirst = nRight - 1;
351cdf0e10cSrcweir 	}
352cdf0e10cSrcweir     const SvxAdjustItem& rAdjust = pFrm->GetTxtNode()->GetSwAttrSet().GetAdjust();
353cdf0e10cSrcweir 	nAdjust = static_cast<sal_uInt16>(rAdjust.GetAdjust());
354cdf0e10cSrcweir 
355cdf0e10cSrcweir     // left is left and right is right
356cdf0e10cSrcweir     if ( pFrm->IsRightToLeft() )
357cdf0e10cSrcweir     {
358cdf0e10cSrcweir         if ( SVX_ADJUST_LEFT == nAdjust )
359cdf0e10cSrcweir             nAdjust = SVX_ADJUST_RIGHT;
360cdf0e10cSrcweir         else if ( SVX_ADJUST_RIGHT == nAdjust )
361cdf0e10cSrcweir             nAdjust = SVX_ADJUST_LEFT;
362cdf0e10cSrcweir     }
363cdf0e10cSrcweir 
364cdf0e10cSrcweir 	bOneBlock = rAdjust.GetOneWord() == SVX_ADJUST_BLOCK;
365cdf0e10cSrcweir 	bLastBlock = rAdjust.GetLastBlock() == SVX_ADJUST_BLOCK;
366cdf0e10cSrcweir 	bLastCenter = rAdjust.GetLastBlock() == SVX_ADJUST_CENTER;
367cdf0e10cSrcweir 
368cdf0e10cSrcweir     // --> OD 2008-07-01 #i91133#
369cdf0e10cSrcweir     mnTabLeft = pNode->GetLeftMarginForTabCalculation();
370cdf0e10cSrcweir     // <--
371cdf0e10cSrcweir 
372cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
373cdf0e10cSrcweir 	static sal_Bool bOne = sal_False;
374cdf0e10cSrcweir 	static sal_Bool bLast = sal_False;
375cdf0e10cSrcweir 	static sal_Bool bCenter = sal_False;
376cdf0e10cSrcweir 	bOneBlock |= bOne;
377cdf0e10cSrcweir 	bLastBlock |= bLast;
378cdf0e10cSrcweir 	bLastCenter |= bCenter;
379cdf0e10cSrcweir #endif
380cdf0e10cSrcweir 	DropInit();
381cdf0e10cSrcweir }
382cdf0e10cSrcweir 
383cdf0e10cSrcweir /*************************************************************************
384cdf0e10cSrcweir  *				  SwTxtMargin::DropInit()
385cdf0e10cSrcweir  *************************************************************************/
DropInit()386cdf0e10cSrcweir void SwTxtMargin::DropInit()
387cdf0e10cSrcweir {
388cdf0e10cSrcweir 	nDropLeft = nDropLines = nDropHeight = nDropDescent = 0;
389cdf0e10cSrcweir 	const SwParaPortion *pPara = GetInfo().GetParaPortion();
390cdf0e10cSrcweir 	if( pPara )
391cdf0e10cSrcweir 	{
392cdf0e10cSrcweir 		const SwDropPortion *pPorDrop = pPara->FindDropPortion();
393cdf0e10cSrcweir 		if ( pPorDrop )
394cdf0e10cSrcweir 		{
395cdf0e10cSrcweir 			nDropLeft = pPorDrop->GetDropLeft();
396cdf0e10cSrcweir 			nDropLines = pPorDrop->GetLines();
397cdf0e10cSrcweir 			nDropHeight = pPorDrop->GetDropHeight();
398cdf0e10cSrcweir 			nDropDescent = pPorDrop->GetDropDescent();
399cdf0e10cSrcweir 		}
400cdf0e10cSrcweir 	}
401cdf0e10cSrcweir }
402cdf0e10cSrcweir 
403cdf0e10cSrcweir /*************************************************************************
404cdf0e10cSrcweir  *				  SwTxtMargin::GetLineStart()
405cdf0e10cSrcweir  *************************************************************************/
406cdf0e10cSrcweir 
407cdf0e10cSrcweir // Unter Beruecksichtigung des Erstzeileneinzuges und der angebenen Breite.
GetLineStart() const408cdf0e10cSrcweir SwTwips SwTxtMargin::GetLineStart() const
409cdf0e10cSrcweir {
410cdf0e10cSrcweir 	SwTwips nRet = GetLeftMargin();
411cdf0e10cSrcweir 	if( GetAdjust() != SVX_ADJUST_LEFT &&
412cdf0e10cSrcweir 		!pCurr->GetFirstPortion()->IsMarginPortion() )
413cdf0e10cSrcweir 	{
414cdf0e10cSrcweir 		// Wenn die erste Portion ein Margin ist, dann wird das
415cdf0e10cSrcweir 		// Adjustment durch die Portions ausgedrueckt.
416cdf0e10cSrcweir 		if( GetAdjust() == SVX_ADJUST_RIGHT )
417cdf0e10cSrcweir 			nRet = Right() - CurrWidth();
418cdf0e10cSrcweir 		else if( GetAdjust() == SVX_ADJUST_CENTER )
419cdf0e10cSrcweir 			nRet += (GetLineWidth() - CurrWidth()) / 2;
420cdf0e10cSrcweir 	}
421cdf0e10cSrcweir 	return nRet;
422cdf0e10cSrcweir }
423cdf0e10cSrcweir 
424cdf0e10cSrcweir /*************************************************************************
425cdf0e10cSrcweir  *						SwTxtCursor::CtorInitTxtCursor()
426cdf0e10cSrcweir  *************************************************************************/
CtorInitTxtCursor(SwTxtFrm * pNewFrm,SwTxtSizeInfo * pNewInf)427cdf0e10cSrcweir void SwTxtCursor::CtorInitTxtCursor( SwTxtFrm *pNewFrm, SwTxtSizeInfo *pNewInf )
428cdf0e10cSrcweir {
429cdf0e10cSrcweir 	CtorInitTxtMargin( pNewFrm, pNewInf );
430cdf0e10cSrcweir 	// 6096: Vorsicht, die Iteratoren sind abgeleitet!
431cdf0e10cSrcweir 	// GetInfo().SetOut( GetInfo().GetWin() );
432cdf0e10cSrcweir }
433cdf0e10cSrcweir 
434cdf0e10cSrcweir /*************************************************************************
435cdf0e10cSrcweir  *						SwTxtCursor::GetEndCharRect()
436cdf0e10cSrcweir  *************************************************************************/
437cdf0e10cSrcweir 
438cdf0e10cSrcweir // 1170: Antikbug: Shift-Ende vergisst das letzte Zeichen ...
439cdf0e10cSrcweir 
GetEndCharRect(SwRect * pOrig,const xub_StrLen nOfst,SwCrsrMoveState * pCMS,const long nMax)440cdf0e10cSrcweir sal_Bool SwTxtCursor::GetEndCharRect( SwRect* pOrig, const xub_StrLen nOfst,
441cdf0e10cSrcweir 								  SwCrsrMoveState* pCMS, const long nMax )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir 	// 1170: Mehrdeutigkeit von Dokumentpositionen
444cdf0e10cSrcweir 	bRightMargin = sal_True;
445cdf0e10cSrcweir 	CharCrsrToLine(nOfst);
446cdf0e10cSrcweir 
447cdf0e10cSrcweir 	// Etwas verdreht: nOfst bezeichnet die Position hinter dem letzten
448cdf0e10cSrcweir 	// Zeichen der letzten Zeile == Position vor dem ersten Zeichen der
449cdf0e10cSrcweir 	// Zeile in der wir gerade stehen:
450cdf0e10cSrcweir 	if( nOfst != GetStart() || !pCurr->GetLen() )
451cdf0e10cSrcweir 	{
452cdf0e10cSrcweir 		// 8810: Masterzeile RightMargin, danach LeftMargin
453cdf0e10cSrcweir 		const sal_Bool bRet = GetCharRect( pOrig, nOfst, pCMS, nMax );
454cdf0e10cSrcweir 		bRightMargin = nOfst >= GetEnd() && nOfst < GetInfo().GetTxt().Len();
455cdf0e10cSrcweir 		return bRet;
456cdf0e10cSrcweir 	}
457cdf0e10cSrcweir 
458cdf0e10cSrcweir 	if( !GetPrev() || !GetPrev()->GetLen() || !PrevLine() )
459cdf0e10cSrcweir 		return GetCharRect( pOrig, nOfst, pCMS, nMax );
460cdf0e10cSrcweir 
461cdf0e10cSrcweir 	// Adjustierung ggf. nachholen
462cdf0e10cSrcweir 	GetAdjusted();
463cdf0e10cSrcweir 
464cdf0e10cSrcweir 	KSHORT nX = 0;
465cdf0e10cSrcweir 	KSHORT nLast = 0;
466cdf0e10cSrcweir 	SwLinePortion *pPor = pCurr->GetFirstPortion();
467cdf0e10cSrcweir 
468cdf0e10cSrcweir 	KSHORT nTmpHeight, nTmpAscent;
469cdf0e10cSrcweir 	CalcAscentAndHeight( nTmpAscent, nTmpHeight );
470cdf0e10cSrcweir 	KSHORT nPorHeight = nTmpHeight;
471cdf0e10cSrcweir 	KSHORT nPorAscent = nTmpAscent;
472cdf0e10cSrcweir 
473cdf0e10cSrcweir 	// Die letzte Text/EndPortion der Zeile suchen
474cdf0e10cSrcweir 	while( pPor )
475cdf0e10cSrcweir 	{
476cdf0e10cSrcweir 		nX = nX + pPor->Width();
477cdf0e10cSrcweir 		if( pPor->InTxtGrp() || ( pPor->GetLen() && !pPor->IsFlyPortion()
478cdf0e10cSrcweir 			&& !pPor->IsHolePortion() ) || pPor->IsBreakPortion() )
479cdf0e10cSrcweir 		{
480cdf0e10cSrcweir 			nLast = nX;
481cdf0e10cSrcweir 			nPorHeight = pPor->Height();
482cdf0e10cSrcweir 			nPorAscent = pPor->GetAscent();
483cdf0e10cSrcweir 		}
484cdf0e10cSrcweir 		pPor = pPor->GetPortion();
485cdf0e10cSrcweir 	}
486cdf0e10cSrcweir 
487cdf0e10cSrcweir 	const Size aCharSize( 1, nTmpHeight );
488cdf0e10cSrcweir 	pOrig->Pos( GetTopLeft() );
489cdf0e10cSrcweir 	pOrig->SSize( aCharSize );
490cdf0e10cSrcweir 	pOrig->Pos().X() += nLast;
491cdf0e10cSrcweir 	const SwTwips nTmpRight = Right() - 1;
492cdf0e10cSrcweir 	if( pOrig->Left() > nTmpRight )
493cdf0e10cSrcweir 		pOrig->Pos().X() = nTmpRight;
494cdf0e10cSrcweir 
495cdf0e10cSrcweir 	if ( pCMS && pCMS->bRealHeight )
496cdf0e10cSrcweir 	{
497cdf0e10cSrcweir 		if ( nTmpAscent > nPorAscent )
498cdf0e10cSrcweir 			pCMS->aRealHeight.X() = nTmpAscent - nPorAscent;
499cdf0e10cSrcweir 		else
500cdf0e10cSrcweir 			pCMS->aRealHeight.X() = 0;
501cdf0e10cSrcweir 		ASSERT( nPorHeight, "GetCharRect: Missing Portion-Height" );
502cdf0e10cSrcweir 		pCMS->aRealHeight.Y() = nPorHeight;
503cdf0e10cSrcweir 	}
504cdf0e10cSrcweir 
505cdf0e10cSrcweir 	return sal_True;
506cdf0e10cSrcweir }
507cdf0e10cSrcweir 
508cdf0e10cSrcweir /*************************************************************************
509cdf0e10cSrcweir  * void	SwTxtCursor::_GetCharRect(..)
510cdf0e10cSrcweir  * internal function, called by SwTxtCursor::GetCharRect() to calculate
511cdf0e10cSrcweir  * the relative character position in the current line.
512cdf0e10cSrcweir  * pOrig referes to x and y coordinates, width and height of the cursor
513cdf0e10cSrcweir  * pCMS is used for restricting the cursor, if there are different font
514cdf0e10cSrcweir  * heights in one line ( first value = offset to y of pOrig, second
515cdf0e10cSrcweir  * value = real height of (shortened) cursor
516cdf0e10cSrcweir  *************************************************************************/
517cdf0e10cSrcweir 
_GetCharRect(SwRect * pOrig,const xub_StrLen nOfst,SwCrsrMoveState * pCMS)518cdf0e10cSrcweir void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
519cdf0e10cSrcweir     SwCrsrMoveState* pCMS )
520cdf0e10cSrcweir {
521cdf0e10cSrcweir 	const XubString &rText = GetInfo().GetTxt();
522cdf0e10cSrcweir 	SwTxtSizeInfo aInf( GetInfo(), rText, nStart );
523cdf0e10cSrcweir 	if( GetPropFont() )
524cdf0e10cSrcweir 		aInf.GetFont()->SetProportion( GetPropFont() );
525cdf0e10cSrcweir 	KSHORT nTmpAscent, nTmpHeight;	// Zeilenhoehe
526cdf0e10cSrcweir 	CalcAscentAndHeight( nTmpAscent, nTmpHeight );
527cdf0e10cSrcweir 	const Size	aCharSize( 1, nTmpHeight );
528cdf0e10cSrcweir 	const Point aCharPos;
529cdf0e10cSrcweir 	pOrig->Pos( aCharPos );
530cdf0e10cSrcweir 	pOrig->SSize( aCharSize );
531cdf0e10cSrcweir 
532cdf0e10cSrcweir     // If we are looking for a position inside a field which covers
533cdf0e10cSrcweir     // more than one line we may not skip any "empty portions" at the
534cdf0e10cSrcweir     // beginning of a line
535cdf0e10cSrcweir     const sal_Bool bInsideFirstField = pCMS && pCMS->pSpecialPos &&
536cdf0e10cSrcweir                                        ( pCMS->pSpecialPos->nLineOfst ||
537cdf0e10cSrcweir                                          SP_EXTEND_RANGE_BEFORE ==
538cdf0e10cSrcweir                                          pCMS->pSpecialPos->nExtendRange );
539cdf0e10cSrcweir 
540cdf0e10cSrcweir 	sal_Bool bWidth = pCMS && pCMS->bRealWidth;
541cdf0e10cSrcweir 	if( !pCurr->GetLen() && !pCurr->Width() )
542cdf0e10cSrcweir 	{
543cdf0e10cSrcweir 		if ( pCMS && pCMS->bRealHeight )
544cdf0e10cSrcweir 		{
545cdf0e10cSrcweir 			pCMS->aRealHeight.X() = 0;
546cdf0e10cSrcweir 			pCMS->aRealHeight.Y() = nTmpHeight;
547cdf0e10cSrcweir 		}
548cdf0e10cSrcweir 	}
549cdf0e10cSrcweir 	else
550cdf0e10cSrcweir 	{
551cdf0e10cSrcweir 		KSHORT nPorHeight = nTmpHeight;
552cdf0e10cSrcweir 		KSHORT nPorAscent = nTmpAscent;
553cdf0e10cSrcweir 		SwTwips nX = 0;
554cdf0e10cSrcweir         SwTwips nTmpFirst = 0;
555cdf0e10cSrcweir 		SwLinePortion *pPor = pCurr->GetFirstPortion();
556cdf0e10cSrcweir         SwBidiPortion* pLastBidiPor = 0;
557cdf0e10cSrcweir 		SwTwips nLastBidiPorWidth = 0;
558cdf0e10cSrcweir         SvUShorts* pKanaComp = pCurr->GetpKanaComp();
559cdf0e10cSrcweir         MSHORT nSpaceIdx = 0;
560cdf0e10cSrcweir         MSHORT nKanaIdx = 0;
561cdf0e10cSrcweir         long nSpaceAdd = pCurr->IsSpaceAdd() ? pCurr->GetLLSpaceAdd( 0 ) : 0;
562cdf0e10cSrcweir 
563cdf0e10cSrcweir         sal_Bool bNoTxt = sal_True;
564cdf0e10cSrcweir 
565cdf0e10cSrcweir 		// Zuerst werden alle Portions ohne Len am Zeilenanfang uebersprungen.
566cdf0e10cSrcweir 		// Ausnahme bilden die fiesen Spezialportions aus WhichFirstPortion:
567cdf0e10cSrcweir 		// Num, ErgoSum, FtnNum, FeldReste
568cdf0e10cSrcweir 		// 8477: aber auch die einzige Textportion einer leeren Zeile mit
569cdf0e10cSrcweir 		// Right/Center-Adjustment! Also nicht nur pPor->GetExpandPortion() ...
570cdf0e10cSrcweir         while( pPor && !pPor->GetLen() && ! bInsideFirstField )
571cdf0e10cSrcweir 		{
572cdf0e10cSrcweir 			nX += pPor->Width();
573cdf0e10cSrcweir             if ( pPor->InSpaceGrp() && nSpaceAdd )
574cdf0e10cSrcweir 				nX += pPor->CalcSpacing( nSpaceAdd, aInf );
575cdf0e10cSrcweir 			if( bNoTxt )
576cdf0e10cSrcweir                 nTmpFirst = nX;
577cdf0e10cSrcweir 			// 8670: EndPortions zaehlen hier einmal als TxtPortions.
578cdf0e10cSrcweir             // --> OD 2008-01-28 #newlistlevelattrs#
579cdf0e10cSrcweir //            if( pPor->InTxtGrp() || pPor->IsBreakPortion() )
580cdf0e10cSrcweir             if( pPor->InTxtGrp() || pPor->IsBreakPortion() || pPor->InTabGrp() )
581cdf0e10cSrcweir             // <--
582cdf0e10cSrcweir 			{
583cdf0e10cSrcweir 				bNoTxt = sal_False;
584cdf0e10cSrcweir 				nTmpFirst = nX;
585cdf0e10cSrcweir 			}
586cdf0e10cSrcweir             if( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
587cdf0e10cSrcweir 			{
588cdf0e10cSrcweir                 if ( pCurr->IsSpaceAdd() )
589cdf0e10cSrcweir                 {
590cdf0e10cSrcweir                     if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
591cdf0e10cSrcweir                         nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
592cdf0e10cSrcweir                     else
593cdf0e10cSrcweir                         nSpaceAdd = 0;
594cdf0e10cSrcweir                 }
595cdf0e10cSrcweir 
596cdf0e10cSrcweir                 if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
597cdf0e10cSrcweir                     ++nKanaIdx;
598cdf0e10cSrcweir 			}
599cdf0e10cSrcweir 			if( pPor->InFixMargGrp() )
600cdf0e10cSrcweir 			{
601cdf0e10cSrcweir 				if( pPor->IsMarginPortion() )
602cdf0e10cSrcweir 					bNoTxt = sal_False;
603cdf0e10cSrcweir                 else
604cdf0e10cSrcweir                 {
605cdf0e10cSrcweir                     // fix margin portion => next SpaceAdd, KanaComp value
606cdf0e10cSrcweir                     if ( pCurr->IsSpaceAdd() )
607cdf0e10cSrcweir                     {
608cdf0e10cSrcweir                         if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
609cdf0e10cSrcweir                             nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
610cdf0e10cSrcweir                         else
611cdf0e10cSrcweir                             nSpaceAdd = 0;
612cdf0e10cSrcweir                     }
613cdf0e10cSrcweir 
614cdf0e10cSrcweir                     if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
615cdf0e10cSrcweir                         ++nKanaIdx;
616cdf0e10cSrcweir                 }
617cdf0e10cSrcweir 			}
618cdf0e10cSrcweir 			pPor = pPor->GetPortion();
619cdf0e10cSrcweir 		}
620cdf0e10cSrcweir 
621cdf0e10cSrcweir 		if( !pPor )
622cdf0e10cSrcweir 		{
623cdf0e10cSrcweir             // Es sind nur Spezialportions unterwegs.
624cdf0e10cSrcweir             nX = nTmpFirst;
625cdf0e10cSrcweir 		}
626cdf0e10cSrcweir 		else
627cdf0e10cSrcweir 		{
628cdf0e10cSrcweir             if( !pPor->IsMarginPortion() && !pPor->IsPostItsPortion() &&
629cdf0e10cSrcweir 				(!pPor->InFldGrp() || pPor->GetAscent() ) )
630cdf0e10cSrcweir 			{
631cdf0e10cSrcweir 				nPorHeight = pPor->Height();
632cdf0e10cSrcweir 				nPorAscent = pPor->GetAscent();
633cdf0e10cSrcweir 			}
634cdf0e10cSrcweir 			while( pPor && !pPor->IsBreakPortion() && ( aInf.GetIdx() < nOfst ||
635cdf0e10cSrcweir                    ( bWidth && ( pPor->IsKernPortion() || pPor->IsMultiPortion() ) ) ) )
636cdf0e10cSrcweir 			{
637cdf0e10cSrcweir 				if( !pPor->IsMarginPortion() && !pPor->IsPostItsPortion() &&
638cdf0e10cSrcweir 					(!pPor->InFldGrp() || pPor->GetAscent() ) )
639cdf0e10cSrcweir 				{
640cdf0e10cSrcweir 					nPorHeight = pPor->Height();
641cdf0e10cSrcweir 					nPorAscent = pPor->GetAscent();
642cdf0e10cSrcweir 				}
643cdf0e10cSrcweir 
644cdf0e10cSrcweir                 // If we are behind the portion, we add the portion width to
645cdf0e10cSrcweir                 // nX. Special case: nOfst = aInf.GetIdx() + pPor->GetLen().
646cdf0e10cSrcweir                 // For common portions (including BidiPortions) we want to add
647cdf0e10cSrcweir                 // the portion width to nX. For MultiPortions, nExtra = 0,
648cdf0e10cSrcweir                 // therefore we go to the 'else' branch and start a recursion.
649cdf0e10cSrcweir                 const sal_uInt8 nExtra = pPor->IsMultiPortion() &&
650cdf0e10cSrcweir                                     ! ((SwMultiPortion*)pPor)->IsBidi() &&
651cdf0e10cSrcweir                                     ! bWidth ? 0 : 1;
652cdf0e10cSrcweir                 if ( aInf.GetIdx() + pPor->GetLen() < nOfst + nExtra )
653cdf0e10cSrcweir 				{
654cdf0e10cSrcweir                     if ( pPor->InSpaceGrp() && nSpaceAdd )
655cdf0e10cSrcweir                         nX += pPor->PrtWidth() +
656cdf0e10cSrcweir                               pPor->CalcSpacing( nSpaceAdd, aInf );
657cdf0e10cSrcweir                     else
658cdf0e10cSrcweir 					{
659cdf0e10cSrcweir                         if( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() )
660cdf0e10cSrcweir 						{
661cdf0e10cSrcweir                             // update to current SpaceAdd, KanaComp values
662cdf0e10cSrcweir                             if ( pCurr->IsSpaceAdd() )
663cdf0e10cSrcweir                             {
664cdf0e10cSrcweir                                 if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
665cdf0e10cSrcweir                                     nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
666cdf0e10cSrcweir                                 else
667cdf0e10cSrcweir                                     nSpaceAdd = 0;
668cdf0e10cSrcweir                             }
669cdf0e10cSrcweir 
670cdf0e10cSrcweir                             if ( pKanaComp &&
671cdf0e10cSrcweir                                 ( nKanaIdx + 1 ) < pKanaComp->Count()
672cdf0e10cSrcweir                                 )
673cdf0e10cSrcweir                                 ++nKanaIdx;
674cdf0e10cSrcweir                         }
675cdf0e10cSrcweir 						if ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
676cdf0e10cSrcweir 								!pPor->GetPortion()->IsMarginPortion() ) )
677cdf0e10cSrcweir 							nX += pPor->PrtWidth();
678cdf0e10cSrcweir 					}
679cdf0e10cSrcweir                     if( pPor->IsMultiPortion() )
680cdf0e10cSrcweir                     {
681cdf0e10cSrcweir                         if ( ((SwMultiPortion*)pPor)->HasTabulator() )
682cdf0e10cSrcweir                         {
683cdf0e10cSrcweir                             if ( pCurr->IsSpaceAdd() )
684cdf0e10cSrcweir                             {
685cdf0e10cSrcweir                                 if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
686cdf0e10cSrcweir                                     nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
687cdf0e10cSrcweir                                 else
688cdf0e10cSrcweir                                     nSpaceAdd = 0;
689cdf0e10cSrcweir                             }
690cdf0e10cSrcweir 
691cdf0e10cSrcweir                             if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
692cdf0e10cSrcweir                                 ++nKanaIdx;
693cdf0e10cSrcweir                         }
694cdf0e10cSrcweir 
695cdf0e10cSrcweir                         // if we are right behind a BidiPortion, we have to
696cdf0e10cSrcweir                         // hold a pointer to the BidiPortion in order to
697cdf0e10cSrcweir                         // find the correct cursor position, depending on the
698cdf0e10cSrcweir                         // cursor level
699cdf0e10cSrcweir                         if ( ((SwMultiPortion*)pPor)->IsBidi() &&
700cdf0e10cSrcweir                              aInf.GetIdx() + pPor->GetLen() == nOfst )
701cdf0e10cSrcweir 						{
702cdf0e10cSrcweir                              pLastBidiPor = (SwBidiPortion*)pPor;
703cdf0e10cSrcweir                              nLastBidiPorWidth = pLastBidiPor->Width() +
704cdf0e10cSrcweir                                                  pLastBidiPor->CalcSpacing( nSpaceAdd, aInf );;
705cdf0e10cSrcweir                         }
706cdf0e10cSrcweir                     }
707cdf0e10cSrcweir 
708cdf0e10cSrcweir 					aInf.SetIdx( aInf.GetIdx() + pPor->GetLen() );
709cdf0e10cSrcweir                     pPor = pPor->GetPortion();
710cdf0e10cSrcweir 				}
711cdf0e10cSrcweir 				else
712cdf0e10cSrcweir 				{
713cdf0e10cSrcweir 					if( pPor->IsMultiPortion() )
714cdf0e10cSrcweir 					{
715cdf0e10cSrcweir                         nTmpAscent = AdjustBaseLine( *pCurr, pPor );
716cdf0e10cSrcweir                         GetInfo().SetMulti( sal_True );
717cdf0e10cSrcweir                         pOrig->Pos().Y() += nTmpAscent - nPorAscent;
718cdf0e10cSrcweir 
719cdf0e10cSrcweir                         if( pCMS && pCMS->b2Lines )
720cdf0e10cSrcweir 						{
721cdf0e10cSrcweir                             sal_Bool bRecursion = sal_True;
722cdf0e10cSrcweir                             if ( ! pCMS->p2Lines )
723cdf0e10cSrcweir                             {
724cdf0e10cSrcweir                                 pCMS->p2Lines = new Sw2LinesPos;
725cdf0e10cSrcweir                                 pCMS->p2Lines->aLine = SwRect(aCharPos, aCharSize);
726cdf0e10cSrcweir                                 bRecursion = sal_False;
727cdf0e10cSrcweir                             }
728cdf0e10cSrcweir 
729cdf0e10cSrcweir 							if( ((SwMultiPortion*)pPor)->HasRotation() )
730cdf0e10cSrcweir 							{
731cdf0e10cSrcweir 								if( ((SwMultiPortion*)pPor)->IsRevers() )
732cdf0e10cSrcweir                                     pCMS->p2Lines->nMultiType = MT_ROT_270;
733cdf0e10cSrcweir 								else
734cdf0e10cSrcweir                                     pCMS->p2Lines->nMultiType = MT_ROT_90;
735cdf0e10cSrcweir 							}
736cdf0e10cSrcweir 							else if( ((SwMultiPortion*)pPor)->IsDouble() )
737cdf0e10cSrcweir                                 pCMS->p2Lines->nMultiType = MT_TWOLINE;
738cdf0e10cSrcweir                             else if( ((SwMultiPortion*)pPor)->IsBidi() )
739cdf0e10cSrcweir                                 pCMS->p2Lines->nMultiType = MT_BIDI;
740cdf0e10cSrcweir 							else
741cdf0e10cSrcweir                                 pCMS->p2Lines->nMultiType = MT_RUBY;
742cdf0e10cSrcweir 
743cdf0e10cSrcweir                             SwTwips nTmpWidth = pPor->Width();
744cdf0e10cSrcweir 							if( nSpaceAdd )
745cdf0e10cSrcweir 								nTmpWidth += pPor->CalcSpacing(nSpaceAdd, aInf);
746cdf0e10cSrcweir 
747cdf0e10cSrcweir                             SwRect aRect( Point(aCharPos.X() + nX, pOrig->Top() ),
748cdf0e10cSrcweir                                           Size( nTmpWidth, pPor->Height() ) );
749cdf0e10cSrcweir 
750cdf0e10cSrcweir                             if ( ! bRecursion )
751cdf0e10cSrcweir                                 pCMS->p2Lines->aPortion = aRect;
752cdf0e10cSrcweir                             else
753cdf0e10cSrcweir                                 pCMS->p2Lines->aPortion2 = aRect;
754cdf0e10cSrcweir 						}
755cdf0e10cSrcweir 
756cdf0e10cSrcweir 						// In a multi-portion we use GetCharRect()-function
757cdf0e10cSrcweir                         // recursively and must add the x-position
758cdf0e10cSrcweir 						// of the multi-portion.
759cdf0e10cSrcweir 						xub_StrLen nOldStart = nStart;
760cdf0e10cSrcweir                         SwTwips nOldY = nY;
761cdf0e10cSrcweir 						sal_uInt8 nOldProp = GetPropFont();
762cdf0e10cSrcweir 						nStart = aInf.GetIdx();
763cdf0e10cSrcweir 						SwLineLayout* pOldCurr = pCurr;
764cdf0e10cSrcweir 						pCurr = &((SwMultiPortion*)pPor)->GetRoot();
765cdf0e10cSrcweir 						if( ((SwMultiPortion*)pPor)->IsDouble() )
766cdf0e10cSrcweir 							SetPropFont( 50 );
767cdf0e10cSrcweir 
768cdf0e10cSrcweir                         GETGRID( GetTxtFrm()->FindPageFrm() )
769cdf0e10cSrcweir                         const sal_Bool bHasGrid = pGrid && GetInfo().SnapToGrid();
770cdf0e10cSrcweir                         const sal_uInt16 nRubyHeight = bHasGrid ?
771cdf0e10cSrcweir                                                    pGrid->GetRubyHeight() : 0;
772cdf0e10cSrcweir 
773cdf0e10cSrcweir                         if( nStart + pCurr->GetLen() <= nOfst && GetNext() &&
774cdf0e10cSrcweir                             ( ! ((SwMultiPortion*)pPor)->IsRuby() ||
775cdf0e10cSrcweir                                 ((SwMultiPortion*)pPor)->OnTop() ) )
776cdf0e10cSrcweir 						{
777cdf0e10cSrcweir                             sal_uInt16 nOffset;
778cdf0e10cSrcweir                             // in grid mode we may only add the height of the
779cdf0e10cSrcweir                             // ruby line if ruby line is on top
780cdf0e10cSrcweir                             if ( bHasGrid &&
781cdf0e10cSrcweir                                 ((SwMultiPortion*)pPor)->IsRuby() &&
782cdf0e10cSrcweir                                 ((SwMultiPortion*)pPor)->OnTop() )
783cdf0e10cSrcweir                                 nOffset = nRubyHeight;
784cdf0e10cSrcweir                             else
785cdf0e10cSrcweir                                 nOffset = GetLineHeight();
786cdf0e10cSrcweir 
787cdf0e10cSrcweir                             pOrig->Pos().Y() += nOffset;
788cdf0e10cSrcweir 							Next();
789cdf0e10cSrcweir 						}
790cdf0e10cSrcweir 
791cdf0e10cSrcweir 						sal_Bool bSpaceChg = ((SwMultiPortion*)pPor)->
792cdf0e10cSrcweir 												ChgSpaceAdd( pCurr, nSpaceAdd );
793cdf0e10cSrcweir 						Point aOldPos = pOrig->Pos();
794cdf0e10cSrcweir 
795cdf0e10cSrcweir                         // Ok, for ruby portions in grid mode we have to
796cdf0e10cSrcweir                         // temporarily set the inner line height to the
797cdf0e10cSrcweir                         // outer line height because that value is needed
798cdf0e10cSrcweir                         // for the adjustment inside the recursion
799cdf0e10cSrcweir                         const sal_uInt16 nOldRubyHeight = pCurr->Height();
800cdf0e10cSrcweir                         const sal_uInt16 nOldRubyRealHeight = pCurr->GetRealHeight();
801cdf0e10cSrcweir                         const sal_Bool bChgHeight =
802cdf0e10cSrcweir                                 ((SwMultiPortion*)pPor)->IsRuby() && bHasGrid;
803cdf0e10cSrcweir 
804cdf0e10cSrcweir                         if ( bChgHeight )
805cdf0e10cSrcweir                         {
806cdf0e10cSrcweir                             pCurr->Height( pOldCurr->Height() - nRubyHeight );
807cdf0e10cSrcweir                             pCurr->SetRealHeight( pOldCurr->GetRealHeight() -
808cdf0e10cSrcweir                                                   nRubyHeight );
809cdf0e10cSrcweir                         }
810cdf0e10cSrcweir 
811cdf0e10cSrcweir                         SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
812cdf0e10cSrcweir                         if ( ((SwMultiPortion*)pPor)->IsBidi() )
813cdf0e10cSrcweir                         {
814cdf0e10cSrcweir                             aLayoutModeModifier.Modify(
815cdf0e10cSrcweir                                 ((SwBidiPortion*)pPor)->GetLevel() % 2 );
816cdf0e10cSrcweir                         }
817cdf0e10cSrcweir 
818cdf0e10cSrcweir                         _GetCharRect( pOrig, nOfst, pCMS );
819cdf0e10cSrcweir 
820cdf0e10cSrcweir                         if ( bChgHeight )
821cdf0e10cSrcweir                         {
822cdf0e10cSrcweir                             pCurr->Height( nOldRubyHeight );
823cdf0e10cSrcweir                             pCurr->SetRealHeight( nOldRubyRealHeight );
824cdf0e10cSrcweir                         }
825cdf0e10cSrcweir 
826cdf0e10cSrcweir                         // if we are still in the first row of
827cdf0e10cSrcweir                         // our 2 line multiportion, we use the FirstMulti flag
828cdf0e10cSrcweir                         // to indicate this
829cdf0e10cSrcweir                         if ( ((SwMultiPortion*)pPor)->IsDouble() )
830cdf0e10cSrcweir                         {
831cdf0e10cSrcweir                             // the recursion may have damaged our font size
832cdf0e10cSrcweir                             SetPropFont( nOldProp );
833cdf0e10cSrcweir                             if ( !nOldProp )
834cdf0e10cSrcweir                                 nOldProp = 100;
835cdf0e10cSrcweir                             GetInfo().GetFont()->SetProportion( 100 );
836cdf0e10cSrcweir 
837cdf0e10cSrcweir                             if ( pCurr == &((SwMultiPortion*)pPor)->GetRoot() )
838cdf0e10cSrcweir                             {
839cdf0e10cSrcweir                                 GetInfo().SetFirstMulti( sal_True );
840cdf0e10cSrcweir 
841cdf0e10cSrcweir                                 // we want to treat a double line portion like a
842cdf0e10cSrcweir                                 // single line portion, if there is no text in
843cdf0e10cSrcweir                                 // the second line
844cdf0e10cSrcweir                                 if ( !pCurr->GetNext() ||
845cdf0e10cSrcweir                                      !pCurr->GetNext()->GetLen() )
846cdf0e10cSrcweir                                     GetInfo().SetMulti( sal_False );
847cdf0e10cSrcweir                             }
848cdf0e10cSrcweir                         }
849cdf0e10cSrcweir                         // ruby portions are treated like single line portions
850cdf0e10cSrcweir                         else if( ((SwMultiPortion*)pPor)->IsRuby() ||
851cdf0e10cSrcweir                                  ((SwMultiPortion*)pPor)->IsBidi() )
852cdf0e10cSrcweir                             GetInfo().SetMulti( sal_False );
853cdf0e10cSrcweir 
854cdf0e10cSrcweir                         // calculate cursor values
855cdf0e10cSrcweir                         if( ((SwMultiPortion*)pPor)->HasRotation() )
856cdf0e10cSrcweir 						{
857cdf0e10cSrcweir                             GetInfo().SetMulti( sal_False );
858cdf0e10cSrcweir                             long nTmp = pOrig->Width();
859cdf0e10cSrcweir 							pOrig->Width( pOrig->Height() );
860cdf0e10cSrcweir 							pOrig->Height( nTmp );
861cdf0e10cSrcweir 							nTmp = pOrig->Left() - aOldPos.X();
862cdf0e10cSrcweir 
863cdf0e10cSrcweir                             // if we travel into our rotated portion from
864cdf0e10cSrcweir                             // a line below, we have to take care, that the
865cdf0e10cSrcweir                             // y coord in pOrig is less than line height:
866cdf0e10cSrcweir                             if ( nTmp )
867cdf0e10cSrcweir                                 nTmp--;
868cdf0e10cSrcweir 
869cdf0e10cSrcweir                             pOrig->Pos().X() = nX + aOldPos.X();
870cdf0e10cSrcweir 							if( ((SwMultiPortion*)pPor)->IsRevers() )
871cdf0e10cSrcweir 								pOrig->Pos().Y() = aOldPos.Y() + nTmp;
872cdf0e10cSrcweir 							else
873cdf0e10cSrcweir 								pOrig->Pos().Y() = aOldPos.Y()
874cdf0e10cSrcweir 									+ pPor->Height() - nTmp - pOrig->Height();
875cdf0e10cSrcweir 							if ( pCMS && pCMS->bRealHeight )
876cdf0e10cSrcweir 							{
877cdf0e10cSrcweir 								pCMS->aRealHeight.Y() = -pCMS->aRealHeight.Y();
878cdf0e10cSrcweir                                 // result for rotated multi portion is not
879cdf0e10cSrcweir                                 // correct for reverse (270 degree) portions
880cdf0e10cSrcweir                                 if( ((SwMultiPortion*)pPor)->IsRevers() )
881cdf0e10cSrcweir                                 {
882cdf0e10cSrcweir                                     if ( SvxParaVertAlignItem::AUTOMATIC ==
883cdf0e10cSrcweir                                          GetLineInfo().GetVertAlign() )
884cdf0e10cSrcweir                                         // if vertical alignment is set to auto,
885cdf0e10cSrcweir                                         // we switch from base line alignment
886cdf0e10cSrcweir                                         // to centered alignment
887cdf0e10cSrcweir                                         pCMS->aRealHeight.X() =
888cdf0e10cSrcweir                                             ( pOrig->Width() +
889cdf0e10cSrcweir                                               pCMS->aRealHeight.Y() ) / 2;
890cdf0e10cSrcweir                                     else
891cdf0e10cSrcweir                                         pCMS->aRealHeight.X() =
892cdf0e10cSrcweir                                             ( pOrig->Width() -
893cdf0e10cSrcweir                                               pCMS->aRealHeight.X() +
894cdf0e10cSrcweir                                               pCMS->aRealHeight.Y() );
895cdf0e10cSrcweir                                 }
896cdf0e10cSrcweir                             }
897cdf0e10cSrcweir 						}
898cdf0e10cSrcweir 						else
899cdf0e10cSrcweir 						{
900cdf0e10cSrcweir 							pOrig->Pos().Y() += aOldPos.Y();
901cdf0e10cSrcweir                             if ( ((SwMultiPortion*)pPor)->IsBidi() )
902cdf0e10cSrcweir                             {
903cdf0e10cSrcweir                                 const SwTwips nPorWidth = pPor->Width() +
904cdf0e10cSrcweir                                                          pPor->CalcSpacing( nSpaceAdd, aInf );
905cdf0e10cSrcweir                                 const SwTwips nInsideOfst = pOrig->Pos().X();
906cdf0e10cSrcweir                                 pOrig->Pos().X() = nX + nPorWidth -
907cdf0e10cSrcweir                                                    nInsideOfst - pOrig->Width();
908cdf0e10cSrcweir                             }
909cdf0e10cSrcweir                             else
910cdf0e10cSrcweir                                 pOrig->Pos().X() += nX;
911cdf0e10cSrcweir 
912cdf0e10cSrcweir                             if( ((SwMultiPortion*)pPor)->HasBrackets() )
913cdf0e10cSrcweir 								pOrig->Pos().X() +=
914cdf0e10cSrcweir 									((SwDoubleLinePortion*)pPor)->PreWidth();
915cdf0e10cSrcweir 						}
916cdf0e10cSrcweir 
917cdf0e10cSrcweir                         if( bSpaceChg )
918cdf0e10cSrcweir 							SwDoubleLinePortion::ResetSpaceAdd( pCurr );
919cdf0e10cSrcweir 
920cdf0e10cSrcweir                         pCurr = pOldCurr;
921cdf0e10cSrcweir 						nStart = nOldStart;
922cdf0e10cSrcweir                         nY = nOldY;
923cdf0e10cSrcweir                         bPrev = sal_False;
924cdf0e10cSrcweir 
925cdf0e10cSrcweir                         return;
926cdf0e10cSrcweir 					}
927cdf0e10cSrcweir 					if ( pPor->PrtWidth() )
928cdf0e10cSrcweir 					{
929cdf0e10cSrcweir 						xub_StrLen nOldLen = pPor->GetLen();
930cdf0e10cSrcweir 						pPor->SetLen( nOfst - aInf.GetIdx() );
931cdf0e10cSrcweir 						aInf.SetLen( pPor->GetLen() );
932cdf0e10cSrcweir 						if( nX || !pPor->InNumberGrp() )
933cdf0e10cSrcweir 						{
934cdf0e10cSrcweir 							SeekAndChg( aInf );
935cdf0e10cSrcweir 							const sal_Bool bOldOnWin = aInf.OnWin();
936cdf0e10cSrcweir 							aInf.SetOnWin( sal_False ); // keine BULLETs!
937cdf0e10cSrcweir 							SwTwips nTmp = nX;
938cdf0e10cSrcweir                             aInf.SetKanaComp( pKanaComp );
939cdf0e10cSrcweir                             aInf.SetKanaIdx( nKanaIdx );
940cdf0e10cSrcweir                             nX += pPor->GetTxtSize( aInf ).Width();
941cdf0e10cSrcweir 							aInf.SetOnWin( bOldOnWin );
942cdf0e10cSrcweir 							if ( pPor->InSpaceGrp() && nSpaceAdd )
943cdf0e10cSrcweir 								nX += pPor->CalcSpacing( nSpaceAdd, aInf );
944cdf0e10cSrcweir 							if( bWidth )
945cdf0e10cSrcweir 							{
946cdf0e10cSrcweir 								pPor->SetLen( pPor->GetLen() + 1 );
947cdf0e10cSrcweir 								aInf.SetLen( pPor->GetLen() );
948cdf0e10cSrcweir 								aInf.SetOnWin( sal_False ); // keine BULLETs!
949cdf0e10cSrcweir 								nTmp += pPor->GetTxtSize( aInf ).Width();
950cdf0e10cSrcweir 								aInf.SetOnWin( bOldOnWin );
951cdf0e10cSrcweir 								if ( pPor->InSpaceGrp() && nSpaceAdd )
952cdf0e10cSrcweir 									nTmp += pPor->CalcSpacing(nSpaceAdd, aInf);
953cdf0e10cSrcweir 								pOrig->Width( nTmp - nX );
954cdf0e10cSrcweir 							}
955cdf0e10cSrcweir 						}
956cdf0e10cSrcweir 						pPor->SetLen( nOldLen );
957cdf0e10cSrcweir 					}
958cdf0e10cSrcweir 					bWidth = sal_False;
959cdf0e10cSrcweir 					break;
960cdf0e10cSrcweir 				}
961cdf0e10cSrcweir 			}
962cdf0e10cSrcweir 		}
963cdf0e10cSrcweir 
964cdf0e10cSrcweir 		if( pPor )
965cdf0e10cSrcweir 		{
966cdf0e10cSrcweir             ASSERT( !pPor->InNumberGrp() || bInsideFirstField, "Number surprise" );
967cdf0e10cSrcweir 			sal_Bool bEmptyFld = sal_False;
968cdf0e10cSrcweir 			if( pPor->InFldGrp() && pPor->GetLen() )
969cdf0e10cSrcweir 			{
970cdf0e10cSrcweir 				SwFldPortion *pTmp = (SwFldPortion*)pPor;
971cdf0e10cSrcweir 				while( pTmp->HasFollow() && !pTmp->GetExp().Len() )
972cdf0e10cSrcweir 				{
973cdf0e10cSrcweir 					KSHORT nAddX = pTmp->Width();
974cdf0e10cSrcweir 					SwLinePortion *pNext = pTmp->GetPortion();
975cdf0e10cSrcweir 					while( pNext && !pNext->InFldGrp() )
976cdf0e10cSrcweir 					{
977cdf0e10cSrcweir 						ASSERT( !pNext->GetLen(), "Where's my field follow?" );
978cdf0e10cSrcweir 						nAddX = nAddX + pNext->Width();
979cdf0e10cSrcweir 						pNext = pNext->GetPortion();
980cdf0e10cSrcweir 					}
981cdf0e10cSrcweir 					if( !pNext )
982cdf0e10cSrcweir 						break;
983cdf0e10cSrcweir 					pTmp = (SwFldPortion*)pNext;
984cdf0e10cSrcweir 					nPorHeight = pTmp->Height();
985cdf0e10cSrcweir 					nPorAscent = pTmp->GetAscent();
986cdf0e10cSrcweir 					nX += nAddX;
987cdf0e10cSrcweir 					bEmptyFld = sal_True;
988cdf0e10cSrcweir 				}
989cdf0e10cSrcweir 			}
990cdf0e10cSrcweir 			// 8513: Felder im Blocksatz, ueberspringen
991cdf0e10cSrcweir             while( pPor && !pPor->GetLen() && ! bInsideFirstField &&
992cdf0e10cSrcweir                    ( pPor->IsFlyPortion() || pPor->IsKernPortion() ||
993cdf0e10cSrcweir                      pPor->IsBlankPortion() || pPor->InTabGrp() ||
994cdf0e10cSrcweir                      ( !bEmptyFld && pPor->InFldGrp() ) ) )
995cdf0e10cSrcweir 			{
996cdf0e10cSrcweir 				if ( pPor->InSpaceGrp() && nSpaceAdd )
997cdf0e10cSrcweir 					nX += pPor->PrtWidth() +
998cdf0e10cSrcweir 						  pPor->CalcSpacing( nSpaceAdd, aInf );
999cdf0e10cSrcweir 				else
1000cdf0e10cSrcweir 				{
1001cdf0e10cSrcweir                     if( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() )
1002cdf0e10cSrcweir 					{
1003cdf0e10cSrcweir                         if ( pCurr->IsSpaceAdd() )
1004cdf0e10cSrcweir                         {
1005cdf0e10cSrcweir                             if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
1006cdf0e10cSrcweir                                 nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
1007cdf0e10cSrcweir                             else
1008cdf0e10cSrcweir                                 nSpaceAdd = 0;
1009cdf0e10cSrcweir                         }
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir                         if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
1012cdf0e10cSrcweir                             ++nKanaIdx;
1013cdf0e10cSrcweir 					}
1014cdf0e10cSrcweir 					if ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
1015cdf0e10cSrcweir 							!pPor->GetPortion()->IsMarginPortion() ) )
1016cdf0e10cSrcweir 						nX += pPor->PrtWidth();
1017cdf0e10cSrcweir 				}
1018cdf0e10cSrcweir                 if( pPor->IsMultiPortion() &&
1019cdf0e10cSrcweir                     ((SwMultiPortion*)pPor)->HasTabulator() )
1020cdf0e10cSrcweir 				{
1021cdf0e10cSrcweir                     if ( pCurr->IsSpaceAdd() )
1022cdf0e10cSrcweir                     {
1023cdf0e10cSrcweir                         if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
1024cdf0e10cSrcweir                             nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
1025cdf0e10cSrcweir                         else
1026cdf0e10cSrcweir                             nSpaceAdd = 0;
1027cdf0e10cSrcweir                     }
1028cdf0e10cSrcweir 
1029cdf0e10cSrcweir                     if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
1030cdf0e10cSrcweir                         ++nKanaIdx;
1031cdf0e10cSrcweir 				}
1032cdf0e10cSrcweir 				if( !pPor->IsFlyPortion() )
1033cdf0e10cSrcweir 				{
1034cdf0e10cSrcweir 					nPorHeight = pPor->Height();
1035cdf0e10cSrcweir 					nPorAscent = pPor->GetAscent();
1036cdf0e10cSrcweir 				}
1037cdf0e10cSrcweir 				pPor = pPor->GetPortion();
1038cdf0e10cSrcweir 			}
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir 			if( aInf.GetIdx() == nOfst && pPor && pPor->InHyphGrp() &&
1041cdf0e10cSrcweir 				pPor->GetPortion() && pPor->GetPortion()->InFixGrp() )
1042cdf0e10cSrcweir 			{
1043cdf0e10cSrcweir 				// Alle Sonderportions muessen uebersprungen werden
1044cdf0e10cSrcweir 				// Beispiel: zu-[FLY]sammen, 'u' == 19, 's' == 20; Right()
1045cdf0e10cSrcweir 				// Ohne den Ausgleich landen wir vor '-' mit dem
1046cdf0e10cSrcweir 				// Ausgleich vor 's'.
1047cdf0e10cSrcweir 				while( pPor && !pPor->GetLen() )
1048cdf0e10cSrcweir 				{
1049cdf0e10cSrcweir 					DBG_LOOP;
1050cdf0e10cSrcweir 					nX += pPor->Width();
1051cdf0e10cSrcweir 					if( !pPor->IsMarginPortion() )
1052cdf0e10cSrcweir 					{
1053cdf0e10cSrcweir 						nPorHeight = pPor->Height();
1054cdf0e10cSrcweir 						nPorAscent = pPor->GetAscent();
1055cdf0e10cSrcweir 					}
1056cdf0e10cSrcweir 					pPor = pPor->GetPortion();
1057cdf0e10cSrcweir 				}
1058cdf0e10cSrcweir 			}
1059cdf0e10cSrcweir 			if( pPor && pCMS )
1060cdf0e10cSrcweir 			{
1061cdf0e10cSrcweir 				if( pCMS->bFieldInfo &&	pPor->InFldGrp() && pPor->Width() )
1062cdf0e10cSrcweir 					pOrig->Width( pPor->Width() );
1063cdf0e10cSrcweir 				if( pPor->IsDropPortion() )
1064cdf0e10cSrcweir                 {
1065cdf0e10cSrcweir 					nPorAscent = ((SwDropPortion*)pPor)->GetDropHeight();
1066cdf0e10cSrcweir                     // The drop height is only calculated, if we have more than
1067cdf0e10cSrcweir                     // one line. Otherwise it is 0.
1068cdf0e10cSrcweir                     if ( ! nPorAscent)
1069cdf0e10cSrcweir                         nPorAscent = pPor->Height();
1070cdf0e10cSrcweir 					nPorHeight = nPorAscent;
1071cdf0e10cSrcweir 					pOrig->Height( nPorHeight +
1072cdf0e10cSrcweir 						((SwDropPortion*)pPor)->GetDropDescent() );
1073cdf0e10cSrcweir 					if( nTmpHeight < pOrig->Height() )
1074cdf0e10cSrcweir 					{
1075cdf0e10cSrcweir 						nTmpAscent = nPorAscent;
1076cdf0e10cSrcweir 						nTmpHeight = sal_uInt16( pOrig->Height() );
1077cdf0e10cSrcweir 					}
1078cdf0e10cSrcweir 				}
1079cdf0e10cSrcweir 				if( bWidth && pPor->PrtWidth() && pPor->GetLen() &&
1080cdf0e10cSrcweir 					aInf.GetIdx() == nOfst )
1081cdf0e10cSrcweir 				{
1082cdf0e10cSrcweir 					if( !pPor->IsFlyPortion() && pPor->Height() &&
1083cdf0e10cSrcweir 						pPor->GetAscent() )
1084cdf0e10cSrcweir 					{
1085cdf0e10cSrcweir 						nPorHeight = pPor->Height();
1086cdf0e10cSrcweir 						nPorAscent = pPor->GetAscent();
1087cdf0e10cSrcweir 					}
1088cdf0e10cSrcweir 					SwTwips nTmp;
1089cdf0e10cSrcweir 					if( 2 > pPor->GetLen() )
1090cdf0e10cSrcweir 					{
1091cdf0e10cSrcweir 						nTmp = pPor->Width();
1092cdf0e10cSrcweir 						if ( pPor->InSpaceGrp() && nSpaceAdd )
1093cdf0e10cSrcweir 							nTmp += pPor->CalcSpacing( nSpaceAdd, aInf );
1094cdf0e10cSrcweir 					}
1095cdf0e10cSrcweir 					else
1096cdf0e10cSrcweir 					{
1097cdf0e10cSrcweir 						const sal_Bool bOldOnWin = aInf.OnWin();
1098cdf0e10cSrcweir 						xub_StrLen nOldLen = pPor->GetLen();
1099cdf0e10cSrcweir 						pPor->SetLen( 1 );
1100cdf0e10cSrcweir 						aInf.SetLen( pPor->GetLen() );
1101cdf0e10cSrcweir 						SeekAndChg( aInf );
1102cdf0e10cSrcweir 						aInf.SetOnWin( sal_False ); // keine BULLETs!
1103cdf0e10cSrcweir                         aInf.SetKanaComp( pKanaComp );
1104cdf0e10cSrcweir                         aInf.SetKanaIdx( nKanaIdx );
1105cdf0e10cSrcweir 						nTmp = pPor->GetTxtSize( aInf ).Width();
1106cdf0e10cSrcweir 						aInf.SetOnWin( bOldOnWin );
1107cdf0e10cSrcweir 						if ( pPor->InSpaceGrp() && nSpaceAdd )
1108cdf0e10cSrcweir 							nTmp += pPor->CalcSpacing( nSpaceAdd, aInf );
1109cdf0e10cSrcweir 						pPor->SetLen( nOldLen );
1110cdf0e10cSrcweir 					}
1111cdf0e10cSrcweir 					pOrig->Width( nTmp );
1112cdf0e10cSrcweir 				}
1113cdf0e10cSrcweir 
1114cdf0e10cSrcweir                 // travel inside field portion?
1115cdf0e10cSrcweir                 if ( pCMS->pSpecialPos )
1116cdf0e10cSrcweir                 {
1117cdf0e10cSrcweir                     // apply attributes to font
1118cdf0e10cSrcweir                     Seek( nOfst );
1119cdf0e10cSrcweir                     lcl_GetCharRectInsideField( aInf, *pOrig, *pCMS, *pPor );
1120cdf0e10cSrcweir                 }
1121cdf0e10cSrcweir             }
1122cdf0e10cSrcweir         }
1123cdf0e10cSrcweir 
1124cdf0e10cSrcweir         // special case: We are at the beginning of a BidiPortion or
1125cdf0e10cSrcweir         // directly behind a BidiPortion
1126cdf0e10cSrcweir         if ( pCMS &&
1127cdf0e10cSrcweir                 ( pLastBidiPor ||
1128cdf0e10cSrcweir                 ( pPor &&
1129cdf0e10cSrcweir                   pPor->IsMultiPortion() &&
1130cdf0e10cSrcweir                   ((SwMultiPortion*)pPor)->IsBidi() ) ) )
1131cdf0e10cSrcweir         {
1132cdf0e10cSrcweir             // we determine if the cursor has to blink before or behind
1133cdf0e10cSrcweir             // the bidi portion
1134cdf0e10cSrcweir             if ( pLastBidiPor )
1135cdf0e10cSrcweir             {
1136cdf0e10cSrcweir                 const sal_uInt8 nPortionLevel = pLastBidiPor->GetLevel();
1137cdf0e10cSrcweir 
1138cdf0e10cSrcweir                 if ( pCMS->nCursorBidiLevel >= nPortionLevel )
1139cdf0e10cSrcweir                 {
1140cdf0e10cSrcweir                     // we came from inside the bidi portion, we want to blink
1141cdf0e10cSrcweir                     // behind the portion
1142cdf0e10cSrcweir                     pOrig->Pos().X() -= nLastBidiPorWidth;
1143cdf0e10cSrcweir 
1144cdf0e10cSrcweir                     // Again, there is a special case: logically behind
1145cdf0e10cSrcweir                     // the portion can actually mean that the cursor is inside
1146cdf0e10cSrcweir                     // the portion. This can happen is the last portion
1147cdf0e10cSrcweir                     // inside the bidi portion is a nested bidi portion
1148cdf0e10cSrcweir                     SwLineLayout& rLineLayout =
1149cdf0e10cSrcweir                             ((SwMultiPortion*)pLastBidiPor)->GetRoot();
1150cdf0e10cSrcweir 
1151cdf0e10cSrcweir                     const SwLinePortion *pLast = rLineLayout.FindLastPortion();
1152cdf0e10cSrcweir                     if ( pLast->IsMultiPortion() )
1153cdf0e10cSrcweir                     {
1154cdf0e10cSrcweir                         ASSERT( ((SwMultiPortion*)pLast)->IsBidi(),
1155cdf0e10cSrcweir                                  "Non-BidiPortion inside BidiPortion" )
1156cdf0e10cSrcweir                         pOrig->Pos().X() += pLast->Width() +
1157cdf0e10cSrcweir                                             pLast->CalcSpacing( nSpaceAdd, aInf );
1158cdf0e10cSrcweir                     }
1159cdf0e10cSrcweir                 }
1160cdf0e10cSrcweir             }
1161cdf0e10cSrcweir             else
1162cdf0e10cSrcweir             {
1163cdf0e10cSrcweir                 const sal_uInt8 nPortionLevel = ((SwBidiPortion*)pPor)->GetLevel();
1164cdf0e10cSrcweir 
1165cdf0e10cSrcweir                 if ( pCMS->nCursorBidiLevel >= nPortionLevel )
1166cdf0e10cSrcweir                 {
1167cdf0e10cSrcweir                     // we came from inside the bidi portion, we want to blink
1168cdf0e10cSrcweir                     // behind the portion
1169cdf0e10cSrcweir                     pOrig->Pos().X() += pPor->Width() +
1170cdf0e10cSrcweir                                         pPor->CalcSpacing( nSpaceAdd, aInf );
1171cdf0e10cSrcweir                 }
1172cdf0e10cSrcweir             }
1173cdf0e10cSrcweir         }
1174cdf0e10cSrcweir 
1175cdf0e10cSrcweir 		pOrig->Pos().X() += nX;
1176cdf0e10cSrcweir 
1177cdf0e10cSrcweir 		if ( pCMS && pCMS->bRealHeight )
1178cdf0e10cSrcweir 		{
1179cdf0e10cSrcweir             nTmpAscent = AdjustBaseLine( *pCurr, 0, nPorHeight, nPorAscent );
1180cdf0e10cSrcweir             if ( nTmpAscent > nPorAscent )
1181cdf0e10cSrcweir 				pCMS->aRealHeight.X() = nTmpAscent - nPorAscent;
1182cdf0e10cSrcweir 			else
1183cdf0e10cSrcweir 				pCMS->aRealHeight.X() = 0;
1184cdf0e10cSrcweir 			ASSERT( nPorHeight, "GetCharRect: Missing Portion-Height" );
1185cdf0e10cSrcweir 			if ( nTmpHeight > nPorHeight )
1186cdf0e10cSrcweir 				pCMS->aRealHeight.Y() = nPorHeight;
1187cdf0e10cSrcweir 			else
1188cdf0e10cSrcweir 				pCMS->aRealHeight.Y() = nTmpHeight;
1189cdf0e10cSrcweir 		}
1190cdf0e10cSrcweir 	}
1191cdf0e10cSrcweir }
1192cdf0e10cSrcweir 
1193cdf0e10cSrcweir /*************************************************************************
1194cdf0e10cSrcweir  *						SwTxtCursor::GetCharRect()
1195cdf0e10cSrcweir  *************************************************************************/
1196cdf0e10cSrcweir 
GetCharRect(SwRect * pOrig,const xub_StrLen nOfst,SwCrsrMoveState * pCMS,const long nMax)1197cdf0e10cSrcweir sal_Bool SwTxtCursor::GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
1198cdf0e10cSrcweir 							   SwCrsrMoveState* pCMS, const long nMax )
1199cdf0e10cSrcweir {
1200cdf0e10cSrcweir 	CharCrsrToLine(nOfst);
1201cdf0e10cSrcweir 
1202cdf0e10cSrcweir     // Indicates that a position inside a special portion (field, number portion)
1203cdf0e10cSrcweir     // is requested.
1204cdf0e10cSrcweir     const sal_Bool bSpecialPos = pCMS && pCMS->pSpecialPos;
1205cdf0e10cSrcweir     xub_StrLen nFindOfst = nOfst;
1206cdf0e10cSrcweir 
1207cdf0e10cSrcweir     if ( bSpecialPos )
1208cdf0e10cSrcweir     {
1209cdf0e10cSrcweir         const sal_uInt8 nExtendRange = pCMS->pSpecialPos->nExtendRange;
1210cdf0e10cSrcweir 
1211cdf0e10cSrcweir         ASSERT( ! pCMS->pSpecialPos->nLineOfst || SP_EXTEND_RANGE_BEFORE != nExtendRange,
1212cdf0e10cSrcweir                 "LineOffset AND Number Portion?" )
1213cdf0e10cSrcweir 
1214cdf0e10cSrcweir         // portions which are behind the string
1215cdf0e10cSrcweir         if ( SP_EXTEND_RANGE_BEHIND == nExtendRange )
1216cdf0e10cSrcweir             ++nFindOfst;
1217cdf0e10cSrcweir 
1218cdf0e10cSrcweir         // skip lines for fields which cover more than one line
1219cdf0e10cSrcweir         for ( sal_uInt16 i = 0; i < pCMS->pSpecialPos->nLineOfst; i++ )
1220cdf0e10cSrcweir             Next();
1221cdf0e10cSrcweir     }
1222cdf0e10cSrcweir 
1223cdf0e10cSrcweir 	// Adjustierung ggf. nachholen
1224cdf0e10cSrcweir 	GetAdjusted();
1225cdf0e10cSrcweir 
1226cdf0e10cSrcweir 	const Point aCharPos( GetTopLeft() );
1227cdf0e10cSrcweir 	sal_Bool bRet = sal_True;
1228cdf0e10cSrcweir 
1229cdf0e10cSrcweir     _GetCharRect( pOrig, nFindOfst, pCMS );
1230cdf0e10cSrcweir 
1231cdf0e10cSrcweir     const SwTwips nTmpRight = Right() - 12;
1232cdf0e10cSrcweir 
1233cdf0e10cSrcweir     pOrig->Pos().X() += aCharPos.X();
1234cdf0e10cSrcweir 	pOrig->Pos().Y() += aCharPos.Y();
1235cdf0e10cSrcweir 
1236cdf0e10cSrcweir 	if( pCMS && pCMS->b2Lines && pCMS->p2Lines )
1237cdf0e10cSrcweir 	{
1238cdf0e10cSrcweir 		pCMS->p2Lines->aLine.Pos().X() += aCharPos.X();
1239cdf0e10cSrcweir 		pCMS->p2Lines->aLine.Pos().Y() += aCharPos.Y();
1240cdf0e10cSrcweir 		pCMS->p2Lines->aPortion.Pos().X() += aCharPos.X();
1241cdf0e10cSrcweir 		pCMS->p2Lines->aPortion.Pos().Y() += aCharPos.Y();
1242cdf0e10cSrcweir 	}
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir     if( pOrig->Left() > nTmpRight )
1245cdf0e10cSrcweir         pOrig->Pos().X() = nTmpRight;
1246cdf0e10cSrcweir 
1247cdf0e10cSrcweir 	if( nMax )
1248cdf0e10cSrcweir 	{
1249cdf0e10cSrcweir         if( pOrig->Top() + pOrig->Height() > nMax )
1250cdf0e10cSrcweir 		{
1251cdf0e10cSrcweir 			if( pOrig->Top() > nMax )
1252cdf0e10cSrcweir 				pOrig->Top( nMax );
1253cdf0e10cSrcweir             pOrig->Height( nMax - pOrig->Top() );
1254cdf0e10cSrcweir 		}
1255cdf0e10cSrcweir 		if ( pCMS && pCMS->bRealHeight && pCMS->aRealHeight.Y() >= 0 )
1256cdf0e10cSrcweir 		{
1257cdf0e10cSrcweir 			long nTmp = pCMS->aRealHeight.X() + pOrig->Top();
1258cdf0e10cSrcweir 			if(	nTmp >= nMax )
1259cdf0e10cSrcweir 			{
1260cdf0e10cSrcweir 				pCMS->aRealHeight.X() = nMax - pOrig->Top();
1261cdf0e10cSrcweir 				pCMS->aRealHeight.Y() = 0;
1262cdf0e10cSrcweir 			}
1263cdf0e10cSrcweir 			else if( nTmp + pCMS->aRealHeight.Y() > nMax )
1264cdf0e10cSrcweir 				pCMS->aRealHeight.Y() = nMax - nTmp;
1265cdf0e10cSrcweir 		}
1266cdf0e10cSrcweir 	}
1267cdf0e10cSrcweir 	long nOut = pOrig->Right() - GetTxtFrm()->Frm().Right();
1268cdf0e10cSrcweir 	if( nOut > 0 )
1269cdf0e10cSrcweir 	{
1270cdf0e10cSrcweir 		if( GetTxtFrm()->Frm().Width() < GetTxtFrm()->Prt().Left()
1271cdf0e10cSrcweir 								   + GetTxtFrm()->Prt().Width() )
1272cdf0e10cSrcweir 			nOut += GetTxtFrm()->Frm().Width() - GetTxtFrm()->Prt().Left()
1273cdf0e10cSrcweir 					- GetTxtFrm()->Prt().Width();
1274cdf0e10cSrcweir 		if( nOut > 0 )
1275cdf0e10cSrcweir 			pOrig->Pos().X() -= nOut + 10;
1276cdf0e10cSrcweir 	}
1277cdf0e10cSrcweir 	return bRet;
1278cdf0e10cSrcweir }
1279cdf0e10cSrcweir 
1280cdf0e10cSrcweir /*************************************************************************
1281cdf0e10cSrcweir  *						SwTxtCursor::GetCrsrOfst()
1282cdf0e10cSrcweir  *
1283cdf0e10cSrcweir  * Return: Offset im String
1284cdf0e10cSrcweir  *************************************************************************/
GetCrsrOfst(SwPosition * pPos,const Point & rPoint,const MSHORT nChgNode,SwCrsrMoveState * pCMS) const1285cdf0e10cSrcweir xub_StrLen SwTxtCursor::GetCrsrOfst( SwPosition *pPos, const Point &rPoint,
1286cdf0e10cSrcweir 					 const MSHORT nChgNode, SwCrsrMoveState* pCMS ) const
1287cdf0e10cSrcweir {
1288cdf0e10cSrcweir 	// Adjustierung ggf. nachholen
1289cdf0e10cSrcweir 	GetAdjusted();
1290cdf0e10cSrcweir 
1291cdf0e10cSrcweir 	const XubString &rText = GetInfo().GetTxt();
1292cdf0e10cSrcweir 	xub_StrLen nOffset = 0;
1293cdf0e10cSrcweir 
1294cdf0e10cSrcweir 	// x ist der horizontale Offset innerhalb der Zeile.
1295cdf0e10cSrcweir 	SwTwips x = rPoint.X();
1296cdf0e10cSrcweir 	CONST SwTwips nLeftMargin  = GetLineStart();
1297cdf0e10cSrcweir 	SwTwips nRightMargin = GetLineEnd();
1298cdf0e10cSrcweir 	if( nRightMargin == nLeftMargin )
1299cdf0e10cSrcweir 		nRightMargin += 30;
1300cdf0e10cSrcweir 
1301cdf0e10cSrcweir 	const sal_Bool bLeftOver = x < nLeftMargin;
1302cdf0e10cSrcweir 	if( bLeftOver )
1303cdf0e10cSrcweir 		x = nLeftMargin;
1304cdf0e10cSrcweir 	const sal_Bool bRightOver = x > nRightMargin;
1305cdf0e10cSrcweir 	if( bRightOver )
1306cdf0e10cSrcweir 		x = nRightMargin;
1307cdf0e10cSrcweir 
1308cdf0e10cSrcweir 	sal_Bool bRightAllowed = pCMS && ( pCMS->eState == MV_NONE );
1309cdf0e10cSrcweir 
1310cdf0e10cSrcweir 	// Bis hierher in Dokumentkoordinaten.
1311cdf0e10cSrcweir 	x -= nLeftMargin;
1312cdf0e10cSrcweir 
1313cdf0e10cSrcweir 	KSHORT nX = KSHORT( x );
1314cdf0e10cSrcweir 
1315cdf0e10cSrcweir 	// Wenn es in der Zeile Attributwechsel gibt, den Abschnitt
1316cdf0e10cSrcweir 	// suchen, in dem nX liegt.
1317cdf0e10cSrcweir 	SwLinePortion *pPor = pCurr->GetFirstPortion();
1318cdf0e10cSrcweir 	xub_StrLen nCurrStart  = nStart;
1319cdf0e10cSrcweir 	sal_Bool bHolePortion = sal_False;
1320cdf0e10cSrcweir 	sal_Bool bLastHyph = sal_False;
1321cdf0e10cSrcweir 
1322cdf0e10cSrcweir     SvUShorts *pKanaComp = pCurr->GetpKanaComp();
1323cdf0e10cSrcweir 	xub_StrLen nOldIdx = GetInfo().GetIdx();
1324cdf0e10cSrcweir 	MSHORT nSpaceIdx = 0;
1325cdf0e10cSrcweir     MSHORT nKanaIdx = 0;
1326cdf0e10cSrcweir     long nSpaceAdd = pCurr->IsSpaceAdd() ? pCurr->GetLLSpaceAdd( 0 ) : 0;
1327cdf0e10cSrcweir     short nKanaComp = pKanaComp ? (*pKanaComp)[0] : 0;
1328cdf0e10cSrcweir 
1329cdf0e10cSrcweir 	// nWidth ist die Breite der Zeile, oder die Breite des
1330cdf0e10cSrcweir 	// Abschnitts mit dem Fontwechsel, in dem nX liegt.
1331cdf0e10cSrcweir 
1332cdf0e10cSrcweir 	KSHORT nWidth = pPor->Width();
1333cdf0e10cSrcweir     if ( pCurr->IsSpaceAdd() || pKanaComp )
1334cdf0e10cSrcweir 	{
1335cdf0e10cSrcweir 		if ( pPor->InSpaceGrp() && nSpaceAdd )
1336cdf0e10cSrcweir 		{
1337cdf0e10cSrcweir 			((SwTxtSizeInfo&)GetInfo()).SetIdx( nCurrStart );
1338cdf0e10cSrcweir 			nWidth = nWidth + sal_uInt16( pPor->CalcSpacing( nSpaceAdd, GetInfo() ) );
1339cdf0e10cSrcweir 		}
1340cdf0e10cSrcweir         if( ( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() ) ||
1341cdf0e10cSrcweir             ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
1342cdf0e10cSrcweir           )
1343cdf0e10cSrcweir 		{
1344cdf0e10cSrcweir             if ( pCurr->IsSpaceAdd() )
1345cdf0e10cSrcweir             {
1346cdf0e10cSrcweir                 if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
1347cdf0e10cSrcweir                     nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
1348cdf0e10cSrcweir                 else
1349cdf0e10cSrcweir                     nSpaceAdd = 0;
1350cdf0e10cSrcweir             }
1351cdf0e10cSrcweir 
1352cdf0e10cSrcweir             if( pKanaComp )
1353cdf0e10cSrcweir             {
1354cdf0e10cSrcweir                 if ( nKanaIdx + 1 < pKanaComp->Count() )
1355cdf0e10cSrcweir                     nKanaComp = (*pKanaComp)[++nKanaIdx];
1356cdf0e10cSrcweir                 else
1357cdf0e10cSrcweir                     nKanaComp = 0;
1358cdf0e10cSrcweir             }
1359cdf0e10cSrcweir 		}
1360cdf0e10cSrcweir 	}
1361cdf0e10cSrcweir 
1362cdf0e10cSrcweir     KSHORT nWidth30;
1363cdf0e10cSrcweir     if ( pPor->IsPostItsPortion() )
1364cdf0e10cSrcweir         nWidth30 = 30 + pPor->GetViewWidth( GetInfo() ) / 2;
1365cdf0e10cSrcweir     else
1366cdf0e10cSrcweir         nWidth30 = ! nWidth && pPor->GetLen() && pPor->InToxRefOrFldGrp() ?
1367cdf0e10cSrcweir                      30 :
1368cdf0e10cSrcweir                      nWidth;
1369cdf0e10cSrcweir 
1370cdf0e10cSrcweir 	while( pPor->GetPortion() && nWidth30 < nX && !pPor->IsBreakPortion() )
1371cdf0e10cSrcweir 	{
1372cdf0e10cSrcweir 		nX = nX - nWidth;
1373cdf0e10cSrcweir 		nCurrStart = nCurrStart + pPor->GetLen();
1374cdf0e10cSrcweir 		bHolePortion = pPor->IsHolePortion();
1375cdf0e10cSrcweir 		pPor = pPor->GetPortion();
1376cdf0e10cSrcweir 		nWidth = pPor->Width();
1377cdf0e10cSrcweir         if ( pCurr->IsSpaceAdd() || pKanaComp )
1378cdf0e10cSrcweir 		{
1379cdf0e10cSrcweir 			if ( pPor->InSpaceGrp() && nSpaceAdd )
1380cdf0e10cSrcweir 			{
1381cdf0e10cSrcweir 				((SwTxtSizeInfo&)GetInfo()).SetIdx( nCurrStart );
1382cdf0e10cSrcweir 				nWidth = nWidth + sal_uInt16( pPor->CalcSpacing( nSpaceAdd, GetInfo() ) );
1383cdf0e10cSrcweir 			}
1384cdf0e10cSrcweir 
1385cdf0e10cSrcweir             if( ( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() ) ||
1386cdf0e10cSrcweir                 ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
1387cdf0e10cSrcweir               )
1388cdf0e10cSrcweir 			{
1389cdf0e10cSrcweir                 if ( pCurr->IsSpaceAdd() )
1390cdf0e10cSrcweir                 {
1391cdf0e10cSrcweir                     if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
1392cdf0e10cSrcweir                         nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
1393cdf0e10cSrcweir                     else
1394cdf0e10cSrcweir                         nSpaceAdd = 0;
1395cdf0e10cSrcweir                 }
1396cdf0e10cSrcweir 
1397cdf0e10cSrcweir                 if ( pKanaComp )
1398cdf0e10cSrcweir                 {
1399cdf0e10cSrcweir                     if( nKanaIdx + 1 < pKanaComp->Count() )
1400cdf0e10cSrcweir                         nKanaComp = (*pKanaComp)[++nKanaIdx];
1401cdf0e10cSrcweir                     else
1402cdf0e10cSrcweir                         nKanaComp = 0;
1403cdf0e10cSrcweir                 }
1404cdf0e10cSrcweir 			}
1405cdf0e10cSrcweir 		}
1406cdf0e10cSrcweir 
1407cdf0e10cSrcweir         if ( pPor->IsPostItsPortion() )
1408cdf0e10cSrcweir             nWidth30 = 30 +  pPor->GetViewWidth( GetInfo() ) / 2;
1409cdf0e10cSrcweir         else
1410cdf0e10cSrcweir             nWidth30 = ! nWidth && pPor->GetLen() && pPor->InToxRefOrFldGrp() ?
1411cdf0e10cSrcweir                          30 :
1412cdf0e10cSrcweir                          nWidth;
1413cdf0e10cSrcweir 		if( !pPor->IsFlyPortion() && !pPor->IsMarginPortion() )
1414cdf0e10cSrcweir 			bLastHyph = pPor->InHyphGrp();
1415cdf0e10cSrcweir 	}
1416cdf0e10cSrcweir 
1417cdf0e10cSrcweir     const sal_Bool bLastPortion = (0 == pPor->GetPortion());
1418cdf0e10cSrcweir 
1419cdf0e10cSrcweir 	if( nX==nWidth )
1420cdf0e10cSrcweir 	{
1421cdf0e10cSrcweir 		SwLinePortion *pNextPor = pPor->GetPortion();
1422cdf0e10cSrcweir 		while( pNextPor && pNextPor->InFldGrp() && !pNextPor->Width() )
1423cdf0e10cSrcweir 		{
1424cdf0e10cSrcweir 			nCurrStart = nCurrStart + pPor->GetLen();
1425cdf0e10cSrcweir 			pPor = pNextPor;
1426cdf0e10cSrcweir 			if( !pPor->IsFlyPortion() && !pPor->IsMarginPortion() )
1427cdf0e10cSrcweir 				bLastHyph = pPor->InHyphGrp();
1428cdf0e10cSrcweir 			pNextPor = pPor->GetPortion();
1429cdf0e10cSrcweir 		}
1430cdf0e10cSrcweir 	}
1431cdf0e10cSrcweir 
1432cdf0e10cSrcweir 	((SwTxtSizeInfo&)GetInfo()).SetIdx( nOldIdx );
1433cdf0e10cSrcweir 
1434cdf0e10cSrcweir 	xub_StrLen nLength = pPor->GetLen();
1435cdf0e10cSrcweir 
1436cdf0e10cSrcweir 	sal_Bool bFieldInfo = pCMS && pCMS->bFieldInfo;
1437cdf0e10cSrcweir 
1438cdf0e10cSrcweir 	if( bFieldInfo && ( nWidth30 < nX || bRightOver || bLeftOver ||
1439cdf0e10cSrcweir 		( pPor->InNumberGrp() && !pPor->IsFtnNumPortion() ) ||
1440cdf0e10cSrcweir 		( pPor->IsMarginPortion() && nWidth > nX + 30 ) ) )
1441cdf0e10cSrcweir 		((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
1442cdf0e10cSrcweir 
1443cdf0e10cSrcweir 
1444cdf0e10cSrcweir     // #i27615#
1445cdf0e10cSrcweir     if (pCMS)
1446cdf0e10cSrcweir     {
1447cdf0e10cSrcweir         if( pCMS->bInFrontOfLabel)
1448cdf0e10cSrcweir         {
1449cdf0e10cSrcweir             if (! (2 * nX < nWidth && pPor->InNumberGrp() &&
1450cdf0e10cSrcweir                    !pPor->IsFtnNumPortion()))
1451cdf0e10cSrcweir                 pCMS->bInFrontOfLabel = sal_False;
1452cdf0e10cSrcweir         }
1453cdf0e10cSrcweir     }
1454cdf0e10cSrcweir 
1455cdf0e10cSrcweir 	// 7684: Wir sind genau auf der HyphPortion angelangt und muessen dafuer
1456cdf0e10cSrcweir 	// sorgen, dass wir in dem String landen.
1457cdf0e10cSrcweir 	// 7993: Wenn die Laenge 0 ist muessen wir raus...
1458cdf0e10cSrcweir 	if( !nLength )
1459cdf0e10cSrcweir 	{
1460cdf0e10cSrcweir 		if( pCMS )
1461cdf0e10cSrcweir 		{
1462cdf0e10cSrcweir 			if( pPor->IsFlyPortion() && bFieldInfo )
1463cdf0e10cSrcweir 				((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
1464cdf0e10cSrcweir 
1465cdf0e10cSrcweir             if (!bRightOver && nX)
1466cdf0e10cSrcweir             {
1467cdf0e10cSrcweir                 if( pPor->IsFtnNumPortion())
1468cdf0e10cSrcweir                     ((SwCrsrMoveState*)pCMS)->bFtnNoInfo = sal_True;
1469cdf0e10cSrcweir                 else if (pPor->InNumberGrp() ) // #i23726#
1470cdf0e10cSrcweir                 {
1471cdf0e10cSrcweir                     ((SwCrsrMoveState*)pCMS)->nInNumPostionOffset = nX;
1472cdf0e10cSrcweir                     ((SwCrsrMoveState*)pCMS)->bInNumPortion = sal_True;
1473cdf0e10cSrcweir                 }
1474cdf0e10cSrcweir             }
1475cdf0e10cSrcweir 		}
1476cdf0e10cSrcweir 		if( !nCurrStart )
1477cdf0e10cSrcweir 			return 0;
1478cdf0e10cSrcweir 
1479cdf0e10cSrcweir 		 // 7849, 7816: auf pPor->GetHyphPortion kann nicht verzichtet werden!
1480cdf0e10cSrcweir 		if( bHolePortion || ( !bRightAllowed && bLastHyph ) ||
1481cdf0e10cSrcweir 			( pPor->IsMarginPortion() && !pPor->GetPortion() &&
1482cdf0e10cSrcweir 			// 46598: In der letzten Zeile eines zentrierten Absatzes wollen
1483cdf0e10cSrcweir 			// wir auch mal hinter dem letzten Zeichen landen.
1484cdf0e10cSrcweir               nCurrStart < rText.Len() ) )
1485cdf0e10cSrcweir 			--nCurrStart;
1486cdf0e10cSrcweir 		else if( pPor->InFldGrp() && ((SwFldPortion*)pPor)->IsFollow()
1487cdf0e10cSrcweir 				 && nWidth > nX )
1488cdf0e10cSrcweir         {
1489cdf0e10cSrcweir 			if( bFieldInfo )
1490cdf0e10cSrcweir 				--nCurrStart;
1491cdf0e10cSrcweir 			else
1492cdf0e10cSrcweir 			{
1493cdf0e10cSrcweir 				KSHORT nHeight = pPor->Height();
1494cdf0e10cSrcweir 				if ( !nHeight || nHeight > nWidth )
1495cdf0e10cSrcweir 					nHeight = nWidth;
1496cdf0e10cSrcweir 				if( nChgNode && nWidth - nHeight/2 > nX )
1497cdf0e10cSrcweir 					--nCurrStart;
1498cdf0e10cSrcweir 			}
1499cdf0e10cSrcweir 		}
1500cdf0e10cSrcweir 		return nCurrStart;
1501cdf0e10cSrcweir 	}
1502cdf0e10cSrcweir 	if ( 1 == nLength )
1503cdf0e10cSrcweir 	{
1504cdf0e10cSrcweir 		if ( nWidth )
1505cdf0e10cSrcweir 		{
1506cdf0e10cSrcweir 			// Sonst kommen wir nicht mehr in zeichengeb. Rahmen hinein...
1507cdf0e10cSrcweir 			if( !( nChgNode && pPos && pPor->IsFlyCntPortion() ) )
1508cdf0e10cSrcweir 			{
1509cdf0e10cSrcweir 				if ( pPor->InFldGrp() ||
1510cdf0e10cSrcweir                      ( pPor->IsMultiPortion() &&
1511cdf0e10cSrcweir                        ((SwMultiPortion*)pPor)->IsBidi()  ) )
1512cdf0e10cSrcweir 				{
1513cdf0e10cSrcweir 					KSHORT nHeight = 0;
1514cdf0e10cSrcweir 					if( !bFieldInfo )
1515cdf0e10cSrcweir 					{
1516cdf0e10cSrcweir 						nHeight = pPor->Height();
1517cdf0e10cSrcweir 						if ( !nHeight || nHeight > nWidth )
1518cdf0e10cSrcweir 							nHeight = nWidth;
1519cdf0e10cSrcweir 					}
1520cdf0e10cSrcweir 
1521cdf0e10cSrcweir 					if( nWidth - nHeight/2 <= nX &&
1522cdf0e10cSrcweir                         ( ! pPor->InFldGrp() ||
1523cdf0e10cSrcweir                           !((SwFldPortion*)pPor)->HasFollow() ) )
1524cdf0e10cSrcweir                         ++nCurrStart;
1525cdf0e10cSrcweir 				}
1526cdf0e10cSrcweir                 else if ( ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
1527cdf0e10cSrcweir 					!pPor->GetPortion()->IsMarginPortion() &&
1528cdf0e10cSrcweir                     !pPor->GetPortion()->IsHolePortion() ) )
1529cdf0e10cSrcweir                          && ( nWidth/2 < nX ) &&
1530cdf0e10cSrcweir                          ( !bFieldInfo ||
1531cdf0e10cSrcweir                             ( pPor->GetPortion() &&
1532cdf0e10cSrcweir                               pPor->GetPortion()->IsPostItsPortion() ) )
1533cdf0e10cSrcweir 						 && ( bRightAllowed || !bLastHyph ))
1534cdf0e10cSrcweir 					++nCurrStart;
1535cdf0e10cSrcweir 
1536cdf0e10cSrcweir                 // if we want to get the position inside the field, we should not return
1537cdf0e10cSrcweir                 if ( !pCMS || !pCMS->pSpecialPos )
1538cdf0e10cSrcweir 				    return nCurrStart;
1539cdf0e10cSrcweir 			}
1540cdf0e10cSrcweir 		}
1541cdf0e10cSrcweir 		else
1542cdf0e10cSrcweir 		{
1543cdf0e10cSrcweir 			if ( pPor->IsPostItsPortion() || pPor->IsBreakPortion() ||
1544cdf0e10cSrcweir 				 pPor->InToxRefGrp() )
1545cdf0e10cSrcweir 				return nCurrStart;
1546cdf0e10cSrcweir 			if ( pPor->InFldGrp() )
1547cdf0e10cSrcweir 			{
1548cdf0e10cSrcweir 				if( bRightOver && !((SwFldPortion*)pPor)->HasFollow() )
1549cdf0e10cSrcweir 					++nCurrStart;
1550cdf0e10cSrcweir 				return nCurrStart;
1551cdf0e10cSrcweir 			}
1552cdf0e10cSrcweir 		}
1553cdf0e10cSrcweir 	}
1554cdf0e10cSrcweir 
1555cdf0e10cSrcweir 	if( bLastPortion && (pCurr->GetNext() || pFrm->GetFollow() ) )
1556cdf0e10cSrcweir 		--nLength;
1557cdf0e10cSrcweir 
1558cdf0e10cSrcweir     if( nWidth > nX ||
1559cdf0e10cSrcweir       ( nWidth == nX && pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsDouble() ) )
1560cdf0e10cSrcweir 	{
1561cdf0e10cSrcweir 		if( pPor->IsMultiPortion() )
1562cdf0e10cSrcweir 		{
1563cdf0e10cSrcweir             // In a multi-portion we use GetCrsrOfst()-function recursively
1564cdf0e10cSrcweir 			SwTwips nTmpY = rPoint.Y() - pCurr->GetAscent() + pPor->GetAscent();
1565cdf0e10cSrcweir             // if we are in the first line of a double line portion, we have
1566cdf0e10cSrcweir             // to add a value to nTmpY for not staying in this line
1567cdf0e10cSrcweir             // we also want to skip the first line, if we are inside ruby
1568cdf0e10cSrcweir             if ( ( ((SwTxtSizeInfo*)pInf)->IsMulti() &&
1569cdf0e10cSrcweir                    ((SwTxtSizeInfo*)pInf)->IsFirstMulti() ) ||
1570cdf0e10cSrcweir                  ( ((SwMultiPortion*)pPor)->IsRuby() &&
1571cdf0e10cSrcweir                    ((SwMultiPortion*)pPor)->OnTop() ) )
1572cdf0e10cSrcweir                 nTmpY += ((SwMultiPortion*)pPor)->Height();
1573cdf0e10cSrcweir 
1574cdf0e10cSrcweir             // Important for cursor traveling in ruby portions:
1575cdf0e10cSrcweir             // We have to set nTmpY to 0 in order to stay in the first row
1576cdf0e10cSrcweir             // if the phonetic line is the second row
1577cdf0e10cSrcweir             if (   ((SwMultiPortion*)pPor)->IsRuby() &&
1578cdf0e10cSrcweir                  ! ((SwMultiPortion*)pPor)->OnTop() )
1579cdf0e10cSrcweir                 nTmpY = 0;
1580cdf0e10cSrcweir 
1581cdf0e10cSrcweir             SwTxtCursorSave aSave( (SwTxtCursor*)this, (SwMultiPortion*)pPor,
1582cdf0e10cSrcweir                  nTmpY, nX, nCurrStart, nSpaceAdd );
1583cdf0e10cSrcweir 
1584cdf0e10cSrcweir             SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
1585cdf0e10cSrcweir             if ( ((SwMultiPortion*)pPor)->IsBidi() )
1586cdf0e10cSrcweir             {
1587cdf0e10cSrcweir                 const sal_uInt8 nBidiLevel = ((SwBidiPortion*)pPor)->GetLevel();
1588cdf0e10cSrcweir                 aLayoutModeModifier.Modify( nBidiLevel % 2 );
1589cdf0e10cSrcweir             }
1590cdf0e10cSrcweir 
1591cdf0e10cSrcweir 			if( ((SwMultiPortion*)pPor)->HasRotation() )
1592cdf0e10cSrcweir 			{
1593cdf0e10cSrcweir 				nTmpY -= nY;
1594cdf0e10cSrcweir 				if( !((SwMultiPortion*)pPor)->IsRevers() )
1595cdf0e10cSrcweir 					nTmpY = pPor->Height() - nTmpY;
1596cdf0e10cSrcweir 				if( nTmpY < 0 )
1597cdf0e10cSrcweir 					nTmpY = 0;
1598cdf0e10cSrcweir                 nX = (KSHORT)nTmpY;
1599cdf0e10cSrcweir 			}
1600cdf0e10cSrcweir 
1601cdf0e10cSrcweir 			if( ((SwMultiPortion*)pPor)->HasBrackets() )
1602cdf0e10cSrcweir             {
1603cdf0e10cSrcweir                 sal_uInt16 nPreWidth = ((SwDoubleLinePortion*)pPor)->PreWidth();
1604cdf0e10cSrcweir                 if ( nX > nPreWidth )
1605cdf0e10cSrcweir                     nX = nX - nPreWidth;
1606cdf0e10cSrcweir                 else
1607cdf0e10cSrcweir                     nX = 0;
1608cdf0e10cSrcweir             }
1609cdf0e10cSrcweir 
1610cdf0e10cSrcweir             return GetCrsrOfst( pPos, Point( GetLineStart() + nX, rPoint.Y() ),
1611cdf0e10cSrcweir 								nChgNode, pCMS );
1612cdf0e10cSrcweir 		}
1613cdf0e10cSrcweir 		if( pPor->InTxtGrp() )
1614cdf0e10cSrcweir 		{
1615cdf0e10cSrcweir 			sal_uInt8 nOldProp;
1616cdf0e10cSrcweir 			if( GetPropFont() )
1617cdf0e10cSrcweir 			{
1618cdf0e10cSrcweir 				((SwFont*)GetFnt())->SetProportion( GetPropFont() );
1619cdf0e10cSrcweir 				nOldProp = GetFnt()->GetPropr();
1620cdf0e10cSrcweir 			}
1621cdf0e10cSrcweir 			else
1622cdf0e10cSrcweir 				nOldProp = 0;
1623cdf0e10cSrcweir 			{
1624cdf0e10cSrcweir 				SwTxtSizeInfo aSizeInf( GetInfo(), rText, nCurrStart );
1625cdf0e10cSrcweir 				((SwTxtCursor*)this)->SeekAndChg( aSizeInf );
1626cdf0e10cSrcweir                 SwTxtSlot aDiffTxt( &aSizeInf, ((SwTxtPortion*)pPor), false, false );
1627cdf0e10cSrcweir 				SwFontSave aSave( aSizeInf, pPor->IsDropPortion() ?
1628cdf0e10cSrcweir 						((SwDropPortion*)pPor)->GetFnt() : NULL );
1629cdf0e10cSrcweir 
1630cdf0e10cSrcweir                 SwParaPortion* pPara = (SwParaPortion*)GetInfo().GetParaPortion();
1631cdf0e10cSrcweir                 ASSERT( pPara, "No paragraph!" );
1632cdf0e10cSrcweir 
1633cdf0e10cSrcweir                 SwDrawTextInfo aDrawInf( aSizeInf.GetVsh(),
1634cdf0e10cSrcweir                                          *aSizeInf.GetOut(),
1635cdf0e10cSrcweir                                          &pPara->GetScriptInfo(),
1636cdf0e10cSrcweir                                          aSizeInf.GetTxt(),
1637cdf0e10cSrcweir                                          aSizeInf.GetIdx(),
1638cdf0e10cSrcweir                                          pPor->GetLen() );
1639cdf0e10cSrcweir                 aDrawInf.SetOfst( nX );
1640cdf0e10cSrcweir 
1641cdf0e10cSrcweir                 if ( nSpaceAdd )
1642cdf0e10cSrcweir                 {
1643cdf0e10cSrcweir                     xub_StrLen nCharCnt;
1644cdf0e10cSrcweir                     // --> FME 2005-04-04 #i41860# Thai justified alignemt needs some
1645cdf0e10cSrcweir                     // additional information:
1646cdf0e10cSrcweir                     aDrawInf.SetNumberOfBlanks( pPor->InTxtGrp() ?
1647cdf0e10cSrcweir                                                 static_cast<const SwTxtPortion*>(pPor)->GetSpaceCnt( aSizeInf, nCharCnt ) :
1648cdf0e10cSrcweir                                                 0 );
1649cdf0e10cSrcweir                     // <--
1650cdf0e10cSrcweir                 }
1651cdf0e10cSrcweir 
1652cdf0e10cSrcweir                 if ( pPor->InFldGrp() && pCMS && pCMS->pSpecialPos )
1653cdf0e10cSrcweir                     aDrawInf.SetLen( STRING_LEN ); // SMARTTAGS
1654cdf0e10cSrcweir 
1655cdf0e10cSrcweir                 aDrawInf.SetSpace( nSpaceAdd );
1656cdf0e10cSrcweir                 aDrawInf.SetFont( aSizeInf.GetFont() );
1657cdf0e10cSrcweir                 aDrawInf.SetFrm( pFrm );
1658cdf0e10cSrcweir                 aDrawInf.SetSnapToGrid( aSizeInf.SnapToGrid() );
1659cdf0e10cSrcweir                 aDrawInf.SetPosMatchesBounds( pCMS && pCMS->bPosMatchesBounds );
1660cdf0e10cSrcweir 
1661cdf0e10cSrcweir                 if ( SW_CJK == aSizeInf.GetFont()->GetActual() &&
1662cdf0e10cSrcweir                      pPara->GetScriptInfo().CountCompChg() &&
1663cdf0e10cSrcweir                     ! pPor->InFldGrp() )
1664cdf0e10cSrcweir                     aDrawInf.SetKanaComp( nKanaComp );
1665cdf0e10cSrcweir 
1666cdf0e10cSrcweir                 nLength = aSizeInf.GetFont()->_GetCrsrOfst( aDrawInf );
1667cdf0e10cSrcweir 
1668cdf0e10cSrcweir                 // get position inside field portion?
1669cdf0e10cSrcweir                 if ( pPor->InFldGrp() && pCMS && pCMS->pSpecialPos )
1670cdf0e10cSrcweir                 {
1671cdf0e10cSrcweir                     pCMS->pSpecialPos->nCharOfst = nLength;
1672cdf0e10cSrcweir                     nLength = 0; // SMARTTAGS
1673cdf0e10cSrcweir                 }
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir                 // set cursor bidi level
1676cdf0e10cSrcweir                 if ( pCMS )
1677cdf0e10cSrcweir                     ((SwCrsrMoveState*)pCMS)->nCursorBidiLevel =
1678cdf0e10cSrcweir                         aDrawInf.GetCursorBidiLevel();
1679cdf0e10cSrcweir 
1680cdf0e10cSrcweir                 if( bFieldInfo && nLength == pPor->GetLen() &&
1681cdf0e10cSrcweir                     ( ! pPor->GetPortion() ||
1682cdf0e10cSrcweir                       ! pPor->GetPortion()->IsPostItsPortion() ) )
1683cdf0e10cSrcweir 					--nLength;
1684cdf0e10cSrcweir 			}
1685cdf0e10cSrcweir 			if( nOldProp )
1686cdf0e10cSrcweir 				((SwFont*)GetFnt())->SetProportion( nOldProp );
1687cdf0e10cSrcweir 		}
1688cdf0e10cSrcweir 		else
1689cdf0e10cSrcweir 		{
1690cdf0e10cSrcweir 			if( nChgNode && pPos && pPor->IsFlyCntPortion()
1691cdf0e10cSrcweir 				&& !( (SwFlyCntPortion*)pPor )->IsDraw() )
1692cdf0e10cSrcweir 			{
1693cdf0e10cSrcweir 				// JP 24.11.94: liegt die Pos nicht im Fly, dann
1694cdf0e10cSrcweir 				// 				darf nicht mit STRING_LEN returnt werden!
1695cdf0e10cSrcweir 				//				(BugId: 9692 + Aenderung in feshview)
1696cdf0e10cSrcweir 				SwFlyInCntFrm *pTmp = ( (SwFlyCntPortion*)pPor )->GetFlyFrm();
1697cdf0e10cSrcweir 				sal_Bool bChgNode = 1 < nChgNode;
1698cdf0e10cSrcweir 				if( !bChgNode )
1699cdf0e10cSrcweir 				{
1700cdf0e10cSrcweir 					SwFrm* pLower = pTmp->GetLower();
1701cdf0e10cSrcweir 					if( pLower && (pLower->IsTxtFrm() || pLower->IsLayoutFrm()) )
1702cdf0e10cSrcweir 						bChgNode = sal_True;
1703cdf0e10cSrcweir 				}
1704cdf0e10cSrcweir                 Point aTmpPoint( rPoint );
1705cdf0e10cSrcweir 
1706cdf0e10cSrcweir                 if ( pFrm->IsRightToLeft() )
1707cdf0e10cSrcweir                     pFrm->SwitchLTRtoRTL( aTmpPoint );
1708cdf0e10cSrcweir 
1709cdf0e10cSrcweir                 if ( pFrm->IsVertical() )
1710cdf0e10cSrcweir                     pFrm->SwitchHorizontalToVertical( aTmpPoint );
1711cdf0e10cSrcweir 
1712cdf0e10cSrcweir                 if( bChgNode && pTmp->Frm().IsInside( aTmpPoint ) &&
1713cdf0e10cSrcweir 					!( pTmp->IsProtected() ) )
1714cdf0e10cSrcweir 				{
1715cdf0e10cSrcweir 					nLength = ((SwFlyCntPortion*)pPor)->
1716cdf0e10cSrcweir                               GetFlyCrsrOfst( nX, aTmpPoint, pPos, pCMS );
1717cdf0e10cSrcweir 					// Sobald der Frame gewechselt wird, muessen wir aufpassen, dass
1718cdf0e10cSrcweir 					// unser Font wieder im OutputDevice steht.
1719cdf0e10cSrcweir 					// vgl. Paint und new SwFlyCntPortion !
1720cdf0e10cSrcweir 					((SwTxtSizeInfo*)pInf)->SelectFont();
1721cdf0e10cSrcweir 
1722cdf0e10cSrcweir 					// 6776: Das pIter->GetCrsrOfst returnt
1723cdf0e10cSrcweir 					// aus einer Verschachtelung mit STRING_LEN.
1724cdf0e10cSrcweir 					return STRING_LEN;
1725cdf0e10cSrcweir 				}
1726cdf0e10cSrcweir 			}
1727cdf0e10cSrcweir 			else
1728cdf0e10cSrcweir 				nLength = pPor->GetCrsrOfst( nX );
1729cdf0e10cSrcweir 		}
1730cdf0e10cSrcweir 	}
1731cdf0e10cSrcweir 	nOffset = nCurrStart + nLength;
1732cdf0e10cSrcweir 
1733cdf0e10cSrcweir 	// 7684: Wir sind vor der HyphPortion angelangt und muessen dafuer
1734cdf0e10cSrcweir 	// sorgen, dass wir in dem String landen.
1735cdf0e10cSrcweir 	// Bei Zeilenenden vor FlyFrms muessen ebenso behandelt werden.
1736cdf0e10cSrcweir 
1737cdf0e10cSrcweir 	if( nOffset && pPor->GetLen() == nLength && pPor->GetPortion() &&
1738cdf0e10cSrcweir 		!pPor->GetPortion()->GetLen() && pPor->GetPortion()->InHyphGrp() )
1739cdf0e10cSrcweir 		--nOffset;
1740cdf0e10cSrcweir 
1741cdf0e10cSrcweir 	return nOffset;
1742cdf0e10cSrcweir }
1743cdf0e10cSrcweir 
1744cdf0e10cSrcweir /** Looks for text portions which are inside the given rectangle
1745cdf0e10cSrcweir 
1746cdf0e10cSrcweir     For a rectangular text selection every text portions which is inside the given
1747cdf0e10cSrcweir     rectangle has to be put into the SwSelectionList as SwPaM
1748cdf0e10cSrcweir     From these SwPaM the SwCursors will be created.
1749cdf0e10cSrcweir 
1750cdf0e10cSrcweir     @param rSelList
1751cdf0e10cSrcweir     The container for the overlapped text portions
1752cdf0e10cSrcweir 
1753cdf0e10cSrcweir     @param rRect
1754cdf0e10cSrcweir     A rectangle in document coordinates, text inside this rectangle has to be
1755cdf0e10cSrcweir     selected.
1756cdf0e10cSrcweir 
1757cdf0e10cSrcweir     @return [ true, false ]
1758cdf0e10cSrcweir     true if any overlapping text portion has been found and put into list
1759cdf0e10cSrcweir     false if no portion overlaps, the list has been unchanged
1760cdf0e10cSrcweir */
FillSelection(SwSelectionList & rSelList,const SwRect & rRect) const1761cdf0e10cSrcweir bool SwTxtFrm::FillSelection( SwSelectionList& rSelList, const SwRect& rRect ) const
1762cdf0e10cSrcweir {
1763cdf0e10cSrcweir     bool bRet = false;
1764cdf0e10cSrcweir     // PaintArea() instead Frm() for negative indents
1765cdf0e10cSrcweir     SwRect aTmpFrm( PaintArea() );
1766cdf0e10cSrcweir     if( !rRect.IsOver( aTmpFrm ) )
1767cdf0e10cSrcweir         return false;
1768cdf0e10cSrcweir     if( rSelList.checkContext( this ) )
1769cdf0e10cSrcweir     {
1770cdf0e10cSrcweir         SwRect aRect( aTmpFrm );
1771cdf0e10cSrcweir         aRect.Intersection( rRect );
1772cdf0e10cSrcweir         // rNode without const to create SwPaMs
1773cdf0e10cSrcweir         SwCntntNode &rNode = const_cast<SwCntntNode&>( *GetNode() );
1774cdf0e10cSrcweir         SwNodeIndex aIdx( rNode );
1775cdf0e10cSrcweir         SwPosition aPosL( aIdx, SwIndex( &rNode, 0 ) );
1776cdf0e10cSrcweir         if( IsEmpty() )
1777cdf0e10cSrcweir         {
1778cdf0e10cSrcweir             SwPaM *pPam = new SwPaM( aPosL, aPosL );
1779cdf0e10cSrcweir             rSelList.insertPaM( pPam );
1780cdf0e10cSrcweir         }
1781cdf0e10cSrcweir         else if( aRect.HasArea() )
1782cdf0e10cSrcweir         {
1783cdf0e10cSrcweir             xub_StrLen nOld = STRING_LEN;
1784cdf0e10cSrcweir             SwPosition aPosR( aPosL );
1785cdf0e10cSrcweir             Point aPoint;
1786cdf0e10cSrcweir             SwTxtInfo aInf( const_cast<SwTxtFrm*>(this) );
1787cdf0e10cSrcweir             SwTxtIter aLine( const_cast<SwTxtFrm*>(this), &aInf );
1788cdf0e10cSrcweir             // We have to care for top-to-bottom layout, where right becomes top etc.
1789cdf0e10cSrcweir             SWRECTFN( this )
1790cdf0e10cSrcweir             SwTwips nTop = (aRect.*fnRect->fnGetTop)();
1791cdf0e10cSrcweir             SwTwips nBottom = (aRect.*fnRect->fnGetBottom)();
1792cdf0e10cSrcweir             SwTwips nLeft = (aRect.*fnRect->fnGetLeft)();
1793cdf0e10cSrcweir             SwTwips nRight = (aRect.*fnRect->fnGetRight)();
1794cdf0e10cSrcweir             SwTwips nY = aLine.Y(); // Top position of the first line
1795cdf0e10cSrcweir             SwTwips nLastY = nY;
1796cdf0e10cSrcweir             while( nY < nTop && aLine.Next() ) // line above rectangle
1797cdf0e10cSrcweir             {
1798cdf0e10cSrcweir                 nLastY = nY;
1799cdf0e10cSrcweir                 nY = aLine.Y();
1800cdf0e10cSrcweir             }
1801cdf0e10cSrcweir             bool bLastLine = false;
1802cdf0e10cSrcweir             if( nY < nTop && !aLine.GetNext() )
1803cdf0e10cSrcweir             {
1804cdf0e10cSrcweir                 bLastLine = true;
1805cdf0e10cSrcweir                 nY += aLine.GetLineHeight();
1806cdf0e10cSrcweir             }
1807cdf0e10cSrcweir             do // check the lines for overlapping
1808cdf0e10cSrcweir             {
1809cdf0e10cSrcweir                 if( nLastY < nTop ) // if the last line was above rectangle
1810cdf0e10cSrcweir                     nLastY = nTop;
1811cdf0e10cSrcweir                 if( nY > nBottom ) // if the current line leaves the rectangle
1812cdf0e10cSrcweir                     nY = nBottom;
1813cdf0e10cSrcweir                 if( nY >= nLastY ) // gotcha: overlapping
1814cdf0e10cSrcweir                 {
1815cdf0e10cSrcweir                     nLastY += nY;
1816cdf0e10cSrcweir                     nLastY /= 2;
1817cdf0e10cSrcweir                     if( bVert )
1818cdf0e10cSrcweir                     {
1819cdf0e10cSrcweir                         aPoint.X() = nLastY;
1820cdf0e10cSrcweir                         aPoint.Y() = nLeft;
1821cdf0e10cSrcweir                     }
1822cdf0e10cSrcweir                     else
1823cdf0e10cSrcweir                     {
1824cdf0e10cSrcweir                         aPoint.X() = nLeft;
1825cdf0e10cSrcweir                         aPoint.Y() = nLastY;
1826cdf0e10cSrcweir                     }
1827cdf0e10cSrcweir                     // Looking for the position of the left border of the rectangle
1828cdf0e10cSrcweir                     // in this text line
1829cdf0e10cSrcweir                     SwCrsrMoveState aState( MV_UPDOWN );
1830cdf0e10cSrcweir                     if( GetCrsrOfst( &aPosL, aPoint, &aState ) )
1831cdf0e10cSrcweir                     {
1832cdf0e10cSrcweir                         if( bVert )
1833cdf0e10cSrcweir                         {
1834cdf0e10cSrcweir                             aPoint.X() = nLastY;
1835cdf0e10cSrcweir                             aPoint.Y() = nRight;
1836cdf0e10cSrcweir                         }
1837cdf0e10cSrcweir                         else
1838cdf0e10cSrcweir                         {
1839cdf0e10cSrcweir                             aPoint.X() = nRight;
1840cdf0e10cSrcweir                             aPoint.Y() = nLastY;
1841cdf0e10cSrcweir                         }
1842cdf0e10cSrcweir                         // If we get a right position and if the left position
1843cdf0e10cSrcweir                         // is not the same like the left position of the line before
1844cdf0e10cSrcweir                         // which cound happen e.g. for field portions or fly frames
1845cdf0e10cSrcweir                         // a SwPaM will be inserted with these positions
1846cdf0e10cSrcweir                         if( GetCrsrOfst( &aPosR, aPoint, &aState ) &&
1847cdf0e10cSrcweir                             nOld != aPosL.nContent.GetIndex() )
1848cdf0e10cSrcweir                         {
1849cdf0e10cSrcweir                             SwPaM *pPam = new SwPaM( aPosL, aPosR );
1850cdf0e10cSrcweir                             rSelList.insertPaM( pPam );
1851cdf0e10cSrcweir                             nOld = aPosL.nContent.GetIndex();
1852cdf0e10cSrcweir                         }
1853cdf0e10cSrcweir                     }
1854cdf0e10cSrcweir                 }
1855cdf0e10cSrcweir                 if( aLine.Next() )
1856cdf0e10cSrcweir                 {
1857cdf0e10cSrcweir                     nLastY = nY;
1858cdf0e10cSrcweir                     nY = aLine.Y();
1859cdf0e10cSrcweir                 }
1860cdf0e10cSrcweir                 else if( !bLastLine )
1861cdf0e10cSrcweir                 {
1862cdf0e10cSrcweir                     bLastLine = true;
1863cdf0e10cSrcweir                     nLastY = nY;
1864cdf0e10cSrcweir                     nY += aLine.GetLineHeight();
1865cdf0e10cSrcweir                 }
1866cdf0e10cSrcweir                 else
1867cdf0e10cSrcweir                     break;
1868cdf0e10cSrcweir             }while( nLastY < nBottom );
1869cdf0e10cSrcweir         }
1870cdf0e10cSrcweir     }
1871cdf0e10cSrcweir     if( GetDrawObjs() )
1872cdf0e10cSrcweir     {
1873cdf0e10cSrcweir         const SwSortedObjs &rObjs = *GetDrawObjs();
1874cdf0e10cSrcweir         for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
1875cdf0e10cSrcweir         {
1876cdf0e10cSrcweir             const SwAnchoredObject* pAnchoredObj = rObjs[i];
1877cdf0e10cSrcweir             if( !pAnchoredObj->ISA(SwFlyFrm) )
1878cdf0e10cSrcweir                 continue;
1879cdf0e10cSrcweir             const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
1880cdf0e10cSrcweir             if( pFly->IsFlyInCntFrm() && pFly->FillSelection( rSelList, rRect ) )
1881cdf0e10cSrcweir                 bRet = true;
1882cdf0e10cSrcweir         }
1883cdf0e10cSrcweir     }
1884cdf0e10cSrcweir     return bRet;
1885cdf0e10cSrcweir }
1886cdf0e10cSrcweir 
1887