LCOV - code coverage report
Current view: top level - libreoffice/tools/source/rc - resmgr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 420 775 54.2 %
Date: 2012-12-27 Functions: 47 69 68.1 %
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 <string.h>
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : 
      24             : #include <tools/debug.hxx>
      25             : #include <tools/stream.hxx>
      26             : #include <tools/resmgr.hxx>
      27             : #include <tools/rc.hxx>
      28             : #include <tools/rcid.h>
      29             : #include <osl/endian.h>
      30             : #include <osl/process.h>
      31             : #include <osl/thread.h>
      32             : #include <osl/file.hxx>
      33             : #include <osl/mutex.hxx>
      34             : #include <osl/signal.h>
      35             : #include <rtl/ustrbuf.hxx>
      36             : #include <rtl/strbuf.hxx>
      37             : #include <sal/log.hxx>
      38             : #include <rtl/instance.hxx>
      39             : #include <rtl/bootstrap.hxx>
      40             : #include <i18npool/languagetag.hxx>
      41             : #include <i18npool/mslangid.hxx>
      42             : #include <tools/simplerm.hxx>
      43             : 
      44             : #include <functional>
      45             : #include <algorithm>
      46             : #include <boost/unordered_map.hpp>
      47             : #include <list>
      48             : #include <set>
      49             : 
      50             : using ::rtl::OUString;
      51             : using ::rtl::OString;
      52             : using ::rtl::OUStringBuffer;
      53             : using ::rtl::OUStringHash;
      54             : 
      55             : using namespace osl;
      56             : 
      57             : // for thread safety
      58             : static osl::Mutex* pResMgrMutex = NULL;
      59             : 
      60      634714 : static osl::Mutex& getResMgrMutex()
      61             : {
      62      634714 :     if( !pResMgrMutex )
      63             :     {
      64          32 :         osl::Guard<osl::Mutex> aGuard( *osl::Mutex::getGlobalMutex() );
      65          32 :         if( ! pResMgrMutex )
      66          32 :             pResMgrMutex = new osl::Mutex();
      67             :     }
      68      634714 :     return *pResMgrMutex;
      69             : }
      70             : 
      71             : struct ImpContent;
      72             : 
      73             : class InternalResMgr
      74             : {
      75             :     friend class ResMgr;
      76             :     friend class SimpleResMgr;
      77             :     friend class ResMgrContainer;
      78             : 
      79             :     ImpContent *                    pContent;
      80             :     sal_uInt32                      nOffCorrection;
      81             :     sal_uInt8 *                     pStringBlock;
      82             :     SvStream *                      pStm;
      83             :     sal_Bool                        bEqual2Content;
      84             :     sal_uInt32                      nEntries;
      85             :     OUString                        aFileName;
      86             :     OUString                        aPrefix;
      87             :     OUString                        aResName;
      88             :     bool                            bSingular;
      89             :     com::sun::star::lang::Locale    aLocale;
      90             :     boost::unordered_map<sal_uInt64, int>* pResUseDump;
      91             : 
      92             :                             InternalResMgr( const OUString& rFileURL,
      93             :                                             const OUString& aPrefix,
      94             :                                             const OUString& aResName,
      95             :                                             const com::sun::star::lang::Locale& rLocale );
      96             :                             ~InternalResMgr();
      97             :     sal_Bool                Create();
      98             : 
      99             :     sal_Bool                IsGlobalAvailable( RESOURCE_TYPE nRT, sal_uInt32 nId ) const;
     100             :     void *                  LoadGlobalRes( RESOURCE_TYPE nRT, sal_uInt32 nId,
     101             :                                            void **pResHandle );
     102             : public:
     103             :     static void             FreeGlobalRes( void *, void * );
     104             : };
     105             : 
     106             : class ResMgrContainer
     107             : {
     108             :     static ResMgrContainer*     pOneInstance;
     109             : 
     110           0 :     struct ContainerElement
     111             :     {
     112             :         InternalResMgr* pResMgr;
     113             :         OUString        aFileURL;
     114             :         int             nRefCount;
     115             :         int             nLoadCount;
     116             : 
     117        1952 :         ContainerElement() :
     118             :             pResMgr( NULL ),
     119             :             nRefCount( 0 ),
     120        1952 :             nLoadCount( 0 )
     121        1952 :             {}
     122             :     };
     123             : 
     124             :     boost::unordered_map< OUString, ContainerElement, OUStringHash> m_aResFiles;
     125             :     com::sun::star::lang::Locale                             m_aDefLocale;
     126             : 
     127          32 :     ResMgrContainer() { init(); }
     128             :     ~ResMgrContainer();
     129             : 
     130             :     void init();
     131             : 
     132             : public:
     133             :     static ResMgrContainer& get();
     134             :     static void release();
     135             : 
     136             :     InternalResMgr* getResMgr( const OUString& rPrefix,
     137             :                                com::sun::star::lang::Locale& rLocale,
     138             :                                bool bForceNewInstance = false
     139             :                                );
     140             :     InternalResMgr* getNextFallback( InternalResMgr* pResMgr );
     141             : 
     142             :     void freeResMgr( InternalResMgr* pResMgr );
     143             : 
     144         208 :     void setDefLocale( const com::sun::star::lang::Locale& rLocale )
     145         208 :     { m_aDefLocale = rLocale; }
     146          99 :     const com::sun::star::lang::Locale& getDefLocale() const
     147          99 :     { return m_aDefLocale; }
     148             : };
     149             : 
     150             : ResMgrContainer* ResMgrContainer::pOneInstance = NULL;
     151             : 
     152        1076 : ResMgrContainer& ResMgrContainer::get()
     153             : {
     154        1076 :     if( ! pOneInstance )
     155          32 :         pOneInstance = new ResMgrContainer();
     156        1076 :     return *pOneInstance;
     157             : }
     158             : 
     159           0 : ResMgrContainer::~ResMgrContainer()
     160             : {
     161           0 :     for( boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it =
     162           0 :             m_aResFiles.begin(); it != m_aResFiles.end(); ++it )
     163             :     {
     164             :         OSL_TRACE( "Resource file %s loaded %d times",
     165             :                          OUStringToOString( it->second.aFileURL, osl_getThreadTextEncoding() ).getStr(),
     166             :                          it->second.nLoadCount );
     167           0 :         delete it->second.pResMgr;
     168             :     }
     169           0 : }
     170             : 
     171           0 : void ResMgrContainer::release()
     172             : {
     173           0 :     delete pOneInstance;
     174           0 :     pOneInstance = NULL;
     175           0 : }
     176             : 
     177          32 : void ResMgrContainer::init()
     178             : {
     179             :     // get resource path
     180          32 :     std::list< OUString > aDirs;
     181          32 :     sal_Int32 nIndex = 0;
     182             : 
     183             :     // 1. fixed locations
     184             :     rtl::OUString uri(
     185          32 :         RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program/resource"));
     186          32 :     rtl::Bootstrap::expandMacros(uri);
     187          32 :     aDirs.push_back(uri);
     188             : 
     189             :     // 2. in STAR_RESOURCEPATH
     190          32 :     const sal_Char* pEnv = getenv( "STAR_RESOURCEPATH" );
     191          32 :     if( pEnv )
     192             :     {
     193          32 :         OUString aEnvPath( OStringToOUString( OString( pEnv ), osl_getThreadTextEncoding() ) );
     194          32 :         nIndex = 0;
     195          96 :         while( nIndex >= 0 )
     196             :         {
     197          32 :             OUString aPathElement( aEnvPath.getToken( 0, SAL_PATHSEPARATOR, nIndex ) );
     198          32 :             if( !aPathElement.isEmpty() )
     199             :             {
     200          32 :                 OUString aFileURL;
     201          32 :                 File::getFileURLFromSystemPath( aPathElement, aFileURL );
     202          32 :                 aDirs.push_back( aFileURL);
     203             :             }
     204          64 :         }
     205             :     }
     206             : 
     207             :     // collect all possible resource files
     208          96 :     for( std::list< OUString >::const_iterator dir_it = aDirs.begin(); dir_it != aDirs.end(); ++dir_it )
     209             :     {
     210          64 :         Directory aDir( *dir_it );
     211          64 :         if( aDir.open() == FileBase::E_None )
     212             :         {
     213          32 :             DirectoryItem aItem;
     214       10430 :             while( aDir.getNextItem( aItem ) == FileBase::E_None )
     215             :             {
     216       10366 :                 FileStatus aStatus(osl_FileStatus_Mask_FileName);
     217       10366 :                 if( aItem.getFileStatus( aStatus ) == FileBase::E_None )
     218             :                 {
     219       10366 :                     OUString aFileName = aStatus.getFileName();
     220       10366 :                     if( aFileName.getLength() < 5 )
     221         416 :                         continue;
     222        9950 :                     if( ! aFileName.endsWithIgnoreAsciiCaseAsciiL( ".res", 4 ) )
     223        7998 :                         continue;
     224        1952 :                     OUString aResName = aFileName.copy( 0, aFileName.getLength()-4 );
     225        1952 :                     if( m_aResFiles.find( aResName ) != m_aResFiles.end() )
     226           0 :                         continue;
     227        1952 :                     OUStringBuffer aURL( dir_it->getLength() + aFileName.getLength() + 1 );
     228        1952 :                     aURL.append( *dir_it );
     229        1952 :                     if( !dir_it->endsWithIgnoreAsciiCaseAsciiL( "/", 1 ) )
     230           0 :                         aURL.append( sal_Unicode('/') );
     231        1952 :                     aURL.append( aFileName );
     232        1952 :                     m_aResFiles[ aResName ].aFileURL = aURL.makeStringAndClear();
     233             :                 }
     234       10398 :             }
     235             :         }
     236             :         #if OSL_DEBUG_LEVEL > 1
     237             :         else
     238             :             OSL_TRACE( "opening dir %s failed", OUStringToOString( *dir_it, osl_getThreadTextEncoding() ).getStr() );
     239             :         #endif
     240          64 :     }
     241             :     #if OSL_DEBUG_LEVEL > 1
     242             :     for( boost::unordered_map< OUString, ContainerElement, OUStringHash >::const_iterator it =
     243             :             m_aResFiles.begin(); it != m_aResFiles.end(); ++it )
     244             :     {
     245             :         OSL_TRACE( "ResMgrContainer: %s -> %s",
     246             :                  OUStringToOString( it->first, osl_getThreadTextEncoding() ).getStr(),
     247             :                  OUStringToOString( it->second.aFileURL, osl_getThreadTextEncoding() ).getStr() );
     248             :     }
     249             :     #endif
     250             : 
     251             :     // set default language
     252          32 :     LanguageType nLang = MsLangId::getSystemUILanguage();
     253          32 :     m_aDefLocale = LanguageTag( nLang).getLocale();
     254          32 : }
     255             : 
     256             : namespace
     257             : {
     258           0 :     bool isAlreadyPureenUS(const com::sun::star::lang::Locale &rLocale)
     259             :     {
     260           0 :         return ( rLocale.Language == "en" && rLocale.Country == "US" && rLocale.Variant.isEmpty() );
     261             :     }
     262             : }
     263             : 
     264         376 : InternalResMgr* ResMgrContainer::getResMgr( const OUString& rPrefix,
     265             :                                             com::sun::star::lang::Locale& rLocale,
     266             :                                             bool bForceNewInstance
     267             :                                             )
     268             : {
     269         376 :     com::sun::star::lang::Locale aLocale( rLocale );
     270         376 :     OUStringBuffer aSearch( rPrefix.getLength() + 16 );
     271         376 :     boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it = m_aResFiles.end();
     272             : 
     273             :     /* FIXME-BCP47: handle language tags! */
     274         376 :     int nTries = 0;
     275         376 :     if( !aLocale.Language.isEmpty() )
     276         376 :         nTries = 1;
     277         376 :     if( !aLocale.Country.isEmpty() )
     278         376 :         nTries = 2;
     279         376 :     if( !aLocale.Variant.isEmpty() )
     280           0 :         nTries = 3;
     281         752 :     while( nTries-- )
     282             :     {
     283         376 :         aSearch.append( rPrefix );
     284         376 :         if( nTries > -1 )
     285             :         {
     286         376 :             aSearch.append( aLocale.Language );
     287             :         }
     288         376 :         if( nTries > 0 )
     289             :         {
     290         376 :             aSearch.append( sal_Unicode('-') );
     291         376 :             aSearch.append( aLocale.Country );
     292             :         }
     293         376 :         if( nTries > 1 )
     294             :         {
     295           0 :             aSearch.append( sal_Unicode('-') );
     296           0 :             aSearch.append( aLocale.Variant );
     297             :         }
     298         376 :         it = m_aResFiles.find( aSearch.makeStringAndClear() );
     299         376 :         if( it != m_aResFiles.end() )
     300             :         {
     301             :             // ensure InternalResMgr existance
     302         376 :             if( ! it->second.pResMgr )
     303             :             {
     304             :                 InternalResMgr* pImp =
     305         250 :                     new InternalResMgr( it->second.aFileURL, rPrefix, it->first, aLocale );
     306         250 :                 if( ! pImp->Create() )
     307             :                 {
     308           0 :                     delete pImp;
     309           0 :                     continue;
     310             :                 }
     311         250 :                 it->second.pResMgr = pImp;
     312             :             }
     313         376 :             break;
     314             :         }
     315           0 :         if( nTries == 0 && !isAlreadyPureenUS(aLocale) )
     316             :         {
     317             :             // locale fallback failed
     318             :             // fallback to en-US locale
     319           0 :             nTries = 2;
     320           0 :             aLocale.Language = OUString( RTL_CONSTASCII_USTRINGPARAM( "en" ) );
     321           0 :             aLocale.Country  = OUString( RTL_CONSTASCII_USTRINGPARAM( "US" ) );
     322           0 :             aLocale.Variant = OUString();
     323             :         }
     324             :     }
     325             :     // try if there is anything with this prefix at all
     326         376 :     if( it == m_aResFiles.end() )
     327             :     {
     328           0 :         aLocale = com::sun::star::lang::Locale();
     329           0 :         it = m_aResFiles.find( rPrefix );
     330           0 :         if( it == m_aResFiles.end() )
     331             :         {
     332           0 :             for( it = m_aResFiles.begin(); it != m_aResFiles.end(); ++it )
     333             :             {
     334           0 :                 if( it->first.matchIgnoreAsciiCase( rPrefix ) )
     335             :                 {
     336             :                     // ensure InternalResMgr existance
     337           0 :                     if( ! it->second.pResMgr )
     338             :                     {
     339             :                         InternalResMgr* pImp =
     340           0 :                             new InternalResMgr( it->second.aFileURL,
     341             :                                                 rPrefix,
     342           0 :                                                 it->first,
     343           0 :                                                 aLocale );
     344           0 :                         if( ! pImp->Create() )
     345             :                         {
     346           0 :                             delete pImp;
     347           0 :                             continue;
     348             :                         }
     349           0 :                         it->second.pResMgr = pImp;
     350             :                     }
     351             :                     // try to guess locale
     352           0 :                     sal_Int32 nIndex = rPrefix.getLength();
     353           0 :                     aLocale.Language = it->first.getToken( 0, '-', nIndex );
     354           0 :                     if( nIndex > 0 )
     355           0 :                         aLocale.Country = it->first.getToken( 0, '-', nIndex );
     356           0 :                     if( nIndex > 0 )
     357           0 :                         aLocale.Variant = it->first.getToken( 0, '-', nIndex );
     358             :                     break;
     359             :                 }
     360             :             }
     361             :         }
     362             :     }
     363             :     // give up
     364         376 :     if( it == m_aResFiles.end() )
     365             :     {
     366             :         /* FIXME-BCP47: handle language tags! */
     367           0 :         OUStringBuffer sKey = rPrefix;
     368           0 :         sKey.append( rLocale.Language );
     369           0 :         if( !rLocale.Country.isEmpty() )
     370             :         {
     371           0 :             sKey.append( sal_Unicode('-') );
     372           0 :             sKey.append( rLocale.Country );
     373             :         }
     374           0 :         if( !rLocale.Variant.isEmpty() )
     375             :         {
     376           0 :             sKey.append( sal_Unicode('-') );
     377           0 :             sKey.append( rLocale.Variant );
     378             :         } // if( !aLocale.Variant.isEmpty() )
     379           0 :         ::rtl::OUString sURL = sKey.makeStringAndClear();
     380           0 :         sURL += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".res"));
     381           0 :         if ( m_aResFiles.find(sURL) == m_aResFiles.end() )
     382             :         {
     383           0 :             m_aResFiles[ sURL ].aFileURL = sURL;
     384           0 :             return getResMgr(rPrefix,rLocale,bForceNewInstance);
     385             :         } // if ( m_aResFiles.find(sURL) == m_aResFiles.end() )
     386           0 :         return NULL;
     387             :     }
     388             : 
     389         376 :     rLocale = aLocale;
     390             :     // at this point it->second.pResMgr must be filled either by creating a new one
     391             :     // (then the refcount is still 0) or because we already had one
     392         376 :     InternalResMgr* pImp = it->second.pResMgr;
     393             : 
     394         376 :     if( it->second.nRefCount == 0 )
     395         250 :         it->second.nLoadCount++;
     396             : 
     397             :     // for SimpleResMgr
     398         376 :     if( bForceNewInstance )
     399             :     {
     400           0 :         if( it->second.nRefCount == 0 )
     401             :         {
     402             :             // shortcut: the match algorithm already created the InternalResMgr
     403             :             // take it instead of creating yet another one
     404           0 :             it->second.pResMgr = NULL;
     405           0 :             pImp->bSingular = true;
     406             :         }
     407             :         else
     408             :         {
     409           0 :             pImp = new InternalResMgr( it->second.aFileURL, rPrefix, it->first, aLocale );
     410           0 :             pImp->bSingular = true;
     411           0 :             if( !pImp->Create() )
     412             :             {
     413           0 :                 delete pImp;
     414           0 :                 pImp = NULL;
     415             :             }
     416             :             else
     417           0 :                 it->second.nLoadCount++;
     418             :         }
     419             :     }
     420             :     else
     421         376 :         it->second.nRefCount++;
     422             : 
     423         376 :     return pImp;
     424             : }
     425             : 
     426           0 : InternalResMgr* ResMgrContainer::getNextFallback( InternalResMgr* pMgr )
     427             : {
     428             :     /* FIXME-BCP47: handle language tags! */
     429           0 :     com::sun::star::lang::Locale aLocale = pMgr->aLocale;
     430           0 :     if( !aLocale.Variant.isEmpty() )
     431           0 :         aLocale.Variant = OUString();
     432           0 :     else if( !aLocale.Country.isEmpty() )
     433           0 :         aLocale.Country = OUString();
     434           0 :     else if( !isAlreadyPureenUS(aLocale) )
     435             :     {
     436           0 :         aLocale.Language = OUString( RTL_CONSTASCII_USTRINGPARAM( "en" ) );
     437           0 :         aLocale.Country = OUString( RTL_CONSTASCII_USTRINGPARAM( "US" ) );
     438             :     }
     439           0 :     InternalResMgr* pNext = getResMgr( pMgr->aPrefix, aLocale, pMgr->bSingular );
     440             :     // prevent recursion
     441           0 :     if( pNext == pMgr || ( pNext && pNext->aResName.equals( pMgr->aResName ) ) )
     442             :     {
     443           0 :         if( pNext->bSingular )
     444           0 :             delete pNext;
     445           0 :         pNext = NULL;
     446             :     }
     447           0 :     return pNext;
     448             : }
     449             : 
     450         143 : void ResMgrContainer::freeResMgr( InternalResMgr* pResMgr )
     451             : {
     452         143 :     if( pResMgr->bSingular )
     453           0 :         delete pResMgr;
     454             :     else
     455             :     {
     456             :         boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it =
     457         143 :         m_aResFiles.find( pResMgr->aResName );
     458         143 :         if( it != m_aResFiles.end() )
     459             :         {
     460             :             DBG_ASSERT( it->second.nRefCount > 0, "InternalResMgr freed too often" );
     461         143 :             if( it->second.nRefCount > 0 )
     462         143 :                 it->second.nRefCount--;
     463         143 :             if( it->second.nRefCount == 0 )
     464             :             {
     465          81 :                 delete it->second.pResMgr;
     466          81 :                 it->second.pResMgr = NULL;
     467             :             }
     468             :         }
     469             :     }
     470         143 : }
     471             : 
     472           0 : void Resource::TestRes()
     473             : {
     474           0 :     if( m_pResMgr )
     475           0 :         m_pResMgr->TestStack( this );
     476           0 : }
     477             : 
     478             : struct ImpContent
     479             : {
     480             :     sal_uInt64   nTypeAndId;
     481             :     sal_uInt32   nOffset;
     482             : };
     483             : 
     484             : struct ImpContentLessCompare : public ::std::binary_function< ImpContent, ImpContent, bool>
     485             : {
     486      956795 :     inline bool operator() (const ImpContent& lhs, const ImpContent& rhs) const
     487             :     {
     488      956795 :         return lhs.nTypeAndId < rhs.nTypeAndId;
     489             :     }
     490             : };
     491             : 
     492             : static ResHookProc pImplResHookProc = 0;
     493             : 
     494         250 : InternalResMgr::InternalResMgr( const OUString& rFileURL,
     495             :                                 const OUString& rPrefix,
     496             :                                 const OUString& rResName,
     497             :                                 const com::sun::star::lang::Locale& rLocale )
     498             :     : pContent( NULL )
     499             :     , pStringBlock( NULL )
     500             :     , pStm( NULL )
     501             :     , bEqual2Content( sal_True )
     502             :     , nEntries( 0 )
     503             :     , aFileName( rFileURL )
     504             :     , aPrefix( rPrefix )
     505             :     , aResName( rResName )
     506             :     , bSingular( false )
     507             :     , aLocale( rLocale )
     508         250 :     , pResUseDump( 0 )
     509             : {
     510         250 : }
     511             : 
     512         162 : InternalResMgr::~InternalResMgr()
     513             : {
     514          81 :     rtl_freeMemory(pContent);
     515          81 :     rtl_freeMemory(pStringBlock);
     516          81 :     delete pStm;
     517             : 
     518             : #ifdef DBG_UTIL
     519             :     if( pResUseDump )
     520             :     {
     521             :         const sal_Char* pLogFile = getenv( "STAR_RESOURCE_LOGGING" );
     522             :         if ( pLogFile )
     523             :         {
     524             :             SvFileStream aStm( UniString( pLogFile, RTL_TEXTENCODING_ASCII_US ), STREAM_WRITE );
     525             :             aStm.Seek( STREAM_SEEK_TO_END );
     526             :             rtl::OStringBuffer aLine(RTL_CONSTASCII_STRINGPARAM("FileName: "));
     527             :             aLine.append(rtl::OUStringToOString(aFileName,
     528             :                 RTL_TEXTENCODING_UTF8));
     529             :             aStm.WriteLine(aLine.makeStringAndClear());
     530             : 
     531             :             for( boost::unordered_map<sal_uInt64, int>::const_iterator it = pResUseDump->begin();
     532             :                  it != pResUseDump->end(); ++it )
     533             :             {
     534             :                 sal_uInt64 nKeyId = it->first;
     535             :                 aLine.append(RTL_CONSTASCII_STRINGPARAM("Type/Id: "));
     536             :                 aLine.append(sal::static_int_cast< sal_Int32 >((nKeyId >> 32) & 0xFFFFFFFF));
     537             :                 aLine.append('/');
     538             :                 aLine.append(sal::static_int_cast< sal_Int32 >(nKeyId & 0xFFFFFFFF));
     539             :                 aStm.WriteLine(aLine.makeStringAndClear());
     540             :             }
     541             :         }
     542             :     }
     543             : #endif
     544             : 
     545          81 :     delete pResUseDump;
     546          81 : }
     547             : 
     548         250 : sal_Bool InternalResMgr::Create()
     549             : {
     550         250 :     ResMgrContainer::get();
     551         250 :     sal_Bool bDone = sal_False;
     552             : 
     553         250 :     pStm = new SvFileStream( aFileName, (STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE) );
     554         250 :     if( pStm->GetError() == 0 )
     555             :     {
     556         250 :         sal_Int32   lContLen = 0;
     557             : 
     558         250 :         pStm->Seek( STREAM_SEEK_TO_END );
     559             :         /*
     560             :         if( ( pInternalResMgr->pHead = (RSHEADER_TYPE *)mmap( 0, nResourceFileSize,
     561             :                                                         PROT_READ, MAP_PRIVATE,
     562             :                                                         fRes, 0 ) ) != (RSHEADER_TYPE *)-1)
     563             :                                                         */
     564         250 :         pStm->SeekRel( - (int)sizeof( lContLen ) );
     565         250 :         pStm->Read( &lContLen, sizeof( lContLen ) );
     566             :         // is bigendian, swab to the right endian
     567         250 :         lContLen = ResMgr::GetLong( &lContLen );
     568         250 :         pStm->SeekRel( -lContLen );
     569             :         // allocate stored ImpContent data (12 bytes per unit)
     570         250 :         sal_uInt8* pContentBuf = (sal_uInt8*)rtl_allocateMemory( lContLen );
     571         250 :         pStm->Read( pContentBuf, lContLen );
     572             :         // allocate ImpContent space (sizeof(ImpContent) per unit, not necessarily 12)
     573         250 :         pContent = (ImpContent *)rtl_allocateMemory( sizeof(ImpContent)*lContLen/12 );
     574             :         // Shorten to number of ImpContent
     575         250 :         nEntries = (sal_uInt32)lContLen / 12;
     576         250 :         bEqual2Content = sal_True;
     577         250 :         sal_Bool bSorted = sal_True;
     578         250 :         if( nEntries )
     579             :         {
     580             : #ifdef DBG_UTIL
     581             :             const sal_Char* pLogFile = getenv( "STAR_RESOURCE_LOGGING" );
     582             :             if ( pLogFile )
     583             :             {
     584             :                 pResUseDump = new boost::unordered_map<sal_uInt64, int>;
     585             :                 for( sal_uInt32 i = 0; i < nEntries; ++i )
     586             :                     (*pResUseDump)[pContent[i].nTypeAndId] = 1;
     587             :             }
     588             : #endif
     589             :             // swap the content to the right endian
     590         250 :             pContent[0].nTypeAndId = ResMgr::GetUInt64( pContentBuf );
     591         250 :             pContent[0].nOffset = ResMgr::GetLong( pContentBuf+8 );
     592         250 :             sal_uInt32 nCount = nEntries - 1;
     593       68065 :             for( sal_uInt32 i = 0,j=1; i < nCount; ++i,++j )
     594             :             {
     595             :                 // swap the content to the right endian
     596       67815 :                 pContent[j].nTypeAndId = ResMgr::GetUInt64( pContentBuf + (12*j) );
     597       67815 :                 pContent[j].nOffset = ResMgr::GetLong( pContentBuf + (12*j+8) );
     598       67815 :                 if( pContent[i].nTypeAndId >= pContent[j].nTypeAndId )
     599           0 :                     bSorted = sal_False;
     600      199485 :                 if( (pContent[i].nTypeAndId & 0xFFFFFFFF00000000LL) == (pContent[j].nTypeAndId & 0xFFFFFFFF00000000LL)
     601      131670 :                     && pContent[i].nOffset >= pContent[j].nOffset )
     602           0 :                     bEqual2Content = sal_False;
     603             :             }
     604             :         }
     605         250 :         rtl_freeMemory( pContentBuf );
     606             :         OSL_ENSURE( bSorted, "content not sorted" );
     607             :         OSL_ENSURE( bEqual2Content, "resource structure wrong" );
     608         250 :         if( !bSorted )
     609           0 :             ::std::sort(pContent,pContent+nEntries,ImpContentLessCompare());
     610             :             //  qsort( pContent, nEntries, sizeof( ImpContent ), Compare );
     611             : 
     612         250 :         bDone = sal_True;
     613             :     }
     614             : 
     615         250 :     return bDone;
     616             : }
     617             : 
     618             : 
     619        6952 : sal_Bool InternalResMgr::IsGlobalAvailable( RESOURCE_TYPE nRT, sal_uInt32 nId ) const
     620             : {
     621             :     // Anfang der Strings suchen
     622             :     ImpContent aValue;
     623        6952 :     aValue.nTypeAndId = ((sal_uInt64(nRT) << 32) | nId);
     624             :     ImpContent * pFind = ::std::lower_bound(pContent,
     625             :                                             pContent + nEntries,
     626             :                                             aValue,
     627        6952 :                                             ImpContentLessCompare());
     628        6952 :     return (pFind != (pContent + nEntries)) && (pFind->nTypeAndId == aValue.nTypeAndId);
     629             : }
     630             : 
     631             : 
     632      107707 : void* InternalResMgr::LoadGlobalRes( RESOURCE_TYPE nRT, sal_uInt32 nId,
     633             :                                      void **pResHandle )
     634             : {
     635             : #ifdef DBG_UTIL
     636             :     if( pResUseDump )
     637             :         pResUseDump->erase( (sal_uInt64(nRT) << 32) | nId );
     638             : #endif
     639             :     // search beginning of string
     640             :     ImpContent aValue;
     641      107707 :     aValue.nTypeAndId = ((sal_uInt64(nRT) << 32) | nId);
     642      107707 :     ImpContent* pEnd = (pContent + nEntries);
     643             :     ImpContent* pFind = ::std::lower_bound( pContent,
     644             :                                             pEnd,
     645             :                                             aValue,
     646      107707 :                                             ImpContentLessCompare());
     647      107707 :     if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == aValue.nTypeAndId) )
     648             :     {
     649      107707 :         if( nRT == RSC_STRING && bEqual2Content )
     650             :         {
     651             :             // string optimization
     652      103457 :             if( !pStringBlock )
     653             :             {
     654             :                 // search beginning of string
     655         121 :                 ImpContent * pFirst = pFind;
     656         121 :                 ImpContent * pLast = pFirst;
     657       34834 :                 while( pFirst > pContent && ((pFirst -1)->nTypeAndId >> 32) == RSC_STRING )
     658       34592 :                     --pFirst;
     659       20133 :                 while( pLast < pEnd && (pLast->nTypeAndId >> 32) == RSC_STRING )
     660       19891 :                     ++pLast;
     661         121 :                 nOffCorrection = pFirst->nOffset;
     662             :                 sal_uInt32 nSize;
     663         121 :                 --pLast;
     664         121 :                 pStm->Seek( pLast->nOffset );
     665             :                 RSHEADER_TYPE aHdr;
     666         121 :                 pStm->Read( &aHdr, sizeof( aHdr ) );
     667         121 :                 nSize = pLast->nOffset + aHdr.GetGlobOff() - nOffCorrection;
     668         121 :                 pStringBlock = (sal_uInt8*)rtl_allocateMemory( nSize );
     669         121 :                 pStm->Seek( pFirst->nOffset );
     670         121 :                 pStm->Read( pStringBlock, nSize );
     671             :             }
     672      103457 :             *pResHandle = pStringBlock;
     673      103457 :             return (sal_uInt8*)pStringBlock + pFind->nOffset - nOffCorrection;
     674             :         } // if( nRT == RSC_STRING && bEqual2Content )
     675             :         else
     676             :         {
     677        4250 :             *pResHandle = 0;
     678             :             RSHEADER_TYPE aHeader;
     679        4250 :             pStm->Seek( pFind->nOffset );
     680        4250 :             pStm->Read( &aHeader, sizeof( RSHEADER_TYPE ) );
     681        4250 :             void * pRes = rtl_allocateMemory( aHeader.GetGlobOff() );
     682        4250 :             memcpy( pRes, &aHeader, sizeof( RSHEADER_TYPE ) );
     683        4250 :             pStm->Read( (sal_uInt8*)pRes + sizeof( RSHEADER_TYPE ),
     684        8500 :                         aHeader.GetGlobOff() - sizeof( RSHEADER_TYPE ) );
     685        4250 :             return pRes;
     686             :         }
     687             :     } // if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == nValue) )
     688           0 :     *pResHandle = 0;
     689           0 :     return NULL;
     690             : }
     691             : 
     692      107707 : void InternalResMgr::FreeGlobalRes( void * pResHandle, void * pResource )
     693             : {
     694      107707 :     if ( !pResHandle )
     695             :         // Free allocated resource
     696        4250 :         rtl_freeMemory(pResource);
     697      107707 : }
     698             : 
     699             : #ifdef DBG_UTIL
     700             : 
     701             : UniString GetTypeRes_Impl( const ResId& rTypeId )
     702             : {
     703             :     // Return on resource errors
     704             :     static int bInUse = sal_False;
     705             :     rtl::OUString aTypStr(OUString::valueOf(static_cast<sal_Int32>(rTypeId.GetId())));
     706             : 
     707             :     if ( !bInUse )
     708             :     {
     709             :         bInUse = sal_True;
     710             : 
     711             :         ResId aResId( sal_uInt32(RSCVERSION_ID), *rTypeId.GetResMgr() );
     712             :         aResId.SetRT( RSC_VERSIONCONTROL );
     713             : 
     714             :         if ( rTypeId.GetResMgr()->GetResource( aResId ) )
     715             :         {
     716             :             rTypeId.SetRT( RSC_STRING );
     717             :             if ( rTypeId.GetResMgr()->IsAvailable( rTypeId ) )
     718             :             {
     719             :                 aTypStr = rTypeId.toString();
     720             :                 // Set class pointer to the end
     721             :                 rTypeId.GetResMgr()->Increment( sizeof( RSHEADER_TYPE ) );
     722             :             }
     723             :         }
     724             :         bInUse = sal_False;
     725             :     }
     726             : 
     727             :     return aTypStr;
     728             : }
     729             : 
     730             : void ResMgr::RscError_Impl( const sal_Char* pMessage, ResMgr* pResMgr,
     731             :                             RESOURCE_TYPE nRT, sal_uInt32 nId,
     732             :                             std::vector< ImpRCStack >& rResStack, int nDepth )
     733             : {
     734             :     // create a separate ResMgr with its own stack
     735             :     // first get a second reference of the InternalResMgr
     736             :     InternalResMgr* pImp =
     737             :         ResMgrContainer::get().getResMgr( pResMgr->pImpRes->aPrefix,
     738             :                                           pResMgr->pImpRes->aLocale,
     739             :                                           true );
     740             : 
     741             :     ResMgr* pNewResMgr = new ResMgr( pImp );
     742             : 
     743             :     rtl::OStringBuffer aStr(rtl::OUStringToOString(pResMgr->GetFileName(),
     744             :         RTL_TEXTENCODING_UTF8));
     745             : 
     746             :     if (aStr.getLength())
     747             :         aStr.append('\n');
     748             : 
     749             :     aStr.append(RTL_CONSTASCII_STRINGPARAM("Class: "));
     750             :     aStr.append(rtl::OUStringToOString(GetTypeRes_Impl(ResId(nRT, *pNewResMgr)),
     751             :         RTL_TEXTENCODING_UTF8));
     752             :     aStr.append(RTL_CONSTASCII_STRINGPARAM(", Id: "));
     753             :     aStr.append(static_cast<sal_Int32>(nId));
     754             :     aStr.append(RTL_CONSTASCII_STRINGPARAM(". "));
     755             :     aStr.append(pMessage);
     756             : 
     757             :     aStr.append(RTL_CONSTASCII_STRINGPARAM("\nResource Stack\n"));
     758             :     while( nDepth > 0 )
     759             :     {
     760             :         aStr.append(RTL_CONSTASCII_STRINGPARAM("Class: "));
     761             :         aStr.append(rtl::OUStringToOString(GetTypeRes_Impl(
     762             :             ResId(rResStack[nDepth].pResource->GetRT(), *pNewResMgr)),
     763             :             RTL_TEXTENCODING_UTF8));
     764             :         aStr.append(RTL_CONSTASCII_STRINGPARAM(", Id: "));
     765             :         aStr.append(static_cast<sal_Int32>(
     766             :             rResStack[nDepth].pResource->GetId()));
     767             :         nDepth--;
     768             :     }
     769             : 
     770             :     // clean up
     771             :     delete pNewResMgr;
     772             : 
     773             :     OSL_FAIL(aStr.getStr());
     774             : }
     775             : 
     776             : #endif
     777             : 
     778           0 : static void RscException_Impl()
     779             : {
     780           0 :     switch ( osl_raiseSignal( OSL_SIGNAL_USER_RESOURCEFAILURE, (void*)"" ) )
     781             :     {
     782             :     case osl_Signal_ActCallNextHdl:
     783           0 :         abort();
     784             : 
     785             :     case osl_Signal_ActIgnore:
     786           0 :         return;
     787             : 
     788             :     case osl_Signal_ActAbortApp:
     789           0 :         abort();
     790             : 
     791             :     default:
     792             :     case osl_Signal_ActKillApp:
     793           0 :         exit(-1);
     794             :     }
     795             : }
     796             : 
     797      141278 : void ImpRCStack::Init( ResMgr* pMgr, const Resource* pObj, sal_uInt32 Id )
     798             : {
     799      141278 :     pResource       = NULL;
     800      141278 :     pClassRes       = NULL;
     801      141278 :     Flags           = RC_NOTYPE;
     802      141278 :     aResHandle      = NULL;
     803      141278 :     pResObj         = pObj;
     804      141278 :     nId             = Id & ~RSC_DONTRELEASE; //TLX: Besser Init aendern
     805      141278 :     pResMgr         = pMgr;
     806      141278 :     if ( !(Id & RSC_DONTRELEASE) )
     807      141278 :         Flags      |= RC_AUTORELEASE;
     808      141278 : }
     809             : 
     810      141654 : void ImpRCStack::Clear()
     811             : {
     812      141654 :     pResource       = NULL;
     813      141654 :     pClassRes       = NULL;
     814      141654 :     Flags           = RC_NOTYPE;
     815      141654 :     aResHandle      = NULL;
     816      141654 :     pResObj         = NULL;
     817      141654 :     nId             = 0;
     818      141654 :     pResMgr         = NULL;
     819      141654 : }
     820             : 
     821      175893 : static RSHEADER_TYPE* LocalResource( const ImpRCStack* pStack,
     822             :                                      RESOURCE_TYPE nRTType,
     823             :                                      sal_uInt32 nId )
     824             : {
     825             :     // Returns position of the resource if found or NULL otherwise
     826             :     RSHEADER_TYPE*  pTmp;   // Pointer to child resource
     827             :     RSHEADER_TYPE*  pEnd;   // Pointer to the end of this resource
     828             : 
     829      175893 :     if ( pStack->pResource && pStack->pClassRes )
     830             :     {
     831             :         pTmp = (RSHEADER_TYPE*)
     832       67682 :                ((sal_uInt8*)pStack->pResource + pStack->pResource->GetLocalOff());
     833             :         pEnd = (RSHEADER_TYPE*)
     834       67682 :                ((sal_uInt8*)pStack->pResource + pStack->pResource->GetGlobOff());
     835    10998135 :         while ( pTmp != pEnd )
     836             :         {
     837    10924005 :             if ( pTmp->GetRT() == nRTType && pTmp->GetId() == nId )
     838       61234 :                 return pTmp;
     839    10862771 :             pTmp = (RSHEADER_TYPE*)((sal_uInt8*)pTmp + pTmp->GetGlobOff());
     840             :         }
     841             :     }
     842             : 
     843      114659 :     return NULL;
     844             : }
     845             : 
     846             : void* ResMgr::pEmptyBuffer = NULL;
     847             : 
     848           0 : void* ResMgr::getEmptyBuffer()
     849             : {
     850           0 :     if( ! pEmptyBuffer )
     851           0 :         pEmptyBuffer = rtl_allocateZeroMemory( 1024 );
     852           0 :     return pEmptyBuffer;
     853             : }
     854             : 
     855           0 : void ResMgr::DestroyAllResMgr()
     856             : {
     857             :     {
     858           0 :         osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     859           0 :         if( pEmptyBuffer )
     860             :         {
     861           0 :             rtl_freeMemory( pEmptyBuffer );
     862           0 :             pEmptyBuffer = NULL;
     863             :         }
     864           0 :         ResMgrContainer::release();
     865             :     }
     866           0 :     delete pResMgrMutex;
     867           0 :     pResMgrMutex = NULL;
     868           0 : }
     869             : 
     870         376 : void ResMgr::Init( const OUString& rFileName )
     871             : {
     872             :     (void) rFileName; // avoid warning about unused parameter
     873         376 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     874             : 
     875         376 :     if ( !pImpRes )
     876             :     {
     877             : #ifdef DBG_UTIL
     878             :         rtl::OStringBuffer aStr(
     879             :             RTL_CONSTASCII_STRINGPARAM("Resourcefile not found:\n"));
     880             :         aStr.append(OUStringToOString(rFileName, RTL_TEXTENCODING_UTF8));
     881             :         OSL_FAIL(aStr.getStr());
     882             : #endif
     883           0 :         RscException_Impl();
     884             :     }
     885             : #ifdef DBG_UTIL
     886             :     else
     887             :     {
     888             :         void* aResHandle = 0;     // Helper variable for resource handles
     889             :         void* pVoid;              // Pointer on the resource
     890             : 
     891             :         pVoid = pImpRes->LoadGlobalRes( RSC_VERSIONCONTROL, RSCVERSION_ID,
     892             :                                         &aResHandle );
     893             :         if ( pVoid )
     894             :             InternalResMgr::FreeGlobalRes( aResHandle, pVoid );
     895             :         else
     896             :         {
     897             :             SAL_WARN("tools", "Wrong version: " << pImpRes->aFileName);
     898             :         }
     899             :     }
     900             : #endif
     901         376 :     nCurStack = -1;
     902         376 :     aStack.clear();
     903         376 :     pFallbackResMgr = pOriginalResMgr = NULL;
     904         376 :     incStack();
     905         376 : }
     906             : 
     907         376 : ResMgr::ResMgr( InternalResMgr * pImpMgr )
     908             : {
     909         376 :     pImpRes = pImpMgr;
     910         376 :     Init( pImpMgr->aFileName );
     911         376 : }
     912             : 
     913         286 : ResMgr::~ResMgr()
     914             : {
     915         143 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     916             : 
     917         143 :     ResMgrContainer::get().freeResMgr( pImpRes );
     918             : 
     919             :     // clean up possible left rc stack frames
     920         286 :     while( nCurStack > 0 )
     921             :     {
     922           0 :         if( ( aStack[nCurStack].Flags & (RC_GLOBAL | RC_NOTFOUND) ) == RC_GLOBAL )
     923           0 :             InternalResMgr::FreeGlobalRes( aStack[nCurStack].aResHandle,
     924           0 :                                     aStack[nCurStack].pResource );
     925           0 :         nCurStack--;
     926         143 :     }
     927         143 : }
     928             : 
     929      141654 : void ResMgr::incStack()
     930             : {
     931      141654 :     nCurStack++;
     932      141654 :     if( nCurStack >= int(aStack.size()) )
     933         709 :         aStack.push_back( ImpRCStack() );
     934      141654 :     aStack[nCurStack].Clear();
     935             : 
     936             :     DBG_ASSERT( nCurStack < 32, "Resource stack unreasonably large" );
     937      141654 : }
     938             : 
     939      141278 : void ResMgr::decStack()
     940             : {
     941             :     DBG_ASSERT( nCurStack > 0, "resource stack underrun  !" );
     942      141278 :     if( (aStack[nCurStack].Flags & RC_FALLBACK_UP) )
     943             :     {
     944           0 :         nCurStack--;
     945             :         // warning: this will delete *this, see below
     946           0 :         pOriginalResMgr->decStack();
     947             :     }
     948             :     else
     949             :     {
     950      141278 :         ImpRCStack& rTop = aStack[nCurStack];
     951      141278 :         if( (rTop.Flags & RC_FALLBACK_DOWN) )
     952             :         {
     953             :             #if OSL_DEBUG_LEVEL > 1
     954             :             OSL_TRACE( "returning from fallback %s",
     955             :                      OUStringToOString(pFallbackResMgr->GetFileName(), osl_getThreadTextEncoding() ).getStr() );
     956             :             #endif
     957           0 :             delete pFallbackResMgr;
     958           0 :             pFallbackResMgr = NULL;
     959             :         }
     960      141278 :         nCurStack--;
     961             :     }
     962      141278 : }
     963             : 
     964             : #ifdef DBG_UTIL
     965             : 
     966             : void ResMgr::TestStack( const Resource* pResObj )
     967             : {
     968             :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     969             : 
     970             :     int upperLimit = nCurStack;
     971             : 
     972             :     if ( upperLimit < 0 )
     973             :     {
     974             :         OSL_FAIL( "resource stack underrun!" );
     975             :         upperLimit = aStack.size() - 1;
     976             :     }
     977             :     else if ( upperLimit >=  static_cast<int>(aStack.size()) )
     978             :     {
     979             :         OSL_FAIL( "stack occupation index > allocated stack size" );
     980             :         upperLimit = aStack.size() - 1;
     981             :     }
     982             : 
     983             :     if ( DbgIsResource() )
     984             :     {
     985             :         for( int i = 1; i <= upperLimit; ++i )
     986             :         {
     987             :             if ( aStack[i].pResObj == pResObj )
     988             :             {
     989             :                 RscError_Impl( "Resource not freed! ", this,
     990             :                                aStack[i].pResource->GetRT(),
     991             :                                aStack[i].pResource->GetId(),
     992             :                                aStack, i-1 );
     993             :             }
     994             :         }
     995             :     }
     996             : }
     997             : 
     998             : #else
     999             : 
    1000           0 : void ResMgr::TestStack( const Resource* )
    1001             : {
    1002           0 : }
    1003             : 
    1004             : #endif
    1005             : 
    1006       34907 : sal_Bool ResMgr::IsAvailable( const ResId& rId, const Resource* pResObj ) const
    1007             : {
    1008       34907 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1009             : 
    1010       34907 :     sal_Bool            bAvailable = sal_False;
    1011       34907 :     RSHEADER_TYPE*  pClassRes = rId.GetpResource();
    1012       34907 :     RESOURCE_TYPE   nRT = rId.GetRT2();
    1013       34907 :     sal_uInt32      nId = rId.GetId();
    1014       34907 :     const ResMgr*   pMgr = rId.GetResMgr();
    1015             : 
    1016       34907 :     if ( !pMgr )
    1017           0 :         pMgr = this;
    1018             : 
    1019       34907 :     if( pMgr->pFallbackResMgr )
    1020             :     {
    1021           0 :         ResId aId( rId );
    1022           0 :         aId.SetResMgr( NULL );
    1023           0 :         return pMgr->pFallbackResMgr->IsAvailable( aId, pResObj );
    1024             :     }
    1025             : 
    1026       34907 :     if ( !pResObj || pResObj == pMgr->aStack[pMgr->nCurStack].pResObj )
    1027             :     {
    1028       34907 :         if ( !pClassRes )
    1029       34907 :             pClassRes = LocalResource( &pMgr->aStack[pMgr->nCurStack], nRT, nId );
    1030       34907 :         if ( pClassRes )
    1031             :         {
    1032       27955 :             if ( pClassRes->GetRT() == nRT )
    1033       27955 :                 bAvailable = sal_True;
    1034             :         }
    1035             :     }
    1036             : 
    1037       34907 :     if ( !pClassRes )
    1038        6952 :         bAvailable = pMgr->pImpRes->IsGlobalAvailable( nRT, nId );
    1039             : 
    1040       34907 :     return bAvailable;
    1041             : }
    1042             : 
    1043      148513 : void* ResMgr::GetClass()
    1044             : {
    1045      148513 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1046             : 
    1047      148513 :     if( pFallbackResMgr )
    1048           0 :         return pFallbackResMgr->GetClass();
    1049             : 
    1050      148513 :     return aStack[nCurStack].pClassRes;
    1051             : }
    1052             : 
    1053      141278 : sal_Bool ResMgr::GetResource( const ResId& rId, const Resource* pResObj )
    1054             : {
    1055      141278 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1056             : 
    1057      141278 :     if( pFallbackResMgr )
    1058             :     {
    1059           0 :         ResId aId( rId );
    1060           0 :         aId.SetResMgr( NULL );
    1061           0 :         return pFallbackResMgr->GetResource( aId, pResObj );
    1062             :     }
    1063             : 
    1064      141278 :     ResMgr* pMgr = rId.GetResMgr();
    1065      141278 :     if ( pMgr && (this != pMgr) )
    1066           0 :         return pMgr->GetResource( rId, pResObj );
    1067             : 
    1068             :     // normally Increment will pop the context; this is
    1069             :     // not possible in RC_NOTFOUND case, so pop a frame here
    1070      141278 :     ImpRCStack* pTop = &aStack[nCurStack];
    1071      141278 :     if( (pTop->Flags & RC_NOTFOUND) )
    1072             :     {
    1073           0 :         decStack();
    1074             :     }
    1075             : 
    1076      141278 :     RSHEADER_TYPE*  pClassRes = rId.GetpResource();
    1077      141278 :     RESOURCE_TYPE   nRT = rId.GetRT2();
    1078      141278 :     sal_uInt32      nId = rId.GetId();
    1079             : 
    1080      141278 :     incStack();
    1081      141278 :     pTop = &aStack[nCurStack];
    1082             :     pTop->Init( pMgr, pResObj, nId |
    1083      141278 :                 (rId.IsAutoRelease() ? 0 : RSC_DONTRELEASE) );
    1084             : 
    1085      141278 :     if ( pClassRes )
    1086             :     {
    1087         292 :         if ( pClassRes->GetRT() == nRT )
    1088         292 :             pTop->pClassRes = pClassRes;
    1089             :         else
    1090             :         {
    1091             : #ifdef DBG_UTIL
    1092             :             RscError_Impl( "Different class and resource type!",
    1093             :                            this, nRT, nId, aStack, nCurStack-1 );
    1094             : #endif
    1095           0 :             pTop->Flags |= RC_NOTFOUND;
    1096           0 :             pTop->pClassRes = getEmptyBuffer();
    1097           0 :             pTop->pResource = (RSHEADER_TYPE*)pTop->pClassRes;
    1098           0 :             return sal_False;
    1099             :         }
    1100             :     }
    1101             :     else
    1102             :     {
    1103             :         OSL_ENSURE( nCurStack > 0, "stack of 1 to shallow" );
    1104      140986 :         pTop->pClassRes = LocalResource( &aStack[nCurStack-1], nRT, nId );
    1105             :     }
    1106             : 
    1107      141278 :     if ( pTop->pClassRes )
    1108             :         // lokale Resource, nicht system Resource
    1109       33571 :         pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
    1110             :     else
    1111             :     {
    1112      107707 :         pTop->pClassRes = pImpRes->LoadGlobalRes( nRT, nId, &pTop->aResHandle );
    1113      107707 :         if ( pTop->pClassRes )
    1114             :         {
    1115      107707 :             pTop->Flags |= RC_GLOBAL;
    1116      107707 :             pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
    1117             :         }
    1118             :         else
    1119             :         {
    1120             :             // try to get a fallback resource
    1121           0 :             pFallbackResMgr = CreateFallbackResMgr( rId, pResObj );
    1122           0 :             if( pFallbackResMgr )
    1123             :             {
    1124           0 :                 pTop->Flags |= RC_FALLBACK_DOWN;
    1125             : #ifdef DBG_UTIL
    1126             :                 rtl::OStringBuffer aMess(
    1127             :                     RTL_CONSTASCII_STRINGPARAM("found resource "));
    1128             :                 aMess.append(static_cast<sal_Int32>(nId));
    1129             :                 aMess.append(RTL_CONSTASCII_STRINGPARAM(" in fallback "));
    1130             :                 aMess.append(rtl::OUStringToOString(
    1131             :                     pFallbackResMgr->GetFileName(),
    1132             :                     osl_getThreadTextEncoding()));
    1133             :                 aMess.append('\n');
    1134             :                 RscError_Impl(aMess.getStr(),
    1135             :                               this, nRT, nId, aStack, nCurStack-1);
    1136             : #endif
    1137             :             }
    1138             :             else
    1139             :             {
    1140             :                 #ifdef DBG_UTIL
    1141             :                 RscError_Impl( "Cannot load resource! ",
    1142             :                               this, nRT, nId, aStack, nCurStack-1 );
    1143             :                 #endif
    1144           0 :                 pTop->Flags |= RC_NOTFOUND;
    1145           0 :                 pTop->pClassRes = getEmptyBuffer();
    1146           0 :                 pTop->pResource = (RSHEADER_TYPE*)pTop->pClassRes;
    1147           0 :                 return sal_False;
    1148             :             }
    1149             :         }
    1150             :     }
    1151             : 
    1152      141278 :     return sal_True;
    1153             : }
    1154             : 
    1155         743 : void * ResMgr::GetResourceSkipHeader( const ResId& rResId, ResMgr ** ppResMgr )
    1156             : {
    1157         743 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1158             : 
    1159             :     DBG_ASSERT( rResId.GetResMgr(), "illegal ResId without ResMgr" );
    1160         743 :     *ppResMgr = rResId.GetResMgr();
    1161         743 :     if( *ppResMgr )
    1162             :     {
    1163         743 :         (*ppResMgr)->GetResource( rResId );
    1164         743 :         (*ppResMgr)->Increment( sizeof( RSHEADER_TYPE ) );
    1165         743 :         return (*ppResMgr)->GetClass();
    1166             :     }
    1167           0 :     return getEmptyBuffer();
    1168             : }
    1169             : 
    1170      141278 : void ResMgr::PopContext( const Resource* pResObj )
    1171             : {
    1172      141278 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1173             : 
    1174      141278 :     if( pFallbackResMgr )
    1175             :     {
    1176           0 :         pFallbackResMgr->PopContext( pResObj );
    1177      141278 :         return;
    1178             :     }
    1179             : 
    1180             : #ifdef DBG_UTIL
    1181             :     if ( DbgIsResource() )
    1182             :     {
    1183             :         if ( (aStack[nCurStack].pResObj != pResObj) || nCurStack == 0 )
    1184             :         {
    1185             :             RscError_Impl( "Cannot free resource! ", this,
    1186             :                            RSC_NOTYPE, 0, aStack, nCurStack );
    1187             :         }
    1188             :     }
    1189             : #endif
    1190             : 
    1191      141278 :     if ( nCurStack > 0 )
    1192             :     {
    1193      141278 :         ImpRCStack* pTop = &aStack[nCurStack];
    1194             : #ifdef DBG_UTIL
    1195             :         if ( DbgIsResource() && !(pTop->Flags & RC_NOTFOUND) )
    1196             :         {
    1197             :             void* pRes = (sal_uInt8*)pTop->pResource +
    1198             :                          pTop->pResource->GetLocalOff();
    1199             : 
    1200             :             if ( pTop->pClassRes != pRes )
    1201             :             {
    1202             :                 RscError_Impl( "Classpointer not at the end!",
    1203             :                                this, pTop->pResource->GetRT(),
    1204             :                                pTop->pResource->GetId(),
    1205             :                                aStack, nCurStack-1 );
    1206             :             }
    1207             :         }
    1208             : #endif
    1209             : 
    1210             :         // free resource
    1211      141278 :         if( (pTop->Flags & (RC_GLOBAL | RC_NOTFOUND)) == RC_GLOBAL )
    1212             :             // free global resource if resource is foreign
    1213      107707 :             InternalResMgr::FreeGlobalRes( pTop->aResHandle, pTop->pResource );
    1214      141278 :         decStack();
    1215      141278 :     }
    1216             : }
    1217             : 
    1218           0 : RSHEADER_TYPE* ResMgr::CreateBlock( const ResId& rId )
    1219             : {
    1220           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1221             : 
    1222           0 :     if( pFallbackResMgr )
    1223             :     {
    1224           0 :         ResId aId( rId );
    1225           0 :         aId.SetResMgr( NULL );
    1226           0 :         return pFallbackResMgr->CreateBlock( aId );
    1227             :     }
    1228             : 
    1229           0 :     RSHEADER_TYPE* pHeader = NULL;
    1230           0 :     if ( GetResource( rId ) )
    1231             :     {
    1232             :         // Pointer is at the beginning of the resource, thus
    1233             :         // class pointer points to the header, and the remaining size
    1234             :         // equals to total size of allocated memory
    1235           0 :         pHeader = (RSHEADER_TYPE*)rtl_allocateMemory( GetRemainSize() );
    1236           0 :         memcpy( pHeader, GetClass(), GetRemainSize() );
    1237           0 :         Increment( pHeader->GetLocalOff() ); //ans Ende setzen
    1238           0 :         if ( pHeader->GetLocalOff() != pHeader->GetGlobOff() )
    1239             :             // Has sub-resources, thus release them as well
    1240           0 :             PopContext();
    1241             :     }
    1242             : 
    1243           0 :     return pHeader;
    1244             : }
    1245             : 
    1246        1767 : sal_Int16 ResMgr::GetShort( void * pShort )
    1247             : {
    1248             :     return ((*((sal_uInt8*)pShort + 0) << 8) |
    1249        1767 :             (*((sal_uInt8*)pShort + 1) << 0)   );
    1250             : }
    1251             : 
    1252    33268333 : sal_Int32 ResMgr::GetLong( void * pLong )
    1253             : {
    1254             :     return ((*((sal_uInt8*)pLong + 0) << 24) |
    1255    33268333 :             (*((sal_uInt8*)pLong + 1) << 16) |
    1256    33268333 :             (*((sal_uInt8*)pLong + 2) <<  8) |
    1257    99804999 :             (*((sal_uInt8*)pLong + 3) <<  0)   );
    1258             : }
    1259             : 
    1260       68065 : sal_uInt64 ResMgr::GetUInt64( void* pDatum )
    1261             : {
    1262             :     return ((sal_uInt64(*((sal_uInt8*)pDatum + 0)) << 56) |
    1263       68065 :             (sal_uInt64(*((sal_uInt8*)pDatum + 1)) << 48) |
    1264       68065 :             (sal_uInt64(*((sal_uInt8*)pDatum + 2)) << 40) |
    1265       68065 :             (sal_uInt64(*((sal_uInt8*)pDatum + 3)) << 32) |
    1266       68065 :             (sal_uInt64(*((sal_uInt8*)pDatum + 4)) << 24) |
    1267       68065 :             (sal_uInt64(*((sal_uInt8*)pDatum + 5)) << 16) |
    1268       68065 :             (sal_uInt64(*((sal_uInt8*)pDatum + 6)) <<  8) |
    1269      476455 :             (sal_uInt64(*((sal_uInt8*)pDatum + 7)) <<  0)   );
    1270             : }
    1271             : 
    1272        2539 : sal_uInt32 ResMgr::GetStringWithoutHook( UniString& rStr, const sal_uInt8* pStr )
    1273             : {
    1274        2539 :     sal_uInt32 nLen=0;
    1275        2539 :     sal_uInt32 nRet = GetStringSize( pStr, nLen );
    1276             :     UniString aString( (sal_Char*)pStr, RTL_TEXTENCODING_UTF8,
    1277             :                        RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |
    1278             :                        RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
    1279        2539 :                        RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
    1280        2539 :     rStr = aString;
    1281        2539 :     return nRet;
    1282             : }
    1283             : 
    1284           0 : sal_uInt32 ResMgr::GetString( UniString& rStr, const sal_uInt8* pStr )
    1285             : {
    1286           0 :     UniString aString;
    1287           0 :     sal_uInt32 nRet =  GetStringWithoutHook( aString, pStr );
    1288           0 :     if ( pImplResHookProc )
    1289           0 :         aString = pImplResHookProc( aString );
    1290           0 :     rStr = aString;
    1291           0 :     return nRet;
    1292             : }
    1293             : 
    1294         582 : sal_uInt32 ResMgr::GetByteString( rtl::OString& rStr, const sal_uInt8* pStr )
    1295             : {
    1296         582 :     sal_uInt32 nLen=0;
    1297         582 :     sal_uInt32 nRet = GetStringSize( pStr, nLen );
    1298         582 :     rStr = rtl::OString( (const sal_Char*)pStr, nLen );
    1299         582 :     return nRet;
    1300             : }
    1301             : 
    1302        3121 : sal_uInt32 ResMgr::GetStringSize( const sal_uInt8* pStr, sal_uInt32& nLen )
    1303             : {
    1304        3121 :     nLen = static_cast< sal_uInt32 >( strlen( (const char*)pStr ) );
    1305        3121 :     return GetStringSize( nLen );
    1306             : }
    1307             : 
    1308           0 : sal_uInt32 ResMgr::GetRemainSize()
    1309             : {
    1310           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1311             : 
    1312           0 :     if( pFallbackResMgr )
    1313           0 :         return pFallbackResMgr->GetRemainSize();
    1314             : 
    1315           0 :     const ImpRCStack& rTop = aStack[nCurStack];
    1316             :     return  (sal_uInt32)((long)(sal_uInt8 *)rTop.pResource +
    1317           0 :                      rTop.pResource->GetLocalOff() -
    1318           0 :                      (long)(sal_uInt8 *)rTop.pClassRes);
    1319             : }
    1320             : 
    1321      153993 : void* ResMgr::Increment( sal_uInt32 nSize )
    1322             : {
    1323      153993 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1324             : 
    1325      153993 :     if( pFallbackResMgr )
    1326           0 :         return pFallbackResMgr->Increment( nSize );
    1327             : 
    1328      153993 :     ImpRCStack& rStack = aStack[nCurStack];
    1329      153993 :     if( (rStack.Flags & RC_NOTFOUND) )
    1330           0 :         return rStack.pClassRes;
    1331             : 
    1332      153993 :     sal_uInt8* pClassRes = (sal_uInt8*)rStack.pClassRes + nSize;
    1333             : 
    1334      153993 :     rStack.pClassRes = pClassRes;
    1335             : 
    1336      153993 :     RSHEADER_TYPE* pRes = rStack.pResource;
    1337             : 
    1338      153993 :     sal_uInt32 nLocalOff = pRes->GetLocalOff();
    1339      153993 :     if ( (pRes->GetGlobOff() == nLocalOff) &&
    1340             :          (((char*)pRes + nLocalOff) == rStack.pClassRes) &&
    1341             :          (rStack.Flags & RC_AUTORELEASE))
    1342             :     {
    1343      135581 :         PopContext( rStack.pResObj );
    1344             :     }
    1345             : 
    1346      153993 :     return pClassRes;
    1347             : }
    1348             : 
    1349           0 : ResMgr* ResMgr::CreateFallbackResMgr( const ResId& rId, const Resource* pResource )
    1350             : {
    1351           0 :     ResMgr *pFallback = NULL;
    1352           0 :     if( nCurStack > 0 )
    1353             :     {
    1354             :         // get the next fallback level in resource file scope
    1355           0 :         InternalResMgr* pRes = ResMgrContainer::get().getNextFallback( pImpRes );
    1356           0 :         if( pRes )
    1357             :         {
    1358             :             // check that the fallback locale is not already in the chain of
    1359             :             // fallbacks - prevent fallback loops
    1360           0 :             ResMgr* pResMgr = this;
    1361           0 :             while( pResMgr &&
    1362           0 :                    ( pResMgr->pImpRes->aLocale.Language != pRes->aLocale.Language ||
    1363           0 :                      pResMgr->pImpRes->aLocale.Country  != pRes->aLocale.Country  ||
    1364           0 :                      pResMgr->pImpRes->aLocale.Variant  != pRes->aLocale.Variant )
    1365             :                  )
    1366             :             {
    1367           0 :                 pResMgr = pResMgr->pOriginalResMgr;
    1368             :             }
    1369           0 :             if( pResMgr )
    1370             :             {
    1371             :                 // found a recursion, no fallback possible
    1372           0 :                 ResMgrContainer::get().freeResMgr( pRes );
    1373           0 :                 return NULL;
    1374             :             }
    1375             :             OSL_TRACE( "trying fallback: %s", OUStringToOString( pRes->aFileName, osl_getThreadTextEncoding() ).getStr() );
    1376           0 :             pFallback = new ResMgr( pRes );
    1377           0 :             pFallback->pOriginalResMgr = this;
    1378             :             // try to recreate the resource stack
    1379           0 :             bool bHaveStack = true;
    1380           0 :             for( int i = 1; i < nCurStack; i++ )
    1381             :             {
    1382           0 :                 if( !aStack[i].pResource )
    1383             :                 {
    1384           0 :                     bHaveStack = false;
    1385             :                     break;
    1386             :                 }
    1387           0 :                 ResId aId( aStack[i].pResource->GetId(), *pFallbackResMgr );
    1388           0 :                 aId.SetRT( aStack[i].pResource->GetRT() );
    1389           0 :                 if( !pFallback->GetResource( aId ) )
    1390             :                 {
    1391           0 :                     bHaveStack = false;
    1392             :                     break;
    1393             :                 }
    1394             :             }
    1395           0 :             if( bHaveStack )
    1396             :             {
    1397           0 :                 ResId aId( rId.GetId(), *pFallback );
    1398           0 :                 aId.SetRT( rId.GetRT() );
    1399           0 :                 if( !pFallback->GetResource( aId, pResource ) )
    1400           0 :                     bHaveStack = false;
    1401             :                 else
    1402           0 :                     pFallback->aStack[pFallback->nCurStack].Flags |= RC_FALLBACK_UP;
    1403             :             }
    1404           0 :             if( !bHaveStack )
    1405             :             {
    1406           0 :                 delete pFallback;
    1407           0 :                 pFallback = NULL;
    1408             :             }
    1409             :         }
    1410             :     }
    1411           0 :     return pFallback;
    1412             : }
    1413             : 
    1414             : // method left here for SDK compatibility,
    1415             : // used in "framework/source/services/substitutepathvars.cxx"
    1416             : // phone numbers no longer in use for resource files
    1417             : 
    1418          19 : const char* ResMgr::GetLang( LanguageType& nType, sal_uInt16 nPrio )
    1419             : {
    1420          19 :     if ( nType == LANGUAGE_SYSTEM || nType == LANGUAGE_DONTKNOW )
    1421           0 :         nType = MsLangId::getSystemUILanguage();
    1422             : 
    1423          19 :     if ( nPrio == 0 )
    1424             :     {
    1425          19 :         switch ( nType )
    1426             :         {
    1427             :             case LANGUAGE_DANISH:
    1428           0 :                 return "45";
    1429             : 
    1430             :             case LANGUAGE_DUTCH:
    1431             :             case LANGUAGE_DUTCH_BELGIAN:
    1432           0 :                 return "31";
    1433             : 
    1434             :             case LANGUAGE_ENGLISH:
    1435             :             case LANGUAGE_ENGLISH_UK:
    1436             :             case LANGUAGE_ENGLISH_EIRE:
    1437             :             case LANGUAGE_ENGLISH_SAFRICA:
    1438             :             case LANGUAGE_ENGLISH_JAMAICA:
    1439             :             case LANGUAGE_ENGLISH_BELIZE:
    1440             :             case LANGUAGE_ENGLISH_TRINIDAD:
    1441             :             case LANGUAGE_ENGLISH_ZIMBABWE:
    1442             :             case LANGUAGE_ENGLISH_PHILIPPINES:
    1443           0 :                 return "44";
    1444             : 
    1445             :             case LANGUAGE_ENGLISH_US:
    1446             :             case LANGUAGE_ENGLISH_CAN:
    1447          19 :                 return "01";
    1448             : 
    1449             :             case LANGUAGE_ENGLISH_AUS:
    1450             :             case LANGUAGE_ENGLISH_NZ:
    1451           0 :                 return "61";
    1452             :             case LANGUAGE_ESTONIAN:
    1453           0 :                 return "77";
    1454             : 
    1455             : 
    1456             :             case LANGUAGE_FINNISH:
    1457           0 :                 return "35";
    1458             : 
    1459             :             case LANGUAGE_FRENCH_CANADIAN:
    1460           0 :                 return "02";
    1461             : 
    1462             :             case LANGUAGE_FRENCH:
    1463             :             case LANGUAGE_FRENCH_BELGIAN:
    1464             :             case LANGUAGE_FRENCH_SWISS:
    1465             :             case LANGUAGE_FRENCH_LUXEMBOURG:
    1466             :             case LANGUAGE_FRENCH_MONACO:
    1467           0 :                 return "33";
    1468             : 
    1469             :             case LANGUAGE_GERMAN:
    1470             :             case LANGUAGE_GERMAN_SWISS:
    1471             :             case LANGUAGE_GERMAN_AUSTRIAN:
    1472             :             case LANGUAGE_GERMAN_LUXEMBOURG:
    1473             :             case LANGUAGE_GERMAN_LIECHTENSTEIN:
    1474           0 :                 return "49";
    1475             : 
    1476             :             case LANGUAGE_ITALIAN:
    1477             :             case LANGUAGE_ITALIAN_SWISS:
    1478           0 :                 return "39";
    1479             : 
    1480             :             case LANGUAGE_NORWEGIAN:
    1481             :             case LANGUAGE_NORWEGIAN_BOKMAL:
    1482           0 :                 return "47";
    1483             : 
    1484             :             case LANGUAGE_PORTUGUESE:
    1485           0 :                 return "03";
    1486             : 
    1487             :             case LANGUAGE_PORTUGUESE_BRAZILIAN:
    1488           0 :                 return "55";
    1489             : 
    1490             :             case LANGUAGE_SPANISH_DATED:
    1491             :             case LANGUAGE_SPANISH_MEXICAN:
    1492             :             case LANGUAGE_SPANISH_MODERN:
    1493             :             case LANGUAGE_SPANISH_GUATEMALA:
    1494             :             case LANGUAGE_SPANISH_COSTARICA:
    1495             :             case LANGUAGE_SPANISH_PANAMA:
    1496             :             case LANGUAGE_SPANISH_DOMINICAN_REPUBLIC:
    1497             :             case LANGUAGE_SPANISH_VENEZUELA:
    1498             :             case LANGUAGE_SPANISH_COLOMBIA:
    1499             :             case LANGUAGE_SPANISH_PERU:
    1500             :             case LANGUAGE_SPANISH_ARGENTINA:
    1501             :             case LANGUAGE_SPANISH_ECUADOR:
    1502             :             case LANGUAGE_SPANISH_CHILE:
    1503             :             case LANGUAGE_SPANISH_URUGUAY:
    1504             :             case LANGUAGE_SPANISH_PARAGUAY:
    1505             :             case LANGUAGE_SPANISH_BOLIVIA:
    1506           0 :                 return "34";
    1507             : 
    1508             :             case LANGUAGE_SWEDISH:
    1509           0 :                 return "46";
    1510             : 
    1511             :             case LANGUAGE_POLISH:
    1512           0 :                 return "48";
    1513             :             case LANGUAGE_CZECH:
    1514           0 :                 return "42";
    1515             :             case LANGUAGE_SLOVENIAN:
    1516           0 :                 return "50";
    1517             :             case LANGUAGE_HUNGARIAN:
    1518           0 :                 return "36";
    1519             :             case LANGUAGE_RUSSIAN:
    1520           0 :                 return "07";
    1521             :             case LANGUAGE_SLOVAK:
    1522           0 :                 return "43";
    1523             :             case LANGUAGE_GREEK:
    1524           0 :                 return "30";
    1525             :             case LANGUAGE_TURKISH:
    1526           0 :                 return "90";
    1527             : 
    1528             :             case LANGUAGE_CHINESE_SIMPLIFIED:
    1529           0 :                 return "86";
    1530             :             case LANGUAGE_CHINESE_TRADITIONAL:
    1531           0 :                 return "88";
    1532             :             case LANGUAGE_JAPANESE:
    1533           0 :                 return "81";
    1534             :             case LANGUAGE_KOREAN:
    1535             :             case LANGUAGE_KOREAN_JOHAB:
    1536           0 :                 return "82";
    1537             :             case LANGUAGE_THAI:
    1538           0 :                 return "66";
    1539             :             case LANGUAGE_HINDI:
    1540           0 :                 return "91";
    1541             : 
    1542             :             case LANGUAGE_ARABIC_PRIMARY_ONLY:
    1543             :             case LANGUAGE_ARABIC_IRAQ:
    1544             :             case LANGUAGE_ARABIC_EGYPT:
    1545             :             case LANGUAGE_ARABIC_LIBYA:
    1546             :             case LANGUAGE_ARABIC_ALGERIA:
    1547             :             case LANGUAGE_ARABIC_MOROCCO:
    1548             :             case LANGUAGE_ARABIC_TUNISIA:
    1549             :             case LANGUAGE_ARABIC_OMAN:
    1550             :             case LANGUAGE_ARABIC_YEMEN:
    1551             :             case LANGUAGE_ARABIC_SYRIA:
    1552             :             case LANGUAGE_ARABIC_JORDAN:
    1553             :             case LANGUAGE_ARABIC_LEBANON:
    1554             :             case LANGUAGE_ARABIC_KUWAIT:
    1555             :             case LANGUAGE_ARABIC_UAE:
    1556             :             case LANGUAGE_ARABIC_BAHRAIN:
    1557             :             case LANGUAGE_ARABIC_QATAR:
    1558           0 :                 return "96";
    1559             : 
    1560             :             case LANGUAGE_HEBREW:
    1561           0 :                 return "97";
    1562             : 
    1563             :             case LANGUAGE_CATALAN:
    1564           0 :                 return "37";
    1565             : 
    1566             :             default:
    1567           0 :                 return "99";
    1568             :         }
    1569             :     }
    1570           0 :     else if ( nPrio == 1 )
    1571             :     {
    1572           0 :         switch ( nType )
    1573             :         {
    1574             :             case LANGUAGE_FRENCH_CANADIAN:
    1575           0 :                 return "33";
    1576             : 
    1577             :             case LANGUAGE_PORTUGUESE_BRAZILIAN:
    1578           0 :                 return "03";
    1579             : 
    1580             :             default:
    1581           0 :                 return NULL;
    1582             :         }
    1583             :     }
    1584           0 :     else if ( nPrio == 2 )
    1585           0 :         return "01";
    1586           0 :     else if ( nPrio == 3 )
    1587           0 :         return "44";
    1588           0 :     else if ( nPrio == 4 )
    1589           0 :         return "49";
    1590             :     else
    1591           0 :         return "99";
    1592             : }
    1593             : 
    1594         368 : ResMgr* ResMgr::CreateResMgr( const sal_Char* pPrefixName,
    1595             :                               com::sun::star::lang::Locale aLocale )
    1596             : {
    1597         368 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1598             : 
    1599         368 :     OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
    1600             : 
    1601             :     /* FIXME-BCP47: handle language tags! */
    1602         368 :     if( aLocale.Language.isEmpty() )
    1603          99 :         aLocale = ResMgrContainer::get().getDefLocale();
    1604             : 
    1605         368 :     InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, aLocale );
    1606         368 :     return pImp ? new ResMgr( pImp ) : NULL;
    1607             : }
    1608             : 
    1609           8 : ResMgr* ResMgr::SearchCreateResMgr(
    1610             :     const sal_Char* pPrefixName,
    1611             :     com::sun::star::lang::Locale& rLocale )
    1612             : {
    1613           8 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1614             : 
    1615           8 :     OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
    1616             : 
    1617             :     /* FIXME-BCP47: handle language tags! */
    1618           8 :     if( rLocale.Language.isEmpty() )
    1619           0 :         rLocale = ResMgrContainer::get().getDefLocale();
    1620             : 
    1621           8 :     InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, rLocale );
    1622           8 :     return pImp ? new ResMgr( pImp ) : NULL;
    1623             : }
    1624             : 
    1625        1767 : sal_Int16 ResMgr::ReadShort()
    1626             : {
    1627        1767 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1628             : 
    1629        1767 :     if( pFallbackResMgr )
    1630           0 :         return pFallbackResMgr->ReadShort();
    1631             : 
    1632        1767 :     sal_Int16 n = GetShort( GetClass() );
    1633        1767 :     Increment( sizeof( sal_Int16 ) );
    1634        1767 :     return n;
    1635             : }
    1636             : 
    1637        7299 : sal_Int32 ResMgr::ReadLong()
    1638             : {
    1639        7299 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1640             : 
    1641        7299 :     if( pFallbackResMgr )
    1642           0 :         return pFallbackResMgr->ReadLong();
    1643             : 
    1644        7299 :     sal_Int32 n = GetLong( GetClass() );
    1645        7299 :     Increment( sizeof( sal_Int32 ) );
    1646        7299 :     return n;
    1647             : }
    1648             : 
    1649        2539 : UniString ResMgr::ReadStringWithoutHook()
    1650             : {
    1651        2539 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1652             : 
    1653        2539 :     if( pFallbackResMgr )
    1654           0 :         return pFallbackResMgr->ReadStringWithoutHook();
    1655             : 
    1656        2539 :     UniString aRet;
    1657             : 
    1658        2539 :     const ImpRCStack& rTop = aStack[nCurStack];
    1659        2539 :     if( (rTop.Flags & RC_NOTFOUND) )
    1660             :     {
    1661             :         #if OSL_DEBUG_LEVEL > 0
    1662             :         aRet = OUString( RTL_CONSTASCII_USTRINGPARAM( "<resource not found>" ) );
    1663             :         #endif
    1664             :     }
    1665             :     else
    1666        2539 :         Increment( GetStringWithoutHook( aRet, (const sal_uInt8*)GetClass() ) );
    1667             : 
    1668        2539 :     return aRet;
    1669             : }
    1670             : 
    1671        2539 : UniString ResMgr::ReadString()
    1672             : {
    1673        2539 :     UniString aRet = ReadStringWithoutHook();
    1674        2539 :     if ( pImplResHookProc )
    1675           0 :         aRet = pImplResHookProc( aRet );
    1676        2539 :     return aRet;
    1677             : }
    1678             : 
    1679         582 : rtl::OString ResMgr::ReadByteString()
    1680             : {
    1681         582 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1682             : 
    1683         582 :     if( pFallbackResMgr )
    1684           0 :         return pFallbackResMgr->ReadByteString();
    1685             : 
    1686         582 :     rtl::OString aRet;
    1687             : 
    1688         582 :     const ImpRCStack& rTop = aStack[nCurStack];
    1689         582 :     if( (rTop.Flags & RC_NOTFOUND) )
    1690             :     {
    1691             :         #if OSL_DEBUG_LEVEL > 0
    1692             :         aRet = OString( "<resource not found>" );
    1693             :         #endif
    1694             :     }
    1695             :     else
    1696         582 :         Increment( GetByteString( aRet, (const sal_uInt8*)GetClass() ) );
    1697             : 
    1698         582 :     return aRet;
    1699             : }
    1700             : 
    1701         712 : rtl::OString ResMgr::GetAutoHelpId()
    1702             : {
    1703         712 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1704             : 
    1705         712 :     if( pFallbackResMgr )
    1706           0 :         return pFallbackResMgr->GetAutoHelpId();
    1707             : 
    1708             :     OSL_ENSURE( nCurStack, "resource stack empty in Auto help id generation" );
    1709         712 :     if( nCurStack < 1 || nCurStack > 2 )
    1710           0 :         return rtl::OString();
    1711             : 
    1712             :     // prepare HID, start with resource prefix
    1713         712 :     rtl::OStringBuffer aHID( 32 );
    1714         712 :     aHID.append( rtl::OUStringToOString( pImpRes->aPrefix, RTL_TEXTENCODING_UTF8 ) );
    1715         712 :     aHID.append( '.' );
    1716             : 
    1717             :     // append type
    1718         712 :     const ImpRCStack *pRC = StackTop();
    1719             :     OSL_ENSURE( pRC, "missing resource stack level" );
    1720             : 
    1721         712 :     if ( nCurStack == 1 )
    1722             :     {
    1723             :         // auto help ids for top level windows
    1724         712 :         switch( pRC->pResource->GetRT() ) {
    1725           4 :             case RSC_DOCKINGWINDOW:     aHID.append( "DockingWindow" );    break;
    1726           0 :             case RSC_WORKWIN:           aHID.append( "WorkWindow" );       break;
    1727           0 :             case RSC_MODELESSDIALOG:    aHID.append( "ModelessDialog" );   break;
    1728           0 :             case RSC_FLOATINGWINDOW:    aHID.append( "FloatingWindow" );   break;
    1729           0 :             case RSC_MODALDIALOG:       aHID.append( "ModalDialog" );      break;
    1730           0 :             case RSC_TABPAGE:           aHID.append( "TabPage" );          break;
    1731         708 :             default: return rtl::OString();
    1732             :         }
    1733             :     }
    1734             :     else
    1735             :     {
    1736             :         // only controls with the following parents get auto help ids
    1737           0 :         const ImpRCStack *pRC1 = StackTop(1);
    1738           0 :         switch( pRC1->pResource->GetRT() ) {
    1739             :             case RSC_DOCKINGWINDOW:
    1740             :             case RSC_WORKWIN:
    1741             :             case RSC_MODELESSDIALOG:
    1742             :             case RSC_FLOATINGWINDOW:
    1743             :             case RSC_MODALDIALOG:
    1744             :             case RSC_TABPAGE:
    1745             :                 // intentionally no breaks!
    1746             :                 // auto help ids for controls
    1747           0 :                 switch( pRC->pResource->GetRT() ) {
    1748           0 :                     case RSC_TABCONTROL:        aHID.append( "TabControl" );       break;
    1749           0 :                     case RSC_RADIOBUTTON:       aHID.append( "RadioButton" );      break;
    1750           0 :                     case RSC_CHECKBOX:          aHID.append( "CheckBox" );         break;
    1751           0 :                     case RSC_TRISTATEBOX:       aHID.append( "TriStateBox" );      break;
    1752           0 :                     case RSC_EDIT:              aHID.append( "Edit" );             break;
    1753           0 :                     case RSC_MULTILINEEDIT:     aHID.append( "MultiLineEdit" );    break;
    1754           0 :                     case RSC_MULTILISTBOX:      aHID.append( "MultiListBox" );     break;
    1755           0 :                     case RSC_LISTBOX:           aHID.append( "ListBox" );          break;
    1756           0 :                     case RSC_COMBOBOX:          aHID.append( "ComboBox" );         break;
    1757           0 :                     case RSC_PUSHBUTTON:        aHID.append( "PushButton" );       break;
    1758           0 :                     case RSC_SPINFIELD:         aHID.append( "SpinField" );        break;
    1759           0 :                     case RSC_PATTERNFIELD:      aHID.append( "PatternField" );     break;
    1760           0 :                     case RSC_NUMERICFIELD:      aHID.append( "NumericField" );     break;
    1761           0 :                     case RSC_METRICFIELD:       aHID.append( "MetricField" );      break;
    1762           0 :                     case RSC_CURRENCYFIELD:     aHID.append( "CurrencyField" );    break;
    1763           0 :                     case RSC_DATEFIELD:         aHID.append( "DateField" );        break;
    1764           0 :                     case RSC_TIMEFIELD:         aHID.append( "TimeField" );        break;
    1765           0 :                     case RSC_IMAGERADIOBUTTON:  aHID.append( "ImageRadioButton" ); break;
    1766           0 :                     case RSC_NUMERICBOX:        aHID.append( "NumericBox" );       break;
    1767           0 :                     case RSC_METRICBOX:         aHID.append( "MetricBox" );        break;
    1768           0 :                     case RSC_CURRENCYBOX:       aHID.append( "CurrencyBox" );      break;
    1769           0 :                     case RSC_DATEBOX:           aHID.append( "DateBox" );          break;
    1770           0 :                     case RSC_TIMEBOX:           aHID.append( "TimeBox" );          break;
    1771           0 :                     case RSC_IMAGEBUTTON:       aHID.append( "ImageButton" );      break;
    1772           0 :                     case RSC_MENUBUTTON:        aHID.append( "MenuButton" );       break;
    1773           0 :                     case RSC_MOREBUTTON:        aHID.append( "MoreButton" );       break;
    1774             :                     default:
    1775             :                         // no type, no auto HID
    1776           0 :                         return rtl::OString();
    1777             :                 }
    1778           0 :                 break;
    1779             :             default:
    1780           0 :                 return rtl::OString();
    1781             :         }
    1782             :     }
    1783             : 
    1784             :     // append resource id hierarchy
    1785           8 :     for( int nOff = nCurStack-1; nOff >= 0; nOff-- )
    1786             :     {
    1787           4 :         aHID.append( '.' );
    1788           4 :         pRC = StackTop( nOff );
    1789             : 
    1790             :         OSL_ENSURE( pRC->pResource, "missing resource in resource stack level !" );
    1791           4 :         if( pRC->pResource )
    1792           4 :             aHID.append( sal_Int32( pRC->pResource->GetId() ) );
    1793             :     }
    1794             : 
    1795           4 :     return aHID.makeStringAndClear();
    1796             : }
    1797             : 
    1798           0 : void ResMgr::SetReadStringHook( ResHookProc pProc )
    1799             : {
    1800           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1801           0 :     pImplResHookProc = pProc;
    1802           0 : }
    1803             : 
    1804      133692 : ResHookProc ResMgr::GetReadStringHook()
    1805             : {
    1806      133692 :     return pImplResHookProc;
    1807             : }
    1808             : 
    1809         208 : void ResMgr::SetDefaultLocale( const com::sun::star::lang::Locale& rLocale )
    1810             : {
    1811         208 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1812         208 :     ResMgrContainer::get().setDefLocale( rLocale );
    1813         208 : }
    1814             : 
    1815           0 : const OUString& ResMgr::GetFileName() const
    1816             : {
    1817           0 :     return pImpRes->aFileName;
    1818             : }
    1819             : 
    1820           0 : SimpleResMgr::SimpleResMgr( const sal_Char* pPrefixName,
    1821           0 :                             const ::com::sun::star::lang::Locale& rLocale )
    1822             : {
    1823           0 :     OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
    1824           0 :     com::sun::star::lang::Locale aLocale( rLocale );
    1825             : 
    1826           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1827             :     /* FIXME-BCP47: handle language tags! */
    1828           0 :     if( aLocale.Language.isEmpty() )
    1829           0 :         aLocale = ResMgrContainer::get().getDefLocale();
    1830             : 
    1831           0 :     m_pResImpl = ResMgrContainer::get().getResMgr( aPrefix, aLocale, true );
    1832           0 :     DBG_ASSERT( m_pResImpl, "SimpleResMgr::SimpleResMgr : have no impl class !" );
    1833           0 : }
    1834             : 
    1835           0 : SimpleResMgr::~SimpleResMgr()
    1836             : {
    1837           0 :     delete m_pResImpl;
    1838           0 : }
    1839             : 
    1840           0 : SimpleResMgr* SimpleResMgr::Create( const sal_Char* pPrefixName, com::sun::star::lang::Locale aLocale )
    1841             : {
    1842           0 :     return new SimpleResMgr( pPrefixName, aLocale );
    1843             : }
    1844             : 
    1845           0 : bool SimpleResMgr::IsAvailable( RESOURCE_TYPE _resourceType, sal_uInt32 _resourceId )
    1846             : {
    1847           0 :     osl::MutexGuard aGuard(m_aAccessSafety);
    1848             : 
    1849           0 :     if ( ( RSC_STRING != _resourceType ) && ( RSC_RESOURCE != _resourceType ) )
    1850           0 :         return false;
    1851             : 
    1852             :     DBG_ASSERT( m_pResImpl, "SimpleResMgr::IsAvailable: have no impl class !" );
    1853           0 :     return m_pResImpl->IsGlobalAvailable( _resourceType, _resourceId );
    1854             : }
    1855             : 
    1856           0 : rtl::OUString SimpleResMgr::ReadString( sal_uInt32 nId )
    1857             : {
    1858           0 :     osl::MutexGuard aGuard(m_aAccessSafety);
    1859             : 
    1860             :     DBG_ASSERT( m_pResImpl, "SimpleResMgr::ReadString : have no impl class !" );
    1861             :     // perhaps constructed with an invalid filename ?
    1862             : 
    1863           0 :     UniString sReturn;
    1864           0 :     if ( !m_pResImpl )
    1865           0 :         return sReturn;
    1866             : 
    1867           0 :     void* pResHandle = NULL;
    1868           0 :     InternalResMgr* pFallback = m_pResImpl;
    1869           0 :     RSHEADER_TYPE* pResHeader = (RSHEADER_TYPE*)m_pResImpl->LoadGlobalRes( RSC_STRING, nId, &pResHandle );
    1870           0 :     if ( !pResHeader )
    1871             :     {
    1872           0 :         osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
    1873             : 
    1874             :         // try fallback
    1875           0 :         while( ! pResHandle && pFallback )
    1876             :         {
    1877           0 :             InternalResMgr* pOldFallback = pFallback;
    1878           0 :             pFallback = ResMgrContainer::get().getNextFallback( pFallback );
    1879           0 :             if( pOldFallback != m_pResImpl )
    1880           0 :                 ResMgrContainer::get().freeResMgr( pOldFallback );
    1881           0 :             if( pFallback )
    1882             :             {
    1883             :                 // handle possible recursion
    1884           0 :                 if( pFallback->aLocale.Language != m_pResImpl->aLocale.Language ||
    1885           0 :                     pFallback->aLocale.Country  != m_pResImpl->aLocale.Country  ||
    1886           0 :                     pFallback->aLocale.Variant  != m_pResImpl->aLocale.Variant )
    1887             :                 {
    1888           0 :                     pResHeader = (RSHEADER_TYPE*)pFallback->LoadGlobalRes( RSC_STRING, nId, &pResHandle );
    1889             :                 }
    1890             :                 else
    1891             :                 {
    1892           0 :                     ResMgrContainer::get().freeResMgr( pFallback );
    1893           0 :                     pFallback = NULL;
    1894             :                 }
    1895             :             }
    1896             :         }
    1897           0 :         if( ! pResHandle )
    1898             :             // no such resource
    1899           0 :             return sReturn;
    1900             :     }
    1901             : 
    1902             :     // sal_uIntPtr nLen = pResHeader->GetLocalOff() - sizeof(RSHEADER_TYPE);
    1903           0 :     ResMgr::GetString( sReturn, (const sal_uInt8*)(pResHeader+1) );
    1904             : 
    1905             :     // not neccessary with te current implementation which holds the string table permanently, but to be sure ....
    1906             :     // note: pFallback cannot be NULL here and is either the fallback or m_pResImpl
    1907           0 :     InternalResMgr::FreeGlobalRes( pResHeader, pResHandle );
    1908           0 :     if( m_pResImpl != pFallback )
    1909             :     {
    1910           0 :         osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
    1911             : 
    1912           0 :         ResMgrContainer::get().freeResMgr( pFallback );
    1913             :     }
    1914           0 :     return sReturn;
    1915             : }
    1916             : 
    1917             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10