Bump for 3.6-28
[LibreOffice.git] / l10ntools / source / export.cxx
blob39808360033496723adefad87527bf8248dead46
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "sal/config.h"
31 #include <cstddef>
32 #include <cstring>
34 #include "boost/scoped_ptr.hpp"
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include "common.hxx"
38 #include "export.hxx"
39 #include "helper.hxx"
40 #include "tokens.h"
41 #include <iostream>
42 #include <rtl/strbuf.hxx>
44 void yyerror( const char * );
45 void YYWarning( const char * );
47 namespace {
49 rtl::OString sActFileName; //TODO
50 MergeDataFile * pMergeDataFile = 0; //TODO
52 namespace global {
54 bool mergeMode = false;
55 bool errorLog = true;
56 char const * prj = 0;
57 char const * prjRoot = 0;
58 char const * inputPathname = 0;
59 char const * outputPathname = 0;
60 char const * mergeSrc;
61 boost::scoped_ptr< Export > exporter;
65 void handleArguments(int argc, char ** argv) {
66 for (int i = 1; i != argc; ++i) {
67 if (std::strcmp(argv[i], "-e") == 0) {
68 global::errorLog = false;
69 } else if (std::strcmp(argv[i], "-i") == 0) {
70 if (++i == argc) {
71 global::inputPathname = 0; // no valid command line
72 break;
74 global::inputPathname = argv[i];
75 } else if (std::strcmp(argv[i], "-l") == 0) {
76 if (++i == argc) {
77 global::inputPathname = 0; // no valid command line
78 break;
80 Export::sLanguages = argv[i];
81 } else if (std::strcmp(argv[i], "-m") == 0) {
82 if (++i == argc) {
83 global::inputPathname = 0; // no valid command line
84 break;
86 global::mergeSrc = argv[i];
87 global::mergeMode = true;
88 } else if (std::strcmp(argv[i], "-o") == 0) {
89 if (++i == argc) {
90 global::inputPathname = 0; // no valid command line
91 break;
93 global::outputPathname = argv[i];
94 } else if (std::strcmp(argv[i], "-p") == 0) {
95 if (++i == argc) {
96 global::inputPathname = 0; // no valid command line
97 break;
99 global::prj = argv[i];
100 } else if (std::strcmp(argv[i], "-r") == 0) {
101 if (++i == argc) {
102 global::inputPathname = 0; // no valid command line
103 break;
105 global::prjRoot = argv[i];
106 } else {
107 global::inputPathname = 0; // no valid command line
108 break;
111 if (global::inputPathname == 0 || global::outputPathname == 0) {
112 std::fprintf(
113 stderr,
114 ("Syntax: transex3 [-p Prj] [-r PrjRoot] -i FileIn -o FileOut"
115 " [-m DataBase] [-e] [-l l1,l2,...]\n"
116 " Prj: Project\n"
117 " PrjRoot: Path to project root (../.. etc.)\n"
118 " FileIn: Source files (*.src)\n"
119 " FileOut: Destination file (*.*)\n"
120 " DataBase: Mergedata (*.sdf)\n"
121 " -e: Disable writing errorlog\n"
122 " -l: Restrict the handled languages; l1, l2, ... are elements of"
123 " (de, en-US, ...)\n"));
124 std::exit(EXIT_FAILURE);
126 Export::InitLanguages();
131 extern "C" {
133 FILE * init(int argc, char ** argv) {
134 handleArguments(argc, argv);
136 FILE * pFile = std::fopen(global::inputPathname, "r");
137 if (pFile == 0) {
138 std::fprintf(
139 stderr, "Error: Cannot open file \"%s\"\n",
140 global::inputPathname);
141 std::exit(EXIT_FAILURE);
144 if (global::mergeMode) {
145 global::exporter.reset(
146 new Export(global::mergeSrc, global::outputPathname));
147 } else {
148 sActFileName =
149 common::pathnameToken(global::inputPathname, global::prjRoot);
150 global::exporter.reset(new Export(global::outputPathname));
153 global::exporter->Init();
155 return pFile;
158 int Parse( int nTyp, const char *pTokenText ){
159 global::exporter->Execute( nTyp , pTokenText );
160 return 1;
162 void Close(){
163 global::exporter->pParseQueue->Close();
164 global::exporter.reset();
165 // avoid nontrivial Export dtor being executed during exit
168 int WorkOnTokenSet( int nTyp, char *pTokenText )
171 global::exporter->pParseQueue->Push( QueueEntry( nTyp , rtl::OString(pTokenText) ) );
172 return 1;
175 } // extern
177 extern "C" {
178 /*****************************************************************************/
179 int SetError()
180 /*****************************************************************************/
182 // set error at global instance of class Export
183 global::exporter->SetError();
184 return 1;
188 extern "C" {
189 /*****************************************************************************/
190 int GetError()
191 /*****************************************************************************/
193 // get error at global instance of class Export
194 if (global::exporter->GetError())
195 return 1;
196 return sal_False;
201 // class ResData
204 /*****************************************************************************/
205 sal_Bool ResData::SetId( const rtl::OString& rId, sal_uInt16 nLevel )
206 /*****************************************************************************/
208 if ( nLevel > nIdLevel )
210 nIdLevel = nLevel;
211 sId = rId;
213 if ( bChild && bChildWithText )
215 rtl::OString sError(RTL_CONSTASCII_STRINGPARAM("ResId after child definition"));
216 yyerror(sError.getStr());
217 SetError();
220 if ( sId.getLength() > 255 )
222 YYWarning( "LocalId > 255 chars, truncating..." );
223 sId = sId.copy(0, 255).trim();
226 return sal_True;
229 return sal_False;
233 // class Export
236 Export::Export(const rtl::OString &rOutput)
238 pWordTransformer( NULL ),
239 bDefine( sal_False ),
240 bNextMustBeDefineEOL( sal_False ),
241 nLevel( 0 ),
242 nList( LIST_NON ),
243 nListIndex( 0 ),
244 nListLevel( 0 ),
245 bSkipFile( false ),
246 sProject( global::prj ),
247 sRoot( global::prjRoot ),
248 bMergeMode( false ),
249 bError( sal_False ),
250 bReadOver( sal_False ),
251 bDontWriteOutput( sal_False ),
252 sFilename( global::inputPathname )
254 pParseQueue = new ParserQueue( *this );
256 if( !isInitialized ) InitLanguages();
257 // used when export is enabled
259 // open output stream
260 aOutput.open(rOutput.getStr(), std::ios_base::out | std::ios_base::trunc);
261 if (!aOutput.is_open()) {
262 fprintf(stderr, "ERROR : Can't open file %s\n", rOutput.getStr());
263 exit ( -1 );
267 Export::Export(const rtl::OString &rMergeSource, const rtl::OString &rOutput)
269 pWordTransformer( NULL ),
270 bDefine( sal_False ),
271 bNextMustBeDefineEOL( sal_False ),
272 nLevel( 0 ),
273 nList( LIST_NON ),
274 nListIndex( 0 ),
275 nListLevel( 0 ),
276 bSkipFile( false ),
277 sProject( global::prj ),
278 sRoot( global::prjRoot ),
279 bMergeMode( sal_True ),
280 sMergeSrc( rMergeSource ),
281 bError( sal_False ),
282 bReadOver( sal_False ),
283 bDontWriteOutput( sal_False ),
284 sFilename( global::inputPathname )
286 pParseQueue = new ParserQueue( *this );
287 if( !isInitialized ) InitLanguages( bMergeMode );
288 // used when merge is enabled
290 // open output stream
291 aOutput.open(rOutput.getStr(), std::ios_base::out | std::ios_base::trunc);
294 /*****************************************************************************/
295 void Export::Init()
296 /*****************************************************************************/
298 // resets the internal status, used before parseing another file
299 sActPForm = "";
300 bDefine = sal_False;
301 bNextMustBeDefineEOL = sal_False;
302 nLevel = 0;
303 nList = LIST_NON;
304 m_sListLang = rtl::OString();
305 nListIndex = 0;
306 for ( size_t i = 0, n = aResStack.size(); i < n; ++i )
307 delete aResStack[ i ];
308 aResStack.clear();
311 /*****************************************************************************/
312 Export::~Export()
313 /*****************************************************************************/
315 if( pParseQueue )
316 delete pParseQueue;
317 aOutput.close();
318 for ( size_t i = 0, n = aResStack.size(); i < n; ++i )
319 delete aResStack[ i ];
320 aResStack.clear();
322 if ( bMergeMode ) {
323 if ( !pMergeDataFile )
324 pMergeDataFile = new MergeDataFile(sMergeSrc, global::inputPathname, global::errorLog);
326 delete pMergeDataFile;
330 /*****************************************************************************/
331 int Export::Execute( int nToken, const char * pToken )
332 /*****************************************************************************/
335 rtl::OString sToken( pToken );
336 rtl::OString sOrig( sToken );
337 sal_Bool bWriteToMerged = bMergeMode;
339 if ( nToken == CONDITION )
341 rtl::OString sTestToken(pToken);
342 sTestToken = sTestToken.replaceAll("\t", rtl::OString()).
343 replaceAll(" ", rtl::OString());
344 if (( !bReadOver ) && ( sTestToken.indexOf("#ifndef__RSC_PARSER") == 0 ))
345 bReadOver = sal_True;
346 else if (( bReadOver ) && ( sTestToken.indexOf("#endif") == 0 ))
347 bReadOver = sal_False;
349 if ((( nToken < FILTER_LEVEL ) || ( bReadOver )) &&
350 (!(( bNextMustBeDefineEOL ) && ( sOrig == "\n" )))) {
351 // this tokens are not mandatory for parsing, so ignore them ...
352 if ( bMergeMode )
353 WriteToMerged( sOrig , false ); // ... ore whrite them directly to dest.
354 return 0;
357 ResData *pResData = NULL;
358 if ( nLevel ) {
359 // res. exists at cur. level
360 pResData = ( (nLevel-1) < aResStack.size() ) ? aResStack[ nLevel-1 ] : NULL;
362 else if (( nToken != RESSOURCE ) &&
363 ( nToken != RESSOURCEEXPR ) &&
364 ( nToken != SMALRESSOURCE ) &&
365 ( nToken != LEVELUP ) &&
366 ( nToken != NORMDEFINE ) &&
367 ( nToken != RSCDEFINE ) &&
368 ( nToken != CONDITION ) &&
369 ( nToken != PRAGMA ))
371 // no res. exists at cur. level so return
372 if ( bMergeMode )
373 WriteToMerged( sOrig , false );
374 return 0;
376 // #define NO_LOCALIZE_EXPORT
377 if( bSkipFile ){
378 if ( bMergeMode ) {
379 WriteToMerged( sOrig , false );
381 return 1;
385 if ( bDefine ) {
386 if (( nToken != EMPTYLINE ) && ( nToken != LEVELDOWN ) && ( nToken != LEVELUP )) {
387 // cur. res. defined in macro
388 if ( bNextMustBeDefineEOL ) {
389 if ( nToken != RSCDEFINELEND ) {
390 // end of macro found, so destroy res.
391 bDefine = sal_False;
392 if ( bMergeMode ) {
393 MergeRest( pResData );
395 bNextMustBeDefineEOL = sal_False;
396 Execute( LEVELDOWN, "" );
398 else {
399 // next line also in macro definition
400 bNextMustBeDefineEOL = sal_False;
401 if ( bMergeMode )
402 WriteToMerged( sOrig , false );
403 return 1;
409 sal_Bool bExecuteDown = sal_False;
410 if ( nToken != LEVELDOWN ) {
411 sal_uInt16 nOpen = 0;
412 sal_uInt16 nClose = 0;
413 sal_Bool bReadOver1 = sal_False;
414 sal_uInt16 i = 0;
415 for ( i = 0; i < sToken.getLength(); i++ ) {
416 if ( sToken[i] == '"' )
417 bReadOver1 = !bReadOver1;
418 if ( !bReadOver1 && ( sToken[i] == '{' ))
419 nOpen++;
422 bReadOver1 = sal_False;
423 for ( i = 0; i < sToken.getLength(); i++ ) {
424 if ( sToken[i] == '"' )
425 bReadOver1 = !bReadOver1;
426 if ( !bReadOver1 && ( sToken[i] == '}' ))
427 nClose++;
430 if ( nOpen < nClose )
431 bExecuteDown = sal_True;
433 switch ( nToken ) {
435 case NORMDEFINE:
436 sToken = sToken.replace('\r', ' ').replace('\t', ' ');
437 for (;;) {
438 sal_Int32 n = 0;
439 sToken = sToken.replaceFirst(" ", " ", &n);
440 if (n == -1) {
441 break;
444 if( sToken.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("#define NO_LOCALIZE_EXPORT")) ){
445 bSkipFile = true;
446 return 0;
448 if ( bMergeMode )
449 WriteToMerged( sOrig , false );
451 return 0;
454 case RSCDEFINE:
455 bDefine = sal_True; // res. defined in macro
457 case RESSOURCE:
458 case RESSOURCEEXPR: {
459 bDontWriteOutput = sal_False;
460 if ( nToken != RSCDEFINE )
461 bNextMustBeDefineEOL = sal_False;
462 // this is the beginning of a new res.
463 nLevel++;
464 if ( nLevel > 1 ) {
465 aResStack[ nLevel - 2 ]->bChild = sal_True;
468 // create new instance for this res. and fill mandatory fields
470 pResData = new ResData( sActPForm, FullId() , sFilename );
471 aResStack.push_back( pResData );
472 sToken = sToken.replaceAll("\n", rtl::OString()).
473 replaceAll("\r", rtl::OString()).
474 replaceAll("{", rtl::OString()).replace('\t', ' ');
475 sToken = sToken.trim();
476 rtl::OString sTLower = sToken.getToken(0, ' ').toAsciiLowerCase();
477 pResData->sResTyp = sTLower;
478 rtl::OString sId( sToken.copy( pResData->sResTyp.getLength() + 1 ));
479 rtl::OString sCondition;
480 if ( sId.indexOf( '#' ) != -1 )
482 // between ResTyp, Id and paranthes is a precomp. condition
483 sCondition = "#";
484 sal_Int32 n = 0;
485 sId = sId.getToken(0, '#', n);
486 sCondition += sId.getToken(0, '#', n);
488 sId = sId.getToken(0, '/');
489 CleanValue( sId );
490 sId = sId.replaceAll("\t", rtl::OString());
491 pResData->SetId( sId, ID_LEVEL_IDENTIFIER );
492 if (!sCondition.isEmpty())
494 Execute( CONDITION, ""); // execute the precomp. condition
497 break;
498 case SMALRESSOURCE: {
499 bDontWriteOutput = sal_False;
500 // this is the beginning of a new res.
501 bNextMustBeDefineEOL = sal_False;
502 nLevel++;
503 if ( nLevel > 1 ) {
504 aResStack[ nLevel - 2 ]->bChild = sal_True;
507 // create new instance for this res. and fill mandatory fields
509 pResData = new ResData( sActPForm, FullId() , sFilename );
510 aResStack.push_back( pResData );
511 sToken = sToken.replaceAll("\n", rtl::OString()).
512 replaceAll("\r", rtl::OString()).
513 replaceAll("{", rtl::OString()).
514 replaceAll("\t", rtl::OString()).
515 replaceAll(" ", rtl::OString()).
516 replaceAll("\\", rtl::OString()).toAsciiLowerCase();
517 pResData->sResTyp = sToken;
519 break;
520 case LEVELUP: {
521 // push
522 if ( nList )
523 nListLevel++;
524 if ( nList )
525 break;
527 bDontWriteOutput = sal_False;
528 rtl::OString sLowerTyp;
529 if ( pResData )
530 sLowerTyp = "unknown";
531 nLevel++;
532 if ( nLevel > 1 ) {
533 aResStack[ nLevel - 2 ]->bChild = sal_True;
536 ResData *pNewData = new ResData( sActPForm, FullId() , sFilename );
537 pNewData->sResTyp = sLowerTyp;
538 aResStack.push_back( pNewData );
540 break;
541 case LEVELDOWN: {
542 // pop
543 if ( !nList ) {
544 bDontWriteOutput = sal_False;
545 if ( nLevel ) {
546 if ( bDefine && (nLevel == 1 )) {
547 bDefine = sal_False;
548 bNextMustBeDefineEOL = sal_False;
550 WriteData( pResData );
551 ResStack::iterator it = aResStack.begin();
552 ::std::advance( it, nLevel-1 );
553 delete *it;
554 aResStack.erase( it );
555 nLevel--;
558 else {
559 if ( bDefine )
560 bNextMustBeDefineEOL = sal_True;
561 if ( !nListLevel ) {
562 if ( bMergeMode )
563 MergeRest( pResData, MERGE_MODE_LIST );
564 nList = LIST_NON;
566 else
567 nListLevel--;
570 break;
571 case ASSIGNMENT:
573 bDontWriteOutput = sal_False;
574 // interpret different types of assignement
575 sal_Int32 n = 0;
576 rtl::OString sKey = sToken.getToken(0, '=', n).
577 replaceAll(" ", rtl::OString()).
578 replaceAll("\t", rtl::OString());
579 rtl::OString sValue = sToken.getToken(0, '=', n);
580 CleanValue( sValue );
581 sKey = sKey.toAsciiUpperCase();
582 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("IDENTIFIER")))
584 rtl::OString sId(
585 sValue.replaceAll("\t", rtl::OString()).
586 replaceAll(" ", rtl::OString()));
587 pResData->SetId(sId, ID_LEVEL_IDENTIFIER);
589 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("HELPID")))
591 pResData->sHelpId = sValue;
593 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("STRINGLIST")))
595 pResData->bList = sal_True;
596 nList = LIST_STRING;
597 m_sListLang = SOURCE_LANGUAGE;
598 nListIndex = 0;
599 nListLevel = 0;
601 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("FILTERLIST")))
603 pResData->bList = sal_True;
604 nList = LIST_FILTER;
605 m_sListLang = SOURCE_LANGUAGE;
606 nListIndex = 0;
607 nListLevel = 0;
609 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UIENTRIES")))
611 pResData->bList = sal_True;
612 nList = LIST_UIENTRIES;
613 m_sListLang = SOURCE_LANGUAGE;
614 nListIndex = 0;
615 nListLevel = 0;
617 if (sToken.indexOf( '{' ) != -1
618 && (helper::countOccurrences(sToken, '{')
619 > helper::countOccurrences(sToken, '}')))
621 Parse( LEVELUP, "" );
624 break;
625 case UIENTRIES:
626 case LISTASSIGNMENT:
628 bDontWriteOutput = sal_False;
629 rtl::OString sTmpToken(
630 sToken.replaceAll(" ", rtl::OString()).toAsciiLowerCase());
631 sal_Int32 nPos = sTmpToken.indexOf("[en-us]=");
632 if (nPos != -1) {
633 rtl::OString sKey(
634 sTmpToken.copy(0 , nPos).replaceAll(" ", rtl::OString()).
635 replaceAll("\t", rtl::OString()));
636 rtl::OString sValue = sToken.getToken(1, '=');
637 CleanValue( sValue );
638 sKey = sKey.toAsciiUpperCase();
639 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("STRINGLIST")))
641 pResData->bList = sal_True;
642 nList = LIST_STRING;
643 m_sListLang = SOURCE_LANGUAGE;
644 nListIndex = 0;
645 nListLevel = 0;
647 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("FILTERLIST")))
649 pResData->bList = sal_True;
650 nList = LIST_FILTER;
651 m_sListLang = SOURCE_LANGUAGE;
652 nListIndex = 0;
653 nListLevel = 0;
655 // PairedList
656 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("PAIREDLIST")))
658 pResData->bList = sal_True;
659 nList = LIST_PAIRED;
660 m_sListLang = SOURCE_LANGUAGE;
661 nListIndex = 0;
662 nListLevel = 0;
664 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("ITEMLIST")))
666 pResData->bList = sal_True;
667 nList = LIST_ITEM;
668 m_sListLang = SOURCE_LANGUAGE;
669 nListIndex = 0;
670 nListLevel = 0;
672 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UIENTRIES")))
674 pResData->bList = sal_True;
675 nList = LIST_UIENTRIES;
676 m_sListLang = SOURCE_LANGUAGE;
677 nListIndex = 0;
678 nListLevel = 0;
681 else
683 // new res. is a String- or FilterList
684 sal_Int32 n = 0;
685 rtl::OString sKey(
686 sToken.getToken(0, '[', n).replaceAll(" ", rtl::OString()).
687 replaceAll("\t", rtl::OString()).toAsciiUpperCase());
688 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("STRINGLIST")))
689 nList = LIST_STRING;
690 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("FILTERLIST")))
691 nList = LIST_FILTER;
692 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("PAIREDLIST")))
693 nList = LIST_PAIRED; // abcd
694 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("ITEMLIST")))
695 nList = LIST_ITEM;
696 else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UIENTRIES")))
697 nList = LIST_UIENTRIES;
698 if ( nList ) {
699 rtl::OString sLang = sToken.getToken(0, ']', n);
700 CleanValue( sLang );
701 m_sListLang = sLang;
702 nListIndex = 0;
703 nListLevel = 0;
707 break;
708 case TEXT:
709 case _LISTTEXT:
710 case LISTTEXT: {
711 // this is an entry for a String- or FilterList
712 if ( nList ) {
713 SetChildWithText();
714 sal_Int32 n = 0;
715 rtl::OString sEntry(sToken.getToken(1, '"', n));
716 if ( helper::countOccurrences(sToken, '"') > 2 )
717 sEntry += "\"";
718 if ( sEntry == "\\\"" )
719 sEntry = "\"";
720 InsertListEntry( sEntry, sOrig );
721 if ( bMergeMode && ( sEntry != "\"" ))
723 PrepareTextToMerge( sOrig, nList, m_sListLang, pResData );
727 break;
728 case LONGTEXTLINE:
729 case TEXTLINE:
730 bDontWriteOutput = sal_False;
731 if ( nLevel )
733 CutComment( sToken );
735 // this is a text line!!!
736 rtl::OString t(sToken.getToken(0, '='));
737 rtl::OString sKey(
738 t.getToken(0, '[').replaceAll(" ", rtl::OString()).
739 replaceAll("\t", rtl::OString()));
740 rtl::OString sText( GetText( sToken, nToken ));
741 rtl::OString sLang;
742 if ( sToken.getToken(0, '=').indexOf('[') != -1 )
744 sLang = sToken.getToken(0, '=').getToken(1, '[').
745 getToken(0, ']');
746 CleanValue( sLang );
748 rtl::OString sLangIndex = sLang;
749 rtl::OString sOrigKey = sKey;
750 if ( !sText.isEmpty() && !sLang.isEmpty() )
752 sKey = sKey.toAsciiUpperCase();
753 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("TEXT")) ||
754 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("MESSAGE")) ||
755 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("CUSTOMUNITTEXT")) ||
756 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("SLOTNAME")) ||
757 sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("UINAME")))
759 SetChildWithText();
760 if ( Export::isSourceLanguage( sLangIndex ) )
761 pResData->SetId( sText, ID_LEVEL_TEXT );
763 pResData->bText = sal_True;
764 pResData->sTextTyp = sOrigKey;
765 if ( bMergeMode ) {
766 PrepareTextToMerge( sOrig, STRING_TYP_TEXT, sLangIndex, pResData );
768 else
770 if (!pResData->sText[ sLangIndex ].isEmpty())
772 rtl::OStringBuffer sError(RTL_CONSTASCII_STRINGPARAM("Language "));
773 sError.append(sLangIndex);
774 sError.append(RTL_CONSTASCII_STRINGPARAM("defined twice"));
775 yyerror(sError.getStr());
777 pResData->sText[ sLangIndex ] = sText;
780 else if ( sKey == "HELPTEXT" ) {
781 SetChildWithText();
782 pResData->bHelpText = sal_True;
783 if ( bMergeMode )
784 PrepareTextToMerge( sOrig, STRING_TYP_HELPTEXT, sLangIndex, pResData );
785 else
787 if (!pResData->sHelpText[ sLangIndex ].isEmpty())
789 rtl::OStringBuffer sError(RTL_CONSTASCII_STRINGPARAM("Language "));
790 sError.append(sLangIndex);
791 sError.append(" defined twice");
792 YYWarning(sError.getStr());
794 pResData->sHelpText[ sLangIndex ] = sText;
797 else if ( sKey == "QUICKHELPTEXT" ) {
798 SetChildWithText();
799 pResData->bQuickHelpText = sal_True;
800 if ( bMergeMode )
801 PrepareTextToMerge( sOrig, STRING_TYP_QUICKHELPTEXT, sLangIndex, pResData );
802 else
804 if (!pResData->sQuickHelpText[ sLangIndex ].isEmpty())
806 rtl::OStringBuffer sError(RTL_CONSTASCII_STRINGPARAM("Language "));
807 sError.append(sLangIndex);
808 sError.append(RTL_CONSTASCII_STRINGPARAM(" defined twice"));
809 YYWarning(sError.getStr());
811 pResData->sQuickHelpText[ sLangIndex ] = sText;
814 else if ( sKey == "TITLE" ) {
815 SetChildWithText();
816 pResData->bTitle = sal_True;
817 if ( bMergeMode )
818 PrepareTextToMerge( sOrig, STRING_TYP_TITLE, sLangIndex, pResData );
819 else
821 if ( !pResData->sTitle[ sLangIndex ].isEmpty())
823 rtl::OStringBuffer sError(RTL_CONSTASCII_STRINGPARAM("Language "));
824 sError.append(sLangIndex);
825 sError.append(RTL_CONSTASCII_STRINGPARAM(" defined twice"));
826 YYWarning(sError.getStr());
828 pResData->sTitle[ sLangIndex ] = sText;
831 else if ( sKey == "ACCESSPATH" ) {
832 pResData->SetId( sText, ID_LEVEL_ACCESSPATH );
834 else if ( sKey == "FIELDNAME" ) {
835 pResData->SetId( sText, ID_LEVEL_FIELDNAME );
839 break;
840 case NEWTEXTINRES: {
841 bDontWriteOutput = sal_True;
843 break;
844 case APPFONTMAPPING:
846 bDontWriteOutput = sal_False;
847 // this is a AppfontMapping, so look if its a definition
848 // of field size
849 sal_Int32 n = 0;
850 rtl::OString sKey(
851 sToken.getToken(0, '=', n).replaceAll(" ", rtl::OString()).
852 replaceAll("\t", rtl::OString()));
853 rtl::OString sMapping = sToken.getToken(0, '=', n);
854 sMapping = sMapping.getToken(1, '(');
855 sMapping = sMapping.getToken(0, ')').
856 replaceAll(rtl::OString(' '), rtl::OString()).
857 replaceAll(rtl::OString('\t'), rtl::OString()).
858 toAsciiUpperCase();
859 if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("SIZE"))) {
860 pResData->nWidth = sMapping.getToken(0, ',').toInt32();
861 } else if (sKey.equalsL(RTL_CONSTASCII_STRINGPARAM("POSSIZE"))) {
862 pResData->nWidth = sMapping.getToken(2, ',').toInt32();
865 break;
866 case RSCDEFINELEND:
867 bDontWriteOutput = sal_False;
868 break;
869 case CONDITION: {
870 bDontWriteOutput = sal_False;
871 sToken = sToken.replace('\r', ' ').replace('\t', ' ');
872 for (;;) {
873 sal_Int32 n = 0;
874 sToken = sToken.replaceFirst(" ", " ", &n);
875 if (n == -1) {
876 break;
879 sal_Int32 n = 0;
880 rtl::OString sCondition(sToken.getToken(0, ' ', n));
881 if ( sCondition == "#ifndef" ) {
882 sActPForm = "!defined ";
883 sActPForm += sToken.getToken(0, ' ', n);
885 else if ( sCondition == "#ifdef" ) {
886 sActPForm = "defined ";
887 sActPForm += sToken.getToken(0, ' ', n);
889 else if ( sCondition == "#if" ) {
890 sActPForm = sToken.copy( 4 ).replaceAll("||", "\\or");
892 else if ( sCondition == "#elif" ) {
893 sActPForm = sToken.copy( 6 ).replaceAll("||", "\\or");
895 else if ( sCondition == "#else" ) {
896 sActPForm = sCondition;
898 else if ( sCondition == "#endif" ) {
899 sActPForm = "";
901 else break;
902 if ( nLevel ) {
903 WriteData( pResData, sal_True );
904 pResData->sPForm = sActPForm;
907 break;
908 case EMPTYLINE : {
909 bDontWriteOutput = sal_False;
910 if ( bDefine ) {
911 bNextMustBeDefineEOL = sal_False;
912 bDefine = sal_False;
913 while ( nLevel )
914 Parse( LEVELDOWN, "" );
917 break;
918 case PRAGMA : {
919 bDontWriteOutput = sal_False;
920 fprintf(stderr, "ERROR: archaic PRAGMA %s\n", sToken.getStr());
921 exit(-1);
923 break;
924 case TEXTREFID : {
925 bDontWriteOutput = sal_True;
928 if ( bWriteToMerged ) {
929 // the current token must be written to dest. without merging
931 if( bDefine && sOrig.getLength() > 2 ){
932 for( sal_uInt16 n = 0 ; n < sOrig.getLength() ; n++ ){
933 if( sOrig[n] == '\n' && sOrig[n-1] != '\\'){
934 sOrig = sOrig.replaceAt(n++, 0, "\\");
938 WriteToMerged( sOrig , false);
941 if ( bExecuteDown ) {
942 Parse( LEVELDOWN, "" );
945 return 1;
948 /*****************************************************************************/
949 void Export::CutComment( rtl::OString &rText )
950 /*****************************************************************************/
952 if (rText.indexOf("//") != -1) {
953 rtl::OString sWork(rText.replaceAll("\\\"", "XX"));
954 bool bInner = false;
955 for (sal_Int32 i = 0; i < sWork.getLength() - 1; ++i) {
956 if (sWork[i] == '"') {
957 bInner = !bInner;
958 } else if (sWork[i] == '/' && !bInner && sWork[i + 1] == '/' ) {
959 rText = rText.copy(0, i);
960 break;
966 /*****************************************************************************/
967 sal_Bool Export::WriteData( ResData *pResData, sal_Bool bCreateNew )
968 /*****************************************************************************/
970 if ( bMergeMode ) {
971 MergeRest( pResData );
972 return sal_True;
975 // mandatory to export: en-US
977 if (( !pResData->sText[ SOURCE_LANGUAGE ].isEmpty())
979 ( !pResData->sHelpText[ SOURCE_LANGUAGE ].isEmpty())
981 ( !pResData->sQuickHelpText[ SOURCE_LANGUAGE ].isEmpty())
983 ( !pResData->sTitle[ SOURCE_LANGUAGE ].isEmpty()))
986 rtl::OString sGID = pResData->sGId;
987 rtl::OString sLID;
988 if (sGID.isEmpty())
989 sGID = pResData->sId;
990 else
991 sLID = pResData->sId;
993 rtl::OString sXText;
994 rtl::OString sXHText;
995 rtl::OString sXQHText;
996 rtl::OString sXTitle;
998 sXText = pResData->sText[ SOURCE_LANGUAGE ];
999 if (!pResData->sText[ X_COMMENT ].isEmpty())
1000 sXHText = pResData->sText[ X_COMMENT ];
1001 else
1002 sXHText = pResData->sHelpText[ SOURCE_LANGUAGE ];
1003 sXQHText = pResData->sQuickHelpText[ SOURCE_LANGUAGE ];
1004 sXTitle = pResData->sTitle[ SOURCE_LANGUAGE ];
1006 if (sXText.isEmpty())
1007 sXText = "-";
1009 rtl::OString sOutput( sProject ); sOutput += "\t";
1010 if ( !sRoot.isEmpty())
1011 sOutput += sActFileName;
1012 sOutput += "\t0\t";
1013 sOutput += pResData->sResTyp; sOutput += "\t";
1014 sOutput += sGID; sOutput += "\t";
1015 sOutput += sLID; sOutput += "\t";
1016 sOutput += pResData->sHelpId; sOutput += "\t";
1017 sOutput += pResData->sPForm; sOutput += "\t";
1018 sOutput += rtl::OString::valueOf(pResData->nWidth); sOutput += "\t";
1019 sOutput += "en-US"; sOutput += "\t";
1022 sOutput += sXText; sOutput += "\t";
1023 sOutput += sXHText; sOutput += "\t";
1024 sOutput += sXQHText; sOutput+= "\t";
1025 sOutput += sXTitle; sOutput += "\t";
1027 aOutput << sOutput.getStr() << '\n';
1029 if ( bCreateNew ) {
1030 pResData->sText[ SOURCE_LANGUAGE ] = "";
1031 pResData->sHelpText[ SOURCE_LANGUAGE ] = "";
1032 pResData->sQuickHelpText[ SOURCE_LANGUAGE ]= "";
1033 pResData->sTitle[ SOURCE_LANGUAGE ] = "";
1036 if ( pResData->pStringList ) {
1037 rtl::OString sList( "stringlist" );
1038 WriteExportList( pResData, pResData->pStringList, sList, bCreateNew );
1039 if ( bCreateNew )
1040 pResData->pStringList = 0;
1042 if ( pResData->pFilterList ) {
1043 rtl::OString sList( "filterlist" );
1044 WriteExportList( pResData, pResData->pFilterList, sList, bCreateNew );
1045 if ( bCreateNew )
1046 pResData->pFilterList = 0;
1048 if ( pResData->pItemList ) {
1049 rtl::OString sList( "itemlist" );
1050 WriteExportList( pResData, pResData->pItemList, sList, bCreateNew );
1051 if ( bCreateNew )
1052 pResData->pItemList = 0;
1054 if ( pResData->pPairedList ) {
1055 rtl::OString sList( "pairedlist" );
1056 WriteExportList( pResData, pResData->pPairedList, sList, bCreateNew );
1057 if ( bCreateNew )
1058 pResData->pItemList = 0;
1060 if ( pResData->pUIEntries ) {
1061 rtl::OString sList( "uientries" );
1062 WriteExportList( pResData, pResData->pUIEntries, sList, bCreateNew );
1063 if ( bCreateNew )
1064 pResData->pUIEntries = 0;
1066 return sal_True;
1069 rtl::OString Export::GetPairedListID(const rtl::OString& rText)
1071 // < "STRING" ; IDENTIFIER ; > ;
1072 return rText.getToken(1, ';').toAsciiUpperCase().replace('\t', ' ').trim();
1075 rtl::OString Export::GetPairedListString(const rtl::OString& rText)
1077 // < "STRING" ; IDENTIFIER ; > ;
1078 rtl::OString sString(rText.getToken(0, ';').replace('\t', ' '));
1079 sString = sString.trim();
1080 rtl::OString s1(sString.copy(sString.indexOf('"') + 1));
1081 sString = s1.copy(0, s1.lastIndexOf('"'));
1082 return sString.trim();
1085 rtl::OString Export::StripList(const rtl::OString & rText)
1087 rtl::OString s1 = rText.copy( rText.indexOf('\"') + 1);
1088 return s1.copy( 0 , s1.lastIndexOf('\"'));
1091 sal_Bool Export::WriteExportList(ResData *pResData, ExportList *pExportList,
1092 const rtl::OString &rTyp, sal_Bool bCreateNew)
1094 rtl::OString sGID(pResData->sGId);
1095 if (sGID.isEmpty())
1096 sGID = pResData->sId;
1097 else {
1098 sGID += ".";
1099 sGID += pResData->sId;
1100 while (sGID.getLength() != 0 && sGID[sGID.getLength() - 1] == '.') {
1101 sGID = sGID.copy(0, sGID.getLength() - 1);
1105 rtl::OString sCur;
1106 for ( size_t i = 0; pExportList != NULL && i < pExportList->size(); i++ )
1108 ExportListEntry *pEntry = (*pExportList)[ i ];
1110 rtl::OString sLID(rtl::OString::valueOf(static_cast<sal_Int64>(i + 1)));
1111 for (unsigned int n = 0; n < aLanguages.size(); ++n)
1113 sCur = aLanguages[ n ];
1114 if (!(*pEntry)[ SOURCE_LANGUAGE ].isEmpty())
1116 rtl::OString sText((*pEntry)[ SOURCE_LANGUAGE ] );
1118 // Strip PairList Line String
1119 if (rTyp.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("pairedlist")))
1121 sLID = GetPairedListID( sText );
1122 if (!(*pEntry)[ sCur ].isEmpty())
1123 sText = (*pEntry)[ sCur ];
1124 sText = GetPairedListString( sText );
1126 else
1128 sText = StripList( (*pEntry)[ sCur ] );
1129 if( sText == "\\\"" )
1130 sText = "\"";
1133 rtl::OStringBuffer sOutput(sProject);
1134 sOutput.append('\t');
1135 if ( !sRoot.isEmpty())
1136 sOutput.append(sActFileName);
1137 sOutput.append("\t0\t");
1138 sOutput.append(rTyp).append('\t');
1139 sOutput.append(sGID).append('\t');
1140 sOutput.append(sLID).append("\t\t");
1141 sOutput.append(pResData->sPForm).append("\t0\t");
1142 sOutput.append(sCur).append('\t');
1144 sOutput.append(sText).append("\t\t\t\t");
1146 aOutput << sOutput.makeStringAndClear().getStr() << '\n';
1149 if ( bCreateNew )
1150 delete [] pEntry;
1152 if ( bCreateNew )
1153 delete pExportList;
1155 return sal_True;
1158 rtl::OString Export::FullId()
1160 rtl::OStringBuffer sFull;
1161 if ( nLevel > 1 )
1163 sFull.append(aResStack[ 0 ]->sId);
1164 for ( size_t i = 1; i < nLevel - 1; ++i )
1166 rtl::OString sToAdd = aResStack[ i ]->sId;
1167 if (!sToAdd.isEmpty())
1168 sFull.append('.').append(sToAdd);
1171 if (sFull.getLength() > 255)
1173 rtl::OString sError(RTL_CONSTASCII_STRINGPARAM("GroupId > 255 chars"));
1174 printf("GroupID = %s\n", sFull.getStr());
1175 yyerror(sError.getStr());
1178 return sFull.makeStringAndClear();
1181 void Export::InsertListEntry(const rtl::OString &rText, const rtl::OString &rLine)
1183 ResData *pResData = ( nLevel-1 < aResStack.size() ) ? aResStack[ nLevel-1 ] : NULL;
1185 ExportList *pList = NULL;
1186 if ( nList == LIST_STRING ) {
1187 pList = pResData->pStringList;
1188 if ( !pList ) {
1189 pResData->pStringList = new ExportList();
1190 pList = pResData->pStringList;
1191 nListIndex = 0;
1194 else if ( nList == LIST_FILTER ) {
1195 pList = pResData->pFilterList;
1196 if ( !pList ) {
1197 pResData->pFilterList = new ExportList();
1198 pList = pResData->pFilterList;
1199 nListIndex = 0;
1202 else if ( nList == LIST_ITEM ) {
1203 pList = pResData->pItemList;
1204 if ( !pList ) {
1205 pResData->pItemList = new ExportList();
1206 pList = pResData->pItemList;
1207 nListIndex = 0;
1210 else if ( nList == LIST_PAIRED ) {
1211 pList = pResData->pPairedList;
1212 if ( !pList ) {
1213 pResData->pPairedList = new ExportList();
1214 pList = pResData->pPairedList;
1215 nListIndex = 0;
1218 else if ( nList == LIST_UIENTRIES ) {
1219 pList = pResData->pUIEntries;
1220 if ( !pList ) {
1221 pResData->pUIEntries = new ExportList();
1222 pList = pResData->pUIEntries;
1223 nListIndex = 0;
1226 else
1227 return;
1229 if ( nListIndex + 1 > pList->size())
1231 ExportListEntry *pNew = new ExportListEntry();
1232 (*pNew)[LIST_REFID] = rtl::OString::valueOf(static_cast<sal_Int32>(REFID_NONE));
1233 pList->push_back(pNew);
1235 ExportListEntry *pCurEntry = (*pList)[ nListIndex ];
1237 // For paired list use the line to set proper lid
1238 if( nList == LIST_PAIRED ){
1239 (*pCurEntry)[ m_sListLang ] = rLine;
1240 }else
1241 (*pCurEntry)[ m_sListLang ] = rText;
1243 if ( Export::isSourceLanguage( m_sListLang ) ) {
1244 (*pCurEntry)[ SOURCE_LANGUAGE ] = rLine;
1246 pList->NewSourceLanguageListEntry();
1249 nListIndex++;
1252 /*****************************************************************************/
1253 void Export::CleanValue( rtl::OString &rValue )
1254 /*****************************************************************************/
1256 while ( !rValue.isEmpty()) {
1257 if (( rValue[0] == ' ' ) || ( rValue[0] == '\t' ))
1258 rValue = rValue.copy( 1 );
1259 else
1260 break;
1263 if ( !rValue.isEmpty()) {
1264 for ( sal_Int32 i = rValue.getLength() - 1; i > 0; i-- ) {
1265 if (( rValue[i] == ' ' ) || ( rValue[i] == '\t' ) ||
1266 ( rValue[i] == '\n' ) || ( rValue[i] == ';' ) ||
1267 ( rValue[i] == '{' ) || ( rValue[i] == '\\' ) ||
1268 ( rValue[i] == '\r' ))
1269 rValue = rValue.copy(0, i);
1270 else
1271 break;
1276 #define TXT_STATE_NON 0x000
1277 #define TXT_STATE_TEXT 0x001
1278 #define TXT_STATE_MACRO 0x002
1280 rtl::OString Export::GetText(const rtl::OString &rSource, int nToken)
1282 rtl::OString sReturn;
1283 switch ( nToken )
1285 case TEXTLINE:
1286 case LONGTEXTLINE:
1288 rtl::OString sTmp(rSource.copy(rSource.indexOf("=")));
1289 CleanValue( sTmp );
1290 sTmp = sTmp.replaceAll("\n", rtl::OString()).
1291 replaceAll("\r", rtl::OString()).
1292 replaceAll("\\\\\"", "-=<[BSlashBSlashHKom]>=-\"").
1293 replaceAll("\\\"", "-=<[Hochkomma]>=-").
1294 replaceAll("\\\x7f", "-=<[0x7F]>=-").
1295 replaceAll("\\0x7F", "-=<[0x7F]>=-");
1297 sal_uInt16 nState = TXT_STATE_TEXT;
1298 for (sal_Int32 i = 1; i <= helper::countOccurrences(sTmp, '"'); ++i)
1300 rtl::OString sToken(sTmp.getToken(i, '"'));
1301 if (!sToken.isEmpty()) {
1302 if ( nState == TXT_STATE_TEXT ) {
1303 sReturn += sToken;
1304 nState = TXT_STATE_MACRO;
1306 else {
1307 sToken = sToken.replace('\t', ' ');
1308 for (;;) {
1309 sal_Int32 n = 0;
1310 sToken = sToken.replaceFirst(" ", " ", &n);
1311 if (n == -1) {
1312 break;
1315 sToken = sToken.trim();
1316 if (!sToken.isEmpty()) {
1317 sReturn += "\\\" ";
1318 sReturn += sToken;
1319 sReturn += " \\\"";
1321 nState = TXT_STATE_TEXT;
1326 sReturn = sReturn.replaceAll("-=<[0x7F]>=-", "\x7f").
1327 replaceAll("-=<[Hochkomma]>=-", "\"").
1328 replaceAll("-=<[BSlashBSlashHKom]>=-", "\\\\").
1329 replaceAll("\\\\", "-=<[BSlashBSlash]>=-").
1330 replaceAll("-=<[BSlashBSlash]>=-", "\\");
1332 break;
1334 return sReturn;
1337 void Export::WriteToMerged(const rtl::OString &rText , bool bSDFContent)
1339 rtl::OString sText(rText);
1340 for (;;) {
1341 sal_Int32 n = 0;
1342 sText = sText.replaceFirst(" \n", "\n", &n);
1343 if (n == -1) {
1344 break;
1347 if (pParseQueue->bNextIsM && bSDFContent && sText.getLength() > 2) {
1348 for (sal_Int32 n = 0; n < sText.getLength(); ++n) {
1349 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1350 sText = sText.replaceAt(n++, 0, "\\");
1353 } else if (pParseQueue->bLastWasM && sText.getLength() > 2) {
1354 for (sal_Int32 n = 0; n < sText.getLength(); ++n) {
1355 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1356 sText = sText.replaceAt(n++, 0, "\\");
1358 if (sText[n] == '\n') {
1359 pParseQueue->bMflag = true;
1362 } else if (pParseQueue->bCurrentIsM && bSDFContent && sText.getLength() > 2)
1364 for (sal_Int32 n = 0; n < sText.getLength(); ++n) {
1365 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1366 sText = sText.replaceAt(n++, 0, "\\");
1367 pParseQueue->bMflag = true;
1370 } else if (pParseQueue->bMflag) {
1371 for (sal_Int32 n = 1; n < sText.getLength(); ++n) {
1372 if (sText[n] == '\n' && sText[n - 1] != '\\') {
1373 sText = sText.replaceAt(n++, 0, "\\");
1376 } for (sal_Int32 i = 0; i < sText.getLength(); ++i) {
1377 if (sText[i] == '\n') {
1378 aOutput << '\n';
1379 } else {
1380 char cChar = sText[i];
1381 aOutput << cChar;
1386 /*****************************************************************************/
1387 void Export::ConvertMergeContent( rtl::OString &rText )
1388 /*****************************************************************************/
1390 sal_Bool bNoOpen = ( rText.indexOf( "\\\"" ) != 0 );
1391 sal_Bool bNoClose = !rText.endsWithL(RTL_CONSTASCII_STRINGPARAM("\\\""));
1392 rtl::OStringBuffer sNew;
1393 for ( sal_Int32 i = 0; i < rText.getLength(); i++ )
1395 rtl::OString sChar( rText[i]);
1396 if (sChar.equalsL(RTL_CONSTASCII_STRINGPARAM("\\")))
1398 if (( i + 1 ) < rText.getLength())
1400 sal_Char cNext = rText[i + 1];
1401 if ( cNext == '\"' )
1403 sChar = rtl::OString('\"');
1404 i++;
1406 else if ( cNext == 'n' )
1408 sChar = rtl::OString(RTL_CONSTASCII_STRINGPARAM("\\n"));
1409 i++;
1411 else if ( cNext == 't' )
1413 sChar = rtl::OString(RTL_CONSTASCII_STRINGPARAM("\\t"));
1414 i++;
1416 else if ( cNext == '\'' )
1418 sChar = rtl::OString(RTL_CONSTASCII_STRINGPARAM("\\\'"));
1419 i++;
1421 else
1423 sChar = rtl::OString(RTL_CONSTASCII_STRINGPARAM("\\\\"));
1426 else
1428 sChar = rtl::OString(RTL_CONSTASCII_STRINGPARAM("\\\\"));
1431 else if (sChar.equalsL(RTL_CONSTASCII_STRINGPARAM("\"")))
1433 sChar = rtl::OString(RTL_CONSTASCII_STRINGPARAM("\\\""));
1435 else if (sChar.equalsL(RTL_CONSTASCII_STRINGPARAM("\x7f")))
1437 sChar = rtl::OString(RTL_CONSTASCII_STRINGPARAM("\\0x7F"));
1439 sNew.append(sChar);
1442 rText = sNew.makeStringAndClear();
1444 if ( bNoOpen ) {
1445 rtl::OString sTmp( rText );
1446 rText = "\"";
1447 rText += sTmp;
1449 if ( bNoClose )
1450 rText += "\"";
1453 sal_Bool Export::PrepareTextToMerge(rtl::OString &rText, sal_uInt16 nTyp,
1454 rtl::OString &rLangIndex, ResData *pResData)
1456 // position to merge in:
1457 sal_Int32 nStart = 0;
1458 sal_Int32 nEnd = 0;
1459 rtl::OString sOldId = pResData->sId;
1460 rtl::OString sOldGId = pResData->sGId;
1461 rtl::OString sOldTyp = pResData->sResTyp;
1463 rtl::OString sOrigText( rText );
1465 switch ( nTyp ) {
1466 case LIST_STRING :
1467 case LIST_UIENTRIES :
1468 case LIST_FILTER :
1469 case LIST_PAIRED:
1470 case LIST_ITEM :
1472 ExportList *pList = NULL;
1473 switch ( nTyp ) {
1474 case LIST_STRING : {
1475 pResData->sResTyp = "stringlist";
1476 pList = pResData->pStringList;
1478 break;
1479 case LIST_UIENTRIES : {
1480 pResData->sResTyp = "uientries";
1481 pList = pResData->pUIEntries;
1483 break;
1484 case LIST_FILTER : {
1485 pResData->sResTyp = "filterlist";
1486 pList = pResData->pFilterList;
1488 break;
1489 case LIST_ITEM : {
1490 pResData->sResTyp = "itemlist";
1491 pList = pResData->pItemList;
1493 break;
1494 case LIST_PAIRED : {
1495 pResData->sResTyp = "pairedlist";
1496 pList = pResData->pPairedList;
1498 break;
1501 if (pList)
1503 ExportListEntry *pCurEntry = (*pList)[ nListIndex - 1 ];
1504 if ( pCurEntry )
1505 rText = (*pCurEntry)[ SOURCE_LANGUAGE ];
1508 nStart = rText.indexOf( '"' );
1509 if ( nStart == -1 ) {
1510 rText = sOrigText;
1511 return sal_False;
1514 sal_Bool bFound = sal_False;
1515 for ( nEnd = nStart + 1; nEnd < rText.getLength() && !bFound; nEnd++ ) {
1516 if ( rText[nEnd] == '\"' )
1517 bFound = sal_True;
1519 if ( !bFound ) {
1520 rText = sOrigText;
1521 return sal_False;
1524 nEnd --;
1525 sLastListLine = rText;
1526 if (( sLastListLine.indexOf( '>' ) != -1 ) &&
1527 ( sLastListLine.indexOf( '<' ) == -1 ))
1529 rtl::OString sTmp = sLastListLine;
1530 sLastListLine = "<";
1531 sLastListLine += sTmp;
1533 if ( pResData->sResTyp.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("pairedlist")) )
1535 pResData->sId = GetPairedListID( sLastListLine );
1537 else pResData->sId = rtl::OString::valueOf(static_cast<sal_Int32>(nListIndex));
1539 if (!pResData->sGId.isEmpty())
1540 pResData->sGId = pResData->sGId + rtl::OString('.');
1541 pResData->sGId = pResData->sGId + sOldId;
1542 nTyp = STRING_TYP_TEXT;
1544 break;
1545 case STRING_TYP_TEXT :
1546 case STRING_TYP_HELPTEXT :
1547 case STRING_TYP_QUICKHELPTEXT :
1548 case STRING_TYP_TITLE :
1550 nStart = rText.indexOf( "=" );
1551 if ( nStart == -1 ) {
1552 rText = sOrigText;
1553 return sal_False;
1556 nStart++;
1557 sal_Bool bFound = sal_False;
1558 while(( nStart < rText.getLength()) && !bFound ) {
1559 if (( rText[nStart] != ' ' ) && ( rText[nStart] != '\t' ))
1560 bFound = sal_True;
1561 else
1562 nStart ++;
1565 // no start position found
1566 if ( !bFound ) {
1567 rText = sOrigText;
1568 return sal_False;
1571 // position to end mergeing in
1572 nEnd = rText.getLength() - 1;
1573 bFound = sal_False;
1575 while (( nEnd > nStart ) && !bFound ) {
1576 if (( rText[nEnd] != ' ' ) && ( rText[nEnd] != '\t' ) &&
1577 ( rText[nEnd] != '\n' ) && ( rText[nEnd] != ';' ) &&
1578 ( rText[nEnd] != '{' ) && ( rText[nEnd] != '\\' ))
1580 bFound = sal_True;
1582 else
1583 nEnd --;
1586 break;
1589 // search for merge data
1590 if ( !pMergeDataFile ){
1591 pMergeDataFile = new MergeDataFile( sMergeSrc, global::inputPathname, global::errorLog );
1593 // Init Languages
1594 if( Export::sLanguages.equalsIgnoreAsciiCase("ALL") )
1595 SetLanguages( pMergeDataFile->GetLanguages() );
1596 else if( !isInitialized )InitLanguages();
1600 PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
1601 pResData->sId = sOldId;
1602 pResData->sGId = sOldGId;
1603 pResData->sResTyp = sOldTyp;
1605 if ( !pEntrys ) {
1606 rText = sOrigText;
1607 return sal_False; // no data found
1610 rtl::OString sContent;
1611 pEntrys->GetTransex3Text(sContent, nTyp, rLangIndex);
1612 if (sContent.isEmpty() && (!Export::isSourceLanguage(rLangIndex)))
1614 rText = sOrigText;
1615 return sal_False; // no data found
1618 if (Export::isSourceLanguage(rLangIndex))
1619 return sal_False;
1621 rtl::OString sPostFix( rText.copy( ++nEnd ));
1622 rText = rText.copy(0, nStart);
1624 ConvertMergeContent( sContent );
1628 // merge new res. in text line
1629 rText += sContent;
1630 rText += sPostFix;
1632 return sal_True;
1635 void Export::ResData2Output( PFormEntrys *pEntry, sal_uInt16 nType, const rtl::OString& rTextType )
1637 sal_Bool bAddSemicolon = sal_False;
1638 sal_Bool bFirst = sal_True;
1639 rtl::OString sCur;
1641 for( unsigned int n = 0; n < aLanguages.size(); n++ ){
1642 sCur = aLanguages[ n ];
1644 rtl::OString sText;
1645 sal_Bool bText = pEntry->GetTransex3Text( sText, nType, sCur , sal_True );
1646 if ( bText && !sText.isEmpty() && sText != "-" ) {
1647 rtl::OString sOutput;
1648 if ( bNextMustBeDefineEOL) {
1649 if ( bFirst )
1650 sOutput += "\t\\\n";
1651 else
1652 sOutput += ";\t\\\n";
1654 bFirst=sal_False;
1655 sOutput += "\t";
1657 sOutput += rTextType;
1659 if ( ! Export::isSourceLanguage( sCur ) ) {
1660 sOutput += "[ ";
1661 sOutput += sCur;
1662 sOutput += " ] ";
1664 sOutput += "= ";
1665 ConvertMergeContent( sText );
1666 sOutput += sText;
1668 if ( bDefine )
1669 sOutput += ";\\\n";
1670 else if ( !bNextMustBeDefineEOL )
1671 sOutput += ";\n";
1672 else
1673 bAddSemicolon = sal_True;
1674 for ( sal_uInt16 j = 1; j < nLevel; j++ )
1675 sOutput += "\t";
1676 WriteToMerged( sOutput , true );
1681 if ( bAddSemicolon ) {
1682 rtl::OString sOutput( ";" );
1683 WriteToMerged( sOutput , false );
1687 /*****************************************************************************/
1688 void Export::MergeRest( ResData *pResData, sal_uInt16 nMode )
1689 /*****************************************************************************/
1691 if ( !pMergeDataFile ){
1692 pMergeDataFile = new MergeDataFile( sMergeSrc, global::inputPathname, global::errorLog );
1694 // Init Languages
1695 if (Export::sLanguages.equalsIgnoreAsciiCase("ALL"))
1696 SetLanguages( pMergeDataFile->GetLanguages() );
1697 else if( !isInitialized )InitLanguages();
1700 switch ( nMode ) {
1701 case MERGE_MODE_NORMAL : {
1702 PFormEntrys *pEntry = pMergeDataFile->GetPFormEntrys( pResData );
1704 if ( pEntry ) {
1705 if ( pResData->bText )
1706 ResData2Output( pEntry, STRING_TYP_TEXT, pResData->sTextTyp );
1708 if ( pResData->bQuickHelpText )
1709 ResData2Output( pEntry, STRING_TYP_QUICKHELPTEXT, rtl::OString("QuickHelpText") );
1711 if ( pResData->bTitle )
1712 ResData2Output( pEntry, STRING_TYP_TITLE, rtl::OString("Title") );
1715 // Merge Lists
1717 if ( pResData->bList ) {
1718 bool bPairedList = false;
1719 rtl::OString sOldId = pResData->sId;
1720 rtl::OString sOldGId = pResData->sGId;
1721 rtl::OString sOldTyp = pResData->sResTyp;
1722 if (!pResData->sGId.isEmpty())
1723 pResData->sGId = pResData->sGId + rtl::OString('.');
1724 pResData->sGId = pResData->sGId + sOldId;
1725 rtl::OString sSpace;
1726 for ( sal_uInt16 i = 1; i < nLevel-1; i++ )
1727 sSpace += "\t";
1728 for ( sal_uInt16 nT = LIST_STRING; nT <= LIST_UIENTRIES; nT++ ) {
1729 ExportList *pList = NULL;
1730 switch ( nT ) {
1731 case LIST_STRING : pResData->sResTyp = "stringlist"; pList = pResData->pStringList; bPairedList = false; break;
1732 case LIST_FILTER : pResData->sResTyp = "filterlist"; pList = pResData->pFilterList; bPairedList = false; break;
1733 case LIST_UIENTRIES : pResData->sResTyp = "uientries"; pList = pResData->pUIEntries;bPairedList = false; break;
1734 case LIST_ITEM : pResData->sResTyp = "itemlist"; pList = pResData->pItemList; bPairedList = false; break;
1735 case LIST_PAIRED : pResData->sResTyp = "pairedlist"; pList = pResData->pPairedList; bPairedList = true; break;
1737 rtl::OString sCur;
1738 for( unsigned int n = 0; n < aLanguages.size(); n++ )
1740 sCur = aLanguages[ n ];
1741 sal_uInt16 nIdx = 1;
1743 // Set matching pairedlist identifier
1744 if( bPairedList && pResData->pPairedList && ( nIdx == 1 ) ){
1745 ExportListEntry* pListE = ( ExportListEntry* ) (*pResData->pPairedList)[ nIdx-1 ];
1746 pResData->sId = GetPairedListID ( (*pListE)[ SOURCE_LANGUAGE ] );
1748 else
1749 pResData->sId = "1";
1751 PFormEntrys *pEntrys;
1752 std::size_t nLIndex = 0;
1753 std::size_t nMaxIndex = 0;
1754 if ( pList )
1755 nMaxIndex = pList->GetSourceLanguageListEntryCount();
1756 pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
1757 while( pEntrys && ( nLIndex < nMaxIndex )) {
1758 rtl::OString sText;
1759 sal_Bool bText;
1760 bText = pEntrys->GetTransex3Text( sText, STRING_TYP_TEXT, sCur, sal_True );
1761 if( !bText )
1762 bText = pEntrys->GetTransex3Text( sText , STRING_TYP_TEXT, SOURCE_LANGUAGE , sal_False );
1764 if ( bText && !sText.isEmpty())
1766 if ( nIdx == 1 )
1768 rtl::OStringBuffer sHead;
1769 if ( bNextMustBeDefineEOL )
1770 sHead.append(RTL_CONSTASCII_STRINGPARAM("\\\n\t"));
1771 sHead.append(sSpace);
1772 switch ( nT )
1774 case LIST_STRING:
1775 sHead.append(RTL_CONSTASCII_STRINGPARAM("StringList "));
1776 break;
1777 case LIST_FILTER:
1778 sHead.append(RTL_CONSTASCII_STRINGPARAM("FilterList "));
1779 break;
1780 case LIST_ITEM:
1781 sHead.append(RTL_CONSTASCII_STRINGPARAM("ItemList "));
1782 break;
1783 case LIST_PAIRED:
1784 sHead.append(RTL_CONSTASCII_STRINGPARAM("PairedList "));
1785 break;
1786 case LIST_UIENTRIES:
1787 sHead.append(RTL_CONSTASCII_STRINGPARAM("UIEntries "));
1788 break;
1790 sHead.append(RTL_CONSTASCII_STRINGPARAM("[ "));
1791 sHead.append(sCur);
1792 sHead.append(RTL_CONSTASCII_STRINGPARAM(" ] "));
1794 if ( bDefine || bNextMustBeDefineEOL )
1796 sHead.append(RTL_CONSTASCII_STRINGPARAM("= \\\n"));
1797 sHead.append(sSpace);
1798 sHead.append(RTL_CONSTASCII_STRINGPARAM("\t{\\\n\t"));
1800 else
1802 sHead.append(RTL_CONSTASCII_STRINGPARAM("= \n"));
1803 sHead.append(sSpace);
1804 sHead.append(RTL_CONSTASCII_STRINGPARAM("\t{\n\t"));
1806 WriteToMerged(sHead.makeStringAndClear() , true);
1808 rtl::OString sLine;
1809 if ( pList && (*pList)[ nLIndex ] )
1810 sLine = ( *(*pList)[ nLIndex ])[ SOURCE_LANGUAGE ];
1811 if ( sLine.isEmpty())
1812 sLine = sLastListLine;
1814 if ( sLastListLine.indexOf( '<' ) != -1 ) {
1815 if (( nT != LIST_UIENTRIES ) &&
1816 (( sLine.indexOf( '{' ) == -1 ) ||
1817 ( sLine.indexOf( '{' ) >= sLine.indexOf( '"' ))) &&
1818 (( sLine.indexOf( '<' ) == -1 ) ||
1819 ( sLine.indexOf( '<' ) >= sLine.indexOf( '"' ))))
1821 sLine = sLine.replaceFirst("\"", "< \"" );
1825 sal_Int32 nStart, nEnd;
1826 nStart = sLine.indexOf( '"' );
1828 rtl::OString sPostFix;
1829 if( !bPairedList ){
1830 nEnd = sLine.lastIndexOf( '"' );
1831 sPostFix = sLine.copy( ++nEnd );
1832 sLine = sLine.copy(0, nStart);
1836 ConvertMergeContent( sText );
1838 // merge new res. in text line
1839 if( bPairedList ){
1840 sLine = MergePairedList( sLine , sText );
1842 else{
1843 sLine += sText;
1844 sLine += sPostFix;
1847 rtl::OString sText1( "\t" );
1848 sText1 += sLine;
1849 if ( bDefine || bNextMustBeDefineEOL )
1850 sText1 += " ;\\\n";
1851 else
1852 sText1 += " ;\n";
1853 sText1 += sSpace;
1854 sText1 += "\t";
1855 WriteToMerged( sText1 ,true );
1857 // Set matching pairedlist identifier
1858 if ( bPairedList ){
1859 nIdx++;
1860 ExportListEntry* pListE = ( ExportListEntry* )(*pResData->pPairedList)[ ( nIdx ) -1 ];
1861 if( pListE ){
1862 pResData->sId = GetPairedListID ( (*pListE)[ SOURCE_LANGUAGE ] );
1865 else
1866 pResData->sId = rtl::OString::valueOf(static_cast<sal_Int32>(++nIdx));
1868 else
1869 break;
1870 nLIndex ++;
1871 PFormEntrys *oldEntry = pEntrys;
1872 pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
1873 if( !pEntrys )
1874 pEntrys = oldEntry;
1876 if ( nIdx > 1 ) {
1877 rtl::OString sFooter;
1878 if (!sSpace.isEmpty()) {
1879 sFooter = sSpace.copy(1);
1881 if ( bNextMustBeDefineEOL )
1882 sFooter += "};";
1883 else if ( !bDefine )
1884 sFooter += "};\n\t";
1885 else
1886 sFooter += "\n\n";
1887 WriteToMerged( sFooter ,true );
1892 pResData->sId = sOldId;
1893 pResData->sGId = sOldGId;
1894 pResData->sResTyp = sOldTyp;
1897 break;
1898 case MERGE_MODE_LIST : {
1899 ExportList *pList = NULL;
1900 switch ( nList ) {
1901 // PairedList
1902 case LIST_STRING : pList = pResData->pStringList; break;
1903 case LIST_FILTER : pList = pResData->pFilterList; break;
1904 case LIST_UIENTRIES : pList = pResData->pUIEntries; break;
1905 case LIST_ITEM : pList = pResData->pItemList; break;
1906 case LIST_PAIRED : pList = pResData->pPairedList; break;
1910 nListIndex++;
1911 std::size_t nMaxIndex = 0;
1912 if ( pList )
1913 nMaxIndex = pList->GetSourceLanguageListEntryCount();
1914 rtl::OString sLine;
1915 if ( pList && (*pList)[ nListIndex ] )
1916 sLine = ( *(*pList)[ nListIndex ])[ SOURCE_LANGUAGE ];
1917 if ( sLine.isEmpty())
1918 sLine = sLastListLine;
1920 if ( sLastListLine.indexOf( '<' ) != -1 ) {
1921 if (( nList != LIST_UIENTRIES ) &&
1922 (( sLine.indexOf( '{' ) == -1 ) ||
1923 ( sLine.indexOf( '{' ) >= sLine.indexOf( '"' ))) &&
1924 (( sLine.indexOf( '<' ) == -1 ) ||
1925 ( sLine.indexOf( '<' ) >= sLine.indexOf( '"' ))))
1927 sLine = sLine.replaceFirst("\"", "< \"");
1931 while( PrepareTextToMerge( sLine, nList, m_sListLang, pResData ) && ( nListIndex <= nMaxIndex )) {
1932 rtl::OString sText( "\t" );
1933 sText += sLine;
1934 sText += " ;";
1935 sText += "\n";
1936 for ( sal_uInt16 i = 0; i < nLevel; i++ )
1937 sText += "\t";
1938 WriteToMerged( sText ,false );
1939 nListIndex++;
1940 if ( pList && (*pList)[ nListIndex ])
1941 sLine = ( *(*pList)[ nListIndex ])[ SOURCE_LANGUAGE ];
1942 if ( sLine.isEmpty())
1943 sLine = sLastListLine;
1944 sLine += " ;";
1947 break;
1949 pParseQueue->bMflag = false;
1952 rtl::OString Export::MergePairedList( rtl::OString const & sLine , rtl::OString const & sText ){
1953 // < "xy" ; IDENTIFIER ; >
1954 rtl::OString sPre = sLine.copy( 0 , sLine.indexOf('"') );
1955 rtl::OString sPost = sLine.copy( sLine.lastIndexOf('"') + 1 );
1956 sPre += sText;
1957 sPre += sPost;
1958 return sPre;
1961 /*****************************************************************************/
1962 void Export::SetChildWithText()
1963 /*****************************************************************************/
1965 if ( aResStack.size() > 1 ) {
1966 for ( size_t i = 0; i < aResStack.size() - 1; i++ ) {
1967 aResStack[ i ]->bChildWithText = sal_True;
1972 void ParserQueue::Push( const QueueEntry& aEntry )
1974 sal_Int32 nLen = aEntry.sLine.getLength();
1976 if( !bStart ){
1977 aQueueCur->push( aEntry );
1978 if( nLen > 1 && aEntry.sLine[nLen-1] == '\n' )
1979 bStart = true;
1980 else if ( aEntry.nTyp != IGNOREDTOKENS ){
1981 if( nLen > 1 && ( aEntry.sLine[nLen-1] == '\\') ){
1982 // Next is Macro
1983 bCurrentIsM = true;
1984 }else{
1985 // Next is no Macro
1986 bCurrentIsM = false;
1990 else{
1991 aQueueNext->push( aEntry );
1992 if( nLen > 1 && aEntry.sLine[nLen-1] != '\n' ){
1993 if( nLen > 1 && ( aEntry.sLine[nLen-1] == '\\') ){
1994 // Next is Macro
1995 bNextIsM = true;
1997 else{
1998 // Next is no Macro
1999 bNextIsM = false;
2001 }else if( nLen > 2 && aEntry.sLine[nLen-1] == '\n' ){
2002 if( aEntry.nTyp != IGNOREDTOKENS ){
2003 if( nLen > 2 && ( aEntry.sLine[nLen-2] == '\\') ){
2004 // Next is Macro
2005 bNextIsM = true;
2007 else{
2008 // Next is no Macro
2009 bNextIsM = false;
2012 // Pop current
2013 Pop( *aQueueCur );
2014 bLastWasM = bCurrentIsM;
2015 // next -> current
2016 bCurrentIsM = bNextIsM;
2017 aQref = aQueueCur;
2018 aQueueCur = aQueueNext;
2019 aQueueNext = aQref;
2023 else{
2024 // Pop current
2025 Pop( *aQueueCur );
2026 bLastWasM = bCurrentIsM;
2027 // next -> current
2028 bCurrentIsM = bNextIsM;
2029 aQref = aQueueCur;
2030 aQueueCur = aQueueNext;
2031 aQueueNext = aQref;
2036 void ParserQueue::Close(){
2037 // Pop current
2038 Pop( *aQueueCur );
2039 // next -> current
2040 bLastWasM = bCurrentIsM;
2041 bCurrentIsM = bNextIsM;
2042 aQref = aQueueCur;
2043 aQueueCur = aQueueNext;
2044 aQueueNext = aQref;
2045 bNextIsM = false;
2046 Pop( *aQueueNext );
2049 void ParserQueue::Pop( std::queue<QueueEntry>& aQueue )
2051 while (!aQueue.empty())
2053 QueueEntry aEntry = aQueue.front();
2054 aQueue.pop();
2055 aExport.Execute(aEntry.nTyp, aEntry.sLine.getStr());
2059 ParserQueue::ParserQueue( Export& aExportObj )
2061 bCurrentIsM( false ),
2062 bNextIsM( false ) ,
2063 bLastWasM( false ),
2064 bMflag( false ) ,
2065 aExport( aExportObj ) ,
2066 bStart( false ) ,
2067 bStartNext( false )
2069 aQueueNext = new std::queue<QueueEntry>;
2070 aQueueCur = new std::queue<QueueEntry>;
2074 ParserQueue::~ParserQueue(){
2075 if( aQueueNext ) delete aQueueNext;
2076 if( aQueueCur ) delete aQueueCur;
2079 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */