update credits
[LibreOffice.git] / forms / source / richtext / richtextcontrol.cxx
blob942253209681dbdef2ccc0f296cf93f476b6ca99
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "richtextcontrol.hxx"
21 #include "frm_module.hxx"
22 #include "property.hrc"
23 #include "services.hxx"
25 #include "richtextmodel.hxx"
26 #include "richtextvclcontrol.hxx"
27 #include "clipboarddispatcher.hxx"
28 #include "parametrizedattributedispatcher.hxx"
29 #include "specialdispatchers.hxx"
31 #include <com/sun/star/awt/PosSize.hpp>
33 #include <toolkit/helper/vclunohelper.hxx>
34 #include <tools/diagnose_ex.h>
35 #include <vcl/svapp.hxx>
37 #include <svx/svxids.hrc>
38 #include <editeng/editview.hxx>
39 #include <svl/itemset.hxx>
40 #include <svl/itempool.hxx>
41 #include <sfx2/msgpool.hxx>
43 //--------------------------------------------------------------------------
44 extern "C" void SAL_CALL createRegistryInfo_ORichTextControl()
46 static ::frm::OMultiInstanceAutoRegistration< ::frm::ORichTextControl > aAutoRegistration;
49 //.........................................................................
50 namespace frm
52 //.........................................................................
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::beans;
56 using namespace ::com::sun::star::awt;
57 using namespace ::com::sun::star::lang;
58 using namespace ::com::sun::star::frame;
60 #define FORWARD_TO_PEER_1_RET( returnType, unoInterface, method, param1 ) \
61 returnType aReturn; \
62 Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \
63 if ( xTypedPeer.is() ) \
64 { \
65 aReturn = xTypedPeer->method( param1 ); \
66 } \
67 return aReturn;
69 #define FORWARD_TO_PEER_3_RET( returnType, unoInterface, method, param1, param2, param3 ) \
70 returnType aReturn; \
71 Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \
72 if ( xTypedPeer.is() ) \
73 { \
74 aReturn = xTypedPeer->method( param1, param2, param3 ); \
75 } \
76 return aReturn;
78 //==================================================================
79 // ORichTextControl
80 //==================================================================
81 DBG_NAME( ORichTextControl )
82 //------------------------------------------------------------------
83 ORichTextControl::ORichTextControl()
84 :UnoEditControl()
86 DBG_CTOR( ORichTextControl, NULL );
89 //------------------------------------------------------------------
90 ORichTextControl::~ORichTextControl()
92 DBG_DTOR( ORichTextControl, NULL );
95 //------------------------------------------------------------------
96 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORichTextControl, UnoEditControl, ORichTextControl_Base )
98 //------------------------------------------------------------------
99 Any SAL_CALL ORichTextControl::queryAggregation( const Type& _rType ) throw ( RuntimeException )
101 Any aReturn = UnoEditControl::queryAggregation( _rType );
103 if ( !aReturn.hasValue() )
104 aReturn = ORichTextControl_Base::queryInterface( _rType );
106 return aReturn;
109 //------------------------------------------------------------------
110 namespace
112 //..............................................................
113 static void implAdjustTriStateFlag( const Reference< XPropertySet >& _rxProps, const OUString& _rPropertyName,
114 WinBits& _rAllBits, WinBits _nPositiveFlag, WinBits nNegativeFlag )
116 sal_Bool bFlagValue = sal_False;
117 if ( _rxProps->getPropertyValue( _rPropertyName ) >>= bFlagValue )
118 _rAllBits |= ( bFlagValue ? _nPositiveFlag : nNegativeFlag );
121 //..............................................................
122 static void implAdjustTwoStateFlag( const Any& _rValue, WinBits& _rAllBits, WinBits _nFlag, bool _bInvert = false )
124 sal_Bool bFlagValue = sal_False;
125 if ( _rValue >>= bFlagValue )
127 if ( _bInvert )
128 bFlagValue = !bFlagValue;
129 if ( bFlagValue )
130 _rAllBits |= _nFlag;
131 else
132 _rAllBits &= ~_nFlag;
136 //..............................................................
137 static void implAdjustTwoStateFlag( const Reference< XPropertySet >& _rxProps, const OUString& _rPropertyName,
138 WinBits& _rAllBits, WinBits _nFlag, bool _bInvert = false )
140 implAdjustTwoStateFlag( _rxProps->getPropertyValue( _rPropertyName ), _rAllBits, _nFlag, _bInvert );
143 //..............................................................
144 static void adjustTwoStateWinBit( Window* _pWindow, const Any& _rValue, WinBits _nFlag, bool _bInvert = false )
146 WinBits nBits = _pWindow->GetStyle();
147 implAdjustTwoStateFlag( _rValue, nBits, _nFlag, _bInvert );
148 _pWindow->SetStyle( nBits );
151 //..............................................................
152 static WinBits getWinBits( const Reference< XControlModel >& _rxModel, WinBits nBaseBits = 0 )
154 WinBits nBits = nBaseBits;
157 Reference< XPropertySet > xProps( _rxModel, UNO_QUERY );
158 if ( xProps.is() )
160 sal_Int16 nBorder = 0;
161 xProps->getPropertyValue( PROPERTY_BORDER ) >>= nBorder;
162 if ( nBorder )
163 nBits |= WB_BORDER;
165 implAdjustTriStateFlag( xProps, PROPERTY_TABSTOP, nBits, WB_TABSTOP, WB_NOTABSTOP );
166 implAdjustTwoStateFlag( xProps, PROPERTY_HSCROLL, nBits, WB_HSCROLL );
167 implAdjustTwoStateFlag( xProps, PROPERTY_VSCROLL, nBits, WB_VSCROLL );
168 implAdjustTwoStateFlag( xProps, PROPERTY_HARDLINEBREAKS, nBits, WB_WORDBREAK, true );
171 catch( const Exception& )
173 DBG_UNHANDLED_EXCEPTION();
175 return nBits;
179 //------------------------------------------------------------------
180 void SAL_CALL ORichTextControl::createPeer( const Reference< XToolkit >& _rToolkit, const Reference< XWindowPeer >& _rParentPeer ) throw( RuntimeException )
182 sal_Bool bReallyActAsRichText = sal_False;
185 Reference< XPropertySet > xModelProps( getModel(), UNO_QUERY_THROW );
186 xModelProps->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bReallyActAsRichText;
188 catch( const Exception& )
190 DBG_UNHANDLED_EXCEPTION();
193 if ( !bReallyActAsRichText )
195 UnoEditControl::createPeer( _rToolkit, _rParentPeer );
196 OControl::initFormControlPeer( getPeer() );
197 return;
200 SolarMutexGuard aGuard;
202 if (!getPeer().is())
204 mbCreatingPeer = sal_True;
206 // determine the VLC window for the parent
207 Window* pParentWin = NULL;
208 if ( _rParentPeer.is() )
210 VCLXWindow* pParentXWin = VCLXWindow::GetImplementation( _rParentPeer );
211 if ( pParentXWin )
212 pParentWin = pParentXWin->GetWindow();
213 DBG_ASSERT( pParentWin, "ORichTextControl::createPeer: could not obtain the VCL-level parent window!" );
216 // create the peer
217 Reference< XControlModel > xModel( getModel() );
218 ORichTextPeer* pPeer = ORichTextPeer::Create( xModel, pParentWin, getWinBits( xModel ) );
219 DBG_ASSERT( pPeer, "ORichTextControl::createPeer: invalid peer returned!" );
220 if ( pPeer )
222 // by definition, the returned component is aquired once
223 pPeer->release();
225 // announce the peer to the base class
226 setPeer( pPeer );
228 // initialize ourself (and thus the peer) with the model properties
229 updateFromModel();
231 Reference< XView > xPeerView( getPeer(), UNO_QUERY );
232 if ( xPeerView.is() )
234 xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY );
235 xPeerView->setGraphics( mxGraphics );
238 // a lot of initial settings from our component infos
239 setPosSize( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight, PosSize::POSSIZE );
241 pPeer->setVisible ( maComponentInfos.bVisible && !mbDesignMode );
242 pPeer->setEnable ( maComponentInfos.bEnable );
243 pPeer->setDesignMode( mbDesignMode );
245 peerCreated();
248 mbCreatingPeer = sal_False;
250 OControl::initFormControlPeer( getPeer() );
254 //------------------------------------------------------------------
255 OUString SAL_CALL ORichTextControl::getImplementationName() throw( RuntimeException )
257 return getImplementationName_Static();
260 //------------------------------------------------------------------
261 Sequence< OUString > SAL_CALL ORichTextControl::getSupportedServiceNames() throw( RuntimeException )
263 return getSupportedServiceNames_Static();
266 //------------------------------------------------------------------
267 OUString SAL_CALL ORichTextControl::getImplementationName_Static()
269 return OUString( "com.sun.star.comp.form.ORichTextControl" );
272 //------------------------------------------------------------------
273 Sequence< OUString > SAL_CALL ORichTextControl::getSupportedServiceNames_Static()
275 Sequence< OUString > aServices( 3 );
276 aServices[ 0 ] = OUString( "com.sun.star.awt.UnoControl" );
277 aServices[ 1 ] = OUString( "com.sun.star.awt.UnoControlEdit" );
278 aServices[ 2 ] = FRM_SUN_CONTROL_RICHTEXTCONTROL;
279 return aServices;
282 //------------------------------------------------------------------
283 Reference< XInterface > SAL_CALL ORichTextControl::Create( const Reference< XMultiServiceFactory >& )
285 return *( new ORichTextControl() );
288 //--------------------------------------------------------------------
289 Reference< XDispatch > SAL_CALL ORichTextControl::queryDispatch( const ::com::sun::star::util::URL& _rURL, const OUString& _rTargetFrameName, sal_Int32 _nSearchFlags ) throw (RuntimeException)
291 FORWARD_TO_PEER_3_RET( Reference< XDispatch >, XDispatchProvider, queryDispatch, _rURL, _rTargetFrameName, _nSearchFlags );
294 //--------------------------------------------------------------------
295 Sequence< Reference< XDispatch > > SAL_CALL ORichTextControl::queryDispatches( const Sequence< DispatchDescriptor >& _rRequests ) throw (RuntimeException)
297 FORWARD_TO_PEER_1_RET( Sequence< Reference< XDispatch > >, XDispatchProvider, queryDispatches, _rRequests );
300 //--------------------------------------------------------------------
301 sal_Bool ORichTextControl::requiresNewPeer( const OUString& _rPropertyName ) const
303 return UnoControl::requiresNewPeer( _rPropertyName ) || _rPropertyName.equals( PROPERTY_RICH_TEXT );
306 //==================================================================
307 // ORichTextPeer
308 //==================================================================
309 DBG_NAME( ORichTextPeer )
310 //------------------------------------------------------------------
311 ORichTextPeer* ORichTextPeer::Create( const Reference< XControlModel >& _rxModel, Window* _pParentWindow, WinBits _nStyle )
313 DBG_TESTSOLARMUTEX();
315 // the EditEngine of the model
316 RichTextEngine* pEngine = ORichTextModel::getEditEngine( _rxModel );
317 OSL_ENSURE( pEngine, "ORichTextPeer::Create: could not obtaine the edit engine from the model!" );
318 if ( !pEngine )
319 return NULL;
321 // the peer itself
322 ORichTextPeer* pPeer = new ORichTextPeer;
323 pPeer->acquire(); // by definition, the returned object is aquired once
325 // the VCL control for the peer
326 RichTextControl* pRichTextControl = new RichTextControl( pEngine, _pParentWindow, _nStyle, NULL, pPeer );
328 // some knittings
329 pRichTextControl->SetComponentInterface( pPeer );
331 // outta here
332 return pPeer;
335 //------------------------------------------------------------------
336 ORichTextPeer::ORichTextPeer()
338 DBG_CTOR( ORichTextPeer, NULL );
341 //------------------------------------------------------------------
342 ORichTextPeer::~ORichTextPeer()
344 DBG_DTOR( ORichTextPeer, NULL );
347 //------------------------------------------------------------------
348 void ORichTextPeer::dispose( ) throw(RuntimeException)
351 SolarMutexGuard aGuard;
352 RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() );
354 if ( pRichTextControl )
356 for ( AttributeDispatchers::iterator aDisposeLoop = m_aDispatchers.begin();
357 aDisposeLoop != m_aDispatchers.end();
358 ++aDisposeLoop
361 pRichTextControl->disableAttributeNotification( aDisposeLoop->first );
362 aDisposeLoop->second->dispose();
366 AttributeDispatchers aEmpty;
367 m_aDispatchers.swap( aEmpty );
370 VCLXWindow::dispose();
373 //--------------------------------------------------------------------
374 void SAL_CALL ORichTextPeer::draw( sal_Int32 _nX, sal_Int32 _nY ) throw(::com::sun::star::uno::RuntimeException)
376 SolarMutexGuard aGuard;
378 RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() );
379 if ( !pControl )
380 return;
382 OutputDevice* pTargetDevice = VCLUnoHelper::GetOutputDevice( getGraphics() );
383 OSL_ENSURE( pTargetDevice != NULL, "ORichTextPeer::draw: no graphics -> no drawing!" );
384 if ( !pTargetDevice )
385 return;
387 ::Size aSize = pControl->GetSizePixel();
388 const MapUnit eTargetUnit = pTargetDevice->GetMapMode().GetMapUnit();
389 if ( eTargetUnit != MAP_PIXEL )
390 aSize = pTargetDevice->PixelToLogic( aSize );
392 ::Point aPos( _nX, _nY );
393 // the XView::draw API talks about pixels, always ...
394 if ( eTargetUnit != MAP_PIXEL )
395 aPos = pTargetDevice->PixelToLogic( aPos );
397 pControl->Draw( pTargetDevice, aPos, aSize, WINDOW_DRAW_NOCONTROLS );
400 //--------------------------------------------------------------------
401 void SAL_CALL ORichTextPeer::setProperty( const OUString& _rPropertyName, const Any& _rValue ) throw (RuntimeException)
403 if ( !GetWindow() )
405 VCLXWindow::setProperty( _rPropertyName, _rValue );
406 return;
409 if ( _rPropertyName.equals( PROPERTY_BACKGROUNDCOLOR ) )
411 RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() );
412 if ( !_rValue.hasValue() )
414 pControl->SetBackgroundColor( );
416 else
418 sal_Int32 nColor = COL_TRANSPARENT;
419 _rValue >>= nColor;
420 pControl->SetBackgroundColor( Color( nColor ) );
423 else if ( _rPropertyName.equals( PROPERTY_HSCROLL ) )
425 adjustTwoStateWinBit( GetWindow(), _rValue, WB_HSCROLL );
427 else if ( _rPropertyName.equals( PROPERTY_VSCROLL ) )
429 adjustTwoStateWinBit( GetWindow(), _rValue, WB_VSCROLL );
431 else if ( _rPropertyName.equals( PROPERTY_HARDLINEBREAKS ) )
433 adjustTwoStateWinBit( GetWindow(), _rValue, WB_WORDBREAK, true );
435 else if ( _rPropertyName.equals( PROPERTY_READONLY ) )
437 RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() );
438 sal_Bool bReadOnly( pControl->IsReadOnly() );
439 OSL_VERIFY( _rValue >>= bReadOnly );
440 pControl->SetReadOnly( bReadOnly );
442 // update the dispatchers
443 for ( AttributeDispatchers::iterator aDispatcherLoop = m_aDispatchers.begin();
444 aDispatcherLoop != m_aDispatchers.end();
445 ++aDispatcherLoop
448 aDispatcherLoop->second->invalidate();
451 else if ( _rPropertyName.equals( PROPERTY_HIDEINACTIVESELECTION ) )
453 RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() );
454 sal_Bool bHide = pRichTextControl->GetHideInactiveSelection();
455 OSL_VERIFY( _rValue >>= bHide );
456 pRichTextControl->SetHideInactiveSelection( bHide );
458 else
459 VCLXWindow::setProperty( _rPropertyName, _rValue );
462 //------------------------------------------------------------------
463 IMPLEMENT_FORWARD_XINTERFACE2( ORichTextPeer, VCLXWindow, ORichTextPeer_Base )
465 //------------------------------------------------------------------
466 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORichTextPeer, VCLXWindow, ORichTextPeer_Base )
468 //--------------------------------------------------------------------
469 namespace
471 static SfxSlotId lcl_translateConflictingSlot( SfxSlotId _nIDFromPool )
473 // HACK HACK HACK
474 // unfortunately, some of our applications have some conflicting slots,
475 // i.e. slots which have the same UNO name as an existing other (common)
476 // slot.
477 // For instance, both the slots SID_SET_SUPER_SCRIPT (from SVX) and FN_SET_SUPER_SCRIPT
478 // (from SW) have the UNO name "SuperScript".
479 // Now, if the controls lives in a text document, and asks the SfxSlotPool for
480 // the id belonging to "SuperScript", it gets the FN_SET_SUPER_SCRIPT - which
481 // is completely unknown to the EditEngine.
482 // So, we need to translate such conflicting ids.
484 // Note that the real solution would be to fix the applications to
485 // *not* define conflicting slots. Alternatively, if SFX would provide a slot pool
486 // which is *static* (i.e. independent on the active application), then we
487 // would also never encounter such a conflict.
488 SfxSlotId nReturn( _nIDFromPool );
489 switch ( _nIDFromPool )
491 case 20411: /* FM_SET_SUPER_SCRIPT, originating in SW */
492 nReturn = SID_SET_SUPER_SCRIPT;
493 break;
494 case 20412: /* FN_SET_SUB_SCRIPT, originating in SW */
495 nReturn = SID_SET_SUB_SCRIPT;
496 break;
498 return nReturn;
502 //--------------------------------------------------------------------
503 ORichTextPeer::SingleAttributeDispatcher ORichTextPeer::implCreateDispatcher( SfxSlotId _nSlotId, const ::com::sun::star::util::URL& _rURL )
505 RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() );
506 OSL_PRECOND( pRichTextControl, "ORichTextPeer::implCreateDispatcher: invalid window!" );
507 if ( !pRichTextControl )
508 return SingleAttributeDispatcher( NULL );
510 ORichTextFeatureDispatcher* pDispatcher = NULL;
511 OAttributeDispatcher* pAttributeDispatcher = NULL;
512 switch ( _nSlotId )
514 case SID_CUT:
515 pDispatcher = new OClipboardDispatcher( pRichTextControl->getView(), OClipboardDispatcher::eCut );
516 break;
518 case SID_COPY:
519 pDispatcher = new OClipboardDispatcher( pRichTextControl->getView(), OClipboardDispatcher::eCopy );
520 break;
522 case SID_PASTE:
523 pDispatcher = new OPasteClipboardDispatcher( pRichTextControl->getView() );
524 break;
526 case SID_SELECTALL:
527 pDispatcher = new OSelectAllDispatcher( pRichTextControl->getView(), _rURL );
528 break;
530 case SID_ATTR_PARA_LEFT_TO_RIGHT:
531 case SID_ATTR_PARA_RIGHT_TO_LEFT:
532 pAttributeDispatcher = new OParagraphDirectionDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
533 break;
535 case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
536 case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
537 pDispatcher = new OTextDirectionDispatcher( pRichTextControl->getView(), _rURL );
538 break;
540 case SID_ATTR_PARA_HANGPUNCTUATION:
541 case SID_ATTR_PARA_FORBIDDEN_RULES:
542 case SID_ATTR_PARA_SCRIPTSPACE:
543 pAttributeDispatcher = new OAsianFontLayoutDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
544 break;
546 default:
548 // is it a supported slot?
549 bool bSupportedSlot = false;
550 if ( !bSupportedSlot )
552 const SfxItemPool& rPool = *pRichTextControl->getView().GetEmptyItemSet().GetPool();
553 bSupportedSlot = rPool.IsInRange( rPool.GetWhich( _nSlotId ) );
555 if ( !bSupportedSlot )
556 bSupportedSlot = RichTextControl::isMappableSlot( _nSlotId );
558 if ( bSupportedSlot )
559 { // it's really a slot which is supported by the EditEngine
561 bool bNeedParametrizedDispatcher = true;
562 if ( ( _nSlotId == SID_ATTR_CHAR_POSTURE )
563 || ( _nSlotId == SID_ATTR_CHAR_CJK_POSTURE )
564 || ( _nSlotId == SID_ATTR_CHAR_CTL_POSTURE )
565 || ( _nSlotId == SID_ATTR_CHAR_LATIN_POSTURE )
566 || ( _nSlotId == SID_ATTR_CHAR_WEIGHT )
567 || ( _nSlotId == SID_ATTR_CHAR_CJK_WEIGHT )
568 || ( _nSlotId == SID_ATTR_CHAR_CTL_WEIGHT )
569 || ( _nSlotId == SID_ATTR_CHAR_LATIN_WEIGHT )
570 || ( _nSlotId == SID_ATTR_CHAR_LANGUAGE )
571 || ( _nSlotId == SID_ATTR_CHAR_CJK_LANGUAGE )
572 || ( _nSlotId == SID_ATTR_CHAR_CTL_LANGUAGE )
573 || ( _nSlotId == SID_ATTR_CHAR_LATIN_LANGUAGE )
574 || ( _nSlotId == SID_ATTR_CHAR_CONTOUR )
575 || ( _nSlotId == SID_ATTR_CHAR_SHADOWED )
576 || ( _nSlotId == SID_ATTR_CHAR_WORDLINEMODE )
577 || ( _nSlotId == SID_ATTR_CHAR_COLOR )
578 || ( _nSlotId == SID_ATTR_CHAR_RELIEF )
579 || ( _nSlotId == SID_ATTR_CHAR_KERNING )
580 || ( _nSlotId == SID_ATTR_CHAR_AUTOKERN )
581 || ( _nSlotId == SID_ATTR_CHAR_SCALEWIDTH )
584 bNeedParametrizedDispatcher = true;
586 else if ( ( _nSlotId == SID_ATTR_PARA_HANGPUNCTUATION )
587 || ( _nSlotId == SID_ATTR_PARA_FORBIDDEN_RULES )
588 || ( _nSlotId == SID_ATTR_PARA_SCRIPTSPACE )
591 bNeedParametrizedDispatcher = false;
593 else
595 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( NULL );
596 const SfxSlot* pSlot = rSlotPool.GetSlot( _nSlotId );
597 const SfxType* pType = pSlot ? pSlot->GetType() : NULL;
598 if ( pType )
600 bNeedParametrizedDispatcher = ( pType->nAttribs > 0 );
604 if ( bNeedParametrizedDispatcher )
606 #if OSL_DEBUG_LEVEL > 0
607 OString sTrace( "ORichTextPeer::implCreateDispatcher: creating *parametrized* dispatcher for " );
608 sTrace += OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US );
609 OSL_TRACE( "%s", sTrace.getStr() );
610 #endif
611 pAttributeDispatcher = new OParametrizedAttributeDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
613 else
615 #if OSL_DEBUG_LEVEL > 0
616 OString sTrace( "ORichTextPeer::implCreateDispatcher: creating *normal* dispatcher for " );
617 sTrace += OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US );
618 OSL_TRACE( "%s", sTrace.getStr() );
619 #endif
620 pAttributeDispatcher = new OAttributeDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
623 #if OSL_DEBUG_LEVEL > 0
624 else
626 OString sTrace( "ORichTextPeer::implCreateDispatcher: not creating dispatcher (unsupported slot) for " );
627 sTrace += OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US );
628 OSL_TRACE( "%s", sTrace.getStr() );
630 #endif
632 break;
635 SingleAttributeDispatcher xDispatcher( pDispatcher );
636 if ( pAttributeDispatcher )
638 xDispatcher = SingleAttributeDispatcher( pAttributeDispatcher );
639 pRichTextControl->enableAttributeNotification( _nSlotId, pAttributeDispatcher );
642 return xDispatcher;
645 //--------------------------------------------------------------------
646 namespace
648 SfxSlotId lcl_getSlotFromUnoName( SfxSlotPool& _rSlotPool, const OUString& _rUnoSlotName )
650 const SfxSlot* pSlot = _rSlotPool.GetUnoSlot( _rUnoSlotName );
651 if ( pSlot )
653 // okay, there's a slot with the given UNO name
654 return lcl_translateConflictingSlot( pSlot->GetSlotId() );
657 // some hard-coded slots, which do not have a UNO name at SFX level, but which
658 // we nevertheless need to transport via UNO mechanisms, so we need a name
659 if ( _rUnoSlotName == "AllowHangingPunctuation" )
660 return SID_ATTR_PARA_HANGPUNCTUATION;
661 if ( _rUnoSlotName == "ApplyForbiddenCharacterRules" )
662 return SID_ATTR_PARA_FORBIDDEN_RULES;
663 if ( _rUnoSlotName == "UseScriptSpacing" )
664 return SID_ATTR_PARA_SCRIPTSPACE;
666 OSL_ENSURE( pSlot, "lcl_getSlotFromUnoName: unknown UNO slot name!" );
667 return 0;
671 //--------------------------------------------------------------------
672 Reference< XDispatch > SAL_CALL ORichTextPeer::queryDispatch( const ::com::sun::star::util::URL& _rURL, const OUString& /*_rTargetFrameName*/, sal_Int32 /*_nSearchFlags*/ ) throw (RuntimeException)
674 Reference< XDispatch > xReturn;
675 if ( !GetWindow() )
677 OSL_FAIL( "ORichTextPeer::queryDispatch: already disposed?" );
678 return xReturn;
681 // is it an UNO slot?
682 OUString sUnoProtocolPrefix( ".uno:" );
683 if ( _rURL.Complete.startsWith( sUnoProtocolPrefix ) )
685 OUString sUnoSlotName = _rURL.Complete.copy( sUnoProtocolPrefix.getLength() );
686 SfxSlotId nSlotId = lcl_getSlotFromUnoName( SfxSlotPool::GetSlotPool( NULL ), sUnoSlotName );
687 if ( nSlotId > 0 )
689 // do we already have a dispatcher for this?
690 AttributeDispatchers::const_iterator aDispatcherPos = m_aDispatchers.find( nSlotId );
691 if ( aDispatcherPos == m_aDispatchers.end() )
693 SingleAttributeDispatcher pDispatcher = implCreateDispatcher( nSlotId, _rURL );
694 if ( pDispatcher.is() )
696 aDispatcherPos = m_aDispatchers.insert( AttributeDispatchers::value_type( nSlotId, pDispatcher ) ).first;
700 if ( aDispatcherPos != m_aDispatchers.end() )
701 xReturn = aDispatcherPos->second.getRef();
705 return xReturn;
708 //--------------------------------------------------------------------
709 Sequence< Reference< XDispatch > > SAL_CALL ORichTextPeer::queryDispatches( const Sequence< DispatchDescriptor >& _rRequests ) throw (RuntimeException)
711 Sequence< Reference< XDispatch > > aReturn( _rRequests.getLength() );
712 Reference< XDispatch >* pReturn = aReturn.getArray();
714 const DispatchDescriptor* pRequest = _rRequests.getConstArray();
715 const DispatchDescriptor* pRequestEnd = pRequest + _rRequests.getLength();
716 for ( ; pRequest != pRequestEnd; ++pRequest, ++pReturn )
718 *pReturn = queryDispatch( pRequest->FeatureURL, pRequest->FrameName, pRequest->SearchFlags );
720 return aReturn;
723 //--------------------------------------------------------------------
724 void ORichTextPeer::onSelectionChanged( const ESelection& /*_rSelection*/ )
726 AttributeDispatchers::iterator aDispatcherPos = m_aDispatchers.find( SID_COPY );
727 if ( aDispatcherPos != m_aDispatchers.end() )
728 aDispatcherPos->second.get()->invalidate();
730 aDispatcherPos = m_aDispatchers.find( SID_CUT );
731 if ( aDispatcherPos != m_aDispatchers.end() )
732 aDispatcherPos->second.get()->invalidate();
735 //........................................................................
736 } // namespace frm
737 //........................................................................
739 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */