xref: /trunk/main/svtools/source/edit/svmedit.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 
32 #include <memory>
33 
34 #include "unoiface.hxx"
35 
36 #include <tools/rc.h>
37 
38 #include <vcl/decoview.hxx>
39 #include <vcl/svapp.hxx>
40 
41 #include <svtools/svmedit.hxx>
42 #include <svtools/xtextedt.hxx>
43 #include <svl/brdcst.hxx>
44 #include <svl/undo.hxx>
45 #include <svtools/textwindowpeer.hxx>
46 #include <svl/lstner.hxx>
47 #include <svl/smplhint.hxx>
48 
49 
50 // IDs erstmal aus VCL geklaut, muss mal richtig delivert werden...
51 #define SV_MENU_EDIT_UNDO           1
52 #define SV_MENU_EDIT_CUT            2
53 #define SV_MENU_EDIT_COPY           3
54 #define SV_MENU_EDIT_PASTE          4
55 #define SV_MENU_EDIT_DELETE         5
56 #define SV_MENU_EDIT_SELECTALL      6
57 #define SV_MENU_EDIT_INSERTSYMBOL   7
58 #include <vcl/scrbar.hxx>
59 
60 namespace css = ::com::sun::star;
61 
62 class TextWindow : public Window
63 {
64 private:
65     ExtTextEngine*  mpExtTextEngine;
66     ExtTextView*    mpExtTextView;
67 
68     sal_Bool            mbInMBDown;
69     sal_Bool            mbFocusSelectionHide;
70     sal_Bool            mbIgnoreTab;
71     sal_Bool            mbActivePopup;
72     sal_Bool            mbSelectOnTab;
73 
74 public:
75                     TextWindow( Window* pParent );
76                     ~TextWindow();
77 
78     ExtTextEngine*  GetTextEngine() const { return mpExtTextEngine; }
79     ExtTextView*    GetTextView() const { return mpExtTextView; }
80 
81     virtual void    MouseMove( const MouseEvent& rMEvt );
82     virtual void    MouseButtonDown( const MouseEvent& rMEvt );
83     virtual void    MouseButtonUp( const MouseEvent& rMEvt );
84     virtual void    KeyInput( const KeyEvent& rKEvent );
85 
86     virtual void    Command( const CommandEvent& rCEvt );
87 
88     virtual void    Paint( const Rectangle& rRect );
89     virtual void    Resize();
90 
91     virtual void    GetFocus();
92     virtual void    LoseFocus();
93 
94     sal_Bool            IsAutoFocusHide() const { return mbFocusSelectionHide; }
95     void            SetAutoFocusHide( sal_Bool bAutoHide ) { mbFocusSelectionHide = bAutoHide; }
96 
97     sal_Bool            IsIgnoreTab() const { return mbIgnoreTab; }
98     void            SetIgnoreTab( sal_Bool bIgnore ) { mbIgnoreTab = bIgnore; }
99 
100     void            DisableSelectionOnFocus() {mbSelectOnTab = sal_False;}
101 
102     virtual
103     ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer >
104     GetComponentInterface(sal_Bool bCreate = sal_True);
105 };
106 
107 
108 class ImpSvMEdit : public SfxListener
109 {
110 private:
111     MultiLineEdit*      pSvMultiLineEdit;
112 
113     TextWindow*         mpTextWindow;
114     ScrollBar*          mpHScrollBar;
115     ScrollBar*          mpVScrollBar;
116     ScrollBarBox*       mpScrollBox;
117 
118     Point               maTextWindowOffset;
119     xub_StrLen          mnTextWidth;
120     mutable Selection   maSelection;
121 
122 protected:
123     virtual void        Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
124     void                ImpUpdateSrollBarVis( WinBits nWinStyle );
125     void                ImpInitScrollBars();
126     void                ImpSetScrollBarRanges();
127     void                ImpSetHScrollBarThumbPos();
128     DECL_LINK(          ScrollHdl, ScrollBar* );
129 
130 public:
131                 ImpSvMEdit( MultiLineEdit* pSvMultiLineEdit, WinBits nWinStyle );
132                 ~ImpSvMEdit();
133 
134     void        SetModified( sal_Bool bMod );
135     sal_Bool        IsModified() const;
136 
137     void        SetReadOnly( sal_Bool bRdOnly );
138     sal_Bool        IsReadOnly() const;
139 
140     void        SetMaxTextLen( xub_StrLen nLen );
141     xub_StrLen  GetMaxTextLen() const;
142 
143     void        SetInsertMode( sal_Bool bInsert );
144     sal_Bool        IsInsertMode() const;
145 
146     void        InsertText( const String& rStr );
147     String      GetSelected() const;
148     String      GetSelected( LineEnd aSeparator ) const;
149 
150     void        SetSelection( const Selection& rSelection );
151     const Selection& GetSelection() const;
152 
153     void        Cut();
154     void        Copy();
155     void        Paste();
156 
157     void        SetText( const String& rStr );
158     String      GetText() const;
159     String      GetText( LineEnd aSeparator ) const;
160     String      GetTextLines() const;
161     String      GetTextLines( LineEnd aSeparator ) const;
162 
163     void        Resize();
164     void        GetFocus();
165 
166     sal_Bool        HandleCommand( const CommandEvent& rCEvt );
167 
168     void        Enable( sal_Bool bEnable );
169 
170     Size        CalcMinimumSize() const;
171     Size        CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const;
172     void        GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const;
173 
174     void        SetAlign( WinBits nWinStyle );
175 
176     void        InitFromStyle( WinBits nWinStyle );
177 
178     TextWindow* GetTextWindow() { return mpTextWindow; }
179     ScrollBar*  GetHScrollBar() { return mpHScrollBar; }
180     ScrollBar*  GetVScrollBar() { return mpVScrollBar; }
181 
182     void        SetTextWindowOffset( const Point& rOffset );
183 };
184 
185 ImpSvMEdit::ImpSvMEdit( MultiLineEdit* pEdt, WinBits nWinStyle )
186     :mpHScrollBar(NULL)
187     ,mpVScrollBar(NULL)
188     ,mpScrollBox(NULL)
189 {
190     pSvMultiLineEdit = pEdt;
191     mnTextWidth = 0;
192     mpTextWindow = new TextWindow( pEdt );
193     mpTextWindow->Show();
194     InitFromStyle( nWinStyle );
195     StartListening( *mpTextWindow->GetTextEngine() );
196 }
197 
198 void ImpSvMEdit::ImpUpdateSrollBarVis( WinBits nWinStyle )
199 {
200     const sal_Bool bHaveVScroll = (NULL != mpVScrollBar);
201     const sal_Bool bHaveHScroll = (NULL != mpHScrollBar);
202     const sal_Bool bHaveScrollBox = (NULL != mpScrollBox);
203 
204           sal_Bool bNeedVScroll = ( nWinStyle & WB_VSCROLL ) == WB_VSCROLL;
205     const sal_Bool bNeedHScroll = ( nWinStyle & WB_HSCROLL ) == WB_HSCROLL;
206 
207     const sal_Bool bAutoVScroll = ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL;
208     if ( !bNeedVScroll && bAutoVScroll )
209     {
210         TextEngine& rEngine( *mpTextWindow->GetTextEngine() );
211         sal_uLong nOverallTextHeight(0);
212         for ( sal_uLong i=0; i<rEngine.GetParagraphCount(); ++i )
213             nOverallTextHeight += rEngine.GetTextHeight( i );
214         if ( nOverallTextHeight > (sal_uLong)mpTextWindow->GetOutputSizePixel().Height() )
215             bNeedVScroll = true;
216     }
217 
218     const sal_Bool bNeedScrollBox = bNeedVScroll && bNeedHScroll;
219 
220     sal_Bool bScrollbarsChanged = false;
221     if ( bHaveVScroll != bNeedVScroll )
222     {
223         delete mpVScrollBar;
224         mpVScrollBar = bNeedVScroll ? new ScrollBar( pSvMultiLineEdit, WB_VSCROLL|WB_DRAG ) : NULL;
225 
226         if ( bNeedVScroll )
227         {
228             mpVScrollBar->Show();
229             mpVScrollBar->SetScrollHdl( LINK( this, ImpSvMEdit, ScrollHdl ) );
230         }
231 
232         bScrollbarsChanged = sal_True;
233     }
234 
235     if ( bHaveHScroll != bNeedHScroll )
236     {
237         delete mpHScrollBar;
238         mpHScrollBar = bNeedHScroll ? new ScrollBar( pSvMultiLineEdit, WB_HSCROLL|WB_DRAG ) : NULL;
239 
240         if ( bNeedHScroll )
241         {
242             mpHScrollBar->Show();
243             mpHScrollBar->SetScrollHdl( LINK( this, ImpSvMEdit, ScrollHdl ) );
244         }
245 
246         bScrollbarsChanged = sal_True;
247     }
248 
249     if ( bHaveScrollBox != bNeedScrollBox )
250     {
251         delete mpScrollBox;
252         mpScrollBox = bNeedScrollBox ? new ScrollBarBox( pSvMultiLineEdit, WB_SIZEABLE ) : NULL;
253 
254         if ( bNeedScrollBox )
255             mpScrollBox->Show();
256     }
257 
258     if ( bScrollbarsChanged )
259     {
260         ImpInitScrollBars();
261         Resize();
262     }
263 }
264 
265 void ImpSvMEdit::InitFromStyle( WinBits nWinStyle )
266 {
267     ImpUpdateSrollBarVis( nWinStyle );
268     SetAlign( nWinStyle );
269 
270     if ( nWinStyle & WB_NOHIDESELECTION )
271         mpTextWindow->SetAutoFocusHide( sal_False );
272     else
273         mpTextWindow->SetAutoFocusHide( sal_True );
274 
275     if ( nWinStyle & WB_READONLY )
276         mpTextWindow->GetTextView()->SetReadOnly( sal_True );
277     else
278         mpTextWindow->GetTextView()->SetReadOnly( sal_False );
279 
280     if ( nWinStyle & WB_IGNORETAB )
281     {
282         mpTextWindow->SetIgnoreTab( sal_True );
283     }
284     else
285     {
286         mpTextWindow->SetIgnoreTab( sal_False );
287         // #103667# MultiLineEdit has the flag, but focusable window also needs this flag
288         WinBits nStyle = mpTextWindow->GetStyle();
289         nStyle |= WINDOW_DLGCTRL_MOD1TAB;
290         mpTextWindow->SetStyle( nStyle );
291     }
292 }
293 
294 ImpSvMEdit::~ImpSvMEdit()
295 {
296     EndListening( *mpTextWindow->GetTextEngine() );
297     delete mpTextWindow;
298     delete mpHScrollBar;
299     delete mpVScrollBar;
300     delete mpScrollBox;
301 }
302 
303 void ImpSvMEdit::ImpSetScrollBarRanges()
304 {
305     if ( mpVScrollBar )
306     {
307         sal_uLong nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
308         mpVScrollBar->SetRange( Range( 0, (long)nTextHeight-1 ) );
309     }
310     if ( mpHScrollBar )
311     {
312 //      sal_uLong nTextWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
313         // Es gibt kein Notify bei Breiten-Aenderung...
314 //      sal_uLong nW = Max( (sal_uLong)mpTextWindow->GetOutputSizePixel().Width()*5, (sal_uLong)nTextWidth );
315 //      mpHScrollBar->SetRange( Range( 0, (long)nW ) );
316         mpHScrollBar->SetRange( Range( 0, (long)mnTextWidth-1 ) );
317     }
318 }
319 
320 void ImpSvMEdit::ImpInitScrollBars()
321 {
322     static const sal_Unicode sampleText[] = { 'x', '\0' };
323     if ( mpHScrollBar || mpVScrollBar )
324     {
325         ImpSetScrollBarRanges();
326         Size aCharBox;
327         aCharBox.Width() = mpTextWindow->GetTextWidth( sampleText );
328         aCharBox.Height() = mpTextWindow->GetTextHeight();
329         Size aOutSz = mpTextWindow->GetOutputSizePixel();
330         if ( mpHScrollBar )
331         {
332             mpHScrollBar->SetVisibleSize( aOutSz.Width() );
333             mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 );
334             mpHScrollBar->SetLineSize( aCharBox.Width()*10 );
335             ImpSetHScrollBarThumbPos();
336         }
337         if ( mpVScrollBar )
338         {
339             mpVScrollBar->SetVisibleSize( aOutSz.Height() );
340             mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 );
341             mpVScrollBar->SetLineSize( aCharBox.Height() );
342             mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
343         }
344     }
345 }
346 
347 void ImpSvMEdit::ImpSetHScrollBarThumbPos()
348 {
349     long nX = mpTextWindow->GetTextView()->GetStartDocPos().X();
350     if ( !mpTextWindow->GetTextEngine()->IsRightToLeft() )
351         mpHScrollBar->SetThumbPos( nX );
352     else
353         mpHScrollBar->SetThumbPos( mnTextWidth - mpHScrollBar->GetVisibleSize() - nX );
354 
355 }
356 
357 IMPL_LINK( ImpSvMEdit, ScrollHdl, ScrollBar*, pCurScrollBar )
358 {
359     long nDiffX = 0, nDiffY = 0;
360 
361     if ( pCurScrollBar == mpVScrollBar )
362         nDiffY = mpTextWindow->GetTextView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
363     else if ( pCurScrollBar == mpHScrollBar )
364         nDiffX = mpTextWindow->GetTextView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
365 
366     mpTextWindow->GetTextView()->Scroll( nDiffX, nDiffY );
367     // mpTextWindow->GetTextView()->ShowCursor( sal_False, sal_True );
368 
369     return 0;
370 }
371 
372 
373 // void ImpSvMEdit::ImpModified()
374 // {
375 //  // Wann wird das gerufen ?????????????????????
376 //  pSvMultiLineEdit->Modify();
377 // }
378 
379 void ImpSvMEdit::SetAlign( WinBits nWinStyle )
380 {
381     sal_Bool bRTL = Application::GetSettings().GetLayoutRTL();
382     mpTextWindow->GetTextEngine()->SetRightToLeft( bRTL );
383 
384     if ( nWinStyle & WB_CENTER )
385         mpTextWindow->GetTextEngine()->SetTextAlign( TXTALIGN_CENTER );
386     else if ( nWinStyle & WB_RIGHT )
387         mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_RIGHT : TXTALIGN_LEFT );
388     else if ( nWinStyle & WB_LEFT )
389         mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TXTALIGN_LEFT : TXTALIGN_RIGHT );
390 }
391 
392 void ImpSvMEdit::SetTextWindowOffset( const Point& rOffset )
393 {
394     maTextWindowOffset = rOffset;
395     Resize();
396 }
397 
398 void ImpSvMEdit::SetModified( sal_Bool bMod )
399 {
400     mpTextWindow->GetTextEngine()->SetModified( bMod );
401 }
402 
403 sal_Bool ImpSvMEdit::IsModified() const
404 {
405     return mpTextWindow->GetTextEngine()->IsModified();
406 }
407 
408 void ImpSvMEdit::SetInsertMode( sal_Bool bInsert )
409 {
410     mpTextWindow->GetTextView()->SetInsertMode( bInsert );
411 }
412 
413 void ImpSvMEdit::SetReadOnly( sal_Bool bRdOnly )
414 {
415     mpTextWindow->GetTextView()->SetReadOnly( bRdOnly );
416     // Farbe anpassen ???????????????????????????
417 }
418 
419 sal_Bool ImpSvMEdit::IsReadOnly() const
420 {
421     return mpTextWindow->GetTextView()->IsReadOnly();
422 }
423 
424 void ImpSvMEdit::SetMaxTextLen( xub_StrLen nLen )
425 {
426     mpTextWindow->GetTextEngine()->SetMaxTextLen( nLen );
427 }
428 
429 xub_StrLen ImpSvMEdit::GetMaxTextLen() const
430 {
431     return sal::static_int_cast< xub_StrLen >(
432         mpTextWindow->GetTextEngine()->GetMaxTextLen());
433 }
434 
435 void ImpSvMEdit::InsertText( const String& rStr )
436 {
437     mpTextWindow->GetTextView()->InsertText( rStr );
438 }
439 
440 String ImpSvMEdit::GetSelected() const
441 {
442     return mpTextWindow->GetTextView()->GetSelected();
443 }
444 
445 String ImpSvMEdit::GetSelected( LineEnd aSeparator ) const
446 {
447     return mpTextWindow->GetTextView()->GetSelected( aSeparator );
448 }
449 
450 void ImpSvMEdit::Resize()
451 {
452     size_t nIteration = 1;
453     do
454     {
455         WinBits nWinStyle( pSvMultiLineEdit->GetStyle() );
456         if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
457             ImpUpdateSrollBarVis( nWinStyle );
458 
459         Size aSz = pSvMultiLineEdit->GetOutputSizePixel();
460         Size aEditSize = aSz;
461         long nSBWidth = pSvMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize();
462         nSBWidth = pSvMultiLineEdit->CalcZoom( nSBWidth );
463 
464         if ( mpHScrollBar )
465             aSz.Height() -= nSBWidth+1;
466         if ( mpVScrollBar )
467             aSz.Width() -= nSBWidth+1;
468 
469         if ( !mpHScrollBar )
470             mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() );
471         else
472             mpHScrollBar->SetPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth );
473 
474         Point aTextWindowPos( maTextWindowOffset );
475         if ( mpVScrollBar )
476         {
477             if( Application::GetSettings().GetLayoutRTL() )
478             {
479                 mpVScrollBar->SetPosSizePixel( 0, 0, nSBWidth, aSz.Height() );
480                 aTextWindowPos.X() += nSBWidth;
481             }
482             else
483                 mpVScrollBar->SetPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() );
484         }
485 
486         if ( mpScrollBox )
487             mpScrollBox->SetPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth );
488 
489         Size aTextWindowSize( aSz );
490         aTextWindowSize.Width() -= maTextWindowOffset.X();
491         aTextWindowSize.Height() -= maTextWindowOffset.Y();
492         if ( aTextWindowSize.Width() < 0 )
493             aTextWindowSize.Width() = 0;
494         if ( aTextWindowSize.Height() < 0 )
495             aTextWindowSize.Height() = 0;
496 
497         Size aOldTextWindowSize( mpTextWindow->GetSizePixel() );
498         mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize );
499         if ( aOldTextWindowSize == aTextWindowSize )
500             break;
501 
502         // Changing the text window size might effectively have changed the need for
503         // scrollbars, so do another iteration.
504         ++nIteration;
505         OSL_ENSURE( nIteration < 3, "ImpSvMEdit::Resize: isn't this expected to terminate with the second iteration?" );
506 
507     } while ( nIteration <= 3 );    // artificial break after four iterations
508 
509     ImpInitScrollBars();
510 }
511 
512 void ImpSvMEdit::GetFocus()
513 {
514     mpTextWindow->GrabFocus();
515 }
516 
517 void ImpSvMEdit::Cut()
518 {
519     if ( !mpTextWindow->GetTextView()->IsReadOnly() )
520         mpTextWindow->GetTextView()->Cut();
521 }
522 
523 void ImpSvMEdit::Copy()
524 {
525     mpTextWindow->GetTextView()->Copy();
526 }
527 
528 void ImpSvMEdit::Paste()
529 {
530     if ( !mpTextWindow->GetTextView()->IsReadOnly() )
531         mpTextWindow->GetTextView()->Paste();
532 }
533 
534 void ImpSvMEdit::SetText( const String& rStr )
535 {
536     sal_Bool bWasModified = mpTextWindow->GetTextEngine()->IsModified();
537     mpTextWindow->GetTextEngine()->SetText( rStr );
538     if ( !bWasModified )
539         mpTextWindow->GetTextEngine()->SetModified( sal_False );
540 
541     mpTextWindow->GetTextView()->SetSelection( TextSelection() );
542 
543     WinBits nWinStyle( pSvMultiLineEdit->GetStyle() );
544     if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
545         ImpUpdateSrollBarVis( nWinStyle );
546 }
547 
548 String ImpSvMEdit::GetText() const
549 {
550     return mpTextWindow->GetTextEngine()->GetText();
551 }
552 
553 String ImpSvMEdit::GetText( LineEnd aSeparator ) const
554 {
555     return mpTextWindow->GetTextEngine()->GetText( aSeparator );
556 }
557 
558 String ImpSvMEdit::GetTextLines() const
559 {
560     return mpTextWindow->GetTextEngine()->GetTextLines();
561 }
562 
563 String ImpSvMEdit::GetTextLines( LineEnd aSeparator ) const
564 {
565     return mpTextWindow->GetTextEngine()->GetTextLines( aSeparator );
566 }
567 
568 void ImpSvMEdit::Notify( SfxBroadcaster&, const SfxHint& rHint )
569 {
570     if ( rHint.ISA( TextHint ) )
571     {
572         const TextHint& rTextHint = (const TextHint&)rHint;
573         if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED )
574         {
575             if ( mpHScrollBar )
576                 ImpSetHScrollBarThumbPos();
577             if ( mpVScrollBar )
578                 mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
579         }
580         else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED )
581         {
582             if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() )
583             {
584                 long nOutHeight = mpTextWindow->GetOutputSizePixel().Height();
585                 long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
586                 if ( nTextHeight < nOutHeight )
587                     mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() );
588             }
589 
590             ImpSetScrollBarRanges();
591         }
592         else if( rTextHint.GetId() == TEXT_HINT_TEXTFORMATTED )
593         {
594             if ( mpHScrollBar )
595             {
596                 sal_uLong nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
597                 if ( nWidth != mnTextWidth )
598                 {
599                     mnTextWidth = sal::static_int_cast< xub_StrLen >(nWidth);
600                     mpHScrollBar->SetRange( Range( 0, (long)mnTextWidth-1 ) );
601                     ImpSetHScrollBarThumbPos();
602                 }
603             }
604         }
605         else if( rTextHint.GetId() == TEXT_HINT_MODIFIED )
606         {
607             pSvMultiLineEdit->Modify();
608         }
609     }
610 }
611 
612 void ImpSvMEdit::SetSelection( const Selection& rSelection )
613 {
614     String aText = mpTextWindow->GetTextEngine()->GetText();
615 
616     Selection aNewSelection( rSelection );
617     if ( aNewSelection.Min() < 0 )
618         aNewSelection.Min() = 0;
619     else if ( aNewSelection.Min() > aText.Len() )
620         aNewSelection.Min() = aText.Len();
621     if ( aNewSelection.Max() < 0 )
622         aNewSelection.Max() = 0;
623     else if ( aNewSelection.Max() > aText.Len() )
624         aNewSelection.Max() = aText.Len();
625 
626     long nEnd = Max( aNewSelection.Min(), aNewSelection.Max() );
627     TextSelection aTextSel;
628     sal_uLong nPara = 0;
629     sal_uInt16 nChar = 0;
630     sal_uInt16 x = 0;
631     while ( x <= nEnd )
632     {
633         if ( x == aNewSelection.Min() )
634             aTextSel.GetStart() = TextPaM( nPara, nChar );
635         if ( x == aNewSelection.Max() )
636             aTextSel.GetEnd() = TextPaM( nPara, nChar );
637 
638         if ( ( x < aText.Len() ) && ( aText.GetChar( x ) == '\n' ) )
639         {
640             nPara++;
641             nChar = 0;
642         }
643         else
644             nChar++;
645         x++;
646     }
647     mpTextWindow->GetTextView()->SetSelection( aTextSel );
648 }
649 
650 const Selection& ImpSvMEdit::GetSelection() const
651 {
652     maSelection = Selection();
653     TextSelection aTextSel( mpTextWindow->GetTextView()->GetSelection() );
654     aTextSel.Justify();
655     // Selektion flachklopfen => jeder Umbruch ein Zeichen...
656 
657     ExtTextEngine* pExtTextEngine = mpTextWindow->GetTextEngine();
658     // Absaetze davor:
659     sal_uLong n;
660     for ( n = 0; n < aTextSel.GetStart().GetPara(); n++ )
661     {
662         maSelection.Min() += pExtTextEngine->GetTextLen( n );
663         maSelection.Min()++;
664     }
665 
666     // Erster Absatz mit Selektion:
667     maSelection.Max() = maSelection.Min();
668     maSelection.Min() += aTextSel.GetStart().GetIndex();
669 
670     for ( n = aTextSel.GetStart().GetPara(); n < aTextSel.GetEnd().GetPara(); n++ )
671     {
672         maSelection.Max() += pExtTextEngine->GetTextLen( n );
673         maSelection.Max()++;
674     }
675 
676     maSelection.Max() += aTextSel.GetEnd().GetIndex();
677 
678     return maSelection;
679 }
680 
681 Size ImpSvMEdit::CalcMinimumSize() const
682 {
683     Size aSz(   mpTextWindow->GetTextEngine()->CalcTextWidth(),
684                 mpTextWindow->GetTextEngine()->GetTextHeight() );
685 
686     if ( mpHScrollBar )
687         aSz.Height() += mpHScrollBar->GetSizePixel().Height();
688     if ( mpVScrollBar )
689         aSz.Width() += mpVScrollBar->GetSizePixel().Width();
690 
691     return aSz;
692 }
693 
694 Size ImpSvMEdit::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
695 {
696     static const sal_Unicode sampleText[] = { 'X', '\0' };
697 
698     Size aSz;
699     Size aCharSz;
700     aCharSz.Width() = mpTextWindow->GetTextWidth( sampleText );
701     aCharSz.Height() = mpTextWindow->GetTextHeight();
702 
703     if ( nLines )
704         aSz.Height() = nLines*aCharSz.Height();
705     else
706         aSz.Height() = mpTextWindow->GetTextEngine()->GetTextHeight();
707 
708     if ( nColumns )
709         aSz.Width() = nColumns*aCharSz.Width();
710     else
711         aSz.Width() = mpTextWindow->GetTextEngine()->CalcTextWidth();
712 
713     if ( mpHScrollBar )
714         aSz.Height() += mpHScrollBar->GetSizePixel().Height();
715     if ( mpVScrollBar )
716         aSz.Width() += mpVScrollBar->GetSizePixel().Width();
717 
718     return aSz;
719 }
720 
721 void ImpSvMEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
722 {
723     static const sal_Unicode sampleText[] = { 'x', '\0' };
724     Size aOutSz = mpTextWindow->GetOutputSizePixel();
725     Size aCharSz( mpTextWindow->GetTextWidth( sampleText ), mpTextWindow->GetTextHeight() );
726     rnCols = (sal_uInt16) (aOutSz.Width()/aCharSz.Width());
727     rnLines = (sal_uInt16) (aOutSz.Height()/aCharSz.Height());
728 }
729 
730 void ImpSvMEdit::Enable( sal_Bool bEnable )
731 {
732     mpTextWindow->Enable( bEnable );
733     if ( mpHScrollBar )
734         mpHScrollBar->Enable( bEnable );
735     if ( mpVScrollBar )
736         mpVScrollBar->Enable( bEnable );
737 }
738 
739 sal_Bool ImpSvMEdit::HandleCommand( const CommandEvent& rCEvt )
740 {
741     sal_Bool bDone = sal_False;
742     if ( ( rCEvt.GetCommand() == COMMAND_WHEEL ) ||
743          ( rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL ) ||
744          ( rCEvt.GetCommand() == COMMAND_AUTOSCROLL ) )
745     {
746         mpTextWindow->HandleScrollCommand( rCEvt, mpHScrollBar, mpVScrollBar );
747         bDone = sal_True;
748     }
749     return bDone;
750 }
751 
752 
753 TextWindow::TextWindow( Window* pParent ) : Window( pParent )
754 {
755     mbInMBDown = sal_False;
756     mbSelectOnTab = sal_True;
757     mbFocusSelectionHide = sal_False;
758     mbIgnoreTab = sal_False;
759     mbActivePopup = sal_False;
760     mbSelectOnTab = sal_True;
761 
762     SetPointer( Pointer( POINTER_TEXT ) );
763 
764     mpExtTextEngine = new ExtTextEngine;
765     mpExtTextEngine->SetMaxTextLen( STRING_MAXLEN );
766     if( pParent->GetStyle() & WB_BORDER )
767         mpExtTextEngine->SetLeftMargin( 2 );
768     mpExtTextEngine->SetLocale( GetSettings().GetLocale() );
769     mpExtTextView = new ExtTextView( mpExtTextEngine, this );
770     mpExtTextEngine->InsertView( mpExtTextView );
771     mpExtTextEngine->EnableUndo( sal_True );
772     mpExtTextView->ShowCursor();
773 
774     Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor();
775     SetBackground( aBackgroundColor );
776     pParent->SetBackground( aBackgroundColor );
777 }
778 
779 TextWindow::~TextWindow()
780 {
781     delete mpExtTextView;
782     delete mpExtTextEngine;
783 }
784 
785 void TextWindow::MouseMove( const MouseEvent& rMEvt )
786 {
787     mpExtTextView->MouseMove( rMEvt );
788     Window::MouseMove( rMEvt );
789 }
790 
791 void TextWindow::MouseButtonDown( const MouseEvent& rMEvt )
792 {
793     mbInMBDown = sal_True;  // Dann im GetFocus nicht alles selektieren wird
794     mpExtTextView->MouseButtonDown( rMEvt );
795     Window::MouseButtonDown( rMEvt );
796     GrabFocus();
797     mbInMBDown = sal_False;
798 }
799 
800 void TextWindow::MouseButtonUp( const MouseEvent& rMEvt )
801 {
802     mpExtTextView->MouseButtonUp( rMEvt );
803     Window::MouseButtonUp( rMEvt );
804 }
805 
806 void TextWindow::KeyInput( const KeyEvent& rKEvent )
807 {
808     sal_Bool bDone = sal_False;
809     sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
810     if ( nCode == com::sun::star::awt::Key::SELECT_ALL ||
811          ( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() )
812        )
813     {
814         mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) );
815         bDone = sal_True;
816     }
817     else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() )
818     {
819         if ( Edit::GetGetSpecialCharsFunction() )
820         {
821             // Damit die Selektion erhalten bleibt
822             mbActivePopup = sal_True;
823             XubString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() );
824             if ( aChars.Len() )
825             {
826                 mpExtTextView->InsertText( aChars );
827                 mpExtTextView->GetTextEngine()->SetModified( sal_True );
828             }
829             mbActivePopup = sal_False;
830             bDone = sal_True;
831         }
832     }
833     else if ( nCode == KEY_TAB )
834     {
835         if ( !mbIgnoreTab || rKEvent.GetKeyCode().IsMod1() )
836             bDone = mpExtTextView->KeyInput( rKEvent  );
837     }
838     else
839     {
840         bDone = mpExtTextView->KeyInput( rKEvent  );
841     }
842 
843     if ( !bDone )
844         Window::KeyInput( rKEvent );
845 }
846 
847 void TextWindow::Paint( const Rectangle& rRect )
848 {
849     mpExtTextView->Paint( rRect );
850 }
851 
852 void TextWindow::Resize()
853 {
854 }
855 
856 void TextWindow::Command( const CommandEvent& rCEvt )
857 {
858     if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
859     {
860         PopupMenu* pPopup = Edit::CreatePopupMenu();
861         const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
862         if ( rStyleSettings.GetOptions() & STYLE_OPTION_HIDEDISABLED )
863             pPopup->SetMenuFlags( MENU_FLAG_HIDEDISABLEDENTRIES );
864         if ( !mpExtTextView->HasSelection() )
865         {
866             pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False );
867             pPopup->EnableItem( SV_MENU_EDIT_COPY, sal_False );
868             pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False );
869         }
870         if ( mpExtTextView->IsReadOnly() )
871         {
872             pPopup->EnableItem( SV_MENU_EDIT_CUT, sal_False );
873             pPopup->EnableItem( SV_MENU_EDIT_PASTE, sal_False );
874             pPopup->EnableItem( SV_MENU_EDIT_DELETE, sal_False );
875             pPopup->EnableItem( SV_MENU_EDIT_INSERTSYMBOL, sal_False );
876         }
877         if ( !mpExtTextView->GetTextEngine()->HasUndoManager() || !mpExtTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() )
878         {
879             pPopup->EnableItem( SV_MENU_EDIT_UNDO, sal_False );
880         }
881 //      if ( ( maSelection.Min() == 0 ) && ( maSelection.Max() == maText.Len() ) )
882 //      {
883 //          pPopup->EnableItem( SV_MENU_EDIT_SELECTALL, sal_False );
884 //      }
885         if ( !Edit::GetGetSpecialCharsFunction() )
886         {
887             sal_uInt16 nPos = pPopup->GetItemPos( SV_MENU_EDIT_INSERTSYMBOL );
888             pPopup->RemoveItem( nPos );
889             pPopup->RemoveItem( nPos-1 );
890         }
891 
892         mbActivePopup = sal_True;
893         Point aPos = rCEvt.GetMousePosPixel();
894         if ( !rCEvt.IsMouseEvent() )
895         {
896             // !!! Irgendwann einmal Menu zentriert in der Selektion anzeigen !!!
897             Size aSize = GetOutputSizePixel();
898             aPos = Point( aSize.Width()/2, aSize.Height()/2 );
899         }
900 //      pPopup->RemoveDisabledEntries();
901         sal_uInt16 n = pPopup->Execute( this, aPos );
902         Edit::DeletePopupMenu( pPopup );
903         switch ( n )
904         {
905             case SV_MENU_EDIT_UNDO:     mpExtTextView->Undo();
906                                         mpExtTextEngine->SetModified( sal_True );
907                                         mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
908                                         break;
909             case SV_MENU_EDIT_CUT:      mpExtTextView->Cut();
910                                         mpExtTextEngine->SetModified( sal_True );
911                                         mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
912                                         break;
913             case SV_MENU_EDIT_COPY:     mpExtTextView->Copy();
914                                         break;
915             case SV_MENU_EDIT_PASTE:    mpExtTextView->Paste();
916                                         mpExtTextEngine->SetModified( sal_True );
917                                         mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
918                                         break;
919             case SV_MENU_EDIT_DELETE:   mpExtTextView->DeleteSelected();
920                                         mpExtTextEngine->SetModified( sal_True );
921                                         mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
922                                         break;
923             case SV_MENU_EDIT_SELECTALL:    mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFFFFFF, 0xFFFF ) ) );
924                                             break;
925             case SV_MENU_EDIT_INSERTSYMBOL:
926                 {
927                     XubString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() );
928                     if ( aChars.Len() )
929                     {
930                         mpExtTextView->InsertText( aChars );
931                         mpExtTextEngine->SetModified( sal_True );
932                         mpExtTextEngine->Broadcast( TextHint( TEXT_HINT_MODIFIED ) );
933                     }
934                 }
935                 break;
936         }
937         mbActivePopup = sal_False;
938     }
939     else
940     {
941         mpExtTextView->Command( rCEvt );
942     }
943     Window::Command( rCEvt );
944 }
945 
946 void TextWindow::GetFocus()
947 {
948     Window::GetFocus();
949     if ( !mbActivePopup )
950     {
951         sal_Bool bGotoCursor = !mpExtTextView->IsReadOnly();
952         if ( mbFocusSelectionHide && IsReallyVisible() && !mpExtTextView->IsReadOnly()
953                 && ( mbSelectOnTab &&
954                     (!mbInMBDown || ( GetSettings().GetStyleSettings().GetSelectionOptions() & SELECTION_OPTION_FOCUS ) )) )
955         {
956             // Alles selektieren, aber nicht scrollen
957             sal_Bool bAutoScroll = mpExtTextView->IsAutoScroll();
958             mpExtTextView->SetAutoScroll( sal_False );
959             mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFF, 0xFFFF ) ) );
960             mpExtTextView->SetAutoScroll( bAutoScroll );
961             bGotoCursor = sal_False;
962         }
963         mpExtTextView->SetPaintSelection( sal_True );
964         mpExtTextView->ShowCursor( bGotoCursor );
965     }
966 }
967 
968 void TextWindow::LoseFocus()
969 {
970     Window::LoseFocus();
971 
972     if ( mbFocusSelectionHide && !mbActivePopup )
973         mpExtTextView->SetPaintSelection( sal_False );
974 }
975 
976 // virtual
977 ::css::uno::Reference< ::css::awt::XWindowPeer >
978 TextWindow::GetComponentInterface(sal_Bool bCreate)
979 {
980     ::css::uno::Reference< ::css::awt::XWindowPeer > xPeer(
981         Window::GetComponentInterface(false));
982     if (!xPeer.is() && bCreate)
983     {
984         xPeer = new ::svt::TextWindowPeer(*GetTextView(), true);
985         SetComponentInterface(xPeer);
986     }
987     return xPeer;
988 }
989 
990 MultiLineEdit::MultiLineEdit( Window* pParent, WinBits nWinStyle )
991     : Edit( pParent, nWinStyle )
992 {
993     SetType( WINDOW_MULTILINEEDIT );
994     pImpSvMEdit = new ImpSvMEdit( this, nWinStyle );
995     ImplInitSettings( sal_True, sal_True, sal_True );
996     pUpdateDataTimer = 0;
997 
998     SetCompoundControl( sal_True );
999     SetStyle( ImplInitStyle( nWinStyle ) );
1000 }
1001 
1002 MultiLineEdit::MultiLineEdit( Window* pParent, const ResId& rResId )
1003     : Edit( pParent, rResId.SetRT( RSC_MULTILINEEDIT ) )
1004 {
1005     SetType( WINDOW_MULTILINEEDIT );
1006     WinBits nWinStyle = rResId.GetWinBits();
1007     pImpSvMEdit = new ImpSvMEdit( this, nWinStyle );
1008     ImplInitSettings( sal_True, sal_True, sal_True );
1009     pUpdateDataTimer = 0;
1010 
1011     sal_uInt16 nMaxLen = Edit::GetMaxTextLen();
1012     if ( nMaxLen )
1013         SetMaxTextLen( nMaxLen );
1014 
1015     SetText( Edit::GetText() );
1016 
1017     if ( IsVisible() )
1018         pImpSvMEdit->Resize();
1019 
1020     SetCompoundControl( sal_True );
1021     SetStyle( ImplInitStyle( nWinStyle ) );
1022 
1023     // Base Edit ctor could call Show already, but that would cause problems
1024     // with accessibility, as Show might (indirectly) trigger a call to virtual
1025     // GetComponentInterface, which is the Edit's base version instead of the
1026     // MultiLineEdit's version while in the base Edit ctor:
1027     if ((GetStyle() & WB_HIDE) == 0)
1028         Show();
1029 }
1030 
1031 MultiLineEdit::~MultiLineEdit()
1032 {
1033     {
1034         ::std::auto_ptr< ImpSvMEdit > pDelete( pImpSvMEdit );
1035         pImpSvMEdit = NULL;
1036     }
1037     delete pUpdateDataTimer;
1038 }
1039 
1040 WinBits MultiLineEdit::ImplInitStyle( WinBits nStyle )
1041 {
1042     if ( !(nStyle & WB_NOTABSTOP) )
1043         nStyle |= WB_TABSTOP;
1044 
1045     if ( !(nStyle & WB_NOGROUP) )
1046         nStyle |= WB_GROUP;
1047 
1048     if ( !(nStyle & WB_IGNORETAB ))
1049         nStyle |= WINDOW_DLGCTRL_MOD1TAB;
1050 
1051     return nStyle;
1052 }
1053 
1054 
1055 void MultiLineEdit::ImplInitSettings( sal_Bool /*bFont*/, sal_Bool /*bForeground*/, sal_Bool bBackground )
1056 {
1057     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1058 
1059     // Der Font muss immer mit manipuliert werden, weil die TextEngine
1060     // sich nicht um TextColor/Background kuemmert
1061 
1062     Color aTextColor = rStyleSettings.GetFieldTextColor();
1063     if ( IsControlForeground() )
1064         aTextColor = GetControlForeground();
1065     if ( !IsEnabled() )
1066         aTextColor = rStyleSettings.GetDisableColor();
1067 
1068     Font aFont = rStyleSettings.GetFieldFont();
1069     if ( IsControlFont() )
1070         aFont.Merge( GetControlFont() );
1071     aFont.SetTransparent( IsPaintTransparent() );
1072     SetZoomedPointFont( aFont );
1073     Font TheFont = GetFont();
1074     TheFont.SetColor( aTextColor );
1075     if( IsPaintTransparent() )
1076         TheFont.SetFillColor( Color( COL_TRANSPARENT ) );
1077     else
1078         TheFont.SetFillColor( IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor() );
1079     pImpSvMEdit->GetTextWindow()->SetFont( TheFont );
1080     pImpSvMEdit->GetTextWindow()->GetTextEngine()->SetFont( TheFont );
1081     pImpSvMEdit->GetTextWindow()->SetTextColor( aTextColor );
1082 
1083     if ( bBackground )
1084     {
1085         if( IsPaintTransparent() )
1086         {
1087             pImpSvMEdit->GetTextWindow()->SetPaintTransparent( sal_True );
1088             pImpSvMEdit->GetTextWindow()->SetBackground();
1089             pImpSvMEdit->GetTextWindow()->SetControlBackground();
1090             SetBackground();
1091             SetControlBackground();
1092         }
1093         else
1094         {
1095             if( IsControlBackground() )
1096                 pImpSvMEdit->GetTextWindow()->SetBackground( GetControlBackground() );
1097             else
1098                 pImpSvMEdit->GetTextWindow()->SetBackground( rStyleSettings.GetFieldColor() );
1099             // Auch am MultiLineEdit einstellen, weil die TextComponent
1100             // ggf. die Scrollbars hidet.
1101             SetBackground( pImpSvMEdit->GetTextWindow()->GetBackground() );
1102         }
1103     }
1104 }
1105 
1106 void MultiLineEdit::Modify()
1107 {
1108     aModifyHdlLink.Call( this );
1109 
1110     CallEventListeners( VCLEVENT_EDIT_MODIFY );
1111 
1112     if ( pUpdateDataTimer )
1113         pUpdateDataTimer->Start();
1114 }
1115 
1116 IMPL_LINK( MultiLineEdit, ImpUpdateDataHdl, Timer*, EMPTYARG )
1117 {
1118     UpdateData();
1119     return 0;
1120 }
1121 
1122 void MultiLineEdit::UpdateData()
1123 {
1124     aUpdateDataHdlLink.Call( this );
1125 }
1126 
1127 void MultiLineEdit::SetModifyFlag()
1128 {
1129     pImpSvMEdit->SetModified( sal_True );
1130 }
1131 
1132 void MultiLineEdit::ClearModifyFlag()
1133 {
1134     pImpSvMEdit->SetModified( sal_False );
1135 }
1136 
1137 sal_Bool MultiLineEdit::IsModified() const
1138 {
1139     return pImpSvMEdit->IsModified();
1140 }
1141 
1142 void MultiLineEdit::EnableUpdateData( sal_uLong nTimeout )
1143 {
1144     if ( !nTimeout )
1145         DisableUpdateData();
1146     else
1147     {
1148         if ( !pUpdateDataTimer )
1149         {
1150             pUpdateDataTimer = new Timer;
1151             pUpdateDataTimer->SetTimeoutHdl( LINK( this, MultiLineEdit, ImpUpdateDataHdl ) );
1152         }
1153         pUpdateDataTimer->SetTimeout( nTimeout );
1154     }
1155 }
1156 
1157 void MultiLineEdit::SetReadOnly( sal_Bool bReadOnly )
1158 {
1159     pImpSvMEdit->SetReadOnly( bReadOnly );
1160     Edit::SetReadOnly( bReadOnly );
1161 
1162     // #94921# ReadOnly can be overwritten in InitFromStyle() when WB not set.
1163     WinBits nStyle = GetStyle();
1164     if ( bReadOnly )
1165         nStyle |= WB_READONLY;
1166     else
1167         nStyle &= ~WB_READONLY;
1168     SetStyle( nStyle );
1169 }
1170 
1171 sal_Bool MultiLineEdit::IsReadOnly() const
1172 {
1173     return pImpSvMEdit->IsReadOnly();
1174 }
1175 
1176 void MultiLineEdit::SetMaxTextLen( xub_StrLen nMaxLen )
1177 {
1178     pImpSvMEdit->SetMaxTextLen( nMaxLen );
1179 }
1180 
1181 xub_StrLen MultiLineEdit::GetMaxTextLen() const
1182 {
1183     return pImpSvMEdit->GetMaxTextLen();
1184 }
1185 
1186 void MultiLineEdit::ReplaceSelected( const String& rStr )
1187 {
1188     pImpSvMEdit->InsertText( rStr );
1189 }
1190 
1191 void MultiLineEdit::DeleteSelected()
1192 {
1193     pImpSvMEdit->InsertText( String() );
1194 }
1195 
1196 String MultiLineEdit::GetSelected() const
1197 {
1198     return pImpSvMEdit->GetSelected();
1199 }
1200 
1201 String MultiLineEdit::GetSelected( LineEnd aSeparator ) const
1202 {
1203     return pImpSvMEdit->GetSelected( aSeparator );
1204 }
1205 
1206 void MultiLineEdit::Cut()
1207 {
1208     pImpSvMEdit->Cut();
1209 }
1210 
1211 void MultiLineEdit::Copy()
1212 {
1213     pImpSvMEdit->Copy();
1214 }
1215 
1216 void MultiLineEdit::Paste()
1217 {
1218     pImpSvMEdit->Paste();
1219 }
1220 
1221 void MultiLineEdit::SetText( const String& rStr )
1222 {
1223     pImpSvMEdit->SetText( rStr );
1224 }
1225 
1226 String MultiLineEdit::GetText() const
1227 {
1228     return pImpSvMEdit->GetText();
1229 }
1230 
1231 String MultiLineEdit::GetText( LineEnd aSeparator ) const
1232 {
1233     return pImpSvMEdit->GetText( aSeparator );
1234 }
1235 
1236 String MultiLineEdit::GetTextLines() const
1237 {
1238     return pImpSvMEdit->GetTextLines();
1239 }
1240 
1241 String MultiLineEdit::GetTextLines(  LineEnd aSeparator ) const
1242 {
1243     return pImpSvMEdit->GetTextLines( aSeparator );
1244 }
1245 
1246 void MultiLineEdit::Resize()
1247 {
1248     pImpSvMEdit->Resize();
1249 }
1250 
1251 void MultiLineEdit::GetFocus()
1252 {
1253     if ( !pImpSvMEdit )  // might be called from within the dtor, when pImpSvMEdit == NULL is a valid state
1254         return;
1255 
1256     Edit::GetFocus();
1257     pImpSvMEdit->GetFocus();
1258 }
1259 
1260 void MultiLineEdit::SetSelection( const Selection& rSelection )
1261 {
1262     pImpSvMEdit->SetSelection( rSelection );
1263 }
1264 
1265 const Selection& MultiLineEdit::GetSelection() const
1266 {
1267     return pImpSvMEdit->GetSelection();
1268 }
1269 
1270 Size MultiLineEdit::CalcMinimumSize() const
1271 {
1272     Size aSz = pImpSvMEdit->CalcMinimumSize();
1273 
1274     sal_Int32 nLeft, nTop, nRight, nBottom;
1275     ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
1276     aSz.Width() += nLeft+nRight;
1277     aSz.Height() += nTop+nBottom;
1278 
1279     return aSz;
1280 }
1281 
1282 Size MultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const
1283 {
1284     Size aSz = rPrefSize;
1285     sal_Int32 nLeft, nTop, nRight, nBottom;
1286     ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
1287 
1288     // In der Hoehe auf ganze Zeilen justieren
1289 
1290     long nHeight = aSz.Height() - nTop - nBottom;
1291     long nLineHeight = pImpSvMEdit->CalcSize( 1, 1 ).Height();
1292     long nLines = nHeight / nLineHeight;
1293     if ( nLines < 1 )
1294         nLines = 1;
1295 
1296     aSz.Height() = nLines * nLineHeight;
1297     aSz.Height() += nTop+nBottom;
1298 
1299     return aSz;
1300 }
1301 
1302 Size MultiLineEdit::CalcSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1303 {
1304     Size aSz = pImpSvMEdit->CalcSize( nColumns, nLines );
1305 
1306     sal_Int32 nLeft, nTop, nRight, nBottom;
1307     ((Window*)this)->GetBorder( nLeft, nTop, nRight, nBottom );
1308     aSz.Width() += nLeft+nRight;
1309     aSz.Height() += nTop+nBottom;
1310     return aSz;
1311 }
1312 
1313 void MultiLineEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1314 {
1315     pImpSvMEdit->GetMaxVisColumnsAndLines( rnCols, rnLines );
1316 }
1317 
1318 void MultiLineEdit::StateChanged( StateChangedType nType )
1319 {
1320     if( nType == STATE_CHANGE_ENABLE )
1321     {
1322         pImpSvMEdit->Enable( IsEnabled() );
1323         ImplInitSettings( sal_True, sal_False, sal_False );
1324     }
1325     else if( nType == STATE_CHANGE_READONLY )
1326     {
1327         pImpSvMEdit->SetReadOnly( IsReadOnly() );
1328     }
1329     else if ( nType == STATE_CHANGE_ZOOM )
1330     {
1331         pImpSvMEdit->GetTextWindow()->SetZoom( GetZoom() );
1332         ImplInitSettings( sal_True, sal_False, sal_False );
1333         Resize();
1334     }
1335     else if ( nType == STATE_CHANGE_CONTROLFONT )
1336     {
1337         ImplInitSettings( sal_True, sal_False, sal_False );
1338         Resize();
1339         Invalidate();
1340     }
1341     else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
1342     {
1343         ImplInitSettings( sal_False, sal_True, sal_False );
1344         Invalidate();
1345     }
1346     else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
1347     {
1348         ImplInitSettings( sal_False, sal_False, sal_True );
1349         Invalidate();
1350     }
1351     else if ( nType == STATE_CHANGE_STYLE )
1352     {
1353         pImpSvMEdit->InitFromStyle( GetStyle() );
1354         SetStyle( ImplInitStyle( GetStyle() ) );
1355     }
1356     else if ( nType == STATE_CHANGE_INITSHOW )
1357     {
1358         if( IsPaintTransparent() )
1359         {
1360             pImpSvMEdit->GetTextWindow()->SetPaintTransparent( sal_True );
1361             pImpSvMEdit->GetTextWindow()->SetBackground();
1362             pImpSvMEdit->GetTextWindow()->SetControlBackground();
1363             SetBackground();
1364             SetControlBackground();
1365         }
1366     }
1367 
1368     Control::StateChanged( nType );
1369 }
1370 
1371 void MultiLineEdit::DataChanged( const DataChangedEvent& rDCEvt )
1372 {
1373     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1374          (rDCEvt.GetFlags() & SETTINGS_STYLE) )
1375     {
1376         ImplInitSettings( sal_True, sal_True, sal_True );
1377         Resize();
1378         Invalidate();
1379     }
1380     else
1381         Control::DataChanged( rDCEvt );
1382 }
1383 
1384 void MultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
1385 {
1386     ImplInitSettings( sal_True, sal_True, sal_True );
1387 
1388     Point aPos = pDev->LogicToPixel( rPos );
1389     Size aSize = pDev->LogicToPixel( rSize );
1390     Font aFont = pImpSvMEdit->GetTextWindow()->GetDrawPixelFont( pDev );
1391     aFont.SetTransparent( sal_True );
1392     OutDevType eOutDevType = pDev->GetOutDevType();
1393 
1394     pDev->Push();
1395     pDev->SetMapMode();
1396     pDev->SetFont( aFont );
1397     pDev->SetTextFillColor();
1398 
1399     // Border/Background
1400     pDev->SetLineColor();
1401     pDev->SetFillColor();
1402     sal_Bool bBorder = !(nFlags & WINDOW_DRAW_NOBORDER ) && (GetStyle() & WB_BORDER);
1403     sal_Bool bBackground = !(nFlags & WINDOW_DRAW_NOBACKGROUND) && IsControlBackground();
1404     if ( bBorder || bBackground )
1405     {
1406         Rectangle aRect( aPos, aSize );
1407         if ( bBorder )
1408         {
1409             DecorationView aDecoView( pDev );
1410             aRect = aDecoView.DrawFrame( aRect, FRAME_DRAW_DOUBLEIN );
1411         }
1412         if ( bBackground )
1413         {
1414             pDev->SetFillColor( GetControlBackground() );
1415             pDev->DrawRect( aRect );
1416         }
1417     }
1418 
1419     // Inhalt
1420     if ( ( nFlags & WINDOW_DRAW_MONO ) || ( eOutDevType == OUTDEV_PRINTER ) )
1421         pDev->SetTextColor( Color( COL_BLACK ) );
1422     else
1423     {
1424         if ( !(nFlags & WINDOW_DRAW_NODISABLE ) && !IsEnabled() )
1425         {
1426             const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1427             pDev->SetTextColor( rStyleSettings.GetDisableColor() );
1428         }
1429         else
1430         {
1431             pDev->SetTextColor( GetTextColor() );
1432         }
1433     }
1434 
1435     XubString aText = GetText();
1436     Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() );
1437     sal_uLong nLines = (sal_uLong) (aSize.Height() / aTextSz.Height());
1438     if ( !nLines )
1439         nLines = 1;
1440     aTextSz.Height() = nLines*aTextSz.Height();
1441     long nOnePixel = GetDrawPixel( pDev, 1 );
1442     long nOffX = 3*nOnePixel;
1443     long nOffY = 2*nOnePixel;
1444 
1445     // Clipping?
1446     if ( ( nOffY < 0  ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) )
1447     {
1448         Rectangle aClip( aPos, aSize );
1449         if ( aTextSz.Height() > aSize.Height() )
1450             aClip.Bottom() += aTextSz.Height() - aSize.Height() + 1;  // Damit HP-Drucker nicht 'weg-optimieren'
1451         pDev->IntersectClipRegion( aClip );
1452     }
1453 
1454     TextEngine aTE;
1455     aTE.SetText( GetText() );
1456     aTE.SetMaxTextWidth( aSize.Width() );
1457     aTE.SetFont( aFont );
1458     aTE.SetTextAlign( pImpSvMEdit->GetTextWindow()->GetTextEngine()->GetTextAlign() );
1459     aTE.Draw( pDev, Point( aPos.X() + nOffX, aPos.Y() + nOffY ) );
1460 
1461     pDev->Pop();
1462 }
1463 
1464 long MultiLineEdit::Notify( NotifyEvent& rNEvt )
1465 {
1466     long nDone = 0;
1467     if( rNEvt.GetType() == EVENT_COMMAND )
1468     {
1469         nDone = pImpSvMEdit->HandleCommand( *rNEvt.GetCommandEvent() );
1470     }
1471     return nDone ? nDone : Edit::Notify( rNEvt );
1472 }
1473 
1474 long MultiLineEdit::PreNotify( NotifyEvent& rNEvt )
1475 {
1476     long nDone = 0;
1477 
1478 #if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL)
1479     if( rNEvt.GetType() == EVENT_KEYINPUT )
1480     {
1481         const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
1482         if ( ( rKEvent.GetKeyCode().GetCode() == KEY_W ) && rKEvent.GetKeyCode().IsMod1() && rKEvent.GetKeyCode().IsMod2() )
1483         {
1484             SetRightToLeft( !IsRightToLeft() );
1485         }
1486     }
1487 #endif
1488 
1489     if( ( rNEvt.GetType() == EVENT_KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) )
1490     {
1491         const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
1492         if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) )
1493         {
1494             nDone = 1;
1495             TextSelection aSel = pImpSvMEdit->GetTextWindow()->GetTextView()->GetSelection();
1496             if ( aSel.HasRange() )
1497             {
1498                 aSel.GetStart() = aSel.GetEnd();
1499                 pImpSvMEdit->GetTextWindow()->GetTextView()->SetSelection( aSel );
1500             }
1501             else
1502             {
1503                 switch ( rKEvent.GetKeyCode().GetCode() )
1504                 {
1505                     case KEY_UP:
1506                     {
1507                         if ( pImpSvMEdit->GetVScrollBar() )
1508                             pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEUP );
1509                     }
1510                     break;
1511                     case KEY_DOWN:
1512                     {
1513                         if ( pImpSvMEdit->GetVScrollBar() )
1514                             pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_LINEDOWN );
1515                     }
1516                     break;
1517                     case KEY_PAGEUP :
1518                     {
1519                         if ( pImpSvMEdit->GetVScrollBar() )
1520                             pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEUP );
1521                     }
1522                     break;
1523                     case KEY_PAGEDOWN:
1524                     {
1525                         if ( pImpSvMEdit->GetVScrollBar() )
1526                             pImpSvMEdit->GetVScrollBar()->DoScrollAction( SCROLL_PAGEDOWN );
1527                     }
1528                     break;
1529                     case KEY_LEFT:
1530                     {
1531                         if ( pImpSvMEdit->GetHScrollBar() )
1532                             pImpSvMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEUP );
1533                     }
1534                     break;
1535                     case KEY_RIGHT:
1536                     {
1537                         if ( pImpSvMEdit->GetHScrollBar() )
1538                             pImpSvMEdit->GetHScrollBar()->DoScrollAction( SCROLL_LINEDOWN );
1539                     }
1540                     break;
1541                     case KEY_HOME:
1542                     {
1543                         if ( rKEvent.GetKeyCode().IsMod1() )
1544                             pImpSvMEdit->GetTextWindow()->GetTextView()->
1545                                 SetSelection( TextSelection( TextPaM( 0, 0 ) ) );
1546                     }
1547                     break;
1548                     case KEY_END:
1549                     {
1550                         if ( rKEvent.GetKeyCode().IsMod1() )
1551                             pImpSvMEdit->GetTextWindow()->GetTextView()->
1552                                 SetSelection( TextSelection( TextPaM( 0xFFFF, 0xFFFF ) ) );
1553                     }
1554                     break;
1555                     default:
1556                     {
1557                         nDone = 0;
1558                     }
1559                 }
1560             }
1561         }
1562     }
1563 
1564     return nDone ? nDone : Edit::PreNotify( rNEvt );
1565 }
1566 
1567 //
1568 // Internas fuer abgeleitete Klassen, z.B. TextComponent
1569 
1570 ExtTextEngine* MultiLineEdit::GetTextEngine() const
1571 {
1572     return pImpSvMEdit->GetTextWindow()->GetTextEngine();
1573 }
1574 
1575 ExtTextView* MultiLineEdit::GetTextView() const
1576 {
1577     return pImpSvMEdit->GetTextWindow()->GetTextView();
1578 }
1579 
1580 ScrollBar* MultiLineEdit::GetHScrollBar() const
1581 {
1582     return pImpSvMEdit->GetHScrollBar();
1583 }
1584 
1585 
1586 ScrollBar* MultiLineEdit::GetVScrollBar() const
1587 {
1588     return pImpSvMEdit->GetVScrollBar();
1589 }
1590 
1591 void MultiLineEdit::EnableFocusSelectionHide( sal_Bool bHide )
1592 {
1593     pImpSvMEdit->GetTextWindow()->SetAutoFocusHide( bHide );
1594 }
1595 
1596 sal_Bool MultiLineEdit::IsFocusSelectionHideEnabled() const
1597 {
1598     return pImpSvMEdit->GetTextWindow()->IsAutoFocusHide();
1599 }
1600 
1601 
1602 void MultiLineEdit::SetLeftMargin( sal_uInt16 n )
1603 {
1604     if ( GetTextEngine() )
1605         GetTextEngine()->SetLeftMargin( n );
1606 }
1607 
1608 sal_uInt16 MultiLineEdit::GetLeftMargin() const
1609 {
1610     if ( GetTextEngine() )
1611         return GetTextEngine()->GetLeftMargin();
1612     else
1613         return 0;
1614 }
1615 
1616 void MultiLineEdit::SetRightToLeft( sal_Bool bRightToLeft )
1617 {
1618     if ( GetTextEngine() )
1619     {
1620         GetTextEngine()->SetRightToLeft( bRightToLeft );
1621         GetTextView()->ShowCursor();
1622     }
1623 }
1624 
1625 sal_Bool MultiLineEdit::IsRightToLeft() const
1626 {
1627     sal_Bool bRightToLeft = sal_False;
1628 
1629     if ( GetTextEngine() )
1630         bRightToLeft = GetTextEngine()->IsRightToLeft();
1631 
1632     return bRightToLeft;
1633 }
1634 
1635 // virtual
1636 ::css::uno::Reference< ::css::awt::XWindowPeer >
1637 MultiLineEdit::GetComponentInterface(sal_Bool bCreate)
1638 {
1639     ::css::uno::Reference< ::css::awt::XWindowPeer > xPeer(
1640         Edit::GetComponentInterface(false));
1641     if (!xPeer.is() && bCreate)
1642     {
1643         ::std::auto_ptr< VCLXMultiLineEdit > xEdit(new VCLXMultiLineEdit());
1644         xEdit->SetWindow(this);
1645         xPeer = xEdit.release();
1646         SetComponentInterface(xPeer);
1647     }
1648     return xPeer;
1649 }
1650 /*-- 11.08.2004 11:29:23---------------------------------------------------
1651 
1652   -----------------------------------------------------------------------*/
1653 void MultiLineEdit::DisableSelectionOnFocus()
1654 {
1655     pImpSvMEdit->GetTextWindow()->DisableSelectionOnFocus();
1656 }
1657