1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 #include <svtools/textview.hxx>
27 #include <svtools/texteng.hxx>
28 #include <textdoc.hxx>
29 #include <svtools/textdata.hxx>
30 #include <textdat2.hxx>
31
32 #include <svl/undo.hxx>
33 #include <vcl/cursor.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/sound.hxx>
37 #include <tools/stream.hxx>
38
39 #include <sot/formats.hxx>
40 #include <svl/urlbmk.hxx>
41
42 #ifndef _COM_SUN_STAR_TEXT_XBREAKITERATOR_HPP_
43 #include <com/sun/star/i18n/XBreakIterator.hpp>
44 #endif
45
46 #ifndef _COM_SUN_STAR_TEXT_CHARACTERITERATORMODE_HPP_
47 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
48 #endif
49
50 #ifndef _COM_SUN_STAR_TEXT_WORDTYPE_HPP_
51 #include <com/sun/star/i18n/WordType.hpp>
52 #endif
53 #include <cppuhelper/weak.hxx>
54 #include <vcl/unohelp.hxx>
55 #include <com/sun/star/datatransfer/XTransferable.hpp>
56 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
57 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
58 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59
60 #ifndef _COM_SUN_STAR_DATATRANSFER_DND_DNDCONSTANS_HPP_
61 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
62 #endif
63 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
64 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
65
66 #include <vcl/edit.hxx>
67
68
69 #include <sot/exchange.hxx>
70 #include <sot/formats.hxx>
71
72 #include <vos/mutex.hxx>
73
74
75 using namespace ::com::sun::star;
76
77 class TETextDataObject : public ::com::sun::star::datatransfer::XTransferable,
78 public ::cppu::OWeakObject
79
80 {
81 private:
82 String maText;
83 SvMemoryStream maHTMLStream;
84
85 public:
86 TETextDataObject( const String& rText );
87 ~TETextDataObject();
88
GetText()89 String& GetText() { return maText; }
GetHTMLStream()90 SvMemoryStream& GetHTMLStream() { return maHTMLStream; }
91
92 // ::com::sun::star::uno::XInterface
93 ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException);
acquire()94 void SAL_CALL acquire() throw() { OWeakObject::acquire(); }
release()95 void SAL_CALL release() throw() { OWeakObject::release(); }
96
97 // ::com::sun::star::datatransfer::XTransferable
98 ::com::sun::star::uno::Any SAL_CALL getTransferData( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) throw(::com::sun::star::datatransfer::UnsupportedFlavorException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
99 ::com::sun::star::uno::Sequence< ::com::sun::star::datatransfer::DataFlavor > SAL_CALL getTransferDataFlavors( ) throw(::com::sun::star::uno::RuntimeException);
100 sal_Bool SAL_CALL isDataFlavorSupported( const ::com::sun::star::datatransfer::DataFlavor& aFlavor ) throw(::com::sun::star::uno::RuntimeException);
101 };
102
TETextDataObject(const String & rText)103 TETextDataObject::TETextDataObject( const String& rText ) : maText( rText )
104 {
105 }
106
~TETextDataObject()107 TETextDataObject::~TETextDataObject()
108 {
109 }
110
111 // uno::XInterface
queryInterface(const uno::Type & rType)112 uno::Any TETextDataObject::queryInterface( const uno::Type & rType ) throw(uno::RuntimeException)
113 {
114 uno::Any aRet = ::cppu::queryInterface( rType, SAL_STATIC_CAST( datatransfer::XTransferable*, this ) );
115 return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
116 }
117
118 // datatransfer::XTransferable
getTransferData(const datatransfer::DataFlavor & rFlavor)119 uno::Any TETextDataObject::getTransferData( const datatransfer::DataFlavor& rFlavor ) throw(datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException)
120 {
121 uno::Any aAny;
122
123 sal_uLong nT = SotExchange::GetFormat( rFlavor );
124 if ( nT == SOT_FORMAT_STRING )
125 {
126 aAny <<= (::rtl::OUString)GetText();
127 }
128 else if ( nT == SOT_FORMATSTR_ID_HTML )
129 {
130 GetHTMLStream().Seek( STREAM_SEEK_TO_END );
131 sal_uLong nLen = GetHTMLStream().Tell();
132 GetHTMLStream().Seek(0);
133
134 uno::Sequence< sal_Int8 > aSeq( nLen );
135 memcpy( aSeq.getArray(), GetHTMLStream().GetData(), nLen );
136 aAny <<= aSeq;
137 }
138 else
139 {
140 throw datatransfer::UnsupportedFlavorException();
141 }
142 return aAny;
143 }
144
getTransferDataFlavors()145 uno::Sequence< datatransfer::DataFlavor > TETextDataObject::getTransferDataFlavors( ) throw(uno::RuntimeException)
146 {
147 GetHTMLStream().Seek( STREAM_SEEK_TO_END );
148 sal_Bool bHTML = GetHTMLStream().Tell() > 0;
149 uno::Sequence< datatransfer::DataFlavor > aDataFlavors( bHTML ? 2 : 1 );
150 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aDataFlavors.getArray()[0] );
151 if ( bHTML )
152 SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_HTML, aDataFlavors.getArray()[1] );
153 return aDataFlavors;
154 }
155
isDataFlavorSupported(const datatransfer::DataFlavor & rFlavor)156 sal_Bool TETextDataObject::isDataFlavorSupported( const datatransfer::DataFlavor& rFlavor ) throw(uno::RuntimeException)
157 {
158 sal_uLong nT = SotExchange::GetFormat( rFlavor );
159 return ( nT == SOT_FORMAT_STRING );
160 }
161
162 /*-- 24.06.2004 13:54:36---------------------------------------------------
163
164 -----------------------------------------------------------------------*/
165 struct ImpTextView
166 {
167 TextEngine* mpTextEngine;
168
169 Window* mpWindow;
170 TextSelection maSelection;
171 Point maStartDocPos;
172 // TextPaM maMBDownPaM;
173
174 Cursor* mpCursor;
175
176 TextDDInfo* mpDDInfo;
177
178 VirtualDevice* mpVirtDev;
179
180 SelectionEngine* mpSelEngine;
181 TextSelFunctionSet* mpSelFuncSet;
182
183 ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDragSourceListener > mxDnDListener;
184
185 sal_uInt16 mnTravelXPos;
186
187 sal_Bool mbAutoScroll : 1;
188 sal_Bool mbInsertMode : 1;
189 sal_Bool mbReadOnly : 1;
190 sal_Bool mbPaintSelection : 1;
191 sal_Bool mbAutoIndent : 1;
192 sal_Bool mbHighlightSelection : 1;
193 sal_Bool mbCursorEnabled : 1;
194 sal_Bool mbClickedInSelection : 1;
195 sal_Bool mbSupportProtectAttribute : 1;
196 bool mbCursorAtEndOfLine;
197 };
198
199 // -------------------------------------------------------------------------
200 // (+) class TextView
201 // -------------------------------------------------------------------------
TextView(TextEngine * pEng,Window * pWindow)202 TextView::TextView( TextEngine* pEng, Window* pWindow ) :
203 mpImpl(new ImpTextView)
204 {
205 pWindow->EnableRTL( sal_False );
206
207 mpImpl->mpWindow = pWindow;
208 mpImpl->mpTextEngine = pEng;
209 mpImpl->mpVirtDev = NULL;
210
211 mpImpl->mbPaintSelection = sal_True;
212 mpImpl->mbAutoScroll = sal_True;
213 mpImpl->mbInsertMode = sal_True;
214 mpImpl->mbReadOnly = sal_False;
215 mpImpl->mbHighlightSelection = sal_False;
216 mpImpl->mbAutoIndent = sal_False;
217 mpImpl->mbCursorEnabled = sal_True;
218 mpImpl->mbClickedInSelection = sal_False;
219 mpImpl->mbSupportProtectAttribute = sal_False;
220 mpImpl->mbCursorAtEndOfLine = false;
221 // mbInSelection = sal_False;
222
223 mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
224
225 mpImpl->mpSelFuncSet = new TextSelFunctionSet( this );
226 mpImpl->mpSelEngine = new SelectionEngine( mpImpl->mpWindow, mpImpl->mpSelFuncSet );
227 mpImpl->mpSelEngine->SetSelectionMode( RANGE_SELECTION );
228 mpImpl->mpSelEngine->EnableDrag( sal_True );
229
230 mpImpl->mpCursor = new Cursor;
231 mpImpl->mpCursor->Show();
232 pWindow->SetCursor( mpImpl->mpCursor );
233 pWindow->SetInputContext( InputContext( pEng->GetFont(), INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT ) );
234
235 if ( pWindow->GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_INVERT )
236 mpImpl->mbHighlightSelection = sal_True;
237
238 pWindow->SetLineColor();
239
240 mpImpl->mpDDInfo = NULL;
241
242 if ( pWindow->GetDragGestureRecognizer().is() )
243 {
244 vcl::unohelper::DragAndDropWrapper* pDnDWrapper = new vcl::unohelper::DragAndDropWrapper( this );
245 mpImpl->mxDnDListener = pDnDWrapper;
246
247 uno::Reference< datatransfer::dnd::XDragGestureListener> xDGL( mpImpl->mxDnDListener, uno::UNO_QUERY );
248 pWindow->GetDragGestureRecognizer()->addDragGestureListener( xDGL );
249 uno::Reference< datatransfer::dnd::XDropTargetListener> xDTL( xDGL, uno::UNO_QUERY );
250 pWindow->GetDropTarget()->addDropTargetListener( xDTL );
251 pWindow->GetDropTarget()->setActive( sal_True );
252 pWindow->GetDropTarget()->setDefaultActions( datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE );
253 }
254 }
255
~TextView()256 TextView::~TextView()
257 {
258 delete mpImpl->mpSelEngine;
259 delete mpImpl->mpSelFuncSet;
260 delete mpImpl->mpVirtDev;
261
262 if ( mpImpl->mpWindow->GetCursor() == mpImpl->mpCursor )
263 mpImpl->mpWindow->SetCursor( 0 );
264 delete mpImpl->mpCursor;
265 delete mpImpl->mpDDInfo;
266 delete mpImpl;
267 }
268
Invalidate()269 void TextView::Invalidate()
270 {
271 mpImpl->mpWindow->Invalidate();
272 }
273
SetSelection(const TextSelection & rTextSel,sal_Bool bGotoCursor)274 void TextView::SetSelection( const TextSelection& rTextSel, sal_Bool bGotoCursor )
275 {
276 // Falls jemand gerade ein leeres Attribut hinterlassen hat,
277 // und dann der Outliner die Selektion manipulitert:
278 if ( !mpImpl->maSelection.HasRange() )
279 mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() );
280
281 // Wenn nach einem KeyInput die Selection manipuliert wird:
282 mpImpl->mpTextEngine->CheckIdleFormatter();
283
284 HideSelection();
285 TextSelection aNewSel( rTextSel );
286 mpImpl->mpTextEngine->ValidateSelection( aNewSel );
287 ImpSetSelection( aNewSel );
288 ShowSelection();
289 ShowCursor( bGotoCursor );
290 }
291
SetSelection(const TextSelection & rTextSel)292 void TextView::SetSelection( const TextSelection& rTextSel )
293 {
294 SetSelection( rTextSel, mpImpl->mbAutoScroll );
295 }
296
GetSelection() const297 const TextSelection& TextView::GetSelection() const
298 {
299 return mpImpl->maSelection;
300 }
GetSelection()301 TextSelection& TextView::GetSelection()
302 {
303 return mpImpl->maSelection;
304 }
305
DeleteSelected()306 void TextView::DeleteSelected()
307 {
308 // HideSelection();
309
310 mpImpl->mpTextEngine->UndoActionStart();
311 TextPaM aPaM = mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection );
312 mpImpl->mpTextEngine->UndoActionEnd();
313
314 ImpSetSelection( aPaM );
315 mpImpl->mpTextEngine->FormatAndUpdate( this );
316 ShowCursor();
317 }
318
ImpPaint(OutputDevice * pOut,const Point & rStartPos,Rectangle const * pPaintArea,TextSelection const * pPaintRange,TextSelection const * pSelection)319 void TextView::ImpPaint( OutputDevice* pOut, const Point& rStartPos, Rectangle const* pPaintArea, TextSelection const* pPaintRange, TextSelection const* pSelection )
320 {
321 if ( !mpImpl->mbPaintSelection )
322 pSelection = NULL;
323 else
324 {
325 // Richtige Hintergrundfarbe einstellen.
326 // Ich bekomme leider nicht mit, ob sich diese inzwischen geaendert hat.
327 Font aFont = mpImpl->mpTextEngine->GetFont();
328 Color aColor = pOut->GetBackground().GetColor();
329 aColor.SetTransparency( 0 );
330 if ( aColor != aFont.GetFillColor() )
331 {
332 if( aFont.IsTransparent() )
333 aColor = Color( COL_TRANSPARENT );
334 aFont.SetFillColor( aColor );
335 mpImpl->mpTextEngine->maFont = aFont;
336 }
337 }
338
339 mpImpl->mpTextEngine->ImpPaint( pOut, rStartPos, pPaintArea, pPaintRange, pSelection );
340 }
341
Paint(const Rectangle & rRect)342 void TextView::Paint( const Rectangle& rRect )
343 {
344 ImpPaint( rRect, sal_False );
345 }
346
ImpPaint(const Rectangle & rRect,sal_Bool bUseVirtDev)347 void TextView::ImpPaint( const Rectangle& rRect, sal_Bool bUseVirtDev )
348 {
349 if ( !mpImpl->mpTextEngine->GetUpdateMode() || mpImpl->mpTextEngine->IsInUndo() )
350 return;
351
352 TextSelection *pDrawSelection = NULL;
353 if ( !mpImpl->mbHighlightSelection && mpImpl->maSelection.HasRange() )
354 pDrawSelection = &mpImpl->maSelection;
355
356 if ( bUseVirtDev )
357 {
358 VirtualDevice* pVDev = GetVirtualDevice();
359
360 const Color& rBackgroundColor = mpImpl->mpWindow->GetBackground().GetColor();
361 if ( pVDev->GetFillColor() != rBackgroundColor )
362 pVDev->SetFillColor( rBackgroundColor );
363 if ( pVDev->GetBackground().GetColor() != rBackgroundColor )
364 pVDev->SetBackground( rBackgroundColor );
365
366 sal_Bool bVDevValid = sal_True;
367 Size aOutSz( pVDev->GetOutputSizePixel() );
368 if ( ( aOutSz.Width() < rRect.GetWidth() ) ||
369 ( aOutSz.Height() < rRect.GetHeight() ) )
370 {
371 bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() );
372 }
373 else
374 {
375 // Das VirtDev kann bei einem Resize sehr gross werden =>
376 // irgendwann mal kleiner machen!
377 if ( ( aOutSz.Height() > ( rRect.GetHeight() + 20 ) ) ||
378 ( aOutSz.Width() > ( rRect.GetWidth() + 20 ) ) )
379 {
380 bVDevValid = pVDev->SetOutputSizePixel( rRect.GetSize() );
381 }
382 else
383 {
384 pVDev->Erase();
385 }
386 }
387 if ( !bVDevValid )
388 {
389 ImpPaint( rRect, sal_False /* ohne VDev */ );
390 return;
391 }
392
393 Rectangle aTmpRec( Point( 0, 0 ), rRect.GetSize() );
394
395 Point aDocPos( mpImpl->maStartDocPos.X(), mpImpl->maStartDocPos.Y() + rRect.Top() );
396 Point aStartPos = ImpGetOutputStartPos( aDocPos );
397 ImpPaint( pVDev, aStartPos, &aTmpRec, NULL, pDrawSelection );
398 mpImpl->mpWindow->DrawOutDev( rRect.TopLeft(), rRect.GetSize(),
399 Point(0,0), rRect.GetSize(), *pVDev );
400 // ShowSelection();
401 if ( mpImpl->mbHighlightSelection )
402 ImpHighlight( mpImpl->maSelection );
403 }
404 else
405 {
406 Point aStartPos = ImpGetOutputStartPos( mpImpl->maStartDocPos );
407 ImpPaint( mpImpl->mpWindow, aStartPos, &rRect, NULL, pDrawSelection );
408
409 // ShowSelection();
410 if ( mpImpl->mbHighlightSelection )
411 ImpHighlight( mpImpl->maSelection );
412 }
413 }
414
ImpHighlight(const TextSelection & rSel)415 void TextView::ImpHighlight( const TextSelection& rSel )
416 {
417 TextSelection aSel( rSel );
418 aSel.Justify();
419 if ( aSel.HasRange() && !mpImpl->mpTextEngine->IsInUndo() && mpImpl->mpTextEngine->GetUpdateMode() )
420 {
421 mpImpl->mpCursor->Hide();
422
423 DBG_ASSERT( !mpImpl->mpTextEngine->mpIdleFormatter->IsActive(), "ImpHighlight: Not formatted!" );
424
425 Rectangle aVisArea( mpImpl->maStartDocPos, mpImpl->mpWindow->GetOutputSizePixel() );
426 long nY = 0;
427 sal_uLong nStartPara = aSel.GetStart().GetPara();
428 sal_uLong nEndPara = aSel.GetEnd().GetPara();
429 for ( sal_uLong nPara = 0; nPara <= nEndPara; nPara++ )
430 {
431 long nParaHeight = (long)mpImpl->mpTextEngine->CalcParaHeight( nPara );
432 if ( ( nPara >= nStartPara ) && ( ( nY + nParaHeight ) > aVisArea.Top() ) )
433 {
434 TEParaPortion* pTEParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( nPara );
435 sal_uInt16 nStartLine = 0;
436 sal_uInt16 nEndLine = pTEParaPortion->GetLines().Count() -1;
437 if ( nPara == nStartPara )
438 nStartLine = pTEParaPortion->GetLineNumber( aSel.GetStart().GetIndex(), sal_False );
439 if ( nPara == nEndPara )
440 nEndLine = pTEParaPortion->GetLineNumber( aSel.GetEnd().GetIndex(), sal_True );
441
442 // ueber die Zeilen iterieren....
443 for ( sal_uInt16 nLine = nStartLine; nLine <= nEndLine; nLine++ )
444 {
445 TextLine* pLine = pTEParaPortion->GetLines().GetObject( nLine );
446 sal_uInt16 nStartIndex = pLine->GetStart();
447 sal_uInt16 nEndIndex = pLine->GetEnd();
448 if ( ( nPara == nStartPara ) && ( nLine == nStartLine ) )
449 nStartIndex = aSel.GetStart().GetIndex();
450 if ( ( nPara == nEndPara ) && ( nLine == nEndLine ) )
451 nEndIndex = aSel.GetEnd().GetIndex();
452
453 // Kann passieren, wenn am Anfang einer umgebrochenen Zeile.
454 if ( nEndIndex < nStartIndex )
455 nEndIndex = nStartIndex;
456
457 Rectangle aTmpRec( mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nStartIndex ), sal_False ) );
458 aTmpRec.Top() += nY;
459 aTmpRec.Bottom() += nY;
460 Point aTopLeft( aTmpRec.TopLeft() );
461
462 aTmpRec = mpImpl->mpTextEngine->GetEditCursor( TextPaM( nPara, nEndIndex ), sal_True );
463 aTmpRec.Top() += nY;
464 aTmpRec.Bottom() += nY;
465 Point aBottomRight( aTmpRec.BottomRight() );
466 aBottomRight.X()--;
467
468 // Nur Painten, wenn im sichtbaren Bereich...
469 if ( ( aTopLeft.X() < aBottomRight.X() ) && ( aBottomRight.Y() >= aVisArea.Top() ) )
470 {
471 Point aPnt1( GetWindowPos( aTopLeft ) );
472 Point aPnt2( GetWindowPos( aBottomRight ) );
473
474 Rectangle aRect( aPnt1, aPnt2 );
475 mpImpl->mpWindow->Invert( aRect );
476 }
477 }
478 }
479 nY += nParaHeight;
480
481 if ( nY >= aVisArea.Bottom() )
482 break;
483 }
484 }
485 }
486
ImpSetSelection(const TextSelection & rSelection)487 void TextView::ImpSetSelection( const TextSelection& rSelection )
488 {
489 if ( rSelection != mpImpl->maSelection )
490 {
491 mpImpl->maSelection = rSelection;
492 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSELECTIONCHANGED ) );
493 }
494 }
495
ShowSelection()496 void TextView::ShowSelection()
497 {
498 ImpShowHideSelection( sal_True );
499 }
500
HideSelection()501 void TextView::HideSelection()
502 {
503 ImpShowHideSelection( sal_False );
504 }
505
ShowSelection(const TextSelection & rRange)506 void TextView::ShowSelection( const TextSelection& rRange )
507 {
508 ImpShowHideSelection( sal_True, &rRange );
509 }
510
ImpShowHideSelection(sal_Bool bShow,const TextSelection * pRange)511 void TextView::ImpShowHideSelection( sal_Bool bShow, const TextSelection* pRange )
512 {
513 const TextSelection* pRangeOrSelection = pRange ? pRange : &mpImpl->maSelection;
514
515 if ( pRangeOrSelection->HasRange() )
516 {
517 if ( mpImpl->mbHighlightSelection )
518 {
519 ImpHighlight( *pRangeOrSelection );
520 }
521 else
522 {
523 if( mpImpl->mpWindow->IsPaintTransparent() )
524 mpImpl->mpWindow->Invalidate();
525 else
526 {
527 Rectangle aOutArea( Point( 0, 0 ), mpImpl->mpWindow->GetOutputSizePixel() );
528 Point aStartPos( ImpGetOutputStartPos( mpImpl->maStartDocPos ) );
529 TextSelection aRange( *pRangeOrSelection );
530 aRange.Justify();
531 sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible();
532 mpImpl->mpCursor->Hide();
533 ImpPaint( mpImpl->mpWindow, aStartPos, &aOutArea, &aRange, bShow ? &mpImpl->maSelection : NULL );
534 if ( bVisCursor )
535 mpImpl->mpCursor->Show();
536 }
537 }
538 }
539 }
540
GetVirtualDevice()541 VirtualDevice* TextView::GetVirtualDevice()
542 {
543 if ( !mpImpl->mpVirtDev )
544 {
545 mpImpl->mpVirtDev = new VirtualDevice;
546 mpImpl->mpVirtDev->SetLineColor();
547 }
548 return mpImpl->mpVirtDev;
549 }
550
EraseVirtualDevice()551 void TextView::EraseVirtualDevice()
552 {
553 delete mpImpl->mpVirtDev;
554 mpImpl->mpVirtDev = 0;
555 }
556
KeyInput(const KeyEvent & rKeyEvent)557 sal_Bool TextView::KeyInput( const KeyEvent& rKeyEvent )
558 {
559 sal_Bool bDone = sal_True;
560 sal_Bool bModified = sal_False;
561 sal_Bool bMoved = sal_False;
562 sal_Bool bEndKey = sal_False; // spezielle CursorPosition
563 sal_Bool bAllowIdle = sal_True;
564
565 // Um zu pruefen ob durch irgendeine Aktion mModified, das lokale
566 // bModified wird z.B. bei Cut/Paste nicht gesetzt, weil dort an anderen
567 // Stellen das updaten erfolgt.
568 sal_Bool bWasModified = mpImpl->mpTextEngine->IsModified();
569 mpImpl->mpTextEngine->SetModified( sal_False );
570
571 TextSelection aCurSel( mpImpl->maSelection );
572 TextSelection aOldSel( aCurSel );
573
574 sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode();
575 KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction();
576 if ( eFunc != KEYFUNC_DONTKNOW )
577 {
578 switch ( eFunc )
579 {
580 case KEYFUNC_CUT:
581 {
582 if ( !mpImpl->mbReadOnly )
583 Cut();
584 }
585 break;
586 case KEYFUNC_COPY:
587 {
588 Copy();
589 }
590 break;
591 case KEYFUNC_PASTE:
592 {
593 if ( !mpImpl->mbReadOnly )
594 Paste();
595 }
596 break;
597 case KEYFUNC_UNDO:
598 {
599 if ( !mpImpl->mbReadOnly )
600 Undo();
601 }
602 break;
603 case KEYFUNC_REDO:
604 {
605 if ( !mpImpl->mbReadOnly )
606 Redo();
607 }
608 break;
609
610 default: // wird dann evtl. unten bearbeitet.
611 eFunc = KEYFUNC_DONTKNOW;
612 }
613 }
614 if ( eFunc == KEYFUNC_DONTKNOW )
615 {
616 switch ( nCode )
617 {
618 case KEY_UP:
619 case KEY_DOWN:
620 case KEY_LEFT:
621 case KEY_RIGHT:
622 case KEY_HOME:
623 case KEY_END:
624 case KEY_PAGEUP:
625 case KEY_PAGEDOWN:
626 case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
627 case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
628 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
629 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
630 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
631 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
632 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
633 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
634 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
635 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
636 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
637 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
638 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
639 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
640 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
641 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
642 {
643 if ( ( !rKeyEvent.GetKeyCode().IsMod2() || ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) )
644 && !( rKeyEvent.GetKeyCode().IsMod1() && ( nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN ) ) )
645 {
646 aCurSel = ImpMoveCursor( rKeyEvent );
647 if ( aCurSel.HasRange() ) {
648 uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection());
649 Copy( aSelection );
650 }
651 bMoved = sal_True;
652 if ( nCode == KEY_END )
653 bEndKey = sal_True;
654 }
655 else
656 bDone = sal_False;
657 }
658 break;
659 case KEY_BACKSPACE:
660 case KEY_DELETE:
661 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
662 case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
663 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE:
664 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE:
665 {
666 if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod2() )
667 {
668 sal_uInt8 nDel = ( nCode == KEY_DELETE ) ? DEL_RIGHT : DEL_LEFT;
669 sal_uInt8 nMode = rKeyEvent.GetKeyCode().IsMod1() ? DELMODE_RESTOFWORD : DELMODE_SIMPLE;
670 if ( ( nMode == DELMODE_RESTOFWORD ) && rKeyEvent.GetKeyCode().IsShift() )
671 nMode = DELMODE_RESTOFCONTENT;
672
673 switch( nCode )
674 {
675 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
676 nDel = DEL_LEFT;
677 nMode = DELMODE_RESTOFWORD;
678 break;
679 case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
680 nDel = DEL_RIGHT;
681 nMode = DELMODE_RESTOFWORD;
682 break;
683 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE:
684 nDel = DEL_LEFT;
685 nMode = DELMODE_RESTOFCONTENT;
686 break;
687 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE:
688 nDel = DEL_RIGHT;
689 nMode = DELMODE_RESTOFCONTENT;
690 break;
691 default: break;
692 }
693
694 mpImpl->mpTextEngine->UndoActionStart();
695 if(mpImpl->mbSupportProtectAttribute)
696 {
697 //expand selection to include all protected content - if there is any
698 const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
699 TextPaM(mpImpl->maSelection.GetStart().GetPara(),
700 mpImpl->maSelection.GetStart().GetIndex()),
701 TEXTATTR_PROTECTED );
702 const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib(
703 TextPaM(mpImpl->maSelection.GetEnd().GetPara(),
704 mpImpl->maSelection.GetEnd().GetIndex()),
705 TEXTATTR_PROTECTED );
706 if(pStartAttr && pStartAttr->GetStart() < mpImpl->maSelection.GetStart().GetIndex())
707 {
708 mpImpl->maSelection.GetStart().GetIndex() = pStartAttr->GetStart();
709 }
710 if(pEndAttr && pEndAttr->GetEnd() > mpImpl->maSelection.GetEnd().GetIndex())
711 {
712 mpImpl->maSelection.GetEnd().GetIndex() = pEndAttr->GetEnd();
713 }
714 }
715 aCurSel = ImpDelete( nDel, nMode );
716 mpImpl->mpTextEngine->UndoActionEnd();
717 bModified = sal_True;
718 bAllowIdle = sal_False;
719 }
720 else
721 bDone = sal_False;
722 }
723 break;
724 case KEY_TAB:
725 {
726 if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsShift() &&
727 !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() &&
728 ImplCheckTextLen( 'x' ) )
729 {
730 aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, '\t', !IsInsertMode() );
731 bModified = sal_True;
732 }
733 else
734 bDone = sal_False;
735 }
736 break;
737 case KEY_RETURN:
738 {
739 // Shift-RETURN darf nicht geschluckt werden, weil dann keine
740 // mehrzeilige Eingabe in Dialogen/Property-Editor moeglich.
741 if ( !mpImpl->mbReadOnly && !rKeyEvent.GetKeyCode().IsMod1() &&
742 !rKeyEvent.GetKeyCode().IsMod2() && ImplCheckTextLen( 'x' ) )
743 {
744 mpImpl->mpTextEngine->UndoActionStart();
745 aCurSel = mpImpl->mpTextEngine->ImpInsertParaBreak( aCurSel );
746 if ( mpImpl->mbAutoIndent )
747 {
748 TextNode* pPrev = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aCurSel.GetEnd().GetPara() - 1 );
749 sal_uInt16 n = 0;
750 while ( ( n < pPrev->GetText().Len() ) && (
751 ( pPrev->GetText().GetChar( n ) == ' ' ) ||
752 ( pPrev->GetText().GetChar( n ) == '\t' ) ) )
753 {
754 n++;
755 }
756 if ( n )
757 aCurSel = mpImpl->mpTextEngine->ImpInsertText( aCurSel, pPrev->GetText().Copy( 0, n ) );
758 }
759 mpImpl->mpTextEngine->UndoActionEnd();
760 bModified = sal_True;
761 }
762 else
763 bDone = sal_False;
764 }
765 break;
766 case KEY_INSERT:
767 {
768 if ( !mpImpl->mbReadOnly )
769 SetInsertMode( !IsInsertMode() );
770 }
771 break;
772 default:
773 {
774 if ( TextEngine::IsSimpleCharInput( rKeyEvent ) )
775 {
776 xub_Unicode nCharCode = rKeyEvent.GetCharCode();
777 if ( !mpImpl->mbReadOnly && ImplCheckTextLen( nCharCode ) ) // sonst trotzdem das Zeichen schlucken...
778 {
779 aCurSel = mpImpl->mpTextEngine->ImpInsertText( nCharCode, aCurSel, !IsInsertMode(), sal_True );
780 bModified = sal_True;
781 }
782 }
783 else
784 bDone = sal_False;
785 }
786 }
787 }
788
789 if ( aCurSel != aOldSel ) // Check if changed, maybe other method already changed mpImpl->maSelection, don't overwrite that!
790 ImpSetSelection( aCurSel );
791
792 mpImpl->mpTextEngine->UpdateSelections();
793
794 if ( ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) )
795 mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
796
797 if ( bModified )
798 {
799 // Idle-Formatter nur, wenn AnyInput.
800 if ( bAllowIdle && Application::AnyInput( INPUT_KEYBOARD) )
801 mpImpl->mpTextEngine->IdleFormatAndUpdate( this );
802 else
803 mpImpl->mpTextEngine->FormatAndUpdate( this);
804 }
805 else if ( bMoved )
806 {
807 // Selection wird jetzt gezielt in ImpMoveCursor gemalt.
808 ImpShowCursor( mpImpl->mbAutoScroll, sal_True, bEndKey );
809 }
810
811 if ( mpImpl->mpTextEngine->IsModified() )
812 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
813 else if ( bWasModified )
814 mpImpl->mpTextEngine->SetModified( sal_True );
815
816 return bDone;
817 }
818
MouseButtonUp(const MouseEvent & rMouseEvent)819 void TextView::MouseButtonUp( const MouseEvent& rMouseEvent )
820 {
821 mpImpl->mbClickedInSelection = sal_False;
822 mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
823 mpImpl->mpSelEngine->SelMouseButtonUp( rMouseEvent );
824 if ( rMouseEvent.IsMiddle() && !IsReadOnly() &&
825 ( GetWindow()->GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) )
826 {
827 uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection());
828 Paste( aSelection );
829 if ( mpImpl->mpTextEngine->IsModified() )
830 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
831 }
832 else if ( rMouseEvent.IsLeft() && GetSelection().HasRange() )
833 {
834 uno::Reference<datatransfer::clipboard::XClipboard> aSelection(GetWindow()->GetPrimarySelection());
835 Copy( aSelection );
836 }
837 }
838
MouseButtonDown(const MouseEvent & rMouseEvent)839 void TextView::MouseButtonDown( const MouseEvent& rMouseEvent )
840 {
841 mpImpl->mpTextEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown
842 mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
843 mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() );
844
845 mpImpl->mpTextEngine->SetActiveView( this );
846
847 mpImpl->mpSelEngine->SelMouseButtonDown( rMouseEvent );
848
849 // mbu 20.01.2005 - SelMouseButtonDown() possibly triggers a 'selection changed'
850 // notification. The appropriate handler could change the current selection,
851 // which is the case in the MailMerge address block control. To enable select'n'drag
852 // we need to reevaluate the selection after the notification has been fired.
853 mpImpl->mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() );
854
855 // Sonderbehandlungen
856 if ( !rMouseEvent.IsShift() && ( rMouseEvent.GetClicks() >= 2 ) )
857 {
858 if ( rMouseEvent.IsMod2() )
859 {
860 HideSelection();
861 ImpSetSelection( mpImpl->maSelection.GetEnd() );
862 SetCursorAtPoint( rMouseEvent.GetPosPixel() ); // Wird von SelectionEngine bei MOD2 nicht gesetzt
863 }
864
865 if ( rMouseEvent.GetClicks() == 2 )
866 {
867 // Wort selektieren
868 if ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) )
869 {
870 HideSelection();
871 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( mpImpl->maSelection.GetEnd().GetPara() );
872 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
873 i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
874 TextSelection aNewSel( mpImpl->maSelection );
875 aNewSel.GetStart().GetIndex() = (sal_uInt16)aBoundary.startPos;
876 aNewSel.GetEnd().GetIndex() = (sal_uInt16)aBoundary.endPos;
877 if(mpImpl->mbSupportProtectAttribute)
878 {
879 //expand selection to include all protected content - if there is any
880 const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
881 TextPaM(aNewSel.GetStart().GetPara(),
882 (sal_uInt16)aBoundary.startPos),
883 TEXTATTR_PROTECTED );
884 const TextCharAttrib* pEndAttr = mpImpl->mpTextEngine->FindCharAttrib(
885 TextPaM(aNewSel.GetEnd().GetPara(),
886 (sal_uInt16)aBoundary.endPos),
887 TEXTATTR_PROTECTED );
888 if(pStartAttr && pStartAttr->GetStart() < aNewSel.GetStart().GetIndex())
889 {
890 aNewSel.GetStart().GetIndex() = pStartAttr->GetStart();
891 }
892 if(pEndAttr && pEndAttr->GetEnd() > aNewSel.GetEnd().GetIndex())
893 {
894 aNewSel.GetEnd().GetIndex() = pEndAttr->GetEnd();
895 }
896 }
897 ImpSetSelection( aNewSel );
898 ShowSelection();
899 ShowCursor( sal_True, sal_True );
900 }
901 }
902 else if ( rMouseEvent.GetClicks() == 3 )
903 {
904 // Absatz selektieren
905 if ( mpImpl->maSelection.GetStart().GetIndex() || ( mpImpl->maSelection.GetEnd().GetIndex() < mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection.GetEnd().GetPara() ) ) )
906 {
907 HideSelection();
908 TextSelection aNewSel( mpImpl->maSelection );
909 aNewSel.GetStart().GetIndex() = 0;
910 aNewSel.GetEnd().GetIndex() = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( mpImpl->maSelection.GetEnd().GetPara() )->GetText().Len();
911 ImpSetSelection( aNewSel );
912 ShowSelection();
913 ShowCursor( sal_True, sal_True );
914 }
915 }
916 }
917 }
918
919
MouseMove(const MouseEvent & rMouseEvent)920 void TextView::MouseMove( const MouseEvent& rMouseEvent )
921 {
922 mpImpl->mnTravelXPos = TRAVEL_X_DONTKNOW;
923 mpImpl->mpSelEngine->SelMouseMove( rMouseEvent );
924 }
925
Command(const CommandEvent & rCEvt)926 void TextView::Command( const CommandEvent& rCEvt )
927 {
928 mpImpl->mpTextEngine->CheckIdleFormatter(); // Falls schnelles Tippen und MouseButtonDown
929 mpImpl->mpTextEngine->SetActiveView( this );
930
931 if ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT )
932 {
933 DeleteSelected();
934 delete mpImpl->mpTextEngine->mpIMEInfos;
935 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( GetSelection().GetEnd().GetPara() );
936 mpImpl->mpTextEngine->mpIMEInfos = new TEIMEInfos( GetSelection().GetEnd(), pNode->GetText().Copy( GetSelection().GetEnd().GetIndex() ) );
937 mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite = !IsInsertMode();
938 }
939 else if ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT )
940 {
941 DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_ENDEXTTEXTINPUT => Kein Start ?" );
942 if( mpImpl->mpTextEngine->mpIMEInfos )
943 {
944 TEParaPortion* pPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() );
945 pPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 );
946
947 sal_Bool bInsertMode = !mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite;
948
949 delete mpImpl->mpTextEngine->mpIMEInfos;
950 mpImpl->mpTextEngine->mpIMEInfos = NULL;
951
952 mpImpl->mpTextEngine->FormatAndUpdate( this );
953
954 SetInsertMode( bInsertMode );
955
956 if ( mpImpl->mpTextEngine->IsModified() )
957 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
958 }
959 }
960 else if ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT )
961 {
962 DBG_ASSERT( mpImpl->mpTextEngine->mpIMEInfos, "COMMAND_EXTTEXTINPUT => Kein Start ?" );
963 if( mpImpl->mpTextEngine->mpIMEInfos )
964 {
965 const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
966
967 if ( !pData->IsOnlyCursorChanged() )
968 {
969 TextSelection aSelect( mpImpl->mpTextEngine->mpIMEInfos->aPos );
970 aSelect.GetEnd().GetIndex() = aSelect.GetEnd().GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen;
971 aSelect = mpImpl->mpTextEngine->ImpDeleteText( aSelect );
972 aSelect = mpImpl->mpTextEngine->ImpInsertText( aSelect, pData->GetText() );
973
974 if ( mpImpl->mpTextEngine->mpIMEInfos->bWasCursorOverwrite )
975 {
976 sal_uInt16 nOldIMETextLen = mpImpl->mpTextEngine->mpIMEInfos->nLen;
977 sal_uInt16 nNewIMETextLen = pData->GetText().Len();
978
979 if ( ( nOldIMETextLen > nNewIMETextLen ) &&
980 ( nNewIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) )
981 {
982 // restore old characters
983 sal_uInt16 nRestore = nOldIMETextLen - nNewIMETextLen;
984 TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos );
985 aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
986 mpImpl->mpTextEngine->ImpInsertText( aPaM, mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Copy( nNewIMETextLen, nRestore ) );
987 }
988 else if ( ( nOldIMETextLen < nNewIMETextLen ) &&
989 ( nOldIMETextLen < mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() ) )
990 {
991 // overwrite
992 sal_uInt16 nOverwrite = nNewIMETextLen - nOldIMETextLen;
993 if ( ( nOldIMETextLen + nOverwrite ) > mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() )
994 nOverwrite = mpImpl->mpTextEngine->mpIMEInfos->aOldTextAfterStartPos.Len() - nOldIMETextLen;
995 DBG_ASSERT( nOverwrite && (nOverwrite < 0xFF00), "IME Overwrite?!" );
996 TextPaM aPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos );
997 aPaM.GetIndex() = aPaM.GetIndex() + nNewIMETextLen;
998 TextSelection aSel( aPaM );
999 aSel.GetEnd().GetIndex() =
1000 aSel.GetEnd().GetIndex() + nOverwrite;
1001 mpImpl->mpTextEngine->ImpDeleteText( aSel );
1002 }
1003 }
1004
1005 if ( pData->GetTextAttr() )
1006 {
1007 mpImpl->mpTextEngine->mpIMEInfos->CopyAttribs( pData->GetTextAttr(), pData->GetText().Len() );
1008 mpImpl->mpTextEngine->mpIMEInfos->bCursor = pData->IsCursorVisible();
1009 }
1010 else
1011 {
1012 mpImpl->mpTextEngine->mpIMEInfos->DestroyAttribs();
1013 }
1014
1015 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara() );
1016 pPPortion->MarkSelectionInvalid( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex(), 0 );
1017 mpImpl->mpTextEngine->FormatAndUpdate( this );
1018 }
1019
1020 TextSelection aNewSel = TextPaM( mpImpl->mpTextEngine->mpIMEInfos->aPos.GetPara(), mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex()+pData->GetCursorPos() );
1021 SetSelection( aNewSel );
1022 SetInsertMode( !pData->IsCursorOverwrite() );
1023
1024 if ( pData->IsCursorVisible() )
1025 ShowCursor();
1026 else
1027 HideCursor();
1028 }
1029 }
1030 else if ( rCEvt.GetCommand() == COMMAND_CURSORPOS )
1031 {
1032 if ( mpImpl->mpTextEngine->mpIMEInfos && mpImpl->mpTextEngine->mpIMEInfos->nLen )
1033 {
1034 TextPaM aPaM( GetSelection().GetEnd() );
1035 Rectangle aR1 = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM );
1036
1037 sal_uInt16 nInputEnd = mpImpl->mpTextEngine->mpIMEInfos->aPos.GetIndex() + mpImpl->mpTextEngine->mpIMEInfos->nLen;
1038
1039 if ( !mpImpl->mpTextEngine->IsFormatted() )
1040 mpImpl->mpTextEngine->FormatDoc();
1041
1042 TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1043 sal_uInt16 nLine = pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True );
1044 TextLine* pLine = pParaPortion->GetLines().GetObject( nLine );
1045 if ( pLine && ( nInputEnd > pLine->GetEnd() ) )
1046 nInputEnd = pLine->GetEnd();
1047 Rectangle aR2 = mpImpl->mpTextEngine->PaMtoEditCursor( TextPaM( aPaM.GetPara(), nInputEnd ) );
1048
1049 long nWidth = aR2.Left()-aR1.Right();
1050 aR1.Move( -GetStartDocPos().X(), -GetStartDocPos().Y() );
1051 if ( nWidth == 0 ) {
1052 Rectangle aR3 = mpImpl->mpTextEngine->PaMtoEditCursor( mpImpl->mpTextEngine->mpIMEInfos->aPos );
1053 nWidth = -(aR1.Left() - aR3.Left());
1054 }
1055 GetWindow()->SetCursorRect( &aR1, nWidth );
1056 }
1057 else
1058 {
1059 GetWindow()->SetCursorRect();
1060 }
1061 }
1062 else
1063 {
1064 mpImpl->mpSelEngine->Command( rCEvt );
1065 }
1066 }
1067
ShowCursor(sal_Bool bGotoCursor,sal_Bool bForceVisCursor)1068 void TextView::ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor )
1069 {
1070 // Die Einstellung hat mehr Gewicht:
1071 if ( !mpImpl->mbAutoScroll )
1072 bGotoCursor = sal_False;
1073 ImpShowCursor( bGotoCursor, bForceVisCursor, sal_False );
1074 }
1075
HideCursor()1076 void TextView::HideCursor()
1077 {
1078 mpImpl->mpCursor->Hide();
1079 }
1080
Scroll(long ndX,long ndY)1081 void TextView::Scroll( long ndX, long ndY )
1082 {
1083 DBG_ASSERT( mpImpl->mpTextEngine->IsFormatted(), "Scroll: Nicht formatiert!" );
1084
1085 if ( !ndX && !ndY )
1086 return;
1087
1088 Point aNewStartPos( mpImpl->maStartDocPos );
1089
1090 // Vertical:
1091 aNewStartPos.Y() -= ndY;
1092 if ( aNewStartPos.Y() < 0 )
1093 aNewStartPos.Y() = 0;
1094
1095 // Horizontal:
1096 aNewStartPos.X() -= ndX;
1097 if ( aNewStartPos.X() < 0 )
1098 aNewStartPos.X() = 0;
1099
1100 long nDiffX = mpImpl->maStartDocPos.X() - aNewStartPos.X();
1101 long nDiffY = mpImpl->maStartDocPos.Y() - aNewStartPos.Y();
1102
1103 if ( nDiffX || nDiffY )
1104 {
1105 sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible();
1106 mpImpl->mpCursor->Hide();
1107 mpImpl->mpWindow->Update();
1108 mpImpl->maStartDocPos = aNewStartPos;
1109
1110 if ( mpImpl->mpTextEngine->IsRightToLeft() )
1111 nDiffX = -nDiffX;
1112 mpImpl->mpWindow->Scroll( nDiffX, nDiffY );
1113 mpImpl->mpWindow->Update();
1114 mpImpl->mpCursor->SetPos( mpImpl->mpCursor->GetPos() + Point( nDiffX, nDiffY ) );
1115 if ( bVisCursor && !mpImpl->mbReadOnly )
1116 mpImpl->mpCursor->Show();
1117 }
1118
1119 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSCROLLED ) );
1120 }
1121
Undo()1122 void TextView::Undo()
1123 {
1124 mpImpl->mpTextEngine->SetActiveView( this );
1125 mpImpl->mpTextEngine->GetUndoManager().Undo();
1126 }
1127
Redo()1128 void TextView::Redo()
1129 {
1130 mpImpl->mpTextEngine->SetActiveView( this );
1131 mpImpl->mpTextEngine->GetUndoManager().Redo();
1132 }
1133
Cut()1134 void TextView::Cut()
1135 {
1136 mpImpl->mpTextEngine->UndoActionStart();
1137 Copy();
1138 DeleteSelected();
1139 mpImpl->mpTextEngine->UndoActionEnd();
1140 }
1141
Copy(uno::Reference<datatransfer::clipboard::XClipboard> & rxClipboard)1142 void TextView::Copy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1143 {
1144 if ( rxClipboard.is() )
1145 {
1146 TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
1147
1148 if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) ) // Dann auch als HTML
1149 mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True );
1150
1151 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1152
1153 try
1154 {
1155 rxClipboard->setContents( pDataObj, NULL );
1156
1157 uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
1158 if( xFlushableClipboard.is() )
1159 xFlushableClipboard->flushClipboard();
1160 }
1161 catch( const ::com::sun::star::uno::Exception& )
1162 {
1163 }
1164
1165 Application::AcquireSolarMutex( nRef );
1166 }
1167 }
1168
Copy()1169 void TextView::Copy()
1170 {
1171 uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
1172 Copy( aClipboard );
1173 }
1174
Paste(uno::Reference<datatransfer::clipboard::XClipboard> & rxClipboard)1175 void TextView::Paste( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1176 {
1177 if ( rxClipboard.is() )
1178 {
1179 uno::Reference< datatransfer::XTransferable > xDataObj;
1180
1181 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1182
1183 try
1184 {
1185 xDataObj = rxClipboard->getContents();
1186 }
1187 catch( const ::com::sun::star::uno::Exception& )
1188 {
1189 }
1190
1191 Application::AcquireSolarMutex( nRef );
1192
1193 if ( xDataObj.is() )
1194 {
1195 datatransfer::DataFlavor aFlavor;
1196 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
1197 if ( xDataObj->isDataFlavorSupported( aFlavor ) )
1198 {
1199 try
1200 {
1201 uno::Any aData = xDataObj->getTransferData( aFlavor );
1202 ::rtl::OUString aText;
1203 aData >>= aText;
1204 bool bWasTruncated = false;
1205 if( mpImpl->mpTextEngine->GetMaxTextLen() != 0 )
1206 bWasTruncated = ImplTruncateNewText( aText );
1207 InsertNewText( aText, sal_False );
1208 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
1209
1210 if( bWasTruncated )
1211 Edit::ShowTruncationWarning( mpImpl->mpWindow );
1212 }
1213 catch( const ::com::sun::star::datatransfer::UnsupportedFlavorException& )
1214 {
1215 }
1216 }
1217 }
1218 }
1219 }
1220
Paste()1221 void TextView::Paste()
1222 {
1223 uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
1224 Paste( aClipboard );
1225 }
1226
GetSelected()1227 String TextView::GetSelected()
1228 {
1229 return GetSelected( GetSystemLineEnd() );
1230 }
1231
GetSelected(LineEnd aSeparator)1232 String TextView::GetSelected( LineEnd aSeparator )
1233 {
1234 return mpImpl->mpTextEngine->GetText( mpImpl->maSelection, aSeparator );
1235 }
1236
SetInsertMode(sal_Bool bInsert)1237 void TextView::SetInsertMode( sal_Bool bInsert )
1238 {
1239 if ( mpImpl->mbInsertMode != bInsert )
1240 {
1241 mpImpl->mbInsertMode = bInsert;
1242 ShowCursor( mpImpl->mbAutoScroll, sal_False );
1243 }
1244 }
1245
SetReadOnly(sal_Bool bReadOnly)1246 void TextView::SetReadOnly( sal_Bool bReadOnly )
1247 {
1248 if ( mpImpl->mbReadOnly != bReadOnly )
1249 {
1250 mpImpl->mbReadOnly = bReadOnly;
1251 if ( !mpImpl->mbReadOnly )
1252 ShowCursor( mpImpl->mbAutoScroll, sal_False );
1253 else
1254 HideCursor();
1255
1256 GetWindow()->SetInputContext( InputContext( mpImpl->mpTextEngine->GetFont(), bReadOnly ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) );
1257 }
1258 }
1259
ImpMoveCursor(const KeyEvent & rKeyEvent)1260 TextSelection TextView::ImpMoveCursor( const KeyEvent& rKeyEvent )
1261 {
1262 // Eigentlich nur bei Up/Down noetig, aber was solls.
1263 mpImpl->mpTextEngine->CheckIdleFormatter();
1264
1265 TextPaM aPaM( mpImpl->maSelection.GetEnd() );
1266 TextPaM aOldEnd( aPaM );
1267
1268 TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom;
1269 if ( mpImpl->mpTextEngine->IsRightToLeft() )
1270 eTextDirection = TextDirectionality_RightToLeft_TopToBottom;
1271
1272 KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection );
1273
1274 sal_Bool bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1() ? sal_True : sal_False;
1275 sal_uInt16 nCode = aTranslatedKeyEvent.GetKeyCode().GetCode();
1276
1277 bool bSelect = aTranslatedKeyEvent.GetKeyCode().IsShift();
1278 switch ( nCode )
1279 {
1280 case KEY_UP: aPaM = CursorUp( aPaM );
1281 break;
1282 case KEY_DOWN: aPaM = CursorDown( aPaM );
1283 break;
1284 case KEY_HOME: aPaM = bCtrl ? CursorStartOfDoc() : CursorStartOfLine( aPaM );
1285 break;
1286 case KEY_END: aPaM = bCtrl ? CursorEndOfDoc() : CursorEndOfLine( aPaM );
1287 break;
1288 case KEY_PAGEUP: aPaM = bCtrl ? CursorStartOfDoc() : PageUp( aPaM );
1289 break;
1290 case KEY_PAGEDOWN: aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM );
1291 break;
1292 case KEY_LEFT: aPaM = bCtrl ? CursorWordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1293 break;
1294 case KEY_RIGHT: aPaM = bCtrl ? CursorWordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1295 break;
1296 case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
1297 bSelect = true; // fallthrough intentional
1298 case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
1299 aPaM = CursorWordRight( aPaM );
1300 break;
1301 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
1302 bSelect = true; // fallthrough intentional
1303 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
1304 aPaM = CursorWordLeft( aPaM );
1305 break;
1306 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
1307 bSelect = true; // fallthrough intentional
1308 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
1309 aPaM = CursorStartOfLine( aPaM );
1310 break;
1311 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
1312 bSelect = true; // fallthrough intentional
1313 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
1314 aPaM = CursorEndOfLine( aPaM );
1315 break;
1316 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
1317 bSelect = true; // falltthrough intentional
1318 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
1319 aPaM = CursorStartOfParagraph( aPaM );
1320 break;
1321 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
1322 bSelect = true; // falltthrough intentional
1323 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
1324 aPaM = CursorEndOfParagraph( aPaM );
1325 break;
1326 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
1327 bSelect = true; // falltthrough intentional
1328 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
1329 aPaM = CursorStartOfDoc();
1330 break;
1331 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
1332 bSelect = true; // falltthrough intentional
1333 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
1334 aPaM = CursorEndOfDoc();
1335 break;
1336 }
1337
1338 // Bewirkt evtl. ein CreateAnchor oder Deselection all
1339 mpImpl->mpSelEngine->CursorPosChanging( bSelect, aTranslatedKeyEvent.GetKeyCode().IsMod1() );
1340
1341 if ( aOldEnd != aPaM )
1342 {
1343 mpImpl->mpTextEngine->CursorMoved( aOldEnd.GetPara() );
1344
1345
1346 TextSelection aOldSelection( mpImpl->maSelection );
1347 TextSelection aNewSelection( mpImpl->maSelection );
1348 aNewSelection.GetEnd() = aPaM;
1349 if ( bSelect )
1350 {
1351 // Dann wird die Selektion erweitert...
1352 ImpSetSelection( aNewSelection );
1353 ShowSelection( TextSelection( aOldEnd, aPaM ) );
1354 }
1355 else
1356 {
1357 aNewSelection.GetStart() = aPaM;
1358 ImpSetSelection( aNewSelection );
1359 }
1360 }
1361
1362 return mpImpl->maSelection;
1363 }
1364
InsertText(const XubString & rStr,sal_Bool bSelect)1365 void TextView::InsertText( const XubString& rStr, sal_Bool bSelect )
1366 {
1367 InsertNewText( rStr, bSelect );
1368 }
1369
InsertNewText(const rtl::OUString & rStr,sal_Bool bSelect)1370 void TextView::InsertNewText( const rtl::OUString& rStr, sal_Bool bSelect )
1371 {
1372 // HideSelection();
1373 mpImpl->mpTextEngine->UndoActionStart();
1374
1375 /* #i87633#
1376 break inserted text into chunks that fit into the underlying String
1377 based API (which has a maximum length of 65534 elements
1378
1379 note: this will of course still cause problems for lines longer than those
1380 65534 elements, but those cases will hopefully be few.
1381 In the long run someone should switch the TextEngine to OUString instead of String
1382 */
1383 sal_Int32 nLen = rStr.getLength();
1384 sal_Int32 nPos = 0;
1385 do
1386 {
1387 sal_Int32 nChunkLen = nLen > 65534 ? 65534 : nLen;
1388 String aChunk( rStr.copy( nPos, nChunkLen ) );
1389
1390 TextSelection aNewSel( mpImpl->maSelection );
1391
1392 TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, aChunk );
1393
1394 if ( bSelect )
1395 {
1396 aNewSel.Justify();
1397 aNewSel.GetEnd() = aPaM;
1398 }
1399 else
1400 {
1401 aNewSel = aPaM;
1402 }
1403
1404 ImpSetSelection( aNewSel );
1405 nLen -= nChunkLen;
1406 nPos += nChunkLen;
1407 } while( nLen );
1408 mpImpl->mpTextEngine->UndoActionEnd();
1409
1410 mpImpl->mpTextEngine->FormatAndUpdate( this );
1411 }
1412
1413 /*
1414 void TextView::InsertText( const XubString& rStr, sal_Bool bSelect )
1415 {
1416 // HideSelection();
1417
1418 TextSelection aNewSel( mpImpl->maSelection );
1419
1420 mpImpl->mpTextEngine->UndoActionStart();
1421 TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, rStr );
1422 mpImpl->mpTextEngine->UndoActionEnd();
1423
1424 if ( bSelect )
1425 {
1426 aNewSel.Justify();
1427 aNewSel.GetEnd() = aPaM;
1428 }
1429 else
1430 {
1431 aNewSel = aPaM;
1432 }
1433
1434 ImpSetSelection( aNewSel );
1435
1436 mpImpl->mpTextEngine->FormatAndUpdate( this );
1437 }
1438 */
1439
1440 // OLD
CursorLeft(const TextPaM & rPaM,sal_Bool bWordMode)1441 TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_Bool bWordMode )
1442 {
1443 return bWordMode ? CursorWordLeft( rPaM ) : CursorLeft( rPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1444
1445 // Remove (sal_uInt16) typecasts in this file when removing this method!
1446 }
1447
1448 // OLD
CursorRight(const TextPaM & rPaM,sal_Bool bWordMode)1449 TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_Bool bWordMode )
1450 {
1451 return bWordMode ? CursorWordRight( rPaM ) : CursorRight( rPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1452
1453 // Remove (sal_uInt16) typecasts in this file when removing this method!
1454 }
1455
CursorLeft(const TextPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1456 TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1457 {
1458 TextPaM aPaM( rPaM );
1459
1460 if ( aPaM.GetIndex() )
1461 {
1462 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1463 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1464 sal_Int32 nCount = 1;
1465 aPaM.GetIndex() = (sal_uInt16)xBI->previousCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
1466 }
1467 else if ( aPaM.GetPara() )
1468 {
1469 aPaM.GetPara()--;
1470 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1471 aPaM.GetIndex() = pNode->GetText().Len();
1472 }
1473 return aPaM;
1474 }
1475
CursorRight(const TextPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1476 TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1477 {
1478 TextPaM aPaM( rPaM );
1479
1480 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1481 if ( aPaM.GetIndex() < pNode->GetText().Len() )
1482 {
1483 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1484 sal_Int32 nCount = 1;
1485 aPaM.GetIndex() = (sal_uInt16)xBI->nextCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
1486 }
1487 else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
1488 {
1489 aPaM.GetPara()++;
1490 aPaM.GetIndex() = 0;
1491 }
1492
1493 return aPaM;
1494 }
1495
1496
CursorWordLeft(const TextPaM & rPaM)1497 TextPaM TextView::CursorWordLeft( const TextPaM& rPaM )
1498 {
1499 TextPaM aPaM( rPaM );
1500
1501 if ( aPaM.GetIndex() )
1502 {
1503 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1504 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1505 i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1506 if ( aBoundary.startPos >= rPaM.GetIndex() )
1507 aBoundary = xBI->previousWord( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1508 aPaM.GetIndex() = ( aBoundary.startPos != -1 ) ? (sal_uInt16)aBoundary.startPos : 0;
1509 }
1510 else if ( aPaM.GetPara() )
1511 {
1512 aPaM.GetPara()--;
1513 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1514 aPaM.GetIndex() = pNode->GetText().Len();
1515 }
1516 return aPaM;
1517 }
1518
1519
CursorWordRight(const TextPaM & rPaM)1520 TextPaM TextView::CursorWordRight( const TextPaM& rPaM )
1521 {
1522 TextPaM aPaM( rPaM );
1523
1524 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1525 if ( aPaM.GetIndex() < pNode->GetText().Len() )
1526 {
1527 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1528 i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1529 aPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
1530 }
1531 else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
1532 {
1533 aPaM.GetPara()++;
1534 aPaM.GetIndex() = 0;
1535 }
1536
1537 return aPaM;
1538 }
1539
ImpDelete(sal_uInt8 nMode,sal_uInt8 nDelMode)1540 TextPaM TextView::ImpDelete( sal_uInt8 nMode, sal_uInt8 nDelMode )
1541 {
1542 if ( mpImpl->maSelection.HasRange() ) // dann nur Sel. loeschen
1543 return mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection );
1544
1545 TextPaM aStartPaM = mpImpl->maSelection.GetStart();
1546 TextPaM aEndPaM = aStartPaM;
1547 if ( nMode == DEL_LEFT )
1548 {
1549 if ( nDelMode == DELMODE_SIMPLE )
1550 {
1551 aEndPaM = CursorLeft( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER );
1552 }
1553 else if ( nDelMode == DELMODE_RESTOFWORD )
1554 {
1555 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1556 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1557 i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1558 if ( aBoundary.startPos == mpImpl->maSelection.GetEnd().GetIndex() )
1559 aBoundary = xBI->previousWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1560 // #i63506# startPos is -1 when the paragraph starts with a tab
1561 aEndPaM.GetIndex() = (aBoundary.startPos >= 0) ? (sal_uInt16)aBoundary.startPos : 0;
1562 }
1563 else // DELMODE_RESTOFCONTENT
1564 {
1565 if ( aEndPaM.GetIndex() != 0 )
1566 aEndPaM.GetIndex() = 0;
1567 else if ( aEndPaM.GetPara() )
1568 {
1569 // Absatz davor
1570 aEndPaM.GetPara()--;
1571 aEndPaM.GetIndex() = 0;
1572 }
1573 }
1574 }
1575 else
1576 {
1577 if ( nDelMode == DELMODE_SIMPLE )
1578 {
1579 aEndPaM = CursorRight( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1580 }
1581 else if ( nDelMode == DELMODE_RESTOFWORD )
1582 {
1583 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1584 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1585 i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1586 aEndPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
1587 }
1588 else // DELMODE_RESTOFCONTENT
1589 {
1590 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1591 if ( aEndPaM.GetIndex() < pNode->GetText().Len() )
1592 aEndPaM.GetIndex() = pNode->GetText().Len();
1593 else if ( aEndPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) )
1594 {
1595 // Absatz danach
1596 aEndPaM.GetPara()++;
1597 TextNode* pNextNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1598 aEndPaM.GetIndex() = pNextNode->GetText().Len();
1599 }
1600 }
1601 }
1602
1603 return mpImpl->mpTextEngine->ImpDeleteText( TextSelection( aStartPaM, aEndPaM ) );
1604 }
1605
1606
1607
CursorUp(const TextPaM & rPaM)1608 TextPaM TextView::CursorUp( const TextPaM& rPaM )
1609 {
1610 TextPaM aPaM( rPaM );
1611
1612 long nX;
1613 if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
1614 {
1615 nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left();
1616 mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
1617 }
1618 else
1619 nX = mpImpl->mnTravelXPos;
1620
1621 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1622 sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False );
1623 if ( nLine ) // gleicher Absatz
1624 {
1625 sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine-1, nX );
1626 aPaM.GetIndex() = nCharPos;
1627 // Wenn davor eine autom.Umgebrochene Zeile, und ich muss genau an das
1628 // Ende dieser Zeile, landet der Cursor in der aktuellen Zeile am Anfang
1629 // Siehe Problem: Letztes Zeichen einer autom.umgebr. Zeile = Cursor
1630 TextLine* pLine = pPPortion->GetLines().GetObject( nLine - 1 );
1631 if ( aPaM.GetIndex() && ( aPaM.GetIndex() == pLine->GetEnd() ) )
1632 aPaM.GetIndex()--;
1633 }
1634 else if ( rPaM.GetPara() ) // vorheriger Absatz
1635 {
1636 aPaM.GetPara()--;
1637 pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1638 sal_uInt16 nL = pPPortion->GetLines().Count() - 1;
1639 sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), nL, nX+1 );
1640 aPaM.GetIndex() = nCharPos;
1641 }
1642
1643 return aPaM;
1644 }
1645
CursorDown(const TextPaM & rPaM)1646 TextPaM TextView::CursorDown( const TextPaM& rPaM )
1647 {
1648 TextPaM aPaM( rPaM );
1649
1650 long nX;
1651 if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
1652 {
1653 nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left();
1654 mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
1655 }
1656 else
1657 nX = mpImpl->mnTravelXPos;
1658
1659 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1660 sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False );
1661 if ( nLine < ( pPPortion->GetLines().Count() - 1 ) )
1662 {
1663 sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine+1, nX );
1664 aPaM.GetIndex() = nCharPos;
1665
1666 // Sonderbehandlung siehe CursorUp...
1667 TextLine* pLine = pPPortion->GetLines().GetObject( nLine + 1 );
1668 if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && aPaM.GetIndex() < pPPortion->GetNode()->GetText().Len() )
1669 aPaM.GetIndex()--;
1670 }
1671 else if ( rPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) ) // naechster Absatz
1672 {
1673 aPaM.GetPara()++;
1674 pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1675 sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), 0, nX+1 );
1676 aPaM.GetIndex() = nCharPos;
1677 TextLine* pLine = pPPortion->GetLines().GetObject( 0 );
1678 if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && ( pPPortion->GetLines().Count() > 1 ) )
1679 aPaM.GetIndex()--;
1680 }
1681
1682 return aPaM;
1683 }
1684
CursorStartOfLine(const TextPaM & rPaM)1685 TextPaM TextView::CursorStartOfLine( const TextPaM& rPaM )
1686 {
1687 TextPaM aPaM( rPaM );
1688
1689 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1690 sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1691 TextLine* pLine = pPPortion->GetLines().GetObject( nLine );
1692 aPaM.GetIndex() = pLine->GetStart();
1693
1694 return aPaM;
1695 }
1696
CursorEndOfLine(const TextPaM & rPaM)1697 TextPaM TextView::CursorEndOfLine( const TextPaM& rPaM )
1698 {
1699 TextPaM aPaM( rPaM );
1700
1701 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1702 sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1703 TextLine* pLine = pPPortion->GetLines().GetObject( nLine );
1704 aPaM.GetIndex() = pLine->GetEnd();
1705
1706 if ( pLine->GetEnd() > pLine->GetStart() ) // Leerzeile
1707 {
1708 xub_Unicode cLastChar = pPPortion->GetNode()->GetText().GetChar((sal_uInt16)(aPaM.GetIndex()-1) );
1709 if ( ( cLastChar == ' ' ) && ( aPaM.GetIndex() != pPPortion->GetNode()->GetText().Len() ) )
1710 {
1711 // Bei einem Blank in einer autom. umgebrochenen Zeile macht es Sinn,
1712 // davor zu stehen, da der Anwender hinter das Wort will.
1713 // Wenn diese geaendert wird, Sonderbehandlung fuer Pos1 nach End!
1714 aPaM.GetIndex()--;
1715 }
1716 }
1717 return aPaM;
1718 }
1719
CursorStartOfParagraph(const TextPaM & rPaM)1720 TextPaM TextView::CursorStartOfParagraph( const TextPaM& rPaM )
1721 {
1722 TextPaM aPaM( rPaM );
1723 aPaM.GetIndex() = 0;
1724 return aPaM;
1725 }
1726
CursorEndOfParagraph(const TextPaM & rPaM)1727 TextPaM TextView::CursorEndOfParagraph( const TextPaM& rPaM )
1728 {
1729 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( rPaM.GetPara() );
1730 TextPaM aPaM( rPaM );
1731 aPaM.GetIndex() = pNode->GetText().Len();
1732 return aPaM;
1733 }
1734
CursorStartOfDoc()1735 TextPaM TextView::CursorStartOfDoc()
1736 {
1737 TextPaM aPaM( 0, 0 );
1738 return aPaM;
1739 }
1740
CursorEndOfDoc()1741 TextPaM TextView::CursorEndOfDoc()
1742 {
1743 sal_uLong nNode = mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1;
1744 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( nNode );
1745 TextPaM aPaM( nNode, pNode->GetText().Len() );
1746 return aPaM;
1747 }
1748
PageUp(const TextPaM & rPaM)1749 TextPaM TextView::PageUp( const TextPaM& rPaM )
1750 {
1751 Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
1752 Point aTopLeft = aRec.TopLeft();
1753 aTopLeft.Y() -= mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
1754 aTopLeft.X() += 1;
1755 if ( aTopLeft.Y() < 0 )
1756 aTopLeft.Y() = 0;
1757
1758 TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aTopLeft );
1759 return aPaM;
1760 }
1761
PageDown(const TextPaM & rPaM)1762 TextPaM TextView::PageDown( const TextPaM& rPaM )
1763 {
1764 Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
1765 Point aBottomRight = aRec.BottomRight();
1766 aBottomRight.Y() += mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
1767 aBottomRight.X() += 1;
1768 long nHeight = mpImpl->mpTextEngine->GetTextHeight();
1769 if ( aBottomRight.Y() > nHeight )
1770 aBottomRight.Y() = nHeight-1;
1771
1772 TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aBottomRight );
1773 return aPaM;
1774 }
1775
ImpShowCursor(sal_Bool bGotoCursor,sal_Bool bForceVisCursor,sal_Bool bSpecial)1776 void TextView::ImpShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, sal_Bool bSpecial )
1777 {
1778 if ( mpImpl->mpTextEngine->IsFormatting() )
1779 return;
1780 if ( mpImpl->mpTextEngine->GetUpdateMode() == sal_False )
1781 return;
1782 if ( mpImpl->mpTextEngine->IsInUndo() )
1783 return;
1784
1785 mpImpl->mpTextEngine->CheckIdleFormatter();
1786 if ( !mpImpl->mpTextEngine->IsFormatted() )
1787 mpImpl->mpTextEngine->FormatAndUpdate( this );
1788
1789
1790 TextPaM aPaM( mpImpl->maSelection.GetEnd() );
1791 Rectangle aEditCursor = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM, bSpecial );
1792
1793 // Remember that we placed the cursor behind the last character of a line
1794 mpImpl->mbCursorAtEndOfLine = false;
1795 if( bSpecial )
1796 {
1797 TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1798 mpImpl->mbCursorAtEndOfLine =
1799 pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True ) != pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1800 }
1801
1802 if ( !IsInsertMode() && !mpImpl->maSelection.HasRange() )
1803 {
1804 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1805 if ( pNode->GetText().Len() && ( aPaM.GetIndex() < pNode->GetText().Len() ) )
1806 {
1807 // If we are behind a portion, and the next portion has other direction, we must change position...
1808 aEditCursor.Left() = aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aPaM, sal_False, sal_True ).Left();
1809
1810 TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1811
1812 sal_uInt16 nTextPortionStart = 0;
1813 sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, sal_True );
1814 TETextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
1815 if ( pTextPortion->GetKind() == PORTIONKIND_TAB )
1816 {
1817 if ( mpImpl->mpTextEngine->IsRightToLeft() )
1818 {
1819
1820 }
1821 aEditCursor.Right() += pTextPortion->GetWidth();
1822 }
1823 else
1824 {
1825 TextPaM aNext = CursorRight( TextPaM( aPaM.GetPara(), aPaM.GetIndex() ), (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1826 aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aNext, sal_True ).Left();
1827 }
1828 }
1829 }
1830
1831 Size aOutSz = mpImpl->mpWindow->GetOutputSizePixel();
1832 if ( aEditCursor.GetHeight() > aOutSz.Height() )
1833 aEditCursor.Bottom() = aEditCursor.Top() + aOutSz.Height() - 1;
1834
1835 aEditCursor.Left() -= 1;
1836
1837 if ( bGotoCursor
1838 // #i81283# protext maStartDocPos against initialization problems
1839 && aOutSz.Width() && aOutSz.Height()
1840 )
1841 {
1842 long nVisStartY = mpImpl->maStartDocPos.Y();
1843 long nVisEndY = mpImpl->maStartDocPos.Y() + aOutSz.Height();
1844 long nVisStartX = mpImpl->maStartDocPos.X();
1845 long nVisEndX = mpImpl->maStartDocPos.X() + aOutSz.Width();
1846 long nMoreX = aOutSz.Width() / 4;
1847
1848 Point aNewStartPos( mpImpl->maStartDocPos );
1849
1850 if ( aEditCursor.Bottom() > nVisEndY )
1851 {
1852 aNewStartPos.Y() += ( aEditCursor.Bottom() - nVisEndY );
1853 }
1854 else if ( aEditCursor.Top() < nVisStartY )
1855 {
1856 aNewStartPos.Y() -= ( nVisStartY - aEditCursor.Top() );
1857 }
1858
1859 if ( aEditCursor.Right() >= nVisEndX )
1860 {
1861 aNewStartPos.X() += ( aEditCursor.Right() - nVisEndX );
1862
1863 // Darfs ein bischen mehr sein?
1864 aNewStartPos.X() += nMoreX;
1865 }
1866 else if ( aEditCursor.Left() <= nVisStartX )
1867 {
1868 aNewStartPos.X() -= ( nVisStartX - aEditCursor.Left() );
1869
1870 // Darfs ein bischen mehr sein?
1871 aNewStartPos.X() -= nMoreX;
1872 }
1873
1874 // X kann durch das 'bischen mehr' falsch sein:
1875 // sal_uLong nMaxTextWidth = mpImpl->mpTextEngine->GetMaxTextWidth();
1876 // if ( !nMaxTextWidth || ( nMaxTextWidth > 0x7FFFFFFF ) )
1877 // nMaxTextWidth = 0x7FFFFFFF;
1878 // long nMaxX = (long)nMaxTextWidth - aOutSz.Width();
1879 long nMaxX = mpImpl->mpTextEngine->CalcTextWidth() - aOutSz.Width();
1880 if ( nMaxX < 0 )
1881 nMaxX = 0;
1882
1883 if ( aNewStartPos.X() < 0 )
1884 aNewStartPos.X() = 0;
1885 else if ( aNewStartPos.X() > nMaxX )
1886 aNewStartPos.X() = nMaxX;
1887
1888 // Y sollte nicht weiter unten als noetig liegen:
1889 long nYMax = mpImpl->mpTextEngine->GetTextHeight() - aOutSz.Height();
1890 if ( nYMax < 0 )
1891 nYMax = 0;
1892 if ( aNewStartPos.Y() > nYMax )
1893 aNewStartPos.Y() = nYMax;
1894
1895 if ( aNewStartPos != mpImpl->maStartDocPos )
1896 Scroll( -(aNewStartPos.X() - mpImpl->maStartDocPos.X()), -(aNewStartPos.Y() - mpImpl->maStartDocPos.Y()) );
1897 }
1898
1899 if ( aEditCursor.Right() < aEditCursor.Left() )
1900 {
1901 long n = aEditCursor.Left();
1902 aEditCursor.Left() = aEditCursor.Right();
1903 aEditCursor.Right() = n;
1904 }
1905
1906 Point aPoint( GetWindowPos( !mpImpl->mpTextEngine->IsRightToLeft() ? aEditCursor.TopLeft() : aEditCursor.TopRight() ) );
1907 mpImpl->mpCursor->SetPos( aPoint );
1908 mpImpl->mpCursor->SetSize( aEditCursor.GetSize() );
1909 if ( bForceVisCursor && mpImpl->mbCursorEnabled )
1910 mpImpl->mpCursor->Show();
1911 }
1912
SetCursorAtPoint(const Point & rPosPixel)1913 sal_Bool TextView::SetCursorAtPoint( const Point& rPosPixel )
1914 {
1915 mpImpl->mpTextEngine->CheckIdleFormatter();
1916
1917 Point aDocPos = GetDocPos( rPosPixel );
1918
1919 TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos );
1920
1921 // aTmpNewSel: Diff zwischen alt und neu, nicht die neue Selektion
1922 TextSelection aTmpNewSel( mpImpl->maSelection.GetEnd(), aPaM );
1923 TextSelection aNewSel( mpImpl->maSelection );
1924 aNewSel.GetEnd() = aPaM;
1925
1926 if ( !mpImpl->mpSelEngine->HasAnchor() )
1927 {
1928 if ( mpImpl->maSelection.GetStart() != aPaM )
1929 mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() );
1930 aNewSel.GetStart() = aPaM;
1931 ImpSetSelection( aNewSel );
1932 }
1933 else
1934 {
1935 ImpSetSelection( aNewSel );
1936 ShowSelection( aTmpNewSel );
1937 }
1938
1939 sal_Bool bForceCursor = mpImpl->mpDDInfo ? sal_False : sal_True; // && !mbInSelection
1940 ImpShowCursor( mpImpl->mbAutoScroll, bForceCursor, sal_False );
1941 return sal_True;
1942 }
1943
IsSelectionAtPoint(const Point & rPosPixel)1944 sal_Bool TextView::IsSelectionAtPoint( const Point& rPosPixel )
1945 {
1946 // if ( !Rectangle( Point(), mpImpl->mpWindow->GetOutputSizePixel() ).IsInside( rPosPixel ) && !mbInSelection )
1947 // return sal_False;
1948
1949 Point aDocPos = GetDocPos( rPosPixel );
1950 TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos, sal_False );
1951 // Bei Hyperlinks D&D auch ohne Selektion starten.
1952 // BeginDrag wird aber nur gerufen, wenn IsSelectionAtPoint()
1953 // Problem: IsSelectionAtPoint wird bei Command() nicht gerufen,
1954 // wenn vorher im MBDown schon sal_False returnt wurde.
1955 return ( IsInSelection( aPaM ) ||
1956 ( /* mpImpl->mpSelEngine->IsInCommand() && */ mpImpl->mpTextEngine->FindAttrib( aPaM, TEXTATTR_HYPERLINK ) ) );
1957 }
1958
IsInSelection(const TextPaM & rPaM)1959 sal_Bool TextView::IsInSelection( const TextPaM& rPaM )
1960 {
1961 TextSelection aSel = mpImpl->maSelection;
1962 aSel.Justify();
1963
1964 sal_uLong nStartNode = aSel.GetStart().GetPara();
1965 sal_uLong nEndNode = aSel.GetEnd().GetPara();
1966 sal_uLong nCurNode = rPaM.GetPara();
1967
1968 if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) )
1969 return sal_True;
1970
1971 if ( nStartNode == nEndNode )
1972 {
1973 if ( nCurNode == nStartNode )
1974 if ( ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
1975 return sal_True;
1976 }
1977 else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) )
1978 return sal_True;
1979 else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
1980 return sal_True;
1981
1982 return sal_False;
1983 }
1984
ImpHideDDCursor()1985 void TextView::ImpHideDDCursor()
1986 {
1987 if ( mpImpl->mpDDInfo && mpImpl->mpDDInfo->mbVisCursor )
1988 {
1989 mpImpl->mpDDInfo->maCursor.Hide();
1990 mpImpl->mpDDInfo->mbVisCursor = sal_False;
1991 }
1992 }
1993
ImpShowDDCursor()1994 void TextView::ImpShowDDCursor()
1995 {
1996 if ( !mpImpl->mpDDInfo->mbVisCursor )
1997 {
1998 Rectangle aCursor = mpImpl->mpTextEngine->PaMtoEditCursor( mpImpl->mpDDInfo->maDropPos, sal_True );
1999 aCursor.Right()++;
2000 aCursor.SetPos( GetWindowPos( aCursor.TopLeft() ) );
2001
2002 mpImpl->mpDDInfo->maCursor.SetWindow( mpImpl->mpWindow );
2003 mpImpl->mpDDInfo->maCursor.SetPos( aCursor.TopLeft() );
2004 mpImpl->mpDDInfo->maCursor.SetSize( aCursor.GetSize() );
2005 mpImpl->mpDDInfo->maCursor.Show();
2006 mpImpl->mpDDInfo->mbVisCursor = sal_True;
2007 }
2008 }
2009
SetPaintSelection(sal_Bool bPaint)2010 void TextView::SetPaintSelection( sal_Bool bPaint )
2011 {
2012 if ( bPaint != mpImpl->mbPaintSelection )
2013 {
2014 mpImpl->mbPaintSelection = bPaint;
2015 ShowSelection( mpImpl->maSelection );
2016 }
2017 }
2018
SetHighlightSelection(sal_Bool bSelectByHighlight)2019 void TextView::SetHighlightSelection( sal_Bool bSelectByHighlight )
2020 {
2021 if ( bSelectByHighlight != mpImpl->mbHighlightSelection )
2022 {
2023 // Falls umschalten zwischendurch moeglich...
2024 mpImpl->mbHighlightSelection = bSelectByHighlight;
2025 }
2026 }
2027
Read(SvStream & rInput)2028 sal_Bool TextView::Read( SvStream& rInput )
2029 {
2030 sal_Bool bDone = mpImpl->mpTextEngine->Read( rInput, &mpImpl->maSelection );
2031 ShowCursor();
2032 return bDone;
2033 }
2034
Write(SvStream & rOutput)2035 sal_Bool TextView::Write( SvStream& rOutput )
2036 {
2037 return mpImpl->mpTextEngine->Read( rOutput, &mpImpl->maSelection );
2038 }
2039
ImplTruncateNewText(rtl::OUString & rNewText) const2040 bool TextView::ImplTruncateNewText( rtl::OUString& rNewText ) const
2041 {
2042 bool bTruncated = false;
2043
2044 if( rNewText.getLength() > 65534 ) // limit to String API
2045 {
2046 rNewText = rNewText.copy( 0, 65534 );
2047 bTruncated = true;
2048 }
2049
2050 sal_uLong nMaxLen = mpImpl->mpTextEngine->GetMaxTextLen();
2051 // 0 means unlimited, there is just the String API limit handled above
2052 if( nMaxLen != 0 )
2053 {
2054 sal_uLong nCurLen = mpImpl->mpTextEngine->GetTextLen();
2055
2056 sal_uInt32 nNewLen = rNewText.getLength();
2057 if ( nCurLen + nNewLen > nMaxLen )
2058 {
2059 // see how much text will be replaced
2060 sal_uLong nSelLen = mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
2061 if ( nCurLen + nNewLen - nSelLen > nMaxLen )
2062 {
2063 sal_uInt32 nTruncatedLen = static_cast<sal_uInt32>(nMaxLen - (nCurLen - nSelLen));
2064 rNewText = rNewText.copy( 0, nTruncatedLen );
2065 bTruncated = true;
2066 }
2067 }
2068 }
2069 return bTruncated;
2070 }
2071
ImplCheckTextLen(const String & rNewText)2072 sal_Bool TextView::ImplCheckTextLen( const String& rNewText )
2073 {
2074 sal_Bool bOK = sal_True;
2075 if ( mpImpl->mpTextEngine->GetMaxTextLen() )
2076 {
2077 sal_uLong n = mpImpl->mpTextEngine->GetTextLen();
2078 n += rNewText.Len();
2079 if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
2080 {
2081 // nur dann noch ermitteln, wie viel Text geloescht wird
2082 n -= mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
2083 if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
2084 {
2085 // Beep hat hier eigentlich nichts verloren, sondern lieber ein Hdl,
2086 // aber so funktioniert es wenigstens in ME, BasicIDE, SourceView
2087 Sound::Beep();
2088 bOK = sal_False;
2089 }
2090 }
2091 }
2092 return bOK;
2093 }
2094
dragGestureRecognized(const::com::sun::star::datatransfer::dnd::DragGestureEvent & rDGE)2095 void TextView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException)
2096 {
2097 if ( mpImpl->mbClickedInSelection )
2098 {
2099 vos::OGuard aVclGuard( Application::GetSolarMutex() );
2100
2101 DBG_ASSERT( mpImpl->maSelection.HasRange(), "TextView::dragGestureRecognized: mpImpl->mbClickedInSelection, but no selection?" );
2102
2103 delete mpImpl->mpDDInfo;
2104 mpImpl->mpDDInfo = new TextDDInfo;
2105 mpImpl->mpDDInfo->mbStarterOfDD = sal_True;
2106
2107 TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
2108
2109 if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) ) // Dann auch als HTML
2110 mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True );
2111
2112
2113 /*
2114 // D&D eines Hyperlinks.
2115 // Besser waere es im MBDown sich den MBDownPaM zu merken,
2116 // ist dann aber inkompatibel => spaeter mal umstellen.
2117 TextPaM aPaM( mpImpl->mpTextEngine->GetPaM( GetDocPos( GetWindow()->GetPointerPosPixel() ) ) );
2118 const TextCharAttrib* pAttr = mpImpl->mpTextEngine->FindCharAttrib( aPaM, TEXTATTR_HYPERLINK );
2119 if ( pAttr )
2120 {
2121 aSel = aPaM;
2122 aSel.GetStart().GetIndex() = pAttr->GetStart();
2123 aSel.GetEnd().GetIndex() = pAttr->GetEnd();
2124
2125 const TextAttribHyperLink& rLink = (const TextAttribHyperLink&)pAttr->GetAttr();
2126 String aText( rLink.GetDescription() );
2127 if ( !aText.Len() )
2128 aText = mpImpl->mpTextEngine->GetText( aSel );
2129 INetBookmark aBookmark( rLink.GetURL(), aText );
2130 aBookmark.CopyDragServer();
2131 }
2132 */
2133
2134 mpImpl->mpCursor->Hide();
2135
2136 sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY;
2137 if ( !IsReadOnly() )
2138 nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE;
2139 rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mpImpl->mxDnDListener );
2140 }
2141 }
2142
dragDropEnd(const::com::sun::star::datatransfer::dnd::DragSourceDropEvent &)2143 void TextView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& ) throw (::com::sun::star::uno::RuntimeException)
2144 {
2145 ImpHideDDCursor();
2146 delete mpImpl->mpDDInfo;
2147 mpImpl->mpDDInfo = NULL;
2148 }
2149
drop(const::com::sun::star::datatransfer::dnd::DropTargetDropEvent & rDTDE)2150 void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
2151 {
2152 vos::OGuard aVclGuard( Application::GetSolarMutex() );
2153
2154 sal_Bool bChanges = sal_False;
2155 if ( !mpImpl->mbReadOnly && mpImpl->mpDDInfo )
2156 {
2157 ImpHideDDCursor();
2158
2159 // Daten fuer das loeschen nach einem DROP_MOVE:
2160 TextSelection aPrevSel( mpImpl->maSelection );
2161 aPrevSel.Justify();
2162 sal_uLong nPrevParaCount = mpImpl->mpTextEngine->GetParagraphCount();
2163 sal_uInt16 nPrevStartParaLen = mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() );
2164
2165 sal_Bool bStarterOfDD = sal_False;
2166 for ( sal_uInt16 nView = mpImpl->mpTextEngine->GetViewCount(); nView && !bStarterOfDD; )
2167 bStarterOfDD = mpImpl->mpTextEngine->GetView( --nView )->mpImpl->mpDDInfo ? mpImpl->mpTextEngine->GetView( nView )->mpImpl->mpDDInfo->mbStarterOfDD : sal_False;
2168
2169 HideSelection();
2170 ImpSetSelection( mpImpl->mpDDInfo->maDropPos );
2171
2172 mpImpl->mpTextEngine->UndoActionStart();
2173
2174 String aText;
2175 uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
2176 if ( xDataObj.is() )
2177 {
2178 datatransfer::DataFlavor aFlavor;
2179 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
2180 if ( xDataObj->isDataFlavorSupported( aFlavor ) )
2181 {
2182 uno::Any aData = xDataObj->getTransferData( aFlavor );
2183 ::rtl::OUString aOUString;
2184 aData >>= aOUString;
2185 aText = aOUString;
2186 aText.ConvertLineEnd( LINEEND_LF );
2187 }
2188 }
2189
2190 if ( aText.Len() && ( aText.GetChar( aText.Len()-1 ) == LINE_SEP ) )
2191 aText.Erase( aText.Len()-1 );
2192
2193 TextPaM aTempStart = mpImpl->maSelection.GetStart();
2194 if ( ImplCheckTextLen( aText ) )
2195 ImpSetSelection( mpImpl->mpTextEngine->ImpInsertText( mpImpl->mpDDInfo->maDropPos, aText ) );
2196 if(mpImpl->mbSupportProtectAttribute)
2197 {
2198 mpImpl->mpTextEngine->SetAttrib( TextAttribProtect(),
2199 aTempStart.GetPara(),
2200 aTempStart.GetIndex(),
2201 mpImpl->maSelection.GetEnd().GetIndex(), sal_False );
2202 }
2203
2204 if ( aPrevSel.HasRange() &&
2205 !mpImpl->mbSupportProtectAttribute && // don't remove currently selected element
2206 (( rDTDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) || !bStarterOfDD) )
2207 {
2208 // ggf. Selection anpasssen:
2209 if ( ( mpImpl->mpDDInfo->maDropPos.GetPara() < aPrevSel.GetStart().GetPara() ) ||
2210 ( ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
2211 && ( mpImpl->mpDDInfo->maDropPos.GetIndex() < aPrevSel.GetStart().GetIndex() ) ) )
2212 {
2213 sal_uLong nNewParasBeforeSelection =
2214 mpImpl->mpTextEngine->GetParagraphCount() - nPrevParaCount;
2215
2216 aPrevSel.GetStart().GetPara() += nNewParasBeforeSelection;
2217 aPrevSel.GetEnd().GetPara() += nNewParasBeforeSelection;
2218
2219 if ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
2220 {
2221 sal_uInt16 nNewChars =
2222 mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() ) - nPrevStartParaLen;
2223
2224 aPrevSel.GetStart().GetIndex() =
2225 aPrevSel.GetStart().GetIndex() + nNewChars;
2226 if ( aPrevSel.GetStart().GetPara() == aPrevSel.GetEnd().GetPara() )
2227 aPrevSel.GetEnd().GetIndex() =
2228 aPrevSel.GetEnd().GetIndex() + nNewChars;
2229 }
2230 }
2231 else
2232 {
2233 // aktuelle Selektion anpassen
2234 TextPaM aPaM = mpImpl->maSelection.GetStart();
2235 aPaM.GetPara() -= ( aPrevSel.GetEnd().GetPara() - aPrevSel.GetStart().GetPara() );
2236 if ( aPrevSel.GetEnd().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
2237 {
2238 aPaM.GetIndex() =
2239 aPaM.GetIndex() - aPrevSel.GetEnd().GetIndex();
2240 if ( aPrevSel.GetStart().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
2241 aPaM.GetIndex() =
2242 aPaM.GetIndex() + aPrevSel.GetStart().GetIndex();
2243 }
2244 ImpSetSelection( aPaM );
2245
2246 }
2247 mpImpl->mpTextEngine->ImpDeleteText( aPrevSel );
2248 }
2249
2250 mpImpl->mpTextEngine->UndoActionEnd();
2251
2252 delete mpImpl->mpDDInfo;
2253 mpImpl->mpDDInfo = 0;
2254
2255 mpImpl->mpTextEngine->FormatAndUpdate( this );
2256
2257 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
2258 }
2259 rDTDE.Context->dropComplete( bChanges );
2260 }
2261
dragEnter(const::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent &)2262 void TextView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& ) throw (::com::sun::star::uno::RuntimeException)
2263 {
2264 }
2265
dragExit(const::com::sun::star::datatransfer::dnd::DropTargetEvent &)2266 void TextView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException)
2267 {
2268 vos::OGuard aVclGuard( Application::GetSolarMutex() );
2269 ImpHideDDCursor();
2270 }
2271
dragOver(const::com::sun::star::datatransfer::dnd::DropTargetDragEvent & rDTDE)2272 void TextView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
2273 {
2274 vos::OGuard aVclGuard( Application::GetSolarMutex() );
2275
2276 if ( !mpImpl->mpDDInfo )
2277 mpImpl->mpDDInfo = new TextDDInfo;
2278
2279 TextPaM aPrevDropPos = mpImpl->mpDDInfo->maDropPos;
2280 Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
2281 Point aDocPos = GetDocPos( aMousePos );
2282 mpImpl->mpDDInfo->maDropPos = mpImpl->mpTextEngine->GetPaM( aDocPos );
2283
2284 /*
2285 Size aOutSize = mpImpl->mpWindow->GetOutputSizePixel();
2286 if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) ||
2287 ( aMousePos.Y() < 0 ) || ( aMousePos.Y() > aOutSize.Height() ) )
2288 {
2289 // Scroll?
2290 // No, I will not receive events for this...
2291 }
2292 */
2293
2294 sal_Bool bProtected = sal_False;
2295 if(mpImpl->mbSupportProtectAttribute)
2296 {
2297 const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
2298 mpImpl->mpDDInfo->maDropPos,
2299 TEXTATTR_PROTECTED );
2300 bProtected = pStartAttr != 0 &&
2301 pStartAttr->GetStart() != mpImpl->mpDDInfo->maDropPos.GetIndex() &&
2302 pStartAttr->GetEnd() != mpImpl->mpDDInfo->maDropPos.GetIndex();
2303 }
2304 // Don't drop in selection or in read only engine
2305 if ( IsReadOnly() || IsInSelection( mpImpl->mpDDInfo->maDropPos ) || bProtected)
2306 {
2307 ImpHideDDCursor();
2308 rDTDE.Context->rejectDrag();
2309 }
2310 else
2311 {
2312 // Alten Cursor wegzeichnen...
2313 if ( !mpImpl->mpDDInfo->mbVisCursor || ( aPrevDropPos != mpImpl->mpDDInfo->maDropPos ) )
2314 {
2315 ImpHideDDCursor();
2316 ImpShowDDCursor();
2317 }
2318 rDTDE.Context->acceptDrag( rDTDE.DropAction );
2319 }
2320 }
2321
ImpGetOutputStartPos(const Point & rStartDocPos) const2322 Point TextView::ImpGetOutputStartPos( const Point& rStartDocPos ) const
2323 {
2324 Point aStartPos( -rStartDocPos.X(), -rStartDocPos.Y() );
2325 if ( mpImpl->mpTextEngine->IsRightToLeft() )
2326 {
2327 Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2328 aStartPos.X() = rStartDocPos.X() + aSz.Width() - 1; // -1: Start is 0
2329 }
2330 return aStartPos;
2331 }
2332
GetDocPos(const Point & rWindowPos) const2333 Point TextView::GetDocPos( const Point& rWindowPos ) const
2334 {
2335 // Fensterposition => Dokumentposition
2336
2337 Point aPoint;
2338
2339 aPoint.Y() = rWindowPos.Y() + mpImpl->maStartDocPos.Y();
2340
2341 if ( !mpImpl->mpTextEngine->IsRightToLeft() )
2342 {
2343 aPoint.X() = rWindowPos.X() + mpImpl->maStartDocPos.X();
2344 }
2345 else
2346 {
2347 Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2348 aPoint.X() = ( aSz.Width() - 1 ) - rWindowPos.X() + mpImpl->maStartDocPos.X();
2349 }
2350
2351 return aPoint;
2352 }
2353
GetWindowPos(const Point & rDocPos) const2354 Point TextView::GetWindowPos( const Point& rDocPos ) const
2355 {
2356 // Dokumentposition => Fensterposition
2357
2358 Point aPoint;
2359
2360 aPoint.Y() = rDocPos.Y() - mpImpl->maStartDocPos.Y();
2361
2362 if ( !mpImpl->mpTextEngine->IsRightToLeft() )
2363 {
2364 aPoint.X() = rDocPos.X() - mpImpl->maStartDocPos.X();
2365 }
2366 else
2367 {
2368 Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2369 aPoint.X() = ( aSz.Width() - 1 ) - ( rDocPos.X() - mpImpl->maStartDocPos.X() );
2370 }
2371
2372 return aPoint;
2373 }
2374
GetLineNumberOfCursorInSelection() const2375 sal_Int32 TextView::GetLineNumberOfCursorInSelection() const
2376 {
2377 // PROGRESS
2378 sal_Int32 nLineNo = -1;
2379 if( mpImpl->mbCursorEnabled )
2380 {
2381 TextPaM aPaM = GetSelection().GetEnd();
2382 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
2383 nLineNo = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
2384 if( mpImpl->mbCursorAtEndOfLine )
2385 --nLineNo;
2386 }
2387 return nLineNo;
2388 }
2389
2390
2391 // -------------------------------------------------------------------------
2392 // (+) class TextSelFunctionSet
2393 // -------------------------------------------------------------------------
TextSelFunctionSet(TextView * pView)2394 TextSelFunctionSet::TextSelFunctionSet( TextView* pView )
2395 {
2396 mpView = pView;
2397 }
2398
BeginDrag()2399 void __EXPORT TextSelFunctionSet::BeginDrag()
2400 {
2401 }
2402
CreateAnchor()2403 void __EXPORT TextSelFunctionSet::CreateAnchor()
2404 {
2405 // TextSelection aSel( mpView->GetSelection() );
2406 // aSel.GetStart() = aSel.GetEnd();
2407 // mpView->SetSelection( aSel );
2408
2409 // Es darf kein ShowCursor folgen:
2410 mpView->HideSelection();
2411 mpView->ImpSetSelection( mpView->mpImpl->maSelection.GetEnd() );
2412 }
2413
SetCursorAtPoint(const Point & rPointPixel,sal_Bool)2414 sal_Bool __EXPORT TextSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool )
2415 {
2416 return mpView->SetCursorAtPoint( rPointPixel );
2417 }
2418
IsSelectionAtPoint(const Point & rPointPixel)2419 sal_Bool __EXPORT TextSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
2420 {
2421 return mpView->IsSelectionAtPoint( rPointPixel );
2422 }
2423
DeselectAll()2424 void __EXPORT TextSelFunctionSet::DeselectAll()
2425 {
2426 CreateAnchor();
2427 }
2428
DeselectAtPoint(const Point &)2429 void __EXPORT TextSelFunctionSet::DeselectAtPoint( const Point& )
2430 {
2431 // Nur bei Mehrfachselektion
2432 }
2433
DestroyAnchor()2434 void __EXPORT TextSelFunctionSet::DestroyAnchor()
2435 {
2436 // Nur bei Mehrfachselektion
2437 }
GetTextEngine() const2438 TextEngine* TextView::GetTextEngine() const
2439 { return mpImpl->mpTextEngine; }
GetWindow() const2440 Window* TextView::GetWindow() const
2441 { return mpImpl->mpWindow; }
EnableCursor(sal_Bool bEnable)2442 void TextView::EnableCursor( sal_Bool bEnable )
2443 { mpImpl->mbCursorEnabled = bEnable; }
IsCursorEnabled() const2444 sal_Bool TextView::IsCursorEnabled() const
2445 { return mpImpl->mbCursorEnabled; }
SetStartDocPos(const Point & rPos)2446 void TextView::SetStartDocPos( const Point& rPos )
2447 { mpImpl->maStartDocPos = rPos; }
GetStartDocPos() const2448 const Point& TextView::GetStartDocPos() const
2449 { return mpImpl->maStartDocPos; }
SetAutoIndentMode(sal_Bool bAutoIndent)2450 void TextView::SetAutoIndentMode( sal_Bool bAutoIndent )
2451 { mpImpl->mbAutoIndent = bAutoIndent; }
IsAutoIndentMode() const2452 sal_Bool TextView::IsAutoIndentMode() const
2453 { return mpImpl->mbAutoIndent; }
IsReadOnly() const2454 sal_Bool TextView::IsReadOnly() const
2455 { return mpImpl->mbReadOnly; }
SetAutoScroll(sal_Bool bAutoScroll)2456 void TextView::SetAutoScroll( sal_Bool bAutoScroll )
2457 { mpImpl->mbAutoScroll = bAutoScroll; }
IsAutoScroll() const2458 sal_Bool TextView::IsAutoScroll() const
2459 { return mpImpl->mbAutoScroll; }
IsPaintSelection() const2460 sal_Bool TextView::IsPaintSelection() const
2461 { return mpImpl->mbPaintSelection; }
IsHighlightSelection() const2462 sal_Bool TextView::IsHighlightSelection() const
2463 { return mpImpl->mbHighlightSelection; }
HasSelection() const2464 sal_Bool TextView::HasSelection() const
2465 { return mpImpl->maSelection.HasRange(); }
IsInsertMode() const2466 sal_Bool TextView::IsInsertMode() const
2467 { return mpImpl->mbInsertMode; }
SupportProtectAttribute(sal_Bool bSupport)2468 void TextView::SupportProtectAttribute(sal_Bool bSupport)
2469 { mpImpl->mbSupportProtectAttribute = bSupport;}
2470
2471