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

Generated by: LCOV version 1.11