xref: /aoo42x/main/svtools/source/edit/svmedit.cxx (revision cdf0e10c)
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