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 GetWindow()->SetCursorRect( &aR1, nWidth );
1052 }
1053 else
1054 {
1055 GetWindow()->SetCursorRect();
1056 }
1057 }
1058 else
1059 {
1060 mpImpl->mpSelEngine->Command( rCEvt );
1061 }
1062 }
1063
ShowCursor(sal_Bool bGotoCursor,sal_Bool bForceVisCursor)1064 void TextView::ShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor )
1065 {
1066 // Die Einstellung hat mehr Gewicht:
1067 if ( !mpImpl->mbAutoScroll )
1068 bGotoCursor = sal_False;
1069 ImpShowCursor( bGotoCursor, bForceVisCursor, sal_False );
1070 }
1071
HideCursor()1072 void TextView::HideCursor()
1073 {
1074 mpImpl->mpCursor->Hide();
1075 }
1076
Scroll(long ndX,long ndY)1077 void TextView::Scroll( long ndX, long ndY )
1078 {
1079 DBG_ASSERT( mpImpl->mpTextEngine->IsFormatted(), "Scroll: Nicht formatiert!" );
1080
1081 if ( !ndX && !ndY )
1082 return;
1083
1084 Point aNewStartPos( mpImpl->maStartDocPos );
1085
1086 // Vertical:
1087 aNewStartPos.Y() -= ndY;
1088 if ( aNewStartPos.Y() < 0 )
1089 aNewStartPos.Y() = 0;
1090
1091 // Horizontal:
1092 aNewStartPos.X() -= ndX;
1093 if ( aNewStartPos.X() < 0 )
1094 aNewStartPos.X() = 0;
1095
1096 long nDiffX = mpImpl->maStartDocPos.X() - aNewStartPos.X();
1097 long nDiffY = mpImpl->maStartDocPos.Y() - aNewStartPos.Y();
1098
1099 if ( nDiffX || nDiffY )
1100 {
1101 sal_Bool bVisCursor = mpImpl->mpCursor->IsVisible();
1102 mpImpl->mpCursor->Hide();
1103 mpImpl->mpWindow->Update();
1104 mpImpl->maStartDocPos = aNewStartPos;
1105
1106 if ( mpImpl->mpTextEngine->IsRightToLeft() )
1107 nDiffX = -nDiffX;
1108 mpImpl->mpWindow->Scroll( nDiffX, nDiffY );
1109 mpImpl->mpWindow->Update();
1110 mpImpl->mpCursor->SetPos( mpImpl->mpCursor->GetPos() + Point( nDiffX, nDiffY ) );
1111 if ( bVisCursor && !mpImpl->mbReadOnly )
1112 mpImpl->mpCursor->Show();
1113 }
1114
1115 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_VIEWSCROLLED ) );
1116 }
1117
Undo()1118 void TextView::Undo()
1119 {
1120 mpImpl->mpTextEngine->SetActiveView( this );
1121 mpImpl->mpTextEngine->GetUndoManager().Undo();
1122 }
1123
Redo()1124 void TextView::Redo()
1125 {
1126 mpImpl->mpTextEngine->SetActiveView( this );
1127 mpImpl->mpTextEngine->GetUndoManager().Redo();
1128 }
1129
Cut()1130 void TextView::Cut()
1131 {
1132 mpImpl->mpTextEngine->UndoActionStart();
1133 Copy();
1134 DeleteSelected();
1135 mpImpl->mpTextEngine->UndoActionEnd();
1136 }
1137
Copy(uno::Reference<datatransfer::clipboard::XClipboard> & rxClipboard)1138 void TextView::Copy( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1139 {
1140 if ( rxClipboard.is() )
1141 {
1142 TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
1143
1144 if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) ) // Dann auch als HTML
1145 mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True );
1146
1147 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1148
1149 try
1150 {
1151 rxClipboard->setContents( pDataObj, NULL );
1152
1153 uno::Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( rxClipboard, uno::UNO_QUERY );
1154 if( xFlushableClipboard.is() )
1155 xFlushableClipboard->flushClipboard();
1156 }
1157 catch( const ::com::sun::star::uno::Exception& )
1158 {
1159 }
1160
1161 Application::AcquireSolarMutex( nRef );
1162 }
1163 }
1164
Copy()1165 void TextView::Copy()
1166 {
1167 uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
1168 Copy( aClipboard );
1169 }
1170
Paste(uno::Reference<datatransfer::clipboard::XClipboard> & rxClipboard)1171 void TextView::Paste( uno::Reference< datatransfer::clipboard::XClipboard >& rxClipboard )
1172 {
1173 if ( rxClipboard.is() )
1174 {
1175 uno::Reference< datatransfer::XTransferable > xDataObj;
1176
1177 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1178
1179 try
1180 {
1181 xDataObj = rxClipboard->getContents();
1182 }
1183 catch( const ::com::sun::star::uno::Exception& )
1184 {
1185 }
1186
1187 Application::AcquireSolarMutex( nRef );
1188
1189 if ( xDataObj.is() )
1190 {
1191 datatransfer::DataFlavor aFlavor;
1192 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
1193 if ( xDataObj->isDataFlavorSupported( aFlavor ) )
1194 {
1195 try
1196 {
1197 uno::Any aData = xDataObj->getTransferData( aFlavor );
1198 ::rtl::OUString aText;
1199 aData >>= aText;
1200 bool bWasTruncated = false;
1201 if( mpImpl->mpTextEngine->GetMaxTextLen() != 0 )
1202 bWasTruncated = ImplTruncateNewText( aText );
1203 InsertNewText( aText, sal_False );
1204 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
1205
1206 if( bWasTruncated )
1207 Edit::ShowTruncationWarning( mpImpl->mpWindow );
1208 }
1209 catch( const ::com::sun::star::datatransfer::UnsupportedFlavorException& )
1210 {
1211 }
1212 }
1213 }
1214 }
1215 }
1216
Paste()1217 void TextView::Paste()
1218 {
1219 uno::Reference<datatransfer::clipboard::XClipboard> aClipboard(GetWindow()->GetClipboard());
1220 Paste( aClipboard );
1221 }
1222
GetSelected()1223 String TextView::GetSelected()
1224 {
1225 return GetSelected( GetSystemLineEnd() );
1226 }
1227
GetSelected(LineEnd aSeparator)1228 String TextView::GetSelected( LineEnd aSeparator )
1229 {
1230 return mpImpl->mpTextEngine->GetText( mpImpl->maSelection, aSeparator );
1231 }
1232
SetInsertMode(sal_Bool bInsert)1233 void TextView::SetInsertMode( sal_Bool bInsert )
1234 {
1235 if ( mpImpl->mbInsertMode != bInsert )
1236 {
1237 mpImpl->mbInsertMode = bInsert;
1238 ShowCursor( mpImpl->mbAutoScroll, sal_False );
1239 }
1240 }
1241
SetReadOnly(sal_Bool bReadOnly)1242 void TextView::SetReadOnly( sal_Bool bReadOnly )
1243 {
1244 if ( mpImpl->mbReadOnly != bReadOnly )
1245 {
1246 mpImpl->mbReadOnly = bReadOnly;
1247 if ( !mpImpl->mbReadOnly )
1248 ShowCursor( mpImpl->mbAutoScroll, sal_False );
1249 else
1250 HideCursor();
1251
1252 GetWindow()->SetInputContext( InputContext( mpImpl->mpTextEngine->GetFont(), bReadOnly ? INPUTCONTEXT_TEXT|INPUTCONTEXT_EXTTEXTINPUT : 0 ) );
1253 }
1254 }
1255
ImpMoveCursor(const KeyEvent & rKeyEvent)1256 TextSelection TextView::ImpMoveCursor( const KeyEvent& rKeyEvent )
1257 {
1258 // Eigentlich nur bei Up/Down noetig, aber was solls.
1259 mpImpl->mpTextEngine->CheckIdleFormatter();
1260
1261 TextPaM aPaM( mpImpl->maSelection.GetEnd() );
1262 TextPaM aOldEnd( aPaM );
1263
1264 TextDirectionality eTextDirection = TextDirectionality_LeftToRight_TopToBottom;
1265 if ( mpImpl->mpTextEngine->IsRightToLeft() )
1266 eTextDirection = TextDirectionality_RightToLeft_TopToBottom;
1267
1268 KeyEvent aTranslatedKeyEvent = rKeyEvent.LogicalTextDirectionality( eTextDirection );
1269
1270 sal_Bool bCtrl = aTranslatedKeyEvent.GetKeyCode().IsMod1() ? sal_True : sal_False;
1271 sal_uInt16 nCode = aTranslatedKeyEvent.GetKeyCode().GetCode();
1272
1273 bool bSelect = aTranslatedKeyEvent.GetKeyCode().IsShift();
1274 switch ( nCode )
1275 {
1276 case KEY_UP: aPaM = CursorUp( aPaM );
1277 break;
1278 case KEY_DOWN: aPaM = CursorDown( aPaM );
1279 break;
1280 case KEY_HOME: aPaM = bCtrl ? CursorStartOfDoc() : CursorStartOfLine( aPaM );
1281 break;
1282 case KEY_END: aPaM = bCtrl ? CursorEndOfDoc() : CursorEndOfLine( aPaM );
1283 break;
1284 case KEY_PAGEUP: aPaM = bCtrl ? CursorStartOfDoc() : PageUp( aPaM );
1285 break;
1286 case KEY_PAGEDOWN: aPaM = bCtrl ? CursorEndOfDoc() : PageDown( aPaM );
1287 break;
1288 case KEY_LEFT: aPaM = bCtrl ? CursorWordLeft( aPaM ) : CursorLeft( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1289 break;
1290 case KEY_RIGHT: aPaM = bCtrl ? CursorWordRight( aPaM ) : CursorRight( aPaM, aTranslatedKeyEvent.GetKeyCode().IsMod2() ? (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER : (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1291 break;
1292 case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
1293 bSelect = true; // fallthrough intentional
1294 case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
1295 aPaM = CursorWordRight( aPaM );
1296 break;
1297 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
1298 bSelect = true; // fallthrough intentional
1299 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
1300 aPaM = CursorWordLeft( aPaM );
1301 break;
1302 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
1303 bSelect = true; // fallthrough intentional
1304 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
1305 aPaM = CursorStartOfLine( aPaM );
1306 break;
1307 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
1308 bSelect = true; // fallthrough intentional
1309 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
1310 aPaM = CursorEndOfLine( aPaM );
1311 break;
1312 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
1313 bSelect = true; // falltthrough intentional
1314 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
1315 aPaM = CursorStartOfParagraph( aPaM );
1316 break;
1317 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
1318 bSelect = true; // falltthrough intentional
1319 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
1320 aPaM = CursorEndOfParagraph( aPaM );
1321 break;
1322 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
1323 bSelect = true; // falltthrough intentional
1324 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
1325 aPaM = CursorStartOfDoc();
1326 break;
1327 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
1328 bSelect = true; // falltthrough intentional
1329 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
1330 aPaM = CursorEndOfDoc();
1331 break;
1332 }
1333
1334 // Bewirkt evtl. ein CreateAnchor oder Deselection all
1335 mpImpl->mpSelEngine->CursorPosChanging( bSelect, aTranslatedKeyEvent.GetKeyCode().IsMod1() );
1336
1337 if ( aOldEnd != aPaM )
1338 {
1339 mpImpl->mpTextEngine->CursorMoved( aOldEnd.GetPara() );
1340
1341
1342 TextSelection aOldSelection( mpImpl->maSelection );
1343 TextSelection aNewSelection( mpImpl->maSelection );
1344 aNewSelection.GetEnd() = aPaM;
1345 if ( bSelect )
1346 {
1347 // Dann wird die Selektion erweitert...
1348 ImpSetSelection( aNewSelection );
1349 ShowSelection( TextSelection( aOldEnd, aPaM ) );
1350 }
1351 else
1352 {
1353 aNewSelection.GetStart() = aPaM;
1354 ImpSetSelection( aNewSelection );
1355 }
1356 }
1357
1358 return mpImpl->maSelection;
1359 }
1360
InsertText(const XubString & rStr,sal_Bool bSelect)1361 void TextView::InsertText( const XubString& rStr, sal_Bool bSelect )
1362 {
1363 InsertNewText( rStr, bSelect );
1364 }
1365
InsertNewText(const rtl::OUString & rStr,sal_Bool bSelect)1366 void TextView::InsertNewText( const rtl::OUString& rStr, sal_Bool bSelect )
1367 {
1368 // HideSelection();
1369 mpImpl->mpTextEngine->UndoActionStart();
1370
1371 /* #i87633#
1372 break inserted text into chunks that fit into the underlying String
1373 based API (which has a maximum length of 65534 elements
1374
1375 note: this will of course still cause problems for lines longer than those
1376 65534 elements, but those cases will hopefully be few.
1377 In the long run someone should switch the TextEngine to OUString instead of String
1378 */
1379 sal_Int32 nLen = rStr.getLength();
1380 sal_Int32 nPos = 0;
1381 do
1382 {
1383 sal_Int32 nChunkLen = nLen > 65534 ? 65534 : nLen;
1384 String aChunk( rStr.copy( nPos, nChunkLen ) );
1385
1386 TextSelection aNewSel( mpImpl->maSelection );
1387
1388 TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, aChunk );
1389
1390 if ( bSelect )
1391 {
1392 aNewSel.Justify();
1393 aNewSel.GetEnd() = aPaM;
1394 }
1395 else
1396 {
1397 aNewSel = aPaM;
1398 }
1399
1400 ImpSetSelection( aNewSel );
1401 nLen -= nChunkLen;
1402 nPos += nChunkLen;
1403 } while( nLen );
1404 mpImpl->mpTextEngine->UndoActionEnd();
1405
1406 mpImpl->mpTextEngine->FormatAndUpdate( this );
1407 }
1408
1409 /*
1410 void TextView::InsertText( const XubString& rStr, sal_Bool bSelect )
1411 {
1412 // HideSelection();
1413
1414 TextSelection aNewSel( mpImpl->maSelection );
1415
1416 mpImpl->mpTextEngine->UndoActionStart();
1417 TextPaM aPaM = mpImpl->mpTextEngine->ImpInsertText( mpImpl->maSelection, rStr );
1418 mpImpl->mpTextEngine->UndoActionEnd();
1419
1420 if ( bSelect )
1421 {
1422 aNewSel.Justify();
1423 aNewSel.GetEnd() = aPaM;
1424 }
1425 else
1426 {
1427 aNewSel = aPaM;
1428 }
1429
1430 ImpSetSelection( aNewSel );
1431
1432 mpImpl->mpTextEngine->FormatAndUpdate( this );
1433 }
1434 */
1435
1436 // OLD
CursorLeft(const TextPaM & rPaM,sal_Bool bWordMode)1437 TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_Bool bWordMode )
1438 {
1439 return bWordMode ? CursorWordLeft( rPaM ) : CursorLeft( rPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1440
1441 // Remove (sal_uInt16) typecasts in this file when removing this method!
1442 }
1443
1444 // OLD
CursorRight(const TextPaM & rPaM,sal_Bool bWordMode)1445 TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_Bool bWordMode )
1446 {
1447 return bWordMode ? CursorWordRight( rPaM ) : CursorRight( rPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1448
1449 // Remove (sal_uInt16) typecasts in this file when removing this method!
1450 }
1451
CursorLeft(const TextPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1452 TextPaM TextView::CursorLeft( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1453 {
1454 TextPaM aPaM( rPaM );
1455
1456 if ( aPaM.GetIndex() )
1457 {
1458 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1459 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1460 sal_Int32 nCount = 1;
1461 aPaM.GetIndex() = (sal_uInt16)xBI->previousCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
1462 }
1463 else if ( aPaM.GetPara() )
1464 {
1465 aPaM.GetPara()--;
1466 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1467 aPaM.GetIndex() = pNode->GetText().Len();
1468 }
1469 return aPaM;
1470 }
1471
CursorRight(const TextPaM & rPaM,sal_uInt16 nCharacterIteratorMode)1472 TextPaM TextView::CursorRight( const TextPaM& rPaM, sal_uInt16 nCharacterIteratorMode )
1473 {
1474 TextPaM aPaM( rPaM );
1475
1476 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1477 if ( aPaM.GetIndex() < pNode->GetText().Len() )
1478 {
1479 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1480 sal_Int32 nCount = 1;
1481 aPaM.GetIndex() = (sal_uInt16)xBI->nextCharacters( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), nCharacterIteratorMode, nCount, nCount );
1482 }
1483 else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
1484 {
1485 aPaM.GetPara()++;
1486 aPaM.GetIndex() = 0;
1487 }
1488
1489 return aPaM;
1490 }
1491
1492
CursorWordLeft(const TextPaM & rPaM)1493 TextPaM TextView::CursorWordLeft( const TextPaM& rPaM )
1494 {
1495 TextPaM aPaM( rPaM );
1496
1497 if ( aPaM.GetIndex() )
1498 {
1499 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1500 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1501 i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1502 if ( aBoundary.startPos >= rPaM.GetIndex() )
1503 aBoundary = xBI->previousWord( pNode->GetText(), rPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1504 aPaM.GetIndex() = ( aBoundary.startPos != -1 ) ? (sal_uInt16)aBoundary.startPos : 0;
1505 }
1506 else if ( aPaM.GetPara() )
1507 {
1508 aPaM.GetPara()--;
1509 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1510 aPaM.GetIndex() = pNode->GetText().Len();
1511 }
1512 return aPaM;
1513 }
1514
1515
CursorWordRight(const TextPaM & rPaM)1516 TextPaM TextView::CursorWordRight( const TextPaM& rPaM )
1517 {
1518 TextPaM aPaM( rPaM );
1519
1520 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1521 if ( aPaM.GetIndex() < pNode->GetText().Len() )
1522 {
1523 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1524 i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), aPaM.GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1525 aPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
1526 }
1527 else if ( aPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count()-1) )
1528 {
1529 aPaM.GetPara()++;
1530 aPaM.GetIndex() = 0;
1531 }
1532
1533 return aPaM;
1534 }
1535
ImpDelete(sal_uInt8 nMode,sal_uInt8 nDelMode)1536 TextPaM TextView::ImpDelete( sal_uInt8 nMode, sal_uInt8 nDelMode )
1537 {
1538 if ( mpImpl->maSelection.HasRange() ) // dann nur Sel. loeschen
1539 return mpImpl->mpTextEngine->ImpDeleteText( mpImpl->maSelection );
1540
1541 TextPaM aStartPaM = mpImpl->maSelection.GetStart();
1542 TextPaM aEndPaM = aStartPaM;
1543 if ( nMode == DEL_LEFT )
1544 {
1545 if ( nDelMode == DELMODE_SIMPLE )
1546 {
1547 aEndPaM = CursorLeft( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCHARACTER );
1548 }
1549 else if ( nDelMode == DELMODE_RESTOFWORD )
1550 {
1551 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1552 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1553 i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True );
1554 if ( aBoundary.startPos == mpImpl->maSelection.GetEnd().GetIndex() )
1555 aBoundary = xBI->previousWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1556 // #i63506# startPos is -1 when the paragraph starts with a tab
1557 aEndPaM.GetIndex() = (aBoundary.startPos >= 0) ? (sal_uInt16)aBoundary.startPos : 0;
1558 }
1559 else // DELMODE_RESTOFCONTENT
1560 {
1561 if ( aEndPaM.GetIndex() != 0 )
1562 aEndPaM.GetIndex() = 0;
1563 else if ( aEndPaM.GetPara() )
1564 {
1565 // Absatz davor
1566 aEndPaM.GetPara()--;
1567 aEndPaM.GetIndex() = 0;
1568 }
1569 }
1570 }
1571 else
1572 {
1573 if ( nDelMode == DELMODE_SIMPLE )
1574 {
1575 aEndPaM = CursorRight( aEndPaM, (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1576 }
1577 else if ( nDelMode == DELMODE_RESTOFWORD )
1578 {
1579 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1580 uno::Reference < i18n::XBreakIterator > xBI = mpImpl->mpTextEngine->GetBreakIterator();
1581 i18n::Boundary aBoundary = xBI->nextWord( pNode->GetText(), mpImpl->maSelection.GetEnd().GetIndex(), mpImpl->mpTextEngine->GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES );
1582 aEndPaM.GetIndex() = (sal_uInt16)aBoundary.startPos;
1583 }
1584 else // DELMODE_RESTOFCONTENT
1585 {
1586 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1587 if ( aEndPaM.GetIndex() < pNode->GetText().Len() )
1588 aEndPaM.GetIndex() = pNode->GetText().Len();
1589 else if ( aEndPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) )
1590 {
1591 // Absatz danach
1592 aEndPaM.GetPara()++;
1593 TextNode* pNextNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aEndPaM.GetPara() );
1594 aEndPaM.GetIndex() = pNextNode->GetText().Len();
1595 }
1596 }
1597 }
1598
1599 return mpImpl->mpTextEngine->ImpDeleteText( TextSelection( aStartPaM, aEndPaM ) );
1600 }
1601
1602
1603
CursorUp(const TextPaM & rPaM)1604 TextPaM TextView::CursorUp( const TextPaM& rPaM )
1605 {
1606 TextPaM aPaM( rPaM );
1607
1608 long nX;
1609 if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
1610 {
1611 nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left();
1612 mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
1613 }
1614 else
1615 nX = mpImpl->mnTravelXPos;
1616
1617 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1618 sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False );
1619 if ( nLine ) // gleicher Absatz
1620 {
1621 sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine-1, nX );
1622 aPaM.GetIndex() = nCharPos;
1623 // Wenn davor eine autom.Umgebrochene Zeile, und ich muss genau an das
1624 // Ende dieser Zeile, landet der Cursor in der aktuellen Zeile am Anfang
1625 // Siehe Problem: Letztes Zeichen einer autom.umgebr. Zeile = Cursor
1626 TextLine* pLine = pPPortion->GetLines().GetObject( nLine - 1 );
1627 if ( aPaM.GetIndex() && ( aPaM.GetIndex() == pLine->GetEnd() ) )
1628 aPaM.GetIndex()--;
1629 }
1630 else if ( rPaM.GetPara() ) // vorheriger Absatz
1631 {
1632 aPaM.GetPara()--;
1633 pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1634 sal_uInt16 nL = pPPortion->GetLines().Count() - 1;
1635 sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), nL, nX+1 );
1636 aPaM.GetIndex() = nCharPos;
1637 }
1638
1639 return aPaM;
1640 }
1641
CursorDown(const TextPaM & rPaM)1642 TextPaM TextView::CursorDown( const TextPaM& rPaM )
1643 {
1644 TextPaM aPaM( rPaM );
1645
1646 long nX;
1647 if ( mpImpl->mnTravelXPos == TRAVEL_X_DONTKNOW )
1648 {
1649 nX = mpImpl->mpTextEngine->GetEditCursor( rPaM, sal_False ).Left();
1650 mpImpl->mnTravelXPos = (sal_uInt16)nX+1;
1651 }
1652 else
1653 nX = mpImpl->mnTravelXPos;
1654
1655 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1656 sal_uInt16 nLine = pPPortion->GetLineNumber( rPaM.GetIndex(), sal_False );
1657 if ( nLine < ( pPPortion->GetLines().Count() - 1 ) )
1658 {
1659 sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( rPaM.GetPara(), nLine+1, nX );
1660 aPaM.GetIndex() = nCharPos;
1661
1662 // Sonderbehandlung siehe CursorUp...
1663 TextLine* pLine = pPPortion->GetLines().GetObject( nLine + 1 );
1664 if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && aPaM.GetIndex() < pPPortion->GetNode()->GetText().Len() )
1665 aPaM.GetIndex()--;
1666 }
1667 else if ( rPaM.GetPara() < ( mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1 ) ) // naechster Absatz
1668 {
1669 aPaM.GetPara()++;
1670 pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1671 sal_uInt16 nCharPos = mpImpl->mpTextEngine->GetCharPos( aPaM.GetPara(), 0, nX+1 );
1672 aPaM.GetIndex() = nCharPos;
1673 TextLine* pLine = pPPortion->GetLines().GetObject( 0 );
1674 if ( ( aPaM.GetIndex() == pLine->GetEnd() ) && ( aPaM.GetIndex() > pLine->GetStart() ) && ( pPPortion->GetLines().Count() > 1 ) )
1675 aPaM.GetIndex()--;
1676 }
1677
1678 return aPaM;
1679 }
1680
CursorStartOfLine(const TextPaM & rPaM)1681 TextPaM TextView::CursorStartOfLine( const TextPaM& rPaM )
1682 {
1683 TextPaM aPaM( rPaM );
1684
1685 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1686 sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1687 TextLine* pLine = pPPortion->GetLines().GetObject( nLine );
1688 aPaM.GetIndex() = pLine->GetStart();
1689
1690 return aPaM;
1691 }
1692
CursorEndOfLine(const TextPaM & rPaM)1693 TextPaM TextView::CursorEndOfLine( const TextPaM& rPaM )
1694 {
1695 TextPaM aPaM( rPaM );
1696
1697 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( rPaM.GetPara() );
1698 sal_uInt16 nLine = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1699 TextLine* pLine = pPPortion->GetLines().GetObject( nLine );
1700 aPaM.GetIndex() = pLine->GetEnd();
1701
1702 if ( pLine->GetEnd() > pLine->GetStart() ) // Leerzeile
1703 {
1704 xub_Unicode cLastChar = pPPortion->GetNode()->GetText().GetChar((sal_uInt16)(aPaM.GetIndex()-1) );
1705 if ( ( cLastChar == ' ' ) && ( aPaM.GetIndex() != pPPortion->GetNode()->GetText().Len() ) )
1706 {
1707 // Bei einem Blank in einer autom. umgebrochenen Zeile macht es Sinn,
1708 // davor zu stehen, da der Anwender hinter das Wort will.
1709 // Wenn diese geaendert wird, Sonderbehandlung fuer Pos1 nach End!
1710 aPaM.GetIndex()--;
1711 }
1712 }
1713 return aPaM;
1714 }
1715
CursorStartOfParagraph(const TextPaM & rPaM)1716 TextPaM TextView::CursorStartOfParagraph( const TextPaM& rPaM )
1717 {
1718 TextPaM aPaM( rPaM );
1719 aPaM.GetIndex() = 0;
1720 return aPaM;
1721 }
1722
CursorEndOfParagraph(const TextPaM & rPaM)1723 TextPaM TextView::CursorEndOfParagraph( const TextPaM& rPaM )
1724 {
1725 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( rPaM.GetPara() );
1726 TextPaM aPaM( rPaM );
1727 aPaM.GetIndex() = pNode->GetText().Len();
1728 return aPaM;
1729 }
1730
CursorStartOfDoc()1731 TextPaM TextView::CursorStartOfDoc()
1732 {
1733 TextPaM aPaM( 0, 0 );
1734 return aPaM;
1735 }
1736
CursorEndOfDoc()1737 TextPaM TextView::CursorEndOfDoc()
1738 {
1739 sal_uLong nNode = mpImpl->mpTextEngine->mpDoc->GetNodes().Count() - 1;
1740 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( nNode );
1741 TextPaM aPaM( nNode, pNode->GetText().Len() );
1742 return aPaM;
1743 }
1744
PageUp(const TextPaM & rPaM)1745 TextPaM TextView::PageUp( const TextPaM& rPaM )
1746 {
1747 Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
1748 Point aTopLeft = aRec.TopLeft();
1749 aTopLeft.Y() -= mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
1750 aTopLeft.X() += 1;
1751 if ( aTopLeft.Y() < 0 )
1752 aTopLeft.Y() = 0;
1753
1754 TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aTopLeft );
1755 return aPaM;
1756 }
1757
PageDown(const TextPaM & rPaM)1758 TextPaM TextView::PageDown( const TextPaM& rPaM )
1759 {
1760 Rectangle aRec = mpImpl->mpTextEngine->PaMtoEditCursor( rPaM );
1761 Point aBottomRight = aRec.BottomRight();
1762 aBottomRight.Y() += mpImpl->mpWindow->GetOutputSizePixel().Height() * 9/10;
1763 aBottomRight.X() += 1;
1764 long nHeight = mpImpl->mpTextEngine->GetTextHeight();
1765 if ( aBottomRight.Y() > nHeight )
1766 aBottomRight.Y() = nHeight-1;
1767
1768 TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aBottomRight );
1769 return aPaM;
1770 }
1771
ImpShowCursor(sal_Bool bGotoCursor,sal_Bool bForceVisCursor,sal_Bool bSpecial)1772 void TextView::ImpShowCursor( sal_Bool bGotoCursor, sal_Bool bForceVisCursor, sal_Bool bSpecial )
1773 {
1774 if ( mpImpl->mpTextEngine->IsFormatting() )
1775 return;
1776 if ( mpImpl->mpTextEngine->GetUpdateMode() == sal_False )
1777 return;
1778 if ( mpImpl->mpTextEngine->IsInUndo() )
1779 return;
1780
1781 mpImpl->mpTextEngine->CheckIdleFormatter();
1782 if ( !mpImpl->mpTextEngine->IsFormatted() )
1783 mpImpl->mpTextEngine->FormatAndUpdate( this );
1784
1785
1786 TextPaM aPaM( mpImpl->maSelection.GetEnd() );
1787 Rectangle aEditCursor = mpImpl->mpTextEngine->PaMtoEditCursor( aPaM, bSpecial );
1788
1789 // Remember that we placed the cursor behind the last character of a line
1790 mpImpl->mbCursorAtEndOfLine = false;
1791 if( bSpecial )
1792 {
1793 TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1794 mpImpl->mbCursorAtEndOfLine =
1795 pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_True ) != pParaPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
1796 }
1797
1798 if ( !IsInsertMode() && !mpImpl->maSelection.HasRange() )
1799 {
1800 TextNode* pNode = mpImpl->mpTextEngine->mpDoc->GetNodes().GetObject( aPaM.GetPara() );
1801 if ( pNode->GetText().Len() && ( aPaM.GetIndex() < pNode->GetText().Len() ) )
1802 {
1803 // If we are behind a portion, and the next portion has other direction, we must change position...
1804 aEditCursor.Left() = aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aPaM, sal_False, sal_True ).Left();
1805
1806 TEParaPortion* pParaPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
1807
1808 sal_uInt16 nTextPortionStart = 0;
1809 sal_uInt16 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, sal_True );
1810 TETextPortion* pTextPortion = pParaPortion->GetTextPortions().GetObject( nTextPortion );
1811 if ( pTextPortion->GetKind() == PORTIONKIND_TAB )
1812 {
1813 if ( mpImpl->mpTextEngine->IsRightToLeft() )
1814 {
1815
1816 }
1817 aEditCursor.Right() += pTextPortion->GetWidth();
1818 }
1819 else
1820 {
1821 TextPaM aNext = CursorRight( TextPaM( aPaM.GetPara(), aPaM.GetIndex() ), (sal_uInt16)i18n::CharacterIteratorMode::SKIPCELL );
1822 aEditCursor.Right() = mpImpl->mpTextEngine->GetEditCursor( aNext, sal_True ).Left();
1823 }
1824 }
1825 }
1826
1827 Size aOutSz = mpImpl->mpWindow->GetOutputSizePixel();
1828 if ( aEditCursor.GetHeight() > aOutSz.Height() )
1829 aEditCursor.Bottom() = aEditCursor.Top() + aOutSz.Height() - 1;
1830
1831 aEditCursor.Left() -= 1;
1832
1833 if ( bGotoCursor
1834 // #i81283# protext maStartDocPos against initialization problems
1835 && aOutSz.Width() && aOutSz.Height()
1836 )
1837 {
1838 long nVisStartY = mpImpl->maStartDocPos.Y();
1839 long nVisEndY = mpImpl->maStartDocPos.Y() + aOutSz.Height();
1840 long nVisStartX = mpImpl->maStartDocPos.X();
1841 long nVisEndX = mpImpl->maStartDocPos.X() + aOutSz.Width();
1842 long nMoreX = aOutSz.Width() / 4;
1843
1844 Point aNewStartPos( mpImpl->maStartDocPos );
1845
1846 if ( aEditCursor.Bottom() > nVisEndY )
1847 {
1848 aNewStartPos.Y() += ( aEditCursor.Bottom() - nVisEndY );
1849 }
1850 else if ( aEditCursor.Top() < nVisStartY )
1851 {
1852 aNewStartPos.Y() -= ( nVisStartY - aEditCursor.Top() );
1853 }
1854
1855 if ( aEditCursor.Right() >= nVisEndX )
1856 {
1857 aNewStartPos.X() += ( aEditCursor.Right() - nVisEndX );
1858
1859 // Darfs ein bischen mehr sein?
1860 aNewStartPos.X() += nMoreX;
1861 }
1862 else if ( aEditCursor.Left() <= nVisStartX )
1863 {
1864 aNewStartPos.X() -= ( nVisStartX - aEditCursor.Left() );
1865
1866 // Darfs ein bischen mehr sein?
1867 aNewStartPos.X() -= nMoreX;
1868 }
1869
1870 // X kann durch das 'bischen mehr' falsch sein:
1871 // sal_uLong nMaxTextWidth = mpImpl->mpTextEngine->GetMaxTextWidth();
1872 // if ( !nMaxTextWidth || ( nMaxTextWidth > 0x7FFFFFFF ) )
1873 // nMaxTextWidth = 0x7FFFFFFF;
1874 // long nMaxX = (long)nMaxTextWidth - aOutSz.Width();
1875 long nMaxX = mpImpl->mpTextEngine->CalcTextWidth() - aOutSz.Width();
1876 if ( nMaxX < 0 )
1877 nMaxX = 0;
1878
1879 if ( aNewStartPos.X() < 0 )
1880 aNewStartPos.X() = 0;
1881 else if ( aNewStartPos.X() > nMaxX )
1882 aNewStartPos.X() = nMaxX;
1883
1884 // Y sollte nicht weiter unten als noetig liegen:
1885 long nYMax = mpImpl->mpTextEngine->GetTextHeight() - aOutSz.Height();
1886 if ( nYMax < 0 )
1887 nYMax = 0;
1888 if ( aNewStartPos.Y() > nYMax )
1889 aNewStartPos.Y() = nYMax;
1890
1891 if ( aNewStartPos != mpImpl->maStartDocPos )
1892 Scroll( -(aNewStartPos.X() - mpImpl->maStartDocPos.X()), -(aNewStartPos.Y() - mpImpl->maStartDocPos.Y()) );
1893 }
1894
1895 if ( aEditCursor.Right() < aEditCursor.Left() )
1896 {
1897 long n = aEditCursor.Left();
1898 aEditCursor.Left() = aEditCursor.Right();
1899 aEditCursor.Right() = n;
1900 }
1901
1902 Point aPoint( GetWindowPos( !mpImpl->mpTextEngine->IsRightToLeft() ? aEditCursor.TopLeft() : aEditCursor.TopRight() ) );
1903 mpImpl->mpCursor->SetPos( aPoint );
1904 mpImpl->mpCursor->SetSize( aEditCursor.GetSize() );
1905 if ( bForceVisCursor && mpImpl->mbCursorEnabled )
1906 mpImpl->mpCursor->Show();
1907 }
1908
SetCursorAtPoint(const Point & rPosPixel)1909 sal_Bool TextView::SetCursorAtPoint( const Point& rPosPixel )
1910 {
1911 mpImpl->mpTextEngine->CheckIdleFormatter();
1912
1913 Point aDocPos = GetDocPos( rPosPixel );
1914
1915 TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos );
1916
1917 // aTmpNewSel: Diff zwischen alt und neu, nicht die neue Selektion
1918 TextSelection aTmpNewSel( mpImpl->maSelection.GetEnd(), aPaM );
1919 TextSelection aNewSel( mpImpl->maSelection );
1920 aNewSel.GetEnd() = aPaM;
1921
1922 if ( !mpImpl->mpSelEngine->HasAnchor() )
1923 {
1924 if ( mpImpl->maSelection.GetStart() != aPaM )
1925 mpImpl->mpTextEngine->CursorMoved( mpImpl->maSelection.GetStart().GetPara() );
1926 aNewSel.GetStart() = aPaM;
1927 ImpSetSelection( aNewSel );
1928 }
1929 else
1930 {
1931 ImpSetSelection( aNewSel );
1932 ShowSelection( aTmpNewSel );
1933 }
1934
1935 sal_Bool bForceCursor = mpImpl->mpDDInfo ? sal_False : sal_True; // && !mbInSelection
1936 ImpShowCursor( mpImpl->mbAutoScroll, bForceCursor, sal_False );
1937 return sal_True;
1938 }
1939
IsSelectionAtPoint(const Point & rPosPixel)1940 sal_Bool TextView::IsSelectionAtPoint( const Point& rPosPixel )
1941 {
1942 // if ( !Rectangle( Point(), mpImpl->mpWindow->GetOutputSizePixel() ).IsInside( rPosPixel ) && !mbInSelection )
1943 // return sal_False;
1944
1945 Point aDocPos = GetDocPos( rPosPixel );
1946 TextPaM aPaM = mpImpl->mpTextEngine->GetPaM( aDocPos, sal_False );
1947 // Bei Hyperlinks D&D auch ohne Selektion starten.
1948 // BeginDrag wird aber nur gerufen, wenn IsSelectionAtPoint()
1949 // Problem: IsSelectionAtPoint wird bei Command() nicht gerufen,
1950 // wenn vorher im MBDown schon sal_False returnt wurde.
1951 return ( IsInSelection( aPaM ) ||
1952 ( /* mpImpl->mpSelEngine->IsInCommand() && */ mpImpl->mpTextEngine->FindAttrib( aPaM, TEXTATTR_HYPERLINK ) ) );
1953 }
1954
IsInSelection(const TextPaM & rPaM)1955 sal_Bool TextView::IsInSelection( const TextPaM& rPaM )
1956 {
1957 TextSelection aSel = mpImpl->maSelection;
1958 aSel.Justify();
1959
1960 sal_uLong nStartNode = aSel.GetStart().GetPara();
1961 sal_uLong nEndNode = aSel.GetEnd().GetPara();
1962 sal_uLong nCurNode = rPaM.GetPara();
1963
1964 if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) )
1965 return sal_True;
1966
1967 if ( nStartNode == nEndNode )
1968 {
1969 if ( nCurNode == nStartNode )
1970 if ( ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
1971 return sal_True;
1972 }
1973 else if ( ( nCurNode == nStartNode ) && ( rPaM.GetIndex() >= aSel.GetStart().GetIndex() ) )
1974 return sal_True;
1975 else if ( ( nCurNode == nEndNode ) && ( rPaM.GetIndex() < aSel.GetEnd().GetIndex() ) )
1976 return sal_True;
1977
1978 return sal_False;
1979 }
1980
ImpHideDDCursor()1981 void TextView::ImpHideDDCursor()
1982 {
1983 if ( mpImpl->mpDDInfo && mpImpl->mpDDInfo->mbVisCursor )
1984 {
1985 mpImpl->mpDDInfo->maCursor.Hide();
1986 mpImpl->mpDDInfo->mbVisCursor = sal_False;
1987 }
1988 }
1989
ImpShowDDCursor()1990 void TextView::ImpShowDDCursor()
1991 {
1992 if ( !mpImpl->mpDDInfo->mbVisCursor )
1993 {
1994 Rectangle aCursor = mpImpl->mpTextEngine->PaMtoEditCursor( mpImpl->mpDDInfo->maDropPos, sal_True );
1995 aCursor.Right()++;
1996 aCursor.SetPos( GetWindowPos( aCursor.TopLeft() ) );
1997
1998 mpImpl->mpDDInfo->maCursor.SetWindow( mpImpl->mpWindow );
1999 mpImpl->mpDDInfo->maCursor.SetPos( aCursor.TopLeft() );
2000 mpImpl->mpDDInfo->maCursor.SetSize( aCursor.GetSize() );
2001 mpImpl->mpDDInfo->maCursor.Show();
2002 mpImpl->mpDDInfo->mbVisCursor = sal_True;
2003 }
2004 }
2005
SetPaintSelection(sal_Bool bPaint)2006 void TextView::SetPaintSelection( sal_Bool bPaint )
2007 {
2008 if ( bPaint != mpImpl->mbPaintSelection )
2009 {
2010 mpImpl->mbPaintSelection = bPaint;
2011 ShowSelection( mpImpl->maSelection );
2012 }
2013 }
2014
SetHighlightSelection(sal_Bool bSelectByHighlight)2015 void TextView::SetHighlightSelection( sal_Bool bSelectByHighlight )
2016 {
2017 if ( bSelectByHighlight != mpImpl->mbHighlightSelection )
2018 {
2019 // Falls umschalten zwischendurch moeglich...
2020 mpImpl->mbHighlightSelection = bSelectByHighlight;
2021 }
2022 }
2023
Read(SvStream & rInput)2024 sal_Bool TextView::Read( SvStream& rInput )
2025 {
2026 sal_Bool bDone = mpImpl->mpTextEngine->Read( rInput, &mpImpl->maSelection );
2027 ShowCursor();
2028 return bDone;
2029 }
2030
Write(SvStream & rOutput)2031 sal_Bool TextView::Write( SvStream& rOutput )
2032 {
2033 return mpImpl->mpTextEngine->Read( rOutput, &mpImpl->maSelection );
2034 }
2035
ImplTruncateNewText(rtl::OUString & rNewText) const2036 bool TextView::ImplTruncateNewText( rtl::OUString& rNewText ) const
2037 {
2038 bool bTruncated = false;
2039
2040 if( rNewText.getLength() > 65534 ) // limit to String API
2041 {
2042 rNewText = rNewText.copy( 0, 65534 );
2043 bTruncated = true;
2044 }
2045
2046 sal_uLong nMaxLen = mpImpl->mpTextEngine->GetMaxTextLen();
2047 // 0 means unlimited, there is just the String API limit handled above
2048 if( nMaxLen != 0 )
2049 {
2050 sal_uLong nCurLen = mpImpl->mpTextEngine->GetTextLen();
2051
2052 sal_uInt32 nNewLen = rNewText.getLength();
2053 if ( nCurLen + nNewLen > nMaxLen )
2054 {
2055 // see how much text will be replaced
2056 sal_uLong nSelLen = mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
2057 if ( nCurLen + nNewLen - nSelLen > nMaxLen )
2058 {
2059 sal_uInt32 nTruncatedLen = static_cast<sal_uInt32>(nMaxLen - (nCurLen - nSelLen));
2060 rNewText = rNewText.copy( 0, nTruncatedLen );
2061 bTruncated = true;
2062 }
2063 }
2064 }
2065 return bTruncated;
2066 }
2067
ImplCheckTextLen(const String & rNewText)2068 sal_Bool TextView::ImplCheckTextLen( const String& rNewText )
2069 {
2070 sal_Bool bOK = sal_True;
2071 if ( mpImpl->mpTextEngine->GetMaxTextLen() )
2072 {
2073 sal_uLong n = mpImpl->mpTextEngine->GetTextLen();
2074 n += rNewText.Len();
2075 if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
2076 {
2077 // nur dann noch ermitteln, wie viel Text geloescht wird
2078 n -= mpImpl->mpTextEngine->GetTextLen( mpImpl->maSelection );
2079 if ( n > mpImpl->mpTextEngine->GetMaxTextLen() )
2080 {
2081 // Beep hat hier eigentlich nichts verloren, sondern lieber ein Hdl,
2082 // aber so funktioniert es wenigstens in ME, BasicIDE, SourceView
2083 Sound::Beep();
2084 bOK = sal_False;
2085 }
2086 }
2087 }
2088 return bOK;
2089 }
2090
dragGestureRecognized(const::com::sun::star::datatransfer::dnd::DragGestureEvent & rDGE)2091 void TextView::dragGestureRecognized( const ::com::sun::star::datatransfer::dnd::DragGestureEvent& rDGE ) throw (::com::sun::star::uno::RuntimeException)
2092 {
2093 if ( mpImpl->mbClickedInSelection )
2094 {
2095 vos::OGuard aVclGuard( Application::GetSolarMutex() );
2096
2097 DBG_ASSERT( mpImpl->maSelection.HasRange(), "TextView::dragGestureRecognized: mpImpl->mbClickedInSelection, but no selection?" );
2098
2099 delete mpImpl->mpDDInfo;
2100 mpImpl->mpDDInfo = new TextDDInfo;
2101 mpImpl->mpDDInfo->mbStarterOfDD = sal_True;
2102
2103 TETextDataObject* pDataObj = new TETextDataObject( GetSelected() );
2104
2105 if ( mpImpl->mpTextEngine->HasAttrib( TEXTATTR_HYPERLINK ) ) // Dann auch als HTML
2106 mpImpl->mpTextEngine->Write( pDataObj->GetHTMLStream(), &mpImpl->maSelection, sal_True );
2107
2108
2109 /*
2110 // D&D eines Hyperlinks.
2111 // Besser waere es im MBDown sich den MBDownPaM zu merken,
2112 // ist dann aber inkompatibel => spaeter mal umstellen.
2113 TextPaM aPaM( mpImpl->mpTextEngine->GetPaM( GetDocPos( GetWindow()->GetPointerPosPixel() ) ) );
2114 const TextCharAttrib* pAttr = mpImpl->mpTextEngine->FindCharAttrib( aPaM, TEXTATTR_HYPERLINK );
2115 if ( pAttr )
2116 {
2117 aSel = aPaM;
2118 aSel.GetStart().GetIndex() = pAttr->GetStart();
2119 aSel.GetEnd().GetIndex() = pAttr->GetEnd();
2120
2121 const TextAttribHyperLink& rLink = (const TextAttribHyperLink&)pAttr->GetAttr();
2122 String aText( rLink.GetDescription() );
2123 if ( !aText.Len() )
2124 aText = mpImpl->mpTextEngine->GetText( aSel );
2125 INetBookmark aBookmark( rLink.GetURL(), aText );
2126 aBookmark.CopyDragServer();
2127 }
2128 */
2129
2130 mpImpl->mpCursor->Hide();
2131
2132 sal_Int8 nActions = datatransfer::dnd::DNDConstants::ACTION_COPY;
2133 if ( !IsReadOnly() )
2134 nActions |= datatransfer::dnd::DNDConstants::ACTION_MOVE;
2135 rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, pDataObj, mpImpl->mxDnDListener );
2136 }
2137 }
2138
dragDropEnd(const::com::sun::star::datatransfer::dnd::DragSourceDropEvent &)2139 void TextView::dragDropEnd( const ::com::sun::star::datatransfer::dnd::DragSourceDropEvent& ) throw (::com::sun::star::uno::RuntimeException)
2140 {
2141 ImpHideDDCursor();
2142 delete mpImpl->mpDDInfo;
2143 mpImpl->mpDDInfo = NULL;
2144 }
2145
drop(const::com::sun::star::datatransfer::dnd::DropTargetDropEvent & rDTDE)2146 void TextView::drop( const ::com::sun::star::datatransfer::dnd::DropTargetDropEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
2147 {
2148 vos::OGuard aVclGuard( Application::GetSolarMutex() );
2149
2150 sal_Bool bChanges = sal_False;
2151 if ( !mpImpl->mbReadOnly && mpImpl->mpDDInfo )
2152 {
2153 ImpHideDDCursor();
2154
2155 // Daten fuer das loeschen nach einem DROP_MOVE:
2156 TextSelection aPrevSel( mpImpl->maSelection );
2157 aPrevSel.Justify();
2158 sal_uLong nPrevParaCount = mpImpl->mpTextEngine->GetParagraphCount();
2159 sal_uInt16 nPrevStartParaLen = mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() );
2160
2161 sal_Bool bStarterOfDD = sal_False;
2162 for ( sal_uInt16 nView = mpImpl->mpTextEngine->GetViewCount(); nView && !bStarterOfDD; )
2163 bStarterOfDD = mpImpl->mpTextEngine->GetView( --nView )->mpImpl->mpDDInfo ? mpImpl->mpTextEngine->GetView( nView )->mpImpl->mpDDInfo->mbStarterOfDD : sal_False;
2164
2165 HideSelection();
2166 ImpSetSelection( mpImpl->mpDDInfo->maDropPos );
2167
2168 mpImpl->mpTextEngine->UndoActionStart();
2169
2170 String aText;
2171 uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable;
2172 if ( xDataObj.is() )
2173 {
2174 datatransfer::DataFlavor aFlavor;
2175 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
2176 if ( xDataObj->isDataFlavorSupported( aFlavor ) )
2177 {
2178 uno::Any aData = xDataObj->getTransferData( aFlavor );
2179 ::rtl::OUString aOUString;
2180 aData >>= aOUString;
2181 aText = aOUString;
2182 aText.ConvertLineEnd( LINEEND_LF );
2183 }
2184 }
2185
2186 if ( aText.Len() && ( aText.GetChar( aText.Len()-1 ) == LINE_SEP ) )
2187 aText.Erase( aText.Len()-1 );
2188
2189 TextPaM aTempStart = mpImpl->maSelection.GetStart();
2190 if ( ImplCheckTextLen( aText ) )
2191 ImpSetSelection( mpImpl->mpTextEngine->ImpInsertText( mpImpl->mpDDInfo->maDropPos, aText ) );
2192 if(mpImpl->mbSupportProtectAttribute)
2193 {
2194 mpImpl->mpTextEngine->SetAttrib( TextAttribProtect(),
2195 aTempStart.GetPara(),
2196 aTempStart.GetIndex(),
2197 mpImpl->maSelection.GetEnd().GetIndex(), sal_False );
2198 }
2199
2200 if ( aPrevSel.HasRange() &&
2201 !mpImpl->mbSupportProtectAttribute && // don't remove currently selected element
2202 (( rDTDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) || !bStarterOfDD) )
2203 {
2204 // ggf. Selection anpasssen:
2205 if ( ( mpImpl->mpDDInfo->maDropPos.GetPara() < aPrevSel.GetStart().GetPara() ) ||
2206 ( ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
2207 && ( mpImpl->mpDDInfo->maDropPos.GetIndex() < aPrevSel.GetStart().GetIndex() ) ) )
2208 {
2209 sal_uLong nNewParasBeforeSelection =
2210 mpImpl->mpTextEngine->GetParagraphCount() - nPrevParaCount;
2211
2212 aPrevSel.GetStart().GetPara() += nNewParasBeforeSelection;
2213 aPrevSel.GetEnd().GetPara() += nNewParasBeforeSelection;
2214
2215 if ( mpImpl->mpDDInfo->maDropPos.GetPara() == aPrevSel.GetStart().GetPara() )
2216 {
2217 sal_uInt16 nNewChars =
2218 mpImpl->mpTextEngine->GetTextLen( aPrevSel.GetStart().GetPara() ) - nPrevStartParaLen;
2219
2220 aPrevSel.GetStart().GetIndex() =
2221 aPrevSel.GetStart().GetIndex() + nNewChars;
2222 if ( aPrevSel.GetStart().GetPara() == aPrevSel.GetEnd().GetPara() )
2223 aPrevSel.GetEnd().GetIndex() =
2224 aPrevSel.GetEnd().GetIndex() + nNewChars;
2225 }
2226 }
2227 else
2228 {
2229 // aktuelle Selektion anpassen
2230 TextPaM aPaM = mpImpl->maSelection.GetStart();
2231 aPaM.GetPara() -= ( aPrevSel.GetEnd().GetPara() - aPrevSel.GetStart().GetPara() );
2232 if ( aPrevSel.GetEnd().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
2233 {
2234 aPaM.GetIndex() =
2235 aPaM.GetIndex() - aPrevSel.GetEnd().GetIndex();
2236 if ( aPrevSel.GetStart().GetPara() == mpImpl->mpDDInfo->maDropPos.GetPara() )
2237 aPaM.GetIndex() =
2238 aPaM.GetIndex() + aPrevSel.GetStart().GetIndex();
2239 }
2240 ImpSetSelection( aPaM );
2241
2242 }
2243 mpImpl->mpTextEngine->ImpDeleteText( aPrevSel );
2244 }
2245
2246 mpImpl->mpTextEngine->UndoActionEnd();
2247
2248 delete mpImpl->mpDDInfo;
2249 mpImpl->mpDDInfo = 0;
2250
2251 mpImpl->mpTextEngine->FormatAndUpdate( this );
2252
2253 mpImpl->mpTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
2254 }
2255 rDTDE.Context->dropComplete( bChanges );
2256 }
2257
dragEnter(const::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent &)2258 void TextView::dragEnter( const ::com::sun::star::datatransfer::dnd::DropTargetDragEnterEvent& ) throw (::com::sun::star::uno::RuntimeException)
2259 {
2260 }
2261
dragExit(const::com::sun::star::datatransfer::dnd::DropTargetEvent &)2262 void TextView::dragExit( const ::com::sun::star::datatransfer::dnd::DropTargetEvent& ) throw (::com::sun::star::uno::RuntimeException)
2263 {
2264 vos::OGuard aVclGuard( Application::GetSolarMutex() );
2265 ImpHideDDCursor();
2266 }
2267
dragOver(const::com::sun::star::datatransfer::dnd::DropTargetDragEvent & rDTDE)2268 void TextView::dragOver( const ::com::sun::star::datatransfer::dnd::DropTargetDragEvent& rDTDE ) throw (::com::sun::star::uno::RuntimeException)
2269 {
2270 vos::OGuard aVclGuard( Application::GetSolarMutex() );
2271
2272 if ( !mpImpl->mpDDInfo )
2273 mpImpl->mpDDInfo = new TextDDInfo;
2274
2275 TextPaM aPrevDropPos = mpImpl->mpDDInfo->maDropPos;
2276 Point aMousePos( rDTDE.LocationX, rDTDE.LocationY );
2277 Point aDocPos = GetDocPos( aMousePos );
2278 mpImpl->mpDDInfo->maDropPos = mpImpl->mpTextEngine->GetPaM( aDocPos );
2279
2280 /*
2281 Size aOutSize = mpImpl->mpWindow->GetOutputSizePixel();
2282 if ( ( aMousePos.X() < 0 ) || ( aMousePos.X() > aOutSize.Width() ) ||
2283 ( aMousePos.Y() < 0 ) || ( aMousePos.Y() > aOutSize.Height() ) )
2284 {
2285 // Scroll?
2286 // No, I will not receive events for this...
2287 }
2288 */
2289
2290 sal_Bool bProtected = sal_False;
2291 if(mpImpl->mbSupportProtectAttribute)
2292 {
2293 const TextCharAttrib* pStartAttr = mpImpl->mpTextEngine->FindCharAttrib(
2294 mpImpl->mpDDInfo->maDropPos,
2295 TEXTATTR_PROTECTED );
2296 bProtected = pStartAttr != 0 &&
2297 pStartAttr->GetStart() != mpImpl->mpDDInfo->maDropPos.GetIndex() &&
2298 pStartAttr->GetEnd() != mpImpl->mpDDInfo->maDropPos.GetIndex();
2299 }
2300 // Don't drop in selection or in read only engine
2301 if ( IsReadOnly() || IsInSelection( mpImpl->mpDDInfo->maDropPos ) || bProtected)
2302 {
2303 ImpHideDDCursor();
2304 rDTDE.Context->rejectDrag();
2305 }
2306 else
2307 {
2308 // Alten Cursor wegzeichnen...
2309 if ( !mpImpl->mpDDInfo->mbVisCursor || ( aPrevDropPos != mpImpl->mpDDInfo->maDropPos ) )
2310 {
2311 ImpHideDDCursor();
2312 ImpShowDDCursor();
2313 }
2314 rDTDE.Context->acceptDrag( rDTDE.DropAction );
2315 }
2316 }
2317
ImpGetOutputStartPos(const Point & rStartDocPos) const2318 Point TextView::ImpGetOutputStartPos( const Point& rStartDocPos ) const
2319 {
2320 Point aStartPos( -rStartDocPos.X(), -rStartDocPos.Y() );
2321 if ( mpImpl->mpTextEngine->IsRightToLeft() )
2322 {
2323 Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2324 aStartPos.X() = rStartDocPos.X() + aSz.Width() - 1; // -1: Start is 0
2325 }
2326 return aStartPos;
2327 }
2328
GetDocPos(const Point & rWindowPos) const2329 Point TextView::GetDocPos( const Point& rWindowPos ) const
2330 {
2331 // Fensterposition => Dokumentposition
2332
2333 Point aPoint;
2334
2335 aPoint.Y() = rWindowPos.Y() + mpImpl->maStartDocPos.Y();
2336
2337 if ( !mpImpl->mpTextEngine->IsRightToLeft() )
2338 {
2339 aPoint.X() = rWindowPos.X() + mpImpl->maStartDocPos.X();
2340 }
2341 else
2342 {
2343 Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2344 aPoint.X() = ( aSz.Width() - 1 ) - rWindowPos.X() + mpImpl->maStartDocPos.X();
2345 }
2346
2347 return aPoint;
2348 }
2349
GetWindowPos(const Point & rDocPos) const2350 Point TextView::GetWindowPos( const Point& rDocPos ) const
2351 {
2352 // Dokumentposition => Fensterposition
2353
2354 Point aPoint;
2355
2356 aPoint.Y() = rDocPos.Y() - mpImpl->maStartDocPos.Y();
2357
2358 if ( !mpImpl->mpTextEngine->IsRightToLeft() )
2359 {
2360 aPoint.X() = rDocPos.X() - mpImpl->maStartDocPos.X();
2361 }
2362 else
2363 {
2364 Size aSz = mpImpl->mpWindow->GetOutputSizePixel();
2365 aPoint.X() = ( aSz.Width() - 1 ) - ( rDocPos.X() - mpImpl->maStartDocPos.X() );
2366 }
2367
2368 return aPoint;
2369 }
2370
GetLineNumberOfCursorInSelection() const2371 sal_Int32 TextView::GetLineNumberOfCursorInSelection() const
2372 {
2373 // PROGRESS
2374 sal_Int32 nLineNo = -1;
2375 if( mpImpl->mbCursorEnabled )
2376 {
2377 TextPaM aPaM = GetSelection().GetEnd();
2378 TEParaPortion* pPPortion = mpImpl->mpTextEngine->mpTEParaPortions->GetObject( aPaM.GetPara() );
2379 nLineNo = pPPortion->GetLineNumber( aPaM.GetIndex(), sal_False );
2380 if( mpImpl->mbCursorAtEndOfLine )
2381 --nLineNo;
2382 }
2383 return nLineNo;
2384 }
2385
2386
2387 // -------------------------------------------------------------------------
2388 // (+) class TextSelFunctionSet
2389 // -------------------------------------------------------------------------
TextSelFunctionSet(TextView * pView)2390 TextSelFunctionSet::TextSelFunctionSet( TextView* pView )
2391 {
2392 mpView = pView;
2393 }
2394
BeginDrag()2395 void __EXPORT TextSelFunctionSet::BeginDrag()
2396 {
2397 }
2398
CreateAnchor()2399 void __EXPORT TextSelFunctionSet::CreateAnchor()
2400 {
2401 // TextSelection aSel( mpView->GetSelection() );
2402 // aSel.GetStart() = aSel.GetEnd();
2403 // mpView->SetSelection( aSel );
2404
2405 // Es darf kein ShowCursor folgen:
2406 mpView->HideSelection();
2407 mpView->ImpSetSelection( mpView->mpImpl->maSelection.GetEnd() );
2408 }
2409
SetCursorAtPoint(const Point & rPointPixel,sal_Bool)2410 sal_Bool __EXPORT TextSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, sal_Bool )
2411 {
2412 return mpView->SetCursorAtPoint( rPointPixel );
2413 }
2414
IsSelectionAtPoint(const Point & rPointPixel)2415 sal_Bool __EXPORT TextSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel )
2416 {
2417 return mpView->IsSelectionAtPoint( rPointPixel );
2418 }
2419
DeselectAll()2420 void __EXPORT TextSelFunctionSet::DeselectAll()
2421 {
2422 CreateAnchor();
2423 }
2424
DeselectAtPoint(const Point &)2425 void __EXPORT TextSelFunctionSet::DeselectAtPoint( const Point& )
2426 {
2427 // Nur bei Mehrfachselektion
2428 }
2429
DestroyAnchor()2430 void __EXPORT TextSelFunctionSet::DestroyAnchor()
2431 {
2432 // Nur bei Mehrfachselektion
2433 }
GetTextEngine() const2434 TextEngine* TextView::GetTextEngine() const
2435 { return mpImpl->mpTextEngine; }
GetWindow() const2436 Window* TextView::GetWindow() const
2437 { return mpImpl->mpWindow; }
EnableCursor(sal_Bool bEnable)2438 void TextView::EnableCursor( sal_Bool bEnable )
2439 { mpImpl->mbCursorEnabled = bEnable; }
IsCursorEnabled() const2440 sal_Bool TextView::IsCursorEnabled() const
2441 { return mpImpl->mbCursorEnabled; }
SetStartDocPos(const Point & rPos)2442 void TextView::SetStartDocPos( const Point& rPos )
2443 { mpImpl->maStartDocPos = rPos; }
GetStartDocPos() const2444 const Point& TextView::GetStartDocPos() const
2445 { return mpImpl->maStartDocPos; }
SetAutoIndentMode(sal_Bool bAutoIndent)2446 void TextView::SetAutoIndentMode( sal_Bool bAutoIndent )
2447 { mpImpl->mbAutoIndent = bAutoIndent; }
IsAutoIndentMode() const2448 sal_Bool TextView::IsAutoIndentMode() const
2449 { return mpImpl->mbAutoIndent; }
IsReadOnly() const2450 sal_Bool TextView::IsReadOnly() const
2451 { return mpImpl->mbReadOnly; }
SetAutoScroll(sal_Bool bAutoScroll)2452 void TextView::SetAutoScroll( sal_Bool bAutoScroll )
2453 { mpImpl->mbAutoScroll = bAutoScroll; }
IsAutoScroll() const2454 sal_Bool TextView::IsAutoScroll() const
2455 { return mpImpl->mbAutoScroll; }
IsPaintSelection() const2456 sal_Bool TextView::IsPaintSelection() const
2457 { return mpImpl->mbPaintSelection; }
IsHighlightSelection() const2458 sal_Bool TextView::IsHighlightSelection() const
2459 { return mpImpl->mbHighlightSelection; }
HasSelection() const2460 sal_Bool TextView::HasSelection() const
2461 { return mpImpl->maSelection.HasRange(); }
IsInsertMode() const2462 sal_Bool TextView::IsInsertMode() const
2463 { return mpImpl->mbInsertMode; }
SupportProtectAttribute(sal_Bool bSupport)2464 void TextView::SupportProtectAttribute(sal_Bool bSupport)
2465 { mpImpl->mbSupportProtectAttribute = bSupport;}
2466
2467