xref: /AOO41X/main/forms/source/richtext/richtextimplcontrol.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_forms.hxx"
30 #include "richtextimplcontrol.hxx"
31 #include "textattributelistener.hxx"
32 #include "richtextengine.hxx"
33 #include <editeng/editeng.hxx>
34 #include <editeng/editview.hxx>
35 #include <editeng/eeitem.hxx>
36 #include <editeng/editstat.hxx>
37 #ifndef _SVX_SVXIDS_HRC
38 #include <svx/svxids.hrc>
39 #endif
40 #include <editeng/scripttypeitem.hxx>
41 
42 #include <editeng/editobj.hxx>
43 #include <svl/itempool.hxx>
44 #include <svl/itemset.hxx>
45 #include <tools/mapunit.hxx>
46 #include <vcl/window.hxx>
47 #include <vcl/svapp.hxx>
48 
49 #include <memory>
50 
51 #define EMPTY_PAPER_SIZE    0x7FFFFFFF
52 
53 //........................................................................
54 namespace frm
55 {
56 //........................................................................
57     //====================================================================
58     //= RichTextControlImpl
59     //====================================================================
60     //--------------------------------------------------------------------
61     RichTextControlImpl::RichTextControlImpl( Control* _pAntiImpl, RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttrListener, ITextSelectionListener* _pSelectionListener )
62         :m_pAntiImpl            ( _pAntiImpl          )
63         ,m_pViewport            ( NULL                )
64         ,m_pHScroll             ( NULL                )
65         ,m_pVScroll             ( NULL                )
66         ,m_pScrollCorner        ( NULL                )
67         ,m_pEngine              ( _pEngine            )
68         ,m_pView                ( NULL                )
69         ,m_pTextAttrListener    ( _pTextAttrListener  )
70         ,m_pSelectionListener   ( _pSelectionListener )
71         ,m_bHasEverBeenShown    ( false               )
72     {
73         OSL_ENSURE( m_pAntiImpl, "RichTextControlImpl::RichTextControlImpl: invalid window!" );
74         OSL_ENSURE( m_pEngine,   "RichTextControlImpl::RichTextControlImpl: invalid edit engine! This will *definately* crash!" );
75 
76         m_pViewport = new RichTextViewPort( m_pAntiImpl );
77         m_pViewport->setAttributeInvalidationHandler( LINK( this, RichTextControlImpl, OnInvalidateAllAttributes ) );
78         m_pViewport->Show();
79 
80         // ensure that both the window and the reference device have the same map unit
81         MapMode aRefDeviceMapMode( m_pEngine->GetRefDevice()->GetMapMode() );
82         m_pAntiImpl->SetMapMode( aRefDeviceMapMode );
83         m_pViewport->SetMapMode( aRefDeviceMapMode );
84 
85         m_pView = new EditView( m_pEngine, m_pViewport );
86         m_pEngine->InsertView( m_pView );
87         m_pViewport->setView( *m_pView );
88 
89         m_pEngine->registerEngineStatusListener( this );
90 
91         {
92             sal_uLong nViewControlWord = m_pView->GetControlWord();
93             nViewControlWord |= EV_CNTRL_AUTOSCROLL;
94             m_pView->SetControlWord( nViewControlWord );
95         }
96 
97         // ensure that it's initially scrolled to the upper left
98         m_pView->SetVisArea( Rectangle( Point( ), m_pViewport->GetOutputSize() ) );
99 
100         ensureScrollbars();
101 
102         m_pAntiImpl->SetBackground( Wallpaper( m_pAntiImpl->GetSettings().GetStyleSettings().GetFieldColor() ) );
103     }
104 
105     //--------------------------------------------------------------------
106     RichTextControlImpl::~RichTextControlImpl( )
107     {
108         m_pEngine->RemoveView( m_pView );
109         m_pEngine->revokeEngineStatusListener( this );
110         delete m_pView;
111         delete m_pViewport;
112         delete m_pHScroll;
113         delete m_pVScroll;
114         delete m_pScrollCorner;
115     }
116 
117     //--------------------------------------------------------------------
118     void RichTextControlImpl::implUpdateAttribute( AttributeHandlerPool::const_iterator _pHandler )
119     {
120         if  (  ( _pHandler->first == SID_ATTR_CHAR_WEIGHT )
121             || ( _pHandler->first == SID_ATTR_CHAR_POSTURE )
122             || ( _pHandler->first == SID_ATTR_CHAR_FONT )
123             || ( _pHandler->first == SID_ATTR_CHAR_FONTHEIGHT )
124             )
125         {
126             // these are attributes whose value depends on the current script type.
127             // I.e., in real, there are *three* items in the ItemSet: One for each script
128             // type (Latin, Asian, Complex). However, if we have an observer who is interested
129             // in the state of this attribute, we have to kind of *merge* the three attributes
130             // to only one.
131             // This is usefull in case the observer is for instance a toolbox which contains only
132             // an, e.g., "bold" slot, and thus not interested in the particular script type of the
133             // current selection.
134             SvxScriptSetItem aNormalizedSet( (WhichId)_pHandler->first, *m_pView->GetAttribs().GetPool() );
135             normalizeScriptDependentAttribute( aNormalizedSet );
136 
137             implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( aNormalizedSet.GetItemSet() ) );
138         }
139         else
140             implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( m_pView->GetAttribs() ) );
141     }
142 
143     //--------------------------------------------------------------------
144     void RichTextControlImpl::updateAttribute( AttributeId _nAttribute )
145     {
146         AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.find( _nAttribute );
147         if ( pHandler != m_aAttributeHandlers.end() )
148             implUpdateAttribute( pHandler );
149     }
150 
151     //--------------------------------------------------------------------
152     void RichTextControlImpl::updateAllAttributes( )
153     {
154         for (   AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.begin();
155                 pHandler != m_aAttributeHandlers.end();
156                 ++pHandler
157             )
158         {
159             implUpdateAttribute( pHandler );
160         }
161 
162         // notify changes of the selection, if necessary
163         if ( m_pSelectionListener && m_pView )
164         {
165             ESelection aCurrentSelection = m_pView->GetSelection();
166             if ( !aCurrentSelection.IsEqual( m_aLastKnownSelection ) )
167             {
168                 m_aLastKnownSelection = aCurrentSelection;
169                 m_pSelectionListener->onSelectionChanged( m_aLastKnownSelection );
170             }
171         }
172     }
173 
174     //--------------------------------------------------------------------
175     AttributeState RichTextControlImpl::getAttributeState( AttributeId _nAttributeId ) const
176     {
177         StateCache::const_iterator aCachedStatePos = m_aLastKnownStates.find( _nAttributeId );
178         if ( aCachedStatePos == m_aLastKnownStates.end() )
179         {
180             OSL_ENSURE( sal_False, "RichTextControlImpl::getAttributeState: Don't ask for the state of an attribute which I never encountered!" );
181             return AttributeState( eIndetermined );
182         }
183         return aCachedStatePos->second;
184     }
185 
186     //--------------------------------------------------------------------
187     bool RichTextControlImpl::executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rAttribs, AttributeId _nAttribute, const SfxPoolItem* _pArgument, ScriptType _nForScriptType )
188     {
189         // let's see whether we have a handler for this attribute
190         AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttribute );
191         if ( aHandlerPos != m_aAttributeHandlers.end() )
192         {
193             aHandlerPos->second->executeAttribute( _rCurrentAttribs, _rAttribs, _pArgument, _nForScriptType );
194             return true;
195         }
196         return false;
197     }
198 
199     //--------------------------------------------------------------------
200     void RichTextControlImpl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener )
201     {
202         AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId  );
203         if ( aHandlerPos == m_aAttributeHandlers.end() )
204         {
205             ::rtl::Reference< IAttributeHandler > aHandler = AttributeHandlerFactory::getHandlerFor( _nAttributeId, *m_pEngine->GetEmptyItemSet().GetPool() );
206             OSL_ENSURE( aHandler.is(), "RichTextControlImpl::enableAttributeNotification: no handler available for this attribute!" );
207             if ( !aHandler.is() )
208                 return;
209             OSL_POSTCOND( _nAttributeId == aHandler->getAttributeId(), "RichTextControlImpl::enableAttributeNotification: suspicious handler!" );
210 
211             aHandlerPos = m_aAttributeHandlers.insert( AttributeHandlerPool::value_type( _nAttributeId , aHandler ) ).first;
212         }
213 
214         // remember the listener
215         if ( _pListener )
216             m_aAttributeListeners.insert( AttributeListenerPool::value_type( _nAttributeId, _pListener ) );
217 
218         // update (and broadcast) the state of this attribute
219         updateAttribute( _nAttributeId );
220     }
221 
222     //--------------------------------------------------------------------
223     void RichTextControlImpl::disableAttributeNotification( AttributeId _nAttributeId )
224     {
225         // forget the handler for this attribute
226         AttributeHandlerPool::iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId );
227         if ( aHandlerPos != m_aAttributeHandlers.end() )
228             m_aAttributeHandlers.erase( aHandlerPos );
229 
230         // as well as the listener
231         AttributeListenerPool::iterator aListenerPos = m_aAttributeListeners.find( _nAttributeId );
232         if ( aListenerPos != m_aAttributeListeners.end() )
233             m_aAttributeListeners.erase( aListenerPos );
234     }
235 
236     //--------------------------------------------------------------------
237     void RichTextControlImpl::normalizeScriptDependentAttribute( SvxScriptSetItem& _rScriptSetItem )
238     {
239         _rScriptSetItem.GetItemSet().Put( m_pView->GetAttribs(), sal_False );
240         const SfxPoolItem* pNormalizedItem = _rScriptSetItem.GetItemOfScript( getSelectedScriptType() );
241 
242         WhichId nNormalizedWhichId = _rScriptSetItem.GetItemSet().GetPool()->GetWhich( _rScriptSetItem.Which() );
243         if ( pNormalizedItem )
244         {
245             SfxPoolItem* pProperWhich = pNormalizedItem->Clone();
246             pProperWhich->SetWhich( nNormalizedWhichId );
247             _rScriptSetItem.GetItemSet().Put( *pProperWhich );
248             DELETEZ( pProperWhich );
249         }
250         else
251             _rScriptSetItem.GetItemSet().InvalidateItem( nNormalizedWhichId );
252     }
253 
254     //--------------------------------------------------------------------
255     void RichTextControlImpl::implCheckUpdateCache( AttributeId _nAttribute, const AttributeState& _rState )
256     {
257         StateCache::iterator aCachePos = m_aLastKnownStates.find( _nAttribute );
258         if ( aCachePos == m_aLastKnownStates.end() )
259         {   // nothing known about this attribute, yet
260             m_aLastKnownStates.insert( StateCache::value_type( _nAttribute, _rState ) );
261         }
262         else
263         {
264             if ( aCachePos->second == _rState )
265             {
266                 // nothing to do
267                 return;
268             }
269             aCachePos->second = _rState;
270         }
271 
272         // is there a dedicated listener for this particular attribute?
273         AttributeListenerPool::const_iterator aListenerPos = m_aAttributeListeners.find( _nAttribute );
274         if ( aListenerPos != m_aAttributeListeners.end( ) )
275             aListenerPos->second->onAttributeStateChanged( _nAttribute, _rState );
276 
277         // call our global listener, if there is one
278         if ( m_pTextAttrListener )
279             m_pTextAttrListener->onAttributeStateChanged( _nAttribute, _rState );
280     }
281 
282     //--------------------------------------------------------------------
283     ScriptType RichTextControlImpl::getSelectedScriptType() const
284     {
285         ScriptType nScript = m_pView->GetSelectedScriptType();
286         if ( !nScript )
287             nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() );
288         return nScript;
289     }
290 
291     //--------------------------------------------------------------------
292     void RichTextControlImpl::EditEngineStatusChanged( const EditStatus& _rStatus )
293     {
294         sal_uLong nStatusWord( _rStatus.GetStatusWord() );
295         if  (   ( nStatusWord & EE_STAT_TEXTWIDTHCHANGED )
296             ||  ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED )
297             )
298         {
299             if ( ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED ) && windowHasAutomaticLineBreak() )
300                 m_pEngine->SetPaperSize( Size( m_pEngine->GetPaperSize().Width(), m_pEngine->GetTextHeight() ) );
301 
302             updateScrollbars();
303         }
304 
305         bool bHScroll = 0 != ( nStatusWord & EE_STAT_HSCROLL );
306         bool bVScroll = 0 != ( nStatusWord & EE_STAT_VSCROLL );
307 
308         // In case of *no* automatic line breaks, we also need to check for the *range* here.
309         // Normally, we would do this only after a EE_STAT_TEXTWIDTHCHANGED. However, due to a bug
310         // in the EditEngine (I believe so) this is not fired when the engine does not have
311         // the AutoPaperSize bits set.
312         // So in order to be properly notified, we would need the AutoPaperSize. But, with
313         // AutoPaperSize, other things do not work anymore: Either, when we set a MaxAutoPaperSize,
314         // then the view does automatic soft line breaks at the paper end - which we definately do
315         // want. Or, if we did not set a MaxAutoPaperSize, then the view does not automatically scroll
316         // anymore in horizontal direction.
317         // So this is some kind of lose-lose situation ... :(
318         if ( !windowHasAutomaticLineBreak() && bHScroll )
319         {
320             updateScrollbars();
321             return;
322         }
323 
324         if ( bHScroll && m_pHScroll )
325             m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() );
326         if ( bVScroll && m_pVScroll )
327             m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() );
328     }
329 
330     //--------------------------------------------------------------------
331     IMPL_LINK( RichTextControlImpl, OnInvalidateAllAttributes, void*, /*_pNotInterestedIn*/ )
332     {
333         updateAllAttributes();
334         return 0L;
335     }
336 
337     //--------------------------------------------------------------------
338     IMPL_LINK( RichTextControlImpl, OnHScroll, ScrollBar*, _pScrollbar )
339     {
340         m_pView->Scroll( -_pScrollbar->GetDelta(), 0, RGCHK_PAPERSZ1 );
341         return 0L;
342     }
343 
344     //--------------------------------------------------------------------
345     IMPL_LINK( RichTextControlImpl, OnVScroll, ScrollBar*, _pScrollbar )
346     {
347         m_pView->Scroll( 0, -_pScrollbar->GetDelta(), RGCHK_PAPERSZ1 );
348         return 0L;
349     }
350 
351     //--------------------------------------------------------------------
352     void RichTextControlImpl::ensureScrollbars()
353     {
354         bool bNeedVScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_VSCROLL );
355         bool bNeedHScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_HSCROLL );
356 
357         if ( ( bNeedVScroll == hasVScrollBar() ) && ( bNeedHScroll == hasHScrollBar( ) ) )
358             // nothing to do
359             return;
360 
361         // create or delete the scrollbars, as necessary
362         if ( !bNeedVScroll )
363         {
364             delete m_pVScroll;
365             m_pVScroll = NULL;
366         }
367         else
368         {
369             m_pVScroll = new ScrollBar( m_pAntiImpl, WB_VSCROLL | WB_DRAG | WB_REPEAT );
370             m_pVScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnVScroll ) );
371             m_pVScroll->Show();
372         }
373 
374         if ( !bNeedHScroll )
375         {
376             delete m_pHScroll;
377             m_pHScroll = NULL;
378         }
379         else
380         {
381             m_pHScroll = new ScrollBar( m_pAntiImpl, WB_HSCROLL | WB_DRAG | WB_REPEAT );
382             m_pHScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnHScroll ) );
383             m_pHScroll->Show();
384         }
385 
386         if ( m_pHScroll && m_pVScroll )
387         {
388             delete m_pScrollCorner;
389             m_pScrollCorner = new ScrollBarBox( m_pAntiImpl );
390             m_pScrollCorner->Show();
391         }
392         else
393         {
394             delete m_pScrollCorner;
395             m_pScrollCorner = NULL;
396         }
397 
398         layoutWindow();
399     }
400 
401     //--------------------------------------------------------------------
402     void RichTextControlImpl::ensureLineBreakSetting()
403     {
404         if ( !windowHasAutomaticLineBreak() )
405             m_pEngine->SetPaperSize( Size( EMPTY_PAPER_SIZE, EMPTY_PAPER_SIZE ) );
406 
407         layoutWindow();
408     }
409 
410     //--------------------------------------------------------------------
411     void RichTextControlImpl::layoutWindow()
412     {
413         if ( !m_bHasEverBeenShown )
414             // no need to do anything. Especially, no need to set the paper size on the
415             // EditEngine to anything ....
416             return;
417 
418         const StyleSettings& rStyleSettings = m_pAntiImpl->GetSettings().GetStyleSettings();
419 
420         long nScrollBarWidth = m_pVScroll ? rStyleSettings.GetScrollBarSize() : 0;
421         long nScrollBarHeight = m_pHScroll ? rStyleSettings.GetScrollBarSize() : 0;
422 
423         if ( m_pAntiImpl->IsZoom() )
424         {
425             nScrollBarWidth = m_pAntiImpl->CalcZoom( nScrollBarWidth );
426             nScrollBarHeight = m_pAntiImpl->CalcZoom( nScrollBarHeight );
427         }
428 
429         // the overall size we can use
430         Size aPlaygroundSizePixel( m_pAntiImpl->GetOutputSizePixel() );
431 
432         // the size of the viewport - note that the viewport does *not* occupy all the place
433         // which is left when subtracting the scrollbar width/height
434         Size aViewportPlaygroundPixel( aPlaygroundSizePixel );
435         aViewportPlaygroundPixel.Width() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Width() - nScrollBarWidth ) );
436         aViewportPlaygroundPixel.Height() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Height() - nScrollBarHeight ) );
437         Size aViewportPlaygroundLogic( m_pViewport->PixelToLogic( aViewportPlaygroundPixel ) );
438 
439         const long nOffset = 2;
440         Size aViewportSizePixel( aViewportPlaygroundPixel.Width() - 2 * nOffset, aViewportPlaygroundPixel.Height() - 2 * nOffset );
441         Size aViewportSizeLogic( m_pViewport->PixelToLogic( aViewportSizePixel ) );
442 
443         // position the viewport
444         m_pViewport->SetPosSizePixel( Point( nOffset, nOffset ), aViewportSizePixel );
445         // position the scrollbars
446         if ( m_pVScroll )
447             m_pVScroll->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), 0 ), Size( nScrollBarWidth, aViewportPlaygroundPixel.Height() ) );
448         if ( m_pHScroll )
449             m_pHScroll->SetPosSizePixel( Point( 0, aViewportPlaygroundPixel.Height() ), Size( aViewportPlaygroundPixel.Width(), nScrollBarHeight ) );
450         if ( m_pScrollCorner )
451             m_pScrollCorner->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), aViewportPlaygroundPixel.Height() ), Size( nScrollBarWidth, nScrollBarHeight ) );
452 
453         // paper size
454         if ( windowHasAutomaticLineBreak() )
455             m_pEngine->SetPaperSize( Size( aViewportSizeLogic.Width(), m_pEngine->GetTextHeight() ) );
456 
457         // output area of the view
458         m_pView->SetOutputArea( Rectangle( Point( ), aViewportSizeLogic ) );
459         m_pView->SetVisArea( Rectangle( Point( ), aViewportSizeLogic ) );
460 
461         if ( m_pVScroll )
462         {
463             m_pVScroll->SetVisibleSize( aViewportPlaygroundLogic.Height() );
464 
465             // the default height of a text line ....
466             long nFontHeight = m_pEngine->GetStandardFont(0).GetSize().Height();
467             // ... is the scroll size for the vertical scrollbar
468             m_pVScroll->SetLineSize( nFontHeight );
469             // the viewport width, minus one line, is the page scroll size
470             m_pVScroll->SetPageSize( ::std::max( nFontHeight, aViewportPlaygroundLogic.Height() - nFontHeight ) );
471         }
472 
473         // the font width
474         if ( m_pHScroll )
475         {
476             m_pHScroll->SetVisibleSize( aViewportPlaygroundLogic.Width() );
477 
478             long nFontWidth = m_pEngine->GetStandardFont(0).GetSize().Width();
479             if ( !nFontWidth )
480             {
481                 m_pViewport->Push( PUSH_FONT );
482                 m_pViewport->SetFont( m_pEngine->GetStandardFont(0) );
483                 nFontWidth = m_pViewport->GetTextWidth( String( RTL_CONSTASCII_USTRINGPARAM( "x" ) ) );
484                 m_pViewport->Pop();
485             }
486             // ... is the scroll size for the horizontal scrollbar
487             m_pHScroll->SetLineSize( 5 * nFontWidth );
488             // the viewport height, minus one character, is the page scroll size
489             m_pHScroll->SetPageSize( ::std::max( nFontWidth, aViewportPlaygroundLogic.Width() - nFontWidth ) );
490         }
491 
492         // update range and position of the scrollbars
493         updateScrollbars();
494     }
495 
496     //--------------------------------------------------------------------
497     void RichTextControlImpl::updateScrollbars()
498     {
499         if ( m_pVScroll )
500         {
501             long nOverallTextHeight = m_pEngine->GetTextHeight();
502             m_pVScroll->SetRange( Range( 0, nOverallTextHeight ) );
503             m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() );
504         }
505 
506         if ( m_pHScroll )
507         {
508             Size aPaperSize( m_pEngine->GetPaperSize() );
509             long nOverallTextWidth = ( aPaperSize.Width() == EMPTY_PAPER_SIZE ) ? m_pEngine->CalcTextWidth() : aPaperSize.Width();
510             m_pHScroll->SetRange( Range( 0, nOverallTextWidth ) );
511             m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() );
512         }
513     }
514 
515     //--------------------------------------------------------------------
516     void RichTextControlImpl::notifyInitShow()
517     {
518         if ( !m_bHasEverBeenShown )
519         {
520             m_bHasEverBeenShown = true;
521             layoutWindow();
522         }
523     }
524 
525     //--------------------------------------------------------------------
526     void RichTextControlImpl::notifyStyleChanged()
527     {
528         ensureScrollbars();
529         ensureLineBreakSetting();
530     }
531 
532     //--------------------------------------------------------------------
533     void RichTextControlImpl::notifyZoomChanged()
534     {
535         const Fraction& rZoom = m_pAntiImpl->GetZoom();
536 
537         MapMode aMapMode( m_pAntiImpl->GetMapMode() );
538         aMapMode.SetScaleX( rZoom );
539         aMapMode.SetScaleY( rZoom );
540         m_pAntiImpl->SetMapMode( aMapMode );
541 
542         m_pViewport->SetZoom( rZoom );
543         m_pViewport->SetMapMode( aMapMode );
544 
545         layoutWindow();
546     }
547 
548     //--------------------------------------------------------------------
549     bool RichTextControlImpl::windowHasAutomaticLineBreak()
550     {
551         return ( m_pAntiImpl->GetStyle() & WB_WORDBREAK ) != 0;
552     }
553 
554     //--------------------------------------------------------------------
555     void RichTextControlImpl::SetReadOnly( bool _bReadOnly )
556     {
557         m_pView->SetReadOnly( _bReadOnly );
558     }
559 
560     //--------------------------------------------------------------------
561     bool RichTextControlImpl::IsReadOnly() const
562     {
563         return m_pView->IsReadOnly( );
564     }
565 
566     //--------------------------------------------------------------------
567     namespace
568     {
569         static void lcl_inflate( Rectangle& _rRect, long _nInflateX, long _nInflateY )
570         {
571             _rRect.Left() -= _nInflateX;
572             _rRect.Right() += _nInflateX;
573             _rRect.Top() -= _nInflateY;
574             _rRect.Bottom() += _nInflateY;
575         }
576     }
577     //--------------------------------------------------------------------
578     long RichTextControlImpl::HandleCommand( const CommandEvent& _rEvent )
579     {
580         if (  ( _rEvent.GetCommand() == COMMAND_WHEEL )
581            || ( _rEvent.GetCommand() == COMMAND_STARTAUTOSCROLL )
582            || ( _rEvent.GetCommand() == COMMAND_AUTOSCROLL )
583            )
584         {
585             m_pAntiImpl->HandleScrollCommand( _rEvent, m_pHScroll, m_pVScroll );
586             return 1;
587         }
588         return 0;
589     }
590 
591     //--------------------------------------------------------------------
592     void RichTextControlImpl::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, sal_uLong /*_nFlags*/ )
593     {
594         // need to normalize the map mode of the device - every paint operation on any device needs
595         // to use the same map mode
596         _pDev->Push( PUSH_MAPMODE | PUSH_LINECOLOR | PUSH_FILLCOLOR );
597 
598         // enforce our "normalize map mode" on the device
599         MapMode aRefMapMode( m_pEngine->GetRefDevice()->GetMapMode() );
600         MapMode aOriginalMapMode( _pDev->GetMapMode() );
601         MapMode aNormalizedMapMode( aRefMapMode.GetMapUnit(), aRefMapMode.GetOrigin(), aOriginalMapMode.GetScaleX(), aOriginalMapMode.GetScaleY() );
602         _pDev->SetMapMode( aNormalizedMapMode );
603 
604         // translate coordinates
605         Point aPos( _rPos );
606         Size aSize( _rSize );
607         if ( aOriginalMapMode.GetMapUnit() == MAP_PIXEL )
608         {
609             aPos = _pDev->PixelToLogic( _rPos, aNormalizedMapMode );
610             aSize = _pDev->PixelToLogic( _rSize, aNormalizedMapMode );
611         }
612         else
613         {
614             aPos = OutputDevice::LogicToLogic( _rPos, aOriginalMapMode, aNormalizedMapMode );
615             aSize = OutputDevice::LogicToLogic( _rSize, aOriginalMapMode, aNormalizedMapMode );
616         }
617 
618         Rectangle aPlayground( aPos, aSize );
619         Size aOnePixel( _pDev->PixelToLogic( Size( 1, 1 ) ) );
620         aPlayground.Right() -= aOnePixel.Width();
621         aPlayground.Bottom() -= aOnePixel.Height();
622 
623         // background
624         _pDev->SetLineColor();
625         _pDev->DrawRect( aPlayground );
626 
627         // do we need to draw a border?
628         bool bBorder = ( m_pAntiImpl->GetStyle() & WB_BORDER );
629         if ( bBorder )
630             _pDev->SetLineColor( m_pAntiImpl->GetSettings().GetStyleSettings().GetMonoColor() );
631         else
632             _pDev->SetLineColor();
633         _pDev->SetFillColor( m_pAntiImpl->GetBackground().GetColor() );
634         _pDev->DrawRect( aPlayground );
635 
636         if ( bBorder )
637             // don't draw the text over the border
638             lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
639 
640         // leave a space of one pixel between the "surroundings" of the control
641         // and the content
642         lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
643         lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
644 
645         // actually draw the content
646         m_pEngine->Draw( _pDev, aPlayground, Point(), sal_True );
647 
648         _pDev->Pop();
649     }
650 
651     //--------------------------------------------------------------------
652     void RichTextControlImpl::SetBackgroundColor( )
653     {
654         SetBackgroundColor( Application::GetSettings().GetStyleSettings().GetFieldColor() );
655     }
656 
657     //--------------------------------------------------------------------
658     void RichTextControlImpl::SetBackgroundColor( const Color& _rColor )
659     {
660         Wallpaper aWallpaper( _rColor );
661         m_pAntiImpl->SetBackground( aWallpaper );
662         m_pViewport->SetBackground( aWallpaper );
663     }
664 
665     //--------------------------------------------------------------------
666     void RichTextControlImpl::SetHideInactiveSelection( bool _bHide )
667     {
668         m_pViewport->SetHideInactiveSelection( _bHide );
669     }
670 
671     //--------------------------------------------------------------------
672     bool RichTextControlImpl::GetHideInactiveSelection() const
673     {
674         return m_pViewport->GetHideInactiveSelection( );
675     }
676 
677 //........................................................................
678 }   // namespace frm
679 //........................................................................
680 
681