1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_editeng.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include <vcl/wrkwin.hxx>
28*b1cdbd2cSJim Jagielski #include <vcl/dialog.hxx>
29*b1cdbd2cSJim Jagielski #include <vcl/msgbox.hxx>
30*b1cdbd2cSJim Jagielski #include <vcl/svapp.hxx>
31*b1cdbd2cSJim Jagielski 
32*b1cdbd2cSJim Jagielski #include <editeng/lspcitem.hxx>
33*b1cdbd2cSJim Jagielski #include <editeng/flditem.hxx>
34*b1cdbd2cSJim Jagielski #include <impedit.hxx>
35*b1cdbd2cSJim Jagielski #include <editeng/editeng.hxx>
36*b1cdbd2cSJim Jagielski #include <editeng/editview.hxx>
37*b1cdbd2cSJim Jagielski #include <editdbg.hxx>
38*b1cdbd2cSJim Jagielski #include <eerdll2.hxx>
39*b1cdbd2cSJim Jagielski #include <editeng/eerdll.hxx>
40*b1cdbd2cSJim Jagielski #include <edtspell.hxx>
41*b1cdbd2cSJim Jagielski #include <eeobj.hxx>
42*b1cdbd2cSJim Jagielski #include <editeng/txtrange.hxx>
43*b1cdbd2cSJim Jagielski #include <svl/urlbmk.hxx>
44*b1cdbd2cSJim Jagielski #include <svtools/colorcfg.hxx>
45*b1cdbd2cSJim Jagielski #include <svl/ctloptions.hxx>
46*b1cdbd2cSJim Jagielski #include <editeng/acorrcfg.hxx>
47*b1cdbd2cSJim Jagielski #include <editeng/fhgtitem.hxx>
48*b1cdbd2cSJim Jagielski #include <editeng/lrspitem.hxx>
49*b1cdbd2cSJim Jagielski #include <editeng/ulspitem.hxx>
50*b1cdbd2cSJim Jagielski #include <editeng/wghtitem.hxx>
51*b1cdbd2cSJim Jagielski #include <editeng/postitem.hxx>
52*b1cdbd2cSJim Jagielski #include <editeng/udlnitem.hxx>
53*b1cdbd2cSJim Jagielski #include <editeng/adjitem.hxx>
54*b1cdbd2cSJim Jagielski #include <editeng/scripttypeitem.hxx>
55*b1cdbd2cSJim Jagielski #include <editeng/frmdiritem.hxx>
56*b1cdbd2cSJim Jagielski #include <editeng/fontitem.hxx>
57*b1cdbd2cSJim Jagielski #include <vcl/cmdevt.h>
58*b1cdbd2cSJim Jagielski 
59*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
60*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/WordType.hpp>
61*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/ScriptType.hpp>
62*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/Locale.hpp>
63*b1cdbd2cSJim Jagielski #include <com/sun/star/text/CharacterCompressionType.hpp>
64*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
65*b1cdbd2cSJim Jagielski 
66*b1cdbd2cSJim Jagielski #include <comphelper/processfactory.hxx>
67*b1cdbd2cSJim Jagielski 
68*b1cdbd2cSJim Jagielski #include <sot/formats.hxx>
69*b1cdbd2cSJim Jagielski 
70*b1cdbd2cSJim Jagielski #include <unicode/ubidi.h>
71*b1cdbd2cSJim Jagielski 
72*b1cdbd2cSJim Jagielski using namespace ::com::sun::star;
73*b1cdbd2cSJim Jagielski 
lcl_CalcExtraSpace(ParaPortion *,const SvxLineSpacingItem & rLSItem)74*b1cdbd2cSJim Jagielski sal_uInt16 lcl_CalcExtraSpace( ParaPortion*, const SvxLineSpacingItem& rLSItem )
75*b1cdbd2cSJim Jagielski {
76*b1cdbd2cSJim Jagielski 	sal_uInt16 nExtra = 0;
77*b1cdbd2cSJim Jagielski 	/* if ( ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
78*b1cdbd2cSJim Jagielski 			&& ( rLSItem.GetPropLineSpace() != 100 ) )
79*b1cdbd2cSJim Jagielski 	{
80*b1cdbd2cSJim Jagielski 		// sal_uLong nH = pPortion->GetNode()->GetCharAttribs().GetDefFont().GetSize().Height();
81*b1cdbd2cSJim Jagielski 		sal_uLong nH = pPortion->GetLines().GetObject( 0 )->GetHeight();
82*b1cdbd2cSJim Jagielski 		long n = nH * rLSItem.GetPropLineSpace();
83*b1cdbd2cSJim Jagielski 		n /= 100;
84*b1cdbd2cSJim Jagielski 		n -= nH;	// nur den Abstand
85*b1cdbd2cSJim Jagielski 		if ( n > 0 )
86*b1cdbd2cSJim Jagielski 			nExtra = (sal_uInt16)n;
87*b1cdbd2cSJim Jagielski 	}
88*b1cdbd2cSJim Jagielski 	else */
89*b1cdbd2cSJim Jagielski 	if ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
90*b1cdbd2cSJim Jagielski 	{
91*b1cdbd2cSJim Jagielski 		nExtra = rLSItem.GetInterLineSpace();
92*b1cdbd2cSJim Jagielski 	}
93*b1cdbd2cSJim Jagielski 
94*b1cdbd2cSJim Jagielski 	return nExtra;
95*b1cdbd2cSJim Jagielski }
96*b1cdbd2cSJim Jagielski 
97*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------
98*b1cdbd2cSJim Jagielski //	class ImpEditEngine
99*b1cdbd2cSJim Jagielski //	----------------------------------------------------------------------
100*b1cdbd2cSJim Jagielski 
ImpEditEngine(EditEngine * pEE,SfxItemPool * pItemPool)101*b1cdbd2cSJim Jagielski ImpEditEngine::ImpEditEngine( EditEngine* pEE, SfxItemPool* pItemPool ) :
102*b1cdbd2cSJim Jagielski 	aPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
103*b1cdbd2cSJim Jagielski 	aMinAutoPaperSize( 0x0, 0x0 ),
104*b1cdbd2cSJim Jagielski 	aMaxAutoPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
105*b1cdbd2cSJim Jagielski 	aEditDoc( pItemPool ),
106*b1cdbd2cSJim Jagielski 	aWordDelimiters( RTL_CONSTASCII_USTRINGPARAM( "  .,;:-'`'?!_=\"{}()[]\0xFF" ) ),
107*b1cdbd2cSJim Jagielski 	aGroupChars( RTL_CONSTASCII_USTRINGPARAM( "{}()[]" ) )
108*b1cdbd2cSJim Jagielski {
109*b1cdbd2cSJim Jagielski 	pEditEngine 		= pEE;
110*b1cdbd2cSJim Jagielski 	pRefDev 			= NULL;
111*b1cdbd2cSJim Jagielski 	pVirtDev 			= NULL;
112*b1cdbd2cSJim Jagielski 	pEmptyItemSet 		= NULL;
113*b1cdbd2cSJim Jagielski 	pActiveView 		= NULL;
114*b1cdbd2cSJim Jagielski 	pSpellInfo 			= NULL;
115*b1cdbd2cSJim Jagielski     pConvInfo           = NULL;
116*b1cdbd2cSJim Jagielski 	pTextObjectPool 	= NULL;
117*b1cdbd2cSJim Jagielski 	mpIMEInfos			= NULL;
118*b1cdbd2cSJim Jagielski 	pStylePool 			= NULL;
119*b1cdbd2cSJim Jagielski 	pUndoManager 		= NULL;
120*b1cdbd2cSJim Jagielski 	pUndoMarkSelection	= NULL;
121*b1cdbd2cSJim Jagielski 	pTextRanger			= NULL;
122*b1cdbd2cSJim Jagielski     pColorConfig        = NULL;
123*b1cdbd2cSJim Jagielski     pCTLOptions         = NULL;
124*b1cdbd2cSJim Jagielski 
125*b1cdbd2cSJim Jagielski 	nCurTextHeight 		= 0;
126*b1cdbd2cSJim Jagielski     nBlockNotifications = 0;
127*b1cdbd2cSJim Jagielski 	nBigTextObjectStart	= 20;
128*b1cdbd2cSJim Jagielski 
129*b1cdbd2cSJim Jagielski 	nStretchX			= 100;
130*b1cdbd2cSJim Jagielski 	nStretchY			= 100;
131*b1cdbd2cSJim Jagielski 
132*b1cdbd2cSJim Jagielski 	bInSelection 		= sal_False;
133*b1cdbd2cSJim Jagielski 	bOwnerOfRefDev 		= sal_False;
134*b1cdbd2cSJim Jagielski 	bDowning 			= sal_False;
135*b1cdbd2cSJim Jagielski 	bIsInUndo 			= sal_False;
136*b1cdbd2cSJim Jagielski 	bIsFormatting 		= sal_False;
137*b1cdbd2cSJim Jagielski 	bFormatted			= sal_False;
138*b1cdbd2cSJim Jagielski 	bUpdate 			= sal_True;
139*b1cdbd2cSJim Jagielski 	bUpdateForAcc		= TRUE;
140*b1cdbd2cSJim Jagielski     bUseAutoColor       = sal_True;
141*b1cdbd2cSJim Jagielski     bForceAutoColor     = sal_False;
142*b1cdbd2cSJim Jagielski     bAddExtLeading      = sal_False;
143*b1cdbd2cSJim Jagielski 	bUndoEnabled 		= sal_True;
144*b1cdbd2cSJim Jagielski 	bCallParaInsertedOrDeleted = sal_False;
145*b1cdbd2cSJim Jagielski     bImpConvertFirstCall= sal_False;
146*b1cdbd2cSJim Jagielski     bFirstWordCapitalization    = sal_True;
147*b1cdbd2cSJim Jagielski 
148*b1cdbd2cSJim Jagielski 	eDefLanguage		= LANGUAGE_DONTKNOW;
149*b1cdbd2cSJim Jagielski 	maBackgroundColor	= COL_AUTO;
150*b1cdbd2cSJim Jagielski 
151*b1cdbd2cSJim Jagielski     nAsianCompressionMode = text::CharacterCompressionType::NONE;
152*b1cdbd2cSJim Jagielski 	bKernAsianPunctuation = sal_False;
153*b1cdbd2cSJim Jagielski 
154*b1cdbd2cSJim Jagielski     eDefaultHorizontalTextDirection = EE_HTEXTDIR_DEFAULT;
155*b1cdbd2cSJim Jagielski 
156*b1cdbd2cSJim Jagielski 
157*b1cdbd2cSJim Jagielski 	aStatus.GetControlWord() =	EE_CNTRL_USECHARATTRIBS | EE_CNTRL_DOIDLEFORMAT |
158*b1cdbd2cSJim Jagielski 								EE_CNTRL_PASTESPECIAL | EE_CNTRL_UNDOATTRIBS |
159*b1cdbd2cSJim Jagielski 								EE_CNTRL_ALLOWBIGOBJS | EE_CNTRL_RTFSTYLESHEETS |
160*b1cdbd2cSJim Jagielski 								EE_CNTRL_FORMAT100;
161*b1cdbd2cSJim Jagielski 
162*b1cdbd2cSJim Jagielski 	aSelEngine.SetFunctionSet( &aSelFuncSet );
163*b1cdbd2cSJim Jagielski 
164*b1cdbd2cSJim Jagielski 	aStatusTimer.SetTimeout( 200 );
165*b1cdbd2cSJim Jagielski 	aStatusTimer.SetTimeoutHdl( LINK( this, ImpEditEngine, StatusTimerHdl ) );
166*b1cdbd2cSJim Jagielski 
167*b1cdbd2cSJim Jagielski 	aIdleFormatter.SetTimeout( 5 );
168*b1cdbd2cSJim Jagielski 	aIdleFormatter.SetTimeoutHdl( LINK( this, ImpEditEngine, IdleFormatHdl ) );
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski 	aOnlineSpellTimer.SetTimeout( 100 );
171*b1cdbd2cSJim Jagielski 	aOnlineSpellTimer.SetTimeoutHdl( LINK( this, ImpEditEngine, OnlineSpellHdl ) );
172*b1cdbd2cSJim Jagielski 
173*b1cdbd2cSJim Jagielski 	pRefDev 			= EE_DLL()->GetGlobalData()->GetStdRefDevice();
174*b1cdbd2cSJim Jagielski 
175*b1cdbd2cSJim Jagielski 	// Ab hier wird schon auf Daten zugegriffen!
176*b1cdbd2cSJim Jagielski 	SetRefDevice( pRefDev );
177*b1cdbd2cSJim Jagielski 	InitDoc( sal_False );
178*b1cdbd2cSJim Jagielski 
179*b1cdbd2cSJim Jagielski 	bCallParaInsertedOrDeleted = sal_True;
180*b1cdbd2cSJim Jagielski 
181*b1cdbd2cSJim Jagielski     aEditDoc.SetModifyHdl( LINK( this, ImpEditEngine, DocModified ) );
182*b1cdbd2cSJim Jagielski 
183*b1cdbd2cSJim Jagielski 	mbLastTryMerge = sal_False;
184*b1cdbd2cSJim Jagielski }
185*b1cdbd2cSJim Jagielski 
~ImpEditEngine()186*b1cdbd2cSJim Jagielski ImpEditEngine::~ImpEditEngine()
187*b1cdbd2cSJim Jagielski {
188*b1cdbd2cSJim Jagielski 	aStatusTimer.Stop();
189*b1cdbd2cSJim Jagielski 	aOnlineSpellTimer.Stop();
190*b1cdbd2cSJim Jagielski 	aIdleFormatter.Stop();
191*b1cdbd2cSJim Jagielski 
192*b1cdbd2cSJim Jagielski 	// das Zerstoeren von Vorlagen kann sonst unnoetiges Formatieren ausloesen,
193*b1cdbd2cSJim Jagielski 	// wenn eine Parent-Vorlage zerstoert wird.
194*b1cdbd2cSJim Jagielski 	// Und das nach dem Zerstoeren der Daten!
195*b1cdbd2cSJim Jagielski 	bDowning = sal_True;
196*b1cdbd2cSJim Jagielski 	SetUpdateMode( sal_False );
197*b1cdbd2cSJim Jagielski 
198*b1cdbd2cSJim Jagielski 	delete pVirtDev;
199*b1cdbd2cSJim Jagielski 	delete pEmptyItemSet;
200*b1cdbd2cSJim Jagielski 	delete pUndoManager;
201*b1cdbd2cSJim Jagielski 	delete pTextRanger;
202*b1cdbd2cSJim Jagielski 	delete mpIMEInfos;
203*b1cdbd2cSJim Jagielski     delete pColorConfig;
204*b1cdbd2cSJim Jagielski     delete pCTLOptions;
205*b1cdbd2cSJim Jagielski 	if ( bOwnerOfRefDev )
206*b1cdbd2cSJim Jagielski 		delete pRefDev;
207*b1cdbd2cSJim Jagielski     delete pSpellInfo;
208*b1cdbd2cSJim Jagielski }
209*b1cdbd2cSJim Jagielski 
SetRefDevice(OutputDevice * pRef)210*b1cdbd2cSJim Jagielski void ImpEditEngine::SetRefDevice( OutputDevice* pRef )
211*b1cdbd2cSJim Jagielski {
212*b1cdbd2cSJim Jagielski 	if ( bOwnerOfRefDev )
213*b1cdbd2cSJim Jagielski 		delete pRefDev;
214*b1cdbd2cSJim Jagielski 
215*b1cdbd2cSJim Jagielski 	pRefDev = pRef;
216*b1cdbd2cSJim Jagielski 	bOwnerOfRefDev = sal_False;
217*b1cdbd2cSJim Jagielski 
218*b1cdbd2cSJim Jagielski 	if ( !pRef )
219*b1cdbd2cSJim Jagielski 		pRefDev = EE_DLL()->GetGlobalData()->GetStdRefDevice();
220*b1cdbd2cSJim Jagielski 
221*b1cdbd2cSJim Jagielski 	nOnePixelInRef = (sal_uInt16)pRefDev->PixelToLogic( Size( 1, 0 ) ).Width();
222*b1cdbd2cSJim Jagielski 
223*b1cdbd2cSJim Jagielski 	if ( IsFormatted() )
224*b1cdbd2cSJim Jagielski 	{
225*b1cdbd2cSJim Jagielski 		FormatFullDoc();
226*b1cdbd2cSJim Jagielski 		UpdateViews( (EditView*) 0);
227*b1cdbd2cSJim Jagielski 	}
228*b1cdbd2cSJim Jagielski }
229*b1cdbd2cSJim Jagielski 
SetRefMapMode(const MapMode & rMapMode)230*b1cdbd2cSJim Jagielski void ImpEditEngine::SetRefMapMode( const MapMode& rMapMode )
231*b1cdbd2cSJim Jagielski {
232*b1cdbd2cSJim Jagielski 	if ( GetRefDevice()->GetMapMode() == rMapMode )
233*b1cdbd2cSJim Jagielski 		return;
234*b1cdbd2cSJim Jagielski 
235*b1cdbd2cSJim Jagielski 	// Wenn RefDev == GlobalRefDev => eigenes anlegen!
236*b1cdbd2cSJim Jagielski 	if ( !bOwnerOfRefDev && ( pRefDev == EE_DLL()->GetGlobalData()->GetStdRefDevice() ) )
237*b1cdbd2cSJim Jagielski 	{
238*b1cdbd2cSJim Jagielski 		pRefDev = new VirtualDevice;
239*b1cdbd2cSJim Jagielski 		pRefDev->SetMapMode( MAP_TWIP );
240*b1cdbd2cSJim Jagielski 		SetRefDevice( pRefDev );
241*b1cdbd2cSJim Jagielski 		bOwnerOfRefDev = sal_True;
242*b1cdbd2cSJim Jagielski 	}
243*b1cdbd2cSJim Jagielski 	pRefDev->SetMapMode( rMapMode );
244*b1cdbd2cSJim Jagielski 	nOnePixelInRef = (sal_uInt16)pRefDev->PixelToLogic( Size( 1, 0 ) ).Width();
245*b1cdbd2cSJim Jagielski 	if ( IsFormatted() )
246*b1cdbd2cSJim Jagielski 	{
247*b1cdbd2cSJim Jagielski 		FormatFullDoc();
248*b1cdbd2cSJim Jagielski 		UpdateViews( (EditView*) 0);
249*b1cdbd2cSJim Jagielski 	}
250*b1cdbd2cSJim Jagielski }
251*b1cdbd2cSJim Jagielski 
InitDoc(sal_Bool bKeepParaAttribs)252*b1cdbd2cSJim Jagielski void ImpEditEngine::InitDoc( sal_Bool bKeepParaAttribs )
253*b1cdbd2cSJim Jagielski {
254*b1cdbd2cSJim Jagielski 	sal_uInt16 nParas = aEditDoc.Count();
255*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 n = bKeepParaAttribs ? 1 : 0; n < nParas; n++ )
256*b1cdbd2cSJim Jagielski 	{
257*b1cdbd2cSJim Jagielski 		if ( aEditDoc[n]->GetStyleSheet() )
258*b1cdbd2cSJim Jagielski 			EndListening( *aEditDoc[n]->GetStyleSheet(), sal_False );
259*b1cdbd2cSJim Jagielski 	}
260*b1cdbd2cSJim Jagielski 
261*b1cdbd2cSJim Jagielski 	if ( bKeepParaAttribs )
262*b1cdbd2cSJim Jagielski 		aEditDoc.RemoveText();
263*b1cdbd2cSJim Jagielski 	else
264*b1cdbd2cSJim Jagielski 		aEditDoc.Clear();
265*b1cdbd2cSJim Jagielski 
266*b1cdbd2cSJim Jagielski 	GetParaPortions().Reset();
267*b1cdbd2cSJim Jagielski 
268*b1cdbd2cSJim Jagielski 	ParaPortion* pIniPortion = new ParaPortion( aEditDoc[0] );
269*b1cdbd2cSJim Jagielski 	GetParaPortions().Insert( pIniPortion, 0 );
270*b1cdbd2cSJim Jagielski 
271*b1cdbd2cSJim Jagielski 	bFormatted = sal_False;
272*b1cdbd2cSJim Jagielski 
273*b1cdbd2cSJim Jagielski 	if ( IsCallParaInsertedOrDeleted() )
274*b1cdbd2cSJim Jagielski 	{
275*b1cdbd2cSJim Jagielski 		GetEditEnginePtr()->ParagraphDeleted( EE_PARA_ALL );
276*b1cdbd2cSJim Jagielski 		GetEditEnginePtr()->ParagraphInserted( 0 );
277*b1cdbd2cSJim Jagielski 	}
278*b1cdbd2cSJim Jagielski 
279*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
280*b1cdbd2cSJim Jagielski 	if ( GetStatus().DoOnlineSpelling() )
281*b1cdbd2cSJim Jagielski 		aEditDoc.GetObject( 0 )->CreateWrongList();
282*b1cdbd2cSJim Jagielski #endif // !SVX_LIGHT
283*b1cdbd2cSJim Jagielski }
284*b1cdbd2cSJim Jagielski 
DeleteSelected(EditSelection aSel)285*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::DeleteSelected( EditSelection aSel )
286*b1cdbd2cSJim Jagielski {
287*b1cdbd2cSJim Jagielski 	EditPaM aPaM ( ImpDeleteSelection( aSel ) );
288*b1cdbd2cSJim Jagielski 	return aPaM;
289*b1cdbd2cSJim Jagielski }
290*b1cdbd2cSJim Jagielski 
GetSelected(const EditSelection & rSel,const LineEnd eEnd) const291*b1cdbd2cSJim Jagielski XubString ImpEditEngine::GetSelected( const EditSelection& rSel, const LineEnd eEnd  ) const
292*b1cdbd2cSJim Jagielski {
293*b1cdbd2cSJim Jagielski 	XubString aText;
294*b1cdbd2cSJim Jagielski 	if ( !rSel.HasRange() )
295*b1cdbd2cSJim Jagielski 		return aText;
296*b1cdbd2cSJim Jagielski 
297*b1cdbd2cSJim Jagielski 	String aSep = EditDoc::GetSepStr( eEnd );
298*b1cdbd2cSJim Jagielski 
299*b1cdbd2cSJim Jagielski 	EditSelection aSel( rSel );
300*b1cdbd2cSJim Jagielski 	aSel.Adjust( aEditDoc );
301*b1cdbd2cSJim Jagielski 
302*b1cdbd2cSJim Jagielski 	ContentNode* pStartNode = aSel.Min().GetNode();
303*b1cdbd2cSJim Jagielski 	ContentNode* pEndNode = aSel.Max().GetNode();
304*b1cdbd2cSJim Jagielski 	sal_uInt16 nStartNode = aEditDoc.GetPos( pStartNode );
305*b1cdbd2cSJim Jagielski 	sal_uInt16 nEndNode = aEditDoc.GetPos( pEndNode );
306*b1cdbd2cSJim Jagielski 
307*b1cdbd2cSJim Jagielski 	DBG_ASSERT( nStartNode <= nEndNode, "Selektion nicht sortiert ?" );
308*b1cdbd2cSJim Jagielski 
309*b1cdbd2cSJim Jagielski 	// ueber die Absaetze iterieren...
310*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++	)
311*b1cdbd2cSJim Jagielski 	{
312*b1cdbd2cSJim Jagielski 		DBG_ASSERT( aEditDoc.SaveGetObject( nNode ), "Node nicht gefunden: GetSelected" );
313*b1cdbd2cSJim Jagielski 		ContentNode* pNode = aEditDoc.GetObject( nNode );
314*b1cdbd2cSJim Jagielski 
315*b1cdbd2cSJim Jagielski 		xub_StrLen nStartPos = 0;
316*b1cdbd2cSJim Jagielski 		xub_StrLen nEndPos = pNode->Len();
317*b1cdbd2cSJim Jagielski 		if ( nNode == nStartNode )
318*b1cdbd2cSJim Jagielski 			nStartPos = aSel.Min().GetIndex();
319*b1cdbd2cSJim Jagielski 		if ( nNode == nEndNode ) // kann auch == nStart sein!
320*b1cdbd2cSJim Jagielski 			nEndPos = aSel.Max().GetIndex();
321*b1cdbd2cSJim Jagielski 
322*b1cdbd2cSJim Jagielski 		aText += aEditDoc.GetParaAsString( pNode, nStartPos, nEndPos );
323*b1cdbd2cSJim Jagielski 		if ( nNode < nEndNode )
324*b1cdbd2cSJim Jagielski 			aText += aSep;
325*b1cdbd2cSJim Jagielski 	}
326*b1cdbd2cSJim Jagielski 	return aText;
327*b1cdbd2cSJim Jagielski }
328*b1cdbd2cSJim Jagielski 
MouseButtonDown(const MouseEvent & rMEvt,EditView * pView)329*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::MouseButtonDown( const MouseEvent& rMEvt, EditView* pView )
330*b1cdbd2cSJim Jagielski {
331*b1cdbd2cSJim Jagielski 	GetSelEngine().SetCurView( pView );
332*b1cdbd2cSJim Jagielski 	SetActiveView( pView );
333*b1cdbd2cSJim Jagielski 
334*b1cdbd2cSJim Jagielski 	if ( GetAutoCompleteText().Len() )
335*b1cdbd2cSJim Jagielski 		SetAutoCompleteText( String(), sal_True );
336*b1cdbd2cSJim Jagielski 
337*b1cdbd2cSJim Jagielski 	GetSelEngine().SelMouseButtonDown( rMEvt );
338*b1cdbd2cSJim Jagielski 	// Sonderbehandlungen
339*b1cdbd2cSJim Jagielski 	EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
340*b1cdbd2cSJim Jagielski 	if ( !rMEvt.IsShift() )
341*b1cdbd2cSJim Jagielski 	{
342*b1cdbd2cSJim Jagielski 		if ( rMEvt.GetClicks() == 2 )
343*b1cdbd2cSJim Jagielski 		{
344*b1cdbd2cSJim Jagielski 			// damit die SelectionEngine weiss, dass Anker.
345*b1cdbd2cSJim Jagielski 			aSelEngine.CursorPosChanging( sal_True, sal_False );
346*b1cdbd2cSJim Jagielski 
347*b1cdbd2cSJim Jagielski 			EditSelection aNewSelection( SelectWord( aCurSel ) );
348*b1cdbd2cSJim Jagielski 			pView->pImpEditView->DrawSelection();
349*b1cdbd2cSJim Jagielski 			pView->pImpEditView->SetEditSelection( aNewSelection );
350*b1cdbd2cSJim Jagielski 			pView->pImpEditView->DrawSelection();
351*b1cdbd2cSJim Jagielski 			pView->ShowCursor( sal_True, sal_True );
352*b1cdbd2cSJim Jagielski 		}
353*b1cdbd2cSJim Jagielski 		else if ( rMEvt.GetClicks() == 3 )
354*b1cdbd2cSJim Jagielski 		{
355*b1cdbd2cSJim Jagielski 			// damit die SelectionEngine weiss, dass Anker.
356*b1cdbd2cSJim Jagielski 			aSelEngine.CursorPosChanging( sal_True, sal_False );
357*b1cdbd2cSJim Jagielski 
358*b1cdbd2cSJim Jagielski 			EditSelection aNewSelection( aCurSel );
359*b1cdbd2cSJim Jagielski 			aNewSelection.Min().SetIndex( 0 );
360*b1cdbd2cSJim Jagielski 			aNewSelection.Max().SetIndex( aCurSel.Min().GetNode()->Len() );
361*b1cdbd2cSJim Jagielski 			pView->pImpEditView->DrawSelection();
362*b1cdbd2cSJim Jagielski 			pView->pImpEditView->SetEditSelection( aNewSelection );
363*b1cdbd2cSJim Jagielski 			pView->pImpEditView->DrawSelection();
364*b1cdbd2cSJim Jagielski 			pView->ShowCursor( sal_True, sal_True );
365*b1cdbd2cSJim Jagielski 		}
366*b1cdbd2cSJim Jagielski 	}
367*b1cdbd2cSJim Jagielski 	return sal_True;
368*b1cdbd2cSJim Jagielski }
369*b1cdbd2cSJim Jagielski 
Command(const CommandEvent & rCEvt,EditView * pView)370*b1cdbd2cSJim Jagielski void ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView )
371*b1cdbd2cSJim Jagielski {
372*b1cdbd2cSJim Jagielski 	GetSelEngine().SetCurView( pView );
373*b1cdbd2cSJim Jagielski 	SetActiveView( pView );
374*b1cdbd2cSJim Jagielski     if ( rCEvt.GetCommand() == COMMAND_VOICE )
375*b1cdbd2cSJim Jagielski 	{
376*b1cdbd2cSJim Jagielski 		const CommandVoiceData* pData = rCEvt.GetVoiceData();
377*b1cdbd2cSJim Jagielski 		if ( pData->GetType() == VOICECOMMANDTYPE_DICTATION )
378*b1cdbd2cSJim Jagielski 		{
379*b1cdbd2cSJim Jagielski 			// Funktionen auf KeyEvents umbiegen, wenn keine entsprechende
380*b1cdbd2cSJim Jagielski 			// Methode an EditView/EditEngine, damit Undo konsistent bleibt.
381*b1cdbd2cSJim Jagielski 
382*b1cdbd2cSJim Jagielski 			SfxPoolItem* pNewAttr = NULL;
383*b1cdbd2cSJim Jagielski 
384*b1cdbd2cSJim Jagielski 			switch ( pData->GetCommand() )
385*b1cdbd2cSJim Jagielski 			{
386*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_UNKNOWN:
387*b1cdbd2cSJim Jagielski 				{
388*b1cdbd2cSJim Jagielski 					pView->InsertText( pData->GetText() );
389*b1cdbd2cSJim Jagielski 				}
390*b1cdbd2cSJim Jagielski 				break;
391*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_NEWPARAGRAPH:
392*b1cdbd2cSJim Jagielski 				{
393*b1cdbd2cSJim Jagielski 					pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_RETURN, 0 ) ) );
394*b1cdbd2cSJim Jagielski 				}
395*b1cdbd2cSJim Jagielski 				break;
396*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_NEWLINE:
397*b1cdbd2cSJim Jagielski 				{
398*b1cdbd2cSJim Jagielski 					pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_RETURN, KEY_SHIFT ) ) );
399*b1cdbd2cSJim Jagielski 				}
400*b1cdbd2cSJim Jagielski 				break;
401*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_TAB:
402*b1cdbd2cSJim Jagielski 				{
403*b1cdbd2cSJim Jagielski 					pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_TAB, 0 ) ) );
404*b1cdbd2cSJim Jagielski 				}
405*b1cdbd2cSJim Jagielski 				break;
406*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_LEFT:
407*b1cdbd2cSJim Jagielski 				{
408*b1cdbd2cSJim Jagielski 					pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1  ) ) );
409*b1cdbd2cSJim Jagielski 				}
410*b1cdbd2cSJim Jagielski 				break;
411*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_RIGHT:
412*b1cdbd2cSJim Jagielski 				{
413*b1cdbd2cSJim Jagielski 					pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_RIGHT, KEY_MOD1  ) ) );
414*b1cdbd2cSJim Jagielski 				}
415*b1cdbd2cSJim Jagielski 				break;
416*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_UP:
417*b1cdbd2cSJim Jagielski 				{
418*b1cdbd2cSJim Jagielski 					pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_UP, 0 ) ) );
419*b1cdbd2cSJim Jagielski 				}
420*b1cdbd2cSJim Jagielski 				break;
421*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_DOWN:
422*b1cdbd2cSJim Jagielski 				{
423*b1cdbd2cSJim Jagielski 					pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_UP, 0 ) ) );
424*b1cdbd2cSJim Jagielski 				}
425*b1cdbd2cSJim Jagielski 				break;
426*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_UNDO:
427*b1cdbd2cSJim Jagielski 				{
428*b1cdbd2cSJim Jagielski 					pView->Undo();
429*b1cdbd2cSJim Jagielski 				}
430*b1cdbd2cSJim Jagielski 				break;
431*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_DEL:
432*b1cdbd2cSJim Jagielski 				{
433*b1cdbd2cSJim Jagielski 					pView->PostKeyEvent( KeyEvent( 0, KeyCode( KEY_LEFT, KEY_MOD1|KEY_SHIFT  ) ) );
434*b1cdbd2cSJim Jagielski 					pView->DeleteSelected();
435*b1cdbd2cSJim Jagielski 				}
436*b1cdbd2cSJim Jagielski 				break;
437*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_BOLD_ON:
438*b1cdbd2cSJim Jagielski 				{
439*b1cdbd2cSJim Jagielski 					pNewAttr = new SvxWeightItem( WEIGHT_BOLD, EE_CHAR_WEIGHT );
440*b1cdbd2cSJim Jagielski 				}
441*b1cdbd2cSJim Jagielski 				break;
442*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_BOLD_OFF:
443*b1cdbd2cSJim Jagielski 				{
444*b1cdbd2cSJim Jagielski 					pNewAttr = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT );
445*b1cdbd2cSJim Jagielski 				}
446*b1cdbd2cSJim Jagielski 				break;
447*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_ITALIC_ON:
448*b1cdbd2cSJim Jagielski 				{
449*b1cdbd2cSJim Jagielski 					pNewAttr = new SvxPostureItem( ITALIC_NORMAL, EE_CHAR_ITALIC );
450*b1cdbd2cSJim Jagielski 				}
451*b1cdbd2cSJim Jagielski 				break;
452*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_ITALIC_OFF:
453*b1cdbd2cSJim Jagielski 				{
454*b1cdbd2cSJim Jagielski 					pNewAttr = new SvxPostureItem( ITALIC_NORMAL, EE_CHAR_ITALIC );
455*b1cdbd2cSJim Jagielski 				}
456*b1cdbd2cSJim Jagielski 				break;
457*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_UNDERLINE_ON:
458*b1cdbd2cSJim Jagielski 				{
459*b1cdbd2cSJim Jagielski 					pNewAttr = new SvxUnderlineItem( UNDERLINE_SINGLE, EE_CHAR_UNDERLINE );
460*b1cdbd2cSJim Jagielski 				}
461*b1cdbd2cSJim Jagielski 				break;
462*b1cdbd2cSJim Jagielski 				case DICTATIONCOMMAND_UNDERLINE_OFF:
463*b1cdbd2cSJim Jagielski 				{
464*b1cdbd2cSJim Jagielski 					pNewAttr = new SvxUnderlineItem( UNDERLINE_NONE, EE_CHAR_UNDERLINE );
465*b1cdbd2cSJim Jagielski 				}
466*b1cdbd2cSJim Jagielski 				break;
467*b1cdbd2cSJim Jagielski 			}
468*b1cdbd2cSJim Jagielski 
469*b1cdbd2cSJim Jagielski 			if ( pNewAttr )
470*b1cdbd2cSJim Jagielski 			{
471*b1cdbd2cSJim Jagielski 				SfxItemSet aSet( GetEmptyItemSet() );
472*b1cdbd2cSJim Jagielski 				aSet.Put( *pNewAttr );
473*b1cdbd2cSJim Jagielski 				pView->SetAttribs( aSet );
474*b1cdbd2cSJim Jagielski 				delete pNewAttr;
475*b1cdbd2cSJim Jagielski 			}
476*b1cdbd2cSJim Jagielski 		}
477*b1cdbd2cSJim Jagielski 	}
478*b1cdbd2cSJim Jagielski 	else if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT )
479*b1cdbd2cSJim Jagielski 	{
480*b1cdbd2cSJim Jagielski 		pView->DeleteSelected();
481*b1cdbd2cSJim Jagielski 		delete mpIMEInfos;
482*b1cdbd2cSJim Jagielski         EditPaM aPaM = pView->GetImpEditView()->GetEditSelection().Max();
483*b1cdbd2cSJim Jagielski         String aOldTextAfterStartPos = aPaM.GetNode()->Copy( aPaM.GetIndex() );
484*b1cdbd2cSJim Jagielski         sal_uInt16 nMax = aOldTextAfterStartPos.Search( CH_FEATURE );
485*b1cdbd2cSJim Jagielski         if ( nMax != STRING_NOTFOUND )  // don't overwrite features!
486*b1cdbd2cSJim Jagielski             aOldTextAfterStartPos.Erase( nMax );
487*b1cdbd2cSJim Jagielski 	    mpIMEInfos = new ImplIMEInfos( aPaM, aOldTextAfterStartPos );
488*b1cdbd2cSJim Jagielski 		mpIMEInfos->bWasCursorOverwrite = !pView->IsInsertMode();
489*b1cdbd2cSJim Jagielski         UndoActionStart( EDITUNDO_INSERT );
490*b1cdbd2cSJim Jagielski 	}
491*b1cdbd2cSJim Jagielski 	else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
492*b1cdbd2cSJim Jagielski 	{
493*b1cdbd2cSJim Jagielski 		DBG_ASSERT( mpIMEInfos, "COMMAND_ENDEXTTEXTINPUT => Kein Start ?" );
494*b1cdbd2cSJim Jagielski 		if( mpIMEInfos )
495*b1cdbd2cSJim Jagielski 		{
496*b1cdbd2cSJim Jagielski 			// #102812# convert quotes in IME text
497*b1cdbd2cSJim Jagielski 			// works on the last input character, this is escpecially in Korean text often done
498*b1cdbd2cSJim Jagielski 			// quotes that are inside of the string are not replaced!
499*b1cdbd2cSJim Jagielski 			// Borrowed from sw: edtwin.cxx
500*b1cdbd2cSJim Jagielski 			if ( mpIMEInfos->nLen )
501*b1cdbd2cSJim Jagielski 			{
502*b1cdbd2cSJim Jagielski 				EditSelection aSel( mpIMEInfos->aPos );
503*b1cdbd2cSJim Jagielski 				aSel.Min().GetIndex() += mpIMEInfos->nLen-1;
504*b1cdbd2cSJim Jagielski 				aSel.Max().GetIndex() =
505*b1cdbd2cSJim Jagielski                     aSel.Max().GetIndex() + mpIMEInfos->nLen;
506*b1cdbd2cSJim Jagielski 				// #102812# convert quotes in IME text
507*b1cdbd2cSJim Jagielski 				// works on the last input character, this is escpecially in Korean text often done
508*b1cdbd2cSJim Jagielski 				// quotes that are inside of the string are not replaced!
509*b1cdbd2cSJim Jagielski 				const sal_Unicode nCharCode = aSel.Min().GetNode()->GetChar( aSel.Min().GetIndex() );
510*b1cdbd2cSJim Jagielski 				if ( ( GetStatus().DoAutoCorrect() ) && ( ( nCharCode == '\"' ) || ( nCharCode == '\'' ) ) )
511*b1cdbd2cSJim Jagielski 				{
512*b1cdbd2cSJim Jagielski 					aSel = DeleteSelected( aSel );
513*b1cdbd2cSJim Jagielski 					aSel = AutoCorrect( aSel, nCharCode, mpIMEInfos->bWasCursorOverwrite );
514*b1cdbd2cSJim Jagielski 					pView->pImpEditView->SetEditSelection( aSel );
515*b1cdbd2cSJim Jagielski 				}
516*b1cdbd2cSJim Jagielski 			}
517*b1cdbd2cSJim Jagielski 
518*b1cdbd2cSJim Jagielski 			ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() );
519*b1cdbd2cSJim Jagielski 			pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex(), 0 );
520*b1cdbd2cSJim Jagielski 
521*b1cdbd2cSJim Jagielski 			sal_Bool bWasCursorOverwrite = mpIMEInfos->bWasCursorOverwrite;
522*b1cdbd2cSJim Jagielski 
523*b1cdbd2cSJim Jagielski 			delete mpIMEInfos;
524*b1cdbd2cSJim Jagielski 			mpIMEInfos = NULL;
525*b1cdbd2cSJim Jagielski 
526*b1cdbd2cSJim Jagielski 			FormatAndUpdate( pView );
527*b1cdbd2cSJim Jagielski 
528*b1cdbd2cSJim Jagielski 			pView->SetInsertMode( !bWasCursorOverwrite );
529*b1cdbd2cSJim Jagielski 		}
530*b1cdbd2cSJim Jagielski         UndoActionEnd( EDITUNDO_INSERT );
531*b1cdbd2cSJim Jagielski 	}
532*b1cdbd2cSJim Jagielski 	else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT )
533*b1cdbd2cSJim Jagielski 	{
534*b1cdbd2cSJim Jagielski 		DBG_ASSERT( mpIMEInfos, "COMMAND_EXTTEXTINPUT => Kein Start ?" );
535*b1cdbd2cSJim Jagielski 		if( mpIMEInfos )
536*b1cdbd2cSJim Jagielski 		{
537*b1cdbd2cSJim Jagielski 			const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
538*b1cdbd2cSJim Jagielski 
539*b1cdbd2cSJim Jagielski 			if ( !pData->IsOnlyCursorChanged() )
540*b1cdbd2cSJim Jagielski 			{
541*b1cdbd2cSJim Jagielski 				EditSelection aSel( mpIMEInfos->aPos );
542*b1cdbd2cSJim Jagielski 				aSel.Max().GetIndex() =
543*b1cdbd2cSJim Jagielski                     aSel.Max().GetIndex() + mpIMEInfos->nLen;
544*b1cdbd2cSJim Jagielski 				aSel = DeleteSelected( aSel );
545*b1cdbd2cSJim Jagielski 				aSel = ImpInsertText( aSel, pData->GetText() );
546*b1cdbd2cSJim Jagielski 
547*b1cdbd2cSJim Jagielski                 if ( mpIMEInfos->bWasCursorOverwrite )
548*b1cdbd2cSJim Jagielski                 {
549*b1cdbd2cSJim Jagielski                     sal_uInt16 nOldIMETextLen = mpIMEInfos->nLen;
550*b1cdbd2cSJim Jagielski                     sal_uInt16 nNewIMETextLen = pData->GetText().Len();
551*b1cdbd2cSJim Jagielski 
552*b1cdbd2cSJim Jagielski                     if ( ( nOldIMETextLen > nNewIMETextLen ) &&
553*b1cdbd2cSJim Jagielski                          ( nNewIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) )
554*b1cdbd2cSJim Jagielski                     {
555*b1cdbd2cSJim Jagielski                         // restore old characters
556*b1cdbd2cSJim Jagielski                         sal_uInt16 nRestore = nOldIMETextLen - nNewIMETextLen;
557*b1cdbd2cSJim Jagielski                         EditPaM aPaM( mpIMEInfos->aPos );
558*b1cdbd2cSJim Jagielski                         aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
559*b1cdbd2cSJim Jagielski                         ImpInsertText( aPaM, mpIMEInfos->aOldTextAfterStartPos.Copy( nNewIMETextLen, nRestore ) );
560*b1cdbd2cSJim Jagielski                     }
561*b1cdbd2cSJim Jagielski                     else if ( ( nOldIMETextLen < nNewIMETextLen ) &&
562*b1cdbd2cSJim Jagielski                               ( nOldIMETextLen < mpIMEInfos->aOldTextAfterStartPos.Len() ) )
563*b1cdbd2cSJim Jagielski                     {
564*b1cdbd2cSJim Jagielski                         // overwrite
565*b1cdbd2cSJim Jagielski                         sal_uInt16 nOverwrite = nNewIMETextLen - nOldIMETextLen;
566*b1cdbd2cSJim Jagielski                         if ( ( nOldIMETextLen + nOverwrite ) > mpIMEInfos->aOldTextAfterStartPos.Len() )
567*b1cdbd2cSJim Jagielski                             nOverwrite = mpIMEInfos->aOldTextAfterStartPos.Len() - nOldIMETextLen;
568*b1cdbd2cSJim Jagielski                         DBG_ASSERT( nOverwrite && (nOverwrite < 0xFF00), "IME Overwrite?!" );
569*b1cdbd2cSJim Jagielski                         EditPaM aPaM( mpIMEInfos->aPos );
570*b1cdbd2cSJim Jagielski                         aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
571*b1cdbd2cSJim Jagielski                         EditSelection _aSel( aPaM );
572*b1cdbd2cSJim Jagielski                         _aSel.Max().GetIndex() =
573*b1cdbd2cSJim Jagielski                             _aSel.Max().GetIndex() + nOverwrite;
574*b1cdbd2cSJim Jagielski                         DeleteSelected( _aSel );
575*b1cdbd2cSJim Jagielski                     }
576*b1cdbd2cSJim Jagielski                 }
577*b1cdbd2cSJim Jagielski 				if ( pData->GetTextAttr() )
578*b1cdbd2cSJim Jagielski 				{
579*b1cdbd2cSJim Jagielski 					mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() );
580*b1cdbd2cSJim Jagielski 					mpIMEInfos->bCursor = pData->IsCursorVisible();
581*b1cdbd2cSJim Jagielski 				}
582*b1cdbd2cSJim Jagielski 				else
583*b1cdbd2cSJim Jagielski 				{
584*b1cdbd2cSJim Jagielski 					mpIMEInfos->DestroyAttribs();
585*b1cdbd2cSJim Jagielski 					mpIMEInfos->nLen = pData->GetText().Len();
586*b1cdbd2cSJim Jagielski 				}
587*b1cdbd2cSJim Jagielski 
588*b1cdbd2cSJim Jagielski 				ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() );
589*b1cdbd2cSJim Jagielski 				pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex(), 0 );
590*b1cdbd2cSJim Jagielski 				FormatAndUpdate( pView );
591*b1cdbd2cSJim Jagielski 			}
592*b1cdbd2cSJim Jagielski 
593*b1cdbd2cSJim Jagielski 			EditSelection aNewSel = EditPaM( mpIMEInfos->aPos.GetNode(), mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() );
594*b1cdbd2cSJim Jagielski 			pView->SetSelection( CreateESel( aNewSel ) );
595*b1cdbd2cSJim Jagielski 			pView->SetInsertMode( !pData->IsCursorOverwrite() );
596*b1cdbd2cSJim Jagielski 
597*b1cdbd2cSJim Jagielski 			if ( pData->IsCursorVisible() )
598*b1cdbd2cSJim Jagielski 				pView->ShowCursor();
599*b1cdbd2cSJim Jagielski 			else
600*b1cdbd2cSJim Jagielski 				pView->HideCursor();
601*b1cdbd2cSJim Jagielski 		}
602*b1cdbd2cSJim Jagielski 	}
603*b1cdbd2cSJim Jagielski 	else if ( rCEvt.GetCommand() == COMMAND_INPUTCONTEXTCHANGE )
604*b1cdbd2cSJim Jagielski 	{
605*b1cdbd2cSJim Jagielski 	}
606*b1cdbd2cSJim Jagielski 	else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS )
607*b1cdbd2cSJim Jagielski 	{
608*b1cdbd2cSJim Jagielski 		if ( mpIMEInfos && mpIMEInfos->nLen )
609*b1cdbd2cSJim Jagielski 		{
610*b1cdbd2cSJim Jagielski 			EditPaM aPaM( pView->pImpEditView->GetEditSelection().Max() );
611*b1cdbd2cSJim Jagielski 			Rectangle aR1 = PaMtoEditCursor( aPaM, 0 );
612*b1cdbd2cSJim Jagielski 
613*b1cdbd2cSJim Jagielski 			sal_uInt16 nInputEnd = mpIMEInfos->aPos.GetIndex() + mpIMEInfos->nLen;
614*b1cdbd2cSJim Jagielski 
615*b1cdbd2cSJim Jagielski 			if ( !IsFormatted() )
616*b1cdbd2cSJim Jagielski 				FormatDoc();
617*b1cdbd2cSJim Jagielski 
618*b1cdbd2cSJim Jagielski 			ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( GetEditDoc().GetPos( aPaM.GetNode() ) );
619*b1cdbd2cSJim Jagielski 			sal_uInt16 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_True );
620*b1cdbd2cSJim Jagielski 			EditLine* pLine = pParaPortion->GetLines().GetObject( nLine );
621*b1cdbd2cSJim Jagielski 			if ( pLine && ( nInputEnd > pLine->GetEnd() ) )
622*b1cdbd2cSJim Jagielski 				nInputEnd = pLine->GetEnd();
623*b1cdbd2cSJim Jagielski 			Rectangle aR2 = PaMtoEditCursor( EditPaM( aPaM.GetNode(), nInputEnd ), GETCRSR_ENDOFLINE );
624*b1cdbd2cSJim Jagielski 			Rectangle aRect = pView->GetImpEditView()->GetWindowPos( aR1 );
625*b1cdbd2cSJim Jagielski 			pView->GetWindow()->SetCursorRect( &aRect, aR2.Left()-aR1.Right() );
626*b1cdbd2cSJim Jagielski 		}
627*b1cdbd2cSJim Jagielski 		else
628*b1cdbd2cSJim Jagielski 		{
629*b1cdbd2cSJim Jagielski 			pView->GetWindow()->SetCursorRect();
630*b1cdbd2cSJim Jagielski 		}
631*b1cdbd2cSJim Jagielski 	}
632*b1cdbd2cSJim Jagielski     else if ( rCEvt.GetCommand() == COMMAND_SELECTIONCHANGE )
633*b1cdbd2cSJim Jagielski 	{
634*b1cdbd2cSJim Jagielski         const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData();
635*b1cdbd2cSJim Jagielski 
636*b1cdbd2cSJim Jagielski         ESelection aSelection = pView->GetSelection();
637*b1cdbd2cSJim Jagielski         aSelection.Adjust();
638*b1cdbd2cSJim Jagielski 
639*b1cdbd2cSJim Jagielski 	    if( pView->HasSelection() )
640*b1cdbd2cSJim Jagielski 	    {
641*b1cdbd2cSJim Jagielski 		    aSelection.nEndPos = aSelection.nStartPos;
642*b1cdbd2cSJim Jagielski 		    aSelection.nStartPos += pData->GetStart();
643*b1cdbd2cSJim Jagielski 		    aSelection.nEndPos += pData->GetEnd();
644*b1cdbd2cSJim Jagielski 	    }
645*b1cdbd2cSJim Jagielski 	    else
646*b1cdbd2cSJim Jagielski 	    {
647*b1cdbd2cSJim Jagielski 		    aSelection.nStartPos = pData->GetStart();
648*b1cdbd2cSJim Jagielski 		    aSelection.nEndPos = pData->GetEnd();
649*b1cdbd2cSJim Jagielski 	    }
650*b1cdbd2cSJim Jagielski         pView->SetSelection( aSelection );
651*b1cdbd2cSJim Jagielski 	}
652*b1cdbd2cSJim Jagielski 	else if ( rCEvt.GetCommand() == COMMAND_PREPARERECONVERSION )
653*b1cdbd2cSJim Jagielski 	{
654*b1cdbd2cSJim Jagielski 	    if ( pView->HasSelection() )
655*b1cdbd2cSJim Jagielski 	    {
656*b1cdbd2cSJim Jagielski 		    ESelection aSelection = pView->GetSelection();
657*b1cdbd2cSJim Jagielski 		    aSelection.Adjust();
658*b1cdbd2cSJim Jagielski 
659*b1cdbd2cSJim Jagielski 		    if ( aSelection.nStartPara != aSelection.nEndPara )
660*b1cdbd2cSJim Jagielski 		    {
661*b1cdbd2cSJim Jagielski 		        xub_StrLen aParaLen = pEditEngine->GetTextLen( aSelection.nStartPara );
662*b1cdbd2cSJim Jagielski 		        aSelection.nEndPara = aSelection.nStartPara;
663*b1cdbd2cSJim Jagielski 		        aSelection.nEndPos = aParaLen;
664*b1cdbd2cSJim Jagielski 		        pView->SetSelection( aSelection );
665*b1cdbd2cSJim Jagielski 		    }
666*b1cdbd2cSJim Jagielski 	    }
667*b1cdbd2cSJim Jagielski 	}
668*b1cdbd2cSJim Jagielski 
669*b1cdbd2cSJim Jagielski 	GetSelEngine().Command( rCEvt );
670*b1cdbd2cSJim Jagielski }
671*b1cdbd2cSJim Jagielski 
MouseButtonUp(const MouseEvent & rMEvt,EditView * pView)672*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::MouseButtonUp( const MouseEvent& rMEvt, EditView* pView )
673*b1cdbd2cSJim Jagielski {
674*b1cdbd2cSJim Jagielski 	GetSelEngine().SetCurView( pView );
675*b1cdbd2cSJim Jagielski 	GetSelEngine().SelMouseButtonUp( rMEvt );
676*b1cdbd2cSJim Jagielski 	bInSelection = sal_False;
677*b1cdbd2cSJim Jagielski 	// Sonderbehandlungen
678*b1cdbd2cSJim Jagielski 	EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
679*b1cdbd2cSJim Jagielski 	if ( !aCurSel.HasRange() )
680*b1cdbd2cSJim Jagielski 	{
681*b1cdbd2cSJim Jagielski 		if ( ( rMEvt.GetClicks() == 1 ) && rMEvt.IsLeft() && !rMEvt.IsMod2() )
682*b1cdbd2cSJim Jagielski 		{
683*b1cdbd2cSJim Jagielski 			const SvxFieldItem* pFld = pView->GetFieldUnderMousePointer();
684*b1cdbd2cSJim Jagielski 			if ( pFld )
685*b1cdbd2cSJim Jagielski 			{
686*b1cdbd2cSJim Jagielski 				EditPaM aPaM( aCurSel.Max() );
687*b1cdbd2cSJim Jagielski 				sal_uInt16 nPara = GetEditDoc().GetPos( aPaM.GetNode() );
688*b1cdbd2cSJim Jagielski 				GetEditEnginePtr()->FieldClicked( *pFld, nPara, aPaM.GetIndex() );
689*b1cdbd2cSJim Jagielski 			}
690*b1cdbd2cSJim Jagielski 		}
691*b1cdbd2cSJim Jagielski 	}
692*b1cdbd2cSJim Jagielski 	return sal_True;
693*b1cdbd2cSJim Jagielski }
694*b1cdbd2cSJim Jagielski 
MouseMove(const MouseEvent & rMEvt,EditView * pView)695*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::MouseMove( const MouseEvent& rMEvt, EditView* pView )
696*b1cdbd2cSJim Jagielski {
697*b1cdbd2cSJim Jagielski 	// MouseMove wird sofort nach ShowQuickHelp() gerufen!
698*b1cdbd2cSJim Jagielski //	if ( GetAutoCompleteText().Len() )
699*b1cdbd2cSJim Jagielski //		SetAutoCompleteText( String(), sal_True );
700*b1cdbd2cSJim Jagielski 	GetSelEngine().SetCurView( pView );
701*b1cdbd2cSJim Jagielski 	GetSelEngine().SelMouseMove( rMEvt );
702*b1cdbd2cSJim Jagielski 	return sal_True;
703*b1cdbd2cSJim Jagielski }
704*b1cdbd2cSJim Jagielski 
InsertText(EditSelection aSel,const XubString & rStr)705*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::InsertText( EditSelection aSel, const XubString& rStr )
706*b1cdbd2cSJim Jagielski {
707*b1cdbd2cSJim Jagielski 	EditPaM aPaM = ImpInsertText( aSel, rStr );
708*b1cdbd2cSJim Jagielski 	return aPaM;
709*b1cdbd2cSJim Jagielski }
710*b1cdbd2cSJim Jagielski 
Clear()711*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::Clear()
712*b1cdbd2cSJim Jagielski {
713*b1cdbd2cSJim Jagielski 	InitDoc( sal_False );
714*b1cdbd2cSJim Jagielski 
715*b1cdbd2cSJim Jagielski 	EditPaM aPaM = aEditDoc.GetStartPaM();
716*b1cdbd2cSJim Jagielski 	EditSelection aSel( aPaM );
717*b1cdbd2cSJim Jagielski 
718*b1cdbd2cSJim Jagielski 	nCurTextHeight = 0;
719*b1cdbd2cSJim Jagielski 
720*b1cdbd2cSJim Jagielski 	ResetUndoManager();
721*b1cdbd2cSJim Jagielski 
722*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nView = aEditViews.Count(); nView; )
723*b1cdbd2cSJim Jagielski 	{
724*b1cdbd2cSJim Jagielski 		EditView* pView = aEditViews[--nView];
725*b1cdbd2cSJim Jagielski 		DBG_CHKOBJ( pView, EditView, 0 );
726*b1cdbd2cSJim Jagielski 		pView->pImpEditView->SetEditSelection( aSel );
727*b1cdbd2cSJim Jagielski 	}
728*b1cdbd2cSJim Jagielski 
729*b1cdbd2cSJim Jagielski 	return aPaM;
730*b1cdbd2cSJim Jagielski }
731*b1cdbd2cSJim Jagielski 
RemoveText()732*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::RemoveText()
733*b1cdbd2cSJim Jagielski {
734*b1cdbd2cSJim Jagielski 	InitDoc( sal_True );
735*b1cdbd2cSJim Jagielski 
736*b1cdbd2cSJim Jagielski 	EditPaM aStartPaM = aEditDoc.GetStartPaM();
737*b1cdbd2cSJim Jagielski 	EditSelection aEmptySel( aStartPaM, aStartPaM );
738*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nView = 0; nView < aEditViews.Count(); nView++ )
739*b1cdbd2cSJim Jagielski 	{
740*b1cdbd2cSJim Jagielski 		EditView* pView = aEditViews.GetObject(nView);
741*b1cdbd2cSJim Jagielski 		DBG_CHKOBJ( pView, EditView, 0 );
742*b1cdbd2cSJim Jagielski 		pView->pImpEditView->SetEditSelection( aEmptySel );
743*b1cdbd2cSJim Jagielski 	}
744*b1cdbd2cSJim Jagielski 	ResetUndoManager();
745*b1cdbd2cSJim Jagielski 	return aEditDoc.GetStartPaM();
746*b1cdbd2cSJim Jagielski }
747*b1cdbd2cSJim Jagielski 
748*b1cdbd2cSJim Jagielski 
SetText(const XubString & rText)749*b1cdbd2cSJim Jagielski void ImpEditEngine::SetText( const XubString& rText )
750*b1cdbd2cSJim Jagielski {
751*b1cdbd2cSJim Jagielski 	// RemoveText loescht die Undo-Liste!
752*b1cdbd2cSJim Jagielski 	EditPaM aStartPaM = RemoveText();
753*b1cdbd2cSJim Jagielski 	sal_Bool bUndoCurrentlyEnabled = IsUndoEnabled();
754*b1cdbd2cSJim Jagielski 	// Der von Hand reingesteckte Text kann nicht vom Anwender rueckgaengig gemacht werden.
755*b1cdbd2cSJim Jagielski 	EnableUndo( sal_False );
756*b1cdbd2cSJim Jagielski 
757*b1cdbd2cSJim Jagielski 	EditSelection aEmptySel( aStartPaM, aStartPaM );
758*b1cdbd2cSJim Jagielski 	EditPaM aPaM = aStartPaM;
759*b1cdbd2cSJim Jagielski 	if ( rText.Len() )
760*b1cdbd2cSJim Jagielski 		aPaM = ImpInsertText( aEmptySel, rText );
761*b1cdbd2cSJim Jagielski 
762*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nView = 0; nView < aEditViews.Count(); nView++ )
763*b1cdbd2cSJim Jagielski 	{
764*b1cdbd2cSJim Jagielski 		EditView* pView = aEditViews[nView];
765*b1cdbd2cSJim Jagielski 		DBG_CHKOBJ( pView, EditView, 0 );
766*b1cdbd2cSJim Jagielski 		pView->pImpEditView->SetEditSelection( EditSelection( aPaM, aPaM ) );
767*b1cdbd2cSJim Jagielski 		// Wenn kein Text, dann auch Kein Format&Update
768*b1cdbd2cSJim Jagielski 		// => Der Text bleibt stehen.
769*b1cdbd2cSJim Jagielski 		if ( !rText.Len() && GetUpdateMode() )
770*b1cdbd2cSJim Jagielski 		{
771*b1cdbd2cSJim Jagielski 			Rectangle aTmpRec( pView->GetOutputArea().TopLeft(),
772*b1cdbd2cSJim Jagielski 								Size( aPaperSize.Width(), nCurTextHeight ) );
773*b1cdbd2cSJim Jagielski 			aTmpRec.Intersection( pView->GetOutputArea() );
774*b1cdbd2cSJim Jagielski 			pView->GetWindow()->Invalidate( aTmpRec );
775*b1cdbd2cSJim Jagielski 		}
776*b1cdbd2cSJim Jagielski 	}
777*b1cdbd2cSJim Jagielski 	if( !rText.Len() )	// sonst muss spaeter noch invalidiert werden, !bFormatted reicht.
778*b1cdbd2cSJim Jagielski 		nCurTextHeight = 0;
779*b1cdbd2cSJim Jagielski 	EnableUndo( bUndoCurrentlyEnabled );
780*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
781*b1cdbd2cSJim Jagielski 	DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Undo nach SetText?" );
782*b1cdbd2cSJim Jagielski #endif
783*b1cdbd2cSJim Jagielski }
784*b1cdbd2cSJim Jagielski 
785*b1cdbd2cSJim Jagielski 
GetEmptyItemSet()786*b1cdbd2cSJim Jagielski const SfxItemSet& ImpEditEngine::GetEmptyItemSet()
787*b1cdbd2cSJim Jagielski {
788*b1cdbd2cSJim Jagielski 	if ( !pEmptyItemSet )
789*b1cdbd2cSJim Jagielski 	{
790*b1cdbd2cSJim Jagielski 		pEmptyItemSet = new SfxItemSet( aEditDoc.GetItemPool(), EE_ITEMS_START, EE_ITEMS_END );
791*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
792*b1cdbd2cSJim Jagielski 		{
793*b1cdbd2cSJim Jagielski 			pEmptyItemSet->ClearItem( nWhich );
794*b1cdbd2cSJim Jagielski 		}
795*b1cdbd2cSJim Jagielski 	}
796*b1cdbd2cSJim Jagielski 	return *pEmptyItemSet;
797*b1cdbd2cSJim Jagielski }
798*b1cdbd2cSJim Jagielski 
799*b1cdbd2cSJim Jagielski //	----------------------------------------------------------------------
800*b1cdbd2cSJim Jagielski //	MISC
801*b1cdbd2cSJim Jagielski //	----------------------------------------------------------------------
CursorMoved(ContentNode * pPrevNode)802*b1cdbd2cSJim Jagielski void ImpEditEngine::CursorMoved( ContentNode* pPrevNode )
803*b1cdbd2cSJim Jagielski {
804*b1cdbd2cSJim Jagielski 	// Leere Attribute loeschen, aber nur, wenn Absatz nicht leer!
805*b1cdbd2cSJim Jagielski 	if ( pPrevNode->GetCharAttribs().HasEmptyAttribs() && pPrevNode->Len() )
806*b1cdbd2cSJim Jagielski 		pPrevNode->GetCharAttribs().DeleteEmptyAttribs( aEditDoc.GetItemPool() );
807*b1cdbd2cSJim Jagielski }
808*b1cdbd2cSJim Jagielski 
TextModified()809*b1cdbd2cSJim Jagielski void ImpEditEngine::TextModified()
810*b1cdbd2cSJim Jagielski {
811*b1cdbd2cSJim Jagielski 	bFormatted = sal_False;
812*b1cdbd2cSJim Jagielski 
813*b1cdbd2cSJim Jagielski     if ( GetNotifyHdl().IsSet() )
814*b1cdbd2cSJim Jagielski     {
815*b1cdbd2cSJim Jagielski         EENotify aNotify( EE_NOTIFY_TEXTMODIFIED );
816*b1cdbd2cSJim Jagielski         aNotify.pEditEngine = GetEditEnginePtr();
817*b1cdbd2cSJim Jagielski         CallNotify( aNotify );
818*b1cdbd2cSJim Jagielski     }
819*b1cdbd2cSJim Jagielski }
820*b1cdbd2cSJim Jagielski 
821*b1cdbd2cSJim Jagielski 
ParaAttribsChanged(ContentNode * pNode)822*b1cdbd2cSJim Jagielski void ImpEditEngine::ParaAttribsChanged( ContentNode* pNode )
823*b1cdbd2cSJim Jagielski {
824*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pNode, "ParaAttribsChanged: Welcher?" );
825*b1cdbd2cSJim Jagielski 
826*b1cdbd2cSJim Jagielski 	aEditDoc.SetModified( sal_True );
827*b1cdbd2cSJim Jagielski 	bFormatted = sal_False;
828*b1cdbd2cSJim Jagielski 
829*b1cdbd2cSJim Jagielski 	ParaPortion* pPortion = FindParaPortion( pNode );
830*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPortion, "ParaAttribsChanged: Portion?" );
831*b1cdbd2cSJim Jagielski 	pPortion->MarkSelectionInvalid( 0, pNode->Len() );
832*b1cdbd2cSJim Jagielski 
833*b1cdbd2cSJim Jagielski 	sal_uInt16 nPara = aEditDoc.GetPos( pNode );
834*b1cdbd2cSJim Jagielski 	pEditEngine->ParaAttribsChanged( nPara );
835*b1cdbd2cSJim Jagielski 
836*b1cdbd2cSJim Jagielski 	ParaPortion* pNextPortion = GetParaPortions().SaveGetObject( nPara+1 );
837*b1cdbd2cSJim Jagielski 	// => wird sowieso noch formatiert, wenn Invalid.
838*b1cdbd2cSJim Jagielski 	if ( pNextPortion && !pNextPortion->IsInvalid() )
839*b1cdbd2cSJim Jagielski 		CalcHeight( pNextPortion );
840*b1cdbd2cSJim Jagielski }
841*b1cdbd2cSJim Jagielski 
842*b1cdbd2cSJim Jagielski //	----------------------------------------------------------------------
843*b1cdbd2cSJim Jagielski //	Cursorbewegungen
844*b1cdbd2cSJim Jagielski //	----------------------------------------------------------------------
845*b1cdbd2cSJim Jagielski 
MoveCursor(const KeyEvent & rKeyEvent,EditView * pEditView)846*b1cdbd2cSJim Jagielski EditSelection ImpEditEngine::MoveCursor( const KeyEvent& rKeyEvent, EditView* pEditView )
847*b1cdbd2cSJim Jagielski {
848*b1cdbd2cSJim Jagielski 	// Eigentlich nur bei Up/Down noetig, aber was solls.
849*b1cdbd2cSJim Jagielski 	CheckIdleFormatter();
850*b1cdbd2cSJim Jagielski 
851*b1cdbd2cSJim Jagielski 	EditPaM aPaM( pEditView->pImpEditView->GetEditSelection().Max() );
852*b1cdbd2cSJim Jagielski 
853*b1cdbd2cSJim Jagielski 	EditPaM aOldPaM( aPaM );
854*b1cdbd2cSJim Jagielski 
855*b1cdbd2cSJim Jagielski     TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom;
856*b1cdbd2cSJim Jagielski 	if ( IsVertical() )
857*b1cdbd2cSJim Jagielski         eTextDirection = TextDirectionality_TopToBottom_RightToLeft;
858*b1cdbd2cSJim Jagielski     else if ( IsRightToLeft( GetEditDoc().GetPos( aPaM.GetNode() ) ) )
859*b1cdbd2cSJim Jagielski         eTextDirection = TextDirectionality_RightToLeft_TopToBottom;
860*b1cdbd2cSJim Jagielski 
861*b1cdbd2cSJim Jagielski     KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection );
862*b1cdbd2cSJim Jagielski 
863*b1cdbd2cSJim Jagielski     sal_Bool bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1() ? sal_True : sal_False;
864*b1cdbd2cSJim Jagielski 	sal_uInt16 nCode = aTranslatedKeyEvent.GetKeyCode().GetCode();
865*b1cdbd2cSJim Jagielski 
866*b1cdbd2cSJim Jagielski     if ( DoVisualCursorTraveling( aPaM.GetNode() ) )
867*b1cdbd2cSJim Jagielski     {
868*b1cdbd2cSJim Jagielski         // Only for simple cursor movement...
869*b1cdbd2cSJim Jagielski         if ( !bCtrl && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ) )
870*b1cdbd2cSJim Jagielski         {
871*b1cdbd2cSJim Jagielski             aPaM = CursorVisualLeftRight( pEditView, aPaM, rKeyEvent.GetKeyCode().IsMod2() ? i18n::CharacterIteratorMode::SKIPCHARACTER : i18n::CharacterIteratorMode::SKIPCELL, rKeyEvent.GetKeyCode().GetCode() == KEY_LEFT );
872*b1cdbd2cSJim Jagielski 	        nCode = 0;  // skip switch statement
873*b1cdbd2cSJim Jagielski         }
874*b1cdbd2cSJim Jagielski         /*
875*b1cdbd2cSJim Jagielski         else if ( !bCtrl && ( ( nCode == KEY_HOME ) || ( nCode == KEY_END ) ) )
876*b1cdbd2cSJim Jagielski         {
877*b1cdbd2cSJim Jagielski             aPaM = CursorVisualStartEnd( pEditView, aPaM, nCode == KEY_HOME );
878*b1cdbd2cSJim Jagielski 	        nCode = 0;  // skip switch statement
879*b1cdbd2cSJim Jagielski         }
880*b1cdbd2cSJim Jagielski         */
881*b1cdbd2cSJim Jagielski     }
882*b1cdbd2cSJim Jagielski 
883*b1cdbd2cSJim Jagielski     bool bKeyModifySelection = aTranslatedKeyEvent.GetKeyCode().IsShift();
884*b1cdbd2cSJim Jagielski 	switch ( nCode )
885*b1cdbd2cSJim Jagielski 	{
886*b1cdbd2cSJim Jagielski 		case KEY_UP:		aPaM = CursorUp( aPaM, pEditView );
887*b1cdbd2cSJim Jagielski 							break;
888*b1cdbd2cSJim Jagielski 		case KEY_DOWN:		aPaM = CursorDown( aPaM, pEditView );
889*b1cdbd2cSJim Jagielski 							break;
890*b1cdbd2cSJim Jagielski         case KEY_LEFT:		aPaM = bCtrl ? WordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? i18n::CharacterIteratorMode::SKIPCHARACTER : i18n::CharacterIteratorMode::SKIPCELL );
891*b1cdbd2cSJim Jagielski 							break;
892*b1cdbd2cSJim Jagielski 		case KEY_RIGHT: 	aPaM = bCtrl ? WordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? i18n::CharacterIteratorMode::SKIPCHARACTER : i18n::CharacterIteratorMode::SKIPCELL );
893*b1cdbd2cSJim Jagielski 							break;
894*b1cdbd2cSJim Jagielski 		case KEY_HOME:		aPaM = bCtrl ? CursorStartOfDoc() : CursorStartOfLine( aPaM );
895*b1cdbd2cSJim Jagielski 							break;
896*b1cdbd2cSJim Jagielski 		case KEY_END:		aPaM = bCtrl ? CursorEndOfDoc() : CursorEndOfLine( aPaM );
897*b1cdbd2cSJim Jagielski 							break;
898*b1cdbd2cSJim Jagielski 		case KEY_PAGEUP:	aPaM = bCtrl ? CursorStartOfDoc() : PageUp( aPaM, pEditView );
899*b1cdbd2cSJim Jagielski 							break;
900*b1cdbd2cSJim Jagielski 		case KEY_PAGEDOWN:	aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM, pEditView );
901*b1cdbd2cSJim Jagielski 							break;
902*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
903*b1cdbd2cSJim Jagielski                             aPaM = CursorStartOfLine( aPaM );
904*b1cdbd2cSJim Jagielski                             bKeyModifySelection = false;
905*b1cdbd2cSJim Jagielski                             break;
906*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
907*b1cdbd2cSJim Jagielski                             aPaM = CursorEndOfLine( aPaM );
908*b1cdbd2cSJim Jagielski                             bKeyModifySelection = false;
909*b1cdbd2cSJim Jagielski                             break;
910*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
911*b1cdbd2cSJim Jagielski                             aPaM = WordLeft( aPaM );
912*b1cdbd2cSJim Jagielski                             bKeyModifySelection = false;
913*b1cdbd2cSJim Jagielski                             break;
914*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
915*b1cdbd2cSJim Jagielski                             aPaM = WordRight( aPaM );
916*b1cdbd2cSJim Jagielski                             bKeyModifySelection = false;
917*b1cdbd2cSJim Jagielski                             break;
918*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
919*b1cdbd2cSJim Jagielski                             aPaM = CursorStartOfParagraph( aPaM );
920*b1cdbd2cSJim Jagielski                             if( aPaM == aOldPaM )
921*b1cdbd2cSJim Jagielski                             {
922*b1cdbd2cSJim Jagielski                                 aPaM = CursorLeft( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
923*b1cdbd2cSJim Jagielski                                 aPaM = CursorStartOfParagraph( aPaM );
924*b1cdbd2cSJim Jagielski                             }
925*b1cdbd2cSJim Jagielski                             bKeyModifySelection = false;
926*b1cdbd2cSJim Jagielski                             break;
927*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
928*b1cdbd2cSJim Jagielski                             aPaM = CursorEndOfParagraph( aPaM );
929*b1cdbd2cSJim Jagielski                             if( aPaM == aOldPaM )
930*b1cdbd2cSJim Jagielski                             {
931*b1cdbd2cSJim Jagielski                                 aPaM = CursorRight( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
932*b1cdbd2cSJim Jagielski                                 aPaM = CursorEndOfParagraph( aPaM );
933*b1cdbd2cSJim Jagielski                             }
934*b1cdbd2cSJim Jagielski                             bKeyModifySelection = false;
935*b1cdbd2cSJim Jagielski                             break;
936*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
937*b1cdbd2cSJim Jagielski                             aPaM = CursorStartOfDoc();
938*b1cdbd2cSJim Jagielski                             bKeyModifySelection = false;
939*b1cdbd2cSJim Jagielski                             break;
940*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
941*b1cdbd2cSJim Jagielski                             aPaM = CursorEndOfDoc();
942*b1cdbd2cSJim Jagielski                             bKeyModifySelection = false;
943*b1cdbd2cSJim Jagielski                             break;
944*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
945*b1cdbd2cSJim Jagielski                             aPaM = CursorStartOfLine( aPaM );
946*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
947*b1cdbd2cSJim Jagielski                             break;
948*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
949*b1cdbd2cSJim Jagielski                             aPaM = CursorEndOfLine( aPaM );
950*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
951*b1cdbd2cSJim Jagielski                             break;
952*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_BACKWARD:
953*b1cdbd2cSJim Jagielski                             aPaM = CursorLeft( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
954*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
955*b1cdbd2cSJim Jagielski                             break;
956*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_FORWARD:
957*b1cdbd2cSJim Jagielski                             aPaM = CursorRight( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
958*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
959*b1cdbd2cSJim Jagielski                             break;
960*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
961*b1cdbd2cSJim Jagielski                             aPaM = WordLeft( aPaM );
962*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
963*b1cdbd2cSJim Jagielski                             break;
964*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
965*b1cdbd2cSJim Jagielski                             aPaM = WordRight( aPaM );
966*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
967*b1cdbd2cSJim Jagielski                             break;
968*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
969*b1cdbd2cSJim Jagielski                             aPaM = CursorStartOfParagraph( aPaM );
970*b1cdbd2cSJim Jagielski                             if( aPaM == aOldPaM )
971*b1cdbd2cSJim Jagielski                             {
972*b1cdbd2cSJim Jagielski                                 aPaM = CursorLeft( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
973*b1cdbd2cSJim Jagielski                                 aPaM = CursorStartOfParagraph( aPaM );
974*b1cdbd2cSJim Jagielski                             }
975*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
976*b1cdbd2cSJim Jagielski                             break;
977*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
978*b1cdbd2cSJim Jagielski                             aPaM = CursorEndOfParagraph( aPaM );
979*b1cdbd2cSJim Jagielski                             if( aPaM == aOldPaM )
980*b1cdbd2cSJim Jagielski                             {
981*b1cdbd2cSJim Jagielski                                 aPaM = CursorRight( aPaM, i18n::CharacterIteratorMode::SKIPCELL );
982*b1cdbd2cSJim Jagielski                                 aPaM = CursorEndOfParagraph( aPaM );
983*b1cdbd2cSJim Jagielski                             }
984*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
985*b1cdbd2cSJim Jagielski                             break;
986*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
987*b1cdbd2cSJim Jagielski                             aPaM = CursorStartOfDoc();
988*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
989*b1cdbd2cSJim Jagielski                             break;
990*b1cdbd2cSJim Jagielski         case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
991*b1cdbd2cSJim Jagielski                             aPaM = CursorEndOfDoc();
992*b1cdbd2cSJim Jagielski                             bKeyModifySelection = true;
993*b1cdbd2cSJim Jagielski                             break;
994*b1cdbd2cSJim Jagielski 	}
995*b1cdbd2cSJim Jagielski 
996*b1cdbd2cSJim Jagielski 	if ( aOldPaM != aPaM )
997*b1cdbd2cSJim Jagielski 	{
998*b1cdbd2cSJim Jagielski 		CursorMoved( aOldPaM.GetNode() );
999*b1cdbd2cSJim Jagielski 		if ( aStatus.NotifyCursorMovements() && ( aOldPaM.GetNode() != aPaM.GetNode() ) )
1000*b1cdbd2cSJim Jagielski 		{
1001*b1cdbd2cSJim Jagielski 			aStatus.GetStatusWord() = aStatus.GetStatusWord() | EE_STAT_CRSRLEFTPARA;
1002*b1cdbd2cSJim Jagielski 			aStatus.GetPrevParagraph() = aEditDoc.GetPos( aOldPaM.GetNode() );
1003*b1cdbd2cSJim Jagielski 		}
1004*b1cdbd2cSJim Jagielski 	}
1005*b1cdbd2cSJim Jagielski 	else
1006*b1cdbd2cSJim Jagielski 		aStatus.GetStatusWord() = aStatus.GetStatusWord() | EE_STAT_CRSRMOVEFAIL;
1007*b1cdbd2cSJim Jagielski 
1008*b1cdbd2cSJim Jagielski 	// Bewirkt evtl. ein CreateAnchor oder Deselection all
1009*b1cdbd2cSJim Jagielski 	aSelEngine.SetCurView( pEditView );
1010*b1cdbd2cSJim Jagielski 	aSelEngine.CursorPosChanging( bKeyModifySelection, aTranslatedKeyEvent.GetKeyCode().IsMod1() );
1011*b1cdbd2cSJim Jagielski 	EditPaM aOldEnd( pEditView->pImpEditView->GetEditSelection().Max() );
1012*b1cdbd2cSJim Jagielski 	pEditView->pImpEditView->GetEditSelection().Max() = aPaM;
1013*b1cdbd2cSJim Jagielski 	if ( bKeyModifySelection )
1014*b1cdbd2cSJim Jagielski 	{
1015*b1cdbd2cSJim Jagielski 		// Dann wird die Selektion erweitert...
1016*b1cdbd2cSJim Jagielski 		EditSelection aTmpNewSel( aOldEnd, aPaM );
1017*b1cdbd2cSJim Jagielski 		pEditView->pImpEditView->DrawSelection( aTmpNewSel );
1018*b1cdbd2cSJim Jagielski 	}
1019*b1cdbd2cSJim Jagielski 	else
1020*b1cdbd2cSJim Jagielski 		pEditView->pImpEditView->GetEditSelection().Min() = aPaM;
1021*b1cdbd2cSJim Jagielski 
1022*b1cdbd2cSJim Jagielski 	return pEditView->pImpEditView->GetEditSelection();
1023*b1cdbd2cSJim Jagielski }
1024*b1cdbd2cSJim Jagielski 
CursorVisualStartEnd(EditView * pEditView,const EditPaM & rPaM,sal_Bool bStart)1025*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorVisualStartEnd( EditView* pEditView, const EditPaM& rPaM, sal_Bool bStart )
1026*b1cdbd2cSJim Jagielski {
1027*b1cdbd2cSJim Jagielski     EditPaM aPaM( rPaM );
1028*b1cdbd2cSJim Jagielski 
1029*b1cdbd2cSJim Jagielski     sal_uInt16 nPara = GetEditDoc().GetPos( aPaM.GetNode() );
1030*b1cdbd2cSJim Jagielski     ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
1031*b1cdbd2cSJim Jagielski 
1032*b1cdbd2cSJim Jagielski     sal_uInt16 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_False );
1033*b1cdbd2cSJim Jagielski     EditLine* pLine = pParaPortion->GetLines().GetObject( nLine );
1034*b1cdbd2cSJim Jagielski     sal_Bool bEmptyLine = pLine->GetStart() == pLine->GetEnd();
1035*b1cdbd2cSJim Jagielski 
1036*b1cdbd2cSJim Jagielski     pEditView->pImpEditView->nExtraCursorFlags = 0;
1037*b1cdbd2cSJim Jagielski 
1038*b1cdbd2cSJim Jagielski     if ( !bEmptyLine )
1039*b1cdbd2cSJim Jagielski     {
1040*b1cdbd2cSJim Jagielski         String aLine( *aPaM.GetNode(), pLine->GetStart(), pLine->GetEnd() - pLine->GetStart() );
1041*b1cdbd2cSJim Jagielski //        sal_uInt16 nPosInLine = aPaM.GetIndex() - pLine->GetStart();
1042*b1cdbd2cSJim Jagielski 
1043*b1cdbd2cSJim Jagielski         const sal_Unicode* pLineString = aLine.GetBuffer();
1044*b1cdbd2cSJim Jagielski 
1045*b1cdbd2cSJim Jagielski         UErrorCode nError = U_ZERO_ERROR;
1046*b1cdbd2cSJim Jagielski         UBiDi* pBidi = ubidi_openSized( aLine.Len(), 0, &nError );
1047*b1cdbd2cSJim Jagielski 
1048*b1cdbd2cSJim Jagielski         const UBiDiLevel  nBidiLevel = IsRightToLeft( nPara ) ? 1 /*RTL*/ : 0 /*LTR*/;
1049*b1cdbd2cSJim Jagielski         ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), aLine.Len(), nBidiLevel, NULL, &nError );	// UChar != sal_Unicode in MinGW
1050*b1cdbd2cSJim Jagielski 
1051*b1cdbd2cSJim Jagielski         sal_uInt16 nVisPos = bStart ? 0 : aLine.Len()-1;
1052*b1cdbd2cSJim Jagielski         sal_uInt16 nLogPos = (sal_uInt16)ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
1053*b1cdbd2cSJim Jagielski 
1054*b1cdbd2cSJim Jagielski         ubidi_close( pBidi );
1055*b1cdbd2cSJim Jagielski 
1056*b1cdbd2cSJim Jagielski         aPaM.GetIndex() = nLogPos + pLine->GetStart();
1057*b1cdbd2cSJim Jagielski 
1058*b1cdbd2cSJim Jagielski         sal_uInt16 nTmp;
1059*b1cdbd2cSJim Jagielski         sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTmp, sal_True );
1060*b1cdbd2cSJim Jagielski         TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
1061*b1cdbd2cSJim Jagielski         sal_uInt16 nRTLLevel = pTextPortion->GetRightToLeft();
1062*b1cdbd2cSJim Jagielski //        sal_Bool bParaRTL = IsRightToLeft( nPara );
1063*b1cdbd2cSJim Jagielski         sal_Bool bPortionRTL = nRTLLevel%2 ? sal_True : sal_False;
1064*b1cdbd2cSJim Jagielski 
1065*b1cdbd2cSJim Jagielski         if ( bStart )
1066*b1cdbd2cSJim Jagielski         {
1067*b1cdbd2cSJim Jagielski             pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 0 : 1 );
1068*b1cdbd2cSJim Jagielski             // Maybe we must be *behind* the character
1069*b1cdbd2cSJim Jagielski             if ( bPortionRTL && pEditView->IsInsertMode() )
1070*b1cdbd2cSJim Jagielski                 aPaM.GetIndex()++;
1071*b1cdbd2cSJim Jagielski         }
1072*b1cdbd2cSJim Jagielski         else
1073*b1cdbd2cSJim Jagielski         {
1074*b1cdbd2cSJim Jagielski             pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 1 : 0 );
1075*b1cdbd2cSJim Jagielski             if ( !bPortionRTL && pEditView->IsInsertMode() )
1076*b1cdbd2cSJim Jagielski                 aPaM.GetIndex()++;
1077*b1cdbd2cSJim Jagielski         }
1078*b1cdbd2cSJim Jagielski     }
1079*b1cdbd2cSJim Jagielski 
1080*b1cdbd2cSJim Jagielski     return aPaM;
1081*b1cdbd2cSJim Jagielski }
1082*b1cdbd2cSJim Jagielski 
CursorVisualLeftRight(EditView * pEditView,const EditPaM & rPaM,sal_uInt16 nCharacterIteratorMode,sal_Bool bVisualToLeft)1083*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorVisualLeftRight( EditView* pEditView, const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode, sal_Bool bVisualToLeft )
1084*b1cdbd2cSJim Jagielski {
1085*b1cdbd2cSJim Jagielski     EditPaM aPaM( rPaM );
1086*b1cdbd2cSJim Jagielski 
1087*b1cdbd2cSJim Jagielski     sal_uInt16 nPara = GetEditDoc().GetPos( aPaM.GetNode() );
1088*b1cdbd2cSJim Jagielski     ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
1089*b1cdbd2cSJim Jagielski 
1090*b1cdbd2cSJim Jagielski     sal_uInt16 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), sal_False );
1091*b1cdbd2cSJim Jagielski     EditLine* pLine = pParaPortion->GetLines().GetObject( nLine );
1092*b1cdbd2cSJim Jagielski     sal_Bool bEmptyLine = pLine->GetStart() == pLine->GetEnd();
1093*b1cdbd2cSJim Jagielski 
1094*b1cdbd2cSJim Jagielski //    sal_uInt16 nCurrentCursorFlags = pEditView->pImpEditView->nExtraCursorFlags;
1095*b1cdbd2cSJim Jagielski     pEditView->pImpEditView->nExtraCursorFlags = 0;
1096*b1cdbd2cSJim Jagielski 
1097*b1cdbd2cSJim Jagielski     sal_Bool bParaRTL = IsRightToLeft( nPara );
1098*b1cdbd2cSJim Jagielski 
1099*b1cdbd2cSJim Jagielski     sal_Bool bDone = sal_False;
1100*b1cdbd2cSJim Jagielski 
1101*b1cdbd2cSJim Jagielski     if ( bEmptyLine )
1102*b1cdbd2cSJim Jagielski     {
1103*b1cdbd2cSJim Jagielski         if ( bVisualToLeft )
1104*b1cdbd2cSJim Jagielski         {
1105*b1cdbd2cSJim Jagielski             aPaM = CursorUp( aPaM, pEditView );
1106*b1cdbd2cSJim Jagielski             if ( aPaM != rPaM )
1107*b1cdbd2cSJim Jagielski                 aPaM = CursorVisualStartEnd( pEditView, aPaM, sal_False );
1108*b1cdbd2cSJim Jagielski         }
1109*b1cdbd2cSJim Jagielski         else
1110*b1cdbd2cSJim Jagielski         {
1111*b1cdbd2cSJim Jagielski             aPaM = CursorDown( aPaM, pEditView );
1112*b1cdbd2cSJim Jagielski             if ( aPaM != rPaM )
1113*b1cdbd2cSJim Jagielski                 aPaM = CursorVisualStartEnd( pEditView, aPaM, sal_True );
1114*b1cdbd2cSJim Jagielski         }
1115*b1cdbd2cSJim Jagielski 
1116*b1cdbd2cSJim Jagielski         bDone = sal_True;
1117*b1cdbd2cSJim Jagielski     }
1118*b1cdbd2cSJim Jagielski 
1119*b1cdbd2cSJim Jagielski     sal_Bool bLogicalBackward = bParaRTL ? !bVisualToLeft : bVisualToLeft;
1120*b1cdbd2cSJim Jagielski 
1121*b1cdbd2cSJim Jagielski     if ( !bDone && pEditView->IsInsertMode() )
1122*b1cdbd2cSJim Jagielski     {
1123*b1cdbd2cSJim Jagielski         // Check if we are within a portion and don't have overwrite mode, then it's easy...
1124*b1cdbd2cSJim Jagielski         sal_uInt16 nPortionStart;
1125*b1cdbd2cSJim Jagielski         sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nPortionStart, sal_False );
1126*b1cdbd2cSJim Jagielski         TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
1127*b1cdbd2cSJim Jagielski 
1128*b1cdbd2cSJim Jagielski         sal_Bool bPortionBoundary = ( aPaM.GetIndex() == nPortionStart ) || ( aPaM.GetIndex() == (nPortionStart+pTextPortion->GetLen()) );
1129*b1cdbd2cSJim Jagielski         sal_uInt16 nRTLLevel = pTextPortion->GetRightToLeft();
1130*b1cdbd2cSJim Jagielski 
1131*b1cdbd2cSJim Jagielski         // Portion boundary doesn't matter if both have same RTL level
1132*b1cdbd2cSJim Jagielski         sal_uInt16 nRTLLevelNextPortion = 0xFFFF;
1133*b1cdbd2cSJim Jagielski         if ( bPortionBoundary && aPaM.GetIndex() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) )
1134*b1cdbd2cSJim Jagielski         {
1135*b1cdbd2cSJim Jagielski             sal_uInt16 nTmp;
1136*b1cdbd2cSJim Jagielski             sal_uInt16 nNextTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex()+1, nTmp, bLogicalBackward ? sal_False : sal_True );
1137*b1cdbd2cSJim Jagielski             TextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nNextTextPortion );
1138*b1cdbd2cSJim Jagielski             nRTLLevelNextPortion = pNextTextPortion->GetRightToLeft();
1139*b1cdbd2cSJim Jagielski         }
1140*b1cdbd2cSJim Jagielski 
1141*b1cdbd2cSJim Jagielski         if ( !bPortionBoundary || ( nRTLLevel == nRTLLevelNextPortion ) )
1142*b1cdbd2cSJim Jagielski         {
1143*b1cdbd2cSJim Jagielski             if ( ( bVisualToLeft && !(nRTLLevel%2) ) || ( !bVisualToLeft && (nRTLLevel%2) ) )
1144*b1cdbd2cSJim Jagielski             {
1145*b1cdbd2cSJim Jagielski                 aPaM = CursorLeft( aPaM, nCharacterIteratorMode );
1146*b1cdbd2cSJim Jagielski                 pEditView->pImpEditView->SetCursorBidiLevel( 1 );
1147*b1cdbd2cSJim Jagielski             }
1148*b1cdbd2cSJim Jagielski             else
1149*b1cdbd2cSJim Jagielski             {
1150*b1cdbd2cSJim Jagielski                 aPaM = CursorRight( aPaM, nCharacterIteratorMode );
1151*b1cdbd2cSJim Jagielski                 pEditView->pImpEditView->SetCursorBidiLevel( 0 );
1152*b1cdbd2cSJim Jagielski             }
1153*b1cdbd2cSJim Jagielski             bDone = sal_True;
1154*b1cdbd2cSJim Jagielski         }
1155*b1cdbd2cSJim Jagielski     }
1156*b1cdbd2cSJim Jagielski 
1157*b1cdbd2cSJim Jagielski     if ( !bDone )
1158*b1cdbd2cSJim Jagielski     {
1159*b1cdbd2cSJim Jagielski         sal_Bool bGotoStartOfNextLine = sal_False;
1160*b1cdbd2cSJim Jagielski         sal_Bool bGotoEndOfPrevLine = sal_False;
1161*b1cdbd2cSJim Jagielski 
1162*b1cdbd2cSJim Jagielski         String aLine( *aPaM.GetNode(), pLine->GetStart(), pLine->GetEnd() - pLine->GetStart() );
1163*b1cdbd2cSJim Jagielski         sal_uInt16 nPosInLine = aPaM.GetIndex() - pLine->GetStart();
1164*b1cdbd2cSJim Jagielski 
1165*b1cdbd2cSJim Jagielski         const sal_Unicode* pLineString = aLine.GetBuffer();
1166*b1cdbd2cSJim Jagielski 
1167*b1cdbd2cSJim Jagielski         UErrorCode nError = U_ZERO_ERROR;
1168*b1cdbd2cSJim Jagielski         UBiDi* pBidi = ubidi_openSized( aLine.Len(), 0, &nError );
1169*b1cdbd2cSJim Jagielski 
1170*b1cdbd2cSJim Jagielski         const UBiDiLevel  nBidiLevel = IsRightToLeft( nPara ) ? 1 /*RTL*/ : 0 /*LTR*/;
1171*b1cdbd2cSJim Jagielski         ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), aLine.Len(), nBidiLevel, NULL, &nError );	// UChar != sal_Unicode in MinGW
1172*b1cdbd2cSJim Jagielski 
1173*b1cdbd2cSJim Jagielski         if ( !pEditView->IsInsertMode() )
1174*b1cdbd2cSJim Jagielski         {
1175*b1cdbd2cSJim Jagielski             sal_Bool bEndOfLine = nPosInLine == aLine.Len();
1176*b1cdbd2cSJim Jagielski             sal_uInt16 nVisPos = (sal_uInt16)ubidi_getVisualIndex( pBidi, !bEndOfLine ? nPosInLine : nPosInLine-1, &nError );
1177*b1cdbd2cSJim Jagielski             if ( bVisualToLeft )
1178*b1cdbd2cSJim Jagielski             {
1179*b1cdbd2cSJim Jagielski                 bGotoEndOfPrevLine = nVisPos == 0;
1180*b1cdbd2cSJim Jagielski                 if ( !bEndOfLine )
1181*b1cdbd2cSJim Jagielski                     nVisPos--;
1182*b1cdbd2cSJim Jagielski             }
1183*b1cdbd2cSJim Jagielski             else
1184*b1cdbd2cSJim Jagielski             {
1185*b1cdbd2cSJim Jagielski                 bGotoStartOfNextLine = nVisPos == (aLine.Len() - 1);
1186*b1cdbd2cSJim Jagielski                 if ( !bEndOfLine )
1187*b1cdbd2cSJim Jagielski                     nVisPos++;
1188*b1cdbd2cSJim Jagielski             }
1189*b1cdbd2cSJim Jagielski 
1190*b1cdbd2cSJim Jagielski             if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine )
1191*b1cdbd2cSJim Jagielski             {
1192*b1cdbd2cSJim Jagielski                 sal_uInt16 nLogPos = (sal_uInt16)ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
1193*b1cdbd2cSJim Jagielski                 aPaM.GetIndex() = pLine->GetStart() + nLogPos;
1194*b1cdbd2cSJim Jagielski                 pEditView->pImpEditView->SetCursorBidiLevel( 0 );
1195*b1cdbd2cSJim Jagielski             }
1196*b1cdbd2cSJim Jagielski         }
1197*b1cdbd2cSJim Jagielski         else
1198*b1cdbd2cSJim Jagielski         {
1199*b1cdbd2cSJim Jagielski             sal_Bool bWasBehind = sal_False;
1200*b1cdbd2cSJim Jagielski             sal_Bool bBeforePortion = !nPosInLine || pEditView->pImpEditView->GetCursorBidiLevel() == 1;
1201*b1cdbd2cSJim Jagielski             if ( nPosInLine && ( !bBeforePortion ) ) // before the next portion
1202*b1cdbd2cSJim Jagielski                 bWasBehind = sal_True;  // step one back, otherwise visual will be unusable when rtl portion follows.
1203*b1cdbd2cSJim Jagielski 
1204*b1cdbd2cSJim Jagielski             sal_uInt16 nPortionStart;
1205*b1cdbd2cSJim Jagielski             sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nPortionStart, bBeforePortion );
1206*b1cdbd2cSJim Jagielski             TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
1207*b1cdbd2cSJim Jagielski             sal_Bool bRTLPortion = (pTextPortion->GetRightToLeft() % 2) != 0;
1208*b1cdbd2cSJim Jagielski 
1209*b1cdbd2cSJim Jagielski             // -1: We are 'behind' the character
1210*b1cdbd2cSJim Jagielski             long nVisPos = (long)ubidi_getVisualIndex( pBidi, bWasBehind ? nPosInLine-1 : nPosInLine, &nError );
1211*b1cdbd2cSJim Jagielski             if ( bVisualToLeft )
1212*b1cdbd2cSJim Jagielski             {
1213*b1cdbd2cSJim Jagielski                 if ( !bWasBehind || bRTLPortion )
1214*b1cdbd2cSJim Jagielski                     nVisPos--;
1215*b1cdbd2cSJim Jagielski             }
1216*b1cdbd2cSJim Jagielski             else
1217*b1cdbd2cSJim Jagielski             {
1218*b1cdbd2cSJim Jagielski                 if ( bWasBehind || bRTLPortion || bBeforePortion )
1219*b1cdbd2cSJim Jagielski                     nVisPos++;
1220*b1cdbd2cSJim Jagielski //                if ( bWasBehind && bRTLPortion )
1221*b1cdbd2cSJim Jagielski //                    nVisPos++;
1222*b1cdbd2cSJim Jagielski             }
1223*b1cdbd2cSJim Jagielski 
1224*b1cdbd2cSJim Jagielski             bGotoEndOfPrevLine = nVisPos < 0;
1225*b1cdbd2cSJim Jagielski             bGotoStartOfNextLine = nVisPos >= aLine.Len();
1226*b1cdbd2cSJim Jagielski 
1227*b1cdbd2cSJim Jagielski             if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine )
1228*b1cdbd2cSJim Jagielski             {
1229*b1cdbd2cSJim Jagielski                 sal_uInt16 nLogPos = (sal_uInt16)ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
1230*b1cdbd2cSJim Jagielski 
1231*b1cdbd2cSJim Jagielski /*
1232*b1cdbd2cSJim Jagielski                 if ( nLogPos == aPaM.GetIndex() )
1233*b1cdbd2cSJim Jagielski                 {
1234*b1cdbd2cSJim Jagielski                     if ( bVisualToLeft )
1235*b1cdbd2cSJim Jagielski                         bGotoEndOfPrevLine = sal_True;
1236*b1cdbd2cSJim Jagielski                     else
1237*b1cdbd2cSJim Jagielski                         bGotoStartOfNextLine = sal_True;
1238*b1cdbd2cSJim Jagielski                 }
1239*b1cdbd2cSJim Jagielski                 else
1240*b1cdbd2cSJim Jagielski */
1241*b1cdbd2cSJim Jagielski                 {
1242*b1cdbd2cSJim Jagielski                     aPaM.GetIndex() = pLine->GetStart() + nLogPos;
1243*b1cdbd2cSJim Jagielski 
1244*b1cdbd2cSJim Jagielski                     // RTL portion, stay visually on the left side.
1245*b1cdbd2cSJim Jagielski                     sal_uInt16 _nPortionStart;
1246*b1cdbd2cSJim Jagielski                     // sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nPortionStart, !bRTLPortion );
1247*b1cdbd2cSJim Jagielski                     sal_uInt16 _nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), _nPortionStart, sal_True );
1248*b1cdbd2cSJim Jagielski                     TextPortion* _pTextPortion = pParaPortion->GetTextPortions().GetObject( _nTextPortion );
1249*b1cdbd2cSJim Jagielski                     if ( bVisualToLeft && !bRTLPortion && ( _pTextPortion->GetRightToLeft() % 2 ) )
1250*b1cdbd2cSJim Jagielski                         aPaM.GetIndex()++;
1251*b1cdbd2cSJim Jagielski                     else if ( !bVisualToLeft && bRTLPortion && ( bWasBehind || !(_pTextPortion->GetRightToLeft() % 2 )) )
1252*b1cdbd2cSJim Jagielski                         aPaM.GetIndex()++;
1253*b1cdbd2cSJim Jagielski 
1254*b1cdbd2cSJim Jagielski                     pEditView->pImpEditView->SetCursorBidiLevel( _nPortionStart );
1255*b1cdbd2cSJim Jagielski                 }
1256*b1cdbd2cSJim Jagielski             }
1257*b1cdbd2cSJim Jagielski         }
1258*b1cdbd2cSJim Jagielski 
1259*b1cdbd2cSJim Jagielski         ubidi_close( pBidi );
1260*b1cdbd2cSJim Jagielski 
1261*b1cdbd2cSJim Jagielski         if ( bGotoEndOfPrevLine )
1262*b1cdbd2cSJim Jagielski         {
1263*b1cdbd2cSJim Jagielski             aPaM = CursorUp( aPaM, pEditView );
1264*b1cdbd2cSJim Jagielski             if ( aPaM != rPaM )
1265*b1cdbd2cSJim Jagielski                 aPaM = CursorVisualStartEnd( pEditView, aPaM, sal_False );
1266*b1cdbd2cSJim Jagielski         }
1267*b1cdbd2cSJim Jagielski         else if ( bGotoStartOfNextLine )
1268*b1cdbd2cSJim Jagielski         {
1269*b1cdbd2cSJim Jagielski             aPaM = CursorDown( aPaM, pEditView );
1270*b1cdbd2cSJim Jagielski             if ( aPaM != rPaM )
1271*b1cdbd2cSJim Jagielski                 aPaM = CursorVisualStartEnd( pEditView, aPaM, sal_True );
1272*b1cdbd2cSJim Jagielski         }
1273*b1cdbd2cSJim Jagielski     }
1274*b1cdbd2cSJim Jagielski     return aPaM;
1275*b1cdbd2cSJim Jagielski }
1276*b1cdbd2cSJim Jagielski 
1277*b1cdbd2cSJim Jagielski 
CursorLeft(const EditPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1278*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorLeft( const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1279*b1cdbd2cSJim Jagielski {
1280*b1cdbd2cSJim Jagielski     EditPaM aCurPaM( rPaM );
1281*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( aCurPaM );
1282*b1cdbd2cSJim Jagielski 
1283*b1cdbd2cSJim Jagielski 	if ( aCurPaM.GetIndex() )
1284*b1cdbd2cSJim Jagielski 	{
1285*b1cdbd2cSJim Jagielski 		sal_Int32 nCount = 1;
1286*b1cdbd2cSJim Jagielski 		uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1287*b1cdbd2cSJim Jagielski  		aNewPaM.SetIndex( (sal_uInt16)_xBI->previousCharacters( *aNewPaM.GetNode(), aNewPaM.GetIndex(), GetLocale( aNewPaM ), nCharacterIteratorMode, nCount, nCount ) );
1288*b1cdbd2cSJim Jagielski 	}
1289*b1cdbd2cSJim Jagielski 	else
1290*b1cdbd2cSJim Jagielski 	{
1291*b1cdbd2cSJim Jagielski 		ContentNode* pNode = aCurPaM.GetNode();
1292*b1cdbd2cSJim Jagielski 		pNode = GetPrevVisNode( pNode );
1293*b1cdbd2cSJim Jagielski 		if ( pNode )
1294*b1cdbd2cSJim Jagielski 		{
1295*b1cdbd2cSJim Jagielski 			aNewPaM.SetNode( pNode );
1296*b1cdbd2cSJim Jagielski 			aNewPaM.SetIndex( pNode->Len() );
1297*b1cdbd2cSJim Jagielski 		}
1298*b1cdbd2cSJim Jagielski 	}
1299*b1cdbd2cSJim Jagielski 
1300*b1cdbd2cSJim Jagielski 	return aNewPaM;
1301*b1cdbd2cSJim Jagielski }
1302*b1cdbd2cSJim Jagielski 
CursorRight(const EditPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1303*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorRight( const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1304*b1cdbd2cSJim Jagielski {
1305*b1cdbd2cSJim Jagielski     EditPaM aCurPaM( rPaM );
1306*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( aCurPaM );
1307*b1cdbd2cSJim Jagielski 
1308*b1cdbd2cSJim Jagielski     if ( aCurPaM.GetIndex() < aCurPaM.GetNode()->Len() )
1309*b1cdbd2cSJim Jagielski 	{
1310*b1cdbd2cSJim Jagielski 		uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1311*b1cdbd2cSJim Jagielski 		sal_Int32 nCount = 1;
1312*b1cdbd2cSJim Jagielski 		aNewPaM.SetIndex( (sal_uInt16)_xBI->nextCharacters( *aNewPaM.GetNode(), aNewPaM.GetIndex(), GetLocale( aNewPaM ), nCharacterIteratorMode, nCount, nCount ) );
1313*b1cdbd2cSJim Jagielski 	}
1314*b1cdbd2cSJim Jagielski 	else
1315*b1cdbd2cSJim Jagielski 	{
1316*b1cdbd2cSJim Jagielski 		ContentNode* pNode = aCurPaM.GetNode();
1317*b1cdbd2cSJim Jagielski 		pNode = GetNextVisNode( pNode );
1318*b1cdbd2cSJim Jagielski 		if ( pNode )
1319*b1cdbd2cSJim Jagielski 		{
1320*b1cdbd2cSJim Jagielski 			aNewPaM.SetNode( pNode );
1321*b1cdbd2cSJim Jagielski 			aNewPaM.SetIndex( 0 );
1322*b1cdbd2cSJim Jagielski 		}
1323*b1cdbd2cSJim Jagielski 	}
1324*b1cdbd2cSJim Jagielski 
1325*b1cdbd2cSJim Jagielski 	return aNewPaM;
1326*b1cdbd2cSJim Jagielski }
1327*b1cdbd2cSJim Jagielski 
CursorUp(const EditPaM & rPaM,EditView * pView)1328*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorUp( const EditPaM& rPaM, EditView* pView )
1329*b1cdbd2cSJim Jagielski {
1330*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pView, "Keine View - Keine Cursorbewegung!" );
1331*b1cdbd2cSJim Jagielski 
1332*b1cdbd2cSJim Jagielski 	ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() );
1333*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPPortion, "Keine passende Portion gefunden: CursorUp" );
1334*b1cdbd2cSJim Jagielski 	sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex() );
1335*b1cdbd2cSJim Jagielski 	EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
1336*b1cdbd2cSJim Jagielski 
1337*b1cdbd2cSJim Jagielski 	long nX;
1338*b1cdbd2cSJim Jagielski 	if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW )
1339*b1cdbd2cSJim Jagielski 	{
1340*b1cdbd2cSJim Jagielski 		nX = GetXPos( pPPortion, pLine, rPaM.GetIndex() );
1341*b1cdbd2cSJim Jagielski 		pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef;
1342*b1cdbd2cSJim Jagielski 	}
1343*b1cdbd2cSJim Jagielski 	else
1344*b1cdbd2cSJim Jagielski 		nX = pView->pImpEditView->nTravelXPos;
1345*b1cdbd2cSJim Jagielski 
1346*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( rPaM );
1347*b1cdbd2cSJim Jagielski 	if ( nLine )	// gleicher Absatz
1348*b1cdbd2cSJim Jagielski 	{
1349*b1cdbd2cSJim Jagielski 		EditLine* pPrevLine = pPPortion->GetLines().GetObject(nLine-1);
1350*b1cdbd2cSJim Jagielski 		aNewPaM.SetIndex( GetChar( pPPortion, pPrevLine, nX ) );
1351*b1cdbd2cSJim Jagielski 		// Wenn davor eine autom.Umgebrochene Zeile, und ich muss genau an das
1352*b1cdbd2cSJim Jagielski 		// Ende dieser Zeile, landet der Cursor in der aktuellen Zeile am Anfang
1353*b1cdbd2cSJim Jagielski 		// Siehe Problem: Letztes Zeichen einer autom.umgebr. Zeile = Cursor
1354*b1cdbd2cSJim Jagielski 		if ( aNewPaM.GetIndex() && ( aNewPaM.GetIndex() == pLine->GetStart() ) )
1355*b1cdbd2cSJim Jagielski 			aNewPaM = CursorLeft( aNewPaM );
1356*b1cdbd2cSJim Jagielski 	}
1357*b1cdbd2cSJim Jagielski 	else	// vorheriger Absatz
1358*b1cdbd2cSJim Jagielski 	{
1359*b1cdbd2cSJim Jagielski 		ParaPortion* pPrevPortion = GetPrevVisPortion( pPPortion );
1360*b1cdbd2cSJim Jagielski 		if ( pPrevPortion )
1361*b1cdbd2cSJim Jagielski 		{
1362*b1cdbd2cSJim Jagielski 			pLine = pPrevPortion->GetLines().GetObject( pPrevPortion->GetLines().Count()-1 );
1363*b1cdbd2cSJim Jagielski 			DBG_ASSERT( pLine, "Zeile davor nicht gefunden: CursorUp" );
1364*b1cdbd2cSJim Jagielski 			aNewPaM.SetNode( pPrevPortion->GetNode() );
1365*b1cdbd2cSJim Jagielski 			aNewPaM.SetIndex( GetChar( pPrevPortion, pLine, nX+nOnePixelInRef ) );
1366*b1cdbd2cSJim Jagielski 		}
1367*b1cdbd2cSJim Jagielski 	}
1368*b1cdbd2cSJim Jagielski 
1369*b1cdbd2cSJim Jagielski 	return aNewPaM;
1370*b1cdbd2cSJim Jagielski }
1371*b1cdbd2cSJim Jagielski 
CursorDown(const EditPaM & rPaM,EditView * pView)1372*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorDown( const EditPaM& rPaM, EditView* pView )
1373*b1cdbd2cSJim Jagielski {
1374*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pView, "Keine View - Keine Cursorbewegung!" );
1375*b1cdbd2cSJim Jagielski 
1376*b1cdbd2cSJim Jagielski 	ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() );
1377*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPPortion, "Keine passende Portion gefunden: CursorDown" );
1378*b1cdbd2cSJim Jagielski 	sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex() );
1379*b1cdbd2cSJim Jagielski 
1380*b1cdbd2cSJim Jagielski 	long nX;
1381*b1cdbd2cSJim Jagielski 	if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW )
1382*b1cdbd2cSJim Jagielski 	{
1383*b1cdbd2cSJim Jagielski 		EditLine* pLine = pPPortion->GetLines().GetObject(nLine);
1384*b1cdbd2cSJim Jagielski 		nX = GetXPos( pPPortion, pLine, rPaM.GetIndex() );
1385*b1cdbd2cSJim Jagielski 		pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef;
1386*b1cdbd2cSJim Jagielski 	}
1387*b1cdbd2cSJim Jagielski 	else
1388*b1cdbd2cSJim Jagielski 		nX = pView->pImpEditView->nTravelXPos;
1389*b1cdbd2cSJim Jagielski 
1390*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( rPaM );
1391*b1cdbd2cSJim Jagielski 	if ( nLine < pPPortion->GetLines().Count()-1 )
1392*b1cdbd2cSJim Jagielski 	{
1393*b1cdbd2cSJim Jagielski 		EditLine* pNextLine = pPPortion->GetLines().GetObject(nLine+1);
1394*b1cdbd2cSJim Jagielski 		aNewPaM.SetIndex( GetChar( pPPortion, pNextLine, nX ) );
1395*b1cdbd2cSJim Jagielski 		// Sonderbehandlung siehe CursorUp...
1396*b1cdbd2cSJim Jagielski 		if ( ( aNewPaM.GetIndex() == pNextLine->GetEnd() ) && ( aNewPaM.GetIndex() > pNextLine->GetStart() ) && ( aNewPaM.GetIndex() < pPPortion->GetNode()->Len() ) )
1397*b1cdbd2cSJim Jagielski 			aNewPaM = CursorLeft( aNewPaM );
1398*b1cdbd2cSJim Jagielski 	}
1399*b1cdbd2cSJim Jagielski 	else	// naechster Absatz
1400*b1cdbd2cSJim Jagielski 	{
1401*b1cdbd2cSJim Jagielski 		ParaPortion* pNextPortion = GetNextVisPortion( pPPortion );
1402*b1cdbd2cSJim Jagielski 		if ( pNextPortion )
1403*b1cdbd2cSJim Jagielski 		{
1404*b1cdbd2cSJim Jagielski 			EditLine* pLine = pNextPortion->GetLines().GetObject(0);
1405*b1cdbd2cSJim Jagielski 			DBG_ASSERT( pLine, "Zeile davor nicht gefunden: CursorUp" );
1406*b1cdbd2cSJim Jagielski 			aNewPaM.SetNode( pNextPortion->GetNode() );
1407*b1cdbd2cSJim Jagielski 			// Nie ganz ans Ende wenn mehrere Zeilen, da dann eine
1408*b1cdbd2cSJim Jagielski 			// Zeile darunter der Cursor angezeigt wird.
1409*b1cdbd2cSJim Jagielski 			aNewPaM.SetIndex( GetChar( pNextPortion, pLine, nX+nOnePixelInRef ) );
1410*b1cdbd2cSJim Jagielski 			if ( ( aNewPaM.GetIndex() == pLine->GetEnd() ) && ( aNewPaM.GetIndex() > pLine->GetStart() ) && ( pNextPortion->GetLines().Count() > 1 ) )
1411*b1cdbd2cSJim Jagielski 				aNewPaM = CursorLeft( aNewPaM );
1412*b1cdbd2cSJim Jagielski 		}
1413*b1cdbd2cSJim Jagielski 	}
1414*b1cdbd2cSJim Jagielski 
1415*b1cdbd2cSJim Jagielski 	return aNewPaM;
1416*b1cdbd2cSJim Jagielski }
1417*b1cdbd2cSJim Jagielski 
CursorStartOfLine(const EditPaM & rPaM)1418*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorStartOfLine( const EditPaM& rPaM )
1419*b1cdbd2cSJim Jagielski {
1420*b1cdbd2cSJim Jagielski 	ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() );
1421*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pCurPortion, "Keine Portion fuer den PaM ?" );
1422*b1cdbd2cSJim Jagielski 	sal_uInt16 nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() );
1423*b1cdbd2cSJim Jagielski 	EditLine* pLine = pCurPortion->GetLines().GetObject(nLine);
1424*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pLine, "Aktuelle Zeile nicht gefunden ?!" );
1425*b1cdbd2cSJim Jagielski 
1426*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( rPaM );
1427*b1cdbd2cSJim Jagielski 	aNewPaM.SetIndex( pLine->GetStart() );
1428*b1cdbd2cSJim Jagielski 	return aNewPaM;
1429*b1cdbd2cSJim Jagielski }
1430*b1cdbd2cSJim Jagielski 
CursorEndOfLine(const EditPaM & rPaM)1431*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorEndOfLine( const EditPaM& rPaM )
1432*b1cdbd2cSJim Jagielski {
1433*b1cdbd2cSJim Jagielski 	ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() );
1434*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pCurPortion, "Keine Portion fuer den PaM ?" );
1435*b1cdbd2cSJim Jagielski 	sal_uInt16 nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() );
1436*b1cdbd2cSJim Jagielski 	EditLine* pLine = pCurPortion->GetLines().GetObject(nLine);
1437*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pLine, "Aktuelle Zeile nicht gefunden ?!" );
1438*b1cdbd2cSJim Jagielski 
1439*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( rPaM );
1440*b1cdbd2cSJim Jagielski 	aNewPaM.SetIndex( pLine->GetEnd() );
1441*b1cdbd2cSJim Jagielski 	if ( pLine->GetEnd() > pLine->GetStart() )
1442*b1cdbd2cSJim Jagielski 	{
1443*b1cdbd2cSJim Jagielski //		xub_Unicode cLastChar = aNewPaM.GetNode()->GetChar( aNewPaM.GetIndex()-1 );
1444*b1cdbd2cSJim Jagielski 		if ( aNewPaM.GetNode()->IsFeature( aNewPaM.GetIndex() - 1 ) )
1445*b1cdbd2cSJim Jagielski 		{
1446*b1cdbd2cSJim Jagielski 			// Bei einem weichen Umbruch muss ich davor stehen!
1447*b1cdbd2cSJim Jagielski 			EditCharAttrib* pNextFeature = aNewPaM.GetNode()->GetCharAttribs().FindFeature( aNewPaM.GetIndex()-1 );
1448*b1cdbd2cSJim Jagielski 			if ( pNextFeature && ( pNextFeature->GetItem()->Which() == EE_FEATURE_LINEBR ) )
1449*b1cdbd2cSJim Jagielski 				aNewPaM = CursorLeft( aNewPaM );
1450*b1cdbd2cSJim Jagielski 		}
1451*b1cdbd2cSJim Jagielski 		else if ( ( aNewPaM.GetNode()->GetChar( aNewPaM.GetIndex() - 1 ) == ' ' ) && ( aNewPaM.GetIndex() != aNewPaM.GetNode()->Len() ) )
1452*b1cdbd2cSJim Jagielski 		{
1453*b1cdbd2cSJim Jagielski 			// Bei einem Blank in einer autom. umgebrochenen Zeile macht es Sinn,
1454*b1cdbd2cSJim Jagielski 			// davor zu stehen, da der Anwender hinter das Wort will.
1455*b1cdbd2cSJim Jagielski 			// Wenn diese geaendert wird, Sonderbehandlung fuer Pos1 nach End!
1456*b1cdbd2cSJim Jagielski 			aNewPaM = CursorLeft( aNewPaM );
1457*b1cdbd2cSJim Jagielski 		}
1458*b1cdbd2cSJim Jagielski 	}
1459*b1cdbd2cSJim Jagielski 	return aNewPaM;
1460*b1cdbd2cSJim Jagielski }
1461*b1cdbd2cSJim Jagielski 
CursorStartOfParagraph(const EditPaM & rPaM)1462*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorStartOfParagraph( const EditPaM& rPaM )
1463*b1cdbd2cSJim Jagielski {
1464*b1cdbd2cSJim Jagielski 	EditPaM aPaM( rPaM.GetNode(), 0 );
1465*b1cdbd2cSJim Jagielski 	return aPaM;
1466*b1cdbd2cSJim Jagielski }
1467*b1cdbd2cSJim Jagielski 
CursorEndOfParagraph(const EditPaM & rPaM)1468*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorEndOfParagraph( const EditPaM& rPaM )
1469*b1cdbd2cSJim Jagielski {
1470*b1cdbd2cSJim Jagielski 	EditPaM aPaM( rPaM.GetNode(), rPaM.GetNode()->Len() );
1471*b1cdbd2cSJim Jagielski 	return aPaM;
1472*b1cdbd2cSJim Jagielski }
1473*b1cdbd2cSJim Jagielski 
CursorStartOfDoc()1474*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorStartOfDoc()
1475*b1cdbd2cSJim Jagielski {
1476*b1cdbd2cSJim Jagielski 	EditPaM aPaM( aEditDoc.SaveGetObject( 0 ), 0 );
1477*b1cdbd2cSJim Jagielski 	return aPaM;
1478*b1cdbd2cSJim Jagielski }
1479*b1cdbd2cSJim Jagielski 
CursorEndOfDoc()1480*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::CursorEndOfDoc()
1481*b1cdbd2cSJim Jagielski {
1482*b1cdbd2cSJim Jagielski 	ContentNode* pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count()-1 );
1483*b1cdbd2cSJim Jagielski 	ParaPortion* pLastPortion = GetParaPortions().SaveGetObject( aEditDoc.Count()-1 );
1484*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pLastNode && pLastPortion, "CursorEndOfDoc: Node oder Portion nicht gefunden" );
1485*b1cdbd2cSJim Jagielski 
1486*b1cdbd2cSJim Jagielski 	if ( !pLastPortion->IsVisible() )
1487*b1cdbd2cSJim Jagielski 	{
1488*b1cdbd2cSJim Jagielski 		pLastNode = GetPrevVisNode( pLastPortion->GetNode() );
1489*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pLastNode, "Kein sichtbarer Absatz?" );
1490*b1cdbd2cSJim Jagielski 		if ( !pLastNode )
1491*b1cdbd2cSJim Jagielski 			pLastNode = aEditDoc.SaveGetObject( aEditDoc.Count()-1 );
1492*b1cdbd2cSJim Jagielski 	}
1493*b1cdbd2cSJim Jagielski 
1494*b1cdbd2cSJim Jagielski 	EditPaM aPaM( pLastNode, pLastNode->Len() );
1495*b1cdbd2cSJim Jagielski 	return aPaM;
1496*b1cdbd2cSJim Jagielski }
1497*b1cdbd2cSJim Jagielski 
PageUp(const EditPaM & rPaM,EditView * pView)1498*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::PageUp( const EditPaM& rPaM, EditView* pView )
1499*b1cdbd2cSJim Jagielski {
1500*b1cdbd2cSJim Jagielski 	Rectangle aRec = PaMtoEditCursor( rPaM );
1501*b1cdbd2cSJim Jagielski 	Point aTopLeft = aRec.TopLeft();
1502*b1cdbd2cSJim Jagielski 	aTopLeft.Y() -= pView->GetVisArea().GetHeight() *9/10;
1503*b1cdbd2cSJim Jagielski 	aTopLeft.X() += nOnePixelInRef;
1504*b1cdbd2cSJim Jagielski 	if ( aTopLeft.Y() < 0 )
1505*b1cdbd2cSJim Jagielski 	{
1506*b1cdbd2cSJim Jagielski 		aTopLeft.Y() = 0;
1507*b1cdbd2cSJim Jagielski 	}
1508*b1cdbd2cSJim Jagielski 	return GetPaM( aTopLeft );
1509*b1cdbd2cSJim Jagielski }
1510*b1cdbd2cSJim Jagielski 
PageDown(const EditPaM & rPaM,EditView * pView)1511*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::PageDown( const EditPaM& rPaM, EditView* pView )
1512*b1cdbd2cSJim Jagielski {
1513*b1cdbd2cSJim Jagielski 	Rectangle aRec = PaMtoEditCursor( rPaM );
1514*b1cdbd2cSJim Jagielski 	Point aBottomRight = aRec.BottomRight();
1515*b1cdbd2cSJim Jagielski 	aBottomRight.Y() += pView->GetVisArea().GetHeight() *9/10;
1516*b1cdbd2cSJim Jagielski 	aBottomRight.X() += nOnePixelInRef;
1517*b1cdbd2cSJim Jagielski 	long nHeight = GetTextHeight();
1518*b1cdbd2cSJim Jagielski 	if ( aBottomRight.Y() > nHeight )
1519*b1cdbd2cSJim Jagielski 	{
1520*b1cdbd2cSJim Jagielski 		aBottomRight.Y() = nHeight-2;
1521*b1cdbd2cSJim Jagielski 	}
1522*b1cdbd2cSJim Jagielski 	return GetPaM( aBottomRight );
1523*b1cdbd2cSJim Jagielski }
1524*b1cdbd2cSJim Jagielski 
WordLeft(const EditPaM & rPaM,sal_Int16 nWordType)1525*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::WordLeft( const EditPaM& rPaM, sal_Int16 nWordType )
1526*b1cdbd2cSJim Jagielski {
1527*b1cdbd2cSJim Jagielski 	sal_uInt16 nCurrentPos = rPaM.GetIndex();
1528*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( rPaM );
1529*b1cdbd2cSJim Jagielski 	if ( nCurrentPos == 0 )
1530*b1cdbd2cSJim Jagielski 	{
1531*b1cdbd2cSJim Jagielski 		// Vorheriger Absatz...
1532*b1cdbd2cSJim Jagielski 		sal_uInt16 nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() );
1533*b1cdbd2cSJim Jagielski 		ContentNode* pPrevNode = aEditDoc.SaveGetObject( --nCurPara );
1534*b1cdbd2cSJim Jagielski 		if ( pPrevNode )
1535*b1cdbd2cSJim Jagielski 		{
1536*b1cdbd2cSJim Jagielski 			aNewPaM.SetNode( pPrevNode );
1537*b1cdbd2cSJim Jagielski 			aNewPaM.SetIndex( pPrevNode->Len() );
1538*b1cdbd2cSJim Jagielski 		}
1539*b1cdbd2cSJim Jagielski 	}
1540*b1cdbd2cSJim Jagielski 	else
1541*b1cdbd2cSJim Jagielski 	{
1542*b1cdbd2cSJim Jagielski 		// we need to increase the position by 1 when retrieving the locale
1543*b1cdbd2cSJim Jagielski 		// since the attribute for the char left to the cursor position is returned
1544*b1cdbd2cSJim Jagielski 		EditPaM aTmpPaM( aNewPaM );
1545*b1cdbd2cSJim Jagielski 		xub_StrLen nMax = rPaM.GetNode()->Len();
1546*b1cdbd2cSJim Jagielski 		if ( aTmpPaM.GetIndex() < nMax )
1547*b1cdbd2cSJim Jagielski 			aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
1548*b1cdbd2cSJim Jagielski         lang::Locale aLocale( GetLocale( aTmpPaM ) );
1549*b1cdbd2cSJim Jagielski 
1550*b1cdbd2cSJim Jagielski 		uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1551*b1cdbd2cSJim Jagielski 		i18n::Boundary aBoundary = _xBI->getWordBoundary( *aNewPaM.GetNode(), nCurrentPos, aLocale, nWordType, sal_True );
1552*b1cdbd2cSJim Jagielski 		if ( aBoundary.startPos >= nCurrentPos )
1553*b1cdbd2cSJim Jagielski             aBoundary = _xBI->previousWord( *aNewPaM.GetNode(), nCurrentPos, aLocale, nWordType );
1554*b1cdbd2cSJim Jagielski         aNewPaM.SetIndex( ( aBoundary.startPos != (-1) ) ? (sal_uInt16)aBoundary.startPos : 0 );
1555*b1cdbd2cSJim Jagielski 	}
1556*b1cdbd2cSJim Jagielski 
1557*b1cdbd2cSJim Jagielski 	return aNewPaM;
1558*b1cdbd2cSJim Jagielski }
1559*b1cdbd2cSJim Jagielski 
WordRight(const EditPaM & rPaM,sal_Int16 nWordType)1560*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::WordRight( const EditPaM& rPaM, sal_Int16 nWordType )
1561*b1cdbd2cSJim Jagielski {
1562*b1cdbd2cSJim Jagielski 	xub_StrLen nMax = rPaM.GetNode()->Len();
1563*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( rPaM );
1564*b1cdbd2cSJim Jagielski 	if ( aNewPaM.GetIndex() < nMax )
1565*b1cdbd2cSJim Jagielski 	{
1566*b1cdbd2cSJim Jagielski 		// we need to increase the position by 1 when retrieving the locale
1567*b1cdbd2cSJim Jagielski 		// since the attribute for the char left to the cursor position is returned
1568*b1cdbd2cSJim Jagielski 		EditPaM aTmpPaM( aNewPaM );
1569*b1cdbd2cSJim Jagielski         aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
1570*b1cdbd2cSJim Jagielski         lang::Locale aLocale( GetLocale( aTmpPaM ) );
1571*b1cdbd2cSJim Jagielski 
1572*b1cdbd2cSJim Jagielski 		uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1573*b1cdbd2cSJim Jagielski         i18n::Boundary aBoundary = _xBI->nextWord( *aNewPaM.GetNode(), aNewPaM.GetIndex(), aLocale, nWordType );
1574*b1cdbd2cSJim Jagielski 		aNewPaM.SetIndex( (sal_uInt16)aBoundary.startPos );
1575*b1cdbd2cSJim Jagielski 	}
1576*b1cdbd2cSJim Jagielski 	// not 'else', maybe the index reached nMax now...
1577*b1cdbd2cSJim Jagielski 	if ( aNewPaM.GetIndex() >= nMax )
1578*b1cdbd2cSJim Jagielski 	{
1579*b1cdbd2cSJim Jagielski 		// Naechster Absatz...
1580*b1cdbd2cSJim Jagielski 		sal_uInt16 nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() );
1581*b1cdbd2cSJim Jagielski 		ContentNode* pNextNode = aEditDoc.SaveGetObject( ++nCurPara );
1582*b1cdbd2cSJim Jagielski 		if ( pNextNode )
1583*b1cdbd2cSJim Jagielski 		{
1584*b1cdbd2cSJim Jagielski 			aNewPaM.SetNode( pNextNode );
1585*b1cdbd2cSJim Jagielski 			aNewPaM.SetIndex( 0 );
1586*b1cdbd2cSJim Jagielski 		}
1587*b1cdbd2cSJim Jagielski 	}
1588*b1cdbd2cSJim Jagielski 	return aNewPaM;
1589*b1cdbd2cSJim Jagielski }
1590*b1cdbd2cSJim Jagielski 
StartOfWord(const EditPaM & rPaM,sal_Int16 nWordType)1591*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::StartOfWord( const EditPaM& rPaM, sal_Int16 nWordType )
1592*b1cdbd2cSJim Jagielski {
1593*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( rPaM );
1594*b1cdbd2cSJim Jagielski 
1595*b1cdbd2cSJim Jagielski 	// we need to increase the position by 1 when retrieving the locale
1596*b1cdbd2cSJim Jagielski 	// since the attribute for the char left to the cursor position is returned
1597*b1cdbd2cSJim Jagielski 	EditPaM aTmpPaM( aNewPaM );
1598*b1cdbd2cSJim Jagielski 	xub_StrLen nMax = rPaM.GetNode()->Len();
1599*b1cdbd2cSJim Jagielski 	if ( aTmpPaM.GetIndex() < nMax )
1600*b1cdbd2cSJim Jagielski 		aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
1601*b1cdbd2cSJim Jagielski     lang::Locale aLocale( GetLocale( aTmpPaM ) );
1602*b1cdbd2cSJim Jagielski 
1603*b1cdbd2cSJim Jagielski 	uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1604*b1cdbd2cSJim Jagielski 	i18n::Boundary aBoundary = _xBI->getWordBoundary( *rPaM.GetNode(), rPaM.GetIndex(), aLocale, nWordType, sal_True );
1605*b1cdbd2cSJim Jagielski 	aNewPaM.SetIndex( (sal_uInt16)aBoundary.startPos );
1606*b1cdbd2cSJim Jagielski 	return aNewPaM;
1607*b1cdbd2cSJim Jagielski }
1608*b1cdbd2cSJim Jagielski 
EndOfWord(const EditPaM & rPaM,sal_Int16 nWordType)1609*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::EndOfWord( const EditPaM& rPaM, sal_Int16 nWordType )
1610*b1cdbd2cSJim Jagielski {
1611*b1cdbd2cSJim Jagielski 	EditPaM aNewPaM( rPaM );
1612*b1cdbd2cSJim Jagielski 
1613*b1cdbd2cSJim Jagielski 	// we need to increase the position by 1 when retrieving the locale
1614*b1cdbd2cSJim Jagielski 	// since the attribute for the char left to the cursor position is returned
1615*b1cdbd2cSJim Jagielski 	EditPaM aTmpPaM( aNewPaM );
1616*b1cdbd2cSJim Jagielski 	xub_StrLen nMax = rPaM.GetNode()->Len();
1617*b1cdbd2cSJim Jagielski 	if ( aTmpPaM.GetIndex() < nMax )
1618*b1cdbd2cSJim Jagielski 		aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
1619*b1cdbd2cSJim Jagielski     lang::Locale aLocale( GetLocale( aTmpPaM ) );
1620*b1cdbd2cSJim Jagielski 
1621*b1cdbd2cSJim Jagielski 	uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1622*b1cdbd2cSJim Jagielski 	i18n::Boundary aBoundary = _xBI->getWordBoundary( *rPaM.GetNode(), rPaM.GetIndex(), aLocale, nWordType, sal_True );
1623*b1cdbd2cSJim Jagielski 	aNewPaM.SetIndex( (sal_uInt16)aBoundary.endPos );
1624*b1cdbd2cSJim Jagielski 	return aNewPaM;
1625*b1cdbd2cSJim Jagielski }
1626*b1cdbd2cSJim Jagielski 
SelectWord(const EditSelection & rCurSel,sal_Int16 nWordType,sal_Bool bAcceptStartOfWord)1627*b1cdbd2cSJim Jagielski EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 nWordType, sal_Bool bAcceptStartOfWord )
1628*b1cdbd2cSJim Jagielski {
1629*b1cdbd2cSJim Jagielski     EditSelection aNewSel( rCurSel );
1630*b1cdbd2cSJim Jagielski 	EditPaM aPaM( rCurSel.Max() );
1631*b1cdbd2cSJim Jagielski 
1632*b1cdbd2cSJim Jagielski 	// we need to increase the position by 1 when retrieving the locale
1633*b1cdbd2cSJim Jagielski 	// since the attribute for the char left to the cursor position is returned
1634*b1cdbd2cSJim Jagielski 	EditPaM aTmpPaM( aPaM );
1635*b1cdbd2cSJim Jagielski 	xub_StrLen nMax = aPaM.GetNode()->Len();
1636*b1cdbd2cSJim Jagielski 	if ( aTmpPaM.GetIndex() < nMax )
1637*b1cdbd2cSJim Jagielski 		aTmpPaM.SetIndex( aTmpPaM.GetIndex() + 1 );
1638*b1cdbd2cSJim Jagielski     lang::Locale aLocale( GetLocale( aTmpPaM ) );
1639*b1cdbd2cSJim Jagielski 
1640*b1cdbd2cSJim Jagielski 	uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1641*b1cdbd2cSJim Jagielski     sal_Int16 nType = _xBI->getWordType( *aPaM.GetNode(), aPaM.GetIndex(), aLocale );
1642*b1cdbd2cSJim Jagielski 	if ( nType == i18n::WordType::ANY_WORD )
1643*b1cdbd2cSJim Jagielski 	{
1644*b1cdbd2cSJim Jagielski 		i18n::Boundary aBoundary = _xBI->getWordBoundary( *aPaM.GetNode(), aPaM.GetIndex(), aLocale, nWordType, sal_True );
1645*b1cdbd2cSJim Jagielski 		// don't select when curser at end of word
1646*b1cdbd2cSJim Jagielski 		if ( ( aBoundary.endPos > aPaM.GetIndex() ) &&
1647*b1cdbd2cSJim Jagielski 			 ( ( aBoundary.startPos < aPaM.GetIndex() ) || ( bAcceptStartOfWord && ( aBoundary.startPos == aPaM.GetIndex() ) ) ) )
1648*b1cdbd2cSJim Jagielski 		{
1649*b1cdbd2cSJim Jagielski 			aNewSel.Min().SetIndex( (sal_uInt16)aBoundary.startPos );
1650*b1cdbd2cSJim Jagielski 			aNewSel.Max().SetIndex( (sal_uInt16)aBoundary.endPos );
1651*b1cdbd2cSJim Jagielski 		}
1652*b1cdbd2cSJim Jagielski 	}
1653*b1cdbd2cSJim Jagielski 
1654*b1cdbd2cSJim Jagielski 	return aNewSel;
1655*b1cdbd2cSJim Jagielski }
1656*b1cdbd2cSJim Jagielski 
SelectSentence(const EditSelection & rCurSel)1657*b1cdbd2cSJim Jagielski EditSelection ImpEditEngine::SelectSentence( const EditSelection& rCurSel )
1658*b1cdbd2cSJim Jagielski {
1659*b1cdbd2cSJim Jagielski     uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1660*b1cdbd2cSJim Jagielski     const EditPaM& rPaM = rCurSel.Min();
1661*b1cdbd2cSJim Jagielski     const ContentNode* pNode = rPaM.GetNode();
1662*b1cdbd2cSJim Jagielski     // #i50710# line breaks are marked with 0x01 - the break iterator prefers 0x0a for that
1663*b1cdbd2cSJim Jagielski     String sParagraph(*pNode);
1664*b1cdbd2cSJim Jagielski     sParagraph.SearchAndReplaceAll(0x01,0x0a);
1665*b1cdbd2cSJim Jagielski     //return Null if search starts at the beginning of the string
1666*b1cdbd2cSJim Jagielski     long nStart = rPaM.GetIndex() ? _xBI->beginOfSentence( sParagraph, rPaM.GetIndex(), GetLocale( rPaM ) ) : 0;
1667*b1cdbd2cSJim Jagielski 
1668*b1cdbd2cSJim Jagielski     long nEnd = _xBI->endOfSentence( *pNode, rPaM.GetIndex(), GetLocale( rPaM ) );
1669*b1cdbd2cSJim Jagielski     EditSelection aNewSel( rCurSel );
1670*b1cdbd2cSJim Jagielski     DBG_ASSERT(nStart < pNode->Len() && nEnd <= pNode->Len(), "sentence indices out of range");
1671*b1cdbd2cSJim Jagielski     aNewSel.Min().SetIndex( (sal_uInt16)nStart );
1672*b1cdbd2cSJim Jagielski     aNewSel.Max().SetIndex( (sal_uInt16)nEnd );
1673*b1cdbd2cSJim Jagielski     return aNewSel;
1674*b1cdbd2cSJim Jagielski }
1675*b1cdbd2cSJim Jagielski 
IsInputSequenceCheckingRequired(sal_Unicode nChar,const EditSelection & rCurSel) const1676*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::IsInputSequenceCheckingRequired( sal_Unicode nChar, const EditSelection& rCurSel ) const
1677*b1cdbd2cSJim Jagielski {
1678*b1cdbd2cSJim Jagielski     uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1679*b1cdbd2cSJim Jagielski     if (!pCTLOptions)
1680*b1cdbd2cSJim Jagielski         pCTLOptions = new SvtCTLOptions;
1681*b1cdbd2cSJim Jagielski 
1682*b1cdbd2cSJim Jagielski     // get the index that really is first
1683*b1cdbd2cSJim Jagielski     sal_uInt16 nFirstPos = rCurSel.Min().GetIndex();
1684*b1cdbd2cSJim Jagielski     sal_uInt16 nMaxPos   = rCurSel.Max().GetIndex();
1685*b1cdbd2cSJim Jagielski     if (nMaxPos < nFirstPos)
1686*b1cdbd2cSJim Jagielski         nFirstPos = nMaxPos;
1687*b1cdbd2cSJim Jagielski 
1688*b1cdbd2cSJim Jagielski     sal_Bool bIsSequenceChecking =
1689*b1cdbd2cSJim Jagielski         pCTLOptions->IsCTLFontEnabled() &&
1690*b1cdbd2cSJim Jagielski         pCTLOptions->IsCTLSequenceChecking() &&
1691*b1cdbd2cSJim Jagielski         nFirstPos != 0 && /* first char needs not to be checked */
1692*b1cdbd2cSJim Jagielski         _xBI.is() && i18n::ScriptType::COMPLEX == _xBI->getScriptType( rtl::OUString( nChar ), 0 );
1693*b1cdbd2cSJim Jagielski 
1694*b1cdbd2cSJim Jagielski     return bIsSequenceChecking;
1695*b1cdbd2cSJim Jagielski }
1696*b1cdbd2cSJim Jagielski 
1697*b1cdbd2cSJim Jagielski /*************************************************************************
1698*b1cdbd2cSJim Jagielski  *                 lcl_HasStrongLTR
1699*b1cdbd2cSJim Jagielski  *************************************************************************/
lcl_HasStrongLTR(const String & rTxt,xub_StrLen nStart,xub_StrLen nEnd)1700*b1cdbd2cSJim Jagielski  bool lcl_HasStrongLTR ( const String& rTxt, xub_StrLen nStart, xub_StrLen nEnd )
1701*b1cdbd2cSJim Jagielski  {
1702*b1cdbd2cSJim Jagielski      for ( xub_StrLen nCharIdx = nStart; nCharIdx < nEnd; ++nCharIdx )
1703*b1cdbd2cSJim Jagielski      {
1704*b1cdbd2cSJim Jagielski          const UCharDirection nCharDir = u_charDirection ( rTxt.GetChar ( nCharIdx ));
1705*b1cdbd2cSJim Jagielski          if ( nCharDir == U_LEFT_TO_RIGHT ||
1706*b1cdbd2cSJim Jagielski               nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
1707*b1cdbd2cSJim Jagielski               nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
1708*b1cdbd2cSJim Jagielski              return true;
1709*b1cdbd2cSJim Jagielski      }
1710*b1cdbd2cSJim Jagielski      return false;
1711*b1cdbd2cSJim Jagielski  }
1712*b1cdbd2cSJim Jagielski 
1713*b1cdbd2cSJim Jagielski 
1714*b1cdbd2cSJim Jagielski 
InitScriptTypes(sal_uInt16 nPara)1715*b1cdbd2cSJim Jagielski void ImpEditEngine::InitScriptTypes( sal_uInt16 nPara )
1716*b1cdbd2cSJim Jagielski {
1717*b1cdbd2cSJim Jagielski 	ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
1718*b1cdbd2cSJim Jagielski 	ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
1719*b1cdbd2cSJim Jagielski 	rTypes.clear();
1720*b1cdbd2cSJim Jagielski 
1721*b1cdbd2cSJim Jagielski 	ContentNode* pNode = pParaPortion->GetNode();
1722*b1cdbd2cSJim Jagielski 	if ( pNode->Len() )
1723*b1cdbd2cSJim Jagielski 	{
1724*b1cdbd2cSJim Jagielski 		uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
1725*b1cdbd2cSJim Jagielski 
1726*b1cdbd2cSJim Jagielski 		String aText( *pNode );
1727*b1cdbd2cSJim Jagielski 
1728*b1cdbd2cSJim Jagielski 		// To handle fields put the character from the field in the string,
1729*b1cdbd2cSJim Jagielski 		// because endOfScript( ... ) will skip the CH_FEATURE, because this is WEAK
1730*b1cdbd2cSJim Jagielski 		EditCharAttrib* pField = pNode->GetCharAttribs().FindNextAttrib( EE_FEATURE_FIELD, 0 );
1731*b1cdbd2cSJim Jagielski 		while ( pField )
1732*b1cdbd2cSJim Jagielski 		{
1733*b1cdbd2cSJim Jagielski 			::rtl::OUString aFldText( ((EditCharAttribField*)pField)->GetFieldValue() );
1734*b1cdbd2cSJim Jagielski 			if ( aFldText.getLength() )
1735*b1cdbd2cSJim Jagielski 			{
1736*b1cdbd2cSJim Jagielski 				aText.SetChar( pField->GetStart(), aFldText.getStr()[0] );
1737*b1cdbd2cSJim Jagielski 				short nFldScriptType = _xBI->getScriptType( aFldText, 0 );
1738*b1cdbd2cSJim Jagielski 
1739*b1cdbd2cSJim Jagielski 				for ( sal_uInt16 nCharInField = 1; nCharInField < aFldText.getLength(); nCharInField++ )
1740*b1cdbd2cSJim Jagielski 				{
1741*b1cdbd2cSJim Jagielski 					short nTmpType = _xBI->getScriptType( aFldText, nCharInField );
1742*b1cdbd2cSJim Jagielski 
1743*b1cdbd2cSJim Jagielski 					// First char from field wins...
1744*b1cdbd2cSJim Jagielski 					if ( nFldScriptType == i18n::ScriptType::WEAK )
1745*b1cdbd2cSJim Jagielski 					{
1746*b1cdbd2cSJim Jagielski 						nFldScriptType = nTmpType;
1747*b1cdbd2cSJim Jagielski 						aText.SetChar( pField->GetStart(), aFldText.getStr()[nCharInField] );
1748*b1cdbd2cSJim Jagielski 					}
1749*b1cdbd2cSJim Jagielski 
1750*b1cdbd2cSJim Jagielski 					// ...  but if the first one is LATIN, and there are CJK or CTL chars too,
1751*b1cdbd2cSJim Jagielski 					// we prefer that ScripType because we need an other font.
1752*b1cdbd2cSJim Jagielski 					if ( ( nTmpType == i18n::ScriptType::ASIAN ) || ( nTmpType == i18n::ScriptType::COMPLEX ) )
1753*b1cdbd2cSJim Jagielski 					{
1754*b1cdbd2cSJim Jagielski 						aText.SetChar( pField->GetStart(), aFldText.getStr()[nCharInField] );
1755*b1cdbd2cSJim Jagielski 						break;
1756*b1cdbd2cSJim Jagielski 					}
1757*b1cdbd2cSJim Jagielski 				}
1758*b1cdbd2cSJim Jagielski 			}
1759*b1cdbd2cSJim Jagielski 			// #112831# Last Field might go from 0xffff to 0x0000
1760*b1cdbd2cSJim Jagielski 			pField = pField->GetEnd() ? pNode->GetCharAttribs().FindNextAttrib( EE_FEATURE_FIELD, pField->GetEnd() ) : NULL;
1761*b1cdbd2cSJim Jagielski 		}
1762*b1cdbd2cSJim Jagielski 
1763*b1cdbd2cSJim Jagielski 		::rtl::OUString aOUText( aText );
1764*b1cdbd2cSJim Jagielski 		sal_uInt16 nTextLen = (sal_uInt16)aOUText.getLength();
1765*b1cdbd2cSJim Jagielski 
1766*b1cdbd2cSJim Jagielski 		sal_Int32 nPos = 0;
1767*b1cdbd2cSJim Jagielski 		short nScriptType = _xBI->getScriptType( aOUText, nPos );
1768*b1cdbd2cSJim Jagielski 		rTypes.push_back( ScriptTypePosInfo( nScriptType, (sal_uInt16)nPos, nTextLen ) );
1769*b1cdbd2cSJim Jagielski 		nPos = _xBI->endOfScript( aOUText, nPos, nScriptType );
1770*b1cdbd2cSJim Jagielski 		while ( ( nPos != (-1) ) && ( nPos < nTextLen ) )
1771*b1cdbd2cSJim Jagielski 		{
1772*b1cdbd2cSJim Jagielski 			rTypes.back().nEndPos = (sal_uInt16)nPos;
1773*b1cdbd2cSJim Jagielski 
1774*b1cdbd2cSJim Jagielski             nScriptType = _xBI->getScriptType( aOUText, nPos );
1775*b1cdbd2cSJim Jagielski 			long nEndPos = _xBI->endOfScript( aOUText, nPos, nScriptType );
1776*b1cdbd2cSJim Jagielski 
1777*b1cdbd2cSJim Jagielski             if ( ( nScriptType == i18n::ScriptType::WEAK ) || ( nScriptType == rTypes.back().nScriptType ) )
1778*b1cdbd2cSJim Jagielski             {
1779*b1cdbd2cSJim Jagielski                 // Expand last ScriptTypePosInfo, don't create weak or unecessary portions
1780*b1cdbd2cSJim Jagielski                 rTypes.back().nEndPos = (sal_uInt16)nEndPos;
1781*b1cdbd2cSJim Jagielski             }
1782*b1cdbd2cSJim Jagielski             else
1783*b1cdbd2cSJim Jagielski             {
1784*b1cdbd2cSJim Jagielski                 if ( _xBI->getScriptType( aOUText, nPos - 1 ) == i18n::ScriptType::WEAK )
1785*b1cdbd2cSJim Jagielski                 {
1786*b1cdbd2cSJim Jagielski                     switch ( u_charType(aOUText.iterateCodePoints(&nPos, 0) ) ) {
1787*b1cdbd2cSJim Jagielski                     case U_NON_SPACING_MARK:
1788*b1cdbd2cSJim Jagielski                     case U_ENCLOSING_MARK:
1789*b1cdbd2cSJim Jagielski                     case U_COMBINING_SPACING_MARK:
1790*b1cdbd2cSJim Jagielski                         --nPos;
1791*b1cdbd2cSJim Jagielski                         rTypes.back().nEndPos--;
1792*b1cdbd2cSJim Jagielski                         break;
1793*b1cdbd2cSJim Jagielski                     }
1794*b1cdbd2cSJim Jagielski                 }
1795*b1cdbd2cSJim Jagielski 			    rTypes.push_back( ScriptTypePosInfo( nScriptType, (sal_uInt16)nPos, nTextLen ) );
1796*b1cdbd2cSJim Jagielski             }
1797*b1cdbd2cSJim Jagielski 
1798*b1cdbd2cSJim Jagielski 			nPos = nEndPos;
1799*b1cdbd2cSJim Jagielski 		}
1800*b1cdbd2cSJim Jagielski 
1801*b1cdbd2cSJim Jagielski 		if ( rTypes[0].nScriptType == i18n::ScriptType::WEAK )
1802*b1cdbd2cSJim Jagielski 			rTypes[0].nScriptType = ( rTypes.size() > 1 ) ? rTypes[1].nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
1803*b1cdbd2cSJim Jagielski 
1804*b1cdbd2cSJim Jagielski 		// create writing direction information:
1805*b1cdbd2cSJim Jagielski 		if ( pParaPortion->aWritingDirectionInfos.empty() )
1806*b1cdbd2cSJim Jagielski 			InitWritingDirections( nPara );
1807*b1cdbd2cSJim Jagielski 
1808*b1cdbd2cSJim Jagielski 		// i89825: Use CTL font for numbers embedded into an RTL run:
1809*b1cdbd2cSJim Jagielski         WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos;
1810*b1cdbd2cSJim Jagielski         for ( size_t n = 0; n < rDirInfos.size(); ++n )
1811*b1cdbd2cSJim Jagielski         {
1812*b1cdbd2cSJim Jagielski             const xub_StrLen nStart = rDirInfos[n].nStartPos;
1813*b1cdbd2cSJim Jagielski             const xub_StrLen nEnd   = rDirInfos[n].nEndPos;
1814*b1cdbd2cSJim Jagielski             const sal_uInt8 nCurrDirType = rDirInfos[n].nType;
1815*b1cdbd2cSJim Jagielski 
1816*b1cdbd2cSJim Jagielski             if ( nCurrDirType % 2 == UBIDI_RTL  || // text in RTL run
1817*b1cdbd2cSJim Jagielski                 ( nCurrDirType > UBIDI_LTR && !lcl_HasStrongLTR( aText, nStart, nEnd ) ) ) // non-strong text in embedded LTR run
1818*b1cdbd2cSJim Jagielski             {
1819*b1cdbd2cSJim Jagielski                 size_t nIdx = 0;
1820*b1cdbd2cSJim Jagielski 
1821*b1cdbd2cSJim Jagielski                 // Skip entries in ScriptArray which are not inside the RTL run:
1822*b1cdbd2cSJim Jagielski                 while ( nIdx < rTypes.size() && rTypes[nIdx].nStartPos < nStart )
1823*b1cdbd2cSJim Jagielski                     ++nIdx;
1824*b1cdbd2cSJim Jagielski 
1825*b1cdbd2cSJim Jagielski                 // Remove any entries *inside* the current run:
1826*b1cdbd2cSJim Jagielski                 while ( nIdx < rTypes.size() && rTypes[nIdx].nEndPos <= nEnd )
1827*b1cdbd2cSJim Jagielski                     rTypes.erase( rTypes.begin()+nIdx );
1828*b1cdbd2cSJim Jagielski 
1829*b1cdbd2cSJim Jagielski                 // special case:
1830*b1cdbd2cSJim Jagielski                 if(nIdx < rTypes.size() && rTypes[nIdx].nStartPos < nStart && rTypes[nIdx].nEndPos > nEnd)
1831*b1cdbd2cSJim Jagielski                 {
1832*b1cdbd2cSJim Jagielski                     rTypes.insert( rTypes.begin()+nIdx, ScriptTypePosInfo( rTypes[nIdx].nScriptType, (sal_uInt16)nEnd, rTypes[nIdx].nEndPos ) );
1833*b1cdbd2cSJim Jagielski                     rTypes[nIdx].nEndPos = nStart;
1834*b1cdbd2cSJim Jagielski                 }
1835*b1cdbd2cSJim Jagielski 
1836*b1cdbd2cSJim Jagielski                 if( nIdx )
1837*b1cdbd2cSJim Jagielski                     rTypes[nIdx - 1].nEndPos = nStart;
1838*b1cdbd2cSJim Jagielski 
1839*b1cdbd2cSJim Jagielski                 rTypes.insert( rTypes.begin()+nIdx, ScriptTypePosInfo( i18n::ScriptType::COMPLEX, (sal_uInt16)nStart, (sal_uInt16)nEnd) );
1840*b1cdbd2cSJim Jagielski                 ++nIdx;
1841*b1cdbd2cSJim Jagielski 
1842*b1cdbd2cSJim Jagielski                 if( nIdx < rTypes.size() )
1843*b1cdbd2cSJim Jagielski                     rTypes[nIdx].nStartPos = nEnd;
1844*b1cdbd2cSJim Jagielski             }
1845*b1cdbd2cSJim Jagielski         }
1846*b1cdbd2cSJim Jagielski 
1847*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
1848*b1cdbd2cSJim Jagielski         sal_uInt16 nDebugStt = 0;
1849*b1cdbd2cSJim Jagielski         sal_uInt16 nDebugEnd = 0;
1850*b1cdbd2cSJim Jagielski         short nDebugType = 0;
1851*b1cdbd2cSJim Jagielski         for ( size_t n = 0; n < rTypes.size(); ++n )
1852*b1cdbd2cSJim Jagielski         {
1853*b1cdbd2cSJim Jagielski             nDebugStt  = rTypes[n].nStartPos;
1854*b1cdbd2cSJim Jagielski             nDebugEnd  = rTypes[n].nEndPos;
1855*b1cdbd2cSJim Jagielski             nDebugType = rTypes[n].nScriptType;
1856*b1cdbd2cSJim Jagielski         }
1857*b1cdbd2cSJim Jagielski #endif
1858*b1cdbd2cSJim Jagielski     }
1859*b1cdbd2cSJim Jagielski }
1860*b1cdbd2cSJim Jagielski 
GetScriptType(const EditPaM & rPaM,sal_uInt16 * pEndPos) const1861*b1cdbd2cSJim Jagielski sal_uInt16 ImpEditEngine::GetScriptType( const EditPaM& rPaM, sal_uInt16* pEndPos ) const
1862*b1cdbd2cSJim Jagielski {
1863*b1cdbd2cSJim Jagielski 	sal_uInt16 nScriptType = 0;
1864*b1cdbd2cSJim Jagielski 
1865*b1cdbd2cSJim Jagielski 	if ( pEndPos )
1866*b1cdbd2cSJim Jagielski 		*pEndPos = rPaM.GetNode()->Len();
1867*b1cdbd2cSJim Jagielski 
1868*b1cdbd2cSJim Jagielski 	if ( rPaM.GetNode()->Len() )
1869*b1cdbd2cSJim Jagielski 	{
1870*b1cdbd2cSJim Jagielski  		sal_uInt16 nPara = GetEditDoc().GetPos( rPaM.GetNode() );
1871*b1cdbd2cSJim Jagielski 		ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
1872*b1cdbd2cSJim Jagielski 		if ( pParaPortion->aScriptInfos.empty() )
1873*b1cdbd2cSJim Jagielski 			((ImpEditEngine*)this)->InitScriptTypes( nPara );
1874*b1cdbd2cSJim Jagielski 
1875*b1cdbd2cSJim Jagielski 		ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
1876*b1cdbd2cSJim Jagielski 		sal_uInt16 nPos = rPaM.GetIndex();
1877*b1cdbd2cSJim Jagielski 		for ( size_t n = 0; n < rTypes.size(); n++ )
1878*b1cdbd2cSJim Jagielski 		{
1879*b1cdbd2cSJim Jagielski 			if ( ( rTypes[n].nStartPos <= nPos ) && ( rTypes[n].nEndPos >= nPos ) )
1880*b1cdbd2cSJim Jagielski 	   		{
1881*b1cdbd2cSJim Jagielski 				nScriptType = rTypes[n].nScriptType;
1882*b1cdbd2cSJim Jagielski 				if( pEndPos )
1883*b1cdbd2cSJim Jagielski 					*pEndPos = rTypes[n].nEndPos;
1884*b1cdbd2cSJim Jagielski 				break;
1885*b1cdbd2cSJim Jagielski 			}
1886*b1cdbd2cSJim Jagielski 		}
1887*b1cdbd2cSJim Jagielski 	}
1888*b1cdbd2cSJim Jagielski 	return nScriptType ? nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
1889*b1cdbd2cSJim Jagielski }
1890*b1cdbd2cSJim Jagielski 
GetScriptType(const EditSelection & rSel) const1891*b1cdbd2cSJim Jagielski sal_uInt16 ImpEditEngine::GetScriptType( const EditSelection& rSel ) const
1892*b1cdbd2cSJim Jagielski {
1893*b1cdbd2cSJim Jagielski 	EditSelection aSel( rSel );
1894*b1cdbd2cSJim Jagielski 	aSel.Adjust( aEditDoc );
1895*b1cdbd2cSJim Jagielski 
1896*b1cdbd2cSJim Jagielski 	short nScriptType = 0;
1897*b1cdbd2cSJim Jagielski 
1898*b1cdbd2cSJim Jagielski  	sal_uInt16 nStartPara = GetEditDoc().GetPos( aSel.Min().GetNode() );
1899*b1cdbd2cSJim Jagielski  	sal_uInt16 nEndPara = GetEditDoc().GetPos( aSel.Max().GetNode() );
1900*b1cdbd2cSJim Jagielski 
1901*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nPara = nStartPara; nPara <= nEndPara; nPara++ )
1902*b1cdbd2cSJim Jagielski 	{
1903*b1cdbd2cSJim Jagielski 		ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
1904*b1cdbd2cSJim Jagielski 		if ( pParaPortion->aScriptInfos.empty() )
1905*b1cdbd2cSJim Jagielski 			((ImpEditEngine*)this)->InitScriptTypes( nPara );
1906*b1cdbd2cSJim Jagielski 
1907*b1cdbd2cSJim Jagielski 		ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
1908*b1cdbd2cSJim Jagielski 
1909*b1cdbd2cSJim Jagielski 		// find the first(!) script type position that holds the
1910*b1cdbd2cSJim Jagielski 		// complete selection. Thus it will work for selections as
1911*b1cdbd2cSJim Jagielski 		// well as with just moving the cursor from char to char.
1912*b1cdbd2cSJim Jagielski 		sal_uInt16 nS = ( nPara == nStartPara ) ? aSel.Min().GetIndex() : 0;
1913*b1cdbd2cSJim Jagielski 		sal_uInt16 nE = ( nPara == nEndPara ) ? aSel.Max().GetIndex() : pParaPortion->GetNode()->Len();
1914*b1cdbd2cSJim Jagielski 		for ( size_t n = 0; n < rTypes.size(); n++ )
1915*b1cdbd2cSJim Jagielski 		{
1916*b1cdbd2cSJim Jagielski             if (rTypes[n].nStartPos <= nS  &&  nE <= rTypes[n].nEndPos)
1917*b1cdbd2cSJim Jagielski 		   	{
1918*b1cdbd2cSJim Jagielski 				if ( rTypes[n].nScriptType != i18n::ScriptType::WEAK )
1919*b1cdbd2cSJim Jagielski 				{
1920*b1cdbd2cSJim Jagielski                     nScriptType |= GetItemScriptType ( rTypes[n].nScriptType );
1921*b1cdbd2cSJim Jagielski                 }
1922*b1cdbd2cSJim Jagielski                 else
1923*b1cdbd2cSJim Jagielski 				{
1924*b1cdbd2cSJim Jagielski                     if ( !nScriptType && n )
1925*b1cdbd2cSJim Jagielski                     {
1926*b1cdbd2cSJim Jagielski                         // #93548# When starting with WEAK, use prev ScriptType...
1927*b1cdbd2cSJim Jagielski                         nScriptType = rTypes[n-1].nScriptType;
1928*b1cdbd2cSJim Jagielski                     }
1929*b1cdbd2cSJim Jagielski 				}
1930*b1cdbd2cSJim Jagielski 				break;
1931*b1cdbd2cSJim Jagielski 			}
1932*b1cdbd2cSJim Jagielski 		}
1933*b1cdbd2cSJim Jagielski 	}
1934*b1cdbd2cSJim Jagielski 	return nScriptType ? nScriptType : GetI18NScriptTypeOfLanguage( GetDefaultLanguage() );
1935*b1cdbd2cSJim Jagielski }
1936*b1cdbd2cSJim Jagielski 
IsScriptChange(const EditPaM & rPaM) const1937*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::IsScriptChange( const EditPaM& rPaM ) const
1938*b1cdbd2cSJim Jagielski {
1939*b1cdbd2cSJim Jagielski 	sal_Bool bScriptChange = sal_False;
1940*b1cdbd2cSJim Jagielski 
1941*b1cdbd2cSJim Jagielski 	if ( rPaM.GetNode()->Len() )
1942*b1cdbd2cSJim Jagielski 	{
1943*b1cdbd2cSJim Jagielski 		sal_uInt16 nPara = GetEditDoc().GetPos( rPaM.GetNode() );
1944*b1cdbd2cSJim Jagielski 		ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
1945*b1cdbd2cSJim Jagielski 		if ( pParaPortion->aScriptInfos.empty() )
1946*b1cdbd2cSJim Jagielski 			((ImpEditEngine*)this)->InitScriptTypes( nPara );
1947*b1cdbd2cSJim Jagielski 
1948*b1cdbd2cSJim Jagielski 		ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
1949*b1cdbd2cSJim Jagielski 		sal_uInt16 nPos = rPaM.GetIndex();
1950*b1cdbd2cSJim Jagielski 		for ( size_t n = 0; n < rTypes.size(); n++ )
1951*b1cdbd2cSJim Jagielski 		{
1952*b1cdbd2cSJim Jagielski 			if ( rTypes[n].nStartPos == nPos )
1953*b1cdbd2cSJim Jagielski 	   		{
1954*b1cdbd2cSJim Jagielski 				bScriptChange = sal_True;
1955*b1cdbd2cSJim Jagielski 				break;
1956*b1cdbd2cSJim Jagielski 			}
1957*b1cdbd2cSJim Jagielski 		}
1958*b1cdbd2cSJim Jagielski 	}
1959*b1cdbd2cSJim Jagielski 	return bScriptChange;
1960*b1cdbd2cSJim Jagielski }
1961*b1cdbd2cSJim Jagielski 
HasScriptType(sal_uInt16 nPara,sal_uInt16 nType) const1962*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::HasScriptType( sal_uInt16 nPara, sal_uInt16 nType ) const
1963*b1cdbd2cSJim Jagielski {
1964*b1cdbd2cSJim Jagielski     sal_Bool bTypeFound = sal_False;
1965*b1cdbd2cSJim Jagielski 
1966*b1cdbd2cSJim Jagielski 	ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
1967*b1cdbd2cSJim Jagielski 	if ( pParaPortion->aScriptInfos.empty() )
1968*b1cdbd2cSJim Jagielski 		((ImpEditEngine*)this)->InitScriptTypes( nPara );
1969*b1cdbd2cSJim Jagielski 
1970*b1cdbd2cSJim Jagielski     ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
1971*b1cdbd2cSJim Jagielski 	for ( size_t n = rTypes.size(); n && !bTypeFound; )
1972*b1cdbd2cSJim Jagielski 	{
1973*b1cdbd2cSJim Jagielski 	    if ( rTypes[--n].nScriptType == nType )
1974*b1cdbd2cSJim Jagielski                 bTypeFound = sal_True;
1975*b1cdbd2cSJim Jagielski     }
1976*b1cdbd2cSJim Jagielski     return bTypeFound;
1977*b1cdbd2cSJim Jagielski }
1978*b1cdbd2cSJim Jagielski 
InitWritingDirections(sal_uInt16 nPara)1979*b1cdbd2cSJim Jagielski void ImpEditEngine::InitWritingDirections( sal_uInt16 nPara )
1980*b1cdbd2cSJim Jagielski {
1981*b1cdbd2cSJim Jagielski 	ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
1982*b1cdbd2cSJim Jagielski 	WritingDirectionInfos& rInfos = pParaPortion->aWritingDirectionInfos;
1983*b1cdbd2cSJim Jagielski 	rInfos.clear();
1984*b1cdbd2cSJim Jagielski 
1985*b1cdbd2cSJim Jagielski     sal_Bool bCTL = sal_False;
1986*b1cdbd2cSJim Jagielski 	ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
1987*b1cdbd2cSJim Jagielski 	for ( size_t n = 0; n < rTypes.size(); n++ )
1988*b1cdbd2cSJim Jagielski 	{
1989*b1cdbd2cSJim Jagielski 		if ( rTypes[n].nScriptType == i18n::ScriptType::COMPLEX )
1990*b1cdbd2cSJim Jagielski 	   	{
1991*b1cdbd2cSJim Jagielski 			bCTL = sal_True;
1992*b1cdbd2cSJim Jagielski 			break;
1993*b1cdbd2cSJim Jagielski 		}
1994*b1cdbd2cSJim Jagielski 	}
1995*b1cdbd2cSJim Jagielski 
1996*b1cdbd2cSJim Jagielski     const UBiDiLevel nBidiLevel = IsRightToLeft( nPara ) ? 1 /*RTL*/ : 0 /*LTR*/;
1997*b1cdbd2cSJim Jagielski     if ( ( bCTL || ( nBidiLevel == 1 /*RTL*/ ) ) && pParaPortion->GetNode()->Len() )
1998*b1cdbd2cSJim Jagielski 	{
1999*b1cdbd2cSJim Jagielski 
2000*b1cdbd2cSJim Jagielski         String aText( *pParaPortion->GetNode() );
2001*b1cdbd2cSJim Jagielski 
2002*b1cdbd2cSJim Jagielski         //
2003*b1cdbd2cSJim Jagielski         // Bidi functions from icu 2.0
2004*b1cdbd2cSJim Jagielski         //
2005*b1cdbd2cSJim Jagielski         UErrorCode nError = U_ZERO_ERROR;
2006*b1cdbd2cSJim Jagielski         UBiDi* pBidi = ubidi_openSized( aText.Len(), 0, &nError );
2007*b1cdbd2cSJim Jagielski         nError = U_ZERO_ERROR;
2008*b1cdbd2cSJim Jagielski 
2009*b1cdbd2cSJim Jagielski         ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(aText.GetBuffer()), aText.Len(), nBidiLevel, NULL, &nError );	// UChar != sal_Unicode in MinGW
2010*b1cdbd2cSJim Jagielski         nError = U_ZERO_ERROR;
2011*b1cdbd2cSJim Jagielski 
2012*b1cdbd2cSJim Jagielski         size_t nCount = ubidi_countRuns( pBidi, &nError );
2013*b1cdbd2cSJim Jagielski 
2014*b1cdbd2cSJim Jagielski         int32_t nStart = 0;
2015*b1cdbd2cSJim Jagielski         int32_t nEnd;
2016*b1cdbd2cSJim Jagielski         UBiDiLevel nCurrDir;
2017*b1cdbd2cSJim Jagielski 
2018*b1cdbd2cSJim Jagielski         for ( size_t nIdx = 0; nIdx < nCount; ++nIdx )
2019*b1cdbd2cSJim Jagielski         {
2020*b1cdbd2cSJim Jagielski             ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
2021*b1cdbd2cSJim Jagielski             rInfos.push_back( WritingDirectionInfo( nCurrDir, (sal_uInt16)nStart, (sal_uInt16)nEnd ) );
2022*b1cdbd2cSJim Jagielski             nStart = nEnd;
2023*b1cdbd2cSJim Jagielski         }
2024*b1cdbd2cSJim Jagielski 
2025*b1cdbd2cSJim Jagielski         ubidi_close( pBidi );
2026*b1cdbd2cSJim Jagielski 	}
2027*b1cdbd2cSJim Jagielski 
2028*b1cdbd2cSJim Jagielski     // No infos mean no CTL and default dir is L2R...
2029*b1cdbd2cSJim Jagielski     if ( rInfos.empty() )
2030*b1cdbd2cSJim Jagielski         rInfos.push_back( WritingDirectionInfo( 0, 0, (sal_uInt16)pParaPortion->GetNode()->Len() ) );
2031*b1cdbd2cSJim Jagielski 
2032*b1cdbd2cSJim Jagielski }
2033*b1cdbd2cSJim Jagielski 
IsRightToLeft(sal_uInt16 nPara) const2034*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::IsRightToLeft( sal_uInt16 nPara ) const
2035*b1cdbd2cSJim Jagielski {
2036*b1cdbd2cSJim Jagielski     sal_Bool bR2L = sal_False;
2037*b1cdbd2cSJim Jagielski     const SvxFrameDirectionItem* pFrameDirItem = NULL;
2038*b1cdbd2cSJim Jagielski 
2039*b1cdbd2cSJim Jagielski     if ( !IsVertical() )
2040*b1cdbd2cSJim Jagielski     {
2041*b1cdbd2cSJim Jagielski         bR2L = GetDefaultHorizontalTextDirection() == EE_HTEXTDIR_R2L;
2042*b1cdbd2cSJim Jagielski         pFrameDirItem = &(const SvxFrameDirectionItem&)GetParaAttrib( nPara, EE_PARA_WRITINGDIR );
2043*b1cdbd2cSJim Jagielski         if ( pFrameDirItem->GetValue() == FRMDIR_ENVIRONMENT )
2044*b1cdbd2cSJim Jagielski         {
2045*b1cdbd2cSJim Jagielski             // #103045# if DefaultHorizontalTextDirection is set, use that value, otherwise pool default.
2046*b1cdbd2cSJim Jagielski             if ( GetDefaultHorizontalTextDirection() != EE_HTEXTDIR_DEFAULT )
2047*b1cdbd2cSJim Jagielski             {
2048*b1cdbd2cSJim Jagielski                 pFrameDirItem = NULL; // bR2L allready set to default horizontal text direction
2049*b1cdbd2cSJim Jagielski             }
2050*b1cdbd2cSJim Jagielski             else
2051*b1cdbd2cSJim Jagielski             {
2052*b1cdbd2cSJim Jagielski                 // Use pool default
2053*b1cdbd2cSJim Jagielski                 pFrameDirItem = &(const SvxFrameDirectionItem&)((ImpEditEngine*)this)->GetEmptyItemSet().Get( EE_PARA_WRITINGDIR );
2054*b1cdbd2cSJim Jagielski             }
2055*b1cdbd2cSJim Jagielski         }
2056*b1cdbd2cSJim Jagielski     }
2057*b1cdbd2cSJim Jagielski 
2058*b1cdbd2cSJim Jagielski     if ( pFrameDirItem )
2059*b1cdbd2cSJim Jagielski         bR2L = pFrameDirItem->GetValue() == FRMDIR_HORI_RIGHT_TOP;
2060*b1cdbd2cSJim Jagielski 
2061*b1cdbd2cSJim Jagielski     return bR2L;
2062*b1cdbd2cSJim Jagielski }
2063*b1cdbd2cSJim Jagielski 
HasDifferentRTLLevels(const ContentNode * pNode)2064*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::HasDifferentRTLLevels( const ContentNode* pNode )
2065*b1cdbd2cSJim Jagielski {
2066*b1cdbd2cSJim Jagielski     sal_uInt16 nPara = GetEditDoc().GetPos( (ContentNode*)pNode );
2067*b1cdbd2cSJim Jagielski 	ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
2068*b1cdbd2cSJim Jagielski 
2069*b1cdbd2cSJim Jagielski     sal_Bool bHasDifferentRTLLevels = sal_False;
2070*b1cdbd2cSJim Jagielski 
2071*b1cdbd2cSJim Jagielski     sal_uInt16 nRTLLevel = IsRightToLeft( nPara ) ? 1 : 0;
2072*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 n = 0; n < pParaPortion->GetTextPortions().Count(); n++ )
2073*b1cdbd2cSJim Jagielski 	{
2074*b1cdbd2cSJim Jagielski 		TextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( n );
2075*b1cdbd2cSJim Jagielski         if ( pTextPortion->GetRightToLeft() != nRTLLevel )
2076*b1cdbd2cSJim Jagielski         {
2077*b1cdbd2cSJim Jagielski             bHasDifferentRTLLevels = sal_True;
2078*b1cdbd2cSJim Jagielski             break;
2079*b1cdbd2cSJim Jagielski         }
2080*b1cdbd2cSJim Jagielski 	}
2081*b1cdbd2cSJim Jagielski     return bHasDifferentRTLLevels;
2082*b1cdbd2cSJim Jagielski }
2083*b1cdbd2cSJim Jagielski 
2084*b1cdbd2cSJim Jagielski 
GetRightToLeft(sal_uInt16 nPara,sal_uInt16 nPos,sal_uInt16 * pStart,sal_uInt16 * pEnd)2085*b1cdbd2cSJim Jagielski sal_uInt8 ImpEditEngine::GetRightToLeft( sal_uInt16 nPara, sal_uInt16 nPos, sal_uInt16* pStart, sal_uInt16* pEnd )
2086*b1cdbd2cSJim Jagielski {
2087*b1cdbd2cSJim Jagielski //    sal_uInt8 nRightToLeft = IsRightToLeft( nPara ) ? 1 : 0;
2088*b1cdbd2cSJim Jagielski     sal_uInt8 nRightToLeft = 0;
2089*b1cdbd2cSJim Jagielski 
2090*b1cdbd2cSJim Jagielski     ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
2091*b1cdbd2cSJim Jagielski     if ( pNode && pNode->Len() )
2092*b1cdbd2cSJim Jagielski     {
2093*b1cdbd2cSJim Jagielski 		ParaPortion* pParaPortion = GetParaPortions().SaveGetObject( nPara );
2094*b1cdbd2cSJim Jagielski 		if ( pParaPortion->aWritingDirectionInfos.empty() )
2095*b1cdbd2cSJim Jagielski 			InitWritingDirections( nPara );
2096*b1cdbd2cSJim Jagielski 
2097*b1cdbd2cSJim Jagielski //        sal_uInt8 nType = 0;
2098*b1cdbd2cSJim Jagielski 		WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos;
2099*b1cdbd2cSJim Jagielski 		for ( size_t n = 0; n < rDirInfos.size(); n++ )
2100*b1cdbd2cSJim Jagielski 		{
2101*b1cdbd2cSJim Jagielski 			if ( ( rDirInfos[n].nStartPos <= nPos ) && ( rDirInfos[n].nEndPos >= nPos ) )
2102*b1cdbd2cSJim Jagielski 	   		{
2103*b1cdbd2cSJim Jagielski 				nRightToLeft = rDirInfos[n].nType;
2104*b1cdbd2cSJim Jagielski                 if ( pStart )
2105*b1cdbd2cSJim Jagielski                     *pStart = rDirInfos[n].nStartPos;
2106*b1cdbd2cSJim Jagielski                 if ( pEnd )
2107*b1cdbd2cSJim Jagielski                     *pEnd = rDirInfos[n].nEndPos;
2108*b1cdbd2cSJim Jagielski 				break;
2109*b1cdbd2cSJim Jagielski 			}
2110*b1cdbd2cSJim Jagielski 		}
2111*b1cdbd2cSJim Jagielski     }
2112*b1cdbd2cSJim Jagielski     return nRightToLeft;
2113*b1cdbd2cSJim Jagielski }
2114*b1cdbd2cSJim Jagielski 
GetJustification(sal_uInt16 nPara) const2115*b1cdbd2cSJim Jagielski SvxAdjust ImpEditEngine::GetJustification( sal_uInt16 nPara ) const
2116*b1cdbd2cSJim Jagielski {
2117*b1cdbd2cSJim Jagielski 	SvxAdjust eJustification = SVX_ADJUST_LEFT;
2118*b1cdbd2cSJim Jagielski 
2119*b1cdbd2cSJim Jagielski     if ( !aStatus.IsOutliner() )
2120*b1cdbd2cSJim Jagielski     {
2121*b1cdbd2cSJim Jagielski 		eJustification = ((const SvxAdjustItem&) GetParaAttrib( nPara, EE_PARA_JUST )).GetAdjust();
2122*b1cdbd2cSJim Jagielski 
2123*b1cdbd2cSJim Jagielski         if ( IsRightToLeft( nPara ) )
2124*b1cdbd2cSJim Jagielski         {
2125*b1cdbd2cSJim Jagielski             if ( eJustification == SVX_ADJUST_LEFT )
2126*b1cdbd2cSJim Jagielski                 eJustification = SVX_ADJUST_RIGHT;
2127*b1cdbd2cSJim Jagielski             else if ( eJustification == SVX_ADJUST_RIGHT )
2128*b1cdbd2cSJim Jagielski                 eJustification = SVX_ADJUST_LEFT;
2129*b1cdbd2cSJim Jagielski         }
2130*b1cdbd2cSJim Jagielski     }
2131*b1cdbd2cSJim Jagielski     return eJustification;
2132*b1cdbd2cSJim Jagielski }
2133*b1cdbd2cSJim Jagielski 
2134*b1cdbd2cSJim Jagielski 
2135*b1cdbd2cSJim Jagielski //	----------------------------------------------------------------------
2136*b1cdbd2cSJim Jagielski //	Textaenderung
2137*b1cdbd2cSJim Jagielski //	----------------------------------------------------------------------
2138*b1cdbd2cSJim Jagielski 
ImpRemoveChars(const EditPaM & rPaM,sal_uInt16 nChars,EditUndoRemoveChars * pCurUndo)2139*b1cdbd2cSJim Jagielski void ImpEditEngine::ImpRemoveChars( const EditPaM& rPaM, sal_uInt16 nChars, EditUndoRemoveChars* pCurUndo )
2140*b1cdbd2cSJim Jagielski {
2141*b1cdbd2cSJim Jagielski 	if ( IsUndoEnabled() && !IsInUndo() )
2142*b1cdbd2cSJim Jagielski 	{
2143*b1cdbd2cSJim Jagielski 		XubString aStr( rPaM.GetNode()->Copy( rPaM.GetIndex(), nChars ) );
2144*b1cdbd2cSJim Jagielski 
2145*b1cdbd2cSJim Jagielski 		// Pruefen, ob Attribute geloescht oder geaendert werden:
2146*b1cdbd2cSJim Jagielski 		sal_uInt16 nStart = rPaM.GetIndex();
2147*b1cdbd2cSJim Jagielski 		sal_uInt16 nEnd = nStart + nChars;
2148*b1cdbd2cSJim Jagielski 		CharAttribArray& rAttribs = rPaM.GetNode()->GetCharAttribs().GetAttribs();
2149*b1cdbd2cSJim Jagielski //		sal_uInt16 nAttrs = rAttribs.Count();
2150*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 nAttr = 0; nAttr < rAttribs.Count(); nAttr++ )
2151*b1cdbd2cSJim Jagielski 		{
2152*b1cdbd2cSJim Jagielski 			EditCharAttrib* pAttr = rAttribs[nAttr];
2153*b1cdbd2cSJim Jagielski 			if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetStart() < nEnd ) )
2154*b1cdbd2cSJim Jagielski 			{
2155*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2156*b1cdbd2cSJim Jagielski 				EditSelection aSel( rPaM );
2157*b1cdbd2cSJim Jagielski 				aSel.Max().GetIndex() = aSel.Max().GetIndex() + nChars;
2158*b1cdbd2cSJim Jagielski 				EditUndoSetAttribs* pAttrUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
2159*b1cdbd2cSJim Jagielski 				InsertUndo( pAttrUndo );
2160*b1cdbd2cSJim Jagielski #endif
2161*b1cdbd2cSJim Jagielski 				break;	// for
2162*b1cdbd2cSJim Jagielski 			}
2163*b1cdbd2cSJim Jagielski 		}
2164*b1cdbd2cSJim Jagielski 		if ( pCurUndo && ( CreateEditPaM( pCurUndo->GetEPaM() ) == rPaM ) )
2165*b1cdbd2cSJim Jagielski 			pCurUndo->GetStr() += aStr;
2166*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2167*b1cdbd2cSJim Jagielski 		else
2168*b1cdbd2cSJim Jagielski 			InsertUndo( new EditUndoRemoveChars( this, CreateEPaM( rPaM ), aStr ) );
2169*b1cdbd2cSJim Jagielski #endif
2170*b1cdbd2cSJim Jagielski 	}
2171*b1cdbd2cSJim Jagielski 
2172*b1cdbd2cSJim Jagielski 	aEditDoc.RemoveChars( rPaM, nChars );
2173*b1cdbd2cSJim Jagielski 	TextModified();
2174*b1cdbd2cSJim Jagielski }
2175*b1cdbd2cSJim Jagielski 
ImpMoveParagraphs(Range aOldPositions,sal_uInt16 nNewPos)2176*b1cdbd2cSJim Jagielski EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_uInt16 nNewPos )
2177*b1cdbd2cSJim Jagielski {
2178*b1cdbd2cSJim Jagielski 	aOldPositions.Justify();
2179*b1cdbd2cSJim Jagielski 	sal_Bool bValidAction = ( (long)nNewPos < aOldPositions.Min() ) || ( (long)nNewPos > aOldPositions.Max() );
2180*b1cdbd2cSJim Jagielski 	DBG_ASSERT( bValidAction, "Move in sich selbst ?" );
2181*b1cdbd2cSJim Jagielski 	DBG_ASSERT( aOldPositions.Max() <= (long)GetParaPortions().Count(), "Voll drueber weg: MoveParagraphs" );
2182*b1cdbd2cSJim Jagielski 
2183*b1cdbd2cSJim Jagielski 	EditSelection aSelection;
2184*b1cdbd2cSJim Jagielski 
2185*b1cdbd2cSJim Jagielski 	if ( !bValidAction )
2186*b1cdbd2cSJim Jagielski 	{
2187*b1cdbd2cSJim Jagielski 		aSelection = aEditDoc.GetStartPaM();
2188*b1cdbd2cSJim Jagielski 		return aSelection;
2189*b1cdbd2cSJim Jagielski 	}
2190*b1cdbd2cSJim Jagielski 
2191*b1cdbd2cSJim Jagielski 	sal_uLong nParaCount = GetParaPortions().Count();
2192*b1cdbd2cSJim Jagielski 
2193*b1cdbd2cSJim Jagielski 	if ( nNewPos >= nParaCount )
2194*b1cdbd2cSJim Jagielski 		nNewPos = GetParaPortions().Count();
2195*b1cdbd2cSJim Jagielski 
2196*b1cdbd2cSJim Jagielski 	// Height may change when moving first or last Paragraph
2197*b1cdbd2cSJim Jagielski 	ParaPortion* pRecalc1 = NULL;
2198*b1cdbd2cSJim Jagielski 	ParaPortion* pRecalc2 = NULL;
2199*b1cdbd2cSJim Jagielski 	ParaPortion* pRecalc3 = NULL;
2200*b1cdbd2cSJim Jagielski 	ParaPortion* pRecalc4 = NULL;
2201*b1cdbd2cSJim Jagielski 
2202*b1cdbd2cSJim Jagielski 	if ( nNewPos == 0 )	// Move to Start
2203*b1cdbd2cSJim Jagielski 	{
2204*b1cdbd2cSJim Jagielski 		pRecalc1 = GetParaPortions().GetObject( 0 );
2205*b1cdbd2cSJim Jagielski 		pRecalc2 = GetParaPortions().GetObject( (sal_uInt16)aOldPositions.Min() );
2206*b1cdbd2cSJim Jagielski 
2207*b1cdbd2cSJim Jagielski 	}
2208*b1cdbd2cSJim Jagielski 	else if ( nNewPos == nParaCount )
2209*b1cdbd2cSJim Jagielski 	{
2210*b1cdbd2cSJim Jagielski 		pRecalc1 = GetParaPortions().GetObject( (sal_uInt16)(nParaCount-1) );
2211*b1cdbd2cSJim Jagielski 		pRecalc2 = GetParaPortions().GetObject( (sal_uInt16)aOldPositions.Max() );
2212*b1cdbd2cSJim Jagielski 	}
2213*b1cdbd2cSJim Jagielski 
2214*b1cdbd2cSJim Jagielski 	if ( aOldPositions.Min() == 0 )	// Move from Start
2215*b1cdbd2cSJim Jagielski 	{
2216*b1cdbd2cSJim Jagielski 		pRecalc3 = GetParaPortions().GetObject( 0 );
2217*b1cdbd2cSJim Jagielski 		pRecalc4 = GetParaPortions().GetObject(
2218*b1cdbd2cSJim Jagielski             sal::static_int_cast< sal_uInt16 >( aOldPositions.Max()+1 ) );
2219*b1cdbd2cSJim Jagielski 	}
2220*b1cdbd2cSJim Jagielski 	else if ( (sal_uInt16)aOldPositions.Max() == (nParaCount-1) )
2221*b1cdbd2cSJim Jagielski 	{
2222*b1cdbd2cSJim Jagielski 		pRecalc3 = GetParaPortions().GetObject( (sal_uInt16)aOldPositions.Max() );
2223*b1cdbd2cSJim Jagielski 		pRecalc4 = GetParaPortions().GetObject( (sal_uInt16)(aOldPositions.Min()-1) );
2224*b1cdbd2cSJim Jagielski 	}
2225*b1cdbd2cSJim Jagielski 
2226*b1cdbd2cSJim Jagielski 	MoveParagraphsInfo aMoveParagraphsInfo( sal::static_int_cast< sal_uInt16 >(aOldPositions.Min()), sal::static_int_cast< sal_uInt16 >(aOldPositions.Max()), nNewPos );
2227*b1cdbd2cSJim Jagielski 	aBeginMovingParagraphsHdl.Call( &aMoveParagraphsInfo );
2228*b1cdbd2cSJim Jagielski 
2229*b1cdbd2cSJim Jagielski 	if ( IsUndoEnabled() && !IsInUndo())
2230*b1cdbd2cSJim Jagielski 		InsertUndo( new EditUndoMoveParagraphs( this, aOldPositions, nNewPos ) );
2231*b1cdbd2cSJim Jagielski 
2232*b1cdbd2cSJim Jagielski 	// Position nicht aus dem Auge verlieren!
2233*b1cdbd2cSJim Jagielski 	ParaPortion* pDestPortion = GetParaPortions().SaveGetObject( nNewPos );
2234*b1cdbd2cSJim Jagielski 
2235*b1cdbd2cSJim Jagielski 	ParaPortionList aTmpPortionList;
2236*b1cdbd2cSJim Jagielski 	sal_uInt16 i;
2237*b1cdbd2cSJim Jagielski 	for ( i = (sal_uInt16)aOldPositions.Min(); i <= (sal_uInt16)aOldPositions.Max(); i++  )
2238*b1cdbd2cSJim Jagielski 	{
2239*b1cdbd2cSJim Jagielski 		// Immer aOldPositions.Min(), da Remove().
2240*b1cdbd2cSJim Jagielski 		ParaPortion* pTmpPortion = GetParaPortions().GetObject( (sal_uInt16)aOldPositions.Min() );
2241*b1cdbd2cSJim Jagielski 		GetParaPortions().Remove( (sal_uInt16)aOldPositions.Min() );
2242*b1cdbd2cSJim Jagielski 		aEditDoc.Remove( (sal_uInt16)aOldPositions.Min() );
2243*b1cdbd2cSJim Jagielski 		aTmpPortionList.Insert( pTmpPortion, aTmpPortionList.Count() );
2244*b1cdbd2cSJim Jagielski 	}
2245*b1cdbd2cSJim Jagielski 
2246*b1cdbd2cSJim Jagielski 	sal_uInt16 nRealNewPos = pDestPortion ? GetParaPortions().GetPos( pDestPortion ) : GetParaPortions().Count();
2247*b1cdbd2cSJim Jagielski 	DBG_ASSERT( nRealNewPos != USHRT_MAX, "ImpMoveParagraphs: Ungueltige Position!" );
2248*b1cdbd2cSJim Jagielski 
2249*b1cdbd2cSJim Jagielski 	for ( i = 0; i < (sal_uInt16)aTmpPortionList.Count(); i++  )
2250*b1cdbd2cSJim Jagielski 	{
2251*b1cdbd2cSJim Jagielski 		ParaPortion* pTmpPortion = aTmpPortionList.GetObject( i );
2252*b1cdbd2cSJim Jagielski 		if ( i == 0 )
2253*b1cdbd2cSJim Jagielski 			aSelection.Min().SetNode( pTmpPortion->GetNode() );
2254*b1cdbd2cSJim Jagielski 
2255*b1cdbd2cSJim Jagielski 		aSelection.Max().SetNode( pTmpPortion->GetNode() );
2256*b1cdbd2cSJim Jagielski 		aSelection.Max().SetIndex( pTmpPortion->GetNode()->Len() );
2257*b1cdbd2cSJim Jagielski 
2258*b1cdbd2cSJim Jagielski 		ContentNode* pN = pTmpPortion->GetNode();
2259*b1cdbd2cSJim Jagielski 		aEditDoc.Insert( pN, nRealNewPos+i );
2260*b1cdbd2cSJim Jagielski 
2261*b1cdbd2cSJim Jagielski 		GetParaPortions().Insert( pTmpPortion, nRealNewPos+i );
2262*b1cdbd2cSJim Jagielski 	}
2263*b1cdbd2cSJim Jagielski 
2264*b1cdbd2cSJim Jagielski     aEndMovingParagraphsHdl.Call( &aMoveParagraphsInfo );
2265*b1cdbd2cSJim Jagielski 
2266*b1cdbd2cSJim Jagielski     if ( GetNotifyHdl().IsSet() )
2267*b1cdbd2cSJim Jagielski     {
2268*b1cdbd2cSJim Jagielski         EENotify aNotify( EE_NOTIFY_PARAGRAPHSMOVED );
2269*b1cdbd2cSJim Jagielski         aNotify.pEditEngine = GetEditEnginePtr();
2270*b1cdbd2cSJim Jagielski         aNotify.nParagraph = nNewPos;
2271*b1cdbd2cSJim Jagielski         aNotify.nParam1 = sal::static_int_cast< sal_uInt16 >(aOldPositions.Min());
2272*b1cdbd2cSJim Jagielski         aNotify.nParam2 = sal::static_int_cast< sal_uInt16 >(aOldPositions.Max());
2273*b1cdbd2cSJim Jagielski         CallNotify( aNotify );
2274*b1cdbd2cSJim Jagielski     }
2275*b1cdbd2cSJim Jagielski 
2276*b1cdbd2cSJim Jagielski 	aEditDoc.SetModified( sal_True );
2277*b1cdbd2cSJim Jagielski 
2278*b1cdbd2cSJim Jagielski 	if ( pRecalc1 )
2279*b1cdbd2cSJim Jagielski 		CalcHeight( pRecalc1 );
2280*b1cdbd2cSJim Jagielski 	if ( pRecalc2 )
2281*b1cdbd2cSJim Jagielski 		CalcHeight( pRecalc2 );
2282*b1cdbd2cSJim Jagielski 	if ( pRecalc3 )
2283*b1cdbd2cSJim Jagielski 		CalcHeight( pRecalc3 );
2284*b1cdbd2cSJim Jagielski 	if ( pRecalc4 )
2285*b1cdbd2cSJim Jagielski 		CalcHeight( pRecalc4 );
2286*b1cdbd2cSJim Jagielski 
2287*b1cdbd2cSJim Jagielski 	aTmpPortionList.Remove( 0, aTmpPortionList.Count() );	// wichtig !
2288*b1cdbd2cSJim Jagielski 
2289*b1cdbd2cSJim Jagielski #ifdef EDITDEBUG
2290*b1cdbd2cSJim Jagielski 	GetParaPortions().DbgCheck(aEditDoc);
2291*b1cdbd2cSJim Jagielski #endif
2292*b1cdbd2cSJim Jagielski 	return aSelection;
2293*b1cdbd2cSJim Jagielski }
2294*b1cdbd2cSJim Jagielski 
2295*b1cdbd2cSJim Jagielski 
ImpConnectParagraphs(ContentNode * pLeft,ContentNode * pRight,sal_Bool bBackward)2296*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, sal_Bool bBackward )
2297*b1cdbd2cSJim Jagielski {
2298*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pLeft != pRight, "Den gleichen Absatz zusammenfuegen ?" );
2299*b1cdbd2cSJim Jagielski 	DBG_ASSERT( aEditDoc.GetPos( pLeft ) != USHRT_MAX, "Einzufuegenden Node nicht gefunden(1)" );
2300*b1cdbd2cSJim Jagielski 	DBG_ASSERT( aEditDoc.GetPos( pRight ) != USHRT_MAX, "Einzufuegenden Node nicht gefunden(2)" );
2301*b1cdbd2cSJim Jagielski 
2302*b1cdbd2cSJim Jagielski     // #120020# it is possible that left and right are *not* in the desired order (left/right)
2303*b1cdbd2cSJim Jagielski     // so correct it. This correction is needed, else an invalid SfxLinkUndoAction will be
2304*b1cdbd2cSJim Jagielski     // created from ConnectParagraphs below. Assert this situation, it should be corrected by the
2305*b1cdbd2cSJim Jagielski     // caller.
2306*b1cdbd2cSJim Jagielski     if(aEditDoc.GetPos( pLeft ) > aEditDoc.GetPos( pRight ))
2307*b1cdbd2cSJim Jagielski     {
2308*b1cdbd2cSJim Jagielski         OSL_ENSURE(false, "ImpConnectParagraphs wit wrong order of pLeft/pRight nodes (!)");
2309*b1cdbd2cSJim Jagielski         std::swap(pLeft, pRight);
2310*b1cdbd2cSJim Jagielski     }
2311*b1cdbd2cSJim Jagielski 
2312*b1cdbd2cSJim Jagielski 	sal_uInt16 nParagraphTobeDeleted = aEditDoc.GetPos( pRight );
2313*b1cdbd2cSJim Jagielski 	DeletedNodeInfo* pInf = new DeletedNodeInfo( (sal_uLong)pRight, nParagraphTobeDeleted );
2314*b1cdbd2cSJim Jagielski 	aDeletedNodes.Insert( pInf, aDeletedNodes.Count() );
2315*b1cdbd2cSJim Jagielski 
2316*b1cdbd2cSJim Jagielski     GetEditEnginePtr()->ParagraphConnected( aEditDoc.GetPos( pLeft ), aEditDoc.GetPos( pRight ) );
2317*b1cdbd2cSJim Jagielski 
2318*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2319*b1cdbd2cSJim Jagielski 	if ( IsUndoEnabled() && !IsInUndo() )
2320*b1cdbd2cSJim Jagielski 	{
2321*b1cdbd2cSJim Jagielski 		InsertUndo( new EditUndoConnectParas( this,
2322*b1cdbd2cSJim Jagielski 			aEditDoc.GetPos( pLeft ), pLeft->Len(),
2323*b1cdbd2cSJim Jagielski 			pLeft->GetContentAttribs().GetItems(), pRight->GetContentAttribs().GetItems(),
2324*b1cdbd2cSJim Jagielski 			pLeft->GetStyleSheet(), pRight->GetStyleSheet(), bBackward ) );
2325*b1cdbd2cSJim Jagielski 	}
2326*b1cdbd2cSJim Jagielski #endif
2327*b1cdbd2cSJim Jagielski 
2328*b1cdbd2cSJim Jagielski 	if ( bBackward )
2329*b1cdbd2cSJim Jagielski 	{
2330*b1cdbd2cSJim Jagielski 		pLeft->SetStyleSheet( pRight->GetStyleSheet(), sal_True );
2331*b1cdbd2cSJim Jagielski 		pLeft->GetContentAttribs().GetItems().Set( pRight->GetContentAttribs().GetItems() );
2332*b1cdbd2cSJim Jagielski 		pLeft->GetCharAttribs().GetDefFont() = pRight->GetCharAttribs().GetDefFont();
2333*b1cdbd2cSJim Jagielski 	}
2334*b1cdbd2cSJim Jagielski 
2335*b1cdbd2cSJim Jagielski 	ParaAttribsChanged( pLeft );
2336*b1cdbd2cSJim Jagielski 
2337*b1cdbd2cSJim Jagielski 	// Erstmal Portions suchen, da pRight nach ConnectParagraphs weg.
2338*b1cdbd2cSJim Jagielski 	ParaPortion* pLeftPortion = FindParaPortion( pLeft );
2339*b1cdbd2cSJim Jagielski 	ParaPortion* pRightPortion = FindParaPortion( pRight );
2340*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pLeftPortion, "Blinde Portion in ImpConnectParagraphs(1)" );
2341*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pRightPortion, "Blinde Portion in ImpConnectParagraphs(2)" );
2342*b1cdbd2cSJim Jagielski 	DBG_ASSERT( nParagraphTobeDeleted == GetParaPortions().GetPos( pRightPortion ), "NodePos != PortionPos?" );
2343*b1cdbd2cSJim Jagielski 
2344*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2345*b1cdbd2cSJim Jagielski 	if ( GetStatus().DoOnlineSpelling() )
2346*b1cdbd2cSJim Jagielski 	{
2347*b1cdbd2cSJim Jagielski 		xub_StrLen nEnd = pLeft->Len();
2348*b1cdbd2cSJim Jagielski 		xub_StrLen nInv = nEnd ? nEnd-1 : nEnd;
2349*b1cdbd2cSJim Jagielski 		pLeft->GetWrongList()->ClearWrongs( nInv, 0xFFFF, pLeft );	// Evtl. einen wegnehmen
2350*b1cdbd2cSJim Jagielski 		pLeft->GetWrongList()->MarkInvalid( nInv, nEnd+1 );
2351*b1cdbd2cSJim Jagielski 		// Falschgeschriebene Woerter ruebernehmen:
2352*b1cdbd2cSJim Jagielski 		sal_uInt16 nRWrongs = pRight->GetWrongList()->Count();
2353*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 nW = 0; nW < nRWrongs; nW++ )
2354*b1cdbd2cSJim Jagielski 		{
2355*b1cdbd2cSJim Jagielski 			WrongRange aWrong = pRight->GetWrongList()->GetObject( nW );
2356*b1cdbd2cSJim Jagielski 			if ( aWrong.nStart != 0 ) 	// Nicht ein anschliessender
2357*b1cdbd2cSJim Jagielski 			{
2358*b1cdbd2cSJim Jagielski 				aWrong.nStart = aWrong.nStart + nEnd;
2359*b1cdbd2cSJim Jagielski 				aWrong.nEnd = aWrong.nEnd + nEnd;
2360*b1cdbd2cSJim Jagielski 				pLeft->GetWrongList()->InsertWrong( aWrong, pLeft->GetWrongList()->Count() );
2361*b1cdbd2cSJim Jagielski 			}
2362*b1cdbd2cSJim Jagielski 		}
2363*b1cdbd2cSJim Jagielski 	}
2364*b1cdbd2cSJim Jagielski #endif
2365*b1cdbd2cSJim Jagielski 
2366*b1cdbd2cSJim Jagielski 	if ( IsCallParaInsertedOrDeleted() )
2367*b1cdbd2cSJim Jagielski 		GetEditEnginePtr()->ParagraphDeleted( nParagraphTobeDeleted );
2368*b1cdbd2cSJim Jagielski 
2369*b1cdbd2cSJim Jagielski 	EditPaM aPaM = aEditDoc.ConnectParagraphs( pLeft, pRight );
2370*b1cdbd2cSJim Jagielski 	GetParaPortions().Remove( nParagraphTobeDeleted );
2371*b1cdbd2cSJim Jagielski 	delete pRightPortion;
2372*b1cdbd2cSJim Jagielski 
2373*b1cdbd2cSJim Jagielski 	pLeftPortion->MarkSelectionInvalid( aPaM.GetIndex(), pLeft->Len() );
2374*b1cdbd2cSJim Jagielski 
2375*b1cdbd2cSJim Jagielski 	// der rechte Node wird von EditDoc::ConnectParagraphs() geloescht.
2376*b1cdbd2cSJim Jagielski 
2377*b1cdbd2cSJim Jagielski 	if ( GetTextRanger() )
2378*b1cdbd2cSJim Jagielski 	{
2379*b1cdbd2cSJim Jagielski 		// Durch das zusammenfuegen wird der linke zwar neu formatiert, aber
2380*b1cdbd2cSJim Jagielski 		// wenn sich dessen Hoehe nicht aendert bekommt die Formatierung die
2381*b1cdbd2cSJim Jagielski 		// Aenderung der Gesaamthoehe des Textes zu spaet mit...
2382*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 n = nParagraphTobeDeleted; n < GetParaPortions().Count(); n++ )
2383*b1cdbd2cSJim Jagielski 		{
2384*b1cdbd2cSJim Jagielski 			ParaPortion* pPP = GetParaPortions().GetObject( n );
2385*b1cdbd2cSJim Jagielski 			pPP->MarkSelectionInvalid( 0, pPP->GetNode()->Len() );
2386*b1cdbd2cSJim Jagielski 			pPP->GetLines().Reset();
2387*b1cdbd2cSJim Jagielski 		}
2388*b1cdbd2cSJim Jagielski 	}
2389*b1cdbd2cSJim Jagielski 
2390*b1cdbd2cSJim Jagielski 	TextModified();
2391*b1cdbd2cSJim Jagielski 
2392*b1cdbd2cSJim Jagielski 	return aPaM;
2393*b1cdbd2cSJim Jagielski }
2394*b1cdbd2cSJim Jagielski 
DeleteLeftOrRight(const EditSelection & rSel,sal_uInt8 nMode,sal_uInt8 nDelMode)2395*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::DeleteLeftOrRight( const EditSelection& rSel, sal_uInt8 nMode, sal_uInt8 nDelMode )
2396*b1cdbd2cSJim Jagielski {
2397*b1cdbd2cSJim Jagielski 	DBG_ASSERT( !EditSelection( rSel ).DbgIsBuggy( aEditDoc ), "Index im Wald in DeleteLeftOrRight" );
2398*b1cdbd2cSJim Jagielski 
2399*b1cdbd2cSJim Jagielski 	if ( rSel.HasRange() )	// dann nur Sel. loeschen
2400*b1cdbd2cSJim Jagielski 		return ImpDeleteSelection( rSel );
2401*b1cdbd2cSJim Jagielski 
2402*b1cdbd2cSJim Jagielski 	const EditPaM aCurPos( rSel.Max() );
2403*b1cdbd2cSJim Jagielski 	EditPaM aDelStart( aCurPos );
2404*b1cdbd2cSJim Jagielski 	EditPaM aDelEnd( aCurPos );
2405*b1cdbd2cSJim Jagielski 	if ( nMode == DEL_LEFT )
2406*b1cdbd2cSJim Jagielski 	{
2407*b1cdbd2cSJim Jagielski 		if ( nDelMode == DELMODE_SIMPLE )
2408*b1cdbd2cSJim Jagielski 		{
2409*b1cdbd2cSJim Jagielski 			aDelStart = CursorLeft( aCurPos, i18n::CharacterIteratorMode::SKIPCHARACTER );
2410*b1cdbd2cSJim Jagielski 		}
2411*b1cdbd2cSJim Jagielski 		else if ( nDelMode == DELMODE_RESTOFWORD )
2412*b1cdbd2cSJim Jagielski 		{
2413*b1cdbd2cSJim Jagielski 			aDelStart = StartOfWord( aCurPos );
2414*b1cdbd2cSJim Jagielski 			if ( aDelStart.GetIndex() == aCurPos.GetIndex() )
2415*b1cdbd2cSJim Jagielski 				aDelStart = WordLeft( aCurPos );
2416*b1cdbd2cSJim Jagielski 		}
2417*b1cdbd2cSJim Jagielski 		else	// DELMODE_RESTOFCONTENT
2418*b1cdbd2cSJim Jagielski 		{
2419*b1cdbd2cSJim Jagielski 			aDelStart.SetIndex( 0 );
2420*b1cdbd2cSJim Jagielski 			if ( aDelStart == aCurPos )
2421*b1cdbd2cSJim Jagielski 			{
2422*b1cdbd2cSJim Jagielski 				// kompletter Absatz davor
2423*b1cdbd2cSJim Jagielski 				ContentNode* pPrev = GetPrevVisNode( aCurPos.GetNode() );
2424*b1cdbd2cSJim Jagielski 				if ( pPrev )
2425*b1cdbd2cSJim Jagielski 					aDelStart = EditPaM( pPrev, 0 );
2426*b1cdbd2cSJim Jagielski 			}
2427*b1cdbd2cSJim Jagielski 		}
2428*b1cdbd2cSJim Jagielski 	}
2429*b1cdbd2cSJim Jagielski 	else
2430*b1cdbd2cSJim Jagielski 	{
2431*b1cdbd2cSJim Jagielski 		if ( nDelMode == DELMODE_SIMPLE )
2432*b1cdbd2cSJim Jagielski 		{
2433*b1cdbd2cSJim Jagielski 			aDelEnd = CursorRight( aCurPos );
2434*b1cdbd2cSJim Jagielski 		}
2435*b1cdbd2cSJim Jagielski 		else if ( nDelMode == DELMODE_RESTOFWORD )
2436*b1cdbd2cSJim Jagielski 		{
2437*b1cdbd2cSJim Jagielski             aDelEnd = EndOfWord( aCurPos );
2438*b1cdbd2cSJim Jagielski 
2439*b1cdbd2cSJim Jagielski             if (aDelEnd.GetIndex() == aCurPos.GetIndex())
2440*b1cdbd2cSJim Jagielski             {
2441*b1cdbd2cSJim Jagielski                 const xub_StrLen nLen(aCurPos.GetNode()->Len());
2442*b1cdbd2cSJim Jagielski 
2443*b1cdbd2cSJim Jagielski                 // #120020# when 0 == nLen, aDelStart needs to be adapted, not
2444*b1cdbd2cSJim Jagielski                 // aDelEnd. This would (and did) lead to a wrong order in the
2445*b1cdbd2cSJim Jagielski                 // ImpConnectParagraphs call later.
2446*b1cdbd2cSJim Jagielski                 if(nLen)
2447*b1cdbd2cSJim Jagielski                 {
2448*b1cdbd2cSJim Jagielski                     // end of para?
2449*b1cdbd2cSJim Jagielski                     if (aDelEnd.GetIndex() == nLen)
2450*b1cdbd2cSJim Jagielski                     {
2451*b1cdbd2cSJim Jagielski                         aDelEnd = WordLeft( aCurPos );
2452*b1cdbd2cSJim Jagielski                     }
2453*b1cdbd2cSJim Jagielski                     else // there's still sth to delete on the right
2454*b1cdbd2cSJim Jagielski                     {
2455*b1cdbd2cSJim Jagielski                         aDelEnd = EndOfWord( WordRight( aCurPos ) );
2456*b1cdbd2cSJim Jagielski                         // if there'n no next word...
2457*b1cdbd2cSJim Jagielski                         if (aDelEnd.GetIndex() == nLen )
2458*b1cdbd2cSJim Jagielski                         {
2459*b1cdbd2cSJim Jagielski                             aDelEnd.SetIndex( nLen );
2460*b1cdbd2cSJim Jagielski                         }
2461*b1cdbd2cSJim Jagielski                     }
2462*b1cdbd2cSJim Jagielski                 }
2463*b1cdbd2cSJim Jagielski                 else
2464*b1cdbd2cSJim Jagielski                 {
2465*b1cdbd2cSJim Jagielski                     aDelStart = WordLeft(aCurPos);
2466*b1cdbd2cSJim Jagielski                 }
2467*b1cdbd2cSJim Jagielski             }
2468*b1cdbd2cSJim Jagielski         }
2469*b1cdbd2cSJim Jagielski 		else	// DELMODE_RESTOFCONTENT
2470*b1cdbd2cSJim Jagielski 		{
2471*b1cdbd2cSJim Jagielski 			aDelEnd.SetIndex( aCurPos.GetNode()->Len() );
2472*b1cdbd2cSJim Jagielski 			if ( aDelEnd == aCurPos )
2473*b1cdbd2cSJim Jagielski 			{
2474*b1cdbd2cSJim Jagielski 				// kompletter Absatz dahinter
2475*b1cdbd2cSJim Jagielski 				ContentNode* pNext = GetNextVisNode( aCurPos.GetNode() );
2476*b1cdbd2cSJim Jagielski 				if ( pNext )
2477*b1cdbd2cSJim Jagielski 					aDelEnd = EditPaM( pNext, pNext->Len() );
2478*b1cdbd2cSJim Jagielski 			}
2479*b1cdbd2cSJim Jagielski 		}
2480*b1cdbd2cSJim Jagielski 	}
2481*b1cdbd2cSJim Jagielski 
2482*b1cdbd2cSJim Jagielski 	// Bei DELMODE_RESTOFCONTENT reicht bei verschiedenen Nodes
2483*b1cdbd2cSJim Jagielski 	// kein ConnectParagraphs.
2484*b1cdbd2cSJim Jagielski 	if ( ( nDelMode == DELMODE_RESTOFCONTENT ) || ( aDelStart.GetNode() == aDelEnd.GetNode() ) )
2485*b1cdbd2cSJim Jagielski 		return ImpDeleteSelection( EditSelection( aDelStart, aDelEnd ) );
2486*b1cdbd2cSJim Jagielski 
2487*b1cdbd2cSJim Jagielski 	// Jetzt entscheiden, ob noch Selektion loeschen (RESTOFCONTENTS)
2488*b1cdbd2cSJim Jagielski 	sal_Bool bSpecialBackward = ( ( nMode == DEL_LEFT ) && ( nDelMode == DELMODE_SIMPLE ) )
2489*b1cdbd2cSJim Jagielski 								? sal_True : sal_False;
2490*b1cdbd2cSJim Jagielski 	if ( aStatus.IsAnyOutliner() )
2491*b1cdbd2cSJim Jagielski 		bSpecialBackward = sal_False;
2492*b1cdbd2cSJim Jagielski 
2493*b1cdbd2cSJim Jagielski 	return ImpConnectParagraphs( aDelStart.GetNode(), aDelEnd.GetNode(), bSpecialBackward );
2494*b1cdbd2cSJim Jagielski }
2495*b1cdbd2cSJim Jagielski 
ImpDeleteSelection(EditSelection aSel)2496*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::ImpDeleteSelection( EditSelection aSel )
2497*b1cdbd2cSJim Jagielski {
2498*b1cdbd2cSJim Jagielski 	if ( !aSel.HasRange() )
2499*b1cdbd2cSJim Jagielski 		return aSel.Min();
2500*b1cdbd2cSJim Jagielski 
2501*b1cdbd2cSJim Jagielski 	aSel.Adjust( aEditDoc );
2502*b1cdbd2cSJim Jagielski 	EditPaM aStartPaM( aSel.Min() );
2503*b1cdbd2cSJim Jagielski 	EditPaM aEndPaM( aSel.Max() );
2504*b1cdbd2cSJim Jagielski 
2505*b1cdbd2cSJim Jagielski 	CursorMoved( aStartPaM.GetNode() ); // nur damit neu eingestellte Attribute verschwinden...
2506*b1cdbd2cSJim Jagielski 	CursorMoved( aEndPaM.GetNode() );	// nur damit neu eingestellte Attribute verschwinden...
2507*b1cdbd2cSJim Jagielski 
2508*b1cdbd2cSJim Jagielski 	DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index im Wald in ImpDeleteSelection" );
2509*b1cdbd2cSJim Jagielski 	DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index im Wald in ImpDeleteSelection" );
2510*b1cdbd2cSJim Jagielski 
2511*b1cdbd2cSJim Jagielski 	sal_uInt16 nStartNode = aEditDoc.GetPos( aStartPaM.GetNode() );
2512*b1cdbd2cSJim Jagielski 	sal_uInt16 nEndNode = aEditDoc.GetPos( aEndPaM.GetNode() );
2513*b1cdbd2cSJim Jagielski 
2514*b1cdbd2cSJim Jagielski 	DBG_ASSERT( nEndNode != USHRT_MAX, "Start > End ?!" );
2515*b1cdbd2cSJim Jagielski 	DBG_ASSERT( nStartNode <= nEndNode, "Start > End ?!" );
2516*b1cdbd2cSJim Jagielski 
2517*b1cdbd2cSJim Jagielski 	// Alle Nodes dazwischen entfernen....
2518*b1cdbd2cSJim Jagielski 	for ( sal_uLong z = nStartNode+1; z < nEndNode; z++ )
2519*b1cdbd2cSJim Jagielski 	{
2520*b1cdbd2cSJim Jagielski 		// Immer nStartNode+1, wegen Remove()!
2521*b1cdbd2cSJim Jagielski 		ImpRemoveParagraph( nStartNode+1 );
2522*b1cdbd2cSJim Jagielski 	}
2523*b1cdbd2cSJim Jagielski 
2524*b1cdbd2cSJim Jagielski 	if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
2525*b1cdbd2cSJim Jagielski 	{
2526*b1cdbd2cSJim Jagielski 		// Den Rest des StartNodes...
2527*b1cdbd2cSJim Jagielski 		sal_uInt16 nChars;
2528*b1cdbd2cSJim Jagielski 		nChars = aStartPaM.GetNode()->Len() - aStartPaM.GetIndex();
2529*b1cdbd2cSJim Jagielski 		ImpRemoveChars( aStartPaM, nChars );
2530*b1cdbd2cSJim Jagielski 		ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
2531*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteSelection(3)" );
2532*b1cdbd2cSJim Jagielski 		pPortion->MarkSelectionInvalid( aStartPaM.GetIndex(), aStartPaM.GetNode()->Len() );
2533*b1cdbd2cSJim Jagielski 
2534*b1cdbd2cSJim Jagielski 		// Den Anfang des EndNodes....
2535*b1cdbd2cSJim Jagielski 		nChars = aEndPaM.GetIndex();
2536*b1cdbd2cSJim Jagielski 		aEndPaM.SetIndex( 0 );
2537*b1cdbd2cSJim Jagielski 		ImpRemoveChars( aEndPaM, nChars );
2538*b1cdbd2cSJim Jagielski 		pPortion = FindParaPortion( aEndPaM.GetNode() );
2539*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteSelection(4)" );
2540*b1cdbd2cSJim Jagielski 		pPortion->MarkSelectionInvalid( 0, aEndPaM.GetNode()->Len() );
2541*b1cdbd2cSJim Jagielski 		// Zusammenfuegen....
2542*b1cdbd2cSJim Jagielski 		aStartPaM = ImpConnectParagraphs( aStartPaM.GetNode(), aEndPaM.GetNode() );
2543*b1cdbd2cSJim Jagielski 	}
2544*b1cdbd2cSJim Jagielski 	else
2545*b1cdbd2cSJim Jagielski 	{
2546*b1cdbd2cSJim Jagielski 		sal_uInt16 nChars;
2547*b1cdbd2cSJim Jagielski 		nChars = aEndPaM.GetIndex() - aStartPaM.GetIndex();
2548*b1cdbd2cSJim Jagielski 		ImpRemoveChars( aStartPaM, nChars );
2549*b1cdbd2cSJim Jagielski 		ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
2550*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pPortion, "Blinde Portion in ImpDeleteSelection(5)" );
2551*b1cdbd2cSJim Jagielski 		pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() );
2552*b1cdbd2cSJim Jagielski 	}
2553*b1cdbd2cSJim Jagielski 
2554*b1cdbd2cSJim Jagielski 	UpdateSelections();
2555*b1cdbd2cSJim Jagielski 	TextModified();
2556*b1cdbd2cSJim Jagielski 	return aStartPaM;
2557*b1cdbd2cSJim Jagielski }
2558*b1cdbd2cSJim Jagielski 
ImpRemoveParagraph(sal_uInt16 nPara)2559*b1cdbd2cSJim Jagielski void ImpEditEngine::ImpRemoveParagraph( sal_uInt16 nPara )
2560*b1cdbd2cSJim Jagielski {
2561*b1cdbd2cSJim Jagielski 	ContentNode* pNode = aEditDoc.SaveGetObject( nPara );
2562*b1cdbd2cSJim Jagielski 	ContentNode* pNextNode = aEditDoc.SaveGetObject( nPara+1 );
2563*b1cdbd2cSJim Jagielski 	ParaPortion* pPortion = GetParaPortions().SaveGetObject( nPara );
2564*b1cdbd2cSJim Jagielski 
2565*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pNode, "Blinder Node in ImpRemoveParagraph" );
2566*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPortion, "Blinde Portion in ImpRemoveParagraph(2)" );
2567*b1cdbd2cSJim Jagielski 
2568*b1cdbd2cSJim Jagielski 	DeletedNodeInfo* pInf = new DeletedNodeInfo( (sal_uLong)pNode, nPara );
2569*b1cdbd2cSJim Jagielski 	aDeletedNodes.Insert( pInf, aDeletedNodes.Count() );
2570*b1cdbd2cSJim Jagielski 
2571*b1cdbd2cSJim Jagielski 	// Der Node wird vom Undo verwaltet und ggf. zerstoert!
2572*b1cdbd2cSJim Jagielski 	/* delete */ aEditDoc.Remove( nPara );
2573*b1cdbd2cSJim Jagielski 	GetParaPortions().Remove( nPara );
2574*b1cdbd2cSJim Jagielski 	delete pPortion;
2575*b1cdbd2cSJim Jagielski 
2576*b1cdbd2cSJim Jagielski 	if ( IsCallParaInsertedOrDeleted() )
2577*b1cdbd2cSJim Jagielski 	{
2578*b1cdbd2cSJim Jagielski 		GetEditEnginePtr()->ParagraphDeleted( nPara );
2579*b1cdbd2cSJim Jagielski 	}
2580*b1cdbd2cSJim Jagielski 
2581*b1cdbd2cSJim Jagielski 	// Im folgenden muss ggf. Extra-Space neu ermittelt werden.
2582*b1cdbd2cSJim Jagielski 	// Bei ParaAttribsChanged wird leider der Absatz neu formatiert,
2583*b1cdbd2cSJim Jagielski 	// aber diese Methode sollte nicht Zeitkritsch sein!
2584*b1cdbd2cSJim Jagielski 	if ( pNextNode )
2585*b1cdbd2cSJim Jagielski 		ParaAttribsChanged( pNextNode );
2586*b1cdbd2cSJim Jagielski 
2587*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2588*b1cdbd2cSJim Jagielski 	if ( IsUndoEnabled() && !IsInUndo() )
2589*b1cdbd2cSJim Jagielski 		InsertUndo( new EditUndoDelContent( this, pNode, nPara ) );
2590*b1cdbd2cSJim Jagielski 	else
2591*b1cdbd2cSJim Jagielski #endif
2592*b1cdbd2cSJim Jagielski 	{
2593*b1cdbd2cSJim Jagielski 		aEditDoc.RemoveItemsFromPool( pNode );
2594*b1cdbd2cSJim Jagielski 		if ( pNode->GetStyleSheet() )
2595*b1cdbd2cSJim Jagielski 			EndListening( *pNode->GetStyleSheet(), sal_False );
2596*b1cdbd2cSJim Jagielski 		delete pNode;
2597*b1cdbd2cSJim Jagielski 	}
2598*b1cdbd2cSJim Jagielski }
2599*b1cdbd2cSJim Jagielski 
AutoCorrect(const EditSelection & rCurSel,xub_Unicode c,sal_Bool bOverwrite)2600*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::AutoCorrect( const EditSelection& rCurSel, xub_Unicode c, sal_Bool bOverwrite )
2601*b1cdbd2cSJim Jagielski {
2602*b1cdbd2cSJim Jagielski 	EditSelection aSel( rCurSel );
2603*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2604*b1cdbd2cSJim Jagielski 	SvxAutoCorrect*	pAutoCorrect = SvxAutoCorrCfg::Get()->GetAutoCorrect();
2605*b1cdbd2cSJim Jagielski 	if ( pAutoCorrect )
2606*b1cdbd2cSJim Jagielski 	{
2607*b1cdbd2cSJim Jagielski 		if ( aSel.HasRange() )
2608*b1cdbd2cSJim Jagielski 			aSel = ImpDeleteSelection( rCurSel );
2609*b1cdbd2cSJim Jagielski 
2610*b1cdbd2cSJim Jagielski 		// #i78661 allow application to turn off capitalization of
2611*b1cdbd2cSJim Jagielski 		// start sentence explicitly.
2612*b1cdbd2cSJim Jagielski 		// (This is done by setting IsFirstWordCapitalization to sal_False.)
2613*b1cdbd2cSJim Jagielski 		sal_Bool bOldCptlSttSntnc = pAutoCorrect->IsAutoCorrFlag( CptlSttSntnc );
2614*b1cdbd2cSJim Jagielski 		if (!IsFirstWordCapitalization())
2615*b1cdbd2cSJim Jagielski 		{
2616*b1cdbd2cSJim Jagielski 			ESelection aESel( CreateESel(aSel) );
2617*b1cdbd2cSJim Jagielski 			EditSelection aFirstWordSel;
2618*b1cdbd2cSJim Jagielski 			EditSelection aSecondWordSel;
2619*b1cdbd2cSJim Jagielski 			if (aESel.nEndPara == 0)	// is this the first para?
2620*b1cdbd2cSJim Jagielski 			{
2621*b1cdbd2cSJim Jagielski 				// select first word...
2622*b1cdbd2cSJim Jagielski 				// start by checking if para starts with word.
2623*b1cdbd2cSJim Jagielski 				aFirstWordSel = SelectWord( CreateSel(ESelection()) );
2624*b1cdbd2cSJim Jagielski 				if (aFirstWordSel.Min().GetIndex() == 0 && aFirstWordSel.Max().GetIndex() == 0)
2625*b1cdbd2cSJim Jagielski 				{
2626*b1cdbd2cSJim Jagielski 					// para does not start with word -> select next/first word
2627*b1cdbd2cSJim Jagielski 					EditPaM aRightWord( WordRight( aFirstWordSel.Max(), 1 ) );
2628*b1cdbd2cSJim Jagielski 					aFirstWordSel = SelectWord( EditSelection( aRightWord ) );
2629*b1cdbd2cSJim Jagielski 				}
2630*b1cdbd2cSJim Jagielski 
2631*b1cdbd2cSJim Jagielski 				// select second word
2632*b1cdbd2cSJim Jagielski 				// (sometimes aSel mightnot point to the end of the first word
2633*b1cdbd2cSJim Jagielski 				// but to some following char like '.'. ':', ...
2634*b1cdbd2cSJim Jagielski 				// In those cases we need aSecondWordSel to see if aSel
2635*b1cdbd2cSJim Jagielski 				// will actually effect the first word.)
2636*b1cdbd2cSJim Jagielski 				EditPaM aRight2Word( WordRight( aFirstWordSel.Max(), 1 ) );
2637*b1cdbd2cSJim Jagielski 				aSecondWordSel = SelectWord( EditSelection( aRight2Word ) );
2638*b1cdbd2cSJim Jagielski 			}
2639*b1cdbd2cSJim Jagielski 			sal_Bool bIsFirstWordInFirstPara = aESel.nEndPara == 0 &&
2640*b1cdbd2cSJim Jagielski 					aFirstWordSel.Max().GetIndex() <= aSel.Max().GetIndex() &&
2641*b1cdbd2cSJim Jagielski 					aSel.Max().GetIndex() <= aSecondWordSel.Min().GetIndex();
2642*b1cdbd2cSJim Jagielski 
2643*b1cdbd2cSJim Jagielski 			if (bIsFirstWordInFirstPara)
2644*b1cdbd2cSJim Jagielski 				pAutoCorrect->SetAutoCorrFlag( CptlSttSntnc, IsFirstWordCapitalization() );
2645*b1cdbd2cSJim Jagielski 		}
2646*b1cdbd2cSJim Jagielski 
2647*b1cdbd2cSJim Jagielski 		ContentNode* pNode = aSel.Max().GetNode();
2648*b1cdbd2cSJim Jagielski 		sal_uInt16 nIndex = aSel.Max().GetIndex();
2649*b1cdbd2cSJim Jagielski 		EdtAutoCorrDoc aAuto( this, pNode, nIndex, c );
2650*b1cdbd2cSJim Jagielski 		pAutoCorrect->AutoCorrect( aAuto, *pNode, nIndex, c, !bOverwrite );
2651*b1cdbd2cSJim Jagielski 		aSel.Max().SetIndex( aAuto.GetCursor() );
2652*b1cdbd2cSJim Jagielski 
2653*b1cdbd2cSJim Jagielski 		// #i78661 since the SvxAutoCorrect object used here is
2654*b1cdbd2cSJim Jagielski 		// shared we need to reset the value to it's original state.
2655*b1cdbd2cSJim Jagielski 		pAutoCorrect->SetAutoCorrFlag( CptlSttSntnc, bOldCptlSttSntnc );
2656*b1cdbd2cSJim Jagielski 	}
2657*b1cdbd2cSJim Jagielski #endif // !SVX_LIGHT
2658*b1cdbd2cSJim Jagielski 	return aSel.Max();
2659*b1cdbd2cSJim Jagielski }
2660*b1cdbd2cSJim Jagielski 
2661*b1cdbd2cSJim Jagielski 
InsertText(const EditSelection & rCurSel,xub_Unicode c,sal_Bool bOverwrite,sal_Bool bIsUserInput)2662*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::InsertText( const EditSelection& rCurSel,
2663*b1cdbd2cSJim Jagielski         xub_Unicode c, sal_Bool bOverwrite, sal_Bool bIsUserInput )
2664*b1cdbd2cSJim Jagielski {
2665*b1cdbd2cSJim Jagielski 	DBG_ASSERT( c != '\t', "Tab bei InsertText ?" );
2666*b1cdbd2cSJim Jagielski 	DBG_ASSERT( c != '\n', "Zeilenumbruch bei InsertText ?" );
2667*b1cdbd2cSJim Jagielski 
2668*b1cdbd2cSJim Jagielski 	EditPaM aPaM( rCurSel.Min() );
2669*b1cdbd2cSJim Jagielski 
2670*b1cdbd2cSJim Jagielski 	sal_Bool bDoOverwrite = ( bOverwrite &&
2671*b1cdbd2cSJim Jagielski 			( aPaM.GetIndex() < aPaM.GetNode()->Len() ) ) ? sal_True : sal_False;
2672*b1cdbd2cSJim Jagielski 
2673*b1cdbd2cSJim Jagielski 	sal_Bool bUndoAction = ( rCurSel.HasRange() || bDoOverwrite );
2674*b1cdbd2cSJim Jagielski 
2675*b1cdbd2cSJim Jagielski 	if ( bUndoAction )
2676*b1cdbd2cSJim Jagielski 		UndoActionStart( EDITUNDO_INSERT );
2677*b1cdbd2cSJim Jagielski 
2678*b1cdbd2cSJim Jagielski 	if ( rCurSel.HasRange() )
2679*b1cdbd2cSJim Jagielski 	{
2680*b1cdbd2cSJim Jagielski 		aPaM = ImpDeleteSelection( rCurSel );
2681*b1cdbd2cSJim Jagielski 	}
2682*b1cdbd2cSJim Jagielski 	else if ( bDoOverwrite )
2683*b1cdbd2cSJim Jagielski 	{
2684*b1cdbd2cSJim Jagielski 		// Wenn Selektion, dann nicht auch noch ein Zeichen ueberschreiben!
2685*b1cdbd2cSJim Jagielski 		EditSelection aTmpSel( aPaM );
2686*b1cdbd2cSJim Jagielski 		aTmpSel.Max().GetIndex()++;
2687*b1cdbd2cSJim Jagielski 		DBG_ASSERT( !aTmpSel.DbgIsBuggy( aEditDoc ), "Overwrite: Fehlerhafte Selektion!" );
2688*b1cdbd2cSJim Jagielski 		ImpDeleteSelection( aTmpSel );
2689*b1cdbd2cSJim Jagielski 	}
2690*b1cdbd2cSJim Jagielski 
2691*b1cdbd2cSJim Jagielski 	if ( aPaM.GetNode()->Len() < MAXCHARSINPARA )
2692*b1cdbd2cSJim Jagielski 	{
2693*b1cdbd2cSJim Jagielski         if (bIsUserInput && IsInputSequenceCheckingRequired( c, rCurSel ))
2694*b1cdbd2cSJim Jagielski         {
2695*b1cdbd2cSJim Jagielski             uno::Reference < i18n::XExtendedInputSequenceChecker > _xISC( ImplGetInputSequenceChecker() );
2696*b1cdbd2cSJim Jagielski             if (!pCTLOptions)
2697*b1cdbd2cSJim Jagielski                 pCTLOptions = new SvtCTLOptions;
2698*b1cdbd2cSJim Jagielski 
2699*b1cdbd2cSJim Jagielski             if (_xISC.is() || pCTLOptions)
2700*b1cdbd2cSJim Jagielski             {
2701*b1cdbd2cSJim Jagielski                 xub_StrLen nTmpPos = aPaM.GetIndex();
2702*b1cdbd2cSJim Jagielski                 sal_Int16 nCheckMode = pCTLOptions->IsCTLSequenceCheckingRestricted() ?
2703*b1cdbd2cSJim Jagielski                         i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
2704*b1cdbd2cSJim Jagielski 
2705*b1cdbd2cSJim Jagielski 				// the text that needs to be checked is only the one
2706*b1cdbd2cSJim Jagielski 				// before the current cursor position
2707*b1cdbd2cSJim Jagielski                 rtl::OUString aOldText( aPaM.GetNode()->Copy(0, nTmpPos) );
2708*b1cdbd2cSJim Jagielski                 rtl::OUString aNewText( aOldText );
2709*b1cdbd2cSJim Jagielski                 if (pCTLOptions->IsCTLSequenceCheckingTypeAndReplace())
2710*b1cdbd2cSJim Jagielski                 {
2711*b1cdbd2cSJim Jagielski                     /*const xub_StrLen nPrevPos = static_cast< xub_StrLen >*/( _xISC->correctInputSequence( aNewText, nTmpPos - 1, c, nCheckMode ) );
2712*b1cdbd2cSJim Jagielski 
2713*b1cdbd2cSJim Jagielski                     // find position of first character that has changed
2714*b1cdbd2cSJim Jagielski                     sal_Int32 nOldLen = aOldText.getLength();
2715*b1cdbd2cSJim Jagielski                     sal_Int32 nNewLen = aNewText.getLength();
2716*b1cdbd2cSJim Jagielski                     const sal_Unicode *pOldTxt = aOldText.getStr();
2717*b1cdbd2cSJim Jagielski                     const sal_Unicode *pNewTxt = aNewText.getStr();
2718*b1cdbd2cSJim Jagielski                     sal_Int32 nChgPos = 0;
2719*b1cdbd2cSJim Jagielski                     while ( nChgPos < nOldLen && nChgPos < nNewLen &&
2720*b1cdbd2cSJim Jagielski                             pOldTxt[nChgPos] == pNewTxt[nChgPos] )
2721*b1cdbd2cSJim Jagielski                         ++nChgPos;
2722*b1cdbd2cSJim Jagielski 
2723*b1cdbd2cSJim Jagielski                     xub_StrLen nChgLen = static_cast< xub_StrLen >( nNewLen - nChgPos );
2724*b1cdbd2cSJim Jagielski 					String aChgText( aNewText.copy( nChgPos ).getStr(), nChgLen );
2725*b1cdbd2cSJim Jagielski 
2726*b1cdbd2cSJim Jagielski                     // select text from first pos to be changed to current pos
2727*b1cdbd2cSJim Jagielski                     EditSelection aSel( EditPaM( aPaM.GetNode(), (sal_uInt16) nChgPos ), aPaM );
2728*b1cdbd2cSJim Jagielski 
2729*b1cdbd2cSJim Jagielski 					if (aChgText.Len())
2730*b1cdbd2cSJim Jagielski 						return InsertText( aSel, aChgText ); // implicitly handles undo
2731*b1cdbd2cSJim Jagielski 					else
2732*b1cdbd2cSJim Jagielski 						return aPaM;
2733*b1cdbd2cSJim Jagielski                 }
2734*b1cdbd2cSJim Jagielski                 else
2735*b1cdbd2cSJim Jagielski                 {
2736*b1cdbd2cSJim Jagielski                     // should the character be ignored (i.e. not get inserted) ?
2737*b1cdbd2cSJim Jagielski                     if (!_xISC->checkInputSequence( aOldText, nTmpPos - 1, c, nCheckMode ))
2738*b1cdbd2cSJim Jagielski                         return aPaM;    // nothing to be done -> no need for undo
2739*b1cdbd2cSJim Jagielski                 }
2740*b1cdbd2cSJim Jagielski             }
2741*b1cdbd2cSJim Jagielski 
2742*b1cdbd2cSJim Jagielski             // at this point now we will insert the character 'normally' some lines below...
2743*b1cdbd2cSJim Jagielski         }
2744*b1cdbd2cSJim Jagielski 
2745*b1cdbd2cSJim Jagielski 		if ( IsUndoEnabled() && !IsInUndo() )
2746*b1cdbd2cSJim Jagielski 		{
2747*b1cdbd2cSJim Jagielski 			EditUndoInsertChars* pNewUndo = new EditUndoInsertChars( this, CreateEPaM( aPaM ), c );
2748*b1cdbd2cSJim Jagielski 			sal_Bool bTryMerge = ( !bDoOverwrite && ( c != ' ' ) ) ? sal_True : sal_False;
2749*b1cdbd2cSJim Jagielski 			InsertUndo( pNewUndo, bTryMerge );
2750*b1cdbd2cSJim Jagielski 		}
2751*b1cdbd2cSJim Jagielski 
2752*b1cdbd2cSJim Jagielski         aEditDoc.InsertText( (const EditPaM&)aPaM, c );
2753*b1cdbd2cSJim Jagielski 		ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
2754*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pPortion, "Blinde Portion in InsertText" );
2755*b1cdbd2cSJim Jagielski         pPortion->MarkInvalid( aPaM.GetIndex(), 1 );
2756*b1cdbd2cSJim Jagielski         aPaM.GetIndex()++;   // macht EditDoc-Methode nicht mehr
2757*b1cdbd2cSJim Jagielski 	}
2758*b1cdbd2cSJim Jagielski 
2759*b1cdbd2cSJim Jagielski 	TextModified();
2760*b1cdbd2cSJim Jagielski 
2761*b1cdbd2cSJim Jagielski 	if ( bUndoAction )
2762*b1cdbd2cSJim Jagielski 		UndoActionEnd( EDITUNDO_INSERT );
2763*b1cdbd2cSJim Jagielski 
2764*b1cdbd2cSJim Jagielski 	return aPaM;
2765*b1cdbd2cSJim Jagielski }
2766*b1cdbd2cSJim Jagielski 
ImpInsertText(EditSelection aCurSel,const XubString & rStr)2767*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::ImpInsertText( EditSelection aCurSel, const XubString& rStr )
2768*b1cdbd2cSJim Jagielski {
2769*b1cdbd2cSJim Jagielski 	UndoActionStart( EDITUNDO_INSERT );
2770*b1cdbd2cSJim Jagielski 
2771*b1cdbd2cSJim Jagielski 	EditPaM aPaM;
2772*b1cdbd2cSJim Jagielski 	if ( aCurSel.HasRange() )
2773*b1cdbd2cSJim Jagielski 		aPaM = ImpDeleteSelection( aCurSel );
2774*b1cdbd2cSJim Jagielski 	else
2775*b1cdbd2cSJim Jagielski 		aPaM = aCurSel.Max();
2776*b1cdbd2cSJim Jagielski 
2777*b1cdbd2cSJim Jagielski 	EditPaM aCurPaM( aPaM );	// fuers Invalidieren
2778*b1cdbd2cSJim Jagielski 
2779*b1cdbd2cSJim Jagielski     // get word boundaries in order to clear possible WrongList entries
2780*b1cdbd2cSJim Jagielski     // and invalidate all the necessary text (everything after and including the
2781*b1cdbd2cSJim Jagielski     // start of the word)
2782*b1cdbd2cSJim Jagielski     // #i107201# do the expensive SelectWord call only if online spelling is active
2783*b1cdbd2cSJim Jagielski     EditSelection aCurWord;
2784*b1cdbd2cSJim Jagielski     if ( GetStatus().DoOnlineSpelling() )
2785*b1cdbd2cSJim Jagielski         aCurWord = SelectWord( aCurPaM, i18n::WordType::DICTIONARY_WORD );
2786*b1cdbd2cSJim Jagielski 
2787*b1cdbd2cSJim Jagielski 	XubString aText( rStr );
2788*b1cdbd2cSJim Jagielski 	aText.ConvertLineEnd( LINEEND_LF );
2789*b1cdbd2cSJim Jagielski 	SfxVoidItem aTabItem( EE_FEATURE_TAB );
2790*b1cdbd2cSJim Jagielski 
2791*b1cdbd2cSJim Jagielski 	// Konvertiert nach LineSep = \n
2792*b1cdbd2cSJim Jagielski 	// Token mit LINE_SEP abfragen,
2793*b1cdbd2cSJim Jagielski 	// da der MAC-Compiler aus \n etwas anderes macht!
2794*b1cdbd2cSJim Jagielski 
2795*b1cdbd2cSJim Jagielski 	// #117400
2796*b1cdbd2cSJim Jagielski 	// The loop run variable must be capable to hold STRLEN_MAX+1,
2797*b1cdbd2cSJim Jagielski 	// that with STRING32 would be SAL_MAX_INT32+1 but with 16-bit is 0xFFFF+1
2798*b1cdbd2cSJim Jagielski 	sal_uInt32 nStart = 0;
2799*b1cdbd2cSJim Jagielski 	while ( nStart < aText.Len() )
2800*b1cdbd2cSJim Jagielski 	{
2801*b1cdbd2cSJim Jagielski 		sal_uInt32 nEnd = aText.Search( LINE_SEP, static_cast<xub_StrLen>(nStart) );
2802*b1cdbd2cSJim Jagielski 		if ( nEnd == STRING_NOTFOUND )
2803*b1cdbd2cSJim Jagielski 			nEnd = aText.Len();	// nicht dereferenzieren!
2804*b1cdbd2cSJim Jagielski 
2805*b1cdbd2cSJim Jagielski 		// Start == End => Leerzeile
2806*b1cdbd2cSJim Jagielski 		if ( nEnd > nStart )
2807*b1cdbd2cSJim Jagielski 		{
2808*b1cdbd2cSJim Jagielski 			XubString aLine( aText, nStart, static_cast<xub_StrLen>(nEnd-nStart) );
2809*b1cdbd2cSJim Jagielski 			xub_StrLen nChars = aPaM.GetNode()->Len() + aLine.Len();
2810*b1cdbd2cSJim Jagielski 			if ( nChars > MAXCHARSINPARA )
2811*b1cdbd2cSJim Jagielski 			{
2812*b1cdbd2cSJim Jagielski 				xub_StrLen nMaxNewChars = MAXCHARSINPARA-aPaM.GetNode()->Len();
2813*b1cdbd2cSJim Jagielski 				nEnd -= ( aLine.Len() - nMaxNewChars );	// Dann landen die Zeichen im naechsten Absatz.
2814*b1cdbd2cSJim Jagielski 				aLine.Erase( nMaxNewChars );            // Del Rest...
2815*b1cdbd2cSJim Jagielski 			}
2816*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2817*b1cdbd2cSJim Jagielski 			if ( IsUndoEnabled() && !IsInUndo() )
2818*b1cdbd2cSJim Jagielski 				InsertUndo( new EditUndoInsertChars( this, CreateEPaM( aPaM ), aLine ) );
2819*b1cdbd2cSJim Jagielski #endif
2820*b1cdbd2cSJim Jagielski 			// Tabs ?
2821*b1cdbd2cSJim Jagielski 			if ( aLine.Search( '\t' ) == STRING_NOTFOUND )
2822*b1cdbd2cSJim Jagielski 				aPaM = aEditDoc.InsertText( aPaM, aLine );
2823*b1cdbd2cSJim Jagielski 			else
2824*b1cdbd2cSJim Jagielski 			{
2825*b1cdbd2cSJim Jagielski 				sal_uInt32 nStart2 = 0;
2826*b1cdbd2cSJim Jagielski 				while ( nStart2 < aLine.Len() )
2827*b1cdbd2cSJim Jagielski 				{
2828*b1cdbd2cSJim Jagielski 					sal_uInt32 nEnd2 = aLine.Search( '\t', static_cast<xub_StrLen>(nStart2) );
2829*b1cdbd2cSJim Jagielski 					if ( nEnd2 == STRING_NOTFOUND )
2830*b1cdbd2cSJim Jagielski 						nEnd2 = aLine.Len();	// nicht dereferenzieren!
2831*b1cdbd2cSJim Jagielski 
2832*b1cdbd2cSJim Jagielski 					if ( nEnd2 > nStart2 )
2833*b1cdbd2cSJim Jagielski 						aPaM = aEditDoc.InsertText( aPaM, XubString( aLine,
2834*b1cdbd2cSJim Jagielski 							static_cast<xub_StrLen>(nStart2),
2835*b1cdbd2cSJim Jagielski 							static_cast<xub_StrLen>(nEnd2-nStart2 ) ) );
2836*b1cdbd2cSJim Jagielski 					if ( nEnd2 < aLine.Len() )
2837*b1cdbd2cSJim Jagielski 					{
2838*b1cdbd2cSJim Jagielski 						// aPaM = ImpInsertFeature( EditSelection( aPaM, aPaM ),  );
2839*b1cdbd2cSJim Jagielski 						aPaM = aEditDoc.InsertFeature( aPaM, aTabItem );
2840*b1cdbd2cSJim Jagielski 					}
2841*b1cdbd2cSJim Jagielski 					nStart2 = nEnd2+1;
2842*b1cdbd2cSJim Jagielski 				}
2843*b1cdbd2cSJim Jagielski 			}
2844*b1cdbd2cSJim Jagielski 			ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
2845*b1cdbd2cSJim Jagielski 			DBG_ASSERT( pPortion, "Blinde Portion in InsertText" );
2846*b1cdbd2cSJim Jagielski 
2847*b1cdbd2cSJim Jagielski             if ( GetStatus().DoOnlineSpelling() )
2848*b1cdbd2cSJim Jagielski             {
2849*b1cdbd2cSJim Jagielski                 // now remove the Wrongs (red spell check marks) from both words...
2850*b1cdbd2cSJim Jagielski                 WrongList *pWrongs = aCurPaM.GetNode()->GetWrongList();
2851*b1cdbd2cSJim Jagielski                 if (pWrongs && pWrongs->HasWrongs())
2852*b1cdbd2cSJim Jagielski                     pWrongs->ClearWrongs( aCurWord.Min().GetIndex(), aPaM.GetIndex(), aPaM.GetNode() );
2853*b1cdbd2cSJim Jagielski                 // ... and mark both words as 'to be checked again'
2854*b1cdbd2cSJim Jagielski                 pPortion->MarkInvalid( aCurWord.Min().GetIndex(), aLine.Len() );
2855*b1cdbd2cSJim Jagielski             }
2856*b1cdbd2cSJim Jagielski             else
2857*b1cdbd2cSJim Jagielski                 pPortion->MarkInvalid( aCurPaM.GetIndex(), aLine.Len() );
2858*b1cdbd2cSJim Jagielski 		}
2859*b1cdbd2cSJim Jagielski 		if ( nEnd < aText.Len() )
2860*b1cdbd2cSJim Jagielski 			aPaM = ImpInsertParaBreak( aPaM );
2861*b1cdbd2cSJim Jagielski 
2862*b1cdbd2cSJim Jagielski 		nStart = nEnd+1;
2863*b1cdbd2cSJim Jagielski 	}
2864*b1cdbd2cSJim Jagielski 
2865*b1cdbd2cSJim Jagielski 	UndoActionEnd( EDITUNDO_INSERT );
2866*b1cdbd2cSJim Jagielski 
2867*b1cdbd2cSJim Jagielski 	TextModified();
2868*b1cdbd2cSJim Jagielski 	return aPaM;
2869*b1cdbd2cSJim Jagielski }
2870*b1cdbd2cSJim Jagielski 
ImpFastInsertText(EditPaM aPaM,const XubString & rStr)2871*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::ImpFastInsertText( EditPaM aPaM, const XubString& rStr )
2872*b1cdbd2cSJim Jagielski {
2873*b1cdbd2cSJim Jagielski 	DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "FastInsertText: Zeilentrenner nicht erlaubt!" );
2874*b1cdbd2cSJim Jagielski 	DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "FastInsertText: Zeilentrenner nicht erlaubt!" );
2875*b1cdbd2cSJim Jagielski 	DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "FastInsertText: Features nicht erlaubt!" );
2876*b1cdbd2cSJim Jagielski 
2877*b1cdbd2cSJim Jagielski 	if ( ( aPaM.GetNode()->Len() + rStr.Len() ) < MAXCHARSINPARA )
2878*b1cdbd2cSJim Jagielski 	{
2879*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2880*b1cdbd2cSJim Jagielski 		if ( IsUndoEnabled() && !IsInUndo() )
2881*b1cdbd2cSJim Jagielski 			InsertUndo( new EditUndoInsertChars( this, CreateEPaM( aPaM ), rStr ) );
2882*b1cdbd2cSJim Jagielski #endif
2883*b1cdbd2cSJim Jagielski 
2884*b1cdbd2cSJim Jagielski 		aPaM = aEditDoc.InsertText( aPaM, rStr );
2885*b1cdbd2cSJim Jagielski 		TextModified();
2886*b1cdbd2cSJim Jagielski 	}
2887*b1cdbd2cSJim Jagielski 	else
2888*b1cdbd2cSJim Jagielski 	{
2889*b1cdbd2cSJim Jagielski 		aPaM = ImpInsertText( aPaM, rStr );
2890*b1cdbd2cSJim Jagielski 	}
2891*b1cdbd2cSJim Jagielski 
2892*b1cdbd2cSJim Jagielski 	return aPaM;
2893*b1cdbd2cSJim Jagielski }
2894*b1cdbd2cSJim Jagielski 
ImpInsertFeature(EditSelection aCurSel,const SfxPoolItem & rItem)2895*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::ImpInsertFeature( EditSelection aCurSel, const SfxPoolItem& rItem )
2896*b1cdbd2cSJim Jagielski {
2897*b1cdbd2cSJim Jagielski 	EditPaM aPaM;
2898*b1cdbd2cSJim Jagielski 	if ( aCurSel.HasRange() )
2899*b1cdbd2cSJim Jagielski 		aPaM = ImpDeleteSelection( aCurSel );
2900*b1cdbd2cSJim Jagielski 	else
2901*b1cdbd2cSJim Jagielski 		aPaM = aCurSel.Max();
2902*b1cdbd2cSJim Jagielski 
2903*b1cdbd2cSJim Jagielski 	if ( aPaM.GetIndex() >= 0xfffe )
2904*b1cdbd2cSJim Jagielski 		return aPaM;
2905*b1cdbd2cSJim Jagielski 
2906*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2907*b1cdbd2cSJim Jagielski 	if ( IsUndoEnabled() && !IsInUndo() )
2908*b1cdbd2cSJim Jagielski 		InsertUndo( new EditUndoInsertFeature( this, CreateEPaM( aPaM ), rItem ) );
2909*b1cdbd2cSJim Jagielski #endif
2910*b1cdbd2cSJim Jagielski 	aPaM = aEditDoc.InsertFeature( aPaM, rItem );
2911*b1cdbd2cSJim Jagielski 
2912*b1cdbd2cSJim Jagielski 	ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
2913*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPortion, "Blinde Portion in InsertFeature" );
2914*b1cdbd2cSJim Jagielski 	pPortion->MarkInvalid( aPaM.GetIndex()-1, 1 );
2915*b1cdbd2cSJim Jagielski 
2916*b1cdbd2cSJim Jagielski 	TextModified();
2917*b1cdbd2cSJim Jagielski 
2918*b1cdbd2cSJim Jagielski 	return aPaM;
2919*b1cdbd2cSJim Jagielski }
2920*b1cdbd2cSJim Jagielski 
ImpInsertParaBreak(const EditSelection & rCurSel,sal_Bool bKeepEndingAttribs)2921*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::ImpInsertParaBreak( const EditSelection& rCurSel, sal_Bool bKeepEndingAttribs )
2922*b1cdbd2cSJim Jagielski {
2923*b1cdbd2cSJim Jagielski 	EditPaM aPaM;
2924*b1cdbd2cSJim Jagielski 	if ( rCurSel.HasRange() )
2925*b1cdbd2cSJim Jagielski 		aPaM = ImpDeleteSelection( rCurSel );
2926*b1cdbd2cSJim Jagielski 	else
2927*b1cdbd2cSJim Jagielski 		aPaM = rCurSel.Max();
2928*b1cdbd2cSJim Jagielski 
2929*b1cdbd2cSJim Jagielski 	return ImpInsertParaBreak( aPaM, bKeepEndingAttribs );
2930*b1cdbd2cSJim Jagielski }
2931*b1cdbd2cSJim Jagielski 
ImpInsertParaBreak(const EditPaM & rPaM,sal_Bool bKeepEndingAttribs)2932*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::ImpInsertParaBreak( const EditPaM& rPaM, sal_Bool bKeepEndingAttribs )
2933*b1cdbd2cSJim Jagielski {
2934*b1cdbd2cSJim Jagielski 	if ( aEditDoc.Count() >= 0xFFFE )
2935*b1cdbd2cSJim Jagielski 	{
2936*b1cdbd2cSJim Jagielski 		DBG_ERROR( "Can't process more than 64K paragraphs!" );
2937*b1cdbd2cSJim Jagielski 		return rPaM;
2938*b1cdbd2cSJim Jagielski 	}
2939*b1cdbd2cSJim Jagielski 
2940*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2941*b1cdbd2cSJim Jagielski 	if ( IsUndoEnabled() && !IsInUndo() )
2942*b1cdbd2cSJim Jagielski 		InsertUndo( new EditUndoSplitPara( this, aEditDoc.GetPos( rPaM.GetNode() ), rPaM.GetIndex() ) );
2943*b1cdbd2cSJim Jagielski #endif
2944*b1cdbd2cSJim Jagielski 
2945*b1cdbd2cSJim Jagielski 	EditPaM aPaM( aEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) );
2946*b1cdbd2cSJim Jagielski 
2947*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
2948*b1cdbd2cSJim Jagielski 	if ( GetStatus().DoOnlineSpelling() )
2949*b1cdbd2cSJim Jagielski 	{
2950*b1cdbd2cSJim Jagielski 		xub_StrLen nEnd = rPaM.GetNode()->Len();
2951*b1cdbd2cSJim Jagielski 		aPaM.GetNode()->CreateWrongList();
2952*b1cdbd2cSJim Jagielski 		WrongList* pLWrongs = rPaM.GetNode()->GetWrongList();
2953*b1cdbd2cSJim Jagielski 		WrongList* pRWrongs = aPaM.GetNode()->GetWrongList();
2954*b1cdbd2cSJim Jagielski 		// Falschgeschriebene Woerter ruebernehmen:
2955*b1cdbd2cSJim Jagielski 		sal_uInt16 nLWrongs = pLWrongs->Count();
2956*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 nW = 0; nW < nLWrongs; nW++ )
2957*b1cdbd2cSJim Jagielski 		{
2958*b1cdbd2cSJim Jagielski 			WrongRange& rWrong = pLWrongs->GetObject( nW );
2959*b1cdbd2cSJim Jagielski 			// Nur wenn wirklich dahinter, ein ueberlappendes wird beim Spell korrigiert
2960*b1cdbd2cSJim Jagielski 			if ( rWrong.nStart > nEnd )
2961*b1cdbd2cSJim Jagielski 			{
2962*b1cdbd2cSJim Jagielski 				pRWrongs->InsertWrong( rWrong, pRWrongs->Count() );
2963*b1cdbd2cSJim Jagielski 				WrongRange& rRWrong = pRWrongs->GetObject( pRWrongs->Count() - 1 );
2964*b1cdbd2cSJim Jagielski 				rRWrong.nStart = rRWrong.nStart - nEnd;
2965*b1cdbd2cSJim Jagielski 				rRWrong.nEnd = rRWrong.nEnd - nEnd;
2966*b1cdbd2cSJim Jagielski 			}
2967*b1cdbd2cSJim Jagielski 			else if ( ( rWrong.nStart < nEnd ) && ( rWrong.nEnd > nEnd ) )
2968*b1cdbd2cSJim Jagielski 				rWrong.nEnd = nEnd;
2969*b1cdbd2cSJim Jagielski 		}
2970*b1cdbd2cSJim Jagielski 		sal_uInt16 nInv = nEnd ? nEnd-1 : nEnd;
2971*b1cdbd2cSJim Jagielski 		if ( nEnd )
2972*b1cdbd2cSJim Jagielski 			pLWrongs->MarkInvalid( nInv, nEnd );
2973*b1cdbd2cSJim Jagielski 		else
2974*b1cdbd2cSJim Jagielski 			pLWrongs->SetValid();
2975*b1cdbd2cSJim Jagielski 		pRWrongs->SetValid(); // sonst 0 - 0xFFFF
2976*b1cdbd2cSJim Jagielski 		pRWrongs->MarkInvalid( 0, 1 );	// Nur das erste Wort testen
2977*b1cdbd2cSJim Jagielski 	}
2978*b1cdbd2cSJim Jagielski #endif // !SVX_LIGHT
2979*b1cdbd2cSJim Jagielski 
2980*b1cdbd2cSJim Jagielski 
2981*b1cdbd2cSJim Jagielski 	ParaPortion* pPortion = FindParaPortion( rPaM.GetNode() );
2982*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPortion, "Blinde Portion in ImpInsertParaBreak" );
2983*b1cdbd2cSJim Jagielski 	pPortion->MarkInvalid( rPaM.GetIndex(), 0 );
2984*b1cdbd2cSJim Jagielski 
2985*b1cdbd2cSJim Jagielski 	// Optimieren: Nicht unnoetig viele GetPos auf die Listen ansetzen!
2986*b1cdbd2cSJim Jagielski 	// Hier z.B. bei Undo, aber auch in allen anderen Methoden.
2987*b1cdbd2cSJim Jagielski 	sal_uInt16 nPos = GetParaPortions().GetPos( pPortion );
2988*b1cdbd2cSJim Jagielski 	ParaPortion* pNewPortion = new ParaPortion( aPaM.GetNode() );
2989*b1cdbd2cSJim Jagielski 	GetParaPortions().Insert( pNewPortion, nPos + 1 );
2990*b1cdbd2cSJim Jagielski 	ParaAttribsChanged( pNewPortion->GetNode() );
2991*b1cdbd2cSJim Jagielski 	if ( IsCallParaInsertedOrDeleted() )
2992*b1cdbd2cSJim Jagielski 		GetEditEnginePtr()->ParagraphInserted( nPos+1 );
2993*b1cdbd2cSJim Jagielski 
2994*b1cdbd2cSJim Jagielski 	CursorMoved( rPaM.GetNode() );	// falls leeres Attribut entstanden.
2995*b1cdbd2cSJim Jagielski 	TextModified();
2996*b1cdbd2cSJim Jagielski 	return aPaM;
2997*b1cdbd2cSJim Jagielski }
2998*b1cdbd2cSJim Jagielski 
ImpFastInsertParagraph(sal_uInt16 nPara)2999*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::ImpFastInsertParagraph( sal_uInt16 nPara )
3000*b1cdbd2cSJim Jagielski {
3001*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
3002*b1cdbd2cSJim Jagielski 	if ( IsUndoEnabled() && !IsInUndo() )
3003*b1cdbd2cSJim Jagielski 	{
3004*b1cdbd2cSJim Jagielski 		if ( nPara )
3005*b1cdbd2cSJim Jagielski 		{
3006*b1cdbd2cSJim Jagielski 			DBG_ASSERT( aEditDoc.SaveGetObject( nPara-1 ), "FastInsertParagraph: Prev existiert nicht" );
3007*b1cdbd2cSJim Jagielski 			InsertUndo( new EditUndoSplitPara( this, nPara-1, aEditDoc.GetObject( nPara-1 )->Len() ) );
3008*b1cdbd2cSJim Jagielski 		}
3009*b1cdbd2cSJim Jagielski 		else
3010*b1cdbd2cSJim Jagielski 			InsertUndo( new EditUndoSplitPara( this, 0, 0 ) );
3011*b1cdbd2cSJim Jagielski 	}
3012*b1cdbd2cSJim Jagielski #endif
3013*b1cdbd2cSJim Jagielski 
3014*b1cdbd2cSJim Jagielski 	ContentNode* pNode = new ContentNode( aEditDoc.GetItemPool() );
3015*b1cdbd2cSJim Jagielski 	// Falls FlatMode, wird spaeter kein Font eingestellt:
3016*b1cdbd2cSJim Jagielski 	pNode->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont();
3017*b1cdbd2cSJim Jagielski 
3018*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
3019*b1cdbd2cSJim Jagielski 	if ( GetStatus().DoOnlineSpelling() )
3020*b1cdbd2cSJim Jagielski 		pNode->CreateWrongList();
3021*b1cdbd2cSJim Jagielski #endif // !SVX_LIGHT
3022*b1cdbd2cSJim Jagielski 
3023*b1cdbd2cSJim Jagielski 	aEditDoc.Insert( pNode, nPara );
3024*b1cdbd2cSJim Jagielski 
3025*b1cdbd2cSJim Jagielski 	ParaPortion* pNewPortion = new ParaPortion( pNode );
3026*b1cdbd2cSJim Jagielski 	GetParaPortions().Insert( pNewPortion, nPara );
3027*b1cdbd2cSJim Jagielski 	if ( IsCallParaInsertedOrDeleted() )
3028*b1cdbd2cSJim Jagielski 		GetEditEnginePtr()->ParagraphInserted( nPara );
3029*b1cdbd2cSJim Jagielski 
3030*b1cdbd2cSJim Jagielski 	return EditPaM( pNode, 0 );
3031*b1cdbd2cSJim Jagielski }
3032*b1cdbd2cSJim Jagielski 
InsertParaBreak(EditSelection aCurSel)3033*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::InsertParaBreak( EditSelection aCurSel )
3034*b1cdbd2cSJim Jagielski {
3035*b1cdbd2cSJim Jagielski 	EditPaM aPaM( ImpInsertParaBreak( aCurSel ) );
3036*b1cdbd2cSJim Jagielski 	if ( aStatus.DoAutoIndenting() )
3037*b1cdbd2cSJim Jagielski 	{
3038*b1cdbd2cSJim Jagielski 		sal_uInt16 nPara = aEditDoc.GetPos( aPaM.GetNode() );
3039*b1cdbd2cSJim Jagielski 		DBG_ASSERT( nPara > 0, "AutoIndenting: Fehler!" );
3040*b1cdbd2cSJim Jagielski 		XubString aPrevParaText( GetEditDoc().GetParaAsString( nPara-1 ) );
3041*b1cdbd2cSJim Jagielski 		sal_uInt16 n = 0;
3042*b1cdbd2cSJim Jagielski 		while ( ( n < aPrevParaText.Len() ) &&
3043*b1cdbd2cSJim Jagielski 				( ( aPrevParaText.GetChar(n) == ' ' ) || ( aPrevParaText.GetChar(n) == '\t' ) ) )
3044*b1cdbd2cSJim Jagielski 		{
3045*b1cdbd2cSJim Jagielski 			if ( aPrevParaText.GetChar(n) == '\t' )
3046*b1cdbd2cSJim Jagielski 				aPaM = ImpInsertFeature( aPaM, SfxVoidItem( EE_FEATURE_TAB ) );
3047*b1cdbd2cSJim Jagielski 			else
3048*b1cdbd2cSJim Jagielski 				aPaM = ImpInsertText( aPaM, aPrevParaText.GetChar(n) );
3049*b1cdbd2cSJim Jagielski 			n++;
3050*b1cdbd2cSJim Jagielski 		}
3051*b1cdbd2cSJim Jagielski 
3052*b1cdbd2cSJim Jagielski 	}
3053*b1cdbd2cSJim Jagielski 	return aPaM;
3054*b1cdbd2cSJim Jagielski }
3055*b1cdbd2cSJim Jagielski 
InsertTab(EditSelection aCurSel)3056*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::InsertTab( EditSelection aCurSel )
3057*b1cdbd2cSJim Jagielski {
3058*b1cdbd2cSJim Jagielski 	EditPaM aPaM( ImpInsertFeature( aCurSel, SfxVoidItem( EE_FEATURE_TAB ) ) );
3059*b1cdbd2cSJim Jagielski 	return aPaM;
3060*b1cdbd2cSJim Jagielski }
3061*b1cdbd2cSJim Jagielski 
InsertField(EditSelection aCurSel,const SvxFieldItem & rFld)3062*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::InsertField( EditSelection aCurSel, const SvxFieldItem& rFld )
3063*b1cdbd2cSJim Jagielski {
3064*b1cdbd2cSJim Jagielski 	EditPaM aPaM( ImpInsertFeature( aCurSel, rFld ) );
3065*b1cdbd2cSJim Jagielski 	return aPaM;
3066*b1cdbd2cSJim Jagielski }
3067*b1cdbd2cSJim Jagielski 
UpdateFields()3068*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::UpdateFields()
3069*b1cdbd2cSJim Jagielski {
3070*b1cdbd2cSJim Jagielski 	sal_Bool bChanges = sal_False;
3071*b1cdbd2cSJim Jagielski 	sal_uInt16 nParas = GetEditDoc().Count();
3072*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nPara = 0; nPara < nParas; nPara++ )
3073*b1cdbd2cSJim Jagielski 	{
3074*b1cdbd2cSJim Jagielski 		sal_Bool bChangesInPara = sal_False;
3075*b1cdbd2cSJim Jagielski 		ContentNode* pNode = GetEditDoc().GetObject( nPara );
3076*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pNode, "NULL-Pointer im Doc" );
3077*b1cdbd2cSJim Jagielski 		CharAttribArray& rAttribs = pNode->GetCharAttribs().GetAttribs();
3078*b1cdbd2cSJim Jagielski //		sal_uInt16 nAttrs = rAttribs.Count();
3079*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 nAttr = 0; nAttr < rAttribs.Count(); nAttr++ )
3080*b1cdbd2cSJim Jagielski 		{
3081*b1cdbd2cSJim Jagielski 			EditCharAttrib* pAttr = rAttribs[nAttr];
3082*b1cdbd2cSJim Jagielski 			if ( pAttr->Which() == EE_FEATURE_FIELD )
3083*b1cdbd2cSJim Jagielski 			{
3084*b1cdbd2cSJim Jagielski 				EditCharAttribField* pField = (EditCharAttribField*)pAttr;
3085*b1cdbd2cSJim Jagielski 				EditCharAttribField* pCurrent = new EditCharAttribField( *pField );
3086*b1cdbd2cSJim Jagielski 				pField->Reset();
3087*b1cdbd2cSJim Jagielski 
3088*b1cdbd2cSJim Jagielski                 if ( aStatus.MarkFields() )
3089*b1cdbd2cSJim Jagielski                     pField->GetFldColor() = new Color( GetColorConfig().GetColorValue( svtools::WRITERFIELDSHADINGS ).nColor );
3090*b1cdbd2cSJim Jagielski 
3091*b1cdbd2cSJim Jagielski 				XubString aFldValue = GetEditEnginePtr()->CalcFieldValue(
3092*b1cdbd2cSJim Jagielski 										(const SvxFieldItem&)*pField->GetItem(),
3093*b1cdbd2cSJim Jagielski 										nPara, pField->GetStart(),
3094*b1cdbd2cSJim Jagielski 										pField->GetTxtColor(), pField->GetFldColor() );
3095*b1cdbd2cSJim Jagielski 				pField->GetFieldValue() = aFldValue;
3096*b1cdbd2cSJim Jagielski 				if ( *pField != *pCurrent )
3097*b1cdbd2cSJim Jagielski 				{
3098*b1cdbd2cSJim Jagielski 					bChanges = sal_True;
3099*b1cdbd2cSJim Jagielski 					bChangesInPara = sal_True;
3100*b1cdbd2cSJim Jagielski 				}
3101*b1cdbd2cSJim Jagielski 				delete pCurrent;
3102*b1cdbd2cSJim Jagielski 			}
3103*b1cdbd2cSJim Jagielski 		}
3104*b1cdbd2cSJim Jagielski 		if ( bChangesInPara )
3105*b1cdbd2cSJim Jagielski 		{
3106*b1cdbd2cSJim Jagielski 			// ggf. etwas genauer invalidieren.
3107*b1cdbd2cSJim Jagielski 			ParaPortion* pPortion = GetParaPortions().GetObject( nPara );
3108*b1cdbd2cSJim Jagielski 			DBG_ASSERT( pPortion, "NULL-Pointer im Doc" );
3109*b1cdbd2cSJim Jagielski 			pPortion->MarkSelectionInvalid( 0, pNode->Len() );
3110*b1cdbd2cSJim Jagielski 		}
3111*b1cdbd2cSJim Jagielski 	}
3112*b1cdbd2cSJim Jagielski 	return bChanges;
3113*b1cdbd2cSJim Jagielski }
3114*b1cdbd2cSJim Jagielski 
InsertLineBreak(EditSelection aCurSel)3115*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::InsertLineBreak( EditSelection aCurSel )
3116*b1cdbd2cSJim Jagielski {
3117*b1cdbd2cSJim Jagielski 	EditPaM aPaM( ImpInsertFeature( aCurSel, SfxVoidItem( EE_FEATURE_LINEBR ) ) );
3118*b1cdbd2cSJim Jagielski 	return aPaM;
3119*b1cdbd2cSJim Jagielski }
3120*b1cdbd2cSJim Jagielski 
3121*b1cdbd2cSJim Jagielski //	----------------------------------------------------------------------
3122*b1cdbd2cSJim Jagielski //	Hilfsfunktionen
3123*b1cdbd2cSJim Jagielski //	----------------------------------------------------------------------
PaMtoEditCursor(EditPaM aPaM,sal_uInt16 nFlags)3124*b1cdbd2cSJim Jagielski Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, sal_uInt16 nFlags )
3125*b1cdbd2cSJim Jagielski {
3126*b1cdbd2cSJim Jagielski 	DBG_ASSERT( GetUpdateMode(), "Darf bei Update=sal_False nicht erreicht werden: PaMtoEditCursor" );
3127*b1cdbd2cSJim Jagielski 
3128*b1cdbd2cSJim Jagielski 	Rectangle aEditCursor;
3129*b1cdbd2cSJim Jagielski 	long nY = 0;
3130*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
3131*b1cdbd2cSJim Jagielski 	{
3132*b1cdbd2cSJim Jagielski 		ParaPortion* pPortion = GetParaPortions().GetObject(nPortion);
3133*b1cdbd2cSJim Jagielski 		ContentNode* pNode = pPortion->GetNode();
3134*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pNode, "Ungueltiger Node in Portion!" );
3135*b1cdbd2cSJim Jagielski 		if ( pNode != aPaM.GetNode() )
3136*b1cdbd2cSJim Jagielski 		{
3137*b1cdbd2cSJim Jagielski 			nY += pPortion->GetHeight();
3138*b1cdbd2cSJim Jagielski 		}
3139*b1cdbd2cSJim Jagielski 		else
3140*b1cdbd2cSJim Jagielski 		{
3141*b1cdbd2cSJim Jagielski 			aEditCursor = GetEditCursor( pPortion, aPaM.GetIndex(), nFlags );
3142*b1cdbd2cSJim Jagielski 			aEditCursor.Top() += nY;
3143*b1cdbd2cSJim Jagielski 			aEditCursor.Bottom() += nY;
3144*b1cdbd2cSJim Jagielski 			return aEditCursor;
3145*b1cdbd2cSJim Jagielski 		}
3146*b1cdbd2cSJim Jagielski 	}
3147*b1cdbd2cSJim Jagielski 	DBG_ERROR( "Portion nicht gefunden!" );
3148*b1cdbd2cSJim Jagielski 	return aEditCursor;
3149*b1cdbd2cSJim Jagielski }
3150*b1cdbd2cSJim Jagielski 
GetPaM(Point aDocPos,sal_Bool bSmart)3151*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::GetPaM( Point aDocPos, sal_Bool bSmart )
3152*b1cdbd2cSJim Jagielski {
3153*b1cdbd2cSJim Jagielski 	DBG_ASSERT( GetUpdateMode(), "Darf bei Update=sal_False nicht erreicht werden: GetPaM" );
3154*b1cdbd2cSJim Jagielski 
3155*b1cdbd2cSJim Jagielski 	long nY = 0;
3156*b1cdbd2cSJim Jagielski 	long nTmpHeight;
3157*b1cdbd2cSJim Jagielski 	EditPaM aPaM;
3158*b1cdbd2cSJim Jagielski 	sal_uInt16 nPortion;
3159*b1cdbd2cSJim Jagielski 	for ( nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
3160*b1cdbd2cSJim Jagielski 	{
3161*b1cdbd2cSJim Jagielski 		ParaPortion* pPortion = GetParaPortions().GetObject(nPortion);
3162*b1cdbd2cSJim Jagielski 		nTmpHeight = pPortion->GetHeight(); 	// sollte auch bei !bVisible richtig sein!
3163*b1cdbd2cSJim Jagielski 		nY += nTmpHeight;
3164*b1cdbd2cSJim Jagielski 		if ( nY > aDocPos.Y() )
3165*b1cdbd2cSJim Jagielski 		{
3166*b1cdbd2cSJim Jagielski 			nY -= nTmpHeight;
3167*b1cdbd2cSJim Jagielski 			aDocPos.Y() -= nY;
3168*b1cdbd2cSJim Jagielski 			// unsichtbare Portions ueberspringen:
3169*b1cdbd2cSJim Jagielski 			while ( pPortion && !pPortion->IsVisible() )
3170*b1cdbd2cSJim Jagielski 			{
3171*b1cdbd2cSJim Jagielski 				nPortion++;
3172*b1cdbd2cSJim Jagielski 				pPortion = GetParaPortions().SaveGetObject( nPortion );
3173*b1cdbd2cSJim Jagielski 			}
3174*b1cdbd2cSJim Jagielski 			DBG_ASSERT( pPortion, "Keinen sichtbaren Absatz gefunden: GetPaM" );
3175*b1cdbd2cSJim Jagielski 			aPaM = GetPaM( pPortion, aDocPos, bSmart );
3176*b1cdbd2cSJim Jagielski 			return aPaM;
3177*b1cdbd2cSJim Jagielski 
3178*b1cdbd2cSJim Jagielski 		}
3179*b1cdbd2cSJim Jagielski 	}
3180*b1cdbd2cSJim Jagielski 	// Dann den letzten sichtbaren Suchen:
3181*b1cdbd2cSJim Jagielski 	nPortion = GetParaPortions().Count()-1;
3182*b1cdbd2cSJim Jagielski 	while ( nPortion && !GetParaPortions()[nPortion]->IsVisible() )
3183*b1cdbd2cSJim Jagielski 		nPortion--;
3184*b1cdbd2cSJim Jagielski 
3185*b1cdbd2cSJim Jagielski 	DBG_ASSERT( GetParaPortions()[nPortion]->IsVisible(), "Keinen sichtbaren Absatz gefunden: GetPaM" );
3186*b1cdbd2cSJim Jagielski 	aPaM.SetNode( GetParaPortions()[nPortion]->GetNode() );
3187*b1cdbd2cSJim Jagielski 	aPaM.SetIndex( GetParaPortions()[nPortion]->GetNode()->Len() );
3188*b1cdbd2cSJim Jagielski 	return aPaM;
3189*b1cdbd2cSJim Jagielski }
3190*b1cdbd2cSJim Jagielski 
GetTextHeight() const3191*b1cdbd2cSJim Jagielski sal_uInt32 ImpEditEngine::GetTextHeight() const
3192*b1cdbd2cSJim Jagielski {
3193*b1cdbd2cSJim Jagielski 	DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: GetTextHeight" );
3194*b1cdbd2cSJim Jagielski 	DBG_ASSERT( IsFormatted() || IsFormatting(), "GetTextHeight: Nicht formatiert" );
3195*b1cdbd2cSJim Jagielski 	return nCurTextHeight;
3196*b1cdbd2cSJim Jagielski }
3197*b1cdbd2cSJim Jagielski 
CalcTextWidth(sal_Bool bIgnoreExtraSpace)3198*b1cdbd2cSJim Jagielski sal_uInt32 ImpEditEngine::CalcTextWidth( sal_Bool bIgnoreExtraSpace )
3199*b1cdbd2cSJim Jagielski {
3200*b1cdbd2cSJim Jagielski 	// Wenn noch nicht formatiert und nicht gerade dabei.
3201*b1cdbd2cSJim Jagielski 	// Wird in der Formatierung bei AutoPageSize gerufen.
3202*b1cdbd2cSJim Jagielski 	if ( !IsFormatted() && !IsFormatting() )
3203*b1cdbd2cSJim Jagielski 		FormatDoc();
3204*b1cdbd2cSJim Jagielski 
3205*b1cdbd2cSJim Jagielski 	EditLine* pLine;
3206*b1cdbd2cSJim Jagielski 
3207*b1cdbd2cSJim Jagielski 	long nMaxWidth = 0;
3208*b1cdbd2cSJim Jagielski 	long nCurWidth = 0;
3209*b1cdbd2cSJim Jagielski 
3210*b1cdbd2cSJim Jagielski 	// --------------------------------------------------
3211*b1cdbd2cSJim Jagielski 	// Ueber alle Absaetze...
3212*b1cdbd2cSJim Jagielski 	// --------------------------------------------------
3213*b1cdbd2cSJim Jagielski 	sal_uInt16 nParas = GetParaPortions().Count();
3214*b1cdbd2cSJim Jagielski //	sal_uInt16 nBiggestPara = 0;
3215*b1cdbd2cSJim Jagielski //	sal_uInt16 nBiggestLine = 0;
3216*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nPara = 0; nPara < nParas; nPara++ )
3217*b1cdbd2cSJim Jagielski 	{
3218*b1cdbd2cSJim Jagielski 		ParaPortion* pPortion = GetParaPortions().GetObject( nPara );
3219*b1cdbd2cSJim Jagielski 		if ( pPortion->IsVisible() )
3220*b1cdbd2cSJim Jagielski 		{
3221*b1cdbd2cSJim Jagielski             const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pPortion->GetNode() );
3222*b1cdbd2cSJim Jagielski             sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pPortion->GetNode() );
3223*b1cdbd2cSJim Jagielski 
3224*b1cdbd2cSJim Jagielski 			// --------------------------------------------------
3225*b1cdbd2cSJim Jagielski 			// Ueber die Zeilen des Absatzes...
3226*b1cdbd2cSJim Jagielski 			// --------------------------------------------------
3227*b1cdbd2cSJim Jagielski 			sal_uLong nLines = pPortion->GetLines().Count();
3228*b1cdbd2cSJim Jagielski 			for ( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
3229*b1cdbd2cSJim Jagielski 			{
3230*b1cdbd2cSJim Jagielski 				pLine = pPortion->GetLines().GetObject( nLine );
3231*b1cdbd2cSJim Jagielski 				DBG_ASSERT( pLine, "NULL-Pointer im Zeileniterator in CalcWidth" );
3232*b1cdbd2cSJim Jagielski 				// nCurWidth = pLine->GetStartPosX();
3233*b1cdbd2cSJim Jagielski 				// Bei Center oder Right haengt die breite von der
3234*b1cdbd2cSJim Jagielski 				// Papierbreite ab, hier nicht erwuenscht.
3235*b1cdbd2cSJim Jagielski 				// Am besten generell nicht auf StartPosX verlassen,
3236*b1cdbd2cSJim Jagielski 				// es muss auch die rechte Einrueckung beruecksichtigt werden!
3237*b1cdbd2cSJim Jagielski                 nCurWidth = GetXValue( rLRItem.GetTxtLeft() + nSpaceBeforeAndMinLabelWidth );
3238*b1cdbd2cSJim Jagielski 				if ( nLine == 0 )
3239*b1cdbd2cSJim Jagielski 				{
3240*b1cdbd2cSJim Jagielski 					long nFI = GetXValue( rLRItem.GetTxtFirstLineOfst() );
3241*b1cdbd2cSJim Jagielski 					nCurWidth -= nFI;
3242*b1cdbd2cSJim Jagielski 					if ( pPortion->GetBulletX() > nCurWidth )
3243*b1cdbd2cSJim Jagielski 					{
3244*b1cdbd2cSJim Jagielski 						nCurWidth += nFI;	// LI?
3245*b1cdbd2cSJim Jagielski 						if ( pPortion->GetBulletX() > nCurWidth )
3246*b1cdbd2cSJim Jagielski 							nCurWidth = pPortion->GetBulletX();
3247*b1cdbd2cSJim Jagielski 					}
3248*b1cdbd2cSJim Jagielski 				}
3249*b1cdbd2cSJim Jagielski 				nCurWidth += GetXValue( rLRItem.GetRight() );
3250*b1cdbd2cSJim Jagielski 				nCurWidth += CalcLineWidth( pPortion, pLine, bIgnoreExtraSpace );
3251*b1cdbd2cSJim Jagielski 				if ( nCurWidth > nMaxWidth )
3252*b1cdbd2cSJim Jagielski 				{
3253*b1cdbd2cSJim Jagielski 					nMaxWidth = nCurWidth;
3254*b1cdbd2cSJim Jagielski 				}
3255*b1cdbd2cSJim Jagielski 			}
3256*b1cdbd2cSJim Jagielski 		}
3257*b1cdbd2cSJim Jagielski 	}
3258*b1cdbd2cSJim Jagielski 	if ( nMaxWidth < 0 )
3259*b1cdbd2cSJim Jagielski 		nMaxWidth = 0;
3260*b1cdbd2cSJim Jagielski 
3261*b1cdbd2cSJim Jagielski 	nMaxWidth++; // Ein breiter, da in CreateLines bei >= umgebrochen wird.
3262*b1cdbd2cSJim Jagielski 	return (sal_uInt32)nMaxWidth;
3263*b1cdbd2cSJim Jagielski }
3264*b1cdbd2cSJim Jagielski 
CalcLineWidth(ParaPortion * pPortion,EditLine * pLine,sal_Bool bIgnoreExtraSpace)3265*b1cdbd2cSJim Jagielski sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, sal_Bool bIgnoreExtraSpace )
3266*b1cdbd2cSJim Jagielski {
3267*b1cdbd2cSJim Jagielski 	sal_uInt16 nPara = GetEditDoc().GetPos( pPortion->GetNode() );
3268*b1cdbd2cSJim Jagielski 
3269*b1cdbd2cSJim Jagielski     // #114278# Saving both layout mode and language (since I'm
3270*b1cdbd2cSJim Jagielski     // potentially changing both)
3271*b1cdbd2cSJim Jagielski     GetRefDevice()->Push( PUSH_TEXTLAYOUTMODE|PUSH_TEXTLANGUAGE );
3272*b1cdbd2cSJim Jagielski 
3273*b1cdbd2cSJim Jagielski     ImplInitLayoutMode( GetRefDevice(), nPara, 0xFFFF );
3274*b1cdbd2cSJim Jagielski 
3275*b1cdbd2cSJim Jagielski     SvxAdjust eJustification = GetJustification( nPara );
3276*b1cdbd2cSJim Jagielski 
3277*b1cdbd2cSJim Jagielski     // Berechnung der Breite ohne die Indents...
3278*b1cdbd2cSJim Jagielski 	sal_uInt32 nWidth = 0;
3279*b1cdbd2cSJim Jagielski     sal_uInt16 nPos = pLine->GetStart();
3280*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ )
3281*b1cdbd2cSJim Jagielski 	{
3282*b1cdbd2cSJim Jagielski 		TextPortion* pTextPortion = pPortion->GetTextPortions().GetObject( nTP );
3283*b1cdbd2cSJim Jagielski 		switch ( pTextPortion->GetKind() )
3284*b1cdbd2cSJim Jagielski 		{
3285*b1cdbd2cSJim Jagielski 			case PORTIONKIND_FIELD:
3286*b1cdbd2cSJim Jagielski 			case PORTIONKIND_HYPHENATOR:
3287*b1cdbd2cSJim Jagielski 			case PORTIONKIND_TAB:
3288*b1cdbd2cSJim Jagielski 			{
3289*b1cdbd2cSJim Jagielski 				nWidth += pTextPortion->GetSize().Width();
3290*b1cdbd2cSJim Jagielski 			}
3291*b1cdbd2cSJim Jagielski 			break;
3292*b1cdbd2cSJim Jagielski 			case PORTIONKIND_TEXT:
3293*b1cdbd2cSJim Jagielski 			{
3294*b1cdbd2cSJim Jagielski                 if ( ( eJustification != SVX_ADJUST_BLOCK ) || ( !bIgnoreExtraSpace ) )
3295*b1cdbd2cSJim Jagielski                 {
3296*b1cdbd2cSJim Jagielski 				    nWidth += pTextPortion->GetSize().Width();
3297*b1cdbd2cSJim Jagielski                 }
3298*b1cdbd2cSJim Jagielski                 else
3299*b1cdbd2cSJim Jagielski                 {
3300*b1cdbd2cSJim Jagielski 	                SvxFont aTmpFont( pPortion->GetNode()->GetCharAttribs().GetDefFont() );
3301*b1cdbd2cSJim Jagielski 				    SeekCursor( pPortion->GetNode(), nPos+1, aTmpFont );
3302*b1cdbd2cSJim Jagielski 				    aTmpFont.SetPhysFont( GetRefDevice() );
3303*b1cdbd2cSJim Jagielski                     ImplInitDigitMode( GetRefDevice(), 0, 0, 0, aTmpFont.GetLanguage() );
3304*b1cdbd2cSJim Jagielski                     nWidth += aTmpFont.QuickGetTextSize( GetRefDevice(), *pPortion->GetNode(), nPos, pTextPortion->GetLen(), NULL ).Width();
3305*b1cdbd2cSJim Jagielski                 }
3306*b1cdbd2cSJim Jagielski 			}
3307*b1cdbd2cSJim Jagielski 			break;
3308*b1cdbd2cSJim Jagielski 		}
3309*b1cdbd2cSJim Jagielski         nPos = nPos + pTextPortion->GetLen();
3310*b1cdbd2cSJim Jagielski 	}
3311*b1cdbd2cSJim Jagielski 
3312*b1cdbd2cSJim Jagielski     GetRefDevice()->Pop();
3313*b1cdbd2cSJim Jagielski 
3314*b1cdbd2cSJim Jagielski     return nWidth;
3315*b1cdbd2cSJim Jagielski }
3316*b1cdbd2cSJim Jagielski 
CalcTextHeight()3317*b1cdbd2cSJim Jagielski sal_uInt32 ImpEditEngine::CalcTextHeight()
3318*b1cdbd2cSJim Jagielski {
3319*b1cdbd2cSJim Jagielski 	DBG_ASSERT( GetUpdateMode(), "Sollte bei Update=sal_False nicht verwendet werden: CalcTextHeight" );
3320*b1cdbd2cSJim Jagielski 	sal_uInt32 nY = 0;
3321*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ )
3322*b1cdbd2cSJim Jagielski 		nY += GetParaPortions()[nPortion]->GetHeight();
3323*b1cdbd2cSJim Jagielski 	return nY;
3324*b1cdbd2cSJim Jagielski }
3325*b1cdbd2cSJim Jagielski 
GetLineCount(sal_uInt16 nParagraph) const3326*b1cdbd2cSJim Jagielski sal_uInt16 ImpEditEngine::GetLineCount( sal_uInt16 nParagraph ) const
3327*b1cdbd2cSJim Jagielski {
3328*b1cdbd2cSJim Jagielski 	DBG_ASSERT( nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
3329*b1cdbd2cSJim Jagielski 	ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
3330*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetLineCount" );
3331*b1cdbd2cSJim Jagielski 	if ( pPPortion )
3332*b1cdbd2cSJim Jagielski 		return pPPortion->GetLines().Count();
3333*b1cdbd2cSJim Jagielski 
3334*b1cdbd2cSJim Jagielski 	return 0xFFFF;
3335*b1cdbd2cSJim Jagielski }
3336*b1cdbd2cSJim Jagielski 
GetLineLen(sal_uInt16 nParagraph,sal_uInt16 nLine) const3337*b1cdbd2cSJim Jagielski xub_StrLen ImpEditEngine::GetLineLen( sal_uInt16 nParagraph, sal_uInt16 nLine ) const
3338*b1cdbd2cSJim Jagielski {
3339*b1cdbd2cSJim Jagielski     DBG_ASSERT( nParagraph < GetParaPortions().Count(), "GetLineLen: Out of range" );
3340*b1cdbd2cSJim Jagielski 	ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
3341*b1cdbd2cSJim Jagielski     DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetLineLen" );
3342*b1cdbd2cSJim Jagielski 	if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
3343*b1cdbd2cSJim Jagielski 	{
3344*b1cdbd2cSJim Jagielski 		EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
3345*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pLine, "Zeile nicht gefunden: GetLineHeight" );
3346*b1cdbd2cSJim Jagielski 		return pLine->GetLen();
3347*b1cdbd2cSJim Jagielski 	}
3348*b1cdbd2cSJim Jagielski 
3349*b1cdbd2cSJim Jagielski 	return 0xFFFF;
3350*b1cdbd2cSJim Jagielski }
3351*b1cdbd2cSJim Jagielski 
GetLineBoundaries(sal_uInt16 & rStart,sal_uInt16 & rEnd,sal_uInt16 nParagraph,sal_uInt16 nLine) const3352*b1cdbd2cSJim Jagielski void ImpEditEngine::GetLineBoundaries( /*out*/sal_uInt16 &rStart, /*out*/sal_uInt16 &rEnd, sal_uInt16 nParagraph, sal_uInt16 nLine ) const
3353*b1cdbd2cSJim Jagielski {
3354*b1cdbd2cSJim Jagielski     DBG_ASSERT( nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
3355*b1cdbd2cSJim Jagielski     ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
3356*b1cdbd2cSJim Jagielski     DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetLineBoundaries" );
3357*b1cdbd2cSJim Jagielski     rStart = rEnd = 0xFFFF;     // default values in case of error
3358*b1cdbd2cSJim Jagielski     if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
3359*b1cdbd2cSJim Jagielski     {
3360*b1cdbd2cSJim Jagielski         EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
3361*b1cdbd2cSJim Jagielski         DBG_ASSERT( pLine, "Zeile nicht gefunden: GetLineBoundaries" );
3362*b1cdbd2cSJim Jagielski         rStart = pLine->GetStart();
3363*b1cdbd2cSJim Jagielski         rEnd   = pLine->GetEnd();
3364*b1cdbd2cSJim Jagielski     }
3365*b1cdbd2cSJim Jagielski }
3366*b1cdbd2cSJim Jagielski 
GetLineNumberAtIndex(sal_uInt16 nPara,sal_uInt16 nIndex) const3367*b1cdbd2cSJim Jagielski sal_uInt16 ImpEditEngine::GetLineNumberAtIndex( sal_uInt16 nPara, sal_uInt16 nIndex ) const
3368*b1cdbd2cSJim Jagielski {
3369*b1cdbd2cSJim Jagielski     sal_uInt16 nLineNo = 0xFFFF;
3370*b1cdbd2cSJim Jagielski     ContentNode* pNode = GetEditDoc().SaveGetObject( nPara );
3371*b1cdbd2cSJim Jagielski     DBG_ASSERT( pNode, "GetLineNumberAtIndex: invalid paragraph index" );
3372*b1cdbd2cSJim Jagielski     if (pNode)
3373*b1cdbd2cSJim Jagielski     {
3374*b1cdbd2cSJim Jagielski         // we explicitly allow for the index to point at the character right behind the text
3375*b1cdbd2cSJim Jagielski         const bool bValidIndex = /*0 <= nIndex &&*/ nIndex <= pNode->Len();
3376*b1cdbd2cSJim Jagielski         DBG_ASSERT( bValidIndex, "GetLineNumberAtIndex: invalid index" );
3377*b1cdbd2cSJim Jagielski         const sal_uInt16 nLineCount = GetLineCount( nPara );
3378*b1cdbd2cSJim Jagielski         if (nIndex == pNode->Len())
3379*b1cdbd2cSJim Jagielski             nLineNo = nLineCount > 0 ? nLineCount - 1 : 0;
3380*b1cdbd2cSJim Jagielski         else if (bValidIndex)   // nIndex < pNode->Len()
3381*b1cdbd2cSJim Jagielski         {
3382*b1cdbd2cSJim Jagielski             sal_uInt16 nStart = USHRT_MAX, nEnd = USHRT_MAX;
3383*b1cdbd2cSJim Jagielski             for (sal_uInt16 i = 0;  i < nLineCount && nLineNo == 0xFFFF;  ++i)
3384*b1cdbd2cSJim Jagielski             {
3385*b1cdbd2cSJim Jagielski                 GetLineBoundaries( nStart, nEnd, nPara, i );
3386*b1cdbd2cSJim Jagielski                 if (nStart <= nIndex && nIndex < nEnd)
3387*b1cdbd2cSJim Jagielski                     nLineNo = i;
3388*b1cdbd2cSJim Jagielski             }
3389*b1cdbd2cSJim Jagielski         }
3390*b1cdbd2cSJim Jagielski     }
3391*b1cdbd2cSJim Jagielski     return nLineNo;
3392*b1cdbd2cSJim Jagielski }
3393*b1cdbd2cSJim Jagielski 
GetLineHeight(sal_uInt16 nParagraph,sal_uInt16 nLine)3394*b1cdbd2cSJim Jagielski sal_uInt16 ImpEditEngine::GetLineHeight( sal_uInt16 nParagraph, sal_uInt16 nLine )
3395*b1cdbd2cSJim Jagielski {
3396*b1cdbd2cSJim Jagielski 	DBG_ASSERT( nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" );
3397*b1cdbd2cSJim Jagielski 	ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
3398*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetLineHeight" );
3399*b1cdbd2cSJim Jagielski 	if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) )
3400*b1cdbd2cSJim Jagielski 	{
3401*b1cdbd2cSJim Jagielski 		EditLine* pLine = pPPortion->GetLines().GetObject( nLine );
3402*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pLine, "Zeile nicht gefunden: GetLineHeight" );
3403*b1cdbd2cSJim Jagielski 		return pLine->GetHeight();
3404*b1cdbd2cSJim Jagielski 	}
3405*b1cdbd2cSJim Jagielski 
3406*b1cdbd2cSJim Jagielski 	return 0xFFFF;
3407*b1cdbd2cSJim Jagielski }
3408*b1cdbd2cSJim Jagielski 
GetParaHeight(sal_uInt16 nParagraph)3409*b1cdbd2cSJim Jagielski sal_uInt32 ImpEditEngine::GetParaHeight( sal_uInt16 nParagraph )
3410*b1cdbd2cSJim Jagielski {
3411*b1cdbd2cSJim Jagielski 	sal_uInt32 nHeight = 0;
3412*b1cdbd2cSJim Jagielski 
3413*b1cdbd2cSJim Jagielski 	ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nParagraph );
3414*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPPortion, "Absatz nicht gefunden: GetParaHeight" );
3415*b1cdbd2cSJim Jagielski 
3416*b1cdbd2cSJim Jagielski 	if ( pPPortion )
3417*b1cdbd2cSJim Jagielski 		nHeight = pPPortion->GetHeight();
3418*b1cdbd2cSJim Jagielski 
3419*b1cdbd2cSJim Jagielski 	return nHeight;
3420*b1cdbd2cSJim Jagielski }
3421*b1cdbd2cSJim Jagielski 
UpdateSelections()3422*b1cdbd2cSJim Jagielski void ImpEditEngine::UpdateSelections()
3423*b1cdbd2cSJim Jagielski {
3424*b1cdbd2cSJim Jagielski 	sal_uInt16 nInvNodes = aDeletedNodes.Count();
3425*b1cdbd2cSJim Jagielski 
3426*b1cdbd2cSJim Jagielski 	// Pruefen, ob eine der Selektionen auf einem geloeschten Node steht...
3427*b1cdbd2cSJim Jagielski 	// Wenn der Node gueltig ist, muss noch der Index geprueft werden!
3428*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nView = 0; nView < aEditViews.Count(); nView++ )
3429*b1cdbd2cSJim Jagielski 	{
3430*b1cdbd2cSJim Jagielski 		EditView* pView = aEditViews.GetObject(nView);
3431*b1cdbd2cSJim Jagielski 		DBG_CHKOBJ( pView, EditView, 0 );
3432*b1cdbd2cSJim Jagielski 		EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
3433*b1cdbd2cSJim Jagielski 		sal_Bool bChanged = sal_False;
3434*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 n = 0; n < nInvNodes; n++ )
3435*b1cdbd2cSJim Jagielski 		{
3436*b1cdbd2cSJim Jagielski 			DeletedNodeInfo* pInf = aDeletedNodes.GetObject( n );
3437*b1cdbd2cSJim Jagielski 			if ( ( ( sal_uLong )(aCurSel.Min().GetNode()) == pInf->GetInvalidAdress() ) ||
3438*b1cdbd2cSJim Jagielski 				 ( ( sal_uLong )(aCurSel.Max().GetNode()) == pInf->GetInvalidAdress() ) )
3439*b1cdbd2cSJim Jagielski 			{
3440*b1cdbd2cSJim Jagielski 				// ParaPortions verwenden, da jetzt auch versteckte
3441*b1cdbd2cSJim Jagielski 				// Absaetze beruecksichtigt werden muessen!
3442*b1cdbd2cSJim Jagielski 				sal_uInt16 nPara = pInf->GetPosition();
3443*b1cdbd2cSJim Jagielski 				ParaPortion* pPPortion = GetParaPortions().SaveGetObject( nPara );
3444*b1cdbd2cSJim Jagielski 				if ( !pPPortion ) // letzter Absatz
3445*b1cdbd2cSJim Jagielski 				{
3446*b1cdbd2cSJim Jagielski 					nPara = GetParaPortions().Count()-1;
3447*b1cdbd2cSJim Jagielski 					pPPortion = GetParaPortions().GetObject( nPara );
3448*b1cdbd2cSJim Jagielski 				}
3449*b1cdbd2cSJim Jagielski 				DBG_ASSERT( pPPortion, "Leeres Document in UpdateSelections ?" );
3450*b1cdbd2cSJim Jagielski 				// Nicht aus einem verstecktem Absatz landen:
3451*b1cdbd2cSJim Jagielski 				sal_uInt16 nCurPara = nPara;
3452*b1cdbd2cSJim Jagielski 				sal_uInt16 nLastPara = GetParaPortions().Count()-1;
3453*b1cdbd2cSJim Jagielski 				while ( nPara <= nLastPara && !GetParaPortions()[nPara]->IsVisible() )
3454*b1cdbd2cSJim Jagielski 					nPara++;
3455*b1cdbd2cSJim Jagielski 				if ( nPara > nLastPara ) // dann eben rueckwaerts...
3456*b1cdbd2cSJim Jagielski 				{
3457*b1cdbd2cSJim Jagielski 					nPara = nCurPara;
3458*b1cdbd2cSJim Jagielski 					while ( nPara && !GetParaPortions()[nPara]->IsVisible() )
3459*b1cdbd2cSJim Jagielski 						nPara--;
3460*b1cdbd2cSJim Jagielski 				}
3461*b1cdbd2cSJim Jagielski 				DBG_ASSERT( GetParaPortions()[nPara]->IsVisible(), "Keinen sichtbaren Absatz gefunden: UpdateSelections" );
3462*b1cdbd2cSJim Jagielski 
3463*b1cdbd2cSJim Jagielski 				ParaPortion* pParaPortion = GetParaPortions()[nPara];
3464*b1cdbd2cSJim Jagielski 				EditSelection aTmpSelection( EditPaM( pParaPortion->GetNode(), 0 ) );
3465*b1cdbd2cSJim Jagielski 				pView->pImpEditView->SetEditSelection( aTmpSelection );
3466*b1cdbd2cSJim Jagielski 				bChanged=sal_True;
3467*b1cdbd2cSJim Jagielski 				break;	// for-Schleife
3468*b1cdbd2cSJim Jagielski 			}
3469*b1cdbd2cSJim Jagielski 		}
3470*b1cdbd2cSJim Jagielski 		if ( !bChanged )
3471*b1cdbd2cSJim Jagielski 		{
3472*b1cdbd2cSJim Jagielski 			// Index prueffen, falls Node geschrumpft.
3473*b1cdbd2cSJim Jagielski 			if ( aCurSel.Min().GetIndex() > aCurSel.Min().GetNode()->Len() )
3474*b1cdbd2cSJim Jagielski 			{
3475*b1cdbd2cSJim Jagielski 				aCurSel.Min().GetIndex() = aCurSel.Min().GetNode()->Len();
3476*b1cdbd2cSJim Jagielski 				pView->pImpEditView->SetEditSelection( aCurSel );
3477*b1cdbd2cSJim Jagielski 			}
3478*b1cdbd2cSJim Jagielski 			if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
3479*b1cdbd2cSJim Jagielski 			{
3480*b1cdbd2cSJim Jagielski 				aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
3481*b1cdbd2cSJim Jagielski 				pView->pImpEditView->SetEditSelection( aCurSel );
3482*b1cdbd2cSJim Jagielski 			}
3483*b1cdbd2cSJim Jagielski 		}
3484*b1cdbd2cSJim Jagielski 	}
3485*b1cdbd2cSJim Jagielski 
3486*b1cdbd2cSJim Jagielski 	// Loeschen...
3487*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 n = 0; n < nInvNodes; n++ )
3488*b1cdbd2cSJim Jagielski 	{
3489*b1cdbd2cSJim Jagielski 		DeletedNodeInfo* pInf = aDeletedNodes.GetObject( n );
3490*b1cdbd2cSJim Jagielski 		delete pInf;
3491*b1cdbd2cSJim Jagielski 	}
3492*b1cdbd2cSJim Jagielski 	aDeletedNodes.Remove( 0, aDeletedNodes.Count() );
3493*b1cdbd2cSJim Jagielski }
3494*b1cdbd2cSJim Jagielski 
ConvertSelection(sal_uInt16 nStartPara,sal_uInt16 nStartPos,sal_uInt16 nEndPara,sal_uInt16 nEndPos) const3495*b1cdbd2cSJim Jagielski EditSelection ImpEditEngine::ConvertSelection( sal_uInt16 nStartPara, sal_uInt16 nStartPos,
3496*b1cdbd2cSJim Jagielski 							 sal_uInt16 nEndPara, sal_uInt16 nEndPos ) const
3497*b1cdbd2cSJim Jagielski {
3498*b1cdbd2cSJim Jagielski 	EditSelection aNewSelection;
3499*b1cdbd2cSJim Jagielski 
3500*b1cdbd2cSJim Jagielski 	// Start...
3501*b1cdbd2cSJim Jagielski 	ContentNode* pNode = aEditDoc.SaveGetObject( nStartPara );
3502*b1cdbd2cSJim Jagielski 	sal_uInt16 nIndex = nStartPos;
3503*b1cdbd2cSJim Jagielski 	if ( !pNode )
3504*b1cdbd2cSJim Jagielski 	{
3505*b1cdbd2cSJim Jagielski 		pNode = aEditDoc[ aEditDoc.Count()-1 ];
3506*b1cdbd2cSJim Jagielski 		nIndex = pNode->Len();
3507*b1cdbd2cSJim Jagielski 	}
3508*b1cdbd2cSJim Jagielski 	else if ( nIndex > pNode->Len() )
3509*b1cdbd2cSJim Jagielski 		nIndex = pNode->Len();
3510*b1cdbd2cSJim Jagielski 
3511*b1cdbd2cSJim Jagielski 	aNewSelection.Min().SetNode( pNode );
3512*b1cdbd2cSJim Jagielski 	aNewSelection.Min().SetIndex( nIndex );
3513*b1cdbd2cSJim Jagielski 
3514*b1cdbd2cSJim Jagielski 	// End...
3515*b1cdbd2cSJim Jagielski 	pNode = aEditDoc.SaveGetObject( nEndPara );
3516*b1cdbd2cSJim Jagielski 	nIndex = nEndPos;
3517*b1cdbd2cSJim Jagielski 	if ( !pNode )
3518*b1cdbd2cSJim Jagielski 	{
3519*b1cdbd2cSJim Jagielski 		pNode = aEditDoc[ aEditDoc.Count()-1 ];
3520*b1cdbd2cSJim Jagielski 		nIndex = pNode->Len();
3521*b1cdbd2cSJim Jagielski 	}
3522*b1cdbd2cSJim Jagielski 	else if ( nIndex > pNode->Len() )
3523*b1cdbd2cSJim Jagielski 		nIndex = pNode->Len();
3524*b1cdbd2cSJim Jagielski 
3525*b1cdbd2cSJim Jagielski 	aNewSelection.Max().SetNode( pNode );
3526*b1cdbd2cSJim Jagielski 	aNewSelection.Max().SetIndex( nIndex );
3527*b1cdbd2cSJim Jagielski 
3528*b1cdbd2cSJim Jagielski 	return aNewSelection;
3529*b1cdbd2cSJim Jagielski }
3530*b1cdbd2cSJim Jagielski 
MatchGroup(const EditSelection & rSel)3531*b1cdbd2cSJim Jagielski EditSelection ImpEditEngine::MatchGroup( const EditSelection& rSel )
3532*b1cdbd2cSJim Jagielski {
3533*b1cdbd2cSJim Jagielski 	EditSelection aMatchSel;
3534*b1cdbd2cSJim Jagielski 	EditSelection aTmpSel( rSel );
3535*b1cdbd2cSJim Jagielski 	aTmpSel.Adjust( GetEditDoc() );
3536*b1cdbd2cSJim Jagielski 	if ( (	aTmpSel.Min().GetNode() != aTmpSel.Max().GetNode() ) ||
3537*b1cdbd2cSJim Jagielski 		 ( ( aTmpSel.Max().GetIndex() - aTmpSel.Min().GetIndex() ) > 1 ) )
3538*b1cdbd2cSJim Jagielski 	{
3539*b1cdbd2cSJim Jagielski 		return aMatchSel;
3540*b1cdbd2cSJim Jagielski 	}
3541*b1cdbd2cSJim Jagielski 
3542*b1cdbd2cSJim Jagielski 	sal_uInt16 nPos = aTmpSel.Min().GetIndex();
3543*b1cdbd2cSJim Jagielski 	ContentNode* pNode = aTmpSel.Min().GetNode();
3544*b1cdbd2cSJim Jagielski 	if ( nPos >= pNode->Len() )
3545*b1cdbd2cSJim Jagielski 		return aMatchSel;
3546*b1cdbd2cSJim Jagielski 
3547*b1cdbd2cSJim Jagielski 	sal_uInt16 nMatchChar = aGroupChars.Search( pNode->GetChar( nPos ) );
3548*b1cdbd2cSJim Jagielski 	if ( nMatchChar != STRING_NOTFOUND )
3549*b1cdbd2cSJim Jagielski 	{
3550*b1cdbd2cSJim Jagielski 		sal_uInt16 nNode = aEditDoc.GetPos( pNode );
3551*b1cdbd2cSJim Jagielski 		if ( ( nMatchChar % 2 ) == 0 )
3552*b1cdbd2cSJim Jagielski 		{
3553*b1cdbd2cSJim Jagielski 			// Vorwaerts suchen...
3554*b1cdbd2cSJim Jagielski 			xub_Unicode nSC = aGroupChars.GetChar( nMatchChar );
3555*b1cdbd2cSJim Jagielski 			DBG_ASSERT( aGroupChars.Len() > (nMatchChar+1), "Ungueltige Gruppe von MatchChars!" );
3556*b1cdbd2cSJim Jagielski 			xub_Unicode nEC = aGroupChars.GetChar( nMatchChar+1 );
3557*b1cdbd2cSJim Jagielski 
3558*b1cdbd2cSJim Jagielski 			sal_uInt16 nCur = aTmpSel.Min().GetIndex()+1;
3559*b1cdbd2cSJim Jagielski 			sal_uInt16 nLevel = 1;
3560*b1cdbd2cSJim Jagielski 			while ( pNode && nLevel )
3561*b1cdbd2cSJim Jagielski 			{
3562*b1cdbd2cSJim Jagielski 				XubString& rStr = *pNode;
3563*b1cdbd2cSJim Jagielski 				while ( nCur < rStr.Len() )
3564*b1cdbd2cSJim Jagielski 				{
3565*b1cdbd2cSJim Jagielski 					if ( rStr.GetChar( nCur ) == nSC )
3566*b1cdbd2cSJim Jagielski 						nLevel++;
3567*b1cdbd2cSJim Jagielski 					else if ( rStr.GetChar( nCur ) == nEC )
3568*b1cdbd2cSJim Jagielski 					{
3569*b1cdbd2cSJim Jagielski 						nLevel--;
3570*b1cdbd2cSJim Jagielski 						if ( !nLevel )
3571*b1cdbd2cSJim Jagielski 							break;	// while nCur...
3572*b1cdbd2cSJim Jagielski 					}
3573*b1cdbd2cSJim Jagielski 					nCur++;
3574*b1cdbd2cSJim Jagielski 				}
3575*b1cdbd2cSJim Jagielski 
3576*b1cdbd2cSJim Jagielski 				if ( nLevel )
3577*b1cdbd2cSJim Jagielski 				{
3578*b1cdbd2cSJim Jagielski 					nNode++;
3579*b1cdbd2cSJim Jagielski 					pNode = nNode < aEditDoc.Count() ? aEditDoc.GetObject( nNode ) : 0;
3580*b1cdbd2cSJim Jagielski 					nCur = 0;
3581*b1cdbd2cSJim Jagielski 				}
3582*b1cdbd2cSJim Jagielski 			}
3583*b1cdbd2cSJim Jagielski 			if ( nLevel == 0 )	// gefunden
3584*b1cdbd2cSJim Jagielski 			{
3585*b1cdbd2cSJim Jagielski 				aMatchSel.Min() = aTmpSel.Min();
3586*b1cdbd2cSJim Jagielski 				aMatchSel.Max() = EditPaM( pNode, nCur+1 );
3587*b1cdbd2cSJim Jagielski 			}
3588*b1cdbd2cSJim Jagielski 		}
3589*b1cdbd2cSJim Jagielski 		else
3590*b1cdbd2cSJim Jagielski 		{
3591*b1cdbd2cSJim Jagielski 			// Rueckwaerts suchen...
3592*b1cdbd2cSJim Jagielski 			xub_Unicode nEC = aGroupChars.GetChar( nMatchChar );
3593*b1cdbd2cSJim Jagielski 			xub_Unicode nSC = aGroupChars.GetChar( nMatchChar-1 );
3594*b1cdbd2cSJim Jagielski 
3595*b1cdbd2cSJim Jagielski 			sal_uInt16 nCur = aTmpSel.Min().GetIndex()-1;
3596*b1cdbd2cSJim Jagielski 			sal_uInt16 nLevel = 1;
3597*b1cdbd2cSJim Jagielski 			while ( pNode && nLevel )
3598*b1cdbd2cSJim Jagielski 			{
3599*b1cdbd2cSJim Jagielski 				if ( pNode->Len() )
3600*b1cdbd2cSJim Jagielski 				{
3601*b1cdbd2cSJim Jagielski 					XubString& rStr = *pNode;
3602*b1cdbd2cSJim Jagielski 					while ( nCur )
3603*b1cdbd2cSJim Jagielski 					{
3604*b1cdbd2cSJim Jagielski 						if ( rStr.GetChar( nCur ) == nSC )
3605*b1cdbd2cSJim Jagielski 						{
3606*b1cdbd2cSJim Jagielski 							nLevel--;
3607*b1cdbd2cSJim Jagielski 							if ( !nLevel )
3608*b1cdbd2cSJim Jagielski 								break;	// while nCur...
3609*b1cdbd2cSJim Jagielski 						}
3610*b1cdbd2cSJim Jagielski 						else if ( rStr.GetChar( nCur ) == nEC )
3611*b1cdbd2cSJim Jagielski 							nLevel++;
3612*b1cdbd2cSJim Jagielski 
3613*b1cdbd2cSJim Jagielski 						nCur--;
3614*b1cdbd2cSJim Jagielski 					}
3615*b1cdbd2cSJim Jagielski 				}
3616*b1cdbd2cSJim Jagielski 
3617*b1cdbd2cSJim Jagielski 				if ( nLevel )
3618*b1cdbd2cSJim Jagielski 				{
3619*b1cdbd2cSJim Jagielski 					pNode = nNode ? aEditDoc.GetObject( --nNode ) : 0;
3620*b1cdbd2cSJim Jagielski 					if ( pNode )
3621*b1cdbd2cSJim Jagielski 						nCur = pNode->Len()-1;	// egal ob negativ, weil if Len()
3622*b1cdbd2cSJim Jagielski 				}
3623*b1cdbd2cSJim Jagielski 			}
3624*b1cdbd2cSJim Jagielski 
3625*b1cdbd2cSJim Jagielski 			if ( nLevel == 0 )	// gefunden
3626*b1cdbd2cSJim Jagielski 			{
3627*b1cdbd2cSJim Jagielski 				aMatchSel.Min() = aTmpSel.Min();
3628*b1cdbd2cSJim Jagielski 				aMatchSel.Min().GetIndex()++;	// hinter das Zeichen
3629*b1cdbd2cSJim Jagielski 				aMatchSel.Max() = EditPaM( pNode, nCur );
3630*b1cdbd2cSJim Jagielski 			}
3631*b1cdbd2cSJim Jagielski 		}
3632*b1cdbd2cSJim Jagielski 	}
3633*b1cdbd2cSJim Jagielski 	return aMatchSel;
3634*b1cdbd2cSJim Jagielski }
3635*b1cdbd2cSJim Jagielski 
StopSelectionMode()3636*b1cdbd2cSJim Jagielski void ImpEditEngine::StopSelectionMode()
3637*b1cdbd2cSJim Jagielski {
3638*b1cdbd2cSJim Jagielski 	if ( ( IsInSelectionMode() || aSelEngine.IsInSelection() ) && pActiveView )
3639*b1cdbd2cSJim Jagielski 	{
3640*b1cdbd2cSJim Jagielski 		pActiveView->pImpEditView->DrawSelection();	// Wegzeichnen...
3641*b1cdbd2cSJim Jagielski 		EditSelection aSel( pActiveView->pImpEditView->GetEditSelection() );
3642*b1cdbd2cSJim Jagielski 		aSel.Min() = aSel.Max();
3643*b1cdbd2cSJim Jagielski 		pActiveView->pImpEditView->SetEditSelection( aSel );
3644*b1cdbd2cSJim Jagielski 		pActiveView->ShowCursor();
3645*b1cdbd2cSJim Jagielski 		aSelEngine.Reset();
3646*b1cdbd2cSJim Jagielski 		bInSelection = sal_False;
3647*b1cdbd2cSJim Jagielski 	}
3648*b1cdbd2cSJim Jagielski }
3649*b1cdbd2cSJim Jagielski 
SetActiveView(EditView * pView)3650*b1cdbd2cSJim Jagielski void ImpEditEngine::SetActiveView( EditView* pView )
3651*b1cdbd2cSJim Jagielski {
3652*b1cdbd2cSJim Jagielski 	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3653*b1cdbd2cSJim Jagielski 	// Eigentlich waere jetzt ein bHasVisSel und HideSelection notwendig !!!
3654*b1cdbd2cSJim Jagielski 
3655*b1cdbd2cSJim Jagielski 	if ( pView == pActiveView )
3656*b1cdbd2cSJim Jagielski 		return;
3657*b1cdbd2cSJim Jagielski 
3658*b1cdbd2cSJim Jagielski 	if ( pActiveView && pActiveView->HasSelection() )
3659*b1cdbd2cSJim Jagielski 		pActiveView->pImpEditView->DrawSelection();	// Wegzeichnen...
3660*b1cdbd2cSJim Jagielski 
3661*b1cdbd2cSJim Jagielski 	pActiveView = pView;
3662*b1cdbd2cSJim Jagielski 
3663*b1cdbd2cSJim Jagielski 	if ( pActiveView && pActiveView->HasSelection() )
3664*b1cdbd2cSJim Jagielski 		pActiveView->pImpEditView->DrawSelection();	// Wegzeichnen...
3665*b1cdbd2cSJim Jagielski 
3666*b1cdbd2cSJim Jagielski 	//	NN: Quick fix for #78668#:
3667*b1cdbd2cSJim Jagielski 	//	When editing of a cell in Calc is ended, the edit engine is not deleted,
3668*b1cdbd2cSJim Jagielski 	//	only the edit views are removed. If mpIMEInfos is still set in that case,
3669*b1cdbd2cSJim Jagielski 	//	mpIMEInfos->aPos points to an invalid selection.
3670*b1cdbd2cSJim Jagielski 	//	-> reset mpIMEInfos now
3671*b1cdbd2cSJim Jagielski 	//	(probably something like this is necessary whenever the content is modified
3672*b1cdbd2cSJim Jagielski 	//	from the outside)
3673*b1cdbd2cSJim Jagielski 
3674*b1cdbd2cSJim Jagielski 	if ( !pView && mpIMEInfos )
3675*b1cdbd2cSJim Jagielski 	{
3676*b1cdbd2cSJim Jagielski 		delete mpIMEInfos;
3677*b1cdbd2cSJim Jagielski 		mpIMEInfos = NULL;
3678*b1cdbd2cSJim Jagielski 	}
3679*b1cdbd2cSJim Jagielski }
3680*b1cdbd2cSJim Jagielski 
CreateTransferable(const EditSelection & rSelection) const3681*b1cdbd2cSJim Jagielski uno::Reference< datatransfer::XTransferable > ImpEditEngine::CreateTransferable( const EditSelection& rSelection ) const
3682*b1cdbd2cSJim Jagielski {
3683*b1cdbd2cSJim Jagielski #ifndef SVX_LIGHT
3684*b1cdbd2cSJim Jagielski     EditSelection aSelection( rSelection );
3685*b1cdbd2cSJim Jagielski 	aSelection.Adjust( GetEditDoc() );
3686*b1cdbd2cSJim Jagielski 
3687*b1cdbd2cSJim Jagielski 	EditDataObject* pDataObj = new EditDataObject;
3688*b1cdbd2cSJim Jagielski 	uno::Reference< datatransfer::XTransferable > xDataObj;
3689*b1cdbd2cSJim Jagielski 	xDataObj = pDataObj;
3690*b1cdbd2cSJim Jagielski 
3691*b1cdbd2cSJim Jagielski 	XubString aText( GetSelected( aSelection ) );
3692*b1cdbd2cSJim Jagielski 	aText.ConvertLineEnd();	// Systemspezifisch
3693*b1cdbd2cSJim Jagielski 	pDataObj->GetString() = aText;
3694*b1cdbd2cSJim Jagielski 
3695*b1cdbd2cSJim Jagielski     SvxFontItem::EnableStoreUnicodeNames( sal_True );
3696*b1cdbd2cSJim Jagielski 	WriteBin( pDataObj->GetStream(), aSelection, sal_True );
3697*b1cdbd2cSJim Jagielski 	pDataObj->GetStream().Seek( 0 );
3698*b1cdbd2cSJim Jagielski     SvxFontItem::EnableStoreUnicodeNames( sal_False );
3699*b1cdbd2cSJim Jagielski 
3700*b1cdbd2cSJim Jagielski     ((ImpEditEngine*)this)->WriteRTF( pDataObj->GetRTFStream(), aSelection );
3701*b1cdbd2cSJim Jagielski 	pDataObj->GetRTFStream().Seek( 0 );
3702*b1cdbd2cSJim Jagielski 
3703*b1cdbd2cSJim Jagielski 	if ( ( aSelection.Min().GetNode() == aSelection.Max().GetNode() )
3704*b1cdbd2cSJim Jagielski 			&& ( aSelection.Max().GetIndex() == (aSelection.Min().GetIndex()+1) ) )
3705*b1cdbd2cSJim Jagielski 	{
3706*b1cdbd2cSJim Jagielski 		const EditCharAttrib* pAttr = aSelection.Min().GetNode()->GetCharAttribs().
3707*b1cdbd2cSJim Jagielski 			FindFeature( aSelection.Min().GetIndex() );
3708*b1cdbd2cSJim Jagielski 		if ( pAttr &&
3709*b1cdbd2cSJim Jagielski 			( pAttr->GetStart() == aSelection.Min().GetIndex() ) &&
3710*b1cdbd2cSJim Jagielski 			( pAttr->Which() == EE_FEATURE_FIELD ) )
3711*b1cdbd2cSJim Jagielski 		{
3712*b1cdbd2cSJim Jagielski 			const SvxFieldItem*	pField = (const SvxFieldItem*)pAttr->GetItem();
3713*b1cdbd2cSJim Jagielski 			const SvxFieldData* pFld = pField->GetField();
3714*b1cdbd2cSJim Jagielski 			if ( pFld && pFld->ISA( SvxURLField ) )
3715*b1cdbd2cSJim Jagielski 			{
3716*b1cdbd2cSJim Jagielski 				// Office-Bookmark
3717*b1cdbd2cSJim Jagielski 				String aURL( ((const SvxURLField*)pFld)->GetURL() );
3718*b1cdbd2cSJim Jagielski 				String aTxt( ((const SvxURLField*)pFld)->GetRepresentation() );
3719*b1cdbd2cSJim Jagielski 				pDataObj->GetURL() = aURL;
3720*b1cdbd2cSJim Jagielski 			}
3721*b1cdbd2cSJim Jagielski 		}
3722*b1cdbd2cSJim Jagielski 	}
3723*b1cdbd2cSJim Jagielski 
3724*b1cdbd2cSJim Jagielski     return xDataObj;
3725*b1cdbd2cSJim Jagielski #else
3726*b1cdbd2cSJim Jagielski 	return uno::Reference< datatransfer::XTransferable >();
3727*b1cdbd2cSJim Jagielski #endif
3728*b1cdbd2cSJim Jagielski }
3729*b1cdbd2cSJim Jagielski 
InsertText(uno::Reference<datatransfer::XTransferable> & rxDataObj,const String & rBaseURL,const EditPaM & rPaM,sal_Bool bUseSpecial)3730*b1cdbd2cSJim Jagielski EditSelection ImpEditEngine::InsertText( uno::Reference< datatransfer::XTransferable >& rxDataObj, const String& rBaseURL, const EditPaM& rPaM, sal_Bool bUseSpecial )
3731*b1cdbd2cSJim Jagielski {
3732*b1cdbd2cSJim Jagielski 	EditSelection aNewSelection( rPaM );
3733*b1cdbd2cSJim Jagielski 
3734*b1cdbd2cSJim Jagielski 	if ( rxDataObj.is() )
3735*b1cdbd2cSJim Jagielski 	{
3736*b1cdbd2cSJim Jagielski 		datatransfer::DataFlavor aFlavor;
3737*b1cdbd2cSJim Jagielski 		sal_Bool bDone = sal_False;
3738*b1cdbd2cSJim Jagielski 
3739*b1cdbd2cSJim Jagielski 		if ( bUseSpecial )
3740*b1cdbd2cSJim Jagielski 		{
3741*b1cdbd2cSJim Jagielski 			// BIN
3742*b1cdbd2cSJim Jagielski 			SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_EDITENGINE, aFlavor );
3743*b1cdbd2cSJim Jagielski 			if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
3744*b1cdbd2cSJim Jagielski 			{
3745*b1cdbd2cSJim Jagielski 				try
3746*b1cdbd2cSJim Jagielski 				{
3747*b1cdbd2cSJim Jagielski 					uno::Any aData = rxDataObj->getTransferData( aFlavor );
3748*b1cdbd2cSJim Jagielski 					uno::Sequence< sal_Int8 > aSeq;
3749*b1cdbd2cSJim Jagielski 					aData >>= aSeq;
3750*b1cdbd2cSJim Jagielski 					{
3751*b1cdbd2cSJim Jagielski 						SvMemoryStream aBinStream( aSeq.getArray(), aSeq.getLength(), STREAM_READ );
3752*b1cdbd2cSJim Jagielski 						aNewSelection = Read( aBinStream, rBaseURL, EE_FORMAT_BIN, rPaM );
3753*b1cdbd2cSJim Jagielski 					}
3754*b1cdbd2cSJim Jagielski 					bDone = sal_True;
3755*b1cdbd2cSJim Jagielski 				}
3756*b1cdbd2cSJim Jagielski 				catch( const ::com::sun::star::uno::Exception& )
3757*b1cdbd2cSJim Jagielski 				{
3758*b1cdbd2cSJim Jagielski 				}
3759*b1cdbd2cSJim Jagielski 			}
3760*b1cdbd2cSJim Jagielski 
3761*b1cdbd2cSJim Jagielski 			if ( !bDone )
3762*b1cdbd2cSJim Jagielski 			{
3763*b1cdbd2cSJim Jagielski 				// Bookmark
3764*b1cdbd2cSJim Jagielski 				/*
3765*b1cdbd2cSJim Jagielski 				String aURL = ...;
3766*b1cdbd2cSJim Jagielski 				String aTxt = ...;
3767*b1cdbd2cSJim Jagielski 				// Feld nur einfuegen, wenn Factory vorhanden.
3768*b1cdbd2cSJim Jagielski 				if ( ITEMDATA() && ITEMDATA()->GetClassManager().Get( SVX_URLFIELD ) )
3769*b1cdbd2cSJim Jagielski 				{
3770*b1cdbd2cSJim Jagielski 					SvxFieldItem aField( SvxURLField( aURL, aTxt, SVXURLFORMAT_URL ), EE_FEATURE_FIELD  );
3771*b1cdbd2cSJim Jagielski 					aNewSelection = InsertField( aPaM, aField );
3772*b1cdbd2cSJim Jagielski 					UpdateFields();
3773*b1cdbd2cSJim Jagielski 				}
3774*b1cdbd2cSJim Jagielski 				else
3775*b1cdbd2cSJim Jagielski 					aNewSelection = ImpInsertText( aPaM, aURL );
3776*b1cdbd2cSJim Jagielski 				}
3777*b1cdbd2cSJim Jagielski 				*/
3778*b1cdbd2cSJim Jagielski 			}
3779*b1cdbd2cSJim Jagielski 			if ( !bDone )
3780*b1cdbd2cSJim Jagielski 			{
3781*b1cdbd2cSJim Jagielski 				// RTF
3782*b1cdbd2cSJim Jagielski 				SotExchange::GetFormatDataFlavor( SOT_FORMAT_RTF, aFlavor );
3783*b1cdbd2cSJim Jagielski 				if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
3784*b1cdbd2cSJim Jagielski 				{
3785*b1cdbd2cSJim Jagielski 					try
3786*b1cdbd2cSJim Jagielski 					{
3787*b1cdbd2cSJim Jagielski 						uno::Any aData = rxDataObj->getTransferData( aFlavor );
3788*b1cdbd2cSJim Jagielski 						uno::Sequence< sal_Int8 > aSeq;
3789*b1cdbd2cSJim Jagielski 						aData >>= aSeq;
3790*b1cdbd2cSJim Jagielski 						{
3791*b1cdbd2cSJim Jagielski 							SvMemoryStream aRTFStream( aSeq.getArray(), aSeq.getLength(), STREAM_READ );
3792*b1cdbd2cSJim Jagielski 							aNewSelection = Read( aRTFStream, rBaseURL, EE_FORMAT_RTF, rPaM );
3793*b1cdbd2cSJim Jagielski 						}
3794*b1cdbd2cSJim Jagielski 						bDone = sal_True;
3795*b1cdbd2cSJim Jagielski 					}
3796*b1cdbd2cSJim Jagielski 					catch( const ::com::sun::star::uno::Exception& )
3797*b1cdbd2cSJim Jagielski 					{
3798*b1cdbd2cSJim Jagielski 					}
3799*b1cdbd2cSJim Jagielski 				}
3800*b1cdbd2cSJim Jagielski 			}
3801*b1cdbd2cSJim Jagielski 			if ( !bDone )
3802*b1cdbd2cSJim Jagielski 			{
3803*b1cdbd2cSJim Jagielski 				// XML ?
3804*b1cdbd2cSJim Jagielski                 // Currently, there is nothing like "The" XML format, StarOffice doesn't offer plain XML in Clipboard...
3805*b1cdbd2cSJim Jagielski 			}
3806*b1cdbd2cSJim Jagielski 		}
3807*b1cdbd2cSJim Jagielski 		if ( !bDone )
3808*b1cdbd2cSJim Jagielski 		{
3809*b1cdbd2cSJim Jagielski 			SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
3810*b1cdbd2cSJim Jagielski 			if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
3811*b1cdbd2cSJim Jagielski 			{
3812*b1cdbd2cSJim Jagielski 			    try
3813*b1cdbd2cSJim Jagielski         	    {
3814*b1cdbd2cSJim Jagielski     				uno::Any aData = rxDataObj->getTransferData( aFlavor );
3815*b1cdbd2cSJim Jagielski     				::rtl::OUString aText;
3816*b1cdbd2cSJim Jagielski     				aData >>= aText;
3817*b1cdbd2cSJim Jagielski     				aNewSelection = ImpInsertText( rPaM, aText );
3818*b1cdbd2cSJim Jagielski    					bDone = sal_True;
3819*b1cdbd2cSJim Jagielski 				}
3820*b1cdbd2cSJim Jagielski 				catch( ... )
3821*b1cdbd2cSJim Jagielski 				{
3822*b1cdbd2cSJim Jagielski                     ; // #i9286# can happen, even if isDataFlavorSupported returns true...
3823*b1cdbd2cSJim Jagielski 				}
3824*b1cdbd2cSJim Jagielski 			}
3825*b1cdbd2cSJim Jagielski 		}
3826*b1cdbd2cSJim Jagielski 	}
3827*b1cdbd2cSJim Jagielski 
3828*b1cdbd2cSJim Jagielski 	return aNewSelection;
3829*b1cdbd2cSJim Jagielski }
3830*b1cdbd2cSJim Jagielski 
GetInvalidYOffsets(ParaPortion * pPortion)3831*b1cdbd2cSJim Jagielski Range ImpEditEngine::GetInvalidYOffsets( ParaPortion* pPortion )
3832*b1cdbd2cSJim Jagielski {
3833*b1cdbd2cSJim Jagielski 	Range aRange( 0, 0 );
3834*b1cdbd2cSJim Jagielski 
3835*b1cdbd2cSJim Jagielski 	if ( pPortion->IsVisible() )
3836*b1cdbd2cSJim Jagielski 	{
3837*b1cdbd2cSJim Jagielski 		const SvxULSpaceItem& rULSpace = (const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
3838*b1cdbd2cSJim Jagielski 		const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
3839*b1cdbd2cSJim Jagielski 		sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
3840*b1cdbd2cSJim Jagielski 							? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
3841*b1cdbd2cSJim Jagielski 
3842*b1cdbd2cSJim Jagielski 		// erst von vorne...
3843*b1cdbd2cSJim Jagielski 		sal_uInt16 nFirstInvalid = 0xFFFF;
3844*b1cdbd2cSJim Jagielski 		sal_uInt16 nLine;
3845*b1cdbd2cSJim Jagielski 		for ( nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
3846*b1cdbd2cSJim Jagielski 		{
3847*b1cdbd2cSJim Jagielski 			EditLine* pL = pPortion->GetLines().GetObject( nLine );
3848*b1cdbd2cSJim Jagielski 			if ( pL->IsInvalid() )
3849*b1cdbd2cSJim Jagielski 			{
3850*b1cdbd2cSJim Jagielski 				nFirstInvalid = nLine;
3851*b1cdbd2cSJim Jagielski 				break;
3852*b1cdbd2cSJim Jagielski 			}
3853*b1cdbd2cSJim Jagielski 			if ( nLine && !aStatus.IsOutliner() ) 	// nicht die erste Zeile
3854*b1cdbd2cSJim Jagielski 				aRange.Min() += nSBL;
3855*b1cdbd2cSJim Jagielski 			aRange.Min() += pL->GetHeight();
3856*b1cdbd2cSJim Jagielski 		}
3857*b1cdbd2cSJim Jagielski 		DBG_ASSERT( nFirstInvalid != 0xFFFF, "Keine ungueltige Zeile gefunden in GetInvalidYOffset(1)" );
3858*b1cdbd2cSJim Jagielski 
3859*b1cdbd2cSJim Jagielski 
3860*b1cdbd2cSJim Jagielski 		// Abgleichen und weiter...
3861*b1cdbd2cSJim Jagielski 		aRange.Max() = aRange.Min();
3862*b1cdbd2cSJim Jagielski 		aRange.Max() += pPortion->GetFirstLineOffset();
3863*b1cdbd2cSJim Jagielski 		if ( nFirstInvalid != 0 )	// Nur wenn nicht die erste Zeile ungueltig
3864*b1cdbd2cSJim Jagielski 			aRange.Min() = aRange.Max();
3865*b1cdbd2cSJim Jagielski 
3866*b1cdbd2cSJim Jagielski 		sal_uInt16 nLastInvalid = pPortion->GetLines().Count()-1;
3867*b1cdbd2cSJim Jagielski 		for ( nLine = nFirstInvalid; nLine < pPortion->GetLines().Count(); nLine++ )
3868*b1cdbd2cSJim Jagielski 		{
3869*b1cdbd2cSJim Jagielski 			EditLine* pL = pPortion->GetLines().GetObject( nLine );
3870*b1cdbd2cSJim Jagielski 			if ( pL->IsValid() )
3871*b1cdbd2cSJim Jagielski 			{
3872*b1cdbd2cSJim Jagielski 				nLastInvalid = nLine;
3873*b1cdbd2cSJim Jagielski 				break;
3874*b1cdbd2cSJim Jagielski 			}
3875*b1cdbd2cSJim Jagielski 
3876*b1cdbd2cSJim Jagielski 			if ( nLine && !aStatus.IsOutliner() )
3877*b1cdbd2cSJim Jagielski 				aRange.Max() += nSBL;
3878*b1cdbd2cSJim Jagielski 			aRange.Max() += pL->GetHeight();
3879*b1cdbd2cSJim Jagielski 		}
3880*b1cdbd2cSJim Jagielski 
3881*b1cdbd2cSJim Jagielski 		// MT 07/00 SBL kann jetzt kleiner 100% sein => ggf. die Zeile davor neu ausgeben.
3882*b1cdbd2cSJim Jagielski 		if( ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP ) && rLSItem.GetPropLineSpace() &&
3883*b1cdbd2cSJim Jagielski 			( rLSItem.GetPropLineSpace() < 100 ) )
3884*b1cdbd2cSJim Jagielski 		{
3885*b1cdbd2cSJim Jagielski 			EditLine* pL = pPortion->GetLines().GetObject( nFirstInvalid );
3886*b1cdbd2cSJim Jagielski 			long n = pL->GetTxtHeight() * ( 100 - rLSItem.GetPropLineSpace() );
3887*b1cdbd2cSJim Jagielski 			n /= 100;
3888*b1cdbd2cSJim Jagielski 			aRange.Min() -= n;
3889*b1cdbd2cSJim Jagielski 			aRange.Max() += n;
3890*b1cdbd2cSJim Jagielski 		}
3891*b1cdbd2cSJim Jagielski 
3892*b1cdbd2cSJim Jagielski 		if ( ( nLastInvalid == pPortion->GetLines().Count()-1 ) && ( !aStatus.IsOutliner() ) )
3893*b1cdbd2cSJim Jagielski 			aRange.Max() += GetYValue( rULSpace.GetLower() );
3894*b1cdbd2cSJim Jagielski 	}
3895*b1cdbd2cSJim Jagielski 	return aRange;
3896*b1cdbd2cSJim Jagielski }
3897*b1cdbd2cSJim Jagielski 
GetPaM(ParaPortion * pPortion,Point aDocPos,sal_Bool bSmart)3898*b1cdbd2cSJim Jagielski EditPaM ImpEditEngine::GetPaM( ParaPortion* pPortion, Point aDocPos, sal_Bool bSmart )
3899*b1cdbd2cSJim Jagielski {
3900*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPortion->IsVisible(), "Wozu GetPaM() bei einem unsichtbaren Absatz?" );
3901*b1cdbd2cSJim Jagielski 	DBG_ASSERT( IsFormatted(), "GetPaM: Nicht formatiert" );
3902*b1cdbd2cSJim Jagielski 
3903*b1cdbd2cSJim Jagielski 	sal_uInt16 nCurIndex = 0;
3904*b1cdbd2cSJim Jagielski 	EditPaM aPaM;
3905*b1cdbd2cSJim Jagielski 	aPaM.SetNode( pPortion->GetNode() );
3906*b1cdbd2cSJim Jagielski 
3907*b1cdbd2cSJim Jagielski 	const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
3908*b1cdbd2cSJim Jagielski 	sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
3909*b1cdbd2cSJim Jagielski 						? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
3910*b1cdbd2cSJim Jagielski 
3911*b1cdbd2cSJim Jagielski 	long nY = pPortion->GetFirstLineOffset();
3912*b1cdbd2cSJim Jagielski 
3913*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPortion->GetLines().Count(), "Leere ParaPortion in GetPaM!" );
3914*b1cdbd2cSJim Jagielski 
3915*b1cdbd2cSJim Jagielski 	EditLine* pLine = 0;
3916*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
3917*b1cdbd2cSJim Jagielski 	{
3918*b1cdbd2cSJim Jagielski 		EditLine* pTmpLine = pPortion->GetLines().GetObject( nLine );
3919*b1cdbd2cSJim Jagielski 		nY += pTmpLine->GetHeight();
3920*b1cdbd2cSJim Jagielski 		if ( !aStatus.IsOutliner() )
3921*b1cdbd2cSJim Jagielski 			nY += nSBL;
3922*b1cdbd2cSJim Jagielski 		if ( nY > aDocPos.Y() ) 	// das war 'se
3923*b1cdbd2cSJim Jagielski 		{
3924*b1cdbd2cSJim Jagielski 			pLine = pTmpLine;
3925*b1cdbd2cSJim Jagielski 			break;					// richtige Y-Position intressiert nicht
3926*b1cdbd2cSJim Jagielski 		}
3927*b1cdbd2cSJim Jagielski 
3928*b1cdbd2cSJim Jagielski 		nCurIndex = nCurIndex + pTmpLine->GetLen();
3929*b1cdbd2cSJim Jagielski 	}
3930*b1cdbd2cSJim Jagielski 
3931*b1cdbd2cSJim Jagielski 	if ( !pLine ) // darf nur im Bereich von SA passieren!
3932*b1cdbd2cSJim Jagielski 	{
3933*b1cdbd2cSJim Jagielski 		#ifdef DBG_UTIL
3934*b1cdbd2cSJim Jagielski 		 const SvxULSpaceItem& rULSpace =(const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
3935*b1cdbd2cSJim Jagielski 		 DBG_ASSERT( nY+GetYValue( rULSpace.GetLower() ) >= aDocPos.Y() , "Index in keiner Zeile, GetPaM ?" );
3936*b1cdbd2cSJim Jagielski 		#endif
3937*b1cdbd2cSJim Jagielski 		aPaM.SetIndex( pPortion->GetNode()->Len() );
3938*b1cdbd2cSJim Jagielski 		return aPaM;
3939*b1cdbd2cSJim Jagielski 	}
3940*b1cdbd2cSJim Jagielski 
3941*b1cdbd2cSJim Jagielski 	// Wenn Zeile gefunden, nur noch X-Position => Index
3942*b1cdbd2cSJim Jagielski 	nCurIndex = GetChar( pPortion, pLine, aDocPos.X(), bSmart );
3943*b1cdbd2cSJim Jagielski 	aPaM.SetIndex( nCurIndex );
3944*b1cdbd2cSJim Jagielski 
3945*b1cdbd2cSJim Jagielski 	if ( nCurIndex && ( nCurIndex == pLine->GetEnd() ) &&
3946*b1cdbd2cSJim Jagielski 		 ( pLine != pPortion->GetLines().GetObject( pPortion->GetLines().Count()-1) ) )
3947*b1cdbd2cSJim Jagielski     {
3948*b1cdbd2cSJim Jagielski         aPaM = CursorLeft( aPaM, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL );
3949*b1cdbd2cSJim Jagielski     }
3950*b1cdbd2cSJim Jagielski 
3951*b1cdbd2cSJim Jagielski 	return aPaM;
3952*b1cdbd2cSJim Jagielski }
3953*b1cdbd2cSJim Jagielski 
GetChar(ParaPortion * pParaPortion,EditLine * pLine,long nXPos,sal_Bool bSmart)3954*b1cdbd2cSJim Jagielski sal_uInt16 ImpEditEngine::GetChar( ParaPortion* pParaPortion, EditLine* pLine, long nXPos, sal_Bool bSmart )
3955*b1cdbd2cSJim Jagielski {
3956*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pLine, "Keine Zeile erhalten: GetChar" );
3957*b1cdbd2cSJim Jagielski 
3958*b1cdbd2cSJim Jagielski     sal_uInt16 nChar = 0xFFFF;
3959*b1cdbd2cSJim Jagielski     sal_uInt16 nCurIndex = pLine->GetStart();
3960*b1cdbd2cSJim Jagielski 
3961*b1cdbd2cSJim Jagielski 
3962*b1cdbd2cSJim Jagielski     // Search best matching portion with GetPortionXOffset()
3963*b1cdbd2cSJim Jagielski     for ( sal_uInt16 i = pLine->GetStartPortion(); i <= pLine->GetEndPortion(); i++ )
3964*b1cdbd2cSJim Jagielski 	{
3965*b1cdbd2cSJim Jagielski 		TextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( i );
3966*b1cdbd2cSJim Jagielski         long nXLeft = GetPortionXOffset( pParaPortion, pLine, i );
3967*b1cdbd2cSJim Jagielski         long nXRight = nXLeft + pPortion->GetSize().Width();
3968*b1cdbd2cSJim Jagielski         if ( ( nXLeft <= nXPos ) && ( nXRight >= nXPos ) )
3969*b1cdbd2cSJim Jagielski         {
3970*b1cdbd2cSJim Jagielski              nChar = nCurIndex;
3971*b1cdbd2cSJim Jagielski 
3972*b1cdbd2cSJim Jagielski             // Search within Portion...
3973*b1cdbd2cSJim Jagielski 
3974*b1cdbd2cSJim Jagielski             // Don't search within special portions...
3975*b1cdbd2cSJim Jagielski 			if ( pPortion->GetKind() != PORTIONKIND_TEXT )
3976*b1cdbd2cSJim Jagielski 			{
3977*b1cdbd2cSJim Jagielski                 // ...but check on which side
3978*b1cdbd2cSJim Jagielski                 if ( bSmart )
3979*b1cdbd2cSJim Jagielski                 {
3980*b1cdbd2cSJim Jagielski 				    long nLeftDiff = nXPos-nXLeft;
3981*b1cdbd2cSJim Jagielski 				    long nRightDiff = nXRight-nXPos;
3982*b1cdbd2cSJim Jagielski 				    if ( nRightDiff < nLeftDiff )
3983*b1cdbd2cSJim Jagielski 					    nChar++;
3984*b1cdbd2cSJim Jagielski                 }
3985*b1cdbd2cSJim Jagielski 			}
3986*b1cdbd2cSJim Jagielski             else
3987*b1cdbd2cSJim Jagielski             {
3988*b1cdbd2cSJim Jagielski 			    sal_uInt16 nMax = pPortion->GetLen();
3989*b1cdbd2cSJim Jagielski 			    sal_uInt16 nOffset = 0xFFFF;
3990*b1cdbd2cSJim Jagielski 			    sal_uInt16 nTmpCurIndex = nChar - pLine->GetStart();
3991*b1cdbd2cSJim Jagielski 
3992*b1cdbd2cSJim Jagielski                 long nXInPortion = nXPos - nXLeft;
3993*b1cdbd2cSJim Jagielski                 if ( pPortion->IsRightToLeft() )
3994*b1cdbd2cSJim Jagielski                     nXInPortion = nXRight - nXPos;
3995*b1cdbd2cSJim Jagielski 
3996*b1cdbd2cSJim Jagielski                 // Search in Array...
3997*b1cdbd2cSJim Jagielski 			    for ( sal_uInt16 x = 0; x < nMax; x++ )
3998*b1cdbd2cSJim Jagielski 			    {
3999*b1cdbd2cSJim Jagielski 				    long nTmpPosMax = pLine->GetCharPosArray().GetObject( nTmpCurIndex+x );
4000*b1cdbd2cSJim Jagielski 				    if ( nTmpPosMax > nXInPortion )
4001*b1cdbd2cSJim Jagielski 				    {
4002*b1cdbd2cSJim Jagielski 					    // pruefen, ob dieser oder der davor...
4003*b1cdbd2cSJim Jagielski                         long nTmpPosMin = x ? pLine->GetCharPosArray().GetObject( nTmpCurIndex+x-1 ) : 0;
4004*b1cdbd2cSJim Jagielski 					    long nDiffLeft = nXInPortion - nTmpPosMin;
4005*b1cdbd2cSJim Jagielski 					    long nDiffRight = nTmpPosMax - nXInPortion;
4006*b1cdbd2cSJim Jagielski 					    DBG_ASSERT( nDiffLeft >= 0, "DiffLeft negativ" );
4007*b1cdbd2cSJim Jagielski 					    DBG_ASSERT( nDiffRight >= 0, "DiffRight negativ" );
4008*b1cdbd2cSJim Jagielski 					    nOffset = ( bSmart && ( nDiffRight < nDiffLeft ) ) ? x+1 : x;
4009*b1cdbd2cSJim Jagielski 					    // I18N: If there are character position with the length of 0,
4010*b1cdbd2cSJim Jagielski                         // they belong to the same character, we can not use this position as an index.
4011*b1cdbd2cSJim Jagielski 					    // Skip all 0-positions, cheaper than using XBreakIterator:
4012*b1cdbd2cSJim Jagielski 					    if ( nOffset < nMax )
4013*b1cdbd2cSJim Jagielski 					    {
4014*b1cdbd2cSJim Jagielski 						    const long nX = pLine->GetCharPosArray().GetObject(nOffset);
4015*b1cdbd2cSJim Jagielski 						    while ( ( (nOffset+1) < nMax ) && ( pLine->GetCharPosArray().GetObject(nOffset+1) == nX ) )
4016*b1cdbd2cSJim Jagielski 							    nOffset++;
4017*b1cdbd2cSJim Jagielski 					    }
4018*b1cdbd2cSJim Jagielski 					    break;
4019*b1cdbd2cSJim Jagielski 				    }
4020*b1cdbd2cSJim Jagielski 			    }
4021*b1cdbd2cSJim Jagielski 
4022*b1cdbd2cSJim Jagielski 			    // Bei Verwendung des CharPosArray duerfte es keine Ungenauigkeiten geben!
4023*b1cdbd2cSJim Jagielski 			    // Vielleicht bei Kerning ?
4024*b1cdbd2cSJim Jagielski 			    // 0xFFF passiert z.B. bei Outline-Font, wenn ganz hinten.
4025*b1cdbd2cSJim Jagielski 			    if ( nOffset == 0xFFFF )
4026*b1cdbd2cSJim Jagielski 				    nOffset = nMax;
4027*b1cdbd2cSJim Jagielski 
4028*b1cdbd2cSJim Jagielski 			    DBG_ASSERT( nOffset <= nMax, "nOffset > nMax" );
4029*b1cdbd2cSJim Jagielski 
4030*b1cdbd2cSJim Jagielski                 nChar = nChar + nOffset;
4031*b1cdbd2cSJim Jagielski 
4032*b1cdbd2cSJim Jagielski                 // Check if index is within a cell:
4033*b1cdbd2cSJim Jagielski                 if ( nChar && ( nChar < pParaPortion->GetNode()->Len() ) )
4034*b1cdbd2cSJim Jagielski                 {
4035*b1cdbd2cSJim Jagielski                     EditPaM aPaM( pParaPortion->GetNode(), nChar+1 );
4036*b1cdbd2cSJim Jagielski                     sal_uInt16 nScriptType = GetScriptType( aPaM );
4037*b1cdbd2cSJim Jagielski                     if ( nScriptType == i18n::ScriptType::COMPLEX )
4038*b1cdbd2cSJim Jagielski                     {
4039*b1cdbd2cSJim Jagielski 		                uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
4040*b1cdbd2cSJim Jagielski 		                sal_Int32 nCount = 1;
4041*b1cdbd2cSJim Jagielski                         lang::Locale aLocale = GetLocale( aPaM );
4042*b1cdbd2cSJim Jagielski                         sal_uInt16 nRight = (sal_uInt16)_xBI->nextCharacters( *pParaPortion->GetNode(), nChar, aLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
4043*b1cdbd2cSJim Jagielski 						sal_uInt16 nLeft = (sal_uInt16)_xBI->previousCharacters( *pParaPortion->GetNode(), nRight, aLocale, ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
4044*b1cdbd2cSJim Jagielski                         if ( ( nLeft != nChar ) && ( nRight != nChar ) )
4045*b1cdbd2cSJim Jagielski                         {
4046*b1cdbd2cSJim Jagielski                             nChar = ( Abs( nRight - nChar ) < Abs( nLeft - nChar ) ) ? nRight : nLeft;
4047*b1cdbd2cSJim Jagielski                         }
4048*b1cdbd2cSJim Jagielski                     }
4049*b1cdbd2cSJim Jagielski                 }
4050*b1cdbd2cSJim Jagielski             }
4051*b1cdbd2cSJim Jagielski         }
4052*b1cdbd2cSJim Jagielski 
4053*b1cdbd2cSJim Jagielski         nCurIndex = nCurIndex + pPortion->GetLen();
4054*b1cdbd2cSJim Jagielski     }
4055*b1cdbd2cSJim Jagielski 
4056*b1cdbd2cSJim Jagielski     if ( nChar == 0xFFFF )
4057*b1cdbd2cSJim Jagielski     {
4058*b1cdbd2cSJim Jagielski         nChar = ( nXPos <= pLine->GetStartPosX() ) ? pLine->GetStart() : pLine->GetEnd();
4059*b1cdbd2cSJim Jagielski     }
4060*b1cdbd2cSJim Jagielski 
4061*b1cdbd2cSJim Jagielski     return nChar;
4062*b1cdbd2cSJim Jagielski }
4063*b1cdbd2cSJim Jagielski 
GetLineXPosStartEnd(ParaPortion * pParaPortion,EditLine * pLine)4064*b1cdbd2cSJim Jagielski Range ImpEditEngine::GetLineXPosStartEnd( ParaPortion* pParaPortion, EditLine* pLine )
4065*b1cdbd2cSJim Jagielski {
4066*b1cdbd2cSJim Jagielski     Range aLineXPosStartEnd;
4067*b1cdbd2cSJim Jagielski 
4068*b1cdbd2cSJim Jagielski     sal_uInt16 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
4069*b1cdbd2cSJim Jagielski     if ( !IsRightToLeft( nPara ) )
4070*b1cdbd2cSJim Jagielski     {
4071*b1cdbd2cSJim Jagielski         aLineXPosStartEnd.Min() = pLine->GetStartPosX();
4072*b1cdbd2cSJim Jagielski         aLineXPosStartEnd.Max() = pLine->GetStartPosX() + pLine->GetTextWidth();
4073*b1cdbd2cSJim Jagielski     }
4074*b1cdbd2cSJim Jagielski     else
4075*b1cdbd2cSJim Jagielski     {
4076*b1cdbd2cSJim Jagielski         aLineXPosStartEnd.Min() = GetPaperSize().Width() - ( pLine->GetStartPosX() + pLine->GetTextWidth() );
4077*b1cdbd2cSJim Jagielski         aLineXPosStartEnd.Max() = GetPaperSize().Width() - pLine->GetStartPosX();
4078*b1cdbd2cSJim Jagielski     }
4079*b1cdbd2cSJim Jagielski 
4080*b1cdbd2cSJim Jagielski 
4081*b1cdbd2cSJim Jagielski     return aLineXPosStartEnd;
4082*b1cdbd2cSJim Jagielski }
4083*b1cdbd2cSJim Jagielski 
GetPortionXOffset(ParaPortion * pParaPortion,EditLine * pLine,sal_uInt16 nTextPortion)4084*b1cdbd2cSJim Jagielski long ImpEditEngine::GetPortionXOffset( ParaPortion* pParaPortion, EditLine* pLine, sal_uInt16 nTextPortion )
4085*b1cdbd2cSJim Jagielski {
4086*b1cdbd2cSJim Jagielski 	long nX = pLine->GetStartPosX();
4087*b1cdbd2cSJim Jagielski 
4088*b1cdbd2cSJim Jagielski     for ( sal_uInt16 i = pLine->GetStartPortion(); i < nTextPortion; i++ )
4089*b1cdbd2cSJim Jagielski 	{
4090*b1cdbd2cSJim Jagielski 		TextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( i );
4091*b1cdbd2cSJim Jagielski 		switch ( pPortion->GetKind() )
4092*b1cdbd2cSJim Jagielski 		{
4093*b1cdbd2cSJim Jagielski 			case PORTIONKIND_FIELD:
4094*b1cdbd2cSJim Jagielski 			case PORTIONKIND_TEXT:
4095*b1cdbd2cSJim Jagielski 			case PORTIONKIND_HYPHENATOR:
4096*b1cdbd2cSJim Jagielski 			case PORTIONKIND_TAB:
4097*b1cdbd2cSJim Jagielski //	        case PORTIONKIND_EXTRASPACE:
4098*b1cdbd2cSJim Jagielski 			{
4099*b1cdbd2cSJim Jagielski 				nX += pPortion->GetSize().Width();
4100*b1cdbd2cSJim Jagielski 			}
4101*b1cdbd2cSJim Jagielski 			break;
4102*b1cdbd2cSJim Jagielski 		}
4103*b1cdbd2cSJim Jagielski     }
4104*b1cdbd2cSJim Jagielski 
4105*b1cdbd2cSJim Jagielski     sal_uInt16 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
4106*b1cdbd2cSJim Jagielski     sal_Bool bR2LPara = IsRightToLeft( nPara );
4107*b1cdbd2cSJim Jagielski 
4108*b1cdbd2cSJim Jagielski     TextPortion* pDestPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
4109*b1cdbd2cSJim Jagielski     if ( pDestPortion->GetKind() != PORTIONKIND_TAB )
4110*b1cdbd2cSJim Jagielski     {
4111*b1cdbd2cSJim Jagielski         if ( !bR2LPara && pDestPortion->GetRightToLeft() )
4112*b1cdbd2cSJim Jagielski         {
4113*b1cdbd2cSJim Jagielski             // Portions behind must be added, visual before this portion
4114*b1cdbd2cSJim Jagielski             sal_uInt16 nTmpPortion = nTextPortion+1;
4115*b1cdbd2cSJim Jagielski             while ( nTmpPortion <= pLine->GetEndPortion() )
4116*b1cdbd2cSJim Jagielski             {
4117*b1cdbd2cSJim Jagielski 		        TextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
4118*b1cdbd2cSJim Jagielski                 if ( pNextTextPortion->GetRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
4119*b1cdbd2cSJim Jagielski                     nX += pNextTextPortion->GetSize().Width();
4120*b1cdbd2cSJim Jagielski                 else
4121*b1cdbd2cSJim Jagielski                     break;
4122*b1cdbd2cSJim Jagielski                 nTmpPortion++;
4123*b1cdbd2cSJim Jagielski             }
4124*b1cdbd2cSJim Jagielski             // Portions before must be removed, visual behind this portion
4125*b1cdbd2cSJim Jagielski             nTmpPortion = nTextPortion;
4126*b1cdbd2cSJim Jagielski             while ( nTmpPortion > pLine->GetStartPortion() )
4127*b1cdbd2cSJim Jagielski             {
4128*b1cdbd2cSJim Jagielski                 --nTmpPortion;
4129*b1cdbd2cSJim Jagielski 		        TextPortion* pPrevTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
4130*b1cdbd2cSJim Jagielski                 if ( pPrevTextPortion->GetRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
4131*b1cdbd2cSJim Jagielski                     nX -= pPrevTextPortion->GetSize().Width();
4132*b1cdbd2cSJim Jagielski                 else
4133*b1cdbd2cSJim Jagielski                     break;
4134*b1cdbd2cSJim Jagielski             }
4135*b1cdbd2cSJim Jagielski         }
4136*b1cdbd2cSJim Jagielski         else if ( bR2LPara && !pDestPortion->IsRightToLeft() )
4137*b1cdbd2cSJim Jagielski         {
4138*b1cdbd2cSJim Jagielski             // Portions behind must be ermoved, visual behind this portion
4139*b1cdbd2cSJim Jagielski             sal_uInt16 nTmpPortion = nTextPortion+1;
4140*b1cdbd2cSJim Jagielski             while ( nTmpPortion <= pLine->GetEndPortion() )
4141*b1cdbd2cSJim Jagielski             {
4142*b1cdbd2cSJim Jagielski 		        TextPortion* pNextTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
4143*b1cdbd2cSJim Jagielski                 if ( !pNextTextPortion->IsRightToLeft() && ( pNextTextPortion->GetKind() != PORTIONKIND_TAB ) )
4144*b1cdbd2cSJim Jagielski                     nX += pNextTextPortion->GetSize().Width();
4145*b1cdbd2cSJim Jagielski                 else
4146*b1cdbd2cSJim Jagielski                     break;
4147*b1cdbd2cSJim Jagielski                 nTmpPortion++;
4148*b1cdbd2cSJim Jagielski             }
4149*b1cdbd2cSJim Jagielski             // Portions before must be added, visual before this portion
4150*b1cdbd2cSJim Jagielski             nTmpPortion = nTextPortion;
4151*b1cdbd2cSJim Jagielski             while ( nTmpPortion > pLine->GetStartPortion() )
4152*b1cdbd2cSJim Jagielski             {
4153*b1cdbd2cSJim Jagielski                 --nTmpPortion;
4154*b1cdbd2cSJim Jagielski 		        TextPortion* pPrevTextPortion = pParaPortion->GetTextPortions().GetObject( nTmpPortion );
4155*b1cdbd2cSJim Jagielski                 if ( !pPrevTextPortion->IsRightToLeft() && ( pPrevTextPortion->GetKind() != PORTIONKIND_TAB ) )
4156*b1cdbd2cSJim Jagielski                     nX -= pPrevTextPortion->GetSize().Width();
4157*b1cdbd2cSJim Jagielski                 else
4158*b1cdbd2cSJim Jagielski                     break;
4159*b1cdbd2cSJim Jagielski             }
4160*b1cdbd2cSJim Jagielski         }
4161*b1cdbd2cSJim Jagielski     }
4162*b1cdbd2cSJim Jagielski     if ( bR2LPara )
4163*b1cdbd2cSJim Jagielski     {
4164*b1cdbd2cSJim Jagielski         // Switch X postions...
4165*b1cdbd2cSJim Jagielski         DBG_ASSERT( GetTextRanger() || GetPaperSize().Width(), "GetPortionXOffset - paper size?!" );
4166*b1cdbd2cSJim Jagielski         DBG_ASSERT( GetTextRanger() || (nX <= GetPaperSize().Width()), "GetPortionXOffset - position out of paper size!" );
4167*b1cdbd2cSJim Jagielski         nX = GetPaperSize().Width() - nX;
4168*b1cdbd2cSJim Jagielski         nX -= pDestPortion->GetSize().Width();
4169*b1cdbd2cSJim Jagielski     }
4170*b1cdbd2cSJim Jagielski 
4171*b1cdbd2cSJim Jagielski     return nX;
4172*b1cdbd2cSJim Jagielski }
4173*b1cdbd2cSJim Jagielski 
GetXPos(ParaPortion * pParaPortion,EditLine * pLine,sal_uInt16 nIndex,sal_Bool bPreferPortionStart)4174*b1cdbd2cSJim Jagielski long ImpEditEngine::GetXPos( ParaPortion* pParaPortion, EditLine* pLine, sal_uInt16 nIndex, sal_Bool bPreferPortionStart )
4175*b1cdbd2cSJim Jagielski {
4176*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pLine, "Keine Zeile erhalten: GetXPos" );
4177*b1cdbd2cSJim Jagielski 	DBG_ASSERT( ( nIndex >= pLine->GetStart() ) && ( nIndex <= pLine->GetEnd() ) , "GetXPos muss richtig gerufen werden!" );
4178*b1cdbd2cSJim Jagielski 
4179*b1cdbd2cSJim Jagielski     sal_Bool bDoPreferPortionStart = bPreferPortionStart;
4180*b1cdbd2cSJim Jagielski     // Assure that the portion belongs to this line:
4181*b1cdbd2cSJim Jagielski     if ( nIndex == pLine->GetStart() )
4182*b1cdbd2cSJim Jagielski         bDoPreferPortionStart = sal_True;
4183*b1cdbd2cSJim Jagielski     else if ( nIndex == pLine->GetEnd() )
4184*b1cdbd2cSJim Jagielski         bDoPreferPortionStart = sal_False;
4185*b1cdbd2cSJim Jagielski 
4186*b1cdbd2cSJim Jagielski     sal_uInt16 nTextPortionStart = 0;
4187*b1cdbd2cSJim Jagielski     sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart );
4188*b1cdbd2cSJim Jagielski 
4189*b1cdbd2cSJim Jagielski     DBG_ASSERT( ( nTextPortion >= pLine->GetStartPortion() ) && ( nTextPortion <= pLine->GetEndPortion() ), "GetXPos: Portion not in current line! " );
4190*b1cdbd2cSJim Jagielski 
4191*b1cdbd2cSJim Jagielski     TextPortion* pPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
4192*b1cdbd2cSJim Jagielski 
4193*b1cdbd2cSJim Jagielski     long nX = GetPortionXOffset( pParaPortion, pLine, nTextPortion );
4194*b1cdbd2cSJim Jagielski 
4195*b1cdbd2cSJim Jagielski     // calc text width, portion size may include CJK/CTL spacing...
4196*b1cdbd2cSJim Jagielski     // But the array migh not be init yet, if using text ranger this method is called within CreateLines()...
4197*b1cdbd2cSJim Jagielski     long nPortionTextWidth = pPortion->GetSize().Width();
4198*b1cdbd2cSJim Jagielski     if ( ( pPortion->GetKind() == PORTIONKIND_TEXT ) && pPortion->GetLen() && !GetTextRanger() )
4199*b1cdbd2cSJim Jagielski         nPortionTextWidth = pLine->GetCharPosArray().GetObject( nTextPortionStart + pPortion->GetLen() - 1 - pLine->GetStart() );
4200*b1cdbd2cSJim Jagielski 
4201*b1cdbd2cSJim Jagielski     if ( nTextPortionStart != nIndex )
4202*b1cdbd2cSJim Jagielski     {
4203*b1cdbd2cSJim Jagielski         // Search within portion...
4204*b1cdbd2cSJim Jagielski         if ( nIndex == ( nTextPortionStart + pPortion->GetLen() ) )
4205*b1cdbd2cSJim Jagielski         {
4206*b1cdbd2cSJim Jagielski             // End of Portion
4207*b1cdbd2cSJim Jagielski             if ( pPortion->GetKind() == PORTIONKIND_TAB )
4208*b1cdbd2cSJim Jagielski             {
4209*b1cdbd2cSJim Jagielski                 if ( (nTextPortion+1) < pParaPortion->GetTextPortions().Count() )
4210*b1cdbd2cSJim Jagielski                 {
4211*b1cdbd2cSJim Jagielski                     TextPortion* pNextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion+1 );
4212*b1cdbd2cSJim Jagielski                     if ( pNextPortion->GetKind() != PORTIONKIND_TAB )
4213*b1cdbd2cSJim Jagielski                     {
4214*b1cdbd2cSJim Jagielski                         // DBG_ASSERT( !bPreferPortionStart, "GetXPos - How can we this tab portion here???" );
4215*b1cdbd2cSJim Jagielski 						// #109879# We loop if nIndex == pLine->GetEnd, because bPreferPortionStart will be reset
4216*b1cdbd2cSJim Jagielski 						if ( !bPreferPortionStart )
4217*b1cdbd2cSJim Jagielski 							nX = GetXPos( pParaPortion, pLine, nIndex, sal_True );
4218*b1cdbd2cSJim Jagielski 						else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) )
4219*b1cdbd2cSJim Jagielski 							nX += nPortionTextWidth;
4220*b1cdbd2cSJim Jagielski                     }
4221*b1cdbd2cSJim Jagielski                 }
4222*b1cdbd2cSJim Jagielski                 else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) )
4223*b1cdbd2cSJim Jagielski                 {
4224*b1cdbd2cSJim Jagielski 				    nX += nPortionTextWidth;
4225*b1cdbd2cSJim Jagielski                 }
4226*b1cdbd2cSJim Jagielski             }
4227*b1cdbd2cSJim Jagielski             else if ( !pPortion->IsRightToLeft() )
4228*b1cdbd2cSJim Jagielski             {
4229*b1cdbd2cSJim Jagielski 				nX += nPortionTextWidth;
4230*b1cdbd2cSJim Jagielski             }
4231*b1cdbd2cSJim Jagielski         }
4232*b1cdbd2cSJim Jagielski         else if ( pPortion->GetKind() == PORTIONKIND_TEXT )
4233*b1cdbd2cSJim Jagielski         {
4234*b1cdbd2cSJim Jagielski 			DBG_ASSERT( nIndex != pLine->GetStart(), "Strange behavior in new GetXPos()" );
4235*b1cdbd2cSJim Jagielski 			DBG_ASSERT( pLine && pLine->GetCharPosArray().Count(), "svx::ImpEditEngine::GetXPos(), portion in an empty line?" );
4236*b1cdbd2cSJim Jagielski 
4237*b1cdbd2cSJim Jagielski 			if( pLine->GetCharPosArray().Count() )
4238*b1cdbd2cSJim Jagielski 			{
4239*b1cdbd2cSJim Jagielski 				sal_uInt16 nPos = nIndex - 1 - pLine->GetStart();
4240*b1cdbd2cSJim Jagielski 				if( nPos >= pLine->GetCharPosArray().Count() )
4241*b1cdbd2cSJim Jagielski 				{
4242*b1cdbd2cSJim Jagielski 					nPos = pLine->GetCharPosArray().Count()-1;
4243*b1cdbd2cSJim Jagielski 					DBG_ERROR("svx::ImpEditEngine::GetXPos(), index out of range!");
4244*b1cdbd2cSJim Jagielski 				}
4245*b1cdbd2cSJim Jagielski 
4246*b1cdbd2cSJim Jagielski                 // old code restored see #i112788 (which leaves #i74188 unfixed again)
4247*b1cdbd2cSJim Jagielski                 long nPosInPortion = pLine->GetCharPosArray().GetObject( nPos );
4248*b1cdbd2cSJim Jagielski 
4249*b1cdbd2cSJim Jagielski 				if ( !pPortion->IsRightToLeft() )
4250*b1cdbd2cSJim Jagielski 				{
4251*b1cdbd2cSJim Jagielski 					nX += nPosInPortion;
4252*b1cdbd2cSJim Jagielski 				}
4253*b1cdbd2cSJim Jagielski 				else
4254*b1cdbd2cSJim Jagielski 				{
4255*b1cdbd2cSJim Jagielski 					nX += nPortionTextWidth - nPosInPortion;
4256*b1cdbd2cSJim Jagielski 				}
4257*b1cdbd2cSJim Jagielski 
4258*b1cdbd2cSJim Jagielski 				if ( pPortion->GetExtraInfos() && pPortion->GetExtraInfos()->bCompressed )
4259*b1cdbd2cSJim Jagielski 				{
4260*b1cdbd2cSJim Jagielski 					nX += pPortion->GetExtraInfos()->nPortionOffsetX;
4261*b1cdbd2cSJim Jagielski 					if ( pPortion->GetExtraInfos()->nAsianCompressionTypes & CHAR_PUNCTUATIONRIGHT )
4262*b1cdbd2cSJim Jagielski 					{
4263*b1cdbd2cSJim Jagielski 						sal_uInt8 nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex ) );
4264*b1cdbd2cSJim Jagielski 						if ( nType == CHAR_PUNCTUATIONRIGHT )
4265*b1cdbd2cSJim Jagielski 						{
4266*b1cdbd2cSJim Jagielski 							sal_uInt16 n = nIndex - nTextPortionStart;
4267*b1cdbd2cSJim Jagielski 							const sal_Int32* pDXArray = pLine->GetCharPosArray().GetData()+( nTextPortionStart-pLine->GetStart() );
4268*b1cdbd2cSJim Jagielski 							sal_Int32 nCharWidth = ( ( (n+1) < pPortion->GetLen() ) ? pDXArray[n] : pPortion->GetSize().Width() )
4269*b1cdbd2cSJim Jagielski 															- ( n ? pDXArray[n-1] : 0 );
4270*b1cdbd2cSJim Jagielski 							if ( (n+1) < pPortion->GetLen() )
4271*b1cdbd2cSJim Jagielski 							{
4272*b1cdbd2cSJim Jagielski 								// smaller, when char behind is CHAR_PUNCTUATIONRIGHT also
4273*b1cdbd2cSJim Jagielski 								nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex+1 ) );
4274*b1cdbd2cSJim Jagielski 								if ( nType == CHAR_PUNCTUATIONRIGHT )
4275*b1cdbd2cSJim Jagielski 								{
4276*b1cdbd2cSJim Jagielski 									sal_Int32 nNextCharWidth = ( ( (n+2) < pPortion->GetLen() ) ? pDXArray[n+1] : pPortion->GetSize().Width() )
4277*b1cdbd2cSJim Jagielski 																	- pDXArray[n];
4278*b1cdbd2cSJim Jagielski 									sal_Int32 nCompressed = nNextCharWidth/2;
4279*b1cdbd2cSJim Jagielski 									nCompressed *= pPortion->GetExtraInfos()->nMaxCompression100thPercent;
4280*b1cdbd2cSJim Jagielski 									nCompressed /= 10000;
4281*b1cdbd2cSJim Jagielski 									nCharWidth += nCompressed;
4282*b1cdbd2cSJim Jagielski 								}
4283*b1cdbd2cSJim Jagielski 							}
4284*b1cdbd2cSJim Jagielski 							else
4285*b1cdbd2cSJim Jagielski 							{
4286*b1cdbd2cSJim Jagielski 								nCharWidth *= 2;    // last char pos to portion end is only compressed size
4287*b1cdbd2cSJim Jagielski 							}
4288*b1cdbd2cSJim Jagielski 							nX += nCharWidth/2; // 50% compression
4289*b1cdbd2cSJim Jagielski 						}
4290*b1cdbd2cSJim Jagielski 					}
4291*b1cdbd2cSJim Jagielski 				}
4292*b1cdbd2cSJim Jagielski 			}
4293*b1cdbd2cSJim Jagielski 		}
4294*b1cdbd2cSJim Jagielski     }
4295*b1cdbd2cSJim Jagielski     else // if ( nIndex == pLine->GetStart() )
4296*b1cdbd2cSJim Jagielski     {
4297*b1cdbd2cSJim Jagielski         if ( pPortion->IsRightToLeft() )
4298*b1cdbd2cSJim Jagielski         {
4299*b1cdbd2cSJim Jagielski 		    nX += nPortionTextWidth;
4300*b1cdbd2cSJim Jagielski         }
4301*b1cdbd2cSJim Jagielski     }
4302*b1cdbd2cSJim Jagielski 
4303*b1cdbd2cSJim Jagielski 	return nX;
4304*b1cdbd2cSJim Jagielski }
4305*b1cdbd2cSJim Jagielski 
CalcHeight(ParaPortion * pPortion)4306*b1cdbd2cSJim Jagielski void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
4307*b1cdbd2cSJim Jagielski {
4308*b1cdbd2cSJim Jagielski 	pPortion->nHeight = 0;
4309*b1cdbd2cSJim Jagielski 	pPortion->nFirstLineOffset = 0;
4310*b1cdbd2cSJim Jagielski 
4311*b1cdbd2cSJim Jagielski 	if ( pPortion->IsVisible() )
4312*b1cdbd2cSJim Jagielski 	{
4313*b1cdbd2cSJim Jagielski 		DBG_ASSERT( pPortion->GetLines().Count(), "Absatz ohne Zeilen in ParaPortion::CalcHeight" );
4314*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
4315*b1cdbd2cSJim Jagielski 			pPortion->nHeight += pPortion->GetLines().GetObject( nLine )->GetHeight();
4316*b1cdbd2cSJim Jagielski 
4317*b1cdbd2cSJim Jagielski 		if ( !aStatus.IsOutliner() )
4318*b1cdbd2cSJim Jagielski 		{
4319*b1cdbd2cSJim Jagielski 			const SvxULSpaceItem& rULItem = (const SvxULSpaceItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
4320*b1cdbd2cSJim Jagielski 			const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
4321*b1cdbd2cSJim Jagielski 			sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX ) ? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
4322*b1cdbd2cSJim Jagielski 
4323*b1cdbd2cSJim Jagielski 			if ( nSBL )
4324*b1cdbd2cSJim Jagielski 			{
4325*b1cdbd2cSJim Jagielski 				if ( pPortion->GetLines().Count() > 1 )
4326*b1cdbd2cSJim Jagielski 					pPortion->nHeight += ( pPortion->GetLines().Count() - 1 ) * nSBL;
4327*b1cdbd2cSJim Jagielski 				if ( aStatus.ULSpaceSummation() )
4328*b1cdbd2cSJim Jagielski 					pPortion->nHeight += nSBL;
4329*b1cdbd2cSJim Jagielski 			}
4330*b1cdbd2cSJim Jagielski 
4331*b1cdbd2cSJim Jagielski 			sal_uInt16 nPortion = GetParaPortions().GetPos( pPortion );
4332*b1cdbd2cSJim Jagielski 			if ( nPortion || aStatus.ULSpaceFirstParagraph() )
4333*b1cdbd2cSJim Jagielski 			{
4334*b1cdbd2cSJim Jagielski 				sal_uInt16 nUpper = GetYValue( rULItem.GetUpper() );
4335*b1cdbd2cSJim Jagielski 				pPortion->nHeight += nUpper;
4336*b1cdbd2cSJim Jagielski 				pPortion->nFirstLineOffset = nUpper;
4337*b1cdbd2cSJim Jagielski 			}
4338*b1cdbd2cSJim Jagielski 
4339*b1cdbd2cSJim Jagielski 			if ( ( nPortion != (GetParaPortions().Count()-1) ) )
4340*b1cdbd2cSJim Jagielski 			{
4341*b1cdbd2cSJim Jagielski 				pPortion->nHeight += GetYValue( rULItem.GetLower() );	// nicht in letzter
4342*b1cdbd2cSJim Jagielski 			}
4343*b1cdbd2cSJim Jagielski 
4344*b1cdbd2cSJim Jagielski 
4345*b1cdbd2cSJim Jagielski 			if ( nPortion && !aStatus.ULSpaceSummation() )
4346*b1cdbd2cSJim Jagielski 			{
4347*b1cdbd2cSJim Jagielski 				ParaPortion* pPrev = GetParaPortions().SaveGetObject( nPortion-1 );
4348*b1cdbd2cSJim Jagielski 				const SvxULSpaceItem& rPrevULItem = (const SvxULSpaceItem&)pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
4349*b1cdbd2cSJim Jagielski 				const SvxLineSpacingItem& rPrevLSItem = (const SvxLineSpacingItem&)pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
4350*b1cdbd2cSJim Jagielski 
4351*b1cdbd2cSJim Jagielski 				// Verhalten WinWord6/Writer3:
4352*b1cdbd2cSJim Jagielski 				// Bei einem proportionalen Zeilenabstand wird auch der Absatzabstand
4353*b1cdbd2cSJim Jagielski 				// manipuliert.
4354*b1cdbd2cSJim Jagielski 				// Nur Writer3: Nicht aufaddieren, sondern Mindestabstand.
4355*b1cdbd2cSJim Jagielski 
4356*b1cdbd2cSJim Jagielski 				// Pruefen, ob Abstand durch LineSpacing > Upper:
4357*b1cdbd2cSJim Jagielski 				sal_uInt16 nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPortion, rLSItem ) );
4358*b1cdbd2cSJim Jagielski 				if ( nExtraSpace > pPortion->nFirstLineOffset )
4359*b1cdbd2cSJim Jagielski 				{
4360*b1cdbd2cSJim Jagielski 					// Absatz wird 'groesser':
4361*b1cdbd2cSJim Jagielski 					pPortion->nHeight += ( nExtraSpace - pPortion->nFirstLineOffset );
4362*b1cdbd2cSJim Jagielski 					pPortion->nFirstLineOffset = nExtraSpace;
4363*b1cdbd2cSJim Jagielski 				}
4364*b1cdbd2cSJim Jagielski 
4365*b1cdbd2cSJim Jagielski 				// nFirstLineOffset jetzt f(pNode) => jetzt f(pNode, pPrev) ermitteln:
4366*b1cdbd2cSJim Jagielski 				sal_uInt16 nPrevLower = GetYValue( rPrevULItem.GetLower() );
4367*b1cdbd2cSJim Jagielski 
4368*b1cdbd2cSJim Jagielski 				// Dieser PrevLower steckt noch in der Hoehe der PrevPortion...
4369*b1cdbd2cSJim Jagielski 				if ( nPrevLower > pPortion->nFirstLineOffset )
4370*b1cdbd2cSJim Jagielski 				{
4371*b1cdbd2cSJim Jagielski 					// Absatz wird 'kleiner':
4372*b1cdbd2cSJim Jagielski 					pPortion->nHeight -= pPortion->nFirstLineOffset;
4373*b1cdbd2cSJim Jagielski 					pPortion->nFirstLineOffset = 0;
4374*b1cdbd2cSJim Jagielski 				}
4375*b1cdbd2cSJim Jagielski 				else if ( nPrevLower )
4376*b1cdbd2cSJim Jagielski 				{
4377*b1cdbd2cSJim Jagielski 					// Absatz wird 'etwas kleiner':
4378*b1cdbd2cSJim Jagielski 					pPortion->nHeight -= nPrevLower;
4379*b1cdbd2cSJim Jagielski 					pPortion->nFirstLineOffset =
4380*b1cdbd2cSJim Jagielski                         pPortion->nFirstLineOffset - nPrevLower;
4381*b1cdbd2cSJim Jagielski 				}
4382*b1cdbd2cSJim Jagielski 
4383*b1cdbd2cSJim Jagielski 				// Finde ich zwar nicht so gut, aber Writer3-Feature:
4384*b1cdbd2cSJim Jagielski 				// Pruefen, ob Abstand durch LineSpacing > Lower:
4385*b1cdbd2cSJim Jagielski 				// Dieser Wert steckt nicht in der Hoehe der PrevPortion.
4386*b1cdbd2cSJim Jagielski 				if ( !pPrev->IsInvalid() )
4387*b1cdbd2cSJim Jagielski 				{
4388*b1cdbd2cSJim Jagielski 					nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPrev, rPrevLSItem ) );
4389*b1cdbd2cSJim Jagielski 					if ( nExtraSpace > nPrevLower )
4390*b1cdbd2cSJim Jagielski 					{
4391*b1cdbd2cSJim Jagielski 						sal_uInt16 nMoreLower = nExtraSpace - nPrevLower;
4392*b1cdbd2cSJim Jagielski 						// Absatz wird 'groesser', 'waechst' nach unten:
4393*b1cdbd2cSJim Jagielski 						if ( nMoreLower > pPortion->nFirstLineOffset )
4394*b1cdbd2cSJim Jagielski 						{
4395*b1cdbd2cSJim Jagielski 							pPortion->nHeight += ( nMoreLower - pPortion->nFirstLineOffset );
4396*b1cdbd2cSJim Jagielski 							pPortion->nFirstLineOffset = nMoreLower;
4397*b1cdbd2cSJim Jagielski 						}
4398*b1cdbd2cSJim Jagielski 					}
4399*b1cdbd2cSJim Jagielski 				}
4400*b1cdbd2cSJim Jagielski 			}
4401*b1cdbd2cSJim Jagielski 		}
4402*b1cdbd2cSJim Jagielski 	}
4403*b1cdbd2cSJim Jagielski }
4404*b1cdbd2cSJim Jagielski 
GetEditCursor(ParaPortion * pPortion,sal_uInt16 nIndex,sal_uInt16 nFlags)4405*b1cdbd2cSJim Jagielski Rectangle ImpEditEngine::GetEditCursor( ParaPortion* pPortion, sal_uInt16 nIndex, sal_uInt16 nFlags )
4406*b1cdbd2cSJim Jagielski {
4407*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPortion->IsVisible(), "Wozu GetEditCursor() bei einem unsichtbaren Absatz?" );
4408*b1cdbd2cSJim Jagielski 	DBG_ASSERT( IsFormatted() || GetTextRanger(), "GetEditCursor: Nicht formatiert" );
4409*b1cdbd2cSJim Jagielski 
4410*b1cdbd2cSJim Jagielski 	/*
4411*b1cdbd2cSJim Jagielski 	 GETCRSR_ENDOFLINE: Wenn hinter dem letzten Zeichen einer umgebrochenen Zeile,
4412*b1cdbd2cSJim Jagielski 	 am Ende der Zeile bleiben, nicht am Anfang der naechsten.
4413*b1cdbd2cSJim Jagielski 	 Zweck: 	- END => wirklich hinter das letzte Zeichen
4414*b1cdbd2cSJim Jagielski 				- Selektion....
4415*b1cdbd2cSJim Jagielski 	*/
4416*b1cdbd2cSJim Jagielski 
4417*b1cdbd2cSJim Jagielski 	long nY = pPortion->GetFirstLineOffset();
4418*b1cdbd2cSJim Jagielski 
4419*b1cdbd2cSJim Jagielski 	const SvxLineSpacingItem& rLSItem = (const SvxLineSpacingItem&)pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
4420*b1cdbd2cSJim Jagielski 	sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_FIX )
4421*b1cdbd2cSJim Jagielski 						? GetYValue( rLSItem.GetInterLineSpace() ) : 0;
4422*b1cdbd2cSJim Jagielski 
4423*b1cdbd2cSJim Jagielski 	sal_uInt16 nCurIndex = 0;
4424*b1cdbd2cSJim Jagielski 	DBG_ASSERT( pPortion->GetLines().Count(), "Leere ParaPortion in GetEditCursor!" );
4425*b1cdbd2cSJim Jagielski 	EditLine* pLine = 0;
4426*b1cdbd2cSJim Jagielski 	sal_Bool bEOL = ( nFlags & GETCRSR_ENDOFLINE ) ? sal_True : sal_False;
4427*b1cdbd2cSJim Jagielski 	for ( sal_uInt16 nLine = 0; nLine < pPortion->GetLines().Count(); nLine++ )
4428*b1cdbd2cSJim Jagielski 	{
4429*b1cdbd2cSJim Jagielski 		EditLine* pTmpLine = pPortion->GetLines().GetObject( nLine );
4430*b1cdbd2cSJim Jagielski 		if ( ( pTmpLine->GetStart() == nIndex ) || ( pTmpLine->IsIn( nIndex, bEOL ) ) )
4431*b1cdbd2cSJim Jagielski 		{
4432*b1cdbd2cSJim Jagielski 			pLine = pTmpLine;
4433*b1cdbd2cSJim Jagielski 			break;
4434*b1cdbd2cSJim Jagielski 		}
4435*b1cdbd2cSJim Jagielski 
4436*b1cdbd2cSJim Jagielski 		nCurIndex = nCurIndex + pTmpLine->GetLen();
4437*b1cdbd2cSJim Jagielski 		nY += pTmpLine->GetHeight();
4438*b1cdbd2cSJim Jagielski 		if ( !aStatus.IsOutliner() )
4439*b1cdbd2cSJim Jagielski 			nY += nSBL;
4440*b1cdbd2cSJim Jagielski 	}
4441*b1cdbd2cSJim Jagielski 	if ( !pLine )
4442*b1cdbd2cSJim Jagielski 	{
4443*b1cdbd2cSJim Jagielski 		// Cursor am Ende des Absatzes.
4444*b1cdbd2cSJim Jagielski 		DBG_ASSERT( nIndex == nCurIndex, "Index voll daneben in GetEditCursor!" );
4445*b1cdbd2cSJim Jagielski 
4446*b1cdbd2cSJim Jagielski 		pLine = pPortion->GetLines().GetObject( pPortion->GetLines().Count()-1 );
4447*b1cdbd2cSJim Jagielski 		nY -= pLine->GetHeight();
4448*b1cdbd2cSJim Jagielski 		if ( !aStatus.IsOutliner() )
4449*b1cdbd2cSJim Jagielski 			nY -= nSBL;
4450*b1cdbd2cSJim Jagielski 		nCurIndex = nCurIndex -  pLine->GetLen();
4451*b1cdbd2cSJim Jagielski 	}
4452*b1cdbd2cSJim Jagielski 
4453*b1cdbd2cSJim Jagielski 	Rectangle aEditCursor;
4454*b1cdbd2cSJim Jagielski 
4455*b1cdbd2cSJim Jagielski 	aEditCursor.Top() = nY;
4456*b1cdbd2cSJim Jagielski 	nY += pLine->GetHeight();
4457*b1cdbd2cSJim Jagielski 	aEditCursor.Bottom() = nY-1;
4458*b1cdbd2cSJim Jagielski 
4459*b1cdbd2cSJim Jagielski 	// innerhalb der Zeile suchen...
4460*b1cdbd2cSJim Jagielski     long nX;
4461*b1cdbd2cSJim Jagielski 
4462*b1cdbd2cSJim Jagielski     if ( ( nIndex == pLine->GetStart() ) && ( nFlags & GETCRSR_STARTOFLINE ) )
4463*b1cdbd2cSJim Jagielski     {
4464*b1cdbd2cSJim Jagielski         Range aXRange = GetLineXPosStartEnd( pPortion, pLine );
4465*b1cdbd2cSJim Jagielski         nX = !IsRightToLeft( GetEditDoc().GetPos( pPortion->GetNode() ) ) ? aXRange.Min() : aXRange.Max();
4466*b1cdbd2cSJim Jagielski     }
4467*b1cdbd2cSJim Jagielski     else if ( ( nIndex == pLine->GetEnd() ) && ( nFlags & GETCRSR_ENDOFLINE ) )
4468*b1cdbd2cSJim Jagielski     {
4469*b1cdbd2cSJim Jagielski         Range aXRange = GetLineXPosStartEnd( pPortion, pLine );
4470*b1cdbd2cSJim Jagielski         nX = !IsRightToLeft( GetEditDoc().GetPos( pPortion->GetNode() ) ) ? aXRange.Max() : aXRange.Min();
4471*b1cdbd2cSJim Jagielski     }
4472*b1cdbd2cSJim Jagielski     else
4473*b1cdbd2cSJim Jagielski     {
4474*b1cdbd2cSJim Jagielski         nX = GetXPos( pPortion, pLine, nIndex, ( nFlags & GETCRSR_PREFERPORTIONSTART ) ? sal_True : sal_False );
4475*b1cdbd2cSJim Jagielski     }
4476*b1cdbd2cSJim Jagielski 
4477*b1cdbd2cSJim Jagielski     aEditCursor.Left() = aEditCursor.Right() = nX;
4478*b1cdbd2cSJim Jagielski 
4479*b1cdbd2cSJim Jagielski 	if ( nFlags & GETCRSR_TXTONLY )
4480*b1cdbd2cSJim Jagielski 		aEditCursor.Top() = aEditCursor.Bottom() - pLine->GetTxtHeight() + 1;
4481*b1cdbd2cSJim Jagielski 	else
4482*b1cdbd2cSJim Jagielski 		aEditCursor.Top() = aEditCursor.Bottom() - Min( pLine->GetTxtHeight(), pLine->GetHeight() ) + 1;
4483*b1cdbd2cSJim Jagielski 
4484*b1cdbd2cSJim Jagielski 	return aEditCursor;
4485*b1cdbd2cSJim Jagielski }
4486*b1cdbd2cSJim Jagielski 
SetValidPaperSize(const Size & rNewSz)4487*b1cdbd2cSJim Jagielski void ImpEditEngine::SetValidPaperSize( const Size& rNewSz )
4488*b1cdbd2cSJim Jagielski {
4489*b1cdbd2cSJim Jagielski 	aPaperSize = rNewSz;
4490*b1cdbd2cSJim Jagielski 
4491*b1cdbd2cSJim Jagielski 	long nMinWidth = aStatus.AutoPageWidth() ? aMinAutoPaperSize.Width() : 0;
4492*b1cdbd2cSJim Jagielski 	long nMaxWidth = aStatus.AutoPageWidth() ? aMaxAutoPaperSize.Width() : 0x7FFFFFFF;
4493*b1cdbd2cSJim Jagielski 	long nMinHeight = aStatus.AutoPageHeight() ? aMinAutoPaperSize.Height() : 0;
4494*b1cdbd2cSJim Jagielski 	long nMaxHeight = aStatus.AutoPageHeight() ? aMaxAutoPaperSize.Height() : 0x7FFFFFFF;
4495*b1cdbd2cSJim Jagielski 
4496*b1cdbd2cSJim Jagielski 	// Minimale/Maximale Breite:
4497*b1cdbd2cSJim Jagielski 	if ( aPaperSize.Width() < nMinWidth )
4498*b1cdbd2cSJim Jagielski 		aPaperSize.Width() = nMinWidth;
4499*b1cdbd2cSJim Jagielski 	else if ( aPaperSize.Width() > nMaxWidth )
4500*b1cdbd2cSJim Jagielski 		aPaperSize.Width() = nMaxWidth;
4501*b1cdbd2cSJim Jagielski 
4502*b1cdbd2cSJim Jagielski 	// Minimale/Maximale Hoehe:
4503*b1cdbd2cSJim Jagielski 	if ( aPaperSize.Height() < nMinHeight )
4504*b1cdbd2cSJim Jagielski 		aPaperSize.Height() = nMinHeight;
4505*b1cdbd2cSJim Jagielski 	else if ( aPaperSize.Height() > nMaxHeight )
4506*b1cdbd2cSJim Jagielski 		aPaperSize.Height() = nMaxHeight;
4507*b1cdbd2cSJim Jagielski }
4508*b1cdbd2cSJim Jagielski 
IndentBlock(EditView * pEditView,sal_Bool bRight)4509*b1cdbd2cSJim Jagielski void ImpEditEngine::IndentBlock( EditView* pEditView, sal_Bool bRight )
4510*b1cdbd2cSJim Jagielski {
4511*b1cdbd2cSJim Jagielski 	ESelection aESel( CreateESel( pEditView->pImpEditView->GetEditSelection() ) );
4512*b1cdbd2cSJim Jagielski 	aESel.Adjust();
4513*b1cdbd2cSJim Jagielski 
4514*b1cdbd2cSJim Jagielski 	// Nur wenn mehrere selektierte Absaetze...
4515*b1cdbd2cSJim Jagielski 	if ( aESel.nEndPara > aESel.nStartPara )
4516*b1cdbd2cSJim Jagielski 	{
4517*b1cdbd2cSJim Jagielski 		ESelection aNewSel = aESel;
4518*b1cdbd2cSJim Jagielski 		aNewSel.nStartPos = 0;
4519*b1cdbd2cSJim Jagielski 		aNewSel.nEndPos = 0xFFFF;
4520*b1cdbd2cSJim Jagielski 
4521*b1cdbd2cSJim Jagielski 		if ( aESel.nEndPos == 0 )
4522*b1cdbd2cSJim Jagielski 		{
4523*b1cdbd2cSJim Jagielski 			aESel.nEndPara--;		// dann diesen Absatz nicht...
4524*b1cdbd2cSJim Jagielski 			aNewSel.nEndPos = 0;
4525*b1cdbd2cSJim Jagielski 		}
4526*b1cdbd2cSJim Jagielski 
4527*b1cdbd2cSJim Jagielski 		pEditView->pImpEditView->DrawSelection();
4528*b1cdbd2cSJim Jagielski 		pEditView->pImpEditView->SetEditSelection(
4529*b1cdbd2cSJim Jagielski 						pEditView->pImpEditView->GetEditSelection().Max() );
4530*b1cdbd2cSJim Jagielski 		UndoActionStart( bRight ? EDITUNDO_INDENTBLOCK : EDITUNDO_UNINDENTBLOCK );
4531*b1cdbd2cSJim Jagielski 
4532*b1cdbd2cSJim Jagielski 		for ( sal_uInt16 nPara = aESel.nStartPara; nPara <= aESel.nEndPara; nPara++ )
4533*b1cdbd2cSJim Jagielski 		{
4534*b1cdbd2cSJim Jagielski 			ContentNode* pNode = GetEditDoc().GetObject( nPara );
4535*b1cdbd2cSJim Jagielski 			if ( bRight )
4536*b1cdbd2cSJim Jagielski 			{
4537*b1cdbd2cSJim Jagielski 				// Tabs hinzufuegen
4538*b1cdbd2cSJim Jagielski 				EditPaM aPaM( pNode, 0 );
4539*b1cdbd2cSJim Jagielski 				InsertTab( aPaM );
4540*b1cdbd2cSJim Jagielski 			}
4541*b1cdbd2cSJim Jagielski 			else
4542*b1cdbd2cSJim Jagielski 			{
4543*b1cdbd2cSJim Jagielski 				// Tabs entfernen
4544*b1cdbd2cSJim Jagielski 				EditCharAttrib* pFeature = pNode->GetCharAttribs().FindFeature( 0 );
4545*b1cdbd2cSJim Jagielski 				if ( pFeature && ( pFeature->GetStart() == 0 ) &&
4546*b1cdbd2cSJim Jagielski 				   ( pFeature->GetItem()->Which() == EE_FEATURE_TAB ) )
4547*b1cdbd2cSJim Jagielski 				{
4548*b1cdbd2cSJim Jagielski 					EditPaM aStartPaM( pNode, 0 );
4549*b1cdbd2cSJim Jagielski 					EditPaM aEndPaM( pNode, 1 );
4550*b1cdbd2cSJim Jagielski 					ImpDeleteSelection( EditSelection( aStartPaM, aEndPaM ) );
4551*b1cdbd2cSJim Jagielski 				}
4552*b1cdbd2cSJim Jagielski 			}
4553*b1cdbd2cSJim Jagielski 		}
4554*b1cdbd2cSJim Jagielski 
4555*b1cdbd2cSJim Jagielski 		UndoActionEnd( bRight ? EDITUNDO_INDENTBLOCK : EDITUNDO_UNINDENTBLOCK );
4556*b1cdbd2cSJim Jagielski 		UpdateSelections();
4557*b1cdbd2cSJim Jagielski 		FormatAndUpdate( pEditView );
4558*b1cdbd2cSJim Jagielski 
4559*b1cdbd2cSJim Jagielski 		ContentNode* pLastNode = GetEditDoc().GetObject( aNewSel.nEndPara );
4560*b1cdbd2cSJim Jagielski 		if ( pLastNode->Len() < aNewSel.nEndPos )
4561*b1cdbd2cSJim Jagielski 			aNewSel.nEndPos = pLastNode->Len();
4562*b1cdbd2cSJim Jagielski 		pEditView->pImpEditView->SetEditSelection( CreateSel( aNewSel ) );
4563*b1cdbd2cSJim Jagielski 		pEditView->pImpEditView->DrawSelection();
4564*b1cdbd2cSJim Jagielski 		pEditView->pImpEditView->ShowCursor( sal_False, sal_True );
4565*b1cdbd2cSJim Jagielski 	}
4566*b1cdbd2cSJim Jagielski }
4567*b1cdbd2cSJim Jagielski 
GetForbiddenCharsTable(sal_Bool bGetInternal) const4568*b1cdbd2cSJim Jagielski vos::ORef<SvxForbiddenCharactersTable> ImpEditEngine::GetForbiddenCharsTable( sal_Bool bGetInternal ) const
4569*b1cdbd2cSJim Jagielski {
4570*b1cdbd2cSJim Jagielski 	vos::ORef<SvxForbiddenCharactersTable> xF = xForbiddenCharsTable;
4571*b1cdbd2cSJim Jagielski 	if ( !xF.isValid() && bGetInternal )
4572*b1cdbd2cSJim Jagielski 		xF = EE_DLL()->GetGlobalData()->GetForbiddenCharsTable();
4573*b1cdbd2cSJim Jagielski 	return xF;
4574*b1cdbd2cSJim Jagielski }
4575*b1cdbd2cSJim Jagielski 
SetForbiddenCharsTable(vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars)4576*b1cdbd2cSJim Jagielski void ImpEditEngine::SetForbiddenCharsTable( vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars )
4577*b1cdbd2cSJim Jagielski {
4578*b1cdbd2cSJim Jagielski 	EE_DLL()->GetGlobalData()->SetForbiddenCharsTable( xForbiddenChars );
4579*b1cdbd2cSJim Jagielski }
4580*b1cdbd2cSJim Jagielski 
GetColorConfig()4581*b1cdbd2cSJim Jagielski svtools::ColorConfig& ImpEditEngine::GetColorConfig()
4582*b1cdbd2cSJim Jagielski {
4583*b1cdbd2cSJim Jagielski     if ( !pColorConfig )
4584*b1cdbd2cSJim Jagielski         pColorConfig = new svtools::ColorConfig;
4585*b1cdbd2cSJim Jagielski 
4586*b1cdbd2cSJim Jagielski     return *pColorConfig;
4587*b1cdbd2cSJim Jagielski }
4588*b1cdbd2cSJim Jagielski 
IsVisualCursorTravelingEnabled()4589*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::IsVisualCursorTravelingEnabled()
4590*b1cdbd2cSJim Jagielski {
4591*b1cdbd2cSJim Jagielski     sal_Bool bVisualCursorTravaling = sal_False;
4592*b1cdbd2cSJim Jagielski 
4593*b1cdbd2cSJim Jagielski     if( !pCTLOptions )
4594*b1cdbd2cSJim Jagielski         pCTLOptions = new SvtCTLOptions;
4595*b1cdbd2cSJim Jagielski 
4596*b1cdbd2cSJim Jagielski     if ( pCTLOptions->IsCTLFontEnabled() && ( pCTLOptions->GetCTLCursorMovement() == SvtCTLOptions::MOVEMENT_VISUAL ) )
4597*b1cdbd2cSJim Jagielski     {
4598*b1cdbd2cSJim Jagielski         bVisualCursorTravaling = sal_True;
4599*b1cdbd2cSJim Jagielski     }
4600*b1cdbd2cSJim Jagielski 
4601*b1cdbd2cSJim Jagielski     return bVisualCursorTravaling;
4602*b1cdbd2cSJim Jagielski 
4603*b1cdbd2cSJim Jagielski }
4604*b1cdbd2cSJim Jagielski 
DoVisualCursorTraveling(const ContentNode *)4605*b1cdbd2cSJim Jagielski sal_Bool ImpEditEngine::DoVisualCursorTraveling( const ContentNode* )
4606*b1cdbd2cSJim Jagielski {
4607*b1cdbd2cSJim Jagielski     // Don't check if it's necessary, because we also need it when leaving the paragraph
4608*b1cdbd2cSJim Jagielski     return IsVisualCursorTravelingEnabled();
4609*b1cdbd2cSJim Jagielski /*
4610*b1cdbd2cSJim Jagielski     sal_Bool bDoVisualCursorTraveling = sal_False;
4611*b1cdbd2cSJim Jagielski 
4612*b1cdbd2cSJim Jagielski     if ( IsVisualCursorTravelingEnabled() && pNode->Len() )
4613*b1cdbd2cSJim Jagielski     {
4614*b1cdbd2cSJim Jagielski         // Only necessary when RTL text in LTR para or LTR text in RTL para
4615*b1cdbd2cSJim Jagielski         bDoVisualCursorTraveling = HasDifferentRTLLevels( pNode );
4616*b1cdbd2cSJim Jagielski     }
4617*b1cdbd2cSJim Jagielski 
4618*b1cdbd2cSJim Jagielski     return bDoVisualCursorTraveling;
4619*b1cdbd2cSJim Jagielski */
4620*b1cdbd2cSJim Jagielski }
4621*b1cdbd2cSJim Jagielski 
4622*b1cdbd2cSJim Jagielski 
CallNotify(EENotify & rNotify)4623*b1cdbd2cSJim Jagielski void ImpEditEngine::CallNotify( EENotify& rNotify )
4624*b1cdbd2cSJim Jagielski {
4625*b1cdbd2cSJim Jagielski     if ( !nBlockNotifications )
4626*b1cdbd2cSJim Jagielski     {
4627*b1cdbd2cSJim Jagielski         GetNotifyHdl().Call( &rNotify );
4628*b1cdbd2cSJim Jagielski     }
4629*b1cdbd2cSJim Jagielski     else
4630*b1cdbd2cSJim Jagielski     {
4631*b1cdbd2cSJim Jagielski         EENotify* pNewNotify = new EENotify( rNotify );
4632*b1cdbd2cSJim Jagielski         aNotifyCache.Insert( pNewNotify, aNotifyCache.Count() );
4633*b1cdbd2cSJim Jagielski     }
4634*b1cdbd2cSJim Jagielski }
4635*b1cdbd2cSJim Jagielski 
EnterBlockNotifications()4636*b1cdbd2cSJim Jagielski void ImpEditEngine::EnterBlockNotifications()
4637*b1cdbd2cSJim Jagielski {
4638*b1cdbd2cSJim Jagielski     if( !nBlockNotifications )
4639*b1cdbd2cSJim Jagielski     {
4640*b1cdbd2cSJim Jagielski         // #109864# Send out START notification immediately, to allow
4641*b1cdbd2cSJim Jagielski         // external, non-queued events to be captured as well from
4642*b1cdbd2cSJim Jagielski         // client side
4643*b1cdbd2cSJim Jagielski         EENotify aNotify( EE_NOTIFY_BLOCKNOTIFICATION_START );
4644*b1cdbd2cSJim Jagielski         aNotify.pEditEngine = GetEditEnginePtr();
4645*b1cdbd2cSJim Jagielski         GetNotifyHdl().Call( &aNotify );
4646*b1cdbd2cSJim Jagielski     }
4647*b1cdbd2cSJim Jagielski 
4648*b1cdbd2cSJim Jagielski     nBlockNotifications++;
4649*b1cdbd2cSJim Jagielski }
4650*b1cdbd2cSJim Jagielski 
LeaveBlockNotifications()4651*b1cdbd2cSJim Jagielski void ImpEditEngine::LeaveBlockNotifications()
4652*b1cdbd2cSJim Jagielski {
4653*b1cdbd2cSJim Jagielski     DBG_ASSERT( nBlockNotifications, "LeaveBlockNotifications - Why?" );
4654*b1cdbd2cSJim Jagielski 
4655*b1cdbd2cSJim Jagielski     nBlockNotifications--;
4656*b1cdbd2cSJim Jagielski     if ( !nBlockNotifications )
4657*b1cdbd2cSJim Jagielski     {
4658*b1cdbd2cSJim Jagielski         // Call blocked notify events...
4659*b1cdbd2cSJim Jagielski         while ( aNotifyCache.Count() )
4660*b1cdbd2cSJim Jagielski         {
4661*b1cdbd2cSJim Jagielski             EENotify* pNotify = aNotifyCache[0];
4662*b1cdbd2cSJim Jagielski             // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler...
4663*b1cdbd2cSJim Jagielski             aNotifyCache.Remove( 0 );
4664*b1cdbd2cSJim Jagielski             GetNotifyHdl().Call( pNotify );
4665*b1cdbd2cSJim Jagielski             delete pNotify;
4666*b1cdbd2cSJim Jagielski         }
4667*b1cdbd2cSJim Jagielski 
4668*b1cdbd2cSJim Jagielski         EENotify aNotify( EE_NOTIFY_BLOCKNOTIFICATION_END );
4669*b1cdbd2cSJim Jagielski         aNotify.pEditEngine = GetEditEnginePtr();
4670*b1cdbd2cSJim Jagielski         GetNotifyHdl().Call( &aNotify );
4671*b1cdbd2cSJim Jagielski     }
4672*b1cdbd2cSJim Jagielski }
4673*b1cdbd2cSJim Jagielski 
IMPL_LINK(ImpEditEngine,DocModified,void *,EMPTYARG)4674*b1cdbd2cSJim Jagielski IMPL_LINK( ImpEditEngine, DocModified, void*, EMPTYARG )
4675*b1cdbd2cSJim Jagielski {
4676*b1cdbd2cSJim Jagielski     aModifyHdl.Call( NULL /*GetEditEnginePtr()*/ ); // NULL, because also used for Outliner
4677*b1cdbd2cSJim Jagielski     return 0;
4678*b1cdbd2cSJim Jagielski }
4679