xref: /aoo41x/main/l10ntools/source/localize.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_l10ntools.hxx"
30 
31 #include "srciter.hxx"
32 #include "export.hxx"
33 #include "treeconfig.hxx"
34 #include <string>
35 #include <vector>
36 #include <stdio.h>
37 #include <iostream>
38 #include "tools/errcode.hxx"
39 #include "tools/fsys.hxx"
40 
41 #ifndef L10NTOOLS_FILE_HXX
42 #define L10NTOOLS_FILE_HXX
43 #include <l10ntools/file.hxx>
44 #endif
45 
46 namespace transex3
47 {
48 
49 //
50 // SourceTreeLocalizer
51 //
52 
53 const char *ExeTable[][5] = {
54 	{ "src", "transex3", "  -UTF8 -e", "negative", "noiso" },
55 	{ "hrc", "transex3", "  -UTF8 -e", "positive", "noiso" },
56 	{ "tree", "xhtex", "", "negative", "noiso" },
57 	{ "xtx", "xtxex", "", "negative", "noiso" },
58 	{ "ulf", "ulfex", " -e", "negative", "noiso" },
59 	{ "xrb", "xmlex", "-UTF8 -e", "negative", "iso" },
60 	{ "xxl", "xmlex", "-UTF8 -e", "negative", "iso" },
61 	{ "xgf", "xmlex", "-UTF8 -e -t:xgf", "negative", "iso" },
62 	{ "xcd", "cfgex", "-UTF8 -e", "negative", "iso" },
63 	{ "xcu", "cfgex", "-UTF8 -e", "negative", "iso" },
64 	{ "xcs", "cfgex", "-UTF8 -e -f", "negative", "iso" },
65 	{ "xrm", "xrmex", "-UTF8 -e", "negative", "iso" },
66 	{ "xhp", "helpex", " -e", "negative", "noiso" },
67    	{ "properties", "jpropex", " -e", "negative", "noiso" },
68     { "NULL", "NULL", "NULL", "NULL", "NULL" }
69 };
70 
71 const char *NegativeList[] = {
72 	"officecfg/data/org.openoffice.Office.Labels.xcd",
73 	"officecfg/data/org/openoffice/Office/Labels.xcd",
74 	"officecfg/data/org/openoffice/Office/SFX.xcd",
75 	"officecfg/data/org/openoffice/Office/Accelerators.xcu",
76 	"hidother.src",
77 	"NULL"
78 };
79 
80 const char *PositiveList[] = {
81 	"svx/inc/globlmn_tmpl.hrc",
82 	"sw/source/ui/inc/swmn_tmpl.hrc",
83 	"sw/source/ui/inc/swacc_tmpl.hrc",
84 	"sw/source/ui/inc/toolbox_tmpl.hrc",
85 	"offmgr/inc/offmenu_tmpl.hrc",
86 	"offmgr/source/offapp/intro/intro_tmpl.hrc",
87 	"dbaccess/source/ui/inc/toolbox_tmpl.hrc",
88 	"svx/source/intro/intro_tmpl.hrc",
89     "dbaccess/source/ui/dlg/AutoControls_tmpl.hrc",
90     "svx/source/unodialogs/textconversiondlgs/chinese_direction_tmpl.hrc",
91     "chart2/source/controller/dialogs/res_DataLabel_tmpl.hrc",
92     "chart2/source/controller/dialogs/res_LegendPosition_tmpl.hrc",
93     "chart2/source/controller/dialogs/res_Statistic_tmpl.hrc",
94     "chart2/source/controller/dialogs/res_Titlesx_tmpl.hrc",
95     "chart2/source/controller/dialogs/res_SecondaryAxisCheckBoxes_tmpl.hrc",
96     "chart2/source/controller/menu/MenuItems_tmpl.hrc",
97     "chart2/source/controller/dialogs/res_ErrorBar_tmpl.hrc",
98     "chart2/source/controller/dialogs/res_Trendline_tmpl.hrc",
99    	"svx.link/inc/globlmn_tmpl.hrc",
100 	"sw.link/source/ui/inc/swmn_tmpl.hrc",
101 	"sw.link/source/ui/inc/swacc_tmpl.hrc",
102 	"sw.link/source/ui/inc/toolbox_tmpl.hrc",
103 	"offmgr.link/inc/offmenu_tmpl.hrc",
104 	"offmgr.link/source/offapp/intro/intro_tmpl.hrc",
105 	"dbaccess.link/source/ui/inc/toolbox_tmpl.hrc",
106 	"svx.link/source/intro/intro_tmpl.hrc",
107     "dbaccess.link/source/ui/dlg/AutoControls_tmpl.hrc",
108     "svx.link/source/unodialogs/textconversiondlgs/chinese_direction_tmpl.hrc",
109     "chart2.link/source/controller/dialogs/res_DataLabel_tmpl.hrc",
110     "chart2.link/source/controller/dialogs/res_LegendPosition_tmpl.hrc",
111     "chart2.link/source/controller/dialogs/res_Statistic_tmpl.hrc",
112     "chart2.link/source/controller/dialogs/res_Titlesx_tmpl.hrc",
113     "chart2.link/source/controller/dialogs/res_SecondaryAxisCheckBoxes_tmpl.hrc",
114     "chart2.link/source/controller/menu/MenuItems_tmpl.hrc",
115     "chart2.link/source/controller/dialogs/res_ErrorBar_tmpl.hrc",
116     "chart2.link/source/controller/dialogs/res_Trendline_tmpl.hrc",
117     "NULL"
118 };
119 
120 
121 const char PRJ_DIR_NAME[] = "prj";
122 const char DLIST_NAME[] = "d.lst";
123 
124 #define LOCALIZE_NONE		0x0000
125 #define LOCALIZE_EXTRACT	0x0001
126 #define LOCALIZE_MERGE		0x0002
127 
128 class SourceTreeLocalizer : public SourceTreeIterator
129 {
130 private:
131 	SvFileStream aSDF;
132 	sal_uInt16 nMode;
133 
134 	ByteString sLanguageRestriction;
135 
136 	ByteString sOutputFile;
137 
138     int nFileCnt;
139 
140 	const ByteString GetProjectName( sal_Bool bAbs = sal_False );
141 	const ByteString GetProjectRootRel();
142 
143 
144     sal_Bool CheckNegativeList( const ByteString &rFileName );
145 	sal_Bool CheckPositiveList( const ByteString &rFileName );
146 
147 	void WorkOnFile(
148 		const ByteString &rFileName,
149 		const ByteString &rExecutable,
150 		const ByteString &rParameter
151 	);
152 
153 	void WorkOnFileType(
154 		const ByteString &rDirectory,
155 		const ByteString &rExtension,
156 		const ByteString &rExecutable,
157 		const ByteString &rParameter,
158 		const ByteString &rCollectMode
159 	);
160 	void WorkOnDirectory( const ByteString &rDirectory );
161 	sal_Bool ExecuteMerge();
162 	sal_Bool MergeSingleFile(
163 		const ByteString &rPrj,
164 		const ByteString &rFile,
165 		const ByteString &rSDFFile
166 	);
167 
168 public:
169 	SourceTreeLocalizer( const ByteString &rRoot, const ByteString &rVersion , bool bLocal , bool skip_links );
170 	~SourceTreeLocalizer();
171 
172     ByteString getSourceLanguages( ByteString sLanguageRestriction , ByteString sCommand );
173 
174 	void SetLanguageRestriction( const ByteString& rRestrictions )
175 		{ sLanguageRestriction = rRestrictions; }
176     int getFileCnt();
177 	sal_Bool Extract( const ByteString &rDestinationFile );
178 	sal_Bool Merge( const ByteString &rSourceFile , const ByteString &rOutput );
179     int GetFileCnt();
180 	virtual void OnExecuteDirectory( const rtl::OUString &rDirectory );
181 };
182 
183 /*****************************************************************************/
184 SourceTreeLocalizer::SourceTreeLocalizer(
185 	const ByteString &rRoot, const ByteString &rVersion, bool bLocal_in , bool skip_links )
186 /*****************************************************************************/
187 				: SourceTreeIterator( rRoot, rVersion , bLocal_in ),
188 				nMode( LOCALIZE_NONE ),
189                 nFileCnt( 0 )
190 {
191         bSkipLinks  = skip_links ;
192 }
193 
194 /*****************************************************************************/
195 SourceTreeLocalizer::~SourceTreeLocalizer()
196 /*****************************************************************************/
197 {
198 }
199 
200 /*****************************************************************************/
201 const ByteString SourceTreeLocalizer::GetProjectName( sal_Bool bAbs )
202 /*****************************************************************************/
203 {
204 	sal_Bool bFound = sal_False;
205 	DirEntry aCur;
206 	aCur.ToAbs();
207 
208 	for ( ; ! bFound && aCur.Level() > 1; aCur.CutName() )
209 	{
210 		DirEntry aTest = aCur + DirEntry(PRJ_DIR_NAME) + DirEntry(DLIST_NAME);
211 		if ( aTest.Exists() )
212 		{
213 			if ( bAbs )
214 				return ByteString( aCur.GetFull(), RTL_TEXTENCODING_ASCII_US );
215 			else
216 				return ByteString( aCur.GetName(), RTL_TEXTENCODING_ASCII_US );
217 		}
218 	}
219 
220 	return "";
221 }
222 /*****************************************************************************/
223 int SourceTreeLocalizer::GetFileCnt(){
224 /*****************************************************************************/
225     return nFileCnt;
226 }
227 
228 /*****************************************************************************/
229 const ByteString SourceTreeLocalizer::GetProjectRootRel()
230 /*****************************************************************************/
231 {
232 	ByteString sProjectRoot( GetProjectName( sal_True ));
233 	DirEntry aCur;
234 	aCur.ToAbs();
235 	ByteString sCur( aCur.GetFull(), RTL_TEXTENCODING_ASCII_US );
236 
237 	if( sCur.SearchAndReplace( sProjectRoot, "" ) == STRING_NOTFOUND )
238 		return "";
239 
240 	ByteString sDelimiter(
241 		DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
242 
243 	sCur.SearchAndReplaceAll( sDelimiter, "/" );
244 	sCur.EraseLeadingChars( '/' );
245 	sal_uLong nCount = sCur.GetTokenCount( '/' );
246 
247 	ByteString sProjectRootRel;
248 	for ( sal_uLong i = 0; i < nCount; i++ ) {
249 		if ( sProjectRootRel.Len())
250 			sProjectRootRel += sDelimiter;
251 		sProjectRootRel += "..";
252 	}
253 	if ( sProjectRootRel.Len())
254 		return sProjectRootRel;
255 
256 	return ".";
257 }
258 
259 bool skipProject( ByteString sPrj )
260 {
261     static const ByteString READLICENSE( "readlicense" );
262     return sPrj.EqualsIgnoreCaseAscii( READLICENSE );
263 }
264 
265 /*****************************************************************************/
266 void SourceTreeLocalizer::WorkOnFile(
267 	const ByteString &rFileName, const ByteString &rExecutable,
268 	const ByteString &rParameter )
269 /*****************************************************************************/
270 {
271         String sFull( rFileName, RTL_TEXTENCODING_ASCII_US );
272 		DirEntry aEntry( sFull );
273 		ByteString sFileName( aEntry.GetName(), RTL_TEXTENCODING_ASCII_US );
274 
275 		// set current working directory
276 		DirEntry aPath( aEntry.GetPath());
277 		DirEntry aOldCWD;
278 		aPath.SetCWD();
279 
280 		ByteString sPrj( GetProjectName());
281         if ( sPrj.Len() && !skipProject( sPrj ) )
282         {
283 			ByteString sRoot( GetProjectRootRel());
284 
285 			DirEntry aTemp( Export::GetTempFile());
286 			ByteString sTempFile( aTemp.GetFull(), RTL_TEXTENCODING_ASCII_US );
287 
288             ByteString sDel;
289 #if defined(WNT) || defined(OS2)
290             sDel=ByteString("\\");
291 #else
292             sDel=ByteString("/");
293 #endif
294             ByteString sPath1( Export::GetEnv("SOLARVER") );
295 			ByteString sPath2( Export::GetEnv("INPATH") );
296             ByteString sPath3( "bin" );
297             ByteString sPath4( Export::GetEnv("UPDMINOREXT") );
298             ByteString sExecutable( sPath1 );
299             sExecutable += sDel ;
300             sExecutable += sPath2 ;
301             sExecutable += sDel;
302             sExecutable += sPath3 ;
303             sExecutable += sPath4 ;
304             sExecutable += sDel ;
305             sExecutable += rExecutable ;
306 
307 
308 	    ByteString sCommand( sExecutable );
309 	    sCommand += " ";
310 	    sCommand += rParameter;
311 	    sCommand += " -p ";
312 	    sCommand += sPrj;
313 	    sCommand += " -r ";
314 	    sCommand += sRoot;
315 	    sCommand += " -i ";
316 	    sCommand += sFileName;
317 	    sCommand += " -o ";
318 	    sCommand += sTempFile;
319 	    if ( sLanguageRestriction.Len()) {
320 	    	sCommand += " -l ";
321 		sCommand += getSourceLanguages( sLanguageRestriction , sCommand );
322 	    }
323 
324             //printf("DBG: %s\n",sCommand.GetBuffer());
325             if (system(sCommand.GetBuffer()) == -1)
326                 fprintf(stderr, "%s failed\n", sCommand.GetBuffer());
327             nFileCnt++;
328             printf(".");
329             fflush( stdout );
330 
331 			SvFileStream aSDFIn( aTemp.GetFull(), STREAM_READ );
332 			ByteString sLine;
333 			while ( aSDFIn.IsOpen() && !aSDFIn.IsEof()) {
334 				aSDFIn.ReadLine( sLine );
335 				if ( sLine.Len()) {
336 					aSDF.WriteLine( sLine );
337 				}
338 			}
339 			aSDFIn.Close();
340 
341 			aTemp.Kill();
342 
343         }
344 		// reset current working directory
345 		aOldCWD.SetCWD();
346 }
347 
348 ByteString SourceTreeLocalizer::getSourceLanguages( ByteString sLanguageRestriction_inout , ByteString sCommand )
349 {
350     // Source languages in helpcontent2 and macromigration en-US only!
351     if( sCommand.Search("helpex") != STRING_NOTFOUND ) {
352         sLanguageRestriction_inout.Assign( ByteString("en-US") );
353     }
354     else if( sCommand.Search("xmlex") != STRING_NOTFOUND ){
355         sLanguageRestriction_inout.Assign( ByteString("en-US") );
356     }
357     return sLanguageRestriction_inout;
358 }
359 
360 /*****************************************************************************/
361 sal_Bool SourceTreeLocalizer::CheckNegativeList( const ByteString &rFileName )
362 /*****************************************************************************/
363 {
364 	sal_uLong nIndex = 0;
365 	sal_Bool bReturn  = sal_True;
366 
367 	ByteString sDelimiter(
368 		DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
369 
370 	ByteString sFileName( rFileName );
371 	sFileName.ToLowerAscii();
372 
373 	ByteString sNegative( NegativeList[ nIndex ] );
374 	while( !sNegative.Equals( "NULL" ) && bReturn ) {
375 		sNegative.SearchAndReplaceAll( "\\", sDelimiter );
376 		sNegative.SearchAndReplaceAll( "/", sDelimiter );
377 		sNegative.ToLowerAscii();
378 
379 		if( sFileName.Search( sNegative ) == sFileName.Len() - sNegative.Len())
380 			bReturn = sal_False;
381 
382 		nIndex++;
383 		sNegative = NegativeList[ nIndex ];
384 	}
385 
386 	return bReturn;
387 }
388 
389 /*****************************************************************************/
390 sal_Bool SourceTreeLocalizer::CheckPositiveList( const ByteString &rFileName )
391 /*****************************************************************************/
392 {
393 	sal_uLong nIndex = 0;
394 	sal_Bool bReturn  = sal_False;
395 
396 	ByteString sDelimiter(
397 		DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
398 
399 	ByteString sFileName( rFileName );
400 	sFileName.ToLowerAscii();
401 
402 	ByteString sNegative( PositiveList[ nIndex ] );
403 	while( !sNegative.Equals( "NULL" ) && !bReturn ) {
404 		sNegative.SearchAndReplaceAll( "\\", sDelimiter );
405 		sNegative.SearchAndReplaceAll( "/", sDelimiter );
406 		sNegative.ToLowerAscii();
407 
408 		if( sFileName.Search( sNegative ) == sFileName.Len() - sNegative.Len())
409 			bReturn = sal_True;
410 
411 		nIndex++;
412 		sNegative = PositiveList[ nIndex ];
413 	}
414 
415 	return bReturn;
416 }
417 
418 /*****************************************************************************/
419 void SourceTreeLocalizer::WorkOnFileType(
420 	const ByteString &rDirectory, const ByteString &rExtension,
421 	const ByteString &rExecutable, const ByteString &rParameter,
422 	const ByteString &rCollectMode
423 )
424 /*****************************************************************************/
425 {
426 	String sWild( rDirectory, RTL_TEXTENCODING_ASCII_US );
427 	sWild += DirEntry::GetAccessDelimiter();
428 	sWild += String::CreateFromAscii( "*." );
429 	sWild += String( rExtension, RTL_TEXTENCODING_ASCII_US );
430 
431 	DirEntry aEntry( sWild );
432 	Dir aDir( sWild, FSYS_KIND_FILE );
433 
434 	for ( sal_uInt16 i = 0; i < aDir.Count(); i++ ) {
435 		DirEntry aFile( aDir[ i ] );
436 		ByteString sFile( aFile.GetFull(), RTL_TEXTENCODING_ASCII_US );
437 
438 		sal_Bool bAllowed = sal_True;
439 
440 		if ( rCollectMode.Equals( "negative" ))
441 			bAllowed = CheckNegativeList( sFile );
442 		else if ( rCollectMode.Equals( "positive" ))
443 			bAllowed = CheckPositiveList( sFile );
444 
445 		if ( bAllowed )
446 			WorkOnFile( sFile, rExecutable, rParameter );
447 	}
448 }
449 
450 /*****************************************************************************/
451 void SourceTreeLocalizer::WorkOnDirectory( const ByteString &rDirectory )
452 /*****************************************************************************/
453 {
454 	//printf("Working on Directory %s\n",rDirectory.GetBuffer());
455     sal_uLong nIndex = 0;
456 	ByteString sExtension( ExeTable[ nIndex ][ 0 ] );
457 	ByteString sExecutable( ExeTable[ nIndex ][ 1 ] );
458 	ByteString sParameter( ExeTable[ nIndex ][ 2 ] );
459 	ByteString sCollectMode( ExeTable[ nIndex ][ 3 ] );
460 
461 	while( !sExtension.Equals( "NULL" )) {
462 		WorkOnFileType(
463 			rDirectory,
464 			sExtension,
465 			sExecutable,
466 			sParameter,
467 			sCollectMode
468 		);
469 
470 		nIndex++;
471 
472 		sExtension = ExeTable[ nIndex ][ 0 ];
473 		sExecutable = ExeTable[ nIndex ][ 1 ];
474 		sParameter = ExeTable[ nIndex ][ 2 ];
475 		sCollectMode = ExeTable[ nIndex ][ 3 ];
476 	}
477 }
478 
479 void SourceTreeLocalizer::OnExecuteDirectory( const rtl::OUString &aDirectory )
480 {
481 	ByteString rDirectory( rtl::OUStringToOString( aDirectory , RTL_TEXTENCODING_UTF8 , aDirectory.getLength() ) ) ;
482 	if ( nMode == LOCALIZE_NONE ){
483     }
484 	else
485 		WorkOnDirectory( rDirectory );
486 }
487 
488 /*****************************************************************************/
489 sal_Bool SourceTreeLocalizer::Extract( const ByteString &rDestinationFile )
490 /*****************************************************************************/
491 {
492 	nMode = LOCALIZE_EXTRACT;
493 
494     aSDF.Open( String( rDestinationFile , RTL_TEXTENCODING_ASCII_US ) , STREAM_STD_WRITE );
495 	aSDF.SetLineDelimiter( LINEEND_CRLF );
496 
497 	sal_Bool bReturn = aSDF.IsOpen();
498 	if ( bReturn ) {
499 		aSDF.Seek( STREAM_SEEK_TO_END );
500         bReturn = StartExecute();
501 		aSDF.Close();
502 	}
503     else{
504         printf("ERROR: Can't create file %s\n", rDestinationFile.GetBuffer() );
505     }
506 	nMode = LOCALIZE_NONE;
507 	aSDF.Close();
508     return bReturn;
509 }
510 
511 /*****************************************************************************/
512 sal_Bool SourceTreeLocalizer::MergeSingleFile(
513 	const ByteString &rPrj,
514 	const ByteString &rFile,
515 	const ByteString &rSDFFile
516 )
517 /*****************************************************************************/
518 {
519 	//printf("MergeSingleFile(%s,%s,%s)",rPrj.GetBuffer(),rFile.GetBuffer(),rSDFFile.GetBuffer());
520 	if ( !rFile.Len())
521 		return sal_True;
522 
523 	ByteString sRoot( Export::GetEnv( "SRC_ROOT" ));
524 	DirEntry aEntry( String( sRoot, RTL_TEXTENCODING_ASCII_US ));
525 	aEntry += DirEntry( String( rPrj, RTL_TEXTENCODING_ASCII_US ));
526 
527 	ByteString sDelimiter(
528 		DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
529 
530 	ByteString sCur( rFile );
531 	sCur.SearchAndReplaceAll( "\\", sDelimiter );
532 	sCur.SearchAndReplaceAll( "/", sDelimiter );
533 
534 	aEntry += DirEntry( String( sCur, RTL_TEXTENCODING_ASCII_US ));
535 	ByteString sFile( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
536 
537 	ByteString sBCur( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
538 
539 	sal_uLong nIndex = 0;
540 	ByteString sExtension( aEntry.GetExtension(), RTL_TEXTENCODING_ASCII_US );
541 	ByteString sCandidate( ExeTable[ nIndex ][ 0 ] );
542 
543 	while( !sCandidate.Equals ("NULL") && !sCandidate.Equals(sExtension) )
544 		sCandidate = ExeTable[ ++nIndex ][ 0 ];
545 
546 	if ( !sCandidate.Equals( "NULL" ) ) {
547 		if( !aEntry.Exists()) {
548 			DirEntryKind theDir=FSYS_KIND_FILE;
549 			Dir myDir( aEntry.GetPath(), theDir);
550 			DirEntry current;
551 			sal_Bool found=sal_False;
552 			for( sal_uInt16 x=0; x < myDir.Count() && !found;){
553 				current=myDir[x++];
554 				StringCompare result=current.GetName().CompareIgnoreCaseToAscii( aEntry.GetName() );
555 				if( result==COMPARE_EQUAL ){
556 					fprintf(stderr,"WARNING: %s not found\n", ByteString(aEntry.GetFull(),RTL_TEXTENCODING_ASCII_US).GetBuffer() );
557 					fprintf(stderr,"but use  %s instead \n" , ByteString(current.GetFull(), RTL_TEXTENCODING_ASCII_US).GetBuffer() );
558 					aEntry=current;
559 					found=sal_True;
560 				}
561 			}
562 			if(!found)	return sal_True;
563 
564 		}
565 
566 		DirEntry aOut( Export::GetTempFile() );
567 		ByteString sOutput;
568 		if( sOutputFile.Len() == 0 )
569 			sOutput = ByteString ( aOut.GetFull(), RTL_TEXTENCODING_ASCII_US );
570 		else
571 			sOutput = sOutputFile;
572 		ByteString sCommand( ExeTable[ nIndex ][ 1 ] );
573 		sCommand += " -i ";
574 		sCommand += ByteString( aEntry.GetName(), RTL_TEXTENCODING_ASCII_US );
575 		sCommand += " -m ";
576 		sCommand += rSDFFile;
577 		sCommand += " -o ";
578 		sCommand += sOutput;
579 		sCommand += " ";
580 		sCommand += ByteString( ExeTable[ nIndex ][ 2 ] );
581 		if ( sLanguageRestriction.Len()) {
582 			sCommand += " -l ";
583 			sCommand += sLanguageRestriction;
584 		}
585 
586 		DirEntry aPath( aEntry.GetPath());
587 		DirEntry aOldCWD;
588 		aPath.SetCWD();
589 
590 		if (system(sCommand.GetBuffer()) == -1)
591 			fprintf(stderr, "%s failed\n", sCommand.GetBuffer());
592         nFileCnt++;
593         printf(".");
594         SvFileStream aInStream( aOut.GetFull(), STREAM_READ );
595 		if ( !aInStream.IsOpen()) {
596 			fprintf( stderr,
597 				"ERROR: Unable to open file %s for reading!\n",
598 				sOutput.GetBuffer());
599 		}
600 		else {
601 			FileStat::SetReadOnlyFlag( aEntry, sal_False );
602 			String myStr2(aEntry.GetFull());
603 			String aTemp22 = String::CreateFromAscii("_tmp");
604 			myStr2.Append(aTemp22);
605 
606 			ByteString test(myStr2,RTL_TEXTENCODING_ASCII_US);
607 			SvFileStream aOutStream( myStr2, STREAM_STD_WRITE | STREAM_TRUNC );
608 			if ( !aOutStream.IsOpen()) {
609 				ByteString test2(myStr2,RTL_TEXTENCODING_ASCII_US);
610 				fprintf( stderr,"ERROR: Unable to open file %s for modification!\n", test2.GetBuffer());
611 				aInStream.Close();
612 			}
613 
614 			else {
615 				ByteString sLine;
616                 aOutStream.SetLineDelimiter( LINEEND_LF );
617 
618                 aInStream.ReadLine( sLine );
619                 while ( !aInStream.IsEof()) {
620 					aOutStream.WriteLine( sLine );
621                     aInStream.ReadLine( sLine );
622 				}
623 				aInStream.Close();
624 				aOutStream.Close();
625 
626 
627 					DirEntry myTempFile(ByteString(myStr2,RTL_TEXTENCODING_ASCII_US));		// xxx_tmp ->
628 					DirEntry myFile(ByteString(aEntry.GetFull(),RTL_TEXTENCODING_ASCII_US));// xxx
629 
630 					DirEntry oldFile(ByteString(aEntry.GetFull(),RTL_TEXTENCODING_ASCII_US));
631 
632 					if(oldFile.Kill()==ERRCODE_NONE){
633 						if(myTempFile.MoveTo(myFile)!=ERRCODE_NONE){
634 							fprintf( stderr, "ERROR: Can't rename file %s\n",ByteString(myStr2,RTL_TEXTENCODING_ASCII_US).GetBuffer());
635 						}
636 					}
637 					else{
638 						fprintf( stderr, "ERROR: Can't remove file %s\n",ByteString(aEntry.GetFull(),RTL_TEXTENCODING_ASCII_US).GetBuffer());
639 					}
640 				} // else
641 
642 				aOldCWD.SetCWD();
643 				aOut.Kill();
644 			}	// else
645 		}
646 	return sal_True;
647 }
648 /*****************************************************************************/
649 sal_Bool SourceTreeLocalizer::ExecuteMerge( )
650 /*****************************************************************************/
651 {
652 	DirEntry aEntry( Export::GetTempFile());
653 	sal_Bool bReturn = sal_True;
654 	bool bMerged = false;
655 
656 	ByteString sFileName;
657 	ByteString sCurFile;
658 	ByteString sLine;
659 	ByteString sFileKey;
660 
661 	SvFileStream aFile;
662 
663 	ByteString sOutputFileName = sOutputFile;
664 	ByteString sInpath(".");
665 	sInpath += Export::GetEnv("INPATH");
666 	ByteString sBlank("");
667 
668 	sOutputFileName.SearchAndReplaceAll( sInpath , sBlank );
669 
670 	String sDel = DirEntry::GetAccessDelimiter();
671     ByteString sBDel( sDel.GetBuffer() , sDel.Len() , RTL_TEXTENCODING_UTF8 );
672 	if( bLocal ){
673 		xub_StrLen nPos = sOutputFileName.SearchBackward( sBDel.GetChar(0) );
674 		sOutputFileName = sOutputFileName.Copy( nPos+1 , sOutputFileName.Len()-nPos-1 );
675 	}
676 	ByteStringBoolHashMap aFileHM;
677     // Read all possible files
678     while ( !aSDF.IsEof()) {
679 		aSDF.ReadLine( sLine );
680 		sFileName = sLine.GetToken( 0, '\t' );
681 		sFileName += "#";
682 		sFileName += sLine.GetToken( 1, '\t' );
683         aFileHM[sFileName]=true;
684     }
685 
686     for( ByteStringBoolHashMap::iterator iter = aFileHM.begin(); iter != aFileHM.end(); ++iter ){
687         sFileKey = iter->first;
688         aSDF.Seek( 0 );
689 		aFile.Open( aEntry.GetFull(), STREAM_STD_WRITE |STREAM_TRUNC );
690 
691         while ( !aSDF.IsEof()) {
692 		    aSDF.ReadLine( sLine );
693 		    sFileName = sLine.GetToken( 0, '\t' );
694 		    sFileName += "#";
695 		    sFileName += sLine.GetToken( 1, '\t' );
696             if( sFileName.Len() && ( sFileName.CompareTo(sFileKey) == COMPARE_EQUAL ) ){
697 		        if ( aFile.IsOpen() && sLine.Len())
698 			        aFile.WriteLine( sLine );
699             }
700         }
701         if ( aFile.IsOpen())
702 		    aFile.Close();
703 
704         ByteString sPrj( sFileKey.GetToken( 0, '#' ));
705         ByteString sFile( sFileKey.GetToken( 1, '#' ));
706 		ByteString sSDFFile( aFile.GetFileName(), RTL_TEXTENCODING_ASCII_US );
707 
708         //printf("localize test sPrj = %s , sFile = %s , sSDFFile = %s sOutputFileName = %s\n",sPrj.GetBuffer(), sFile.GetBuffer() , sSDFFile.GetBuffer() , sOutputFileName.GetBuffer() );
709 
710         // Test
711         bLocal = true;
712         // Test
713 
714         if( bLocal ){
715             sal_uInt16 nPos = sFile.SearchBackward( '\\' );
716             ByteString sTmp = sFile.Copy( nPos+1 , sFile.Len()-nPos-1 );
717             //printf("'%s'='%s'\n",sTmp.GetBuffer(), sOutputFileName.GetBuffer());
718             if( sTmp.CompareTo(sOutputFileName) == COMPARE_EQUAL ){
719 				    bMerged = true;
720 				    if ( !MergeSingleFile( sPrj, sFile, sSDFFile ))
721 					    bReturn = sal_False;
722 		    }else{
723 			    bMerged = true;
724                 //printf("MergeSingleFile('%s','%s','%s')\n",sPrj.GetBuffer(),sFile.GetBuffer(),sSDFFile.GetBuffer());
725 			    if ( !MergeSingleFile( sPrj, sFile, sSDFFile ))
726 				    bReturn = sal_False;
727 		    }
728         }
729     }
730     aEntry.Kill();
731     // If Outputfile not included in the SDF file copy it without merge
732 
733     if( bLocal && !bMerged ){
734 		DirEntry aSourceFile( sOutputFileName.GetBuffer() );
735 		FSysError aErr = aSourceFile.CopyTo( DirEntry ( sOutputFile.GetBuffer() ) , FSYS_ACTION_COPYFILE );
736 		if( aErr != FSYS_ERR_OK ){
737 			printf("ERROR: Can't copy file '%s' to '%s' %d\n",sOutputFileName.GetBuffer(),sOutputFile.GetBuffer(),sal::static_int_cast<int>(aErr));
738 		}
739 	}
740 	return bReturn;
741 
742 }
743 
744 /*****************************************************************************/
745 sal_Bool SourceTreeLocalizer::Merge( const ByteString &rSourceFile , const ByteString &rOutput )
746 /*****************************************************************************/
747 {
748     sOutputFile = rOutput;
749 	nMode = LOCALIZE_MERGE;
750 	aSDF.Open( String( rSourceFile, RTL_TEXTENCODING_ASCII_US ),
751 		STREAM_STD_READ );
752 
753 	sal_Bool bReturn = aSDF.IsOpen();
754 	if ( bReturn ) {
755 		bReturn = ExecuteMerge();
756 //		aSDF.Close();
757 	}
758     aSDF.Close();
759 	nMode = LOCALIZE_NONE;
760 	return bReturn;
761 }
762 
763 }
764 using namespace transex3;
765 
766 #define STATE_NONE		0x0000
767 #define STATE_EXPORT	0x0001
768 #define STATE_MERGE		0x0002
769 #define STATE_ISOCODE	0x0003
770 #define STATE_LANGUAGES	0x0004
771 #define STATE_FILENAME	0x0005
772 #define STATE_OUTPUT	0x0006
773 
774 /*****************************************************************************/
775 void Help()
776 /*****************************************************************************/
777 {
778 	fprintf( stdout,
779 		"localize (c)2001 by Sun Microsystems\n"
780 		"====================================\n" );
781 	fprintf( stdout,
782 		"As part of the L10N framework, localize extracts and merges translations\n"
783 		"out of and into the whole source tree.\n\n"
784 		"Syntax: localize -e -l en-US -f FileName \n"
785 		"Parameter:\n"
786 		"\t-e: Extract mode\n"
787 		"\tFileName: Output file when extract mode, input file when merge mode\n"
788 		"\tl1...ln: supported languages (\"all\" for all languages).\n"
789 	);
790 
791 	fprintf( stdout,
792 		"Valid language codes for l1...ln and f1...fn are:\n" );
793 	fprintf( stdout,
794 		"\nExample 1:\n"
795 		"==========\n"
796 		"localize -e -l en-US -f MyFile\n\n"
797 		"All strings will be extracted for language de and language en-US.\n"
798 	);
799 }
800 
801 /*****************************************************************************/
802 int Error()
803 /*****************************************************************************/
804 {
805 	Help();
806 	return 1;
807 }
808 
809 /*****************************************************************************/
810 sal_Bool CheckLanguages( ByteString &rLanguages )
811 /*****************************************************************************/
812 {
813 	ByteString sTmp( rLanguages );
814     return true;
815 }
816 
817 /*****************************************************************************/
818 #if defined(UNX) || defined(OS2)
819 int main( int argc, char *argv[] )
820 #else
821 int _cdecl main( int argc, char *argv[] )
822 #endif
823 /*****************************************************************************/
824 {
825     String sTempBase( String::CreateFromAscii( "loc" ));
826 	DirEntry::SetTempNameBase( sTempBase );
827 	sal_uInt16 nState   = STATE_NONE;
828 
829 	sal_Bool bExport    = sal_False;
830 	sal_Bool bMerge     = sal_False;
831 	bool bSkipLinks = false;
832 
833 	ByteString sLanguages;
834 	ByteString sFileName;
835 	ByteString sOutput;
836 
837     bExport = sal_True;
838 
839 	for( int i = 1; i < argc; i++ ) {
840 		ByteString sSwitch( argv[ i ] );
841         sSwitch.ToUpperAscii();
842 
843         if ( sSwitch.Equals( "-E" )) {
844 			nState = STATE_EXPORT;
845 			if ( bMerge )
846 				return Error();
847 			bExport = sal_True;
848 		}
849 		else if ( sSwitch.Equals( "-I" ) )
850 			nState = STATE_ISOCODE;
851 		else if ( sSwitch.Equals( "-L" ) )
852 			nState = STATE_LANGUAGES;
853 		else if ( sSwitch.Equals( "-F" ) )
854 			nState = STATE_FILENAME;
855 		else if ( ByteString( argv[ i ]).ToUpperAscii().Equals( "-O" ) )
856 			nState = STATE_OUTPUT;
857 		else {
858 			switch ( nState ) {
859 				case STATE_NONE:
860 					return Error();
861 				case STATE_OUTPUT:
862 					if ( sOutput.Len())
863 						return Error();
864 					sOutput = ByteString( argv[ i ] );
865 					nState = STATE_NONE;
866 				break;
867 				case STATE_LANGUAGES:
868 					if ( sLanguages.Len())
869 						return Error();
870 					sLanguages = ByteString( argv[ i ] );
871 					nState = STATE_NONE;
872 				break;
873 				case STATE_FILENAME:
874 					if ( sFileName.Len())
875 						return Error();
876 					sFileName = ByteString( argv[ i ] );
877 					nState = STATE_NONE;
878 				break;
879 				default:
880 					return Error();
881 			}
882 		}
883 	}
884 	if ( !bMerge && !bExport ) {
885 		Help();
886 		return 1;
887 	}
888 
889 	ByteString sSolarVer( Export::GetEnv( "WORK_STAMP" ));
890     ByteString sVersion( Export::GetEnv( "WORK_STAMP" ));
891 
892 	if ( !sSolarVer.Len() || !sVersion.Len()) {
893 		fprintf( stderr, "ERROR: No environment set!\n" );
894 		return 1;
895 	}
896 
897 	if ( !CheckLanguages( sLanguages ))
898 		return 2;
899 
900 	if ( !sFileName.Len()) {
901 		fprintf( stderr, "ERROR: No filename given\n" );
902 		return 3;
903 	}
904 
905     DirEntry aEntry( String( sFileName , RTL_TEXTENCODING_ASCII_US ));
906 	aEntry.ToAbs();
907 	String sFullEntry = aEntry.GetFull();
908 	ByteString sFileABS( aEntry.GetFull(), gsl_getSystemTextEncoding());
909     //printf("B %s\nA %s\n",rDestinationFile.GetBuffer(), sFile.GetBuffer());
910     sFileName = sFileABS;
911 
912     Treeconfig treeconfig;
913     vector<string> repos;
914     bool hasPwd = treeconfig.getActiveRepositories( repos );
915     if( hasPwd ) cout << "Found special path!\n";
916 
917     string minor_ext;
918     bool has_minor_ext;
919 
920     if( Export::GetEnv("UPDMINOREXT") != NULL )
921     {
922         minor_ext     = string( Export::GetEnv("UPDMINOREXT") );
923         has_minor_ext = minor_ext.size();
924     }
925     else
926         has_minor_ext = false;
927 
928     // localize through all repositories
929     for( vector<string>::iterator iter = repos.begin(); iter != repos.end() ; ++iter )
930     {
931         string curRepository;
932         if( has_minor_ext )
933             curRepository = string( Export::GetEnv("SOURCE_ROOT_DIR") ) + "/" + *iter + minor_ext;
934         else
935             curRepository = string( Export::GetEnv("SOURCE_ROOT_DIR") ) + "/" + *iter;
936         cout << "Localizing repository " << curRepository << "\n";
937         SourceTreeLocalizer aIter( ByteString( curRepository.c_str() ) , sVersion , (sOutput.Len() > 0) , bSkipLinks );
938         aIter.SetLanguageRestriction( sLanguages );
939         if ( bExport ){
940             fflush( stdout );
941             if( *iter == "ooo" )
942                 aIter.Extract( sFileName );
943             else
944             {
945                 ByteString sFileNameWithExt( sFileName );
946                 sFileNameWithExt += ByteString( "." );
947                 sFileNameWithExt += ByteString( (*iter).c_str() );
948                 aIter.Extract( sFileNameWithExt );
949             }
950             printf("\n%d files found!\n",aIter.GetFileCnt());
951         }
952     }
953     if( hasPwd )
954     {
955         string pwd;
956         Export::getCurrentDir( pwd );
957         cout << "Localizing repository " << pwd << "\n";
958         SourceTreeLocalizer aIter( ByteString( pwd.c_str() ) , sVersion , (sOutput.Len() > 0) , bSkipLinks );
959         aIter.SetLanguageRestriction( sLanguages );
960         if ( bExport ){
961             fflush( stdout );
962             aIter.Extract( sFileName );
963             printf("\n%d files found!\n",aIter.GetFileCnt());
964         }
965 
966     }
967 
968     return 0;
969 }
970 
971