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