xref: /trunk/main/rsc/source/parser/rscdb.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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