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 //-------------------------------------------------------------------------- 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 //================================================================== 105 DBG_NAME( ORichTextControl ) 106 //------------------------------------------------------------------ 107 ORichTextControl::ORichTextControl( const Reference< XMultiServiceFactory >& _rxORB ) 108 :UnoEditControl( _rxORB ) 109 { 110 DBG_CTOR( ORichTextControl, NULL ); 111 } 112 113 //------------------------------------------------------------------ 114 ORichTextControl::~ORichTextControl() 115 { 116 DBG_DTOR( ORichTextControl, NULL ); 117 } 118 119 //------------------------------------------------------------------ 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 //.............................................................. 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 //.............................................................. 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 //.............................................................. 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 //.............................................................. 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 //.............................................................. 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 //------------------------------------------------------------------ 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 aquired 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 //------------------------------------------------------------------ 279 ::rtl::OUString SAL_CALL ORichTextControl::getImplementationName() throw( RuntimeException ) 280 { 281 return getImplementationName_Static(); 282 } 283 284 //------------------------------------------------------------------ 285 Sequence< ::rtl::OUString > SAL_CALL ORichTextControl::getSupportedServiceNames() throw( RuntimeException ) 286 { 287 return getSupportedServiceNames_Static(); 288 } 289 290 //------------------------------------------------------------------ 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 //------------------------------------------------------------------ 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 //------------------------------------------------------------------ 307 Reference< XInterface > SAL_CALL ORichTextControl::Create( const Reference< XMultiServiceFactory >& _rxFactory ) 308 { 309 return *( new ORichTextControl( _rxFactory ) ); 310 } 311 312 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 325 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 //================================================================== 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 aquired 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 //------------------------------------------------------------------ 360 ORichTextPeer::ORichTextPeer() 361 { 362 DBG_CTOR( ORichTextPeer, NULL ); 363 } 364 365 //------------------------------------------------------------------ 366 ORichTextPeer::~ORichTextPeer() 367 { 368 DBG_DTOR( ORichTextPeer, NULL ); 369 } 370 371 //------------------------------------------------------------------ 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 { 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 //-------------------------------------------------------------------- 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 { 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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 //-------------------------------------------------------------------- 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