Imported version 0.5-1
[mstardict] / src / libwrapper.cpp
1 /*
2  *  MStarDict - International dictionary for Maemo.
3  *  Copyright (C) 2010 Roman Moravcik
4  *
5  *  base on code of stardict:
6  *  Copyright (C) 2003-2007 Hu Zheng <huzheng_001@163.com>
7  *
8  *  based on code of sdcv:
9  *  Copyright (C) 2005-2006 Evgeniy <dushistov@mail.ru>
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #  include "config.h"
28 #endif
29
30 #include <glib.h>
31 #include <glib/gi18n.h>
32
33 #include "lib/getuint32.h"
34
35 #include "libwrapper.hpp"
36 #include "mstardict.hpp"
37
38 static
39 string parse_data(const gchar *data,
40                   const gchar *oword)
41 {
42     if (!data)
43         return "";
44
45     string mark;
46     guint32 data_size, sec_size = 0;
47     const gchar *p = data;
48     data_size = get_uint32(data);
49     p += sizeof(guint32);
50     size_t iPlugin;
51     size_t nPlugins = pMStarDict->oPlugins->ParseDataPlugins.nplugins();
52     unsigned int parsed_size;
53     ParseResult parse_result;
54
55     while (guint32(p - data) < data_size) {
56         for (iPlugin = 0; iPlugin < nPlugins; iPlugin++) {
57             parse_result.clear();
58             if (pMStarDict->oPlugins->ParseDataPlugins.parse(iPlugin, p, &parsed_size, parse_result, oword)) {
59                 p += parsed_size;
60                 break;
61             }
62         }
63         if (iPlugin != nPlugins) {
64             for (std::list<ParseResultItem>::iterator it = parse_result.item_list.begin(); it != parse_result.item_list.end(); ++it) {
65                 switch (it->type) {
66                     case ParseResultItemType_mark:
67                         g_debug("ParseResultItemType_mark");
68                         mark += it->mark->pango;
69                         break;
70                     case ParseResultItemType_link:
71                         mark += it->mark->pango;
72                         break;
73                     case ParseResultItemType_res:
74                     {
75                         g_debug("ParseResultItemType_res");
76                         bool loaded = false;
77                         if (it->res->type == "image") {
78                         } else if (it->res->type == "sound") {
79                         } else if (it->res->type == "video") {
80                         } else {
81                         }
82                         if (!loaded) {
83                             mark += "<span foreground=\"red\">";
84                             gchar *m_str = g_markup_escape_text(it->res->key.c_str(), -1);
85                             mark += m_str;
86                             g_free(m_str);
87                             mark += "</span>";
88                         }
89                         break;
90                     }
91                     case ParseResultItemType_widget:
92                         g_debug("ParseResultItemType_widget");
93                         break;
94                     default:
95                         g_debug("ParseResultItemType_default");
96                         break;
97                 }
98             }
99             parse_result.clear();
100             continue;
101         }
102
103         switch (*p) {
104         case 'm':
105         case 'l':               //need more work...
106             p++;
107             sec_size = strlen(p);
108             if (sec_size) {
109                 gchar *m_str = g_markup_escape_text(p, sec_size);
110                 mark += m_str;
111                 g_free(m_str);
112             }
113             sec_size++;
114             break;
115         case 'g':
116             p++;
117             sec_size = strlen(p);
118             if (sec_size) {
119                 mark += p;
120             }
121             sec_size++;
122             break;
123         case 'x':
124             p++;
125             sec_size = strlen(p) + 1;
126             mark += _("XDXF data parsing plug-in is not found!");
127             break;
128         case 'k':
129             p++;
130             sec_size = strlen(p) + 1;
131             mark += _("PowerWord data parsing plug-in is not found!");
132             break;
133         case 'w':
134             p++;
135             sec_size = strlen(p) + 1;
136             mark += _("Wiki data parsing plug-in is not found!");
137             break;
138         case 'h':
139             p++;
140             sec_size = strlen(p) + 1;
141             mark += _("HTML data parsing plug-in is not found!");
142             break;
143         case 'n':
144             p++;
145             sec_size = strlen(p) + 1;
146             mark += _("WordNet data parsing plug-in is not found!");
147             break;
148         case 't':
149             p++;
150             sec_size = strlen(p);
151             if (sec_size) {
152                 mark += "[<span foreground=\"blue\">";
153                 gchar *m_str = g_markup_escape_text(p, sec_size);
154                 mark += m_str;
155                 g_free(m_str);
156                 mark += "</span>]";
157             }
158             sec_size++;
159             break;
160         case 'y':
161             p++;
162             sec_size = strlen(p);
163             if (sec_size) {
164                 mark += "[<span foreground=\"red\">";
165                 gchar *m_str = g_markup_escape_text(p, sec_size);
166                 mark += m_str;
167                 g_free(m_str);
168                 mark += "</span>]";
169             }
170             sec_size++;
171             break;
172         case 'W':
173             p++;
174             sec_size = g_ntohl(get_uint32(p));
175             //enbale sound button.
176             sec_size += sizeof(guint32);
177             break;
178         case 'P':
179             {
180                 p++;
181                 sec_size = g_ntohl(get_uint32(p));
182                 if (sec_size) {
183                     GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
184                     gdk_pixbuf_loader_write(loader, (const guchar *) (p + sizeof(guint32)), sec_size, NULL);
185                     gdk_pixbuf_loader_close(loader, NULL);
186                     GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
187                     if (pixbuf) {
188 //                      append_and_mark_orig_word(mark, real_oword, LinksPosList());
189 //                      mark.clear();
190 //                      append_pixbuf(pixbuf);
191                     } else {
192                         mark += _("<span foreground=\"red\">[Load image error!]</span>");
193                     }
194                     g_object_unref(loader);
195                 } else {
196                     mark += _("<span foreground=\"red\">[Missing Image]</span>");
197                 }
198                 sec_size += sizeof(guint32);
199             }
200             break;
201         default:
202             if (g_ascii_isupper(*p)) {
203                 p++;
204                 sec_size = g_ntohl(get_uint32(p));
205                 sec_size += sizeof(guint32);
206             } else {
207                 p++;
208                 sec_size = strlen(p) + 1;
209             }
210             mark += _("Unknown data type");
211             break;
212         }
213         p += sec_size;
214     }
215     return mark;
216 }
217
218 void
219 Library::ListWords(CurrentIndex *iIndex)
220 {
221     CurrentIndex *iCurrent = (CurrentIndex *) g_memdup(iIndex,
222                                                        sizeof(CurrentIndex) *
223                                                        query_dictmask.size());
224
225     oStarDict->ResultsListClear();
226
227     int iWordCount = 0;
228     const gchar *poCurrentWord = poGetCurrentWord(iIndex, query_dictmask, 0);
229     if (poCurrentWord) {
230         oStarDict->ResultsListInsertLast(poCurrentWord);
231         iWordCount++;
232
233         while (iWordCount < 30 && (poCurrentWord = poGetNextWord(NULL, iIndex, query_dictmask, 0))) {
234             oStarDict->ResultsListInsertLast(poCurrentWord);
235             iWordCount++;
236         }
237     }
238     oStarDict->ResultsReScroll();
239
240     if (iCurrent)
241         g_free(iCurrent);
242 }
243
244 bool
245 Library::BuildResultData(std::vector < InstantDictIndex > &dictmask,
246                          const char *sWord,
247                          CurrentIndex *iIndex,
248                          int iLib,
249                          GList **result_data)
250 {
251     int iRealLib;
252     bool bFound = false, bLookupWord = false, bLookupSynonymWord = false;
253     gint nWord = 0, count = 0, i = 0, j = 0;
254     glong iWordIdx;
255     struct SearchResult *result;
256
257     iRealLib = dictmask[iLib].index;
258
259     bLookupWord = LookupWord(sWord, iIndex[iLib].idx, iIndex[iLib].idx_suggest, iRealLib, 0);
260     if (!bLookupWord)
261         bLookupWord =
262             LookupSimilarWord(sWord, iIndex[iLib].idx, iIndex[iLib].idx_suggest, iRealLib, 0);
263     if (!bLookupWord)
264         bLookupWord =
265             SimpleLookupWord(sWord, iIndex[iLib].idx, iIndex[iLib].idx_suggest, iRealLib, 0);
266
267     bLookupSynonymWord =
268         LookupSynonymWord(sWord, iIndex[iLib].synidx, iIndex[iLib].synidx_suggest, iRealLib, 0);
269     if (!bLookupSynonymWord)
270         bLookupSynonymWord =
271             LookupSynonymSimilarWord(sWord, iIndex[iLib].synidx,
272                                      iIndex[iLib].synidx_suggest, iRealLib, 0);
273     if (!bLookupSynonymWord)
274         bLookupSynonymWord =
275             SimpleLookupSynonymWord(sWord, iIndex[iLib].synidx,
276                                     iIndex[iLib].synidx_suggest, iRealLib, 0);
277
278     if (bLookupWord || bLookupSynonymWord) {
279         if (bLookupWord)
280             nWord++;
281
282         if (bLookupSynonymWord)
283             nWord += GetOrigWordCount(iIndex[iLib].synidx, iRealLib, false);
284
285         if (bLookupWord) {
286             count = GetOrigWordCount(iIndex[iLib].idx, iRealLib, true);
287             for (i = 0; i < count; i++) {
288                 result = (SearchResult *) g_malloc(sizeof(struct SearchResult));
289                 result->bookname = g_strdup(dict_name(iLib).c_str());
290                 result->exp = g_strdup(poGetOrigWord(iIndex[iLib].idx, iRealLib));
291                 result->def = g_strdup(parse_data(poGetOrigWordData(iIndex[iLib].idx + i, iRealLib), poGetOrigWord(iIndex[iLib].idx, iRealLib)).c_str());
292                 *result_data = g_list_append(*result_data, result);
293             }
294             i = 1;
295         } else {
296             i = 0;
297         }
298         for (j = 0; i < nWord; i++, j++) {
299             iWordIdx = poGetOrigSynonymWordIdx(iIndex[iLib].synidx + j, iRealLib);
300             result = (SearchResult *) g_malloc(sizeof(struct SearchResult));
301             result->bookname = g_strdup(dict_name(iLib).c_str());
302             result->exp = g_strdup(poGetOrigWord(iWordIdx, iRealLib));
303             result->def = g_strdup(parse_data(poGetOrigWordData(iWordIdx, iRealLib), poGetOrigWord(iWordIdx, iRealLib)).c_str());
304             *result_data = g_list_append(*result_data, result);
305         }
306
307         bFound = true;
308     }
309
310     return bFound;
311 }
312
313 void
314 Library::FreeResultData(GList *result_data)
315 {
316 }
317
318 bool
319 Library::SimpleLookup(const gchar *sWord,
320                       CurrentIndex *piIndex)
321 {
322     CurrentIndex *iIndex;
323     GList *results = NULL;
324     bool bFound = false;
325
326     if (!piIndex)
327         iIndex = (CurrentIndex *) g_malloc(sizeof(CurrentIndex) * query_dictmask.size());
328     else
329         iIndex = piIndex;
330
331     for (size_t iLib = 0; iLib < query_dictmask.size(); iLib++) {
332         if (BuildResultData(query_dictmask, sWord, iIndex, iLib, &results))
333             bFound = true;
334     }
335
336     FreeResultData(results);
337
338     if (!piIndex)
339         g_free(iIndex);
340
341     return bFound;
342 }
343
344 bool
345 Library::LookupWithFuzzy(const gchar *sWord)
346 {
347     static const int MAX_FUZZY_MATCH_ITEM = 100;
348     gchar *fuzzy_reslist[MAX_FUZZY_MATCH_ITEM];
349     bool bFound = false;
350
351     oStarDict->ResultsListClear();
352
353     bFound = Libs::LookupWithFuzzy(sWord, fuzzy_reslist, MAX_FUZZY_MATCH_ITEM, query_dictmask);
354     if (bFound) {
355         SimpleLookup(fuzzy_reslist[0], iCurrentIndex);
356
357         for (int i = 0; i < MAX_FUZZY_MATCH_ITEM && fuzzy_reslist[i]; i++) {
358             oStarDict->ResultsListInsertLast(fuzzy_reslist[i]);
359             g_free(fuzzy_reslist[i]);
360         }
361         oStarDict->ResultsReScroll();
362     }
363
364     return bFound;
365 }
366
367 bool
368 Library::LookupWithRule(const gchar *sWord)
369 {
370     gint iMatchCount = 0;
371     bool bFound = false;
372     gchar **ppMatchWord =
373         (gchar **) g_malloc(sizeof(gchar *) * (MAX_MATCH_ITEM_PER_LIB) * query_dictmask.size());
374
375     oStarDict->ResultsListClear();
376
377     iMatchCount = Libs::LookupWithRule(sWord, ppMatchWord, query_dictmask);
378     if (iMatchCount) {
379         for (gint i = 0; i < iMatchCount; i++)
380             oStarDict->ResultsListInsertLast(ppMatchWord[i]);
381
382         SimpleLookup(ppMatchWord[0], iCurrentIndex);
383         oStarDict->ResultsReScroll();
384
385         for (gint i = 0; i < iMatchCount; i++)
386             g_free(ppMatchWord[i]);
387
388         bFound = true;
389     }
390     g_free(ppMatchWord);
391     return bFound;
392 }
393
394 bool
395 Library::LookupWithRegex(const gchar *sWord)
396 {
397     gint iMatchCount = 0;
398     bool bFound = false;
399     gchar **ppMatchWord =
400         (gchar **) g_malloc(sizeof(gchar *) * (MAX_MATCH_ITEM_PER_LIB) * query_dictmask.size());
401
402     oStarDict->ResultsListClear();
403
404     iMatchCount = Libs::LookupWithRegex(sWord, ppMatchWord, query_dictmask);
405     if (iMatchCount) {
406         for (gint i = 0; i < iMatchCount; i++)
407             oStarDict->ResultsListInsertLast(ppMatchWord[i]);
408
409         SimpleLookup(ppMatchWord[0], iCurrentIndex);
410         oStarDict->ResultsReScroll();
411
412         for (gint i = 0; i < iMatchCount; i++)
413             g_free(ppMatchWord[i]);
414
415         bFound = true;
416     }
417     g_free(ppMatchWord);
418     return bFound;
419 }
420
421 static void
422 LookupProgressDialogUpdate(gpointer data,
423                            double fraction)
424 {
425     GtkWidget *dialog = GTK_WIDGET(data);
426     GtkWidget *progress;
427
428     progress = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), "progress_bar"));
429     gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction);
430
431     while (gtk_events_pending())
432         gtk_main_iteration();
433 }
434
435 bool
436 Library::LookupData(const gchar *sWord)
437 {
438     GtkWidget *dialog;
439     bool cancel = false;
440     bool bFound = false;
441
442     std::vector < std::vector < gchar * > > reslist(query_dictmask.size());
443
444
445     oStarDict->ResultsListClear();
446     oStarDict->ShowProgressIndicator(true);
447     dialog = oStarDict->CreateLookupProgressDialog(&cancel);
448
449     bFound = Libs::LookupData(sWord, &reslist[0], LookupProgressDialogUpdate, (gpointer) dialog, &cancel, query_dictmask);
450     if (bFound) {
451         for (size_t iLib = 0; iLib < query_dictmask.size(); iLib++) {
452             if (!reslist[iLib].empty()) {
453                 SimpleLookup(reslist[iLib][0], iCurrentIndex);
454
455                 for (std::vector < gchar *>::iterator i = reslist[iLib].begin();
456                      i != reslist[iLib].end(); ++i) {
457                     oStarDict->ResultsListInsertLast(*i);
458                 }
459                 break;
460             }
461         }
462         oStarDict->ResultsReScroll();
463     }
464     oStarDict->ShowProgressIndicator(false);
465     oStarDict->DestroyLookupProgressDialog(dialog);
466     return bFound;
467 }
468
469 Library::Library(MStarDict *mStarDict):Libs(NULL, FALSE, 0, 0)
470 {
471     oStarDict = mStarDict;
472     iCurrentIndex = NULL;
473 }
474
475 Library::~Library()
476 {
477     if (iCurrentIndex)
478         g_free(iCurrentIndex);
479 }