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_vcl.hxx" 26 27 #include <string.h> 28 29 #include "rtl/instance.hxx" 30 31 #include "osl/process.h" 32 #include "osl/file.hxx" 33 34 #include "tools/debug.hxx" 35 #include "tools/resary.hxx" 36 37 #include "unotools/fontcfg.hxx" 38 39 #include "vos/mutex.hxx" 40 41 #include "cppuhelper/implbase1.hxx" 42 43 #include "uno/current_context.hxx" 44 45 #include "vcl/configsettings.hxx" 46 #include "vcl/svapp.hxx" 47 #include "vcl/wrkwin.hxx" 48 #include "vcl/msgbox.hxx" 49 #include "vcl/unohelp.hxx" 50 #include "vcl/button.hxx" // for Button::GetStandardText 51 #include "vcl/dockwin.hxx" // for DockingManager 52 53 #include "salinst.hxx" 54 #include "salframe.hxx" 55 #include "svdata.hxx" 56 #include "window.h" 57 #include "salimestatus.hxx" 58 #include "salsys.hxx" 59 #include "svids.hrc" 60 61 #include "com/sun/star/lang/XMultiServiceFactory.hpp" 62 #include "com/sun/star/lang/XComponent.hpp" 63 #include "com/sun/star/awt/XExtendedToolkit.hpp" 64 #include "com/sun/star/java/JavaNotConfiguredException.hpp" 65 #include "com/sun/star/java/JavaVMCreationFailureException.hpp" 66 #include "com/sun/star/java/MissingJavaRuntimeException.hpp" 67 #include "com/sun/star/java/JavaDisabledException.hpp" 68 69 #include <stdio.h> 70 71 namespace { 72 73 namespace css = com::sun::star; 74 75 } 76 77 using namespace com::sun::star::uno; 78 using namespace com::sun::star::lang; 79 using namespace com::sun::star::awt; 80 using namespace rtl; 81 82 // ======================================================================= 83 84 namespace 85 { 86 struct private_aImplSVData : 87 public rtl::Static<ImplSVData, private_aImplSVData> {}; 88 } 89 90 // static SV-Data 91 ImplSVData* pImplSVData = NULL; 92 93 SalSystem* ImplGetSalSystem() 94 { 95 ImplSVData* pSVData = ImplGetSVData(); 96 if( ! pSVData->mpSalSystem ) 97 pSVData->mpSalSystem = pSVData->mpDefInst->CreateSalSystem(); 98 return pSVData->mpSalSystem; 99 } 100 101 102 static String& ReplaceJavaErrorMessages( String& rString ) 103 { 104 rString.SearchAndReplaceAllAscii( "%OK", Button::GetStandardText( BUTTON_OK ) ); 105 rString.SearchAndReplaceAllAscii( "%IGNORE", Button::GetStandardText( BUTTON_IGNORE ) ); 106 rString.SearchAndReplaceAllAscii( "%CANCEL", Button::GetStandardText( BUTTON_CANCEL ) ); 107 108 return rString; 109 } 110 111 // ======================================================================= 112 113 void ImplInitSVData() 114 { 115 pImplSVData = &private_aImplSVData::get(); 116 117 // init global instance data 118 memset( pImplSVData, 0, sizeof( ImplSVData ) ); 119 pImplSVData->maHelpData.mbAutoHelpId = sal_True; 120 pImplSVData->maNWFData.maMenuBarHighlightTextColor = Color( COL_TRANSPARENT ); 121 122 // find out whether we are running in the testtool 123 // in this case we need some special workarounds 124 sal_uInt32 nArgs = osl_getCommandArgCount(); 125 for( sal_uInt32 i = 0; i < nArgs; i++ ) 126 { 127 rtl::OUString aArg; 128 osl_getCommandArg( i, &aArg.pData ); 129 if( aArg.equalsAscii( "-enableautomation" ) ) 130 { 131 pImplSVData->mbIsTestTool = true; 132 break; 133 } 134 } 135 136 // mark default layout border as unitialized 137 pImplSVData->maAppData.mnDefaultLayoutBorder = -1; 138 } 139 140 // ----------------------------------------------------------------------- 141 142 void ImplDeInitSVData() 143 { 144 ImplSVData* pSVData = ImplGetSVData(); 145 146 // delete global instance data 147 if( pSVData->mpSettingsConfigItem ) 148 delete pSVData->mpSettingsConfigItem; 149 150 if( pSVData->mpDockingManager ) 151 delete pSVData->mpDockingManager; 152 153 if( pSVData->maGDIData.mpDefaultFontConfiguration ) 154 delete pSVData->maGDIData.mpDefaultFontConfiguration; 155 if( pSVData->maGDIData.mpFontSubstConfiguration ) 156 delete pSVData->maGDIData.mpFontSubstConfiguration; 157 158 if ( pSVData->maAppData.mpMSFTempFileName ) 159 { 160 if ( pSVData->maAppData.mxMSF.is() ) 161 { 162 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > xComp( pSVData->maAppData.mxMSF, ::com::sun::star::uno::UNO_QUERY ); 163 xComp->dispose(); 164 pSVData->maAppData.mxMSF = NULL; 165 } 166 167 ::rtl::OUString aFileUrl; 168 ::osl::File::getFileURLFromSystemPath( *pSVData->maAppData.mpMSFTempFileName, aFileUrl ); 169 osl::File::remove( aFileUrl ); 170 delete pSVData->maAppData.mpMSFTempFileName; 171 pSVData->maAppData.mpMSFTempFileName = NULL; 172 } 173 174 if( pSVData->maCtrlData.mpFieldUnitStrings ) 175 delete pSVData->maCtrlData.mpFieldUnitStrings, pSVData->maCtrlData.mpFieldUnitStrings = NULL; 176 if( pSVData->maCtrlData.mpCleanUnitStrings ) 177 delete pSVData->maCtrlData.mpCleanUnitStrings, pSVData->maCtrlData.mpCleanUnitStrings = NULL; 178 if( pSVData->mpPaperNames ) 179 delete pSVData->mpPaperNames, pSVData->mpPaperNames = NULL; 180 } 181 182 // ----------------------------------------------------------------------- 183 184 void ImplDestroySVData() 185 { 186 pImplSVData = NULL; 187 } 188 189 // ----------------------------------------------------------------------- 190 191 Window* ImplGetDefaultWindow() 192 { 193 ImplSVData* pSVData = ImplGetSVData(); 194 if ( pSVData->maWinData.mpAppWin ) 195 return pSVData->maWinData.mpAppWin; 196 197 // First test if we already have a default window. 198 // Don't only place a single if..else inside solar mutex lockframe 199 // because then we might have to wait for the solar mutex what is not neccessary 200 // if we already have a default window. 201 202 if ( !pSVData->mpDefaultWin ) 203 { 204 Application::GetSolarMutex().acquire(); 205 206 // Test again because the thread who released the solar mutex could have called 207 // the same method 208 209 if ( !pSVData->mpDefaultWin && !pSVData->mbDeInit ) 210 { 211 DBG_WARNING( "ImplGetDefaultWindow(): No AppWindow" ); 212 pSVData->mpDefaultWin = new WorkWindow( 0, WB_DEFAULTWIN ); 213 pSVData->mpDefaultWin->SetText( OUString( RTL_CONSTASCII_USTRINGPARAM( "VCL ImplGetDefaultWindow" ) ) ); 214 } 215 Application::GetSolarMutex().release(); 216 } 217 218 return pSVData->mpDefaultWin; 219 } 220 221 // ----------------------------------------------------------------------- 222 223 #define VCL_CREATERESMGR_NAME( Name ) #Name 224 225 ResMgr* ImplGetResMgr() 226 { 227 ImplSVData* pSVData = ImplGetSVData(); 228 if ( !pSVData->mpResMgr ) 229 { 230 ::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale(); 231 pSVData->mpResMgr = ResMgr::SearchCreateResMgr( VCL_CREATERESMGR_NAME( vcl ), aLocale ); 232 233 static bool bMessageOnce = false; 234 if( !pSVData->mpResMgr && ! bMessageOnce ) 235 { 236 bMessageOnce = true; 237 const char* pMsg = 238 "Missing vcl resource. This indicates that files vital to localization are missing. " 239 "You might have a corrupt installation."; 240 fprintf( stderr, "%s\n", pMsg ); 241 ErrorBox aBox( NULL, WB_OK | WB_DEF_OK, rtl::OUString( pMsg, strlen( pMsg ), RTL_TEXTENCODING_ASCII_US ) ); 242 aBox.Execute(); 243 } 244 } 245 return pSVData->mpResMgr; 246 } 247 248 ResId VclResId( sal_Int32 nId ) 249 { 250 ResMgr* pMgr = ImplGetResMgr(); 251 if( ! pMgr ) 252 throw std::bad_alloc(); 253 254 return ResId( nId, *pMgr ); 255 } 256 257 FieldUnitStringList* ImplGetFieldUnits() 258 { 259 ImplSVData* pSVData = ImplGetSVData(); 260 if( ! pSVData->maCtrlData.mpFieldUnitStrings ) 261 { 262 ResMgr* pResMgr = ImplGetResMgr(); 263 if( pResMgr ) 264 { 265 ResStringArray aUnits( ResId (SV_FUNIT_STRINGS, *pResMgr) ); 266 sal_uInt32 nUnits = aUnits.Count(); 267 pSVData->maCtrlData.mpFieldUnitStrings = new FieldUnitStringList(); 268 pSVData->maCtrlData.mpFieldUnitStrings->reserve( nUnits ); 269 for( sal_uInt32 i = 0; i < nUnits; i++ ) 270 { 271 std::pair< String, FieldUnit > aElement( aUnits.GetString(i), static_cast<FieldUnit>(aUnits.GetValue(i)) ); 272 pSVData->maCtrlData.mpFieldUnitStrings->push_back( aElement ); 273 } 274 } 275 } 276 return pSVData->maCtrlData.mpFieldUnitStrings; 277 } 278 279 FieldUnitStringList* ImplGetCleanedFieldUnits() 280 { 281 ImplSVData* pSVData = ImplGetSVData(); 282 if( ! pSVData->maCtrlData.mpCleanUnitStrings ) 283 { 284 FieldUnitStringList* pUnits = ImplGetFieldUnits(); 285 if( pUnits ) 286 { 287 size_t nUnits = pUnits->size(); 288 pSVData->maCtrlData.mpCleanUnitStrings = new FieldUnitStringList(); 289 pSVData->maCtrlData.mpCleanUnitStrings->reserve( nUnits ); 290 for( size_t i = 0; i < nUnits; i++ ) 291 { 292 String aUnit( (*pUnits)[i].first ); 293 aUnit.EraseAllChars( sal_Unicode( ' ' ) ); 294 aUnit.ToLowerAscii(); 295 std::pair< String, FieldUnit > aElement( aUnit, (*pUnits)[i].second ); 296 pSVData->maCtrlData.mpCleanUnitStrings->push_back( aElement ); 297 } 298 } 299 } 300 return pSVData->maCtrlData.mpCleanUnitStrings; 301 } 302 303 DockingManager* ImplGetDockingManager() 304 { 305 ImplSVData* pSVData = ImplGetSVData(); 306 if ( !pSVData->mpDockingManager ) 307 pSVData->mpDockingManager = new DockingManager(); 308 309 return pSVData->mpDockingManager; 310 } 311 312 class AccessBridgeCurrentContext: public cppu::WeakImplHelper1< com::sun::star::uno::XCurrentContext > 313 { 314 public: 315 AccessBridgeCurrentContext( 316 const com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > &context ) : 317 m_prevContext( context ) {} 318 319 // XCurrentContext 320 virtual com::sun::star::uno::Any SAL_CALL getValueByName( const rtl::OUString& Name ) 321 throw (com::sun::star::uno::RuntimeException); 322 private: 323 com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > m_prevContext; 324 }; 325 326 com::sun::star::uno::Any AccessBridgeCurrentContext::getValueByName( const rtl::OUString & Name ) 327 throw (com::sun::star::uno::RuntimeException) 328 { 329 com::sun::star::uno::Any ret; 330 if( Name.equalsAscii( "java-vm.interaction-handler" ) ) 331 { 332 // Currently, for accessbility no interaction handler shall be offered. 333 // There may be introduced later on a handler using native toolkits 334 // jbu->obr: Instantiate here your interaction handler 335 } 336 else if( m_prevContext.is() ) 337 { 338 ret = m_prevContext->getValueByName( Name ); 339 } 340 return ret; 341 } 342 343 344 bool ImplInitAccessBridge(sal_Bool bAllowCancel, sal_Bool &rCancelled) 345 { 346 rCancelled = sal_False; 347 348 bool bErrorMessage = true; 349 350 // Note: 351 // if bAllowCancel is sal_True we were called from application startup 352 // where we will disable any Java errorboxes and show our own accessibility dialog if Java throws an exception 353 // if bAllowCancel is sal_False we were called from Tools->Options 354 // where we will see Java errorboxes, se we do not show our dialogs in addition to Java's 355 356 try 357 { 358 bool bSuccess = true; 359 360 // No error messages when env var is set .. 361 static const char* pEnv = getenv("SAL_ACCESSIBILITY_ENABLED" ); 362 if( pEnv && *pEnv ) 363 { 364 bErrorMessage = false; 365 } 366 367 ImplSVData* pSVData = ImplGetSVData(); 368 if( ! pSVData->mxAccessBridge.is() ) 369 { 370 css::uno::Reference< XMultiServiceFactory > xFactory(vcl::unohelper::GetMultiServiceFactory()); 371 372 if( xFactory.is() ) 373 { 374 css::uno::Reference< XExtendedToolkit > xToolkit = 375 css::uno::Reference< XExtendedToolkit >(Application::GetVCLToolkit(), UNO_QUERY); 376 377 Sequence< Any > arguments(1); 378 arguments[0] = makeAny(xToolkit); 379 380 // Disable default java error messages on startup, because they were probably unreadable 381 // for a disabled user. Use native message boxes which are accessible without java support. 382 // No need to do this when activated by Tools-Options dialog .. 383 if( bAllowCancel ) 384 { 385 // customize the java-not-available-interaction-handler entry within the 386 // current context when called at startup. 387 com::sun::star::uno::ContextLayer layer( 388 new AccessBridgeCurrentContext( com::sun::star::uno::getCurrentContext() ) ); 389 390 pSVData->mxAccessBridge = xFactory->createInstanceWithArguments( 391 OUString::createFromAscii( "com.sun.star.accessibility.AccessBridge" ), 392 arguments 393 ); 394 } 395 else 396 { 397 pSVData->mxAccessBridge = xFactory->createInstanceWithArguments( 398 OUString::createFromAscii( "com.sun.star.accessibility.AccessBridge" ), 399 arguments 400 ); 401 } 402 403 if( !pSVData->mxAccessBridge.is() ) 404 bSuccess = false; 405 } 406 } 407 408 return bSuccess; 409 } 410 411 catch(::com::sun::star::java::JavaNotConfiguredException&) 412 { 413 ResMgr *pResMgr = ImplGetResMgr(); 414 if( bErrorMessage && bAllowCancel && pResMgr ) 415 { 416 String aTitle(ResId(SV_ACCESSERROR_JAVA_NOT_CONFIGURED, *pResMgr)); 417 String aMessage(ResId(SV_ACCESSERROR_JAVA_MSG, *pResMgr)); 418 419 aMessage += String(" ", 1, RTL_TEXTENCODING_ASCII_US); 420 aMessage += String(ResId(SV_ACCESSERROR_OK_CANCEL_MSG, *pResMgr)); 421 422 int ret = ImplGetSalSystem()->ShowNativeMessageBox( 423 aTitle, 424 ReplaceJavaErrorMessages(aMessage), 425 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, 426 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL); 427 428 // Do not change the setting in case the user chooses to cancel 429 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL == ret ) 430 rCancelled = sal_True; 431 } 432 433 return false; 434 } 435 436 catch(::com::sun::star::java::JavaVMCreationFailureException&) 437 { 438 ResMgr *pResMgr = ImplGetResMgr(); 439 if( bErrorMessage && bAllowCancel && pResMgr ) 440 { 441 String aTitle(ResId(SV_ACCESSERROR_FAULTY_JAVA, *pResMgr)); 442 String aMessage(ResId(SV_ACCESSERROR_JAVA_MSG, *pResMgr)); 443 444 aMessage += String(" ", 1, RTL_TEXTENCODING_ASCII_US); 445 aMessage += String(ResId(SV_ACCESSERROR_OK_CANCEL_MSG, *pResMgr)); 446 447 int ret = ImplGetSalSystem()->ShowNativeMessageBox( 448 aTitle, 449 ReplaceJavaErrorMessages(aMessage), 450 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, 451 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL); 452 453 // Do not change the setting in case the user chooses to cancel 454 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL == ret ) 455 rCancelled = sal_True; 456 } 457 458 return false; 459 } 460 461 catch(::com::sun::star::java::MissingJavaRuntimeException&) 462 { 463 ResMgr *pResMgr = ImplGetResMgr(); 464 if( bErrorMessage && bAllowCancel && pResMgr ) 465 { 466 String aTitle(ResId(SV_ACCESSERROR_MISSING_JAVA, *pResMgr)); 467 String aMessage(ResId(SV_ACCESSERROR_JAVA_MSG, *pResMgr)); 468 469 aMessage += String(" ", 1, RTL_TEXTENCODING_ASCII_US); 470 aMessage += String(ResId(SV_ACCESSERROR_OK_CANCEL_MSG, *pResMgr)); 471 472 int ret = ImplGetSalSystem()->ShowNativeMessageBox( 473 aTitle, 474 ReplaceJavaErrorMessages(aMessage), 475 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, 476 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL); 477 478 // Do not change the setting in case the user chooses to cancel 479 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL == ret ) 480 rCancelled = sal_True; 481 } 482 483 return false; 484 } 485 486 catch(::com::sun::star::java::JavaDisabledException&) 487 { 488 ResMgr *pResMgr = ImplGetResMgr(); 489 if( bErrorMessage && bAllowCancel && pResMgr ) 490 { 491 String aTitle(ResId(SV_ACCESSERROR_JAVA_DISABLED, *pResMgr)); 492 String aMessage(ResId(SV_ACCESSERROR_JAVA_MSG, *pResMgr)); 493 494 aMessage += String(" ", 1, RTL_TEXTENCODING_ASCII_US); 495 aMessage += String(ResId(SV_ACCESSERROR_OK_CANCEL_MSG, *pResMgr)); 496 497 int ret = ImplGetSalSystem()->ShowNativeMessageBox( 498 aTitle, 499 ReplaceJavaErrorMessages(aMessage), 500 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, 501 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL); 502 503 // Do not change the setting in case the user chooses to cancel 504 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL == ret ) 505 rCancelled = sal_True; 506 } 507 508 return false; 509 } 510 511 512 catch(::com::sun::star::uno::RuntimeException& e) 513 { 514 ResMgr *pResMgr = ImplGetResMgr(); 515 if( bErrorMessage && pResMgr ) 516 { 517 String aTitle; 518 String aMessage(ResId(SV_ACCESSERROR_BRIDGE_MSG, *pResMgr)); 519 520 if( 0 == e.Message.compareTo(::rtl::OUString::createFromAscii("ClassNotFound"), 13) ) 521 { 522 aTitle = String(ResId(SV_ACCESSERROR_MISSING_BRIDGE, *pResMgr)); 523 } 524 else if( 0 == e.Message.compareTo(::rtl::OUString::createFromAscii("NoSuchMethod"), 12) ) 525 { 526 aTitle = String(ResId(SV_ACCESSERROR_WRONG_VERSION, *pResMgr)); 527 } 528 529 if( aTitle.Len() != 0 ) 530 { 531 if( bAllowCancel ) 532 { 533 // Something went wrong initializing the Java AccessBridge (on Windows) during the 534 // startup. Since the office will be probably unusable for a disabled user, we offer 535 // to terminate directly. 536 aMessage += String(" ", 1, RTL_TEXTENCODING_ASCII_US); 537 aMessage += String(ResId(SV_ACCESSERROR_OK_CANCEL_MSG, *pResMgr)); 538 539 int ret = ImplGetSalSystem()->ShowNativeMessageBox( 540 aTitle, 541 ReplaceJavaErrorMessages(aMessage), 542 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL, 543 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL); 544 545 // Do not change the setting in case the user chooses to cancel 546 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL == ret ) 547 rCancelled = sal_True; 548 } 549 else 550 { 551 // The user tried to activate accessibility support using Tools-Options dialog, 552 // so we don't offer to terminate here ! 553 ImplGetSalSystem()->ShowNativeMessageBox( 554 aTitle, 555 ReplaceJavaErrorMessages(aMessage), 556 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK, 557 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK); 558 } 559 } 560 } 561 562 return false; 563 } 564 565 catch (...) 566 { 567 return false; 568 } 569 } 570 571 // ----------------------------------------------------------------------- 572 573 Window* ImplFindWindow( const SalFrame* pFrame, ::Point& rSalFramePos ) 574 { 575 ImplSVData* pSVData = ImplGetSVData(); 576 Window* pFrameWindow = pSVData->maWinData.mpFirstFrame; 577 while ( pFrameWindow ) 578 { 579 if ( pFrameWindow->ImplGetFrame() == pFrame ) 580 { 581 Window* pWindow = pFrameWindow->ImplFindWindow( rSalFramePos ); 582 if ( !pWindow ) 583 pWindow = pFrameWindow->ImplGetWindow(); 584 rSalFramePos = pWindow->ImplFrameToOutput( rSalFramePos ); 585 return pWindow; 586 } 587 pFrameWindow = pFrameWindow->ImplGetFrameData()->mpNextFrame; 588 } 589 590 return NULL; 591 } 592 593 void LocaleConfigurationListener::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 nHint ) 594 { 595 AllSettings::LocaleSettingsChanged( nHint ); 596 } 597 598