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