summaryrefslogtreecommitdiff
path: root/l10ntools
diff options
context:
space:
mode:
authorAndras Timar <atimar@suse.com>2012-11-20 15:03:34 +0100
committerAndras Timar <atimar@suse.com>2012-11-20 15:03:34 +0100
commitfa88b3717d58410f6318c520b0397000f86b9720 (patch)
treead8f1b2135ebe8045de55e5af233ff442d901444 /l10ntools
parent54cd57e03e115d6b009409e6df374603452b1378 (diff)
parenta7261b424716463a7bb157f0d79084c868e10015 (diff)
Merge branch 'feature/killsdf'
Conflicts: desktop/prj/build.lst helpcontent2 l10ntools/Executable_gsicheck.mk l10ntools/Executable_uiex.mk regexp/inc/regexp/reclass.hxx solenv/gbuild/AllLangResTarget.mk Change-Id: I398f0cd9e7daefa8d2e04fd977d5bc2e9708169b
Diffstat (limited to 'l10ntools')
-rw-r--r--l10ntools/Executable_cfgex.mk5
-rw-r--r--l10ntools/Executable_gsicheck.mk45
-rw-r--r--l10ntools/Executable_helpex.mk6
-rw-r--r--l10ntools/Executable_localize.mk14
-rw-r--r--l10ntools/Executable_propex.mk36
-rw-r--r--l10ntools/Executable_renewpo.mk36
-rw-r--r--l10ntools/Executable_transex3.mk5
-rw-r--r--l10ntools/Executable_treex.mk37
-rw-r--r--l10ntools/Executable_uiex.mk2
-rw-r--r--l10ntools/Executable_ulfex.mk5
-rw-r--r--l10ntools/Executable_xrmex.mk6
-rw-r--r--l10ntools/Module_l10ntools.mk4
-rw-r--r--l10ntools/Package_scripts.mk6
-rw-r--r--l10ntools/StaticLibrary_transex.mk3
-rw-r--r--l10ntools/inc/export.hxx24
-rw-r--r--l10ntools/inc/helpmerge.hxx2
-rw-r--r--l10ntools/inc/po.hxx129
-rw-r--r--l10ntools/inc/propmerge.hxx37
-rw-r--r--l10ntools/inc/tagtest.hxx346
-rw-r--r--l10ntools/inc/treemerge.hxx38
-rw-r--r--l10ntools/prj/build.lst2
-rwxr-xr-xl10ntools/scripts/po2lo48
-rwxr-xr-xl10ntools/scripts/propex68
-rwxr-xr-xl10ntools/scripts/propex.bat8
-rwxr-xr-xl10ntools/scripts/propmerge88
-rw-r--r--l10ntools/scripts/update_tree.pl394
-rw-r--r--l10ntools/source/cfgmerge.cxx95
-rw-r--r--l10ntools/source/export.cxx99
-rw-r--r--l10ntools/source/export2.cxx111
-rw-r--r--l10ntools/source/gsicheck.cxx1051
-rw-r--r--l10ntools/source/helper.hxx66
-rw-r--r--l10ntools/source/helpex.cxx261
-rw-r--r--l10ntools/source/helpmerge.cxx60
-rw-r--r--l10ntools/source/lngex.cxx140
-rw-r--r--l10ntools/source/lngmerge.cxx6
-rw-r--r--l10ntools/source/localize.cxx145
-rw-r--r--l10ntools/source/merge.cxx171
-rw-r--r--l10ntools/source/po.cxx869
-rw-r--r--l10ntools/source/propex.cxx45
-rw-r--r--l10ntools/source/propmerge.cxx227
-rw-r--r--l10ntools/source/renewpo.cxx231
-rw-r--r--l10ntools/source/tagtest.cxx1570
-rw-r--r--l10ntools/source/treemerge.cxx305
-rw-r--r--l10ntools/source/treex.cxx60
-rw-r--r--l10ntools/source/uimerge.cxx113
-rw-r--r--l10ntools/source/xrmlex.l14
-rw-r--r--l10ntools/source/xrmmerge.cxx131
47 files changed, 2760 insertions, 4404 deletions
diff --git a/l10ntools/Executable_cfgex.mk b/l10ntools/Executable_cfgex.mk
index a2c8d6cb3bbc..e8e16829536c 100644
--- a/l10ntools/Executable_cfgex.mk
+++ b/l10ntools/Executable_cfgex.mk
@@ -49,4 +49,9 @@ $(eval $(call gb_Executable_add_exception_objects,cfgex,\
l10ntools/source/cfgmerge \
))
+$(eval $(call gb_Executable_use_externals,cfgex,\
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
+))
+
# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/l10ntools/Executable_gsicheck.mk b/l10ntools/Executable_gsicheck.mk
deleted file mode 100644
index a99dc3048b2a..000000000000
--- a/l10ntools/Executable_gsicheck.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
-# Version: MPL 1.1 / GPLv3+ / LGPLv3+
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License or as specified alternatively below. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# Major Contributor(s):
-# Copyright (C) 2012 David Ostrovsky <d.ostrovsky@gmx.de> (initial developer)
-#
-# All Rights Reserved.
-#
-# For minor contributions see the git repository.
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
-# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
-# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
-# instead of those above.
-
-$(eval $(call gb_Executable_Executable,gsicheck))
-
-$(eval $(call gb_Executable_set_include,gsicheck,\
- -I$(SRCDIR)/l10ntools/inc \
- $$(INCLUDE) \
-))
-
-$(eval $(call gb_Executable_use_libraries,gsicheck,\
- sal \
-))
-
-$(eval $(call gb_Executable_use_external,gsicheck,boost_headers))
-
-$(eval $(call gb_Executable_add_exception_objects,gsicheck,\
- l10ntools/source/gsicheck \
- l10ntools/source/tagtest \
-))
-
-# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/l10ntools/Executable_helpex.mk b/l10ntools/Executable_helpex.mk
index 085fd94b9e99..66d870768bc2 100644
--- a/l10ntools/Executable_helpex.mk
+++ b/l10ntools/Executable_helpex.mk
@@ -50,4 +50,10 @@ $(eval $(call gb_Executable_add_exception_objects,helpex,\
l10ntools/source/helpmerge \
))
+$(eval $(call gb_Executable_use_externals,helpex,\
+ libxml2 \
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
+))
+
# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/l10ntools/Executable_localize.mk b/l10ntools/Executable_localize.mk
index 511604ac74d2..a810b6cd8e22 100644
--- a/l10ntools/Executable_localize.mk
+++ b/l10ntools/Executable_localize.mk
@@ -26,12 +26,26 @@
$(eval $(call gb_Executable_Executable,localize))
+$(eval $(call gb_Executable_set_include,localize,\
+ -I$(SRCDIR)/l10ntools/inc \
+ $$(INCLUDE) \
+))
+
$(eval $(call gb_Executable_use_libraries,localize,\
sal \
))
+$(eval $(call gb_Executable_use_static_libraries,localize,\
+ transex \
+))
+
$(eval $(call gb_Executable_add_exception_objects,localize,\
l10ntools/source/localize \
))
+$(eval $(call gb_Executable_use_externals,localize,\
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
+))
+
# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/l10ntools/Executable_propex.mk b/l10ntools/Executable_propex.mk
new file mode 100644
index 000000000000..06080c682840
--- /dev/null
+++ b/l10ntools/Executable_propex.mk
@@ -0,0 +1,36 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+
+$(eval $(call gb_Executable_Executable,propex))
+
+$(eval $(call gb_Executable_set_include,propex,\
+ -I$(SRCDIR)/l10ntools/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_Executable_use_libraries,propex,\
+ sal \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,propex,\
+ transex \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,propex,\
+ l10ntools/source/propmerge \
+ l10ntools/source/propex \
+))
+
+$(eval $(call gb_Executable_use_externals,propex,\
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/l10ntools/Executable_renewpo.mk b/l10ntools/Executable_renewpo.mk
new file mode 100644
index 000000000000..db84a41ae5d7
--- /dev/null
+++ b/l10ntools/Executable_renewpo.mk
@@ -0,0 +1,36 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# convert old po to new po
+#
+
+$(eval $(call gb_Executable_Executable,renewpo))
+
+$(eval $(call gb_Executable_set_include,renewpo,\
+ -I$(SRCDIR)/l10ntools/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_Executable_use_libraries,renewpo,\
+ sal \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,renewpo,\
+ transex \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,renewpo,\
+ l10ntools/source/renewpo \
+))
+
+$(eval $(call gb_Executable_use_externals,renewpo,\
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/l10ntools/Executable_transex3.mk b/l10ntools/Executable_transex3.mk
index bc9a85272d9f..d2b7952f0372 100644
--- a/l10ntools/Executable_transex3.mk
+++ b/l10ntools/Executable_transex3.mk
@@ -49,4 +49,9 @@ $(eval $(call gb_Executable_add_exception_objects,transex3,\
l10ntools/source/export \
))
+$(eval $(call gb_Executable_use_externals,transex3,\
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
+))
+
# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/l10ntools/Executable_treex.mk b/l10ntools/Executable_treex.mk
new file mode 100644
index 000000000000..af77c71a1546
--- /dev/null
+++ b/l10ntools/Executable_treex.mk
@@ -0,0 +1,37 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+
+$(eval $(call gb_Executable_Executable,treex))
+
+$(eval $(call gb_Executable_set_include,treex,\
+ -I$(SRCDIR)/l10ntools/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_Executable_use_libraries,treex,\
+ sal \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,treex,\
+ transex \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,treex,\
+ l10ntools/source/treemerge \
+ l10ntools/source/treex \
+))
+
+$(eval $(call gb_Executable_use_externals,treex,\
+ libxml2 \
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/l10ntools/Executable_uiex.mk b/l10ntools/Executable_uiex.mk
index 064b2078479e..8a20512b3412 100644
--- a/l10ntools/Executable_uiex.mk
+++ b/l10ntools/Executable_uiex.mk
@@ -31,6 +31,8 @@ $(eval $(call gb_Executable_use_externals,uiex,\
libxml2 \
libxslt \
boost_headers \
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
))
# vim: set noet sw=4 ts=4:
diff --git a/l10ntools/Executable_ulfex.mk b/l10ntools/Executable_ulfex.mk
index f0b134ef2264..5f4a492fdac8 100644
--- a/l10ntools/Executable_ulfex.mk
+++ b/l10ntools/Executable_ulfex.mk
@@ -46,4 +46,9 @@ $(eval $(call gb_Executable_add_exception_objects,ulfex,\
l10ntools/source/lngex \
))
+$(eval $(call gb_Executable_use_externals,ulfex,\
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
+))
+
# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/l10ntools/Executable_xrmex.mk b/l10ntools/Executable_xrmex.mk
index 3cbcd8861a50..3dab334c7032 100644
--- a/l10ntools/Executable_xrmex.mk
+++ b/l10ntools/Executable_xrmex.mk
@@ -49,4 +49,10 @@ $(eval $(call gb_Executable_add_exception_objects,xrmex,\
l10ntools/source/xrmmerge \
))
+$(eval $(call gb_Executable_use_externals,xrmex,\
+ libxml2 \
+ icuuc \
+ $(if $(filter MSC,$(COM)),icuin,icui18n) \
+))
+
# vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/l10ntools/Module_l10ntools.mk b/l10ntools/Module_l10ntools.mk
index 6fe7dcb5d083..4b2b0f6d970d 100644
--- a/l10ntools/Module_l10ntools.mk
+++ b/l10ntools/Module_l10ntools.mk
@@ -31,12 +31,14 @@ $(eval $(call gb_Module_add_targets,l10ntools,\
Executable_idxdict \
Executable_ulfconv \
Executable_ulfex \
- Executable_gsicheck \
Executable_cfgex \
Executable_uiex \
Executable_xrmex \
Executable_localize \
Executable_transex3 \
+ Executable_renewpo \
+ Executable_propex \
+ Executable_treex \
StaticLibrary_transex \
Package_inc \
Package_scripts \
diff --git a/l10ntools/Package_scripts.mk b/l10ntools/Package_scripts.mk
index 3739f123b434..d00d283a8cc6 100644
--- a/l10ntools/Package_scripts.mk
+++ b/l10ntools/Package_scripts.mk
@@ -30,11 +30,5 @@ $(eval $(call gb_Package_add_file,l10ntools_scripts,bin/addkeyid2pot.pl,addkeyid
$(eval $(call gb_Package_add_file,l10ntools_scripts,bin/fast_merge.pl,fast_merge.pl))
$(eval $(call gb_Package_add_file,l10ntools_scripts,bin/keyidGen.pl,keyidGen.pl))
$(eval $(call gb_Package_add_file,l10ntools_scripts,bin/po2lo,po2lo))
-$(eval $(call gb_Package_add_file,l10ntools_scripts,bin/propex,propex))
-$(eval $(call gb_Package_add_file,l10ntools_scripts,bin/propmerge,propmerge))
-
-ifeq ($(OS_FOR_BUILD),WNT)
-$(eval $(call gb_Package_add_file,l10ntools_scripts,bin/propex.bat,propex.bat))
-endif
# vim: set noet sw=4 ts=4:
diff --git a/l10ntools/StaticLibrary_transex.mk b/l10ntools/StaticLibrary_transex.mk
index 4e7780120d1d..f7bed0500355 100644
--- a/l10ntools/StaticLibrary_transex.mk
+++ b/l10ntools/StaticLibrary_transex.mk
@@ -39,11 +39,14 @@ $(eval $(call gb_StaticLibrary_set_include,transex,\
$(eval $(call gb_StaticLibrary_use_external,transex,boost_headers))
+$(eval $(call gb_StaticLibrary_use_sdk_api,transex))
+
$(eval $(call gb_StaticLibrary_add_exception_objects,transex,\
l10ntools/source/export2 \
l10ntools/source/merge \
l10ntools/source/file \
l10ntools/source/directory \
+ l10ntools/source/po \
))
# vim: set noet sw=4 ts=4:
diff --git a/l10ntools/inc/export.hxx b/l10ntools/inc/export.hxx
index 9a4ce788ec77..28807f6c95a8 100644
--- a/l10ntools/inc/export.hxx
+++ b/l10ntools/inc/export.hxx
@@ -248,6 +248,27 @@ typedef ::std::vector< ResData* > ResStack;
class WordTransformer;
class ParserQueue;
+//result type of handleArguments()
+struct HandledArgs
+{
+ OString m_sPrj;
+ OString m_sPrjRoot;
+ OString m_sInputFile;
+ OString m_sOutputFile;
+ OString m_sMergeSrc;
+ OString m_sLanguages;
+ bool m_bMergeMode;
+ HandledArgs()
+ : m_sPrj( OString() )
+ , m_sPrjRoot( OString() )
+ , m_sInputFile( OString() )
+ , m_sOutputFile( OString() )
+ , m_sMergeSrc( OString() )
+ , m_sLanguages( OString() )
+ , m_bMergeMode( false )
+ {}
+};
+
class Export
{
private:
@@ -285,6 +306,9 @@ public:
static rtl::OString sLanguages; // public ?
static rtl::OString sForcedLanguages; // public ?
+ static bool handleArguments(int argc, char * argv[], HandledArgs& o_aHandledArgs);
+ static void writeUsage(const OString& rName, const OString& rFileType);
+
static void InitLanguages( bool bMergeMode = false );
static void InitForcedLanguages( bool bMergeMode = false );
static std::vector<rtl::OString> GetLanguages();
diff --git a/l10ntools/inc/helpmerge.hxx b/l10ntools/inc/helpmerge.hxx
index 34dfdc7eb472..401f8392a424 100644
--- a/l10ntools/inc/helpmerge.hxx
+++ b/l10ntools/inc/helpmerge.hxx
@@ -55,8 +55,6 @@ public:
/// point to existing files.
bool Merge( const rtl::OString &rSDFFile_in, const rtl::OString &rDestinationFile_in ,
const rtl::OString& sLanguage , MergeDataFile& aMergeDataFile );
- bool Merge( const rtl::OString &rSDFFile, const rtl::OString &rPathX , const rtl::OString &rPathY , bool bISO
- , const std::vector<rtl::OString>& aLanguages , MergeDataFile& aMergeDataFile , bool bCreateDir );
private:
rtl::OString GetOutpath( const rtl::OString& rPathX , const rtl::OString& sCur , const rtl::OString& rPathY );
diff --git a/l10ntools/inc/po.hxx b/l10ntools/inc/po.hxx
new file mode 100644
index 000000000000..856c7bb04ff1
--- /dev/null
+++ b/l10ntools/inc/po.hxx
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef _PO_INCLUDED
+#define _PO_INCLUDED
+
+#include <fstream>
+#include <rtl/string.hxx>
+#include <boost/noncopyable.hpp>
+
+class PoOfstream;
+class PoIfstream;
+class GenPoEntry;
+
+class PoEntry
+{
+private:
+
+ GenPoEntry* m_pGenPo;
+ bool m_bIsInitialized;
+
+public:
+
+ friend class PoOfstream;
+ friend class PoIfstream;
+
+ enum SDFPART { PROJECT, SOURCEFILE, DUMMY, RESOURCETYPE, GROUPID,
+ LOCALID, HELPID, PLATFORM, WIDTH, LANGUAGEID,
+ TEXT, HELPTEXT, QUICKHELPTEXT, TITLE, TIMESTAMP };
+ enum TYPE { TTEXT=TEXT, TQUICKHELPTEXT=QUICKHELPTEXT, TTITLE=TITLE };
+ enum Exception { INVALIDSDFLINE };
+
+ PoEntry();
+ PoEntry(const OString& rSDFLine,
+ const TYPE eType = TTEXT);
+ ~PoEntry();
+
+ PoEntry( const PoEntry& rPo );
+ PoEntry& operator=( const PoEntry& rPo );
+
+ OString getSourceFile() const;
+ OString getGroupId() const;
+ OString getLocalId() const;
+ OString getResourceType() const;
+ TYPE getType() const;
+ OString getMsgId() const;
+ OString getMsgStr() const;
+ bool isFuzzy() const;
+ OString getKeyId() const;
+ void setMsgId(const OString& rUnTransStr);
+ void setMsgStr(const OString& rTransStr);
+ void setFuzzy(const bool bFuzzy);
+
+ static bool IsInSameComp(const PoEntry& rPo1,const PoEntry& rPo2);
+
+};
+
+class PoHeader: private boost::noncopyable
+{
+private:
+
+ GenPoEntry* m_pGenPo;
+ bool m_bIsInitialized;
+
+public:
+
+ friend class PoOfstream;
+ friend class PoIfstream;
+
+ enum Exception { NOLANG };
+
+ PoHeader();
+ PoHeader( const OString& rExtSrc );
+ PoHeader( std::ifstream& rOldPo );
+ ~PoHeader();
+
+ OString getLanguage() const;
+};
+
+class PoOfstream: private boost::noncopyable
+{
+private:
+
+ std::ofstream m_aOutPut;
+ bool m_bIsAfterHeader;
+
+public:
+ PoOfstream();
+ ~PoOfstream();
+ bool isOpen() const { return m_aOutPut.is_open(); }
+
+ void open(const OString& rFileName);
+ void close();
+ void writeHeader(const PoHeader& rHeader);
+ void writeEntry(const PoEntry& rPo);
+};
+
+class PoIfstream: private boost::noncopyable
+{
+private:
+
+ std::ifstream m_aInPut;
+ bool m_bIsAfterHeader;
+ bool m_bEof;
+
+public:
+
+ enum Exception { INVALIDENTRY, INVALIDHEADER };
+
+ PoIfstream();
+ ~PoIfstream();
+ bool isOpen() const { return m_aInPut.is_open(); }
+ bool eof() const { return m_bEof; }
+
+ void open(const OString& rFileName);
+ void close();
+ void readHeader(PoHeader& rHeader);
+ void readEntry(PoEntry& rPo);
+};
+
+#endif // _PO_INCLUDED
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/inc/propmerge.hxx b/l10ntools/inc/propmerge.hxx
new file mode 100644
index 000000000000..4f0e3275a434
--- /dev/null
+++ b/l10ntools/inc/propmerge.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef _PROPMERGE_INCLUDED
+#define _PROPMERGE_INCLUDED
+
+#include <rtl/string.hxx>
+#include <vector>
+
+class PropParser
+{
+private:
+ std::vector<OString> m_vLines;
+ OString m_sSource;
+ OString m_sLang;
+ bool m_bIsInitialized;
+
+public:
+ PropParser(
+ const OString& rInputFile, const OString& rLang,
+ const bool bMergeMode );
+ ~PropParser();
+
+ bool isInitialized() const { return m_bIsInitialized; }
+ void Extract(
+ const OString& rSDFFile, const OString& rPrj, const OString& rRoot );
+ void Merge( const OString &rMergeSrc, const OString &rDestinationFile );
+};
+
+#endif //_PROPMERGE_INCLUDED
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/inc/tagtest.hxx b/l10ntools/inc/tagtest.hxx
deleted file mode 100644
index a6ccec4d73ea..000000000000
--- a/l10ntools/inc/tagtest.hxx
+++ /dev/null
@@ -1,346 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#ifndef _TAGTEST_HXX_
-#define _TAGTEST_HXX_
-
-#include <boost/unordered_map.hpp>
-#include <vector>
-
-class GSILine;
-
-typedef sal_Int32 TokenId;
-
-#define TOK_INVALIDPOS (-1)
-
-class ParserMessage;
-typedef ::std::vector< ParserMessage* > Impl_ParserMessageList;
-
-class ParserMessageList;
-
-typedef boost::unordered_map<rtl::OString, rtl::OUString, rtl::OStringHash> StringHashMap;
-
-class TokenInfo
-{
-private:
- void SplitTag( ParserMessageList &rErrorList );
-
- rtl::OUString aTagName;
- StringHashMap aProperties;
- sal_Bool bClosed; // tag is closed <sdnf/>
- sal_Bool bCloseTag; // tag is close Tag </sdnf>
-
-
- sal_Bool bIsBroken;
- sal_Bool bHasBeenFixed;
- sal_Bool bDone;
-
-public:
-
- rtl::OUString aTokenString;
- TokenId nId;
- sal_Int32 nPos; // Position in String
-
- TokenInfo():bClosed(sal_False),bCloseTag(sal_False),bIsBroken(sal_False),bHasBeenFixed(sal_False),bDone(sal_False),nId( 0 ){;}
-explicit TokenInfo( TokenId pnId, sal_Int32 nP ):bClosed(sal_False),bCloseTag(sal_False),bIsBroken(sal_False),bHasBeenFixed(sal_False),bDone(sal_False),nId( pnId ),nPos(nP){;}
- explicit TokenInfo( TokenId pnId, sal_Int32 nP, rtl::OUString const & paStr ):bClosed(sal_False),bCloseTag(sal_False),bIsBroken(sal_False),bHasBeenFixed(sal_False),bDone(sal_False),aTokenString( paStr ),nId( pnId ),nPos(nP) {;}
- explicit TokenInfo( TokenId pnId, sal_Int32 nP, rtl::OUString const & paStr, ParserMessageList &rErrorList );
-
- rtl::OUString GetTagName() const;
-
- rtl::OUString MakeTag() const;
-
- /**
- Is the property to be ignored or does it have the default value anyways
- **/
- sal_Bool IsPropertyRelevant( const rtl::OString &rName, const rtl::OUString &rValue ) const;
- sal_Bool IsPropertyValueValid( const rtl::OString &rName, const rtl::OUString &rValue ) const;
- /**
- Does the property contain the same value for all languages
- e.g.: the href in a link tag
- **/
- sal_Bool IsPropertyInvariant( const rtl::OString &rName, const rtl::OUString &rValue ) const;
- /**
- a subset of IsPropertyInvariant but containing only those that are fixable
- we dont wat to fix e.g.: ahelp :: visibility
- **/
- sal_Bool IsPropertyFixable( const rtl::OString &rName ) const;
- sal_Bool MatchesTranslation( TokenInfo& rInfo, sal_Bool bGenErrors, ParserMessageList &rErrorList, sal_Bool bFixTags = sal_False ) const;
-
- sal_Bool IsDone() const { return bDone; }
- void SetDone( sal_Bool bNew = sal_True ) { bDone = bNew; }
-
- sal_Bool HasBeenFixed() const { return bHasBeenFixed; }
- void SetHasBeenFixed( sal_Bool bNew = sal_True ) { bHasBeenFixed = bNew; }
-};
-
-
-class ParserMessageList
-{
-private:
- Impl_ParserMessageList maList;
-
-public:
- ~ParserMessageList() { clear(); }
- void AddError( sal_Int32 nErrorNr, const rtl::OString& rErrorText, const TokenInfo &rTag );
- void AddWarning( sal_Int32 nErrorNr, const rtl::OString& rErrorText, const TokenInfo &rTag );
-
- sal_Bool HasErrors();
- bool empty() const { return maList.empty(); }
- size_t size() const { return maList.size(); }
- ParserMessage* operator [] ( size_t i ) { return ( i < maList.size() ) ? maList[ i ] : NULL; }
- void clear();
-};
-
-
-#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 )
-
-typedef ::std::vector< TokenInfo* > TokenListImpl;
-
-class TokenList
-{
-private:
- TokenListImpl maList;
- TokenList& operator =( const TokenList& rList );
-
-public:
- TokenList() {}
- ~TokenList(){ clear(); }
-
- size_t size() const { return maList.size(); }
- void clear()
- {
- for ( size_t i = 0 ; i < maList.size() ; i++ )
- delete maList[ i ];
- maList.clear();
- }
-
- void insert( TokenInfo p, size_t nIndex = size_t(-1) )
- {
- if ( nIndex < maList.size() ) {
- TokenListImpl::iterator it = maList.begin();
- ::std::advance( it, nIndex );
- maList.insert( it, new TokenInfo(p) );
- } else {
- maList.push_back( new TokenInfo(p) );
- }
- }
- TokenInfo& operator [] ( size_t nIndex ) const
- {
- return *maList[ nIndex ];
- }
-
- TokenList( const TokenList& rList );
-};
-
-class ParserMessage
-{
- sal_Int32 nErrorNr;
- rtl::OString aErrorText;
- sal_Int32 nTagBegin,nTagLength;
-
-protected:
- ParserMessage( sal_Int32 PnErrorNr, const rtl::OString &rPaErrorText, const TokenInfo &rTag );
-public:
-
- sal_Int32 GetErrorNr() { return nErrorNr; }
- rtl::OString GetErrorText() { return aErrorText; }
-
- sal_Int32 GetTagBegin() { return nTagBegin; }
- sal_Int32 GetTagLength() { return nTagLength; }
-
- virtual ~ParserMessage() {}
- virtual sal_Bool IsError() =0;
- virtual rtl::OString Prefix() =0;
-};
-
-class ParserError : public ParserMessage
-{
-public:
- ParserError( sal_Int32 PnErrorNr, const rtl::OString &rPaErrorText, const TokenInfo &rTag );
-
- virtual sal_Bool IsError() {return sal_True;}
- virtual rtl::OString Prefix() {return rtl::OString(RTL_CONSTASCII_STRINGPARAM("Error:")); }
-};
-
-class ParserWarning : public ParserMessage
-{
-public:
- ParserWarning( sal_Int32 PnErrorNr, const rtl::OString &rPaErrorText, const TokenInfo &rTag );
-
- virtual sal_Bool IsError() {return sal_False;}
- virtual rtl::OString Prefix() {return rtl::OString(RTL_CONSTASCII_STRINGPARAM("Warning:")); }
-};
-
-class SimpleParser
-{
-private:
- sal_Int32 nPos;
- rtl::OUString aSource;
- rtl::OUString aLastToken;
- TokenList aTokenList;
-
- TokenInfo aNextTag; // to store closetag in case of combined tags like <br/>
-
- rtl::OUString GetNextTokenString( ParserMessageList &rErrorList, sal_Int32 &rTokeStartPos );
-
-public:
- SimpleParser();
- void Parse( rtl::OUString const & PaSource );
- TokenInfo GetNextToken( ParserMessageList &rErrorList );
- static rtl::OUString GetLexem( TokenInfo const &aToken );
- TokenList& GetTokenList(){ return aTokenList; }
-};
-
-class TokenParser
-{
- sal_Bool match( const TokenInfo &aCurrentToken, const TokenId &aExpectedToken );
- sal_Bool match( const TokenInfo &aCurrentToken, const TokenInfo &aExpectedToken );
- void ParseError( sal_Int32 nErrNr, const rtl::OString &rErrMsg, 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;
- sal_Bool bPfCaseActive ,bAppCaseActive;
-
- TokenId nActiveRefTypes;
-
- ParserMessageList *pErrorList;
-
-public:
- TokenParser();
- void Parse( const rtl::OUString &aCode, ParserMessageList* pList );
- TokenList& GetTokenList(){ return aParser.GetTokenList(); }
-};
-
-class LingTest
-{
-private:
- TokenParser aReferenceParser;
- TokenParser aTesteeParser;
- ParserMessageList aCompareWarningList;
- void CheckTags( TokenList &aReference, TokenList &aTestee, sal_Bool bFixTags );
- sal_Bool IsTagMandatory( TokenInfo const &aToken, TokenId &aMetaTokens );
- rtl::OUString aFixedTestee;
-public:
- void CheckReference( GSILine *aReference );
- void CheckTestee( GSILine *aTestee, sal_Bool bHasSourceLine, sal_Bool bFixTags );
-
- ParserMessageList& GetCompareWarnings(){ return aCompareWarningList; }
- sal_Bool HasCompareWarnings(){ return ( !aCompareWarningList.empty() ); }
-
- rtl::OUString GetFixedTestee(){ return aFixedTestee; }
-};
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/inc/treemerge.hxx b/l10ntools/inc/treemerge.hxx
new file mode 100644
index 000000000000..3b681126bfab
--- /dev/null
+++ b/l10ntools/inc/treemerge.hxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef _TREEMERGE_INCLUDED
+#define _TREEMERGE_INCLUDED
+
+#include <libxml/tree.h>
+#include <rtl/string.hxx>
+#include <vector>
+
+class TreeParser
+{
+private:
+ xmlDocPtr m_pSource;
+ OString m_sLang;
+ bool m_bIsInitialized;
+
+public:
+ TreeParser(
+ const OString& rInputFile, const OString& rLang );
+ ~TreeParser();
+
+ bool isInitialized() const { return m_bIsInitialized; }
+ void Extract(
+ const OString& rSDFFile, const OString& rPrj, const OString& rRoot );
+ void Merge(
+ const OString &rMergeSrc, const OString &rDestinationFile,
+ const OString &rXhpRoot );
+};
+
+#endif //_TREEMERGE_INCLUDED
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/prj/build.lst b/l10ntools/prj/build.lst
index 5f7fca144415..af0fdfeff475 100644
--- a/l10ntools/prj/build.lst
+++ b/l10ntools/prj/build.lst
@@ -1,3 +1,3 @@
-tr l10ntools : EXPAT:expat LIBXSLT:libxslt sal NULL
+tr l10ntools : EXPAT:expat LIBXSLT:libxslt ICU:icu sal NULL
tr l10ntools usr1 - all tr_mkout NULL
tr l10ntools\prj nmake - all tr_prj NULL
diff --git a/l10ntools/scripts/po2lo b/l10ntools/scripts/po2lo
index cdf8892fc950..6303c63a6fa7 100755
--- a/l10ntools/scripts/po2lo
+++ b/l10ntools/scripts/po2lo
@@ -41,6 +41,7 @@ class Entry:
"""Represents a single line in an SDF file."""
def __init__(self, items):
+ self.has_po = None
self.items = items # list of 15 fields
path = self.items[1].split('\\')
self.po = "%s/%s/%s.po" % (options.input.replace('\\', '/'), self.items[0], "/".join(path[:-1]))
@@ -65,13 +66,22 @@ class Entry:
"""Translates text in the entry based on translations."""
self.items[9] = options.language
+ self.items[2] = ""
+ self.has_po = False
for idx, key in self.keys:
try:
- self.items[idx] = translations.data[(self.po, key)]
+ self.items[8] = str(translations.snumber[(self.po, key)])
+ self.has_po = True
+ (text, fuzzy) = translations.data[(self.po, key)]
+ if fuzzy:
+ self.items[2] += "1"
+ else:
+ self.items[2] += "0"
+ self.items[idx] = text
self.items[14] = "2002-02-02 02:02:02"
except KeyError:
- pass
+ self.items[idx]=""
self.items[14] = self.items[14].strip()
def sdf2po(self, s):
@@ -95,8 +105,11 @@ class Template:
sock = xopen(options.output, "w", encoding='utf-8')
for line in self.lines:
+ temp = "\t".join(line.items)
line.translate(translations)
- sock.write("\t".join(line.items)+"\r\n")
+ if line.has_po:
+ sock.write(temp)
+ sock.write("\t".join(line.items)+"\r\n")
sock.close()
class Translations:
@@ -104,6 +117,8 @@ class Translations:
def __init__(self):
self.data = {}
+ self.snumber = {}
+ counter = 0
for root, dirs, files in os.walk(options.input):
for file in files:
path = "%s/%s" % (root, file)
@@ -115,16 +130,17 @@ class Translations:
for line in sock:
if line.startswith("#: "):
key = line.strip()[3:]
+ fuzzy = False
elif line.startswith("#, fuzzy"):
fuzzy = True
+ elif line.startswith("msgid "):
+ counter = counter + 1
+ self.setserialnumber(path, key, counter)
elif line.startswith("msgstr "):
trans = line.strip()[8:-1]
if len(trans):
- if fuzzy:
- fuzzy = False
- else:
- self.setdata(path, key, trans)
- multiline = False
+ self.setdata(path, key, trans, fuzzy)
+ multiline = False
else:
buf = []
buf.append(trans)
@@ -132,16 +148,13 @@ class Translations:
elif multiline and line.startswith('"'):
buf.append(line.strip()[1:-1])
elif multiline and not len(line.strip()) and len("".join(buf)):
- if fuzzy:
- fuzzy = False
- else:
- self.setdata(path, key, "".join(buf))
+ self.setdata(path, key, "".join(buf),fuzzy)
buf = []
multiline = False
- if multiline and len("".join(buf)) and not fuzzy:
- self.setdata(path, key, "".join(buf))
+ if multiline and len("".join(buf)):
+ self.setdata(path, key, "".join(buf),fuzzy)
- def setdata(self, path, key, s):
+ def setdata(self, path, key, s, fuzzy = False):
"""Sets the translation for a given path and key, handling (un)escaping
as well."""
if key:
@@ -151,7 +164,10 @@ class Translations:
s = self.escape_help_text(s)
else:
s = s.replace('\\\\', '\\')
- self.data[(path.replace('\\', '/'), key)] = s
+ self.data[(path.replace('\\', '/'), key)] = ( s , fuzzy )
+
+ def setserialnumber(self, path, key, number):
+ self.snumber[(path.replace('\\', '/'), key)] = ( number )
def escape_help_text(self, text):
"""Escapes the help text as it would be in an SDF file."""
diff --git a/l10ntools/scripts/propex b/l10ntools/scripts/propex
deleted file mode 100755
index 35dcb258e381..000000000000
--- a/l10ntools/scripts/propex
+++ /dev/null
@@ -1,68 +0,0 @@
-:
-eval 'exec perl -S $0 ${1+"$@"}'
- if 0;
-# Version: MPL 1.1 / GPLv3+ / LGPLv3+
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License or as specified alternatively below. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Initial Developer of the Original Code is
-# Andras Timar <atimar@suse.com>
-# Portions created by the Initial Developer are Copyright (C) 2011 the
-# Initial Developer. All Rights Reserved.
-#
-# Major Contributor(s):
-#
-# For minor contributions see the git repository.
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
-# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
-# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
-# instead of those above.
-#
-# extracts strings from Java properties files
-#
-
-use strict;
-use File::Basename;
-use Getopt::Std;
-use Cwd;
-
-my %options=();
-getopts("ep:r:i:o:l:", \%options);
-
-unless ( $options{i} =~ m/en_US/ ) {exit 0;}
-
-$options{i} =~ s|\\|/|g; # fix path on Windows, Perl expects / separator
-my ($unused1, $dir, $unused2) = File::Basename::fileparse($options{i});
-my $file = substr ( Cwd::abs_path($options{i}), length(Cwd::abs_path($dir . $options{r})) + 1 );
-$file =~ s|/|\\|g;
-
-open (INFILE, "<$options{i}") || die "propex: cannot open input file: $options{i}";
-open (OUTFILE, ">$options{o}") || die "propex: cannot open output file: $options{o}";
-
-while (<INFILE>) {
- chomp;
- if (/=/) {
- my ($id, $value) = split /=/;
- $id =~ s/^\s+//; #remove leading spaces
- $id =~ s/\s+$//; #remove trailing spaces
- $value =~ s/^\s+//; #remove leading spaces
- $value =~ s/\s+$//; #remove trailing spaces
- $value =~ s/(\\u([0-9a-fA-F]{4}))/pack("C0U1",hex($2))/ge; #convert ascii escaped unicode to utf-8
- print OUTFILE "$options{p}\t$file\t0\tproperty\t$id\t\t\t\t0\ten-US\t$value\t\t\t\t20020202 02:02:02\n";
- }
-}
-
-close (INFILE);
-close (OUTFILE);
-
-exit 0;
diff --git a/l10ntools/scripts/propex.bat b/l10ntools/scripts/propex.bat
deleted file mode 100755
index 1174286920da..000000000000
--- a/l10ntools/scripts/propex.bat
+++ /dev/null
@@ -1,8 +0,0 @@
-@echo off
-
-if "x%PERL%x" EQU "xx" (
- echo ERROR: Perl not found. Environment is not set.
- exit /b 1
-)
-
-%PERL% %SOLARVER%\%INPATH%\bin\propex %* \ No newline at end of file
diff --git a/l10ntools/scripts/propmerge b/l10ntools/scripts/propmerge
deleted file mode 100755
index 5ba420d5c858..000000000000
--- a/l10ntools/scripts/propmerge
+++ /dev/null
@@ -1,88 +0,0 @@
-:
-eval 'exec perl -S $0 ${1+"$@"}'
- if 0;
-# Version: MPL 1.1 / GPLv3+ / LGPLv3+
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License or as specified alternatively below. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Initial Developer of the Original Code is
-# Andras Timar <atimar@suse.com>
-# Portions created by the Initial Developer are Copyright (C) 2011 the
-# Initial Developer. All Rights Reserved.
-#
-# Major Contributor(s):
-#
-# For minor contributions see the git repository.
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
-# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
-# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
-# instead of those above.
-#
-# merges strings from SDF file to properties files
-#
-
-use strict;
-use Getopt::Std;
-
-my %options=();
-getopts("i:m:", \%options);
-
-my %translations = ();
-my %languages = ();
- # ( leftpart ) ( rightpart )
- # prj file dummy type gid lid helpid pform width lang text helptext qhelptext title
-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]*)))";
-
-open (SDFFILE, "<$options{m}") || die "propmerge: cannot open sdf file: $options{m}";
-
-while (<SDFFILE>) {
- chomp;
- if( /$sdf_regex/ ) {
- my $gid = defined $7 ? $7 : '';
- my $lang = defined $12 ? $12 : '';
- my $text = defined $14 ? $14 : '';
- my $key = $lang . $gid;
- $languages{$lang} = 1;
- utf8::decode($text);
- $text =~ s/([^\x{20}-\x{7E}])/sprintf("\\u%04X",ord($1))/ge;
- $translations{$key} = $text;
- }
-}
-
-close (SDFFILE);
-
-foreach my $lang (keys %languages) {
- my $locfilename = $options{i};
- $lang =~ s/-/_/;
- $locfilename =~ s/en_US\.properties/$lang.properties/;
- $lang =~ s/_/-/;
- open (INFILE, "<$options{i}") || die "propmerge: cannot open source file: $options{i}";
- open (OUTFILE, ">$locfilename") || die "propmerge: cannot open output file: $locfilename";
- while (<INFILE>) {
- if (/=/) {
- chomp;
- my ($id, $value) = split /=/;
- $id =~ s/^\s+//; #remove leading spaces
- $id =~ s/\s+$//; #remove trailing spaces
- my $key = $lang . $id;
- print OUTFILE "$id=$translations{$key}\n";
- }
- else {
- print OUTFILE "$_";
- }
- }
- close (INFILE);
- close (OUTFILE);
-}
-
-exit 0;
diff --git a/l10ntools/scripts/update_tree.pl b/l10ntools/scripts/update_tree.pl
deleted file mode 100644
index 02faf6a37c72..000000000000
--- a/l10ntools/scripts/update_tree.pl
+++ /dev/null
@@ -1,394 +0,0 @@
-:
-eval 'exec perl -wS $0 ${1+"$@"}'
- if 0;
-#*************************************************************************
-#
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# Copyright 2000, 2010 Oracle and/or its affiliates.
-#
-# OpenOffice.org - a multi-platform office productivity suite
-#
-# 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 Cwd 'abs_path';
-use File::Find;
-use File::Copy qw/cp mv/;
-use File::Basename;
-
-# update the tree files in <platform>/misc/*
-
-$| = 1;
-
-my $prj = $ENV{PWD};
-
-my $inpath = $ENV{WORKDIR};
-terminate() if ( ! defined $inpath );
-
-my $destpath = $inpath;
-my $with_lang = $ARGV[1];
-my $xmllint = $ENV{XMLLINT} || "$ENV{OUTDIR_FOR_BUILD}/bin/xmllint";
-
-$tree_target_prefix = $ARGV[4];
-
-# Always use / directory separators
-$prj =~ s/\\/\//g if defined($prj);
-$inpath =~ s/\\/\//g;
-$destpath =~ s/\\/\//g;
-
-if ( ! defined $prj ) {
-# do someting that works for manual call
- ($scriptname = `pwd`) =~ s/\n/\/$0/;
- ($tree_src = $scriptname) =~ s/\/update_tree.pl/\/..\/source\/auxiliary/;
- ($tree_dest = $scriptname) =~ s/\/update_tree.pl/\/..\/$destpath\/misc/;
- ($source_dir = $scriptname) =~ s/\/update_tree.pl/\/..\/source/;
- ($source_dir_xhp = $scriptname) =~ s/\/update_tree.pl/\/..\/source/;
-
- if ( defined $ENV{TRYSDF} || defined $ENV{LOCALIZESDF} )
- {
- if( defined $ENV{LOCALIZATION_FOUND} && $ENV{LOCALIZATION_FOUND} eq "YES" )
- {
- $source_dir = $ENV{TRYSDF};
- }
- elsif( defined $ENV{LOCALIZESDF} && $ENV{LOCALIZESDF} ne "" )
- {
- $source_dir = $ENV{LOCALIZESDF};
- }
- $source_dir =~ s/\/auxiliary\/localize.sdf$// ;
- }
- $treestrings = "$ARGV[0]";
- $treestrings=~ s/\/*.tree//g;
-} else {
- $source_dir_xhp = "$prj/source/presenter/help";
- $tree_src = "$ARGV[0]";
- $tree_src =~ s/\/help.tree//g;
- $tree_dest = "$ARGV[3]";
- $tree_dest =~ s/\/help.tree//g;
- $source_dir = "$ARGV[2]";
- $source_dir =~ s/\/localize.sdf//g;
- $treestrings = "$ARGV[0]";
- $treestrings=~ s/\/help.tree/\/tree_strings.xhp/g;
-
- if( defined $ENV{LOCALIZATION_FOUND} && $ENV{LOCALIZATION_FOUND} eq "YES" )
- {
- $source_dir = $ENV{TRYSDF};
- }
- elsif ( defined $ENV{LOCALIZESDF} && $ENV{LOCALIZESDF} ne "" )
- {
- $source_dir = $ENV{LOCALIZESDF};
- }
- $source_dir =~ s/\/auxiliary\/localize.sdf$// ;
-}
-
-# Get the English tree files as master
-#-------------------------------
-# Update English from xhp
-#-------------------------------
-&do_english;
-#-------------------------------
-# Update localizations from sdf
-#-------------------------------
-
-if( defined $with_lang && $with_lang ne "" )
-{
- @langs = split /\s+/, $with_lang;
- &read_loc;
- for $l(@langs)
- {
- #if ($l ne "en-US") {
- &do_lang($l);
- #}
- }
-}
-else
-{
- print "\nNo WITH_LANG set, skipping l10n\n";
-}
-#-------------------------------
-#
-
-####################
-# SUBS
-####################
-sub terminate {
- $err = shift;
- print "$err\n\n";
- $msg = <<"MSG";
-
-update_tree.pl
- all languages in WITH_LANG are processed. WITH_LANG=ALL is
- not supported in manual calls.
-
- Updates the *.tree files.
- At first, the English file is updated based on the English
- help topic titles as read from the help files. Then, the
- localized tree files are written based on the English tree
- file and the localized help topic titles.
-
- Requires a valid LibreOffice build environment.
-MSG
- print "$msg\n";
- exit( -1 );
- # die "$msg\n";
-}
-
-#---------------------------------------------------
-
-sub do_english {
- undef %helpsection; undef %node;
- &readtreestrings;
- &gettreefiles;
-}
-
-#---------------------------------------------------
-sub do_lang {
- $lng = shift;
- print "Processing $lng\n";
- &processtreefiles($lng);
-}
-
-#---------------------------------------------------
-sub readtreestrings {
- if (open TREE, $treestrings) {
- print "Processing readtreestrings\n";
- while (<TREE>) {
- chomp;
- s/<\/*help:productname>//gis;
- if (/help_section/) {
- s/^\s*<.*help_section//;
- s/<\/.*$//;
- ($id = $_) =~ s/^.*id=&quot;(\d+)&quot;.*$/$1/;
- ($title = $_) =~ s/^.*title=&quot;(.*)&quot;.*$/$1/;
- $helpsection{$id} = $title;
- }
-
- if (/node id=/) {
- s/^\s*<.*node //;
- s/<\/.*$//;
- ($id = $_) =~ s/^.*id=&quot;(\d+)&quot;.*$/$1/;
- ($title = $_) =~ s/^.*title=&quot;(.*)&quot;.*$/$1/;
- $node{$id} = $title;
- }
- }
- close TREE;
- } else {
- &terminate("Error opening $treestrings");
- }
-}
-
-#------------------------------------
-sub gettreefiles {
- # Read the tree files from the directory
- # this list is also used for all foreign languages
- if (opendir ENUS, "$tree_src") {
- @treeviews = grep /\.tree/, readdir ENUS;
- closedir ENUS;
- } else {
- &terminate("Cannot open directory $tree_src");
- }
-}
-
-#------------------------------------
-sub processtreefiles {
- $lng = shift;
- use File::Temp qw/ tempfile /;
- use File::Spec;
-
- for $tv(@treeviews) {
- @lines = &readtv("$tree_src/$tv");
- for $l(@lines) {
- if ($l =~ /topic/) {
- ($id = $l) =~ s/^.*id="([^"]*)".*$/$1/gis;
- ($module = $id) =~ s/^([^\/]*).*$/$1/;
- $id =~ s/^.*?\///;
- $file = "$source_dir_xhp/$lng/$id";
-
- if ($lng eq 'en-US') { # english comes from the file
- $temp = $l;
- $temp =~ s/^.*<topic[^>]+id=".*"[^>]*>([^<]*)<\/topic>.*$/$1/gis;
- $temp =~ s/&apos;/\'/gis; $temp=~ s/&amp;/+/gis;
- $temp =~ s/&quot;/\'/gis; $temp =~ s/&/+/gis;
-
- $id =~s/^.*\/(.*.xhp)/$1/;
- $l = "<topic id=\"$module/$tree_target_prefix/$id\">$temp</topic>\n";
- } else { # localized comes from the localize sdf
- if (defined($loc_title{$lng}->{$id})) {
- $xhpname = $id;
- $xhpname =~s/^.*\/(.*.xhp)/$1/;
- $l = "<topic id=\"$module/$tree_target_prefix/$xhpname\">$loc_title{$lng}->{$id}</topic>\n";
- } else {
- }
- }
- }
-
- if ($l =~/<node/) {
- ($id = $l) =~ s/^.*id="(\d+)".*$/$1/gis;
- if ($lng eq 'en-US') {
- if (defined($node{$id})) {
- $l =~ s/title="(.*)"/title="$node{$id}"/;
- } else {
- $l =~ s/title="(.*)"/title="NOTFOUND:$id"/;
- }
- } else {
- if (defined($node{$lng}->{$id})) {
- $l =~ s/title="(.*)"/title="$node{$lng}->{$id}"/;
- }
- }
- }
-
- if ($l =~/<help_section/) {
- ($id = $l) =~ s/^.*id="(\d+)".*$/$1/gis;
- if ($lng eq 'en-US') {
- if (defined($helpsection{$id})) {
- $l =~ s/title="(.*)"/title="$helpsection{$id}"/;
- } else {
- $l =~ s/title="(.*)"/title="NOTFOUND:$id"/;
- }
- } else {
- if (defined($helpsection{$lng}->{$id})) {
- $l =~ s/title="(.*)"/title="$helpsection{$lng}->{$id}"/;
- }
- }
- }
- }
-
-
- my $treeoutdir = "$tree_dest";
- my $tmpname_template=$tv."_XXXXX";
- my ( $treetmpfilehandle, $treetmpfile ) = tempfile($tmpname_template , DIR => File::Spec->tmpdir() );
- close $treetmpfilehandle ;
-
- if (open TV, ">$treetmpfile") {
- for $line(@lines) {
- $line =~ s/\$\[officename\]/%PRODUCTNAME/g;
- $line =~ s/\$\[officeversion\]/%PRODUCTVERSION/g;
- print TV $line;
- }
- close TV;
- chmod 0664, $treetmpfile or &terminate("Cannot change rights on $treetmpfile");
- if( $^O eq 'MSWin32' )
- {
- $tree_dest =~ s/\//\\/g ;
- unlink "$tree_dest\\$tv" ;
- mv $treetmpfile , "$tree_dest\\$tv" or &terminate("Cannot mv $treetmpfile to $tree_dest\\$tv" );
- }
- else
- {
- unlink "$tree_dest/$tv" ;
- my $ret=mv $treetmpfile , "$tree_dest/$tv" or &terminate("Cannot write to $tree_dest/$tv - Error $!");
- my $ret=mv "$tree_dest/$tv" , "$tree_dest/$tv" or &terminate("Cannot write to $tree_dest/$tv - Error $!");
- #xmllint is crashing on windows, fixme
- if( $^O ne 'cygwin' )
- {
- system("$xmllint --noout --noent $tree_dest/$tv") == 0 or &terminate("$tree_dest/$tv is illformed xml ($xmllint on $^O)" );
- }
- }
- } else {
- &terminate("Cannot write to $tvout");
- }
- }
-}
-
-#------------------------------------
-sub readtv {
- my $f = shift;
- if (open TV, $f) {
- $/ = "\n";
- my @l = <TV>;
- close TV;
- return @l;
- } else {
- &terminate("Error opening $f");
- }
-}
-
-#-------------------------------------
-# read entries from localize.sdf files
-#-------------------------------------
-sub read_loc {
- $/ = "\n";
- my $path = "$source_dir";
- @files = `find $source_dir -name localize.sdf`;
- for my $fname (@files) {
- $FS = '\t';
- open(LOCALIZE_SDF, $fname) || die 'Cannot open "localize.sdf".'."$fname";
- while (<LOCALIZE_SDF>) {
- my $sdf_line = $_;
- my ($Fld1,$file,$Fld3,$Fld4,$id,$Fld6,$Fld7,$Fld8,$Fld9,$lang,$text) = split($FS, $sdf_line , 12);
- next if ( $Fld1 =~ /^#/);
- if ($id eq 'tit') {
- #strip filename
- $file =~ s/.*text\\/text\\/g;
- #convert \ to / in filename
- $file =~ s/\\/\//g;
- $file =~ s/^.*\/(.*)\/(.*)$/$1\/$2/;
- #fpe: i46823 - need to encode &s, added encoding
- $text =~ s/&(?!amp;)/&amp;/g;
- #help xml tags are not allowed in .tree files
- $text =~ s/\\<.*?\\>//g;
- # add entry to the hash
-
- $loc_title{$lang}->{$file} = $text;
- }
- if ($file =~ /tree_strings.xhp/) {
- #strip filename
- $file =~ s/.*text/text/g;
- #convert \ to / in filename
- $file =~ s/\\/\//g;
- if ($text =~ /^<help_section/) {
- #example: <help_section application="scalc" id="08" title="表計算ドキュメント">
- my ($fld1,$app,$fld3,$id,$fld5,$sec_title) = split('"', $text, 7);
- #fpe: i46823 - need to encode &s, added encoding
- if( defined $sec_title )
- {
- $sec_title =~ s/&(?!amp;)/&amp;/g;
- #help xml tags are not allowed in .tree files
- $sec_title =~ s/\\<.*?\\>//g;
- #unquot \<item ... /\>
- terminate( "\n\nERROR: Bad string in file '$fname' will cause invalid xml tree file \n---\n'$sdf_line'\n---\nPlease remove or replace < = '&lt;' and > = '&gt;' within the title attribute '$sec_title'\n") , if( $sec_title =~ /[\<\>]/ );
- $helpsection{$lang}->{$id} = $sec_title;
- }
- } elsif ($text =~/<node id=/) {
- # example: <node id="0205" title="Tabelas em documentos de texto">
- # BEWARE: title may contain escaped '"' so only match " not preceded by \
- # using a zero‐width negative look‐behind assertion.
- my ($fld1,$id,$fld3,$node_title,$Fld5) = split(/(?<!\\)"/, $text, 5);
- #fpe: i46823 - need to encode &s, added encoding
- if( defined $node_title )
- {
- $node_title =~ s/&(?!amp;)/&amp;/g;
- #help xml tags are not allowed in .tree files
- $node_title =~ s/\\<.*?\\>//g;
- terminate( "\n\nERROR: Bad string in '$fname' will cause invalid xml tree file \n---\n'$sdf_line'\n---\nPlease remove or replace < = '&lt;' and > = '&gt;' within the title attribute '$node_title'\n") , if( $node_title =~ /[\<\>]/ );
- }
- $node{$lang}->{$id} = $node_title;
- }
- }
- }
- close LOCALIZE_SDF;
- }
- # statistics
- $total_elements=0;
- foreach $lang (keys %loc_title) {
- $no_elements = scalar(keys(%{$loc_title{$lang}}));
- push(@langstat, "$lang:\t ".$no_elements." matches\n");
- $total_elements += $no_elements;
- }
-}
diff --git a/l10ntools/source/cfgmerge.cxx b/l10ntools/source/cfgmerge.cxx
index 41db0973fb47..1d0a819b3d4c 100644
--- a/l10ntools/source/cfgmerge.cxx
+++ b/l10ntools/source/cfgmerge.cxx
@@ -38,105 +38,44 @@ namespace {
namespace global {
-bool mergeMode = false;
-char const * prj = 0;
-char const * prjRoot = 0;
-char const * inputPathname = 0;
-char const * outputPathname = 0;
-char const * mergeSrc;
+OString inputPathname;
boost::scoped_ptr< CfgParser > parser;
}
-
-void handleArguments(int argc, char ** argv) {
- for (int i = 1; i != argc; ++i) {
- if (std::strcmp(argv[i], "-e") == 0) {
- // ignored, used to be "Disable writing errorlog"
- } else if (std::strcmp(argv[i], "-i") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::inputPathname = argv[i];
- } else if (std::strcmp(argv[i], "-l") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- Export::sLanguages = argv[i];
- } else if (std::strcmp(argv[i], "-m") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::mergeSrc = argv[i];
- global::mergeMode = true;
- } else if (std::strcmp(argv[i], "-o") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::outputPathname = argv[i];
- } else if (std::strcmp(argv[i], "-p") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::prj = argv[i];
- } else if (std::strcmp(argv[i], "-r") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::prjRoot = argv[i];
- } else {
- global::inputPathname = 0; // no valid command line
- break;
- }
- }
- if (global::inputPathname == 0 || global::outputPathname == 0) {
- std::fprintf(
- stderr,
- ("Syntax: cfgex [-p Prj] [-r PrjRoot] -i FileIn -o FileOut"
- " [-m DataBase] [-e] [-l l1,l2,...]\n"
- " Prj: Project\n"
- " PrjRoot: Path to project root (../.. etc.)\n"
- " FileIn: Source files (*.src)\n"
- " FileOut: Destination file (*.*)\n"
- " DataBase: Mergedata (*.sdf)\n"
- " -e: ignored\n"
- " -l: Restrict the handled languages; l1, l2, ... are elements of"
- " (de, en-US, ...)\n"));
- std::exit(EXIT_FAILURE);
- }
- Export::InitLanguages();
-}
-
}
extern "C" {
FILE * init(int argc, char ** argv) {
- handleArguments(argc, argv);
- FILE * pFile = std::fopen(global::inputPathname, "r");
+ HandledArgs aArgs;
+ if ( !Export::handleArguments(argc, argv, aArgs) )
+ {
+ Export::writeUsage("cfgex","xcu");
+ std::exit(EXIT_FAILURE);
+ }
+ Export::InitLanguages();
+ global::inputPathname = aArgs.m_sInputFile;
+
+ FILE * pFile = std::fopen(global::inputPathname.getStr(), "r");
if (pFile == 0) {
std::fprintf(
stderr, "Error: Cannot open file \"%s\"\n",
- global::inputPathname);
+ global::inputPathname.getStr() );
std::exit(EXIT_FAILURE);
}
- if (global::mergeMode) {
+ if (aArgs.m_bMergeMode) {
global::parser.reset(
new CfgMerge(
- global::mergeSrc, global::outputPathname,
+ aArgs.m_sMergeSrc.getStr(), aArgs.m_sOutputFile.getStr(),
global::inputPathname));
} else {
global::parser.reset(
new CfgExport(
- global::outputPathname, global::prj,
- common::pathnameToken(global::inputPathname, global::prjRoot)));
+ aArgs.m_sOutputFile.getStr(), aArgs.m_sPrj.getStr(),
+ common::pathnameToken(global::inputPathname.getStr(),
+ aArgs.m_sPrjRoot.getStr())));
}
return pFile;
diff --git a/l10ntools/source/export.cxx b/l10ntools/source/export.cxx
index 8fe8057188c3..13870da558a2 100644
--- a/l10ntools/source/export.cxx
+++ b/l10ntools/source/export.cxx
@@ -42,102 +42,45 @@ MergeDataFile * pMergeDataFile = 0; //TODO
namespace global {
-bool mergeMode = false;
-char const * prj = 0;
-char const * prjRoot = 0;
-char const * inputPathname = 0;
-char const * outputPathname = 0;
-char const * mergeSrc;
+OString prj;
+OString prjRoot;
+OString inputPathname;
boost::scoped_ptr< Export > exporter;
}
-
-void handleArguments(int argc, char ** argv) {
- for (int i = 1; i != argc; ++i) {
- if (std::strcmp(argv[i], "-e") == 0) {
- // ingored, used to be "Disable writing errorlog"
- } else if (std::strcmp(argv[i], "-i") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::inputPathname = argv[i];
- } else if (std::strcmp(argv[i], "-l") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- Export::sLanguages = argv[i];
- } else if (std::strcmp(argv[i], "-m") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::mergeSrc = argv[i];
- global::mergeMode = true;
- } else if (std::strcmp(argv[i], "-o") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::outputPathname = argv[i];
- } else if (std::strcmp(argv[i], "-p") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::prj = argv[i];
- } else if (std::strcmp(argv[i], "-r") == 0) {
- if (++i == argc) {
- global::inputPathname = 0; // no valid command line
- break;
- }
- global::prjRoot = argv[i];
- } else {
- global::inputPathname = 0; // no valid command line
- break;
- }
- }
- if (global::inputPathname == 0 || global::outputPathname == 0) {
- std::fprintf(
- stderr,
- ("Syntax: transex3 [-p Prj] [-r PrjRoot] -i FileIn -o FileOut"
- " [-m DataBase] [-e] [-l l1,l2,...]\n"
- " Prj: Project\n"
- " PrjRoot: Path to project root (../.. etc.)\n"
- " FileIn: Source files (*.src)\n"
- " FileOut: Destination file (*.*)\n"
- " DataBase: Mergedata (*.sdf)\n"
- " -e: ignored\n"
- " -l: Restrict the handled languages; l1, l2, ... are elements of"
- " (de, en-US, ...)\n"));
- std::exit(EXIT_FAILURE);
- }
- Export::InitLanguages();
-}
-
}
extern "C" {
FILE * init(int argc, char ** argv) {
- handleArguments(argc, argv);
- FILE * pFile = std::fopen(global::inputPathname, "r");
+ HandledArgs aArgs;
+ if ( !Export::handleArguments(argc, argv, aArgs) )
+ {
+ Export::writeUsage("transex3","src/hrc");
+ std::exit(EXIT_FAILURE);
+ }
+ Export::InitLanguages();
+ global::prj = aArgs.m_sPrj;
+ global::prjRoot = aArgs.m_sPrjRoot;
+ global::inputPathname = aArgs.m_sInputFile;
+
+ FILE * pFile = std::fopen(global::inputPathname.getStr(), "r");
if (pFile == 0) {
std::fprintf(
stderr, "Error: Cannot open file \"%s\"\n",
- global::inputPathname);
+ global::inputPathname.getStr());
std::exit(EXIT_FAILURE);
}
- if (global::mergeMode) {
+ if (aArgs.m_bMergeMode) {
global::exporter.reset(
- new Export(global::mergeSrc, global::outputPathname));
+ new Export(aArgs.m_sMergeSrc.getStr(), aArgs.m_sOutputFile.getStr()));
} else {
sActFileName =
- common::pathnameToken(global::inputPathname, global::prjRoot);
- global::exporter.reset(new Export(global::outputPathname));
+ common::pathnameToken(
+ global::inputPathname.getStr(), global::prjRoot.getStr());
+ global::exporter.reset(new Export(aArgs.m_sOutputFile.getStr()));
}
global::exporter->Init();
diff --git a/l10ntools/source/export2.cxx b/l10ntools/source/export2.cxx
index 726f36a59541..5ef2231f6d6e 100644
--- a/l10ntools/source/export2.cxx
+++ b/l10ntools/source/export2.cxx
@@ -31,6 +31,15 @@
#include <time.h>
#include <stdlib.h>
+//flags for handleArguments()
+#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_LANGUAGES 0x0007
+
//
// class ResData();
//
@@ -82,6 +91,108 @@ rtl::OString Export::sLanguages;
rtl::OString Export::sForcedLanguages;
/*****************************************************************************/
+bool Export::handleArguments(
+ int argc, char * argv[], HandledArgs& o_aHandledArgs)
+{
+ o_aHandledArgs = HandledArgs();
+ sLanguages = "";
+ sal_uInt16 nState = STATE_NON;
+
+ for( int i = 1; i < argc; i++ )
+ {
+ if ( OString( argv[ i ] ).toAsciiUpperCase() == "-I" )
+ {
+ nState = STATE_INPUT; // next token specifies source file
+ }
+ else if ( OString( argv[ i ] ).toAsciiUpperCase() == "-O" )
+ {
+ nState = STATE_OUTPUT; // next token specifies the dest file
+ }
+ else if ( OString( argv[ i ] ).toAsciiUpperCase() == "-P" )
+ {
+ nState = STATE_PRJ; // next token specifies the cur. project
+ }
+ else if ( OString( argv[ i ] ).toAsciiUpperCase() == "-R" )
+ {
+ nState = STATE_ROOT; // next token specifies path to project root
+ }
+ else if ( OString( argv[ i ] ).toAsciiUpperCase() == "-M" )
+ {
+ nState = STATE_MERGESRC; // next token specifies the merge database
+ }
+ else if ( OString( argv[ i ] ).toAsciiUpperCase() == "-L" )
+ {
+ nState = STATE_LANGUAGES;
+ }
+ else
+ {
+ switch ( nState )
+ {
+ case STATE_NON:
+ {
+ return false; // no valid command line
+ }
+ case STATE_INPUT:
+ {
+ o_aHandledArgs.m_sInputFile = OString( argv[i] );
+ }
+ break;
+ case STATE_OUTPUT:
+ {
+ o_aHandledArgs.m_sOutputFile = OString( argv[i] );
+ }
+ break;
+ case STATE_PRJ:
+ {
+ o_aHandledArgs.m_sPrj = OString( argv[i] );
+ }
+ break;
+ case STATE_ROOT:
+ {
+ o_aHandledArgs.m_sPrjRoot = OString( argv[i] );
+ }
+ break;
+ case STATE_MERGESRC:
+ {
+ o_aHandledArgs.m_sMergeSrc = OString( argv[i] );
+ o_aHandledArgs.m_bMergeMode = true;
+ }
+ break;
+ case STATE_LANGUAGES:
+ {
+ sLanguages = OString( argv[i] );
+ }
+ break;
+ }
+ }
+ }
+ if( !o_aHandledArgs.m_sInputFile.isEmpty() &&
+ !o_aHandledArgs.m_sOutputFile.isEmpty() )
+ {
+ return true;
+ }
+ else
+ {
+ o_aHandledArgs = HandledArgs();
+ return false;
+ }
+}
+
+void Export::writeUsage(const OString& rName, const OString& rFileType)
+{
+ std::cout
+ << "Syntax: " << rName.getStr()
+ << " [-p Prj] [-r PrjRoot] -i FileIn -o FileOut"
+ << " [-m DataBase] [-l l1,l2,...]\n"
+ << " Prj: Project\n"
+ << " PrjRoot: Path to project root (../.. etc.)\n"
+ << " FileIn: Source files (*." << rFileType.getStr() << ")\n"
+ << " FileOut: Destination file (*.*)\n"
+ << " DataBase: Mergedata (*.po)\n"
+ << " -l: Restrict the handled languages; l1, l2, ... are elements of"
+ << " (de, en-US, ...)\n";
+}
+
/*****************************************************************************/
void Export::SetLanguages( std::vector<rtl::OString> val ){
/*****************************************************************************/
diff --git a/l10ntools/source/gsicheck.cxx b/l10ntools/source/gsicheck.cxx
deleted file mode 100644
index 1abc00d17ac9..000000000000
--- a/l10ntools/source/gsicheck.cxx
+++ /dev/null
@@ -1,1051 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * 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 "sal/config.h"
-
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <fstream>
-#include <string>
-
-#include <stdio.h>
-
-#include <rtl/strbuf.hxx>
-#include "sal/main.h"
-#include "helper.hxx"
-#include "tagtest.hxx"
-#include "gsicheck.hxx"
-
-sal_Int32 const MAX_GID_LID_LEN = 250;
-
-namespace {
-
-rtl::OString copyUpTo(
- rtl::OString const & text, sal_Int32 start, sal_Int32 maximumLength)
-{
- assert(start >= 0 && start <= text.getLength());
- return text.copy(start, std::min(text.getLength() - start, maximumLength));
-}
-
-rtl::OString addSuffix(
- rtl::OString const & pathname, rtl::OString const & suffix)
-{
- sal_Int32 n = pathname.lastIndexOf('.');
- if (n == -1) {
- fprintf(
- stderr,
- ("Error: pathname \"%s\" does not contain dot to add suffix in"
- " front of\n"),
- pathname.getStr());
- exit(EXIT_FAILURE);
- }
- return pathname.replaceAt(n, 0, suffix);
-}
-
-}
-
-/*****************************************************************************/
-void PrintMessage( rtl::OString const & aType, rtl::OString const & aMsg, rtl::OString const & aPrefix,
- rtl::OString const & aContext, sal_Bool bPrintContext, std::size_t nLine, rtl::OString aUniqueId = rtl::OString() )
-/*****************************************************************************/
-{
- fprintf( stdout, "%s %s, Line %u", aType.getStr(), aPrefix.getStr(), static_cast<unsigned>( nLine ) );
- if ( !aUniqueId.isEmpty() )
- fprintf( stdout, ", UniqueID %s", aUniqueId.getStr() );
- fprintf( stdout, ": %s", aMsg.getStr() );
-
- if ( bPrintContext )
- fprintf( stdout, " \"%s\"", aContext.getStr() );
- fprintf( stdout, "\n" );
-}
-
-/*****************************************************************************/
-void PrintError( rtl::OString const & aMsg, rtl::OString const & aPrefix,
- rtl::OString const & aContext, sal_Bool bPrintContext, std::size_t nLine, rtl::OString const & aUniqueId = rtl::OString() )
-/*****************************************************************************/
-{
- PrintMessage( "Error:", aMsg, aPrefix, aContext, bPrintContext, nLine, aUniqueId );
-}
-
-bool LanguageOK( rtl::OString const & aLang )
-{
- sal_Int32 n = 0;
- rtl::OString t0(aLang.getToken(0, '-', n));
- if (n == -1) {
- return !t0.isEmpty()
- && (helper::isAllAsciiDigits(t0)
- || helper::isAllAsciiLowerCase(t0));
- }
- rtl::OString t1(aLang.getToken(0, '-', n));
- return n == -1
- && !t0.isEmpty() && helper::isAllAsciiLowerCase(t0)
- && !t1.isEmpty() && helper::isAllAsciiUpperCase(t1)
- && !t0.equalsIgnoreAsciiCase(t1);
-}
-
-class LazyStream: public std::ofstream
-{
-
-private:
- rtl::OString aFileName;
- bool bOpened;
-
-public:
- LazyStream()
- : aFileName()
- , bOpened(false)
- {};
-
- void SetFileName( const rtl::OString& rFileName )
- {
- aFileName = rFileName;
- };
-
- void LazyOpen();
-};
-
-void LazyStream::LazyOpen()
-{
- if ( !bOpened )
- {
- open(aFileName.getStr(), std::ios_base::out | std::ios_base::trunc);
- if (!is_open())
- {
- fprintf( stderr, "\nERROR: Could not open Output-File %s!\n\n",
- aFileName.getStr() );
- exit ( 4 );
- }
- bOpened = true;
- }
-}
-
-
-//
-// class GSILine
-//
-
-/*****************************************************************************/
-GSILine::GSILine( const rtl::OString &rLine, std::size_t nLine )
-/*****************************************************************************/
- : nLineNumber( nLine )
- , bOK( sal_True )
- , bFixed ( sal_False )
- , data_( rLine )
-{
- if (rLine.isEmpty()) {
- NotOK();
- return;
- }
-
- aFormat = FORMAT_SDF;
- sal_Int32 n = 0;
- aUniqId = rLine.getToken(0, '\t', n); // token 0
- aUniqId += "/";
- aUniqId += rLine.getToken(0, '\t', n); // token 1
- aUniqId += "/";
- aUniqId += rLine.getToken(1, '\t', n); // token 3
- aUniqId += "/";
- rtl::OString gid(rLine.getToken(0, '\t', n)); // token 4
- aUniqId += gid;
- aUniqId += "/";
- rtl::OString lid(rLine.getToken(0, '\t', n)); // token 5
- aUniqId += lid;
- aUniqId += "/";
- aUniqId += rLine.getToken(0, '\t', n); // token 6
- aUniqId += "/";
- aUniqId += rLine.getToken(0, '\t', n); // token 7
- rtl::OString length(rLine.getToken(0, '\t', n)); // token 8
- aLineType = rtl::OString();
- aLangId = rLine.getToken(0, '\t', n); // token 9
- aText = rLine.getToken(0, '\t', n); // token 10
- aQuickHelpText = rLine.getToken(1, '\t', n); // token 12
- aTitle = rLine.getToken(0, '\t', n); // token 13
- if (n == -1) {
- NotOK();
- return;
- }
- rLine.getToken(0, '\t', n); // token 14
- if (n != -1) {
- NotOK();
- return;
- }
-
- // do some more format checks here
- if (!helper::isAllAsciiDigits(length)) {
- PrintError(
- "The length field does not contain a number!", "Line format",
- length, 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 (gid.getLength() > MAX_GID_LID_LEN || lid.getLength() > MAX_GID_LID_LEN)
- {
- PrintError(
- (rtl::OString(
- RTL_CONSTASCII_STRINGPARAM("GID and LID may only be "))
- + rtl::OString::valueOf(MAX_GID_LID_LEN)
- + rtl::OString(RTL_CONSTASCII_STRINGPARAM(" chars long each"))),
- "Line format", aLangId, true, GetLineNumber(), GetUniqId());
- NotOK();
- }
-}
-
-/*****************************************************************************/
-void GSILine::NotOK()
-/*****************************************************************************/
-{
- bOK = sal_False;
-}
-
-/*****************************************************************************/
-void GSILine::ReassembleLine()
-/*****************************************************************************/
-{
- if (GetLineFormat() != FORMAT_SDF) {
- PrintError(
- "Cannot reassemble line of unknown type (internal Error).",
- "Line format", rtl::OString(), false, GetLineNumber(),
- GetUniqId());
- return;
- }
- rtl::OStringBuffer b;
- sal_Int32 n = 0;
- for (sal_Int32 i = 0; i != 10; ++i) {
- b.append(data_.getToken(0, '\t', n)); // token 0--9
- b.append('\t');
- }
- b.append(aText);
- b.append('\t');
- b.append(data_.getToken(1, '\t', n));
- // token 11; should be empty but there are some places in sc not
- // reflected to sources
- b.append('\t');
- b.append(aQuickHelpText);
- b.append('\t');
- b.append(aTitle);
- b.append('\t');
- b.append(data_.getToken(2, '\t', n)); // token 14
- data_ = b.makeStringAndClear();
-}
-
-//
-// class GSIBlock
-//
-/*****************************************************************************/
-GSIBlock::GSIBlock( sal_Bool PbPrintContext, sal_Bool bSource, sal_Bool bTrans, sal_Bool bRef, sal_Bool bAllowSusp )
-/*****************************************************************************/
- : pSourceLine( NULL )
- , pReferenceLine( NULL )
- , bPrintContext( PbPrintContext )
- , bCheckSourceLang( bSource )
- , bCheckTranslationLang( bTrans )
- , bReference( bRef )
- , bAllowSuspicious( bAllowSusp )
- , bHasBlockError( sal_False )
-{
-}
-
-/*****************************************************************************/
-GSIBlock::~GSIBlock()
-/*****************************************************************************/
-{
- delete pSourceLine;
- delete pReferenceLine;
-
- for ( size_t i = 0, n = maList.size(); i < n; ++i )
- delete maList[ i ];
- maList.clear();
-}
-
-void GSIBlock::InsertLine( GSILine* pLine, const rtl::OString &rSourceLang)
-{
- if ( pLine->GetLanguageId() == rSourceLang )
- {
- if ( pSourceLine )
- {
- PrintError( "Source Language entry double. Treating as Translation.", "File format", "", pLine->GetLineNumber(), pLine->GetUniqId() );
- bHasBlockError = sal_True;
- pSourceLine->NotOK();
- pLine->NotOK();
- }
- else
- {
- pSourceLine = pLine;
- return;
- }
- }
-
- if (!rSourceLang.isEmpty()) // only check blockstructure if source lang is given
- {
- for ( size_t nPos = 0, n = maList.size(); nPos < n; ++nPos )
- {
- if ( maList[ nPos ]->GetLanguageId() == pLine->GetLanguageId() )
- {
- PrintError( "Translation Language entry double. Checking both.", "File format", "", pLine->GetLineNumber(), pLine->GetUniqId() );
- bHasBlockError = sal_True;
- maList[ nPos ]->NotOK();
- pLine->NotOK();
- }
- nPos++;
- }
- }
- maList.push_back( pLine );
-}
-
-/*****************************************************************************/
-void GSIBlock::SetReferenceLine( GSILine* pLine )
-/*****************************************************************************/
-{
- pReferenceLine = pLine;
-}
-
-/*****************************************************************************/
-void GSIBlock::PrintMessage( rtl::OString const & aType, rtl::OString const & aMsg, rtl::OString const & aPrefix,
- rtl::OString const & aContext, std::size_t nLine, rtl::OString const & aUniqueId )
-/*****************************************************************************/
-{
- ::PrintMessage( aType, aMsg, aPrefix, aContext, bPrintContext, nLine, aUniqueId );
-}
-
-/*****************************************************************************/
-void GSIBlock::PrintError( rtl::OString const & aMsg, rtl::OString const & aPrefix,
- rtl::OString const & aContext, std::size_t nLine, rtl::OString const & aUniqueId )
-/*****************************************************************************/
-{
- PrintMessage( "Error:", aMsg, aPrefix, aContext, nLine, aUniqueId );
-}
-
-/*****************************************************************************/
-void GSIBlock::PrintList( ParserMessageList *pList, rtl::OString const & aPrefix,
- GSILine *pLine )
-/*****************************************************************************/
-{
- for ( size_t i = 0 ; i < pList->size() ; i++ )
- {
- ParserMessage *pMsg = (*pList)[ i ];
- rtl::OString aContext;
- if ( bPrintContext )
- {
- if ( pMsg->GetTagBegin() == -1 )
- aContext = pLine->GetText().copy( 0, 300 );
- else
- aContext = helper::abbreviate( pLine->data_, pMsg->GetTagBegin()-150, 300 );
- aContext = aContext.trim();
- }
-
- PrintMessage( pMsg->Prefix(), pMsg->GetErrorText(), aPrefix, aContext, pLine->GetLineNumber(), pLine->GetUniqId() );
- }
-}
-
-/*****************************************************************************/
-sal_Bool GSIBlock::IsUTF8( const rtl::OString &aTestee, sal_Bool bFixTags, sal_Int32 &nErrorPos, rtl::OString &aErrorMsg, sal_Bool &bHasBeenFixed, rtl::OString &aFixed ) const
-/*****************************************************************************/
-{
- rtl::OUString aUTF8Tester(
- rtl::OStringToOUString(aTestee, RTL_TEXTENCODING_UTF8));
- rtl::OString aTestee2(
- rtl::OUStringToOString(aUTF8Tester, RTL_TEXTENCODING_UTF8));
- sal_Int32 i = 0;
- while (i != std::min(aTestee.getLength(), aTestee2.getLength())
- && aTestee[i] == aTestee2[i])
- {
- ++i;
- }
- if (i != aTestee.getLength() || i != aTestee2.getLength())
- {
- aUTF8Tester = rtl::OUString(aTestee.getStr(), i, RTL_TEXTENCODING_UTF8);
- nErrorPos = aUTF8Tester.getLength();
- aErrorMsg = "UTF8 Encoding seems to be broken";
- return sal_False;
- }
-
- nErrorPos = helper::indexOfAnyAsciiL(
- aUTF8Tester,
- RTL_CONSTASCII_STRINGPARAM(
- "\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"));
- if (nErrorPos != -1)
- {
- aErrorMsg = "String contains illegal character";
- return sal_False;
- }
-
- if ( bFixTags )
- {
- bHasBeenFixed = sal_False;
- aFixed = rtl::OString();
- }
-
- return sal_True;
-}
-
-/*****************************************************************************/
-sal_Bool GSIBlock::TestUTF8( GSILine* pTestee, sal_Bool bFixTags )
-/*****************************************************************************/
-{
- sal_Int32 nErrorPos = 0;
- rtl::OString aErrorMsg;
- sal_Bool bError = sal_False;
- rtl::OString aFixed;
- sal_Bool bHasBeenFixed = sal_False;
- if ( !IsUTF8( pTestee->GetText(), bFixTags, nErrorPos, aErrorMsg, bHasBeenFixed, aFixed ) )
- {
- rtl::OString aContext(copyUpTo(pTestee->GetText(), nErrorPos, 20));
- PrintError(rtl::OStringBuffer(aErrorMsg).append(RTL_CONSTASCII_STRINGPARAM(" in Text at Position "))
- .append(nErrorPos).getStr(),
- "Text format", aContext, pTestee->GetLineNumber(), pTestee->GetUniqId());
- bError = sal_True;
- if ( bHasBeenFixed )
- {
- pTestee->SetText( aFixed );
- pTestee->SetFixed();
- }
- }
- if ( !IsUTF8( pTestee->GetQuickHelpText(), bFixTags, nErrorPos, aErrorMsg, bHasBeenFixed, aFixed ) )
- {
- rtl::OString aContext(
- copyUpTo(pTestee->GetQuickHelpText(), nErrorPos, 20));
- PrintError(rtl::OStringBuffer(aErrorMsg).append(RTL_CONSTASCII_STRINGPARAM(" in QuickHelpText at Position "))
- .append(nErrorPos).getStr(),
- "Text format", aContext, pTestee->GetLineNumber(), pTestee->GetUniqId());
- bError = sal_True;
- if ( bHasBeenFixed )
- {
- pTestee->SetQuickHelpText( aFixed );
- pTestee->SetFixed();
- }
- }
- if ( !IsUTF8( pTestee->GetTitle(), bFixTags, nErrorPos, aErrorMsg, bHasBeenFixed, aFixed ) )
- {
- rtl::OString aContext( pTestee->GetTitle().copy( nErrorPos, 20 ) );
- PrintError(rtl::OStringBuffer(aErrorMsg).append(RTL_CONSTASCII_STRINGPARAM(" in Title at Position "))
- .append(nErrorPos).getStr(),
- "Text format", aContext, pTestee->GetLineNumber(), pTestee->GetUniqId());
- bError = sal_True;
- if ( bHasBeenFixed )
- {
- pTestee->SetTitle( aFixed );
- pTestee->SetFixed();
- }
- }
- if ( bError )
- pTestee->NotOK();
- return !bError;
-}
-
-
-/*****************************************************************************/
-sal_Bool GSIBlock::HasSuspiciousChars( GSILine* pTestee, GSILine* pSource )
-/*****************************************************************************/
-{
- sal_Int32 nPos = 0;
- if ( !bAllowSuspicious && ( nPos = pTestee->GetText().indexOf("??")) != -1 )
- if ( pSource->GetText().indexOf("??") == -1 )
- {
- rtl::OUString aUTF8Tester(
- rtl::OStringToOUString(
- pTestee->GetText().copy(0, nPos), RTL_TEXTENCODING_UTF8));
- sal_Int32 nErrorPos = aUTF8Tester.getLength();
- rtl::OString aContext( helper::abbreviate( pTestee->GetText(), nPos, 20 ) );
- PrintError(rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Found double questionmark in translation only. Looks like an encoding problem at Position "))
- .append(nErrorPos).getStr(),
- "Text format", aContext, pTestee->GetLineNumber(), pTestee->GetUniqId());
- pTestee->NotOK();
- return sal_True;
- }
-
- return sal_False;
-}
-
-
-/*****************************************************************************/
-sal_Bool GSIBlock::CheckSyntax( std::size_t nLine, sal_Bool bRequireSourceLine, sal_Bool bFixTags )
-/*****************************************************************************/
-{
- static LingTest aTester;
- sal_Bool bHasError = sal_False;
-
- if ( !pSourceLine )
- {
- if ( bRequireSourceLine )
- {
- PrintError( "No source language entry defined!", "File format", "", nLine );
- bHasBlockError = sal_True;
- }
- }
- else
- {
- aTester.CheckReference( pSourceLine );
- if ( pSourceLine->HasMessages() )
- {
- PrintList( pSourceLine->GetMessageList(), "ReferenceString", pSourceLine );
- pSourceLine->NotOK();
- bHasError = sal_True;
- }
- }
- if ( bReference )
- {
- if ( !pReferenceLine )
- {
- GSILine *pSource;
- if ( pSourceLine )
- pSource = pSourceLine;
- else
- pSource = maList.empty() ? NULL : maList[ 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 = sal_True;
- }
- else
- {
- if ( pSourceLine && pSourceLine->data_ != pReferenceLine->data_ )
- {
- sal_Int32 nPos = pSourceLine->data_.indexOf( pReferenceLine->data_ );
- rtl::OStringBuffer aContext( pReferenceLine->data_.copy( nPos - 5, 15) );
- aContext.append( "\" --> \"" ).append( pSourceLine->data_.copy( nPos - 5, 15) );
- PrintError( "Source Language Entry has changed.", "File format", aContext.makeStringAndClear(), pSourceLine->GetLineNumber(), pSourceLine->GetUniqId() );
- pSourceLine->NotOK();
- bHasError = sal_True;
- }
- }
- }
-
- if ( pSourceLine )
- bHasError |= !TestUTF8( pSourceLine, bFixTags );
-
- for ( size_t i = 0, n = maList.size(); i < n; ++i )
- {
- GSILine* pItem = maList[ i ];
- aTester.CheckTestee( pItem, pSourceLine != NULL, bFixTags );
- if ( pItem->HasMessages() || aTester.HasCompareWarnings() )
- {
- if ( pItem->HasMessages() || aTester.GetCompareWarnings().HasErrors() )
- pItem->NotOK();
- bHasError = sal_True;
- PrintList( pItem->GetMessageList(), "Translation", pItem );
- PrintList( &(aTester.GetCompareWarnings()), "Translation Tag Mismatch", pItem );
- }
- bHasError |= !TestUTF8( pItem, bFixTags );
- if ( pSourceLine )
- bHasError |= HasSuspiciousChars( pItem, pSourceLine );
- }
-
- return bHasError || bHasBlockError;
-}
-
-void GSIBlock::WriteError( LazyStream &aErrOut, sal_Bool bRequireSourceLine )
-{
- if ( pSourceLine && pSourceLine->IsOK() && bCheckSourceLang && !bHasBlockError )
- return;
-
- sal_Bool bHasError = sal_False;
- sal_Bool bCopyAll = ( !pSourceLine && bRequireSourceLine ) || ( pSourceLine && !pSourceLine->IsOK() && !bCheckTranslationLang ) || bHasBlockError;
- for ( size_t i = 0, n = maList.size(); i < n; ++i )
- {
- GSILine* pItem = maList[ i ];
- if ( !pItem->IsOK() || bCopyAll )
- {
- bHasError = sal_True;
- aErrOut.LazyOpen();
- aErrOut << pItem->data_.getStr() << '\n';
- }
- }
-
- if ( pSourceLine && ( bHasError || !pSourceLine->IsOK() ) && !( !bHasError && bCheckTranslationLang ) )
- {
- aErrOut.LazyOpen();
- aErrOut << pSourceLine->data_.getStr() << '\n';
- }
-}
-
-void GSIBlock::WriteCorrect( LazyStream &aOkOut, sal_Bool bRequireSourceLine )
-{
- if ( ( !pSourceLine && bRequireSourceLine ) || ( pSourceLine && !pSourceLine->IsOK() && !bCheckTranslationLang ) )
- return;
-
- sal_Bool bHasOK = sal_False;
- for ( size_t i = 0, n = maList.size(); i < n; ++i )
- {
- GSILine* pItem = maList[ i ];
- if ( ( pItem->IsOK() || bCheckSourceLang ) && !bHasBlockError )
- {
- bHasOK = sal_True;
- aOkOut.LazyOpen();
- aOkOut << pItem->data_.getStr() << '\n';
- }
- }
-
- if ( ( pSourceLine && pSourceLine->IsOK() && ( !maList.empty() || !bCheckTranslationLang ) ) || ( bHasOK && bCheckTranslationLang ) )
- {
- aOkOut.LazyOpen();
- aOkOut << pSourceLine->data_.getStr() << '\n';
- }
-}
-
-void GSIBlock::WriteFixed( LazyStream &aFixOut )
-{
- if ( pSourceLine && !pSourceLine->IsFixed() && bCheckSourceLang )
- return;
-
- sal_Bool bHasFixes = sal_False;
- for ( size_t i = 0, n = maList.size(); i < n; ++i )
- {
- GSILine* pItem = maList[ i ];
- if ( pItem->IsFixed() )
- {
- bHasFixes = sal_True;
- aFixOut.LazyOpen();
- aFixOut << pItem->data_.getStr() << '\n';
- }
- }
-
- if ( pSourceLine && ( bHasFixes || pSourceLine->IsFixed() ) )
- {
- aFixOut.LazyOpen();
- aFixOut << pSourceLine->data_.getStr() << '\n';
- }
-}
-
-
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-/*****************************************************************************/
-
-/*****************************************************************************/
-void Help()
-/*****************************************************************************/
-{
- fprintf( stdout, "\n" );
- fprintf( stdout, "gsicheck checks the syntax of tags in SDF-Files\n" );
- fprintf( stdout, " checks for inconsistencies and malicious UTF8 encoding\n" );
- fprintf( stdout, " checks tags in Online Help\n" );
- fprintf( stdout, " relax GID/LID length to %s\n",
- rtl::OString::valueOf(static_cast<sal_Int32>(MAX_GID_LID_LEN)).getStr() );
- 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, "-e disable encoding checks. E.g.: double questionmark \'??\' which may be the\n" );
- fprintf( stdout, " result of false conversions\n" );
- fprintf( stdout, "-l ISO language code 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" );
-}
-
-SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
- sal_Bool bError = sal_False;
- sal_Bool bPrintContext = sal_False;
- sal_Bool bCheckSourceLang = sal_False;
- sal_Bool bCheckTranslationLang = sal_False;
- sal_Bool bWriteError = sal_False;
- sal_Bool bWriteCorrect = sal_False;
- sal_Bool bWriteFixed = sal_False;
- sal_Bool bFixTags = sal_False;
- sal_Bool bAllowSuspicious = sal_False;
- rtl::OString aErrorFilename;
- rtl::OString aCorrectFilename;
- rtl::OString aFixedFilename;
- sal_Bool bFileHasError = sal_False;
- rtl::OString aSourceLang( "en-US" ); // English is default
- rtl::OString aFilename;
- rtl::OString aReferenceFilename;
- sal_Bool bReferenceFile = sal_False;
- for ( int i = 1 ; i < argc ; i++ )
- {
- if ( *argv[ i ] == '-' )
- {
- switch (*(argv[ i ]+1))
- {
- case 'c':bPrintContext = sal_True;
- break;
- case 'w':
- {
- if ( (*(argv[ i ]+2)) == 'e' )
- {
- if ( (*(argv[ i ]+3)) == 'f' )
- if ( (i+1) < argc )
- {
- aErrorFilename = argv[i + 1];
- bWriteError = sal_True;
- i++;
- }
- else
- {
- fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
- bError = sal_True;
- }
- else
- bWriteError = sal_True;
- }
- else if ( (*(argv[ i ]+2)) == 'c' )
- if ( (*(argv[ i ]+3)) == 'f' )
- if ( (i+1) < argc )
- {
- aCorrectFilename = argv[i + 1];
- bWriteCorrect = sal_True;
- i++;
- }
- else
- {
- fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
- bError = sal_True;
- }
- else
- bWriteCorrect = sal_True;
- else if ( (*(argv[ i ]+2)) == 'f' )
- if ( (*(argv[ i ]+3)) == 'f' )
- if ( (i+1) < argc )
- {
- aFixedFilename = argv[i + 1];
- bWriteFixed = sal_True;
- bFixTags = sal_True;
- i++;
- }
- else
- {
- fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
- bError = sal_True;
- }
- else
- {
- bWriteFixed = sal_True;
- bFixTags = sal_True;
- }
- else
- {
- fprintf( stderr, "\nERROR: Unknown Switch %s!\n\n", argv[ i ] );
- bError = sal_True;
- }
- }
- break;
- case 's':bCheckSourceLang = sal_True;
- break;
- case 't':bCheckTranslationLang = sal_True;
- break;
- case 'l':
- {
- if ( (i+1) < argc )
- {
- aSourceLang = argv[ i+1 ];
- if ( aSourceLang.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("none")) )
- aSourceLang = rtl::OString();
- i++;
- }
- else
- {
- fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
- bError = sal_True;
- }
- }
- break;
- case 'r':
- {
- if ( (i+1) < argc )
- {
- aReferenceFilename = argv[ i+1 ];
- bReferenceFile = sal_True;
- i++;
- }
- else
- {
- fprintf( stderr, "\nERROR: Switch %s requires parameter!\n\n", argv[ i ] );
- bError = sal_True;
- }
- }
- break;
- case 'f':
- {
- bFixTags = sal_True;
- }
- break;
- case 'e':
- {
- bAllowSuspicious = sal_True;
- }
- break;
- default:
- fprintf( stderr, "\nERROR: Unknown Switch %s!\n\n", argv[ i ] );
- bError = sal_True;
- }
- }
- else
- {
- if (aFilename.isEmpty())
- aFilename = argv[i];
- else
- {
- fprintf( stderr, "\nERROR: Only one filename may be specified!\n\n");
- bError = sal_True;
- }
- }
- }
-
-
- if (aFilename.isEmpty() || bError)
- {
- Help();
- exit ( 0 );
- }
-
- if ( !aSourceLang.isEmpty() && !LanguageOK( aSourceLang ) )
- {
- fprintf( stderr, "\nERROR: The Language '%s' is invalid!\n\n", aSourceLang.getStr() );
- 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 );
- }
-
-
-
- std::ifstream aGSI(aFilename.getStr());
- if (!aGSI.is_open()) {
- fprintf( stderr, "\nERROR: Could not open GSI-File %s!\n\n", aFilename.getStr() );
- exit ( 3 );
- }
-
- std::ifstream aReferenceGSI;
- if ( bReferenceFile )
- {
- aReferenceGSI.open(aReferenceFilename.getStr());
- if (!aReferenceGSI.is_open()) {
- fprintf( stderr, "\nERROR: Could not open Input-File %s!\n\n", aFilename.getStr() );
- exit ( 3 );
- }
- }
-
- LazyStream aOkOut;
- if ( bWriteCorrect )
- {
- if (aCorrectFilename.isEmpty())
- {
- aCorrectFilename = addSuffix(
- aFilename, rtl::OString(RTL_CONSTASCII_STRINGPARAM("_ok")));
- }
- aOkOut.SetFileName(aCorrectFilename);
- }
-
- LazyStream aErrOut;
- if ( bWriteError )
- {
- if (aErrorFilename.isEmpty())
- {
- aErrorFilename = addSuffix(
- aFilename, rtl::OString(RTL_CONSTASCII_STRINGPARAM("_err")));
- }
- aErrOut.SetFileName(aErrorFilename);
- }
-
- LazyStream aFixOut;
- if ( bWriteFixed )
- {
- if (aFixedFilename.isEmpty())
- {
- aFixedFilename = addSuffix(
- aFilename, rtl::OString(RTL_CONSTASCII_STRINGPARAM("_fix")));
- }
- aFixOut.SetFileName(aFixedFilename);
- }
-
-
- GSILine* pReferenceLine = NULL;
- std::size_t nReferenceLine = 0;
-
- GSILine* pGSILine = NULL;
- rtl::OString aOldId("No Valid ID"); // just set to something which can never be an ID
- GSIBlock *pBlock = NULL;
- std::size_t nLine = 0;
-
- while (!aGSI.eof())
- {
- std::string s;
- std::getline(aGSI, s);
- nLine++;
- pGSILine = new GSILine(rtl::OString(s.data(), s.length()), nLine );
- sal_Bool bDelete = sal_True;
-
-
- if ( !pGSILine->data_.isEmpty() )
- {
- if ( FORMAT_UNKNOWN == pGSILine->GetLineFormat() )
- {
- PrintError( "Format of line is unknown. Ignoring!", "Line format", pGSILine->data_.copy( 0,40 ), bPrintContext, pGSILine->GetLineNumber() );
- pGSILine->NotOK();
- if ( bWriteError )
- {
- bFileHasError = sal_True;
- aErrOut.LazyOpen();
- aErrOut << pGSILine->data_.getStr();
- }
- }
- else if ( pGSILine->GetLineType().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("res-comment")) )
- { // ignore comment lines, but write them to Correct Items File
- if ( bWriteCorrect )
- {
- aOkOut.LazyOpen();
- aOkOut << pGSILine->data_.getStr() << '\n';
- }
- }
- else
- {
- rtl::OString aId = pGSILine->GetUniqId();
- if ( aId != aOldId )
- {
- if ( pBlock )
- {
- bFileHasError |= pBlock->CheckSyntax( nLine, !aSourceLang.isEmpty(), bFixTags );
-
- if ( bWriteError )
- pBlock->WriteError( aErrOut, !aSourceLang.isEmpty() );
- if ( bWriteCorrect )
- pBlock->WriteCorrect( aOkOut, !aSourceLang.isEmpty() );
- if ( bWriteFixed )
- pBlock->WriteFixed( aFixOut );
-
- delete pBlock;
- }
- pBlock = new GSIBlock( bPrintContext, bCheckSourceLang, bCheckTranslationLang, bReferenceFile, bAllowSuspicious );
-
- aOldId = aId;
-
-
- // find corresponding line in reference file
- if ( bReferenceFile )
- {
- sal_Bool bContinueSearching = sal_True;
- while ( ( !aReferenceGSI.eof() || pReferenceLine ) && bContinueSearching )
- {
- if ( !pReferenceLine )
- {
- std::string s2;
- std::getline(aReferenceGSI, s2);
- nReferenceLine++;
- pReferenceLine = new GSILine(
- rtl::OString(s2.data(), s2.length()),
- nReferenceLine);
- }
- if ( pReferenceLine->GetLineFormat() != FORMAT_UNKNOWN )
- {
- if ( pReferenceLine->GetUniqId() == aId && pReferenceLine->GetLanguageId() == aSourceLang )
- {
- pBlock->SetReferenceLine( pReferenceLine );
- pReferenceLine = NULL;
- }
- else if ( pReferenceLine->GetUniqId() > aId )
- {
- bContinueSearching = sal_False;
- }
- else
- {
- if ( pReferenceLine->GetUniqId() < aId && pReferenceLine->GetLanguageId() == 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 = sal_False;
- }
- }
- if ( bDelete )
- delete pGSILine;
-
- }
- if ( pBlock )
- {
- bFileHasError |= pBlock->CheckSyntax( nLine, !aSourceLang.isEmpty(), bFixTags );
-
- if ( bWriteError )
- pBlock->WriteError( aErrOut, !aSourceLang.isEmpty() );
- if ( bWriteCorrect )
- pBlock->WriteCorrect( aOkOut, !aSourceLang.isEmpty() );
- if ( bWriteFixed )
- pBlock->WriteFixed( aFixOut );
-
- delete pBlock;
- }
- aGSI.close();
-
- if ( bWriteError )
- aErrOut.close();
- if ( bWriteCorrect )
- aOkOut.close();
- if ( bWriteFixed )
- aFixOut.close();
-
- if ( bFileHasError )
- return 55;
- else
- return 0;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/helper.hxx b/l10ntools/source/helper.hxx
index cc33b71ff8ac..1d268dd1c0f7 100644
--- a/l10ntools/source/helper.hxx
+++ b/l10ntools/source/helper.hxx
@@ -35,8 +35,11 @@
#include <algorithm>
#include <cassert>
+#include <libxml/parser.h>
+
#include "rtl/string.hxx"
#include "rtl/ustring.hxx"
+#include "rtl/strbuf.hxx"
#include "sal/types.h"
namespace helper {
@@ -100,6 +103,69 @@ inline sal_Int32 indexOfAnyAsciiL(
return -1;
}
+rtl::OString QuotHTML(const rtl::OString &rString)
+{
+ rtl::OStringBuffer sReturn;
+ for (sal_Int32 i = 0; i < rString.getLength(); ++i) {
+ switch (rString[i]) {
+ case '\\':
+ if (i < rString.getLength()) {
+ switch (rString[i + 1]) {
+ case '"':
+ case '<':
+ case '>':
+ case '\\':
+ ++i;
+ break;
+ }
+ }
+ // fall through
+ default:
+ sReturn.append(rString[i]);
+ break;
+
+ case '<':
+ sReturn.append("&lt;");
+ break;
+
+ case '>':
+ sReturn.append("&gt;");
+ break;
+
+ case '"':
+ sReturn.append("&quot;");
+ break;
+
+ case '&':
+ if (rString.matchL(RTL_CONSTASCII_STRINGPARAM("&amp;"), i))
+ sReturn.append('&');
+ else
+ sReturn.append(RTL_CONSTASCII_STRINGPARAM("&amp;"));
+ break;
+ }
+ }
+ return sReturn.makeStringAndClear();
+}
+
+inline bool isWellFormedXML( OString const & text )
+{
+ xmlDocPtr doc;
+ OString content;
+ bool result = true;
+
+ content = "<root>";
+ content += text;
+ content += "</root>";
+ doc = xmlParseMemory(content.getStr(),(int)content.getLength());
+ if (doc == NULL) {
+ result = false;
+ }
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ return result;
+}
+
+
template< typename T > inline T abbreviate(
T const & text, sal_Int32 start, sal_Int32 length)
{
diff --git a/l10ntools/source/helpex.cxx b/l10ntools/source/helpex.cxx
index 470b4f1383bc..7ab581a2a1d6 100644
--- a/l10ntools/source/helpex.cxx
+++ b/l10ntools/source/helpex.cxx
@@ -20,6 +20,9 @@
#include "sal/config.h"
#include <iostream>
+#include <fstream>
+#include <string>
+#include <cstring>
#include <stdio.h>
#include <stdlib.h>
@@ -28,214 +31,94 @@
#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_LANGUAGES 0x000A
-#define STATE_FORCE_LANGUAGES 0x000B
-#define STATE_OUTPUTX 0xfe
-#define STATE_OUTPUTY 0xff
-
-// set of global variables
-rtl::OString sInputFile;
-sal_Bool bEnableExport;
-sal_Bool bMergeMode;
-rtl::OString sPrj;
-rtl::OString sPrjRoot;
-rtl::OString sOutputFile;
-rtl::OString sOutputFileX;
-rtl::OString sOutputFileY;
-rtl::OString sSDFFile;
+#ifndef TESTDRIVER
-/*****************************************************************************/
-sal_Bool ParseCommandLine( int argc, char* argv[])
-/*****************************************************************************/
+void WriteUsage()
{
- bEnableExport = sal_False;
- bMergeMode = sal_False;
- sPrj = "";
- sPrjRoot = "";
- Export::sLanguages = "";
- Export::sForcedLanguages = "";
+ std::cout
+ << "Syntax: Helpex [-p Prj] [-r Root] -[m]i FileIn -o FileOut"
+ << " [-m DataBase] [-l l1,l2,...]\n"
+ << " Prj: Project\n"
+ << " Root: Path to project root (../.. etc.)\n"
+ << " FileIn + i: Source file (*.xhp)\n"
+ << " FileIn + -mi: File including pathes of source files"
+ << " (only for merge)"
+ << " FileOut: Destination file (*.*) or files (in case of -mi)\n"
+ << " DataBase: Mergedata (*.po)\n"
+ << " -l: Restrict the handled languages; l1, l2, ... are elements of"
+ << " (de, en-US, ...)\n";
+}
- sal_uInt16 nState = STATE_NON;
- sal_Bool bInput = sal_False;
+SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
- // parse command line
- for( int i = 1; i < argc; i++ )
+ bool bMultiMerge = false;
+ for (int nIndex = 1; nIndex != argc; ++nIndex)
{
- rtl::OString aArg = rtl::OString(argv[i]).toAsciiUpperCase();
- if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-I")))
- nState = STATE_INPUT; // next tokens specifies source files
- else if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-O")))
- nState = STATE_OUTPUT; // next token specifies the dest file
- else if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-X")))
- nState = STATE_OUTPUTX; // next token specifies the dest file
- else if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-Y" )))
- nState = STATE_OUTPUTY; // next token specifies the dest file
- else if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-P" )))
- nState = STATE_PRJ; // next token specifies the cur. project
- else if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-LF")))
- nState = STATE_FORCE_LANGUAGES;
- else if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-R" )))
- nState = STATE_ROOT; // next token specifies path to project root
- else if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-M" )))
- nState = STATE_SDFFILE; // next token specifies the merge database
- else if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-E" )))
+ if (std::strcmp(argv[nIndex], "-mi") == 0)
{
- nState = STATE_ERRORLOG;
+ argv[nIndex][1] = 'i';
+ argv[nIndex][2] = '\0';
+ bMultiMerge = true;
+ break;
}
- else if (aArg.equalsL(RTL_CONSTASCII_STRINGPARAM("-L" )))
- nState = STATE_LANGUAGES;
- else
- {
- switch ( nState )
- {
- case STATE_NON: {
- return sal_False; // no valid command line
- }
- //break;
- case STATE_INPUT: {
- sInputFile = argv[ i ];
- bInput = sal_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 ];
- }
- break;
- case STATE_ROOT: {
- sPrjRoot = argv[ i ]; // path to project root
- }
- break;
- case STATE_SDFFILE: {
- sSDFFile = argv[ i ];
- bMergeMode = sal_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 = sal_True;
- return sal_True;
}
- // command line is not valid
- return sal_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,...] -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, " -L: Restrict the handled languages. l1,l2,... are elements of (en-US,fr,de...)\n" );
- fprintf( stdout, " -LF: Force the creation of that languages\n" );
-
-}
-
-/*****************************************************************************/
-#ifndef TESTDRIVER
-
-SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
- if ( !ParseCommandLine( argc, argv )) {
- Help();
+ HandledArgs aArgs;
+ if ( !Export::handleArguments( argc, argv, aArgs) )
+ {
+ WriteUsage();
return 1;
}
- //sal_uInt32 startfull = Export::startMessure();
-
- bool hasInputList = sInputFile[0]=='@';
bool hasNoError = true;
- if ( sOutputFile.getLength() ){ // Merge single file ?
- HelpParser aParser( sInputFile );
-
- if ( bMergeMode )
+ if ( aArgs.m_bMergeMode )
+ {
+ if( bMultiMerge )
{
- //sal_uInt64 startreadloc = Export::startMessure();
- MergeDataFile aMergeDataFile(sSDFFile, sInputFile, false);
-
- hasNoError = aParser.Merge( sSDFFile, sOutputFile , Export::sLanguages , aMergeDataFile );
- }
- else
- hasNoError = aParser.CreateSDF( sOutputFile, sPrj, sPrjRoot, sInputFile, new XMLFile( rtl::OUString('0') ), "help" );
- }else if ( sOutputFileX.getLength() && sOutputFileY.getLength() && hasInputList ) { // Merge multiple files ?
- if ( bMergeMode ){
-
- ifstream aFStream( sInputFile.copy( 1 ).getStr() , ios::in );
-
- if( !aFStream ){
- std::cerr << "ERROR: - helpex - Can't open the file " << sInputFile.copy( 1 ).getStr() << "\n";
- std::exit(EXIT_FAILURE);
- }
-
- vector<rtl::OString> filelist;
- rtl::OStringBuffer filename;
- sal_Char aChar;
- while( aFStream.get( aChar ) )
+ std::ifstream aInput( aArgs.m_sInputFile.getStr() );
+ if( !aInput.is_open() )
{
- if( aChar == ' ' || aChar == '\n')
- filelist.push_back(filename.makeStringAndClear());
- else
- filename.append( aChar );
+ std::cerr << "Helpex error: cannot open input file\n";
+ return 1;
}
- if( filename.getLength() > 0 )
- filelist.push_back(filename.makeStringAndClear());
-
- aFStream.close();
- rtl::OString sHelpFile; // dummy
- MergeDataFile aMergeDataFile( sSDFFile, sHelpFile, false );
-
- std::vector<rtl::OString> aLanguages;
- HelpParser::parse_languages( aLanguages , aMergeDataFile );
-
- bool bCreateDir = true;
- for( vector<rtl::OString>::iterator pos = filelist.begin() ; pos != filelist.end() ; ++pos )
+ MergeDataFile aMergeDataFile( aArgs.m_sMergeSrc, OString(), false);
+ std::string sTemp;
+ aInput >> sTemp;
+ while( !aInput.eof() )
{
- sHelpFile = *pos;
-
- HelpParser aParser( sHelpFile );
- hasNoError = aParser.Merge( sSDFFile , sOutputFileX , sOutputFileY , true , aLanguages , aMergeDataFile , bCreateDir );
- bCreateDir = false;
+ const OString sXhpFile( sTemp.data(), sTemp.length() );
+ HelpParser aParser( sXhpFile );
+ const OString sOutput(
+ aArgs.m_sOutputFile +
+ sXhpFile.copy( sXhpFile.lastIndexOf("/") ));
+ if( !aParser.Merge( aArgs.m_sMergeSrc, sOutput,
+ Export::sLanguages, aMergeDataFile ))
+ {
+ hasNoError = false;
+ }
+ aInput >> sTemp;
}
+ aInput.close();
}
- } else
- std::cerr << "helpex ERROR: Wrong input parameters!\n";
+ else
+ {
+ HelpParser aParser( aArgs.m_sInputFile );
+ MergeDataFile aMergeDataFile(
+ aArgs.m_sMergeSrc, aArgs.m_sInputFile, false );
+ hasNoError =
+ aParser.Merge(
+ aArgs.m_sMergeSrc, aArgs.m_sOutputFile,
+ Export::sLanguages , aMergeDataFile );
+ }
+ }
+ else
+ {
+ HelpParser aParser( aArgs.m_sInputFile );
+ hasNoError =
+ aParser.CreateSDF(
+ aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot,
+ aArgs.m_sInputFile, new XMLFile( OUString('0') ), "help" );
+ }
if( hasNoError )
return 0;
diff --git a/l10ntools/source/helpmerge.cxx b/l10ntools/source/helpmerge.cxx
index 05b3800bbc81..68f745397378 100644
--- a/l10ntools/source/helpmerge.cxx
+++ b/l10ntools/source/helpmerge.cxx
@@ -227,51 +227,6 @@ void HelpParser::parse_languages( std::vector<rtl::OString>& aLanguages , MergeD
}
-bool HelpParser::Merge(
- const rtl::OString &rSDFFile, const rtl::OString &rPathX , const rtl::OString &rPathY , bool bISO ,
- const std::vector<rtl::OString>& aLanguages , MergeDataFile& aMergeDataFile , bool bCreateDir )
-{
-
-
- (void) rSDFFile ;
- bool hasNoError = true;
- SimpleXMLParser aParser;
- rtl::OUString sXmlFile(
- rtl::OStringToOUString(sHelpFile, RTL_TEXTENCODING_ASCII_US));
- //TODO: explicit BOM handling?
-
- XMLFile* xmlfile = aParser.Execute( sXmlFile, new XMLFile( rtl::OUString('0') ) );
-
- if( xmlfile == NULL)
- {
- printf("%s\n", rtl::OUStringToOString(aParser.GetError().sMessage, RTL_TEXTENCODING_UTF8).getStr());
- exit(-1);
- }
-
- xmlfile->Extract();
-
- rtl::OString sCur;
- for( unsigned int n = 0; n < aLanguages.size(); n++ ){
- sCur = aLanguages[ n ];
-
- rtl::OString sFilepath;
- if( bISO ) sFilepath = GetOutpath( rPathX , sCur , rPathY );
- else sFilepath = rPathX;
- if( bCreateDir )
- MakeDir(sFilepath);
-
- XMLFile* file = new XMLFile( *xmlfile );
- sFilepath += sHelpFile;
- hasNoError = MergeSingleFile( file , aMergeDataFile , sCur , sFilepath );
- delete file;
-
- if( !hasNoError ) return false; // Stop on error
- }
-
- delete xmlfile;
- return hasNoError;
-}
-
bool HelpParser::MergeSingleFile( XMLFile* file , MergeDataFile& aMergeDataFile , const rtl::OString& sLanguage ,
rtl::OString const & sPath )
{
@@ -341,7 +296,7 @@ void HelpParser::MakeDir(const rtl::OString& rPath)
void HelpParser::ProcessHelp( LangHashMap* aLangHM , const rtl::OString& sCur , ResData *pResData , MergeDataFile& aMergeDataFile ){
XMLElement* pXMLElement = NULL;
- PFormEntrys *pEntrys = NULL;
+ PFormEntrys *pEntrys = NULL;
XMLData *data = NULL;
rtl::OString sLId;
@@ -379,9 +334,16 @@ void HelpParser::ProcessHelp( LangHashMap* aLangHM , const rtl::OString& sCur ,
while ( (nPreSpaces < nLen) && (*(sSourceText.getStr()+nPreSpaces) == ' ') )
nPreSpaces++;
pEntrys->GetText( sNewText, STRING_TYP_TEXT, sCur , true );
- rtl::OUString sNewdata(
- sSourceText.copy(0,nPreSpaces) +
- rtl::OStringToOUString(sNewText, RTL_TEXTENCODING_UTF8));
+ OUString sNewdata;
+ if (helper::isWellFormedXML(helper::QuotHTML(sNewText)))
+ {
+ sNewdata = sSourceText.copy(0,nPreSpaces) +
+ rtl::OStringToOUString(sNewText, RTL_TEXTENCODING_UTF8);
+ }
+ else
+ {
+ sNewdata = sSourceText;
+ }
if (!sNewdata.isEmpty())
{
if( pXMLElement != NULL )
diff --git a/l10ntools/source/lngex.cxx b/l10ntools/source/lngex.cxx
index ab2f0afe0eb5..eb5cccc578fc 100644
--- a/l10ntools/source/lngex.cxx
+++ b/l10ntools/source/lngex.cxx
@@ -25,141 +25,21 @@
#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_ULF 0x000A
-#define STATE_LANGUAGES 0x000B
-
-// set of global variables
-rtl::OString sInputFile;
-sal_Bool bEnableExport;
-sal_Bool bMergeMode;
-sal_Bool bUTF8;
-sal_Bool bULF; // ULF = Unicode Language File
-rtl::OString sPrj;
-rtl::OString sPrjRoot;
-rtl::OString sOutputFile;
-rtl::OString sMergeSrc;
-
-/*****************************************************************************/
-sal_Bool ParseCommandLine( int argc, char* argv[])
-/*****************************************************************************/
-{
- bEnableExport = sal_False;
- bMergeMode = sal_False;
- bUTF8 = sal_True;
- bULF = sal_False;
- sPrj = "";
- sPrjRoot = "";
- Export::sLanguages = "";
-
- sal_uInt16 nState = STATE_NON;
- sal_Bool bInput = sal_False;
-
- // parse command line
- for( int i = 1; i < argc; i++ ) {
- rtl::OString sSwitch = rtl::OString(argv[i]).toAsciiUpperCase();
- if (sSwitch.equalsL(RTL_CONSTASCII_STRINGPARAM("-I")))
- nState = STATE_INPUT; // next tokens specifies source files
- else if (sSwitch.equalsL(RTL_CONSTASCII_STRINGPARAM("-O")))
- nState = STATE_OUTPUT; // next token specifies the dest file
- else if (sSwitch.equalsL(RTL_CONSTASCII_STRINGPARAM("-P")))
- nState = STATE_PRJ; // next token specifies the cur. project
- else if (sSwitch.equalsL(RTL_CONSTASCII_STRINGPARAM("-R")))
- nState = STATE_ROOT; // next token specifies path to project root
- else if (sSwitch.equalsL(RTL_CONSTASCII_STRINGPARAM("-M")))
- nState = STATE_MERGESRC; // next token specifies the merge database
- else if (sSwitch.equalsL(RTL_CONSTASCII_STRINGPARAM("-E")))
- {
- nState = STATE_ERRORLOG;
- }
- else if (sSwitch.equalsL(RTL_CONSTASCII_STRINGPARAM("-L")))
- nState = STATE_LANGUAGES;
- else
- {
- switch ( nState ) {
- case STATE_NON: {
- return sal_False; // no valid command line
- }
- //break;
- case STATE_INPUT: {
- sInputFile = argv[ i ];
- bInput = sal_True; // source file found
- }
- break;
- case STATE_OUTPUT: {
- sOutputFile = argv[ i ]; // the dest. file
- }
- break;
- case STATE_PRJ: {
- sPrj = argv[ i ];
- }
- break;
- case STATE_ROOT: {
- sPrjRoot = argv[ i ]; // path to project root
- }
- break;
- case STATE_MERGESRC: {
- sMergeSrc = argv[ i ];
- bMergeMode = sal_True; // activate merge mode, cause merge database found
- }
- break;
- case STATE_LANGUAGES: {
- Export::sLanguages = argv[ i ];
- }
- break;
- }
- }
- }
-
- if ( bInput ) {
- // command line is valid
- bULF = sal_True;
- bEnableExport = sal_True;
- return sal_True;
- }
-
- // command line is not valid
- return sal_False;
-}
-
-
-/*****************************************************************************/
-void Help()
-/*****************************************************************************/
-{
- 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, " -L: Restrict the handled languages. l1,l2,... are elements of (de,en-US...)\n" );
-}
-
SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
- if ( !ParseCommandLine( argc, argv ))
+
+ HandledArgs aArgs;
+ if ( !Export::handleArguments(argc, argv, aArgs) )
{
- Help();
+ Export::writeUsage("ulfex","ulf");
return 1;
}
- if (!sOutputFile.isEmpty())
- {
- LngParser aParser( sInputFile, bULF );
- if ( bMergeMode )
- aParser.Merge(sMergeSrc, sOutputFile);
- else
- aParser.CreateSDF( sOutputFile, sPrj, sPrjRoot );
- }
+ LngParser aParser( aArgs.m_sInputFile, true );
+ if ( aArgs.m_bMergeMode )
+ aParser.Merge(aArgs.m_sMergeSrc, aArgs.m_sOutputFile);
+ else
+ aParser.CreateSDF(
+ aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot );
return 0;
}
diff --git a/l10ntools/source/lngmerge.cxx b/l10ntools/source/lngmerge.cxx
index 00a58d25a0ad..7294e27339f6 100644
--- a/l10ntools/source/lngmerge.cxx
+++ b/l10ntools/source/lngmerge.cxx
@@ -50,10 +50,10 @@ LngParser::LngParser(const rtl::OString &rLngFile,
if (aStream.is_open())
{
bool bFirstLine = true;
+ std::string s;
+ std::getline(aStream, s);
while (!aStream.eof())
{
- std::string s;
- std::getline(aStream, s);
rtl::OString sLine(s.data(), s.length());
if( bFirstLine )
@@ -64,7 +64,9 @@ LngParser::LngParser(const rtl::OString &rLngFile,
}
pLines->push_back( new rtl::OString(sLine) );
+ std::getline(aStream, s);
}
+ pLines->push_back( new rtl::OString() );
}
else
nError = LNG_COULD_NOT_OPEN;
diff --git a/l10ntools/source/localize.cxx b/l10ntools/source/localize.cxx
index e4eb955a6c2a..f20ed5045f65 100644
--- a/l10ntools/source/localize.cxx
+++ b/l10ntools/source/localize.cxx
@@ -40,16 +40,12 @@
#include "sal/main.h"
#include "sal/types.h"
+#include "po.hxx"
+
using namespace std;
namespace {
-namespace global {
-
-std::ofstream output;
-
-}
-
rtl::OUString getEnvironment(rtl::OUString const & variable) {
rtl::OUString value;
if (osl_getEnvironment(variable.pData, &value.pData) != osl_Process_E_None)
@@ -164,7 +160,8 @@ bool passesPositiveList(rtl::OUString const & url) {
void handleCommand(
rtl::OUString const & project, rtl::OUString const & projectRoot,
- rtl::OUString const & url, rtl::OUString const & executable, bool positive)
+ rtl::OUString const & url, rtl::OUString const & actualDir,
+ PoOfstream & rPoOutPut, rtl::OUString const & executable, bool positive)
{
if (positive ? passesPositiveList(url) : passesNegativeList(url)) {
rtl::OUString inPath;
@@ -196,7 +193,7 @@ void handleCommand(
RTL_CONSTASCII_USTRINGPARAM("INPATH_FOR_BUILD"))));
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/bin/"));
buf.append(executable);
- buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -e -p "));
+ buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -p "));
buf.append(project);
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -r "));
buf.append(projectRoot);
@@ -229,23 +226,89 @@ void handleCommand(
}
std::ifstream in(outPath8.getStr());
if (!in.is_open()) {
- std::cerr << "Error: Cannot open " << outPath.getStr() << "\n";
+ std::cerr << "Error: Cannot open " << outPath8.getStr() << "\n";
throw false; //TODO
}
+
+ std::string s;
+ std::getline(in, s);
+ if (!in.eof() && !rPoOutPut.isOpen())
+ {
+ rtl::OUString outDirUrl;
+ if (osl::FileBase::getFileURLFromSystemPath(actualDir.
+ copy(0,actualDir.lastIndexOf('/')), outDirUrl)
+ != osl::FileBase::E_None)
+ {
+ std::cerr << "Error: Cannot convert pathname to URL\n";
+ throw false; //TODO
+ }
+ osl::Directory::createPath(outDirUrl);
+
+ rtl::OString outFilePath;
+ if (!actualDir.concat(".pot").
+ convertToString(
+ &outFilePath, osl_getThreadTextEncoding(),
+ (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
+ {
+ std::cerr << "Error: Cannot convert pathname from UTF-16\n";
+ throw false; //TODO
+ }
+ rPoOutPut.open(outFilePath.getStr());
+ if (!rPoOutPut.isOpen())
+ {
+ std::cerr
+ << "Error: Cannot open po file "
+ << outFilePath.getStr() << "\n";
+ throw false; //TODO
+ }
+
+ //Add header to actual po file
+ {
+ const sal_Int32 nProjectInd = inPath.indexOf(project);
+ const OString relativPath =
+ OUStringToOString(
+ inPath.copy( nProjectInd,
+ inPath.lastIndexOf('/')- nProjectInd),
+ RTL_TEXTENCODING_UTF8 );
+
+ rPoOutPut.writeHeader(PoHeader(relativPath));
+ }
+ }
while (!in.eof())
{
- std::string s;
+ OString sLine = OString(s.data(),s.length());
+ try
+ {
+ if (!sLine.getToken(PoEntry::TEXT,'\t').isEmpty())
+ rPoOutPut.writeEntry(PoEntry(sLine));
+ if (!sLine.getToken(PoEntry::QUICKHELPTEXT,'\t').isEmpty())
+ rPoOutPut.writeEntry(PoEntry(sLine,PoEntry::TQUICKHELPTEXT));
+ if (!sLine.getToken(PoEntry::TITLE,'\t').isEmpty())
+ rPoOutPut.writeEntry(PoEntry(sLine,PoEntry::TTITLE));
+ }
+ catch(PoEntry::Exception& aException)
+ {
+ if(aException == PoEntry::INVALIDSDFLINE)
+ {
+ std::cerr
+ << executable
+ << "'s output is invalid:\n"
+ << sLine.replaceAll("\t","\\t").getStr()
+ << std::endl;
+ throw false; //TODO
+ }
+ }
std::getline(in, s);
- if (!s.empty())
- global::output << s << '\n';
- }
+ };
in.close();
}
}
void handleFile(
rtl::OUString const & project, rtl::OUString const & projectRoot,
- rtl::OUString const & url)
+ rtl::OUString const & url, rtl::OUString const & actualDir,
+ PoOfstream & rPoOutPut)
{
struct Command {
char const * extension;
@@ -262,13 +325,14 @@ void handleFile(
{ RTL_CONSTASCII_STRINGPARAM(".xml"), "xrmex", true },
{ RTL_CONSTASCII_STRINGPARAM(".xhp"), "helpex", false },
{ RTL_CONSTASCII_STRINGPARAM(".properties"), "propex", false },
- { RTL_CONSTASCII_STRINGPARAM(".ui"), "uiex", false } };
+ { RTL_CONSTASCII_STRINGPARAM(".ui"), "uiex", false },
+ { RTL_CONSTASCII_STRINGPARAM(".tree"), "treex", false } };
for (std::size_t i = 0; i != SAL_N_ELEMENTS(commands); ++i) {
if (url.endsWithAsciiL(
commands[i].extension, commands[i].extensionLength))
{
handleCommand(
- project, projectRoot, url,
+ project, projectRoot, url, actualDir, rPoOutPut,
rtl::OUString::createFromAscii(commands[i].executable),
commands[i].positive);
break;
@@ -379,8 +443,9 @@ bool excludeDirectory(rtl::OUString const & directory) {
/// level <= 0)
void handleDirectory(
rtl::OUString const & url, int level, rtl::OUString const & project,
- rtl::OUString const & projectRoot)
+ rtl::OUString const & projectRoot, rtl::OUString const & actualDir)
{
+ PoOfstream aPoOutPut;
osl::Directory dir(url);
if (dir.open() != osl::FileBase::E_None) {
std::cerr
@@ -410,7 +475,8 @@ void handleDirectory(
case -1: // the clone or src directory
if (stat.getFileType() == osl::FileStatus::Directory) {
handleDirectory(
- stat.getFileURL(), 0, rtl::OUString(), rtl::OUString());
+ stat.getFileURL(), 0, rtl::OUString(),
+ rtl::OUString(), actualDir);
}
break;
case 0: // a root directory
@@ -418,12 +484,14 @@ void handleDirectory(
if (includeProject(stat.getFileName())) {
handleDirectory(
stat.getFileURL(), 1, stat.getFileName(),
- rtl::OUString());
- } else if ( stat.getFileName() == "clone" || stat.getFileName() == "src" )
+ rtl::OUString(), actualDir.concat("/").
+ concat(stat.getFileName()));
+ } else if ( stat.getFileName() == "clone" ||
+ stat.getFileName() == "src" )
{
handleDirectory(
stat.getFileURL(), -1, rtl::OUString(),
- rtl::OUString());
+ rtl::OUString(), actualDir);
}
}
break;
@@ -435,24 +503,29 @@ void handleDirectory(
pr += rtl::OUString('/');
}
pr += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".."));
- handleDirectory(stat.getFileURL(), 2, project, pr);
+ handleDirectory(stat.getFileURL(), 2, project, pr,
+ actualDir.concat("/").
+ concat(stat.getFileName()));
}
} else {
- handleFile(project, projectRoot, stat.getFileURL());
+ handleFile(project, projectRoot,
+ stat.getFileURL(), actualDir, aPoOutPut);
}
break;
}
}
+ if (aPoOutPut.isOpen())
+ aPoOutPut.close();
if (dir.close() != osl::FileBase::E_None) {
std::cerr << "Error: Cannot close directory\n";
throw false; //TODO
}
}
-void handleProjects(char const * root) {
+void handleProjects(char const * sourceRoot, char const * destRoot) {
rtl::OUString root16;
if (!rtl_convertStringToUString(
- &root16.pData, root, rtl_str_getLength(root),
+ &root16.pData, sourceRoot, rtl_str_getLength(sourceRoot),
osl_getThreadTextEncoding(),
(RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
| RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
@@ -468,9 +541,19 @@ void handleProjects(char const * root) {
std::cerr << "Error: Cannot convert pathname to URL\n";
throw false; //TODO
}
- handleDirectory(rootUrl, 0, rtl::OUString(), rtl::OUString());
+ rtl::OUString outPutRoot;
+ if (!rtl_convertStringToUString(
+ &outPutRoot.pData, destRoot, rtl_str_getLength(destRoot),
+ osl_getThreadTextEncoding(),
+ (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
+ {
+ std::cerr << "Error: Cannot convert pathname to UTF-16\n";
+ throw false; //TODO
+ }
+ handleDirectory(rootUrl, 0, rtl::OUString(), rtl::OUString(), outPutRoot);
}
-
}
SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
@@ -483,17 +566,11 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
"Syntax: localize <source-root> <outfile>\n");
std::exit(EXIT_FAILURE);
}
- global::output.open(argv[2], std::ios_base::out | std::ios_base::trunc);
- if (!global::output.is_open()) {
- std::cerr << "Error: Cannot append to " << argv[2] << '\n';
- std::exit(EXIT_FAILURE);
- }
try {
- handleProjects(argv[1]);
+ handleProjects(argv[1],argv[2]);
} catch (bool) { //TODO
return EXIT_FAILURE;
}
- global::output.close();
return EXIT_SUCCESS;
}
diff --git a/l10ntools/source/merge.cxx b/l10ntools/source/merge.cxx
index e4fc598322a3..73bd8dd7d866 100644
--- a/l10ntools/source/merge.cxx
+++ b/l10ntools/source/merge.cxx
@@ -25,6 +25,7 @@
#include <vector>
#include "export.hxx"
+#include "po.hxx"
namespace
{
@@ -35,6 +36,27 @@ namespace
rFilename.lastIndexOf( '\\' ),
rFilename.lastIndexOf( '/' ))+1);
};
+
+ static bool lcl_ReadPoChecked(
+ PoEntry& o_rPoEntry, PoIfstream& rPoFile,
+ const std::string& rFileName)
+ {
+ try
+ {
+ rPoFile.readEntry( o_rPoEntry );
+ }
+ catch( PoIfstream::Exception& aException )
+ {
+ if( aException == PoIfstream::INVALIDENTRY )
+ {
+ printf(
+ "Warning : %s contains invalid entry\n",
+ rFileName.c_str() );
+ return false;
+ }
+ }
+ return true;
+ }
}
//
@@ -128,47 +150,134 @@ sal_Bool MergeData::operator==( ResData *pData )
//
MergeDataFile::MergeDataFile(
- const rtl::OString &rFileName,
- const rtl::OString &rFile,
+ const rtl::OString &rFileName, const rtl::OString &rFile,
bool bCaseSensitive)
{
- std::ifstream aInputStream(rFileName.getStr());
- const ::rtl::OString sHACK(RTL_CONSTASCII_STRINGPARAM("HACK"));
- const ::rtl::OString sFileNormalized(lcl_NormalizeFilename(rFile));
- const bool isFileEmpty = sFileNormalized.isEmpty();
-
- if (!aInputStream.is_open())
+ std::ifstream aInputStream( rFileName.getStr() );
+ if ( !aInputStream.is_open() )
{
- printf("Warning : Can't open %s\n", rFileName.getStr());
+ printf("Warning : Can't open po path container file");
return;
}
- while (!aInputStream.eof())
+ std::string sPoFileName;
+ aInputStream >> sPoFileName;
+ bool bFirstLang = true;
+ while( !aInputStream.eof() )
{
- std::string buf;
- std::getline(aInputStream, buf);
- rtl::OString sLine(buf.data(), buf.length());
- sal_Int32 n = 0;
- // Skip all wrong filenames
- const ::rtl::OString filename = lcl_NormalizeFilename(sLine.getToken(1, '\t', n)); // token 1
- if (isFileEmpty || (!isFileEmpty && filename.equals(sFileNormalized)) )
+ const OString sHack("HACK");
+ const OString sFileName( lcl_NormalizeFilename(rFile) );
+ const bool bReadAll = sFileName.isEmpty();
+ PoIfstream aPoInput;
+ aPoInput.open( OString(sPoFileName.data(), sPoFileName.length()) );
+ if ( !aPoInput.isOpen() )
+ {
+ printf( "Warning : Can't open %s\n", sPoFileName.c_str() );
+ return;
+ }
+ PoHeader aPoHeader;
+ try
+ {
+ aPoInput.readHeader( aPoHeader );
+ }
+ catch( PoIfstream::Exception& aException )
{
- const rtl::OString sTYP = sLine.getToken( 1, '\t', n ); // token 3
- const rtl::OString sGID = sLine.getToken( 0, '\t', n ); // token 4
- const rtl::OString sLID = sLine.getToken( 0, '\t', n ); // token 5
- rtl::OString sPFO = sLine.getToken( 1, '\t', n ); // token 7
- sPFO = sHACK;
- rtl::OString nLANG = sLine.getToken( 1, '\t', n ); // token 9
- nLANG = nLANG.trim();
- const rtl::OString sTEXT = sLine.getToken( 0, '\t', n ); // token 10
- const rtl::OString sQHTEXT = sLine.getToken( 1, '\t', n ); // token 12
- const rtl::OString sTITLE = sLine.getToken( 0, '\t', n ); // token 13
-
- if (!nLANG.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("en-US")))
+ if( aException == PoIfstream::INVALIDHEADER )
+ {
+ printf(
+ "Warning : %s has invalid header\n",
+ sPoFileName.c_str() );
+ return;
+ }
+ }
+ OString sLang;
+ try
+ {
+ sLang = aPoHeader.getLanguage();
+ }
+ catch( PoHeader::Exception& aException )
+ {
+ if( aException == PoHeader::NOLANG )
+ {
+ printf(
+ "Warning : %s' header not has language specification\n",
+ sPoFileName.c_str() );
+ return;
+ }
+ }
+ aLanguageSet.insert( sLang );
+ PoEntry aNextPo;
+ do
+ {
+ if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
+ {
+ return;
+ }
+ } while( !aPoInput.eof() && aNextPo.getSourceFile() != sFileName && !bReadAll );
+ while( !aPoInput.eof() && (aNextPo.getSourceFile() == sFileName || bReadAll ))
+ {
+ PoEntry aActPo( aNextPo );
+
+ bool bInSameComp = false;
+ OString sText;
+ OString sQHText;
+ OString sTitle;
+ OString sExText;
+ OString sExQHText;
+ OString sExTitle;
+ OString sQTZText;
+ OString sQTZQHText;
+ OString sQTZTitle;
+ do
+ {
+ if( bInSameComp )
+ aActPo = aNextPo;
+ OString sTemp = aActPo.getMsgStr();
+ if( aActPo.isFuzzy() || sTemp.isEmpty() )
+ sTemp = aActPo.getMsgId();
+ switch( aActPo.getType() )
+ {
+ case PoEntry::TTEXT:
+ sText = sTemp;
+ sExText = aActPo.getMsgId();
+ sQTZText = aActPo.getKeyId();
+ break;
+ case PoEntry::TQUICKHELPTEXT:
+ sQHText = sTemp;
+ sExQHText = aActPo.getMsgId();
+ sQTZQHText = aActPo.getKeyId();
+ break;
+ case PoEntry::TTITLE:
+ sTitle = sTemp;
+ sExTitle = aActPo.getMsgId();
+ sQTZTitle = aActPo.getKeyId();
+ break;
+ }
+ if( !lcl_ReadPoChecked(aNextPo, aPoInput, sPoFileName) )
+ {
+ return;
+ }
+ } while( !aPoInput.eof() &&
+ ( bInSameComp = PoEntry::IsInSameComp(aActPo, aNextPo) ) );
+
+ InsertEntry(
+ aActPo.getResourceType(), aActPo.getGroupId(),
+ aActPo.getLocalId(), sHack, sLang, sText,
+ sQHText, sTitle, aActPo.getSourceFile(), bCaseSensitive );
+
+ if( bFirstLang )
{
- aLanguageSet.insert(nLANG);
- InsertEntry( sTYP, sGID, sLID, sPFO, nLANG, sTEXT, sQHTEXT, sTITLE, filename, bCaseSensitive );
+ aLanguageSet.insert("qtz");
+ InsertEntry(
+ aActPo.getResourceType(), aActPo.getGroupId(),
+ aActPo.getLocalId(), sHack, "qtz",
+ sQTZText + "||" + sExText, sQTZQHText + "||" + sExQHText,
+ sQTZTitle + "||" + sExTitle, aActPo.getSourceFile(),
+ bCaseSensitive );
}
}
+ aPoInput.close();
+ aInputStream >> sPoFileName;
+ bFirstLang = false;
}
aInputStream.close();
}
diff --git a/l10ntools/source/po.cxx b/l10ntools/source/po.cxx
new file mode 100644
index 000000000000..1be60ecaf312
--- /dev/null
+++ b/l10ntools/source/po.cxx
@@ -0,0 +1,869 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <rtl/ustring.hxx>
+
+#include <cstring>
+#include <ctime>
+#include <cassert>
+
+#include <vector>
+#include <string>
+
+#include <boost/crc.hpp>
+#include <unicode/regex.h>
+
+#include "po.hxx"
+
+#define POESCAPED OString("\\n\\t\\r\\\\\\\"")
+#define POUNESCAPED OString("\n\t\r\\\"")
+
+using namespace U_ICU_NAMESPACE;
+
+//Class GenPoEntry
+
+class GenPoEntry
+{
+private:
+
+ OString m_sExtractCom;
+ OString m_sReference;
+ OString m_sMsgCtxt;
+ OString m_sMsgId;
+ OString m_sMsgStr;
+ bool m_bFuzzy;
+ bool m_bNull;
+
+public:
+
+ GenPoEntry();
+ virtual ~GenPoEntry();
+ //Default copy constructor and copy operator work well
+
+ virtual OString getExtractCom() const { return m_sExtractCom; }
+ virtual OString getReference() const { return m_sReference; }
+ virtual OString getMsgCtxt() const { return m_sMsgCtxt; }
+ virtual OString getMsgId() const { return m_sMsgId; }
+ virtual OString getMsgStr() const { return m_sMsgStr; }
+ virtual bool isFuzzy() const { return m_bFuzzy; }
+ virtual bool isNull() const { return m_bNull; }
+
+ virtual void setExtractCom(const OString& rExtractCom);
+ virtual void setReference(const OString& rReference);
+ virtual void setMsgCtxt(const OString& rMsgCtxt);
+ virtual void setMsgId(const OString& rMsgId);
+ virtual void setMsgStr(const OString& rMsgStr);
+ virtual void setFuzzy(const bool bFuzzy);
+
+ virtual void writeToFile(std::ofstream& rOFStream) const;
+ virtual void readFromFile(std::ifstream& rIFStream);
+};
+
+namespace
+{
+ //Escape text
+ static OString lcl_EscapeText(const OString& rText,
+ const OString& rUnEscaped= POUNESCAPED,
+ const OString& rEscaped = POESCAPED)
+ {
+ assert( rEscaped.getLength() == 2*rUnEscaped.getLength() );
+ OString sResult = rText;
+ int nCount = 0;
+ for(sal_Int32 nIndex=0; nIndex<rText.getLength(); ++nIndex)
+ {
+ sal_Int32 nActChar = rUnEscaped.indexOf(rText[nIndex]);
+ if(nActChar!=-1)
+ sResult = sResult.replaceAt((nIndex)+(nCount++),1,
+ rEscaped.copy(2*nActChar,2));
+ }
+ return sResult;
+ }
+
+ //Unescape text
+ static OString lcl_UnEscapeText(const OString& rText,
+ const OString& rEscaped = POESCAPED,
+ const OString& rUnEscaped = POUNESCAPED)
+ {
+ assert( rEscaped.getLength() == 2*rUnEscaped.getLength() );
+ OString sResult = rText;
+ int nCount = 0;
+ for(sal_Int32 nIndex=0; nIndex<rText.getLength()-1; ++nIndex)
+ {
+ sal_Int32 nActChar = rEscaped.indexOf(rText.copy(nIndex,2));
+ if(nActChar % 2 == 0)
+ sResult = sResult.replaceAt((nIndex++)-(nCount++),2,
+ rUnEscaped.copy(nActChar/2,1));
+ }
+ return sResult;
+ }
+
+ //Convert a normal string to msg/po output string
+ static OString lcl_GenMsgString(const OString& rString)
+ {
+ if ( rString.isEmpty() )
+ return "\"\"";
+
+ OString sResult = "\"" + lcl_EscapeText(rString) + "\"";
+ sal_Int32 nIndex = 0;
+ while((nIndex=sResult.indexOf("\\n",nIndex))!=-1)
+ {
+ if( sResult.copy(nIndex-1,3)!="\\\\n" &&
+ nIndex!=sResult.getLength()-3)
+ {
+ sResult = sResult.replaceAt(nIndex,2,"\\n\"\n\"");
+ }
+ ++nIndex;
+ }
+
+ if ( sResult.indexOf('\n') != -1 )
+ return "\"\"\n" + sResult;
+
+ return sResult;
+ }
+
+ //Convert msg string to normal form
+ static OString lcl_GenNormString(const OString& rString)
+ {
+ return lcl_UnEscapeText(rString.copy(1,rString.getLength()-2));
+ }
+}
+
+//Default constructor
+GenPoEntry::GenPoEntry()
+ : m_sExtractCom( OString() )
+ , m_sReference( OString() )
+ , m_sMsgCtxt( OString() )
+ , m_sMsgId( OString() )
+ , m_sMsgStr( OString() )
+ , m_bFuzzy( false )
+ , m_bNull( false )
+{
+}
+
+//Destructor
+GenPoEntry::~GenPoEntry()
+{
+}
+
+//Set class members
+void GenPoEntry::setExtractCom(const OString& rExtractCom)
+{
+ m_sExtractCom = rExtractCom;
+}
+
+void GenPoEntry::setReference(const OString& rReference)
+{
+ m_sReference = rReference;
+}
+
+void GenPoEntry::setMsgCtxt(const OString& rMsgCtxt)
+{
+ m_sMsgCtxt = rMsgCtxt;
+}
+
+void GenPoEntry::setMsgId(const OString& rMsgId)
+{
+ m_sMsgId = rMsgId;
+}
+
+void GenPoEntry::setMsgStr(const OString& rMsgStr)
+{
+ m_sMsgStr = rMsgStr;
+}
+
+void GenPoEntry::setFuzzy(const bool bFuzzy)
+{
+ m_bFuzzy = bFuzzy;
+}
+
+//Write to file
+void GenPoEntry::writeToFile(std::ofstream& rOFStream) const
+{
+ if ( rOFStream.tellp() != 0 )
+ rOFStream << std::endl;
+ if ( !m_sExtractCom.isEmpty() )
+ rOFStream
+ << "#. "
+ << m_sExtractCom.replaceAll("\n","\n#. ").getStr() << std::endl;
+ if ( !m_sReference.isEmpty() )
+ rOFStream << "#: " << m_sReference.getStr() << std::endl;
+ if ( m_bFuzzy )
+ rOFStream << "#, fuzzy" << std::endl;
+ if ( !m_sMsgCtxt.isEmpty() )
+ rOFStream << "msgctxt "
+ << lcl_GenMsgString(m_sReference+"\n"+m_sMsgCtxt).getStr()
+ << std::endl;
+ rOFStream << "msgid "
+ << lcl_GenMsgString(m_sMsgId).getStr() << std::endl;
+ rOFStream << "msgstr "
+ << lcl_GenMsgString(m_sMsgStr).getStr() << std::endl;
+}
+
+//Read from file
+void GenPoEntry::readFromFile(std::ifstream& rIFStream)
+{
+ *this = GenPoEntry();
+ if( rIFStream.eof() )
+ {
+ m_bNull = true;
+ return;
+ }
+ OString* pLastMsg = 0;
+ std::string sTemp;
+ getline(rIFStream,sTemp);
+ while(!rIFStream.eof())
+ {
+ OString sLine = OString(sTemp.data(),sTemp.length());
+ if (sLine.startsWith("#. "))
+ {
+ if( !m_sExtractCom.isEmpty() )
+ {
+ m_sExtractCom += "\n";
+ }
+ m_sExtractCom += sLine.copy(3);
+ }
+ else if (sLine.startsWith("#: "))
+ {
+ m_sReference = sLine.copy(3);
+ }
+ else if (sLine.startsWith("#, fuzzy"))
+ {
+ m_bFuzzy = true;
+ }
+ else if (sLine.startsWith("msgctxt "))
+ {
+ m_sMsgCtxt = lcl_GenNormString(sLine.copy(8));
+ pLastMsg = &m_sMsgCtxt;
+ }
+ else if (sLine.startsWith("msgid "))
+ {
+ m_sMsgId = lcl_GenNormString(sLine.copy(6));
+ pLastMsg = &m_sMsgId;
+ }
+ else if (sLine.startsWith("msgstr "))
+ {
+ m_sMsgStr = lcl_GenNormString(sLine.copy(7));
+ pLastMsg = &m_sMsgStr;
+ }
+ else if (sLine.startsWith("\"") && pLastMsg)
+ {
+ if (pLastMsg != &m_sMsgCtxt || sLine != "\"" + m_sReference + "\\n\"")
+ {
+ *pLastMsg += lcl_GenNormString(sLine);
+ }
+ }
+ else
+ break;
+ getline(rIFStream,sTemp);
+ }
+ }
+
+//Class PoEntry
+
+namespace
+{
+ //Generate KeyId
+ static OString lcl_GenKeyId(const OString& rGenerator)
+ {
+ boost::crc_32_type aCRC32;
+ aCRC32.process_bytes(rGenerator.getStr(), rGenerator.getLength());
+ sal_uInt32 nCRC = aCRC32.checksum();
+ //Use all readable ASCII charachter exclude xml special tags: ",',&,<,>
+ const OString sSymbols = "!#$%()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
+ char sKeyId[5];
+ for( short nKeyInd = 0; nKeyInd < 4; ++nKeyInd )
+ {
+ sKeyId[nKeyInd] = sSymbols[(nCRC & 255) % 89];
+ nCRC >>= 8;
+ }
+ sKeyId[4] = '\0';
+ return OString(sKeyId);
+ }
+
+ //Split string at the delimiter char
+ static void lcl_SplitAt(const OString& rSource, const sal_Char nDelimiter,
+ std::vector<OString>& o_vParts)
+ {
+ o_vParts.resize( 0 );
+ sal_Int32 nActIndex = 0;
+ sal_Int32 nLastSplit = 0;
+ while( nActIndex < rSource.getLength() )
+ {
+ if ( rSource[nActIndex] == nDelimiter )
+ {
+ o_vParts.push_back(
+ rSource.copy(nLastSplit,nActIndex-nLastSplit));
+ nLastSplit = nActIndex+1;
+ }
+ ++nActIndex;
+ }
+ o_vParts.push_back(rSource.copy(nLastSplit));
+ }
+
+ //Unescape sdf string
+ static OString lcl_UnEscapeSDFText(
+ const OString& rText,const bool bHelpText = false )
+ {
+ if ( bHelpText )
+ return lcl_UnEscapeText(rText,"\\<\\>\\\"\\\\","<>\"\\");
+ else
+ return lcl_UnEscapeText(rText,"\\n\\t\\r","\n\t\r");
+ }
+
+ //Find all special tag in a string using a regular expression
+ static void lcl_FindAllTag(
+ const OString& rText,std::vector<OString>& o_vFoundTags )
+ {
+
+ UErrorCode nIcuErr = U_ZERO_ERROR;
+ sal_uInt32 nSearchFlags = UREGEX_DOTALL | UREGEX_CASE_INSENSITIVE;
+ OUString sLocaleText( OStringToOUString(rText,RTL_TEXTENCODING_UTF8) );
+ OUString sPattern( "<[/]??[a-z_-]+?(?:| +[a-z]+?=\".*?\") *[/]??>" );
+ UnicodeString sSearchPat(
+ reinterpret_cast<const UChar*>(
+ sPattern.getStr()), sPattern.getLength() );
+ UnicodeString sSource(
+ reinterpret_cast<const UChar*>(
+ sLocaleText.getStr()), sLocaleText.getLength() );
+
+ RegexMatcher aRegexMatcher( sSearchPat, nSearchFlags, nIcuErr );
+ aRegexMatcher.reset( sSource );
+ int64_t nStartPos = 0;
+ while( aRegexMatcher.find(nStartPos, nIcuErr) &&
+ nIcuErr == U_ZERO_ERROR )
+ {
+ UnicodeString sMatch =
+ aRegexMatcher.group(nIcuErr);
+ o_vFoundTags.push_back(
+ OUStringToOString(
+ OUString(
+ reinterpret_cast<const sal_Unicode*>(
+ sMatch.getBuffer()),sMatch.length()),
+ RTL_TEXTENCODING_UTF8));
+ nStartPos = aRegexMatcher.start(nIcuErr)+1;
+ }
+ }
+
+ //Escape special tags
+ static OString lcl_EscapeTags( const OString& rText )
+ {
+ typedef std::vector<OString> StrVec_t;
+ const OString vInitializer[] = {
+ "ahelp", "link", "item", "emph", "defaultinline",
+ "switchinline", "caseinline", "variable",
+ "bookmark_value", "image", "embedvar", "alt" };
+ const StrVec_t vTagsForEscape( vInitializer,
+ vInitializer + sizeof(vInitializer) / sizeof(vInitializer[0]) );
+ StrVec_t vFoundTags;
+ lcl_FindAllTag(rText,vFoundTags);
+ OString sResult = rText;
+ for(StrVec_t::const_iterator pFound = vFoundTags.begin();
+ pFound != vFoundTags.end(); ++pFound)
+ {
+ bool bEscapeThis = false;
+ for(StrVec_t::const_iterator pEscape = vTagsForEscape.begin();
+ pEscape != vTagsForEscape.end(); ++pEscape)
+ {
+ if (pFound->startsWith("<" + *pEscape) ||
+ *pFound == "</" + *pEscape + ">")
+ {
+ bEscapeThis = true;
+ break;
+ }
+ }
+ if( bEscapeThis || *pFound=="<br/>" ||
+ *pFound =="<help-id-missing/>")
+ {
+ OString sToReplace = "\\<" +
+ pFound->copy(1,pFound->getLength()-2).
+ replaceAll("\"","\\\"") + "\\>";
+ sResult = sResult.replaceAll(*pFound, sToReplace);
+ }
+ }
+ return sResult;
+ }
+
+ //Escape to get sdf/merge string
+ static OString lcl_EscapeSDFText(
+ const OString& rText,const bool bHelpText = false )
+ {
+ if ( bHelpText )
+ return lcl_EscapeTags(rText.replaceAll("\\","\\\\"));
+ else
+ return lcl_EscapeText(rText,"\n\t\r","\\n\\t\\r");
+ }
+}
+
+//Default constructor
+PoEntry::PoEntry()
+ : m_pGenPo( 0 )
+ , m_bIsInitialized( false )
+{
+}
+
+//Construct PoEntry from sdfline
+PoEntry::PoEntry(const OString& rSDFLine, const TYPE eType)
+ : m_pGenPo( 0 )
+ , m_bIsInitialized( false )
+{
+ std::vector<OString> vParts;
+ lcl_SplitAt(rSDFLine,'\t',vParts);
+ if( vParts.size()!=15 ||
+ vParts[SOURCEFILE].isEmpty() ||
+ vParts[GROUPID].isEmpty() ||
+ vParts[RESOURCETYPE].isEmpty() ||
+ vParts[eType].isEmpty() ||
+ vParts[HELPTEXT].getLength() == 4 )
+ {
+ throw INVALIDSDFLINE;
+ }
+
+ m_pGenPo = new GenPoEntry();
+ m_pGenPo->setReference(vParts[SOURCEFILE].
+ copy(vParts[SOURCEFILE].lastIndexOf("\\")+1));
+
+ OString sMsgCtxt =
+ vParts[GROUPID] + "\n" +
+ (vParts[LOCALID].isEmpty() ? "" : vParts[LOCALID] + "\n") +
+ vParts[RESOURCETYPE];
+ switch(eType){
+ case TTEXT:
+ sMsgCtxt += ".text"; break;
+ case TQUICKHELPTEXT:
+ sMsgCtxt += ".quickhelptext"; break;
+ case TTITLE:
+ sMsgCtxt += ".title"; break;
+ /*Default case is unneeded because the type of eType has
+ only three element*/
+ }
+ m_pGenPo->setExtractCom(
+ ( !vParts[HELPTEXT].isEmpty() ? vParts[HELPTEXT] + "\n" : "" ) +
+ lcl_GenKeyId(
+ vParts[SOURCEFILE] + sMsgCtxt + vParts[eType] ) );
+ m_pGenPo->setMsgCtxt(sMsgCtxt);
+ m_pGenPo->setMsgId(
+ lcl_UnEscapeSDFText(
+ vParts[eType],vParts[SOURCEFILE].endsWith(".xhp")));
+ m_bIsInitialized = true;
+}
+
+//Destructor
+PoEntry::~PoEntry()
+{
+ delete m_pGenPo;
+}
+
+//Copy constructor
+PoEntry::PoEntry( const PoEntry& rPo )
+ : m_pGenPo( rPo.m_pGenPo ? new GenPoEntry( *(rPo.m_pGenPo) ) : 0 )
+ , m_bIsInitialized( rPo.m_bIsInitialized )
+{
+}
+
+//Copy operator
+PoEntry& PoEntry::operator=(const PoEntry& rPo)
+{
+ if( this == &rPo )
+ {
+ return *this;
+ }
+ if( rPo.m_pGenPo )
+ {
+ if( m_pGenPo )
+ {
+ *m_pGenPo = *(rPo.m_pGenPo);
+ }
+ else
+ {
+ m_pGenPo = new GenPoEntry( *(rPo.m_pGenPo) );
+ }
+ }
+ else
+ {
+ delete m_pGenPo;
+ m_pGenPo = 0;
+ }
+ m_bIsInitialized = rPo.m_bIsInitialized;
+ return *this;
+}
+
+//Get name of file from which entry is extracted
+OString PoEntry::getSourceFile() const
+{
+ assert( m_bIsInitialized );
+ return m_pGenPo->getReference();
+}
+
+//Get groupid
+OString PoEntry::getGroupId() const
+{
+ assert( m_bIsInitialized );
+ return m_pGenPo->getMsgCtxt().getToken(0,'\n');
+}
+
+//Get localid
+OString PoEntry::getLocalId() const
+{
+ assert( m_bIsInitialized );
+ const OString sMsgCtxt = m_pGenPo->getMsgCtxt();
+ if (sMsgCtxt.indexOf('\n')==sMsgCtxt.lastIndexOf('\n'))
+ return OString();
+ else
+ return sMsgCtxt.getToken(1,'\n');
+}
+
+//Get the type of component from which entry is extracted
+OString PoEntry::getResourceType() const
+{
+ assert( m_bIsInitialized );
+ const OString sMsgCtxt = m_pGenPo->getMsgCtxt();
+ if (sMsgCtxt.indexOf('\n')==sMsgCtxt.lastIndexOf('\n'))
+ return sMsgCtxt.getToken(1,'\n').getToken(0,'.');
+ else
+ return sMsgCtxt.getToken(2,'\n').getToken(0,'.');
+}
+
+//Get the type of entry
+PoEntry::TYPE PoEntry::getType() const
+{
+ assert( m_bIsInitialized );
+ const OString sMsgCtxt = m_pGenPo->getMsgCtxt();
+ const OString sType = sMsgCtxt.copy( sMsgCtxt.lastIndexOf('.') + 1 );
+ assert(
+ (sType == "text" || sType == "quickhelptext" || sType == "title") );
+ if ( sType == "text" )
+ return TTEXT;
+ else if ( sType == "quickhelptext" )
+ return TQUICKHELPTEXT;
+ else
+ return TTITLE;
+}
+
+//Check wheather entry is fuzzy
+bool PoEntry::isFuzzy() const
+{
+ assert( m_bIsInitialized );
+ return m_pGenPo->isFuzzy();
+}
+
+//Get keyid
+OString PoEntry::getKeyId() const
+{
+ assert( m_bIsInitialized );
+ const OString sExtractCom = m_pGenPo->getExtractCom();
+ if( sExtractCom.indexOf("\n") == -1 )
+ {
+ return sExtractCom;
+ }
+ else
+ {
+ return sExtractCom.getToken(1,'\n');
+ }
+}
+
+
+//Get translation string in sdf/merge format
+OString PoEntry::getMsgId() const
+{
+ assert( m_bIsInitialized );
+ return
+ lcl_EscapeSDFText(
+ m_pGenPo->getMsgId(), getSourceFile().endsWith(".xhp") );
+}
+
+//Get translated string in sdf/merge format
+OString PoEntry::getMsgStr() const
+{
+ assert( m_bIsInitialized );
+ return
+ lcl_EscapeSDFText(
+ m_pGenPo->getMsgStr(), getSourceFile().endsWith(".xhp") );
+
+}
+
+//Set translated string when input is in sdf format
+void PoEntry::setMsgStr(const OString& rMsgStr)
+{
+ assert( m_bIsInitialized );
+ m_pGenPo->setMsgStr(
+ lcl_UnEscapeSDFText(
+ rMsgStr,getSourceFile().endsWith(".xhp")));
+}
+
+//Set fuzzy flag
+void PoEntry::setFuzzy(const bool bFuzzy)
+{
+ assert( m_bIsInitialized );
+ m_pGenPo->setFuzzy(bFuzzy);
+}
+
+//Check whether po-s belong to the same localization component
+bool PoEntry::IsInSameComp(const PoEntry& rPo1,const PoEntry& rPo2)
+{
+ assert( rPo1.m_bIsInitialized && rPo2.m_bIsInitialized );
+ return ( rPo1.getSourceFile() == rPo2.getSourceFile() &&
+ rPo1.getGroupId() == rPo2.getGroupId() &&
+ rPo1.getLocalId() == rPo2.getLocalId() &&
+ rPo1.getResourceType() == rPo2.getResourceType() );
+}
+
+//Class PoHeader
+
+namespace
+{
+ //Get actual time in "YEAR-MO-DA HO:MI+ZONE" form
+ static OString lcl_GetTime()
+ {
+ time_t aNow = time(NULL);
+ struct tm* pNow = localtime(&aNow);
+ char pBuff[50];
+ strftime( pBuff, sizeof pBuff, "%Y-%m-%d %H:%M%z", pNow );
+ return pBuff;
+ }
+
+ static OString lcl_ReplaceAttribute(
+ const OString& rSource, const OString& rOld, const OString& rNew )
+ {
+ const sal_Int32 nFirstIndex =
+ rSource.indexOf( rOld ) + rOld.getLength()+2;
+ const sal_Int32 nCount =
+ rSource.indexOf( "\n", nFirstIndex ) - nFirstIndex;
+ return rSource.replaceFirst( rSource.copy(nFirstIndex, nCount), rNew );
+ }
+}
+
+//Default Constructor
+PoHeader::PoHeader()
+ : m_pGenPo( 0 )
+ , m_bIsInitialized( false )
+{
+}
+
+//Template Constructor
+PoHeader::PoHeader( const OString& rExtSrc )
+ : m_pGenPo( new GenPoEntry() )
+ , m_bIsInitialized( false )
+{
+ m_pGenPo->setExtractCom("extracted from " + rExtSrc);
+ m_pGenPo->setMsgStr(
+ OString("Project-Id-Version: PACKAGE VERSION\n"
+ "Report-Msgid-Bugs-To: https://bugs.freedesktop.org/enter_bug.cgi?"
+ "product=LibreOffice&bug_status=UNCONFIRMED&component=UI\n"
+ "POT-Creation-Date: ") + lcl_GetTime() +
+ OString("\nPO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+ "Language-Team: LANGUAGE <LL@li.org>\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/plain; charset=UTF-8\n"
+ "Content-Transfer-Encoding: 8bit\n"
+ "X-Generator: LibreOffice\n"
+ "X-Accelerator-Marker: ~\n"));
+ m_bIsInitialized = true;
+}
+
+
+//Constructor for old headers to renew po files
+PoHeader::PoHeader( std::ifstream& rOldPo )
+ : m_pGenPo( new GenPoEntry() )
+ , m_bIsInitialized( false )
+{
+ assert( rOldPo.is_open() );
+ m_pGenPo->readFromFile( rOldPo );
+
+ const OString sExtractCom = m_pGenPo->getExtractCom();
+ m_pGenPo->setExtractCom(
+ sExtractCom.copy( 0, sExtractCom.getLength() - 3 ) );
+
+ OString sMsgStr = m_pGenPo->getMsgStr();
+ sMsgStr =
+ lcl_ReplaceAttribute( sMsgStr, "Report-Msgid-Bugs-To",
+ "https://bugs.freedesktop.org/enter_bug.cgi?product="
+ "LibreOffice&bug_status=UNCONFIRMED&component=UI" );
+ sMsgStr =
+ lcl_ReplaceAttribute( sMsgStr, "X-Generator", "LibreOffice" );
+ sMsgStr =
+ lcl_ReplaceAttribute( sMsgStr, "X-Accelerator-Marker", "~" );
+ m_pGenPo->setMsgStr( sMsgStr );
+ m_bIsInitialized = true;
+}
+
+PoHeader::~PoHeader()
+{
+ delete m_pGenPo;
+}
+
+//Get the language of header
+OString PoHeader::getLanguage() const
+{
+ assert( m_bIsInitialized );
+ const OString sLang = "Language: ";
+ const OString sMsgStr = m_pGenPo->getMsgStr();
+ const sal_Int32 nFirstIndex = sMsgStr.indexOf(sLang)+sLang.getLength();
+ const sal_Int32 nCount = sMsgStr.indexOf('\n',nFirstIndex)-nFirstIndex;
+ if( nFirstIndex == sLang.getLength()-1 || nCount == -nFirstIndex-1 )
+ {
+ throw NOLANG;
+ }
+ return sMsgStr.copy( nFirstIndex, nCount );
+}
+
+//Class PoOfstream
+
+PoOfstream::PoOfstream()
+ : m_aOutPut()
+ , m_bIsAfterHeader( false )
+{
+}
+
+PoOfstream::~PoOfstream()
+{
+ if( isOpen() )
+ {
+ close();
+ }
+}
+
+void PoOfstream::open(const OString& rFileName)
+{
+ assert( !isOpen() );
+ m_aOutPut.open( rFileName.getStr(),
+ std::ios_base::out | std::ios_base::trunc );
+ m_bIsAfterHeader = false;
+}
+
+void PoOfstream::close()
+{
+ assert( isOpen() );
+ m_aOutPut.close();
+}
+
+void PoOfstream::writeHeader(const PoHeader& rPoHeader)
+{
+ assert( isOpen() && !m_bIsAfterHeader && rPoHeader.m_bIsInitialized );
+ rPoHeader.m_pGenPo->writeToFile( m_aOutPut );
+ m_bIsAfterHeader = true;
+}
+
+void PoOfstream::writeEntry( const PoEntry& rPoEntry )
+{
+ assert( isOpen() && m_bIsAfterHeader && rPoEntry.m_bIsInitialized );
+ rPoEntry.m_pGenPo->writeToFile( m_aOutPut );
+}
+
+//Class PoIfstream
+
+PoIfstream::PoIfstream()
+ : m_aInPut()
+ , m_bIsAfterHeader( false )
+ , m_bEof( false )
+{
+}
+
+PoIfstream::~PoIfstream()
+{
+ if( isOpen() )
+ {
+ close();
+ }
+}
+
+void PoIfstream::open( const OString& rFileName )
+{
+ assert( !isOpen() );
+ m_aInPut.open( rFileName.getStr(), std::ios_base::in );
+ m_bIsAfterHeader = false;
+ m_bEof = false;
+}
+
+void PoIfstream::close()
+{
+ assert( isOpen() );
+ m_aInPut.close();
+}
+
+void PoIfstream::readHeader( PoHeader& rPoHeader )
+{
+ assert( isOpen() && !eof() && !m_bIsAfterHeader );
+ GenPoEntry aGenPo;
+ aGenPo.readFromFile( m_aInPut );
+ if( !aGenPo.getExtractCom().isEmpty() &&
+ aGenPo.getMsgId().isEmpty() &&
+ !aGenPo.getMsgStr().isEmpty() )
+ {
+ if( rPoHeader.m_pGenPo )
+ {
+ *(rPoHeader.m_pGenPo) = aGenPo;
+ }
+ else
+ {
+ rPoHeader.m_pGenPo = new GenPoEntry( aGenPo );
+ }
+ rPoHeader.m_bIsInitialized = true;
+ m_bIsAfterHeader = true;
+ }
+ else
+ {
+ throw INVALIDHEADER;
+ }
+}
+
+void PoIfstream::readEntry( PoEntry& rPoEntry )
+{
+ assert( isOpen() && !eof() && m_bIsAfterHeader );
+ GenPoEntry aGenPo;
+ aGenPo.readFromFile( m_aInPut );
+ if( aGenPo.isNull() )
+ {
+ m_bEof = true;
+ rPoEntry = PoEntry();
+ }
+ else
+ {
+ const OString sMsgCtxt = aGenPo.getMsgCtxt();
+ const sal_Int32 nFirstEndLine = sMsgCtxt.indexOf('\n');
+ const sal_Int32 nLastEndLine = sMsgCtxt.lastIndexOf('\n');
+ const sal_Int32 nLastDot = sMsgCtxt.lastIndexOf('.');
+ const OString sType = sMsgCtxt.copy( nLastDot + 1 );
+ if( !aGenPo.getReference().isEmpty() &&
+ nFirstEndLine > 0 &&
+ (nLastEndLine == nFirstEndLine ||
+ nLastEndLine == sMsgCtxt.indexOf('\n',nFirstEndLine+1)) &&
+ nLastDot - nLastEndLine > 1 &&
+ (sType == "text" || sType == "quickhelptext" || sType == "title")&&
+ !aGenPo.getMsgId().isEmpty() )
+ {
+ if( rPoEntry.m_pGenPo )
+ {
+ *(rPoEntry.m_pGenPo) = aGenPo;
+ }
+ else
+ {
+ rPoEntry.m_pGenPo = new GenPoEntry( aGenPo );
+ }
+ const OString sExtractCom = aGenPo.getExtractCom();
+ if( sExtractCom.isEmpty() ||
+ ( sExtractCom.getLength() != 4 &&
+ sExtractCom.indexOf("\n") == -1 ) )
+ {
+ aGenPo.setExtractCom(
+ ( !sExtractCom.isEmpty() ? sExtractCom + "\n" : "" ) +
+ lcl_GenKeyId(
+ aGenPo.getReference() + sMsgCtxt +
+ aGenPo.getMsgId() ) );
+ }
+ rPoEntry.m_bIsInitialized = true;
+ }
+ else
+ {
+ throw INVALIDENTRY;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/propex.cxx b/l10ntools/source/propex.cxx
new file mode 100644
index 000000000000..2977cb158874
--- /dev/null
+++ b/l10ntools/source/propex.cxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "sal/main.h"
+
+#include "export.hxx"
+#include "propmerge.hxx"
+
+SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
+{
+ HandledArgs aArgs;
+ if( !Export::handleArguments(argc, argv, aArgs) )
+ {
+ Export::writeUsage("propex","properties");
+ return 1;
+ }
+
+ if( aArgs.m_sInputFile.indexOf("en_US") != -1 )
+ {
+ PropParser aParser(
+ aArgs.m_sInputFile, Export::sLanguages, aArgs.m_bMergeMode );
+ if( !aParser.isInitialized() )
+ {
+ return 1;
+ }
+ if( aArgs.m_bMergeMode )
+ {
+ aParser.Merge(aArgs.m_sMergeSrc, aArgs.m_sOutputFile);
+ }
+ else
+ {
+ aParser.Extract(
+ aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot );
+ }
+ }
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/propmerge.cxx b/l10ntools/source/propmerge.cxx
new file mode 100644
index 000000000000..689e931c4b72
--- /dev/null
+++ b/l10ntools/source/propmerge.cxx
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+
+#include "export.hxx"
+#include "common.hxx"
+#include "propmerge.hxx"
+
+namespace
+{
+ //Write out an sdf line
+ static void lcl_WriteSDF(
+ std::ofstream &aSDFStream, const OString& rText, const OString& rPrj,
+ const OString& rActFileName, const OString& rID )
+ {
+ OString sOutput( rPrj ); sOutput += "\t";
+ sOutput += rActFileName;
+ sOutput += "\t0\tproperty\t";
+ sOutput += rID; sOutput += "\t\t\t\t0\ten-US\t";
+ sOutput += rText; sOutput += "\t\t\t\t";
+ aSDFStream << sOutput.getStr() << std::endl;
+ }
+
+ //Find ascii escaped unicode
+ static sal_Int32 lcl_IndexOfUnicode(
+ const OString& rSource, const sal_Int32 nFrom = 0 )
+ {
+ const OString sHexDigits = "0123456789abcdefABCDEF";
+ sal_Int32 nIndex = rSource.indexOf( "\\u", nFrom );
+ if( nIndex == -1 )
+ {
+ return -1;
+ }
+ bool bIsUnicode = true;
+ for( short nDist = 2; nDist <= 5; ++nDist )
+ {
+ if( sHexDigits.indexOf( rSource[nIndex + nDist] ) == -1 )
+ {
+ bIsUnicode = false;
+ }
+ }
+ return bIsUnicode ? nIndex : -1;
+ }
+
+ //Convert ascii escaped unicode to utf-8
+ static OString lcl_ConvertToUTF8( const OString& rText )
+ {
+ OString sResult = rText;
+ sal_Int32 nIndex = lcl_IndexOfUnicode( sResult );
+ while( nIndex != -1 && nIndex < rText.getLength() )
+ {
+ const OString sHex = sResult.copy( nIndex + 2, 4 );
+ const sal_Unicode cDec =
+ static_cast<sal_Unicode>( strtol( sHex.getStr(), NULL, 16 ) );
+ const OString sNewChar =
+ OString( &cDec, 1, RTL_TEXTENCODING_UTF8 );
+ sResult = sResult.replaceAll( "\\u" + sHex, sNewChar );
+ nIndex = lcl_IndexOfUnicode( sResult, nIndex );
+ }
+ return sResult;
+ }
+
+ //Escape unicode characters
+ static void lcl_PrintJavaStyle( const OString& rText, std::ofstream &rOfstream )
+ {
+ const OUString sTemp =
+ OStringToOUString( rText, RTL_TEXTENCODING_UTF8 );
+ for ( sal_Int32 nIndex = 0; nIndex < sTemp.getLength(); ++nIndex )
+ {
+ sal_Unicode cUniCode = sTemp[nIndex];
+ if( cUniCode < 128 )
+ {
+ rOfstream << static_cast<char>( cUniCode );
+ }
+ else
+ {
+ rOfstream
+ << "\\u"
+ << std::setfill('0') << std::setw(2) << std::uppercase
+ << std::hex << (cUniCode >> 8) << (cUniCode & 0xFF);
+ }
+ }
+ }
+}
+
+//Open source file and store its lines
+PropParser::PropParser(
+ const OString& rInputFile, const OString& rLang,
+ const bool bMergeMode )
+ : m_vLines( std::vector<OString>() )
+ , m_sSource( rInputFile )
+ , m_sLang( rLang )
+ , m_bIsInitialized( false )
+{
+ std::ifstream aIfstream( m_sSource.getStr() );
+ if( aIfstream.is_open() )
+ {
+ std::string s;
+ std::getline( aIfstream, s );
+ while( !aIfstream.eof() )
+ {
+ OString sLine( s.data(), s.length() );
+ if( bMergeMode ||
+ ( !sLine.startsWith(" *") && !sLine.startsWith("/*") ) )
+ {
+ m_vLines.push_back( sLine );
+ }
+ std::getline( aIfstream, s );
+ }
+ }
+ else
+ {
+ std::cerr
+ << "Propex error: Cannot open source file: "
+ << m_sSource.getStr() << std::endl;
+ return;
+ }
+ m_bIsInitialized = true;
+}
+
+PropParser::~PropParser()
+{
+}
+
+//Extract strings form source file
+void PropParser::Extract(
+ const OString& rSDFFile, const OString& rPrj, const OString& rRoot )
+{
+ assert( m_bIsInitialized );
+ std::ofstream aSDFStream(
+ rSDFFile.getStr(), std::ios_base::out | std::ios_base::trunc );
+ if( !aSDFStream.is_open() )
+ {
+ std::cerr
+ << "Propex error: Cannot open sdffile for extract: "
+ << rSDFFile.getStr() << std::endl;
+ return;
+ }
+
+ for( unsigned nIndex = 0; nIndex < m_vLines.size(); ++nIndex )
+ {
+ const OString sLine = m_vLines[nIndex];
+ const sal_Int32 nEqualSign = sLine.indexOf('=');
+ if( nEqualSign != -1 )
+ {
+ lcl_WriteSDF(
+ aSDFStream,
+ lcl_ConvertToUTF8( sLine.copy( nEqualSign + 1 ).trim() ),//Text
+ rPrj,
+ common::pathnameToken(
+ m_sSource.getStr(), rRoot.getStr()), //FileName
+ sLine.copy( 0, nEqualSign ).trim() ); //ID
+ }
+ }
+
+ aSDFStream.close();
+}
+
+//Merge strings to source file
+void PropParser::Merge( const OString &rMergeSrc, const OString &rDestinationFile )
+{
+ assert( m_bIsInitialized );
+ std::ofstream aDestination(
+ rDestinationFile.getStr(), std::ios_base::out | std::ios_base::trunc );
+ if( !aDestination.is_open() ) {
+ std::cerr
+ << "Propex error: Cannot open source file for merge: "
+ << rDestinationFile.getStr() << std::endl;
+ return;
+ }
+
+ MergeDataFile aMergeDataFile( rMergeSrc, m_sSource, false );
+
+ const std::vector<OString> aLanguages = aMergeDataFile.GetLanguages();
+ if( m_sLang != "qtz" && !aLanguages.empty() && aLanguages[0] != m_sLang )
+ {
+ std::cerr
+ << "Propex error: given language conflicts with "
+ << "language of Mergedata file: "
+ << m_sLang.getStr() << " - " << rMergeSrc.getStr() << std::endl;
+ return;
+ }
+
+ for( unsigned nIndex = 0; nIndex < m_vLines.size(); ++nIndex )
+ {
+ const OString sLine = m_vLines[nIndex];
+ const sal_Int32 nEqualSign = sLine.indexOf('=');
+ if( !sLine.startsWith(" *") && !sLine.startsWith("/*") &&
+ nEqualSign != -1 )
+ {
+ const OString sID( sLine.copy( 0, sLine.indexOf("=") ).trim() );
+ ResData aResData( "", sID , m_sSource );
+ aResData.sResTyp = "property";
+ PFormEntrys* pEntrys = aMergeDataFile.GetPFormEntrys( &aResData );
+ if( pEntrys )
+ {
+ OString sNewText;
+ pEntrys->GetText( sNewText, STRING_TYP_TEXT, m_sLang );
+ aDestination << (sID + OString("=")).getStr();
+ lcl_PrintJavaStyle( sNewText, aDestination );
+ aDestination << std::endl;
+ }
+ else
+ {
+ aDestination << sLine.getStr() << std::endl;
+ }
+ }
+ else
+ {
+ aDestination << sLine.getStr() << std::endl;
+ }
+ }
+ aDestination.close();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/renewpo.cxx b/l10ntools/source/renewpo.cxx
new file mode 100644
index 000000000000..a9f3321d2c4b
--- /dev/null
+++ b/l10ntools/source/renewpo.cxx
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <dirent.h>
+#include <string>
+#include <vector>
+#include <map>
+
+#include <osl/file.hxx>
+#include <rtl/string.hxx>
+
+#include "po.hxx"
+
+using namespace std;
+
+bool isInSameFile( const OString& rFirstLine, const OString& rSecondLine)
+{
+ const OString rFirstSource =
+ rFirstLine.getToken(PoEntry::SOURCEFILE,'\t');
+ const OString rSecondSource =
+ rSecondLine.getToken(PoEntry::SOURCEFILE,'\t');
+ return
+ rFirstSource.copy(0,rFirstSource.lastIndexOf("\\")) ==
+ rSecondSource.copy(0,rSecondSource.lastIndexOf("\\"));
+}
+
+
+//Get path of po file
+OString GetPath(const OString& rPath, const OString& rLine)
+{
+ OString sSourceFile = rLine.getToken(PoEntry::SOURCEFILE,'\t');
+ OString sSourcePath = rPath + "/" +
+ rLine.getToken(PoEntry::PROJECT,'\t') + "/" +
+ sSourceFile.copy(0,sSourceFile.lastIndexOf("\\")).
+ replaceAll("\\","/");
+ return sSourcePath;
+}
+
+OString DelLocalId(const OString& rLine)
+{
+ unsigned nTabIndex = 0;
+ for(unsigned nComponent=0; nComponent<PoEntry::LOCALID; ++nComponent)
+ {
+ nTabIndex = rLine.indexOf('\t',nTabIndex);
+ ++nTabIndex;
+ }
+ return rLine.replaceAt(nTabIndex,
+ rLine.indexOf('\t',nTabIndex)-nTabIndex,
+ "");
+}
+
+//Renew po files of the actual language
+void HandleLanguage(struct dirent* pLangEntry, const OString& rOldPath,
+ const OString& rNewPath, const OString& rpo2loPath,
+ const OString& rSDFPath)
+{
+ const OString LangEntryName = pLangEntry->d_name;
+
+ //Generate and open sdf
+ cout << "Process start with language: " << LangEntryName.getStr() << endl;
+ OUString aTempUrl;
+ if (osl::FileBase::createTempFile(0, 0, &aTempUrl)
+ != osl::FileBase::E_None)
+ {
+ cerr << "osl::FileBase::createTempFile() failed\n";
+ return;
+ }
+ OUString aTempPath;
+ if (osl::FileBase::getSystemPathFromFileURL(aTempUrl, aTempPath)
+ != osl::FileBase::E_None)
+ {
+ cerr
+ << "osl::FileBase::getSystemPathFromFileURL(" << aTempUrl
+ << ") failed\n";
+ return;
+ }
+ const OString SDFFileName =
+ OUStringToOString(aTempPath, RTL_TEXTENCODING_UTF8);
+ system( (rpo2loPath +
+ " -i " + rOldPath + "/" + LangEntryName +
+ " -o " + SDFFileName +
+ " -l " + LangEntryName +
+ " -t " + rSDFPath).getStr());
+ cout << "Language sdf is ready!" << endl;
+
+ //Store info for po entries
+ ifstream aSDFInput(SDFFileName.getStr());
+ map<sal_Int32,pair<OString,OString> > aPoInfos;
+ string s;
+ getline(aSDFInput,s);
+ while(!aSDFInput.eof())
+ {
+ //Get strings belong to one po entry and store
+ const OString sActUnTrans = OString(s.data(),s.length());
+ if( sActUnTrans.getToken(PoEntry::LANGUAGEID,'\t')=="ast" ) throw;
+ getline(aSDFInput,s);
+ const OString sActTrans = OString(s.data(),s.length());
+
+ if(!(aPoInfos.insert( pair<sal_Int32,pair<OString,OString> >(
+ sActTrans.getToken(PoEntry::WIDTH,'\t').toInt32(),
+ pair<OString,OString>(sActUnTrans,sActTrans))).second))
+ {
+ cerr << "Error: faild to insert into map!" << '\n';
+ throw;
+ }
+ getline(aSDFInput,s);
+ }
+
+ //Close and remove sdf file
+ aSDFInput.close();
+ if (osl::File::remove(aTempUrl) != osl::FileBase::E_None)
+ {
+ cerr << "Warning: failure removing temporary " << aTempUrl << '\n';
+ }
+
+ //Construct and write out po entries
+ PoOfstream aNewPo;
+ for( map<sal_Int32,pair<OString,OString> >::iterator
+ pActInfo=aPoInfos.begin(); pActInfo!=aPoInfos.end(); ++pActInfo )
+ {
+ //Make new po file and add header
+ if ( pActInfo==aPoInfos.begin() ||
+ !isInSameFile(((--pActInfo)++)->second.first,pActInfo->second.first) )
+ {
+ if( pActInfo!=aPoInfos.begin() )
+ aNewPo.close();
+
+ const OString sNewPoFileName =
+ GetPath(rNewPath + "/" +LangEntryName,pActInfo->second.first) +
+ ".po";
+ system(("mkdir -p " + sNewPoFileName.copy(0,sNewPoFileName.lastIndexOf("/"))).getStr());
+ aNewPo.open(sNewPoFileName);
+ if (!aNewPo.isOpen())
+ {
+ cerr
+ << "Cannot open new po file: "
+ << sNewPoFileName.getStr() << endl;
+ return;
+ }
+ const OString sOldPoFileName =
+ GetPath(rOldPath + "/" +LangEntryName,pActInfo->second.first) +
+ ".po";
+ ifstream aOldPo(sOldPoFileName.getStr());
+ if (!aOldPo.is_open())
+ {
+ cerr
+ << "Cannot open old po file: "
+ << sOldPoFileName.getStr() << endl;
+ return;
+ }
+ aNewPo.writeHeader(PoHeader(aOldPo));
+ aOldPo.close();
+ }
+
+ //Write out po entries
+ const PoEntry::TYPE vInitializer[] =
+ { PoEntry::TTEXT, PoEntry::TQUICKHELPTEXT, PoEntry::TTITLE };
+ const vector<PoEntry::TYPE> vTypes( vInitializer,
+ vInitializer + sizeof(vInitializer) / sizeof(vInitializer[0]) );
+ unsigned short nDummyBit = 0;
+ for( unsigned short nIndex=0; nIndex<vTypes.size(); ++nIndex )
+ {
+ if (!pActInfo->second.first.getToken(vTypes[nIndex],'\t').isEmpty())
+ {
+ /**Because of xrmex there are duplicated id's,
+ only use this if xrmex have already fixed*/
+ const OString sSource =
+ pActInfo->second.first.getToken(PoEntry::SOURCEFILE,'\t');
+ const OString sEnding =
+ sSource.copy(sSource.getLength()-4, 4);
+ if (pActInfo->second.first.getToken(PoEntry::GROUPID,'\t')==
+ pActInfo->second.first.getToken(PoEntry::LOCALID,'\t') &&
+ ( sEnding == ".xrm" || sEnding == ".xml" ))
+ {
+ pActInfo->second.first = DelLocalId(pActInfo->second.first);
+ }
+ try
+ {
+ PoEntry aPE(pActInfo->second.first, vTypes[nIndex]);
+ const OString sActStr =
+ pActInfo->second.second.getToken(vTypes[nIndex],'\t');
+ aPE.setMsgStr(sActStr);
+ aPE.setFuzzy( sActStr.isEmpty() ? false :
+ static_cast<bool>(pActInfo->second.second.getToken(PoEntry::DUMMY,'\t').
+ copy(nDummyBit++,1).toBoolean()));
+ aNewPo.writeEntry(aPE);
+ }
+ catch( PoEntry::Exception& )
+ {
+ cerr
+ << "Invalid sdf line "
+ << pActInfo->second.first.replaceAll("\t","\\t").getStr() << '\n';
+ }
+ }
+ }
+ }
+ aNewPo.close();
+ aPoInfos.clear();
+}
+
+
+int main(int argc, char* argv[])
+{
+ //Usage
+ if (argc < 4)
+ {
+ cout << "Use: renewpot oldpots newpots po2lo en-US.sdf" << endl;
+ return 1;
+ }
+
+ //Call processing function with all language directories
+ DIR* pTranslations = opendir(argv[1]);
+ while ( struct dirent* pActEntry = readdir(pTranslations) )
+ {
+ if ( OString(pActEntry->d_name).indexOf('.')==-1 )
+ HandleLanguage(pActEntry,OString(argv[1]),
+ OString(argv[2]),OString(argv[3]),
+ OString(argv[4]));
+ }
+ closedir(pTranslations);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/tagtest.cxx b/l10ntools/source/tagtest.cxx
deleted file mode 100644
index ada1a36582f1..000000000000
--- a/l10ntools/source/tagtest.cxx
+++ /dev/null
@@ -1,1570 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include "sal/config.h"
-
-#include "rtl/strbuf.hxx"
-#include "rtl/string.hxx"
-#include "rtl/ustrbuf.hxx"
-#include "rtl/ustring.hxx"
-
-#include "tagtest.hxx"
-
-#if OSL_DEBUG_LEVEL > 1
-#include <stdio.h>
-#endif
-
-#include "gsicheck.hxx"
-#include "helper.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, sal_Int32 nP, rtl::OUString const & paStr, ParserMessageList &rErrorList )
-: bClosed(sal_False)
-, bCloseTag(sal_False)
-, bIsBroken(sal_False)
-, bHasBeenFixed(sal_False)
-, bDone(sal_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 )
-{
- sal_Int32 nLastPos = 2; // skip initial \<
- sal_Int32 nCheckPos = nLastPos;
- static char const aDelims[] = " \\=>/";
- rtl::OUString aPortion;
- rtl::OUString aValue; // store the value of a property
- rtl::OString aName; // store the name of a property/tag
- sal_Bool bCheckName = sal_False;
- sal_Bool bCheckEmpty = sal_False;
- sal_Unicode cDelim;
- tagcheck aState = TC_START;
-
- // skip blanks
- while ( nLastPos < aTokenString.getLength() && aTokenString[nLastPos] == ' ')
- nLastPos++;
-
- nCheckPos = helper::indexOfAnyAsciiL(
- aTokenString, RTL_CONSTASCII_STRINGPARAM(aDelims), nLastPos);
- while ( nCheckPos != -1 && !( aState == TC_FINISHED || aState == TC_ERROR ) )
- {
- aPortion = aTokenString.copy( nLastPos, nCheckPos-nLastPos );
-
- if ( aTokenString[nCheckPos] == '\\' )
- nCheckPos++;
-
- cDelim = aTokenString[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 = sal_True;
- break;
- case '/':
- {
- if (aPortion.isEmpty())
- {
- aState = TC_CLOSETAG;
- }
- else
- {
- aState = TC_CLOSED;
- bCheckName = sal_True;
- }
- }
- break;
- case '>': aState = TC_FINISHED;
- bCheckName = sal_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 = sal_True;
- break;
- case ' ': aState = TC_HAS_PROP_NAME_SP;
- bCheckName = sal_True;
- break;
- case '/': aState = TC_CLOSED;
- bCheckEmpty = sal_True;
- break;
- case '>': aState = TC_FINISHED;
- bCheckEmpty = sal_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 = sal_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 = sal_True;
- break;
- case '\"': aState = TC_INSIDE_STRING;
- bCheckEmpty = sal_True;
- aValue = rtl::OUString();
- 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 = sal_True;
- aValue = rtl::OUString();
- 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, rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Property '")).append(aName).append(RTL_CONSTASCII_STRINGPARAM("' has invalid value '")).append(rtl::OUStringToOString(aValue, RTL_TEXTENCODING_UTF8)).append("' ").makeStringAndClear(), *this );
- bIsBroken = sal_True;
- }
- aProperties[ aName ] = aValue;
- }
- else
- {
- rErrorList.AddError( 25, rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Property '")).append(aName).append(RTL_CONSTASCII_STRINGPARAM("' defined twice ")).makeStringAndClear(), *this );
- bIsBroken = sal_True;
- }
- }
- break;
- default:
- {
- aState = TC_INSIDE_STRING;
- aValue += aPortion;
- aValue += rtl::OUString(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 = sal_True;
- break;
- case '/': aState = TC_CLOSED;
- bCheckEmpty = sal_True;
- break;
- case '>': aState = TC_FINISHED;
- bCheckEmpty = sal_True;
- break;
- default: aState = TC_ERROR;
- }
- break;
-
-// CLOSED ' ' -> CLOSED_SPACE
-// CLOSED '>' -> FINISHED
- case TC_CLOSED:
- switch ( cDelim )
- {
- case ' ': aState = TC_CLOSED_SPACE;
- bCheckEmpty = sal_True;
- bClosed = sal_True;
- break;
- case '>': aState = TC_FINISHED;
- bCheckEmpty = sal_True;
- break;
- default: aState = TC_ERROR;
- }
- break;
-
-// CLOSED_SPACE '>' -> FINISHED
- case TC_CLOSED_SPACE:
- switch ( cDelim )
- {
- case '>': aState = TC_FINISHED;
- bCheckEmpty = sal_True;
- break;
- default: aState = TC_ERROR;
- }
- break;
-
-// CLOSETAG ' ' -> CLOSETAG_HAS_TAG_NAME
-// CLOSETAG '>' -> FINISHED
- case TC_CLOSETAG:
- bCloseTag = sal_True;
- switch ( cDelim )
- {
- case ' ': aState = TC_CLOSETAG_HAS_TAG_NAME;
- aTagName = aPortion;
- bCheckName = sal_True;
- break;
- case '>': aState = TC_FINISHED;
- aTagName = aPortion;
- bCheckName = sal_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 = sal_True;
- break;
- default: aState = TC_ERROR;
- }
- break;
-
-
- default: rErrorList.AddError( 99, "Internal error Parsing Tag ", *this );
- bIsBroken = sal_True;
-
- }
-
- if ( bCheckName )
- {
- if (aPortion.isEmpty())
- {
- rErrorList.AddError( 25, "Tag/Property name missing ", *this );
- bIsBroken = sal_True;
- }
- else
- {
- aName = rtl::OUStringToOString(aPortion, RTL_TEXTENCODING_UTF8);
- // "a-zA-Z_-.0-9"
- sal_Bool bBroken = sal_False;
- const sal_Char* aBuf = aName.getStr();
- for (sal_Int32 nCount = 0 ; !bBroken && nCount < aName.getLength() ; ++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 = sal_True;
- }
- }
-
- bCheckName = sal_False;
- }
-
- if ( bCheckEmpty )
- {
- if (!aPortion.isEmpty())
- {
- rErrorList.AddError( 25, rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Found displaced characters '")).append(rtl::OUStringToOString(aPortion, RTL_TEXTENCODING_UTF8)).append(RTL_CONSTASCII_STRINGPARAM("' in Tag ")).makeStringAndClear(), *this );
- bIsBroken = sal_True;
- }
- bCheckEmpty = sal_False;
- }
-
-
- nLastPos = nCheckPos;
-
- // skip further blanks
- if ( cDelim == ' ' && aState != TC_INSIDE_STRING )
- while ( nLastPos < aTokenString.getLength() && aTokenString[nLastPos] == ' ')
- nLastPos++;
-
- nCheckPos = helper::indexOfAnyAsciiL(
- aTokenString, RTL_CONSTASCII_STRINGPARAM(aDelims), nLastPos);
- }
- if ( aState != TC_FINISHED )
- {
- rErrorList.AddError( 25, "Parsing error in Tag ", *this );
- bIsBroken = sal_True;
- }
-}
-
-sal_Bool TokenInfo::IsPropertyRelevant( const rtl::OString &rName, const rtl::OUString &rValue ) const
-{
- if ( aTagName == "alt" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("xml-lang")) )
- return sal_False;
- if ( aTagName == "ahelp" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("visibility")) && rValue == "visible" )
- return sal_False;
- if ( aTagName == "image" && (rName.equalsL(RTL_CONSTASCII_STRINGPARAM("width")) || rName.equalsL(RTL_CONSTASCII_STRINGPARAM("height"))) )
- return sal_False;
-
- return sal_True;
-}
-
-sal_Bool TokenInfo::IsPropertyValueValid( const rtl::OString &rName, const rtl::OUString &rValue ) const
-{
-/* removed due to i56740
- if ( aTagName.EqualsAscii( "switchinline" ) && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("select")) )
- {
- return rValue.EqualsAscii("sys") ||
- rValue.EqualsAscii("appl") ||
- rValue.EqualsAscii("distrib");
- } */
- if ( aTagName == "caseinline" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("select")) )
- {
- return !rValue.isEmpty();
- }
-
- // we don't know any better so we assume it to be OK
- return sal_True;
-}
-
-sal_Bool TokenInfo::IsPropertyInvariant( const rtl::OString &rName, const rtl::OUString &rValue ) const
-{
- if ( aTagName == "link" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("name")) )
- return sal_False;
- if ( aTagName == "link" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("href")) )
- { // check for external reference
- return
- !(rValue.matchIgnoreAsciiCaseAsciiL(
- RTL_CONSTASCII_STRINGPARAM("http:"))
- || rValue.matchIgnoreAsciiCaseAsciiL(
- RTL_CONSTASCII_STRINGPARAM("https:"))
- || rValue.matchIgnoreAsciiCaseAsciiL(
- RTL_CONSTASCII_STRINGPARAM("ftp:")));
- }
- return sal_True;
-}
-
-sal_Bool TokenInfo::IsPropertyFixable( const rtl::OString &rName ) const
-{
- // name everything that is allowed to be fixed automatically here
- if ( (aTagName == "ahelp" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("hid")))
- || (aTagName == "link" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("href")))
- || (aTagName == "alt" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("id")))
- || (aTagName == "variable" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("id")))
- || (aTagName == "image" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("src")))
- || (aTagName == "image" && rName.equalsL(RTL_CONSTASCII_STRINGPARAM("id")) ))
- return sal_True;
- return sal_False;
-}
-
-sal_Bool TokenInfo::MatchesTranslation( TokenInfo& rInfo, sal_Bool bGenErrors, ParserMessageList &rErrorList, sal_Bool bFixTags ) const
-{
- // check if tags are equal
- // check if all existing properties are in the translation as well and
- // whether they have a matching content (the same in most cases)
-
- if ( nId != rInfo.nId )
- return sal_False;
-
- if ( aTagName != rInfo.aTagName )
- return sal_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 sal_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 != iProp->second )
- {
- if ( bGenErrors )
- {
- if ( bFixTags && IsPropertyFixable( iProp->first ) )
- {
- rInfo.aProperties.find( iProp->first )->second = iProp->second;
- rInfo.SetHasBeenFixed();
- rErrorList.AddWarning( 25, rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Property '")).append(iProp->first).append(RTL_CONSTASCII_STRINGPARAM("': FIXED different value in Translation ")).makeStringAndClear(), *this );
- }
- else
- rErrorList.AddError( 25, rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Property '")).append(iProp->first).append(RTL_CONSTASCII_STRINGPARAM("': value different in Translation ")).makeStringAndClear(), *this );
- }
- else return sal_False;
- }
- }
- }
- }
- else
- {
- if ( IsPropertyRelevant( iProp->first, iProp->second ) )
- {
- if ( bGenErrors )
- rErrorList.AddError( 25, rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Property '")).append(iProp->first).append(RTL_CONSTASCII_STRINGPARAM("' missing in Translation ")).makeStringAndClear(), *this );
- else return sal_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, rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM("Extra Property '")).append(iProp->first).append(RTL_CONSTASCII_STRINGPARAM("' in Translation ")).makeStringAndClear(), rInfo );
- else return sal_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 sal_True;
-}
-
-rtl::OUString TokenInfo::GetTagName() const
-{
- return aTagName;
-}
-
-rtl::OUString TokenInfo::MakeTag() const
-{
- rtl::OUStringBuffer 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( rtl::OStringToOUString( iProp->first, RTL_TEXTENCODING_UTF8 ) );
- aRet.appendAscii("=\\\"");
- aRet.append( iProp->second );
- aRet.appendAscii("\\\"");
- }
- if ( bClosed )
- aRet.appendAscii("/");
- aRet.appendAscii("\\>");
- return aRet.makeStringAndClear();
-}
-
-
-void ParserMessageList::AddError( sal_Int32 nErrorNr, const rtl::OString& rErrorText, const TokenInfo &rTag )
-{
- maList.push_back( new ParserError( nErrorNr, rErrorText, rTag ) );
-}
-
-void ParserMessageList::AddWarning( sal_Int32 nErrorNr, const rtl::OString& rErrorText, const TokenInfo &rTag )
-{
- maList.push_back( new ParserWarning( nErrorNr, rErrorText, rTag ) );
-}
-
-sal_Bool ParserMessageList::HasErrors()
-{
- for ( size_t i = 0, n = maList.size(); i < n; ++i )
- if ( maList[ i ]->IsError() )
- return sal_True;
- return sal_False;
-}
-
-void ParserMessageList::clear()
-{
- for ( size_t i = 0, n = maList.size(); i < n; ++i )
- delete maList[ i ];
- maList.clear();
-}
-
-struct Tag
-{
- rtl::OUString GetName() const { return rtl::OUString::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( rtl::OUString const & PaSource )
-{
- aSource = PaSource;
- nPos = 0;
- aLastToken = rtl::OUString();
- aNextTag = TokenInfo( TAG_NOMORETAGS, TOK_INVALIDPOS );
- aTokenList.clear();
-};
-
-TokenInfo SimpleParser::GetNextToken( ParserMessageList &rErrorList )
-{
- TokenInfo aResult;
- sal_Int32 nTokenStartPos = 0;
- if ( aNextTag.nId != TAG_NOMORETAGS )
- {
- aResult = aNextTag;
- aNextTag = TokenInfo( TAG_NOMORETAGS, TOK_INVALIDPOS );
- }
- else
- {
- aLastToken = GetNextTokenString( rErrorList, nTokenStartPos );
- if ( aLastToken.isEmpty() )
- return TokenInfo( TAG_NOMORETAGS, TOK_INVALIDPOS );
-
- // do we have a \< ... \> style tag?
- if (aLastToken.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("\\<")))
- {
- // check for paired \" \"
- bool bEven = true;
- sal_Int32 nQuotePos = 0;
- sal_Int32 nQuotedQuotesPos =
- aLastToken.indexOfAsciiL(RTL_CONSTASCII_STRINGPARAM("\\\""));
- sal_Int32 nQuotedBackPos = aLastToken.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("\\\\"));
- // this is only to kick out quoted backslashes
- while (nQuotedQuotesPos != -1)
- {
- if ( nQuotedBackPos != -1 && nQuotedBackPos <= nQuotedQuotesPos )
- nQuotePos = nQuotedBackPos+2;
- else
- {
- nQuotePos = nQuotedQuotesPos+2;
- bEven = !bEven;
- }
- nQuotedQuotesPos = aLastToken.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("\\\""), nQuotePos);
- nQuotedBackPos = aLastToken.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("\\\\"), 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
- sal_Int32 nNonBlankStartPos = 2;
- while (aLastToken[nNonBlankStartPos] == ' ')
- nNonBlankStartPos++;
- if (aLastToken[nNonBlankStartPos] == '/')
- aResult = TokenInfo( TAG_COMMONEND, nTokenStartPos, aLastToken, rErrorList );
- else
- {
- aResult = TokenInfo( TAG_COMMONSTART, nTokenStartPos, aLastToken, rErrorList );
- sal_Int32 nNonBlankEndPos = aLastToken.getLength() - 3;
- while (aLastToken[nNonBlankEndPos] == ' ')
- nNonBlankEndPos--;
- if (aLastToken[nNonBlankEndPos] == '/')
- aNextTag = TokenInfo( TAG_COMMONEND, nTokenStartPos, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\\</")) + aResult.GetTagName() + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\\>")), rErrorList );
- }
- }
- else
- {
- sal_Int32 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 );
- return aResult;
-}
-
-rtl::OUString SimpleParser::GetNextTokenString( ParserMessageList &rErrorList, sal_Int32 &rTagStartPos )
-{
- sal_Int32 nStyle2StartPos = aSource.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("$["), nPos );
- sal_Int32 nStyle3StartPos = aSource.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("\\<"), nPos);
- sal_Int32 nStyle4StartPos = aSource.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("\\\\"), nPos);
- // this is only to kick out quoted backslashes
-
- rTagStartPos = 0;
-
- if (nStyle2StartPos == -1 && nStyle3StartPos == -1)
- return rtl::OUString(); // no more tokens
-
- if ( nStyle4StartPos != -1
- && (nStyle2StartPos == -1 || nStyle4StartPos < nStyle2StartPos)
- && (nStyle3StartPos == -1 || nStyle4StartPos < nStyle3StartPos ) )
- // to make sure \\ is always handled first
- { // Skip quoted Backslash
- nPos = nStyle4StartPos +2;
- return GetNextTokenString( rErrorList, rTagStartPos );
- }
-
- if ( nStyle2StartPos != -1 && ( nStyle3StartPos == -1 || nStyle2StartPos < nStyle3StartPos ) )
- { // test for $[ ... ] style tokens
- sal_Int32 nEndPos = aSource.indexOf(']', nStyle2StartPos);
- if (nEndPos == -1)
- { // 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
- sal_Int32 nEndPos = aSource.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("\\>"), nStyle3StartPos);
- sal_Int32 nQuotedBackPos = aSource.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("\\\\"), nStyle3StartPos);
- // this is only to kick out quoted backslashes
- while (nQuotedBackPos <= nEndPos && nQuotedBackPos != -1)
- {
- nEndPos = aSource.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("\\>"), nQuotedBackPos + 2);
- nQuotedBackPos = aSource.indexOfAsciiL(
- RTL_CONSTASCII_STRINGPARAM("\\\\"), nQuotedBackPos + 2);
- // this is only to kick out quoted backslashes
- }
- if (nEndPos == -1)
- { // Token is incomplete. Skip start and search for better ones
- nPos = nStyle3StartPos +2;
- rErrorList.AddError( 24, "Tag Start '\\<' without Tag End '\\>'", TokenInfo( TAG_UNKNOWN_TAG, nStyle3StartPos, helper::abbreviate(aSource, nStyle3StartPos - 10, 20) ) );
- return GetNextTokenString( rErrorList, rTagStartPos );
- }
- // check for paired quoted " --> \"sometext\"
-
- nPos = nEndPos;
- rTagStartPos = nStyle3StartPos;
- return aSource.copy(nStyle3StartPos, nEndPos-nStyle3StartPos + 2);
- }
-}
-
-rtl::OUString SimpleParser::GetLexem( TokenInfo const &aToken )
-{
- if ( !aToken.aTokenString.isEmpty() )
- return aToken.aTokenString;
- else
- {
- sal_Int32 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 rtl::OUString &aCode, ParserMessageList* pList )
-{
- pErrorList = pList;
-
- //Scanner initialisieren
- aParser.Parse( aCode );
-
- //erstes Symbol holen
- aTag = aParser.GetNextToken( *pErrorList );
-
- nPfCaseOptions = 0;
- nAppCaseOptions = 0;
- bPfCaseActive = sal_False;
- bAppCaseActive = sal_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_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_WIN:
- case TAG_UNIX:
- case TAG_MAC: //...
- {
- if ( ! bPfCaseActive )
- {
- //PfCases duerfen nicht verschachtelt sein:
- bPfCaseActive = sal_True;
- PfCase();
-
- //So jetzt kann wieder ein PfCase kommen:
- bPfCaseActive = sal_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 = sal_True;
- AppCase();
-
- //jetzt koennen wieder AppCases kommen:
- bAppCaseActive = sal_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_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_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 );
- }
-}
-
-sal_Bool TokenParser::match( const TokenInfo &aCurrentToken, const TokenId &aExpectedToken )
-{
- return match( aCurrentToken, TokenInfo( aExpectedToken, TOK_INVALIDPOS ) );
-}
-
-sal_Bool TokenParser::match( const TokenInfo &aCurrentToken, const TokenInfo &rExpectedToken )
-{
- TokenInfo aExpectedToken( rExpectedToken );
- if ( aCurrentToken.nId == aExpectedToken.nId )
- {
- if ( ( aCurrentToken.nId == TAG_COMMONEND
- && aCurrentToken.GetTagName() == aExpectedToken.GetTagName() )
- || aCurrentToken.nId != TAG_COMMONEND )
- {
- aTag = aParser.GetNextToken( *pErrorList );
- return sal_True;
- }
- }
-
- if ( aExpectedToken.nId == TAG_COMMONEND )
- {
- aExpectedToken.aTokenString =
- rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Close tag for "))
- + aExpectedToken.aTokenString;
- }
-
- rtl::OString sTmp(RTL_CONSTASCII_STRINGPARAM("Expected Symbol"));
- if ( aCurrentToken.nId == TAG_NOMORETAGS )
- {
- ParseError( 7, sTmp, aExpectedToken );
- }
- else
- {
- rtl::OStringBuffer aBuf(sTmp);
- aBuf.append(": ").
- append(rtl::OUStringToOString(aParser.GetLexem( aExpectedToken ), RTL_TEXTENCODING_UTF8)).
- append(RTL_CONSTASCII_STRINGPARAM(" near "));
- ParseError( 7, aBuf.makeStringAndClear(), aCurrentToken );
- }
- return sal_False;
-}
-
-void TokenParser::ParseError( sal_Int32 nErrNr, const rtl::OString &rErrMsg, const TokenInfo &rTag )
-{
- pErrorList->AddError( nErrNr, rErrMsg, rTag);
-
- // Das Fehlerhafte Tag ueberspringen
- aTag = aParser.GetNextToken( *pErrorList );
-}
-
-
-ParserMessage::ParserMessage( sal_Int32 PnErrorNr, const rtl::OString &rPaErrorText, const TokenInfo &rTag )
- : nErrorNr( PnErrorNr )
- , nTagBegin( 0 )
- , nTagLength( 0 )
-{
- rtl::OUString aLexem( SimpleParser::GetLexem( rTag ) );
- rtl::OStringBuffer aErrorBuffer(rPaErrorText);
- aErrorBuffer.append(RTL_CONSTASCII_STRINGPARAM(": "));
- aErrorBuffer.append(rtl::OUStringToOString(aLexem, RTL_TEXTENCODING_UTF8));
- if ( rTag.nId == TAG_NOMORETAGS )
- aErrorBuffer.append(RTL_CONSTASCII_STRINGPARAM(" at end of line "));
- else if ( rTag.nPos != TOK_INVALIDPOS )
- {
- aErrorBuffer.append(RTL_CONSTASCII_STRINGPARAM(" at Position "));
- aErrorBuffer.append(static_cast<sal_Int32>(rTag.nPos));
- }
- aErrorText = aErrorBuffer.makeStringAndClear();
- nTagBegin = rTag.nPos;
- nTagLength = aLexem.getLength();
-}
-
-ParserError::ParserError( sal_Int32 ErrorNr, const rtl::OString &rErrorText, const TokenInfo &rTag )
-: ParserMessage( ErrorNr, rErrorText, rTag )
-{}
-
-ParserWarning::ParserWarning( sal_Int32 ErrorNr, const rtl::OString &rErrorText, const TokenInfo &rTag )
-: ParserMessage( ErrorNr, rErrorText, rTag )
-{}
-
-sal_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 sal_True;
- }
- else if ( TAG_COMMONSTART == aTokenId
- || TAG_COMMONEND == aTokenId )
- {
- rtl::OUString aTagName = aToken.GetTagName();
- return !(aTagName.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("comment"))
- || aTagName.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("bookmark_value"))
- || aTagName.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("emph"))
- || aTagName.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("item"))
- || aTagName.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("br")) );
- }
- return sal_False;
-}
-
-void LingTest::CheckTags( TokenList &aReference, TokenList &aTestee, sal_Bool bFixTags )
-{
- size_t i=0,j=0;
- // Clean old Warnings
- aCompareWarningList.clear();
-
- /* 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.size() ; i++ )
- {
- if ( !IsTagMandatory( aReference[ i ], aMetaTokens ) )
- aReference[ i ].SetDone();
- }
-
- aMetaTokens = 0;
- for ( i=0 ; i < aTestee.size() ; i++ )
- {
- if ( !IsTagMandatory( aTestee[ i ], aMetaTokens ) )
- aTestee[ i ].SetDone();
- }
-
- // remove all matching tags
- for ( i=0 ; i < aReference.size() ; i++ )
- {
- if ( aReference[ i ].IsDone() )
- continue;
-
- sal_Bool bTagFound = sal_False;
- for ( j=0 ; j < aTestee.size() && !bTagFound ; j++ )
- {
- if ( aTestee[ j ].IsDone() )
- continue;
-
- if ( aReference[ i ].MatchesTranslation( aTestee[ j ], sal_False, aCompareWarningList ) )
- {
- aReference[ i ].SetDone();
- aTestee[ j ].SetDone();
- bTagFound = sal_True;
- }
- }
- }
-
- sal_Bool bCanFix = sal_True;
-
- if ( bFixTags )
- {
- // we fix only if its a really simple case
- sal_Int32 nTagCount = 0;
- for ( i=0 ; i < aReference.size() ; i++ )
- if ( !aReference[ i ].IsDone() )
- nTagCount++;
- if ( nTagCount > 1 )
- bCanFix = sal_False;
-
- nTagCount = 0;
- for ( i=0 ; i < aTestee.size() ; i++ )
- if ( !aTestee[ i ].IsDone() )
- nTagCount++;
- if ( nTagCount > 1 )
- bCanFix = sal_False;
- }
-
- // generate errors for tags that have differing attributes
- for ( i=0 ; i < aReference.size() ; i++ )
- {
- if ( aReference[ i ].IsDone() )
- continue;
-
- sal_Bool bTagFound = sal_False;
- for ( j=0 ; j < aTestee.size() && !bTagFound ; j++ )
- {
- if ( aTestee[ j ].IsDone() )
- continue;
-
- if ( aReference[ i ].MatchesTranslation( aTestee[ j ], sal_True, aCompareWarningList, bCanFix && bFixTags ) )
- {
- aReference[ i ].SetDone();
- aTestee[ j ].SetDone();
- bTagFound = sal_True;
- }
- }
- }
-
- // list remaining tags as errors
- for ( i=0 ; i < aReference.size() ; i++ )
- {
- if ( aReference[ i ].IsDone() )
- continue;
-
- aCompareWarningList.AddError( 20, "Missing Tag in Translation", aReference[ i ] );
- }
- for ( i=0 ; i < aTestee.size() ; i++ )
- {
- if ( aTestee[ i ].IsDone() )
- continue;
-
- aCompareWarningList.AddError( 21, "Extra Tag in Translation", aTestee[ i ] );
- }
-
- for ( i=0 ; i < aReference.size() ; i++ )
- aReference[ i ].SetDone( sal_False );
-
- for ( i=0 ; i < aTestee.size() ; i++ )
- aTestee[ i ].SetDone( sal_False );
-}
-
-void LingTest::CheckReference( GSILine *aReference )
-{
- aReferenceParser.Parse( aReference->GetUText(), aReference->GetMessageList() );
-}
-
-void LingTest::CheckTestee( GSILine *aTestee, sal_Bool bHasSourceLine, sal_Bool bFixTags )
-{
- aFixedTestee = aTestee->GetUText();
- aTesteeParser.Parse( aFixedTestee, aTestee->GetMessageList() );
-
- if ( bHasSourceLine )
- CheckTags( aReferenceParser.GetTokenList(), aTesteeParser.GetTokenList(), bFixTags );
-
- if ( bFixTags )
- {
- TokenList& aTesteeTokens = aTesteeParser.GetTokenList();
- sal_Bool bFixesDone = sal_False;
- // count backwards to allow replacing from right to left
- int i;
- for ( i = aTesteeTokens.size() ; i > 0 ; )
- {
- if ( aTesteeTokens[ --i ].HasBeenFixed() )
- {
- bFixesDone = sal_True;
- aFixedTestee = aFixedTestee.replaceAt( aTesteeTokens[ i ].nPos, aTesteeTokens[ i ].aTokenString.getLength(), aTesteeTokens[ i ].MakeTag() );
- }
- }
- if ( bFixesDone )
- {
- aTestee->SetUText( aFixedTestee );
- aTestee->SetFixed();
- }
- }
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/treemerge.cxx b/l10ntools/source/treemerge.cxx
new file mode 100644
index 000000000000..622564c5d58c
--- /dev/null
+++ b/l10ntools/source/treemerge.cxx
@@ -0,0 +1,305 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <cassert>
+#include <cstring>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlstring.h>
+
+#include "export.hxx"
+#include "common.hxx"
+#include "treemerge.hxx"
+
+
+namespace
+{
+ //Write out an sdf line
+ static void lcl_WriteSDF(
+ std::ofstream &aSDFStream, const OString& rText, const OString& rPrj,
+ const OString& rActFileName, const OString& rID, const OString& rType )
+ {
+ OString sOutput( rPrj ); sOutput += "\t";
+ sOutput += rActFileName;
+ sOutput += "\t0\t";
+ sOutput += rType; sOutput += "\t";
+ sOutput += rID; sOutput += "\t\t\t\t0\ten-US\t";
+ sOutput += rText; sOutput += "\t\t\t\t";
+ aSDFStream << sOutput.getStr() << std::endl;
+ }
+
+ //Convert xmlChar* to OString
+ static OString lcl_xmlStrToOString( const xmlChar* pString )
+ {
+ xmlChar* pTemp = xmlStrdup( pString );
+ OString sResult =
+ static_cast<OString>(reinterpret_cast<sal_Char*>( pTemp ));
+ xmlFree( pTemp );
+ return sResult;
+ }
+
+ //Extract strings from nodes on all level recursively
+ static void lcl_ExtractLevel(
+ const xmlDocPtr pSource, const xmlNodePtr pRoot,
+ const xmlChar* pNodeName, std::ofstream& rSDFStream,
+ const OString& rPrj, const OString& rRoot )
+ {
+ if( !pRoot->children )
+ {
+ return;
+ }
+ for( xmlNodePtr pCurrent = pRoot->children->next;
+ pCurrent; pCurrent = pCurrent->next)
+ {
+ if (!xmlStrcmp(pCurrent->name, pNodeName))
+ {
+ xmlChar* pID = xmlGetProp(pCurrent, (const xmlChar*)("id"));
+ xmlChar* pText =
+ xmlGetProp(pCurrent, (const xmlChar*)("title"));
+ lcl_WriteSDF(
+ rSDFStream,
+ lcl_xmlStrToOString( pText ),
+ rPrj,
+ common::pathnameToken(
+ pSource->name, rRoot.getStr()),
+ lcl_xmlStrToOString( pID ),
+ lcl_xmlStrToOString( pNodeName ));
+
+ xmlFree( pID );
+ xmlFree( pText );
+
+ lcl_ExtractLevel(
+ pSource, pCurrent, (const xmlChar *)("node"),
+ rSDFStream, rPrj, rRoot );
+ }
+ }
+ }
+
+ //Update id and content of the topic
+ static xmlNodePtr lcl_UpdateTopic(
+ const xmlNodePtr pCurrent, const OString& rXhpRoot )
+ {
+ xmlNodePtr pReturn = pCurrent;
+ xmlChar* pID = xmlGetProp(pReturn, (const xmlChar*)("id"));
+ const OString sID =
+ lcl_xmlStrToOString( pID );
+ xmlFree( pID );
+
+ const sal_Int32 nFirstSlash = sID.indexOf("/");
+ //Update id attribute of topic
+ {
+ OString sNewID =
+ sID.copy( 0, nFirstSlash + 1 ) +
+ rXhpRoot.copy( rXhpRoot.lastIndexOf("/") + 1 ) +
+ sID.copy( sID.indexOf( "/", nFirstSlash + 1 ) );
+ xmlSetProp(
+ pReturn, (const xmlChar*)("id"),
+ reinterpret_cast<const xmlChar*>(sNewID.getStr()));
+ }
+
+ const OString sXhpPath =
+ rXhpRoot +
+ sID.copy(sID.indexOf("/", nFirstSlash + 1));
+ xmlDocPtr pXhpFile = xmlParseFile( sXhpPath.getStr() );
+ //if xhpfile is missing than we put this topic into comment
+ if ( !pXhpFile )
+ {
+ xmlNodePtr pTemp = pReturn;
+ xmlChar* sNewID =
+ xmlGetProp(pReturn, (const xmlChar*)("id"));
+ xmlChar* sComment =
+ xmlStrcat( xmlCharStrdup("removed "), sNewID );
+ pReturn = xmlNewComment( sComment );
+ xmlReplaceNode( pTemp, pReturn );
+ xmlFree( pTemp );
+ xmlFree( sNewID );
+ xmlFree( sComment );
+ }
+ //update topic's content on the basis of xhpfile's title
+ else
+ {
+ xmlNodePtr pXhpNode = xmlDocGetRootElement( pXhpFile );
+ for( pXhpNode = pXhpNode->children;
+ pXhpNode; pXhpNode = pXhpNode->children )
+ {
+ while( pXhpNode->type != XML_ELEMENT_NODE )
+ {
+ pXhpNode = pXhpNode->next;
+ }
+ if(!xmlStrcmp(pXhpNode->name, (const xmlChar *)("title")))
+ {
+ xmlChar* sTitle =
+ xmlNodeListGetString(pXhpFile, pXhpNode->children, 1);
+ OString sNewTitle =
+ lcl_xmlStrToOString( sTitle ).
+ replaceAll("$[officename]","%PRODUCTNAME").
+ replaceAll("$[officeversion]","%PRODUCTVERSION");
+ xmlNodeSetContent(
+ pReturn,
+ xmlEncodeSpecialChars( NULL,
+ reinterpret_cast<const xmlChar*>(
+ sNewTitle.getStr() )));
+ xmlFree( sTitle );
+ break;
+ }
+ }
+ if( !pXhpNode )
+ {
+ std::cerr
+ << "Treex error: Cannot find title in "
+ << sXhpPath.getStr() << std::endl;
+ return 0;
+ }
+ xmlFree( pXhpFile );
+ xmlCleanupParser();
+ }
+ return pReturn;
+ }
+ //Localize title attribute of help_section and node tags
+ static void lcl_MergeLevel(
+ xmlDocPtr io_pSource, const xmlNodePtr pRoot,
+ const xmlChar * pNodeName, MergeDataFile* pMergeDataFile,
+ const OString& rLang, const OString& rXhpRoot )
+ {
+ if( !pRoot->children )
+ {
+ return;
+ }
+ for( xmlNodePtr pCurrent = pRoot->children;
+ pCurrent; pCurrent = pCurrent->next)
+ {
+ if( !xmlStrcmp(pCurrent->name, pNodeName) )
+ {
+ if( pMergeDataFile )
+ {
+ xmlChar* pID = xmlGetProp(pCurrent, (const xmlChar*)("id"));
+ ResData aResData(
+ "", lcl_xmlStrToOString( pID ),
+ static_cast<OString>(io_pSource->name) );
+ xmlFree( pID );
+ aResData.sResTyp = lcl_xmlStrToOString( pNodeName );
+ PFormEntrys* pEntrys =
+ pMergeDataFile->GetPFormEntrys( &aResData );
+ if( pEntrys )
+ {
+ OString sNewText;
+ pEntrys->GetText( sNewText, STRING_TYP_TEXT, rLang );
+ xmlSetProp(
+ pCurrent, (const xmlChar*)("title"),
+ (const xmlChar*)(sNewText.getStr()));
+ }
+ }
+ lcl_MergeLevel(
+ io_pSource, pCurrent, (const xmlChar *)("node"),
+ pMergeDataFile, rLang, rXhpRoot );
+ }
+ else if( !xmlStrcmp(pCurrent->name, (const xmlChar *)("topic")) )
+ {
+ pCurrent = lcl_UpdateTopic( pCurrent, rXhpRoot );
+ }
+ }
+ }
+}
+
+//Parse tree file
+TreeParser::TreeParser(
+ const OString& rInputFile, const OString& rLang )
+ : m_pSource( 0 )
+ , m_sLang( rLang )
+ , m_bIsInitialized( false )
+{
+ m_pSource = xmlParseFile( rInputFile.getStr() );
+ if ( !m_pSource ) {
+ std::cerr
+ << "Treex error: Cannot open source file: "
+ << rInputFile.getStr() << std::endl;
+ return;
+ }
+ if( !m_pSource->name )
+ {
+ m_pSource->name = new char[strlen(rInputFile.getStr())+1];
+ strcpy( m_pSource->name, rInputFile.getStr() );
+ }
+ m_bIsInitialized = true;
+}
+
+TreeParser::~TreeParser()
+{
+}
+
+//Extract strings form source file
+void TreeParser::Extract(
+ const OString& rSDFFile, const OString& rPrj, const OString& rRoot )
+{
+ assert( m_bIsInitialized );
+ std::ofstream aSDFStream(
+ rSDFFile.getStr(), std::ios_base::out | std::ios_base::trunc );
+ if( !aSDFStream.is_open() )
+ {
+ std::cerr
+ << "Treex error: Cannot open sdffile for extract: "
+ << rSDFFile.getStr() << std::endl;
+ return;
+ }
+
+ xmlNodePtr pRootNode = xmlDocGetRootElement( m_pSource );
+ lcl_ExtractLevel(
+ m_pSource, pRootNode, (const xmlChar *)("help_section"),
+ aSDFStream, rPrj, rRoot );
+
+ xmlFreeDoc( m_pSource );
+ xmlCleanupParser();
+ aSDFStream.close();
+ m_bIsInitialized = false;
+}
+
+//Merge strings to tree file and update reference to help files(xhp)
+void TreeParser::Merge(
+ const OString &rMergeSrc, const OString &rDestinationFile,
+ const OString &rXhpRoot )
+{
+ assert( m_bIsInitialized );
+
+ const xmlNodePtr pRootNode = xmlDocGetRootElement( m_pSource );
+ if( m_sLang == "en-US" )
+ {
+ lcl_MergeLevel(
+ m_pSource, pRootNode, (const xmlChar *)("help_section"),
+ 0, m_sLang, rXhpRoot );
+ }
+ else
+ {
+ MergeDataFile aMergeDataFile(
+ rMergeSrc, static_cast<OString>( m_pSource->name ), false );
+ const std::vector<OString> vLanguages = aMergeDataFile.GetLanguages();
+ if( !vLanguages.empty() && vLanguages[0] != m_sLang )
+ {
+ std::cerr
+ << "Treex error: given language conflicts with "
+ << "language of Mergedata file: "
+ << m_sLang.getStr() << " - " << rMergeSrc.getStr() << std::endl;
+ return;
+ }
+ lcl_MergeLevel(
+ m_pSource, pRootNode, (const xmlChar *)("help_section"),
+ &aMergeDataFile, m_sLang, rXhpRoot );
+ }
+
+ xmlSaveFile( rDestinationFile.getStr(), m_pSource );
+ xmlFreeDoc( m_pSource );
+ xmlCleanupParser();
+ m_bIsInitialized = false;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/treex.cxx b/l10ntools/source/treex.cxx
new file mode 100644
index 000000000000..65807b1a5c0b
--- /dev/null
+++ b/l10ntools/source/treex.cxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <iostream>
+#include "sal/main.h"
+
+#include "export.hxx"
+#include "treemerge.hxx"
+
+void WriteUsage()
+{
+ std::cout
+ << "Syntax: Treex [-p Prj] [-r Root] -i FileIn -o FileOut"
+ << " [-m DataBase] [-l l1,l2,...]\n"
+ << " Prj: Project\n"
+ << " Root: Path to project root (../.. etc.)\n"
+ << " or path to root of localized xhp files\n"
+ << " FileIn: Source files (*.tree)\n"
+ << " FileOut: Destination file (*.*)\n"
+ << " DataBase: Mergedata (*.po)\n"
+ << " -l: Restrict the handled languages; l1, l2, ... are elements of"
+ << " (de, en-US, ...)\n";
+}
+
+
+SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
+{
+ HandledArgs aArgs;
+ if( !Export::handleArguments(argc, argv, aArgs) )
+ {
+ WriteUsage();
+ return 1;
+ }
+
+ TreeParser aParser(aArgs.m_sInputFile, Export::sLanguages);
+ if( !aParser.isInitialized() )
+ {
+ return 1;
+ }
+
+ if( aArgs.m_bMergeMode || aArgs.m_sPrj.isEmpty() )
+ {
+ aParser.Merge(
+ aArgs.m_sMergeSrc, aArgs.m_sOutputFile, aArgs.m_sPrjRoot );
+ }
+ else
+ {
+ aParser.Extract(
+ aArgs.m_sOutputFile, aArgs.m_sPrj, aArgs.m_sPrjRoot );
+ }
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/l10ntools/source/uimerge.cxx b/l10ntools/source/uimerge.cxx
index bdf536a238dc..4192ed73d6be 100644
--- a/l10ntools/source/uimerge.cxx
+++ b/l10ntools/source/uimerge.cxx
@@ -26,100 +26,10 @@
#include <fstream>
#include <vector>
-#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_LANGUAGES 0x000C
-
-sal_Bool bMergeMode;
-sal_Bool bErrorLog;
-sal_Bool bUTF8;
-sal_Bool bDisplayName;
-sal_Bool bExtensionDescription;
rtl::OString sPrj;
rtl::OString sPrjRoot;
rtl::OString sInputFileName;
rtl::OString sOutputFile;
-rtl::OString sMergeSrc;
-rtl::OString sLangAttribute;
-rtl::OString sResourceType;
-XRMResParser *pParser = NULL;
-
-void GetOutputFile( int argc, char* argv[])
-{
- bMergeMode = sal_False;
- bErrorLog = sal_True;
- bUTF8 = sal_True;
- bDisplayName = sal_False;
- bExtensionDescription = sal_False;
- sPrj = "";
- sPrjRoot = "";
- sInputFileName = "";
- Export::sLanguages = "";
- sal_uInt16 nState = STATE_NON;
-
- // parse command line
- for( int i = 1; i < argc; i++ ) {
- if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-I" ) {
- nState = STATE_INPUT; // next token specifies source file
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-O" ) {
- nState = STATE_OUTPUT; // next token specifies the dest file
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-P" ) {
- nState = STATE_PRJ; // next token specifies the cur. project
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-R" ) {
- nState = STATE_ROOT; // next token specifies path to project root
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-M" ) {
- nState = STATE_MERGESRC; // next token specifies the merge database
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-E" ) {
- nState = STATE_ERRORLOG;
- bErrorLog = sal_False;
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-L" ) {
- nState = STATE_LANGUAGES;
- }
- else {
- switch ( nState ) {
- case STATE_NON: {
- return; // no valid command line
- }
- case STATE_INPUT: {
- sInputFileName = argv[ i ];
- }
- break;
- case STATE_OUTPUT: {
- sOutputFile = argv[ i ]; // the dest. file
- }
- break;
- case STATE_PRJ: {
- sPrj = rtl::OString( argv[ i ]);
- }
- break;
- case STATE_ROOT: {
- sPrjRoot = rtl::OString( argv[ i ]); // path to project root
- }
- break;
- case STATE_MERGESRC: {
- sMergeSrc = rtl::OString( argv[ i ]);
- bMergeMode = sal_True; // activate merge mode, cause merge database found
- }
- break;
- case STATE_LANGUAGES: {
- Export::sLanguages = rtl::OString( argv[ i ]);
- }
- break;
- }
- }
- }
-}
int extractTranslations()
{
@@ -275,22 +185,19 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
{
int nRetValue = 0;
- GetOutputFile( argc, argv );
-
- if (sOutputFile.isEmpty())
+ HandledArgs aArgs;
+ if ( !Export::handleArguments(argc, argv, aArgs) )
{
- fprintf( stdout, "Syntax: UIEX[-p Prj][-r PrjRoot]-i FileIn [-o FileOut][-m DataBase][-e][-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, " -L: Restrict the handled languages. l1,l2,... are elements of (de,en-US,es...)\n" );
+ Export::writeUsage("uiex","ui");
return 1;
}
- if (!bMergeMode)
+ sPrj = aArgs.m_sPrj;
+ sPrjRoot = aArgs.m_sPrjRoot;
+ sInputFileName = aArgs.m_sInputFile;
+ sOutputFile = aArgs.m_sOutputFile;
+
+ if (!aArgs.m_bMergeMode)
{
if (Export::sLanguages != "en-US")
{
@@ -302,7 +209,7 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
}
else
{
- Merge(sMergeSrc, sInputFileName, sOutputFile);
+ Merge(aArgs.m_sMergeSrc, sInputFileName, sOutputFile);
}
return nRetValue;
diff --git a/l10ntools/source/xrmlex.l b/l10ntools/source/xrmlex.l
index dfe74d7c1a56..8d6094c18d06 100644
--- a/l10ntools/source/xrmlex.l
+++ b/l10ntools/source/xrmlex.l
@@ -221,18 +221,8 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
pOutput = GetOutputFile( argc, argv );
- 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" );
+ if ( !pOutput )
+ {
return 1;
}
pFile = GetXrmFile();
diff --git a/l10ntools/source/xrmmerge.cxx b/l10ntools/source/xrmmerge.cxx
index a22996d8db43..5b562ea7f627 100644
--- a/l10ntools/source/xrmmerge.cxx
+++ b/l10ntools/source/xrmmerge.cxx
@@ -27,6 +27,7 @@
#include "export.hxx"
#include "xrmmerge.hxx"
#include "tokens.h"
+#include "helper.hxx"
#include <iostream>
#include <fstream>
#include <vector>
@@ -36,20 +37,8 @@ using namespace std;
void yyerror( const char * );
void YYWarning( const 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_LANGUAGES 0x000C
-
// set of global variables
-sal_Bool bEnableExport;
-sal_Bool bMergeMode;
-sal_Bool bUTF8;
+bool bMergeMode;
sal_Bool bDisplayName;
sal_Bool bExtensionDescription;
rtl::OString sPrj;
@@ -69,87 +58,30 @@ extern "C" {
extern char *GetOutputFile( int argc, char* argv[])
/*****************************************************************************/
{
- bEnableExport = sal_False;
- bMergeMode = sal_False;
- bUTF8 = sal_True;
bDisplayName = sal_False;
bExtensionDescription = sal_False;
- sPrj = "";
- sPrjRoot = "";
- sInputFileName = "";
sActFileName = "";
- Export::sLanguages = "";
- sal_uInt16 nState = STATE_NON;
- sal_Bool bInput = sal_False;
-
- // parse command line
- for( int i = 1; i < argc; i++ ) {
- if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-I" ) {
- nState = STATE_INPUT; // next token specifies source file
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-O" ) {
- nState = STATE_OUTPUT; // next token specifies the dest file
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-P" ) {
- nState = STATE_PRJ; // next token specifies the cur. project
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-R" ) {
- nState = STATE_ROOT; // next token specifies path to project root
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-M" ) {
- nState = STATE_MERGESRC; // next token specifies the merge database
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-E" ) {
- nState = STATE_ERRORLOG;
- }
- else if ( rtl::OString( argv[ i ] ).toAsciiUpperCase() == "-L" ) {
- nState = STATE_LANGUAGES;
- }
- else {
- switch ( nState ) {
- case STATE_NON: {
- return NULL; // no valid command line
- }
- case STATE_INPUT: {
- sInputFileName = argv[ i ];
- bInput = sal_True; // source file found
- }
- break;
- case STATE_OUTPUT: {
- sOutputFile = argv[ i ]; // the dest. file
- }
- break;
- case STATE_PRJ: {
- sPrj = rtl::OString( argv[ i ]);
- }
- break;
- case STATE_ROOT: {
- sPrjRoot = rtl::OString( argv[ i ]); // path to project root
- }
- break;
- case STATE_MERGESRC: {
- sMergeSrc = rtl::OString( argv[ i ]);
- bMergeMode = sal_True; // activate merge mode, cause merge database found
- }
- break;
- case STATE_LANGUAGES: {
- Export::sLanguages = rtl::OString( argv[ i ]);
- }
- break;
- }
- }
- }
- if ( bInput ) {
+ HandledArgs aArgs;
+ if ( Export::handleArguments(argc, argv, aArgs) )
+ {
// command line is valid
- bEnableExport = sal_True;
+ bMergeMode = aArgs.m_bMergeMode;
+ sPrj = aArgs.m_sPrj;
+ sPrjRoot = aArgs.m_sPrjRoot;
+ sInputFileName = aArgs.m_sInputFile;
+ sOutputFile = aArgs.m_sOutputFile;
+ sMergeSrc = aArgs.m_sMergeSrc;
char *pReturn = new char[ sOutputFile.getLength() + 1 ];
std::strcpy( pReturn, sOutputFile.getStr()); // #100211# - checked
return pReturn;
}
-
- // command line is not valid
- return NULL;
+ else
+ {
+ // command line is not valid
+ Export::writeUsage("xrmex","xrm/xml");
+ return NULL;
+ }
}
/*****************************************************************************/
@@ -261,9 +193,9 @@ int XRMResParser::Execute( int nToken, char * pToken )
switch ( nToken ) {
case XRM_TEXT_START:{
- rtl::OString sNewLID = GetAttribute( rToken, "id" );
- if ( sNewLID != sLID ) {
- sLID = sNewLID;
+ rtl::OString sNewGID = GetAttribute( rToken, "id" );
+ if ( sNewGID != sGID ) {
+ sGID = sNewGID;
}
bText = sal_True;
sCurrentText = "";
@@ -297,7 +229,7 @@ int XRMResParser::Execute( int nToken, char * pToken )
case DESC_TEXT_START:{
if (bDisplayName) {
- sLID = rtl::OString("dispname");
+ sGID = rtl::OString("dispname");
bText = sal_True;
sCurrentText = "";
sCurrentOpenTag = rToken;
@@ -333,7 +265,7 @@ int XRMResParser::Execute( int nToken, char * pToken )
case DESC_EXTENSION_DESCRIPTION_SRC: {
if (bExtensionDescription) {
- sLID = rtl::OString("extdesc");
+ sGID = rtl::OString("extdesc");
sResourceType = rtl::OString ( "description" );
sLangAttribute = rtl::OString ( "lang" );
sCurrentOpenTag = rToken;
@@ -498,7 +430,6 @@ void XRMResExport::WorkOnText(
{
rtl::OString sPlatform( "" );
pResData = new ResData( sPlatform, GetGID() );
- pResData->sId = GetLID();
}
rtl::OString sText(rText);
@@ -528,12 +459,8 @@ void XRMResExport::EndOfText(
sOutput += "\t0\t";
sOutput += sResourceType;
sOutput += "\t";
- sOutput += pResData->sId;
- // USE LID AS GID OR MERGE DON'T WORK
- //sOutput += pResData->sGId;
- sOutput += "\t";
- sOutput += pResData->sId;
- sOutput += "\t\t\t0\t";
+ sOutput += pResData->sGId;
+ sOutput += "\t\t\t\t0\t";
sOutput += sCur;
sOutput += "\t";
@@ -670,8 +597,7 @@ void XRMResMerge::WorkOnText(
if ( pMergeDataFile ) {
if ( !pResData ) {
rtl::OString sPlatform( "" );
- pResData = new ResData( sPlatform, GetLID() , sFilename );
- pResData->sId = GetLID();
+ pResData = new ResData( sPlatform, GetGID() , sFilename );
pResData->sResTyp = sResourceType;
}
@@ -681,8 +607,8 @@ void XRMResMerge::WorkOnText(
if ( Export::isAllowed( sLang ) &&
( pEntrys->GetText(
sContent, STRING_TYP_TEXT, sLang )) &&
- ( sContent != "-" ) && !sContent.isEmpty())
-
+ ( sContent != "-" ) && !sContent.isEmpty() &&
+ helper::isWellFormedXML( sContent ))
{
rText = sContent;
ConvertStringToXMLFormat( rText );
@@ -718,7 +644,8 @@ void XRMResMerge::EndOfText(
if (!sCur.equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("en-US")) &&
( pEntrys->GetText(
sContent, STRING_TYP_TEXT, sCur, sal_True )) &&
- ( sContent != "-" ) && !sContent.isEmpty())
+ ( sContent != "-" ) && !sContent.isEmpty() &&
+ helper::isWellFormedXML( sContent ))
{
rtl::OString sText( sContent );
rtl::OString sAdditionalLine( "\n " );