# Author: Damyan Ivanov <dmn@debian.org>
# 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<string> 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<string> dirs);
 	virtual ~DictGui();
 
 	void run();
@@ -58,7 +58,7 @@ public:
 
 protected:
 	// our data directory
-	const char *dataDir;
+	vector<string> 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 <cstring>
 #include <getopt.h>
 #include <gtkmm/main.h>
+
 using namespace std;
 
 extern char *optarg;
 Properties *cfg;
 bool lang = false;
+vector<string> defaultDictDirs;
+vector<string> userDictDirs;
+vector<string> dictDirs;
+
+vector<string> splitString(const string path, char delimiter)
+{
+	vector<string> 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 <stdio.h>
 #include <string.h>
 
+#ifdef DEBUG
+#include <iostream>
+#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 '"<<directory<<"'\n";
+#endif
 }
 
 
@@ -63,6 +87,7 @@ Properties::~Properties() {
 	delete [] key;
 	delete [] fileName;
 	delete [] backupFileName;
+	delete [] directory;
 }
 
 
@@ -186,3 +211,5 @@ bool Properties::setInt(const char *prop
 bool Properties::setBool(const char *property, const bool value) {
 	return setString(property, (value ? "true" : "false"));
 }
+
+// vi: set noexpandtab softtabstop=0 tabstop=8 shiftwidth=8 :
--- a/src/properties.h
+++ b/src/properties.h
@@ -30,7 +30,7 @@
 class Properties {
 
 public:
-	Properties(const char *path, const char *file, const char *suffix = "~");
+	Properties(const char *file_path, const char *file = "", const char *suffix = "~");
 	~Properties();
 	char *getString(const char *property, const char *defaultValue = "");
 	int getInt(const char *property, const int defaultValue = 0);
@@ -39,6 +39,7 @@ public:
 	bool setString(const char *property, const char *value);
 	bool setInt(const char *property, const int value);
 	bool setBool(const char *property, const bool value);
+	char *getDirectory() { return directory; };
 
 private:
 	static const int MAX_LINE_LEN;
@@ -48,7 +49,10 @@ private:
 	char *key;
 	char *fileName;
 	char *backupFileName;
+	char *directory;
 
 };
 
 #endif
+
+// vi: set noexpandtab softtabstop=0 tabstop=8 shiftwidth=8 :
--- a/src/translator.cpp
+++ b/src/translator.cpp
@@ -23,6 +23,10 @@
 #include <string.h>
 #include <ctype.h>
 
+#ifdef DEBUG
+#include <iostream.h>
+#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<string> 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<string> dict = findFiles(dataDir, ".dict");
+	vector<string> 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<string> test = findFiles(dataDir, ".test");
+	vector<string> 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<string> TranslatorManager::findFiles(const char *dir, const char *extension) {
+vector<string> TranslatorManager::findFiles(const vector<string> dirs, const char *extension) {
 	int l = strlen(extension);
 	vector<string> 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<string> dataDirs);
 	~TranslatorManager();
 	bool init(const bool ignoreLANG = false);
 
@@ -92,7 +92,7 @@ public:
 
 
 private:
-	char *dataDir;
+	vector<string> dataDirs;
 
 	vector<Dictionary> dictionaries;
 	vector<TestDictionary> testDictionaries;
@@ -101,8 +101,10 @@ private:
 	Translator *currentTranslator;
 	int currentDict;
 
-	vector<string> findFiles(const char *dir, const char *extension);
+	vector<string> findFiles(const vector<string> dirs, const char *extension);
 
 };
 
 #endif
+
+// vi: set noexpandtab softtabstop=0 tabstop=8 shiftwidth=8 :
