OPT added to MAkefile; KanjiView::Cell constructor: fg,bg changed to int (Fl_Color...
[aoi.git] / src / main.cxx
blobd6a6cec3e563c31696fd338c5efef821c00d5b3e
1 /*
2 Copyright 2013 Karel Matas
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "aoi.hxx"
18 #include "utils.hxx"
19 #include "parsers.hxx"
20 #include "sqlite3.hxx"
21 #include "config.hxx"
23 #include <exception>
24 #include <string>
26 using aoi::ElementKanji;
27 using aoi::ElementReading;
28 using aoi::ElementSense;
29 using aoi::DicWord;
30 using aoi::App;
31 using std::string;
32 using utils::to_string;
34 const char *TEMP_JMDICT = "gztemp.jmdict";
35 const char *TEMP_KANJIDIC = "gztemp.kanjidic";
37 const char *DBSCRIPT_LICENSE =
38 "--This file is based on the JMDICT and KANJIDIC dictionary files. These files \
39 are the property of the Electronic Dictionary Research and Development \
40 Group, and are used in conformance with the Group's licence.\
41 --http://www.csse.monash.edu.au/~jwb/jmdict.html\n\
42 --http://www.csse.monash.edu.au/~jwb/kanjidic2\n\
43 --http://www.edrdg.org/edrdg/licence.html\n\
44 --Decompositions of the kanji to radicals are taken from the KRADFILE-U \
45 - Copyright is held by Jim Rose. (http://www.kanjicafe.com/kradfile_license.htm)\n\
46 --The SKIP (System of Kanji Indexing by Patterns) system for ordering kanji \
47 used in this program was developed by Jack Halpern (Kanji Dictionary \
48 Publishing Society at http://www.kanji.org/, and is used with his \
49 permission.\n\
50 --See http://aoi.souko.cz for more details.\n";
52 /*!
53 * Parses JMDict. File may be GZipped.
54 * \see parsers::JmdictParser
55 * \exception utils::ParsingError
56 * \param fname path to JMDict file
58 void parse_jmdict ( const char *fname )
60 printf("Loading JMdict file '%s'.\n", fname);
61 std::stringstream ss;
62 ss << DBSCRIPT_LICENSE;
63 ss << "BEGIN TRANSACTION;\n";
65 // create parser
66 try {
67 printf("Decompressing file: %s -> %s\n", fname, TEMP_JMDICT);
68 utils::gzip_decompress_file( fname, TEMP_JMDICT);
69 parsers::JmdictParser jmp(TEMP_JMDICT);
70 const char *SEP = aoi::SEPARATOR_SQL;
72 // tables
73 for ( auto &mi: aoi_config::db_tables.at("main") ){
74 if ( strncmp( mi.first, "d_",2 ) !=0 && strcmp( mi.first, "aoi" )!=0 )
75 continue;
76 ss << "DROP TABLE IF EXISTS " << mi.first << ";\n"
77 << "CREATE TABLE " << mi.first << " ( ";
78 for ( size_t i=0; i<mi.second.size(); i++ )
79 ss << mi.second[i].name << " " << mi.second[i].type
80 << ((i==mi.second.size()-1) ? "":",");
81 ss << ");\n";
84 // version
85 ss << "INSERT INTO aoi (key,val) VALUES ('jmdict_version', '"
86 << jmp.get_version() << "');\n";
87 printf("jmdict_version: %s\n", jmp.get_version().c_str());
89 // get entities
90 for ( std::pair<string,string> elt: jmp.get_entities() ){
91 ss << "INSERT INTO d_entities (abbr,desc) VALUES ('" << SQLite3::escape(elt.first)
92 << "','" << SQLite3::escape(elt.second) << "');\n";
95 int n_entries = 1;
96 DicWord entry = jmp.get_entry();
97 while ( entry.did() != -1 ) {
98 for ( ElementReading &rele: entry.r_ele() )
99 ss << rele.sql(entry.did(),SEP);
100 for ( ElementKanji &kele: entry.k_ele() )
101 ss << kele.sql(entry.did(),SEP);
102 for ( ElementSense &sele: entry.s_ele() )
103 ss << sele.sql(entry.did(),SEP);
104 // tbl: header
105 n_entries++;
106 entry = jmp.get_entry();
107 } // while entry
108 printf("%d entries processed.\n", n_entries);
110 catch ( utils::ParsingError &e ){
111 std::string msg = "App::parse_jmdict(): ParsingError: ";
112 msg += e.what();
113 printf("parse_jmdict(): ParsingError: %s\n", e.what() );
114 return;
117 ss << "END TRANSACTION;\n";
118 printf("Writing file 'script.jmdict.sql'...\n");
119 std::ofstream f ("script.jmdict.sql");
120 f << ss.str();
121 f.close();
123 remove(TEMP_JMDICT);
128 * Parses kanjidic2. Works in the same way as parse_jmdict().
129 * \see parsers::KanjidicParser
131 void parse_kanjidic ( const char *fname )
133 printf("Loading kanjidic file: %s\n", fname);
134 const char *SEP = aoi::SEPARATOR_SQL;
136 int n_kanji = 0;
137 try {
138 printf("Decompressing file: %s -> %s\n", fname, TEMP_KANJIDIC);
139 utils::gzip_decompress_file( fname, TEMP_KANJIDIC);
140 parsers::KanjidicParser p(TEMP_KANJIDIC);
141 auto kanji = p.get_entry();
143 std::stringstream ss;
144 ss << "BEGIN TRANSACTION;\n";
146 // tables
147 for ( auto &mi: aoi_config::db_tables.at("main") ){
148 if ( strncmp( mi.first, "k_",2 ) !=0 )
149 continue;
150 ss << "DROP TABLE IF EXISTS " << mi.first << ";\n"
151 << "CREATE TABLE " << mi.first << " ( ";
152 for ( size_t i=0; i<mi.second.size(); i++ )
153 ss << mi.second[i].name << " " << mi.second[i].type
154 << ((i==mi.second.size()-1) ? "":",");
155 ss << ");\n";
158 // version
159 ss << "REPLACE INTO aoi (key,val) VALUES ('kanjidic_version','"
160 << p.get_version() << "');\n";
162 while ( kanji.kanji() != "" ){
163 n_kanji++;
164 ss << "INSERT INTO k_kanji "
165 << "(kanji,ucs,onyomi,kunyomi,meaning,nanori,flags,jlpt,grade,freq,strokes,"
166 << "rad_classic,rad_nelson,components)"
167 << " VALUES('"
168 << kanji.kanji() << "','"
169 << kanji.ucs() << "','"
170 << to_string(kanji.onyomi(),SEP) << "','"
171 << to_string(kanji.kunyomi(),SEP) << "','"
172 << SQLite3::escape(to_string(kanji.meaning(),SEP)) << "','"
173 << to_string(kanji.nanori(),SEP) << "','"
174 << to_string(kanji.flags(),SEP) << "',"
175 << kanji.jlpt() << ","
176 << kanji.grade() << ","
177 << kanji.freq() << ","
178 << kanji.strokes() << ","
179 << kanji.rad_classic() << ","
180 << kanji.rad_nelson() << ","
181 << "''"
182 << ");\n";
183 for ( aoi::SKIP &s: kanji.skip() ) {
184 ss << "INSERT INTO k_skip (kanji,skip1,skip2,skip3,misclass) VALUES('"
185 << kanji.kanji() << "'," << s.s1 << "," << s.s2 << "," << s.s3
186 << ",'" << s.misclass << "');\n";
188 kanji = p.get_entry();
190 ss << "END TRANSACTION\n;";
192 printf("Writing file 'script.kanjidic.sql'...\n");
193 std::ofstream f ("script.kanjidic.sql");
194 f << ss.str();
195 f.close();
197 catch ( utils::ParsingError &e ){
198 printf("parse_kanjidic(): ParsingError: %s\n", e.what());
199 return;
201 remove( TEMP_KANJIDIC );
206 void usage ()
208 printf("USAGE: aoi [OPTIONS]\n");
209 printf("OPTIONS:\n");
210 printf(" -geometry W*H+X+Y \n");
211 printf(" -scheme none|GTK+|plastic \n");
212 printf(" -config config string\n");
213 printf(" -parse jmdict|kanjidic parse either jmdict or kanjidic\n");
217 //////////////////////////////////////////////////////////////////////////
220 int main ( int argc, char **argv )
222 int ret = 0;
223 int fltk_argc = 1;
224 char **fltk_argv = &argv[0];
226 // Commandline options
227 try {
228 for ( int i=1; i < argc; i++ ){
229 ///////////////////////////////////////////////////////
230 // CONFIG
231 if ( !strcmp( argv[i], "-config") ){
232 string opts = argv[++i];
233 if ( opts == "help" ){
234 for ( auto mi: App::get()->get_config_map() )
235 printf("%s [%s]\n %s\n\n",
236 mi.first.c_str(), mi.second.val.c_str(), mi.second.desc.c_str() );
237 continue;
239 for ( string &s: utils::split_string( opts, ":" ) ){
240 vector<string> kv = utils::split_string(s, "=");
241 App::get()->log("Config override: " + kv[0] + "=" + kv[1]);
242 try {
243 App::get()->config_override( kv[0], kv[1] ); }
244 catch ( std::runtime_error &e ) {
245 App::get()->log_w("Unknown option: " + kv[0] ); }
247 App::get()->apply_config();
248 } // -config
249 ///////////////////////////////////////////////////////
250 // Parse source files
251 else if ( !strcmp( argv[i], "-parse" ) ) {
252 if ( i == argc-1 ){
253 printf("-parse: Missing parameter: either kanjidic or jmdict\n");
254 return 0;
256 i++;
257 if ( !strcmp( argv[i], "jmdict") ){
258 if ( utils::file_exists("JMdict_e.gz") )
259 parse_jmdict( "JMdict_e.gz" );
260 else if ( utils::file_exists("JMdict_e") )
261 parse_jmdict( "JMdict_e" );
262 else {
263 printf("File not found: JMdict_e or JMdict_e.gz\n");
264 return 0;
267 else if ( !strcmp( argv[i], "kanjidic") ){
268 if ( utils::file_exists("kanjidic2.xml.gz") )
269 parse_kanjidic( "kanjidic2.xml.gz" );
270 else if ( utils::file_exists("kanjidic2.xml") )
271 parse_kanjidic( "kanjidic2.xml" );
272 else {
273 printf("File not found: kanjidic2.xml or kanjidic2.xml.gz\n");
274 return 0;
277 else {
278 printf("-parse: wrong parameter '%s'.\n", argv[i] );
279 printf("Possible parameters: kanjidic or jmdict\n");
281 return 1;
283 ///////////////////////////////////////////////////////
284 // load database script
285 else if ( !strncmp( argv[i], "-loaddb", 7) ){
286 if ( i==argc-1 ) {
287 printf("Missing file: -loaddb FILE\n");
288 return 0;
290 if ( !utils::file_exists(argv[i+1]) ){
291 printf("File does not exist: %s\n", argv[i+1]);
292 return 0;
294 App::get()->load_dbscript( argv[i+1] );
295 return 1;
297 ///////////////////////////////////////////////////////
298 // argv[i] not recognized
299 else {
300 printf("argv[%d] : %s -> FLTK\n", i, argv[i]);
301 // pass unparsed arguments to FLTK
302 fltk_argv[fltk_argc++] = argv[i];
305 ret = App::get()->run(fltk_argc,fltk_argv);
307 ///////////////////////////////////////////////////////
308 // EXCEPTIONS
309 catch ( std::exception &e ){
310 // This should never happen ...
311 string msg = std::string("Something went wrong...\n")
312 + std::string(typeid(e).name())
313 + std::string(": ") + std::string(e.what());
314 App::get()->alert(msg);
317 delete App::get();
318 return ret;