xref: /aoo42x/main/vcl/source/app/svdata.cxx (revision 9f62ea84)
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