Stop leaking all ScPostIt instances.
[LibreOffice.git] / l10ntools / source / export.cxx
blob405716719b4468b335f1579ce1be46a4161e87b1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "sal/config.h"
22 #include <cstddef>
23 #include <cstring>
25 #include "helper.hxx"
26 #include "boost/scoped_ptr.hpp"
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include "common.hxx"
30 #include "export.hxx"
31 #include "tokens.h"
32 #include <iostream>
33 #include <rtl/strbuf.hxx>
35 void yyerror( const char * );
36 void YYWarning( const char * );
38 namespace {
40 MergeDataFile * pMergeDataFile = 0; //TODO
42 namespace global {
44 OString inputPathname;
45 boost::scoped_ptr< Export > exporter;
51 extern "C" {
53 FILE * init(int argc, char ** argv) {
55 common::HandledArgs aArgs;
56 if ( !common::handleArguments(argc, argv, aArgs) )
58 common::writeUsage("transex3","*.src/*.hrc");
59 std::exit(EXIT_FAILURE);
61 global::inputPathname = aArgs.m_sInputFile;
63 FILE * pFile = std::fopen(global::inputPathname.getStr(), "r");
64 if (pFile == 0) {
65 std::fprintf(
66 stderr, "Error: Cannot open file \"%s\"\n",
67 global::inputPathname.getStr());
68 std::exit(EXIT_FAILURE);
71 if (aArgs.m_bMergeMode) {
72 global::exporter.reset(new Export(aArgs.m_sMergeSrc, aArgs.m_sOutputFile,
73 aArgs.m_sLanguage, aArgs.m_bUTF8BOM));
74 } else {
75 global::exporter.reset(new Export(aArgs.m_sOutputFile));
78 global::exporter->Init();
80 return pFile;
83 int Parse( int nTyp, const char *pTokenText ){
84 global::exporter->Execute( nTyp , pTokenText );
85 return 1;
87 void Close(){
88 global::exporter->pParseQueue->Close();
89 global::exporter.reset();
90 // avoid nontrivial Export dtor being executed during exit
93 int WorkOnTokenSet( int nTyp, char *pTokenText )
96 global::exporter->pParseQueue->Push( QueueEntry( nTyp , OString(pTokenText) ) );
97 return 1;
100 } // extern
102 extern "C" {
104 int SetError()
106 // set error at global instance of class Export
107 global::exporter->SetError();
108 return 1;
112 extern "C" {
114 int GetError()
116 // get error at global instance of class Export
117 if (global::exporter->GetError())
118 return 1;
119 return sal_False;
124 // class ResData
127 sal_Bool ResData::SetId( const OString& rId, sal_uInt16 nLevel )
129 if ( nLevel > nIdLevel )
131 nIdLevel = nLevel;
132 sId = rId;
134 if ( bChild && bChildWithText )
136 OString sError("ResId after child definition");
137 yyerror(sError.getStr());
138 SetError();
141 if ( sId.getLength() > 255 )
143 YYWarning( "LocalId > 255 chars, truncating..." );
144 sId = sId.copy(0, 255).trim();
147 return sal_True;
150 return sal_False;
154 // class Export
157 namespace
160 static sal_Int32 lcl_countOccurrences(const OString& text, char c)
162 sal_Int32 n = 0;
163 for (sal_Int32 i = 0;; ++i) {
164 i = text.indexOf(c, i);
165 if (i == -1) {
166 break;
168 ++n;
170 return n;
175 Export::Export(const OString &rOutput)
177 bDefine( sal_False ),
178 bNextMustBeDefineEOL( sal_False ),
179 nLevel( 0 ),
180 nList( LIST_NON ),
181 nListIndex( 0 ),
182 nListLevel( 0 ),
183 bSkipFile( false ),
184 bMergeMode( false ),
185 bError( sal_False ),
186 bReadOver( sal_False ),
187 bDontWriteOutput( sal_False ),
188 sFilename( global::inputPathname ),
189 sLanguages( OString() ),
190 pParseQueue( new ParserQueue( *this ) )
192 aOutput.mPo = new PoOfstream( rOutput, PoOfstream::APP );
193 if (!aOutput.mPo->isOpen()) {
194 fprintf(stderr, "ERROR : Can't open file %s\n", rOutput.getStr());
195 exit ( -1 );
199 Export::Export(
200 const OString &rMergeSource, const OString &rOutput,
201 const OString &rLanguage, bool bUTF8BOM)
203 bDefine( sal_False ),
204 bNextMustBeDefineEOL( sal_False ),
205 nLevel( 0 ),
206 nList( LIST_NON ),
207 nListIndex( 0 ),
208 nListLevel( 0 ),
209 bSkipFile( false ),
210 bMergeMode( sal_True ),
211 sMergeSrc( rMergeSource ),
212 bError( sal_False ),
213 bReadOver( sal_False ),
214 bDontWriteOutput( sal_False ),
215 sFilename( global::inputPathname ),
216 sLanguages( rLanguage ),
217 pParseQueue( new ParserQueue( *this ) )
219 aOutput.mSimple = new std::ofstream();
220 aOutput.mSimple->open(rOutput.getStr(), std::ios_base::out | std::ios_base::trunc);
222 if ( bUTF8BOM ) WriteUTF8ByteOrderMarkToOutput();
225 void Export::Init()
227 // resets the internal status, used before parseing another file
228 bDefine = sal_False;
229 bNextMustBeDefineEOL = sal_False;
230 nLevel = 0;
231 nList = LIST_NON;
232 m_sListLang = OString();
233 nListIndex = 0;
234 for ( size_t i = 0, n = aResStack.size(); i < n; ++i )
235 delete aResStack[ i ];
236 aResStack.clear();
239 Export::~Export()
241 if( pParseQueue )
242 delete pParseQueue;
243 if ( bMergeMode )
245 aOutput.mSimple->close();
246 delete aOutput.mSimple;
248 else
250 aOutput.mPo->close();
251 delete aOutput.mPo;
253 for ( size_t i = 0, n = aResStack.size(); i < n; ++i )
254 delete aResStack[ i ];
255 aResStack.clear();
257 if ( bMergeMode ) {
258 if ( !pMergeDataFile )
259 pMergeDataFile = new MergeDataFile(sMergeSrc, global::inputPathname, false);
261 delete pMergeDataFile;
265 int Export::Execute( int nToken, const char * pToken )
268 OString sToken( pToken );
269 OString sOrig( sToken );
270 sal_Bool bWriteToMerged = bMergeMode;
272 if ( nToken == CONDITION )
274 OString sTestToken(pToken);
275 sTestToken = sTestToken.replaceAll("\t", OString()).
276 replaceAll(" ", OString());
277 if (( !bReadOver ) && ( sTestToken.startsWith("#ifndef__RSC_PARSER")))
278 bReadOver = sal_True;
279 else if (( bReadOver ) && ( sTestToken.startsWith("#endif") ))
280 bReadOver = sal_False;
282 if ((( nToken < FILTER_LEVEL ) || ( bReadOver )) &&
283 (!(( bNextMustBeDefineEOL ) && ( sOrig == "\n" )))) {
284 // this tokens are not mandatory for parsing, so ignore them ...
285 if ( bMergeMode )
286 WriteToMerged( sOrig , false ); // ... or write them directly to dest.
287 return 0;
290 ResData *pResData = NULL;
291 if ( nLevel ) {
292 // res. exists at cur. level
293 pResData = ( (nLevel-1) < aResStack.size() ) ? aResStack[ nLevel-1 ] : NULL;
295 else if (( nToken != RESOURCE ) &&
296 ( nToken != RESOURCEEXPR ) &&
297 ( nToken != SMALRESOURCE ) &&
298 ( nToken != LEVELUP ) &&
299 ( nToken != NORMDEFINE ) &&
300 ( nToken != RSCDEFINE ) &&
301 ( nToken != CONDITION ) &&
302 ( nToken != PRAGMA ))
304 // no res. exists at cur. level so return
305 if ( bMergeMode )
306 WriteToMerged( sOrig , false );
307 return 0;
309 // #define NO_LOCALIZE_EXPORT
310 if( bSkipFile ){
311 if ( bMergeMode ) {
312 WriteToMerged( sOrig , false );
314 return 1;
318 if ( bDefine ) {
319 if (( nToken != EMPTYLINE ) && ( nToken != LEVELDOWN ) && ( nToken != LEVELUP )) {
320 // cur. res. defined in macro
321 if ( bNextMustBeDefineEOL ) {
322 if ( nToken != RSCDEFINELEND ) {
323 // end of macro found, so destroy res.
324 bDefine = sal_False;
325 Execute( LEVELDOWN, "" );
326 bNextMustBeDefineEOL = sal_False;
328 else {
329 // next line also in macro definition
330 bNextMustBeDefineEOL = sal_False;
331 if ( bMergeMode )
332 WriteToMerged( sOrig , false );
333 return 1;
339 sal_Bool bExecuteDown = sal_False;
340 if ( nToken != LEVELDOWN ) {
341 sal_uInt16 nOpen = 0;
342 sal_uInt16 nClose = 0;
343 sal_Bool bReadOver1 = sal_False;
344 sal_uInt16 i = 0;
345 for ( i = 0; i < sToken.getLength(); i++ ) {
346 if ( sToken[i] == '"' )
347 bReadOver1 = !bReadOver1;
348 if ( !bReadOver1 && ( sToken[i] == '{' ))
349 nOpen++;
352 bReadOver1 = sal_False;
353 for ( i = 0; i < sToken.getLength(); i++ ) {
354 if ( sToken[i] == '"' )
355 bReadOver1 = !bReadOver1;
356 if ( !bReadOver1 && ( sToken[i] == '}' ))
357 nClose++;
360 if ( nOpen < nClose )
361 bExecuteDown = sal_True;
363 switch ( nToken ) {
365 case NORMDEFINE:
366 sToken = sToken.replace('\r', ' ').replace('\t', ' ');
367 for (;;) {
368 sal_Int32 n = 0;
369 sToken = sToken.replaceFirst(" ", " ", &n);
370 if (n == -1) {
371 break;
374 if( sToken.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("#define NO_LOCALIZE_EXPORT")) ){
375 bSkipFile = true;
376 return 0;
378 if ( bMergeMode )
379 WriteToMerged( sOrig , false );
381 return 0;
384 case RSCDEFINE:
385 bDefine = sal_True; // res. defined in macro
387 case RESOURCE:
388 case RESOURCEEXPR: {
389 bDontWriteOutput = sal_False;
390 if ( nToken != RSCDEFINE )
391 bNextMustBeDefineEOL = sal_False;
392 // this is the beginning of a new res.
393 nLevel++;
394 if ( nLevel > 1 ) {
395 aResStack[ nLevel - 2 ]->bChild = sal_True;
398 // create new instance for this res. and fill mandatory fields
400 pResData = new ResData( FullId() , sFilename );
401 aResStack.push_back( pResData );
402 sToken = sToken.replaceAll("\n", OString()).
403 replaceAll("\r", OString()).
404 replaceAll("{", OString()).replace('\t', ' ');
405 sToken = sToken.trim();
406 OString sTLower = sToken.getToken(0, ' ').toAsciiLowerCase();
407 pResData->sResTyp = sTLower;
408 OString sId( sToken.copy( pResData->sResTyp.getLength() + 1 ));
409 OString sCondition;
410 if ( sId.indexOf( '#' ) != -1 )
412 // between ResTyp, Id and paranthes is a precomp. condition
413 sCondition = "#";
414 sal_Int32 n = 0;
415 sId = sId.getToken(0, '#', n);
416 sCondition += sId.getToken(0, '#', n);
418 sId = sId.getToken(0, '/');
419 CleanValue( sId );
420 sId = sId.replaceAll("\t", OString());
421 pResData->SetId( sId, ID_LEVEL_IDENTIFIER );
422 if (!sCondition.isEmpty())
424 Execute( CONDITION, ""); // execute the precomp. condition
427 break;
428 case SMALRESOURCE: {
429 bDontWriteOutput = sal_False;
430 // this is the beginning of a new res.
431 bNextMustBeDefineEOL = sal_False;
432 nLevel++;
433 if ( nLevel > 1 ) {
434 aResStack[ nLevel - 2 ]->bChild = sal_True;
437 // create new instance for this res. and fill mandatory fields
439 pResData = new ResData( FullId() , sFilename );
440 aResStack.push_back( pResData );
441 sToken = sToken.replaceAll("\n", OString()).
442 replaceAll("\r", OString()).
443 replaceAll("{", OString()).
444 replaceAll("\t", OString()).
445 replaceAll(" ", OString()).
446 replaceAll("\\", OString()).toAsciiLowerCase();
447 pResData->sResTyp = sToken;
449 break;
450 case LEVELUP: {
451 // push
452 if ( nList )
453 nListLevel++;
454 if ( nList )
455 break;
457 bDontWriteOutput = sal_False;
458 OString sLowerTyp;
459 if ( pResData )
460 sLowerTyp = "unknown";
461 nLevel++;
462 if ( nLevel > 1 ) {
463 aResStack[ nLevel - 2 ]->bChild = sal_True;
466 ResData *pNewData = new ResData( FullId() , sFilename );
467 pNewData->sResTyp = sLowerTyp;
468 aResStack.push_back( pNewData );
470 break;
471 case LEVELDOWN: {
472 // pop
473 if ( !nList ) {
474 bDontWriteOutput = sal_False;
475 if ( nLevel ) {
476 if ( bDefine && (nLevel == 1 )) {
477 bDefine = sal_False;
478 bNextMustBeDefineEOL = sal_False;
480 WriteData( pResData );
481 ResStack::iterator it = aResStack.begin();
482 ::std::advance( it, nLevel-1 );
483 delete *it;
484 aResStack.erase( it );
485 nLevel--;
488 else {
489 if ( bDefine )
490 bNextMustBeDefineEOL = sal_True;
491 if ( !nListLevel ) {
492 nList = LIST_NON;
494 else
495 nListLevel--;
498 break;
499 case ASSIGNMENT:
501 bDontWriteOutput = sal_False;
502 // interpret different types of assignement
503 sal_Int32 n = 0;
504 OString sKey = sToken.getToken(0, '=', n).
505 replaceAll(" ", OString()).
506 replaceAll("\t", OString());
507 OString sValue = sToken.getToken(0, '=', n);
508 CleanValue( sValue );
509 sKey = sKey.toAsciiUpperCase();
510 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("IDENTIFIER")))
512 OString sId(
513 sValue.replaceAll("\t", OString()).
514 replaceAll(" ", OString()));
515 pResData->SetId(sId, ID_LEVEL_IDENTIFIER);
517 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("HELPID")))
519 pResData->sHelpId = sValue;
521 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("STRINGLIST")))
523 pResData->bList = sal_True;
524 nList = LIST_STRING;
525 m_sListLang = SOURCE_LANGUAGE;
526 nListIndex = 0;
527 nListLevel = 0;
529 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("FILTERLIST")))
531 pResData->bList = sal_True;
532 nList = LIST_FILTER;
533 m_sListLang = SOURCE_LANGUAGE;
534 nListIndex = 0;
535 nListLevel = 0;
537 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UIENTRIES")))
539 pResData->bList = sal_True;
540 nList = LIST_UIENTRIES;
541 m_sListLang = SOURCE_LANGUAGE;
542 nListIndex = 0;
543 nListLevel = 0;
545 if (sToken.indexOf( '{' ) != -1
546 && (lcl_countOccurrences(sToken, '{')
547 > lcl_countOccurrences(sToken, '}')))
549 Parse( LEVELUP, "" );
552 break;
553 case UIENTRIES:
554 case LISTASSIGNMENT:
556 bDontWriteOutput = sal_False;
557 OString sTmpToken(
558 sToken.replaceAll(" ", OString()).toAsciiLowerCase());
559 sal_Int32 nPos = sTmpToken.indexOf("[en-us]=");
560 if (nPos != -1) {
561 OString sKey(
562 sTmpToken.copy(0 , nPos).replaceAll(" ", OString()).
563 replaceAll("\t", OString()));
564 OString sValue = sToken.getToken(1, '=');
565 CleanValue( sValue );
566 sKey = sKey.toAsciiUpperCase();
567 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("STRINGLIST")))
569 pResData->bList = sal_True;
570 nList = LIST_STRING;
571 m_sListLang = SOURCE_LANGUAGE;
572 nListIndex = 0;
573 nListLevel = 0;
575 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("FILTERLIST")))
577 pResData->bList = sal_True;
578 nList = LIST_FILTER;
579 m_sListLang = SOURCE_LANGUAGE;
580 nListIndex = 0;
581 nListLevel = 0;
583 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("PAIREDLIST")))
585 pResData->bList = sal_True;
586 nList = LIST_PAIRED;
587 m_sListLang = SOURCE_LANGUAGE;
588 nListIndex = 0;
589 nListLevel = 0;
591 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("ITEMLIST")))
593 pResData->bList = sal_True;
594 nList = LIST_ITEM;
595 m_sListLang = SOURCE_LANGUAGE;
596 nListIndex = 0;
597 nListLevel = 0;
599 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UIENTRIES")))
601 pResData->bList = sal_True;
602 nList = LIST_UIENTRIES;
603 m_sListLang = SOURCE_LANGUAGE;
604 nListIndex = 0;
605 nListLevel = 0;
609 break;
610 case TEXT:
611 case _LISTTEXT:
612 case LISTTEXT: {
613 // this is an entry for a String- or FilterList
614 if ( nList ) {
615 SetChildWithText();
616 sal_Int32 n = 0;
617 OString sEntry(sToken.getToken(1, '"', n));
618 if ( lcl_countOccurrences(sToken, '"') > 2 )
619 sEntry += "\"";
620 if ( sEntry == "\\\"" )
621 sEntry = "\"";
622 InsertListEntry( sEntry, sOrig );
625 break;
626 case LONGTEXTLINE:
627 case TEXTLINE:
628 bDontWriteOutput = sal_False;
629 if ( nLevel )
631 CutComment( sToken );
633 // this is a text line!!!
634 OString t(sToken.getToken(0, '='));
635 OString sKey(
636 t.getToken(0, '[').replaceAll(" ", OString()).
637 replaceAll("\t", OString()));
638 OString sText( GetText( sToken, nToken ));
639 OString sLang;
640 if ( sToken.getToken(0, '=').indexOf('[') != -1 )
642 sLang = sToken.getToken(0, '=').getToken(1, '[').
643 getToken(0, ']');
644 CleanValue( sLang );
646 OString sLangIndex = sLang;
647 OString sOrigKey = sKey;
648 if ( !sText.isEmpty() && !sLang.isEmpty() )
650 sKey = sKey.toAsciiUpperCase();
651 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("TEXT")) ||
652 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("MESSAGE")) ||
653 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("CUSTOMUNITTEXT")) ||
654 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("SLOTNAME")) ||
655 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UINAME")))
657 SetChildWithText();
658 if ( sLangIndex.equalsIgnoreAsciiCase("en-US") )
659 pResData->SetId( sText, ID_LEVEL_TEXT );
661 pResData->bText = sal_True;
662 pResData->sTextTyp = sOrigKey;
663 if ( !bMergeMode )
665 if (!pResData->sText[ sLangIndex ].isEmpty())
667 OStringBuffer sError("Language ");
668 sError.append(sLangIndex);
669 sError.append("defined twice");
670 yyerror(sError.getStr());
672 pResData->sText[ sLangIndex ] = sText;
675 else if ( sKey == "HELPTEXT" ) {
676 SetChildWithText();
677 pResData->bHelpText = sal_True;
678 if ( !bMergeMode )
680 if (!pResData->sHelpText[ sLangIndex ].isEmpty())
682 OStringBuffer sError("Language ");
683 sError.append(sLangIndex);
684 sError.append(" defined twice");
685 YYWarning(sError.getStr());
687 pResData->sHelpText[ sLangIndex ] = sText;
690 else if ( sKey == "QUICKHELPTEXT" ) {
691 SetChildWithText();
692 pResData->bQuickHelpText = sal_True;
693 if ( !bMergeMode )
695 if (!pResData->sQuickHelpText[ sLangIndex ].isEmpty())
697 OStringBuffer sError("Language ");
698 sError.append(sLangIndex);
699 sError.append(" defined twice");
700 YYWarning(sError.getStr());
702 pResData->sQuickHelpText[ sLangIndex ] = sText;
705 else if ( sKey == "TITLE" ) {
706 SetChildWithText();
707 pResData->bTitle = sal_True;
708 if ( !bMergeMode )
710 if ( !pResData->sTitle[ sLangIndex ].isEmpty())
712 OStringBuffer sError("Language ");
713 sError.append(sLangIndex);
714 sError.append(" defined twice");
715 YYWarning(sError.getStr());
717 pResData->sTitle[ sLangIndex ] = sText;
720 else if ( sKey == "ACCESSPATH" ) {
721 pResData->SetId( sText, ID_LEVEL_ACCESSPATH );
723 else if ( sKey == "FIELDNAME" ) {
724 pResData->SetId( sText, ID_LEVEL_FIELDNAME );
728 break;
729 case NEWTEXTINRES: {
730 bDontWriteOutput = sal_True;
732 break;
733 case APPFONTMAPPING:
735 bDontWriteOutput = sal_False;
737 break;
738 case RSCDEFINELEND:
739 bDontWriteOutput = sal_False;
740 break;
741 case CONDITION: {
742 bDontWriteOutput = sal_False;
743 if ( nLevel ) {
744 WriteData( pResData, sal_True );
747 break;
748 case EMPTYLINE : {
749 bDontWriteOutput = sal_False;
750 if ( bDefine ) {
751 bNextMustBeDefineEOL = sal_False;
752 bDefine = sal_False;
753 while ( nLevel )
754 Parse( LEVELDOWN, "" );
757 break;
758 case PRAGMA : {
759 bDontWriteOutput = sal_False;
760 fprintf(stderr, "ERROR: archaic PRAGMA %s\n", sToken.getStr());
761 exit(-1);
763 break;
764 case TEXTREFID : {
765 bDontWriteOutput = sal_True;
768 if ( bWriteToMerged ) {
769 // the current token must be written to dest. without merging
771 if( bDefine && sOrig.getLength() > 2 ){
772 for( sal_uInt16 n = 0 ; n < sOrig.getLength() ; n++ ){
773 if( sOrig[n] == '\n' && sOrig[n-1] != '\\'){
774 sOrig = sOrig.replaceAt(n++, 0, "\\");
778 WriteToMerged( sOrig , false);
781 if ( bExecuteDown ) {
782 Parse( LEVELDOWN, "" );
785 return 1;
788 void Export::CutComment( OString &rText )
790 if (rText.indexOf("//") != -1) {
791 OString sWork(rText.replaceAll("\\\"", "XX"));
792 bool bInner = false;
793 for (sal_Int32 i = 0; i < sWork.getLength() - 1; ++i) {
794 if (sWork[i] == '"') {
795 bInner = !bInner;
796 } else if (sWork[i] == '/' && !bInner && sWork[i + 1] == '/' ) {
797 rText = rText.copy(0, i);
798 break;
804 sal_Bool Export::WriteData( ResData *pResData, sal_Bool bCreateNew )
806 if ( bMergeMode ) {
807 MergeRest( pResData );
808 return sal_True;
811 // mandatory to export: en-US
813 if (( !pResData->sText[ SOURCE_LANGUAGE ].isEmpty())
815 ( !pResData->sHelpText[ SOURCE_LANGUAGE ].isEmpty())
817 ( !pResData->sQuickHelpText[ SOURCE_LANGUAGE ].isEmpty())
819 ( !pResData->sTitle[ SOURCE_LANGUAGE ].isEmpty()))
822 OString sGID = pResData->sGId;
823 OString sLID;
824 if (sGID.isEmpty())
825 sGID = pResData->sId;
826 else
827 sLID = pResData->sId;
829 OString sXText;
830 OString sXHText;
831 OString sXQHText;
832 OString sXTitle;
834 sXText = pResData->sText[ SOURCE_LANGUAGE ];
835 if (!pResData->sText[ X_COMMENT ].isEmpty())
836 sXHText = pResData->sText[ X_COMMENT ];
837 else
838 sXHText = pResData->sHelpText[ SOURCE_LANGUAGE ];
839 sXQHText = pResData->sQuickHelpText[ SOURCE_LANGUAGE ];
840 sXTitle = pResData->sTitle[ SOURCE_LANGUAGE ];
842 if( !sXText.isEmpty() )
844 ConvertExportContent(sXText);
845 ConvertExportContent(sXHText);
846 common::writePoEntry(
847 "Transex3", *aOutput.mPo, global::inputPathname,
848 pResData->sResTyp, sGID, sLID, sXHText, sXText);
850 if( !sXQHText.isEmpty() )
852 ConvertExportContent(sXQHText);
853 common::writePoEntry(
854 "Transex3", *aOutput.mPo, global::inputPathname, pResData->sResTyp,
855 sGID, sLID, OString(), sXQHText, PoEntry::TQUICKHELPTEXT );
857 if( !sXTitle.isEmpty() )
859 ConvertExportContent(sXTitle);
860 common::writePoEntry(
861 "Transex3", *aOutput.mPo, global::inputPathname, pResData->sResTyp,
862 sGID, sLID, OString(), sXTitle, PoEntry::TTITLE );
865 if ( bCreateNew ) {
866 pResData->sText[ SOURCE_LANGUAGE ] = "";
867 pResData->sHelpText[ SOURCE_LANGUAGE ] = "";
868 pResData->sQuickHelpText[ SOURCE_LANGUAGE ]= "";
869 pResData->sTitle[ SOURCE_LANGUAGE ] = "";
872 if ( pResData->pStringList ) {
873 OString sList( "stringlist" );
874 WriteExportList( pResData, pResData->pStringList, sList, bCreateNew );
875 if ( bCreateNew )
876 pResData->pStringList = 0;
878 if ( pResData->pFilterList ) {
879 OString sList( "filterlist" );
880 WriteExportList( pResData, pResData->pFilterList, sList, bCreateNew );
881 if ( bCreateNew )
882 pResData->pFilterList = 0;
884 if ( pResData->pItemList ) {
885 OString sList( "itemlist" );
886 WriteExportList( pResData, pResData->pItemList, sList, bCreateNew );
887 if ( bCreateNew )
888 pResData->pItemList = 0;
890 if ( pResData->pPairedList ) {
891 OString sList( "pairedlist" );
892 WriteExportList( pResData, pResData->pPairedList, sList, bCreateNew );
893 if ( bCreateNew )
894 pResData->pPairedList = 0;
896 if ( pResData->pUIEntries ) {
897 OString sList( "uientries" );
898 WriteExportList( pResData, pResData->pUIEntries, sList, bCreateNew );
899 if ( bCreateNew )
900 pResData->pUIEntries = 0;
902 return sal_True;
905 OString Export::GetPairedListID(const OString& rText)
907 // < "STRING" ; IDENTIFIER ; > ;
908 return rText.getToken(1, ';').toAsciiUpperCase().replace('\t', ' ').trim();
911 OString Export::GetPairedListString(const OString& rText)
913 // < "STRING" ; IDENTIFIER ; > ;
914 OString sString(rText.getToken(0, ';').replace('\t', ' '));
915 sString = sString.trim();
916 OString s1(sString.copy(sString.indexOf('"') + 1));
917 sString = s1.copy(0, s1.lastIndexOf('"'));
918 return sString.trim();
921 OString Export::StripList(const OString & rText)
923 OString s1 = rText.copy( rText.indexOf('\"') + 1);
924 return s1.copy( 0 , s1.lastIndexOf('\"'));
927 sal_Bool Export::WriteExportList(ResData *pResData, ExportList *pExportList,
928 const OString &rTyp, sal_Bool bCreateNew)
930 OString sGID(pResData->sGId);
931 if (sGID.isEmpty())
932 sGID = pResData->sId;
933 else {
934 sGID += ".";
935 sGID += pResData->sId;
936 while (sGID.endsWith(".")) {
937 sGID = sGID.copy(0, sGID.getLength() - 1);
941 for ( size_t i = 0; pExportList != NULL && i < pExportList->size(); i++ )
943 ExportListEntry *pEntry = (*pExportList)[ i ];
945 OString sLID;
946 OString sText((*pEntry)[ SOURCE_LANGUAGE ] );
948 // Strip PairList Line String
949 if (rTyp.equalsIgnoreAsciiCase("pairedlist"))
951 sLID = GetPairedListID( sText );
952 sText = GetPairedListString( sText );
954 else
956 sLID = OString::number(i + 1);
957 sText = StripList( sText );
958 if( sText == "\\\"" )
959 sText = "\"";
961 ConvertExportContent(sText);
962 common::writePoEntry(
963 "Transex3", *aOutput.mPo, global::inputPathname,
964 rTyp, sGID, sLID, OString(), sText);
966 if ( bCreateNew )
967 delete [] pEntry;
969 if ( bCreateNew )
970 delete pExportList;
972 return sal_True;
975 OString Export::FullId()
977 OStringBuffer sFull;
978 if ( nLevel > 1 )
980 sFull.append(aResStack[ 0 ]->sId);
981 for ( size_t i = 1; i < nLevel - 1; ++i )
983 OString sToAdd = aResStack[ i ]->sId;
984 if (!sToAdd.isEmpty())
985 sFull.append('.').append(sToAdd);
988 if (sFull.getLength() > 255)
990 OString sError("GroupId > 255 chars");
991 printf("GroupID = %s\n", sFull.getStr());
992 yyerror(sError.getStr());
995 return sFull.makeStringAndClear();
998 void Export::InsertListEntry(const OString &rText, const OString &rLine)
1000 ResData *pResData = ( nLevel-1 < aResStack.size() ) ? aResStack[ nLevel-1 ] : NULL;
1002 ExportList *pList = NULL;
1003 if ( nList == LIST_STRING ) {
1004 pList = pResData->pStringList;
1005 if ( !pList ) {
1006 pResData->pStringList = new ExportList();
1007 pList = pResData->pStringList;
1008 nListIndex = 0;
1011 else if ( nList == LIST_FILTER ) {
1012 pList = pResData->pFilterList;
1013 if ( !pList ) {
1014 pResData->pFilterList = new ExportList();
1015 pList = pResData->pFilterList;
1016 nListIndex = 0;
1019 else if ( nList == LIST_ITEM ) {
1020 pList = pResData->pItemList;
1021 if ( !pList ) {
1022 pResData->pItemList = new ExportList();
1023 pList = pResData->pItemList;
1024 nListIndex = 0;
1027 else if ( nList == LIST_PAIRED ) {
1028 pList = pResData->pPairedList;
1029 if ( !pList ) {
1030 pResData->pPairedList = new ExportList();
1031 pList = pResData->pPairedList;
1032 nListIndex = 0;
1035 else if ( nList == LIST_UIENTRIES ) {
1036 pList = pResData->pUIEntries;
1037 if ( !pList ) {
1038 pResData->pUIEntries = new ExportList();
1039 pList = pResData->pUIEntries;
1040 nListIndex = 0;
1043 else
1044 return;
1046 if ( nListIndex + 1 > pList->size())
1048 ExportListEntry *pNew = new ExportListEntry();
1049 (*pNew)[LIST_REFID] = OString::number(REFID_NONE);
1050 pList->push_back(pNew);
1052 ExportListEntry *pCurEntry = (*pList)[ nListIndex ];
1054 // For paired list use the line to set proper lid
1055 if( nList == LIST_PAIRED ){
1056 (*pCurEntry)[ m_sListLang ] = rLine;
1057 }else
1058 (*pCurEntry)[ m_sListLang ] = rText;
1060 if ( m_sListLang.equalsIgnoreAsciiCase("en-US") ) {
1061 (*pCurEntry)[ SOURCE_LANGUAGE ] = rLine;
1063 pList->NewSourceLanguageListEntry();
1066 nListIndex++;
1069 void Export::CleanValue( OString &rValue )
1071 while ( !rValue.isEmpty()) {
1072 if (( rValue[0] == ' ' ) || ( rValue[0] == '\t' ))
1073 rValue = rValue.copy( 1 );
1074 else
1075 break;
1078 if ( !rValue.isEmpty()) {
1079 for ( sal_Int32 i = rValue.getLength() - 1; i > 0; i-- ) {
1080 if (( rValue[i] == ' ' ) || ( rValue[i] == '\t' ) ||
1081 ( rValue[i] == '\n' ) || ( rValue[i] == ';' ) ||
1082 ( rValue[i] == '{' ) || ( rValue[i] == '\\' ) ||
1083 ( rValue[i] == '\r' ))
1084 rValue = rValue.copy(0, i);
1085 else
1086 break;
1091 #define TXT_STATE_TEXT 0x001
1092 #define TXT_STATE_MACRO 0x002
1094 OString Export::GetText(const OString &rSource, int nToken)
1096 OString sReturn;
1097 switch ( nToken )
1099 case TEXTLINE:
1100 case LONGTEXTLINE:
1102 OString sTmp(rSource.copy(rSource.indexOf('=')));
1103 CleanValue( sTmp );
1104 sTmp = sTmp.replaceAll("\n", OString()).
1105 replaceAll("\r", OString()).
1106 replaceAll("\\\\\"", "-=<[BSlashBSlashHKom]>=-\"").
1107 replaceAll("\\\"", "-=<[Hochkomma]>=-").
1108 replaceAll("\\\x7f", "-=<[0x7F]>=-").
1109 replaceAll("\\0x7F", "-=<[0x7F]>=-");
1111 sal_uInt16 nState = TXT_STATE_TEXT;
1112 for (sal_Int32 i = 1; i <= lcl_countOccurrences(sTmp, '"'); ++i)
1114 OString sToken(sTmp.getToken(i, '"'));
1115 if (!sToken.isEmpty()) {
1116 if ( nState == TXT_STATE_TEXT ) {
1117 sReturn += sToken;
1118 nState = TXT_STATE_MACRO;
1120 else {
1121 sToken = sToken.replace('\t', ' ');
1122 for (;;) {
1123 sal_Int32 n = 0;
1124 sToken = sToken.replaceFirst(" ", " ", &n);
1125 if (n == -1) {
1126 break;
1129 sToken = sToken.trim();
1130 if (!sToken.isEmpty()) {
1131 sReturn += "\\\" ";
1132 sReturn += sToken;
1133 sReturn += " \\\"";
1135 nState = TXT_STATE_TEXT;
1140 sReturn = sReturn.replaceAll("-=<[0x7F]>=-", "\x7f").
1141 replaceAll("-=<[Hochkomma]>=-", "\"").
1142 replaceAll("-=<[BSlashBSlashHKom]>=-", "\\\\").
1143 replaceAll("\\\\", "-=<[BSlashBSlash]>=-").
1144 replaceAll("-=<[BSlashBSlash]>=-", "\\");
1146 break;
1148 return sReturn;
1151 void Export::WriteToMerged(const OString &rText , bool bSDFContent)
1153 OString sText(rText);
1154 for (;;) {
1155 sal_Int32 n = 0;
1156 sText = sText.replaceFirst(" \n", "\n", &n);
1157 if (n == -1) {
1158 break;
1161 if (pParseQueue->bNextIsM && bSDFContent && sText.getLength() > 2) {
1162 for (sal_Int32 n = 0; n < sText.getLength(); ++n) {
1163 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1164 sText = sText.replaceAt(n++, 0, "\\");
1167 } else if (pParseQueue->bLastWasM && sText.getLength() > 2) {
1168 for (sal_Int32 n = 0; n < sText.getLength(); ++n) {
1169 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1170 sText = sText.replaceAt(n++, 0, "\\");
1172 if (sText[n] == '\n') {
1173 pParseQueue->bMflag = true;
1176 } else if (pParseQueue->bCurrentIsM && bSDFContent && sText.getLength() > 2)
1178 for (sal_Int32 n = 0; n < sText.getLength(); ++n) {
1179 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1180 sText = sText.replaceAt(n++, 0, "\\");
1181 pParseQueue->bMflag = true;
1184 } else if (pParseQueue->bMflag) {
1185 for (sal_Int32 n = 1; n < sText.getLength(); ++n) {
1186 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1187 sText = sText.replaceAt(n++, 0, "\\");
1190 } for (sal_Int32 i = 0; i < sText.getLength(); ++i) {
1191 if (sText[i] == '\n') {
1192 *aOutput.mSimple << '\n';
1193 } else {
1194 char cChar = sText[i];
1195 *aOutput.mSimple << cChar;
1200 void Export::ConvertMergeContent( OString &rText )
1202 rText = rText.replaceAll("\\\'","\'"); // Temporary: until PO files contain escaped single quotes
1203 // (Maybe next PO update solve this)
1204 rText =
1205 helper::escapeAll(
1206 rText.replaceAll("\x7f","\\0x7F"),
1207 "\n""\t""\\""\"","\\n""\\t""\\\\""\\\"");
1209 rText = "\"" + rText + "\"";
1212 void Export::ConvertExportContent( OString& rText )
1214 rText = helper::unEscapeAll(rText,"\\n""\\t""\\\\""\\\"","\n""\t""\\""\"");
1217 bool Export::GetAllMergeEntrysOfList(ResData *pResData, std::vector<MergeEntrys*>& o_vMergeEntrys, ExportList*& o_pList )
1219 o_vMergeEntrys.clear();
1220 o_pList = 0;
1222 if (!pResData->sGId.isEmpty())
1223 pResData->sGId = pResData->sGId + OString('.');
1224 pResData->sGId = pResData->sGId + pResData->sId;
1226 // Find out the type of List
1227 MergeEntrys* pEntrysOfFirstItem = 0;
1228 sal_uInt16 nType = LIST_STRING;
1229 bool bPairedList = false;
1230 while( !pEntrysOfFirstItem && nType <= LIST_UIENTRIES )
1232 switch ( nType )
1234 case LIST_STRING : pResData->sResTyp = "stringlist"; o_pList = pResData->pStringList; bPairedList = false; break;
1235 case LIST_FILTER : pResData->sResTyp = "filterlist"; o_pList = pResData->pFilterList; bPairedList = false; break;
1236 case LIST_UIENTRIES : pResData->sResTyp = "uientries"; o_pList = pResData->pUIEntries;bPairedList = false; break;
1237 case LIST_ITEM : pResData->sResTyp = "itemlist"; o_pList = pResData->pItemList; bPairedList = false; break;
1238 case LIST_PAIRED : pResData->sResTyp = "pairedlist"; o_pList = pResData->pPairedList; bPairedList = true; break;
1241 // Set matching pairedlist identifier
1242 if( bPairedList && pResData->pPairedList )
1244 ExportListEntry* pListE = ( ExportListEntry* ) (*pResData->pPairedList)[ 0 ];
1245 pResData->sId = GetPairedListID ( (*pListE)[ SOURCE_LANGUAGE ] );
1247 else
1248 pResData->sId = "1";
1250 pEntrysOfFirstItem = pMergeDataFile->GetMergeEntrys( pResData );
1251 ++nType;
1254 if( !pEntrysOfFirstItem )
1256 o_pList = 0;
1257 return false;
1259 else
1260 nList = nType-1;
1262 sal_uInt16 nMaxIndex = 0;
1263 if ( o_pList )
1265 nMaxIndex = o_pList->GetSourceLanguageListEntryCount();
1268 * Check whether count of listentries match with count
1269 * of translated items. If not than write origin items
1270 * to the list to avoid mixed translations
1271 * (exclude pairedlist)
1273 if( !bPairedList )
1275 MergeEntrys* pEntrys;
1276 // MergeData contains longer list
1277 pResData->sId = OString::number(nMaxIndex+1);
1278 pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
1279 if ( pEntrys )
1280 return false;
1281 // MergeData contains shorter list
1282 pResData->sId = OString::number(nMaxIndex);
1283 pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
1284 if ( !pEntrys )
1285 return false;
1286 pResData->sId = "1";
1289 o_vMergeEntrys.push_back(pEntrysOfFirstItem);
1291 for( sal_uInt16 nLIndex = 2; nLIndex <= nMaxIndex; ++nLIndex )
1293 // Set matching pairedlist identifier
1294 if ( bPairedList )
1296 ExportListEntry* pListE = ( ExportListEntry* )(*pResData->pPairedList)[ ( nLIndex ) -1 ];
1297 if( pListE )
1299 pResData->sId = GetPairedListID ( (*pListE)[ SOURCE_LANGUAGE ] );
1302 else
1303 pResData->sId = OString::number(nLIndex);
1305 MergeEntrys* pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
1306 o_vMergeEntrys.push_back(pEntrys);
1308 return true;
1311 void Export::ResData2Output( MergeEntrys *pEntry, sal_uInt16 nType, const OString& rTextType )
1313 sal_Bool bAddSemicolon = sal_False;
1314 sal_Bool bFirst = sal_True;
1315 OString sCur;
1317 for( unsigned int n = 0; n < aLanguages.size(); n++ ){
1318 sCur = aLanguages[ n ];
1320 OString sText;
1321 sal_Bool bText = pEntry->GetText( sText, nType, sCur , sal_True );
1322 if ( bText && !sText.isEmpty() ) {
1323 OString sOutput;
1324 if ( bNextMustBeDefineEOL) {
1325 if ( bFirst )
1326 sOutput += "\t\\\n";
1327 else
1328 sOutput += ";\t\\\n";
1330 bFirst=sal_False;
1331 sOutput += "\t";
1333 sOutput += rTextType;
1335 if ( !sCur.equalsIgnoreAsciiCase("en-US") ) {
1336 sOutput += "[ ";
1337 sOutput += sCur;
1338 sOutput += " ] ";
1340 sOutput += "= ";
1341 ConvertMergeContent( sText );
1342 sOutput += sText;
1344 if ( bDefine )
1345 sOutput += ";\\\n";
1346 else if ( !bNextMustBeDefineEOL )
1347 sOutput += ";\n";
1348 else
1349 bAddSemicolon = sal_True;
1350 for ( sal_uInt16 j = 1; j < nLevel; j++ )
1351 sOutput += "\t";
1352 WriteToMerged( sOutput , true );
1357 if ( bAddSemicolon ) {
1358 OString sOutput( ";" );
1359 WriteToMerged( sOutput , false );
1363 void Export::MergeRest( ResData *pResData, sal_uInt16 nMode )
1365 if ( !pMergeDataFile ){
1366 pMergeDataFile = new MergeDataFile( sMergeSrc, global::inputPathname, false );
1367 aLanguages = pMergeDataFile->GetLanguages();
1370 switch ( nMode ) {
1371 case MERGE_MODE_NORMAL : {
1372 MergeEntrys *pEntry = 0;
1373 if( pResData->bText || pResData->bQuickHelpText || pResData->bTitle )
1374 pEntry = pMergeDataFile->GetMergeEntrys( pResData );
1376 if ( pEntry ) {
1377 if ( pResData->bText )
1378 ResData2Output( pEntry, STRING_TYP_TEXT, pResData->sTextTyp );
1380 if ( pResData->bQuickHelpText )
1381 ResData2Output( pEntry, STRING_TYP_QUICKHELPTEXT, OString("QuickHelpText") );
1383 if ( pResData->bTitle )
1384 ResData2Output( pEntry, STRING_TYP_TITLE, OString("Title") );
1387 // Merge Lists
1389 if ( pResData->bList ) {
1390 OString sOldId = pResData->sId;
1391 OString sOldGId = pResData->sGId;
1392 OString sOldTyp = pResData->sResTyp;
1393 sal_uInt16 nOldListTyp = nList;
1395 OString sSpace;
1396 for ( sal_uInt16 i = 1; i < nLevel-1; i++ )
1397 sSpace += "\t";
1399 std::vector<MergeEntrys*> vMergeEntryVector;
1400 ExportList* pList = 0;
1401 bool bTranslateList = GetAllMergeEntrysOfList(pResData, vMergeEntryVector, pList);
1403 if( pList )
1405 OString sCur;
1406 for( unsigned int n = 0; n < aLanguages.size(); n++ )
1408 sCur = aLanguages[ n ];
1410 sal_uInt16 nLIndex = 0;
1411 sal_uInt16 nMaxIndex = pList->GetSourceLanguageListEntryCount();
1412 while( nLIndex < nMaxIndex )
1414 if ( nLIndex == 0 )
1416 OStringBuffer sHead;
1417 if ( bNextMustBeDefineEOL )
1418 sHead.append("\\\n\t");
1419 sHead.append(sSpace);
1420 switch ( nList )
1422 case LIST_STRING:
1423 sHead.append("StringList ");
1424 break;
1425 case LIST_FILTER:
1426 sHead.append("FilterList ");
1427 break;
1428 case LIST_ITEM:
1429 sHead.append("ItemList ");
1430 break;
1431 case LIST_PAIRED:
1432 sHead.append("PairedList ");
1433 break;
1434 case LIST_UIENTRIES:
1435 sHead.append("UIEntries ");
1436 break;
1438 sHead.append("[ ");
1439 sHead.append(sCur);
1440 sHead.append(" ] ");
1441 if ( bDefine || bNextMustBeDefineEOL )
1443 sHead.append("= \\\n");
1444 sHead.append(sSpace);
1445 sHead.append("\t{\\\n\t");
1447 else
1449 sHead.append("= \n");
1450 sHead.append(sSpace);
1451 sHead.append("\t{\n\t");
1453 WriteToMerged(sHead.makeStringAndClear() , true);
1455 OString sLine;
1456 if ( pList && (*pList)[ nLIndex ] )
1457 sLine = ( *(*pList)[ nLIndex ])[ SOURCE_LANGUAGE ];
1459 if ( sLine.indexOf( '>' ) != -1 ) {
1460 if (( nList != LIST_UIENTRIES ) &&
1461 (( sLine.indexOf( '{' ) == -1 ) ||
1462 ( sLine.indexOf( '{' ) >= sLine.indexOf( '"' ))) &&
1463 (( sLine.indexOf( '<' ) == -1 ) ||
1464 ( sLine.indexOf( '<' ) >= sLine.indexOf( '"' ))))
1466 sLine = sLine.replaceFirst("\"", "< \"" );
1470 if( bTranslateList && nLIndex < vMergeEntryVector.size() && vMergeEntryVector[nLIndex] )
1472 OString sText;
1473 sal_Bool bText;
1474 bText = vMergeEntryVector[nLIndex]->GetText( sText, STRING_TYP_TEXT, sCur, sal_True );
1475 if ( bText && !sText.isEmpty() )
1477 ConvertMergeContent( sText );
1478 OString sPre = sLine.copy( 0 , sLine.indexOf('"') );
1479 OString sPost = sLine.copy( sLine.lastIndexOf('"') + 1 );
1480 sLine = sPre + sText + sPost;
1484 OString sText1( "\t" );
1485 sText1 += sLine;
1486 if ( bDefine || bNextMustBeDefineEOL )
1487 sText1 += " ;\\\n";
1488 else
1489 sText1 += " ;\n";
1490 sText1 += sSpace;
1491 sText1 += "\t";
1492 WriteToMerged( sText1 ,true );
1493 ++nLIndex;
1495 if ( nLIndex > 0 ) {
1496 OString sFooter;
1497 if (!sSpace.isEmpty()) {
1498 sFooter = sSpace.copy(1);
1500 if ( bNextMustBeDefineEOL )
1501 sFooter += "};";
1502 else if ( !bDefine )
1503 sFooter += "};\n\t";
1504 else
1505 sFooter += "\n\n";
1506 WriteToMerged( sFooter ,true );
1511 pResData->sId = sOldId;
1512 pResData->sGId = sOldGId;
1513 pResData->sResTyp = sOldTyp;
1514 nList = nOldListTyp;
1517 break;
1518 case MERGE_MODE_LIST : {
1520 break;
1522 pParseQueue->bMflag = false;
1525 void Export::SetChildWithText()
1527 if ( aResStack.size() > 1 ) {
1528 for ( size_t i = 0; i < aResStack.size() - 1; i++ ) {
1529 aResStack[ i ]->bChildWithText = sal_True;
1534 void ParserQueue::Push( const QueueEntry& aEntry )
1536 sal_Int32 nLen = aEntry.sLine.getLength();
1538 if( !bStart ){
1539 aQueueCur->push( aEntry );
1540 if( nLen > 1 && aEntry.sLine[nLen-1] == '\n' )
1541 bStart = true;
1542 else if ( aEntry.nTyp != IGNOREDTOKENS ){
1543 if( nLen > 1 && ( aEntry.sLine[nLen-1] == '\\') ){
1544 // Next is Macro
1545 bCurrentIsM = true;
1546 }else{
1547 // Next is no Macro
1548 bCurrentIsM = false;
1552 else{
1553 aQueueNext->push( aEntry );
1554 if( nLen > 1 && aEntry.sLine[nLen-1] != '\n' ){
1555 if( nLen > 1 && ( aEntry.sLine[nLen-1] == '\\') ){
1556 // Next is Macro
1557 bNextIsM = true;
1559 else{
1560 // Next is no Macro
1561 bNextIsM = false;
1563 }else if( nLen > 2 && aEntry.sLine[nLen-1] == '\n' ){
1564 if( aEntry.nTyp != IGNOREDTOKENS ){
1565 if( nLen > 2 && ( aEntry.sLine[nLen-2] == '\\') ){
1566 // Next is Macro
1567 bNextIsM = true;
1569 else{
1570 // Next is no Macro
1571 bNextIsM = false;
1574 // Pop current
1575 Pop( *aQueueCur );
1576 bLastWasM = bCurrentIsM;
1577 // next -> current
1578 bCurrentIsM = bNextIsM;
1579 aQref = aQueueCur;
1580 aQueueCur = aQueueNext;
1581 aQueueNext = aQref;
1585 else{
1586 // Pop current
1587 Pop( *aQueueCur );
1588 bLastWasM = bCurrentIsM;
1589 // next -> current
1590 bCurrentIsM = bNextIsM;
1591 aQref = aQueueCur;
1592 aQueueCur = aQueueNext;
1593 aQueueNext = aQref;
1598 void ParserQueue::Close(){
1599 // Pop current
1600 Pop( *aQueueCur );
1601 // next -> current
1602 bLastWasM = bCurrentIsM;
1603 bCurrentIsM = bNextIsM;
1604 aQref = aQueueCur;
1605 aQueueCur = aQueueNext;
1606 aQueueNext = aQref;
1607 bNextIsM = false;
1608 Pop( *aQueueNext );
1611 void ParserQueue::Pop( std::queue<QueueEntry>& aQueue )
1613 while (!aQueue.empty())
1615 QueueEntry aEntry = aQueue.front();
1616 aQueue.pop();
1617 aExport.Execute(aEntry.nTyp, aEntry.sLine.getStr());
1621 ParserQueue::ParserQueue( Export& aExportObj )
1623 bCurrentIsM( false ),
1624 bNextIsM( false ) ,
1625 bLastWasM( false ),
1626 bMflag( false ) ,
1627 aExport( aExportObj ) ,
1628 bStart( false )
1630 aQueueNext = new std::queue<QueueEntry>;
1631 aQueueCur = new std::queue<QueueEntry>;
1635 ParserQueue::~ParserQueue(){
1636 if( aQueueNext ) delete aQueueNext;
1637 if( aQueueCur ) delete aQueueCur;
1640 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */