LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/desktop/source/app - langselect.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 140 221 63.3 %
Date: 2013-07-09 Functions: 14 17 82.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : 
      21             : #include "app.hxx"
      22             : #include "langselect.hxx"
      23             : #include "cmdlineargs.hxx"
      24             : #include <stdio.h>
      25             : 
      26             : #include <rtl/string.hxx>
      27             : #include <rtl/bootstrap.hxx>
      28             : #include <unotools/pathoptions.hxx>
      29             : #include <tools/resid.hxx>
      30             : #include <tools/config.hxx>
      31             : #include <i18nlangtag/mslangid.hxx>
      32             : #include <i18nlangtag/languagetag.hxx>
      33             : #include <comphelper/processfactory.hxx>
      34             : #include <com/sun/star/configuration/theDefaultProvider.hpp>
      35             : #include <com/sun/star/container/XNameAccess.hpp>
      36             : #include <com/sun/star/lang/XComponent.hpp>
      37             : #include <com/sun/star/beans/NamedValue.hpp>
      38             : #include <com/sun/star/util/XChangesBatch.hpp>
      39             : #include <com/sun/star/uno/Any.hxx>
      40             : #include <com/sun/star/lang/XLocalizable.hpp>
      41             : #include <com/sun/star/lang/Locale.hpp>
      42             : #include "com/sun/star/util/XFlushable.hpp"
      43             : #include <rtl/instance.hxx>
      44             : #include <osl/process.h>
      45             : #include <osl/file.hxx>
      46             : 
      47             : using namespace com::sun::star::uno;
      48             : using namespace com::sun::star::lang;
      49             : using namespace com::sun::star::container;
      50             : using namespace com::sun::star::beans;
      51             : using namespace com::sun::star::util;
      52             : 
      53             : 
      54             : namespace desktop {
      55             : 
      56             : static char const SOFFICE_BOOTSTRAP[] = "Bootstrap";
      57             : static char const SOFFICE_STARTLANG[] = "STARTLANG";
      58             : 
      59             : sal_Bool LanguageSelection::bFoundLanguage = sal_False;
      60          83 : OUString LanguageSelection::aFoundLanguage;
      61             : LanguageSelection::LanguageSelectionStatus LanguageSelection::m_eStatus = LS_STATUS_OK;
      62             : 
      63          83 : static sal_Bool existsURL( OUString const& sURL )
      64             : {
      65             :     using namespace osl;
      66          83 :     DirectoryItem aDirItem;
      67             : 
      68          83 :     if (!sURL.isEmpty())
      69          83 :         return ( DirectoryItem::get( sURL, aDirItem ) == DirectoryItem::E_None );
      70             : 
      71           0 :     return sal_False;
      72             : }
      73             : 
      74             : // locate soffice.ini/.rc file
      75          83 : static OUString locateSofficeIniFile()
      76             : {
      77          83 :     OUString aUserDataPath;
      78         166 :     OUString aSofficeIniFileURL;
      79             : 
      80             :     // Retrieve the default file URL for the soffice.ini/rc
      81          83 :     rtl::Bootstrap().getIniName( aSofficeIniFileURL );
      82             : 
      83          83 :     if ( utl::Bootstrap::locateUserData( aUserDataPath ) == utl::Bootstrap::PATH_EXISTS )
      84             :     {
      85          83 :         sal_Int32 nIndex = aSofficeIniFileURL.lastIndexOf( '/');
      86          83 :         if ( nIndex > 0 )
      87             :         {
      88          83 :             OUString aUserSofficeIniFileURL = aUserDataPath + "/config" + aSofficeIniFileURL.copy( nIndex );
      89             : 
      90          83 :             if ( existsURL( aUserSofficeIniFileURL ))
      91           0 :                 return aUserSofficeIniFileURL;
      92             :         }
      93             :     }
      94             :     // Fallback try to use the soffice.ini/rc from program folder
      95         166 :     return aSofficeIniFileURL;
      96             : }
      97             : 
      98          83 : bool LanguageSelection::prepareLanguage()
      99             : {
     100          83 :     m_eStatus = LS_STATUS_OK;
     101             :     Reference< XLocalizable > theConfigProvider(
     102             :         com::sun::star::configuration::theDefaultProvider::get(
     103             :             comphelper::getProcessComponentContext() ),
     104          83 :         UNO_QUERY_THROW );
     105             : 
     106          83 :     sal_Bool bSuccess = sal_False;
     107             : 
     108             :     // #i42730#get the windows 16Bit locale - it should be preferred over the UI language
     109             :     try
     110             :     {
     111          83 :         Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.System/L10N/", sal_False), UNO_QUERY_THROW);
     112         166 :         Any aWin16SysLocale = xProp->getPropertyValue("SystemLocale");
     113         166 :         OUString sWin16SysLocale;
     114          83 :         aWin16SysLocale >>= sWin16SysLocale;
     115          83 :         if( !sWin16SysLocale.isEmpty())
     116         166 :             setDefaultLanguage(sWin16SysLocale);
     117             :     }
     118           0 :     catch(const Exception&)
     119             :     {
     120           0 :         m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
     121             :     }
     122             : 
     123             :     // #i32939# use system locale to set document default locale
     124             :     try
     125             :     {
     126          83 :         OUString usLocale;
     127             :         Reference< XPropertySet > xLocaleProp(getConfigAccess(
     128         166 :             "org.openoffice.System/L10N", sal_True), UNO_QUERY_THROW);
     129          83 :         xLocaleProp->getPropertyValue("Locale") >>= usLocale;
     130         166 :             setDefaultLanguage(usLocale);
     131             :     }
     132           0 :     catch (const Exception&)
     133             :     {
     134           0 :         m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
     135             :     }
     136             : 
     137             :     // get the selected UI language as string
     138          83 :     bool     bCmdLanguage( false );
     139          83 :     bool     bIniLanguage( false );
     140         166 :     OUString aLocaleString = getUserUILanguage();
     141             : 
     142          83 :     if ( aLocaleString.isEmpty() )
     143             :     {
     144          83 :         OUString aEmpty;
     145             : 
     146          83 :         const CommandLineArgs& rCmdLineArgs = Desktop::GetCommandLineArgs();
     147          83 :         aLocaleString = rCmdLineArgs.GetLanguage();
     148          83 :         if (isInstalledLanguage(aLocaleString, sal_False))
     149             :         {
     150           0 :             bCmdLanguage   = true;
     151           0 :             bFoundLanguage = true;
     152           0 :             aFoundLanguage = aLocaleString;
     153             :         }
     154             :         else
     155          83 :             aLocaleString = aEmpty;
     156             : 
     157          83 :         if ( !bCmdLanguage )
     158             :         {
     159          83 :             OUString aSOfficeIniURL = locateSofficeIniFile();
     160         166 :             Config aConfig(aSOfficeIniURL);
     161          83 :             aConfig.SetGroup( SOFFICE_BOOTSTRAP );
     162         166 :             OString sLang = aConfig.ReadKey( SOFFICE_STARTLANG );
     163          83 :             aLocaleString = OUString( sLang.getStr(), sLang.getLength(), RTL_TEXTENCODING_ASCII_US );
     164          83 :             if (isInstalledLanguage(aLocaleString, sal_False))
     165             :             {
     166           0 :                 bIniLanguage   = true;
     167           0 :                 bFoundLanguage = true;
     168           0 :                 aFoundLanguage = aLocaleString;
     169             :             }
     170             :             else
     171         166 :                 aLocaleString = aEmpty;
     172          83 :         }
     173             :     }
     174             : 
     175             :     // user further fallbacks for the UI language
     176          83 :     if ( aLocaleString.isEmpty() )
     177          83 :         aLocaleString = getLanguageString();
     178             : 
     179          83 :     if ( !aLocaleString.isEmpty() )
     180             :     {
     181             :         try
     182             :         {
     183             :             // prepare default config provider by localizing it to the selected
     184             :             // locale this will ensure localized configuration settings to be
     185             :             // selected according to the UI language.
     186          83 :             LanguageTag aUILanguageTag(aLocaleString);
     187          83 :             theConfigProvider->setLocale(aUILanguageTag.getLocale( false));
     188             : 
     189         166 :             Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Setup/L10N/", sal_True), UNO_QUERY_THROW);
     190          83 :             if ( !bCmdLanguage )
     191             :             {
     192             :                 // Store language only
     193          83 :                 xProp->setPropertyValue("ooLocale", makeAny(aLocaleString));
     194          83 :                 Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges();
     195             :             }
     196             : 
     197          83 :             if ( bIniLanguage )
     198             :             {
     199             :                 // Store language only
     200           0 :                 Reference< XPropertySet > xProp2(getConfigAccess("org.openoffice.Office.Linguistic/General/", sal_True), UNO_QUERY_THROW);
     201           0 :                 xProp2->setPropertyValue("UILocale", makeAny(aLocaleString));
     202           0 :                 Reference< XChangesBatch >(xProp2, UNO_QUERY_THROW)->commitChanges();
     203             :             }
     204             : 
     205          83 :             MsLangId::setConfiguredSystemUILanguage( aUILanguageTag.getLanguageType( false) );
     206             : 
     207         166 :             OUString sLocale;
     208          83 :             xProp->getPropertyValue("ooSetupSystemLocale") >>= sLocale;
     209          83 :             if ( !sLocale.isEmpty() )
     210             :             {
     211           0 :                 LanguageTag aLocaleLanguageTag(sLocale);
     212           0 :                 MsLangId::setConfiguredSystemLanguage( aLocaleLanguageTag.getLanguageType( false) );
     213             :             }
     214             :             else
     215          83 :                 MsLangId::setConfiguredSystemLanguage( MsLangId::getSystemLanguage() );
     216             : 
     217         166 :             bSuccess = sal_True;
     218             :         }
     219           0 :         catch ( const PropertyVetoException& )
     220             :         {
     221             :             // we are not allowed to change this
     222             :         }
     223           0 :         catch (const Exception& e)
     224             :         {
     225           0 :             OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
     226           0 :             OSL_FAIL(aMsg.getStr());
     227             : 
     228             :         }
     229             :     }
     230             : 
     231             :     // #i32939# setting of default document locale
     232             :     // #i32939# this should not be based on the UI language
     233          83 :     setDefaultLanguage(aLocaleString);
     234             : 
     235         166 :     return bSuccess;
     236             : }
     237             : 
     238         249 : void LanguageSelection::setDefaultLanguage(const OUString& sLocale)
     239             : {
     240             :     // #i32939# setting of default document language
     241             :     // See #i42730# for rules for determining source of settings
     242             : 
     243             :     // determine script type of locale
     244         249 :     LanguageType nLang = LanguageTag(sLocale).getLanguageType();
     245         249 :     sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage(nLang);
     246             : 
     247         249 :     switch (nScriptType)
     248             :     {
     249             :         case SCRIPTTYPE_ASIAN:
     250           0 :             MsLangId::setConfiguredAsianFallback( nLang );
     251           0 :             break;
     252             :         case SCRIPTTYPE_COMPLEX:
     253           0 :             MsLangId::setConfiguredComplexFallback( nLang );
     254           0 :             break;
     255             :         default:
     256         249 :             MsLangId::setConfiguredWesternFallback( nLang );
     257         249 :             break;
     258             :     }
     259         249 : }
     260             : 
     261         166 : OUString LanguageSelection::getUserUILanguage()
     262             : {
     263             :     // check whether the user has selected a specific language
     264         166 :     OUString aUserLanguage = getUserLanguage();
     265         166 :     if (!aUserLanguage.isEmpty() )
     266             :     {
     267           0 :         if (isInstalledLanguage(aUserLanguage))
     268             :         {
     269             :             // all is well
     270           0 :             bFoundLanguage = sal_True;
     271           0 :             aFoundLanguage = aUserLanguage;
     272           0 :             return aFoundLanguage;
     273             :         }
     274             :         else
     275             :         {
     276             :             // selected language is not/no longer installed
     277           0 :             resetUserLanguage();
     278             :         }
     279             :     }
     280             : 
     281         166 :     return aUserLanguage;
     282             : }
     283             : 
     284         166 : OUString LanguageSelection::getLanguageString()
     285             : {
     286             :     // did we already find a language?
     287         166 :     if (bFoundLanguage)
     288          83 :         return aFoundLanguage;
     289             : 
     290             :     // check whether the user has selected a specific language
     291          83 :     OUString aUserLanguage = getUserUILanguage();
     292          83 :     if (!aUserLanguage.isEmpty() )
     293           0 :         return aUserLanguage ;
     294             : 
     295             :     // try to use system default
     296          83 :     aUserLanguage = getSystemLanguage();
     297          83 :     if (!aUserLanguage.isEmpty() )
     298             :     {
     299          83 :         if (isInstalledLanguage(aUserLanguage, sal_False))
     300             :         {
     301             :             // great, system default language is available
     302          83 :             bFoundLanguage = sal_True;
     303          83 :             aFoundLanguage = aUserLanguage;
     304          83 :             return aFoundLanguage;
     305             :         }
     306             :     }
     307             :     // fallback 1: en-US
     308           0 :     OUString usFB("en-US");
     309           0 :     if (isInstalledLanguage(usFB))
     310             :     {
     311           0 :         bFoundLanguage = sal_True;
     312           0 :         aFoundLanguage = "en-US";
     313           0 :         return aFoundLanguage;
     314             :     }
     315             : 
     316             :     // fallback didn't work use first installed language
     317           0 :     aUserLanguage = getFirstInstalledLanguage();
     318             : 
     319           0 :     bFoundLanguage = sal_True;
     320           0 :     aFoundLanguage = aUserLanguage;
     321          83 :     return aFoundLanguage;
     322             : }
     323             : 
     324         747 : Reference< XNameAccess > LanguageSelection::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate)
     325             : {
     326         747 :     Reference< XNameAccess > xNameAccess;
     327             :     try{
     328         747 :         OUString sAccessSrvc;
     329         747 :         if (bUpdate)
     330         166 :             sAccessSrvc = "com.sun.star.configuration.ConfigurationUpdateAccess";
     331             :         else
     332         581 :             sAccessSrvc = "com.sun.star.configuration.ConfigurationAccess";
     333             : 
     334        1494 :         OUString sConfigURL = OUString::createFromAscii(pPath);
     335             : 
     336             :         Reference< XMultiServiceFactory > theConfigProvider(
     337             :             com::sun::star::configuration::theDefaultProvider::get(
     338        1494 :                 comphelper::getProcessComponentContext() ) );
     339             : 
     340             :         // access the provider
     341        1494 :         Sequence< Any > theArgs(1);
     342         747 :         theArgs[ 0 ] <<= sConfigURL;
     343        1494 :         xNameAccess = Reference< XNameAccess > (
     344         747 :             theConfigProvider->createInstanceWithArguments(
     345        2241 :                 sAccessSrvc, theArgs ), UNO_QUERY_THROW );
     346           0 :     } catch (const com::sun::star::uno::Exception& e)
     347             :     {
     348           0 :         OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
     349           0 :         OSL_FAIL(aMsg.getStr());
     350             :     }
     351         747 :     return xNameAccess;
     352             : }
     353             : 
     354         249 : Sequence< OUString > LanguageSelection::getInstalledLanguages()
     355             : {
     356         249 :     Sequence< OUString > seqLanguages;
     357         498 :     Reference< XNameAccess > xAccess = getConfigAccess("org.openoffice.Setup/Office/InstalledLocales", sal_False);
     358         249 :     if (!xAccess.is()) return seqLanguages;
     359         249 :     seqLanguages = xAccess->getElementNames();
     360         249 :     return seqLanguages;
     361             : }
     362             : 
     363             : // FIXME
     364             : // it's not very clever to handle language fallbacks here, but
     365             : // right now, there is no place that handles those fallbacks globally
     366         166 : static Sequence< OUString > _getFallbackLocales(const OUString& aIsoLang)
     367             : {
     368         166 :     Sequence< OUString > seqFallbacks;
     369         166 :     if ( aIsoLang == "zh-HK" ) {
     370           0 :         seqFallbacks = Sequence< OUString >(1);
     371           0 :         seqFallbacks[0] = "zh-TW";
     372             :     }
     373         166 :     return seqFallbacks;
     374             : }
     375             : 
     376         249 : sal_Bool LanguageSelection::isInstalledLanguage(OUString& usLocale, sal_Bool bExact)
     377             : {
     378         249 :     sal_Bool bInstalled = sal_False;
     379         249 :     Sequence< OUString > seqLanguages = getInstalledLanguages();
     380         415 :     for (sal_Int32 i=0; i<seqLanguages.getLength(); i++)
     381             :     {
     382         249 :         if (usLocale.equals(seqLanguages[i]))
     383             :         {
     384          83 :             bInstalled = sal_True;
     385          83 :             break;
     386             :         }
     387             :     }
     388             : 
     389         249 :     if (!bInstalled && !bExact)
     390             :     {
     391             :         // try fallback locales
     392         166 :         Sequence< OUString > seqFallbacks = _getFallbackLocales(usLocale);
     393         166 :         for (sal_Int32 j=0; j<seqFallbacks.getLength(); j++)
     394             :         {
     395           0 :             for (sal_Int32 i=0; i<seqLanguages.getLength(); i++)
     396             :             {
     397           0 :                 if (seqFallbacks[j].equals(seqLanguages[i]))
     398             :                 {
     399           0 :                     bInstalled = sal_True;
     400           0 :                     usLocale = seqFallbacks[j];
     401           0 :                     break;
     402             :                 }
     403             :             }
     404         166 :         }
     405             :     }
     406             : 
     407         249 :     if (!bInstalled && !bExact)
     408             :     {
     409             :         // no exact match was found, well try to find a substitute
     410         332 :         for (sal_Int32 i=0; i<seqLanguages.getLength(); i++)
     411             :         {
     412         166 :             if (usLocale.indexOf(seqLanguages[i]) == 0)
     413             :             {
     414             :                 // requested locale starts with the installed locale
     415             :                 // (i.e. installed locale has index 0 in requested locale)
     416           0 :                 bInstalled = sal_True;
     417           0 :                 usLocale   = seqLanguages[i];
     418           0 :                 break;
     419             :             }
     420             :         }
     421             :     }
     422         249 :     return bInstalled;
     423             : }
     424             : 
     425           0 : OUString LanguageSelection::getFirstInstalledLanguage()
     426             : {
     427           0 :     OUString aLanguage;
     428           0 :     Sequence< OUString > seqLanguages = getInstalledLanguages();
     429           0 :     if (seqLanguages.getLength() > 0)
     430           0 :         aLanguage = seqLanguages[0];
     431           0 :     return aLanguage;
     432             : }
     433             : 
     434         166 : OUString LanguageSelection::getUserLanguage()
     435             : {
     436         166 :     OUString aUserLanguage;
     437         332 :     Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_False));
     438         166 :     if (xAccess.is())
     439             :     {
     440             :         try
     441             :         {
     442         166 :             xAccess->getByName("UILocale") >>= aUserLanguage;
     443             :         }
     444           0 :         catch ( NoSuchElementException const & )
     445             :         {
     446           0 :             m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
     447           0 :             return OUString();
     448             :         }
     449           0 :         catch ( WrappedTargetException const & )
     450             :         {
     451           0 :             m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
     452           0 :             return OUString();
     453             :         }
     454             :     }
     455         332 :     return aUserLanguage;
     456             : }
     457             : 
     458          83 : OUString LanguageSelection::getSystemLanguage()
     459             : {
     460          83 :     OUString aUserLanguage;
     461         166 :     Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.System/L10N", sal_False));
     462          83 :     if (xAccess.is())
     463             :     {
     464             :         try
     465             :         {
     466          83 :             xAccess->getByName("UILocale") >>= aUserLanguage;
     467             :         }
     468           0 :         catch ( NoSuchElementException const & )
     469             :         {
     470           0 :             m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
     471           0 :             return OUString();
     472             :         }
     473           0 :         catch ( WrappedTargetException const & )
     474             :         {
     475           0 :             m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
     476           0 :             return OUString();
     477             :         }
     478             :     }
     479         166 :     return aUserLanguage;
     480             : }
     481             : 
     482             : 
     483           0 : void LanguageSelection::resetUserLanguage()
     484             : {
     485             :     try
     486             :     {
     487           0 :         Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_True), UNO_QUERY_THROW);
     488           0 :         xProp->setPropertyValue("UILocale", makeAny(OUString()));
     489           0 :         Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges();
     490             :     }
     491           0 :     catch ( const PropertyVetoException& )
     492             :     {
     493             :         // we are not allowed to change this
     494             :     }
     495           0 :     catch (const Exception& e)
     496             :     {
     497           0 :         OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
     498             :         OSL_FAIL(aMsg.getStr());
     499           0 :         m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN;
     500             :     }
     501           0 : }
     502             : 
     503           0 : LanguageSelection::LanguageSelectionStatus LanguageSelection::getStatus()
     504             : {
     505           0 :     return m_eStatus;
     506             : }
     507             : 
     508         249 : } // namespace desktop
     509             : 
     510             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10