1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_forms.hxx"
26 #include "richtextcontrol.hxx"
27 #include "frm_module.hxx"
28 #ifndef _FRM_PROPERTY_HRC_
29 #include "property.hrc"
30 #endif
31 #include "services.hxx"
32
33 #include "richtextmodel.hxx"
34 #include "richtextvclcontrol.hxx"
35 #include "clipboarddispatcher.hxx"
36 #include "parametrizedattributedispatcher.hxx"
37 #include "specialdispatchers.hxx"
38
39 /** === begin UNO includes === **/
40 #include <com/sun/star/awt/PosSize.hpp>
41 /** === end UNO includes === **/
42
43 #include <toolkit/helper/vclunohelper.hxx>
44 #include <tools/diagnose_ex.h>
45 #include <vcl/svapp.hxx>
46
47 #include <svx/svxids.hrc>
48 #include <editeng/editview.hxx>
49 #include <svl/itemset.hxx>
50 #include <svl/itempool.hxx>
51 #include <sfx2/msgpool.hxx>
52
53 //--------------------------------------------------------------------------
createRegistryInfo_ORichTextControl()54 extern "C" void SAL_CALL createRegistryInfo_ORichTextControl()
55 {
56 static ::frm::OMultiInstanceAutoRegistration< ::frm::ORichTextControl > aAutoRegistration;
57 }
58
59 //.........................................................................
60 namespace frm
61 {
62 //.........................................................................
63
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::beans;
66 using namespace ::com::sun::star::awt;
67 using namespace ::com::sun::star::lang;
68 using namespace ::com::sun::star::frame;
69
70 #define FORWARD_TO_PEER_1( unoInterface, method, param1 ) \
71 Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \
72 if ( xTypedPeer.is() ) \
73 { \
74 xTypedPeer->method( param1 ); \
75 }
76
77 #define FORWARD_TO_PEER_1_RET( returnType, unoInterface, method, param1 ) \
78 returnType aReturn; \
79 Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \
80 if ( xTypedPeer.is() ) \
81 { \
82 aReturn = xTypedPeer->method( param1 ); \
83 } \
84 return aReturn;
85
86 #define FORWARD_TO_PEER_3( unoInterface, method, param1, param2, param3 ) \
87 Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \
88 if ( xTypedPeer.is() ) \
89 { \
90 xTypedPeer->method( param1, param2, param3 ); \
91 }
92
93 #define FORWARD_TO_PEER_3_RET( returnType, unoInterface, method, param1, param2, param3 ) \
94 returnType aReturn; \
95 Reference< unoInterface > xTypedPeer( getPeer(), UNO_QUERY ); \
96 if ( xTypedPeer.is() ) \
97 { \
98 aReturn = xTypedPeer->method( param1, param2, param3 ); \
99 } \
100 return aReturn;
101
102 //==================================================================
103 // ORichTextControl
104 //==================================================================
DBG_NAME(ORichTextControl)105 DBG_NAME( ORichTextControl )
106 //------------------------------------------------------------------
107 ORichTextControl::ORichTextControl( const Reference< XMultiServiceFactory >& _rxORB )
108 :UnoEditControl( _rxORB )
109 {
110 DBG_CTOR( ORichTextControl, NULL );
111 }
112
113 //------------------------------------------------------------------
~ORichTextControl()114 ORichTextControl::~ORichTextControl()
115 {
116 DBG_DTOR( ORichTextControl, NULL );
117 }
118
119 //------------------------------------------------------------------
IMPLEMENT_FORWARD_XTYPEPROVIDER2(ORichTextControl,UnoEditControl,ORichTextControl_Base)120 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORichTextControl, UnoEditControl, ORichTextControl_Base )
121
122 //------------------------------------------------------------------
123 Any SAL_CALL ORichTextControl::queryAggregation( const Type& _rType ) throw ( RuntimeException )
124 {
125 Any aReturn = UnoEditControl::queryAggregation( _rType );
126
127 if ( !aReturn.hasValue() )
128 aReturn = ORichTextControl_Base::queryInterface( _rType );
129
130 return aReturn;
131 }
132
133 //------------------------------------------------------------------
134 namespace
135 {
136 //..............................................................
implAdjustTriStateFlag(const Reference<XPropertySet> & _rxProps,const::rtl::OUString & _rPropertyName,WinBits & _rAllBits,WinBits _nPositiveFlag,WinBits nNegativeFlag)137 static void implAdjustTriStateFlag( const Reference< XPropertySet >& _rxProps, const ::rtl::OUString& _rPropertyName,
138 WinBits& _rAllBits, WinBits _nPositiveFlag, WinBits nNegativeFlag )
139 {
140 sal_Bool bFlagValue = sal_False;
141 if ( _rxProps->getPropertyValue( _rPropertyName ) >>= bFlagValue )
142 _rAllBits |= ( bFlagValue ? _nPositiveFlag : nNegativeFlag );
143 }
144
145 //..............................................................
implAdjustTwoStateFlag(const Any & _rValue,WinBits & _rAllBits,WinBits _nFlag,bool _bInvert=false)146 static void implAdjustTwoStateFlag( const Any& _rValue, WinBits& _rAllBits, WinBits _nFlag, bool _bInvert = false )
147 {
148 sal_Bool bFlagValue = sal_False;
149 if ( _rValue >>= bFlagValue )
150 {
151 if ( _bInvert )
152 bFlagValue = !bFlagValue;
153 if ( bFlagValue )
154 _rAllBits |= _nFlag;
155 else
156 _rAllBits &= ~_nFlag;
157 }
158 }
159
160 //..............................................................
implAdjustTwoStateFlag(const Reference<XPropertySet> & _rxProps,const::rtl::OUString & _rPropertyName,WinBits & _rAllBits,WinBits _nFlag,bool _bInvert=false)161 static void implAdjustTwoStateFlag( const Reference< XPropertySet >& _rxProps, const ::rtl::OUString& _rPropertyName,
162 WinBits& _rAllBits, WinBits _nFlag, bool _bInvert = false )
163 {
164 implAdjustTwoStateFlag( _rxProps->getPropertyValue( _rPropertyName ), _rAllBits, _nFlag, _bInvert );
165 }
166
167 //..............................................................
adjustTwoStateWinBit(Window * _pWindow,const Any & _rValue,WinBits _nFlag,bool _bInvert=false)168 static void adjustTwoStateWinBit( Window* _pWindow, const Any& _rValue, WinBits _nFlag, bool _bInvert = false )
169 {
170 WinBits nBits = _pWindow->GetStyle();
171 implAdjustTwoStateFlag( _rValue, nBits, _nFlag, _bInvert );
172 _pWindow->SetStyle( nBits );
173 }
174
175 //..............................................................
getWinBits(const Reference<XControlModel> & _rxModel,WinBits nBaseBits=0)176 static WinBits getWinBits( const Reference< XControlModel >& _rxModel, WinBits nBaseBits = 0 )
177 {
178 WinBits nBits = nBaseBits;
179 try
180 {
181 Reference< XPropertySet > xProps( _rxModel, UNO_QUERY );
182 if ( xProps.is() )
183 {
184 sal_Int16 nBorder = 0;
185 xProps->getPropertyValue( PROPERTY_BORDER ) >>= nBorder;
186 if ( nBorder )
187 nBits |= WB_BORDER;
188
189 implAdjustTriStateFlag( xProps, PROPERTY_TABSTOP, nBits, WB_TABSTOP, WB_NOTABSTOP );
190 implAdjustTwoStateFlag( xProps, PROPERTY_HSCROLL, nBits, WB_HSCROLL );
191 implAdjustTwoStateFlag( xProps, PROPERTY_VSCROLL, nBits, WB_VSCROLL );
192 implAdjustTwoStateFlag( xProps, PROPERTY_HARDLINEBREAKS, nBits, WB_WORDBREAK, true );
193 }
194 }
195 catch( const Exception& )
196 {
197 DBG_UNHANDLED_EXCEPTION();
198 }
199 return nBits;
200 }
201 }
202
203 //------------------------------------------------------------------
createPeer(const Reference<XToolkit> & _rToolkit,const Reference<XWindowPeer> & _rParentPeer)204 void SAL_CALL ORichTextControl::createPeer( const Reference< XToolkit >& _rToolkit, const Reference< XWindowPeer >& _rParentPeer ) throw( RuntimeException )
205 {
206 sal_Bool bReallyActAsRichText = sal_False;
207 try
208 {
209 Reference< XPropertySet > xModelProps( getModel(), UNO_QUERY_THROW );
210 xModelProps->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bReallyActAsRichText;
211 }
212 catch( const Exception& )
213 {
214 DBG_UNHANDLED_EXCEPTION();
215 }
216
217 if ( !bReallyActAsRichText )
218 {
219 UnoEditControl::createPeer( _rToolkit, _rParentPeer );
220 OControl::initFormControlPeer( getPeer() );
221 return;
222 }
223
224 ::vos::OGuard aGuard( Application::GetSolarMutex() );
225
226 if (!getPeer().is())
227 {
228 mbCreatingPeer = sal_True;
229
230 // determine the VLC window for the parent
231 Window* pParentWin = NULL;
232 if ( _rParentPeer.is() )
233 {
234 VCLXWindow* pParentXWin = VCLXWindow::GetImplementation( _rParentPeer );
235 if ( pParentXWin )
236 pParentWin = pParentXWin->GetWindow();
237 DBG_ASSERT( pParentWin, "ORichTextControl::createPeer: could not obtain the VCL-level parent window!" );
238 }
239
240 // create the peer
241 Reference< XControlModel > xModel( getModel() );
242 ORichTextPeer* pPeer = ORichTextPeer::Create( xModel, pParentWin, getWinBits( xModel ) );
243 DBG_ASSERT( pPeer, "ORichTextControl::createPeer: invalid peer returned!" );
244 if ( pPeer )
245 {
246 // by definition, the returned component is acquired once
247 pPeer->release();
248
249 // announce the peer to the base class
250 setPeer( pPeer );
251
252 // initialize ourself (and thus the peer) with the model properties
253 updateFromModel();
254
255 Reference< XView > xPeerView( getPeer(), UNO_QUERY );
256 if ( xPeerView.is() )
257 {
258 xPeerView->setZoom( maComponentInfos.nZoomX, maComponentInfos.nZoomY );
259 xPeerView->setGraphics( mxGraphics );
260 }
261
262 // a lot of initial settings from our component infos
263 setPosSize( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight, PosSize::POSSIZE );
264
265 pPeer->setVisible ( maComponentInfos.bVisible && !mbDesignMode );
266 pPeer->setEnable ( maComponentInfos.bEnable );
267 pPeer->setDesignMode( mbDesignMode );
268
269 peerCreated();
270 }
271
272 mbCreatingPeer = sal_False;
273
274 OControl::initFormControlPeer( getPeer() );
275 }
276 }
277
278 //------------------------------------------------------------------
getImplementationName()279 ::rtl::OUString SAL_CALL ORichTextControl::getImplementationName() throw( RuntimeException )
280 {
281 return getImplementationName_Static();
282 }
283
284 //------------------------------------------------------------------
getSupportedServiceNames()285 Sequence< ::rtl::OUString > SAL_CALL ORichTextControl::getSupportedServiceNames() throw( RuntimeException )
286 {
287 return getSupportedServiceNames_Static();
288 }
289
290 //------------------------------------------------------------------
getImplementationName_Static()291 ::rtl::OUString SAL_CALL ORichTextControl::getImplementationName_Static()
292 {
293 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.form.ORichTextControl" ) );
294 }
295
296 //------------------------------------------------------------------
getSupportedServiceNames_Static()297 Sequence< ::rtl::OUString > SAL_CALL ORichTextControl::getSupportedServiceNames_Static()
298 {
299 Sequence< ::rtl::OUString > aServices( 3 );
300 aServices[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControl" ) );
301 aServices[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlEdit" ) );
302 aServices[ 2 ] = FRM_SUN_CONTROL_RICHTEXTCONTROL;
303 return aServices;
304 }
305
306 //------------------------------------------------------------------
Create(const Reference<XMultiServiceFactory> & _rxFactory)307 Reference< XInterface > SAL_CALL ORichTextControl::Create( const Reference< XMultiServiceFactory >& _rxFactory )
308 {
309 return *( new ORichTextControl( _rxFactory ) );
310 }
311
312 //--------------------------------------------------------------------
queryDispatch(const::com::sun::star::util::URL & _rURL,const::rtl::OUString & _rTargetFrameName,sal_Int32 _nSearchFlags)313 Reference< XDispatch > SAL_CALL ORichTextControl::queryDispatch( const ::com::sun::star::util::URL& _rURL, const ::rtl::OUString& _rTargetFrameName, sal_Int32 _nSearchFlags ) throw (RuntimeException)
314 {
315 FORWARD_TO_PEER_3_RET( Reference< XDispatch >, XDispatchProvider, queryDispatch, _rURL, _rTargetFrameName, _nSearchFlags );
316 }
317
318 //--------------------------------------------------------------------
queryDispatches(const Sequence<DispatchDescriptor> & _rRequests)319 Sequence< Reference< XDispatch > > SAL_CALL ORichTextControl::queryDispatches( const Sequence< DispatchDescriptor >& _rRequests ) throw (RuntimeException)
320 {
321 FORWARD_TO_PEER_1_RET( Sequence< Reference< XDispatch > >, XDispatchProvider, queryDispatches, _rRequests );
322 }
323
324 //--------------------------------------------------------------------
requiresNewPeer(const::rtl::OUString & _rPropertyName) const325 sal_Bool ORichTextControl::requiresNewPeer( const ::rtl::OUString& _rPropertyName ) const
326 {
327 return UnoControl::requiresNewPeer( _rPropertyName ) || _rPropertyName.equals( PROPERTY_RICH_TEXT );
328 }
329
330 //==================================================================
331 // ORichTextPeer
332 //==================================================================
DBG_NAME(ORichTextPeer)333 DBG_NAME( ORichTextPeer )
334 //------------------------------------------------------------------
335 ORichTextPeer* ORichTextPeer::Create( const Reference< XControlModel >& _rxModel, Window* _pParentWindow, WinBits _nStyle )
336 {
337 DBG_TESTSOLARMUTEX();
338
339 // the EditEngine of the model
340 RichTextEngine* pEngine = ORichTextModel::getEditEngine( _rxModel );
341 OSL_ENSURE( pEngine, "ORichTextPeer::Create: could not obtaine the edit engine from the model!" );
342 if ( !pEngine )
343 return NULL;
344
345 // the peer itself
346 ORichTextPeer* pPeer = new ORichTextPeer;
347 pPeer->acquire(); // by definition, the returned object is acquired once
348
349 // the VCL control for the peer
350 RichTextControl* pRichTextControl = new RichTextControl( pEngine, _pParentWindow, _nStyle, NULL, pPeer );
351
352 // some knittings
353 pRichTextControl->SetComponentInterface( pPeer );
354
355 // outta here
356 return pPeer;
357 }
358
359 //------------------------------------------------------------------
ORichTextPeer()360 ORichTextPeer::ORichTextPeer()
361 {
362 DBG_CTOR( ORichTextPeer, NULL );
363 }
364
365 //------------------------------------------------------------------
~ORichTextPeer()366 ORichTextPeer::~ORichTextPeer()
367 {
368 DBG_DTOR( ORichTextPeer, NULL );
369 }
370
371 //------------------------------------------------------------------
dispose()372 void ORichTextPeer::dispose( ) throw(RuntimeException)
373 {
374 {
375 ::vos::OGuard aGuard( GetMutex() );
376 RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() );
377
378 if ( pRichTextControl )
379 {
380 for ( AttributeDispatchers::iterator aDisposeLoop = m_aDispatchers.begin();
381 aDisposeLoop != m_aDispatchers.end();
382 ++aDisposeLoop
383 )
384 {
385 pRichTextControl->disableAttributeNotification( aDisposeLoop->first );
386 aDisposeLoop->second->dispose();
387 }
388 }
389
390 AttributeDispatchers aEmpty;
391 m_aDispatchers.swap( aEmpty );
392 }
393
394 VCLXWindow::dispose();
395 }
396
397 //--------------------------------------------------------------------
draw(sal_Int32 _nX,sal_Int32 _nY)398 void SAL_CALL ORichTextPeer::draw( sal_Int32 _nX, sal_Int32 _nY ) throw(::com::sun::star::uno::RuntimeException)
399 {
400 ::vos::OGuard aGuard( Application::GetSolarMutex() );
401
402 RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() );
403 if ( !pControl )
404 return;
405
406 OutputDevice* pTargetDevice = VCLUnoHelper::GetOutputDevice( getGraphics() );
407 OSL_ENSURE( pTargetDevice != NULL, "ORichTextPeer::draw: no graphics -> no drawing!" );
408 if ( !pTargetDevice )
409 return;
410
411 ::Size aSize = pControl->GetSizePixel();
412 const MapUnit eTargetUnit = pTargetDevice->GetMapMode().GetMapUnit();
413 if ( eTargetUnit != MAP_PIXEL )
414 aSize = pControl->PixelToLogic( aSize, eTargetUnit );
415
416 ::Point aPos( _nX, _nY );
417 // the XView::draw API talks about pixels, always ...
418 if ( eTargetUnit != MAP_PIXEL )
419 aPos = pTargetDevice->PixelToLogic( aPos );
420
421 pControl->Draw( pTargetDevice, aPos, aSize, WINDOW_DRAW_NOCONTROLS );
422 }
423
424 //--------------------------------------------------------------------
setProperty(const::rtl::OUString & _rPropertyName,const Any & _rValue)425 void SAL_CALL ORichTextPeer::setProperty( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (RuntimeException)
426 {
427 if ( !GetWindow() )
428 {
429 VCLXWindow::setProperty( _rPropertyName, _rValue );
430 return;
431 }
432
433 if ( _rPropertyName.equals( PROPERTY_BACKGROUNDCOLOR ) )
434 {
435 RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() );
436 if ( !_rValue.hasValue() )
437 {
438 pControl->SetBackgroundColor( );
439 }
440 else
441 {
442 sal_Int32 nColor = COL_TRANSPARENT;
443 _rValue >>= nColor;
444 pControl->SetBackgroundColor( Color( nColor ) );
445 }
446 }
447 else if ( _rPropertyName.equals( PROPERTY_HSCROLL ) )
448 {
449 adjustTwoStateWinBit( GetWindow(), _rValue, WB_HSCROLL );
450 }
451 else if ( _rPropertyName.equals( PROPERTY_VSCROLL ) )
452 {
453 adjustTwoStateWinBit( GetWindow(), _rValue, WB_VSCROLL );
454 }
455 else if ( _rPropertyName.equals( PROPERTY_HARDLINEBREAKS ) )
456 {
457 adjustTwoStateWinBit( GetWindow(), _rValue, WB_WORDBREAK, true );
458 }
459 else if ( _rPropertyName.equals( PROPERTY_READONLY ) )
460 {
461 RichTextControl* pControl = static_cast< RichTextControl* >( GetWindow() );
462 sal_Bool bReadOnly( pControl->IsReadOnly() );
463 OSL_VERIFY( _rValue >>= bReadOnly );
464 pControl->SetReadOnly( bReadOnly );
465
466 // update the dispatchers
467 for ( AttributeDispatchers::iterator aDispatcherLoop = m_aDispatchers.begin();
468 aDispatcherLoop != m_aDispatchers.end();
469 ++aDispatcherLoop
470 )
471 {
472 aDispatcherLoop->second->invalidate();
473 }
474 }
475 else if ( _rPropertyName.equals( PROPERTY_HIDEINACTIVESELECTION ) )
476 {
477 RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() );
478 sal_Bool bHide = pRichTextControl->GetHideInactiveSelection();
479 OSL_VERIFY( _rValue >>= bHide );
480 pRichTextControl->SetHideInactiveSelection( bHide );
481 }
482 else
483 VCLXWindow::setProperty( _rPropertyName, _rValue );
484 }
485
486 //------------------------------------------------------------------
487 IMPLEMENT_FORWARD_XINTERFACE2( ORichTextPeer, VCLXWindow, ORichTextPeer_Base )
488
489 //------------------------------------------------------------------
490 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORichTextPeer, VCLXWindow, ORichTextPeer_Base )
491
492 //--------------------------------------------------------------------
493 namespace
494 {
lcl_translateConflictingSlot(SfxSlotId _nIDFromPool)495 static SfxSlotId lcl_translateConflictingSlot( SfxSlotId _nIDFromPool )
496 {
497 // HACK HACK HACK
498 // unfortunately, some of our applications have some conflicting slots,
499 // i.e. slots which have the same UNO name as an existing other (common)
500 // slot.
501 // For instance, both the slots SID_SET_SUPER_SCRIPT (from SVX) and FN_SET_SUPER_SCRIPT
502 // (from SW) have the UNO name "SuperScript".
503 // Now, if the controls lives in a text document, and asks the SfxSlotPool for
504 // the id belonging to "SuperScript", it gets the FN_SET_SUPER_SCRIPT - which
505 // is completely unknown to the EditEngine.
506 // So, we need to translate such conflicting ids.
507 //
508 // Note that the real solution would be to fix the applications to
509 // *not* define conflicting slots. Alternatively, if SFX would provide a slot pool
510 // which is *static* (i.e. independent on the active application), then we
511 // would also never encounter such a conflict.
512 SfxSlotId nReturn( _nIDFromPool );
513 switch ( _nIDFromPool )
514 {
515 case 20411: /* FM_SET_SUPER_SCRIPT, originating in SW */
516 nReturn = SID_SET_SUPER_SCRIPT;
517 break;
518 case 20412: /* FN_SET_SUB_SCRIPT, originating in SW */
519 nReturn = SID_SET_SUB_SCRIPT;
520 break;
521 }
522 return nReturn;
523 }
524 }
525
526 //--------------------------------------------------------------------
implCreateDispatcher(SfxSlotId _nSlotId,const::com::sun::star::util::URL & _rURL)527 ORichTextPeer::SingleAttributeDispatcher ORichTextPeer::implCreateDispatcher( SfxSlotId _nSlotId, const ::com::sun::star::util::URL& _rURL )
528 {
529 RichTextControl* pRichTextControl = static_cast< RichTextControl* >( GetWindow() );
530 OSL_PRECOND( pRichTextControl, "ORichTextPeer::implCreateDispatcher: invalid window!" );
531 if ( !pRichTextControl )
532 return SingleAttributeDispatcher( NULL );
533
534 ORichTextFeatureDispatcher* pDispatcher = NULL;
535 OAttributeDispatcher* pAttributeDispatcher = NULL;
536 switch ( _nSlotId )
537 {
538 case SID_CUT:
539 pDispatcher = new OClipboardDispatcher( pRichTextControl->getView(), OClipboardDispatcher::eCut );
540 break;
541
542 case SID_COPY:
543 pDispatcher = new OClipboardDispatcher( pRichTextControl->getView(), OClipboardDispatcher::eCopy );
544 break;
545
546 case SID_PASTE:
547 pDispatcher = new OPasteClipboardDispatcher( pRichTextControl->getView() );
548 break;
549
550 case SID_SELECTALL:
551 pDispatcher = new OSelectAllDispatcher( pRichTextControl->getView(), _rURL );
552 break;
553
554 case SID_ATTR_PARA_LEFT_TO_RIGHT:
555 case SID_ATTR_PARA_RIGHT_TO_LEFT:
556 pAttributeDispatcher = new OParagraphDirectionDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
557 break;
558
559 case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
560 case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
561 pDispatcher = new OTextDirectionDispatcher( pRichTextControl->getView(), _rURL );
562 break;
563
564 case SID_ATTR_PARA_HANGPUNCTUATION:
565 case SID_ATTR_PARA_FORBIDDEN_RULES:
566 case SID_ATTR_PARA_SCRIPTSPACE:
567 pAttributeDispatcher = new OAsianFontLayoutDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
568 break;
569
570 default:
571 {
572 // is it a supported slot?
573 bool bSupportedSlot = false;
574 if ( !bSupportedSlot )
575 {
576 const SfxItemPool& rPool = *pRichTextControl->getView().GetEmptyItemSet().GetPool();
577 bSupportedSlot = rPool.IsInRange( rPool.GetWhich( _nSlotId ) );
578 }
579 if ( !bSupportedSlot )
580 bSupportedSlot = RichTextControl::isMappableSlot( _nSlotId );
581
582 if ( bSupportedSlot )
583 { // it's really a slot which is supported by the EditEngine
584
585 bool bNeedParametrizedDispatcher = true;
586 if ( ( _nSlotId == SID_ATTR_CHAR_POSTURE )
587 || ( _nSlotId == SID_ATTR_CHAR_CJK_POSTURE )
588 || ( _nSlotId == SID_ATTR_CHAR_CTL_POSTURE )
589 || ( _nSlotId == SID_ATTR_CHAR_LATIN_POSTURE )
590 || ( _nSlotId == SID_ATTR_CHAR_WEIGHT )
591 || ( _nSlotId == SID_ATTR_CHAR_CJK_WEIGHT )
592 || ( _nSlotId == SID_ATTR_CHAR_CTL_WEIGHT )
593 || ( _nSlotId == SID_ATTR_CHAR_LATIN_WEIGHT )
594 || ( _nSlotId == SID_ATTR_CHAR_LANGUAGE )
595 || ( _nSlotId == SID_ATTR_CHAR_CJK_LANGUAGE )
596 || ( _nSlotId == SID_ATTR_CHAR_CTL_LANGUAGE )
597 || ( _nSlotId == SID_ATTR_CHAR_LATIN_LANGUAGE )
598 || ( _nSlotId == SID_ATTR_CHAR_CONTOUR )
599 || ( _nSlotId == SID_ATTR_CHAR_SHADOWED )
600 || ( _nSlotId == SID_ATTR_CHAR_WORDLINEMODE )
601 || ( _nSlotId == SID_ATTR_CHAR_COLOR )
602 || ( _nSlotId == SID_ATTR_CHAR_RELIEF )
603 || ( _nSlotId == SID_ATTR_CHAR_KERNING )
604 || ( _nSlotId == SID_ATTR_CHAR_AUTOKERN )
605 || ( _nSlotId == SID_ATTR_CHAR_SCALEWIDTH )
606 )
607 {
608 bNeedParametrizedDispatcher = true;
609 }
610 else if ( ( _nSlotId == SID_ATTR_PARA_HANGPUNCTUATION )
611 || ( _nSlotId == SID_ATTR_PARA_FORBIDDEN_RULES )
612 || ( _nSlotId == SID_ATTR_PARA_SCRIPTSPACE )
613 )
614 {
615 bNeedParametrizedDispatcher = false;
616 }
617 else
618 {
619 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( NULL );
620 const SfxSlot* pSlot = rSlotPool.GetSlot( _nSlotId );
621 const SfxType* pType = pSlot ? pSlot->GetType() : NULL;
622 if ( pType )
623 {
624 bNeedParametrizedDispatcher = ( pType->nAttribs > 0 );
625 }
626 }
627
628 if ( bNeedParametrizedDispatcher )
629 {
630 #if OSL_DEBUG_LEVEL > 0
631 ::rtl::OString sTrace( "ORichTextPeer::implCreateDispatcher: creating *parametrized* dispatcher for " );
632 sTrace += ::rtl::OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US );
633 DBG_TRACE( sTrace.getStr() );
634 #endif
635 pAttributeDispatcher = new OParametrizedAttributeDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
636 }
637 else
638 {
639 #if OSL_DEBUG_LEVEL > 0
640 ::rtl::OString sTrace( "ORichTextPeer::implCreateDispatcher: creating *normal* dispatcher for " );
641 sTrace += ::rtl::OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US );
642 DBG_TRACE( sTrace.getStr() );
643 #endif
644 pAttributeDispatcher = new OAttributeDispatcher( pRichTextControl->getView(), _nSlotId, _rURL, pRichTextControl );
645 }
646 }
647 #if OSL_DEBUG_LEVEL > 0
648 else
649 {
650 ::rtl::OString sTrace( "ORichTextPeer::implCreateDispatcher: not creating dispatcher (unsupported slot) for " );
651 sTrace += ::rtl::OString( _rURL.Complete.getStr(), _rURL.Complete.getLength(), RTL_TEXTENCODING_ASCII_US );
652 DBG_TRACE( sTrace.getStr() );
653 }
654 #endif
655 }
656 break;
657 }
658
659 SingleAttributeDispatcher xDispatcher( pDispatcher );
660 if ( pAttributeDispatcher )
661 {
662 xDispatcher = SingleAttributeDispatcher( pAttributeDispatcher );
663 pRichTextControl->enableAttributeNotification( _nSlotId, pAttributeDispatcher );
664 }
665
666 return xDispatcher;
667 }
668
669 //--------------------------------------------------------------------
670 namespace
671 {
lcl_getSlotFromUnoName(SfxSlotPool & _rSlotPool,const::rtl::OUString & _rUnoSlotName)672 SfxSlotId lcl_getSlotFromUnoName( SfxSlotPool& _rSlotPool, const ::rtl::OUString& _rUnoSlotName )
673 {
674 const SfxSlot* pSlot = _rSlotPool.GetUnoSlot( _rUnoSlotName );
675 if ( pSlot )
676 {
677 // okay, there's a slot with the given UNO name
678 return lcl_translateConflictingSlot( pSlot->GetSlotId() );
679 }
680
681 // some hard-coded slots, which do not have a UNO name at SFX level, but which
682 // we nevertheless need to transport via UNO mechanisms, so we need a name
683 if ( _rUnoSlotName.equalsAscii( "AllowHangingPunctuation" ) )
684 return SID_ATTR_PARA_HANGPUNCTUATION;
685 if ( _rUnoSlotName.equalsAscii( "ApplyForbiddenCharacterRules" ) )
686 return SID_ATTR_PARA_FORBIDDEN_RULES;
687 if ( _rUnoSlotName.equalsAscii( "UseScriptSpacing" ) )
688 return SID_ATTR_PARA_SCRIPTSPACE;
689
690 OSL_ENSURE( pSlot, "lcl_getSlotFromUnoName: unknown UNO slot name!" );
691 return 0;
692 }
693 }
694
695 //--------------------------------------------------------------------
queryDispatch(const::com::sun::star::util::URL & _rURL,const::rtl::OUString &,sal_Int32)696 Reference< XDispatch > SAL_CALL ORichTextPeer::queryDispatch( const ::com::sun::star::util::URL& _rURL, const ::rtl::OUString& /*_rTargetFrameName*/, sal_Int32 /*_nSearchFlags*/ ) throw (RuntimeException)
697 {
698 Reference< XDispatch > xReturn;
699 if ( !GetWindow() )
700 {
701 OSL_ENSURE( sal_False, "ORichTextPeer::queryDispatch: already disposed?" );
702 return xReturn;
703 }
704
705 // is it an UNO slot?
706 ::rtl::OUString sUnoProtocolPrefix( RTL_CONSTASCII_USTRINGPARAM( ".uno:" ) );
707 if ( 0 == _rURL.Complete.compareTo( sUnoProtocolPrefix, sUnoProtocolPrefix.getLength() ) )
708 {
709 ::rtl::OUString sUnoSlotName = _rURL.Complete.copy( sUnoProtocolPrefix.getLength() );
710 SfxSlotId nSlotId = lcl_getSlotFromUnoName( SfxSlotPool::GetSlotPool( NULL ), sUnoSlotName );
711 if ( nSlotId > 0 )
712 {
713 // do we already have a dispatcher for this?
714 AttributeDispatchers::const_iterator aDispatcherPos = m_aDispatchers.find( nSlotId );
715 if ( aDispatcherPos == m_aDispatchers.end() )
716 {
717 SingleAttributeDispatcher pDispatcher = implCreateDispatcher( nSlotId, _rURL );
718 if ( pDispatcher.is() )
719 {
720 aDispatcherPos = m_aDispatchers.insert( AttributeDispatchers::value_type( nSlotId, pDispatcher ) ).first;
721 }
722 }
723
724 if ( aDispatcherPos != m_aDispatchers.end() )
725 xReturn = aDispatcherPos->second.getRef();
726 }
727 }
728
729 return xReturn;
730 }
731
732 //--------------------------------------------------------------------
queryDispatches(const Sequence<DispatchDescriptor> & _rRequests)733 Sequence< Reference< XDispatch > > SAL_CALL ORichTextPeer::queryDispatches( const Sequence< DispatchDescriptor >& _rRequests ) throw (RuntimeException)
734 {
735 Sequence< Reference< XDispatch > > aReturn( _rRequests.getLength() );
736 Reference< XDispatch >* pReturn = aReturn.getArray();
737
738 const DispatchDescriptor* pRequest = _rRequests.getConstArray();
739 const DispatchDescriptor* pRequestEnd = pRequest + _rRequests.getLength();
740 for ( ; pRequest != pRequestEnd; ++pRequest, ++pReturn )
741 {
742 *pReturn = queryDispatch( pRequest->FeatureURL, pRequest->FrameName, pRequest->SearchFlags );
743 }
744 return aReturn;
745 }
746
747 //--------------------------------------------------------------------
onSelectionChanged(const ESelection &)748 void ORichTextPeer::onSelectionChanged( const ESelection& /*_rSelection*/ )
749 {
750 AttributeDispatchers::iterator aDispatcherPos = m_aDispatchers.find( SID_COPY );
751 if ( aDispatcherPos != m_aDispatchers.end() )
752 aDispatcherPos->second.get()->invalidate();
753
754 aDispatcherPos = m_aDispatchers.find( SID_CUT );
755 if ( aDispatcherPos != m_aDispatchers.end() )
756 aDispatcherPos->second.get()->invalidate();
757 }
758
759 //........................................................................
760 } // namespace frm
761 //........................................................................
762
763