# Author: Damyan Ivanov # Description: add support to multiple dictionary directories # stolen from upstream multidir branch --- a/configure.in +++ b/configure.in @@ -26,10 +26,13 @@ AC_ARG_ENABLE(light-version, echo "Light version will be compiled..." AC_DEFINE([USE_LIGHT],[],[enable light version])],) -AC_ARG_ENABLE(dictionary-dir, -[ --enable-dictionary-dir search for dictionaries only in /usr/local/share/bgoffice dir],[ - echo "Dictionary lookup enabled..." - AC_DEFINE([USE_USER_LOCAL],[],[dictionary lookup])],) +AC_ARG_ENABLE(dictionary-dirs, +[ --enable-dictionary-dirs=DIRS List default dictiopnary directories (Use colon to delimit entries. Default is /usr/local/share/bgoffice)], +[ + test -z "$enableval" && echo "--enable-dictionary-dirs requires an argument" && exit 1 + AC_DEFINE_UNQUOTED([DICT_DIRS],["$enableval"],[default dictionary directories]) + echo "Default dictionary directories set to $enableval" +],) AC_ARG_ENABLE(trayicon, [ --disable-trayicon disable trayicon support],[ --- a/src/defaults.h +++ b/src/defaults.h @@ -24,6 +24,7 @@ #include "config.h" +#define DICT_DIR_DELIMITER ':' #ifdef DATA_DIR_CONFIG static const char FILES_DIR[] = DATA_DIR_CONFIG; @@ -32,8 +33,8 @@ static const char FILES_DIR[] = "/usr/lo #endif -#ifdef USE_USER_LOCAL -static const char DICT_DIR[] = "/usr/local/share/bgoffice/"; +#ifdef DICT_DIRS +static const char DICT_DIR[] = DICT_DIRS; #else static const char DICT_DIR[] = DATA_DIR_CONFIG; #endif --- a/src/dictgui.cpp +++ b/src/dictgui.cpp @@ -38,7 +38,7 @@ extern Properties *cfg; extern bool lang; -DictGui::DictGui(int argc, char **argv, const char *dir) +DictGui::DictGui(int argc, char **argv, const vector dirs) #ifndef ENABLE_LIGHT_VERSION : spacer(" "), add_to_history(true), @@ -48,7 +48,8 @@ DictGui::DictGui(int argc, char **argv, #endif { - dataDir = dir; + dataDirs = dirs; + use_tray = cfg->getBool("UseTray", true); use_tray_close = cfg->getBool("UseTrayClose", false); tray_hide_os = cfg->getBool("TrayHideOnStart", false); @@ -66,7 +67,7 @@ DictGui::DictGui(int argc, char **argv, splash->set_step(0.2); #endif - dict = new TranslatorManager((char*) dataDir); + dict = new TranslatorManager(dataDirs); if (!dict->init()) { #ifndef ENABLE_LIGHT_VERSION delete splash; --- a/src/dictgui.h +++ b/src/dictgui.h @@ -38,7 +38,7 @@ class DictGui : public GbgofficeTools { public: - DictGui(int argc, char **argv, const char *dir); + DictGui(int argc, char **argv, const vector dirs); virtual ~DictGui(); void run(); @@ -58,7 +58,7 @@ public: protected: // our data directory - const char *dataDir; + vector dataDirs; // number of words in list (treeview widget) // this will not be taken from cfg, for faster access --- a/src/main.cpp +++ b/src/main.cpp @@ -27,16 +27,80 @@ #include #include #include + using namespace std; extern char *optarg; Properties *cfg; bool lang = false; +vector defaultDictDirs; +vector userDictDirs; +vector dictDirs; + +vector splitString(const string path, char delimiter) +{ + vector result; + string str = path; + size_t p; + + if (str.length()) { + do { + p = str.find(delimiter); + if (p != str.npos) { + if (p != 0) { + result.push_back(str.substr(0, p)); + } + str = str.substr(p + 1); + } else { + if (str.length()) { + result.push_back(str); + } + break; + } + } while (p != str.npos); + } + + return result; +} + +void prepareDictDirs() +{ + userDictDirs = splitString(cfg->getString("DataDir", ""), DICT_DIR_DELIMITER); +// std::cout << (cfg->getString("DataDir", DICT_DIR)) << std::endl; + defaultDictDirs = splitString( DICT_DIR, DICT_DIR_DELIMITER ); + // start with directories from user configuration + + if(userDictDirs.size() == 0) { + dictDirs = defaultDictDirs; + } else { + dictDirs = userDictDirs; + } + +/* + // then add non-duplicating default directories + defaultDictDirs = splitString( DICT_DIR, DICT_DIR_DELIMITER ); + + for( size_t i = 0; i < defaultDictDirs.size(); i++) { + string candidate = defaultDictDirs[i]; + bool found = false; + + for( size_t j = 0; j < dictDirs.size(); j++ ) { + if( candidate == dictDirs[j] ) { + found = true; + break; + } + } + + if( !found ) { + dictDirs.push_back(candidate); + } + } */ +} int main(int argc, char **argv) { - char *env, *path, *dataDir; + char *env, *path; int ch; @@ -55,13 +119,8 @@ int main(int argc, char **argv) * with some modifications */ cfg = new Properties(getenv("HOME"), CONF_FILENAME); - path = cfg->getString("DataDir", DICT_DIR); - dataDir = new char[strlen(path) + 2]; - strcpy(dataDir, path); - if ((dataDir[0] != '\0') && (dataDir[strlen(dataDir) - 1] != '/')) { - strcat(dataDir, "/"); - } - + prepareDictDirs(); + /* parsing command line options */ while ((ch = getopt_long(argc, argv, "dhl:v", longopts, NULL)) != -1) { @@ -71,7 +130,7 @@ int main(int argc, char **argv) return 0; case 'd': - cout << dataDir << endl; + cout << dictDirs[0] << endl; return 0; case 'l': @@ -125,7 +184,7 @@ int main(int argc, char **argv) Gtk::Main kit(argc, argv); // gui init - DictGui maindict(argc, argv, dataDir); + DictGui maindict(argc, argv, dictDirs); #if !defined(ENABLE_LIGHT_VERSION) && !defined(DISABLE_TRAY) if (use_tray) { @@ -140,3 +199,4 @@ int main(int argc, char **argv) return 0; } +// vi: set tabstop=8 noexpandtab softtabstop=8 shiftwidth=8 : --- a/src/properties.cpp +++ b/src/properties.cpp @@ -23,6 +23,10 @@ #include #include +#ifdef DEBUG +#include +#endif + #include "properties.h" @@ -39,21 +43,41 @@ const int Properties::MAX_LINE_LEN = 10 const int Properties::MAX_KEY_LEN = 128; -Properties::Properties(const char *path, const char *file, const char *suffix) { +Properties::Properties(const char *file_path, const char *file, const char *suffix) { + char *p; + // Allocate memory buf = new char[MAX_LINE_LEN]; sbuf = new char[MAX_LINE_LEN]; key = new char[MAX_KEY_LEN]; - fileName = new char[strlen(path) + strlen(file) + 2]; - backupFileName = new char[strlen(path) + strlen(file) + strlen(suffix) + 2]; + + + fileName = new char[strlen(file_path) + strlen(file) + 2]; + backupFileName = new char[strlen(file_path) + strlen(file) + strlen(suffix) + 2]; // Copy file names in local variables - strcpy(fileName, path); - if ((path[0] != '\0') && (path[strlen(path) - 1] != '/')) { + strcpy(fileName, file_path); + if (strlen(file)) { strcat(fileName, "/"); + strcat(fileName, file); } - strcat(fileName, file); strcpy(backupFileName, fileName); strcat(backupFileName, suffix); + + // Find directory name +#ifdef DEBUG + std::cerr << "Properties:: parsing fileName '"<< fileName <<"'\n"; +#endif + p = strrchr( fileName, '/' ); + if (p) { + directory = new char[ p - fileName + 2 ]; + strncpy( directory, fileName, p-fileName + 1); // include the slash + directory[p-fileName+1] = '\0'; // terminate + } else { + directory = "./"; + } +#ifdef DEBUG + std::cerr << "Properties:: directory is '"< #include +#ifdef DEBUG +#include +#endif + #include "database.h" #include "translator.h" @@ -111,9 +115,15 @@ Translator::~Translator() { bool Translator::init(const int type, const char *fileName, const long fixedLastWordPointer) { // Check input data if ((type != EN_BG) && (type != BG_EN)) { +#ifdef DEBUG + std::cerr << "Translator::init: failure 1\n"; +#endif return false; } if ((dictionaryType != DUAL) && (type != dictionaryType)) { +#ifdef DEBUG + std::cerr << "Translator::init: failure 2\n"; +#endif return false; } // Init database @@ -121,9 +131,19 @@ bool Translator::init(const int type, co if (type == EN_BG) { dictEnBg = new Database(); ret = dictEnBg->init(fileName, fixedLastWordPointer); +#ifdef DEBUG + if( !ret ) { + std::cerr << "Translator::init: failure 3 " << fileName << "\n"; + } +#endif } else { dictBgEn = new Database(); ret = dictBgEn->init(fileName, fixedLastWordPointer); +#ifdef DEBUG + if( !ret ) { + std::cerr << "Translator::init: failure 4 " << fileName << "\n"; + } +#endif } // Set current dictionary // If it is dual, en-bg is set as default @@ -669,3 +689,5 @@ char *Translator::extractText(const char dataBuffer[j] = '\0'; return dataBuffer; } + +// vi: set noexpandtab softtabstop=0 tabstop=8 shiftwidth=8 : --- a/src/translator_manager.cpp +++ b/src/translator_manager.cpp @@ -46,8 +46,8 @@ using namespace std; */ -TranslatorManager::TranslatorManager(char *pDataDir) { - dataDir = pDataDir; +TranslatorManager::TranslatorManager(const vector dirs) { + dataDirs = dirs; } @@ -63,17 +63,17 @@ bool TranslatorManager::init(const bool char *lang = getenv("LANG"); bool isBG = (!ignoreLANG) && (lang != NULL) && (lang[0] == 'b') && (lang[1] == 'g'); // Load Dictionaries - vector dict = findFiles(dataDir, ".dict"); + vector dict = findFiles(dataDirs, ".dict"); if (dict.size() == 0) { - cerr << "TranslatorManager::init - There is no dictionary files in directory: " << dataDir << "\n"; + cerr << "TranslatorManager::init - There are no dictionary files. Run with -d to see where are the dictionary directories\n" << std::endl; return false; } for (unsigned int i = 0; i < dict.size(); i++) { - Properties *prop = new Properties(dataDir, dict[i].c_str()); + Properties *prop = new Properties(dict[i].c_str()); struct Dictionary d; - d.file = dict[i]; + d.fileName = dict[i]; d.version = string(prop->getString("version")); - d.icon = string(dataDir) + prop->getString("icon"); + d.icon = string(prop->getDirectory()) + prop->getString("icon"); d.name = string(prop->getString(isBG ? "name.bg" : "name")); dictionaries.push_back(d); string type = string(prop->getString("type")); @@ -81,14 +81,26 @@ bool TranslatorManager::init(const bool bool isDataOk = true; if (type.compare("dual") == 0) { tr = new Translator(tr->DUAL); - isDataOk = isDataOk && tr->init(tr->EN_BG, string(string(dataDir) + prop->getString("data.en")).c_str()); - isDataOk = isDataOk && tr->init(tr->BG_EN, string(string(dataDir) + prop->getString("data.bg")).c_str()); + isDataOk = isDataOk && tr->init(tr->EN_BG, string(string(prop->getDirectory()) + prop->getString("data.en")).c_str()); +#ifdef DEBUG + cerr << 1 << isDataOk << "\n"; +#endif + isDataOk = isDataOk && tr->init(tr->BG_EN, string(string(prop->getDirectory()) + prop->getString("data.bg")).c_str()); +#ifdef DEBUG + cerr << 2 << isDataOk << "\n"; +#endif } else if (type.compare("en") == 0) { tr = new Translator(tr->EN_BG); - isDataOk = isDataOk && tr->init(tr->EN_BG, string(string(dataDir) + prop->getString("data")).c_str()); + isDataOk = isDataOk && tr->init(tr->EN_BG, string(string(prop->getDirectory()) + prop->getString("data")).c_str()); +#ifdef DEBUG + cerr << 3 << isDataOk << prop->getDirectory() << "+" << prop->getString("data") << "\n"; +#endif } else if (type.compare("bg") == 0) { tr = new Translator(tr->BG_EN); - isDataOk = isDataOk && tr->init(tr->BG_EN, string(string(dataDir) + prop->getString("data")).c_str()); + isDataOk = isDataOk && tr->init(tr->BG_EN, string(string(prop->getDirectory()) + prop->getString("data")).c_str()); +#ifdef DEBUG + cerr << 4 << isDataOk << "\n"; +#endif } else { cerr << "TranslatorManager::init - Wrong description file: " << dict[i] << "\n"; return false; @@ -104,11 +116,11 @@ bool TranslatorManager::init(const bool currentTranslator = translators[0]; // Load TestDictionaries - vector test = findFiles(dataDir, ".test"); + vector test = findFiles(dataDirs, ".test"); for (unsigned int i = 0; i < test.size(); i++) { - Properties *prop = new Properties(dataDir, test[i].c_str()); + Properties *prop = new Properties(test[i].c_str()); struct TestDictionary td; - td.file = test[i]; + td.fileName = test[i]; td.name = string(prop->getString(isBG ? "name.bg" : "name")); testDictionaries.push_back(td); delete prop; @@ -152,22 +164,22 @@ TestDictionary TranslatorManager::getTes Translator *TranslatorManager::getTestDictionaryObject(const int index, const int level) { - Properties *prop = new Properties(dataDir, testDictionaries[index].file.c_str()); + Properties *prop = new Properties(testDictionaries[index].fileName.c_str()); string type = string(prop->getString("type")); Translator *tr; bool isDataOk = true; if (type.compare("en") == 0) { tr = new Translator(tr->EN_BG); - isDataOk = isDataOk && tr->init(tr->EN_BG, string(string(dataDir) + prop->getString("data")).c_str()); + isDataOk = isDataOk && tr->init(tr->EN_BG, string(string(prop->getDirectory()) + prop->getString("data")).c_str()); } else if (type.compare("bg") == 0) { tr = new Translator(tr->BG_EN); - isDataOk = isDataOk && tr->init(tr->BG_EN, string(string(dataDir) + prop->getString("data")).c_str()); + isDataOk = isDataOk && tr->init(tr->BG_EN, string(string(prop->getDirectory()) + prop->getString("data")).c_str()); } else { - cerr << "TranslatorManager::getTestDictionaryObject - Wrong description file: " << testDictionaries[index].file << "\n"; + cerr << "TranslatorManager::getTestDictionaryObject - Wrong description file: " << testDictionaries[index].fileName << "\n"; return false; } if (!isDataOk) { - cerr << "TranslatorManager::getTestDictionaryObject - Problem initialazing dictionary: " << testDictionaries[index].file << "\n"; + cerr << "TranslatorManager::getTestDictionaryObject - Problem initialazing dictionary: " << testDictionaries[index].fileName << "\n"; return false; } char c[16]; @@ -309,30 +321,37 @@ void TranslatorManager::setAdvancedSearc } } - -vector TranslatorManager::findFiles(const char *dir, const char *extension) { +vector TranslatorManager::findFiles(const vector dirs, const char *extension) { int l = strlen(extension); vector result; DIR *d; struct dirent *e; + size_t i; + const char *i_dir; - if ((d = opendir(dir)) == NULL) { - cerr << "TranslatorManager::findFiles - Unable to open directory: " << dir << "\n"; - return result; - } + for (i = 0; i < dirs.size(); i++) { + i_dir = dirs[i].c_str(); - while ((e = readdir(d)) != NULL) { - string fn(e->d_name); - size_t p = fn.rfind(extension); - if ((p != string::npos) && (p == fn.size() - l)) { - result.push_back(fn); + if ((d = opendir(i_dir)) == NULL) { + cerr << "TranslatorManager::findFiles - Unable to open directory: " << i_dir << "\n"; + continue; } - } - if (closedir(d) != 0) { - cerr << "TranslatorManager::findFiles - Unable to close directory: " << dir << "\n"; + while ((e = readdir(d)) != NULL) { + string fn(e->d_name); + size_t p = fn.rfind(extension); + if ((p != string::npos) && (p == fn.size() - l)) { + result.push_back(string(i_dir) + '/' + string(fn)); + } + } + + if (closedir(d) != 0) { + cerr << "TranslatorManager::findFiles - Unable to close directory: " << i_dir << "\n"; + } } sort(result.begin(), result.end()); return result; } + +// vi: set noexpandtab softtabstop=0 tabstop=8 shiftwidth=8 : --- a/src/translator_manager.h +++ b/src/translator_manager.h @@ -36,14 +36,14 @@ using namespace std; struct Dictionary { - string file; + string fileName; string name; string icon; string version; }; struct TestDictionary { - string file; + string fileName; string name; }; @@ -51,7 +51,7 @@ struct TestDictionary { class TranslatorManager { public: - TranslatorManager(char *pDataDir); + TranslatorManager(const vector dataDirs); ~TranslatorManager(); bool init(const bool ignoreLANG = false); @@ -92,7 +92,7 @@ public: private: - char *dataDir; + vector dataDirs; vector dictionaries; vector testDictionaries; @@ -101,8 +101,10 @@ private: Translator *currentTranslator; int currentDict; - vector findFiles(const char *dir, const char *extension); + vector findFiles(const vector dirs, const char *extension); }; #endif + +// vi: set noexpandtab softtabstop=0 tabstop=8 shiftwidth=8 :