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