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 1372163 : static osl::Mutex& getResMgrMutex()
61 : {
62 1372163 : if( !pResMgrMutex )
63 : {
64 98 : osl::Guard<osl::Mutex> aGuard( *osl::Mutex::getGlobalMutex() );
65 98 : if( ! pResMgrMutex )
66 98 : pResMgrMutex = new osl::Mutex();
67 : }
68 1372163 : 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 472 : struct ContainerElement
111 : {
112 : InternalResMgr* pResMgr;
113 : OUString aFileURL;
114 : int nRefCount;
115 : int nLoadCount;
116 :
117 5962 : ContainerElement() :
118 : pResMgr( NULL ),
119 : nRefCount( 0 ),
120 5962 : nLoadCount( 0 )
121 5962 : {}
122 : };
123 :
124 : boost::unordered_map< OUString, ContainerElement, OUStringHash> m_aResFiles;
125 : com::sun::star::lang::Locale m_aDefLocale;
126 :
127 98 : 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 646 : void setDefLocale( const com::sun::star::lang::Locale& rLocale )
145 646 : { m_aDefLocale = rLocale; }
146 368 : const com::sun::star::lang::Locale& getDefLocale() const
147 368 : { return m_aDefLocale; }
148 : };
149 :
150 : ResMgrContainer* ResMgrContainer::pOneInstance = NULL;
151 :
152 3450 : ResMgrContainer& ResMgrContainer::get()
153 : {
154 3450 : if( ! pOneInstance )
155 98 : pOneInstance = new ResMgrContainer();
156 3450 : return *pOneInstance;
157 : }
158 :
159 16 : ResMgrContainer::~ResMgrContainer()
160 : {
161 1440 : for( boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it =
162 968 : 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 472 : delete it->second.pResMgr;
168 : }
169 8 : }
170 :
171 8 : void ResMgrContainer::release()
172 : {
173 8 : delete pOneInstance;
174 8 : pOneInstance = NULL;
175 8 : }
176 :
177 98 : void ResMgrContainer::init()
178 : {
179 : // get resource path
180 98 : std::list< OUString > aDirs;
181 98 : sal_Int32 nIndex = 0;
182 :
183 : // 1. fixed locations
184 : rtl::OUString uri(
185 98 : RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program/resource"));
186 98 : rtl::Bootstrap::expandMacros(uri);
187 98 : aDirs.push_back(uri);
188 :
189 : // 2. in STAR_RESOURCEPATH
190 98 : const sal_Char* pEnv = getenv( "STAR_RESOURCEPATH" );
191 98 : if( pEnv )
192 : {
193 98 : OUString aEnvPath( OStringToOUString( OString( pEnv ), osl_getThreadTextEncoding() ) );
194 98 : nIndex = 0;
195 294 : while( nIndex >= 0 )
196 : {
197 98 : OUString aPathElement( aEnvPath.getToken( 0, SAL_PATHSEPARATOR, nIndex ) );
198 98 : if( !aPathElement.isEmpty() )
199 : {
200 98 : OUString aFileURL;
201 98 : File::getFileURLFromSystemPath( aPathElement, aFileURL );
202 98 : aDirs.push_back( aFileURL);
203 : }
204 196 : }
205 : }
206 :
207 : // collect all possible resource files
208 294 : for( std::list< OUString >::const_iterator dir_it = aDirs.begin(); dir_it != aDirs.end(); ++dir_it )
209 : {
210 196 : Directory aDir( *dir_it );
211 196 : if( aDir.open() == FileBase::E_None )
212 : {
213 106 : DirectoryItem aItem;
214 30496 : while( aDir.getNextItem( aItem ) == FileBase::E_None )
215 : {
216 30284 : FileStatus aStatus(osl_FileStatus_Mask_FileName);
217 30284 : if( aItem.getFileStatus( aStatus ) == FileBase::E_None )
218 : {
219 30284 : OUString aFileName = aStatus.getFileName();
220 30284 : if( aFileName.getLength() < 5 )
221 1170 : continue;
222 29114 : if( ! aFileName.endsWithIgnoreAsciiCaseAsciiL( ".res", 4 ) )
223 22680 : continue;
224 6434 : OUString aResName = aFileName.copy( 0, aFileName.getLength()-4 );
225 6434 : if( m_aResFiles.find( aResName ) != m_aResFiles.end() )
226 472 : continue;
227 5962 : OUStringBuffer aURL( dir_it->getLength() + aFileName.getLength() + 1 );
228 5962 : aURL.append( *dir_it );
229 5962 : if( !dir_it->endsWithIgnoreAsciiCaseAsciiL( "/", 1 ) )
230 472 : aURL.append( sal_Unicode('/') );
231 5962 : aURL.append( aFileName );
232 5962 : m_aResFiles[ aResName ].aFileURL = aURL.makeStringAndClear();
233 : }
234 30390 : }
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 196 : }
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 98 : LanguageType nLang = MsLangId::getSystemUILanguage();
253 98 : m_aDefLocale = LanguageTag( nLang).getLocale();
254 98 : }
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 1192 : InternalResMgr* ResMgrContainer::getResMgr( const OUString& rPrefix,
265 : com::sun::star::lang::Locale& rLocale,
266 : bool bForceNewInstance
267 : )
268 : {
269 1192 : com::sun::star::lang::Locale aLocale( rLocale );
270 1192 : OUStringBuffer aSearch( rPrefix.getLength() + 16 );
271 1192 : boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it = m_aResFiles.end();
272 :
273 : /* FIXME-BCP47: handle language tags! */
274 1192 : int nTries = 0;
275 1192 : if( !aLocale.Language.isEmpty() )
276 1192 : nTries = 1;
277 1192 : if( !aLocale.Country.isEmpty() )
278 1192 : nTries = 2;
279 1192 : if( !aLocale.Variant.isEmpty() )
280 0 : nTries = 3;
281 2384 : while( nTries-- )
282 : {
283 1192 : aSearch.append( rPrefix );
284 1192 : if( nTries > -1 )
285 : {
286 1192 : aSearch.append( aLocale.Language );
287 : }
288 1192 : if( nTries > 0 )
289 : {
290 1192 : aSearch.append( sal_Unicode('-') );
291 1192 : aSearch.append( aLocale.Country );
292 : }
293 1192 : if( nTries > 1 )
294 : {
295 0 : aSearch.append( sal_Unicode('-') );
296 0 : aSearch.append( aLocale.Variant );
297 : }
298 1192 : it = m_aResFiles.find( aSearch.makeStringAndClear() );
299 1192 : if( it != m_aResFiles.end() )
300 : {
301 : // ensure InternalResMgr existance
302 1192 : if( ! it->second.pResMgr )
303 : {
304 : InternalResMgr* pImp =
305 842 : new InternalResMgr( it->second.aFileURL, rPrefix, it->first, aLocale );
306 842 : if( ! pImp->Create() )
307 : {
308 0 : delete pImp;
309 0 : continue;
310 : }
311 842 : it->second.pResMgr = pImp;
312 : }
313 1192 : 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 1192 : 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 1192 : 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 1192 : 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 1192 : InternalResMgr* pImp = it->second.pResMgr;
393 :
394 1192 : if( it->second.nRefCount == 0 )
395 842 : it->second.nLoadCount++;
396 :
397 : // for SimpleResMgr
398 1192 : 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 1192 : it->second.nRefCount++;
422 :
423 1192 : 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 402 : void ResMgrContainer::freeResMgr( InternalResMgr* pResMgr )
451 : {
452 402 : if( pResMgr->bSingular )
453 0 : delete pResMgr;
454 : else
455 : {
456 : boost::unordered_map< OUString, ContainerElement, OUStringHash >::iterator it =
457 402 : m_aResFiles.find( pResMgr->aResName );
458 402 : if( it != m_aResFiles.end() )
459 : {
460 : DBG_ASSERT( it->second.nRefCount > 0, "InternalResMgr freed too often" );
461 402 : if( it->second.nRefCount > 0 )
462 402 : it->second.nRefCount--;
463 402 : if( it->second.nRefCount == 0 )
464 : {
465 258 : delete it->second.pResMgr;
466 258 : it->second.pResMgr = NULL;
467 : }
468 : }
469 : }
470 402 : }
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 1962480 : inline bool operator() (const ImpContent& lhs, const ImpContent& rhs) const
487 : {
488 1962480 : return lhs.nTypeAndId < rhs.nTypeAndId;
489 : }
490 : };
491 :
492 : static ResHookProc pImplResHookProc = 0;
493 :
494 842 : 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 842 : , pResUseDump( 0 )
509 : {
510 842 : }
511 :
512 544 : InternalResMgr::~InternalResMgr()
513 : {
514 272 : rtl_freeMemory(pContent);
515 272 : rtl_freeMemory(pStringBlock);
516 272 : 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 272 : delete pResUseDump;
546 272 : }
547 :
548 842 : sal_Bool InternalResMgr::Create()
549 : {
550 842 : ResMgrContainer::get();
551 842 : sal_Bool bDone = sal_False;
552 :
553 842 : pStm = new SvFileStream( aFileName, (STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE) );
554 842 : if( pStm->GetError() == 0 )
555 : {
556 842 : sal_Int32 lContLen = 0;
557 :
558 842 : 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 842 : pStm->SeekRel( - (int)sizeof( lContLen ) );
565 842 : pStm->Read( &lContLen, sizeof( lContLen ) );
566 : // is bigendian, swab to the right endian
567 842 : lContLen = ResMgr::GetLong( &lContLen );
568 842 : pStm->SeekRel( -lContLen );
569 : // allocate stored ImpContent data (12 bytes per unit)
570 842 : sal_uInt8* pContentBuf = (sal_uInt8*)rtl_allocateMemory( lContLen );
571 842 : pStm->Read( pContentBuf, lContLen );
572 : // allocate ImpContent space (sizeof(ImpContent) per unit, not necessarily 12)
573 842 : pContent = (ImpContent *)rtl_allocateMemory( sizeof(ImpContent)*lContLen/12 );
574 : // Shorten to number of ImpContent
575 842 : nEntries = (sal_uInt32)lContLen / 12;
576 842 : bEqual2Content = sal_True;
577 842 : sal_Bool bSorted = sal_True;
578 842 : 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 842 : pContent[0].nTypeAndId = ResMgr::GetUInt64( pContentBuf );
591 842 : pContent[0].nOffset = ResMgr::GetLong( pContentBuf+8 );
592 842 : sal_uInt32 nCount = nEntries - 1;
593 234466 : for( sal_uInt32 i = 0,j=1; i < nCount; ++i,++j )
594 : {
595 : // swap the content to the right endian
596 233624 : pContent[j].nTypeAndId = ResMgr::GetUInt64( pContentBuf + (12*j) );
597 233624 : pContent[j].nOffset = ResMgr::GetLong( pContentBuf + (12*j+8) );
598 233624 : if( pContent[i].nTypeAndId >= pContent[j].nTypeAndId )
599 0 : bSorted = sal_False;
600 686300 : if( (pContent[i].nTypeAndId & 0xFFFFFFFF00000000LL) == (pContent[j].nTypeAndId & 0xFFFFFFFF00000000LL)
601 452676 : && pContent[i].nOffset >= pContent[j].nOffset )
602 0 : bEqual2Content = sal_False;
603 : }
604 : }
605 842 : rtl_freeMemory( pContentBuf );
606 : OSL_ENSURE( bSorted, "content not sorted" );
607 : OSL_ENSURE( bEqual2Content, "resource structure wrong" );
608 842 : if( !bSorted )
609 0 : ::std::sort(pContent,pContent+nEntries,ImpContentLessCompare());
610 : // qsort( pContent, nEntries, sizeof( ImpContent ), Compare );
611 :
612 842 : bDone = sal_True;
613 : }
614 :
615 842 : return bDone;
616 : }
617 :
618 :
619 18317 : sal_Bool InternalResMgr::IsGlobalAvailable( RESOURCE_TYPE nRT, sal_uInt32 nId ) const
620 : {
621 : // Anfang der Strings suchen
622 : ImpContent aValue;
623 18317 : aValue.nTypeAndId = ((sal_uInt64(nRT) << 32) | nId);
624 : ImpContent * pFind = ::std::lower_bound(pContent,
625 : pContent + nEntries,
626 : aValue,
627 18317 : ImpContentLessCompare());
628 18317 : return (pFind != (pContent + nEntries)) && (pFind->nTypeAndId == aValue.nTypeAndId);
629 : }
630 :
631 :
632 219312 : 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 219312 : aValue.nTypeAndId = ((sal_uInt64(nRT) << 32) | nId);
642 219312 : ImpContent* pEnd = (pContent + nEntries);
643 : ImpContent* pFind = ::std::lower_bound( pContent,
644 : pEnd,
645 : aValue,
646 219312 : ImpContentLessCompare());
647 219312 : if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == aValue.nTypeAndId) )
648 : {
649 219312 : if( nRT == RSC_STRING && bEqual2Content )
650 : {
651 : // string optimization
652 210192 : if( !pStringBlock )
653 : {
654 : // search beginning of string
655 464 : ImpContent * pFirst = pFind;
656 464 : ImpContent * pLast = pFirst;
657 115798 : while( pFirst > pContent && ((pFirst -1)->nTypeAndId >> 32) == RSC_STRING )
658 114870 : --pFirst;
659 70588 : while( pLast < pEnd && (pLast->nTypeAndId >> 32) == RSC_STRING )
660 69660 : ++pLast;
661 464 : nOffCorrection = pFirst->nOffset;
662 : sal_uInt32 nSize;
663 464 : --pLast;
664 464 : pStm->Seek( pLast->nOffset );
665 : RSHEADER_TYPE aHdr;
666 464 : pStm->Read( &aHdr, sizeof( aHdr ) );
667 464 : nSize = pLast->nOffset + aHdr.GetGlobOff() - nOffCorrection;
668 464 : pStringBlock = (sal_uInt8*)rtl_allocateMemory( nSize );
669 464 : pStm->Seek( pFirst->nOffset );
670 464 : pStm->Read( pStringBlock, nSize );
671 : }
672 210192 : *pResHandle = pStringBlock;
673 210192 : return (sal_uInt8*)pStringBlock + pFind->nOffset - nOffCorrection;
674 : } // if( nRT == RSC_STRING && bEqual2Content )
675 : else
676 : {
677 9120 : *pResHandle = 0;
678 : RSHEADER_TYPE aHeader;
679 9120 : pStm->Seek( pFind->nOffset );
680 9120 : pStm->Read( &aHeader, sizeof( RSHEADER_TYPE ) );
681 9120 : void * pRes = rtl_allocateMemory( aHeader.GetGlobOff() );
682 9120 : memcpy( pRes, &aHeader, sizeof( RSHEADER_TYPE ) );
683 9120 : pStm->Read( (sal_uInt8*)pRes + sizeof( RSHEADER_TYPE ),
684 18240 : aHeader.GetGlobOff() - sizeof( RSHEADER_TYPE ) );
685 9120 : return pRes;
686 : }
687 : } // if( pFind && (pFind != pEnd) && (pFind->nTypeAndId == nValue) )
688 0 : *pResHandle = 0;
689 0 : return NULL;
690 : }
691 :
692 219312 : void InternalResMgr::FreeGlobalRes( void * pResHandle, void * pResource )
693 : {
694 219312 : if ( !pResHandle )
695 : // Free allocated resource
696 9120 : rtl_freeMemory(pResource);
697 219312 : }
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 301486 : void ImpRCStack::Init( ResMgr* pMgr, const Resource* pObj, sal_uInt32 Id )
798 : {
799 301486 : pResource = NULL;
800 301486 : pClassRes = NULL;
801 301486 : Flags = RC_NOTYPE;
802 301486 : aResHandle = NULL;
803 301486 : pResObj = pObj;
804 301486 : nId = Id & ~RSC_DONTRELEASE; //TLX: Besser Init aendern
805 301486 : pResMgr = pMgr;
806 301486 : if ( !(Id & RSC_DONTRELEASE) )
807 301486 : Flags |= RC_AUTORELEASE;
808 301486 : }
809 :
810 302678 : void ImpRCStack::Clear()
811 : {
812 302678 : pResource = NULL;
813 302678 : pClassRes = NULL;
814 302678 : Flags = RC_NOTYPE;
815 302678 : aResHandle = NULL;
816 302678 : pResObj = NULL;
817 302678 : nId = 0;
818 302678 : pResMgr = NULL;
819 302678 : }
820 :
821 389447 : 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 389447 : if ( pStack->pResource && pStack->pClassRes )
830 : {
831 : pTmp = (RSHEADER_TYPE*)
832 168429 : ((sal_uInt8*)pStack->pResource + pStack->pResource->GetLocalOff());
833 : pEnd = (RSHEADER_TYPE*)
834 168429 : ((sal_uInt8*)pStack->pResource + pStack->pResource->GetGlobOff());
835 27775530 : while ( pTmp != pEnd )
836 : {
837 27590490 : if ( pTmp->GetRT() == nRTType && pTmp->GetId() == nId )
838 151818 : return pTmp;
839 27438672 : pTmp = (RSHEADER_TYPE*)((sal_uInt8*)pTmp + pTmp->GetGlobOff());
840 : }
841 : }
842 :
843 237629 : 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 8 : void ResMgr::DestroyAllResMgr()
856 : {
857 : {
858 8 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
859 8 : if( pEmptyBuffer )
860 : {
861 0 : rtl_freeMemory( pEmptyBuffer );
862 0 : pEmptyBuffer = NULL;
863 : }
864 8 : ResMgrContainer::release();
865 : }
866 8 : delete pResMgrMutex;
867 8 : pResMgrMutex = NULL;
868 8 : }
869 :
870 1192 : void ResMgr::Init( const OUString& rFileName )
871 : {
872 : (void) rFileName; // avoid warning about unused parameter
873 1192 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
874 :
875 1192 : 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 1192 : nCurStack = -1;
902 1192 : aStack.clear();
903 1192 : pFallbackResMgr = pOriginalResMgr = NULL;
904 1192 : incStack();
905 1192 : }
906 :
907 1192 : ResMgr::ResMgr( InternalResMgr * pImpMgr )
908 : {
909 1192 : pImpRes = pImpMgr;
910 1192 : Init( pImpMgr->aFileName );
911 1192 : }
912 :
913 804 : ResMgr::~ResMgr()
914 : {
915 402 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
916 :
917 402 : ResMgrContainer::get().freeResMgr( pImpRes );
918 :
919 : // clean up possible left rc stack frames
920 804 : 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 402 : }
927 402 : }
928 :
929 302678 : void ResMgr::incStack()
930 : {
931 302678 : nCurStack++;
932 302678 : if( nCurStack >= int(aStack.size()) )
933 2214 : aStack.push_back( ImpRCStack() );
934 302678 : aStack[nCurStack].Clear();
935 :
936 : DBG_ASSERT( nCurStack < 32, "Resource stack unreasonably large" );
937 302678 : }
938 :
939 301486 : void ResMgr::decStack()
940 : {
941 : DBG_ASSERT( nCurStack > 0, "resource stack underrun !" );
942 301486 : 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 301486 : ImpRCStack& rTop = aStack[nCurStack];
951 301486 : 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 301486 : nCurStack--;
961 : }
962 301486 : }
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 88657 : sal_Bool ResMgr::IsAvailable( const ResId& rId, const Resource* pResObj ) const
1007 : {
1008 88657 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1009 :
1010 88657 : sal_Bool bAvailable = sal_False;
1011 88657 : RSHEADER_TYPE* pClassRes = rId.GetpResource();
1012 88657 : RESOURCE_TYPE nRT = rId.GetRT2();
1013 88657 : sal_uInt32 nId = rId.GetId();
1014 88657 : const ResMgr* pMgr = rId.GetResMgr();
1015 :
1016 88657 : if ( !pMgr )
1017 0 : pMgr = this;
1018 :
1019 88657 : 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 88657 : if ( !pResObj || pResObj == pMgr->aStack[pMgr->nCurStack].pResObj )
1027 : {
1028 88657 : if ( !pClassRes )
1029 88657 : pClassRes = LocalResource( &pMgr->aStack[pMgr->nCurStack], nRT, nId );
1030 88657 : if ( pClassRes )
1031 : {
1032 70340 : if ( pClassRes->GetRT() == nRT )
1033 70340 : bAvailable = sal_True;
1034 : }
1035 : }
1036 :
1037 88657 : if ( !pClassRes )
1038 18317 : bAvailable = pMgr->pImpRes->IsGlobalAvailable( nRT, nId );
1039 :
1040 88657 : return bAvailable;
1041 : }
1042 :
1043 317956 : void* ResMgr::GetClass()
1044 : {
1045 317956 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1046 :
1047 317956 : if( pFallbackResMgr )
1048 0 : return pFallbackResMgr->GetClass();
1049 :
1050 317956 : return aStack[nCurStack].pClassRes;
1051 : }
1052 :
1053 301486 : sal_Bool ResMgr::GetResource( const ResId& rId, const Resource* pResObj )
1054 : {
1055 301486 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1056 :
1057 301486 : if( pFallbackResMgr )
1058 : {
1059 0 : ResId aId( rId );
1060 0 : aId.SetResMgr( NULL );
1061 0 : return pFallbackResMgr->GetResource( aId, pResObj );
1062 : }
1063 :
1064 301486 : ResMgr* pMgr = rId.GetResMgr();
1065 301486 : 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 301486 : ImpRCStack* pTop = &aStack[nCurStack];
1071 301486 : if( (pTop->Flags & RC_NOTFOUND) )
1072 : {
1073 0 : decStack();
1074 : }
1075 :
1076 301486 : RSHEADER_TYPE* pClassRes = rId.GetpResource();
1077 301486 : RESOURCE_TYPE nRT = rId.GetRT2();
1078 301486 : sal_uInt32 nId = rId.GetId();
1079 :
1080 301486 : incStack();
1081 301486 : pTop = &aStack[nCurStack];
1082 : pTop->Init( pMgr, pResObj, nId |
1083 301486 : (rId.IsAutoRelease() ? 0 : RSC_DONTRELEASE) );
1084 :
1085 301486 : if ( pClassRes )
1086 : {
1087 696 : if ( pClassRes->GetRT() == nRT )
1088 696 : 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 300790 : pTop->pClassRes = LocalResource( &aStack[nCurStack-1], nRT, nId );
1105 : }
1106 :
1107 301486 : if ( pTop->pClassRes )
1108 : // lokale Resource, nicht system Resource
1109 82174 : pTop->pResource = (RSHEADER_TYPE *)pTop->pClassRes;
1110 : else
1111 : {
1112 219312 : pTop->pClassRes = pImpRes->LoadGlobalRes( nRT, nId, &pTop->aResHandle );
1113 219312 : if ( pTop->pClassRes )
1114 : {
1115 219312 : pTop->Flags |= RC_GLOBAL;
1116 219312 : 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 301486 : return sal_True;
1153 : }
1154 :
1155 1602 : void * ResMgr::GetResourceSkipHeader( const ResId& rResId, ResMgr ** ppResMgr )
1156 : {
1157 1602 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1158 :
1159 : DBG_ASSERT( rResId.GetResMgr(), "illegal ResId without ResMgr" );
1160 1602 : *ppResMgr = rResId.GetResMgr();
1161 1602 : if( *ppResMgr )
1162 : {
1163 1602 : (*ppResMgr)->GetResource( rResId );
1164 1602 : (*ppResMgr)->Increment( sizeof( RSHEADER_TYPE ) );
1165 1602 : return (*ppResMgr)->GetClass();
1166 : }
1167 0 : return getEmptyBuffer();
1168 : }
1169 :
1170 301486 : void ResMgr::PopContext( const Resource* pResObj )
1171 : {
1172 301486 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1173 :
1174 301486 : if( pFallbackResMgr )
1175 : {
1176 0 : pFallbackResMgr->PopContext( pResObj );
1177 301486 : 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 301486 : if ( nCurStack > 0 )
1192 : {
1193 301486 : 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 301486 : if( (pTop->Flags & (RC_GLOBAL | RC_NOTFOUND)) == RC_GLOBAL )
1212 : // free global resource if resource is foreign
1213 219312 : InternalResMgr::FreeGlobalRes( pTop->aResHandle, pTop->pResource );
1214 301486 : decStack();
1215 301486 : }
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 3586 : sal_Int16 ResMgr::GetShort( void * pShort )
1247 : {
1248 : return ((*((sal_uInt8*)pShort + 0) << 8) |
1249 3586 : (*((sal_uInt8*)pShort + 1) << 0) );
1250 : }
1251 :
1252 83959889 : sal_Int32 ResMgr::GetLong( void * pLong )
1253 : {
1254 : return ((*((sal_uInt8*)pLong + 0) << 24) |
1255 83959889 : (*((sal_uInt8*)pLong + 1) << 16) |
1256 83959889 : (*((sal_uInt8*)pLong + 2) << 8) |
1257 251879667 : (*((sal_uInt8*)pLong + 3) << 0) );
1258 : }
1259 :
1260 234466 : sal_uInt64 ResMgr::GetUInt64( void* pDatum )
1261 : {
1262 : return ((sal_uInt64(*((sal_uInt8*)pDatum + 0)) << 56) |
1263 234466 : (sal_uInt64(*((sal_uInt8*)pDatum + 1)) << 48) |
1264 234466 : (sal_uInt64(*((sal_uInt8*)pDatum + 2)) << 40) |
1265 234466 : (sal_uInt64(*((sal_uInt8*)pDatum + 3)) << 32) |
1266 234466 : (sal_uInt64(*((sal_uInt8*)pDatum + 4)) << 24) |
1267 234466 : (sal_uInt64(*((sal_uInt8*)pDatum + 5)) << 16) |
1268 234466 : (sal_uInt64(*((sal_uInt8*)pDatum + 6)) << 8) |
1269 1641262 : (sal_uInt64(*((sal_uInt8*)pDatum + 7)) << 0) );
1270 : }
1271 :
1272 6010 : sal_uInt32 ResMgr::GetStringWithoutHook( UniString& rStr, const sal_uInt8* pStr )
1273 : {
1274 6010 : sal_uInt32 nLen=0;
1275 6010 : 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 6010 : RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
1280 6010 : rStr = aString;
1281 6010 : 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 1184 : sal_uInt32 ResMgr::GetByteString( rtl::OString& rStr, const sal_uInt8* pStr )
1295 : {
1296 1184 : sal_uInt32 nLen=0;
1297 1184 : sal_uInt32 nRet = GetStringSize( pStr, nLen );
1298 1184 : rStr = rtl::OString( (const sal_Char*)pStr, nLen );
1299 1184 : return nRet;
1300 : }
1301 :
1302 7194 : sal_uInt32 ResMgr::GetStringSize( const sal_uInt8* pStr, sal_uInt32& nLen )
1303 : {
1304 7194 : nLen = static_cast< sal_uInt32 >( strlen( (const char*)pStr ) );
1305 7194 : 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 329393 : void* ResMgr::Increment( sal_uInt32 nSize )
1322 : {
1323 329393 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1324 :
1325 329393 : if( pFallbackResMgr )
1326 0 : return pFallbackResMgr->Increment( nSize );
1327 :
1328 329393 : ImpRCStack& rStack = aStack[nCurStack];
1329 329393 : if( (rStack.Flags & RC_NOTFOUND) )
1330 0 : return rStack.pClassRes;
1331 :
1332 329393 : sal_uInt8* pClassRes = (sal_uInt8*)rStack.pClassRes + nSize;
1333 :
1334 329393 : rStack.pClassRes = pClassRes;
1335 :
1336 329393 : RSHEADER_TYPE* pRes = rStack.pResource;
1337 :
1338 329393 : sal_uInt32 nLocalOff = pRes->GetLocalOff();
1339 329393 : if ( (pRes->GetGlobOff() == nLocalOff) &&
1340 : (((char*)pRes + nLocalOff) == rStack.pClassRes) &&
1341 : (rStack.Flags & RC_AUTORELEASE))
1342 : {
1343 289649 : PopContext( rStack.pResObj );
1344 : }
1345 :
1346 329393 : 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 72 : const char* ResMgr::GetLang( LanguageType& nType, sal_uInt16 nPrio )
1419 : {
1420 72 : if ( nType == LANGUAGE_SYSTEM || nType == LANGUAGE_DONTKNOW )
1421 0 : nType = MsLangId::getSystemUILanguage();
1422 :
1423 72 : if ( nPrio == 0 )
1424 : {
1425 72 : 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 72 : 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 1134 : ResMgr* ResMgr::CreateResMgr( const sal_Char* pPrefixName,
1595 : com::sun::star::lang::Locale aLocale )
1596 : {
1597 1134 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1598 :
1599 1134 : OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
1600 :
1601 : /* FIXME-BCP47: handle language tags! */
1602 1134 : if( aLocale.Language.isEmpty() )
1603 360 : aLocale = ResMgrContainer::get().getDefLocale();
1604 :
1605 1134 : InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, aLocale );
1606 1134 : return pImp ? new ResMgr( pImp ) : NULL;
1607 : }
1608 :
1609 58 : ResMgr* ResMgr::SearchCreateResMgr(
1610 : const sal_Char* pPrefixName,
1611 : com::sun::star::lang::Locale& rLocale )
1612 : {
1613 58 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1614 :
1615 58 : OUString aPrefix( pPrefixName, strlen( pPrefixName ), osl_getThreadTextEncoding() );
1616 :
1617 : /* FIXME-BCP47: handle language tags! */
1618 58 : if( rLocale.Language.isEmpty() )
1619 8 : rLocale = ResMgrContainer::get().getDefLocale();
1620 :
1621 58 : InternalResMgr* pImp = ResMgrContainer::get().getResMgr( aPrefix, rLocale );
1622 58 : return pImp ? new ResMgr( pImp ) : NULL;
1623 : }
1624 :
1625 3586 : sal_Int16 ResMgr::ReadShort()
1626 : {
1627 3586 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1628 :
1629 3586 : if( pFallbackResMgr )
1630 0 : return pFallbackResMgr->ReadShort();
1631 :
1632 3586 : sal_Int16 n = GetShort( GetClass() );
1633 3586 : Increment( sizeof( sal_Int16 ) );
1634 3586 : return n;
1635 : }
1636 :
1637 15911 : sal_Int32 ResMgr::ReadLong()
1638 : {
1639 15911 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1640 :
1641 15911 : if( pFallbackResMgr )
1642 0 : return pFallbackResMgr->ReadLong();
1643 :
1644 15911 : sal_Int32 n = GetLong( GetClass() );
1645 15911 : Increment( sizeof( sal_Int32 ) );
1646 15911 : return n;
1647 : }
1648 :
1649 6010 : UniString ResMgr::ReadStringWithoutHook()
1650 : {
1651 6010 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1652 :
1653 6010 : if( pFallbackResMgr )
1654 0 : return pFallbackResMgr->ReadStringWithoutHook();
1655 :
1656 6010 : UniString aRet;
1657 :
1658 6010 : const ImpRCStack& rTop = aStack[nCurStack];
1659 6010 : 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 6010 : Increment( GetStringWithoutHook( aRet, (const sal_uInt8*)GetClass() ) );
1667 :
1668 6010 : return aRet;
1669 : }
1670 :
1671 6010 : UniString ResMgr::ReadString()
1672 : {
1673 6010 : UniString aRet = ReadStringWithoutHook();
1674 6010 : if ( pImplResHookProc )
1675 1240 : aRet = pImplResHookProc( aRet );
1676 6010 : return aRet;
1677 : }
1678 :
1679 1184 : rtl::OString ResMgr::ReadByteString()
1680 : {
1681 1184 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1682 :
1683 1184 : if( pFallbackResMgr )
1684 0 : return pFallbackResMgr->ReadByteString();
1685 :
1686 1184 : rtl::OString aRet;
1687 :
1688 1184 : const ImpRCStack& rTop = aStack[nCurStack];
1689 1184 : if( (rTop.Flags & RC_NOTFOUND) )
1690 : {
1691 : #if OSL_DEBUG_LEVEL > 0
1692 : aRet = OString( "<resource not found>" );
1693 : #endif
1694 : }
1695 : else
1696 1184 : Increment( GetByteString( aRet, (const sal_uInt8*)GetClass() ) );
1697 :
1698 1184 : return aRet;
1699 : }
1700 :
1701 1444 : rtl::OString ResMgr::GetAutoHelpId()
1702 : {
1703 1444 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1704 :
1705 1444 : if( pFallbackResMgr )
1706 0 : return pFallbackResMgr->GetAutoHelpId();
1707 :
1708 : OSL_ENSURE( nCurStack, "resource stack empty in Auto help id generation" );
1709 1444 : if( nCurStack < 1 || nCurStack > 2 )
1710 0 : return rtl::OString();
1711 :
1712 : // prepare HID, start with resource prefix
1713 1444 : rtl::OStringBuffer aHID( 32 );
1714 1444 : aHID.append( rtl::OUStringToOString( pImpRes->aPrefix, RTL_TEXTENCODING_UTF8 ) );
1715 1444 : aHID.append( '.' );
1716 :
1717 : // append type
1718 1444 : const ImpRCStack *pRC = StackTop();
1719 : OSL_ENSURE( pRC, "missing resource stack level" );
1720 :
1721 1444 : if ( nCurStack == 1 )
1722 : {
1723 : // auto help ids for top level windows
1724 1444 : switch( pRC->pResource->GetRT() ) {
1725 8 : 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 1436 : 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 16 : for( int nOff = nCurStack-1; nOff >= 0; nOff-- )
1786 : {
1787 8 : aHID.append( '.' );
1788 8 : pRC = StackTop( nOff );
1789 :
1790 : OSL_ENSURE( pRC->pResource, "missing resource in resource stack level !" );
1791 8 : if( pRC->pResource )
1792 8 : aHID.append( sal_Int32( pRC->pResource->GetId() ) );
1793 : }
1794 :
1795 8 : return aHID.makeStringAndClear();
1796 : }
1797 :
1798 8 : void ResMgr::SetReadStringHook( ResHookProc pProc )
1799 : {
1800 8 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1801 8 : pImplResHookProc = pProc;
1802 8 : }
1803 :
1804 285600 : ResHookProc ResMgr::GetReadStringHook()
1805 : {
1806 285600 : return pImplResHookProc;
1807 : }
1808 :
1809 646 : void ResMgr::SetDefaultLocale( const com::sun::star::lang::Locale& rLocale )
1810 : {
1811 646 : osl::Guard<osl::Mutex> aGuard( getResMgrMutex() );
1812 646 : ResMgrContainer::get().setDefLocale( rLocale );
1813 646 : }
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: */
|