Various changes to preferences object, file loading, and error logging.
[jben.git] / preferences.cpp
bloba2e608c6b77369d2aa617fc5cba1d8ac9946b08f
1 /*
2 Project: J-Ben
3 Author: Paul Goins
4 Website: http://www.vultaire.net/software/jben/
5 License: GNU General Public License (GPL) version 2
6 (http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt)
8 File: preferences.cpp
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>
24 #ifndef JB_DATADIR
25 # define JB_DATADIR "."
26 #endif
28 #ifdef __WXMSW__
29 # define CFGFILE "jben.cfg"
30 # define HOMEENV "APPDATA"
31 #else
32 # define CFGFILE ".jben"
33 # define HOMEENV "HOME"
34 #endif
36 #define CURRENT_CONFIG_VERSION "1.1"
38 #include "preferences.h"
39 #include "jben.h"
40 #include "file_utils.h"
41 #include "encoding_convert.h"
42 #include "string_utils.h"
43 #include "errorlog.h"
44 #include <sstream>
45 #include <fstream>
46 #include <iostream>
47 #include <iomanip>
48 #include <cstdlib>
49 using namespace std;
51 Preferences* Preferences::prefsSingleton = NULL;
53 Preferences *Preferences::Get() {
54 if(!prefsSingleton) {
55 prefsSingleton = new Preferences;
56 /* Load with default preferences, and overwrite with any stored
57 preferences. */
58 prefsSingleton->SetDefaultPrefs();
60 /* Check for the config file in the user's home directory. */
61 string homedir = getenv(HOMEENV);
62 homedir.append(1, DSCHAR);
63 bool OK = (prefsSingleton
64 ->LoadFile(string(homedir).append(CFGFILE).c_str())
65 == REF_SUCCESS);
67 /* If the config file could not be loaded from the home directory,
68 fall back and check the current directory. */
69 if(!OK)
70 prefsSingleton->LoadFile(CFGFILE);
72 return prefsSingleton;
75 Preferences::Preferences() {
76 /* Nothing to be done */
79 void Preferences::Destroy() {
80 if(prefsSingleton) {
81 delete prefsSingleton;
82 prefsSingleton = NULL;
86 void Preferences::SetDefaultPrefs() {
87 kanjidicOptions =
88 KDO_READINGS | KDO_MEANINGS | KDO_HIGHIMPORTANCE | KDO_VOCABCROSSREF;
89 kanjidicDictionaries = 0;
90 stringOpts["config_version"] = CURRENT_CONFIG_VERSION;
91 stringOpts["config_save_target"] = "home";
92 stringOpts["kdict_kanjidic2"]
93 = JB_DATADIR DSSTR "dicts" DSSTR "kanjidic2.xml";
94 stringOpts["kdict_kanjidic"] = JB_DATADIR DSSTR "dicts" DSSTR "kanjidic";
95 stringOpts["kdict_kanjd212"] = JB_DATADIR DSSTR "dicts" DSSTR "kanjd212";
96 stringOpts["kdict_kradfile"] = JB_DATADIR DSSTR "dicts" DSSTR "kradfile";
97 stringOpts["kdict_radkfile"] = JB_DATADIR DSSTR "dicts" DSSTR "radkfile";
98 stringOpts["wdict_edict2"] = JB_DATADIR DSSTR "dicts" DSSTR "edict2";
99 stringOpts["sod_dir"] = JB_DATADIR DSSTR "sods";
102 int Preferences::LoadFile(const char *filename) {
103 wstring s;
104 kanjidicOptions = KDO_ALL | KDO_UNHANDLED;
105 kanjidicDictionaries = 0; /* KDD_ALL */
107 int e = ReadEncodedFile(filename, s);
108 if(e==REF_SUCCESS) {
109 ostringstream oss;
110 oss << "Preferences file \"" << filename
111 << "\" loaded successfully.";
112 el.Push(EL_Silent, oss.str());
114 /* Split into strings for each line */
115 list<wstring> tokenList = StrTokenize<wchar_t>(s, L"\n");
116 wstring token, subToken;
117 size_t index;
118 while(tokenList.size()>0) {
119 token = tokenList.front();
120 tokenList.pop_front();
121 if( (token.length()>0) && (token[0]!=L'#') ) {
122 /* We only want to split the string into two subtokens, so we'll
123 do it manually. */
124 index = token.find_first_of(_T(" \t"));
125 if(index!=wstring::npos) {
126 subToken = token.substr(0, index);
127 subToken = ToLower(subToken);
129 if(subToken==L"kanjidicoptionmask") {
130 subToken = token.substr(index+1);
131 subToken = Trim(subToken);
132 /* We know the subtoken starts with 0x, so skip the
133 first two characters. */
134 wistringstream(subToken.substr(2))
135 >> hex >> kanjidicOptions;
137 } else if(subToken==L"kanjidicdictionarymask") {
138 subToken = token.substr(index+1);
139 subToken = Trim(subToken);
140 wistringstream(subToken.substr(2))
141 >> hex >> kanjidicDictionaries;
143 } else if(subToken==L"vocablist") {
144 subToken = token.substr(index+1);
145 subToken = Trim(subToken);
146 list<wstring> tSub
147 = StrTokenize<wchar_t>(subToken, L";");
148 while(tSub.size()>0) {
149 subToken = tSub.front();
150 tSub.pop_front();
151 if(subToken.length()>0) {
152 string *temp = &stringOpts["vocablist"];
153 if(temp->length()>0)
154 temp->append(1, '\n');
155 temp->append(utfconv_wm(subToken));
159 } else {
160 /* Default handling for any
161 other string-based entries */
162 string key = utfconv_wm(subToken);
163 subToken = token.substr(index+1);
164 stringOpts[key] = utfconv_wm(Trim(subToken));
166 } else {
167 /* No space/tab was found. Check no-arg options, if any.
168 (Currently there are none.) */
170 } /* if(tokenlen>0, token[0]!=# */
171 } /* while(hasmoretokens) */
172 } /* if(file opened) */
173 else {
174 ostringstream oss;
175 oss << "Preferences file \"" << filename
176 << "\" could NOT be loaded." << endl;
177 el.Push(EL_Silent, oss.str());
180 /* The file is now loaded.
181 Upgrade it to the latest version, if necessary. */
182 if(stringOpts["config_version"] != CURRENT_CONFIG_VERSION)
183 UpgradeConfigFile();
185 return e;
188 void Preferences::UpgradeConfigFile() {
189 string version = stringOpts["config_version"];
190 /* Iterate through the version-wise changes */
191 if(version=="1") {
192 el.Push(EL_Silent, "Upgrading config file from version 1 to 1.1.");
193 /* 1 to 1.1:
194 - Add config_save_target setting
195 - Add KANJIDIC2 and KANJD212 default settings */
196 stringOpts["config_save_target"] = "home";
197 stringOpts["kdict_kanjidic2"]
198 = JB_DATADIR DSSTR "dicts" DSSTR "kanjidic2.xml";
199 stringOpts["kdict_kanjd212"]
200 = JB_DATADIR DSSTR "dicts" DSSTR "kanjd212";
201 version = "1.1";
203 stringOpts["config_version"] = CURRENT_CONFIG_VERSION;
206 Preferences::~Preferences() {
207 string prefs = GetPrefsStr();
208 ofstream ofile;
209 string filename;
210 if(ToLower(stringOpts["config_save_target"]) == "home") {
211 filename = string(getenv(HOMEENV)).append(1, DSCHAR).append(CFGFILE);
212 ofile.open(filename.c_str(), ios::out | ios::binary);
214 if(!ofile.is_open()) {
215 filename = CFGFILE;
216 ofile.open(filename.c_str(), ios::out | ios::binary);
219 ostringstream oss;
220 if(ofile.is_open()) {
221 ofile << prefs;
222 oss << "Preferences file \"" << filename
223 << "\" saved successfully.";
224 el.Push(EL_Silent, oss.str());
226 else {
227 oss << "Unable to save preferences to file \"" << CFGFILE
228 << "\"!";
229 el.Push(EL_Error, oss.str());
232 ofile.close();
235 string Preferences::GetPrefsStr() {
236 ostringstream prefs;
237 string kanjiList, vocabList;
239 /* Output config version first */
240 prefs << "config_version\t" << stringOpts["config_version"] << '\n';
242 /* Get kanji and vocab lists in UTF-8 encoded strings */
243 kanjiList = utfconv_wm(jben->kanjiList->ToString());
244 vocabList = utfconv_wm(jben->vocabList->ToString(';'));
246 prefs << "KanjidicOptionMask\t0x"
247 << uppercase << hex << setw(8) << setfill('0')
248 << kanjidicOptions << '\n';
249 prefs << "KanjidicDictionaryMask\t0x"
250 << uppercase << hex << setw(8) << setfill('0')
251 << kanjidicDictionaries << '\n';
252 prefs << "KanjiList\t"
253 << utfconv_wm(jben->kanjiList->ToString()) << '\n';
254 prefs << "VocabList\t"
255 << utfconv_wm(jben->vocabList->ToString(';')) << '\n';
257 /* Append any other variables stored */
258 for(map<string, string>::iterator mi = stringOpts.begin();
259 mi != stringOpts.end(); mi++) {
260 if(mi->first!="kanjilist" &&
261 mi->first!="vocablist" &&
262 mi->first!="config_version") {
263 prefs << mi->first << '\t' << mi->second << '\n';
267 return prefs.str();
270 string& Preferences::GetSetting(string key) {
271 return stringOpts[ToLower(key)];