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