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