Update ooo320-m1
[ooovba.git] / tools / source / rc / resmgr.cxx
blob198b028d8b62a312bd81e2915320fd43b2858742
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: resmgr.cxx,v $
10 * $Revision: 1.52.30.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
34 #include <string.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <vos/signal.hxx>
38 #include <tools/debug.hxx>
39 #ifndef _TABLE_HXX
40 #include <tools/table.hxx>
41 #endif
42 #include <tools/stream.hxx>
43 #include <tools/resmgr.hxx>
44 #include <tools/rc.hxx>
45 #include <tools/rcid.h>
46 #include <osl/endian.h>
47 #include <osl/process.h>
48 #include <osl/thread.h>
49 #include <osl/file.hxx>
50 #include <osl/mutex.hxx>
51 #include <rtl/ustrbuf.hxx>
52 #include <tools/urlobj.hxx>
53 #include <rtl/instance.hxx>
54 #include <rtl/bootstrap.hxx>
55 #include <i18npool/mslangid.hxx>
56 #include <tools/simplerm.hxx>
58 #include <tools/isofallback.hxx>
60 #include <functional>
61 #include <algorithm>
62 #include <hash_map>
63 #include <list>
64 #include <set>
66 #ifdef UNX
67 #define SEARCH_PATH_DELIMITER_CHAR_STRING ":"
68 #define SEARCH_PATH_DELIMITER ':'
69 #else
70 #define SEARCH_PATH_DELIMITER_CHAR_STRING ";"
71 #define SEARCH_PATH_DELIMITER ';'
72 #endif
74 #define SEARCH_PATH_DELIMITER_STRING ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SEARCH_PATH_DELIMITER_CHAR_STRING ) )
76 using namespace rtl;
77 using namespace osl;
79 // for thread safety
80 static osl::Mutex* pResMgrMutex = NULL;
81 static osl::Mutex& getResMgrMutex()
83 if( !pResMgrMutex )
85 osl::Guard<osl::Mutex> aGuard( *osl::Mutex::getGlobalMutex() );
86 if( ! pResMgrMutex )
87 pResMgrMutex = new osl::Mutex();
89 return *pResMgrMutex;
92 struct ImpContent;
93 class InternalResMgr
95 friend class ResMgr;
96 friend class SimpleResMgr;
97 friend class ResMgrContainer;
99 ImpContent * pContent;
100 UINT32 nOffCorrection;
101 BYTE * pStringBlock;
102 SvStream * pStm;
103 BOOL bEqual2Content;
104 UINT32 nEntries;
105 OUString aFileName;
106 OUString aPrefix;
107 OUString aResName;
108 bool bSingular;
109 com::sun::star::lang::Locale aLocale;
110 std::hash_map<sal_uInt64, int>* pResUseDump;
112 InternalResMgr( const OUString& rFileURL,
113 const OUString& aPrefix,
114 const OUString& aResName,
115 const com::sun::star::lang::Locale& rLocale );
116 ~InternalResMgr();
117 BOOL Create();
119 BOOL IsGlobalAvailable( RESOURCE_TYPE nRT, sal_uInt32 nId ) const;
120 void * LoadGlobalRes( RESOURCE_TYPE nRT, sal_uInt32 nId,
121 void **pResHandle );
122 public:
123 void FreeGlobalRes( void *, void * );
125 SvStream * GetBitmapStream( sal_uInt32 nResId );
128 // =======================================================================
130 class ResMgrContainer
132 static ResMgrContainer* pOneInstance;
134 struct ContainerElement
136 InternalResMgr* pResMgr;
137 OUString aFileURL;
138 int nRefCount;
139 int nLoadCount;
141 ContainerElement() :
142 pResMgr( NULL ),
143 nRefCount( 0 ),
144 nLoadCount( 0 )
148 std::hash_map< OUString, ContainerElement, OUStringHash> m_aResFiles;
149 com::sun::star::lang::Locale m_aDefLocale;
151 ResMgrContainer() { init(); }
152 ~ResMgrContainer();
154 void init();
155 public:
157 static ResMgrContainer& get();
158 static void release();
160 InternalResMgr* getResMgr( const OUString& rPrefix,
161 com::sun::star::lang::Locale& rLocale,
162 bool bForceNewInstance = false
164 InternalResMgr* getNextFallback( InternalResMgr* pResMgr );
166 void freeResMgr( InternalResMgr* pResMgr );
168 void setDefLocale( const com::sun::star::lang::Locale& rLocale )
169 { m_aDefLocale = rLocale; }
170 const com::sun::star::lang::Locale& getDefLocale() const
171 { return m_aDefLocale; }
174 ResMgrContainer* ResMgrContainer::pOneInstance = NULL;
176 ResMgrContainer& ResMgrContainer::get()
178 if( ! pOneInstance )
179 pOneInstance = new ResMgrContainer();
180 return *pOneInstance;
183 ResMgrContainer::~ResMgrContainer()
185 for( std::hash_map< OUString, ContainerElement, OUStringHash >::iterator it =
186 m_aResFiles.begin(); it != m_aResFiles.end(); ++it )
188 OSL_TRACE( "Resource file %s loaded %d times\n",
189 OUStringToOString( it->second.aFileURL, osl_getThreadTextEncoding() ).getStr(),
190 it->second.nLoadCount );
191 delete it->second.pResMgr;
195 void ResMgrContainer::release()
197 delete pOneInstance;
198 pOneInstance = NULL;
201 void ResMgrContainer::init()
203 // get resource path
204 std::list< OUString > aDirs;
205 sal_Int32 nIndex = 0;
207 // 1. fixed locations
208 rtl::OUString uri(
209 RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program/resource"));
210 rtl::Bootstrap::expandMacros(uri);
211 aDirs.push_back(uri);
212 uri = rtl::OUString(
213 RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/program/resource"));
214 rtl::Bootstrap::expandMacros(uri);
215 aDirs.push_back(uri);
217 // 2. in STAR_RESOURCEPATH
218 const sal_Char* pEnv = getenv( "STAR_RESOURCEPATH" );
219 if( pEnv )
221 OUString aEnvPath( OStringToOUString( OString( pEnv ), osl_getThreadTextEncoding() ) );
222 nIndex = 0;
223 while( nIndex >= 0 )
225 OUString aPathElement( aEnvPath.getToken( 0, SEARCH_PATH_DELIMITER, nIndex ) );
226 if( aPathElement.getLength() )
228 OUString aFileURL;
229 File::getFileURLFromSystemPath( aPathElement, aFileURL );
230 aDirs.push_back( aFileURL);
235 // collect all possible resource files
236 for( std::list< OUString >::const_iterator dir_it = aDirs.begin(); dir_it != aDirs.end(); ++dir_it )
238 Directory aDir( *dir_it );
239 if( aDir.open() == FileBase::E_None )
241 DirectoryItem aItem;
242 while( aDir.getNextItem( aItem ) == FileBase::E_None )
244 FileStatus aStatus(FileStatusMask_FileName);
245 if( aItem.getFileStatus( aStatus ) == FileBase::E_None )
247 OUString aFileName = aStatus.getFileName();
248 if( aFileName.getLength() < 5 )
249 continue;
250 if( ! aFileName.endsWithIgnoreAsciiCaseAsciiL( ".res", 4 ) )
251 continue;
252 OUString aResName = aFileName.copy( 0, aFileName.getLength()-4 );
253 if( m_aResFiles.find( aResName ) != m_aResFiles.end() )
254 continue;
255 OUStringBuffer aURL( dir_it->getLength() + aFileName.getLength() + 1 );
256 aURL.append( *dir_it );
257 if( !dir_it->endsWithIgnoreAsciiCaseAsciiL( "/", 1 ) )
258 aURL.append( sal_Unicode('/') );
259 aURL.append( aFileName );
260 m_aResFiles[ aResName ].aFileURL = aURL.makeStringAndClear();
264 #if OSL_DEBUG_LEVEL > 1
265 else
266 OSL_TRACE( "opening dir %s failed\n", OUStringToOString( *dir_it, osl_getThreadTextEncoding() ).getStr() );
267 #endif
269 #if OSL_DEBUG_LEVEL > 1
270 for( std::hash_map< OUString, ContainerElement, OUStringHash >::const_iterator it =
271 m_aResFiles.begin(); it != m_aResFiles.end(); ++it )
273 OSL_TRACE( "ResMgrContainer: %s -> %s\n",
274 OUStringToOString( it->first, osl_getThreadTextEncoding() ).getStr(),
275 OUStringToOString( it->second.aFileURL, osl_getThreadTextEncoding() ).getStr() );
277 #endif
279 // set default language
280 LanguageType nLang = MsLangId::getSystemUILanguage();
281 MsLangId::convertLanguageToLocale(nLang, m_aDefLocale);
284 InternalResMgr* ResMgrContainer::getResMgr( const OUString& rPrefix,
285 com::sun::star::lang::Locale& rLocale,
286 bool bForceNewInstance
289 com::sun::star::lang::Locale aLocale( rLocale );
290 OUStringBuffer aSearch( rPrefix.getLength() + 16 );
291 std::hash_map< OUString, ContainerElement, OUStringHash >::iterator it = m_aResFiles.end();
293 int nTries = 0;
294 if( aLocale.Language.getLength() > 0 )
295 nTries = 1;
296 if( aLocale.Country.getLength() > 0 )
297 nTries = 2;
298 if( aLocale.Variant.getLength() > 0 )
299 nTries = 3;
300 while( nTries-- )
302 aSearch.append( rPrefix );
303 if( nTries > -1 )
305 aSearch.append( aLocale.Language );
307 if( nTries > 0 )
309 aSearch.append( sal_Unicode('-') );
310 aSearch.append( aLocale.Country );
312 if( nTries > 1 )
314 aSearch.append( sal_Unicode('-') );
315 aSearch.append( aLocale.Variant );
317 it = m_aResFiles.find( aSearch.makeStringAndClear() );
318 if( it != m_aResFiles.end() )
320 // ensure InternalResMgr existance
321 if( ! it->second.pResMgr )
323 InternalResMgr* pImp =
324 new InternalResMgr( it->second.aFileURL, rPrefix, it->first, aLocale );
325 if( ! pImp->Create() )
327 delete pImp;
328 continue;
330 it->second.pResMgr = pImp;
332 break;
334 if( nTries == 0 && !aLocale.Language.equalsIgnoreAsciiCaseAscii( "en" ) )
336 // locale fallback failed
337 // fallback to en-US locale
338 nTries = 2;
339 aLocale.Language = OUString( RTL_CONSTASCII_USTRINGPARAM( "en" ) );
340 aLocale.Country = OUString( RTL_CONSTASCII_USTRINGPARAM( "US" ) );
341 aLocale.Variant = OUString();
344 // try if there is anything with this prefix at all
345 if( it == m_aResFiles.end() )
347 aLocale = com::sun::star::lang::Locale();
348 it = m_aResFiles.find( rPrefix );
349 if( it == m_aResFiles.end() )
351 for( it = m_aResFiles.begin(); it != m_aResFiles.end(); ++it )
353 if( it->first.matchIgnoreAsciiCase( rPrefix ) )
355 // ensure InternalResMgr existance
356 if( ! it->second.pResMgr )
358 InternalResMgr* pImp =
359 new InternalResMgr( it->second.aFileURL,
360 rPrefix,
361 it->first,
362 aLocale );
363 if( ! pImp->Create() )
365 delete pImp;
366 continue;
368 it->second.pResMgr = pImp;
370 // try to guess locale
371 sal_Int32 nIndex = rPrefix.getLength();
372 aLocale.Language = it->first.getToken( 0, '-', nIndex );
373 if( nIndex > 0 )
374 aLocale.Country = it->first.getToken( 0, '-', nIndex );
375 if( nIndex > 0 )
376 aLocale.Variant = it->first.getToken( 0, '-', nIndex );
377 break;
382 // give up
383 if( it == m_aResFiles.end() )
385 OUStringBuffer sKey = rPrefix;
386 sKey.append( rLocale.Language );
387 if( rLocale.Country.getLength() )
389 sKey.append( sal_Unicode('-') );
390 sKey.append( rLocale.Country );
392 if( rLocale.Variant.getLength() )
394 sKey.append( sal_Unicode('-') );
395 sKey.append( rLocale.Variant );
396 } // if( aLocale.Variant.getLength() )
397 ::rtl::OUString sURL = sKey.makeStringAndClear();
398 sURL += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".res"));
399 if ( m_aResFiles.find(sURL) == m_aResFiles.end() )
401 m_aResFiles[ sURL ].aFileURL = sURL;
402 return getResMgr(rPrefix,rLocale,bForceNewInstance);
403 } // if ( m_aResFiles.find(sURL) == m_aResFiles.end() )
404 return NULL;
407 rLocale = aLocale;
408 // at this point it->second.pResMgr must be filled either by creating a new one
409 // (then the refcount is still 0) or because we already had one
410 InternalResMgr* pImp = it->second.pResMgr;
412 if( it->second.nRefCount == 0 )
413 it->second.nLoadCount++;
415 // for SimpleResMgr
416 if( bForceNewInstance )
418 if( it->second.nRefCount == 0 )
420 // shortcut: the match algorithm already created the InternalResMgr
421 // take it instead of creating yet another one
422 it->second.pResMgr = NULL;
423 pImp->bSingular = true;
425 else
427 pImp = new InternalResMgr( it->second.aFileURL, rPrefix, it->first, aLocale );
428 pImp->bSingular = true;
429 if( !pImp->Create() )
431 delete pImp;
432 pImp = NULL;
434 else
435 it->second.nLoadCount++;
438 else
439 it->second.nRefCount++;
441 return pImp;
444 InternalResMgr* ResMgrContainer::getNextFallback( InternalResMgr* pMgr )
446 com::sun::star::lang::Locale aLocale = pMgr->aLocale;
447 if( aLocale.Variant.getLength() )
448 aLocale.Variant = OUString();
449 else if( aLocale.Country.getLength() )
450 aLocale.Country = OUString();
451 else if( ! aLocale.Language.equalsIgnoreAsciiCaseAscii( "en" ) )
453 aLocale.Language = OUString( RTL_CONSTASCII_USTRINGPARAM( "en" ) );
454 aLocale.Country = OUString( RTL_CONSTASCII_USTRINGPARAM( "US" ) );
456 InternalResMgr* pNext = getResMgr( pMgr->aPrefix, aLocale, pMgr->bSingular );
457 // prevent recursion
458 if( pNext == pMgr || pNext->aResName.equals( pMgr->aResName ) )
460 if( pNext->bSingular )
461 delete pNext;
462 pNext = NULL;
464 return pNext;
467 void ResMgrContainer::freeResMgr( InternalResMgr* pResMgr )
469 if( pResMgr->bSingular )
470 delete pResMgr;
471 else
473 std::hash_map< OUString, ContainerElement, OUStringHash >::iterator it =
474 m_aResFiles.find( pResMgr->aResName );
475 if( it != m_aResFiles.end() )
477 DBG_ASSERT( it->second.nRefCount > 0, "InternalResMgr freed too often" );
478 if( it->second.nRefCount > 0 )
479 it->second.nRefCount--;
480 if( it->second.nRefCount == 0 )
482 delete it->second.pResMgr;
483 it->second.pResMgr = NULL;
489 // =======================================================================
491 void Resource::TestRes()
493 if( m_pResMgr )
494 m_pResMgr->TestStack( this );
497 struct ImpContent
499 sal_uInt64 nTypeAndId;
500 sal_uInt32 nOffset;
503 struct ImpContentLessCompare : public ::std::binary_function< ImpContent, ImpContent, bool>
505 inline bool operator() (const ImpContent& lhs, const ImpContent& rhs) const
507 return lhs.nTypeAndId < rhs.nTypeAndId;
511 struct ImpContentMixLessCompare : public ::std::binary_function< ImpContent, sal_uInt64, bool>
513 inline bool operator() (const ImpContent& lhs, const sal_uInt64& rhs) const
515 return lhs.nTypeAndId < rhs;
517 inline bool operator() (const sal_uInt64& lhs, const ImpContent& rhs) const
519 return lhs < rhs.nTypeAndId;
524 // =======================================================================
526 static ResHookProc pImplResHookProc = 0;
528 // =======================================================================
530 SvStream * InternalResMgr::GetBitmapStream( sal_uInt32 nId )
532 // Anfang der Strings suchen
533 ImpContent * pFind = ::std::lower_bound(pContent,
534 pContent + nEntries,
535 ((sal_uInt64(RT_SYS_BITMAP) << 32) | nId),
536 ImpContentMixLessCompare());
537 if ( (pFind != (pContent + nEntries)) && (pFind->nTypeAndId == ((sal_uInt64(RT_SYS_BITMAP) << 32) | nId)) )
539 pStm->Seek( pFind->nOffset );
540 return pStm;
542 return NULL;
545 // -----------------------------------------------------------------------
547 InternalResMgr::InternalResMgr( const OUString& rFileURL,
548 const OUString& rPrefix,
549 const OUString& rResName,
550 const com::sun::star::lang::Locale& rLocale )
551 : pContent( NULL )
552 , pStringBlock( NULL )
553 , pStm( NULL )
554 , bEqual2Content( TRUE )
555 , nEntries( 0 )
556 , aFileName( rFileURL )
557 , aPrefix( rPrefix )
558 , aResName( rResName )
559 , bSingular( false )
560 , aLocale( rLocale )
561 , pResUseDump( 0 )
565 // -----------------------------------------------------------------------
567 InternalResMgr::~InternalResMgr()
569 rtl_freeMemory(pContent);
570 rtl_freeMemory(pStringBlock);
571 delete pStm;
573 #ifdef DBG_UTIL
574 if( pResUseDump )
576 const sal_Char* pLogFile = getenv( "STAR_RESOURCE_LOGGING" );
577 if ( pLogFile )
579 SvFileStream aStm( UniString( pLogFile, RTL_TEXTENCODING_ASCII_US ), STREAM_WRITE );
580 aStm.Seek( STREAM_SEEK_TO_END );
581 ByteString aLine( "FileName: " );
582 aLine.Append( ByteString( OUStringToOString( aFileName, RTL_TEXTENCODING_UTF8 ) ) );
583 aStm.WriteLine( aLine );
585 for( std::hash_map<sal_uInt64, int>::const_iterator it = pResUseDump->begin();
586 it != pResUseDump->end(); ++it )
588 sal_uInt64 nKeyId = it->first;
589 aLine.Assign( "Type/Id: " );
590 aLine.Append( ByteString::CreateFromInt32( sal::static_int_cast< sal_Int32 >((nKeyId >> 32) & 0xFFFFFFFF) ) );
591 aLine.Append( '/' );
592 aLine.Append( ByteString::CreateFromInt32( sal::static_int_cast< sal_Int32 >(nKeyId & 0xFFFFFFFF) ) );
593 aStm.WriteLine( aLine );
597 #endif
599 delete pResUseDump;
602 // -----------------------------------------------------------------------
605 BOOL InternalResMgr::Create()
607 ResMgrContainer::get();
608 BOOL bDone = FALSE;
610 pStm = new SvFileStream( aFileName, (STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE) );
611 if( pStm->GetError() == 0 )
613 INT32 lContLen = 0;
615 pStm->Seek( STREAM_SEEK_TO_END );
617 if( ( pInternalResMgr->pHead = (RSHEADER_TYPE *)mmap( 0, nResourceFileSize,
618 PROT_READ, MAP_PRIVATE,
619 fRes, 0 ) ) != (RSHEADER_TYPE *)-1)
621 pStm->SeekRel( - (int)sizeof( lContLen ) );
622 pStm->Read( &lContLen, sizeof( lContLen ) );
623 // is bigendian, swab to the right endian
624 lContLen = ResMgr::GetLong( &lContLen );
625 pStm->SeekRel( -lContLen );
626 // allocate stored ImpContent data (12 bytes per unit)
627 BYTE* pContentBuf = (BYTE*)rtl_allocateMemory( lContLen );
628 pStm->Read( pContentBuf, lContLen );
629 // allocate ImpContent space (sizeof(ImpContent) per unit, not necessarily 12)
630 pContent = (ImpContent *)rtl_allocateMemory( sizeof(ImpContent)*lContLen/12 );
631 // Auf die Anzahl der ImpContent k�rzen
632 nEntries = (UINT32)lContLen / 12;
633 bEqual2Content = TRUE; // Die Daten der Resourcen liegen
634 // genauso wie das Inhaltsverzeichnis
635 BOOL bSorted = TRUE;
636 if( nEntries )
638 #ifdef DBG_UTIL
639 const sal_Char* pLogFile = getenv( "STAR_RESOURCE_LOGGING" );
640 if ( pLogFile )
642 pResUseDump = new std::hash_map<sal_uInt64, int>;
643 for( sal_uInt32 i = 0; i < nEntries; ++i )
644 (*pResUseDump)[pContent[i].nTypeAndId] = 1;
646 #endif
647 // swap the content to the right endian
648 pContent[0].nTypeAndId = ResMgr::GetUInt64( pContentBuf );
649 pContent[0].nOffset = ResMgr::GetLong( pContentBuf+8 );
650 sal_uInt32 nCount = nEntries - 1;
651 for( sal_uInt32 i = 0,j=1; i < nCount; ++i,++j )
653 // swap the content to the right endian
654 pContent[j].nTypeAndId = ResMgr::GetUInt64( pContentBuf + (12*j) );
655 pContent[j].nOffset = ResMgr::GetLong( pContentBuf + (12*j+8) );
656 if( pContent[i].nTypeAndId >= pContent[j].nTypeAndId )
657 bSorted = FALSE;
658 if( (pContent[i].nTypeAndId & 0xFFFFFFFF00000000LL) == (pContent[j].nTypeAndId & 0xFFFFFFFF00000000LL)
659 && pContent[i].nOffset >= pContent[j].nOffset )
660 bEqual2Content = FALSE;
663 rtl_freeMemory( pContentBuf );
664 #ifndef OS2
665 OSL_ENSURE( bSorted, "content not sorted" );
666 #endif
667 OSL_ENSURE( bEqual2Content, "resource structure wrong" );
668 if( !bSorted )
669 ::std::sort(pContent,pContent+nEntries,ImpContentLessCompare());
670 // qsort( pContent, nEntries, sizeof( ImpContent ), Compare );
672 bDone = TRUE;
675 return bDone;
678 // -----------------------------------------------------------------------
680 BOOL InternalResMgr::IsGlobalAvailable( RESOURCE_TYPE nRT, sal_uInt32 nId ) const
682 // Anfang der Strings suchen
683 sal_uInt64 nValue = ((sal_uInt64(nRT) << 32) | nId);
684 ImpContent * pFind = ::std::lower_bound(pContent,
685 pContent + nEntries,
686 nValue,
687 ImpContentMixLessCompare());
688 return (pFind != (pContent + nEntries)) && (pFind->nTypeAndId == nValue);
691 // -----------------------------------------------------------------------
693 void* InternalResMgr::LoadGlobalRes( RESOURCE_TYPE nRT, sal_uInt32 nId,
694 void **pResHandle )
696 #ifdef DBG_UTIL
697 if( pResUseDump )
698 pResUseDump->erase( (sal_uInt64(nRT) << 32) | nId );
699 #endif
700 // Anfang der Strings suchen
701 sal_uInt64 nValue = ((sal_uInt64(nRT) << 32) | nId);
702 ImpContent* pEnd = (pContent + nEntries);
703 ImpContent* pFind = ::std::lower_bound( pContent,
704 pEnd,
705 nValue,
706 ImpContentMixLessCompare());
707 if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == nValue) )
709 if( nRT == RSC_STRING && bEqual2Content )
711 // String Optimierung
712 if( !pStringBlock )
714 // Anfang der Strings suchen
715 ImpContent * pFirst = pFind;
716 ImpContent * pLast = pFirst;
717 while( pFirst > pContent && ((pFirst -1)->nTypeAndId >> 32) == RSC_STRING )
718 --pFirst;
719 while( pLast < pEnd && (pLast->nTypeAndId >> 32) == RSC_STRING )
720 ++pLast;
721 nOffCorrection = pFirst->nOffset;
722 UINT32 nSize;
723 --pLast;
724 pStm->Seek( pLast->nOffset );
725 RSHEADER_TYPE aHdr;
726 pStm->Read( &aHdr, sizeof( aHdr ) );
727 nSize = pLast->nOffset + aHdr.GetGlobOff() - nOffCorrection;
728 pStringBlock = (BYTE*)rtl_allocateMemory( nSize );
729 pStm->Seek( pFirst->nOffset );
730 pStm->Read( pStringBlock, nSize );
732 *pResHandle = pStringBlock;
733 return (BYTE*)pStringBlock + pFind->nOffset - nOffCorrection;
734 } // if( nRT == RSC_STRING && bEqual2Content )
735 else
737 *pResHandle = 0;
738 RSHEADER_TYPE aHeader;
739 pStm->Seek( pFind->nOffset );
740 pStm->Read( &aHeader, sizeof( RSHEADER_TYPE ) );
741 void * pRes = rtl_allocateMemory( aHeader.GetGlobOff() );
742 memcpy( pRes, &aHeader, sizeof( RSHEADER_TYPE ) );
743 pStm->Read( (BYTE*)pRes + sizeof( RSHEADER_TYPE ),
744 aHeader.GetGlobOff() - sizeof( RSHEADER_TYPE ) );
745 return pRes;
747 } // if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == nValue) )
748 *pResHandle = 0;
749 //Resource holen
750 return NULL;
753 // -----------------------------------------------------------------------
755 void InternalResMgr::FreeGlobalRes( void * pResHandle, void * pResource )
757 if ( !pResHandle )
758 // REsource wurde extra allokiert
759 rtl_freeMemory(pResource);
762 // =======================================================================
764 #ifdef DBG_UTIL
766 UniString GetTypeRes_Impl( const ResId& rTypeId )
768 // Funktion verlassen, falls Resourcefehler in dieser Funktion
769 static int bInUse = FALSE;
770 UniString aTypStr( UniString::CreateFromInt32( rTypeId.GetId() ) );
772 if ( !bInUse )
774 bInUse = TRUE;
776 ResId aResId( sal_uInt32(RSCVERSION_ID), *rTypeId.GetResMgr() );
777 aResId.SetRT( RSC_VERSIONCONTROL );
779 if ( rTypeId.GetResMgr()->GetResource( aResId ) )
781 rTypeId.SetRT( RSC_STRING );
782 if ( rTypeId.GetResMgr()->IsAvailable( rTypeId ) )
784 aTypStr = UniString( rTypeId );
785 // Versions Resource Klassenzeiger ans Ende setzen
786 rTypeId.GetResMgr()->Increment( sizeof( RSHEADER_TYPE ) );
789 bInUse = FALSE;
792 return aTypStr;
795 // -----------------------------------------------------------------------
797 void ResMgr::RscError_Impl( const sal_Char* pMessage, ResMgr* pResMgr,
798 RESOURCE_TYPE nRT, sal_uInt32 nId,
799 std::vector< ImpRCStack >& rResStack, int nDepth )
801 // create a separate ResMgr with its own stack
802 // first get a second reference of the InternalResMgr
803 InternalResMgr* pImp =
804 ResMgrContainer::get().getResMgr( pResMgr->pImpRes->aPrefix,
805 pResMgr->pImpRes->aLocale,
806 true );
808 ResMgr* pNewResMgr = new ResMgr( pImp );
810 ByteString aStr = OUStringToOString( pResMgr->GetFileName(), RTL_TEXTENCODING_UTF8 );
811 if ( aStr.Len() )
812 aStr += '\n';
814 aStr.Append( "Class: " );
815 aStr.Append( ByteString( GetTypeRes_Impl( ResId( nRT, *pNewResMgr ) ), RTL_TEXTENCODING_UTF8 ) );
816 aStr.Append( ", Id: " );
817 aStr.Append( ByteString::CreateFromInt32( (long)nId ) );
818 aStr.Append( ". " );
819 aStr.Append( pMessage );
821 aStr.Append( "\nResource Stack\n" );
822 while( nDepth > 0 )
824 aStr.Append( "Class: " );
825 aStr.Append( ByteString( GetTypeRes_Impl( ResId( rResStack[nDepth].pResource->GetRT(), *pNewResMgr ) ), RTL_TEXTENCODING_UTF8 ) );
826 aStr.Append( ", Id: " );
827 aStr.Append( ByteString::CreateFromInt32( (long)rResStack[nDepth].pResource->GetId() ) );
828 nDepth--;
831 // clean up
832 delete pNewResMgr;
834 DBG_ERROR( aStr.GetBuffer() );
837 #endif
839 // =======================================================================
841 static void RscException_Impl()
843 switch ( NAMESPACE_VOS(OSignalHandler)::raise( OSL_SIGNAL_USER_RESOURCEFAILURE, (void*)"" ) )
845 case NAMESPACE_VOS(OSignalHandler)::TAction_CallNextHandler:
846 abort();
848 case NAMESPACE_VOS(OSignalHandler)::TAction_Ignore:
849 return;
851 case NAMESPACE_VOS(OSignalHandler)::TAction_AbortApplication:
852 abort();
854 case NAMESPACE_VOS(OSignalHandler)::TAction_KillApplication:
855 exit(-1);
859 // =======================================================================
861 void ImpRCStack::Init( ResMgr* pMgr, const Resource* pObj, sal_uInt32 Id )
863 pResource = NULL;
864 pClassRes = NULL;
865 Flags = RC_NOTYPE;
866 aResHandle = NULL;
867 pResObj = pObj;
868 nId = Id & ~RSC_DONTRELEASE; //TLX: Besser Init aendern
869 pResMgr = pMgr;
870 if ( !(Id & RSC_DONTRELEASE) )
871 Flags |= RC_AUTORELEASE;
874 // -----------------------------------------------------------------------
876 void ImpRCStack::Clear()
878 pResource = NULL;
879 pClassRes = NULL;
880 Flags = RC_NOTYPE;
881 aResHandle = NULL;
882 pResObj = NULL;
883 nId = 0;
884 pResMgr = NULL;
887 // -----------------------------------------------------------------------
889 static RSHEADER_TYPE* LocalResource( const ImpRCStack* pStack,
890 RESOURCE_TYPE nRTType,
891 sal_uInt32 nId )
893 // Gibt die Position der Resource zurueck, wenn sie gefunden wurde.
894 // Ansonsten gibt die Funktion Null zurueck.
895 RSHEADER_TYPE* pTmp; // Zeiger auf Kind-Resourceobjekte
896 RSHEADER_TYPE* pEnd; // Zeiger auf das Ende der Resource
898 if ( pStack->pResource && pStack->pClassRes )
900 pTmp = (RSHEADER_TYPE*)
901 ((BYTE*)pStack->pResource + pStack->pResource->GetLocalOff());
902 pEnd = (RSHEADER_TYPE*)
903 ((BYTE*)pStack->pResource + pStack->pResource->GetGlobOff());
904 while ( pTmp != pEnd )
906 if ( pTmp->GetRT() == nRTType && pTmp->GetId() == nId )
907 return pTmp;
908 pTmp = (RSHEADER_TYPE*)((BYTE*)pTmp + pTmp->GetGlobOff());
912 return NULL;
915 // =======================================================================
917 void* ResMgr::pEmptyBuffer = NULL;
919 void* ResMgr::getEmptyBuffer()
921 if( ! pEmptyBuffer )
922 pEmptyBuffer = rtl_allocateZeroMemory( 1024 );
923 return pEmptyBuffer;
926 void ResMgr::DestroyAllResMgr()
929 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
930 if( pEmptyBuffer )
932 rtl_freeMemory( pEmptyBuffer );
933 pEmptyBuffer = NULL;
935 ResMgrContainer::release();
937 delete pResMgrMutex;
938 pResMgrMutex = NULL;
941 // -----------------------------------------------------------------------
943 void ResMgr::Init( const OUString& rFileName )
945 (void) rFileName; // avoid warning about unused parameter
946 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
948 if ( !pImpRes )
950 #ifdef DBG_UTIL
951 ByteString aStr( "Resourcefile not found:\n" );
952 aStr += ByteString( OUStringToOString( rFileName, RTL_TEXTENCODING_UTF8 ) );
953 DBG_ERROR( aStr.GetBuffer() );
954 #endif
955 RscException_Impl();
957 #ifdef DBG_UTIL
958 else
960 void* aResHandle = 0; // Hilfvariable fuer Resource
961 void* pVoid; // Zeiger auf die Resource
963 pVoid = pImpRes->LoadGlobalRes( RSC_VERSIONCONTROL, RSCVERSION_ID,
964 &aResHandle );
965 if ( pVoid )
966 pImpRes->FreeGlobalRes( aResHandle, pVoid );
967 else
969 ByteString aStr( "Wrong version:\n" );
970 aStr += ByteString( OUStringToOString( pImpRes->aFileName, RTL_TEXTENCODING_UTF8 ) );
971 DbgError( aStr.GetBuffer() );
974 #endif
975 nCurStack = -1;
976 aStack.clear();
977 pFallbackResMgr = pOriginalResMgr = NULL;
978 incStack();
981 // -----------------------------------------------------------------------
983 ResMgr::ResMgr( InternalResMgr * pImpMgr )
985 pImpRes = pImpMgr;
986 Init( pImpMgr->aFileName );
989 // -----------------------------------------------------------------------
991 ResMgr::~ResMgr()
993 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
995 ResMgrContainer::get().freeResMgr( pImpRes );
997 // clean up possible left rc stack frames
998 while( nCurStack > 0 )
1000 if( ( aStack[nCurStack].Flags & (RC_GLOBAL | RC_NOTFOUND) ) == RC_GLOBAL )
1001 pImpRes->FreeGlobalRes( aStack[nCurStack].aResHandle,
1002 aStack[nCurStack].pResource );
1003 nCurStack--;
1008 void ResMgr::incStack()
1010 nCurStack++;
1011 if( nCurStack >= int(aStack.size()) )
1012 aStack.push_back( ImpRCStack() );
1013 aStack[nCurStack].Clear();
1015 DBG_ASSERT( nCurStack < 32, "Resource stack unreasonably large" );
1018 void ResMgr::decStack()
1020 DBG_ASSERT( nCurStack > 0, "resource stack underrun !" );
1021 if( (aStack[nCurStack].Flags & RC_FALLBACK_UP) )
1023 nCurStack--;
1024 // warning: this will delete *this, see below
1025 pOriginalResMgr->decStack();
1027 else
1029 ImpRCStack& rTop = aStack[nCurStack];
1030 if( (rTop.Flags & RC_FALLBACK_DOWN) )
1032 #if OSL_DEBUG_LEVEL > 1
1033 OSL_TRACE( "returning from fallback %s\n",
1034 OUStringToOString(pFallbackResMgr->GetFileName(), osl_getThreadTextEncoding() ).getStr() );
1035 #endif
1036 delete pFallbackResMgr;
1037 pFallbackResMgr = NULL;
1039 nCurStack--;
1043 #ifdef DBG_UTIL
1045 void ResMgr::TestStack( const Resource* pResObj )
1047 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1049 if ( DbgIsResource() )
1051 for( int i = 1; i <= nCurStack; ++i )
1053 if ( aStack[i].pResObj == pResObj )
1055 #ifdef DBG_UTIL
1056 RscError_Impl( "Resource not freed! ", this,
1057 aStack[i].pResource->GetRT(),
1058 aStack[i].pResource->GetId(),
1059 aStack, i-1 );
1060 #endif
1066 #else
1068 void ResMgr::TestStack( const Resource* )
1072 #endif
1074 // -----------------------------------------------------------------------
1075 BOOL ResMgr::IsAvailable( const ResId& rId, const Resource* pResObj ) const
1077 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1079 BOOL bAvailable = FALSE;
1080 RSHEADER_TYPE* pClassRes = rId.GetpResource();
1081 RESOURCE_TYPE nRT = rId.GetRT2();
1082 sal_uInt32 nId = rId.GetId();
1083 const ResMgr* pMgr = rId.GetResMgr();
1085 if ( !pMgr )
1086 pMgr = this;
1088 if( pMgr->pFallbackResMgr )
1090 ResId aId( rId );
1091 aId.SetResMgr( NULL );
1092 return pMgr->pFallbackResMgr->IsAvailable( aId, pResObj );
1095 if ( !pResObj || pResObj == pMgr->aStack[pMgr->nCurStack].pResObj )
1097 if ( !pClassRes )
1098 pClassRes = LocalResource( &pMgr->aStack[pMgr->nCurStack], nRT, nId );
1099 if ( pClassRes )
1101 if ( pClassRes->GetRT() == nRT )
1102 bAvailable = TRUE;
1106 // vieleicht globale Resource
1107 if ( !pClassRes )
1108 bAvailable = pMgr->pImpRes->IsGlobalAvailable( nRT, nId );
1110 return bAvailable;
1113 // -----------------------------------------------------------------------
1115 void* ResMgr::GetClass()
1117 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1119 if( pFallbackResMgr )
1120 return pFallbackResMgr->GetClass();
1122 return aStack[nCurStack].pClassRes;
1125 // -----------------------------------------------------------------------
1127 BOOL ResMgr::GetResource( const ResId& rId, const Resource* pResObj )
1129 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1131 if( pFallbackResMgr )
1133 ResId aId( rId );
1134 aId.SetResMgr( NULL );
1135 return pFallbackResMgr->GetResource( aId, pResObj );
1138 ResMgr* pMgr = rId.GetResMgr();
1139 if ( pMgr && (this != pMgr) )
1140 return pMgr->GetResource( rId, pResObj );
1142 // normally Increment will pop the context; this is
1143 // not possible in RC_NOTFOUND case, so pop a frame here
1144 ImpRCStack* pTop = &aStack[nCurStack];
1145 if( (pTop->Flags & RC_NOTFOUND) )
1147 decStack();
1150 RSHEADER_TYPE* pClassRes = rId.GetpResource();
1151 RESOURCE_TYPE nRT = rId.GetRT2();
1152 sal_uInt32 nId = rId.GetId();
1154 incStack();
1155 pTop = &aStack[nCurStack];
1156 pTop->Init( pMgr, pResObj, nId |
1157 (rId.IsAutoRelease() ? 0 : RSC_DONTRELEASE) );
1159 if ( pClassRes )
1161 if ( pClassRes->GetRT() == nRT )
1162 pTop->pClassRes = pClassRes;
1163 else
1165 #ifdef DBG_UTIL
1166 RscError_Impl( "Different class and resource type!",
1167 this, nRT, nId, aStack, nCurStack-1 );
1168 #endif
1169 pTop->Flags |= RC_NOTFOUND;
1170 pTop->pClassRes = getEmptyBuffer();
1171 pTop->pResource = (RSHEADER_TYPE*)pTop->pClassRes;
1172 return FALSE;
1175 else
1177 OSL_ENSURE( nCurStack > 0, "stack of 1 to shallow" );
1178 pTop->pClassRes = LocalResource( &aStack[nCurStack-1], nRT, nId );
1181 if ( pTop->pClassRes )
1182 // lokale Resource, nicht system Resource
1183 pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
1184 else
1186 pTop->pClassRes = pImpRes->LoadGlobalRes( nRT, nId, &pTop->aResHandle );
1187 if ( pTop->pClassRes )
1189 pTop->Flags |= RC_GLOBAL;
1190 pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
1192 else
1194 // try to get a fallback resource
1195 pFallbackResMgr = CreateFallbackResMgr( rId, pResObj );
1196 if( pFallbackResMgr )
1198 pTop->Flags |= RC_FALLBACK_DOWN;
1199 #ifdef DBG_UTIL
1200 ByteString aMess( "found resource " );
1201 aMess.Append( ByteString::CreateFromInt32( nId ) );
1202 aMess.Append( " in fallback " );
1203 aMess.Append( ByteString( OUStringToOString( pFallbackResMgr->GetFileName(), osl_getThreadTextEncoding() ) ) );
1204 aMess.Append( "\n" );
1205 RscError_Impl( aMess.GetBuffer(),
1206 this, nRT, nId, aStack, nCurStack-1 );
1207 #endif
1209 else
1211 #ifdef DBG_UTIL
1212 RscError_Impl( "Cannot load resource! ",
1213 this, nRT, nId, aStack, nCurStack-1 );
1214 #endif
1215 pTop->Flags |= RC_NOTFOUND;
1216 pTop->pClassRes = getEmptyBuffer();
1217 pTop->pResource = (RSHEADER_TYPE*)pTop->pClassRes;
1218 return FALSE;
1223 return TRUE;
1226 // -----------------------------------------------------------------------
1228 void * ResMgr::GetResourceSkipHeader( const ResId& rResId, ResMgr ** ppResMgr )
1230 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1232 DBG_ASSERT( rResId.GetResMgr(), "illegal ResId without ResMgr" );
1233 *ppResMgr = rResId.GetResMgr();
1234 if( *ppResMgr )
1236 (*ppResMgr)->GetResource( rResId );
1237 (*ppResMgr)->Increment( sizeof( RSHEADER_TYPE ) );
1238 return (*ppResMgr)->GetClass();
1240 return getEmptyBuffer();
1243 // -----------------------------------------------------------------------
1245 void ResMgr::PopContext( const Resource* pResObj )
1247 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1249 if( pFallbackResMgr )
1251 pFallbackResMgr->PopContext( pResObj );
1252 return;
1255 #ifdef DBG_UTIL
1256 if ( DbgIsResource() )
1258 if ( (aStack[nCurStack].pResObj != pResObj) || nCurStack == 0 )
1260 RscError_Impl( "Cannot free resource! ", this,
1261 RSC_NOTYPE, 0, aStack, nCurStack );
1264 #endif
1266 if ( nCurStack > 0 )
1268 ImpRCStack* pTop = &aStack[nCurStack];
1269 #ifdef DBG_UTIL
1270 if ( DbgIsResource() && !(pTop->Flags & RC_NOTFOUND) )
1272 void* pRes = (BYTE*)pTop->pResource +
1273 pTop->pResource->GetLocalOff();
1275 if ( pTop->pClassRes != pRes )
1277 RscError_Impl( "Classpointer not at the end!",
1278 this, pTop->pResource->GetRT(),
1279 pTop->pResource->GetId(),
1280 aStack, nCurStack-1 );
1283 #endif
1285 // Resource freigeben
1286 if( (pTop->Flags & (RC_GLOBAL | RC_NOTFOUND)) == RC_GLOBAL )
1287 // kann auch Fremd-Ressource sein
1288 pImpRes->FreeGlobalRes( pTop->aResHandle, pTop->pResource );
1289 decStack();
1293 // -----------------------------------------------------------------------
1295 RSHEADER_TYPE* ResMgr::CreateBlock( const ResId& rId )
1297 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1299 if( pFallbackResMgr )
1301 ResId aId( rId );
1302 aId.SetResMgr( NULL );
1303 return pFallbackResMgr->CreateBlock( aId );
1306 RSHEADER_TYPE* pHeader = NULL;
1307 if ( GetResource( rId ) )
1309 // Der Zeiger steht am Anfang, deswegen zeigt der Klassen-Pointer
1310 // auf den Header und die restliche Groesse ist die Gesammte.
1311 pHeader = (RSHEADER_TYPE*)rtl_allocateMemory( GetRemainSize() );
1312 memcpy( pHeader, GetClass(), GetRemainSize() );
1313 Increment( pHeader->GetLocalOff() ); //ans Ende setzen
1314 if ( pHeader->GetLocalOff() != pHeader->GetGlobOff() )
1315 // Hat Sub-Ressourcen, deshalb extra freigeben
1316 PopContext();
1319 return pHeader;
1322 // ------------------------------------------------------------------
1324 INT16 ResMgr::GetShort( void * pShort )
1326 return ((*((sal_uInt8*)pShort + 0) << 8) |
1327 (*((sal_uInt8*)pShort + 1) << 0) );
1330 // ------------------------------------------------------------------
1332 INT32 ResMgr::GetLong( void * pLong )
1334 return ((*((sal_uInt8*)pLong + 0) << 24) |
1335 (*((sal_uInt8*)pLong + 1) << 16) |
1336 (*((sal_uInt8*)pLong + 2) << 8) |
1337 (*((sal_uInt8*)pLong + 3) << 0) );
1340 // ------------------------------------------------------------------
1342 sal_uInt64 ResMgr::GetUInt64( void* pDatum )
1344 return ((sal_uInt64(*((sal_uInt8*)pDatum + 0)) << 56) |
1345 (sal_uInt64(*((sal_uInt8*)pDatum + 1)) << 48) |
1346 (sal_uInt64(*((sal_uInt8*)pDatum + 2)) << 40) |
1347 (sal_uInt64(*((sal_uInt8*)pDatum + 3)) << 32) |
1348 (sal_uInt64(*((sal_uInt8*)pDatum + 4)) << 24) |
1349 (sal_uInt64(*((sal_uInt8*)pDatum + 5)) << 16) |
1350 (sal_uInt64(*((sal_uInt8*)pDatum + 6)) << 8) |
1351 (sal_uInt64(*((sal_uInt8*)pDatum + 7)) << 0) );
1354 // -----------------------------------------------------------------------
1355 sal_uInt32 ResMgr::GetStringWithoutHook( UniString& rStr, const BYTE* pStr )
1357 sal_uInt32 nRet = GetStringSize( pStr );
1358 UniString aString( (sal_Char*)pStr, RTL_TEXTENCODING_UTF8,
1359 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |
1360 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
1361 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
1362 rStr = aString;
1363 return nRet;
1366 sal_uInt32 ResMgr::GetString( UniString& rStr, const BYTE* pStr )
1368 UniString aString;
1369 sal_uInt32 nRet = GetStringWithoutHook( aString, pStr );
1370 if ( pImplResHookProc )
1371 pImplResHookProc( aString );
1372 rStr = aString;
1373 return nRet;
1376 // ------------------------------------------------------------------
1378 sal_uInt32 ResMgr::GetStringSize( const BYTE* pStr )
1380 return GetStringSize( strlen( (const char*)pStr ) );
1383 // -----------------------------------------------------------------------
1385 sal_uInt32 ResMgr::GetRemainSize()
1387 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1389 if( pFallbackResMgr )
1390 return pFallbackResMgr->GetRemainSize();
1392 const ImpRCStack& rTop = aStack[nCurStack];
1393 return (sal_uInt32)((long)(BYTE *)rTop.pResource +
1394 rTop.pResource->GetLocalOff() -
1395 (long)(BYTE *)rTop.pClassRes);
1398 // -----------------------------------------------------------------------
1400 void* ResMgr::Increment( sal_uInt32 nSize )
1402 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1404 if( pFallbackResMgr )
1405 return pFallbackResMgr->Increment( nSize );
1407 ImpRCStack& rStack = aStack[nCurStack];
1408 if( (rStack.Flags & RC_NOTFOUND) )
1409 return rStack.pClassRes;
1411 BYTE* pClassRes = (BYTE*)rStack.pClassRes + nSize;
1413 rStack.pClassRes = pClassRes;
1415 RSHEADER_TYPE* pRes = rStack.pResource;
1417 sal_uInt32 nLocalOff = pRes->GetLocalOff();
1418 if ( (pRes->GetGlobOff() == nLocalOff) &&
1419 (((char*)pRes + nLocalOff) == rStack.pClassRes) &&
1420 (rStack.Flags & RC_AUTORELEASE))
1422 PopContext( rStack.pResObj );
1425 return pClassRes;
1428 ResMgr* ResMgr::CreateFallbackResMgr( const ResId& rId, const Resource* pResource )
1430 ResMgr *pFallback = NULL;
1431 if( nCurStack > 0 )
1433 // get the next fallback level in resource file scope
1434 InternalResMgr* pRes = ResMgrContainer::get().getNextFallback( pImpRes );
1435 if( pRes )
1437 // check that the fallback locale is not already in the chain of
1438 // fallbacks - prevent fallback loops
1439 ResMgr* pResMgr = this;
1440 while( pResMgr &&
1441 ( pResMgr->pImpRes->aLocale.Language != pRes->aLocale.Language ||
1442 pResMgr->pImpRes->aLocale.Country != pRes->aLocale.Country ||
1443 pResMgr->pImpRes->aLocale.Variant != pRes->aLocale.Variant )
1446 pResMgr = pResMgr->pOriginalResMgr;
1448 if( pResMgr )
1450 // found a recursion, no fallback possible
1451 ResMgrContainer::get().freeResMgr( pRes );
1452 return NULL;
1454 OSL_TRACE( "trying fallback: %s\n", OUStringToOString( pRes->aFileName, osl_getThreadTextEncoding() ).getStr() );
1455 pFallback = new ResMgr( pRes );
1456 pFallback->pOriginalResMgr = this;
1457 // try to recreate the resource stack
1458 bool bHaveStack = true;
1459 for( int i = 1; i < nCurStack; i++ )
1461 if( !aStack[i].pResource )
1463 bHaveStack = false;
1464 break;
1466 ResId aId( aStack[i].pResource->GetId(), *pFallbackResMgr );
1467 aId.SetRT( aStack[i].pResource->GetRT() );
1468 if( !pFallback->GetResource( aId ) )
1470 bHaveStack = false;
1471 break;
1474 if( bHaveStack )
1476 ResId aId( rId.GetId(), *pFallback );
1477 aId.SetRT( rId.GetRT() );
1478 if( !pFallback->GetResource( aId, pResource ) )
1479 bHaveStack = false;
1480 else
1481 pFallback->aStack[pFallback->nCurStack].Flags |= RC_FALLBACK_UP;
1483 if( !bHaveStack )
1485 delete pFallback;
1486 pFallback = NULL;
1490 return pFallback;
1493 //---------------------------------------------------------------------------
1495 // method left here for SDK compatibility,
1496 // used in "framework/source/services/substitutepathvars.cxx"
1498 // phone numbers no longer in use for resource files
1500 //---------------------------------------------------------------------------
1502 const char* ResMgr::GetLang( LanguageType& nType, USHORT nPrio )
1504 if ( nType == LANGUAGE_SYSTEM || nType == LANGUAGE_DONTKNOW )
1505 nType = MsLangId::getSystemUILanguage();
1507 if ( nPrio == 0 )
1509 switch ( nType )
1511 case LANGUAGE_DANISH:
1512 return "45";
1514 case LANGUAGE_DUTCH:
1515 case LANGUAGE_DUTCH_BELGIAN:
1516 return "31";
1518 case LANGUAGE_ENGLISH:
1519 case LANGUAGE_ENGLISH_UK:
1520 case LANGUAGE_ENGLISH_EIRE:
1521 case LANGUAGE_ENGLISH_SAFRICA:
1522 case LANGUAGE_ENGLISH_JAMAICA:
1523 case LANGUAGE_ENGLISH_BELIZE:
1524 case LANGUAGE_ENGLISH_TRINIDAD:
1525 case LANGUAGE_ENGLISH_ZIMBABWE:
1526 case LANGUAGE_ENGLISH_PHILIPPINES:
1527 return "44";
1529 case LANGUAGE_ENGLISH_US:
1530 case LANGUAGE_ENGLISH_CAN:
1531 return "01";
1533 case LANGUAGE_ENGLISH_AUS:
1534 case LANGUAGE_ENGLISH_NZ:
1535 return "61";
1536 case LANGUAGE_ESTONIAN:
1537 return "77";
1540 case LANGUAGE_FINNISH:
1541 return "35";
1543 case LANGUAGE_FRENCH_CANADIAN:
1544 return "02";
1546 case LANGUAGE_FRENCH:
1547 case LANGUAGE_FRENCH_BELGIAN:
1548 case LANGUAGE_FRENCH_SWISS:
1549 case LANGUAGE_FRENCH_LUXEMBOURG:
1550 case LANGUAGE_FRENCH_MONACO:
1551 return "33";
1553 case LANGUAGE_GERMAN:
1554 case LANGUAGE_GERMAN_SWISS:
1555 case LANGUAGE_GERMAN_AUSTRIAN:
1556 case LANGUAGE_GERMAN_LUXEMBOURG:
1557 case LANGUAGE_GERMAN_LIECHTENSTEIN:
1558 return "49";
1560 case LANGUAGE_ITALIAN:
1561 case LANGUAGE_ITALIAN_SWISS:
1562 return "39";
1564 case LANGUAGE_NORWEGIAN:
1565 case LANGUAGE_NORWEGIAN_BOKMAL:
1566 return "47";
1568 case LANGUAGE_PORTUGUESE:
1569 return "03";
1571 case LANGUAGE_PORTUGUESE_BRAZILIAN:
1572 return "55";
1574 case LANGUAGE_SPANISH_DATED:
1575 case LANGUAGE_SPANISH_MEXICAN:
1576 case LANGUAGE_SPANISH_MODERN:
1577 case LANGUAGE_SPANISH_GUATEMALA:
1578 case LANGUAGE_SPANISH_COSTARICA:
1579 case LANGUAGE_SPANISH_PANAMA:
1580 case LANGUAGE_SPANISH_DOMINICAN_REPUBLIC:
1581 case LANGUAGE_SPANISH_VENEZUELA:
1582 case LANGUAGE_SPANISH_COLOMBIA:
1583 case LANGUAGE_SPANISH_PERU:
1584 case LANGUAGE_SPANISH_ARGENTINA:
1585 case LANGUAGE_SPANISH_ECUADOR:
1586 case LANGUAGE_SPANISH_CHILE:
1587 case LANGUAGE_SPANISH_URUGUAY:
1588 case LANGUAGE_SPANISH_PARAGUAY:
1589 case LANGUAGE_SPANISH_BOLIVIA:
1590 return "34";
1592 case LANGUAGE_SWEDISH:
1593 return "46";
1595 case LANGUAGE_POLISH:
1596 return "48";
1597 case LANGUAGE_CZECH:
1598 return "42";
1599 case LANGUAGE_SLOVENIAN:
1600 return "50";
1601 case LANGUAGE_HUNGARIAN:
1602 return "36";
1603 case LANGUAGE_RUSSIAN:
1604 return "07";
1605 case LANGUAGE_SLOVAK:
1606 return "43";
1607 case LANGUAGE_GREEK:
1608 return "30";
1609 case LANGUAGE_TURKISH:
1610 return "90";
1612 case LANGUAGE_CHINESE_SIMPLIFIED:
1613 return "86";
1614 case LANGUAGE_CHINESE_TRADITIONAL:
1615 return "88";
1616 case LANGUAGE_JAPANESE:
1617 return "81";
1618 case LANGUAGE_KOREAN:
1619 case LANGUAGE_KOREAN_JOHAB:
1620 return "82";
1621 case LANGUAGE_THAI:
1622 return "66";
1623 case LANGUAGE_HINDI:
1624 return "91";
1626 case LANGUAGE_ARABIC_PRIMARY_ONLY:
1627 case LANGUAGE_ARABIC_IRAQ:
1628 case LANGUAGE_ARABIC_EGYPT:
1629 case LANGUAGE_ARABIC_LIBYA:
1630 case LANGUAGE_ARABIC_ALGERIA:
1631 case LANGUAGE_ARABIC_MOROCCO:
1632 case LANGUAGE_ARABIC_TUNISIA:
1633 case LANGUAGE_ARABIC_OMAN:
1634 case LANGUAGE_ARABIC_YEMEN:
1635 case LANGUAGE_ARABIC_SYRIA:
1636 case LANGUAGE_ARABIC_JORDAN:
1637 case LANGUAGE_ARABIC_LEBANON:
1638 case LANGUAGE_ARABIC_KUWAIT:
1639 case LANGUAGE_ARABIC_UAE:
1640 case LANGUAGE_ARABIC_BAHRAIN:
1641 case LANGUAGE_ARABIC_QATAR:
1642 return "96";
1644 case LANGUAGE_HEBREW:
1645 return "97";
1647 case LANGUAGE_CATALAN:
1648 return "37";
1650 default:
1651 return "99";
1654 else if ( nPrio == 1 )
1656 switch ( nType )
1658 case LANGUAGE_FRENCH_CANADIAN:
1659 return "33";
1661 case LANGUAGE_PORTUGUESE_BRAZILIAN:
1662 return "03";
1664 default:
1665 return NULL;
1668 else if ( nPrio == 2 )
1669 return "01";
1670 else if ( nPrio == 3 )
1671 return "44";
1672 else if ( nPrio == 4 )
1673 return "49";
1674 else
1675 return "99";
1678 // -----------------------------------------------------------------------
1680 ResMgr* ResMgr::CreateResMgr( const sal_Char* pPrefixName,
1681 com::sun::star::lang::Locale aLocale )
1683 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1685 OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
1687 if( ! aLocale.Language.getLength() )
1688 aLocale = ResMgrContainer::get().getDefLocale();
1690 InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, aLocale );
1691 return pImp ? new ResMgr( pImp ) : NULL;
1694 // -----------------------------------------------------------------------
1696 ResMgr* ResMgr::SearchCreateResMgr(
1697 const sal_Char* pPrefixName,
1698 com::sun::star::lang::Locale& rLocale )
1700 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1702 OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
1704 if( ! rLocale.Language.getLength() )
1705 rLocale = ResMgrContainer::get().getDefLocale();
1707 InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, rLocale );
1708 return pImp ? new ResMgr( pImp ) : NULL;
1711 // -----------------------------------------------------------------------
1713 INT16 ResMgr::ReadShort()
1715 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1717 if( pFallbackResMgr )
1718 return pFallbackResMgr->ReadShort();
1720 INT16 n = GetShort( GetClass() );
1721 Increment( sizeof( INT16 ) );
1722 return n;
1725 // -----------------------------------------------------------------------
1727 INT32 ResMgr::ReadLong()
1729 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1731 if( pFallbackResMgr )
1732 return pFallbackResMgr->ReadLong();
1734 INT32 n = GetLong( GetClass() );
1735 Increment( sizeof( INT32 ) );
1736 return n;
1739 // -----------------------------------------------------------------------
1741 UniString ResMgr::ReadStringWithoutHook()
1743 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1745 if( pFallbackResMgr )
1746 return pFallbackResMgr->ReadStringWithoutHook();
1748 UniString aRet;
1750 const ImpRCStack& rTop = aStack[nCurStack];
1751 if( (rTop.Flags & RC_NOTFOUND) )
1753 #if OSL_DEBUG_LEVEL > 0
1754 aRet = OUString( RTL_CONSTASCII_USTRINGPARAM( "<resource not found>" ) );
1755 #endif
1757 else
1758 Increment( GetStringWithoutHook( aRet, (const BYTE*)GetClass() ) );
1760 return aRet;
1763 UniString ResMgr::ReadString()
1765 UniString aRet = ReadStringWithoutHook();
1766 if ( pImplResHookProc )
1767 pImplResHookProc( aRet );
1768 return aRet;
1771 // -----------------------------------------------------------------------
1773 ULONG ResMgr::GetAutoHelpId()
1775 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1777 if( pFallbackResMgr )
1778 return pFallbackResMgr->GetAutoHelpId();
1780 DBG_ASSERT( nCurStack, "resource stack empty in Auto help id generation" );
1781 if( nCurStack < 1 || nCurStack > 2 )
1782 return 0;
1784 const ImpRCStack *pRC = StackTop( nCurStack==1 ? 0 : 1 );
1786 DBG_ASSERT( pRC->pResource, "MM hat gesagt, dass der immer einen hat" );
1787 ULONG nGID = pRC->pResource->GetId();
1789 if( !nGID || nGID > 32767 )
1790 return 0;
1792 ULONG nHID = 0;
1794 // GGGg gggg::gggg gggg::ggLL LLLl::llll llll
1795 switch( pRC->pResource->GetRT() ) { // maximal 7
1796 case RSC_DOCKINGWINDOW:
1797 nHID += 0x20000000L;
1798 case RSC_WORKWIN:
1799 nHID += 0x20000000L;
1800 case RSC_MODELESSDIALOG:
1801 nHID += 0x20000000L;
1802 case RSC_FLOATINGWINDOW:
1803 nHID += 0x20000000L;
1804 case RSC_MODALDIALOG:
1805 nHID += 0x20000000L;
1806 case RSC_TABPAGE:
1807 nHID += 0x20000000L;
1809 if( nCurStack == 2 ) {
1810 pRC = StackTop();
1811 ULONG nLID = pRC->pResource->GetId();
1813 if( !nLID || nLID > 511 )
1814 return 0;
1816 switch( pRC->pResource->GetRT() ) { // maximal 32
1817 case RSC_TABCONTROL: nHID |= 0x0000; break;
1818 case RSC_RADIOBUTTON: nHID |= 0x0200; break;
1819 case RSC_CHECKBOX: nHID |= 0x0400; break;
1820 case RSC_TRISTATEBOX: nHID |= 0x0600; break;
1821 case RSC_EDIT: nHID |= 0x0800; break;
1822 case RSC_MULTILINEEDIT: nHID |= 0x0A00; break;
1823 case RSC_MULTILISTBOX: nHID |= 0x0C00; break;
1824 case RSC_LISTBOX: nHID |= 0x0E00; break;
1825 case RSC_COMBOBOX: nHID |= 0x1000; break;
1826 case RSC_PUSHBUTTON: nHID |= 0x1200; break;
1827 case RSC_SPINFIELD: nHID |= 0x1400; break;
1828 case RSC_PATTERNFIELD: nHID |= 0x1600; break;
1829 case RSC_NUMERICFIELD: nHID |= 0x1800; break;
1830 case RSC_METRICFIELD: nHID |= 0x1A00; break;
1831 case RSC_CURRENCYFIELD: nHID |= 0x1C00; break;
1832 case RSC_DATEFIELD: nHID |= 0x1E00; break;
1833 case RSC_TIMEFIELD: nHID |= 0x2000; break;
1834 case RSC_IMAGERADIOBUTTON: nHID |= 0x2200; break;
1835 case RSC_NUMERICBOX: nHID |= 0x2400; break;
1836 case RSC_METRICBOX: nHID |= 0x2600; break;
1837 case RSC_CURRENCYBOX: nHID |= 0x2800; break;
1838 case RSC_DATEBOX: nHID |= 0x2A00; break;
1839 case RSC_TIMEBOX: nHID |= 0x2C00; break;
1840 case RSC_IMAGEBUTTON: nHID |= 0x2E00; break;
1841 case RSC_MENUBUTTON: nHID |= 0x3000; break;
1842 case RSC_MOREBUTTON: nHID |= 0x3200; break;
1843 default:
1844 return 0;
1845 } // of switch
1846 nHID |= nLID;
1847 } // of if
1848 break;
1849 default:
1850 return 0;
1851 } // of switch
1852 nHID |= nGID << 14;
1854 return nHID;
1857 // -----------------------------------------------------------------------
1859 void ResMgr::SetReadStringHook( ResHookProc pProc )
1861 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1862 pImplResHookProc = pProc;
1865 // -----------------------------------------------------------------------
1867 ResHookProc ResMgr::GetReadStringHook()
1869 return pImplResHookProc;
1872 // -----------------------------------------------------------------------
1874 void ResMgr::SetDefaultLocale( const com::sun::star::lang::Locale& rLocale )
1876 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1877 ResMgrContainer::get().setDefLocale( rLocale );
1880 // -----------------------------------------------------------------------
1882 const OUString& ResMgr::GetFileName() const
1884 return pImpRes->aFileName;
1887 // =======================================================================
1889 SimpleResMgr::SimpleResMgr( const sal_Char* pPrefixName,
1890 const ::com::sun::star::lang::Locale& rLocale )
1892 OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
1893 com::sun::star::lang::Locale aLocale( rLocale );
1895 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1896 if( ! aLocale.Language.getLength() )
1897 aLocale = ResMgrContainer::get().getDefLocale();
1899 m_pResImpl = ResMgrContainer::get().getResMgr( aPrefix, aLocale, true );
1900 DBG_ASSERT( m_pResImpl, "SimpleResMgr::SimpleResMgr : have no impl class !" );
1903 // -----------------------------------------------------------------------
1904 SimpleResMgr::SimpleResMgr( const ::rtl::OUString& _rPrefixName, ::com::sun::star::lang::Locale& _inout_Locale )
1906 osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1907 m_pResImpl = ResMgrContainer::get().getResMgr( _rPrefixName, _inout_Locale, true );
1910 // -----------------------------------------------------------------------
1911 SimpleResMgr::~SimpleResMgr()
1913 delete m_pResImpl;
1916 // -----------------------------------------------------------------------
1917 SimpleResMgr* SimpleResMgr::Create( const sal_Char* pPrefixName, com::sun::star::lang::Locale aLocale )
1919 return new SimpleResMgr( pPrefixName, aLocale );
1922 // -----------------------------------------------------------------------
1923 bool SimpleResMgr::IsAvailable( RESOURCE_TYPE _resourceType, sal_uInt32 _resourceId )
1925 NAMESPACE_VOS(OGuard) aGuard(m_aAccessSafety);
1927 if ( ( RSC_STRING != _resourceType ) && ( RSC_RESOURCE != _resourceType ) )
1928 return false;
1930 DBG_ASSERT( m_pResImpl, "SimpleResMgr::IsAvailable: have no impl class !" );
1931 return m_pResImpl->IsGlobalAvailable( _resourceType, _resourceId );
1934 // -----------------------------------------------------------------------
1935 UniString SimpleResMgr::ReadString( sal_uInt32 nId )
1937 NAMESPACE_VOS(OGuard) aGuard(m_aAccessSafety);
1939 DBG_ASSERT( m_pResImpl, "SimpleResMgr::ReadString : have no impl class !" );
1940 // perhaps constructed with an invalid filename ?
1942 UniString sReturn;
1943 if ( !m_pResImpl )
1944 return sReturn;
1946 void* pResHandle = NULL;
1947 InternalResMgr* pFallback = m_pResImpl;
1948 RSHEADER_TYPE* pResHeader = (RSHEADER_TYPE*)m_pResImpl->LoadGlobalRes( RSC_STRING, nId, &pResHandle );
1949 if ( !pResHeader )
1951 osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
1953 // try fallback
1954 while( ! pResHandle && pFallback )
1956 InternalResMgr* pOldFallback = pFallback;
1957 pFallback = ResMgrContainer::get().getNextFallback( pFallback );
1958 if( pOldFallback != m_pResImpl )
1959 ResMgrContainer::get().freeResMgr( pOldFallback );
1960 if( pFallback )
1962 // handle possible recursion
1963 if( pFallback->aLocale.Language != m_pResImpl->aLocale.Language ||
1964 pFallback->aLocale.Country != m_pResImpl->aLocale.Country ||
1965 pFallback->aLocale.Variant != m_pResImpl->aLocale.Variant )
1967 pResHeader = (RSHEADER_TYPE*)pFallback->LoadGlobalRes( RSC_STRING, nId, &pResHandle );
1969 else
1971 ResMgrContainer::get().freeResMgr( pFallback );
1972 pFallback = NULL;
1976 if( ! pResHandle )
1977 // no such resource
1978 return sReturn;
1981 // ULONG nLen = pResHeader->GetLocalOff() - sizeof(RSHEADER_TYPE);
1982 ResMgr::GetString( sReturn, (const BYTE*)(pResHeader+1) );
1984 // not neccessary with te current implementation which holds the string table permanently, but to be sure ....
1985 // note: pFallback cannot be NULL here and is either the fallback or m_pResImpl
1986 pFallback->FreeGlobalRes( pResHeader, pResHandle );
1987 if( m_pResImpl != pFallback )
1989 osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
1991 ResMgrContainer::get().freeResMgr( pFallback );
1993 return sReturn;
1996 // -----------------------------------------------------------------------
1998 const ::com::sun::star::lang::Locale& SimpleResMgr::GetLocale() const
2000 DBG_ASSERT( IsValid(), "SimpleResMgr::ReadBlob: invalid, this will crash!" );
2001 return m_pResImpl->aLocale;
2004 // -----------------------------------------------------------------------
2006 sal_uInt32 SimpleResMgr::ReadBlob( sal_uInt32 nId, void** pBuffer )
2008 NAMESPACE_VOS(OGuard) aGuard(m_aAccessSafety);
2010 DBG_ASSERT( m_pResImpl, "SimpleResMgr::ReadBlob : have no impl class !" );
2012 // perhaps constructed with an invalid filename ?
2013 DBG_ASSERT( pBuffer, "SimpleResMgr::ReadBlob : invalid argument !" );
2014 *pBuffer = NULL;
2016 void* pResHandle = NULL;
2017 InternalResMgr* pFallback = m_pResImpl;
2018 RSHEADER_TYPE* pResHeader = (RSHEADER_TYPE*)m_pResImpl->LoadGlobalRes( RSC_RESOURCE, nId, &pResHandle );
2019 DBG_ASSERT( pResHeader, "SimpleResMgr::ReadBlob : couldn't find the resource with the given id !" );
2021 if ( !pResHeader )
2023 osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
2025 // try fallback
2026 while( ! pResHandle && pFallback )
2028 InternalResMgr* pOldFallback = pFallback;
2029 pFallback = ResMgrContainer::get().getNextFallback( pFallback );
2030 if( pOldFallback != m_pResImpl )
2031 ResMgrContainer::get().freeResMgr( pOldFallback );
2032 if( pFallback )
2034 // handle possible recursion
2035 if( pFallback->aLocale.Language != m_pResImpl->aLocale.Language ||
2036 pFallback->aLocale.Country != m_pResImpl->aLocale.Country ||
2037 pFallback->aLocale.Variant != m_pResImpl->aLocale.Variant )
2039 pResHeader = (RSHEADER_TYPE*)pFallback->LoadGlobalRes( RSC_RESOURCE, nId, &pResHandle );
2041 else
2043 ResMgrContainer::get().freeResMgr( pFallback );
2044 pFallback = NULL;
2048 if( ! pResHandle )
2049 // no exception handling, this would require the locking of the solar mutex which isn't allowed within this class
2050 return 0;
2053 DBG_ASSERT( pResHandle == NULL, "SimpleResMgr::ReadBlob : behaviour of LoadGlobalRes changed !" );
2054 // if pResHandle is not NULL the FreeBlob wouldn't have to delete the pointer given as pBuffer, but
2055 // FreeBlob doesn't know that so it would probably crash ....
2057 sal_uInt32 nRemaining = pResHeader->GetLocalOff() - sizeof(RSHEADER_TYPE);
2058 *pBuffer = (void*)(((BYTE*)pResHeader) + sizeof(RSHEADER_TYPE));
2060 // free an eventual fallback InternalResMgr
2061 if( m_pResImpl != pFallback )
2063 osl::Guard<osl::Mutex> aGuard2( getResMgrMutex() );
2065 ResMgrContainer::get().freeResMgr( pFallback );
2068 return nRemaining;
2071 // -----------------------------------------------------------------------
2073 void SimpleResMgr::FreeBlob( void* pBuffer )
2075 void* pCompleteBuffer = (void*)(((BYTE*)pBuffer) - sizeof(RSHEADER_TYPE));
2076 rtl_freeMemory(pCompleteBuffer);