1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <boost/ptr_container/ptr_vector.hpp>
23 #include <comphelper/processfactory.hxx>
24 #include <comphelper/string.hxx>
25 #include <osl/mutex.hxx>
26 #include <rtl/process.h>
27 #include <tools/debug.hxx>
28 #include <tools/resary.hxx>
29 #include <tools/gen.hxx>
30 #include <unotools/fontcfg.hxx>
31 #include <cppuhelper/implbase1.hxx>
32 #include <uno/current_context.hxx>
34 #include "vcl/configsettings.hxx"
35 #include "vcl/svapp.hxx"
36 #include "vcl/wrkwin.hxx"
37 #include "vcl/msgbox.hxx"
38 #include "vcl/button.hxx" // for Button::GetStandardText
39 #include "vcl/dockwin.hxx" // for DockingManager
40 #include "salinst.hxx"
41 #include "salframe.hxx"
44 #include "salimestatus.hxx"
48 #include "com/sun/star/accessibility/AccessBridge.hpp"
49 #include "com/sun/star/awt/XExtendedToolkit.hpp"
50 #include "com/sun/star/java/JavaNotConfiguredException.hpp"
51 #include "com/sun/star/java/JavaVMCreationFailureException.hpp"
52 #include "com/sun/star/java/MissingJavaRuntimeException.hpp"
53 #include "com/sun/star/java/JavaDisabledException.hpp"
57 using namespace com::sun::star::uno
;
58 using namespace com::sun::star::lang
;
59 using namespace com::sun::star::awt
;
61 // =======================================================================
65 struct private_aImplSVData
:
66 public rtl::Static
<ImplSVData
, private_aImplSVData
> {};
70 ImplSVData
* pImplSVData
= NULL
;
72 SalSystem
* ImplGetSalSystem()
74 ImplSVData
* pSVData
= ImplGetSVData();
75 if( ! pSVData
->mpSalSystem
)
76 pSVData
->mpSalSystem
= pSVData
->mpDefInst
->CreateSalSystem();
77 return pSVData
->mpSalSystem
;
81 static OUString
ReplaceJavaErrorMessages( const OUString
& rString
)
83 return rString
.replaceAll("%OK", Button::GetStandardText(BUTTON_OK
)).
84 replaceAll("%IGNORE", Button::GetStandardText(BUTTON_IGNORE
)).
85 replaceAll("%CANCEL", Button::GetStandardText(BUTTON_CANCEL
));
88 // =======================================================================
92 pImplSVData
= &private_aImplSVData::get();
94 // init global instance data
95 memset( pImplSVData
, 0, sizeof( ImplSVData
) );
96 pImplSVData
->maHelpData
.mbAutoHelpId
= sal_True
;
97 pImplSVData
->maNWFData
.maMenuBarHighlightTextColor
= Color( COL_TRANSPARENT
);
99 // mark default layout border as unitialized
100 pImplSVData
->maAppData
.mnDefaultLayoutBorder
= -1;
103 // -----------------------------------------------------------------------
105 void ImplDeInitSVData()
107 ImplSVData
* pSVData
= ImplGetSVData();
109 // delete global instance data
110 if( pSVData
->mpSettingsConfigItem
)
111 delete pSVData
->mpSettingsConfigItem
;
113 if( pSVData
->mpDockingManager
)
114 delete pSVData
->mpDockingManager
;
116 if( pSVData
->maGDIData
.mpDefaultFontConfiguration
)
117 delete pSVData
->maGDIData
.mpDefaultFontConfiguration
;
118 if( pSVData
->maGDIData
.mpFontSubstConfiguration
)
119 delete pSVData
->maGDIData
.mpFontSubstConfiguration
;
121 if( pSVData
->maCtrlData
.mpFieldUnitStrings
)
122 delete pSVData
->maCtrlData
.mpFieldUnitStrings
, pSVData
->maCtrlData
.mpFieldUnitStrings
= NULL
;
123 if( pSVData
->maCtrlData
.mpCleanUnitStrings
)
124 delete pSVData
->maCtrlData
.mpCleanUnitStrings
, pSVData
->maCtrlData
.mpCleanUnitStrings
= NULL
;
125 if( pSVData
->mpPaperNames
)
126 delete pSVData
->mpPaperNames
, pSVData
->mpPaperNames
= NULL
;
129 // -----------------------------------------------------------------------
131 void ImplDestroySVData()
136 // -----------------------------------------------------------------------
138 Window
* ImplGetDefaultWindow()
140 ImplSVData
* pSVData
= ImplGetSVData();
141 if ( pSVData
->maWinData
.mpAppWin
)
142 return pSVData
->maWinData
.mpAppWin
;
144 // First test if we already have a default window.
145 // Don't only place a single if..else inside solar mutex lockframe
146 // because then we might have to wait for the solar mutex what is not necessary
147 // if we already have a default window.
149 if ( !pSVData
->mpDefaultWin
)
151 Application::GetSolarMutex().acquire();
153 // Test again because the thread who released the solar mutex could have called
156 if ( !pSVData
->mpDefaultWin
&& !pSVData
->mbDeInit
)
158 DBG_WARNING( "ImplGetDefaultWindow(): No AppWindow" );
159 pSVData
->mpDefaultWin
= new WorkWindow( 0, WB_DEFAULTWIN
);
160 pSVData
->mpDefaultWin
->SetText( OUString( "VCL ImplGetDefaultWindow" ) );
162 Application::GetSolarMutex().release();
165 return pSVData
->mpDefaultWin
;
168 // -----------------------------------------------------------------------
170 #define VCL_CREATERESMGR_NAME( Name ) #Name
172 ResMgr
* ImplGetResMgr()
174 ImplSVData
* pSVData
= ImplGetSVData();
175 if ( !pSVData
->mpResMgr
)
177 LanguageTag
aLocale( Application::GetSettings().GetUILanguageTag());
178 pSVData
->mpResMgr
= ResMgr::SearchCreateResMgr( VCL_CREATERESMGR_NAME( vcl
), aLocale
);
180 static bool bMessageOnce
= false;
181 if( !pSVData
->mpResMgr
&& ! bMessageOnce
)
185 "Missing vcl resource. This indicates that files vital to localization are missing. "
186 "You might have a corrupt installation.";
187 fprintf( stderr
, "%s\n", pMsg
);
188 ErrorBox
aBox( NULL
, WB_OK
| WB_DEF_OK
, OUString( pMsg
, strlen( pMsg
), RTL_TEXTENCODING_ASCII_US
) );
192 return pSVData
->mpResMgr
;
195 ResId
VclResId( sal_Int32 nId
)
197 ResMgr
* pMgr
= ImplGetResMgr();
199 throw std::bad_alloc();
201 return ResId( nId
, *pMgr
);
204 FieldUnitStringList
* ImplGetFieldUnits()
206 ImplSVData
* pSVData
= ImplGetSVData();
207 if( ! pSVData
->maCtrlData
.mpFieldUnitStrings
)
209 ResMgr
* pResMgr
= ImplGetResMgr();
212 ResStringArray
aUnits( ResId (SV_FUNIT_STRINGS
, *pResMgr
) );
213 sal_uInt32 nUnits
= aUnits
.Count();
214 pSVData
->maCtrlData
.mpFieldUnitStrings
= new FieldUnitStringList();
215 pSVData
->maCtrlData
.mpFieldUnitStrings
->reserve( nUnits
);
216 for( sal_uInt32 i
= 0; i
< nUnits
; i
++ )
218 std::pair
< String
, FieldUnit
> aElement( aUnits
.GetString(i
), static_cast<FieldUnit
>(aUnits
.GetValue(i
)) );
219 pSVData
->maCtrlData
.mpFieldUnitStrings
->push_back( aElement
);
223 return pSVData
->maCtrlData
.mpFieldUnitStrings
;
226 FieldUnitStringList
* ImplGetCleanedFieldUnits()
228 ImplSVData
* pSVData
= ImplGetSVData();
229 if( ! pSVData
->maCtrlData
.mpCleanUnitStrings
)
231 FieldUnitStringList
* pUnits
= ImplGetFieldUnits();
234 size_t nUnits
= pUnits
->size();
235 pSVData
->maCtrlData
.mpCleanUnitStrings
= new FieldUnitStringList();
236 pSVData
->maCtrlData
.mpCleanUnitStrings
->reserve( nUnits
);
237 for( size_t i
= 0; i
< nUnits
; ++i
)
239 OUString
aUnit( (*pUnits
)[i
].first
);
240 aUnit
= comphelper::string::remove(aUnit
, ' ');
241 aUnit
= aUnit
.toAsciiLowerCase();
242 std::pair
< String
, FieldUnit
> aElement( aUnit
, (*pUnits
)[i
].second
);
243 pSVData
->maCtrlData
.mpCleanUnitStrings
->push_back( aElement
);
247 return pSVData
->maCtrlData
.mpCleanUnitStrings
;
250 DockingManager
* ImplGetDockingManager()
252 ImplSVData
* pSVData
= ImplGetSVData();
253 if ( !pSVData
->mpDockingManager
)
254 pSVData
->mpDockingManager
= new DockingManager();
256 return pSVData
->mpDockingManager
;
259 BlendFrameCache
* ImplGetBlendFrameCache()
261 ImplSVData
* pSVData
= ImplGetSVData();
262 if ( !pSVData
->mpBlendFrameCache
)
263 pSVData
->mpBlendFrameCache
= new BlendFrameCache();
265 return pSVData
->mpBlendFrameCache
;
268 class AccessBridgeCurrentContext
: public cppu::WeakImplHelper1
< com::sun::star::uno::XCurrentContext
>
271 AccessBridgeCurrentContext(
272 const com::sun::star::uno::Reference
< com::sun::star::uno::XCurrentContext
> &context
) :
273 m_prevContext( context
) {}
276 virtual com::sun::star::uno::Any SAL_CALL
getValueByName( const OUString
& Name
)
277 throw (com::sun::star::uno::RuntimeException
);
279 com::sun::star::uno::Reference
< com::sun::star::uno::XCurrentContext
> m_prevContext
;
282 com::sun::star::uno::Any
AccessBridgeCurrentContext::getValueByName( const OUString
& Name
)
283 throw (com::sun::star::uno::RuntimeException
)
285 com::sun::star::uno::Any ret
;
286 if ( Name
== "java-vm.interaction-handler" )
288 // Currently, for accessbility no interaction handler shall be offered.
289 // There may be introduced later on a handler using native toolkits
290 // jbu->obr: Instantiate here your interaction handler
292 else if( m_prevContext
.is() )
294 ret
= m_prevContext
->getValueByName( Name
);
300 bool ImplInitAccessBridge(bool bAllowCancel
, bool &rCancelled
)
304 bool bErrorMessage
= true;
307 // if bAllowCancel is sal_True we were called from application startup
308 // where we will disable any Java errorboxes and show our own accessibility dialog if Java throws an exception
309 // if bAllowCancel is sal_False we were called from Tools->Options
310 // where we will see Java errorboxes, se we do not show our dialogs in addition to Java's
314 // No error messages when env var is set ..
315 static const char* pEnv
= getenv("SAL_ACCESSIBILITY_ENABLED" );
318 bErrorMessage
= false;
321 ImplSVData
* pSVData
= ImplGetSVData();
322 if( ! pSVData
->mxAccessBridge
.is() )
324 css::uno::Reference
< XComponentContext
> xContext(comphelper::getProcessComponentContext());
326 css::uno::Reference
< XExtendedToolkit
> xToolkit
=
327 css::uno::Reference
< XExtendedToolkit
>(Application::GetVCLToolkit(), UNO_QUERY
);
329 // Disable default java error messages on startup, because they were probably unreadable
330 // for a disabled user. Use native message boxes which are accessible without java support.
331 // No need to do this when activated by Tools-Options dialog ..
334 // customize the java-not-available-interaction-handler entry within the
335 // current context when called at startup.
336 com::sun::star::uno::ContextLayer
layer(
337 new AccessBridgeCurrentContext( com::sun::star::uno::getCurrentContext() ) );
339 pSVData
->mxAccessBridge
340 = css::accessibility::AccessBridge::createWithToolkit(
345 pSVData
->mxAccessBridge
346 = css::accessibility::AccessBridge::createWithToolkit(
353 catch (const ::com::sun::star::java::JavaNotConfiguredException
&)
355 ResMgr
*pResMgr
= ImplGetResMgr();
356 if( bErrorMessage
&& bAllowCancel
&& pResMgr
)
358 OUString
aTitle(ResId(SV_ACCESSERROR_JAVA_NOT_CONFIGURED
, *pResMgr
).toString());
359 OUStringBuffer
aMessage((ResId(SV_ACCESSERROR_JAVA_MSG
, *pResMgr
)).toString());
361 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
363 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
365 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
366 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
367 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
369 // Do not change the setting in case the user chooses to cancel
370 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
376 catch (const ::com::sun::star::java::JavaVMCreationFailureException
&)
378 ResMgr
*pResMgr
= ImplGetResMgr();
379 if( bErrorMessage
&& bAllowCancel
&& pResMgr
)
381 OUString
aTitle(ResId(SV_ACCESSERROR_FAULTY_JAVA
, *pResMgr
).toString());
382 OUStringBuffer
aMessage(ResId(SV_ACCESSERROR_JAVA_MSG
, *pResMgr
).toString());
384 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
386 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
388 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
389 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
390 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
392 // Do not change the setting in case the user chooses to cancel
393 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
399 catch (const ::com::sun::star::java::MissingJavaRuntimeException
&)
401 ResMgr
*pResMgr
= ImplGetResMgr();
402 if( bErrorMessage
&& bAllowCancel
&& pResMgr
)
404 OUString
aTitle(ResId(SV_ACCESSERROR_MISSING_JAVA
, *pResMgr
).toString());
405 OUStringBuffer
aMessage(ResId(SV_ACCESSERROR_JAVA_MSG
, *pResMgr
).toString());
407 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
409 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
411 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
412 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
413 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
415 // Do not change the setting in case the user chooses to cancel
416 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
422 catch (const ::com::sun::star::java::JavaDisabledException
&)
424 ResMgr
*pResMgr
= ImplGetResMgr();
425 if( bErrorMessage
&& bAllowCancel
&& pResMgr
)
427 OUString
aTitle(ResId(SV_ACCESSERROR_JAVA_DISABLED
, *pResMgr
).toString());
428 OUStringBuffer
aMessage(ResId(SV_ACCESSERROR_JAVA_MSG
, *pResMgr
).toString());
430 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
432 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
434 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
435 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
436 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
438 // Do not change the setting in case the user chooses to cancel
439 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
445 catch (const ::com::sun::star::uno::RuntimeException
& e
)
447 ResMgr
*pResMgr
= ImplGetResMgr();
448 if( bErrorMessage
&& pResMgr
)
451 OUStringBuffer
aMessage(ResId(SV_ACCESSERROR_BRIDGE_MSG
, *pResMgr
).toString());
453 if( e
.Message
.startsWith("ClassNotFound") )
455 aTitle
= ResId(SV_ACCESSERROR_MISSING_BRIDGE
, *pResMgr
).toString();
457 else if( e
.Message
.startsWith("NoSuchMethod") )
459 aTitle
= ResId(SV_ACCESSERROR_WRONG_VERSION
, *pResMgr
).toString();
462 if (!aTitle
.isEmpty())
466 // Something went wrong initializing the Java AccessBridge (on Windows) during the
467 // startup. Since the office will be probably unusable for a disabled user, we offer
468 // to terminate directly.
469 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
471 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
473 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
474 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
475 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
477 // Do not change the setting in case the user chooses to cancel
478 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
479 rCancelled
= sal_True
;
483 // The user tried to activate accessibility support using Tools-Options dialog,
484 // so we don't offer to terminate here !
485 ImplGetSalSystem()->ShowNativeMessageBox(
487 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
488 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK
,
489 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
, true);
502 // -----------------------------------------------------------------------
504 Window
* ImplFindWindow( const SalFrame
* pFrame
, ::Point
& rSalFramePos
)
506 ImplSVData
* pSVData
= ImplGetSVData();
507 Window
* pFrameWindow
= pSVData
->maWinData
.mpFirstFrame
;
508 while ( pFrameWindow
)
510 if ( pFrameWindow
->ImplGetFrame() == pFrame
)
512 Window
* pWindow
= pFrameWindow
->ImplFindWindow( rSalFramePos
);
514 pWindow
= pFrameWindow
->ImplGetWindow();
515 rSalFramePos
= pWindow
->ImplFrameToOutput( rSalFramePos
);
518 pFrameWindow
= pFrameWindow
->ImplGetFrameData()->mpNextFrame
;
524 void LocaleConfigurationListener::ConfigurationChanged( utl::ConfigurationBroadcaster
*, sal_uInt32 nHint
)
526 AllSettings::LocaleSettingsChanged( nHint
);
529 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */