1 /*
2  * Copyright 2011 kubtek <kubtek@mail.com>
3  *
4  * This file is part of StarDict.
5  *
6  * StarDict is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * StarDict is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with StarDict.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23 
24 #include <glib.h>
25 #include <glib/gstdio.h>
26 #include <glib/gi18n.h>
27 #include <cstring>
28 #include <cstdlib>
29 
30 #include "class_factory.h"
31 #include "lib/utils.h"
32 #include "inifile.h"
33 #include "libcommon.h"
34 
35 #include "conf.h"
36 
37 #ifdef CONFIG_GPE
38 const int DEFAULT_WINDOW_WIDTH=238;
39 const int DEFAULT_WINDOW_HEIGHT=279;
40 const int DEFAULT_HPANED_POS=79;
41 #else
42 const int DEFAULT_WINDOW_WIDTH=600;
43 const int DEFAULT_WINDOW_HEIGHT=390;
44 const int DEFAULT_HPANED_POS=120;
45 #endif
46 
47 std::auto_ptr<AppConf> conf;
48 std::auto_ptr<AppDirs> conf_dirs;
49 
50 #ifdef _WIN32
51 HINSTANCE stardictexe_hInstance;
52 
53 /* Get full path to the directory containing StarDict executable file
54 	- application directory. */
get_application_dir(void)55 std::string get_application_dir(void)
56 {
57 	TCHAR path_win[MAX_PATH];
58 	DWORD dwRes = GetModuleFileName(NULL, path_win, MAX_PATH);
59 	if(dwRes == 0 || dwRes == MAX_PATH)
60 		exit(EXIT_FAILURE);
61 	std::string path_utf8;
62 	if(windows_to_utf8(path_win, path_utf8)) {
63 		glib::CharStr buf(g_path_get_dirname(path_utf8.c_str()));
64 		return get_impl(buf);
65 	} else
66 		exit(EXIT_FAILURE);
67 }
68 
69 /* transform a path relative to the application dir to an absolute path.
70 Do nothing if the path is already an absolute path.
71 Return value: EXIT_FAILURE or EXIT_SUCCESS. */
abs_path_to_app_dir(const std::string & path,std::string & abs_path)72 int abs_path_to_app_dir(const std::string& path, std::string& abs_path)
73 {
74 	abs_path.clear();
75 	std::string path_norm;
76 	if(norm_path_win(path, path_norm))
77 		return EXIT_FAILURE;
78 	if(!is_valid_path_win(path_norm))
79 		return EXIT_FAILURE;
80 	if(is_absolute_path_win(path_norm)) {
81 		abs_path = path_norm;
82 		return EXIT_SUCCESS;
83 	}
84 	std::string path_abs(build_path(get_application_dir(), path_norm));
85 	std::string path_abs_norm;
86 	if(norm_path_win(path_abs, path_abs_norm))
87 		return EXIT_FAILURE;
88 	abs_path = path_abs_norm;
89 	return EXIT_SUCCESS;
90 }
91 
92 #endif // #ifdef _WIN32
93 
94 //---------------------------------------------------------------------------------
AppConf()95 AppConf::AppConf() :
96 	cf(static_cast<config_file *>(PlatformFactory::create_class_by_name("config_file")))
97 {
98 	add_entry("/apps/stardict/preferences/main_window/maximized", false);
99 #ifdef _WIN32
100 	add_entry("/apps/stardict/preferences/dictionary/use_custom_font", get_win32_use_custom_font());
101 #else
102 #ifdef CONFIG_DARWIN
103 	add_entry("/apps/stardict/preferences/dictionary/use_custom_font", get_darwin_use_custom_font());
104 #else
105 	add_entry("/apps/stardict/preferences/dictionary/use_custom_font", false);
106 #endif
107 #endif
108 #if defined(_WIN32) || defined(CONFIG_DARWIN)
109 	add_entry("/apps/stardict/preferences/network/enable_netdict", true);
110 #else
111 	add_entry("/apps/stardict/preferences/network/enable_netdict", false);
112 #endif
113 	// Default stardictd server.
114 	add_entry("/apps/stardict/preferences/network/server", std::string(_("dict.stardict.org")));
115 	add_entry("/apps/stardict/preferences/network/port", 2628);
116 	add_entry("/apps/stardict/preferences/network/user", std::string());
117 	add_entry("/apps/stardict/preferences/network/md5passwd", std::string());
118 	// may store relative path
119 	add_entry("/apps/stardict/preferences/main_window/skin", std::string());
120 	add_entry("/apps/stardict/preferences/main_window/hide_on_startup", false);
121 	add_entry("/apps/stardict/preferences/main_window/search_while_typing", true);
122 	add_entry("/apps/stardict/preferences/main_window/word_change_timeout", 300);
123 	add_entry("/apps/stardict/preferences/main_window/showfirst_when_notfound", true);
124 	add_entry("/apps/stardict/preferences/translate/engine", 0);
125 	add_entry("/apps/stardict/preferences/translate/fromlang", 0);
126 	add_entry("/apps/stardict/preferences/translate/tolang", 0);
127 	add_entry("/apps/stardict/preferences/dictionary/enable_sound_event", true);
128 	add_entry("/apps/stardict/preferences/dictionary/use_tts_program", false);
129 	add_entry("/apps/stardict/preferences/dictionary/tts_program_cmdline", std::string()); // absolute command
130 	add_entry("/apps/stardict/preferences/main_window/hide_list", false);
131 	add_entry("/apps/stardict/preferences/dictionary/scan_selection", true);
132 	add_entry("/apps/stardict/preferences/dictionary/bookname_style", 0);
133 	add_entry("/apps/stardict/preferences/dictionary/markup_search_word", false);
134 #ifdef _WIN32
135 	add_entry("/apps/stardict/preferences/dictionary/scan_clipboard", false);
136 #endif
137 #ifndef CONFIG_DARWIN
138 	add_entry("/apps/stardict/preferences/dictionary/use_scan_hotkey", true);
139 	add_entry("/apps/stardict/preferences/dictionary/use_mainwindow_hotkey", true);
140 	add_entry("/apps/stardict/preferences/dictionary/scan_hotkey", std::string("<Ctrl><Alt>x"));
141  	add_entry("/apps/stardict/preferences/dictionary/mainwindow_hotkey", std::string("<Ctrl><Alt>z"));
142 #endif
143 	add_entry("/apps/stardict/preferences/notification_area_icon/middle_click_action", int(namclaQueryFloatWindow));
144 	add_entry("/apps/stardict/preferences/dictionary/only_scan_while_modifier_key", false);
145 	add_entry("/apps/stardict/preferences/dictionary/hide_floatwin_when_modifier_key_released", true);
146 	add_entry("/apps/stardict/preferences/floating_window/pronounce_when_popup", false);
147 	add_entry("/apps/stardict/preferences/floating_window/lock", false);
148 	add_entry("/apps/stardict/preferences/floating_window/show_if_not_found", true);
149 	add_entry("/apps/stardict/preferences/floating_window/use_custom_bg", false);
150 #if GTK_MAJOR_VERSION >= 3
151 	add_entry("/apps/stardict/preferences/floating_window/bg_red", 1.0);
152 	add_entry("/apps/stardict/preferences/floating_window/bg_green", 1.0);
153 	add_entry("/apps/stardict/preferences/floating_window/bg_blue", (51200/(double)65535));
154 #else
155 	add_entry("/apps/stardict/preferences/floating_window/bg_red", 65535);
156 	add_entry("/apps/stardict/preferences/floating_window/bg_green", 65535);
157 	add_entry("/apps/stardict/preferences/floating_window/bg_blue", 51200);
158 #endif
159 	add_entry("/apps/stardict/preferences/floating_window/transparent", 0);
160 
161 	add_entry("/apps/stardict/preferences/floating_window/lock_x", 0);
162 	add_entry("/apps/stardict/preferences/floating_window/lock_y", 0);
163 	add_entry("/apps/stardict/preferences/dictionary/scan_modifier_key", 0);
164 	add_entry("/apps/stardict/preferences/main_window/transparent", 0);
165 	add_entry("/apps/stardict/preferences/main_window/hpaned_pos", DEFAULT_HPANED_POS);
166 	add_entry("/apps/stardict/preferences/main_window/window_width", DEFAULT_WINDOW_WIDTH);
167 	add_entry("/apps/stardict/preferences/main_window/window_height", DEFAULT_WINDOW_HEIGHT);
168 	add_entry("/apps/stardict/preferences/floating_window/max_window_width", DEFAULT_MAX_FLOATWIN_WIDTH);
169 	add_entry("/apps/stardict/preferences/floating_window/max_window_height", DEFAULT_MAX_FLOATWIN_HEIGHT);
170 
171 #ifdef _WIN32
172 	add_entry("/apps/stardict/preferences/dictionary/custom_font", get_win32_custom_font());
173 #else
174 #ifdef CONFIG_DARWIN
175 	add_entry("/apps/stardict/preferences/dictionary/custom_font", get_darwin_custom_font());
176 #else
177 	add_entry("/apps/stardict/preferences/dictionary/custom_font", std::string());
178 #endif
179 #endif
180 
181 	add_entry("/apps/stardict/preferences/dictionary/create_cache_file", true);
182 	add_entry("/apps/stardict/preferences/dictionary/enable_collation", false);
183 	add_entry("/apps/stardict/preferences/dictionary/collate_function", 0);
184 	add_entry("/apps/stardict/preferences/dictionary/do_not_load_bad_dict", true);
185 	add_entry("/apps/stardict/preferences/dictionary/add_new_dict_in_active_group", true);
186 	add_entry("/apps/stardict/preferences/dictionary/add_new_plugin_in_active_group", true);
187 
188 #if defined(_WIN32)
189 	add_entry("/apps/stardict/preferences/dictionary/sound_play_command", std::string("play")); // absolute command
190 	add_entry("/apps/stardict/preferences/dictionary/always_use_sound_play_command", false);
191 #else
192 	add_entry("/apps/stardict/preferences/dictionary/sound_play_command", std::string("play")); // absolute command
193 #endif
194 	add_entry("/apps/stardict/preferences/dictionary/video_play_command", std::string("play")); // absolute command
195 #if defined(CONFIG_GPE)
196 	add_entry("/apps/stardict/preferences/dictionary/url_open_command", std::string("gpe-mini-browser"));
197 #else
198 	add_entry("/apps/stardict/preferences/dictionary/url_open_command", std::string("xdg-open")); // absolute command
199 #endif
200 #if defined(_WIN32) || defined(CONFIG_GNOME)
201 	add_entry("/apps/stardict/preferences/dictionary/always_use_open_url_command", false);
202 #endif
203 	{
204 		std::list<std::string> pathlist;
205 #ifdef _WIN32
206 		pathlist.push_back("C:\\Program Files\\WyabdcRealPeopleTTS");
207 		pathlist.push_back("C:\\Program Files\\OtdRealPeopleTTS");
208 		pathlist.push_back("WyabdcRealPeopleTTS");
209 		pathlist.push_back("OtdRealPeopleTTS");
210 		// stores absolute and relative paths
211 		add_entry("/apps/stardict/preferences/dictionary/tts_path", pathlist);
212 #else
213 		pathlist.push_back("/usr/local/share/WyabdcRealPeopleTTS");
214 		pathlist.push_back("/usr/local/share/OtdRealPeopleTTS");
215 		add_entry("/apps/stardict/preferences/dictionary/tts_path", pathlist);
216 #endif
217 	}
218 	// may store relative path
219 	add_entry("/apps/stardict/preferences/dictionary/history", get_default_history_filename());
220 	add_entry("/apps/stardict/preferences/dictionary/only_export_word", true);
221 	// may store relative path
222 	add_entry("/apps/stardict/preferences/dictionary/export_file", get_default_export_filename());
223 
224 	add_entry("/apps/stardict/preferences/main_window/search_website_list", std::list<std::string>());
225 	// stores absolute and relative paths
226 	add_entry("/apps/stardict/manage_dictionaries/treedict_order_list", std::list<std::string>());
227 	// stores absolute and relative paths
228 	add_entry("/apps/stardict/manage_dictionaries/treedict_disable_list", std::list<std::string>());
229 	add_entry("/apps/stardict/manage_dictionaries/dict_order_list", std::list<std::string>());
230 	// stores absolute and relative paths
231 	add_entry("/apps/stardict/manage_dictionaries/dict_config_xml", std::string());
232 	add_entry("/apps/stardict/manage_dictionaries/dict_default_group", std::string());
233 
234 	// stores absolute and relative paths
235 	add_entry("/apps/stardict/manage_plugins/plugin_order_list", std::list<std::string>());
236 	// stores absolute and relative paths
237 	add_entry("/apps/stardict/manage_plugins/plugin_disable_list", std::list<std::string>());
238 
239 	std::list<std::string> dirs;
240 	{
241 		std::string dir(build_path(conf_dirs->get_data_dir(), "dic"));
242 #ifdef _WIN32
243 		dirs.push_back(rel_path_to_data_dir(dir));
244 #else
245 		dirs.push_back(dir);
246 #endif
247 	}
248 #ifndef _WIN32
249 	if (conf_dirs->get_data_dir() != "/usr/local/share/stardict") {
250 		dirs.push_back("/usr/local/share/stardict/dic");
251 	}
252 	dirs.push_back(std::string(g_get_home_dir())+"/.stardict/dic");
253 #endif
254 	// stores absolute and relative paths
255 	add_entry("/apps/stardict/manage_dictionaries/dict_dirs_list", dirs);
256 
257 	dirs.clear();
258 	{
259 		std::string dir(build_path(conf_dirs->get_data_dir(), "treedict"));
260 #ifdef _WIN32
261 		dirs.push_back(abs_path_to_data_dir(dir));
262 #else
263 		dirs.push_back(dir);
264 #endif
265 	}
266 #ifndef _WIN32
267 	dirs.push_back(std::string(g_get_home_dir())+"/.stardict/treedict");
268 #endif
269 	// stores absolute and relative paths
270 	add_entry("/apps/stardict/manage_dictionaries/treedict_dirs_list", dirs);
271 
272 	Load();
273 }
274 //---------------------------------------------------------------------------------
~AppConf()275 AppConf::~AppConf()
276 {
277 	for (cache_t::iterator it=cache.begin(); it!=cache.end(); ++it)
278 		delete it->second;
279 }
280 //---------------------------------------------------------------------------------
split(const std::string & s)281 static std::pair<std::string, std::string> split(const std::string& s)
282 {
283 	std::string::size_type pos=s.rfind("/");
284 	std::pair<std::string, std::string> res;
285 	if (pos!=std::string::npos)
286 		res.second = s.substr(pos+1);
287 	else
288 		pos=s.length();
289 
290 	res.first=s.substr(0, pos);
291 
292 	return res;
293 }
294 //---------------------------------------------------------------------------------
295 
296 //---------------------------------------------------------------------------------
notify_add(const char * name,const sigc::slot<void,const baseconfval * > & slot)297 void AppConf::notify_add(const char *name, const sigc::slot<void, const baseconfval*>& slot)
298 {
299 	std::pair<std::string, std::string> split_name = split(name);
300 	cf->notify_add(split_name.first.c_str(), split_name.second.c_str(), slot);
301 }
302 //---------------------------------------------------------------------------------
303 //load preference
Load()304 void AppConf::Load()
305 {
306 	for (cache_t::iterator p=cache.begin(); p!=cache.end(); ++p) {
307 		std::pair<std::string, std::string> name = split(p->first);
308 		p->second->load(*cf, name.first.c_str(), name.second.c_str());
309 	}
310 	const std::list<std::string> &list=
311 		get_strlist("/apps/stardict/preferences/main_window/search_website_list");
312 	if (list.empty()) {
313 		cache_t::iterator p =
314 			cache.find("/apps/stardict/preferences/main_window/search_website_list");
315 		static_cast<confval< std::list<std::string> > *>(p->second)->val_ =
316 			get_default_search_website_list();
317 	}
318 }
319 //---------------------------------------------------------------------------------
get_default_history_filename()320 std::string AppConf::get_default_history_filename()
321 {
322 	std::string histname;
323 #ifdef _WIN32
324 	histname = build_path(conf_dirs->get_user_config_dir(), "history.txt");
325 	histname = rel_path_to_data_dir(histname);
326 #else
327 	histname = build_path(conf_dirs->get_user_config_dir(), "history");
328 #endif
329 
330 	return histname;
331 }
332 
get_default_export_filename()333 std::string AppConf::get_default_export_filename()
334 {
335 	std::string exportname;
336 #ifdef _WIN32
337 	exportname = build_path(conf_dirs->get_data_dir(), "dic.txt");
338 	exportname = rel_path_to_data_dir(exportname);
339 #else
340 	exportname = g_get_home_dir();
341 	exportname+= G_DIR_SEPARATOR_S "dic.txt";
342 #endif
343 	return exportname;
344 }
345 
get_default_search_website_list()346 std::list<std::string> AppConf::get_default_search_website_list()
347 {
348 	/* xgettext: no-c-format */
349 	gchar *default_website = _("StarDict.org	http://www.stardict.org	http://www.stardict.org/query.php?q=%s\n"
350 		"Dictionary.com	http://dictionary.reference.com	http://dictionary.reference.com/search?q=%s\n"
351 		"dict.leo.org	http://dict.leo.org	http://dict.leo.org/?search=%s&lang=en\n"
352 		"H2G2	http://www.h2g2.com	http://www.h2g2.com/Search?searchstring=%s&searchtype=ARTICLE&skip=0&show=20&showapproved=1&shownormal=1&showsubmitted=1\n"
353 		"WhatIs	http://whatis.techtarget.com	http://whatis.techtarget.com/wsearchResults/1,290214,sid9,00.html?query=%s\n"
354 		"Altavista	http://www.altavista.com	http://www.altavista.com/cgi-bin/query?q=%s\n"
355 		"WEB.DE	http://suche.web.de	http://suche.web.de/search/?su=%s\n"
356 		"WebCrawler	http://www.webcrawler.com	http://www.webcrawler.com/cgi-bin/WebQuery?searchText=%s\n"
357 		"Google	http://www.google.com	http://www.google.com/search?q=%s\n"
358 		"Yahoo	http://search.yahoo.com	http://search.yahoo.com/bin/search?p=%s\n"
359 		"CMU	http://www.speech.cs.cmu.edu	http://www.speech.cs.cmu.edu/cgi-bin/cmudict?in=%s\n"
360 		);
361 //TODO: use split instead?
362 	gchar *p = default_website;
363 	gchar *p1;
364 	std::list<std::string> list;
365 	while ((p1 = strchr(p, '\n'))!= NULL) {
366 		list.push_back(std::string(p, p1-p));
367 		p= p1+1;
368 	}
369 	return list;
370 }
371 
372 #ifdef _WIN32
get_win32_use_custom_font()373 bool AppConf::get_win32_use_custom_font()
374 {
375 	// You may translate it to "win32_use_custom_font=1" for your language.
376 	gchar *ch = _("win32_use_custom_font=0");
377 	gchar *s = strstr(ch, "win32_use_custom_font=");
378 	if (s) {
379 		if (*(s+ sizeof("win32_use_custom_font=")-1)=='1')
380 			return true;
381 	}
382 	return false;
383 }
384 
get_win32_custom_font()385 std::string AppConf::get_win32_custom_font()
386 {
387 	// You may translate it as "win32_custom_font=tahoma 9".
388 	gchar *ch = _("win32_custom_font=");
389 	gchar *s = strstr(ch, "win32_custom_font=");
390 	if (s) {
391 		return (s+ sizeof("win32_custom_font=")-1);
392 	}
393 	return "";
394 }
395 #endif
396 
397 #ifdef CONFIG_DARWIN
get_darwin_use_custom_font()398 bool AppConf::get_darwin_use_custom_font()
399 {
400 	// You may translate it to "darwin_use_custom_font=1" for your language.
401 	gchar *ch = _("darwin_use_custom_font=0");
402 	gchar *s = strstr(ch, "darwin_use_custom_font=");
403 	if (s) {
404 		if (*(s+ sizeof("darwin_use_custom_font=")-1)=='1')
405 			return true;
406 	}
407 	return false;
408 }
409 
get_darwin_custom_font()410 std::string AppConf::get_darwin_custom_font()
411 {
412 	// You may translate it as "darwin_custom_font=STSong 12".
413 	gchar *ch = _("darwin_custom_font=");
414 	gchar *s = strstr(ch, "darwin_custom_font=");
415 	if (s) {
416 		return (s+ sizeof("darwin_custom_font=")-1);
417 	}
418 	return "";
419 }
420 #endif
421 //---------------------------------------------------------------------------------
422 
423 /* Wrapper of stardict-dirs.cfg configuration file.
424  * Provides access to configuration parameters.
425  * If a parameter is not defined, an empty string is returned.
426  *
427  * Do not use conf_dirs in this class! conf_dirs creation is in progress
428  * when an instance of this class is created. */
429 class AppDirsConf
430 {
431 public:
AppDirsConf(void)432 	AppDirsConf(void)
433 	: loaded(false)
434 	{
435 	}
436 
load(const std::string & conf_file)437 	void load(const std::string& conf_file)
438 	{
439 		if(g_file_test(conf_file.c_str(), GFileTest(G_FILE_TEST_IS_REGULAR))) {
440 			g_debug("Loading StarDict dirs config: %s", conf_file.c_str());
441 			if(!ini.load(conf_file, true, false))
442 				exit(EXIT_FAILURE);
443 			loaded = true;
444 		}
445 	}
446 
get_string_at(const char * key)447 	std::string get_string_at(const char* key)
448 	{
449 		if(!loaded)
450 			return "";
451 		std::string val;
452 		if(ini.read_string("general", key, val))
453 			return val;
454 		else
455 			return "";
456 	}
457 
458 private:
459 	inifile ini;
460 	bool loaded;
461 };
462 
AppDirs(const std::string & dirs_config_file)463 AppDirs::AppDirs(const std::string& dirs_config_file)
464 {
465 #ifdef _WIN32
466 	std::string t_path;
467 #endif
468 	std::string l_dirs_config_file = get_dirs_config_file(dirs_config_file);
469 #ifdef _WIN32
470 	if(abs_path_to_app_dir(l_dirs_config_file, t_path)) {
471 		g_error(_("Unable to resolve StarDict directories config file: %s."),
472 			l_dirs_config_file.c_str());
473 	}
474 	l_dirs_config_file = t_path;
475 #endif
476 	AppDirsConf app_conf;
477 	app_conf.load(l_dirs_config_file);
478 
479 	std::string path;
480 
481 	path = app_conf.get_string_at("user_config_dir");
482 	user_config_dir = path.empty() ? get_default_user_config_dir() : path;
483 #ifdef _WIN32
484 	if(abs_path_to_app_dir(user_config_dir, t_path)) {
485 		g_error(_("Unable to resolve user config directory: %s."),
486 			user_config_dir.c_str());
487 	}
488 	user_config_dir = t_path;
489 #endif
490 	if (!g_file_test(user_config_dir.c_str(), G_FILE_TEST_IS_DIR)) {
491 		if (-1 == g_mkdir_with_parents(user_config_dir.c_str(), S_IRWXU))
492 			g_warning(_("Cannot create user config directory %s."),
493 				user_config_dir.c_str());
494 	}
495 
496 	path = app_conf.get_string_at("user_cache_dir");
497 	user_cache_dir = path.empty() ? get_default_user_cache_dir() : path;
498 #ifdef _WIN32
499 	if(abs_path_to_app_dir(user_cache_dir, t_path)) {
500 		g_error(_("Unable to resolve user cache directory: %s."),
501 			user_cache_dir.c_str());
502 	}
503 	user_cache_dir = t_path;
504 #endif
505 
506 	path = app_conf.get_string_at("data_dir");
507 	data_dir = path.empty() ? get_default_data_dir() : path;
508 #ifdef _WIN32
509 	if(abs_path_to_app_dir(data_dir, t_path)) {
510 		g_error(_("Unable to resolve data directory: %s."),
511 			data_dir.c_str());
512 	}
513 	data_dir = t_path;
514 #endif
515 
516 	path = app_conf.get_string_at("log_dir");
517 	log_dir = path.empty() ? get_default_log_dir() : path;
518 #ifdef _WIN32
519 	if(abs_path_to_app_dir(log_dir, t_path)) {
520 		g_error(_("Unable to resolve log directory: %s."),
521 			log_dir.c_str());
522 	}
523 	log_dir = t_path;
524 #endif
525 	if(!g_file_test(log_dir.c_str(), G_FILE_TEST_IS_DIR))
526 		if(-1 == g_mkdir_with_parents(log_dir.c_str(), S_IRWXU))
527 			g_warning(_("Cannot create log directory %s."), log_dir.c_str());
528 
529 #ifdef _WIN32
530 	path = app_conf.get_string_at("dll_dir");
531 	dll_dir = path.empty() ? data_dir : path;
532 	if(abs_path_to_app_dir(dll_dir, t_path)) {
533 		g_error(_("Unable to resolve DLL directory: %s."),
534 			dll_dir.c_str());
535 	}
536 	dll_dir = t_path;
537 #endif
538 	path = app_conf.get_string_at("plugin_dir");
539 	plugin_dir = path.empty() ? get_default_plugin_dir() : path;
540 #ifdef _WIN32
541 	if(abs_path_to_app_dir(plugin_dir, t_path)) {
542 		g_error(_("Unable to resolve plugin directory: %s."),
543 			plugin_dir.c_str());
544 	}
545 	plugin_dir = t_path;
546 #endif
547 #ifndef CONFIG_GNOME
548 	path = app_conf.get_string_at("help_dir");
549 	help_dir = path.empty() ? get_default_help_dir() : path;
550 #endif
551 	locale_dir = get_default_locale_dir();
552 #ifdef _WIN32
553 	if(abs_path_to_app_dir(locale_dir, t_path)) {
554 		g_error(_("Unable to resolve locale directory: %s."),
555 			locale_dir.c_str());
556 	}
557 	locale_dir = t_path;
558 #endif
559 }
560 
561 #ifndef _WIN32
get_system_icon_dir(void) const562 std::string AppDirs::get_system_icon_dir(void) const
563 {
564 #ifdef CONFIG_DARWIN
565 	const gchar* dir = g_getenv("STARDICT_ICON_DIR");
566 	if (dir) {
567 		return dir;
568 	} else {
569 		return SYSTEM_ICON_DIR;
570 	}
571 #else
572 	return SYSTEM_ICON_DIR;
573 #endif
574 }
575 #endif
576 
get_dirs_config_file(const std::string & dirs_config_file) const577 std::string AppDirs::get_dirs_config_file(const std::string& dirs_config_file) const
578 {
579 	if(!dirs_config_file.empty())
580 		return dirs_config_file;
581 	const gchar * conf_file_env = g_getenv("STARDICT_DIRS_CONFIG_FILE");
582 	if(conf_file_env)
583 		return conf_file_env;
584 	return build_path(get_default_user_config_dir(), "stardict-dirs.cfg");
585 }
586 
get_default_user_config_dir(void) const587 std::string AppDirs::get_default_user_config_dir(void) const
588 {
589 	/* Note
590 	 * StarDict plugins use user config dir.
591 	 * Search for get_cfg_filename and g_get_user_config_dir functions.
592 	 * If you make change to this function, do not forget to change other
593 	 * functions as well. */
594 	const gchar *config_path_from_env = g_getenv("STARDICT_CONFIG_PATH");
595 	if (config_path_from_env)
596 		return config_path_from_env;
597 #ifdef _WIN32
598 	std::string res = g_get_user_config_dir();
599 	res += G_DIR_SEPARATOR_S "StarDict";
600 	return res;
601 #else
602 	std::string res = g_get_user_config_dir();
603 	res += G_DIR_SEPARATOR_S "stardict";
604 	return res;
605 #endif
606 }
607 
get_default_user_cache_dir(void) const608 std::string AppDirs::get_default_user_cache_dir(void) const
609 {
610 	std::string res = g_get_user_cache_dir();
611 	res += G_DIR_SEPARATOR_S "stardict";
612 	return res;
613 }
614 
get_default_data_dir(void) const615 std::string AppDirs::get_default_data_dir(void) const
616 {
617 #ifdef _WIN32
618 	return get_application_dir();
619 #elif defined(CONFIG_DARWIN)
620 	const gchar* dir = g_getenv("STARDICT_DATA_DIR");
621 	if (dir) {
622 		return dir;
623 	} else {
624 		return STARDICT_DATA_DIR;
625 	}
626 #else
627 	return STARDICT_DATA_DIR;
628 #endif
629 }
630 
get_default_log_dir(void) const631 std::string AppDirs::get_default_log_dir(void) const
632 {
633 	std::string res = g_get_tmp_dir();
634 #ifdef _WIN32
635 	res += G_DIR_SEPARATOR_S "StarDict";
636 #else
637 	res += G_DIR_SEPARATOR_S "stardict";
638 #endif
639 	return res;
640 }
641 
get_default_plugin_dir(void) const642 std::string AppDirs::get_default_plugin_dir(void) const
643 {
644 #ifdef _WIN32
645 	return build_path(data_dir, "plugins");
646 #elif defined(CONFIG_DARWIN)
647 	const gchar* dir = g_getenv("STARDICT_LIB_DIR");
648 	if (dir) {
649 		return build_path(dir, "plugins");
650 	} else {
651 		return build_path(STARDICT_LIB_DIR, "plugins");
652 	}
653 #else
654 	return build_path(STARDICT_LIB_DIR, "plugins");
655 #endif
656 }
657 
658 #ifndef CONFIG_GNOME
get_default_help_dir(void) const659 std::string AppDirs::get_default_help_dir(void) const
660 {
661 	return build_path(data_dir, "help");
662 }
663 #endif
664 
get_default_locale_dir(void) const665 std::string AppDirs::get_default_locale_dir(void) const
666 {
667 #ifdef _WIN32
668 	return build_path(data_dir, "locale");
669 #elif defined(CONFIG_DARWIN)
670 	const gchar* dir = g_getenv("STARDICT_LOCALE_DIR");
671 	if (dir) {
672 		return dir;
673 	} else {
674 		return STARDICT_LOCALE_DIR;
675 	}
676 #else
677 	return STARDICT_LOCALE_DIR;
678 #endif
679 }
680