xref: /aoo41x/main/rsc/source/parser/rscdb.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_rsc.hxx"
30 /****************** I N C L U D E S **************************************/
31 // C and C++ Includes.
32 #include <ctype.h>		// isdigit(), isalpha()
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 
37 #include <tools/fsys.hxx>
38 #include <tools/rc.h>
39 #include <tools/isofallback.hxx>
40 #include <rtl/strbuf.hxx>
41 
42 // Programmabhaengige Includes.
43 #include <rsctree.hxx>
44 #include <rsctop.hxx>
45 #include <rscmgr.hxx>
46 #include <rscdb.hxx>
47 #include <rscrsc.hxx>
48 
49 using namespace rtl;
50 
51 /*************************************************************************
52 |*
53 |*	  RscTypCont :: RscTypCont
54 |*
55 |*	  Beschreibung		RES.DOC
56 |*	  Ersterstellung	MM 22.03.90
57 |*	  Letzte Aenderung	MM 27.06.90
58 |*
59 *************************************************************************/
60 RscTypCont :: RscTypCont( RscError * pErrHdl,
61 						  RSCBYTEORDER_TYPE nOrder,
62 						  const ByteString & rSearchPath,
63 						  sal_uInt32 nFlagsP )
64 	:
65 	  nSourceCharSet( RTL_TEXTENCODING_UTF8 ),
66 	  nByteOrder( nOrder ),
67 	  aSearchPath( rSearchPath ),
68 	  aBool( pHS->getID( "sal_Bool" ), RSC_NOTYPE ),
69 	  aShort( pHS->getID( "short" ), RSC_NOTYPE ),
70 	  aUShort( pHS->getID( "sal_uInt16" ), RSC_NOTYPE ),
71 	  aLong( pHS->getID( "long" ), RSC_NOTYPE ),
72 	  aEnumLong( pHS->getID( "enum_long" ), RSC_NOTYPE ),
73 	  aIdUShort( pHS->getID( "IDUSHORT" ), RSC_NOTYPE ),
74 	  aIdNoZeroUShort( pHS->getID( "IDUSHORT" ), RSC_NOTYPE ),
75 	  aNoZeroShort( pHS->getID( "NoZeroShort" ), RSC_NOTYPE ),
76 	  a1to12Short( pHS->getID( "MonthShort" ), RSC_NOTYPE ),
77 	  a0to23Short( pHS->getID( "HourShort" ), RSC_NOTYPE ),
78 	  a1to31Short( pHS->getID( "DayShort" ), RSC_NOTYPE ),
79 	  a0to59Short( pHS->getID( "MinuteShort" ), RSC_NOTYPE ),
80 	  a0to99Short( pHS->getID( "_0to59Short" ), RSC_NOTYPE ),
81 	  a0to9999Short( pHS->getID( "YearShort" ), RSC_NOTYPE ),
82 	  aIdLong( pHS->getID( "IDLONG" ), RSC_NOTYPE ),
83 	  aString( pHS->getID( "Chars" ), RSC_NOTYPE ),
84 	  aStringLiteral( pHS->getID( "Chars" ), RSC_NOTYPE ),
85 	  aWinBits( pHS->getID( "WinBits" ), RSC_NOTYPE ),
86 	  aLangType(),
87 	  aLangString( pHS->getID( "Lang_Chars" ), RSC_NOTYPE, &aString, &aLangType ),
88 	  aLangShort( pHS->getID( "Lang_short" ), RSC_NOTYPE, &aShort, &aLangType ),
89       nAcceleratorType( 0 ),
90 	  nFlags( nFlagsP )
91 {
92 	nUniqueId = 256;
93 	nPMId = RSC_VERSIONCONTROL +1; //mindestens einen groesser
94 	pEH = pErrHdl;
95 	Init();
96 }
97 
98 static sal_uInt32 getLangIdAndShortenLocale( RscTypCont* pTypCont,
99                                              rtl::OString& rLang,
100                                              rtl::OString& rCountry,
101                                              rtl::OString& rVariant )
102 {
103     rtl::OStringBuffer aLangStr( 64 );
104     aLangStr.append( rLang.toAsciiLowerCase() );
105     if( rCountry.getLength() )
106     {
107         aLangStr.append( '-' );
108         aLangStr.append( rCountry.toAsciiUpperCase() );
109     }
110     if( rVariant.getLength() )
111     {
112         aLangStr.append( '-' );
113         aLangStr.append( rVariant );
114     }
115     rtl::OString aL( aLangStr.makeStringAndClear() );
116     sal_uInt32 nRet = GetLangId( aL );
117     if( nRet == 0 )
118     {
119         pTypCont->AddLanguage( aL );
120         nRet = GetLangId( aL );
121     }
122     if( rVariant.getLength() )
123         rVariant = rtl::OString();
124     else if( rCountry.getLength() )
125         rCountry = rtl::OString();
126     else
127         rLang = rtl::OString();
128 #if OSL_DEBUG_LEVEL > 1
129         fprintf( stderr, " %s (0x%hx)", aL.getStr(), (int)nRet );
130 #endif
131     return nRet;
132 }
133 
134 ByteString RscTypCont::ChangeLanguage( const ByteString& rNewLang )
135 {
136     ByteString aRet = aLanguage;
137     aLanguage = rNewLang;
138 
139     rtl::OString aLang = aLanguage;
140     rtl::OString aLg, aCountry, aVariant;
141     sal_Int32 nIndex = 0;
142     aLg = aLang.getToken( 0, '-', nIndex );
143     if( nIndex != -1 )
144         aCountry = aLang.getToken( 0, '-', nIndex );
145     if( nIndex != -1 )
146         aVariant = aLang.copy( nIndex );
147 
148     bool bAppendEnUsFallback =
149         ! (rNewLang.EqualsIgnoreCaseAscii( "en-US" ) ||
150            rNewLang.EqualsIgnoreCaseAscii( "x-no-translate" ) );
151 
152 #if OSL_DEBUG_LEVEL > 1
153     fprintf( stderr, "RscTypCont::ChangeLanguage:" );
154 #endif
155     aLangFallbacks.clear();
156 
157     do
158     {
159         aLangFallbacks.push_back(getLangIdAndShortenLocale( this, aLg, aCountry, aVariant ) );
160     } while( aLg.getLength() );
161 
162     if( bAppendEnUsFallback )
163     {
164         aLg = "en";
165         aCountry = "US";
166         aVariant = rtl::OString();
167         aLangFallbacks.push_back( getLangIdAndShortenLocale( this, aLg, aCountry, aVariant ) );
168     }
169 
170 #if OSL_DEBUG_LEVEL > 1
171     fprintf( stderr, "\n" );
172 #endif
173 
174     return aRet;
175 }
176 
177 Atom RscTypCont::AddLanguage( const char* pLang )
178 {
179     return aLangType.AddLanguage( pLang, aNmTb );
180 }
181 
182 
183 /*************************************************************************
184 |*
185 |*	  RscTypCont :: ~RscTypCont
186 |*
187 |*	  Beschreibung		RES.DOC
188 |*	  Ersterstellung	MM 22.03.90
189 |*	  Letzte Aenderung	MM 27.06.90
190 |*
191 *************************************************************************/
192 void DestroyNode( RscTop * pRscTop, ObjNode * pObjNode ){
193 	if( pObjNode ){
194 		DestroyNode( pRscTop, (ObjNode*)pObjNode->Left() );
195 		DestroyNode( pRscTop, (ObjNode*)pObjNode->Right() );
196 
197 		if( pObjNode->GetRscObj() ){
198 			pRscTop->Destroy( RSCINST( pRscTop, pObjNode->GetRscObj() ) );
199 			rtl_freeMemory( pObjNode->GetRscObj() );
200 		}
201 		delete pObjNode;
202 	};
203 }
204 
205 void DestroySubTrees( RscTop * pRscTop ){
206 	if( pRscTop ){
207 		DestroySubTrees( (RscTop*)pRscTop->Left() );
208 
209 		DestroyNode( pRscTop, pRscTop->GetObjNode() );
210 
211 		DestroySubTrees( (RscTop*)pRscTop->Right() );
212 	};
213 }
214 
215 void DestroyTree( RscTop * pRscTop ){
216 	if( pRscTop ){
217 		DestroyTree( (RscTop*)pRscTop->Left() );
218 		DestroyTree( (RscTop*)pRscTop->Right() );
219 
220 		delete pRscTop;
221 	};
222 }
223 
224 void Pre_dtorTree( RscTop * pRscTop ){
225 	if( pRscTop ){
226 		Pre_dtorTree( (RscTop*)pRscTop->Left() );
227 		Pre_dtorTree( (RscTop*)pRscTop->Right() );
228 
229 		pRscTop->Pre_dtor();
230 	};
231 }
232 
233 RscTypCont :: ~RscTypCont(){
234 	RscTop	*		pRscTmp;
235 	RscSysEntry   * pSysEntry;
236 
237 	// Alle Unterbaeume loeschen
238 	aVersion.pClass->Destroy( aVersion );
239 	rtl_freeMemory( aVersion.pData );
240 	DestroySubTrees( pRoot );
241 
242 	// Alle Klassen noch gueltig, jeweilige Instanzen freigeben
243 	// BasisTypen
244 	pRscTmp = aBaseLst.First();
245 	while( pRscTmp ){
246 		pRscTmp->Pre_dtor();
247 		pRscTmp = aBaseLst.Next();
248 	};
249 	aBool.Pre_dtor();
250 	aShort.Pre_dtor();
251 	aUShort.Pre_dtor();
252 	aIdUShort.Pre_dtor();
253 	aIdNoZeroUShort.Pre_dtor();
254 	aNoZeroShort.Pre_dtor();
255 	aIdLong.Pre_dtor();
256 	aString.Pre_dtor();
257 	aWinBits.Pre_dtor();
258 	aVersion.pClass->Pre_dtor();
259 	// Zusammengesetzte Typen
260 	Pre_dtorTree( pRoot );
261 
262 	// Klassen zerstoeren
263 	delete aVersion.pClass;
264 	DestroyTree( pRoot );
265 
266 	while( NULL != (pRscTmp = aBaseLst.Remove()) ){
267 		delete pRscTmp;
268 	};
269 
270 	while( NULL != (pSysEntry = aSysLst.Remove()) ){
271 		delete pSysEntry;
272 	};
273 }
274 
275 void RscTypCont::ClearSysNames()
276 {
277 	RscSysEntry   * pSysEntry;
278 	while( NULL != (pSysEntry = aSysLst.Remove()) ){
279 		delete pSysEntry;
280 	};
281 }
282 
283 //=======================================================================
284 RscTop * RscTypCont::SearchType( Atom nId )
285 /*	[Beschreibung]
286 
287 	Sucht eine Basistyp nId;
288 */
289 {
290 	if( nId == InvalidAtom )
291 		return NULL;
292 
293 #define ELSE_IF( a )				\
294 	else if( a.GetId() == nId )	\
295 		return &a;					\
296 
297 	if( aBool.GetId() == nId )
298 		return &aBool;
299 	ELSE_IF( aShort )
300 	ELSE_IF( aUShort )
301 	ELSE_IF( aLong )
302 	ELSE_IF( aEnumLong )
303 	ELSE_IF( aIdUShort )
304 	ELSE_IF( aIdNoZeroUShort )
305 	ELSE_IF( aNoZeroShort )
306 	ELSE_IF( a1to12Short )
307 	ELSE_IF( a0to23Short )
308 	ELSE_IF( a1to31Short )
309 	ELSE_IF( a0to59Short )
310 	ELSE_IF( a0to99Short )
311 	ELSE_IF( a0to9999Short )
312 	ELSE_IF( aIdLong )
313 	ELSE_IF( aString )
314 	ELSE_IF( aWinBits )
315 	ELSE_IF( aLangType )
316 	ELSE_IF( aLangString )
317 	ELSE_IF( aLangShort )
318 
319 	RscTop * pEle = aBaseLst.First();
320 	while( pEle )
321 	{
322 		if( pEle->GetId() == nId )
323 			return pEle;
324 		pEle = aBaseLst.Next();
325 	}
326 	return NULL;
327 }
328 
329 /*************************************************************************
330 |*
331 |*	  RscTypCont :: Search
332 |*
333 |*	  Beschreibung		RES.DOC
334 |*	  Ersterstellung	MM 22.03.90
335 |*	  Letzte Aenderung	MM 27.06.90
336 |*
337 *************************************************************************/
338 RscTop * RscTypCont :: Search( Atom nRT ){
339 	return( (RscTop *)pRoot->Search( nRT ) );
340 }
341 
342 CLASS_DATA RscTypCont :: Search( Atom nRT, const RscId & rId ){
343 	ObjNode *pObjNode;
344 	RscTop	*pRscTop;
345 
346 	if( NULL != (pRscTop = Search( nRT )) ){
347 		if( NULL != (pObjNode = pRscTop->GetObjNode( rId )) ){
348 			return( pObjNode->GetRscObj() );
349 		}
350 	}
351 	return( (CLASS_DATA)0 );
352 }
353 
354 /*************************************************************************
355 |*
356 |*	  RscTypCont :: Delete()
357 |*
358 |*	  Beschreibung
359 |*	  Ersterstellung	MM 10.07.91
360 |*	  Letzte Aenderung	MM 10.07.91
361 |*
362 *************************************************************************/
363 void RscTypCont :: Delete( Atom nRT, const RscId & rId ){
364 	ObjNode *	pObjNode;
365 	RscTop	*	pRscTop;
366 
367 	if( NULL != (pRscTop = Search( nRT )) ){
368 		if( NULL != (pObjNode = pRscTop->GetObjNode()) ){
369 			pObjNode = pObjNode->Search( rId );
370 
371 			if( pObjNode ){
372 				//Objekt aus Baum entfernen
373 				pRscTop->pObjBiTree =
374 					(ObjNode *)pRscTop->pObjBiTree->Remove( pObjNode );
375 
376 				if( pObjNode->GetRscObj() ){
377 					pRscTop->Destroy( RSCINST( pRscTop,
378 											   pObjNode->GetRscObj() ) );
379 					rtl_freeMemory( pObjNode->GetRscObj() );
380 				}
381 				delete pObjNode;
382 			}
383 		}
384 	}
385 }
386 
387 /*************************************************************************
388 |*
389 |*	  RscTypCont :: PutSysName()
390 |*
391 |*	  Beschreibung		RES.DOC
392 |*	  Ersterstellung	MM 22.03.90
393 |*	  Letzte Aenderung	MM 27.06.90
394 |*
395 *************************************************************************/
396 sal_uInt32 RscTypCont :: PutSysName( sal_uInt32 nRscTyp, char * pFileName,
397 								 sal_uInt32 nConst, sal_uInt32 nId, sal_Bool bFirst )
398 {
399 	RscSysEntry *	pSysEntry;
400 	sal_Bool			bId1 = sal_False;
401 
402 	pSysEntry = aSysLst.First();
403 	while( pSysEntry )
404 	{
405 		if( pSysEntry->nKey == 1 )
406 			bId1 = sal_True;
407 		if( !strcmp( pSysEntry->aFileName.GetBuffer(), pFileName ) )
408 			if( pSysEntry->nRscTyp == nRscTyp
409 			  && pSysEntry->nTyp == nConst
410 			  && pSysEntry->nRefId == nId )
411 				break;
412 		pSysEntry = aSysLst.Next();
413 	}
414 
415 	if ( !pSysEntry || (bFirst && !bId1) )
416 	{
417 		pSysEntry = new RscSysEntry;
418 		pSysEntry->nKey = nUniqueId++;
419 		pSysEntry->nRscTyp = nRscTyp;
420 		pSysEntry->nTyp = nConst;
421 		pSysEntry->nRefId = nId;
422 		pSysEntry->aFileName = (const char*)pFileName;
423 		if( bFirst && !bId1 )
424 		{
425 			pSysEntry->nKey = 1;
426 			aSysLst.Insert( pSysEntry, (sal_uLong)0 );
427 		}
428 		else
429 			aSysLst.Insert( pSysEntry, LIST_APPEND );
430 	}
431 
432 	return pSysEntry->nKey;
433 }
434 
435 /*************************************************************************
436 |*
437 |*	  RscTypCont :: WriteInc
438 |*
439 |*	  Beschreibung		RES.DOC
440 |*	  Ersterstellung	MM 21.06.90
441 |*	  Letzte Aenderung	MM 21.06.90
442 |*
443 *************************************************************************/
444 void RscTypCont :: WriteInc( FILE * fOutput, sal_uLong lFileKey )
445 {
446 	RscFile   * pFName;
447 
448 	if( NOFILE_INDEX == lFileKey )
449 	{
450 		pFName = aFileTab.First();
451 		while( pFName )
452 		{
453 			if( pFName && pFName->IsIncFile() )
454 			{
455 				fprintf( fOutput, "#include " );
456 				fprintf( fOutput, "\"%s\"\n",
457 								  pFName->aFileName.GetBuffer() );
458 			}
459 			pFName = aFileTab.Next();
460 		}
461 	}
462 	else
463 	{
464 		RscDepend * 	pDep;
465 		RscFile   * 	pFile;
466 
467 		pFName = aFileTab.Get( lFileKey );
468 		if( pFName )
469 		{
470 			pDep = pFName->First();
471 			while( pDep )
472 			{
473 				if( pDep->GetFileKey() != lFileKey )
474 				{
475 					pFile = aFileTab.GetFile( pDep->GetFileKey() );
476 					if( pFile )
477 					{
478 						fprintf( fOutput, "#include " );
479 						fprintf( fOutput, "\"%s\"\n",
480 								 pFile->aFileName.GetBuffer() );
481 					}
482 				}
483 				pDep = pFName->Next();
484 			};
485 		};
486 	};
487 }
488 
489 /*************************************************************************
490 |*
491 |*	  RscTypCont :: Methoden die ueber all Knoten laufen
492 |*
493 |*	  Beschreibung		RES.DOC
494 |*	  Ersterstellung	MM 22.03.90
495 |*	  Letzte Aenderung	MM 09.12.91
496 |*
497 *************************************************************************/
498 
499 class RscEnumerateObj
500 {
501 friend class RscEnumerateRef;
502 private:
503 	ERRTYPE 	aError; 	// Enthaelt den ersten Fehler
504 	RscTypCont* pTypCont;
505 	FILE *		fOutput;	// AusgabeDatei
506 	sal_uLong		lFileKey;	// Welche src-Datei
507 	RscTop *	pClass;
508 
509 	DECL_LINK( CallBackWriteRc, ObjNode * );
510 	DECL_LINK( CallBackWriteSrc, ObjNode * );
511 	DECL_LINK( CallBackWriteCxx, ObjNode * );
512 	DECL_LINK( CallBackWriteHxx, ObjNode * );
513 
514 	ERRTYPE WriteRc( RscTop * pCl, ObjNode * pRoot )
515 	{
516 		pClass = pCl;
517 		if( pRoot )
518 			pRoot->EnumNodes( LINK( this, RscEnumerateObj, CallBackWriteRc ) );
519 		return aError;
520 	}
521 	ERRTYPE WriteSrc( RscTop * pCl, ObjNode * pRoot ){
522 		pClass = pCl;
523 		if( pRoot )
524 			pRoot->EnumNodes( LINK( this, RscEnumerateObj, CallBackWriteSrc ) );
525 		return aError;
526 	}
527 	ERRTYPE WriteCxx( RscTop * pCl, ObjNode * pRoot ){
528 		pClass = pCl;
529 		if( pRoot )
530 			pRoot->EnumNodes( LINK( this, RscEnumerateObj, CallBackWriteCxx ) );
531 		return aError;
532 	}
533 	ERRTYPE WriteHxx( RscTop * pCl, ObjNode * pRoot ){
534 		pClass = pCl;
535 		if( pRoot )
536 			pRoot->EnumNodes( LINK( this, RscEnumerateObj, CallBackWriteHxx ) );
537 		return aError;
538 	}
539 public:
540 	void WriteRcFile( RscWriteRc & rMem, FILE * fOutput );
541 };
542 
543 /*************************************************************************
544 |*
545 |*	  RscEnumerateObj :: CallBackWriteRc
546 |*
547 |*	  Beschreibung
548 |*	  Ersterstellung	MM 09.12.91
549 |*	  Letzte Aenderung	MM 09.12.91
550 |*
551 *************************************************************************/
552 IMPL_LINK( RscEnumerateObj, CallBackWriteRc, ObjNode *, pObjNode )
553 {
554 	RscWriteRc		aMem( pTypCont->GetByteOrder() );
555 
556 	aError = pClass->WriteRcHeader( RSCINST( pClass, pObjNode->GetRscObj() ),
557 									 aMem, pTypCont,
558 									 pObjNode->GetRscId(), 0, sal_True );
559 	if( aError.IsError() || aError.IsWarning() )
560 		pTypCont->pEH->Error( aError, pClass, pObjNode->GetRscId() );
561 
562 	WriteRcFile( aMem, fOutput );
563 	return 0;
564 }
565 
566 /*************************************************************************
567 |*
568 |*	  RscEnumerateObj :: CallBackWriteSrc
569 |*
570 |*	  Beschreibung
571 |*	  Ersterstellung	MM 09.12.91
572 |*	  Letzte Aenderung	MM 09.12.91
573 |*
574 *************************************************************************/
575 IMPL_LINK_INLINE_START( RscEnumerateObj, CallBackWriteSrc, ObjNode *, pObjNode )
576 {
577 	if( pObjNode->GetFileKey() == lFileKey ){
578 		pClass->WriteSrcHeader( RSCINST( pClass, pObjNode->GetRscObj() ),
579 								fOutput, pTypCont, 0,
580 								pObjNode->GetRscId(), "" );
581 		fprintf( fOutput, ";\n" );
582 	}
583 	return 0;
584 }
585 IMPL_LINK_INLINE_END( RscEnumerateObj, CallBackWriteSrc, ObjNode *, pObjNode )
586 
587 /*************************************************************************
588 |*
589 |*	  RscEnumerateObj :: CallBackWriteCxx
590 |*
591 |*	  Beschreibung
592 |*	  Ersterstellung	MM 09.12.91
593 |*	  Letzte Aenderung	MM 09.12.91
594 |*
595 *************************************************************************/
596 IMPL_LINK_INLINE_START( RscEnumerateObj, CallBackWriteCxx, ObjNode *, pObjNode )
597 {
598 	if( pClass->IsCodeWriteable() && pObjNode->GetFileKey() == lFileKey )
599 		aError = pClass->WriteCxxHeader(
600 							  RSCINST( pClass, pObjNode->GetRscObj() ),
601 							  fOutput, pTypCont, pObjNode->GetRscId() );
602 	return 0;
603 }
604 IMPL_LINK_INLINE_END( RscEnumerateObj, CallBackWriteCxx, ObjNode *, pObjNode )
605 
606 /*************************************************************************
607 |*
608 |*	  RscEnumerateObj :: CallBackWriteHxx
609 |*
610 |*	  Beschreibung
611 |*	  Ersterstellung	MM 09.12.91
612 |*	  Letzte Aenderung	MM 09.12.91
613 |*
614 *************************************************************************/
615 IMPL_LINK_INLINE_START( RscEnumerateObj, CallBackWriteHxx, ObjNode *, pObjNode )
616 {
617 	if( pClass->IsCodeWriteable() && pObjNode->GetFileKey() == lFileKey )
618 		aError = pClass->WriteHxxHeader(
619 							  RSCINST( pClass, pObjNode->GetRscObj() ),
620 							  fOutput, pTypCont, pObjNode->GetRscId() );
621 	return 0;
622 }
623 IMPL_LINK_INLINE_END( RscEnumerateObj, CallBackWriteHxx, ObjNode *, pObjNode )
624 
625 /*************************************************************************
626 |*
627 |*	  RscEnumerateObj :: WriteRcFile
628 |*
629 |*	  Beschreibung
630 |*	  Ersterstellung	MM 09.12.91
631 |*	  Letzte Aenderung	MM 09.12.91
632 |*
633 *************************************************************************/
634 void RscEnumerateObj :: WriteRcFile( RscWriteRc & rMem, FILE * fOut ){
635 	// Definition der Struktur, aus denen die Resource aufgebaut ist
636 	/*
637 	struct RSHEADER_TYPE{
638 		sal_uInt32			nId;		// Identifier der Resource
639 		sal_uInt32			nRT;		// Resource Typ
640 		sal_uInt32			nGlobOff;	// Globaler Offset
641 		sal_uInt32			nLocalOff;	// Lokaler Offset
642 	} aHeader;
643 	*/
644 
645 	sal_uInt32 nId = rMem.GetLong( 0 );
646 	sal_uInt32 nRT = rMem.GetLong( 4 );
647 
648 	// Tabelle wird entsprechend gefuellt
649 	pTypCont->PutTranslatorKey( (sal_uInt64(nRT) << 32) + sal_uInt64(nId) );
650 
651 	if( nRT == RSC_VERSIONCONTROL )
652 	{ // kommt immmer als letztes
653 		sal_Int32 nCount = pTypCont->aIdTranslator.size();
654 		// groesse der Tabelle
655 		sal_uInt32 nSize = (nCount * (sizeof(sal_uInt64)+sizeof(sal_Int32))) + sizeof(sal_Int32);
656 
657 		rMem.Put( nCount ); //Anzahl speichern
658         for( std::map< sal_uInt64, sal_uLong >::const_iterator it =
659              pTypCont->aIdTranslator.begin(); it != pTypCont->aIdTranslator.end(); ++it )
660 		{
661 			// Schluessel schreiben
662 			rMem.Put( it->first );
663 			// Objekt Id oder Position schreiben
664 			rMem.Put( (sal_Int32)it->second );
665 		}
666 		rMem.Put( nSize ); // Groesse hinten Speichern
667 	}
668 
669 	//Dateioffset neu setzen
670 	pTypCont->IncFilePos( rMem.Size() );
671 
672 
673 	//Position wurde vorher in Tabelle geschrieben
674 	fwrite( rMem.GetBuffer(), rMem.Size(), 1, fOut );
675 
676 };
677 
678 class RscEnumerateRef
679 {
680 private:
681 	RscTop *		pRoot;
682 
683 	DECL_LINK( CallBackWriteRc, RscTop * );
684 	DECL_LINK( CallBackWriteSrc, RscTop * );
685 	DECL_LINK( CallBackWriteCxx, RscTop * );
686 	DECL_LINK( CallBackWriteHxx, RscTop * );
687 	DECL_LINK( CallBackWriteSyntax, RscTop * );
688 	DECL_LINK( CallBackWriteRcCtor, RscTop * );
689 public:
690 	RscEnumerateObj aEnumObj;
691 
692 			RscEnumerateRef( RscTypCont * pTC, RscTop * pR,
693 							 FILE * fOutput )
694 			{
695 				aEnumObj.pTypCont = pTC;
696 				aEnumObj.fOutput  = fOutput;
697 				pRoot			  = pR;
698 			}
699 	ERRTYPE WriteRc()
700 	{
701 		aEnumObj.aError.Clear();
702 		pRoot->EnumNodes( LINK( this, RscEnumerateRef, CallBackWriteRc ) );
703 		return aEnumObj.aError;
704 	};
705 
706 	ERRTYPE WriteSrc( sal_uLong lFileKey )
707 	{
708 		aEnumObj.lFileKey = lFileKey;
709 
710 		aEnumObj.aError.Clear();
711 		pRoot->EnumNodes( LINK( this, RscEnumerateRef, CallBackWriteSrc ) );
712 		return aEnumObj.aError;
713 	}
714 
715 	ERRTYPE WriteCxx( sal_uLong lFileKey )
716 	{
717 		aEnumObj.lFileKey = lFileKey;
718 
719 		aEnumObj.aError.Clear();
720 		pRoot->EnumNodes( LINK( this, RscEnumerateRef, CallBackWriteCxx ) );
721 		return aEnumObj.aError;
722 	}
723 
724 	ERRTYPE WriteHxx(  sal_uLong lFileKey )
725 	{
726 		aEnumObj.lFileKey = lFileKey;
727 
728 		aEnumObj.aError.Clear();
729 		pRoot->EnumNodes( LINK( this, RscEnumerateRef, CallBackWriteHxx ) );
730 		return aEnumObj.aError;
731 	}
732 
733 	void	WriteSyntax()
734 			{
735 				pRoot->EnumNodes( LINK( this, RscEnumerateRef,
736 										CallBackWriteSyntax ) );
737 			}
738 
739 	void	WriteRcCtor()
740 			{
741 				pRoot->EnumNodes( LINK( this, RscEnumerateRef,
742 										CallBackWriteRcCtor ) );
743 			}
744 };
745 
746 /*************************************************************************
747 |*
748 |*	  RscRscEnumerateRef :: CallBack...
749 |*
750 |*	  Beschreibung
751 |*	  Ersterstellung	MM 09.12.91
752 |*	  Letzte Aenderung	MM 09.12.91
753 |*
754 *************************************************************************/
755 IMPL_LINK_INLINE_START( RscEnumerateRef, CallBackWriteRc, RscTop *, pRef )
756 {
757 	aEnumObj.WriteRc( pRef, pRef->GetObjNode() );
758 	return 0;
759 }
760 IMPL_LINK_INLINE_END( RscEnumerateRef, CallBackWriteRc, RscTop *, pRef )
761 IMPL_LINK_INLINE_START( RscEnumerateRef, CallBackWriteSrc, RscTop *, pRef )
762 {
763 	aEnumObj.WriteSrc( pRef, pRef->GetObjNode() );
764 	return 0;
765 }
766 IMPL_LINK_INLINE_END( RscEnumerateRef, CallBackWriteSrc, RscTop *, pRef )
767 IMPL_LINK_INLINE_START( RscEnumerateRef, CallBackWriteCxx, RscTop *, pRef )
768 {
769 	if( pRef->IsCodeWriteable() )
770 		aEnumObj.WriteCxx( pRef, pRef->GetObjNode() );
771 	return 0;
772 }
773 IMPL_LINK_INLINE_END( RscEnumerateRef, CallBackWriteCxx, RscTop *, pRef )
774 IMPL_LINK_INLINE_START( RscEnumerateRef, CallBackWriteHxx, RscTop *, pRef )
775 {
776 	if( pRef->IsCodeWriteable() )
777 		aEnumObj.WriteHxx( pRef, pRef->GetObjNode() );
778 	return 0;
779 }
780 IMPL_LINK_INLINE_END( RscEnumerateRef, CallBackWriteHxx, RscTop *, pRef )
781 IMPL_LINK_INLINE_START( RscEnumerateRef, CallBackWriteSyntax, RscTop *, pRef )
782 {
783 	pRef->WriteSyntaxHeader( aEnumObj.fOutput, aEnumObj.pTypCont );
784 	return 0;
785 }
786 IMPL_LINK_INLINE_END( RscEnumerateRef, CallBackWriteSyntax, RscTop *, pRef )
787 IMPL_LINK_INLINE_START( RscEnumerateRef, CallBackWriteRcCtor, RscTop *, pRef )
788 {
789 	pRef->WriteRcCtor( aEnumObj.fOutput, aEnumObj.pTypCont );
790 	return 0;
791 }
792 IMPL_LINK_INLINE_END( RscEnumerateRef, CallBackWriteRcCtor, RscTop *, pRef )
793 
794 /*************************************************************************
795 |*
796 |*	  RscTypCont :: WriteRc
797 |*
798 |*	  Beschreibung		RES.DOC
799 |*	  Ersterstellung	MM 22.03.90
800 |*	  Letzte Aenderung	MM 22.07.91
801 |*
802 *************************************************************************/
803 
804 ERRTYPE RscTypCont::WriteRc( WriteRcContext& rContext )
805 {
806 	ERRTYPE 	  aError;
807 	RscEnumerateRef aEnumRef( this, pRoot, rContext.fOutput );
808 
809 	aIdTranslator.clear();
810 	nFilePos = 0;
811 	nPMId = RSCVERSION_ID +1; //mindestens einen groesser
812 
813 	aError = aEnumRef.WriteRc();
814 
815 	// version control
816 	RscWriteRc aMem( nByteOrder );
817 	aVersion.pClass->WriteRcHeader( aVersion, aMem, this, RscId( RSCVERSION_ID ), 0, sal_True );
818 	aEnumRef.aEnumObj.WriteRcFile( aMem, rContext.fOutput );
819 
820 	return aError;
821 }
822 
823 /*************************************************************************
824 |*
825 |*	  RscTypCont :: WriteSrc
826 |*
827 |*	  Beschreibung		RES.DOC
828 |*	  Ersterstellung	MM 22.03.90
829 |*	  Letzte Aenderung	MM 27.06.90
830 |*
831 *************************************************************************/
832 void RscTypCont :: WriteSrc( FILE * fOutput, sal_uLong nFileKey,
833 							 CharSet /*nCharSet*/, sal_Bool bName )
834 {
835 	RscFile 	*	pFName;
836 	RscEnumerateRef aEnumRef( this, pRoot, fOutput );
837 
838     unsigned char aUTF8BOM[3] = { 0xef, 0xbb, 0xbf };
839     fwrite( aUTF8BOM, sizeof(unsigned char), sizeof(aUTF8BOM)/sizeof(aUTF8BOM[0]), fOutput );
840 	if( bName )
841 	{
842 		WriteInc( fOutput, nFileKey );
843 
844 		if( NOFILE_INDEX == nFileKey )
845 		{
846 			pFName = aFileTab.First();
847 			while( pFName  ){
848 				if( !pFName->IsIncFile() )
849 					pFName->aDefLst.WriteAll( fOutput );
850 				aEnumRef.WriteSrc( aFileTab.GetIndex( pFName ) );
851 				pFName = aFileTab.Next();
852 			};
853 		}
854 		else
855 		{
856 			pFName = aFileTab.Get( nFileKey );
857 			if( pFName ){
858 				pFName->aDefLst.WriteAll( fOutput );
859 				aEnumRef.WriteSrc( nFileKey );
860 			}
861 		}
862 	}
863 	else
864 	{
865 		RscId::SetNames( sal_False );
866 		if( NOFILE_INDEX == nFileKey )
867 		{
868 			pFName = aFileTab.First();
869 			while( pFName  )
870 			{
871 				aEnumRef.WriteSrc( aFileTab.GetIndex( pFName ) );
872 				pFName = aFileTab.Next();
873 			};
874 		}
875 		else
876 			 aEnumRef.WriteSrc( nFileKey );
877 		RscId::SetNames();
878 	};
879 }
880 
881 /*************************************************************************
882 |*
883 |*	  RscTypCont :: WriteHxx
884 |*
885 |*	  Beschreibung
886 |*	  Ersterstellung	MM 30.05.91
887 |*	  Letzte Aenderung	MM 30.05.91
888 |*
889 *************************************************************************/
890 ERRTYPE RscTypCont :: WriteHxx( FILE * fOutput, sal_uLong nFileKey )
891 {
892 	fprintf( fOutput, "#include <tools/rc.hxx>\n" );
893 	fprintf( fOutput, "#include <tools/resid.hxx>\n" );
894 	fprintf( fOutput, "#include <vcl/accel.hxx>\n" );
895 	fprintf( fOutput, "#include <vcl/bitmap.hxx>\n" );
896 	fprintf( fOutput, "#include <vcl/button.hxx>\n" );
897 	fprintf( fOutput, "#include <tools/color.hxx>\n" );
898 	fprintf( fOutput, "#include <vcl/combobox.hxx>\n" );
899 	fprintf( fOutput, "#include <vcl/ctrl.hxx>\n" );
900 	fprintf( fOutput, "#include <vcl/dialog.hxx>\n" );
901 	fprintf( fOutput, "#include <vcl/edit.hxx>\n" );
902 	fprintf( fOutput, "#include <vcl/field.hxx>\n" );
903 	fprintf( fOutput, "#include <vcl/fixed.hxx>\n" );
904 	fprintf( fOutput, "#include <vcl/group.hxx>\n" );
905 	fprintf( fOutput, "#include <vcl/image.hxx>\n" );
906 	fprintf( fOutput, "#include <vcl/button.hxx>\n" );
907 	fprintf( fOutput, "#include <vcl/keycod.hxx>\n" );
908 	fprintf( fOutput, "#include <vcl/lstbox.hxx>\n" );
909 	fprintf( fOutput, "#include <vcl/mapmod.hxx>\n" );
910 	fprintf( fOutput, "#include <vcl/menu.hxx>\n" );
911 	fprintf( fOutput, "#include <vcl/menubtn.hxx>\n" );
912 	fprintf( fOutput, "#include <vcl/morebtn.hxx>\n" );
913 	fprintf( fOutput, "#include <vcl/msgbox.hxx>\n" );
914 	fprintf( fOutput, "#include <vcl/scrbar.hxx>\n" );
915 	fprintf( fOutput, "#include <vcl/spin.hxx>\n" );
916 	fprintf( fOutput, "#include <vcl/spinfld.hxx>\n" );
917 	fprintf( fOutput, "#include <vcl/splitwin.hxx>\n" );
918 	fprintf( fOutput, "#include <vcl/status.hxx>\n" );
919 	fprintf( fOutput, "#include <vcl/tabctrl.hxx>\n" );
920 	fprintf( fOutput, "#include <vcl/tabdlg.hxx>\n" );
921 	fprintf( fOutput, "#include <vcl/tabpage.hxx>\n" );
922 	fprintf( fOutput, "#include <vcl/toolbox.hxx>\n" );
923 	fprintf( fOutput, "#include <vcl/window.hxx>\n" );
924 	fprintf( fOutput, "#include <vcl/wrkwin.hxx>\n" );
925 	fprintf( fOutput, "#include <svtools/svmedit.hxx>\n" );
926 
927 	RscEnumerateRef aEnumRef( this, pRoot, fOutput );
928 	ERRTYPE 		aError;
929 
930 	if( NOFILE_INDEX == nFileKey )
931 	{
932 		RscFile 	*	pFName;
933 
934 		pFName = aFileTab.First();
935 		while( pFName  )
936 		{
937 			aError = aEnumRef.WriteHxx( aFileTab.GetIndex( pFName ) );
938 			pFName = aFileTab.Next();
939 		};
940 	}
941 	else
942 		aError = aEnumRef.WriteHxx( nFileKey );
943 
944 	return aError;
945 }
946 
947 /*************************************************************************
948 |*
949 |*	  RscTypCont :: WriteCxx
950 |*
951 |*	  Beschreibung
952 |*	  Ersterstellung	MM 30.05.91
953 |*	  Letzte Aenderung	MM 30.05.91
954 |*
955 *************************************************************************/
956 ERRTYPE RscTypCont::WriteCxx( FILE * fOutput, sal_uLong nFileKey,
957 							  const ByteString & rHxxName )
958 {
959 	RscEnumerateRef aEnumRef( this, pRoot, fOutput );
960 	ERRTYPE 		aError;
961 	fprintf( fOutput, "#include <string.h>\n" );
962 	WriteInc( fOutput, nFileKey );
963 	if( rHxxName.Len() )
964 		fprintf( fOutput, "#include \"%s\"\n", rHxxName.GetBuffer() );
965 	fprintf( fOutput, "\n\n" );
966 
967 	if( NOFILE_INDEX == nFileKey )
968 	{
969 		RscFile 	*	pFName;
970 
971 		pFName = aFileTab.First();
972 		while( pFName  )
973 		{
974 			aError = aEnumRef.WriteCxx( aFileTab.GetIndex( pFName ) );
975 			pFName = aFileTab.Next();
976 		};
977 	}
978 	else
979 		aError = aEnumRef.WriteCxx( nFileKey );
980 
981 	return aError;
982 }
983 
984 /*************************************************************************
985 |*
986 |*	  RscTypCont :: WriteSyntax
987 |*
988 |*	  Beschreibung
989 |*	  Ersterstellung	MM 30.05.91
990 |*	  Letzte Aenderung	MM 30.05.91
991 |*
992 *************************************************************************/
993 void RscTypCont::WriteSyntax( FILE * fOutput )
994 {
995 	for( sal_uInt32 i = 0; i < aBaseLst.Count(); i++ )
996 		aBaseLst.GetObject( i )->WriteSyntaxHeader( fOutput, this );
997 	RscEnumerateRef aEnumRef( this, pRoot, fOutput );
998 	aEnumRef.WriteSyntax();
999 }
1000 
1001 //=======================================================================
1002 void RscTypCont::WriteRcCtor
1003 (
1004 	FILE * fOutput
1005 )
1006 {
1007 	RscEnumerateRef aEnumRef( this, pRoot, fOutput );
1008 	aEnumRef.WriteRcCtor();
1009 }
1010 
1011 /*************************************************************************
1012 |*
1013 |*	  RscTypCont :: Delete()
1014 |*
1015 |*	  Beschreibung
1016 |*	  Ersterstellung	MM 09.12.91
1017 |*	  Letzte Aenderung	MM 09.12.91
1018 |*
1019 *************************************************************************/
1020 class RscDel
1021 {
1022 	sal_uLong lFileKey;
1023 	DECL_LINK( Delete, RscTop * );
1024 public:
1025 	RscDel( RscTop * pRoot, sal_uLong lKey );
1026 };
1027 
1028 
1029 inline RscDel::RscDel( RscTop * pRoot, sal_uLong lKey )
1030 {
1031 	lFileKey = lKey;
1032 	pRoot->EnumNodes( LINK( this, RscDel, Delete ) );
1033 }
1034 
1035 IMPL_LINK_INLINE_START( RscDel, Delete, RscTop *, pNode )
1036 {
1037 	if( pNode->GetObjNode() )
1038 		pNode->pObjBiTree = pNode->GetObjNode()->DelObjNode( pNode, lFileKey );
1039 	return 0;
1040 }
1041 IMPL_LINK_INLINE_END( RscDel, Delete, RscTop *, pNode )
1042 
1043 void RscTypCont :: Delete( sal_uLong lFileKey ){
1044 	// Resourceinstanzen loeschen
1045 	RscDel aDel( pRoot, lFileKey );
1046 	// Defines loeschen
1047 	aFileTab.DeleteFileContext( lFileKey );
1048 }
1049 
1050 /*************************************************************************
1051 |*
1052 |*	  RscTypCont :: MakeConsistent()
1053 |*
1054 |*	  Beschreibung
1055 |*	  Ersterstellung	MM 23.09.91
1056 |*	  Letzte Aenderung	MM 23.09.91
1057 |*
1058 *************************************************************************/
1059 sal_Bool IsInstConsistent( ObjNode * pObjNode, RscTop * pRscTop,
1060 					   RscInconsList * pList )
1061 {
1062 	sal_Bool bRet = sal_True;
1063 
1064 	if( pObjNode ){
1065 		RSCINST aTmpI;
1066 
1067 		if( ! IsInstConsistent( (ObjNode*)pObjNode->Left(), pRscTop, pList ) )
1068 			bRet = sal_False;
1069 
1070 		aTmpI.pClass = pRscTop;
1071 		aTmpI.pData = pObjNode->GetRscObj();
1072 		if( ! aTmpI.pClass->IsConsistent( aTmpI, pList ) )
1073 			bRet = sal_False;
1074 
1075 		if( ! IsInstConsistent( (ObjNode*)pObjNode->Right(), pRscTop, pList ) )
1076 			bRet = sal_False;
1077 	};
1078 
1079 	return( bRet );
1080 }
1081 
1082 sal_Bool MakeConsistent( RscTop * pRscTop, RscInconsList * pList )
1083 {
1084 	sal_Bool bRet = sal_True;
1085 
1086 	if( pRscTop ){
1087 		if( ! ::MakeConsistent( (RscTop*)pRscTop->Left(), pList ) )
1088 			bRet = sal_False;
1089 
1090 		if( pRscTop->GetObjNode() ){
1091 			if( ! pRscTop->GetObjNode()->IsConsistent() ){
1092 				pRscTop->GetObjNode()->OrderTree();
1093 				if( ! pRscTop->GetObjNode()->IsConsistent( pList ) )
1094 					bRet = sal_False;
1095 			}
1096 			if( ! IsInstConsistent( pRscTop->GetObjNode(), pRscTop, pList ) )
1097 				bRet = sal_False;
1098 		}
1099 
1100 		if( ! ::MakeConsistent( (RscTop*)pRscTop->Right(), pList ) )
1101 			bRet = sal_False;
1102 	};
1103 
1104 	return bRet;
1105 }
1106 
1107 sal_Bool RscTypCont :: MakeConsistent( RscInconsList * pList ){
1108 	return( ::MakeConsistent( pRoot, pList ) );
1109 }
1110 
1111 sal_uInt32 RscTypCont::PutTranslatorKey( sal_uInt64 nKey )
1112 {
1113     aIdTranslator[ nKey ] = nFilePos;
1114 	return nPMId++;
1115 }
1116 
1117