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