summaryrefslogtreecommitdiff
path: root/l10ntools/source/gL10nMemDB.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'l10ntools/source/gL10nMemDB.cxx')
-rw-r--r--l10ntools/source/gL10nMemDB.cxx463
1 files changed, 463 insertions, 0 deletions
diff --git a/l10ntools/source/gL10nMemDB.cxx b/l10ntools/source/gL10nMemDB.cxx
new file mode 100644
index 000000000000..2055b0e5e318
--- /dev/null
+++ b/l10ntools/source/gL10nMemDB.cxx
@@ -0,0 +1,463 @@
+/* -*- 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 "gL10nMem.hxx"
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+
+/*****************************************************************************
+ ********************** G L 1 0 N M E M D B . C X X **********************
+ *****************************************************************************
+ * This is the translation memory that links between the converts (from source
+ * files) and to the language files. The memory contains the actual text info
+ ***********************d******************************************************/
+
+
+
+/******************* G L O B A L D E F I N I T I O N *******************/
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_lang_entry::l10nMem_lang_entry(const std::string& sMsgStr, bool bFuzzy)
+ :
+ msMsgStr(sMsgStr),
+ mbFuzzy(bFuzzy)
+{
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_lang_entry::~l10nMem_lang_entry()
+{
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_enus_entry::l10nMem_enus_entry(const std::string& sKey,
+ const std::string& sMsgId,
+ int iLineNo,
+ int iFileInx,
+ int iLangSize,
+ l10nMem::ENTRY_STATE eState)
+ :
+ msMsgId(sMsgId),
+ meState(eState),
+ miFileInx(iFileInx),
+ miLineNo(iLineNo)
+{
+ int i;
+
+ // add dummy language entries
+ for (i = 0; i < iLangSize; ++i)
+ mcLangText.push_back(l10nMem_lang_entry("", false));
+
+ // convert key to upper case
+ msKey = sKey;
+ l10nMem_db::keyToUpper(msKey);
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_enus_entry::~l10nMem_enus_entry()
+{
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_file_entry::l10nMem_file_entry(const std::string& sFileName, int iStart)
+ :
+ msFileName(sFileName),
+ miStart(iStart),
+ miEnd(iStart)
+{
+ // Store fileName without relative path
+ int i = msFileName.rfind("/");
+ if (i == (int)std::string::npos)
+ msPureName = msFileName;
+ else
+ msPureName = msFileName.substr(i+1);
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_file_entry::~l10nMem_file_entry()
+{
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_lang_list_entry::l10nMem_lang_list_entry(const std::string& sName)
+ :
+ msName(sName),
+ mbChanged(false)
+{
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_lang_list_entry::~l10nMem_lang_list_entry()
+{
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_db::l10nMem_db()
+ :
+ miCurFileInx(0),
+ miCurLangInx(0),
+ miCurENUSinx(0),
+ mbNeedWrite(false),
+ mbConvertMode(false),
+ mbStrictMode(false)
+{
+ mcFileList.push_back(l10nMem_file_entry("-genLang-", 0));
+ mcLangList.push_back(l10nMem_lang_list_entry("-genLang-"));
+ mcENUSlist.push_back(l10nMem_enus_entry("-genLang-", "-genLang-", 0, 0, 0, l10nMem::ENTRY_DELETED));
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+l10nMem_db::~l10nMem_db()
+{
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+void l10nMem_db::loadENUSkey(int iLineNo,
+ const std::string& sSourceFile,
+ const std::string& sKey,
+ const std::string& sMsgId)
+{
+ // add it to vector and update file pointer
+ addKey(iLineNo, sSourceFile, sKey, sMsgId, l10nMem::ENTRY_DELETED);
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+void l10nMem_db::setLanguage(const std::string& sLanguage,
+ bool bCreate)
+{
+ int i, iSize;
+
+ // regular load or convert of old po files
+ miCurFileInx = 0;
+
+ // With no languages selected only en-US is generated
+ if (!sLanguage.size())
+ {
+ miCurLangInx = 0;
+ return;
+ }
+
+ // en-US is loaded as master and cannot be loaded again
+ if (sLanguage == "en-US")
+ throw l10nMem::showError("en-US is loaded automatically");
+
+ // check if language is already loaded
+ iSize = mcLangList.size();
+ for (miCurLangInx = 0; miCurLangInx < iSize && mcLangList[miCurLangInx].msName != sLanguage; ++miCurLangInx) ;
+ if (miCurLangInx < iSize)
+ {
+ if (bCreate)
+ throw l10nMem::showError("loading " + sLanguage + " twice");
+ return;
+ }
+
+ // language does not exist in db
+ if (!bCreate)
+ throw l10nMem::showError("language " + sLanguage + " not loaded");
+
+ // create language
+ mcLangList.push_back(sLanguage);
+
+ // add language to all ENUS entries
+ iSize = mcENUSlist.size();
+ for (i = 0; i < iSize; ++i)
+ mcENUSlist[i].mcLangText.push_back(l10nMem_lang_entry("", false));
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+void l10nMem_db::setConvert(bool bConvert,
+ bool bStrict)
+{
+ // regular load or convert of old po files
+ mbConvertMode = bConvert;
+ mbStrictMode = bStrict;
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+bool l10nMem_db::findFileName(const std::string& sSourceFile)
+{
+ int iSize = mcFileList.size();
+
+ // Check this or next file
+ if (mcFileList[miCurFileInx].msFileName == sSourceFile || mcFileList[miCurFileInx].msPureName == sSourceFile)
+ return true;
+ if (++miCurFileInx < iSize && mcFileList[miCurFileInx].msFileName == sSourceFile)
+ return true;
+
+ for (miCurFileInx = 1;
+ miCurFileInx < iSize && mcFileList[miCurFileInx].msFileName != sSourceFile &&
+ mcFileList[miCurFileInx].msPureName != sSourceFile;
+ ++miCurFileInx) ;
+ if (miCurFileInx == iSize)
+ {
+ miCurFileInx = 0;
+ return false;
+ }
+ else
+ return true;
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+void l10nMem_db::loadLangKey(int iLineNo,
+ const std::string& sSourceFile,
+ const std::string& sKey,
+ const std::string& sMsgId,
+ const std::string& sMsgStr,
+ bool bFuzzy)
+{
+ if (!locateKey(iLineNo, sSourceFile, sKey, sMsgId, true))
+ throw l10nMem::showError(".po file contains unknown filename: " + sSourceFile + " or key: " + sKey);
+
+ l10nMem_lang_entry& xCur = mcENUSlist[miCurENUSinx].mcLangText[miCurLangInx];
+ xCur.msMsgStr = sMsgStr;
+ xCur.mbFuzzy = bFuzzy;
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+void l10nMem_db::reorganize(bool bConvert)
+{
+ int iE, iEsize = mcENUSlist.size();
+ int iD, iDsize;
+ std::vector<int> listDel, listAdd;
+
+
+ // Check number of changes
+ for (iE = 1; iE < iEsize; ++iE)
+ {
+ l10nMem_enus_entry& cur = mcENUSlist[iE];
+ if (cur.meState == l10nMem::ENTRY_ADDED)
+ listAdd.push_back(iE);
+ if (cur.meState == l10nMem::ENTRY_DELETED)
+ {
+ if (bConvert)
+ cur.meState = l10nMem::ENTRY_NORMAL;
+ else
+ listDel.push_back(iE);
+ }
+ }
+
+ if (!listDel.size() || !listAdd.size())
+ return;
+
+ // loop through added text and see if key match deleted text
+ iEsize = listAdd.size();
+ iDsize = listDel.size();
+ for (iE = 0; iE < iEsize; ++iE)
+ {
+ l10nMem_enus_entry& curAdd = mcENUSlist[listAdd[iE]];
+ for (iD = 0; iD < iDsize; ++iD)
+ {
+ l10nMem_enus_entry& curE = mcENUSlist[listDel[iD]];
+
+ if (curE.miFileInx != curAdd.miFileInx)
+ continue;
+ if (curE.msKey == curAdd.msKey)
+ break;
+ if (curE.msMsgId == curAdd.msMsgId)
+ break;
+ }
+ if (iD == iDsize)
+ continue;
+
+ // Update deleted entry (original), because lang is connected here
+ l10nMem_enus_entry& curDel = mcENUSlist[listDel[iD]];
+ curDel.msMsgId = curAdd.msMsgId;
+ curDel.msKey = curAdd.msKey;
+ curDel.meState = l10nMem::ENTRY_CHANGED;
+ curAdd.meState = l10nMem::ENTRY_DELETED;
+ }
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+bool l10nMem_db::locateKey(int iLineNo,
+ const std::string& sSourceFile,
+ const std::string& sKey,
+ const std::string& sMsgId,
+ bool bThrow)
+{
+ std::string sUpperKey(sKey);
+ int i, iSize = sUpperKey.size();
+ char ch;
+
+ // Position file pointer
+ if (!findFileName(sSourceFile))
+ return false;
+
+ // convert key to upper case
+ for (i = 0; i < iSize; ++i)
+ {
+ ch = sUpperKey[i];
+ if (ch == ' ' || ch == '*' || ch == '+' || ch == '%')
+ sUpperKey[i] = '_';
+ else
+ sUpperKey[i] = toupper(sUpperKey[i]);
+ }
+
+ // Fast check, to see if next key is the one (normal with load and source without change)
+ if (++miCurENUSinx < (int)mcENUSlist.size())
+ {
+ l10nMem_enus_entry& nowEntry = mcENUSlist[miCurENUSinx];
+ if (nowEntry.msMsgId == sMsgId && nowEntry.msKey == sUpperKey)
+ return true;
+ }
+
+ // Start from beginning of file and to end
+ l10nMem_file_entry& cCur = mcFileList[miCurFileInx];
+
+ // Find match with key and text
+ for (miCurENUSinx = cCur.miStart; miCurENUSinx <= cCur.miEnd; ++miCurENUSinx)
+ {
+ l10nMem_enus_entry& cEntry = mcENUSlist[miCurENUSinx];
+ if (cEntry.msMsgId == sMsgId && cEntry.msKey == sUpperKey)
+ return true;
+ }
+
+ if (bThrow)
+ throw l10nMem::showError("cannot find key(" + sUpperKey +") with text(" + sMsgId + ")", iLineNo);
+ return false;
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+void l10nMem_db::addKey(int iLineNo,
+ const std::string& sSourceFile,
+ const std::string& sKey,
+ const std::string& sMsgId,
+ l10nMem::ENTRY_STATE eStat)
+{
+ // check file
+ if (!findFileName(sSourceFile))
+ {
+ // prepare for new entry
+ miCurENUSinx = mcENUSlist.size();
+ miCurFileInx = mcFileList.size();
+
+ // Create file
+ mcFileList.push_back(l10nMem_file_entry(sSourceFile, miCurENUSinx));
+
+ // and add entry at the back (no problem since it is a new file)
+ mcENUSlist.push_back(l10nMem_enus_entry(sKey, sMsgId, iLineNo, miCurFileInx,
+ mcLangList.size(), eStat));
+ mcFileList[miCurFileInx].miEnd = miCurENUSinx;
+ }
+ else
+ {
+ int iFsize = mcFileList.size();
+ l10nMem_file_entry& curF = mcFileList[miCurFileInx];
+ std::vector<l10nMem_enus_entry>::iterator it = mcENUSlist.begin();
+
+ // file is registred, so we need to add the entry at the end of the file range
+ curF.miEnd++;
+ miCurENUSinx = curF.miEnd;
+ mcENUSlist.insert(it + curF.miEnd,
+ l10nMem_enus_entry(sKey, sMsgId, iLineNo, miCurFileInx,
+ mcLangList.size(), eStat));
+ for (int i = miCurFileInx+1; i < iFsize; ++i)
+ {
+ l10nMem_file_entry& curF2 = mcFileList[i];
+ if (curF2.miStart >= curF.miEnd)
+ curF2.miStart++;
+ if (curF2.miEnd >= curF.miEnd)
+ curF2.miEnd++;
+ }
+ }
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+int l10nMem_db::prepareMerge()
+{
+ miCurLangInx = 0;
+ return mcLangList.size();
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+bool l10nMem_db::getMergeLang(std::string& sLang,
+ std::string& sMsgStr)
+{
+ miCurLangInx++;
+ if (miCurLangInx >= (int)mcLangList.size())
+ return false;
+
+ // update pointers
+ sLang = mcLangList[miCurLangInx].msName;
+ if (!sMsgStr.size())
+ sMsgStr = "NOT TRANSLATED";
+ else
+ sMsgStr = mcENUSlist[miCurENUSinx].mcLangText[miCurLangInx].msMsgStr;
+ return true;
+}
+
+
+
+/********************** I M P L E M E N T A T I O N **********************/
+void l10nMem_db::keyToUpper(std::string& sKey)
+{
+ int i, iSize;
+
+ iSize = sKey.size();
+ for (i = 0; i < iSize; ++i)
+ {
+ char ch = sKey[i];
+ if (ch == ' ' || ch == '*' || ch == '+' || ch == '%')
+ sKey[i] = '_';
+ else
+ sKey[i] = toupper(ch);
+ }
+}