LCOV - code coverage report
Current view: top level - tools/source/rc - resmgr.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 17 660 2.6 %
Date: 2014-04-14 Functions: 3 66 4.5 %
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           1 : static osl::Mutex& getResMgrMutex()
      63             : {
      64           1 :     if( !pResMgrMutex )
      65             :     {
      66           1 :         osl::Guard<osl::Mutex> aGuard( *osl::Mutex::getGlobalMutex() );
      67           1 :         if( ! pResMgrMutex )
      68           1 :             pResMgrMutex = new osl::Mutex();
      69             :     }
      70           1 :     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           0 :     struct ContainerElement
     113             :     {
     114             :         InternalResMgr* pResMgr;
     115             :         OUString        aFileURL;
     116             :         int             nRefCount;
     117             :         int             nLoadCount;
     118             : 
     119           0 :         ContainerElement() :
     120             :             pResMgr( NULL ),
     121             :             nRefCount( 0 ),
     122           0 :             nLoadCount( 0 )
     123           0 :             {}
     124             :     };
     125             : 
     126             :     boost::unordered_map< OUString, ContainerElement, OUStringHash> m_aResFiles;
     127             :     LanguageTag     m_aDefLocale;
     128             : 
     129           0 :     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           0 :     void setDefLocale( const LanguageTag& rLocale )
     147           0 :     { m_aDefLocale = rLocale; }
     148           0 :     const LanguageTag& getDefLocale() const
     149           0 :     { return m_aDefLocale; }
     150             : };
     151             : 
     152             : ResMgrContainer* ResMgrContainer::pOneInstance = NULL;
     153             : 
     154           0 : ResMgrContainer& ResMgrContainer::get()
     155             : {
     156           0 :     if( ! pOneInstance )
     157           0 :         pOneInstance = new ResMgrContainer();
     158           0 :     return *pOneInstance;
     159             : }
     160             : 
     161           0 : ResMgrContainer::~ResMgrContainer()
     162             : {
     163           0 :     for( boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it =
     164           0 :             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           0 :         delete it->second.pResMgr;
     170             :     }
     171           0 : }
     172             : 
     173           1 : void ResMgrContainer::release()
     174             : {
     175           1 :     delete pOneInstance;
     176           1 :     pOneInstance = NULL;
     177           1 : }
     178             : 
     179           0 : void ResMgrContainer::init()
     180             : {
     181             :     assert( m_aResFiles.empty() );
     182             : 
     183             :     // get resource path
     184           0 :     OUString uri("$BRAND_BASE_DIR/" LIBO_SHARE_RESOURCE_FOLDER "/");
     185           0 :     rtl::Bootstrap::expandMacros(uri); //TODO: detect failure
     186             : 
     187             :     // collect all possible resource files
     188           0 :     Directory aDir( uri );
     189           0 :     if( aDir.open() == FileBase::E_None )
     190             :     {
     191           0 :         DirectoryItem aItem;
     192           0 :         while( aDir.getNextItem( aItem ) == FileBase::E_None )
     193             :         {
     194           0 :             FileStatus aStatus(osl_FileStatus_Mask_FileName);
     195           0 :             if( aItem.getFileStatus( aStatus ) == FileBase::E_None )
     196             :             {
     197           0 :                 OUString aFileName = aStatus.getFileName();
     198           0 :                 if( ! aFileName.endsWithIgnoreAsciiCase( ".res" ) )
     199           0 :                     continue;
     200           0 :                 OUString aResName = aFileName.copy( 0, aFileName.getLength() - strlen(".res") );
     201           0 :                 if( aResName.isEmpty() )
     202           0 :                     continue;
     203             :                 assert( m_aResFiles.find( aResName ) == m_aResFiles.end() );
     204           0 :                 m_aResFiles[ aResName ].aFileURL = uri + aFileName;
     205             :                 SAL_INFO(
     206             :                     "tools.rc",
     207             :                     "ResMgrContainer: " << aResName << " -> "
     208           0 :                         << m_aResFiles[ aResName ].aFileURL );
     209             :             }
     210           0 :         }
     211             :     }
     212             :     else
     213             :         SAL_WARN( "tools.rc", "opening dir " << uri << " failed" );
     214             : 
     215             :     // set default language
     216           0 :     LanguageType nLang = MsLangId::getSystemUILanguage();
     217           0 :     m_aDefLocale.reset( nLang);
     218           0 : }
     219             : 
     220             : namespace
     221             : {
     222           0 :     bool isAlreadyPureenUS(const LanguageTag &rLocale)
     223             :     {
     224           0 :         return ( rLocale.getLanguageType() == LANGUAGE_ENGLISH_US );
     225             :     }
     226             : }
     227             : 
     228           0 : InternalResMgr* ResMgrContainer::getResMgr( const OUString& rPrefix,
     229             :                                             LanguageTag& rLocale,
     230             :                                             bool bForceNewInstance
     231             :                                             )
     232             : {
     233           0 :     LanguageTag aLocale( rLocale );
     234           0 :     boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it = m_aResFiles.end();
     235             : 
     236           0 :     ::std::vector< OUString > aFallbacks( aLocale.getFallbackStrings( true));
     237           0 :     if (!isAlreadyPureenUS( aLocale))
     238           0 :         aFallbacks.push_back( "en-US");     // last resort if all fallbacks fail
     239             : 
     240           0 :     for (::std::vector< OUString >::const_iterator fb( aFallbacks.begin()); fb != aFallbacks.end(); ++fb)
     241             :     {
     242           0 :         OUString aSearch( rPrefix + *fb );
     243           0 :         it = m_aResFiles.find( aSearch );
     244           0 :         if( it != m_aResFiles.end() )
     245             :         {
     246             :             // ensure InternalResMgr existance
     247           0 :             if( ! it->second.pResMgr )
     248             :             {
     249             :                 InternalResMgr* pImp =
     250           0 :                     new InternalResMgr( it->second.aFileURL, rPrefix, it->first, aLocale );
     251           0 :                 if( ! pImp->Create() )
     252             :                 {
     253           0 :                     delete pImp;
     254           0 :                     continue;
     255             :                 }
     256           0 :                 it->second.pResMgr = pImp;
     257             :             }
     258           0 :             break;
     259             :         }
     260           0 :     }
     261             :     // try if there is anything with this prefix at all
     262           0 :     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 existance
     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           0 :     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           0 :     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           0 :     InternalResMgr* pImp = it->second.pResMgr;
     317             : 
     318           0 :     if( it->second.nRefCount == 0 )
     319           0 :         it->second.nLoadCount++;
     320             : 
     321             :     // for SimpleResMgr
     322           0 :     if( bForceNewInstance )
     323             :     {
     324           0 :         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           0 :             it->second.pResMgr = NULL;
     329           0 :             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           0 :         it->second.nRefCount++;
     346             : 
     347           0 :     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           0 : void ResMgrContainer::freeResMgr( InternalResMgr* pResMgr )
     376             : {
     377           0 :     if( pResMgr->bSingular )
     378           0 :         delete pResMgr;
     379             :     else
     380             :     {
     381             :         boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it =
     382           0 :         m_aResFiles.find( pResMgr->aResName );
     383           0 :         if( it != m_aResFiles.end() )
     384             :         {
     385             :             DBG_ASSERT( it->second.nRefCount > 0, "InternalResMgr freed too often" );
     386           0 :             if( it->second.nRefCount > 0 )
     387           0 :                 it->second.nRefCount--;
     388           0 :             if( it->second.nRefCount == 0 )
     389             :             {
     390           0 :                 delete it->second.pResMgr;
     391           0 :                 it->second.pResMgr = NULL;
     392             :             }
     393             :         }
     394             :     }
     395           0 : }
     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           0 :     inline bool operator() (const ImpContent& lhs, const ImpContent& rhs) const
     414             :     {
     415           0 :         return lhs.nTypeAndId < rhs.nTypeAndId;
     416             :     }
     417             : };
     418             : 
     419             : static ResHookProc pImplResHookProc = 0;
     420             : 
     421           0 : 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           0 :     , pResUseDump( 0 )
     437             : {
     438           0 : }
     439             : 
     440           0 : InternalResMgr::~InternalResMgr()
     441             : {
     442           0 :     rtl_freeMemory(pContent);
     443           0 :     rtl_freeMemory(pStringBlock);
     444           0 :     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           0 :     delete pResUseDump;
     474           0 : }
     475             : 
     476           0 : bool InternalResMgr::Create()
     477             : {
     478           0 :     ResMgrContainer::get();
     479           0 :     bool bDone = false;
     480             : 
     481           0 :     pStm = new SvFileStream( aFileName, (STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE) );
     482           0 :     if( pStm->GetError() == 0 )
     483             :     {
     484           0 :         sal_Int32   lContLen = 0;
     485             : 
     486           0 :         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           0 :         pStm->SeekRel( - (int)sizeof( lContLen ) );
     493           0 :         pStm->Read( &lContLen, sizeof( lContLen ) );
     494             :         // is bigendian, swab to the right endian
     495           0 :         lContLen = ResMgr::GetLong( &lContLen );
     496           0 :         pStm->SeekRel( -lContLen );
     497             :         // allocate stored ImpContent data (12 bytes per unit)
     498           0 :         sal_uInt8* pContentBuf = (sal_uInt8*)rtl_allocateMemory( lContLen );
     499           0 :         pStm->Read( pContentBuf, lContLen );
     500             :         // allocate ImpContent space (sizeof(ImpContent) per unit, not necessarily 12)
     501           0 :         pContent = (ImpContent *)rtl_allocateMemory( sizeof(ImpContent)*lContLen/12 );
     502             :         // Shorten to number of ImpContent
     503           0 :         nEntries = (sal_uInt32)lContLen / 12;
     504           0 :         bEqual2Content = true;
     505           0 :         bool bSorted = true;
     506           0 :         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           0 :             pContent[0].nTypeAndId = ResMgr::GetUInt64( pContentBuf );
     519           0 :             pContent[0].nOffset = ResMgr::GetLong( pContentBuf+8 );
     520           0 :             sal_uInt32 nCount = nEntries - 1;
     521           0 :             for( sal_uInt32 i = 0,j=1; i < nCount; ++i,++j )
     522             :             {
     523             :                 // swap the content to the right endian
     524           0 :                 pContent[j].nTypeAndId = ResMgr::GetUInt64( pContentBuf + (12*j) );
     525           0 :                 pContent[j].nOffset = ResMgr::GetLong( pContentBuf + (12*j+8) );
     526           0 :                 if( pContent[i].nTypeAndId >= pContent[j].nTypeAndId )
     527           0 :                     bSorted = false;
     528           0 :                 if( (pContent[i].nTypeAndId & 0xFFFFFFFF00000000LL) == (pContent[j].nTypeAndId & 0xFFFFFFFF00000000LL)
     529           0 :                     && pContent[i].nOffset >= pContent[j].nOffset )
     530           0 :                     bEqual2Content = false;
     531             :             }
     532             :         }
     533           0 :         rtl_freeMemory( pContentBuf );
     534             :         OSL_ENSURE( bSorted, "content not sorted" );
     535             :         OSL_ENSURE( bEqual2Content, "resource structure wrong" );
     536           0 :         if( !bSorted )
     537           0 :             ::std::sort(pContent,pContent+nEntries,ImpContentLessCompare());
     538             :             //  qsort( pContent, nEntries, sizeof( ImpContent ), Compare );
     539             : 
     540           0 :         bDone = true;
     541             :     }
     542             : 
     543           0 :     return bDone;
     544             : }
     545             : 
     546             : 
     547           0 : bool InternalResMgr::IsGlobalAvailable( RESOURCE_TYPE nRT, sal_uInt32 nId ) const
     548             : {
     549             :     // Anfang der Strings suchen
     550             :     ImpContent aValue;
     551           0 :     aValue.nTypeAndId = ((sal_uInt64(nRT) << 32) | nId);
     552             :     ImpContent * pFind = ::std::lower_bound(pContent,
     553             :                                             pContent + nEntries,
     554             :                                             aValue,
     555           0 :                                             ImpContentLessCompare());
     556           0 :     return (pFind != (pContent + nEntries)) && (pFind->nTypeAndId == aValue.nTypeAndId);
     557             : }
     558             : 
     559             : 
     560           0 : 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           0 :     aValue.nTypeAndId = ((sal_uInt64(nRT) << 32) | nId);
     570           0 :     ImpContent* pEnd = (pContent + nEntries);
     571             :     ImpContent* pFind = ::std::lower_bound( pContent,
     572             :                                             pEnd,
     573             :                                             aValue,
     574           0 :                                             ImpContentLessCompare());
     575           0 :     if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == aValue.nTypeAndId) )
     576             :     {
     577           0 :         if( nRT == RSC_STRING && bEqual2Content )
     578             :         {
     579             :             // string optimization
     580           0 :             if( !pStringBlock )
     581             :             {
     582             :                 // search beginning of string
     583           0 :                 ImpContent * pFirst = pFind;
     584           0 :                 ImpContent * pLast = pFirst;
     585           0 :                 while( pFirst > pContent && ((pFirst -1)->nTypeAndId >> 32) == RSC_STRING )
     586           0 :                     --pFirst;
     587           0 :                 while( pLast < pEnd && (pLast->nTypeAndId >> 32) == RSC_STRING )
     588           0 :                     ++pLast;
     589           0 :                 nOffCorrection = pFirst->nOffset;
     590             :                 sal_uInt32 nSize;
     591           0 :                 --pLast;
     592           0 :                 pStm->Seek( pLast->nOffset );
     593             :                 RSHEADER_TYPE aHdr;
     594           0 :                 pStm->Read( &aHdr, sizeof( aHdr ) );
     595           0 :                 nSize = pLast->nOffset + aHdr.GetGlobOff() - nOffCorrection;
     596           0 :                 pStringBlock = (sal_uInt8*)rtl_allocateMemory( nSize );
     597           0 :                 pStm->Seek( pFirst->nOffset );
     598           0 :                 pStm->Read( pStringBlock, nSize );
     599             :             }
     600           0 :             *pResHandle = pStringBlock;
     601           0 :             return (sal_uInt8*)pStringBlock + pFind->nOffset - nOffCorrection;
     602             :         } // if( nRT == RSC_STRING && bEqual2Content )
     603             :         else
     604             :         {
     605           0 :             *pResHandle = 0;
     606             :             RSHEADER_TYPE aHeader;
     607           0 :             pStm->Seek( pFind->nOffset );
     608           0 :             pStm->Read( &aHeader, sizeof( RSHEADER_TYPE ) );
     609           0 :             void * pRes = rtl_allocateMemory( aHeader.GetGlobOff() );
     610           0 :             memcpy( pRes, &aHeader, sizeof( RSHEADER_TYPE ) );
     611           0 :             pStm->Read( (sal_uInt8*)pRes + sizeof( RSHEADER_TYPE ),
     612           0 :                         aHeader.GetGlobOff() - sizeof( RSHEADER_TYPE ) );
     613           0 :             return pRes;
     614             :         }
     615             :     } // if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == nValue) )
     616           0 :     *pResHandle = 0;
     617           0 :     return NULL;
     618             : }
     619             : 
     620           0 : void InternalResMgr::FreeGlobalRes( void * pResHandle, void * pResource )
     621             : {
     622           0 :     if ( !pResHandle )
     623             :         // Free allocated resource
     624           0 :         rtl_freeMemory(pResource);
     625           0 : }
     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           0 : void ImpRCStack::Init( ResMgr* pMgr, const Resource* pObj, sal_uInt32 Id )
     726             : {
     727           0 :     pResource       = NULL;
     728           0 :     pClassRes       = NULL;
     729           0 :     Flags           = RC_NOTYPE;
     730           0 :     aResHandle      = NULL;
     731           0 :     pResObj         = pObj;
     732           0 :     nId             = Id & ~RSC_DONTRELEASE; //TLX: Besser Init aendern
     733           0 :     pResMgr         = pMgr;
     734           0 :     if ( !(Id & RSC_DONTRELEASE) )
     735           0 :         Flags      |= RC_AUTORELEASE;
     736           0 : }
     737             : 
     738           0 : void ImpRCStack::Clear()
     739             : {
     740           0 :     pResource       = NULL;
     741           0 :     pClassRes       = NULL;
     742           0 :     Flags           = RC_NOTYPE;
     743           0 :     aResHandle      = NULL;
     744           0 :     pResObj         = NULL;
     745           0 :     nId             = 0;
     746           0 :     pResMgr         = NULL;
     747           0 : }
     748             : 
     749           0 : 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           0 :     if ( pStack->pResource && pStack->pClassRes )
     758             :     {
     759             :         pTmp = (RSHEADER_TYPE*)
     760           0 :                ((sal_uInt8*)pStack->pResource + pStack->pResource->GetLocalOff());
     761             :         pEnd = (RSHEADER_TYPE*)
     762           0 :                ((sal_uInt8*)pStack->pResource + pStack->pResource->GetGlobOff());
     763           0 :         while ( pTmp != pEnd )
     764             :         {
     765           0 :             if ( pTmp->GetRT() == nRTType && pTmp->GetId() == nId )
     766           0 :                 return pTmp;
     767           0 :             pTmp = (RSHEADER_TYPE*)((sal_uInt8*)pTmp + pTmp->GetGlobOff());
     768             :         }
     769             :     }
     770             : 
     771           0 :     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           1 : void ResMgr::DestroyAllResMgr()
     784             : {
     785             :     {
     786           1 :         osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     787           1 :         if( pEmptyBuffer )
     788             :         {
     789           0 :             rtl_freeMemory( pEmptyBuffer );
     790           0 :             pEmptyBuffer = NULL;
     791             :         }
     792           1 :         ResMgrContainer::release();
     793             :     }
     794           1 :     delete pResMgrMutex;
     795           1 :     pResMgrMutex = NULL;
     796           1 : }
     797             : 
     798           0 : void ResMgr::Init( const OUString& rFileName )
     799             : {
     800             :     (void) rFileName; // avoid warning about unused parameter
     801           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     802             : 
     803           0 :     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           0 :     nCurStack = -1;
     829           0 :     aStack.clear();
     830           0 :     pFallbackResMgr = pOriginalResMgr = NULL;
     831           0 :     incStack();
     832           0 : }
     833             : 
     834           0 : ResMgr::ResMgr( InternalResMgr * pImpMgr )
     835             : {
     836           0 :     pImpRes = pImpMgr;
     837           0 :     Init( pImpMgr->aFileName );
     838           0 : }
     839             : 
     840           0 : ResMgr::~ResMgr()
     841             : {
     842           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     843             : 
     844           0 :     ResMgrContainer::get().freeResMgr( pImpRes );
     845             : 
     846             :     // clean up possible left rc stack frames
     847           0 :     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           0 :     }
     854           0 : }
     855             : 
     856           0 : void ResMgr::incStack()
     857             : {
     858           0 :     nCurStack++;
     859           0 :     if( nCurStack >= int(aStack.size()) )
     860           0 :         aStack.push_back( ImpRCStack() );
     861           0 :     aStack[nCurStack].Clear();
     862             : 
     863             :     DBG_ASSERT( nCurStack < 32, "Resource stack unreasonably large" );
     864           0 : }
     865             : 
     866           0 : void ResMgr::decStack()
     867             : {
     868             :     DBG_ASSERT( nCurStack > 0, "resource stack underrun  !" );
     869           0 :     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           0 :         ImpRCStack& rTop = aStack[nCurStack];
     878           0 :         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           0 :         nCurStack--;
     888             :     }
     889           0 : }
     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           0 : bool ResMgr::IsAvailable( const ResId& rId, const Resource* pResObj ) const
     928             : {
     929           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     930             : 
     931           0 :     bool            bAvailable = false;
     932           0 :     RSHEADER_TYPE*  pClassRes = rId.GetpResource();
     933           0 :     RESOURCE_TYPE   nRT = rId.GetRT2();
     934           0 :     sal_uInt32      nId = rId.GetId();
     935           0 :     const ResMgr*   pMgr = rId.GetResMgr();
     936             : 
     937           0 :     if ( !pMgr )
     938           0 :         pMgr = this;
     939             : 
     940           0 :     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           0 :     if ( !pResObj || pResObj == pMgr->aStack[pMgr->nCurStack].pResObj )
     948             :     {
     949           0 :         if ( !pClassRes )
     950           0 :             pClassRes = LocalResource( &pMgr->aStack[pMgr->nCurStack], nRT, nId );
     951           0 :         if ( pClassRes )
     952             :         {
     953           0 :             if ( pClassRes->GetRT() == nRT )
     954           0 :                 bAvailable = true;
     955             :         }
     956             :     }
     957             : 
     958           0 :     if ( !pClassRes )
     959           0 :         bAvailable = pMgr->pImpRes->IsGlobalAvailable( nRT, nId );
     960             : 
     961           0 :     return bAvailable;
     962             : }
     963             : 
     964           0 : void* ResMgr::GetClass()
     965             : {
     966           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     967             : 
     968           0 :     if( pFallbackResMgr )
     969           0 :         return pFallbackResMgr->GetClass();
     970             : 
     971           0 :     return aStack[nCurStack].pClassRes;
     972             : }
     973             : 
     974           0 : bool ResMgr::GetResource( const ResId& rId, const Resource* pResObj )
     975             : {
     976           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
     977             : 
     978           0 :     if( pFallbackResMgr )
     979             :     {
     980           0 :         ResId aId( rId );
     981           0 :         aId.SetResMgr( NULL );
     982           0 :         return pFallbackResMgr->GetResource( aId, pResObj );
     983             :     }
     984             : 
     985           0 :     ResMgr* pMgr = rId.GetResMgr();
     986           0 :     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           0 :     ImpRCStack* pTop = &aStack[nCurStack];
     992           0 :     if( (pTop->Flags & RC_NOTFOUND) )
     993             :     {
     994           0 :         decStack();
     995             :     }
     996             : 
     997           0 :     RSHEADER_TYPE*  pClassRes = rId.GetpResource();
     998           0 :     RESOURCE_TYPE   nRT = rId.GetRT2();
     999           0 :     sal_uInt32      nId = rId.GetId();
    1000             : 
    1001           0 :     incStack();
    1002           0 :     pTop = &aStack[nCurStack];
    1003             :     pTop->Init( pMgr, pResObj, nId |
    1004           0 :                 (rId.IsAutoRelease() ? 0 : RSC_DONTRELEASE) );
    1005             : 
    1006           0 :     if ( pClassRes )
    1007             :     {
    1008           0 :         if ( pClassRes->GetRT() == nRT )
    1009           0 :             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           0 :         pTop->pClassRes = LocalResource( &aStack[nCurStack-1], nRT, nId );
    1026             :     }
    1027             : 
    1028           0 :     if ( pTop->pClassRes )
    1029             :         // lokale Resource, nicht system Resource
    1030           0 :         pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
    1031             :     else
    1032             :     {
    1033           0 :         pTop->pClassRes = pImpRes->LoadGlobalRes( nRT, nId, &pTop->aResHandle );
    1034           0 :         if ( pTop->pClassRes )
    1035             :         {
    1036           0 :             pTop->Flags |= RC_GLOBAL;
    1037           0 :             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           0 :     return true;
    1073             : }
    1074             : 
    1075           0 : void * ResMgr::GetResourceSkipHeader( const ResId& rResId, ResMgr ** ppResMgr )
    1076             : {
    1077           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1078             : 
    1079             :     DBG_ASSERT( rResId.GetResMgr(), "illegal ResId without ResMgr" );
    1080           0 :     *ppResMgr = rResId.GetResMgr();
    1081           0 :     if( *ppResMgr )
    1082             :     {
    1083           0 :         (*ppResMgr)->GetResource( rResId );
    1084           0 :         (*ppResMgr)->Increment( sizeof( RSHEADER_TYPE ) );
    1085           0 :         return (*ppResMgr)->GetClass();
    1086             :     }
    1087           0 :     return getEmptyBuffer();
    1088             : }
    1089             : 
    1090           0 : void ResMgr::PopContext( const Resource* pResObj )
    1091             : {
    1092           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1093             : 
    1094           0 :     if( pFallbackResMgr )
    1095             :     {
    1096           0 :         pFallbackResMgr->PopContext( pResObj );
    1097           0 :         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           0 :     if ( nCurStack > 0 )
    1112             :     {
    1113           0 :         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           0 :         if( (pTop->Flags & (RC_GLOBAL | RC_NOTFOUND)) == RC_GLOBAL )
    1132             :             // free global resource if resource is foreign
    1133           0 :             InternalResMgr::FreeGlobalRes( pTop->aResHandle, pTop->pResource );
    1134           0 :         decStack();
    1135           0 :     }
    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           0 : sal_Int16 ResMgr::GetShort( void * pShort )
    1167             : {
    1168           0 :     return ((*((sal_uInt8*)pShort + 0) << 8) |
    1169           0 :             (*((sal_uInt8*)pShort + 1) << 0)   );
    1170             : }
    1171             : 
    1172           0 : sal_Int32 ResMgr::GetLong( void * pLong )
    1173             : {
    1174           0 :     return ((*((sal_uInt8*)pLong + 0) << 24) |
    1175           0 :             (*((sal_uInt8*)pLong + 1) << 16) |
    1176           0 :             (*((sal_uInt8*)pLong + 2) <<  8) |
    1177           0 :             (*((sal_uInt8*)pLong + 3) <<  0)   );
    1178             : }
    1179             : 
    1180           0 : sal_uInt64 ResMgr::GetUInt64( void* pDatum )
    1181             : {
    1182           0 :     return ((sal_uInt64(*((sal_uInt8*)pDatum + 0)) << 56) |
    1183           0 :             (sal_uInt64(*((sal_uInt8*)pDatum + 1)) << 48) |
    1184           0 :             (sal_uInt64(*((sal_uInt8*)pDatum + 2)) << 40) |
    1185           0 :             (sal_uInt64(*((sal_uInt8*)pDatum + 3)) << 32) |
    1186           0 :             (sal_uInt64(*((sal_uInt8*)pDatum + 4)) << 24) |
    1187           0 :             (sal_uInt64(*((sal_uInt8*)pDatum + 5)) << 16) |
    1188           0 :             (sal_uInt64(*((sal_uInt8*)pDatum + 6)) <<  8) |
    1189           0 :             (sal_uInt64(*((sal_uInt8*)pDatum + 7)) <<  0)   );
    1190             : }
    1191             : 
    1192           0 : sal_uInt32 ResMgr::GetStringWithoutHook( OUString& rStr, const sal_uInt8* pStr )
    1193             : {
    1194           0 :     sal_uInt32 nLen=0;
    1195           0 :     sal_uInt32 nRet = GetStringSize( pStr, nLen );
    1196           0 :     const sal_Char* str = reinterpret_cast< const sal_Char* >( pStr );
    1197           0 :     OUString aString( str, strlen( str ), RTL_TEXTENCODING_UTF8,
    1198             :                        RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |
    1199             :                        RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
    1200           0 :                        RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
    1201           0 :     rStr = aString;
    1202           0 :     return nRet;
    1203             : }
    1204             : 
    1205           0 : sal_uInt32 ResMgr::GetString( OUString& rStr, const sal_uInt8* pStr )
    1206             : {
    1207           0 :     OUString aString;
    1208           0 :     sal_uInt32 nRet =  GetStringWithoutHook( aString, pStr );
    1209           0 :     if ( pImplResHookProc )
    1210           0 :         aString = pImplResHookProc( aString );
    1211           0 :     rStr = aString;
    1212           0 :     return nRet;
    1213             : }
    1214             : 
    1215           0 : sal_uInt32 ResMgr::GetByteString( OString& rStr, const sal_uInt8* pStr )
    1216             : {
    1217           0 :     sal_uInt32 nLen=0;
    1218           0 :     sal_uInt32 nRet = GetStringSize( pStr, nLen );
    1219           0 :     rStr = OString( (const sal_Char*)pStr, nLen );
    1220           0 :     return nRet;
    1221             : }
    1222             : 
    1223           0 : sal_uInt32 ResMgr::GetStringSize( const sal_uInt8* pStr, sal_uInt32& nLen )
    1224             : {
    1225           0 :     nLen = static_cast< sal_uInt32 >( strlen( (const char*)pStr ) );
    1226           0 :     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           0 :     return  (sal_uInt32)((sal_IntPtr)(sal_uInt8 *)rTop.pResource +
    1238           0 :                      rTop.pResource->GetLocalOff() -
    1239           0 :                      (sal_IntPtr)(sal_uInt8 *)rTop.pClassRes);
    1240             : }
    1241             : 
    1242           0 : void* ResMgr::Increment( sal_uInt32 nSize )
    1243             : {
    1244           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1245             : 
    1246           0 :     if( pFallbackResMgr )
    1247           0 :         return pFallbackResMgr->Increment( nSize );
    1248             : 
    1249           0 :     ImpRCStack& rStack = aStack[nCurStack];
    1250           0 :     if( (rStack.Flags & RC_NOTFOUND) )
    1251           0 :         return rStack.pClassRes;
    1252             : 
    1253           0 :     sal_uInt8* pClassRes = (sal_uInt8*)rStack.pClassRes + nSize;
    1254             : 
    1255           0 :     rStack.pClassRes = pClassRes;
    1256             : 
    1257           0 :     RSHEADER_TYPE* pRes = rStack.pResource;
    1258             : 
    1259           0 :     sal_uInt32 nLocalOff = pRes->GetLocalOff();
    1260           0 :     if ( (pRes->GetGlobOff() == nLocalOff) &&
    1261           0 :          (((char*)pRes + nLocalOff) == rStack.pClassRes) &&
    1262           0 :          (rStack.Flags & RC_AUTORELEASE))
    1263             :     {
    1264           0 :         PopContext( rStack.pResObj );
    1265             :     }
    1266             : 
    1267           0 :     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           0 : ResMgr* ResMgr::CreateResMgr( const sal_Char* pPrefixName,
    1332             :                               LanguageTag aLocale )
    1333             : {
    1334           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1335             : 
    1336           0 :     OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
    1337             : 
    1338           0 :     if( aLocale.isSystemLocale() )
    1339           0 :         aLocale = ResMgrContainer::get().getDefLocale();
    1340             : 
    1341           0 :     InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, aLocale );
    1342           0 :     return pImp ? new ResMgr( pImp ) : NULL;
    1343             : }
    1344             : 
    1345           0 : ResMgr* ResMgr::SearchCreateResMgr(
    1346             :     const sal_Char* pPrefixName,
    1347             :     LanguageTag& rLocale )
    1348             : {
    1349           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1350             : 
    1351           0 :     OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
    1352             : 
    1353           0 :     if( rLocale.isSystemLocale() )
    1354           0 :         rLocale = ResMgrContainer::get().getDefLocale();
    1355             : 
    1356           0 :     InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, rLocale );
    1357           0 :     return pImp ? new ResMgr( pImp ) : NULL;
    1358             : }
    1359             : 
    1360           0 : sal_Int16 ResMgr::ReadShort()
    1361             : {
    1362           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1363             : 
    1364           0 :     if( pFallbackResMgr )
    1365           0 :         return pFallbackResMgr->ReadShort();
    1366             : 
    1367           0 :     sal_Int16 n = GetShort( GetClass() );
    1368           0 :     Increment( sizeof( sal_Int16 ) );
    1369           0 :     return n;
    1370             : }
    1371             : 
    1372           0 : sal_Int32 ResMgr::ReadLong()
    1373             : {
    1374           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1375             : 
    1376           0 :     if( pFallbackResMgr )
    1377           0 :         return pFallbackResMgr->ReadLong();
    1378             : 
    1379           0 :     sal_Int32 n = GetLong( GetClass() );
    1380           0 :     Increment( sizeof( sal_Int32 ) );
    1381           0 :     return n;
    1382             : }
    1383             : 
    1384           0 : OUString ResMgr::ReadStringWithoutHook()
    1385             : {
    1386           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1387             : 
    1388           0 :     if( pFallbackResMgr )
    1389           0 :         return pFallbackResMgr->ReadStringWithoutHook();
    1390             : 
    1391           0 :     OUString aRet;
    1392             : 
    1393           0 :     const ImpRCStack& rTop = aStack[nCurStack];
    1394           0 :     if( (rTop.Flags & RC_NOTFOUND) )
    1395             :     {
    1396             :         #if OSL_DEBUG_LEVEL > 0
    1397             :         aRet = "<resource not found>";
    1398             :         #endif
    1399             :     }
    1400             :     else
    1401           0 :         Increment( GetStringWithoutHook( aRet, (const sal_uInt8*)GetClass() ) );
    1402             : 
    1403           0 :     return aRet;
    1404             : }
    1405             : 
    1406           0 : OUString ResMgr::ReadString()
    1407             : {
    1408           0 :     OUString aRet = ReadStringWithoutHook();
    1409           0 :     if ( pImplResHookProc )
    1410           0 :         aRet = pImplResHookProc( aRet );
    1411           0 :     return aRet;
    1412             : }
    1413             : 
    1414           0 : OString ResMgr::ReadByteString()
    1415             : {
    1416           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1417             : 
    1418           0 :     if( pFallbackResMgr )
    1419           0 :         return pFallbackResMgr->ReadByteString();
    1420             : 
    1421           0 :     OString aRet;
    1422             : 
    1423           0 :     const ImpRCStack& rTop = aStack[nCurStack];
    1424           0 :     if( (rTop.Flags & RC_NOTFOUND) )
    1425             :     {
    1426             :         #if OSL_DEBUG_LEVEL > 0
    1427             :         aRet = OString( "<resource not found>" );
    1428             :         #endif
    1429             :     }
    1430             :     else
    1431           0 :         Increment( GetByteString( aRet, (const sal_uInt8*)GetClass() ) );
    1432             : 
    1433           0 :     return aRet;
    1434             : }
    1435             : 
    1436           0 : OString ResMgr::GetAutoHelpId()
    1437             : {
    1438           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1439             : 
    1440           0 :     if( pFallbackResMgr )
    1441           0 :         return pFallbackResMgr->GetAutoHelpId();
    1442             : 
    1443             :     OSL_ENSURE( nCurStack, "resource stack empty in Auto help id generation" );
    1444           0 :     if( nCurStack < 1 || nCurStack > 2 )
    1445           0 :         return OString();
    1446             : 
    1447             :     // prepare HID, start with resource prefix
    1448           0 :     OStringBuffer aHID( 32 );
    1449           0 :     aHID.append( OUStringToOString( pImpRes->aPrefix, RTL_TEXTENCODING_UTF8 ) );
    1450           0 :     aHID.append( '.' );
    1451             : 
    1452             :     // append type
    1453           0 :     const ImpRCStack *pRC = StackTop();
    1454             :     OSL_ENSURE( pRC, "missing resource stack level" );
    1455             : 
    1456           0 :     if ( nCurStack == 1 )
    1457             :     {
    1458             :         // auto help ids for top level windows
    1459           0 :         switch( pRC->pResource->GetRT() ) {
    1460           0 :             case RSC_DOCKINGWINDOW:     aHID.append( "DockingWindow" );    break;
    1461           0 :             case RSC_WORKWIN:           aHID.append( "WorkWindow" );       break;
    1462           0 :             case RSC_MODELESSDIALOG:    aHID.append( "ModelessDialog" );   break;
    1463           0 :             case RSC_FLOATINGWINDOW:    aHID.append( "FloatingWindow" );   break;
    1464           0 :             case RSC_MODALDIALOG:       aHID.append( "ModalDialog" );      break;
    1465           0 :             case RSC_TABPAGE:           aHID.append( "TabPage" );          break;
    1466           0 :             default: return OString();
    1467             :         }
    1468             :     }
    1469             :     else
    1470             :     {
    1471             :         // only controls with the following parents get auto help ids
    1472           0 :         const ImpRCStack *pRC1 = StackTop(1);
    1473           0 :         switch( pRC1->pResource->GetRT() ) {
    1474             :             case RSC_DOCKINGWINDOW:
    1475             :             case RSC_WORKWIN:
    1476             :             case RSC_MODELESSDIALOG:
    1477             :             case RSC_FLOATINGWINDOW:
    1478             :             case RSC_MODALDIALOG:
    1479             :             case RSC_TABPAGE:
    1480             :                 // intentionally no breaks!
    1481             :                 // auto help ids for controls
    1482           0 :                 switch( pRC->pResource->GetRT() ) {
    1483           0 :                     case RSC_TABCONTROL:        aHID.append( "TabControl" );       break;
    1484           0 :                     case RSC_RADIOBUTTON:       aHID.append( "RadioButton" );      break;
    1485           0 :                     case RSC_CHECKBOX:          aHID.append( "CheckBox" );         break;
    1486           0 :                     case RSC_TRISTATEBOX:       aHID.append( "TriStateBox" );      break;
    1487           0 :                     case RSC_EDIT:              aHID.append( "Edit" );             break;
    1488           0 :                     case RSC_MULTILINEEDIT:     aHID.append( "MultiLineEdit" );    break;
    1489           0 :                     case RSC_MULTILISTBOX:      aHID.append( "MultiListBox" );     break;
    1490           0 :                     case RSC_LISTBOX:           aHID.append( "ListBox" );          break;
    1491           0 :                     case RSC_COMBOBOX:          aHID.append( "ComboBox" );         break;
    1492           0 :                     case RSC_PUSHBUTTON:        aHID.append( "PushButton" );       break;
    1493           0 :                     case RSC_SPINFIELD:         aHID.append( "SpinField" );        break;
    1494           0 :                     case RSC_PATTERNFIELD:      aHID.append( "PatternField" );     break;
    1495           0 :                     case RSC_NUMERICFIELD:      aHID.append( "NumericField" );     break;
    1496           0 :                     case RSC_METRICFIELD:       aHID.append( "MetricField" );      break;
    1497           0 :                     case RSC_DATEFIELD:         aHID.append( "DateField" );        break;
    1498           0 :                     case RSC_TIMEFIELD:         aHID.append( "TimeField" );        break;
    1499           0 :                     case RSC_NUMERICBOX:        aHID.append( "NumericBox" );       break;
    1500           0 :                     case RSC_IMAGEBUTTON:       aHID.append( "ImageButton" );      break;
    1501           0 :                     case RSC_MENUBUTTON:        aHID.append( "MenuButton" );       break;
    1502             :                     default:
    1503             :                         // no type, no auto HID
    1504           0 :                         return OString();
    1505             :                 }
    1506           0 :                 break;
    1507             :             default:
    1508           0 :                 return OString();
    1509             :         }
    1510             :     }
    1511             : 
    1512             :     // append resource id hierarchy
    1513           0 :     for( int nOff = nCurStack-1; nOff >= 0; nOff-- )
    1514             :     {
    1515           0 :         aHID.append( '.' );
    1516           0 :         pRC = StackTop( nOff );
    1517             : 
    1518             :         OSL_ENSURE( pRC->pResource, "missing resource in resource stack level !" );
    1519           0 :         if( pRC->pResource )
    1520           0 :             aHID.append( sal_Int32( pRC->pResource->GetId() ) );
    1521             :     }
    1522             : 
    1523           0 :     return aHID.makeStringAndClear();
    1524             : }
    1525             : 
    1526           0 : void ResMgr::SetReadStringHook( ResHookProc pProc )
    1527             : {
    1528           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1529           0 :     pImplResHookProc = pProc;
    1530           0 : }
    1531             : 
    1532           0 : ResHookProc ResMgr::GetReadStringHook()
    1533             : {
    1534           0 :     return pImplResHookProc;
    1535             : }
    1536             : 
    1537           0 : void ResMgr::SetDefaultLocale( const LanguageTag& rLocale )
    1538             : {
    1539           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1540           0 :     ResMgrContainer::get().setDefLocale( rLocale );
    1541           0 : }
    1542             : 
    1543           0 : const OUString& ResMgr::GetFileName() const
    1544             : {
    1545           0 :     return pImpRes->aFileName;
    1546             : }
    1547             : 
    1548           0 : SimpleResMgr::SimpleResMgr( const sal_Char* pPrefixName,
    1549           0 :                             const LanguageTag& rLocale )
    1550             : {
    1551           0 :     OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
    1552           0 :     LanguageTag aLocale( rLocale );
    1553             : 
    1554           0 :     osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
    1555           0 :     if( aLocale.isSystemLocale() )
    1556           0 :         aLocale = ResMgrContainer::get().getDefLocale();
    1557             : 
    1558           0 :     m_pResImpl = ResMgrContainer::get().getResMgr( aPrefix, aLocale, true );
    1559           0 :     DBG_ASSERT( m_pResImpl, "SimpleResMgr::SimpleResMgr : have no impl class !" );
    1560           0 : }
    1561             : 
    1562           0 : SimpleResMgr::~SimpleResMgr()
    1563             : {
    1564           0 :     delete m_pResImpl;
    1565           0 : }
    1566             : 
    1567           0 : SimpleResMgr* SimpleResMgr::Create( const sal_Char* pPrefixName, LanguageTag aLocale )
    1568             : {
    1569           0 :     return new SimpleResMgr( pPrefixName, aLocale );
    1570             : }
    1571             : 
    1572           0 : bool SimpleResMgr::IsAvailable( RESOURCE_TYPE _resourceType, sal_uInt32 _resourceId )
    1573             : {
    1574           0 :     osl::MutexGuard aGuard(m_aAccessSafety);
    1575             : 
    1576           0 :     if ( ( RSC_STRING != _resourceType ) && ( RSC_RESOURCE != _resourceType ) )
    1577           0 :         return false;
    1578             : 
    1579             :     DBG_ASSERT( m_pResImpl, "SimpleResMgr::IsAvailable: have no impl class !" );
    1580           0 :     return m_pResImpl->IsGlobalAvailable( _resourceType, _resourceId );
    1581             : }
    1582             : 
    1583           0 : OUString SimpleResMgr::ReadString( sal_uInt32 nId )
    1584             : {
    1585           0 :     osl::MutexGuard aGuard(m_aAccessSafety);
    1586             : 
    1587             :     DBG_ASSERT( m_pResImpl, "SimpleResMgr::ReadString : have no impl class !" );
    1588             :     // perhaps constructed with an invalid filename ?
    1589             : 
    1590           0 :     OUString sReturn;
    1591           0 :     if ( !m_pResImpl )
    1592           0 :         return sReturn;
    1593             : 
    1594           0 :     void* pResHandle = NULL;
    1595           0 :     InternalResMgr* pFallback = m_pResImpl;
    1596           0 :     RSHEADER_TYPE* pResHeader = (RSHEADER_TYPE*)m_pResImpl->LoadGlobalRes( RSC_STRING, nId, &pResHandle );
    1597           0 :     if ( !pResHeader )
    1598             :     {
    1599           0 :         osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
    1600             : 
    1601             :         // try fallback
    1602           0 :         while( ! pResHandle && pFallback )
    1603             :         {
    1604           0 :             InternalResMgr* pOldFallback = pFallback;
    1605           0 :             pFallback = ResMgrContainer::get().getNextFallback( pFallback );
    1606           0 :             if( pOldFallback != m_pResImpl )
    1607           0 :                 ResMgrContainer::get().freeResMgr( pOldFallback );
    1608           0 :             if( pFallback )
    1609             :             {
    1610             :                 // handle possible recursion
    1611           0 :                 if( pFallback->aLocale != m_pResImpl->aLocale )
    1612             :                 {
    1613           0 :                     pResHeader = (RSHEADER_TYPE*)pFallback->LoadGlobalRes( RSC_STRING, nId, &pResHandle );
    1614             :                 }
    1615             :                 else
    1616             :                 {
    1617           0 :                     ResMgrContainer::get().freeResMgr( pFallback );
    1618           0 :                     pFallback = NULL;
    1619             :                 }
    1620             :             }
    1621             :         }
    1622           0 :         if( ! pResHandle )
    1623             :             // no such resource
    1624           0 :             return sReturn;
    1625             :     }
    1626             : 
    1627             :     // sal_uIntPtr nLen = pResHeader->GetLocalOff() - sizeof(RSHEADER_TYPE);
    1628           0 :     ResMgr::GetString( sReturn, (const sal_uInt8*)(pResHeader+1) );
    1629             : 
    1630             :     // not necessary with te current implementation which holds the string table permanently, but to be sure ....
    1631             :     // note: pFallback cannot be NULL here and is either the fallback or m_pResImpl
    1632           0 :     InternalResMgr::FreeGlobalRes( pResHeader, pResHandle );
    1633           0 :     if( m_pResImpl != pFallback )
    1634             :     {
    1635           0 :         osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
    1636             : 
    1637           0 :         ResMgrContainer::get().freeResMgr( pFallback );
    1638             :     }
    1639           0 :     return sReturn;
    1640             : }
    1641             : 
    1642             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10