bump product version to 4.1.6.2
[LibreOffice.git] / l10ntools / source / export.cxx
blob44672df9a8c463135284ecf91fd786bcbadf10f2
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(
73 new Export(aArgs.m_sMergeSrc, aArgs.m_sOutputFile, aArgs.m_sLanguage));
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(RTL_CONSTASCII_STRINGPARAM("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 )
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);
223 void Export::Init()
225 // resets the internal status, used before parseing another file
226 bDefine = sal_False;
227 bNextMustBeDefineEOL = sal_False;
228 nLevel = 0;
229 nList = LIST_NON;
230 m_sListLang = OString();
231 nListIndex = 0;
232 for ( size_t i = 0, n = aResStack.size(); i < n; ++i )
233 delete aResStack[ i ];
234 aResStack.clear();
237 Export::~Export()
239 if( pParseQueue )
240 delete pParseQueue;
241 if ( bMergeMode )
243 aOutput.mSimple->close();
244 delete aOutput.mSimple;
246 else
248 aOutput.mPo->close();
249 delete aOutput.mPo;
251 for ( size_t i = 0, n = aResStack.size(); i < n; ++i )
252 delete aResStack[ i ];
253 aResStack.clear();
255 if ( bMergeMode ) {
256 if ( !pMergeDataFile )
257 pMergeDataFile = new MergeDataFile(sMergeSrc, global::inputPathname, false);
259 delete pMergeDataFile;
263 int Export::Execute( int nToken, const char * pToken )
266 OString sToken( pToken );
267 OString sOrig( sToken );
268 sal_Bool bWriteToMerged = bMergeMode;
270 if ( nToken == CONDITION )
272 OString sTestToken(pToken);
273 sTestToken = sTestToken.replaceAll("\t", OString()).
274 replaceAll(" ", OString());
275 if (( !bReadOver ) && ( sTestToken.indexOf("#ifndef__RSC_PARSER") == 0 ))
276 bReadOver = sal_True;
277 else if (( bReadOver ) && ( sTestToken.indexOf("#endif") == 0 ))
278 bReadOver = sal_False;
280 if ((( nToken < FILTER_LEVEL ) || ( bReadOver )) &&
281 (!(( bNextMustBeDefineEOL ) && ( sOrig == "\n" )))) {
282 // this tokens are not mandatory for parsing, so ignore them ...
283 if ( bMergeMode )
284 WriteToMerged( sOrig , false ); // ... or write them directly to dest.
285 return 0;
288 ResData *pResData = NULL;
289 if ( nLevel ) {
290 // res. exists at cur. level
291 pResData = ( (nLevel-1) < aResStack.size() ) ? aResStack[ nLevel-1 ] : NULL;
293 else if (( nToken != RESOURCE ) &&
294 ( nToken != RESOURCEEXPR ) &&
295 ( nToken != SMALRESOURCE ) &&
296 ( nToken != LEVELUP ) &&
297 ( nToken != NORMDEFINE ) &&
298 ( nToken != RSCDEFINE ) &&
299 ( nToken != CONDITION ) &&
300 ( nToken != PRAGMA ))
302 // no res. exists at cur. level so return
303 if ( bMergeMode )
304 WriteToMerged( sOrig , false );
305 return 0;
307 // #define NO_LOCALIZE_EXPORT
308 if( bSkipFile ){
309 if ( bMergeMode ) {
310 WriteToMerged( sOrig , false );
312 return 1;
316 if ( bDefine ) {
317 if (( nToken != EMPTYLINE ) && ( nToken != LEVELDOWN ) && ( nToken != LEVELUP )) {
318 // cur. res. defined in macro
319 if ( bNextMustBeDefineEOL ) {
320 if ( nToken != RSCDEFINELEND ) {
321 // end of macro found, so destroy res.
322 bDefine = sal_False;
323 Execute( LEVELDOWN, "" );
324 bNextMustBeDefineEOL = sal_False;
326 else {
327 // next line also in macro definition
328 bNextMustBeDefineEOL = sal_False;
329 if ( bMergeMode )
330 WriteToMerged( sOrig , false );
331 return 1;
337 sal_Bool bExecuteDown = sal_False;
338 if ( nToken != LEVELDOWN ) {
339 sal_uInt16 nOpen = 0;
340 sal_uInt16 nClose = 0;
341 sal_Bool bReadOver1 = sal_False;
342 sal_uInt16 i = 0;
343 for ( i = 0; i < sToken.getLength(); i++ ) {
344 if ( sToken[i] == '"' )
345 bReadOver1 = !bReadOver1;
346 if ( !bReadOver1 && ( sToken[i] == '{' ))
347 nOpen++;
350 bReadOver1 = sal_False;
351 for ( i = 0; i < sToken.getLength(); i++ ) {
352 if ( sToken[i] == '"' )
353 bReadOver1 = !bReadOver1;
354 if ( !bReadOver1 && ( sToken[i] == '}' ))
355 nClose++;
358 if ( nOpen < nClose )
359 bExecuteDown = sal_True;
361 switch ( nToken ) {
363 case NORMDEFINE:
364 sToken = sToken.replace('\r', ' ').replace('\t', ' ');
365 for (;;) {
366 sal_Int32 n = 0;
367 sToken = sToken.replaceFirst(" ", " ", &n);
368 if (n == -1) {
369 break;
372 if( sToken.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("#define NO_LOCALIZE_EXPORT")) ){
373 bSkipFile = true;
374 return 0;
376 if ( bMergeMode )
377 WriteToMerged( sOrig , false );
379 return 0;
382 case RSCDEFINE:
383 bDefine = sal_True; // res. defined in macro
385 case RESOURCE:
386 case RESOURCEEXPR: {
387 bDontWriteOutput = sal_False;
388 if ( nToken != RSCDEFINE )
389 bNextMustBeDefineEOL = sal_False;
390 // this is the beginning of a new res.
391 nLevel++;
392 if ( nLevel > 1 ) {
393 aResStack[ nLevel - 2 ]->bChild = sal_True;
396 // create new instance for this res. and fill mandatory fields
398 pResData = new ResData( FullId() , sFilename );
399 aResStack.push_back( pResData );
400 sToken = sToken.replaceAll("\n", OString()).
401 replaceAll("\r", OString()).
402 replaceAll("{", OString()).replace('\t', ' ');
403 sToken = sToken.trim();
404 OString sTLower = sToken.getToken(0, ' ').toAsciiLowerCase();
405 pResData->sResTyp = sTLower;
406 OString sId( sToken.copy( pResData->sResTyp.getLength() + 1 ));
407 OString sCondition;
408 if ( sId.indexOf( '#' ) != -1 )
410 // between ResTyp, Id and paranthes is a precomp. condition
411 sCondition = "#";
412 sal_Int32 n = 0;
413 sId = sId.getToken(0, '#', n);
414 sCondition += sId.getToken(0, '#', n);
416 sId = sId.getToken(0, '/');
417 CleanValue( sId );
418 sId = sId.replaceAll("\t", OString());
419 pResData->SetId( sId, ID_LEVEL_IDENTIFIER );
420 if (!sCondition.isEmpty())
422 Execute( CONDITION, ""); // execute the precomp. condition
425 break;
426 case SMALRESOURCE: {
427 bDontWriteOutput = sal_False;
428 // this is the beginning of a new res.
429 bNextMustBeDefineEOL = sal_False;
430 nLevel++;
431 if ( nLevel > 1 ) {
432 aResStack[ nLevel - 2 ]->bChild = sal_True;
435 // create new instance for this res. and fill mandatory fields
437 pResData = new ResData( FullId() , sFilename );
438 aResStack.push_back( pResData );
439 sToken = sToken.replaceAll("\n", OString()).
440 replaceAll("\r", OString()).
441 replaceAll("{", OString()).
442 replaceAll("\t", OString()).
443 replaceAll(" ", OString()).
444 replaceAll("\\", OString()).toAsciiLowerCase();
445 pResData->sResTyp = sToken;
447 break;
448 case LEVELUP: {
449 // push
450 if ( nList )
451 nListLevel++;
452 if ( nList )
453 break;
455 bDontWriteOutput = sal_False;
456 OString sLowerTyp;
457 if ( pResData )
458 sLowerTyp = "unknown";
459 nLevel++;
460 if ( nLevel > 1 ) {
461 aResStack[ nLevel - 2 ]->bChild = sal_True;
464 ResData *pNewData = new ResData( FullId() , sFilename );
465 pNewData->sResTyp = sLowerTyp;
466 aResStack.push_back( pNewData );
468 break;
469 case LEVELDOWN: {
470 // pop
471 if ( !nList ) {
472 bDontWriteOutput = sal_False;
473 if ( nLevel ) {
474 if ( bDefine && (nLevel == 1 )) {
475 bDefine = sal_False;
476 bNextMustBeDefineEOL = sal_False;
478 WriteData( pResData );
479 ResStack::iterator it = aResStack.begin();
480 ::std::advance( it, nLevel-1 );
481 delete *it;
482 aResStack.erase( it );
483 nLevel--;
486 else {
487 if ( bDefine )
488 bNextMustBeDefineEOL = sal_True;
489 if ( !nListLevel ) {
490 nList = LIST_NON;
492 else
493 nListLevel--;
496 break;
497 case ASSIGNMENT:
499 bDontWriteOutput = sal_False;
500 // interpret different types of assignement
501 sal_Int32 n = 0;
502 OString sKey = sToken.getToken(0, '=', n).
503 replaceAll(" ", OString()).
504 replaceAll("\t", OString());
505 OString sValue = sToken.getToken(0, '=', n);
506 CleanValue( sValue );
507 sKey = sKey.toAsciiUpperCase();
508 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("IDENTIFIER")))
510 OString sId(
511 sValue.replaceAll("\t", OString()).
512 replaceAll(" ", OString()));
513 pResData->SetId(sId, ID_LEVEL_IDENTIFIER);
515 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("HELPID")))
517 pResData->sHelpId = sValue;
519 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("STRINGLIST")))
521 pResData->bList = sal_True;
522 nList = LIST_STRING;
523 m_sListLang = SOURCE_LANGUAGE;
524 nListIndex = 0;
525 nListLevel = 0;
527 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("FILTERLIST")))
529 pResData->bList = sal_True;
530 nList = LIST_FILTER;
531 m_sListLang = SOURCE_LANGUAGE;
532 nListIndex = 0;
533 nListLevel = 0;
535 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UIENTRIES")))
537 pResData->bList = sal_True;
538 nList = LIST_UIENTRIES;
539 m_sListLang = SOURCE_LANGUAGE;
540 nListIndex = 0;
541 nListLevel = 0;
543 if (sToken.indexOf( '{' ) != -1
544 && (lcl_countOccurrences(sToken, '{')
545 > lcl_countOccurrences(sToken, '}')))
547 Parse( LEVELUP, "" );
550 break;
551 case UIENTRIES:
552 case LISTASSIGNMENT:
554 bDontWriteOutput = sal_False;
555 OString sTmpToken(
556 sToken.replaceAll(" ", OString()).toAsciiLowerCase());
557 sal_Int32 nPos = sTmpToken.indexOf("[en-us]=");
558 if (nPos != -1) {
559 OString sKey(
560 sTmpToken.copy(0 , nPos).replaceAll(" ", OString()).
561 replaceAll("\t", OString()));
562 OString sValue = sToken.getToken(1, '=');
563 CleanValue( sValue );
564 sKey = sKey.toAsciiUpperCase();
565 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("STRINGLIST")))
567 pResData->bList = sal_True;
568 nList = LIST_STRING;
569 m_sListLang = SOURCE_LANGUAGE;
570 nListIndex = 0;
571 nListLevel = 0;
573 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("FILTERLIST")))
575 pResData->bList = sal_True;
576 nList = LIST_FILTER;
577 m_sListLang = SOURCE_LANGUAGE;
578 nListIndex = 0;
579 nListLevel = 0;
581 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("PAIREDLIST")))
583 pResData->bList = sal_True;
584 nList = LIST_PAIRED;
585 m_sListLang = SOURCE_LANGUAGE;
586 nListIndex = 0;
587 nListLevel = 0;
589 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("ITEMLIST")))
591 pResData->bList = sal_True;
592 nList = LIST_ITEM;
593 m_sListLang = SOURCE_LANGUAGE;
594 nListIndex = 0;
595 nListLevel = 0;
597 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UIENTRIES")))
599 pResData->bList = sal_True;
600 nList = LIST_UIENTRIES;
601 m_sListLang = SOURCE_LANGUAGE;
602 nListIndex = 0;
603 nListLevel = 0;
607 break;
608 case TEXT:
609 case _LISTTEXT:
610 case LISTTEXT: {
611 // this is an entry for a String- or FilterList
612 if ( nList ) {
613 SetChildWithText();
614 sal_Int32 n = 0;
615 OString sEntry(sToken.getToken(1, '"', n));
616 if ( lcl_countOccurrences(sToken, '"') > 2 )
617 sEntry += "\"";
618 if ( sEntry == "\\\"" )
619 sEntry = "\"";
620 InsertListEntry( sEntry, sOrig );
623 break;
624 case LONGTEXTLINE:
625 case TEXTLINE:
626 bDontWriteOutput = sal_False;
627 if ( nLevel )
629 CutComment( sToken );
631 // this is a text line!!!
632 OString t(sToken.getToken(0, '='));
633 OString sKey(
634 t.getToken(0, '[').replaceAll(" ", OString()).
635 replaceAll("\t", OString()));
636 OString sText( GetText( sToken, nToken ));
637 OString sLang;
638 if ( sToken.getToken(0, '=').indexOf('[') != -1 )
640 sLang = sToken.getToken(0, '=').getToken(1, '[').
641 getToken(0, ']');
642 CleanValue( sLang );
644 OString sLangIndex = sLang;
645 OString sOrigKey = sKey;
646 if ( !sText.isEmpty() && !sLang.isEmpty() )
648 sKey = sKey.toAsciiUpperCase();
649 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("TEXT")) ||
650 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("MESSAGE")) ||
651 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("CUSTOMUNITTEXT")) ||
652 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("SLOTNAME")) ||
653 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UINAME")))
655 SetChildWithText();
656 if ( sLangIndex.equalsIgnoreAsciiCase("en-US") )
657 pResData->SetId( sText, ID_LEVEL_TEXT );
659 pResData->bText = sal_True;
660 pResData->sTextTyp = sOrigKey;
661 if ( !bMergeMode )
663 if (!pResData->sText[ sLangIndex ].isEmpty())
665 OStringBuffer sError(RTL_CONSTASCII_STRINGPARAM("Language "));
666 sError.append(sLangIndex);
667 sError.append(RTL_CONSTASCII_STRINGPARAM("defined twice"));
668 yyerror(sError.getStr());
670 pResData->sText[ sLangIndex ] = sText;
673 else if ( sKey == "HELPTEXT" ) {
674 SetChildWithText();
675 pResData->bHelpText = sal_True;
676 if ( !bMergeMode )
678 if (!pResData->sHelpText[ sLangIndex ].isEmpty())
680 OStringBuffer sError(RTL_CONSTASCII_STRINGPARAM("Language "));
681 sError.append(sLangIndex);
682 sError.append(" defined twice");
683 YYWarning(sError.getStr());
685 pResData->sHelpText[ sLangIndex ] = sText;
688 else if ( sKey == "QUICKHELPTEXT" ) {
689 SetChildWithText();
690 pResData->bQuickHelpText = sal_True;
691 if ( !bMergeMode )
693 if (!pResData->sQuickHelpText[ sLangIndex ].isEmpty())
695 OStringBuffer sError(RTL_CONSTASCII_STRINGPARAM("Language "));
696 sError.append(sLangIndex);
697 sError.append(RTL_CONSTASCII_STRINGPARAM(" defined twice"));
698 YYWarning(sError.getStr());
700 pResData->sQuickHelpText[ sLangIndex ] = sText;
703 else if ( sKey == "TITLE" ) {
704 SetChildWithText();
705 pResData->bTitle = sal_True;
706 if ( !bMergeMode )
708 if ( !pResData->sTitle[ sLangIndex ].isEmpty())
710 OStringBuffer sError(RTL_CONSTASCII_STRINGPARAM("Language "));
711 sError.append(sLangIndex);
712 sError.append(RTL_CONSTASCII_STRINGPARAM(" defined twice"));
713 YYWarning(sError.getStr());
715 pResData->sTitle[ sLangIndex ] = sText;
718 else if ( sKey == "ACCESSPATH" ) {
719 pResData->SetId( sText, ID_LEVEL_ACCESSPATH );
721 else if ( sKey == "FIELDNAME" ) {
722 pResData->SetId( sText, ID_LEVEL_FIELDNAME );
726 break;
727 case NEWTEXTINRES: {
728 bDontWriteOutput = sal_True;
730 break;
731 case APPFONTMAPPING:
733 bDontWriteOutput = sal_False;
735 break;
736 case RSCDEFINELEND:
737 bDontWriteOutput = sal_False;
738 break;
739 case CONDITION: {
740 bDontWriteOutput = sal_False;
741 if ( nLevel ) {
742 WriteData( pResData, sal_True );
745 break;
746 case EMPTYLINE : {
747 bDontWriteOutput = sal_False;
748 if ( bDefine ) {
749 bNextMustBeDefineEOL = sal_False;
750 bDefine = sal_False;
751 while ( nLevel )
752 Parse( LEVELDOWN, "" );
755 break;
756 case PRAGMA : {
757 bDontWriteOutput = sal_False;
758 fprintf(stderr, "ERROR: archaic PRAGMA %s\n", sToken.getStr());
759 exit(-1);
761 break;
762 case TEXTREFID : {
763 bDontWriteOutput = sal_True;
766 if ( bWriteToMerged ) {
767 // the current token must be written to dest. without merging
769 if( bDefine && sOrig.getLength() > 2 ){
770 for( sal_uInt16 n = 0 ; n < sOrig.getLength() ; n++ ){
771 if( sOrig[n] == '\n' && sOrig[n-1] != '\\'){
772 sOrig = sOrig.replaceAt(n++, 0, "\\");
776 WriteToMerged( sOrig , false);
779 if ( bExecuteDown ) {
780 Parse( LEVELDOWN, "" );
783 return 1;
786 void Export::CutComment( OString &rText )
788 if (rText.indexOf("//") != -1) {
789 OString sWork(rText.replaceAll("\\\"", "XX"));
790 bool bInner = false;
791 for (sal_Int32 i = 0; i < sWork.getLength() - 1; ++i) {
792 if (sWork[i] == '"') {
793 bInner = !bInner;
794 } else if (sWork[i] == '/' && !bInner && sWork[i + 1] == '/' ) {
795 rText = rText.copy(0, i);
796 break;
802 sal_Bool Export::WriteData( ResData *pResData, sal_Bool bCreateNew )
804 if ( bMergeMode ) {
805 MergeRest( pResData );
806 return sal_True;
809 // mandatory to export: en-US
811 if (( !pResData->sText[ SOURCE_LANGUAGE ].isEmpty())
813 ( !pResData->sHelpText[ SOURCE_LANGUAGE ].isEmpty())
815 ( !pResData->sQuickHelpText[ SOURCE_LANGUAGE ].isEmpty())
817 ( !pResData->sTitle[ SOURCE_LANGUAGE ].isEmpty()))
820 OString sGID = pResData->sGId;
821 OString sLID;
822 if (sGID.isEmpty())
823 sGID = pResData->sId;
824 else
825 sLID = pResData->sId;
827 OString sXText;
828 OString sXHText;
829 OString sXQHText;
830 OString sXTitle;
832 sXText = pResData->sText[ SOURCE_LANGUAGE ];
833 if (!pResData->sText[ X_COMMENT ].isEmpty())
834 sXHText = pResData->sText[ X_COMMENT ];
835 else
836 sXHText = pResData->sHelpText[ SOURCE_LANGUAGE ];
837 sXQHText = pResData->sQuickHelpText[ SOURCE_LANGUAGE ];
838 sXTitle = pResData->sTitle[ SOURCE_LANGUAGE ];
840 if( !sXText.isEmpty() )
842 ConvertExportContent(sXText);
843 ConvertExportContent(sXHText);
844 common::writePoEntry(
845 "Transex3", *aOutput.mPo, global::inputPathname,
846 pResData->sResTyp, sGID, sLID, sXHText, sXText);
848 if( !sXQHText.isEmpty() )
850 ConvertExportContent(sXQHText);
851 common::writePoEntry(
852 "Transex3", *aOutput.mPo, global::inputPathname, pResData->sResTyp,
853 sGID, sLID, OString(), sXQHText, PoEntry::TQUICKHELPTEXT );
855 if( !sXTitle.isEmpty() )
857 ConvertExportContent(sXTitle);
858 common::writePoEntry(
859 "Transex3", *aOutput.mPo, global::inputPathname, pResData->sResTyp,
860 sGID, sLID, OString(), sXTitle, PoEntry::TTITLE );
863 if ( bCreateNew ) {
864 pResData->sText[ SOURCE_LANGUAGE ] = "";
865 pResData->sHelpText[ SOURCE_LANGUAGE ] = "";
866 pResData->sQuickHelpText[ SOURCE_LANGUAGE ]= "";
867 pResData->sTitle[ SOURCE_LANGUAGE ] = "";
870 if ( pResData->pStringList ) {
871 OString sList( "stringlist" );
872 WriteExportList( pResData, pResData->pStringList, sList, bCreateNew );
873 if ( bCreateNew )
874 pResData->pStringList = 0;
876 if ( pResData->pFilterList ) {
877 OString sList( "filterlist" );
878 WriteExportList( pResData, pResData->pFilterList, sList, bCreateNew );
879 if ( bCreateNew )
880 pResData->pFilterList = 0;
882 if ( pResData->pItemList ) {
883 OString sList( "itemlist" );
884 WriteExportList( pResData, pResData->pItemList, sList, bCreateNew );
885 if ( bCreateNew )
886 pResData->pItemList = 0;
888 if ( pResData->pPairedList ) {
889 OString sList( "pairedlist" );
890 WriteExportList( pResData, pResData->pPairedList, sList, bCreateNew );
891 if ( bCreateNew )
892 pResData->pPairedList = 0;
894 if ( pResData->pUIEntries ) {
895 OString sList( "uientries" );
896 WriteExportList( pResData, pResData->pUIEntries, sList, bCreateNew );
897 if ( bCreateNew )
898 pResData->pUIEntries = 0;
900 return sal_True;
903 OString Export::GetPairedListID(const OString& rText)
905 // < "STRING" ; IDENTIFIER ; > ;
906 return rText.getToken(1, ';').toAsciiUpperCase().replace('\t', ' ').trim();
909 OString Export::GetPairedListString(const OString& rText)
911 // < "STRING" ; IDENTIFIER ; > ;
912 OString sString(rText.getToken(0, ';').replace('\t', ' '));
913 sString = sString.trim();
914 OString s1(sString.copy(sString.indexOf('"') + 1));
915 sString = s1.copy(0, s1.lastIndexOf('"'));
916 return sString.trim();
919 OString Export::StripList(const OString & rText)
921 OString s1 = rText.copy( rText.indexOf('\"') + 1);
922 return s1.copy( 0 , s1.lastIndexOf('\"'));
925 sal_Bool Export::WriteExportList(ResData *pResData, ExportList *pExportList,
926 const OString &rTyp, sal_Bool bCreateNew)
928 OString sGID(pResData->sGId);
929 if (sGID.isEmpty())
930 sGID = pResData->sId;
931 else {
932 sGID += ".";
933 sGID += pResData->sId;
934 while (sGID.getLength() != 0 && sGID[sGID.getLength() - 1] == '.') {
935 sGID = sGID.copy(0, sGID.getLength() - 1);
939 for ( size_t i = 0; pExportList != NULL && i < pExportList->size(); i++ )
941 ExportListEntry *pEntry = (*pExportList)[ i ];
943 OString sLID;
944 OString sText((*pEntry)[ SOURCE_LANGUAGE ] );
946 // Strip PairList Line String
947 if (rTyp.equalsIgnoreAsciiCase("pairedlist"))
949 sLID = GetPairedListID( sText );
950 sText = GetPairedListString( sText );
952 else
954 sLID = OString::valueOf(static_cast<sal_Int64>(i + 1));
955 sText = StripList( sText );
956 if( sText == "\\\"" )
957 sText = "\"";
959 ConvertExportContent(sText);
960 common::writePoEntry(
961 "Transex3", *aOutput.mPo, global::inputPathname,
962 rTyp, sGID, sLID, OString(), sText);
964 if ( bCreateNew )
965 delete [] pEntry;
967 if ( bCreateNew )
968 delete pExportList;
970 return sal_True;
973 OString Export::FullId()
975 OStringBuffer sFull;
976 if ( nLevel > 1 )
978 sFull.append(aResStack[ 0 ]->sId);
979 for ( size_t i = 1; i < nLevel - 1; ++i )
981 OString sToAdd = aResStack[ i ]->sId;
982 if (!sToAdd.isEmpty())
983 sFull.append('.').append(sToAdd);
986 if (sFull.getLength() > 255)
988 OString sError(RTL_CONSTASCII_STRINGPARAM("GroupId > 255 chars"));
989 printf("GroupID = %s\n", sFull.getStr());
990 yyerror(sError.getStr());
993 return sFull.makeStringAndClear();
996 void Export::InsertListEntry(const OString &rText, const OString &rLine)
998 ResData *pResData = ( nLevel-1 < aResStack.size() ) ? aResStack[ nLevel-1 ] : NULL;
1000 ExportList *pList = NULL;
1001 if ( nList == LIST_STRING ) {
1002 pList = pResData->pStringList;
1003 if ( !pList ) {
1004 pResData->pStringList = new ExportList();
1005 pList = pResData->pStringList;
1006 nListIndex = 0;
1009 else if ( nList == LIST_FILTER ) {
1010 pList = pResData->pFilterList;
1011 if ( !pList ) {
1012 pResData->pFilterList = new ExportList();
1013 pList = pResData->pFilterList;
1014 nListIndex = 0;
1017 else if ( nList == LIST_ITEM ) {
1018 pList = pResData->pItemList;
1019 if ( !pList ) {
1020 pResData->pItemList = new ExportList();
1021 pList = pResData->pItemList;
1022 nListIndex = 0;
1025 else if ( nList == LIST_PAIRED ) {
1026 pList = pResData->pPairedList;
1027 if ( !pList ) {
1028 pResData->pPairedList = new ExportList();
1029 pList = pResData->pPairedList;
1030 nListIndex = 0;
1033 else if ( nList == LIST_UIENTRIES ) {
1034 pList = pResData->pUIEntries;
1035 if ( !pList ) {
1036 pResData->pUIEntries = new ExportList();
1037 pList = pResData->pUIEntries;
1038 nListIndex = 0;
1041 else
1042 return;
1044 if ( nListIndex + 1 > pList->size())
1046 ExportListEntry *pNew = new ExportListEntry();
1047 (*pNew)[LIST_REFID] = OString::number(REFID_NONE);
1048 pList->push_back(pNew);
1050 ExportListEntry *pCurEntry = (*pList)[ nListIndex ];
1052 // For paired list use the line to set proper lid
1053 if( nList == LIST_PAIRED ){
1054 (*pCurEntry)[ m_sListLang ] = rLine;
1055 }else
1056 (*pCurEntry)[ m_sListLang ] = rText;
1058 if ( m_sListLang.equalsIgnoreAsciiCase("en-US") ) {
1059 (*pCurEntry)[ SOURCE_LANGUAGE ] = rLine;
1061 pList->NewSourceLanguageListEntry();
1064 nListIndex++;
1067 void Export::CleanValue( OString &rValue )
1069 while ( !rValue.isEmpty()) {
1070 if (( rValue[0] == ' ' ) || ( rValue[0] == '\t' ))
1071 rValue = rValue.copy( 1 );
1072 else
1073 break;
1076 if ( !rValue.isEmpty()) {
1077 for ( sal_Int32 i = rValue.getLength() - 1; i > 0; i-- ) {
1078 if (( rValue[i] == ' ' ) || ( rValue[i] == '\t' ) ||
1079 ( rValue[i] == '\n' ) || ( rValue[i] == ';' ) ||
1080 ( rValue[i] == '{' ) || ( rValue[i] == '\\' ) ||
1081 ( rValue[i] == '\r' ))
1082 rValue = rValue.copy(0, i);
1083 else
1084 break;
1089 #define TXT_STATE_TEXT 0x001
1090 #define TXT_STATE_MACRO 0x002
1092 OString Export::GetText(const OString &rSource, int nToken)
1094 OString sReturn;
1095 switch ( nToken )
1097 case TEXTLINE:
1098 case LONGTEXTLINE:
1100 OString sTmp(rSource.copy(rSource.indexOf('=')));
1101 CleanValue( sTmp );
1102 sTmp = sTmp.replaceAll("\n", OString()).
1103 replaceAll("\r", OString()).
1104 replaceAll("\\\\\"", "-=<[BSlashBSlashHKom]>=-\"").
1105 replaceAll("\\\"", "-=<[Hochkomma]>=-").
1106 replaceAll("\\\x7f", "-=<[0x7F]>=-").
1107 replaceAll("\\0x7F", "-=<[0x7F]>=-");
1109 sal_uInt16 nState = TXT_STATE_TEXT;
1110 for (sal_Int32 i = 1; i <= lcl_countOccurrences(sTmp, '"'); ++i)
1112 OString sToken(sTmp.getToken(i, '"'));
1113 if (!sToken.isEmpty()) {
1114 if ( nState == TXT_STATE_TEXT ) {
1115 sReturn += sToken;
1116 nState = TXT_STATE_MACRO;
1118 else {
1119 sToken = sToken.replace('\t', ' ');
1120 for (;;) {
1121 sal_Int32 n = 0;
1122 sToken = sToken.replaceFirst(" ", " ", &n);
1123 if (n == -1) {
1124 break;
1127 sToken = sToken.trim();
1128 if (!sToken.isEmpty()) {
1129 sReturn += "\\\" ";
1130 sReturn += sToken;
1131 sReturn += " \\\"";
1133 nState = TXT_STATE_TEXT;
1138 sReturn = sReturn.replaceAll("-=<[0x7F]>=-", "\x7f").
1139 replaceAll("-=<[Hochkomma]>=-", "\"").
1140 replaceAll("-=<[BSlashBSlashHKom]>=-", "\\\\").
1141 replaceAll("\\\\", "-=<[BSlashBSlash]>=-").
1142 replaceAll("-=<[BSlashBSlash]>=-", "\\");
1144 break;
1146 return sReturn;
1149 void Export::WriteToMerged(const OString &rText , bool bSDFContent)
1151 OString sText(rText);
1152 for (;;) {
1153 sal_Int32 n = 0;
1154 sText = sText.replaceFirst(" \n", "\n", &n);
1155 if (n == -1) {
1156 break;
1159 if (pParseQueue->bNextIsM && bSDFContent && sText.getLength() > 2) {
1160 for (sal_Int32 n = 0; n < sText.getLength(); ++n) {
1161 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1162 sText = sText.replaceAt(n++, 0, "\\");
1165 } else if (pParseQueue->bLastWasM && sText.getLength() > 2) {
1166 for (sal_Int32 n = 0; n < sText.getLength(); ++n) {
1167 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1168 sText = sText.replaceAt(n++, 0, "\\");
1170 if (sText[n] == '\n') {
1171 pParseQueue->bMflag = true;
1174 } else if (pParseQueue->bCurrentIsM && bSDFContent && sText.getLength() > 2)
1176 for (sal_Int32 n = 0; n < sText.getLength(); ++n) {
1177 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1178 sText = sText.replaceAt(n++, 0, "\\");
1179 pParseQueue->bMflag = true;
1182 } else if (pParseQueue->bMflag) {
1183 for (sal_Int32 n = 1; n < sText.getLength(); ++n) {
1184 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1185 sText = sText.replaceAt(n++, 0, "\\");
1188 } for (sal_Int32 i = 0; i < sText.getLength(); ++i) {
1189 if (sText[i] == '\n') {
1190 *aOutput.mSimple << '\n';
1191 } else {
1192 char cChar = sText[i];
1193 *aOutput.mSimple << cChar;
1198 void Export::ConvertMergeContent( OString &rText )
1200 rText = rText.replaceAll("\\\'","\'"); // Temporary: until PO files contain escaped single quotes
1201 // (Maybe next PO update solve this)
1202 rText =
1203 helper::escapeAll(
1204 rText.replaceAll("\x7f","\\0x7F"),
1205 "\n""\t""\\""\"","\\n""\\t""\\\\""\\\"");
1207 rText = "\"" + rText + "\"";
1210 void Export::ConvertExportContent( OString& rText )
1212 rText = helper::unEscapeAll(rText,"\\n""\\t""\\\\""\\\"","\n""\t""\\""\"");
1215 bool Export::GetAllMergeEntrysOfList(ResData *pResData, std::vector<MergeEntrys*>& o_vMergeEntrys, ExportList*& o_pList )
1217 o_vMergeEntrys.clear();
1218 o_pList = 0;
1220 if (!pResData->sGId.isEmpty())
1221 pResData->sGId = pResData->sGId + OString('.');
1222 pResData->sGId = pResData->sGId + pResData->sId;
1224 // Find out the type of List
1225 MergeEntrys* pEntrysOfFirstItem = 0;
1226 sal_uInt16 nType = LIST_STRING;
1227 bool bPairedList = false;
1228 while( !pEntrysOfFirstItem && nType <= LIST_UIENTRIES )
1230 switch ( nType )
1232 case LIST_STRING : pResData->sResTyp = "stringlist"; o_pList = pResData->pStringList; bPairedList = false; break;
1233 case LIST_FILTER : pResData->sResTyp = "filterlist"; o_pList = pResData->pFilterList; bPairedList = false; break;
1234 case LIST_UIENTRIES : pResData->sResTyp = "uientries"; o_pList = pResData->pUIEntries;bPairedList = false; break;
1235 case LIST_ITEM : pResData->sResTyp = "itemlist"; o_pList = pResData->pItemList; bPairedList = false; break;
1236 case LIST_PAIRED : pResData->sResTyp = "pairedlist"; o_pList = pResData->pPairedList; bPairedList = true; break;
1239 // Set matching pairedlist identifier
1240 if( bPairedList && pResData->pPairedList )
1242 ExportListEntry* pListE = ( ExportListEntry* ) (*pResData->pPairedList)[ 0 ];
1243 pResData->sId = GetPairedListID ( (*pListE)[ SOURCE_LANGUAGE ] );
1245 else
1246 pResData->sId = "1";
1248 pEntrysOfFirstItem = pMergeDataFile->GetMergeEntrys( pResData );
1249 ++nType;
1252 if( !pEntrysOfFirstItem )
1254 o_pList = 0;
1255 return false;
1257 else
1258 nList = nType-1;
1260 sal_uInt16 nMaxIndex = 0;
1261 if ( o_pList )
1263 nMaxIndex = o_pList->GetSourceLanguageListEntryCount();
1266 * Check whether count of listentries match with count
1267 * of translated items. If not than write origin items
1268 * to the list to avoid mixed translations
1269 * (exclude pairedlist)
1271 if( !bPairedList )
1273 MergeEntrys* pEntrys;
1274 // MergeData contains longer list
1275 pResData->sId = OString::number(nMaxIndex+1);
1276 pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
1277 if ( pEntrys )
1278 return false;
1279 // MergeData contains shorter list
1280 pResData->sId = OString::number(nMaxIndex);
1281 pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
1282 if ( !pEntrys )
1283 return false;
1284 pResData->sId = "1";
1287 o_vMergeEntrys.push_back(pEntrysOfFirstItem);
1289 for( sal_uInt16 nLIndex = 2; nLIndex <= nMaxIndex; ++nLIndex )
1291 // Set matching pairedlist identifier
1292 if ( bPairedList )
1294 ExportListEntry* pListE = ( ExportListEntry* )(*pResData->pPairedList)[ ( nLIndex ) -1 ];
1295 if( pListE )
1297 pResData->sId = GetPairedListID ( (*pListE)[ SOURCE_LANGUAGE ] );
1300 else
1301 pResData->sId = OString::number(nLIndex);
1303 MergeEntrys* pEntrys = pMergeDataFile->GetMergeEntrys( pResData );
1304 if( pEntrys )
1306 o_vMergeEntrys.push_back(pEntrys);
1309 return true;
1312 void Export::ResData2Output( MergeEntrys *pEntry, sal_uInt16 nType, const OString& rTextType )
1314 sal_Bool bAddSemicolon = sal_False;
1315 sal_Bool bFirst = sal_True;
1316 OString sCur;
1318 for( unsigned int n = 0; n < aLanguages.size(); n++ ){
1319 sCur = aLanguages[ n ];
1321 OString sText;
1322 sal_Bool bText = pEntry->GetText( sText, nType, sCur , sal_True );
1323 if ( bText && !sText.isEmpty() ) {
1324 OString sOutput;
1325 if ( bNextMustBeDefineEOL) {
1326 if ( bFirst )
1327 sOutput += "\t\\\n";
1328 else
1329 sOutput += ";\t\\\n";
1331 bFirst=sal_False;
1332 sOutput += "\t";
1334 sOutput += rTextType;
1336 if ( !sCur.equalsIgnoreAsciiCase("en-US") ) {
1337 sOutput += "[ ";
1338 sOutput += sCur;
1339 sOutput += " ] ";
1341 sOutput += "= ";
1342 ConvertMergeContent( sText );
1343 sOutput += sText;
1345 if ( bDefine )
1346 sOutput += ";\\\n";
1347 else if ( !bNextMustBeDefineEOL )
1348 sOutput += ";\n";
1349 else
1350 bAddSemicolon = sal_True;
1351 for ( sal_uInt16 j = 1; j < nLevel; j++ )
1352 sOutput += "\t";
1353 WriteToMerged( sOutput , true );
1358 if ( bAddSemicolon ) {
1359 OString sOutput( ";" );
1360 WriteToMerged( sOutput , false );
1364 void Export::MergeRest( ResData *pResData, sal_uInt16 nMode )
1366 if ( !pMergeDataFile ){
1367 pMergeDataFile = new MergeDataFile( sMergeSrc, global::inputPathname, false );
1368 aLanguages = pMergeDataFile->GetLanguages();
1371 switch ( nMode ) {
1372 case MERGE_MODE_NORMAL : {
1373 MergeEntrys *pEntry = 0;
1374 if( pResData->bText || pResData->bQuickHelpText || pResData->bTitle )
1375 pEntry = pMergeDataFile->GetMergeEntrys( pResData );
1377 if ( pEntry ) {
1378 if ( pResData->bText )
1379 ResData2Output( pEntry, STRING_TYP_TEXT, pResData->sTextTyp );
1381 if ( pResData->bQuickHelpText )
1382 ResData2Output( pEntry, STRING_TYP_QUICKHELPTEXT, OString("QuickHelpText") );
1384 if ( pResData->bTitle )
1385 ResData2Output( pEntry, STRING_TYP_TITLE, OString("Title") );
1388 // Merge Lists
1390 if ( pResData->bList ) {
1391 OString sOldId = pResData->sId;
1392 OString sOldGId = pResData->sGId;
1393 OString sOldTyp = pResData->sResTyp;
1394 sal_uInt16 nOldListTyp = nList;
1396 OString sSpace;
1397 for ( sal_uInt16 i = 1; i < nLevel-1; i++ )
1398 sSpace += "\t";
1400 std::vector<MergeEntrys*> vMergeEntryVector;
1401 ExportList* pList = 0;
1402 bool bTranslateList = GetAllMergeEntrysOfList(pResData, vMergeEntryVector, pList);
1404 if( pList )
1406 OString sCur;
1407 for( unsigned int n = 0; n < aLanguages.size(); n++ )
1409 sCur = aLanguages[ n ];
1411 sal_uInt16 nLIndex = 0;
1412 sal_uInt16 nMaxIndex = pList->GetSourceLanguageListEntryCount();
1413 while( nLIndex < nMaxIndex )
1415 if ( nLIndex == 0 )
1417 OStringBuffer sHead;
1418 if ( bNextMustBeDefineEOL )
1419 sHead.append("\\\n\t");
1420 sHead.append(sSpace);
1421 switch ( nList )
1423 case LIST_STRING:
1424 sHead.append("StringList ");
1425 break;
1426 case LIST_FILTER:
1427 sHead.append("FilterList ");
1428 break;
1429 case LIST_ITEM:
1430 sHead.append("ItemList ");
1431 break;
1432 case LIST_PAIRED:
1433 sHead.append("PairedList ");
1434 break;
1435 case LIST_UIENTRIES:
1436 sHead.append("UIEntries ");
1437 break;
1439 sHead.append("[ ");
1440 sHead.append(sCur);
1441 sHead.append(" ] ");
1442 if ( bDefine || bNextMustBeDefineEOL )
1444 sHead.append("= \\\n");
1445 sHead.append(sSpace);
1446 sHead.append("\t{\\\n\t");
1448 else
1450 sHead.append("= \n");
1451 sHead.append(sSpace);
1452 sHead.append("\t{\n\t");
1454 WriteToMerged(sHead.makeStringAndClear() , true);
1456 OString sLine;
1457 if ( pList && (*pList)[ nLIndex ] )
1458 sLine = ( *(*pList)[ nLIndex ])[ SOURCE_LANGUAGE ];
1460 if ( sLine.indexOf( '>' ) != -1 ) {
1461 if (( nList != LIST_UIENTRIES ) &&
1462 (( sLine.indexOf( '{' ) == -1 ) ||
1463 ( sLine.indexOf( '{' ) >= sLine.indexOf( '"' ))) &&
1464 (( sLine.indexOf( '<' ) == -1 ) ||
1465 ( sLine.indexOf( '<' ) >= sLine.indexOf( '"' ))))
1467 sLine = sLine.replaceFirst("\"", "< \"" );
1471 if( bTranslateList && nLIndex < vMergeEntryVector.size() )
1473 OString sText;
1474 sal_Bool bText;
1475 bText = vMergeEntryVector[nLIndex]->GetText( sText, STRING_TYP_TEXT, sCur, sal_True );
1476 if ( bText && !sText.isEmpty() )
1478 ConvertMergeContent( sText );
1479 OString sPre = sLine.copy( 0 , sLine.indexOf('"') );
1480 OString sPost = sLine.copy( sLine.lastIndexOf('"') + 1 );
1481 sLine = sPre + sText + sPost;
1485 OString sText1( "\t" );
1486 sText1 += sLine;
1487 if ( bDefine || bNextMustBeDefineEOL )
1488 sText1 += " ;\\\n";
1489 else
1490 sText1 += " ;\n";
1491 sText1 += sSpace;
1492 sText1 += "\t";
1493 WriteToMerged( sText1 ,true );
1494 ++nLIndex;
1496 if ( nLIndex > 0 ) {
1497 OString sFooter;
1498 if (!sSpace.isEmpty()) {
1499 sFooter = sSpace.copy(1);
1501 if ( bNextMustBeDefineEOL )
1502 sFooter += "};";
1503 else if ( !bDefine )
1504 sFooter += "};\n\t";
1505 else
1506 sFooter += "\n\n";
1507 WriteToMerged( sFooter ,true );
1512 pResData->sId = sOldId;
1513 pResData->sGId = sOldGId;
1514 pResData->sResTyp = sOldTyp;
1515 nList = nOldListTyp;
1518 break;
1519 case MERGE_MODE_LIST : {
1521 break;
1523 pParseQueue->bMflag = false;
1526 void Export::SetChildWithText()
1528 if ( aResStack.size() > 1 ) {
1529 for ( size_t i = 0; i < aResStack.size() - 1; i++ ) {
1530 aResStack[ i ]->bChildWithText = sal_True;
1535 void ParserQueue::Push( const QueueEntry& aEntry )
1537 sal_Int32 nLen = aEntry.sLine.getLength();
1539 if( !bStart ){
1540 aQueueCur->push( aEntry );
1541 if( nLen > 1 && aEntry.sLine[nLen-1] == '\n' )
1542 bStart = true;
1543 else if ( aEntry.nTyp != IGNOREDTOKENS ){
1544 if( nLen > 1 && ( aEntry.sLine[nLen-1] == '\\') ){
1545 // Next is Macro
1546 bCurrentIsM = true;
1547 }else{
1548 // Next is no Macro
1549 bCurrentIsM = false;
1553 else{
1554 aQueueNext->push( aEntry );
1555 if( nLen > 1 && aEntry.sLine[nLen-1] != '\n' ){
1556 if( nLen > 1 && ( aEntry.sLine[nLen-1] == '\\') ){
1557 // Next is Macro
1558 bNextIsM = true;
1560 else{
1561 // Next is no Macro
1562 bNextIsM = false;
1564 }else if( nLen > 2 && aEntry.sLine[nLen-1] == '\n' ){
1565 if( aEntry.nTyp != IGNOREDTOKENS ){
1566 if( nLen > 2 && ( aEntry.sLine[nLen-2] == '\\') ){
1567 // Next is Macro
1568 bNextIsM = true;
1570 else{
1571 // Next is no Macro
1572 bNextIsM = false;
1575 // Pop current
1576 Pop( *aQueueCur );
1577 bLastWasM = bCurrentIsM;
1578 // next -> current
1579 bCurrentIsM = bNextIsM;
1580 aQref = aQueueCur;
1581 aQueueCur = aQueueNext;
1582 aQueueNext = aQref;
1586 else{
1587 // Pop current
1588 Pop( *aQueueCur );
1589 bLastWasM = bCurrentIsM;
1590 // next -> current
1591 bCurrentIsM = bNextIsM;
1592 aQref = aQueueCur;
1593 aQueueCur = aQueueNext;
1594 aQueueNext = aQref;
1599 void ParserQueue::Close(){
1600 // Pop current
1601 Pop( *aQueueCur );
1602 // next -> current
1603 bLastWasM = bCurrentIsM;
1604 bCurrentIsM = bNextIsM;
1605 aQref = aQueueCur;
1606 aQueueCur = aQueueNext;
1607 aQueueNext = aQref;
1608 bNextIsM = false;
1609 Pop( *aQueueNext );
1612 void ParserQueue::Pop( std::queue<QueueEntry>& aQueue )
1614 while (!aQueue.empty())
1616 QueueEntry aEntry = aQueue.front();
1617 aQueue.pop();
1618 aExport.Execute(aEntry.nTyp, aEntry.sLine.getStr());
1622 ParserQueue::ParserQueue( Export& aExportObj )
1624 bCurrentIsM( false ),
1625 bNextIsM( false ) ,
1626 bLastWasM( false ),
1627 bMflag( false ) ,
1628 aExport( aExportObj ) ,
1629 bStart( false )
1631 aQueueNext = new std::queue<QueueEntry>;
1632 aQueueCur = new std::queue<QueueEntry>;
1636 ParserQueue::~ParserQueue(){
1637 if( aQueueNext ) delete aQueueNext;
1638 if( aQueueCur ) delete aQueueCur;
1641 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */