diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /l10ntools/inc | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'l10ntools/inc')
-rw-r--r-- | l10ntools/inc/cfglex.hxx | 34 | ||||
-rw-r--r-- | l10ntools/inc/cfgmerge.hxx | 180 | ||||
-rw-r--r-- | l10ntools/inc/common.hxx | 58 | ||||
-rw-r--r-- | l10ntools/inc/export.hxx | 153 | ||||
-rw-r--r-- | l10ntools/inc/helper.hxx | 48 | ||||
-rw-r--r-- | l10ntools/inc/helpmerge.hxx | 62 | ||||
-rw-r--r-- | l10ntools/inc/lngmerge.hxx | 64 | ||||
-rw-r--r-- | l10ntools/inc/po.hxx | 150 | ||||
-rw-r--r-- | l10ntools/inc/propmerge.hxx | 43 | ||||
-rw-r--r-- | l10ntools/inc/tokens.h | 100 | ||||
-rw-r--r-- | l10ntools/inc/treemerge.hxx | 47 | ||||
-rw-r--r-- | l10ntools/inc/xmlparse.hxx | 364 | ||||
-rw-r--r-- | l10ntools/inc/xrmlex.hxx | 40 | ||||
-rw-r--r-- | l10ntools/inc/xrmmerge.hxx | 137 |
14 files changed, 1480 insertions, 0 deletions
diff --git a/l10ntools/inc/cfglex.hxx b/l10ntools/inc/cfglex.hxx new file mode 100644 index 000000000..bc474a09b --- /dev/null +++ b/l10ntools/inc/cfglex.hxx @@ -0,0 +1,34 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_CFGLEX_HXX +#define INCLUDED_L10NTOOLS_INC_CFGLEX_HXX + +#include <sal/config.h> + +#include <stdio.h> + +extern "C" void workOnTokenSet( int, char* ); +extern "C" FILE * init(int, char **); + +void yyerror(char const *); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/cfgmerge.hxx b/l10ntools/inc/cfgmerge.hxx new file mode 100644 index 000000000..3f4fdb55c --- /dev/null +++ b/l10ntools/inc/cfgmerge.hxx @@ -0,0 +1,180 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_CFGMERGE_HXX +#define INCLUDED_L10NTOOLS_INC_CFGMERGE_HXX + +#include <sal/config.h> + +#include <fstream> +#include <unordered_map> +#include <memory> +#include <vector> +#include "po.hxx" + +typedef std::unordered_map<OString, OString> OStringHashMap; + + + + +class CfgStackData +{ +friend class CfgParser; +friend class CfgExport; +friend class CfgMerge; +private: + OString sTagType; + OString sIdentifier; + + OString sResTyp; + + OString sTextTag; + OString sEndTextTag; + + OStringHashMap sText; +public: + CfgStackData(const OString &rTag, const OString &rId) + : sTagType( rTag ), sIdentifier( rId ) + {} + + const OString &GetTagType() const { return sTagType; } + const OString &GetIdentifier() const { return sIdentifier; } + +}; + + + + +class CfgStack +{ +private: + std::vector< CfgStackData* > maList; + +public: + CfgStack() {} + ~CfgStack(); + + CfgStackData *Push(const OString &rTag, const OString &rId); + void Pop() + { + if (!maList.empty()) + { + delete maList.back(); + maList.pop_back(); + } + } + + CfgStackData *GetStackData(); + + OString GetAccessPath( size_t nPos ); + + size_t size() const { return maList.size(); } +}; + +/// Parser for *.xcu files +class CfgParser +{ +protected: + OString sCurrentResTyp; + OString sCurrentIsoLang; + OString sCurrentText; + + OString sLastWhitespace; + + CfgStack aStack; + CfgStackData *pStackData; + + bool bLocalize; + + virtual void WorkOnText( + OString &rText, + const OString &rLangIndex )=0; + + virtual void WorkOnResourceEnd()=0; + + virtual void Output(const OString & rOutput)=0; + +private: + void ExecuteAnalyzedToken( int nToken, char *pToken ); + void AddText( + OString &rText, + const OString &rIsoLang, + const OString &rResTyp ); + + static bool IsTokenClosed(const OString &rToken); + +public: + CfgParser(); + virtual ~CfgParser(); + + void Execute( int nToken, char * pToken ); +}; + +/// Export strings from *.xcu files +class CfgExport : public CfgParser +{ +private: + OString sPath; + PoOfstream pOutputStream; + +protected: + virtual void WorkOnText( + OString &rText, + const OString &rIsoLang + ) override; + + void WorkOnResourceEnd() override; + void Output(const OString& rOutput) override; +public: + CfgExport( + const OString &rOutputFile, + const OString &rFilePath + ); + virtual ~CfgExport() override; +}; + +/// Merge strings to *.xcu files +class CfgMerge : public CfgParser +{ +private: + std::unique_ptr<MergeDataFile> pMergeDataFile; + std::vector<OString> aLanguages; + std::unique_ptr<ResData> pResData; + + OString sFilename; + bool bEnglish; + + std::ofstream pOutputStream; + +protected: + virtual void WorkOnText(OString &rText, const OString &rLangIndex) override; + + void WorkOnResourceEnd() override; + + void Output(const OString& rOutput) override; +public: + CfgMerge( + const OString &rMergeSource, const OString &rOutputFile, + const OString &rFilename, const OString &rLanguage ); + virtual ~CfgMerge() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/common.hxx b/l10ntools/inc/common.hxx new file mode 100644 index 000000000..993d51529 --- /dev/null +++ b/l10ntools/inc/common.hxx @@ -0,0 +1,58 @@ +/* -*- 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/. + */ + +// Methods used by all of executables + +#ifndef INCLUDED_L10NTOOLS_INC_COMMON_HXX +#define INCLUDED_L10NTOOLS_INC_COMMON_HXX + +#include <sal/config.h> + +#include <iostream> +#include <rtl/string.hxx> +#include "po.hxx" + +namespace common { + +/// Result type of handleArguments() +struct HandledArgs +{ + OString m_sInputFile; + OString m_sOutputFile; + OString m_sMergeSrc; + OString m_sLanguage; + bool m_bMergeMode; + bool m_bUTF8BOM; + HandledArgs() + : m_sInputFile( OString() ) + , m_sOutputFile( OString() ) + , m_sMergeSrc( OString() ) + , m_sLanguage( OString() ) + , m_bMergeMode( false ) + , m_bUTF8BOM( false ) + {} +}; + +/// Handle command line parameters +bool handleArguments(int argc, char * argv[], HandledArgs& o_aHandledArgs); + +/// Write out a help about usage +void writeUsage(const OString& rName, const OString& rFileType); + +/// Write out a PoEntry with attention to exceptions +void writePoEntry( + const OString& rExecutable, PoOfstream& rPoStream, const OString& rSourceFile, + const OString& rResType, const OString& rGroupId, const OString& rLocalId, + const OString& rHelpText, const OString& rText, const PoEntry::TYPE eType = PoEntry::TTEXT ); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/export.hxx b/l10ntools/inc/export.hxx new file mode 100644 index 000000000..1ca56e4fe --- /dev/null +++ b/l10ntools/inc/export.hxx @@ -0,0 +1,153 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_EXPORT_HXX +#define INCLUDED_L10NTOOLS_INC_EXPORT_HXX + +#include <sal/config.h> +#include "po.hxx" + +#include <cstddef> +#include <fstream> + +#include <osl/file.hxx> +#include <osl/file.h> + +#include <iterator> +#include <set> +#include <unordered_map> +#include <memory> +#include <vector> +#include <queue> +#include <string> + +#ifdef _WIN32 +#include <direct.h> +#else +#include <unistd.h> +#endif + +#define NO_TRANSLATE_ISO "x-no-translate" + +class MergeEntrys; + +typedef std::unordered_map<OString, OString> + OStringHashMap; + +typedef std::unordered_map<OString, bool> + OStringBoolHashMap; + +#define SOURCE_LANGUAGE "en-US" +#define X_COMMENT "x-comment" + + + + +/// Purpose: holds mandatory data to export a single res +class ResData +{ +public: + ResData( const OString &rGId ); + ResData( const OString &rGId , const OString &rFilename ); + + OString sResTyp; + OString sId; + OString sGId; + OString sFilename; + + OStringHashMap sText; +}; + + + + +class ParserQueue; + + + +/// Purpose: holds information of data to merge +class MergeEntrys +{ +friend class MergeDataFile; +private: + OStringHashMap sText; + OStringBoolHashMap bTextFirst; + OStringHashMap sQuickHelpText; + OStringBoolHashMap bQuickHelpTextFirst; + OStringHashMap sTitle; + OStringBoolHashMap bTitleFirst; + +public: + MergeEntrys(){}; + void InsertEntry(const OString &rId, const OString &rText, + const OString &rQuickHelpText, const OString &rTitle) + { + + sText[ rId ] = rText; + bTextFirst[ rId ] = true; + sQuickHelpText[ rId ] = rQuickHelpText; + bQuickHelpTextFirst[ rId ] = true; + sTitle[ rId ] = rTitle; + bTitleFirst[ rId ] = true; + } + bool GetText( OString &rReturn, const OString &nLangIndex, bool bDel = false ); + + /** + Generate QTZ string with ResData + For executable which works one language and without PO files. + */ + static OString GetQTZText(const ResData& rResData, const OString& rOrigText); + +}; + + + +/// Purpose: holds information of data to merge, read from PO file +class MergeDataFile +{ + private: + std::unordered_map<OString, std::unique_ptr<MergeEntrys>> aMap; + std::set<OString> aLanguageSet; + + MergeEntrys *GetMergeData( ResData *pResData , bool bCaseSensitive = false ); + void InsertEntry(const OString &rTYP, const OString &rGID, + const OString &rLID, const OString &nLang, + const OString &rTEXT, const OString &rQHTEXT, + const OString &rTITLE, const OString &sFilename, + bool bFirstLang, bool bCaseSensitive); + public: + explicit MergeDataFile( + const OString &rFileName, const OString& rFile, + bool bCaseSensitive, bool bWithQtz = true ); + ~MergeDataFile(); + + + std::vector<OString> GetLanguages() const; + + MergeEntrys *GetMergeEntrys( ResData *pResData ); + MergeEntrys *GetMergeEntrysCaseSensitive( ResData *pResData ); + + static OString CreateKey(const OString& rTYP, const OString& rGID, + const OString& rLID, const OString& rFilename, bool bCaseSensitive); +}; + + +#endif // INCLUDED_L10NTOOLS_INC_EXPORT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/helper.hxx b/l10ntools/inc/helper.hxx new file mode 100644 index 000000000..a6eed4ff5 --- /dev/null +++ b/l10ntools/inc/helper.hxx @@ -0,0 +1,48 @@ +/* -*- 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/. + */ + +// Helper string methods + +#ifndef INCLUDED_L10NTOOLS_INC_HELPER_HXX +#define INCLUDED_L10NTOOLS_INC_HELPER_HXX + +#include <sal/config.h> +#include <sal/types.h> + +#include <libxml/parser.h> + +#include <rtl/string.hxx> +#include <rtl/strbuf.hxx> + + +namespace helper { + +/// Escape all given character in the text +OString escapeAll( + const OString& rText, const OString& rUnEscaped, const OString& rEscaped ); +/// Unescape all given character in the text +OString unEscapeAll( + const OString& rText, const OString& rEscaped, const OString& rUnEscaped ); + +/// Convert special characters to XML entity references +OString QuotHTML( const OString &rString ); +/// Convert XML entity references to single characters +OString UnQuotHTML( const OString& rString ); + +/// Check whether text is a valid XML expression +bool isWellFormedXML( OString const & text ); + +/// Convert xmlChar* to OString +OString xmlStrToOString( const xmlChar* pString ); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/helpmerge.hxx b/l10ntools/inc/helpmerge.hxx new file mode 100644 index 000000000..99c9270df --- /dev/null +++ b/l10ntools/inc/helpmerge.hxx @@ -0,0 +1,62 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_HELPMERGE_HXX +#define INCLUDED_L10NTOOLS_INC_HELPMERGE_HXX + +#include "xmlparse.hxx" +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> + +/// This Class is responsible for extracting/merging OpenOffice XML Helpfiles +class HelpParser +{ +private: + OString sHelpFile; + +#if OSL_DEBUG_LEVEL > 2 + /// Debugmethod, prints the content of the map to stdout + static void Dump(LangHashMap* rElem_in , const OString & sKey_in); + + /// Debugmethod, prints the content of the map to stdout + static void Dump(XMLHashMap* rElem_in); +#endif + +public: + HelpParser( const OString &rHelpFile ); + +/// Method append a PO file with the content of a parsed XML file +/// @PRECOND rHelpFile is valid + static bool CreatePO( const OString &rPOFile_in, const OString &sHelpFile, + XMLFile *pXmlFile, const OString &rGsi1 ); + +/// Method merges the String into XMLfile, which must point to an existing file. + bool Merge( const OString &rDestinationFile_in , + const OString& sLanguage , MergeDataFile* pMergeDataFile ); + +private: + void MergeSingleFile( XMLFile* file , MergeDataFile* pMergeDataFile , const OString& sLanguage , OString const & sPath ); + + static void ProcessHelp( LangHashMap* aLangHM , const OString& sCur , ResData *pResData , MergeDataFile* pMergeDataFile ); +}; + +#endif // INCLUDED_L10NTOOLS_INC_HELPMERGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/lngmerge.hxx b/l10ntools/inc/lngmerge.hxx new file mode 100644 index 000000000..56eaec71b --- /dev/null +++ b/l10ntools/inc/lngmerge.hxx @@ -0,0 +1,64 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_LNGMERGE_HXX +#define INCLUDED_L10NTOOLS_INC_LNGMERGE_HXX + +#include <sal/config.h> + +#include <iosfwd> +#include <vector> + +#include "common.hxx" +#include "export.hxx" + +#define LNG_OK 0x0000 +#define LNG_COULD_NOT_OPEN 0x0001 + + +/** + Class for localization of *.ulf files + + Parse *.ulf files, extract translatable strings + and merge translated strings. +*/ +class LngParser +{ +private: + std::vector<OString> mvLines; + OString sSource; + std::vector<OString> aLanguages; + + static bool isNextGroup(OString &sGroup_out, const OString &sLine_in); + static void ReadLine(const OString &rLine_in, + OStringHashMap &rText_inout); + static void WritePO(PoOfstream &aPOStream, OStringHashMap &rText_inout, + const OString &rActFileName, const OString &rID); +public: + LngParser(const OString &rLngFile); + ~LngParser(); + + void CreatePO( const OString &rPOFile ); + void Merge(const OString &rPOFile, const OString &rDestinationFile, + const OString &rLanguage ); +}; + +#endif // INCLUDED_L10NTOOLS_INC_LNGMERGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/po.hxx b/l10ntools/inc/po.hxx new file mode 100644 index 000000000..778d70fe6 --- /dev/null +++ b/l10ntools/inc/po.hxx @@ -0,0 +1,150 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_PO_HXX +#define INCLUDED_L10NTOOLS_INC_PO_HXX + +#include <fstream> +#include <memory> +#include <rtl/string.hxx> + +class PoOfstream; +class PoIfstream; +class GenPoEntry; + + +/** Interface to use po entries in localization + + PoEntry based on GenPoEntry class which stores attributes + of general po entry(see po.cxx). It makes easy to get/set + all information needed to localize one english(US) string. + It contains some basic checkings and some string + transformations between po string and string used by + localization tools. +*/ +class PoEntry +{ +private: + + std::unique_ptr<GenPoEntry> m_pGenPo; + bool m_bIsInitialized; + +public: + + friend class PoOfstream; + friend class PoIfstream; + + enum TYPE { TTEXT, TQUICKHELPTEXT, TTITLE }; + enum Exception { NOSOURCFILE, NORESTYPE, NOGROUPID, NOSTRING, WRONGHELPTEXT }; + + PoEntry(); + PoEntry( const OString& rSourceFile, const OString& rResType, const OString& rGroupId, + const OString& rLocalId, const OString& rHelpText, const OString& rText, + const TYPE eType ); + ~PoEntry(); + + PoEntry( const PoEntry& rPo ); + PoEntry& operator=( const PoEntry& rPo ); + PoEntry& operator=( PoEntry&& rPo ) noexcept; + + OString const & getSourceFile() const; ///< Get name of file from which entry is extracted + OString getGroupId() const; + OString getLocalId() const; + OString getResourceType() const; ///< Get the type of component from which entry is extracted + TYPE getType() const; ///< Get the type of entry + OString const & getMsgCtxt() const; + OString const & getMsgId() const; + OString const & getMsgStr() const; + bool isFuzzy() const; + + /// Check whether po-s belong to the same localization component + static bool IsInSameComp(const PoEntry& rPo1,const PoEntry& rPo2); + static OString genKeyId(const OString& rGenerator); + +}; + +/** Interface to work with header of po/pot files + + This class stores information which is in header of + a po file. It's main function to generate header to + template po files(pot). +*/ +class PoHeader +{ +private: + + std::unique_ptr<GenPoEntry> m_pGenPo; + bool m_bIsInitialized; + +public: + + friend class PoOfstream; + friend class PoIfstream; + + PoHeader( const OString& rExtSrc ); ///< Template Constructor + PoHeader( const OString& rExtSrc, const OString& rPoHeaderMsgStr ); + ~PoHeader(); + PoHeader(const PoHeader&) = delete; + PoHeader& operator=(const PoHeader&) = delete; +}; + +/// Interface to write po entry to files as output streams +class PoOfstream +{ +private: + + std::ofstream m_aOutPut; + bool m_bIsAfterHeader; + +public: + + enum OpenMode { TRUNC, APP }; + + PoOfstream(); + PoOfstream(const OString& rFileName, OpenMode aMode ); + ~PoOfstream(); + PoOfstream(const PoOfstream&) = delete; + PoOfstream& operator=(const PoOfstream&) = delete; + bool isOpen() const { return m_aOutPut.is_open(); } + + void open(const OString& rFileName, OpenMode aMode = TRUNC ); + void close(); + void writeHeader(const PoHeader& rHeader); + void writeEntry(const PoEntry& rPo); +}; + +/// Interface to read po entry from files as input streams +class PoIfstream +{ +private: + + std::ifstream m_aInPut; + bool m_bEof; + +public: + + class Exception final : public std::exception { }; + + PoIfstream(); + PoIfstream( const OString& rFileName ); + ~PoIfstream(); + PoIfstream(const PoIfstream&) = delete; + PoIfstream& operator=(const PoIfstream&) = delete; + bool isOpen() const { return m_aInPut.is_open(); } + bool eof() const { return m_bEof; } + + void open(const OString& rFileName); + void open(const OString& rFileName, OString& sPoHeader); + void close(); + void readEntry(PoEntry& rPo); +}; + +#endif // INCLUDED_L10NTOOLS_INC_PO_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/propmerge.hxx b/l10ntools/inc/propmerge.hxx new file mode 100644 index 000000000..7e9eb594d --- /dev/null +++ b/l10ntools/inc/propmerge.hxx @@ -0,0 +1,43 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_PROPMERGE_HXX +#define INCLUDED_L10NTOOLS_INC_PROPMERGE_HXX + +#include <rtl/string.hxx> +#include <vector> + +/** + Class for localization of *.properties files + + Parse *.properties files, extract translatable strings + and merge translated strings. +*/ + +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& rPOFile ); + void Merge( const OString &rMergeSrc, const OString &rDestinationFile ); +}; + +#endif // INCLUDED_L10NTOOLS_INC_PROPMERGE_HXX +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/tokens.h b/l10ntools/inc/tokens.h new file mode 100644 index 000000000..95370cf70 --- /dev/null +++ b/l10ntools/inc/tokens.h @@ -0,0 +1,100 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_TOKENS_H +#define INCLUDED_L10NTOOLS_INC_TOKENS_H + +/*------------------------------------------------------ */ +/*------------------------------------------------------ */ +/* Tokens for parsing src files */ +/*------------------------------------------------------ */ +/*------------------------------------------------------ */ +#define IGNOREDTOKENS 400 /* #include | #pragma | //... | ... */ +#define COMMENT 401 /*... */ +#define DEFINEDRES 402 /* Text = { */ +#define ANYTOKEN 404 /* XYZ */ +#define UNKNOWNCHAR 407 /* . */ +/*------------------------------------------------------ */ +/* prev. tokens will not be executed */ +#define FILTER_LEVEL 500 +/* following tokens will be executed */ +/*------------------------------------------------------ */ +#define CONDITION 501 /* #if... | #endif ... | ... */ +#define EMPTYLINE 502 /* */ +#define RESOURCE 503 /* Menu MID_TEST */ +#define RESOURCEEXPR 504 /* Menu ( MID_TEST + .. ) */ +#define SMALRESOURCE 505 /* PageItem { */ +#define TEXTLINE 506 /* TEXT = "hhh" */ +#define LONGTEXTLINE 507 /* TEXT = "hhh" TEST "HHH" ... */ +#define TEXT 508 /* "Something like this" */ +#define LEVELUP 509 /* { */ +#define LEVELDOWN 510 /* }; */ +#define APPFONTMAPPING 511 /* MAP_APPFONT(10,10) */ +#define ASSIGNMENT 512 /* Something = Anything */ +#define LISTASSIGNMENT 513 /* ...List [xyz]=... */ +#define LISTTEXT 514 /* < "Text" ... > */ +#define RSCDEFINE 515 /* #define MY_TEXT */ +#define RSCDEFINELEND 516 /* */ +#define PRAGMA 519 /* #pragma ... */ +#define LISTTEXT_ 521 /* { "Text" ... } */ +#define NORMDEFINE 524 /* #define ... */ +/*------------------------------------------------------ */ +/*------------------------------------------------------ */ +/* Tokens for parsing cfg files */ +/*------------------------------------------------------ */ +/*------------------------------------------------------ */ +#define CFG_TAG 501 +#define CFG_TEXT_START 505 +#define CFG_TEXT_END 506 +#define CFG_TEXTCHAR 507 +#define CFG_CLOSETAG 508 +#define CFG_UNKNOWNTAG 509 +#define CFG_TOKEN_PACKAGE 600 +#define CFG_TOKEN_COMPONENT 601 +#define CFG_TOKEN_CONFIGNAME 602 +#define CFG_TOKEN_TEMPLATE 603 +#define CFG_TOKEN_OORNAME 604 +#define CFG_TOKEN_OORVALUE 605 +#define CFG_TOKEN_NO_TRANSLATE 606 + +/*------------------------------------------------------ */ +/*------------------------------------------------------ */ +/* Tokens for parsing xrm files */ +/*------------------------------------------------------ */ +/*------------------------------------------------------ */ +#define XRM_TEXT_START 507 +#define XRM_TEXT_END 508 +#define XML_TEXTCHAR 600 + +/*------------------------------------------------------ */ +/*------------------------------------------------------ */ +/* Tokens for parsing description.xml files */ +/*------------------------------------------------------ */ +/*------------------------------------------------------ */ +#define DESC_DISPLAY_NAME_START 700 +#define DESC_DISPLAY_NAME_END 701 +#define DESC_TEXT_START 702 +#define DESC_TEXT_END 703 +#define DESC_EXTENSION_DESCRIPTION_START 704 +#define DESC_EXTENSION_DESCRIPTION_END 705 +#define DESC_EXTENSION_DESCRIPTION_SRC 706 + +#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 000000000..63791b465 --- /dev/null +++ b/l10ntools/inc/treemerge.hxx @@ -0,0 +1,47 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_TREEMERGE_HXX +#define INCLUDED_L10NTOOLS_INC_TREEMERGE_HXX + +#include <libxml/tree.h> +#include <rtl/string.hxx> +#include <vector> + +/** + Class for localization of *.tree files + + Parse *.tree files, extract translatable strings, + merge translated strings and update reference and title + of referred help files. +*/ +class TreeParser +{ +private: + xmlDocPtr m_pSource; + OString m_sLang; + bool m_bIsInitialized; + +public: + /// Parse tree file + TreeParser( const OString& rInputFile, const OString& rLang ); + ~TreeParser(); + + bool isInitialized() const { return m_bIsInitialized; } + /// Export strings + void Extract( const OString& rPOFile ); + /// Merge strings to tree file and update reference to help files(xhp) + void Merge( + const OString &rMergeSrc, const OString &rDestinationFile, + const OString &rXhpRoot ); +}; + +#endif // INCLUDED_L10NTOOLS_INC_TREEMERGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/xmlparse.hxx b/l10ntools/inc/xmlparse.hxx new file mode 100644 index 000000000..951d33b5d --- /dev/null +++ b/l10ntools/inc/xmlparse.hxx @@ -0,0 +1,364 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_XMLPARSE_HXX +#define INCLUDED_L10NTOOLS_INC_XMLPARSE_HXX + +#include <sal/config.h> + +#include <cstddef> +#include <memory> +#include <vector> + +#include <signal.h> + +#include <libxml/xmlexports.h> +#include <expat.h> + +#include <rtl/string.hxx> +#include <rtl/strbuf.hxx> +#include "export.hxx" +#include <unordered_map> + +class XMLParentNode; +class XMLElement; + +enum class XMLNodeType{ + XFILE = 0x001, + ELEMENT = 0x002, + DATA = 0x003, + COMMENT = 0x004, + DEFAULT = 0x005 +}; + +/** Holds data of Attributes + */ +class XMLAttribute +{ +private: + OString m_sName; + OString m_sValue; + +public: + /// creates an attribute + XMLAttribute( + const OString &rName, // attributes name + const OString &rValue // attributes data + ) + : m_sName( rName ), m_sValue( rValue ) {} + + const OString& GetName() const { return m_sName; } + const OString& GetValue() const { return m_sValue; } + + void setValue( const OString &rValue ){ m_sValue = rValue; } +}; + + +typedef std::vector< XMLAttribute* > XMLAttributeList; + +/** Virtual base to handle different kinds of XML nodes + */ +class XMLNode +{ +protected: + XMLNode(){} + +public: + virtual XMLNodeType GetNodeType() const = 0; + virtual ~XMLNode(){} + + XMLNode(XMLNode const &) = default; + XMLNode(XMLNode &&) = default; + XMLNode & operator =(XMLNode const &) = default; + XMLNode & operator =(XMLNode &&) = default; +}; + + +/** Virtual base to handle different kinds of child nodes + */ +class XMLChildNode : public XMLNode +{ +private: + XMLParentNode *m_pParent; + +protected: + XMLChildNode( XMLParentNode *pPar ); + XMLChildNode( const XMLChildNode& rObj); + XMLChildNode& operator=(const XMLChildNode& rObj); +public: + /// returns the parent of this node + XMLParentNode *GetParent() { return m_pParent; } +}; + +typedef std::vector< XMLChildNode* > XMLChildNodeList; + +class XMLData; + +/** Virtual base to handle different kinds of parent nodes + */ + +class XMLParentNode : public XMLChildNode +{ +private: + std::unique_ptr<XMLChildNodeList> m_pChildList; + +protected: + XMLParentNode( XMLParentNode *pPar ) + : XMLChildNode( pPar ) {} + + XMLParentNode( const XMLParentNode& ); + + XMLParentNode& operator=(const XMLParentNode& rObj); + virtual ~XMLParentNode() override; + +public: + /// returns child list of this node + XMLChildNodeList *GetChildList() { return m_pChildList.get(); } + + /// adds a new child + void AddChild( + XMLChildNode *pChild /// the new child + ); + + void RemoveAndDeleteAllChildren(); +}; + +/// Mapping numeric Language code <-> XML Element +typedef std::unordered_map<OString, XMLElement*> LangHashMap; + +/// Mapping XML Element string identifier <-> Language Map +typedef std::unordered_map<OString, LangHashMap*> XMLHashMap; + +/** Holds information of a XML file, is root node of tree + */ +class XMLFile final : public XMLParentNode +{ +public: + XMLFile( + const OString &rFileName // the file name, empty if created from memory stream + ); + XMLFile( const XMLFile& rObj ) ; + virtual ~XMLFile() override; + + void Print( XMLNode *pCur, sal_uInt16 nLevel = 0 ); + void SearchL10NElements( XMLChildNode *pCur ); + void Extract(); + + XMLHashMap* GetStrings(){ return m_pXMLStrings.get(); } + void Write( OString const &rFilename ); + void Write( std::ofstream &rStream, XMLNode *pCur = nullptr ); + + bool CheckExportStatus( XMLParentNode *pCur = nullptr ); + + XMLFile& operator=(const XMLFile& rObj); + + virtual XMLNodeType GetNodeType() const override { return XMLNodeType::XFILE; } + + /// returns file name + const OString& GetName() const { return m_sFileName; } + void SetName( const OString &rFilename ) { m_sFileName = rFilename; } + const std::vector<OString>& getOrder() const { return m_vOrder; } + +private: + + void InsertL10NElement( XMLElement* pElement); + + // DATA + OString m_sFileName; + + /// Mapping XML tag names <-> have localizable strings + std::unordered_map<OString, bool> m_aNodes_localize; + + std::unique_ptr<XMLHashMap> m_pXMLStrings; + + std::vector <OString> m_vOrder; +}; + +/// A Utility class for XML +class XMLUtil +{ +public: + /// Quot the XML characters + static OString QuotHTML( const OString& rString ); +}; + + +/** Hold information of an element node + */ +class XMLElement : public XMLParentNode +{ +private: + OString m_sElementName; + std::unique_ptr<XMLAttributeList> m_pAttributes; + +protected: + void Print(XMLNode *pCur, OStringBuffer& rBuffer, bool bRootelement) const; +public: + /// create an element node + XMLElement( + const OString &rName, // the element name + XMLParentNode *pParent // parent node of this element + ); + + virtual ~XMLElement() override; + XMLElement(const XMLElement&); + + XMLElement& operator=(const XMLElement& rObj); + virtual XMLNodeType GetNodeType() const override { return XMLNodeType::ELEMENT; } + + /// returns element name + const OString& GetName() const { return m_sElementName; } + + /// returns list of attributes of this element + XMLAttributeList *GetAttributeList() { return m_pAttributes.get(); } + + /// adds a new attribute to this element, typically used by parser + void AddAttribute( const OString &rAttribute, const OString &rValue ); + + void ChangeLanguageTag( const OString &rValue ); + + /// Return a Unicode String representation of this object + OString ToOString(); +}; + +/** Holds character data + */ +class XMLData : public XMLChildNode +{ +private: + OString m_sData; + +public: + /// create a data node + XMLData( + const OString &rData, // the initial data + XMLParentNode *pParent // the parent node of this data, typically an element node + ) + : XMLChildNode( pParent ), m_sData( rData ) {} + + // Default copy constructor and copy operator work well. + + virtual XMLNodeType GetNodeType() const override { return XMLNodeType::DATA; } + + /// returns the data + const OString& GetData() const { return m_sData; } + + /// adds new character data to the existing one + void AddData( const OString &rData ) { m_sData += rData; } +}; + +/** Holds comments + */ +class XMLComment final : public XMLChildNode +{ +private: + OString m_sComment; + +public: + /// create a comment node + XMLComment( + const OString &rComment, // the comment + XMLParentNode *pParent // the parent node of this comemnt, typically an element node + ) + : XMLChildNode( pParent ), m_sComment( rComment ) {} + + // Default copy constructor and copy operator work well. + + virtual XMLNodeType GetNodeType() const override { return XMLNodeType::COMMENT; } + + /// returns the comment + const OString& GetComment() const { return m_sComment; } +}; + +/** Holds additional file content like those for which no handler exists + */ +class XMLDefault final : public XMLChildNode +{ +private: + OString m_sDefault; + +public: + /// create a comment node + XMLDefault( + const OString &rDefault, // the comment + XMLParentNode *pParent // the parent node of this comemnt, typically an element node + ) + : XMLChildNode( pParent ), m_sDefault( rDefault ) {} + + // Default copy constructor and copy operator work well. + + virtual XMLNodeType GetNodeType() const override { return XMLNodeType::DEFAULT; } + + /// returns the comment + const OString& GetDefault() const { return m_sDefault; } +}; + +/** struct for error information, used by class SimpleXMLParser + */ +struct XMLError { + XML_Error m_eCode; ///< the error code + std::size_t m_nLine; ///< error line number + std::size_t m_nColumn; ///< error column number + OString m_sMessage; ///< readable error message +}; + +/** validating xml parser, creates a document tree with xml nodes + */ + +class SimpleXMLParser +{ +private: + XML_Parser m_aParser; + XMLError m_aErrorInformation; + + XMLParentNode *m_pCurNode; + XMLData *m_pCurData; + + + static void StartElementHandler( void *userData, const XML_Char *name, const XML_Char **atts ); + static void EndElementHandler( void *userData, const XML_Char *name ); + static void CharacterDataHandler( void *userData, const XML_Char *s, int len ); + static void CommentHandler( void *userData, const XML_Char *data ); + static void DefaultHandler( void *userData, const XML_Char *s, int len ); + + + void StartElement( const XML_Char *name, const XML_Char **atts ); + void EndElement(); + void CharacterData( const XML_Char *s, int len ); + void Comment( const XML_Char *data ); + void Default( const XML_Char *s, int len ); + +public: + /// creates a new parser + SimpleXMLParser(); + ~SimpleXMLParser(); + + /// parse a file, return false on critical errors + bool Execute( + const OString &rFileName, // the file name + XMLFile* pXMLFile // the XMLFile + ); + + /// returns an error struct + const XMLError &GetError() const { return m_aErrorInformation; } +}; + +#endif // INCLUDED_L10NTOOLS_INC_XMLPARSE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/xrmlex.hxx b/l10ntools/inc/xrmlex.hxx new file mode 100644 index 000000000..483b6dbaa --- /dev/null +++ b/l10ntools/inc/xrmlex.hxx @@ -0,0 +1,40 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_XRMLEX_HXX +#define INCLUDED_L10NTOOLS_INC_XRMLEX_HXX + +#include <sal/config.h> + +#include <stdio.h> + +extern "C" int WorkOnTokenSet( int, char* ); +extern "C" int InitXrmExport( const char * ); +extern "C" int EndXrmExport(); +extern "C" int GetError(); +extern "C" int SetError(); +extern "C" bool GetOutputFile( int argc, char* argv[]); +extern "C" FILE *GetXrmFile(); +extern "C" const char* getFilename(); + +void yyerror( const char * ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/l10ntools/inc/xrmmerge.hxx b/l10ntools/inc/xrmmerge.hxx new file mode 100644 index 000000000..fd54f113b --- /dev/null +++ b/l10ntools/inc/xrmmerge.hxx @@ -0,0 +1,137 @@ +/* -*- 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 INCLUDED_L10NTOOLS_INC_XRMMERGE_HXX +#define INCLUDED_L10NTOOLS_INC_XRMMERGE_HXX + +#include <memory> +#include <sal/config.h> + +#include <fstream> + + +/// Parser for *.xrm and description.xml files +class XRMResParser +{ +private: + OString sGID; + + bool bError; + bool bText; + + OString sCurrentOpenTag; + OString sCurrentCloseTag; + OString sCurrentText; +protected: + static OString GetAttribute( const OString &rToken, const OString &rAttribute ); + static void Error( const OString &rError ); + + virtual void Output( const OString& rOutput )=0; + virtual void WorkOnDesc( + const OString &rOpenTag, + OString &rText + )=0; + virtual void WorkOnText( + const OString &rOpenTag, + OString &rText + )=0; + virtual void EndOfText( + const OString &rOpenTag, + const OString &rCloseTag + )=0; + + const OString& GetGID() const { return sGID; } + +public: + XRMResParser(); + virtual ~XRMResParser(); + + void Execute( int nToken, char * pToken ); + + void SetError() { bError = true; } + bool GetError() const { return bError; } +}; + + +/// Export strings from *.xrm and description.xml files +class XRMResExport final : public XRMResParser +{ +private: + std::unique_ptr<ResData> pResData; + OString sPath; + PoOfstream pOutputStream; + + void WorkOnDesc( + const OString &rOpenTag, + OString &rText + ) override; + void WorkOnText( + const OString &rOpenTag, + OString &rText + ) override; + void EndOfText( + const OString &rOpenTag, + const OString &rCloseTag + ) override; + void Output( const OString& rOutput ) override; + +public: + XRMResExport( + const OString &rOutputFile, + const OString &rFilePath + ); + virtual ~XRMResExport() override; +}; + + +/// Merge strings to *.xrm and description.xml files +class XRMResMerge final : public XRMResParser +{ +private: + std::unique_ptr<MergeDataFile> pMergeDataFile; + OString sFilename; + std::unique_ptr<ResData> pResData; + std::ofstream pOutputStream; + std::vector<OString> aLanguages; + + void WorkOnDesc( + const OString &rOpenTag, + OString &rText + ) override; + void WorkOnText( + const OString &rOpenTag, + OString &rText + ) override; + void EndOfText( + const OString &rOpenTag, + const OString &rCloseTag + ) override; + void Output( const OString& rOutput ) override; +public: + XRMResMerge( + const OString &rMergeSource, + const OString &rOutputFile, + const OString &rFilename + ); + virtual ~XRMResMerge() override; +}; + +#endif // INCLUDED_L10NTOOLS_INC_XRMMERGE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |