Imported version 0.2-5
[mstardict] / src / libwrapper.cpp
1 /* 
2  * This file part of sdcv - console version of Stardict program
3  * http://sdcv.sourceforge.net
4  * Copyright (C) 2005-2006 Evgeniy <dushistov@mail.ru>
5  *
6  * This program 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 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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 Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #endif
24
25 #include <glib/gi18n.h>
26 #include <map>
27
28 #include "libwrapper.hpp"
29 #include "mstardict.hpp"
30
31 static std::string xdxf2text(const char *p)
32 {
33         std::string res;
34         for (; *p; ++p) {
35                 if (*p!='<') {
36                         if (g_str_has_prefix(p, "&gt;")) {
37                                 res+=">";
38                                 p+=3;
39                         } else if (g_str_has_prefix(p, "&lt;")) {
40                                 res+="<";
41                                 p+=3;
42                         } else if (g_str_has_prefix(p, "&amp;")) {
43                                 res+="&";
44                                 p+=4;
45                         } else if (g_str_has_prefix(p, "&quot;")) {
46                                 res+="\"";
47                                 p+=5;
48                         } else
49                                 res+=*p;
50                         continue;
51                 }
52
53                 const char *next=strchr(p, '>');
54                 if (!next)
55                         continue;
56
57                 std::string name(p+1, next-p-1);
58
59                 if (name=="abr")
60                         res+="";
61                 else if (name=="/abr")
62                         res+="";
63                 else if (name=="k") {
64                         const char *begin=next;
65                         if ((next=strstr(begin, "</k>"))!=NULL)
66                                 next+=sizeof("</k>")-1-1;
67                         else
68                                 next=begin;
69                 } else if (name=="b")
70                         res+="";
71                 else if (name=="/b")
72                         res+="";
73                 else if (name=="i")
74                         res+="";
75                 else if (name=="/i")
76                         res+="";
77                 else if (name=="tr")
78                         res+="[";
79                 else if (name=="/tr")
80                         res+="]";
81                 else if (name=="ex")
82                         res+="";
83                 else if (name=="/ex")
84                         res+="";
85                 else if (!name.empty() && name[0]=='c' && name!="co") {
86                         std::string::size_type pos=name.find("code");
87                         if (pos!=std::string::size_type(-1)) {
88                                 pos+=sizeof("code=\"")-1;
89                                 std::string::size_type end_pos=name.find("\"");
90                                 std::string color(name, pos, end_pos-pos);
91                                 res+="";
92                         } else {
93                                 res+="";
94                         }
95                 } else if (name=="/c")
96                         res+="";
97
98                 p=next;
99         }
100         return res;
101 }
102
103 static string parse_data(const gchar *data)
104 {
105         if (!data)
106                 return "";
107
108         string res;
109         guint32 data_size, sec_size=0;
110         gchar *m_str;
111         const gchar *p=data;
112         data_size=*((guint32 *)p);
113         p+=sizeof(guint32);
114         while (guint32(p - data)<data_size) {
115                 switch (*p++) {
116                 case 'g':
117                 case 'm':
118                 case 'l': //need more work...
119                         sec_size = strlen(p);
120                         if (sec_size) {
121                                 res+="\n";
122                                 m_str = g_strndup(p, sec_size);
123                                 res += m_str;
124                                 g_free(m_str);
125                         }
126                         sec_size++;
127                         break;
128                 case 'x':
129                         sec_size = strlen(p);
130                         if (sec_size) {
131                                 res+="\n";
132                                 m_str = g_strndup(p, sec_size);
133                                 res += xdxf2text(m_str);
134                                 g_free(m_str);
135                         }
136                         sec_size++;
137                         break;
138                 case 't':
139                         sec_size = strlen(p);
140                         if(sec_size){
141                                 res+="\n";
142                                 m_str = g_strndup(p, sec_size);
143                                 res += "["+string(m_str)+"]";
144                                 g_free(m_str);
145                         }
146                         sec_size++;
147                         break;
148                 case 'y':
149                         sec_size = strlen(p);
150                         sec_size++;                             
151                         break;
152                 case 'W':
153                 case 'P':
154                         sec_size=*((guint32 *)p);
155                         sec_size+=sizeof(guint32);
156                         break;
157                 }
158                 p += sec_size;
159         }
160
161         return res;
162 }
163
164 void Library::ListWords(CurrentIndex* iIndex)
165 {
166         CurrentIndex *iCurrent = (CurrentIndex*)g_memdup(iIndex, sizeof(CurrentIndex)*query_dictmask.size());
167
168         pMStarDict->ResultsListClear();
169
170         int iWordCount=0;
171         const gchar * poCurrentWord = poGetCurrentWord(iIndex, query_dictmask, 0);
172         if (poCurrentWord) {
173                 pMStarDict->ResultsListInsertLast(poCurrentWord);
174                 iWordCount++;
175
176                 while (iWordCount < 30 && (poCurrentWord = poGetNextWord(NULL, iIndex, query_dictmask, 0))) {
177                         pMStarDict->ResultsListInsertLast(poCurrentWord);
178                         iWordCount++;
179                 }
180         }
181         pMStarDict->ReScroll();
182
183         if (iCurrent)
184                 g_free (iCurrent);
185 }
186
187 bool Library::BuildResultData(std::vector<InstantDictIndex> &dictmask, const char* sWord, CurrentIndex *iIndex, int iLib, TSearchResultList& res_list)
188 {
189         int iRealLib;
190         bool bFound = false, bLookupWord = false, bLookupSynonymWord = false;
191         gint nWord=0, count=0, i=0, j=0;
192
193         iRealLib = dictmask[iLib].index;
194
195         bLookupWord = LookupWord(sWord, iIndex[iLib].idx, iIndex[iLib].idx_suggest, iRealLib, 0);
196         if (!bLookupWord)
197                 bLookupWord = LookupSimilarWord(sWord, iIndex[iLib].idx, iIndex[iLib].idx_suggest, iRealLib, 0);
198         if (!bLookupWord)
199                 bLookupWord = SimpleLookupWord(sWord, iIndex[iLib].idx, iIndex[iLib].idx_suggest, iRealLib, 0);
200
201         bLookupSynonymWord = LookupSynonymWord(sWord, iIndex[iLib].synidx, iIndex[iLib].synidx_suggest, iRealLib, 0);
202         if (!bLookupSynonymWord)
203                 bLookupSynonymWord = LookupSynonymSimilarWord(sWord, iIndex[iLib].synidx, iIndex[iLib].synidx_suggest, iRealLib, 0);
204         if (!bLookupSynonymWord)
205                 bLookupSynonymWord = SimpleLookupSynonymWord(sWord, iIndex[iLib].synidx, iIndex[iLib].synidx_suggest, iRealLib, 0);
206
207         g_debug ("bookname: %s, iLib: %d, iRealLib: %d, str: %s", dict_name(iLib).c_str(), iLib, iRealLib, sWord);
208
209         if (bLookupWord || bLookupSynonymWord) {
210                 if (bLookupWord)
211                         nWord++;
212
213                 if (bLookupSynonymWord)
214                         nWord+=GetOrigWordCount(iIndex[iLib].synidx, iRealLib, false);
215
216                 if (bLookupWord) {
217                         count = GetOrigWordCount(iIndex[iLib].idx, iRealLib, true);
218                         for (i=0;i<count;i++) {
219                                 res_list.push_back(TSearchResult(dict_name(iLib),
220                                                                  poGetWord(iIndex[iLib].idx, iRealLib, 0),
221                                                                  parse_data(poGetOrigWordData(iIndex[iLib].idx+i, iRealLib))));
222                         }
223                         i = 1;
224                 } else {
225                         i = 0;
226                 }
227                 for (j = 0; i < nWord; i++, j++) {
228                                 res_list.push_back(TSearchResult(dict_name(iLib),
229                                                                  poGetWord(iIndex[iLib].synidx+j, iRealLib, 0),
230                                                                  parse_data(poGetOrigWordData(iIndex[iLib].synidx+j, iRealLib))));
231                 }
232
233                 bFound = true;
234         }
235
236         return bFound;
237 }
238
239 bool Library::SimpleLookup(const gchar* sWord, CurrentIndex* piIndex)
240 {
241         CurrentIndex *iIndex;
242         TSearchResultList results;
243         bool bFound = false;
244
245         if (!piIndex)
246                 iIndex = (CurrentIndex *)g_malloc(sizeof(CurrentIndex) * query_dictmask.size());
247         else
248                 iIndex = piIndex;
249
250         for (size_t iLib=0; iLib<query_dictmask.size(); iLib++) {
251                 bFound = BuildResultData(query_dictmask, sWord, iIndex, iLib, results);
252         }
253
254         if (!piIndex)
255                 g_free(iIndex);
256
257         return bFound;
258 }
259
260 void Library::LookupWithFuzzy(const gchar* sWord)
261 {
262         static const int MAX_FUZZY_MATCH_ITEM=100;
263         gchar *fuzzy_reslist[MAX_FUZZY_MATCH_ITEM];
264         bool bFound = false;
265
266         pMStarDict->ResultsListClear();
267
268         bFound = Libs::LookupWithFuzzy(sWord, fuzzy_reslist, MAX_FUZZY_MATCH_ITEM, query_dictmask);
269         if (bFound) {
270                 SimpleLookup(fuzzy_reslist[0], iCurrentIndex);
271
272                 for (int i=0; i<MAX_FUZZY_MATCH_ITEM && fuzzy_reslist[i]; i++) {
273                         pMStarDict->ResultsListInsertLast(fuzzy_reslist[i]);
274                         g_free(fuzzy_reslist[i]);
275                 }
276                 pMStarDict->ReScroll();
277         }
278 }
279
280 void Library::LookupWithRule(const gchar* sWord)
281 {
282         gint iMatchCount=0;
283         gchar **ppMatchWord = (gchar **)g_malloc(sizeof(gchar *) * (MAX_MATCH_ITEM_PER_LIB) * query_dictmask.size());
284
285         pMStarDict->ResultsListClear();
286
287         iMatchCount=Libs::LookupWithRule(sWord, ppMatchWord, query_dictmask);
288         if (iMatchCount) {
289                 for (gint i=0; i<iMatchCount; i++)
290                         pMStarDict->ResultsListInsertLast(ppMatchWord[i]);
291
292                 SimpleLookup(ppMatchWord[0], iCurrentIndex);
293                 pMStarDict->ReScroll();
294
295                 for(gint i=0; i<iMatchCount; i++)
296                         g_free(ppMatchWord[i]);
297         }
298         g_free(ppMatchWord);
299 }
300
301 void Library::LookupData(const string &str, TSearchResultList& res_list)
302 {
303         bool cancel = false;
304         std::vector<gchar *> drl[query_dictmask.size()];
305         if (!Libs::LookupData(str.c_str(), drl, NULL, NULL, &cancel, query_dictmask))
306                 return;
307         for (size_t iLib=0; iLib<query_dictmask.size(); iLib++)
308                 for (std::vector<gchar *>::size_type j=0; j<drl[iLib].size(); ++j) {
309 //                      SimpleLookup(drl[iLib][j], res_list);
310                         g_free(drl[iLib][j]);
311                 }
312 }
313
314 Library::Library () : Libs (NULL, FALSE, 0, 0)
315 {
316         iCurrentIndex = NULL;
317 }
318
319 Library::~Library ()
320 {
321         if (iCurrentIndex)
322                 g_free (iCurrentIndex);
323 }