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 /*
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 <cstring>
29 #include "file-utils.h"
30 #include "utils.h"
31
32 #include "treedict.h"
33
34 GtkTreeStore *TreeDict::model=NULL;
35
TreeDict()36 TreeDict::TreeDict()
37 {
38 if (model)
39 return;
40
41 // It is said G_TYPE_UINT will always be 32 bit.
42 // see http://bugzilla.gnome.org/show_bug.cgi?id=337966
43 model = gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT); //word, offset, size
44 }
45
load(const std::string & ifofilename)46 bool TreeDict::load(const std::string& ifofilename)
47 {
48 gulong tdxfilesize;
49 if (!load_ifofile(ifofilename, &tdxfilesize))
50 return false;
51
52 if(!DictBase::load(ifofilename.substr(0, ifofilename.length()-sizeof(".ifo")+1),
53 "dict"))
54 return false;
55
56 std::string fullfilename(ifofilename);
57 fullfilename.replace(fullfilename.length()-sizeof("ifo")+1, sizeof("ifo")-1, "tdx.gz");
58
59 gchar *buffer= NULL;
60 if (g_file_test(fullfilename.c_str(), G_FILE_TEST_EXISTS)) {
61 gzFile in;
62 in = gzopen(fullfilename.c_str(),"rb");
63 if (in == NULL) {
64 //g_print("Open file %s failed!\n",idxfilename);
65 return false;
66 }
67
68 buffer = (gchar *)g_malloc(tdxfilesize);
69
70 gulong len;
71 len = gzread(in, buffer, tdxfilesize);
72 if (len < 0) {
73 g_free(buffer);
74 return false;
75 }
76 gzclose(in);
77 if (len != tdxfilesize) {
78 g_free(buffer);
79 return false;
80 }
81 } else {
82 fullfilename.erase(fullfilename.length()-sizeof(".gz")+1, sizeof(".gz")-1);
83 FILE *file;
84 if (!(file = fopen (fullfilename.c_str(), "rb"))) {
85 //g_print("Open file %s failed!\n",fullfilename);
86 return false;
87 }
88 buffer = (gchar *)g_malloc(tdxfilesize);
89 gulong read_len;
90 read_len = fread(buffer, 1, tdxfilesize, file);
91 fclose(file);
92 if (read_len!=tdxfilesize) {
93 g_free(buffer);
94 return false;
95 }
96 }
97
98 gchar *tmp_buffer = buffer;
99 load_model(&tmp_buffer, NULL, 1); // tmp_buffer will be changed.
100 g_free(buffer);
101 return true;
102 }
103
load_ifofile(const std::string & ifofilename,gulong * tdxfilesize)104 bool TreeDict::load_ifofile(const std::string& ifofilename, gulong *tdxfilesize)
105 {
106 DictInfo dict_info;
107 if (!dict_info.load_from_ifo_file(ifofilename, DictInfoType_TreeDict))
108 return false;
109
110 *tdxfilesize = dict_info.get_index_file_size();
111 sametypesequence=dict_info.get_sametypesequence();
112
113 return true;
114 }
115
load_model(gchar ** buffer,GtkTreeIter * parent,guint32 count)116 void TreeDict::load_model(gchar **buffer, GtkTreeIter *parent, guint32 count)
117 {
118 GtkTreeIter iter;
119 gchar *p1;
120 guint32 offset, size, subentry_count;
121
122 for (guint32 i=0; i< count; i++) {
123 p1 = *buffer + strlen(*buffer) +1;
124 offset = g_ntohl(get_uint32(p1));
125 p1 += sizeof(guint32);
126 size = g_ntohl(get_uint32(p1));
127 p1 += sizeof(guint32);
128 subentry_count = g_ntohl(get_uint32(p1));
129 p1 += sizeof(guint32);
130 gtk_tree_store_append(model, &iter, parent);
131 gtk_tree_store_set(model, &iter, 0, *buffer, 1, offset, 2, size, -1);
132 *buffer = p1;
133 if (subentry_count)
134 load_model(buffer, &iter, subentry_count);
135 }
136 }
137
138
139 /**************************************************/
TreeDicts()140 TreeDicts::TreeDicts()
141 {
142 }
143
~TreeDicts()144 TreeDicts::~TreeDicts()
145 {
146 for (std::vector<TreeDict *>::iterator it=oTreeDict.begin();
147 it!=oTreeDict.end(); ++it)
148 delete *it;
149 }
150
load_dict(const std::string & url)151 void TreeDicts::load_dict(const std::string& url)
152 {
153 TreeDict *lib = new TreeDict;
154 if (lib->load(url))
155 oTreeDict.push_back(lib);
156 else
157 delete lib;
158 }
159
160 class TreeDictLoader {
161 public:
TreeDictLoader(TreeDicts & td_)162 TreeDictLoader(TreeDicts& td_) : td(td_) {}
operator ()(const std::string & url,bool disable)163 void operator()(const std::string& url, bool disable) {
164 if (!disable)
165 td.load_dict(url);
166 }
167 private:
168 TreeDicts& td;
169 };
170
Load(const strlist_t & tree_dicts_dirs,const strlist_t & order_list,const strlist_t & disable_list)171 GtkTreeStore* TreeDicts::Load(const strlist_t& tree_dicts_dirs,
172 const strlist_t& order_list,
173 const strlist_t& disable_list)
174 {
175 TreeDictLoader load(*this);
176 for_each_file(tree_dicts_dirs, ".ifo", order_list, disable_list, load);
177
178 return TreeDict::get_model();
179 }
180
poGetWordData(guint32 offset,guint32 size,int iTreeDict)181 gchar* TreeDicts::poGetWordData(guint32 offset, guint32 size, int iTreeDict)
182 {
183 return oTreeDict[iTreeDict]->GetWordData(offset, size);
184 }
185