LCOV - code coverage report
Current view: top level - xmloff/source/style - chrlohdl.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 81 158 51.3 %
Date: 2014-11-03 Functions: 18 20 90.0 %
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             : #include <chrlohdl.hxx>
      21             : #include <xmloff/xmltoken.hxx>
      22             : #include <xmloff/xmluconv.hxx>
      23             : #include <unotools/saveopt.hxx>
      24             : #include <i18nlangtag/languagetag.hxx>
      25             : #include <rtl/ustrbuf.hxx>
      26             : #include <com/sun/star/uno/Any.hxx>
      27             : #include <com/sun/star/lang/Locale.hpp>
      28             : 
      29             : using namespace ::com::sun::star;
      30             : using namespace ::xmloff::token;
      31             : 
      32             : /* TODO-BCP47: this fiddling with Locale is quite ugly and fragile, especially
      33             :  * for the fo:script temporarily stored in Variant, it would be better to use
      34             :  * LanguageTagODF but we have that nasty UNO API requirement here.
      35             :  * => make LanguageTagODF (unpublished) API? */
      36             : 
      37             : // For runtime performance, instead of converting back and forth between
      38             : // com::sun::star::Locale and LanguageTag to decide if script or tag are
      39             : // needed, this code takes advantage of knowledge about the internal
      40             : // representation of BCP 47 language tags in a Locale if present as done in a
      41             : // LanguageTag.
      42             : 
      43       31872 : XMLCharLanguageHdl::~XMLCharLanguageHdl()
      44             : {
      45             :     // nothing to do
      46       31872 : }
      47             : 
      48          26 : bool XMLCharLanguageHdl::equals( const ::com::sun::star::uno::Any& r1, const ::com::sun::star::uno::Any& r2 ) const
      49             : {
      50          26 :     bool bRet = false;
      51          52 :     lang::Locale aLocale1, aLocale2;
      52             : 
      53          26 :     if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) )
      54             :     {
      55          26 :         bool bEmptyOrScriptVariant1 = (aLocale1.Variant.isEmpty() || aLocale1.Variant[0] == '-');
      56          26 :         bool bEmptyOrScriptVariant2 = (aLocale2.Variant.isEmpty() || aLocale2.Variant[0] == '-');
      57          26 :         if (bEmptyOrScriptVariant1 && bEmptyOrScriptVariant2)
      58          26 :             bRet = ( aLocale1.Language == aLocale2.Language );
      59             :         else
      60             :         {
      61           0 :             OUString aLanguage1, aLanguage2;
      62           0 :             if (bEmptyOrScriptVariant1)
      63           0 :                 aLanguage1 = aLocale1.Language;
      64             :             else
      65           0 :                 aLanguage1 = LanguageTag( aLocale1).getLanguage();
      66           0 :             if (bEmptyOrScriptVariant2)
      67           0 :                 aLanguage2 = aLocale2.Language;
      68             :             else
      69           0 :                 aLanguage2 = LanguageTag( aLocale2).getLanguage();
      70           0 :             bRet = ( aLanguage1 == aLanguage2 );
      71             :         }
      72             :     }
      73             : 
      74          52 :     return bRet;
      75             : }
      76             : 
      77        4114 : bool XMLCharLanguageHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
      78             : {
      79        4114 :     lang::Locale aLocale;
      80        4114 :     rValue >>= aLocale;
      81             : 
      82        4114 :     if( !IsXMLToken(rStrImpValue, XML_NONE) )
      83             :     {
      84        3978 :         if (aLocale.Variant.isEmpty())
      85        3978 :             aLocale.Language = rStrImpValue;
      86             :         else
      87             :         {
      88           0 :             if (!aLocale.Language.isEmpty() || aLocale.Variant[0] != '-')
      89             :             {
      90             :                 SAL_WARN_IF( aLocale.Language != I18NLANGTAG_QLT, "xmloff.style",
      91             :                         "XMLCharLanguageHdl::importXML - attempt to import language twice");
      92             :             }
      93             :             else
      94             :             {
      95           0 :                 aLocale.Variant = rStrImpValue + aLocale.Variant;
      96           0 :                 if (!aLocale.Country.isEmpty())
      97           0 :                     aLocale.Variant += "-" + aLocale.Country;
      98           0 :                 aLocale.Language = I18NLANGTAG_QLT;
      99             :             }
     100             :         }
     101             :     }
     102             : 
     103        4114 :     rValue <<= aLocale;
     104        4114 :     return true;
     105             : }
     106             : 
     107         674 : bool XMLCharLanguageHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
     108             : {
     109         674 :     lang::Locale aLocale;
     110         674 :     if(!(rValue >>= aLocale))
     111           0 :         return false;
     112             : 
     113         674 :     if (aLocale.Variant.isEmpty())
     114         674 :         rStrExpValue = aLocale.Language;
     115             :     else
     116             :     {
     117           0 :         LanguageTag aLanguageTag( aLocale);
     118           0 :         OUString aScript, aCountry;
     119           0 :         aLanguageTag.getIsoLanguageScriptCountry( rStrExpValue, aScript, aCountry);
     120             :         // Do not write *:language='none' for a non-ISO language with
     121             :         // *:rfc-language-tag that is written if Variant is not empty. If there
     122             :         // is no match do not write this attribute at all.
     123           0 :         if (rStrExpValue.isEmpty())
     124           0 :             return false;
     125             :     }
     126             : 
     127         674 :     if( rStrExpValue.isEmpty() )
     128           0 :         rStrExpValue = GetXMLToken( XML_NONE );
     129             : 
     130         674 :     return true;
     131             : }
     132             : 
     133       31872 : XMLCharScriptHdl::~XMLCharScriptHdl()
     134             : {
     135             :     // nothing to do
     136       31872 : }
     137             : 
     138          26 : bool XMLCharScriptHdl::equals( const ::com::sun::star::uno::Any& r1, const ::com::sun::star::uno::Any& r2 ) const
     139             : {
     140          26 :     bool bRet = false;
     141          52 :     lang::Locale aLocale1, aLocale2;
     142             : 
     143          26 :     if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) )
     144             :     {
     145          26 :         bool bEmptyVariant1 = aLocale1.Variant.isEmpty();
     146          26 :         bool bEmptyVariant2 = aLocale2.Variant.isEmpty();
     147          26 :         if (bEmptyVariant1 && bEmptyVariant2)
     148          26 :             bRet = true;
     149           0 :         else if ((bEmptyVariant1 && !bEmptyVariant2) || (!bEmptyVariant1 && bEmptyVariant2))
     150             :             ;   // stays false
     151             :         else
     152             :         {
     153           0 :             OUString aScript1, aScript2;
     154           0 :             if (aLocale1.Variant[0] == '-')
     155           0 :                 aScript1 = aLocale1.Variant.copy(1);
     156             :             else
     157           0 :                 aScript1 = LanguageTag( aLocale1).getScript();
     158           0 :             if (aLocale2.Variant[0] == '-')
     159           0 :                 aScript2 = aLocale2.Variant.copy(1);
     160             :             else
     161           0 :                 aScript2 = LanguageTag( aLocale2).getScript();
     162           0 :             bRet = ( aScript1 == aScript2 );
     163             :         }
     164             :     }
     165             : 
     166          52 :     return bRet;
     167             : }
     168             : 
     169           0 : bool XMLCharScriptHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
     170             : {
     171           0 :     lang::Locale aLocale;
     172           0 :     rValue >>= aLocale;
     173             : 
     174           0 :     if( !IsXMLToken( rStrImpValue, XML_NONE ) )
     175             :     {
     176             :         // Import the script only if we don't have a full BCP 47 language tag
     177             :         // in Variant yet.
     178           0 :         if (aLocale.Variant.isEmpty())
     179             :         {
     180           0 :             if (aLocale.Language.isEmpty())
     181             :             {
     182             :                 SAL_INFO( "xmloff.style", "XMLCharScriptHdl::importXML - script but no language yet");
     183             :                 // Temporarily store in Variant and hope the best (we will get
     184             :                 // a language later, yes?)
     185           0 :                 aLocale.Variant = "-" + rStrImpValue;
     186             :             }
     187             :             else
     188             :             {
     189           0 :                 aLocale.Variant = aLocale.Language + "-" + rStrImpValue;
     190           0 :                 if (!aLocale.Country.isEmpty())
     191           0 :                     aLocale.Variant += "-" + aLocale.Country;
     192           0 :                 aLocale.Language = I18NLANGTAG_QLT;
     193             :             }
     194             :         }
     195           0 :         else if (aLocale.Variant[0] == '-')
     196             :         {
     197             :             SAL_WARN( "xmloff.style", "XMLCharScriptHdl::importXML - attempt to insert script twice: "
     198             :                     << rStrImpValue << " -> " << aLocale.Variant);
     199             :         }
     200             :         else
     201             :         {
     202             :             // Assume that if there already is a script or anything else BCP 47
     203             :             // it was read by XMLCharRfcLanguageTagHdl() and takes precedence.
     204             :             // On the other hand, an *:rfc-language-tag without script and a
     205             :             // *:script ?!?
     206             : #if OSL_DEBUG_LEVEL > 0 || defined(DBG_UTIL)
     207             :             LanguageTag aLanguageTag( aLocale);
     208             :             if (!aLanguageTag.hasScript())
     209             :             {
     210             :                 SAL_WARN( "xmloff.style", "XMLCharScriptHdl::importXML - attempt to insert script over bcp47: "
     211             :                         << rStrImpValue << " -> " << aLanguageTag.getBcp47());
     212             :             }
     213             : #endif
     214             :         }
     215             :     }
     216             : 
     217           0 :     rValue <<= aLocale;
     218           0 :     return true;
     219             : }
     220             : 
     221         674 : bool XMLCharScriptHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
     222             : {
     223         674 :     lang::Locale aLocale;
     224         674 :     if(!(rValue >>= aLocale))
     225           0 :         return false;
     226             : 
     227             :     // Do not write script='none' for default script.
     228             : 
     229         674 :     if (aLocale.Variant.isEmpty())
     230         674 :         return false;
     231             : 
     232           0 :     LanguageTag aLanguageTag( aLocale);
     233           0 :     if (!aLanguageTag.hasScript())
     234           0 :         return false;
     235             : 
     236           0 :     if (SvtSaveOptions().GetODFDefaultVersion() < SvtSaveOptions::ODFVER_012)
     237           0 :         return false;
     238             : 
     239           0 :     OUString aLanguage, aCountry;
     240           0 :     aLanguageTag.getIsoLanguageScriptCountry( aLanguage, rStrExpValue, aCountry);
     241             :     // For non-ISO language it does not make sense to write *:script if
     242             :     // *:language is not written either, does it? It's all in
     243             :     // *:rfc-language-tag
     244           0 :     if (aLanguage.isEmpty() || rStrExpValue.isEmpty())
     245           0 :         return false;
     246             : 
     247         674 :     return true;
     248             : }
     249             : 
     250       31872 : XMLCharCountryHdl::~XMLCharCountryHdl()
     251             : {
     252             :     // nothing to do
     253       31872 : }
     254             : 
     255          26 : bool XMLCharCountryHdl::equals( const ::com::sun::star::uno::Any& r1, const ::com::sun::star::uno::Any& r2 ) const
     256             : {
     257          26 :     bool bRet = false;
     258          52 :     lang::Locale aLocale1, aLocale2;
     259             : 
     260          26 :     if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) )
     261          26 :         bRet = ( aLocale1.Country == aLocale2.Country );
     262             : 
     263          52 :     return bRet;
     264             : }
     265             : 
     266        4114 : bool XMLCharCountryHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
     267             : {
     268        4114 :     lang::Locale aLocale;
     269        4114 :     rValue >>= aLocale;
     270             : 
     271        4114 :     if( !IsXMLToken( rStrImpValue, XML_NONE ) )
     272             :     {
     273        3700 :         if (aLocale.Country.isEmpty())
     274             :         {
     275        3700 :             aLocale.Country = rStrImpValue;
     276        3700 :             if (aLocale.Variant.getLength() >= 7 && aLocale.Language == I18NLANGTAG_QLT)
     277             :             {
     278             :                 // already assembled language tag, at least ll-Ssss and not
     279             :                 // ll-CC or lll-CC
     280           0 :                 sal_Int32 i = aLocale.Variant.indexOf('-');     // separator to script
     281           0 :                 if (2 <= i && i < aLocale.Variant.getLength())
     282             :                 {
     283           0 :                     i = aLocale.Variant.indexOf( '-', i+1);
     284           0 :                     if (i < 0)                                  // no other separator
     285           0 :                         aLocale.Variant += "-" + rStrImpValue;  // append country
     286             :                 }
     287             :             }
     288             :         }
     289             :     }
     290             : 
     291        4114 :     rValue <<= aLocale;
     292        4114 :     return true;
     293             : }
     294             : 
     295         674 : bool XMLCharCountryHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
     296             : {
     297         674 :     lang::Locale aLocale;
     298         674 :     if(!(rValue >>= aLocale))
     299           0 :         return false;
     300             : 
     301         674 :     if (aLocale.Variant.isEmpty())
     302         674 :         rStrExpValue = aLocale.Country;
     303             :     else
     304             :     {
     305           0 :         LanguageTag aLanguageTag( aLocale);
     306           0 :         OUString aLanguage, aScript;
     307           0 :         aLanguageTag.getIsoLanguageScriptCountry( aLanguage, aScript, rStrExpValue);
     308             :         // Do not write *:country='none' for a non-ISO country with
     309             :         // *:rfc-language-tag that is written if Variant is not empty. If there
     310             :         // is no match do not write this attribute at all.
     311           0 :         if (rStrExpValue.isEmpty())
     312           0 :             return false;
     313             :     }
     314             : 
     315         674 :     if( rStrExpValue.isEmpty() )
     316          16 :         rStrExpValue = GetXMLToken( XML_NONE );
     317             : 
     318         674 :     return true;
     319             : }
     320             : 
     321       31872 : XMLCharRfcLanguageTagHdl::~XMLCharRfcLanguageTagHdl()
     322             : {
     323             :     // nothing to do
     324       31872 : }
     325             : 
     326          26 : bool XMLCharRfcLanguageTagHdl::equals( const ::com::sun::star::uno::Any& r1, const ::com::sun::star::uno::Any& r2 ) const
     327             : {
     328          26 :     bool bRet = false;
     329          52 :     lang::Locale aLocale1, aLocale2;
     330             : 
     331          26 :     if( ( r1 >>= aLocale1 ) && ( r2 >>= aLocale2 ) )
     332          26 :         bRet = ( aLocale1.Variant == aLocale2.Variant );
     333             : 
     334          52 :     return bRet;
     335             : }
     336             : 
     337           0 : bool XMLCharRfcLanguageTagHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
     338             : {
     339           0 :     lang::Locale aLocale;
     340           0 :     rValue >>= aLocale;
     341             : 
     342           0 :     if( !IsXMLToken( rStrImpValue, XML_NONE ) )
     343             :     {
     344           0 :         aLocale.Variant = rStrImpValue;
     345           0 :         aLocale.Language = I18NLANGTAG_QLT;
     346             :     }
     347             : 
     348           0 :     rValue <<= aLocale;
     349           0 :     return true;
     350             : }
     351             : 
     352         674 : bool XMLCharRfcLanguageTagHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
     353             : {
     354         674 :     lang::Locale aLocale;
     355         674 :     if(!(rValue >>= aLocale))
     356           0 :         return false;
     357             : 
     358             :     // Do not write rfc-language-tag='none' if BCP 47 is not needed.
     359         674 :     if (aLocale.Variant.isEmpty())
     360         674 :         return false;
     361             : 
     362           0 :     if (SvtSaveOptions().GetODFDefaultVersion() < SvtSaveOptions::ODFVER_012)
     363           0 :         return false;
     364             : 
     365           0 :     rStrExpValue = aLocale.Variant;
     366             : 
     367           0 :     return true;
     368             : }
     369             : 
     370             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10