LCOV - code coverage report
Current view: top level - tools/source/rc - resmgr.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 462 649 71.2 %
Date: 2014-11-03 Functions: 59 66 89.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <config_folders.h>
      21             : 
      22             : #include <sal/config.h>
      23             : 
      24             : #include <cassert>
      25             : 
      26             : #include <string.h>
      27             : #include <stdio.h>
      28             : #include <stdlib.h>
      29             : 
      30             : #include <tools/debug.hxx>
      31             : #include <tools/stream.hxx>
      32             : #include <tools/resmgr.hxx>
      33             : #include <tools/rc.hxx>
      34             : #include <tools/rcid.h>
      35             : #include <osl/endian.h>
      36             : #include <osl/process.h>
      37             : #include <osl/thread.h>
      38             : #include <osl/file.hxx>
      39             : #include <osl/mutex.hxx>
      40             : #include <osl/signal.h>
      41             : #include <rtl/ustrbuf.hxx>
      42             : #include <rtl/strbuf.hxx>
      43             : #include <sal/log.hxx>
      44             : #include <rtl/instance.hxx>
      45             : #include <rtl/bootstrap.hxx>
      46             : #include <i18nlangtag/languagetag.hxx>
      47             : #include <i18nlangtag/mslangid.hxx>
      48             : #include <tools/simplerm.hxx>
      49             : 
      50             : #include <functional>
      51             : #include <algorithm>
      52             : #include <boost/unordered_map.hpp>
      53             : #include <list>
      54             : #include <set>
      55             : 
      56             : 
      57             : using namespace osl;
      58             : 
      59             : // for thread safety
      60             : static osl::Mutex* pResMgrMutex = NULL;
      61             : 
      62     9468392 : static osl::Mutex& getResMgrMutex()
      63             : {
      64     9468392 :     if( !pResMgrMutex )
      65             :     {
      66         373 :         osl::Guard<osl::Mutex> aGuard( *osl::Mutex::getGlobalMutex() );
      67         373 :         if( ! pResMgrMutex )
      68         373 :             pResMgrMutex = new osl::Mutex();
      69             :     }
      70     9468392 :     return *pResMgrMutex;
      71             : }
      72             : 
      73             : struct ImpContent;
      74             : 
      75             : class InternalResMgr
      76             : {
      77             :     friend class ResMgr;
      78             :     friend class SimpleResMgr;
      79             :     friend class ResMgrContainer;
      80             : 
      81             :     ImpContent *                    pContent;
      82             :     sal_uInt32                      nOffCorrection;
      83             :     sal_uInt8 *                     pStringBlock;
      84             :     SvStream *                      pStm;
      85             :     bool                            bEqual2Content;
      86             :     sal_uInt32                      nEntries;
      87             :     OUString                        aFileName;
      88             :     OUString                        aPrefix;
      89             :     OUString                        aResName;
      90             :     bool                            bSingular;
      91             :     LanguageTag                     aLocale;
      92             :     boost::unordered_map<sal_uInt64, int>* pResUseDump;
      93             : 
      94             :                             InternalResMgr( const OUString& rFileURL,
      95             :                                             const OUString& aPrefix,
      96             :                                             const OUString& aResName,
      97             :                                             const LanguageTag& rLocale );
      98             :                             ~InternalResMgr();
      99             :     bool                    Create();
     100             : 
     101             :     bool                    IsGlobalAvailable( RESOURCE_TYPE nRT, sal_uInt32 nId ) const;
     102             :     void *                  LoadGlobalRes( RESOURCE_TYPE nRT, sal_uInt32 nId,
     103             :                                            void **pResHandle );
     104             : public:
     105             :     static void             FreeGlobalRes( void *, void * );
     106             : };
     107             : 
     108             : class ResMgrContainer
     109             : {
     110             :     static ResMgrContainer*     pOneInstance;
     111             : 
     112       20552 :     struct ContainerElement
     113             :     {
     114             :         InternalResMgr* pResMgr;
     115             :         OUString        aFileURL;
     116             :         int             nRefCount;
     117             :         int             nLoadCount;
     118             : 
     119       20888 :         ContainerElement() :
     120             :             pResMgr( NULL ),
     121             :             nRefCount( 0 ),
     122       20888 :             nLoadCount( 0 )
     123       20888 :             {}
     124             :     };
     125             : 
     126             :     boost::unordered_map< OUString, ContainerElement, OUStringHash> m_aResFiles;
     127             :     LanguageTag     m_aDefLocale;
     128             : 
     129         373 :     ResMgrContainer() : m_aDefLocale( LANGUAGE_SYSTEM) { init(); }
     130             :     ~ResMgrContainer();
     131             : 
     132             :     void init();
     133             : 
     134             : public:
     135             :     static ResMgrContainer& get();
     136             :     static void release();
     137             : 
     138             :     InternalResMgr* getResMgr( const OUString& rPrefix,
     139             :                                LanguageTag& rLocale,
     140             :                                bool bForceNewInstance = false
     141             :                                );
     142             :     InternalResMgr* getNextFallback( InternalResMgr* pResMgr );
     143             : 
     144             :     void freeResMgr( InternalResMgr* pResMgr );
     145             : 
     146        1389 :     void setDefLocale( const LanguageTag& rLocale )
     147        1389 :     { m_aDefLocale = rLocale; }
     148        1620 :     const LanguageTag& getDefLocale() const
     149        1620 :     { return m_aDefLocale; }
     150             : };
     151             : 
     152             : ResMgrContainer* ResMgrContainer::pOneInstance = NULL;
     153             : 
     154       12399 : ResMgrContainer& ResMgrContainer::get()
     155             : {
     156       12399 :     if( ! pOneInstance )
     157         373 :         pOneInstance = new ResMgrContainer();
     158       12399 :     return *pOneInstance;
     159             : }
     160             : 
     161         734 : ResMgrContainer::~ResMgrContainer()
     162             : {
     163       62757 :     for( boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it =
     164       42205 :             m_aResFiles.begin(); it != m_aResFiles.end(); ++it )
     165             :     {
     166             :         OSL_TRACE( "Resource file %s loaded %d times",
     167             :                          OUStringToOString( it->second.aFileURL, osl_getThreadTextEncoding() ).getStr(),
     168             :                          it->second.nLoadCount );
     169       20552 :         delete it->second.pResMgr;
     170             :     }
     171         367 : }
     172             : 
     173         367 : void ResMgrContainer::release()
     174             : {
     175         367 :     delete pOneInstance;
     176         367 :     pOneInstance = NULL;
     177         367 : }
     178             : 
     179         373 : void ResMgrContainer::init()
     180             : {
     181             :     assert( m_aResFiles.empty() );
     182             : 
     183             :     // get resource path
     184         373 :     OUString uri("$BRAND_BASE_DIR/" LIBO_SHARE_RESOURCE_FOLDER "/");
     185         373 :     rtl::Bootstrap::expandMacros(uri); //TODO: detect failure
     186             : 
     187             :     // collect all possible resource files
     188         746 :     Directory aDir( uri );
     189         373 :     if( aDir.open() == FileBase::E_None )
     190             :     {
     191         373 :         DirectoryItem aItem;
     192       21634 :         while( aDir.getNextItem( aItem ) == FileBase::E_None )
     193             :         {
     194       20888 :             FileStatus aStatus(osl_FileStatus_Mask_FileName);
     195       20888 :             if( aItem.getFileStatus( aStatus ) == FileBase::E_None )
     196             :             {
     197       20888 :                 OUString aFileName = aStatus.getFileName();
     198       20888 :                 if( ! aFileName.endsWithIgnoreAsciiCase( ".res" ) )
     199           0 :                     continue;
     200       41776 :                 OUString aResName = aFileName.copy( 0, aFileName.getLength() - strlen(".res") );
     201       20888 :                 if( aResName.isEmpty() )
     202           0 :                     continue;
     203             :                 assert( m_aResFiles.find( aResName ) == m_aResFiles.end() );
     204       20888 :                 m_aResFiles[ aResName ].aFileURL = uri + aFileName;
     205             :                 SAL_INFO(
     206             :                     "tools.rc",
     207             :                     "ResMgrContainer: " << aResName << " -> "
     208       20888 :                         << m_aResFiles[ aResName ].aFileURL );
     209             :             }
     210       21261 :         }
     211             :     }
     212             :     else
     213             :         SAL_WARN( "tools.rc", "opening dir " << uri << " failed" );
     214             : 
     215             :     // set default language
     216         373 :     LanguageType nLang = MsLangId::getSystemUILanguage();
     217         746 :     m_aDefLocale.reset( nLang);
     218         373 : }
     219             : 
     220             : namespace
     221             : {
     222        4230 :     bool isAlreadyPureenUS(const LanguageTag &rLocale)
     223             :     {
     224        4230 :         return ( rLocale.getLanguageType() == LANGUAGE_ENGLISH_US );
     225             :     }
     226             : }
     227             : 
     228        4230 : InternalResMgr* ResMgrContainer::getResMgr( const OUString& rPrefix,
     229             :                                             LanguageTag& rLocale,
     230             :                                             bool bForceNewInstance
     231             :                                             )
     232             : {
     233        4230 :     LanguageTag aLocale( rLocale );
     234        4230 :     boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it = m_aResFiles.end();
     235             : 
     236        8460 :     ::std::vector< OUString > aFallbacks( aLocale.getFallbackStrings( true));
     237        4230 :     if (!isAlreadyPureenUS( aLocale))
     238           0 :         aFallbacks.push_back( "en-US");     // last resort if all fallbacks fail
     239             : 
     240        4230 :     for (::std::vector< OUString >::const_iterator fb( aFallbacks.begin()); fb != aFallbacks.end(); ++fb)
     241             :     {
     242        4230 :         OUString aSearch( rPrefix + *fb );
     243        4230 :         it = m_aResFiles.find( aSearch );
     244        4230 :         if( it != m_aResFiles.end() )
     245             :         {
     246             :             // ensure InternalResMgr existence
     247        4230 :             if( ! it->second.pResMgr )
     248             :             {
     249             :                 InternalResMgr* pImp =
     250        2939 :                     new InternalResMgr( it->second.aFileURL, rPrefix, it->first, aLocale );
     251        2939 :                 if( ! pImp->Create() )
     252             :                 {
     253           0 :                     delete pImp;
     254           0 :                     continue;
     255             :                 }
     256        2939 :                 it->second.pResMgr = pImp;
     257             :             }
     258        4230 :             break;
     259             :         }
     260           0 :     }
     261             :     // try if there is anything with this prefix at all
     262        4230 :     if( it == m_aResFiles.end() )
     263             :     {
     264           0 :         aLocale.reset( LANGUAGE_SYSTEM);
     265           0 :         it = m_aResFiles.find( rPrefix );
     266           0 :         if( it == m_aResFiles.end() )
     267             :         {
     268           0 :             for( it = m_aResFiles.begin(); it != m_aResFiles.end(); ++it )
     269             :             {
     270           0 :                 if( it->first.matchIgnoreAsciiCase( rPrefix ) )
     271             :                 {
     272             :                     // ensure InternalResMgr existence
     273           0 :                     if( ! it->second.pResMgr )
     274             :                     {
     275             :                         InternalResMgr* pImp =
     276           0 :                             new InternalResMgr( it->second.aFileURL,
     277             :                                                 rPrefix,
     278           0 :                                                 it->first,
     279           0 :                                                 aLocale );
     280           0 :                         if( ! pImp->Create() )
     281             :                         {
     282           0 :                             delete pImp;
     283           0 :                             continue;
     284             :                         }
     285           0 :                         it->second.pResMgr = pImp;
     286             :                     }
     287             :                     // try to guess locale
     288           0 :                     sal_Int32 nIndex = rPrefix.getLength();
     289           0 :                     if (nIndex < it->first.getLength())
     290           0 :                         aLocale.reset( it->first.copy( nIndex));
     291             :                     else
     292             :                     {
     293             :                         SAL_WARN( "tools.rc", "ResMgrContainer::getResMgr: it->first " <<
     294             :                                 it->first << " shorter than prefix " << rPrefix);
     295             :                     }
     296           0 :                     break;
     297             :                 }
     298             :             }
     299             :         }
     300             :     }
     301             :     // give up
     302        4230 :     if( it == m_aResFiles.end() )
     303             :     {
     304           0 :         OUString sURL = rPrefix + rLocale.getBcp47() + ".res";
     305           0 :         if ( m_aResFiles.find(sURL) == m_aResFiles.end() )
     306             :         {
     307           0 :             m_aResFiles[ sURL ].aFileURL = sURL;
     308           0 :             return getResMgr(rPrefix,rLocale,bForceNewInstance);
     309             :         } // if ( m_aResFiles.find(sURL) == m_aResFiles.end() )
     310           0 :         return NULL;
     311             :     }
     312             : 
     313        4230 :     rLocale = aLocale;
     314             :     // at this point it->second.pResMgr must be filled either by creating a new one
     315             :     // (then the refcount is still 0) or because we already had one
     316        4230 :     InternalResMgr* pImp = it->second.pResMgr;
     317             : 
     318        4230 :     if( it->second.nRefCount == 0 )
     319        2939 :         it->second.nLoadCount++;
     320             : 
     321             :     // for SimpleResMgr
     322        4230 :     if( bForceNewInstance )
     323             :     {
     324          15 :         if( it->second.nRefCount == 0 )
     325             :         {
     326             :             // shortcut: the match algorithm already created the InternalResMgr
     327             :             // take it instead of creating yet another one
     328          15 :             it->second.pResMgr = NULL;
     329          15 :             pImp->bSingular = true;
     330             :         }
     331             :         else
     332             :         {
     333           0 :             pImp = new InternalResMgr( it->second.aFileURL, rPrefix, it->first, aLocale );
     334           0 :             pImp->bSingular = true;
     335           0 :             if( !pImp->Create() )
     336             :             {
     337           0 :                 delete pImp;
     338           0 :                 pImp = NULL;
     339             :             }
     340             :             else
     341           0 :                 it->second.nLoadCount++;
     342             :         }
     343             :     }
     344             :     else
     345        4215 :         it->second.nRefCount++;
     346             : 
     347        8460 :     return pImp;
     348             : }
     349             : 
     350           0 : InternalResMgr* ResMgrContainer::getNextFallback( InternalResMgr* pMgr )
     351             : {
     352             :     /* TODO-BCP47: this is nasty, but the previous code simply stripped a
     353             :      * locale's variant and country in subsequent calls to end up with language
     354             :      * only and then fallback to en-US if all failed, so this is at least
     355             :      * equivalent if not better. Maybe this method could be changed to get
     356             :      * passed / remember a fallback list and an index within to pick the next.
     357             :      * */
     358             : 
     359           0 :     ::std::vector< OUString > aFallbacks( pMgr->aLocale.getFallbackStrings( true));
     360             :     // The first is the locale itself, use next fallback or en-US.
     361             :     /* TODO: what happens if the chain is "en-US", "en" -> "en-US", ...
     362             :      * This was already an issue with the previous code. */
     363           0 :     LanguageTag aLocale( ((aFallbacks.size() > 1) ? aFallbacks[1] : OUString( "en-US")));
     364           0 :     InternalResMgr* pNext = getResMgr( pMgr->aPrefix, aLocale, pMgr->bSingular );
     365             :     // prevent recursion
     366           0 :     if( pNext == pMgr || ( pNext && pNext->aResName.equals( pMgr->aResName ) ) )
     367             :     {
     368           0 :         if( pNext->bSingular )
     369           0 :             delete pNext;
     370           0 :         pNext = NULL;
     371             :     }
     372           0 :     return pNext;
     373             : }
     374             : 
     375        2221 : void ResMgrContainer::freeResMgr( InternalResMgr* pResMgr )
     376             : {
     377        2221 :     if( pResMgr->bSingular )
     378           0 :         delete pResMgr;
     379             :     else
     380             :     {
     381             :         boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it =
     382        2221 :         m_aResFiles.find( pResMgr->aResName );
     383        2221 :         if( it != m_aResFiles.end() )
     384             :         {
     385             :             DBG_ASSERT( it->second.nRefCount > 0, "InternalResMgr freed too often" );
     386        2221 :             if( it->second.nRefCount > 0 )
     387        2221 :                 it->second.nRefCount--;
     388        2221 :             if( it->second.nRefCount == 0 )
     389             :             {
     390        1429 :                 delete it->second.pResMgr;
     391        1429 :                 it->second.pResMgr = NULL;
     392             :             }
     393             :         }
     394             :     }
     395        2221 : }
     396             : 
     397             : #ifdef DBG_UTIL
     398             : void Resource::TestRes()
     399             : {
     400             :     if( m_pResMgr )
     401             :         m_pResMgr->TestStack( this );
     402             : }
     403             : #endif
     404             : 
     405             : struct ImpContent
     406             : {
     407             :     sal_uInt64   nTypeAndId;
     408             :     sal_uInt32   nOffset;
     409             : };
     410             : 
     411             : struct ImpContentLessCompare : public ::std::binary_function< ImpContent, ImpContent, bool>
     412             : {
     413    16885968 :     inline bool operator() (const ImpContent& lhs, const ImpContent& rhs) const
     414             :     {
     415    16885968 :         return lhs.nTypeAndId < rhs.nTypeAndId;
     416             :     }
     417             : };
     418             : 
     419             : static ResHookProc pImplResHookProc = 0;
     420             : 
     421        2939 : InternalResMgr::InternalResMgr( const OUString& rFileURL,
     422             :                                 const OUString& rPrefix,
     423             :                                 const OUString& rResName,
     424             :                                 const LanguageTag& rLocale )
     425             :     : pContent( NULL )
     426             :     , nOffCorrection( 0 )
     427             :     , pStringBlock( NULL )
     428             :     , pStm( NULL )
     429             :     , bEqual2Content( true )
     430             :     , nEntries( 0 )
     431             :     , aFileName( rFileURL )
     432             :     , aPrefix( rPrefix )
     433             :     , aResName( rResName )
     434             :     , bSingular( false )
     435             :     , aLocale( rLocale )
     436        2939 :     , pResUseDump( 0 )
     437             : {
     438        2939 : }
     439             : 
     440        5790 : InternalResMgr::~InternalResMgr()
     441             : {
     442        2895 :     rtl_freeMemory(pContent);
     443        2895 :     rtl_freeMemory(pStringBlock);
     444        2895 :     delete pStm;
     445             : 
     446             : #ifdef DBG_UTIL
     447             :     if( pResUseDump )
     448             :     {
     449             :         const sal_Char* pLogFile = getenv( "STAR_RESOURCE_LOGGING" );
     450             :         if ( pLogFile )
     451             :         {
     452             :             SvFileStream aStm( OUString::createFromAscii( pLogFile ), STREAM_WRITE );
     453             :             aStm.Seek( STREAM_SEEK_TO_END );
     454             :             OStringBuffer aLine("FileName: ");
     455             :             aLine.append(OUStringToOString(aFileName,
     456             :                 RTL_TEXTENCODING_UTF8));
     457             :             aStm.WriteLine(aLine.makeStringAndClear());
     458             : 
     459             :             for( boost::unordered_map<sal_uInt64, int>::const_iterator it = pResUseDump->begin();
     460             :                  it != pResUseDump->end(); ++it )
     461             :             {
     462             :                 sal_uInt64 nKeyId = it->first;
     463             :                 aLine.append("Type/Id: ");
     464             :                 aLine.append(sal::static_int_cast< sal_Int32 >((nKeyId >> 32) & 0xFFFFFFFF));
     465             :                 aLine.append('/');
     466             :                 aLine.append(sal::static_int_cast< sal_Int32 >(nKeyId & 0xFFFFFFFF));
     467             :                 aStm.WriteLine(aLine.makeStringAndClear());
     468             :             }
     469             :         }
     470             :     }
     471             : #endif
     472             : 
     473        2895 :     delete pResUseDump;
     474        2895 : }
     475             : 
     476        2939 : bool InternalResMgr::Create()
     477             : {
     478        2939 :     ResMgrContainer::get();
     479        2939 :     bool bDone = false;
     480             : 
     481        2939 :     pStm = new SvFileStream( aFileName, (STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE) );
     482        2939 :     if( pStm->GetError() == 0 )
     483             :     {
     484        2939 :         sal_Int32   lContLen = 0;
     485             : 
     486        2939 :         pStm->Seek( STREAM_SEEK_TO_END );
     487             :         /*
     488             :         if( ( pInternalResMgr->pHead = (RSHEADER_TYPE *)mmap( 0, nResourceFileSize,
     489             :                                                         PROT_READ, MAP_PRIVATE,
     490             :                                                         fRes, 0 ) ) != (RSHEADER_TYPE *)-1)
     491             :                                                         */
     492        2939 :         pStm->SeekRel( - (int)sizeof( lContLen ) );
     493        2939 :         pStm->Read( &lContLen, sizeof( lContLen ) );
     494             :         // is bigendian, swab to the right endian
     495        2939 :         lContLen = ResMgr::GetLong( &lContLen );
     496        2939 :         pStm->SeekRel( -lContLen );
     497             :         // allocate stored ImpContent data (12 bytes per unit)
     498        2939 :         sal_uInt8* pContentBuf = (sal_uInt8*)rtl_allocateMemory( lContLen );
     499        2939 :         pStm->Read( pContentBuf, lContLen );
     500             :         // allocate ImpContent space (sizeof(ImpContent) per unit, not necessarily 12)
     501        2939 :         pContent = (ImpContent *)rtl_allocateMemory( sizeof(ImpContent)*lContLen/12 );
     502             :         // Shorten to number of ImpContent
     503        2939 :         nEntries = (sal_uInt32)lContLen / 12;
     504        2939 :         bEqual2Content = true;
     505        2939 :         bool bSorted = true;
     506        2939 :         if( nEntries )
     507             :         {
     508             : #ifdef DBG_UTIL
     509             :             const sal_Char* pLogFile = getenv( "STAR_RESOURCE_LOGGING" );
     510             :             if ( pLogFile )
     511             :             {
     512             :                 pResUseDump = new boost::unordered_map<sal_uInt64, int>;
     513             :                 for( sal_uInt32 i = 0; i < nEntries; ++i )
     514             :                     (*pResUseDump)[pContent[i].nTypeAndId] = 1;
     515             :             }
     516             : #endif
     517             :             // swap the content to the right endian
     518        2939 :             pContent[0].nTypeAndId = ResMgr::GetUInt64( pContentBuf );
     519        2939 :             pContent[0].nOffset = ResMgr::GetLong( pContentBuf+8 );
     520        2939 :             sal_uInt32 nCount = nEntries - 1;
     521      803627 :             for( sal_uInt32 i = 0,j=1; i < nCount; ++i,++j )
     522             :             {
     523             :                 // swap the content to the right endian
     524      800688 :                 pContent[j].nTypeAndId = ResMgr::GetUInt64( pContentBuf + (12*j) );
     525      800688 :                 pContent[j].nOffset = ResMgr::GetLong( pContentBuf + (12*j+8) );
     526      800688 :                 if( pContent[i].nTypeAndId >= pContent[j].nTypeAndId )
     527           0 :                     bSorted = false;
     528      800688 :                 if( (pContent[i].nTypeAndId & 0xFFFFFFFF00000000LL) == (pContent[j].nTypeAndId & 0xFFFFFFFF00000000LL)
     529      783433 :                     && pContent[i].nOffset >= pContent[j].nOffset )
     530           0 :                     bEqual2Content = false;
     531             :             }
     532             :         }
     533        2939 :         rtl_freeMemory( pContentBuf );
     534             :         OSL_ENSURE( bSorted, "content not sorted" );
     535             :         OSL_ENSURE( bEqual2Content, "resource structure wrong" );
     536        2939 :         if( !bSorted )
     537           0 :             ::std::sort(pContent,pContent+nEntries,ImpContentLessCompare());
     538             :             //  qsort( pContent, nEntries, sizeof( ImpContent ), Compare );
     539             : 
     540        2939 :         bDone = true;
     541             :     }
     542             : 
     543        2939 :     return bDone;
     544             : }
     545             : 
     546             : 
     547       18970 : bool InternalResMgr::IsGlobalAvailable( RESOURCE_TYPE nRT, sal_uInt32 nId ) const
     548             : {
     549             :     // Anfang der Strings suchen
     550             :     ImpContent aValue;
     551       18970 :     aValue.nTypeAndId = ((sal_uInt64(nRT) << 32) | nId);
     552             :     ImpContent * pFind = ::std::lower_bound(pContent,
     553             :                                             pContent + nEntries,
     554             :                                             aValue,
     555       18970 :                                             ImpContentLessCompare());
     556       18970 :     return (pFind != (pContent + nEntries)) && (pFind->nTypeAndId == aValue.nTypeAndId);
     557             : }
     558             : 
     559             : 
     560     1691387 : void* InternalResMgr::LoadGlobalRes( RESOURCE_TYPE nRT, sal_uInt32 nId,
     561             :                                      void **pResHandle )
     562             : {
     563             : #ifdef DBG_UTIL
     564             :     if( pResUseDump )
     565             :         pResUseDump->erase( (sal_uInt64(nRT) << 32) | nId );
     566             : #endif
     567             :     // search beginning of string
     568             :     ImpContent aValue;
     569     1691387 :     aValue.nTypeAndId = ((sal_uInt64(nRT) << 32) | nId);
     570     1691387 :     ImpContent* pEnd = (pContent + nEntries);
     571             :     ImpContent* pFind = ::std::lower_bound( pContent,
     572             :                                             pEnd,
     573             :                                             aValue,
     574     1691387 :                                             ImpContentLessCompare());
     575     1691387 :     if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == aValue.nTypeAndId) )
     576             :     {
     577     1691387 :         if( nRT == RSC_STRING && bEqual2Content )
     578             :         {
     579             :             // string optimization
     580     1589931 :             if( !pStringBlock )
     581             :             {
     582             :                 // search beginning of string
     583        1912 :                 ImpContent * pFirst = pFind;
     584        1912 :                 ImpContent * pLast = pFirst;
     585      350928 :                 while( pFirst > pContent && ((pFirst -1)->nTypeAndId >> 32) == RSC_STRING )
     586      347104 :                     --pFirst;
     587      295759 :                 while( pLast < pEnd && (pLast->nTypeAndId >> 32) == RSC_STRING )
     588      291935 :                     ++pLast;
     589        1912 :                 nOffCorrection = pFirst->nOffset;
     590             :                 sal_uInt32 nSize;
     591        1912 :                 --pLast;
     592        1912 :                 pStm->Seek( pLast->nOffset );
     593             :                 RSHEADER_TYPE aHdr;
     594        1912 :                 pStm->Read( &aHdr, sizeof( aHdr ) );
     595        1912 :                 nSize = pLast->nOffset + aHdr.GetGlobOff() - nOffCorrection;
     596        1912 :                 pStringBlock = (sal_uInt8*)rtl_allocateMemory( nSize );
     597        1912 :                 pStm->Seek( pFirst->nOffset );
     598        1912 :                 pStm->Read( pStringBlock, nSize );
     599             :             }
     600     1589931 :             *pResHandle = pStringBlock;
     601     1589931 :             return (sal_uInt8*)pStringBlock + pFind->nOffset - nOffCorrection;
     602             :         } // if( nRT == RSC_STRING && bEqual2Content )
     603             :         else
     604             :         {
     605      101456 :             *pResHandle = 0;
     606             :             RSHEADER_TYPE aHeader;
     607      101456 :             pStm->Seek( pFind->nOffset );
     608      101456 :             pStm->Read( &aHeader, sizeof( RSHEADER_TYPE ) );
     609      101456 :             void * pRes = rtl_allocateMemory( aHeader.GetGlobOff() );
     610      101456 :             memcpy( pRes, &aHeader, sizeof( RSHEADER_TYPE ) );
     611      101456 :             pStm->Read( (sal_uInt8*)pRes + sizeof( RSHEADER_TYPE ),
     612      202912 :                         aHeader.GetGlobOff() - sizeof( RSHEADER_TYPE ) );
     613      101456 :             return pRes;
     614             :         }
     615             :     } // if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == nValue) )
     616           0 :     *pResHandle = 0;
     617           0 :     return NULL;
     618             : }
     619             : 
     620     1691387 : void InternalResMgr::FreeGlobalRes( void * pResHandle, void * pResource )
     621             : {
     622     1691387 :     if ( !pResHandle )
     623             :         // Free allocated resource
     624      101456 :         rtl_freeMemory(pResource);
     625     1691387 : }
     626             : 
     627             : #ifdef DBG_UTIL
     628             : 
     629             : OUString GetTypeRes_Impl( const ResId& rTypeId )
     630             : {
     631             :     // Return on resource errors
     632             :     static bool bInUse = false;
     633             :     OUString aTypStr(OUString::number(rTypeId.GetId()));
     634             : 
     635             :     if ( !bInUse )
     636             :     {
     637             :         bInUse = true;
     638             : 
     639             :         ResId aResId( sal_uInt32(RSCVERSION_ID), *rTypeId.GetResMgr() );
     640             :         aResId.SetRT( RSC_VERSIONCONTROL );
     641             : 
     642             :         if ( rTypeId.GetResMgr()->GetResource( aResId ) )
     643             :         {
     644             :             rTypeId.SetRT( RSC_STRING );
     645             :             if ( rTypeId.GetResMgr()->IsAvailable( rTypeId ) )
     646             :             {
     647             :                 aTypStr = rTypeId.toString();
     648             :                 // Set class pointer to the end
     649             :                 rTypeId.GetResMgr()->Increment( sizeof( RSHEADER_TYPE ) );
     650             :             }
     651             :         }
     652             :         bInUse = false;
     653             :     }
     654             : 
     655             :     return aTypStr;
     656             : }
     657             : 
     658             : void ResMgr::RscError_Impl( const sal_Char* pMessage, ResMgr* pResMgr,
     659             :                             RESOURCE_TYPE nRT, sal_uInt32 nId,
     660             :                             std::vector< ImpRCStack >& rResStack, int nDepth )
     661             : {
     662             :     // create a separate ResMgr with its own stack
     663             :     // first get a second reference of the InternalResMgr
     664             :     InternalResMgr* pImp =
     665             :         ResMgrContainer::get().getResMgr( pResMgr->pImpRes->aPrefix,
     666             :                                           pResMgr->pImpRes->aLocale,
     667             :                                           true );
     668             : 
     669             :     ResMgr* pNewResMgr = new ResMgr( pImp );
     670             : 
     671             :     OStringBuffer aStr(OUStringToOString(pResMgr->GetFileName(),
     672             :         RTL_TEXTENCODING_UTF8));
     673             : 
     674             :     if (aStr.getLength())
     675             :         aStr.append('\n');
     676             : 
     677             :     aStr.append("Class: ");
     678             :     aStr.append(OUStringToOString(GetTypeRes_Impl(ResId(nRT, *pNewResMgr)),
     679             :         RTL_TEXTENCODING_UTF8));
     680             :     aStr.append(", Id: ");
     681             :     aStr.append(static_cast<sal_Int32>(nId));
     682             :     aStr.append(". ");
     683             :     aStr.append(pMessage);
     684             : 
     685             :     aStr.append("\nResource Stack\n");
     686             :     while( nDepth > 0 )
     687             :     {
     688             :         aStr.append("Class: ");
     689             :         aStr.append(OUStringToOString(GetTypeRes_Impl(
     690             :             ResId(rResStack[nDepth].pResource->GetRT(), *pNewResMgr)),
     691             :             RTL_TEXTENCODING_UTF8));
     692             :         aStr.append(", Id: ");
     693             :         aStr.append(static_cast<sal_Int32>(
     694             :             rResStack[nDepth].pResource->GetId()));
     695             :         nDepth--;
     696             :     }
     697             : 
     698             :     // clean up
     699             :     delete pNewResMgr;
     700             : 
     701             :     OSL_FAIL(aStr.getStr());
     702             : }
     703             : 
     704             : #endif
     705             : 
     706           0 : static void RscException_Impl()
     707             : {
     708           0 :     switch ( osl_raiseSignal( OSL_SIGNAL_USER_RESOURCEFAILURE, (void*)"" ) )
     709             :     {
     710             :     case osl_Signal_ActCallNextHdl:
     711           0 :         abort();
     712             : 
     713             :     case osl_Signal_ActIgnore:
     714           0 :         return;
     715             : 
     716             :     case osl_Signal_ActAbortApp:
     717           0 :         abort();
     718             : 
     719             :     default:
     720             :     case osl_Signal_ActKillApp:
     721           0 :         exit(-1);
     722             :     }
     723             : }
     724             : 
     725     1897605 : void ImpRCStack::Init( ResMgr* pMgr, const Resource* pObj, sal_uInt32 Id )
     726             : {
     727     1897605 :     pResource       = NULL;
     728     1897605 :     pClassRes       = NULL;
     729     1897605 :     Flags           = RC_NOTYPE;
     730     1897605 :     aResHandle      = NULL;
     731     1897605 :     pResObj         = pObj;
     732     1897605 :     nId             = Id & ~RSC_DONTRELEASE; //TLX: Besser Init aendern
     733     1897605 :     pResMgr         = pMgr;
     734     1897605 :     if ( !(Id & RSC_DONTRELEASE) )
     735     1897605 :         Flags      |= RC_AUTORELEASE;
     736     1897605 : }
     737             : 
     738     1901820 : void ImpRCStack::Clear()
     739             : {
     740     1901820 :     pResource       = NULL;
     741     1901820 :     pClassRes       = NULL;
     742     1901820 :     Flags           = RC_NOTYPE;
     743     1901820 :     aResHandle      = NULL;
     744     1901820 :     pResObj         = NULL;
     745     1901820 :     nId             = 0;
     746     1901820 :     pResMgr         = NULL;
     747     1901820 : }
     748             : 
     749     1920231 : static RSHEADER_TYPE* LocalResource( const ImpRCStack* pStack,
     750             :                                      RESOURCE_TYPE nRTType,
     751             :                                      sal_uInt32 nId )
     752             : {
     753             :     // Returns position of the resource if found or NULL otherwise
     754             :     RSHEADER_TYPE*  pTmp;   // Pointer to child resource
     755             :     RSHEADER_TYPE*  pEnd;   // Pointer to the end of this resource
     756             : 
     757     1920231 :     if ( pStack->pResource && pStack->pClassRes )
     758             :     {
     759             :         pTmp = (RSHEADER_TYPE*)
     760      226224 :                ((sal_uInt8*)pStack->pResource + pStack->pResource->GetLocalOff());
     761             :         pEnd = (RSHEADER_TYPE*)
     762      226224 :                ((sal_uInt8*)pStack->pResource + pStack->pResource->GetGlobOff());
     763    32741546 :         while ( pTmp != pEnd )
     764             :         {
     765    32499468 :             if ( pTmp->GetRT() == nRTType && pTmp->GetId() == nId )
     766      210370 :                 return pTmp;
     767    32289098 :             pTmp = (RSHEADER_TYPE*)((sal_uInt8*)pTmp + pTmp->GetGlobOff());
     768             :         }
     769             :     }
     770             : 
     771     1709861 :     return NULL;
     772             : }
     773             : 
     774             : void* ResMgr::pEmptyBuffer = NULL;
     775             : 
     776           0 : void* ResMgr::getEmptyBuffer()
     777             : {
     778           0 :     if( ! pEmptyBuffer )
     779           0 :         pEmptyBuffer = rtl_allocateZeroMemory( 1024 );
     780           0 :     return pEmptyBuffer;
     781             : }
     782             : 
     783         367 : void ResMgr::DestroyAllResMgr()
     784             : {
     785             :     {
     786         367 :         osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     787         367 :         if( pEmptyBuffer )
     788             :         {
     789           0 :             rtl_freeMemory( pEmptyBuffer );
     790           0 :             pEmptyBuffer = NULL;
     791             :         }
     792         367 :         ResMgrContainer::release();
     793             :     }
     794         367 :     delete pResMgrMutex;
     795         367 :     pResMgrMutex = NULL;
     796         367 : }
     797             : 
     798        4215 : void ResMgr::Init( const OUString& rFileName )
     799             : {
     800             :     (void) rFileName; // avoid warning about unused parameter
     801        4215 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     802             : 
     803        4215 :     if ( !pImpRes )
     804             :     {
     805             : #ifdef DBG_UTIL
     806             :         OStringBuffer aStr("Resourcefile not found:\n");
     807             :         aStr.append(OUStringToOString(rFileName, RTL_TEXTENCODING_UTF8));
     808             :         OSL_FAIL(aStr.getStr());
     809             : #endif
     810           0 :         RscException_Impl();
     811             :     }
     812             : #ifdef DBG_UTIL
     813             :     else
     814             :     {
     815             :         void* aResHandle = 0;     // Helper variable for resource handles
     816             :         void* pVoid;              // Pointer on the resource
     817             : 
     818             :         pVoid = pImpRes->LoadGlobalRes( RSC_VERSIONCONTROL, RSCVERSION_ID,
     819             :                                         &aResHandle );
     820             :         if ( pVoid )
     821             :             InternalResMgr::FreeGlobalRes( aResHandle, pVoid );
     822             :         else
     823             :         {
     824             :             SAL_WARN("tools.rc", "Wrong version: " << pImpRes->aFileName);
     825             :         }
     826             :     }
     827             : #endif
     828        4215 :     nCurStack = -1;
     829        4215 :     aStack.clear();
     830        4215 :     pFallbackResMgr = pOriginalResMgr = NULL;
     831        4215 :     incStack();
     832        4215 : }
     833             : 
     834        4215 : ResMgr::ResMgr( InternalResMgr * pImpMgr )
     835             : {
     836        4215 :     pImpRes = pImpMgr;
     837        4215 :     Init( pImpMgr->aFileName );
     838        4215 : }
     839             : 
     840        4442 : ResMgr::~ResMgr()
     841             : {
     842        2221 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     843             : 
     844        2221 :     ResMgrContainer::get().freeResMgr( pImpRes );
     845             : 
     846             :     // clean up possible left rc stack frames
     847        4442 :     while( nCurStack > 0 )
     848             :     {
     849           0 :         if( ( aStack[nCurStack].Flags & (RC_GLOBAL | RC_NOTFOUND) ) == RC_GLOBAL )
     850           0 :             InternalResMgr::FreeGlobalRes( aStack[nCurStack].aResHandle,
     851           0 :                                     aStack[nCurStack].pResource );
     852           0 :         nCurStack--;
     853        2221 :     }
     854        2221 : }
     855             : 
     856     1901820 : void ResMgr::incStack()
     857             : {
     858     1901820 :     nCurStack++;
     859     1901820 :     if( nCurStack >= int(aStack.size()) )
     860        7181 :         aStack.push_back( ImpRCStack() );
     861     1901820 :     aStack[nCurStack].Clear();
     862             : 
     863             :     DBG_ASSERT( nCurStack < 32, "Resource stack unreasonably large" );
     864     1901820 : }
     865             : 
     866     1897605 : void ResMgr::decStack()
     867             : {
     868             :     DBG_ASSERT( nCurStack > 0, "resource stack underrun  !" );
     869     1897605 :     if( (aStack[nCurStack].Flags & RC_FALLBACK_UP) )
     870             :     {
     871           0 :         nCurStack--;
     872             :         // warning: this will delete *this, see below
     873           0 :         pOriginalResMgr->decStack();
     874             :     }
     875             :     else
     876             :     {
     877     1897605 :         ImpRCStack& rTop = aStack[nCurStack];
     878     1897605 :         if( (rTop.Flags & RC_FALLBACK_DOWN) )
     879             :         {
     880             :             #if OSL_DEBUG_LEVEL > 1
     881             :             OSL_TRACE( "returning from fallback %s",
     882             :                      OUStringToOString(pFallbackResMgr->GetFileName(), osl_getThreadTextEncoding() ).getStr() );
     883             :             #endif
     884           0 :             delete pFallbackResMgr;
     885           0 :             pFallbackResMgr = NULL;
     886             :         }
     887     1897605 :         nCurStack--;
     888             :     }
     889     1897605 : }
     890             : 
     891             : #ifdef DBG_UTIL
     892             : 
     893             : void ResMgr::TestStack( const Resource* pResObj )
     894             : {
     895             :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     896             : 
     897             :     int upperLimit = nCurStack;
     898             : 
     899             :     if ( upperLimit < 0 )
     900             :     {
     901             :         OSL_FAIL( "resource stack underrun!" );
     902             :         upperLimit = aStack.size() - 1;
     903             :     }
     904             :     else if ( upperLimit >=  static_cast<int>(aStack.size()) )
     905             :     {
     906             :         OSL_FAIL( "stack occupation index > allocated stack size" );
     907             :         upperLimit = aStack.size() - 1;
     908             :     }
     909             : 
     910             :     if ( DbgIsResource() )
     911             :     {
     912             :         for( int i = 1; i <= upperLimit; ++i )
     913             :         {
     914             :             if ( aStack[i].pResObj == pResObj )
     915             :             {
     916             :                 RscError_Impl( "Resource not freed! ", this,
     917             :                                aStack[i].pResource->GetRT(),
     918             :                                aStack[i].pResource->GetId(),
     919             :                                aStack, i-1 );
     920             :             }
     921             :         }
     922             :     }
     923             : }
     924             : 
     925             : #endif
     926             : 
     927      102552 : bool ResMgr::IsAvailable( const ResId& rId, const Resource* pResObj ) const
     928             : {
     929      102552 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     930             : 
     931      102552 :     bool            bAvailable = false;
     932      102552 :     RSHEADER_TYPE*  pClassRes = rId.GetpResource();
     933      102552 :     RESOURCE_TYPE   nRT = rId.GetRT2();
     934      102552 :     sal_uInt32      nId = rId.GetId();
     935      102552 :     const ResMgr*   pMgr = rId.GetResMgr();
     936             : 
     937      102552 :     if ( !pMgr )
     938           0 :         pMgr = this;
     939             : 
     940      102552 :     if( pMgr->pFallbackResMgr )
     941             :     {
     942           0 :         ResId aId( rId );
     943           0 :         aId.SetResMgr( NULL );
     944           0 :         return pMgr->pFallbackResMgr->IsAvailable( aId, pResObj );
     945             :     }
     946             : 
     947      102552 :     if ( !pResObj || pResObj == pMgr->aStack[pMgr->nCurStack].pResObj )
     948             :     {
     949      102552 :         if ( !pClassRes )
     950      102552 :             pClassRes = LocalResource( &pMgr->aStack[pMgr->nCurStack], nRT, nId );
     951      102552 :         if ( pClassRes )
     952             :         {
     953       83628 :             if ( pClassRes->GetRT() == nRT )
     954       83628 :                 bAvailable = true;
     955             :         }
     956             :     }
     957             : 
     958      102552 :     if ( !pClassRes )
     959       18924 :         bAvailable = pMgr->pImpRes->IsGlobalAvailable( nRT, nId );
     960             : 
     961      102552 :     return bAvailable;
     962             : }
     963             : 
     964     2463296 : void* ResMgr::GetClass()
     965             : {
     966     2463296 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     967             : 
     968     2463296 :     if( pFallbackResMgr )
     969           0 :         return pFallbackResMgr->GetClass();
     970             : 
     971     2463296 :     return aStack[nCurStack].pClassRes;
     972             : }
     973             : 
     974     1897605 : bool ResMgr::GetResource( const ResId& rId, const Resource* pResObj )
     975             : {
     976     1897605 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     977             : 
     978     1897605 :     if( pFallbackResMgr )
     979             :     {
     980           0 :         ResId aId( rId );
     981           0 :         aId.SetResMgr( NULL );
     982           0 :         return pFallbackResMgr->GetResource( aId, pResObj );
     983             :     }
     984             : 
     985     1897605 :     ResMgr* pMgr = rId.GetResMgr();
     986     1897605 :     if ( pMgr && (this != pMgr) )
     987           0 :         return pMgr->GetResource( rId, pResObj );
     988             : 
     989             :     // normally Increment will pop the context; this is
     990             :     // not possible in RC_NOTFOUND case, so pop a frame here
     991     1897605 :     ImpRCStack* pTop = &aStack[nCurStack];
     992     1897605 :     if( (pTop->Flags & RC_NOTFOUND) )
     993             :     {
     994           0 :         decStack();
     995             :     }
     996             : 
     997     1897605 :     RSHEADER_TYPE*  pClassRes = rId.GetpResource();
     998     1897605 :     RESOURCE_TYPE   nRT = rId.GetRT2();
     999     1897605 :     sal_uInt32      nId = rId.GetId();
    1000             : 
    1001     1897605 :     incStack();
    1002     1897605 :     pTop = &aStack[nCurStack];
    1003             :     pTop->Init( pMgr, pResObj, nId |
    1004     1897605 :                 (rId.IsAutoRelease() ? 0 : RSC_DONTRELEASE) );
    1005             : 
    1006     1897605 :     if ( pClassRes )
    1007             :     {
    1008       79926 :         if ( pClassRes->GetRT() == nRT )
    1009       79926 :             pTop->pClassRes = pClassRes;
    1010             :         else
    1011             :         {
    1012             : #ifdef DBG_UTIL
    1013             :             RscError_Impl( "Different class and resource type!",
    1014             :                            this, nRT, nId, aStack, nCurStack-1 );
    1015             : #endif
    1016           0 :             pTop->Flags |= RC_NOTFOUND;
    1017           0 :             pTop->pClassRes = getEmptyBuffer();
    1018           0 :             pTop->pResource = (RSHEADER_TYPE*)pTop->pClassRes;
    1019           0 :             return false;
    1020             :         }
    1021             :     }
    1022             :     else
    1023             :     {
    1024             :         OSL_ENSURE( nCurStack > 0, "stack of 1 to shallow" );
    1025     1817679 :         pTop->pClassRes = LocalResource( &aStack[nCurStack-1], nRT, nId );
    1026             :     }
    1027             : 
    1028     1897605 :     if ( pTop->pClassRes )
    1029             :         // local Resource, not a system Resource
    1030      206668 :         pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
    1031             :     else
    1032             :     {
    1033     1690937 :         pTop->pClassRes = pImpRes->LoadGlobalRes( nRT, nId, &pTop->aResHandle );
    1034     1690937 :         if ( pTop->pClassRes )
    1035             :         {
    1036     1690937 :             pTop->Flags |= RC_GLOBAL;
    1037     1690937 :             pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
    1038             :         }
    1039             :         else
    1040             :         {
    1041             :             // try to get a fallback resource
    1042           0 :             pFallbackResMgr = CreateFallbackResMgr( rId, pResObj );
    1043           0 :             if( pFallbackResMgr )
    1044             :             {
    1045           0 :                 pTop->Flags |= RC_FALLBACK_DOWN;
    1046             : #ifdef DBG_UTIL
    1047             :                 OStringBuffer aMess("found resource ");
    1048             :                 aMess.append(static_cast<sal_Int32>(nId));
    1049             :                 aMess.append(" in fallback ");
    1050             :                 aMess.append(OUStringToOString(
    1051             :                     pFallbackResMgr->GetFileName(),
    1052             :                     osl_getThreadTextEncoding()));
    1053             :                 aMess.append('\n');
    1054             :                 RscError_Impl(aMess.getStr(),
    1055             :                               this, nRT, nId, aStack, nCurStack-1);
    1056             : #endif
    1057             :             }
    1058             :             else
    1059             :             {
    1060             :                 #ifdef DBG_UTIL
    1061             :                 RscError_Impl( "Cannot load resource! ",
    1062             :                               this, nRT, nId, aStack, nCurStack-1 );
    1063             :                 #endif
    1064           0 :                 pTop->Flags |= RC_NOTFOUND;
    1065           0 :                 pTop->pClassRes = getEmptyBuffer();
    1066           0 :                 pTop->pResource = (RSHEADER_TYPE*)pTop->pClassRes;
    1067           0 :                 return false;
    1068             :             }
    1069             :         }
    1070             :     }
    1071             : 
    1072     1897605 :     return true;
    1073             : }
    1074             : 
    1075       69010 : void * ResMgr::GetResourceSkipHeader( const ResId& rResId, ResMgr ** ppResMgr )
    1076             : {
    1077       69010 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1078             : 
    1079             :     DBG_ASSERT( rResId.GetResMgr(), "illegal ResId without ResMgr" );
    1080       69010 :     *ppResMgr = rResId.GetResMgr();
    1081       69010 :     if( *ppResMgr )
    1082             :     {
    1083       69010 :         (*ppResMgr)->GetResource( rResId );
    1084       69010 :         (*ppResMgr)->Increment( sizeof( RSHEADER_TYPE ) );
    1085       69010 :         return (*ppResMgr)->GetClass();
    1086             :     }
    1087           0 :     return getEmptyBuffer();
    1088             : }
    1089             : 
    1090     1897605 : void ResMgr::PopContext( const Resource* pResObj )
    1091             : {
    1092     1897605 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1093             : 
    1094     1897605 :     if( pFallbackResMgr )
    1095             :     {
    1096           0 :         pFallbackResMgr->PopContext( pResObj );
    1097     1897605 :         return;
    1098             :     }
    1099             : 
    1100             : #ifdef DBG_UTIL
    1101             :     if ( DbgIsResource() )
    1102             :     {
    1103             :         if ( (aStack[nCurStack].pResObj != pResObj) || nCurStack == 0 )
    1104             :         {
    1105             :             RscError_Impl( "Cannot free resource! ", this,
    1106             :                            RSC_NOTYPE, 0, aStack, nCurStack );
    1107             :         }
    1108             :     }
    1109             : #endif
    1110             : 
    1111     1897605 :     if ( nCurStack > 0 )
    1112             :     {
    1113     1897605 :         ImpRCStack* pTop = &aStack[nCurStack];
    1114             : #ifdef DBG_UTIL
    1115             :         if ( DbgIsResource() && !(pTop->Flags & RC_NOTFOUND) )
    1116             :         {
    1117             :             void* pRes = (sal_uInt8*)pTop->pResource +
    1118             :                          pTop->pResource->GetLocalOff();
    1119             : 
    1120             :             if ( pTop->pClassRes != pRes )
    1121             :             {
    1122             :                 RscError_Impl( "Classpointer not at the end!",
    1123             :                                this, pTop->pResource->GetRT(),
    1124             :                                pTop->pResource->GetId(),
    1125             :                                aStack, nCurStack-1 );
    1126             :             }
    1127             :         }
    1128             : #endif
    1129             : 
    1130             :         // free resource
    1131     1897605 :         if( (pTop->Flags & (RC_GLOBAL | RC_NOTFOUND)) == RC_GLOBAL )
    1132             :             // free global resource if resource is foreign
    1133     1690937 :             InternalResMgr::FreeGlobalRes( pTop->aResHandle, pTop->pResource );
    1134     1897605 :         decStack();
    1135     1897605 :     }
    1136             : }
    1137             : 
    1138           0 : RSHEADER_TYPE* ResMgr::CreateBlock( const ResId& rId )
    1139             : {
    1140           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1141             : 
    1142           0 :     if( pFallbackResMgr )
    1143             :     {
    1144           0 :         ResId aId( rId );
    1145           0 :         aId.SetResMgr( NULL );
    1146           0 :         return pFallbackResMgr->CreateBlock( aId );
    1147             :     }
    1148             : 
    1149           0 :     RSHEADER_TYPE* pHeader = NULL;
    1150           0 :     if ( GetResource( rId ) )
    1151             :     {
    1152             :         // Pointer is at the beginning of the resource, thus
    1153             :         // class pointer points to the header, and the remaining size
    1154             :         // equals to total size of allocated memory
    1155           0 :         pHeader = (RSHEADER_TYPE*)rtl_allocateMemory( GetRemainSize() );
    1156           0 :         memcpy( pHeader, GetClass(), GetRemainSize() );
    1157           0 :         Increment( pHeader->GetLocalOff() ); //ans Ende setzen
    1158           0 :         if ( pHeader->GetLocalOff() != pHeader->GetGlobOff() )
    1159             :             // Has sub-resources, thus release them as well
    1160           0 :             PopContext();
    1161             :     }
    1162             : 
    1163           0 :     return pHeader;
    1164             : }
    1165             : 
    1166       19134 : sal_Int16 ResMgr::GetShort( void * pShort )
    1167             : {
    1168       19134 :     return ((*((sal_uInt8*)pShort + 0) << 8) |
    1169       19134 :             (*((sal_uInt8*)pShort + 1) << 0)   );
    1170             : }
    1171             : 
    1172   104363013 : sal_Int32 ResMgr::GetLong( void * pLong )
    1173             : {
    1174   208726026 :     return ((*((sal_uInt8*)pLong + 0) << 24) |
    1175   208726026 :             (*((sal_uInt8*)pLong + 1) << 16) |
    1176   104363013 :             (*((sal_uInt8*)pLong + 2) <<  8) |
    1177   104363013 :             (*((sal_uInt8*)pLong + 3) <<  0)   );
    1178             : }
    1179             : 
    1180      803627 : sal_uInt64 ResMgr::GetUInt64( void* pDatum )
    1181             : {
    1182     1607254 :     return ((sal_uInt64(*((sal_uInt8*)pDatum + 0)) << 56) |
    1183     1607254 :             (sal_uInt64(*((sal_uInt8*)pDatum + 1)) << 48) |
    1184     1607254 :             (sal_uInt64(*((sal_uInt8*)pDatum + 2)) << 40) |
    1185     1607254 :             (sal_uInt64(*((sal_uInt8*)pDatum + 3)) << 32) |
    1186     1607254 :             (sal_uInt64(*((sal_uInt8*)pDatum + 4)) << 24) |
    1187     1607254 :             (sal_uInt64(*((sal_uInt8*)pDatum + 5)) << 16) |
    1188      803627 :             (sal_uInt64(*((sal_uInt8*)pDatum + 6)) <<  8) |
    1189      803627 :             (sal_uInt64(*((sal_uInt8*)pDatum + 7)) <<  0)   );
    1190             : }
    1191             : 
    1192      122870 : sal_uInt32 ResMgr::GetStringWithoutHook( OUString& rStr, const sal_uInt8* pStr )
    1193             : {
    1194      122870 :     sal_uInt32 nLen=0;
    1195      122870 :     sal_uInt32 nRet = GetStringSize( pStr, nLen );
    1196      122870 :     const sal_Char* str = reinterpret_cast< const sal_Char* >( pStr );
    1197      122870 :     OUString aString( str, strlen( str ), RTL_TEXTENCODING_UTF8,
    1198             :                        RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |
    1199             :                        RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
    1200      122870 :                        RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
    1201      122870 :     rStr = aString;
    1202      122870 :     return nRet;
    1203             : }
    1204             : 
    1205         450 : sal_uInt32 ResMgr::GetString( OUString& rStr, const sal_uInt8* pStr )
    1206             : {
    1207         450 :     OUString aString;
    1208         450 :     sal_uInt32 nRet =  GetStringWithoutHook( aString, pStr );
    1209         450 :     if ( pImplResHookProc )
    1210         440 :         aString = pImplResHookProc( aString );
    1211         450 :     rStr = aString;
    1212         450 :     return nRet;
    1213             : }
    1214             : 
    1215       13996 : sal_uInt32 ResMgr::GetByteString( OString& rStr, const sal_uInt8* pStr )
    1216             : {
    1217       13996 :     sal_uInt32 nLen=0;
    1218       13996 :     sal_uInt32 nRet = GetStringSize( pStr, nLen );
    1219       13996 :     rStr = OString( (const sal_Char*)pStr, nLen );
    1220       13996 :     return nRet;
    1221             : }
    1222             : 
    1223      136866 : sal_uInt32 ResMgr::GetStringSize( const sal_uInt8* pStr, sal_uInt32& nLen )
    1224             : {
    1225      136866 :     nLen = static_cast< sal_uInt32 >( strlen( (const char*)pStr ) );
    1226      136866 :     return GetStringSize( nLen );
    1227             : }
    1228             : 
    1229           0 : sal_uInt32 ResMgr::GetRemainSize()
    1230             : {
    1231           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1232             : 
    1233           0 :     if( pFallbackResMgr )
    1234           0 :         return pFallbackResMgr->GetRemainSize();
    1235             : 
    1236           0 :     const ImpRCStack& rTop = aStack[nCurStack];
    1237             :     return (sal_uInt32)(reinterpret_cast<sal_IntPtr>(rTop.pResource) +
    1238           0 :                         rTop.pResource->GetLocalOff() -
    1239           0 :                         reinterpret_cast<sal_IntPtr>(rTop.pClassRes));
    1240             : }
    1241             : 
    1242     2507486 : void* ResMgr::Increment( sal_uInt32 nSize )
    1243             : {
    1244     2507486 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1245             : 
    1246     2507486 :     if( pFallbackResMgr )
    1247           0 :         return pFallbackResMgr->Increment( nSize );
    1248             : 
    1249     2507486 :     ImpRCStack& rStack = aStack[nCurStack];
    1250     2507486 :     if( (rStack.Flags & RC_NOTFOUND) )
    1251           0 :         return rStack.pClassRes;
    1252             : 
    1253     2507486 :     sal_uInt8* pClassRes = (sal_uInt8*)rStack.pClassRes + nSize;
    1254             : 
    1255     2507486 :     rStack.pClassRes = pClassRes;
    1256             : 
    1257     2507486 :     RSHEADER_TYPE* pRes = rStack.pResource;
    1258             : 
    1259     2507486 :     sal_uInt32 nLocalOff = pRes->GetLocalOff();
    1260     7456672 :     if ( (pRes->GetGlobOff() == nLocalOff) &&
    1261     4362075 :          (((char*)pRes + nLocalOff) == rStack.pClassRes) &&
    1262     1854589 :          (rStack.Flags & RC_AUTORELEASE))
    1263             :     {
    1264     1854589 :         PopContext( rStack.pResObj );
    1265             :     }
    1266             : 
    1267     2507486 :     return pClassRes;
    1268             : }
    1269             : 
    1270           0 : ResMgr* ResMgr::CreateFallbackResMgr( const ResId& rId, const Resource* pResource )
    1271             : {
    1272           0 :     ResMgr *pFallback = NULL;
    1273           0 :     if( nCurStack > 0 )
    1274             :     {
    1275             :         // get the next fallback level in resource file scope
    1276           0 :         InternalResMgr* pRes = ResMgrContainer::get().getNextFallback( pImpRes );
    1277           0 :         if( pRes )
    1278             :         {
    1279             :             // check that the fallback locale is not already in the chain of
    1280             :             // fallbacks - prevent fallback loops
    1281           0 :             ResMgr* pResMgr = this;
    1282           0 :             while( pResMgr && (pResMgr->pImpRes->aLocale != pRes->aLocale))
    1283             :             {
    1284           0 :                 pResMgr = pResMgr->pOriginalResMgr;
    1285             :             }
    1286           0 :             if( pResMgr )
    1287             :             {
    1288             :                 // found a recursion, no fallback possible
    1289           0 :                 ResMgrContainer::get().freeResMgr( pRes );
    1290           0 :                 return NULL;
    1291             :             }
    1292             :             OSL_TRACE( "trying fallback: %s", OUStringToOString( pRes->aFileName, osl_getThreadTextEncoding() ).getStr() );
    1293           0 :             pFallback = new ResMgr( pRes );
    1294           0 :             pFallback->pOriginalResMgr = this;
    1295             :             // try to recreate the resource stack
    1296           0 :             bool bHaveStack = true;
    1297           0 :             for( int i = 1; i < nCurStack; i++ )
    1298             :             {
    1299           0 :                 if( !aStack[i].pResource )
    1300             :                 {
    1301           0 :                     bHaveStack = false;
    1302           0 :                     break;
    1303             :                 }
    1304           0 :                 ResId aId( aStack[i].pResource->GetId(), *pFallbackResMgr );
    1305           0 :                 aId.SetRT( aStack[i].pResource->GetRT() );
    1306           0 :                 if( !pFallback->GetResource( aId ) )
    1307             :                 {
    1308           0 :                     bHaveStack = false;
    1309           0 :                     break;
    1310             :                 }
    1311             :             }
    1312           0 :             if( bHaveStack )
    1313             :             {
    1314           0 :                 ResId aId( rId.GetId(), *pFallback );
    1315           0 :                 aId.SetRT( rId.GetRT() );
    1316           0 :                 if( !pFallback->GetResource( aId, pResource ) )
    1317           0 :                     bHaveStack = false;
    1318             :                 else
    1319           0 :                     pFallback->aStack[pFallback->nCurStack].Flags |= RC_FALLBACK_UP;
    1320             :             }
    1321           0 :             if( !bHaveStack )
    1322             :             {
    1323           0 :                 delete pFallback;
    1324           0 :                 pFallback = NULL;
    1325             :             }
    1326             :         }
    1327             :     }
    1328           0 :     return pFallback;
    1329             : }
    1330             : 
    1331        3789 : ResMgr* ResMgr::CreateResMgr( const sal_Char* pPrefixName,
    1332             :                               const LanguageTag& _aLocale )
    1333             : {
    1334        3789 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1335             : 
    1336        7578 :     OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
    1337             : 
    1338        7578 :     LanguageTag aLocale = _aLocale;
    1339        3789 :     if( aLocale.isSystemLocale() )
    1340        1460 :         aLocale = ResMgrContainer::get().getDefLocale();
    1341             : 
    1342        3789 :     InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, aLocale );
    1343        7578 :     return pImp ? new ResMgr( pImp ) : NULL;
    1344             : }
    1345             : 
    1346         426 : ResMgr* ResMgr::SearchCreateResMgr(
    1347             :     const sal_Char* pPrefixName,
    1348             :     LanguageTag& rLocale )
    1349             : {
    1350         426 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1351             : 
    1352         852 :     OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
    1353             : 
    1354         426 :     if( rLocale.isSystemLocale() )
    1355         160 :         rLocale = ResMgrContainer::get().getDefLocale();
    1356             : 
    1357         426 :     InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, rLocale );
    1358         852 :     return pImp ? new ResMgr( pImp ) : NULL;
    1359             : }
    1360             : 
    1361       19134 : sal_Int16 ResMgr::ReadShort()
    1362             : {
    1363       19134 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1364             : 
    1365       19134 :     if( pFallbackResMgr )
    1366           0 :         return pFallbackResMgr->ReadShort();
    1367             : 
    1368       19134 :     sal_Int16 n = GetShort( GetClass() );
    1369       19134 :     Increment( sizeof( sal_Int16 ) );
    1370       19134 :     return n;
    1371             : }
    1372             : 
    1373      352704 : sal_Int32 ResMgr::ReadLong()
    1374             : {
    1375      352704 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1376             : 
    1377      352704 :     if( pFallbackResMgr )
    1378           0 :         return pFallbackResMgr->ReadLong();
    1379             : 
    1380      352704 :     sal_Int32 n = GetLong( GetClass() );
    1381      352704 :     Increment( sizeof( sal_Int32 ) );
    1382      352704 :     return n;
    1383             : }
    1384             : 
    1385      122420 : OUString ResMgr::ReadStringWithoutHook()
    1386             : {
    1387      122420 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1388             : 
    1389      122420 :     if( pFallbackResMgr )
    1390           0 :         return pFallbackResMgr->ReadStringWithoutHook();
    1391             : 
    1392      244840 :     OUString aRet;
    1393             : 
    1394      122420 :     const ImpRCStack& rTop = aStack[nCurStack];
    1395      122420 :     if( (rTop.Flags & RC_NOTFOUND) )
    1396             :     {
    1397             :         #if OSL_DEBUG_LEVEL > 0
    1398             :         aRet = "<resource not found>";
    1399             :         #endif
    1400             :     }
    1401             :     else
    1402      122420 :         Increment( GetStringWithoutHook( aRet, (const sal_uInt8*)GetClass() ) );
    1403             : 
    1404      244840 :     return aRet;
    1405             : }
    1406             : 
    1407      122420 : OUString ResMgr::ReadString()
    1408             : {
    1409      122420 :     OUString aRet = ReadStringWithoutHook();
    1410      122420 :     if ( pImplResHookProc )
    1411       93015 :         aRet = pImplResHookProc( aRet );
    1412      122420 :     return aRet;
    1413             : }
    1414             : 
    1415       13996 : OString ResMgr::ReadByteString()
    1416             : {
    1417       13996 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1418             : 
    1419       13996 :     if( pFallbackResMgr )
    1420           0 :         return pFallbackResMgr->ReadByteString();
    1421             : 
    1422       27992 :     OString aRet;
    1423             : 
    1424       13996 :     const ImpRCStack& rTop = aStack[nCurStack];
    1425       13996 :     if( (rTop.Flags & RC_NOTFOUND) )
    1426             :     {
    1427             :         #if OSL_DEBUG_LEVEL > 0
    1428             :         aRet = OString( "<resource not found>" );
    1429             :         #endif
    1430             :     }
    1431             :     else
    1432       13996 :         Increment( GetByteString( aRet, (const sal_uInt8*)GetClass() ) );
    1433             : 
    1434       27992 :     return aRet;
    1435             : }
    1436             : 
    1437       10002 : OString ResMgr::GetAutoHelpId()
    1438             : {
    1439       10002 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1440             : 
    1441       10002 :     if( pFallbackResMgr )
    1442           0 :         return pFallbackResMgr->GetAutoHelpId();
    1443             : 
    1444             :     OSL_ENSURE( nCurStack, "resource stack empty in Auto help id generation" );
    1445       10002 :     if( nCurStack < 1 || nCurStack > 2 )
    1446           0 :         return OString();
    1447             : 
    1448             :     // prepare HID, start with resource prefix
    1449       20004 :     OStringBuffer aHID( 32 );
    1450       10002 :     aHID.append( OUStringToOString( pImpRes->aPrefix, RTL_TEXTENCODING_UTF8 ) );
    1451       10002 :     aHID.append( '.' );
    1452             : 
    1453             :     // append type
    1454       10002 :     const ImpRCStack *pRC = StackTop();
    1455             :     OSL_ENSURE( pRC, "missing resource stack level" );
    1456             : 
    1457       10002 :     if ( nCurStack == 1 )
    1458             :     {
    1459             :         // auto help ids for top level windows
    1460        5530 :         switch( pRC->pResource->GetRT() ) {
    1461         202 :             case RSC_DOCKINGWINDOW:     aHID.append( "DockingWindow" );    break;
    1462           0 :             case RSC_WORKWIN:           aHID.append( "WorkWindow" );       break;
    1463        5328 :             default: return OString();
    1464             :         }
    1465             :     }
    1466             :     else
    1467             :     {
    1468             :         // only controls with the following parents get auto help ids
    1469        4472 :         const ImpRCStack *pRC1 = StackTop(1);
    1470        4472 :         switch( pRC1->pResource->GetRT() ) {
    1471             :             case RSC_DOCKINGWINDOW:
    1472             :             case RSC_WORKWIN:
    1473             :                 // intentionally no breaks!
    1474             :                 // auto help ids for controls
    1475          68 :                 switch( pRC->pResource->GetRT() ) {
    1476           0 :                     case RSC_RADIOBUTTON:       aHID.append( "RadioButton" );      break;
    1477           0 :                     case RSC_CHECKBOX:          aHID.append( "CheckBox" );         break;
    1478           0 :                     case RSC_EDIT:              aHID.append( "Edit" );             break;
    1479          34 :                     case RSC_LISTBOX:           aHID.append( "ListBox" );          break;
    1480           0 :                     case RSC_COMBOBOX:          aHID.append( "ComboBox" );         break;
    1481           0 :                     case RSC_PUSHBUTTON:        aHID.append( "PushButton" );       break;
    1482           0 :                     case RSC_SPINFIELD:         aHID.append( "SpinField" );        break;
    1483           0 :                     case RSC_NUMERICFIELD:      aHID.append( "NumericField" );     break;
    1484           0 :                     case RSC_METRICFIELD:       aHID.append( "MetricField" );      break;
    1485           0 :                     case RSC_DATEFIELD:         aHID.append( "DateField" );        break;
    1486           0 :                     case RSC_TIMEFIELD:         aHID.append( "TimeField" );        break;
    1487           0 :                     case RSC_IMAGEBUTTON:       aHID.append( "ImageButton" );      break;
    1488             :                     default:
    1489             :                         // no type, no auto HID
    1490          34 :                         return OString();
    1491             :                 }
    1492          34 :                 break;
    1493             :             default:
    1494        4404 :                 return OString();
    1495             :         }
    1496             :     }
    1497             : 
    1498             :     // append resource id hierarchy
    1499         506 :     for( int nOff = nCurStack-1; nOff >= 0; nOff-- )
    1500             :     {
    1501         270 :         aHID.append( '.' );
    1502         270 :         pRC = StackTop( nOff );
    1503             : 
    1504             :         OSL_ENSURE( pRC->pResource, "missing resource in resource stack level !" );
    1505         270 :         if( pRC->pResource )
    1506         270 :             aHID.append( sal_Int32( pRC->pResource->GetId() ) );
    1507             :     }
    1508             : 
    1509       10238 :     return aHID.makeStringAndClear();
    1510             : }
    1511             : 
    1512         160 : void ResMgr::SetReadStringHook( ResHookProc pProc )
    1513             : {
    1514         160 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1515         160 :     pImplResHookProc = pProc;
    1516         160 : }
    1517             : 
    1518     1694111 : ResHookProc ResMgr::GetReadStringHook()
    1519             : {
    1520     1694111 :     return pImplResHookProc;
    1521             : }
    1522             : 
    1523        1389 : void ResMgr::SetDefaultLocale( const LanguageTag& rLocale )
    1524             : {
    1525        1389 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1526        1389 :     ResMgrContainer::get().setDefLocale( rLocale );
    1527        1389 : }
    1528             : 
    1529           0 : const OUString& ResMgr::GetFileName() const
    1530             : {
    1531           0 :     return pImpRes->aFileName;
    1532             : }
    1533             : 
    1534          15 : SimpleResMgr::SimpleResMgr( const sal_Char* pPrefixName,
    1535          15 :                             const LanguageTag& rLocale )
    1536             : {
    1537          15 :     OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
    1538          30 :     LanguageTag aLocale( rLocale );
    1539             : 
    1540          30 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1541          15 :     if( aLocale.isSystemLocale() )
    1542           0 :         aLocale = ResMgrContainer::get().getDefLocale();
    1543             : 
    1544          15 :     m_pResImpl = ResMgrContainer::get().getResMgr( aPrefix, aLocale, true );
    1545          15 :     DBG_ASSERT( m_pResImpl, "SimpleResMgr::SimpleResMgr : have no impl class !" );
    1546          15 : }
    1547             : 
    1548          45 : SimpleResMgr::~SimpleResMgr()
    1549             : {
    1550          15 :     delete m_pResImpl;
    1551          30 : }
    1552             : 
    1553          10 : SimpleResMgr* SimpleResMgr::Create( const sal_Char* pPrefixName, LanguageTag aLocale )
    1554             : {
    1555          10 :     return new SimpleResMgr( pPrefixName, aLocale );
    1556             : }
    1557             : 
    1558          46 : bool SimpleResMgr::IsAvailable( RESOURCE_TYPE _resourceType, sal_uInt32 _resourceId )
    1559             : {
    1560          46 :     osl::MutexGuard aGuard(m_aAccessSafety);
    1561             : 
    1562          46 :     if ( ( RSC_STRING != _resourceType ) && ( RSC_RESOURCE != _resourceType ) )
    1563           0 :         return false;
    1564             : 
    1565             :     DBG_ASSERT( m_pResImpl, "SimpleResMgr::IsAvailable: have no impl class !" );
    1566          46 :     return m_pResImpl->IsGlobalAvailable( _resourceType, _resourceId );
    1567             : }
    1568             : 
    1569         450 : OUString SimpleResMgr::ReadString( sal_uInt32 nId )
    1570             : {
    1571         450 :     osl::MutexGuard aGuard(m_aAccessSafety);
    1572             : 
    1573             :     DBG_ASSERT( m_pResImpl, "SimpleResMgr::ReadString : have no impl class !" );
    1574             :     // perhaps constructed with an invalid filename ?
    1575             : 
    1576         450 :     OUString sReturn;
    1577         450 :     if ( !m_pResImpl )
    1578           0 :         return sReturn;
    1579             : 
    1580         450 :     void* pResHandle = NULL;
    1581         450 :     InternalResMgr* pFallback = m_pResImpl;
    1582         450 :     RSHEADER_TYPE* pResHeader = (RSHEADER_TYPE*)m_pResImpl->LoadGlobalRes( RSC_STRING, nId, &pResHandle );
    1583         450 :     if ( !pResHeader )
    1584             :     {
    1585           0 :         osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
    1586             : 
    1587             :         // try fallback
    1588           0 :         while( ! pResHandle && pFallback )
    1589             :         {
    1590           0 :             InternalResMgr* pOldFallback = pFallback;
    1591           0 :             pFallback = ResMgrContainer::get().getNextFallback( pFallback );
    1592           0 :             if( pOldFallback != m_pResImpl )
    1593           0 :                 ResMgrContainer::get().freeResMgr( pOldFallback );
    1594           0 :             if( pFallback )
    1595             :             {
    1596             :                 // handle possible recursion
    1597           0 :                 if( pFallback->aLocale != m_pResImpl->aLocale )
    1598             :                 {
    1599           0 :                     pResHeader = (RSHEADER_TYPE*)pFallback->LoadGlobalRes( RSC_STRING, nId, &pResHandle );
    1600             :                 }
    1601             :                 else
    1602             :                 {
    1603           0 :                     ResMgrContainer::get().freeResMgr( pFallback );
    1604           0 :                     pFallback = NULL;
    1605             :                 }
    1606             :             }
    1607             :         }
    1608           0 :         if( ! pResHandle )
    1609             :             // no such resource
    1610           0 :             return sReturn;
    1611             :     }
    1612             : 
    1613             :     // sal_uIntPtr nLen = pResHeader->GetLocalOff() - sizeof(RSHEADER_TYPE);
    1614         450 :     ResMgr::GetString( sReturn, (const sal_uInt8*)(pResHeader+1) );
    1615             : 
    1616             :     // not necessary with the current implementation which holds the string table permanently, but to be sure ....
    1617             :     // note: pFallback cannot be NULL here and is either the fallback or m_pResImpl
    1618         450 :     InternalResMgr::FreeGlobalRes( pResHeader, pResHandle );
    1619         450 :     if( m_pResImpl != pFallback )
    1620             :     {
    1621           0 :         osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
    1622             : 
    1623           0 :         ResMgrContainer::get().freeResMgr( pFallback );
    1624             :     }
    1625         450 :     return sReturn;
    1626             : }
    1627             : 
    1628             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10