Added sqlite3 bookmarks
[mdictionary] / src / bookmarks / sql3 / src / engine_bookmark.c
1 /******************************************************************************
2 This file is part of WhiteStork.
3
4 WhiteStork 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 2 of the License, or
7 (at your option) any later version.
8
9 WhiteStork 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.
13
14 You should have received a copy of the GNU General Public License 
15 along with WhiteStork; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18 Copyright 2006 ComArch S.A.
19 ******************************************************************************/
20
21 // header with data structure and function definition for XDXF engine.
22 // Also Engine API. 
23 #include <engine_bookmark.h>
24 //------------------------------------------------------------------------------
25
26 #ifndef NOLOGS
27 #include <glib/gstdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #endif
31
32 #define LOGS g_debug
33
34 /*inline void LOGS(gchar* frm, ...) {
35 #ifndef NOLOGS
36         //g_printf(frm);
37 #endif
38 }*/
39
40 //==============================================================================
41 //==============================================================================
42 //==============================================================================
43 //-------------------------------------- FUNCTION FROM API 0.2 !!!
44 //==============================================================================
45 int get_id(void* data,int n,char** argv,char** names) {
46         int len = strlen(&(argv[0][0]));
47         memcpy(data,&(argv[0][0]), len);
48         gchar* tmp = (gchar*)data;
49         tmp[len] = 0;
50         return 0;
51 }
52
53 gboolean bm_engine_add_word(Engine* engine,
54                          gchar*  word,
55                          gchar*  translation) {
56         gint sql_res = 0;
57         gchar* err = NULL;
58         gboolean result = TRUE;
59         gchar* sql = NULL;
60
61         LOGS("Bookmark/%s->%s() called. Param\nEngine at address: %p\n"
62              "word: %s\ntranslation address: %p\n",
63              (gchar*)__FILE__,
64              (gchar*)__FUNCTION__,
65              engine,
66              word,
67              translation
68             );
69         g_assert(engine != NULL);
70         g_assert(word != NULL);
71         g_assert(translation != NULL);
72
73         // start timer for this function
74         timer(TIMER_START, (gchar*)(gchar*)__FUNCTION__);
75
76         BookData* data = (BookData*)(engine->engine_data);
77         sql = sqlite3_mprintf(
78                 "INSERT INTO translations VALUES(NULL, '%q', '%q');",
79                 word, translation);
80         sql_res = sqlite3_exec(data->db, sql, NULL, NULL, &err);
81         if(err || sql_res!=0) {
82                 LOGS("Error while adding translation for word %s \nreason:%s\n\n", word, err);
83                 result = FALSE;
84         } 
85         sqlite3_free(sql); sql = NULL;
86
87         timer(TIMER_STOP, (gchar*)(gchar*)__FUNCTION__);
88         return result;
89 }
90 //------------------------------------------------------------------------------
91 gboolean bm_engine_remove_word(Engine* engine, gchar*  word) {
92         gint sql_res = 0;
93         gchar* err = NULL;
94         gboolean result = TRUE;
95
96         LOGS("Bookmark/%s->%s() called. Param\nEngine at address: %p\n"
97              "word: %s\n",(gchar*)__FILE__,(gchar*)__FUNCTION__,engine,word);
98         g_assert(engine != NULL);
99         g_assert(word != NULL);
100         timer(TIMER_START, (gchar*)(gchar*)__FUNCTION__);
101
102         BookData* data = (BookData*)(engine->engine_data);
103         gchar* sql = sqlite3_mprintf(
104                 "DELETE FROM translations WHERE word LIKE '%q';", 
105                                 word);
106         sql_res = sqlite3_exec(data->db, sql, NULL, NULL, &err);
107         if(err || sql_res!=0) {
108                 LOGS("Error while deleting \'%s\' <-> reason:\n%s\n",word,err);
109                 sqlite3_free(sql); sql = NULL;
110                 return FALSE;
111         }
112         sqlite3_free(sql); sql = NULL;
113
114         timer(TIMER_STOP, (gchar*)(gchar*)__FUNCTION__);
115         return result;
116 }
117 //------------------------------------------------------------------------------      
118 gchar* bm_engine_get_lang_from(Engine* engine) {
119         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
120         gchar* result = g_strdup("any");
121         LOGS("Bookmark/%s->%s() return string=%s\n",
122                 (gchar*)__FILE__,
123                 (gchar*)__FUNCTION__,
124                 result
125                );
126         return result;
127 }
128 //------------------------------------------------------------------------------
129 gchar* bm_engine_get_lang_to(Engine* engine) {
130         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
131         gchar* result = g_strdup("any");
132         LOGS("Bookmark/%s->%s() return string=%s\n",
133                 (gchar*)__FILE__,
134                 (gchar*)__FUNCTION__,
135                 result
136                );
137         return result;
138 }
139 //------------------------------------------------------------------------------
140 gchar* bm_engine_get_title(Engine* engine) {
141         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
142         gchar* result = g_strconcat(g_get_user_name(),"s' bookmarks",NULL);
143         LOGS("Bookmark/%s->%s() return string=%s\n",
144                 (gchar*)__FILE__,
145                 (gchar*)__FUNCTION__,
146                 result
147                );
148         return result;
149 }
150 //------------------------------------------------------------------------------
151 gchar* bm_engine_get_icon_path(Engine* engine) {
152         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
153         gchar* result = g_strdup("/usr/share/pixmaps/ws_eng_bookmark_icon.png");
154         LOGS("Bookmark/%s->%s() return string=%s\n",
155                 (gchar*)__FILE__,
156                 (gchar*)__FUNCTION__,
157                 result
158                );
159         return result;
160 }
161
162 //==============================================================================
163 //==============================================================================
164 //==============================================================================
165 //-------------------------------------- FUNCTION TO WRITE (NOT IMPLEMENTED YET)
166 //==============================================================================
167
168 //------------------------------------------------------------------------------
169 // searching word by concrete engine
170 void bm_engine_search_word_translation(Engine* engine, gchar* word)
171 {
172         LOGS("Bookmark/%s->%s() called.\n-->PARAM:engine at adress=%p\n"
173              "-->PARAM:word=\'%s\'\n",
174              (gchar*)__FILE__,
175              (gchar*)__FUNCTION__,
176              engine,
177              word
178             );
179         g_assert(engine != NULL);
180         g_assert(word != NULL);
181         // start timer for this function
182         timer(TIMER_START, (gchar*)(gchar*)__FUNCTION__);
183         BookData* data = (BookData*)(engine->engine_data);
184         gchar* tmp = g_utf8_strdown(word,-1);
185         //sqlite3_vm* query;
186         gchar* sql = NULL;
187         gchar* tran = NULL;
188         sqlite3_stmt *query;//ppStmt
189         const char *pzTail;
190 /*
191         sql = g_strconcat("SELECT * FROM translations WHERE "
192                           "word_id=(SELECT id FROM words WHERE word=\'",
193                           tmp,
194                           "\');",
195                           NULL);
196 */
197
198         /*sql = g_strconcat("SELECT * FROM translations WHERE word LIKE \'",
199                           tmp,
200                           "\';",
201                           NULL);*/
202         
203         sql = sqlite3_mprintf(
204                         "SELECT * FROM translations WHERE word LIKE '%q';",
205                         tmp);   
206         
207         g_debug("Query text: %s", sql);
208         gint sql_res = 0;
209        // const gchar* end;
210        //gchar* err = NULL;
211         sql_res = sqlite3_prepare(
212                         data->db,/* Database handle */
213                         (const gchar *)sql,/* SQL statement, UTF-8 encoded */
214                         -1,/* Length of zSql in bytes. */
215                         &query,/* OUT: Statement handle */
216                         &pzTail/* OUT: Pointer to unused portion of zSql */
217                         );
218         if (sql_res != SQLITE_OK)
219         {
220                  LOGS("Error while compiling query:\n%s\nreason: %d\n",sql, sql_res);
221                  sqlite3_free(sql); sql = NULL;
222                  data->cb_search_word_trans(NULL, NULL, 
223                                         data->cb_search_word_trans_data,
224                                         ENGINE_NO_ERROR);
225                  return;
226         }
227         gint status = 0;
228         gboolean first = TRUE;
229         do { 
230                 first = TRUE;
231                 do {
232                         if(!first) sleep(1);
233                         first = FALSE;
234                         status = sqlite3_step(query);
235                         if(status == SQLITE_ROW) {
236                                 if (tran != NULL){
237                                         tran = g_strconcat(tran,"<BR><BR>", 
238                                                 sqlite3_column_text(query, 2),
239                                                 NULL);  
240                                 }else{
241                                         tran = g_strdup_printf("%s <BR><BR>",
242                                                 sqlite3_column_text(query, 2));
243                                 }
244                                 LOGS("Translation found :\n\"%s\"\n",tran);
245                                 
246                         }
247                 } while((status == SQLITE_BUSY) && (status != SQLITE_ERROR));
248         } while((status == SQLITE_ROW) && (status != SQLITE_ERROR));
249         sqlite3_finalize(query);
250
251         
252         timer(TIMER_STOP,(gchar*)(gchar*)__FUNCTION__);
253         timer(TIMER_START,"callback for returning word's translation START");
254         // calling callback for word translation
255
256         data->cb_search_word_trans(tran, word, data->cb_search_word_trans_data,
257                  ENGINE_NO_ERROR);
258         sqlite3_free(sql); sql = NULL;
259         timer(TIMER_STOP,"callback for returning word's translation END");
260         if(data->auto_free) {
261                 LOGS("Bookmark/%s->%s() deleting all dynamic data because "
262                      "AUTO_FREE=TRUE\n",
263                      (gchar*)__FILE__,
264                      (gchar*)__FUNCTION__
265                     );
266                 g_free(tran);
267         }
268         tran = NULL;
269 }
270
271 //------------------------------------------------------------------------------
272 void bm_engine_close(Engine* engine)
273 {
274         LOGS("Bookmark/%s->%s() called.\n-->PARAM: engine adress=%p\n",
275                 (gchar*)__FILE__,
276                 (gchar*)__FUNCTION__,
277                 engine);
278         g_assert(engine != NULL);
279         
280         BookData* data = (BookData*)(engine->engine_data);
281         sqlite3_close(data->db);
282         
283         LOGS("Bookmark/%s->%s() engine at adress=%p is deleted.\n",
284                 (gchar*)__FILE__,
285                 (gchar*)__FUNCTION__,
286                 engine);
287         g_free(engine);
288         engine = NULL;
289 }
290 //------------------------------------------------------------------------------
291
292 Engine* bm_engine_create(gchar* location,
293                       EngineOptimizationFlag auto_cache,
294                       cb_progress progress_handler,
295                       gpointer progress_data,
296                       gdouble seed)
297 {
298         LOGS("Bookmark/%s->%s() called.\n"
299              "-->PARAM:location=\'%s\'\n"
300              "-->PARAM:auto_cache=%d\n",
301              (gchar*)__FILE__,
302              (gchar*)__FUNCTION__,
303              location,
304              (guint)auto_cache
305             );
306         timer(TIMER_START,(gchar*)(gchar*)__FUNCTION__);        
307
308         gchar* tmp = g_strdup(location);
309         string_to_path(&tmp);
310
311         Engine* result = (Engine*)g_try_malloc(sizeof(Engine));
312         result->engine_location = bm_engine_location;
313         result->engine_is_optimized = bm_engine_is_optimized;
314         result->engine_optimize = bm_engine_optimize;
315         result->engine_search_word_list = bm_engine_search_word_list;
316         result->engine_search_word_translation = 
317                         bm_engine_search_word_translation;        
318         result->engine_close = bm_engine_close;
319         result->engine_status = bm_engine_status;
320         result->engine_error_message = bm_engine_status_message;
321         result->engine_set_callback = bm_engine_set_callback;
322         result->engine_set_progress_seed = bm_engine_set_progress_seed;
323         result->engine_set_auto_free = bm_engine_set_auto_free;
324         // 0.2 API:
325         result->engine_add_word = bm_engine_add_word;
326         result->engine_remove_word = bm_engine_remove_word;
327         result->engine_get_lang_from = bm_engine_get_lang_from;
328         result->engine_get_lang_to = bm_engine_get_lang_to;
329         result->engine_get_title = bm_engine_get_title;
330         result->engine_get_icon_path = bm_engine_get_icon_path;
331
332
333         BookData* data = (BookData*)g_try_malloc(sizeof(BookData));
334         result->engine_data = (gpointer)data;
335
336         LOGS("Bookmark/%s->%s() opening file...\'%s\'.\n",
337              (gchar*)__FILE__,
338              (gchar*)__FUNCTION__,
339              location
340             );
341         gchar* tmp2 = g_strconcat(tmp,"/ws_bookmarks3",NULL);
342         //gchar* err;
343         gint res = sqlite3_open(tmp2,&data->db);
344         g_free(tmp2); tmp2 = NULL;
345         if(res != SQLITE_OK) {
346                 LOGS("Bookmark/%s->%s() opening bookmark file failed.%s\n",
347                      (gchar*)__FILE__,
348                      (gchar*)__FUNCTION__,
349                      sqlite3_errmsg(data->db)
350                     );
351                 //g_free(err);
352                 g_free(data);
353                 g_free(result);
354                 result = NULL;
355         }
356         else {
357                 LOGS("Bookmark/%s->%s()opening dictionary file successed.\n",
358                         (gchar*)__FILE__,
359                         (gchar*)__FUNCTION__
360                        );
361                 data->dict_path = g_strdup(tmp);
362                 data->cb_progress_caching = progress_handler;
363                 data->cb_progress_caching_data = progress_data;        
364                 data->cb_progress_caching_seed = seed;        
365                 data->cb_progress_word_list = NULL;
366                 data->cb_progress_word_list_data = NULL;
367                 data->cb_progress_word_list_seed = 0.01;
368                 data->cb_progress_word_trans = NULL;
369                 data->cb_progress_word_trans_data = NULL;
370                 data->cb_progress_word_trans_seed = 0.01;
371
372                 data->cb_search_word_list = NULL;
373                 data->cb_search_word_list_data = NULL;
374
375                 data->cb_search_word_trans = NULL;
376                 data->cb_search_word_trans_data = NULL;
377
378                 data->auto_free = FALSE;
379                 // there is no cache mechanizm in bookmarks
380         }
381         g_free(tmp); tmp = NULL;
382         
383         timer(TIMER_STOP,(gchar*)(gchar*)__FUNCTION__);
384         LOGS("Bookmark/%s->%s() returned Engine at adress=%p\n",
385              (gchar*)__FILE__,
386              (gchar*)__FUNCTION__,
387              result
388             );
389         return result;
390 }
391 //------------------------------------------------------------------------------
392
393
394
395 static gboolean is_Bookmark_file(gchar* file) {
396         LOGS("Bookmark/%s->%s() called.\n\
397                  -->PARAM:file=\'%s\'\n",
398                  (gchar*)__FILE__,
399                  (gchar*)__FUNCTION__,
400                  file
401                );
402         gchar* err = NULL;
403         sqlite3* tmp = NULL;
404         gint result = sqlite3_open(file, &tmp);
405         if(result != SQLITE_OK) {
406                 LOGS("Wrong file! Not a sqlite database.\n");
407                 //g_free(err);
408                 sqlite3_close(tmp);
409                 return FALSE;
410         }
411
412         
413         gchar sql[] = "SELECT COUNT(word) FROM translations WHERE word=\'.\';";  
414         result = sqlite3_exec(tmp, sql, NULL, NULL, &err);
415         if(err || result!=0) {
416                 LOGS("Wrong database! Not a bookmark.\n");
417                 g_free(err);
418                 sqlite3_close(tmp);
419                 return FALSE;
420         }
421         sqlite3_close(tmp);
422         return TRUE;
423 }
424 //------------------------------------------------------------------------------
425
426
427 void bm_engine_optimize(Engine* engine)
428 {
429         LOGS("Bookmark/%s->%s() called for engine at adress=%p\n",
430              (gchar*)__FILE__,
431              (gchar*)__FUNCTION__,
432              engine
433             );
434         LOGS("Unsupported optimization mechanizm for this engine!\n");
435         LOGS("Bookmark/%s->%s()'s work finished.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
436 }
437 //------------------------------------------------------------------------------
438 gboolean bm_engine_check(gchar* location) 
439 {        
440         LOGS("Bookmark/%s->%s() called.\n-->PARAM:location=\'%s\'\n",
441              (gchar*)__FILE__,
442              (gchar*)__FUNCTION__,
443              location
444             );
445         timer(TIMER_START,(gchar*)(gchar*)__FUNCTION__);
446         gboolean result = TRUE;        
447         gchar* filepath = g_strdup(location);
448         gchar* tmp = NULL;
449         
450         string_to_path(&filepath);
451         if (filepath == NULL) {
452                 result = FALSE;
453                 LOGS("Bookmark/%s->%s() location \'%s\' is not a proper "
454                      "path!\n",
455                      (gchar*)__FILE__,
456                      (gchar*)__FUNCTION__,
457                      location
458                     );
459         }
460         else {
461                 tmp = g_strconcat(filepath,"/ws_bookmarks3",NULL);
462                 g_free(filepath);
463                 filepath = tmp;
464                 tmp = NULL;
465
466                 LOGS("Bookmark/%s->%s() finnal file to check is: %s\n",
467                      (gchar*)__FILE__,
468                      (gchar*)__FUNCTION__,
469                      filepath
470                     );
471                 if (!g_file_test(filepath, G_FILE_TEST_IS_REGULAR)) {
472                         LOGS("Bookmark/%s->%s() file \'%s\' does not exists!\n",
473                              (gchar*)__FILE__,
474                              (gchar*)__FUNCTION__,
475                              filepath
476                             );
477                         result = FALSE;
478                 };
479         };
480         if (result != FALSE) {
481                 result = is_Bookmark_file(filepath);
482         };
483
484         g_free(filepath);
485         timer(TIMER_STOP,(gchar*)(gchar*)__FUNCTION__);
486         LOGS("Bookmark/%s->%s() returned bool statement=%s.\n",
487              (gchar*)__FILE__,
488              (gchar*)__FUNCTION__,
489              PRINT_STATE(result)
490             );
491         return result;
492 }
493
494 //------------------------------------------------------------------------------
495 gboolean bm_engine_is_optimized(Engine* engine) 
496 {
497         LOGS("Bookmark/%s->%s() called.\n-->PARAM: engine adress=%p\n",
498              (gchar*)__FILE__,
499              (gchar*)__FUNCTION__,
500              engine
501             );
502         g_assert(engine != NULL);                
503         gboolean result = FALSE;
504         LOGS("Bookmark/%s->%s() returned bool statement=%s.\n",
505              (gchar*)__FILE__,
506              (gchar*)__FUNCTION__,
507              PRINT_STATE(result)
508             );
509         return result;
510 }
511 //------------------------------------------------------------------------------
512
513 void bm_engine_search_word_list(Engine* engine, gchar* pattern)
514 {
515         LOGS("Bookmark/%s->%s() called. Searching words list\n"
516              "-->PARAM:engine at adress=%p\n"
517              "-->PARAM:pattern=\"%s\"\n",
518              (gchar*)__FILE__,
519              (gchar*)__FUNCTION__,
520              engine,
521              pattern
522             );
523         g_assert(engine != NULL);
524         g_assert(pattern != NULL);
525
526         timer(TIMER_START,(gchar*)(gchar*)__FUNCTION__);
527         BookData* data = (BookData*)(engine->engine_data);
528         if(data->cb_search_word_list == NULL) {
529                 LOGS("Bookmark/%s->%s() callback for Word List not set. "
530                      "Searching aborted.\n",
531                      (gchar*)__FILE__,
532                      (gchar*)__FUNCTION__
533                     );
534                 timer(TIMER_STOP,(gchar*)(gchar*)__FUNCTION__);
535                 return;
536         };
537  
538
539         gchar* tmp = g_utf8_strdown(pattern,-1);
540         sqlite3_stmt *query;//ppStmt
541         const char *pzTail;
542         gchar* sql = NULL;
543         gchar* tran = NULL;
544         g_strstrip(tmp);
545         if ((int)(tmp[0]) == 42 && tmp[1] == '\0') //asterix?
546         {
547                 sql = sqlite3_mprintf("SELECT DISTINCT word FROM translations;");
548         }
549         else
550         {
551                 sql = sqlite3_mprintf(
552                 "SELECT DISTINCT word FROM translations WHERE word LIKE'%q%%';", tmp);
553         }
554         /*sql = g_strconcat("SELECT word FROM translations WHERE "
555                           "word LIKE \'",tmp,"\%\';",NULL);*/
556         LOGS("QUERY: %s\n",sql);
557         gint sql_res = 0;
558         sql_res = sqlite3_prepare(
559                         data->db,/* Database handle */
560                         (const gchar *)sql,/* SQL statement, UTF-8 encoded */
561                         -1,/* Length of zSql in bytes. */
562                         &query,/* OUT: Statement handle */
563                         &pzTail/* OUT: Pointer to unused portion of zSql */
564                         );
565         if (sql_res != SQLITE_OK)
566         {
567                 LOGS("Error while compiling query:\n%s\nreason:%d\n",sql,
568                                                                 sql_res);
569                 sqlite3_free(sql); sql = NULL;
570                 return;
571         }
572         gint status = 0;
573         gboolean first = TRUE;
574         GArray* result = g_array_new(TRUE, TRUE, sizeof(gchar*) );
575         do { 
576                 first = TRUE;
577                 do {
578                         if(!first) sleep(1);
579                         first = FALSE;;
580                         /*status = sqlite3_step(
581                                         query, 
582                                         &nCol,            
583                                         &values,  
584                                         &head 
585                                         );*/
586                         status = sqlite3_step(query);
587                         if(status == SQLITE_ERROR) {
588                                 LOGS("Error while making next step\n");
589                                 sqlite3_free(sql); sql = NULL;
590                                 data->cb_search_word_list(NULL , NULL, 
591                                 data->cb_search_word_list_data, ENGINE_NO_ERROR);
592                                 return;
593                         };
594                         /*if(status == SQLITE_ROW) {
595                                 LOGS("Fount new word: \"%s\"\n",&(values[0][0]));
596                                 gchar* tmp = g_strdup((gchar*)&(values[0][0]));
597                                 g_array_append_val(result, tmp );        
598                         }*/
599                         if(status == SQLITE_ROW) {
600                                 gchar* tmp = g_strdup(
601                                                 sqlite3_column_text(query, 0));
602                                 LOGS("Found new word: \"%s\"\n", tmp);
603                                 g_array_append_val(result, tmp);
604                         }
605                 } while((status == SQLITE_BUSY) && (status != SQLITE_ERROR));
606         } while((status == SQLITE_ROW) && (status != SQLITE_ERROR));
607         sqlite3_finalize(query);
608         timer(TIMER_STOP,(gchar*)(gchar*)__FUNCTION__);
609
610
611         timer(TIMER_START,"callback for returning words LIST START");
612         // calling callback for word translation
613
614         data->cb_search_word_list(result , pattern, 
615                         data->cb_search_word_list_data, ENGINE_NO_ERROR);
616                 
617         timer(TIMER_STOP,"callback for returning word LIST END");
618         if(data->auto_free) {
619                 LOGS("Bookmark/%s->%s() deleting all dynamic data because "
620                      "AUTO_FREE=TRUE\n",
621                      (gchar*)__FILE__,
622                      (gchar*)__FUNCTION__
623                     );
624                 g_free(tran);
625         }
626 }
627
628 //==============================================================================
629 //==============================================================================
630 //==============================================================================
631 //---------------------------------------------------------- COMPLETED FUNCTIONS
632 //==============================================================================
633 // global functions
634 EngineModule engine_global_functions()
635 {
636         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
637         EngineModule* result = g_try_new(EngineModule, 1);        
638         result->engine_check             = bm_engine_check;
639         result->engine_description       = bm_engine_description;
640         result->engine_format            = bm_engine_format;
641         result->engine_version           = bm_engine_version;
642         result->engine_create            = bm_engine_create;
643         LOGS("Bookmark/%s->%s()returned EngineModule at adress=%p.\n",
644              (gchar*)__FILE__,
645              (gchar*)__FUNCTION__,
646              result
647             );
648         return *result;
649 }
650 //------------------------------------------------------------------------------
651 // for macro: dict_eng_status_message(error)
652 gchar* bm_engine_status_message(EngineStatus error) 
653 {
654         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
655         switch (error) {
656                 case ENGINE_NO_ERROR:
657                         return "No error.";
658                 case ENGINE_WRONG_FILE:
659                         return "File which You are trying to use is wrong type.";
660                 case ENGINE_COULDNT_READ:
661                         return "Could not read from file.";
662                 case ENGINE_NO_FILE:
663                         return "There is no such a file.";
664                 case ENGINE_OUT_OF_MEMORY:
665                         return "There were no enough memory for this action.";
666                 default:
667                         return "Wrong engine's status identifier!";
668         }
669 }
670 //------------------------------------------------------------------------------
671 // for macro: dict_eng_module_get_version(module)
672 gchar* bm_engine_version() 
673 {
674         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
675         gchar* result = g_strdup(DIC_ENG_VERSION);
676         LOGS("Bookmark/%s->%s() return string=%s\n",
677                 (gchar*)__FILE__,
678                 (gchar*)__FUNCTION__,
679                 result
680                );
681         return result;
682 }
683 //------------------------------------------------------------------------------
684 // for macro: dict_eng_module_get_format(module)
685 gchar* bm_engine_format() 
686 {
687         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
688         gchar* result = g_strdup(DIC_ENG_FORMAT);
689         LOGS("Bookmark/%s->%s() return string=%s\n",
690              (gchar*)__FILE__,
691              (gchar*)__FUNCTION__,
692              result
693             );
694         return result;
695 }
696 //------------------------------------------------------------------------------
697 // for macro: dict_eng_module_get_description(module)
698 gchar* bm_engine_description() 
699 {
700         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
701         gchar* result = g_strdup(DIC_ENG_DESCRIPTION);
702         LOGS("Bookmark/%s->%s() return string=%s\n",
703              (gchar*)__FILE__,
704              (gchar*)__FUNCTION__,
705              result
706             );
707         return result;
708 }
709 //------------------------------------------------------------------------------
710 // for macro: dict_eng_get_location(engine)
711 gchar* bm_engine_location(Engine* engine)
712 {
713         LOGS("Bookmark/%s->%s() called.\n-->PARAM: engine adress=%p\n",
714              (gchar*)__FILE__,
715              (gchar*)__FUNCTION__,
716              engine
717             );
718         g_assert(engine != NULL);
719         BookData* data = (BookData*)(engine->engine_data);
720         
721         gchar* result;
722         if(data->auto_free) {
723                 result = data->dict_path;
724         }
725         else {
726                 result = g_strdup(data->dict_path);
727         }
728
729         LOGS("Bookmark/%s->%s() returned string=%s\n",
730              (gchar*)__FILE__,
731              (gchar*)__FUNCTION__,
732              result
733             );
734         return result;
735 }
736 //------------------------------------------------------------------------------
737 // for macro: dict_eng_set_auto_free(engine, state)
738 void bm_engine_set_auto_free(Engine* engine, gboolean state) 
739 {
740         LOGS("Bookmark/%s->%s() called.\n"
741              "-->PARAM:engine at adress=%p\n"
742              "-->PARAM:state=%s\n",
743              (gchar*)__FILE__,
744              (gchar*)__FUNCTION__,
745              engine,
746              PRINT_STATE(state)
747             );
748         g_assert(engine != NULL);
749         BookData* data = (BookData*)(engine->engine_data);
750         
751         data->auto_free = state;
752         LOGS("Bookmark/%s->%s() Current auto_free is %s\n",
753              (gchar*)__FILE__,
754              (gchar*)__FUNCTION__,
755              PRINT_STATE(data->auto_free)
756             );
757 }
758 //------------------------------------------------------------------------------
759 // for macro: dict_eng_get_last_status(engine)
760 EngineStatus bm_engine_status(Engine* engine) 
761 {
762         LOGS("Bookmark/%s->%s() called.\n"
763                 "-->PARAM:engine at adress=%p\n",
764                 (gchar*)__FILE__,
765                 (gchar*)__FUNCTION__,
766                engine
767                );
768         BookData* data = (BookData*)(engine->engine_data);
769         LOGS("Bookmark/%s->%s() returned error code: %d\n",
770              (gchar*)__FILE__,
771              (gchar*)__FUNCTION__,
772              (gint)(data->last_error)
773             );        
774         return data->last_error;
775 }
776 //------------------------------------------------------------------------------
777 // for macro: dict_eng_set_progress_seed(engine, signal, val)
778 void bm_engine_set_progress_seed(Engine* engine, gchar* signal, gdouble seed) {
779         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
780         BookData* data = (BookData*)(engine->engine_data);
781         if(g_ascii_strcasecmp(signal,ENGINE_PROGRESS_OPTIMIZING_SIGNAL) == 0)  {
782                 data->cb_progress_caching_seed = seed;
783                 LOGS("Bookmark/%s->%s() sets new seed=%0.2f for for signal "
784                      "\"%s\".\n",
785                      (gchar*)__FILE__,
786                      (gchar*)__FUNCTION__,
787                      seed,
788                      signal
789                     );        
790         } 
791         else {
792                 LOGS("Bookmark/%s->%s() unsupported signalfor progress: %s.\n",
793                      (gchar*)__FILE__,
794                      (gchar*)__FUNCTION__,
795                      signal
796                     );
797         };
798 }
799 //------------------------------------------------------------------------------
800 // for macro: dict_eng_set_callback(engine,signal,c_handler,data)
801 gpointer bm_engine_set_callback(Engine* engine,
802                              gchar* signal,
803                              gpointer c_handler,
804                              gpointer user_data)
805 {
806         LOGS("Bookmark/%s->%s() called.\n",(gchar*)__FILE__,(gchar*)__FUNCTION__);
807         g_assert(engine != NULL);
808         g_assert(signal != NULL);
809         g_assert(c_handler != NULL);
810         BookData* data = (BookData*)(engine->engine_data);
811         if(g_ascii_strcasecmp(signal,ENGINE_PROGRESS_OPTIMIZING_SIGNAL) == 0)  {
812                 gpointer result = data->cb_progress_caching;
813                 data->cb_progress_caching = c_handler;
814                 data->cb_progress_caching_data = user_data;
815                 LOGS("Bookmark/%s->%s() sets handler for signal \"%s\".\n",
816                         (gchar*)__FILE__,
817                         (gchar*)__FUNCTION__,
818                         signal
819                        );
820                 LOGS("Bookmark/%s->%s() Function at adress =  %d.\n",
821                         (gchar*)__FILE__,
822                         (gchar*)__FUNCTION__,
823                         (guint)c_handler
824                        );
825                 LOGS("Bookmark/%s->%s()     Data at adress =  %d.\n",
826                         (gchar*)__FILE__,
827                         (gchar*)__FUNCTION__,
828                         (guint)user_data
829                        );
830                 return result;                
831         }
832         else if(g_ascii_strcasecmp(signal, ENGINE_WORD_LIST_SIGNAL) == 0) {
833                 gpointer result = data->cb_search_word_list;
834                 data->cb_search_word_list = c_handler;
835                 data->cb_search_word_list_data = user_data;
836                 LOGS("Bookmark/%s->%s() sets handler for signal \"%s\".\n",
837                         (gchar*)__FILE__,
838                         (gchar*)__FUNCTION__,
839                         signal
840                        );
841                 LOGS("Bookmark/%s->%s() Function at adress =  %d.\n",
842                         (gchar*)__FILE__,
843                         (gchar*)__FUNCTION__,
844                         (guint)c_handler
845                        );
846                 LOGS("Bookmark/%s->%s()     Data at adress =  %d.\n",
847                         (gchar*)__FILE__,
848                         (gchar*)__FUNCTION__,
849                         (guint)user_data
850                        );
851                 return result;                        
852         }
853         else if(g_ascii_strcasecmp(signal,
854                 ENGINE_WORD_TRANSLATION_SIGNAL) == 0)  {
855                         gpointer result = data->cb_search_word_trans;
856                         data->cb_search_word_trans = c_handler;
857                         data->cb_search_word_trans_data = user_data;
858                         LOGS("Bookmark/%s->%s() sets handler for signal \"%s\".\n",
859                                 (gchar*)__FILE__,
860                                 (gchar*)__FUNCTION__,
861                                 signal
862                                );
863                         LOGS("Bookmark/%s->%s() Function at adress =  %d.\n",
864                                 (gchar*)__FILE__,
865                                 (gchar*)__FUNCTION__,
866                                 (guint)c_handler
867                                );
868                         LOGS("Bookmark/%s->%s()     Data at adress =  %d.\n",
869                                 (gchar*)__FILE__,
870                                 (gchar*)__FUNCTION__,
871                                 (guint)user_data
872                                );
873                         return result;                        
874                 }
875                 else {
876                         g_warning("Bookmark/%s->%s() unsupported signal: %s.\n",
877                                   (gchar*)__FILE__,
878                                   (gchar*)__FUNCTION__,
879                                   signal
880                                  );
881                         return NULL;
882                 }
883 }
884
885
886
887
888
889
890 //==============================================================================
891 //==============================================================================
892 //==============================================================================
893 //---------------------------------------------------------- HELPFULLY FUNCTIONS
894 //==============================================================================
895
896 //------------------------------------------------------------------------------
897 static gchar* string_to_path(gchar** string) {
898         LOGS("Bookmark/%s->%s() called.\n\
899                  -->PARAM:string=\'%s\'\n",
900                  (gchar*)__FILE__,
901                  (gchar*)__FUNCTION__,
902                  string[0]
903                );
904         gchar* arg = string[0];
905         gchar* new = NULL;
906         // cleaning from leading and trailing whitespaces
907         g_strstrip(arg);        
908          // add current directory if this is not absolute directory
909         if (!g_path_is_absolute(arg)) {
910                 gchar* tmp = g_get_current_dir();
911                 new = g_strconcat(tmp,"/",arg,NULL);
912                 g_free(arg); arg = new; new = NULL;
913         };
914         // this is not a directory
915         if (!g_file_test(arg, G_FILE_TEST_IS_DIR)) {        
916                 // if this is wrong filepath, string was wrong
917                 if (!g_file_test(arg, G_FILE_TEST_IS_REGULAR)) {        
918                         g_free(arg);
919                         new = NULL;
920                 }
921                 //if this is a file, remove filename
922                 else
923                 {   
924                         new = g_path_get_dirname (arg);
925                         g_free(arg);
926                 }
927         }
928         // this is a directory
929         else {   
930                 // remove suffix "/" if neded...     
931                 if (g_str_has_suffix(arg,"/") ) {        
932                         new = g_path_get_dirname (arg);
933                         g_free(arg);
934                 }
935                 else {
936                         new = arg;
937                 }
938         };
939         // now in new should be proper filepath, if not, string was wrong
940         if (!g_file_test(new, G_FILE_TEST_IS_DIR))  {        
941                 // if that directory does not exist, passed string wasn't proper       
942                 g_free(new);
943                 new = NULL;
944         };
945         // replace string under passed address
946         string[0] = new;
947         LOGS("Bookmark/%s->%s() returned string=\'%s\'\n",
948                 (gchar*)__FILE__,
949                 (gchar*)__FUNCTION__,
950                 string[0]
951                );
952         return new;
953 }
954 //------------------------------------------------------------------------------
955 static double timer(gboolean start, gchar* message)
956 {
957         static GArray* stack = NULL;
958         static gboolean first_run = TRUE;
959         static struct timeval actual_time;
960         static struct timeval last_time;
961         static struct timeval result;
962         static double seconds = 0.0;
963         if(first_run) {
964                 first_run = FALSE;
965                 stack = g_array_new(TRUE, TRUE, sizeof(struct timeval));
966         };        
967
968         if (start) {
969                 LOGS("Bookmark->%s() start timer for function '%s()'.\n",
970                         (gchar*)__FUNCTION__,
971                         message
972                        );
973                 g_array_prepend_val(stack, actual_time);
974                 gettimeofday(&g_array_index(stack, struct timeval, 0),NULL);
975                 return -1.0;
976         }
977         // we just want to end some timer - print some information about 
978         // working time;
979         else {          
980                 gettimeofday(&actual_time,NULL);
981                 last_time = g_array_index(stack, struct timeval, 0);
982                 g_array_remove_index(stack, 0);
983
984                 if (actual_time.tv_usec < last_time.tv_usec) {
985                         int nsec = (last_time.tv_usec - actual_time.tv_usec) / 
986                                         (1000000 + 1);
987                         last_time.tv_usec -= 1000000 * nsec;
988                         last_time.tv_sec += nsec;
989                 }
990                 if (actual_time.tv_usec - last_time.tv_usec > 1000000) {
991                         int nsec = (last_time.tv_usec - actual_time.tv_usec) / 
992                                         1000000;
993                         last_time.tv_usec += 1000000 * nsec;
994                         last_time.tv_sec -= nsec;
995                 }
996                 result.tv_sec = actual_time.tv_sec - last_time.tv_sec;
997                 result.tv_usec = actual_time.tv_usec - last_time.tv_usec;
998                 seconds = (((double)(result.tv_usec)) / 1e6) +
999                                 ((double)(result.tv_sec));
1000
1001                 LOGS("Bookmark->%s() function \'%s()\' was working for: %g "
1002                                 "[s] or %ld [us].\n",
1003                 (gchar*)__FUNCTION__,
1004                 message,
1005                 seconds,
1006                 ((long)(result.tv_sec*1e6)+(result.tv_usec))
1007                        );
1008                 // stack is empty so we delete everything
1009                 if(stack->len == 0)   
1010                 {
1011                         g_array_free(stack, TRUE);
1012                         first_run = TRUE;
1013                 }
1014         }
1015         return seconds;
1016 }
1017 //------------------------------------------------------------------------------
1018
1019
1020