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