Imported version 0.2-1
[mstardict] / src / lib / treedict.cpp
1 /*
2  * This file part of StarDict - A international dictionary for GNOME.
3  * http://stardict.sourceforge.net
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Implementation of class to work with GtkTree
22  * based StarDict's dictionaries
23  */
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include "file.hpp"
29 #include "getuint32.h"
30
31 #include "treedict.hpp"
32
33 GtkTreeStore *TreeDict::model=NULL;
34
35 TreeDict::TreeDict()
36 {
37         if (model)
38                 return;
39
40         // It is said G_TYPE_UINT will always be 32 bit.
41         // see http://bugzilla.gnome.org/show_bug.cgi?id=337966
42         model = gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT); //word, offset, size
43 }
44
45 bool TreeDict::load(const std::string& ifofilename)
46 {
47         gulong tdxfilesize;
48         if (!load_ifofile(ifofilename, &tdxfilesize))
49                 return false;
50
51         std::string fullfilename(ifofilename);
52         fullfilename.replace(fullfilename.length()-sizeof("ifo")+1, sizeof("ifo")-1, "dict.dz");
53
54         if (g_file_test(fullfilename.c_str(), G_FILE_TEST_EXISTS)) {
55                 dictdzfile.reset(new dictData);
56                 if (!dictdzfile->open(fullfilename, 0)) {
57                         //g_print("open file %s failed!\n",fullfilename);
58                         return false;
59                 }
60         } else {
61                 fullfilename.erase(fullfilename.length()-sizeof(".dz")+1, sizeof(".dz")-1);
62                 dictfile = fopen(fullfilename.c_str(),"rb");
63                 if (!dictfile) {
64                         //g_print("open file %s failed!\n",fullfilename);
65                         return false;
66                 }
67         }
68
69         fullfilename=ifofilename;
70         fullfilename.replace(fullfilename.length()-sizeof("ifo")+1, sizeof("ifo")-1, "tdx.gz");
71
72         gchar *buffer= NULL;
73         if (g_file_test(fullfilename.c_str(), G_FILE_TEST_EXISTS)) {
74                 gzFile in;
75                 in = gzopen(fullfilename.c_str(),"rb");
76                 if (in == NULL) {
77                         //g_print("Open file %s failed!\n",idxfilename);
78                         return false;
79                 }
80
81                 buffer = (gchar *)g_malloc(tdxfilesize);
82
83                 gulong len;
84                 len = gzread(in, buffer, tdxfilesize);
85                 if (len < 0) {
86                         g_free(buffer);
87                         return false;
88                 }
89                 gzclose(in);
90                 if (len != tdxfilesize) {
91                         g_free(buffer);
92                         return false;
93                 }
94         } else {
95                 fullfilename.erase(fullfilename.length()-sizeof(".gz")+1, sizeof(".gz")-1);
96                 FILE *file;
97                 if (!(file = fopen (fullfilename.c_str(), "rb"))) {
98                         //g_print("Open file %s failed!\n",fullfilename);
99                         return false;
100                 }
101                 buffer = (gchar *)g_malloc(tdxfilesize);
102                 gulong read_len;
103                 read_len = fread(buffer, 1, tdxfilesize, file);
104                 fclose(file);
105                 if (read_len!=tdxfilesize) {
106                         g_free(buffer);
107                         return false;
108                 }
109         }
110
111         gchar *tmp_buffer = buffer;
112         load_model(&tmp_buffer, NULL, 1); // tmp_buffer will be changed.
113         g_free(buffer);
114         return true;
115 }
116
117 bool TreeDict::load_ifofile(const std::string& ifofilename, gulong *tdxfilesize)
118 {
119         DictInfo dict_info;
120         if (!dict_info.load_from_ifo_file(ifofilename, true))
121                 return false;
122
123         *tdxfilesize = dict_info.index_file_size;
124         sametypesequence=dict_info.sametypesequence;
125
126         return true;
127 }
128
129 void TreeDict::load_model(gchar **buffer, GtkTreeIter *parent, guint32 count)
130 {
131         GtkTreeIter iter;
132         gchar *p1;
133         guint32 offset, size, subentry_count;
134
135         for (guint32 i=0; i< count; i++) {
136                 p1 = *buffer + strlen(*buffer) +1;
137                 offset = g_ntohl(get_uint32(p1));
138                 p1 += sizeof(guint32);
139                 size = g_ntohl(get_uint32(p1));
140                 p1 += sizeof(guint32);
141                 subentry_count = g_ntohl(get_uint32(p1));
142                 p1 += sizeof(guint32);
143                 gtk_tree_store_append(model, &iter, parent);
144                 gtk_tree_store_set(model, &iter, 0, *buffer, 1, offset, 2, size, -1);
145                 *buffer = p1;
146                 if (subentry_count)
147                         load_model(buffer, &iter, subentry_count);
148         }
149 }
150
151
152 /**************************************************/
153 TreeDicts::TreeDicts()
154 {
155 }
156
157 TreeDicts::~TreeDicts()
158 {
159         for (std::vector<TreeDict *>::iterator it=oTreeDict.begin();
160              it!=oTreeDict.end(); ++it)
161                 delete *it;
162 }
163
164 void TreeDicts::load_dict(const std::string& url)
165 {
166         TreeDict *lib = new TreeDict;
167         if (lib->load(url))
168                 oTreeDict.push_back(lib);
169         else
170                 delete lib;
171 }
172
173 class TreeDictLoader {
174 public:
175         TreeDictLoader(TreeDicts& td_) : td(td_) {}
176         void operator()(const std::string& url, bool disable) {
177                 if (!disable)
178                         td.load_dict(url);
179         }
180 private:
181         TreeDicts& td;
182 };
183
184 GtkTreeStore* TreeDicts::Load(const strlist_t& tree_dicts_dirs,
185                               const strlist_t& order_list,
186                               const strlist_t& disable_list)
187 {
188         TreeDictLoader load(*this);
189         for_each_file(tree_dicts_dirs, ".ifo", order_list, disable_list, load);
190
191         return TreeDict::get_model();
192 }
193
194 gchar* TreeDicts::poGetWordData(guint32 offset, guint32 size, int iTreeDict)
195 {
196         return oTreeDict[iTreeDict]->GetWordData(offset, size);
197 }