summaryrefslogtreecommitdiff
path: root/l10ntools
diff options
context:
space:
mode:
Diffstat (limited to 'l10ntools')
-rw-r--r--l10ntools/inc/cfgmerge.hxx208
-rw-r--r--l10ntools/inc/export.hxx586
-rw-r--r--l10ntools/inc/gsicheck.hxx131
-rw-r--r--l10ntools/inc/helpmerge.hxx87
-rw-r--r--l10ntools/inc/inireader.hxx52
-rw-r--r--l10ntools/inc/l10ntools/directory.hxx54
-rw-r--r--l10ntools/inc/l10ntools/file.hxx23
-rw-r--r--l10ntools/inc/l10ntools/vosapp.hxx33
-rw-r--r--l10ntools/inc/lngmerge.hxx69
-rw-r--r--l10ntools/inc/makefile.mk51
-rw-r--r--l10ntools/inc/pch/precompiled_l10ntools.cxx32
-rw-r--r--l10ntools/inc/pch/precompiled_l10ntools.hxx35
-rw-r--r--l10ntools/inc/srciter.hxx61
-rw-r--r--l10ntools/inc/tagtest.hxx399
-rw-r--r--l10ntools/inc/tokens.h112
-rw-r--r--l10ntools/inc/treeconfig.hxx28
-rw-r--r--l10ntools/inc/utf8conv.hxx47
-rw-r--r--l10ntools/inc/wrdtrans.hxx90
-rw-r--r--l10ntools/inc/wtranode.hxx121
-rw-r--r--l10ntools/inc/wtratree.hxx162
-rw-r--r--l10ntools/inc/xmlparse.hxx553
-rw-r--r--l10ntools/inc/xmlutil.hxx9
-rw-r--r--l10ntools/inc/xrmmerge.hxx161
-rwxr-xr-xl10ntools/java/l10nconv/build.xml233
-rwxr-xr-xl10ntools/java/l10nconv/converter.MF1
-rwxr-xr-xl10ntools/java/l10nconv/documentation/readmeConverter.sxwbin0 -> 9824 bytes
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/DirtyTagWrapCheck.java85
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/DirtyTagWrapper.java252
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/Tag.java249
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/TagPair.java310
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Convert.java553
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Converter.java523
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ConverterException.java79
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataHandler.java149
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataReader.java79
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataWriter.java91
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ExtMap.java97
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/FileMaker.java87
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIReader.java250
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIWriter.java246
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIandSDFMerger.java167
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/LineErrorException.java81
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/OutputHandler.java228
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ResTypeResolver.java71
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Resolver.java98
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/SDFReader.java635
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/SDFWriter.java175
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/XLIFFReader.java745
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/XLIFFWriter.java535
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/converter/dtd/xliff.dtd391
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/languageResolver/LanguageResolver.java201
-rwxr-xr-xl10ntools/java/l10nconv/java/com/sun/star/tooling/languageResolver/lang.map41
-rwxr-xr-xl10ntools/java/l10nconv/makefile.mk39
-rwxr-xr-xl10ntools/java/receditor/build.xml173
-rw-r--r--l10ntools/java/receditor/java/transex3/controller/EditorController.java334
-rw-r--r--l10ntools/java/receditor/java/transex3/controller/Main.java10
-rw-r--r--l10ntools/java/receditor/java/transex3/model/ResourceFile.java77
-rw-r--r--l10ntools/java/receditor/java/transex3/model/SdfEntity.java211
-rw-r--r--l10ntools/java/receditor/java/transex3/model/SdfString.java192
-rw-r--r--l10ntools/java/receditor/java/transex3/view/Editor.java97
-rw-r--r--l10ntools/java/receditor/java/transex3/view/SdfTable.java24
-rwxr-xr-xl10ntools/java/receditor/makefile.mk39
-rwxr-xr-xl10ntools/java/receditor/receditor.MF1
-rw-r--r--l10ntools/layout/README27
-rw-r--r--l10ntools/layout/layoutparse.cxx139
-rw-r--r--l10ntools/layout/layoutparse.hxx55
-rw-r--r--l10ntools/layout/loc.sdf24
-rw-r--r--l10ntools/layout/makefile.mk81
-rw-r--r--l10ntools/layout/tralay.cxx403
-rw-r--r--l10ntools/layout/zoom.xml40
-rw-r--r--l10ntools/prj/build.lst10
-rw-r--r--l10ntools/prj/d.lst61
-rw-r--r--l10ntools/scripts/fast_merge.pl348
-rw-r--r--l10ntools/scripts/keyidGen.pl189
-rwxr-xr-xl10ntools/scripts/localize.pl1201
-rwxr-xr-xl10ntools/scripts/localize_old.pl1130
-rw-r--r--l10ntools/source/cfg_yy_wrapper.c2
-rw-r--r--l10ntools/source/cfglex.l232
-rw-r--r--l10ntools/source/cfgmerge.cxx886
-rw-r--r--l10ntools/source/directory.cxx276
-rw-r--r--l10ntools/source/export.cxx2660
-rw-r--r--l10ntools/source/export2.cxx742
-rw-r--r--l10ntools/source/file.cxx58
-rw-r--r--l10ntools/source/filter/merge/FCFGMerge.cfg125
-rw-r--r--l10ntools/source/filter/merge/FCFGMerge.java131
-rw-r--r--l10ntools/source/filter/merge/Manifest.mf1
-rw-r--r--l10ntools/source/filter/merge/Merger.java364
-rw-r--r--l10ntools/source/filter/merge/makefile.mk96
-rw-r--r--l10ntools/source/filter/utils/AnalyzeStartupLog.java328
-rw-r--r--l10ntools/source/filter/utils/Cache.java2449
-rw-r--r--l10ntools/source/filter/utils/ConfigHelper.java303
-rw-r--r--l10ntools/source/filter/utils/FileHelper.java766
-rw-r--r--l10ntools/source/filter/utils/Logger.java177
-rw-r--r--l10ntools/source/filter/utils/MalformedCommandLineException.java50
-rw-r--r--l10ntools/source/filter/utils/XMLHelper.java825
-rw-r--r--l10ntools/source/filter/utils/makefile.mk57
-rw-r--r--l10ntools/source/gsicheck.cxx1177
-rw-r--r--l10ntools/source/gsiconv.cxx372
-rw-r--r--l10ntools/source/help/HelpCompiler.cxx593
-rw-r--r--l10ntools/source/help/HelpCompiler.hxx320
-rw-r--r--l10ntools/source/help/HelpFileDocument.java89
-rw-r--r--l10ntools/source/help/HelpIndexerTool.java372
-rw-r--r--l10ntools/source/help/HelpLinker.cxx1173
-rw-r--r--l10ntools/source/help/compilehelp.hxx81
-rw-r--r--l10ntools/source/help/helplinker.pmk35
-rw-r--r--l10ntools/source/help/makefile.mk120
-rw-r--r--l10ntools/source/helpex.cxx299
-rw-r--r--l10ntools/source/helpmerge.cxx730
-rw-r--r--l10ntools/source/inireader.cxx132
-rw-r--r--l10ntools/source/lngex.cxx226
-rw-r--r--l10ntools/source/lngmerge.cxx360
-rw-r--r--l10ntools/source/localize.cxx986
-rw-r--r--l10ntools/source/makefile.mk210
-rw-r--r--l10ntools/source/merge.cxx445
-rw-r--r--l10ntools/source/src_yy_wrapper.c2
-rw-r--r--l10ntools/source/srciter.cxx141
-rw-r--r--l10ntools/source/srclex.l308
-rw-r--r--l10ntools/source/tagtest.cxx1577
-rw-r--r--l10ntools/source/treeconfig.cxx128
-rw-r--r--l10ntools/source/utf8conv.cxx77
-rw-r--r--l10ntools/source/wrdtrans.cxx248
-rw-r--r--l10ntools/source/wtranode.cxx111
-rw-r--r--l10ntools/source/wtratree.cxx421
-rw-r--r--l10ntools/source/xgfconv.cxx66
-rw-r--r--l10ntools/source/xmlparse.cxx1456
-rw-r--r--l10ntools/source/xrm_yy_wrapper.c2
-rw-r--r--l10ntools/source/xrmlex.l228
-rw-r--r--l10ntools/source/xrmmerge.cxx754
-rw-r--r--l10ntools/workbench/gsicheck_errors.sdf15
-rw-r--r--l10ntools/workbench/gsicheck_errors_err-.sdf11
-rw-r--r--l10ntools/workbench/gsicheck_errors_err-l.sdf2
-rw-r--r--l10ntools/workbench/gsicheck_errors_err-s.sdf9
-rw-r--r--l10ntools/workbench/gsicheck_errors_err-t.sdf9
-rw-r--r--l10ntools/workbench/gsicheck_errors_ok-.sdf5
-rw-r--r--l10ntools/workbench/gsicheck_errors_ok-l.sdf12
-rw-r--r--l10ntools/workbench/gsicheck_errors_ok-s.sdf6
-rw-r--r--l10ntools/workbench/gsicheck_errors_ok-t.sdf6
-rw-r--r--l10ntools/workbench/gsicheckcheck.btm17
138 files changed, 38520 insertions, 0 deletions
diff --git a/l10ntools/inc/cfgmerge.hxx b/l10ntools/inc/cfgmerge.hxx
new file mode 100644
index 000000000000..9f1c97f05af5
--- /dev/null
+++ b/l10ntools/inc/cfgmerge.hxx
@@ -0,0 +1,208 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: cfgmerge.hxx,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CFG_MERGE_HXX
+#define _CFG_MERGE_HXX
+
+#include <tools/string.hxx>
+#include <tools/list.hxx>
+#include <hash_map>
+
+typedef std::hash_map<ByteString , ByteString , hashByteString,equalByteString>
+ ByteStringHashMap;
+
+
+//
+// class CfgStackData
+//
+
+class CfgStackData
+{
+friend class CfgParser;
+friend class CfgExport;
+friend class CfgMerge;
+private:
+ ByteString sTagType;
+ ByteString sIdentifier;
+
+ ByteString sResTyp;
+
+ ByteString sTextTag;
+ ByteString sEndTextTag;
+
+ ByteStringHashMap sText;
+public:
+ CfgStackData( const ByteString &rTag, const ByteString &rId )
+ : sTagType( rTag ), sIdentifier( rId ) {};
+
+ ByteString &GetTagType() { return sTagType; }
+ ByteString &GetIdentifier() { return sIdentifier; }
+
+};
+
+//
+// class CfgStack
+//
+
+DECLARE_LIST( CfgStackList, CfgStackData * )
+
+class CfgStack : public CfgStackList
+{
+public:
+ CfgStack() : CfgStackList( 10, 10 ) {}
+ ~CfgStack();
+
+ ULONG Push( CfgStackData *pStackData );
+ CfgStackData *Push( const ByteString &rTag, const ByteString &rId );
+ CfgStackData *Pop() { return Remove( Count() - 1 ); }
+
+ CfgStackData *GetStackData( ULONG nPos = LIST_APPEND );
+
+ ByteString GetAccessPath( ULONG nPos = LIST_APPEND );
+};
+
+//
+// class CfgParser
+//
+
+class CfgParser
+{
+protected:
+ ByteString sCurrentResTyp;
+ ByteString sCurrentIsoLang;
+ ByteString sCurrentText;
+
+ ByteString sLastWhitespace;
+
+ CfgStack aStack;
+ CfgStackData *pStackData;
+
+ BOOL bLocalize;
+
+ virtual void WorkOnText(
+ ByteString &rText,
+ const ByteString &nLangIndex )=0;
+
+ virtual void WorkOnRessourceEnd()=0;
+
+ virtual void Output( const ByteString& rOutput )=0;
+
+ void Error( const ByteString &rError );
+
+private:
+ int ExecuteAnalyzedToken( int nToken, char *pToken );
+ std::vector<ByteString> aLanguages;
+ void AddText(
+ ByteString &rText,
+ const ByteString &rIsoLang,
+ const ByteString &rResTyp );
+
+BOOL IsTokenClosed( const ByteString &rToken );
+
+public:
+ CfgParser();
+ virtual ~CfgParser();
+
+ int Execute( int nToken, char * pToken );
+};
+
+//
+// class CfgOutputParser
+//
+
+class CfgOutputParser : public CfgParser
+{
+protected:
+ SvFileStream *pOutputStream;
+public:
+ CfgOutputParser ( const ByteString &rOutputFile );
+ virtual ~CfgOutputParser();
+};
+
+//
+// class CfgExport
+//
+
+class CfgExport : public CfgOutputParser
+{
+private:
+ ByteString sPrj;
+ ByteString sPath;
+ std::vector<ByteString> aLanguages;
+protected:
+ void WorkOnText(
+ ByteString &rText,
+ const ByteString &rIsoLang
+ );
+
+ void WorkOnRessourceEnd();
+ void Output( const ByteString& rOutput );
+public:
+ CfgExport(
+ const ByteString &rOutputFile,
+ const ByteString &rProject,
+ const ByteString &rFilePath
+ );
+ ~CfgExport();
+};
+
+//
+// class CfgMerge
+//
+
+class CfgMerge : public CfgOutputParser
+{
+private:
+ MergeDataFile *pMergeDataFile;
+ std::vector<ByteString> aLanguages;
+ ResData *pResData;
+
+ BOOL bGerman;
+ ByteString sFilename;
+ BOOL bEnglish;
+
+protected:
+ void WorkOnText(
+ ByteString &rText,
+ const ByteString &nLangIndex );
+
+ void WorkOnRessourceEnd();
+
+ void Output( const ByteString& rOutput );
+public:
+ CfgMerge(
+ const ByteString &rMergeSource,
+ const ByteString &rOutputFile,
+ ByteString &rFilename
+ );
+ ~CfgMerge();
+};
+
+#endif
diff --git a/l10ntools/inc/export.hxx b/l10ntools/inc/export.hxx
new file mode 100644
index 000000000000..6d94297c25fb
--- /dev/null
+++ b/l10ntools/inc/export.hxx
@@ -0,0 +1,586 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: export.hxx,v $
+ * $Revision: 1.27 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _EXPORT_HXX
+#define _EXPORT_HXX
+
+#ifndef L10NTOOLS_DIRECTORY_HXX
+#define L10NTOOLS_DIRECTORY_HXX
+#include <l10ntools/directory.hxx>
+#endif
+
+
+// #define MERGE_SOURCE_LANGUAGES <- To merge en-US and de resource
+
+#include <tools/string.hxx>
+#include <tools/list.hxx>
+#include <tools/stream.hxx>
+#include <tools/fsys.hxx>
+#include <osl/file.hxx>
+#include <osl/file.h>
+
+#include <hash_map> /* std::hashmap*/
+#include <iterator> /* std::iterator*/
+#include <set> /* std::set*/
+#include <vector> /* std::vector*/
+#include <queue>
+#include <string>
+
+#include <unistd.h>
+#ifdef WNT
+#include <direct.h>
+#endif
+
+#define NO_TRANSLATE_ISO "x-no-translate"
+
+#define JAPANESE_ISO "ja"
+
+
+struct eqstr{
+ BOOL operator()(const char* s1, const char* s2) const{
+ return strcmp(s1,s2)==0;
+ }
+};
+
+struct equalByteString{
+ bool operator()( const ByteString& rKey1, const ByteString& rKey2 ) const {
+ return rKey1.CompareTo( rKey2 )==COMPARE_EQUAL;
+ }
+};
+struct lessByteString{
+ bool operator()( const ByteString& rKey1, const ByteString& rKey2 ) const {
+ return rKey1.CompareTo( rKey2 )==COMPARE_LESS;
+ }
+};
+
+struct hashByteString{
+ size_t operator()( const ByteString& rName ) const{
+ std::hash< const char* > myHash;
+ return myHash( rName.GetBuffer() );
+ }
+};
+
+class PFormEntrys;
+class MergeData;
+typedef std::set<ByteString , lessByteString > ByteStringSet;
+
+typedef std::hash_map<ByteString , ByteString , hashByteString,equalByteString>
+ ByteStringHashMap;
+
+typedef std::hash_map<ByteString , bool , hashByteString,equalByteString>
+ ByteStringBoolHashMap;
+
+typedef std::hash_map<ByteString , PFormEntrys* , hashByteString,equalByteString>
+ PFormEntrysHashMap;
+
+typedef std::hash_map<ByteString , MergeData* , hashByteString,equalByteString>
+ MergeDataHashMap;
+
+#define SOURCE_LANGUAGE ByteString("en-US")
+#define LIST_REFID "LIST_REFID"
+
+typedef ByteStringHashMap ExportListEntry;
+
+DECLARE_LIST( ExportListBase, ExportListEntry * )
+
+//
+// class ExportList
+//
+
+class ExportList : public ExportListBase
+{
+private:
+ ULONG nSourceLanguageListEntryCount;
+
+public:
+ ExportList() : ExportListBase() { nSourceLanguageListEntryCount = 0; }
+ ULONG GetSourceLanguageListEntryCount() { return nSourceLanguageListEntryCount; }
+ void NewSourceLanguageListEntry() { nSourceLanguageListEntryCount++; }
+};
+
+#define REFID_NONE 0xFFFF
+
+//
+// struct ResData
+//
+
+/******************************************************************************
+* Purpose: holds mandatory data to export a single res (used with ResStack)
+******************************************************************************/
+
+#define ID_LEVEL_NULL 0x0000
+#define ID_LEVEL_AUTOID 0x0001
+#define ID_LEVEL_TEXT 0x0002
+#define ID_LEVEL_FIELDNAME 0x0003
+#define ID_LEVEL_ACCESSPATH 0x0004
+#define ID_LEVEL_IDENTIFIER 0x0005
+#define ID_LEVEL_LISTINDEX 0x0006
+
+class ResData
+{
+public:
+ ~ResData();
+ BOOL SetId( const ByteString &rId, USHORT nLevel );
+
+ USHORT nWidth;
+ USHORT nChildIndex;
+ USHORT nIdLevel;
+ BOOL bChild;
+ BOOL bChildWithText;
+
+ BOOL bText;
+ BOOL bHelpText;
+ BOOL bQuickHelpText;
+ BOOL bTitle;
+ BOOL bList;
+
+ BOOL bRestMerged;
+
+ ByteString sResTyp;
+ ByteString sId;
+ ByteString sGId;
+ ByteString sHelpId;
+ ByteString sFilename;
+
+ ByteStringHashMap sText;
+ USHORT nTextRefId;
+
+ ByteStringHashMap sHelpText;
+ USHORT nHelpTextRefId;
+
+ ByteStringHashMap sQuickHelpText;
+ USHORT nQuickHelpTextRefId;
+
+ ByteStringHashMap sTitle;
+ USHORT nTitleRefId;
+
+ ByteString sTextTyp;
+ ByteStringHashMap aFallbackData;
+ ByteStringHashMap aMergedLanguages;
+
+ ExportList *pStringList;
+ ExportList *pUIEntries;
+ ExportList *pItemList;
+ ExportList *pFilterList;
+ ExportList *pPairedList;
+
+ ByteString sPForm;
+
+ void Dump();
+ void addFallbackData( ByteString& sId , const ByteString& sText );
+ bool getFallbackData( ByteString& sId , ByteString& sText);
+
+ void addMergedLanguage( ByteString& sLang );
+ bool isMerged( ByteString& sLang );
+ ResData( const ByteString &rPF, const ByteString &rGId )
+ :
+ nWidth( 0 ),
+ nChildIndex( 0 ),
+ nIdLevel( ID_LEVEL_NULL ),
+ bChild( FALSE ),
+ bChildWithText( FALSE ),
+ bText( FALSE ),
+ bHelpText( FALSE ),
+ bQuickHelpText( FALSE ),
+ bTitle( FALSE ),
+ bList( FALSE ),
+ bRestMerged( FALSE ),
+ sGId( rGId ),
+ nTextRefId( REFID_NONE ),
+ nHelpTextRefId( REFID_NONE ),
+ nQuickHelpTextRefId( REFID_NONE ),
+ nTitleRefId( REFID_NONE ),
+ sTextTyp( "Text" ),
+ pStringList( NULL ),
+ pUIEntries( NULL ),
+ pItemList( NULL ),
+ pFilterList( NULL ),
+ pPairedList( NULL ),
+ sPForm( rPF )
+ {
+ sGId.EraseAllChars( '\r' );
+ sPForm.EraseAllChars( '\r' );
+ };
+ ResData( const ByteString &rPF, const ByteString &rGId , const ByteString &rFilename )
+ :
+ nChildIndex( 0 ),
+ nIdLevel( ID_LEVEL_NULL ),
+ bChild( FALSE ),
+ bChildWithText( FALSE ),
+ bText( FALSE ),
+ bHelpText( FALSE ),
+ bQuickHelpText( FALSE ),
+ bTitle( FALSE ),
+ bList( FALSE ),
+ bRestMerged( FALSE ),
+ sGId( rGId ),
+ sFilename( rFilename ),
+ nTextRefId( REFID_NONE ),
+ nHelpTextRefId( REFID_NONE ),
+ nQuickHelpTextRefId( REFID_NONE ),
+ nTitleRefId( REFID_NONE ),
+ sTextTyp( "Text" ),
+ pStringList( NULL ),
+ pUIEntries( NULL ),
+ pItemList( NULL ),
+ pFilterList( NULL ),
+ pPairedList( NULL ),
+ sPForm( rPF )
+
+ {
+ sGId.EraseAllChars( '\r' );
+ sPForm.EraseAllChars( '\r' );
+ };
+
+
+};
+
+
+//
+// class Export
+//
+
+/******************************************************************************
+* Purpose: syntax check and export of *.src, called from lexer
+******************************************************************************/
+
+#define LIST_NON 0x0000
+#define LIST_STRING 0x0001
+#define LIST_FILTER 0x0002
+#define LIST_ITEM 0x0004
+#define LIST_PAIRED 0x0005
+#define LIST_UIENTRIES 0x0008
+#define STRING_TYP_TEXT 0x0010
+#define STRING_TYP_HELPTEXT 0x0020
+#define STRING_TYP_QUICKHELPTEXT 0x0040
+#define STRING_TYP_TITLE 0x0080
+
+#define MERGE_MODE_NORMAL 0x0000
+#define MERGE_MODE_LIST 0x0001
+
+DECLARE_LIST( ResStack, ResData * )
+// forwards
+class WordTransformer;
+class ParserQueue;
+
+class Export
+{
+private:
+ WordTransformer *pWordTransformer;
+
+ CharSet aCharSet; // used charset in src
+
+ SvFileStream aOutput;
+
+ ResStack aResStack; // stack for parsing recursive
+
+ ByteString sActPForm; // hold cur. system
+
+ BOOL bDefine; // cur. res. in a define?
+ BOOL bNextMustBeDefineEOL; // define but no \ at lineend
+ ULONG nLevel; // res. recursiv? how deep?
+ USHORT nList; // cur. res. is String- or FilterList
+ ByteString nListLang;
+ ULONG nListIndex;
+ ULONG nListLevel;
+ bool bSkipFile;
+ ByteString sProject;
+ ByteString sRoot;
+ BOOL bEnableExport;
+ BOOL bMergeMode;
+ ByteString sMergeSrc;
+ ByteString sLastListLine;
+ BOOL bError; // any errors while export?
+ BOOL bReadOver;
+ BOOL bDontWriteOutput;
+ ByteString sLastTextTyp;
+ static bool isInitialized;
+ ByteString sFilename;
+
+
+public:
+ ParserQueue* pParseQueue; // public ?
+ static ByteString sLanguages; // public ?
+ static ByteString sForcedLanguages; // public ?
+
+
+ static bool skipProject( ByteString sPrj ) ;
+ static void InitLanguages( bool bMergeMode = false );
+ static void InitForcedLanguages( bool bMergeMode = false );
+ static std::vector<ByteString> GetLanguages();
+ static std::vector<ByteString> GetForcedLanguages();
+
+ static void SetLanguages( std::vector<ByteString> val );
+ static void RemoveUTF8ByteOrderMarker( ByteString &rString );
+ static bool hasUTF8ByteOrderMarker( const ByteString &rString );
+ static void RemoveUTF8ByteOrderMarkerFromFile( const ByteString &rFilename );
+ static bool fileHasUTF8ByteOrderMarker( const ByteString &rString );
+ static ByteString GetIsoLangByIndex( USHORT nIndex );
+ static void QuotHTML( ByteString &rString );
+ static bool CopyFile( const ByteString& source , const ByteString& dest );
+
+ static void QuotHTMLXRM( ByteString &rString );
+ static void UnquotHTML( ByteString &rString );
+
+ static const char* GetEnv( const char *pVar );
+ static int getCurrentDirectory( rtl::OUString& base_fqurl , rtl::OUString& base );
+
+ static bool isSourceLanguage( const ByteString &sLanguage );
+ static bool isAllowed( const ByteString &sLanguage );
+
+ static bool LanguageAllowed( const ByteString &nLanguage );
+ static void Languages( std::vector<ByteString>::const_iterator& begin , std::vector<ByteString>::const_iterator& end );
+ static void getRandomName( const ByteString& sPrefix , ByteString& sRandStr , const ByteString& sPostfix );
+ static void getRandomName( ByteString& sRandStr );
+ static void getCurrentDir( std::string& dir );
+
+ static void replaceEncoding( ByteString& rString );
+
+ static ByteString GetFallbackLanguage( const ByteString nLanguage );
+ static void FillInFallbacks( ResData *pResData );
+ static void FillInListFallbacks( ExportList *pList, const ByteString &nSource, const ByteString &nFallback );
+ static ByteString GetTimeStamp();
+ static BOOL ConvertLineEnds( ByteString sSource, ByteString sDestination );
+ static ByteString GetNativeFile( ByteString sSource );
+ static DirEntry GetTempFile();
+
+ static void DumpExportList( ByteString& sListName , ExportList& aList );
+ static ByteString DumpMap( ByteString& sMapName , ByteStringHashMap& aMap );
+
+private:
+ static std::vector<ByteString> aLanguages;
+ static std::vector<ByteString> aForcedLanguages;
+
+ BOOL ListExists( ResData *pResData, USHORT nLst );
+
+ BOOL WriteData( ResData *pResData, BOOL bCreateNew = FALSE );// called befor dest. cur ResData
+ BOOL WriteExportList( ResData *pResData, ExportList *pExportList,
+ const ByteString &rTyp, BOOL bCreateNew = FALSE );
+
+ ByteString MergePairedList( ByteString& sLine , ByteString& sText );
+
+ ByteString FullId(); // creates cur. GID
+
+ bool PairedListFallback( ByteString& sText , ResData& aResData );
+
+ ByteString GetPairedListID ( const ByteString& sText );
+ ByteString GetPairedListString ( const ByteString& sText );
+ ByteString StripList ( const ByteString& sText );
+
+ void UnmergeUTF8( ByteString& sOrig );
+ void InsertListEntry( const ByteString &rText, const ByteString &rLine );
+ void CleanValue( ByteString &rValue );
+ ByteString GetText( const ByteString &rSource, int nToken );
+
+ BOOL PrepareTextToMerge( ByteString &rText, USHORT nTyp,
+ ByteString &nLangIndex, ResData *pResData );
+
+ void MergeRest( ResData *pResData, USHORT nMode = MERGE_MODE_NORMAL );
+ void ConvertMergeContent( ByteString &rText );
+
+ void WriteToMerged( const ByteString &rText , bool bSDFContent );
+ void SetChildWithText();
+
+ void CutComment( ByteString &rText );
+
+public:
+ Export( const ByteString &rOutput, BOOL bWrite,
+ const ByteString &rPrj, const ByteString &rPrjRoot , const ByteString& rFile );
+ Export( const ByteString &rOutput, BOOL bWrite,
+ const ByteString &rPrj, const ByteString &rPrjRoot,
+ const ByteString &rMergeSource , const ByteString& rFile );
+ ~Export();
+
+ void Init();
+ int Execute( int nToken, const char * pToken ); // called from lexer
+ void SetError() { bError = TRUE; }
+ BOOL GetError() { return bError; }
+};
+
+
+//
+// class PFormEntrys
+//
+
+/******************************************************************************
+* Purpose: holds information of data to merge (one pform)
+******************************************************************************/
+
+class PFormEntrys : public ByteString
+{
+friend class MergeDataFile;
+private:
+ ByteString sHelpText; // empty string
+ ByteStringHashMap sText;
+ ByteStringBoolHashMap bTextFirst;
+ ByteStringHashMap sQuickHelpText;
+ ByteStringBoolHashMap bQuickHelpTextFirst;
+ ByteStringHashMap sTitle;
+ ByteStringBoolHashMap bTitleFirst;
+
+public:
+ PFormEntrys( const ByteString &rPForm ) : ByteString( rPForm ) {};
+ ByteString Dump();
+ void InsertEntry(
+ const ByteString &nId ,
+ const ByteString &rText,
+ const ByteString &rQuickHelpText,
+ const ByteString &rTitle
+ )
+ {
+
+ sText[ nId ] = rText;
+ bTextFirst[ nId ] = true;
+ sQuickHelpText[ nId ] = rQuickHelpText;
+ bQuickHelpTextFirst[ nId ] = true;
+ sTitle[ nId ] = rTitle;
+ bTitleFirst[ nId ] = true;
+ }
+ BOOL GetText( ByteString &rReturn, USHORT nTyp, const ByteString &nLangIndex, BOOL bDel = FALSE );
+};
+
+//
+// class MergeData
+//
+
+/******************************************************************************
+* Purpose: holds information of data to merge (one ressource)
+******************************************************************************/
+
+class MergeDataFile;
+
+class MergeData
+{
+friend class MergeDataFile;
+private:
+ ByteString sTyp;
+ ByteString sGID;
+ ByteString sLID;
+ ByteString sFilename;
+ PFormEntrysHashMap aMap;
+public:
+ MergeData( const ByteString &rTyp, const ByteString &rGID, const ByteString &rLID , const ByteString &rFilename )
+ : sTyp( rTyp ), sGID( rGID ), sLID( rLID ) , sFilename( rFilename ) {};
+ ~MergeData();
+ PFormEntrys* InsertEntry( const ByteString &rPForm );
+ PFormEntrys* GetPFormEntrys( ResData *pResData );
+
+ void Insert( const ByteString& rPFO , PFormEntrys* pfEntrys );
+ PFormEntrys* GetPFObject( const ByteString& rPFO );
+
+ ByteString Dump();
+ BOOL operator==( ResData *pData );
+};
+
+//
+// class MergeDataFile
+//
+
+/******************************************************************************
+* Purpose: holds information of data to merge
+******************************************************************************/
+
+class MergeDataFile
+{
+private:
+ BOOL bErrorLog;
+ ByteString sErrorLog;
+ SvFileStream aErrLog;
+ ByteStringSet aLanguageSet;
+ MergeDataHashMap aMap;
+ ByteStringHashMap aLanguageMap;
+ std::vector<ByteString> aLanguageList;
+ ByteStringHashMap aFilenames;
+
+
+public:
+ MergeDataFile( const ByteString &rFileName, const ByteString& rFile , BOOL bErrLog, CharSet aCharSet, bool bCaseSensitive = false );
+ ~MergeDataFile();
+
+
+ std::vector<ByteString> GetLanguages();
+ MergeData *GetMergeData( ResData *pResData , bool bCaseSensitve = false );
+
+ PFormEntrys *GetPFormEntrys( ResData *pResData );
+ PFormEntrys *GetPFormEntrysCaseSensitive( ResData *pResData );
+
+ void InsertEntry( const ByteString &rTYP, const ByteString &rGID, const ByteString &rLID,
+ const ByteString &rPFO,
+ const ByteString &nLang , const ByteString &rTEXT,
+ const ByteString &rQHTEXT, const ByteString &rTITLE ,
+ const ByteString &sFilename , bool bCaseSensitive
+ );
+ static USHORT GetLangIndex( USHORT nId );
+ static ByteString CreateKey( const ByteString& rTYP , const ByteString& rGID , const ByteString& rLID , const ByteString& rFilename , bool bCaseSensitive = false );
+
+ ByteString Dump();
+ void WriteError( const ByteString &rLine );
+};
+
+
+class QueueEntry
+{
+public:
+ QueueEntry( int nTypVal , ByteString sLineVal ): nTyp( nTypVal ) , sLine( sLineVal ){};
+ int nTyp;
+ ByteString sLine;
+};
+
+class ParserQueue
+{
+public:
+
+ ParserQueue( Export& aExportObj );
+ ~ParserQueue();
+
+ inline void Push( const QueueEntry& aEntry );
+ bool bCurrentIsM; // public ?
+ bool bNextIsM; // public ?
+ bool bLastWasM; // public ?
+ bool bMflag; // public ?
+
+ void Close();
+private:
+ // Future / Next
+ std::queue<QueueEntry>* aQueueNext;
+ // Current
+ std::queue<QueueEntry>* aQueueCur;
+ // Ref
+ std::queue<QueueEntry>* aQref;
+
+ Export& aExport;
+ bool bStart;
+ bool bStartNext;
+
+ inline void Pop( std::queue<QueueEntry>& aQueue );
+
+};
+#endif
+
diff --git a/l10ntools/inc/gsicheck.hxx b/l10ntools/inc/gsicheck.hxx
new file mode 100644
index 000000000000..13debcfc7106
--- /dev/null
+++ b/l10ntools/inc/gsicheck.hxx
@@ -0,0 +1,131 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: gsicheck.hxx,v $
+ * $Revision: 1.8.22.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _GSICHECK_HXX_
+#define _GSICHECK_HXX_
+
+#include "tagtest.hxx"
+
+//
+// class GSILine
+//
+enum LineFormat { FORMAT_GSI, FORMAT_SDF, FORMAT_UNKNOWN };
+
+class GSILine : public ByteString
+{
+private:
+
+ ParserMessageList aMessages;
+ LineFormat aFormat;
+ ULONG nLineNumber;
+
+ ByteString aUniqId;
+ ByteString aLineType;
+ ByteString aLangId;
+ ByteString aText;
+ ByteString aQuickHelpText;
+ ByteString aTitle;
+
+ BOOL bOK;
+ BOOL bFixed;
+
+ void ReassembleLine();
+
+public:
+ GSILine( const ByteString &rLine, ULONG nLine );
+ LineFormat GetLineFormat() const { return aFormat; }
+ ULONG GetLineNumber() const { return nLineNumber; }
+
+ ByteString const GetUniqId() const { return aUniqId; }
+ ByteString const GetLineType() const { return aLineType; }
+ ByteString const GetLanguageId() const { return aLangId; }
+ ByteString const GetText() const { return aText; }
+ String const GetUText() const { return String( aText, RTL_TEXTENCODING_UTF8 ); }
+ ByteString const GetQuickHelpText() const { return aQuickHelpText; }
+ ByteString const GetTitle() const { return aTitle; }
+
+ void SetUText( String &aNew ) { aText = ByteString( aNew, RTL_TEXTENCODING_UTF8 ); ReassembleLine(); }
+ void SetText( ByteString &aNew ) { aText = aNew; ReassembleLine(); }
+ void SetQuickHelpText( ByteString &aNew ) { aQuickHelpText = aNew; ReassembleLine(); }
+ void SetTitle( ByteString &aNew ) { aTitle = aNew; ReassembleLine(); }
+
+ ParserMessageList* GetMessageList() { return &aMessages; };
+ BOOL HasMessages(){ return ( aMessages.Count() > 0 ); };
+
+ BOOL IsOK() const { return bOK; }
+ void NotOK();
+
+ BOOL IsFixed() const { return bFixed; }
+ void SetFixed() { bFixed = TRUE; };
+};
+
+//
+// class GSIBlock
+//
+
+DECLARE_LIST( GSIBlock_Impl, GSILine * )
+
+class LazySvFileStream;
+
+class GSIBlock : public GSIBlock_Impl
+{
+private:
+ GSILine *pSourceLine;
+ GSILine *pReferenceLine;
+ void PrintList( ParserMessageList *pList, ByteString aPrefix, GSILine *pLine );
+ BOOL bPrintContext;
+ BOOL bCheckSourceLang;
+ BOOL bCheckTranslationLang;
+ BOOL bReference;
+ BOOL bAllowKeyIDs;
+ BOOL bAllowSuspicious;
+
+ BOOL bHasBlockError;
+
+ BOOL IsUTF8( const ByteString &aTestee, BOOL bFixTags, USHORT &nErrorPos, ByteString &aErrorMsg, BOOL &bHasBeenFixed, ByteString &aFixed ) const;
+ BOOL TestUTF8( GSILine* pTestee, BOOL bFixTags );
+ BOOL HasSuspiciousChars( GSILine* pTestee, GSILine* pSource );
+
+public:
+ GSIBlock( BOOL PbPrintContext, BOOL bSource, BOOL bTrans, BOOL bRef, BOOL bAllowKID, BOOL bAllowSusp );
+ ~GSIBlock();
+ void PrintMessage( ByteString aType, ByteString aMsg, ByteString aPrefix, ByteString aContext, ULONG nLine, ByteString aUniqueId = ByteString() );
+ void PrintError( ByteString aMsg, ByteString aPrefix, ByteString aContext, ULONG nLine, ByteString aUniqueId = ByteString() );
+ void InsertLine( GSILine* pLine, const ByteString aSourceLang);
+ void SetReferenceLine( GSILine* pLine );
+ BOOL CheckSyntax( ULONG nLine, BOOL bRequireSourceLine, BOOL bFixTags );
+
+ void WriteError( LazySvFileStream &aErrOut, BOOL bRequireSourceLine );
+ void WriteCorrect( LazySvFileStream &aOkOut, BOOL bRequireSourceLine );
+ void WriteFixed( LazySvFileStream &aFixOut, BOOL bRequireSourceLine );
+};
+
+#endif
+
diff --git a/l10ntools/inc/helpmerge.hxx b/l10ntools/inc/helpmerge.hxx
new file mode 100644
index 000000000000..0ebfa7ed62a9
--- /dev/null
+++ b/l10ntools/inc/helpmerge.hxx
@@ -0,0 +1,87 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: helpmerge.hxx,v $
+ * $Revision: 1.12 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// local includes
+#include "export.hxx"
+#include "xmlparse.hxx"
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/strbuf.hxx>
+#include <memory> /* auto_ptr */
+#include "tools/isofallback.hxx"
+
+#define MOVEFILE_REPLACE_EXISTING 0x01
+
+/// This Class is responsible for extracting/merging OpenOffice XML Helpfiles
+class HelpParser
+{
+private:
+ ByteString sHelpFile;
+ bool bUTF8;
+ bool bHasInputList;
+
+/// Copy fallback language String (ENUS,DE) into position of the numeric language iso code
+/// @PRECOND 0 < langIdx_in < MAX_IDX
+ static void FillInFallbacks( LangHashMap& rElem_out, ByteString sLangIdx_in );
+
+/// Debugmethod, prints the content of the map to stdout
+ static void Dump( LangHashMap* rElem_in , const ByteString sKey_in );
+
+/// Debugmethod, prints the content of the map to stdout
+ static void Dump( XMLHashMap* rElem_in ) ;
+
+
+
+public:
+ HelpParser( const ByteString &rHelpFile, bool bUTF8 , bool bHasInputList );
+ ~HelpParser(){};
+
+/// Method creates/append a SDF file with the content of a parsed XML file
+/// @PRECOND rHelpFile is valid
+ static bool CreateSDF( const ByteString &rSDFFile_in, const ByteString &rPrj_in, const ByteString &rRoot_in,
+ const ByteString &sHelpFile, XMLFile *pXmlFile, const ByteString &rGsi1 );
+
+ static void parse_languages( std::vector<ByteString>& aLanguages , MergeDataFile& aMergeDataFile );
+
+/// Method merges the String from the SDFfile into XMLfile. Both Strings must
+/// point to existing files.
+ bool Merge( const ByteString &rSDFFile_in, const ByteString &rDestinationFile_in , ByteString& sLanguage , MergeDataFile& aMergeDataFile );
+ bool Merge( const ByteString &rSDFFile, const ByteString &rPathX , const ByteString &rPathY , bool bISO
+ , const std::vector<ByteString>& aLanguages , MergeDataFile& aMergeDataFile , bool bCreateDir );
+
+private:
+ static ByteString makeAbsolutePath( const ByteString& sHelpFile , const ByteString& rRoot_in );
+
+ ByteString GetOutpath( const ByteString& rPathX , const ByteString& sCur , const ByteString& rPathY );
+ bool MergeSingleFile( XMLFile* file , MergeDataFile& aMergeDataFile , const ByteString& sLanguage , ByteString sPath );
+
+ void Process( LangHashMap* aLangHM , const ByteString& sCur , ResData *pResData , MergeDataFile& aMergeDataFile );
+ void ProcessHelp( LangHashMap* aLangHM , const ByteString& sCur , ResData *pResData , MergeDataFile& aMergeDataFile );
+ void MakeDir( const ByteString& sPath );
+};
diff --git a/l10ntools/inc/inireader.hxx b/l10ntools/inc/inireader.hxx
new file mode 100644
index 000000000000..0861290adf9f
--- /dev/null
+++ b/l10ntools/inc/inireader.hxx
@@ -0,0 +1,52 @@
+#include <string>
+#include <hash_map>
+#include <unicode/regex.h>
+
+using namespace std;
+
+namespace transex3
+{
+
+struct eqstr
+{
+ bool operator()( const string s1 , const string s2) const
+ {
+ return s1.compare( s2 ) == 0;
+ }
+};
+
+typedef std::hash_map< string , string > stringmap;
+typedef std::hash_map< string, stringmap* > INImap;
+
+class INIreader
+{
+ private:
+ UErrorCode section_status;
+ UErrorCode parameter_status;
+ RegexMatcher* section_match;
+ RegexMatcher* parameter_match;
+
+ public:
+ INIreader(): section_status ( U_ZERO_ERROR ) ,
+ parameter_status ( U_ZERO_ERROR )
+ {
+ section_match = new RegexMatcher ( "^\\s*\\[([a-zA-Z0-9]*)\\].*" , 0 , section_status );
+ parameter_match = new RegexMatcher ( "^\\s*([a-zA-Z0-9]*)\\s*=\\s*([a-zA-Z0-9 ]*).*" , 0 , parameter_status ) ;
+ }
+ ~INIreader()
+ {
+ delete section_match;
+ delete parameter_match;
+ }
+ // open "filename", fill hash_map with sections / paramaters
+ bool read( INImap& myMap , string& filename );
+
+ private:
+ bool is_section( string& line , string& section_str );
+ bool is_parameter( string& line , string& parameter_key , string& parameter_value );
+ inline void check_status( UErrorCode status );
+ inline void toStlString ( const UnicodeString& str, string& stl_str );
+ inline void trim( string& str );
+};
+
+}
diff --git a/l10ntools/inc/l10ntools/directory.hxx b/l10ntools/inc/l10ntools/directory.hxx
new file mode 100644
index 000000000000..6b71f59435f7
--- /dev/null
+++ b/l10ntools/inc/l10ntools/directory.hxx
@@ -0,0 +1,54 @@
+#include <vector>
+#include <algorithm>
+#include <rtl/ustring.hxx>
+#include <tools/string.hxx>
+
+#ifdef WNT
+#else
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#endif
+
+#include <stdio.h>
+
+#ifndef L10NTOOLS_FILE_HXX
+#define L10NTOOLS_FILE_HXX
+#include <l10ntools/file.hxx>
+#endif
+
+namespace transex{
+
+class Directory
+{
+ private:
+ rtl::OUString sDirectoryName;
+ rtl::OUString sFullName;
+ bool bSkipLinks;
+
+ std::vector<Directory> aDirVec;
+ std::vector<File> aFileVec;
+
+ public:
+ std::vector<Directory> getSubDirectories() { return aDirVec; }
+ std::vector<File> getFiles() { return aFileVec; }
+
+ void readDirectory();
+ void readDirectory( const rtl::OUString& sFullpath );
+ void scanSubDir( int nLevels = 0 );
+
+ rtl::OUString getDirectoryName() { return sDirectoryName; }
+ rtl::OUString getFullName() { return sFullName ; }
+ void setSkipLinks( bool is_skipped );
+
+ void dump();
+ Directory(){};
+
+ Directory( const rtl::OUString sFullPath );
+ Directory( const rtl::OUString sFullPath , const rtl::OUString sEntry ) ;
+ Directory( const ByteString sFullPath );
+
+ static bool lessDir ( const Directory& rKey1, const Directory& rKey2 ) ;
+};
+
+}
diff --git a/l10ntools/inc/l10ntools/file.hxx b/l10ntools/inc/l10ntools/file.hxx
new file mode 100644
index 000000000000..e3a1a46b4ee8
--- /dev/null
+++ b/l10ntools/inc/l10ntools/file.hxx
@@ -0,0 +1,23 @@
+#include "rtl/ustring.hxx"
+
+namespace transex
+{
+
+class File
+{
+ private:
+ rtl::OUString sFileName;
+ rtl::OUString sFullName;
+
+ public:
+ rtl::OUString getFileName(){ return sFileName; }
+ rtl::OUString getFullName(){ return sFullName; }
+
+ File( const rtl::OUString sFile );
+ File( const rtl::OUString sFullName , const rtl::OUString sFile );
+
+ static bool lessFile ( const File& rKey1, const File& rKey2 );
+
+};
+
+}
diff --git a/l10ntools/inc/l10ntools/vosapp.hxx b/l10ntools/inc/l10ntools/vosapp.hxx
new file mode 100644
index 000000000000..49e10e15e3d4
--- /dev/null
+++ b/l10ntools/inc/l10ntools/vosapp.hxx
@@ -0,0 +1,33 @@
+#ifndef VOSAPP_HXX
+#define VOSAPP_HXX
+
+#include <sal/main.h>
+#include <tools/solar.h>
+#include <tools/string.hxx>
+#include <vos/process.hxx>
+
+// Mininmal vcl/svapp compatibility without vcl dependence
+class Application
+{
+public:
+ USHORT GetCommandLineParamCount();
+ XubString GetCommandLineParam( USHORT nParam );
+ virtual void Main() = 0;
+};
+
+// Urg: Cut & Paste from svapp.cxx: we don't want to depend on vcl
+USHORT Application::GetCommandLineParamCount()
+{
+ vos::OStartupInfo aStartInfo;
+ return (USHORT)aStartInfo.getCommandArgCount();
+}
+
+XubString Application::GetCommandLineParam( USHORT nParam )
+{
+ vos::OStartupInfo aStartInfo;
+ rtl::OUString aParam;
+ aStartInfo.getCommandArg( nParam, aParam );
+ return XubString( aParam );
+}
+
+#endif /* VOSAPP_HXX */
diff --git a/l10ntools/inc/lngmerge.hxx b/l10ntools/inc/lngmerge.hxx
new file mode 100644
index 000000000000..502889b27aa9
--- /dev/null
+++ b/l10ntools/inc/lngmerge.hxx
@@ -0,0 +1,69 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: lngmerge.hxx,v $
+ * $Revision: 1.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+// local includes
+#include "export.hxx"
+
+DECLARE_LIST( LngLineList, ByteString * )
+
+#define LNG_OK 0x0000
+#define LNG_FILE_NOTFOUND 0x0001
+#define LNG_COULD_NOT_OPEN 0x0002
+#define SDF_OK 0x0003
+#define SDF_FILE_NOTFOUND 0x0004
+#define SDF_COULD_NOT_OPEN 0x0005
+
+//
+// class LngParser
+//
+
+class LngParser
+{
+private:
+ USHORT nError;
+ LngLineList *pLines;
+ ByteString sSource;
+ BOOL bDBIsUTF8;
+ BOOL bULF;
+ bool bQuiet;
+ std::vector<ByteString> aLanguages;
+
+ void FillInFallbacks( ByteStringHashMap Text );
+ bool isNextGroup( ByteString &sGroup_out , ByteString &sLine_in);
+ void ReadLine( const ByteString &sLine_in , ByteStringHashMap &rText_inout );
+ void WriteSDF( SvFileStream &aSDFStream , ByteStringHashMap &rText_inout ,
+ const ByteString &rPrj ,
+ const ByteString &rRoot , const ByteString &sActFileName , const ByteString &sID );
+public:
+ LngParser( const ByteString &rLngFile, BOOL bUTF8, BOOL bULFFormat, bool bQuiet_in );
+ ~LngParser();
+
+ BOOL CreateSDF( const ByteString &rSDFFile, const ByteString &rPrj, const ByteString &rRoot );
+ BOOL Merge( const ByteString &rSDFFile, const ByteString &rDestinationFile , const ByteString &rPrj );
+};
diff --git a/l10ntools/inc/makefile.mk b/l10ntools/inc/makefile.mk
new file mode 100644
index 000000000000..6a704d63e48f
--- /dev/null
+++ b/l10ntools/inc/makefile.mk
@@ -0,0 +1,51 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..
+
+PRJNAME=l10ntools
+TARGET=inc
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+# --- Targets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.IF "$(ENABLE_PCH)"!=""
+ALLTAR : \
+ $(SLO)$/precompiled.pch \
+ $(SLO)$/precompiled_ex.pch
+
+.ENDIF # "$(ENABLE_PCH)"!=""
+
diff --git a/l10ntools/inc/pch/precompiled_l10ntools.cxx b/l10ntools/inc/pch/precompiled_l10ntools.cxx
new file mode 100644
index 000000000000..b6cac813375f
--- /dev/null
+++ b/l10ntools/inc/pch/precompiled_l10ntools.cxx
@@ -0,0 +1,32 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: precompiled_transex3.cxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_l10ntools.hxx"
+
diff --git a/l10ntools/inc/pch/precompiled_l10ntools.hxx b/l10ntools/inc/pch/precompiled_l10ntools.hxx
new file mode 100644
index 000000000000..2ed3c72ad4ee
--- /dev/null
+++ b/l10ntools/inc/pch/precompiled_l10ntools.hxx
@@ -0,0 +1,35 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: precompiled_transex3.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): Generated on 2006-09-01 17:50:15.326479
+
+#ifdef PRECOMPILED_HEADERS
+#endif
+
diff --git a/l10ntools/inc/srciter.hxx b/l10ntools/inc/srciter.hxx
new file mode 100644
index 000000000000..7f80074cd651
--- /dev/null
+++ b/l10ntools/inc/srciter.hxx
@@ -0,0 +1,61 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: srciter.hxx,v $
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef L10NTOOLS_DIRECTORY_HXX
+#define L10NTOOLS_DIRECTORY_HXX
+#include <l10ntools/directory.hxx>
+#endif
+
+// class SourceTreeIterator
+//
+
+class SourceTreeIterator
+{
+private:
+ transex::Directory aRootDirectory;
+ bool bInExecute;
+
+ void ExecuteDirectory( transex::Directory& pDirectory );
+
+protected:
+ bool bLocal;
+ bool bSkipLinks;
+
+public:
+ SourceTreeIterator( const ByteString &rRootDirectory, const ByteString &rVersion , bool bLocal_in = false);
+ virtual ~SourceTreeIterator();
+
+ BOOL StartExecute();
+ void EndExecute();
+
+ virtual void OnExecuteDirectory( const rtl::OUString &rDirectory );
+};
+
+
diff --git a/l10ntools/inc/tagtest.hxx b/l10ntools/inc/tagtest.hxx
new file mode 100644
index 000000000000..811c4bf0e164
--- /dev/null
+++ b/l10ntools/inc/tagtest.hxx
@@ -0,0 +1,399 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: tagtest.hxx,v $
+ * $Revision: 1.12 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _TAGTEST_HXX_
+#define _TAGTEST_HXX_
+
+#include <tools/string.hxx>
+#include <tools/list.hxx>
+#include <hash_map> /* std::hashmap*/
+
+class GSILine;
+
+typedef USHORT TokenId;
+
+#define TOK_INVALIDPOS USHORT( 0xFFFF )
+
+class ParserMessage;
+
+DECLARE_LIST( Impl_ParserMessageList, ParserMessage* )
+class ParserMessageList;
+
+
+struct equalByteString{
+ bool operator()( const ByteString& rKey1, const ByteString& rKey2 ) const {
+ return rKey1.CompareTo( rKey2 )==COMPARE_EQUAL;
+ }
+};
+struct lessByteString{
+ bool operator()( const ByteString& rKey1, const ByteString& rKey2 ) const {
+ return rKey1.CompareTo( rKey2 )==COMPARE_LESS;
+ }
+};
+
+struct hashByteString{
+ size_t operator()( const ByteString& rName ) const{
+ std::hash< const char* > myHash;
+ return myHash( rName.GetBuffer() );
+ }
+};
+
+
+
+typedef std::hash_map<ByteString , String , hashByteString,equalByteString>
+ StringHashMap;
+
+class TokenInfo
+{
+private:
+ void SplitTag( ParserMessageList &rErrorList );
+
+ String aTagName;
+ StringHashMap aProperties;
+ BOOL bClosed; // tag is closed <sdnf/>
+ BOOL bCloseTag; // tag is close Tag </sdnf>
+
+
+ BOOL bIsBroken;
+ BOOL bHasBeenFixed;
+ BOOL bDone;
+
+public:
+
+ String aTokenString;
+ TokenId nId;
+ USHORT nPos; // Position in String
+
+ TokenInfo():bClosed(FALSE),bCloseTag(FALSE),bIsBroken(FALSE),bHasBeenFixed(FALSE),bDone(FALSE),nId( 0 ){;}
+explicit TokenInfo( TokenId pnId, USHORT nP ):bClosed(FALSE),bCloseTag(FALSE),bIsBroken(FALSE),bHasBeenFixed(FALSE),bDone(FALSE),nId( pnId ),nPos(nP){;}
+explicit TokenInfo( TokenId pnId, USHORT nP, String paStr ):bClosed(FALSE),bCloseTag(FALSE),bIsBroken(FALSE),bHasBeenFixed(FALSE),bDone(FALSE),aTokenString( paStr ),nId( pnId ),nPos(nP) {;}
+explicit TokenInfo( TokenId pnId, USHORT nP, String paStr, ParserMessageList &rErrorList );
+
+ String GetTagName() const;
+
+ String MakeTag() const;
+
+ /**
+ Is the property to be ignored or does it have the default value anyways
+ **/
+ BOOL IsPropertyRelevant( const ByteString &aName, const String &aValue ) const;
+ BOOL IsPropertyValueValid( const ByteString &aName, const String &aValue ) const;
+ /**
+ Does the property contain the same value for all languages
+ e.g.: the href in a link tag
+ **/
+ BOOL IsPropertyInvariant( const ByteString &aName, const String &aValue ) const;
+ /**
+ a subset of IsPropertyInvariant but containing only those that are fixable
+ we dont wat to fix e.g.: ahelp :: visibility
+ **/
+ BOOL IsPropertyFixable( const ByteString &aName ) const;
+ BOOL MatchesTranslation( TokenInfo& rInfo, BOOL bGenErrors, ParserMessageList &rErrorList, BOOL bFixTags = FALSE ) const;
+
+ BOOL IsDone() const { return bDone; }
+ void SetDone( BOOL bNew = TRUE ) { bDone = bNew; }
+
+ BOOL HasBeenFixed() const { return bHasBeenFixed; }
+ void SetHasBeenFixed( BOOL bNew = TRUE ) { bHasBeenFixed = bNew; }
+};
+
+
+class ParserMessageList : public Impl_ParserMessageList
+{
+public:
+ void AddError( USHORT nErrorNr, ByteString aErrorText, const TokenInfo &rTag );
+ void AddWarning( USHORT nErrorNr, ByteString aErrorText, const TokenInfo &rTag );
+
+ BOOL HasErrors();
+};
+
+
+#define TAG_GROUPMASK 0xF000
+#define TAG_GROUPSHIFT 12
+
+#define TAG_GROUP( nTag ) (( nTag & TAG_GROUPMASK ) >> TAG_GROUPSHIFT )
+#define TAG_NOGROUP( nTag ) ( nTag & ~TAG_GROUPMASK ) // ~ = Bitweises NOT
+
+#define TAG_NOMORETAGS 0x0
+
+#define TAG_GROUP_FORMAT 0x1
+#define TAG_ON 0x100
+#define TAG_BOLDON ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x001 )
+#define TAG_BOLDOFF ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | 0x001 )
+#define TAG_ITALICON ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x002 )
+#define TAG_ITALICOFF ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | 0x002 )
+#define TAG_UNDERLINEON ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x004 )
+#define TAG_UNDERLINEOFF ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | 0x004 )
+
+#define TAG_GROUP_NOTALLOWED 0x2
+#define TAG_HELPID ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x001 )
+#define TAG_MODIFY ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x002 )
+#define TAG_REFNR ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x004 )
+
+#define TAG_GROUP_STRUCTURE 0x3
+#define TAG_NAME ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x001 )
+#define TAG_HREF ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x002 )
+#define TAG_AVIS ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x004 )
+#define TAG_AHID ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x008 )
+
+#define TAG_TITEL ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x020 )
+#define TAG_KEY ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x040 )
+#define TAG_INDEX ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x080 )
+
+#define TAG_REFSTART ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x100 )
+
+#define TAG_GRAPHIC ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x200 )
+#define TAG_NEXTVERSION ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x400 )
+
+#define TAG_GROUP_SYSSWITCH 0x4
+#define TAG_WIN ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x001 )
+#define TAG_UNIX ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x002 )
+#define TAG_MAC ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x004 )
+#define TAG_OS2 ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x008 )
+
+#define TAG_GROUP_PROGSWITCH 0x5
+#define TAG_WRITER ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x001 )
+#define TAG_CALC ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x002 )
+#define TAG_DRAW ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x004 )
+#define TAG_IMPRESS ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x008 )
+#define TAG_SCHEDULE ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x010 )
+#define TAG_IMAGE ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x020 )
+#define TAG_MATH ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x040 )
+#define TAG_CHART ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x080 )
+#define TAG_OFFICE ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x100 )
+
+
+#define TAG_GROUP_META 0x6
+#define TAG_OFFICEFULLNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x001 )
+#define TAG_OFFICENAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x002 )
+#define TAG_OFFICEPATH ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x004 )
+#define TAG_OFFICEVERSION ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x008 )
+#define TAG_PORTALNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x010 )
+#define TAG_PORTALFULLNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x020 )
+#define TAG_PORTALPATH ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x040 )
+#define TAG_PORTALVERSION ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x080 )
+#define TAG_PORTALSHORTNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x100 )
+
+
+#define TAG_GROUP_SINGLE 0x7
+#define TAG_REFINSERT ( TAG_GROUP_SINGLE << TAG_GROUPSHIFT | 0x001 )
+
+
+#define TAG_GROUP_MULTI 0x8
+#define TAG_END ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x010 )
+#define TAG_ELSE ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x020 )
+#define TAG_AEND ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x040 )
+#define TAG_VERSIONEND ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x080 )
+#define TAG_ENDGRAPHIC ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x100 )
+
+#define TAG_GROUP_MISC 0x9
+#define TAG_COMMONSTART ( TAG_GROUP_MISC << TAG_GROUPSHIFT | 0x001 )
+#define TAG_COMMONEND ( TAG_GROUP_MISC << TAG_GROUPSHIFT | 0x002 )
+
+#define TAG_UNKNOWN_TAG ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x800 )
+
+DECLARE_LIST( TokenListImpl, TokenInfo* )
+
+class TokenList : private TokenListImpl
+{
+private:
+
+ TokenList& operator =( const TokenList& rList );
+// { TokenListImpl::operator =( rList ); return *this; }
+
+
+public:
+ using TokenListImpl::Count;
+
+
+ TokenList() : TokenListImpl(){};
+ ~TokenList(){ Clear(); };
+
+ void Clear()
+ {
+ for ( ULONG i = 0 ; i < Count() ; i++ )
+ delete TokenListImpl::GetObject( i );
+ TokenListImpl::Clear();
+ }
+ void Insert( TokenInfo p, ULONG nIndex = LIST_APPEND )
+ { TokenListImpl::Insert( new TokenInfo(p), nIndex ); }
+/* TokenInfo Remove( ULONG nIndex )
+ {
+ TokenInfo aT = GetObject( nIndex );
+ delete TokenListImpl::GetObject( nIndex );
+ TokenListImpl::Remove( nIndex );
+ return aT;
+ }*/
+// TokenInfo Remove( TokenInfo p ){ return Remove( GetPos( p ) ); }
+// TokenInfo GetCurObject() const { return *TokenListImpl::GetCurObject(); }
+ TokenInfo& GetObject( ULONG nIndex ) const
+ {
+// if ( TokenListImpl::GetObject(nIndex) )
+ return *TokenListImpl::GetObject(nIndex);
+// else
+// return TokenInfo();
+ }
+/* ULONG GetPos( const TokenInfo p ) const
+ {
+ for ( ULONG i = 0 ; i < Count() ; i++ )
+ if ( p == GetObject( i ) )
+ return i;
+ return LIST_ENTRY_NOTFOUND;
+ }*/
+
+ TokenList( const TokenList& rList );
+/* {
+ for ( ULONG i = 0 ; i < rList.Count() ; i++ )
+ {
+ Insert( rList.GetObject( i ), LIST_APPEND );
+ }
+ }*/
+};
+
+class ParserMessage
+{
+ USHORT nErrorNr;
+ ByteString aErrorText;
+ USHORT nTagBegin,nTagLength;
+
+protected:
+ ParserMessage( USHORT PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag );
+public:
+
+ USHORT GetErrorNr() { return nErrorNr; }
+ ByteString GetErrorText() { return aErrorText; }
+
+ USHORT GetTagBegin() { return nTagBegin; }
+ USHORT GetTagLength() { return nTagLength; }
+
+ virtual ~ParserMessage() {}
+ virtual BOOL IsError() =0;
+ virtual ByteString Prefix() =0;
+};
+
+class ParserError : public ParserMessage
+{
+public:
+ ParserError( USHORT PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag );
+
+ virtual BOOL IsError() {return TRUE;};
+ virtual ByteString Prefix() {return "Error:"; };
+};
+
+class ParserWarning : public ParserMessage
+{
+public:
+ ParserWarning( USHORT PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag );
+
+ virtual BOOL IsError() {return FALSE;};
+ virtual ByteString Prefix() {return "Warning:"; };
+};
+
+class SimpleParser
+{
+private:
+ USHORT nPos;
+ String aSource;
+ String aLastToken;
+ TokenList aTokenList;
+
+ TokenInfo aNextTag; // to store closetag in case of combined tags like <br/>
+
+ String GetNextTokenString( ParserMessageList &rErrorList, USHORT &rTokeStartPos );
+
+public:
+ SimpleParser();
+ void Parse( String PaSource );
+ TokenInfo GetNextToken( ParserMessageList &rErrorList );
+ static String GetLexem( TokenInfo const &aToken );
+ TokenList& GetTokenList(){ return aTokenList; }
+};
+
+class TokenParser
+{
+ BOOL match( const TokenInfo &aCurrentToken, const TokenId &aExpectedToken );
+ BOOL match( const TokenInfo &aCurrentToken, const TokenInfo &aExpectedToken );
+ void ParseError( USHORT nErrNr, ByteString aErrMsg, const TokenInfo &rTag );
+ void Paragraph();
+ void PfCase();
+ void PfCaseBegin();
+ void AppCase();
+ void AppCaseBegin();
+ void CaseEnd();
+ void SimpleTag();
+ void TagPair();
+ void TagRef();
+
+ SimpleParser aParser;
+ TokenInfo aTag;
+
+ TokenId nPfCaseOptions;
+ TokenId nAppCaseOptions;
+ BOOL bPfCaseActive ,bAppCaseActive;
+
+ TokenId nActiveRefTypes;
+
+ ParserMessageList *pErrorList;
+
+public:
+ TokenParser();
+ void Parse( const String &aCode, ParserMessageList* pList );
+// ParserMessageList& GetErrors(){ return aErrorList; }
+// BOOL HasErrors(){ return ( aErrorList.Count() > 0 ); }
+ TokenList& GetTokenList(){ return aParser.GetTokenList(); }
+};
+
+class LingTest
+{
+private:
+ TokenParser aReferenceParser;
+ TokenParser aTesteeParser;
+ ParserMessageList aCompareWarningList;
+ void CheckTags( TokenList &aReference, TokenList &aTestee, BOOL bFixTags );
+ BOOL IsTagMandatory( TokenInfo const &aToken, TokenId &aMetaTokens );
+ String aFixedTestee;
+public:
+ void CheckReference( GSILine *aReference );
+ void CheckTestee( GSILine *aTestee, BOOL bHasSourceLine, BOOL bFixTags );
+
+// ParserMessageList& GetReferenceErrors(){ return aReferenceParser.GetErrors(); }
+// BOOL HasReferenceErrors(){ return aReferenceParser.HasErrors(); }
+
+// ParserMessageList& GetTesteeErrors(){ return aTesteeParser.GetErrors(); }
+// BOOL HasTesteeErrors(){ return aTesteeParser.HasErrors(); }
+
+ ParserMessageList& GetCompareWarnings(){ return aCompareWarningList; }
+ BOOL HasCompareWarnings(){ return ( aCompareWarningList.Count() > 0 ); }
+
+ String GetFixedTestee(){ return aFixedTestee; }
+};
+
+#endif
+
diff --git a/l10ntools/inc/tokens.h b/l10ntools/inc/tokens.h
new file mode 100644
index 000000000000..ef285f4c6361
--- /dev/null
+++ b/l10ntools/inc/tokens.h
@@ -0,0 +1,112 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: tokens.h,v $
+ * $Revision: 1.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _TOKENS_H
+#define _TOKENS_H
+
+/*------------------------------------------------------ */
+/*------------------------------------------------------ */
+/* Tokens for parsing src files */
+/*------------------------------------------------------ */
+/*------------------------------------------------------ */
+#define IGNOREDTOKENS 400 /* #include | #pragma | //... | ... */
+#define COMMEND 401 /*... */
+#define DEFINEDRES 402 /* Text = { */
+#define ANYTOKEN 404 /* XYZ */
+#define UNKNOWNTOKEN 405 /* XYZ[ \t]$ */
+#define UNKNOWNCONSTRUCTION 406 /* XYZ ( xxx, yyy, zzz ) */
+#define UNKNOWNCHAR 407 /* . */
+/*------------------------------------------------------ */
+/* prev. tokens will not be executed */
+#define FILTER_LEVEL 500
+/* following tokens will be executed */
+/*------------------------------------------------------ */
+#define CONDITION 501 /* #if... | #endif ... | ... */
+#define EMPTYLINE 502 /* */
+#define RESSOURCE 503 /* Menu MID_TEST */
+#define RESSOURCEEXPR 504 /* Menu ( MID_TEST + .. ) */
+#define SMALRESSOURCE 505 /* PageItem { */
+#define TEXTLINE 506 /* TEXT = "hhh" */
+#define LONGTEXTLINE 507 /* TEXT = "hhh" TEST "HHH" ... */
+#define TEXT 508 /* "Something like this" */
+#define LEVELUP 509 /* { */
+#define LEVELDOWN 510 /* }; */
+#define APPFONTMAPPING 511 /* MAP_APPFONT(10,10) */
+#define ASSIGNMENT 512 /* Somathing = Anything */
+#define LISTASSIGNMENT 513 /* ...List [xyz]=... */
+#define LISTTEXT 514 /* < "Text" ... > */
+#define RSCDEFINE 515 /* #define MY_TEXT */
+#define RSCDEFINELEND 516 /* */
+#define NEWTEXTINRES 517 /* ### Achtung : Ne... */
+#define UIENTRIES 518 /* UIEntries = { */
+#define PRAGMA 519 /* #pragma ... */
+#define _LISTTEXT 521 /* { "Text" ... } */
+#define TEXTREFID 522 /* Text = 12345 */
+#define LISTRESID 523 /* < 12345; ... > */
+#define _LISTRESID 523 /* { 12345; ... } */
+#define NORMDEFINE 524 /* #define ... */
+/*------------------------------------------------------ */
+/*------------------------------------------------------ */
+/* Tokens for parsing cfg files */
+/*------------------------------------------------------ */
+/*------------------------------------------------------ */
+#define CFG_TAG 501
+#define CFG_TEXT_START 505
+#define CFG_TEXT_END 506
+#define CFG_TEXTCHAR 507
+#define CFG_CLOSETAG 508
+#define CFG_UNKNOWNTAG 509
+#define CFG_TOKEN_PACKAGE 600
+#define CFG_TOKEN_COMPONENT 601
+#define CFG_TOKEN_CONFIGNAME 602
+#define CFG_TOKEN_TEMPLATE 603
+#define CFG_TOKEN_OORNAME 604
+#define CFG_TOKEN_OORVALUE 605
+#define CFG_TOKEN_NO_TRANSLATE 606
+
+/*------------------------------------------------------ */
+/*------------------------------------------------------ */
+/* Tokens for parsing xrm files */
+/*------------------------------------------------------ */
+/*------------------------------------------------------ */
+#define XRM_README_START 501
+#define XRM_README_END 502
+#define XRM_SECTION_START 503
+#define XRM_SECTION_END 504
+#define XRM_PARAGRAPH_START 505
+#define XRM_PARAGRAPH_END 506
+#define XRM_TEXT_START 507
+#define XRM_TEXT_END 508
+#define XRM_LIST_START 509
+#define XRM_LIST_END 510
+#define XML_TEXTCHAR 600
+
+
+#endif
diff --git a/l10ntools/inc/treeconfig.hxx b/l10ntools/inc/treeconfig.hxx
new file mode 100644
index 000000000000..96d693b0d376
--- /dev/null
+++ b/l10ntools/inc/treeconfig.hxx
@@ -0,0 +1,28 @@
+#include <vector>
+#include <string>
+
+#include "inireader.hxx"
+
+namespace transex3{
+
+class Treeconfig
+{
+
+ private:
+ INIreader inireader;
+ INImap map;
+ bool has_config_file;
+ void getCurrentDir( string& dir );
+ bool isConfigFilePresent();
+
+ public:
+
+ Treeconfig() : has_config_file( false ) { parseConfig(); }
+ // read the config file, returns true in case a config file had been found
+ bool parseConfig();
+ // returns a string vector containing all active repositories, returns true in case we are deep inside
+ // of a source tree. This could affect the behavour of the tool
+ bool getActiveRepositories( vector<string>& active_repos);
+};
+
+}
diff --git a/l10ntools/inc/utf8conv.hxx b/l10ntools/inc/utf8conv.hxx
new file mode 100644
index 000000000000..32e506edbda8
--- /dev/null
+++ b/l10ntools/inc/utf8conv.hxx
@@ -0,0 +1,47 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: utf8conv.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// global includes
+#include <rtl/textcvt.h>
+#include <tools/string.hxx>
+
+//
+// class UTF8Converter
+//
+
+class UTF8Converter
+{
+private:
+ static void Convert( ByteString &rBuffer, rtl_TextEncoding nSourceENC, rtl_TextEncoding nDestENC );
+
+public:
+ static ByteString ConvertToUTF8( const ByteString &rASCII, rtl_TextEncoding nEncoding );
+ static ByteString ConvertFromUTF8( const ByteString &rUTF8, rtl_TextEncoding nEncoding );
+};
diff --git a/l10ntools/inc/wrdtrans.hxx b/l10ntools/inc/wrdtrans.hxx
new file mode 100644
index 000000000000..efcb663204a6
--- /dev/null
+++ b/l10ntools/inc/wrdtrans.hxx
@@ -0,0 +1,90 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: wrdtrans.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+
+// OBSOLETE //
+
+#ifndef TX3_WRDTRANS_HXX
+#define TX3_WRDTRANS_HXX
+
+// USED
+ // Base Classes
+ // Components
+class WordTransTree;
+class WordTrans_ErrorList;
+ // Parameters
+#include <tools/string.hxx>
+
+class WordTransformer
+{
+ public:
+ enum E_Error
+ {
+ OK = 0,
+ ERROR_NO_WORDLIST,
+ ERROR_HOTKEY,
+ ERROR_OUTPUTSTRING_TOO_LONG,
+ OTHER_ERROR
+ };
+
+ // LIFECYCLE
+ WordTransformer();
+ ~WordTransformer();
+ BOOL LoadWordlist( /// @return False, if file could not be read, or there is already a wordlist loaded.
+ const ByteString & i_sWordlist_Filepath,
+ CharSet i_nWorkingCharSet = RTL_TEXTENCODING_MS_1252,
+ CharSet i_nFileCharSet = RTL_TEXTENCODING_MS_1252 );
+
+ // OPERATIONS
+ USHORT Transform( /// @return The number of errors during transforming.
+ ByteString & io_sText);
+
+ // INQUIRY
+ USHORT NrOfErrors() const;
+ E_Error GetError(
+ USHORT i_nNr, /// [0 .. NrOfErrors()-1], other values return an empty error.
+ ByteString * o_pErrorText = 0) const; /// If o_pErrorText != 0, the String is filled with the description of the error.
+
+ private:
+ // SERVICE FUNCTION
+ void CreateError();
+
+ // DATA
+ WordTransTree * dpTransformer;
+ WordTrans_ErrorList *
+ dpErrors;
+};
+
+
+
+#endif
+
+
+*/
diff --git a/l10ntools/inc/wtranode.hxx b/l10ntools/inc/wtranode.hxx
new file mode 100644
index 000000000000..4d71fc160fff
--- /dev/null
+++ b/l10ntools/inc/wtranode.hxx
@@ -0,0 +1,121 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: wtranode.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#ifndef TX3_WTRANODE_HXX
+#define TX3_WTRANODE_HXX
+
+// USED
+ // Base Classes
+ // Components
+ // Parameters
+#include <tools/string.hxx>
+
+
+typedef UINT8 BRANCH_T;
+
+
+
+const BRANCH_T C_BR_ALPHABASE = 4;
+const BRANCH_T C_NR_OF_BRANCHES = 34;
+
+
+
+
+/** @task
+ This is a node of the parsing-tree which implements the fuctionality of
+ class WordTransTree.
+ WordTransTree is dependant of this class, but NOT the other way!
+**/
+class WTT_Node // WordTransTree-Node
+{
+ public:
+ enum E_TokenType
+ {
+// no_token = 0,
+ token_to_keep,
+ token_to_replace
+ };
+
+ // LIFECYCLE
+ WTT_Node(
+ UINT8 i_nValue, // Own branch-value.
+ WTT_Node * i_pDefaultBranch,
+ WTT_Node * i_pDefaultBranchForAlphas );
+ void SetBranch(
+ UINT8 i_cBranch,
+ WTT_Node * i_pNode );
+ void SetAsTokenToReplace(
+ const ByteString & i_sReplaceString );
+ ~WTT_Node();
+
+ // OPERATIONS
+ WTT_Node * GetNextNode(
+ UINT8 i_cBranch ); /// [0 .. C_NR_OF_BRANCHES-1], sonst GPF !!!
+
+ // INQUIRY
+ E_TokenType TokenType() const;
+ UINT8 Value() const;
+ BOOL IsOnDeleting() const;
+ const ByteString & ReplaceString() const;
+
+ private:
+ // DATA
+ UINT8 nValue;
+ E_TokenType eType;
+ ByteString sReplaceString;
+ WTT_Node * aBranches[C_NR_OF_BRANCHES]; // Mostly DYN pointers.
+ char bIsOnDeleting;
+};
+
+
+inline WTT_Node *
+WTT_Node::GetNextNode(UINT8 i_cBranch)
+ { return aBranches[i_cBranch]; }
+inline WTT_Node::E_TokenType
+WTT_Node::TokenType() const
+ { return eType; }
+inline UINT8
+WTT_Node::Value() const
+ { return nValue; }
+inline BOOL
+WTT_Node::IsOnDeleting() const
+ { return bIsOnDeleting; }
+inline const ByteString &
+WTT_Node::ReplaceString() const
+ { return sReplaceString; }
+
+
+
+
+#endif
+
+
+
diff --git a/l10ntools/inc/wtratree.hxx b/l10ntools/inc/wtratree.hxx
new file mode 100644
index 000000000000..67d63280449f
--- /dev/null
+++ b/l10ntools/inc/wtratree.hxx
@@ -0,0 +1,162 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: wtratree.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#ifndef TX3_WTRATREE_HXX
+#define TX3_WTRATREE_HXX
+
+// USED
+ // Base Classes
+ // Components
+ // Parameters
+#include <tools/string.hxx>
+
+const INT16 C_NR_OF_WTT_RESULTS = 5;
+const INT16 C_NR_OF_POSSIBLE_CHARS = 256;
+
+
+typedef unsigned char u_char;
+typedef const char * constr;
+
+
+class WTT_Node;
+
+
+/** @task
+ This class implements the functionality, that class WordTransformer
+ offers.
+ WordTransformer is dependant of this class, but NOT the other way!
+**/
+class WordTransTree
+{
+ public:
+ enum E_Result
+ {
+ OK = 0,
+ HOTKEY_LOST,
+ OUTPUT_OVERFLOW
+ };
+
+
+ // LIFECYCLE
+ WordTransTree(
+ CharSet i_nWorkingCharSet = RTL_TEXTENCODING_MS_1252);
+ void SetCharSet(
+ CharSet i_nWorkingCharSet);
+ ~WordTransTree();
+
+ void AddWordPair(
+ const ByteString & i_sOldString,
+ const ByteString & i_sReplaceString );
+
+ // OPERATIONS
+ void InitTransformation(
+ const char * i_sInput, /// [!=0], a range of i_nInputLength must be valid memory for read.
+ UINT32 i_nInputLength,
+ UINT32 i_nOutputMaxLength = STRING_MAXLEN - 12 );
+ E_Result TransformNextToken();
+
+ // INQUIRY
+ BOOL TextEndReached() const;
+ const char * Output() const;
+
+ // These 3 functions are valid between two calls of
+ // TransformNextToken():
+ E_Result CurResult() const;
+ ByteString CurReplacedString() const;
+ ByteString CurReplacingString() const;
+ char CurHotkey() const;
+
+ private:
+ // SERVICE FUNCTONS
+ UINT8 CalculateBranch(
+ u_char i_cInputChar ) const;
+
+ void Handle_Hotkey();
+ void Handle_TokenToKeep();
+ void Handle_TokenToTransform();
+
+ // DATA
+ // Fixed data
+ const u_char * sInput;
+ UINT32 nInputLength;
+ const u_char * pInputEnd;
+
+ u_char * sOutput; // DYN
+ UINT32 nOutputMaxLength;
+
+ WTT_Node * dpParsingTreeTop; // DYN
+ WTT_Node * pUnknownAlpha;
+ u_char cChar2Branch[C_NR_OF_POSSIBLE_CHARS];
+ u_char c_AE, c_OE, c_UE, c_ae, c_oe, c_ue;
+
+ // Working data
+ const u_char * pInputCurTokenStart;
+ const u_char * pInputPosition;
+ u_char * pOutputPosition;
+ WTT_Node * pCurParseNode;
+
+ // Data which are valid only after a completed call to TransformNextToken()
+ E_Result eCurResult;
+ u_char cCurHotkey; // Letter wich is used as hotkey
+ u_char cCurHotkeySign; // Letter which is used to assign hotkey ('~'or '&') .
+};
+
+
+
+
+
+
+
+inline BOOL
+WordTransTree::TextEndReached() const
+ { return pInputPosition == pInputEnd; }
+inline const char *
+WordTransTree::Output() const
+ { return TextEndReached() ? (constr) sOutput : ""; }
+inline WordTransTree::E_Result
+WordTransTree::CurResult() const
+ { return eCurResult; }
+inline ByteString
+WordTransTree::CurReplacedString() const
+ { return ByteString((constr) pInputCurTokenStart,pInputPosition-pInputCurTokenStart); }
+inline char
+WordTransTree::CurHotkey() const
+ { return cCurHotkey; }
+inline UINT8
+WordTransTree::CalculateBranch(u_char i_cInputChar) const
+ { return cChar2Branch[i_cInputChar]; }
+
+
+
+#endif
+
+
+
diff --git a/l10ntools/inc/xmlparse.hxx b/l10ntools/inc/xmlparse.hxx
new file mode 100644
index 000000000000..18b047ef75c1
--- /dev/null
+++ b/l10ntools/inc/xmlparse.hxx
@@ -0,0 +1,553 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: xmlparse.hxx,v $
+ * $Revision: 1.15 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef BOOTSTRP_XMLPARSE_HXX
+#define BOOTSTRP_XMLPARSE_HXX
+
+#include <signal.h>
+#include <expat.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include "tools/string.hxx"
+#include "tools/list.hxx"
+#define ENABLE_BYTESTRING_STREAM_OPERATORS
+#include "tools/stream.hxx"
+#include "tools/isofallback.hxx"
+#include "export.hxx"
+#include "xmlutil.hxx"
+
+#include <fstream>
+#include <iostream>
+
+class XMLParentNode;
+class XMLElement;
+
+
+using namespace ::rtl;
+using namespace std;
+
+#include <hash_map> /* std::hashmap*/
+#include <deque> /* std::deque*/
+#include <iterator> /* std::iterator*/
+#include <list> /* std::list*/
+#include <vector> /* std::vector*/
+#define XML_NODE_TYPE_FILE 0x001
+#define XML_NODE_TYPE_ELEMENT 0x002
+#define XML_NODE_TYPE_DATA 0x003
+#define XML_NODE_TYPE_COMMENT 0x004
+#define XML_NODE_TYPE_DEFAULT 0x005
+#define MAX_LANGUAGES 99
+
+
+//#define TESTDRIVER /* use xml2gsi testclass */
+//-------------------------------------------------------------------------
+
+/** Holds data of Attributes
+ */
+class XMLAttribute : public String
+{
+private:
+ String sValue;
+
+public:
+ /// creates an attribute
+ XMLAttribute(
+ const String &rName, // attributes name
+ const String &rValue // attributes data
+ )
+ : String( rName ), sValue( rValue ) {}
+
+ /// getting value of an attribue
+ const String &GetValue() { return sValue; }
+
+ void setValue(const String &rValue){sValue=rValue;}
+
+ /// returns true if two attributes are equal and have the same value
+ BOOL IsEqual(
+ const XMLAttribute &rAttribute // the attribute which has to be equal
+ )
+ {
+ return (( rAttribute == *this ) && ( rAttribute.sValue == sValue ));
+ }
+};
+
+DECLARE_LIST( XMLAttributeList, XMLAttribute * )
+
+//-------------------------------------------------------------------------
+
+/** Virtual base to handle different kinds of XML nodes
+ */
+class XMLNode
+{
+protected:
+ XMLNode() {}
+
+public:
+ virtual USHORT GetNodeType() = 0;
+ virtual ~XMLNode() {}
+};
+
+//-------------------------------------------------------------------------
+
+/** Virtual base to handle different kinds of child nodes
+ */
+class XMLChildNode : public XMLNode
+{
+private:
+ XMLParentNode *pParent;
+
+protected:
+ XMLChildNode( XMLParentNode *pPar );
+ XMLChildNode():pParent( NULL ){};
+ XMLChildNode( const XMLChildNode& obj);
+ XMLChildNode& operator=(const XMLChildNode& obj);
+public:
+ virtual USHORT GetNodeType() = 0;
+
+ /// returns the parent of this node
+ XMLParentNode *GetParent() { return pParent; }
+ virtual ~XMLChildNode(){};
+};
+
+DECLARE_LIST( XMLChildNodeList, XMLChildNode * )
+
+//-------------------------------------------------------------------------
+
+/** Virtual base to handle different kinds of parent nodes
+ */
+class XMLData;
+
+class XMLParentNode : public XMLChildNode
+{
+private:
+ XMLChildNodeList *pChildList;
+ static int dbgcnt;
+ //int nParentPos;
+protected:
+ XMLParentNode( XMLParentNode *pPar )
+ : XMLChildNode( pPar ), pChildList( NULL )
+ {
+ }
+ XMLParentNode(): pChildList(NULL){
+ }
+ /// Copyconstructor
+ XMLParentNode( const XMLParentNode& );
+
+ XMLParentNode& operator=(const XMLParentNode& obj);
+ virtual ~XMLParentNode();
+
+
+public:
+ virtual USHORT GetNodeType() = 0;
+
+ /// returns child list of this node
+ XMLChildNodeList *GetChildList() { return pChildList; }
+
+ /// adds a new child
+ void AddChild(
+ XMLChildNode *pChild /// the new child
+ );
+
+ void AddChild(
+ XMLChildNode *pChild , int pos /// the new child
+ );
+
+ virtual int GetPosition( ByteString id );
+ int RemoveChild( XMLElement *pRefElement );
+ void RemoveAndDeleteAllChilds();
+
+ /// returns a child element which matches the given one
+ XMLElement *GetChildElement(
+ XMLElement *pRefElement // the reference elelement
+ );
+};
+
+//-------------------------------------------------------------------------
+
+DECLARE_LIST( XMLStringList, XMLElement* )
+
+/// Mapping numeric Language code <-> XML Element
+typedef std::hash_map< ByteString ,XMLElement* , hashByteString,equalByteString > LangHashMap;
+
+/// Mapping XML Element string identifier <-> Language Map
+typedef std::hash_map<ByteString , LangHashMap* ,
+ hashByteString,equalByteString> XMLHashMap;
+
+/// Mapping iso alpha string code <-> iso numeric code
+typedef std::hash_map<ByteString, int, hashByteString,equalByteString> HashMap;
+
+/// Mapping XML tag names <-> have localizable strings
+typedef std::hash_map<ByteString , BOOL ,
+ hashByteString,equalByteString> TagMap;
+
+/** Holds information of a XML file, is root node of tree
+ */
+
+
+class XMLFile : public XMLParentNode
+{
+public:
+ XMLFile() ;
+ XMLFile(
+ const String &rFileName // the file name, empty if created from memory stream
+ );
+ XMLFile( const XMLFile& obj ) ;
+ ~XMLFile();
+
+ ByteString* GetGroupID(std::deque<ByteString> &groupid);
+ void Print( XMLNode *pCur = NULL, USHORT nLevel = 0 );
+ virtual void SearchL10NElements( XMLParentNode *pCur, int pos = 0 );
+ void Extract( XMLFile *pCur = NULL );
+ void View();
+// void static Signal_handler(int signo);//void*,oslSignalInfo * pInfo);
+ void showType(XMLParentNode* node);
+
+ XMLHashMap* GetStrings(){return XMLStrings;}
+ BOOL Write( ByteString &rFilename );
+ BOOL Write( ofstream &rStream , XMLNode *pCur = NULL );
+
+ bool CheckExportStatus( XMLParentNode *pCur = NULL );// , int pos = 0 );
+
+ XMLFile& operator=(const XMLFile& obj);
+
+ virtual USHORT GetNodeType();
+
+ /// returns file name
+ const String &GetName() { return sFileName; }
+ void SetName( const String &rFilename ) { sFileName = rFilename; }
+ void SetFullName( const String &rFullFilename ) { sFullName = rFullFilename; }
+ const std::vector<ByteString> getOrder(){ return order; }
+
+protected:
+ // writes a string as UTF8 with dos line ends to a given stream
+ void WriteString( ofstream &rStream, const String &sString );
+
+ // quotes the given text for writing to a file
+ void QuotHTML( String &rString );
+
+ void InsertL10NElement( XMLElement* pElement);
+
+ // DATA
+ String sFileName;
+ String sFullName;
+
+ const ByteString ID,OLDREF,XML_LANG;
+
+ TagMap nodes_localize;
+ XMLHashMap* XMLStrings;
+
+ std::vector <ByteString> order;
+};
+
+/// An Utility class for XML
+/// See RFC 3066 / #i8252# for ISO codes
+class XMLUtil{
+
+public:
+ /// Quot the XML characters and replace \n \t
+ static void QuotHTML( String &rString );
+
+ /// UnQuot the XML characters and restore \n \t
+ static void UnQuotHTML ( String &rString );
+
+ /// Return the numeric iso language code
+ //USHORT GetLangByIsoLang( const ByteString &rIsoLang );
+
+ /// Return the alpha strings representation
+ ByteString GetIsoLangByIndex( USHORT nIndex );
+
+ static XMLUtil& Instance();
+ ~XMLUtil();
+
+ void dump();
+
+private:
+ /// Mapping iso alpha string code <-> iso numeric code
+ HashMap lMap;
+
+ /// Mapping iso numeric code <-> iso alpha string code
+ ByteString isoArray[MAX_LANGUAGES];
+
+ static void UnQuotData( String &rString );
+ static void UnQuotTags( String &rString );
+
+ XMLUtil();
+ XMLUtil(const XMLUtil&);
+
+};
+
+
+
+//-------------------------------------------------------------------------
+
+/** Hold information of an element node
+ */
+class XMLElement : public XMLParentNode
+{
+private:
+ String sElementName;
+ XMLAttributeList *pAttributes;
+ ByteString project,
+ filename,
+ id,
+ sOldRef,
+ resourceType,
+ languageId;
+ int nPos;
+
+protected:
+ void Print(XMLNode *pCur, OUStringBuffer& buffer , bool rootelement);
+public:
+ /// create a element node
+ XMLElement(){}
+ XMLElement(
+ const String &rName, // the element name
+ XMLParentNode *Parent // parent node of this element
+ ): XMLParentNode( Parent ),
+ sElementName( rName ),
+ pAttributes( NULL ),
+ project(""),
+ filename(""),
+ id(""),
+ sOldRef(""),
+ resourceType(""),
+ languageId(""),
+ nPos(0)
+ {
+ }
+ ~XMLElement();
+ XMLElement(const XMLElement&);
+
+ XMLElement& operator=(const XMLElement& obj);
+ /// returns node type XML_NODE_ELEMENT
+ virtual USHORT GetNodeType();
+
+ /// returns element name
+ const String &GetName() { return sElementName; }
+
+ /// returns list of attributes of this element
+ XMLAttributeList *GetAttributeList() { return pAttributes; }
+
+ /// adds a new attribute to this element, typically used by parser
+ void AddAttribute( const String &rAttribute, const String &rValue );
+
+ void ChangeLanguageTag( const String &rValue );
+ // Return a ASCII String representation of this object
+ OString ToOString();
+
+ // Return a Unicode String representation of this object
+ OUString ToOUString();
+
+ bool Equals(OUString refStr);
+
+ /// returns a attribute
+ XMLAttribute *GetAttribute(
+ const String &rName // the attribute name
+ );
+ void SetProject ( ByteString prj ){ project = prj; }
+ void SetFileName ( ByteString fn ){ filename = fn; }
+ void SetId ( ByteString theId ){ id = theId; }
+ void SetResourceType ( ByteString rt ){ resourceType = rt; }
+ void SetLanguageId ( ByteString lid ){ languageId = lid; }
+ void SetPos ( int nPos_in ){ nPos = nPos_in; }
+ void SetOldRef ( ByteString sOldRef_in ){ sOldRef = sOldRef_in; }
+
+ virtual int GetPos() { return nPos; }
+ ByteString GetProject() { return project; }
+ ByteString GetFileName() { return filename; }
+ ByteString GetId() { return id; }
+ ByteString GetOldref() { return sOldRef; }
+ ByteString GetResourceType(){ return resourceType; }
+ ByteString GetLanguageId() { return languageId; }
+
+
+};
+//-------------------------------------------------------------------------
+
+
+/** Holds character data
+ */
+class XMLData : public XMLChildNode
+{
+private:
+ String sData;
+ bool isNewCreated;
+
+public:
+ /// create a data node
+ XMLData(
+ const String &rData, // the initial data
+ XMLParentNode *Parent // the parent node of this data, typically a element node
+ )
+ : XMLChildNode( Parent ), sData( rData ) , isNewCreated ( false ){}
+ XMLData(
+ const String &rData, // the initial data
+ XMLParentNode *Parent, // the parent node of this data, typically a element node
+ bool newCreated
+ )
+ : XMLChildNode( Parent ), sData( rData ) , isNewCreated ( newCreated ){}
+
+ XMLData(const XMLData& obj);
+
+ XMLData& operator=(const XMLData& obj);
+ virtual USHORT GetNodeType();
+
+ /// returns the data
+ const String &GetData() { return sData; }
+
+ bool isNew() { return isNewCreated; }
+ /// adds new character data to the existing one
+ void AddData(
+ const String &rData // the new data
+ );
+
+
+
+};
+
+//-------------------------------------------------------------------------
+
+/** Holds comments
+ */
+class XMLComment : public XMLChildNode
+{
+private:
+ String sComment;
+
+public:
+ /// create a comment node
+ XMLComment(
+ const String &rComment, // the comment
+ XMLParentNode *Parent // the parent node of this comemnt, typically a element node
+ )
+ : XMLChildNode( Parent ), sComment( rComment ) {}
+
+ virtual USHORT GetNodeType();
+
+ XMLComment( const XMLComment& obj );
+
+ XMLComment& operator=(const XMLComment& obj);
+
+ /// returns the comment
+ const String &GetComment() { return sComment; }
+};
+
+//-------------------------------------------------------------------------
+
+/** Holds additional file content like those for which no handler exists
+ */
+class XMLDefault : public XMLChildNode
+{
+private:
+ String sDefault;
+
+public:
+ /// create a comment node
+ XMLDefault(
+ const String &rDefault, // the comment
+ XMLParentNode *Parent // the parent node of this comemnt, typically a element node
+ )
+ : XMLChildNode( Parent ), sDefault( rDefault ) {}
+
+ XMLDefault(const XMLDefault& obj);
+
+ XMLDefault& operator=(const XMLDefault& obj);
+
+ /// returns node type XML_NODE_TYPE_COMMENT
+ virtual USHORT GetNodeType();
+
+ /// returns the comment
+ const String &GetDefault() { return sDefault; }
+};
+
+//-------------------------------------------------------------------------
+
+/** struct for error information, used by class SimpleXMLParser
+ */
+struct XMLError {
+ XML_Error eCode; // the error code
+ ULONG nLine; // error line number
+ ULONG nColumn; // error column number
+ String sMessage; // readable error message
+};
+
+//-------------------------------------------------------------------------
+
+/** validating xml parser, creates a document tree with xml nodes
+ */
+
+
+class SimpleXMLParser
+{
+private:
+ XML_Parser aParser;
+ XMLError aErrorInformation;
+
+ XMLFile *pXMLFile;
+ XMLParentNode *pCurNode;
+ XMLData *pCurData;
+
+
+ static void StartElementHandler( void *userData, const XML_Char *name, const XML_Char **atts );
+ static void EndElementHandler( void *userData, const XML_Char *name );
+ static void CharacterDataHandler( void *userData, const XML_Char *s, int len );
+ static void CommentHandler( void *userData, const XML_Char *data );
+ static void DefaultHandler( void *userData, const XML_Char *s, int len );
+
+
+ void StartElement( const XML_Char *name, const XML_Char **atts );
+ void EndElement( const XML_Char *name );
+ void CharacterData( const XML_Char *s, int len );
+ void Comment( const XML_Char *data );
+ void Default( const XML_Char *s, int len );
+
+
+public:
+ /// creates a new parser
+ SimpleXMLParser();
+ ~SimpleXMLParser();
+
+ /// parse a file, returns NULL on criticall errors
+ XMLFile *Execute(
+ const String &rFullFileName,
+ const String &rFileName, // the file name
+ XMLFile *pXMLFileIn // the XMLFile
+ );
+
+ /// parse a memory stream, returns NULL on criticall errors
+ XMLFile *Execute(
+ SvMemoryStream *pStream // the stream
+ );
+
+ /// returns an error struct
+ const XMLError &GetError() { return aErrorInformation; }
+};
+
+#endif
diff --git a/l10ntools/inc/xmlutil.hxx b/l10ntools/inc/xmlutil.hxx
new file mode 100644
index 000000000000..812f50b85c45
--- /dev/null
+++ b/l10ntools/inc/xmlutil.hxx
@@ -0,0 +1,9 @@
+#define ENGLISH_US 1
+#define ENGLISH_US_ISO "en-US"
+#define ENGLISH_US_PROPERTY "en_US"
+#define ENGLISH_US_INDEX 1
+#define GERMAN_DE 4
+#define GERMAN_DE_ISO "x-german"
+#define GERMAN_DE_INDEX 3
+#define GERMAN_ISO2 "de-DE"
+
diff --git a/l10ntools/inc/xrmmerge.hxx b/l10ntools/inc/xrmmerge.hxx
new file mode 100644
index 000000000000..47be1ea7a038
--- /dev/null
+++ b/l10ntools/inc/xrmmerge.hxx
@@ -0,0 +1,161 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: xrmmerge.hxx,v $
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// global includes
+#include <tools/string.hxx>
+
+//
+// XRMResParser
+//
+
+class XRMResParser
+{
+private:
+ ByteString sGID;
+ ByteString sLID;
+
+ BOOL bError;
+ BOOL bText;
+
+ bool sLocalized;
+
+ ByteString sCurrentOpenTag;
+ ByteString sCurrentCloseTag;
+ ByteString sCurrentText;
+ std::vector<ByteString> aLanguages;
+
+protected:
+ ByteString GetAttribute( const ByteString &rToken, const ByteString &rAttribute );
+ void Error( const ByteString &rError );
+
+ virtual void Output( const ByteString& rOutput )=0;
+ virtual void WorkOnText(
+ const ByteString &rOpenTag,
+ ByteString &rText
+ )=0;
+ virtual void EndOfText(
+ const ByteString &rOpenTag,
+ const ByteString &rCloseTag
+ )=0;
+
+ ByteString GetGID() { return sGID; }
+ ByteString GetLID() { return sLID; }
+
+ void ConvertStringToDBFormat( ByteString &rString );
+ void ConvertStringToXMLFormat( ByteString &rString );
+
+public:
+ XRMResParser();
+ virtual ~XRMResParser();
+
+ int Execute( int nToken, char * pToken );
+
+ void SetError( BOOL bErr = TRUE ) { bError = bErr; }
+ BOOL GetError() { return bError; }
+};
+
+//
+// class XRMResOutputParser
+//
+
+class XRMResOutputParser : public XRMResParser
+{
+private:
+ std::vector<ByteString> aLanguages;
+protected:
+ SvFileStream *pOutputStream;
+public:
+ XRMResOutputParser ( const ByteString &rOutputFile );
+ virtual ~XRMResOutputParser();
+};
+
+//
+// XRMResExport
+//
+
+class XRMResExport : public XRMResOutputParser
+{
+private:
+ ResData *pResData;
+ ByteString sPrj;
+ ByteString sPath;
+ std::vector<ByteString> aLanguages;
+
+protected:
+ void WorkOnText(
+ const ByteString &rOpenTag,
+ ByteString &rText
+ );
+ void EndOfText(
+ const ByteString &rOpenTag,
+ const ByteString &rCloseTag
+ );
+ void Output( const ByteString& rOutput );
+
+public:
+ XRMResExport(
+ const ByteString &rOutputFile,
+ const ByteString &rProject,
+ const ByteString &rFilePath
+ );
+ virtual ~XRMResExport();
+};
+
+//
+// class XRMResMerge
+//
+
+class XRMResMerge : public XRMResOutputParser
+{
+private:
+ MergeDataFile *pMergeDataFile;
+ ByteString sFilename;
+ ResData *pResData;
+ std::vector<ByteString> aLanguages;
+
+protected:
+ void WorkOnText(
+ const ByteString &rOpenTag,
+ ByteString &rText
+ );
+ void EndOfText(
+ const ByteString &rOpenTag,
+ const ByteString &rCloseTag
+ );
+ void Output( const ByteString& rOutput );
+public:
+ XRMResMerge(
+ const ByteString &rMergeSource,
+ const ByteString &rOutputFile,
+ ByteString &rFilename
+ );
+ virtual ~XRMResMerge();
+};
+
diff --git a/l10ntools/java/l10nconv/build.xml b/l10ntools/java/l10nconv/build.xml
new file mode 100755
index 000000000000..6902227e5122
--- /dev/null
+++ b/l10ntools/java/l10nconv/build.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: build.xml,v $
+
+ $Revision: 1.4 $
+
+ This file is part of OpenOffice.org.
+
+ OpenOffice.org is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 3
+ only, as published by the Free Software Foundation.
+
+ OpenOffice.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License version 3 for more details
+ (a copy is included in the LICENSE file that accompanied this code).
+
+ You should have received a copy of the GNU Lesser General Public License
+ version 3 along with OpenOffice.org. If not, see
+ <http://www.openoffice.org/license.html>
+ for a copy of the LGPLv3 License.
+
+-->
+<project name="l10nconv" default="main" basedir=".">
+
+ <!-- ================================================================= -->
+ <!-- settings -->
+ <!-- ================================================================= -->
+
+ <!-- name of this sub target used in recursive builds -->
+ <property name="target" value="l10nconv"/>
+
+ <!-- name of jar file created, without .jar extension -->
+ <property name="jarname" value="converter"/>
+
+ <!-- relative path to project directory -->
+ <property name="prj" value="."/>
+
+ <!-- build output directory -->
+ <property name="out" value="build"/>
+
+ <!-- build directories -->
+ <property name="build.dir" value="${out}"/>
+ <property name="build.class" value="${build.dir}/class/converter"/>
+ <property name="build.misc" value="${build.dir}/misc/converter"/>
+
+ <!-- start of java source code package structure -->
+ <property name="java.dir" value="java"/>
+
+ <!-- define how to handle CLASSPATH environment -->
+ <property name="build.sysclasspath" value="ignore"/>
+
+ <!-- classpath settings for compile and javadoc tasks -->
+ <path id="classpath">
+ <pathelement location="."/>
+ <pathelement location="${build.class}"/>
+ </path>
+
+ <!-- name to display in documentation -->
+ <property name="docname" value="l10n converter"/>
+
+ <!-- set "modern" java compiler -->
+ <property name="build.compiler" value="modern"/>
+
+ <!-- set wether we want to compile with debug information -->
+ <property name="debug" value="on"/>
+
+ <!-- set wether we want to compile with optimisation -->
+ <property name="optimize" value="off"/>
+
+ <!-- set wether we want to compile with or without deprecation -->
+ <property name="deprecation" value="on"/>
+
+ <target name="info">
+ <echo message="--------------------"/>
+ <echo message="${target}"/>
+ <echo message="--------------------"/>
+ </target>
+
+ <!-- ================================================================= -->
+ <!-- custom targets -->
+ <!-- ================================================================= -->
+
+ <!-- the main target, called in recursive builds -->
+ <target name="main" depends="info,prepare,compile,jar,javadoc,zipdoc"/>
+
+ <!-- prepare output directories -->
+ <target name="prepare">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${build.dir}/doc"/>
+ <mkdir dir="${build.dir}/doc/javadoc"/>
+ <mkdir dir="${build.class}"/>
+ <mkdir dir="${build.misc}"/>
+ </target>
+
+
+ <target name="res" depends="prepare">
+ <copy todir="${build.class}">
+ <fileset dir="${java.dir}">
+ <include name="**/*.properties"/>
+ <include name="**/*.css"/>
+ <include name="**/*.dtd"/>
+ <include name="**/*.form"/>
+ <include name="**/*.gif "/>
+ <include name="**/*.htm"/>
+ <include name="**/*.html"/>
+ <include name="**/*.js"/>
+ <include name="**/*.mod"/>
+ <include name="**/*.sql"/>
+ <include name="**/*.xml"/>
+ <include name="**/*.xsl"/>
+ <include name="**/*.map"/>
+
+ </fileset>
+ </copy>
+ </target>
+
+
+ <target name="compile" depends="prepare,res">
+ <javac destdir="${build.class}"
+ debug="${debug}"
+ deprecation="${deprication}"
+ optimize="${optimize}"
+ classpathref="classpath">
+ <src path="${java.dir}"/>
+ <include name="**/*.java"/>
+ </javac>
+ </target>
+
+ <!-- check if javadoc is up to date -->
+ <target name="javadoc_check" depends="prepare" if="build.dir">
+ <uptodate property="javadocBuild.notRequired" value="true"
+ targetfile="${build.dir}/doc/converter_javadoc.zip">
+ <srcfiles dir="${java.dir}" includes="**/*.java"/>
+ </uptodate>
+ </target>
+
+ <!-- generate java documentation -->
+ <target name="javadoc" depends="prepare,javadoc_check,compile"
+ unless="javadocBuild.notRequired"
+ if="build.dir">
+
+ <javadoc destdir="${build.dir}/doc/javadoc"
+ verbose="false"
+ author="false"
+ nodeprecated="true"
+ nodeprecatedlist="true"
+ use="true"
+ Doctitle="${docname}"
+ windowtitle="${docname}"
+ classpathref="classpath">
+
+ <packageset dir="${java.dir}" defaultexcludes="yes">
+ <include name="com/**"/>
+ </packageset>
+
+ <link offline="true" href="http://java.sun.com/j2se/1.4.2/docs/api"
+ packagelistLoc="${common.doc}/jdk1.4.2"/>
+ <link offline="true"
+ href="http://java.sun.com/products/servlet/2.3/javadoc"
+ packagelistLoc="${common.doc}/servlet2.3"/>
+ <link offline="true"
+ href="http://logging.apache.org/log4j/docs/api"
+ packagelistLoc="${common.doc}/log4j-1.2.8"/>
+ <link offline="true"
+ href="http://java.sun.com/products/javabeans/glasgow/javadocs"
+ packagelistLoc="${common.doc}/jaf-1.0.2"/>
+ <link offline="true"
+ href="http://java.sun.com/products/javamail/javadocs"
+ packagelistLoc="${common.doc}/javamail-1.3.1"/>
+ <link offline="true"
+ href="http://ws.apache.org/soap/docs"
+ packagelistLoc="${common.doc}/soap-2.3.1"/>
+
+ <bottom>&lt;i&gt;Copyright &amp;#169; 2004 Sun Microsystems, Inc., 901 San Antonio Road, Palo Alto, CA 94303 USA&lt;/i&gt;</bottom>
+ <header>${docname}</header>
+
+ </javadoc>
+ </target>
+
+ <!-- zip documentation and store in build/misc -->
+ <target name="zipdoc" depends="javadoc" if="build.dir" unless="javadocBuild.notRequired">
+ <zip zipfile="${build.dir}/doc/converter_javadoc.zip"
+ basedir="${build.dir}/doc/javadoc"
+ update="true"/>
+ </target>
+
+ <!-- clean up -->
+ <target name="clean" depends="prepare">
+ <delete includeEmptyDirs="true">
+ <fileset dir="${build.class}">
+ <patternset>
+ <include name="${package}/**/*.class"/>
+ </patternset>
+ </fileset>
+ </delete>
+ </target>
+
+ <!-- create jar file -->
+ <target name="jar" depends="prepare,compile" if="build.class">
+ <jar jarfile="${build.class}/${jarname}.jar"
+ basedir="${build.class}"
+ manifest="${jarname}.MF">
+ <include name="**/*.class"/>
+ <include name="**/*.properties"/>
+ <include name="**/*.css"/>
+ <include name="**/*.dtd"/>
+ <include name="**/*.form"/>
+ <include name="**/*.gif "/>
+ <include name="**/*.htm"/>
+ <include name="**/*.html"/>
+ <include name="**/*.js"/>
+ <include name="**/*.mod"/>
+ <include name="**/*.sql"/>
+ <include name="**/*.xml"/>
+ <include name="**/*.xsl"/>
+ <include name="**/*.map"/>
+ </jar>
+ </target>
+
+ <target name="test" depends="prepare">
+ </target>
+
+</project>
+
diff --git a/l10ntools/java/l10nconv/converter.MF b/l10ntools/java/l10nconv/converter.MF
new file mode 100755
index 000000000000..843d500b7548
--- /dev/null
+++ b/l10ntools/java/l10nconv/converter.MF
@@ -0,0 +1 @@
+Main-Class: com.sun.star.tooling.converter.Convert
diff --git a/l10ntools/java/l10nconv/documentation/readmeConverter.sxw b/l10ntools/java/l10nconv/documentation/readmeConverter.sxw
new file mode 100755
index 000000000000..f779e10acb2c
--- /dev/null
+++ b/l10ntools/java/l10nconv/documentation/readmeConverter.sxw
Binary files differ
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/DirtyTagWrapCheck.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/DirtyTagWrapCheck.java
new file mode 100755
index 000000000000..d304c2544bff
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/DirtyTagWrapCheck.java
@@ -0,0 +1,85 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DirtyTagWrapCheck.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Created on 2005
+ * by Christian Schmidt
+ */
+package com.sun.star.tooling.DirtyTags;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+
+
+public class DirtyTagWrapCheck {
+ static String line="";
+ public static void main(String[] args) {
+ try {
+ File fi = new File("D:\\Testfiles\\KID_helpcontent.sdf");//Copy of
+ FileReader fr = new FileReader(fi);
+ BufferedReader br = new BufferedReader(fr);
+
+ int readCounter=0;
+ int missCounter=0;
+ int lineErrorCounter=0;
+ while((line=br.readLine())!=null){
+ readCounter++;
+ String [] split = line.split("\t");
+ if(split.length<15){
+
+ lineErrorCounter++;
+ continue;
+ }
+ String string = split[10];
+ String wrapped = DirtyTagWrapper.wrapString(string);
+ String unwrapped=DirtyTagWrapper.unwrapString(wrapped);
+ if(!string.equals(unwrapped)){
+
+ missCounter++;
+ System.out.println(""+readCounter+"\n"+string+"\n"+unwrapped+"\n"+wrapped+"\n");
+ }
+ }
+ System.out.println("Fertig "+readCounter+" "+missCounter+" "+lineErrorCounter);
+ } catch (FileNotFoundException e) {
+ //
+ e.printStackTrace();
+ } catch (IOException e) {
+ //
+ e.printStackTrace();
+ } catch (DirtyTagWrapper.TagWrapperException e) {
+ System.out.println(e.getMessage()+"\n"+line+"\n");
+
+ }
+
+ }
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/DirtyTagWrapper.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/DirtyTagWrapper.java
new file mode 100755
index 000000000000..49fc08b69d32
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/DirtyTagWrapper.java
@@ -0,0 +1,252 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DirtyTagWrapper.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Created on 2005
+ * by Christian Schmidt
+ */
+package com.sun.star.tooling.DirtyTags;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Solves the problem with translating strings from the
+ * Star-Office Help. This Strings contain XML snippets
+ * (that means parts of an xml dokument). I call them 'dirty'
+ * because the start of a tag (<) and the and of an tag (>)
+ * are quoted by a single backslash(\<.....\>). This is done
+ * because the text out of th tags should not contain '<' and '>'
+ * as Entity references (&lt; or &gt;) but as readable signs.
+ * This is for translation purposes.
+ * Because translators get mad while find out the really translatable
+ * parts between all the markup information, the XLIFF Specification
+ * allows to wrap parts of a String that should not be translated by
+ * special tags (<ept>, <bpt>).
+ * This Class has two static methods that do the wrapping and unwrapping
+ * NOTE: this won't work with not 'dirty' Strings.
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+public class DirtyTagWrapper {
+
+ private static boolean doWrap=true;
+ public static void setWrapping(boolean doWrap){
+ DirtyTagWrapper.doWrap=doWrap;
+ }
+
+ /**
+ * Unwraps the 'dirty' parts of a String from ept and bpt tags
+ *
+ * @param checkString The String to unwrap
+ * @return the unwrapped String
+ */
+ public static String unwrapString(String checkString){
+ //remove the ept and bpt tags
+ String[] splitted =checkString.split("(<ept ([^<>])*>)|(</ept>)|(<bpt ([^<>])*>)|(</bpt>)|(<sub([^<>])*>)|(</sub>)|(<ex ([^<>])*/>)");
+ StringBuffer workBuffer= new StringBuffer();
+ for(int i=0;i<splitted.length;i++){
+ workBuffer.append(splitted[i]);
+ }
+ String string = new String(workBuffer);
+ //replace Entity references
+ string=string.replaceAll( "&amp;","&").replaceAll( "&lt;","<").replaceAll( "&gt;",">").replaceAll( "&quot;","\"").replaceAll( "&apos;","'");
+
+ //remove the nsub tags
+ splitted =string.split("(<sub([^<>])*>)|(</sub>)");
+ StringBuffer returnBuffer= new StringBuffer();
+ for(int i=0;i<splitted.length;i++){
+ returnBuffer.append(splitted[i]);
+ }
+ String returnString = new String(returnBuffer);
+ return returnString;
+ }
+
+
+ /**
+ * Wrap the dirty parts of a string
+ *
+ * @param checkString The String to check if there are dirty Parts to wrap
+ * @return A String with wrapped dirty parts
+ * @throws TagWrapperException
+ * @throws IOException
+ */
+ public static String wrapString(String checkString) throws TagWrapperException, IOException {
+ // if no wrapping should be done return the given string
+ if(!doWrap) return checkString;
+ // let's wrap
+ String[] parts=null;
+ int idx=0;
+ //split the string at tag ends
+ String[] parts2 = checkString.split("\\\\>");
+
+ ArrayList tagString =new ArrayList();
+ // put the while splitting lost parts to the end of the single strings
+ for(int j=0;j<parts2.length-1;j++){
+ parts2[j]+="\\>";
+ }
+ // same for the last string
+ if (checkString.endsWith("\\>")){
+ parts2[parts2.length-1]+="\\>";
+ }
+ // split the leading text from the real tag string (<...>)
+ for(int j=0;j<parts2.length;j++){
+
+ //is it just a tag
+ if(parts2[j].startsWith("\\<")){
+ tagString.add(parts2[j]);
+ // or is it a tag with leading text?
+ }else if((idx=parts2[j].indexOf("\\<"))>0&&parts2[j].indexOf("\\>")>0){
+ //...then split it in two parts
+ // the leading text
+ tagString.add(parts2[j].substring(0,(parts2[j].indexOf("\\<"))));
+ // ...and the tag
+ tagString.add(parts2[j].substring(parts2[j].indexOf("\\<")));
+
+ }else{
+ //no tag...must be text only
+ tagString.add(parts2[j]);
+ }
+
+ }
+ ArrayList tagNames=new ArrayList();
+ String item="";
+ for(int i=0;i<tagString.size();i++){
+ item=((String)tagString.get(i));
+ int start=item.indexOf("\\<")+2;
+ // check if we have an index that is ok
+ if(start==1) start=-1;
+ int end=item.lastIndexOf("\\>");
+ if(start>=0&&end>0){
+ boolean isStandalone=false;
+ if(item.endsWith("/\\>")){
+ // this is a standalone tag
+ isStandalone=true;
+ }
+ item=item.substring(start,end);
+
+ if(item.indexOf(" ")>0){
+ item=item.substring(0,item.indexOf(" "));
+ }
+ if(isStandalone){
+ item=item+"/";
+ }
+ tagNames.add(item);
+ }else{
+ tagNames.add("");
+ }
+ }
+ ArrayList tagType=new ArrayList();
+ for(int i=0;i<tagNames.size();i++){
+ if(((String)tagNames.get(i)).equals("")){
+ tagType.add("Text");
+ }else if(((String)tagNames.get(i)).startsWith("/")){
+ tagType.add("EndTag");
+ }else if(((String)tagNames.get(i)).endsWith("/")){
+ tagType.add("StartAndEndTag");
+ }else {
+ tagType.add("StartTag");
+ }
+
+ }
+
+ ArrayList tagList=new ArrayList();
+ for(int i=0;i<tagNames.size();i++){
+ tagList.add(new Tag(
+ (String)tagType.get(i),
+ (String)tagNames.get(i),
+ (String)tagString.get(i)));
+ }
+ tagType=null;
+ tagNames=null;
+ tagString=null;
+
+ TagPair start;
+ StringBuffer returnBuffer=new StringBuffer();
+ while(tagList.size()>0){
+ try{
+ start=new TagPair(tagList);
+ returnBuffer.append(start.getWrapped());
+ }catch(TagPair.TagPairConstructionException e){
+ throw (new DirtyTagWrapper()).new TagWrapperException(e);
+ }
+ }
+ TagPair.resetCounter();
+ return new String(returnBuffer);
+ }
+ /**
+ * @author Christian Schmidt 2005
+ *
+ */
+ public class TagWrapperException extends Exception {
+
+ /**
+ * Create a new Instance of TagWrapperException
+ *
+ *
+ */
+ public TagWrapperException() {
+ super();
+ //
+ }
+
+ /**
+ * Create a new Instance of TagWrapperException
+ *
+ * @param arg0
+ */
+ public TagWrapperException(String arg0) {
+ super(arg0);
+ //
+ }
+
+ /**
+ * Create a new Instance of TagWrapperException
+ *
+ * @param arg0
+ * @param arg1
+ */
+ public TagWrapperException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ //
+ }
+
+ /**
+ * Create a new Instance of TagWrapperException
+ *
+ * @param arg0
+ */
+ public TagWrapperException(Throwable arg0) {
+ super(arg0);
+ //
+ }
+
+ }
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/Tag.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/Tag.java
new file mode 100755
index 000000000000..7495736ab68c
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/Tag.java
@@ -0,0 +1,249 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Tag.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Created on 2005
+ * by Christian Schmidt
+ */
+package com.sun.star.tooling.DirtyTags;
+
+import java.io.IOException;
+import java.util.Map;
+
+import com.sun.star.tooling.converter.ExtMap;
+
+/**
+ * @author Christian Schmidt 2005
+ *
+ */
+public class Tag {
+ private static int indent=0;
+ Map tagNames;
+ private String tagType;
+ private String tagName;
+ private String tagString;
+ public static Tag EMPTYTAG=new Tag("","","");
+
+ /**
+ * Create a new Instance of Tag
+ *
+ * @param tagType
+ * @param tagName
+ * @param tagString
+ */
+ public Tag(String tagType, String tagName, String tagString) {
+
+ this.tagType=tagType;
+ this.tagName=tagName;
+ this.tagString=tagString;
+
+ tagNames=new ExtMap();
+ tagNames.put("link","name");
+ tagNames.put("caption","xml-lang");
+ tagNames.put("alt","xml-lang");
+ }
+
+ public String getWrappedTagString() throws IOException{
+ if(this.canHaveTranslateableContent()){
+ return this.wrapTagStringIntern();
+ }else{
+ return xmlString(this.tagString);
+ }
+ }
+
+ private final String xmlString( final String string) throws java.io.IOException {
+ if (string == null)
+ return string; // ""
+ String str = string;
+
+ for(int i=0;i<str.length();i++){
+ if(str.charAt(i)=='&'){
+ str=str.substring(0, i)+"&amp;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='<'){
+ str=str.substring(0, i)+"&lt;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='>'){
+ str=str.substring(0, i)+"&gt;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='"'){
+ str=str.substring(0, i)+"&quot;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='\''){
+ str=str.substring(0, i)+"&apos;"+str.substring(i+1);
+ continue;
+ }
+ }
+
+ return str;
+ }
+ /**
+ * @return
+ */
+ private boolean canHaveTranslateableContent() {
+ return (tagNames.containsKey(this.tagName));
+
+ }
+
+ /**
+ * @throws IOException
+ *
+ */
+ private String wrapTagStringIntern() throws IOException {
+
+
+ String[] split=this.tagString.split("=");
+ int length=split.length;
+ // no attribute found;
+ if (length==0) return xmlString(tagString);
+ else{
+ int i=0;
+
+ while(i<length-1/*the last part can only contain an attribute value*/){
+ String attributeName = split[i].trim();
+ if(split[i]. indexOf("</sub>")<0) split[i]=xmlString(split[i]);
+ i++;
+ String value;
+ attributeName=(attributeName.substring(attributeName.lastIndexOf(" ")).trim());
+ if((value=translateableAttributeValue(this.tagName)).equals(attributeName)){
+ int valueStart=0;
+ int valueEnd=0;
+
+ // get the value to the found attribute name
+ // it must either be surrounded by '"'...
+ if((valueStart=split[i].indexOf('"'))>=0){
+ valueEnd = split[i].lastIndexOf('"');
+ //...or surrounded by "'"
+ }else if((valueStart=split[i].indexOf("'"))>=0){
+ valueEnd = split[i].lastIndexOf("'");
+ }else{
+ // there seems to be an error,
+ // we found an '=' (we split there) but no '"' or '''
+ // but although we don't check the syntax
+ // we just continue
+ continue;
+ }
+ //ok we found the border of a value that might be translated
+ //now we wrap it with the tags
+
+ split[i]=xmlString(split[i].substring(0,valueStart+1))+"<sub>"+xmlString(split[i].substring(valueStart+1,valueEnd))+"</sub>"+xmlString(split[i].substring(valueEnd));
+
+ }
+ }
+ String wrappedString="";
+ // we have the wrapped parts, now we put them together
+ int j=0;
+ for(j=0;j<split.length-1;j++){
+ wrappedString+=(split[j]+"=");
+ }
+ wrappedString+=split[j];
+// System.out.println(this.tagString);
+// System.out.println(wrappedString);
+ return wrappedString;
+ }
+
+ }
+
+
+
+ /**
+ * @param tagName the name of the tag to check
+ * @return the name of the attribute that can contain translateable value
+ */
+ private String translateableAttributeValue(String tagName) {
+
+ return (String)this.tagNames.get(tagName);
+ }
+
+
+ /**
+ * Create a new Instance of Tag
+ *
+ *
+ */
+ public Tag(String tagString) {
+ this(extractTagType(extractTagName(tagString)),extractTagName(tagString),tagString);
+ }
+
+ private static String extractTagName(String tagString){
+
+ int start=tagString.indexOf('<')+1;
+ int end=tagString.lastIndexOf('\\');
+ if(start>=0&&end>0){
+ tagString=tagString.substring(start,end);
+
+ if(tagString.indexOf(" ")>0){
+ tagString=tagString.substring(0,tagString.indexOf(" "));
+ }
+ return tagString;
+ }else{
+ return "";
+ }
+ }
+ private static String extractTagType(String tagName){
+ if(tagName.equals("")){
+ return "Text";
+ }else if(tagName.startsWith("/")){
+ return "EndTag";
+ }else if(tagName.endsWith("/")){
+ return "StartAndEndTag";
+ }else {
+ return "StartTag";
+ }
+ }
+
+ /**
+ * @return Returns the tagName.
+ */
+ public String getTagName() {
+ return this.tagName;
+ }
+ /**
+ * @return Returns the tagString.
+ */
+ public String getTagString() {
+ return this.tagString;
+ }
+ /**
+ * @return Returns the tagType.
+ */
+ public String getTagType() {
+ return this.tagType;
+ }
+
+
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/TagPair.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/TagPair.java
new file mode 100755
index 000000000000..7993fc9cf0a4
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/DirtyTags/TagPair.java
@@ -0,0 +1,310 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TagPair.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Created on 2005
+ * by Christian Schmidt
+ */
+package com.sun.star.tooling.DirtyTags;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+
+/**
+ * @author Christian Schmidt 2005
+ *
+ */
+public class TagPair {
+
+
+ private Tag startTag=Tag.EMPTYTAG;
+ private Tag endTag=Tag.EMPTYTAG;
+ private String startingText="";
+ private ArrayList enclosedTags=new ArrayList();
+ private long id;
+ private static int ElementCounter=1;
+ private String endingText="";
+
+ /**
+ * @author Christian Schmidt 2005
+ *
+ */
+ public class TagPairConstructionException extends Exception {
+
+ /**
+ * Create a new Instance of TagPairConstructionException
+ *
+ * @param string
+ */
+ public TagPairConstructionException(String string) {
+
+ }
+
+ }
+
+ /**
+ * Create a new Instance of TagPair
+ *
+ *
+ */
+ public TagPair() {
+
+ }
+
+
+ /**
+ * Create a new Instance of TagPair
+ *
+ * Find matching tags in tagList, create a TagPair of it, create
+ * tagPairs from the content in the tagPair and remove all used
+ * tags from tagList. The rest of the tagList starts after the
+ * endTag of this TagPair.
+ *
+ * @param tagList a List of the tags to check
+ *
+ * @throws TagPairConstructionException
+ */
+ public TagPair(ArrayList tagList) throws TagPairConstructionException {
+
+ if(tagList.size()==0){
+ return;
+ }
+ ArrayList contentList=new ArrayList();;
+ Tag tag=(Tag)tagList.get(0);
+ tagList.remove(0);
+
+
+ if("Text".equals(tag.getTagType())){
+ // is this Text the only content
+ // of this Tag ?
+ if(tagList.size()==0){
+ //yes...then it is the starting Text of this TagPair
+ this.startingText=tag.getTagString();
+ return;
+ }else{
+ //no...the tag is normal content
+ contentList.add(tag);
+ }
+ this.startingText=tag.getTagString();
+
+ }else if("EndTag".equals(tag.getTagType())){
+ //ERRor throw EXception
+ }else if("StartTag".equals(tag.getTagType())){
+ // find the matching end tag
+ this.startTag=tag;
+ Iterator iter=tagList.iterator();
+
+ int equivalentTagCounter=0;
+ while(iter.hasNext()){
+ //is this the end tag?
+ if((tag=(Tag)iter.next()).getTagName().equals('/'+this.startTag.getTagName())&&equivalentTagCounter==0){
+ //found the corresponding end tag
+
+ //this TagPair is complete
+ //so it needs an id
+ this.id=TagPair.ElementCounter++;
+ this.endTag=tag;
+ //...remove it from list
+ tagList.removeAll(contentList);
+ tagList.remove(tag);
+ break;
+ }else{
+ // tag is not the end tag
+ // so it is between the start and the end tag
+ // and belongs to the content
+ // but first check if it has the same name as the current tag
+ if(tag.getTagName().equals(this.startTag.getTagName())){
+ // if this is a start tag like the current start tag
+ // we count it to find out the matching end tag in nested tags
+ if(tag.getTagType().equals("StartTag")){
+ equivalentTagCounter++;
+ }
+ }
+ if(tag.getTagName().equals("/"+this.startTag.getTagName())){
+ if(tag.getTagType().equals("EndTag")){
+ equivalentTagCounter--;
+ }
+ }
+
+ contentList.add(tag);
+ }
+ }
+ //found the end tag ?
+ //no...
+ if (this.endTag.getTagType()==""){
+
+ throw new TagPairConstructionException("ERROR: Missing end tag ("+
+ this.startTag.getTagString()+").");
+ //...yes
+ }else{
+ //We need to check whether the content is starting or ending with text
+ //...check starting with text
+ if(contentList.size()>=1&&((String)((Tag)contentList.get(0)).getTagType()).equals("Text")){
+ //yes...store it as startingText
+ this.startingText=(String)((Tag)contentList.get(0)).getTagString();
+ //remove it from list
+ contentList.remove(0);
+ }
+ // ...check ending with text
+ if(contentList.size()>=1&&((String)((Tag)contentList.get(contentList.size()-1)).getTagType()).equals("Text")){
+ //yes...store it as endingText
+ this.endingText=(String)((Tag)contentList.get(contentList.size()-1)).getTagString();
+ //remove it from list
+ contentList.remove(contentList.size()-1);
+ }
+ //create the list of tags enclosed by this tagPair
+ createEnclosedTags(contentList);
+ }
+ //if stand AloneTag create own TagObject...give ID...add to List
+ }else if("StartAndEndTag".equals(tag.getTagType())){
+ this.startTag=tag;
+ this.endTag=new Tag("EndOfStandAlone","","");
+ createEnclosedTags(contentList);
+ }
+
+ }
+
+ /**
+ * @param contentList
+ * @throws TagPairConstructionException
+ */
+ private void createEnclosedTags(ArrayList contentList) throws TagPairConstructionException {
+ while(contentList.size()>0){
+ //create the inner TagPairs
+ this.enclosedTags.add(new TagPair(contentList));
+ }
+
+ }
+
+ public String toString(){
+ StringBuffer outString= new StringBuffer(this.startTag.toString());
+ TagPair help=new TagPair();
+ Iterator iter=enclosedTags.iterator();
+ outString.append(this.startingText);
+ while(iter.hasNext()){
+ if((help=(TagPair)iter.next())==null){
+ continue;
+ }else{
+ outString.append(help.toString());
+ }
+ }
+ outString.append(this.endingText);
+ outString.append(this.endTag.toString());
+ return new String(outString);
+ }
+
+ public String getWrapped() throws IOException{
+ Iterator iter=enclosedTags.iterator();
+ StringBuffer returnBuffer=new StringBuffer();
+
+ returnBuffer.append(wrap(this.startTag)+xmlString(this.startingText));
+ while(iter.hasNext()){
+ returnBuffer.append(((TagPair)iter.next()).getWrapped());
+ }
+ returnBuffer.append(xmlString(this.endingText)+wrap(this.endTag));
+
+
+
+ return new String(returnBuffer);
+ }
+
+ private String wrap(Tag tag) throws IOException{
+ String string="";
+ //can be a start tag
+ if(tag.getTagType().startsWith("Start")){
+ return new String("<bpt id='"+this.id+"'>"+tag.getWrappedTagString()+"</bpt>");
+ //...or a end tag
+ }else if (tag.getTagType().startsWith("End")){
+ //maybe the end tag of a Start and end tag
+// if("EndOfStandAlone".equals(tag.getTagType())){
+// return new String("<ex id='"+this.id+"'/>");
+// }else{
+ string=tag.getWrappedTagString();
+ return new String("<ept id='"+this.id+"'>"+string+"</ept>");
+// }
+
+ //...or text
+ }else{
+ return xmlString(tag.getTagString());
+ }
+ }
+ /**
+ * Replaces all characters that mustn't be in XLIFF PCdata
+ *
+ * @param string the string to check
+ * @return the checked string with all characters replaced
+ * @throws java.io.IOException
+ */
+ private final String xmlString( final String string) throws java.io.IOException {
+ if (string == null)
+ return string; // ""
+ String str = string;
+
+ for(int i=0;i<str.length();i++){
+ if(str.charAt(i)=='&'){
+ str=str.substring(0, i)+"&amp;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='<'){
+ str=str.substring(0, i)+"&lt;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='>'){
+ str=str.substring(0, i)+"&gt;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='"'){
+ str=str.substring(0, i)+"&quot;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='\''){
+ str=str.substring(0, i)+"&apos;"+str.substring(i+1);
+ continue;
+ }
+ }
+
+ return str;
+ }
+
+ /**
+ *
+ */
+ public static void resetCounter() {
+ TagPair.ElementCounter=1;
+
+ }
+
+
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Convert.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Convert.java
new file mode 100755
index 000000000000..5b1fb6c62b61
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Convert.java
@@ -0,0 +1,553 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Convert.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * the main Class
+ *
+ * Command Line arguments are reviewed
+ * and a Converter is constructed
+ */
+package com.sun.star.tooling.converter;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Calendar;
+
+import com.sun.star.tooling.DirtyTags.DirtyTagWrapper;
+
+/**
+ * The main class of the converter tool
+ *
+ * The converter tool is command line based.
+ * Its classes allow the converting between the
+ * file formats sdf, gsi and <a href="http://www.oasis-open.org/committees/xliff/documents/cs-xliff-core-1.1-20031031.htm">xliff</a>.
+ *
+ * Those file formats are used in localization
+ * of Star-Office and Open-Office.
+ *
+ * Information about the whole localization process can be found in
+ * <a href="http://ded-1.germany.sun.com/webcontent/guidelines/pdf/L10NSO8.pdf">http://ded-1.germany.sun.com/webcontent/guidelines/pdf/L10NSO8.pdf</a>
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+public class Convert {
+
+ private static Calendar cal;
+
+ private static final String EMPTY = "";
+
+ /**
+ * The name of the file containing the debug information
+ * that where found while converting (every output goes here too)
+ */
+ private static String dbgName = EMPTY;
+
+ /**
+ * the character that separates the extension from the file name
+ */
+ private static final char extensionSeperator = '.';
+
+ /**
+ * the log File
+ */
+ private static File log;
+
+ /**
+ * the name of the log file
+ */
+ private static String logString = EMPTY;
+
+ /**
+ * indicates whether existing sources should be overwritten
+ * without asking
+ */
+ private static boolean overwrite = false;
+
+ /**
+ * A second Source File needed for GSI Merging
+ */
+ private static File secondSource;
+
+ //private static final char pathSeperator = '\\';
+
+ /**
+ * The language that should be the source language
+ * that means the language to translate from
+ */
+ private static String sourceLanguage = "en-US";
+
+ /**
+ * the name of the source file
+ */
+ private static String sourceName = EMPTY;
+
+ /**
+ * the type of the source file (sdf,xliff,...)
+ */
+ private static String sourceType = EMPTY;
+
+ /**
+ * The time when converting started
+ */
+ private static String startTime = EMPTY;
+ /**
+ * The language that should be the target language
+ * that means the language to translate to
+ */
+ private static String TargetLanguage = EMPTY;
+
+ /**
+ * the name of the target file
+ */
+ private static String targetName = EMPTY;
+
+ /**
+ * the type of the target file (sdf,xliff,...)
+ */
+ private static String targetType = EMPTY;
+
+ /**
+ * Store the current version ID and number of this tool
+ */
+ final static String version = " Prod.20050710:1255 ";
+
+ /**
+ * The name of the (original) sdf file used as second source for gsi->sdf merging
+ */
+ private static String secondSourceName=EMPTY;
+ /**
+ * Indicate whether strings in xliff files should
+ * be wrapped with ept/bpt or sub tags to enable translation tools
+ * to synchronize source language string with there translation
+ *
+ * @see <a href="http://ded-1.germany.sun.com/webcontent/guidelines/pdf/L10NSO8.pdf">http://ded-1.germany.sun.com/webcontent/guidelines/pdf/L10NSO8.pdf</a>
+ */
+ private static boolean doWrap=true;
+
+
+
+ public static void main(String[] args) throws IOException, Exception {
+ try{
+
+ //go, parse and check the command line parameters
+ ParameterChecker.checkClParameters(args);
+ ParameterChecker.createContentOfClParameters();
+ //Initialize the tagWrapper
+ DirtyTagWrapper.setWrapping(doWrap);
+ //create an instance of converter
+ Converter conv = new Converter(sourceType, sourceName, sourceLanguage,
+ targetType, targetName, TargetLanguage,secondSourceName, overwrite);
+ // get aktual time
+ cal = Calendar.getInstance();
+ startTime = cal.getTime().toString();
+ //show infos
+ printPreamble();
+ //do the job
+ conv.convert();
+
+ showStatistic();
+
+ //close log, debug...
+ OutputHandler.closeAll();
+
+ } catch(Exception e){
+ System.out.print("An EXCEPTION occured, please check your commad line settings \n"+e.getMessage());
+ System.exit(-1);
+ }catch(Throwable t){
+ System.out.print("A FATAL ERROR occured, please check your commad line settings \n"+t.getMessage());
+ System.exit(-1);
+ }
+
+ }
+
+ /**
+ * show the command line help
+ */
+ private static void printHelp() {
+
+ final String ls = System.getProperty("line.separator");
+ System.out
+ .println(
+
+ "File Converting Tool 'converter' Version "
+ + Convert.version
+ + ls
+ + "Converts SDF files to wellformed XLIFF or GSI files and vice versa" + ls
+ + ls
+ + "Use: " + ls
+ + "convert [-h]|[SourcePath [TargetPath] [-T Type] [[-S Type [secondSourcePath]] " + ls
+ + " [-s LanguageID] [-t LanguageID] [-l [LogPath]] [-o]]" + ls
+ + ls
+ + "-h show this help." + ls
+ + "SourcePath path of the file to convert." + ls
+ + "secondSourcePath path of the SDF file to merge to (GSI -> SDF only!)." + ls
+ + "TargetPath path where to store the result." + ls
+ + "LogPath path of the log file" + ls
+ + "-T Type the type of the target file (xliff,sdf,gsi)" + ls
+ + "-S Type the type of the source file (xliff,sdf,gsi)" + ls
+ + "-s LanguageID the ISO language code of the source language (de, fr...)." + ls
+ + " Default is 'en-US' " + ls
+ + "-t LanguageID the language code of the target language (de, fr...)." + ls
+ + " Default is first found Language other than source language." + ls
+ + "-l [LogPath] write a log file, you can name the file." + ls
+ + "-o overwrite existing files without asking." + ls
+ + "-nw disable the wrapping with ept/bpt tags." + ls
+ + ls
+ + "The created files were stored in the SourceFile Path if nothing else is given. " + ls
+ + "The extension is '.xliff','.sdf' depending on the source file and '.log' " + ls
+ + "for the logfile." + ls);
+ }
+
+ /**
+ * show the parameters the converter starts with
+ *
+ * @throws IOException
+ */
+ final private static void printPreamble() throws IOException {
+ OutputHandler.out(EMPTY);
+ OutputHandler.out("Source File is: " + sourceName);
+ OutputHandler.out("Target File is: " + targetName);
+ if (OutputHandler.doLog) {
+ OutputHandler.out("Log File is: " + logString);
+ } else {
+ OutputHandler.out("Log File is: disabled");
+ }
+
+ OutputHandler.out(EMPTY);
+
+ }
+
+ /**
+ * show some statistic data
+ *
+ * @throws IOException
+ */
+ final private static void showStatistic() throws IOException {
+ OutputHandler.dbg(EMPTY);
+ OutputHandler
+ .out((targetType.equalsIgnoreCase("xliff") ? "TransUnits written: "
+ : "Lines written : ")
+ + Converter.getLineCounter());
+ OutputHandler.dbg(EMPTY);
+ OutputHandler.out("Started at : " + Convert.startTime);
+ Convert.cal = Calendar.getInstance();
+ OutputHandler.out("Finished at : " + Convert.cal.getTime());
+ OutputHandler.dbg(EMPTY);
+
+ }
+
+ /**
+ * Get the extensiion of a file name
+ * (sdf,xliff,gsi)
+ *
+ * @param sourceString the file name
+ * @return the extension
+ */
+ static protected String extractExtension(String sourceString) {
+ String ext = sourceString.substring(sourceString
+ .lastIndexOf(Convert.extensionSeperator) + 1);
+ return ext;
+ }
+
+// static protected String extractFileName(String sourceString) {
+// String sName = EMPTY;
+// sName = (sourceString.substring(sourceString
+// .lastIndexOf(File.separator) + 1, sourceString
+// .lastIndexOf(Convert.extensionSeperator)));
+//
+// return sName;
+// }
+//
+// static protected String extractPath(String sourceString) {
+// String sPath = sourceString.substring(0, sourceString
+// .lastIndexOf(File.separator) + 1);
+// return sPath;
+// }
+
+ /**
+ *
+ */
+ public Convert() {
+ }
+
+ /**
+ *
+ * Verify a parameter array and create content useable by the programm
+ * from the switches and attributes set at command line
+ *
+ * @author Christian Schmidt 2005
+ */
+ private static class ParameterChecker {
+
+ /**
+ * Holds the path of the source file
+ */
+ private static String filePath;
+ /**
+ * Holds the name of the source file
+ */
+ private static String fileName;
+
+ /**
+ * Create a new Instance of ParameterChecker
+ *
+ *
+ */
+ public ParameterChecker(){};
+ /**
+ * Checks the command line parameters
+ *
+ * @param args the parameters to check and to parse
+ * @throws IOException
+ */
+ private static void checkClParameters(String[] args) throws IOException {
+ try {
+ //show help if no attrributes...
+ if (args.length == 0) {
+ printHelp();
+ System.exit(-1);
+ }
+ //...or attribute is -h
+ if (args[0].equals("-h")) {
+ printHelp();
+ System.exit(0);
+ }
+ if (args[0].equals("-ver")) {
+ System.out.println("File Converting Tool Version "+version);
+ System.exit(0);
+ }
+ //source file Location and path is always first attribute
+ sourceName = new String(args[0]);
+
+ File source = new File(sourceName);
+ //break if there is no source to convert
+ if (!source.exists())
+ throw new IOException("ERROR:Can not find Source File '"
+ + sourceName + "'. Aborting...");
+
+ // String name=source.getName();
+ // String parent=source.getParent();
+ // String path=source.getPath();
+
+ filePath = (source.getParent()==null)?"":source.getParent()+File.separator; //extractPath(sourceName);
+ fileName = source.getName().substring(0,source.getName().lastIndexOf(extensionSeperator));
+
+ for (int i = 1; i < args.length; i++) {
+
+
+ if ("-s".equals(args[i])) {
+ if (args.length > i + 1) {
+ sourceLanguage = args[++i];
+
+ } else {
+ throw new ConverterException(
+ "missing argument for -s source language");
+ }
+ continue;
+ }
+
+ if ("-S".equals(args[i])) {
+ if (args.length > i + 1) {
+ sourceType = args[++i];
+ if (args.length > i +1 &&!args[i+1].startsWith("-")) {
+ secondSourceName = args[++i];
+ }
+
+ } else {
+ throw new ConverterException(
+ "missing argument for -S source type");
+ }
+ continue;
+ }
+
+ if ("-T".equals(args[i])) {
+ if (args.length > i + 1) {
+ targetType = args[++i];
+
+
+ } else {
+ throw new ConverterException(
+ "missing argument for -T target type");
+ }
+ continue;
+ }
+
+ if ("-l".equals(args[i])) {
+ OutputHandler.doLog = true;
+ if (args.length > i + 1
+ && (!args[i + 1].startsWith("-"))) {
+ logString = args[++i];
+ } else {
+ logString = EMPTY;
+ }
+ continue;
+ }
+
+ if ("-o".equals(args[i])) {
+ overwrite = true;
+ continue;
+ }
+
+ if ("-nw".equals(args[i])) {
+ doWrap = false;
+ continue;
+ }
+
+ if ("-h".equals(args[i])) {
+ printHelp();
+ System.exit(0);
+ }
+
+ if ("-dbg".equals(args[i])) {
+ OutputHandler.doDebug = true;
+ continue;
+ }
+
+ if ("-t".equals(args[i])) {
+ if (args.length > i + 1) {
+ TargetLanguage = args[++i];
+ } else {
+ throw new ConverterException(
+ "missing argument for -t target language");
+ }
+ continue;
+ }
+
+ if (i == 1 && !args[i].startsWith("-")) { //target file
+ // found
+ targetName = args[i];
+ continue;
+ }
+ //if we come here we
+ //can not match the Attribute
+ throw new ConverterException("unknown Attribute: "
+ + args[i]);
+
+
+ }//end for
+ } catch (ConverterException e) {
+ OutputHandler.out("ERROR: "+e.getMessage());
+ System.exit(-1);
+ } catch (Throwable t){
+ System.out.print("An Error occured while parsing the command line,\n please check your commad line settings.\n "+t.getMessage());
+ System.exit(-1);
+ }
+
+ }//end checkClParameters
+
+ /**
+ * Creates the appropriate content of what ever data
+ * we found in the command line
+ *
+ * @throws IOException
+ */
+ private static void createContentOfClParameters() throws IOException {
+
+ try {
+ if (OutputHandler.doDebug) {
+ // if the -dbg switch is set, we
+ // create
+ // a file that gets all information
+ // produced by this tool
+
+ OutputHandler.dbgFile = new BufferedWriter(new FileWriter(
+ new File(new String(filePath + fileName + ".dbg"))));
+ }
+
+ if (OutputHandler.doLog) {// create a logfile?
+ //given at command line?
+ if (EMPTY.equals(logString) || logString == null) {
+ logString = new String(filePath + fileName + ".log");
+ }
+ log = FileMaker.newFile(logString, overwrite);
+ OutputHandler.logFile = (new BufferedWriter(new FileWriter(
+ log)));
+ }
+
+ if (EMPTY.equals(sourceType) || sourceType == null) {
+ // not given at command line?
+ if (!(EMPTY.equals(sourceName) || sourceName == null)) {
+ sourceType = extractExtension(sourceName);
+ } else {
+ throw new ConverterException("Source type is missing");
+ }
+ }
+
+ if(sourceType.equalsIgnoreCase("gsi")){
+
+ if(EMPTY.equals(Convert.secondSourceName)){
+ Convert.secondSourceName=filePath+fileName+".sdf";
+ }
+ //secondSource=new File(Convert.secondSourceName);
+
+ }
+
+ if (EMPTY.equals(sourceName)) {
+ sourceName = filePath + fileName + "." + sourceType;
+ }
+ //no target type given at command line?
+ if (EMPTY.equals(targetType) || targetType == null) {
+ if (!(EMPTY.equals(targetName) || targetName == null)) {
+ targetType = extractExtension(targetName);
+ } else {
+ throw new ConverterException("Target type is missing");
+
+ }
+ }
+ //no target File specified at command line
+ if (EMPTY.equals(targetName) || targetName == null) {
+ targetName = filePath + fileName + "." + targetType;
+ if (targetName.equals(Convert.secondSourceName)){
+ OutputHandler.out("ERROR: \nSource '"+Convert.secondSourceName+"' and \nTarget'"+targetName+"' are the same");
+ System.exit(0);
+ }else if (targetName.equals(Convert.sourceName)){
+ OutputHandler.out("ERROR: \nSource '"+Convert.sourceName+"' and \nTarget'"+targetName+"' are the same");
+ System.exit(0);
+ }
+ }else if (targetName.equals(Convert.secondSourceName)){
+ OutputHandler.out("ERROR: \nSource '"+Convert.secondSourceName+"' and \nTarget'"+targetName+"' are the same");
+ System.exit(0);
+ }else if (targetName.equals(Convert.sourceName)){
+ OutputHandler.out("ERROR: \nSource '"+Convert.sourceName+"' and \nTarget'"+targetName+"' are the same");
+ System.exit(0);
+ }
+
+
+ } catch (ConverterException e) {
+ OutputHandler.out(e.getMessage());
+ }
+
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Converter.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Converter.java
new file mode 100755
index 000000000000..7ec09bcb411a
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Converter.java
@@ -0,0 +1,523 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Converter.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Converter.java
+ *
+ * create Source and Target
+ * for converting
+ * TODO maybe a factory would be good here
+ */
+
+package com.sun.star.tooling.converter;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ *
+ * This class handles the creating of the source to read from,
+ * the target to write to and the appropriate DataHandler
+ *
+ * @author Christian Schmidt 2005
+ */
+public final class Converter {
+
+ /**
+ * the used charset f.e. UTF-8
+ */
+ private final static String CHARSET = new String("UTF-8");
+
+ private static final String EMPTY = new String("");
+
+ /**
+ * The DataHandler use to connect reader and writer
+ */
+ private static DataHandler handler;
+
+ /**
+ * Counting the lines written by a writer
+ */
+ private static int lineCounter;
+
+ /**
+ * The target to write to
+ */
+ private static DataWriter theTargetWriter;
+
+
+ /**
+ * Overwrite existing files
+ */
+ private boolean overwrite = false;
+ /**
+ * The source to read from
+ */
+ private Source reader;
+ /**
+ * The name of the source file
+ */
+ private String sourceString;
+ /**
+ * the Type of the Source file(SDF,GSI,XLIFF)
+ */
+ private String sourceType;
+ /**
+ * The name of the target fille
+ */
+ private String targetString;
+ /**
+ * the Type of the Target file(SDF,GSI,XLIFF)
+ */
+ private String targetType;
+ /**
+ * The writer that handles the output
+ */
+ private Target writer;
+
+ /**
+ * The sourceLanguage
+ */
+ String sourceLanguage = "en-US";
+
+ /**
+ * The targetLanguage
+ */
+ String targetLanguage = "";
+
+ /**
+ * The name of the second source, needed for GSI to SDF merge
+ */
+ private String secondSourceString=EMPTY;
+
+
+ /**
+ * Get the line counter
+ * @return Returns the lineCounter.
+ */
+ public static int getLineCounter() {
+ return lineCounter;
+ }
+
+ /**
+ * increment the lineCounter
+ */
+ final static void countLine() {
+ lineCounter++;
+ }
+
+ /**
+ * Creates a new instance of Converter
+ *
+ * @param sourceType the type of the sourceFile
+ * @param sourceString the name of the sourceFile
+ * @param SourceLanguage the ISO Id of the sourceLanguage
+ * @param targetType the type of the targetFile
+ * @param targetString the name of the targetFile
+ * @param TargetLanguage the ISO Id of the targetLanguage
+ * @param secondSourceString the name of the second sourceFile (GSI merge only)
+ * @param overwrite indicates whether overwrite existing files
+ * @throws IOException
+ * @throws Exception
+ */
+ public Converter(String sourceType, String sourceString,
+ String SourceLanguage, String targetType, String targetString,
+ String TargetLanguage,String secondSourceString, boolean overwrite) throws IOException,
+ Exception {
+
+ this.sourceType = sourceType;
+ this.sourceString = sourceString;
+ this.sourceLanguage = SourceLanguage;
+ this.targetType = targetType;
+ this.targetString = targetString;
+ this.targetLanguage = TargetLanguage;
+ this.secondSourceString=secondSourceString;
+ this.overwrite = overwrite;
+
+ handler = new DataHandler();
+
+ if ("sdf".equalsIgnoreCase(sourceType)) {
+ reader = new SDFSource();
+ } else if ("xliff".equalsIgnoreCase(sourceType)||"dbxliff".equalsIgnoreCase(sourceType)) {
+ reader = new XLIFFSource();
+ } else if ("gsi".equalsIgnoreCase(sourceType)) {
+ reader = new GSISource();
+ } else {
+ throw new ConverterException("Unknown Source File Type: '"+sourceType+"'");
+ }
+
+ if ("sdf".equalsIgnoreCase(targetType)) {
+ writer = new SDFTarget();
+ } else if ("xliff".equalsIgnoreCase(targetType)) {
+ writer = new XLIFFTarget();
+ } else if ("gsi".equalsIgnoreCase(targetType)) {
+ writer = new GSITarget();
+ } else {
+ throw new ConverterException("Unknown Target File Type: '"+targetType+"'");
+ }
+
+ }
+
+ /**
+ * Do the converting from the source file format to the target file format
+ *
+ * @throws IOException
+ */
+ public final void convert() throws IOException {
+
+ try {
+
+ reader.convertTo(writer);
+
+ //TODO this belongs in the Target Class
+ theTargetWriter.flush();
+ theTargetWriter.close();
+ } catch (Exception e) {
+ OutputHandler.out(e.getMessage());
+ }
+
+ }
+
+
+ /**
+ *
+ * Encapsulate the reading from an GSI file
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+ private class GSISource implements Source {
+ DataReader theSourceReader;
+ /**
+ * Create a new Instance of GSISource
+ *
+ * @throws IOException
+ * @throws Exception
+ */
+ public GSISource() throws IOException {
+
+ theSourceReader = new GSIandSDFMerger(new File(sourceString),new File(secondSourceString), sourceLanguage,
+ targetLanguage, CHARSET);
+ }
+
+ public void convertTo(Target t) {
+
+ try {
+ theTargetWriter = t.getWriter();
+ while (handler.fillDataFrom(theSourceReader)) {
+
+ theTargetWriter.getDatafrom(handler);
+ theTargetWriter.writeData();
+ }
+ } catch (IOException e) {
+ OutputHandler.out(e.getMessage());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ }
+ /**
+ *
+ * Encapsulate to write to a GSI file
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+ private class GSITarget implements Target {
+
+ File target;
+
+ /**
+ * Create a new Instance of GSITarget
+ *
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ public GSITarget() throws FileNotFoundException, IOException {
+
+ target = FileMaker.newFile(targetString, overwrite);
+ theTargetWriter = new GSIWriter(new BufferedOutputStream(
+ new FileOutputStream(target)), CHARSET);
+ }
+
+ public DataWriter getWriter() {
+
+ return theTargetWriter;
+ }
+
+ }
+ /**
+ *
+ * Encapsulate the reading from an SDF file
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+ private final class SDFSource implements Source {
+
+ DataReader Source;
+
+ /**
+ * Create a new Instance of SDFSource
+ * @throws IOException
+ * @throws Exception
+ */
+ public SDFSource() throws IOException, Exception {
+
+ Source = new SDFReader(new File(sourceString), sourceLanguage,
+ targetLanguage, CHARSET);
+ }
+
+ public void convertTo(Target t) {
+ try {
+ theTargetWriter = t.getWriter();
+ while (handler.fillDataFrom(Source)) {
+
+ theTargetWriter.getDatafrom(handler);
+ theTargetWriter.writeData();
+ }
+
+ } catch (IOException e) {
+ OutputHandler.out(e.getMessage());
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ }
+ /**
+ * Encapsulate writing to a SDF file
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+ private class SDFTarget implements Target {
+
+ /**
+ * Create a new Instance of SDFTarget
+ *
+ * @throws IOException
+ */
+ public SDFTarget() throws IOException {
+ File target = FileMaker.newFile(targetString, overwrite);
+ theTargetWriter = new SDFWriter(new BufferedOutputStream(
+ new FileOutputStream(target)), CHARSET);
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.Converter.Target#getWriter()
+ */
+ public DataWriter getWriter() {
+
+ return theTargetWriter;
+ }
+
+ }
+
+ /**
+ * The interface for all convertable sources
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+ private interface Source {
+
+ DataReader Source=null;
+ /**
+ * Convert this. to the designated target
+ * @param target the target of the converting
+ * @throws IOException
+ */
+ abstract void convertTo(Target target) throws IOException;
+ }
+
+ /**
+ * The interface for all creatable targets
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+ private interface Target {
+ /**
+ * The writer to use
+ */
+ public OutputStream writer = null;
+
+ /**
+ * Get the writer
+ * this target uses to write the
+ * data in the correct format.
+ *
+ * @return the used DataWriter
+ */
+ abstract DataWriter getWriter();
+
+ }
+ /**
+ * Encapsulate the reading from an XLIFF file
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+ private class XLIFFSource implements Source {
+ File source;
+
+ /**
+ * Create a new Instance of XLIFFSource
+ *
+ *
+ */
+ public XLIFFSource() {
+
+ source = new File(sourceString);
+ }
+
+ public void convertTo(Target t) throws IOException {
+ try {
+ System.setProperty("entityExpansionLimit", "1000000");
+ boolean laden = source.canRead();
+ if (laden) {
+ DefaultHandler contentHandler=null;
+ if("dbxliff".equalsIgnoreCase(sourceType)){
+ contentHandler = new XLIFFReader(handler, t
+ .getWriter(),false);
+ }else{
+ contentHandler = new XLIFFReader(handler, t
+ .getWriter());
+ }
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware( true );
+ factory.setValidating( true );
+
+ SAXParser parser=factory.newSAXParser();
+ XMLReader xliffreader=parser.getXMLReader();
+
+
+
+// XMLReader xliffreader = XMLReaderFactory
+// .createXMLReader("org.apache.crimson.parser.XMLReaderImpl");
+ xliffreader.setErrorHandler(contentHandler);
+ xliffreader.setContentHandler(contentHandler);
+ /* one possibility to resolve an extern entity (DTD) */
+ EntityResolver res = new Resolver();
+ xliffreader.setEntityResolver(res);
+ /*
+ * a second possibility to resolve an extern entity (DTD)
+ *
+ * xliffreader.setFeature("xml.org/sax/features/validation",true);
+ * xliffreader.setEntityResolver(new EntityResolver() {
+ * public InputSource resolveEntity(java.lang.String
+ * publicId, java.lang.String systemId) throws SAXException,
+ * java.io.IOException { if (publicId.equals("-//XLIFF//DTD
+ * XLIFF//EN")) // this deactivates the open office DTD
+ * return new InputSource(new ByteArrayInputStream( " <?xml
+ * version='1.0' encoding='UTF-8'?>" .getBytes())); else
+ * return null; } });
+ *
+ */
+
+ xliffreader.parse(sourceString);
+
+ } else {
+ System.out.println("Datei existiert nicht");
+ }
+
+ } catch (SAXParseException e) {
+ try {
+ theTargetWriter.flush();
+ } catch (IOException e1) {
+
+ e1.printStackTrace();
+ }
+ OutputHandler.out("PARSE ERROR Zeile " + e.getLineNumber()
+ + ", " + e.getMessage());
+
+ }catch (SAXException e){
+ try {
+ theTargetWriter.flush();
+ } catch (IOException e1) {
+
+ e1.printStackTrace();
+ }
+ OutputHandler.out("PARSE EXCEPTION " + e.getMessage());
+ } catch (ParserConfigurationException e) {
+ OutputHandler.out("PARSER Configuration failed\n " + e.getMessage());
+ }
+ }
+
+ }
+ /**
+ * Encapsulate writing to a XLIFF file
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+ private class XLIFFTarget implements Target {
+ File target;
+
+ /**
+ * Create a new Instance of XLIFFTarget
+ *
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ public XLIFFTarget() throws FileNotFoundException, IOException {
+ target = FileMaker.newFile(targetString, overwrite);
+ theTargetWriter = new XLIFFWriter(new BufferedOutputStream(
+ new FileOutputStream(target)), CHARSET);
+
+ }
+
+ public DataWriter getWriter() {
+
+ return theTargetWriter;
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ConverterException.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ConverterException.java
new file mode 100755
index 000000000000..07a3708d4366
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ConverterException.java
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ConverterException.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * a simple exception
+ * just to seperate
+ * it from other
+ * exceptions
+ */
+package com.sun.star.tooling.converter;
+
+/**
+ * @author Christian Schmidt
+ *
+ * Thrown if an error occurs during converting from one file format to another
+ * that does not belong to an other exception
+ */
+public class ConverterException extends Exception {
+
+ /**
+ *
+ */
+ public ConverterException() {
+ super();
+
+ }
+
+ /**
+ * @param arg0
+ */
+ public ConverterException(String arg0) {
+ super(arg0);
+
+ }
+
+ /**
+ * @param arg0
+ */
+ public ConverterException(Throwable arg0) {
+ super(arg0);
+
+ }
+
+ /**
+ * @param arg0
+ * @param arg1
+ */
+ public ConverterException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+
+ }
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataHandler.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataHandler.java
new file mode 100755
index 000000000000..e8b4136f185a
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataHandler.java
@@ -0,0 +1,149 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DataHandler.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * DataHandler.java
+ *
+ * take the data from the reader
+ * and put it to the Writer
+ *
+ */
+
+package com.sun.star.tooling.converter;
+
+import java.util.*;
+
+/**
+ * Handle the Data to get it from the Source
+ * readable to the Target
+ *
+ * @author Christian Schmidt
+ */
+public class DataHandler {
+
+ /**
+ * An arrays that holds the names that will be
+ * keys for the HashMap containing the data
+ *
+ */
+ private final String[] dataNames = { "BlockNr", "Project",
+ "SourceFile", "Dummy", "ResType", "GID", "LID", "HID", "Platform",
+ "Width", "SourceLanguageID", "SourceText", "SourceHText",
+ "SourceQText", "SourceTitle", "TargetLanguageID", "TargetText",
+ "TargetHText", "TargetQText", "TargetTitle", "TimeStamp" };
+
+ private static final String EMPTY = new String("");
+
+ /**
+ * The HashMap containing the data
+ */
+ private final Map data = new ExtMap(dataNames, null);
+
+ /** Creates a new instance of DataHandler */
+ public DataHandler() {
+ }
+
+ /**
+ * fill the data from the desired source
+ *
+ * @param source where to get the data from
+ * @return true if data is read and false if null is read
+ * @throws IOException
+ * @throws ConverterException
+ */
+ public boolean fillDataFrom(DataReader source) throws java.io.IOException,
+ ConverterException {
+
+ Map line = null;
+
+ line = source.getData();
+ if (line == null){
+
+ return false;
+ }else{
+
+ this.data.putAll(line);
+ return true;
+ }
+
+
+ }
+
+ /**
+ * fill this data with the inData
+ *
+ * @param inData the data to handle by this handler
+ */
+ public void fillDataWith(Map inData) {
+ data.putAll(inData);
+ }
+
+// public void transfer(DataWriter target, DataReader source) {
+//
+// source.setHandler(this);
+//
+// }
+
+ /**
+ * The designated output is filled with the content of this handler
+ *
+ * @param output an array of Maps [0] should hold the source language data [1] the target language data
+ * @throws java.io.IOException
+ */
+ public void putDataTo(Map[] output) throws java.io.IOException {
+ String aKey = EMPTY;
+ for (int j = 0; j < output.length; j++) {
+ Set keys = output[j].keySet();
+ Iterator iter = keys.iterator();
+ while (iter.hasNext()) {
+ aKey = (String) iter.next();
+ output[j].put(aKey, data.get(aKey));
+ }
+ }
+
+ }
+ /**
+ * The designated output is filled with the content of this handler
+ *
+ * @param output a Map that should hold the source language data and the target language data
+ * @throws java.io.IOException
+ */
+ public void putDataTo(Map output) throws java.io.IOException {
+ String aKey = EMPTY;
+
+ Set keys = output.keySet();
+ Iterator iter = keys.iterator();
+ while (iter.hasNext()) {
+ aKey = (String) iter.next();
+ output.put(aKey, data.get(aKey));
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataReader.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataReader.java
new file mode 100755
index 000000000000..59de7ca7e1f4
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataReader.java
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DataReader.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.tooling.converter;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Gets Line counting from LineNumberReader all Converter Reader classes inherit
+ * from this.
+ * The abstract parent class of all converter reader classes
+ *
+ * @author Christian Schmidt
+ */
+abstract public class DataReader extends LineNumberReader {
+
+ /**
+ * Creates a new instance of DataReader
+ *
+ * @param isr
+ * InputStreamReader used as Source for this class
+ */
+ public DataReader(InputStreamReader isr) {
+ super(isr);
+ }
+
+ /**
+
+ * @throws java.io.IOException
+ * @throws ConverterException
+ *
+ * TODO this should no longer use an array as return type better a Map
+ *
+ */
+ /**
+ * The next block of the SDF file is reviewed and the Line including the
+ * source language and the Line including the target Language are given back
+ * in an array
+ *
+ *
+ * @return A Map including the source language
+ * and the target Language content are given back
+ *
+ * @throws java.io.IOException
+ * @throws ConverterException
+ */
+ public Map getData() throws java.io.IOException, ConverterException {
+ return null;
+ }
+
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataWriter.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataWriter.java
new file mode 100755
index 000000000000..c5d6765e3840
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/DataWriter.java
@@ -0,0 +1,91 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DataWriter.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * DataWriter.java
+ *
+ * parent of all XXXWriter classes used by
+ * Converter
+ */
+
+package com.sun.star.tooling.converter;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+/**
+ * The abstract parent class of all converter writer classes
+ *
+ * @author Christian Schmidt
+ */
+abstract public class DataWriter extends OutputStreamWriter {
+ protected final String seperator = new String("|");
+
+ /**
+ * the char sequence used as line seperator
+ */
+ protected final String lineEnd = java.lang.System.getProperty(
+ "line.seperator", "\n");
+
+ /** Creates a new instance of DataWriter */
+ /**
+ * @param bos the buffered output stream holding the data
+ * @param encoding the encoding to use for read from bos
+ * @throws java.io.UnsupportedEncodingException
+ */
+ public DataWriter(BufferedOutputStream bos, String encoding)
+ throws java.io.UnsupportedEncodingException {
+ super(bos, encoding);
+ }
+
+// abstract protected void writeData(Map[] data) throws java.io.IOException;
+
+ /**
+ * get the data that should be written from the DataHandler
+ *
+ * @param handler the DataHandler having the data
+ * @throws java.io.IOException
+ */
+ abstract protected void getDataFrom(DataHandler handler)
+ throws java.io.IOException;
+
+ /**
+ * write the Data
+ *
+ * @throws java.io.IOException
+ */
+ abstract protected void writeData() throws java.io.IOException;
+
+ /**
+ * @param handler
+ * @throws IOException
+ */
+ abstract protected void getDatafrom(DataHandler handler) throws IOException;
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ExtMap.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ExtMap.java
new file mode 100755
index 000000000000..b05767e93ae3
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ExtMap.java
@@ -0,0 +1,97 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ExtMap.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * A special HashMap,
+ * can be constructed of
+ * two Arrays
+ */
+package com.sun.star.tooling.converter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Christian Schmidt
+ *
+ * Create a Hash Map from two Arrays
+ *
+ */
+public class ExtMap extends HashMap {
+
+ /**
+ *
+ */
+ public ExtMap() {
+ super();
+
+ }
+
+ /**
+ * @see java.util.HashMap
+ * @param arg0
+ */
+ public ExtMap(int arg0) {
+ super(arg0);
+
+ }
+
+ /**
+ * @param arg0
+ * @param arg1
+ */
+ public ExtMap(int arg0, float arg1) {
+ super(arg0, arg1);
+
+ }
+
+ /**
+ * @param arg0
+ */
+ public ExtMap(Map arg0) {
+ super(arg0);
+
+ }
+
+ // create a new Map from two string arrays
+ public ExtMap(String[] names, String[] content) {
+ super(names.length);
+ if (content == null)
+ content = new String[names.length];
+ for (int i = 0; i < names.length; i++) {
+ if (i >= content.length) {
+ break;
+ } else {
+ this.put(names[i], content[i]);
+ }
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/FileMaker.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/FileMaker.java
new file mode 100755
index 000000000000..a21b8daa7b1d
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/FileMaker.java
@@ -0,0 +1,87 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FileMaker.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * creates new files
+ * checks if they exist or
+ * can be overwritten
+ *
+ */
+package com.sun.star.tooling.converter;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Creates new files only if the file does not yet exist
+ * or overwriting is allowed
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+public final class FileMaker {
+
+ /**
+ * Create a new file if overwriting is not alowed
+ * ask if existing files should be overwritten
+ *
+ * @param fileName the files name to overwrite
+ * @param overwrite indicates wether the file can be overwritten
+ * @return the File created from the fileName
+ * @throws IOException
+ */
+ public final static File newFile(String fileName, boolean overwrite)
+ throws IOException {
+ File file = new File(fileName);
+ if (file.exists()) {
+ if (!overwrite) {
+ char c = 0;
+
+ System.out.print("Warning: File " + fileName
+ + " already exist.\n" + "Overwrite (y/n) ? :");
+ byte[] waste = new byte[10];
+ System.in.read(waste);
+ c = (char) waste[0];
+ if (c == 'y') {
+ OutputHandler.out("...overwriting " + fileName);
+ } else {
+ OutputHandler.out(
+ "\nPlease set '-o' switch at command line to overwrite.\n\nProgramm Aborted.");
+ System.exit(-1);
+ }
+ } else {
+ OutputHandler.out("...overwriting " + fileName);
+ }
+ } else {
+ OutputHandler.out("...creating new target file " + fileName);
+ }
+ return file;
+ }
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIReader.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIReader.java
new file mode 100755
index 000000000000..adb6e358a74c
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIReader.java
@@ -0,0 +1,250 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: GSIReader.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Created on 2005
+ * by Christian Schmidt
+ */
+package com.sun.star.tooling.converter;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.sun.star.tooling.languageResolver.LanguageResolver;
+import com.sun.star.tooling.languageResolver.LanguageResolver.LanguageResolvingException;
+
+/**
+ * @author Christian Schmidt 2005
+ *
+ */
+public class GSIReader extends DataReader {
+ /**
+ * A Map holding an empty GSIBlock
+ */
+ private Map EmptyGSIBlock;
+
+ /**
+ * @see LanguageResolver
+ */
+ LanguageResolver languageResolver;
+
+ /**
+ * The source language identifier
+ */
+ protected String sourceLanguage;
+
+ /**
+ * The target language identifier
+ */
+ protected String targetLanguage;
+
+ /**
+ * The number of the last block
+ */
+ private String oldBlockNr;
+
+ /**
+ * A buffer holding one GSILine
+ */
+ private Map GSILineBuffer;
+
+ /**
+ * Indicates whether to use the buffered line
+ */
+ private boolean useBuffer = false;
+
+ private static final String EMPTY = new String("");
+
+ /**
+ * An empty Map to fill with language depending data
+ */
+ private ExtMap EmptyLanguageMap;
+
+ /**
+ * Indicates whether the first block is read
+ */
+ private boolean isFirst = true;
+
+ private int lineCounter;
+
+ private int blockCounter;
+ /**
+ * Indicates whether the last line is read
+ */
+ private boolean lastLineFound = false;
+
+ /**
+ * Create a new Instance of GSIReader
+ *
+ * @param source
+ * the file to read from
+ * @param sourceLanguage
+ * the sourceLanguage (must not be empty)
+ * @param targetLanguage
+ * the targetLanguage
+ * @param charset
+ * the charset used to read source
+ * @throws java.io.IOException
+ * @throws Exception
+ */
+ public GSIReader(File source, String sourceLanguage, String targetLanguage,
+ String charset) throws java.io.IOException {
+ super(new InputStreamReader(new FileInputStream(source), charset));
+ this.languageResolver = new LanguageResolver();
+ this.sourceLanguage = sourceLanguage;
+ this.targetLanguage = targetLanguage;
+
+ EmptyLanguageMap = new ExtMap(new String[0], new String[0]);
+
+ }
+
+ /**
+ * Read the next GSIBlock and return the data
+ *
+ * @return A Map containing the data of the read GSIBlock the keys for the language depending data are the language id (numeric) the
+ * single language are acessible with the keys "BlockNr", "resType", "languageNr", "status","content".
+ *
+ * @throws IOException
+ */
+ public Map getGSIData() throws IOException {
+ String help;
+ Map helpmap;
+ Map GSIBlock = new HashMap();
+ GSIBlock.put(sourceLanguage, EmptyLanguageMap.clone());
+ GSIBlock.put(targetLanguage, EmptyLanguageMap.clone());
+ String line = EMPTY;
+ String[] splitLine;
+ Map GSILine;
+ String[] GSINames = { "BlockNr", "resType", "languageNr", "status",
+ "content" };
+
+ while (useBuffer || (line = readLine()) != null) {
+
+
+
+ if (useBuffer) {
+ GSILine = GSILineBuffer;
+ GSIBlock.put(sourceLanguage, EmptyLanguageMap.clone());
+ GSIBlock.put(targetLanguage, EmptyLanguageMap.clone());
+ GSIBlock.put("BlockNr", GSILine.get("BlockNr"));
+ useBuffer = false;
+ } else {
+ this.lineCounter++;
+ if ((splitLine = split(line)) == null) {
+ continue;
+ }
+ GSILine = new ExtMap(GSINames, splitLine);
+ if (isFirst) {
+ GSIBlock.put("BlockNr", GSILine.get("BlockNr"));
+ oldBlockNr = (String) GSILine.get("BlockNr");
+ isFirst = false;
+ }
+ }
+ if (oldBlockNr == null) {
+ oldBlockNr = (String) GSILine.get("BlockNr");
+ }
+ if (!oldBlockNr.equals((String) GSILine.get("BlockNr"))) {
+ GSILineBuffer = GSILine;
+ oldBlockNr = (String) GSILine.get("BlockNr");
+ useBuffer = true;
+ break;
+ }
+ String lang;
+ try {
+ // Is there the source language in this line?
+ if ((lang = languageResolver.getISOfromNr((String) GSILine
+ .get("languageNr"))).equals(this.sourceLanguage)) {
+ // ok..store it as Source String under the depending
+ // ressource type
+
+ ((Map) GSIBlock.get(sourceLanguage)).put("Source"
+ + ResTypeResolver.getInternKey((String) GSILine
+ .get("resType")), GSILine.get("content"));
+ // ..maybe the target language?
+ } else {
+ if (targetLanguage.equals(EMPTY)) {
+ // if no target language is given at command line
+ targetLanguage = lang;
+ GSIBlock.put(targetLanguage, EmptyLanguageMap.clone());
+ }
+ if (lang.equals(this.targetLanguage)) {
+
+ // ok..store it as target String under the depending
+ // ressource type
+ ((Map) GSIBlock.get(targetLanguage)).put("Target"
+ + ResTypeResolver.getInternKey((String) GSILine
+ .get("resType")), GSILine
+ .get("content"));
+ }
+ }
+ } catch (LanguageResolvingException e) {
+ OutputHandler.out("Can not resolve the language "+e.getMessage());
+ }
+
+ }
+ if (line == null) {
+ if (lastLineFound){
+ OutputHandler.out("\n\n");
+ OutputHandler.out("GSI Blocks : " + this.blockCounter);
+ OutputHandler.out("GSI Lines : " + this.lineCounter);
+
+ return null;
+ }else{
+ lastLineFound = true;
+ this.blockCounter++;
+ return GSIBlock;
+ }
+ } else {
+ this.blockCounter++;
+ return GSIBlock;
+ }
+
+ }
+
+ /**
+ * Split a GSILine to single fields
+ *
+ * @param line
+ * The line to split
+ * @return An array containing the contents of the columns in the given line
+ */
+ private String[] split(String line) {
+ String[] splitLine = (line.substring(0, line.length() - 1))
+ .split("\\(\\$\\$\\)");
+ if (splitLine.length != 5)
+ return null;
+ else
+ return splitLine;
+ }
+
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIWriter.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIWriter.java
new file mode 100755
index 000000000000..085e26475e09
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIWriter.java
@@ -0,0 +1,246 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: GSIWriter.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package com.sun.star.tooling.converter;
+import java.io.*;
+import java.util.Map;
+
+import com.sun.star.tooling.languageResolver.LanguageResolver;
+import com.sun.star.tooling.languageResolver.LanguageResolver.LanguageResolvingException;
+/**
+ *
+ * @author cs156069
+ */
+public class GSIWriter extends DataWriter {
+ /**
+ * The seperator used to seperate GSI columns
+ */
+ final String seperator=new String("($$)");
+
+ /**
+ * Holding the keys used by a map holding the content of an GSI Line contianing the source language
+ */
+ final static String[] sourceLineNames= {"Project","SourceFile","Dummy","ResType","GID","LID","HID","Platform","Width","SourceLanguageID","SourceText","SourceHText","SourceQText","SourceTitle","TimeStamp"};
+ /**
+ * Holding the keys used by a map holding the content of an GSI Line contianing the target language
+ */
+ final static String[] targetLineNames= {"Project","SourceFile","Dummy","ResType","GID","LID","HID","Platform","Width","TargetLanguageID","TargetText","TargetHText","TargetQText","TargetTitle","TimeStamp"};
+ /**
+ * Holding the keys used by a map holding the content of an GSI Line contianing the source and the target language
+ */
+ final static String[] outLineNames= {"BlockNr","Project","SourceFile","Dummy","ResType","GID","LID","HID","Platform","Width","SourceLanguageID","SourceText","SourceHText","SourceQText","SourceTitle","TargetLanguageID","TargetText","TargetHText","TargetQText","TargetTitle","TimeStamp"};
+
+ /**
+ * A map holding the content of an GSI Line contianing the source language
+ */
+ private ExtMap sourceLine=new ExtMap(sourceLineNames,null);
+ /**
+ * A map holding the content of an GSI Line contianing the target language
+ */
+ private ExtMap targetLine=new ExtMap(targetLineNames,null);
+ /**
+ * A map holding the content of an GSI Line contianing the source and the target language
+ */
+ private ExtMap outData=new ExtMap(outLineNames, null);
+
+ private static final String EMPTY = new String("");
+ /**
+ * The sourceLanguage to use
+ */
+ private String sourceLanguage;
+ /**
+ * The sourceLanguage to use
+ */
+ private String targetLanguage;
+
+ /**
+ * GSILines have a special Line End
+ */
+ private final static String lineEnd="!"+'\r'+'\n';
+ //private boolean SourceIsFirst=false;
+
+ /**
+ * The blockNr of the current line
+ */
+ private String blockNr;
+
+
+
+
+ /**
+ * Create a new Instance of GSIWriter
+ *
+ * @param bos the Buffered Output Stream to write to
+ * @param charset the used charset
+ * @throws java.io.UnsupportedEncodingException
+ */
+ public GSIWriter(BufferedOutputStream bos,String charset) throws java.io.UnsupportedEncodingException {
+ super(bos,charset);
+
+
+
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#writeData()
+ */
+ public final void writeData() throws java.io.IOException {
+
+ StringBuffer buffer=new StringBuffer("");
+ if(this.sourceLanguage==null&&this.targetLanguage==null){
+ LanguageResolver lang =new LanguageResolver();
+ try {
+ this.sourceLanguage=lang.getNrFromISO((String)outData.get("SourceLanguageID"));
+ this.targetLanguage=lang.getNrFromISO((String)outData.get("TargetLanguageID"));
+ } catch (LanguageResolvingException e) {
+
+ OutputHandler.out(e.getMessage());
+ System.exit(0);
+ }
+ }
+
+
+ this.blockNr=(String)outData.get("BlockNr");
+ // get the values of the found fields
+ //create the gsi lines
+ //
+ //at first the source language line
+ buffer.append(getSourceLine("Text"));
+ buffer.append(getSourceLine("HText"));
+ buffer.append(getSourceLine("QText"));
+ buffer.append(getSourceLine("Title"));
+
+ //now the target language line
+ // put them together for output
+ buffer.append(getTargetLine("Text"));
+ buffer.append(getTargetLine("HText"));
+ buffer.append(getTargetLine("QText"));
+ buffer.append(getTargetLine("Title"));
+ //ok...put all to disk;
+ this.write(buffer.toString());
+
+ }
+
+ /**
+ * Create a line containing the source string from the data
+ * @param resType
+ * @return The StringBuffer containing the line
+ */
+ private StringBuffer getSourceLine(String resType){
+ StringBuffer buffer =new StringBuffer(200);
+ String resString = "Source"+resType;
+
+ String help;
+ if(EMPTY.equals((String)outData.get(resString))||" ".equals(outData.get(resString))) return new StringBuffer(EMPTY);
+ else {
+ // put them together for output
+ buffer.append(this.blockNr);
+ // seperate the fields with ($$)
+ buffer.append(this.seperator);
+ buffer.append(ResTypeResolver.getExternKey(resType));
+ // seperate the fields with ($$)
+ buffer.append(this.seperator);
+ buffer.append(this.sourceLanguage);
+ // seperate the fields with ($$)
+ buffer.append(this.seperator);
+ buffer.append("int");
+ // seperate the fields with ($$)
+ buffer.append(this.seperator);
+ buffer.append(outData.get(resString));
+
+ // this line is full
+ // so close it with '! cr lf'
+ buffer.append(GSIWriter.lineEnd);
+ Converter.countLine();
+ return buffer;
+ }
+
+ }
+ /**
+ * Create a line containing the target string from the data
+ * @param resType
+ * @return The StringBuffer containing the line
+ */
+ private StringBuffer getTargetLine(String resType){
+ StringBuffer buffer =new StringBuffer(200);
+ String resString = "Target"+resType;
+
+ if(EMPTY.equals((String)outData.get(resString))||" ".equals(outData.get(resString))) return new StringBuffer(EMPTY);
+ else {
+ // put them together for output
+ buffer.append(this.blockNr);
+ // seperate the fields with ($$)
+ buffer.append(this.seperator);
+ buffer.append(ResTypeResolver.getExternKey(resType));
+ // seperate the fields with ($$)
+ buffer.append(this.seperator);
+ buffer.append(this.targetLanguage);
+ // seperate the fields with ($$)
+ buffer.append(this.seperator);
+ buffer.append("ext");
+ // seperate the fields with ($$)
+ buffer.append(this.seperator);
+ buffer.append(outData.get(resString));
+
+ // this line is full
+ // so close it with '! cr lf'
+ buffer.append(GSIWriter.lineEnd);
+ Converter.countLine();
+ return buffer;
+ }
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#writeData(java.util.Map[])
+ */
+ protected void writeData(Map[] data) throws IOException {
+ // TODO redesign DataHandler in the way that this is not nessesary any more
+
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#getDataFrom(com.sun.star.tooling.converter.DataHandler)
+ */
+ protected void getDataFrom(DataHandler handler) throws IOException {
+
+ handler.putDataTo(this.outData);
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#getDatafrom(com.sun.star.tooling.converter.DataHandler)
+ */
+ protected void getDatafrom(DataHandler handler) throws IOException {
+
+ handler.putDataTo(this.outData);
+
+ }
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIandSDFMerger.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIandSDFMerger.java
new file mode 100755
index 000000000000..ff0348f97d3d
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/GSIandSDFMerger.java
@@ -0,0 +1,167 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: GSIandSDFMerger.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Created on 2005
+ * by Christian Schmidt
+ */
+package com.sun.star.tooling.converter;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Merge GSIFiles back to to the original (!) SDFFile
+ *
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+public class GSIandSDFMerger extends SDFReader {
+
+ int lineCounter=0;
+
+ GSIReader gsiReader;
+
+ private Map temp=new HashMap();
+ private int j;
+ private boolean skip=true;
+ Map gsiBlock=null;
+ Map sdfBlock=null;
+
+ private boolean dontLoadGSI=false;
+
+ private int count;
+ /**
+ * Merge the GSIFile back to the original(!) SDFFile
+ *
+ * @param source the file to read from
+ * @param sourceLanguage the source language in the source file
+ * @param targetLanguage the target language in the source file
+ * @param charset the charset of the files
+ * @throws java.io.IOException
+ * @throws Exception
+ */
+ public GSIandSDFMerger(File source, File secondSource,String sourceLanguage,
+ String targetLanguage, String charset) throws IOException {
+ // merging GSI and SDF requieres two Sources
+ //this. is the SDF source
+ super(secondSource, sourceLanguage, targetLanguage, charset);
+ //create the GSI Source
+
+ gsiReader=new GSIReader(source,sourceLanguage,targetLanguage,charset);
+
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataReader#getData()
+ */
+ public Map getData()throws java.io.IOException{
+ do{
+ skip=false;
+ this.temp=matchGSI();
+ }while(skip);
+ if(temp==null){
+ OutputHandler.out("Blocks merged : "+this.lineCounter);
+ }
+ return temp;
+
+ }
+
+ /**
+ * Read each block of the GSIFile and check whether there is a matching
+ * block in the SDFFile. Match depends on the BlockNr and BlockId.
+ *
+ * @return A Map that contains the source language content
+ * and the target language content.
+ * @throws IOException
+ * @throws ConverterException
+ */
+ public Map matchGSI() throws IOException{
+
+
+ try {
+ //System.out.println("Start...");
+
+ if (dontLoadGSI||(gsiBlock=gsiReader.getGSIData())!=null){
+ dontLoadGSI=false;
+ //check if we must update this block
+ //if so its BlockNr is in the gsi file
+ if((sdfBlock = super.getData())!=null){
+
+ if(((String)sdfBlock.get("BlockNr")).equals((String)gsiBlock.get("BlockNr"))){
+
+ gsiBlock.remove(EMPTY);
+ //if the target language string is empty this may be caused by an error in the source sdf File
+ //I don't want to overwrite a possibly correct translation with an empty string
+ // so remove the target part from the gsiBlock
+ Map mp=(Map)gsiBlock.get(gsiReader.targetLanguage);
+ if (mp.size()!=0&&!((String)mp.get("TargetText")).equals("")){
+
+ // target language part in this gsiBlock
+// if(((String)mp.get("TargetText")).equals("")){
+// gsiBlock.remove(targetLanguage);
+// }
+ // count the merged blocks
+ lineCounter++;
+ Map helpMap = (Map)gsiBlock.get(super.targetLanguage);//"ja"
+ sdfBlock.putAll(helpMap);
+ skip=false;
+ }else{
+ //no target language part in this gsiBlock
+ skip=true;
+//
+// return null;
+ }
+ }else{
+// skip=true;
+//
+// // we cant match this gsi block to the current sdf block
+ // try matching the next sdf block with this gsi line
+ dontLoadGSI=true;
+ }
+ }
+ return sdfBlock;
+ }
+
+ } catch (IOException e) {
+
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+
+
+
+
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/LineErrorException.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/LineErrorException.java
new file mode 100755
index 000000000000..6a11360cc472
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/LineErrorException.java
@@ -0,0 +1,81 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: LineErrorException.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Exception for errors in
+ * SDFLines
+ */
+package com.sun.star.tooling.converter;
+
+
+/**
+ * This Exeption is thrown if a DataReader finds an error in a read Line
+ * f. e. wrong column number
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+public class LineErrorException extends Exception {
+
+ public int tokenCount;
+ /**
+ *
+ */
+ public LineErrorException() {
+ super();
+
+ }
+
+ /**
+ * @param arg0
+ */
+ public LineErrorException(String arg0) {
+ super(arg0);
+
+ }
+
+ /**
+ * @param arg0
+ */
+ public LineErrorException(Throwable arg0) {
+ super(arg0);
+
+ }
+
+ /**
+ * @param arg0
+ * @param arg1
+ */
+ public LineErrorException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+
+ }
+
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/OutputHandler.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/OutputHandler.java
new file mode 100755
index 000000000000..997c05a70b4f
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/OutputHandler.java
@@ -0,0 +1,228 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: OutputHandler.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Creates logfile and file for debug information
+ *
+ */
+package com.sun.star.tooling.converter;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+
+/**
+ * Handle the whole output during converting process except the converted files.
+ * Write output to logfiles and to screen depending on switches given
+ * at command line.
+ * @author Christian Schmidt 2005
+ *
+ */
+public class OutputHandler {
+
+ private static final String EMPTY = "";
+
+ /**
+ * The logfile to write
+ */
+ public static BufferedWriter logFile;
+
+ /**
+ * Indicates whether excisting files should be overwritten
+ */
+ public static boolean doLog = false;
+
+ /**
+ * Indicate whether the debug information should be written
+ */
+ public static boolean doDebug = false;
+
+ /**
+ * The File to write the debug information to
+ */
+ public static BufferedWriter dbgFile;
+
+ /**
+ * Write the data to screen and if the switches were set to
+ * logfile and debugfile
+ *
+ * @param out the String to write
+ */
+ final static void out(String out) {
+ try {
+ if (doDebug)
+ OutputHandler.dbg(out);
+
+ if (!doLog || logFile == null) {
+ System.out.println(out);
+ } else {
+ System.out.println(out);
+ if (EMPTY.equals(out)) {
+ OutputHandler.log(EMPTY);
+ } else {
+ OutputHandler.log(out);
+ }
+ }
+ } catch (IOException e) {
+
+ OutputHandler.log(e.toString());
+ }
+ }
+
+ /**
+ * make a dot on the screen to show the user that it is going on
+ */
+ final static void printDot() {
+ System.out.print(".");
+
+ }
+
+ /**
+ * write the data to log file and if the switch is set
+ * to the debug file
+ *
+ * @param out the String to write
+ */
+ final static void log(String out) {
+ try {
+ if(out==null) return;
+ if (doDebug)
+
+ OutputHandler.dbg(out);
+
+ if (doLog) {
+ if (!EMPTY.equals(out)) {
+ logFile.write(out);
+ }
+ logFile.newLine();
+ logFile.flush();
+ }
+ } catch (IOException e) {
+
+ System.out.println(e.getMessage());
+ }
+ }
+
+ /**
+ * write the string to the debug file
+ *
+ * @param out the String to write
+ * @throws IOException
+ */
+ final static void dbg(String out) throws IOException {
+ if(out==null) return;
+ if (doDebug) {
+ if (!EMPTY.equals(out)) {
+ dbgFile.write(out);
+
+ }
+ dbgFile.newLine();
+ dbgFile.flush();
+ }
+ }
+
+ /**
+ * Set a new value to indicate whether a debug file should be written or not
+ *
+ * @param doDebug
+ * The debug value to set.
+ */
+ private static void setDebug(boolean doDebug) {
+ OutputHandler.doDebug = doDebug;
+ }
+
+ // /**
+ // * @return Returns the doDebug.
+ // */
+ // private static boolean isDebug() {
+ // return doDebug;
+ // }
+
+ /**
+ * Set the debug file to write to.
+ *
+ * @param dbgFile
+ * The debug File to use.
+ */
+ private static void setDbgFile(BufferedWriter dbgFile) {
+ OutputHandler.dbgFile = dbgFile;
+ }
+
+ /**
+ * @return Returns the debug File.
+ */
+ private static BufferedWriter getDbgFile() {
+ return dbgFile;
+ }
+
+ /**
+ * @param doLog
+ * The log value to set.
+ */
+ private static void setLog(boolean doLog) {
+ OutputHandler.doLog = doLog;
+ }
+
+ /**
+ * @return Returns the log value.
+ */
+ private static boolean isLog() {
+ return doLog;
+ }
+
+ /**
+ * @param logFile
+ * The logFile to set.
+ */
+ private static void setLogFile(BufferedWriter logFile) {
+ OutputHandler.logFile = logFile;
+ }
+
+ /**
+ * @return Returns the logFile.
+ */
+ private static BufferedWriter getLogFile() {
+ return logFile;
+ }
+
+ /**
+ * @throws IOException
+ * close log and dbg
+ */
+ public static void closeAll() throws IOException {
+ if (OutputHandler.logFile != null) {
+ OutputHandler.logFile.flush();
+ OutputHandler.logFile.close();
+ }
+ if (OutputHandler.dbgFile != null) {
+ OutputHandler.dbgFile.flush();
+ OutputHandler.dbgFile.close();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ResTypeResolver.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ResTypeResolver.java
new file mode 100755
index 000000000000..f53fe0101275
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/ResTypeResolver.java
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ResTypeResolver.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Created on 2005
+ * by Christian Schmidt
+ */
+package com.sun.star.tooling.converter;
+
+import java.util.Map;
+
+/**
+ * Helps resolving restype descriptors used outside the tool to
+ * restype descriptors used by this tool
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+public class ResTypeResolver {
+ final static String[] inFields={"Text","QText","HText","Title"};
+ final static String[] outFields={"res","res-quickhelp","res-help","res-title"};
+ final static Map internKeys=new ExtMap(inFields,outFields);
+ final static Map externKeys=new ExtMap(outFields,inFields);
+
+ /**
+ * Get the intern key depending to the given extern key
+ *
+ * @param externKey the externKey {"res","res-quickhelp","res-help","title"}
+ * @return the depending intern key
+ */
+ public static String getInternKey(String externKey){
+ return (String)externKeys.get(externKey);
+ }
+
+ /**
+ * Get the extern key to the given intern key
+ *
+ * @param internKey the internal key
+ * @return the external key
+ */
+ public static String getExternKey(String internKey){
+ return (String)internKeys.get(internKey);
+ }
+
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Resolver.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Resolver.java
new file mode 100755
index 000000000000..29a9ee2e528a
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/Resolver.java
@@ -0,0 +1,98 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Resolver.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Created on 27.01.2005
+ *
+ */
+package com.sun.star.tooling.converter;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Resolve external entities by provide the
+ * XLIFF DTD stored in the jar file
+ */
+public class Resolver implements EntityResolver {
+
+ /**
+ * Resolver constructor.
+ */
+ public Resolver() {
+ }
+
+ /**
+ * Allow the application to resolve external entities.
+ *
+ * The Parser will call this method before opening any external entity
+ * except the top-level document entity (including the external DTD subset,
+ * external entities referenced within the DTD, and external entities
+ * referenced within the document element): the application may request that
+ * the parser resolve the entity itself, that it use an alternative URI, or
+ * that it use an entirely different input source.
+ */
+
+ /* (non-Javadoc)
+ * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String, java.lang.String)
+ */
+
+ public InputSource resolveEntity(String publicId, String systemId)
+ throws SAXException, IOException {
+
+ if ((publicId != null) && (publicId.equals("-//XLIFF//DTD XLIFF//EN"))) {
+ systemId = "dtd:///xliff.dtd";
+ }
+ if (systemId != null) {
+ if (systemId.startsWith("dtd://")) {
+ String dtd = "com/sun/star/tooling/converter/dtd"
+ + systemId.substring(6);
+ ClassLoader cl = this.getClass().getClassLoader();
+ InputStream in = cl.getResourceAsStream(dtd);
+ InputSource ins = new InputSource(in);
+ ins.setSystemId(systemId);
+ return ins;
+ } /*
+ * else if ( systemId.startsWith("jar:") ) { try { URL url=new
+ * URL(systemId); JarURLConnection jarConn =
+ * (JarURLConnection)url.openConnection(); InputSource ins=new
+ * InputSource(jarConn.getInputStream());
+ * ins.setSystemId(systemId); return ins; }
+ * catch(MalformedURLException me){ throw new SAXException(me);
+ * Incorrect URL format used } }
+ */
+ }
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/SDFReader.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/SDFReader.java
new file mode 100755
index 000000000000..4c0c234778ec
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/SDFReader.java
@@ -0,0 +1,635 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SDFReader.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * SDFReader.java
+ *
+ *
+ */
+
+package com.sun.star.tooling.converter;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.text.DecimalFormat;
+import java.util.*;
+
+/**
+ *
+ * SDFReader is a FileReader that knows about
+ * the content of SDFFiles
+ *
+ * A SDFBlock is read of the given file. A SDFBlock
+ * consists of all SDFLines that are traanslations of the
+ * same String and the SDFLine containing the source string
+ * itself. SDFFile lines are read and checked whether they
+ * have the allowed column count and don't contain illeagal
+ * characters (like most unprintable characters below 0x00df).
+ * If the given source language is not found in the first
+ * block of SDFLines a ConverterException is thrown at runtime.
+ * If the given target language is "" (that means not given)
+ * the first language that is not the given source language
+ * is taken for target language. The found values are returned in HashMaps that
+ * use the following keys:
+ * <br/>
+ * "BlockNr" originally coming from reading the sdf file, contains 'block nr in sdf file'+'-'+'hash value of the sdf id fields'.<br/>
+ * "Project" first column in sdf file format.<br/>
+ * "SourceFile" second column in sdf file format.<br/>
+ * "Dummy" third column in sdf file format.<br/>
+ * "ResType" 4. column in sdf file format.<br/>
+ * "GID" 5. column in sdf file format. <br/>
+ * "LID" 6. column in sdf file format.<br/>
+ * "HID" 7. column in sdf file format.<br/>
+ * "Platform" 8. column in sdf file format. <br/>
+ * "Width", 9. column in sdf file format.<br/>
+ * "SourceLanguageID" 10. column in sdf file format(in the line with the source language).<br/>
+ * "SourceText" 11. column in sdf file format(in the line with the source language).<br/>
+ * "SourceHText" 12. column in sdf file format(in the line with the source language).<br/>
+ * "SourceQText" 13. column in sdf file format(in the line with the source language).<br/>
+ * "SourceTitle" 14. column in sdf file format(in the line with the source language).<br/>
+ * "TargetLanguageID" 10. column in sdf file format (in the line with the target language).<br/>
+ * "TargetText" 11. column in sdf file format (in the line with the target language).<br/>
+ * "TargetHText" 12. column in sdf file format (in the line with the target language).<br/>
+ * "TargetQText" 13. column in sdf file format (in the line with the target language).<br/>
+ * "TargetTitle", 14. column in sdf file format (in the line with the target language).<br/>
+ * "TimeStamp" 15. column in sdf file format.<br/>
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+
+public class SDFReader extends DataReader {
+
+ /**
+ * an array of the SDF files column names
+ */
+ final static String[] fieldnames = { "Project", "SourceFile", "Dummy",
+ "ResType", "GID", "LID", "HID", "Platform", "Width", "LanguageID",
+ "Text", "HText", "QText", "Title", "TimeStamp" };
+
+ /**
+ * an array of the SDF files column names if the source language is in
+ */
+ final static String[] sourceLineNames = { "Project", "SourceFile", "Dummy",
+ "ResType", "GID", "LID", "HID", "Platform", "Width",
+ "SourceLanguageID", "SourceText", "SourceHText", "SourceQText",
+ "SourceTitle", "TimeStamp" };
+
+ /**
+ * an array of the SDF files column names if the target language is in
+ */
+ final static String[] targetLineNames = { "Project", "SourceFile", "Dummy",
+ "ResType", "GID", "LID", "HID", "Platform", "Width",
+ "TargetLanguageID", "TargetText", "TargetHText", "TargetQText",
+ "TargetTitle", "TimeStamp" };
+
+ final static String EMPTY = new String("");
+
+ private int dotCount = 0;
+
+ /**
+ * a Map containing an SDF line with source language
+ */
+ private Map sourceMap;
+
+ /**
+ * a Map containing an SDF line with target language
+ */
+ private Map targetMap;
+
+ /**
+ * a Map containing an SDF
+ */
+ private Map SDFMap;
+
+ /**
+ * a Map Array containing one SDF source language line and one SDF target
+ * language line
+ */
+ private Map[] data = { sourceMap, targetMap };
+
+ /**
+ * The Id of the current SDFBlock
+ */
+ private String CurrentBlockId;
+
+ /**
+ * The SDF file to read from
+ */
+ private File sourceFile;
+
+ /**
+ * The language in the source file that should be handelt as source language
+ */
+ protected String sourceLanguage;
+
+ /**
+ * The language in the source file that should be handelt as target language
+ */
+ protected String targetLanguage;
+
+ /**
+ * A counter holding the number of blocks just read
+ * from this file
+ */
+ private long blockNr = 0;// If we use Integer, more then numbers greater than 128k would be signed
+
+ /**
+ * A counter holding the number of skipped lines that means
+ * lines that can not be worked with because they contain an error
+ */
+ private int skippedLines = 0;
+
+ /**
+ * This switch is set for indicating that all source file lines
+ * are read and no lines remain buffered. Finding this like 'true'
+ * means the source file is finished
+ */
+ private boolean endIt = false;
+
+ /**
+ * Indicates whether the targetLanguage is found in this source file so far
+ */
+ private boolean foundTarget = false;
+ /**
+ * Indicates whether the sourceLanguage is found in this source file so far
+ */
+ private boolean foundSource = false;
+
+ /**
+ * Counts how many lines were skipped because the language is
+ * neither sourceLanguage nor targetLanguage
+ */
+ private int langMiss;
+
+ /**
+ * Indicates whether there is a line in the read buffer or not
+ */
+ private boolean useBuffer = false;
+
+ /**
+ * A buffer for SDFLines
+ */
+ private String lineBuffer;
+
+ /**
+ * The buffer for the already splitted SDFLines
+ */
+ private String[] splittedLineBuffer;
+
+ /**
+ * Counts how many Blocks were skipped
+ * f.e. because no sourceLanguage is found
+ * in it
+ */
+ private int skippedBlocks;
+
+ /**
+ * Counts the blocks without targetLanguage
+ */
+ private int targetLangMiss;
+
+ /**
+ * Counts the blocks without sourceLanguage
+ */
+ private int sourceLangMiss;
+
+ /**
+ * Counts the lines where no targetLanguage line was found
+ * and so empty lines were created
+ */
+ private int targetLangCreate;
+
+
+ DecimalFormat blockNrFormatter = new DecimalFormat("000000");
+
+ /**
+ * The hashcode of the current block
+ */
+ private int CurrentBlockHash;
+
+ private boolean skip;
+
+ /**
+ * Create a new Instance of SDFREader
+ *
+ * @param source the file to read from
+ * @param sourceLanguage the sourceLanguage (must not be empty)
+ * @param targetLanguage the targetLanguage
+ * @param charset the charset used to read source
+ * @throws java.io.IOException
+ * @throws Exception
+ */
+ public SDFReader(File source, String sourceLanguage, String targetLanguage,
+ String charset) throws java.io.IOException {
+ super(new InputStreamReader(new FileInputStream(source), charset));
+ sourceFile = source;
+ this.sourceLanguage = sourceLanguage;
+ this.targetLanguage = targetLanguage;
+ String line;
+ String[] splitLine;
+ //read first line to get the first
+ //SDF block id
+ mark(16000);
+ if ((line = readLine()) != null) {
+ if ((splitLine = split(line)) != null){
+ this.CurrentBlockId = getSDFBlockId(splitLine);
+ this.CurrentBlockHash=this.CurrentBlockId.hashCode();
+ //found the first
+ this.blockNr++;
+ }
+ this.splittedLineBuffer = splitLine;
+ }
+ reset();
+
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataReader#getData()
+ */
+ public Map getData()throws IOException {
+
+ Map map=new HashMap();
+// do {
+ this.skip=false;
+ Map[] help=readBlock();
+ if(help==null||help[1]==null||help[0]==null){
+ return null;
+// }else if (help[1].get("TargetLanguageID")==null||help[0].get("SourceLanguageID")==null) {
+// OutputHandler.log("Missing Language Id in block "+blockNr+"\nthe block is skipped." );
+// this.skippedBlocks++;
+// this.skip=true;
+ }else{
+ map.putAll(help[1]);
+ map.putAll(help[0]);
+
+ }
+// }while(this.skip=true);
+ return map;
+ }
+
+
+ /**
+ * Read a Block from the sdf file and return
+ * @return a Map[] where [0] holds the source and [1] the target language data.
+ *
+ * @throws java.io.IOException
+ */
+ public Map[] readBlock() throws java.io.IOException {
+ String line = EMPTY;
+ String blockId = EMPTY;
+ String[] splittedLine = null;
+ data[0]=new ExtMap();
+ data[1]=new ExtMap();
+ String help;
+ String c = null;
+ //read next line or use buffered line
+ while (useBuffer || (line = readLine()) != null) { //works because '||' is shortcut
+
+ try {
+ // buffer used?
+ if (useBuffer) {
+ line = this.lineBuffer;
+ splittedLine = this.splittedLineBuffer;
+ this.SDFMap = new ExtMap(SDFReader.fieldnames, splittedLine);
+
+ try {
+ checkLanguage(splittedLine);
+ } catch (ConverterException e) {
+ throw e;
+ }finally{
+
+ useBuffer = false;
+ }
+ } else {
+ //...are there wrong characters?
+ if ((check(line)).length() < line.length()) {
+ throw new LineErrorException(getLineNumber()
+ + " : Line contains wrong character "
+ //+ Integer.toHexString(Integer.parseInt(c))
+ + " \n" + line);
+ }
+ //...is the number of columns ok?
+ if ((splittedLine = split(line)) == null) {
+
+ throw new LineErrorException(super.getLineNumber()
+ + " : Line has wrong column number \n" + line);
+ //continue;
+ } else {
+ // TODO makeDot is better in Data Handler
+ makeDot();
+ // ...is this line in a new SDF block ?
+ if ((blockId = getSDFBlockId(splittedLine))
+ .equals(CurrentBlockId)) {
+
+ this.SDFMap = new ExtMap(SDFReader.fieldnames,
+ splittedLine);
+ //what language is in it ?
+ checkLanguage(splittedLine);
+
+ } else {
+
+ /*
+ * we found the next block , but do we have the
+ * target text?
+ */
+
+ if (!foundTarget) {
+ createTargetLine();
+ }
+
+ blockNr++;
+ splittedLineBuffer = splittedLine;//read one line
+ // too much so
+ // buffer it
+ lineBuffer = line;
+ useBuffer = true;//reset();
+
+ this.CurrentBlockId = blockId;
+ this.CurrentBlockHash=this.CurrentBlockId.hashCode();
+
+ /* ...and what about the source text ? */
+ if (!foundSource) {
+
+ OutputHandler
+ .log("Error in Line:"
+ + getLineNumber()
+ + "Source Language is missing maybe "
+ + "previous block has an error.\nBlock "
+ + (blockNr - 1)
+ + " is skipped. before line: \n"
+ + line);
+
+ foundTarget = false;//no target without source
+ skippedBlocks++;
+ skippedLines++;
+ sourceLangMiss++;
+ continue;// skip output of this block if no
+ // source language is found
+
+ }
+
+ break;
+
+ }
+ }
+
+ }
+
+ } catch (LineErrorException e) {
+
+ OutputHandler.log(e.getMessage());
+ this.skippedLines++;
+ } catch (ConverterException e) {
+ OutputHandler.log(e.getMessage());
+ }
+
+ }
+ // did we read the whole stuff?
+ if (null != line) {
+ // no
+ foundSource = false;
+ foundTarget = false;
+
+ return this.data;
+
+ } else {
+ // ok , its the end but is everything written now?
+ if (!endIt) {
+ // there is something to write
+ // but next time we can end it
+ endIt = true;
+ if(!foundTarget){
+ createTargetLine();
+ }
+ // write
+ return this.data;//last lines
+ } else {
+
+ showStat();
+ return null;
+ }
+ }
+ // }catch(ConverterException e) {
+ // Converter.log(e.getMessage());
+ // return null;
+ // }
+ }
+
+ /**
+ *
+ */
+ private void createTargetLine() {
+ targetLangMiss++;
+ // if not, create one ...
+ data[1] = new ExtMap(SDFReader.targetLineNames,
+ splittedLineBuffer);
+ data[1].put("TargetLanguageID",
+ this.targetLanguage);
+ if ((String) data[1].get("TargetText") != EMPTY)
+ data[1].put("TargetText", EMPTY);
+ if ((String) data[1].get("TargetHText") != EMPTY)
+ data[1].put("TargetHText", EMPTY);
+ if ((String) data[1].get("TargetQText") != EMPTY)
+ data[1].put("TargetQText", EMPTY);
+ if ((String) data[1].get("TargetTitle") != EMPTY)
+ data[1].put("TargetTitle", EMPTY);
+ this.data[1].put("BlockNr", blockNrFormatter.format(blockNr)+'-'+Integer.toString(this.CurrentBlockHash));
+ targetLangCreate++;
+ }
+
+ /**
+ * Show the statistic information got while
+ * reading the file
+ *
+ * @throws IOException
+ */
+ private void showStat() throws IOException {
+ OutputHandler.out(EMPTY);OutputHandler.out(EMPTY);
+ // OutputHandler.out("Hashes: " + (theHashes.size()) + " ");
+ OutputHandler.out("Blocks found: " + blockNr + " ");
+ OutputHandler.out(EMPTY);
+ OutputHandler.out("Lines read: " + (getLineNumber()) + " ");
+ OutputHandler
+ .dbg("Lines created " + (targetLangCreate) + " ");
+ OutputHandler.dbg(" -------");
+ OutputHandler.dbg("Lines total: "
+ + (getLineNumber() + targetLangCreate) + " ");
+ OutputHandler.dbg("Lines skipped: " + skippedLines + " ");
+
+ OutputHandler.dbg("Source Language misses: " + sourceLangMiss + " ");
+ OutputHandler.dbg("Target Language misses: " + targetLangMiss + " ");
+ OutputHandler.dbg("Blocks found: " + blockNr + " ");
+ OutputHandler.dbg("Blocks skipped: " + skippedBlocks + " ");
+ if ((sourceLangMiss + skippedBlocks + skippedLines) > 0)
+ OutputHandler.out("\n---! Errors found !--- view Logfile.\n\n"
+ + "To enable logfile use -l option at command line.\n"
+ + "For help type 'convert -h {Enter}'.\n");
+ }
+
+ /**
+ * Check the current line whether the source language
+ * or target language is in it
+ *
+ * @throws ConverterException if a not needed language or no target language is found
+ * in this block
+ * @throws IOException
+ *
+ */
+ final private void checkLanguage(String[] splittedLine)
+ throws ConverterException, IOException {
+ String langID = (String) SDFMap.get("LanguageID");
+
+ //maybe the source language is in this line
+ if (!foundSource && this.sourceLanguage.equals(langID)) {
+// found the next source language line
+ this.data[0] = new ExtMap(SDFReader.sourceLineNames, splittedLine);
+
+// this.data[0].put("BlockNr", Integer.toHexString(blockNr));
+// this.data[0].put("BlockHash", Integer.toHexString(this.CurrentBlockHash));
+ this.data[0].put("BlockNr", blockNrFormatter.format(blockNr)+'-'+Integer.toHexString(this.CurrentBlockHash));
+// this.data[0].put("BlockHash", blockHashFormatter.format(this.CurrentBlockHash));
+ foundSource = true;
+ return;
+
+ } else {
+ // or the target language is in this line
+ if (!foundTarget) {
+ //no target language is given at command line
+ if (this.targetLanguage.equals(EMPTY)) {
+ //try if we can use the current lines language for target
+ // language
+ if (!langID.equals(this.sourceLanguage)) {
+ //yes , we can use this lines laanguage as target
+ this.targetLanguage = langID;
+
+ //source and target language both are known: show it
+ OutputHandler.out("Source Language is: "
+ + this.sourceLanguage + " ");
+ OutputHandler.out("Target Language is: "
+ + this.targetLanguage + " ");
+ OutputHandler.out(EMPTY);
+ System.out.println("Start");
+
+ } else {
+ throw new ConverterException("(" + getLineNumber()
+ + ") No target language found: "
+ + this.targetLanguage);
+ }
+ }
+ if (this.targetLanguage.equals(langID)) {
+ this.data[1] = new ExtMap(SDFReader.targetLineNames,
+ splittedLine);// found the next target language line
+ this.data[1].put("BlockNr", blockNrFormatter.format(blockNr)+'-'+Integer.toHexString(this.CurrentBlockHash));
+ foundTarget = true;
+
+ return;
+ }
+ }//end !foundTarget
+ }
+ //if we go here we dont need the found language...
+ throw new ConverterException("found not needed language '"
+ + this.SDFMap.get("LanguageID") + "' in Line: "
+ + getLineNumber());
+
+ }
+
+ /**
+ * Make a dot on the screen to show the user that it is going on
+ */
+ private void makeDot() {
+ int count = 0;
+ if ((count = (int) super.getLineNumber() / 1000) > this.dotCount) {
+ this.dotCount = count;
+ OutputHandler.printDot();
+ }
+
+ }
+
+ /**
+ * split the SDFLine in its columns
+ *
+ * @param line the current SDFLine
+ * @return the splitted SDFLine as array of String
+ * or null if an error occours
+ * @throws IOException
+ */
+ private String[] split(String line) throws IOException {
+ check(line);
+ String[] splitLine;
+ if ((splitLine = line.split("\t")).length == 15)
+ return splitLine;
+ else
+ //an error occured
+ return null;
+ }
+
+ /**
+ * create a block Id from a splitted SDFLine
+ * the blockId consists of the column one to eight of an SDF File
+ *
+ * @param splitLine the line to create a block id from
+ * @return the blockId as String
+ */
+ private String getSDFBlockId(String[] splitLine) {
+ StringBuffer BlockId = new StringBuffer("");
+ for (int i = 0; i < 8; i++) {
+ BlockId.append(splitLine[i]);
+ }
+ return BlockId.toString();
+ }
+
+// public final boolean canRead() {
+// return this.sourceFile.canRead();
+// }
+
+ /**
+ * Check if there are not allowed characters in this line
+ *
+ * @param line the SDFLine to check
+ * @return if everything, ok the original
+ * else the wrong character as String
+ *
+ * @throws java.io.IOException
+ */
+ private String check(String line) throws java.io.IOException {
+ char c = ' ';
+ for (int i = 0; i < line.length(); i++) {
+ c = line.charAt(i);
+ if (c < 30 && c != 9) {
+ return (new Character(c)).toString();
+ }
+
+ }
+ return line;
+
+ }
+} \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/SDFWriter.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/SDFWriter.java
new file mode 100755
index 000000000000..98eb8c856e6a
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/SDFWriter.java
@@ -0,0 +1,175 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SDFWriter.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * SDFWriter.java
+ *
+ *
+ */
+
+package com.sun.star.tooling.converter;
+import java.io.*;
+import java.util.Map;
+
+/**
+ * Write data to a SDFFile
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+public class SDFWriter extends DataWriter {
+ /**
+ * the seperator the seperate columns
+ */
+ final String seperator=new String("\t");
+ /**
+ * an array of the SDF files column names if the source language is in
+ */
+ final static String[] sourceLineNames= {"Project","SourceFile","Dummy","ResType","GID","LID","HID","Platform","Width","SourceLanguageID","SourceText","SourceHText","SourceQText","SourceTitle","TimeStamp"};
+ /**
+ * an array of the SDF files column names if the target language is in
+ */
+ final static String[] targetLineNames= {"Project","SourceFile","Dummy","ResType","GID","LID","HID","Platform","Width","TargetLanguageID","TargetText","TargetHText","TargetQText","TargetTitle","TimeStamp"};
+ /**
+ * an array of the SDF files column names if the source and the target language is in
+ */
+ final static String[] outLineNames= {"BlockNr","Project","SourceFile","Dummy","ResType","GID","LID","HID","Platform","Width","SourceLanguageID","SourceText","SourceHText","SourceQText","SourceTitle","TargetLanguageID","TargetText","TargetHText","TargetQText","TargetTitle","TimeStamp"};
+
+ /**
+ * A Map holding the source language line content
+ */
+ private ExtMap sourceLine=new ExtMap(sourceLineNames,null);
+ /**
+ * A Map holding the target language line content
+ */
+ private ExtMap targetLine=new ExtMap(targetLineNames,null);
+ /**
+ * A Map holding the whole content for output
+ */
+ private ExtMap outData=new ExtMap(outLineNames, null);
+// private ExtMap SDFLine;
+// private InputStreamReader isr;
+ /**
+ * The language to translate from
+ */
+ private String sourceLanguage;
+ /**
+ * The language to translate to
+ */
+ private String targetLanguage;
+
+// private boolean SourceIsFirst=false;
+
+
+
+
+ /**
+ * Create a new Instance of SDFWriter
+ *
+ * @param bos BufferedWriter to write to
+ * @param charset the charset to use to write
+ * @throws java.io.UnsupportedEncodingException
+ */
+ public SDFWriter(BufferedOutputStream bos,String charset) throws java.io.UnsupportedEncodingException {
+ super(bos,charset);
+
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#writeData()
+ */
+ public final void writeData() throws java.io.IOException {
+
+ StringBuffer buffer=new StringBuffer("");
+
+ // get the values of the found fields
+ //create the two sdf lines
+
+ //at first the source language line
+ for(int i=0;i<sourceLineNames.length;i++){
+ // put them together for output
+ buffer.append(outData.get(sourceLineNames[i]));
+ if(i!=sourceLineNames.length-1) {
+ // seperate the fields with tab
+ buffer.append(seperator);
+ }else{
+ // this line is full
+ // so close it with lf
+ buffer.append(lineEnd);
+ Converter.countLine();
+ }
+ }
+ // is there a target line with anything in the strings?
+ if (!(outData.get("TargetLanguageID")==null||((outData.get("TargetTitle").equals("")&&outData.get("TargetText").equals("")&&outData.get("TargetHText").equals("")&&outData.get("TargetQText").equals(""))))){
+ //now the target language line
+ for(int i=0;i<targetLineNames.length;i++){
+ // put them together for output
+ buffer.append(outData.get(targetLineNames[i]));
+ if(i!=targetLineNames.length-1) {
+ // seperate the fields with tab
+ buffer.append(seperator);
+ }else{
+ // this line is full
+ //so close it with lf
+ buffer.append(lineEnd);
+ Converter.countLine();
+ }
+ }
+ }
+ this.write(buffer.toString());
+
+ }
+
+
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#writeData(java.util.Map[])
+ */
+ protected void writeData(Map[] data) throws IOException {
+ // TODO redesign DataHandler in the way that this is not nessesary any more
+
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#getDataFrom(com.sun.star.tooling.converter.DataHandler)
+ */
+ protected void getDataFrom(DataHandler handler) throws IOException {
+
+ handler.putDataTo(this.outData);
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#getDatafrom(com.sun.star.tooling.converter.DataHandler)
+ */
+ protected void getDatafrom(DataHandler handler) throws IOException {
+
+ handler.putDataTo(this.outData);
+
+ }
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/XLIFFReader.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/XLIFFReader.java
new file mode 100755
index 000000000000..522dcc18a5bd
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/XLIFFReader.java
@@ -0,0 +1,745 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: XLIFFReader.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * XLIFFReader.java
+ *
+ *
+ */
+package com.sun.star.tooling.converter;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Map;
+
+import com.sun.star.tooling.languageResolver.LanguageResolver;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+/**
+ * Parse the given file and extract the content needed.
+ * <br/>
+ * This Reader understands the parts of the
+ * <a href="http://www.oasis-open.org/committees/xliff/documents/cs-xliff-core-1.1-20031031.htm">xliff</a> spezification used to translate
+ * the strings in Star-Office and Open-Office.
+ * <br/>
+ * The given file is parsed and the content is stored in a HashMap with those keys:
+ * <br/>
+ * "BlockNr" originally coming from reading the sdf file, contains 'block nr in sdf file'+'-'+'hash value of the sdf id fields'.<br/>
+ * "Project" first column in sdf file format.<br/>
+ * "SourceFile" second column in sdf file format.<br/>
+ * "Dummy" third column in sdf file format.<br/>
+ * "ResType" 4. column in sdf file format.<br/>
+ * "GID" 5. column in sdf file format. <br/>
+ * "LID" 6. column in sdf file format.<br/>
+ * "HID" 7. column in sdf file format.<br/>
+ * "Platform" 8. column in sdf file format. <br/>
+ * "Width", 9. column in sdf file format.<br/>
+ * "SourceLanguageID" 10. column in sdf file format(in the line with the source language).<br/>
+ * "SourceText" 11. column in sdf file format(in the line with the source language).<br/>
+ * "SourceHText" 12. column in sdf file format(in the line with the source language).<br/>
+ * "SourceQText" 13. column in sdf file format(in the line with the source language).<br/>
+ * "SourceTitle" 14. column in sdf file format(in the line with the source language).<br/>
+ * "TargetLanguageID" 10. column in sdf file format (in the line with the target language).<br/>
+ * "TargetText" 11. column in sdf file format (in the line with the target language).<br/>
+ * "TargetHText" 12. column in sdf file format (in the line with the target language).<br/>
+ * "TargetQText" 13. column in sdf file format (in the line with the target language).<br/>
+ * "TargetTitle", 14. column in sdf file format (in the line with the target language).<br/>
+ * "TimeStamp" 15. column in sdf file format.<br/>
+ * @
+ * @author Christian Schmidt 2005
+ *
+ */
+public class XLIFFReader extends DefaultHandler {
+
+ /**
+ * A String array holding the keys used by the HashMap holding the Data
+ */
+ private final String[] dataNames = { "BlockNr", "Project",
+ "SourceFile", "Dummy", "ResType", "GID", "LID", "HID", "Platform",
+ "Width", "SourceLanguageID", "SourceText", "SourceHText",
+ "SourceQText", "SourceTitle", "TargetLanguageID", "TargetText",
+ "TargetHText", "TargetQText", "TargetTitle", "TimeStamp" };
+
+ /**
+ * Used to index in the data array
+ */
+ static int index = 0;
+
+ /**
+ * The Map that holds the data returned by this class
+ */
+ private Map moveData = new ExtMap();
+
+ /**
+ * A Map that holds yet incomplete data
+ * until all depending transunits are found
+ */
+ private Hashtable DataStore = new Hashtable();
+
+ /**
+ * An Elements name
+ */
+ private String name = new String("");
+
+ /**
+ *List of Attributes used by an Element
+ */
+ private Attributes attrs;
+
+// private String tagElement = new String("");
+
+ /**
+ * Indicates whether the next found content string should be printed
+ */
+ private boolean printThis = false;
+ /**
+ * Indicates whether the next found content string should be stored
+ */
+ private boolean storeIt = false;
+
+ /**
+ * data holds the information created while parsing
+ *
+ */
+ private String[] data = new String[26];
+
+ /**
+ * The handler used by this class
+ */
+ private final DataHandler handler;
+ /**
+ * The target used by this class
+ */
+ private final DataWriter target;
+
+// private boolean searchForText = false;
+
+ /**
+ * counts how many dots are made
+ */
+ private int dotCount;
+
+ /**
+ * Counts how many Trans Units are read
+ */
+ private int transUnitCounter;
+
+ /**
+ * used source Language
+ */
+ private String sourceLanguage;
+
+ /**
+ * used target language
+ */
+ private String targetLanguage;
+
+ /**
+ * indicates whether this is the first Transunit
+ */
+ private boolean isFirst = true;
+
+ private static final String EMPTY = new String("");
+
+ /**
+ * the last index in data where something is written
+ */
+ private int oldindex;
+
+// private boolean isBptEptTag;
+
+// private String innerString;
+//
+// private String key;
+
+ /**
+ * Index for the BlockNr in the data array
+ */
+ private static final int BLOCKNR_IDX = 0;
+ /**
+ * Index for the Project in the data array
+ */
+ private static final int PROJECT_IDX = 1;
+ /**
+ * Index for the Sourcefile name in the data array
+ */
+ private static final int SOURCEFILE_IDX = 2;
+ /**
+ * Index for the 'dummy' in the data array
+ */
+ private static final int DUMMY_IDX = 3;
+ /**
+ * Index for the Group Id in the data array
+ */
+ private static final int GID_IDX = 4;
+ /**
+ * Index for the Local Id in the data array
+ */
+ private static final int LID_IDX = 5;
+ /**
+ * Index for the Help Id in the data array
+ */
+ private static final int HID_IDX = 6;
+ /**
+ * Index for the Platform in the data array
+ */
+ private static final int PLATFORM_IDX = 7;
+ /**
+ * Index for the 'Width' in the data array
+ */
+ private static final int WIDTH_IDX = 8;
+ /**
+ * Index for the Sourcelanguage Id in the data array
+ */
+ private static final int SOURCE_LANGUAGE_ID_IDX = 10;
+ /**
+ * Index for the Source Text in the data array
+ */
+ private static final int SOURCE_TEXT_IDX = 11;
+ /**
+ * Index for the Source Helptext in the data array
+ */
+ private static final int SOURCE_HELPTEXT_IDX = 12;
+ /**
+ * Index for the Source Quickhelp Text in the data array
+ */
+ private static final int SOURCE_QUICK_HELPTEXT_IDX = 13;
+ /**
+ * Index for the Source Titletext in the data array
+ */
+ private static final int SOURCE_TITLETEXT_IDX = 14;
+ /**
+ * Index for the Timestamp in the data array
+ */
+ private static final int TIMESTAMP_IDX = 15;
+ /**
+ * Index for the res type in the data array
+ */
+ private static final int RESTYPE_IDX = 16;
+ /**
+ * Index for the Target Language Id in the data array
+ */
+ private static final int TARGET_LANGUAGE_ID_IDX = 20;
+ /**
+ * Index for the Target Text in the data array
+ */
+ private static final int TARGET_TEXT_IDX = 21;
+ /**
+ * Index for the Target Helptext in the data array
+ */
+ private static final int TARGET_HELP_TEXT_IDX = 22;
+ /**
+ * Index for the Target Quickhelp Text in the data array
+ */
+ private static final int TARGET_QUICKHELP_TEXT_IDX = 23;
+ /**
+ * Index for the Target Titletext in the data array
+ */
+ private static final int TARGET_TITLE_TEXT_IDX = 24;
+ /**
+ * Index for the Found Parts Counter in the data array
+ */
+ private static final int FOUND_PARTS_COUNTER_IDX = 18;
+
+ /**
+ * used to find the matching ISO or RFC3066 language code
+ */
+ LanguageResolver languageResolver;
+
+ private boolean doBlockCompleteCheck=true;
+
+
+
+ /**
+ * Create a new Instance of XLIFFReader
+ *
+ * @param handler the DataHandler to use
+ * @param target the target used
+ * @throws IOException
+ */
+ public XLIFFReader(DataHandler handler, DataWriter target) throws IOException {
+ this.languageResolver = new LanguageResolver();
+ this.handler = handler;
+ this.target = target;
+ }
+
+ /**
+ * Create a new Instance of XLIFFReader
+ *
+ * @param handler the DataHandler to use
+ * @param target the target used
+ * @param doBlockCompleteCheck indicates whether every single transunit should be returned or the whole block data is to be collected
+ *
+ * @throws IOException
+ */
+ public XLIFFReader(DataHandler handler, DataWriter target,boolean doBlockCompleteCheck) throws IOException {
+ this(handler, target);
+ this.languageResolver = new LanguageResolver();
+ this.doBlockCompleteCheck=doBlockCompleteCheck;
+
+ }
+
+ /**
+ * delete and initialize the data content
+ */
+ public void initData() {
+ for (int i = BLOCKNR_IDX; i < SOURCE_LANGUAGE_ID_IDX; i++) {
+ data[i] = "";
+ }
+ for (int i = SOURCE_TEXT_IDX; i < TIMESTAMP_IDX; i++) { // skip Time Stamp
+ data[i] = "";
+ }
+ for (int i = RESTYPE_IDX; i < TARGET_LANGUAGE_ID_IDX; i++) { // skip Source language ID
+ data[i] = "";
+ }
+ for (int i = TARGET_TEXT_IDX; i < 26; i++) {// skip Target language ID,
+ data[i] = "";
+ }
+
+ data[DUMMY_IDX] = "0";//dummy
+ data[FOUND_PARTS_COUNTER_IDX] = "1";//parts found
+
+ }
+
+ /** (non-Javadoc)
+ * @see org.xml.sax.ContentHandler#startDocument()
+ */
+ public void startDocument() {
+ initData();
+ //System.out.print("Start");
+
+ }
+
+ /** (non-Javadoc)
+ * @see org.xml.sax.ContentHandler#endDocument()
+ */
+ public void endDocument() {
+
+ try {
+ showStatistic();
+ } catch (IOException e) {
+
+ OutputHandler.log(e.getMessage());
+
+ }
+ }
+
+ /** (non-Javadoc)
+ * @throws SAXException
+ * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
+ */
+ public void startElement(String namespaceURI, String sName, String qName,
+ Attributes attrs) throws SAXException {
+ this.name = new String(qName);
+ this.attrs = new AttributesImpl(attrs);
+ String resType;
+
+ String attributeName = new String("");
+ String attribute = new String("");
+ String tagElement = new String("");
+ int i;
+
+ if (qName.equals("bpt")||qName.equals("ept")||qName.equals("sub")||qName.equals("ex")) {
+ //ignore bpt, ept, ex and sub tags
+ // content of the tags will be stored
+
+ storeIt=true;
+ return;
+
+ }
+ if (qName.equals("target")) {
+ if ((resType = data[RESTYPE_IDX]) == null) {
+
+ } else {
+ if ("res".equals(resType)) {
+ index = TARGET_TEXT_IDX;
+
+ storeIt = true;
+ return;
+ }
+ // if("res-Help".equals(resType)){
+ // index=TARGET_HELP_TEXT_IDX;
+ // storeIt=true;
+ // return;
+ // }
+ if ("res-QuickHelp".equals(resType)) {
+ index = TARGET_QUICKHELP_TEXT_IDX;
+
+ storeIt = true;
+ return;
+ }
+ if ("res-Title".equals(resType)) {
+ index = TARGET_TITLE_TEXT_IDX;
+
+ storeIt = true;
+ return;
+ }
+ }
+
+ }
+ if (qName.equals("source")) {
+ if ((resType = data[RESTYPE_IDX]) == null) {
+ //throw new SAXException("Ressource type not found");
+ } else {
+ if ("res".equals(resType)) {
+ index = SOURCE_TEXT_IDX;
+
+ storeIt = true;
+ return;
+ }
+ // if("res-Help".equals(resType)){
+ // index=SOURCEHELPTEXT_IDX;
+ // storeIt=true;
+ // return;
+ // }
+ if ("res-QuickHelp".equals(resType)) {
+ index = SOURCE_QUICK_HELPTEXT_IDX;
+ storeIt = true;
+ return;
+ }
+ if ("res-Title".equals(resType)) {
+ index = SOURCE_TITLETEXT_IDX;
+ storeIt = true;
+ return;
+ }
+ }
+ }
+
+ if (qName.equals("file")) {
+ data[TIMESTAMP_IDX] = attrs.getValue("date");
+ //data[17]=(attrs.getValue("original"));
+ try{
+ data[SOURCE_LANGUAGE_ID_IDX] = (languageResolver.getISOFromRFC((String)attrs.getValue("source-language")));
+ if(languageResolver.getISOFromRFC((String)attrs.getValue("target-language"))!=null){
+ data[TARGET_LANGUAGE_ID_IDX] = (languageResolver.getISOFromRFC((String)attrs.getValue("target-language")));
+ }
+ }catch(Exception e){
+ OutputHandler.log(e.getMessage());
+ }
+ return;
+ }
+ if (qName.equals("trans-unit")) {
+ String id = attrs.getValue("id");
+ if ((DataStore.get(id)) != null) {
+ //TODO arraycopy might not be nessessary
+ System.arraycopy((String[]) DataStore.get(id), 0, data, 0,
+ data.length);
+ int help = (new Integer(data[FOUND_PARTS_COUNTER_IDX])).intValue(); //found one more part
+ help++; // refresh the actual found parts
+ data[FOUND_PARTS_COUNTER_IDX] = (new Integer(help)).toString(); // belonging to this information
+
+ DataStore.remove(attrs.getValue("id")); // TODO this can be deleted?
+ } else {
+
+ data[BLOCKNR_IDX] = (attrs.getValue("id")); // a new part
+ }
+ data[RESTYPE_IDX] = (attrs.getValue("restype"));
+
+ return;
+ }
+
+ if (qName.equals("context")) {
+
+ String value = attrs.getValue("context-type");
+
+ if ("SourceHelpText".equals(value)) {
+ index = SOURCE_HELPTEXT_IDX;
+ storeIt = true;
+ return;
+ }else if ("TargetHelpText".equals(value)) {
+ index = TARGET_HELP_TEXT_IDX;
+ storeIt = true;
+ return;
+ }else if ("DBType".equals(value)) {
+ //index=SOURCEFILE_IDX;
+ //storeIt=true;
+ return;
+ }else if ("Project".equals(value)) {
+ index = PROJECT_IDX;
+ storeIt = true;
+ return;
+ }else if ("Filename".equals(value)) {
+ index = SOURCEFILE_IDX;
+ storeIt = true;
+ return;
+ }else if ("Type".equals(value)) {
+ index = RESTYPE_IDX;
+ storeIt = true;
+ return;
+ }else if ("GID".equals(value)) {
+ index = GID_IDX;
+ storeIt = true;
+ return;
+ }else if ("LID".equals(value)) {
+ index = LID_IDX;
+ storeIt = true;
+ return;
+ }else if ("HID".equals(value)) {
+ index = HID_IDX;
+ storeIt = true;
+ return;
+ }else if ("Platform".equals(value)) {
+ index = PLATFORM_IDX;
+ storeIt = true;
+ return;
+ }else if ("Width".equals(value)) {
+ index = WIDTH_IDX;
+ storeIt = true;
+ return;
+ }
+
+ }
+
+ }
+
+ /** (non-Javadoc)
+ * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void endElement(String namespaceURI, String sName, String qName)
+ throws SAXException {
+ //we ignore bpt and ept tags
+ if(!(qName.equals("bpt")||qName.equals("ept")||qName.equals("sub")||qName.equals("ex"))){
+ storeIt = false;
+ }
+ if (qName.equals("trans-unit")) {
+ showData();
+ }
+
+ }
+
+ /** (non-Javadoc)
+ * @see org.xml.sax.ContentHandler#characters(char[], int, int)
+ */
+ public void characters(char[] ch, int start, int length) {
+
+ // checkContent();
+ String str2 = new String(ch, start, length);
+
+ if (storeIt) {
+
+ String str = new String(ch, start, length);
+ if (index == oldindex) {
+ data[index] += str;
+ } else {
+ data[index] = str;
+ }
+
+ }
+ oldindex = index;
+
+ }
+
+ /** (non-Javadoc)
+ * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
+ */
+ public void error(SAXParseException e) throws SAXParseException {
+
+ OutputHandler.log(e.getMessage());
+ }
+
+ /** (non-Javadoc)
+ * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
+ */
+ public void fatalError(SAXParseException e) throws SAXParseException {
+
+ OutputHandler.log("PARSE ERROR in line " + e.getLineNumber() + ", "
+ + e.getMessage() );
+
+ }
+
+ /** (non-Javadoc)
+ * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
+ */
+ public void warning(SAXParseException e) throws SAXParseException {
+ //throw e;
+ OutputHandler.log(e.getMessage());
+ }
+
+ /**
+ * Put the Data to the DataHandler
+ * tell the Writer to write it
+ *
+ * @throws SAXException
+ */
+ public void showData() throws SAXException {
+ transUnitCounter++;
+ makeDot();
+ if (isComplete()) {
+
+ try {
+ moveData();
+ if (isFirst == true) {
+ this.sourceLanguage = (String) this.moveData
+ .get("SourceLanguageID");
+ this.targetLanguage = (String) this.moveData
+ .get("TargetLanguageID");
+ OutputHandler.out(EMPTY);
+ OutputHandler.out("Source Language is: "
+ + this.sourceLanguage);
+ OutputHandler.out("Target Language is: "
+ + this.targetLanguage);
+ OutputHandler.out(EMPTY);
+ OutputHandler.out("Start");
+ OutputHandler.out(EMPTY);
+ isFirst = false;
+ }
+ target.getDataFrom(handler);
+ target.writeData();
+
+ } catch (java.io.IOException e) {
+ throw new SAXException(e);
+ }
+
+ } else {
+ DataStore.put(data[BLOCKNR_IDX], data.clone());
+ initData();
+
+ }
+ initData();
+ }
+
+
+ /**
+ * put the data in an Map in the format that
+ * DataHandler can handle it
+ */
+ final public void moveData() {
+
+ moveData.put("BlockNr", data[BLOCKNR_IDX]);
+
+ moveData.put("Project", data[PROJECT_IDX]);
+
+ moveData.put("SourceFile", data[SOURCEFILE_IDX]);
+
+ moveData.put("Dummy", "0");
+
+ moveData.put("ResType", data[RESTYPE_IDX]);
+
+ moveData.put("GID", data[GID_IDX]);
+
+ moveData.put("LID", data[LID_IDX]);
+
+ moveData.put("HID", data[HID_IDX]);
+
+ moveData.put("Platform", data[PLATFORM_IDX]);
+
+ if (EMPTY.equals(data[WIDTH_IDX]))
+ data[WIDTH_IDX] = "0";
+ moveData.put("Width", data[WIDTH_IDX]);
+
+ moveData.put("SourceLanguageID", data[SOURCE_LANGUAGE_ID_IDX]);
+
+ moveData.put("SourceText", data[SOURCE_TEXT_IDX]);
+
+ moveData.put("SourceHText", data[SOURCE_HELPTEXT_IDX]);
+
+ moveData.put("SourceQText", data[SOURCE_QUICK_HELPTEXT_IDX]);
+
+ moveData.put("SourceTitle", data[SOURCE_TITLETEXT_IDX]);
+
+ moveData.put("TargetLanguageID", data[TARGET_LANGUAGE_ID_IDX]);
+
+ moveData.put("TargetText", data[TARGET_TEXT_IDX]);
+
+ moveData.put("TargetHText", data[TARGET_HELP_TEXT_IDX]);
+
+ moveData.put("TargetQText", data[TARGET_QUICKHELP_TEXT_IDX]);
+
+ moveData.put("TargetTitle", data[TARGET_TITLE_TEXT_IDX]);
+
+ moveData.put("TimeStamp", data[TIMESTAMP_IDX]);
+
+ //and give it to the data handler
+ this.handler.fillDataWith(moveData);
+ }
+
+ /**
+ * complete means all depending parts have been found esp. all res types
+ * that belong to the same SDF Line
+ *
+ * @return true if the data is complete
+ *
+ */
+ final public boolean isComplete() {
+
+ if(!doBlockCompleteCheck){
+ return true;
+ }
+
+ String sParts;
+ if (data[FOUND_PARTS_COUNTER_IDX] == EMPTY)
+ data[FOUND_PARTS_COUNTER_IDX] = "1"; //this is the first part
+
+ String sFoundParts = data[FOUND_PARTS_COUNTER_IDX];
+ //create the new 'id'
+ sParts = data[BLOCKNR_IDX].substring(data[BLOCKNR_IDX].lastIndexOf(":") + 1);
+
+ if (sFoundParts.equals(sParts)) {
+ return true;
+ }
+ return false;
+ }
+
+ // TODO this belongs in OutputHandler
+ /**
+ * show the user that it is going
+ * on by printing dots on the screen
+ *
+ */
+ private void makeDot() {
+ int count = 0;
+ if ((count = (int) this.transUnitCounter / 1000) > this.dotCount) {
+ this.dotCount = count;
+ OutputHandler.printDot();
+ }
+ }
+
+ /**
+ * show the statistic data found while parse this file
+ *
+ * @throws IOException
+ */
+ final void showStatistic() throws IOException {
+ OutputHandler.out(EMPTY);
+ OutputHandler.out("TransUnits found: " + this.transUnitCounter);
+ // every data in DataStore is
+ // skipped 'cause its not complete
+ // TODO count really every transunit not only the data (might consist of
+ // more than one
+ OutputHandler.dbg("TransUnits skip : " + this.DataStore.size());
+ //Converter.out(EMPTY);
+ }
+}
+
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/XLIFFWriter.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/XLIFFWriter.java
new file mode 100755
index 000000000000..42eef42884c1
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/XLIFFWriter.java
@@ -0,0 +1,535 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: XLIFFWriter.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ *
+ /*
+ * XLIFFWriter.java
+ *
+ *
+ */
+
+package com.sun.star.tooling.converter;
+
+import java.io.*;
+import java.util.*;
+
+import com.sun.star.tooling.DirtyTags.DirtyTagWrapper;
+import com.sun.star.tooling.languageResolver.LanguageResolver;
+import com.sun.star.tooling.languageResolver.LanguageResolver.LanguageResolvingException;
+
+/**
+ * Write the Data to a wellformed XLIFF File
+ *
+ * @author Christian Schmidt
+ */
+public class XLIFFWriter extends DataWriter {
+
+ /**
+ * An array holding the keys of the HashMap containing the source language string
+ */
+ private final static String[] sourceLineNames = { "Project", "SourceFile",
+ "Dummy", "ResType", "GID", "LID", "HID", "Platform", "Width",
+ "SourceLanguageID", "SourceText", "SourceHText", "SourceQText",
+ "SourceTitle", "TimeStamp" };
+ /**
+ * An array holding the keys of the HashMap containing the target language string
+ */
+ private final static String[] targetLineNames = { "Project", "SourceFile",
+ "Dummy", "ResType", "GID", "LID", "HID", "Platform", "Width",
+ "TargetLanguageID", "TargetText", "TargetHText", "TargetQText",
+ "TargetTitle", "TimeStamp" };
+ /**
+ * An array holding the keys of the HashMap containing the source and target language string
+ */
+ private final static String[] outLineNames = { "BlockNr", "Project",
+ "SourceFile", "Dummy", "ResType", "GID", "LID", "HID", "Platform",
+ "Width", "SourceLanguageID", "SourceText", "SourceHText",
+ "SourceQText", "SourceTitle", "TargetLanguageID", "TargetText",
+ "TargetHText", "TargetQText", "TargetTitle", "TimeStamp" };
+ /**
+ * An Map holding the source and target content
+ */
+ private final Map data = new ExtMap(outLineNames, null);
+
+
+ /**
+ * Indicates if this is the first Transunit to write
+ */
+ boolean isFirst = true;
+
+ LanguageResolver languageResolver;
+
+
+ /**
+ * Create a new Instance of XLIFFWriter
+ *
+ * @param bos the Buffered Output Stream to write to
+ * @param charset the charset to use
+ * @throws IOException
+ */
+ public XLIFFWriter(BufferedOutputStream bos, String charset)
+ throws IOException {
+ super(bos, charset);
+ this.languageResolver =new LanguageResolver();
+
+
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#getDatafrom(com.sun.star.tooling.converter.DataHandler)
+ */
+ public void getDatafrom(DataHandler handler) throws java.io.IOException {
+ handler.putDataTo(this.data);
+ }
+
+ /**
+ * check if the item is an empty String
+ *
+ * @param item the string to check
+ * @return true if it is not empty, false if it is empty
+ */
+ private final boolean isUsed(String item) {
+ if (!"".equals(item))
+ return true;
+ return false;
+ }
+
+ /**
+ * Replaces all characters that mustn't be in XLIFF PCdata
+ *
+ * @param string the string to check
+ * @return the checked string with all characters replaced
+ * @throws java.io.IOException
+ */
+ private final String xmlString( final String string) throws java.io.IOException {
+ if (string == null)
+ return string; // ""
+ String str = string;
+// str = str.replaceAll("&", "&amp;");
+// str = str.replaceAll("<", "&lt;");
+// str = str.replaceAll(">", "&gt;");
+// str = str.replaceAll("\"", "&quot;");
+// str = str.replaceAll("'", "&apos;");
+ for(int i=0;i<str.length();i++){
+ if(str.charAt(i)=='&'){
+ str=str.substring(0, i)+"&amp;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='<'){
+ str=str.substring(0, i)+"&lt;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='>'){
+ str=str.substring(0, i)+"&gt;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='"'){
+ str=str.substring(0, i)+"&quot;"+str.substring(i+1);
+ continue;
+ }
+
+ if(str.charAt(i)=='\''){
+ str=str.substring(0, i)+"&apos;"+str.substring(i+1);
+ continue;
+ }
+ }
+
+ return str;
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.Writer#close()
+ */
+ public void close() throws IOException {
+ this.writeTrailer();
+
+ super.close();
+ }
+
+ /* (non-Javadoc)
+ * @see com.sun.star.tooling.converter.DataWriter#writeData()
+ */
+ public void writeData() throws IOException {
+ if (isFirst) {
+
+ writeHeader();
+ isFirst = false;
+ }
+ try{
+ writeTransUnit();
+ }catch(DirtyTagWrapper.TagWrapperException e){
+
+ }
+ }
+
+ /**
+ * Write the XLIFFFiles header
+ *
+ * @throws IOException
+ */
+ private void writeHeader() throws IOException {
+
+ this.write(getHeader());
+ }
+
+ /**
+ * Write the XLIFFFiles Trailer
+ *
+ * @throws IOException
+ */
+ private void writeTrailer() throws IOException {
+ this.write(getTrailer());
+ }
+
+ /**
+ * Write the next TransUnit
+ *
+ * @throws IOException
+ */
+ private void writeTransUnit() throws IOException, DirtyTagWrapper.TagWrapperException {
+ try{
+ StringBuffer writeBuffer = new StringBuffer(1000);
+
+ StringBuffer allLinesEnd = new StringBuffer(200);
+ String sRessource = "";
+ int parts = 0;
+ if (data == null) {
+ OutputHandler.out("error");// TBD Exception
+ }
+
+ if (!(this.data.get("SourceText").equals("") || this.data.get(
+ "SourceText").equals(" "))) {
+ parts++;
+ }
+ // if(!(this.data.get("SourceHText").equals("")||this.data.get("SourceHText").equals("
+ // "))){
+ // parts++;
+ // }
+ if (!(this.data.get("SourceQText").equals("") || this.data.get(
+ "SourceQText").equals(" "))) {
+ parts++;
+ }
+ if (!(this.data.get("SourceTitle").equals("") || this.data.get(
+ "SourceTitle").equals(" "))) {
+ parts++;
+ }
+ if (!(this.data.get("SourceText").equals("") || this.data.get(
+ "SourceText").equals(" "))) {
+ sRessource = "res"; // normal TEXT source
+
+ allLinesEnd
+ .append("\t\t\t\t<context-group name=\"StarOffice Attributes\">\n");
+
+ if (isUsed((String) this.data.get("ResType")))
+ allLinesEnd
+ .append("\t\t\t\t\t<context context-type=\"DBType\">"
+ + xmlString((String) this.data.get("ResType"))
+ + "</context>\n");
+ if (isUsed((String) this.data.get("Project")))
+ allLinesEnd
+ .append("\t\t\t\t\t<context context-type=\"Project\">"
+ + xmlString((String) this.data.get("Project"))
+ + "</context>\n");
+ if (isUsed((String) this.data.get("SourceFile")))
+ allLinesEnd
+ .append("\t\t\t\t\t<context context-type=\"Filename\">"
+ + xmlString((String) this.data
+ .get("SourceFile")) + "</context>\n");
+ if (isUsed((String) this.data.get("SourceHText")))
+ allLinesEnd
+ .append("\t\t\t\t\t<context context-type=\"SourceHelpText\">"
+ + xmlString((String) this.data
+ .get("SourceHText")) + "</context>\n");
+ if (isUsed((String) this.data.get("TargetHText")))
+ allLinesEnd
+ .append("\t\t\t\t\t<context context-type=\"TargetHelpText\">"
+ + xmlString((String) this.data
+ .get("TargetHText")) + "</context>\n");
+ if (isUsed((String) this.data.get("ResType")))
+ allLinesEnd.append("\t\t\t\t\t<context context-type=\"Type\">"
+ + xmlString((String) this.data.get("ResType"))
+ + "</context>\n");
+ if (isUsed((String) this.data.get("GID")))
+ allLinesEnd.append("\t\t\t\t\t<context context-type=\"GID\">"
+ + xmlString((String) this.data.get("GID"))
+ + "</context>\n");
+ if (isUsed((String) this.data.get("LID")))
+ allLinesEnd.append("\t\t\t\t\t<context context-type=\"LID\">"
+ + xmlString((String) this.data.get("LID"))
+ + "</context>\n");
+ if (isUsed((String) this.data.get("HID")))
+ allLinesEnd.append("\t\t\t\t\t<context context-type=\"HID\">"
+ + xmlString((String) this.data.get("HID"))
+ + "</context>\n");
+ if (isUsed((String) this.data.get("Platform")))
+ allLinesEnd
+ .append("\t\t\t\t\t<context context-type=\"Platform\">"
+ + xmlString((String) this.data.get("Platform"))
+ + "</context>\n");
+ if (isUsed((String) this.data.get("Width")))
+ allLinesEnd.append("\t\t\t\t\t<context context-type=\"Width\">"
+ + xmlString((String) this.data.get("Width"))
+ + "</context>\n");
+ allLinesEnd.append("\t\t\t\t</context-group>\n"
+ + "\t\t\t</trans-unit>\n");
+
+ writeBuffer.append("\t\t\t<trans-unit id=\""
+ + this.data.get("BlockNr") + ":" + parts + "\" restype=\""
+ + sRessource + "\" translate=\"yes\">\n");
+ if (isUsed((String) this.data.get("SourceText")))
+ writeBuffer.append("\t\t\t\t<source xml:lang=\""
+ + languageResolver.getRFCFromISO((String)this.data.get("SourceLanguageID")) + "\">"
+ + DirtyTagWrapper.wrapString((String) this.data.get("SourceText"))
+ + "</source>\n");
+
+ if (isUsed((String) this.data.get("TargetText")))
+ writeBuffer
+ .append("\t\t\t\t<target state=\"to_translate\" xml:lang=\""
+ + languageResolver.getRFCFromISO((String)this.data.get("TargetLanguageID"))
+ + "\">"
+ +DirtyTagWrapper.wrapString((String) this.data
+ .get("TargetText")) + "</target>\n");
+ writeBuffer.append(allLinesEnd);
+ Converter.countLine();
+
+ }
+ // if(!(this.data.get("SourceHText").equals("")||this.data.get("SourceHText").equals("
+ // "))){
+ // sRessource="res-Help"; //Source is Help
+ // //sLineNumber=String.valueOf(iLineNumber);//
+ // writeBuffer.append("\t\t<trans-unit
+ // id=\""+this.data.get("BlockNr")+":"+parts+"\"
+ // restype=\""+sRessource+"\" translate=\"yes\">\n");//always translate
+ // if(isUsed((String)this.data.get("SourceHText")))
+ // writeBuffer.append("\t\t\t<source
+ // xml:lang=\""+this.data.get("SourceLanguageID")+"\">"+xmlString((String)this.data.get("SourceHText"))+"</source>\n");
+ // if(isUsed((String)this.data.get("TargetHText")))
+ // writeBuffer.append("\t\t\t<target state=\"to_translate\"
+ // xml:lang=\""+this.data.get("TargetLanguageID")+"\">"+xmlString((String)this.data.get("TargetHText"))+"</target>\n");
+ // writeBuffer.append(allLinesEnd);
+ // Converter.countLine();
+ // }
+
+ if (!(this.data.get("SourceQText").equals("") || this.data.get(
+ "SourceQText").equals(" "))) {
+ sRessource = "res-QuickHelp"; // Source is OuickHelp
+ // sLineNumber=String.valueOf(iLineNumber);//
+ writeBuffer.append("\t\t\t<trans-unit id=\""
+ + this.data.get("BlockNr") + ":" + parts + "\" restype=\""
+ + sRessource + "\" translate=\"yes\">\n");// always translate
+ if (isUsed((String) this.data.get("SourceQText")))
+ writeBuffer.append("\t\t\t\t<source xml:lang=\""
+ + languageResolver.getRFCFromISO((String)this.data.get("SourceLanguageID")) + "\">"
+ + DirtyTagWrapper.wrapString((String) this.data.get("SourceQText"))
+ + "</source>\n");
+ if (isUsed((String) this.data.get("TargetQText")))
+ writeBuffer
+ .append("\t\t\t\t<target state=\"to_translate\" xml:lang=\""
+ + languageResolver.getRFCFromISO((String)this.data.get("TargetLanguageID"))
+ + "\">"
+ + DirtyTagWrapper.wrapString((String) this.data
+ .get("TargetQText")) + "</target>\n");
+ writeBuffer.append(allLinesEnd);
+ Converter.countLine();
+ }
+
+ if (!(this.data.get("SourceTitle").equals("") || this.data.get(
+ "SourceTitle").equals(" "))) {
+ sRessource = "res-Title"; // Source is Title
+
+ writeBuffer.append("\t\t\t<trans-unit id=\""
+ + this.data.get("BlockNr") + ":" + parts + "\" restype=\""
+ + sRessource + "\" translate=\"yes\">\n");// always translate
+ if (isUsed((String) this.data.get("SourceTitle")))
+ writeBuffer.append("\t\t\t\t<source xml:lang=\""
+ + languageResolver.getRFCFromISO((String)this.data.get("SourceLanguageID")) + "\">"
+ + DirtyTagWrapper.wrapString((String) this.data.get("SourceTitle"))
+ + "</source>\n");
+ if (isUsed((String) this.data.get("TargetTitle")))
+ writeBuffer
+ .append("\t\t\t\t<target state=\"to_translate\" xml:lang=\""
+ + languageResolver.getRFCFromISO((String)this.data.get("TargetLanguageID"))
+ + "\">"
+ + DirtyTagWrapper.wrapString((String) this.data
+ .get("TargetTitle")) + "</target>\n");
+ writeBuffer.append(allLinesEnd);
+ Converter.countLine();
+ }
+ this.write(writeBuffer.toString());
+ }catch(Exception e){
+ OutputHandler.log(e.getMessage());
+ }
+ }
+
+ /**
+ * Create the XLIFFFiles Header
+ *
+ * @return the header as string
+ * @throws java.io.UnsupportedEncodingException
+ */
+ private String getHeader() throws java.io.UnsupportedEncodingException {
+ return new String(
+ (getProcessingInstructionTag() + getDTDLine()
+ + openVersionLine() + openFileLine() + getHeaderTag() + openBodyTag())
+ .getBytes(), "UTF8");
+
+ }
+
+ /**
+ * Create the XLIFFFiles Trailer
+ *
+ * @return the trailer as string
+ */
+ private String getTrailer() {
+ return closeBodyTag() + closeFileLine() + closeVersionLine();
+ }
+
+ /**
+ * Create the Processing Instruction Tag used by this XLIFFFile
+ * @return the Processing Instruction Tag used by this XLIFFFile
+ */
+ private String getProcessingInstructionTag() {
+ String sPITagStart = "<?";
+ String sPIName = "xml ";
+ String sPIVersion = "version=\"1.0\" ";
+ String sPIEncoding = "encoding=\"UTF-8\"";
+ String sPITagEnd = "?>";
+ return sPITagStart + sPIName + sPIVersion + sPIEncoding
+ + /* sPIStandalone+ */sPITagEnd + '\n';
+ }
+
+ /**
+ * Create the line holding the DTD referenced by this XLIFFFile
+ * @return a string holding the DTD referenced by this XLIFFFile
+ */
+ private String getDTDLine() {
+ String sDTDTagStart = "<!DOCTYPE ";
+ String sDTDType = "xliff ";
+ String sDTDSource = "PUBLIC \"-//XLIFF//DTD XLIFF//EN\" \"http://www.oasis-open.org/committees/xliff/documents/xliff.dtd\">";// http://www.oasis-open.org/committees/xliff/documents/
+ String sDTSTagEnd = ">";
+ return sDTDTagStart + sDTDType + sDTDSource + '\n';
+ }
+
+ /**
+ * Create the beginning of the line holding the version of this XIFFFile
+ *
+ * @return a string with the beginning of the line holding the version of this XIFFFile
+ */
+ private String openVersionLine() {
+ return "<xliff version=\"1.0\">\n";
+ }
+ /**
+ * Create the ending of the line holding the version of this XIFFFile
+ *
+ * @return a string with the ending of the line holding the version of this XIFFFile
+ */
+ private String closeVersionLine() {
+ return "</xliff>";
+ }
+ /**
+ * Create the beginning of the line holding the file tag of this XIFFFile
+ *
+ * @return a string with the beginning of the file tag of this XIFFFile
+ */
+ private String openFileLine() {
+
+ String FileTagStart = "\t<file";
+ String FileDataType = " datatype=\"STAROFFICE\"";
+ String FileDate = " date=\"" + this.data.get("TimeStamp") + "\"";
+ String FileOriginal = " original=\"" + this.data.get("SourceFile")
+ + "\"";
+ String FileSourceLanguage="";
+ String FileTargetLanguage="";
+ try {
+ FileSourceLanguage = " source-language=\""
+ + languageResolver.getRFCFromISO((String)this.data.get("SourceLanguageID")) + "\" ";
+ FileTargetLanguage = " target-language=\""
+ + languageResolver.getRFCFromISO((String)this.data.get("TargetLanguageID")) + "\" ";
+ } catch (LanguageResolvingException e) {
+ OutputHandler.out(e.getMessage());
+ }
+ String FileTagEnd = ">";
+ return FileTagStart + FileDataType + FileDate + FileOriginal
+ + FileSourceLanguage + FileTargetLanguage + FileTagEnd;
+
+ }
+ /**
+ * Create the ending of the line holding the file tag of this XIFFFile
+ *
+ * @return a string with the ending of the file tag of this XIFFFile
+ */
+ private String closeFileLine() {
+ return "\t</file>";
+ }
+ /**
+ * Create a String containing the header tag
+ * @return the String containing the header tag
+ */
+ private String getHeaderTag() {
+ return "<header></header>\n";
+ }
+ /**
+ * Create the begining of the line holding the body tag of this XIFFFile
+ *
+ * @return a string with the begining of the body tag of this XIFFFile
+ */
+ private String openBodyTag() {
+ return "\t\t<body>\n";
+ }
+ /**
+ * Create the ending of the line holding the body tag of this XIFFFile
+ *
+ * @return a string with the ending of the body tag of this XIFFFile
+ */
+ private String closeBodyTag() {
+ return "\t\t</body>";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.sun.star.tooling.converter.DataWriter#writeData(java.util.Map[])
+ */
+ protected void writeData(Map[] data) throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.sun.star.tooling.converter.DataWriter#getDataFrom(com.sun.star.tooling.converter.DataHandler)
+ */
+ protected void getDataFrom(DataHandler handler) { }
+
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/dtd/xliff.dtd b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/dtd/xliff.dtd
new file mode 100755
index 000000000000..91262ec28204
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/converter/dtd/xliff.dtd
@@ -0,0 +1,391 @@
+<!-- XLIFF
+
+Public Identifier: "-//XLIFF//DTD XLIFF//EN"
+
+History of modifications (latest first):
+
+Jul-14-2003 by YS: Added extype definition (was missing)
+Jan-28-2003 by YS: Implemented fixes for resname
+Jan-28-2002 by YS: Implemented fixes after OASIS TC spec revision
+May-15-2001 by YS: Add phase-name to <trans-unit> and <bin-unit>
+May-15-2001 by YS: Reverse id for <trans-unit> to required
+Apr-19-2001 by YS: Enda+JohnR last changes
+Apr-18-2001 by YS: Removed empty ATTLISTs
+Apr-12-2001 by YS: Changed target* to target+ in trans-match
+Apr-11-2001 by YS: Fixed DOCTYPE id
+Apr-10-2001 by YS: Synchronize from conference call
+Apr-05-2001 by YS: Synchronize with latest specs
+Apr-04-2001 by YS: Synchronize with latest specs
+Apr-03-2001 by YS: Added name in <prop-group>
+Apr-02-2001 by YS: Implemented JR fixes
+Mar-29-2001 by JC: fixes for xml:space and bin-unit
+Mar-28-2001 by YS: First draft version
+
+-->
+
+
+<!ENTITY % CodeContent "#PCDATA|sub" >
+<!ENTITY % TextContent "#PCDATA|g|bpt|ept|ph|it|mrk|x|bx|ex" >
+
+<!ENTITY lt "&#38;#60;" >
+<!ENTITY amp "&#38;#38;" >
+<!ENTITY gt "&#62;" >
+<!ENTITY apos "&#39;" >
+<!ENTITY quot "&#34;" >
+
+
+<!-- ***************************************************************** -->
+<!-- Structural Elements -->
+<!-- ***************************************************************** -->
+
+<!ELEMENT xliff (file)+ >
+<!ATTLIST xliff
+ version CDATA #FIXED "1.0"
+ xml:lang CDATA #IMPLIED
+>
+
+<!ELEMENT file (header,body) >
+<!ATTLIST file
+ original CDATA #REQUIRED
+ source-language CDATA #REQUIRED
+ datatype CDATA #REQUIRED
+ tool CDATA #IMPLIED
+ date CDATA #IMPLIED
+ xml:space (default|preserve) "default"
+ ts CDATA #IMPLIED
+ category CDATA #IMPLIED
+ target-language CDATA #IMPLIED
+ product-name CDATA #IMPLIED
+ product-version CDATA #IMPLIED
+ build-num CDATA #IMPLIED
+>
+<!-- tool default = "manual" -->
+
+
+<!ELEMENT header (skl?,phase-group?,(prop-group|glossary|reference|note|count-group)*) >
+
+<!ELEMENT skl (internal-file|external-file) >
+
+<!ELEMENT internal-file (#PCDATA) >
+<!ATTLIST internal-file
+ form CDATA #IMPLIED
+ crc NMTOKEN #IMPLIED
+>
+<!-- text|base64 (text is default) -->
+
+<!ELEMENT external-file EMPTY >
+<!ATTLIST external-file
+ href CDATA #REQUIRED
+ crc NMTOKEN #IMPLIED
+ uid NMTOKEN #IMPLIED
+>
+
+<!ELEMENT glossary (internal-file|external-file) >
+
+<!ELEMENT reference (internal-file|external-file) >
+
+<!ELEMENT note (#PCDATA) >
+<!ATTLIST note
+ xml:lang CDATA #IMPLIED
+ priority (1|2|3|4|5|6|7|8|9|10) "1"
+ from CDATA #IMPLIED
+>
+
+<!ELEMENT prop-group (prop)+ >
+<!ATTLIST prop-group
+ name CDATA #IMPLIED
+>
+
+<!ELEMENT prop (#PCDATA) >
+<!ATTLIST prop
+ prop-type CDATA #REQUIRED
+ xml:lang CDATA #IMPLIED
+>
+
+<!ELEMENT context-group (context)+ >
+<!ATTLIST context-group
+ name CDATA #REQUIRED
+ crc NMTOKEN #IMPLIED
+>
+
+<!-- Processing instructions related to <context-group>:
+
+<?xliff-show-context-group name='value' ?>
+
+Indicates that any <context-group> element with a name set to 'value' should be
+displayed to the end-user.
+
+-->
+
+<!ELEMENT context (#PCDATA) >
+<!ATTLIST context
+ context-type CDATA #REQUIRED
+ match-mandatory (yes|no) "no"
+ crc NMTOKEN #IMPLIED
+>
+
+<!-- Processing instructions related to <context>:
+
+<?xliff-show-context context-type='value' ?>
+
+Indicates that any <context> element with a context-type set to 'value' should
+be displayed to the end-user.
+
+-->
+
+<!ELEMENT phase-group (phase)+ >
+
+<!ELEMENT phase (note)* >
+<!ATTLIST phase
+ phase-name CDATA #REQUIRED
+ process-name CDATA #REQUIRED
+ company-name CDATA #IMPLIED
+ tool CDATA #IMPLIED
+ date CDATA #IMPLIED
+ job-id CDATA #IMPLIED
+ contact-name CDATA #IMPLIED
+ contact-email CDATA #IMPLIED
+ contact-phone CDATA #IMPLIED
+>
+
+<!ELEMENT count-group (count)* >
+<!ATTLIST count-group
+ name CDATA #REQUIRED
+>
+
+<!ELEMENT count (#PCDATA) >
+<!ATTLIST count
+ count-type CDATA #IMPLIED
+ unit CDATA #IMPLIED
+>
+
+<!ELEMENT body (group|trans-unit|bin-unit)* >
+
+<!ELEMENT group ((context-group*,count-group*,prop-group*,note*),(group|trans-unit|bin-unit)*)
+>
+<!ATTLIST group
+ id NMTOKEN #IMPLIED
+ datatype CDATA #IMPLIED
+ xml:space (default|preserve) "default"
+ ts CDATA #IMPLIED
+ restype CDATA #IMPLIED
+ resname CDATA #IMPLIED
+ extradata CDATA #IMPLIED
+ extype CDATA #IMPLIED
+ help-id NMTOKEN #IMPLIED
+ menu CDATA #IMPLIED
+ menu-option CDATA #IMPLIED
+ menu-name CDATA #IMPLIED
+ coord CDATA #IMPLIED
+ font CDATA #IMPLIED
+ css-style CDATA #IMPLIED
+ style NMTOKEN #IMPLIED
+ exstyle NMTOKEN #IMPLIED
+>
+
+<!ELEMENT trans-unit (source,target?,(count-group|note|context-group|prop-group|alt-trans)*) >
+<!ATTLIST trans-unit
+ id NMTOKEN #REQUIRED
+ approved (yes|no) #IMPLIED
+ translate (yes|no) "yes"
+ reformat (yes|no) "yes"
+ xml:space (default|preserve) "default"
+ datatype CDATA #IMPLIED
+ ts CDATA #IMPLIED
+ restype CDATA #IMPLIED
+ resname CDATA #IMPLIED
+ extradata CDATA #IMPLIED
+ extype CDATA #IMPLIED
+ help-id NMTOKEN #IMPLIED
+ menu CDATA #IMPLIED
+ menu-option CDATA #IMPLIED
+ menu-name CDATA #IMPLIED
+ coord CDATA #IMPLIED
+ font CDATA #IMPLIED
+ css-style CDATA #IMPLIED
+ style NMTOKEN #IMPLIED
+ exstyle NMTOKEN #IMPLIED
+ size-unit CDATA #IMPLIED
+ maxwidth NMTOKEN #IMPLIED
+ minwidth NMTOKEN #IMPLIED
+ maxheight NMTOKEN #IMPLIED
+ minheight NMTOKEN #IMPLIED
+ maxbytes NMTOKEN #IMPLIED
+ minbytes NMTOKEN #IMPLIED
+ charclass CDATA #IMPLIED
+ phase-name CDATA #IMPLIED
+>
+<!-- size-unit: char|byte|pixel|glyph|dlgunit default='pixel' -->
+
+<!ELEMENT source (%TextContent;)* >
+<!ATTLIST source
+ xml:lang CDATA #IMPLIED
+ ts CDATA #IMPLIED
+>
+<!-- coord = "x;y;cx;cy"
+ font= "fontname[;size[;weight]]"
+-->
+
+<!ELEMENT target (%TextContent;)* >
+<!ATTLIST target
+ state NMTOKEN #IMPLIED
+ phase-name NMTOKEN #IMPLIED
+ xml:lang CDATA #IMPLIED
+ ts CDATA #IMPLIED
+ restype CDATA #IMPLIED
+ resname CDATA #IMPLIED
+ coord CDATA #IMPLIED
+ font CDATA #IMPLIED
+ css-style CDATA #IMPLIED
+ style NMTOKEN #IMPLIED
+ exstyle NMTOKEN #IMPLIED
+>
+
+<!ELEMENT alt-trans (source?,target+,(note|context-group|prop-group)*) >
+<!ATTLIST alt-trans
+ match-quality CDATA #IMPLIED
+ tool CDATA #IMPLIED
+ crc NMTOKEN #IMPLIED
+ xml:lang CDATA #IMPLIED
+ origin CDATA #IMPLIED
+ datatype CDATA #IMPLIED
+ xml:space (default|preserve) "default"
+ ts CDATA #IMPLIED
+ restype CDATA #IMPLIED
+ resname CDATA #IMPLIED
+ extradata CDATA #IMPLIED
+ extype CDATA #IMPLIED
+ help-id NMTOKEN #IMPLIED
+ menu CDATA #IMPLIED
+ menu-option CDATA #IMPLIED
+ menu-name CDATA #IMPLIED
+ coord CDATA #IMPLIED
+ font CDATA #IMPLIED
+ css-style CDATA #IMPLIED
+ style NMTOKEN #IMPLIED
+ exstyle NMTOKEN #IMPLIED
+>
+
+
+<!ELEMENT bin-unit (bin-source,bin-target?,(note|context-group|prop-group|trans-unit)*) >
+<!ATTLIST bin-unit
+ id NMTOKEN #REQUIRED
+ mime-type NMTOKEN #REQUIRED
+ approved (yes|no) #IMPLIED
+ translate (yes|no) "yes"
+ reformat (yes|no) "yes"
+ ts CDATA #IMPLIED
+ restype CDATA #IMPLIED
+ resname CDATA #IMPLIED
+ phase-name CDATA #IMPLIED
+>
+
+<!ELEMENT bin-source (internal-file|external-file) >
+<!ATTLIST bin-source
+ ts CDATA #IMPLIED
+>
+
+<!ELEMENT bin-target (internal-file|external-file) >
+<!ATTLIST bin-target
+ mime-type NMTOKEN #IMPLIED
+ ts CDATA #IMPLIED
+ state NMTOKEN #IMPLIED
+ phase-name NMTOKEN #IMPLIED
+ restype CDATA #IMPLIED
+ resname CDATA #IMPLIED
+>
+
+
+
+<!-- ***************************************************************** -->
+<!-- In-Line Elements -->
+<!-- ***************************************************************** -->
+
+<!ELEMENT g (%TextContent;)* >
+<!ATTLIST g
+ id CDATA #REQUIRED
+ ctype CDATA #IMPLIED
+ clone (yes|no) "yes"
+ ts CDATA #IMPLIED
+>
+
+<!ELEMENT x EMPTY >
+<!ATTLIST x
+ id CDATA #REQUIRED
+ ctype CDATA #IMPLIED
+ clone (yes|no) "yes"
+ ts CDATA #IMPLIED
+>
+
+<!ELEMENT bx EMPTY >
+<!ATTLIST bx
+ id CDATA #REQUIRED
+ rid NMTOKEN #IMPLIED
+ ctype CDATA #IMPLIED
+ clone (yes|no) "yes"
+ ts CDATA #IMPLIED
+>
+
+<!ELEMENT ex EMPTY >
+<!ATTLIST ex
+ id CDATA #REQUIRED
+ rid NMTOKEN #IMPLIED
+ ts CDATA #IMPLIED
+>
+
+<!ELEMENT ph (%CodeContent;)* >
+<!ATTLIST ph
+ id CDATA #REQUIRED
+ ctype CDATA #IMPLIED
+ ts CDATA #IMPLIED
+ crc NMTOKEN #IMPLIED
+ assoc CDATA #IMPLIED
+>
+
+<!ELEMENT bpt (%CodeContent;)* >
+<!ATTLIST bpt
+ id CDATA #REQUIRED
+ rid NMTOKEN #IMPLIED
+ ctype CDATA #IMPLIED
+ ts CDATA #IMPLIED
+ crc NMTOKEN #IMPLIED
+>
+
+<!ELEMENT ept (%CodeContent;)* >
+<!ATTLIST ept
+ id CDATA #REQUIRED
+ rid NMTOKEN #IMPLIED
+ ts CDATA #IMPLIED
+ crc NMTOKEN #IMPLIED
+>
+
+<!ELEMENT it (%CodeContent;)* >
+<!ATTLIST it
+ id CDATA #REQUIRED
+ pos (open|close) #REQUIRED
+ rid NMTOKEN #IMPLIED
+ ctype CDATA #IMPLIED
+ ts CDATA #IMPLIED
+ crc NMTOKEN #IMPLIED
+>
+
+<!ELEMENT mrk (%TextContent;)* >
+<!ATTLIST mrk
+ mtype CDATA #REQUIRED
+ mid NMTOKEN #IMPLIED
+ comment CDATA #IMPLIED
+ ts CDATA #IMPLIED
+>
+
+<!ELEMENT sub (%TextContent;)* >
+<!ATTLIST sub
+ datatype CDATA #IMPLIED
+ ctype CDATA #IMPLIED
+>
+
+
+
+<!-- ***** End of DTD ************************************************ -->
+
+
+
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/languageResolver/LanguageResolver.java b/l10ntools/java/l10nconv/java/com/sun/star/tooling/languageResolver/LanguageResolver.java
new file mode 100755
index 000000000000..62ff008156ab
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/languageResolver/LanguageResolver.java
@@ -0,0 +1,201 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: LanguageResolver.java,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+/*
+ * Created on 2005
+ * by Christian Schmidt
+ */
+package com.sun.star.tooling.languageResolver;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.ListIterator;
+
+/**
+ * Translate language codes into another format
+ * between ISO, RFC3066 and numeric
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+public class LanguageResolver {
+ private final static int ISO =2;
+ private final static int LANGID =0;
+ private final static int LANGNAME =1;
+ private final static int RFC3066 =3;
+
+ ArrayList languages=new ArrayList();
+
+// public static void main(String[] args){
+// try {
+// LanguageResolver lr=new LanguageResolver();
+// } catch (IOException e) {
+// //
+// e.printStackTrace();
+// }
+// }
+
+ /**
+ * Create a new Instance of LanguageResolver
+ *
+ * @throws IOException
+ */
+ public LanguageResolver() throws IOException{
+ String lang = "com/sun/star/tooling/languageResolver/lang.map";
+ ClassLoader cl = this.getClass().getClassLoader();
+ InputStream in = cl.getResourceAsStream(lang);
+ BufferedReader languageTable= new BufferedReader(new InputStreamReader(in));
+
+ String line;
+
+ while((line=(languageTable.readLine()))!=null){
+ languages.add(line.split(","));
+ }
+ }
+ /**
+ * Get the numeric value of the given ISO Language Code
+ *
+ * @param isoCode the ISO Language Code to find
+ * @return numeric value of the given isoCode
+ * @throws LanguageResolvingException if the Language ISO Code is not known
+ */
+ public String getNrFromISO(String isoCode) throws LanguageResolvingException{
+ if("".equals(isoCode)) return "";
+ ListIterator iter=languages.listIterator();
+ String[] line=new String[5];
+ while(isoCode!="" && iter.hasNext()){
+ line=(String[]) iter.next();
+ if(line[ISO].equals(isoCode)) return line[LANGID];
+ }
+ throw new LanguageResolvingException("Can not find ISO Code: "+isoCode );
+
+ }
+
+ /**
+ * Get the ISO Language Code corresponding with the given Language ID
+ *
+ * @param ID the numeric language id to find
+ * @return the ISO Language Code corresponding with the given Language ID
+ * @throws LanguageResolvingException if the Language ID is not known
+ */
+ public String getISOfromNr(String ID) throws LanguageResolvingException{
+ if("".equals(ID)) return "";
+ ListIterator iter=languages.listIterator();
+ String[] line=new String[5];
+ while(iter.hasNext()){
+ line=(String[]) iter.next();
+ if(line[LANGID].equals(ID)) return line[ISO];
+ }
+ throw new LanguageResolvingException("Can not find Language Id: "+ID );
+ }
+
+ /**
+ * Get the RFC3066 value of the given ISO Language Code
+ *
+ * @param isoCode the ISO Language Code to find
+ * @return RFC3066 value of the given isoCode
+ * @throws LanguageResolvingException if the Language ISO Code is not known
+ */
+ public String getRFCFromISO(String isoCode) throws LanguageResolvingException{
+ if("".equals(isoCode)) return "";
+ ListIterator iter=languages.listIterator();
+ String[] line=new String[5];
+ while(iter.hasNext()){
+ line=(String[]) iter.next();
+ if(line[ISO].equals(isoCode)) return line[RFC3066];
+ }
+ throw new LanguageResolvingException("Can not find ISO Code: "+isoCode );
+ }
+
+ /**
+ * Get the ISO Language Code corresponding with the given RFC3066 code
+ *
+ * @param RFC RFC3066 language id to find
+ * @return the ISO Language Code corresponding with the given RFC3066 code
+ * @throws LanguageResolvingException if the RFC3066 code is not known
+ */
+ public String getISOFromRFC(String RFC) throws LanguageResolvingException{
+ if("".equals(RFC)) return "";
+ ListIterator iter=languages.listIterator();
+ String[] line=new String[5];
+ while(iter.hasNext()){
+ line=(String[]) iter.next();
+ if(line[RFC3066].equals(RFC)) return line[ISO];
+ }
+ throw new LanguageResolvingException("Can not find Language Id: "+RFC );
+ }
+
+
+ /**
+ * This Exception is thrown if a Language Identfier is unknown
+ *
+ * @author Christian Schmidt 2005
+ *
+ */
+ public class LanguageResolvingException extends Exception {
+
+ /**
+ *
+ */
+ public LanguageResolvingException() {
+ super();
+ //
+ }
+
+ /**
+ * @param arg0
+ */
+ public LanguageResolvingException(String arg0) {
+ super(arg0);
+ //
+ }
+
+ /**
+ * @param arg0
+ * @param arg1
+ */
+ public LanguageResolvingException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ //
+ }
+
+ /**
+ * @param arg0
+ */
+ public LanguageResolvingException(Throwable arg0) {
+ super(arg0);
+ //
+ }
+
+ }
+
+}
diff --git a/l10ntools/java/l10nconv/java/com/sun/star/tooling/languageResolver/lang.map b/l10ntools/java/l10nconv/java/com/sun/star/tooling/languageResolver/lang.map
new file mode 100755
index 000000000000..a43e8f5e0218
--- /dev/null
+++ b/l10ntools/java/l10nconv/java/com/sun/star/tooling/languageResolver/lang.map
@@ -0,0 +1,41 @@
+1,English,en-US,en-US,1033
+3,Portuguese,pt,pt-PT,2070
+30,Greek,el,el-GR,1032
+33,French,fr,fr-FR,1036
+35,Finnish,fi,fi-FI,1035
+39,Italian,it,it-IT,1040
+43,Slowak,sk,sk-SK,1051
+46,Swedish,sv,sv-SE,1053
+48,Polish,pl,pl-PL,1045
+55,Portuguese (Brasil),pt-BR,pt-BR,2070
+82,Korean,ko,ko-KR,1042
+88,Chinese (traditional),zh-TW,zh-TW,1028
+96,Arabic,ar,,1025
+97,Hebrew,he,he-IL,1037
+7,Russian,ru,ru-RU,1049
+31,Dutch,nl,nl-NL,1043
+34,Spanish,es,es-ES,1034
+36,Hungarian,hu,hu-HU,1038
+42,Czech,cs,cs-CZ,1029
+45,Danish,da,da-DK,1030
+47,Norwegian (Bokmal),nb,nb-NB,1044
+49,German,de,de-DE,1031
+81,Japanese,ja,ja-JP,1041
+86,Chinese (simple),zh-CN,zh-CN,2052
+90,Turkish,tr,tr-TR,1055
+37,Catalan,ca,,
+66,Thai,th,th-TH,
+91,Hindi,hi-IN,hi-IN,
+77,Estonian,et,et,
+50,Slovenian,sl,sl,
+79,Norwegian Nynorsk,nn,nn-NN,
+53,Welsh,cy,cy,
+27,Afrikaans,af,af-ZA,
+38,Galician,gl-ES,gl-ES,
+58,Lithuanian,lt,lt-LT,
+29,Tswana,tn,tn-TN,
+76,Khmer ( Cambodia ),km,km,
+26,Northern Sotho,ns,ns-ZA,
+28,Zulu,zu,zu-ZA,
+10,Basque,eu,eu-ES,
+93,Kannada,kn,kn-KN, \ No newline at end of file
diff --git a/l10ntools/java/l10nconv/makefile.mk b/l10ntools/java/l10nconv/makefile.mk
new file mode 100755
index 000000000000..2be2eb391ced
--- /dev/null
+++ b/l10ntools/java/l10nconv/makefile.mk
@@ -0,0 +1,39 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=../..
+PRJNAME=l10ntools
+TARGET=converter
+
+.INCLUDE : ant.mk
+
+ALLTAR : ANTBUILD
+
diff --git a/l10ntools/java/receditor/build.xml b/l10ntools/java/receditor/build.xml
new file mode 100755
index 000000000000..34f02128f034
--- /dev/null
+++ b/l10ntools/java/receditor/build.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: build.xml,v $
+
+ $Revision: 1.3 $
+
+ This file is part of OpenOffice.org.
+
+ OpenOffice.org is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 3
+ only, as published by the Free Software Foundation.
+
+ OpenOffice.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License version 3 for more details
+ (a copy is included in the LICENSE file that accompanied this code).
+
+ You should have received a copy of the GNU Lesser General Public License
+ version 3 along with OpenOffice.org. If not, see
+ <http://www.openoffice.org/license.html>
+ for a copy of the LGPLv3 License.
+
+-->
+<project name="receditor" default="main" basedir=".">
+
+ <!-- ================================================================= -->
+ <!-- settings -->
+ <!-- ================================================================= -->
+
+ <!-- name of this sub target used in recursive builds -->
+ <property name="target" value="receditor"/>
+
+ <!-- name of jar file created, without .jar extension -->
+ <property name="jarname" value="receditor"/>
+
+ <!-- relative path to project directory -->
+ <property name="prj" value="."/>
+
+ <!-- build output directory -->
+ <property name="out" value="build"/>
+
+ <!-- build directories -->
+ <property name="build.dir" value="${out}"/>
+ <property name="build.class" value="${build.dir}/class/receditor"/>
+ <property name="build.misc" value="${build.dir}/misc/receditor"/>
+
+ <!-- start of java source code package structure -->
+ <property name="java.dir" value="java"/>
+
+ <!-- define how to handle CLASSPATH environment -->
+ <property name="build.sysclasspath" value="ignore"/>
+
+ <!-- classpath settings for compile and javadoc tasks -->
+ <path id="classpath">
+ <pathelement location="."/>
+ <pathelement location="${build.class}"/>
+ </path>
+
+ <!-- name to display in documentation -->
+ <!-- <property name="docname" value="l10n converter"/> -->
+
+ <!-- set "modern" java compiler -->
+ <property name="build.compiler" value="modern"/>
+
+ <!-- set wether we want to compile with debug information -->
+ <property name="debug" value="on"/>
+
+ <!-- set wether we want to compile with optimisation -->
+ <property name="optimize" value="off"/>
+
+ <!-- set wether we want to compile with or without deprecation -->
+ <property name="deprecation" value="on"/>
+
+ <target name="info">
+ <echo message="--------------------"/>
+ <echo message="${target}"/>
+ <echo message="--------------------"/>
+ </target>
+
+ <!-- ================================================================= -->
+ <!-- custom targets -->
+ <!-- ================================================================= -->
+
+ <!-- the main target, called in recursive builds -->
+ <target name="main" depends="info,prepare,compile,jar"/>
+
+ <!-- prepare output directories -->
+ <target name="prepare">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${build.class}"/>
+ <mkdir dir="${build.misc}"/>
+ </target>
+
+
+ <target name="res" depends="prepare">
+ <copy todir="${build.class}">
+ <fileset dir="${java.dir}">
+ <include name="**/*.properties"/>
+ <include name="**/*.css"/>
+ <include name="**/*.dtd"/>
+ <include name="**/*.form"/>
+ <include name="**/*.gif "/>
+ <include name="**/*.htm"/>
+ <include name="**/*.html"/>
+ <include name="**/*.js"/>
+ <include name="**/*.mod"/>
+ <include name="**/*.sql"/>
+ <include name="**/*.xml"/>
+ <include name="**/*.xsl"/>
+ <include name="**/*.map"/>
+
+ </fileset>
+ </copy>
+ </target>
+
+
+ <target name="compile" depends="prepare,res">
+ <javac destdir="${build.class}"
+ debug="${debug}"
+ deprecation="${deprication}"
+ optimize="${optimize}"
+ classpathref="classpath">
+ <src path="${java.dir}"/>
+ <include name="**/*.java"/>
+ </javac>
+ </target>
+
+ <!-- clean up -->
+ <target name="clean" depends="prepare">
+ <delete includeEmptyDirs="true">
+ <fileset dir="${build.class}">
+ <patternset>
+ <include name="${package}/**/*.class"/>
+ </patternset>
+ </fileset>
+ </delete>
+ </target>
+
+ <!-- create jar file -->
+ <target name="jar" depends="prepare,compile" if="build.class">
+ <jar jarfile="${build.class}/${jarname}.jar"
+ basedir="${build.class}"
+ manifest="${jarname}.MF">
+ <include name="**/*.class"/>
+ <include name="**/*.properties"/>
+ <include name="**/*.css"/>
+ <include name="**/*.dtd"/>
+ <include name="**/*.form"/>
+ <include name="**/*.gif "/>
+ <include name="**/*.htm"/>
+ <include name="**/*.html"/>
+ <include name="**/*.js"/>
+ <include name="**/*.mod"/>
+ <include name="**/*.sql"/>
+ <include name="**/*.xml"/>
+ <include name="**/*.xsl"/>
+ <include name="**/*.map"/>
+ </jar>
+ </target>
+
+ <target name="test" depends="prepare">
+ </target>
+
+</project>
+
diff --git a/l10ntools/java/receditor/java/transex3/controller/EditorController.java b/l10ntools/java/receditor/java/transex3/controller/EditorController.java
new file mode 100644
index 000000000000..38462d665304
--- /dev/null
+++ b/l10ntools/java/receditor/java/transex3/controller/EditorController.java
@@ -0,0 +1,334 @@
+package transex3.controller;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.*;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.Runtime;
+import java.util.*;
+
+import javax.swing.ListSelectionModel;
+import javax.swing.WindowConstants;
+import javax.swing.event.*;
+
+import transex3.model.*;
+
+import java.io.*;
+import javax.swing.*;
+//import transex3.model.*;
+public class EditorController {
+ public final String[] RESTYPES = { ".src",".hrc",".xcu",".xrm",".xhp" };
+ public final String RECFILE = ".recommand";
+ // Editor View
+ static transex3.view.Editor aEditor = null;
+ // Editor Model
+ static Vector sdfstrings = new Vector();
+ static HashMap hashedsdfstrings = new HashMap();
+ int oldindex = 0;
+ //HashMap hashedfilenames = new HashMap();
+ // Search for source Strings
+ public String fetchSourceStrings( String rootdir ){
+
+ //String outputfile = "h:\\workspace\\recommandEditor\\null2";
+ File tempfile = null;
+
+ try {
+ tempfile = File.createTempFile( "receditor" , "tmp" );
+ } catch (IOException e1) {
+ // TODO Auto-generated catch block
+ System.err.println("Can not create temp file\n");
+ e1.printStackTrace();
+ }
+
+ String outputfile = tempfile.getAbsolutePath();
+ try
+ {
+ //System.out.println("localize_sl -QQ -skip_links -e -l en-US -f "+outputfile+" -d "+rootdir);
+ System.out.println("localize_sl -QQ -skip_links -e -l en-US -f "+outputfile );
+ java.lang.Process aProc = Runtime.getRuntime().exec("localize_sl -QQ -skip_links -e -l en-US -f "+outputfile);
+
+ //java.lang.Process aProc = Runtime.getRuntime().exec("localize_sl -QQ -e -l en-US -f "+outputfile+" -d "+rootdir);
+ BufferedReader aBR = new BufferedReader( new InputStreamReader( aProc.getInputStream() ) );
+ String line = aBR.readLine();
+ while( line != null && line.length() > 0 ){
+ //System.out.print( line );
+ line = aBR.readLine();
+ }
+
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return outputfile;
+ }
+ // Search for recommand files
+ public void findRecommandFiles( File rootdir , Vector list ){
+ System.out.print(".");
+ System.out.flush();
+ File[] aFileArray = rootdir.listFiles();
+ if( aFileArray != null ){
+ for( int cnt = 0; aFileArray.length > cnt ; cnt++ ){
+ if( aFileArray[ cnt ].isDirectory() && !aFileArray[ cnt ].getAbsolutePath().endsWith(".lnk") )
+ findRecommandFiles( aFileArray[ cnt ] , list);
+ else if( aFileArray[ cnt ].isFile() && isRecommandFile( aFileArray[ cnt ] ) )
+ list.add( aFileArray[ cnt ]);
+ }
+ }
+ }
+ private boolean isResourceType( File aFile ){
+ String filename = aFile.getName();
+ boolean isResType = false;
+ for(int cnt = 0; cnt < RESTYPES.length ; cnt++){
+ if( filename.endsWith( RESTYPES[ cnt ] ) )
+ isResType = true;
+ }
+ return isResType;
+ }
+ private boolean isRecommandFile( File aFile ){
+ return aFile.getName().endsWith( RECFILE );
+ }
+ public void clearAllRows( JTable aTable ){
+ for ( int n = 0; n < aTable.getRowCount() ; n++ ){
+ aTable.setValueAt( null , n , 0 );
+ aTable.setValueAt( null , n , 1 );
+ aTable.setValueAt( null , n , 2 );
+ aTable.setValueAt( null , n , 3 );
+ aTable.setValueAt( null , n , 4 );
+ }
+ }
+ // Add all data to view
+ void updateData(){
+ JTable recTable =transex3.controller.EditorController.aEditor.getRectable();
+
+ SdfString aSdfString = (SdfString) sdfstrings.get( oldindex );
+ Vector newStrings = new Vector();
+ for ( int n = 1; n < recTable.getRowCount() ; n++ ){
+ String lang = (String) recTable.getValueAt(n , 0 );
+ String text = (String) recTable.getValueAt(n , 1 );
+ String htext = (String) recTable.getValueAt(n , 2 );
+ String qhtext = (String) recTable.getValueAt(n , 3 );
+ String ttext = (String) recTable.getValueAt(n , 4 );
+ if( lang != null && text != null ){
+ //System.out.println("Data "+ lang + " " + text );
+ SdfEntity aSdfEntity = new SdfEntity();
+ aSdfEntity.setLangid( lang );
+ aSdfEntity.setText( text );
+ aSdfEntity.setHelptext( htext );
+ aSdfEntity.setQuickhelptext( qhtext );
+ aSdfEntity.setTitle( ttext );
+ newStrings.add( aSdfEntity );
+ aSdfString.setLanguageStrings( newStrings );
+ }
+ }
+ }
+
+ public void initView(){
+ Object[][] sourceStringData = new Object[ sdfstrings.size() ][ 4 ];
+ Object[][] firstData = new Object[100][5];
+ // Set the files
+ Iterator aIter = sdfstrings.iterator();
+ int counter = 0;
+ while( aIter.hasNext() ){
+ SdfString aSdfString = (SdfString) aIter.next();
+ sourceStringData[ counter ][ 0 ] = aSdfString.getSourceString().getProject()+"\\"+aSdfString.getSourceString().getSource_file();
+ sourceStringData[ counter ][ 1 ] = aSdfString.getSourceString().getGid();
+ sourceStringData[ counter ][ 2 ] = aSdfString.getSourceString().getLid();
+ sourceStringData[ counter ][ 3 ] = aSdfString.getSourceString().getText();
+ if( counter == 0 ){
+ firstData[ 0 ][ 0 ] = "en-US";
+ firstData[ 0 ][ 1 ] = aSdfString.getSourceString().getText();
+ firstData[ 0 ][ 2 ] = aSdfString.getSourceString().getHelptext();
+ firstData[ 0 ][ 3 ] = aSdfString.getSourceString().getQuickhelptext();
+ firstData[ 0 ][ 4 ] = aSdfString.getSourceString().getTitle();
+ aSdfString = (SdfString) sdfstrings.get( 0 );
+ Vector values = aSdfString.getLanguageStrings();
+ for( int n = 0; n < values.size() ; n++ )
+ {
+ SdfEntity aEntity = (SdfEntity) values.get( n );
+ firstData[ n+1 ][ 0 ] = aEntity.getLangid();
+ firstData[ n+1 ][ 1 ] = aEntity.getText();
+ firstData[ n+1 ][ 2 ] = aEntity.getHelptext();
+ firstData[ n+1 ][ 3 ] = aEntity.getQuickhelptext();
+ firstData[ n+1 ][ 4 ] = aEntity.getTitle();
+ }
+ }
+ counter++;
+ }
+ // Set the source srtings
+
+
+ //aEditor = new transex3.view.Editor( sourceStringData , filedata.toArray() );
+ aEditor = new transex3.view.Editor( sourceStringData , firstData );
+
+ aEditor.setBounds(100,100,800,900);
+ aEditor.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
+ aEditor.setVisible(true);
+ aEditor.repaint();
+ aEditor.addWindowListener( new WindowAdapter(){
+ public void windowClosed(WindowEvent e ){
+ System.exit( 0 );
+ }
+ });
+
+ aEditor.getMiExit().addActionListener( new ActionListener(){
+ public void actionPerformed( ActionEvent e ){
+ System.exit( 0 );
+ }
+ });
+
+ aEditor.getMiSave().addActionListener( new ActionListener(){
+ public void actionPerformed( ActionEvent e ){
+ Iterator aIter = sdfstrings.iterator();
+ String lastFile="";
+ while( aIter.hasNext() )
+ {
+ SdfString aSdfString = (SdfString )aIter.next();
+ if( aSdfString.getFileId().compareTo( lastFile ) != 0 ){
+ //aSdfString.removeFile();
+ }
+ aSdfString.writeString();
+ lastFile = aSdfString.getFileId();
+ }
+ }
+ });
+
+ //aEditor.getRectable().putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
+ aEditor.getRectable().addFocusListener( new FocusListener(){
+ public void focusLost(FocusEvent e){
+ //super.focusLost( e );
+ //System.out.println("focus lost");
+ JTable aTable = aEditor.getRectable();
+ if( aTable.getSelectedRow() != -1 && aTable.getSelectedColumn() != -1 )
+ aTable.getCellEditor( aTable.getSelectedRow(), aTable.getSelectedColumn() ).stopCellEditing();
+ updateData();
+ }
+ public void focusGained( FocusEvent e){
+ //super.focusGained( e );
+ //System.out.println("focus gained");
+ }
+ });
+ //setDefaultEditor(Object.class, new transex3.view.FocusCellEditor(new JTextField()));
+
+ aEditor.getRectable().getModel().addTableModelListener( new TableModelListener() {
+ public void tableChanged( TableModelEvent e ){
+ //System.out.println( e );
+ }});
+
+
+ aEditor.getRectable().getSelectionModel().addListSelectionListener( new ListSelectionListener(){
+ public void valueChanged( ListSelectionEvent e ){
+ JTable aTable = aEditor.getRectable();
+ //if( aTable.getSelectedRow() != -1 && aTable.getSelectedColumn() != -1 )
+ //aTable.getCellEditor( aTable.getSelectedRow(), aTable.getSelectedColumn() ).stopCellEditing();
+
+ updateData();
+ }
+ });
+
+ aEditor.getTable().setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+ aEditor.getTable().getSelectionModel().addListSelectionListener( new ListSelectionListener(){
+ public void valueChanged( ListSelectionEvent e ){
+ //System.out.println("Selected = " +e.getFirstIndex()+"\n");
+ JTable table =transex3.controller.EditorController.aEditor.getTable();
+ JTable recTable =transex3.controller.EditorController.aEditor.getRectable();
+ SdfString aSdfString;
+ JTable aTable = aEditor.getRectable();
+ if( aTable.getSelectedRow() != -1 && aTable.getSelectedColumn() != -1 )
+ aTable.getCellEditor( aTable.getSelectedRow(), aTable.getSelectedColumn() ).stopCellEditing();
+
+ updateData();
+ clearAllRows( recTable );
+
+ aSdfString = (SdfString) sdfstrings.get( table.getSelectedRow() );
+ recTable.setValueAt( "en-US" , 0, 0 );
+ recTable.setValueAt( aSdfString.getSourceString().getText() , 0, 1 );
+ recTable.setValueAt( aSdfString.getSourceString().getHelptext() , 0, 2 );
+ recTable.setValueAt( aSdfString.getSourceString().getQuickhelptext() , 0, 3 );
+ recTable.setValueAt( aSdfString.getSourceString().getTitle() , 0, 4 );
+ Vector values = aSdfString.getLanguageStrings();
+ for( int n = 0; n < values.size() ; n++ )
+ {
+ SdfEntity aEntity = (SdfEntity) values.get( n );
+ recTable.setValueAt( aEntity.getLangid() , n+1 , 0 );
+ recTable.setValueAt( aEntity.getText() , n+1 , 1 );
+ recTable.setValueAt( aEntity.getHelptext() , n+1 , 2 );
+ recTable.setValueAt( aEntity.getQuickhelptext() , n+1 , 3 );
+ recTable.setValueAt( aEntity.getTitle() , n+1 , 4 );
+ }
+ oldindex = table.getSelectedRow();
+ }
+ });
+ //System.out.println("initView successfully");
+ }
+ public void initInitialStrings(){
+ String rootdir = java.lang.System.getProperty("SOLARSRC");
+ String sourcestringsfile = null;
+ Vector recList = new Vector();
+ sourcestringsfile = fetchSourceStrings( rootdir );
+ //findRecommandFiles( new File( rootdir ) , recList );
+ readStrings( sourcestringsfile , recList );
+ File sfile = new File ( sourcestringsfile );
+ sfile.delete();
+ initView();
+ aEditor.repaint();
+ }
+ // Connect recommand strings with source strings
+ public void readStrings( String sourcefiles , Vector recfiles ) {
+ BufferedReader aBR = null;
+ try {
+ //System.out.println("DBG: sourcefiles = " +sourcefiles);
+ aBR = new BufferedReader( new FileReader( sourcefiles ) );
+ String current = aBR.readLine();
+ SdfString aSdfString = null;
+ SdfEntity aSdfEntity = null;
+ while( current != null ){
+ aSdfEntity = new SdfEntity();
+ aSdfEntity.setProperties( current );
+ aSdfString = new SdfString();
+ aSdfString.addSourceString( aSdfEntity );
+ hashedsdfstrings.put( aSdfString.getId() , aSdfString );
+ //System.out.println("Put ID '"+aSdfString.getId()+"'");
+ sdfstrings.add( aSdfString );
+ current = aBR.readLine();
+
+ }
+ Iterator aIter=recfiles.iterator();
+ File aFile;
+ BufferedReader aBR2 = null;
+ //System.out.println("Connecting strings");
+ while( aIter.hasNext() ){
+ aFile = (File) aIter.next();
+ aBR2 = new BufferedReader( new FileReader( aFile ) ) ;
+ String current2 = aBR2.readLine();
+
+ while ( current2 != null ){
+ SdfEntity aEntity = new SdfEntity();
+ aEntity.setProperties( current2 );
+
+ if( hashedsdfstrings.containsKey( aEntity.getId() ) )
+ {
+ aSdfString = (SdfString) hashedsdfstrings.get( aEntity.getId() );
+ aSdfString.addLanguageString( aEntity );
+ }
+ else
+ {
+ System.out.println("DBG: Can't find source string '"+aEntity.getId()+"'" );
+ }
+ current2 = aBR2.readLine();
+ }
+ }
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch ( IOException e){
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/l10ntools/java/receditor/java/transex3/controller/Main.java b/l10ntools/java/receditor/java/transex3/controller/Main.java
new file mode 100644
index 000000000000..e8dd06ce9f85
--- /dev/null
+++ b/l10ntools/java/receditor/java/transex3/controller/Main.java
@@ -0,0 +1,10 @@
+package transex3.controller;
+
+public class Main {
+
+ public static void main( String args[] ){
+ EditorController aEditor = new EditorController();
+ aEditor.initInitialStrings();
+ }
+}
+
diff --git a/l10ntools/java/receditor/java/transex3/model/ResourceFile.java b/l10ntools/java/receditor/java/transex3/model/ResourceFile.java
new file mode 100644
index 000000000000..51fabb3a4b7a
--- /dev/null
+++ b/l10ntools/java/receditor/java/transex3/model/ResourceFile.java
@@ -0,0 +1,77 @@
+package transex3.model;
+
+import java.util.*;
+
+public class ResourceFile {
+ Vector sdfStrings = new Vector();
+ HashMap sdfHashMap = new HashMap();
+ String filepathid = null;
+ String modulename = null;
+ String filename = null;
+
+
+ public String getModuleName(){
+ return modulename;
+ }
+ public String getFilePath(){
+ return filepathid;
+ }
+ public String getFileName(){
+ return filename;
+ }
+/* public List readSoureStrings( java.io.File aSdfFile ){
+ List sdfList=null;
+ return sdfList;
+ };*/
+ public void addString( SdfString aSdfstring ){
+ sdfStrings.add( aSdfstring );
+ sdfHashMap.put( aSdfstring.getFileId() , aSdfstring );
+ if( filepathid == null )
+ filepathid = aSdfstring.getFilePath();
+ if( modulename == null )
+ modulename = aSdfstring.getModuleName();
+ if( filename == null )
+ filename = aSdfstring.getFileName();
+ }
+
+
+ public void ParseString( String aSourceString ){
+ //sourceString = new SdfEntity();
+ SdfEntity aSdfEntity = new SdfEntity();
+ aSdfEntity.setProperties( aSourceString );
+ SdfString sdfstring = null;
+ if( sdfHashMap.containsKey( aSdfEntity.getFileId() ) ){
+ sdfstring = (SdfString) sdfHashMap.get( aSdfEntity.getFileId() );
+ }
+ else
+ {
+ sdfstring = new SdfString();
+ addString( sdfstring );
+ }
+ sdfstring.addLanguageString( aSdfEntity );
+
+
+ }
+ /*public void ParseSdfFile( java.util.Vector aSdfList ){
+ ListIterator aLI = aSdfList.listIterator();
+ String current;
+ String[] splitted;
+ SdfEntity aSdfEntity;
+ SdfString aSdfString = new SdfString();
+ while( aLI.hasNext() ){
+ aSdfEntity = new SdfEntity();
+ aSdfEntity.setProperties( (String) aLI.next() );
+ SdfString aString;
+
+ if( sdfHashMap.containsKey( aSdfEntity.getFileId() ) )
+ aString = (SdfString) sdfHashMap.get( aSdfEntity.getFileId() );
+ else
+ {
+ aString = new SdfString();
+ addString( aString );
+ }
+ aString.addLanguageString( aSdfEntity );
+ }
+
+ }*/
+}
diff --git a/l10ntools/java/receditor/java/transex3/model/SdfEntity.java b/l10ntools/java/receditor/java/transex3/model/SdfEntity.java
new file mode 100644
index 000000000000..4b293421fd28
--- /dev/null
+++ b/l10ntools/java/receditor/java/transex3/model/SdfEntity.java
@@ -0,0 +1,211 @@
+package transex3.model;
+
+public class SdfEntity {
+ private String project;
+ private String source_file;
+ private String dummy1;
+ private String resource_type;
+ private String gid;
+ private String lid;
+ private String helpid;
+ private String platform;
+ private String dummy2;
+ private String langid;
+ private String text;
+ private String helptext;
+ private String quickhelptext;
+ private String title;
+ private String date;
+
+ public static int PROJECT_POS = 0;
+ public static int SOURCE_FILE_POS = 1;
+ public static int DUMMY1_POS = 2;
+ public static int RESOURCE_TYPE_POS = 3;
+ public static int GID_POS = 4;
+ public static int LID_POS = 5;
+ public static int HELPID_POS = 6;
+ public static int PLATFORM_POS = 7;
+ public static int DUMMY2_POS = 8;
+ public static int LANGID_POS = 9;
+ public static int TEXT_POS = 10;
+ public static int HELPTEXT_POS = 11;
+ public static int QUICKHELPTEXT_POS = 12;
+ public static int TITLE_POS = 13;
+ public static int DATE_POS = 14;
+
+ public SdfEntity(){}
+ public SdfEntity(String project, String source_file, String dummy1, String resource_type, String gid, String lid, String helpid, String platform, String dummy2, String langid, String text, String helptext, String quickhelptext, String title , String date) {
+ super();
+ this.project = project;
+ this.source_file = source_file;
+ this.dummy1 = dummy1;
+ this.resource_type = resource_type;
+ this.gid = gid;
+ this.lid = lid;
+ this.helpid = helpid;
+ this.platform = platform;
+ this.dummy2 = dummy2;
+ this.langid = langid;
+ this.text = text;
+ this.helptext = helptext;
+ this.quickhelptext = quickhelptext;
+ this.title = title;
+ this.date = date;
+ }
+
+ public void setProperties( String line ){
+
+ String[] splitted = line.split("\t");
+
+ setProject( splitted[ SdfEntity.PROJECT_POS ] );
+ setSource_file( splitted[ SdfEntity.SOURCE_FILE_POS ] );
+ setDummy1( splitted[ SdfEntity.DUMMY1_POS ] );
+ setResource_type( splitted[ SdfEntity.RESOURCE_TYPE_POS ] );
+ setGid( splitted[ SdfEntity.GID_POS ] );
+ setLid( splitted[ SdfEntity.LID_POS ] );
+ setHelpid( splitted[ SdfEntity.HELPID_POS ] );
+ setPlatform( splitted[ SdfEntity.PLATFORM_POS ] );
+ setDummy2( splitted[ SdfEntity.DUMMY2_POS ] );
+ setLangid( splitted[ SdfEntity.LANGID_POS ] );
+ setText( splitted[ SdfEntity.TEXT_POS ] );
+ setHelptext( splitted[ SdfEntity.HELPTEXT_POS ] );
+ setQuickhelptext( splitted[ SdfEntity.QUICKHELPTEXT_POS ] );
+ setTitle( splitted[ SdfEntity.TITLE_POS ] );
+ setDate( splitted[ SdfEntity.DATE_POS ] );
+ }
+
+ public String getFileId(){
+ return project+"\\"+source_file;
+ }
+ public String getResourcePath(){
+ return source_file.substring(0 , source_file.lastIndexOf( "\\" )-1 );
+ }
+ public String toString(){
+ return project+"\t"+source_file+"\t"+dummy1+"\t"+resource_type+"\t"+gid+"\t"
+ +lid+"\t"+helpid+"\t"+platform+"\t"+dummy2+"\t"+langid+"\t"
+ +text+"\t"+helptext+"\t"+quickhelptext+"\t"+title+"\t"+date;
+ }
+ public String getId(){
+ return project+gid+lid+source_file+resource_type+platform+helpid;
+ }
+
+ public String getDummy1() {
+ return dummy1;
+ }
+
+ public void setDummy1(String dummy1) {
+ this.dummy1 = dummy1;
+ }
+
+ public String getPlatform() {
+ return platform;
+ }
+
+ public void setPlatform(String platform) {
+ this.platform = platform;
+ }
+
+ public String getDummy2() {
+ return dummy2;
+ }
+
+ public void setDummy2(String dummy2) {
+ this.dummy2 = dummy2;
+ }
+
+ public String getGid() {
+ return gid;
+ }
+
+ public void setGid(String gid) {
+ this.gid = gid;
+ }
+
+ public String getHelpid() {
+ return helpid;
+ }
+
+ public void setHelpid(String helpid) {
+ this.helpid = helpid;
+ }
+
+ public String getHelptext() {
+ return helptext;
+ }
+
+ public void setHelptext(String helptext) {
+ this.helptext = helptext;
+ }
+
+ public String getLangid() {
+ return langid;
+ }
+
+ public void setLangid(String langid) {
+ this.langid = langid;
+ }
+
+ public String getLid() {
+ return lid;
+ }
+
+ public void setLid(String lid) {
+ this.lid = lid;
+ }
+
+ public String getProject() {
+ return project;
+ }
+
+ public void setProject(String project) {
+ this.project = project;
+ }
+
+ public String getQuickhelptext() {
+ return quickhelptext;
+ }
+
+ public void setQuickhelptext(String quickhelptext) {
+ this.quickhelptext = quickhelptext;
+ }
+
+ public String getResource_type() {
+ return resource_type;
+ }
+
+ public void setResource_type(String resource_type) {
+ this.resource_type = resource_type;
+ }
+
+ public String getSource_file() {
+ return source_file;
+ }
+
+ public void setSource_file(String source_file) {
+ this.source_file = source_file;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+ public String getDate() {
+ return date;
+ }
+ public void setDate(String date) {
+ this.date = date;
+ }
+
+
+}
diff --git a/l10ntools/java/receditor/java/transex3/model/SdfString.java b/l10ntools/java/receditor/java/transex3/model/SdfString.java
new file mode 100644
index 000000000000..7419aeb5578b
--- /dev/null
+++ b/l10ntools/java/receditor/java/transex3/model/SdfString.java
@@ -0,0 +1,192 @@
+package transex3.model;
+import java.util.*;
+import java.io.*;
+public class SdfString {
+ private SdfEntity sourceString = null;
+ //private java.util.HashMap languageStrings = new HashMap();
+ private Vector languageList = new Vector();
+ private String id = null;
+ private String fileid = null;
+ private String filename = null;
+ private String modulename = null;
+ private String filepath = null;
+
+ /*public HashMap getLanguageStrings() {
+ return languageStrings;
+ }*/
+ public Vector getLanguageStrings() {
+ return languageList;
+ }
+
+ public void setLanguageStrings(Vector languageStrings) {
+ this.languageList = languageStrings;
+ }
+
+ public void addSourceString( SdfEntity aSdfEntity )
+ {
+ if( id == null )
+ id = aSdfEntity.getId();
+ if ( fileid == null )
+ fileid = aSdfEntity.getFileId();
+ if( modulename == null )
+ modulename = aSdfEntity.getProject();
+ if( filename == null )
+ filename = aSdfEntity.getSource_file();
+ if( filepath == null )
+ filepath = aSdfEntity.getResourcePath();
+ setSourceString( aSdfEntity );
+ }
+ public void addLanguageString( SdfEntity aSdfEntity ){
+ if( !aSdfEntity.getLangid().equals( "en-US" ) )
+ {
+ if( id == null )
+ id = aSdfEntity.getId();
+ if ( fileid == null )
+ fileid = aSdfEntity.getFileId();
+ if( modulename == null )
+ modulename = aSdfEntity.getProject();
+ if( filename == null )
+ filename = aSdfEntity.getSource_file();
+ if( filepath == null )
+ filepath = aSdfEntity.getResourcePath();
+
+ //if( aSdfEntity.getLangid().equals( "en-US" ) )
+ //{
+ // setSourceString( aSdfEntity );
+ //}
+ //else
+ //{
+ //languageStrings.put( aSdfEntity.getLangid() , aSdfEntity );
+ languageList.add( aSdfEntity );
+ //}
+ id = aSdfEntity.getId();
+ }
+ }
+
+ public SdfEntity getSourceString() {
+ return sourceString;
+ }
+
+ public void setSourceString(SdfEntity sourceString) {
+ this.sourceString = sourceString;
+ id = sourceString.getId();
+ }
+ public String getFilePath(){
+ return filepath;
+ }
+ public String getId(){
+ //return id;
+ return sourceString.getId();
+ }
+ public String getFileId(){
+ return fileid;
+ }
+
+ public String getFileName() {
+ return filename;
+ }
+
+ public void setFileName(String filename) {
+ this.filename = filename;
+ }
+
+ public String getModuleName() {
+ return modulename;
+ }
+
+ public void setModuleName(String modulename) {
+ this.modulename = modulename;
+ }
+ /*
+ public String getRealFileName(){
+ //String srcroot = "U:\\cws01\\l10ncleanup\\SRC680\\src.m213";//java.lang.System.getProperty( "SOLARSRC");
+ //String isWindows = "4nt";//java.lang.System.getProperty( "USE_SHELL");
+ String srcroot = java.lang.System.getProperty( "SOLARSRC" );
+ String isWindows = java.lang.System.getProperty( "USE_SHELL" );
+
+ //System.out.println("srcroot="+srcroot+" isWindows="+isWindows );
+ //if( true ) return;
+ //String relpath = sourceString.getFileId().substring( sourceString.getFileId().lastIndexOf("\\")
+ // , sourceString.getFileId().length() );
+ String filename;
+ if( isWindows != null && isWindows.compareTo( "4nt") == 0 )
+ {
+ filename = srcroot + "\\" + //sourceString.getProject() + "\\" +
+ sourceString.getFileId() +".recommand";
+ }
+ else
+ {
+ String filepart = sourceString.getFileId();
+ filepart = filepart.replaceAll( "\\\\" , "/" );
+ filename = srcroot + "/" + //sourceString.getProject() + "//" +
+ filepart +".recommand";
+ }
+ return filename;
+ }*/
+ public String getRealFileName(){
+ String filepart = sourceString.getFileId();
+ filepart = filepart.replaceAll( "\\\\" , "_" );
+ String filename = "/so/ws/merge/In/" + java.lang.System.getProperty( "WORK_STAMP" ) + "/" + filepart + ".sdf";
+ return filename;
+ }
+ public void removeFile(){
+ String filename = getRealFileName();
+ File aFile = new File( filename );
+ if( aFile.exists() ){
+ if( ! aFile.delete() )
+ {
+ System.out.println("Can't delete File "+filename+"\nWrong access rights?\n");
+ }
+ }
+ }
+ public void writeString(){
+ String filename = getRealFileName();
+ try {
+ if( languageList.size() > 0 )
+ {
+ System.out.print("\nWrite to "+filename );
+ BufferedWriter aBW = new BufferedWriter( new FileWriter( filename , true) );
+ aBW.write( sourceString + "\n" );
+ Iterator aIter = languageList.iterator();
+ while( aIter.hasNext() ){
+ SdfEntity aEntity = (SdfEntity)aIter.next();
+ aBW.write( sourceString.getProject()+"\t" );
+ aBW.write( sourceString.getSource_file()+"\t" );
+ aBW.write( sourceString.getDummy1()+"\t" );
+ aBW.write( sourceString.getResource_type()+"\t" );
+ aBW.write( sourceString.getGid()+"\t" );
+ aBW.write( sourceString.getLid()+"\t" );
+ aBW.write( sourceString.getHelpid()+"\t" );
+ aBW.write( sourceString.getPlatform()+"\t" );
+ aBW.write( sourceString.getDummy2()+"\t" );
+ if( aEntity.getLangid() == null )
+ aBW.write( "\t" );
+ else
+ aBW.write( aEntity.getLangid()+"\t" );
+ if( aEntity.getText() == null )
+ aBW.write( "\t" );
+ else
+ aBW.write( aEntity.getText()+"\t" );
+ if( aEntity.getHelptext() == null )
+ aBW.write( "\t" );
+ else
+ aBW.write( aEntity.getHelptext()+"\t" );
+ if( aEntity.getQuickhelptext() == null )
+ aBW.write( "\t" );
+ else
+ aBW.write( aEntity.getQuickhelptext()+"\t" );
+ if( aEntity.getTitle() == null )
+ aBW.write( "\t" );
+ else
+ aBW.write( aEntity.getTitle()+"\t" );
+ aBW.write( "2002-02-02 02:02:02\n" );
+ }
+ aBW.close();
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ //e.printStackTrace();
+ System.out.println("\nERROR: Can't write to file '"+filename+"'\nPlease contact RE/Tooling!");
+ }
+ }
+}
diff --git a/l10ntools/java/receditor/java/transex3/view/Editor.java b/l10ntools/java/receditor/java/transex3/view/Editor.java
new file mode 100644
index 000000000000..f46a82a11a2b
--- /dev/null
+++ b/l10ntools/java/receditor/java/transex3/view/Editor.java
@@ -0,0 +1,97 @@
+package transex3.view;
+import javax.swing.*;
+import java.awt.*;
+
+public class Editor extends JFrame{
+ Object[] columnnames = { "File" , "GID" , "LID" , "String" };
+ Object[] stringcolnames = { "Language", "Text", "Helptext" , "Quickhelptext","Title"};
+ //Object[][] data = new Object[4][1];//{ { "a " }, { "v " }, { "v " } , { "a " } };
+ JTable table = null;
+ JTable rectable = null;
+ JComboBox cBox = null;
+ JMenuBar menubar = null;
+ JMenu filemenu = null;
+ JMenuItem miNew = null;
+ JMenuItem miSave = null;
+ JMenuItem miExit = null;
+ //JButton button = null;
+
+ public Editor( Object[][] tabledata , Object[][] firstdata ){
+ table = new JTable( tabledata , columnnames );
+ rectable = new SdfTable( firstdata , stringcolnames );
+ menubar = new JMenuBar();
+ filemenu = new JMenu("File");
+ //miNew = new JMenuItem("New");
+ miSave = new JMenuItem("Save");
+ miExit = new JMenuItem("Exit");
+ //button = new JButton("Edit");
+ //filemenu.add( miNew );
+ filemenu.add( miSave );
+ filemenu.add( miExit );
+ menubar.add( filemenu );
+
+ Container contentPane = getContentPane();
+ //contentPane.add( new ControlPanel() , BorderLayout.NORTH );
+ contentPane.add( menubar , BorderLayout.NORTH );
+ //JPanel aPanel = new JPanel( new FlowLayout( FlowLayout.CENTER) );
+ JPanel aPanel = new JPanel( new GridLayout( 2,1 ) );
+ aPanel.add( new JScrollPane( table ) );
+ aPanel.add( new JScrollPane( rectable ) );
+ contentPane.add( aPanel , BorderLayout.CENTER );
+ //contentPane.add( button , BorderLayout.SOUTH );
+ //contentPane.add( new JScrollPane( table ), BorderLayout.CENTER );
+ //contentPane.add( new JScrollPane( table ), BorderLayout.SOUTH );
+ //contentPane.add( new JScrollPane( rectable ), BorderLayout.SOUTH );
+ //contentPane.add( new JScrollPane( rectable ), BorderLayout.SOUTH );
+ this.repaint();
+
+ }
+
+ public JTable getRectable() {
+ return rectable;
+ }
+
+ public void setRectable(JTable rectable) {
+ this.rectable = rectable;
+ }
+
+ public JTable getTable() {
+ return table;
+ }
+
+ public void setTable(JTable table) {
+ this.table = table;
+ }
+
+ /*public JButton getButton() {
+ return button;
+ }
+
+ public void setButton(JButton button) {
+ this.button = button;
+ }*/
+
+ public JMenuItem getMiExit() {
+ return miExit;
+ }
+
+ public void setMiExit(JMenuItem miExit) {
+ this.miExit = miExit;
+ }
+
+ public JMenuItem getMiSave() {
+ return miSave;
+ }
+
+ public void setMiSave(JMenuItem miSave) {
+ this.miSave = miSave;
+ }
+
+ /*public void setTableData(){
+
+ }*/
+
+}
+
+//class ControlPanel extends JPanel{}
+
diff --git a/l10ntools/java/receditor/java/transex3/view/SdfTable.java b/l10ntools/java/receditor/java/transex3/view/SdfTable.java
new file mode 100644
index 000000000000..f0cc7bd84a34
--- /dev/null
+++ b/l10ntools/java/receditor/java/transex3/view/SdfTable.java
@@ -0,0 +1,24 @@
+package transex3.view;
+
+import javax.swing.JTable;
+
+class SdfTable extends JTable{
+ //private String tableId;
+ public SdfTable( Object[][] obj1 , Object[] obj2){
+ super(obj1,obj2);
+ }
+ //@Override
+ public boolean isCellEditable(int row, int col) {
+ if( row == 0 && col == 0 || row == 0 && col == 1 || row == 0 && col == 2 || row == 0 && col == 3 || row == 0 && col == 4 )
+ return false;
+ else
+ return true;
+ }
+ /*public String getTableId() {
+ return tableId;
+ }
+ public void setTableId(String tableId) {
+ this.tableId = tableId;
+ }*/
+
+} \ No newline at end of file
diff --git a/l10ntools/java/receditor/makefile.mk b/l10ntools/java/receditor/makefile.mk
new file mode 100755
index 000000000000..dd3f84daccce
--- /dev/null
+++ b/l10ntools/java/receditor/makefile.mk
@@ -0,0 +1,39 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=../..
+PRJNAME=l10ntools
+TARGET=receditor
+
+.INCLUDE : ant.mk
+
+ALLTAR : ANTBUILD
+
diff --git a/l10ntools/java/receditor/receditor.MF b/l10ntools/java/receditor/receditor.MF
new file mode 100755
index 000000000000..dced97882df9
--- /dev/null
+++ b/l10ntools/java/receditor/receditor.MF
@@ -0,0 +1 @@
+Main-Class: transex3.controller.Main
diff --git a/l10ntools/layout/README b/l10ntools/layout/README
new file mode 100644
index 000000000000..1838e2a94ba0
--- /dev/null
+++ b/l10ntools/layout/README
@@ -0,0 +1,27 @@
+Tralay - Extract and translate strings in Layout xml files.
+
+Translatable strings in layout xml files are attributes that have name
+which starts with an underscore, eg
+
+ _title="Set Zoom"
+ _label="Whole Page"
+
+Here is how it works
+
+ * Extract: generate out.sdf
+ ../unxlngx6.pro/bin/tralay -l en-US zoom.xml > out.sdf
+
+ * Translate: do:
+ cat out.sdf > trans.sdf
+ sed 's/en-US\t/de\tde:/' out.sdf >> trans.sdf
+
+ * Merge: translate
+ ../unxlngx6.pro/bin/tralay -m trans.sdf -l de zoom.xml > zoom-DE.xml
+
+Running
+
+ dmake test
+
+does something similar.
+
+ \ No newline at end of file
diff --git a/l10ntools/layout/layoutparse.cxx b/l10ntools/layout/layoutparse.cxx
new file mode 100644
index 000000000000..0f43c9a3053f
--- /dev/null
+++ b/l10ntools/layout/layoutparse.cxx
@@ -0,0 +1,139 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: layoutparse.cxx,v $
+ *
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "layoutparse.hxx"
+
+#define STRING( str ) String( str, RTL_TEXTENCODING_UTF8 )
+#define BSTRING( str ) ByteString( str, RTL_TEXTENCODING_UTF8 )
+
+LayoutXMLFile::LayoutXMLFile( bool mergeMode )
+ : XMLFile()
+ , mMergeMode( mergeMode )
+{
+}
+
+void
+LayoutXMLFile::SearchL10NElements( XMLParentNode* pCur, int )
+{
+ if ( !pCur )
+ pCur = this;
+
+ /* Recurse int children, SearchL10NElements does not do that for us. */
+ if ( XMLChildNodeList* lst = pCur->GetChildList() )
+ for ( ULONG i = 0; i < lst->Count(); i++ )
+ if ( lst->GetObject( i )->GetNodeType() == XML_NODE_TYPE_ELEMENT )
+ HandleElement( ( XMLElement* )lst->GetObject( i ) );
+ else if ( lst->GetObject( i )->GetNodeType() == XML_NODE_TYPE_COMMENT )
+ lst->Remove( i-- );
+}
+
+std::vector<XMLAttribute*>
+interestingAttributes( XMLAttributeList* lst )
+{
+ std::vector<XMLAttribute*> interesting;
+ if ( lst )
+ for ( ULONG i = 0; i < lst->Count(); i++ )
+ if ( lst->GetObject( i )->Equals( STRING( "id" ) ) )
+ interesting.insert( interesting.begin(), lst->GetObject( i ) );
+ else if ( ! BSTRING( *lst->GetObject( i ) ).CompareTo( "_", 1 ) )
+ interesting.push_back( lst->GetObject( i ) );
+ return interesting;
+}
+
+void
+LayoutXMLFile::HandleElement( XMLElement* element )
+{
+ std::vector<XMLAttribute*> interesting = interestingAttributes( element->GetAttributeList() );
+
+ if ( interesting.size() )
+ {
+ std::vector<XMLAttribute*>::iterator i = interesting.begin();
+
+ ByteString id = BSTRING( (*i++)->GetValue() );
+
+ if ( mMergeMode )
+ InsertL10NElement( id, element );
+ else
+ for ( ; i != interesting.end(); ++i )
+ {
+ ByteString attributeId = id;
+ ByteString value = BSTRING( ( *i )->GetValue() );
+ XMLElement *e = new XMLElement( *element );
+ e->RemoveAndDeleteAllChilds();
+ /* Copy translatable text to CONTENT. */
+ //new XMLData( STRING( ( *i )->GetValue() ), e, true );
+ new XMLData( STRING( value ), e, true );
+ attributeId += BSTRING ( **i );
+ InsertL10NElement( attributeId, e );
+ }
+ }
+
+ SearchL10NElements( (XMLParentNode*) element );
+}
+
+void LayoutXMLFile::InsertL10NElement( ByteString const& id, XMLElement* element )
+{
+ ByteString const language = "en-US";
+ LangHashMap* languageMap = 0;
+ XMLHashMap::iterator pos = XMLStrings->find( id );
+ if ( pos != XMLStrings->end() )
+ {
+ languageMap = pos->second;
+ fprintf( stderr, "error:%s:duplicate translation found, id=%s\n",
+ id.GetBuffer(), BSTRING( sFileName ).GetBuffer() );
+ exit( 1 );
+ }
+ else
+ {
+ languageMap = new LangHashMap();
+ XMLStrings->insert( XMLHashMap::value_type( id , languageMap ) );
+ order.push_back( id );
+ }
+ (*languageMap)[ language ] = element;
+}
+
+BOOL LayoutXMLFile::Write( ByteString &aFilename )
+{
+
+ if ( aFilename.Len() )
+ {
+ ofstream aFStream( aFilename.GetBuffer() , ios::out | ios::trunc );
+ if ( !aFStream )
+ fprintf( stderr, "ERROR: cannot open file:%s\n", aFilename.GetBuffer() );
+ else
+ {
+ XMLFile::Write( aFStream );
+ aFStream.close();
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/l10ntools/layout/layoutparse.hxx b/l10ntools/layout/layoutparse.hxx
new file mode 100644
index 000000000000..b9cd8f6c18b2
--- /dev/null
+++ b/l10ntools/layout/layoutparse.hxx
@@ -0,0 +1,55 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: layoutparse.hxx,v $
+ *
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef LAYOUTPARSE_HXX
+#define LAYOUTPARSE_HXX
+
+#include "xmlparse.hxx"
+
+class LayoutXMLFile : public XMLFile
+{
+ bool mMergeMode;
+
+public:
+ LayoutXMLFile( bool mergeMode );
+
+ void SearchL10NElements( XMLParentNode *pCur, int pos = 0 );
+ BOOL Write( ByteString &aFilename );
+ void HandleElement( XMLElement* element );
+ void InsertL10NElement( ByteString const& id, XMLElement* element );
+
+ using XMLFile::InsertL10NElement;
+ using XMLFile::Write;
+};
+
+std::vector<XMLAttribute*> interestingAttributes( XMLAttributeList* lst );
+
+#endif /* LAYOUTPARSE_HXX */
diff --git a/l10ntools/layout/loc.sdf b/l10ntools/layout/loc.sdf
new file mode 100644
index 000000000000..023357adc420
--- /dev/null
+++ b/l10ntools/layout/loc.sdf
@@ -0,0 +1,24 @@
+transex3 layout\workben\zoom-1.xml 0 help FL_ZOOM 0 en-US Zoom factor 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_WHOLE_PAGE 0 en-US Whole Page 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_PAGE_WIDTH 0 en-US Page Width 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_OPTIMAL 0 en-US Optimal 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_200 0 en-US 200 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_150 0 en-US 15~0 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_100 0 en-US 100 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_75 0 en-US 75 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_50 0 en-US 50 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_USER 0 en-US Variable 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help FL_ZOOM 0 de deZoom factor 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_WHOLE_PAGE 0 de deWhole Page 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_PAGE_WIDTH 0 de dePage Width 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_OPTIMAL 0 de deOptimal 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_200 0 de de200 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_150 0 de de15~0 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_100 0 de de100 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_75 0 de de75 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_50 0 de de50 % 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_USER 0 de deVariable 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help FL_ZOOM 0 en-US Zoom factor 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_WHOLE_PAGE 0 en-US Whole Page 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help FL_ZOOM 0 de de3:Zoom factor 20080204 13:51:01
+transex3 layout\workben\zoom-1.xml 0 help BTN_WHOLE_PAGE 0 de de3:Whole Page 20080204 13:51:01
diff --git a/l10ntools/layout/makefile.mk b/l10ntools/layout/makefile.mk
new file mode 100644
index 000000000000..63dbeae6d9e9
--- /dev/null
+++ b/l10ntools/layout/makefile.mk
@@ -0,0 +1,81 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..
+
+INCPRE=$(MISC)
+
+PRJNAME=l10ntools
+TARGET=tralay
+#TARGETTYPE=GUI
+TARGETTYPE=CUI
+LIBTARGET=no
+
+# --- Settings -----------------------------------------------------
+
+ENABLE_EXCEPTIONS=TRUE
+
+.INCLUDE : settings.mk
+
+.IF "$(SYSTEM_EXPAT)" == "YES"
+CFLAGS+=-DSYSTEM_EXPAT
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+APP1TARGET=$(TARGET)
+
+OBJFILES =\
+ $(OBJ)/export2.obj\
+ $(OBJ)/helpmerge.obj\
+ $(OBJ)/layoutparse.obj\
+ $(OBJ)/merge.obj\
+ $(OBJ)/tralay.obj\
+ $(OBJ)/xmlparse.obj
+
+APP1OBJS = $(OBJFILES)
+
+APP1STDLIBS =\
+ $(TOOLSLIB)\
+ $(EXPATASCII3RDLIB)\
+ $(VOSLIB)\
+ $(CPPULIB) \
+ $(SALLIB)
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+test .PHONY:
+ ../$(INPATH)/bin/tralay -l en-US -o out.sdf zoom.xml
+ cat out.sdf > trans.sdf
+ sed 's/en-US\t/de\tde:/' out.sdf >> trans.sdf
+ ../$(INPATH)/bin/tralay -m trans.sdf -l de -o zoom-DE.xml zoom.xml
diff --git a/l10ntools/layout/tralay.cxx b/l10ntools/layout/tralay.cxx
new file mode 100644
index 000000000000..13a7fdb0c5d9
--- /dev/null
+++ b/l10ntools/layout/tralay.cxx
@@ -0,0 +1,403 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: tralay.cxx,v $
+ *
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <com/sun/star/xml/sax/SAXException.hpp>
+#include <l10ntools/vosapp.hxx>
+
+#include <osl/file.hxx>
+
+#include "export.hxx"
+#include "layoutparse.hxx"
+#include "helpmerge.hxx"
+#include "xmlparse.hxx"
+
+// Convert a rtl::OUString to a byte string.
+#define OUSTRING_CSTR( str ) \
+ rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr()
+
+#define STRING( str ) String( str, RTL_TEXTENCODING_UTF8 )
+#define BSTRING( str ) ByteString( str, RTL_TEXTENCODING_UTF8 )
+
+using ::rtl::OUString;
+
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+
+class TranslateLayout : public Application
+{
+ ByteString mGid1;
+ ByteString mLanguage;
+ ByteString mLocalize;
+ ByteString mOutput;
+ ByteString mProject;
+ ByteString mRoot;
+ bool mMergeMode;
+ std::vector< ByteString > mLanguages;
+ std::list< ByteString > mFiles;
+
+public:
+ TranslateLayout();
+ virtual ~TranslateLayout();
+ ByteString GetCommandLineParam( int i );
+ ByteString GetOptionArgument( int const i );
+ void ExceptionalMain();
+ void Main();
+ void Merge();
+ void MergeLanguage( ByteString const& language );
+ void ParseCommandLine();
+ void CreateSDF();
+
+ using Application::GetCommandLineParam;
+};
+
+static void usage()
+{
+ fprintf( stderr, "Usage: tralay [OPTION]... XML-FILE\n" );
+ fprintf( stderr, "\nOptions:\n" );
+ fprintf( stderr, " -h,--help show this help\n" );
+ fprintf( stderr, " -l,--language=LANG process this language\n" );
+ fprintf( stderr, " -m,--merge=DATABASE.SDF translation database\n" );
+ fprintf( stderr, "\nExamples:\n" );
+ fprintf( stderr, " tralay -l en-US -o localize.sdf zoom.xml # Extract\n" );
+ fprintf( stderr, " tralay -m localize.sdf -l de -l nl -o out zoom.xml # Merge/translate\n" );
+ exit( 2 );
+}
+
+static ByteString ConvertSystemPath( const ByteString& rPath )
+{
+ if( rPath.CompareTo( ".", 1 ) == 0 )
+ {
+ OUString sPath( rPath.GetBuffer(), rPath.Len(), RTL_TEXTENCODING_UTF8 );
+
+ ::rtl::OUString curDirPth, sURL;
+ osl_getProcessWorkingDir( &curDirPth.pData );
+
+ ::osl::FileBase::getAbsoluteFileURL( curDirPth, sPath, sURL );
+ ::osl::FileBase::getSystemPathFromFileURL( sURL, sPath );
+
+ return ByteString( rtl::OUStringToOString( sPath, RTL_TEXTENCODING_UTF8 ) );
+ }
+ else
+ {
+ return rPath;
+ }
+}
+
+ByteString TranslateLayout::GetCommandLineParam( int i )
+{
+ return ByteString( OUSTRING_CSTR( Application::GetCommandLineParam( sal::static_int_cast< USHORT >( i ) ) ) );
+}
+
+ByteString TranslateLayout::GetOptionArgument( int const i )
+{
+ if ( i >= GetCommandLineParamCount() )
+ usage();
+ ByteString arg = GetCommandLineParam( i );
+ if ( !arg.CompareTo( "-", 1 ) )
+ {
+ fprintf( stderr, "Option needs an argument: %s, found: %s\n",
+ GetCommandLineParam( i - 1 ).GetBuffer(),
+ arg.GetBuffer() );
+ usage();
+ }
+ return arg;
+ }
+
+void TranslateLayout::ParseCommandLine()
+{
+ for ( int i = 0; i < GetCommandLineParamCount(); i++ )
+ {
+ ByteString aParam = GetCommandLineParam( i );
+ if ( aParam.Equals( "-h" ) || aParam.Equals( "--help" ) )
+ usage();
+ else if ( aParam.Equals( "-l" ) || aParam.Equals( "--language" ) )
+ mLanguages.push_back ( GetOptionArgument( ++i ) );
+ else if ( aParam.Equals( "-m" ) || aParam.Equals( "--merge" ) )
+ {
+ mMergeMode = true;
+ mLocalize = GetOptionArgument( ++i );
+ }
+ else if ( aParam.Equals( "-o" ) || aParam.Equals( "--output" ) )
+ mOutput = ConvertSystemPath( GetOptionArgument( ++i ) );
+ else if ( !aParam.CompareTo( "-", 1 ) )
+ {
+ fprintf( stderr, "error: No such option: %s\n", aParam.GetBuffer() );
+ usage();
+ }
+ else
+ mFiles.push_back( ConvertSystemPath( aParam ) );
+ }
+ if ( !mFiles.size() )
+ {
+ fprintf( stderr, "error: No XML-FILE found\n" );
+ usage();
+ }
+}
+
+static XMLAttribute*
+findAttribute( XMLAttributeList* lst, String const& name )
+{
+ for ( ULONG i = 0; i < lst->Count(); i++ )
+ if ( lst->GetObject( i )->Equals( name ) )
+ return lst->GetObject( i );
+ return 0;
+}
+
+static XMLAttribute*
+translateAttribute( XMLAttributeList* lst,
+ String const& name, String const& translation )
+{
+ if ( XMLAttribute* a = findAttribute( lst, name ) )
+ return lst->Replace ( new XMLAttribute( name.Copy( 1 ), translation ), a );
+ return 0;
+}
+
+static void
+translateElement( XMLElement* element, ByteString const& lang,
+ ResData* resData, MergeDataFile& mergeData )
+{
+ XMLAttributeList* attributes = element->GetAttributeList();
+ std::vector<XMLAttribute*> interesting( interestingAttributes( attributes ) );
+
+
+ if( !interesting.empty() )
+ {
+ std::vector<XMLAttribute*>::iterator i( interesting.begin() );
+ ByteString id = BSTRING( (*i++)->GetValue() );
+ for ( ; i != interesting.end(); ++i )
+ {
+ ByteString attributeId = id;
+ attributeId += BSTRING ( **i );
+ resData->sGId = attributeId;
+ resData->sId = element->GetOldref();
+
+ if ( PFormEntrys* entry = mergeData.GetPFormEntrys( resData ) )
+ {
+ ByteString translation;
+ entry->GetText( translation, STRING_TYP_TEXT, lang, true );
+ // ByteString original = removeContent( element );
+ if ( !translation.Len() )
+#if 0
+ translation = original;
+#else
+ translation = BSTRING( ( *i )->GetValue() );
+#endif
+ delete translateAttribute( attributes, **i , STRING( translation ) );
+ }
+ }
+ }
+}
+
+static bool is_dir( ByteString const& name )
+{
+ DirectoryItem aItem;
+ OUString sFileURL( name.GetBuffer(), name.Len(), RTL_TEXTENCODING_UTF8 );
+ FileBase::getFileURLFromSystemPath( sFileURL, sFileURL );
+ if( DirectoryItem::get( sFileURL, aItem ) == FileBase::E_None )
+ {
+ FileStatus aStatus(FileStatusMask_Type);
+ if( aItem.getFileStatus( aStatus ) == FileBase::E_None )
+ {
+ if( aStatus.getFileType() == FileStatus::Directory )
+ return true;
+ }
+ }
+ return false;
+}
+
+static void make_directory( ByteString const& name )
+{
+ OUString sFileURL( name.GetBuffer(), name.Len(), RTL_TEXTENCODING_UTF8 );
+ FileBase::getFileURLFromSystemPath( sFileURL, sFileURL );
+ Directory::create( sFileURL );
+}
+
+static void insertMarker( XMLParentNode *p, ByteString const& file )
+{
+ if ( XMLChildNodeList* lst = p->GetChildList() )
+ if ( lst->Count() )
+ {
+ ULONG i = 1;
+ // Skip newline, if possible.
+ if ( lst->Count() > 1
+ && lst->GetObject( 2 )->GetNodeType() == XML_NODE_TYPE_DEFAULT )
+ i++;
+ OUString marker = OUString::createFromAscii( "\n NOTE: This file has been generated automagically by transex3/layout/tralay,\n from source template: " )
+ + STRING( file )
+ + OUString::createFromAscii( ".\n Do not edit, changes will be lost.\n" );
+ lst->Insert( new XMLComment( marker, 0 ), i );
+ }
+}
+
+void TranslateLayout::MergeLanguage( ByteString const& language )
+{
+ ByteString xmlFile = mFiles.front();
+
+ MergeDataFile mergeData( mLocalize, xmlFile,
+ FALSE, RTL_TEXTENCODING_MS_1252 );
+
+ DirEntry aFile( xmlFile );
+ SimpleXMLParser aParser;
+ LayoutXMLFile* layoutXml = new LayoutXMLFile( mMergeMode );
+ if ( !aParser.Execute( aFile.GetFull() , STRING( xmlFile ), layoutXml ) )
+ {
+ fprintf(stderr, "error: parsing: %s\n", xmlFile.GetBuffer() );
+ return;
+ }
+
+ layoutXml->Extract();
+ insertMarker( layoutXml, xmlFile );
+
+ ResData resData( "", "", "" );
+ resData.sResTyp = mProject; /* mGid1 ?? */
+ resData.sFilename = xmlFile;
+
+ XMLHashMap* xmlStrings = layoutXml->GetStrings();
+ for ( XMLHashMap::iterator i = xmlStrings->begin(); i != xmlStrings->end();
+ ++i )
+ {
+ if ( LangHashMap* languageMap = i->second )
+ if ( XMLElement* element = ( *languageMap )[ "en-US" ] )
+ translateElement( element, language, &resData, mergeData );
+ }
+
+#ifndef WNT
+ ByteString outFile = "/dev/stdout";
+#else
+ ByteString outFile = "\\\\.\\CON";
+#endif
+ if ( mOutput.Len() )
+ {
+ outFile = mOutput;
+ if ( is_dir( outFile ) )
+ {
+ ByteString outDir = mOutput;
+ outDir.Append( "/" ).Append( language );
+ if ( !is_dir( outDir ) )
+ make_directory( outDir );
+ outFile = outDir;
+ outFile.Append( "/" ).Append( xmlFile );
+ }
+ }
+ layoutXml->Write( outFile );
+ delete layoutXml;
+}
+
+void TranslateLayout::Merge()
+{
+ if ( mLanguages.size() )
+ for ( std::vector<ByteString>::iterator i = mLanguages.begin();
+ i != mLanguages.end(); ++i)
+ MergeLanguage( *i );
+ else
+ MergeLanguage( mLanguage );
+}
+
+void TranslateLayout::CreateSDF()
+{
+ ByteString xmlFile = mFiles.front();
+#ifndef WNT
+ ByteString sdf = "/dev/stdout";
+#else
+ ByteString sdf = "\\\\.\\CON";
+#endif
+ if ( mOutput.Len() )
+ sdf = mOutput;
+ Export::SetLanguages( mLanguages );
+ HelpParser::CreateSDF( sdf, mProject, mRoot, xmlFile,
+ new LayoutXMLFile( mMergeMode ), mGid1 );
+}
+
+void TranslateLayout::ExceptionalMain()
+{
+ ParseCommandLine();
+ if ( mLanguages.size() )
+ mLanguage = mLanguages.front();
+ if ( mMergeMode )
+ Merge();
+ else
+ CreateSDF();
+}
+
+void TranslateLayout::Main()
+{
+ try
+ {
+ ExceptionalMain();
+ }
+ catch ( xml::sax::SAXException& rExc )
+ {
+ OString aStr( OUStringToOString( rExc.Message,
+ RTL_TEXTENCODING_ASCII_US ) );
+ uno::Exception exc;
+ if (rExc.WrappedException >>= exc)
+ {
+ aStr += OString( " >>> " );
+ aStr += OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US );
+ }
+ fprintf( stderr, "error: parsing: '%s'\n", aStr.getStr() );
+ OSL_ENSURE( 0, aStr.getStr() );
+ }
+ catch ( uno::Exception& rExc )
+ {
+ OString aStr( OUStringToOString( rExc.Message,
+ RTL_TEXTENCODING_ASCII_US ) );
+ fprintf( stderr, "error: UNO: '%s'\n", aStr.getStr() );
+ OSL_ENSURE( 0, aStr.getStr() );
+ }
+}
+
+TranslateLayout::TranslateLayout()
+ : Application()
+ , mGid1( "layout" )
+ , mLanguage( "en-US" )
+ , mLocalize( "localize.sdf" )
+ , mOutput()
+ , mProject( "layout" )
+ , mRoot()
+ , mMergeMode( false )
+ , mLanguages()
+ , mFiles()
+{
+}
+
+TranslateLayout::~TranslateLayout()
+{
+}
+
+SAL_IMPLEMENT_MAIN()
+{
+ TranslateLayout t;
+ t.Main();
+ return 0;
+}
diff --git a/l10ntools/layout/zoom.xml b/l10ntools/layout/zoom.xml
new file mode 100644
index 000000000000..0fb3d27343ff
--- /dev/null
+++ b/l10ntools/layout/zoom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This is a template. i18n translation is not performed in-place;
+ i18n translated xml files are generated from this template by
+ transex3/layout/tralay. !-->
+
+<modaldialog xmlns="http://openoffice.org/2007/layout"
+ xmlns:cnt="http://openoffice.org/2007/layout/container"
+ id="dialog" _title="Set Zoom" _label="boe" optimumsize="true"
+ help-id="SID_ATTR_ZOOM"
+ has_border="true" sizeable="true" moveable="true">
+ <vbox spacing="5" border="5">
+ <fixedline id="FL_ZOOM" _text="Zoom factor" _tooltip="bah" cnt:expand="true"/>
+ <radiobutton radiogroup="zoom" id="BTN_WHOLE_PAGE" _label="Whole Page"/>
+ <radiobutton radiogroup="zoom" id="BTN_PAGE_WIDTH" _label="Page Width"/>
+ <radiobutton radiogroup="zoom" id="BTN_OPTIMAL" _label="Optimal"/>
+ <radiobutton radiogroup="zoom" id="BTN_200" _label="200 %"/>
+ <radiobutton radiogroup="zoom" id="BTN_150" _label="15~0 %"/>
+ <radiobutton radiogroup="zoom" id="BTN_100" _label="100 %"/>
+ <radiobutton radiogroup="zoom" id="BTN_75" _label="75 %"/>
+ <radiobutton radiogroup="zoom" id="BTN_50" _label="50 %"/>
+ <hbox cnt:expand="false" cnt:fill="true">
+ <align cnt:expand="false" cnt:fill="true">
+ <radiobutton cnt:v-align="0.5" cnt:v-fill="0" radiogroup="zoom" id="BTN_USER" _label="Variable"/>
+ </align>
+ <flow cnt:padding="10" cnt:expand="false"/>
+ <metricfield id="ED_USER" value-step="1"
+ repeat="true" has_border="true" spin="true"
+ text="100%" unit="13" custom-unit-text="%"
+ right="true"
+ cnt:expand="false"/>
+ </hbox>
+ <fixedline cnt:padding="1" id="FL_BOTTOM"/>
+ <dialogbuttonhbox border="5" spacing="5">
+ <flow/>
+ <okbutton id="BTN_ZOOM_OK"/>
+ <cancelbutton id="BTN_ZOOM_CANCEL"/>
+ <helpbutton id="BTN_ZOOM_HELP"/>
+ </dialogbuttonhbox>
+ </vbox>
+</modaldialog>
diff --git a/l10ntools/prj/build.lst b/l10ntools/prj/build.lst
new file mode 100644
index 000000000000..ff961c096cbd
--- /dev/null
+++ b/l10ntools/prj/build.lst
@@ -0,0 +1,10 @@
+tr l10ntools : tools LIBXSLT:libxslt BERKELEYDB:berkeleydb LUCENE:lucene NULL
+tr l10ntools usr1 - all tr_mkout NULL
+tr l10ntools\inc nmake - all tr_inc NULL
+tr l10ntools\source nmake - all tr_src tr_inc NULL
+tr l10ntools\layout nmake - all rt_layout tr_src tr_inc NULL
+#tr l10ntools\java\l10nconv nmake - all tr_conv NULL
+#tr l10ntools\java\receditor nmake - all tr_rece NULL
+tr l10ntools\source\help nmake - all tr_bla_help NULL
+tr l10ntools\source\filter\utils nmake - all tr_bla_utils NULL
+tr l10ntools\source\filter\merge nmake - all tr_bla_merge tr_bla_utils NULL
diff --git a/l10ntools/prj/d.lst b/l10ntools/prj/d.lst
new file mode 100644
index 000000000000..f75c16b43764
--- /dev/null
+++ b/l10ntools/prj/d.lst
@@ -0,0 +1,61 @@
+mkdir: %_DEST%\inc%_EXT%\l10ntools
+mkdir: %_DEST%\bin%_EXT%
+mkdir: %_DEST%\bin%_EXT%\help
+mkdir: %_DEST%\bin%_EXT%\help\com
+mkdir: %_DEST%\bin%_EXT%\help\com\sun
+mkdir: %_DEST%\bin%_EXT%\help\com\sun\star
+mkdir: %_DEST%\bin%_EXT%\help\com\sun\star\help
+
+..\%__SRC%\bin\cfgex.exe %_DEST%\bin%_EXT%\cfgex.exe
+..\%__SRC%\bin\cfgex %_DEST%\bin%_EXT%\cfgex
+..\%__SRC%\bin\transex3.exe %_DEST%\bin%_EXT%\transex3.exe
+..\%__SRC%\bin\transex3 %_DEST%\bin%_EXT%\transex3
+..\%__SRC%\bin\lngex.exe %_DEST%\bin%_EXT%\lngex.exe
+..\%__SRC%\bin\lngex %_DEST%\bin%_EXT%\lngex
+..\%__SRC%\bin\localize_sl.exe %_DEST%\bin%_EXT%\localize_sl.exe
+..\%__SRC%\bin\localize_sl %_DEST%\bin%_EXT%\localize_sl
+..\%__SRC%\bin\xrmex.exe %_DEST%\bin%_EXT%\xrmex.exe
+..\%__SRC%\bin\xrmex %_DEST%\bin%_EXT%\xrmex
+..\%__SRC%\bin\gsicheck.exe %_DEST%\bin%_EXT%\gsicheck.exe
+..\%__SRC%\bin\gsicheck %_DEST%\bin%_EXT%\gsicheck
+..\%__SRC%\bin\helpex.exe %_DEST%\bin%_EXT%\helpex.exe
+..\%__SRC%\bin\helpex %_DEST%\bin%_EXT%\helpex
+..\%__SRC%\bin\ulfex.exe %_DEST%\bin%_EXT%\ulfex.exe
+..\%__SRC%\bin\ulfex %_DEST%\bin%_EXT%\ulfex
+..\%__SRC%\bin\txtconv.exe %_DEST%\bin%_EXT%\txtconv.exe
+..\%__SRC%\bin\txtconv %_DEST%\bin%_EXT%\txtconv
+..\%__SRC%\bin\tralay.exe %_DEST%\bin%_EXT%\tralay.exe
+..\%__SRC%\bin\tralay %_DEST%\bin%_EXT%\tralay
+..\%__SRC%\bin\ulfconv %_DEST%\bin%_EXT%\ulfconv
+..\%__SRC%\class\FCFGMerge.jar %_DEST%\bin%_EXT%\FCFGMerge.jar
+..\%__SRC%\class\HelpIndexerTool.jar %_DEST%\bin%_EXT%\HelpIndexerTool.jar
+..\%__SRC%\bin\HelpLinker %_DEST%\bin%_EXT%\HelpLinker
+..\%__SRC%\bin\HelpCompiler %_DEST%\bin%_EXT%\HelpCompiler
+..\%__SRC%\bin\HelpCompiler.exe %_DEST%\bin%_EXT%\HelpCompiler.exe
+..\%__SRC%\bin\HelpLinker.exe %_DEST%\bin%_EXT%\HelpLinker.exe
+..\%__SRC%\bin\HelpLinker* %_DEST%\bin%_EXT%
+
+..\%__SRC%\class\converter\converter.jar %_DEST%\bin%_EXT%\converter.jar
+..\%__SRC%\doc\converter_javadoc.zip %_DEST%\bin%_EXT%\converter_javadoc.zip
+
+..\%__SRC%\class\receditor\receditor.jar %_DEST%\bin%_EXT%\receditor.jar
+
+..\scripts\localize.pl %_DEST%\bin%_EXT%\localize.pl
+..\scripts\localize_old.pl %_DEST%\bin%_EXT%\localize_old.pl
+..\scripts\localize %_DEST%\bin%_EXT%\localize
+..\scripts\fast_merge.pl %_DEST%\bin%_EXT%\fast_merge.pl
+..\scripts\keyidGen.pl %_DEST%\bin%_EXT%\keyidGen.pl
+
+..\inc\export.hxx %_DEST%\inc%_EXT%\l10ntools\export.hxx
+..\inc\l10ntools\directory.hxx %_DEST%\inc%_EXT%\l10ntools\directory.hxx
+..\inc\l10ntools\file.hxx %_DEST%\inc%_EXT%\l10ntools\file.hxx
+..\inc\l10ntools\vosapp.hxx %_DEST%\inc%_EXT%\l10ntools\vosapp.hxx
+
+..\inc\utf8conv.hxx %_DEST%\inc%_EXT%\l10ntools\utf8conv.hxx
+..\%__SRC%\lib\transex.lib %_DEST%\lib%_EXT%\transex.lib
+..\%__SRC%\lib\libtransex.a %_DEST%\lib%_EXT%\libtransex.a
+
+..\source\help\compilehelp.hxx %_DEST%\inc%_EXT%\l10ntools\compilehelp.hxx
+#..\source\help\helplinkerdllapi.h %_DEST%\inc%_EXT%\l10ntools\helplinkerdllapi.h
+..\%__SRC%\lib\* %_DEST%\lib%_EXT%\*
+..\%__SRC%\class\com\sun\star\help\* %_DEST%\bin%_EXT%\help\com\sun\star\help\*
diff --git a/l10ntools/scripts/fast_merge.pl b/l10ntools/scripts/fast_merge.pl
new file mode 100644
index 000000000000..7321a9a42911
--- /dev/null
+++ b/l10ntools/scripts/fast_merge.pl
@@ -0,0 +1,348 @@
+:
+eval 'exec perl -wS $0 ${1+"$@"}'
+ if 0;
+#*************************************************************************
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: fast_merge.pl,v $
+#
+# $Revision: 1.1.2.2 $
+#
+# last change: $Author: ihi $ $Date: 2007/07/20 10:37:53 $
+#
+# The Contents of this file are made available subject to
+# the terms of GNU Lesser General Public License Version 2.1.
+#
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2005 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#*************************************************************************
+
+use strict;
+use Class::Struct;
+use Getopt::Long;
+use File::Temp;
+use File::Path;
+
+my @files;
+my @file_names;
+my $module_name = '';
+my @current;
+my @buffer;
+my $last_file;
+my $last_path;
+my $last_localize_file;
+my $first_run = "1";
+my $sdf_filename;
+my $merge_dir;
+my $WIN;
+my $state = "none";
+
+if ( defined $ENV{USE_SHELL} && $ENV{USE_SHELL} eq '4nt' ) { $WIN = 'TRUE'; }
+else { $WIN = ''; }
+
+$SIG{INT} = 'inthandler';
+$SIG{QUIT} = 'quithandler';
+
+struct ( sdf_obj =>
+{
+ module => '$',
+ file => '$',
+ dir => '$',
+ FILEHANDLE => '$',
+ line => '$',
+ endoffile => '$'
+}
+);
+
+parse_options();
+my $lock_file = $merge_dir."/lock.mk";
+$lock_file =~ s/\//\\/g , if ( $WIN ) ;
+acquire_lock();
+read_sdf_file_names();
+init();
+my $reference;
+my $path ;
+my $localize_file;
+while( hasLines() )
+{
+ @current = ();
+ foreach ( @files )
+ {
+ push @current , $_;
+ }
+
+ $reference = getNextIdentifier( );
+
+ @current = ();
+ foreach ( @files )
+ {
+ if( $_->module eq $reference->module && $_->dir eq $reference->dir )
+ {
+ push @current , $_ ;
+ }
+ }
+ write_lines();
+}
+if( $#current+1 ne 0 )
+{
+ ( $path , $localize_file ) = make_paths();
+ add_to_buffer();
+ write_buffer( $path , $localize_file );
+}
+release_lock();
+exit( 0 );
+
+##########################################################################################
+sub acquire_lock
+{
+ if( -e $lock_file ){
+ $state = "blocked";
+ print "WARNING: Lock file '$lock_file' 'found, waiting ....\n";
+ my $cnt = 0;
+ sleep 10 , while( -e $lock_file && $cnt++ < 180 );
+ exit( 0 );
+ }else
+ {
+ $state = "locked";
+ print "Writing lock file '$lock_file'\n";
+ open FILE, ">$lock_file" or die "Can't create lock file '$lock_file'";
+ print FILE "L10N_LOCK=YES" ;
+ close ( FILE );
+ }
+}
+sub release_lock
+{
+ print "Deleting lock file '$lock_file'\n";
+ unlink $lock_file, if( -e $lock_file );
+ $state = "none";
+}
+sub inthandler
+{
+ release_lock() , if( $state eq "locked" );
+ exit( -1 );
+}
+sub quithandler
+{
+ release_lock() , if( $state eq "locked" );
+ exit( 0 );
+}
+
+sub init
+{
+ foreach my $file ( @file_names )
+ {
+ my $obj = new sdf_obj;
+ open my $FILEHANDLE , "<$file" or die "Can't open file '$file'";
+ $obj->FILEHANDLE ( $FILEHANDLE ) ;
+ getNextSdfObj( $obj );
+ push @files, $obj ;
+ print "Open file '$file'\n";
+ }
+}
+
+# get the next module/file
+sub getNextIdentifier
+{
+ my @sorted = sort {
+ return $a->module.$a->dir cmp $b->module.$b->dir;
+ } @current ;
+ return shift @sorted;
+}
+
+# update the obj with the next line
+sub getNextSdfObj
+{
+ my $obj = shift;
+ my $line = readline ( $obj->FILEHANDLE );
+ if ( $line eq undef )
+ {
+ $obj->endoffile( "true" );
+ }
+ else
+ {
+ $line =~ /^(([^\t]*)\t([^\t]*)[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t[^\t]*\t*)/o ;
+ if( defined $1 && defined $2 && defined $3 )
+ {
+ $obj->line ( $1 );
+ $obj->module( $2 );
+ $obj->file ( $3 );
+ $obj->dir ( getDir( $3 ) );
+ }
+ else
+ {
+ $obj->line ( "" );
+ $obj->module( "" );
+ $obj->file ( "" );
+ $obj->dir ( "" );
+ }
+ }
+ return $obj;
+}
+sub getNextSdfObjModule
+{
+ my $obj = shift;
+ while( !$obj->endoffile )
+ {
+ my $line = readline ( $obj->FILEHANDLE );
+ if ( $line eq undef )
+ {
+ $obj->endoffile( "true" );
+ }
+ else
+ {
+ $line =~ /^(([^\t]*)\t([^\t]*).*)/o ;
+ if( defined $1 && defined $2 && defined $3 )
+ {
+ $obj->line ( $1 );
+ $obj->module( $2 );
+ $obj->file ( $3 );
+ $obj->dir ( getDir( $3 ) );
+ }
+ else
+ {
+ $obj->line ( "" );
+ $obj->module( "" );
+ $obj->file ( "" );
+ $obj->dir ( "" );
+ }
+ return $obj , if( $obj->module eq $module_name )
+ }
+ }
+ #return $obj;
+}
+sub getDir
+{
+ my $path = shift ;
+ $path =~ s/\//\\/g;
+ my @tmp_path = split /\\/ , $path;
+ pop @tmp_path;
+ $path = join '\\' , @tmp_path;
+ return $path;
+}
+
+sub hasLines
+{
+ my $hasLines = "";
+ my @tmpfiles;
+ foreach ( @files )
+ {
+ push @tmpfiles , $_, if( !$_->endoffile );
+ }
+ @files = @tmpfiles;
+ return $#files+1;
+}
+
+sub make_paths
+{
+ my $localizeFile = $merge_dir."\\".$current[ 0 ]->module."\\".$current[ 0 ]->file;
+ my $path = getDir( $localizeFile );
+ if ( !$WIN ) { $path =~ s/\\/\//g; }
+
+ $localizeFile = $path."\\localize.sdf";
+ if ( !$WIN ) { $localizeFile =~ s/\\/\//g; }
+
+ return ( $path , $localizeFile );
+}
+sub write_lines
+{
+ if( $first_run ){
+ add_to_buffer();
+ my( $path , $localize_file ) = make_paths();
+ $last_path = $path;
+ $last_localize_file = $localize_file;
+ mkpath $path;
+ write_buffer( $path , $localize_file );
+ $first_run = '';
+ }
+ else
+ {
+ return , if ( $#current+1 eq 0 );
+ my( $path , $localize_file ) = make_paths();
+ if( $path eq $last_path )
+ {
+ add_to_buffer();
+ }
+ else
+ {
+ mkpath $path;
+ write_buffer( $last_path , $last_localize_file );
+ add_to_buffer();
+ $last_path = $path;
+ $last_localize_file = $localize_file;
+ }
+ }
+}
+sub add_to_buffer
+{
+ my $plainline;
+ my $afile;
+ my $amodule;
+ foreach my $elem ( @current )
+ {
+ do {
+ $amodule=$elem->module;
+ $afile=$elem->file;
+ $plainline=$elem->line;
+ push @buffer, $plainline;
+ getNextSdfObj( $elem );
+ } while ( !$elem->endoffile && $amodule eq $elem->module && $afile eq $elem->file );
+ }
+}
+sub write_buffer
+{
+ my $path = shift;
+ my $localize_file = shift;
+ my $cnt = $#buffer+1;
+ print "Write to $path $cnt lines\n";
+ open FILE , ">>$localize_file" or die "Can't open file '$localize_file'\n";
+ foreach ( @buffer )
+ {
+ print FILE $_."\n";
+ }
+ @buffer = ();
+}
+sub parse_options
+{
+ my $success = GetOptions( 'sdf_files=s' => \$sdf_filename , 'merge_dir=s' => \$merge_dir ); #, 'module=s' => \$module_name );
+ if( ! ( $sdf_filename && $merge_dir && $success ) )
+ {
+ usage();
+ exit( -1 );
+ }
+}
+
+sub usage
+{
+ print "Usage: fast_merge -sdf_files <file containing sdf file names> -merge_dir <directory>\n" ;
+}
+
+sub read_sdf_file_names
+{
+ open FILE , "<$sdf_filename" or die "Can't open file '$sdf_filename'\n";
+ while ( <FILE> )
+ {
+ push @file_names , split " " , $_ ;
+ }
+ close ( FILE );
+}
+
+
diff --git a/l10ntools/scripts/keyidGen.pl b/l10ntools/scripts/keyidGen.pl
new file mode 100644
index 000000000000..acb5137e3f7c
--- /dev/null
+++ b/l10ntools/scripts/keyidGen.pl
@@ -0,0 +1,189 @@
+:
+eval 'exec perl -S $0 ${1+"$@"}'
+ if 0;
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: keyidGen.pl,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+#
+# add keyids to sdf file
+#
+
+use Compress::Zlib();
+
+print "\nkeyidGen version 1.0 \n\n";
+
+my ( $infile,$outfile,$dbimport );
+get_options();
+
+print_help() if ( !defined $infile || $help );
+exit 1 if ( !defined $infile );
+if ( ! defined $outfile )
+{
+ $outfile = $infile;
+ $outfile =~ s/\.sdf$//i;
+ $outfile .= "_KeyID.sdf";
+}
+
+$collisions = 0;
+%hashcodes = ();
+$count = 0;
+print "writing to $outfile\n";
+open INFILE,"<$infile" || die "could not open $infile $! $^E\n";
+open OUTFILE,">$outfile" || die "could not open $outfile $! $^E\n";
+
+while ( <INFILE> )
+{
+ $line = $_;
+ chomp $line;
+ $hash = 0;
+ if ( $line =~ /^([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)$/ )
+ {
+ $string="$1 $2 $4 $5 $6 $7 $8";
+ $hashp = makeID( $string );
+
+ if ( defined ($hashcodes{ $hashp } ) )
+ {
+ $collisions ++ unless $hashcodes{ $hashp } eq $string;
+ }
+ $hashcodes{ $hashp } = $string;
+ $count++;
+ if ( $dbimport )
+ {
+ my ( $pre, $post, $old );
+ $pre = "$1\t$2\t";
+ $post = "\t$4\t$5\t$6\t$7\t$8\t$9\t$10\t$11\t$12\t$13\t$14\t$15\n";
+ $old = $3;
+ $old =~ s/;{0,1}keyid:......;{0,1}//;
+ $old =~ s/^0$//;
+ if ( $old ne "" ) { $old .= ";"; }
+ print OUTFILE "$pre${old}keyid:$hashp$post";
+ }
+ else
+ {
+ print OUTFILE "$1\t$2\t$3\t$4\t$5\t$6\t$7\t$8\t$9\t$10\t".makekidstr($hashp,$11)."\t".makekidstr($hashp,$12)."\t$13\t".makekidstr($hashp,$14)."\t$15\n";
+ }
+ }
+}
+print "$count entries\n";
+print "$collisions collisions\n";
+
+close INFILE;
+close OUTFILE;
+
+sub makeID
+{
+ my ( $String ) = shift;
+ my ( $hash );
+ # hardcoded to prevent windows installer to choke on bad directoryname :-((
+ if ( $String eq "scp2 source\\ooo\\directory_ooo.ulf LngText STR_DIR_KAPITEL " )
+ {
+ return "keyid1";
+ }
+
+ $hash = Compress::Zlib::crc32( $String, undef );
+ return makenumber( $hash );
+}
+
+sub makenumber
+{
+ $h = shift;
+ # 1 2 3 4
+ # 1234567890123456789012345678901234567890
+ $symbols="0123456789abcdefghijklmnopqrstuvwxyz+-<=>";
+ $order = length($symbols);
+ $result = "";
+ while ( length( $result ) < 6 )
+ {
+ $result .= substr( $symbols, ($h % $order), 1 );
+ $h = int( $h / $order );
+ }
+ die "makenumber failed because number is too big (this cannot be so this is a strange error)" if $h > 0;
+
+ return reverse $result;
+}
+
+
+sub makekidstr
+{
+ $kid = shift;
+ $str = shift;
+
+ if ( $str ne "" )
+ {
+ # special handling for strings starting with font descriptions like {&Tahoma8} (win system integration)
+ if ( $str =~ s/^(\{\&[^\}]+\})// )
+ {
+ return "$1$kid‖$str";
+ }
+ else
+ {
+ return "$kid‖$str";
+ }
+ }
+ else
+ {
+ return "";
+ }
+# return "default";
+}
+
+sub print_help
+{
+ print "\n\n";
+ print "keyidGen 0.5 for sdf files\n";
+ print "--------------------------\n";
+ print "Usage:\n";
+ print "keyidGen <infile> [<outfile>] [-dbimport]\n";
+ print " add keyids to the entries and write them to a file with\n";
+ print " _KeyID added to the name\n";
+ print " -dbimport Add KeyID to a new column instead of to the strings.\n";
+ print " This is needed to import the IDs into tha database.\n";
+ print "\n\n";
+}
+
+
+sub get_options {
+ my ($arg,$has_infile);
+
+ while ($arg = shift @ARGV) {
+ $arg =~ /^-dbimport$/ and $dbimport = 1 and next;
+ $arg =~ /^-help$/ and $help = 1 and next; #show help
+
+ if ( !$has_infile )
+ {
+ $infile = $arg;
+ $has_infile = 1;
+ }
+ else
+ {
+ $outfile = $arg;
+ }
+ }
+}
diff --git a/l10ntools/scripts/localize.pl b/l10ntools/scripts/localize.pl
new file mode 100755
index 000000000000..0f6a19effc38
--- /dev/null
+++ b/l10ntools/scripts/localize.pl
@@ -0,0 +1,1201 @@
+:
+eval 'exec perl -wS $0 ${1+"$@"}'
+ if 0;
+
+
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: localize.pl,v $
+#
+# $Revision: 1.18.6.2 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+use strict;
+use Getopt::Long;
+use IO::Handle;
+use File::Find;
+use File::Temp;
+use File::Path;
+use File::Copy;
+use File::Glob qw(:glob csh_glob);
+use Cwd;
+
+my $CVS_BINARY = "/usr/bin/cvs";
+# ver 1.1
+#
+#### module lookup
+#use lib ("$ENV{SOLARENV}/bin/modules", "$ENV{COMMON_ENV_TOOLS}/modules");
+
+#### module lookup
+# OOo conform
+my @lib_dirs;
+BEGIN {
+ if ( !defined($ENV{SOLARENV}) ) {
+ die "No environment found (environment variable SOLARENV is undefined)";
+ }
+ push(@lib_dirs, "$ENV{SOLARENV}/bin/modules");
+ push(@lib_dirs, "$ENV{COMMON_ENV_TOOLS}/modules") if defined($ENV{COMMON_ENV_TOOLS});
+}
+use lib (@lib_dirs);
+
+#### globals ####
+my $sdffile = '';
+my $no_sort = '';
+my $create_dirs = '';
+my $multi_localize_files = '';
+my $module_to_merge = '';
+my $sort_sdf_before = '';
+my $outputfile = '';
+my $no_gsicheck = '';
+my $mode = '';
+my $bVerbose = "0";
+my $srcpath = '';
+my $WIN;
+my $languages;
+#my %sl_modules; # Contains all modules where en-US and de is source language
+my $use_default_date = '0';
+my $force_ooo_module = '0';
+my %is_ooo_module;
+my %is_so_module;
+my $DELIMITER;
+
+ # ( leftpart ) ( rightpart )
+ # prj file dummy type gid lid helpid pform width lang text helptext qhelptext title timestamp
+my $sdf_regex = "((([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*))\t([^\t]*)\t(([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t)([^\t]*))";
+my $file_types = "(src|hrc|xcs|xcu|lng|ulf|xrm|xhp|xcd|xgf|xxl|xrb)";
+# Always use this date to prevent cvs conflicts
+my $default_date = "2002-02-02 02:02:02";
+my @sdfparticles;
+
+#### main ####
+parse_options();
+check_modules_scm();
+
+if ( defined $ENV{USE_SHELL} && $ENV{USE_SHELL} eq '4nt' ) {
+ $WIN = 'TRUE';
+ $DELIMITER = "\\";
+}
+ else {
+ $WIN = '';
+ $DELIMITER = "/";
+}
+
+my $binpath = '';
+if( defined $ENV{UPDMINOREXT} )
+{
+ $binpath = $ENV{SOLARVER}.$DELIMITER.$ENV{INPATH}.$DELIMITER."bin".$ENV{UPDMINOREXT}.$DELIMITER ;
+}
+else
+{
+ $binpath = $ENV{SOLARVER}.$DELIMITER.$ENV{INPATH}.$DELIMITER."bin".$DELIMITER ;
+}
+
+#%sl_modules = fetch_sourcelanguage_dirlist();
+
+
+if ( $mode eq "merge" ) {
+ if ( ! $no_gsicheck ){
+ merge_gsicheck();
+ }
+ splitfile( $sdffile );
+ if ( ! $no_gsicheck ){
+ unlink $sdffile; # remove temp file!
+ }
+}
+elsif( $mode eq "extract" ) {
+ collectfiles( $outputfile );
+}
+else {
+ usage();
+}
+
+exit(0);
+
+#########################################################
+sub splitfile{
+
+ my $lastFile = '';
+ my $currentFile = '';
+ my $cur_sdffile = '';
+ my $last_sdffile = '';
+ my $delim;
+ my $badDelim;
+ my $start = 'TRUE';
+ my %index = ();
+ my %block;
+
+ STDOUT->autoflush( 1 );
+
+ #print STDOUT "Open File $sdffile\n";
+ open MYFILE , "< $sdffile"
+ or die "Can't open '$sdffile'\n";
+
+# my %lang_hash;
+ my %string_hash_ooo;
+ my %string_hash_so;
+ my %so_modules;
+ $so_modules{ "extras_full" } = "TRUE";
+
+ while( <MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+ next if( $prj eq "binfilter" ); # Don't merge strings into binfilter module
+ chomp( $line );
+
+ if( is_openoffice_module( $prj ) )
+ {
+ $string_hash_ooo { $lang }{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } = $line;
+ }
+ else
+ {
+ $string_hash_so{ $lang }{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } = $line;
+ }
+ }
+ }
+ close( MYFILE );
+
+ if( !defined $ENV{SRC_ROOT} ){
+ print "Error, no SRC_ROOT in env found.\n";
+ exit( -1 );
+ }
+ my $src_root = $ENV{SRC_ROOT};
+ #print $WIN eq "TRUE" ? $src_root."\\l10n_so\n" : $src_root."/l10n_so\n";
+ my $so_l10n_path = $WIN eq "TRUE" ? $src_root."\\l10n_so\\source" : $src_root."/l10n_so/source";
+ my $ooo_l10n_path = $WIN eq "TRUE" ? $src_root."\\l10n\\source" : $src_root."/l10n/source";
+
+ #print "$so_l10n_path\n";
+ #print "$ooo_l10n_path\n";
+
+ write_sdf( \%string_hash_so , $so_l10n_path );
+ write_sdf( \%string_hash_ooo , $ooo_l10n_path );
+
+}
+sub check_modules_scm
+{
+ #my @ooo_modules;
+ #my @so_modules;
+ my $src_path = $ENV{ SRC_ROOT } ;
+ my $last_dir = getcwd();
+ chdir $src_path ;
+ my @modules = <*/.svn/entries>;
+
+ foreach my $module ( @modules )
+ {
+ #print "$module \n";
+ if( open ( FILE , "<$module" ) )
+ {
+ while( <FILE> )
+ {
+
+ my @path = split ( "/" , $module ) ;
+
+ if( /svn.services.openoffice.org/ )
+ {
+ my $mod = $path[ 0 ];
+ #push @ooo_modules , $mod;
+ $is_ooo_module{ $mod } = "true";
+ # print "$module -> ooo ";
+ }
+ elsif ( /jumbo2.germany.sun.com/ )
+ {
+ my $mod = $path[ 0 ];
+ #push @so_modules , $mod;
+ # print "$module -> so ";
+ #$so_lookup_hash{ $mod } = "true";
+ }
+ #else
+ #{
+ # print "ERROR: Is $module a SO or OOo module? Can not parese the $module/.svn/entries file ... please check mwsfinnish/merge/splitsdf.pl line 280\n";
+ # exit -1;
+ #}
+ }
+ }
+ }
+ chdir $last_dir ;
+ #print "OOO\n";
+ #print @ooo_modules;
+ #print "\nSO\n";
+ #print @so_modules;
+}
+
+
+#sub parse
+#{
+# my $command = "$CVS_BINARY -d:pserver:anoncvs\@anoncvs.services.openoffice.org:/cvs co -c";
+# my $output = `$command`;
+# my $rc = $? << 8;
+# if ( $output eq "" || $rc < 0 ){
+# print STDERR "ERROR: Can not fetch cvs alias list, please login to the cvs server and press at the password prompt just return\ncvs -d:pserver:anoncvs\@anoncvs.services.openoffice.org:/cvs login\n";
+# exit ( -1 );
+# }
+# my @list = split /\n/ , $output ;
+# foreach my $string( @list )
+# {
+#
+# # print "Found '$1'\n" , if( $string =~ /^(\w*)/ && $1 ne "" );
+#
+# $is_ooo_module{ $1 } = "TRUE", if( $string =~ /^(\w*)/ && $1 ne "" );
+# }
+# # foreach my $key( keys( %is_ooo_module ) )
+# #{
+# # print "$key\n";
+# #}
+#}
+sub is_openoffice_module
+{
+ my $module = shift;
+ return "TRUE", if ( $force_ooo_module || defined $is_ooo_module{ $module } );
+ return "";
+}
+
+sub write_sdf
+{
+ my $string_hash = shift;
+ my $l10n_file = shift;
+
+ foreach my $lang( keys( %{ $string_hash } ) )
+ {
+ my @sdf_file;
+
+ # mkdir!!!!
+ my $current_l10n_file = $WIN eq "TRUE" ? $l10n_file."\\$lang\\localize.sdf" : $l10n_file."/$lang/localize.sdf";
+ print "Writing '$current_l10n_file'\n";
+ if( open DESTFILE , "< $current_l10n_file" ){
+
+ while(<DESTFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ chomp( $line );
+ if ( defined $string_hash->{ $lang }{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } )
+ {
+ # Changed String!
+ push @sdf_file , $string_hash->{ $lang }{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } ;
+ $string_hash->{ $lang }{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } = undef;
+ }
+ else
+ {
+ # No new string
+ push @sdf_file , $line;
+ }
+ }
+ }
+ }
+ close( DESTFILE );
+ #Now just append the enw strings
+ #FIXME!!! Implement insertion in the correct order
+ foreach my $key ( keys ( %{ $string_hash->{ $lang } } ) )
+ {
+ push @sdf_file , $string_hash->{ $lang }{ $key } , if ( defined $string_hash->{ $lang }{ $key } );
+ #print "WARNING: Not defined = ".$string_hash->{ $lang }{ $key }."\n", if( ! defined $string_hash->{ $lang }{ $key } );
+ }
+
+ # Write the new file
+ my ( $TMPFILE , $tmpfile ) = File::Temp::tempfile();
+ if( open DESTFILE , "+> $tmpfile " ){
+ print DESTFILE get_license_header();
+ foreach my $string( @sdf_file ){
+ print DESTFILE "$string\n";
+ }
+ close ( DESTFILE );
+ if( move( $current_l10n_file , $current_l10n_file.".backup" ) ){
+ if( copy( $tmpfile , $current_l10n_file ) ){
+ unlink $l10n_file.".backup";
+ } else { print STDERR "Can't open/create '$l10n_file', original file is renamed to $l10n_file.backup\n"; }
+ } else { print STDERR "Can't open/create '$l10n_file'\n"; }
+ }else{
+ print STDERR "WARNING: Can't open/create '$l10n_file'\n";
+ }
+ unlink $tmpfile;
+ }
+}
+
+#########################################################
+
+sub get_license_header{
+ return
+"#\n".
+"# #### ### # # ### ##### ##### #### ##### ##### \n".
+"# # # # # ## # # # # # # # # # \n".
+"# # # # # # # # # # # ### # # # # \n".
+"# # # # # # ## # # # # # # # # \n".
+"# #### ### # # ### # ##### #### ##### # \n".
+"#\n".
+"# DO NOT EDIT! This file will be overwritten by localisation process\n".
+"#\n".
+"#*************************************************************************\n".
+"#\n".
+"# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n".
+"# \n".
+"# Copyright 2008 by Sun Microsystems, Inc.\n".
+"#\n".
+"# OpenOffice.org - a multi-platform office productivity suite\n".
+"#\n".
+"# \$RCSfile:".
+"localize.pl,v \$\n".
+"#\n".
+"# \$Revision: ".
+"1.17.4.1 \$\n".
+"#\n".
+"# This file is part of OpenOffice.org.\n".
+"#\n".
+"# OpenOffice.org is free software: you can redistribute it and/or modify\n".
+"# it under the terms of the GNU Lesser General Public License version 3\n".
+"# only, as published by the Free Software Foundation.\n".
+"#\n".
+"# OpenOffice.org is distributed in the hope that it will be useful,\n".
+"# but WITHOUT ANY WARRANTY; without even the implied warranty of\n".
+"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n".
+"# GNU Lesser General Public License version 3 for more details\n".
+"# (a copy is included in the LICENSE file that accompanied this code).\n".
+"#\n".
+"# You should have received a copy of the GNU Lesser General Public License\n".
+"# version 3 along with OpenOffice.org. If not, see\n".
+"# <http://www.openoffice.org/license.html>\n".
+"# for a copy of the LGPLv3 License.\n".
+"#\n".
+"#*************************************************************************\n";
+}
+######## Check input sdf file and use only the correct part
+sub merge_gsicheck{
+ my $command = '';
+ my ( $TMPHANDLE , $tmpfile ) = File::Temp::tempfile();
+ close ( $TMPHANDLE );
+
+ if( $ENV{WRAPCMD} ){
+ $command = "$ENV{WRAPCMD} gsicheck";
+ }else{
+ $command = "gsicheck";
+ }
+ my $errfile = $sdffile.".err";
+ $command .= " -k -c -wcf $tmpfile -wef $errfile -l \"\" $sdffile";
+ #my $rc = system( $command );
+ my $output = `$command`;
+ my $rc = $? << 8;
+ if ( $output ne "" ){
+ print STDOUT "### gsicheck ###\n";
+ print STDOUT "### The file $errfile have been written containing the errors in your sdf file. Those lines will not be merged: ###\n\n";
+ print STDOUT "$output\n";
+ print STDOUT "################\n";
+
+ }else{
+ # Remove the 0 Byte file
+ unlink $errfile;
+ }
+ $sdffile = $tmpfile;
+}
+#########################################################
+# find search function
+sub wanted
+{
+ my $file = $File::Find::name;
+ if( -f $file && $file =~ /.*localize.sdf$/ && !( $file =~ /.*\.svn.*/ ) ) {
+ push @sdfparticles , $file;
+ if( $bVerbose eq "1" ) { print STDOUT "$file\n"; }
+ else { print "."; }
+ }
+}
+
+sub add_paths
+{
+ my $langhash_ref = shift;
+ my $root_dir = $ENV{ SRC_ROOT };
+ my $ooo_l10n_dir = "$root_dir"."$DELIMITER"."l10n"."$DELIMITER"."source";
+ my $so_l10n_dir = "$root_dir"."$DELIMITER"."l10n_so"."$DELIMITER"."source";
+
+ if( -e $ooo_l10n_dir )
+ {
+ foreach my $lang ( keys( %{ $langhash_ref } ) )
+ {
+ my $loc_file = "$ooo_l10n_dir"."$DELIMITER"."$lang"."$DELIMITER"."localize.sdf";
+ if( -e $loc_file )
+ {
+ push @sdfparticles , "$ooo_l10n_dir"."$DELIMITER"."$lang"."$DELIMITER"."localize.sdf";
+ }
+ else { print "WARNING: $loc_file not found ....\n"; }
+ }
+ }
+ else { die "ERROR: Can not find directory $ooo_l10n_dir!!!" }
+ if( -e $so_l10n_dir )
+ {
+ foreach my $lang ( keys( %{ $langhash_ref } ) )
+ {
+ my $loc_file = "$so_l10n_dir"."$DELIMITER"."$lang"."$DELIMITER"."localize.sdf";
+ if( -e $loc_file )
+ {
+ push @sdfparticles , "$ooo_l10n_dir"."$DELIMITER"."$lang"."$DELIMITER"."localize.sdf";
+ }
+ else { #print "WARNING: $loc_file not found ....\n";
+ }
+ }
+
+ }
+}
+sub collectfiles{
+ print STDOUT "### Localize\n";
+ my $localizehash_ref;
+ my ( $bAll , $bUseLocalize, $langhash_ref , $bHasSourceLanguage , $bFakeEnglish ) = parseLanguages();
+
+ # Enable autoflush on STDOUT
+ # $| = 1;
+ STDOUT->autoflush( 1 );
+
+ ### Search sdf particles
+ #print STDOUT "### Searching sdf particles\n";
+ my $working_path = getcwd();
+ #chdir $srcpath;
+ #find ( { wanted => \&wanted , follow => 1 }, getcwd() );
+ #chdir $working_path;
+ add_paths( $langhash_ref );
+ #my $nFound = $#sdfparticles +1;
+ #print "\n $nFound files found !\n";
+
+ my ( $LOCALIZEPARTICLE , $localizeSDF ) = File::Temp::tempfile();
+ close( $LOCALIZEPARTICLE );
+
+ my ( $ALLPARTICLES_MERGED , $particleSDF_merged ) = File::Temp::tempfile();
+ close( $ALLPARTICLES_MERGED );
+ my ( $LOCALIZE_LOG , $my_localize_log ) = File::Temp::tempfile();
+ close( $LOCALIZE_LOG );
+
+ ## Get the localize en-US extract
+ if( $bAll || $bUseLocalize ){
+ print "### Fetching source language strings\n";
+ my $command = "";
+ my $args = "";
+
+ if( $ENV{WRAPCMD} ){
+ $command = $ENV{WRAPCMD}.$binpath."localize_sl";
+ }else{
+ $command = $binpath."localize_sl";
+ }
+ print $command;
+ # -e
+ # if ( -x $command ){
+ if( $command ){
+ if( !$bVerbose ){ $args .= " -QQ "; }
+ $args .= " -e -f $localizeSDF -l ";
+ my $bFlag="";
+ if( $bAll ) {$args .= " en-US";}
+ else{
+ my @list;
+ foreach my $isokey ( keys( %{ $langhash_ref } ) ){
+ push @list , $isokey;
+ if( $langhash_ref->{ $isokey } ne "" ){
+ push @list , $langhash_ref->{ $isokey };
+ }
+ }
+ remove_duplicates( \@list );
+ foreach my $isokey ( @list ){
+ switch :{
+ ( $isokey=~ /^en-US$/i )
+ && do{
+ if( $bFlag eq "TRUE" ){ $args .= ",en-US"; }
+ else {
+ $args .= "en-US"; $bFlag = "TRUE";
+ }
+ };
+
+ } #switch
+ } #foreach
+ } # if
+ } # if
+# if ( !$bVerbose ){
+# if ( $WIN eq "TRUE" ) { $args .= " > $my_localize_log"; }
+# else { $args .= " >& $my_localize_log"; }
+# }
+ if ( $bVerbose ) { print STDOUT $command.$args."\n"; }
+
+ my $rc = system( $command.$args );
+
+ if( $rc < 0 ){ print STDERR "ERROR: localize rc = $rc\n"; exit( -1 ); }
+ ( $localizehash_ref ) = read_file( $localizeSDF , $langhash_ref );
+
+ }
+ ## Get sdf particles
+#*****************
+ open ALLPARTICLES_MERGED , "+>> $particleSDF_merged"
+ or die "Can't open $particleSDF_merged";
+
+ ## Fill fackback hash
+ my( $fallbackhashhash_ref ) = fetch_fallback( \@sdfparticles , $localizeSDF , $langhash_ref );
+ my %block;
+ my $cur_fallback;
+ if( !$bAll) {
+ foreach my $cur_lang ( keys( %{ $langhash_ref } ) ){
+ #print STDOUT "DBG: G1 cur_lang=$cur_lang\n";
+ $cur_fallback = $langhash_ref->{ $cur_lang };
+ if( $cur_fallback ne "" ){
+ # Insert fallback strings
+ #print STDOUT "DBG: Renaming $cur_fallback to $cur_lang in fallbackhash\n";
+ rename_language( $fallbackhashhash_ref , $cur_fallback , $cur_lang );
+ }
+ foreach my $currentfile ( @sdfparticles ){
+ if ( open MYFILE , "< $currentfile" ) {
+ while(<MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ chomp( $line );
+
+ if ( $lang eq $cur_lang ){
+ # Overwrite fallback strings with collected strings
+ #if( ( !has_two_sourcelanguages( $cur_lang) && $cur_lang eq "de" ) || $cur_lang ne "en-US" ){
+ $fallbackhashhash_ref->{ $cur_lang }{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ;
+ #}
+
+ }
+ }
+ }
+ }else { print STDERR "WARNING: Can't open file $currentfile"; }
+ }
+
+ foreach my $line ( keys( %{$fallbackhashhash_ref->{ $cur_lang } } )) {
+ if( #$cur_lang ne "de" &&
+ $cur_lang ne "en-US" ){
+ print ALLPARTICLES_MERGED ( $fallbackhashhash_ref->{ $cur_lang }{ $line }, "\n" );
+ }
+ }
+ }
+ } else {
+ foreach my $currentfile ( @sdfparticles ){
+ if ( open MYFILE , "< $currentfile" ) {
+ while( <MYFILE> ){
+ print ALLPARTICLES_MERGED ( $_, "\n" ); # recheck de / en-US !
+ }
+ }
+ else { print STDERR "WARNING: Can't open file $currentfile"; }
+ }
+ }
+ close ALLPARTICLES_MERGED;
+#***************
+
+ # Hash of array
+ my %output;
+ my @order;
+
+ ## Join both
+ if( $outputfile ){
+ if( open DESTFILE , "+> $outputfile" ){
+ if( !open LOCALIZEPARTICLE , "< $localizeSDF" ) { print STDERR "ERROR: Can't open file $localizeSDF\n"; }
+ if( !open ALLPARTICLES_MERGED , "< $particleSDF_merged" ) { print STDERR "ERROR: Can't open file $particleSDF_merged\n"; }
+
+ # Insert localize
+ my $extract_date="";
+ while ( <LOCALIZEPARTICLE> ){
+ if( /$sdf_regex/ ){
+ my $leftpart = defined $2 ? $2 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $rightpart = defined $13 ? $13 : '';
+ my $timestamp = defined $18 ? $18 : '';
+
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ #my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+
+ if( $use_default_date )
+ {
+ $extract_date = "$default_date\n" ;
+ }
+ elsif( $extract_date eq "" ) {
+ $extract_date = $timestamp ;
+ $extract_date =~ tr/\r\n//d;
+ $extract_date .= "\n";
+ }
+
+ if( $bAll ){ print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date ; }
+ else {
+ foreach my $sLang ( keys( %{ $langhash_ref } ) ){
+ if( $sLang=~ /all/i ) {
+ push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ;
+ #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date;
+ }
+ #if( $sLang eq "de" && $lang eq "de" ) {
+ # push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ;
+ #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date;
+ #}
+ if( $sLang eq "en-US" && $lang eq "en-US" ) {
+ push @order , $prj.$gid.$lid.$file.$type.$plattform.$helpid;
+ if( !$bFakeEnglish ){ push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ; }
+ #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date;
+ }
+
+ }
+ }
+ }
+ }
+ # Insert particles
+ while ( <ALLPARTICLES_MERGED> ){
+ if( /$sdf_regex/ ){
+ my $leftpart = defined $2 ? $2 : '';
+ my $prj = defined $3 ? $3 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $rightpart = defined $13 ? $13 : '';
+ my $timestamp = defined $18 ? $18 : '';
+
+ #my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ #my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+
+ if( $use_default_date )
+ {
+ $extract_date = "$default_date\n" ;
+ }
+ elsif( $extract_date eq "" )
+ {
+ $extract_date = $timestamp;
+ }
+
+ if( ! ( $prj =~ /binfilter/i ) ) {
+ push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ;
+ #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date ;
+ }
+ }
+ }
+
+ # Write!
+ foreach my $curkey ( @order ){
+ foreach my $curlist ( $output{ $curkey } ){
+ foreach my $line ( @{$curlist} ){
+ print DESTFILE $line;
+ }
+ }
+ }
+
+ }else { print STDERR "Can't open $outputfile";}
+ }
+ close DESTFILE;
+ close LOCALIZEPARTICLE;
+ close ALLPARTICLES_MERGED;
+
+ #print STDOUT "DBG: \$localizeSDF $localizeSDF \$particleSDF_merged $particleSDF_merged\n";
+ unlink $localizeSDF , $particleSDF_merged , $my_localize_log;
+
+ #sort_outfile( $outputfile );
+ #remove_obsolete( $outputfile ) , if $bHasSourceLanguage ne "";
+ }
+
+#########################################################
+sub remove_obsolete{
+ my $outfile = shift;
+ my @lines;
+ my $enusleftpart;
+ my @good_lines;
+
+ print STDOUT "### Removing obsolete strings\n";
+
+ # Kick out all strings without en-US reference
+ if ( open ( SORTEDFILE , "< $outfile" ) ){
+ while( <SORTEDFILE> ){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $language = defined $12 ? $12 : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ my $leftpart = $prj.$gid.$lid.$file.$type.$plattform.$helpid;
+
+ if( $language eq "en-US" ){ # source string found, 1. entry
+ $enusleftpart = $leftpart;
+ push @good_lines , $line;
+ }else{
+ if( !defined $enusleftpart or !defined $leftpart ){
+ print STDERR "BADLINE: $line\n";
+ print STDERR "\$enusleftpart = $enusleftpart\n";
+ print STDERR "\$leftpart = $leftpart\n";
+ }
+ if( $enusleftpart eq $leftpart ){ # matching language
+ push @good_lines , $line;
+ }
+ #else{
+ # print STDERR "OUT: \$enusleftpart=$enusleftpart \$leftpart=$leftpart \$line=$line\n";
+ #}
+ }
+ }
+ }
+ close SORTEDFILE;
+ } else { print STDERR "ERROR: Can't open file $outfile\n";}
+
+ # Write file
+ if ( open ( SORTEDFILE , "> $outfile" ) ){
+ foreach my $newline ( @good_lines ) {
+ print SORTEDFILE $newline;
+ }
+ close SORTEDFILE;
+ } else { print STDERR "ERROR: Can't open file $outfile\n";}
+
+}
+#########################################################
+sub sort_outfile{
+ my $outfile = shift;
+ print STDOUT "### Sorting ... $outfile ...";
+ my @lines;
+ my @sorted_lines;
+
+
+ #if ( open ( SORTEDFILE , "< $outputfile" ) ){
+ if ( open ( SORTEDFILE , "< $outfile" ) ){
+ my $line;
+ while ( <SORTEDFILE> ){
+ $line = $_;
+ if( $line =~ /^[^\#]/ ){
+ push @lines , $line;
+ }
+ }
+ close SORTEDFILE;
+ @sorted_lines = sort {
+ my $xa_lang = "";
+ my $xa_left_part = "";
+ my $xa_right_part = "";
+ my $xa_timestamp = "";
+ my $xb_lang = "";
+ my $xb_left_part = "";
+ my $xb_right_part = "";
+ my $xb_timestamp = "";
+ my $xa = "";
+ my $xb = "";
+ my @alist;
+ my @blist;
+
+ if( $a=~ /$sdf_regex/ ){
+ $xa_left_part = defined $2 ? $2 : '';
+ $xa_lang = defined $12 ? $12 : '';
+ $xa_right_part = defined $13 ? $13 : '';
+ $xa_left_part = remove_last_column( $xa_left_part );
+
+ }
+ if( $b=~ /$sdf_regex/ ){
+ $xb_left_part = defined $2 ? $2 : '';
+ $xb_lang = defined $12 ? $12 : '';
+ $xb_right_part = defined $13 ? $13 : '';
+ $xb_left_part = remove_last_column( $xb_left_part );
+
+
+ }
+ if( ( $xa_left_part cmp $xb_left_part ) == 0 ){ # Left part equal
+ if( ( $xa_lang cmp $xb_lang ) == 0 ){ # Lang equal
+ return ( $xa_right_part cmp $xb_right_part ); # Right part compare
+ }
+ elsif( $xa_lang eq "en-US" ) { return -1; } # en-US wins
+ elsif( $xb_lang eq "en-US" ) { return 1; } # en-US wins
+ else { return $xa_lang cmp $xb_lang; } # lang compare
+ }
+ else {
+ return $xa_left_part cmp $xb_left_part; # Left part compare
+ }
+ } @lines;
+
+ if ( open ( SORTEDFILE , "> $outfile" ) ){
+ print SORTEDFILE get_license_header();
+ foreach my $newline ( @sorted_lines ) {
+ print SORTEDFILE $newline;
+ #print STDOUT $newline;
+ }
+ }
+ close SORTEDFILE;
+ } else { print STDERR "WARNING: Can't open file $outfile\n";}
+ print "done\n";
+
+}
+#########################################################
+sub remove_last_column{
+ my $string = shift;
+ my @alist = split ( "\t" , $string );
+ pop @alist;
+ return join( "\t" , @alist );
+}
+
+#########################################################
+sub rename_language{
+ my $fallbackhashhash_ref = shift;
+ my $cur_fallback = shift;
+ my $cur_lang = shift;
+ my $line;
+
+ foreach my $key( keys ( %{ $fallbackhashhash_ref->{ $cur_fallback } } ) ){
+ $line = $fallbackhashhash_ref->{ $cur_fallback }{ $key };
+ if( $line =~ /$sdf_regex/ ){
+ my $leftpart = defined $2 ? $2 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $rightpart = defined $13 ? $13 : '';
+
+ $fallbackhashhash_ref->{ $cur_lang }{ $key } = $leftpart."\t".$cur_lang."\t".$rightpart;
+ }
+ }
+}
+
+############################################################
+sub remove_duplicates{
+ my $list_ref = shift;
+ my %tmphash;
+ foreach my $key ( @{ $list_ref } ){ $tmphash{ $key } = '' ; }
+ @{$list_ref} = keys( %tmphash );
+}
+
+##############################################################
+sub fetch_fallback{
+ my $sdfparticleslist_ref = shift;
+ my $localizeSDF = shift;
+ my $langhash_ref = shift;
+ my %fallbackhashhash;
+ my $cur_lang;
+ my @langlist;
+
+ foreach my $key ( keys ( %{ $langhash_ref } ) ){
+ $cur_lang = $langhash_ref->{ $key };
+ if ( $cur_lang ne "" ) {
+ push @langlist , $cur_lang;
+ }
+ }
+ remove_duplicates( \@langlist );
+ foreach $cur_lang ( @langlist ){
+ if( $cur_lang eq "en-US" ){
+ read_fallbacks_from_source( $localizeSDF , $cur_lang , \%fallbackhashhash );
+ }
+ }
+
+ # remove de / en-US
+ my @tmplist;
+ foreach $cur_lang( @langlist ){
+ if( $cur_lang ne "en-US" ){
+ push @tmplist , $cur_lang;
+
+ }
+ }
+ @langlist = @tmplist;
+ if ( $#langlist +1 ){
+ read_fallbacks_from_particles( $sdfparticleslist_ref , \@langlist , \%fallbackhashhash );
+
+ }
+ return (\%fallbackhashhash);
+}
+
+#########################################################
+sub write_file{
+
+ my $localizeFile = shift;
+ my $index_ref = shift;
+
+ if( open DESTFILE , "+> $localizeFile" ){
+ foreach my $key( %{ $index_ref } ){
+ print DESTFILE ($index_ref->{ $key }, "\n" );
+ }
+ close DESTFILE;
+ }else {
+ print STDERR "Can't open/create '$localizeFile'";
+ }
+}
+
+#########################################################
+sub read_file{
+
+ my $sdffile = shift;
+ my $langhash_ref = shift;
+ my %block = ();
+
+ open MYFILE , "< $sdffile"
+ or die "Can't open '$sdffile'\n";
+ while( <MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ foreach my $isolang ( keys ( %{ $langhash_ref } ) ){
+ if( $isolang=~ /$lang/i || $isolang=~ /all/i ) { $block{$prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ; }
+ }
+ }
+ }
+ return (\%block);
+}
+
+#########################################################
+sub read_fallbacks_from_particles{
+
+ my $sdfparticleslist_ref = shift;
+ my $isolanglist_ref = shift;
+ my $fallbackhashhash_ref = shift;
+ my $block_ref;
+ foreach my $currentfile ( @{ $sdfparticleslist_ref } ){
+ if ( open MYFILE , "< $currentfile" ) {
+ while(<MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ chomp( $line );
+
+ foreach my $isolang ( @{$isolanglist_ref} ){
+ if( $isolang=~ /$lang/i ) {
+ $fallbackhashhash_ref->{ $isolang }{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ;
+ }
+ }
+ }
+ }
+ }else { print STDERR "WARNING: Can't open file $currentfile"; }
+ }
+}
+
+#########################################################
+sub read_fallbacks_from_source{
+
+ my $sdffile = shift;
+ my $isolang = shift;
+ my $fallbackhashhash_ref = shift;
+ my $block_ref;
+ # read fallback for single file
+ open MYFILE , "< $sdffile"
+ or die "Can't open '$sdffile'\n";
+
+ while( <MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $helpid = defined $9 ? $9 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+
+ chomp( $line );
+ if( $isolang=~ /$lang/i ) { $fallbackhashhash_ref->{ $isolang }{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ;
+ }
+ }
+ }
+}
+
+#########################################################
+sub parseLanguages{
+
+ my $bAll;
+ my $bUseLocalize;
+ my $bHasSourceLanguage="";
+ my $bFakeEnglish="";
+ my %langhash;
+ my $iso="";
+ my $fallback="";
+
+ #### -l all
+ if( $languages=~ /all/ ){
+ $bAll = "TRUE";
+ $bHasSourceLanguage = "TRUE";
+ }
+ ### -l fr=de,de
+ elsif( $languages=~ /.*,.*/ ){
+ my @tmpstr = split "," , $languages;
+ for my $lang ( @tmpstr ){
+ if( $lang=~ /([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)(=([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*))?/ ){
+ $iso = $1;
+ $fallback = $4;
+
+ if( ( $iso && $iso=~ /(en-US)/i ) || ( $fallback && $fallback=~ /(en-US)/i ) ) {
+ $bUseLocalize = "TRUE";
+ }
+ if( ( $iso && $iso=~ /(en-US)/i ) ) {
+ $bHasSourceLanguage = "TRUE";
+ }
+ if( $fallback ) { $langhash{ $iso } = $fallback; }
+ else { $langhash{ $iso } = ""; }
+ }
+ }
+ }
+ ### -l de
+ else{
+ if( $languages=~ /([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)(=([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*))?/ ){
+ $iso = $1;
+ $fallback = $4;
+
+ if( ( $iso && $iso=~ /(en-US)/i ) || ( $fallback && $fallback=~ /(en-US)/i ) ) {
+ $bUseLocalize = "TRUE";
+
+ }
+ if( ( $iso && $iso=~ /(en-US)/i ) ) {
+ $bHasSourceLanguage = "TRUE";
+ }
+
+ if( $fallback ) { $langhash{ $iso } = $fallback; }
+ else { $langhash{ $iso } = ""; }
+ }
+ }
+ # HACK en-US always needed!
+ if( !$bHasSourceLanguage ){
+ #$bHasSourceLanguage = "TRUE";
+ $bUseLocalize = "TRUE";
+ $bFakeEnglish = "TRUE";
+ $langhash{ "en-US" } = "";
+ }
+ return ( $bAll , $bUseLocalize , \%langhash , $bHasSourceLanguage, $bFakeEnglish);
+}
+
+#########################################################
+sub parse_options{
+
+ my $help;
+ my $merge;
+ my $extract;
+ my $success = GetOptions('f=s' => \$sdffile , 'l=s' => \$languages , 's=s' => \$srcpath , 'h' => \$help , 'v' => \$bVerbose ,
+ 'm' => \$merge , 'e' => \$extract , 'x' => \$no_sort , 'd' => \$use_default_date , 'c' => \$create_dirs ,
+ 'n' => \$no_gsicheck , 'o' => \$force_ooo_module );
+ $outputfile = $sdffile;
+
+ #print STDOUT "DBG: lang = $languages\n";
+ if( !$srcpath ){
+ $srcpath = "$ENV{SRC_ROOT}";
+ if( !$srcpath ){
+ print STDERR "No path to the source root found!\n\n";
+ usage();
+ exit(1);
+ }
+ }
+ if( $help ){
+ usage();
+ exit(0);
+ }
+ if( !$success || $#ARGV > 1 || ( !$sdffile ) ){
+ usage();
+ exit(1);
+ }
+ if( $merge && $sdffile && ! ( -r $sdffile)){
+ print STDERR "Can't open file '$sdffile'\n";
+ exit(1);
+ }
+ if( !( $languages=~ /[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*(=[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)?(,[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*(=[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)?)*/ ) ){
+ print STDERR "Please check the -l iso code\n";
+ exit(1);
+ }
+ if( ( !$merge && !$extract ) || ( $merge && $extract ) ){ usage();exit( -1 );}
+ if( $extract ){ $mode = "extract"; }
+ else { $mode = "merge"; }
+}
+#my $multi_localize_files = ''; h
+#my $module_to_merge = ''; i
+#my $sort_sdf_before = ''; g
+
+#########################################################
+sub usage{
+
+ print STDERR "Usage: localize.pl\n";
+ print STDERR "Split or collect SDF files\n";
+ print STDERR " merge: -m -f <sdffile> -l l1[=f1][,l2[=f2]][...] [ -s <sourceroot> ] [ -c ]\n";
+ print STDERR " extract: -e -f <outputfile> -l <lang> [ -s <sourceroot> ] [-d]\n";
+ print STDERR "Options:\n";
+ print STDERR " -h help\n";
+ print STDERR " -m Merge mode\n";
+ print STDERR " -e Extract mode\n";
+ print STDERR " -f <sdffile> To split a big SDF file into particles\n";
+ print STDERR " <outputfile> To collect and join all particles to one big file\n";
+ print STDERR " -s <sourceroot> Path to the modules, if no \$SRC_ROOT is set\n";
+ print STDERR " -l ( all | <isocode> | <isocode>=fallback ) comma seperated languages\n";
+ print STDERR " -d Use default date in extracted sdf file\n";
+ print STDERR " -c Create needed directories\n";
+ print STDERR " -g Sort sdf file before mergeing\n";
+ print STDERR " -h File with localize.sdf's\n!";
+ print STDERR " -n No gsicheck\n";
+ print STDERR " -i Module to merge\n";
+ print STDERR " -o force using ooo localization from the l10n module instead of l10n_so; \n";
+ print STDERR " useful if the type can't be detected by the .svn tags; \n";
+ print STDERR " -v Verbose\n";
+ print STDERR "\nExample:\n";
+ print STDERR "\nlocalize -e -l en-US,pt-BR=en-US -f my.sdf\n( Extract en-US and pt-BR with en-US fallback )\n";
+ print STDERR "\nlocalize -m -l cs -f my.sdf\n( Merge cs translation into the sourcecode ) \n";
+}
+
+# my $line = defined $_ ? $_ : '';
+# my $leftpart = defined $2 ? $2 : '';
+# my $prj = defined $3 ? $3 : '';
+# my $file = defined $4 ? $4 : '';
+# my $dummy = defined $5 ? $5 : '';
+# my $type = defined $6 ? $6 : '';
+# my $gid = defined $7 ? $7 : '';
+# my $lid = defined $8 ? $8 : '';
+# my $helpid = defined $9 ? $9 : '';
+# my $plattform = defined $10 ? $10 : '';
+# my $width = defined $11 ? $11 : '';
+# my $lang = defined $12 ? $12 : '';
+# my $rightpart = defined $13 ? $13 : '';
+# my $text = defined $14 ? $14 : '';
+# my $helptext = defined $15 ? $15 : '';
+# my $quickhelptext = defined $16 ? $16 : '';
+# my $title = defined $17 ? $17 : '';
+# my $timestamp = defined $18 ? $18 : '';
+
diff --git a/l10ntools/scripts/localize_old.pl b/l10ntools/scripts/localize_old.pl
new file mode 100755
index 000000000000..151399d22002
--- /dev/null
+++ b/l10ntools/scripts/localize_old.pl
@@ -0,0 +1,1130 @@
+:
+eval 'exec perl -wS $0 ${1+"$@"}'
+ if 0;
+
+
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: localize.pl,v $
+#
+# $Revision: 1.18 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+use strict;
+use Getopt::Long;
+use IO::Handle;
+use File::Find;
+use File::Temp;
+use File::Copy;
+use File::Glob qw(:glob csh_glob);
+use Cwd;
+
+# ver 1.1
+#
+#### module lookup
+#use lib ("$ENV{SOLARENV}/bin/modules", "$ENV{COMMON_ENV_TOOLS}/modules");
+
+#### module lookup
+# OOo conform
+my @lib_dirs;
+BEGIN {
+ if ( !defined($ENV{SOLARENV}) ) {
+ die "No environment found (environment variable SOLARENV is undefined)";
+ }
+ push(@lib_dirs, "$ENV{SOLARENV}/bin/modules");
+ push(@lib_dirs, "$ENV{COMMON_ENV_TOOLS}/modules") if defined($ENV{COMMON_ENV_TOOLS});
+}
+use lib (@lib_dirs);
+
+#### globals ####
+my $sdffile = '';
+my $no_sort = '';
+my $outputfile = '';
+my $mode = '';
+my $bVerbose="0";
+my $srcpath = '';
+my $WIN;
+my $languages;
+#my %sl_modules; # Contains all modules where en-US and de is source language
+my $use_default_date = '0';
+
+ # ( leftpart ) ( rightpart )
+ # prj file dummy type gid lid helpid pform width lang text helptext qhelptext title timestamp
+my $sdf_regex = "((([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*))\t([^\t]*)\t(([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t)([^\t]*))";
+my $file_types = "(src|hrc|xcs|xcu|lng|ulf|xrm|xhp|xcd|xgf|xxl|xrb)";
+# Always use this date to prevent cvs conflicts
+my $default_date = "2002-02-02 02:02:02";
+
+#### main ####
+parse_options();
+
+if ( defined $ENV{USE_SHELL} && $ENV{USE_SHELL} eq '4nt' ) {
+ $WIN = 'TRUE';
+}
+ else {
+ $WIN = '';
+}
+
+#%sl_modules = fetch_sourcelanguage_dirlist();
+
+
+if ( $mode eq "merge" ) {
+ merge_gsicheck();
+ splitfile( $sdffile );
+ unlink $sdffile; # remove temp file!
+}
+elsif( $mode eq "extract" ) {
+ collectfiles( $outputfile );
+}
+else {
+ usage();
+}
+
+exit(0);
+
+#########################################################
+sub splitfile{
+
+ my $lastFile = '';
+ my $currentFile = '';
+ my $cur_sdffile = '';
+ my $last_sdffile = '';
+ my $delim;
+ my $badDelim;
+ my $start = 'TRUE';
+ my %index = ();
+ my %block;
+
+ STDOUT->autoflush( 1 );
+
+ #print STDOUT "Open File $sdffile\n";
+ open MYFILE , "< $sdffile"
+ or die "Can't open '$sdffile'\n";
+
+ while( <MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ next if( $prj eq "binfilter" ); # Don't merge strings into binfilter module
+ chomp( $line );
+ $currentFile = $srcpath . '\\' . $prj . '\\' . $file;
+ if ( $WIN ) { $currentFile =~ s/\//\\/g; }
+ else { $currentFile =~ s/\\/\//g; }
+
+ $cur_sdffile = $currentFile;
+ #if( $cur_sdffile =~ /\.$file_types[\s]*$/ ){
+ if( $WIN ) { $cur_sdffile =~ s/\\[^\\]*\.$file_types[\s]*$/\\localize.sdf/; }
+ else { $cur_sdffile =~ s/\/[^\/]*\.$file_types[\s]*$/\/localize.sdf/; }
+ #}
+
+ # Set default date
+ if( $line =~ /(.*)\t[^\t\$]*$/ ){
+ $line = $1."\t".$default_date;
+ }
+
+ if( $start ){
+ $start='';
+ $lastFile = $currentFile; # ?
+ $last_sdffile = $cur_sdffile;
+ }
+
+ if( $lang eq "en-US" ){}
+ elsif( $cur_sdffile eq $last_sdffile )
+ {
+ $block{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } = $line ;
+ }
+ else
+ {
+ writesdf( $lastFile , \%block );
+ $lastFile = $currentFile; #?
+ $last_sdffile = $cur_sdffile;
+ %block = ();
+ #if( ! $lang eq "en-US" ) {
+ $block{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } = $line ;
+ #}
+
+ }
+ } #else { print STDOUT "splitfile REGEX kaputt\n";}
+
+ }
+ writesdf( $lastFile , \%block );
+ %block = ();
+ close( MYFILE );
+
+}
+#########################################################
+
+#sub fetch_sourcelanguage_dirlist
+#{
+#
+# my $working_path = getcwd();
+# my %sl_dirlist;
+#
+# chdir $srcpath;
+# my @all_dirs = csh_glob( "*" );
+#
+# foreach my $file ( @all_dirs )
+# {
+# if( -d $file )
+# {
+# my $module = $file;
+# $file .= "/prj/l10n";
+# $file =~ s/\//\\/ , if( $WIN ) ;
+#
+# if( -f $file ) # Test file <module>/prj/l10n
+# {
+# $sl_dirlist{ $module } = 1;
+# if( $bVerbose eq "1" ) { print STDOUT "$module: de and en-US source language detected\n"; }
+# }
+# }
+# }
+#
+# chdir $working_path;
+#
+# return %sl_dirlist;
+#}
+
+#sub has_two_sourcelanguages
+#{
+# my $module = shift;
+# return defined $sl_modules{ $module } ;
+#}
+sub writesdf{
+
+ my $lastFile = shift;
+ my $blockhash_ref = shift;
+ my $localizeFile = $lastFile;
+ my %index=();
+
+ if( $localizeFile =~ /\.$file_types[\s]*$/ ){
+ if( $WIN ) { $localizeFile =~ s/\\[^\\]*\.$file_types[\s]*$/\\localize.sdf/; }
+ else { $localizeFile =~ s/\/[^\/]*\.$file_types[\s]*$/\/localize.sdf/; }
+ }else {
+ print STDERR "Strange filetype found '$localizeFile'\n";
+ return;
+ }
+ if( open DESTFILE , "< $localizeFile" ){
+
+ #or die "Can't open/create '\$localizeFile'";
+
+ #### Build hash
+ while(<DESTFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ chomp( $line );
+ $index{ "$prj\t$file\t$type\t$gid\t$lid\t$helpid\t$plattform\t$lang" } = $line ;
+
+ } #else { print STDOUT "writesdf REGEX kaputt $_\n";}
+
+ }
+ close( DESTFILE );
+ }
+ #### Copy new strings
+ my @mykeys = keys( %{ $blockhash_ref } );
+ my $isDirty = "FALSE";
+ foreach my $key( @mykeys ){
+ if( ! defined $index{ $key } ){
+ # Add new entry
+ $index{ $key } = $blockhash_ref->{ $key} ;
+ $isDirty = "TRUE";
+ }elsif( $index{ $key } ne $blockhash_ref->{ $key } ){
+ # Overwrite old entry
+ $index{ $key } = $blockhash_ref->{ $key };
+ $isDirty = "TRUE";
+ }else {
+ }
+ }
+
+ #### Write file
+
+ if( !$bVerbose ){ print STDOUT "."; }
+ if( $isDirty eq "TRUE" ){
+ if( $bVerbose ){ print STDOUT "$localizeFile\n"; }
+ if( open DESTFILE , "+> $localizeFile" ){
+ print DESTFILE get_license_header();
+ @mykeys = sort keys( %index );
+ foreach my $key( @mykeys ){
+ print DESTFILE ( $index{ $key } , "\n" );
+ }
+ close DESTFILE;
+ }else {
+ print STDOUT "WARNING: File $localizeFile is not writable , try to merge ...\n";
+ my ( $TMPFILE , $tmpfile ) = File::Temp::tempfile();
+ if( open DESTFILE , "+> $tmpfile " ){
+ @mykeys = keys( %index );
+ foreach my $key( @mykeys ){
+ print DESTFILE ( $index{ $key } , "\n" );
+ }
+ close DESTFILE;
+ if( move( $localizeFile , $localizeFile.".backup" ) ){
+ if( copy( $tmpfile , $localizeFile ) ){
+ unlink $localizeFile.".backup";
+ } else { print STDERR "Can't open/create '$localizeFile', original file is renamed to $localizeFile.backup\n"; }
+ } else { print STDERR "Can't open/create '$localizeFile'\n"; }
+ }else{
+ print STDERR "WARNING: Can't open/create '$localizeFile'\n";
+ }
+ unlink $tmpfile;
+ }
+ }
+# if( $no_sort eq '' ){
+# sort_outfile( $localizeFile );
+# }
+}
+
+sub get_license_header{
+ return
+"#\n".
+"# #### ### # # ### ##### ##### #### ##### ##### \n".
+"# # # # # ## # # # # # # # # # \n".
+"# # # # # # # # # # # ### # # # # \n".
+"# # # # # # ## # # # # # # # # \n".
+"# #### ### # # ### # ##### #### ##### # \n".
+"#\n".
+"# DO NOT EDIT! This file will be overwritten by localisation process\n".
+"#\n".
+"#*************************************************************************\n".
+"#\n".
+"# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n".
+"# \n".
+"# Copyright 2008 by Sun Microsystems, Inc.\n".
+"#\n".
+"# OpenOffice.org - a multi-platform office productivity suite\n".
+"#\n".
+"# \$RCSfile:".
+"localize.pl,v \$\n".
+"#\n".
+"# \$Revision: ".
+"1.17.4.1 \$\n".
+"#\n".
+"# This file is part of OpenOffice.org.\n".
+"#\n".
+"# OpenOffice.org is free software: you can redistribute it and/or modify\n".
+"# it under the terms of the GNU Lesser General Public License version 3\n".
+"# only, as published by the Free Software Foundation.\n".
+"#\n".
+"# OpenOffice.org is distributed in the hope that it will be useful,\n".
+"# but WITHOUT ANY WARRANTY; without even the implied warranty of\n".
+"# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n".
+"# GNU Lesser General Public License version 3 for more details\n".
+"# (a copy is included in the LICENSE file that accompanied this code).\n".
+"#\n".
+"# You should have received a copy of the GNU Lesser General Public License\n".
+"# version 3 along with OpenOffice.org. If not, see\n".
+"# <http://www.openoffice.org/license.html>\n".
+"# for a copy of the LGPLv3 License.\n".
+"#\n".
+"#*************************************************************************\n";
+}
+######## Check input sdf file and use only the correct part
+sub merge_gsicheck{
+ my $command = '';
+ my ( $TMPHANDLE , $tmpfile ) = File::Temp::tempfile();
+ my ( $TMPHANDLE2 , $tmpfile2 ) = File::Temp::tempfile();
+ close ( $TMPHANDLE );
+ close ( $TMPHANDLE2 );
+
+ unlink $tmpfile2;
+ my $output2 = `cat $sdffile | sort > $tmpfile2`;
+ my $rc2 = $? << 8;
+ if( $rc2 ne 0 ){
+ printf("ERROR: Failed -> cat $sdffile | sort > $tmpfile2\n$output2\n");
+ exit( -1 );
+ }
+
+# if( $ENV{WRAPCMD} ){
+# $command = "$ENV{WRAPCMD} gsicheck";
+# }else{
+# $command = "gsicheck";
+# }
+# my $errfile = $tmpfile.".err";
+# $command .= " -k -c -wcf $tmpfile -wef $errfile -l \"\" $tmpfile2";
+# my $output = `$command`;
+# my $rc = $? << 8;
+# if ( $output ne "" ){
+# print STDOUT "### gsicheck ###\n";
+# print STDOUT "### The file $errfile have been written containing the errors in your sdf file. Those lines will not be merged: ###\n\n";
+# print STDOUT "$output\n";
+# print STDOUT "################\n";
+#
+# }else{
+# # Remove the 0 Byte file
+# unlink $errfile;
+# }
+ $sdffile = $tmpfile2;
+# unlink $tmpfile2;
+}
+#########################################################
+sub collectfiles{
+ print STDOUT "### Localize\n";
+ my @sdfparticles;
+ my $localizehash_ref;
+ my ( $bAll , $bUseLocalize, $langhash_ref , $bHasSourceLanguage , $bFakeEnglish ) = parseLanguages();
+
+ # Enable autoflush on STDOUT
+ # $| = 1;
+ STDOUT->autoflush( 1 );
+
+ ### Search sdf particles
+ print STDOUT "### Searching sdf particles\n";
+ my $working_path = getcwd();
+ chdir $srcpath;
+ find sub {
+ my $file = $File::Find::name;
+ if( -f && $file =~ /.*localize.sdf$/ ) {
+ push @sdfparticles , $file;
+ if( $bVerbose eq "1" ) { print STDOUT "$file\n"; }
+ else { print "."; }
+
+ }
+ } , getcwd() ;#"."; #$srcpath;
+ chdir $working_path;
+
+ my $nFound = $#sdfparticles +1;
+ print "\n $nFound files found !\n";
+
+ my ( $LOCALIZEPARTICLE , $localizeSDF ) = File::Temp::tempfile();
+ close( $LOCALIZEPARTICLE );
+
+ my ( $ALLPARTICLES_MERGED , $particleSDF_merged ) = File::Temp::tempfile();
+ close( $ALLPARTICLES_MERGED );
+ my ( $LOCALIZE_LOG , $my_localize_log ) = File::Temp::tempfile();
+ close( $LOCALIZE_LOG );
+
+ ## Get the localize de,en-US extract
+ if( $bAll || $bUseLocalize ){
+ print "### Fetching source language strings\n";
+ my $command = "";
+ my $args = "";
+
+ if( $ENV{WRAPCMD} ){
+ $command = "$ENV{WRAPCMD} localize_sl";
+ }else{
+ $command = "localize_sl";
+ }
+
+ # -e
+ # if ( -x $command ){
+ if( $command ){
+ if( !$bVerbose ){ $args .= " -QQ -skip_links "; }
+ $args .= " -e -f $localizeSDF -l ";
+ my $bFlag="";
+ if( $bAll ) {$args .= " en-US";}
+ else{
+ my @list;
+ foreach my $isokey ( keys( %{ $langhash_ref } ) ){
+ push @list , $isokey;
+ if( $langhash_ref->{ $isokey } ne "" ){
+ push @list , $langhash_ref->{ $isokey };
+ }
+ }
+ remove_duplicates( \@list );
+ foreach my $isokey ( @list ){
+ switch :{
+ #( $isokey=~ /^de$/i )
+ # && do{
+ # if( $bFlag eq "TRUE" ){ $args .= ",de"; }
+ # else {
+ # $args .= "de"; $bFlag = "TRUE";
+ # }
+ # };
+ ( $isokey=~ /^en-US$/i )
+ && do{
+ if( $bFlag eq "TRUE" ){ $args .= ",en-US"; }
+ else {
+ $args .= "en-US"; $bFlag = "TRUE";
+ }
+ };
+
+ } #switch
+ } #foreach
+ } # if
+ } # if
+# if ( !$bVerbose ){
+# if ( $WIN eq "TRUE" ) { $args .= " > $my_localize_log"; }
+# else { $args .= " >& $my_localize_log"; }
+# }
+ if ( $bVerbose ) { print STDOUT $command.$args."\n"; }
+
+ my $rc = system( $command.$args );
+
+ #my $output = `$command.$args`;
+ #my $rc = $? << 8;
+
+ if( $rc < 0 ){ print STDERR "ERROR: localize rc = $rc\n"; exit( -1 ); }
+ ( $localizehash_ref ) = read_file( $localizeSDF , $langhash_ref );
+
+ }
+ ## Get sdf particles
+ open ALLPARTICLES_MERGED , "+>> $particleSDF_merged"
+ or die "Can't open $particleSDF_merged";
+
+ ## Fill fackback hash
+ my( $fallbackhashhash_ref ) = fetch_fallback( \@sdfparticles , $localizeSDF , $langhash_ref );
+# my( $fallbackhashhash_ref ) = fetch_fallback( \@sdfparticles , $localizeSDF , $langhash_ref );
+ my %block;
+ my $cur_fallback;
+ if( !$bAll) {
+ foreach my $cur_lang ( keys( %{ $langhash_ref } ) ){
+ #print STDOUT "DBG: G1 cur_lang=$cur_lang\n";
+ $cur_fallback = $langhash_ref->{ $cur_lang };
+ if( $cur_fallback ne "" ){
+ # Insert fallback strings
+ #print STDOUT "DBG: Renaming $cur_fallback to $cur_lang in fallbackhash\n";
+ rename_language( $fallbackhashhash_ref , $cur_fallback , $cur_lang );
+ }
+ foreach my $currentfile ( @sdfparticles ){
+ if ( open MYFILE , "< $currentfile" ) {
+ while(<MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ chomp( $line );
+
+ if ( $lang eq $cur_lang ){
+ # Overwrite fallback strings with collected strings
+ #if( ( !has_two_sourcelanguages( $cur_lang) && $cur_lang eq "de" ) || $cur_lang ne "en-US" ){
+ $fallbackhashhash_ref->{ $cur_lang }{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ;
+ #}
+
+ }
+ }
+ }
+ }else { print STDERR "WARNING: Can't open file $currentfile"; }
+ }
+
+ foreach my $line ( keys( %{$fallbackhashhash_ref->{ $cur_lang } } )) {
+ if( #$cur_lang ne "de" &&
+ $cur_lang ne "en-US" ){
+ print ALLPARTICLES_MERGED ( $fallbackhashhash_ref->{ $cur_lang }{ $line }, "\n" );
+ }
+ }
+ }
+ } else {
+ foreach my $currentfile ( @sdfparticles ){
+ if ( open MYFILE , "< $currentfile" ) {
+ while( <MYFILE> ){
+ print ALLPARTICLES_MERGED ( $_, "\n" ); # recheck de / en-US !
+ }
+ }
+ else { print STDERR "WARNING: Can't open file $currentfile"; }
+ }
+ }
+ close ALLPARTICLES_MERGED;
+
+
+ # Hash of array
+ my %output;
+ my @order;
+
+ ## Join both
+ if( $outputfile ){
+ if( open DESTFILE , "+> $outputfile" ){
+ if( !open LOCALIZEPARTICLE , "< $localizeSDF" ) { print STDERR "ERROR: Can't open file $localizeSDF\n"; }
+ if( !open ALLPARTICLES_MERGED , "< $particleSDF_merged" ) { print STDERR "ERROR: Can't open file $particleSDF_merged\n"; }
+
+ # Insert localize
+ my $extract_date="";
+ while ( <LOCALIZEPARTICLE> ){
+ if( /$sdf_regex/ ){
+ my $leftpart = defined $2 ? $2 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $rightpart = defined $13 ? $13 : '';
+ my $timestamp = defined $18 ? $18 : '';
+
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ #my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+
+ if( $use_default_date )
+ {
+ $extract_date = "$default_date\n" ;
+ }
+ elsif( $extract_date eq "" ) {
+ $extract_date = $timestamp ;
+ $extract_date =~ tr/\r\n//d;
+ $extract_date .= "\n";
+ }
+
+ if( $bAll ){ print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date ; }
+ else {
+ foreach my $sLang ( keys( %{ $langhash_ref } ) ){
+ if( $sLang=~ /all/i ) {
+ push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ;
+ #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date;
+ }
+ #if( $sLang eq "de" && $lang eq "de" ) {
+ # push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ;
+ #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date;
+ #}
+ if( $sLang eq "en-US" && $lang eq "en-US" ) {
+ push @order , $prj.$gid.$lid.$file.$type.$plattform.$helpid;
+ if( !$bFakeEnglish ){ push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ; }
+ #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date;
+ }
+
+ }
+ }
+ }
+ }
+ # Insert particles
+ while ( <ALLPARTICLES_MERGED> ){
+ if( /$sdf_regex/ ){
+ my $leftpart = defined $2 ? $2 : '';
+ my $prj = defined $3 ? $3 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $rightpart = defined $13 ? $13 : '';
+ my $timestamp = defined $18 ? $18 : '';
+
+ #my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ #my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+
+ if( $use_default_date )
+ {
+ $extract_date = "$default_date\n" ;
+ }
+ elsif( $extract_date eq "" )
+ {
+ $extract_date = $timestamp;
+ }
+
+ if( ! ( $prj =~ /binfilter/i ) ) {
+ push @{ $output{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } } , $leftpart."\t".$lang."\t".$rightpart.$extract_date ;
+ #print DESTFILE $leftpart."\t".$lang."\t".$rightpart.$extract_date ;
+ }
+ }
+ }
+
+ # Write!
+ foreach my $curkey ( @order ){
+ foreach my $curlist ( $output{ $curkey } ){
+ foreach my $line ( @{$curlist} ){
+ print DESTFILE $line;
+ }
+ }
+ }
+
+ }else { print STDERR "Can't open $outputfile";}
+ }
+ close DESTFILE;
+ close LOCALIZEPARTICLE;
+ close ALLPARTICLES_MERGED;
+
+ #print STDOUT "DBG: \$localizeSDF $localizeSDF \$particleSDF_merged $particleSDF_merged\n";
+ unlink $localizeSDF , $particleSDF_merged , $my_localize_log;
+
+ #sort_outfile( $outputfile );
+ #remove_obsolete( $outputfile ) , if $bHasSourceLanguage ne "";
+ }
+
+#########################################################
+sub remove_obsolete{
+ my $outfile = shift;
+ my @lines;
+ my $enusleftpart;
+ my @good_lines;
+
+ print STDOUT "### Removing obsolete strings\n";
+
+ # Kick out all strings without en-US reference
+ if ( open ( SORTEDFILE , "< $outfile" ) ){
+ while( <SORTEDFILE> ){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $language = defined $12 ? $12 : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ my $leftpart = $prj.$gid.$lid.$file.$type.$plattform.$helpid;
+
+ if( $language eq "en-US" ){ # source string found, 1. entry
+ $enusleftpart = $leftpart;
+ push @good_lines , $line;
+ }else{
+ if( !defined $enusleftpart or !defined $leftpart ){
+ print STDERR "BADLINE: $line\n";
+ print STDERR "\$enusleftpart = $enusleftpart\n";
+ print STDERR "\$leftpart = $leftpart\n";
+ }
+ if( $enusleftpart eq $leftpart ){ # matching language
+ push @good_lines , $line;
+ }
+ #else{
+ # print STDERR "OUT: \$enusleftpart=$enusleftpart \$leftpart=$leftpart \$line=$line\n";
+ #}
+ }
+ }
+ }
+ close SORTEDFILE;
+ } else { print STDERR "ERROR: Can't open file $outfile\n";}
+
+ # Write file
+ if ( open ( SORTEDFILE , "> $outfile" ) ){
+ foreach my $newline ( @good_lines ) {
+ print SORTEDFILE $newline;
+ }
+ close SORTEDFILE;
+ } else { print STDERR "ERROR: Can't open file $outfile\n";}
+
+}
+#########################################################
+sub sort_outfile{
+ my $outfile = shift;
+ print STDOUT "### Sorting ... $outfile ...";
+ my @lines;
+ my @sorted_lines;
+
+
+ #if ( open ( SORTEDFILE , "< $outputfile" ) ){
+ if ( open ( SORTEDFILE , "< $outfile" ) ){
+ my $line;
+ while ( <SORTEDFILE> ){
+ $line = $_;
+ if( $line =~ /^[^\#]/ ){
+ push @lines , $line;
+ }
+ }
+ close SORTEDFILE;
+ @sorted_lines = sort {
+ my $xa_lang = "";
+ my $xa_left_part = "";
+ my $xa_right_part = "";
+ my $xa_timestamp = "";
+ my $xb_lang = "";
+ my $xb_left_part = "";
+ my $xb_right_part = "";
+ my $xb_timestamp = "";
+ my $xa = "";
+ my $xb = "";
+ my @alist;
+ my @blist;
+
+ if( $a=~ /$sdf_regex/ ){
+ $xa_left_part = defined $2 ? $2 : '';
+ $xa_lang = defined $12 ? $12 : '';
+ $xa_right_part = defined $13 ? $13 : '';
+ $xa_left_part = remove_last_column( $xa_left_part );
+
+ }
+ if( $b=~ /$sdf_regex/ ){
+ $xb_left_part = defined $2 ? $2 : '';
+ $xb_lang = defined $12 ? $12 : '';
+ $xb_right_part = defined $13 ? $13 : '';
+ $xb_left_part = remove_last_column( $xb_left_part );
+
+
+ }
+ if( ( $xa_left_part cmp $xb_left_part ) == 0 ){ # Left part equal
+ if( ( $xa_lang cmp $xb_lang ) == 0 ){ # Lang equal
+ return ( $xa_right_part cmp $xb_right_part ); # Right part compare
+ }
+ elsif( $xa_lang eq "en-US" ) { return -1; } # en-US wins
+ elsif( $xb_lang eq "en-US" ) { return 1; } # en-US wins
+ else { return $xa_lang cmp $xb_lang; } # lang compare
+ }
+ else {
+ return $xa_left_part cmp $xb_left_part; # Left part compare
+ }
+ } @lines;
+
+ if ( open ( SORTEDFILE , "> $outfile" ) ){
+ print SORTEDFILE get_license_header();
+ foreach my $newline ( @sorted_lines ) {
+ print SORTEDFILE $newline;
+ #print STDOUT $newline;
+ }
+ }
+ close SORTEDFILE;
+ } else { print STDERR "WARNING: Can't open file $outfile\n";}
+ print "done\n";
+
+}
+#########################################################
+sub remove_last_column{
+ my $string = shift;
+ my @alist = split ( "\t" , $string );
+ pop @alist;
+ return join( "\t" , @alist );
+}
+
+#########################################################
+sub rename_language{
+ my $fallbackhashhash_ref = shift;
+ my $cur_fallback = shift;
+ my $cur_lang = shift;
+ my $line;
+
+ foreach my $key( keys ( %{ $fallbackhashhash_ref->{ $cur_fallback } } ) ){
+ $line = $fallbackhashhash_ref->{ $cur_fallback }{ $key };
+ if( $line =~ /$sdf_regex/ ){
+ my $leftpart = defined $2 ? $2 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $rightpart = defined $13 ? $13 : '';
+
+ $fallbackhashhash_ref->{ $cur_lang }{ $key } = $leftpart."\t".$cur_lang."\t".$rightpart;
+ }
+ }
+}
+
+############################################################
+sub remove_duplicates{
+ my $list_ref = shift;
+ my %tmphash;
+ foreach my $key ( @{ $list_ref } ){ $tmphash{ $key } = '' ; }
+ @{$list_ref} = keys( %tmphash );
+}
+
+##############################################################
+sub fetch_fallback{
+ my $sdfparticleslist_ref = shift;
+ my $localizeSDF = shift;
+ my $langhash_ref = shift;
+ my %fallbackhashhash;
+ my $cur_lang;
+ my @langlist;
+
+ foreach my $key ( keys ( %{ $langhash_ref } ) ){
+ $cur_lang = $langhash_ref->{ $key };
+ if ( $cur_lang ne "" ) {
+ push @langlist , $cur_lang;
+ }
+ }
+ remove_duplicates( \@langlist );
+ foreach $cur_lang ( @langlist ){
+ if( $cur_lang eq "en-US" ){
+ read_fallbacks_from_source( $localizeSDF , $cur_lang , \%fallbackhashhash );
+ }
+ }
+
+ # remove de / en-US
+ my @tmplist;
+ foreach $cur_lang( @langlist ){
+ if( $cur_lang ne "en-US" ){
+ push @tmplist , $cur_lang;
+
+ }
+ }
+ @langlist = @tmplist;
+ if ( $#langlist +1 ){
+ read_fallbacks_from_particles( $sdfparticleslist_ref , \@langlist , \%fallbackhashhash );
+
+ }
+ return (\%fallbackhashhash);
+}
+
+#########################################################
+sub write_file{
+
+ my $localizeFile = shift;
+ my $index_ref = shift;
+
+ if( open DESTFILE , "+> $localizeFile" ){
+ foreach my $key( %{ $index_ref } ){
+ print DESTFILE ($index_ref->{ $key }, "\n" );
+ }
+ close DESTFILE;
+ }else {
+ print STDERR "Can't open/create '$localizeFile'";
+ }
+}
+
+#########################################################
+sub read_file{
+
+ my $sdffile = shift;
+ my $langhash_ref = shift;
+ my %block = ();
+
+ open MYFILE , "< $sdffile"
+ or die "Can't open '$sdffile'\n";
+ while( <MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ foreach my $isolang ( keys ( %{ $langhash_ref } ) ){
+ if( $isolang=~ /$lang/i || $isolang=~ /all/i ) { $block{$prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ; }
+ }
+ }
+ }
+ return (\%block);
+}
+
+#########################################################
+sub read_fallbacks_from_particles{
+
+ my $sdfparticleslist_ref = shift;
+ my $isolanglist_ref = shift;
+ my $fallbackhashhash_ref = shift;
+ my $block_ref;
+ foreach my $currentfile ( @{ $sdfparticleslist_ref } ){
+ if ( open MYFILE , "< $currentfile" ) {
+ while(<MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+ my $helpid = defined $9 ? $9 : '';
+
+ chomp( $line );
+
+ foreach my $isolang ( @{$isolanglist_ref} ){
+ if( $isolang=~ /$lang/i ) {
+ $fallbackhashhash_ref->{ $isolang }{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ;
+ }
+ }
+ }
+ }
+ }else { print STDERR "WARNING: Can't open file $currentfile"; }
+ }
+}
+
+#########################################################
+sub read_fallbacks_from_source{
+
+ my $sdffile = shift;
+ my $isolang = shift;
+ my $fallbackhashhash_ref = shift;
+ my $block_ref;
+ # read fallback for single file
+ open MYFILE , "< $sdffile"
+ or die "Can't open '$sdffile'\n";
+
+ while( <MYFILE>){
+ if( /$sdf_regex/ ){
+ my $line = defined $_ ? $_ : '';
+ my $prj = defined $3 ? $3 : '';
+ my $file = defined $4 ? $4 : '';
+ my $type = defined $6 ? $6 : '';
+ my $gid = defined $7 ? $7 : '';
+ my $lid = defined $8 ? $8 : '';
+ my $helpid = defined $9 ? $9 : '';
+ my $lang = defined $12 ? $12 : '';
+ my $plattform = defined $10 ? $10 : '';
+
+ chomp( $line );
+ if( $isolang=~ /$lang/i ) { $fallbackhashhash_ref->{ $isolang }{ $prj.$gid.$lid.$file.$type.$plattform.$helpid } = $line ;
+ }
+ }
+ }
+}
+
+#########################################################
+sub parseLanguages{
+
+ my $bAll;
+ my $bUseLocalize;
+ my $bHasSourceLanguage="";
+ my $bFakeEnglish="";
+ my %langhash;
+ my $iso="";
+ my $fallback="";
+
+ #### -l all
+ if( $languages=~ /all/ ){
+ $bAll = "TRUE";
+ $bHasSourceLanguage = "TRUE";
+ }
+ ### -l fr=de,de
+ elsif( $languages=~ /.*,.*/ ){
+ my @tmpstr = split "," , $languages;
+ for my $lang ( @tmpstr ){
+ if( $lang=~ /([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)(=([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*))?/ ){
+ $iso = $1;
+ $fallback = $4;
+
+ if( ( $iso && $iso=~ /(en-US)/i ) || ( $fallback && $fallback=~ /(en-US)/i ) ) {
+ $bUseLocalize = "TRUE";
+ }
+ if( ( $iso && $iso=~ /(en-US)/i ) ) {
+ $bHasSourceLanguage = "TRUE";
+ }
+ if( $fallback ) { $langhash{ $iso } = $fallback; }
+ else { $langhash{ $iso } = ""; }
+ }
+ }
+ }
+ ### -l de
+ else{
+ if( $languages=~ /([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)(=([a-zA-Z]{2,3}(-[a-zA-Z\-]*)*))?/ ){
+ $iso = $1;
+ $fallback = $4;
+
+ if( ( $iso && $iso=~ /(en-US)/i ) || ( $fallback && $fallback=~ /(en-US)/i ) ) {
+ $bUseLocalize = "TRUE";
+
+ }
+ if( ( $iso && $iso=~ /(en-US)/i ) ) {
+ $bHasSourceLanguage = "TRUE";
+ }
+
+ if( $fallback ) { $langhash{ $iso } = $fallback; }
+ else { $langhash{ $iso } = ""; }
+ }
+ }
+ # HACK en-US always needed!
+ if( !$bHasSourceLanguage ){
+ #$bHasSourceLanguage = "TRUE";
+ $bUseLocalize = "TRUE";
+ $bFakeEnglish = "TRUE";
+ $langhash{ "en-US" } = "";
+ }
+ return ( $bAll , $bUseLocalize , \%langhash , $bHasSourceLanguage, $bFakeEnglish);
+}
+
+#########################################################
+sub parse_options{
+
+ my $help;
+ my $merge;
+ my $extract;
+ my $success = GetOptions('f=s' => \$sdffile , 'l=s' => \$languages , 's=s' => \$srcpath , 'h' => \$help , 'v' => \$bVerbose ,
+ 'm' => \$merge , 'e' => \$extract , 'x' => \$no_sort , 'd' => \$use_default_date );
+ $outputfile = $sdffile;
+
+ #print STDOUT "DBG: lang = $languages\n";
+ if( !$srcpath ){
+ #$srcpath = "$ENV{SRC_ROOT}";
+ if( !$srcpath ){
+ print STDERR "No path to the source root found!\n\n";
+ usage();
+ exit(1);
+ }
+ }
+ if( $help || !$success || $#ARGV > 1 || ( !$sdffile ) ){
+ usage();
+ exit(1);
+ }
+ if( $merge && $sdffile && ! ( -r $sdffile)){
+ print STDERR "Can't open file '$sdffile'\n";
+ exit(1);
+ }
+ if( !( $languages=~ /[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*(=[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)?(,[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*(=[a-zA-Z]{2,3}(-[a-zA-Z\-]*)*)?)*/ ) ){
+ print STDERR "Please check the -l iso code\n";
+ exit(1);
+ }
+ if( ( !$merge && !$extract ) || ( $merge && $extract ) ){ usage();exit( -1 );}
+ if( $extract ){ $mode = "extract"; }
+ else { $mode = "merge"; }
+}
+
+#########################################################
+sub usage{
+
+ print STDERR "Usage: localize.pl\n";
+ print STDERR "Split or collect SDF files\n";
+ print STDERR " merge: -m -f <sdffile> -l l1[=f1][,l2[=f2]][...] [ -s <sourceroot> ]\n";
+ print STDERR " extract: -e -f <outputfile> -l <lang> [ -s <sourceroot> ] [-d]\n";
+ print STDERR "Options:\n";
+ print STDERR " -h help\n";
+ print STDERR " -m Merge mode\n";
+ print STDERR " -e Extract mode\n";
+ print STDERR " -f <sdffile> To split a big SDF file into particles\n";
+ print STDERR " <outputfile> To collect and join all particles to one big file\n";
+ print STDERR " -s <sourceroot> Path to the modules, if no \$SRC_ROOT is set\n";
+ print STDERR " -l ( all | <isocode> | <isocode>=fallback ) comma seperated languages\n";
+ print STDERR " -d Use default date in extracted sdf file\n";
+ print STDERR " -v Verbose\n";
+ print STDERR "\nExample:\n";
+ print STDERR "\nlocalize -e -l en-US,pt-BR=en-US -f my.sdf\n( Extract en-US and pt-BR with en-US fallback )\n";
+ print STDERR "\nlocalize -m -l cs -f my.sdf\n( Merge cs translation into the sourcecode ) \n";
+}
+
+# my $line = defined $_ ? $_ : '';
+# my $leftpart = defined $2 ? $2 : '';
+# my $prj = defined $3 ? $3 : '';
+# my $file = defined $4 ? $4 : '';
+# my $dummy = defined $5 ? $5 : '';
+# my $type = defined $6 ? $6 : '';
+# my $gid = defined $7 ? $7 : '';
+# my $lid = defined $8 ? $8 : '';
+# my $helpid = defined $9 ? $9 : '';
+# my $plattform = defined $10 ? $10 : '';
+# my $width = defined $11 ? $11 : '';
+# my $lang = defined $12 ? $12 : '';
+# my $rightpart = defined $13 ? $13 : '';
+# my $text = defined $14 ? $14 : '';
+# my $helptext = defined $15 ? $15 : '';
+# my $quickhelptext = defined $16 ? $16 : '';
+# my $title = defined $17 ? $17 : '';
+# my $timestamp = defined $18 ? $18 : '';
+
diff --git a/l10ntools/source/cfg_yy_wrapper.c b/l10ntools/source/cfg_yy_wrapper.c
new file mode 100644
index 000000000000..ac678d17f399
--- /dev/null
+++ b/l10ntools/source/cfg_yy_wrapper.c
@@ -0,0 +1,2 @@
+// Helper to suppress warnings in lex generated c code, see #i57362#
+#include "cfg_yy.c"
diff --git a/l10ntools/source/cfglex.l b/l10ntools/source/cfglex.l
new file mode 100644
index 000000000000..dd2d9a45ab59
--- /dev/null
+++ b/l10ntools/source/cfglex.l
@@ -0,0 +1,232 @@
+%{
+/*
+ * lexer for parsing cfg source files
+ *
+ */
+
+
+/* enlarge token buffer to tokenize whole strings */
+#undef YYLMAX
+#define YYLMAX 64000
+
+/* to enable debug output define LEXDEBUG */
+#define LEXDEBUG 1
+#ifdef LEXDEBUG
+#define OUTPUT fprintf
+#else
+#define OUTPUT(Par1,Par2);
+#endif
+
+/* table of possible token ids */
+#include "tokens.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined __GNUC__
+#pragma GCC system_header
+#elif defined __SINPRO_CC
+#pragma disable_warn
+#elif defined _MSC_VER
+#pragma warning(push, 1)
+#endif
+
+/* external functions (C++ code, declared as extren "C" */
+extern int WorkOnTokenSet( int, char* );
+extern int InitCfgExport( char * , char *);
+extern int EndCfgExport();
+extern int GetError();
+extern int SetError();
+extern char *GetOutputFile( int argc, char* argv[]);
+extern FILE *GetCfgFile();
+extern int isQuiet();
+extern void removeTempFile();
+extern char* getFilename();
+/* forwards */
+void YYWarning();
+
+int bText=0;
+%}
+
+%p 24000
+%e 1200
+%n 500
+
+%%
+
+\<[^\>]*"xml:lang="\""x-no-translate"\"[^\<]*\/\> {
+ bText = 0;
+ WorkOnTokenSet( CFG_TOKEN_NO_TRANSLATE, yytext );
+}
+
+\<.*\/\> {
+ bText = 0;
+ WorkOnTokenSet( ANYTOKEN, yytext );
+}
+
+\<[^\>]*"xml:lang="\".*\"[^\<]*\> {
+ bText = 1;
+ WorkOnTokenSet( CFG_TEXT_START, yytext );
+}
+
+
+\<[^\/\!][^\>]*\> {
+ bText = 0;
+ WorkOnTokenSet( CFG_TAG, yytext );
+}
+
+"<!"DOCTYPE[^\>]*\> {
+ bText = 0;
+ WorkOnTokenSet( CFG_TAG, yytext );
+}
+
+
+\<\!\-\- {
+ char c1 = 0, c2 = 0, c3 = input();
+ char pChar[2];
+ pChar[1] = 0x00;
+ pChar[0] = c3;
+
+ WorkOnTokenSet( COMMEND, yytext );
+ WorkOnTokenSet( COMMEND, pChar );
+
+ for(;;) {
+ if ( c3 == EOF )
+ break;
+ if ( c1 == '-' && c2 == '-' && c3 == '>' )
+ break;
+ c1 = c2;
+ c2 = c3;
+ c3 = input();
+ pChar[0] = c3;
+ WorkOnTokenSet( COMMEND, pChar );
+ }
+}
+
+\<\/[^\>]*\> {
+ bText = 0;
+ WorkOnTokenSet( CFG_CLOSETAG, yytext );
+}
+
+\<[^\>\!]*\> {
+ bText = 0;
+ if ( yytext[ 1 ] == '!' && yytext[ 2 ] == '-' && yytext[ 3 ] == '-' )
+ WorkOnTokenSet( COMMEND, yytext );
+ else
+ WorkOnTokenSet( CFG_UNKNOWNTAG, yytext );
+}
+
+.|\n {
+ if ( bText == 1 )
+ WorkOnTokenSet( CFG_TEXTCHAR, yytext );
+ else
+ WorkOnTokenSet( UNKNOWNCHAR, yytext );
+}
+
+
+%%
+
+/*****************************************************************************/
+int yywrap(void)
+/*****************************************************************************/
+{
+ return 1;
+}
+
+/*****************************************************************************/
+void YYWarning( char *s )
+/*****************************************************************************/
+{
+ /* write warning to stderr */
+ fprintf( stderr,
+ "Warning: \"%s\" in line %d: \"%s\"\n", s, yylineno, yytext );
+}
+
+/*****************************************************************************/
+#ifdef GCC
+void yyerror ( char *s, ... )
+#else
+void yyerror ( char *s )
+#endif
+/*****************************************************************************/
+{
+ /* write error to stderr */
+ fprintf( stderr,
+ "Error: \"%s\" in line %d: \"%s\"\n", s, yylineno, yytext );
+ SetError();
+}
+
+/*****************************************************************************/
+int
+#ifdef WNT
+_cdecl
+#endif
+main( int argc, char* argv[])
+/*****************************************************************************/
+{
+ /* error level */
+ int nRetValue = 0;
+ char *pOutput;
+ FILE *pFile;
+
+ pOutput = GetOutputFile( argc, argv );
+ if( !isQuiet() ){
+ fprintf( stdout, "\nCfgEx 0.9 Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.\n" );
+ fprintf( stdout, "======================================================================\n" );
+ }
+
+ if ( !pOutput ) {
+ fprintf( stdout, "Syntax: CFGEX[-p Prj][-r PrjRoot]-i FileIn [-o FileOut][-m DataBase][-e][-b][-u][-f][-d DoneFile][-g[:dtd] ][-L l1,l2,...]\n" );
+ fprintf( stdout, " Prj: Project\n" );
+ fprintf( stdout, " PrjRoot: Path to project root (..\\.. etc.)\n" );
+ fprintf( stdout, " FileIn: Source files (*.src)\n" );
+ fprintf( stdout, " FileOut: Destination file (*.*)\n" );
+ fprintf( stdout, " DataBase: Mergedata (*.sdf)\n" );
+ fprintf( stdout, " -QQ: quiet output\n" );
+ fprintf( stdout, " -e: Disable writing errorlog\n" );
+ fprintf( stdout, " -b: Break when Token \"HelpText\" found in source\n" );
+ fprintf( stdout, " -u: [english] and [german] are allowed, Id is Taken from DataBase \n" );
+ fprintf( stdout, " -f: force extraction and merge even if only one language is existent\n" );
+ fprintf( stdout, " -g[:dtd]: enables generation of properties (dtds if :dtd is set) - in this case FileOut is the output path\n" );
+ fprintf( stdout, " -d: enables generation of *.don if work is done\n" );
+ fprintf( stdout, " -L: Restrict the handled languages. l1,l2,... are elements of (de,en-US...)\n" );
+ fprintf( stdout, " A fallback language can be defined like this: l1=f1.\n" );
+ fprintf( stdout, " f1, f2,... are also elements of (de,en-US...)\n" );
+ fprintf( stdout, " Example: -L de,es=en-US\n" );
+ fprintf( stdout, " Restriction to de and es, en-US will be fallback for es\n" );
+ return 1;
+ }
+
+ pFile = GetCfgFile();
+ InitCfgExport( pOutput , getFilename() );
+ if ( !pFile )
+ return 1;
+
+ yyin = pFile;
+
+ /* create global instance of class CfgExport */
+ //InitCfgExport( pOutput );
+
+ /* start parser */
+ yylex();
+
+ /* get error info. and end export */
+ nRetValue = GetError();
+ EndCfgExport();
+
+ if( !isQuiet() ){
+ fprintf( stdout, "\n===================================\n\n" );
+ }
+
+ removeTempFile();
+/* return error level */
+ return nRetValue;
+}
+
+/*"<!--"[^"-->"]*"-->" {
+ bText = 0;
+ WorkOnTokenSet( COMMEND, yytext );
+}*/
+/*"<!"[^\-].*\> {
+ bText = 0;
+ WorkOnTokenSet( CFG_TAG, yytext );
+}*/
diff --git a/l10ntools/source/cfgmerge.cxx b/l10ntools/source/cfgmerge.cxx
new file mode 100644
index 000000000000..5d85a4835843
--- /dev/null
+++ b/l10ntools/source/cfgmerge.cxx
@@ -0,0 +1,886 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: cfgmerge.cxx,v $
+ * $Revision: 1.46 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <stdio.h>
+#include <tools/string.hxx>
+#include <tools/fsys.hxx>
+
+// local includes
+#include "export.hxx"
+#include "cfgmerge.hxx"
+#include "tokens.h"
+#include "utf8conv.hxx"
+
+extern "C" { int yyerror( char * ); }
+extern "C" { int YYWarning( char * ); }
+
+// defines to parse command line
+#define STATE_NON 0x0001
+#define STATE_INPUT 0x0002
+#define STATE_OUTPUT 0x0003
+#define STATE_PRJ 0x0004
+#define STATE_ROOT 0x0005
+#define STATE_MERGESRC 0x0006
+#define STATE_ERRORLOG 0x0007
+#define STATE_UTF8 0x0008
+#define STATE_LANGUAGES 0X0009
+#define STATE_ISOCODE99 0x000A
+#define STATE_FORCE 0x000B
+
+// set of global variables
+BOOL bEnableExport;
+BOOL bMergeMode;
+BOOL bErrorLog;
+BOOL bForce;
+BOOL bUTF8;
+bool bQuiet;
+ByteString sPrj;
+ByteString sPrjRoot;
+ByteString sInputFileName;
+ByteString sActFileName;
+ByteString sFullEntry;
+ByteString sOutputFile;
+ByteString sMergeSrc;
+String sUsedTempFile;
+
+CfgParser *pParser;
+
+extern "C" {
+// the whole interface to lexer is in this extern "C" section
+
+/*****************************************************************************/
+extern char *GetOutputFile( int argc, char* argv[])
+/*****************************************************************************/
+{
+ bEnableExport = FALSE;
+ bMergeMode = FALSE;
+ bErrorLog = TRUE;
+ bForce = FALSE;
+ bUTF8 = TRUE;
+ bQuiet = false;
+ sPrj = "";
+ sPrjRoot = "";
+ sInputFileName = "";
+ sActFileName = "";
+
+ USHORT nState = STATE_NON;
+ BOOL bInput = FALSE;
+
+ // parse command line
+ for( int i = 1; i < argc; i++ ) {
+ ByteString sSwitch( argv[ i ] );
+ sSwitch.ToUpperAscii();
+
+ if ( sSwitch == "-I" ) {
+ nState = STATE_INPUT; // next token specifies source file
+ }
+ else if ( sSwitch == "-O" ) {
+ nState = STATE_OUTPUT; // next token specifies the dest file
+ }
+ else if ( sSwitch == "-P" ) {
+ nState = STATE_PRJ; // next token specifies the cur. project
+ }
+ else if ( sSwitch == "-R" ) {
+ nState = STATE_ROOT; // next token specifies path to project root
+ }
+ else if ( sSwitch == "-M" ) {
+ nState = STATE_MERGESRC; // next token specifies the merge database
+ }
+ else if ( sSwitch == "-E" ) {
+ nState = STATE_ERRORLOG;
+ bErrorLog = FALSE;
+ }
+ else if ( sSwitch == "-UTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = TRUE;
+ }
+ else if ( sSwitch == "-NOUTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = FALSE;
+ }
+ else if ( sSwitch == "-F" ) {
+ nState = STATE_FORCE;
+ bForce = TRUE;
+ }
+ else if ( sSwitch == "-QQ" ) {
+ bQuiet = true;
+ }
+ else if ( sSwitch == "-L" ) {
+ nState = STATE_LANGUAGES;
+ }
+ else if ( sSwitch.ToUpperAscii() == "-ISO99" ) {
+ nState = STATE_ISOCODE99;
+ }
+ else {
+ switch ( nState ) {
+ case STATE_NON: {
+ return NULL; // no valid command line
+ }
+ case STATE_INPUT: {
+ sInputFileName = argv[ i ];
+ bInput = TRUE; // source file found
+ }
+ break;
+ case STATE_OUTPUT: {
+ sOutputFile = argv[ i ]; // the dest. file
+ }
+ break;
+ case STATE_PRJ: {
+ sPrj = ByteString( argv[ i ]);
+// sPrj.ToLowerAscii(); // the project
+ }
+ break;
+ case STATE_ROOT: {
+ sPrjRoot = ByteString( argv[ i ]); // path to project root
+ }
+ break;
+ case STATE_MERGESRC: {
+ sMergeSrc = ByteString( argv[ i ]);
+ bMergeMode = TRUE; // activate merge mode, cause merge database found
+ }
+ break;
+ case STATE_LANGUAGES: {
+ Export::sLanguages = ByteString( argv[ i ]);
+ }
+ break;
+ }
+ }
+ }
+
+ if ( bInput ) {
+ // command line is valid
+ bEnableExport = TRUE;
+ char *pReturn = new char[ sOutputFile.Len() + 1 ];
+ strcpy( pReturn, sOutputFile.GetBuffer()); // #100211# - checked
+ return pReturn;
+ }
+
+ // command line is not valid
+ return NULL;
+}
+int isQuiet(){
+ if( bQuiet ) return 1;
+ else return 0;
+}
+/*****************************************************************************/
+int InitCfgExport( char *pOutput , char* pFilename )
+/*****************************************************************************/
+{
+ // instanciate Export
+ ByteString sOutput( pOutput );
+ ByteString sFilename( pFilename );
+ Export::InitLanguages();
+
+ if ( bMergeMode )
+ pParser = new CfgMerge( sMergeSrc, sOutputFile, sFilename );
+ else if ( sOutputFile.Len())
+ pParser = new CfgExport( sOutputFile, sPrj, sActFileName );
+
+ return 1;
+}
+
+/*****************************************************************************/
+int EndCfgExport()
+/*****************************************************************************/
+{
+ delete pParser;
+
+ return 1;
+}
+
+void removeTempFile(){
+ if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) ){
+ DirEntry aTempFile( sUsedTempFile );
+ aTempFile.Kill();
+ }
+}
+extern const char* getFilename()
+{
+ return sInputFileName.GetBuffer();
+}
+/*****************************************************************************/
+extern FILE *GetCfgFile()
+/*****************************************************************************/
+{
+ FILE *pFile = 0;
+ // look for valid filename
+ if ( sInputFileName.Len()) {
+ if( Export::fileHasUTF8ByteOrderMarker( sInputFileName ) ){
+ DirEntry aTempFile = Export::GetTempFile();
+ DirEntry aSourceFile( String( sInputFileName , RTL_TEXTENCODING_ASCII_US ) );
+ aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
+ String sTempFile = aTempFile.GetFull();
+ Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
+ pFile = fopen( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ).GetBuffer(), "r" );
+ sUsedTempFile = sTempFile;
+ }else{
+ // able to open file?
+ pFile = fopen( sInputFileName.GetBuffer(), "r" );
+ sUsedTempFile = String::CreateFromAscii("");
+ }
+ if ( !pFile ){
+ fprintf( stderr, "Error: Could not open file %s\n",
+ sInputFileName.GetBuffer());
+ exit( 13 );
+ }
+ else {
+ // this is a valid file which can be opened, so
+ // create path to project root
+ DirEntry aEntry( String( sInputFileName, RTL_TEXTENCODING_ASCII_US ));
+ aEntry.ToAbs();
+ sFullEntry= ByteString( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
+ aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
+ aEntry += DirEntry( sPrjRoot );
+ ByteString sPrjEntry( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
+
+ // create file name, beginnig with project root
+ // (e.g.: source\ui\src\menue.src)
+// printf("sFullEntry = %s\n",sFullEntry.GetBuffer());
+ sActFileName = sFullEntry.Copy( sPrjEntry.Len() + 1 );
+// printf("sActFileName = %s\n",sActFileName.GetBuffer());
+ if( !bQuiet )
+ fprintf( stdout, "\nProcessing File %s ...\n", sInputFileName.GetBuffer());
+
+ sActFileName.SearchAndReplaceAll( "/", "\\" );
+
+ return pFile;
+ }
+ }
+ // this means the file could not be opened
+ return NULL;
+}
+
+/*****************************************************************************/
+int WorkOnTokenSet( int nTyp, char *pTokenText )
+/*****************************************************************************/
+{
+ pParser->Execute( nTyp, pTokenText );
+
+ return 1;
+}
+
+
+/*****************************************************************************/
+int SetError()
+/*****************************************************************************/
+{
+ return 1;
+}
+
+/*****************************************************************************/
+int GetError()
+/*****************************************************************************/
+{
+ return 0;
+}
+}
+
+//
+// class CfgStackData
+//
+
+CfgStackData* CfgStack::Push( const ByteString &rTag, const ByteString &rId )
+{
+ CfgStackData *pD = new CfgStackData( rTag, rId );
+ Insert( pD, LIST_APPEND );
+ return pD;
+}
+
+//
+// class CfgStack
+//
+
+/*****************************************************************************/
+CfgStack::~CfgStack()
+/*****************************************************************************/
+{
+ for ( ULONG i = 0; i < Count(); i++ )
+ delete GetObject( i );
+}
+
+/*****************************************************************************/
+ByteString CfgStack::GetAccessPath( ULONG nPos )
+/*****************************************************************************/
+{
+ if ( nPos == LIST_APPEND )
+ nPos = Count() - 1;
+
+ ByteString sReturn;
+ for ( ULONG i = 0; i <= nPos; i++ ) {
+ if ( i )
+ sReturn += ".";
+ sReturn += GetStackData( i )->GetIdentifier();
+ }
+
+ return sReturn;
+}
+
+/*****************************************************************************/
+CfgStackData *CfgStack::GetStackData( ULONG nPos )
+/*****************************************************************************/
+{
+ if ( nPos == LIST_APPEND )
+ nPos = Count() - 1;
+
+ return GetObject( nPos );
+}
+
+//
+// class CfgParser
+//
+
+/*****************************************************************************/
+CfgParser::CfgParser()
+/*****************************************************************************/
+ : pStackData( NULL ),
+ bLocalize( FALSE )
+{
+}
+
+/*****************************************************************************/
+CfgParser::~CfgParser()
+/*****************************************************************************/
+{
+}
+
+
+/*****************************************************************************/
+BOOL CfgParser::IsTokenClosed( const ByteString &rToken )
+/*****************************************************************************/
+{
+ return rToken.GetChar( rToken.Len() - 2 ) == '/';
+}
+
+/*****************************************************************************/
+void CfgParser::AddText(
+ ByteString &rText,
+ const ByteString &rIsoLang,
+ const ByteString &rResTyp
+)
+/*****************************************************************************/
+{
+ USHORT nTextLen = 0;
+ while ( rText.Len() != nTextLen ) {
+ nTextLen = rText.Len();
+ rText.SearchAndReplaceAll( "\n", " " );
+ rText.SearchAndReplaceAll( "\r", " " );
+ rText.SearchAndReplaceAll( "\t", " " );
+ rText.SearchAndReplaceAll( " ", " " );
+ }
+ pStackData->sResTyp = rResTyp;
+ WorkOnText( rText, rIsoLang );
+
+ pStackData->sText[ rIsoLang ] = rText;
+}
+
+
+/*****************************************************************************/
+void CfgParser::WorkOnRessourceEnd()
+/*****************************************************************************/
+{
+}
+
+/*****************************************************************************/
+int CfgParser::ExecuteAnalyzedToken( int nToken, char *pToken )
+/*****************************************************************************/
+{
+ ByteString sToken( pToken );
+
+ if ( sToken == " " || sToken == "\t" )
+ sLastWhitespace += sToken;
+
+ ByteString sTokenName;
+ ByteString sTokenId;
+
+ BOOL bOutput = TRUE;
+
+ switch ( nToken ) {
+ case CFG_TOKEN_PACKAGE:
+ case CFG_TOKEN_COMPONENT:
+ case CFG_TOKEN_TEMPLATE:
+ case CFG_TOKEN_CONFIGNAME:
+ case CFG_TOKEN_OORNAME:
+ case CFG_TOKEN_OORVALUE:
+ case CFG_TAG:
+ case ANYTOKEN:
+ case CFG_TEXT_START:
+ {
+ sTokenName = sToken.GetToken( 1, '<' ).GetToken( 0, '>' ).GetToken( 0, ' ' );
+
+ if ( !IsTokenClosed( sToken )) {
+ ByteString sSearch;
+ switch ( nToken ) {
+ case CFG_TOKEN_PACKAGE:
+ sSearch = "package-id=";
+ break;
+ case CFG_TOKEN_COMPONENT:
+ sSearch = "component-id=";
+ break;
+ case CFG_TOKEN_TEMPLATE:
+ sSearch = "template-id=";
+ break;
+ case CFG_TOKEN_CONFIGNAME:
+ sSearch = "cfg:name=";
+ break;
+ case CFG_TOKEN_OORNAME:
+ sSearch = "oor:name=";
+ bLocalize = TRUE;
+ break;
+ case CFG_TOKEN_OORVALUE:
+ sSearch = "oor:value=";
+ break;
+ case CFG_TEXT_START: {
+ if ( sCurrentResTyp != sTokenName ) {
+ WorkOnRessourceEnd();
+ ByteString sCur;
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ pStackData->sText[ sCur ] = ByteString("");
+ }
+ }
+ sCurrentResTyp = sTokenName;
+
+ ByteString sTemp = sToken.Copy( sToken.Search( "xml:lang=" ));
+ sCurrentIsoLang = sTemp.GetToken( 1, '\"' ).GetToken( 0, '\"' );
+
+ if ( sCurrentIsoLang == NO_TRANSLATE_ISO )
+ bLocalize = FALSE;
+
+ pStackData->sTextTag = sToken;
+
+ sCurrentText = "";
+ }
+ break;
+ }
+ if ( sSearch.Len()) {
+ ByteString sTemp = sToken.Copy( sToken.Search( sSearch ));
+ sTokenId = sTemp.GetToken( 1, '\"' ).GetToken( 0, '\"' );
+ }
+ pStackData = aStack.Push( sTokenName, sTokenId );
+
+ if ( sSearch == "cfg:name=" ) {
+ ByteString sTemp( sToken );
+ sTemp.ToUpperAscii();
+ bLocalize = (( sTemp.Search( "CFG:TYPE=\"STRING\"" ) != STRING_NOTFOUND ) &&
+ ( sTemp.Search( "CFG:LOCALIZED=\"TRUE\"" ) != STRING_NOTFOUND ));
+ }
+ }
+ else if ( sTokenName == "label" ) {
+ if ( sCurrentResTyp != sTokenName ) {
+ WorkOnRessourceEnd();
+ ByteString sCur;
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ pStackData->sText[ sCur ] = ByteString("");
+ }
+ }
+ sCurrentResTyp = sTokenName;
+ }
+ }
+ break;
+ case CFG_CLOSETAG:
+ sTokenName = sToken.GetToken( 1, '/' ).GetToken( 0, '>' ).GetToken( 0, ' ' );
+ if ( aStack.GetStackData() && ( aStack.GetStackData()->GetTagType() == sTokenName )) {
+ if ( ! sCurrentText.Len())
+ WorkOnRessourceEnd();
+ aStack.Pop();
+ pStackData = aStack.GetStackData();
+ }
+ else {
+ ByteString sError( "Missplaced close tag: " );
+ ByteString sInFile(" in file ");
+ sError += sToken;
+ sError += sInFile;
+ sError += sFullEntry;
+ Error( sError );
+ exit ( 13 );
+ }
+ break;
+
+ case CFG_TEXTCHAR:
+ sCurrentText += sToken;
+ bOutput = FALSE;
+ break;
+
+ case CFG_TOKEN_NO_TRANSLATE:
+ bLocalize = FALSE;
+ break;
+ }
+
+ if ( sCurrentText.Len() && nToken != CFG_TEXTCHAR ) {
+ AddText( sCurrentText, sCurrentIsoLang, sCurrentResTyp );
+ Output( sCurrentText );
+ sCurrentText = "";
+ pStackData->sEndTextTag = sToken;
+ }
+
+ if ( bOutput )
+ Output( sToken );
+
+ if ( sToken != " " && sToken != "\t" )
+ sLastWhitespace = "";
+
+ return 1;
+}
+
+/*****************************************************************************/
+void CfgExport::Output( const ByteString& rOutput )
+/*****************************************************************************/
+{
+ // Dummy operation to suppress warnings caused by poor class design
+ ByteString a( rOutput );
+}
+
+/*****************************************************************************/
+int CfgParser::Execute( int nToken, char * pToken )
+/*****************************************************************************/
+{
+ ByteString sToken( pToken );
+
+ switch ( nToken ) {
+ case CFG_TAG:
+ if ( sToken.Search( "package-id=" ) != STRING_NOTFOUND )
+ return ExecuteAnalyzedToken( CFG_TOKEN_PACKAGE, pToken );
+ else if ( sToken.Search( "component-id=" ) != STRING_NOTFOUND )
+ return ExecuteAnalyzedToken( CFG_TOKEN_COMPONENT, pToken );
+ else if ( sToken.Search( "template-id=" ) != STRING_NOTFOUND )
+ return ExecuteAnalyzedToken( CFG_TOKEN_TEMPLATE, pToken );
+ else if ( sToken.Search( "cfg:name=" ) != STRING_NOTFOUND )
+ return ExecuteAnalyzedToken( CFG_TOKEN_OORNAME, pToken );
+ else if ( sToken.Search( "oor:name=" ) != STRING_NOTFOUND )
+ return ExecuteAnalyzedToken( CFG_TOKEN_OORNAME, pToken );
+ else if ( sToken.Search( "oor:value=" ) != STRING_NOTFOUND )
+ return ExecuteAnalyzedToken( CFG_TOKEN_OORVALUE, pToken );
+ break;
+ }
+ return ExecuteAnalyzedToken( nToken, pToken );
+}
+
+
+/*****************************************************************************/
+void CfgParser::Error( const ByteString &rError )
+/*****************************************************************************/
+{
+// ByteString sError( rError );
+// sError.Append("Error: In file ");
+// sError.Append( sActFileName );
+ yyerror(( char * ) rError.GetBuffer());
+}
+
+
+//
+// class CfgOutputParser
+//
+
+/*****************************************************************************/
+CfgOutputParser::CfgOutputParser( const ByteString &rOutputFile )
+/*****************************************************************************/
+{
+ pOutputStream =
+ new SvFileStream(
+ String( rOutputFile, RTL_TEXTENCODING_ASCII_US ),
+ STREAM_STD_WRITE | STREAM_TRUNC
+ );
+ pOutputStream->SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
+
+ if ( !pOutputStream->IsOpen()) {
+ ByteString sError( "ERROR: Unable to open output file: " );
+ sError += rOutputFile;
+ Error( sError );
+ delete pOutputStream;
+ pOutputStream = NULL;
+ exit( 13 );
+ }
+}
+
+/*****************************************************************************/
+CfgOutputParser::~CfgOutputParser()
+/*****************************************************************************/
+{
+ if ( pOutputStream ) {
+ pOutputStream->Close();
+ delete pOutputStream;
+ }
+}
+
+//
+// class CfgExport
+//
+
+/*****************************************************************************/
+CfgExport::CfgExport(
+ const ByteString &rOutputFile,
+ const ByteString &rProject,
+ const ByteString &rFilePath
+)
+/*****************************************************************************/
+ : CfgOutputParser( rOutputFile ),
+ sPrj( rProject ),
+ sPath( rFilePath )
+{
+ Export::InitLanguages( false );
+ aLanguages = Export::GetLanguages();
+}
+
+/*****************************************************************************/
+CfgExport::~CfgExport()
+/*****************************************************************************/
+{
+}
+
+/*****************************************************************************/
+void CfgExport::WorkOnRessourceEnd()
+/*****************************************************************************/
+{
+ if ( pOutputStream && bLocalize ) {
+ if (( pStackData->sText[ ByteString("en-US") ].Len()
+ ) ||
+ ( bForce &&
+ ( pStackData->sText[ ByteString("de") ].Len() ||
+ pStackData->sText[ ByteString("en-US") ].Len() )))
+ {
+ ByteString sFallback = pStackData->sText[ ByteString("en-US") ];
+
+ //if ( pStackData->sText[ ByteString("en-US") ].Len())
+ // sFallback = pStackData->sText[ ByteString("en-US") ];
+
+ ByteString sLocalId = pStackData->sIdentifier;
+ ByteString sGroupId;
+ if ( aStack.Count() == 1 ) {
+ sGroupId = sLocalId;
+ sLocalId = "";
+ }
+ else {
+ sGroupId = aStack.GetAccessPath( aStack.Count() - 2 );
+ }
+
+ ByteString sTimeStamp( Export::GetTimeStamp());
+
+ ByteString sCur;
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+
+ ByteString sText = pStackData->sText[ sCur ];
+ if ( !sText.Len())
+ sText = sFallback;
+
+ Export::UnquotHTML( sText );
+
+ ByteString sOutput( sPrj ); sOutput += "\t";
+ sOutput += sPath;
+ sOutput += "\t0\t";
+ sOutput += pStackData->sResTyp; sOutput += "\t";
+ sOutput += sGroupId; sOutput += "\t";
+ sOutput += sLocalId; sOutput += "\t\t\t0\t";
+ sOutput += sCur;
+ sOutput += "\t";
+
+ sOutput += sText; sOutput += "\t\t\t\t";
+ sOutput += sTimeStamp;
+
+ //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( sPrj ) ) )
+ pOutputStream->WriteLine( sOutput );
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+void CfgExport::WorkOnText(
+ ByteString &rText,
+ const ByteString &rIsoLang
+)
+/*****************************************************************************/
+{
+ if( rIsoLang.Len() ) Export::UnquotHTML( rText );
+}
+
+
+//
+// class CfgMerge
+//
+
+/*****************************************************************************/
+CfgMerge::CfgMerge(
+ const ByteString &rMergeSource, const ByteString &rOutputFile,
+ ByteString &rFilename )
+/*****************************************************************************/
+ : CfgOutputParser( rOutputFile ),
+ pMergeDataFile( NULL ),
+ pResData( NULL ),
+ bGerman( FALSE ),
+ sFilename( rFilename ),
+ bEnglish( FALSE )
+{
+ if ( rMergeSource.Len()){
+ pMergeDataFile = new MergeDataFile(
+ rMergeSource, sInputFileName , bErrorLog, RTL_TEXTENCODING_MS_1252, true );
+ if( Export::sLanguages.EqualsIgnoreCaseAscii("ALL") ){
+ Export::SetLanguages( pMergeDataFile->GetLanguages() );
+ aLanguages = pMergeDataFile->GetLanguages();
+ }
+ else aLanguages = Export::GetLanguages();
+ }else
+ aLanguages = Export::GetLanguages();
+}
+
+/*****************************************************************************/
+CfgMerge::~CfgMerge()
+/*****************************************************************************/
+{
+ delete pMergeDataFile;
+ delete pResData;
+}
+
+/*****************************************************************************/
+void CfgMerge::WorkOnText(
+ ByteString &rText,
+ const ByteString& nLangIndex
+)
+/*****************************************************************************/
+{
+
+ if ( pMergeDataFile && bLocalize ) {
+ if ( !pResData ) {
+ ByteString sLocalId = pStackData->sIdentifier;
+ ByteString sGroupId;
+ if ( aStack.Count() == 1 ) {
+ sGroupId = sLocalId;
+ sLocalId = "";
+ }
+ else {
+ sGroupId = aStack.GetAccessPath( aStack.Count() - 2 );
+ }
+
+ ByteString sPlatform( "" );
+
+ pResData = new ResData( sPlatform, sGroupId , sFilename );
+ pResData->sId = sLocalId;
+ pResData->sResTyp = pStackData->sResTyp;
+ }
+
+ //if ( nLangIndex.EqualsIgnoreCaseAscii("de") )
+ // bGerman = TRUE;
+ if (( nLangIndex.EqualsIgnoreCaseAscii("en-US") ))
+ bEnglish = TRUE;
+
+ PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrysCaseSensitive( pResData );
+ if ( pEntrys ) {
+ ByteString sContent;
+ pEntrys->GetText( sContent, STRING_TYP_TEXT, nLangIndex );
+
+ if ( Export::isAllowed( nLangIndex ) &&
+ ( sContent != "-" ) && ( sContent.Len()))
+ {
+#ifdef MERGE_SOURCE_LANGUAGES
+ if( nLangIndex.EqualsIgnoreCaseAscii("de") || nLangIndex.EqualsIgnoreCaseAscii("en-US") )
+ rText = sContent;
+#endif
+ Export::QuotHTML( rText );
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+void CfgMerge::Output( const ByteString& rOutput )
+/*****************************************************************************/
+{
+ if ( pOutputStream )
+ pOutputStream->Write( rOutput.GetBuffer(), rOutput.Len());
+}
+
+ULONG CfgStack::Push( CfgStackData *pStackData )
+{
+ Insert( pStackData, LIST_APPEND );
+ return Count() - 1;
+}
+
+/*****************************************************************************/
+void CfgMerge::WorkOnRessourceEnd()
+/*****************************************************************************/
+{
+
+ if ( pMergeDataFile && pResData && bLocalize && (( bEnglish ) || bForce )) {
+ PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrysCaseSensitive( pResData );
+ if ( pEntrys ) {
+ ByteString sCur;
+
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+
+ ByteString sContent;
+ pEntrys->GetText( sContent, STRING_TYP_TEXT, sCur , TRUE );
+ if (
+ // (!sCur.EqualsIgnoreCaseAscii("de") ) &&
+ ( !sCur.EqualsIgnoreCaseAscii("en-US") ) &&
+
+ ( sContent != "-" ) && ( sContent.Len()))
+ {
+
+ ByteString sText = sContent;
+ Export::QuotHTML( sText );
+
+ ByteString sAdditionalLine( "\t" );
+
+ ByteString sTextTag = pStackData->sTextTag;
+ ByteString sTemp = sTextTag.Copy( sTextTag.Search( "xml:lang=" ));
+
+ ByteString sSearch = sTemp.GetToken( 0, '\"' );
+ sSearch += "\"";
+ sSearch += sTemp.GetToken( 1, '\"' );
+ sSearch += "\"";
+
+ ByteString sReplace = sTemp.GetToken( 0, '\"' );
+ sReplace += "\"";
+ sReplace += sCur;
+ sReplace += "\"";
+
+ sTextTag.SearchAndReplace( sSearch, sReplace );
+
+ sAdditionalLine += sTextTag;
+ sAdditionalLine += sText;
+ sAdditionalLine += pStackData->sEndTextTag;
+
+ sAdditionalLine += "\n";
+ sAdditionalLine += sLastWhitespace;
+
+ Output( sAdditionalLine );
+ }
+ }
+ }
+ }
+ delete pResData;
+ pResData = NULL;
+ bGerman = FALSE;
+ bEnglish = FALSE;
+}
diff --git a/l10ntools/source/directory.cxx b/l10ntools/source/directory.cxx
new file mode 100644
index 000000000000..21d0a5878d66
--- /dev/null
+++ b/l10ntools/source/directory.cxx
@@ -0,0 +1,276 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: directory.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <l10ntools/directory.hxx>
+#include "tools/string.hxx"
+#include <iostream>
+#include <vector>
+#include <algorithm>
+
+namespace transex
+{
+
+Directory::Directory( const rtl::OUString sFullpath ) : bSkipLinks( false )
+{
+ sFullName = sFullpath;
+}
+
+Directory::Directory( const rtl::OUString sFullPath , const rtl::OUString sEntry ) : bSkipLinks( false )
+{
+ sFullName = sFullPath;
+ sDirectoryName = sEntry;
+}
+
+
+Directory::Directory( const ByteString sFullPath ) : bSkipLinks( false )
+{
+ sDirectoryName = rtl::OUString( sFullPath.GetBuffer() , RTL_TEXTENCODING_UTF8 , sFullPath.Len() );
+}
+
+bool Directory::lessDir ( const Directory& rKey1, const Directory& rKey2 )
+{
+ rtl::OUString sName1( ( static_cast< Directory >( rKey1 ) ).getDirectoryName() );
+ rtl::OUString sName2( ( static_cast< Directory >( rKey2 ) ).getDirectoryName() );
+
+ return sName1.compareTo( sName2 ) < 0 ;
+}
+
+
+void Directory::dump()
+{
+
+ for( std::vector< transex::File >::iterator iter = aFileVec.begin() ; iter != aFileVec.end() ; ++iter )
+ {
+ std::cout << "FILE " << rtl::OUStringToOString( (*iter).getFullName().getStr() , RTL_TEXTENCODING_UTF8 , (*iter).getFullName().getLength() ).getStr() << "\n";
+ }
+
+ for( std::vector< transex::Directory >::iterator iter = aDirVec.begin() ; iter != aDirVec.end() ; ++iter )
+ {
+ std::cout << "DIR " << rtl::OUStringToOString( (*iter).getFullName().getStr() , RTL_TEXTENCODING_UTF8 , (*iter).getFullName().getLength() ).getStr() << "\n";
+ }
+
+}
+
+void Directory::scanSubDir( int nLevels )
+{
+ readDirectory( sFullName );
+ dump();
+ if( nLevels > 0 ) {
+ for( std::vector< transex::Directory >::iterator iter = aDirVec.begin() ; iter != aDirVec.end() || nLevels > 0 ; ++iter , nLevels-- )
+ {
+ ( *iter ).scanSubDir();
+ }
+ }
+}
+
+void Directory::setSkipLinks( bool is_skipped )
+{
+ bSkipLinks = is_skipped;
+}
+
+void Directory::readDirectory()
+{
+ readDirectory( sFullName );
+}
+
+#ifdef WNT
+#include <tools/prewin.h>
+#include <windows.h>
+#include <tools/postwin.h>
+
+void Directory::readDirectory ( const rtl::OUString& sFullpath )
+{
+ BOOL fFinished;
+ HANDLE hList;
+ TCHAR szDir[MAX_PATH+1];
+ TCHAR szSubDir[MAX_PATH+1];
+ WIN32_FIND_DATA FileData;
+
+ rtl::OString sFullpathext = rtl::OUStringToOString( sFullpath , RTL_TEXTENCODING_UTF8 , sFullpath.getLength() );
+ const char *dirname = sFullpathext.getStr();
+
+ // Get the proper directory path
+ sprintf(szDir, "%s\\*", dirname);
+
+ // Get the first file
+ hList = FindFirstFile(szDir, &FileData);
+ if (hList == INVALID_HANDLE_VALUE)
+ {
+ //FindClose(hList);
+ //printf("No files found %s\n", szDir ); return;
+ }
+ else
+ {
+ fFinished = FALSE;
+ while (!fFinished)
+ {
+
+ sprintf(szSubDir, "%s\\%s", dirname, FileData.cFileName);
+ rtl::OString myfile( FileData.cFileName );
+ rtl::OString mydir( szSubDir );
+
+ if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if ( (strcmp(FileData.cFileName, ".") != 0 ) &&
+ (strcmp(FileData.cFileName, "..") != 0 ) )
+ {
+ //sprintf(szSubDir, "%s\\%s", dirname, FileData.cFileName);
+ transex::Directory aDir( rtl::OStringToOUString( mydir , RTL_TEXTENCODING_UTF8 , mydir.getLength() ),
+ rtl::OStringToOUString( myfile , RTL_TEXTENCODING_UTF8 , myfile.getLength() ) );
+ aDirVec.push_back( aDir );
+ }
+ }
+ else
+ {
+ transex::File aFile( rtl::OStringToOUString( mydir , RTL_TEXTENCODING_UTF8 , mydir.getLength() ),
+ rtl::OStringToOUString( myfile , RTL_TEXTENCODING_UTF8 , myfile.getLength() ) );
+ aFileVec.push_back( aFile );
+ }
+ if (!FindNextFile(hList, &FileData))
+ {
+ if (GetLastError() == ERROR_NO_MORE_FILES)
+ {
+ fFinished = TRUE;
+ }
+ }
+ }
+ }
+
+ FindClose(hList);
+
+ ::std::sort( aFileVec.begin() , aFileVec.end() , File::lessFile );
+ ::std::sort( aDirVec.begin() , aDirVec.end() , Directory::lessDir );
+}
+
+#else
+
+class dirholder
+{
+private:
+ DIR *mpDir;
+public:
+ dirholder(DIR *pDir) : mpDir(pDir) {}
+ int close() { int nRet = mpDir ? closedir(mpDir) : 0; mpDir = NULL; return nRet; }
+ ~dirholder() { close(); }
+};
+
+void Directory::readDirectory( const rtl::OUString& sFullpath )
+{
+ struct stat statbuf;
+ struct stat statbuf2;
+ struct dirent *dirp;
+ DIR *dir;
+ //int ret;
+ //char *ptr;
+
+ if( sFullpath.getLength() < 1 ) return;
+
+ rtl::OString sFullpathext = rtl::OUStringToOString( sFullpath , RTL_TEXTENCODING_UTF8 , sFullpath.getLength() ).getStr();
+ //printf("%s\n",sFullpathext.getStr());
+ const char* path = sFullpathext.getStr();
+
+ // stat
+ if( stat( path , &statbuf ) < 0 ){ printf("warning: Can not stat %s" , path ); return; }// error }
+
+ if( S_ISDIR(statbuf.st_mode ) == 0 ) { return; }// error } return; // not dir
+
+ if( (dir = opendir( path ) ) == NULL ) {printf("readerror 2 in %s \n",path); return; } // error } return; // error
+ dirholder aHolder(dir);
+
+ sFullpathext += rtl::OString( "/" );
+
+ const rtl::OString sDot ( "." ) ;
+ const rtl::OString sDDot( ".." );
+
+ if ( chdir( path ) == -1 ) { printf("chdir error in %s \n",path); return; } // error
+
+ while( ( dirp = readdir( dir ) ) != NULL )
+ {
+ rtl::OString sEntryName( dirp->d_name );
+
+ if( sEntryName.equals( sDot ) || sEntryName.equals( sDDot ) )
+ continue;
+
+ // add dir entry
+ rtl::OString sEntity = sFullpathext;
+ sEntity += sEntryName;
+
+ // stat new entry
+ if( lstat( sEntity.getStr() , &statbuf2 ) < 0 )
+ {
+ printf("error on entry %s\n" , sEntity.getStr() ) ; // error
+ continue;
+ }
+
+ // add file / dir to vector
+ switch( statbuf2.st_mode & S_IFMT )
+ {
+ case S_IFREG:
+ {
+ rtl::OString sFile = sFullpathext;
+ sFile += sEntryName ;
+ transex::File aFile( rtl::OStringToOUString( sEntity , RTL_TEXTENCODING_UTF8 , sEntity.getLength() ) ,
+ rtl::OStringToOUString( sEntryName , RTL_TEXTENCODING_UTF8 , sEntryName.getLength() )
+ );
+
+ aFileVec.push_back( aFile ) ;
+ break;
+ }
+ case S_IFLNK:
+ {
+ if( bSkipLinks ) break;
+ }
+ case S_IFDIR:
+ {
+ rtl::OString sDir = sFullpathext;
+ sDir += sEntryName ;
+
+ transex::Directory aDir(
+ rtl::OStringToOUString( sEntity , RTL_TEXTENCODING_UTF8 , sEntity.getLength() ) ,
+ rtl::OStringToOUString( sEntryName , RTL_TEXTENCODING_UTF8 , sEntryName.getLength() )
+ ) ;
+ aDirVec.push_back( aDir ) ;
+ break;
+ }
+ }
+ }
+ if ( chdir( ".." ) == -1 ) { printf("chdir error in .. \n"); return; } // error
+ if( aHolder.close() < 0 ) return ; // error
+
+ std::sort( aFileVec.begin() , aFileVec.end() , File::lessFile );
+ std::sort( aDirVec.begin() , aDirVec.end() , Directory::lessDir );
+
+}
+
+#endif
+}
diff --git a/l10ntools/source/export.cxx b/l10ntools/source/export.cxx
new file mode 100644
index 000000000000..72826d7bf1f2
--- /dev/null
+++ b/l10ntools/source/export.cxx
@@ -0,0 +1,2660 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: export.cxx,v $
+ * $Revision: 1.57 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <stdio.h>
+#include <stdlib.h>
+#include <tools/fsys.hxx>
+#include "export.hxx"
+#include "tokens.h"
+#include "utf8conv.hxx"
+#include <iostream>
+
+extern "C" { int yyerror( char * ); }
+extern "C" { int YYWarning( char * ); }
+
+Export *pExport = 0L;
+
+// defines to parse command line
+#define STATE_NON 0x0001
+#define STATE_INPUT 0x0002
+#define STATE_OUTPUT 0x0003
+#define STATE_PRJ 0x0004
+#define STATE_ROOT 0x0005
+#define STATE_MERGESRC 0x0006
+#define STATE_ERRORLOG 0x0007
+#define STATE_BREAKHELP 0x0008
+#define STATE_UNMERGE 0x0009
+#define STATE_UTF8 0x000A
+#define STATE_LANGUAGES 0X000B
+
+// set of global variables
+DECLARE_LIST( FileList, ByteString * )
+FileList aInputFileList;
+BOOL bEnableExport;
+BOOL bMergeMode;
+BOOL bErrorLog;
+BOOL bBreakWhenHelpText;
+BOOL bUnmerge;
+BOOL bUTF8;
+bool bQuiet;
+ByteString sPrj;
+ByteString sPrjRoot;
+ByteString sActFileName;
+ByteString sOutputFile;
+ByteString sMergeSrc;
+ByteString sTempFile;
+ByteString sFile;
+MergeDataFile *pMergeDataFile;
+FILE *pTempFile;
+
+
+ByteString sStrBuffer;
+bool bMarcro = false;
+
+extern "C" {
+// the whole interface to lexer is in this extern "C" section
+
+
+/*****************************************************************************/
+extern char *GetOutputFile( int argc, char* argv[])
+/*****************************************************************************/
+{
+ bEnableExport = FALSE;
+ bMergeMode = FALSE;
+ bErrorLog = TRUE;
+ bBreakWhenHelpText = FALSE;
+ bUnmerge = FALSE;
+ bUTF8 = TRUE;
+ sPrj = "";
+ sPrjRoot = "";
+ sActFileName = "";
+ Export::sLanguages = "";
+ Export::sForcedLanguages = "";
+ sTempFile = "";
+ pTempFile = NULL;
+ bQuiet = false;
+ USHORT nState = STATE_NON;
+ BOOL bInput = FALSE;
+
+ // parse command line
+ for( int i = 1; i < argc; i++ ) {
+ ByteString sSwitch( argv[ i ] );
+
+ if (sSwitch == "-i" || sSwitch == "-I" ) {
+ nState = STATE_INPUT; // next tokens specifies source files
+ }
+ else if (sSwitch == "-o" || sSwitch == "-O" ) {
+ nState = STATE_OUTPUT; // next token specifies the dest file
+ }
+ else if (sSwitch == "-p" || sSwitch == "-P" ) {
+ nState = STATE_PRJ; // next token specifies the cur. project
+ }
+ else if (sSwitch == "-qq" || sSwitch == "-QQ" ) {
+ bQuiet = true;
+ }
+
+ else if (sSwitch == "-r" || sSwitch == "-R" ) {
+ nState = STATE_ROOT; // next token specifies path to project root
+ }
+ else if (sSwitch == "-m" || sSwitch == "-M" ) {
+ nState = STATE_MERGESRC; // next token specifies the merge database
+ }
+ else if (sSwitch == "-e" || sSwitch == "-E" ) {
+ nState = STATE_ERRORLOG;
+ bErrorLog = FALSE;
+ }
+ else if (sSwitch == "-b" || sSwitch == "-B" ) {
+ nState = STATE_BREAKHELP;
+ bBreakWhenHelpText = TRUE;
+ }
+ else if (sSwitch == "-u" || sSwitch == "-U" ) {
+ nState = STATE_UNMERGE;
+ bUnmerge = TRUE;
+ bMergeMode = TRUE;
+ }
+ else if ( sSwitch.ToUpperAscii() == "-UTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = TRUE;
+ }
+ else if ( sSwitch.ToUpperAscii() == "-NOUTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = FALSE;
+ }
+ else if ( sSwitch == "-l" || sSwitch == "-L" ) {
+ nState = STATE_LANGUAGES;
+ }
+ else {
+ switch ( nState ) {
+ case STATE_NON: {
+ return NULL; // no valid command line
+ }
+ case STATE_INPUT: {
+ aInputFileList.Insert( new ByteString( argv[ i ]), LIST_APPEND );
+ bInput = TRUE; // min. one source file found
+ }
+ break;
+ case STATE_OUTPUT: {
+ sOutputFile = ByteString( argv[ i ]); // the dest. file
+ }
+ break;
+ case STATE_PRJ: {
+ sPrj = ByteString( argv[ i ]);
+ }
+ break;
+ case STATE_ROOT: {
+ sPrjRoot = ByteString( argv[ i ]); // path to project root
+ }
+ break;
+ case STATE_MERGESRC: {
+ sMergeSrc = ByteString( argv[ i ]);
+ bMergeMode = TRUE; // activate merge mode, cause merge database found
+ }
+ break;
+ case STATE_LANGUAGES: {
+ Export::sLanguages = ByteString( argv[ i ]);
+ }
+ break;
+ }
+ }
+ }
+ if( bUnmerge ) sMergeSrc = ByteString();
+ if ( bInput ) {
+ // command line is valid
+ bEnableExport = TRUE;
+ char *pReturn = new char[ sOutputFile.Len() + 1 ];
+ strcpy( pReturn, sOutputFile.GetBuffer()); // #100211# - checked
+ return pReturn;
+ }
+
+ // command line is not valid
+ return NULL;
+}
+/*****************************************************************************/
+int isQuiet(){
+/*****************************************************************************/
+ if( bQuiet ) return 1;
+ else return 0;
+}
+/*****************************************************************************/
+int InitExport( char *pOutput , char* pFilename )
+/*****************************************************************************/
+{
+ // instanciate Export
+ ByteString sOutput( pOutput );
+ ByteString sFilename( pFilename );
+
+ if ( bMergeMode && !bUnmerge ) {
+ // merge mode enabled, so read database
+ pExport = new Export(sOutput, bEnableExport, sPrj, sPrjRoot, sMergeSrc , sFilename );
+ }
+ else
+ // no merge mode, only export
+ pExport = new Export( sOutput, bEnableExport, sPrj, sPrjRoot , sFilename );
+ return 1;
+}
+
+/*****************************************************************************/
+int EndExport()
+/*****************************************************************************/
+{
+ delete pExport;
+ return 1;
+}
+
+extern const char* getFilename()
+{
+ return (*(aInputFileList.GetObject( 0 ))).GetBuffer();
+}
+/*****************************************************************************/
+extern FILE *GetNextFile()
+/*****************************************************************************/
+{
+ // look for next valid filename in input file list
+ if ( sTempFile.Len()) {
+ fclose( pTempFile );
+ String sTemp( sTempFile, RTL_TEXTENCODING_ASCII_US );
+ DirEntry aTemp( sTemp );
+ aTemp.Kill();
+ }
+
+ while ( aInputFileList.Count()) {
+ ByteString sFileName( *(aInputFileList.GetObject( 0 )));
+
+ ByteString sOrigFile( sFileName );
+
+ sFileName = Export::GetNativeFile( sFileName );
+ delete aInputFileList.GetObject(( ULONG ) 0 );
+ aInputFileList.Remove(( ULONG ) 0 );
+
+ if ( sFileName == "" ) {
+ fprintf( stderr, "ERROR: Could not precompile File %s\n",
+ sOrigFile.GetBuffer());
+ return GetNextFile();
+ }
+
+ sTempFile = sFileName;
+ Export::RemoveUTF8ByteOrderMarkerFromFile( sFileName );
+
+ // able to open file?
+ FILE *pFile = fopen( sFileName.GetBuffer(), "r" );
+ if ( !pFile )
+ fprintf( stderr, "Error: Could not open File %s\n",
+ sFileName.GetBuffer());
+ else {
+ pTempFile = pFile;
+
+ // this is a valid file which can be opened, so
+ // create path to project root
+ DirEntry aEntry( String( sOrigFile, RTL_TEXTENCODING_ASCII_US ));
+ aEntry.ToAbs();
+ ByteString sFullEntry( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
+ aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
+ aEntry += DirEntry( sPrjRoot );
+ ByteString sPrjEntry( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
+
+ // create file name, beginnig with project root
+ // (e.g.: source\ui\src\menue.src)
+ sActFileName = sFullEntry.Copy( sPrjEntry.Len() + 1 );
+
+ if( !bQuiet ) fprintf( stdout, "\nProcessing File %s ...\n", sOrigFile.GetBuffer());
+
+ sActFileName.SearchAndReplaceAll( "/", "\\" );
+ sFile = sActFileName;
+
+ if ( pExport ) {
+ // create instance of class export
+ pExport->Init();
+ }
+ // return the valid file handle
+ return pFile;
+ }
+ }
+ // this means the file could not be opened
+ return NULL;
+}
+
+int Parse( int nTyp, const char *pTokenText ){
+ pExport->Execute( nTyp , pTokenText );
+ return 1;
+}
+void Close(){
+ pExport->pParseQueue->Close();
+}
+/*****************************************************************************/
+int WorkOnTokenSet( int nTyp, char *pTokenText )
+/*****************************************************************************/
+{
+
+ pExport->pParseQueue->Push( QueueEntry( nTyp , ByteString( pTokenText ) ) );
+ return 1;
+}
+
+} // extern
+
+extern "C" {
+/*****************************************************************************/
+int SetError()
+/*****************************************************************************/
+{
+ // set error at global instance of class Export
+ pExport->SetError();
+ return 1;
+}
+}
+
+extern "C" {
+/*****************************************************************************/
+int GetError()
+/*****************************************************************************/
+{
+ // get error at global instance of class Export
+ if ( pExport->GetError())
+ return 1;
+ return FALSE;
+}
+}
+
+//
+// class ResData
+//
+
+void ResData::Dump(){
+ printf("**************\nResData\n");
+ printf("sPForm = %s , sResTyp = %s , sId = %s , sGId = %s , sHelpId = %s\n",sPForm.GetBuffer()
+ ,sResTyp.GetBuffer(),sId.GetBuffer(),sGId.GetBuffer(),sHelpId.GetBuffer());
+
+ ByteString a("*pStringList");
+ ByteString b("*pUIEntries");
+ ByteString c("*pFilterList");
+ ByteString d("*pItemList");
+ ByteString e("*pPairedList");
+ ByteString f("sText");
+
+ Export::DumpMap( f , sText );
+
+ if( pStringList ) Export::DumpExportList( a , *pStringList );
+ if( pUIEntries ) Export::DumpExportList( b , *pUIEntries );
+ if( pFilterList ) Export::DumpExportList( c , *pFilterList );
+ if( pItemList ) Export::DumpExportList( d , *pItemList );
+ if( pPairedList ) Export::DumpExportList( e , *pPairedList );
+ printf("\n");
+}
+
+void ResData::addFallbackData( ByteString& sId_in , const ByteString& sText_in ){
+ //printf(" ResData::addFallbackData ( sId = %s , sText = %s )\n", sId_in.GetBuffer() , sText_in.GetBuffer() );
+ aFallbackData[ sId_in ] = sText_in;
+}
+bool ResData::getFallbackData( ByteString& sId_in , ByteString& sText_inout ){
+ sText_inout = aFallbackData[ sId_in ];
+ //printf("ResData::getFallbackData( sId = %s , return sText = %s \n" , sId_in.GetBuffer(), sText_inout.GetBuffer());
+ return sText_inout.Len() > 0;
+}
+
+void ResData::addMergedLanguage( ByteString& sLang ){
+ aMergedLanguages[ sLang ]=ByteString("1");
+}
+bool ResData::isMerged( ByteString& sLang ){
+ return aMergedLanguages[ sLang ].Equals("1");
+}
+
+/*****************************************************************************/
+BOOL ResData::SetId( const ByteString &rId, USHORT nLevel )
+/*****************************************************************************/
+{
+ if ( nLevel > nIdLevel )
+ {
+ nIdLevel = nLevel;
+ sId = rId;
+
+ if ( bChild && bChildWithText ) {
+ ByteString sError( "ResId after child definition" );
+ yyerror( sError.GetBufferAccess());
+ sError.ReleaseBufferAccess();
+ SetError();
+ }
+
+ if ( sId.Len() > 255 ) {
+ ByteString sWarning( "LocalId > 255 chars, truncating..." );
+ YYWarning( sWarning.GetBufferAccess());
+ sWarning.ReleaseBufferAccess();
+ sId.Erase( 255 );
+ sId.EraseTrailingChars( ' ' );
+ sId.EraseTrailingChars( '\t' );
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//
+// class Export
+//
+
+/*****************************************************************************/
+Export::Export( const ByteString &rOutput, BOOL bWrite,
+ const ByteString &rPrj, const ByteString &rPrjRoot , const ByteString& rFile )
+/*****************************************************************************/
+ :
+ pWordTransformer( NULL ),
+ aCharSet( RTL_TEXTENCODING_MS_1252 ),
+ bDefine( FALSE ),
+ bNextMustBeDefineEOL( FALSE ),
+ nLevel( 0 ),
+ nList( LIST_NON ),
+ nListIndex( 0 ),
+ nListLevel( 0 ),
+ bSkipFile( false ),
+ sProject( sPrj ),
+ sRoot( sPrjRoot ),
+ bEnableExport( bWrite ),
+ bMergeMode( bUnmerge ),
+ bError( FALSE ),
+ bReadOver( FALSE ),
+ bDontWriteOutput( FALSE ),
+ sFilename( rFile )
+{
+ pParseQueue = new ParserQueue( *this );
+ (void) rPrj;
+ (void) rPrjRoot;
+ (void) rFile;
+
+ if( !isInitialized ) InitLanguages();
+ // used when export is enabled
+
+ // open output stream
+ if ( bEnableExport ) {
+ aOutput.Open( String( rOutput, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_WRITE | STREAM_TRUNC );
+ if( !aOutput.IsOpen() ) {
+ printf("ERROR : Can't open file %s\n",rOutput.GetBuffer());
+ exit ( -1 );
+ }
+ aOutput.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
+
+ aOutput.SetLineDelimiter( LINEEND_CRLF );
+ }
+}
+
+/*****************************************************************************/
+Export::Export( const ByteString &rOutput, BOOL bWrite,
+ const ByteString &rPrj, const ByteString &rPrjRoot,
+ const ByteString &rMergeSource , const ByteString& rFile )
+/*****************************************************************************/
+ :
+ pWordTransformer( NULL ),
+ aCharSet( RTL_TEXTENCODING_MS_1252 ),
+ bDefine( FALSE ),
+ bNextMustBeDefineEOL( FALSE ),
+ nLevel( 0 ),
+ nList( LIST_NON ),
+ nListIndex( 0 ),
+ nListLevel( 0 ),
+ bSkipFile( false ),
+ sProject( sPrj ),
+ sRoot( sPrjRoot ),
+ bEnableExport( bWrite ),
+ bMergeMode( TRUE ),
+ sMergeSrc( rMergeSource ),
+ bError( FALSE ),
+ bReadOver( FALSE ),
+ bDontWriteOutput( FALSE ),
+ sFilename( rFile )
+{
+ (void) rPrj;
+ (void) rPrjRoot;
+ (void) rFile;
+ pParseQueue = new ParserQueue( *this );
+ if( !isInitialized ) InitLanguages( bMergeMode );
+ // used when merge is enabled
+
+ // open output stream
+ if ( bEnableExport ) {
+ aOutput.Open( String( rOutput, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_WRITE | STREAM_TRUNC );
+ aOutput.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
+ aOutput.SetLineDelimiter( LINEEND_CRLF );
+ }
+
+}
+
+/*****************************************************************************/
+void Export::Init()
+/*****************************************************************************/
+{
+ // resets the internal status, used before parseing another file
+ sActPForm = "";
+ bDefine = FALSE;
+ bNextMustBeDefineEOL = FALSE;
+ nLevel = 0;
+ nList = LIST_NON;
+ nListLang = ByteString( String::CreateFromAscii(""),RTL_TEXTENCODING_ASCII_US );
+ nListIndex = 0;
+ while ( aResStack.Count()) {
+ delete aResStack.GetObject(( ULONG ) 0 );
+ aResStack.Remove(( ULONG ) 0 );
+ }
+}
+
+/*****************************************************************************/
+Export::~Export()
+/*****************************************************************************/
+{
+ if( pParseQueue )
+ delete pParseQueue;
+ // close output stream
+ if ( bEnableExport )
+ aOutput.Close();
+ while ( aResStack.Count()) {
+ delete aResStack.GetObject(( ULONG ) 0 );
+ aResStack.Remove(( ULONG ) 0 );
+ }
+
+ if ( bMergeMode && !bUnmerge ) {
+ if ( !pMergeDataFile )
+ pMergeDataFile = new MergeDataFile( sMergeSrc,sFile , bErrorLog, aCharSet);//, bUTF8 );
+
+ //pMergeDataFile->WriteErrorLog( sActFileName );
+ delete pMergeDataFile;
+ }
+}
+
+/*****************************************************************************/
+int Export::Execute( int nToken, const char * pToken )
+/*****************************************************************************/
+{
+
+ ByteString sToken( pToken );
+ ByteString sOrig( sToken );
+/* printf("+---------------\n");
+ printf("sToken = %s\n",sToken.GetBuffer());
+ printf("nToken = %d\n",nToken);
+ printf("+---------------\n"); */
+ BOOL bWriteToMerged = bMergeMode;
+
+ if ( nToken == CONDITION ) {
+ ByteString sTestToken( pToken );
+ sTestToken.EraseAllChars( '\t' );
+ sTestToken.EraseAllChars( ' ' );
+ if (( !bReadOver ) && ( sTestToken.Search( "#ifndef__RSC_PARSER" ) == 0 ))
+ bReadOver = TRUE;
+ else if (( bReadOver ) && ( sTestToken.Search( "#endif" ) == 0 ))
+ bReadOver = FALSE;
+ }
+ if ((( nToken < FILTER_LEVEL ) || ( bReadOver )) &&
+ (!(( bNextMustBeDefineEOL ) && ( sOrig == "\n" )))) {
+ // this tokens are not mandatory for parsing, so ignore them ...
+ if ( bMergeMode )
+ WriteToMerged( sOrig , false ); // ... ore whrite them directly to dest.
+ return 0;
+ }
+
+ ResData *pResData = NULL;
+ if ( nLevel ) {
+ // res. exists at cur. level
+ pResData = aResStack.GetObject( nLevel-1 );
+ }
+ else if (( nToken != RESSOURCE ) &&
+ ( nToken != RESSOURCEEXPR ) &&
+ ( nToken != SMALRESSOURCE ) &&
+ ( nToken != LEVELUP ) &&
+ ( nToken != NORMDEFINE ) &&
+ ( nToken != RSCDEFINE ) &&
+ ( nToken != CONDITION ) &&
+ ( nToken != PRAGMA ))
+ {
+ // no res. exists at cur. level so return
+ if ( bMergeMode )
+ WriteToMerged( sOrig , false );
+ return 0;
+ }
+ // #define NO_LOCALIZE_EXPORT
+ if( bSkipFile ){
+ if ( bMergeMode ) {
+ WriteToMerged( sOrig , false );
+ }
+ return 1;
+ }
+
+
+ if ( bDefine ) {
+ if (( nToken != EMPTYLINE ) && ( nToken != LEVELDOWN ) && ( nToken != LEVELUP )) {
+ // cur. res. defined in macro
+ if ( bNextMustBeDefineEOL ) {
+ if ( nToken != RSCDEFINELEND ) {
+ // end of macro found, so destroy res.
+ bDefine = FALSE;
+ if ( bMergeMode ) {
+ /*if ( bDontWriteOutput && bUnmerge ) {
+ bDontWriteOutput = FALSE;
+ bNextMustBeDefineEOL = FALSE;
+ bDefine = TRUE;
+ }*/
+ MergeRest( pResData );
+ }
+ bNextMustBeDefineEOL = FALSE;
+ Execute( LEVELDOWN, "" );
+ }
+ else {
+ // next line also in macro definition
+ bNextMustBeDefineEOL = FALSE;
+ if ( bMergeMode )
+ WriteToMerged( sOrig , false );
+ return 1;
+ }
+ }
+ else if (( nToken != LISTASSIGNMENT ) && ( nToken != UIENTRIES )){
+ // cur. line has macro line end
+ ByteString sTmpLine( sToken );
+ sTmpLine.EraseAllChars( '\t' ); sTmpLine.EraseAllChars( ' ' );
+ #if 0
+ // impossible, unsigned is never negative
+ if( sTmpLine.Len() < 0 ){
+ if ( sTmpLine.GetChar(( USHORT )( sTmpLine.Len() - 1 )) != '\\' )
+ bNextMustBeDefineEOL = TRUE;
+ }
+ #endif
+ }
+ }
+ }
+
+ BOOL bExecuteDown = FALSE;
+ if ( nToken != LEVELDOWN ) {
+ USHORT nOpen = 0;
+ USHORT nClose = 0;
+ BOOL bReadOver1 = FALSE;
+ USHORT i = 0;
+ for ( i = 0; i < sToken.Len(); i++ ) {
+ if ( sToken.GetChar( i ) == '\"' )
+ bReadOver1 = !bReadOver1;
+ if ( !bReadOver1 && ( sToken.GetChar( i ) == '{' ))
+ nOpen++;
+ }
+
+ bReadOver1 = FALSE;
+ for ( i = 0; i < sToken.Len(); i++ ) {
+ if ( sToken.GetChar( i ) == '\"' )
+ bReadOver1 = !bReadOver1;
+ if ( !bReadOver1 && ( sToken.GetChar( i ) == '}' ))
+ nClose++;
+ }
+
+ if ( nOpen < nClose )
+ bExecuteDown = TRUE;
+ }
+ switch ( nToken ) {
+
+ case NORMDEFINE:
+ //printf("sToken = '%s'",sToken.GetBuffer());
+ while( sToken.SearchAndReplace( "\r", " " ) != STRING_NOTFOUND ) {};
+ while( sToken.SearchAndReplace( "\t", " " ) != STRING_NOTFOUND ) {};
+ while( sToken.SearchAndReplace( " ", " " ) != STRING_NOTFOUND ) {};
+ if( sToken.EqualsIgnoreCaseAscii( "#define NO_LOCALIZE_EXPORT" ) ){
+ bSkipFile = true;
+ return 0;
+ }
+ if ( bMergeMode )
+ WriteToMerged( sOrig , false );
+
+ return 0;
+
+
+ case RSCDEFINE:
+ bDefine = TRUE; // res. defined in macro
+
+ case RESSOURCE:
+ case RESSOURCEEXPR: {
+ bDontWriteOutput = FALSE;
+ if ( nToken != RSCDEFINE )
+ bNextMustBeDefineEOL = FALSE;
+ // this is the beginning of a new res.
+ nLevel++;
+ if ( nLevel > 1 ) {
+ aResStack.GetObject( nLevel - 2 )->bChild = TRUE;
+ }
+
+ // create new instance for this res. and fill mandatory fields
+
+ pResData = new ResData( sActPForm, FullId() , sFilename );
+ aResStack.Insert( pResData, LIST_APPEND );
+ ByteString sBackup( sToken );
+ sToken.EraseAllChars( '\n' );
+ sToken.EraseAllChars( '\r' );
+ sToken.EraseAllChars( '{' );
+ while( sToken.SearchAndReplace( "\t", " " ) != STRING_NOTFOUND ) {};
+ sToken.EraseTrailingChars( ' ' );
+ ByteString sT = sToken.GetToken( 0, ' ' );
+ pResData->sResTyp = sT.ToLowerAscii();
+ ByteString sId( sToken.Copy( pResData->sResTyp.Len() + 1 ));
+ ByteString sCondition;
+ if ( sId.Search( "#" ) != STRING_NOTFOUND ) {
+ // between ResTyp, Id and paranthes is a precomp. condition
+ sCondition = "#";
+ sCondition += sId.GetToken( 1, '#' );
+ sId = sId.GetToken( 0, '#' );
+ }
+ sId = sId.GetToken( 0, '/' );
+ CleanValue( sId );
+ sId = sId.EraseAllChars( '\t' );
+ pResData->SetId( sId, ID_LEVEL_IDENTIFIER );
+ if ( sCondition.Len()) {
+ ByteString sEmpty( "" );
+ Execute( CONDITION, sEmpty.GetBufferAccess()); // execute the
+ // precomp.
+ // condition
+ sEmpty.ReleaseBufferAccess();
+ }
+ }
+ break;
+ case SMALRESSOURCE: {
+ bDontWriteOutput = FALSE;
+ // this is the beginning of a new res.
+ bNextMustBeDefineEOL = FALSE;
+ nLevel++;
+ if ( nLevel > 1 ) {
+ aResStack.GetObject( nLevel - 2 )->bChild = TRUE;
+ }
+
+ // create new instance for this res. and fill mandatory fields
+
+ pResData = new ResData( sActPForm, FullId() , sFilename );
+ aResStack.Insert( pResData, LIST_APPEND );
+ sToken.EraseAllChars( '\n' );
+ sToken.EraseAllChars( '\r' );
+ sToken.EraseAllChars( '{' );
+ sToken.EraseAllChars( '\t' );
+ sToken.EraseAllChars( ' ' );
+ sToken.EraseAllChars( '\\' );
+ pResData->sResTyp = sToken.ToLowerAscii();
+ }
+ break;
+ case LEVELUP: {
+ // push
+ if ( nList )
+ nListLevel++;
+ if ( nList )
+ break;
+
+ bDontWriteOutput = FALSE;
+ ByteString sLowerTyp;
+ if ( pResData )
+ sLowerTyp = "unknown";
+ nLevel++;
+ if ( nLevel > 1 ) {
+ aResStack.GetObject( nLevel - 2 )->bChild = TRUE;
+ }
+
+ ResData *pNewData = new ResData( sActPForm, FullId() , sFilename );
+ pNewData->sResTyp = sLowerTyp;
+ aResStack.Insert( pNewData, LIST_APPEND );
+ }
+ break;
+ case LEVELDOWN: {
+ // pop
+ if ( !nList ) {
+ bDontWriteOutput = FALSE;
+ if ( nLevel ) {
+ if ( bDefine && (nLevel == 1 )) {
+ bDefine = FALSE;
+ bNextMustBeDefineEOL = FALSE;
+ }
+ WriteData( pResData );
+ delete aResStack.GetObject( nLevel - 1 );
+ aResStack.Remove( nLevel - 1 );
+ nLevel--;
+ }
+ }
+ else {
+ if ( bDefine )
+ bNextMustBeDefineEOL = TRUE;
+ if ( !nListLevel ) {
+ if ( bMergeMode )
+ MergeRest( pResData, MERGE_MODE_LIST );
+ nList = LIST_NON;
+ }
+ else
+ nListLevel--;
+ }
+ }
+ break;
+ case ASSIGNMENT: {
+ bDontWriteOutput = FALSE;
+ // interpret different types of assignement
+ ByteString sKey = sToken.GetToken( 0, '=' );
+ sKey.EraseAllChars( ' ' );
+ sKey.EraseAllChars( '\t' );
+ ByteString sValue = sToken.GetToken( 1, '=' );
+ CleanValue( sValue );
+ if ( sKey.ToUpperAscii() == "IDENTIFIER" ) {
+ ByteString sId( sValue.EraseAllChars( '\t' ));
+ pResData->SetId( sId.EraseAllChars( ' ' ), ID_LEVEL_IDENTIFIER );
+ }
+ else if ( sKey == "HELPID" ) {
+ pResData->sHelpId = sValue;
+ }
+ else if ( sKey == "STRINGLIST" ) {
+ //if ( bUnmerge ){
+ // ( sOrig.SearchAndReplace( "=", "[ de ] =" ));
+ //}
+
+ pResData->bList = TRUE;
+ nList = LIST_STRING;
+ //ByteString sLang("en-US" , RTL_TEXTENCODING_ASCII_US );
+ nListLang = SOURCE_LANGUAGE;
+ nListIndex = 0;
+ nListLevel = 0;
+ }
+ else if ( sKey == "FILTERLIST" ) {
+ //if ( bUnmerge ){
+ // ( sOrig.SearchAndReplace( "=", "[ de ] =" ));
+ //}
+ pResData->bList = TRUE;
+ nList = LIST_FILTER;
+ //ByteString sLang("en-US" , RTL_TEXTENCODING_ASCII_US );
+ nListLang = SOURCE_LANGUAGE;
+ nListIndex = 0;
+ nListLevel = 0;
+ }
+ else if ( sKey == "UIENTRIES" ) {
+ //if ( bUnmerge ){
+ // ( sOrig.SearchAndReplace( "=", "[ de ] =" ));}
+ pResData->bList = TRUE;
+ nList = LIST_UIENTRIES;
+ //ByteString sLang("en-US" , RTL_TEXTENCODING_ASCII_US );
+ nListLang = SOURCE_LANGUAGE;
+ nListIndex = 0;
+ nListLevel = 0;
+ }
+ if (( sToken.Search( "{" ) != STRING_NOTFOUND ) &&
+ ( sToken.GetTokenCount( '{' ) > sToken.GetTokenCount( '}' )))
+ {
+ //WorkOnTokenSet( LEVELUP, pTkn );
+ Parse( LEVELUP, "" );
+ }
+ //if ( bUnmerge && ( nListLang.EqualsIgnoreCaseAscii("de") || nListLang.EqualsIgnoreCaseAscii("en-US") ) && ListExists( pResData, nList ))
+ // bDontWriteOutput = TRUE;
+ }
+ break;
+ case UIENTRIES:
+ case LISTASSIGNMENT: {
+ bDontWriteOutput = FALSE;
+ ByteString sTmpToken( sToken);
+ sTmpToken.EraseAllChars(' ');
+ USHORT nPos = 0;
+ //nPos = sTmpToken.ToLowerAscii().Search("[de]=");
+ nPos = sTmpToken.ToLowerAscii().Search("[en-us]=");
+ if( nPos != STRING_NOTFOUND ) {
+ //if ( bUnmerge ){
+ // ( sOrig.SearchAndReplace( "=", "[ de ] =" ));
+ //}
+ ByteString sKey = sTmpToken.Copy( 0 , nPos );
+ sKey.EraseAllChars( ' ' );
+ sKey.EraseAllChars( '\t' );
+ ByteString sValue = sToken.GetToken( 1, '=' );
+ CleanValue( sValue );
+ if ( sKey.ToUpperAscii() == "STRINGLIST" ) {
+ pResData->bList = TRUE;
+ nList = LIST_STRING;
+ //ByteString sLang("en-US" , RTL_TEXTENCODING_ASCII_US );
+ nListLang = SOURCE_LANGUAGE;
+ nListIndex = 0;
+ nListLevel = 0;
+ }
+ else if ( sKey == "FILTERLIST" ) {
+ pResData->bList = TRUE;
+ nList = LIST_FILTER;
+ //ByteString sLang("en-US" , RTL_TEXTENCODING_ASCII_US );
+ nListLang = SOURCE_LANGUAGE;
+ nListIndex = 0;
+ nListLevel = 0;
+ }
+ // PairedList
+ else if ( sKey == "PAIREDLIST" ) {
+ pResData->bList = TRUE;
+ nList = LIST_PAIRED;
+ //ByteString sLang("en-US" , RTL_TEXTENCODING_ASCII_US );
+ nListLang = SOURCE_LANGUAGE;
+ nListIndex = 0;
+ nListLevel = 0;
+ }
+
+ else if ( sKey == "ITEMLIST" ) {
+ pResData->bList = TRUE;
+ nList = LIST_ITEM;
+ //ByteString sLang("en-US" , RTL_TEXTENCODING_ASCII_US );
+ nListLang = SOURCE_LANGUAGE;
+ nListIndex = 0;
+ nListLevel = 0;
+ }
+ else if ( sKey == "UIENTRIES" ) {
+ pResData->bList = TRUE;
+ nList = LIST_UIENTRIES;
+ //ByteString sLang("en-US" , RTL_TEXTENCODING_ASCII_US );
+ nListLang = SOURCE_LANGUAGE;
+ nListIndex = 0;
+ nListLevel = 0;
+ }
+ /*if ( bUnmerge && ( nListLang.EqualsIgnoreCaseAscii( "de" )
+ || nListLang.EqualsIgnoreCaseAscii("en-US" ) )
+ && ListExists( pResData, nList ))
+ bDontWriteOutput = TRUE;*/
+ }
+ else {
+ // new res. is a String- or FilterList
+ ByteString sKey = sToken.GetToken( 0, '[' );
+ sKey.EraseAllChars( ' ' );
+ sKey.EraseAllChars( '\t' );
+ if ( sKey.ToUpperAscii() == "STRINGLIST" )
+ nList = LIST_STRING;
+ else if ( sKey == "FILTERLIST" )
+ nList = LIST_FILTER;
+ else if ( sKey == "PAIREDLIST" )
+ nList = LIST_PAIRED; // abcd
+ else if ( sKey == "ITEMLIST" )
+ nList = LIST_ITEM;
+ else if ( sKey == "UIENTRIES" )
+ nList = LIST_UIENTRIES;
+ if ( nList ) {
+ ByteString sLang=sToken.GetToken( 1, '[' ).GetToken( 0, ']' );
+ CleanValue( sLang );
+ nListLang = sLang;
+ /*if (( bUnmerge ) && ( !nListLang.EqualsIgnoreCaseAscii("de")) && ( !nListLang.EqualsIgnoreCaseAscii("en-US")))
+ bDontWriteOutput = TRUE;*/
+ nListIndex = 0;
+ nListLevel = 0;
+ /*if ( bUnmerge && nListLang.EqualsIgnoreCaseAscii("de") && ListExists( pResData, nList ) )
+ bDontWriteOutput = TRUE;*/
+ }
+ }
+ }
+ break;
+ case TEXT:
+ case _LISTTEXT:
+ case LISTTEXT: {
+ // this is an entry for a String- or FilterList
+ if ( nList ) {
+ SetChildWithText();
+ ByteString sEntry( sToken.GetToken( 1, '\"' ));
+ if ( sToken.GetTokenCount( '\"' ) > 3 )
+ sEntry += "\"";
+ if ( sEntry == "\\\"" )
+ sEntry = "\"";
+ //sEntry = sEntry.Convert( aCharSet, RTL_TEXTENCODING_MS_1252 );
+ //sEntry = sEntry.Convert( RTL_TEXTENCODING_MS_1252, RTL_TEXTENCODING_UTF8 );
+ InsertListEntry( sEntry, sOrig );
+ if ( bMergeMode && ( sEntry != "\"" )) {
+ PrepareTextToMerge( sOrig, nList, nListLang, pResData );
+ }
+ }
+ }
+ break;
+ case LONGTEXTLINE:
+ case TEXTLINE:
+ bDontWriteOutput = FALSE;
+ if ( nLevel ) {
+ CutComment( sToken );
+
+ // this is a text line!!!
+ ByteString sKey = sToken.GetToken( 0, '=' ).GetToken( 0, '[' );
+ sKey.EraseAllChars( ' ' );
+ sKey.EraseAllChars( '\t' );
+ ByteString sText( GetText( sToken, nToken ));
+ if ( !bMergeMode )
+ sText = sText.Convert( aCharSet, RTL_TEXTENCODING_MS_1252 );
+ ByteString sLang;
+ if ( sToken.GetToken( 0, '=' ).Search( "[" ) != STRING_NOTFOUND ) {
+ sLang = sToken.GetToken( 0, '=' ).GetToken( 1, '[' ).GetToken( 0, ']' );
+ CleanValue( sLang );
+ }
+ ByteString nLangIndex = sLang;
+ ByteString sOrigKey = sKey;
+ if ( sText.Len() && sLang.Len() ) {
+ if (( sKey.ToUpperAscii() == "TEXT" ) ||
+ ( sKey == "MESSAGE" ) ||
+ ( sKey == "CUSTOMUNITTEXT" ) ||
+ ( sKey == "SLOTNAME" ) ||
+ ( sKey == "UINAME" ))
+ {
+ //if ( bUnmerge && sToken.GetToken( 0, '=' ).Search( "[" ) == STRING_NOTFOUND )
+ // ( sOrig.SearchAndReplace( "=", "[ de ] =" ));
+
+ SetChildWithText();
+ //if ( nLangIndex.EqualsIgnoreCaseAscii("en-US") )
+ if ( Export::isSourceLanguage( nLangIndex ) )
+ pResData->SetId( sText, ID_LEVEL_TEXT );
+
+ pResData->bText = TRUE;
+ pResData->sTextTyp = sOrigKey;
+ if ( bMergeMode ) {
+ PrepareTextToMerge( sOrig, STRING_TYP_TEXT, nLangIndex, pResData );
+ //if ( bUnmerge )
+ // pResData->sText[ nLangIndex ] = sText;
+ }
+ else {
+ if ( pResData->sText[ nLangIndex ].Len()) {
+ ByteString sError( "Language " );
+ sError += nLangIndex;
+ sError += " defined twice";
+ }
+ pResData->sText[ nLangIndex ] = sText;
+ }
+ }
+ else if ( sKey == "HELPTEXT" ) {
+ //if ( bUnmerge && sToken.GetToken( 0, '=' ).Search( "[" ) == STRING_NOTFOUND ){
+ // ( sOrig.SearchAndReplace( "=", "[ de ] =" ));
+ // }
+ SetChildWithText();
+ pResData->bHelpText = TRUE;
+ if ( bBreakWhenHelpText ) {
+ ByteString sError( "\"HelpText\" found in source\n" );
+ YYWarning( sError.GetBufferAccess());
+ sError.ReleaseBufferAccess();
+ SetError();
+ }
+ if ( bMergeMode )
+ PrepareTextToMerge( sOrig, STRING_TYP_HELPTEXT, nLangIndex, pResData );
+ //if ( bUnmerge )
+ // pResData->sHelpText[ nLangIndex ] = sText;
+ else {
+ if ( pResData->sHelpText[ nLangIndex ].Len()) {
+ ByteString sError( "Language " );
+ sError += nLangIndex;
+ sError += " defined twice";
+ }
+ pResData->sHelpText[ nLangIndex ] = sText;
+ }
+ }
+ else if ( sKey == "QUICKHELPTEXT" ) {
+ //if ( bUnmerge && sToken.GetToken( 0, '=' ).Search( "[" ) == STRING_NOTFOUND ){
+ // ( sOrig.SearchAndReplace( "=", "[ de ] =" ));
+ // }
+ SetChildWithText();
+ pResData->bQuickHelpText = TRUE;
+ if ( bMergeMode )
+ PrepareTextToMerge( sOrig, STRING_TYP_QUICKHELPTEXT, nLangIndex, pResData );
+ //if ( bUnmerge )
+ // pResData->sQuickHelpText[ nLangIndex ] = sText;
+ else {
+ if ( pResData->sQuickHelpText[ nLangIndex ].Len()) {
+ ByteString sError( "Language " );
+ sError += nLangIndex;
+ sError += " defined twice";
+ }
+ pResData->sQuickHelpText[ nLangIndex ] = sText;
+ }
+ }
+ else if ( sKey == "TITLE" ) {
+ //if ( bUnmerge && sToken.GetToken( 0, '=' ).Search( "[" ) == STRING_NOTFOUND ){
+ // ( sOrig.SearchAndReplace( "=", "[ de ] =" ));
+ // }
+ SetChildWithText();
+ pResData->bTitle = TRUE;
+ if ( bMergeMode )
+ PrepareTextToMerge( sOrig, STRING_TYP_TITLE, nLangIndex, pResData );
+ //if ( bUnmerge )
+ // pResData->sTitle[ nLangIndex ] = sText;
+ else {
+ if ( pResData->sTitle[ nLangIndex ].Len()) {
+ ByteString sError( "Language " );
+ sError += nLangIndex;
+ sError += " defined twice";
+ }
+ pResData->sTitle[ nLangIndex ] = sText;
+ }
+ }
+ else if ( sKey == "ACCESSPATH" ) {
+ pResData->SetId( sText, ID_LEVEL_ACCESSPATH );
+ }
+ else if ( sKey == "FIELDNAME" ) {
+ pResData->SetId( sText, ID_LEVEL_FIELDNAME );
+ }
+ }
+ }
+ break;
+ case NEWTEXTINRES: {
+ bDontWriteOutput = TRUE;
+ // this means something like // ### Achtung : Neuer Text ...
+ /*ByteString sLang( "GERMAN" );
+ ByteString sText = sToken.GetToken( 2, ':' ).GetToken( 0, '*' );
+ CleanValue( sText );
+ if ( sText.Len())
+ pResData->sText[ sLang ] = sText;*/
+ }
+ break;
+ case APPFONTMAPPING: {
+ bDontWriteOutput = FALSE;
+ // this is a AppfontMapping, so look if its a definition
+ // of field size
+ ByteString sKey = sToken.GetToken( 0, '=' );
+ sKey.EraseAllChars( ' ' );
+ sKey.EraseAllChars( '\t' );
+ ByteString sMapping = sToken.GetToken( 1, '=' );
+ sMapping = sMapping.GetToken( 1, '(' );
+ sMapping = sMapping.GetToken( 0, ')' );
+ sMapping.EraseAllChars( ' ' );
+ sMapping.EraseAllChars( '\t' );
+ if ( sKey.ToUpperAscii() == "SIZE" ) {
+ pResData->nWidth = ( USHORT ) sMapping.GetToken( 0, ',' ).ToInt64();
+ }
+ else if ( sKey == "POSSIZE" ) {
+ pResData->nWidth = ( USHORT ) sMapping.GetToken( 2, ',' ).ToInt64();
+ }
+ }
+ break;
+ case RSCDEFINELEND:
+ bDontWriteOutput = FALSE;
+ break;
+ case CONDITION: {
+ bDontWriteOutput = FALSE;
+ while( sToken.SearchAndReplace( "\r", " " ) != STRING_NOTFOUND ) {};
+ while( sToken.SearchAndReplace( "\t", " " ) != STRING_NOTFOUND ) {};
+ while( sToken.SearchAndReplace( " ", " " ) != STRING_NOTFOUND ) {};
+ ByteString sCondition = sToken.GetToken( 0, ' ' );
+ if ( sCondition == "#ifndef" ) {
+ sActPForm = "!defined ";
+ sActPForm += sToken.GetToken( 1, ' ' );
+ }
+ else if ( sCondition == "#ifdef" ) {
+ sActPForm = "defined ";
+ sActPForm += sToken.GetToken( 1, ' ' );
+ }
+ else if ( sCondition == "#if" ) {
+ sActPForm = sToken.Copy( 4 );
+ while ( sActPForm.SearchAndReplace( "||", "\\or" ) != STRING_NOTFOUND ) {};
+ }
+ else if ( sCondition == "#elif" ) {
+ sActPForm = sToken.Copy( 6 );
+ while ( sActPForm.SearchAndReplace( "||", "\\or" ) != STRING_NOTFOUND ) {};
+ }
+ else if ( sCondition == "#else" ) {
+ sActPForm = sCondition;
+ }
+ else if ( sCondition == "#endif" ) {
+ sActPForm = "";
+ }
+ else break;
+ if ( nLevel ) {
+ WriteData( pResData, TRUE );
+ pResData->sPForm = sActPForm;
+ }
+ }
+ break;
+ case EMPTYLINE : {
+ bDontWriteOutput = FALSE;
+ if ( bDefine ) {
+ bNextMustBeDefineEOL = FALSE;
+ bDefine = FALSE;
+ while ( nLevel )
+ Parse( LEVELDOWN, "" );
+ //WorkOnTokenSet( LEVELDOWN, pTkn );
+ }
+ }
+ break;
+ case PRAGMA : {
+ bDontWriteOutput = FALSE;
+ while( sToken.SearchAndReplace( "\t", " " ) != STRING_NOTFOUND ) {};
+ while( sToken.SearchAndReplace( " ", " " ) != STRING_NOTFOUND ) {};
+ sToken.EraseLeadingChars( ' ' );
+ sToken.EraseTrailingChars( ' ' );
+
+ ByteString sCharset = sToken.GetToken( 1, ' ' );
+ ByteString sSet = sToken.GetToken( 2, ' ' );
+ if (( sCharset.ToUpperAscii() == "CHARSET_IBMPC" ) ||
+ ( sCharset == "RTL_TEXTENCODING_IBM_850" ) ||
+ (( sCharset == "CHARSET" ) && ( sSet.ToUpperAscii() == "IBMPC" )))
+ {
+ aCharSet = RTL_TEXTENCODING_IBM_850;
+ }
+ else if (( sCharset == "CHARSET_ANSI" ) ||
+ ( sCharset == "RTL_TEXTENCODING_MS_1252" ) ||
+ (( sCharset == "CHARSET" ) && ( sSet.ToUpperAscii() == "ANSI" )))
+ {
+ aCharSet = RTL_TEXTENCODING_MS_1252;
+ }
+ }
+ break;
+ case TEXTREFID : {
+ bDontWriteOutput = TRUE;
+ /*ByteString sK = sToken.GetToken( 0, '=' );
+ ByteString sKey = sK.EraseAllChars( '\t' ).EraseAllChars( ' ' );
+ ByteString sT = sToken.GetToken( 1, '=' ).GetToken( 0, ';' );
+ USHORT nRefId = ( USHORT ) sT.EraseAllChars( '\t' ).EraseAllChars( ' ' ).ToInt32();
+ if (( sKey.ToUpperAscii() == "TEXT" ) ||
+ ( sKey == "MESSAGE" ) ||
+ ( sKey == "CUSTOMUNITTEXT" ) ||
+ ( sKey == "SLOTNAME" ) ||
+ ( sKey == "UINAME" ))
+ pResData->nTextRefId = nRefId;
+ else if ( sKey == "HELPTEXT" )
+ pResData->nHelpTextRefId = nRefId;
+ else if ( sKey == "QUICKHELPTEXT" )
+ pResData->nQuickHelpTextRefId = nRefId;
+ else if ( sKey == "TITLE" )
+ pResData->nTitleRefId = nRefId;*/
+ }
+ }
+ if ( bWriteToMerged ) {
+ // the current token must be written to dest. without merging
+
+ if( bDefine && sOrig.Len() > 2 ){
+ for( USHORT n = 0 ; n < sOrig.Len() ; n++ ){
+ if( sOrig.GetChar( n ) == '\n' && sOrig.GetChar( n-1 ) != '\\'){
+ sOrig.Insert('\\' , n++ );
+ }
+ }
+ }
+ WriteToMerged( sOrig , false);
+ }
+
+ if ( bExecuteDown ) {
+ Parse( LEVELDOWN, "" );
+ //WorkOnTokenSet( LEVELDOWN, pTkn );
+ }
+
+ return 1;
+}
+
+/*****************************************************************************/
+void Export::CutComment( ByteString &rText )
+/*****************************************************************************/
+{
+ if ( rText.Search( "//" ) != STRING_NOTFOUND ) {
+ ByteString sWork( rText );
+ sWork.SearchAndReplaceAll( "\\\"", "XX" );
+ USHORT i = 0;
+ BOOL bInner = FALSE;
+
+ while ( i < sWork.Len() - 1 ) {
+ if ( sWork.GetChar( i ) == '\"' )
+ bInner = !bInner;
+ else if
+ (( sWork.GetChar( i ) == '/' ) &&
+ ( !bInner ) &&
+ ( sWork.GetChar( i + 1 ) == '/' ))
+ {
+ rText.Erase( i );
+ return;
+ }
+ i++;
+ }
+ }
+}
+
+void Export::UnmergeUTF8( ByteString& sOrig ){
+ USHORT nPos1 = sOrig.Search('\"');
+ USHORT nPos2 = sOrig.SearchBackward('\"');
+ if( nPos1 > 0 && nPos2 > 0 && nPos1 < nPos2){
+ ByteString sPart = sOrig.Copy(nPos1+1 , nPos2-1);
+ ByteString sPartUTF8 = sPart;
+ sPartUTF8.Convert( RTL_TEXTENCODING_MS_1252 , RTL_TEXTENCODING_UTF8 );
+ sOrig.SearchAndReplace( sPart , sPartUTF8 );
+ }
+}
+
+/*****************************************************************************/
+BOOL Export::ListExists( ResData *pResData, USHORT nLst )
+/*****************************************************************************/
+{
+ switch ( nLst ) {
+ case LIST_STRING: return pResData->pStringList != NULL;
+ case LIST_FILTER: return pResData->pFilterList != NULL;
+ case LIST_ITEM: return pResData->pItemList != NULL;
+ case LIST_PAIRED: return pResData->pPairedList != NULL;
+ case LIST_UIENTRIES: return pResData->pUIEntries != NULL;
+ }
+ return FALSE;
+}
+
+/*****************************************************************************/
+BOOL Export::WriteData( ResData *pResData, BOOL bCreateNew )
+/*****************************************************************************/
+{
+ if ( bMergeMode ) {
+ MergeRest( pResData );
+ return TRUE;
+ }
+
+ if ( bUnmerge )
+ return TRUE;
+
+/* ByteStringHashMap::iterator pos3 = pResData->sText.begin();
+ ByteStringHashMap::iterator end3 = pResData->sText.end();
+ for(;pos3!=end3;++pos3){
+
+ printf("[%s]=%s\n", pos3->first.GetBuffer(), pos3->second.GetBuffer() );
+ }*/
+ // mandatory to export: en-US
+
+ if (( //pResData->sText[ ByteString("de") ].Len() &&
+ ( pResData->sText[ SOURCE_LANGUAGE ].Len()))
+ ||
+ ( //pResData->sHelpText[ ByteString("de") ].Len() &&
+ ( pResData->sHelpText[ SOURCE_LANGUAGE ].Len()))
+ ||
+ ( //pResData->sQuickHelpText[ ByteString("de") ].Len() &&
+ ( pResData->sQuickHelpText[ SOURCE_LANGUAGE ].Len()))
+ ||
+ ( //pResData->sTitle[ ByteString("de") ].Len() &&
+ ( pResData->sTitle[ SOURCE_LANGUAGE ].Len())))
+
+ {
+ FillInFallbacks( pResData );
+
+ ByteString sGID = pResData->sGId;
+ ByteString sLID;
+ if ( !sGID.Len())
+ sGID = pResData->sId;
+ else
+ sLID = pResData->sId;
+
+ ByteString sXText;
+ ByteString sXHText;
+ ByteString sXQHText;
+ ByteString sXTitle;
+
+ ByteString sTimeStamp( Export::GetTimeStamp());
+ ByteString sCur;
+
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ if ( !sCur.EqualsIgnoreCaseAscii("x-comment") ){
+ if ( pResData->sText[ sCur ].Len())
+ sXText = pResData->sText[ sCur ];
+ else {
+ sXText = pResData->sText[ SOURCE_LANGUAGE ];
+ /*if ( !sXText.Len())
+ sXText = pResData->sText[ ByteString("en") ];
+ if ( !sXText.Len())
+ sXText = pResData->sText[ ByteString("de") ];*/
+ }
+
+ if ( pResData->sHelpText[ sCur ].Len())
+ sXHText = pResData->sHelpText[ sCur ];
+ else {
+ sXHText = pResData->sHelpText[ SOURCE_LANGUAGE ];
+ /*if ( !sXHText.Len())
+ sXHText = pResData->sHelpText[ ByteString("en") ];
+ if ( !sXText.Len())
+ sXHText = pResData->sHelpText[ ByteString("de") ];*/
+ }
+
+ if ( pResData->sQuickHelpText[ sCur ].Len())
+ sXQHText = pResData->sQuickHelpText[ sCur ];
+ else {
+ sXQHText = pResData->sQuickHelpText[ SOURCE_LANGUAGE ];
+ /*if ( !sXQHText.Len())
+ sXQHText = pResData->sQuickHelpText[ ByteString("en") ];
+ if ( !sXQHText.Len())
+ sXQHText = pResData->sQuickHelpText[ ByteString("de") ];*/
+ }
+
+ if ( pResData->sTitle[ sCur ].Len())
+ sXTitle = pResData->sTitle[ sCur ];
+ else {
+ sXTitle = pResData->sTitle[ SOURCE_LANGUAGE ];
+ /*if ( !sXTitle.Len())
+ sXTitle = pResData->sTitle[ ByteString("en") ];
+ if ( !sXTitle.Len())
+ sXTitle = pResData->sTitle[ ByteString("de") ];*/
+ }
+
+ if ( !sXText.Len())
+ sXText = "-";
+
+ if ( !sXHText.Len()) {
+ /*if ( pResData->sHelpText[ ByteString("de") ].Len())
+ sXHText = pResData->sHelpText[ ByteString("de") ];*/
+ if ( pResData->sHelpText[ SOURCE_LANGUAGE ].Len())
+ sXHText = pResData->sHelpText[ SOURCE_LANGUAGE ];
+ /*else if ( pResData->sHelpText[ ByteString("en") ].Len())
+ sXHText = pResData->sHelpText[ ByteString("en") ];*/
+ }
+ }
+ else
+ sXText = pResData->sText[ sCur ];
+
+ if ( bEnableExport ) {
+ ByteString sOutput( sProject ); sOutput += "\t";
+ if ( sRoot.Len())
+ sOutput += sActFileName;
+ sOutput += "\t0\t";
+ sOutput += pResData->sResTyp; sOutput += "\t";
+ sOutput += sGID; sOutput += "\t";
+ sOutput += sLID; sOutput += "\t";
+ sOutput += pResData->sHelpId; sOutput += "\t";
+ sOutput += pResData->sPForm; sOutput += "\t";
+ sOutput += ByteString::CreateFromInt64( pResData->nWidth ); sOutput += "\t";
+ sOutput += sCur; sOutput += "\t";
+
+
+ sOutput += sXText; sOutput += "\t";
+ sOutput += sXHText; sOutput += "\t";
+ sOutput += sXQHText; sOutput+= "\t";
+ sOutput += sXTitle; sOutput += "\t";
+ sOutput += sTimeStamp;
+
+ // if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( sProject ) ) )
+ aOutput.WriteLine( sOutput );
+ }
+
+ if ( bCreateNew ) {
+ pResData->sText[ sCur ] = "";
+ pResData->sHelpText[ sCur ] = "";
+ pResData->sQuickHelpText[ sCur ]= "";
+ pResData->sTitle[ sCur ] = "";
+ }
+ }
+ }
+ FillInFallbacks( pResData );
+ if ( pResData->pStringList ) {
+ ByteString sList( "stringlist" );
+ WriteExportList( pResData, pResData->pStringList, sList, bCreateNew );
+ if ( bCreateNew )
+ pResData->pStringList = 0;
+ }
+ if ( pResData->pFilterList ) {
+ ByteString sList( "filterlist" );
+ WriteExportList( pResData, pResData->pFilterList, sList, bCreateNew );
+ if ( bCreateNew )
+ pResData->pFilterList = 0;
+ }
+ if ( pResData->pItemList ) {
+ ByteString sList( "itemlist" );
+ WriteExportList( pResData, pResData->pItemList, sList, bCreateNew );
+ if ( bCreateNew )
+ pResData->pItemList = 0;
+ }
+ if ( pResData->pPairedList ) {
+ ByteString sList( "pairedlist" );
+ WriteExportList( pResData, pResData->pPairedList, sList, bCreateNew );
+ if ( bCreateNew )
+ pResData->pItemList = 0;
+ }
+ if ( pResData->pUIEntries ) {
+ ByteString sList( "uientries" );
+ WriteExportList( pResData, pResData->pUIEntries, sList, bCreateNew );
+ if ( bCreateNew )
+ pResData->pUIEntries = 0;
+ }
+ return TRUE;
+}
+ByteString Export::GetPairedListID( const ByteString& sText ){
+// < "STRING" ; IDENTIFIER ; > ;
+ ByteString sIdent = sText.GetToken( 1, ';' );
+ sIdent.ToUpperAscii();
+ while( sIdent.SearchAndReplace( "\t", " " ) != STRING_NOTFOUND ) {};
+ sIdent.EraseTrailingChars( ' ' );
+ sIdent.EraseLeadingChars( ' ' );
+ return sIdent;
+}
+ByteString Export::GetPairedListString( const ByteString& sText ){
+// < "STRING" ; IDENTIFIER ; > ;
+ ByteString sString = sText.GetToken( 0, ';' );
+ while( sString.SearchAndReplace( "\t", " " ) != STRING_NOTFOUND ) {};
+ sString.EraseTrailingChars( ' ' );
+ ByteString s1 = sString.Copy( sString.Search( '\"' )+1 );
+ sString = s1.Copy( 0 , s1.SearchBackward( '\"' ) );
+ sString.EraseTrailingChars( ' ' );
+ sString.EraseLeadingChars( ' ' );
+ return sString;
+}
+ByteString Export::StripList( const ByteString& sText ){
+ ByteString s1 = sText.Copy( sText.Search( '\"' ) + 1 );
+ return s1.Copy( 0 , s1.SearchBackward( '\"' ) );
+}
+
+/*****************************************************************************/
+BOOL Export::WriteExportList( ResData *pResData, ExportList *pExportList,
+ const ByteString &rTyp, BOOL bCreateNew )
+/*****************************************************************************/
+{
+ ByteString sGID = pResData->sGId;
+ if ( !sGID.Len())
+ sGID = pResData->sId;
+ else {
+ sGID += ".";
+ sGID += pResData->sId;
+ sGID.EraseTrailingChars( '.' );
+ }
+
+ ByteString sTimeStamp( Export::GetTimeStamp());
+ ByteString sCur;
+ for ( ULONG i = 0; pExportList != NULL && i < pExportList->Count(); i++ ) {
+ ExportListEntry *pEntry = pExportList->GetObject( i );
+ // mandatory for export: german and eng. and/or enus
+ //ByteString a("Export::WriteExportList::pEntry");
+ //Export::DumpMap( a, *pEntry );
+
+ ByteString sLID( ByteString::CreateFromInt64( i + 1 ));
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ if ( //1 )
+ //(*pEntry)[ ByteString("de") ].Len() &&
+ (*pEntry)[ SOURCE_LANGUAGE ].Len() )
+ //||
+ // (*pEntry)[ ByteString("en") ].Len()))
+ {
+ if ( bEnableExport )
+ {
+ ByteString sText((*pEntry)[ SOURCE_LANGUAGE ] );
+
+ // Strip PairList Line String
+ if( rTyp.EqualsIgnoreCaseAscii("pairedlist") ){
+ sLID = GetPairedListID( sText );
+ if ((*pEntry)[ sCur ].Len())
+ sText = (*pEntry)[ sCur ];
+ sText = GetPairedListString( sText );
+ }
+ else{
+ //if ((*pEntry)[ sCur ].Len()){
+ // if( sCur.EqualsIgnoreCaseAscii("de") ){
+ // sText = StripList( (*pEntry)[ sCur ] );
+ // }
+ // else
+ sText = StripList( (*pEntry)[ sCur ] );
+ if( sText == "\\\"" )
+ sText = "\"";
+ //}
+ }
+
+ ByteString sOutput( sProject ); sOutput += "\t";
+ if ( sRoot.Len())
+ sOutput += sActFileName;
+ sOutput += "\t0\t";
+ sOutput += rTyp; sOutput += "\t";
+ sOutput += sGID; sOutput += "\t";
+ sOutput += sLID; sOutput += "\t\t";
+ sOutput += pResData->sPForm; sOutput += "\t0\t";
+ sOutput += sCur; sOutput += "\t";
+
+ sOutput += sText; sOutput += "\t\t\t\t";
+ sOutput += sTimeStamp;
+
+ //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( sProject ) ) )
+ aOutput.WriteLine( sOutput );
+
+ }
+ }
+ }
+ if ( bCreateNew )
+ delete [] pEntry;
+ }
+ if ( bCreateNew )
+ delete pExportList;
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+ByteString Export::FullId()
+/*****************************************************************************/
+{
+ ByteString sFull;
+ if ( nLevel > 1 ) {
+ sFull = aResStack.GetObject( 0 )->sId;
+ for ( USHORT i = 1; i < nLevel - 1; i++ ) {
+ ByteString sToAdd = aResStack.GetObject( i )->sId;
+ if ( sToAdd.Len()) {
+ sFull += ".";
+ sFull += sToAdd;
+ }
+ }
+ }
+ if ( sFull.Len() > 255 ) {
+ ByteString sError( "GroupId > 255 chars" );
+ printf("GroupID = %s\n",sFull.GetBuffer());
+ yyerror( sError.GetBufferAccess());
+ sError.ReleaseBufferAccess();
+ }
+
+ return sFull;
+}
+
+/*****************************************************************************/
+void Export::InsertListEntry( const ByteString &rText, const ByteString &rLine )
+/*****************************************************************************/
+{
+ ResData *pResData = aResStack.GetObject( nLevel-1 );
+
+ ExportList *pList = NULL;
+ if ( nList == LIST_STRING ) {
+ pList = pResData->pStringList;
+ if ( !pList ) {
+ pResData->pStringList = new ExportList();
+ pList = pResData->pStringList;
+ nListIndex = 0;
+ }
+ }
+ else if ( nList == LIST_FILTER ) {
+ pList = pResData->pFilterList;
+ if ( !pList ) {
+ pResData->pFilterList = new ExportList();
+ pList = pResData->pFilterList;
+ nListIndex = 0;
+ }
+ }
+ else if ( nList == LIST_ITEM ) {
+ pList = pResData->pItemList;
+ if ( !pList ) {
+ pResData->pItemList = new ExportList();
+ pList = pResData->pItemList;
+ nListIndex = 0;
+ }
+ }
+ else if ( nList == LIST_PAIRED ) {
+ pList = pResData->pPairedList;
+ if ( !pList ) {
+ pResData->pPairedList = new ExportList();
+ pList = pResData->pPairedList;
+ nListIndex = 0;
+ }
+ }
+ else if ( nList == LIST_UIENTRIES ) {
+ pList = pResData->pUIEntries;
+ if ( !pList ) {
+ pResData->pUIEntries = new ExportList();
+ pList = pResData->pUIEntries;
+ nListIndex = 0;
+ }
+ }
+ else
+ return;
+
+ if ( nListIndex + 1 > pList->Count()) {
+ ExportListEntry *pNew = new ExportListEntry();
+ (*pNew)[ LIST_REFID ] = ByteString::CreateFromInt32( REFID_NONE );
+ pList->Insert( pNew, LIST_APPEND );
+ }
+ ExportListEntry *pCurEntry = pList->GetObject( nListIndex );
+
+ // For paired list use the line to set proper lid
+ if( nList == LIST_PAIRED ){
+ (*pCurEntry)[ nListLang ] = rLine;
+ }else
+ (*pCurEntry)[ nListLang ] = rText;
+
+ // Remember en-US fallback string, so each list has the same amount of elements
+ //if ( nListLang.EqualsIgnoreCaseAscii("en-US") ) {
+ if ( Export::isSourceLanguage( nListLang ) ) {
+ if( nList == LIST_PAIRED ){
+ const ByteString sPlist("pairedlist");
+ ByteString sKey = MergeDataFile::CreateKey( sPlist , pResData->sId , GetPairedListID( rLine ) , sFilename );
+ pResData->addFallbackData( sKey , rText );
+ }
+ // new fallback
+ else{
+ const ByteString sPlist("list");
+ ByteString a( pResData->sGId );
+ a.Append( "." );
+ a.Append( pResData->sId );
+ sal_Int64 x = nListIndex+1;
+ ByteString b( ByteString::CreateFromInt64( x ) );
+ ByteString sKey = MergeDataFile::CreateKey( sPlist , a , b , sFilename );
+ pResData->addFallbackData( sKey , rText );
+ }
+ // new fallback
+ }
+
+ //if ( nListLang.EqualsIgnoreCaseAscii("en-US") ) {
+ if ( Export::isSourceLanguage( nListLang ) ) {
+ if( nList == LIST_PAIRED ){
+ (*pCurEntry)[ SOURCE_LANGUAGE ] = rLine;
+ }
+ else
+ (*pCurEntry)[ SOURCE_LANGUAGE ] = rLine;
+
+ pList->NewSourceLanguageListEntry();
+ }
+
+ //printf("Export::InsertListEntry ResData.id = %s ResData.ListData = %s\n",pResData->sId.GetBuffer() ,(*pCurEntry)[ nListLang ].GetBuffer());
+ nListIndex++;
+}
+
+/*****************************************************************************/
+void Export::CleanValue( ByteString &rValue )
+/*****************************************************************************/
+{
+ while ( rValue.Len()) {
+ if (( rValue.GetChar( 0 ) == ' ' ) || ( rValue.GetChar( 0 ) == '\t' ))
+ rValue = rValue.Copy( 1 );
+ else
+ break;
+ }
+
+ if ( rValue.Len()) {
+ for ( USHORT i = rValue.Len() - 1; i > 0; i-- ) {
+ if (( rValue.GetChar( i ) == ' ' ) || ( rValue.GetChar( i ) == '\t' ) ||
+ ( rValue.GetChar( i ) == '\n' ) || ( rValue.GetChar( i ) == ';' ) ||
+ ( rValue.GetChar( i ) == '{' ) || ( rValue.GetChar( i ) == '\\' ) ||
+ ( rValue.GetChar( i ) == '\r' ))
+ rValue.Erase( i );
+ else
+ break;
+ }
+ }
+}
+
+
+/*****************************************************************************/
+ByteString Export::GetText( const ByteString &rSource, int nToken )
+/*****************************************************************************/
+#define TXT_STATE_NON 0x000
+#define TXT_STATE_TEXT 0x001
+#define TXT_STATE_MACRO 0x002
+{
+ ByteString sReturn;
+ switch ( nToken ) {
+ case TEXTLINE:
+ case LONGTEXTLINE: {
+ ByteString sTmp( rSource.Copy( rSource.Search( "=" )));
+ CleanValue( sTmp );
+ sTmp.EraseAllChars( '\n' );
+ sTmp.EraseAllChars( '\r' );
+
+ while ( sTmp.SearchAndReplace( "\\\\\"", "-=<[BSlashBSlashHKom]>=-\"" )
+ != STRING_NOTFOUND ) {};
+ while ( sTmp.SearchAndReplace( "\\\"", "-=<[Hochkomma]>=-" )
+ != STRING_NOTFOUND ) {};
+ while ( sTmp.SearchAndReplace( "\\", "-=<[0x7F]>=-" )
+ != STRING_NOTFOUND ) {};
+ while ( sTmp.SearchAndReplace( "\\0x7F", "-=<[0x7F]>=-" )
+ != STRING_NOTFOUND ) {};
+
+ USHORT nStart = 0;
+ USHORT nState = TXT_STATE_MACRO;
+
+ nState = TXT_STATE_TEXT;
+ nStart = 1;
+
+
+ for ( USHORT i = nStart; i < sTmp.GetTokenCount( '\"' ); i++ ) {
+ ByteString sToken = sTmp.GetToken( i, '\"' );
+ if ( sToken.Len()) {
+ if ( nState == TXT_STATE_TEXT ) {
+ sReturn += sToken;
+ nState = TXT_STATE_MACRO;
+ }
+ else {
+ while( sToken.SearchAndReplace( "\t", " " ) !=
+ STRING_NOTFOUND ) {};
+ while( sToken.SearchAndReplace( " ", " " ) !=
+ STRING_NOTFOUND ) {};
+ sToken.EraseLeadingChars( ' ' );
+ sToken.EraseTrailingChars( ' ' );
+ if ( sToken.Len()) {
+ sReturn += "\\\" ";
+ sReturn += sToken;
+ sReturn += " \\\"";
+ }
+ nState = TXT_STATE_TEXT;
+ }
+ }
+ }
+
+ while ( sReturn.SearchAndReplace( "-=<[0x7F]>=-", "" )
+ != STRING_NOTFOUND ) {};
+ while ( sReturn.SearchAndReplace( "-=<[Hochkomma]>=-", "\"" )
+ != STRING_NOTFOUND ) {};
+ while ( sReturn.SearchAndReplace( "-=<[BSlashBSlashHKom]>=-", "\\\\" )
+ != STRING_NOTFOUND ) {};
+
+
+ while ( sReturn.SearchAndReplace( "\\\\", "-=<[BSlashBSlash]>=-" )
+ != STRING_NOTFOUND ) {};
+ while ( sReturn.SearchAndReplace( "-=<[BSlashBSlash]>=-", "\\" )
+ != STRING_NOTFOUND ) {};
+
+ }
+ break;
+ }
+ return sReturn;
+}
+
+/*****************************************************************************/
+void Export::WriteToMerged( const ByteString &rText , bool bSDFContent )
+/*****************************************************************************/
+{
+ static ByteString SLASH ('\\');
+ static ByteString RETURN ('\n');
+ //printf("%s\n",rText.GetBuffer() );
+
+ #if 0
+ // statement has no effect
+ if( pParseQueue->bMflag && !bSDFContent ) pParseQueue->bMflag;
+ #endif
+
+ if ( !bDontWriteOutput || !bUnmerge ) {
+ ByteString sText( rText );
+ while ( sText.SearchAndReplace( " \n", "\n" ) != STRING_NOTFOUND ) {};
+ if( pParseQueue->bNextIsM && bSDFContent && sText.Len() > 2 ){
+ for( USHORT n = 0 ; n < sText.Len() ; n++ ){
+ if( sText.GetChar( n ) == '\n' && sText.GetChar( n-1 ) != '\\'){
+ sText.Insert('\\' , n++ );
+
+ }
+ }
+ }
+ else if( pParseQueue->bLastWasM && sText.Len() > 2 ){
+ for( USHORT n = 0 ; n < sText.Len() ; n++ ){
+ if( sText.GetChar( n ) == '\n' && sText.GetChar( n-1 ) != '\\'){
+ sText.Insert('\\' , n++ );
+ }
+ if( sText.GetChar( n ) == '\n' )pParseQueue->bMflag=true;
+ }
+ }
+ else if( pParseQueue->bCurrentIsM && bSDFContent && sText.Len() > 2 ){
+ for( USHORT n = 0 ; n < sText.Len() ; n++ ){
+ if( sText.GetChar( n ) == '\n' && sText.GetChar( n-1 ) != '\\'){
+ sText.Insert('\\' , n++ );
+ pParseQueue->bMflag=true;
+ }
+ }
+ }
+ else if( pParseQueue->bMflag ){
+ for( USHORT n = 1 ; n < sText.Len() ; n++ ){
+ if( sText.GetChar( n ) == '\n' && sText.GetChar( n-1 ) != '\\'){
+ sText.Insert('\\' , n++ );
+ }
+ }
+ }
+ for ( USHORT i = 0; i < sText.Len(); i++ ) {
+ if ( sText.GetChar( i ) != '\n' ){
+ aOutput.Write( ByteString( sText.GetChar( i )).GetBuffer(), 1 );
+
+ }
+ else{
+ aOutput.WriteLine( ByteString());
+ }
+
+ }
+ }
+}
+
+/*****************************************************************************/
+void Export::ConvertMergeContent( ByteString &rText )
+/*****************************************************************************/
+{
+ BOOL bNoOpen = ( rText.Search( "\\\"" ) != 0 );
+ ByteString sClose( rText.Copy( rText.Len() - 2 ));
+ BOOL bNoClose = ( sClose != "\\\"" );
+ ByteString sNew;
+ for ( USHORT i = 0; i < rText.Len(); i++ ) {
+ ByteString sChar( rText.GetChar( i ));
+ if ( sChar == "\\" ) {
+ if (( i + 1 ) < rText.Len()) {
+ ByteString sNext( rText.GetChar( i + 1 ));
+ if ( sNext == "\"" ) {
+ sChar = "\"";
+ i++;
+ }
+ else if ( sNext == "n" ) {
+ sChar = "\\n";
+ i++;
+ }
+ else if ( sNext == "t" ) {
+ sChar = "\\t";
+ i++;
+ }
+ else if ( sNext == "\'" ) {
+ sChar = "\\\'";
+ i++;
+ }
+ else
+ sChar = "\\\\";
+ }
+ else {
+ sChar = "\\\\";
+ }
+ }
+ else if ( sChar == "\"" ) {
+ sChar = "\\\"";
+ }
+ else if ( sChar == "" ) {
+ sChar = "\\0x7F";
+ }
+ sNew += sChar;
+ }
+
+ rText = sNew;
+
+ if ( bNoOpen ) {
+ ByteString sTmp( rText );
+ rText = "\"";
+ rText += sTmp;
+ }
+ if ( bNoClose )
+ rText += "\"";
+}
+
+/*****************************************************************************/
+BOOL Export::PrepareTextToMerge( ByteString &rText, USHORT nTyp,
+ ByteString &nLangIndex, ResData *pResData )
+/*****************************************************************************/
+{
+ // position to merge in:
+ USHORT nStart = 0;
+ USHORT nEnd = 0;
+ ByteString sOldId = pResData->sId;
+ ByteString sOldGId = pResData->sGId;
+ ByteString sOldTyp = pResData->sResTyp;
+
+ ByteString sOrigText( rText );
+
+ switch ( nTyp ) {
+ case LIST_STRING :
+ case LIST_UIENTRIES :
+ case LIST_FILTER :
+ case LIST_PAIRED:
+ case LIST_ITEM :
+ {
+ if ( bUnmerge )
+ return TRUE;
+
+ ExportList *pList = NULL;
+ switch ( nTyp ) {
+ case LIST_STRING : {
+ pResData->sResTyp = "stringlist";
+ pList = pResData->pStringList;
+ }
+ break;
+ case LIST_UIENTRIES : {
+ pResData->sResTyp = "uientries";
+ pList = pResData->pUIEntries;
+ }
+ break;
+ case LIST_FILTER : {
+ pResData->sResTyp = "filterlist";
+ pList = pResData->pFilterList;
+ }
+ break;
+ case LIST_ITEM : {
+ pResData->sResTyp = "itemlist";
+ pList = pResData->pItemList;
+ }
+ break;
+ case LIST_PAIRED : {
+ pResData->sResTyp = "pairedlist";
+ pList = pResData->pPairedList;
+ }
+ break;
+
+ }
+ if ( pList ) {
+ ExportListEntry *pCurEntry = pList->GetObject( nListIndex - 1 );
+ if ( pCurEntry ) {
+ //printf("%s\n",Export::DumpMap( "pCurEntry", *pCurEntry ).GetBuffer() );
+ //ByteString a("pCurEntry");
+ //Export::DumpMap( a , *pCurEntry );
+ rText = (*pCurEntry)[ SOURCE_LANGUAGE ];
+ if( nTyp == LIST_PAIRED ){
+ pResData->addMergedLanguage( nLangIndex );
+ }
+ }
+ }
+
+ nStart = rText.Search( "\"" );
+ if ( nStart == STRING_NOTFOUND ) {
+ rText = sOrigText;
+ return FALSE;
+ }
+
+ BOOL bFound = FALSE;
+ for ( nEnd = nStart + 1; nEnd < rText.Len() && !bFound; nEnd++ ) {
+ if ( rText.GetChar( nEnd ) == '\"' )
+ bFound = TRUE;
+ }
+ if ( !bFound ) {
+ rText = sOrigText;
+ return FALSE;
+ }
+
+ nEnd --;
+ sLastListLine = rText;
+ if (( sLastListLine.Search( ">" ) != STRING_NOTFOUND ) &&
+ ( sLastListLine.Search( "<" ) == STRING_NOTFOUND ))
+ {
+ ByteString sTmp = sLastListLine;
+ sLastListLine = "<";
+ sLastListLine += sTmp;
+ }
+ if ( pResData->sResTyp.EqualsIgnoreCaseAscii( "pairedlist" ) ){
+ pResData->sId = GetPairedListID( sLastListLine );
+ }
+ else pResData->sId = ByteString::CreateFromInt32( nListIndex );
+
+ if ( pResData->sGId.Len())
+ pResData->sGId += ".";
+ pResData->sGId += sOldId;
+ nTyp = STRING_TYP_TEXT;
+ }
+ break;
+ case STRING_TYP_TEXT :
+ case STRING_TYP_HELPTEXT :
+ case STRING_TYP_QUICKHELPTEXT :
+ case STRING_TYP_TITLE :
+ {
+ /*if ( bUnmerge ) {
+ if (( nLangIndex != ByteString("de") ) &&
+ ( nLangIndex != ByteString("en-US") ))
+ {
+ bDontWriteOutput = TRUE;
+ }
+ return TRUE;
+ }*/
+
+ nStart = rText.Search( "=" );
+ if ( nStart == STRING_NOTFOUND ) {
+ rText = sOrigText;
+ return FALSE;
+ }
+
+ nStart++;
+ BOOL bFound = FALSE;
+ while(( nStart < rText.Len()) && !bFound ) {
+ if (( rText.GetChar( nStart ) != ' ' ) && ( rText.GetChar( nStart ) != '\t' ))
+ bFound = TRUE;
+ else
+ nStart ++;
+ }
+
+ // no start position found
+ if ( !bFound ) {
+ rText = sOrigText;
+ return FALSE;
+ }
+
+ // position to end mergeing in
+ nEnd = rText.Len() - 1;
+ bFound = FALSE;
+
+ while (( nEnd > nStart ) && !bFound ) {
+ if (( rText.GetChar( nEnd ) != ' ' ) && ( rText.GetChar( nEnd ) != '\t' ) &&
+ ( rText.GetChar( nEnd ) != '\n' ) && ( rText.GetChar( nEnd ) != ';' ) &&
+ ( rText.GetChar( nEnd ) != '{' ) && ( rText.GetChar( nEnd ) != '\\' ))
+ {
+ bFound = TRUE;
+ }
+ else
+ nEnd --;
+ }
+ }
+ break;
+ }
+
+ // search for merge data
+ if ( !pMergeDataFile ){
+ pMergeDataFile = new MergeDataFile( sMergeSrc, sFile , bErrorLog, aCharSet);//, bUTF8 );
+
+ // Init Languages
+ ByteString sTmp = Export::sLanguages;
+ if( sTmp.ToUpperAscii().Equals("ALL") )
+ SetLanguages( pMergeDataFile->GetLanguages() );
+ else if( !isInitialized )InitLanguages();
+
+ }
+// printf("*************DUMPING****************\n");
+// printf("%s\n",pMergeDataFile->Dump().GetBuffer());
+// printf("*************DUMPING****************\n");
+
+// printf("Dumping ResData\n");
+// pResData->Dump();
+ PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
+ //printf("Dumping pEntrys\n");
+ //if( pEntrys ) pEntrys->Dump();
+ pResData->sId = sOldId;
+ pResData->sGId = sOldGId;
+ pResData->sResTyp = sOldTyp;
+
+ if ( !pEntrys ) {
+ rText = sOrigText;
+ return FALSE; // no data found
+ }
+
+ ByteString sContent;
+ pEntrys->GetText( sContent, nTyp, nLangIndex );
+ //if ( !sContent.Len() && ( ! nLangIndex.EqualsIgnoreCaseAscii("en-US") )) {
+ if ( !sContent.Len() && ( ! Export::isSourceLanguage( nLangIndex ) )) {
+ rText = sOrigText;
+ return FALSE; // no data found
+ }
+
+ //if ( nLangIndex.EqualsIgnoreCaseAscii("en-US") ) {
+ if ( Export::isSourceLanguage( nLangIndex ) ) {
+ return FALSE;
+ }
+
+ ByteString sPostFix( rText.Copy( ++nEnd ));
+ rText.Erase( nStart );
+
+ //ConvertMergeContent( sContent, nTyp );
+ ConvertMergeContent( sContent );
+
+
+
+ //printf("Merged %s\n",nLangIndex.GetBuffer());
+ // merge new res. in text line
+ rText += sContent;
+ rText += sPostFix;
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+void Export::MergeRest( ResData *pResData, USHORT nMode )
+/*****************************************************************************/
+{
+ //if ( bUnmerge ) { return;}
+
+ //pResData->Dump();
+
+ if ( !pMergeDataFile ){
+ pMergeDataFile = new MergeDataFile( sMergeSrc, sFile ,bErrorLog, aCharSet);//, bUTF8 );
+
+ // Init Languages
+ ByteString sTmp = Export::sLanguages;
+ if( sTmp.ToUpperAscii().Equals("ALL") )
+ SetLanguages( pMergeDataFile->GetLanguages() );
+ else if( !isInitialized )InitLanguages();
+
+ }
+ switch ( nMode ) {
+ case MERGE_MODE_NORMAL : {
+ PFormEntrys *pEntry = pMergeDataFile->GetPFormEntrys( pResData );
+
+ bool bWriteNoSlash = false;
+ if ( pEntry && pResData->bText ) {
+
+ BOOL bAddSemikolon = FALSE;
+ BOOL bFirst = TRUE;
+ ByteString sCur;
+ ByteString sTmp = Export::sLanguages;
+
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+
+ ByteString sText;
+ BOOL bText = pEntry->GetText( sText, STRING_TYP_TEXT, sCur , TRUE );
+ if ( bText && sText.Len() && sText != "-" ) {
+ ByteString sOutput;
+ if ( bNextMustBeDefineEOL) {
+ if ( bFirst )
+ sOutput += "\t\\\n";
+ else
+ sOutput += ";\t\\\n";
+ }
+ bFirst=FALSE;
+ sOutput += "\t";
+ sOutput += pResData->sTextTyp;
+ //if ( !sCur.EqualsIgnoreCaseAscii("en-US")) {
+ if ( ! Export::isSourceLanguage( sCur ) ) {
+ sOutput += "[ ";
+ sOutput += sCur;
+ sOutput += " ] ";
+ }
+ sOutput += "= ";
+ ConvertMergeContent( sText );
+ sOutput += sText;
+
+ if ( bDefine && bWriteNoSlash )
+ sOutput += ";\n";
+
+ if ( bDefine )
+ sOutput += ";\\\n";
+ else if ( !bNextMustBeDefineEOL )
+ sOutput += ";\n";
+ else
+ bAddSemikolon = TRUE;
+ for ( USHORT j = 1; j < nLevel; j++ )
+ sOutput += "\t";
+ WriteToMerged( sOutput , true );
+ }
+ }
+
+
+ if ( bAddSemikolon ) {
+ ByteString sOutput( ";" );
+ WriteToMerged( sOutput , false );
+ }
+ }
+
+ if ( pEntry && pResData->bQuickHelpText ) {
+ BOOL bAddSemikolon = FALSE;
+ BOOL bFirst = TRUE;
+ ByteString sCur;
+
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+
+ ByteString sText;
+ BOOL bText = pEntry->GetText( sText, STRING_TYP_QUICKHELPTEXT, sCur, TRUE );
+ if ( bText && sText.Len() && sText != "-" ) {
+ ByteString sOutput;
+ if ( bNextMustBeDefineEOL) {
+ if ( bFirst )
+ sOutput += "\t\\\n";
+ else
+ sOutput += ";\t\\\n";
+ }
+ bFirst=FALSE;
+ sOutput += "\t";
+ sOutput += "QuickHelpText";
+ //if ( !sCur.EqualsIgnoreCaseAscii("en-US") ) {
+ if ( ! Export::isSourceLanguage( sCur ) ) {
+ sOutput += "[ ";
+ sOutput += sCur;
+ sOutput += " ] ";
+ }
+ sOutput += "= ";
+ ConvertMergeContent( sText );
+ sOutput += sText;
+ if ( bDefine )
+ sOutput += ";\\\n";
+ else if ( !bNextMustBeDefineEOL )
+ sOutput += ";\n";
+ else
+ bAddSemikolon = TRUE;
+ for ( USHORT j = 1; j < nLevel; j++ )
+ sOutput += "\t";
+ WriteToMerged( sOutput ,true );
+ }
+ }
+ if ( bAddSemikolon ) {
+ ByteString sOutput( ";" );
+ WriteToMerged( sOutput , false );
+ }
+ }
+
+ if ( pEntry && pResData->bTitle ) {
+ BOOL bAddSemikolon = FALSE;
+ BOOL bFirst = TRUE;
+ ByteString sCur;
+
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+
+ ByteString sText;
+ BOOL bText = pEntry->GetText( sText, STRING_TYP_TITLE, sCur, TRUE );
+ if ( bText && sText.Len() && sText != "-" ) {
+ ByteString sOutput;
+ if ( bNextMustBeDefineEOL) {
+ if ( bFirst )
+ sOutput += "\t\\\n";
+ else
+ sOutput += ";\t\\\n";
+ }
+ bFirst=FALSE;
+ sOutput += "\t";
+ sOutput += "Title";
+ //if ( !sCur.EqualsIgnoreCaseAscii("en-US") ) {
+ if ( ! Export::isSourceLanguage( sCur ) ) {
+ sOutput += "[ ";
+ sOutput += sCur;
+ sOutput += " ] ";
+ }
+ sOutput += "= ";
+ ConvertMergeContent( sText );
+ sOutput += sText;
+ if ( bDefine )
+ sOutput += ";\\\n";
+ else if ( !bNextMustBeDefineEOL )
+ sOutput += ";\n";
+ else
+ bAddSemikolon = TRUE;
+ for ( USHORT j = 1; j < nLevel; j++ )
+ sOutput += "\t";
+ WriteToMerged( sOutput ,true );
+ }
+ }
+ if ( bAddSemikolon ) {
+ ByteString sOutput( ";" );
+ WriteToMerged( sOutput ,false);
+ }
+ }
+ // Merge Lists
+
+ if ( pResData->bList ) {
+ //printf("Dumping ResData\n");
+ //pResData->Dump();
+
+ bool bPairedList = false;
+ ByteString sOldId = pResData->sId;
+ ByteString sOldGId = pResData->sGId;
+ ByteString sOldTyp = pResData->sResTyp;
+ if ( pResData->sGId.Len())
+ pResData->sGId += ".";
+ pResData->sGId += sOldId;
+ ByteString sSpace;
+ for ( USHORT i = 1; i < nLevel-1; i++ )
+ sSpace += "\t";
+ for ( USHORT nT = LIST_STRING; nT <= LIST_UIENTRIES; nT++ ) {
+ ExportList *pList = NULL;
+ switch ( nT ) {
+ case LIST_STRING : pResData->sResTyp = "stringlist"; pList = pResData->pStringList; bPairedList = false; break;
+ case LIST_FILTER : pResData->sResTyp = "filterlist"; pList = pResData->pFilterList; bPairedList = false; break;
+ case LIST_UIENTRIES : pResData->sResTyp = "uientries"; pList = pResData->pUIEntries;bPairedList = false; break;
+ case LIST_ITEM : pResData->sResTyp = "itemlist"; pList = pResData->pItemList; bPairedList = false; break;
+ case LIST_PAIRED : pResData->sResTyp = "pairedlist"; pList = pResData->pPairedList; bPairedList = true; break;
+ }
+ ByteString sCur;
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ USHORT nIdx = 1;
+
+ // Set matching pairedlist identifier
+ if( bPairedList && pResData->pPairedList && ( nIdx == 1 ) ){
+ ExportListEntry* pListE = ( ExportListEntry* ) pResData->pPairedList->GetObject( nIdx-1 );
+ pResData->sId = GetPairedListID ( (*pListE)[ SOURCE_LANGUAGE ] );
+ }
+ else
+ pResData->sId = ByteString("1");
+
+ PFormEntrys *pEntrys;
+ ULONG nLIndex = 0;
+ ULONG nMaxIndex = 0;
+ if ( pList )
+ nMaxIndex = pList->GetSourceLanguageListEntryCount();
+ pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
+ while( pEntrys && ( nLIndex < nMaxIndex )) {
+ //printf("Lang %s, List Index %d\n",sCur.GetBuffer(),(int)nLIndex);
+ ByteString sText;
+ BOOL bText;
+ bText = pEntrys->GetText( sText, STRING_TYP_TEXT, sCur, TRUE );
+ if( !bText )
+ bText = pEntrys->GetText( sText , STRING_TYP_TEXT, SOURCE_LANGUAGE , FALSE );
+
+ // Use fallback, if data is missing in sdf file
+ //if( !bText && pResData->sResTyp.Equals( "pairedlist" ) ){
+ if( !bText && bPairedList ){
+ if( pResData->isMerged( sCur ) ) break;
+ const ByteString sPlist("pairedlist");
+ ByteString sKey = MergeDataFile::CreateKey( sPlist , pResData->sGId , pResData->sId , sFilename );
+ bText = pResData->getFallbackData( sKey , sText );
+ }else if ( !bText ){// new fallback
+ if( pResData->isMerged( sCur ) ) break;
+ const ByteString sPlist("list");
+ ByteString sKey = MergeDataFile::CreateKey( sPlist , pResData->sGId , pResData->sId , sFilename );
+ bText = pResData->getFallbackData( sKey , sText );
+ } // new fallback
+
+ if ( bText && sText.Len()) {
+ //if( pEntrys ) pEntrys->Dump();
+ if ( nIdx == 1 ) {
+ ByteString sHead;
+ if ( bNextMustBeDefineEOL )
+ sHead = "\\\n\t";
+ sHead += sSpace;
+ switch ( nT ) {
+ case LIST_STRING : sHead += "StringList "; break;
+ case LIST_FILTER : sHead += "FilterList "; break;
+ case LIST_ITEM : sHead += "ItemList "; break;
+ case LIST_PAIRED : sHead += "PairedList "; break;
+ case LIST_UIENTRIES : sHead += "UIEntries "; break;
+ }
+ sHead += "[ ";
+ sHead += sCur;
+ sHead += " ] ";
+ //}
+ if ( bDefine || bNextMustBeDefineEOL ) {
+ sHead += "= \\\n";
+ sHead += sSpace;
+ sHead += "\t{\\\n\t";
+ }
+ else {
+ sHead += "= \n";
+ sHead += sSpace;
+ sHead += "\t{\n\t";
+ }
+ WriteToMerged( sHead , true);
+ }
+ ByteString sLine;
+ if ( pList && pList->GetObject( nLIndex ))
+ sLine = ( *pList->GetObject( nLIndex ))[ SOURCE_LANGUAGE ];
+ if ( !sLine.Len())
+ sLine = sLastListLine;
+
+ if ( sLastListLine.Search( "<" ) != STRING_NOTFOUND ) {
+ if (( nT != LIST_UIENTRIES ) &&
+ (( sLine.Search( "{" ) == STRING_NOTFOUND ) ||
+ ( sLine.Search( "{" ) >= sLine.Search( "\"" ))) &&
+ (( sLine.Search( "<" ) == STRING_NOTFOUND ) ||
+ ( sLine.Search( "<" ) >= sLine.Search( "\"" ))))
+ {
+ sLine.SearchAndReplace( "\"", "< \"" );
+ }
+ }
+
+ USHORT nStart, nEnd;
+ nStart = sLine.Search( "\"" );
+
+ ByteString sPostFix;
+ if( !bPairedList ){
+ nEnd = sLine.SearchBackward( '\"' );
+ sPostFix = ByteString( sLine.Copy( ++nEnd ));
+ sLine.Erase( nStart );
+ }
+
+
+ ConvertMergeContent( sText );
+
+ // merge new res. in text line
+ if( bPairedList ){
+ sLine = MergePairedList( sLine , sText );
+ }
+ else{
+ sLine += sText;
+ sLine += sPostFix;
+ }
+
+ ByteString sText1( "\t" );
+ sText1 += sLine;
+ if ( bDefine || bNextMustBeDefineEOL )
+ sText1 += " ;\\\n";
+ else
+ sText1 += " ;\n";
+ sText1 += sSpace;
+ sText1 += "\t";
+ //printf("Writing '%s'\n",sText1.GetBuffer());
+ WriteToMerged( sText1 ,true );
+
+ // Set matching pairedlist identifier
+ if ( bPairedList ){
+ nIdx++;
+ ExportListEntry* pListE = ( ExportListEntry* ) pResData->pPairedList->GetObject( ( nIdx ) -1 );
+ if( pListE ){
+ pResData->sId = GetPairedListID ( (*pListE)[ SOURCE_LANGUAGE ] );
+ }
+ }
+ else
+ pResData->sId = ByteString::CreateFromInt32( ++nIdx );
+ }
+ else
+ break;
+ nLIndex ++;
+ PFormEntrys *oldEntry = pEntrys;
+ pEntrys = pMergeDataFile->GetPFormEntrys( pResData ); // <--- game over
+ if( !pEntrys )
+ pEntrys = oldEntry;
+ }
+ if ( nIdx > 1 ) {
+ ByteString sFooter( sSpace.Copy( 1 ));
+ if ( bNextMustBeDefineEOL )
+ sFooter += "};";
+ else if ( !bDefine )
+ sFooter += "};\n\t";
+ else
+ sFooter += "\n\n";
+ WriteToMerged( sFooter ,true );
+ }
+ }
+ }
+
+ pResData->sId = sOldId;
+ pResData->sGId = sOldGId;
+ pResData->sResTyp = sOldTyp;
+ }
+ }
+ break;
+ case MERGE_MODE_LIST : {
+ ExportList *pList = NULL;
+ switch ( nList ) {
+ // PairedList
+ case LIST_STRING : pList = pResData->pStringList; break;
+ case LIST_FILTER : pList = pResData->pFilterList; break;
+ case LIST_UIENTRIES : pList = pResData->pUIEntries; break;
+ case LIST_ITEM : pList = pResData->pItemList; break;
+ case LIST_PAIRED : pList = pResData->pPairedList; break;
+
+ }
+
+ nListIndex++;
+ ULONG nMaxIndex = 0;
+ if ( pList )
+ nMaxIndex = pList->GetSourceLanguageListEntryCount();
+ ByteString sLine;
+ if ( pList && pList->GetObject( nListIndex ))
+ sLine = ( *pList->GetObject( nListIndex ))[ SOURCE_LANGUAGE ];
+ if ( !sLine.Len())
+ sLine = sLastListLine;
+
+ if ( sLastListLine.Search( "<" ) != STRING_NOTFOUND ) {
+ if (( nList != LIST_UIENTRIES ) &&
+ (( sLine.Search( "{" ) == STRING_NOTFOUND ) ||
+ ( sLine.Search( "{" ) >= sLine.Search( "\"" ))) &&
+ (( sLine.Search( "<" ) == STRING_NOTFOUND ) ||
+ ( sLine.Search( "<" ) >= sLine.Search( "\"" ))))
+ {
+ sLine.SearchAndReplace( "\"", "< \"" );
+ }
+ }
+
+ while( PrepareTextToMerge( sLine, nList, nListLang, pResData ) && ( nListIndex <= nMaxIndex )) {
+ ByteString sText( "\t" );
+ sText += sLine;
+ sText += " ;";
+ sText += "\n";
+ for ( USHORT i = 0; i < nLevel; i++ )
+ sText += "\t";
+ WriteToMerged( sText ,false );
+ nListIndex++;
+ if ( pList && pList->GetObject( nListIndex ))
+ sLine = ( *pList->GetObject( nListIndex ))[ SOURCE_LANGUAGE ];
+ if ( !sLine.Len())
+ sLine = sLastListLine;
+ sLine += " ;";
+ }
+ }
+ break;
+ }
+ pParseQueue->bMflag = false;
+}
+
+ByteString Export::MergePairedList( ByteString& sLine , ByteString& sText ){
+// < "xy" ; IDENTIFIER ; >
+ ByteString sPre = sLine.Copy( 0 , sLine.Search('\"') );
+ ByteString sPost = sLine.Copy( sLine.SearchBackward('\"') + 1 , sLine.Len() );
+ sPre.Append( sText );
+ sPre.Append( sPost );
+ return sPre;
+}
+
+/*****************************************************************************/
+void Export::SetChildWithText()
+/*****************************************************************************/
+{
+ if ( aResStack.Count() > 1 ) {
+ for ( ULONG i = 0; i < aResStack.Count() - 1; i++ ) {
+ aResStack.GetObject( i )->bChildWithText = TRUE;
+ }
+ }
+}
+
+void ParserQueue::Push( const QueueEntry& aEntry ){
+// printf("nTyp = %d ",aEntry.nTyp);
+ USHORT nLen = aEntry.sLine.Len();
+
+ if( !bStart ){
+ aQueueCur->push( aEntry );
+ if( nLen > 1 && aEntry.sLine.GetChar( nLen-1 ) == '\n' )
+ bStart = true;
+ else if ( aEntry.nTyp != IGNOREDTOKENS ){
+ if( nLen > 1 && ( aEntry.sLine.GetChar( nLen-1 ) == '\\') ){
+ // Next is Macro
+ bCurrentIsM = true;
+ }else{
+ // Next is no Macro
+ bCurrentIsM = false;
+ }
+ }
+ }
+ else{
+ aQueueNext->push( aEntry );
+ if( nLen > 1 && aEntry.sLine.GetChar( nLen-1 ) != '\n' ){
+ if( nLen > 1 && ( aEntry.sLine.GetChar( nLen-1 ) == '\\') ){
+ // Next is Macro
+ bNextIsM = true;
+ }
+ else{
+ // Next is no Macro
+ bNextIsM = false;
+ }
+ }else if( nLen > 2 && aEntry.sLine.GetChar( nLen-1 ) == '\n' ){
+ if( aEntry.nTyp != IGNOREDTOKENS ){
+ if( nLen > 2 && ( aEntry.sLine.GetChar( nLen-2 ) == '\\') ){
+ // Next is Macro
+ bNextIsM = true;
+ }
+ else{
+ // Next is no Macro
+ bNextIsM = false;
+ }
+ }
+ // Pop current
+ Pop( *aQueueCur );
+ bLastWasM = bCurrentIsM;
+ // next -> current
+ bCurrentIsM = bNextIsM;
+ aQref = aQueueCur;
+ aQueueCur = aQueueNext;
+ aQueueNext = aQref;
+
+ }
+
+ else{
+ // Pop current
+ Pop( *aQueueCur );
+ bLastWasM = bCurrentIsM;
+ // next -> current
+ bCurrentIsM = bNextIsM;
+ aQref = aQueueCur;
+ aQueueCur = aQueueNext;
+ aQueueNext = aQref;
+ }
+ }
+}
+
+void ParserQueue::Close(){
+ // Pop current
+ Pop( *aQueueCur );
+ // next -> current
+ bLastWasM = bCurrentIsM;
+ bCurrentIsM = bNextIsM;
+ aQref = aQueueCur;
+ aQueueCur = aQueueNext;
+ aQueueNext = aQref;
+ bNextIsM = false;
+ Pop( *aQueueNext );
+};
+void ParserQueue::Pop( std::queue<QueueEntry>& aQueue ){
+ while( !aQueue.empty() ){
+ QueueEntry aEntry = aQueue.front();
+ aQueue.pop();
+ aExport.Execute( aEntry.nTyp , (char*) aEntry.sLine.GetBuffer() );
+ }
+}
+ParserQueue::ParserQueue( Export& aExportObj )
+ :
+ bCurrentIsM( false ),
+ bNextIsM( false ) ,
+ bLastWasM( false ),
+ bMflag( false ) ,
+ aExport( aExportObj ) ,
+ bStart( false ) ,
+ bStartNext( false )
+{
+ aQueueNext = new std::queue<QueueEntry>;
+ aQueueCur = new std::queue<QueueEntry>;
+}
+
+
+ParserQueue::~ParserQueue(){
+ if( aQueueNext ) delete aQueueNext;
+ if( aQueueCur ) delete aQueueCur;
+}
diff --git a/l10ntools/source/export2.cxx b/l10ntools/source/export2.cxx
new file mode 100644
index 000000000000..6132b01db644
--- /dev/null
+++ b/l10ntools/source/export2.cxx
@@ -0,0 +1,742 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: export2.cxx,v $
+ * $Revision: 1.43 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include "export.hxx"
+#include "utf8conv.hxx"
+#include <tools/datetime.hxx>
+#include <tools/isofallback.hxx>
+#include <stdio.h>
+#include <osl/time.h>
+#include <osl/process.h>
+#include <rtl/ustring.hxx>
+#include <iostream>
+#include <iomanip>
+#include <tools/urlobj.hxx>
+#include <time.h>
+#include <stdlib.h>
+
+using namespace std;
+//
+// class ResData();
+//
+
+/*****************************************************************************/
+ResData::~ResData()
+/*****************************************************************************/
+{
+ if ( pStringList ) {
+ // delete existing res. of type StringList
+ for ( ULONG i = 0; i < pStringList->Count(); i++ ) {
+ ExportListEntry* test = pStringList->GetObject( i );
+ if( test != NULL ) delete test;
+ }
+ delete pStringList;
+ }
+ if ( pFilterList ) {
+ // delete existing res. of type FilterList
+ for ( ULONG i = 0; i < pFilterList->Count(); i++ ) {
+ ExportListEntry* test = pFilterList->GetObject( i );
+ delete test;
+ }
+ delete pFilterList;
+ }
+ if ( pItemList ) {
+ // delete existing res. of type ItemList
+ for ( ULONG i = 0; i < pItemList->Count(); i++ ) {
+ ExportListEntry* test = pItemList->GetObject( i );
+ delete test;
+ }
+ delete pItemList;
+ }
+ if ( pUIEntries ) {
+ // delete existing res. of type UIEntries
+ for ( ULONG i = 0; i < pUIEntries->Count(); i++ ) {
+ ExportListEntry* test = pUIEntries->GetObject( i );
+ delete test;
+ }
+ delete pUIEntries;
+ }
+}
+
+//
+// class Export
+//
+
+/*****************************************************************************/
+ByteString Export::sLanguages;
+ByteString Export::sForcedLanguages;
+//ByteString Export::sIsoCode99;
+/*****************************************************************************/
+
+void Export::DumpExportList( ByteString& sListName , ExportList& aList ){
+ printf( "%s\n", sListName.GetBuffer() );
+ ByteString l("");
+ ExportListEntry* aEntry;
+ for( unsigned int x = 0; x < aList.Count() ; x++ ){
+ aEntry = (ExportListEntry*) aList.GetObject( x );
+ Export::DumpMap( l , *aEntry );
+ }
+ printf("\n");
+}
+ByteString Export::DumpMap( ByteString& sMapName , ByteStringHashMap& aMap ){
+ ByteStringHashMap::const_iterator idbg;
+ ByteString sReturn;
+
+ if( sMapName.Len() )
+ printf("MapName %s\n", sMapName.GetBuffer());
+ if( aMap.size() < 1 ) return ByteString();
+ for( idbg = aMap.begin() ; idbg != aMap.end(); ++idbg ){
+ ByteString a( idbg->first );
+ ByteString b( idbg->second );
+ printf("[%s]= %s",a.GetBuffer(),b.GetBuffer());
+ printf("\n");
+ }
+ printf("\n");
+ return sReturn;
+}
+/*****************************************************************************/
+void Export::SetLanguages( std::vector<ByteString> val ){
+/*****************************************************************************/
+ aLanguages = val;
+ isInitialized = true;
+}
+/*****************************************************************************/
+std::vector<ByteString> Export::GetLanguages(){
+/*****************************************************************************/
+ return aLanguages;
+}
+/*****************************************************************************/
+std::vector<ByteString> Export::GetForcedLanguages(){
+/*****************************************************************************/
+ return aForcedLanguages;
+}
+std::vector<ByteString> Export::aLanguages = std::vector<ByteString>();
+std::vector<ByteString> Export::aForcedLanguages = std::vector<ByteString>();
+
+
+/*****************************************************************************/
+void Export::QuotHTMLXRM( ByteString &rString )
+/*****************************************************************************/
+{
+ ByteString sReturn;
+ //BOOL bBreak = FALSE;
+ for ( USHORT i = 0; i < rString.Len(); i++ ) {
+ ByteString sTemp = rString.Copy( i );
+ if ( sTemp.Search( "<Arg n=" ) == 0 ) {
+ while ( i < rString.Len() && rString.GetChar( i ) != '>' ) {
+ sReturn += rString.GetChar( i );
+ i++;
+ }
+ if ( rString.GetChar( i ) == '>' ) {
+ sReturn += ">";
+ i++;
+ }
+ }
+
+ if ( i < rString.Len()) {
+ switch ( rString.GetChar( i )) {
+ case '<':
+ if( i+2 < rString.Len() &&
+ (rString.GetChar( i+1 ) == 'b' || rString.GetChar( i+1 ) == 'B') &&
+ rString.GetChar( i+2 ) == '>' )
+ {
+ sReturn +="<b>";
+ i += 2;
+ }
+ else if( i+3 < rString.Len() &&
+ rString.GetChar( i+1 ) == '/' &&
+ (rString.GetChar( i+2 ) == 'b' || rString.GetChar( i+2 ) == 'B') &&
+ rString.GetChar( i+3 ) == '>' )
+ {
+ sReturn +="</b>";
+ i += 3;
+ }
+ else
+ sReturn += "&lt;";
+ break;
+
+ case '>':
+ sReturn += "&gt;";
+ break;
+
+ case '\"':
+ sReturn += "&quot;";
+ break;
+
+ case '\'':
+ sReturn += "&apos;";
+ break;
+
+ case '&':
+ if ((( i + 4 ) < rString.Len()) &&
+ ( rString.Copy( i, 5 ) == "&amp;" ))
+ sReturn += rString.GetChar( i );
+ else
+ sReturn += "&amp;";
+ break;
+
+ default:
+ sReturn += rString.GetChar( i );
+ break;
+ }
+ }
+ }
+ rString = sReturn;
+}
+/*****************************************************************************/
+void Export::QuotHTML( ByteString &rString )
+/*****************************************************************************/
+{
+ ByteString sReturn;
+ for ( USHORT i = 0; i < rString.Len(); i++ ) {
+ ByteString sTemp = rString.Copy( i );
+ if ( sTemp.Search( "<Arg n=" ) == 0 ) {
+ while ( i < rString.Len() && rString.GetChar( i ) != '>' ) {
+ sReturn += rString.GetChar( i );
+ i++;
+ }
+ if ( rString.GetChar( i ) == '>' ) {
+ sReturn += ">";
+ i++;
+ }
+ }
+ if ( i < rString.Len()) {
+ switch ( rString.GetChar( i )) {
+ case '<':
+ sReturn += "&lt;";
+ break;
+
+ case '>':
+ sReturn += "&gt;";
+ break;
+
+ case '\"':
+ sReturn += "&quot;";
+ break;
+
+ case '\'':
+ sReturn += "&apos;";
+ break;
+
+ case '&':
+ if ((( i + 4 ) < rString.Len()) &&
+ ( rString.Copy( i, 5 ) == "&amp;" ))
+ sReturn += rString.GetChar( i );
+ else
+ sReturn += "&amp;";
+ break;
+
+ default:
+ sReturn += rString.GetChar( i );
+ break;
+ }
+ }
+ }
+ rString = sReturn;
+}
+
+void Export::RemoveUTF8ByteOrderMarker( ByteString &rString ){
+ if( hasUTF8ByteOrderMarker( rString ) )
+ rString.Erase( 0 , 3 );
+}
+
+bool Export::hasUTF8ByteOrderMarker( const ByteString &rString ){
+ // Byte order marker signature
+
+ const unsigned char c1 = 0xEF;
+ const unsigned char c2 = 0xBB;
+ const unsigned char c3 = 0xBF;
+
+ const char bom[ 3 ] = { c1 , c2 , c3 };
+
+ return rString.Len() >= 3 &&
+ rString.GetChar( 0 ) == bom[ 0 ] &&
+ rString.GetChar( 1 ) == bom[ 1 ] &&
+ rString.GetChar( 2 ) == bom[ 2 ] ;
+}
+bool Export::fileHasUTF8ByteOrderMarker( const ByteString &rString ){
+ SvFileStream aFileIn( String( rString , RTL_TEXTENCODING_ASCII_US ) , STREAM_READ );
+ ByteString sLine;
+ if( !aFileIn.IsEof() ) {
+ aFileIn.ReadLine( sLine );
+ if( aFileIn.IsOpen() ) aFileIn.Close();
+ return hasUTF8ByteOrderMarker( sLine );
+ }
+ if( aFileIn.IsOpen() ) aFileIn.Close();
+ return false;
+}
+void Export::RemoveUTF8ByteOrderMarkerFromFile( const ByteString &rFilename ){
+ SvFileStream aFileIn( String( rFilename , RTL_TEXTENCODING_ASCII_US ) , STREAM_READ );
+ ByteString sLine;
+ if( !aFileIn.IsEof() ) {
+ aFileIn.ReadLine( sLine );
+ // Test header
+ if( hasUTF8ByteOrderMarker( sLine ) ){
+ //cout << "UTF8 Header found!\n";
+ DirEntry aTempFile = Export::GetTempFile();
+ ByteString sTempFile = ByteString( aTempFile.GetFull() , RTL_TEXTENCODING_ASCII_US );
+ SvFileStream aNewFile( String( sTempFile , RTL_TEXTENCODING_ASCII_US ) , STREAM_WRITE );
+ // Remove header
+ RemoveUTF8ByteOrderMarker( sLine );
+ //cout << "Copy stripped stuff to " << sTempFile.GetBuffer() << endl;
+ aNewFile.WriteLine( sLine );
+ // Copy the rest
+ while( !aFileIn.IsEof() ){
+ aFileIn.ReadLine( sLine );
+ aNewFile.WriteLine( sLine );
+ }
+ if( aFileIn.IsOpen() ) aFileIn.Close();
+ if( aNewFile.IsOpen() ) aNewFile.Close();
+ DirEntry aEntry( rFilename.GetBuffer() );
+ //cout << "Removing file " << rFilename.GetBuffer() << "\n";
+ aEntry.Kill();
+ //cout << "Renaming file " << sTempFile.GetBuffer() << " to " << rFilename.GetBuffer() << "\n";
+ DirEntry( sTempFile ).MoveTo( DirEntry( rFilename.GetBuffer() ) );
+ }
+ }
+ if( aFileIn.IsOpen() ) aFileIn.Close();
+}
+
+// Merge it into source code!
+//bool Export::isMergingGermanAllowed( const ByteString& rPrj ){
+// (void) rPrj;
+// return true;
+/* static ByteStringBoolHashMap aHash;
+
+ if( aHash.find( rPrj ) != aHash.end() ){
+ return aHash[ rPrj ];
+ }
+
+ ByteString sFile = Export::GetEnv( "SRC_ROOT" ) ;
+ sFile.Append("/");
+ sFile.Append( rPrj );
+ sFile.Append("/prj/l10n");
+#if defined(WNT) || defined(OS2)
+ sFile.SearchAndReplaceAll('/','\\');
+#endif
+ DirEntry aFlagfile( sFile );
+
+ aHash[ rPrj ] = !aFlagfile.Exists();
+ return aHash[ rPrj ];*/
+//}
+bool Export::CopyFile( const ByteString& source , const ByteString& dest )
+{
+// cout << "CopyFile( " << source.GetBuffer() << " , " << dest.GetBuffer() << " )\n";
+ const int BUFFERSIZE = 8192;
+ char buf[ BUFFERSIZE ];
+
+ FILE* IN_FILE = fopen( source.GetBuffer() , "r" );
+ if( IN_FILE == NULL )
+ {
+ cerr << "Export::CopyFile WARNING: Could not open " << source.GetBuffer() << "\n";
+ return false;
+ }
+
+ FILE* OUT_FILE = fopen( dest.GetBuffer() , "w" );
+ if( OUT_FILE == NULL )
+ {
+ cerr << "Export::CopyFile WARNING: Could not open/create " << dest.GetBuffer() << " for writing\n";
+ fclose( IN_FILE );
+ return false;
+ }
+
+ while( fgets( buf , BUFFERSIZE , IN_FILE ) != NULL )
+ {
+ if( fputs( buf , OUT_FILE ) == EOF )
+ {
+ cerr << "Export::CopyFile WARNING: Write problems " << source.GetBuffer() << "\n";
+ fclose( IN_FILE );
+ fclose( OUT_FILE );
+ return false;
+ }
+ }
+ if( ferror( IN_FILE ) )
+ {
+ cerr << "Export::CopyFile WARNING: Read problems " << dest.GetBuffer() << "\n";
+ fclose( IN_FILE );
+ fclose( OUT_FILE );
+ return false;
+ }
+ fclose ( IN_FILE );
+ fclose ( OUT_FILE );
+
+ return true;
+}
+
+/*****************************************************************************/
+void Export::UnquotHTML( ByteString &rString )
+/*****************************************************************************/
+{
+ ByteString sReturn;
+ while ( rString.Len()) {
+ if ( rString.Copy( 0, 5 ) == "&amp;" ) {
+ sReturn += "&";
+ rString.Erase( 0, 5 );
+ }
+ else if ( rString.Copy( 0, 4 ) == "&lt;" ) {
+ sReturn += "<";
+ rString.Erase( 0, 4 );
+ }
+ else if ( rString.Copy( 0, 4 ) == "&gt;" ) {
+ sReturn += ">";
+ rString.Erase( 0, 4 );
+ }
+ else if ( rString.Copy( 0, 6 ) == "&quot;" ) {
+ sReturn += "\"";
+ rString.Erase( 0, 6 );
+ }
+ else if ( rString.Copy( 0, 6 ) == "&apos;" ) {
+ sReturn += "\'";
+ rString.Erase( 0, 6 );
+ }
+ else {
+ sReturn += rString.GetChar( 0 );
+ rString.Erase( 0, 1 );
+ }
+ }
+ rString = sReturn;
+}
+bool Export::isSourceLanguage( const ByteString &sLanguage )
+{
+ return !isAllowed( sLanguage );
+}
+bool Export::isAllowed( const ByteString &sLanguage ){
+ return ! ( sLanguage.EqualsIgnoreCaseAscii("en-US") );
+}
+/*****************************************************************************/
+bool Export::LanguageAllowed( const ByteString &nLanguage )
+/*****************************************************************************/
+{
+ return std::find( aLanguages.begin() , aLanguages.end() , nLanguage ) != aLanguages.end();
+}
+
+bool Export::isInitialized = false;
+
+/*****************************************************************************/
+void Export::InitLanguages( bool bMergeMode ){
+/*****************************************************************************/
+ if( !isInitialized ){
+ ByteString sTmp;
+ ByteStringBoolHashMap aEnvLangs;
+ for ( USHORT x = 0; x < sLanguages.GetTokenCount( ',' ); x++ ){
+ sTmp = sLanguages.GetToken( x, ',' ).GetToken( 0, '=' );
+ sTmp.EraseLeadingAndTrailingChars();
+ if( bMergeMode && !isAllowed( sTmp ) ){}
+ else if( !( (sTmp.GetChar(0)=='x' || sTmp.GetChar(0)=='X') && sTmp.GetChar(1)=='-' ) ){
+ aLanguages.push_back( sTmp );
+ }
+ }
+ InitForcedLanguages( bMergeMode );
+ isInitialized = true;
+ }
+}
+/*****************************************************************************/
+void Export::InitForcedLanguages( bool bMergeMode ){
+/*****************************************************************************/
+ ByteString sTmp;
+ ByteStringBoolHashMap aEnvLangs;
+ for ( USHORT x = 0; x < sForcedLanguages.GetTokenCount( ',' ); x++ ){
+ sTmp = sForcedLanguages.GetToken( x, ',' ).GetToken( 0, '=' );
+ sTmp.EraseLeadingAndTrailingChars();
+ if( bMergeMode && isAllowed( sTmp ) ){}
+ else if( !( (sTmp.GetChar(0)=='x' || sTmp.GetChar(0)=='X') && sTmp.GetChar(1)=='-' ) )
+ aForcedLanguages.push_back( sTmp );
+ }
+}
+
+/*****************************************************************************/
+ByteString Export::GetFallbackLanguage( const ByteString nLanguage )
+/*****************************************************************************/
+{
+ ByteString sFallback=nLanguage;
+ GetIsoFallback( sFallback );
+ return sFallback;
+}
+
+void Export::replaceEncoding( ByteString& rString )
+{
+// &#x2122; -> \u2122
+
+ for( xub_StrLen idx = 0; idx <= rString.Len()-8 ; idx++ )
+ {
+ if( rString.GetChar( idx ) == '&' &&
+ rString.GetChar( idx+1 ) == '#' &&
+ rString.GetChar( idx+2 ) == 'x' &&
+ rString.GetChar( idx+7 ) == ';' )
+ {
+ ByteString sTmp = rString.Copy( 0 , idx );
+ sTmp.Append( "\\u" );
+ sTmp.Append( rString.GetChar( idx+3 ) );
+ sTmp.Append( rString.GetChar( idx+4 ) );
+ sTmp.Append( rString.GetChar( idx+5 ) );
+ sTmp.Append( rString.GetChar( idx+6 ) );
+ sTmp.Append( rString.Copy( idx+8 , rString.Len() ) );
+ rString = sTmp;
+ }
+ }
+}
+
+/*****************************************************************************/
+void Export::FillInFallbacks( ResData *pResData )
+/*****************************************************************************/
+{
+ ByteString sCur;
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ if( isAllowed( sCur ) ){
+ ByteString nFallbackIndex = GetFallbackLanguage( sCur );
+ if( nFallbackIndex.Len() ){
+ if ( !pResData->sText[ sCur ].Len())
+ pResData->sText[ sCur ] =
+ pResData->sText[ nFallbackIndex ];
+
+ if ( !pResData->sHelpText[ sCur ].Len())
+ pResData->sHelpText[ sCur ] =
+ pResData->sHelpText[ nFallbackIndex ];
+
+ if ( !pResData->sQuickHelpText[ sCur ].Len())
+ pResData->sQuickHelpText[ sCur ] =
+ pResData->sQuickHelpText[ nFallbackIndex ];
+
+ if ( !pResData->sTitle[ sCur ].Len())
+ pResData->sTitle[ sCur ] =
+ pResData->sTitle[ nFallbackIndex ];
+
+ if ( pResData->pStringList )
+ FillInListFallbacks(
+ pResData->pStringList, sCur, nFallbackIndex );
+
+ if ( pResData->pPairedList )
+ FillInListFallbacks(
+ pResData->pPairedList, sCur, nFallbackIndex );
+
+ if ( pResData->pFilterList )
+ FillInListFallbacks(
+ pResData->pFilterList, sCur, nFallbackIndex );
+
+ if ( pResData->pItemList )
+ FillInListFallbacks(
+ pResData->pItemList, sCur, nFallbackIndex );
+
+ if ( pResData->pUIEntries )
+ FillInListFallbacks(
+ pResData->pUIEntries, sCur, nFallbackIndex );
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+void Export::FillInListFallbacks(
+ ExportList *pList, const ByteString &nSource, const ByteString &nFallback )
+/*****************************************************************************/
+{
+
+ for ( ULONG i = 0; i < pList->Count(); i++ ) {
+ ExportListEntry *pEntry = pList->GetObject( i );
+ if ( !( *pEntry )[ nSource ].Len()){
+ ( *pEntry )[ nSource ] = ( *pEntry )[ nFallback ];
+ ByteString x = ( *pEntry )[ nSource ];
+ ByteString y = ( *pEntry )[ nFallback ];
+ }
+ }
+}
+
+/*****************************************************************************/
+ByteString Export::GetTimeStamp()
+/*****************************************************************************/
+{
+// return "xx.xx.xx";
+ char buf[20];
+ Time aTime;
+
+ snprintf(buf, sizeof(buf), "%8d %02d:%02d:%02d", int(Date().GetDate()),
+ int(aTime.GetHour()), int(aTime.GetMin()), int(aTime.GetSec()));
+ return ByteString(buf);
+}
+
+/*****************************************************************************/
+BOOL Export::ConvertLineEnds(
+ ByteString sSource, ByteString sDestination )
+/*****************************************************************************/
+{
+ String sSourceFile( sSource, RTL_TEXTENCODING_ASCII_US );
+ String sDestinationFile( sDestination, RTL_TEXTENCODING_ASCII_US );
+
+ SvFileStream aSource( sSourceFile, STREAM_READ );
+ if ( !aSource.IsOpen())
+ return FALSE;
+ SvFileStream aDestination( sDestinationFile, STREAM_STD_WRITE | STREAM_TRUNC );
+ if ( !aDestination.IsOpen()) {
+ aSource.Close();
+ return FALSE;
+ }
+
+ ByteString sLine;
+
+ while ( !aSource.IsEof()) {
+ aSource.ReadLine( sLine );
+ if ( !aSource.IsEof()) {
+ sLine.EraseAllChars( '\r' );
+ aDestination.WriteLine( sLine );
+ }
+ else
+ aDestination.WriteByteString( sLine );
+ }
+
+ aSource.Close();
+ aDestination.Close();
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+ByteString Export::GetNativeFile( ByteString sSource )
+/*****************************************************************************/
+{
+ DirEntry aTemp( GetTempFile());
+ ByteString sReturn( aTemp.GetFull(), RTL_TEXTENCODING_ASCII_US );
+
+ for ( USHORT i = 0; i < 10; i++ )
+ if ( ConvertLineEnds( sSource, sReturn ))
+ return sReturn;
+
+ return "";
+}
+
+const char* Export::GetEnv( const char *pVar )
+{
+ char *pRet = getenv( pVar );
+ if ( !pRet )
+ pRet = 0;
+ return pRet;
+}
+
+
+int Export::getCurrentDirectory( rtl::OUString& base_fqurl_out, rtl::OUString& base_out )
+{
+ DirEntry aDir(".");
+ aDir.ToAbs();
+ base_out = rtl::OUString( aDir.GetFull() );
+ return osl::File::getFileURLFromSystemPath( base_out , base_fqurl_out );
+}
+
+void Export::getCurrentDir( string& dir )
+{
+ char buffer[64000];
+ if( getcwd( buffer , sizeof( buffer ) ) == 0 ){
+ cerr << "Error: getcwd failed!\n";
+ exit( -1 );
+ }
+ dir = string( buffer );
+}
+
+
+// Stolen from sal/osl/unx/tempfile.c
+
+#define RAND_NAME_LENGTH 6
+
+void Export::getRandomName( const ByteString& sPrefix , ByteString& sRandStr , const ByteString& sPostfix )
+{
+ static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+ static const int COUNT_OF_LETTERS = sizeof(LETTERS)/sizeof(LETTERS[0]) - 1;
+ sRandStr.Append( sPrefix );
+
+ static sal_uInt64 value;
+ char buffer[RAND_NAME_LENGTH];
+
+ TimeValue tv;
+ sal_uInt64 v;
+ int i;
+
+ osl_getSystemTime( &tv );
+ oslProcessInfo proInfo;
+ osl_getProcessInfo( 0 , osl_Process_IDENTIFIER , &proInfo );
+
+ value += ((sal_uInt64) ( tv.Nanosec / 1000 ) << 16) ^ ( tv.Nanosec / 1000 ) ^ proInfo.Ident;
+
+ v = value;
+
+ for (i = 0; i < RAND_NAME_LENGTH; i++)
+ {
+ buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
+ v /= COUNT_OF_LETTERS;
+ }
+
+ sRandStr.Append( buffer , RAND_NAME_LENGTH );
+ sRandStr.Append( sPostfix );
+}
+
+void Export::getRandomName( ByteString& sRandStr )
+{
+ const ByteString sEmpty;
+ getRandomName( sEmpty , sRandStr , sEmpty );
+}
+
+/*****************************************************************************/
+DirEntry Export::GetTempFile()
+/*****************************************************************************/
+{
+#if defined(WNT) || defined(OS2)
+ String sTempDir( Export::GetEnv( "TEMP" ), RTL_TEXTENCODING_ASCII_US );
+#else
+ String sTempDir( String::CreateFromAscii( "/tmp" ));
+#endif
+ rtl::OUString* sTempFilename = new rtl::OUString();
+
+ // Create a temp file
+ int nRC = osl::FileBase::createTempFile( 0 , 0 , sTempFilename );
+ if( nRC ) printf(" osl::FileBase::createTempFile RC = %d",nRC);
+
+ String strTmp( *sTempFilename );
+
+ INetURLObject::DecodeMechanism eMechanism = INetURLObject::DECODE_TO_IURI;
+ String sDecodedStr = INetURLObject::decode( strTmp , '%' , eMechanism );
+ ByteString sTmp( sDecodedStr , RTL_TEXTENCODING_UTF8 );
+
+#if defined(WNT) || defined(OS2)
+ sTmp.SearchAndReplace("file:///","");
+ sTmp.SearchAndReplaceAll('/','\\');
+#else
+ // Set file permission to 644
+ const sal_uInt64 nPerm = osl_File_Attribute_OwnRead | osl_File_Attribute_OwnWrite |
+ osl_File_Attribute_GrpRead | osl_File_Attribute_OthRead ;
+
+ nRC = osl::File::setAttributes( *sTempFilename , nPerm );
+ if( nRC ) printf(" osl::File::setAttributes RC = %d",nRC);
+
+ sTmp.SearchAndReplace("file://","");
+#endif
+ DirEntry aDirEntry( sTmp );
+ delete sTempFilename;
+ return aDirEntry;
+}
diff --git a/l10ntools/source/file.cxx b/l10ntools/source/file.cxx
new file mode 100644
index 000000000000..43ce4c757d54
--- /dev/null
+++ b/l10ntools/source/file.cxx
@@ -0,0 +1,58 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: file.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <l10ntools/file.hxx>
+
+namespace transex
+{
+
+File::File( const rtl::OUString sFile )
+{
+ sFileName = sFile;
+}
+
+File::File( const rtl::OUString sFullPath , const rtl::OUString sFile )
+{
+ sFileName = sFile;
+ sFullName = sFullPath;
+}
+
+bool File::lessFile ( const File& rKey1, const File& rKey2 )
+{
+ rtl::OUString sName1( ( static_cast< File >( rKey1 ) ).getFileName() );
+ rtl::OUString sName2( ( static_cast< File >( rKey2 ) ).getFileName() );
+
+ return sName1.compareTo( sName2 ) < 0 ;
+}
+
+}
diff --git a/l10ntools/source/filter/merge/FCFGMerge.cfg b/l10ntools/source/filter/merge/FCFGMerge.cfg
new file mode 100644
index 000000000000..46fcccafe7e4
--- /dev/null
+++ b/l10ntools/source/filter/merge/FCFGMerge.cfg
@@ -0,0 +1,125 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: FCFGMerge.cfg,v $
+#
+# $Revision: 1.5 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+#************************************************
+# Specify the verbose mode of this tool.
+# 1 = show errors only
+# 2 = show errors/warnings (default)
+# 3 = show errors/warnings and some generic infos
+# 4 = show anything (including detailed infos)
+#
+# [OPTIONAL]
+#************************************************
+
+loglevel = 2
+
+#************************************************
+# This extension is used for all XML files. It doesnt
+# matter if its used for reading fragments or writing
+# XML packages.
+# Must be given without any additional signes like "."
+# or "*."!
+#
+# [REQUIRED]
+#************************************************
+
+extension_xcu=xcu
+
+#************************************************
+# This extension is used for all Package files. It doesnt
+# matter if its used for reading such files or writing
+# it.
+# Must be given without any additional signes like "."
+# or "*."!
+#
+# [REQUIRED]
+#************************************************
+
+extension_pkg=pkg
+
+#************************************************
+# These values are used to generate a correct XML
+# header.
+# Note: The property "xmlpackage" must be specified
+# via command line. There exists more then one
+# possible value.
+#
+# [REQUIRED]
+#************************************************
+
+xmlversion = 1.0
+xmlencoding = UTF-8
+xmlpath = org.openoffice.TypeDetection
+#xmlpackage =
+
+#************************************************
+# These values are used to name the configuration
+# sets inside the generated XCM file for different
+# item groups like e.g. types, filters etcpp.
+#
+# [REQUIRED]
+#************************************************
+
+setname_types = Types
+setname_filters = Filters
+setname_frameloaders = FrameLoaders
+setname_contenthandlers = ContentHandlers
+
+subdir_types = types
+subdir_filters = filters
+subdir_frameloaders = frameloaders
+subdir_contenthandlers = contenthandlers
+
+#************************************************
+# This delimiter is used to split every
+# item list of the package configuration files
+# (which are temp. created by the make proccess)
+# into its tokens.
+#
+# [REQUIRED]
+#************************************************
+delimiter=,
+
+#************************************************
+# Enable/disable removing of leading/trailing withespaces
+# during splitting stringlists.
+#
+# [REQUIRED]
+#************************************************
+trim=true
+
+#************************************************
+# Enable/disable removing of leading/trailing "-signs
+# during splitting stringlists.
+#
+# [REQUIRED]
+#************************************************
+decode=false
diff --git a/l10ntools/source/filter/merge/FCFGMerge.java b/l10ntools/source/filter/merge/FCFGMerge.java
new file mode 100644
index 000000000000..7fbfa8a0c986
--- /dev/null
+++ b/l10ntools/source/filter/merge/FCFGMerge.java
@@ -0,0 +1,131 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FCFGMerge.java,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package com.sun.star.filter.config.tools.merge;
+
+//_______________________________________________
+
+import java.lang.*;
+import java.util.*;
+import java.io.*;
+import com.sun.star.filter.config.tools.utils.*;
+
+//_______________________________________________
+
+/**
+ * Its a simple command line tool, which can merge different XML fragments
+ * together. Such fragments must exist as files on disk, will be moved into
+ * one file together on disk.
+ *
+ *
+ */
+public class FCFGMerge
+{
+ //___________________________________________
+ // const
+
+ private static final java.lang.String CFGFILE = "com/sun/star/filter/config/tools/merge/FCFGMerge.cfg";
+ private static final java.lang.String PROP_LOGLEVEL = "loglevel";
+
+ //___________________________________________
+ // main
+
+ public static void main(java.lang.String[] sCmdLine)
+ {
+ FCFGMerge.printCopyright();
+
+ // create log object in default mode "WARNINGS"
+ // If a command line parameter indicates another
+ // level - change it!
+ Logger aLog = new Logger();
+
+ try
+ {
+ // merge config file and overwrite properties
+ // via command line
+ ConfigHelper aCfg = null;
+ aCfg = new ConfigHelper(CFGFILE, sCmdLine);
+
+ // update log level
+ int nLogLevel = aCfg.getInt(PROP_LOGLEVEL, Logger.LEVEL_WARNINGS);
+ aLog = new Logger(nLogLevel);
+
+ // help requested?
+ if (aCfg.isHelp())
+ {
+ FCFGMerge.printHelp();
+ System.exit(-1);
+ }
+
+ // create new merge object and start operation
+ Merger aMerger = new Merger(aCfg, aLog);
+ aMerger.merge();
+ }
+ catch(java.lang.Throwable ex)
+ {
+ aLog.setException(ex);
+ System.exit(-1);
+ }
+
+ System.exit(0);
+ }
+
+ //___________________________________________
+
+ /** prints out a copyright message on stdout.
+ */
+ private static void printCopyright()
+ {
+ java.lang.StringBuffer sOut = new java.lang.StringBuffer(256);
+ sOut.append("FCFGMerge\n");
+ sOut.append("Copyright: 2003 by Sun Microsystems, Inc.\n");
+ sOut.append("All Rights Reserved.\n");
+ System.out.println(sOut.toString());
+ }
+
+ //___________________________________________
+
+ /** prints out a help message on stdout.
+ */
+ private static void printHelp()
+ {
+ java.lang.StringBuffer sOut = new java.lang.StringBuffer(256);
+ sOut.append("____________________________________________________________\n");
+ sOut.append("usage: FCFGMerge cfg=<file name>\n" );
+ sOut.append("parameters:\n" );
+ sOut.append("\tcfg=<file name>\n" );
+ sOut.append("\t\tmust point to a system file, which contains\n" );
+ sOut.append("\t\tall neccessary configuration data for the merge process.\n");
+ sOut.append("\n\tFurther cou can specify every parameter allowed in the\n" );
+ sOut.append("\n\tconfig file as command line parameter too, to overwrite\n" );
+ sOut.append("\n\tthe value from the file.\n" );
+ System.out.println(sOut.toString());
+ }
+}
diff --git a/l10ntools/source/filter/merge/Manifest.mf b/l10ntools/source/filter/merge/Manifest.mf
new file mode 100644
index 000000000000..1337eaf4d39a
--- /dev/null
+++ b/l10ntools/source/filter/merge/Manifest.mf
@@ -0,0 +1 @@
+Main-Class: com.sun.star.filter.config.tools.merge.FCFGMerge
diff --git a/l10ntools/source/filter/merge/Merger.java b/l10ntools/source/filter/merge/Merger.java
new file mode 100644
index 000000000000..0bf11fc42fbf
--- /dev/null
+++ b/l10ntools/source/filter/merge/Merger.java
@@ -0,0 +1,364 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Merger.java,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.filter.config.tools.merge;
+
+//_______________________________________________
+
+import java.lang.*;
+import java.util.*;
+import java.io.*;
+import com.sun.star.filter.config.tools.utils.*;
+
+//_______________________________________________
+
+/** can merge different xml fragments together.
+ *
+ *
+ */
+public class Merger
+{
+ //___________________________________________
+ // const
+
+ private static final java.lang.String PROP_XMLVERSION = "xmlversion" ; // <= global cfg file
+ private static final java.lang.String PROP_XMLENCODING = "xmlencoding" ; // <= global cfg file
+ private static final java.lang.String PROP_XMLPATH = "xmlpath" ; // <= global cfg file
+ private static final java.lang.String PROP_XMLPACKAGE = "xmlpackage" ; // <= global cfg file
+
+ private static final java.lang.String PROP_SETNAME_TYPES = "setname_types" ; // <= global cfg file
+ private static final java.lang.String PROP_SETNAME_FILTERS = "setname_filters" ; // <= global cfg file
+ private static final java.lang.String PROP_SETNAME_LOADERS = "setname_frameloaders" ; // <= global cfg file
+ private static final java.lang.String PROP_SETNAME_HANDLERS = "setname_contenthandlers" ; // <= global cfg file
+
+ private static final java.lang.String PROP_SUBDIR_TYPES = "subdir_types" ; // <= global cfg file
+ private static final java.lang.String PROP_SUBDIR_FILTERS = "subdir_filters" ; // <= global cfg file
+ private static final java.lang.String PROP_SUBDIR_LOADERS = "subdir_frameloaders" ; // <= global cfg file
+ private static final java.lang.String PROP_SUBDIR_HANDLERS = "subdir_contenthandlers" ; // <= global cfg file
+
+ private static final java.lang.String PROP_EXTENSION_XCU = "extension_xcu" ; // <= global cfg file
+ private static final java.lang.String PROP_EXTENSION_PKG = "extension_pkg" ; // <= global cfg file
+
+ private static final java.lang.String PROP_DELIMITER = "delimiter" ; // <= global cfg file
+ private static final java.lang.String PROP_TRIM = "trim" ; // <= global cfg file
+ private static final java.lang.String PROP_DECODE = "decode" ; // <= global cfg file
+
+ private static final java.lang.String PROP_FRAGMENTSDIR = "fragmentsdir" ; // <= cmdline
+ private static final java.lang.String PROP_TEMPDIR = "tempdir" ; // <= cmdline
+ private static final java.lang.String PROP_OUTDIR = "outdir" ; // <= cmdline
+ private static final java.lang.String PROP_PKG = "pkg" ; // <= cmdline
+ private static final java.lang.String PROP_DEBUG = "debug" ; // <= cmdline
+
+ private static final java.lang.String PROP_TCFG = "tcfg" ; // <= cmdline
+ private static final java.lang.String PROP_FCFG = "fcfg" ; // <= cmdline
+ private static final java.lang.String PROP_LCFG = "lcfg" ; // <= cmdline
+ private static final java.lang.String PROP_CCFG = "ccfg" ; // <= cmdline
+ private static final java.lang.String PROP_LANGUAGEPACK = "languagepack" ; // <= cmdline
+
+ private static final java.lang.String PROP_ITEMS = "items" ; // <= pkg cfg files!
+
+ //___________________________________________
+ // member
+
+ //-------------------------------------------
+ /** TODO */
+ private ConfigHelper m_aCfg;
+
+ //-------------------------------------------
+ /** TODO */
+ private Logger m_aLog;
+
+ //-------------------------------------------
+ /** TODO */
+ private java.io.File m_aFragmentsDir;
+
+ //-------------------------------------------
+ /** TODO */
+ private java.io.File m_aTempDir;
+
+ //-------------------------------------------
+ /** TODO */
+ private java.io.File m_aOutDir;
+
+ //-------------------------------------------
+ /** TODO */
+ private java.util.Vector m_lTypes;
+ private java.util.Vector m_lFilters;
+ private java.util.Vector m_lLoaders;
+ private java.util.Vector m_lHandlers;
+
+ //___________________________________________
+ // interface
+
+ //-------------------------------------------
+ /** initialize a new instance of this class and
+ * try to get all needed resources from the config module.
+ *
+ * @param aCfg
+ * provides access to all values of the global
+ * config file and to the command line.
+ *
+ * @param aLog
+ * can be used to print out log informations.
+ */
+ public Merger(ConfigHelper aCfg,
+ Logger aLog)
+ throws java.lang.Exception
+ {
+ m_aCfg = aCfg;
+ m_aLog = aLog;
+
+ m_aFragmentsDir = new java.io.File(m_aCfg.getString(PROP_FRAGMENTSDIR));
+ m_aTempDir = new java.io.File(m_aCfg.getString(PROP_TEMPDIR ));
+// m_aOutDir = new java.io.File(m_aCfg.getString(PROP_OUTDIR ));
+
+ java.lang.String sDelimiter = m_aCfg.getString(PROP_DELIMITER);
+ boolean bTrim = m_aCfg.getBoolean(PROP_TRIM);
+ boolean bDecode = m_aCfg.getBoolean(PROP_DECODE);
+
+ try
+ {
+ ConfigHelper aFcfg = new ConfigHelper(m_aCfg.getString(PROP_TCFG), null);
+ m_lTypes = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode);
+ }
+ catch(java.util.NoSuchElementException ex1)
+ {
+ m_lTypes = new java.util.Vector();
+ //m_aLog.setWarning("Fragment list of types is missing. Parameter \"items\" seems to be invalid.");
+ }
+
+ try
+ {
+ ConfigHelper aFcfg = new ConfigHelper(m_aCfg.getString(PROP_FCFG), null);
+ m_lFilters = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode);
+ }
+ catch(java.util.NoSuchElementException ex1)
+ {
+ m_lFilters = new java.util.Vector();
+ //m_aLog.setWarning("Fragment list of filters is missing. Parameter \"items\" seems to be invalid.");
+ }
+
+ try
+ {
+ ConfigHelper aFcfg = new ConfigHelper(m_aCfg.getString(PROP_LCFG), null);
+ m_lLoaders = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode);
+ }
+ catch(java.util.NoSuchElementException ex1)
+ {
+ m_lLoaders = new java.util.Vector();
+ //m_aLog.setWarning("Fragment list of frame loader objects is missing. Parameter \"items\" seems to be invalid.");
+ }
+
+ try
+ {
+ ConfigHelper aFcfg = new ConfigHelper(m_aCfg.getString(PROP_CCFG), null);
+ m_lHandlers = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode);
+ }
+ catch(java.util.NoSuchElementException ex1)
+ {
+ m_lHandlers = new java.util.Vector();
+ //m_aLog.setWarning("Fragment list of content handler objects is missing. Parameter \"items\" seems to be invalid.");
+ }
+ }
+
+ //-------------------------------------------
+ /** TODO */
+ public synchronized void merge()
+ throws java.lang.Exception
+ {
+ java.lang.StringBuffer sBuffer = new java.lang.StringBuffer(1000000);
+ java.lang.String sPackage = m_aCfg.getString(PROP_PKG);
+
+ m_aLog.setGlobalInfo("create package \""+sPackage+"\" ...");
+ m_aLog.setDetailedInfo("generate package header ... ");
+
+ sBuffer.append(
+ XMLHelper.generateHeader(
+ m_aCfg.getString (PROP_XMLVERSION ),
+ m_aCfg.getString (PROP_XMLENCODING ),
+ m_aCfg.getString (PROP_XMLPATH ),
+ m_aCfg.getString (PROP_XMLPACKAGE ),
+ m_aCfg.getBoolean(PROP_LANGUAGEPACK, false)));
+
+ // counts all transfered fragments
+ // Can be used later to decide, if a generated package file
+ // contains "nothing"!
+ int nItemCount = 0;
+
+ for (int i=0; i<4; ++i)
+ {
+ java.lang.String sSetName = null;
+ java.lang.String sSubDir = null;
+ java.util.Vector lFragments = null;
+
+ try
+ {
+ switch(i)
+ {
+ case 0: // types
+ {
+ m_aLog.setDetailedInfo("generate set for types ... ");
+ sSetName = m_aCfg.getString(PROP_SETNAME_TYPES);
+ sSubDir = m_aCfg.getString(PROP_SUBDIR_TYPES );
+ lFragments = m_lTypes;
+ }
+ break;
+
+ case 1: // filters
+ {
+ m_aLog.setDetailedInfo("generate set for filter ... ");
+ sSetName = m_aCfg.getString(PROP_SETNAME_FILTERS);
+ sSubDir = m_aCfg.getString(PROP_SUBDIR_FILTERS );
+ lFragments = m_lFilters;
+ }
+ break;
+
+ case 2: // loaders
+ {
+ m_aLog.setDetailedInfo("generate set for frame loader ... ");
+ sSetName = m_aCfg.getString(PROP_SETNAME_LOADERS);
+ sSubDir = m_aCfg.getString(PROP_SUBDIR_LOADERS );
+ lFragments = m_lLoaders;
+ }
+ break;
+
+ case 3: // handlers
+ {
+ m_aLog.setDetailedInfo("generate set for content handler ... ");
+ sSetName = m_aCfg.getString(PROP_SETNAME_HANDLERS);
+ sSubDir = m_aCfg.getString(PROP_SUBDIR_HANDLERS );
+ lFragments = m_lHandlers;
+ }
+ break;
+ }
+
+ nItemCount += lFragments.size();
+
+ getFragments(
+ new java.io.File(m_aFragmentsDir, sSubDir),
+ sSetName,
+ lFragments,
+ 1,
+ sBuffer);
+ }
+ catch(java.util.NoSuchElementException exIgnore)
+ { continue; }
+ }
+
+ m_aLog.setDetailedInfo("generate package footer ... ");
+ sBuffer.append(XMLHelper.generateFooter());
+
+ // Attention!
+ // If the package seem to be empty, it make no sense to generate a corresponding
+ // xml file. We should suppress writing of this file on disk completly ...
+ if (nItemCount < 1)
+ {
+ m_aLog.setWarning("Package is empty and will not result into a xml file on disk!? Please check configuration file.");
+ return;
+ }
+ m_aLog.setGlobalInfo("package contains "+nItemCount+" items");
+
+ java.io.File aPackage = new File(sPackage);
+ m_aLog.setGlobalInfo("write temp package \""+aPackage.getPath()); // TODO encoding must be readed from the configuration
+ FileHelper.writeEncodedBufferToFile(aPackage, "UTF-8", false, sBuffer); // check for success is done inside this method!
+ }
+
+ //-------------------------------------------
+ /** TODO */
+ private void getFragments(java.io.File aDir ,
+ java.lang.String sSetName ,
+ java.util.Vector lFragments ,
+ int nPrettyTabs,
+ java.lang.StringBuffer sBuffer )
+ throws java.lang.Exception
+ {
+ if (lFragments.size()<1)
+ {
+ m_aLog.setWarning("List of fragments is empty!? Will be ignored ...");
+ return;
+ }
+
+ java.util.Enumeration pFragments = lFragments.elements();
+ java.lang.String sExtXcu = m_aCfg.getString(PROP_EXTENSION_XCU);
+
+ for (int tabs=0; tabs<nPrettyTabs; ++tabs)
+ sBuffer.append("\t");
+ sBuffer.append("<node oor:name=\""+sSetName+"\">\n");
+ ++nPrettyTabs;
+
+ // special mode for generating language packs.
+ // In such case we must live with some missing fragment files.
+ // Reason behind; Not all filters are realy localized.
+ // But we dont use a different fragment list. We try to locate
+ // any fragment file in its language-pack version ...
+ boolean bHandleLanguagePacks = m_aCfg.getBoolean(PROP_LANGUAGEPACK, false);
+ boolean bDebug = m_aCfg.getBoolean(PROP_DEBUG , false);
+ java.lang.String sEncoding = "UTF-8";
+ if (bDebug)
+ sEncoding = "UTF-8Special";
+
+ while(pFragments.hasMoreElements())
+ {
+ java.lang.String sFragment = (java.lang.String)pFragments.nextElement();
+ java.io.File aFragment = new java.io.File(aDir, sFragment+"."+sExtXcu);
+
+ // handle simple files only and check for existence!
+ if (!aFragment.exists())
+ {
+ if (bHandleLanguagePacks)
+ {
+ m_aLog.setWarning("language fragment \""+aFragment.getPath()+"\" does not exist. Will be ignored.");
+ continue;
+ }
+ else
+ throw new java.io.IOException("fragment \""+aFragment.getPath()+"\" does not exists.");
+ }
+
+ if (!aFragment.isFile())
+ {
+ m_aLog.setWarning("fragment \""+aFragment.getPath()+"\" seem to be not a valid file.");
+ continue;
+ }
+
+ // copy file content of original fragment
+ // Note: A FileNotFoundException will be thrown automaticly by the
+ // used reader objects. Let it break this method too. Our calli is interested
+ // on such errors :-)
+ m_aLog.setDetailedInfo("merge fragment \""+aFragment.getPath()+"\" ...");
+ FileHelper.readEncodedBufferFromFile(aFragment, sEncoding, sBuffer);
+
+ sBuffer.append("\n");
+ }
+
+ --nPrettyTabs;
+ for (int tabs=0; tabs<nPrettyTabs; ++tabs)
+ sBuffer.append("\t");
+ sBuffer.append("</node>\n");
+ }
+}
diff --git a/l10ntools/source/filter/merge/makefile.mk b/l10ntools/source/filter/merge/makefile.mk
new file mode 100644
index 000000000000..510ec3202bb4
--- /dev/null
+++ b/l10ntools/source/filter/merge/makefile.mk
@@ -0,0 +1,96 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.9.102.1 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ = ..$/..$/..
+TARGET = FCFGMerge
+PRJNAME = l10ntools
+PACKAGE = com$/sun$/star$/filter$/config$/tools$/merge
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE: settings.mk
+
+#----- compile .java files -----------------------------------------
+#.IF "$(L10N_framework)"==""
+
+OWNCOPY = \
+ $(MISC)$/$(TARGET)_copied.done
+
+#JARFILES = \
+# ridl.jar \
+# unoil.jar \
+# jurt.jar \
+# juh.jar \
+# java_uno.jar
+
+CFGFILES = \
+ FCFGMerge.cfg
+
+JAVACLASSFILES = \
+ $(CLASSDIR)$/$(PACKAGE)$/Merger.class \
+ $(CLASSDIR)$/$(PACKAGE)$/FCFGMerge.class
+
+CUSTOMMANIFESTFILE = \
+ Manifest.mf
+
+MAXLINELENGTH = 100000
+
+#----- make a jar from compiled files ------------------------------
+
+JARCLASSDIRS = \
+ com$/sun$/star$/filter$/config$/tools$/utils \
+ com$/sun$/star$/filter$/config$/tools$/merge
+
+JARTARGET = $(TARGET).jar
+
+JARCOMPRESS = TRUE
+
+# --- targets -----------------------------------------------------
+
+.INCLUDE : target.mk
+
+.IF "$(SOLAR_JAVA)" != "" || "$(GUI)"=="OS2"
+ALLTAR : $(OWNCOPY)
+
+.IF "$(JARTARGETN)" != ""
+$(JARTARGETN) : $(OWNCOPY)
+.ENDIF
+
+$(OWNCOPY) : $(CFGFILES)
+ -$(MKDIRHIER) $(CLASSDIR)$/$(PACKAGE)
+ $(COPY) $? $(CLASSDIR)$/$(PACKAGE) && $(TOUCH) $@
+
+.ENDIF # "$(SOLAR_JAVA)" != ""
+
+#.ELSE
+#pseudo:
+
+#.ENDIF
diff --git a/l10ntools/source/filter/utils/AnalyzeStartupLog.java b/l10ntools/source/filter/utils/AnalyzeStartupLog.java
new file mode 100644
index 000000000000..498528850697
--- /dev/null
+++ b/l10ntools/source/filter/utils/AnalyzeStartupLog.java
@@ -0,0 +1,328 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: AnalyzeStartupLog.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package com.sun.star.filter.config.tools.utils;
+
+//_______________________________________________
+// imports
+import java.util.*;
+import java.lang.*;
+
+//_______________________________________________
+// implementation
+public class AnalyzeStartupLog
+{
+ private class OperationTime
+ {
+ /** name the measured operation. */
+ public java.lang.String sOperation;
+
+ /** contains the time value, when this operation was started. */
+ public long nStartTime;
+
+ /** contains the time value, when this operation was finished. */
+ public long nEndTime;
+
+ /** text inside log file, which identifies the start time value. */
+ public java.lang.String sStartMsg;
+
+ /** text inside log file, which identifies the end time value. */
+ public java.lang.String sEndMsg;
+ }
+
+ //_________________________________
+ // main
+
+ public static void main(java.lang.String[] lCmdLine)
+ {
+ int nExit = 0;
+ try
+ {
+ // analyze command line
+ ConfigHelper aCmdLine = new ConfigHelper("", lCmdLine);
+ java.lang.String sLogDir = aCmdLine.getString("logdir" );
+ java.lang.String sDataFile = aCmdLine.getString("datafile");
+
+ if (sLogDir == null || sDataFile == null)
+ {
+ System.err.println("AnalyzeStartupLog lodir=<dir> datafile=<file>");
+ System.err.println("E.g.: AnalyzeStartupLog lodir=c:\\temp\\logs datafile=c:\\temp\\data.csv");
+ System.exit(--nExit);
+ }
+
+ // get list of all log files
+ boolean bRecursive = true;
+ java.util.Vector lLogs = FileHelper.getSystemFilesFromDir(new java.io.File(sLogDir), bRecursive);
+ if (lLogs == null || lLogs.isEmpty())
+ {
+ System.err.println("log dir is empty");
+ System.exit(--nExit);
+ }
+
+ // analyze it
+ java.lang.StringBuffer sOut = new java.lang.StringBuffer(1000);
+ sOut.append("log;t_cfg_start;t_cfg_end;t_fwk_start;t_fwk_end;t_sfx_start;t_sfx_end;t_types_start;t_types_end;t_filters_start;t_filters_end;");
+ sOut.append("t_filters_swriter_start;t_filters_swriter_end;t_filters_sweb_start;t_filters_sweb_end;t_filters_sglobal_start;t_filters_sglobal_end;t_filters_scalc_start;t_filters_scalc_end;t_filters_sdraw_start;t_filters_sdraw_end;t_filters_simpress_start;t_filters_simpress_end;t_filters_schart_start;t_filters_schart_end;t_filters_smath_start;t_filters_smath_end;");
+ sOut.append("t_others_start;t_others_end;d_cfg;d_fwk;d_sfx;d_types;d_filters;d_others;d_complete\n");
+
+ java.util.Enumeration aIt = lLogs.elements();
+ while (aIt.hasMoreElements())
+ {
+ java.io.File aLog = (java.io.File)aIt.nextElement();
+ java.io.FileReader aReader = new java.io.FileReader(aLog);
+ java.io.BufferedReader aBuffer = new java.io.BufferedReader(aReader);
+
+ long t_cfg_start = 0;
+ long t_cfg_end = 0;
+
+ long t_fwk_start = 0;
+ long t_fwk_end = 0;
+
+ long t_sfx_start = 0;
+ long t_sfx_end = 0;
+
+ long t_types_start = 0;
+ long t_types_end = 0;
+
+ long t_filters_start = 0;
+ long t_filters_end = 0;
+
+ long t_filters_swriter_start = 0;
+ long t_filters_swriter_end = 0;
+
+ long t_filters_sweb_start = 0;
+ long t_filters_sweb_end = 0;
+
+ long t_filters_sglobal_start = 0;
+ long t_filters_sglobal_end = 0;
+
+ long t_filters_scalc_start = 0;
+ long t_filters_scalc_end = 0;
+
+ long t_filters_sdraw_start = 0;
+ long t_filters_sdraw_end = 0;
+
+ long t_filters_simpress_start = 0;
+ long t_filters_simpress_end = 0;
+
+ long t_filters_schart_start = 0;
+ long t_filters_schart_end = 0;
+
+ long t_filters_smath_start = 0;
+ long t_filters_smath_end = 0;
+
+ long t_others_start = 0;
+ long t_others_end = 0;
+
+ while (true)
+ {
+ java.lang.String sLine = aBuffer.readLine();
+ if (sLine == null)
+ break;
+
+ if (sLine.endsWith("| framework (as96863) ::FilterCache::FilterCache : { creation ConfigItem [file=standard, version=6, mode=3]"))
+ t_cfg_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("| framework (as96863) ::FilterCache::FilterCache : } creation ConfigItem"))
+ t_cfg_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("| framework (as96863) ::FilterCache::FilterCache : { reading TypeDetection.xml"))
+ t_fwk_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("| framework (as96863) ::FilterCache::FilterCache : } reading TypeDetection.xml"))
+ t_fwk_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ framework (as96863) ::FilterCFGAccess::impl_loadTypes"))
+ t_types_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} framework (as96863) ::FilterCFGAccess::impl_loadTypes"))
+ t_types_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ framework (as96863) ::FilterCFGAccess::impl_loadFilters"))
+ t_filters_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} framework (as96863) ::FilterCFGAccess::impl_loadFilters"))
+ t_filters_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ reading FilterGroup [swriter]"))
+ t_filters_swriter_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} reading FilterGroup [swriter]"))
+ t_filters_swriter_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ reading FilterGroup [sweb]"))
+ t_filters_sweb_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} reading FilterGroup [sweb]"))
+ t_filters_sweb_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ reading FilterGroup [sglobal]"))
+ t_filters_sglobal_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} reading FilterGroup [sglobal]"))
+ t_filters_sglobal_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ reading FilterGroup [scalc]"))
+ t_filters_scalc_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} reading FilterGroup [scalc]"))
+ t_filters_scalc_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ reading FilterGroup [sdraw]"))
+ t_filters_sdraw_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} reading FilterGroup [sdraw]"))
+ t_filters_sdraw_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ reading FilterGroup [simpress]"))
+ t_filters_simpress_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} reading FilterGroup [simpress]"))
+ t_filters_simpress_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ reading FilterGroup [schart]"))
+ t_filters_schart_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} reading FilterGroup [schart]"))
+ t_filters_schart_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ reading FilterGroup [smath]"))
+ t_filters_smath_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} reading FilterGroup [smath]"))
+ t_filters_smath_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("{ framework (as96863) ::FilterCFGAccess::impl_loadDetectors"))
+ t_others_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} framework (as96863) ::FilterCFGAccess::impl_loadContentHandlers"))
+ t_others_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} framework (as96863) ::FilterCache::FilterCache"))
+ t_sfx_start = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ else
+ if (sLine.endsWith("} desktop (lo119109) OfficeWrapper::OfficeWrapper"))
+ t_sfx_end = new java.lang.Long(sLine.substring(0, 6)).longValue();
+ }
+
+ sOut.append(aLog.getName() );
+ sOut.append(";" );
+ sOut.append(t_cfg_start );
+ sOut.append(";" );
+ sOut.append(t_cfg_end );
+ sOut.append(";" );
+ sOut.append(t_fwk_start );
+ sOut.append(";" );
+ sOut.append(t_fwk_end );
+ sOut.append(";" );
+ sOut.append(t_sfx_start );
+ sOut.append(";" );
+ sOut.append(t_sfx_end );
+ sOut.append(";" );
+ sOut.append(t_types_start );
+ sOut.append(";" );
+ sOut.append(t_types_end );
+ sOut.append(";" );
+ sOut.append(t_filters_start );
+ sOut.append(";" );
+ sOut.append(t_filters_end );
+ sOut.append(";" );
+
+ sOut.append(t_filters_swriter_start );
+ sOut.append(";" );
+ sOut.append(t_filters_swriter_end );
+ sOut.append(";" );
+ sOut.append(t_filters_sweb_start );
+ sOut.append(";" );
+ sOut.append(t_filters_sweb_end );
+ sOut.append(";" );
+ sOut.append(t_filters_sglobal_start );
+ sOut.append(";" );
+ sOut.append(t_filters_sglobal_end );
+ sOut.append(";" );
+ sOut.append(t_filters_scalc_start );
+ sOut.append(";" );
+ sOut.append(t_filters_scalc_end );
+ sOut.append(";" );
+ sOut.append(t_filters_sdraw_start );
+ sOut.append(";" );
+ sOut.append(t_filters_sdraw_end );
+ sOut.append(";" );
+ sOut.append(t_filters_simpress_start );
+ sOut.append(";" );
+ sOut.append(t_filters_simpress_end );
+ sOut.append(";" );
+ sOut.append(t_filters_schart_start );
+ sOut.append(";" );
+ sOut.append(t_filters_schart_end );
+ sOut.append(";" );
+ sOut.append(t_filters_smath_start );
+ sOut.append(";" );
+ sOut.append(t_filters_smath_end );
+ sOut.append(";" );
+
+ sOut.append(t_others_start );
+ sOut.append(";" );
+ sOut.append(t_others_end );
+ sOut.append(";" );
+ sOut.append(t_cfg_end -t_cfg_start );
+ sOut.append(";" );
+ sOut.append(t_fwk_end -t_fwk_start );
+ sOut.append(";" );
+ sOut.append(t_sfx_end -t_sfx_start );
+ sOut.append(";" );
+ sOut.append(t_types_end -t_types_start );
+ sOut.append(";" );
+ sOut.append(t_filters_end-t_filters_start);
+ sOut.append(";" );
+ sOut.append(t_others_end -t_others_start );
+ sOut.append(";" );
+ sOut.append(t_others_end -t_cfg_start );
+ sOut.append("\n" );
+
+ aBuffer.close();
+ }
+
+ java.io.FileWriter aCSV = new java.io.FileWriter(sDataFile);
+ java.lang.String sData = sOut.toString();
+ aCSV.write(sData, 0, sData.length());
+ aCSV.flush();
+ aCSV.close();
+ }
+ catch(java.lang.Throwable exAny)
+ {
+ System.err.println(exAny.getMessage());
+ exAny.printStackTrace();
+ System.exit(--nExit);
+ }
+
+ System.exit(0);
+ }
+}
diff --git a/l10ntools/source/filter/utils/Cache.java b/l10ntools/source/filter/utils/Cache.java
new file mode 100644
index 000000000000..94c26008ed13
--- /dev/null
+++ b/l10ntools/source/filter/utils/Cache.java
@@ -0,0 +1,2449 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Cache.java,v $
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package com.sun.star.filter.config.tools.utils;
+
+//_______________________________________________
+
+import java.lang.*;
+import java.util.*;
+import java.io.*;
+
+//_______________________________________________
+
+/**
+ * It implements a container for all possible entries which are part of the type
+ * and filter mechanism of an office - means all items of the configuration file
+ * "TypeDetection". How these entries will be readed or written can be switch
+ * in different modes. That would make it possible to edit an xml directly or
+ * to contact a running office instance.
+ *
+ *
+ */
+public class Cache
+{
+ //___________________________________________
+ // public const
+
+ /** identifies a file type item of this cache. */
+ public static final int E_TYPE = 0;
+
+ /** identifies a filter item of this cache. */
+ public static final int E_FILTER = 1;
+
+ /** identifies a detect service item of this cache. */
+ public static final int E_DETECTSERVICE = 2;
+
+ /** identifies a frame loader item of this cache. */
+ public static final int E_FRAMELOADER = 3;
+
+ /** identifies a content handler item of this cache. */
+ public static final int E_CONTENTHANDLER = 4;
+
+ /** indicates an unsupported xml format => error! */
+ public static final int FORMAT_UNSUPPORTED = -1;
+
+ /** identify the configuration format of an office 6.0.
+ * The own formated data string is used. */
+ public static final int FORMAT_60 = 0;
+
+ /** identify the configuration format of an office 6.y.
+ * Properties are realy xml tags again. */
+ public static final int FORMAT_6Y = 1;
+
+ /** identify the configuration format which is used inside
+ * this tooling project. */
+ public static final int FORMAT_INTERNAL = 2;
+
+ /** right value for a command line parameter to define a 6.0 version. */
+ public static final java.lang.String CMDVAL_FORMAT_60 = "6.0";
+
+ /** right value for a command line parameter to define a 6.Y version. */
+ public static final java.lang.String CMDVAL_FORMAT_6Y = "6.Y";
+
+ /** right value for a command line parameter to define an internal xml version! */
+ public static final java.lang.String CMDVAL_FORMAT_INTERNAL = "internal";
+
+ // general
+ public static final java.lang.String PROPNAME_DATA = "Data";
+ public static final java.lang.String PROPNAME_NAME = "Name";
+ public static final java.lang.String PROPNAME_UINAME = "UIName";
+ public static final java.lang.String PROPNAME_UINAMES = "UINames";
+
+ // type 6.0 ...
+ public static final java.lang.String PROPNAME_MEDIATYPE = "MediaType";
+ public static final java.lang.String PROPNAME_PREFERRED = "Preferred";
+ public static final java.lang.String PROPNAME_CLIPBOARDFORMAT = "ClipboardFormat";
+ public static final java.lang.String PROPNAME_DOCUMENTICONID = "DocumentIconID";
+ public static final java.lang.String PROPNAME_URLPATTERN = "URLPattern";
+ public static final java.lang.String PROPNAME_EXTENSIONS = "Extensions";
+ // ... +6.y
+ public static final java.lang.String PROPNAME_UIORDER = "UIOrder";
+ public static final java.lang.String PROPNAME_PREFERREDFILTER = "PreferredFilter";
+ public static final java.lang.String PROPNAME_DETECTSERVICE = "DetectService";
+ public static final java.lang.String PROPNAME_FRAMELOADER = "FrameLoader";
+ public static final java.lang.String PROPNAME_CONTENTHANDLER = "ContentHandler";
+
+ // filter
+ public static final java.lang.String PROPNAME_DOCUMENTSERVICE = "DocumentService";
+ public static final java.lang.String PROPNAME_FILEFORMATVERSION = "FileFormatVersion";
+ public static final java.lang.String PROPNAME_FILTERSERVICE = "FilterService";
+ public static final java.lang.String PROPNAME_FLAGS = "Flags";
+ public static final java.lang.String PROPNAME_ORDER = "Order"; // -6.y
+ public static final java.lang.String PROPNAME_TEMPLATENAME = "TemplateName";
+ public static final java.lang.String PROPNAME_TYPE = "Type";
+ public static final java.lang.String PROPNAME_UICOMPONENT = "UIComponent";
+ public static final java.lang.String PROPNAME_USERDATA = "UserData";
+
+ // frame loader / detect services / content handler
+ public static final java.lang.String PROPNAME_TYPES = "Types";
+
+ //___________________________________________
+ // private const
+
+ private static final java.lang.String FILTERSERVICE_NATIVEWARPPER = "com.sun.star.filter.NativeFilterWrapper";
+ private static final java.lang.String GENERIC_DETECTSERVICE = "com.sun.star.comp.office.FrameLoader";
+
+ /** its the name of the cfg set, which contains all types. */
+ private static final java.lang.String CFGNODE_TYPES = "Types";
+
+ /** its the name of the cfg set, which contains all filters. */
+ private static final java.lang.String CFGNODE_FILTERS = "Filters";
+
+ /** its the name of the cfg set, which contains all detect services. */
+ private static final java.lang.String CFGNODE_DETECTSERVICES = "DetectServices";
+
+ /** its the name of the cfg set, which contains all frame loaders. */
+ private static final java.lang.String CFGNODE_FRAMELOADERS = "FrameLoaders";
+
+ /** its the name of the cfg set, which contains all content handlers. */
+ private static final java.lang.String CFGNODE_CONTENTHANDLERS = "ContentHandlers";
+
+ // names for filter flags
+ private static final java.lang.String FLAGNAME_3RDPARTYFILTER = "3RDPARTYFILTER";
+ private static final java.lang.String FLAGNAME_ALIEN = "ALIEN";
+ private static final java.lang.String FLAGNAME_ASYNCHRON = "ASYNCHRON";
+ private static final java.lang.String FLAGNAME_BROWSERPREFERRED = "BROWSERPREFERRED";
+ private static final java.lang.String FLAGNAME_CONSULTSERVICE = "CONSULTSERVICE";
+ private static final java.lang.String FLAGNAME_DEFAULT = "DEFAULT";
+ private static final java.lang.String FLAGNAME_EXPORT = "EXPORT";
+ private static final java.lang.String FLAGNAME_IMPORT = "IMPORT";
+ private static final java.lang.String FLAGNAME_INTERNAL = "INTERNAL";
+ private static final java.lang.String FLAGNAME_NOTINCHOOSER = "NOTINCHOOSER";
+ private static final java.lang.String FLAGNAME_NOTINFILEDIALOG = "NOTINFILEDIALOG";
+ private static final java.lang.String FLAGNAME_NOTINSTALLED = "NOTINSTALLED";
+ private static final java.lang.String FLAGNAME_OWN = "OWN";
+ private static final java.lang.String FLAGNAME_PACKED = "PACKED";
+ private static final java.lang.String FLAGNAME_PREFERRED = "PREFERRED";
+ private static final java.lang.String FLAGNAME_READONLY = "READONLY";
+ private static final java.lang.String FLAGNAME_SILENTEXPORT = "SILENTEXPORT";
+ private static final java.lang.String FLAGNAME_TEMPLATE = "TEMPLATE";
+ private static final java.lang.String FLAGNAME_TEMPLATEPATH = "TEMPLATEPATH";
+ private static final java.lang.String FLAGNAME_USESOPTIONS = "USESOPTIONS";
+
+ private static final java.lang.String FLAGNAME_COMBINED = "COMBINED";
+ private static final java.lang.String FLAGNAME_SUPPORTSSELECTION= "SUPPORTSSELECTION";
+
+ // values for filter flags
+ private static final int FLAGVAL_3RDPARTYFILTER = 0x00080000; // 524288
+ private static final int FLAGVAL_ALIEN = 0x00000040; // 64
+ private static final int FLAGVAL_ALL = 0xffffffff; // 4294967295
+ private static final int FLAGVAL_ASYNCHRON = 0x00004000; // 16384
+ private static final int FLAGVAL_BROWSERPREFERRED = 0x00400000; // 4194304
+ private static final int FLAGVAL_CONSULTSERVICE = 0x00040000; // 262144
+ private static final int FLAGVAL_DEFAULT = 0x00000100; // 256
+ private static final int FLAGVAL_EXPORT = 0x00000002; // 2
+ private static final int FLAGVAL_IMPORT = 0x00000001; // 1
+ private static final int FLAGVAL_INTERNAL = 0x00000008; // 8
+ private static final int FLAGVAL_NOTINCHOOSER = 0x00002000; // 8192
+ private static final int FLAGVAL_NOTINFILEDIALOG = 0x00001000; // 4096
+ private static final int FLAGVAL_NOTINSTALLED = 0x00020000; // 131072
+ private static final int FLAGVAL_OWN = 0x00000020; // 32
+ private static final int FLAGVAL_PACKED = 0x00100000; // 1048576
+ private static final int FLAGVAL_PREFERRED = 0x10000000; // 268435456
+ private static final int FLAGVAL_READONLY = 0x00010000; // 65536
+ private static final int FLAGVAL_SILENTEXPORT = 0x00200000; // 2097152
+ private static final int FLAGVAL_TEMPLATE = 0x00000004; // 4
+ private static final int FLAGVAL_TEMPLATEPATH = 0x00000010; // 16
+ private static final int FLAGVAL_USESOPTIONS = 0x00000080; // 128
+
+ private static final int FLAGVAL_COMBINED = 0x00800000; // ...
+ private static final int FLAGVAL_SUPPORTSSELECTION = 0x00000400; // 1024
+
+ //___________________________________________
+ // member
+
+ /** list of all located types.
+ * Format: [string,HashMap]
+ */
+ private java.util.HashMap m_lTypes;
+
+ /** list of all located filters.
+ * Format: [string,HashMap]
+ */
+ private java.util.HashMap m_lFilters;
+
+ /** list of all located detect services.
+ * Format: [string,HashMap]
+ */
+ private java.util.HashMap m_lDetectServices;
+
+ /** list of all located frame loader.
+ * Format: [string,HashMap]
+ */
+ private java.util.HashMap m_lFrameLoaders;
+
+ /** list of all located content handler.
+ * Format: [string,HashMap]
+ */
+ private java.util.HashMap m_lContentHandlers;
+
+ /** contains all analyzed relations between
+ * filters and types. The key is an internal
+ * type name (can be used as reference into the
+ * list m_lTypes) and the value is a Vector of all
+ * internal filter names, which are registered for
+ * this type.
+ * Format: [string, Vector]
+ */
+ private java.util.HashMap m_lFilterToTypeRegistrations;
+
+ private int m_nDoubleRegisteredFilters;
+ private int m_nTypesForFilters;
+ private int m_nTypesForDetectServices;
+ private int m_nTypesForFrameLoaders;
+ private int m_nTypesForContentHandlers;
+
+ /** can be used to log different informations. */
+ private Logger m_aDebug;
+
+ //___________________________________________
+ // interface
+
+ /** standard ctor.
+ *
+ * Initialize an empty cache instance. You have to use
+ * on of the fromXXX() methods to fill it from different
+ * sources with content.
+ */
+ public Cache(Logger aDebug)
+ {
+ reset();
+ m_aDebug = aDebug;
+ }
+
+ //___________________________________________
+
+ /** free memory and set default values on all members.
+ */
+ public synchronized void reset()
+ {
+ m_lTypes = new java.util.HashMap();
+ m_lFilters = new java.util.HashMap();
+ m_lFrameLoaders = new java.util.HashMap();
+ m_lDetectServices = new java.util.HashMap();
+ m_lContentHandlers = new java.util.HashMap();
+ m_lFilterToTypeRegistrations = new java.util.HashMap();
+ m_aDebug = new Logger();
+ m_nDoubleRegisteredFilters = 0;
+ m_nTypesForFilters = 0;
+ m_nTypesForDetectServices = 0;
+ m_nTypesForFrameLoaders = 0;
+ m_nTypesForContentHandlers = 0;
+ }
+
+ //___________________________________________
+
+ /** converts a string representation of an xml format
+ * to its int value, which must be used at some interface
+ * methods of this cache.
+ *
+ * If the given string does not match to any well known format,
+ * the return value will be FORMAT_UNSUPPORTED. The calli have to
+ * check that. Otherwhise a called interface method at this cache
+ * instance will be rejected by an exception!
+ *
+ * @param sFormat
+ * the string representation
+ * Must be one of our public const values from type CMDVAL_FORMAT_xxx.
+ *
+ * @return [int]
+ * the int representation.
+ * Will be one of our public const values from type FORMAT_xxx.
+ */
+ public static int mapFormatString2Format(java.lang.String sFormat)
+ {
+ int nFormat = FORMAT_UNSUPPORTED;
+ if (sFormat.equalsIgnoreCase(CMDVAL_FORMAT_60))
+ nFormat = FORMAT_60;
+ else
+ if (sFormat.equalsIgnoreCase(CMDVAL_FORMAT_6Y))
+ nFormat = FORMAT_6Y;
+ else
+ if (sFormat.equalsIgnoreCase(CMDVAL_FORMAT_INTERNAL))
+ nFormat = FORMAT_INTERNAL;
+ return nFormat;
+ }
+
+ //___________________________________________
+
+ /** return some statistic values.
+ *
+ * Such values can be: - count of container items,
+ * - ...
+ *
+ * @return [java.lang.String]
+ * a formated string, which contains al statistic data.
+ */
+ public synchronized java.lang.String getStatistics()
+ {
+ java.lang.StringBuffer sBuffer = new java.lang.StringBuffer(256);
+
+ sBuffer.append("types = "+m_lTypes.size() +"\n");
+ sBuffer.append("filters = "+m_lFilters.size() +"\n");
+ sBuffer.append("detect services = "+m_lDetectServices.size() +"\n");
+ sBuffer.append("frame loaders = "+m_lFrameLoaders.size() +"\n");
+ sBuffer.append("content handler = "+m_lContentHandlers.size() +"\n");
+ sBuffer.append("double registered filters = "+m_nDoubleRegisteredFilters+"\n");
+ sBuffer.append("types used by filters = "+m_nTypesForFilters +"\n");
+ sBuffer.append("types used by detect services = "+m_nTypesForDetectServices +"\n");
+ sBuffer.append("types used by frame loaders = "+m_nTypesForFrameLoaders +"\n");
+ sBuffer.append("types used by content handlers = "+m_nTypesForContentHandlers+"\n");
+
+ return sBuffer.toString();
+ }
+
+ //___________________________________________
+
+ /** reset this cache and fill it with new values using the given XML file.
+ *
+ * @param aXML
+ * must be a system file of a suitable XML file, which
+ * include all neccessary type/filter items.
+ *
+ * @param nFormat
+ * identifies the format of the specified xml file,
+ * which must be interpreted.
+ */
+ public synchronized void fromXML(java.io.File aXML ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ // clear this cache
+ reset();
+
+ // parse it
+ javax.xml.parsers.DocumentBuilderFactory aFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
+ /* Attention:
+ * This call is important. It force right handling of entities during parsing and(!)
+ * writing. It let all possible signs for entities or it's quoted representations
+ * untouched. So this class don't change the original signs of the original file.
+ * Means:
+ * <ul>
+ * <li>(') => (')</li>
+ * <li>(") => (")</li>
+ * <li>(>) => (&gt;)</li>
+ * <li>(<) => (&lt;)</li>
+ * <li>(&gt;) => (&gt;)</li>
+ * <li>(&amp;) => (&amp;)</li>
+ * <li>...</li>
+ * </ul>
+ */
+
+ System.out.println("TODO: must be adapted to java 1.3 :-(");
+ System.exit(-1);
+//TODO_JAVA aFactory.setExpandEntityReferences(false);
+
+ javax.xml.parsers.DocumentBuilder aBuilder = aFactory.newDocumentBuilder();
+ org.w3c.dom.Document aDOM = aBuilder.parse(aXML);
+ org.w3c.dom.Element aRoot = aDOM.getDocumentElement();
+
+ // step over all sets
+ java.util.Vector lSetNodes = XMLHelper.extractChildNodesByTagName(aRoot, XMLHelper.XMLTAG_NODE);
+ java.util.Enumeration it1 = lSetNodes.elements();
+ while (it1.hasMoreElements())
+ {
+ // try to find out, which set should be read
+ org.w3c.dom.Node aSetNode = (org.w3c.dom.Node)it1.nextElement();
+ java.lang.String sSetName = XMLHelper.extractNodeAttribByName(aSetNode, XMLHelper.XMLATTRIB_OOR_NAME);
+ if (sSetName == null)
+ throw new java.io.IOException("unsupported format: could not extract set name on node ...\n"+aSetNode);
+
+ // map some generic interfaces to the right members!
+ int eType = -1 ;
+ java.util.HashMap rMap = null;
+
+ if (sSetName.equals(CFGNODE_TYPES))
+ {
+ eType = E_TYPE;
+ rMap = m_lTypes;
+ }
+ else
+ if (sSetName.equals(CFGNODE_FILTERS))
+ {
+ eType = E_FILTER;
+ rMap = m_lFilters;
+ }
+ else
+ if (sSetName.equals(CFGNODE_FRAMELOADERS))
+ {
+ eType = E_FRAMELOADER;
+ rMap = m_lFrameLoaders;
+ }
+ else
+ if (sSetName.equals(CFGNODE_DETECTSERVICES))
+ {
+ eType = E_DETECTSERVICE;
+ rMap = m_lDetectServices;
+ }
+ else
+ if (sSetName.equals(CFGNODE_CONTENTHANDLERS))
+ {
+ eType = E_CONTENTHANDLER;
+ rMap = m_lContentHandlers;
+ }
+ else
+ throw new java.io.IOException("unsupported format: unknown set name [\""+sSetName+"\"] detected on node ...\n"+aSetNode);
+
+ // load all set entries
+ java.util.Vector lChildNodes = XMLHelper.extractChildNodesByTagName(aSetNode, XMLHelper.XMLTAG_NODE);
+ java.util.Enumeration it2 = lChildNodes.elements();
+ while (it2.hasMoreElements())
+ {
+ org.w3c.dom.Node aChildNode = (org.w3c.dom.Node)it2.nextElement();
+ java.lang.String sChildName = XMLHelper.extractNodeAttribByName(aChildNode, XMLHelper.XMLATTRIB_OOR_NAME);
+ if (sChildName == null)
+ throw new java.io.IOException("unsupported format: could not extract child node name on node ...\n"+aChildNode);
+ java.util.HashMap aPropSet = null;
+
+ // Note: Our internal format is different from the source format!
+ java.util.HashMap aTempSet = XMLHelper.convertNodeToPropSet(aChildNode);
+ switch(eType)
+ {
+ case E_TYPE :
+ {
+ aPropSet = Cache.convertTypePropsToInternal(aTempSet, nFormat);
+ m_aDebug.setDetailedInfo("type [\""+sChildName+"\"] converted to internal format");
+ }
+ break;
+
+ case E_FILTER :
+ {
+ aPropSet = Cache.convertFilterPropsToInternal(aTempSet, nFormat);
+ m_aDebug.setDetailedInfo("filter [\""+sChildName+"\"] converted to internal format");
+ }
+ break;
+
+ case E_DETECTSERVICE :
+ {
+ aPropSet = Cache.convertDetectServicePropsToInternal(aTempSet, nFormat);
+ m_aDebug.setDetailedInfo("detect service [\""+sChildName+"\"] converted to internal format");
+ }
+ break;
+
+ case E_FRAMELOADER :
+ {
+ aPropSet = Cache.convertFrameLoaderPropsToInternal(aTempSet, nFormat);
+ m_aDebug.setDetailedInfo("frame loader [\""+sChildName+"\"] converted to internal format");
+ }
+ break;
+
+ case E_CONTENTHANDLER :
+ {
+ aPropSet = Cache.convertContentHandlerPropsToInternal(aTempSet, nFormat);
+ m_aDebug.setDetailedInfo("content handler [\""+sChildName+"\"] converted to internal format");
+ }
+ break;
+ }
+ m_aDebug.setDetailedInfo("props = "+aTempSet);
+ rMap.put(sChildName, aPropSet);
+ }
+ }
+ }
+
+ //___________________________________________
+
+ /** create some hml views of the current content of this cache.
+ *
+ * The given directory is used to create different html files
+ * there. Every of them show another aspect of this cache.
+ * E.g.: - all type/filter properties
+ * - relation ships between types/filters/loaders etc.
+ *
+ * @param aDirectory
+ * points to a system directory, which
+ * can be used completely(!) to generate
+ * the results there.
+ *
+ * @param nFormat
+ * specify in which context the cache items should be
+ * interpreted.
+ */
+ public synchronized void toHTML(java.io.File aDirectory,
+ int nFormat ,
+ java.lang.String sEncoding )
+ throws java.lang.Exception
+ {
+ if (nFormat != FORMAT_6Y)
+ throw new java.lang.Exception("HTML views are supported for the new 6.y format only yet.");
+
+ java.lang.StringBuffer sRelationView = new java.lang.StringBuffer(1000);
+ sRelationView.append("<html><header><title>Relation View</title></header><body>");
+ sRelationView.append("<table border=1>");
+ sRelationView.append("<tr><td><b>type</b></td><td><b>detect service</b></td><td><b>preferred filter</b></td><td><b>frame loader</b></td><td><b>content handler</b></td></tr>");
+
+ java.util.Iterator aIt = m_lTypes.keySet().iterator();
+ while (aIt.hasNext())
+ {
+ java.lang.String sType = (java.lang.String)aIt.next();
+ java.util.HashMap aType = (java.util.HashMap)m_lTypes.get(sType);
+
+ sRelationView.append("<tr>");
+ sRelationView.append("<td>"+sType+"</td>");
+
+ java.lang.String sVal = (java.lang.String)aType.get(PROPNAME_DETECTSERVICE);
+ if (sVal == null || sVal.length()<1)
+ sRelationView.append("<td> - </td>");
+ else
+ sRelationView.append("<td>"+sVal+"</td>");
+
+ sVal = (java.lang.String)aType.get(PROPNAME_PREFERREDFILTER);
+ if (sVal == null || sVal.length()<1)
+ sRelationView.append("<td> - </td>");
+ else
+ sRelationView.append("<td>"+sVal+"</td>");
+
+ sVal = (java.lang.String)aType.get(PROPNAME_FRAMELOADER);
+ if (sVal == null || sVal.length()<1)
+ sRelationView.append("<td> - </td>");
+ else
+ sRelationView.append("<td>"+sVal+"</td>");
+
+ sVal = (java.lang.String)aType.get(PROPNAME_CONTENTHANDLER);
+ if (sVal == null || sVal.length()<1)
+ sRelationView.append("<td> - </td>");
+ else
+ sRelationView.append("<td>"+sVal+"</td>");
+
+ sRelationView.append("</tr>");
+ }
+
+ sRelationView.append("</table>");
+ sRelationView.append("</body>");
+
+ FileHelper.writeEncodedBufferToFile(new java.io.File(aDirectory, "relation_view.html"), sEncoding, false, sRelationView);
+
+ java.util.HashMap lFilters2TypeRegistration = new java.util.HashMap();
+ aIt = m_lFilters.keySet().iterator();
+ while (aIt.hasNext())
+ {
+ java.lang.String sFilter = (java.lang.String)aIt.next();
+ java.util.HashMap aFilter = (java.util.HashMap)m_lFilters.get(sFilter);
+ java.lang.String sType = (java.lang.String)aFilter.get(PROPNAME_TYPE);
+
+ java.util.Vector lFilters = (java.util.Vector)lFilters2TypeRegistration.get(sType);
+ if (lFilters == null)
+ lFilters = new java.util.Vector();
+ lFilters.add(sFilter);
+ lFilters2TypeRegistration.put(sType, lFilters);
+ }
+
+ java.lang.StringBuffer sType2FiltersView = new java.lang.StringBuffer(1000);
+ sType2FiltersView.append("<html><header><title>Type2Filters View</title></header><body>");
+ sType2FiltersView.append("<table border=1>");
+ sType2FiltersView.append("<tr><td><b>type</b></td><td><b>filters</b></td></tr>");
+
+ aIt = lFilters2TypeRegistration.keySet().iterator();
+ while (aIt.hasNext())
+ {
+ java.lang.String sType = (java.lang.String)aIt.next();
+ java.util.Vector lFilters = (java.util.Vector)lFilters2TypeRegistration.get(sType);
+
+ sType2FiltersView.append("<tr><td>"+sType+"</td><td>");
+ java.util.Enumeration aEn = lFilters.elements();
+ while(aEn.hasMoreElements())
+ sType2FiltersView.append(aEn.nextElement()+"<br>");
+ sType2FiltersView.append("</td></tr>");
+ }
+
+ sType2FiltersView.append("</table>");
+ sType2FiltersView.append("</body>");
+
+ FileHelper.writeEncodedBufferToFile(new java.io.File(aDirectory, "type2filters_view.html"), sEncoding, false, sType2FiltersView);
+ }
+
+ //___________________________________________
+
+ /** converts all items of this cache to its xml representation
+ * and write it to the given file.
+ *
+ * @param aXML
+ * the target file for output.
+ *
+ * @param nFormat
+ * the requested xml format.
+ * see const values FORMAT_xxx too.
+ *
+ * @param sEncoding
+ * specify the file encoding for the generated xml file.
+ *
+ * @throws [java.lang.Exception]
+ * if something fail during convertion.
+ */
+ public synchronized void toXML(java.io.File aXML ,
+ int nFormat ,
+ java.lang.String sEncoding)
+ throws java.lang.Exception
+ {
+ java.lang.StringBuffer sXML = new java.lang.StringBuffer(500000);
+
+ for (int i=0; i<5; ++i)
+ {
+ // define right sub container
+ java.lang.String sSetName = null;
+ java.util.HashMap rMap = null;
+ int eType = -1;
+
+ switch(i)
+ {
+ case 0 :
+ {
+ sSetName = CFGNODE_TYPES;
+ rMap = m_lTypes;
+ eType = E_TYPE;
+ }
+ break;
+
+ case 1 :
+ {
+ sSetName = CFGNODE_FILTERS;
+ rMap = m_lFilters;
+ eType = E_FILTER;
+ }
+ break;
+
+ case 2 :
+ {
+ sSetName = CFGNODE_DETECTSERVICES;
+ rMap = m_lDetectServices;
+ eType = E_DETECTSERVICE;
+ }
+ break;
+
+ case 3 :
+ {
+ sSetName = CFGNODE_FRAMELOADERS;
+ rMap = m_lFrameLoaders;
+ eType = E_FRAMELOADER;
+ }
+ break;
+
+ case 4 :
+ {
+ sSetName = CFGNODE_CONTENTHANDLERS;
+ rMap = m_lContentHandlers;
+ eType = E_CONTENTHANDLER;
+ }
+ break;
+ }
+
+ // generate set
+ sXML.append("<node oor:name=\""+sSetName+"\" oor:op=\"replace\">\n");
+ java.util.Iterator it = rMap.keySet().iterator();
+ while(it.hasNext())
+ {
+ java.lang.String sItem = (java.lang.String)it.next();
+ sXML.append("<node oor:name=\""+sItem+"\" oor:op=\"replace\">\n");
+ sXML.append(getItemAsXML(eType, sItem, nFormat));
+ sXML.append("</node>\n");
+ }
+ sXML.append("</node>\n");
+ }
+
+ java.io.FileOutputStream aStream = new java.io.FileOutputStream(aXML.getAbsolutePath(), false);
+ java.io.OutputStreamWriter aWriter = new java.io.OutputStreamWriter(aStream, sEncoding);
+ java.lang.String sOut = sXML.toString();
+ aWriter.write(sOut, 0, sOut.length());
+ aWriter.flush();
+ aWriter.close();
+ }
+
+ //___________________________________________
+
+ /** converts a type property set from internal format
+ * to an external one.
+ *
+ * @param aMap
+ * points to the item, which should be converted.
+ *
+ * @param nFormat
+ * specify the requested output format.
+ *
+ * @return [java.util.HashMap]
+ * contains the properties in the requested format.
+ *
+ * @throws [java.lang.Exception
+ * if something fail during convertion.
+ */
+ private static java.util.HashMap convertTypePropsToExternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ java.util.HashMap aResultMap = new java.util.HashMap();
+ // copy Name property ... if it exists!
+ if (aMap.containsKey(PROPNAME_NAME))
+ aResultMap.put(PROPNAME_NAME, aMap.get(PROPNAME_NAME));
+ switch(nFormat)
+ {
+ //-----------------------------------
+ case FORMAT_60 :
+ {
+ // copy UIName property unchanged
+ aResultMap.put(PROPNAME_UINAME, aMap.get(PROPNAME_UINAME));
+
+ // ignore properties "UIOrder", "PreferredFilter", "DetectService"
+ // They are not supported for 6.0 types.
+
+ // pack all other properties to one "Data" string value
+ java.lang.StringBuffer sData = new java.lang.StringBuffer(256);
+
+ sData.append(aMap.get(PROPNAME_PREFERRED));
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_MEDIATYPE));
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_CLIPBOARDFORMAT));
+ sData.append(",");
+
+ java.util.Vector lList = (java.util.Vector)aMap.get(PROPNAME_URLPATTERN);
+ int c = lList.size();
+ int i = 0;
+ for (i=0; i<c; ++i)
+ {
+ sData.append(lList.elementAt(i));
+ if (i<(c-1))
+ sData.append(";");
+ }
+
+ lList = (java.util.Vector)aMap.get(PROPNAME_EXTENSIONS);
+ c = lList.size();
+ for (i=0; i<c; ++i)
+ {
+ sData.append(lList.elementAt(i));
+ if (i<(c-1))
+ sData.append(";");
+ }
+
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_DOCUMENTICONID));
+ sData.append(",");
+
+ aResultMap.put(PROPNAME_DATA, sData.toString());
+ }
+ break;
+
+ //-----------------------------------
+ case FORMAT_6Y :
+ {
+ // copy all supported properties directly
+ aResultMap.put(PROPNAME_PREFERRED , aMap.get(PROPNAME_PREFERRED ));
+ aResultMap.put(PROPNAME_MEDIATYPE , aMap.get(PROPNAME_MEDIATYPE ));
+ aResultMap.put(PROPNAME_URLPATTERN , aMap.get(PROPNAME_URLPATTERN ));
+ aResultMap.put(PROPNAME_EXTENSIONS , aMap.get(PROPNAME_EXTENSIONS ));
+ aResultMap.put(PROPNAME_UINAME , aMap.get(PROPNAME_UINAME ));
+ aResultMap.put(PROPNAME_PREFERREDFILTER, aMap.get(PROPNAME_PREFERREDFILTER));
+ aResultMap.put(PROPNAME_DETECTSERVICE , aMap.get(PROPNAME_DETECTSERVICE ));
+ aResultMap.put(PROPNAME_CLIPBOARDFORMAT, aMap.get(PROPNAME_CLIPBOARDFORMAT));
+ aResultMap.put(PROPNAME_UIORDER , aMap.get(PROPNAME_UIORDER ));
+ /* REMOVED!
+ aResultMap.put(PROPNAME_DOCUMENTICONID , aMap.get(PROPNAME_DOCUMENTICONID ));
+ */
+ }
+ break;
+
+ //-----------------------------------
+ default :
+ throw new java.lang.Exception("unknown format");
+ }
+
+ return aResultMap;
+ }
+
+ //___________________________________________
+
+ /** converts a filter property set from internal format
+ * to an external one.
+ *
+ * @param aMap
+ * points to the item, which should be converted.
+ *
+ * @param nFormat
+ * specify the requested output format.
+ *
+ * @return [java.util.HashMap]
+ * contains the properties in the requested format.
+ *
+ * @throws [java.lang.Exception
+ * if something fail during convertion.
+ */
+ private static java.util.HashMap convertFilterPropsToExternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ java.util.HashMap aResultMap = new java.util.HashMap();
+ // copy Name property ... if it exists!
+ if (aMap.containsKey(PROPNAME_NAME))
+ aResultMap.put(PROPNAME_NAME, aMap.get(PROPNAME_NAME));
+ switch(nFormat)
+ {
+ //-----------------------------------
+ case FORMAT_60 :
+ {
+ // copy UIName property unchanged!
+ aResultMap.put(PROPNAME_UINAME, aMap.get(PROPNAME_UINAME));
+
+ // but pack all other properties
+ java.lang.StringBuffer sData = new java.lang.StringBuffer(256);
+
+ sData.append(aMap.get(PROPNAME_ORDER));
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_TYPE));
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_DOCUMENTSERVICE));
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_FILTERSERVICE));
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_FLAGS));
+ sData.append(",");
+ java.util.Vector lList = (java.util.Vector)aMap.get(PROPNAME_USERDATA);
+ int c = lList.size();
+ int i = 0;
+ for (i=0; i<c; ++i)
+ {
+ sData.append(lList.elementAt(i));
+ if (i<(c-1))
+ sData.append(";");
+ }
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_FILEFORMATVERSION));
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_TEMPLATENAME));
+ sData.append(",");
+ sData.append(aMap.get(PROPNAME_UICOMPONENT));
+ sData.append(",");
+
+ aResultMap.put(PROPNAME_DATA, sData.toString());
+ }
+ break;
+
+ //-----------------------------------
+ case FORMAT_6Y :
+ {
+ // supress "Order" property.
+ // Will be moved to type entries in 6.y version!
+
+ // supress "UIName" property.
+ // Only type entries will be localized in 6.y version!
+ /* TODO make it configurable :-) */
+ aResultMap.put(PROPNAME_UINAME , aMap.get(PROPNAME_UINAME ));
+
+ // copy all supported properties directly
+ aResultMap.put(PROPNAME_TYPE , aMap.get(PROPNAME_TYPE ));
+ aResultMap.put(PROPNAME_DOCUMENTSERVICE , aMap.get(PROPNAME_DOCUMENTSERVICE ));
+ aResultMap.put(PROPNAME_FILTERSERVICE , aMap.get(PROPNAME_FILTERSERVICE ));
+ aResultMap.put(PROPNAME_USERDATA , aMap.get(PROPNAME_USERDATA ));
+ aResultMap.put(PROPNAME_FILEFORMATVERSION, aMap.get(PROPNAME_FILEFORMATVERSION));
+ aResultMap.put(PROPNAME_TEMPLATENAME , aMap.get(PROPNAME_TEMPLATENAME ));
+ aResultMap.put(PROPNAME_UICOMPONENT , aMap.get(PROPNAME_UICOMPONENT ));
+
+ // "Flags" will be converted from internal format [int] to
+ // the 6.y format [string-list]!
+ java.lang.Integer nFlags = (java.lang.Integer)aMap.get(PROPNAME_FLAGS);
+ java.util.Vector lFlags = Cache.convertFilterFlagValues2Names(nFlags);
+ aResultMap.put(PROPNAME_FLAGS, lFlags);
+ }
+ break;
+
+ //-----------------------------------
+ default :
+ throw new java.lang.Exception("unknown format");
+ }
+
+ return aResultMap;
+ }
+
+ //___________________________________________
+
+ /** converts a detect service property set from internal format
+ * to an external one.
+ *
+ * @param aMap
+ * points to the item, which should be converted.
+ *
+ * @param nFormat
+ * specify the requested output format.
+ *
+ * @return [java.util.HashMap]
+ * contains the properties in the requested format.
+ *
+ * @throws [java.lang.Exception
+ * if something fail during convertion.
+ */
+ private static java.util.HashMap convertDetectServicePropsToExternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ java.util.HashMap aResultMap = null;
+
+ switch(nFormat)
+ {
+ //-----------------------------------
+ case FORMAT_60 :
+ {
+ // no changes!
+ aResultMap = aMap;
+ }
+ break;
+
+ //-----------------------------------
+ case FORMAT_6Y :
+ {
+ // remove localized name
+ aResultMap = aMap;
+ aResultMap.remove(PROPNAME_UINAME);
+ }
+ break;
+
+ //-----------------------------------
+ default :
+ throw new java.lang.Exception("unknown format");
+ }
+
+ return aResultMap;
+ }
+
+ private static java.util.HashMap convertFrameLoaderPropsToExternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ java.util.HashMap aResultMap = null;
+
+ switch(nFormat)
+ {
+ //-----------------------------------
+ case FORMAT_60 :
+ {
+ // no changes!
+ aResultMap = aMap;
+ }
+ break;
+
+ //-----------------------------------
+ case FORMAT_6Y :
+ {
+ // remove localized name
+ aResultMap = aMap;
+ aResultMap.remove(PROPNAME_UINAME);
+ }
+ break;
+
+ //-----------------------------------
+ default :
+ throw new java.lang.Exception("unknown format");
+ }
+
+ return aResultMap;
+ }
+
+ private static java.util.HashMap convertContentHandlerPropsToExternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ java.util.HashMap aResultMap = null;
+
+ switch(nFormat)
+ {
+ //-----------------------------------
+ case FORMAT_60 :
+ {
+ // no changes!
+ aResultMap = aMap;
+ }
+ break;
+
+ //-----------------------------------
+ case FORMAT_6Y :
+ {
+ // remove localized name
+ aResultMap = aMap;
+ aResultMap.remove(PROPNAME_UINAME);
+ }
+ break;
+
+ //-----------------------------------
+ default :
+ throw new java.lang.Exception("unknown format");
+ }
+
+ return aResultMap;
+ }
+
+ //___________________________________________
+
+ /** converts a type property set (using an external format) to
+ * our internal cache format.
+ *
+ * Especialy the data format string will be expanded
+ * to its real properties.
+ *
+ * Schema:
+ * aMap["UIName"] => aExpandedMap["UIName"]
+ * aMap["Data" ] => aExpandedMap["Preferred" ], aExpandedMap["MediaType"] etc. ...
+ *
+ * @param aMap
+ * points to the item, which should be converted.
+
+ * @param nFormat
+ * specify the external format.
+ *
+ * @return [java.util.HashMap]
+ * The new map in internal format.
+ */
+ private static java.util.HashMap convertTypePropsToInternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ java.util.HashMap aResultMap = new java.util.HashMap();
+ // copy Name property ... if it exists!
+ if (aMap.containsKey(PROPNAME_NAME))
+ aResultMap.put(PROPNAME_NAME, aMap.get(PROPNAME_NAME));
+ switch(nFormat)
+ {
+ //-----------------------------------
+ case FORMAT_60 :
+ {
+ // copy UIName property unchanged!
+ aResultMap.put(PROPNAME_UINAME, aMap.get(PROPNAME_UINAME));
+
+ // generate new property "UIOrder"
+ // Its the moved property "Order" of filters for versions >= 6.y!
+ aResultMap.put(PROPNAME_UIORDER, new java.lang.Integer(0));
+
+ // generate new property "PreferredFilter"
+ // Its a the moved filter flag "Preferred" for versions >= 6.y!
+ aResultMap.put(PROPNAME_PREFERREDFILTER, new java.lang.String());
+
+ // generate new property "DetectService"
+ // Every type know its detector diretcly from now. No search
+ // will be neccessary any longer.
+ aResultMap.put(PROPNAME_DETECTSERVICE, new java.lang.String());
+
+ // analyze the Data property of the original map
+ // and copy its results (means all expanded properties)
+ // to the result map.
+ java.lang.String sDataVal = (java.lang.String)aMap.get(PROPNAME_DATA);
+ java.util.Vector lTokens = Cache.splitTokenString(sDataVal, ",");
+
+ int t = 0;
+ java.util.Enumeration it = lTokens.elements();
+ while (it.hasMoreElements())
+ {
+ java.lang.String sToken = (java.lang.String)it.nextElement();
+ switch(t)
+ {
+ case 0 :
+ aResultMap.put(PROPNAME_PREFERRED, new java.lang.Boolean(sToken));
+ break;
+ case 1 :
+ aResultMap.put(PROPNAME_MEDIATYPE, sToken);
+ break;
+ case 2 :
+ {
+ /*HACK ersetze %20 mit " " ...*/
+ int ni = sToken.indexOf("%20");
+ if (ni!=-1)
+ {
+ java.lang.String sPatch = sToken.substring(0,ni) + " " + sToken.substring(ni+3);
+ sToken = sPatch;
+ }
+ aResultMap.put(PROPNAME_CLIPBOARDFORMAT, sToken);
+ }
+ break;
+ case 3 :
+ aResultMap.put(PROPNAME_URLPATTERN, Cache.splitTokenString(sToken, ";"));
+ break;
+ case 4 :
+ aResultMap.put(PROPNAME_EXTENSIONS, Cache.splitTokenString(sToken, ";"));
+ break;
+ case 5 :
+ aResultMap.put(PROPNAME_DOCUMENTICONID, new java.lang.Integer(sToken));
+ break;
+ default :
+ throw new java.lang.Exception("unsupported format for data value of a type \""+aMap.get(PROPNAME_NAME)+"\" detected.");
+ }
+ ++t;
+ }
+ }
+ break;
+
+ //-----------------------------------
+ case FORMAT_6Y :
+ {
+ // copy all supported properties directly
+ aResultMap.put(PROPNAME_PREFERRED , aMap.get(PROPNAME_PREFERRED ));
+ aResultMap.put(PROPNAME_MEDIATYPE , aMap.get(PROPNAME_MEDIATYPE ));
+ aResultMap.put(PROPNAME_CLIPBOARDFORMAT, aMap.get(PROPNAME_CLIPBOARDFORMAT));
+ aResultMap.put(PROPNAME_URLPATTERN , aMap.get(PROPNAME_URLPATTERN ));
+ aResultMap.put(PROPNAME_EXTENSIONS , aMap.get(PROPNAME_EXTENSIONS ));
+ aResultMap.put(PROPNAME_DOCUMENTICONID , aMap.get(PROPNAME_DOCUMENTICONID ));
+ aResultMap.put(PROPNAME_UINAME , aMap.get(PROPNAME_UINAME ));
+ aResultMap.put(PROPNAME_UIORDER , aMap.get(PROPNAME_UIORDER ));
+ aResultMap.put(PROPNAME_PREFERREDFILTER, aMap.get(PROPNAME_PREFERREDFILTER));
+ aResultMap.put(PROPNAME_DETECTSERVICE , aMap.get(PROPNAME_DETECTSERVICE ));
+ }
+ break;
+
+ //-----------------------------------
+ default :
+ throw new java.lang.Exception("unknown format");
+ }
+
+ return aResultMap;
+ }
+
+ //___________________________________________
+
+ /** converts a filter property set (using an external format) to
+ * our internal cache format.
+ *
+ * Especialy the data format string will be expanded
+ * to its real properties.
+ *
+ * Schema:
+ * aMap["UIName"] => aExpandedMap["UIName"]
+ * aMap["Data" ] => aExpandedMap["Order" ], aExpandedMap["Flags"] etc. ...
+ *
+ * @param aMap
+ * points to the item, which should be converted.
+ *
+ * @param nFormat
+ * specify the external format.
+ *
+ * @return [java.util.HashMap]
+ * The new map in internal format.
+ */
+ private static java.util.HashMap convertFilterPropsToInternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ java.util.HashMap aResultMap = new java.util.HashMap();
+ // copy Name property ... if it exists!
+ if (aMap.containsKey(PROPNAME_NAME))
+ aResultMap.put(PROPNAME_NAME, aMap.get(PROPNAME_NAME));
+ switch(nFormat)
+ {
+ //-----------------------------------
+ case FORMAT_60 :
+ {
+ // copy UIName property
+ aResultMap.put(PROPNAME_UINAME, aMap.get(PROPNAME_UINAME));
+
+ // analyze the Data property of the original map
+ // and copy its results (means all expanded properties)
+ // to the result map.
+ java.lang.String sDataVal = (java.lang.String)aMap.get(PROPNAME_DATA);
+ java.util.Vector lTokens = Cache.splitTokenString(sDataVal, ",");
+
+ int t = 0;
+ java.util.Enumeration it = lTokens.elements();
+ while (it.hasMoreElements())
+ {
+ java.lang.String sToken = (java.lang.String)it.nextElement();
+ switch(t)
+ {
+ case 0 :
+ aResultMap.put(PROPNAME_ORDER, new java.lang.Integer(sToken));
+ break;
+ case 1 :
+ aResultMap.put(PROPNAME_TYPE, sToken);
+ break;
+ case 2 :
+ aResultMap.put(PROPNAME_DOCUMENTSERVICE, sToken);
+ break;
+ case 3 :
+ aResultMap.put(PROPNAME_FILTERSERVICE, sToken);
+ break;
+ case 4 :
+ aResultMap.put(PROPNAME_FLAGS, new java.lang.Integer(sToken));
+ break;
+ case 5 :
+ aResultMap.put(PROPNAME_USERDATA, Cache.splitTokenString(sToken, ";"));
+ break;
+ case 6 :
+ aResultMap.put(PROPNAME_FILEFORMATVERSION, new java.lang.Integer(sToken));
+ break;
+ case 7 :
+ aResultMap.put(PROPNAME_TEMPLATENAME, sToken);
+ break;
+ case 8 :
+ aResultMap.put(PROPNAME_UICOMPONENT, sToken);
+ break;
+ default :
+ throw new java.lang.Exception("unsupported format for data value of a filter detected.");
+ }
+ ++t;
+ }
+
+ // its an optional property :-)
+ if (!aResultMap.containsKey(PROPNAME_TEMPLATENAME))
+ aResultMap.put(PROPNAME_TEMPLATENAME, new java.lang.String(""));
+
+ // its an optional property :-)
+ if (!aResultMap.containsKey(PROPNAME_UICOMPONENT))
+ aResultMap.put(PROPNAME_UICOMPONENT, new java.lang.String(""));
+ }
+ break;
+
+ //-----------------------------------
+ case FORMAT_6Y :
+ {
+ // "Order" does not exist for 6.y versions! Use default.
+ aResultMap.put(PROPNAME_ORDER, new java.lang.Integer(0));
+
+ // "UIName" property does not exist for 6.y versions! use default.
+ /* TODO make it configurable :-) */
+ aResultMap.put(PROPNAME_UINAME, aMap.get(PROPNAME_UINAME));
+ //aResultMap.put(PROPNAME_UINAME, new java.util.HashMap());
+
+ // "Flags" must be converted from names to its values
+ java.util.Vector lFlags = (java.util.Vector)aMap.get(PROPNAME_FLAGS);
+ java.lang.Integer nFlags = Cache.convertFilterFlagNames2Values(lFlags);
+ aResultMap.put(PROPNAME_FLAGS, nFlags);
+
+ // copy all direct supported properties
+ aResultMap.put(PROPNAME_TYPE , aMap.get(PROPNAME_TYPE ));
+ aResultMap.put(PROPNAME_DOCUMENTSERVICE , aMap.get(PROPNAME_DOCUMENTSERVICE ));
+ aResultMap.put(PROPNAME_FILTERSERVICE , aMap.get(PROPNAME_ORDER ));
+ aResultMap.put(PROPNAME_USERDATA , aMap.get(PROPNAME_USERDATA ));
+ aResultMap.put(PROPNAME_FILEFORMATVERSION, aMap.get(PROPNAME_FILEFORMATVERSION));
+ aResultMap.put(PROPNAME_TEMPLATENAME , aMap.get(PROPNAME_TEMPLATENAME ));
+ aResultMap.put(PROPNAME_UICOMPONENT , aMap.get(PROPNAME_UICOMPONENT ));
+ }
+ break;
+
+ //-----------------------------------
+ default :
+ throw new java.lang.Exception("unknown format");
+ }
+
+ return aResultMap;
+ }
+
+ private static java.util.HashMap convertDetectServicePropsToInternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ /*FIXME*/
+ java.util.HashMap aResultMap = aMap;
+ return aResultMap;
+ }
+
+ private static java.util.HashMap convertFrameLoaderPropsToInternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ /*FIXME*/
+ java.util.HashMap aResultMap = aMap;
+ return aResultMap;
+ }
+
+ private static java.util.HashMap convertContentHandlerPropsToInternal(java.util.HashMap aMap ,
+ int nFormat)
+ throws java.lang.Exception
+ {
+ /*FIXME*/
+ java.util.HashMap aResultMap = aMap;
+ return aResultMap;
+ }
+
+ //___________________________________________
+
+ /** converts filter flag names to its int representation.
+ *
+ * @param lFlags
+ * a list of flag names.
+ *
+ * @return [java.lang.Integer]
+ * an integer field of all set flags.
+ *
+ * @throws [java.lang.Exception]
+ * for unsupported flags or empty flag fields!
+ */
+ private static java.lang.Integer convertFilterFlagNames2Values(java.util.Vector lFlags)
+ throws java.lang.Exception
+ {
+ int nFlags = 0;
+ java.util.Enumeration it = lFlags.elements();
+ while(it.hasMoreElements())
+ {
+ java.lang.String sFlagName = (java.lang.String)it.nextElement();
+
+ if (sFlagName.equals(FLAGNAME_3RDPARTYFILTER))
+ nFlags |= FLAGVAL_3RDPARTYFILTER;
+ else
+ if (sFlagName.equals(FLAGNAME_ALIEN))
+ nFlags |= FLAGVAL_ALIEN;
+ else
+ if (sFlagName.equals(FLAGNAME_ASYNCHRON))
+ nFlags |= FLAGVAL_ASYNCHRON;
+ else
+ if (sFlagName.equals(FLAGNAME_BROWSERPREFERRED))
+ nFlags |= FLAGVAL_BROWSERPREFERRED;
+ else
+ if (sFlagName.equals(FLAGNAME_CONSULTSERVICE))
+ nFlags |= FLAGVAL_CONSULTSERVICE;
+ else
+ if (sFlagName.equals(FLAGNAME_DEFAULT))
+ nFlags |= FLAGVAL_DEFAULT;
+ else
+ if (sFlagName.equals(FLAGNAME_EXPORT))
+ nFlags |= FLAGVAL_EXPORT;
+ else
+ if (sFlagName.equals(FLAGNAME_IMPORT))
+ nFlags |= FLAGVAL_IMPORT;
+ else
+ if (sFlagName.equals(FLAGNAME_INTERNAL))
+ nFlags |= FLAGVAL_INTERNAL;
+ else
+ if (sFlagName.equals(FLAGNAME_NOTINCHOOSER))
+ nFlags |= FLAGVAL_NOTINCHOOSER;
+ else
+ if (sFlagName.equals(FLAGNAME_NOTINFILEDIALOG))
+ nFlags |= FLAGVAL_NOTINFILEDIALOG;
+ else
+ if (sFlagName.equals(FLAGNAME_NOTINSTALLED))
+ nFlags |= FLAGVAL_NOTINSTALLED;
+ else
+ if (sFlagName.equals(FLAGNAME_OWN))
+ nFlags |= FLAGVAL_OWN;
+ else
+ if (sFlagName.equals(FLAGNAME_PACKED))
+ nFlags |= FLAGVAL_PACKED;
+ else
+ if (sFlagName.equals(FLAGNAME_PREFERRED))
+ nFlags |= FLAGVAL_PREFERRED;
+ else
+ if (sFlagName.equals(FLAGNAME_READONLY))
+ nFlags |= FLAGVAL_READONLY;
+ else
+ if (sFlagName.equals(FLAGNAME_SILENTEXPORT))
+ nFlags |= FLAGVAL_SILENTEXPORT;
+ else
+ if (sFlagName.equals(FLAGNAME_TEMPLATE))
+ nFlags |= FLAGVAL_TEMPLATE;
+ else
+ if (sFlagName.equals(FLAGNAME_TEMPLATEPATH))
+ nFlags |= FLAGVAL_TEMPLATEPATH;
+ else
+ if (sFlagName.equals(FLAGNAME_USESOPTIONS))
+ nFlags |= FLAGVAL_USESOPTIONS;
+ else
+ if (sFlagName.equals(FLAGNAME_COMBINED))
+ nFlags |= FLAGVAL_COMBINED;
+ else
+ throw new java.lang.Exception("unsupported filter flag detected: \""+sFlagName+"\"");
+ }
+
+ if (nFlags == 0)
+ throw new java.lang.Exception("no filter flags?");
+
+ return new java.lang.Integer(nFlags);
+ }
+
+ //___________________________________________
+
+ /** converts filter flag values to its string representation.
+ *
+ * @param nFlags
+ * the flag field as int value.
+ *
+ * @return [java.util.Vector]
+ * a list of flag names.
+ *
+ * @throws [java.lang.Exception]
+ * for unsupported flags or empty flag fields!
+ */
+ private static java.util.Vector convertFilterFlagValues2Names(java.lang.Integer nFlags)
+ throws java.lang.Exception
+ {
+ java.util.Vector lFlags = new java.util.Vector();
+ int field = nFlags.intValue();
+
+ if (field == 0)
+ throw new java.lang.Exception("no filter flags?");
+
+ if((field & FLAGVAL_IMPORT) == FLAGVAL_IMPORT)
+ lFlags.add(FLAGNAME_IMPORT);
+
+ if((field & FLAGVAL_EXPORT) == FLAGVAL_EXPORT)
+ lFlags.add(FLAGNAME_EXPORT);
+
+ if((field & FLAGVAL_TEMPLATE) == FLAGVAL_TEMPLATE)
+ lFlags.add(FLAGNAME_TEMPLATE);
+
+ if((field & FLAGVAL_INTERNAL) == FLAGVAL_INTERNAL)
+ lFlags.add(FLAGNAME_INTERNAL);
+
+ if((field & FLAGVAL_TEMPLATEPATH) == FLAGVAL_TEMPLATEPATH)
+ lFlags.add(FLAGNAME_TEMPLATEPATH);
+
+ if((field & FLAGVAL_OWN) == FLAGVAL_OWN)
+ lFlags.add(FLAGNAME_OWN);
+
+ if((field & FLAGVAL_ALIEN) == FLAGVAL_ALIEN)
+ lFlags.add(FLAGNAME_ALIEN);
+
+ if((field & FLAGVAL_USESOPTIONS) == FLAGVAL_USESOPTIONS)
+ lFlags.add(FLAGNAME_USESOPTIONS);
+
+ if((field & FLAGVAL_DEFAULT) == FLAGVAL_DEFAULT)
+ lFlags.add(FLAGNAME_DEFAULT);
+
+ if((field & FLAGVAL_NOTINFILEDIALOG) == FLAGVAL_NOTINFILEDIALOG)
+ lFlags.add(FLAGNAME_NOTINFILEDIALOG);
+
+ if((field & FLAGVAL_NOTINCHOOSER) == FLAGVAL_NOTINCHOOSER)
+ lFlags.add(FLAGNAME_NOTINCHOOSER);
+
+ if((field & FLAGVAL_ASYNCHRON) == FLAGVAL_ASYNCHRON)
+ lFlags.add(FLAGNAME_ASYNCHRON);
+
+ if((field & FLAGVAL_READONLY) == FLAGVAL_READONLY)
+ lFlags.add(FLAGNAME_READONLY);
+
+ if((field & FLAGVAL_NOTINSTALLED) == FLAGVAL_NOTINSTALLED)
+ lFlags.add(FLAGNAME_NOTINSTALLED);
+
+ if((field & FLAGVAL_CONSULTSERVICE) == FLAGVAL_CONSULTSERVICE)
+ lFlags.add(FLAGNAME_CONSULTSERVICE);
+
+ if((field & FLAGVAL_3RDPARTYFILTER) == FLAGVAL_3RDPARTYFILTER)
+ lFlags.add(FLAGNAME_3RDPARTYFILTER);
+
+ if((field & FLAGVAL_PACKED) == FLAGVAL_PACKED)
+ lFlags.add(FLAGNAME_PACKED);
+
+ if((field & FLAGVAL_SILENTEXPORT) == FLAGVAL_SILENTEXPORT)
+ lFlags.add(FLAGNAME_SILENTEXPORT);
+
+ if((field & FLAGVAL_BROWSERPREFERRED) == FLAGVAL_BROWSERPREFERRED)
+ lFlags.add(FLAGNAME_BROWSERPREFERRED);
+
+ if((field & FLAGVAL_PREFERRED) == FLAGVAL_PREFERRED)
+ lFlags.add(FLAGNAME_PREFERRED);
+
+ if((field & FLAGVAL_COMBINED) == FLAGVAL_COMBINED)
+ lFlags.add(FLAGNAME_COMBINED);
+
+ if((field & FLAGVAL_COMBINED) == FLAGVAL_SUPPORTSSELECTION)
+ lFlags.add(FLAGNAME_SUPPORTSSELECTION);
+
+ return lFlags;
+ }
+
+ //___________________________________________
+
+ /** return a reference to one of our member
+ * lists for types/filters etc ...
+ *
+ * @param eItemType
+ * specify, which item map is required.
+ *
+ * @return [java.util.HashMap]
+ * a reference(!) to the right member.
+ *
+ * @throws [java.lang.Exception]
+ * if the specified map does not exist.
+ */
+ private java.util.HashMap getItemMap(int eItemType)
+ throws java.lang.Exception
+ {
+ java.util.HashMap rMap = null;
+ switch(eItemType)
+ {
+ case E_TYPE :
+ rMap = m_lTypes;
+ break;
+
+ case E_FILTER :
+ rMap = m_lFilters;
+ break;
+
+ case E_DETECTSERVICE :
+ rMap = m_lDetectServices;
+ break;
+
+ case E_FRAMELOADER :
+ rMap = m_lFrameLoaders;
+ break;
+
+ case E_CONTENTHANDLER :
+ rMap = m_lContentHandlers;
+ break;
+
+ default:
+ throw new java.lang.Exception("Invalid item map specified.");
+ }
+ return rMap;
+ }
+
+ //___________________________________________
+
+ /** return the count of items inside a sub container
+ * of this cache.
+ *
+ * @param eItemType
+ * specify, which item map is required.
+ *
+ * @throws [java.lang.Exception]
+ * if the specified map does not exist.
+ */
+ public synchronized int getItemCount(int eItemType)
+ throws java.lang.Exception
+ {
+ java.util.HashMap rMap = getItemMap(eItemType);
+ return rMap.size();
+ }
+
+ //___________________________________________
+
+ /** get a list of all item names of the specified
+ * sub container.
+ *
+ * @param eItemType
+ * specify, which item map is required.
+ *
+ * @throws [java.lang.Exception]
+ * if the specified map does not exist.
+ */
+ public synchronized java.util.Vector getItemNames(int eItemType)
+ throws java.lang.Exception
+ {
+ java.util.Vector lNames = new java.util.Vector();
+ java.util.HashMap rMap = getItemMap(eItemType);
+ java.util.Iterator it = rMap.keySet().iterator();
+ while(it.hasNext())
+ lNames.add(it.next());
+ return lNames;
+ }
+
+ //___________________________________________
+
+ /** get a list of all item names of the specified
+ * sub coontainer, where items match to given property set.
+ *
+ * Note: The given property set must exist at all
+ * returned items as minimum and every checked property
+ * value must be equals! Using of reg expressions or
+ * similar mechanism will not be supported here.
+ *
+ * @param eItemType
+ * specify, which item map is required.
+ *
+ * @param aPropSet
+ * the set of properties, which must
+ * exist at the returned item as minimum.
+ *
+ * @throws [java.lang.Exception]
+ * if the specified map does not exist.
+ */
+ public synchronized java.util.Vector getMatchedItemNames(int eItemType,
+ java.util.HashMap aPropSet )
+ throws java.lang.Exception
+ {
+ java.util.Vector lNames = new java.util.Vector();
+ java.util.HashMap rMap = getItemMap(eItemType);
+ java.util.Iterator it = rMap.keySet().iterator();
+ while(it.hasNext())
+ {
+ java.lang.String sItemName = (java.lang.String)it.next();
+ java.util.HashMap rItemProps = (java.util.HashMap)rMap.get(sItemName);
+
+ boolean bMatch = Cache.matchPropSet(rItemProps, aPropSet);
+ if (bMatch)
+ lNames.add(sItemName);
+ else
+ {
+ java.lang.StringBuffer sBuffer = new java.lang.StringBuffer(1000);
+ sBuffer.append("entry ["+eItemType+"] \""+sItemName+"\" does not match.\n");
+ sBuffer.append("\torg items = {"+rItemProps+"}\n");
+ sBuffer.append("\treq items = {"+aPropSet+"}\n");
+
+ m_aDebug.setDetailedInfo(sBuffer.toString());
+ }
+ }
+ return lNames;
+ }
+
+ //___________________________________________
+
+ /** check if two property sets are equals in its
+ * shared properties.
+ *
+ * Note: Only set properties of the match set will be searched
+ * inside the original set. And its values must be equals.
+ * Using of reg expressions or similar mechanism will not
+ * be supported here.
+ *
+ * @param rOrgProps
+ * the original property set, which should be checked.
+ *
+ * @param rMatchProps
+ * contains the properties, which must be searched
+ * inside rOrgProps.
+ *
+ * @return TRUE if all properties of rMatchProps could be located
+ * inside rOrgProps.
+ */
+ private static boolean matchPropSet(java.util.HashMap rOrgProps ,
+ java.util.HashMap rMatchProps)
+ {
+ java.util.Iterator it = rMatchProps.keySet().iterator();
+ while(it.hasNext())
+ {
+ java.lang.String sMatchName = (java.lang.String)it.next();
+ java.lang.Object aMatchValue = rMatchProps.get(sMatchName);
+
+ if (
+ (!rOrgProps.containsKey(sMatchName) ) ||
+ (!rOrgProps.get(sMatchName).equals(aMatchValue))
+ )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ //___________________________________________
+
+ /** return a property set for the queried container item.
+ *
+ * @param eItemType
+ * specify, which item map is required.
+ *
+ * @param sItemName
+ * must be a valid item name of the specified item map.
+ *
+ * @return [java.util.HashMap]
+ * the property set of the queried item.
+ * Always different from null!
+ *
+ * @throws [java.lang.Exception]
+ * if the specified item does not exists or
+ * seems to be invalid in general (means null!).
+ */
+ public synchronized java.util.HashMap getItem(int eItemType,
+ java.lang.String sItemName)
+ throws java.lang.Exception
+ {
+ java.util.HashMap rMap = getItemMap(eItemType);
+ java.util.HashMap rItem = (java.util.HashMap)rMap.get(sItemName);
+ if (rItem == null)
+ throw new java.lang.Exception("Queried item \""+sItemName+"\" does not exist inside this cache.");
+ return rItem;
+ }
+
+ //___________________________________________
+
+ /** return a requested item in XML format.
+ *
+ * @param eItemType
+ * identify the right sub set of this cache
+ * inside which the requested item should exist.
+ * e.g. E_TYPE, E_FILTER, ...
+ *
+ * @param sItemName
+ * the name of the request item
+ *
+ * @param nXMLFormat
+ * means the format of the generated xml source.
+ *
+ * @return [java.lang.String]
+ * a xml formated string, which contains all properties
+ * for this container item.
+ */
+ public synchronized java.lang.String getItemAsXML(int eItemType ,
+ java.lang.String sItemName ,
+ int nXMLFormat)
+ throws java.lang.Exception
+ {
+ // Note: Our internal format must be converted to the target format!
+ java.util.HashMap rItem = getItem(eItemType, sItemName);
+ java.util.HashMap rFormatedItem = null;
+ switch(eItemType)
+ {
+ case E_TYPE :
+ {
+ rFormatedItem = Cache.convertTypePropsToExternal(rItem, nXMLFormat);
+ m_aDebug.setGlobalInfo("type to external \""+sItemName+"\"");
+ }
+ break;
+
+ case E_FILTER :
+ {
+ rFormatedItem = Cache.convertFilterPropsToExternal(rItem, nXMLFormat);
+ m_aDebug.setGlobalInfo("filter to external \""+sItemName+"\"");
+ }
+ break;
+
+ case E_DETECTSERVICE :
+ {
+ rFormatedItem = Cache.convertDetectServicePropsToExternal(rItem, nXMLFormat);
+ m_aDebug.setGlobalInfo("detect service to external \""+sItemName+"\"");
+ }
+ break;
+
+ case E_FRAMELOADER :
+ {
+ rFormatedItem = Cache.convertFrameLoaderPropsToExternal(rItem, nXMLFormat);
+ m_aDebug.setGlobalInfo("frame loader to external \""+sItemName+"\"");
+ }
+ break;
+
+ case E_CONTENTHANDLER :
+ {
+ rFormatedItem = Cache.convertContentHandlerPropsToExternal(rItem, nXMLFormat);
+ m_aDebug.setGlobalInfo("content handler to external \""+sItemName+"\"");
+ }
+ break;
+ }
+
+ java.lang.StringBuffer sXML = new java.lang.StringBuffer(1000);
+ int nPrettyTabs = 1;
+ for (int t=0; t<nPrettyTabs; ++t)
+ sXML.append("\t");
+ sXML.append("<"+XMLHelper.XMLTAG_NODE+" "+XMLHelper.XMLATTRIB_OOR_NAME+"=\""+XMLHelper.encodeHTMLSigns(sItemName)+"\" "+XMLHelper.XMLATTRIB_OOR_OP+"=\""+XMLHelper.XMLATTRIB_OP_REPLACE+"\">\n");
+ sXML.append(XMLHelper.convertPropSetToXML(rFormatedItem, nPrettyTabs+1));
+ for (int t=0; t<nPrettyTabs; ++t)
+ sXML.append("\t");
+ sXML.append("</"+XMLHelper.XMLTAG_NODE+">\n");
+
+ return sXML.toString();
+ }
+
+ //___________________________________________
+
+ /** split the given string (using the specified delimiter)
+ * and return alist of found string tokens.
+ *
+ * Note: Against the normal behaviour of the StringTokenizer class
+ * this method returns empty tokens too.
+ * E.g: "0,,1" will return "0" - "" - "1"
+ *
+ * @param sTokenString
+ * the string value, which should be analyzed.
+ *
+ * @param sDelim
+ * the delimiter, which will be used to differe between tokens.
+ *
+ * @return [java.util.Vector]
+ * a list of string tokens. Can be empty - but not null!
+ */
+ private static java.util.Vector splitTokenString(java.lang.String sTokenString,
+ java.lang.String sDelim )
+ {
+ java.util.Vector lTokens = new java.util.Vector();
+ java.util.StringTokenizer aTokenizer = new java.util.StringTokenizer(sTokenString, sDelim, true);
+ boolean bLastWasDelim = false;
+
+ while (aTokenizer.hasMoreTokens())
+ {
+ java.lang.String sToken = aTokenizer.nextToken();
+ if (sToken.equals(sDelim))
+ {
+ if (bLastWasDelim)
+ {
+ // last token was a delimiter - new one too
+ // => an empty token must be placed between these
+ // two delimiters! Add this empty value to the return list.
+ lTokens.add("");
+ }
+ else
+ {
+ // last token was not a delimiter - new one is such delim
+ // => ignore this delimiter - but save the information, that
+ // it occured
+ bLastWasDelim = true;
+ }
+ }
+ else
+ {
+ // new token is no delim
+ // => Add it to the return list.
+ lTokens.add(sToken);
+ // Dont forget to reset this information - so next loop
+ // will do the right things!
+ bLastWasDelim = false;
+ }
+ }
+
+ return lTokens;
+ }
+
+ //___________________________________________
+
+ /**
+ */
+ public synchronized void analyze()
+ {
+ m_nDoubleRegisteredFilters = 0;
+ m_nTypesForFilters = 0;
+ m_nTypesForDetectServices = 0;
+ m_nTypesForFrameLoaders = 0;
+ m_nTypesForContentHandlers = 0;
+
+ // create table of types and all registered filters for such types
+ // By the way: count all double registrations, where a filter
+ // uses the same type then another filter.
+ m_lFilterToTypeRegistrations = new java.util.HashMap();
+ java.util.Iterator aIt1 = m_lFilters.keySet().iterator();
+ while (aIt1.hasNext())
+ {
+ java.lang.String sFilter = (java.lang.String)aIt1.next();
+ java.util.HashMap aFilter = (java.util.HashMap)m_lFilters.get(sFilter);
+ java.lang.String sType = (java.lang.String)aFilter.get(PROPNAME_TYPE);
+
+ java.util.Vector lFilters = (java.util.Vector)m_lFilterToTypeRegistrations.get(sType);
+ if (lFilters == null)
+ lFilters = new java.util.Vector();
+ else
+ ++m_nDoubleRegisteredFilters;
+ lFilters.add(sFilter);
+ m_lFilterToTypeRegistrations.put(sType, lFilters);
+ }
+
+ // count, how many types are used by filters, frame loaders or content handlers
+ aIt1 = m_lTypes.keySet().iterator();
+ while (aIt1.hasNext())
+ {
+ java.lang.String sType = (java.lang.String)aIt1.next();
+
+ java.util.Iterator aIt2 = m_lFilters.keySet().iterator();
+ while (aIt2.hasNext())
+ {
+ java.lang.String sItem = (java.lang.String)aIt2.next();
+ java.util.HashMap aItem = (java.util.HashMap)m_lFilters.get(sItem);
+ java.lang.String sTypeReg = (java.lang.String)aItem.get(PROPNAME_TYPE);
+
+ if (sTypeReg.equals(sType))
+ {
+ ++m_nTypesForFilters;
+ break;
+ }
+ }
+
+ aIt2 = m_lDetectServices.keySet().iterator();
+ while (aIt2.hasNext())
+ {
+ java.lang.String sItem = (java.lang.String)aIt2.next();
+ java.util.HashMap aItem = (java.util.HashMap)m_lDetectServices.get(sItem);
+ java.util.Vector lTypeReg = (java.util.Vector)aItem.get(PROPNAME_TYPES);
+
+ if (lTypeReg.contains(sType))
+ {
+ ++m_nTypesForDetectServices;
+ break;
+ }
+ }
+
+ aIt2 = m_lFrameLoaders.keySet().iterator();
+ while (aIt2.hasNext())
+ {
+ java.lang.String sItem = (java.lang.String)aIt2.next();
+ java.util.HashMap aItem = (java.util.HashMap)m_lFrameLoaders.get(sItem);
+ java.util.Vector lTypeReg = (java.util.Vector)aItem.get(PROPNAME_TYPES);
+
+ if (lTypeReg.contains(sType))
+ {
+ ++m_nTypesForFrameLoaders;
+ break;
+ }
+ }
+
+ aIt2 = m_lContentHandlers.keySet().iterator();
+ while (aIt2.hasNext())
+ {
+ java.lang.String sItem = (java.lang.String)aIt2.next();
+ java.util.HashMap aItem = (java.util.HashMap)m_lContentHandlers.get(sItem);
+ java.util.Vector lTypeReg = (java.util.Vector)aItem.get(PROPNAME_TYPES);
+
+ if (lTypeReg.contains(sType))
+ {
+ ++m_nTypesForContentHandlers;
+ break;
+ }
+ }
+ }
+ }
+
+ //___________________________________________
+
+ /** validate all cache entries.
+ *
+ * It checks if all made registrations are valid;
+ * try to repair some simple problems;
+ * create missing informations on demand ...
+ *
+ * @param nFormat
+ * specify, which configuration format
+ * must be checked.
+ *
+ * @throws [java.lang.Exception]
+ * if an unrecoverable problem occure.
+ */
+ public synchronized void validate(int nFormat)
+ throws java.lang.Exception
+ {
+ validateTypes(nFormat);
+ validateFilters(nFormat);
+ }
+
+ //___________________________________________
+
+ /** validate all type entries of this cache.
+ *
+ * @param nFormat
+ * specify, which configuration format
+ * must be checked.
+ *
+ * @throws [java.lang.Exception]
+ * if an unrecoverable problem occure.
+ */
+ private void validateTypes(int nFormat)
+ throws java.lang.Exception
+ {
+ java.util.Iterator aIt1 = m_lTypes.keySet().iterator();
+ while(aIt1.hasNext())
+ {
+ java.lang.String sType = (java.lang.String)aIt1.next();
+ java.util.HashMap aType = (java.util.HashMap)m_lTypes.get(sType);
+ if (aType == null)
+ throw new java.lang.Exception("type ["+sType+"] dos not exist realy?!");
+
+ if (
+ (!aType.containsKey(PROPNAME_MEDIATYPE )) ||
+ (!aType.containsKey(PROPNAME_PREFERRED )) ||
+ (!aType.containsKey(PROPNAME_CLIPBOARDFORMAT)) ||
+ (!aType.containsKey(PROPNAME_DOCUMENTICONID )) ||
+ (!aType.containsKey(PROPNAME_URLPATTERN )) ||
+ (!aType.containsKey(PROPNAME_EXTENSIONS )) ||
+ (!aType.containsKey(PROPNAME_UINAME ))
+ )
+ {
+ throw new java.lang.Exception("Type \""+sType+"\" does not contain all neccessary properties for a 6.0/6.Y format.");
+ }
+
+ if (
+ (((java.util.Vector)aType.get(PROPNAME_EXTENSIONS)).isEmpty()) &&
+ (((java.util.Vector)aType.get(PROPNAME_URLPATTERN)).isEmpty())
+ )
+ {
+ throw new java.lang.Exception("Type \""+sType+"\" does not contain any extension nor an url pattern.");
+ }
+
+ if (((java.util.HashMap)aType.get(PROPNAME_UINAME)).isEmpty())
+ throw new java.lang.Exception("Type \""+sType+"\" is not localized.");
+
+ if (nFormat == FORMAT_6Y)
+ {
+ if (
+ (!aType.containsKey(PROPNAME_UIORDER )) ||
+ (!aType.containsKey(PROPNAME_PREFERREDFILTER)) ||
+ (!aType.containsKey(PROPNAME_DETECTSERVICE ))
+ )
+ {
+ throw new java.lang.Exception("Type \""+sType+"\" does not contain all neccessary properties for a 6.Y format.");
+ }
+
+ if (((java.lang.Integer)aType.get(PROPNAME_UIORDER)).intValue() < 0)
+ throw new java.lang.Exception("Type \""+sType+"\" has invalid value for prop UIOrder.");
+
+ if (((java.lang.String)aType.get(PROPNAME_DETECTSERVICE)).length() < 1)
+ m_aDebug.setWarning("Type \""+sType+"\" has no detect service registered.");
+
+ java.lang.String sPreferredReg = (java.lang.String)aType.get(PROPNAME_PREFERREDFILTER);
+ if (
+ (sPreferredReg == null) ||
+ (sPreferredReg.length() < 1 )
+ )
+ {
+ m_aDebug.setWarning("Type \""+sType+"\" has no preferred filter ...");
+ /*FIXME
+ * OK - not every type has a filter registered .. but the
+ * a frame loader MUST(!) exist! Check it.
+ */
+ }
+ else
+ {
+ if (!m_lFilters.containsKey(sPreferredReg))
+ throw new java.lang.Exception("Type \""+sType+"\" has no valid preferred filter registration [\""+sPreferredReg+"\"].");
+ }
+ }
+ }
+ }
+
+ //___________________________________________
+
+ /** validate all filter entries of this cache.
+ *
+ * @param nFormat
+ * specify, which configuration format
+ * must be checked.
+ *
+ * @throws [java.lang.Exception]
+ * if an unrecoverable problem occure.
+ */
+ public synchronized void validateFilters(int nFormat)
+ throws java.lang.Exception
+ {
+ java.util.Iterator aIt1 = m_lFilters.keySet().iterator();
+ while(aIt1.hasNext())
+ {
+ java.lang.String sFilter = (java.lang.String)aIt1.next();
+ java.util.HashMap aFilter = (java.util.HashMap)m_lFilters.get(sFilter);
+ if (aFilter == null)
+ throw new java.lang.Exception("filter ["+sFilter+"] dos not exist realy?!");
+
+ if (
+ (!aFilter.containsKey(PROPNAME_DOCUMENTSERVICE )) ||
+ (!aFilter.containsKey(PROPNAME_FILEFORMATVERSION)) ||
+ (!aFilter.containsKey(PROPNAME_FILTERSERVICE )) ||
+ (!aFilter.containsKey(PROPNAME_FLAGS )) ||
+ (!aFilter.containsKey(PROPNAME_TEMPLATENAME )) ||
+ (!aFilter.containsKey(PROPNAME_TYPE )) ||
+ (!aFilter.containsKey(PROPNAME_UICOMPONENT )) ||
+ (!aFilter.containsKey(PROPNAME_USERDATA ))
+ )
+ {
+ throw new java.lang.Exception("Filter \""+sFilter+"\" does not contain all neccessary properties for a 6.0/6.Y format.");
+ }
+
+ if (((java.lang.Integer)aFilter.get(PROPNAME_FLAGS)).intValue() < 1)
+ throw new java.lang.Exception("Filter \""+sFilter+"\" does not have a valid flag field.");
+
+ if (!m_lTypes.containsKey(aFilter.get(PROPNAME_TYPE)))
+ throw new java.lang.Exception("Filter \""+sFilter+"\" is not registered for a well known type.");
+
+ if (nFormat == FORMAT_60)
+ {
+ if (
+ (!aFilter.containsKey(PROPNAME_ORDER )) ||
+ (!aFilter.containsKey(PROPNAME_UINAME))
+ )
+ {
+ throw new java.lang.Exception("Filter \""+sFilter+"\" does not contain all neccessary properties for a 6.0 format.");
+ }
+
+ if (((java.lang.Integer)aFilter.get(PROPNAME_ORDER)).intValue() < 0)
+ throw new java.lang.Exception("Filter \""+sFilter+"\" does not have a valid Order value.");
+
+ if (((java.util.HashMap)aFilter.get(PROPNAME_UINAME)).isEmpty())
+ throw new java.lang.Exception("Filter \""+sFilter+"\" is not localized.");
+ }
+/*TODO
+ depends from the configuration item "remove_filter_flag_preferred" ...
+
+ if (nFormat == FORMAT_6Y)
+ {
+ int flags = ((java.lang.Integer)aFilter.get(PROPNAME_FLAGS)).intValue();
+ if ((flags & FLAGVAL_PREFERRED) == FLAGVAL_PREFERRED)
+ throw new java.lang.Exception("Filter \""+sFilter+"\" has superflous Preferred flag set. Please remove this flag. ["+flags+"]");
+ }
+*/
+ }
+ }
+
+ /*TODO
+ * - remove graphic filters!
+ * - move detect services to types
+ */
+
+ public synchronized void transform60to6Y(boolean bCreateCombineFilterFlag ,
+ boolean bRemoveFilterFlagBrowserPreferred,
+ boolean bRemoveFilterFlagPreferred ,
+ boolean bRemoveFilterFlag3rdparty ,
+ boolean bRemoveFilterUINames ,
+ boolean bRemoveGraphicFilters ,
+ boolean bSetDefaultDetector )
+ throws java.lang.Exception
+ {
+ // remove some superflous cache entries ...
+ // everything related to "load macros"
+ // Macros should be dispatched instead of loaded!
+ if (m_lTypes.containsKey("macro"))
+ {
+ m_lTypes.remove("macro");
+ m_aDebug.setDetailedInfo("superflous type \"macro\" was removed");
+ }
+ if (m_lFrameLoaders.containsKey("com.sun.star.comp.sfx2.SfxMacroLoader"))
+ {
+ m_lFrameLoaders.remove("com.sun.star.comp.sfx2.SfxMacroLoader");
+ m_aDebug.setDetailedInfo("superflous frame loader \"com.sun.star.comp.sfx2.SfxMacroLoader\" was removed");
+ }
+
+ // step over all filters and check her properties and references
+ java.util.Vector lPreferredFilters = new java.util.Vector();
+ java.util.Vector lNoRealFilters = new java.util.Vector();
+ java.util.Iterator aIt1 = m_lFilters.keySet().iterator();
+ while(aIt1.hasNext())
+ {
+ java.lang.String sFilter = (java.lang.String)aIt1.next();
+ java.util.HashMap aFilter = (java.util.HashMap)m_lFilters.get(sFilter);
+
+ // remove the "graphic helper filters" used by draw and impress
+ // They dont have any valid document service name set and cant be handled
+ // by our generic FrameLoader!
+ // They must be moved to her own configuration ...
+
+ if (
+ (bRemoveGraphicFilters ) &&
+ (((java.lang.String)aFilter.get(PROPNAME_DOCUMENTSERVICE)).length() < 1)
+ )
+ {
+ lNoRealFilters.add(sFilter);
+ continue;
+ }
+
+ java.lang.String sTypeReg = (java.lang.String)aFilter.get(PROPNAME_TYPE);
+ java.util.HashMap aType = (java.util.HashMap)m_lTypes.get(sTypeReg);
+
+ // move UINames of filters to types
+ java.util.HashMap lFilterUINames = (java.util.HashMap)aFilter.get(PROPNAME_UINAME);
+ java.util.HashMap lTypeUINames = (java.util.HashMap)aType.get(PROPNAME_UINAME);
+ java.util.HashMap lPatchUINames = new java.util.HashMap();
+
+ java.util.Iterator pUINames = lTypeUINames.keySet().iterator();
+ while(pUINames.hasNext())
+ {
+ java.lang.String sLocale = (java.lang.String)pUINames.next();
+ java.lang.String sValue = (java.lang.String)lTypeUINames.get(sLocale);
+ lPatchUINames.put(sLocale, sValue);
+ }
+
+ pUINames = lFilterUINames.keySet().iterator();
+ while(pUINames.hasNext())
+ {
+ java.lang.String sLocale = (java.lang.String)pUINames.next();
+ java.lang.String sValue = (java.lang.String)lFilterUINames.get(sLocale);
+ lPatchUINames.put(sFilter+":"+sLocale, sValue);
+ }
+ aType.put(PROPNAME_UINAME, lPatchUINames);
+
+ // set generic filter service wrapper for our own native filters!
+ // By the way: The format types of such filters can be detected by our
+ // generic detector too.
+ if (
+ (bSetDefaultDetector ) &&
+ (((java.lang.String)aFilter.get(PROPNAME_FILTERSERVICE)).length() < 1)
+ )
+ {
+ /*ME_THINKING aFilter.put(PROPNAME_FILTERSERVICE, FILTERSERVICE_NATIVEWARPPER);*/
+ aType.put(PROPNAME_DETECTSERVICE, GENERIC_DETECTSERVICE);
+ }
+
+ // move the preferred filter information to any type
+ // Set the filter name to the type for which the filter is registered.
+ // If this type already have a set PreferredFilter value, check if the current filter
+ // has the preferred flag set. If not ignore it - otherwhise overwrite the
+ // current information at the type. But look for multiple preferred filter relations ...
+ // means: look if more the one filter has set the preferred flag for the same type!
+
+ /* Attention!
+ *
+ * Dont remove the preferred flag from any filter! ... not here.
+ * Otherwhise next loop can't detect ambigous preferred registrations!
+ * Add filter to a temp. list, which can be used later to remove the preferred
+ * flag ...
+ */
+
+ int flags1 = ((java.lang.Integer)aFilter.get(PROPNAME_FLAGS)).intValue();
+ java.lang.String sDocSrv = (java.lang.String)aFilter.get(PROPNAME_DOCUMENTSERVICE);
+ if (sDocSrv.length()>0)// without a doc service its not a real filter - its a graphic filter!
+ {
+ boolean preferred1 = ((flags1 & FLAGVAL_PREFERRED) == FLAGVAL_PREFERRED);
+ if (preferred1)
+ lPreferredFilters.add(aFilter);
+
+ java.lang.String sAlreadyRegisteredFilter = (java.lang.String)aType.get(PROPNAME_PREFERREDFILTER);
+ // no registration => set this filter as "any possible one"!
+ if (sAlreadyRegisteredFilter.length() < 1)
+ aType.put(PROPNAME_PREFERREDFILTER, sFilter);
+ else
+ {
+ java.util.HashMap aAlreadyRegisteredFilter = (java.util.HashMap)m_lFilters.get(sAlreadyRegisteredFilter);
+ int flags2 = ((java.lang.Integer)aAlreadyRegisteredFilter.get(PROPNAME_FLAGS)).intValue();
+ boolean preferred2 = ((flags2 & FLAGVAL_PREFERRED) == FLAGVAL_PREFERRED);
+
+ // two preferred filters for the same type! => error
+ if (preferred1 && preferred2)
+ {
+ java.lang.StringBuffer sMsg = new java.lang.StringBuffer(256);
+ sMsg.append("More the one preferred filter detected for the same type.\n");
+ sMsg.append("\ttype = \""+sTypeReg+"\"\n");
+ sMsg.append("\tfilter[1] = \""+sAlreadyRegisteredFilter+"\"\n");
+ sMsg.append("\tfilter[2] = \""+sFilter+"\"\n");
+ throw new java.lang.Exception(sMsg.toString());
+ }
+ else
+ // overwrite the "any possible" filter with a real preferred one
+ if (preferred1 && !preferred2)
+ aType.put(PROPNAME_PREFERREDFILTER, sFilter);
+ }
+ }
+
+ // create the new combined filter flag if required
+ if (bCreateCombineFilterFlag)
+ {
+ if (
+ ((flags1 & FLAGVAL_IMPORT) == FLAGVAL_IMPORT) &&
+ ((flags1 & FLAGVAL_EXPORT) == FLAGVAL_EXPORT)
+ )
+ {
+ flags1 |= FLAGVAL_COMBINED;
+ flags1 &= ~FLAGVAL_IMPORT ;
+ flags1 &= ~FLAGVAL_EXPORT ;
+ aFilter.put(PROPNAME_FLAGS, new java.lang.Integer(flags1));
+ }
+ }
+
+ // remove some obsolete filter flags
+ if (bRemoveFilterFlagBrowserPreferred)
+ {
+ flags1 &= ~FLAGVAL_BROWSERPREFERRED;
+ aFilter.put(PROPNAME_FLAGS, new java.lang.Integer(flags1));
+ }
+
+ if (bRemoveFilterFlag3rdparty)
+ {
+ flags1 &= ~FLAGVAL_3RDPARTYFILTER;
+ aFilter.put(PROPNAME_FLAGS, new java.lang.Integer(flags1));
+ }
+
+ // if its a filter with an UI order ...
+ // move this information to the registered type.
+ // Note: Because more then one filter can be registered for the same type.
+ // Handle it as an error ... till we find a better transformation!
+ java.lang.Integer nOrder = (java.lang.Integer)aFilter.get(PROPNAME_ORDER);
+ java.lang.Integer nUIOrder = (java.lang.Integer)aType.get(PROPNAME_UIORDER);
+ int order = nOrder.intValue();
+ int uiorder = nUIOrder.intValue();
+
+ if (order > 0)
+ {
+ if (
+ (uiorder < 1 ) ||
+ (uiorder > order)
+ )
+ {
+ aType.put(PROPNAME_UIORDER, nOrder);
+ m_aDebug.setDetailedInfo("moved order value "+nOrder+" from filter \""+sFilter+"\" to type \""+sTypeReg+"\"");
+ }
+ else
+ m_aDebug.setDetailedInfo("ignore order value [order="+nOrder+",uiorder="+nUIOrder+"] for filter \""+sFilter+"\" and type \""+sTypeReg+"\"");
+ }
+ }
+
+ // NOW ... remove the preferred flags from every filter, which it has set.
+ java.util.Enumeration aIt2 = null;
+ if (bRemoveFilterFlagPreferred)
+ {
+ aIt2 = lPreferredFilters.elements();
+ while (aIt2.hasMoreElements())
+ {
+ java.util.HashMap aFilter = (java.util.HashMap)aIt2.nextElement();
+ int flags = ((java.lang.Integer)aFilter.get(PROPNAME_FLAGS)).intValue();
+ flags &= ~FLAGVAL_PREFERRED;
+ aFilter.put(PROPNAME_FLAGS, new java.lang.Integer(flags));
+ }
+ }
+
+ // NOW ... remove all "no real filters" like the graphich helper filters of
+ // draw and impress!
+ aIt2 = lNoRealFilters.elements();
+ while (aIt2.hasMoreElements())
+ m_lFilters.remove(aIt2.nextElement());
+
+ // step over all detect services and move this information directly to
+ // the corresponding types
+ // Overwrite possibel default registrations with a real existing one!
+ aIt1 = m_lDetectServices.keySet().iterator();
+ while(aIt1.hasNext())
+ {
+ java.lang.String sDetector = (java.lang.String)aIt1.next();
+ java.util.HashMap aDetector = (java.util.HashMap)m_lDetectServices.get(sDetector);
+ java.util.Vector lTypeReg = (java.util.Vector)aDetector.get(PROPNAME_TYPES);
+ aIt2 = lTypeReg.elements();
+ while(aIt2.hasMoreElements())
+ {
+ java.lang.String sTypeReg = (java.lang.String)aIt2.nextElement();
+ java.util.HashMap aType = (java.util.HashMap)m_lTypes.get(sTypeReg);
+
+ if (aType == null)
+ {
+ m_aDebug.setWarning("Detector \""+sDetector+"\" seem to be registered for unknown type \""+sTypeReg+"\"");
+ continue;
+ }
+
+ java.lang.Object aAlreadyRegisteredDetector = aType.get(PROPNAME_DETECTSERVICE);
+ if (aAlreadyRegisteredDetector != null && ((java.lang.String)aAlreadyRegisteredDetector).length() > 0)
+ {
+ java.lang.StringBuffer sMsg = new java.lang.StringBuffer(256);
+ sMsg.append("type \""+sTypeReg+"\" has ambigous registrations of a detect service\n");
+ sMsg.append("\tdetect service[1] = \""+(java.lang.String)aAlreadyRegisteredDetector+"\"\n");
+ sMsg.append("\tdetect service[2] = \""+sDetector+"\"\n");
+ m_aDebug.setWarning(sMsg.toString());
+ }
+ aType.put(PROPNAME_DETECTSERVICE, sDetector);
+ m_aDebug.setGlobalInfo("move detector \""+sDetector+"\" to type \""+sTypeReg+"\"");
+ }
+ }
+
+ // because all detect service was registered as type properties directly ...
+ // remove all detect service objects of this cache!
+ m_lDetectServices.clear();
+
+ // step over all frame loader and move this information directly to
+ // the corresponding types
+ // Overwrite possibel default registrations with a real existing one!
+ aIt1 = m_lFrameLoaders.keySet().iterator();
+ while(aIt1.hasNext())
+ {
+ java.lang.String sLoader = (java.lang.String)aIt1.next();
+ java.util.HashMap aLoader = (java.util.HashMap)m_lFrameLoaders.get(sLoader);
+ java.util.Vector lTypeReg = (java.util.Vector)aLoader.get(PROPNAME_TYPES);
+ aIt2 = lTypeReg.elements();
+ while(aIt2.hasMoreElements())
+ {
+ java.lang.String sTypeReg = (java.lang.String)aIt2.nextElement();
+ java.util.HashMap aType = (java.util.HashMap)m_lTypes.get(sTypeReg);
+ java.lang.String sAlreadyRegisteredLoader = (java.lang.String)aType.get(PROPNAME_FRAMELOADER);
+ if (sAlreadyRegisteredLoader != null && sAlreadyRegisteredLoader.length() > 0)
+ {
+ java.lang.StringBuffer sMsg = new java.lang.StringBuffer(256);
+ sMsg.append("type \""+sTypeReg+"\" has ambigous registrations of a frame loader\n");
+ sMsg.append("\tframe loader[1] = \""+sAlreadyRegisteredLoader+"\"\n");
+ sMsg.append("\tframe loader[2] = \""+sLoader+"\"\n");
+ m_aDebug.setWarning(sMsg.toString());
+ }
+ aType.put(PROPNAME_FRAMELOADER, sLoader);
+ System.out.println("move loader \""+sLoader+"\" to type \""+sTypeReg+"\"");
+ }
+ }
+
+ m_lFrameLoaders.clear();
+
+ // step over all content handler and move this information directly to
+ // the corresponding types
+ // Overwrite possibel default registrations with a real existing one!
+ aIt1 = m_lContentHandlers.keySet().iterator();
+ while(aIt1.hasNext())
+ {
+ java.lang.String sHandler = (java.lang.String)aIt1.next();
+ java.util.HashMap aHandler = (java.util.HashMap)m_lContentHandlers.get(sHandler);
+ java.util.Vector lTypeReg = (java.util.Vector)aHandler.get(PROPNAME_TYPES);
+ aIt2 = lTypeReg.elements();
+ while(aIt2.hasMoreElements())
+ {
+ java.lang.String sTypeReg = (java.lang.String)aIt2.nextElement();
+ java.util.HashMap aType = (java.util.HashMap)m_lTypes.get(sTypeReg);
+ java.lang.String sAlreadyRegisteredHandler = (java.lang.String)aType.get(PROPNAME_CONTENTHANDLER);
+ if (sAlreadyRegisteredHandler != null && sAlreadyRegisteredHandler.length() > 0)
+ {
+ java.lang.StringBuffer sMsg = new java.lang.StringBuffer(256);
+ sMsg.append("type \""+sTypeReg+"\" has ambigous registrations of a content handler\n");
+ sMsg.append("\tcontent handler[1] = \""+sAlreadyRegisteredHandler+"\"\n");
+ sMsg.append("\tcontent handler[2] = \""+sHandler+"\"\n");
+ m_aDebug.setWarning(sMsg.toString());
+ }
+ aType.put(PROPNAME_CONTENTHANDLER, sHandler);
+ System.out.println("move handler \""+sHandler+"\" to type \""+sTypeReg+"\"");
+ }
+ }
+
+ m_lContentHandlers.clear();
+
+/*
+ int c = m_lTypes.size();
+ java.lang.String[] lT1 = new java.lang.String[c];
+ java.lang.String[] lT2 = new java.lang.String[c];
+ long nUPS = 0;
+
+ int i = 0;
+ aIt1 = m_lTypes.keySet().iterator();
+ while(aIt1.hasNext())
+ {
+ lT1[i] = (java.lang.String)aIt1.next();
+ lT2[i] = lT1[i];
+ ++i;
+ }
+
+ for (int i1=0; i1<c; ++i1)
+ {
+ java.lang.String sT1 = lT1[i1];
+ java.util.HashMap aT1 = (java.util.HashMap)m_lTypes.get(sT1);
+
+ for (int i2=i1; i2<c; ++i2)
+ {
+ java.lang.String sT2 = lT1[i2];
+ java.util.HashMap aT2 = (java.util.HashMap)m_lTypes.get(sT2);
+
+ if (!sT1.equals(sT2))
+ {
+ if (
+ aT1.get(PROPNAME_MEDIATYPE).equals(aT2.get(PROPNAME_MEDIATYPE)) &&
+ aT1.get(PROPNAME_CLIPBOARDFORMAT).equals(aT2.get(PROPNAME_CLIPBOARDFORMAT)) &&
+ aT1.get(PROPNAME_URLPATTERN).equals(aT2.get(PROPNAME_URLPATTERN)) &&
+ aT1.get(PROPNAME_EXTENSIONS).equals(aT2.get(PROPNAME_EXTENSIONS))
+ )
+ {
+ System.err.println("UUPPSS----------------------------------------------------------------------------");
+ System.err.println("[1]\""+sT1+"\" equals [2]\""+sT2+"\"");
+ System.err.println("\tprops 1: "+aT1);
+ System.err.println("\tprops 2: "+aT2);
+ System.err.println("----------------------------------------------------------------------------------\n");
+ ++nUPS;
+// throw new java.lang.Exception("UUPPS :-)");
+ }
+ }
+ }
+ }
+ System.err.println("count of UPS = "+nUPS);
+*/
+ }
+}
diff --git a/l10ntools/source/filter/utils/ConfigHelper.java b/l10ntools/source/filter/utils/ConfigHelper.java
new file mode 100644
index 000000000000..78cc71cf65b2
--- /dev/null
+++ b/l10ntools/source/filter/utils/ConfigHelper.java
@@ -0,0 +1,303 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ConfigHelper.java,v $
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ **********************************************************************_*/
+
+package com.sun.star.filter.config.tools.utils;
+
+//_______________________________________________
+// imports
+
+import java.lang.*;
+import java.util.*;
+import java.io.*;
+
+//_______________________________________________
+// definition
+
+/** can be used to analyze command line parameters
+ * and merge it together with might existing config
+ * files. That provides the possibility to overwrite
+ * config values via command line parameter.
+ *
+ *
+ */
+public class ConfigHelper extends java.util.Properties
+{
+ //___________________________________________
+ // member
+
+ /** indicates an empty command line. */
+ private boolean m_bEmpty = true;
+
+ //___________________________________________
+ // ctor
+
+ //-------------------------------------------
+ /** initialize a new helper with the list of
+ * command line parameters and bind this new instance
+ * to a property file on disk.
+ *
+ * @param sPropFile
+ * name of the property file.
+ * If its set to null or an empty value
+ * it will be ignored.
+ *
+ * @param lCommandLineArgs
+ * the list of original command line arguments.
+ *
+ * @throws [Exception]
+ * in case the command line contains an unknown
+ * schema for specifiying parameters or the
+ * specified property file does not exists
+ * or seem to be corrupted.
+ */
+ public ConfigHelper(java.lang.String sPropFile ,
+ java.lang.String[] lCommandLineArgs)
+ throws java.lang.Exception
+ {
+ // first load prop file, so its values can be overwritten
+ // by command line args later
+ // Do it only, if a valid file name was given.
+ // But in case this file name is wrong, throw an exception.
+ // So the outside code can react!
+ if (
+ (sPropFile != null) &&
+ (sPropFile.length() > 0 )
+ )
+ {
+ java.lang.ClassLoader aLoader = getClass().getClassLoader();
+ java.io.InputStream aStream = aLoader.getResourceAsStream(sPropFile);
+ if (aStream == null)
+ aStream = new java.io.FileInputStream(sPropFile);
+ load(aStream);
+ }
+
+ int count = 0;
+ if (lCommandLineArgs != null)
+ count = lCommandLineArgs.length;
+ m_bEmpty = (count < 1);
+
+ for (int arg=0; arg<count; ++arg)
+ {
+ // is it a named-value argument?
+ // Note: We ignores double "=" signs! => search from left to right
+ int len = lCommandLineArgs[arg].length();
+ int pos = lCommandLineArgs[arg].indexOf('=');
+ if (pos != -1)
+ {
+ java.lang.String sArg = lCommandLineArgs[arg].substring(0,pos);
+ java.lang.String sValue = lCommandLineArgs[arg].substring(pos+1);
+ setProperty(sArg, sValue);
+ continue;
+ }
+
+ // is it a boolean argument?
+ // Note: Because "--" and "-" will be interpreted as the same
+ // we search from right to left!
+ pos = lCommandLineArgs[arg].lastIndexOf('-');
+ if (pos == -1)
+ pos = lCommandLineArgs[arg].lastIndexOf('/');
+ if (pos != -1)
+ {
+ java.lang.String sArg = lCommandLineArgs[arg].substring(pos+1);
+ setProperty(sArg, java.lang.String.valueOf(true));
+ continue;
+ }
+
+ // There is an unknown format used by this argument ...
+ throw new MalformedCommandLineException("Invalid command line detected. The argument \""+lCommandLineArgs[arg]+"\" use an unsupported format.");
+ }
+ }
+
+ //-------------------------------------------
+ /** indicates if the given command line includes
+ * a help request.
+ *
+ * @return True if there was an explicit help request.
+ */
+ public synchronized boolean isHelp()
+ {
+ return (
+ (containsKey("help")) ||
+ (containsKey("?") ) ||
+ (containsKey("h") )
+ );
+ }
+
+ //-------------------------------------------
+ /** indicates if the gioven command line was empty.
+ *
+ * @return True if there was an empty command line.
+ */
+ public synchronized boolean isEmpty()
+ {
+ return m_bEmpty;
+ }
+
+ //-------------------------------------------
+ /** returns the value of sProp as boolean value.
+ *
+ * @param sProp
+ * the name of the parameter.
+ *
+ * @return The boolean value of the requested property.
+ *
+ * @throw [NoSuchElementException]
+ * if the requested property does not exists.
+ */
+ public synchronized boolean getBoolean(java.lang.String sProp)
+ throws java.util.NoSuchElementException
+ {
+ java.lang.String sValue = getProperty(sProp);
+ if (sValue == null)
+ throw new java.util.NoSuchElementException("The requested config value \""+sProp+"\" does not exists!");
+ return new java.lang.Boolean(sValue).booleanValue();
+ }
+
+ public synchronized boolean getBoolean(java.lang.String sProp ,
+ boolean bDefault)
+ {
+ java.lang.String sDefault = java.lang.String.valueOf(bDefault);
+ java.lang.String sValue = getProperty(sProp, sDefault);
+ return new java.lang.Boolean(sValue).booleanValue();
+ }
+
+ //-------------------------------------------
+ /** returns the value of sProp as int value.
+ *
+ * @param sProp
+ * the name of the parameter.
+ *
+ * @return The int value of the requested property.
+ *
+ * @throw [NoSuchElementException]
+ * if the requested property does not exists.
+ */
+ public synchronized int getInt(java.lang.String sProp)
+ throws java.util.NoSuchElementException
+ {
+ java.lang.String sValue = getProperty(sProp);
+ if (sValue == null)
+ throw new java.util.NoSuchElementException("The requested config value \""+sProp+"\" does not exists!");
+ return new java.lang.Integer(sValue).intValue();
+ }
+
+ public synchronized int getInt(java.lang.String sProp ,
+ int nDefault)
+ {
+ java.lang.String sDefault = java.lang.String.valueOf(nDefault);
+ java.lang.String sValue = getProperty(sProp, sDefault);
+ return new java.lang.Integer(sValue).intValue();
+ }
+
+ //-------------------------------------------
+ /** returns the value of sProp as string value.
+ *
+ * @param sProp
+ * the name of the parameter.
+ *
+ * @return The string value of the requested property.
+ *
+ * @throw [NoSuchElementException]
+ * if the requested property does not exists.
+ */
+ public synchronized java.lang.String getString(java.lang.String sProp)
+ throws java.util.NoSuchElementException
+ {
+ java.lang.String sValue = getProperty(sProp);
+ if (sValue == null)
+ throw new java.util.NoSuchElementException("The requested config value \""+sProp+"\" does not exists!");
+ return sValue;
+ }
+
+ //-------------------------------------------
+ /** returns the value of sProp as string list value!
+ *
+ * @descr The delimiter must be well known and
+ * it must be clear if trailing/leading
+ * whitespaces must be ignored or not.
+ *
+ * @param sProp
+ * the name of the parameter.
+ *
+ * @param sDelim
+ * the delimiter, which must be used to split
+ * the config string value into an array.
+ *
+ * @param bTrim
+ * if its set to true, trailing and leading whitespace
+ * characters will be ommited.
+ *
+ * @param bDecode
+ * if its set to TRUE all liste items will be
+ * interpreted as "<xxx>" and converted to <xxx>!
+ *
+ * @return The string list value of the requested property.
+ *
+ * @throw [NoSuchElementException]
+ * if the requested property does not exists.
+ */
+ public synchronized java.util.Vector getStringList(java.lang.String sProp ,
+ java.lang.String sDelimiter,
+ boolean bTrim ,
+ boolean bDecode )
+ throws java.util.NoSuchElementException
+ {
+ java.lang.String sValue = getProperty(sProp);
+ if (sValue == null)
+ throw new java.util.NoSuchElementException("The requested config value \""+sProp+"\" does not exists!");
+
+ java.util.Vector lValue = new java.util.Vector();
+ try
+ {
+ java.util.StringTokenizer lTokens = new java.util.StringTokenizer(sValue, sDelimiter);
+ while(lTokens.hasMoreTokens())
+ {
+ java.lang.String sToken = lTokens.nextToken();
+ // remove trailing/leading whitespaces
+ if (bTrim)
+ sToken = sToken.trim();
+ // remove ""
+ if (
+ (bDecode ) &&
+ (sToken.indexOf("\"") == 0 ) &&
+ (sToken.lastIndexOf("\"") == sToken.length()-1)
+ )
+ {
+ sToken = sToken.substring(1, sToken.length()-1);
+ }
+ lValue.add(sToken);
+ }
+ }
+ catch(java.lang.Throwable ex)
+ { lValue.clear(); }
+
+ return lValue;
+ }
+}
diff --git a/l10ntools/source/filter/utils/FileHelper.java b/l10ntools/source/filter/utils/FileHelper.java
new file mode 100644
index 000000000000..71f51cf36bf6
--- /dev/null
+++ b/l10ntools/source/filter/utils/FileHelper.java
@@ -0,0 +1,766 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FileHelper.java,v $
+ * $Revision: 1.13 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package com.sun.star.filter.config.tools.utils;
+
+// __________ Imports __________
+
+import java.io.*;
+import java.lang.*;
+import java.net.*;
+import java.util.*;
+
+// __________ Implementation __________
+
+/**
+ * It collects some static helper functons to handle file system specific problems.
+ * Sometimes it's neccessary to convert URL from/to system pathes;
+ * or from string notation to structural versions (e.g. com.sun.star.util.URL).
+ * And sometimes java had another notation then the office it has.
+ * Further it provides functionality to work easiear with the java.io.File class of java.
+ *
+ *
+ */
+public class FileHelper
+{
+ // ____________________
+
+ /**
+ * Because the office need URLs for loading/saving documents
+ * we must convert used system pathes.
+ * And java use another notation for file URLs ... correct it.
+ *
+ * @param aSystemPath
+ * represent the file in system notation
+ *
+ * @return [String]
+ * a file url which represent the given system path
+ */
+ public static java.lang.String getFileURLFromSystemPath(java.io.File aSystemPath)
+ {
+ System.out.println("TODO: must be adapted to java 1.3 :-(");
+ System.exit(-1);
+/*TODO_JAVA
+ try
+ {
+ sFileURL = aSystemPath.toURI().toURL().toString();
+ }
+ catch( MalformedURLException exWrong )
+ {
+ sFileURL = null;
+ }
+*/
+ java.lang.String sFileURL = null;
+
+ // problem of java: file URL's are coded with 1 slash instead of 2 or 3 ones!
+ // => correct this problem first, otherwise office can't use these URL's
+ if(
+ (sFileURL != null ) &&
+ (sFileURL.startsWith("file:/") == true ) &&
+ (sFileURL.startsWith("file://") == false)
+ )
+ {
+ java.lang.StringBuffer sWorkBuffer = new java.lang.StringBuffer(sFileURL);
+ sWorkBuffer.insert(6,"//");
+ sFileURL = sWorkBuffer.toString();
+ }
+
+ return sFileURL;
+ }
+
+ // ____________________
+
+ /**
+ * The same as getFileURLFromSystemPath() before but uses string parameter instead
+ * of a java.io.File type. It exist to supress converting of neccessary parameters in the
+ * outside code. But of course getFileURLFromSystemPath(File) will be a little bit faster
+ * then this method ...
+ *
+ * @param sSystemPath
+ * represent the file in system notation
+ *
+ * @return [String]
+ * a file url which represent the given system path
+ */
+ public static java.lang.String getFileURLFromSystemPath(java.lang.String sSystemPath)
+ {
+ return getFileURLFromSystemPath(new java.io.File(sSystemPath));
+ }
+
+ // ____________________
+
+ /**
+ * Does the same as getFileURLFromSystemPath() before ... but uses
+ * the given protocol string (e.g."http://") insted of "file:///".
+ *
+ * @param aSystemPath
+ * represent the file in system notation
+ *
+ * @param aBasePath
+ * define the base path of the aSystemPath value,
+ * which must be replaced with the value of "sServerPath".
+ *
+ * @param sServerURL
+ * Will be used to replace sBasePath.
+ *
+ * @example
+ * System Path = "d:\test\file.txt"
+ * Base Path = "d:\test"
+ * Server Path = "http://alaska:8000"
+ * => "http://alaska:8000/file.txt"
+ *
+ * @return [String]
+ * an url which represent the given system path
+ * and uses the given protocol
+ */
+ public static java.lang.String getURLWithProtocolFromSystemPath(java.io.File aSystemPath,
+ java.io.File aBasePath ,
+ java.lang.String sServerURL )
+ {
+ System.out.println("TODO: must be adapted to java 1.3 :-(");
+ System.exit(-1);
+
+ java.lang.String sFileURL = FileHelper.getFileURLFromSystemPath(aSystemPath);
+ java.lang.String sBaseURL = FileHelper.getFileURLFromSystemPath(aBasePath );
+
+ // cut last '/'!
+ if (sBaseURL.lastIndexOf('/')==(sBaseURL.length()-1))
+ sBaseURL = sBaseURL.substring(0,sBaseURL.length()-1);
+
+ // cut last '/'!
+ if (sServerURL.lastIndexOf('/')==(sServerURL.length()-1))
+ sServerURL = sServerURL.substring(0,sServerURL.length()-1);
+
+//TODO_JAVA java.lang.String sURL = sFileURL.replaceFirst(sBaseURL,sServerURL);
+ java.lang.String sURL = null;
+ return sURL;
+ }
+
+ // ____________________
+
+ /**
+ * The same as getURLWithProtocolFromSystemPath() before but uses string parameter instead
+ * of a java.io.File types. It exist to supress converting of neccessary parameters in the
+ * outside code. But of course getURLWithProtocolFromSystemPath(File,File,String) will be
+ * a little bit faster then this method ...
+ *
+ * @param sSystemPath
+ * represent the file in system notation
+ *
+ * @param sBasePath
+ * define the base path of the aSystemPath value,
+ * which must be replaced with the value of "sServerPath".
+ *
+ * @param sServerPath
+ * Will be used to replace sBasePath.
+ *
+ * @example
+ * System Path = "d:\test\file.txt"
+ * Base Path = "d:\test"
+ * Server Path = "http://alaska:8000"
+ * => "http://alaska:8000/file.txt"
+ *
+ * @return [String]
+ * an url which represent the given system path
+ * and uses the given protocol
+ */
+ public static java.lang.String getURLWithProtocolFromSystemPath(java.lang.String sSystemPath,
+ java.lang.String sBasePath ,
+ java.lang.String sServerPath)
+ {
+ return getURLWithProtocolFromSystemPath(new java.io.File(sSystemPath), new java.io.File(sBasePath), sServerPath);
+ }
+
+ //_________________________________
+
+ /**
+ * Return a list of all available files of a directory.
+ * We filter sub directories. All other files
+ * are returned. So they can be used for further purposes.
+ * One parameter define the start directory,
+ * another one enable/disable recursive search into sub directories.
+ *
+ * @param aRoot
+ * the start directory, which should be analyzed.
+ *
+ * @param bRecursive
+ * enable/disable search in sub directories.
+ *
+ * @return [Vector]
+ * a filtered list of java java.io.File objects of all available files
+ * of the start dir (and may of its sub directories).
+ */
+ public static java.util.Vector getSystemFilesFromDir(java.io.File aRoot ,
+ boolean bRecursive)
+ {
+ java.io.File[] lAllFiles = aRoot.listFiles();
+ if (lAllFiles == null)
+ return null;
+
+ int c = lAllFiles.length;
+ java.util.Vector lFilteredFiles = new java.util.Vector(c);
+ for (int i=0; i<c; ++i)
+ {
+ // simple files!
+ if (lAllFiles[i].isFile())
+ lFilteredFiles.add(lAllFiles[i]);
+ else
+ // recursion?
+ if (bRecursive && lAllFiles[i].isDirectory())
+ {
+ java.util.Vector lSubFiles = FileHelper.getSystemFilesFromDir(lAllFiles[i],bRecursive);
+ if (lSubFiles != null)
+ {
+ java.util.Enumeration aSnapshot = lSubFiles.elements();
+ while (aSnapshot.hasMoreElements())
+ lFilteredFiles.add(aSnapshot.nextElement());
+ }
+ }
+ }
+
+ return lFilteredFiles;
+ }
+
+ //_________________________________
+ /** it converts the given name (e.g. an internal type name) to
+ * an usable system file name.
+ *
+ * Do so some special characters (e.g. "/") must be replaced with other ones.
+ *
+ * @param sName
+ * the name, which should be analyzed and converted.
+ *
+ * @return A valid system file name, which should be similar to the
+ * given name, but does not contain special characters any longer.
+ */
+ public static java.lang.String convertName2FileName(String sName)
+ {
+ int i = 0;
+ int nLength = sName.length();
+ char[] lBuffer = sName.toCharArray();
+
+ java.lang.StringBuffer sNewName = new java.lang.StringBuffer(nLength);
+ for (i=0; i<nLength; ++i)
+ {
+ char c = lBuffer[i];
+ if (
+ c>=48 && c<=57 // 0-9
+ &&
+ c>=97 && c<=122 // a-z
+ &&
+ c>=65 && c<=90 // A-Z
+ )
+ {
+ sNewName.append(c);
+ }
+ else
+ {
+ sNewName.append("_");
+ }
+ }
+
+ return sNewName.toString();
+ }
+
+ //___________________________________________
+
+ /** it removes all child nodes of a file system directory.
+ *
+ * @param aDirectory
+ * points to the directory, which should be made empty.
+ *
+ * @param bFilesOnly
+ * force deletion of files only. If its set to TRUE,
+ * no subdirectory will be removed.
+ *
+ * @throw [java.io.IOException]
+ * if some of the child nodes couldn't be removed.
+ */
+ public static void makeDirectoryEmpty(java.io.File aDirectory,
+ boolean bFilesOnly)
+ throws java.io.IOException
+ {
+ if (!aDirectory.isDirectory())
+ throw new java.io.FileNotFoundException("\""+aDirectory.toString()+"\" is not a directory.");
+
+ java.io.File[] lChilds = aDirectory.listFiles();
+ for (int f=0; f<lChilds.length; ++f)
+ {
+ if (lChilds[f].isDirectory())
+ {
+ FileHelper.makeDirectoryEmpty(lChilds[f], bFilesOnly);
+ if (!bFilesOnly)
+ {
+ if (!lChilds[f].delete())
+ throw new java.io.IOException("\""+lChilds[f].toString()+"\" could not be deleted.");
+ }
+ }
+ else
+ {
+ if (!lChilds[f].delete())
+ throw new java.io.IOException("\""+lChilds[f].toString()+"\" could not be deleted.");
+ }
+ }
+ }
+
+ //___________________________________________
+
+ /** it try to generate a new file with a unique ID
+ * inside given directory.
+ *
+ * Call this method with a directory and a base name for
+ * a file. It will be used to generate a new files inside
+ * the directory. Existing files will be checked and new file
+ * name will be tested till a non existing file name would be found.
+ *
+ * @param aBaseDir
+ * must be a system path
+ * e.g.: "c:\temp"
+ *
+ * @param sBaseName
+ * must be a system file name without extensions.
+ * e.g.: "myfile_"
+ *
+ * @param sExtension
+ * the whished extension.
+ * e.g.: "dat"
+ *
+ * @return A valid file object, if an unique file could be created -
+ * Null otherwhise.
+ * e.g.: "c:\temp\myfile_1.dat"
+ */
+ public static java.io.File createUniqueFile(java.io.File aBaseDir ,
+ java.lang.String sBaseName ,
+ java.lang.String sExtension)
+ {
+ java.io.File aBaseFile = new java.io.File(aBaseDir, sBaseName);
+ java.io.File aFile = null;
+ long nr = 0;
+ while (aFile == null && nr < java.lang.Long.MAX_VALUE)
+ {
+ java.lang.String sFileName = aBaseFile.getPath() + java.lang.String.valueOf(nr) + "." + sExtension;
+ aFile = new java.io.File(sFileName);
+ if (aFile.exists())
+ aFile=null;
+ ++nr;
+ }
+ return aFile;
+ }
+
+ //___________________________________________
+
+ /** reads the complete file, using the right encoding,
+ * into the given string buffer.
+ *
+ * @param aFile
+ * must point to a system file, which must exist.
+ * e.g.: "c:\temp\test.txt"
+ * "/tmp/test.txt"
+ *
+ * @param sEncoding
+ * will be used to encode the string content
+ * inside the file.
+ * e.g.: "UTF8"
+ *
+ * @param sBuffer
+ * used to return the file content.
+ *
+ * @throw [IOException]
+ * - if the file couldnt be opened
+ * - if the file does not use the right encoding
+ */
+ public static void readEncodedBufferFromFile(java.io.File aFile ,
+ java.lang.String sEncoding,
+ java.lang.StringBuffer sBuffer )
+ throws java.io.IOException
+ {
+ if (sEncoding.equals("UTF-8Special"))
+ {
+ FileHelper.readAndCheckUTF8File(aFile,sBuffer);
+ return;
+ }
+
+ java.io.FileInputStream aByteStream = new java.io.FileInputStream(aFile.getAbsolutePath());
+ java.io.InputStreamReader aEncodedReader = new java.io.InputStreamReader(aByteStream, sEncoding);
+ char[] aEncodedBuffer = new char[4096];
+ int nReadCount = 0;
+
+ while((nReadCount=aEncodedReader.read(aEncodedBuffer))>0)
+ sBuffer.append(aEncodedBuffer, 0, nReadCount);
+
+ aEncodedReader.close();
+ }
+
+ //___________________________________________
+ private static void logEncodingData(java.lang.StringBuffer sLog ,
+ int nUTF8 ,
+ int nByteOrg1 ,
+ int nByteOrg2 ,
+ int nByteOrg3 ,
+ int nByteOrg4 ,
+ int nByte1 ,
+ int nByte2 ,
+ int nByte3 ,
+ int nByte4 ,
+ int nEncodingType)
+ {
+ sLog.append("["+nEncodingType+"]\t");
+ sLog.append((int)nUTF8+"\t=");
+ sLog.append("\t"+nByteOrg1+"/"+nByte1);
+ sLog.append("\t"+nByteOrg2+"/"+nByte2);
+ sLog.append("\t"+nByteOrg3+"/"+nByte3);
+ sLog.append("\t"+nByteOrg4+"/"+nByte4);
+ sLog.append("\n");
+ }
+
+ //___________________________________________
+ private static char impl_convertBytesToChar(int nByte1, int nByte2, int nByte3, int nByte4)
+ {
+ return (char)((nByte1*0x40000)+(nByte2*0x1000)+(nByte3*0x40)+nByte4);
+ }
+
+ //___________________________________________
+ private static int impl_readAndCheckNextByte(byte[] aBuffer ,
+ int nBufPos ,
+ int nBufLength ,
+ int nMinRange ,
+ int nMaxRange )
+ throws java.lang.Exception
+ {
+ if (nBufPos>=nBufLength)
+ throw new java.lang.Exception("impl_readAndCheckNextByte()\nEnd of buffer reached.");
+
+ int nByte = aBuffer[nBufPos] & 0xFF;
+ if (
+ (nByte < nMinRange) ||
+ (nByte > nMaxRange)
+ )
+ {
+ throw new java.lang.Exception("impl_readAndCheckNextByte()\nByte does not fit the specified range.");
+ }
+
+ return nByte;
+ }
+
+ //___________________________________________
+ public static void readAndCheckUTF8File(java.io.File aFile ,
+ java.lang.StringBuffer sBuffer)
+ throws java.io.IOException
+ {
+ java.io.FileInputStream aByteStream = new java.io.FileInputStream(aFile.getAbsolutePath());
+ byte[] aBuffer = new byte[4096];
+ int nReadCount = 0;
+ int nByteOrg_1 = 0;
+ int nByteOrg_2 = 0;
+ int nByteOrg_3 = 0;
+ int nByteOrg_4 = 0;
+ int nByte_1 = 0;
+ int nByte_2 = 0;
+ int nByte_3 = 0;
+ int nByte_4 = 0;
+ char nUTF8 = 0;
+ int i = 0;
+ int nEncodingType = 0;
+ java.lang.StringBuffer sLog = new java.lang.StringBuffer();
+
+ try
+ {
+
+ while((nReadCount=aByteStream.read(aBuffer))>0)
+ {
+ i=0;
+ while (i<nReadCount)
+ {
+ nByteOrg_1 = 0;
+ nByteOrg_2 = 0;
+ nByteOrg_3 = 0;
+ nByteOrg_4 = 0;
+ nByte_1 = 0;
+ nByte_2 = 0;
+ nByte_3 = 0;
+ nByte_4 = 0;
+ nUTF8 = 0;
+ nEncodingType = 0;
+
+ nByteOrg_1 = aBuffer[i++] & 0xFF;
+ nByte_1 = nByteOrg_1;
+ /*
+ Table 3-6. Well-Formed UTF-8 Byte Sequences
+
+ ============================================================================
+ Nr. Code Points 1st Byte 2nd Byte 3rd Byte 4th Byte
+ ============================================================================
+ 01 U+ 0..U+ 7F 00..7F
+ 02 U+ 80..U+ 7FF C2..DF 80..BF
+ 03 U+ 800..U+ FFF E0 A0..BF 80..BF
+ 04 U+ 1000..U+ CFFF E1..EC 80..BF 80..BF
+ 05 U+ D000..U+ D7FF ED 80..9F 80..BF
+ 06 U+ E000..U+ FFFF EE..EF 80..BF 80..BF
+ 07 U+ 10000..U+ 3FFFF F0 90..BF 80..BF 80..BF
+ 08 U+ 40000..U+ FFFFF F1..F3 80..BF 80..BF 80..BF
+ 09 U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
+ */
+ // ------------------------------------------------------------
+ // 01
+ // 1 byte: 0xxxxxxx
+ // ------------------------------------------------------------
+ if (
+ (nByteOrg_1 >= 0x00) &&
+ (nByteOrg_1 <= 0x7F)
+ )
+ {
+ nEncodingType = 1;
+ nUTF8 = (char)nByte_1;
+ }
+ // ------------------------------------------------------------
+ // 02
+ // 1 byte: 110xxxxx
+ // 2 byte: 101xxxxx
+ // ------------------------------------------------------------
+ else
+ if (
+ (nByteOrg_1 >= 0xC2) &&
+ (nByteOrg_1 <= 0xDF)
+ )
+ {
+ nEncodingType = 2;
+ nByteOrg_2 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByte_1 = nByteOrg_1-0xC2;
+ nByte_2 = nByteOrg_2-0x80;
+ nUTF8 = FileHelper.impl_convertBytesToChar(0,0,nByte_1, nByte_2);
+ }
+ // ------------------------------------------------------------
+ // 03
+ // 1 byte: 11100000
+ // 2 byte: 101xxxxx
+ // 3 byte: 10xxxxxx
+ // ------------------------------------------------------------
+ else
+ if (nByteOrg_1 == 0xE0)
+ {
+ nEncodingType = 3;
+ nByteOrg_2 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0xA0, 0xBF);
+ nByteOrg_3 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByte_2 = nByteOrg_2-0xA0;
+ nByte_3 = nByteOrg_3-0x80;
+ nUTF8 = FileHelper.impl_convertBytesToChar(0,0,nByte_2, nByte_3);
+ }
+ // ------------------------------------------------------------
+ // 04
+ // 1 byte: 111xxxxx
+ // 2 byte: 10xxxxxx
+ // 3 byte: 10xxxxxx
+ // ------------------------------------------------------------
+ else
+ if (
+ (nByteOrg_1 >= 0xE1) &&
+ (nByteOrg_1 <= 0xEC)
+ )
+ {
+ nEncodingType = 4;
+ nByteOrg_2 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByteOrg_3 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByte_1 = nByteOrg_1-0xE1;
+ nByte_2 = nByteOrg_2-0x80;
+ nByte_3 = nByteOrg_3-0x80;
+ nUTF8 = FileHelper.impl_convertBytesToChar(0,nByte_1, nByte_2, nByte_3);
+ }
+ // ------------------------------------------------------------
+ // 05
+ // 1 byte: 11101101
+ // 2 byte: 10xxxxxx
+ // 3 byte: 10xxxxxx
+ // ------------------------------------------------------------
+ else
+ if (nByteOrg_1 == 0xED)
+ {
+ nEncodingType = 5;
+ nByteOrg_2 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0x9F);
+ nByteOrg_3 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByte_2 = nByteOrg_2-0x80;
+ nByte_3 = nByteOrg_3-0x80;
+ nUTF8 = FileHelper.impl_convertBytesToChar(0,0, nByte_2, nByte_3);
+ }
+ // ------------------------------------------------------------
+ // 06
+ // 1 byte: 1110111x
+ // 2 byte: 10xxxxxx
+ // 3 byte: 10xxxxxx
+ // ------------------------------------------------------------
+ else
+ if (
+ (nByteOrg_1 >= 0xEE) &&
+ (nByteOrg_1 <= 0xEF)
+ )
+ {
+ nEncodingType = 6;
+ nByteOrg_2 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByteOrg_3 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByte_1 = nByteOrg_1-0xEE;
+ nByte_2 = nByteOrg_2-0x80;
+ nByte_3 = nByteOrg_3-0x80;
+ nUTF8 = FileHelper.impl_convertBytesToChar(0,nByte_1, nByte_2, nByte_3);
+ }
+ // ------------------------------------------------------------
+ // 07
+ // 1 byte: 11110000
+ // 2 byte: 1001xxxx
+ // 3 byte: 10xxxxxx
+ // 4 byte: 10xxxxxx
+ // ------------------------------------------------------------
+ else
+ if (nByteOrg_1 == 0xF0)
+ {
+ nEncodingType = 7;
+ nByteOrg_2 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x90, 0xBF);
+ nByteOrg_3 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByteOrg_4 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByte_2 = nByteOrg_2-0x90;
+ nByte_3 = nByteOrg_3-0x80;
+ nByte_4 = nByteOrg_4-0x80;
+ nUTF8 = FileHelper.impl_convertBytesToChar(0, nByte_2, nByte_3, nByte_4);
+ }
+ // ------------------------------------------------------------
+ // 08
+ // 1 byte: 111100xx
+ // 2 byte: 10xxxxxx
+ // 3 byte: 10xxxxxx
+ // 3 byte: 10xxxxxx
+ // ------------------------------------------------------------
+ else
+ if (
+ (nByteOrg_1 >= 0xF1) &&
+ (nByteOrg_1 <= 0xF3)
+ )
+ {
+ nEncodingType = 8;
+ nByteOrg_2 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByteOrg_3 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByteOrg_4 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByte_1 = nByteOrg_1-0xF1;
+ nByte_2 = nByteOrg_2-0x80;
+ nByte_3 = nByteOrg_3-0x80;
+ nByte_4 = nByteOrg_4-0x80;
+ nUTF8 = FileHelper.impl_convertBytesToChar(nByte_1, nByte_2, nByte_3, nByte_4);
+ }
+ // ------------------------------------------------------------
+ // 09
+ // 1 byte: 11110100
+ // 2 byte: 10xxxxxx
+ // 3 byte: 10xxxxxx
+ // 4 byte: 10xxxxxx
+ // ------------------------------------------------------------
+ else
+ if (nByteOrg_1 == 0xF0)
+ {
+ nEncodingType = 9;
+ nByteOrg_2 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByteOrg_3 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByteOrg_4 = FileHelper.impl_readAndCheckNextByte(aBuffer, i++, nReadCount, 0x80, 0xBF);
+ nByte_2 = nByteOrg_2-0x80;
+ nByte_3 = nByteOrg_3-0x80;
+ nByte_4 = nByteOrg_4-0x80;
+ nUTF8 = FileHelper.impl_convertBytesToChar(0, nByte_2, nByte_3, nByte_4);
+ }
+ // wrong encoding ?
+ else
+ {
+ throw new java.lang.Exception("Non well formed UTF-8 encoding.");
+ }
+
+ sBuffer.append(nUTF8);
+ // -> DEBUG !
+ FileHelper.logEncodingData(sLog, nUTF8, nByteOrg_1, nByteOrg_2, nByteOrg_3, nByteOrg_4, nByte_1, nByte_2, nByte_3, nByte_4, nEncodingType);
+ // <- DEBUG !
+ }
+ }
+
+ }
+ catch(java.lang.Throwable ex)
+ {
+ // -> DEBUG !
+ FileHelper.logEncodingData(sLog, nUTF8, nByteOrg_1, nByteOrg_2, nByteOrg_3, nByteOrg_4, nByte_1, nByte_2, nByte_3, nByte_4, nEncodingType);
+
+ java.io.File aDir = new java.io.File(aFile.getParent());
+ java.lang.String sDump = aFile.getName();
+ java.io.File aDump = FileHelper.createUniqueFile(aDir, sDump, "dump");
+ FileHelper.writeEncodedBufferToFile(aDump, "UTF-8", false, sLog);
+ // <- DEBUG !
+
+ java.lang.String sMsg = "File '"+aFile.getPath()+"' is not encoded right as UTF-8.";
+ throw new java.io.IOException(sMsg);
+ }
+
+ aByteStream.close();
+ }
+
+ //___________________________________________
+
+ /** writes the given string buffer into the specified file
+ * using the specified encoding.
+ *
+ * Further it can be set, if the file should be expanded
+ * or replaced by this new string buffer.
+ *
+ * @param aFile
+ * must point to a system file. It can already exist!
+ * e.g.: "c:\temp\test.txt"
+ * "/tmp/test.txt"
+ *
+ * @param sEncoding
+ * will be used to encode the string content inside the file.
+ * e.g.: "UTF8"
+ *
+ * @param bAppend
+ * specify if an already existing file will be
+ * expanded or replaced.
+ *
+ * @param sBuffer
+ * the new string content for this file.
+ */
+ public static void writeEncodedBufferToFile(java.io.File aFile ,
+ java.lang.String sEncoding,
+ boolean bAppend ,
+ java.lang.StringBuffer sBuffer )
+ throws java.io.IOException
+ {
+ java.io.FileOutputStream aByteStream = new java.io.FileOutputStream(aFile.getAbsolutePath(), bAppend);
+ java.io.OutputStreamWriter aEncodedWriter = new java.io.OutputStreamWriter(aByteStream, sEncoding);
+
+ java.lang.String sTemp = sBuffer.toString();
+ aEncodedWriter.write(sTemp, 0, sTemp.length());
+
+ aEncodedWriter.flush();
+ aEncodedWriter.close();
+
+ if (!aFile.exists())
+ throw new java.io.IOException("File \""+aFile.getAbsolutePath()+"\" not written correctly.");
+ }
+}
diff --git a/l10ntools/source/filter/utils/Logger.java b/l10ntools/source/filter/utils/Logger.java
new file mode 100644
index 000000000000..7657eba5f426
--- /dev/null
+++ b/l10ntools/source/filter/utils/Logger.java
@@ -0,0 +1,177 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Logger.java,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package com.sun.star.filter.config.tools.utils;
+
+//_______________________________________________
+// imports
+
+import java.lang.*;
+import java.util.*;
+
+//_______________________________________________
+// definition
+
+/** can be used to print out some debug messages
+ * and group it into warnings/errors or info statements.
+ *
+ *
+ */
+public class Logger
+{
+ //___________________________________________
+ // const
+
+ /** only error message will be shown. */
+ public static final int LEVEL_ERRORS = 1;
+
+ /** only errors and warnings will be shown. */
+ public static final int LEVEL_WARNINGS = 2;
+
+ /** enable errors/warnings and some global info
+ * message. */
+ public static final int LEVEL_GLOBALINFOS = 3;
+
+ /** enable anything! */
+ public static final int LEVEL_DETAILEDINFOS = 4;
+
+ //___________________________________________
+ // member
+
+ /** enable/disable different output level.
+ * e.g. warnings/errors/infos */
+ private int m_nLevel;
+
+ //___________________________________________
+ // ctor
+
+ /** initialize new debug object with the specified
+ * debug level.
+ *
+ * @param nLevel
+ * the new debug level.
+ * See const values LEVEL_xxx too.
+ */
+ public Logger(int nLevel)
+ {
+ m_nLevel = nLevel;
+ }
+
+ //___________________________________________
+ // interface
+
+ /** initialize new debug object with a default
+ * debug level.
+ */
+ public Logger()
+ {
+ m_nLevel = LEVEL_DETAILEDINFOS;
+ }
+
+ //___________________________________________
+ // interface
+
+ /** prints out an exception ... if the right level is set.
+ *
+ * @param ex
+ * the exception object
+ */
+ public synchronized void setException(java.lang.Throwable ex)
+ {
+ if (m_nLevel >= LEVEL_ERRORS)
+ {
+ System.err.println("Exception:\n");
+ ex.printStackTrace();
+ }
+ }
+
+ //___________________________________________
+ // interface
+
+ /** prints out an error ... if the right level is set.
+ *
+ * @param sError
+ * the error message.
+ */
+ public synchronized void setError(java.lang.String sError)
+ {
+ if (m_nLevel >= LEVEL_ERRORS)
+ System.err.println("Error :\t\""+sError+"\"");
+ }
+
+ //___________________________________________
+ // interface
+
+ /** prints out a warning ... if the right level is set.
+ *
+ * @param sWarning
+ * the warning message.
+ */
+ public synchronized void setWarning(java.lang.String sWarning)
+ {
+ if (m_nLevel >= LEVEL_WARNINGS)
+ System.err.println("Warning :\t\""+sWarning+"\"");
+ }
+
+ //___________________________________________
+ // interface
+
+ /** prints out a global info message ... if the right level is set.
+ *
+ * Global infos should be used to describe a complex operation.
+ * E.g.: loading of a document.
+ * But not for every sub operation like e.g. analyzing lines
+ * during loading the document!
+ *
+ * @param sInfo
+ * the info message.
+ */
+ public synchronized void setGlobalInfo(java.lang.String sInfo)
+ {
+ if (m_nLevel >= LEVEL_GLOBALINFOS)
+ System.out.println("Info :\t\""+sInfo+"\"");
+ }
+
+ //___________________________________________
+ // interface
+
+ /** prints out a mode detailed info message ... if the right level is set.
+ *
+ * Such detailed message are e.g. "analyze line [n] of file ...".
+ *
+ * @param sInfo
+ * the info message.
+ */
+ public synchronized void setDetailedInfo(java.lang.String sInfo)
+ {
+ if (m_nLevel >= LEVEL_DETAILEDINFOS)
+ System.out.println("Detail :\t\""+sInfo+"\"");
+ }
+}
diff --git a/l10ntools/source/filter/utils/MalformedCommandLineException.java b/l10ntools/source/filter/utils/MalformedCommandLineException.java
new file mode 100644
index 000000000000..e073dcb9adcc
--- /dev/null
+++ b/l10ntools/source/filter/utils/MalformedCommandLineException.java
@@ -0,0 +1,50 @@
+/*_***********************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: MalformedCommandLineException.java,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ **********************************************************************_*/
+
+package com.sun.star.filter.config.tools.utils;
+
+//_______________________________________________
+// imports
+
+import java.lang.*;
+
+//___________________________________________
+// types
+
+/** indicates a malformed command line.
+ *
+ * E.g. it must be thrown if the command line contains one item more then once,
+ * or use unsupported format.
+ */
+public class MalformedCommandLineException extends java.lang.Exception
+{
+ public MalformedCommandLineException() {}
+ public MalformedCommandLineException(java.lang.String sMsg) { super(sMsg); }
+}
diff --git a/l10ntools/source/filter/utils/XMLHelper.java b/l10ntools/source/filter/utils/XMLHelper.java
new file mode 100644
index 000000000000..0f912cac8e25
--- /dev/null
+++ b/l10ntools/source/filter/utils/XMLHelper.java
@@ -0,0 +1,825 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: XMLHelper.java,v $
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package com.sun.star.filter.config.tools.utils;
+
+//_______________________________________________
+
+import java.lang.*;
+import java.util.*;
+import java.io.*;
+
+//_______________________________________________
+
+/**
+ * It provides some constant values and some static helper routines
+ * which are neccessary to work with a xml file - especialy
+ * the filter configuration.
+ *
+ *
+ */
+public class XMLHelper
+{
+ //___________________________________________
+ // public const
+
+ /** its a possible value of the xml attribute "oor:type" and identify an integer type. */
+ public static final java.lang.String XMLTYPE_INTEGER = "xs:int";
+
+ /** its a possible value of the xml attribute "oor:type" and identify an boolean type. */
+ public static final java.lang.String XMLTYPE_BOOLEAN = "xs:boolean";
+
+ /** its a possible value of the xml attribute "oor:type" and identify an string type. */
+ public static final java.lang.String XMLTYPE_STRING = "xs:string";
+
+ /** its a possible value of the xml attribute "oor:type" and identify an string list type. */
+ public static final java.lang.String XMLTYPE_STRINGLIST = "oor:string-list";
+
+ /** its a xml attribute, which specify a property name. */
+ public static final java.lang.String XMLATTRIB_OOR_NAME = "oor:name";
+
+ /** its a xml attribute, which specify a property type. */
+ public static final java.lang.String XMLATTRIB_OOR_TYPE = "oor:type";
+
+ /** its a xml attribute, which specify a list separator. */
+ public static final java.lang.String XMLATTRIB_OOR_SEPARATOR = "oor:separator";
+
+ /** its a xml attribute, which specify a localized value. */
+ public static final java.lang.String XMLATTRIB_OOR_LOCALIZED = "oor:localized";
+
+ /** its a xml attribute, which specify a merge operation for cfg layering. */
+ public static final java.lang.String XMLATTRIB_OOR_OP = "oor:op";
+
+ /** can be used as value for XMLATTRIB_OOR_OP. */
+ public static final java.lang.String XMLATTRIB_OP_REPLACE = "replace";
+
+ /** its a xml attribute, which specify a locale value. */
+ public static final java.lang.String XMLATTRIB_XML_LANG = "xml:lang";
+
+ /** its the tag name of a <value ...> entry. */
+ public static final java.lang.String XMLTAG_VALUE = "value";
+
+ /** its the tag name of a <prop ...> entry. */
+ public static final java.lang.String XMLTAG_PROP = "prop";
+
+ /** its the tag name of a <node ...> entry. */
+ public static final java.lang.String XMLTAG_NODE = "node";
+
+ //___________________________________________
+ // private const
+
+ /** a static list of all possible separators, which can be used for configuration type string-list. */
+ private static final java.lang.String[] DELIMS = {" ", ",", ";", ".", ":", "-", "_", "#", "'", "+", "*", "~", "=", "?"};
+
+ /** index of the default separator inside list DELIMS.
+ * Its neccessary to know such default separator; because it can
+ * be supressed as xml attribute of the corresponding value tag. */
+ private static final int DEFAULT_SEPARATOR = 0;
+
+ //___________________________________________
+
+ /** analyze the structures of the given XML node and
+ * return a property set of all found sub nodes.
+ *
+ * Such properties are organized as [name, value] pairs.
+ * The type of a xml node will be detected automaticly.
+ * Following types are supported:
+ * xs:int => java.lang.Integer
+ * xs:bool => java.lang.Boolean
+ * xs:string => java.lang.String
+ * oor:string-list => java.util.LinkedList[java.lang.String]
+ * oor:set => java.util.Vector[java.lang.Object]
+ * oor:localized => java.util.HashMap[java.lang.Object]
+ *
+ * @param aNode
+ * points directly to the xml node, where we should analyze
+ * the children nodes.
+ *
+ * @return [java.util.HashMap]
+ * contains every node name as key and its string(!) as value.
+ */
+ public static java.util.HashMap convertNodeToPropSet(org.w3c.dom.Node aNode)
+ throws java.lang.Exception
+ {
+ java.util.HashMap aPropSet = new java.util.HashMap();
+
+ // get all child nodes, which seems to be properties
+ java.util.Vector lChildNodes = XMLHelper.extractChildNodesByTagName(aNode, XMLTAG_PROP);
+ java.util.Enumeration en1 = lChildNodes.elements();
+ while(en1.hasMoreElements())
+ {
+ org.w3c.dom.Node aChildNode = (org.w3c.dom.Node)en1.nextElement();
+
+ // read its name
+ java.lang.String sChildName = XMLHelper.extractNodeAttribByName(aChildNode, XMLATTRIB_OOR_NAME);
+ if (sChildName == null)
+ throw new java.io.IOException("unsupported format: could not extract child node name");
+
+ // read its type info
+ java.lang.String sChildType = XMLHelper.extractNodeAttribByName(aChildNode, XMLATTRIB_OOR_TYPE);
+ if (sChildType == null)
+ {
+ /** Special patch:
+ * If an xml tag has no type information set ... we can restore it
+ * by analyzing the already readed tag name :-)
+ * Not very nice - but it can help to read stripped xml files too. */
+ sChildType = XMLHelper.getTypeForTag(sChildName);
+ if (sChildType == null)
+ throw new java.io.IOException("unsupported format: could not extract child node type");
+ }
+
+ // read its value(s?)
+ java.util.Vector lChildValues = XMLHelper.extractChildNodesByTagName(aChildNode, XMLTAG_VALUE);
+ java.util.Enumeration en2 = lChildValues.elements();
+ int nValue = 0;
+ java.lang.Object aValue = null;
+ while(en2.hasMoreElements())
+ {
+ org.w3c.dom.Node aValueNode = (org.w3c.dom.Node)en2.nextElement();
+ java.lang.String sChildLocale = XMLHelper.extractNodeAttribByName(aValueNode, XMLATTRIB_XML_LANG);
+ boolean bLocalized = (sChildLocale != null);
+
+ ++nValue;
+
+ if (sChildType.equals(XMLTYPE_INTEGER))
+ {
+ if (!bLocalized && nValue > 1)
+ throw new java.io.IOException("unsupported format: more then one value for non localized but atomic type detected");
+ java.lang.String sData = ((org.w3c.dom.CharacterData)aValueNode.getFirstChild()).getData();
+ aValue = new java.lang.Integer(sData);
+ }
+ else
+ if (sChildType.equals(XMLTYPE_BOOLEAN))
+ {
+ if (!bLocalized && nValue > 1)
+ throw new java.io.IOException("unsupported format: more then one value for non localized but atomic type detected");
+ java.lang.String sData = ((org.w3c.dom.CharacterData)aValueNode.getFirstChild()).getData();
+ aValue = new java.lang.Boolean(sData);
+ }
+ else
+ if (sChildType.equals(XMLTYPE_STRING))
+ {
+ if (!bLocalized && nValue > 1)
+ throw new java.io.IOException("unsupported format: more then one value for non localized but atomic type detected");
+
+ java.lang.String sData = ((org.w3c.dom.CharacterData)aValueNode.getFirstChild()).getData();
+
+ java.util.HashMap lLocalized = null;
+ if (bLocalized)
+ {
+ if (aValue == null)
+ aValue = new java.util.HashMap();
+ lLocalized = (java.util.HashMap)aValue;
+ lLocalized.put(sChildLocale, sData);
+ }
+ else
+ aValue = sData;
+ }
+ else
+ if (sChildType.equals(XMLTYPE_STRINGLIST))
+ {
+ if (!bLocalized && nValue > 1)
+ throw new java.io.IOException("unsupported format: more then one value for non localized but atomic type detected");
+
+ java.lang.String sSeparator = XMLHelper.extractNodeAttribByName(aChildNode, XMLATTRIB_OOR_SEPARATOR);
+ if (sSeparator == null)
+ sSeparator = " ";
+
+ java.lang.String sData = ((org.w3c.dom.CharacterData)aValueNode.getFirstChild()).getData();
+ sData = sData.replace('\t', ' ');
+ sData = sData.replace('\n', ' ');
+ java.util.StringTokenizer aTokenizer = new java.util.StringTokenizer(sData, sSeparator);
+ java.util.Vector lList = new java.util.Vector();
+ while(aTokenizer.hasMoreTokens())
+ {
+ java.lang.String sToken = (java.lang.String)aTokenizer.nextToken();
+ sToken.trim();
+ if (sToken.length() < 1)
+ continue;
+ lList.add(sToken);
+ }
+ aValue = lList;
+ }
+
+ aPropSet.put(sChildName, aValue);
+ }
+ }
+
+ return aPropSet;
+ }
+
+ //___________________________________________
+
+ private static java.lang.String getTypeForTag(java.lang.String sTag)
+ {
+ java.lang.String sType = null;
+
+ if (
+ (sTag.equals(Cache.PROPNAME_DATA )) ||
+ (sTag.equals(Cache.PROPNAME_NAME )) ||
+ (sTag.equals(Cache.PROPNAME_UINAME )) ||
+ (sTag.equals(Cache.PROPNAME_MEDIATYPE )) ||
+ (sTag.equals(Cache.PROPNAME_CLIPBOARDFORMAT )) ||
+ (sTag.equals(Cache.PROPNAME_PREFERREDFILTER )) ||
+ (sTag.equals(Cache.PROPNAME_DETECTSERVICE )) ||
+ (sTag.equals(Cache.PROPNAME_FRAMELOADER )) ||
+ (sTag.equals(Cache.PROPNAME_CONTENTHANDLER )) ||
+ (sTag.equals(Cache.PROPNAME_DOCUMENTSERVICE )) ||
+ (sTag.equals(Cache.PROPNAME_FILTERSERVICE )) ||
+ (sTag.equals(Cache.PROPNAME_TEMPLATENAME )) ||
+ (sTag.equals(Cache.PROPNAME_TYPE )) ||
+ (sTag.equals(Cache.PROPNAME_UICOMPONENT ))
+ )
+ sType = XMLTYPE_STRING;
+ else
+ if (
+ (sTag.equals(Cache.PROPNAME_PREFERRED )) ||
+ (sTag.equals("Installed" ))
+ )
+ sType = XMLTYPE_BOOLEAN;
+ else
+ if (
+ (sTag.equals(Cache.PROPNAME_UIORDER )) ||
+ (sTag.equals(Cache.PROPNAME_DOCUMENTICONID )) ||
+ (sTag.equals(Cache.PROPNAME_FILEFORMATVERSION))
+ )
+ sType = XMLTYPE_INTEGER;
+ else
+ if (
+ (sTag.equals(Cache.PROPNAME_URLPATTERN )) ||
+ (sTag.equals(Cache.PROPNAME_EXTENSIONS )) ||
+ (sTag.equals(Cache.PROPNAME_USERDATA )) ||
+ (sTag.equals(Cache.PROPNAME_FLAGS )) ||
+ (sTag.equals(Cache.PROPNAME_TYPES ))
+ )
+ sType = XMLTYPE_STRINGLIST;
+
+ if (sType == null)
+ System.err.println("getTypeForTag("+sTag+") = "+sType);
+
+ return sType;
+ }
+
+ //___________________________________________
+
+ /** return a xml representation of the given property set.
+ *
+ * @param aPropSet
+ * a set of <name,value> pairs, which should be translated to xml
+ *
+ * @return [java.lang.String]
+ * the xml string representation.
+ *
+ * @throws [java.lang.Exception]
+ * if anything during convertion fill fail.
+ */
+ public static java.lang.String convertPropSetToXML(java.util.HashMap aPropSet ,
+ int nPrettyTabs)
+ throws java.lang.Exception
+ {
+ java.lang.StringBuffer sXML = new java.lang.StringBuffer(256);
+
+ java.util.Iterator it1 = aPropSet.keySet().iterator();
+ while(it1.hasNext())
+ {
+ java.lang.String sProp = (java.lang.String)it1.next();
+ java.lang.Object aVal = aPropSet.get(sProp);
+
+ sProp = encodeHTMLSigns(sProp);
+
+ // is it a simple type?
+ if (
+ (aVal instanceof java.lang.Integer) ||
+ (aVal instanceof java.lang.Boolean) ||
+ (aVal instanceof java.lang.String )
+ )
+ {
+ sXML.append(XMLHelper.convertSimpleObjectToXML(sProp, aVal, nPrettyTabs));
+ continue;
+ }
+
+ // no!
+ // is it a list value?
+ if (aVal instanceof java.util.Vector)
+ {
+ java.util.Vector lVal = (java.util.Vector)aVal;
+ sXML.append(XMLHelper.convertListToXML(sProp, lVal, nPrettyTabs));
+ continue;
+ }
+
+ // its a localized value?
+ if (aVal instanceof java.util.HashMap)
+ {
+ java.util.HashMap lVal = (java.util.HashMap)aVal;
+ sXML.append(XMLHelper.convertLocalizedValueToXML(sProp, lVal, nPrettyTabs));
+ continue;
+ }
+
+ // unknown type!
+ java.lang.StringBuffer sMsg = new java.lang.StringBuffer(256);
+ sMsg.append("unsupported object type detected.");
+ sMsg.append("\ttype ? : \""+sProp+"\" = "+aVal);
+ sMsg.append("\tprop set: \""+aPropSet );
+ throw new java.lang.Exception(sMsg.toString());
+ }
+
+ return sXML.toString();
+ }
+
+ public static java.lang.String encodeHTMLSigns(java.lang.String sValue)
+ {
+ java.lang.StringBuffer sSource = new java.lang.StringBuffer(sValue);
+ java.lang.StringBuffer sDestination = new java.lang.StringBuffer(1000 );
+
+ for (int i=0; i<sSource.length(); ++i)
+ {
+ char c = sSource.charAt(i);
+ if (c == '&')
+ sDestination.append("&amp;");
+ else
+ sDestination.append(c);
+ }
+
+ java.lang.String sReturn = sDestination.toString();
+ if (!sReturn.equals(sValue))
+ System.out.println("encode \""+sValue+"\" => \""+sReturn+"\"");
+
+ return sReturn;
+ }
+
+ //___________________________________________
+
+ /** return a xml representation of an atomic property.
+ *
+ * Atomic property types are e.g. Integer, Boolean, String.
+ *
+ * @param sName
+ * the name of the property.
+
+ * @param aValue
+ * the value of the property.
+ *
+ * @param nPrettyTabs
+ * count of tab signs for pretty format the xml code :-)
+ *
+ * @return [java.lang.String]
+ * the xml string representation.
+ *
+ * @throws [java.lang.Exception]
+ * if anything during convertion fill fail.
+ */
+ private static java.lang.String convertSimpleObjectToXML(java.lang.String sName ,
+ java.lang.Object aValue ,
+ int nPrettyTabs)
+ throws java.lang.Exception
+ {
+ java.lang.StringBuffer sXML = new java.lang.StringBuffer(256);
+ for (int t=0; t<nPrettyTabs; ++t)
+ sXML.append("\t");
+
+ if (aValue instanceof java.lang.Integer)
+ {
+ sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\">");
+ sXML.append("<value>"+aValue.toString()+"</value>");
+ sXML.append("</prop>\n");
+ }
+ else
+ if (aValue instanceof java.lang.Boolean)
+ {
+ sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\">");
+ sXML.append("<value>"+aValue.toString()+"</value>");
+ sXML.append("</prop>\n");
+ }
+ else
+ if (aValue instanceof java.lang.String)
+ {
+ sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\"");
+ java.lang.String sValue = (java.lang.String)aValue;
+
+ sValue = encodeHTMLSigns(sValue);
+
+ if (sValue.length() < 1)
+ sXML.append("/>\n");
+ else
+ {
+ sXML.append("><value>"+sValue+"</value>");
+ sXML.append("</prop>\n");
+ }
+ }
+ else
+ {
+ System.err.println("name = "+sName);
+ System.err.println("value = "+aValue);
+ // ! can be used outside to detect - that it was not a simple type :-)
+ throw new java.lang.Exception("not an atomic type.");
+ }
+
+ return sXML.toString();
+ }
+
+ //___________________________________________
+
+ /** return a xml representation of a string-list property.
+ *
+ * @param sName
+ * the name of the property.
+
+ * @param aValue
+ * the value of the property.
+ *
+ * @param nPrettyTabs
+ * count of tab signs for pretty format the xml code :-)
+ *
+ * @return [java.lang.String]
+ * the xml string representation.
+ *
+ * @throws [java.lang.Exception]
+ * if anything during convertion fill fail.
+ */
+ private static java.lang.String convertListToXML(java.lang.String sName ,
+ java.util.Vector aValue ,
+ int nPrettyTabs)
+ throws java.lang.Exception
+ {
+ java.lang.StringBuffer sXML = new java.lang.StringBuffer(256);
+
+ for (int t=0; t<nPrettyTabs; ++t)
+ sXML.append("\t");
+
+ int c = aValue.size();
+ if (c < 1)
+ {
+ sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\"/>\n");
+ return sXML.toString();
+ }
+
+ // step over all list items and add it to a string buffer
+ // Every item will be separated by a default separator "\n" first.
+ // Because "\n" is not a valid separator at all and can`t occure inside
+ // our list items. During we step over all items, we check if our current separator
+ // (we use a list of possible ones!) clash with an item.
+ // If it clash - we step to the next possible separator.
+ // If our list of possible separator values runs out of range we throw
+ // an exception :-) Its better then generating of wrong values
+ // If we found a valid seperator - we use it to replace our "\n" place holder
+ // at the end of the following loop ...
+
+ int d = 0;
+ java.lang.StringBuffer sValBuff = new java.lang.StringBuffer(256);
+ for (int i=0; i<c; ++i)
+ {
+ // get the next list item
+ java.lang.Object aItem = aValue.get(i);
+ if (!(aItem instanceof java.lang.String))
+ throw new java.lang.Exception("Current implementation supports string-list only!");
+
+ java.lang.String sValue = (java.lang.String)aItem;
+
+ sValue = encodeHTMLSigns(sValue);
+
+ // append item with default separator, which isn a valid separator at all
+ // But supress adding of the separator if last element is reached.
+ sValBuff.append(sValue);
+ if (i<(c-1))
+ sValBuff.append("\n");
+
+ // check for delim clash
+ // Attention: An empty (means default) element forbid using
+ // of a whitespace character as separator!
+ while(true)
+ {
+ if (d >= DELIMS.length)
+ throw new java.lang.Exception("No valid separator found for a string list item.");
+ if (sValue.length() < 1 && DELIMS[d].equals(" "))
+ {
+ ++d;
+ continue;
+ }
+ if (sValue.indexOf(DELIMS[d]) != -1)
+ {
+ ++d;
+ continue;
+ }
+ break;
+ }
+ }
+
+ // replace default separator with right one
+ System.out.println("TODO: must be adapted to java 1.3 :-(");
+ System.exit(-1);
+//TODO_JAVA java.lang.String sListVal = sValBuff.toString().replaceAll("\n", DELIMS[d]);
+ java.lang.String sListVal = null;
+
+ sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\">");
+ if (d == DEFAULT_SEPARATOR)
+ sXML.append("<value>");
+ else
+ sXML.append("<value "+XMLATTRIB_OOR_SEPARATOR+"=\""+DELIMS[d]+"\">");
+ sXML.append(sListVal);
+ sXML.append("</value>");
+ sXML.append("</prop>\n");
+
+ return sXML.toString();
+ }
+
+ //___________________________________________
+
+ /** return a xml representation of a localized property.
+ *
+ * @param sName
+ * the name of the property.
+
+ * @param aValue
+ * the value of the property.
+ *
+ * @param nPrettyTabs
+ * count of tab signs for pretty format the xml code :-)
+ *
+ * @return [java.lang.String]
+ * the xml string representation.
+ *
+ * @throws [java.lang.Exception]
+ * if anything during convertion fill fail.
+ */
+ private static java.lang.String convertLocalizedValueToXML(java.lang.String sName ,
+ java.util.HashMap aValue ,
+ int nPrettyTabs)
+ throws java.lang.Exception
+ {
+ java.lang.StringBuffer sXML = new java.lang.StringBuffer(256);
+
+ int c = aValue.size();
+ if (c < 1)
+ throw new java.lang.Exception("Cant detect type of localized values. Because the given list is empty.");
+
+ for (int t=0; t<nPrettyTabs; ++t)
+ sXML.append("\t");
+ // !Our localized values must be formated at a deeper coloum
+ // then its property name!
+ ++nPrettyTabs;
+
+ sXML.append("<prop "+XMLATTRIB_OOR_NAME+"=\""+sName+"\">\n");
+ java.util.Iterator it = aValue.keySet().iterator();
+// boolean bTypeKnown = false;
+ while(it.hasNext())
+ {
+ java.lang.String sLocale = (java.lang.String)it.next();
+ java.lang.Object aLocalizedValue = aValue.get(sLocale);
+/*
+ if (!bTypeKnown)
+ {
+ bTypeKnown = true;
+ if (aLocalizedValue instanceof java.lang.Integer)
+ sXML.append(" "+XMLATTRIB_OOR_TYPE+"=\""+XMLTYPE_INTEGER+"\">\n");
+ else
+ if (aLocalizedValue instanceof java.lang.Boolean)
+ sXML.append(" "+XMLATTRIB_OOR_TYPE+"=\""+XMLTYPE_BOOLEAN+"\">\n");
+ else
+ if (aLocalizedValue instanceof java.lang.String)
+ sXML.append(" "+XMLATTRIB_OOR_TYPE+"=\""+XMLTYPE_STRING+"\">\n");
+ else
+ throw new java.lang.Exception("Unsupported type for localized value detected.");
+ }
+*/
+ java.lang.String sLocValue = aLocalizedValue.toString();
+ java.lang.String sValue = encodeHTMLSigns(sLocValue);
+
+ for (int t=0; t<nPrettyTabs; ++t)
+ sXML.append("\t");
+ sXML.append("<value "+XMLATTRIB_XML_LANG+"=\""+sLocale+"\">"+sValue+"</value>\n");
+ }
+ --nPrettyTabs;
+ for (int t=0; t<nPrettyTabs; ++t)
+ sXML.append("\t");
+ sXML.append("</prop>\n");
+
+ return sXML.toString();
+ }
+
+ //___________________________________________
+
+ /** returns the value of an attribute of the given node.
+ *
+ * If the given node represent an lement node, may it supports some attributes.
+ * Then this method search for an attribute with the specified name and return it's value.
+ * If nothing could be found ... or the given node isn't a suitable node ... it returns null.
+ *
+ * @param aNode
+ * the node, which should be analyzed.
+ *
+ * @param sAttrib
+ * name of the attribute, which should be searched.
+ *
+ * @return The value of the specified attribute if it could be found at the given node.
+ * Can be null if node doesn't support attributes or the searched one does not exist there.
+ */
+ public static java.lang.String extractNodeAttribByName(org.w3c.dom.Node aNode ,
+ java.lang.String sAttrib)
+ throws java.lang.Exception
+ {
+ // We can get valid attributes for element nodes only!
+ if (aNode.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
+ {
+// System.err.println("not an element node");
+ return null;
+ }
+
+ // may it supports attributes in general ... but doesn't have anyone realy.
+ org.w3c.dom.NamedNodeMap lAttribs = aNode.getAttributes();
+ if (lAttribs==null)
+ {
+// System.err.println("no attributes at all");
+ return null;
+ }
+
+ // step over the attribute list and search for the requested one
+ for (int i=0; i<lAttribs.getLength(); ++i)
+ {
+ org.w3c.dom.Attr aAttrib = (org.w3c.dom.Attr)lAttribs.item(i);
+ if (aAttrib.getName().equals(sAttrib))
+ {
+ java.lang.String sValue = aAttrib.getValue();
+ return sValue;
+ }
+ }
+
+ // the searched attribute was not found!
+// System.err.println("required attribute \""+sAttrib+"\" does not exist for node ["+aNode.toString()+"]");
+ return null;
+ }
+
+ //___________________________________________
+
+ /** returns a list of childs, which are ELEMENT_NODES and have the right tag name.
+ *
+ * It analyze the list of all possible child nodes. Only ELEMENT_NODES are candidates.
+ * All other ones will be ignored. Further these element nodes are compared by it's tag
+ * names. If it match with the specified value it's added to the return list.
+ * So the return list includes references to the DOM tree nodes only, which are child
+ * element nodes with the right tag name.
+ *
+ * @param aNode
+ * provides access to the child nodes, which should be analyzed
+ *
+ * @param sTag
+ * the searched tag name.
+ *
+ * @return A list of child nodes, which are element nodes and have the right tag name.
+ */
+ public static java.util.Vector extractChildNodesByTagName(org.w3c.dom.Node aNode,
+ java.lang.String sTag )
+ {
+ // extract first all ELEMENT_NODES of he given parent
+ // Such nodes only provide tag names.
+ java.util.Vector lChilds = XMLHelper.extractChildNodesByType(aNode,org.w3c.dom.Node.ELEMENT_NODE);
+ java.util.Vector lExtractedChilds = new java.util.Vector(lChilds.size());
+
+ // step over the list and search for the right tags using the specified name
+ java.util.Enumeration en = lChilds.elements();
+ while (en.hasMoreElements())
+ {
+ org.w3c.dom.Node aChild = (org.w3c.dom.Node)en.nextElement();
+ if (aChild.getNodeName().equals(sTag))
+ lExtractedChilds.add(aChild);
+ }
+
+ // pack(!) and return the list
+ lExtractedChilds.trimToSize();
+ return lExtractedChilds;
+ }
+
+ //___________________________________________
+
+ /** returns a list of childs, which supports the right node type.
+ *
+ * It analyze the list of all possible child nodes. If a node represent the right node type
+ * it is added to the return list. Otherwhise it will be ignored.
+ *
+ * @param aNode
+ * provides access to the list of possible children nodes.
+ *
+ * @param nType
+ * represent the searched node type.
+ * Possible values are constant fields of a org.w3c.dom.Node - e.g. org.w3c.dom.Node.ELEMENT_NODE.
+ *
+ * @return A list of child nodes, which provides the right node type.
+ */
+ public static java.util.Vector extractChildNodesByType(org.w3c.dom.Node aNode,
+ short nType)
+ {
+ // get list of all possibe childs and reserve enough space for our return list
+ // Attention: A null pointer is not allowed for return! (means lExtractedChilds)
+ org.w3c.dom.NodeList lChilds = aNode.getChildNodes();
+ int c = lChilds.getLength();
+ java.util.Vector lExtractedChilds = new java.util.Vector(c);
+
+ // step of these childs and select only needed ones
+ for (int i=0; i<c; ++i)
+ {
+ org.w3c.dom.Node aChild = lChilds.item(i);
+ if (aChild.getNodeType() == nType)
+ lExtractedChilds.add(aChild);
+ }
+
+ // pack(!) and return the list
+ lExtractedChilds.trimToSize();
+ return lExtractedChilds;
+ }
+
+ //___________________________________________
+
+ /** generates an xml header, using parameters.
+ *
+ * @param sVersion
+ * number of the xml version.
+ *
+ * @param sEncoding
+ * used file encoding.
+ *
+ * @param sPath
+ * name of the configuration root.
+ *
+ * @param sPackage
+ * name of the configuration package.
+ *
+ * @param bLanguagepack
+ * force creation of a special header,
+ * which is needed for language packs only.
+ *
+ * @return [java.lang.String]
+ * the generated xml header.
+
+*/
+ public static java.lang.String generateHeader(java.lang.String sVersion ,
+ java.lang.String sEncoding ,
+ java.lang.String sPath ,
+ java.lang.String sPackage ,
+ boolean bLanguagePack)
+ {
+ java.lang.StringBuffer sHeader = new java.lang.StringBuffer(256);
+
+ if (bLanguagePack)
+ {
+ sHeader.append("<?xml version=\"");
+ sHeader.append(sVersion);
+ sHeader.append("\" encoding=\"");
+ sHeader.append(sEncoding);
+ sHeader.append("\"?>\n");
+ sHeader.append("<oor:component-data oor:package=\"");
+ sHeader.append(sPath);
+ sHeader.append("\" oor:name=\"");
+ sHeader.append(sPackage);
+ sHeader.append("\" xmlns:install=\"http://openoffice.org/2004/installation\"");
+ sHeader.append(" xmlns:oor=\"http://openoffice.org/2001/registry\"");
+ sHeader.append(" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"");
+ sHeader.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
+ }
+ else
+ {
+ sHeader.append("<?xml version=\"");
+ sHeader.append(sVersion);
+ sHeader.append("\" encoding=\"");
+ sHeader.append(sEncoding);
+ sHeader.append("\"?>\n<!DOCTYPE oor:component-data SYSTEM \"../../../../component-update.dtd\">\n");
+ sHeader.append("<oor:component-data xmlns:oor=\"http://openoffice.org/2001/registry\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" oor:package=\"");
+ sHeader.append(sPath);
+ sHeader.append("\" oor:name=\"");
+ sHeader.append(sPackage);
+ sHeader.append("\">\n");
+ }
+
+ return sHeader.toString();
+ }
+
+ public static java.lang.String generateFooter()
+ {
+ return "</oor:component-data>\n";
+ }
+}
diff --git a/l10ntools/source/filter/utils/makefile.mk b/l10ntools/source/filter/utils/makefile.mk
new file mode 100644
index 000000000000..4025c54b2c38
--- /dev/null
+++ b/l10ntools/source/filter/utils/makefile.mk
@@ -0,0 +1,57 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.9.98.2 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ = ..$/..$/..
+TARGET = FCFGUtils
+PRJNAME = l10ntools
+PACKAGE = com$/sun$/star$/filter$/config$/tools$/utils
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE: settings.mk
+
+#----- compile .java files -----------------------------------------
+
+
+JAVACLASSFILES = \
+ $(CLASSDIR)$/$(PACKAGE)$/AnalyzeStartupLog.class \
+ $(CLASSDIR)$/$(PACKAGE)$/ConfigHelper.class \
+ $(CLASSDIR)$/$(PACKAGE)$/Logger.class \
+ $(CLASSDIR)$/$(PACKAGE)$/FileHelper.class \
+ $(CLASSDIR)$/$(PACKAGE)$/MalformedCommandLineException.class \
+ $(CLASSDIR)$/$(PACKAGE)$/Cache.class \
+ $(CLASSDIR)$/$(PACKAGE)$/XMLHelper.class
+
+MAXLINELENGTH = 100000
+
+# --- targets -----------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/l10ntools/source/gsicheck.cxx b/l10ntools/source/gsicheck.cxx
new file mode 100644
index 000000000000..aa3b8157952d
--- /dev/null
+++ b/l10ntools/source/gsicheck.cxx
@@ -0,0 +1,1177 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: gsicheck.cxx,v $
+ * $Revision: 1.29 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <stdio.h>
+#include <tools/fsys.hxx>
+#include <tools/stream.hxx>
+#include <tools/list.hxx>
+
+// local includes
+#include "tagtest.hxx"
+#include "gsicheck.hxx"
+
+#define MAX_GID_LID_LEN 250
+
+/*****************************************************************************/
+void PrintMessage( ByteString aType, ByteString aMsg, ByteString aPrefix,
+ ByteString aContext, BOOL bPrintContext, ULONG nLine, ByteString aUniqueId = ByteString() )
+/*****************************************************************************/
+{
+ fprintf( stdout, "%s %s, Line %lu", aType.GetBuffer(), aPrefix.GetBuffer(), nLine );
+ if ( aUniqueId.Len() )
+ fprintf( stdout, ", UniqueID %s", aUniqueId.GetBuffer() );
+ fprintf( stdout, ": %s", aMsg.GetBuffer() );
+
+ if ( bPrintContext )
+ fprintf( stdout, " \"%s\"", aContext.GetBuffer() );
+ fprintf( stdout, "\n" );
+}
+
+/*****************************************************************************/
+void PrintError( ByteString aMsg, ByteString aPrefix,
+ ByteString aContext, BOOL bPrintContext, ULONG nLine, ByteString aUniqueId = ByteString() )
+/*****************************************************************************/
+{
+ PrintMessage( "Error:", aMsg, aPrefix, aContext, bPrintContext, nLine, aUniqueId );
+}
+
+BOOL LanguageOK( ByteString aLang )
+{
+ if ( !aLang.Len() )
+ return FALSE;
+
+ if ( aLang.IsNumericAscii() )
+ return TRUE;
+
+ if ( aLang.GetTokenCount( '-' ) == 1 )
+ return aLang.IsAlphaAscii() && aLang.IsLowerAscii();
+ else if ( aLang.GetTokenCount( '-' ) == 2 )
+ {
+ ByteString aTok0( aLang.GetToken( 0, '-' ) );
+ ByteString aTok1( aLang.GetToken( 1, '-' ) );
+ return aTok0.Len() && aTok0.IsAlphaAscii() && aTok0.IsLowerAscii()
+ && aTok1.Len() && aTok1.IsAlphaAscii() && aTok1.IsUpperAscii()
+ && !aTok1.EqualsIgnoreCaseAscii( aTok0 );
+ }
+
+ return FALSE;
+}
+
+
+//
+// class LazySvFileStream
+//
+
+
+class LazySvFileStream : public SvFileStream
+{
+
+private:
+ String aFileName;
+ BOOL bOpened;
+ StreamMode eOpenMode;
+
+public:
+ LazySvFileStream()
+ : aFileName()
+ , bOpened( FALSE )
+ , eOpenMode( 0 )
+ {};
+
+ void SetOpenParams( const String& rFileName, StreamMode eOpenModeP )
+ {
+ aFileName = rFileName;
+ eOpenMode = eOpenModeP;
+ };
+
+ void LazyOpen();
+};
+
+void LazySvFileStream::LazyOpen()
+{
+ if ( !bOpened )
+ {
+ Open( aFileName, eOpenMode );
+ if ( !IsOpen())
+ {
+ fprintf( stderr, "\nERROR: Could not open Output-File %s!\n\n", ByteString( aFileName, RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
+ exit ( 4 );
+ }
+ bOpened = TRUE;
+ }
+}
+
+
+//
+// class GSILine
+//
+
+/*****************************************************************************/
+GSILine::GSILine( const ByteString &rLine, ULONG nLine )
+/*****************************************************************************/
+ : ByteString( rLine )
+ , nLineNumber( nLine )
+ , bOK( TRUE )
+ , bFixed ( FALSE )
+{
+ if ( rLine.GetTokenCount( '\t' ) == 15 )
+ {
+ aFormat = FORMAT_SDF;
+ aUniqId = rLine.GetToken( 0, '\t' );
+ aUniqId.Append("/").Append( rLine.GetToken( 1, '\t' ) ).Append("/").Append( rLine.GetToken( 3, '\t' ) ).Append("/").Append( rLine.GetToken( 4, '\t' ) ).Append("/").Append( rLine.GetToken( 5, '\t' ) ).Append("/").Append( rLine.GetToken( 6, '\t' ) ).Append("/").Append( rLine.GetToken( 7, '\t' ) );
+ aLineType = "";
+ aLangId = rLine.GetToken( 9, '\t' );
+ aText = rLine.GetToken( 10, '\t' );
+ aQuickHelpText = rLine.GetToken( 12, '\t' );
+ aTitle = rLine.GetToken( 13, '\t' );
+
+ // do some more format checks here
+ if ( !rLine.GetToken( 8, '\t' ).IsNumericAscii() )
+ {
+ PrintError( "The length field does not contain a number!", "Line format", rLine.GetToken( 8, '\t' ), TRUE, GetLineNumber(), GetUniqId() );
+ NotOK();
+ }
+ if ( !LanguageOK( aLangId ) )
+ {
+ PrintError( "The Language is invalid!", "Line format", aLangId, TRUE, GetLineNumber(), GetUniqId() );
+ NotOK();
+ }
+ // limit GID and LID to MAX_GID_LID_LEN chars each for database conformity, see #137575#
+ if ( rLine.GetToken( 4, '\t' ).Len() > MAX_GID_LID_LEN || rLine.GetToken( 5, '\t' ).Len() > MAX_GID_LID_LEN )
+ {
+ PrintError( ByteString("GID and LID may only be ").Append( ByteString::CreateFromInt32(MAX_GID_LID_LEN) ).Append( " chars long each!" ), "Line format", aLangId, TRUE, GetLineNumber(), GetUniqId() );
+ NotOK();
+ }
+ }
+ else // allow tabs in gsi files
+ {
+ aFormat = FORMAT_GSI;
+ ByteString sTmp( rLine );
+ USHORT nPos = sTmp.Search( "($$)" );
+ USHORT nStart = 0;
+ if ( nPos != STRING_NOTFOUND )
+ {
+ aUniqId = sTmp.Copy( nStart, nPos - nStart );
+ nStart = nPos + 4; // + length of the delemiter
+ nPos = sTmp.Search( "($$)", nStart );
+ }
+ if ( nPos != STRING_NOTFOUND )
+ {
+ aLineType = sTmp.Copy( nStart, nPos - nStart );
+ nStart = nPos + 4; // + length of the delemiter
+ nPos = sTmp.Search( "($$)", nStart );
+ aUniqId.Append( "/" );
+ aUniqId.Append( aLineType );
+ }
+ if ( nPos != STRING_NOTFOUND )
+ {
+ aLangId = sTmp.Copy( nStart, nPos - nStart );
+ nStart = nPos + 4; // + length of the delemiter
+ nPos = sTmp.Search( "($$)", nStart );
+ }
+ if ( nPos != STRING_NOTFOUND )
+ {
+// ByteString aStatus = sTmp.Copy( nStart, nPos - nStart ); // ext int ...
+ nStart = nPos + 4; // + length of the delemiter
+ }
+ if ( nPos != STRING_NOTFOUND )
+ aText = sTmp.Copy( nStart );
+ else
+ aFormat = FORMAT_UNKNOWN;
+ }
+
+ if ( FORMAT_UNKNOWN == GetLineFormat() )
+ NotOK();
+}
+
+/*****************************************************************************/
+void GSILine::NotOK()
+/*****************************************************************************/
+{
+ bOK = FALSE;
+}
+
+/*****************************************************************************/
+void GSILine::ReassembleLine()
+/*****************************************************************************/
+{
+ ByteString aReassemble;
+ if ( GetLineFormat() == FORMAT_SDF )
+ {
+ USHORT i;
+ for ( i = 0 ; i < 10 ; i++ )
+ {
+ aReassemble.Append( GetToken( i, '\t' ) );
+ aReassemble.Append( "\t" );
+ }
+ aReassemble.Append( aText );
+ aReassemble.Append( "\t" );
+ aReassemble.Append( GetToken( 11, '\t' ) ); // should be empty but there are some places in sc. Not reflected to sources!!
+ aReassemble.Append( "\t" );
+ aReassemble.Append( aQuickHelpText );
+ aReassemble.Append( "\t" );
+ aReassemble.Append( aTitle );
+ for ( i = 14 ; i < 15 ; i++ )
+ {
+ aReassemble.Append( "\t" );
+ aReassemble.Append( GetToken( i, '\t' ) );
+ }
+ *(ByteString*)this = aReassemble;
+ }
+ else if ( GetLineFormat() == FORMAT_GSI )
+ {
+ USHORT nPos = Search( "($$)" );
+ USHORT nStart = 0;
+ if ( nPos != STRING_NOTFOUND )
+ {
+ nStart = nPos + 4; // + length of the delemiter
+ nPos = Search( "($$)", nStart );
+ }
+ if ( nPos != STRING_NOTFOUND )
+ {
+ nStart = nPos + 4; // + length of the delemiter
+ nPos = Search( "($$)", nStart );
+ }
+ if ( nPos != STRING_NOTFOUND )
+ {
+ nStart = nPos + 4; // + length of the delemiter
+ nPos = Search( "($$)", nStart );
+ }
+ if ( nPos != STRING_NOTFOUND )
+ {
+ nStart = nPos + 4; // + length of the delemiter
+ }
+ if ( nPos != STRING_NOTFOUND )
+ {
+ aReassemble = Copy( 0, nStart );
+ aReassemble += aText;
+ *(ByteString*)this = aReassemble;
+ }
+ else
+ PrintError( "Cannot reassemble GSI line (internal Error).", "Line format", "", FALSE, GetLineNumber(), GetUniqId() );
+ }
+ else
+ PrintError( "Cannot reassemble line of unknown type (internal Error).", "Line format", "", FALSE, GetLineNumber(), GetUniqId() );
+}
+
+//
+// class GSIBlock
+//
+/*****************************************************************************/
+GSIBlock::GSIBlock( BOOL PbPrintContext, BOOL bSource, BOOL bTrans, BOOL bRef, BOOL bAllowKID, BOOL bAllowSusp )
+/*****************************************************************************/
+ : pSourceLine( NULL )
+ , pReferenceLine( NULL )
+ , bPrintContext( PbPrintContext )
+ , bCheckSourceLang( bSource )
+ , bCheckTranslationLang( bTrans )
+ , bReference( bRef )
+ , bAllowKeyIDs( bAllowKID )
+ , bAllowSuspicious( bAllowSusp )
+ , bHasBlockError( FALSE )
+{
+}
+
+/*****************************************************************************/
+GSIBlock::~GSIBlock()
+/*****************************************************************************/
+{
+ delete pSourceLine;
+ delete pReferenceLine;
+
+ for ( ULONG i = 0; i < Count(); i++ )
+ delete ( GetObject( i ));
+}
+
+/*****************************************************************************/
+void GSIBlock::InsertLine( GSILine* pLine, ByteString aSourceLang)
+/*****************************************************************************/
+{
+ if ( pLine->GetLanguageId().Equals( aSourceLang ) )
+ {
+ if ( pSourceLine )
+ {
+ PrintError( "Source Language entry double. Treating as Translation.", "File format", "", pLine->GetLineNumber(), pLine->GetUniqId() );
+ bHasBlockError = TRUE;
+ pSourceLine->NotOK();
+ pLine->NotOK();
+ }
+ else
+ {
+ pSourceLine = pLine;
+ return;
+ }
+ }
+ ULONG nPos = 0;
+
+ if ( aSourceLang.Len() ) // only check blockstructure if source lang is given
+ {
+ while ( nPos < Count() )
+ {
+ if ( GetObject( nPos )->GetLanguageId().Equals( pLine->GetLanguageId() ) )
+ {
+ PrintError( "Translation Language entry double. Checking both.", "File format", "", pLine->GetLineNumber(), pLine->GetUniqId() );
+ bHasBlockError = TRUE;
+ GetObject( nPos )->NotOK();
+ pLine->NotOK();
+ }
+ nPos++;
+ }
+ }
+ Insert( pLine, LIST_APPEND );
+}
+
+/*****************************************************************************/
+void GSIBlock::SetReferenceLine( GSILine* pLine )
+/*****************************************************************************/
+{
+ pReferenceLine = pLine;
+}
+
+/*****************************************************************************/
+void GSIBlock::PrintMessage( ByteString aType, ByteString aMsg, ByteString aPrefix,
+ ByteString aContext, ULONG nLine, ByteString aUniqueId )
+/*****************************************************************************/
+{
+ ::PrintMessage( aType, aMsg, aPrefix, aContext, bPrintContext, nLine, aUniqueId );
+}
+
+/*****************************************************************************/
+void GSIBlock::PrintError( ByteString aMsg, ByteString aPrefix,
+ ByteString aContext, ULONG nLine, ByteString aUniqueId )
+/*****************************************************************************/
+{
+ PrintMessage( "Error:", aMsg, aPrefix, aContext, nLine, aUniqueId );
+}
+
+/*****************************************************************************/
+void GSIBlock::PrintList( ParserMessageList *pList, ByteString aPrefix,
+ GSILine *pLine )
+/*****************************************************************************/
+{
+ ULONG i;
+ for ( i = 0 ; i < pList->Count() ; i++ )
+ {
+ ParserMessage *pMsg = pList->GetObject( i );
+ ByteString aContext;
+ if ( bPrintContext )
+ {
+ if ( pMsg->GetTagBegin() == STRING_NOTFOUND )
+ aContext = pLine->GetText().Copy( 0, 300 );
+ else
+ aContext = pLine->Copy( pMsg->GetTagBegin()-150, 300 );
+ aContext.EraseTrailingChars(' ');
+ aContext.EraseLeadingChars(' ');
+ }
+
+ PrintMessage( pMsg->Prefix(), pMsg->GetErrorText(), aPrefix, aContext, pLine->GetLineNumber(), pLine->GetUniqId() );
+ }
+}
+
+/*****************************************************************************/
+BOOL GSIBlock::IsUTF8( const ByteString &aTestee, BOOL bFixTags, USHORT &nErrorPos, ByteString &aErrorMsg, BOOL &bHasBeenFixed, ByteString &aFixed ) const
+/*****************************************************************************/
+{
+ String aUTF8Tester( aTestee, RTL_TEXTENCODING_UTF8 );
+ if ( STRING_MATCH != (nErrorPos = ByteString( aUTF8Tester, RTL_TEXTENCODING_UTF8 ).Match( aTestee )) )
+ {
+ aUTF8Tester = String( aTestee.GetBuffer(), nErrorPos, RTL_TEXTENCODING_UTF8 );
+ nErrorPos = aUTF8Tester.Len();
+ aErrorMsg = ByteString( "UTF8 Encoding seems to be broken" );
+ return FALSE;
+ }
+
+ nErrorPos = aUTF8Tester.SearchChar( String::CreateFromAscii( "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f" ).GetBuffer() );
+ if ( nErrorPos != STRING_NOTFOUND )
+ {
+ aErrorMsg = ByteString( "String contains illegal character" );
+ return FALSE;
+ }
+
+ if ( bFixTags )
+ {
+ bHasBeenFixed = FALSE;
+ aFixed.Erase();
+ }
+
+ if ( !bAllowKeyIDs )
+ {
+ BOOL bIsKeyID = FALSE;
+ BOOL bNewId = FALSE;
+ ByteString aID( aTestee );
+ USHORT nAfterID = 0;
+
+ if ( aTestee.Equals( "{&", 0, 2 ) )
+ { // check for strings from instset_native like "{&Tahoma8}335795.Installation Wiza ..."
+ USHORT nTagEnd = aTestee.Search( '}' );
+ if ( nTagEnd != STRING_NOTFOUND )
+ {
+ if ( bFixTags )
+ aFixed = aTestee.Copy( 0, nTagEnd+1 );
+ nErrorPos = nTagEnd+1;
+ aID = aTestee.Copy( nTagEnd+1 );
+ nAfterID = nTagEnd+1;
+ }
+ }
+
+ ByteString aDelimiter( (String)String( sal_Unicode(0x2016) ), RTL_TEXTENCODING_UTF8 );
+
+ if ( aID.Equals( aDelimiter, 6, aDelimiter.Len() ) )
+ { // New KeyId 6 Letters, digits and spechial chars followed by delimiter
+ bNewId = TRUE;
+ nErrorPos = 1;
+ aID = aID.Copy( 0, 6 );
+ nAfterID += 6;
+ nAfterID = nAfterID + aDelimiter.Len();
+ }
+ else if ( ( aID.GetChar(6) == '*' ) && aID.Equals( aDelimiter, 7, aDelimiter.Len() ) )
+ { // New KeyId 6 Letters, digits and spechial chars followed by '*delimiter' to indicate translation in progress
+ bNewId = TRUE;
+ nErrorPos = 1;
+ aID = aID.Copy( 0, 6 );
+ nAfterID += 7;
+ nAfterID = nAfterID + aDelimiter.Len();
+ }
+ else if ( aID.GetTokenCount( '.' ) > 1 )
+ { // test for old KeyIDs 5 to 6 digits followed by a dot '44373.'
+ bNewId = FALSE;
+ nErrorPos = 1;
+ aID = aID.GetToken( 0, '.' );
+ nAfterID = nAfterID + aID.Len();
+ }
+ else
+ {
+ aID.Erase();
+ }
+
+ if ( bNewId )
+ {
+ if ( aID.Len() == 6 )
+ {
+ bIsKeyID = TRUE;
+ ByteString aDigits("0123456789abcdefghijklmnopqrstuvwxyz+-<=>");
+ for ( USHORT i=0 ; i < aID.Len() ;i++ )
+ {
+ if ( aDigits.Search( aID.GetChar(i) ) == STRING_NOTFOUND )
+ bIsKeyID = FALSE;
+ }
+ }
+ }
+ else
+ {
+ if ( aID.Len() > 0 && aID.GetChar(aID.Len()-1) == '*' )
+ aID.Erase( aID.Len()-1 );
+
+ if ( aID.IsNumericAscii() && aID.Len() >= 5 )
+ bIsKeyID = TRUE;
+ }
+
+ if ( bIsKeyID )
+ {
+ aErrorMsg = ByteString( "String contains KeyID" );
+ if ( bFixTags )
+ {
+ aFixed += aTestee.Copy( nAfterID );
+ bHasBeenFixed = TRUE;
+ aErrorMsg = ByteString( "FIXED String containing KeyID" );
+ }
+ else
+ aErrorMsg = ByteString( "String contains KeyID" );
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/*****************************************************************************/
+BOOL GSIBlock::TestUTF8( GSILine* pTestee, BOOL bFixTags )
+/*****************************************************************************/
+{
+ USHORT nErrorPos = 0;
+ ByteString aErrorMsg;
+ BOOL bError = FALSE;
+ ByteString aFixed;
+ BOOL bHasBeenFixed = FALSE;
+ if ( !IsUTF8( pTestee->GetText(), bFixTags, nErrorPos, aErrorMsg, bHasBeenFixed, aFixed ) )
+ {
+ ByteString aContext( pTestee->GetText().Copy( nErrorPos, 20 ) );
+ PrintError( aErrorMsg.Append(" in Text at Position " ).Append( ByteString::CreateFromInt32( nErrorPos ) ), "Text format", aContext, pTestee->GetLineNumber(), pTestee->GetUniqId() );
+ bError = TRUE;
+ if ( bHasBeenFixed )
+ {
+ pTestee->SetText( aFixed );
+ pTestee->SetFixed();
+ }
+ }
+ if ( !IsUTF8( pTestee->GetQuickHelpText(), bFixTags, nErrorPos, aErrorMsg, bHasBeenFixed, aFixed ) )
+ {
+ ByteString aContext( pTestee->GetQuickHelpText().Copy( nErrorPos, 20 ) );
+ PrintError( aErrorMsg.Append(" in QuickHelpText at Position " ).Append( ByteString::CreateFromInt32( nErrorPos ) ), "Text format", aContext, pTestee->GetLineNumber(), pTestee->GetUniqId() );
+ bError = TRUE;
+ if ( bHasBeenFixed )
+ {
+ pTestee->SetQuickHelpText( aFixed );
+ pTestee->SetFixed();
+ }
+ }
+ if ( !IsUTF8( pTestee->GetTitle(), bFixTags, nErrorPos, aErrorMsg, bHasBeenFixed, aFixed ) )
+ {
+ ByteString aContext( pTestee->GetTitle().Copy( nErrorPos, 20 ) );
+ PrintError( aErrorMsg.Append(" in Title at Position " ).Append( ByteString::CreateFromInt32( nErrorPos ) ), "Text format", aContext, pTestee->GetLineNumber(), pTestee->GetUniqId() );
+ bError = TRUE;
+ if ( bHasBeenFixed )
+ {
+ pTestee->SetTitle( aFixed );
+ pTestee->SetFixed();
+ }
+ }
+ if ( bError )
+ pTestee->NotOK();
+ return !bError;
+}
+
+
+/*****************************************************************************/
+BOOL GSIBlock::HasSuspiciousChars( GSILine* pTestee, GSILine* pSource )
+/*****************************************************************************/
+{
+ USHORT nPos = 0;
+ if ( !bAllowSuspicious && ( nPos = pTestee->GetText().Search("??")) != STRING_NOTFOUND )
+ if ( pSource->GetText().Search("??") == STRING_NOTFOUND )
+ {
+ String aUTF8Tester = String( pTestee->GetText(), 0, nPos, RTL_TEXTENCODING_UTF8 );
+ USHORT nErrorPos = aUTF8Tester.Len();
+ ByteString aContext( pTestee->GetText().Copy( nPos, 20 ) );
+ PrintError( ByteString("Found double questionmark in translation only. Looks like an encoding problem at Position " ).Append( ByteString::CreateFromInt32( nErrorPos ) ), "Text format", aContext, pTestee->GetLineNumber(), pTestee->GetUniqId() );
+ pTestee->NotOK();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*****************************************************************************/
+BOOL GSIBlock::CheckSyntax( ULONG nLine, BOOL bRequireSourceLine, BOOL bFixTags )
+/*****************************************************************************/
+{
+ static LingTest aTester;
+ BOOL bHasError = FALSE;
+
+ if ( !pSourceLine )
+ {
+ if ( bRequireSourceLine )
+ {
+ PrintError( "No source language entry defined!", "File format", "", nLine );
+ bHasBlockError = TRUE;
+ }
+ }
+ else
+ {
+ aTester.CheckReference( pSourceLine );
+ if ( pSourceLine->HasMessages() )
+ {
+ PrintList( pSourceLine->GetMessageList(), "ReferenceString", pSourceLine );
+ pSourceLine->NotOK();
+ bHasError = TRUE;
+ }
+ }
+ if ( bReference )
+ {
+ if ( !pReferenceLine )
+ {
+ GSILine *pSource;
+ if ( pSourceLine )
+ pSource = pSourceLine;
+ else
+ pSource = GetObject( 0 ); // get some other line
+ if ( pSource )
+ PrintError( "No reference line found. Entry is new in source file", "File format", "", pSource->GetLineNumber(), pSource->GetUniqId() );
+ else
+ PrintError( "No reference line found. Entry is new in source file", "File format", "", nLine );
+ bHasBlockError = TRUE;
+ }
+ else
+ {
+ if ( pSourceLine && !pSourceLine->Equals( *pReferenceLine ) )
+ {
+ xub_StrLen nPos = pSourceLine->Match( *pReferenceLine );
+ ByteString aContext( pReferenceLine->Copy( nPos - 5, 15) );
+ aContext.Append( "\" --> \"" ).Append( pSourceLine->Copy( nPos - 5, 15) );
+ PrintError( "Source Language Entry has changed.", "File format", aContext, pSourceLine->GetLineNumber(), pSourceLine->GetUniqId() );
+ pSourceLine->NotOK();
+ bHasError = TRUE;
+ }
+ }
+ }
+
+ if ( pSourceLine )
+ bHasError |= !TestUTF8( pSourceLine, bFixTags );
+
+ ULONG i;
+ for ( i = 0; i < Count(); i++ )
+ {
+ aTester.CheckTestee( GetObject( i ), pSourceLine != NULL, bFixTags );
+ if ( GetObject( i )->HasMessages() || aTester.HasCompareWarnings() )
+ {
+ if ( GetObject( i )->HasMessages() || aTester.GetCompareWarnings().HasErrors() )
+ GetObject( i )->NotOK();
+ bHasError = TRUE;
+ PrintList( GetObject( i )->GetMessageList(), "Translation", GetObject( i ) );
+ PrintList( &(aTester.GetCompareWarnings()), "Translation Tag Missmatch", GetObject( i ) );
+ }
+ bHasError |= !TestUTF8( GetObject( i ), bFixTags );
+ if ( pSourceLine )
+ bHasError |= HasSuspiciousChars( GetObject( i ), pSourceLine );
+ }
+
+ return bHasError || bHasBlockError;
+}
+
+void GSIBlock::WriteError( LazySvFileStream &aErrOut, BOOL bRequireSourceLine )
+{
+ if ( pSourceLine && pSourceLine->IsOK() && bCheckSourceLang && !bHasBlockError )
+ return;
+
+ BOOL bHasError = FALSE;
+ BOOL bCopyAll = ( !pSourceLine && bRequireSourceLine ) || ( pSourceLine && !pSourceLine->IsOK() && !bCheckTranslationLang ) || bHasBlockError;
+ ULONG i;
+ for ( i = 0; i < Count(); i++ )
+ {
+ if ( !GetObject( i )->IsOK() || bCopyAll )
+ {
+ bHasError = TRUE;
+ aErrOut.LazyOpen();
+ aErrOut.WriteLine( *GetObject( i ) );
+ }
+ }
+
+ if ( pSourceLine && ( bHasError || !pSourceLine->IsOK() ) && !( !bHasError && bCheckTranslationLang ) )
+ {
+ aErrOut.LazyOpen();
+ aErrOut.WriteLine( *pSourceLine );
+ }
+}
+
+void GSIBlock::WriteCorrect( LazySvFileStream &aOkOut, BOOL bRequireSourceLine )
+{
+ if ( ( !pSourceLine && bRequireSourceLine ) || ( pSourceLine && !pSourceLine->IsOK() && !bCheckTranslationLang ) )
+ return;
+
+ BOOL bHasOK = FALSE;
+ ULONG i;
+ for ( i = 0; i < Count(); i++ )
+ {
+ if ( ( GetObject( i )->IsOK() || bCheckSourceLang ) && !bHasBlockError )
+ {
+ bHasOK = TRUE;
+ aOkOut.LazyOpen();
+ aOkOut.WriteLine( *GetObject( i ) );
+ }
+ }
+
+ if ( ( pSourceLine && pSourceLine->IsOK() && ( Count() || !bCheckTranslationLang ) ) || ( bHasOK && bCheckTranslationLang ) )
+ {
+ aOkOut.LazyOpen();
+ aOkOut.WriteLine( *pSourceLine );
+ }
+}
+
+void GSIBlock::WriteFixed( LazySvFileStream &aFixOut, BOOL /*bRequireSourceLine*/ )
+{
+ if ( pSourceLine && !pSourceLine->IsFixed() && bCheckSourceLang )
+ return;
+
+ BOOL bHasFixes = FALSE;
+ ULONG i;
+ for ( i = 0; i < Count(); i++ )
+ {
+ if ( GetObject( i )->IsFixed() )
+ {
+ bHasFixes = TRUE;
+ aFixOut.LazyOpen();
+ aFixOut.WriteLine( *GetObject( i ) );
+ }
+ }
+
+ if ( pSourceLine && ( bHasFixes || pSourceLine->IsFixed() ) )
+ {
+ aFixOut.LazyOpen();
+ aFixOut.WriteLine( *pSourceLine );
+ }
+}
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+void Help()
+/*****************************************************************************/
+{
+ fprintf( stdout, "\n" );
+ fprintf( stdout, "gsicheck Version 1.9.0 (c)1999 - 2006 by SUN Microsystems\n" );
+ fprintf( stdout, "=========================================================\n" );
+ fprintf( stdout, "\n" );
+ fprintf( stdout, "gsicheck checks the syntax of tags in GSI-Files and SDF-Files\n" );
+ fprintf( stdout, " checks for inconsistencies and malicious UTF8 encoding\n" );
+ fprintf( stdout, " checks tags in Online Help\n" );
+ fprintf( stdout, " checks for *new* KeyIDs and relax GID/LID length to %s\n", ByteString::CreateFromInt32(MAX_GID_LID_LEN).GetBuffer() );
+ fprintf( stdout, "\n" );
+ fprintf( stdout, "Syntax: gsicheck [ -c ] [-f] [ -we ] [ -wef ErrorFilename ] [ -wc ]\n" );
+ fprintf( stdout, " [ -wcf CorrectFilename ] [ -s | -t ] [ -l LanguageID ]\n" );
+ fprintf( stdout, " [ -r ReferenceFile ] filename\n" );
+ fprintf( stdout, "\n" );
+ fprintf( stdout, "-c Add context to error message (Print the line containing the error)\n" );
+ fprintf( stdout, "-f try to fix errors. See also -wf -wff \n" );
+ fprintf( stdout, "-wf Write File containing all fixed parts\n" );
+ fprintf( stdout, "-wff Same as above but give own filename\n" );
+ fprintf( stdout, "-we Write File containing all errors\n" );
+ fprintf( stdout, "-wef Same as above but give own filename\n" );
+ fprintf( stdout, "-wc Write File containing all correct parts\n" );
+ fprintf( stdout, "-wcf Same as above but give own filename\n" );
+ fprintf( stdout, "-s Check only source language. Should be used before handing out to vendor.\n" );
+ fprintf( stdout, "-t Check only Translation language(s). Should be used before merging.\n" );
+ fprintf( stdout, "-k Allow KeyIDs to be present in strings\n" );
+ fprintf( stdout, "-e disable encoding checks. E.g.: double questionmark \'??\' which may be the\n" );
+ fprintf( stdout, " result of false conversions\n" );
+ fprintf( stdout, "-l ISO Languagecode or numerical 2 digits Identifier of the source language.\n" );
+ fprintf( stdout, " Default is en-US. Use \"\" (empty string) or 'none'\n" );
+ fprintf( stdout, " to disable source language dependent checks\n" );
+ fprintf( stdout, "-r Reference filename to check that source language entries\n" );
+ fprintf( stdout, " have not been changed\n" );
+ fprintf( stdout, "\n" );
+}
+
+/*****************************************************************************/
+#if defined(UNX) || defined(OS2)
+int main( int argc, char *argv[] )
+#else
+int _cdecl main( int argc, char *argv[] )
+#endif
+/*****************************************************************************/
+{
+
+ BOOL bError = FALSE;
+ BOOL bPrintContext = FALSE;
+ BOOL bCheckSourceLang = FALSE;
+ BOOL bCheckTranslationLang = FALSE;
+ BOOL bWriteError = FALSE;
+ BOOL bWriteCorrect = FALSE;
+ BOOL bWriteFixed = FALSE;
+ BOOL bFixTags = FALSE;
+ BOOL bAllowKID = FALSE;
+ BOOL bAllowSuspicious = FALSE;
+ String aErrorFilename;
+ String aCorrectFilename;
+ String aFixedFilename;
+ BOOL bFileHasError = FALSE;
+ ByteString aSourceLang( "en-US" ); // English is default
+ ByteString aFilename;
+ ByteString aReferenceFilename;
+ BOOL bReferenceFile = FALSE;
+ for ( USHORT i = 1 ; i < argc ; i++ )
+ {
+ if ( *argv[ i ] == '-' )
+ {
+ switch (*(argv[ i ]+1))
+ {
+ case 'c':bPrintContext = TRUE;
+ break;
+ case 'w':
+ {
+ if ( (*(argv[ i ]+2)) == 'e' )
+ {
+ if ( (*(argv[ i ]+3)) == 'f' )
+ if ( (i+1) < argc )
+ {
+ aErrorFilename = String( argv[ i+1 ], RTL_TEXTENCODING_ASCII_US );
+ bWriteError = TRUE;
+ i++;
+ }
+ else
+ {
+ fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
+ bError = TRUE;
+ }
+ else
+ bWriteError = TRUE;
+ }
+ else if ( (*(argv[ i ]+2)) == 'c' )
+ if ( (*(argv[ i ]+3)) == 'f' )
+ if ( (i+1) < argc )
+ {
+ aCorrectFilename = String( argv[ i+1 ], RTL_TEXTENCODING_ASCII_US );
+ bWriteCorrect = TRUE;
+ i++;
+ }
+ else
+ {
+ fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
+ bError = TRUE;
+ }
+ else
+ bWriteCorrect = TRUE;
+ else if ( (*(argv[ i ]+2)) == 'f' )
+ if ( (*(argv[ i ]+3)) == 'f' )
+ if ( (i+1) < argc )
+ {
+ aFixedFilename = String( argv[ i+1 ], RTL_TEXTENCODING_ASCII_US );
+ bWriteFixed = TRUE;
+ bFixTags = TRUE;
+ i++;
+ }
+ else
+ {
+ fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
+ bError = TRUE;
+ }
+ else
+ {
+ bWriteFixed = TRUE;
+ bFixTags = TRUE;
+ }
+ else
+ {
+ fprintf( stderr, "\nERROR: Unknown Switch %s!\n\n", argv[ i ] );
+ bError = TRUE;
+ }
+ }
+ break;
+ case 's':bCheckSourceLang = TRUE;
+ break;
+ case 't':bCheckTranslationLang = TRUE;
+ break;
+ case 'l':
+ {
+ if ( (i+1) < argc )
+ {
+ aSourceLang = ByteString( argv[ i+1 ] );
+ if ( aSourceLang.EqualsIgnoreCaseAscii( "none" ) )
+ aSourceLang.Erase();
+ i++;
+ }
+ else
+ {
+ fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
+ bError = TRUE;
+ }
+ }
+ break;
+ case 'r':
+ {
+ if ( (i+1) < argc )
+ {
+ aReferenceFilename = argv[ i+1 ];
+ bReferenceFile = TRUE;
+ i++;
+ }
+ else
+ {
+ fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
+ bError = TRUE;
+ }
+ }
+ break;
+ case 'f':
+ {
+ bFixTags = TRUE;
+ }
+ break;
+ case 'k':
+ {
+ bAllowKID = TRUE;
+ }
+ break;
+ case 'e':
+ {
+ bAllowSuspicious = TRUE;
+ }
+ break;
+ default:
+ fprintf( stderr, "\nERROR: Unknown Switch %s!\n\n", argv[ i ] );
+ bError = TRUE;
+ }
+ }
+ else
+ {
+ if ( !aFilename.Len())
+ aFilename = ByteString( argv[ i ] );
+ else
+ {
+ fprintf( stderr, "\nERROR: Only one filename may be specified!\n\n");
+ bError = TRUE;
+ }
+ }
+ }
+
+
+ if ( !aFilename.Len() || bError )
+ {
+ Help();
+ exit ( 0 );
+ }
+
+ if ( aSourceLang.Len() && !LanguageOK( aSourceLang ) )
+ {
+ fprintf( stderr, "\nERROR: The Language '%s' is invalid!\n\n", aSourceLang.GetBuffer() );
+ Help();
+ exit ( 1 );
+ }
+
+ if ( bCheckSourceLang && bCheckTranslationLang )
+ {
+ fprintf( stderr, "\nERROR: The Options -s and -t are mutually exclusive.\nUse only one of them.\n\n" );
+ Help();
+ exit ( 1 );
+ }
+
+
+
+ DirEntry aSource = DirEntry( String( aFilename, RTL_TEXTENCODING_ASCII_US ));
+ if ( !aSource.Exists()) {
+ fprintf( stderr, "\nERROR: GSI-File %s not found!\n\n", aFilename.GetBuffer() );
+ exit ( 2 );
+ }
+
+ SvFileStream aGSI( String( aFilename, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ );
+ if ( !aGSI.IsOpen()) {
+ fprintf( stderr, "\nERROR: Could not open GSI-File %s!\n\n", aFilename.GetBuffer() );
+ exit ( 3 );
+ }
+
+ SvFileStream aReferenceGSI;
+ if ( bReferenceFile )
+ {
+ DirEntry aReferenceSource = DirEntry( String( aReferenceFilename, RTL_TEXTENCODING_ASCII_US ));
+ if ( !aReferenceSource.Exists()) {
+ fprintf( stderr, "\nERROR: GSI-File %s not found!\n\n", aFilename.GetBuffer() );
+ exit ( 2 );
+ }
+
+ aReferenceGSI.Open( String( aReferenceFilename, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ );
+ if ( !aReferenceGSI.IsOpen()) {
+ fprintf( stderr, "\nERROR: Could not open Input-File %s!\n\n", aFilename.GetBuffer() );
+ exit ( 3 );
+ }
+ }
+
+ LazySvFileStream aOkOut;
+ String aBaseName = aSource.GetBase();
+ if ( bWriteCorrect )
+ {
+ if ( !aCorrectFilename.Len() )
+ {
+ String sTmpBase( aBaseName );
+ sTmpBase += String( "_ok", RTL_TEXTENCODING_ASCII_US );
+ aSource.SetBase( sTmpBase );
+ aCorrectFilename = aSource.GetFull();
+ }
+ aOkOut.SetOpenParams( aCorrectFilename , STREAM_STD_WRITE | STREAM_TRUNC );
+ }
+
+ LazySvFileStream aErrOut;
+ if ( bWriteError )
+ {
+ if ( !aErrorFilename.Len() )
+ {
+ String sTmpBase( aBaseName );
+ sTmpBase += String( "_err", RTL_TEXTENCODING_ASCII_US );
+ aSource.SetBase( sTmpBase );
+ aErrorFilename = aSource.GetFull();
+ }
+ aErrOut.SetOpenParams( aErrorFilename , STREAM_STD_WRITE | STREAM_TRUNC );
+ }
+
+ LazySvFileStream aFixOut;
+ if ( bWriteFixed )
+ {
+ if ( !aFixedFilename.Len() )
+ {
+ String sTmpBase( aBaseName );
+ sTmpBase += String( "_fix", RTL_TEXTENCODING_ASCII_US );
+ aSource.SetBase( sTmpBase );
+ aFixedFilename = aSource.GetFull();
+ }
+ aFixOut.SetOpenParams( aFixedFilename , STREAM_STD_WRITE | STREAM_TRUNC );
+ }
+
+
+ ByteString sReferenceLine;
+ GSILine* pReferenceLine = NULL;
+ ByteString aOldReferenceId("No Valid ID"); // just set to something which can never be an ID
+ ULONG nReferenceLine = 0;
+
+ ByteString sGSILine;
+ GSILine* pGSILine = NULL;
+ ByteString aOldId("No Valid ID"); // just set to something which can never be an ID
+ GSIBlock *pBlock = NULL;
+ ULONG nLine = 0;
+
+ while ( !aGSI.IsEof() )
+ {
+ aGSI.ReadLine( sGSILine );
+ nLine++;
+ pGSILine = new GSILine( sGSILine, nLine );
+ BOOL bDelete = TRUE;
+
+
+ if ( pGSILine->Len() )
+ {
+ if ( FORMAT_UNKNOWN == pGSILine->GetLineFormat() )
+ {
+ PrintError( "Format of line is unknown. Ignoring!", "Line format", pGSILine->Copy( 0,40 ), bPrintContext, pGSILine->GetLineNumber() );
+ pGSILine->NotOK();
+ if ( bWriteError )
+ {
+ bFileHasError = TRUE;
+ aErrOut.LazyOpen();
+ aErrOut.WriteLine( *pGSILine );
+ }
+ }
+ else if ( pGSILine->GetLineType().EqualsIgnoreCaseAscii("res-comment") )
+ { // ignore comment lines, but write them to Correct Items File
+ if ( bWriteCorrect )
+ {
+ aOkOut.LazyOpen();
+ aOkOut.WriteLine( *pGSILine );
+ }
+ }
+ else
+ {
+ ByteString aId = pGSILine->GetUniqId();
+ if ( aId != aOldId )
+ {
+ if ( pBlock )
+ {
+ bFileHasError |= pBlock->CheckSyntax( nLine, aSourceLang.Len() != 0, bFixTags );
+
+ if ( bWriteError )
+ pBlock->WriteError( aErrOut, aSourceLang.Len() != 0 );
+ if ( bWriteCorrect )
+ pBlock->WriteCorrect( aOkOut, aSourceLang.Len() != 0 );
+ if ( bWriteFixed )
+ pBlock->WriteFixed( aFixOut, aSourceLang.Len() != 0 );
+
+ delete pBlock;
+ }
+ pBlock = new GSIBlock( bPrintContext, bCheckSourceLang, bCheckTranslationLang, bReferenceFile, bAllowKID, bAllowSuspicious );
+
+ aOldId = aId;
+
+
+ // find corresponding line in reference file
+ if ( bReferenceFile )
+ {
+ BOOL bContinueSearching = TRUE;
+ while ( ( !aReferenceGSI.IsEof() || pReferenceLine ) && bContinueSearching )
+ {
+ if ( !pReferenceLine )
+ {
+ aReferenceGSI.ReadLine( sReferenceLine );
+ nReferenceLine++;
+ pReferenceLine = new GSILine( sReferenceLine, nReferenceLine );
+ }
+ if ( pReferenceLine->GetLineFormat() != FORMAT_UNKNOWN )
+ {
+ if ( pReferenceLine->GetUniqId() == aId && pReferenceLine->GetLanguageId().Equals( aSourceLang ) )
+ {
+ pBlock->SetReferenceLine( pReferenceLine );
+ pReferenceLine = NULL;
+ }
+ else if ( pReferenceLine->GetUniqId() > aId )
+ {
+// if ( pGSILine->GetLanguageId() == aSourceLang )
+// PrintError( "No reference line found. Entry is new in source file", "File format", "", bPrintContext, pGSILine->GetLineNumber(), aId );
+ bContinueSearching = FALSE;
+ }
+ else
+ {
+ if ( pReferenceLine->GetUniqId() < aId && pReferenceLine->GetLanguageId().Equals( aSourceLang ) )
+ PrintError( "No Entry in source file found. Entry has been removed from source file", "File format", "", bPrintContext, pGSILine->GetLineNumber(), pReferenceLine->GetUniqId() );
+ delete pReferenceLine;
+ pReferenceLine = NULL;
+ }
+ }
+ else
+ {
+ delete pReferenceLine;
+ pReferenceLine = NULL;
+ }
+
+ }
+ }
+
+ }
+
+ pBlock->InsertLine( pGSILine, aSourceLang );
+ bDelete = FALSE;
+ }
+ }
+ if ( bDelete )
+ delete pGSILine;
+
+ }
+ if ( pBlock )
+ {
+ bFileHasError |= pBlock->CheckSyntax( nLine, aSourceLang.Len() != 0, bFixTags );
+
+ if ( bWriteError )
+ pBlock->WriteError( aErrOut, aSourceLang.Len() != 0 );
+ if ( bWriteCorrect )
+ pBlock->WriteCorrect( aOkOut, aSourceLang.Len() != 0 );
+ if ( bWriteFixed )
+ pBlock->WriteFixed( aFixOut, aSourceLang.Len() != 0 );
+
+ delete pBlock;
+ }
+ aGSI.Close();
+
+ if ( bWriteError )
+ aErrOut.Close();
+ if ( bWriteCorrect )
+ aOkOut.Close();
+ if ( bWriteFixed )
+ aFixOut.Close();
+
+ if ( bFileHasError )
+ return 55;
+ else
+ return 0;
+}
diff --git a/l10ntools/source/gsiconv.cxx b/l10ntools/source/gsiconv.cxx
new file mode 100644
index 000000000000..e127e55482da
--- /dev/null
+++ b/l10ntools/source/gsiconv.cxx
@@ -0,0 +1,372 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: gsiconv.cxx,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <stdio.h>
+#include <tools/fsys.hxx>
+#include <tools/stream.hxx>
+
+// local includes
+#include "utf8conv.hxx"
+
+#define GSI_FILE_UNKNOWN 0x0000
+#define GSI_FILE_OLDSTYLE 0x0001
+#define GSI_FILE_L10NFRAMEWORK 0x0002
+
+/*****************************************************************************/
+USHORT GetGSIFileType( SvStream &rStream )
+/*****************************************************************************/
+{
+ USHORT nFileType = GSI_FILE_UNKNOWN;
+
+ ULONG nPos( rStream.Tell());
+ rStream.Seek( STREAM_SEEK_TO_BEGIN );
+
+ ByteString sLine;
+ while( !rStream.IsEof() && !sLine.Len())
+ rStream.ReadLine( sLine );
+
+ if( sLine.Len()) {
+ if( sLine.Search( "($$)" ) != STRING_NOTFOUND )
+ nFileType = GSI_FILE_OLDSTYLE;
+ else
+ nFileType = GSI_FILE_L10NFRAMEWORK;
+ }
+
+ rStream.Seek( nPos );
+
+ return nFileType;
+}
+
+/*****************************************************************************/
+ByteString GetGSILineId( const ByteString &rLine, USHORT nFileType )
+/*****************************************************************************/
+{
+ ByteString sId;
+ switch ( nFileType ) {
+ case GSI_FILE_OLDSTYLE:
+ sId = rLine;
+ sId.SearchAndReplaceAll( "($$)", "\t" );
+ sId = sId.GetToken( 0, '\t' );
+ break;
+
+ case GSI_FILE_L10NFRAMEWORK:
+ sId = rLine.GetToken( 0, '\t' );
+ sId += "\t";
+ sId += rLine.GetToken( 1, '\t' );
+ sId += "\t";
+ sId += rLine.GetToken( 4, '\t' );
+ sId += "\t";
+ sId += rLine.GetToken( 5, '\t' );
+ break;
+ }
+ return sId;
+}
+
+/*****************************************************************************/
+ByteString GetGSILineLangId( const ByteString &rLine, USHORT nFileType )
+/*****************************************************************************/
+{
+ ByteString sLangId;
+ switch ( nFileType ) {
+ case GSI_FILE_OLDSTYLE:
+ sLangId = rLine;
+ sLangId.SearchAndReplaceAll( "($$)", "\t" );
+ sLangId = sLangId.GetToken( 2, '\t' );
+ break;
+
+ case GSI_FILE_L10NFRAMEWORK:
+ sLangId = rLine.GetToken( 9, '\t' );
+ break;
+ }
+ return sLangId;
+}
+
+/*****************************************************************************/
+void ConvertGSILine( BOOL bToUTF8, ByteString &rLine,
+ rtl_TextEncoding nEncoding, USHORT nFileType )
+/*****************************************************************************/
+{
+ switch ( nFileType ) {
+ case GSI_FILE_OLDSTYLE:
+ if ( bToUTF8 )
+ rLine = UTF8Converter::ConvertToUTF8( rLine, nEncoding );
+ else
+ rLine = UTF8Converter::ConvertFromUTF8( rLine, nEncoding );
+ break;
+
+ case GSI_FILE_L10NFRAMEWORK: {
+ ByteString sConverted;
+ for ( USHORT i = 0; i < rLine.GetTokenCount( '\t' ); i++ ) {
+ ByteString sToken = rLine.GetToken( i, '\t' );
+ if (( i > 9 ) && ( i < 14 )) {
+ if( bToUTF8 )
+ sToken = UTF8Converter::ConvertToUTF8( sToken, nEncoding );
+ else
+ sToken = UTF8Converter::ConvertFromUTF8( sToken, nEncoding );
+ }
+ if ( i )
+ sConverted += "\t";
+ sConverted += sToken;
+ }
+ rLine = sConverted;
+ }
+ break;
+ }
+}
+
+/*****************************************************************************/
+void Help()
+/*****************************************************************************/
+{
+ fprintf( stdout, "\n" );
+ fprintf( stdout, "gsiconv (c)1999 by StarOffice Entwicklungs GmbH\n" );
+ fprintf( stdout, "===============================================\n" );
+ fprintf( stdout, "\n" );
+ fprintf( stdout, "gsiconv converts strings in GSI-Files (Gutschmitt Interface) from or to UTF-8\n" );
+ fprintf( stdout, "\n" );
+ fprintf( stdout, "Syntax: gsiconv (-t|-f langid charset)|(-p n) filename\n" );
+ fprintf( stdout, "Switches: -t => conversion from charset to UTF-8\n" );
+ fprintf( stdout, " -f => conversion from UTF-8 to charset\n" );
+ fprintf( stdout, " -p n => creates several files with ca. n lines\n" );
+ fprintf( stdout, "\n" );
+ fprintf( stdout, "Allowed charsets:\n" );
+ fprintf( stdout, " MS_932 => Japanese\n" );
+ fprintf( stdout, " MS_936 => Chinese Simplified\n" );
+ fprintf( stdout, " MS_949 => Korean\n" );
+ fprintf( stdout, " MS_950 => Chinese Traditional\n" );
+ fprintf( stdout, " MS_1250 => East Europe\n" );
+ fprintf( stdout, " MS_1251 => Cyrillic\n" );
+ fprintf( stdout, " MS_1252 => West Europe\n" );
+ fprintf( stdout, " MS_1253 => Greek\n" );
+ fprintf( stdout, " MS_1254 => Turkish\n" );
+ fprintf( stdout, " MS_1255 => Hebrew\n" );
+ fprintf( stdout, " MS_1256 => Arabic\n" );
+ fprintf( stdout, "\n" );
+ fprintf( stdout, "Allowed langids:\n" );
+ fprintf( stdout, " 1 => ENGLISH_US\n" );
+ fprintf( stdout, " 3 => PORTUGUESE \n" );
+ fprintf( stdout, " 4 => GERMAN_DE (new german style)\n" );
+ fprintf( stdout, " 7 => RUSSIAN\n" );
+ fprintf( stdout, " 30 => GREEK\n" );
+ fprintf( stdout, " 31 => DUTCH\n" );
+ fprintf( stdout, " 33 => FRENCH\n" );
+ fprintf( stdout, " 34 => SPANISH\n" );
+ fprintf( stdout, " 35 => FINNISH\n" );
+ fprintf( stdout, " 36 => HUNGARIAN\n" );
+ fprintf( stdout, " 39 => ITALIAN\n" );
+ fprintf( stdout, " 42 => CZECH\n" );
+ fprintf( stdout, " 44 => ENGLISH (UK)\n" );
+ fprintf( stdout, " 45 => DANISH\n" );
+ fprintf( stdout, " 46 => SWEDISH\n" );
+ fprintf( stdout, " 47 => NORWEGIAN\n" );
+ fprintf( stdout, " 49 => GERMAN (old german style)\n" );
+ fprintf( stdout, " 55 => PORTUGUESE_BRAZILIAN\n" );
+ fprintf( stdout, " 81 => JAPANESE\n" );
+ fprintf( stdout, " 82 => KOREAN\n" );
+ fprintf( stdout, " 86 => CHINESE_SIMPLIFIED\n" );
+ fprintf( stdout, " 88 => CHINESE_TRADITIONAL\n" );
+ fprintf( stdout, " 90 => TURKISH\n" );
+ fprintf( stdout, " 96 => ARABIC\n" );
+ fprintf( stdout, " 97 => HEBREW\n" );
+ fprintf( stdout, "\n" );
+}
+
+/*****************************************************************************/
+#if defined(UNX) || defined(OS2)
+int main( int argc, char *argv[] )
+#else
+int _cdecl main( int argc, char *argv[] )
+#endif
+/*****************************************************************************/
+{
+ if (( argc != 5 ) && ( argc != 4 )) {
+ Help();
+ exit ( 0 );
+ }
+
+ if ( argc == 4 ) {
+ if ( ByteString( argv[ 1 ] ) == "-p" ) {
+
+ DirEntry aSource = DirEntry( String( argv[ 3 ], RTL_TEXTENCODING_ASCII_US ));
+ if ( !aSource.Exists()) {
+ fprintf( stderr, "\nERROR: GSI-File %s not found!\n\n", ByteString( argv[ 3 ] ).GetBuffer());
+ exit ( 2 );
+ }
+
+ DirEntry aOutput( aSource );
+
+ String sBase = aOutput.GetBase();
+ String sExt = aOutput.GetExtension();
+
+ String sGSI( argv[ 3 ], RTL_TEXTENCODING_ASCII_US );
+ SvFileStream aGSI( sGSI, STREAM_STD_READ );
+ if ( !aGSI.IsOpen()) {
+ fprintf( stderr, "\nERROR: Could not open GSI-File %s!\n\n", ByteString( argv[ 3 ] ).GetBuffer());
+ exit ( 3 );
+ }
+
+ USHORT nFileType( GetGSIFileType( aGSI ));
+
+ ULONG nMaxLines = (ULONG) ByteString( argv[ 2 ] ).ToInt64();
+ if ( !nMaxLines ) {
+ fprintf( stderr, "\nERROR: Linecount must be at least 1!\n\n" );
+ exit ( 3 );
+ }
+
+ ByteString sGSILine;
+ ByteString sOldId;
+ ULONG nLine = 0;
+ ULONG nOutputFile = 1;
+
+ String sOutput( sBase );
+ sOutput += String( "_", RTL_TEXTENCODING_ASCII_US );
+ sOutput += String::CreateFromInt64( nOutputFile );
+ if ( sExt.Len()) {
+ sOutput += String( ".", RTL_TEXTENCODING_ASCII_US );
+ sOutput += sExt;
+ }
+ nOutputFile ++;
+
+ aOutput.SetName( sOutput );
+ SvFileStream aOutputStream( aOutput.GetFull(), STREAM_STD_WRITE | STREAM_TRUNC );
+
+ while ( !aGSI.IsEof()) {
+
+ aGSI.ReadLine( sGSILine );
+ ByteString sId( GetGSILineId( sGSILine, nFileType ));
+
+ nLine++;
+
+ if (( nLine >= nMaxLines ) && ( sId != sOldId )) {
+ aOutputStream.Close();
+
+ ByteString sText( aOutput.GetFull(), gsl_getSystemTextEncoding());
+ sText += " with ";
+ sText += ByteString::CreateFromInt64( nLine );
+ sText += " lines written.";
+
+ fprintf( stdout, "%s\n", sText.GetBuffer());
+ String sOutput1( sBase );
+ sOutput1 += String( "_", RTL_TEXTENCODING_ASCII_US );
+ sOutput1 += String::CreateFromInt64( nOutputFile );
+ if ( sExt.Len()) {
+ sOutput1 += String( ".", RTL_TEXTENCODING_ASCII_US );
+ sOutput1 += sExt;
+ }
+ nOutputFile ++;
+
+ aOutput.SetName( sOutput1 );
+
+ aOutputStream.Open( aOutput.GetFull(), STREAM_STD_WRITE | STREAM_TRUNC );
+ nLine = 0;
+ }
+
+ aOutputStream.WriteLine( sGSILine );
+
+ sOldId = sId;
+ }
+
+ aGSI.Close();
+ aOutputStream.Close();
+
+ ByteString sText( aOutput.GetFull(), RTL_TEXTENCODING_ASCII_US );
+ sText += " with ";
+ sText += ByteString::CreateFromInt64( nLine );
+ sText += " lines written.";
+ }
+ else {
+ Help();
+ exit( 1 );
+ }
+ }
+ else {
+ if ( ByteString( argv[ 1 ] ) == "-t" || ByteString( argv[ 1 ] ) == "-f" ) {
+ rtl_TextEncoding nEncoding;
+
+ ByteString sCurLangId( argv[ 2 ] );
+
+ ByteString sCharset( argv[ 3 ] );
+ sCharset.ToUpperAscii();
+
+ if ( sCharset == "MS_932" ) nEncoding = RTL_TEXTENCODING_MS_932;
+ else if ( sCharset == "MS_936" ) nEncoding = RTL_TEXTENCODING_MS_936;
+ else if ( sCharset == "MS_949" ) nEncoding = RTL_TEXTENCODING_MS_949;
+ else if ( sCharset == "MS_950" ) nEncoding = RTL_TEXTENCODING_MS_950;
+ else if ( sCharset == "MS_1250" ) nEncoding = RTL_TEXTENCODING_MS_1250;
+ else if ( sCharset == "MS_1251" ) nEncoding = RTL_TEXTENCODING_MS_1251;
+ else if ( sCharset == "MS_1252" ) nEncoding = RTL_TEXTENCODING_MS_1252;
+ else if ( sCharset == "MS_1253" ) nEncoding = RTL_TEXTENCODING_MS_1253;
+ else if ( sCharset == "MS_1254" ) nEncoding = RTL_TEXTENCODING_MS_1254;
+ else if ( sCharset == "MS_1255" ) nEncoding = RTL_TEXTENCODING_MS_1255;
+ else if ( sCharset == "MS_1256" ) nEncoding = RTL_TEXTENCODING_MS_1256;
+ else if ( sCharset == "MS_1257" ) nEncoding = RTL_TEXTENCODING_MS_1257;
+ else if ( sCharset == "UTF8" ) nEncoding = RTL_TEXTENCODING_UTF8;
+
+ else {
+ Help();
+ exit ( 1 );
+ }
+
+ DirEntry aSource = DirEntry( String( argv[ 4 ], RTL_TEXTENCODING_ASCII_US ));
+ if ( !aSource.Exists()) {
+ fprintf( stderr, "\nERROR: GSI-File %s not found!\n\n", ByteString( argv[ 3 ] ).GetBuffer());
+ exit ( 2 );
+ }
+
+ String sGSI( argv[ 4 ], RTL_TEXTENCODING_ASCII_US );
+ SvFileStream aGSI( sGSI, STREAM_STD_READ );
+ if ( !aGSI.IsOpen()) {
+ fprintf( stderr, "\nERROR: Could not open GSI-File %s!\n\n", ByteString( argv[ 3 ] ).GetBuffer());
+ exit ( 3 );
+ }
+ USHORT nFileType( GetGSIFileType( aGSI ));
+
+ ByteString sGSILine;
+ while ( !aGSI.IsEof()) {
+
+ aGSI.ReadLine( sGSILine );
+ ByteString sLangId( GetGSILineLangId( sGSILine, nFileType ));
+ if ( sLangId == sCurLangId )
+ ConvertGSILine(( ByteString( argv[ 1 ] ) == "-t" ), sGSILine, nEncoding, nFileType );
+
+ fprintf( stdout, "%s\n", sGSILine.GetBuffer());
+ }
+
+ aGSI.Close();
+ }
+ else {
+ Help();
+ exit( 1 );
+ }
+ }
+ return 0;
+}
diff --git a/l10ntools/source/help/HelpCompiler.cxx b/l10ntools/source/help/HelpCompiler.cxx
new file mode 100644
index 000000000000..5001d0907972
--- /dev/null
+++ b/l10ntools/source/help/HelpCompiler.cxx
@@ -0,0 +1,593 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: HelpCompiler.cxx,v $
+ * $Revision: 1.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "HelpCompiler.hxx"
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#ifdef __MINGW32__
+#include <tools/prewin.h>
+#include <tools/postwin.h>
+#endif
+#include <osl/thread.hxx>
+
+static void impl_sleep( sal_uInt32 nSec )
+{
+ TimeValue aTime;
+ aTime.Seconds = nSec;
+ aTime.Nanosec = 0;
+
+ osl::Thread::wait( aTime );
+}
+
+HelpCompiler::HelpCompiler(StreamTable &in_streamTable, const fs::path &in_inputFile,
+ const fs::path &in_src, const fs::path &in_resEmbStylesheet,
+ const std::string &in_module, const std::string &in_lang, bool in_bExtensionMode)
+ : streamTable(in_streamTable), inputFile(in_inputFile),
+ src(in_src), module(in_module), lang(in_lang), resEmbStylesheet(in_resEmbStylesheet),
+ bExtensionMode( in_bExtensionMode )
+{
+ xmlKeepBlanksDefaultValue = 0;
+}
+
+xmlDocPtr HelpCompiler::getSourceDocument(const fs::path &filePath)
+{
+ static const char *params[4 + 1];
+ static xsltStylesheetPtr cur = NULL;
+
+ xmlDocPtr res;
+ if( bExtensionMode )
+ {
+ res = xmlParseFile(filePath.native_file_string().c_str());
+ if( !res ){
+ impl_sleep( 3 );
+ res = xmlParseFile(filePath.native_file_string().c_str());
+ }
+ }
+ else
+ {
+ if (!cur)
+ {
+ static std::string fsroot('\'' + src.toUTF8() + '\'');
+ static std::string esclang('\'' + lang + '\'');
+
+ xmlSubstituteEntitiesDefault(1);
+ xmlLoadExtDtdDefaultValue = 1;
+ cur = xsltParseStylesheetFile((const xmlChar *)resEmbStylesheet.native_file_string().c_str());
+
+ int nbparams = 0;
+ params[nbparams++] = "Language";
+ params[nbparams++] = esclang.c_str();
+ params[nbparams++] = "fsroot";
+ params[nbparams++] = fsroot.c_str();
+ params[nbparams] = NULL;
+ }
+ xmlDocPtr doc = xmlParseFile(filePath.native_file_string().c_str());
+ if( !doc )
+ {
+ impl_sleep( 3 );
+ doc = xmlParseFile(filePath.native_file_string().c_str());
+ }
+
+ //???res = xmlParseFile(filePath.native_file_string().c_str());
+
+ res = xsltApplyStylesheet(cur, doc, params);
+ xmlFreeDoc(doc);
+ }
+ return res;
+}
+
+HashSet HelpCompiler::switchFind(xmlDocPtr doc)
+{
+ HashSet hs;
+ xmlChar *xpath = (xmlChar*)"//switchinline";
+
+ xmlXPathContextPtr context = xmlXPathNewContext(doc);
+ xmlXPathObjectPtr result = xmlXPathEvalExpression(xpath, context);
+ xmlXPathFreeContext(context);
+ if (result)
+ {
+ xmlNodeSetPtr nodeset = result->nodesetval;
+ for (int i = 0; i < nodeset->nodeNr; i++)
+ {
+ xmlNodePtr el = nodeset->nodeTab[i];
+ xmlChar *select = xmlGetProp(el, (xmlChar*)"select");
+ if (select)
+ {
+ if (!strcmp((const char*)select, "appl"))
+ {
+ xmlNodePtr n1 = el->xmlChildrenNode;
+ while (n1)
+ {
+ if ((!xmlStrcmp(n1->name, (const xmlChar*)"caseinline")))
+ {
+ xmlChar *appl = xmlGetProp(n1, (xmlChar*)"select");
+ hs.push_back(std::string((const char*)appl));
+ xmlFree(appl);
+ }
+ else if ((!xmlStrcmp(n1->name, (const xmlChar*)"defaultinline")))
+ hs.push_back(std::string("DEFAULT"));
+ n1 = n1->next;
+ }
+ }
+ xmlFree(select);
+ }
+ }
+ xmlXPathFreeObject(result);
+ }
+ hs.push_back(std::string("DEFAULT"));
+ return hs;
+}
+
+// returns a node representing the whole stuff compiled for the current
+// application.
+xmlNodePtr HelpCompiler::clone(xmlNodePtr node, const std::string& appl)
+{
+ xmlNodePtr parent = xmlCopyNode(node, 2);
+ xmlNodePtr n = node->xmlChildrenNode;
+ while (n != NULL)
+ {
+ bool isappl = false;
+ if ( (!strcmp((const char*)n->name, "switchinline")) ||
+ (!strcmp((const char*)n->name, "switch")) )
+ {
+ xmlChar *select = xmlGetProp(n, (xmlChar*)"select");
+ if (select)
+ {
+ if (!strcmp((const char*)select, "appl"))
+ isappl = true;
+ xmlFree(select);
+ }
+ }
+ if (isappl)
+ {
+ xmlNodePtr caseNode = n->xmlChildrenNode;
+ if (appl == "DEFAULT")
+ {
+ while (caseNode)
+ {
+ if (!strcmp((const char*)caseNode->name, "defaultinline"))
+ {
+ xmlNodePtr cnl = caseNode->xmlChildrenNode;
+ while (cnl)
+ {
+ xmlAddChild(parent, clone(cnl, appl));
+ cnl = cnl->next;
+ }
+ break;
+ }
+ caseNode = caseNode->next;
+ }
+ }
+ else
+ {
+ while (caseNode)
+ {
+ isappl=false;
+ if (!strcmp((const char*)caseNode->name, "caseinline"))
+ {
+ xmlChar *select = xmlGetProp(n, (xmlChar*)"select");
+ if (select)
+ {
+ if (!strcmp((const char*)select, appl.c_str()))
+ isappl = true;
+ xmlFree(select);
+ }
+ if (isappl)
+ {
+ xmlNodePtr cnl = caseNode->xmlChildrenNode;
+ while (cnl)
+ {
+ xmlAddChild(parent, clone(cnl, appl));
+ cnl = cnl->next;
+ }
+ break;
+ }
+
+ }
+ caseNode = caseNode->next;
+ }
+ }
+
+ }
+ else
+ xmlAddChild(parent, clone(n, appl));
+
+ n = n->next;
+ }
+ return parent;
+}
+
+class myparser
+{
+public:
+ std::string documentId;
+ std::string fileName;
+ std::string title;
+ HashSet *hidlist;
+ Hashtable *keywords;
+ Stringtable *helptexts;
+private:
+ HashSet extendedHelpText;
+public:
+ myparser(const std::string &indocumentId, const std::string &infileName,
+ const std::string &intitle) : documentId(indocumentId), fileName(infileName),
+ title(intitle)
+ {
+ hidlist = new HashSet;
+ keywords = new Hashtable;
+ helptexts = new Stringtable;
+ }
+ void traverse( xmlNodePtr parentNode );
+private:
+ std::string dump(xmlNodePtr node);
+};
+
+std::string myparser::dump(xmlNodePtr node)
+{
+ std::string app;
+ if (node->xmlChildrenNode)
+ {
+ xmlNodePtr list = node->xmlChildrenNode;
+ while (list)
+ {
+ app += dump(list);
+ list = list->next;
+ }
+ }
+ if (xmlNodeIsText(node))
+ {
+ xmlChar *pContent = xmlNodeGetContent(node);
+ app += std::string((const char*)pContent);
+ xmlFree(pContent);
+ // std::cout << app << std::endl;
+ }
+ return app;
+}
+
+void trim(std::string& str)
+{
+ std::string::size_type pos = str.find_last_not_of(' ');
+ if(pos != std::string::npos)
+ {
+ str.erase(pos + 1);
+ pos = str.find_first_not_of(' ');
+ if(pos != std::string::npos)
+ str.erase(0, pos);
+ }
+ else
+ str.erase(str.begin(), str.end());
+}
+
+void myparser::traverse( xmlNodePtr parentNode )
+{
+ // traverse all nodes that belong to the parent
+ xmlNodePtr test ;
+ for (test = parentNode->xmlChildrenNode; test; test = test->next)
+ {
+ if (fileName.empty() && !strcmp((const char*)test->name, "filename"))
+ {
+ xmlNodePtr node = test->xmlChildrenNode;
+ if (xmlNodeIsText(node))
+ {
+ xmlChar *pContent = xmlNodeGetContent(node);
+ fileName = std::string((const char*)pContent);
+ xmlFree(pContent);
+ }
+ }
+ else if (title.empty() && !strcmp((const char*)test->name, "title"))
+ {
+ title = dump(test);
+ if (title.empty())
+ title = "<notitle>";
+ }
+ else if (!strcmp((const char*)test->name, "bookmark"))
+ {
+ xmlChar *branchxml = xmlGetProp(test, (const xmlChar*)"branch");
+ xmlChar *idxml = xmlGetProp(test, (const xmlChar*)"id");
+ std::string branch((const char*)branchxml);
+ std::string anchor((const char*)idxml);
+ xmlFree (branchxml);
+ xmlFree (idxml);
+
+ std::string hid;
+
+ if (branch.find("hid") == 0)
+ {
+ size_t index = branch.find('/');
+ if (index != std::string::npos)
+ {
+ hid = branch.substr(1 + index);
+ // one shall serve as a documentId
+ if (documentId.empty())
+ documentId = hid;
+ extendedHelpText.push_back(hid);
+ std::string foo = anchor.empty() ? hid : hid + "#" + anchor;
+ HCDBG(std::cerr << "hid pushback" << foo << std::endl);
+ hidlist->push_back( anchor.empty() ? hid : hid + "#" + anchor);
+ }
+ else
+ continue;
+ }
+ else if (branch.compare("index") == 0)
+ {
+ LinkedList ll;
+
+ for (xmlNodePtr nd = test->xmlChildrenNode; nd; nd = nd->next)
+ {
+ if (strcmp((const char*)nd->name, "bookmark_value"))
+ continue;
+
+ std::string embedded;
+ xmlChar *embeddedxml = xmlGetProp(nd, (const xmlChar*)"embedded");
+ if (embeddedxml)
+ {
+ embedded = std::string((const char*)embeddedxml);
+ xmlFree (embeddedxml);
+ std::transform (embedded.begin(), embedded.end(),
+ embedded.begin(), tolower);
+ }
+
+ bool isEmbedded = !embedded.empty() && embedded.compare("true") == 0;
+ if (isEmbedded)
+ continue;
+
+ std::string keyword = dump(nd);
+ size_t keywordSem = keyword.find(';');
+ if (keywordSem != std::string::npos)
+ {
+ std::string tmppre =
+ keyword.substr(0,keywordSem);
+ trim(tmppre);
+ std::string tmppos =
+ keyword.substr(1+keywordSem);
+ trim(tmppos);
+ keyword = tmppre + ";" + tmppos;
+ }
+ ll.push_back(keyword);
+ }
+ if (!ll.empty())
+ (*keywords)[anchor] = ll;
+ }
+ else if (branch.compare("contents") == 0)
+ {
+ // currently not used
+ }
+ }
+ else if (!strcmp((const char*)test->name, "ahelp"))
+ {
+ std::string text = dump(test);
+ trim(text);
+ std::string name;
+
+ HashSet::const_iterator aEnd = extendedHelpText.end();
+ for (HashSet::const_iterator iter = extendedHelpText.begin(); iter != aEnd;
+ ++iter)
+ {
+ name = *iter;
+ (*helptexts)[name] = text;
+ }
+ extendedHelpText.clear();
+ }
+
+ // traverse children
+ traverse(test);
+ }
+}
+
+bool HelpCompiler::compile( void ) throw( HelpProcessingException )
+{
+ // we now have the jaroutputstream, which will contain the document.
+ // now determine the document as a dom tree in variable docResolved
+
+ xmlDocPtr docResolvedOrg = getSourceDocument(inputFile);
+
+ // now add path to the document
+ // resolve the dom
+ if (!docResolvedOrg)
+ {
+ impl_sleep( 3 );
+ docResolvedOrg = getSourceDocument(inputFile);
+ if( !docResolvedOrg )
+ {
+ std::stringstream aStrStream;
+ aStrStream << "ERROR: file not existing: " << inputFile.native_file_string().c_str() << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ }
+
+ // now find all applications for which one has to compile
+ std::string documentId;
+ std::string fileName;
+ std::string title;
+ // returns all applications for which one has to compile
+ HashSet applications = switchFind(docResolvedOrg);
+
+ HashSet::const_iterator aEnd = applications.end();
+ for (HashSet::const_iterator aI = applications.begin(); aI != aEnd; ++aI)
+ {
+ std::string appl = *aI;
+ std::string modulename = appl;
+ if (modulename[0] == 'S')
+ {
+ modulename = modulename.substr(1);
+ std::transform(modulename.begin(), modulename.end(), modulename.begin(), tolower);
+ }
+ if (modulename != "DEFAULT" && modulename != module)
+ continue;
+
+ // returns a clone of the document with swich-cases resolved
+ xmlNodePtr docResolved = clone(xmlDocGetRootElement(docResolvedOrg), appl);
+ myparser aparser(documentId, fileName, title);
+ aparser.traverse(docResolved);
+
+ documentId = aparser.documentId;
+ fileName = aparser.fileName;
+ title = aparser.title;
+
+ HCDBG(std::cerr << documentId << " : " << fileName << " : " << title << std::endl);
+
+ xmlDocPtr docResolvedDoc = xmlCopyDoc(docResolvedOrg, false);
+ xmlDocSetRootElement(docResolvedDoc, docResolved);
+
+ if (modulename == "DEFAULT")
+ {
+ streamTable.dropdefault();
+ streamTable.default_doc = docResolvedDoc;
+ streamTable.default_hidlist = aparser.hidlist;
+ streamTable.default_helptexts = aparser.helptexts;
+ streamTable.default_keywords = aparser.keywords;
+ }
+ else if (modulename == module)
+ {
+ streamTable.dropappl();
+ streamTable.appl_doc = docResolvedDoc;
+ streamTable.appl_hidlist = aparser.hidlist;
+ streamTable.appl_helptexts = aparser.helptexts;
+ streamTable.appl_keywords = aparser.keywords;
+ }
+ else
+ {
+ std::stringstream aStrStream;
+ aStrStream << "ERROR: Found unexpected module name \"" << modulename
+ << "\" in file" << src.native_file_string().c_str() << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ } // end iteration over all applications
+
+ streamTable.document_id = documentId;
+ streamTable.document_path = fileName;
+ streamTable.document_title = title;
+ std::string actMod = module;
+ if ( !bExtensionMode && !fileName.empty())
+ {
+ if (fileName.find("/text/") == 0)
+ {
+ int len = strlen("/text/");
+ actMod = fileName.substr(len);
+ actMod = actMod.substr(0, actMod.find('/'));
+ }
+ }
+ streamTable.document_module = actMod;
+
+ xmlFreeDoc(docResolvedOrg);
+ return true;
+}
+
+namespace fs
+{
+ rtl_TextEncoding getThreadTextEncoding( void )
+ {
+ static bool bNeedsInit = true;
+ static rtl_TextEncoding nThreadTextEncoding;
+ if( bNeedsInit )
+ {
+ bNeedsInit = false;
+ nThreadTextEncoding = osl_getThreadTextEncoding();
+ }
+ return nThreadTextEncoding;
+ }
+
+ void create_directory(const fs::path indexDirName)
+ {
+ HCDBG(
+ std::cerr << "creating " <<
+ rtl::OUStringToOString(indexDirName.data, RTL_TEXTENCODING_UTF8).getStr()
+ << std::endl
+ );
+ osl::Directory::createPath(indexDirName.data);
+ }
+
+ void rename(const fs::path &src, const fs::path &dest)
+ {
+ osl::File::move(src.data, dest.data);
+ }
+
+ void copy(const fs::path &src, const fs::path &dest)
+ {
+ osl::File::copy(src.data, dest.data);
+ }
+
+ bool exists(const fs::path &in)
+ {
+ osl::File tmp(in.data);
+ return (tmp.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None);
+ }
+
+ void remove(const fs::path &in)
+ {
+ osl::File::remove(in.data);
+ }
+
+ void removeRecursive(rtl::OUString const& _suDirURL)
+ {
+ {
+ osl::Directory aDir(_suDirURL);
+ aDir.open();
+ if (aDir.isOpen())
+ {
+ osl::DirectoryItem aItem;
+ osl::FileStatus aStatus(osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Attributes);
+ while (aDir.getNextItem(aItem) == ::osl::FileBase::E_None)
+ {
+ if (osl::FileBase::E_None == aItem.getFileStatus(aStatus) &&
+ aStatus.isValid(osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Attributes))
+ {
+ rtl::OUString suFilename = aStatus.getFileName();
+ rtl::OUString suFullFileURL;
+ suFullFileURL += _suDirURL;
+ suFullFileURL += rtl::OUString::createFromAscii("/");
+ suFullFileURL += suFilename;
+
+ if (aStatus.getFileType() == osl::FileStatus::Directory)
+ removeRecursive(suFullFileURL);
+ else
+ osl::File::remove(suFullFileURL);
+ }
+ }
+ aDir.close();
+ }
+ }
+ osl::Directory::remove(_suDirURL);
+ }
+
+ void remove_all(const fs::path &in)
+ {
+ removeRecursive(in.data);
+ }
+}
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/l10ntools/source/help/HelpCompiler.hxx b/l10ntools/source/help/HelpCompiler.hxx
new file mode 100644
index 000000000000..7ffb096bd635
--- /dev/null
+++ b/l10ntools/source/help/HelpCompiler.hxx
@@ -0,0 +1,320 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: HelpCompiler.hxx,v $
+ * $Revision: 1.8 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef HELPCOMPILER_HXX
+#define HELPCOMPILER_HXX
+
+#include <string>
+#include <hash_map>
+#include <vector>
+#include <list>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+#include <ctype.h>
+#ifdef SYSTEM_DB
+#include <db.h>
+#else
+#include <berkeleydb/db.h>
+#endif
+
+#include <boost/shared_ptr.hpp>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/debugXML.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xinclude.h>
+#include <libxml/catalog.h>
+
+#include <rtl/ustring.hxx>
+#include <osl/thread.h>
+#include <osl/process.h>
+#include <osl/file.hxx>
+
+#include <compilehelp.hxx>
+
+#define EMULATEORIGINAL 1
+
+#ifdef CMCDEBUG
+ #define HCDBG(foo) do { if (1) foo; } while(0)
+#else
+ #define HCDBG(foo) do { if (0) foo; } while(0)
+#endif
+
+namespace fs
+{
+ rtl_TextEncoding getThreadTextEncoding( void );
+
+ enum convert { native };
+ class path
+ {
+ public:
+ ::rtl::OUString data;
+ public:
+ path() {}
+ path(const path &rOther) : data(rOther.data) {}
+ path(const std::string &in, convert)
+ {
+ rtl::OUString sWorkingDir;
+ osl_getProcessWorkingDir(&sWorkingDir.pData);
+
+ rtl::OString tmp(in.c_str());
+ rtl::OUString ustrSystemPath(rtl::OStringToOUString(tmp, getThreadTextEncoding()));
+ osl::File::getFileURLFromSystemPath(ustrSystemPath, data);
+ osl::File::getAbsoluteFileURL(sWorkingDir, data, data);
+ }
+ path(const std::string &FileURL)
+ {
+ rtl::OString tmp(FileURL.c_str());
+ data = rtl::OStringToOUString(tmp, getThreadTextEncoding());
+ }
+ std::string native_file_string() const
+ {
+ ::rtl::OUString ustrSystemPath;
+ osl::File::getSystemPathFromFileURL(data, ustrSystemPath);
+ rtl::OString tmp(rtl::OUStringToOString(ustrSystemPath, getThreadTextEncoding()));
+ HCDBG(std::cerr << "native_file_string is " << tmp.getStr() << std::endl);
+ return std::string(tmp.getStr());
+ }
+ std::string native_directory_string() const { return native_file_string(); }
+ std::string toUTF8() const
+ {
+ rtl::OString tmp(rtl::OUStringToOString(data, RTL_TEXTENCODING_UTF8));
+ return std::string(tmp.getStr());
+ }
+ bool empty() const { return data.getLength() == 0; }
+ path operator/(const std::string &in) const
+ {
+ path ret(*this);
+ HCDBG(std::cerr << "orig was " <<
+ rtl::OUStringToOString(ret.data, RTL_TEXTENCODING_UTF8).getStr() << std::endl);
+ rtl::OString tmp(in.c_str());
+ rtl::OUString ustrSystemPath(rtl::OStringToOUString(tmp, getThreadTextEncoding()));
+ ret.data += rtl::OUString(sal_Unicode('/'));
+ ret.data += ustrSystemPath;
+ HCDBG(std::cerr << "final is " <<
+ rtl::OUStringToOString(ret.data, RTL_TEXTENCODING_UTF8).getStr() << std::endl);
+ return ret;
+ }
+ void append(const char *in)
+ {
+ rtl::OString tmp(in);
+ rtl::OUString ustrSystemPath(rtl::OStringToOUString(tmp, getThreadTextEncoding()));
+ data = data + ustrSystemPath;
+ }
+ void append(const std::string &in) { append(in.c_str()); }
+ };
+
+ void create_directory(const fs::path indexDirName);
+ void rename(const fs::path &src, const fs::path &dest);
+ void copy(const fs::path &src, const fs::path &dest);
+ bool exists(const fs::path &in);
+ void remove_all(const fs::path &in);
+ void remove(const fs::path &in);
+}
+
+struct joaat_hash
+{
+ size_t operator()(const std::string &str) const
+ {
+ size_t hash = 0;
+ const char *key = str.data();
+ for (size_t i = 0; i < str.size(); i++)
+ {
+ hash += key[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+ return hash;
+ }
+};
+
+#define get16bits(d) ((((sal_uInt32)(((const sal_uInt8 *)(d))[1])) << 8)\
+ +(sal_uInt32)(((const sal_uInt8 *)(d))[0]) )
+
+struct SuperFastHash
+{
+ size_t operator()(const std::string &str) const
+ {
+ const char * data = str.data();
+ int len = str.size();
+ size_t hash = len, tmp;
+ if (len <= 0 || data == NULL) return 0;
+
+ int rem = len & 3;
+ len >>= 2;
+
+ /* Main loop */
+ for (;len > 0; len--)
+ {
+ hash += get16bits (data);
+ tmp = (get16bits (data+2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2*sizeof (sal_uInt16);
+ hash += hash >> 11;
+ }
+
+ /* Handle end cases */
+ switch (rem)
+ {
+ case 3: hash += get16bits (data);
+ hash ^= hash << 16;
+ hash ^= data[sizeof (sal_uInt16)] << 18;
+ hash += hash >> 11;
+ break;
+ case 2: hash += get16bits (data);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ break;
+ case 1: hash += *data;
+ hash ^= hash << 10;
+ hash += hash >> 1;
+ }
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
+ }
+};
+
+#define pref_hash joaat_hash
+
+typedef std::hash_map<std::string, std::string, pref_hash> Stringtable;
+typedef std::list<std::string> LinkedList;
+typedef std::vector<std::string> HashSet;
+
+typedef std::hash_map<std::string, LinkedList, pref_hash> Hashtable;
+
+class StreamTable
+{
+public:
+ std::string document_id;
+ std::string document_path;
+ std::string document_module;
+ std::string document_title;
+
+ HashSet *appl_hidlist;
+ Hashtable *appl_keywords;
+ Stringtable *appl_helptexts;
+ xmlDocPtr appl_doc;
+
+ HashSet *default_hidlist;
+ Hashtable *default_keywords;
+ Stringtable *default_helptexts;
+ xmlDocPtr default_doc;
+
+ StreamTable() :
+ appl_hidlist(NULL), appl_keywords(NULL), appl_helptexts(NULL), appl_doc(NULL),
+ default_hidlist(NULL), default_keywords(NULL), default_helptexts(NULL), default_doc(NULL)
+ {}
+ void dropdefault()
+ {
+ delete default_hidlist;
+ delete default_keywords;
+ delete default_helptexts;
+ if (default_doc) xmlFreeDoc(default_doc);
+ }
+ void dropappl()
+ {
+ delete appl_hidlist;
+ delete appl_keywords;
+ delete appl_helptexts;
+ if (appl_doc) xmlFreeDoc(appl_doc);
+ }
+ ~StreamTable()
+ {
+ dropappl();
+ dropdefault();
+ }
+};
+
+struct HelpProcessingException
+{
+ HelpProcessingErrorClass m_eErrorClass;
+ std::string m_aErrorMsg;
+ std::string m_aXMLParsingFile;
+ int m_nXMLParsingLine;
+
+ HelpProcessingException( HelpProcessingErrorClass eErrorClass, const std::string& aErrorMsg )
+ : m_eErrorClass( eErrorClass )
+ , m_aErrorMsg( aErrorMsg )
+ {}
+ HelpProcessingException( const std::string& aErrorMsg, const std::string& aXMLParsingFile, int nXMLParsingLine )
+ : m_eErrorClass( HELPPROCESSING_XMLPARSING_ERROR )
+ , m_aErrorMsg( aErrorMsg )
+ , m_aXMLParsingFile( aXMLParsingFile )
+ , m_nXMLParsingLine( nXMLParsingLine )
+ {}
+};
+
+class HelpCompiler
+{
+public:
+ HelpCompiler(StreamTable &streamTable,
+ const fs::path &in_inputFile,
+ const fs::path &in_src,
+ const fs::path &in_resEmbStylesheet,
+ const std::string &in_module,
+ const std::string &in_lang,
+ bool in_bExtensionMode);
+ bool compile( void ) throw (HelpProcessingException);
+ void addEntryToJarFile(const std::string &prefix,
+ const std::string &entryName, const std::string &bytesToAdd);
+ void addEntryToJarFile(const std::string &prefix,
+ const std::string &entryName, const HashSet &bytesToAdd);
+ void addEntryToJarFile(const std::string &prefix,
+ const std::string &entryName, const Stringtable &bytesToAdd);
+ void addEntryToJarFile(const std::string &prefix,
+ const std::string &entryName, const Hashtable &bytesToAdd);
+private:
+ xmlDocPtr getSourceDocument(const fs::path &filePath);
+ HashSet switchFind(xmlDocPtr doc);
+ xmlNodePtr clone(xmlNodePtr node, const std::string& appl);
+ StreamTable &streamTable;
+ const fs::path inputFile, src;
+ const std::string module, lang;
+ const fs::path resEmbStylesheet;
+ bool bExtensionMode;
+};
+
+#endif
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/l10ntools/source/help/HelpFileDocument.java b/l10ntools/source/help/HelpFileDocument.java
new file mode 100644
index 000000000000..2212db27f251
--- /dev/null
+++ b/l10ntools/source/help/HelpFileDocument.java
@@ -0,0 +1,89 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: HelpFileDocument.java,v $
+ * $Revision: 1.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package com.sun.star.help;
+
+import java.io.File;
+import java.io.Reader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+//import java.io.FileReader;
+import java.io.StringReader;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+
+/** Lucene Document for help files */
+public class HelpFileDocument
+{
+ /** Creates reader for UTF-8 files
+ */
+ private static Reader getReaderForFile( File aFile )
+ throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException {
+ Reader aReader;
+ if( aFile != null ) {
+ FileInputStream fis = new FileInputStream( aFile );
+ aReader = new InputStreamReader( fis, "UTF-8" );
+ }
+ else {
+ aReader = new StringReader( "" );
+ }
+ return aReader;
+ }
+
+ /** Makes a document for a File.
+ */
+ public static Document Document( String aModule, File aCaptionFile, File aContentFile )
+ throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException {
+ Document doc = new Document();
+
+ // Add the path of the file as a field named "path". Use a field that is
+ // indexed (i.e. searchable), but don't tokenize the field into words.
+ File aFile = aCaptionFile != null ? aCaptionFile : aContentFile;
+ if( aFile != null )
+ {
+ String aPath = "#HLP#" + aModule + "/" + aFile.getName();
+ doc.add(new Field("path", aPath, Field.Store.YES, Field.Index.UN_TOKENIZED));
+ }
+
+ // Add the caption of the file to a field named "caption". Specify a Reader,
+ // so that the text of the file is tokenized and indexed, but not stored.
+ doc.add( new Field( "caption", getReaderForFile( aCaptionFile ) ) );
+
+ // Add the contents of the file to a field named "content". Specify a Reader,
+ // so that the text of the file is tokenized and indexed, but not stored.
+ doc.add( new Field( "content", getReaderForFile( aContentFile ) ) );
+
+ // return the document
+ return doc;
+ }
+
+ private HelpFileDocument() {}
+}
diff --git a/l10ntools/source/help/HelpIndexerTool.java b/l10ntools/source/help/HelpIndexerTool.java
new file mode 100644
index 000000000000..6bf22d1ac344
--- /dev/null
+++ b/l10ntools/source/help/HelpIndexerTool.java
@@ -0,0 +1,372 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: HelpIndexer.java,v $
+ * $Revision: 1.21 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package com.sun.star.help;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import java.util.zip.CRC32;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.analysis.cjk.CJKAnalyzer;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.index.IndexWriter;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Date;
+
+public class HelpIndexerTool
+{
+ public HelpIndexerTool()
+ {
+ }
+
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main( String[] args )
+ {
+ boolean bExtensionMode = false;
+ mainImpl( args, bExtensionMode );
+ }
+
+ public static void mainImpl( String[] args, boolean bExtensionMode )
+ {
+ String aDirToZipStr = "";
+ String aSrcDirStr = "";
+ String aLanguageStr = "";
+ String aModule = "";
+ String aTargetZipFileStr = "";
+ String aCfsName = "";
+
+ // Scan arguments
+ boolean bLang = false;
+ boolean bMod = false;
+ boolean bZipDir = false;
+ boolean bSrcDir = false;
+ boolean bOutput = false;
+ boolean bCfsName = false;
+
+ int nArgCount = args.length;
+ for( int i = 0 ; i < nArgCount ; i++ )
+ {
+ if( "-lang".equals(args[i]) )
+ {
+ if( i + 1 < nArgCount )
+ {
+ aLanguageStr = args[i + 1];
+ bLang = true;
+ }
+ i++;
+ }
+ else if( "-mod".equals(args[i]) )
+ {
+ if( i + 1 < nArgCount )
+ {
+ aModule = args[i + 1];
+ bMod = true;
+ }
+ i++;
+ }
+ else if( "-zipdir".equals(args[i]) )
+ {
+ if( i + 1 < nArgCount )
+ {
+ aDirToZipStr = args[i + 1];
+ bZipDir = true;
+ }
+ i++;
+ }
+ else if( "-srcdir".equals(args[i]) )
+ {
+ if( i + 1 < nArgCount )
+ {
+ aSrcDirStr = args[i + 1];
+ bSrcDir = true;
+ }
+ i++;
+ }
+ else if( "-o".equals(args[i]) )
+ {
+ if( i + 1 < nArgCount )
+ {
+ aTargetZipFileStr = args[i + 1];
+ bOutput = true;
+ }
+ i++;
+ }
+ else if( "-checkcfsname".equals(args[i]) )
+ {
+ if( i + 1 < nArgCount )
+ {
+ aCfsName = args[i + 1] + ".cfs";
+ bCfsName = true;
+ }
+ i++;
+ }
+ }
+
+ if( !bLang || !bMod || !bZipDir || (!bOutput && !bExtensionMode) )
+ {
+ if( bExtensionMode )
+ return;
+
+ System.out.println("Usage: HelpIndexer -lang ISOLangCode -mod HelpModule -zipdir TempZipDir -o OutputZipFile");
+ System.exit( -1 );
+ }
+
+ String aIndexDirName = aModule + ".idxl";
+ File aIndexDir = new File( aDirToZipStr + File.separator + aIndexDirName );
+ if( !bSrcDir )
+ aSrcDirStr = aDirToZipStr;
+ File aCaptionFilesDir = new File( aSrcDirStr + File.separator + "caption" );
+ File aContentFilesDir = new File( aSrcDirStr + File.separator + "content" );
+
+ try
+ {
+ Date start = new Date();
+ Analyzer analyzer = aLanguageStr.equals("ja") ? (Analyzer)new CJKAnalyzer() : (Analyzer)new StandardAnalyzer();
+ IndexWriter writer = new IndexWriter( aIndexDir, analyzer, true );
+ if( !bExtensionMode )
+ System.out.println( "Lucene: Indexing to directory '" + aIndexDir + "'..." );
+ int nRet = indexDocs( writer, aModule, bExtensionMode, aCaptionFilesDir, aContentFilesDir );
+ if( nRet != -1 )
+ {
+ if( !bExtensionMode )
+ {
+ System.out.println();
+ System.out.println( "Optimizing ..." );
+ }
+ writer.optimize();
+ }
+ writer.close();
+
+ boolean bCfsFileOk = true;
+ if( bCfsName && !bExtensionMode && nRet != -1 )
+ {
+ String aCompleteCfsFileName = aDirToZipStr + File.separator + aIndexDirName + File.separator + aCfsName;
+ File aCfsFile = new File( aCompleteCfsFileName );
+ bCfsFileOk = aCfsFile.exists();
+ System.out.println( "Checking cfs file " + aCfsName+ ": " + (bCfsFileOk ? "Found" : "Not found") );
+ }
+
+ if( bExtensionMode )
+ {
+ if( !bSrcDir )
+ {
+ deleteRecursively( aCaptionFilesDir );
+ deleteRecursively( aContentFilesDir );
+ }
+ }
+ else
+ {
+ if( nRet == -1 )
+ deleteRecursively( aIndexDir );
+
+ if( bCfsFileOk )
+ System.out.println( "Zipping ..." );
+ File aDirToZipFile = new File( aDirToZipStr );
+ createZipFile( aDirToZipFile, aTargetZipFileStr );
+ deleteRecursively( aDirToZipFile );
+ }
+
+ if( !bCfsFileOk )
+ {
+ System.out.println( "cfs file check failed, terminating..." );
+ System.exit( -1 );
+ }
+
+ Date end = new Date();
+ if( !bExtensionMode )
+ System.out.println(end.getTime() - start.getTime() + " total milliseconds");
+ }
+ catch (IOException e)
+ {
+ if( bExtensionMode )
+ return;
+
+ System.out.println(" caught a " + e.getClass() +
+ "\n with message: " + e.getMessage());
+ System.exit( -1 );
+ }
+ }
+
+ private static int indexDocs(IndexWriter writer, String aModule, boolean bExtensionMode,
+ File aCaptionFilesDir, File aContentFilesDir) throws IOException
+ {
+ if( !aCaptionFilesDir.canRead() || !aCaptionFilesDir.isDirectory() )
+ {
+ if( !bExtensionMode )
+ System.out.println( "Not found: " + aCaptionFilesDir );
+ return -1;
+ }
+ if( !aContentFilesDir.canRead() || !aContentFilesDir.isDirectory() )
+ {
+ if( !bExtensionMode )
+ System.out.println( "Not found: " + aContentFilesDir );
+ return -1;
+ }
+
+ String[] aCaptionFiles = aCaptionFilesDir.list();
+ List aCaptionFilesList = Arrays.asList( aCaptionFiles );
+ HashSet aCaptionFilesHashSet = new HashSet( aCaptionFilesList );
+
+ String[] aContentFiles = aContentFilesDir.list();
+ List aContentFilesList = Arrays.asList( aContentFiles );
+ HashSet aContentFilesHashSet = new HashSet( aContentFilesList );
+
+ // Loop over caption files and find corresponding content file
+ if( !bExtensionMode )
+ System.out.println( "Indexing, adding files" );
+ int nCaptionFilesLen = aCaptionFiles.length;
+ for( int i = 0 ; i < nCaptionFilesLen ; i++ )
+ {
+ String aCaptionFileStr = aCaptionFiles[i];
+ File aCaptionFile = new File( aCaptionFilesDir, aCaptionFileStr );
+ File aContentFile = null;
+ if( aContentFilesHashSet.contains( aCaptionFileStr ) )
+ aContentFile = new File( aContentFilesDir, aCaptionFileStr );
+
+ if( !bExtensionMode )
+ System.out.print( "." );
+ writer.addDocument( HelpFileDocument.Document( aModule, aCaptionFile, aContentFile ) );
+ }
+
+ // Loop over content files to find remaining files not mapped to caption files
+ int nContentFilesLen = aContentFiles.length;
+ for( int i = 0 ; i < nContentFilesLen ; i++ )
+ {
+ String aContentFileStr = aContentFiles[i];
+ if( !aCaptionFilesHashSet.contains( aContentFileStr ) )
+ {
+ // Not already handled in caption files loop
+ File aCaptionFile = null;
+ File aContentFile = new File( aContentFilesDir, aContentFileStr );
+ if( !bExtensionMode )
+ System.out.print( "." );
+ writer.addDocument( HelpFileDocument.Document( aModule, aCaptionFile, aContentFile ) );
+ }
+ }
+ return 0;
+ }
+
+ public static void createZipFile( File aDirToZip, String aTargetZipFileStr )
+ throws FileNotFoundException, IOException
+ {
+ FileOutputStream fos = new FileOutputStream( aTargetZipFileStr );
+ ZipOutputStream zos = new ZipOutputStream( fos );
+
+ File[] aChildrenFiles = aDirToZip.listFiles();
+ int nFileCount = aChildrenFiles.length;
+ for( int i = 0 ; i < nFileCount ; i++ )
+ addToZipRecursively( zos, aChildrenFiles[i], null );
+
+ zos.close();
+ }
+
+ public static void addToZipRecursively( ZipOutputStream zos, File aFile, String aBasePath )
+ throws FileNotFoundException, IOException
+ {
+ if( aFile.isDirectory() )
+ {
+ String aDirName = aFile.getName();
+ if( aDirName.equalsIgnoreCase( "caption" ) || aDirName.equalsIgnoreCase( "content" ) )
+ return;
+
+ File[] aChildrenFiles = aFile.listFiles();
+ String aNewBasePath = "";
+ if( aBasePath != null )
+ aNewBasePath += aBasePath + File.separator;
+ aNewBasePath += aDirName;
+
+ int nFileCount = aChildrenFiles.length;
+ for( int i = 0 ; i < nFileCount ; i++ )
+ addToZipRecursively( zos, aChildrenFiles[i], aNewBasePath );
+
+ return;
+ }
+
+ // No directory
+ // read contents of file we are going to put in the zip
+ int fileLength = (int) aFile.length();
+ FileInputStream fis = new FileInputStream( aFile );
+ byte[] wholeFile = new byte[fileLength];
+ int bytesRead = fis.read( wholeFile, 0, fileLength );
+ fis.close();
+
+ String aFileName = aFile.getName();
+ String aEntryName = "";
+ if( aBasePath != null )
+ aEntryName += aBasePath + "/";
+ aEntryName += aFileName;
+ ZipEntry aZipEntry = new ZipEntry( aEntryName );
+ aZipEntry.setTime( aFile.lastModified() );
+ aZipEntry.setSize( fileLength );
+
+ int nMethod = ( aFileName.toLowerCase().endsWith( ".jar" ) )
+ ? ZipEntry.STORED : ZipEntry.DEFLATED;
+ aZipEntry.setMethod( nMethod );
+
+ CRC32 tempCRC = new CRC32();
+ tempCRC.update( wholeFile, 0, wholeFile.length );
+ aZipEntry.setCrc( tempCRC.getValue() );
+
+ // write the contents into the zip element
+ zos.putNextEntry( aZipEntry );
+ zos.write( wholeFile, 0, fileLength );
+ zos.closeEntry();
+ }
+
+ static public boolean deleteRecursively( File aFile )
+ {
+ if( aFile.isDirectory() )
+ {
+ File[] aChildrenFiles = aFile.listFiles();
+ int nFileCount = aChildrenFiles.length;
+ for( int i = 0 ; i < nFileCount ; i++ )
+ {
+ File aChildrenFile = aChildrenFiles[i];
+ boolean bSuccess = deleteRecursively( aChildrenFile );
+ if( !bSuccess )
+ return false;
+ }
+ }
+
+ return aFile.delete();
+ }
+}
+
diff --git a/l10ntools/source/help/HelpLinker.cxx b/l10ntools/source/help/HelpLinker.cxx
new file mode 100644
index 000000000000..7dfe4ee4a2a2
--- /dev/null
+++ b/l10ntools/source/help/HelpLinker.cxx
@@ -0,0 +1,1173 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: HelpLinker.cxx,v $
+ * $Revision: 1.16 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "HelpCompiler.hxx"
+
+#include <map>
+
+#include <string.h>
+#include <limits.h>
+
+#include <libxslt/xslt.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/functions.h>
+#include <libxslt/extensions.h>
+
+#include <sal/types.h>
+#include <osl/time.h>
+#include <rtl/bootstrap.hxx>
+
+#include <expat.h>
+
+#define DBHELP_ONLY
+
+
+class IndexerPreProcessor
+{
+private:
+ std::string m_aModuleName;
+ fs::path m_fsIndexBaseDir;
+ fs::path m_fsCaptionFilesDirName;
+ fs::path m_fsContentFilesDirName;
+
+ xsltStylesheetPtr m_xsltStylesheetPtrCaption;
+ xsltStylesheetPtr m_xsltStylesheetPtrContent;
+
+public:
+ IndexerPreProcessor( const std::string& aModuleName, const fs::path& fsIndexBaseDir,
+ const fs::path& idxCaptionStylesheet, const fs::path& idxContentStylesheet );
+ ~IndexerPreProcessor();
+
+ void processDocument( xmlDocPtr doc, const std::string& EncodedDocPath );
+};
+
+IndexerPreProcessor::IndexerPreProcessor
+ ( const std::string& aModuleName, const fs::path& fsIndexBaseDir,
+ const fs::path& idxCaptionStylesheet, const fs::path& idxContentStylesheet )
+ : m_aModuleName( aModuleName )
+ , m_fsIndexBaseDir( fsIndexBaseDir )
+{
+ m_fsCaptionFilesDirName = fsIndexBaseDir / "caption";
+ fs::create_directory( m_fsCaptionFilesDirName );
+
+ m_fsContentFilesDirName = fsIndexBaseDir / "content";
+ fs::create_directory( m_fsContentFilesDirName );
+
+ m_xsltStylesheetPtrCaption = xsltParseStylesheetFile
+ ((const xmlChar *)idxCaptionStylesheet.native_file_string().c_str());
+ m_xsltStylesheetPtrContent = xsltParseStylesheetFile
+ ((const xmlChar *)idxContentStylesheet.native_file_string().c_str());
+}
+
+IndexerPreProcessor::~IndexerPreProcessor()
+{
+ if( m_xsltStylesheetPtrCaption )
+ xsltFreeStylesheet( m_xsltStylesheetPtrCaption );
+ if( m_xsltStylesheetPtrContent )
+ xsltFreeStylesheet( m_xsltStylesheetPtrContent );
+}
+
+
+std::string getEncodedPath( const std::string& Path )
+{
+ rtl::OString aOStr_Path( Path.c_str() );
+ rtl::OUString aOUStr_Path( rtl::OStringToOUString
+ ( aOStr_Path, fs::getThreadTextEncoding() ) );
+ rtl::OUString aPathURL;
+ osl::File::getFileURLFromSystemPath( aOUStr_Path, aPathURL );
+ rtl::OString aOStr_PathURL( rtl::OUStringToOString
+ ( aPathURL, fs::getThreadTextEncoding() ) );
+ std::string aStdStr_PathURL( aOStr_PathURL.getStr() );
+ return aStdStr_PathURL;
+}
+
+void IndexerPreProcessor::processDocument
+ ( xmlDocPtr doc, const std::string &EncodedDocPath )
+{
+ std::string aStdStr_EncodedDocPathURL = getEncodedPath( EncodedDocPath );
+
+ if( m_xsltStylesheetPtrCaption )
+ {
+ xmlDocPtr resCaption = xsltApplyStylesheet( m_xsltStylesheetPtrCaption, doc, NULL );
+ xmlNodePtr pResNodeCaption = resCaption->xmlChildrenNode;
+ if( pResNodeCaption )
+ {
+ fs::path fsCaptionPureTextFile_docURL = m_fsCaptionFilesDirName / aStdStr_EncodedDocPathURL;
+ std::string aCaptionPureTextFileStr_docURL = fsCaptionPureTextFile_docURL.native_file_string();
+ FILE* pFile_docURL = fopen( aCaptionPureTextFileStr_docURL.c_str(), "w" );
+ if( pFile_docURL )
+ {
+ fprintf( pFile_docURL, "%s\n", pResNodeCaption->content );
+ fclose( pFile_docURL );
+ }
+ }
+ xmlFreeDoc(resCaption);
+ }
+
+ if( m_xsltStylesheetPtrContent )
+ {
+ xmlDocPtr resContent = xsltApplyStylesheet( m_xsltStylesheetPtrContent, doc, NULL );
+ xmlNodePtr pResNodeContent = resContent->xmlChildrenNode;
+ if( pResNodeContent )
+ {
+ fs::path fsContentPureTextFile_docURL = m_fsContentFilesDirName / aStdStr_EncodedDocPathURL;
+ std::string aContentPureTextFileStr_docURL = fsContentPureTextFile_docURL.native_file_string();
+ FILE* pFile_docURL = fopen( aContentPureTextFileStr_docURL.c_str(), "w" );
+ if( pFile_docURL )
+ {
+ fprintf( pFile_docURL, "%s\n", pResNodeContent->content );
+ fclose( pFile_docURL );
+ }
+ }
+ xmlFreeDoc(resContent);
+ }
+}
+
+struct Data
+{
+ std::vector<std::string> _idList;
+ typedef std::vector<std::string>::const_iterator cIter;
+
+ void append(const std::string &id)
+ {
+ _idList.push_back(id);
+ }
+
+ std::string getString() const
+ {
+ std::string ret;
+ cIter aEnd = _idList.end();
+ for (cIter aIter = _idList.begin(); aIter != aEnd; ++aIter)
+ ret += *aIter + ";";
+ return ret;
+ }
+};
+
+void writeKeyValue_DBHelp( FILE* pFile, const std::string& aKeyStr, const std::string& aValueStr )
+{
+ if( pFile == NULL )
+ return;
+ char cLF = 10;
+ unsigned int nKeyLen = aKeyStr.length();
+ unsigned int nValueLen = aValueStr.length();
+ fprintf( pFile, "%x ", nKeyLen );
+ if( nKeyLen > 0 )
+ {
+ if (fwrite( aKeyStr.c_str(), 1, nKeyLen, pFile ) != nKeyLen)
+ fprintf(stderr, "fwrite to db failed\n");
+ }
+ if (fprintf( pFile, " %x ", nValueLen ) < 0)
+ fprintf(stderr, "fwrite to db failed\n");
+ if( nValueLen > 0 )
+ {
+ if (fwrite( aValueStr.c_str(), 1, nValueLen, pFile ) != nValueLen)
+ fprintf(stderr, "fwrite to db failed\n");
+ }
+ if (fprintf( pFile, "%c", cLF ) < 0)
+ fprintf(stderr, "fwrite to db failed\n");
+}
+
+class HelpKeyword
+{
+private:
+ typedef std::hash_map<std::string, Data, pref_hash> DataHashtable;
+ DataHashtable _hash;
+
+public:
+ void insert(const std::string &key, const std::string &id)
+ {
+ Data &data = _hash[key];
+ data.append(id);
+ }
+
+ void dump(DB* table)
+ {
+ DataHashtable::const_iterator aEnd = _hash.end();
+ for (DataHashtable::const_iterator aIter = _hash.begin(); aIter != aEnd; ++aIter)
+ {
+ const std::string &keystr = aIter->first;
+ DBT key;
+ memset(&key, 0, sizeof(key));
+ key.data = const_cast<char*>(keystr.c_str());
+ key.size = keystr.length();
+
+ const Data &data = aIter->second;
+ std::string str = data.getString();
+ DBT value;
+ memset(&value, 0, sizeof(value));
+ value.data = const_cast<char*>(str.c_str());
+ value.size = str.length();
+
+ table->put(table, NULL, &key, &value, 0);
+ }
+ }
+
+ void dump_DBHelp( const std::string& rFileName )
+ {
+ FILE* pFile = fopen( rFileName.c_str(), "wb" );
+ if( pFile == NULL )
+ return;
+
+ DataHashtable::const_iterator aEnd = _hash.end();
+ for (DataHashtable::const_iterator aIter = _hash.begin(); aIter != aEnd; ++aIter)
+ writeKeyValue_DBHelp( pFile, aIter->first, aIter->second.getString() );
+
+ fclose( pFile );
+ }
+};
+
+class HelpLinker
+{
+public:
+ void main(std::vector<std::string> &args,
+ std::string* pExtensionPath = NULL, const rtl::OUString* pOfficeHelpPath = NULL )
+ throw( HelpProcessingException );
+
+ HelpLinker()
+ : init(true)
+ , m_pIndexerPreProcessor(NULL)
+ {}
+ ~HelpLinker()
+ { delete m_pIndexerPreProcessor; }
+
+private:
+ int locCount, totCount;
+ Stringtable additionalFiles;
+ HashSet helpFiles;
+ fs::path sourceRoot;
+ fs::path embeddStylesheet;
+ fs::path idxCaptionStylesheet;
+ fs::path idxContentStylesheet;
+ fs::path zipdir;
+ fs::path outputFile;
+ std::string module;
+ std::string lang;
+ std::string hid;
+ std::string extensionPath;
+ bool bExtensionMode;
+ fs::path indexDirName;
+ Stringtable hidlistTranslation;
+ fs::path indexDirParentName;
+ bool init;
+ IndexerPreProcessor* m_pIndexerPreProcessor;
+ void initIndexerPreProcessor();
+ void link() throw( HelpProcessingException );
+ void addBookmark( DB* dbBase, FILE* pFile_DBHelp, std::string thishid,
+ const std::string& fileB, const std::string& anchorB,
+ const std::string& jarfileB, const std::string& titleB );
+#if 0
+ /**
+ * @param outputFile
+ * @param module
+ * @param lang
+ * @param hid
+ * @param helpFiles
+ * @param additionalFiles
+ */
+
+ private HelpURLStreamHandlerFactory urlHandler = null;
+#endif
+};
+
+namespace URLEncoder
+{
+ static std::string encode(const std::string &rIn)
+ {
+ const char *good = "!$&'()*+,-.=@_";
+ static const char hex[17] = "0123456789ABCDEF";
+
+ std::string result;
+ for (size_t i=0; i < rIn.length(); ++i)
+ {
+ unsigned char c = rIn[i];
+ if (isalnum (c) || strchr (good, c))
+ result += c;
+ else {
+ result += '%';
+ result += hex[c >> 4];
+ result += hex[c & 0xf];
+ }
+ }
+ return result;
+ }
+}
+
+void HelpLinker::addBookmark( DB* dbBase, FILE* pFile_DBHelp, std::string thishid,
+ const std::string& fileB, const std::string& anchorB,
+ const std::string& jarfileB, const std::string& titleB)
+{
+ HCDBG(std::cerr << "HelpLinker::addBookmark " << thishid << " " <<
+ fileB << " " << anchorB << " " << jarfileB << " " << titleB << std::endl);
+
+ std::string temp = thishid;
+ std::transform (temp.begin(), temp.end(), temp.begin(), toupper);
+ std::replace(temp.begin(), temp.end(), ':', '_');
+ const std::string& translatedHid = hidlistTranslation[temp];
+ if (!translatedHid.empty())
+ thishid = translatedHid;
+
+ thishid = URLEncoder::encode(thishid);
+
+ DBT key;
+ memset(&key, 0, sizeof(key));
+ key.data = const_cast<char*>(thishid.c_str());
+ key.size = thishid.length();
+
+ int fileLen = fileB.length();
+ if (!anchorB.empty())
+ fileLen += (1 + anchorB.length());
+ int dataLen = 1 + fileLen + 1 + jarfileB.length() + 1 + titleB.length();
+
+ std::vector<unsigned char> dataB(dataLen);
+ size_t i = 0;
+ dataB[i++] = static_cast<unsigned char>(fileLen);
+ for (size_t j = 0; j < fileB.length(); ++j)
+ dataB[i++] = fileB[j];
+ if (!anchorB.empty())
+ {
+ dataB[i++] = '#';
+ for (size_t j = 0; j < anchorB.length(); ++j)
+ dataB[i++] = anchorB[j];
+ }
+ dataB[i++] = static_cast<unsigned char>(jarfileB.length());
+ for (size_t j = 0; j < jarfileB.length(); ++j)
+ dataB[i++] = jarfileB[j];
+
+ dataB[i++] = static_cast<unsigned char>(titleB.length());
+ for (size_t j = 0; j < titleB.length(); ++j)
+ dataB[i++] = titleB[j];
+
+ DBT data;
+ memset(&data, 0, sizeof(data));
+ data.data = &dataB[0];
+ data.size = dataB.size();
+
+ if( dbBase != NULL )
+ dbBase->put(dbBase, NULL, &key, &data, 0);
+
+ if( pFile_DBHelp != NULL )
+ {
+ std::string aValueStr( dataB.begin(), dataB.end() );
+ writeKeyValue_DBHelp( pFile_DBHelp, thishid, aValueStr );
+ }
+}
+
+void HelpLinker::initIndexerPreProcessor()
+{
+ if( m_pIndexerPreProcessor )
+ delete m_pIndexerPreProcessor;
+ std::string mod = module;
+ std::transform (mod.begin(), mod.end(), mod.begin(), tolower);
+ m_pIndexerPreProcessor = new IndexerPreProcessor( mod, indexDirParentName,
+ idxCaptionStylesheet, idxContentStylesheet );
+}
+
+/**
+*
+*/
+void HelpLinker::link() throw( HelpProcessingException )
+{
+ bool bIndexForExtension = true;
+
+ if( bExtensionMode )
+ {
+ indexDirParentName = sourceRoot;
+ }
+ else
+ {
+ indexDirParentName = zipdir;
+ fs::create_directory(indexDirParentName);
+ }
+
+#ifdef CMC_DEBUG
+ std::cerr << "will not delete tmpdir of " << indexDirParentName.native_file_string().c_str() << std::endl;
+#endif
+
+ std::string mod = module;
+ std::transform (mod.begin(), mod.end(), mod.begin(), tolower);
+
+ // do the work here
+ // continue with introduction of the overall process thing into the
+ // here all hzip files will be worked on
+ std::string appl = mod;
+ if (appl[0] == 's')
+ appl = appl.substr(1);
+
+ bool bUse_ = true;
+#ifdef DBHELP_ONLY
+ if( !bExtensionMode )
+ bUse_ = false;
+#endif
+
+ DB* helpText(0);
+#ifndef DBHELP_ONLY
+ fs::path helpTextFileName(indexDirParentName / (mod + ".ht"));
+ db_create(&helpText,0,0);
+ helpText->open(helpText, NULL, helpTextFileName.native_file_string().c_str(), NULL, DB_BTREE,
+ DB_CREATE | DB_TRUNCATE, 0644);
+#endif
+
+ fs::path helpTextFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".ht_" : ".ht")));
+ FILE* pFileHelpText_DBHelp = fopen
+ ( helpTextFileName_DBHelp.native_file_string().c_str(), "wb" );
+
+ DB* dbBase(0);
+#ifndef DBHELP_ONLY
+ fs::path dbBaseFileName(indexDirParentName / (mod + ".db"));
+ db_create(&dbBase,0,0);
+ dbBase->open(dbBase, NULL, dbBaseFileName.native_file_string().c_str(), NULL, DB_BTREE,
+ DB_CREATE | DB_TRUNCATE, 0644);
+#endif
+
+ fs::path dbBaseFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".db_" : ".db")));
+ FILE* pFileDbBase_DBHelp = fopen
+ ( dbBaseFileName_DBHelp.native_file_string().c_str(), "wb" );
+
+#ifndef DBHELP_ONLY
+ DB* keyWord(0);
+ fs::path keyWordFileName(indexDirParentName / (mod + ".key"));
+ db_create(&keyWord,0,0);
+ keyWord->open(keyWord, NULL, keyWordFileName.native_file_string().c_str(), NULL, DB_BTREE,
+ DB_CREATE | DB_TRUNCATE, 0644);
+#endif
+
+ fs::path keyWordFileName_DBHelp(indexDirParentName / (mod + (bUse_ ? ".key_" : ".key")));
+
+ HelpKeyword helpKeyword;
+
+ // catch HelpProcessingException to avoid locking data bases
+ try
+ {
+
+ std::ifstream fileReader(hid.c_str());
+ while (fileReader)
+ {
+ std::string key;
+ fileReader >> key;
+ std::transform (key.begin(), key.end(), key.begin(), toupper);
+ std::replace(key.begin(), key.end(), ':', '_');
+ std::string data;
+ fileReader >> data;
+ if (!key.empty() && !data.empty())
+ hidlistTranslation[key] = data;
+ }
+ fileReader.close();
+
+ // lastly, initialize the indexBuilder
+ if ( (!bExtensionMode || bIndexForExtension) && !helpFiles.empty())
+ initIndexerPreProcessor();
+
+ if( !bExtensionMode )
+ {
+#ifndef OS2 // YD @TODO@ crashes libc runtime :-(
+ std::cout << "Making " << outputFile.native_file_string() <<
+ " from " << helpFiles.size() << " input files" << std::endl;
+#endif
+ }
+
+ // here we start our loop over the hzip files.
+ HashSet::iterator end = helpFiles.end();
+ for (HashSet::iterator iter = helpFiles.begin(); iter != end; ++iter)
+ {
+ if( !bExtensionMode )
+ {
+ std::cout << ".";
+ std::cout.flush();
+ }
+
+ // process one file
+ // streamTable contains the streams in the hzip file
+ StreamTable streamTable;
+ const std::string &xhpFileName = *iter;
+
+ if (!bExtensionMode && xhpFileName.rfind(".xhp") != xhpFileName.length()-4)
+ {
+ // only work on .xhp - files
+ std::cerr <<
+ "ERROR: input list entry '"
+ << xhpFileName
+ << "' has the wrong extension (only files with extension .xhp "
+ << "are accepted)";
+ continue;
+ }
+
+ fs::path langsourceRoot(sourceRoot);
+ fs::path xhpFile;
+
+ if( bExtensionMode )
+ {
+ // langsourceRoot == sourceRoot for extensions
+ std::string xhpFileNameComplete( extensionPath );
+ xhpFileNameComplete.append( '/' + xhpFileName );
+ xhpFile = fs::path( xhpFileNameComplete );
+ }
+ else
+ {
+ langsourceRoot.append('/' + lang + '/');
+ xhpFile = fs::path(xhpFileName, fs::native);
+ }
+
+ HelpCompiler hc( streamTable, xhpFile, langsourceRoot,
+ embeddStylesheet, module, lang, bExtensionMode );
+
+ HCDBG(std::cerr << "before compile of " << xhpFileName << std::endl);
+ bool success = hc.compile();
+ HCDBG(std::cerr << "after compile of " << xhpFileName << std::endl);
+
+ if (!success && !bExtensionMode)
+ {
+ std::stringstream aStrStream;
+ aStrStream <<
+ "\nERROR: compiling help particle '"
+ << xhpFileName
+ << "' for language '"
+ << lang
+ << "' failed!";
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ const std::string documentBaseId = streamTable.document_id;
+ std::string documentPath = streamTable.document_path;
+ if (documentPath.find("/") == 0)
+ documentPath = documentPath.substr(1);
+
+ std::string documentJarfile = streamTable.document_module + ".jar";
+
+ std::string documentTitle = streamTable.document_title;
+ if (documentTitle.empty())
+ documentTitle = "<notitle>";
+
+#if 0
+ std::cout << "for " << xhpFileName << " documentBaseId is " << documentBaseId << "\n";
+ std::cout << "for " << xhpFileName << " documentPath is " << documentPath << "\n";
+ std::cout << "for " << xhpFileName << " documentJarfile is " << documentJarfile << "\n";
+ std::cout << "for " << xhpFileName << " documentPath is " << documentTitle << "\n";
+#endif
+
+ const std::string& fileB = documentPath;
+ const std::string& jarfileB = documentJarfile;
+ std::string& titleB = documentTitle;
+
+ // add once this as its own id.
+ addBookmark(dbBase, pFileDbBase_DBHelp, documentPath, fileB, std::string(), jarfileB, titleB);
+
+ // first the database *.db
+ // ByteArrayInputStream bais = null;
+ // ObjectInputStream ois = null;
+
+ const HashSet *hidlist = streamTable.appl_hidlist;
+ if (!hidlist)
+ hidlist = streamTable.default_hidlist;
+ if (hidlist && !hidlist->empty())
+ {
+ // now iterate over all elements of the hidlist
+ HashSet::const_iterator aEnd = hidlist->end();
+ for (HashSet::const_iterator hidListIter = hidlist->begin();
+ hidListIter != aEnd; ++hidListIter)
+ {
+ std::string thishid = *hidListIter;
+
+ std::string anchorB;
+ size_t index = thishid.rfind('#');
+ if (index != std::string::npos)
+ {
+ anchorB = thishid.substr(1 + index);
+ thishid = thishid.substr(0, index);
+ }
+ addBookmark(dbBase, pFileDbBase_DBHelp, thishid, fileB, anchorB, jarfileB, titleB);
+ }
+ }
+
+ // now the keywords
+ const Hashtable *anchorToLL = streamTable.appl_keywords;
+ if (!anchorToLL)
+ anchorToLL = streamTable.default_keywords;
+ if (anchorToLL && !anchorToLL->empty())
+ {
+ std::string fakedHid = URLEncoder::encode(documentPath);
+ Hashtable::const_iterator aEnd = anchorToLL->end();
+ for (Hashtable::const_iterator enumer = anchorToLL->begin();
+ enumer != aEnd; ++enumer)
+ {
+ const std::string &anchor = enumer->first;
+ addBookmark(dbBase, pFileDbBase_DBHelp, documentPath, fileB,
+ anchor, jarfileB, titleB);
+ std::string totalId = fakedHid + "#" + anchor;
+ // std::cerr << hzipFileName << std::endl;
+ const LinkedList& ll = enumer->second;
+ LinkedList::const_iterator aOtherEnd = ll.end();
+ for (LinkedList::const_iterator llIter = ll.begin();
+ llIter != aOtherEnd; ++llIter)
+ {
+ helpKeyword.insert(*llIter, totalId);
+ }
+ }
+
+ }
+
+ // and last the helptexts
+ const Stringtable *helpTextHash = streamTable.appl_helptexts;
+ if (!helpTextHash)
+ helpTextHash = streamTable.default_helptexts;
+ if (helpTextHash && !helpTextHash->empty())
+ {
+ Stringtable::const_iterator aEnd = helpTextHash->end();
+ for (Stringtable::const_iterator helpTextIter = helpTextHash->begin();
+ helpTextIter != aEnd; ++helpTextIter)
+ {
+ std::string helpTextId = helpTextIter->first;
+ const std::string& helpTextText = helpTextIter->second;
+
+ std::string temp = helpTextId;
+ std::transform (temp.begin(), temp.end(), temp.begin(), toupper);
+ std::replace(temp.begin(), temp.end(), ':', '_');
+
+ const std::string& tHid = hidlistTranslation[temp];
+ if (!tHid.empty())
+ helpTextId = tHid;
+ helpTextId = URLEncoder::encode(helpTextId);
+
+ DBT keyDbt;
+ memset(&keyDbt, 0, sizeof(keyDbt));
+ keyDbt.data = const_cast<char*>(helpTextId.c_str());
+ keyDbt.size = helpTextId.length();
+
+ DBT textDbt;
+ memset(&textDbt, 0, sizeof(textDbt));
+ textDbt.data = const_cast<char*>(helpTextText.c_str());
+ textDbt.size = helpTextText.length();
+
+ if( helpText != NULL )
+ helpText->put(helpText, NULL, &keyDbt, &textDbt, 0);
+
+ if( pFileHelpText_DBHelp != NULL )
+ writeKeyValue_DBHelp( pFileHelpText_DBHelp, helpTextId, helpTextText );
+ }
+ }
+
+ //IndexerPreProcessor
+ if( !bExtensionMode || bIndexForExtension )
+ {
+ // now the indexing
+ xmlDocPtr document = streamTable.appl_doc;
+ if (!document)
+ document = streamTable.default_doc;
+ if (document)
+ {
+ std::string temp = module;
+ std::transform (temp.begin(), temp.end(), temp.begin(), tolower);
+ m_pIndexerPreProcessor->processDocument(document, URLEncoder::encode(documentPath) );
+ }
+ }
+
+ } // while loop over hzip files ending
+ if( !bExtensionMode )
+ std::cout << std::endl;
+
+ } // try
+ catch( HelpProcessingException& )
+ {
+ // catch HelpProcessingException to avoid locking data bases
+#ifndef DBHELP_ONLY
+ helpText->close(helpText, 0);
+ dbBase->close(dbBase, 0);
+ keyWord->close(keyWord, 0);
+#endif
+ if( pFileHelpText_DBHelp != NULL )
+ fclose( pFileHelpText_DBHelp );
+ if( pFileDbBase_DBHelp != NULL )
+ fclose( pFileDbBase_DBHelp );
+ throw;
+ }
+
+#ifndef DBHELP_ONLY
+ helpText->close(helpText, 0);
+ dbBase->close(dbBase, 0);
+ helpKeyword.dump(keyWord);
+ keyWord->close(keyWord, 0);
+#endif
+ if( pFileHelpText_DBHelp != NULL )
+ fclose( pFileHelpText_DBHelp );
+ if( pFileDbBase_DBHelp != NULL )
+ fclose( pFileDbBase_DBHelp );
+
+ helpKeyword.dump_DBHelp( keyWordFileName_DBHelp.native_file_string() );
+
+ if( !bExtensionMode )
+ {
+ // New index
+ Stringtable::iterator aEnd = additionalFiles.end();
+ for (Stringtable::iterator enumer = additionalFiles.begin(); enumer != aEnd;
+ ++enumer)
+ {
+ const std::string &additionalFileName = enumer->second;
+ const std::string &additionalFileKey = enumer->first;
+
+ fs::path fsAdditionalFileName( additionalFileName, fs::native );
+ std::string aNativeStr = fsAdditionalFileName.native_file_string();
+ const char* pStr = aNativeStr.c_str();
+ std::cerr << pStr;
+
+ fs::path fsTargetName( indexDirParentName / additionalFileKey );
+
+ fs::copy( fsAdditionalFileName, fsTargetName );
+ }
+ }
+
+/*
+ /////////////////////////////////////////////////////////////////////////
+ /// remove temprary directory for index creation
+ /////////////////////////////////////////////////////////////////////////
+#ifndef CMC_DEBUG
+ if( !bExtensionMode )
+ fs::remove_all( indexDirParentName );
+#endif
+*/
+}
+
+
+void HelpLinker::main( std::vector<std::string> &args,
+ std::string* pExtensionPath, const rtl::OUString* pOfficeHelpPath )
+ throw( HelpProcessingException )
+{
+ rtl::OUString aOfficeHelpPath;
+
+ bExtensionMode = false;
+ if( pExtensionPath && pExtensionPath->length() > 0 && pOfficeHelpPath )
+ {
+ helpFiles.clear();
+ bExtensionMode = true;
+ extensionPath = *pExtensionPath;
+ sourceRoot = fs::path(extensionPath);
+
+ aOfficeHelpPath = *pOfficeHelpPath;
+ }
+ if (args.size() > 0 && args[0][0] == '@')
+ {
+ std::vector<std::string> stringList;
+ std::string strBuf;
+ std::ifstream fileReader(args[0].substr(1).c_str());
+
+ while (fileReader)
+ {
+ std::string token;
+ fileReader >> token;
+ if (!token.empty())
+ stringList.push_back(token);
+ }
+ fileReader.close();
+
+ args = stringList;
+ }
+
+ size_t i = 0;
+
+ while (i < args.size())
+ {
+ if (args[i].compare("-src") == 0)
+ {
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "sourceroot missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ if( !bExtensionMode )
+ sourceRoot = fs::path(args[i], fs::native);
+ }
+ else if (args[i].compare("-sty") == 0)
+ {
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "embeddingStylesheet missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ embeddStylesheet = fs::path(args[i], fs::native);
+ }
+ else if (args[i].compare("-zipdir") == 0)
+ {
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "idxtemp missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ zipdir = fs::path(args[i], fs::native);
+ }
+ else if (args[i].compare("-idxcaption") == 0)
+ {
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "idxcaption stylesheet missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ idxCaptionStylesheet = fs::path(args[i], fs::native);
+ }
+ else if (args[i].compare("-idxcontent") == 0)
+ {
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "idxcontent stylesheet missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ idxContentStylesheet = fs::path(args[i], fs::native);
+ }
+ else if (args[i].compare("-o") == 0)
+ {
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "outputfilename missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ outputFile = fs::path(args[i], fs::native);
+ }
+ else if (args[i].compare("-mod") == 0)
+ {
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "module name missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ module = args[i];
+ }
+ else if (args[i].compare("-lang") == 0)
+ {
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "language name missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ lang = args[i];
+ }
+ else if (args[i].compare("-hid") == 0)
+ {
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "hid list missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ hid = args[i];
+ }
+ else if (args[i].compare("-add") == 0)
+ {
+ std::string addFile, addFileUnderPath;
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "pathname missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ addFileUnderPath = args[i];
+ ++i;
+ if (i >= args.size())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "pathname missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ addFile = args[i];
+ if (!addFileUnderPath.empty() && !addFile.empty())
+ additionalFiles[addFileUnderPath] = addFile;
+ }
+ else
+ helpFiles.push_back(args[i]);
+ ++i;
+ }
+
+ if (!bExtensionMode && zipdir.empty())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "no index dir given" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ if (!bExtensionMode && idxCaptionStylesheet.empty())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "no index caption stylesheet given" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ else if ( bExtensionMode )
+ {
+ rtl::OUString aIdxCaptionPathFileURL( aOfficeHelpPath );
+ aIdxCaptionPathFileURL += rtl::OUString::createFromAscii( "/idxcaption.xsl" );
+
+ rtl::OString aOStr_IdxCaptionPathFileURL( rtl::OUStringToOString
+ ( aIdxCaptionPathFileURL, fs::getThreadTextEncoding() ) );
+ std::string aStdStr_IdxCaptionPathFileURL( aOStr_IdxCaptionPathFileURL.getStr() );
+
+ idxCaptionStylesheet = fs::path( aStdStr_IdxCaptionPathFileURL );
+ }
+ if (!bExtensionMode && idxContentStylesheet.empty())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "no index content stylesheet given" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ else if ( bExtensionMode )
+ {
+ rtl::OUString aIdxContentPathFileURL( aOfficeHelpPath );
+ aIdxContentPathFileURL += rtl::OUString::createFromAscii( "/idxcontent.xsl" );
+
+ rtl::OString aOStr_IdxContentPathFileURL( rtl::OUStringToOString
+ ( aIdxContentPathFileURL, fs::getThreadTextEncoding() ) );
+ std::string aStdStr_IdxContentPathFileURL( aOStr_IdxContentPathFileURL.getStr() );
+
+ idxContentStylesheet = fs::path( aStdStr_IdxContentPathFileURL );
+ }
+ if (!bExtensionMode && embeddStylesheet.empty())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "no embedding resolving file given" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ if (sourceRoot.empty())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "no sourceroot given" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ if (!bExtensionMode && outputFile.empty())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "no output file given" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ if (module.empty())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "module missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ if (!bExtensionMode && lang.empty())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "language missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+ if (!bExtensionMode && hid.empty())
+ {
+ std::stringstream aStrStream;
+ aStrStream << "hid list missing" << std::endl;
+ throw HelpProcessingException( HELPPROCESSING_GENERAL_ERROR, aStrStream.str() );
+ }
+
+ link();
+}
+
+int main(int argc, char**argv)
+{
+ sal_uInt32 starttime = osl_getGlobalTimer();
+ std::vector<std::string> args;
+ for (int i = 1; i < argc; ++i)
+ args.push_back(std::string(argv[i]));
+ try
+ {
+ HelpLinker* pHelpLinker = new HelpLinker();
+ pHelpLinker->main( args );
+ delete pHelpLinker;
+ }
+ catch( const HelpProcessingException& e )
+ {
+ std::cerr << e.m_aErrorMsg;
+ exit(1);
+ }
+ sal_uInt32 endtime = osl_getGlobalTimer();
+#ifndef OS2 // YD @TODO@ crashes libc runtime :-(
+ std::cout << "time taken was " << (endtime-starttime)/1000.0 << " seconds" << std::endl;
+#endif
+ return 0;
+}
+
+// Variable to set an exception in "C" StructuredXMLErrorFunction
+static const HelpProcessingException* GpXMLParsingException = NULL;
+
+extern "C" void StructuredXMLErrorFunction(void *userData, xmlErrorPtr error)
+{
+ (void)userData;
+ (void)error;
+
+ std::string aErrorMsg = error->message;
+ std::string aXMLParsingFile;
+ if( error->file != NULL )
+ aXMLParsingFile = error->file;
+ int nXMLParsingLine = error->line;
+ HelpProcessingException* pException = new HelpProcessingException( aErrorMsg, aXMLParsingFile, nXMLParsingLine );
+ GpXMLParsingException = pException;
+
+ // Reset error handler
+ xmlSetStructuredErrorFunc( NULL, NULL );
+}
+
+HelpProcessingErrorInfo& HelpProcessingErrorInfo::operator=( const struct HelpProcessingException& e )
+{
+ m_eErrorClass = e.m_eErrorClass;
+ rtl::OString tmpErrorMsg( e.m_aErrorMsg.c_str() );
+ m_aErrorMsg = rtl::OStringToOUString( tmpErrorMsg, fs::getThreadTextEncoding() );
+ rtl::OString tmpXMLParsingFile( e.m_aXMLParsingFile.c_str() );
+ m_aXMLParsingFile = rtl::OStringToOUString( tmpXMLParsingFile, fs::getThreadTextEncoding() );
+ m_nXMLParsingLine = e.m_nXMLParsingLine;
+ return *this;
+}
+
+
+// Returns true in case of success, false in case of error
+HELPLINKER_DLLPUBLIC bool compileExtensionHelp
+(
+ const rtl::OUString& aOfficeHelpPath,
+ const rtl::OUString& aExtensionName,
+ const rtl::OUString& aExtensionLanguageRoot,
+ sal_Int32 nXhpFileCount, const rtl::OUString* pXhpFiles,
+ HelpProcessingErrorInfo& o_rHelpProcessingErrorInfo
+)
+{
+ bool bSuccess = true;
+
+ sal_Int32 argc = nXhpFileCount + 3;
+ const char** argv = new const char*[argc];
+ argv[0] = "";
+ argv[1] = "-mod";
+ rtl::OString aOExtensionName = rtl::OUStringToOString( aExtensionName, fs::getThreadTextEncoding() );
+ argv[2] = aOExtensionName.getStr();
+
+ for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp )
+ {
+ rtl::OUString aXhpFile = pXhpFiles[iXhp];
+
+ rtl::OString aOXhpFile = rtl::OUStringToOString( aXhpFile, fs::getThreadTextEncoding() );
+ char* pArgStr = new char[aOXhpFile.getLength() + 1];
+ strcpy( pArgStr, aOXhpFile.getStr() );
+ argv[iXhp + 3] = pArgStr;
+ }
+
+ std::vector<std::string> args;
+ for( sal_Int32 i = 1; i < argc; ++i )
+ args.push_back(std::string( argv[i]) );
+
+ for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp )
+ delete argv[iXhp + 3];
+ delete[] argv;
+
+ rtl::OString aOExtensionLanguageRoot = rtl::OUStringToOString( aExtensionLanguageRoot, fs::getThreadTextEncoding() );
+ const char* pExtensionPath = aOExtensionLanguageRoot.getStr();
+ std::string aStdStrExtensionPath = pExtensionPath;
+
+ // Set error handler
+ xmlSetStructuredErrorFunc( NULL, (xmlStructuredErrorFunc)StructuredXMLErrorFunction );
+ try
+ {
+ HelpLinker* pHelpLinker = new HelpLinker();
+ pHelpLinker->main( args, &aStdStrExtensionPath, &aOfficeHelpPath );
+ delete pHelpLinker;
+ }
+ catch( const HelpProcessingException& e )
+ {
+ if( GpXMLParsingException != NULL )
+ {
+ o_rHelpProcessingErrorInfo = *GpXMLParsingException;
+ delete GpXMLParsingException;
+ GpXMLParsingException = NULL;
+ }
+ else
+ {
+ o_rHelpProcessingErrorInfo = e;
+ }
+ bSuccess = false;
+ }
+ // Reset error handler
+ xmlSetStructuredErrorFunc( NULL, NULL );
+
+ // i83624: Tree files
+ ::rtl::OUString aTreeFileURL = aExtensionLanguageRoot;
+ aTreeFileURL += rtl::OUString::createFromAscii( "/help.tree" );
+ osl::DirectoryItem aTreeFileItem;
+ osl::FileBase::RC rcGet = osl::DirectoryItem::get( aTreeFileURL, aTreeFileItem );
+ osl::FileStatus aFileStatus( FileStatusMask_FileSize );
+ if( rcGet == osl::FileBase::E_None &&
+ aTreeFileItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None &&
+ aFileStatus.isValid( FileStatusMask_FileSize ) )
+ {
+ sal_uInt64 ret, len = aFileStatus.getFileSize();
+ char* s = new char[ int(len) ]; // the buffer to hold the installed files
+ osl::File aFile( aTreeFileURL );
+ aFile.open( OpenFlag_Read );
+ aFile.read( s, len, ret );
+ aFile.close();
+
+ XML_Parser parser = XML_ParserCreate( 0 );
+ int parsed = XML_Parse( parser, s, int( len ), true );
+
+ if( parsed == 0 )
+ {
+ XML_Error nError = XML_GetErrorCode( parser );
+ o_rHelpProcessingErrorInfo.m_eErrorClass = HELPPROCESSING_XMLPARSING_ERROR;
+ o_rHelpProcessingErrorInfo.m_aErrorMsg = rtl::OUString::createFromAscii( XML_ErrorString( nError ) );;
+ o_rHelpProcessingErrorInfo.m_aXMLParsingFile = aTreeFileURL;
+ // CRAHSES!!! o_rHelpProcessingErrorInfo.m_nXMLParsingLine = XML_GetCurrentLineNumber( parser );
+ bSuccess = false;
+ }
+
+ XML_ParserFree( parser );
+ delete[] s;
+ }
+
+ return bSuccess;
+}
+
+// vnd.sun.star.help://swriter/52821?Language=en-US&System=UNIX
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */
+
diff --git a/l10ntools/source/help/compilehelp.hxx b/l10ntools/source/help/compilehelp.hxx
new file mode 100644
index 000000000000..d123d628be27
--- /dev/null
+++ b/l10ntools/source/help/compilehelp.hxx
@@ -0,0 +1,81 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: compilehelp.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef COMPILE_HXX
+#define COMPILE_HXX
+
+#include "sal/types.h"
+
+#if defined(HELPLINKER_DLLIMPLEMENTATION)
+#define HELPLINKER_DLLPUBLIC SAL_DLLPUBLIC_EXPORT
+#else
+#define HELPLINKER_DLLPUBLIC SAL_DLLPUBLIC_IMPORT
+#endif
+#define HELPLINKER_DLLPRIVATE SAL_DLLPRIVATE
+
+
+//#include <helplinkerdllapi.h>
+#include <rtl/ustring.hxx>
+
+enum HelpProcessingErrorClass
+{
+ HELPPROCESSING_NO_ERROR,
+ HELPPROCESSING_GENERAL_ERROR, // Missing files, options etc.
+ HELPPROCESSING_INTERNAL_ERROR, // Unexpected problems
+ HELPPROCESSING_XMLPARSING_ERROR // Errors thrown by libxml
+};
+
+struct HelpProcessingErrorInfo
+{
+ HelpProcessingErrorClass m_eErrorClass;
+ rtl::OUString m_aErrorMsg;
+ rtl::OUString m_aXMLParsingFile;
+ sal_Int32 m_nXMLParsingLine;
+
+ HelpProcessingErrorInfo( void )
+ : m_eErrorClass( HELPPROCESSING_NO_ERROR )
+ , m_nXMLParsingLine( -1 )
+ {}
+
+ HelpProcessingErrorInfo& operator=( const struct HelpProcessingException& e );
+};
+
+
+// Returns true in case of success, false in case of error
+HELPLINKER_DLLPUBLIC bool compileExtensionHelp
+(
+ const rtl::OUString& aOfficeHelpPath,
+ const rtl::OUString& aExtensionName,
+ const rtl::OUString& aExtensionLanguageRoot,
+ sal_Int32 nXhpFileCount, const rtl::OUString* pXhpFiles,
+ HelpProcessingErrorInfo& o_rHelpProcessingErrorInfo
+);
+
+#endif
diff --git a/l10ntools/source/help/helplinker.pmk b/l10ntools/source/help/helplinker.pmk
new file mode 100644
index 000000000000..569c5f4dbdee
--- /dev/null
+++ b/l10ntools/source/help/helplinker.pmk
@@ -0,0 +1,35 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: helplinker.pmk,v $
+#
+# $Revision: 1.4 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+# define HELPLINKER_DLLIMPLEMENTATION (see @ inc/xmlhelp/helplinkerdllapi.h)
+CDEFS += -DHELPLINKER_DLLIMPLEMENTATION
+
+VISIBILITY_HIDDEN=TRUE
diff --git a/l10ntools/source/help/makefile.mk b/l10ntools/source/help/makefile.mk
new file mode 100644
index 000000000000..57164004af8b
--- /dev/null
+++ b/l10ntools/source/help/makefile.mk
@@ -0,0 +1,120 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.38 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ = ..$/..
+PRJNAME = l10ntools
+TARGET = HelpLinker
+LIBBASENAME = helplinker
+PACKAGE = com$/sun$/star$/help
+TARGETTYPE=CUI
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : helplinker.pmk
+
+.IF "$(SYSTEM_LIBXSLT)" == "YES"
+CFLAGS+= $(LIBXSLT_CFLAGS)
+.ELSE
+LIBXSLTINCDIR=external$/libxslt
+CFLAGS+= -I$(SOLARINCDIR)$/$(LIBXSLTINCDIR)
+.ENDIF
+
+.IF "$(SYSTEM_DB)" == "YES"
+CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES)
+.ENDIF
+
+.IF "$(SYSTEM_EXPAT)" == "YES"
+CFLAGS+=-DSYSTEM_EXPAT
+.ENDIF
+
+OBJFILES=\
+ $(OBJ)$/HelpLinker.obj \
+ $(OBJ)$/HelpCompiler.obj
+SLOFILES=\
+ $(SLO)$/HelpLinker.obj \
+ $(SLO)$/HelpCompiler.obj
+
+EXCEPTIONSFILES=\
+ $(OBJ)$/HelpLinker.obj \
+ $(OBJ)$/HelpCompiler.obj \
+ $(SLO)$/HelpLinker.obj \
+ $(SLO)$/HelpCompiler.obj
+.IF "$(OS)" == "MACOSX" && "$(CPU)" == "P" && "$(COM)" == "GCC"
+# There appears to be a GCC 4.0.1 optimization error causing _file:good() to
+# report true right before the call to writeOut at HelpLinker.cxx:1.12 l. 954
+# but out.good() to report false right at the start of writeOut at
+# HelpLinker.cxx:1.12 l. 537:
+NOOPTFILES=\
+ $(OBJ)$/HelpLinker.obj \
+ $(SLO)$/HelpLinker.obj
+.ENDIF
+
+APP1TARGET= $(TARGET)
+APP1OBJS=\
+ $(OBJ)$/HelpLinker.obj \
+ $(OBJ)$/HelpCompiler.obj
+
+APP1STDLIBS+=$(SALLIB) $(BERKELEYLIB) $(XSLTLIB) $(EXPATASCII3RDLIB)
+
+SHL1TARGET =$(LIBBASENAME)$(DLLPOSTFIX)
+SHL1LIBS= $(SLB)$/$(TARGET).lib
+SHL1IMPLIB =i$(LIBBASENAME)
+SHL1DEF =$(MISC)$/$(SHL1TARGET).def
+SHL1STDLIBS =$(SALLIB) $(BERKELEYLIB) $(XSLTLIB) $(EXPATASCII3RDLIB)
+SHL1USE_EXPORTS =ordinal
+
+DEF1NAME =$(SHL1TARGET)
+DEFLIB1NAME =$(TARGET)
+
+JAVAFILES = \
+ HelpIndexerTool.java \
+ HelpFileDocument.java
+
+
+JAVACLASSFILES = \
+ $(CLASSDIR)$/$(PACKAGE)$/HelpIndexerTool.class \
+ $(CLASSDIR)$/$(PACKAGE)$/HelpFileDocument.class
+
+.IF "$(SYSTEM_LUCENE)" == "YES"
+CLASSPATH!:=$(CLASSPATH)$(PATH_SEPERATOR)$(LUCENE_CORE_JAR)$(PATH_SEPERATOR)$(LUCENE_ANALYZERS_JAR)
+.ELSE
+JARFILES += lucene-core-2.3.jar lucene-analyzers-2.3.jar
+.ENDIF
+JAVAFILES = $(subst,$(CLASSDIR)$/$(PACKAGE)$/, $(subst,.class,.java $(JAVACLASSFILES)))
+
+JARCLASSDIRS = $(PACKAGE)/*
+JARTARGET = HelpIndexerTool.jar
+JARCOMPRESS = TRUE
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/l10ntools/source/helpex.cxx b/l10ntools/source/helpex.cxx
new file mode 100644
index 000000000000..8f0b6c1d218f
--- /dev/null
+++ b/l10ntools/source/helpex.cxx
@@ -0,0 +1,299 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: helpex.cxx,v $
+ * $Revision: 1.14 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <stdio.h>
+#include <stdlib.h>
+
+// local includes
+#include "helpmerge.hxx"
+
+// defines to parse command line
+#define STATE_NON 0x0001
+#define STATE_INPUT 0x0002
+#define STATE_OUTPUT 0x0003
+#define STATE_PRJ 0x0004
+#define STATE_ROOT 0x0005
+#define STATE_SDFFILE 0x0006
+#define STATE_ERRORLOG 0x0007
+#define STATE_BREAKHELP 0x0008
+#define STATE_UNMERGE 0x0009
+#define STATE_UTF8 0x000A
+#define STATE_LANGUAGES 0x000B
+#define STATE_FORCE_LANGUAGES 0x000C
+#define STATE_OUTPUTX 0xfe
+#define STATE_OUTPUTY 0xff
+
+// set of global variables
+ByteString sInputFile;
+BOOL bEnableExport;
+BOOL bMergeMode;
+BOOL bErrorLog;
+BOOL bUTF8;
+ByteString sPrj;
+ByteString sPrjRoot;
+ByteString sOutputFile;
+ByteString sOutputFileX;
+ByteString sOutputFileY;
+ByteString sSDFFile;
+bool bQuiet;
+
+/*****************************************************************************/
+BOOL ParseCommandLine( int argc, char* argv[])
+/*****************************************************************************/
+{
+ bEnableExport = FALSE;
+ bMergeMode = FALSE;
+ bErrorLog = TRUE;
+ bUTF8 = TRUE;
+ sPrj = "";
+ sPrjRoot = "";
+ bQuiet = false;
+ Export::sLanguages = "";
+ Export::sForcedLanguages = "";
+
+ USHORT nState = STATE_NON;
+ BOOL bInput = FALSE;
+
+ // parse command line
+ for( int i = 1; i < argc; i++ ) {
+ if ( ByteString( argv[ i ]).ToUpperAscii() == "-I" ) {
+ nState = STATE_INPUT; // next tokens specifies source files
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-O" ) {
+ nState = STATE_OUTPUT; // next token specifies the dest file
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-X" ) {
+ nState = STATE_OUTPUTX; // next token specifies the dest file
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-Y" ) {
+ nState = STATE_OUTPUTY; // next token specifies the dest file
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-P" ) {
+ nState = STATE_PRJ; // next token specifies the cur. project
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-LF" ) {
+ nState = STATE_FORCE_LANGUAGES;
+ }
+
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-R" ) {
+ nState = STATE_ROOT; // next token specifies path to project root
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-M" ) {
+ nState = STATE_SDFFILE; // next token specifies the merge database
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-E" ) {
+ nState = STATE_ERRORLOG;
+ bErrorLog = FALSE;
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-QQ" ) {
+ bQuiet = true;
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-UTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = TRUE;
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-NOUTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = FALSE;
+ }
+ else if ( ByteString( argv[ i ]).ToUpperAscii() == "-L" ) {
+ nState = STATE_LANGUAGES;
+ }
+ else {
+ switch ( nState ) {
+ case STATE_NON: {
+ return FALSE; // no valid command line
+ }
+ //break;
+ case STATE_INPUT: {
+ sInputFile = argv[ i ];
+ bInput = TRUE; // source file found
+ }
+ break;
+ case STATE_OUTPUT: {
+ sOutputFile = argv[ i ]; // the dest. file
+ }
+ break;
+ case STATE_OUTPUTX: {
+ sOutputFileX = argv[ i ]; // the dest. file
+ }
+ break;
+ case STATE_OUTPUTY: {
+ sOutputFileY = argv[ i ]; // the dest. file
+ }
+ break;
+ case STATE_PRJ: {
+ sPrj = argv[ i ];
+// sPrj.ToLowerAscii(); // the project
+ }
+ break;
+ case STATE_ROOT: {
+ sPrjRoot = argv[ i ]; // path to project root
+ }
+ break;
+ case STATE_SDFFILE: {
+ sSDFFile = argv[ i ];
+ bMergeMode = TRUE; // activate merge mode, cause merge database found
+ }
+ break;
+ case STATE_LANGUAGES: {
+ Export::sLanguages = argv[ i ];
+ }
+ case STATE_FORCE_LANGUAGES:{
+ Export::sForcedLanguages = argv[ i ];
+ }
+ break;
+ }
+ }
+ }
+
+ if ( bInput ) {
+ // command line is valid
+ bEnableExport = TRUE;
+ return TRUE;
+ }
+
+ // command line is not valid
+ return FALSE;
+}
+
+
+/*****************************************************************************/
+void Help()
+/*****************************************************************************/
+{
+ fprintf( stdout, "Syntax: HELPEX[-p Prj][-r PrjRoot]-i FileIn ( -o FileOut | -x path -y relfile )[-m DataBase][-e][-b][-u][-L l1,l2,...][-QQ] -LF l1,l2 \n" );
+ fprintf( stdout, " Prj: Project\n" );
+ fprintf( stdout, " PrjRoot: Path to project root (..\\.. etc.)\n" );
+ fprintf( stdout, " FileIn: Source file (*.lng)\n" );
+ fprintf( stdout, " FileOut: Destination file (*.*)\n" );
+ fprintf( stdout, " DataBase: Mergedata (*.sdf)\n" );
+ fprintf( stdout, " -QQ: quiet output\n" );
+ fprintf( stdout, " -L: Restrict the handled languages. l1,l2,... are elements of (en-US,fr,de...)\n" );
+ fprintf( stdout, " A fallback language can be defined like this: l1=f1.\n" );
+ fprintf( stdout, " f1, f2,... are also elements of (en-US,fr,de...)\n" );
+ fprintf( stdout, " Example: -L fr=en-US\n" );
+ fprintf( stdout, " Restriction to fr, en-US will be fallback for fr\n" );
+ fprintf( stdout, " -LF: Force the creation of that languages\n" );
+
+}
+
+/*****************************************************************************/
+#ifndef TESTDRIVER
+
+#if defined(UNX) || defined(OS2)
+int main( int argc, char *argv[] )
+#else
+int _cdecl main( int argc, char *argv[] )
+#endif
+/*****************************************************************************/
+{
+
+ if ( !ParseCommandLine( argc, argv )) {
+ Help();
+ return 1;
+ }
+ //sal_uInt32 startfull = Export::startMessure();
+
+ bool hasInputList = sInputFile.GetBuffer()[0]=='@';
+// printf("x = %s , y = %s , o = %s\n", sOutputFileX.GetBuffer(), sOutputFileY.GetBuffer() , sOutputFile.GetBuffer() );
+ bool hasNoError = true;
+
+ if ( sOutputFile.Len() ){ // Merge single file ?
+ //printf("DBG: Inputfile = %s\n",sInputFile.GetBuffer());
+ HelpParser aParser( sInputFile, bUTF8 , false );
+
+ if ( bMergeMode )
+ {
+
+ //sal_uInt64 startreadloc = Export::startMessure();
+ MergeDataFile aMergeDataFile( sSDFFile, sInputFile , FALSE, RTL_TEXTENCODING_MS_1252 );
+ //MergeDataFile aMergeDataFile( sSDFFile, sInputFile , FALSE, RTL_TEXTENCODING_MS_1252, false );
+ //Export::stopMessure( ByteString("read localize.sdf") , startreadloc );
+
+ hasNoError = aParser.Merge( sSDFFile, sOutputFile , Export::sLanguages , aMergeDataFile );
+ }
+ else
+ hasNoError = aParser.CreateSDF( sOutputFile, sPrj, sPrjRoot, sInputFile, new XMLFile( '0' ), "help" );
+ }else if ( sOutputFileX.Len() && sOutputFileY.Len() && hasInputList ) { // Merge multiple files ?
+ if ( bMergeMode ){
+
+ ifstream aFStream( sInputFile.Copy( 1 , sInputFile.Len() ).GetBuffer() , ios::in );
+
+ if( !aFStream ){
+ cerr << "ERROR: - helpex - Can't open the file " << sInputFile.Copy( 1 , sInputFile.Len() ).GetBuffer() << "\n";
+ exit(-1);
+ }
+
+ vector<ByteString> filelist;
+ rtl::OStringBuffer filename;
+ sal_Char aChar;
+ while( aFStream.get( aChar ) )
+ {
+ if( aChar == ' ' || aChar == '\n')
+ filelist.push_back( ByteString( filename.makeStringAndClear().getStr() ) );
+ else
+ filename.append( aChar );
+ }
+ if( filename.getLength() > 0 )
+ filelist.push_back( ByteString ( filename.makeStringAndClear().getStr() ) );
+
+ aFStream.close();
+ ByteString sHelpFile(""); // dummy
+ //MergeDataFile aMergeDataFile( sSDFFile, sHelpFile , FALSE, RTL_TEXTENCODING_MS_1252, false );
+ MergeDataFile aMergeDataFile( sSDFFile, sHelpFile , FALSE, RTL_TEXTENCODING_MS_1252 );
+
+ //aMergeDataFile.Dump();
+ std::vector<ByteString> aLanguages;
+ HelpParser::parse_languages( aLanguages , aMergeDataFile );
+
+ bool bCreateDir = true;
+ for( vector<ByteString>::iterator pos = filelist.begin() ; pos != filelist.end() ; ++pos )
+ {
+ sHelpFile = *pos;
+ cout << ".";cout.flush();
+
+ HelpParser aParser( sHelpFile , bUTF8 , true );
+ hasNoError = aParser.Merge( sSDFFile , sOutputFileX , sOutputFileY , true , aLanguages , aMergeDataFile , bCreateDir );
+ bCreateDir = false;
+ }
+ }
+ } else
+ cerr << "helpex ERROR: Wrong input parameters!\n";
+
+ //Export::stopMessure( ByteString("full cycle") , startfull );
+ if( hasNoError )
+ return 0;
+ else
+ return 1;
+}
+#endif
diff --git a/l10ntools/source/helpmerge.cxx b/l10ntools/source/helpmerge.cxx
new file mode 100644
index 000000000000..84d73e94f312
--- /dev/null
+++ b/l10ntools/source/helpmerge.cxx
@@ -0,0 +1,730 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: helpmerge.cxx,v $
+ * $Revision: 1.24 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <tools/fsys.hxx>
+#include <osl/file.hxx>
+// local includes
+#include <stdio.h>
+#include <stdlib.h>
+#include "helpmerge.hxx"
+#include "utf8conv.hxx"
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include "rtl/strbuf.hxx"
+#ifdef WNT
+#include <direct.h>
+//#include <WinBase.h>
+#include "tools/prewin.h"
+#include <windows.h>
+#include "tools/postwin.h"
+#endif
+
+/*****************************************************************************/
+void HelpParser::FillInFallbacks( LangHashMap& rElem_out, ByteString sLangIdx_in ){
+/*****************************************************************************/
+ static const ByteString ENGLISH_LANGUAGECODE( "en-US" );
+ static const ByteString GERMAN_LANGUAGECODE ( "de" );
+ ByteString sCur;
+ XMLElement* pTmp = NULL;
+ XMLElement* pTmp2 = NULL;
+
+ sCur = sLangIdx_in;
+ ByteString sFallback( sCur );
+ GetIsoFallback( sFallback );
+ if( (rElem_out.find( sFallback ) != rElem_out.end()) && rElem_out[ sFallback ] != NULL ){
+ pTmp2 = rElem_out[ sFallback ];
+ pTmp = new XMLElement( *pTmp2 ) ; // Copy
+ pTmp->SetPos( pTmp2->GetPos()+1 );
+ pTmp->ChangeLanguageTag( String( sLangIdx_in , RTL_TEXTENCODING_ASCII_US) );
+ rElem_out[ sLangIdx_in ] = pTmp;
+ pTmp2 = NULL;
+ }
+ else if( (rElem_out.find( ENGLISH_LANGUAGECODE ) != rElem_out.end()) && rElem_out[ ENGLISH_LANGUAGECODE ] != NULL ){// No English
+ pTmp2 = rElem_out[ ENGLISH_LANGUAGECODE ];
+ pTmp = new XMLElement( *pTmp2 ) ; // Copy
+ pTmp->SetPos( pTmp2->GetPos()+1 );
+ pTmp->ChangeLanguageTag( String( sLangIdx_in , RTL_TEXTENCODING_ASCII_US) );
+ rElem_out[ sCur ] = pTmp;
+ pTmp2 = NULL;
+ }
+ else if( (rElem_out.find( GERMAN_LANGUAGECODE ) != rElem_out.end() ) && rElem_out[ GERMAN_LANGUAGECODE ] != NULL ){// No English
+ pTmp2 = rElem_out[ GERMAN_LANGUAGECODE ];
+ pTmp = new XMLElement( *pTmp2 ); // Copy
+ pTmp->SetPos( pTmp2->GetPos()+1 );
+ pTmp->ChangeLanguageTag( String( sLangIdx_in , RTL_TEXTENCODING_ASCII_US ) );
+ rElem_out[ sCur ] = pTmp;
+ pTmp2 = NULL;
+ }else{
+ fprintf(stdout,"ERROR: No Fallback found for language %s:\n",sCur.GetBuffer());
+ rElem_out[ sCur ]=new XMLElement(); // Use dummy element
+ }
+}
+
+/*****************************************************************************/
+void HelpParser::Dump(XMLHashMap* rElem_in) {
+/*****************************************************************************/
+ for(XMLHashMap::iterator pos = rElem_in->begin();pos != rElem_in->end(); ++pos){
+ Dump(pos->second,pos->first);
+ }
+}
+/*****************************************************************************/
+void HelpParser::Dump(LangHashMap* rElem_in,const ByteString sKey_in) {
+/*****************************************************************************/
+ ByteString x;
+ OString y;
+ fprintf(stdout,"+------------%s-----------+\n",sKey_in.GetBuffer() );
+ for(LangHashMap::iterator posn=rElem_in->begin();posn!=rElem_in->end();++posn){
+ x=posn->first;
+ y=posn->second->ToOString();
+ fprintf(stdout,"key=%s value=%s\n",x.GetBuffer(),y.getStr());
+ }
+ fprintf(stdout,"+--------------------------+\n");
+}
+
+HelpParser::HelpParser( const ByteString &rHelpFile, bool rUTF8 , bool rHasInputList )
+ : sHelpFile( rHelpFile ),
+ bUTF8 ( rUTF8 ),
+ bHasInputList( rHasInputList )
+ {};
+
+/*****************************************************************************/
+bool HelpParser::CreateSDF(
+/*****************************************************************************/
+ const ByteString &rSDFFile_in, const ByteString &rPrj_in,const ByteString &rRoot_in,
+ const ByteString &sHelpFile, XMLFile *pXmlFile, const ByteString &rGsi1){
+ // GSI File constants
+ static const String GSI_SEQUENCE1( String::CreateFromAscii("\t0\t") );
+ static const String GSI_SEQUENCE2( String::CreateFromAscii("\t\t\t0\t") );
+ static const String GSI_TAB ( String::CreateFromAscii("\t") );
+ static const String GSI_SEQUENCE4( String::CreateFromAscii("\t\t\t\t") );
+ static const String ret ( String::CreateFromAscii("\n") );
+ static const String ret_char ( String::CreateFromAscii("") );
+ static const String tab ( String::CreateFromAscii("\t") );
+ static const String tab_char ( String::CreateFromAscii("") );
+
+ SimpleXMLParser aParser;
+ String sUsedTempFile;
+ String sXmlFile;
+
+ if( Export::fileHasUTF8ByteOrderMarker( sHelpFile ) ){
+ DirEntry aTempFile = Export::GetTempFile();
+ DirEntry aSourceFile( String( sHelpFile , RTL_TEXTENCODING_ASCII_US ) );
+ aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
+ String sTempFile = aTempFile.GetFull();
+ Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
+ sUsedTempFile = sTempFile;
+ sXmlFile = sTempFile;
+ }else{
+ sUsedTempFile = String::CreateFromAscii("");
+ sXmlFile = String( sHelpFile , RTL_TEXTENCODING_ASCII_US );
+ }
+
+// ByteString fullFilePath;
+ //DirEntry aFile( sXmlFile );
+ //makeAbsolutePath( sHelpFile , rRoot_in);
+ ByteString fullFilePath = rPrj_in;
+ fullFilePath.Append( "\\" );
+ fullFilePath.Append( makeAbsolutePath( sHelpFile , rRoot_in ) );
+ fullFilePath.SearchAndReplaceAll( "\\", "/" );
+
+ String strFullPath( fullFilePath.GetBuffer() , RTL_TEXTENCODING_ASCII_US );
+
+ //printf( "%s\n", fullFilePath.GetBuffer() );
+ std::auto_ptr <XMLFile> file ( aParser.Execute( strFullPath , sXmlFile, pXmlFile ) );
+
+ if(file.get() == NULL){
+ printf("%s\n",ByteString(aParser.GetError().sMessage,RTL_TEXTENCODING_ASCII_US).GetBuffer());
+ exit(-1);
+ //return false;
+ }
+ file->Extract();
+ if( !file->CheckExportStatus() ){
+ return true;
+ }
+ SvFileStream aSDFStream( String( rSDFFile_in, RTL_TEXTENCODING_ASCII_US ),
+ STREAM_STD_WRITE | STREAM_TRUNC );
+
+ if ( !aSDFStream.IsOpen()) {
+ fprintf(stdout,"Can't open file %s\n",rSDFFile_in.GetBuffer());
+ return false;
+ }
+
+ ByteString sActFileName = makeAbsolutePath( sHelpFile , rRoot_in );
+
+/* DirEntry aEntry( String( sHelpFile, RTL_TEXTENCODING_ASCII_US ));
+ aEntry.ToAbs();
+ String sFullEntry = aEntry.GetFull();
+ aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
+ aEntry += DirEntry( rRoot_in );
+ ByteString sPrjEntry( aEntry.GetFull(), gsl_getSystemTextEncoding());
+ ByteString sActFileName(
+ sFullEntry.Copy( sPrjEntry.Len() + 1 ), gsl_getSystemTextEncoding());
+
+ sActFileName.SearchAndReplaceAll( "/", "\\" );
+*/
+ XMLHashMap* aXMLStrHM = file->GetStrings();
+ LangHashMap* pElem;
+ XMLElement* pXMLElement = NULL;
+
+ //Dump(aXMLStrHM);
+
+ ByteString sTimeStamp( Export::GetTimeStamp() );
+ OUString sOUTimeStamp( sTimeStamp.GetBuffer() , sTimeStamp.Len() , RTL_TEXTENCODING_ASCII_US );
+
+ OUStringBuffer sBuffer;
+ const OUString sOUPrj( rPrj_in.GetBuffer() , rPrj_in.Len() , RTL_TEXTENCODING_ASCII_US );
+ const OUString sOUActFileName(sActFileName.GetBuffer() , sActFileName.Len() , RTL_TEXTENCODING_ASCII_US );
+ const OUString sOUGsi1( rGsi1.GetBuffer() , rGsi1.Len() , RTL_TEXTENCODING_ASCII_US );
+
+ Export::InitLanguages( false );
+ std::vector<ByteString> aLanguages = Export::GetLanguages();
+
+ std::vector<ByteString> order = file->getOrder();
+ std::vector<ByteString>::iterator pos;
+ XMLHashMap::iterator posm;
+
+ for( pos = order.begin(); pos != order.end() ; ++pos )
+ {
+ posm = aXMLStrHM->find( *pos );
+ pElem = posm->second;
+ ByteString sCur;
+
+ for( unsigned int n = 0; n < aLanguages.size(); n++ )
+ {
+ sCur = aLanguages[ n ];
+ if(pElem->find( sCur )==pElem->end())
+ {
+ FillInFallbacks( *pElem , sCur );
+ }
+ pXMLElement = (*pElem)[ sCur ];
+
+ if( pXMLElement != NULL )
+ {
+ OUString data = pXMLElement->ToOUString();
+ String sTmp = String(data.getStr());
+ sTmp.SearchAndReplaceAll(ret,ret_char); // Remove \n
+ sTmp.SearchAndReplaceAll(tab,tab_char); // Remove \t
+
+ data = OUString( sTmp );
+ sBuffer.append( sOUPrj );
+ sBuffer.append( GSI_TAB ); //"\t";
+ if ( rRoot_in.Len())
+ sBuffer.append( sOUActFileName );
+ sBuffer.append( GSI_SEQUENCE1 ); //"\t0\t";
+ sBuffer.append( sOUGsi1 ); //"help";
+ sBuffer.append( GSI_TAB ); //"\t";
+ ByteString sID = posm->first; // ID
+ sBuffer.append( OUString( sID.GetBuffer() , sID.Len() , RTL_TEXTENCODING_UTF8 ) );
+ sBuffer.append( GSI_TAB ); //"\t";
+ ByteString sOldRef = pXMLElement->GetOldref(); // oldref
+ sBuffer.append( OUString(sOldRef.GetBuffer() , sOldRef.Len() , RTL_TEXTENCODING_UTF8 ) );
+ sBuffer.append( GSI_SEQUENCE2 ); //"\t\t\t0\t";
+ sBuffer.append( OUString( sCur.GetBuffer() , sCur.Len() , RTL_TEXTENCODING_UTF8 ) );
+ sBuffer.append( GSI_TAB ); //"\t";
+ sBuffer.append( data );
+ sBuffer.append( GSI_SEQUENCE4 ); //"\t\t\t\t";
+ sBuffer.append( sOUTimeStamp );
+ ByteString sOut( sBuffer.makeStringAndClear().getStr() , RTL_TEXTENCODING_UTF8 );
+ //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( rPrj_in ) ) )
+ //{
+ if( data.getLength() > 0 ) aSDFStream.WriteLine( sOut );
+ //}
+ pXMLElement=NULL;
+ }else fprintf(stdout,"\nDBG: NullPointer in HelpParser::CreateSDF , Language %s\n",sCur.GetBuffer() );
+ }
+
+ }
+ //Dump(aXMLStrHM);
+ aSDFStream.Close();
+
+ if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) ){
+ DirEntry aTempFile( sUsedTempFile );
+ aTempFile.Kill();
+ }
+ return TRUE;
+}
+
+ByteString HelpParser::makeAbsolutePath( const ByteString& sHelpFile , const ByteString& rRoot_in )
+{
+ DirEntry aEntry( String( sHelpFile, RTL_TEXTENCODING_ASCII_US ));
+ aEntry.ToAbs();
+ String sFullEntry = aEntry.GetFull();
+ aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
+ aEntry += DirEntry( rRoot_in );
+ ByteString sPrjEntry( aEntry.GetFull(), gsl_getSystemTextEncoding());
+ ByteString sActFileName(
+ sFullEntry.Copy( sPrjEntry.Len() + 1 ), gsl_getSystemTextEncoding());
+
+ sActFileName.SearchAndReplaceAll( "/", "\\" );
+ return sActFileName;
+}
+bool HelpParser::Merge( const ByteString &rSDFFile, const ByteString &rDestinationFile ,
+ ByteString& sLanguage , MergeDataFile& aMergeDataFile )
+{
+
+ (void) rSDFFile;
+ bool hasNoError = true;
+
+ SimpleXMLParser aParser;
+
+ String sUsedTempFile;
+ String sXmlFile;
+
+ if( Export::fileHasUTF8ByteOrderMarker( sHelpFile ) ){
+ DirEntry aTempFile = Export::GetTempFile();
+ DirEntry aSourceFile( String( sHelpFile , RTL_TEXTENCODING_ASCII_US ) );
+ aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
+ String sTempFile = aTempFile.GetFull();
+ Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
+ sUsedTempFile = sTempFile;
+ sXmlFile = sTempFile;
+ }else{
+ sUsedTempFile = String::CreateFromAscii("");
+ sXmlFile = String( sHelpFile , RTL_TEXTENCODING_ASCII_US );
+ }
+
+ OUString sOUHelpFile( sXmlFile );
+ String fullFilePath;
+ DirEntry aFile( sXmlFile );
+
+ XMLFile* xmlfile = ( aParser.Execute( aFile.GetFull() , sOUHelpFile, new XMLFile( '0' ) ) );
+ printf("Dest file %s\n",rDestinationFile.GetBuffer());
+ hasNoError = MergeSingleFile( xmlfile , aMergeDataFile , sLanguage , rDestinationFile );
+ delete xmlfile;
+ if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) ){
+ DirEntry aTempFile( sUsedTempFile );
+ aTempFile.Kill();
+ }
+ return hasNoError;
+}
+
+bool ByteStringEqual( const ByteString& rKey1, const ByteString& rKey2 ) {
+ return rKey1.CompareTo( rKey2 )==COMPARE_EQUAL;
+};
+bool ByteStringLess( const ByteString& rKey1, const ByteString& rKey2 ) {
+ return rKey1.CompareTo( rKey2 )==COMPARE_LESS;
+}
+
+void HelpParser::parse_languages( std::vector<ByteString>& aLanguages , MergeDataFile& aMergeDataFile ){
+ std::vector<ByteString> aTmp;
+
+ const ByteString DE ("de");
+ const ByteString ENUS ("en-US");
+ static const ByteString ALL( "ALL" );
+
+ Export::InitLanguages( false );
+
+ if( Export::sLanguages.EqualsIgnoreCaseAscii( ALL ) )
+ {
+ aLanguages = aMergeDataFile.GetLanguages();
+ aLanguages.push_back( DE );
+ aLanguages.push_back( ENUS );
+
+ if( !Export::sForcedLanguages.Equals("") )
+ {
+ std::vector<ByteString> aFL = Export::GetForcedLanguages();
+ std::copy( aFL.begin() ,
+ aFL.end() ,
+ back_inserter( aLanguages )
+ );
+ std::sort( aLanguages.begin() , aLanguages.end() , ByteStringLess );
+ std::vector<ByteString>::iterator unique_iter = std::unique( aLanguages.begin() , aLanguages.end() , ByteStringEqual );
+ std::copy( aLanguages.begin() , unique_iter , back_inserter( aTmp ) );
+ aLanguages = aTmp;
+ }
+ }
+ else{
+ aLanguages = Export::GetLanguages();
+ }
+
+}
+
+bool HelpParser::Merge(
+ const ByteString &rSDFFile, const ByteString &rPathX , const ByteString &rPathY , bool bISO ,
+ const std::vector<ByteString>& aLanguages , MergeDataFile& aMergeDataFile , bool bCreateDir )
+{
+
+
+ (void) rSDFFile ;
+ bool hasNoError = true;
+ SimpleXMLParser aParser;
+ String sUsedTempFile;
+ String sXmlFile;
+
+ if( Export::fileHasUTF8ByteOrderMarker( sHelpFile ) )
+ {
+ DirEntry aTempFile = Export::GetTempFile();
+ DirEntry aSourceFile( String( sHelpFile , RTL_TEXTENCODING_ASCII_US ) );
+ aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
+ String sTempFile = aTempFile.GetFull();
+ Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
+ sUsedTempFile = sTempFile;
+ sXmlFile = sTempFile;
+ }
+ else
+ {
+ sUsedTempFile = String::CreateFromAscii("");
+ sXmlFile = String( sHelpFile , RTL_TEXTENCODING_ASCII_US );
+ }
+
+
+ OUString sOUHelpFile( sXmlFile );
+ String fullFilePath;
+ DirEntry aFile( sXmlFile );
+
+ XMLFile* xmlfile = ( aParser.Execute( aFile.GetFull() , sOUHelpFile, new XMLFile( '0' ) ) );
+ xmlfile->Extract();
+
+ if( xmlfile == NULL)
+ {
+ printf("%s\n",ByteString(aParser.GetError().sMessage,RTL_TEXTENCODING_UTF8).GetBuffer());
+ exit(-1);
+ //return false;
+ }
+
+
+ ByteString sCur;
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+
+ ByteString sFilepath;
+ if( bISO ) sFilepath = GetOutpath( rPathX , sCur , rPathY );
+ else sFilepath = rPathX;
+ if( bCreateDir ) MakeDir( sFilepath );
+
+ XMLFile* file = new XMLFile( *xmlfile );
+ sFilepath.Append( sHelpFile );
+ hasNoError = MergeSingleFile( file , aMergeDataFile , sCur , sFilepath );
+ delete file;
+
+ if( !hasNoError ) return false; // Stop on error
+ }
+
+ if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) )
+ {
+ DirEntry aTempFile( sUsedTempFile );
+ aTempFile.Kill();
+ }
+ delete xmlfile;
+ return hasNoError;
+}
+
+bool HelpParser::MergeSingleFile( XMLFile* file , MergeDataFile& aMergeDataFile , const ByteString& sLanguage ,
+ ByteString sPath )
+{
+ file->Extract();
+
+ XMLHashMap* aXMLStrHM = file->GetStrings();
+ LangHashMap* aLangHM;
+ static ResData pResData( "","","");
+ pResData.sResTyp = "help";
+
+ ByteString sTmp = Export::sLanguages;
+
+ sTmp.EraseLeadingAndTrailingChars();
+
+ for(XMLHashMap::iterator pos=aXMLStrHM->begin();pos!=aXMLStrHM->end();++pos) // Merge every l10n related string
+ {
+
+ aLangHM = pos->second;
+ //printf("*********************DUMPING HASHMAP***************************************");
+ //Dump( aXMLStrHM );
+ //printf("DBG: sHelpFile = %s\n",sHelpFile.GetBuffer() );
+
+ pResData.sGId = pos->first;
+ pResData.sFilename = sHelpFile;
+
+ ProcessHelp( aLangHM , sLanguage, &pResData , aMergeDataFile );
+ }
+
+
+ // Init temp and target file
+ ByteString sTempFile;
+ ByteString sTargetFile( sPath );
+ ByteString sTempFileCopy;
+
+ static const ByteString INPATH = Export::GetEnv( "INPATH" );
+ Export::getRandomName( sPath , sTempFile , INPATH );
+ Export::getRandomName( sPath , sTempFileCopy , INPATH );
+ // Write in the temp file
+ bool hasNoError = file->Write ( sTempFile );
+ if( !hasNoError )
+ {
+ cerr << "ERROR: file->Write failed\n";
+ return false;
+ }
+
+ DirEntry aTmp( sTempFile );
+ DirEntry aTmp2( sTempFileCopy );
+ DirEntry aTar( sTargetFile );
+
+ if( !Export::CopyFile( sTempFile , sTempFileCopy ) )
+ {
+#if defined(UNX) || defined(OS2)
+ sleep( 3 );
+#else
+ Sleep( 3 );
+#endif
+ if( !Export::CopyFile( sTempFile , sTempFileCopy ) )
+ {
+ cerr << "ERROR: Can not copy file from " << sTempFile.GetBuffer() << " to " << sTempFileCopy.GetBuffer() << "\n";
+ return false;
+ }
+ }
+ //remove( sTargetFile.GetBuffer() );
+
+ FileStat aFSTest( aTar );
+ if( aFSTest.GetSize() < 1 )
+ {
+ remove( sTargetFile.GetBuffer() );
+ }
+ int rc;
+#if defined(UNX) || defined(OS2)
+ rc = rename( sTempFile.GetBuffer() , sTargetFile.GetBuffer() );
+#else
+ rc = MoveFileEx( sTempFile.GetBuffer() , sTargetFile.GetBuffer(), MOVEFILE_REPLACE_EXISTING );
+#endif
+ FileStat aFS( aTar );
+
+ //cout << "mv " << sTempFile.GetBuffer() << " " << sTargetFile.GetBuffer() << "\n";
+ //cout << "rc -> " << rc << " filesize -> " << aFS.GetSize() << "\n";
+// Windows rename returns -1 if the file already exits
+//#ifdef UNX
+ if( rc < 0 || aFS.GetSize() < 1 )
+//#else
+// if( aFS.GetSize() < 1 )
+//#endif
+ {
+#if defined(UNX) || defined(OS2)
+ sleep( 3 );
+#else
+ Sleep( 3 );
+#endif
+ aFSTest.Update( aTar );
+ if( aFSTest.GetSize() < 1 )
+ {
+ remove( sTargetFile.GetBuffer() );
+ }
+#if defined(UNX) || defined(OS2)
+ rc = rename( sTempFileCopy.GetBuffer() , sTargetFile.GetBuffer() );
+#else
+ rc = MoveFileEx( sTempFileCopy.GetBuffer() , sTargetFile.GetBuffer() , MOVEFILE_REPLACE_EXISTING );
+#endif
+ aFS.Update( aTar );
+
+ //cout << "mv2 " << sTempFileCopy.GetBuffer() << " " << sTargetFile.GetBuffer() << "\n";
+ //cout << "rc -> " << rc << " filesize -> " << aFS.GetSize() << "\n";
+
+// Windows rename returns -1 if the file already exits
+//#ifdef WNT
+// if( aFS.GetSize() < 1 )
+//#else
+ if( rc < 0 || aFS.GetSize() < 1 )
+//#endif
+ {
+ cerr << "ERROR: helpex Can't rename file " << sTempFileCopy.GetBuffer() << " to " << sTargetFile.GetBuffer() << " rename rc=" << rc << " filesize=" << aFS.GetSize() << "\n";
+ aTmp.Kill();
+ aTmp2.Kill();
+ if( aFS.GetSize() < 1 )
+ aTar.Kill();
+ return false;
+ }
+ }
+ aTmp.Kill();
+ aTmp2.Kill();
+
+ return true;
+}
+
+ByteString HelpParser::GetOutpath( const ByteString& rPathX , const ByteString& sCur , const ByteString& rPathY ){
+ ByteString testpath = rPathX;
+ static const ByteString sDelimiter( DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
+ testpath.EraseTrailingChars( '/' );
+ testpath.EraseTrailingChars( '\\' );
+ testpath += sDelimiter;
+ testpath += sCur;
+ testpath += sDelimiter;
+ ByteString sRelativePath( rPathY );
+ sRelativePath.EraseLeadingChars( '/' );
+ sRelativePath.EraseLeadingChars( '\\' );
+ testpath += sRelativePath;
+ testpath += sDelimiter;
+ return testpath;
+}
+void HelpParser::MakeDir( const ByteString& sPath ){
+ ByteString sTPath( sPath );
+ ByteString sDelimiter( DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
+ sTPath.SearchAndReplaceAll( sDelimiter , '/' );
+ USHORT cnt = sTPath.GetTokenCount( '/' );
+ ByteString sCreateDir;
+ for( USHORT i = 0 ; i < cnt ; i++ )
+ {
+ sCreateDir += sTPath.GetToken( i , '/' );
+ sCreateDir += sDelimiter;
+#ifdef WNT
+ _mkdir( sCreateDir.GetBuffer() );
+#else
+ mkdir( sCreateDir.GetBuffer() , S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
+#endif
+ }
+}
+
+
+/* ProcessHelp Methode: search for en-US entry and replace it with the current language*/
+void HelpParser::ProcessHelp( LangHashMap* aLangHM , const ByteString& sCur , ResData *pResData , MergeDataFile& aMergeDataFile ){
+
+ XMLElement* pXMLElement = NULL;
+ PFormEntrys *pEntrys = NULL;
+ XMLData *data = NULL;
+ XMLParentNode *parent = NULL;
+
+ String sNewdata;
+ ByteString sLId;
+ ByteString sGId;
+
+ pEntrys = NULL;
+
+#ifdef MERGE_SOURCE_LANGUAGES
+ if( true ){ // Merge en-US!
+#else
+ if( !sCur.EqualsIgnoreCaseAscii("en-US") ){
+#endif
+ pXMLElement = (*aLangHM)[ "en-US" ];
+ if( pXMLElement == NULL )
+ {
+ printf("Error: Can't find en-US entry\n");
+ }
+ if( pXMLElement != NULL )
+ {
+ parent = pXMLElement->GetParent();
+ sLId = pXMLElement->GetOldref();
+ pResData->sId = sLId;
+
+ pEntrys = aMergeDataFile.GetPFormEntrys( pResData );
+ if( pEntrys != NULL)
+ {
+ ByteString sNewText;
+ pEntrys->GetText( sNewText, STRING_TYP_TEXT, sCur , true );
+ sNewdata = String( sNewText , RTL_TEXTENCODING_UTF8 );
+ if ( sNewdata.Len())
+ {
+ if( pXMLElement != NULL )
+ {
+ data = new XMLData( sNewdata , NULL , true ); // Add new one
+ pXMLElement->RemoveAndDeleteAllChilds();
+ pXMLElement->AddChild( data );
+ aLangHM->erase( sCur );
+ }
+ }
+ }else if( pResData == NULL ){fprintf(stdout,"Can't find GID=%s LID=%s TYP=%s\n",pResData->sGId.GetBuffer(),pResData->sId.GetBuffer(),pResData->sResTyp.GetBuffer());}
+ pXMLElement->ChangeLanguageTag( String( sCur , RTL_TEXTENCODING_ASCII_US) );
+ }
+
+ }
+}
+/* Process() Method merges */
+void HelpParser::Process( LangHashMap* aLangHM , const ByteString& sCur , ResData *pResData , MergeDataFile& aMergeDataFile ){
+
+ XMLElement* pXMLElement = NULL;
+ PFormEntrys *pEntrys = NULL;
+ XMLData *data = NULL;
+ XMLParentNode *parent = NULL;
+ XMLDefault *xmldefault = NULL;
+
+ short curLang = 0;
+ String sNewdata;
+ bool isFallback = false;
+ ByteString sLId;
+ ByteString sGId;
+
+ pEntrys = NULL;
+
+#ifdef MERGE_SOURCE_LANGUAGES
+ if( true ){ // Merge en-US!
+#else
+ if( !sCur.EqualsIgnoreCaseAscii("en-US") ){
+#endif
+ pXMLElement = (*aLangHM)[ sCur ];
+ if( pXMLElement == NULL )
+ {
+ FillInFallbacks( *aLangHM , sCur );
+ pXMLElement = ( *aLangHM )[ sCur ];
+ isFallback = true;
+ }
+ if( pXMLElement != NULL )
+ {
+ parent = pXMLElement->GetParent();
+ sLId = pXMLElement->GetOldref();
+ pResData->sId = sLId;
+
+ pEntrys = aMergeDataFile.GetPFormEntrys( pResData );
+ if( pEntrys != NULL)
+ {
+ ByteString sNewText;
+ pEntrys->GetText( sNewText, STRING_TYP_TEXT, sCur , true );
+ sNewdata = String( sNewText , RTL_TEXTENCODING_UTF8 );
+ if ( sNewdata.Len())
+ {
+ printf("Entries found\n");
+ if( pXMLElement != NULL )
+ {
+ data = new XMLData( sNewdata , NULL , true ); // Add new one
+ if( pXMLElement->ToOUString().compareTo( OUString(data->GetData()) ) != 0 )
+ {
+ pXMLElement->RemoveAndDeleteAllChilds();
+ pXMLElement->AddChild( data );
+ }
+ if( isFallback )
+ {
+ xmldefault = new XMLDefault( String::CreateFromAscii("\n") , NULL );
+ int pos = parent->GetPosition( pXMLElement->GetId() );
+ if( pos != -1 ){
+ parent->AddChild(xmldefault , pos+1 );
+ parent->AddChild(pXMLElement , pos+2 );
+ }
+ else fprintf(stdout,"ERROR: Can't find reference Element of id %s language %d\n",pXMLElement->GetId().GetBuffer(),curLang);
+ }
+
+ aLangHM->erase( sCur );
+ }
+ }
+ delete pResData;
+ }else if( pResData == NULL ){fprintf(stdout,"Can't find GID=%s LID=%s TYP=%s\n",pResData->sGId.GetBuffer(),pResData->sId.GetBuffer(),pResData->sResTyp.GetBuffer());}
+ }
+
+ }
+}
+
diff --git a/l10ntools/source/inireader.cxx b/l10ntools/source/inireader.cxx
new file mode 100644
index 000000000000..63f902a5a1da
--- /dev/null
+++ b/l10ntools/source/inireader.cxx
@@ -0,0 +1,132 @@
+#include <unicode/regex.h>
+#include <unicode/unistr.h>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include "inireader.hxx"
+
+using namespace std;
+namespace transex3
+{
+
+bool INIreader::read( INImap& myMap , string& filename )
+{
+ ifstream aFStream( filename.c_str() );
+ if( aFStream && aFStream.is_open())
+ {
+ string line;
+ string section;
+ string param_key;
+ string param_value;
+ stringmap* myvalues = 0;
+
+ while( std::getline( aFStream , line ) )
+ {
+ trim( line );
+ if( line.empty() ){
+ }
+ else if( is_section( line , section ) )
+ {
+ //cerr << "[" << section << "]\n";
+ myvalues = new stringmap();
+ myMap[ section ] = myvalues ;
+ }
+ else if ( is_parameter( line , param_key , param_value ) )
+ {
+ //cerr << "" << param_key << " = " << param_value << "\n";
+ if( myvalues )
+ {
+ (*myvalues)[ param_key ] = param_value ;
+ }
+ else
+ {
+ cerr << "ERROR: The INI file " << filename << " appears to be broken ... parameters without a section?!?\n";
+ if( aFStream.is_open() ) aFStream.close();
+ return false;
+ }
+ }
+ }
+
+ if( aFStream.is_open() )
+ aFStream.close();
+
+ return true;
+ }
+ else
+ {
+ cerr << "ERROR: Can't open file '" << filename << "'\n";
+ }
+ return false;
+}
+
+bool INIreader::is_section( string& line , string& section_str )
+{
+ // Error in regex ?
+ check_status( section_status );
+ UnicodeString target( line.c_str() , line.length() );
+
+ section_match->reset( target );
+ check_status( section_status );
+
+ if( section_match->find() )
+ {
+ check_status( section_status );
+ UnicodeString result( section_match->group( 1 , section_status) );
+ check_status( section_status );
+ toStlString( result , section_str );
+
+ return true;
+ }
+ return false;
+}
+
+bool INIreader::is_parameter( string& line , string& parameter_key , string& parameter_value )
+{
+ // Error in regex ?
+ check_status( parameter_status );
+ UnicodeString target( line.c_str() , line.length() );
+
+ parameter_match->reset( target );
+ check_status( parameter_status );
+
+ if( parameter_match->find() )
+ {
+ check_status( parameter_status );
+
+ UnicodeString result1( parameter_match->group( 1 , parameter_status) );
+ check_status( parameter_status );
+ toStlString( result1 , parameter_key );
+ UnicodeString result2( parameter_match->group( 2 , parameter_status) );
+ check_status( parameter_status );
+ toStlString( result2 , parameter_value );
+
+ return true;
+ }
+ return false;
+}
+
+void INIreader::check_status( UErrorCode status )
+{
+ if( U_FAILURE( status) )
+ {
+ cerr << "Error in or while using regex: " << u_errorName( status ) << "\n";
+ exit(-1);
+ }
+}
+
+void INIreader::toStlString( const UnicodeString& str , string& stl_str)
+{
+ // convert to string
+ char* buffer = new char[ str.length()*3 ];
+ str.extract( 0 , str.length() , buffer );
+ stl_str = string( buffer );
+ delete [] buffer;
+}
+
+void INIreader::trim( string& str )
+{
+ string str1 = str.substr( 0 , str.find_last_not_of(' ') + 1 );
+ str = str1.empty() ? str1 : str1.substr( str1.find_first_not_of(' ') );
+}
+
+}
diff --git a/l10ntools/source/lngex.cxx b/l10ntools/source/lngex.cxx
new file mode 100644
index 000000000000..67ee34cbdaab
--- /dev/null
+++ b/l10ntools/source/lngex.cxx
@@ -0,0 +1,226 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: lngex.cxx,v $
+ * $Revision: 1.18 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <stdio.h>
+
+// local includes
+#include "lngmerge.hxx"
+
+// defines to parse command line
+#define STATE_NON 0x0001
+#define STATE_INPUT 0x0002
+#define STATE_OUTPUT 0x0003
+#define STATE_PRJ 0x0004
+#define STATE_ROOT 0x0005
+#define STATE_MERGESRC 0x0006
+#define STATE_ERRORLOG 0x0007
+#define STATE_BREAKHELP 0x0008
+#define STATE_UNMERGE 0x0009
+#define STATE_UTF8 0x000A
+#define STATE_ULF 0x000B
+#define STATE_LANGUAGES 0x000C
+
+// set of global variables
+ByteString sInputFile;
+BOOL bEnableExport;
+BOOL bMergeMode;
+BOOL bErrorLog;
+BOOL bUTF8;
+BOOL bULF; // ULF = Unicode Language File
+bool bQuiet;
+ByteString sPrj;
+ByteString sPrjRoot;
+ByteString sOutputFile;
+ByteString sMergeSrc;
+
+/*****************************************************************************/
+BOOL ParseCommandLine( int argc, char* argv[])
+/*****************************************************************************/
+{
+ bEnableExport = FALSE;
+ bMergeMode = FALSE;
+ bErrorLog = TRUE;
+ bUTF8 = TRUE;
+ bULF = FALSE;
+ bQuiet = false;
+ sPrj = "";
+ sPrjRoot = "";
+ Export::sLanguages = "";
+
+ USHORT nState = STATE_NON;
+ BOOL bInput = FALSE;
+
+ // parse command line
+ for( int i = 1; i < argc; i++ ) {
+ ByteString sSwitch( argv[ i ] );
+ sSwitch.ToUpperAscii();
+ if ( sSwitch == "-I" ) {
+ nState = STATE_INPUT; // next tokens specifies source files
+ }
+ else if ( sSwitch == "-O" ) {
+ nState = STATE_OUTPUT; // next token specifies the dest file
+ }
+ else if ( sSwitch == "-P" ) {
+ nState = STATE_PRJ; // next token specifies the cur. project
+ }
+ else if ( sSwitch == "-R" ) {
+ nState = STATE_ROOT; // next token specifies path to project root
+ }
+ else if ( sSwitch == "-QQ" ) {
+ bQuiet = true;
+ }
+ else if ( sSwitch == "-M" ) {
+ nState = STATE_MERGESRC; // next token specifies the merge database
+ }
+ else if ( sSwitch == "-E" ) {
+ nState = STATE_ERRORLOG;
+ bErrorLog = FALSE;
+ }
+ else if ( sSwitch == "-UTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = TRUE;
+ }
+/* else if ( sSwitch == "-NOUTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = FALSE;
+ }*/
+/* else if ( sSwitch == "-ULF" ) {
+ nState = STATE_ULF;
+ bULF = TRUE;
+ }*/
+ else if ( sSwitch == "-L" ) {
+ nState = STATE_LANGUAGES;
+ }
+ else {
+ switch ( nState ) {
+ case STATE_NON: {
+ return FALSE; // no valid command line
+ }
+ //break;
+ case STATE_INPUT: {
+ sInputFile = argv[ i ];
+ bInput = TRUE; // source file found
+ }
+ break;
+ case STATE_OUTPUT: {
+ sOutputFile = argv[ i ]; // the dest. file
+ }
+ break;
+ case STATE_PRJ: {
+ sPrj = argv[ i ];
+// sPrj.ToLowerAscii(); // the project
+ }
+ break;
+ case STATE_ROOT: {
+ sPrjRoot = argv[ i ]; // path to project root
+ }
+ break;
+ case STATE_MERGESRC: {
+ sMergeSrc = argv[ i ];
+ bMergeMode = TRUE; // activate merge mode, cause merge database found
+ }
+ break;
+ case STATE_LANGUAGES: {
+ Export::sLanguages = argv[ i ];
+ }
+ break;
+ }
+ }
+ }
+
+ if ( bInput ) {
+ // command line is valid
+ bULF = TRUE;
+ bEnableExport = TRUE;
+ return TRUE;
+ }
+
+ // command line is not valid
+ return FALSE;
+}
+
+
+/*****************************************************************************/
+void Help()
+/*****************************************************************************/
+{
+ //fprintf( stdout, "Syntax:ULFEX[-p Prj][-r PrjRoot]-i FileIn -o FileOut[-m DataBase][-e][-b][-u][-NOUTF8][-ULF][-L l1,l2,...]\n" );
+ fprintf( stdout, "Syntax:ULFEX[-p Prj][-r PrjRoot]-i FileIn -o FileOut[-m DataBase][-L l1,l2,...]\n" );
+ fprintf( stdout, " Prj: Project\n" );
+ fprintf( stdout, " PrjRoot: Path to project root (..\\.. etc.)\n" );
+ fprintf( stdout, " FileIn: Source file (*.lng)\n" );
+ fprintf( stdout, " FileOut: Destination file (*.*)\n" );
+ fprintf( stdout, " DataBase: Mergedata (*.sdf)\n" );
+ fprintf( stdout, " -QQ: quite output\n" );
+ //fprintf( stdout, " -NOUTF8: disable UTF8 as language independent encoding\n" );
+ //fprintf( stdout, " -ULF: enables Unicode Language File format, leads to UTF8 encoded version of lng files" );
+ fprintf( stdout, " -L: Restrict the handled languages. l1,l2,... are elements of (de,en-US...)\n" );
+ fprintf( stdout, " A fallback language can be defined like this: l1=f1.\n" );
+ fprintf( stdout, " f1, f2,... are also elements of (de,en-US...)\n" );
+ fprintf( stdout, " Example: -L de,es=en-US\n" );
+ fprintf( stdout, " Restriction to de and es, en-US will be fallback for es\n" );
+}
+
+/*****************************************************************************/
+#if defined(UNX) || defined(OS2)
+int main( int argc, char *argv[] )
+#else
+int _cdecl main( int argc, char *argv[] )
+#endif
+/*****************************************************************************/
+{
+ if ( !ParseCommandLine( argc, argv )) {
+ Help();
+ return 1;
+ }
+ if( !bQuiet ){
+ fprintf( stdout, "\nUlfEx 1 Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.\n" );
+ fprintf( stdout, "====================================================================\n" );
+ fprintf( stdout, "\nProcessing File %s ...\n", sInputFile.GetBuffer());
+ }else
+ {
+ fprintf(stdout, ".");
+ fflush( stdout );
+ }
+
+ if ( sOutputFile.Len()) {
+ LngParser aParser( sInputFile, bUTF8, bULF , bQuiet );
+ if ( bMergeMode )
+ aParser.Merge( sMergeSrc, sOutputFile , sPrj );
+ else
+ aParser.CreateSDF( sOutputFile, sPrj, sPrjRoot );
+ }
+
+ if( !bQuiet ) fprintf( stdout, "\n=================================================\n\n" );
+
+ return 0;
+}
diff --git a/l10ntools/source/lngmerge.cxx b/l10ntools/source/lngmerge.cxx
new file mode 100644
index 000000000000..fcad498128c2
--- /dev/null
+++ b/l10ntools/source/lngmerge.cxx
@@ -0,0 +1,360 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: lngmerge.cxx,v $
+ * $Revision: 1.29 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <tools/fsys.hxx>
+
+// local includes
+#include "lngmerge.hxx"
+#include "utf8conv.hxx"
+#include <iostream>
+using namespace std;
+//
+// class LngParser
+//
+/*****************************************************************************/
+LngParser::LngParser( const ByteString &rLngFile, BOOL bUTF8, BOOL bULFFormat , bool bQuiet_in )
+/*****************************************************************************/
+ :
+ nError( LNG_OK ),
+ pLines( NULL ),
+ sSource( rLngFile ),
+ bDBIsUTF8( bUTF8 ),
+ bULF( bULFFormat ),
+ bQuiet( bQuiet_in )
+{
+ pLines = new LngLineList( 100, 100 );
+ DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US ));
+ if ( aEntry.Exists()) {
+ SvFileStream aStream( String( sSource, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ );
+ if ( aStream.IsOpen()) {
+ ByteString sLine;
+ bool bFirstLine = true;
+ while ( !aStream.IsEof()) {
+ aStream.ReadLine( sLine );
+
+ if( bFirstLine ){ // Always remove UTF8 BOM from the first line
+ Export::RemoveUTF8ByteOrderMarker( sLine );
+ bFirstLine = false;
+ }
+
+ pLines->Insert( new ByteString( sLine ), LIST_APPEND );
+ }
+ }
+ else
+ nError = LNG_COULD_NOT_OPEN;
+ }
+ else
+ nError = LNG_FILE_NOTFOUND;
+}
+
+/*****************************************************************************/
+LngParser::~LngParser()
+/*****************************************************************************/
+{
+ for ( ULONG i = 0; i < pLines->Count(); i++ )
+ delete pLines->GetObject( i );
+ delete pLines;
+}
+
+/*****************************************************************************/
+void LngParser::FillInFallbacks( ByteStringHashMap Text )
+/*****************************************************************************/
+{
+ ByteString sCur;
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+
+ if( Export::isAllowed( sCur ) ){
+ ByteString sFallbackLang = Export::GetFallbackLanguage( sCur );
+ if( sFallbackLang.Len() ){
+ Text[ sCur ] = Text[ sFallbackLang ];
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+BOOL LngParser::CreateSDF(
+ const ByteString &rSDFFile, const ByteString &rPrj,
+ const ByteString &rRoot )
+/*****************************************************************************/
+{
+
+ Export::InitLanguages( false );
+ aLanguages = Export::GetLanguages();
+ SvFileStream aSDFStream( String( rSDFFile, RTL_TEXTENCODING_ASCII_US ),
+ STREAM_STD_WRITE | STREAM_TRUNC );
+ if ( !aSDFStream.IsOpen()) {
+ nError = SDF_COULD_NOT_OPEN;
+ }
+ aSDFStream.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
+ nError = SDF_OK;
+ DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US ));
+ aEntry.ToAbs();
+ String sFullEntry = aEntry.GetFull();
+ aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
+ aEntry += DirEntry( rRoot );
+ ByteString sPrjEntry( aEntry.GetFull(), gsl_getSystemTextEncoding());
+ ByteString sActFileName(
+ sFullEntry.Copy( sPrjEntry.Len() + 1 ), gsl_getSystemTextEncoding());
+ sActFileName.SearchAndReplaceAll( "/", "\\" );
+
+ ULONG nPos = 0;
+ BOOL bStart = true;
+ ByteString sGroup;
+ ByteStringHashMap Text;
+ ByteString sID;
+ ByteString sLine;
+
+ while( nPos < pLines->Count() ){
+ sLine = *pLines->GetObject( nPos++ );
+ while( nPos < pLines->Count() && !isNextGroup( sGroup , sLine ) ){
+ ReadLine( sLine , Text );
+ sID = sGroup;
+ sLine = *pLines->GetObject( nPos++ );
+ };
+ if( bStart ){
+ bStart = false;
+ sID = sGroup;
+ }
+ else {
+
+ WriteSDF( aSDFStream , Text , rPrj , rRoot , sActFileName , sID );
+ }
+ }
+ aSDFStream.Close();
+ return true;
+}
+
+ void LngParser::WriteSDF( SvFileStream &aSDFStream , ByteStringHashMap &rText_inout ,
+ const ByteString &rPrj , const ByteString &rRoot ,
+ const ByteString &sActFileName , const ByteString &sID )
+ {
+
+ BOOL bExport = true;
+ if ( bExport ) {
+ ByteString sTimeStamp( Export::GetTimeStamp());
+ ByteString sCur;
+ FillInFallbacks( rText_inout );
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ ByteString sAct = rText_inout[ sCur ];
+ if ( !sAct.Len() && sCur.Len() )
+ sAct = rText_inout[ ByteString("en-US") ];
+
+ ByteString sOutput( rPrj ); sOutput += "\t";
+ if ( rRoot.Len())
+ sOutput += sActFileName;
+ sOutput += "\t0\t";
+ sOutput += "LngText\t";
+ sOutput += sID; sOutput += "\t\t\t\t0\t";
+ sOutput += sCur; sOutput += "\t";
+ sOutput += sAct; sOutput += "\t\t\t\t";
+ sOutput += sTimeStamp;
+ //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( rPrj ) ) )
+ aSDFStream.WriteLine( sOutput );
+ }
+ }
+ }
+ bool LngParser::isNextGroup( ByteString &sGroup_out , ByteString &sLine_in ){
+ sLine_in.EraseLeadingChars( ' ' );
+ sLine_in.EraseTrailingChars( ' ' );
+ if (( sLine_in.GetChar( 0 ) == '[' ) &&
+ ( sLine_in.GetChar( sLine_in.Len() - 1 ) == ']' )){
+ sGroup_out = sLine_in.GetToken( 1, '[' ).GetToken( 0, ']' );
+ sGroup_out.EraseLeadingChars( ' ' );
+ sGroup_out.EraseTrailingChars( ' ' );
+ return true;
+ }
+ return false;
+ }
+ void LngParser::ReadLine( const ByteString &sLine_in , ByteStringHashMap &rText_inout){
+ //printf("sLine -> '%s'\n",sLine_in.GetBuffer());
+ ByteString sLang = sLine_in.GetToken( 0, '=' );
+ sLang.EraseLeadingChars( ' ' );
+ sLang.EraseTrailingChars( ' ' );
+ ByteString sText = sLine_in.GetToken( 1, '\"' ).GetToken( 0, '\"' );
+ if( sLang.Len() )
+ rText_inout[ sLang ] = sText;
+ }
+
+/*****************************************************************************/
+BOOL LngParser::Merge(
+ const ByteString &rSDFFile, const ByteString &rDestinationFile , const ByteString& rPrj )
+/*****************************************************************************/
+{
+ (void) rPrj;
+ Export::InitLanguages( true );
+ SvFileStream aDestination(
+ String( rDestinationFile, RTL_TEXTENCODING_ASCII_US ),
+ STREAM_STD_WRITE | STREAM_TRUNC );
+ if ( !aDestination.IsOpen()) {
+ nError = LNG_COULD_NOT_OPEN;
+ }
+ nError = LNG_OK;
+// MergeDataFile( const ByteString &rFileName, const ByteString& rFile , BOOL bErrLog, CharSet aCharSet, BOOL bUTF8 );
+
+ MergeDataFile aMergeDataFile( rSDFFile, sSource , FALSE, RTL_TEXTENCODING_MS_1252);//, bDBIsUTF8 );
+ ByteString sTmp( Export::sLanguages );
+ if( sTmp.ToUpperAscii().Equals("ALL") )
+ Export::SetLanguages( aMergeDataFile.GetLanguages() );
+ aLanguages = Export::GetLanguages();
+
+ ULONG nPos = 0;
+ BOOL bGroup = FALSE;
+ ByteString sGroup;
+
+ // seek to next group
+ while ( nPos < pLines->Count() && !bGroup ) {
+ ByteString sLine( *pLines->GetObject( nPos ));
+ sLine.EraseLeadingChars( ' ' );
+ sLine.EraseTrailingChars( ' ' );
+ if (( sLine.GetChar( 0 ) == '[' ) &&
+ ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
+ {
+ sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
+ sGroup.EraseLeadingChars( ' ' );
+ sGroup.EraseTrailingChars( ' ' );
+ bGroup = TRUE;
+ }
+ nPos ++;
+ }
+
+ while ( nPos < pLines->Count()) {
+ ByteStringHashMap Text;
+ ByteString sID( sGroup );
+ ULONG nLastLangPos = 0;
+
+ ResData *pResData = new ResData( "", sID , sSource );
+ pResData->sResTyp = "LngText";
+ PFormEntrys *pEntrys = aMergeDataFile.GetPFormEntrys( pResData );
+ // read languages
+ bGroup = FALSE;
+
+ ByteString sLanguagesDone;
+
+ while ( nPos < pLines->Count() && !bGroup ) {
+ ByteString sLine( *pLines->GetObject( nPos ));
+ sLine.EraseLeadingChars( ' ' );
+ sLine.EraseTrailingChars( ' ' );
+ if (( sLine.GetChar( 0 ) == '[' ) &&
+ ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
+ {
+ sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
+ sGroup.EraseLeadingChars( ' ' );
+ sGroup.EraseTrailingChars( ' ' );
+ bGroup = TRUE;
+ nPos ++;
+ sLanguagesDone = "";
+ }
+ else if ( sLine.GetTokenCount( '=' ) > 1 ) {
+ ByteString sLang = sLine.GetToken( 0, '=' );
+ sLang.EraseLeadingChars( ' ' );
+ sLang.EraseTrailingChars( ' ' );
+
+ ByteString sSearch( ";" );
+ sSearch += sLang;
+ sSearch += ";";
+
+ if (( sLanguagesDone.Search( sSearch ) != STRING_NOTFOUND )) {
+ pLines->Remove( nPos );
+ }
+ if( bULF && pEntrys )
+ {
+ // this is a valid text line
+ ByteString sText = sLine.GetToken( 1, '\"' ).GetToken( 0, '\"' );
+ if( sLang.Len() ){
+ ByteString sNewText;
+ pEntrys->GetText( sNewText, STRING_TYP_TEXT, sLang, TRUE );
+
+ if ( sNewText.Len()) {
+ ByteString *pLine = pLines->GetObject( nPos );
+
+ ByteString sText1( sLang );
+ sText1 += " = \"";
+ sText1 += sNewText;
+ sText1 += "\"";
+ *pLine = sText1;
+ //}
+ Text[ sLang ] = sNewText;
+ }
+ }
+ nLastLangPos = nPos;
+ nPos ++;
+ sLanguagesDone += sSearch;
+ }
+ else {
+ nLastLangPos = nPos;
+ nPos ++;
+ sLanguagesDone += sSearch;
+ }
+ }
+ else
+ nPos++;
+ }
+ ByteString sCur;
+ if ( nLastLangPos ) {
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ if( //( !sCur.EqualsIgnoreCaseAscii("de") ||
+ //( sCur.EqualsIgnoreCaseAscii("de") && Export::isMergingGermanAllowed( rPrj ) ) )
+ !sCur.EqualsIgnoreCaseAscii("en-US") && !Text[ sCur ].Len() && pEntrys ){
+
+ ByteString sNewText;
+ pEntrys->GetText( sNewText, STRING_TYP_TEXT, sCur, TRUE );
+ if (( sNewText.Len()) &&
+ !(( sCur.Equals("x-comment") ) && ( sNewText == "-" )))
+ {
+ ByteString sLine;
+ sLine += sCur;
+ sLine += " = \"";
+ sLine += sNewText;
+ sLine += "\"";
+
+ nLastLangPos++;
+ nPos++;
+
+ pLines->Insert( new ByteString( sLine ), nLastLangPos );
+ }
+ }
+ }
+ }
+
+ delete pResData;
+ }
+
+ for ( ULONG i = 0; i < pLines->Count(); i++ )
+ aDestination.WriteLine( *pLines->GetObject( i ));
+
+ aDestination.Close();
+ return TRUE;
+}
diff --git a/l10ntools/source/localize.cxx b/l10ntools/source/localize.cxx
new file mode 100644
index 000000000000..b617fdb4cf1e
--- /dev/null
+++ b/l10ntools/source/localize.cxx
@@ -0,0 +1,986 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: localize.cxx,v $
+ * $Revision: 1.50 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+
+#include "srciter.hxx"
+#include "export.hxx"
+#include "treeconfig.hxx"
+#include <string>
+#include <vector>
+#include <stdio.h>
+#include <iostream>
+#include "tools/errcode.hxx"
+#include "tools/fsys.hxx"
+
+#ifndef L10NTOOLS_FILE_HXX
+#define L10NTOOLS_FILE_HXX
+#include <l10ntools/file.hxx>
+#endif
+
+namespace transex3
+{
+
+//
+// SourceTreeLocalizer
+//
+
+const char *ExeTable[][5] = {
+ { "src", "transex3", " -UTF8 -e", "negative", "noiso" },
+ { "hrc", "transex3", " -UTF8 -e", "positive", "noiso" },
+ //{ "src", "transex3", "-UTF8 -e", "negative", "noiso" },
+ //{ "hrc", "transex3", "-UTF8 -e", "positive", "noiso" },
+
+ //{ "lng", "lngex", "-UTF8 -e", "negative", "noiso" },
+ { "ulf", "ulfex", " -e", "negative", "noiso" },
+ { "xrb", "xmlex", "-UTF8 -e", "negative", "iso" },
+ { "xxl", "xmlex", "-UTF8 -e", "negative", "iso" },
+ { "xgf", "xmlex", "-UTF8 -e -t:xgf", "negative", "iso" },
+ { "xcd", "cfgex", "-UTF8 -e", "negative", "iso" },
+ { "xcu", "cfgex", "-UTF8 -e", "negative", "iso" },
+ { "xcs", "cfgex", "-UTF8 -e -f", "negative", "iso" },
+ { "xrm", "xrmex", "-UTF8 -e", "negative", "iso" },
+ { "xhp", "helpex", " -e", "negative", "noiso" },
+ { "NULL", "NULL", "NULL", "NULL", "NULL" }
+};
+
+const char *NegativeList[] = {
+ "officecfg/data/org.openoffice.Office.Labels.xcd",
+ "officecfg/data/org/openoffice/Office/Labels.xcd",
+ "officecfg/data/org/openoffice/Office/SFX.xcd",
+ "officecfg/data/org/openoffice/Office/Accelerators.xcu",
+ "hidother.src",
+ "NULL"
+};
+
+const char *PositiveList[] = {
+ "svx/inc/globlmn_tmpl.hrc",
+ "sw/source/ui/inc/swmn_tmpl.hrc",
+ "sw/source/ui/inc/swacc_tmpl.hrc",
+ "sw/source/ui/inc/toolbox_tmpl.hrc",
+ "offmgr/inc/offmenu_tmpl.hrc",
+ "offmgr/source/offapp/intro/intro_tmpl.hrc",
+ "dbaccess/source/ui/inc/toolbox_tmpl.hrc",
+ "svx/source/intro/intro_tmpl.hrc",
+ "dbaccess/source/ui/dlg/AutoControls_tmpl.hrc",
+ "svx/source/unodialogs/textconversiondlgs/chinese_direction_tmpl.hrc",
+ "chart2/source/controller/dialogs/res_DataLabel_tmpl.hrc",
+ "chart2/source/controller/dialogs/res_LegendPosition_tmpl.hrc",
+ "chart2/source/controller/dialogs/res_Statistic_tmpl.hrc",
+ "chart2/source/controller/dialogs/res_Titlesx_tmpl.hrc",
+ "chart2/source/controller/dialogs/res_SecondaryAxisCheckBoxes_tmpl.hrc",
+ "chart2/source/controller/menu/MenuItems_tmpl.hrc",
+ "chart2/source/controller/dialogs/res_ErrorBar_tmpl.hrc",
+ "chart2/source/controller/dialogs/res_Trendline_tmpl.hrc",
+ "svx.link/inc/globlmn_tmpl.hrc",
+ "sw.link/source/ui/inc/swmn_tmpl.hrc",
+ "sw.link/source/ui/inc/swacc_tmpl.hrc",
+ "sw.link/source/ui/inc/toolbox_tmpl.hrc",
+ "offmgr.link/inc/offmenu_tmpl.hrc",
+ "offmgr.link/source/offapp/intro/intro_tmpl.hrc",
+ "dbaccess.link/source/ui/inc/toolbox_tmpl.hrc",
+ "svx.link/source/intro/intro_tmpl.hrc",
+ "dbaccess.link/source/ui/dlg/AutoControls_tmpl.hrc",
+ "svx.link/source/unodialogs/textconversiondlgs/chinese_direction_tmpl.hrc",
+ "chart2.link/source/controller/dialogs/res_DataLabel_tmpl.hrc",
+ "chart2.link/source/controller/dialogs/res_LegendPosition_tmpl.hrc",
+ "chart2.link/source/controller/dialogs/res_Statistic_tmpl.hrc",
+ "chart2.link/source/controller/dialogs/res_Titlesx_tmpl.hrc",
+ "chart2.link/source/controller/dialogs/res_SecondaryAxisCheckBoxes_tmpl.hrc",
+ "chart2.link/source/controller/menu/MenuItems_tmpl.hrc",
+ "chart2.link/source/controller/dialogs/res_ErrorBar_tmpl.hrc",
+ "chart2.link/source/controller/dialogs/res_Trendline_tmpl.hrc",
+ "NULL"
+};
+
+
+const char PRJ_DIR_NAME[] = "prj";
+const char DLIST_NAME[] = "d.lst";
+
+#define LOCALIZE_NONE 0x0000
+#define LOCALIZE_EXTRACT 0x0001
+#define LOCALIZE_MERGE 0x0002
+
+class SourceTreeLocalizer : public SourceTreeIterator
+{
+private:
+ SvFileStream aSDF;
+ USHORT nMode;
+
+ ByteString sLanguageRestriction;
+
+ ByteString sOutputFile;
+ bool bQuiet2;
+
+ int nFileCnt;
+
+ const ByteString GetProjectName( BOOL bAbs = FALSE );
+ const ByteString GetProjectRootRel();
+
+
+ BOOL CheckNegativeList( const ByteString &rFileName );
+ BOOL CheckPositiveList( const ByteString &rFileName );
+
+ void WorkOnFile(
+ const ByteString &rFileName,
+ const ByteString &rExecutable,
+ const ByteString &rParameter
+ );
+
+ void WorkOnFileType(
+ const ByteString &rDirectory,
+ const ByteString &rExtension,
+ const ByteString &rExecutable,
+ const ByteString &rParameter,
+ const ByteString &rCollectMode
+ );
+ void WorkOnDirectory( const ByteString &rDirectory );
+ BOOL ExecuteMerge();
+ BOOL MergeSingleFile(
+ const ByteString &rPrj,
+ const ByteString &rFile,
+ const ByteString &rSDFFile
+ );
+
+public:
+ SourceTreeLocalizer( const ByteString &rRoot, const ByteString &rVersion , bool bLocal , bool bQuiet2_in , bool skip_links );
+ ~SourceTreeLocalizer();
+
+ ByteString getSourceLanguages( ByteString sLanguageRestriction , ByteString sCommand );
+
+ void SetLanguageRestriction( const ByteString& rRestrictions )
+ { sLanguageRestriction = rRestrictions; }
+ int getFileCnt();
+ BOOL Extract( const ByteString &rDestinationFile );
+ BOOL Merge( const ByteString &rSourceFile , const ByteString &rOutput );
+ int GetFileCnt();
+ virtual void OnExecuteDirectory( const rtl::OUString &rDirectory );
+};
+
+/*****************************************************************************/
+SourceTreeLocalizer::SourceTreeLocalizer(
+ const ByteString &rRoot, const ByteString &rVersion, bool bLocal_in , bool bQuiet2_in , bool skip_links )
+/*****************************************************************************/
+ : SourceTreeIterator( rRoot, rVersion , bLocal_in ),
+ nMode( LOCALIZE_NONE ),
+ bQuiet2( bQuiet2_in ),
+ nFileCnt( 0 )
+{
+ bSkipLinks = skip_links ;
+}
+
+/*****************************************************************************/
+SourceTreeLocalizer::~SourceTreeLocalizer()
+/*****************************************************************************/
+{
+}
+
+/*****************************************************************************/
+const ByteString SourceTreeLocalizer::GetProjectName( BOOL bAbs )
+/*****************************************************************************/
+{
+ BOOL bFound = FALSE;
+ DirEntry aCur;
+ aCur.ToAbs();
+
+ for ( ; ! bFound && aCur.Level() > 1; aCur.CutName() )
+ {
+ DirEntry aTest = aCur + DirEntry(PRJ_DIR_NAME) + DirEntry(DLIST_NAME);
+ if ( aTest.Exists() )
+ {
+ if ( bAbs )
+ return ByteString( aCur.GetFull(), RTL_TEXTENCODING_ASCII_US );
+ else
+ return ByteString( aCur.GetName(), RTL_TEXTENCODING_ASCII_US );
+ }
+ }
+
+ return "";
+}
+/*****************************************************************************/
+int SourceTreeLocalizer::GetFileCnt(){
+/*****************************************************************************/
+ return nFileCnt;
+}
+
+/*****************************************************************************/
+const ByteString SourceTreeLocalizer::GetProjectRootRel()
+/*****************************************************************************/
+{
+ ByteString sProjectRoot( GetProjectName( TRUE ));
+ DirEntry aCur;
+ aCur.ToAbs();
+ ByteString sCur( aCur.GetFull(), RTL_TEXTENCODING_ASCII_US );
+
+ if( sCur.SearchAndReplace( sProjectRoot, "" ) == STRING_NOTFOUND )
+ return "";
+
+ ByteString sDelimiter(
+ DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
+
+ sCur.SearchAndReplaceAll( sDelimiter, "/" );
+ sCur.EraseLeadingChars( '/' );
+ ULONG nCount = sCur.GetTokenCount( '/' );
+
+ ByteString sProjectRootRel;
+ for ( ULONG i = 0; i < nCount; i++ ) {
+ if ( sProjectRootRel.Len())
+ sProjectRootRel += sDelimiter;
+ sProjectRootRel += "..";
+ }
+ if ( sProjectRootRel.Len())
+ return sProjectRootRel;
+
+ return ".";
+}
+
+bool skipProject( ByteString sPrj )
+{
+ static const ByteString READLICENSE( "readlicense" );
+ return sPrj.EqualsIgnoreCaseAscii( READLICENSE );
+}
+
+/*****************************************************************************/
+void SourceTreeLocalizer::WorkOnFile(
+ const ByteString &rFileName, const ByteString &rExecutable,
+ const ByteString &rParameter )
+/*****************************************************************************/
+{
+ String sFull( rFileName, RTL_TEXTENCODING_ASCII_US );
+ DirEntry aEntry( sFull );
+ ByteString sFileName( aEntry.GetName(), RTL_TEXTENCODING_ASCII_US );
+
+ // set current working directory
+ DirEntry aPath( aEntry.GetPath());
+ DirEntry aOldCWD;
+ aPath.SetCWD();
+
+ ByteString sPrj( GetProjectName());
+ if ( sPrj.Len() && !skipProject( sPrj ) )
+ {
+ ByteString sRoot( GetProjectRootRel());
+
+ DirEntry aTemp( Export::GetTempFile());
+ ByteString sTempFile( aTemp.GetFull(), RTL_TEXTENCODING_ASCII_US );
+
+ ByteString sDel;
+#if defined(WNT) || defined(OS2)
+ sDel=ByteString("\\");
+#else
+ sDel=ByteString("/");
+#endif
+ ByteString sPath1( Export::GetEnv("SOLARVER") );
+ ByteString sPath2( Export::GetEnv("INPATH") );
+ ByteString sPath3( "bin" );
+ ByteString sPath4( Export::GetEnv("UPDMINOREXT") );
+ ByteString sExecutable( sPath1 );
+ sExecutable += sDel ;
+ sExecutable += sPath2 ;
+ sExecutable += sDel;
+ sExecutable += sPath3 ;
+ sExecutable += sPath4 ;
+ sExecutable += sDel ;
+ sExecutable += rExecutable ;
+
+
+ ByteString sCommand( sExecutable );
+ sCommand += " ";
+ sCommand += rParameter;
+ sCommand += " -p ";
+ sCommand += sPrj;
+ sCommand += " -r ";
+ sCommand += sRoot;
+ sCommand += " -i ";
+ sCommand += sFileName;
+ sCommand += " -o ";
+ sCommand += sTempFile;
+ if ( sLanguageRestriction.Len()) {
+ sCommand += " -l ";
+ sCommand += getSourceLanguages( sLanguageRestriction , sCommand );
+ }
+
+ if( bQuiet2 ){
+ sCommand +=" -QQ ";
+ }
+ //printf("DBG: %s\n",sCommand.GetBuffer());
+ if (system(sCommand.GetBuffer()) == -1)
+ fprintf(stderr, "%s failed\n", sCommand.GetBuffer());
+ nFileCnt++;
+ printf(".");
+ fflush( stdout );
+
+ SvFileStream aSDFIn( aTemp.GetFull(), STREAM_READ );
+ ByteString sLine;
+ while ( aSDFIn.IsOpen() && !aSDFIn.IsEof()) {
+ aSDFIn.ReadLine( sLine );
+ if ( sLine.Len()) {
+ aSDF.WriteLine( sLine );
+ }
+ }
+ aSDFIn.Close();
+
+ aTemp.Kill();
+
+ }
+ // reset current working directory
+ aOldCWD.SetCWD();
+}
+
+ByteString SourceTreeLocalizer::getSourceLanguages( ByteString sLanguageRestriction_inout , ByteString sCommand )
+{
+ // Source languages in helpcontent2 and macromigration en-US only!
+ if( sCommand.Search("helpex") != STRING_NOTFOUND ) {
+ sLanguageRestriction_inout.Assign( ByteString("en-US") );
+ }
+ else if( sCommand.Search("xmlex") != STRING_NOTFOUND ){
+ sLanguageRestriction_inout.Assign( ByteString("en-US") );
+ }
+ return sLanguageRestriction_inout;
+}
+
+/*****************************************************************************/
+BOOL SourceTreeLocalizer::CheckNegativeList( const ByteString &rFileName )
+/*****************************************************************************/
+{
+ ULONG nIndex = 0;
+ BOOL bReturn = TRUE;
+
+ ByteString sDelimiter(
+ DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
+
+ ByteString sFileName( rFileName );
+ sFileName.ToLowerAscii();
+
+ ByteString sNegative( NegativeList[ nIndex ] );
+ while( !sNegative.Equals( "NULL" ) && bReturn ) {
+ sNegative.SearchAndReplaceAll( "\\", sDelimiter );
+ sNegative.SearchAndReplaceAll( "/", sDelimiter );
+ sNegative.ToLowerAscii();
+
+ if( sFileName.Search( sNegative ) == sFileName.Len() - sNegative.Len())
+ bReturn = FALSE;
+
+ nIndex++;
+ sNegative = NegativeList[ nIndex ];
+ }
+
+ return bReturn;
+}
+
+/*****************************************************************************/
+BOOL SourceTreeLocalizer::CheckPositiveList( const ByteString &rFileName )
+/*****************************************************************************/
+{
+ ULONG nIndex = 0;
+ BOOL bReturn = FALSE;
+
+ ByteString sDelimiter(
+ DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
+
+ ByteString sFileName( rFileName );
+ sFileName.ToLowerAscii();
+
+ ByteString sNegative( PositiveList[ nIndex ] );
+ while( !sNegative.Equals( "NULL" ) && !bReturn ) {
+ sNegative.SearchAndReplaceAll( "\\", sDelimiter );
+ sNegative.SearchAndReplaceAll( "/", sDelimiter );
+ sNegative.ToLowerAscii();
+
+ if( sFileName.Search( sNegative ) == sFileName.Len() - sNegative.Len())
+ bReturn = TRUE;
+
+ nIndex++;
+ sNegative = PositiveList[ nIndex ];
+ }
+
+ return bReturn;
+}
+
+/*****************************************************************************/
+void SourceTreeLocalizer::WorkOnFileType(
+ const ByteString &rDirectory, const ByteString &rExtension,
+ const ByteString &rExecutable, const ByteString &rParameter,
+ const ByteString &rCollectMode
+)
+/*****************************************************************************/
+{
+ String sWild( rDirectory, RTL_TEXTENCODING_ASCII_US );
+ sWild += DirEntry::GetAccessDelimiter();
+ sWild += String::CreateFromAscii( "*." );
+ sWild += String( rExtension, RTL_TEXTENCODING_ASCII_US );
+
+ DirEntry aEntry( sWild );
+ Dir aDir( sWild, FSYS_KIND_FILE );
+
+ for ( USHORT i = 0; i < aDir.Count(); i++ ) {
+ DirEntry aFile( aDir[ i ] );
+ ByteString sFile( aFile.GetFull(), RTL_TEXTENCODING_ASCII_US );
+
+ BOOL bAllowed = TRUE;
+
+ if ( rCollectMode.Equals( "negative" ))
+ bAllowed = CheckNegativeList( sFile );
+ else if ( rCollectMode.Equals( "positive" ))
+ bAllowed = CheckPositiveList( sFile );
+
+ if ( bAllowed )
+ WorkOnFile( sFile, rExecutable, rParameter );
+ }
+}
+
+/*****************************************************************************/
+void SourceTreeLocalizer::WorkOnDirectory( const ByteString &rDirectory )
+/*****************************************************************************/
+{
+ //printf("Working on Directory %s\n",rDirectory.GetBuffer());
+ ULONG nIndex = 0;
+ ByteString sExtension( ExeTable[ nIndex ][ 0 ] );
+ ByteString sExecutable( ExeTable[ nIndex ][ 1 ] );
+ ByteString sParameter( ExeTable[ nIndex ][ 2 ] );
+ ByteString sCollectMode( ExeTable[ nIndex ][ 3 ] );
+
+ while( !sExtension.Equals( "NULL" )) {
+ WorkOnFileType(
+ rDirectory,
+ sExtension,
+ sExecutable,
+ sParameter,
+ sCollectMode
+ );
+
+ nIndex++;
+
+ sExtension = ExeTable[ nIndex ][ 0 ];
+ sExecutable = ExeTable[ nIndex ][ 1 ];
+ sParameter = ExeTable[ nIndex ][ 2 ];
+ sCollectMode = ExeTable[ nIndex ][ 3 ];
+ }
+}
+
+void SourceTreeLocalizer::OnExecuteDirectory( const rtl::OUString &aDirectory )
+{
+ ByteString rDirectory( rtl::OUStringToOString( aDirectory , RTL_TEXTENCODING_UTF8 , aDirectory.getLength() ) ) ;
+ if ( nMode == LOCALIZE_NONE ){
+ if( !bQuiet2 ) fprintf( stdout, "%s\n", rDirectory.GetBuffer());
+ }
+ else
+ WorkOnDirectory( rDirectory );
+}
+
+/*****************************************************************************/
+BOOL SourceTreeLocalizer::Extract( const ByteString &rDestinationFile )
+/*****************************************************************************/
+{
+ nMode = LOCALIZE_EXTRACT;
+
+ aSDF.Open( String( rDestinationFile , RTL_TEXTENCODING_ASCII_US ) , STREAM_STD_WRITE );
+ aSDF.SetLineDelimiter( LINEEND_CRLF );
+
+ BOOL bReturn = aSDF.IsOpen();
+ if ( bReturn ) {
+ aSDF.Seek( STREAM_SEEK_TO_END );
+ bReturn = StartExecute();
+ aSDF.Close();
+ }
+ else{
+ printf("ERROR: Can't create file %s\n", rDestinationFile.GetBuffer() );
+ }
+ nMode = LOCALIZE_NONE;
+ aSDF.Close();
+ return bReturn;
+}
+
+/*****************************************************************************/
+BOOL SourceTreeLocalizer::MergeSingleFile(
+ const ByteString &rPrj,
+ const ByteString &rFile,
+ const ByteString &rSDFFile
+)
+/*****************************************************************************/
+{
+ //printf("MergeSingleFile(%s,%s,%s)",rPrj.GetBuffer(),rFile.GetBuffer(),rSDFFile.GetBuffer());
+ if ( !rFile.Len())
+ return TRUE;
+
+ ByteString sRoot( Export::GetEnv( "SRC_ROOT" ));
+ DirEntry aEntry( String( sRoot, RTL_TEXTENCODING_ASCII_US ));
+ aEntry += DirEntry( String( rPrj, RTL_TEXTENCODING_ASCII_US ));
+
+ ByteString sDelimiter(
+ DirEntry::GetAccessDelimiter(), RTL_TEXTENCODING_ASCII_US );
+
+ ByteString sCur( rFile );
+ sCur.SearchAndReplaceAll( "\\", sDelimiter );
+ sCur.SearchAndReplaceAll( "/", sDelimiter );
+
+ aEntry += DirEntry( String( sCur, RTL_TEXTENCODING_ASCII_US ));
+ ByteString sFile( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
+
+ ByteString sBCur( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
+ if( !bQuiet2 ) fprintf( stdout, "##### %s #####\n", sBCur.GetBuffer());
+
+ ULONG nIndex = 0;
+ ByteString sExtension( aEntry.GetExtension(), RTL_TEXTENCODING_ASCII_US );
+ ByteString sCandidate( ExeTable[ nIndex ][ 0 ] );
+
+ while( !sCandidate.Equals ("NULL") && !sCandidate.Equals(sExtension) )
+ sCandidate = ExeTable[ ++nIndex ][ 0 ];
+
+ if ( !sCandidate.Equals( "NULL" ) ) {
+ if( !aEntry.Exists()) {
+ DirEntryKind theDir=FSYS_KIND_FILE;
+ Dir myDir( aEntry.GetPath(), theDir);
+ DirEntry current;
+ BOOL found=FALSE;
+ for( USHORT x=0; x < myDir.Count() && !found;){
+ current=myDir[x++];
+ StringCompare result=current.GetName().CompareIgnoreCaseToAscii( aEntry.GetName() );
+ if( result==COMPARE_EQUAL ){
+ fprintf(stderr,"WARNING: %s not found\n", ByteString(aEntry.GetFull(),RTL_TEXTENCODING_ASCII_US).GetBuffer() );
+ fprintf(stderr,"but use %s instead \n" , ByteString(current.GetFull(), RTL_TEXTENCODING_ASCII_US).GetBuffer() );
+ aEntry=current;
+ found=TRUE;
+ }
+ }
+ if(!found) return TRUE;
+
+ }
+
+ DirEntry aOut( Export::GetTempFile() );
+ ByteString sOutput;
+ if( sOutputFile.Len() == 0 )
+ sOutput = ByteString ( aOut.GetFull(), RTL_TEXTENCODING_ASCII_US );
+ else
+ sOutput = sOutputFile;
+ ByteString sCommand( ExeTable[ nIndex ][ 1 ] );
+ sCommand += " -i ";
+ sCommand += ByteString( aEntry.GetName(), RTL_TEXTENCODING_ASCII_US );
+ sCommand += " -m ";
+ sCommand += rSDFFile;
+ sCommand += " -o ";
+ sCommand += sOutput;
+ sCommand += " ";
+ sCommand += ByteString( ExeTable[ nIndex ][ 2 ] );
+ if ( sLanguageRestriction.Len()) {
+ sCommand += " -l ";
+ sCommand += sLanguageRestriction;
+ }
+ if( bQuiet2 ){
+ sCommand +=" -QQ ";
+ }
+
+ DirEntry aPath( aEntry.GetPath());
+ DirEntry aOldCWD;
+ aPath.SetCWD();
+
+ if (system(sCommand.GetBuffer()) == -1)
+ fprintf(stderr, "%s failed\n", sCommand.GetBuffer());
+ nFileCnt++;
+ printf(".");
+ //if( bQuiet2 ){ printf("."); }
+ SvFileStream aInStream( aOut.GetFull(), STREAM_READ );
+ if ( !aInStream.IsOpen()) {
+ fprintf( stderr,
+ "ERROR: Unable to open file %s for reading!\n",
+ sOutput.GetBuffer());
+ }
+ else {
+ FileStat::SetReadOnlyFlag( aEntry, FALSE );
+ String myStr2(aEntry.GetFull());
+ String aTemp22 = String::CreateFromAscii("_tmp");
+ myStr2.Append(aTemp22);
+
+ ByteString test(myStr2,RTL_TEXTENCODING_ASCII_US);
+ SvFileStream aOutStream( myStr2, STREAM_STD_WRITE | STREAM_TRUNC );
+ if ( !aOutStream.IsOpen()) {
+ ByteString test2(myStr2,RTL_TEXTENCODING_ASCII_US);
+ fprintf( stderr,"ERROR: Unable to open file %s for modification!\n", test2.GetBuffer());
+ aInStream.Close();
+ }
+
+ else {
+ ByteString sLine;
+ aOutStream.SetLineDelimiter( LINEEND_LF );
+
+ aInStream.ReadLine( sLine );
+ while ( !aInStream.IsEof()) {
+ aOutStream.WriteLine( sLine );
+ aInStream.ReadLine( sLine );
+ }
+ aInStream.Close();
+ aOutStream.Close();
+
+
+ DirEntry myTempFile(ByteString(myStr2,RTL_TEXTENCODING_ASCII_US)); // xxx_tmp ->
+ DirEntry myFile(ByteString(aEntry.GetFull(),RTL_TEXTENCODING_ASCII_US));// xxx
+
+ DirEntry oldFile(ByteString(aEntry.GetFull(),RTL_TEXTENCODING_ASCII_US));
+
+ if(oldFile.Kill()==ERRCODE_NONE){
+ if(myTempFile.MoveTo(myFile)!=ERRCODE_NONE){
+ fprintf( stderr, "ERROR: Can't rename file %s\n",ByteString(myStr2,RTL_TEXTENCODING_ASCII_US).GetBuffer());
+ }
+ }
+ else{
+ fprintf( stderr, "ERROR: Can't remove file %s\n",ByteString(aEntry.GetFull(),RTL_TEXTENCODING_ASCII_US).GetBuffer());
+ }
+ } // else
+
+ aOldCWD.SetCWD();
+ aOut.Kill();
+ } // else
+ }
+ return TRUE;
+}
+/*****************************************************************************/
+BOOL SourceTreeLocalizer::ExecuteMerge( )
+/*****************************************************************************/
+{
+ DirEntry aEntry( Export::GetTempFile());
+ BOOL bReturn = TRUE;
+ bool bMerged = false;
+
+ ByteString sFileName;
+ ByteString sCurFile;
+ ByteString sLine;
+ ByteString sFileKey;
+
+ SvFileStream aFile;
+
+ ByteString sOutputFileName = sOutputFile;
+ ByteString sInpath(".");
+ sInpath += Export::GetEnv("INPATH");
+ ByteString sBlank("");
+
+ sOutputFileName.SearchAndReplaceAll( sInpath , sBlank );
+
+ String sDel = DirEntry::GetAccessDelimiter();
+ ByteString sBDel( sDel.GetBuffer() , sDel.Len() , RTL_TEXTENCODING_UTF8 );
+ if( bLocal ){
+ xub_StrLen nPos = sOutputFileName.SearchBackward( sBDel.GetChar(0) );
+ sOutputFileName = sOutputFileName.Copy( nPos+1 , sOutputFileName.Len()-nPos-1 );
+ }
+ ByteStringBoolHashMap aFileHM;
+ // Read all possible files
+ while ( !aSDF.IsEof()) {
+ aSDF.ReadLine( sLine );
+ sFileName = sLine.GetToken( 0, '\t' );
+ sFileName += "#";
+ sFileName += sLine.GetToken( 1, '\t' );
+ aFileHM[sFileName]=true;
+ }
+
+ for( ByteStringBoolHashMap::iterator iter = aFileHM.begin(); iter != aFileHM.end(); ++iter ){
+ sFileKey = iter->first;
+ aSDF.Seek( 0 );
+ aFile.Open( aEntry.GetFull(), STREAM_STD_WRITE |STREAM_TRUNC );
+
+ while ( !aSDF.IsEof()) {
+ aSDF.ReadLine( sLine );
+ sFileName = sLine.GetToken( 0, '\t' );
+ sFileName += "#";
+ sFileName += sLine.GetToken( 1, '\t' );
+ if( sFileName.Len() && ( sFileName.CompareTo(sFileKey) == COMPARE_EQUAL ) ){
+ if ( aFile.IsOpen() && sLine.Len())
+ aFile.WriteLine( sLine );
+ }
+ }
+ if ( aFile.IsOpen())
+ aFile.Close();
+
+ ByteString sPrj( sFileKey.GetToken( 0, '#' ));
+ ByteString sFile( sFileKey.GetToken( 1, '#' ));
+ ByteString sSDFFile( aFile.GetFileName(), RTL_TEXTENCODING_ASCII_US );
+
+ //printf("localize test sPrj = %s , sFile = %s , sSDFFile = %s sOutputFileName = %s\n",sPrj.GetBuffer(), sFile.GetBuffer() , sSDFFile.GetBuffer() , sOutputFileName.GetBuffer() );
+
+ // Test
+ bLocal = true;
+ // Test
+
+ if( bLocal ){
+ USHORT nPos = sFile.SearchBackward( '\\' );
+ ByteString sTmp = sFile.Copy( nPos+1 , sFile.Len()-nPos-1 );
+ //printf("'%s'='%s'\n",sTmp.GetBuffer(), sOutputFileName.GetBuffer());
+ if( sTmp.CompareTo(sOutputFileName) == COMPARE_EQUAL ){
+ bMerged = true;
+ if ( !MergeSingleFile( sPrj, sFile, sSDFFile ))
+ bReturn = FALSE;
+ }else{
+ bMerged = true;
+ //printf("MergeSingleFile('%s','%s','%s')\n",sPrj.GetBuffer(),sFile.GetBuffer(),sSDFFile.GetBuffer());
+ if ( !MergeSingleFile( sPrj, sFile, sSDFFile ))
+ bReturn = FALSE;
+ }
+ }
+ }
+ aEntry.Kill();
+ // If Outputfile not included in the SDF file copy it without merge
+
+ if( bLocal && !bMerged ){
+ DirEntry aSourceFile( sOutputFileName.GetBuffer() );
+ FSysError aErr = aSourceFile.CopyTo( DirEntry ( sOutputFile.GetBuffer() ) , FSYS_ACTION_COPYFILE );
+ if( aErr != FSYS_ERR_OK ){
+ printf("ERROR: Can't copy file '%s' to '%s' %d\n",sOutputFileName.GetBuffer(),sOutputFile.GetBuffer(),sal::static_int_cast<int>(aErr));
+ }
+ }
+ return bReturn;
+
+}
+
+/*****************************************************************************/
+BOOL SourceTreeLocalizer::Merge( const ByteString &rSourceFile , const ByteString &rOutput )
+/*****************************************************************************/
+{
+ sOutputFile = rOutput;
+ nMode = LOCALIZE_MERGE;
+ aSDF.Open( String( rSourceFile, RTL_TEXTENCODING_ASCII_US ),
+ STREAM_STD_READ );
+
+ BOOL bReturn = aSDF.IsOpen();
+ if ( bReturn ) {
+ bReturn = ExecuteMerge();
+// aSDF.Close();
+ }
+ aSDF.Close();
+ nMode = LOCALIZE_NONE;
+ return bReturn;
+}
+
+}
+using namespace transex3;
+
+#define STATE_NONE 0x0000
+#define STATE_EXPORT 0x0001
+#define STATE_MERGE 0x0002
+#define STATE_ISOCODE 0x0003
+#define STATE_LANGUAGES 0x0004
+#define STATE_FILENAME 0x0005
+#define STATE_OUTPUT 0x0006
+
+/*****************************************************************************/
+void Help()
+/*****************************************************************************/
+{
+ fprintf( stdout,
+ "localize (c)2001 by Sun Microsystems\n"
+ "====================================\n" );
+ fprintf( stdout,
+ "As part of the L10N framework, localize extracts and merges translations\n"
+ "out of and into the whole source tree.\n\n"
+ "Syntax: localize -e -l en-US -f FileName [-QQ]\n"
+ "Parameter:\n"
+ "\t-e: Extract mode\n"
+ "\tFileName: Output file when extract mode, input file when merge mode\n"
+ "\tl1...ln: supported languages (\"all\" for all languages).\n"
+ "\tQQ: quiet output)"
+ );
+
+ fprintf( stdout,
+ "Valid language codes for l1...ln and f1...fn are:\n" );
+ fprintf( stdout,
+ "\nExample 1:\n"
+ "==========\n"
+ "localize -e -l en-US -f MyFile\n\n"
+ "All strings will be extracted for language de and language en-US.\n"
+ );
+}
+
+/*****************************************************************************/
+int Error()
+/*****************************************************************************/
+{
+ Help();
+ return 1;
+}
+
+/*****************************************************************************/
+BOOL CheckLanguages( ByteString &rLanguages )
+/*****************************************************************************/
+{
+ ByteString sTmp( rLanguages );
+ return true;
+}
+
+/*****************************************************************************/
+#if defined(UNX) || defined(OS2)
+int main( int argc, char *argv[] )
+#else
+int _cdecl main( int argc, char *argv[] )
+#endif
+/*****************************************************************************/
+{
+ String sTempBase( String::CreateFromAscii( "loc" ));
+ DirEntry::SetTempNameBase( sTempBase );
+ USHORT nState = STATE_NONE;
+
+ BOOL bExport = FALSE;
+ BOOL bMerge = FALSE;
+ bool bQuiet = false;
+ bool bQuiet2 = false;
+ bool bSkipLinks = false;
+
+ ByteString sLanguages;
+ ByteString sFileName;
+ ByteString sOutput;
+
+ bQuiet2 = true;
+ bExport = TRUE;
+
+ for( int i = 1; i < argc; i++ ) {
+ ByteString sSwitch( argv[ i ] );
+ sSwitch.ToUpperAscii();
+
+ if ( sSwitch.Equals( "-E" )) {
+ nState = STATE_EXPORT;
+ if ( bMerge )
+ return Error();
+ bExport = TRUE;
+ }
+ else if( sSwitch.Equals( "-Q" )) {
+ bQuiet = true;
+ }
+ else if ( sSwitch.Equals( "-I" ) )
+ nState = STATE_ISOCODE;
+ else if ( sSwitch.Equals( "-L" ) )
+ nState = STATE_LANGUAGES;
+ else if ( sSwitch.Equals( "-F" ) )
+ nState = STATE_FILENAME;
+ else if ( sSwitch.Equals( "-QQ" ))
+ bQuiet2 = true;
+ else if ( ByteString( argv[ i ]).ToUpperAscii().Equals( "-O" ) )
+ nState = STATE_OUTPUT;
+ else {
+ switch ( nState ) {
+ case STATE_NONE:
+ return Error();
+ case STATE_OUTPUT:
+ if ( sOutput.Len())
+ return Error();
+ sOutput = ByteString( argv[ i ] );
+ nState = STATE_NONE;
+ break;
+ case STATE_LANGUAGES:
+ if ( sLanguages.Len())
+ return Error();
+ sLanguages = ByteString( argv[ i ] );
+ nState = STATE_NONE;
+ break;
+ case STATE_FILENAME:
+ if ( sFileName.Len())
+ return Error();
+ sFileName = ByteString( argv[ i ] );
+ nState = STATE_NONE;
+ break;
+ default:
+ return Error();
+ }
+ }
+ }
+ if ( !bMerge && !bExport ) {
+ Help();
+ return 1;
+ }
+
+ ByteString sSolarVer( Export::GetEnv( "WORK_STAMP" ));
+ ByteString sVersion( Export::GetEnv( "WORK_STAMP" ));
+
+ if ( !sSolarVer.Len() || !sVersion.Len()) {
+ fprintf( stderr, "ERROR: No environment set!\n" );
+ return 1;
+ }
+
+ if ( !CheckLanguages( sLanguages ))
+ return 2;
+
+ if ( !sFileName.Len()) {
+ fprintf( stderr, "ERROR: No filename given\n" );
+ return 3;
+ }
+
+ DirEntry aEntry( String( sFileName , RTL_TEXTENCODING_ASCII_US ));
+ aEntry.ToAbs();
+ String sFullEntry = aEntry.GetFull();
+ ByteString sFileABS( aEntry.GetFull(), gsl_getSystemTextEncoding());
+ //printf("B %s\nA %s\n",rDestinationFile.GetBuffer(), sFile.GetBuffer());
+ sFileName = sFileABS;
+
+ Treeconfig treeconfig;
+ vector<string> repos;
+ bool hasPwd = treeconfig.getActiveRepositories( repos );
+ if( hasPwd ) cout << "Found special path!\n";
+
+ string minor_ext;
+ bool has_minor_ext;
+
+ if( Export::GetEnv("UPDMINOREXT") != NULL )
+ {
+ minor_ext = string( Export::GetEnv("UPDMINOREXT") );
+ has_minor_ext = minor_ext.size();
+ }
+ else
+ has_minor_ext = false;
+
+ // localize through all repositories
+ for( vector<string>::iterator iter = repos.begin(); iter != repos.end() ; ++iter )
+ {
+ string curRepository;
+ if( has_minor_ext )
+ curRepository = string( Export::GetEnv("SOURCE_ROOT_DIR") ) + "/" + *iter + minor_ext;
+ else
+ curRepository = string( Export::GetEnv("SOURCE_ROOT_DIR") ) + "/" + *iter;
+ cout << "Localizing repository " << curRepository << "\n";
+ SourceTreeLocalizer aIter( ByteString( curRepository.c_str() ) , sVersion , (sOutput.Len() > 0) , bQuiet2 , bSkipLinks );
+ aIter.SetLanguageRestriction( sLanguages );
+ if ( bExport ){
+ if( bQuiet2 ){ /*printf("");*/fflush( stdout );}
+ aIter.Extract( sFileName );
+ if( bQuiet2 ){ printf("\n %d files found!\n",aIter.GetFileCnt());}
+ }
+ }
+ if( hasPwd )
+ {
+ string pwd;
+ Export::getCurrentDir( pwd );
+ cout << "Localizing repository " << pwd << "\n";
+ SourceTreeLocalizer aIter( ByteString( pwd.c_str() ) , sVersion , (sOutput.Len() > 0) , bQuiet2 , bSkipLinks );
+ aIter.SetLanguageRestriction( sLanguages );
+ if ( bExport ){
+ if( bQuiet2 ){ /*printf("");*/fflush( stdout );}
+ aIter.Extract( sFileName );
+ if( bQuiet2 ){ printf("\n %d files found!\n",aIter.GetFileCnt());}
+ }
+
+ }
+
+ return 0;
+}
+
diff --git a/l10ntools/source/makefile.mk b/l10ntools/source/makefile.mk
new file mode 100644
index 000000000000..fe4ecc919179
--- /dev/null
+++ b/l10ntools/source/makefile.mk
@@ -0,0 +1,210 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.46 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..
+
+INCPRE=$(MISC)
+
+PRJNAME=l10ntools
+TARGET=transex
+TARGETTYPE=CUI
+LIBTARGET=no
+# --- Settings -----------------------------------------------------
+ENABLE_EXCEPTIONS=TRUE
+
+.INCLUDE : settings.mk
+CDEFS+= -DYY_NEVER_INTERACTIVE=1
+#CDEFS+= -pg
+
+.IF "$(SYSTEM_EXPAT)" == "YES"
+CFLAGS+=-DSYSTEM_EXPAT
+.ENDIF
+
+
+# --- Files --------------------------------------------------------
+
+OBJFILES= \
+ $(OBJ)$/export.obj \
+ $(OBJ)$/export2.obj \
+ $(OBJ)$/merge.obj \
+ $(OBJ)$/srciter.obj \
+ $(OBJ)$/utf8conv.obj \
+ $(OBJ)$/xmlparse.obj \
+ $(OBJ)$/helpmerge.obj \
+ $(OBJ)$/helpex.obj \
+ $(OBJ)$/file.obj \
+ $(OBJ)$/directory.obj
+
+
+LIB1TARGET= $(LB)$/$(TARGET).lib
+LIB1ARCHIV= $(LB)$/libtransex.a
+#LIB1FILES= $(LB)$/transex3.lib
+LIB1OBJFILES= $(OBJ)$/export.obj \
+ $(OBJ)$/export2.obj \
+ $(OBJ)$/merge.obj \
+ $(OBJ)$/srciter.obj \
+ $(OBJ)$/file.obj \
+ $(OBJ)$/directory.obj \
+ $(OBJ)$/utf8conv.obj
+
+
+APP1VERSIONMAP=exports.map
+
+# extractor and merger for *.src and *.hrc
+APP1TARGET= transex3
+#APP1OBJS= $(OBJ)$/src_yy.obj
+APP1OBJS= $(OBJ)$/src_yy_wrapper.obj
+
+APP1STDLIBS+= \
+ $(TOOLSLIB) \
+ $(VOSLIB) \
+ $(SALLIB)
+
+.IF "$(OS)"=="MACOSX"
+# static libs at end for OS X
+.ENDIF
+
+APP1LIBS+= $(LB)$/$(TARGET).lib
+APP1DEPN= $(OBJ)$/src_yy_wrapper.obj $(LB)$/$(TARGET).lib
+
+APP2TARGET= helpex
+APP2OBJS= $(OBJ)$/helpmerge.obj $(OBJ)$/xmlparse.obj $(OBJ)$/export2.obj $(OBJ)$/utf8conv.obj $(OBJ)$/merge.obj $(OBJ)$/helpex.obj
+APP2RPATH= NONE
+
+.IF "$(OS)"!="MACOSX"
+.ENDIF
+
+APP2STDLIBS+=$(SALLIB) $(EXPATASCII3RDLIB) $(TOOLSLIB) $(VOSLIB)
+
+.IF "$(OS)"=="MACOSX"
+# static libs at end for OS X
+.ENDIF
+
+# extractor and merger for *.lng and *.lng
+APP3TARGET= ulfex
+APP3OBJS= $(OBJ)$/lngmerge.obj $(OBJ)$/merge.obj $(OBJ)$/export2.obj $(OBJ)$/lngex.obj $(OBJ)$/utf8conv.obj
+APP3RPATH= NONE
+
+.IF "$(OS)"!="MACOSX"
+#APP3STDLIBS+= $(BTSTRPLIB)
+.ENDIF
+APP3STDLIBS+= \
+ $(TOOLSLIB) \
+ $(VOSLIB) \
+ $(SALLIB)
+.IF "$(OS)"=="MACOSX"
+# static libs at end for OS X
+.ENDIF
+
+# encoding converter for *.gsi
+APP4TARGET= gsiconv
+APP4OBJS= $(OBJ)$/utf8conv.obj $(OBJ)$/gsiconv.obj
+APP4STDLIBS+= \
+ $(TOOLSLIB) \
+ $(VOSLIB) \
+ $(SALLIB)
+
+# tag checker for *.gsi
+APP5TARGET= gsicheck
+APP5OBJS= $(OBJ)$/gsicheck.obj $(OBJ)$/tagtest.obj
+APP5STDLIBS+= \
+ $(TOOLSLIB) \
+ $(VOSLIB) \
+ $(SALLIB)
+
+# extractor and merger for *.cfg
+APP6TARGET= cfgex
+APP6OBJS= $(OBJ)$/cfgmerge.obj $(OBJ)$/cfg_yy_wrapper.obj $(OBJ)$/merge.obj $(OBJ)$/export2.obj $(OBJ)$/utf8conv.obj
+
+.IF "$(OS)"!="MACOSX"
+#APP6STDLIBS+= $(BTSTRPLIB)
+.ENDIF
+
+APP6STDLIBS+= \
+ $(TOOLSLIB) \
+ $(VOSLIB) \
+ $(SALLIB)
+
+.IF "$(OS)"=="MACOSX"
+# static libs at end for OS X
+.ENDIF
+
+# extractor and merger for *.xrm
+APP7TARGET= xrmex
+APP7OBJS= $(OBJ)$/xrmmerge.obj $(OBJ)$/xrm_yy_wrapper.obj $(OBJ)$/merge.obj $(OBJ)$/export2.obj $(OBJ)$/utf8conv.obj
+APP7RPATH= NONE
+
+.IF "$(OS)"!="MACOSX"
+.ENDIF
+
+APP7STDLIBS+= \
+ $(TOOLSLIB) \
+ $(VOSLIB) \
+ $(SALLIB)
+
+.IF "$(OS)"=="MACOSX"
+# static libs at end for OS X
+.ENDIF
+
+#
+#APP8TARGET= treeconfig
+#APP8OBJS= $(OBJ)$/treeconfig.obj $(OBJ)$/inireader.obj $(OBJ)$/export2.obj
+#APP8STDLIBS=$(TOOLSLIB) $(SALLIB) $(VOSLIB) $(ICUINLIB) $(STLPORT)
+
+# localizer for l10n framework
+APP9TARGET= localize_sl
+EXCEPTIONSFILES= \
+ $(OBJ)$/localize.obj
+APP9OBJS= $(OBJ)$/localize.obj $(OBJ)$/utf8conv.obj $(OBJ)$/srciter.obj $(OBJ)$/export2.obj $(OBJ)$/file.obj $(OBJ)$/directory.obj $(OBJ)$/treeconfig.obj $(OBJ)$/inireader.obj
+
+APP9STDLIBS+= \
+ $(TOOLSLIB) \
+ $(VOSLIB) \
+ $(ICUINLIB) \
+ $(ICUUCLIB) \
+ $(STLPORTLIB) \
+ $(SALLIB)
+
+DEPOBJFILES=$(APP1OBJS) $(APP2OBJS) $(APP3OBJS) $(APP4OBJS) $(APP5OBJS) $(APP6OBJS) $(APP7OBJS) $(APP8OBJS) $(APP9OBJS)
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+$(MISC)$/%_yy.c : %lex.l
+ flex -l -w -8 -o$@ $<
+
+# Helper to suppress warnings in lex generated c code, see #i57362#
+
+$(OBJ)$/src_yy_wrapper.obj: $(MISC)$/src_yy.c
+$(OBJ)$/cfg_yy_wrapper.obj: $(MISC)$/cfg_yy.c
+$(OBJ)$/xrm_yy_wrapper.obj: $(MISC)$/xrm_yy.c
+
diff --git a/l10ntools/source/merge.cxx b/l10ntools/source/merge.cxx
new file mode 100644
index 000000000000..42f539065651
--- /dev/null
+++ b/l10ntools/source/merge.cxx
@@ -0,0 +1,445 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: merge.cxx,v $
+ * $Revision: 1.27.36.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <stdio.h>
+#include <tools/fsys.hxx>
+#include "export.hxx"
+#include "utf8conv.hxx"
+#include <iostream>
+
+using namespace std;
+
+extern void ConvertHalfwitdhToFullwidth( String& rString );
+
+//
+// class PFormEntrys
+//
+
+ByteString PFormEntrys::Dump(){
+ ByteString sRet( "PFormEntrys\n" );
+ //sRet.Append( Export::DumpMap( ByteString("sText") , sText ) );
+ //sRet.Append("\n");
+ ByteString a("sText");
+ if ( sText.size() ) Export::DumpMap( a , sText );
+ return sRet;
+}
+
+/*****************************************************************************/
+BOOL PFormEntrys::GetText( ByteString &rReturn,
+ USHORT nTyp, const ByteString &nLangIndex, BOOL bDel )
+/*****************************************************************************/
+{
+
+ /*printf("DBG: PFormEntrys::GetText(nId=%s)\n",nLangIndex.GetBuffer() );
+
+ // DEBUG******************
+ ByteStringHashMap::const_iterator idbg;
+ std::cout << "HASHKEYS : \n";
+ for( idbg = sText.begin() ; idbg != sText.end(); ++idbg )
+ std::cout << (idbg->first).GetBuffer() << "\n";
+ std::cout << "\n\n";
+ std::cout << "String sText[ nLangIndex ] = " << sText[ nLangIndex ].GetBuffer() << "\n";
+ // DEBUG******************
+*/
+
+ BOOL bReturn=TRUE;
+ switch ( nTyp ) {
+ case STRING_TYP_TEXT :
+ rReturn = sText[ nLangIndex ];
+ if ( bDel )
+ sText[ nLangIndex ] = "";
+ bReturn = bTextFirst[ nLangIndex ];
+ bTextFirst[ nLangIndex ] = FALSE;
+ break;
+ case STRING_TYP_HELPTEXT :
+ rReturn = sHelpText;
+ break;
+ case STRING_TYP_QUICKHELPTEXT :
+ rReturn = sQuickHelpText[ nLangIndex ];
+ if ( bDel )
+ sQuickHelpText[ nLangIndex ] = "";
+ bReturn = bQuickHelpTextFirst[ nLangIndex ];
+ bQuickHelpTextFirst[ nLangIndex ] = FALSE;
+ break;
+ case STRING_TYP_TITLE :
+ rReturn = sTitle[ nLangIndex ];
+ if ( bDel )
+ sTitle[ nLangIndex ] = "";
+ bReturn = bTitleFirst[ nLangIndex ];
+ bTitleFirst[ nLangIndex ] = FALSE;
+ break;
+ }
+ //printf("Returning '%s'\n",rReturn.GetBuffer());
+ return bReturn;
+}
+
+
+//
+// class MergeData
+//
+
+/*****************************************************************************/
+MergeData::~MergeData()
+/*****************************************************************************/
+{
+}
+
+/*****************************************************************************/
+PFormEntrys* MergeData::GetPFormEntrys( ResData *pResData )
+/*****************************************************************************/
+{
+
+ (void) pResData; // FIXME
+ if( aMap.find( ByteString("HACK") ) != aMap.end() ){
+ return aMap[ ByteString("HACK") ];
+ }
+ else{
+ return 0;
+ }
+}
+
+void MergeData::Insert( const ByteString& rPFO , PFormEntrys* pfEntrys ){
+ (void) rPFO; // FIXME
+ aMap.insert( PFormEntrysHashMap::value_type( ByteString("HACK") , pfEntrys ) );
+
+}
+ByteString MergeData::Dump(){
+ ByteString sRet( "MergeData\n" );
+
+ printf("MergeData sTyp = %s , sGid = %s , sLid =%s , sFilename = %s\n",sTyp.GetBuffer(),sGID.GetBuffer(),sLID.GetBuffer(), sFilename.GetBuffer() );
+
+ PFormEntrysHashMap::const_iterator idbg;
+ for( idbg = aMap.begin() ; idbg != aMap.end(); ++idbg ){
+ printf("aMap[ %s ] = " ,idbg->first.GetBuffer());
+ ( (PFormEntrys*)(idbg->second) )->Dump();
+ printf("\n") ;
+ }
+ printf("\n") ;
+ return sRet;
+}
+
+PFormEntrys* MergeData::GetPFObject( const ByteString& rPFO ){
+ if( aMap.find( ByteString("HACK") ) != aMap.end() ){
+ return aMap[ rPFO ];
+ }
+ else{
+ return 0;
+ }
+}
+
+
+/*****************************************************************************/
+PFormEntrys *MergeData::InsertEntry( const ByteString &rPForm )
+/*****************************************************************************/
+{
+ PFormEntrys* pFEntrys = new PFormEntrys( rPForm );
+ aMap.insert( PFormEntrysHashMap::value_type( rPForm , pFEntrys ) );
+ return pFEntrys;
+}
+
+/*****************************************************************************/
+BOOL MergeData::operator==( ResData *pData )
+/*****************************************************************************/
+{
+ ByteString sResTyp_upper( pData->sResTyp );
+ sResTyp_upper.ToUpperAscii();
+ ByteString sTyp_upper( sTyp );
+ sTyp_upper.ToUpperAscii();
+
+ return (( pData->sId == sLID ) &&
+ ( pData->sGId == sGID ) &&
+ ( sResTyp_upper == sTyp_upper )
+ );
+}
+
+//
+// class MergeDataFile
+//
+
+#define FFORMAT_UNKNOWN 0x0000
+#define FFORMAT_NEW 0x0001
+#define FFORMAT_OLD 0x0002
+
+/*****************************************************************************/
+MergeDataFile::MergeDataFile( const ByteString &rFileName, const ByteString& sFile ,BOOL bErrLog,
+// CharSet aCharSet, BOOL bUTF8 , bool bCaseSensitive )
+ CharSet aCharSet, bool bCaseSensitive )
+
+/*****************************************************************************/
+ : bErrorLog( bErrLog )
+{
+
+ SvFileStream aInputStream( String( rFileName, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ );
+ aInputStream.SetStreamCharSet( aCharSet );
+ ByteString sLine;
+// printf("\nReading localize.sdf ...\n");
+ ByteString sTYP;
+ ByteString sGID;
+ ByteString sLID;
+ ByteString sPFO;
+ ByteString nLANG;
+ ByteString sTEXT;
+ ByteString sQHTEXT;
+ ByteString sTITLE;
+ ByteString sHACK("HACK");
+
+ const ByteString sEmpty("");
+
+ if( !aInputStream.IsOpen() ) {
+ printf("Warning : Can't open %s\n", rFileName.GetBuffer());
+ //exit( -1 );
+ return;
+ }
+ while ( !aInputStream.IsEof()) {
+ xub_StrLen nToks;
+ aInputStream.ReadLine( sLine );
+ sLine = sLine.Convert( RTL_TEXTENCODING_MS_1252, aCharSet );
+
+ nToks = sLine.GetTokenCount( '\t' );
+ if ( nToks == 15 ) {
+ // Skip all wrong filenames
+ ByteString filename = sLine.GetToken( 1 , '\t' );
+ filename = filename.Copy( filename.SearchCharBackward( "\\" )+1 , filename.Len() );
+
+ if( sFile.Equals( sEmpty ) || ( !sFile.Equals( sEmpty ) && filename.Equals( sFile ) ) )
+ {
+ xub_StrLen rIdx = 0;
+ sTYP = sLine.GetToken( 3, '\t', rIdx );
+ sGID = sLine.GetToken( 0, '\t', rIdx ); // 4
+ sLID = sLine.GetToken( 0, '\t', rIdx ); // 5
+ sPFO = sLine.GetToken( 1, '\t', rIdx ); // 7
+ sPFO = sHACK;
+ nLANG = sLine.GetToken( 1, '\t', rIdx ); // 9
+ sTEXT = sLine.GetToken( 0, '\t', rIdx ); // 10
+
+ sQHTEXT = sLine.GetToken( 1, '\t', rIdx ); // 12
+ sTITLE = sLine.GetToken( 0, '\t', rIdx ); // 13
+
+ nLANG.EraseLeadingAndTrailingChars();
+
+#ifdef MERGE_SOURCE_LANGUAGES
+ if( true ){
+#else
+ if ( !nLANG.EqualsIgnoreCaseAscii("en-US") ){
+#endif
+ ByteStringHashMap::const_iterator lit;
+ lit = aLanguageMap.find (nLANG);
+ ByteString aLANG;
+ if (lit == aLanguageMap.end()) {
+ aLANG = nLANG;
+ aLanguageMap.insert( ByteStringHashMap::value_type( aLANG, aLANG ) );
+ // Remember read languages for -l all switch
+ aLanguageList.push_back( nLANG );
+ } else
+ aLANG = lit->first;
+
+ InsertEntry( sTYP, sGID, sLID, sPFO, aLANG, sTEXT, sQHTEXT, sTITLE , filename , bCaseSensitive );
+ }
+ }
+ }
+ else if ( nToks == 10 ) {
+ printf("ERROR: File format is obsolete and no longer supported!\n");
+ }
+ }
+ aInputStream.Close();
+}
+/*****************************************************************************/
+MergeDataFile::~MergeDataFile()
+/*****************************************************************************/
+{
+}
+
+/*****************************************************************************/
+//void MergeDataFile::WriteErrorLog( const ByteString &rFileName )
+/*****************************************************************************/
+//{
+// DEAD
+//}
+
+ByteString MergeDataFile::Dump(){
+ ByteString sRet( "MergeDataFile\n" );
+
+ //sRet.Append( Export::DumpMap( "aLanguageSet" , aLanguageSet ) );
+ //sRet.Append( Export::DumpMap( "aLanguageList" , aLanguageList ) );
+ printf("MergeDataFile\n");
+ MergeDataHashMap::const_iterator idbg;
+ for( idbg = aMap.begin() ; idbg != aMap.end(); ++idbg ){
+ /*sRet.Append( "aMap[" );
+ sRet.Append( idbg->first );
+ sRet.Append( "]= " );
+ sRet.Append( ((MergeData*) (idbg->second))->Dump() );
+ sRet.Append("\n");*/
+
+ printf("aMap[ %s ] = ",idbg->first.GetBuffer());
+ ((MergeData*) (idbg->second))->Dump();
+ printf("\n");
+ }
+ printf("\n");
+ //sRet.Append("\n");
+ return sRet;
+}
+
+/*****************************************************************************/
+void MergeDataFile::WriteError( const ByteString &rLine )
+/*****************************************************************************/
+{
+ if ( bErrorLog ) {
+ if ( !aErrLog.IsOpen())
+ aErrLog.Open( String( sErrorLog, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_WRITE | STREAM_TRUNC );
+ aErrLog.WriteLine( rLine );
+ }
+ else
+ fprintf( stderr, "%s\n", rLine.GetBuffer());
+}
+std::vector<ByteString> MergeDataFile::GetLanguages(){
+ return aLanguageList;
+}
+
+/*****************************************************************************/
+MergeData *MergeDataFile::GetMergeData( ResData *pResData , bool bCaseSensitive )
+/*****************************************************************************/
+{
+ ByteString sOldG = pResData->sGId;
+ ByteString sOldL = pResData->sId;
+ ByteString sGID = pResData->sGId;
+ ByteString sLID;
+ if ( !sGID.Len())
+ sGID = pResData->sId;
+ else
+ sLID = pResData->sId;
+ pResData->sGId = sGID;
+ pResData->sId = sLID;
+
+ ByteString sKey = CreateKey( pResData->sResTyp , pResData->sGId , pResData->sId , pResData->sFilename , bCaseSensitive );
+
+ //printf("DBG: Searching [%s]\n",sKey.GetBuffer());
+ if( aMap.find( sKey ) != aMap.end() ){
+ pResData->sGId = sOldG;
+ pResData->sId = sOldL;
+ //printf("DBG: Found[%s]\n",sKey.GetBuffer());
+ return aMap[ sKey ];
+ }
+ pResData->sGId = sOldG;
+ pResData->sId = sOldL;
+ //printf("DBG: Found[%s]\n",sKey.GetBuffer());
+ return NULL;
+}
+
+
+/*****************************************************************************/
+PFormEntrys *MergeDataFile::GetPFormEntrys( ResData *pResData )
+/*****************************************************************************/
+{
+ // search for requested PFormEntrys
+ MergeData *pData = GetMergeData( pResData );
+ if ( pData )
+ return pData->GetPFormEntrys( pResData );
+ return NULL;
+}
+
+/*****************************************************************************/
+PFormEntrys *MergeDataFile::GetPFormEntrysCaseSensitive( ResData *pResData )
+/*****************************************************************************/
+{
+ // search for requested PFormEntrys
+ MergeData *pData = GetMergeData( pResData , true );
+ if ( pData )
+ return pData->GetPFormEntrys( pResData );
+ return NULL;
+}
+/*****************************************************************************/
+void MergeDataFile::InsertEntry(
+ const ByteString &rTYP, const ByteString &rGID,
+ const ByteString &rLID, const ByteString &rPFO,
+ const ByteString &nLANG, const ByteString &rTEXT,
+ const ByteString &rQHTEXT, const ByteString &rTITLE ,
+ const ByteString &rInFilename , bool bCaseSensitive
+ )
+/*****************************************************************************/
+{
+ MergeData *pData;
+ BOOL bFound = FALSE;
+
+ // uniquify the filename to save memory.
+ ByteStringHashMap::const_iterator fit = aFilenames.find (rInFilename);
+ ByteString aFilename;
+ if (fit == aFilenames.end()) {
+ aFilename = rInFilename;
+ aFilenames.insert (ByteStringHashMap::value_type (aFilename, aFilename));
+ } else
+ aFilename = fit->first;
+
+ // search for MergeData
+
+ ByteString sKey = CreateKey( rTYP , rGID , rLID , aFilename , bCaseSensitive );
+ MergeDataHashMap::const_iterator mit;
+ mit = aMap.find( sKey );
+ if( mit != aMap.end() ){
+ pData = mit->second;
+ }else{
+ pData = new MergeData( rTYP, rGID, rLID, aFilename );
+ aMap.insert( MergeDataHashMap::value_type( sKey, pData ) );
+ }
+
+ bFound = FALSE;
+ PFormEntrys *pFEntrys = 0;
+
+ // search for PFormEntrys
+
+ pFEntrys = pData->GetPFObject( rPFO );
+ if( !pFEntrys ){
+ // create new PFormEntrys, cause no one exists with current properties
+ pFEntrys = new PFormEntrys( rPFO );
+ pData->Insert( rPFO , pFEntrys );
+ }
+
+ // finaly insert the cur string
+
+ pFEntrys->InsertEntry( nLANG , rTEXT, rQHTEXT, rTITLE );
+
+ //printf("DBG: MergeDataFile::Insert[]=( sKey=%s,nLang=%s,rTEXT=%s)\n",sKey2.GetBuffer(),nLANG.GetBuffer(),rTEXT.GetBuffer());
+}
+ByteString MergeDataFile::CreateKey( const ByteString& rTYP , const ByteString& rGID , const ByteString& rLID , const ByteString& rFilename , bool bCaseSensitive ){
+
+ ByteString sKey( rTYP );
+ sKey.Append( '-' );
+ sKey.Append( rGID );
+ sKey.Append( '-' );
+ sKey.Append( rLID );
+ sKey.Append( '-' );
+ sKey.Append( rFilename );
+
+ if( bCaseSensitive ) return sKey; // officecfg case sensitive identifier
+ else return sKey.ToUpperAscii();
+}
+
+
diff --git a/l10ntools/source/src_yy_wrapper.c b/l10ntools/source/src_yy_wrapper.c
new file mode 100644
index 000000000000..d326b9a94e86
--- /dev/null
+++ b/l10ntools/source/src_yy_wrapper.c
@@ -0,0 +1,2 @@
+// Helper to suppress warnings in lex generated c code, see #i57362#
+#include "src_yy.c"
diff --git a/l10ntools/source/srciter.cxx b/l10ntools/source/srciter.cxx
new file mode 100644
index 000000000000..cf04de4bf3fa
--- /dev/null
+++ b/l10ntools/source/srciter.cxx
@@ -0,0 +1,141 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: srciter.cxx,v $
+ * $Revision: 1.14 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+
+#include "srciter.hxx"
+#include <stdio.h>
+#include <tools/fsys.hxx>
+
+//
+// class SourceTreeIterator
+//
+
+/*****************************************************************************/
+SourceTreeIterator::SourceTreeIterator(
+ const ByteString &rRootDirectory, const ByteString &rVersion , bool bLocal_in )
+/*****************************************************************************/
+ : bInExecute( FALSE ) , bLocal( bLocal_in )
+{
+ (void) rVersion ;
+
+ if(!bLocal){
+ rtl::OUString sRootDirectory( rRootDirectory.GetBuffer() , rRootDirectory.Len() , RTL_TEXTENCODING_UTF8 );
+ aRootDirectory = transex::Directory( sRootDirectory );
+ }
+}
+
+/*****************************************************************************/
+SourceTreeIterator::~SourceTreeIterator()
+/*****************************************************************************/
+{
+}
+
+/*****************************************************************************/
+void SourceTreeIterator::ExecuteDirectory( transex::Directory& aDirectory )
+/*****************************************************************************/
+{
+ if ( bInExecute ) {
+ rtl::OUString sDirName = aDirectory.getDirectoryName();
+
+ static rtl::OUString WCARD1 ( rtl::OUString::createFromAscii( "unxlng" ) );
+ static rtl::OUString WCARD2 ( rtl::OUString::createFromAscii( "unxsol" ) );
+ static rtl::OUString WCARD3 ( rtl::OUString::createFromAscii( "wntmsc" ) );
+ static rtl::OUString WCARD4 ( rtl::OUString::createFromAscii( "common" ) );
+ static rtl::OUString WCARD5 ( rtl::OUString::createFromAscii( "unxmac" ) );
+ static rtl::OUString WCARD6 ( rtl::OUString::createFromAscii( "unxubt" ) );
+ static rtl::OUString WCARD7 ( rtl::OUString::createFromAscii( ".svn" ) );
+
+
+ if( sDirName.indexOf( WCARD1 , 0 ) > -1 ||
+ sDirName.indexOf( WCARD2 , 0 ) > -1 ||
+ sDirName.indexOf( WCARD3 , 0 ) > -1 ||
+ sDirName.indexOf( WCARD4 , 0 ) > -1 ||
+ sDirName.indexOf( WCARD5 , 0 ) > -1 ||
+ sDirName.indexOf( WCARD6 , 0 ) > -1 ||
+ sDirName.indexOf( WCARD7 , 0 ) > -1
+ ) return;
+ //printf("**** %s \n", OUStringToOString( sDirName , RTL_TEXTENCODING_UTF8 , sDirName.getLength() ).getStr() );
+
+ rtl::OUString sDirNameTmp = aDirectory.getFullName();
+ ByteString sDirNameTmpB( rtl::OUStringToOString( sDirNameTmp , RTL_TEXTENCODING_UTF8 , sDirName.getLength() ).getStr() );
+
+#ifdef WNT
+ sDirNameTmpB.Append( ByteString("\\no_localization") );
+#else
+ sDirNameTmpB.Append( ByteString("/no_localization") );
+#endif
+ //printf("**** %s \n", OUStringToOString( sDirNameTmp , RTL_TEXTENCODING_UTF8 , sDirName.getLength() ).getStr() );
+
+ DirEntry aDE( sDirNameTmpB.GetBuffer() );
+ if( aDE.Exists() )
+ {
+ //printf("#### no_localization file found ... skipping");
+ return;
+ }
+
+ aDirectory.setSkipLinks( bSkipLinks );
+ aDirectory.readDirectory();
+ OnExecuteDirectory( aDirectory.getFullName() );
+ if ( aDirectory.getSubDirectories().size() )
+ for ( ULONG i=0;i < aDirectory.getSubDirectories().size();i++ )
+ ExecuteDirectory( aDirectory.getSubDirectories()[ i ] );
+ }
+}
+
+/*****************************************************************************/
+BOOL SourceTreeIterator::StartExecute()
+/*****************************************************************************/
+{
+
+ bInExecute = TRUE; // FIXME
+ ExecuteDirectory( aRootDirectory );
+
+ if ( bInExecute ) { // FIXME
+ bInExecute = FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*****************************************************************************/
+void SourceTreeIterator::EndExecute()
+/*****************************************************************************/
+{
+ bInExecute = FALSE;
+}
+
+/*****************************************************************************/
+void SourceTreeIterator::OnExecuteDirectory( const rtl::OUString &rDirectory )
+/*****************************************************************************/
+{
+ fprintf( stdout, "%s\n", rtl::OUStringToOString( rDirectory, RTL_TEXTENCODING_UTF8, rDirectory.getLength() ).getStr() );
+}
diff --git a/l10ntools/source/srclex.l b/l10ntools/source/srclex.l
new file mode 100644
index 000000000000..fef251e47224
--- /dev/null
+++ b/l10ntools/source/srclex.l
@@ -0,0 +1,308 @@
+
+%{
+/*
+ * lexer for parsing ressource source files (*.src)
+ *
+ */
+
+
+/* enlarge token buffer to tokenize whole strings */
+#undef YYLMAX
+#define YYLMAX 64000
+
+/* to enable debug output define LEXDEBUG */
+#define LEXDEBUG 1
+#ifdef LEXDEBUG
+#define OUTPUT fprintf
+#else
+#define OUTPUT(Par1,Par2);
+#endif
+
+/* table of possible token ids */
+#include "tokens.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined __GNUC__
+#pragma GCC system_header
+#elif defined __SINPRO_CC
+#pragma disable_warn
+#elif defined _MSC_VER
+#pragma warning(push, 1)
+#endif
+
+/* external functions (C++ code, declared as extren "C" */
+extern int WorkOnTokenSet( int, char* );
+extern int InitExport( char * , char * );
+extern int Parse( int nTyp, char *pTokenText );
+extern int EndExport();
+extern int SetError();
+extern int GetError();
+extern char *GetOutputFile( int argc, char* argv[]);
+extern FILE *GetNextFile();
+extern int isQuiet();
+extern void Close();
+extern char* getFilename();
+
+/* forwards */
+void YYWarning();
+%}
+
+%p 24000
+%e 1200
+%n 500
+
+%%
+
+^[\t ]*"#pragma".* {
+ WorkOnTokenSet( PRAGMA, yytext );
+}
+
+^[ \t]*\n {
+ WorkOnTokenSet( EMPTYLINE, yytext );
+}
+
+[\t ]+ |
+^[\t ]*"#include".* |
+^[\t ]*"#undef".* |
+"//".* |
+";" |
+"<" |
+">" |
+\n {
+ WorkOnTokenSet( IGNOREDTOKENS, yytext );
+}
+"/*" {
+ char c1 = 0, c2 = input();
+ char pChar[2];
+ pChar[1] = 0x00;
+ pChar[0] = c2;
+
+ WorkOnTokenSet( COMMEND, yytext );
+ WorkOnTokenSet( COMMEND, pChar );
+ for(;;) {
+ if ( c2 == EOF )
+ break;
+ if ( c1 == '*' && c2 == '/' )
+ break;
+ c1 = c2;
+ c2 = input();
+ pChar[0] = c2;
+ WorkOnTokenSet( COMMEND, pChar );
+ }
+}
+
+^[\t ]*"#ifndef".+$ |
+^[\t ]*"#ifdef".+$ |
+^[\t ]*"#if".+$ |
+^[\t ]*"#elif".*$ |
+^[\t ]*"#else".*$ |
+^[\t ]*"#endif".*$ {
+ WorkOnTokenSet( CONDITION, yytext );
+}
+
+[a-zA-Z]+[\t ]+[^={\n]+[\t ] {
+/* defined Res */
+ WorkOnTokenSet( DEFINEDRES, yytext );
+}
+
+[a-zA-Z]+[ \t]+[^={;\n]+\n[ \t]*"#".*\n[ \t]*"{" |
+[a-zA-Z]+[ \t]+[^={;\n]+\n?([ \t]*"//".*\n)*[ \t]*"{" {
+/* RESSOURCE // String TTT_XX ... */
+ WorkOnTokenSet( RESSOURCE, yytext );
+}
+
+^[\t ]*[a-zA-Z_]+[\t ]*"\\"?[\t ]*\n?[ \t]*"{"[\t ]*"\\"? {
+/* SMALRESSOURCE // String ... */
+ WorkOnTokenSet( SMALRESSOURCE, yytext );
+}
+
+[\t ]*[a-zA-Z0-9_]+[ \t]*("["[ \t]*[a-zA-Z0-9_\-]+[ \t]*"]"[ \t]*)?=[ \t]*L?\".*\".*\n? {
+/* TEXTLINE // TextTyp = "A Text" */
+ WorkOnTokenSet( TEXTLINE, yytext );
+}
+
+[\t ]*[a-zA-Z0-9_]+[ \t]*("["[ \t]*[a-zA-Z0-9_\-]+[ \t]*"]"[ \t]*)?(\n[ \t]*)?=([ \t]*\n)?(([a-zA-Z0-9_]+)|(\".*\")|([ \t\n]*))*\".*\"(([a-zA-Z0-9_]+)|(\".*\")|([ \t\n]*))*; {
+/* LONGTEXTLINE // TextTyp = "A Text" HHH_XXX "A Text" ZZZ_TTT ... */
+ WorkOnTokenSet( LONGTEXTLINE, yytext );
+}
+
+\".*\" {
+/* TEXT // "A Text" */
+ WorkOnTokenSet( TEXT, yytext );
+}
+
+"{"[ \t]*\\? {
+/* LEVELUP */
+ WorkOnTokenSet( LEVELUP, yytext );
+}
+
+"}"[ \t]*;([ \t]*\\)? {
+/* LEVELDOWN */
+ WorkOnTokenSet( LEVELDOWN, yytext );
+}
+
+[a-zA-Z0-9_]+[ \t]*"="[ \t]*"MAP_APPFONT"[ \t]*"(".+")".* {
+/* APPFONTMAPPING Typ = MAP_APPFONT( ... ) */
+ WorkOnTokenSet( APPFONTMAPPING, yytext );
+}
+
+[ \t]*[a-zA-Z0-9_]+[ \t]*=[ \t]*[0123456789]{1,5}[ \t]*";"?\\? {
+/* TEXTREFID // TextTyp = 12345 */
+ WorkOnTokenSet( TEXTREFID, yytext );
+}
+
+[a-zA-Z0-9_]+[ \t]*"="[\t ]*([ \t]*"//".*\n)*.* |
+[a-zA-Z0-9_]+[ \t]*"=".* {
+/* ASSIGNMENT Typ = ... */
+ WorkOnTokenSet( ASSIGNMENT, yytext );
+}
+
+
+
+[a-zA-Z0-9_]+[ \t]*("["[ \t]*[a-zA-Z0-9_\-]+[ \t]*"]"[ \t]*)?"="[ \t]*(\\[ \t]*)?\n?[ \t]*"{"[ \t]*(\\[ \t]*)?\n?[ \t]*"<" {
+/* LISTASSIGNMENT Typ [ ... ] = ... */
+ WorkOnTokenSet( LISTASSIGNMENT, yytext );
+}
+
+"StringList"+[ \t]*("["[ \t]*[a-zA-Z0-9_\-]+[ \t]*"]"[ \t]*)?"="[ \t]*(\\[ \t]*)?\n?[ \t]*"{"[ \t]*(\\[ \t]*)?\n?[ \t]* {
+/* LISTASSIGNMENT Typ [ ... ] = ... */
+ WorkOnTokenSet( LISTASSIGNMENT, yytext );
+}
+
+"UIEntries"[ \t]*("["[ \t]*[a-zA-Z0-9_\-]+[ \t]*"]"[ \t]*)?"="[ \t]*(\\[ \t]*)?\n?[ \t]*"{" {
+/* UIENTRIES */
+ WorkOnTokenSet( UIENTRIES, yytext );
+}
+
+"<"?[ \t]*L?\".*\".*">" {
+/* LISTTEXT */
+ WorkOnTokenSet( LISTTEXT, yytext );
+}
+
+[ \t]*"#define"[ \t]+[a-zA-Z0-9_]+.*"\\" {
+/* RSCDEFINE #define ... */
+ WorkOnTokenSet( RSCDEFINE, yytext );
+}
+
+[ \t]*"#define"[ \t]+[a-zA-Z0-9_]+.+ {
+/* #define ... */
+ WorkOnTokenSet( NORMDEFINE, yytext );
+}
+
+"\\" {
+/* RSCDEFINELEND */
+ WorkOnTokenSet( RSCDEFINELEND, yytext );
+}
+
+[a-zA-Z0-9_]+[ \t]*; {
+/* allowed other tokens like "49 ;" or "SFX_... ;" */
+ WorkOnTokenSet( ANYTOKEN, yytext );
+}
+
+. {
+ WorkOnTokenSet( UNKNOWNCHAR, yytext );
+/* YYWarning( "Unknown Char" ); */
+}
+
+"{"?[ \t]*\".*\"[ \t]*";"[ \t]*"}" {
+/* _LISTTEXT */
+ WorkOnTokenSet( _LISTTEXT, yytext );
+}
+
+%%
+
+/*****************************************************************************/
+int yywrap(void)
+/*****************************************************************************/
+{
+ FILE *pFile;
+ pFile = GetNextFile();
+ if ( pFile ) {
+ yyin = pFile;
+ yylineno = 0;
+ return 0;
+ }
+
+ /* end of input reached */
+ return 1;
+}
+
+/*****************************************************************************/
+void YYWarning( char *s )
+/*****************************************************************************/
+{
+ /* write warning to stderr */
+ fprintf( stderr, "Warning: \"%s\" in line %d: \"%s\"\n", s, yylineno, yytext );
+}
+
+/*****************************************************************************/
+void yyerror( char *s )
+/*****************************************************************************/
+{
+ /* write error to stderr */
+ fprintf( stderr, "Error: \"%s\" in line %d: \"%s\"\n", s, yylineno, yytext );
+ SetError();
+}
+
+/*****************************************************************************/
+int
+#ifdef WNT
+_cdecl
+#endif
+main( int argc, char* argv[])
+/*****************************************************************************/
+{
+ /* error level */
+ int nRetValue = 0;
+ char *pOutput;
+ FILE *pFile;
+
+ pOutput = GetOutputFile( argc, argv );
+ if( !isQuiet() ){
+ fprintf( stdout, "\nTransEx 3.1 Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.\n" );
+ fprintf( stdout, "========================================================================\n" );
+ }
+
+ if ( !pOutput ) {
+ fprintf( stdout, "Syntax:TRANSEX[-p Prj][-r PrjRoot]-i FileIn...[-o FileOut][-m DataBase][-e][-b][-u][-L l1,l2,...]\n" );
+ fprintf( stdout, " Prj: Project\n" );
+ fprintf( stdout, " PrjRoot: Path to project root (..\\.. etc.)\n" );
+ fprintf( stdout, " FileIn: Source files (*.src)\n" );
+ fprintf( stdout, " FileOut: Destination file (*.*)\n" );
+ fprintf( stdout, " DataBase: Mergedata (*.sdf)\n" );
+ fprintf( stdout, " -QQ: quiet output\n" );
+ fprintf( stdout, " -e: Disable writing errorlog\n" );
+ fprintf( stdout, " -b: Break when Token \"HelpText\" found in source\n" );
+ fprintf( stdout, " -u: [english] and [german] are allowed, Id is Taken from DataBase \n" );
+ fprintf( stdout, " -NOUTF8: disable UTF8 as language independent encoding\n" );
+ fprintf( stdout, " -L: Restrict the handled languages. l1,l2,... are elements of (de,en-US...)\n" );
+ fprintf( stdout, " A fallback language can be defined like this: l1=f1.\n" );
+ fprintf( stdout, " f1, f2,... are also elements of (de,en-US...)\n" );
+ fprintf( stdout, " Example: -L de,es=en-US\n" );
+ fprintf( stdout, " Restriction to de and es, en-US will be fallback for es\n" );
+ return 1;
+ }
+
+ InitExport( pOutput , getFilename() );
+ pFile = GetNextFile();
+ if ( !pFile )
+ return 1;
+
+ yyin = pFile;
+
+ /* create global instance of class Export */
+
+ /* start parser */
+ yylex();
+ Close();
+
+ /* get error info. and end export */
+ nRetValue = GetError();
+ EndExport();
+
+ if( !isQuiet() ) fprintf( stdout, "\n===================================\n\n" );
+
+ /* return error level */
+ return nRetValue;
+}
diff --git a/l10ntools/source/tagtest.cxx b/l10ntools/source/tagtest.cxx
new file mode 100644
index 000000000000..7896915ede0c
--- /dev/null
+++ b/l10ntools/source/tagtest.cxx
@@ -0,0 +1,1577 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: tagtest.cxx,v $
+ * $Revision: 1.20 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <tools/string.hxx>
+#include "tagtest.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+#include "gsicheck.hxx"
+
+#define HAS_FLAG( nFlags, nFlag ) ( ( nFlags & nFlag ) != 0 )
+#define SET_FLAG( nFlags, nFlag ) ( nFlags |= nFlag )
+#define RESET_FLAG( nFlags, nFlag ) ( nFlags &= ~nFlag ) // ~ = Bitweises NOT
+
+
+
+TokenInfo::TokenInfo( TokenId pnId, USHORT nP, String paStr, ParserMessageList &rErrorList )
+: bClosed(FALSE)
+, bCloseTag(FALSE)
+, bIsBroken(FALSE)
+, bHasBeenFixed(FALSE)
+, bDone(FALSE)
+, aTokenString( paStr )
+, nId( pnId )
+, nPos(nP)
+{
+ if ( nId == TAG_COMMONSTART || nId == TAG_COMMONEND )
+ SplitTag( rErrorList );
+}
+
+enum tagcheck { TC_START, TC_HAS_TAG_NAME, TC_HAS_PROP_NAME_EQ, TC_HAS_PROP_NAME_EQ_SP, TC_HAS_PROP_NAME_SP, TC_INSIDE_STRING, TC_PROP_FINISHED, TC_CLOSED, TC_CLOSED_SPACE, TC_CLOSETAG, TC_CLOSETAG_HAS_TAG_NAME, TC_FINISHED, TC_ERROR };
+
+/*
+ \< link href = \"text\" name = \"C\" \>
+START ' ' -> HAS_TAG_NAME
+START '/' -> CLOSED
+START '/' -> CLOSETAG - no Portion (starting with /)
+START '>' -> FINISHED
+HAS_TAG_NAME '=' -> HAS_PROP_NAME_EQ
+HAS_TAG_NAME ' ' -> HAS_PROP_NAME_SP
+HAS_TAG_NAME '/' -> CLOSED
+HAS_TAG_NAME '>' -> FINISHED
+HAS_PROP_NAME_SP '=' -> HAS_PROP_NAME_EQ
+HAS_PROP_NAME_EQ ' ' -> HAS_PROP_NAME_EQ_SP
+HAS_PROP_NAME_EQ '"' -> INSIDE_STRING
+HAS_PROP_NAME_EQ_SP '"' -> INSIDE_STRING
+INSIDE_STRING ' ' -> INSIDE_STRING
+INSIDE_STRING '=' -> INSIDE_STRING
+INSIDE_STRING '>' -> INSIDE_STRING
+INSIDE_STRING '"' -> PROP_FINISHED
+PROP_FINISHED ' ' -> HAS_TAG_NAME
+PROP_FINISHED '/' -> CLOSED
+PROP_FINISHED '>' -> FINISHED
+CLOSED ' ' -> CLOSED_SPACE
+CLOSED '>' -> FINISHED
+CLOSED_SPACE '>' -> FINISHED
+
+CLOSETAG ' ' -> CLOSETAG_HAS_TAG_NAME
+CLOSETAG '>' -> FINISHED
+CLOSETAG_HAS_TAG_NAME '>' -> FINISHED
+
+*/
+void TokenInfo::SplitTag( ParserMessageList &rErrorList )
+{
+ USHORT nLastPos = 2; // skip initial \<
+ USHORT nCheckPos = nLastPos;
+ String aDelims( String::CreateFromAscii( " \\=>/" ) );
+ String aPortion;
+ String aValue; // store the value of a property
+ ByteString aName; // store the name of a property/tag
+ BOOL bCheckName = FALSE;
+ BOOL bCheckEmpty = FALSE;
+ sal_Unicode cDelim;
+ tagcheck aState = TC_START;
+
+ // skip blanks
+ while ( nLastPos < aTokenString.Len() && aTokenString.GetChar( nLastPos ) == ' ')
+ nLastPos++;
+
+ nCheckPos = aTokenString.SearchChar( aDelims.GetBuffer(), nLastPos );
+ while ( nCheckPos != STRING_NOTFOUND && !( aState == TC_FINISHED || aState == TC_ERROR ) )
+ {
+ aPortion = aTokenString.Copy( nLastPos, nCheckPos-nLastPos );
+
+ if ( aTokenString.GetChar( nCheckPos ) == '\\' )
+ nCheckPos++;
+
+ cDelim = aTokenString.GetChar( nCheckPos );
+ nCheckPos++;
+
+ switch ( aState )
+ {
+// START ' ' -> HAS_TAG_NAME
+// START '/' -> CLOSED
+// START '>' -> FINISHED
+ case TC_START:
+ aTagName = aPortion;
+ switch ( cDelim )
+ {
+ case ' ': aState = TC_HAS_TAG_NAME;
+ bCheckName = TRUE;
+ break;
+ case '/':
+ {
+ if ( aPortion.Len() == 0 )
+ {
+ aState = TC_CLOSETAG;
+ }
+ else
+ {
+ aState = TC_CLOSED;
+ bCheckName = TRUE;
+ }
+ }
+ break;
+ case '>': aState = TC_FINISHED;
+ bCheckName = TRUE;
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+// HAS_TAG_NAME '=' -> HAS_PROP_NAME_EQ
+// HAS_TAG_NAME ' ' -> HAS_PROP_NAME_SP
+// HAS_TAG_NAME '/' -> CLOSED
+// HAS_TAG_NAME '>' -> FINISHED
+ case TC_HAS_TAG_NAME:
+ switch ( cDelim )
+ {
+ case '=': aState = TC_HAS_PROP_NAME_EQ;
+ bCheckName = TRUE;
+ break;
+ case ' ': aState = TC_HAS_PROP_NAME_SP;
+ bCheckName = TRUE;
+ break;
+ case '/': aState = TC_CLOSED;
+ bCheckEmpty = TRUE;
+ break;
+ case '>': aState = TC_FINISHED;
+ bCheckEmpty = TRUE;
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+// HAS_PROP_NAME_SP '=' -> HAS_PROP_NAME_EQ
+ case TC_HAS_PROP_NAME_SP:
+ switch ( cDelim )
+ {
+ case '=': aState = TC_HAS_PROP_NAME_EQ;
+ bCheckEmpty = TRUE;
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+// HAS_PROP_NAME_EQ ' ' -> HAS_PROP_NAME_EQ_SP
+// HAS_PROP_NAME_EQ '"' -> INSIDE_STRING
+ case TC_HAS_PROP_NAME_EQ:
+ switch ( cDelim )
+ {
+ case ' ': aState = TC_HAS_PROP_NAME_EQ_SP;
+ bCheckEmpty = TRUE;
+ break;
+ case '\"': aState = TC_INSIDE_STRING;
+ bCheckEmpty = TRUE;
+ aValue.Erase();
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+// HAS_PROP_NAME_EQ_SP '"' -> INSIDE_STRING
+ case TC_HAS_PROP_NAME_EQ_SP:
+ switch ( cDelim )
+ {
+ case '\"': aState = TC_INSIDE_STRING;
+ bCheckEmpty = TRUE;
+ aValue.Erase();
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+// INSIDE_STRING * -> INSIDE_STRING
+// INSIDE_STRING '"' -> PROP_FINISHED
+ case TC_INSIDE_STRING:
+ switch ( cDelim )
+ {
+ case '\"':
+ {
+ aState = TC_PROP_FINISHED;
+ aValue += aPortion;
+ if ( aProperties.find( aName ) == aProperties.end() )
+ {
+ if ( !IsPropertyValueValid( aName, aValue ) )
+ {
+ rErrorList.AddError( 25, ByteString("Property '").Append(aName).Append("' has invalid value '").Append(ByteString( aValue, RTL_TEXTENCODING_UTF8 )).Append("' "), *this );
+ bIsBroken = TRUE;
+ }
+ aProperties[ aName ] = aValue;
+ }
+ else
+ {
+ rErrorList.AddError( 25, ByteString("Property '").Append(aName).Append("' defined twice "), *this );
+ bIsBroken = TRUE;
+ }
+ }
+ break;
+ default:
+ {
+ aState = TC_INSIDE_STRING;
+ aValue += aPortion;
+ aValue += cDelim;
+ }
+ }
+ break;
+
+// PROP_FINISHED ' ' -> HAS_TAG_NAME
+// PROP_FINISHED '/' -> CLOSED
+// PROP_FINISHED '>' -> FINISHED
+ case TC_PROP_FINISHED:
+ switch ( cDelim )
+ {
+ case ' ': aState = TC_HAS_TAG_NAME;
+ bCheckEmpty = TRUE;
+ break;
+ case '/': aState = TC_CLOSED;
+ bCheckEmpty = TRUE;
+ break;
+ case '>': aState = TC_FINISHED;
+ bCheckEmpty = TRUE;
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+// CLOSED ' ' -> CLOSED_SPACE
+// CLOSED '>' -> FINISHED
+ case TC_CLOSED:
+ switch ( cDelim )
+ {
+ case ' ': aState = TC_CLOSED_SPACE;
+ bCheckEmpty = TRUE;
+ bClosed = TRUE;
+ break;
+ case '>': aState = TC_FINISHED;
+ bCheckEmpty = TRUE;
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+// CLOSED_SPACE '>' -> FINISHED
+ case TC_CLOSED_SPACE:
+ switch ( cDelim )
+ {
+ case '>': aState = TC_FINISHED;
+ bCheckEmpty = TRUE;
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+// CLOSETAG ' ' -> CLOSETAG_HAS_TAG_NAME
+// CLOSETAG '>' -> FINISHED
+ case TC_CLOSETAG:
+ bCloseTag = TRUE;
+ switch ( cDelim )
+ {
+ case ' ': aState = TC_CLOSETAG_HAS_TAG_NAME;
+ aTagName = aPortion;
+ bCheckName = TRUE;
+ break;
+ case '>': aState = TC_FINISHED;
+ aTagName = aPortion;
+ bCheckName = TRUE;
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+// CLOSETAG_HAS_TAG_NAME '>' -> FINISHED
+ case TC_CLOSETAG_HAS_TAG_NAME:
+ switch ( cDelim )
+ {
+ case '>': aState = TC_FINISHED;
+ bCheckEmpty = TRUE;
+ break;
+ default: aState = TC_ERROR;
+ }
+ break;
+
+
+ default: rErrorList.AddError( 99, "Internal error Parsing Tag ", *this );
+ bIsBroken = TRUE;
+
+ }
+
+ if ( bCheckName )
+ {
+ if ( aPortion.Len() == 0 )
+ {
+ rErrorList.AddError( 25, "Tag/Property name missing ", *this );
+ bIsBroken = TRUE;
+ }
+ else
+ {
+ aName = ByteString( aPortion, RTL_TEXTENCODING_UTF8 );
+ // "a-zA-Z_-.0-9"
+ xub_StrLen nCount;
+ BOOL bBroken = FALSE;
+ const sal_Char* aBuf = aName.GetBuffer();
+ for ( nCount = 0 ; !bBroken && nCount < aName.Len() ; nCount++ )
+ {
+ bBroken = ! ( ( aBuf[nCount] >= 'a' && aBuf[nCount] <= 'z' )
+ ||( aBuf[nCount] >= 'A' && aBuf[nCount] <= 'Z' )
+ ||( aBuf[nCount] >= '0' && aBuf[nCount] <= '9' )
+ ||( aBuf[nCount] == '_' )
+ ||( aBuf[nCount] == '-' )
+ ||( aBuf[nCount] == '.' )
+ );
+ }
+
+ if ( bBroken )
+ {
+ rErrorList.AddError( 25, "Found illegal character in Tag/Property name ", *this );
+ bIsBroken = TRUE;
+ }
+ }
+
+ bCheckName = FALSE;
+ }
+
+ if ( bCheckEmpty )
+ {
+ if ( aPortion.Len() )
+ {
+ rErrorList.AddError( 25, ByteString("Found displaced characters '").Append(ByteString( aPortion, RTL_TEXTENCODING_UTF8 )).Append("' in Tag "), *this );
+ bIsBroken = TRUE;
+ }
+ bCheckEmpty = FALSE;
+ }
+
+
+ nLastPos = nCheckPos;
+
+ // skip further blanks
+ if ( cDelim == ' ' && aState != TC_INSIDE_STRING )
+ while ( nLastPos < aTokenString.Len() && aTokenString.GetChar( nLastPos ) == ' ')
+ nLastPos++;
+
+ nCheckPos = aTokenString.SearchChar( aDelims.GetBuffer(), nLastPos );
+ }
+ if ( aState != TC_FINISHED )
+ {
+ rErrorList.AddError( 25, "Parsing error in Tag ", *this );
+ bIsBroken = TRUE;
+ }
+}
+
+BOOL TokenInfo::IsPropertyRelevant( const ByteString &aName, const String &aValue ) const
+{
+ if ( aTagName.EqualsAscii( "alt" ) && aName.Equals( "xml-lang" ) )
+ return FALSE;
+ if ( aTagName.EqualsAscii( "ahelp" ) && aName.Equals( "visibility" ) && aValue.EqualsAscii("visible") )
+ return FALSE;
+ if ( aTagName.EqualsAscii( "image" ) && (aName.Equals( "width" ) || aName.Equals( "height" )) )
+ return FALSE;
+
+ return TRUE;
+}
+
+BOOL TokenInfo::IsPropertyValueValid( const ByteString &aName, const String &aValue ) const
+{
+/* removed due to i56740
+ if ( aTagName.EqualsAscii( "switchinline" ) && aName.Equals( "select" ) )
+ {
+ return aValue.EqualsAscii("sys") ||
+ aValue.EqualsAscii("appl") ||
+ aValue.EqualsAscii("distrib");
+ } */
+ if ( aTagName.EqualsAscii( "caseinline" ) && aName.Equals( "select" ) )
+ {
+ return /*!aValue.EqualsAscii("OS2") && removed due to i56740 */
+ !aValue.EqualsAscii("");
+ }
+
+ // we don't know any better so we assume it to be OK
+ return TRUE;
+}
+
+BOOL TokenInfo::IsPropertyInvariant( const ByteString &aName, const String &aValue ) const
+{
+ if ( aTagName.EqualsAscii( "link" ) && aName.Equals( "name" ) )
+ return FALSE;
+ if ( aTagName.EqualsAscii( "link" ) && aName.Equals( "href" ) )
+ { // check for external reference
+ if ( aValue.Copy( 0, 5 ).EqualsIgnoreCaseAscii( "http:" )
+ || aValue.Copy( 0, 6 ).EqualsIgnoreCaseAscii( "https:" )
+ || aValue.Copy( 0, 4 ).EqualsIgnoreCaseAscii( "ftp:" ) )
+ return FALSE;
+ else
+ return TRUE;
+ }
+ return TRUE;
+}
+
+BOOL TokenInfo::IsPropertyFixable( const ByteString &aName ) const
+{
+ // name everything that is allowed to be fixed automatically here
+ if ( (aTagName.EqualsAscii( "ahelp" ) && aName.Equals( "hid" ))
+ || (aTagName.EqualsAscii( "link" ) && aName.Equals( "href" ))
+ || (aTagName.EqualsAscii( "alt" ) && aName.Equals( "id" ))
+ || (aTagName.EqualsAscii( "variable" ) && aName.Equals( "id" ))
+ || (aTagName.EqualsAscii( "image" ) && aName.Equals( "src" ))
+ || (aTagName.EqualsAscii( "image" ) && aName.Equals( "id" ) ))
+ return TRUE;
+ return FALSE;
+}
+
+BOOL TokenInfo::MatchesTranslation( TokenInfo& rInfo, BOOL bGenErrors, ParserMessageList &rErrorList, BOOL bFixTags ) const
+{
+ // check if tags are equal
+ // check if all existing properties are in the translation as well and
+ // wether they have a matching content (the same in most cases)
+
+ if ( nId != rInfo.nId )
+ return FALSE;
+
+ if ( !aTagName.Equals( rInfo.aTagName ) )
+ return FALSE;
+
+ // If one of the tags has formating errors already it does make no sense to check here, so return right away
+ if ( bGenErrors && ( bIsBroken || rInfo.bIsBroken ) )
+ return TRUE;
+
+ StringHashMap::const_iterator iProp;
+ for( iProp = aProperties.begin() ; iProp != aProperties.end(); ++iProp )
+ {
+ if ( rInfo.aProperties.find( iProp->first ) != rInfo.aProperties.end() )
+ {
+ if ( IsPropertyRelevant( iProp->first, iProp->second ) || IsPropertyRelevant( iProp->first, rInfo.aProperties.find( iProp->first )->second ) )
+ {
+ if ( IsPropertyInvariant( iProp->first, iProp->second ) )
+ {
+ if ( !rInfo.aProperties.find( iProp->first )->second.Equals( iProp->second ) )
+ {
+ if ( bGenErrors )
+ {
+ if ( bFixTags && IsPropertyFixable( iProp->first ) )
+ {
+ rInfo.aProperties.find( iProp->first )->second = iProp->second;
+ rInfo.SetHasBeenFixed();
+ rErrorList.AddWarning( 25, ByteString("Property '").Append(iProp->first).Append("': FIXED different value in Translation "), *this );
+ }
+ else
+ rErrorList.AddError( 25, ByteString("Property '").Append(iProp->first).Append("': value different in Translation "), *this );
+ }
+ else return FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( IsPropertyRelevant( iProp->first, iProp->second ) )
+ {
+ if ( bGenErrors )
+ rErrorList.AddError( 25, ByteString("Property '").Append(iProp->first).Append("' missing in Translation "), *this );
+ else return FALSE;
+ }
+ }
+ }
+ for( iProp = rInfo.aProperties.begin() ; iProp != rInfo.aProperties.end(); ++iProp )
+ {
+ if ( aProperties.find( iProp->first ) == aProperties.end() )
+ {
+ if ( IsPropertyRelevant( iProp->first, iProp->second ) )
+ {
+ if ( bGenErrors )
+ rErrorList.AddError( 25, ByteString("Extra Property '").Append(iProp->first).Append("' in Translation "), rInfo );
+ else return FALSE;
+ }
+ }
+ }
+
+ // if we reach here eather
+ // the tags match completely or
+ // the tags match but not the properties and we generated errors for that
+ return TRUE;
+}
+
+String TokenInfo::GetTagName() const
+{
+ return aTagName;
+}
+
+String TokenInfo::MakeTag() const
+{
+ String aRet;
+ aRet.AppendAscii("\\<");
+ if ( bCloseTag )
+ aRet.AppendAscii("/");
+ aRet.Append( GetTagName() );
+ StringHashMap::const_iterator iProp;
+
+ for( iProp = aProperties.begin() ; iProp != aProperties.end(); ++iProp )
+ {
+ aRet.AppendAscii(" ");
+ aRet.Append( String( iProp->first, RTL_TEXTENCODING_UTF8 ) );
+ aRet.AppendAscii("=\\\"");
+ aRet.Append( iProp->second );
+ aRet.AppendAscii("\\\"");
+ }
+ if ( bClosed )
+ aRet.AppendAscii("/");
+ aRet.AppendAscii("\\>");
+ return aRet;
+}
+
+
+void ParserMessageList::AddError( USHORT nErrorNr, ByteString aErrorText, const TokenInfo &rTag )
+{
+ Insert( new ParserError( nErrorNr, aErrorText, rTag ), LIST_APPEND );
+}
+
+void ParserMessageList::AddWarning( USHORT nErrorNr, ByteString aErrorText, const TokenInfo &rTag )
+{
+ Insert( new ParserWarning( nErrorNr, aErrorText, rTag ), LIST_APPEND );
+}
+
+BOOL ParserMessageList::HasErrors()
+{
+ USHORT i;
+ for ( i=0 ; i < Count() ; i++ )
+ if ( GetObject( i )->IsError() )
+ return TRUE;
+ return FALSE;
+}
+
+struct Tag
+{
+ String GetName() const { return String::CreateFromAscii( pName ); };
+ const char* pName;
+ TokenId nTag;
+};
+
+
+static const Tag aKnownTags[] =
+{
+/* commenting oldstyle tags
+// { "<#GROUP_FORMAT>", TAG_GROUP_FORMAT },
+ { "<#BOLD>", TAG_BOLDON },
+ { "<#/BOLD>", TAG_BOLDOFF },
+ { "<#ITALIC>", TAG_ITALICON },
+ { "<#/ITALIC>", TAG_ITALICOFF },
+ { "<#UNDER>", TAG_UNDERLINEON },
+ { "<#/UNDER>", TAG_UNDERLINEOFF },
+
+// { "<#GROUP_NOTALLOWED>", TAG_GROUP_NOTALLOWED },
+ { "<#HELPID>", TAG_HELPID },
+ { "<#MODIFY>", TAG_MODIFY },
+ { "<#REFNR>", TAG_REFNR },
+
+// { "<#GROUP_STRUCTURE>", TAG_GROUP_STRUCTURE },
+ { "<#NAME>", TAG_NAME },
+ { "<#HREF>", TAG_HREF },
+ { "<#AVIS>", TAG_AVIS },
+ { "<#AHID>", TAG_AHID },
+ { "<#AEND>", TAG_AEND },
+
+ { "<#TITEL>", TAG_TITEL },
+ { "<#KEY>", TAG_KEY },
+ { "<#INDEX>", TAG_INDEX },
+
+ { "<#REFSTART>", TAG_REFSTART },
+
+ { "<#GRAPHIC>", TAG_GRAPHIC },
+ { "<#NEXTVERSION>", TAG_NEXTVERSION },
+
+ // { "<#GROUP_SYSSWITCH>", TAG_GROUP_SYSSWITCH },
+ { "<#WIN>", TAG_WIN },
+ { "<#UNIX>", TAG_UNIX },
+ { "<#MAC>", TAG_MAC },
+ { "<#OS2>", TAG_OS2 },
+
+// { "<#GROUP_PROGSWITCH>", TAG_GROUP_PROGSWITCH },
+ { "<#WRITER>", TAG_WRITER },
+ { "<#CALC>", TAG_CALC },
+ { "<#DRAW>", TAG_DRAW },
+ { "<#IMPRESS>", TAG_IMPRESS },
+ { "<#SCHEDULE>", TAG_SCHEDULE },
+ { "<#IMAGE>", TAG_IMAGE },
+ { "<#MATH>", TAG_MATH },
+ { "<#CHART>", TAG_CHART },
+ { "<#OFFICE>", TAG_OFFICE },
+ */
+// { "<#TAG_GROUP_META>", TAG_GROUP_META },
+ { "$[officefullname]", TAG_OFFICEFULLNAME },
+ { "$[officename]", TAG_OFFICENAME },
+ { "$[officepath]", TAG_OFFICEPATH },
+ { "$[officeversion]", TAG_OFFICEVERSION },
+ { "$[portalname]", TAG_PORTALNAME },
+ { "$[portalfullname]", TAG_PORTALFULLNAME },
+ { "$[portalpath]", TAG_PORTALPATH },
+ { "$[portalversion]", TAG_PORTALVERSION },
+ { "$[portalshortname]", TAG_PORTALSHORTNAME },
+/* commenting oldstyle tags
+// { "<#TAG_GROUP_SINGLE>", TAG_GROUP_SINGLE },
+ { "<#REFINSERT>", TAG_REFINSERT },
+
+// { "<#GROUP_MULTI>", TAG_GROUP_MULTI },
+ { "<#END>", TAG_END },
+ { "<#ELSE>", TAG_ELSE },
+ { "<#VERSIONEND>", TAG_VERSIONEND },
+ { "<#ENDGRAPHIC>", TAG_ENDGRAPHIC },*/
+ { "<Common Tag>", TAG_COMMONSTART },
+ { "</Common Tag>", TAG_COMMONEND },
+
+ { "<no more tags>", TAG_NOMORETAGS },
+ { "", TAG_UNKNOWN_TAG },
+};
+
+
+SimpleParser::SimpleParser()
+: nPos( 0 )
+, aNextTag( TAG_NOMORETAGS, TOK_INVALIDPOS )
+{
+}
+
+void SimpleParser::Parse( String PaSource )
+{
+ aSource = PaSource;
+ nPos = 0;
+ aLastToken.Erase();
+ aNextTag = TokenInfo( TAG_NOMORETAGS, TOK_INVALIDPOS );
+ aTokenList.Clear();
+};
+
+TokenInfo SimpleParser::GetNextToken( ParserMessageList &rErrorList )
+{
+ TokenInfo aResult;
+ USHORT nTokenStartPos = 0;
+ if ( aNextTag.nId != TAG_NOMORETAGS )
+ {
+ aResult = aNextTag;
+ aNextTag = TokenInfo( TAG_NOMORETAGS, TOK_INVALIDPOS );
+ }
+ else
+ {
+ aLastToken = GetNextTokenString( rErrorList, nTokenStartPos );
+ if ( aLastToken.Len() == 0 )
+ return TokenInfo( TAG_NOMORETAGS, TOK_INVALIDPOS );
+
+ // do we have a \< ... \> style tag?
+ if ( aLastToken.Copy(0,2).EqualsAscii( "\\<" ) )
+ {
+ // check for paired \" \"
+ bool bEven = true;
+ USHORT nQuotePos = 0;
+ USHORT nQuotedQuotesPos = aLastToken.SearchAscii( "\\\"" );
+ USHORT nQuotedBackPos = aLastToken.SearchAscii( "\\\\" ); // this is only to kick out quoted backslashes
+ while ( nQuotedQuotesPos != STRING_NOTFOUND )
+ {
+ if ( nQuotedBackPos <= nQuotedQuotesPos )
+ nQuotePos = nQuotedBackPos+2;
+ else
+ {
+ nQuotePos = nQuotedQuotesPos+2;
+ bEven = !bEven;
+ }
+ nQuotedQuotesPos = aLastToken.SearchAscii( "\\\"", nQuotePos );
+ nQuotedBackPos = aLastToken.SearchAscii( "\\\\", nQuotePos ); // this is only to kick out quoted backslashes
+ }
+ if ( !bEven )
+ {
+ rErrorList.AddError( 24, "Missing quotes ( \\\" ) in Tag", TokenInfo( TAG_UNKNOWN_TAG, nTokenStartPos, aLastToken ) );
+ }
+
+ // check if we have an end-tag or a start-tag
+ USHORT nNonBlankStartPos,nNonBlankEndPos;
+ nNonBlankStartPos = 2;
+ while ( aLastToken.GetChar(nNonBlankStartPos) == ' ' )
+ nNonBlankStartPos++;
+ if ( aLastToken.GetChar(nNonBlankStartPos) == '/' )
+ aResult = TokenInfo( TAG_COMMONEND, nTokenStartPos, aLastToken, rErrorList );
+ else
+ {
+ aResult = TokenInfo( TAG_COMMONSTART, nTokenStartPos, aLastToken, rErrorList );
+ nNonBlankEndPos = aLastToken.Len() -3;
+ while ( aLastToken.GetChar(nNonBlankEndPos) == ' ' )
+ nNonBlankEndPos--;
+ if ( aLastToken.GetChar( nNonBlankEndPos ) == '/' )
+ aNextTag = TokenInfo( TAG_COMMONEND, nTokenStartPos, String::CreateFromAscii("\\</").Append(aResult.GetTagName()).AppendAscii("\\>"), rErrorList );
+ }
+ }
+ else
+ {
+ USHORT i = 0;
+ while ( aKnownTags[i].nTag != TAG_UNKNOWN_TAG &&
+ aLastToken != aKnownTags[i].GetName() )
+ i++;
+ aResult = TokenInfo( aKnownTags[i].nTag, nTokenStartPos );
+ }
+ }
+
+ if ( aResult.nId == TAG_UNKNOWN_TAG )
+ aResult = TokenInfo( TAG_UNKNOWN_TAG, nTokenStartPos, aLastToken );
+ aTokenList.Insert( aResult, LIST_APPEND );
+ return aResult;
+}
+
+String SimpleParser::GetNextTokenString( ParserMessageList &rErrorList, USHORT &rTagStartPos )
+{
+// USHORT nStyle1StartPos = aSource.SearchAscii( "<#", nPos );
+ USHORT nStyle2StartPos = aSource.SearchAscii( "$[", nPos );
+ USHORT nStyle3StartPos = aSource.SearchAscii( "\\<", nPos );
+ USHORT nStyle4StartPos = aSource.SearchAscii( "\\\\", nPos ); // this is only to kick out quoted backslashes
+
+ rTagStartPos = 0;
+
+/* removing since a \<... is not likely
+ // check if the tag starts with a letter to avoid things like <> <= ... >
+ while ( STRING_NOTFOUND != nStyle3StartPos && !( aSource.Copy( nStyle3StartPos+2, 1 ).IsAlphaAscii() || aSource.GetChar( nStyle3StartPos+2 ) == '/' ) )
+ nStyle3StartPos = aSource.SearchAscii( "\\<", nStyle3StartPos+1 );
+*/
+ if ( STRING_NOTFOUND == nStyle2StartPos && STRING_NOTFOUND == nStyle3StartPos )
+ return String(); // no more tokens
+
+ if ( nStyle4StartPos < nStyle2StartPos && nStyle4StartPos <= nStyle3StartPos ) // <= to make sure \\ is always handled first
+ { // Skip quoted Backslash
+ nPos = nStyle4StartPos +2;
+ return GetNextTokenString( rErrorList, rTagStartPos );
+ }
+
+/* if ( nStyle1StartPos < nStyle2StartPos && nStyle1StartPos <= nStyle3StartPos ) // <= to make sure our spechial tags are recognized before all others
+ { // test for <# ... > style tokens
+ USHORT nEndPos = aSource.SearchAscii( ">", nStyle1StartPos );
+ if ( nEndPos == STRING_NOTFOUND )
+ { // Token is incomplete. Skip start and search for better ones
+ nPos = nStyle1StartPos +2;
+ return GetNextTokenString( rErrorList, rTagStartPos );
+ }
+ nPos = nEndPos;
+ rTagStartPos = nStyle1StartPos;
+ return aSource.Copy( nStyle1StartPos, nEndPos-nStyle1StartPos +1 ).ToUpperAscii();
+ }
+ else*/ if ( nStyle2StartPos < nStyle3StartPos )
+ { // test for $[ ... ] style tokens
+ USHORT nEndPos = aSource.SearchAscii( "]", nStyle2StartPos);
+ if ( nEndPos == STRING_NOTFOUND )
+ { // Token is incomplete. Skip start and search for better ones
+ nPos = nStyle2StartPos +2;
+ return GetNextTokenString( rErrorList, rTagStartPos );
+ }
+ nPos = nEndPos;
+ rTagStartPos = nStyle2StartPos;
+ return aSource.Copy( nStyle2StartPos, nEndPos-nStyle2StartPos +1 );
+ }
+ else
+ { // test for \< ... \> style tokens
+ USHORT nEndPos = aSource.SearchAscii( "\\>", nStyle3StartPos);
+ USHORT nQuotedBackPos = aSource.SearchAscii( "\\\\", nStyle3StartPos ); // this is only to kick out quoted backslashes
+ while ( nQuotedBackPos <= nEndPos && nQuotedBackPos != STRING_NOTFOUND )
+ {
+ nEndPos = aSource.SearchAscii( "\\>", nQuotedBackPos +2);
+ nQuotedBackPos = aSource.SearchAscii( "\\\\", nQuotedBackPos +2 ); // this is only to kick out quoted backslashes
+ }
+ if ( nEndPos == STRING_NOTFOUND )
+ { // Token is incomplete. Skip start and search for better ones
+ nPos = nStyle3StartPos +2;
+ ByteString sTmp( "Tag Start '\\<' without Tag End '\\>': " );
+ rErrorList.AddError( 24, "Tag Start '\\<' without Tag End '\\>'", TokenInfo( TAG_UNKNOWN_TAG, nStyle3StartPos, aSource.Copy( nStyle3StartPos-10, 20 ) ) );
+ return GetNextTokenString( rErrorList, rTagStartPos );
+ }
+ // check for paired quoted " --> \"sometext\"
+
+ nPos = nEndPos;
+ rTagStartPos = nStyle3StartPos;
+ return aSource.Copy( nStyle3StartPos, nEndPos-nStyle3StartPos +2 );
+ }
+}
+
+String SimpleParser::GetLexem( TokenInfo const &aToken )
+{
+ if ( aToken.aTokenString.Len() )
+ return aToken.aTokenString;
+ else
+ {
+ USHORT i = 0;
+ while ( aKnownTags[i].nTag != TAG_UNKNOWN_TAG &&
+ aKnownTags[i].nTag != aToken.nId )
+ i++;
+
+ return aKnownTags[i].GetName();
+ }
+}
+
+TokenParser::TokenParser()
+: pErrorList( NULL )
+{}
+
+void TokenParser::Parse( const String &aCode, ParserMessageList* pList )
+{
+ pErrorList = pList;
+
+ //Scanner initialisieren
+ aParser.Parse( aCode );
+
+ //erstes Symbol holen
+ aTag = aParser.GetNextToken( *pErrorList );
+
+ nPfCaseOptions = 0;
+ nAppCaseOptions = 0;
+ bPfCaseActive = FALSE;
+ bAppCaseActive = FALSE;
+
+ nActiveRefTypes = 0;
+
+ //Ausfuehren der Start-Produktion
+ Paragraph();
+
+ //Es wurde nicht die ganze Kette abgearbeitet, bisher ist aber
+ //kein Fehler aufgetreten
+ //=> es wurde ein einleitendes Tag vergessen
+ if ( aTag.nId != TAG_NOMORETAGS )
+ {
+ switch ( aTag.nId )
+ {
+ case TAG_END:
+ {
+ ParseError( 3, "Extra Tag <#END>. Switch or <#HREF> expected.", aTag );
+ }
+ break;
+ case TAG_BOLDOFF:
+ {
+ ParseError( 4, "<#BOLD> expected before <#/BOLD>.", aTag );
+ }
+ break;
+ case TAG_ITALICOFF:
+ {
+ ParseError( 5, "<#ITALIC> expected before <#/ITALIC>.", aTag );
+ }
+ break;
+ case TAG_UNDERLINEOFF:
+ {
+ ParseError( 17, "<#UNDER> expected before <#/UNDER>.", aTag );
+ }
+ break;
+/* case TAG_MISSPARENTHESIS:
+ {
+ ParseError( 14, "missing closing parenthesis '>'", aTag );
+ }
+ break;*/
+ case TAG_AEND:
+ {
+ ParseError( 5, "Extra Tag <#AEND>. <#AVIS> or <#AHID> expected.", aTag );
+ }
+ break;
+ case TAG_ELSE:
+ {
+ ParseError( 16, "Application-tag or platform-tag expected before <#ELSE>.", aTag );
+ }
+ break;
+ case TAG_UNKNOWN_TAG:
+ {
+ ParseError( 6, "unknown Tag", aTag );
+ }
+ break;
+ default:
+ {
+ ParseError( 6, "unexpected Tag", aTag );
+ }
+ }
+ }
+ pErrorList = NULL;
+}
+
+void TokenParser::Paragraph()
+{
+ switch ( aTag.nId )
+ {
+ case TAG_GRAPHIC:
+ case TAG_NEXTVERSION:
+ {
+ TagRef();
+ Paragraph();
+ }
+ break;
+ case TAG_AVIS:
+ case TAG_AHID:
+ {
+ TagRef();
+ Paragraph();
+ }
+ break;
+ case TAG_HELPID:
+ {
+ SimpleTag();
+ Paragraph();
+ }
+ break;
+ case TAG_OFFICEFULLNAME:
+ case TAG_OFFICENAME:
+ case TAG_OFFICEPATH:
+ case TAG_OFFICEVERSION:
+ case TAG_PORTALNAME:
+ case TAG_PORTALFULLNAME:
+ case TAG_PORTALPATH:
+ case TAG_PORTALVERSION:
+ case TAG_PORTALSHORTNAME:
+ {
+ SimpleTag();
+ Paragraph();
+ }
+ break;
+ case TAG_REFINSERT:
+ {
+ SimpleTag();
+ Paragraph();
+ }
+ break;
+ case TAG_BOLDON:
+ case TAG_ITALICON:
+ case TAG_UNDERLINEON:
+ case TAG_COMMONSTART:
+ {
+ TagPair();
+ Paragraph();
+ }
+ break;
+ case TAG_HREF:
+ case TAG_NAME:
+ case TAG_KEY:
+ case TAG_INDEX:
+ case TAG_TITEL:
+ case TAG_REFSTART:
+ {
+ TagRef();
+ Paragraph();
+ }
+ break;
+ case TAG_OS2:
+ case TAG_WIN:
+ case TAG_UNIX:
+ case TAG_MAC: //...
+ {
+ if ( ! bPfCaseActive )
+ {
+ //PfCases duerfen nicht verschachtelt sein:
+ bPfCaseActive = TRUE;
+ PfCase();
+
+ //So jetzt kann wieder ein PfCase kommen:
+ bPfCaseActive = FALSE;
+ Paragraph();
+ }
+ }
+ break;
+ case TAG_WRITER:
+ case TAG_CALC:
+ case TAG_DRAW:
+ case TAG_IMPRESS:
+ case TAG_SCHEDULE:
+ case TAG_IMAGE:
+ case TAG_MATH:
+ case TAG_CHART:
+ case TAG_OFFICE:
+ {
+ if ( !bAppCaseActive )
+ {
+ //AppCases duerfen nicht verschachtelt sein:
+ bAppCaseActive = TRUE;
+ AppCase();
+
+ //jetzt koennen wieder AppCases kommen:
+ bAppCaseActive = FALSE;
+ Paragraph();
+ }
+ }
+ break;
+
+ //Case TAG_BOLDOFF, TAG_ITALICOFF, TAG_BUNDERLINE, TAG_END
+ //nichts tun wg. epsilon-Prod.
+ }
+}
+
+void TokenParser::PfCase()
+{
+
+ //Produktion:
+ //PfCase -> PfCaseBegin Paragraph (PfCase | PfCaseEnd)
+
+ PfCaseBegin();
+
+ //Jetzt ist eine PfCase-Produktion aktiv:
+ Paragraph();
+ switch ( aTag.nId )
+ {
+ case TAG_ELSE:
+ case TAG_END:
+ {
+ CaseEnd();
+ }
+ break;
+ case TAG_OS2:
+ case TAG_WIN:
+ case TAG_UNIX:
+ case TAG_MAC: //First (PfBegin)
+ {
+ PfCase();
+ }
+ break;
+ default:
+ ParseError( 8, "<#ELSE> or <#END> or platform-tag expected.", aTag );
+ }
+ //Die gemerkten Tags wieder loeschen fuer naechstes PfCase:
+ nPfCaseOptions = 0;
+}
+
+void TokenParser::PfCaseBegin()
+{
+ switch ( aTag.nId )
+ {
+ case TAG_OS2:
+ case TAG_WIN:
+ case TAG_UNIX:
+ case TAG_MAC:
+ {
+ //Token darf noch nicht vorgekommen sein im
+ //aktuellen Plattform-Case:
+ if ( !HAS_FLAG( nPfCaseOptions, TAG_NOGROUP( aTag.nId ) ) )
+ {
+ SET_FLAG( nPfCaseOptions, TAG_NOGROUP( aTag.nId ) );
+ match( aTag, aTag );
+ }
+ else {
+ ParseError( 9, "Tag defined twice in the same platform-case", aTag );
+ }
+ }
+ }
+}
+
+void TokenParser::AppCase()
+{
+
+ //Produktion:
+ //AppCase -> AppCaseBegin Paragraph (AppCase | AppCaseEnd)
+
+
+ AppCaseBegin();
+
+ Paragraph();
+
+ switch ( aTag.nId )
+ {
+ case TAG_ELSE:
+ case TAG_END:
+ {
+ CaseEnd();
+ }
+ break;
+ case TAG_WRITER:
+ case TAG_DRAW:
+ case TAG_CALC:
+ case TAG_IMAGE:
+ case TAG_MATH:
+ case TAG_CHART:
+ case TAG_OFFICE:
+ case TAG_IMPRESS:
+ case TAG_SCHEDULE: //First (AppBegin)
+ {
+ AppCase();
+ }
+ break;
+ default:
+ ParseError( 1, "<#ELSE> or <#END> or application-case-tag expected.", aTag );
+ }
+
+ //Die gemerkten Tags wieder loeschen fuer naechstes AppCase:
+ nAppCaseOptions = 0;
+}
+
+void TokenParser::AppCaseBegin()
+{
+ switch ( aTag.nId )
+ {
+ case TAG_WRITER:
+ case TAG_DRAW:
+ case TAG_CALC:
+ case TAG_IMAGE:
+ case TAG_MATH:
+ case TAG_CHART:
+ case TAG_OFFICE:
+ case TAG_IMPRESS:
+ case TAG_SCHEDULE:
+ {
+ //Token darf noch nicht vorgekommen sein im
+ //aktuellen Plattform-Case:
+ if ( !HAS_FLAG( nAppCaseOptions, TAG_NOGROUP( aTag.nId ) ) )
+ {
+ SET_FLAG( nAppCaseOptions, TAG_NOGROUP( aTag.nId ) );
+ match( aTag, aTag );
+ }
+ else {
+ ParseError( 13, "Tag defined twice in the same application-case.", aTag );
+ }
+ }
+ }
+}
+
+void TokenParser::CaseEnd()
+{
+ //Produktion:
+ //CaseEnd -> <#ELSE> Paragraph <#END> | <#END>
+
+ switch ( aTag.nId )
+ {
+ case TAG_ELSE:
+ {
+ match( aTag, TAG_ELSE );
+ Paragraph();
+ match( aTag, TAG_END );
+ }
+ break;
+ case TAG_END:
+ {
+ match( aTag, TAG_END );
+ }
+ break;
+ default:
+ ParseError( 2, "<#ELSE> or <#END> expected.", aTag );
+ }
+}
+
+void TokenParser::SimpleTag()
+{
+
+ switch ( aTag.nId )
+ {
+ case TAG_HELPID:
+ {
+ match( aTag, TAG_HELPID );
+ }
+ break;
+ case TAG_OFFICEFULLNAME:
+ case TAG_OFFICENAME:
+ case TAG_OFFICEPATH:
+ case TAG_OFFICEVERSION:
+ case TAG_PORTALNAME:
+ case TAG_PORTALFULLNAME:
+ case TAG_PORTALPATH:
+ case TAG_PORTALVERSION:
+ case TAG_PORTALSHORTNAME:
+
+ case TAG_REFINSERT:
+ {
+ match( aTag, aTag );
+ }
+ break;
+ default:
+ ParseError( 15, "[<#SimpleTag>] expected.", aTag );
+ }
+}
+
+void TokenParser::TagPair()
+{
+ switch ( aTag.nId )
+ {
+ case TAG_BOLDON:
+ {
+ match( aTag, TAG_BOLDON );
+ Paragraph();
+ match( aTag, TAG_BOLDOFF );
+ }
+ break;
+ case TAG_ITALICON:
+ {
+ match( aTag, TAG_ITALICON );
+ Paragraph();
+ match( aTag, TAG_ITALICOFF );
+ }
+ break;
+ case TAG_UNDERLINEON:
+ {
+ match( aTag, TAG_UNDERLINEON );
+ Paragraph();
+ match( aTag, TAG_UNDERLINEOFF );
+ }
+ break;
+ case TAG_COMMONSTART:
+ {
+ //remember tag so we can give the original tag in case of an error
+ TokenInfo aEndTag( aTag );
+ aEndTag.nId = TAG_COMMONEND;
+ match( aTag, TAG_COMMONSTART );
+ Paragraph();
+ match( aTag, aEndTag );
+ }
+ break;
+ default:
+ ParseError( 10, "<#BOLD>, <#ITALIC>, <#UNDER> expected.", aTag );
+ }
+}
+
+
+void TokenParser::TagRef()
+{
+ switch ( aTag.nId )
+ {
+ case TAG_GRAPHIC:
+ case TAG_NEXTVERSION:
+ {
+ if ( !HAS_FLAG( nActiveRefTypes, TAG_NOGROUP( aTag.nId ) ) )
+ {
+ TokenId aThisToken = aTag.nId;
+ SET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
+ match( aTag, aTag );
+ Paragraph();
+ if ( aThisToken == TAG_GRAPHIC )
+ match( aTag, TAG_ENDGRAPHIC );
+ else
+ match( aTag, TAG_VERSIONEND );
+ // don't reset since alowed only once per paragraph
+ // RESET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
+ }
+ else
+ {
+ ParseError( 11, "Tags <#GRAPHIC>,<#NEXTVERSION> allowed only once per paragraph at", aTag );
+ }
+ }
+ break;
+ case TAG_AVIS:
+ case TAG_AHID:
+ {
+ if ( !HAS_FLAG( nActiveRefTypes, TAG_NOGROUP( aTag.nId ) ) )
+ {
+ TokenId aThisToken = aTag.nId;
+ SET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
+ match( aTag, aTag );
+ Paragraph();
+ match( aTag, TAG_AEND );
+ RESET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
+ }
+ else
+ {
+ ParseError( 11, "Nested <#AHID>,<#AVIS> not allowed.", aTag );
+ }
+ }
+ break;
+ case TAG_HREF:
+ case TAG_NAME:
+ {
+
+ }
+ // NOBREAK
+ case TAG_KEY:
+ case TAG_INDEX:
+ case TAG_TITEL:
+ case TAG_REFSTART:
+ {
+ if ( !HAS_FLAG( nActiveRefTypes, TAG_NOGROUP( aTag.nId ) ) )
+ {
+ TokenId aThisToken = aTag.nId;
+ match( aTag, aTag );
+ if ( aThisToken != TAG_NAME )
+ { // TAG_NAME has no TAG_END
+ SET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
+ Paragraph();
+ match( aTag, TAG_END );
+ RESET_FLAG( nActiveRefTypes, TAG_NOGROUP( aThisToken ) );
+ }
+ }
+ else
+ {
+ ParseError( 11, "Nested <#HREF>,<#NAME> or <#KEY> not allowed.", aTag );
+ }
+ }
+ break;
+ default:
+ ParseError( 12, "<#HREF>,<#NAME> or <#KEY> expected.", aTag );
+ }
+}
+
+BOOL TokenParser::match( const TokenInfo &aCurrentToken, const TokenId &aExpectedToken )
+{
+ return match( aCurrentToken, TokenInfo( aExpectedToken, TOK_INVALIDPOS ) );
+}
+
+BOOL TokenParser::match( const TokenInfo &aCurrentToken, const TokenInfo &rExpectedToken )
+{
+ TokenInfo aExpectedToken( rExpectedToken );
+ if ( aCurrentToken.nId == aExpectedToken.nId )
+ {
+ if ( ( aCurrentToken.nId == TAG_COMMONEND
+ && aCurrentToken.GetTagName().Equals( aExpectedToken.GetTagName() ) )
+ || aCurrentToken.nId != TAG_COMMONEND )
+ {
+ aTag = aParser.GetNextToken( *pErrorList );
+ return TRUE;
+ }
+ }
+
+ if ( aExpectedToken.nId == TAG_COMMONEND )
+ {
+ aExpectedToken.aTokenString.Insert( String::CreateFromAscii( "Close tag for " ), 0 );
+ }
+
+ ByteString sTmp( "Expected Symbol" );
+ if ( aCurrentToken.nId == TAG_NOMORETAGS )
+ {
+ ParseError( 7, sTmp, aExpectedToken );
+ }
+ else
+ {
+ sTmp += ": ";
+ sTmp += ByteString( aParser.GetLexem( aExpectedToken ), RTL_TEXTENCODING_UTF8 );
+ sTmp += " near ";
+ ParseError( 7, sTmp, aCurrentToken );
+ }
+ return FALSE;
+}
+
+void TokenParser::ParseError( USHORT nErrNr, ByteString aErrMsg, const TokenInfo &rTag )
+{
+ pErrorList->AddError( nErrNr, aErrMsg, rTag);
+
+ // Das Fehlerhafte Tag ueberspringen
+ aTag = aParser.GetNextToken( *pErrorList );
+}
+
+
+ParserMessage::ParserMessage( USHORT PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag )
+ : nErrorNr( PnErrorNr )
+ , aErrorText( PaErrorText )
+ , nTagBegin( 0 )
+ , nTagLength( 0 )
+{
+ String aLexem( SimpleParser::GetLexem( rTag ) );
+ aErrorText.Append(": ");
+ aErrorText += ByteString( aLexem, RTL_TEXTENCODING_UTF8 );
+ if ( rTag.nId == TAG_NOMORETAGS )
+ aErrorText.Append(" at end of line ");
+ else if ( rTag.nPos != TOK_INVALIDPOS )
+ {
+ aErrorText.Append(" at Position ");
+ aErrorText.Append( ByteString::CreateFromInt32( rTag.nPos ) );
+ }
+ nTagBegin = rTag.nPos;
+ nTagLength = aLexem.Len();
+}
+
+ParserError::ParserError( USHORT ErrorNr, ByteString ErrorText, const TokenInfo &rTag )
+: ParserMessage( ErrorNr, ErrorText, rTag )
+{}
+
+ParserWarning::ParserWarning( USHORT ErrorNr, ByteString ErrorText, const TokenInfo &rTag )
+: ParserMessage( ErrorNr, ErrorText, rTag )
+{}
+
+BOOL LingTest::IsTagMandatory( TokenInfo const &aToken, TokenId &aMetaTokens )
+{
+ TokenId aTokenId = aToken.nId;
+ TokenId aTokenGroup = TAG_GROUP( aTokenId );
+ if ( TAG_GROUP_PROGSWITCH == aTokenGroup
+ || TAG_REFINSERT == aTokenId
+ || TAG_REFSTART == aTokenId
+ || TAG_NAME == aTokenId
+ || TAG_HREF == aTokenId
+ || TAG_AVIS == aTokenId
+ || TAG_AHID == aTokenId
+ || TAG_GRAPHIC == aTokenId
+ || TAG_NEXTVERSION == aTokenId
+ || ( TAG_GROUP_META == aTokenGroup && (aMetaTokens & aTokenId) == aTokenId ) )
+ {
+ if ( TAG_GROUP_META == aTokenGroup )
+ aMetaTokens |= aTokenId;
+ return TRUE;
+ }
+ else if ( TAG_COMMONSTART == aTokenId
+ || TAG_COMMONEND == aTokenId )
+ {
+ String aTagName = aToken.GetTagName();
+ return !(aTagName.EqualsIgnoreCaseAscii( "comment" )
+ || aTagName.EqualsIgnoreCaseAscii( "bookmark_value" )
+ || aTagName.EqualsIgnoreCaseAscii( "emph" )
+ || aTagName.EqualsIgnoreCaseAscii( "item" )
+ || aTagName.EqualsIgnoreCaseAscii( "br" ) );
+ }
+ return FALSE;
+}
+
+void LingTest::CheckTags( TokenList &aReference, TokenList &aTestee, BOOL bFixTags )
+{
+ ULONG i=0,j=0;
+ // Clean old Warnings
+ while ( aCompareWarningList.Count() )
+ {
+ delete aCompareWarningList.GetCurObject();
+ aCompareWarningList.Remove();
+ }
+
+ /* in xml tags, do not require the following tags
+ comment
+ bookmark_value
+ emph
+ item
+ br
+ */
+
+ // filter uninteresting Tags
+ TokenId aMetaTokens = 0;
+ for ( i=0 ; i < aReference.Count() ; i++ )
+ {
+ if ( !IsTagMandatory( aReference.GetObject( i ), aMetaTokens ) )
+ aReference.GetObject( i ).SetDone();
+ }
+
+ aMetaTokens = 0;
+ for ( i=0 ; i < aTestee.Count() ; i++ )
+ {
+ if ( !IsTagMandatory( aTestee.GetObject( i ), aMetaTokens ) )
+ aTestee.GetObject( i ).SetDone();
+ }
+
+ // remove all matching tags
+ for ( i=0 ; i < aReference.Count() ; i++ )
+ {
+ if ( aReference.GetObject( i ).IsDone() )
+ continue;
+
+ BOOL bTagFound = FALSE;
+ for ( j=0 ; j < aTestee.Count() && !bTagFound ; j++ )
+ {
+ if ( aTestee.GetObject( j ).IsDone() )
+ continue;
+
+ if ( aReference.GetObject( i ).MatchesTranslation( aTestee.GetObject( j ), FALSE, aCompareWarningList ) )
+ {
+ aReference.GetObject( i ).SetDone();
+ aTestee.GetObject( j ).SetDone();
+ bTagFound = TRUE;
+ }
+ }
+ }
+
+ BOOL bCanFix = TRUE;
+
+ if ( bFixTags )
+ {
+ // we fix only if its a really simple case
+ USHORT nTagCount = 0;
+ for ( i=0 ; i < aReference.Count() ; i++ )
+ if ( !aReference.GetObject( i ).IsDone() )
+ nTagCount++;
+ if ( nTagCount > 1 )
+ bCanFix = FALSE;
+
+ nTagCount = 0;
+ for ( i=0 ; i < aTestee.Count() ; i++ )
+ if ( !aTestee.GetObject( i ).IsDone() )
+ nTagCount++;
+ if ( nTagCount > 1 )
+ bCanFix = FALSE;
+ }
+
+ // generate errors for tags that have differing attributes
+ for ( i=0 ; i < aReference.Count() ; i++ )
+ {
+ if ( aReference.GetObject( i ).IsDone() )
+ continue;
+
+ BOOL bTagFound = FALSE;
+ for ( j=0 ; j < aTestee.Count() && !bTagFound ; j++ )
+ {
+ if ( aTestee.GetObject( j ).IsDone() )
+ continue;
+
+ if ( aReference.GetObject( i ).MatchesTranslation( aTestee.GetObject( j ), TRUE, aCompareWarningList, bCanFix && bFixTags ) )
+ {
+ aReference.GetObject( i ).SetDone();
+ aTestee.GetObject( j ).SetDone();
+ bTagFound = TRUE;
+ }
+ }
+ }
+
+ // list remaining tags as errors
+ for ( i=0 ; i < aReference.Count() ; i++ )
+ {
+ if ( aReference.GetObject( i ).IsDone() )
+ continue;
+
+ aCompareWarningList.AddError( 20, "Missing Tag in Translation", aReference.GetObject( i ) );
+ }
+ for ( i=0 ; i < aTestee.Count() ; i++ )
+ {
+ if ( aTestee.GetObject( i ).IsDone() )
+ continue;
+
+ aCompareWarningList.AddError( 21, "Extra Tag in Translation", aTestee.GetObject( i ) );
+ }
+
+ for ( i=0 ; i < aReference.Count() ; i++ )
+ aReference.GetObject( i ).SetDone( FALSE );
+
+ for ( i=0 ; i < aTestee.Count() ; i++ )
+ aTestee.GetObject( i ).SetDone( FALSE );
+}
+
+void LingTest::CheckReference( GSILine *aReference )
+{
+ aReferenceParser.Parse( aReference->GetUText(), aReference->GetMessageList() );
+}
+
+void LingTest::CheckTestee( GSILine *aTestee, BOOL bHasSourceLine, BOOL bFixTags )
+{
+ aFixedTestee = aTestee->GetUText();
+ aTesteeParser.Parse( aFixedTestee, aTestee->GetMessageList() );
+
+ if ( bHasSourceLine )
+ CheckTags( aReferenceParser.GetTokenList(), aTesteeParser.GetTokenList(), bFixTags );
+
+ if ( bFixTags )
+ {
+ TokenList& aTesteeTokens = aTesteeParser.GetTokenList();
+ BOOL bFixesDone = FALSE;
+ // count backwards to allow replacing from right to left
+ int i;
+ for ( i=aTesteeTokens.Count()-1 ; i>=0 ; i-- )
+ {
+ if ( aTesteeTokens.GetObject( i ).HasBeenFixed() )
+ {
+ bFixesDone = TRUE;
+ aFixedTestee.Replace( aTesteeTokens.GetObject( i ).nPos, aTesteeTokens.GetObject( i ).aTokenString.Len(), aTesteeTokens.GetObject( i ).MakeTag() );
+ }
+ }
+ if ( bFixesDone )
+ {
+ aTestee->SetUText( aFixedTestee );
+ aTestee->SetFixed();
+ }
+ }
+}
+
diff --git a/l10ntools/source/treeconfig.cxx b/l10ntools/source/treeconfig.cxx
new file mode 100644
index 000000000000..137492c39a50
--- /dev/null
+++ b/l10ntools/source/treeconfig.cxx
@@ -0,0 +1,128 @@
+#include <vector>
+#include <string>
+#include <iostream>
+#include "treeconfig.hxx"
+#include "export.hxx"
+#ifdef WNT
+#include <direct.h>
+#include <io.h>
+#else
+#include <dirent.h>
+#endif
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace std;
+
+namespace transex3
+{
+
+bool Treeconfig::parseConfig(){
+
+ string source_config_file = string( static_cast<ByteString>( Export::GetEnv("SOURCE_ROOT_DIR") ).GetBuffer() );
+ if( source_config_file.empty() )
+ {
+ cerr << "Error: no suitable environment set?!?";
+ exit( -1 );
+ }
+ source_config_file += string("/source_config");
+ if( isConfigFilePresent() )
+ {
+ inireader.read( map , source_config_file );
+ return true;
+ }
+ else return false;
+}
+
+// ALWAYS add all repositories from source_config file to the container active_repos
+// if a config_file is present ALWAYS return false
+// if you are in the root of a repository also add it to the container active_repos
+// if you are far inside a repository /my/path/ooo/sw/source then don't add it to the container but return true
+// if you are in some misc place like /tmp then return true
+// => the application can decide what to do in case the function returns true thus how to handle pwd() path
+bool Treeconfig::getActiveRepositories( vector<string>& active_repos ){
+
+ bool isPresent = isConfigFilePresent();
+ bool hasPath = false;
+ string pwd;
+ string guessedRepo;
+ Export::getCurrentDir( pwd );
+ string source_root = Export::GetEnv( "SOURCE_ROOT_DIR" );
+ string solarsrc = Export::GetEnv( "SOLARSRC" );
+ string partial;
+
+ // if we are inside of a repository root then active it otherwise let the app handle the return!
+ string::size_type pos = pwd.find_first_of( source_root );
+ if( pos != string::npos && ( pos + source_root.length() +1 ) < pwd.length()){ // I am within SOURCE_ROOT_DIR
+ partial = pwd.substr( pos + source_root.length() +1 , pwd.length());
+ string::size_type nextPart = partial.find_first_of( "/" );
+ if( nextPart != string::npos )
+ hasPath = true;
+ else
+ guessedRepo = partial;
+ }
+ else // I am NOT within SOURCE_ROOT_DIR
+ hasPath = true;
+
+ if( isPresent )
+ {
+ hasPath = false; // if config_file is present don't care about pwd
+ stringmap* repos = static_cast<stringmap*>( map[ string("repositories") ] );
+ if( repos != 0 )
+ {
+ for( stringmap::iterator iter = repos->begin() ; iter != repos->end() ; ++iter )
+ {
+ if( static_cast<string>( iter->second ) == string( "active" ) )
+ {
+ active_repos.push_back( iter->first );
+ if( static_cast<string>( iter->first ) == guessedRepo )
+ {
+ guessedRepo.clear(); // don't add double in case it is present in config_file
+ }
+ }
+ }
+ }
+ else
+ {
+ cerr << "Error: source_config files doesn't contain a 'repositories' section ?!?";
+ exit( -1 );
+ }
+ }
+ if( !guessedRepo.empty() ){
+ active_repos.push_back( guessedRepo ); // add myrepo
+ }
+ return hasPath; // are we deep inside of a source tree or outside of SOURCE_ROOT_DIR?
+}
+
+void Treeconfig::getCurrentDir( string& dir )
+{
+ char buffer[64000];
+ if( getcwd( buffer , sizeof( buffer ) ) == 0 ){
+ cerr << "Error: getcwd failed!\n";
+ exit( -1 );
+ }
+ dir = string( buffer );
+}
+
+bool Treeconfig::isConfigFilePresent()
+{
+ string config_file = Export::GetEnv( "SOURCE_ROOT_DIR" );
+ config_file += "/source_config";
+
+ struct stat status;
+ if( stat( config_file.c_str() , &status ) < 0 )
+ {
+ return false;
+ }
+#ifdef WNT
+ return ( status.st_mode & _S_IFREG ) && ( _access( config_file.c_str() , 4 ) >= 0 ) ;
+#else
+ return ( status.st_mode & S_IFREG ) && ( access( config_file.c_str() , R_OK ) >= 0 ) ;
+#endif
+}
+
+
+
+}
diff --git a/l10ntools/source/utf8conv.cxx b/l10ntools/source/utf8conv.cxx
new file mode 100644
index 000000000000..ee35eb56befd
--- /dev/null
+++ b/l10ntools/source/utf8conv.cxx
@@ -0,0 +1,77 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: utf8conv.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include "utf8conv.hxx"
+
+//
+// class UTF8Converter
+//
+
+#define MAX_CONV_BUFFER_SIZE 0xFF00
+
+#define TO_CVTFLAGS (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_MAPTOPRIVATE |\
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |\
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT)
+
+#define FROM_CVTFLAGS (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |\
+ RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT |\
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE |\
+ RTL_UNICODETOTEXT_FLAGS_PRIVATE_MAPTO0)
+
+/*****************************************************************************/
+void UTF8Converter::Convert( ByteString &rBuffer,
+ rtl_TextEncoding nSourceENC, rtl_TextEncoding nDestENC )
+/*****************************************************************************/
+{
+ String sTemp( rBuffer, nSourceENC );
+ rBuffer = ByteString( sTemp, nDestENC );
+}
+
+/*****************************************************************************/
+ByteString UTF8Converter::ConvertToUTF8(
+ const ByteString &rASCII, rtl_TextEncoding nEncoding )
+/*****************************************************************************/
+{
+ ByteString sReturn( rASCII );
+ Convert( sReturn, nEncoding, RTL_TEXTENCODING_UTF8 );
+ return sReturn;
+}
+
+/*****************************************************************************/
+ByteString UTF8Converter::ConvertFromUTF8(
+ const ByteString &rUTF8, rtl_TextEncoding nEncoding )
+/*****************************************************************************/
+{
+ ByteString sReturn( rUTF8 );
+ Convert( sReturn, RTL_TEXTENCODING_UTF8, nEncoding );
+ return sReturn;
+}
diff --git a/l10ntools/source/wrdtrans.cxx b/l10ntools/source/wrdtrans.cxx
new file mode 100644
index 000000000000..c4a9d6ea5570
--- /dev/null
+++ b/l10ntools/source/wrdtrans.cxx
@@ -0,0 +1,248 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: wrdtrans.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+
+/*
+#include "wrdtrans.hxx"
+
+
+// NOT FULLY DECLARED SERVICES
+#include <vector>
+#include <vos/macros.hxx>
+
+
+#include <tools/stream.hxx>
+#include "wtratree.hxx"
+
+#include <tools/string.hxx>
+*/
+//************** Declaration WordTrans_ErrorList ******************//
+/*
+typedef NAMESPACE_STD(vector)<ByteString> Stl_ByteStringList;
+
+class WordTrans_ErrorList
+{
+ public:
+ // OPERATIONS
+ void AddError(
+ WordTransformer::E_Error
+ i_eType,
+ const char * i_sErrorDescription );
+ void Clear(); /// Empties the list.
+
+ // INQUIRY
+ USHORT NrOfErrors() const;
+ WordTransformer::E_Error
+ GetError(
+ USHORT i_nNr, /// [0 .. NrOfErrors()-1], other values return an empty error.
+ ByteString * o_pErrorText ) const; /// If o_pErrorText != 0, the String is filled with the description of the error.
+ private:
+ // DATA
+ Stl_ByteStringList aErrors;
+};
+
+*/
+
+//************** Implementation WordTransformer ******************//
+
+/*
+WordTransformer::WordTransformer()
+ : dpTransformer(0),
+ dpErrors(new WordTrans_ErrorList)
+{
+}
+
+WordTransformer::~WordTransformer()
+{
+ if (dpTransformer != 0)
+ delete dpTransformer;
+ delete dpErrors;
+}
+
+BOOL
+WordTransformer::LoadWordlist( const ByteString & i_sWordlist_Filepath,
+ CharSet i_nWorkingCharSet,
+ CharSet i_nFileCharSet )
+{
+ if (dpTransformer != 0)
+ return FALSE;
+
+ SvFileStream aFile(String(i_sWordlist_Filepath,RTL_TEXTENCODING_ASCII_US),STREAM_STD_READ);
+ if (! aFile.IsOpen())
+ return FALSE;
+ aFile.SetStreamCharSet( i_nFileCharSet ) ;
+// aFile.SetTargetCharSet( i_nWorkingCharSet );
+
+ dpTransformer = new WordTransTree;
+
+ ByteString sTrans;
+ while ( aFile.ReadLine(sTrans) )
+ {
+ dpTransformer->AddWordPair(sTrans.GetToken(0,';'),sTrans.GetToken(1,';'));
+ }
+
+ aFile.Close();
+ return TRUE;
+}
+
+USHORT
+WordTransformer::Transform(ByteString & io_sText)
+{
+ // Initialization and precondition testing:
+ dpErrors->Clear();
+ if (dpTransformer == 0)
+ {
+ dpErrors->AddError(ERROR_NO_WORDLIST,"Error: No wordlist was loaded.");
+ return dpErrors->NrOfErrors();
+ }
+ else if (io_sText.Len() > 63 * 1024)
+ {
+ dpErrors->AddError(ERROR_OUTPUTSTRING_TOO_LONG,"Error: Inputstring was too long (bigger than 63 KB).");
+ return dpErrors->NrOfErrors();
+ }
+ else if (io_sText.Len() == 0)
+ {
+ return 0;
+ }
+
+ // Transform:
+ dpTransformer->InitTransformation(
+ io_sText.GetBuffer(),
+ io_sText.Len() );
+
+ for ( ; !dpTransformer->TextEndReached(); )
+ {
+ if (dpTransformer->TransformNextToken() != WordTransTree::OK)
+ {
+ CreateError();
+ }
+ }
+ io_sText = dpTransformer->Output();
+ return dpErrors->NrOfErrors();
+}
+
+USHORT
+WordTransformer::NrOfErrors() const
+{
+ return dpErrors->NrOfErrors();
+}
+
+WordTransformer::E_Error
+WordTransformer::GetError( USHORT i_nNr,
+ ByteString * o_pErrorText) const
+{
+ return dpErrors->GetError(i_nNr,o_pErrorText);
+}
+
+void
+WordTransformer::CreateError()
+{
+ ByteString sErr;
+
+ switch (dpTransformer->CurResult())
+ {
+ case WordTransTree::OK:
+ break;
+ case WordTransTree::HOTKEY_LOST:
+ sErr = ByteString("Error: By replacement of string ");
+ sErr += dpTransformer->CurReplacedString();
+ sErr += " by ";
+ sErr += dpTransformer->CurReplacingString();
+ sErr += "the hotkey at char '";
+ sErr += dpTransformer->CurHotkey();
+ sErr += "' was lost.";
+ dpErrors->AddError( ERROR_HOTKEY,sErr.GetBufferAccess());
+ sErr.ReleaseBufferAccess();
+ break;
+ case WordTransTree::OUTPUT_OVERFLOW:
+ dpErrors->AddError(ERROR_OUTPUTSTRING_TOO_LONG,"Error: Output buffer overflow.");
+ break;
+ default:
+ dpErrors->AddError(OTHER_ERROR,"Error: Unknown error.");
+ }
+}
+*/
+//************** Implementation WordTrans_ErrorList ******************//
+/*
+void
+WordTrans_ErrorList::AddError( WordTransformer::E_Error i_eType,
+ const char * i_sErrorDescription )
+{
+ ByteString sErrorType = "xxx";
+ char * pErrorChars = sErrorType.GetBufferAccess();
+ pErrorChars[0] = char(i_eType / 100 + '0');
+ pErrorChars[1] = char( (i_eType % 100) / 10 + '0');
+ pErrorChars[2] = char(i_eType % 10 + '0');
+ sErrorType += i_sErrorDescription;
+
+ aErrors.push_back(sErrorType);
+ sErrorType.ReleaseBufferAccess();
+}
+
+void
+WordTrans_ErrorList::Clear()
+{
+ aErrors.erase(aErrors.begin(),aErrors.end());
+}
+
+USHORT
+WordTrans_ErrorList::NrOfErrors() const
+{
+ return aErrors.size();
+}
+
+WordTransformer::E_Error
+WordTrans_ErrorList::GetError( USHORT i_nNr,
+ ByteString * o_pErrorText ) const
+{
+ if ( i_nNr < aErrors.size() )
+ {
+ const ByteString & rError = aErrors[i_nNr];
+ const char * pErrorChars = rError.GetBuffer();
+
+ USHORT nError = USHORT( (pErrorChars[0] - '0') ) * 100
+ + (pErrorChars[1] - '0') * 10
+ + pErrorChars[2] - '0';
+
+ if (o_pErrorText != 0)
+ *o_pErrorText = pErrorChars+3;
+
+ return WordTransformer::E_Error(nError);
+ }
+ else
+ {
+ if (o_pErrorText != 0)
+ *o_pErrorText = "";
+ return WordTransformer::OK;
+ }
+}
+*/
diff --git a/l10ntools/source/wtranode.cxx b/l10ntools/source/wtranode.cxx
new file mode 100644
index 000000000000..401c0b20fe1a
--- /dev/null
+++ b/l10ntools/source/wtranode.cxx
@@ -0,0 +1,111 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: wtranode.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+
+
+#include "wtranode.hxx"
+
+
+// NOT FULLY DECLARED SERVICES
+
+
+const ByteString sEmptyString("");
+
+
+WTT_Node::WTT_Node( UINT8 i_nValue,
+ WTT_Node * i_pDefaultBranch,
+ WTT_Node * i_pDefaultBranchForAlphas )
+ : nValue(i_nValue),
+ eType(token_to_keep),
+ sReplaceString(sEmptyString),
+ // aBranches,
+ bIsOnDeleting(char(0))
+{
+ int i = 0;
+ for ( ; i < C_BR_ALPHABASE; i++ )
+ {
+ aBranches[i] = i_pDefaultBranch;
+ } // end for
+ for ( ; i < C_NR_OF_BRANCHES; i++ )
+ {
+ aBranches[i] = i_pDefaultBranchForAlphas;
+ }
+}
+
+void
+WTT_Node::SetBranch( UINT8 i_cBranch,
+ WTT_Node * i_pNode )
+{
+ if (i_cBranch < C_NR_OF_BRANCHES)
+ {
+ aBranches[i_cBranch] = i_pNode;
+ }
+}
+
+void
+WTT_Node::SetAsTokenToReplace(const ByteString & i_sReplaceString)
+{
+ sReplaceString = i_sReplaceString;
+ eType = token_to_replace;
+}
+
+WTT_Node::~WTT_Node()
+{
+ // Delete the tree hanging below this node:
+
+ bIsOnDeleting = TRUE; // Avoid double deleting of multiple used nodes.
+
+ for (int i = 0; i < C_NR_OF_BRANCHES; i++)
+ {
+ if (aBranches[i] != 0 ? ! aBranches[i]->IsOnDeleting() : FALSE)
+ {
+ delete aBranches[i];
+ }
+ } // end for
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/l10ntools/source/wtratree.cxx b/l10ntools/source/wtratree.cxx
new file mode 100644
index 000000000000..dbf02a6f22be
--- /dev/null
+++ b/l10ntools/source/wtratree.cxx
@@ -0,0 +1,421 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: wtratree.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+
+
+#include "wtratree.hxx"
+
+
+
+/** @ATTENTION
+ For reasons of speed, class WordTransTree works with two simple
+ char arrays, sOutput and sInput, instead of secure containers or
+ streams. So be extremely careful, when changing this code!!!
+**/
+
+
+
+// NOT FULLY DECLARED SERVICES
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "wtranode.hxx"
+
+
+const BRANCH_T BR_END = 0;
+const BRANCH_T BR_NONALPHA = 1;
+const BRANCH_T BR_HOTKEY = 2;
+const BRANCH_T BR_BACKSLASH = 3;
+const BRANCH_T BR_ALPHABASE = 4; /// @ATTENTION All branches not valid for words must be smaller than this value!
+const BRANCH_T BR_AE = 30;
+const BRANCH_T BR_OE = 31;
+const BRANCH_T BR_UE = 32;
+const BRANCH_T BR_SZ = 33;
+const BRANCH_T BR_MAX = 34; /// @ATTENTION Must be updated always!
+
+const BRANCH_T BR_START = 0;
+
+
+
+
+
+WordTransTree::WordTransTree(CharSet i_nWorkingCharSet)
+ : sInput(0),
+ nInputLength(0),
+ pInputEnd(0),
+ sOutput(0),
+ nOutputMaxLength(0),
+ dpParsingTreeTop(0),
+ pUnknownAlpha(0),
+ // cChar2Branch
+ c_AE(u_char('\xC4')), c_OE(u_char('\xD6')), c_UE(u_char('\xDC')),
+ c_ae(u_char('\xE4')), c_oe(u_char('\xF6')), c_ue(u_char('\xFC')),
+ pInputCurTokenStart(0),
+ pInputPosition(0),
+ pOutputPosition(0),
+ pCurParseNode(0),
+ eCurResult(OK),
+ cCurHotkey(0),
+ cCurHotkeySign(u_char('~'))
+{
+ // Initialize parsing tree:
+ pUnknownAlpha = new WTT_Node(BR_ALPHABASE,0,0); // This will be deleted as part of the parsing tree.
+ for ( UINT8 i = BR_ALPHABASE; i < C_NR_OF_BRANCHES; i++)
+ {
+ pUnknownAlpha->SetBranch(i,pUnknownAlpha);
+ } // end for
+
+ dpParsingTreeTop = new WTT_Node(BR_START,0,pUnknownAlpha);
+
+ WTT_Node * dpNonAlpha = new WTT_Node(BR_NONALPHA,0,0);
+
+ dpNonAlpha->SetBranch(BR_NONALPHA,dpNonAlpha);
+ dpParsingTreeTop->SetBranch(BR_NONALPHA,dpNonAlpha);
+
+ WTT_Node * dpBackslash = new WTT_Node(BR_BACKSLASH,dpNonAlpha,dpNonAlpha);
+ dpBackslash->SetBranch(BR_END,0);
+
+ dpParsingTreeTop->SetBranch(BR_BACKSLASH,dpBackslash);
+ dpNonAlpha->SetBranch(BR_BACKSLASH,dpBackslash);
+
+
+ // Initialize character set:
+ SetCharSet(i_nWorkingCharSet);
+
+ if (C_BR_ALPHABASE != BR_ALPHABASE || C_NR_OF_BRANCHES != BR_MAX)
+ {
+ fprintf(stderr, "Assertion failed: file %s line %d.", __FILE__, __LINE__);
+ exit(1);
+ }
+}
+
+void
+WordTransTree::SetCharSet(CharSet i_nWorkingCharSet)
+{
+ ByteString sConvert("\xC4\xD6\xDC\xE4\xF6\xFC\xDF");
+ const u_char * pConvert = (const u_char * ) ( sConvert.Convert(RTL_TEXTENCODING_MS_1252, i_nWorkingCharSet).GetBuffer() );
+
+ INT16 i = 0;
+ for ( ; i < C_NR_OF_POSSIBLE_CHARS; ++i )
+ {
+ cChar2Branch[i] = BR_NONALPHA;
+ } // end for
+ for ( i = 'a'; i <= 'z'; ++i )
+ {
+ cChar2Branch[i] = BR_ALPHABASE + i - 'a';
+ } // end for
+ for ( i = 'A'; i <= 'Z'; ++i )
+ {
+ cChar2Branch[i] = BR_ALPHABASE + i - 'A';
+ } // end for
+ cChar2Branch[pConvert[0]] = BR_AE;
+ cChar2Branch[pConvert[1]] = BR_OE;
+ cChar2Branch[pConvert[2]] = BR_UE;
+ cChar2Branch[pConvert[3]] = BR_AE;
+ cChar2Branch[pConvert[4]] = BR_OE;
+ cChar2Branch[pConvert[5]] = BR_UE;
+ cChar2Branch[pConvert[6]] = BR_SZ;
+
+ cChar2Branch[u_char('~')] = BR_HOTKEY;
+ cChar2Branch[u_char('&')] = BR_HOTKEY;
+
+
+ c_AE = pConvert[0];
+ c_OE = pConvert[1];
+ c_UE = pConvert[2];
+ c_ae = pConvert[3];
+ c_oe = pConvert[4];
+ c_ue = pConvert[5];
+}
+
+WordTransTree::~WordTransTree()
+{
+ delete dpParsingTreeTop;
+ if (sOutput != 0)
+ delete [] sOutput;
+}
+
+void
+WordTransTree::AddWordPair( const ByteString & i_sOldString,
+ const ByteString & i_sReplaceString )
+{
+ if (i_sOldString.Len() == 0)
+ return;
+
+ pCurParseNode = dpParsingTreeTop;
+ WTT_Node * pBranch = 0;
+ char cBranch = 0;
+
+ for ( constr pOld = i_sOldString.GetBuffer();
+ *pOld != 0;
+ pOld++ )
+ {
+ cBranch = CalculateBranch(*pOld);
+ pBranch = pCurParseNode->GetNextNode(cBranch);
+ if (pBranch == 0 || pBranch == pUnknownAlpha)
+ {
+ pBranch = new WTT_Node(cBranch,0,pUnknownAlpha);
+ pCurParseNode->SetBranch(cBranch,pBranch);
+ }
+ pCurParseNode = pBranch;
+ } // end for
+ pCurParseNode->SetAsTokenToReplace(i_sReplaceString);
+}
+
+void
+WordTransTree::InitTransformation( const char * i_sInput,
+ UINT32 i_nInputLength,
+ UINT32 i_nOutputMaxLength )
+{
+ sInput = (const u_char *)i_sInput;
+ nInputLength = i_nInputLength;
+ pInputEnd = &sInput[i_nInputLength];
+
+ pInputCurTokenStart = sInput;
+ pInputPosition = sInput;
+
+ if (nOutputMaxLength < i_nOutputMaxLength)
+ {
+ if (sOutput != 0)
+ delete [] sOutput;
+ sOutput = new unsigned char[i_nOutputMaxLength];
+ nOutputMaxLength = i_nOutputMaxLength;
+ }
+ pOutputPosition = sOutput;
+}
+
+/** pInputCurTokenStart and CurParseNode are updated just when
+ starting this function. After its end they must not be changed
+ till this functon is called again.
+ Outside this function pInputPositon and pOutputPosition are both
+ on the first not transformed char in their respective array.
+**/
+WordTransTree::E_Result
+WordTransTree::TransformNextToken()
+{
+ pInputCurTokenStart = pInputPosition;
+ pCurParseNode = dpParsingTreeTop;
+ cCurHotkey = 0;
+ eCurResult = OK;
+
+ WTT_Node * pBranch = 0;
+ UINT8 cBranch = 0;
+
+ for ( pCurParseNode = dpParsingTreeTop;
+ pInputPosition != pInputEnd;
+ ++pInputPosition )
+ {
+ cBranch = CalculateBranch(*pInputPosition);
+ pBranch = pCurParseNode->GetNextNode( cBranch );
+ if (pBranch != 0)
+ {
+ pCurParseNode = pBranch;
+ }
+ else
+ {
+ if (cBranch == BR_HOTKEY) // current letter is '~' or '&'.
+ {
+ // Logic of the following. There are 9 possible cases -
+ // A = alphabetic letter, NA = non alphabetic, TB = token begin,
+ // Eot = end of text:
+ // 1. A~A set hotkey to following letter, continue
+ // 2. A~NA token end
+ // 3. A~Eot token end
+ // 4. NA~A token end
+ // 5. NA~NA continue
+ // 6. A~Eof continue
+ // 7. TB~A set hotkey to following letter, continue
+ // 8. TB~NA continue
+ // 9. TB~Eot continue
+
+ // bNext and Prev are true, if there are alphabetic letters:
+ BOOL bNext = pInputPosition + 1 != pInputEnd
+ ? CalculateBranch(pInputPosition[1]) >= BR_ALPHABASE
+ : FALSE;
+ BOOL bPrev = pCurParseNode->Value() >= BR_ALPHABASE;
+
+ if ( bNext && (bPrev || pCurParseNode == dpParsingTreeTop) )
+ { // case 1. and 7.
+ Handle_Hotkey();
+ continue;
+ }
+ else if (!bPrev && !bNext)
+ { // case 5.,6.,8.,9.
+ continue;
+ }
+
+ // Case 2.,3.,4. :
+ // so this should be handled as an end of a token.
+ }
+ if (pCurParseNode->TokenType() == WTT_Node::token_to_keep)
+ {
+ Handle_TokenToKeep();
+ return eCurResult;
+ }
+ else
+ {
+ Handle_TokenToTransform();
+ return eCurResult;
+ } // endif (pCurParseNode->TokenType() == WTT_Node::token_to_keep)
+ } // endif (pBranch == 0) else
+ } // end for
+
+ // If here, the text end is reached
+ if (pCurParseNode->TokenType() == WTT_Node::token_to_keep)
+ {
+ Handle_TokenToKeep();
+ return eCurResult;
+ }
+ else
+ {
+ Handle_TokenToTransform();
+ return eCurResult;
+ }
+}
+
+ByteString
+WordTransTree::CurReplacingString() const
+{
+ return pCurParseNode->ReplaceString();
+}
+
+void
+WordTransTree::Handle_Hotkey()
+{
+ if (cCurHotkey == 0) // Avoid to replace the first found hotkey by
+ // a later one - though this shouldn't happen anyway.
+ {
+ cCurHotkey = (pInputPosition+1) != pInputEnd ? pInputPosition[1] : 0;
+ cCurHotkeySign = *pInputPosition;
+ }
+}
+
+void
+WordTransTree::Handle_TokenToKeep()
+{
+ UINT32 nTokenLength = pInputPosition-pInputCurTokenStart;
+
+ memcpy(pOutputPosition,pInputCurTokenStart,nTokenLength);
+
+ pOutputPosition += nTokenLength;
+ *pOutputPosition = '\0';
+}
+
+void
+WordTransTree::Handle_TokenToTransform()
+{
+ BOOL bHaveHotkey = CalculateBranch(cCurHotkey) >= BR_ALPHABASE;
+ const ByteString & rReplace = pCurParseNode->ReplaceString();
+
+ // Find position of hotkey in replace-string:
+ USHORT nHotkeyPos = bHaveHotkey
+ ? rReplace.Search(char(cCurHotkey))
+ : STRING_NOTFOUND;
+ if (nHotkeyPos == STRING_NOTFOUND && bHaveHotkey)
+ {
+ if (cCurHotkey < 128)
+ {
+ if (islower(cCurHotkey))
+ nHotkeyPos = rReplace.Search(toupper(char(cCurHotkey)));
+ else
+ nHotkeyPos = rReplace.Search(tolower(char(cCurHotkey)));
+ }
+ else // cCurHotkey >= 128
+ {
+ if (cCurHotkey == c_ae)
+ nHotkeyPos = rReplace.Search(char(c_AE));
+ else if (cCurHotkey == c_oe)
+ nHotkeyPos = rReplace.Search(char(c_OE));
+ else if (cCurHotkey == c_ue)
+ nHotkeyPos = rReplace.Search(char(c_UE));
+ else if (cCurHotkey == c_AE)
+ nHotkeyPos = rReplace.Search(char(c_ae));
+ else if (cCurHotkey == c_OE)
+ nHotkeyPos = rReplace.Search(char(c_oe));
+ else if (cCurHotkey == c_UE)
+ nHotkeyPos = rReplace.Search(char(c_ue));
+ } // endif (cCurHotkey < 128) else
+
+ if (nHotkeyPos == STRING_NOTFOUND)
+ {
+ eCurResult = HOTKEY_LOST;
+ bHaveHotkey = FALSE;
+ }
+ } // endif (nHotkeyPos == STRING_NOT_FOUND && bHaveHotkey)
+
+
+ UINT32 nOutputTokenLength = rReplace.Len() + (bHaveHotkey ? 1 : 0);
+
+ if (bHaveHotkey)
+ {
+ memcpy( pOutputPosition,
+ pCurParseNode->ReplaceString().GetBuffer(),
+ nHotkeyPos );
+ *(pOutputPosition + nHotkeyPos) = cCurHotkeySign;
+ memcpy( pOutputPosition + nHotkeyPos + 1,
+ pCurParseNode->ReplaceString().GetBuffer() + nHotkeyPos,
+ nOutputTokenLength - nHotkeyPos - 1);
+ }
+ else
+ {
+ memcpy( pOutputPosition,
+ pCurParseNode->ReplaceString().GetBuffer(),
+ nOutputTokenLength );
+ }
+
+ // Convert first letter into upper if necessary:
+ u_char cInStart = CalculateBranch(*pInputCurTokenStart) == BR_HOTKEY
+ ? pInputCurTokenStart[1]
+ : pInputCurTokenStart[0] ;
+ u_char * pOutStart = nHotkeyPos == 0
+ ? pOutputPosition + 1
+ : pOutputPosition ;
+ if (isupper(cInStart) || cInStart > 127)
+ { // Possibly cInStart is upper character:
+ if (isupper(cInStart) || cInStart == c_AE || cInStart == c_OE || cInStart == c_UE)
+ { // Surely cInStart is upper character:
+ u_char cOutStart = *pOutStart;
+ if (cOutStart < 128)
+ *pOutStart = toupper(cOutStart);
+ else if (cOutStart == c_ae)
+ *pOutStart = c_AE;
+ else if (cOutStart == c_oe)
+ *pOutStart = c_OE;
+ else if (cOutStart == c_ue)
+ *pOutStart = c_UE;
+ }
+ } // endif (isupper(cInStart) || cInStart > 127)
+
+ pOutputPosition += nOutputTokenLength;
+ *pOutputPosition = '\0';
+}
+
diff --git a/l10ntools/source/xgfconv.cxx b/l10ntools/source/xgfconv.cxx
new file mode 100644
index 000000000000..54b92fb3c1c2
--- /dev/null
+++ b/l10ntools/source/xgfconv.cxx
@@ -0,0 +1,66 @@
+#include <stdio.h>
+
+#include "export.hxx"
+#include "utf8conv.hxx"
+
+/*****************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#if defined(UNX) || defined(OS2)
+int main( int argc, char *argv[] )
+#else
+int _cdecl main( int argc, char *argv[] )
+#endif
+/*****************************************************************************/
+{
+ if ( argc != 3 ) {
+ fprintf( stderr, "xgfconv InputFile OutputFile\n" );
+ return ( 5 );
+ }
+
+ ByteString sInput( argv[ 1 ] );
+ ByteString sOutput( argv[ 2 ] );
+
+ SvFileStream aInput( String( sInput, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ );
+ if ( !aInput.IsOpen()) {
+ fprintf( stderr, "ERROR: Unable to open input file!\n" );
+ return ( 5 );
+ }
+
+ SvFileStream aOutput( String( sOutput, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_WRITE | STREAM_TRUNC );
+ if ( !aOutput.IsOpen()) {
+ fprintf( stderr, "ERROR: Unable to open output file!\n" );
+ aInput.Close();
+ return ( 5 );
+ }
+
+ ByteString sLine;
+ BOOL bFirst = TRUE;
+ while ( !aInput.IsEof()) {
+ aInput.ReadLine( sLine );
+ ByteString sLangId = sLine.GetToken( 0, '\t' );
+ ByteString sFile = sLine.GetToken( 1, '\t' );
+ ByteString sText = sLine.Copy( sLangId.Len() + sFile.Len() + 2 );
+
+ USHORT nLangId = sLangId.ToInt32();
+ CharSet aCharSet = Export::GetCharSet( nLangId );
+ if ( aCharSet != 0xFFFF && sText.Len()) {
+ sText = UTF8Converter::ConvertToUTF8( sText, aCharSet );
+ ByteString sOutput = sFile;
+ sOutput += "\t";
+ sOutput += sText;
+ if ( !bFirst ) {
+ ByteString sEmpty;
+ aOutput.WriteLine( sEmpty );
+ }
+ else
+ bFirst = FALSE;
+ aOutput.Write( sOutput.GetBuffer(), sOutput.Len());
+ }
+ }
+ aInput.Close();
+ aOutput.Close();
+ return ( 0 );
+}
+
diff --git a/l10ntools/source/xmlparse.cxx b/l10ntools/source/xmlparse.cxx
new file mode 100644
index 000000000000..f75a0afe9792
--- /dev/null
+++ b/l10ntools/source/xmlparse.cxx
@@ -0,0 +1,1456 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: xmlparse.cxx,v $
+ * $Revision: 1.24 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <iterator> /* std::iterator*/
+
+#include <stdio.h>
+#include <sal/alloca.h>
+
+#include "xmlparse.hxx"
+#include <fstream>
+#include <iostream>
+#include <osl/mutex.hxx>
+#include <osl/thread.hxx>
+#ifdef __MINGW32__
+#include <tools/prewin.h>
+#include <tools/postwin.h>
+#endif
+using namespace std;
+using namespace osl;
+
+//
+// class XMLChildNode
+//
+
+/*****************************************************************************/
+XMLChildNode::XMLChildNode( XMLParentNode *pPar )
+/*****************************************************************************/
+ : pParent( pPar )
+{
+ if ( pParent )
+ pParent->AddChild( this );
+}
+
+
+/*****************************************************************************/
+XMLChildNode::XMLChildNode( const XMLChildNode& obj)
+/*****************************************************************************/
+: XMLNode(obj),
+ pParent(obj.pParent){}
+
+/*****************************************************************************/
+XMLChildNode& XMLChildNode::operator=(const XMLChildNode& obj){
+/*****************************************************************************/
+ if(this != &obj){
+ pParent=obj.pParent;
+ }
+ return *this;
+}
+//
+// class XMLParentNode
+//
+
+
+/*****************************************************************************/
+XMLParentNode::~XMLParentNode()
+/*****************************************************************************/
+{
+ if( pChildList ){
+ RemoveAndDeleteAllChilds();
+ delete pChildList;
+ pChildList = NULL;
+ }
+ pChildList = NULL;
+}
+/*****************************************************************************/
+XMLParentNode::XMLParentNode( const XMLParentNode& obj)
+/*****************************************************************************/
+: XMLChildNode( obj )
+{
+ if( obj.pChildList ){
+ pChildList=new XMLChildNodeList();
+ XMLChildNode* pNode = NULL;
+ for ( ULONG i = 0; i < obj.pChildList->Count(); i++ ){
+ pNode = obj.pChildList->GetObject( i );
+ if( pNode != NULL){
+ switch(pNode->GetNodeType()){
+ case XML_NODE_TYPE_ELEMENT:
+ AddChild( new XMLElement( *static_cast<XMLElement* >(pNode) ) ); break;
+ case XML_NODE_TYPE_DATA:
+ AddChild( new XMLData ( *static_cast<XMLData* > (pNode) ) ); break;
+ case XML_NODE_TYPE_COMMENT:
+ AddChild( new XMLComment( *static_cast<XMLComment* >(pNode) ) ); break;
+ case XML_NODE_TYPE_DEFAULT:
+ AddChild( new XMLDefault( *static_cast<XMLDefault* >(pNode) ) ); break;
+ default: fprintf(stdout,"XMLParentNode::XMLParentNode( const XMLParentNode& obj) strange obj");
+ }
+ }
+ }
+ }else pChildList = NULL;
+}
+/*****************************************************************************/
+XMLParentNode& XMLParentNode::operator=(const XMLParentNode& obj){
+/*****************************************************************************/
+ if(this!=&obj){
+ XMLChildNode::operator=(obj);
+ if( pChildList ){
+ RemoveAndDeleteAllChilds();
+ delete pChildList;
+ pChildList = NULL;
+ }
+ if( obj.pChildList ){
+ pChildList=new XMLChildNodeList();
+ for ( ULONG i = 0; i < obj.pChildList->Count(); i++ )
+ AddChild( obj.pChildList->GetObject( i ) );
+ }else pChildList = NULL;
+
+ }
+ return *this;
+}
+/*****************************************************************************/
+void XMLParentNode::AddChild( XMLChildNode *pChild )
+/*****************************************************************************/
+{
+ if ( !pChildList )
+ pChildList = new XMLChildNodeList();
+ pChildList->Insert( pChild, LIST_APPEND );
+}
+
+/*****************************************************************************/
+void XMLParentNode::AddChild( XMLChildNode *pChild , int pos )
+/*****************************************************************************/
+{
+ if ( !pChildList )
+ pChildList = new XMLChildNodeList();
+ pChildList->Insert( pChild, pos );
+}
+
+/*****************************************************************************/
+int XMLParentNode::GetPosition( ByteString id ){
+/*****************************************************************************/
+ XMLElement* a;
+
+ static const ByteString sEnusStr = ByteString(String::CreateFromAscii(ENGLISH_US_ISO).ToLowerAscii() , RTL_TEXTENCODING_ASCII_US ).ToLowerAscii();
+ static const ByteString sDeStr = ByteString(String::CreateFromAscii(GERMAN_ISO2).ToLowerAscii() , RTL_TEXTENCODING_ASCII_US ).ToLowerAscii();
+
+ if ( pChildList ){
+ for ( ULONG i = 0; i < pChildList->Count(); i++ ) {
+ XMLChildNode *pChild = pChildList->GetObject( i );
+ if ( pChild->GetNodeType() == XML_NODE_TYPE_ELEMENT ){
+ a = static_cast<XMLElement* >(pChild);
+ ByteString elemid( a->GetId() );
+ elemid.ToLowerAscii();
+ if ( elemid.Equals( id.ToLowerAscii() ) ){
+ ByteString elemLID( a->GetLanguageId() );
+ elemLID.ToLowerAscii();
+ if( elemLID.Equals( sEnusStr) ) {
+ return i;
+ }
+ else if( elemLID.Equals( sDeStr) ) {
+ return i;
+ }
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+/*****************************************************************************/
+int XMLParentNode::RemoveChild( XMLElement *pRefElement )
+/*****************************************************************************/
+{
+ XMLElement* a;
+ if ( pChildList ){
+ for ( ULONG i = 0; i < pChildList->Count(); i++ ) {
+ XMLChildNode *pChild = pChildList->GetObject( i );
+ if ( pChild->GetNodeType() == XML_NODE_TYPE_ELEMENT ){
+ a = static_cast<XMLElement* >(pChild);
+ ByteString elemid( a->GetId() );
+ elemid.ToLowerAscii();
+ ByteString elemLID( a->GetLanguageId() );
+ elemLID.ToLowerAscii();
+ ByteString pRefLID( pRefElement->GetLanguageId() );
+ pRefLID.ToLowerAscii();
+ if ( elemid.Equals(pRefElement->GetId())
+ && elemLID.Equals( pRefLID ) )
+ {
+ if( pRefElement->ToOString().compareTo( a->ToOString() )==0 ){
+ pChildList->Remove( i );
+ delete a; // Test
+ return i;
+ }
+ }
+ }
+
+ }
+ }
+ return -1;
+}
+
+/*****************************************************************************/
+void XMLParentNode::RemoveAndDeleteAllChilds(){
+/*****************************************************************************/
+ if ( pChildList ) {
+ for ( ULONG i = 0; i < pChildList->Count(); i++ )
+ delete pChildList->GetObject( i );
+ pChildList->Clear();
+ }
+}
+
+/*****************************************************************************/
+XMLElement *XMLParentNode::GetChildElement( XMLElement *pRefElement )
+/*****************************************************************************/
+{
+ for ( ULONG i = 0; i < pChildList->Count(); i++ ) {
+ XMLChildNode *pChild = pChildList->GetObject( i );
+ if ( pChild->GetNodeType() == XML_NODE_TYPE_ELEMENT )
+ if ((( XMLElement * ) pChild )->GetName() ==
+ pRefElement->GetName())
+ {
+ XMLAttributeList *pList = pRefElement->GetAttributeList();
+ if ( !pList )
+ return ( XMLElement * ) pChild;
+
+ BOOL bMatch = FALSE;
+ for ( ULONG j = 0; j < pList->Count() && bMatch; j++ ) {
+ XMLAttribute *pAttribute = pList->GetObject( j );
+ XMLAttribute *pCandidate =
+ (( XMLElement * ) pChild )->GetAttribute(
+ *pAttribute );
+ if ( !pCandidate || !pAttribute->IsEqual( *pCandidate ))
+ bMatch = FALSE;
+ }
+ if ( bMatch )
+ return ( XMLElement * ) pChild;
+ }
+ }
+ return NULL;
+}
+
+//
+// class XMLFile
+//
+
+/*****************************************************************************/
+USHORT XMLFile::GetNodeType()
+/*****************************************************************************/
+{
+ return XML_NODE_TYPE_FILE;
+}
+
+/*****************************************************************************/
+BOOL XMLFile::Write( ByteString &aFilename )
+/*****************************************************************************/
+{
+
+ if ( aFilename.Len()) {
+ // retry harder if there is a NFS problem,
+ for( int x = 1 ; x < 3 ; x++ ){ // this looks strange...yes!
+ ofstream aFStream( aFilename.GetBuffer() , ios::out | ios::trunc );
+
+ if( !aFStream ) // From time to time the stream can not be opened the first time on NFS volumes,
+ { // I wasn't able to track this down. I think this is an NFS issue .....
+ //cerr << "ERROR: - helpex - Can't write to tempfile " << aFilename.GetBuffer() << " No#" << x << "\n";
+ TimeValue aTime;
+ aTime.Seconds = 3;
+ aTime.Nanosec = 0;
+
+ osl::Thread::wait( aTime );
+ }
+ else
+ {
+ // write out
+ Write( aFStream );
+ aFStream.close();
+
+ // check!
+ DirEntry aTarget( aFilename );
+ FileStat aFileStat( aTarget );
+
+ if( aFileStat.GetSize() < 1 )
+ {
+ //retry
+ //cerr << "WARNING: - helpex - Can't create file " << aFilename.GetBuffer() << " No#" << x << "\n";
+ aTarget.Kill();
+ }
+ else
+ {
+ //everything ok!
+ return true;
+ }
+ }
+ }
+ cerr << "ERROR: - helpex - Can't create file " << aFilename.GetBuffer() << "\nPossible reason: Disk full ? Mounted NFS volume broken ? Wrong permissions ?\n";
+ exit( -1 );
+ }
+ cerr << "ERROR: - helpex - Empty file name\n";
+ exit( -1 );
+}
+
+
+
+void XMLFile::WriteString( ofstream &rStream, const String &sString )
+{
+ ByteString sText( sString, RTL_TEXTENCODING_UTF8 );
+ rStream << sText.GetBuffer();
+}
+
+
+BOOL XMLFile::Write( ofstream &rStream , XMLNode *pCur )
+{
+ XMLUtil& xmlutil = XMLUtil::Instance();
+ (void) xmlutil;
+
+ if ( !pCur )
+ Write( rStream, this );
+ else {
+ switch( pCur->GetNodeType()) {
+ case XML_NODE_TYPE_FILE: {
+ if( GetChildList())
+ for ( ULONG i = 0; i < GetChildList()->Count(); i++ )
+ Write( rStream, GetChildList()->GetObject( i ));
+ }
+ break;
+ case XML_NODE_TYPE_ELEMENT: {
+ XMLElement *pElement = ( XMLElement * ) pCur;
+ rStream << "<";
+ WriteString( rStream, pElement->GetName());
+ if ( pElement->GetAttributeList())
+ for ( ULONG j = 0; j < pElement->GetAttributeList()->Count(); j++ ) {
+ rStream << " ";
+ String sData(*pElement->GetAttributeList()->GetObject( j ));
+ xmlutil.QuotHTML( sData );
+ WriteString( rStream , sData );
+ rStream << "=\"";
+ sData=pElement->GetAttributeList()->GetObject( j )->GetValue();
+ xmlutil.QuotHTML( sData );
+ WriteString( rStream , sData );
+ rStream << "\"";
+ }
+ if ( !pElement->GetChildList())
+ rStream << "/>";
+ else {
+ rStream << ">";
+ for ( ULONG k = 0; k < pElement->GetChildList()->Count(); k++ )
+ Write( rStream, pElement->GetChildList()->GetObject( k ));
+ rStream << "</";
+ WriteString( rStream, pElement->GetName());
+ rStream << ">";
+ }
+ }
+ break;
+ case XML_NODE_TYPE_DATA: {
+ XMLData *pData = ( XMLData * ) pCur;
+ String sData( pData->GetData());
+ xmlutil.QuotHTML( sData );
+ WriteString( rStream, sData );
+ }
+ break;
+ case XML_NODE_TYPE_COMMENT: {
+ XMLComment *pComment = ( XMLComment * ) pCur;
+ rStream << "<!--";
+ WriteString( rStream, pComment->GetComment());
+ rStream << "-->";
+ }
+ break;
+ case XML_NODE_TYPE_DEFAULT: {
+ XMLDefault *pDefault = ( XMLDefault * ) pCur;
+ WriteString( rStream, pDefault->GetDefault());
+ }
+ break;
+ }
+ }
+ return TRUE;
+}
+
+
+void XMLFile::Print( XMLNode *pCur, USHORT nLevel )
+{
+
+ if ( !pCur )
+ Print( this );
+ else {
+ switch( pCur->GetNodeType()) {
+ case XML_NODE_TYPE_FILE: {
+ if( GetChildList())
+ for ( ULONG i = 0; i < GetChildList()->Count(); i++ )
+ Print( GetChildList()->GetObject( i ));
+ }
+ break;
+ case XML_NODE_TYPE_ELEMENT: {
+ XMLElement *pElement = ( XMLElement * ) pCur;
+
+ fprintf( stdout, "<%s", ByteString( pElement->GetName(), RTL_TEXTENCODING_UTF8 ).GetBuffer());
+ if ( pElement->GetAttributeList())
+ for ( ULONG j = 0; j < pElement->GetAttributeList()->Count(); j++ ){
+ ByteString aAttrName( *pElement->GetAttributeList()->GetObject( j ), RTL_TEXTENCODING_UTF8 );
+ if( !aAttrName.EqualsIgnoreCaseAscii( XML_LANG ) ) {
+ fprintf( stdout, " %s=\"%s\"",
+ aAttrName.GetBuffer(),
+ ByteString( pElement->GetAttributeList()->GetObject( j )->GetValue(),
+ RTL_TEXTENCODING_UTF8 ).GetBuffer());
+ }
+ }
+ if ( !pElement->GetChildList())
+ fprintf( stdout, "/>" );
+ else {
+ fprintf( stdout, ">" );
+ for ( ULONG k = 0; k < pElement->GetChildList()->Count(); k++ )
+ Print( pElement->GetChildList()->GetObject( k ), nLevel + 1 );
+ fprintf( stdout, "</%s>", ByteString( pElement->GetName(), RTL_TEXTENCODING_UTF8 ).GetBuffer());
+ }
+ }
+ break;
+ case XML_NODE_TYPE_DATA: {
+ XMLData *pData = ( XMLData * ) pCur;
+ String sData = pData->GetData();
+ fprintf( stdout, "%s", ByteString( sData, RTL_TEXTENCODING_UTF8 ).GetBuffer());
+ }
+ break;
+ case XML_NODE_TYPE_COMMENT: {
+ XMLComment *pComment = ( XMLComment * ) pCur;
+ fprintf( stdout, "<!--%s-->", ByteString( pComment->GetComment(), RTL_TEXTENCODING_UTF8 ).GetBuffer());
+ }
+ break;
+ case XML_NODE_TYPE_DEFAULT: {
+ XMLDefault *pDefault = ( XMLDefault * ) pCur;
+ fprintf( stdout, "%s", ByteString( pDefault->GetDefault(), RTL_TEXTENCODING_UTF8 ).GetBuffer());
+ }
+ break;
+ }
+ }
+}
+XMLFile::~XMLFile()
+{
+ if( XMLStrings != NULL ){
+ XMLHashMap::iterator pos = XMLStrings->begin();
+ for( ; pos != XMLStrings->end() ; ++pos ){
+ delete pos->second; // Check and delete content also ?
+ }
+ delete XMLStrings;
+ XMLStrings = NULL;
+ }
+}
+/*****************************************************************************/
+XMLFile::XMLFile( const String &rFileName ) // the file name, empty if created from memory stream
+/*****************************************************************************/
+ : XMLParentNode( NULL ),
+ sFileName ( rFileName ),
+ ID ( "id" ),
+ OLDREF ( "oldref" ),
+ XML_LANG ( "xml-lang" ),
+ XMLStrings ( NULL )
+
+{
+// nodes_localize.insert( TagMap::value_type(ByteString(String::CreateFromAscii("bookmark_value"),RTL_TEXTENCODING_ASCII_US) , TRUE) );
+ nodes_localize.insert( TagMap::value_type(ByteString(String::CreateFromAscii("bookmark"),RTL_TEXTENCODING_ASCII_US) , TRUE) );
+ nodes_localize.insert( TagMap::value_type(ByteString(String::CreateFromAscii("variable"),RTL_TEXTENCODING_ASCII_US) , TRUE) );
+ nodes_localize.insert( TagMap::value_type(ByteString(String::CreateFromAscii("paragraph"),RTL_TEXTENCODING_ASCII_US) , TRUE) );
+ nodes_localize.insert( TagMap::value_type(ByteString(String::CreateFromAscii("alt"),RTL_TEXTENCODING_ASCII_US) , TRUE) );
+ nodes_localize.insert( TagMap::value_type(ByteString(String::CreateFromAscii("caption"),RTL_TEXTENCODING_ASCII_US) , TRUE) );
+ nodes_localize.insert( TagMap::value_type(ByteString(String::CreateFromAscii("title"),RTL_TEXTENCODING_ASCII_US) , TRUE) );
+ nodes_localize.insert( TagMap::value_type(ByteString(String::CreateFromAscii("link"),RTL_TEXTENCODING_ASCII_US) , TRUE) );
+}
+/*****************************************************************************/
+void XMLFile::Extract( XMLFile *pCur )
+/*****************************************************************************/
+{
+ if( XMLStrings != NULL ) delete XMLStrings; // Elements ?
+
+ XMLStrings = new XMLHashMap();
+ if ( !pCur )
+ SearchL10NElements( this );
+ else {
+ if( pCur->GetNodeType()==XML_NODE_TYPE_FILE) {
+ SearchL10NElements(pCur);
+ }
+ }
+}
+
+/*****************************************************************************/
+void XMLFile::View(){
+/*****************************************************************************/
+ XMLElement* cur;
+ for(XMLHashMap::iterator pos=XMLStrings->begin(); pos!=XMLStrings->end();++pos){
+ fprintf(stdout,"\nid=%s\n",(pos->first).GetBuffer());
+ LangHashMap* elem=pos->second;
+ for(LangHashMap::iterator pos2=elem->begin(); pos2!=elem->end();++pos2){
+ fprintf( stdout,"\nlanguage=%s\n",(pos2->first).GetBuffer() );
+ cur=pos2->second;
+ fprintf(stdout,"\n%s\n",((XMLElement*)cur)->ToOString().getStr());
+
+ }
+ }
+}
+
+/*****************************************************************************/
+void XMLFile::InsertL10NElement( XMLElement* pElement ){
+/*****************************************************************************/
+ ByteString tmpStr,id,oldref,language("");
+ LangHashMap* elem;
+
+ if( pElement->GetAttributeList() != NULL ){
+ for ( ULONG j = 0; j < pElement->GetAttributeList()->Count(); j++ ){
+ tmpStr=ByteString( *pElement->GetAttributeList()->GetObject( j ),RTL_TEXTENCODING_UTF8 );
+ if( tmpStr.CompareTo(ID)==COMPARE_EQUAL ){ // Get the "id" Attribute
+ id = ByteString( pElement->GetAttributeList()->GetObject( j )->GetValue(),RTL_TEXTENCODING_UTF8 );
+ }
+ if( tmpStr.CompareTo( XML_LANG ) == COMPARE_EQUAL ){ // Get the "xml-lang" Attribute
+ language = ByteString( pElement->GetAttributeList()->GetObject( j )->GetValue(),RTL_TEXTENCODING_UTF8 );
+ }
+
+ }
+ }else{
+ fprintf(stdout,"XMLFile::InsertL10NElement: No AttributeList found");
+ fprintf(stdout,"++++++++++++++++++++++++++++++++++++++++++++++++++");
+ Print( pElement , 0 );
+ fprintf(stdout,"++++++++++++++++++++++++++++++++++++++++++++++++++");
+ }
+
+ XMLHashMap::iterator pos = XMLStrings->find( id );
+ if( pos == XMLStrings->end() ){ // No instanze , create new one
+ elem = new LangHashMap();
+ (*elem)[ language ]=pElement;
+ XMLStrings->insert( XMLHashMap::value_type( id , elem ) );
+ order.push_back( id );
+ }else{ // Already there
+ elem=pos->second;
+ if ( (*elem)[ language ] )
+ {
+ fprintf(stdout,"Error: Duplicated entry. ID = %s LANG = %s in File %s\n", id.GetBuffer(), language.GetBuffer(), ByteString( sFullName,RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
+ exit( -1 );
+ }
+ (*elem)[ language ]=pElement;
+ }
+}
+/*****************************************************************************/
+void XMLFile::showType(XMLParentNode* node){
+/*****************************************************************************/
+ switch (node->GetNodeType()){
+ case XML_NODE_TYPE_ELEMENT: fprintf(stdout,"ELEMENT\n") ;break;
+ case XML_NODE_TYPE_FILE: fprintf(stdout,"FILE\n") ;break;
+ case XML_NODE_TYPE_COMMENT: fprintf(stdout,"COMMENT\n") ;break;
+ case XML_NODE_TYPE_DATA: fprintf(stdout,"DATA\n") ;break;
+ case XML_NODE_TYPE_DEFAULT: fprintf(stdout,"DEFAULT\n") ;break;
+ default: break;
+ }
+}
+XMLFile::XMLFile()
+/*****************************************************************************/
+ : XMLParentNode( NULL ),
+ ID ( "id" ),
+ OLDREF ( "oldref" ),
+ XML_LANG ( "xml-lang" ),
+ XMLStrings ( NULL ){};
+
+
+XMLFile::XMLFile( const XMLFile& obj )
+/*****************************************************************************/
+ : XMLParentNode( obj ),
+ sFileName ( obj.sFileName ),
+ ID ( "id" ),
+ OLDREF ( "oldref" ),
+ XML_LANG ( "xml-lang" ),
+ XMLStrings ( NULL )
+{
+ if( this!=&obj )
+ {
+ nodes_localize =obj.nodes_localize;
+ order =obj.order;
+
+ }
+}
+/*****************************************************************************/
+XMLFile& XMLFile::operator=(const XMLFile& obj){
+/*****************************************************************************/
+ if( this!=&obj ){
+
+ XMLParentNode::operator=(obj);
+
+ nodes_localize =obj.nodes_localize;
+ order =obj.order;
+
+ if( XMLStrings ) delete XMLStrings;
+
+ if( obj.XMLStrings )
+ {
+ XMLStrings = new XMLHashMap();
+ for( XMLHashMap::iterator pos = obj.XMLStrings->begin() ; pos != obj.XMLStrings->end() ; ++pos )
+ {
+ LangHashMap* elem=pos->second;
+ LangHashMap* newelem = new LangHashMap();
+ for(LangHashMap::iterator pos2=elem->begin(); pos2!=elem->end();++pos2){
+ (*newelem)[ pos2->first ] = new XMLElement( *pos2->second );
+ printf("*");
+ }
+ (*XMLStrings)[ pos->first ] = newelem;
+ }
+ }
+ }
+ printf("done!\n");
+ return *this;
+}
+
+
+/*****************************************************************************/
+void XMLFile::SearchL10NElements( XMLParentNode *pCur , int pos)
+/*****************************************************************************/
+{
+ static const ByteString LOCALIZE("localize");
+ static const ByteString THEID("id");
+ bool bInsert = true;
+ if ( !pCur )
+ SearchL10NElements( this );
+ else {
+ switch( pCur->GetNodeType()) {
+ case XML_NODE_TYPE_FILE: {
+ XMLParentNode* pElement;
+ if( GetChildList()){
+ for ( ULONG i = 0; i < GetChildList()->Count(); i++ ){
+ pElement = (XMLParentNode*) GetChildList()->GetObject( i );
+ if( pElement->GetNodeType() == XML_NODE_TYPE_ELEMENT ) SearchL10NElements( pElement , i);
+ }
+ }
+ }
+ break;
+ case XML_NODE_TYPE_ELEMENT: {
+ XMLElement *pElement = ( XMLElement * ) pCur;
+ ByteString sName(pElement->GetName(),RTL_TEXTENCODING_ASCII_US);
+ ByteString language,tmpStrVal,oldref;
+ if ( pElement->GetAttributeList()){
+ for ( ULONG j = 0 , cnt = pElement->GetAttributeList()->Count(); j < cnt && bInsert; j++ ){
+ const ByteString tmpStr( *pElement->GetAttributeList()->GetObject( j ),RTL_TEXTENCODING_UTF8 );
+ if( tmpStr.CompareTo(THEID)==COMPARE_EQUAL ){ // Get the "id" Attribute
+ tmpStrVal=ByteString( pElement->GetAttributeList()->GetObject( j )->GetValue(),RTL_TEXTENCODING_UTF8 );
+ //printf("Checking id = %s\n",tmpStrVal.GetBuffer() );
+ }
+ if( tmpStr.CompareTo(LOCALIZE)==COMPARE_EQUAL ){ // Get the "localize" Attribute
+ bInsert=false;
+ }
+ if( tmpStr.CompareTo(XML_LANG)==COMPARE_EQUAL ){ // Get the "xml-lang" Attribute
+ language=ByteString( pElement->GetAttributeList()->GetObject( j )->GetValue(),RTL_TEXTENCODING_UTF8 );
+ }
+ if( tmpStr.CompareTo(OLDREF)==COMPARE_EQUAL ){ // Get the "oldref" Attribute
+ oldref=ByteString( pElement->GetAttributeList()->GetObject( j )->GetValue(),RTL_TEXTENCODING_UTF8 );
+ }
+ }
+ pElement->SetLanguageId ( language );
+ pElement->SetId ( tmpStrVal.GetBuffer() );
+ pElement->SetOldRef ( oldref );
+ pElement->SetPos( pos );
+ }
+
+ if ( bInsert && ( nodes_localize.find( sName.ToLowerAscii() ) != nodes_localize.end() ) )
+ InsertL10NElement(pElement);
+ else if ( bInsert && pElement->GetChildList() ){
+ for ( ULONG k = 0; k < pElement->GetChildList()->Count(); k++ )
+ SearchL10NElements( (XMLParentNode*) pElement->GetChildList()->GetObject( k ) , k);
+ }
+ }
+ break;
+ case XML_NODE_TYPE_DATA: {
+ }
+ break;
+ case XML_NODE_TYPE_COMMENT: {
+ }
+ break;
+ case XML_NODE_TYPE_DEFAULT: {
+ }
+ break;
+ }
+ }
+}
+
+/*****************************************************************************/
+bool XMLFile::CheckExportStatus( XMLParentNode *pCur )
+/*****************************************************************************/
+{
+ static bool bStatusExport = true;
+ const ByteString LOCALIZE("localize");
+ const ByteString STATUS("status");
+ const ByteString PUBLISH("PUBLISH");
+ const ByteString DEPRECATED("DEPRECATED");
+
+ const ByteString TOPIC("topic");
+ bool bInsert = true;
+ if ( !pCur )
+ CheckExportStatus( this );
+ else {
+ switch( pCur->GetNodeType()) {
+ case XML_NODE_TYPE_FILE: {
+ XMLParentNode* pElement;
+ if( GetChildList()){
+ for ( ULONG i = 0; i < GetChildList()->Count(); i++ ){
+ pElement = (XMLParentNode*) GetChildList()->GetObject( i );
+ if( pElement->GetNodeType() == XML_NODE_TYPE_ELEMENT ) CheckExportStatus( pElement );//, i);
+ }
+ }
+ }
+ break;
+ case XML_NODE_TYPE_ELEMENT: {
+ XMLElement *pElement = ( XMLElement * ) pCur;
+ ByteString sName(pElement->GetName(),RTL_TEXTENCODING_ASCII_US);
+ if( sName.EqualsIgnoreCaseAscii( TOPIC ) ){
+ if ( pElement->GetAttributeList()){
+ for ( ULONG j = 0 , cnt = pElement->GetAttributeList()->Count(); j < cnt && bInsert; j++ ){
+ const ByteString tmpStr( *pElement->GetAttributeList()->GetObject( j ),RTL_TEXTENCODING_UTF8 );
+ if( tmpStr.EqualsIgnoreCaseAscii( STATUS ) ){
+ ByteString tmpStrVal=ByteString( pElement->GetAttributeList()->GetObject( j )->GetValue(),RTL_TEXTENCODING_UTF8 );
+ if( !tmpStrVal.EqualsIgnoreCaseAscii( PUBLISH ) &&
+ !tmpStrVal.EqualsIgnoreCaseAscii( DEPRECATED )){
+ bStatusExport = false;
+ }
+ }
+
+ }
+ }
+ }
+ else if ( pElement->GetChildList() ){
+ for ( ULONG k = 0; k < pElement->GetChildList()->Count(); k++ )
+ CheckExportStatus( (XMLParentNode*) pElement->GetChildList()->GetObject( k ) );//, k);
+ }
+ }
+ break;
+ }
+ }
+ return bStatusExport;
+}
+
+/*****************************************************************************/
+USHORT XMLElement::GetNodeType()
+/*****************************************************************************/
+{
+ return XML_NODE_TYPE_ELEMENT;
+}
+
+/*****************************************************************************/
+XMLElement::XMLElement(const XMLElement& obj)
+/*****************************************************************************/
+ :
+ XMLParentNode ( obj ),
+ sElementName ( obj.sElementName ),
+ pAttributes ( NULL ),
+ project ( obj.project ),
+ filename ( obj.filename ),
+ id ( obj.id ),
+ sOldRef ( obj.sOldRef ),
+ resourceType ( obj.resourceType ),
+ languageId ( obj.languageId ),
+ nPos ( obj.nPos )
+
+{
+ if ( obj.pAttributes ){
+ pAttributes = new XMLAttributeList();
+ for ( ULONG i = 0; i < obj.pAttributes->Count(); i++ )
+ AddAttribute( *obj.pAttributes->GetObject( i ) , obj.pAttributes->GetObject( i )->GetValue() );
+ }
+}
+
+/*****************************************************************************/
+XMLElement& XMLElement::operator=(const XMLElement& obj){
+/*****************************************************************************/
+ if( this!=&obj ){
+ XMLParentNode::operator=(obj);
+ sElementName =obj.sElementName;
+ project =obj.project;
+ filename =obj.filename;
+ id =obj.id;
+ sOldRef =obj.sOldRef;
+ resourceType =obj.resourceType;
+ languageId =obj.languageId;
+ nPos =obj.nPos;
+
+ if ( pAttributes ){
+ for ( ULONG i = 0; i < pAttributes->Count(); i++ )
+ delete pAttributes->GetObject( i );
+ delete pAttributes;
+ }
+ if ( obj.pAttributes ){
+ pAttributes =new XMLAttributeList();
+ for ( ULONG i = 0; i < obj.pAttributes->Count(); i++ )
+ AddAttribute( *obj.pAttributes->GetObject( i ) , obj.pAttributes->GetObject( i )->GetValue() );
+ }
+ }
+ return *this;
+}
+
+/*****************************************************************************/
+void XMLElement::AddAttribute( const String &rAttribute, const String &rValue )
+/*****************************************************************************/
+{
+ if ( !pAttributes )
+ pAttributes = new XMLAttributeList();
+ pAttributes->Insert( new XMLAttribute( rAttribute, rValue ), LIST_APPEND );
+}
+
+/*****************************************************************************/
+void XMLElement::ChangeLanguageTag( const String &rValue ){
+/*****************************************************************************/
+ static const String rName = String::CreateFromAscii("xml-lang");
+ SetLanguageId( ByteString(rValue,RTL_TEXTENCODING_UTF8) );
+ if ( pAttributes ){
+ for ( ULONG i = 0; i < pAttributes->Count(); i++ ){
+ if ( *pAttributes->GetObject( i ) == rName ){
+ pAttributes->GetObject( i )->setValue(rValue);
+ }
+ }
+ }
+ XMLChildNode* pNode = NULL;
+ XMLElement* pElem = NULL;
+ XMLChildNodeList* pCList = GetChildList();
+
+ if( pCList != NULL ){
+ for ( ULONG i = 0; i < pCList->Count(); i++ ){
+ pNode = pCList->GetObject( i );
+ if( pNode != NULL && pNode->GetNodeType() == XML_NODE_TYPE_ELEMENT ){
+ pElem = static_cast< XMLElement* >(pNode);
+ pElem->ChangeLanguageTag( rValue );
+ pElem->SetLanguageId( ByteString(rValue,RTL_TEXTENCODING_UTF8) );
+ pElem = NULL;
+ pNode = NULL;
+ }
+ }
+ pCList = NULL;
+ }
+}
+/*****************************************************************************/
+XMLAttribute *XMLElement::GetAttribute( const String &rName )
+/*****************************************************************************/
+{
+ if ( pAttributes )
+ for ( ULONG i = 0; i < pAttributes->Count(); i++ )
+ if ( *pAttributes->GetObject( i ) == rName )
+ return pAttributes->GetObject( i );
+
+ return NULL;
+}
+
+/*****************************************************************************/
+XMLElement::~XMLElement()
+/*****************************************************************************/
+{
+ if ( pAttributes ) {
+ for ( ULONG i = 0; i < pAttributes->Count(); i++ )
+ delete pAttributes->GetObject( i );
+
+ delete pAttributes;
+ pAttributes = NULL;
+ }
+}
+/*****************************************************************************/
+bool XMLElement::Equals(OUString refStr){
+/*****************************************************************************/
+ return refStr.equals( ToOUString() );
+}
+
+/*****************************************************************************/
+OString XMLElement::ToOString(){
+/*****************************************************************************/
+ OUString ouEmpty;
+
+ OUStringBuffer* buffer = new OUStringBuffer();
+ Print( this, *buffer , true );
+
+ OString result( (sal_Unicode* )buffer->getStr(), buffer->getLength() , RTL_TEXTENCODING_UTF8 );
+ delete buffer;
+ return result;
+}
+/*****************************************************************************/
+OUString XMLElement::ToOUString(){
+/*****************************************************************************/
+ OUStringBuffer* buffer = new OUStringBuffer();
+ Print(this,*buffer,true);
+ OUString result=buffer->makeStringAndClear();
+ String xy(result.getStr());
+ result=OUString(xy);
+ delete buffer;
+ return result;
+}
+/*****************************************************************************/
+void XMLElement::Print(XMLNode *pCur, OUStringBuffer& buffer , bool rootelement ){
+/*****************************************************************************/
+ //YD FIXME somewhere COMMENT is defined as 4!
+ static const String _COMMENT = String::CreateFromAscii("comment");
+ static const OUString XML_LANG ( OUString::createFromAscii("xml-lang") );
+
+ if(pCur!=NULL){
+ if(rootelement){
+ XMLElement *pElement = ( XMLElement * ) pCur;
+ if ( pElement->GetAttributeList()){
+ if ( pElement->GetChildList()){
+ XMLChildNode* tmp=NULL;
+ for ( ULONG k = 0; k < pElement->GetChildList()->Count(); k++ ){
+ tmp=pElement->GetChildList()->GetObject( k );
+ Print( tmp, buffer , false);
+ }
+ }
+ }
+ }
+ else{
+
+ switch( pCur->GetNodeType()) {
+ case XML_NODE_TYPE_ELEMENT: {
+ XMLElement *pElement = ( XMLElement * ) pCur;
+
+ if( !pElement->GetName().EqualsIgnoreCaseAscii( _COMMENT ) ){
+ buffer.append( OUString::createFromAscii("\\<") );
+ buffer.append( pElement->GetName() );
+ if ( pElement->GetAttributeList()){
+ for ( ULONG j = 0; j < pElement->GetAttributeList()->Count(); j++ ){
+
+ OUString aAttrName( *pElement->GetAttributeList()->GetObject( j ) );
+ if( !aAttrName.equalsIgnoreAsciiCase( XML_LANG ) ) {
+ buffer.append( OUString::createFromAscii(" ") );
+ buffer.append( aAttrName );
+ buffer.append( OUString::createFromAscii("=") );
+ buffer.append( OUString::createFromAscii("\\\"") );
+ buffer.append( pElement->GetAttributeList()->GetObject( j )->GetValue() );
+ buffer.append( OUString::createFromAscii("\\\"") );
+ }
+ }
+ }
+ if ( !pElement->GetChildList())
+ buffer.append( OUString::createFromAscii("/\\>") );
+ else {
+ buffer.append( OUString::createFromAscii("\\>") );
+ XMLChildNode* tmp=NULL;
+ for ( ULONG k = 0; k < pElement->GetChildList()->Count(); k++ ){
+ tmp=pElement->GetChildList()->GetObject( k );
+ Print( tmp, buffer , false);
+ }
+ buffer.append( OUString::createFromAscii("\\</") );
+ buffer.append( pElement->GetName() );
+ buffer.append( OUString::createFromAscii("\\>") );
+ }
+ }
+ }
+ break;
+ case XML_NODE_TYPE_DATA: {
+ XMLData *pData = ( XMLData * ) pCur;
+ String sData = pData->GetData();
+ buffer.append( sData );
+ }
+ break;
+ case XML_NODE_TYPE_COMMENT: {
+ XMLComment *pComment = ( XMLComment * ) pCur;
+ buffer.append( OUString::createFromAscii("<!--") );
+ buffer.append( pComment->GetComment() );
+ buffer.append( OUString::createFromAscii("-->") );
+ }
+ break;
+ case XML_NODE_TYPE_DEFAULT: {
+ XMLDefault *pDefault = ( XMLDefault * ) pCur;
+ buffer.append( pDefault->GetDefault() );
+ }
+ break;
+ }
+ }
+ }else {
+ fprintf(stdout,"\n#+------Error: NULL Pointer in XMLELement::Print------+#\n");
+ return;
+ }
+}
+
+
+//
+// class XMLData
+//
+/*****************************************************************************/
+XMLData::XMLData(const XMLData& obj)
+/*****************************************************************************/
+ : XMLChildNode( obj ),
+ sData( obj.sData ) ,
+ isNewCreated ( obj.isNewCreated ){}
+
+/*****************************************************************************/
+XMLData& XMLData::operator=(const XMLData& obj){
+/*****************************************************************************/
+ if( this!=&obj ){
+ XMLChildNode::operator=( obj );
+ sData = obj.sData;
+ isNewCreated = obj.isNewCreated;
+ }
+ return *this;
+}
+/*****************************************************************************/
+void XMLData::AddData( const String &rData) {
+/*****************************************************************************/
+ sData += rData;
+}
+
+/*****************************************************************************/
+USHORT XMLData::GetNodeType()
+/*****************************************************************************/
+{
+ return XML_NODE_TYPE_DATA;
+}
+
+//
+// class XMLComment
+//
+
+/*****************************************************************************/
+USHORT XMLComment::GetNodeType()
+/*****************************************************************************/
+{
+ return XML_NODE_TYPE_COMMENT;
+}
+/*****************************************************************************/
+XMLComment::XMLComment(const XMLComment& obj)
+/*****************************************************************************/
+ : XMLChildNode( obj ),
+ sComment( obj.sComment ){}
+
+/*****************************************************************************/
+XMLComment& XMLComment::operator=(const XMLComment& obj){
+/*****************************************************************************/
+ if( this!=&obj ){
+ XMLChildNode::operator=( obj );
+ sComment = obj.sComment;
+ }
+ return *this;
+}
+
+//
+// class XMLDefault
+//
+
+/*****************************************************************************/
+USHORT XMLDefault::GetNodeType()
+/*****************************************************************************/
+{
+ return XML_NODE_TYPE_DEFAULT;
+}
+/*****************************************************************************/
+XMLDefault::XMLDefault(const XMLDefault& obj)
+/*****************************************************************************/
+ : XMLChildNode( obj ),
+ sDefault( obj.sDefault){}
+
+/*****************************************************************************/
+XMLDefault& XMLDefault::operator=(const XMLDefault& obj){
+/*****************************************************************************/
+ if( this!=&obj ){
+ XMLChildNode::operator=( obj );
+ sDefault = obj.sDefault;
+ }
+ return *this;
+}
+
+
+//
+// class SimpleXMLParser
+//
+
+#define XML_CHAR_TO_OUSTRING(x) OStringToOUString(OString(x), RTL_TEXTENCODING_UTF8)
+#define XML_CHAR_N_TO_OUSTRING(x,n) OStringToOUString(OString(x,n), RTL_TEXTENCODING_UTF8 )
+
+
+/*****************************************************************************/
+SimpleXMLParser::SimpleXMLParser()
+/*****************************************************************************/
+ : pXMLFile( NULL )
+{
+ aParser = XML_ParserCreate( NULL );
+ XML_SetUserData( aParser, this );
+ XML_SetElementHandler( aParser, (XML_StartElementHandler) StartElementHandler, (XML_EndElementHandler) EndElementHandler );
+ XML_SetCharacterDataHandler( aParser, (XML_CharacterDataHandler) CharacterDataHandler );
+ XML_SetCommentHandler( aParser, (XML_CommentHandler) CommentHandler );
+ XML_SetDefaultHandler( aParser, (XML_DefaultHandler) DefaultHandler );
+}
+
+/*****************************************************************************/
+SimpleXMLParser::~SimpleXMLParser()
+/*****************************************************************************/
+{
+ XML_ParserFree( aParser );
+}
+
+/*****************************************************************************/
+void SimpleXMLParser::StartElementHandler(
+ void *userData, const XML_Char *name, const XML_Char **atts )
+/*****************************************************************************/
+{
+ (( SimpleXMLParser * ) userData )->StartElement( name, atts );
+}
+
+
+/*****************************************************************************/
+void SimpleXMLParser::EndElementHandler(
+ void *userData, const XML_Char *name )
+/*****************************************************************************/
+{
+ (( SimpleXMLParser * ) userData )->EndElement( name );
+}
+
+/*****************************************************************************/
+void SimpleXMLParser::CharacterDataHandler(
+ void *userData, const XML_Char *s, int len )
+/*****************************************************************************/
+{
+ (( SimpleXMLParser * ) userData )->CharacterData( s, len );
+}
+
+/*****************************************************************************/
+void SimpleXMLParser::CommentHandler(
+ void *userData, const XML_Char *data )
+/*****************************************************************************/
+{
+ (( SimpleXMLParser * ) userData )->Comment( data );
+}
+
+/*****************************************************************************/
+void SimpleXMLParser::DefaultHandler(
+ void *userData, const XML_Char *s, int len )
+/*****************************************************************************/
+{
+ (( SimpleXMLParser * ) userData )->Default( s, len );
+}
+
+/*****************************************************************************/
+void SimpleXMLParser::StartElement(
+ const XML_Char *name, const XML_Char **atts )
+/*****************************************************************************/
+{
+ String sElementName = String( XML_CHAR_TO_OUSTRING( name ));
+ XMLElement *pElement = new XMLElement( sElementName, ( XMLParentNode * ) pCurNode );
+ pCurNode = pElement;
+ pCurData = NULL;
+
+ int i = 0;
+ while( atts[i] ) {
+ pElement->AddAttribute(
+ String( XML_CHAR_TO_OUSTRING( atts[ i ] )),
+ String( XML_CHAR_TO_OUSTRING( atts[ i + 1 ] )));
+ i += 2;
+ }
+}
+
+/*****************************************************************************/
+void SimpleXMLParser::EndElement( const XML_Char *name )
+/*****************************************************************************/
+{
+ // This variable is not used at all, but the the sax C interface can't be changed
+ // To prevent warnings this dummy assignment is used
+ // +++
+ (void) name;
+
+ pCurNode = pCurNode->GetParent();
+ pCurData = NULL;
+}
+
+/*****************************************************************************/
+void SimpleXMLParser::CharacterData(
+ const XML_Char *s, int len )
+/*****************************************************************************/
+{
+ if ( !pCurData ){
+ String x=String( XML_CHAR_N_TO_OUSTRING( s, len ));
+ XMLUtil::UnQuotHTML(x);
+ pCurData = new XMLData( x , pCurNode );
+ }else{
+ String x=String( XML_CHAR_N_TO_OUSTRING( s, len ));
+ XMLUtil::UnQuotHTML(x);
+ pCurData->AddData( x );
+
+ }
+}
+
+/*****************************************************************************/
+void SimpleXMLParser::Comment(
+ const XML_Char *data )
+/*****************************************************************************/
+{
+ pCurData = NULL;
+ new XMLComment( String( XML_CHAR_TO_OUSTRING( data )), pCurNode );
+}
+
+/*****************************************************************************/
+void SimpleXMLParser::Default(
+ const XML_Char *s, int len )
+/*****************************************************************************/
+{
+ pCurData = NULL;
+ new XMLDefault(
+ String( XML_CHAR_N_TO_OUSTRING( s, len )), pCurNode );
+}
+
+/*****************************************************************************/
+XMLFile *SimpleXMLParser::Execute( const String &rFullFileName , const String &rFileName, XMLFile* pXMLFileIn )
+/*****************************************************************************/
+{
+// printf("DBG: SimpleXMLParser::Execute( %s )", ByteString( rFileName , RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
+ aErrorInformation.eCode = XML_ERROR_NONE;
+ aErrorInformation.nLine = 0;
+ aErrorInformation.nColumn = 0;
+ aErrorInformation.sMessage = String::CreateFromAscii( "ERROR: Unable to open file " );
+ aErrorInformation.sMessage += rFileName;
+
+ SvFileStream aStream( rFileName, STREAM_STD_READ );
+
+ if ( !aStream.IsOpen())
+ return NULL;
+
+ SvMemoryStream aMemStream;
+ aStream >> aMemStream;
+ aMemStream.Seek( 0 );
+
+ aStream.Close();
+
+ pXMLFile = pXMLFileIn;
+ pXMLFile->SetName( rFileName );
+ pXMLFile->SetFullName( rFullFileName );
+
+ return Execute( &aMemStream );
+}
+
+/*****************************************************************************/
+XMLFile *SimpleXMLParser::Execute( SvMemoryStream *pStream )
+/*****************************************************************************/
+{
+ if ( !pXMLFile )
+ pXMLFile = new XMLFile( String());
+
+ pCurNode = pXMLFile;
+ pCurData = NULL;
+
+ ULONG nPos = pStream->Tell();
+ pStream->Seek( STREAM_SEEK_TO_END );
+
+ aErrorInformation.eCode = XML_ERROR_NONE;
+ aErrorInformation.nLine = 0;
+ aErrorInformation.nColumn = 0;
+ if ( pXMLFile->GetName().Len()) {
+ aErrorInformation.sMessage = String::CreateFromAscii( "File " );
+ aErrorInformation.sMessage += pXMLFile->GetName();
+ aErrorInformation.sMessage += String::CreateFromAscii( " parsed succesfully" );
+ }
+ else
+ aErrorInformation.sMessage = String::CreateFromAscii( "XML-File parsed successfully" );
+
+ if ( !XML_Parse(
+ aParser, ( char * ) pStream->GetData() + nPos, pStream->Tell() - nPos, TRUE ))
+ {
+ aErrorInformation.eCode = XML_GetErrorCode( aParser );
+ aErrorInformation.nLine = XML_GetErrorLineNumber( aParser );
+ aErrorInformation.nColumn = XML_GetErrorColumnNumber( aParser );
+
+ aErrorInformation.sMessage = String::CreateFromAscii( "ERROR: " );
+ if ( pXMLFile->GetName().Len())
+ aErrorInformation.sMessage += pXMLFile->GetName();
+ else
+ aErrorInformation.sMessage += String::CreateFromAscii( "XML-File" );
+ aErrorInformation.sMessage += String::CreateFromAscii( " (" );
+ aErrorInformation.sMessage += String::CreateFromInt64( aErrorInformation.nLine );
+ aErrorInformation.sMessage += String::CreateFromAscii( "," );
+ aErrorInformation.sMessage += String::CreateFromInt64( aErrorInformation.nColumn );
+ aErrorInformation.sMessage += String::CreateFromAscii( "): " );
+
+ switch( aErrorInformation.eCode ) {
+ case XML_ERROR_NO_MEMORY: aErrorInformation.sMessage += String::CreateFromAscii( "No memory" ); break;
+ case XML_ERROR_SYNTAX: aErrorInformation.sMessage += String::CreateFromAscii( "Syntax" ); break;
+ case XML_ERROR_NO_ELEMENTS: aErrorInformation.sMessage += String::CreateFromAscii( "No elements" ); break;
+ case XML_ERROR_INVALID_TOKEN: aErrorInformation.sMessage += String::CreateFromAscii( "Invalid token" ); break;
+ case XML_ERROR_UNCLOSED_TOKEN: aErrorInformation.sMessage += String::CreateFromAscii( "Unclosed token" ); break;
+ case XML_ERROR_PARTIAL_CHAR: aErrorInformation.sMessage += String::CreateFromAscii( "Partial char" ); break;
+ case XML_ERROR_TAG_MISMATCH: aErrorInformation.sMessage += String::CreateFromAscii( "Tag mismatch" ); break;
+ case XML_ERROR_DUPLICATE_ATTRIBUTE: aErrorInformation.sMessage += String::CreateFromAscii( "Dublicat attribute" ); break;
+ case XML_ERROR_JUNK_AFTER_DOC_ELEMENT: aErrorInformation.sMessage += String::CreateFromAscii( "Junk after doc element" ); break;
+ case XML_ERROR_PARAM_ENTITY_REF: aErrorInformation.sMessage += String::CreateFromAscii( "Param entity ref" ); break;
+ case XML_ERROR_UNDEFINED_ENTITY: aErrorInformation.sMessage += String::CreateFromAscii( "Undefined entity" ); break;
+ case XML_ERROR_RECURSIVE_ENTITY_REF: aErrorInformation.sMessage += String::CreateFromAscii( "Recursive entity ref" ); break;
+ case XML_ERROR_ASYNC_ENTITY: aErrorInformation.sMessage += String::CreateFromAscii( "Async_entity" ); break;
+ case XML_ERROR_BAD_CHAR_REF: aErrorInformation.sMessage += String::CreateFromAscii( "Bad char ref" ); break;
+ case XML_ERROR_BINARY_ENTITY_REF: aErrorInformation.sMessage += String::CreateFromAscii( "Binary entity" ); break;
+ case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF: aErrorInformation.sMessage += String::CreateFromAscii( "Attribute external entity ref" ); break;
+ case XML_ERROR_MISPLACED_XML_PI: aErrorInformation.sMessage += String::CreateFromAscii( "Misplaced xml pi" ); break;
+ case XML_ERROR_UNKNOWN_ENCODING: aErrorInformation.sMessage += String::CreateFromAscii( "Unknown encoding" ); break;
+ case XML_ERROR_INCORRECT_ENCODING: aErrorInformation.sMessage += String::CreateFromAscii( "Incorrect encoding" ); break;
+ case XML_ERROR_UNCLOSED_CDATA_SECTION: aErrorInformation.sMessage += String::CreateFromAscii( "Unclosed cdata section" ); break;
+ case XML_ERROR_EXTERNAL_ENTITY_HANDLING: aErrorInformation.sMessage += String::CreateFromAscii( "External entity handling" ); break;
+ case XML_ERROR_NOT_STANDALONE: aErrorInformation.sMessage += String::CreateFromAscii( "Not standalone" ); break;
+ case XML_ERROR_NONE: break;
+ default:
+ break;
+
+ }
+ delete pXMLFile;
+ pXMLFile = NULL;
+ }
+ pStream->Seek( nPos );
+
+ return pXMLFile;
+}
+
+/*****************************************************************************/
+void XMLUtil::QuotHTML( String &rString )
+/*****************************************************************************/
+{
+ OUStringBuffer sReturn;
+ static const String LT(String::CreateFromAscii("<"));
+ static const String QLT(String::CreateFromAscii("&lt;"));
+ static const String GT(String::CreateFromAscii(">"));
+ static const String QGT(String::CreateFromAscii("&gt;"));
+ static const String QUOT(String::CreateFromAscii("\\"));
+ static const String QQUOT(String::CreateFromAscii("&quot;"));
+ static const String APOS(String::CreateFromAscii("\""));
+ static const String QAPOS(String::CreateFromAscii("&apos;"));
+ static const String AMP(String::CreateFromAscii("&"));
+ static const String QAMP(String::CreateFromAscii("&amp;"));
+ static const String SLASH(String::CreateFromAscii("\\"));
+
+ for ( USHORT i = 0; i < rString.Len(); i++) {
+ if ( i < rString.Len()) {
+ switch ( rString.GetChar( i )) {
+ case '\\': if( i+1 <= rString.Len() ){
+ switch( rString.GetChar( i+1 ) ){
+ case '<': sReturn.append( LT );i++;break;
+ case '>': sReturn.append( GT );i++;break;
+ case '\\': sReturn.append( QUOT );i++;break;
+ case '\"': sReturn.append( APOS );i++;break;
+ //case '\'': sReturn += "\'";i++;break;
+ //case '&' : sRetrun += "&";i++;break;
+ default: sReturn.append( SLASH );break;
+
+ }
+ }
+ break;
+
+ case '<':
+ sReturn.append( QLT );
+ break;
+
+ case '>':
+ sReturn.append( QGT );
+ break;
+
+ case '\"':
+ sReturn.append( QQUOT );
+ break;
+
+/* case '\'':
+ sReturn += "&apos;";
+ break;
+*/
+ case '&':
+ if (
+ ( ( i + 4 ) < rString.Len()) &&
+ ( String( rString.Copy( i, 5 ) ).Equals( QAMP ) )
+ )
+ sReturn.append( rString.GetChar( i ) );
+ else
+ sReturn.append( QAMP );
+ break;
+
+ default:
+ sReturn.append( rString.GetChar( i ) );
+ break;
+ }
+ }
+ }
+ rString = String( sReturn.makeStringAndClear() );
+}
+
+void XMLUtil::UnQuotHTML( String &rString ){
+ UnQuotData( rString );
+}
+
+void XMLUtil::UnQuotData( String &rString_in ){
+ ByteString sReturn;
+ ByteString sString( rString_in , RTL_TEXTENCODING_UTF8 );
+ while ( sString.Len()) {
+ if ( sString.Copy( 0, 1 ) == "\\" ) {
+ sReturn += "\\\\";
+ sString.Erase( 0, 1 );
+ }
+ else if ( sString.Copy( 0, 5 ) == "&amp;" ) {
+ sReturn += "&";
+ sString.Erase( 0, 5 );
+ }
+ else if ( sString.Copy( 0, 4 ) == "&lt;" ) {
+ sReturn += "<";
+ sString.Erase( 0, 4 );
+ }
+ else if ( sString.Copy( 0, 4 ) == "&gt;" ) {
+ sReturn += ">";
+ sString.Erase( 0, 4 );
+ }
+ else if ( sString.Copy( 0, 6 ) == "&quot;" ) {
+ sReturn += "\"";
+ sString.Erase( 0, 6 );
+ }
+ else if ( sString.Copy( 0, 6 ) == "&apos;" ) {
+ sReturn += "\'";
+ sString.Erase( 0, 6 );
+ }
+ else {
+ sReturn += sString.GetChar( 0 );
+ sString.Erase( 0, 1 );
+ }
+ }
+ rString_in = String(sReturn , RTL_TEXTENCODING_UTF8 );
+
+
+}
+
+XMLUtil::XMLUtil(){
+}
+
+
+/*****************************************************************************/
+void XMLUtil::dump(){
+/*****************************************************************************/
+ int cnt=1;
+ printf("size=%lu\n",static_cast<unsigned long>(lMap.size()));
+ for(HashMap::iterator pos = lMap.begin(); pos != lMap.end() ; ++pos){
+ fprintf(stdout,"key=%s , value=%d , no=%d\n",pos->first.GetBuffer(),pos->second,cnt++);
+ }
+}
+/*****************************************************************************/
+XMLUtil& XMLUtil::Instance(){
+/*****************************************************************************/
+ static XMLUtil instance;
+ return instance;
+}
+/*****************************************************************************/
+XMLUtil::~XMLUtil(){}
+/*****************************************************************************/
+/*****************************************************************************/
+ByteString XMLUtil::GetIsoLangByIndex( USHORT nIndex )
+/*****************************************************************************/
+{
+ if(nIndex > 0 && MAX_LANGUAGES >= nIndex )
+ return isoArray[nIndex];
+ return "";
+}
+
diff --git a/l10ntools/source/xrm_yy_wrapper.c b/l10ntools/source/xrm_yy_wrapper.c
new file mode 100644
index 000000000000..6a304d0d09dc
--- /dev/null
+++ b/l10ntools/source/xrm_yy_wrapper.c
@@ -0,0 +1,2 @@
+// Helper to suppress warnings in lex generated c code, see #i57362#
+#include "xrm_yy.c"
diff --git a/l10ntools/source/xrmlex.l b/l10ntools/source/xrmlex.l
new file mode 100644
index 000000000000..efc8bf1f7d91
--- /dev/null
+++ b/l10ntools/source/xrmlex.l
@@ -0,0 +1,228 @@
+%{
+/*
+ * lexer for parsing xml-property source files (*.xml)
+ *
+ */
+
+
+/* enlarge token buffer to tokenize whole strings */
+#undef YYLMAX
+#define YYLMAX 64000
+
+/* to enable debug output define LEXDEBUG */
+#define LEXDEBUG 1
+#ifdef LEXDEBUG
+#define OUTPUT fprintf
+#else
+#define OUTPUT(Par1,Par2);
+#endif
+
+/* table of possible token ids */
+#include "tokens.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined __GNUC__
+#pragma GCC system_header
+#elif defined __SINPRO_CC
+#pragma disable_warn
+#elif defined _MSC_VER
+#pragma warning(push, 1)
+#endif
+
+/* external functions (C++ code, declared as extren "C" */
+extern int WorkOnTokenSet( int, char* );
+extern int Argument( char * );
+extern int InitXrmExport( char * , char * );
+extern int EndXrmExport();
+extern int GetError();
+extern int SetError();
+extern char *GetOutputFile( int argc, char* argv[]);
+extern FILE *GetXrmFile();
+extern int isQuiet();
+extern void removeTempFile();
+extern char* getFilename();
+
+/* forwards */
+void YYWarning();
+
+int bText=0;
+%}
+
+%p 24000
+%e 1200
+%n 500
+
+%%
+
+"<Readme"[^\>]*\> {
+ WorkOnTokenSet( XRM_README_START, yytext );
+}
+
+"</Readme>" {
+ WorkOnTokenSet( XRM_README_END, yytext );
+}
+
+"<apochelp"[^\>]*\> {
+ WorkOnTokenSet( XRM_README_START, yytext );
+}
+
+"</apochelp>" {
+ WorkOnTokenSet( XRM_README_END, yytext );
+}
+
+"<Section"[^\>]*\> {
+ WorkOnTokenSet( XRM_SECTION_START, yytext );
+}
+
+"</Section>" {
+ WorkOnTokenSet( XRM_SECTION_END, yytext );
+}
+
+"<Paragraph"[^\>]*\> {
+ WorkOnTokenSet( XRM_PARAGRAPH_START, yytext );
+}
+
+"</Paragraph>" {
+ WorkOnTokenSet( XRM_PARAGRAPH_END, yytext );
+}
+
+"<Text"[^\>]*\> {
+ WorkOnTokenSet( XRM_TEXT_START, yytext );
+}
+
+"</Text>" {
+ WorkOnTokenSet( XRM_TEXT_END, yytext );
+}
+
+"<List"[^\>]*\> {
+ WorkOnTokenSet( XRM_LIST_START, yytext );
+}
+
+"</List>" {
+ WorkOnTokenSet( XRM_LIST_END, yytext );
+}
+
+"<!--" {
+ char c1 = 0, c2 = 0, c3 = input();
+ char pChar[2];
+ pChar[1] = 0x00;
+ pChar[0] = c3;
+
+ WorkOnTokenSet( COMMEND, yytext );
+ WorkOnTokenSet( COMMEND, pChar );
+
+ for(;;) {
+ if ( c3 == EOF )
+ break;
+ if ( c1 == '-' && c2 == '-' && c3 == '>' )
+ break;
+ c1 = c2;
+ c2 = c3;
+ c3 = input();
+ pChar[0] = c3;
+ WorkOnTokenSet( COMMEND, pChar );
+ }
+}
+
+.|\n {
+ if ( bText == 1 )
+ WorkOnTokenSet( XML_TEXTCHAR, yytext );
+ else
+ WorkOnTokenSet( UNKNOWNCHAR, yytext );
+}
+
+
+%%
+
+/*****************************************************************************/
+int yywrap(void)
+/*****************************************************************************/
+{
+ return 1;
+}
+
+/*****************************************************************************/
+void YYWarning( char *s )
+/*****************************************************************************/
+{
+ /* write warning to stderr */
+ fprintf( stderr,
+ "Warning: \"%s\" in line %d: \"%s\"\n", s, yylineno, yytext );
+}
+
+/*****************************************************************************/
+#ifdef GCC
+void yyerror ( char *s, ... )
+#else
+void yyerror ( char *s )
+#endif
+/*****************************************************************************/
+{
+ /* write error to stderr */
+ fprintf( stderr,
+ "Error: \"%s\" in line %d: \"%s\"\n", s, yylineno, yytext );
+ SetError();
+}
+
+/*****************************************************************************/
+int
+#ifdef WNT
+_cdecl
+#endif
+main( int argc, char* argv[])
+/*****************************************************************************/
+{
+ /* error level */
+ int nRetValue = 0;
+ char *pOutput;
+ FILE *pFile;
+
+ pOutput = GetOutputFile( argc, argv );
+ if( !isQuiet() ){
+ fprintf( stdout, "\nXrmEx 0.9 Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.\n" );
+ fprintf( stdout, "======================================================================\n" );
+ }
+
+ if ( !pOutput ) {
+ fprintf( stdout, "Syntax: XRMEX[-p Prj][-r PrjRoot]-i FileIn [-o FileOut][-m DataBase][-e][-b][-u][-NOUTF8][-L l1,l2,...]\n" );
+ fprintf( stdout, " Prj: Project\n" );
+ fprintf( stdout, " PrjRoot: Path to project root (..\\.. etc.)\n" );
+ fprintf( stdout, " FileIn: Source files (*.src)\n" );
+ fprintf( stdout, " FileOut: Destination file (*.*)\n" );
+ fprintf( stdout, " DataBase: Mergedata (*.sdf)\n" );
+ fprintf( stdout, " -e: Disable writing errorlog\n" );
+ fprintf( stdout, " -b: Break when Token \"HelpText\" found in source\n" );
+ fprintf( stdout, " -u: [english] and [german] are allowed, Id is Taken from DataBase \n" );
+ fprintf( stdout, " -NOUTF8: disable UTF8 as language independent encoding\n" );
+ fprintf( stdout, " -L: Restrict the handled languages. l1,l2,... are elements of (de,en-US,es...)\n" );
+ fprintf( stdout, " A fallback language can be defined like this: l1=f1.\n" );
+ fprintf( stdout, " f1, f2,... are also elements of (de,en-US,es...)\n" );
+ fprintf( stdout, " Example: -L en-US,es=de\n" );
+ fprintf( stdout, " Restriction to es and en-US, de will be fallback for 99\n" );
+// fprintf( stdout, " -ISO99: IsoCode is the full qualified ISO language code for language 99" );
+ return 1;
+ }
+ pFile = GetXrmFile();
+ InitXrmExport( pOutput , getFilename() );
+
+ if ( !pFile )
+ return 1;
+
+ yyin = pFile;
+
+ /* create global instance of class XmlExport */
+ //InitXrmExport( pOutput );
+
+ /* start parser */
+ yylex();
+
+ /* get error info. and end export */
+ nRetValue = GetError();
+ EndXrmExport();
+
+ if( !isQuiet() ) fprintf( stdout, "\n===================================\n\n" );
+ removeTempFile();
+ /* return error level */
+ return nRetValue;
+}
diff --git a/l10ntools/source/xrmmerge.cxx b/l10ntools/source/xrmmerge.cxx
new file mode 100644
index 000000000000..3eadd202ef5c
--- /dev/null
+++ b/l10ntools/source/xrmmerge.cxx
@@ -0,0 +1,754 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: xrmmerge.cxx,v $
+ * $Revision: 1.20 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_l10ntools.hxx"
+#include <stdio.h>
+#include <tools/string.hxx>
+#include <tools/fsys.hxx>
+
+// local includes
+#include "export.hxx"
+#include "xrmmerge.hxx"
+#include "utf8conv.hxx"
+#include "tokens.h"
+#include <iostream>
+#include <vector>
+
+using namespace std;
+
+extern "C" { int yyerror( char * ); }
+extern "C" { int YYWarning( char * ); }
+
+// defines to parse command line
+#define STATE_NON 0x0001
+#define STATE_INPUT 0x0002
+#define STATE_OUTPUT 0x0003
+#define STATE_PRJ 0x0004
+#define STATE_ROOT 0x0005
+#define STATE_MERGESRC 0x0006
+#define STATE_ERRORLOG 0x0007
+#define STATE_UTF8 0x000B
+#define STATE_LANGUAGES 0x000C
+#define STATE_ISOCODE99 0x000D
+
+// set of global variables
+BOOL bEnableExport;
+BOOL bMergeMode;
+BOOL bErrorLog;
+BOOL bUTF8;
+bool bQuiet;
+ByteString sPrj;
+ByteString sPrjRoot;
+ByteString sInputFileName;
+ByteString sActFileName;
+ByteString sOutputFile;
+ByteString sMergeSrc;
+String sUsedTempFile;
+XRMResParser *pParser = NULL;
+
+extern "C" {
+// the whole interface to lexer is in this extern "C" section
+
+/*****************************************************************************/
+extern char *GetOutputFile( int argc, char* argv[])
+/*****************************************************************************/
+{
+ bEnableExport = FALSE;
+ bMergeMode = FALSE;
+ bErrorLog = TRUE;
+ bUTF8 = TRUE;
+ sPrj = "";
+ sPrjRoot = "";
+ sInputFileName = "";
+ sActFileName = "";
+ Export::sLanguages = "";
+ bQuiet = false;
+ USHORT nState = STATE_NON;
+ BOOL bInput = FALSE;
+
+ // parse command line
+ for( int i = 1; i < argc; i++ ) {
+ if ( ByteString( argv[ i ] ).ToUpperAscii() == "-I" ) {
+ nState = STATE_INPUT; // next token specifies source file
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-O" ) {
+ nState = STATE_OUTPUT; // next token specifies the dest file
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-P" ) {
+ nState = STATE_PRJ; // next token specifies the cur. project
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-R" ) {
+ nState = STATE_ROOT; // next token specifies path to project root
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-M" ) {
+ nState = STATE_MERGESRC; // next token specifies the merge database
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-QQ" ) {
+ bQuiet = true;
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-E" ) {
+ nState = STATE_ERRORLOG;
+ bErrorLog = FALSE;
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-UTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = TRUE;
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-NOUTF8" ) {
+ nState = STATE_UTF8;
+ bUTF8 = FALSE;
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-L" ) {
+ nState = STATE_LANGUAGES;
+ }
+ else if ( ByteString( argv[ i ] ).ToUpperAscii() == "-ISO99" ) {
+ nState = STATE_ISOCODE99;
+ }
+ else {
+ switch ( nState ) {
+ case STATE_NON: {
+ return NULL; // no valid command line
+ }
+ case STATE_INPUT: {
+ sInputFileName = argv[ i ];
+ bInput = TRUE; // source file found
+ }
+ break;
+ case STATE_OUTPUT: {
+ sOutputFile = argv[ i ]; // the dest. file
+ }
+ break;
+ case STATE_PRJ: {
+ sPrj = ByteString( argv[ i ]);
+ }
+ break;
+ case STATE_ROOT: {
+ sPrjRoot = ByteString( argv[ i ]); // path to project root
+ }
+ break;
+ case STATE_MERGESRC: {
+ sMergeSrc = ByteString( argv[ i ]);
+ bMergeMode = TRUE; // activate merge mode, cause merge database found
+ }
+ break;
+ case STATE_LANGUAGES: {
+ Export::sLanguages = ByteString( argv[ i ]);
+ }
+ break;
+ }
+ }
+ }
+
+ if ( bInput ) {
+ // command line is valid
+ bEnableExport = TRUE;
+ char *pReturn = new char[ sOutputFile.Len() + 1 ];
+ strcpy( pReturn, sOutputFile.GetBuffer()); // #100211# - checked
+ return pReturn;
+ }
+
+ // command line is not valid
+ return NULL;
+}
+void removeTempFile(){
+ if( !sUsedTempFile.EqualsIgnoreCaseAscii( "" ) ){
+ DirEntry aTempFile( sUsedTempFile );
+ aTempFile.Kill();
+ }
+}
+/*****************************************************************************/
+int InitXrmExport( char *pOutput , char* pFilename)
+/*****************************************************************************/
+{
+ // instanciate Export
+ ByteString sOutput( pOutput );
+ ByteString sFilename( pFilename );
+ Export::InitLanguages( false );
+
+ if ( bMergeMode )
+ pParser = new XRMResMerge( sMergeSrc, sOutputFile, sFilename );
+ else if ( sOutputFile.Len()) {
+ pParser = new XRMResExport( sOutputFile, sPrj, sActFileName );
+ }
+
+ return 1;
+}
+
+int isQuiet(){
+ if( bQuiet ) return 1;
+ else return 0;
+}
+/*****************************************************************************/
+int EndXrmExport()
+/*****************************************************************************/
+{
+ delete pParser;
+ return 1;
+}
+extern const char* getFilename()
+{
+ return sInputFileName.GetBuffer();
+}
+/*****************************************************************************/
+extern FILE *GetXrmFile()
+/*****************************************************************************/
+{
+ FILE *pFile = 0;
+ // look for valid filename
+ if ( sInputFileName.Len()) {
+ if( Export::fileHasUTF8ByteOrderMarker( sInputFileName ) ){
+ DirEntry aTempFile = Export::GetTempFile();
+ DirEntry aSourceFile( String( sInputFileName , RTL_TEXTENCODING_ASCII_US ) );
+ aSourceFile.CopyTo( aTempFile , FSYS_ACTION_COPYFILE );
+ String sTempFile = aTempFile.GetFull();
+ Export::RemoveUTF8ByteOrderMarkerFromFile( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ) );
+ pFile = fopen( ByteString( sTempFile , RTL_TEXTENCODING_ASCII_US ).GetBuffer(), "r" );
+ sUsedTempFile = sTempFile;
+ }else{
+ // able to open file?
+ pFile = fopen( sInputFileName.GetBuffer(), "r" );
+ sUsedTempFile = String::CreateFromAscii("");
+ }
+ if ( !pFile ){
+ fprintf( stderr, "Error: Could not open file %s\n",
+ sInputFileName.GetBuffer());
+ }
+ else {
+ // this is a valid file which can be opened, so
+ // create path to project root
+ DirEntry aEntry( String( sInputFileName, RTL_TEXTENCODING_ASCII_US ));
+ aEntry.ToAbs();
+ ByteString sFullEntry( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
+ aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
+ aEntry += DirEntry( sPrjRoot );
+ ByteString sPrjEntry( aEntry.GetFull(), RTL_TEXTENCODING_ASCII_US );
+
+ // create file name, beginnig with project root
+ // (e.g.: source\ui\src\menue.src)
+ sActFileName = sFullEntry.Copy( sPrjEntry.Len() + 1 );
+
+ if( !bQuiet )
+ fprintf( stdout, "\nProcessing File %s ...\n", sInputFileName.GetBuffer());
+
+ sActFileName.SearchAndReplaceAll( "/", "\\" );
+
+ return pFile;
+ }
+ }
+ // this means the file could not be opened
+ return NULL;
+}
+
+/*****************************************************************************/
+int WorkOnTokenSet( int nTyp, char *pTokenText )
+/*****************************************************************************/
+{
+// printf("Typ = %d , text = '%s'\n",nTyp , pTokenText );
+ pParser->Execute( nTyp, pTokenText );
+
+ return 1;
+}
+
+/*****************************************************************************/
+int SetError()
+/*****************************************************************************/
+{
+ pParser->SetError();
+ return 1;
+}
+}
+
+extern "C" {
+/*****************************************************************************/
+int GetError()
+/*****************************************************************************/
+{
+ return pParser->GetError();
+}
+}
+
+//
+// class XRMResParser
+//
+
+
+/*****************************************************************************/
+XRMResParser::XRMResParser()
+/*****************************************************************************/
+ : bError( FALSE ),
+ bText( FALSE )
+{
+ aLanguages = Export::GetLanguages();
+}
+
+/*****************************************************************************/
+XRMResParser::~XRMResParser()
+/*****************************************************************************/
+{
+}
+
+/*****************************************************************************/
+int XRMResParser::Execute( int nToken, char * pToken )
+/*****************************************************************************/
+{
+ ByteString rToken( pToken );
+
+ switch ( nToken ) {
+ case XRM_README_START:
+ sLID = "";
+ sGID = GetAttribute( rToken, "name" );
+ break;
+
+ case XRM_README_END:
+ sGID = "";
+ break;
+
+ case XRM_SECTION_START:
+ sLID = "";
+ sGID += ".";
+ sGID += GetAttribute( rToken, "id" );
+ //sLocalized = "1";
+
+ //sLocalized = "X:";
+ sLocalized = true;
+ break;
+
+ case XRM_SECTION_END:
+ sGID = sGID.GetToken( 0, '.' );
+ break;
+
+ case XRM_PARAGRAPH_START:
+ sLID = "";
+ sGID += ".";
+ sGID += GetAttribute( rToken, "id" );
+ if ( GetAttribute( rToken, "localized" ) == "false" )
+// sLocalized += "0";
+ sLocalized = false;
+ else
+// sLocalized += "1";
+ sLocalized = true;
+ break;
+
+ case XRM_PARAGRAPH_END: {
+ if ( sLID.Len())
+ EndOfText( sCurrentOpenTag, sCurrentCloseTag );
+ ByteString sTmp = sGID;
+ sGID = "";
+ for ( USHORT i = 0; i + 1 < sTmp.GetTokenCount( '.' ); i++ ) {
+ if ( sGID.Len())
+ sGID += ".";
+ sGID += sTmp.GetToken( i, '.' );
+ }
+ //sLocalized = sLocalized.Copy( 0, sLocalized.Len() - 1 );
+ }
+ break;
+
+ case XRM_TEXT_START:
+// if ( sLocalized.GetChar( sLocalized.Len() - 1 ) == '1' ) {
+ if ( sLocalized ) {
+
+ ByteString sNewLID = GetAttribute( rToken, "id" );
+ if ( sNewLID != sLID ) {
+ EndOfText( sCurrentOpenTag, sCurrentCloseTag );
+ sLID = sNewLID;
+ }
+ bText = TRUE;
+ sCurrentText = "";
+ sCurrentOpenTag = rToken;
+ Output( rToken );
+ }
+ break;
+
+ case XRM_TEXT_END: {
+// if ( sLocalized.GetChar( sLocalized.Len() - 1 ) == '1' ) {
+ if( sLocalized ){
+ sCurrentCloseTag = rToken;
+
+ ByteString sLang = GetAttribute( sCurrentOpenTag, "xml:lang" );
+ if( sLang.EqualsIgnoreCaseAscii("de") ){
+ ULONG nLen = 0;
+ while ( sCurrentText.Len() != nLen )
+ {
+ nLen = sCurrentText.Len();
+ sCurrentText.SearchAndReplaceAll( "\n\t", "\n" );
+ sCurrentText.SearchAndReplaceAll( "\n ", "\n" );
+ }
+ sCurrentText.SearchAndReplaceAll( "\n", " " );
+ sCurrentCloseTag = rToken;
+ }
+ WorkOnText( sCurrentOpenTag, sCurrentText );
+ Output( sCurrentText );
+
+ //fprintf( stdout, "%s %s\n", sGID.GetBuffer(), sLID.GetBuffer());
+ //fprintf( stdout, "%s\n\n", sCurrentText.GetBuffer());
+
+ bText = FALSE;
+ }
+ }
+ break;
+
+ case XRM_LIST_START:
+ sLID = "";
+ break;
+
+ case XRM_LIST_END:
+ if ( sLID.Len())
+ EndOfText( sCurrentOpenTag, sCurrentCloseTag );
+ break;
+
+ default:
+ if ( bText ) {
+ sCurrentText += rToken;
+ }
+ break;
+ }
+
+ if ( !bText )
+ Output( rToken );
+
+ return 0;
+}
+
+/*****************************************************************************/
+ByteString XRMResParser::GetAttribute( const ByteString &rToken, const ByteString &rAttribute )
+/*****************************************************************************/
+{
+ ByteString sTmp( rToken );
+ sTmp.SearchAndReplaceAll( "\t", " " );
+
+ ByteString sSearch( " " );
+ sSearch += rAttribute;
+ sSearch += "=";
+ USHORT nPos = sTmp.Search( sSearch );
+
+ if ( nPos != STRING_NOTFOUND ) {
+ sTmp = sTmp.Copy( nPos );
+ ByteString sId = sTmp.GetToken( 1, '\"' );
+ return sId;
+ }
+ return "";
+}
+
+
+/*****************************************************************************/
+void XRMResParser::Error( const ByteString &rError )
+/*****************************************************************************/
+{
+ yyerror(( char * ) rError.GetBuffer());
+}
+
+/*****************************************************************************/
+void XRMResParser::ConvertStringToDBFormat( ByteString &rString )
+/*****************************************************************************/
+{
+ ByteString sResult;
+ do {
+ sResult = rString;
+ rString.EraseLeadingChars( _LF );
+ // rString.EraseLeadingChars( ' ' );
+ rString.EraseLeadingChars( '\t' );
+ // rString.EraseTrailingChars( ' ' );
+ rString.EraseTrailingChars( '\t' );
+ } while ( sResult != rString );
+
+ rString.SearchAndReplaceAll( "\t", "\\t" );
+}
+
+/*****************************************************************************/
+void XRMResParser::ConvertStringToXMLFormat( ByteString &rString )
+/*****************************************************************************/
+{
+ rString.SearchAndReplaceAll( "\\t", "\t" );
+}
+
+
+
+//
+// class XRMResOutputParser
+//
+
+/*****************************************************************************/
+XRMResOutputParser::XRMResOutputParser ( const ByteString &rOutputFile )
+/*****************************************************************************/
+{
+ aLanguages = Export::GetLanguages();
+ pOutputStream =
+ new SvFileStream(
+ String( rOutputFile, RTL_TEXTENCODING_ASCII_US ),
+ STREAM_STD_WRITE | STREAM_TRUNC
+ );
+ pOutputStream->SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
+ if ( !pOutputStream->IsOpen()) {
+ ByteString sError( "Unable to open output file: " );
+ sError += rOutputFile;
+ Error( sError );
+ delete pOutputStream;
+ pOutputStream = NULL;
+ }
+}
+
+/*****************************************************************************/
+XRMResOutputParser::~XRMResOutputParser()
+/*****************************************************************************/
+{
+ if ( pOutputStream ) {
+ pOutputStream->Close();
+ delete pOutputStream;
+ }
+}
+
+//
+// class XMLResExport
+//
+
+/*****************************************************************************/
+XRMResExport::XRMResExport(
+ const ByteString &rOutputFile, const ByteString &rProject,
+ const ByteString &rFilePath )
+/*****************************************************************************/
+ : XRMResOutputParser( rOutputFile ),
+ pResData( NULL ),
+ sPrj( rProject ),
+ sPath( rFilePath )
+{
+ aLanguages = Export::GetLanguages();
+}
+
+/*****************************************************************************/
+XRMResExport::~XRMResExport()
+/*****************************************************************************/
+{
+ delete pResData;
+}
+
+void XRMResExport::Output( const ByteString& rOutput )
+{
+ // Dummy to suppress warnings caused by poor class design
+ (void) rOutput;
+}
+
+/*****************************************************************************/
+void XRMResExport::WorkOnText(
+ const ByteString &rOpenTag,
+ ByteString &rText
+)
+/*****************************************************************************/
+{
+ ByteString sLang( GetAttribute( rOpenTag, "xml:lang" ));
+
+ if ( !pResData ) {
+ ByteString sPlatform( "" );
+ pResData = new ResData( sPlatform, GetGID() );
+ pResData->sId = GetLID();
+ }
+
+ pResData->sText[ sLang ] = rText;
+ ConvertStringToDBFormat( pResData->sText[ sLang ] );
+}
+
+/*****************************************************************************/
+void XRMResExport::EndOfText(
+ const ByteString &rOpenTag,
+ const ByteString &rCloseTag
+)
+/*****************************************************************************/
+{
+
+ (void) rOpenTag; // FIXME
+ (void) rCloseTag; // FIXME
+
+ if ( pResData && pOutputStream ) {
+
+ char cSearch = 0x00;
+ ByteString sSearch( cSearch );
+
+ // if ( !pResData->sText[ ByteString("en-US") ].Len() )
+ // pResData->sText[ ByteString("en-US") ] = pResData->sText[ ByteString("de") ];
+
+ Export::FillInFallbacks( pResData );
+
+ ByteString sTimeStamp( Export::GetTimeStamp());
+ ByteString sCur;
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+
+ ByteString sAct = pResData->sText[ sCur ];
+ Export::UnquotHTML( sAct );
+ sAct.EraseAllChars( 0x0A );
+
+ ByteString sOutput( sPrj ); sOutput += "\t";
+ sOutput += sPath;
+ sOutput += "\t0\t";
+ sOutput += "readmeitem\t";
+ sOutput += pResData->sGId; sOutput += "\t";
+ sOutput += pResData->sId; sOutput += "\t\t\t0\t";
+ sOutput += sCur;
+ sOutput += "\t";
+
+ sOutput += sAct; sOutput += "\t\t\t\t";
+ sOutput += sTimeStamp;
+
+ sOutput.SearchAndReplaceAll( sSearch, "_" );
+ //if( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && !Export::isMergingGermanAllowed( sPrj ) ) )
+ pOutputStream->WriteLine( sOutput );
+ }
+ }
+ delete pResData;
+ pResData = NULL;
+}
+
+//
+// class XRMResMerge
+//
+
+/*****************************************************************************/
+XRMResMerge::XRMResMerge(
+ const ByteString &rMergeSource, const ByteString &rOutputFile,
+ ByteString &rFilename)
+/*****************************************************************************/
+ : XRMResOutputParser( rOutputFile ),
+ pMergeDataFile( NULL ),
+ sFilename( rFilename ) ,
+ pResData( NULL )
+{
+ if ( rMergeSource.Len())
+ pMergeDataFile = new MergeDataFile(
+ rMergeSource, sInputFileName , bErrorLog, RTL_TEXTENCODING_MS_1252);//, bUTF8 );
+ if( Export::sLanguages.EqualsIgnoreCaseAscii("ALL") ){
+ Export::SetLanguages( pMergeDataFile->GetLanguages() );
+ aLanguages = pMergeDataFile->GetLanguages();
+ }
+ else aLanguages = Export::GetLanguages();
+}
+
+/*****************************************************************************/
+XRMResMerge::~XRMResMerge()
+/*****************************************************************************/
+{
+ delete pMergeDataFile;
+ delete pResData;
+}
+
+/*****************************************************************************/
+void XRMResMerge::WorkOnText(
+ const ByteString &rOpenTag,
+ ByteString &rText
+)
+/*****************************************************************************/
+{
+ ByteString sLang( GetAttribute( rOpenTag, "xml:lang" ));
+
+ if ( pMergeDataFile ) {
+ if ( !pResData ) {
+ ByteString sPlatform( "" );
+ pResData = new ResData( sPlatform, GetGID() , sFilename );
+ pResData->sId = GetLID();
+ pResData->sResTyp = "readmeitem";
+ }
+
+ PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
+ if ( pEntrys ) {
+ ByteString sContent;
+ if ( Export::isAllowed( sLang ) &&
+ ( pEntrys->GetText(
+ sContent, STRING_TYP_TEXT, sLang )) &&
+ ( sContent != "-" ) && ( sContent.Len()))
+
+ {
+ rText = sContent;
+ ConvertStringToXMLFormat( rText );
+ Export::QuotHTMLXRM( rText );
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+void XRMResMerge::Output( const ByteString& rOutput )
+/*****************************************************************************/
+{
+ if ( pOutputStream )
+ pOutputStream->Write( rOutput.GetBuffer(), rOutput.Len());
+}
+
+/*****************************************************************************/
+void XRMResMerge::EndOfText(
+ const ByteString &rOpenTag,
+ const ByteString &rCloseTag
+)
+/*****************************************************************************/
+{
+ if ( pMergeDataFile && pResData ) {
+ PFormEntrys *pEntrys = pMergeDataFile->GetPFormEntrys( pResData );
+ if ( pEntrys ) {
+ ByteString sCur;
+ for( unsigned int n = 0; n < aLanguages.size(); n++ ){
+ sCur = aLanguages[ n ];
+ ByteString sContent;
+//<<<<<<< xrmmerge.cxx
+ if ( !sCur.EqualsIgnoreCaseAscii("en-US") &&
+ // ( !sCur.EqualsIgnoreCaseAscii("de") ||( sCur.EqualsIgnoreCaseAscii("de") && Export::isMergingGermanAllowed( sPrj ) )) &&
+//=======
+// if ( Export::isAllowed( sCur ) &&
+//>>>>>>> 1.17
+ ( pEntrys->GetText(
+ sContent, STRING_TYP_TEXT, sCur, TRUE )) &&
+ ( sContent != "-" ) && ( sContent.Len()))
+ {
+ ByteString sText( sContent );
+ Export::QuotHTMLXRM( sText );
+
+ ByteString sAdditionalLine( "\t" );
+ sAdditionalLine += rOpenTag;
+ ByteString sSearch = "xml:lang=\"";
+ ByteString sReplace( sSearch );
+
+ sSearch += GetAttribute( rOpenTag, "xml:lang" );
+ sReplace += sCur;
+
+ sAdditionalLine.SearchAndReplace( sSearch, sReplace );
+
+ sAdditionalLine += sText;
+ sAdditionalLine += rCloseTag;
+ sAdditionalLine += "\n";
+
+ for ( USHORT i = 0; i + 1 < GetGID().GetTokenCount( '.' ); i++ )
+ sAdditionalLine += "\t";
+
+ Output( sAdditionalLine );
+ }
+ }
+ }
+ }
+ delete pResData;
+ pResData = NULL;
+}
+
diff --git a/l10ntools/workbench/gsicheck_errors.sdf b/l10ntools/workbench/gsicheck_errors.sdf
new file mode 100644
index 000000000000..04dde12e13ca
--- /dev/null
+++ b/l10ntools/workbench/gsicheck_errors.sdf
@@ -0,0 +1,15 @@
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 de ERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 en-US äERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 de äERR OK ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 en-US OK/ERR OK ERR/OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 de OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 en-US OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 en-US OK/ERR OK/ERR OK/ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 6 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 7 0 en-US OK OK ERR 2004-11-09 18:41:29.59
+
diff --git a/l10ntools/workbench/gsicheck_errors_err-.sdf b/l10ntools/workbench/gsicheck_errors_err-.sdf
new file mode 100644
index 000000000000..f6b267b1c55b
--- /dev/null
+++ b/l10ntools/workbench/gsicheck_errors_err-.sdf
@@ -0,0 +1,11 @@
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 de ERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 en-US äERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 de äERR OK ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 en-US OK/ERR OK ERR/OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 en-US OK/ERR OK/ERR OK/ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 6 0 de ERR ERR ERR 2004-11-09 18:41:29.59
diff --git a/l10ntools/workbench/gsicheck_errors_err-l.sdf b/l10ntools/workbench/gsicheck_errors_err-l.sdf
new file mode 100644
index 000000000000..6ca7f7065cd2
--- /dev/null
+++ b/l10ntools/workbench/gsicheck_errors_err-l.sdf
@@ -0,0 +1,2 @@
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 en-US äERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 de äERR OK ERR 2004-11-09 18:41:29.59
diff --git a/l10ntools/workbench/gsicheck_errors_err-s.sdf b/l10ntools/workbench/gsicheck_errors_err-s.sdf
new file mode 100644
index 000000000000..523017fcfb35
--- /dev/null
+++ b/l10ntools/workbench/gsicheck_errors_err-s.sdf
@@ -0,0 +1,9 @@
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 de ERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 en-US äERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 en-US OK/ERR OK/ERR OK/ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 6 0 de ERR ERR ERR 2004-11-09 18:41:29.59
diff --git a/l10ntools/workbench/gsicheck_errors_err-t.sdf b/l10ntools/workbench/gsicheck_errors_err-t.sdf
new file mode 100644
index 000000000000..e9594642113c
--- /dev/null
+++ b/l10ntools/workbench/gsicheck_errors_err-t.sdf
@@ -0,0 +1,9 @@
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 de äERR OK ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 en-US OK/ERR OK ERR/OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 en-US OK/ERR OK/ERR OK/ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 6 0 de ERR ERR ERR 2004-11-09 18:41:29.59
diff --git a/l10ntools/workbench/gsicheck_errors_ok-.sdf b/l10ntools/workbench/gsicheck_errors_ok-.sdf
new file mode 100644
index 000000000000..4bb4b7bece16
--- /dev/null
+++ b/l10ntools/workbench/gsicheck_errors_ok-.sdf
@@ -0,0 +1,5 @@
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 en-US OK/ERR OK ERR/OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 de OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 en-US OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 en-US OK/ERR OK/ERR OK/ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 7 0 en-US OK OK ERR 2004-11-09 18:41:29.59
diff --git a/l10ntools/workbench/gsicheck_errors_ok-l.sdf b/l10ntools/workbench/gsicheck_errors_ok-l.sdf
new file mode 100644
index 000000000000..9a55e7c95dd3
--- /dev/null
+++ b/l10ntools/workbench/gsicheck_errors_ok-l.sdf
@@ -0,0 +1,12 @@
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 de ERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 en-US OK/ERR OK ERR/OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 de OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 en-US OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 en-US OK/ERR OK/ERR OK/ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 en-US ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 5 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 6 0 de ERR ERR ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 7 0 en-US OK OK ERR 2004-11-09 18:41:29.59
diff --git a/l10ntools/workbench/gsicheck_errors_ok-s.sdf b/l10ntools/workbench/gsicheck_errors_ok-s.sdf
new file mode 100644
index 000000000000..97dd4da6a54b
--- /dev/null
+++ b/l10ntools/workbench/gsicheck_errors_ok-s.sdf
@@ -0,0 +1,6 @@
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 de äERR OK ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 en-US OK/ERR OK ERR/OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 de OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 en-US OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 en-US OK/ERR OK/ERR OK/ERR 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 7 0 en-US OK OK ERR 2004-11-09 18:41:29.59
diff --git a/l10ntools/workbench/gsicheck_errors_ok-t.sdf b/l10ntools/workbench/gsicheck_errors_ok-t.sdf
new file mode 100644
index 000000000000..a6c097e6bd2f
--- /dev/null
+++ b/l10ntools/workbench/gsicheck_errors_ok-t.sdf
@@ -0,0 +1,6 @@
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 de ERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 1 0 en-US äERR ERR OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 2 0 en-US OK/ERR OK ERR/OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 de OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 3 0 en-US OK OK OK 2004-11-09 18:41:29.59
+svx source\dialog\langtab.src 0 itemlist RID_SVXSTR_LANGUAGE_TABLE 4 0 en-US OK/ERR OK/ERR OK/ERR 2004-11-09 18:41:29.59
diff --git a/l10ntools/workbench/gsicheckcheck.btm b/l10ntools/workbench/gsicheckcheck.btm
new file mode 100644
index 000000000000..de71b17da332
--- /dev/null
+++ b/l10ntools/workbench/gsicheckcheck.btm
@@ -0,0 +1,17 @@
+gsicheck
+gsicheck.exe gsicheck_errors.sdf -wc -we
+#pause
+diff --brief gsicheck_errors_ok.sdf gsicheck_errors_ok-.sdf || %vdiff gsicheck_errors_ok.sdf gsicheck_errors_ok-.sdf
+diff --brief gsicheck_errors_err.sdf gsicheck_errors_err-.sdf || %vdiff gsicheck_errors_err.sdf gsicheck_errors_err-.sdf
+gsicheck.exe gsicheck_errors.sdf -wc -we -s
+#pause
+diff --brief gsicheck_errors_ok.sdf gsicheck_errors_ok-s.sdf || %vdiff gsicheck_errors_ok.sdf gsicheck_errors_ok-s.sdf
+diff --brief gsicheck_errors_err.sdf gsicheck_errors_err-s.sdf || %vdiff gsicheck_errors_err.sdf gsicheck_errors_err-s.sdf
+gsicheck.exe gsicheck_errors.sdf -wc -we -t
+#pause
+diff --brief gsicheck_errors_ok.sdf gsicheck_errors_ok-t.sdf || %vdiff gsicheck_errors_ok.sdf gsicheck_errors_ok-t.sdf
+diff --brief gsicheck_errors_err.sdf gsicheck_errors_err-t.sdf || %vdiff gsicheck_errors_err.sdf gsicheck_errors_err-t.sdf
+gsicheck.exe gsicheck_errors.sdf -wc -we -l ""
+#pause
+diff --brief gsicheck_errors_ok.sdf gsicheck_errors_ok-l.sdf || %vdiff gsicheck_errors_ok.sdf gsicheck_errors_ok-l.sdf
+diff --brief gsicheck_errors_err.sdf gsicheck_errors_err-l.sdf || %vdiff gsicheck_errors_err.sdf gsicheck_errors_err-l.sdf