1 /* StarDict - A international dictionary for GNOME.
2 * Copyright (C) 2003-2007 Hu Zheng <huzheng001@gmail.com>
3 * Copyright 2011 kubtek <kubtek@mail.com>
4 *
5 * This file is part of StarDict.
6 *
7 * StarDict is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * StarDict is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with StarDict. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /*
22 * Modified by the StarDict Team and others 2003-2006. See the AUTHORS
23 * file for a list of people on the StarDict Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * StarDict at http://www.stardict.org.
26 */
27
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <cstring>
34 #include <cstdlib>
35 #include <cerrno>
36 #include <glib/gstdio.h>
37 #include <glib/gi18n.h>
38 #include <gdk/gdkkeysyms.h>
39 #include <iostream>
40 #include <sstream>
41
42 #ifdef CONFIG_GNOME
43 # include <libgnome/libgnome.h>
44 #endif
45
46 #ifdef CONFIG_GNOME
47 # include <bonobo/bonobo-main.h>
48 # include "stardict-application-server.h"
49 # include "GNOME_Stardict.h"
50 #endif
51
52 #ifdef CONFIG_GPE
53 # include <gpe/init.h>
54 #endif
55
56 #ifdef CONFIG_MAEMO
57 #include "hildon-widgets/hildon-program.h"
58 #include "hildon-widgets/hildon-window.h"
59 #endif
60
61 #ifdef _WIN32
62 # include <gdk/gdkwin32.h>
63 # include <windows.h>
64 # include <io.h>
65 # include <fcntl.h>
66 # include "win32/intl.h"
67 #endif
68
69 #include "desktop.h"
70 #include "splash.h"
71 #include "conf.h"
72 #include "lib/utils.h"
73 #include "prefsdlg.h"
74 #include "iskeyspressed.h"
75 #include "class_factory.h"
76 #include "progresswin.h"
77 #include "dictmanagedlg.h"
78 #include "pluginmanagedlg.h"
79 #include "prefsdlg.h"
80 #include "lib/netdictcache.h"
81 #include "lib/full_text_trans.h"
82 #include "log.h"
83 #include "cmdlineopts.h"
84
85 #include "stardict.h"
86
87 AppCore *gpAppFrame;
88
89 /********************************************************************/
90 class change_cursor {
91 public:
change_cursor(GdkWindow * win_,GdkCursor * busy,GdkCursor * norm_)92 change_cursor(GdkWindow *win_,GdkCursor *busy, GdkCursor *norm_):
93 win(win_), norm(norm_) { gdk_window_set_cursor(win, busy); }
~change_cursor()94 ~change_cursor() { gdk_window_set_cursor(win, norm); }
95 private:
96 GdkWindow *win;
97 GdkCursor *norm;
98 };
99 /********************************************************************/
100 class gtk_show_progress_t : public show_progress_t {
101 public:
notify_about_work()102 void notify_about_work() { ProcessGtkEvent(); }
103 } gtk_show_progress;
104
105 /********************************************************************/
106 class reload_show_progress_t : public show_progress_t {
107 public:
reload_show_progress_t(progress_win & pw_)108 reload_show_progress_t(progress_win &pw_) : pw(pw_) {}
notify_about_start(const std::string & title)109 void notify_about_start(const std::string& title) {
110 pw.display_action(title);
111 }
notify_about_work()112 void notify_about_work() {
113 ProcessGtkEvent();
114 }
115 private:
116 progress_win &pw;
117 };
118
119 /********************************************************************/
120 class load_show_progress_t : public show_progress_t {
121 public:
notify_about_start(const std::string & title)122 void notify_about_start(const std::string& title) {
123 stardict_splash.display_action(title);
124 }
125 } load_show_progress;
126
127 /********************************************************************/
AppCore()128 AppCore::AppCore() :
129 oLibs(>k_show_progress,
130 conf->get_bool_at("dictionary/create_cache_file"),
131 conf->get_bool_at("dictionary/enable_collation") ? CollationLevel_SINGLE : CollationLevel_NONE,
132 int_to_colate_func(conf->get_int_at("dictionary/collate_function")))
133 {
134 iCurrentIndex = NULL;
135 word_change_timeout_id = 0;
136 window = NULL; //need by save_yourself_cb().
137 dict_manage_dlg = NULL;
138 plugin_manage_dlg = NULL;
139 prefs_dlg = NULL;
140 oStarDictPlugins = NULL;
141 }
142
~AppCore()143 AppCore::~AppCore()
144 {
145 stop_word_change_timer();
146 delete dict_manage_dlg;
147 delete plugin_manage_dlg;
148 delete prefs_dlg;
149 g_free(iCurrentIndex);
150 delete oStarDictPlugins;
151 // window?
152 }
153
on_change_scan(bool val)154 void AppCore::on_change_scan(bool val)
155 {
156 conf->set_bool_at("dictionary/scan_selection", val);
157 }
158
on_maximize()159 void AppCore::on_maximize()
160 {
161 if (oTopWin.get_text()[0]) {
162 //so user can input word directly.
163 gtk_widget_grab_focus(oMidWin.oTextWin.view->widget());
164 } else {
165 //this won't change selection text.
166 oTopWin.grab_focus();
167 }
168 }
169
on_docklet_middle_button_click()170 void AppCore::on_docklet_middle_button_click()
171 {
172 TNotifAreaMiddleClickAction action = TNotifAreaMiddleClickAction(
173 conf->get_int_at("notification_area_icon/middle_click_action"));
174 if (action == namclaQueryFloatWindow) {
175 oSelection.LastClipWord.clear();
176 gtk_selection_convert(oSelection.selection_widget,
177 GDK_SELECTION_PRIMARY,
178 oSelection.UTF8_STRING_Atom, GDK_CURRENT_TIME);
179 } else if(action == namclaQueryMainWindow){
180 oDockLet->maximize_from_tray();
181 gtk_selection_convert(oMidWin.oTextWin.view->widget(),
182 GDK_SELECTION_PRIMARY,
183 oSelection.UTF8_STRING_Atom, GDK_CURRENT_TIME);
184 }
185 }
186
on_link_click(const std::string & link)187 void AppCore::on_link_click(const std::string &link)
188 {
189 if (g_str_has_prefix(link.c_str(), "query://")) {
190 oTopWin.InsertHisList(oTopWin.get_text());
191 oTopWin.InsertBackList();
192 oTopWin.SetText(link.c_str() + sizeof("query://") -1);
193 } else if (g_str_has_prefix(link.c_str(), "bword://")) {
194 oTopWin.InsertHisList(oTopWin.get_text());
195 oTopWin.InsertBackList();
196 oTopWin.SetText(link.c_str() + sizeof("bword://") -1);
197 } else {
198 show_url(link.c_str());
199 }
200 }
201
do_send_http_request(const char * shost,const char * sfile,get_http_response_func_t callback_func,gpointer userdata)202 void AppCore::do_send_http_request(const char* shost, const char* sfile, get_http_response_func_t callback_func, gpointer userdata)
203 {
204 HttpClient *client = new HttpClient();
205 client->on_error_.connect(sigc::mem_fun(gpAppFrame, &AppCore::on_http_client_error));
206 client->on_response_.connect(sigc::mem_fun(gpAppFrame, &AppCore::on_http_client_response));
207 gpAppFrame->oHttpManager.Add(client);
208 client->SendHttpGetRequestWithCallback(shost, sfile, callback_func, userdata);
209 }
210
set_news(const char * news,const char * links)211 void AppCore::set_news(const char *news, const char *links)
212 {
213 gpAppFrame->oBottomWin.set_news(news, links);
214 }
215
show_netdict_resp(const char * dict,NetDictResponse * resp,bool ismainwin)216 void AppCore::show_netdict_resp(const char *dict, NetDictResponse *resp, bool ismainwin)
217 {
218 if (ismainwin)
219 gpAppFrame->oMidWin.oTextWin.Show(resp);
220 else {
221 if(gpAppFrame->composite_lookup_float_win.got_net_dict_responce(dict, resp->word))
222 gpAppFrame->oFloatWin.AppendTextNetDict(resp);
223 if(gpAppFrame->composite_lookup_float_win.is_got_all_responses())
224 gpAppFrame->oFloatWin.EndLookup();
225 }
226 }
227
lookup_dict(size_t dictid,const char * sWord,char **** Word,char ***** WordData)228 void AppCore::lookup_dict(size_t dictid, const char *sWord, char ****Word, char *****WordData)
229 {
230 InstantDictIndex instance_dict_index;
231 instance_dict_index.type = InstantDictType_LOCAL;
232 instance_dict_index.index = dictid;
233 std::vector<InstantDictIndex> dictmask;
234 dictmask.push_back(instance_dict_index);
235 bool bFound = false;
236 gchar ***pppWord = (gchar ***)g_malloc(sizeof(gchar **) * dictmask.size());
237 gchar ****ppppWordData = (gchar ****)g_malloc(sizeof(gchar ***) * dictmask.size());
238 CurrentIndex *iIndex = (CurrentIndex *)g_malloc(sizeof(CurrentIndex) * dictmask.size());
239 gpAppFrame->BuildResultData(dictmask, sWord, iIndex, NULL, 0, pppWord, ppppWordData, bFound, 2);
240 *Word = pppWord;
241 *WordData = ppppWordData;
242 g_free(iIndex);
243 }
244
ShowPangoTips(const char * word,const char * text)245 void AppCore::ShowPangoTips(const char *word, const char *text)
246 {
247 gpAppFrame->oFloatWin.ShowPangoTips(word, text);
248 }
249
Create(const gchar * queryword)250 void AppCore::Create(const gchar *queryword)
251 {
252 if (conf->get_bool_at("dictionary/use_custom_font")) {
253 const std::string &custom_font(conf->get_string_at("dictionary/custom_font"));
254
255 if (!custom_font.empty()) {
256 gchar *aa =
257 g_strdup_printf("style \"custom-font\" { font_name= \"%s\" }\n"
258 "class \"GtkWidget\" style \"custom-font\"\n",
259 custom_font.c_str());
260 #if GTK_MAJOR_VERSION >= 3
261 GtkCssProvider *css_provider = gtk_css_provider_get_default();
262 gtk_css_provider_load_from_data(css_provider, aa, -1, NULL);
263 #else
264 gtk_rc_parse_string(aa);
265 #endif
266 g_free(aa);
267 }
268 }
269
270 #ifdef CONFIG_MAEMO
271 HildonProgram *program;
272 program = HILDON_PROGRAM(hildon_program_get_instance());
273 g_set_application_name(_("StarDict"));
274 window = hildon_window_new();
275 hildon_program_add_window(program, HILDON_WINDOW(window));
276 #else
277 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
278 #endif
279
280 // Init oStarDictPlugins after we get window.
281 oStarDictPluginSystemInfo.datadir = conf_dirs->get_data_dir();
282 oStarDictPluginSystemInfo.mainwin = window;
283 oStarDictPluginSystemService.send_http_request = do_send_http_request;
284 oStarDictPluginSystemService.show_url = show_url;
285 oStarDictPluginSystemService.set_news = set_news;
286 oStarDictPluginSystemService.encode_uri_string = common_encode_uri_string;
287 oStarDictPluginSystemService.netdict_save_cache_resp = netdict_save_cache_resp;
288 oStarDictPluginSystemService.show_netdict_resp = show_netdict_resp;
289 oStarDictPluginSystemService.lookup_dict = lookup_dict;
290 oStarDictPluginSystemService.FreeResultData = FreeResultData;
291 oStarDictPluginSystemService.ShowPangoTips = ShowPangoTips;
292 std::list<DictItemId> plugin_new_install_list;
293 UpdatePluginList(plugin_new_install_list);
294 #ifdef _WIN32
295 std::list<std::string> plugin_order_list;
296 std::list<std::string> plugin_disable_list;
297 {
298 const std::list<std::string>& plugin_order_list_rel
299 = conf->get_strlist("/apps/stardict/manage_plugins/plugin_order_list");
300 const std::list<std::string>& plugin_disable_list_rel
301 = conf->get_strlist("/apps/stardict/manage_plugins/plugin_disable_list");
302 abs_path_to_data_dir(plugin_order_list_rel, plugin_order_list);
303 abs_path_to_data_dir(plugin_disable_list_rel, plugin_disable_list);
304 }
305 #else
306 const std::list<std::string>& plugin_order_list
307 = conf->get_strlist("/apps/stardict/manage_plugins/plugin_order_list");
308 const std::list<std::string>& plugin_disable_list
309 = conf->get_strlist("/apps/stardict/manage_plugins/plugin_disable_list");
310 #endif
311 oStarDictPlugins = new StarDictPlugins(conf_dirs->get_plugin_dir(),
312 plugin_order_list,
313 plugin_disable_list);
314
315 oLibs.set_show_progress(&load_show_progress);
316 std::list<DictItemId> dict_new_install_list;
317 bool verify_dict = conf->get_bool_at("dictionary/do_not_load_bad_dict");
318 UpdateDictList(dict_new_install_list, &load_show_progress, verify_dict);
319 UpdateConfigXML(dict_new_install_list, plugin_new_install_list, oStarDictPlugins);
320 LoadDictInfo();
321 {
322 std::list<DictItemId> load_list;
323 GetUsedDictList(load_list);
324 std::list<std::string> s_load_list;
325 DictItemId::convert(s_load_list, load_list);
326 oLibs.load(s_load_list);
327 }
328 oLibs.set_show_progress(>k_show_progress);
329
330 oStarDictClient.set_server(conf->get_string_at("network/server").c_str(), conf->get_int_at("network/port"));
331 const std::string &user = conf->get_string_at("network/user");
332 const std::string &md5passwd = conf->get_string_at("network/md5passwd");
333 if (!user.empty() && !md5passwd.empty()) {
334 oStarDictClient.set_auth(user.c_str(), md5passwd.c_str());
335 }
336 oStarDictClient.on_error_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_error));
337 oStarDictClient.on_lookup_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_lookup_end));
338 oStarDictClient.on_floatwin_lookup_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_floatwin_lookup_end));
339 oStarDictClient.on_register_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_register_end));
340 oStarDictClient.on_getdictmask_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_getdictmask_end));
341 oStarDictClient.on_getadinfo_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_getadinfo_end));
342 oStarDictClient.on_dirinfo_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_dirinfo_end));
343 oStarDictClient.on_dictinfo_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_dictinfo_end));
344 oStarDictClient.on_maxdictcount_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_maxdictcount_end));
345 oStarDictClient.on_previous_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_previous_end));
346 oStarDictClient.on_next_end_.connect(sigc::mem_fun(this, &AppCore::on_stardict_client_next_end));
347
348 UpdateDictMask();
349
350 gtk_container_set_border_width(GTK_CONTAINER(window),2);
351 bool maximized=conf->get_bool_at("main_window/maximized");
352
353 int width=conf->get_int_at("main_window/window_width");
354 int height=conf->get_int_at("main_window/window_height");
355
356 if (width < MIN_WINDOW_WIDTH)
357 width = MIN_WINDOW_WIDTH;
358 if (height < MIN_WINDOW_HEIGHT)
359 height = MIN_WINDOW_HEIGHT;
360 gtk_window_set_default_size (GTK_WINDOW(window), width, height);
361 if (maximized)
362 gtk_window_maximize(GTK_WINDOW(window));
363 int transparent=conf->get_int_at("main_window/transparent");
364 if (transparent != 0)
365 gtk_window_set_opacity(GTK_WINDOW(window), (100-transparent)/100.0);
366 gtk_window_set_title (GTK_WINDOW (window), _("StarDict"));
367 gtk_window_set_icon(GTK_WINDOW(window),
368 get_impl(oAppSkin.icon));
369 gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
370 g_signal_connect (G_OBJECT (window), "show", G_CALLBACK (on_mainwin_show_event), this);
371 g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (on_delete_event), this);
372 g_signal_connect (G_OBJECT (window), "window_state_event", G_CALLBACK (on_window_state_event), this);
373 g_signal_connect (G_OBJECT (window), "key_press_event", G_CALLBACK (vKeyPressReleaseCallback), this);
374 g_signal_connect (G_OBJECT (window), "key_release_event", G_CALLBACK (vKeyPressReleaseCallback), this);
375
376 #if GTK_MAJOR_VERSION >= 3
377 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
378 #else
379 GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
380 #endif
381 gtk_widget_show(vbox);
382 gtk_container_add(GTK_CONTAINER(window),vbox);
383 oTopWin.Create(vbox);
384 oMidWin.Create(vbox);
385 oBottomWin.Create(vbox);
386 unlock_keys.reset(static_cast<hotkeys *>(PlatformFactory::create_class_by_name("hotkeys",
387 GTK_WINDOW(window))));
388 unlock_keys->set_comb(combnum2str(conf->get_int_at("dictionary/scan_modifier_key")));
389 oFloatWin.Create();
390 bool scan=conf->get_bool_at("dictionary/scan_selection");
391 oDockLet.reset(PlatformFactory::create_tray_icon(window, scan,
392 oAppSkin));
393 oDockLet->on_quit_.connect(sigc::mem_fun(this, &AppCore::Quit));
394 oDockLet->on_change_scan_.connect(
395 sigc::mem_fun(this, &AppCore::on_change_scan));
396 oDockLet->on_maximize_.connect(
397 sigc::mem_fun(this, &AppCore::on_maximize));
398 oDockLet->on_middle_btn_click_.connect(
399 sigc::mem_fun(this, &AppCore::on_docklet_middle_button_click));
400 oSelection.Init();
401 #ifdef _WIN32
402 oClipboard.Init();
403 oMouseover.Init();
404 #endif
405 oHotkey.Init();
406 #ifdef ENABLE_LOG_WINDOW
407 gLogWindow.Init();
408 #endif
409
410 if (scan) {
411 oSelection.start();
412 #ifdef _WIN32
413 if (conf->get_bool_at("dictionary/scan_clipboard")) {
414 oClipboard.start();
415 }
416 oMouseover.start();
417 #endif
418 }
419 if (conf->get_bool_at("dictionary/use_scan_hotkey")) {
420 const std::string &hotkey = conf->get_string_at(
421 "dictionary/scan_hotkey");
422 oHotkey.start_scan(hotkey.c_str());
423 }
424 if (conf->get_bool_at("dictionary/use_mainwindow_hotkey")) {
425 const std::string &hotkey = conf->get_string_at(
426 "dictionary/mainwindow_hotkey");
427 oHotkey.start_mainwindow(hotkey.c_str());
428 }
429
430 bool hide=conf->get_bool_at("main_window/hide_on_startup");
431
432 //NOTICE: when docklet embedded failed,it should always show the window,but,how to detect the failure?
433 // As stardict is FOR GNOME,so i don't want to consider the case that haven't the Notification area applet.
434 if (!CmdLineOptions::get_hide() && (queryword || !hide)) {
435 oDockLet->hide_state();
436 gtk_widget_show(window);
437 } else {
438 // This may be needed, so gtk_window_get_screen() in gtk_iskeyspressed.cpp can always work.
439 gtk_widget_realize(window);
440 gdk_notify_startup_complete();
441 }
442
443 bool have_netdict = false;
444 for (size_t iLib=0; iLib<query_dictmask.size(); iLib++) {
445 if (query_dictmask[iLib].type == InstantDictType_NET) {
446 have_netdict = true;
447 break;
448 }
449 }
450 if (oLibs.has_dict() || conf->get_bool_at("network/enable_netdict") || have_netdict) {
451 if (queryword) {
452 Query(queryword);
453 } else {
454 oMidWin.oTextWin.ShowTips();
455 }
456 } else {
457 oMidWin.oTextWin.ShowInitFailed();
458 }
459 }
460
on_mainwin_show_event(GtkWidget * window,AppCore * app)461 void AppCore::on_mainwin_show_event(GtkWidget * window, AppCore *app)
462 {
463 static bool loaded = false;
464 if (!loaded) {
465 loaded = true;
466 // We need to set the hpaned position after the window showed, or it will become incorrect.
467 int pos=conf->get_int_at("main_window/hpaned_pos");
468 gtk_paned_set_position(GTK_PANED(app->oMidWin.hpaned), pos);
469 }
470 }
471
on_delete_event(GtkWidget * window,GdkEvent * event,AppCore * app)472 gboolean AppCore::on_delete_event(GtkWidget * window, GdkEvent *event , AppCore *app)
473 {
474 #ifdef CONFIG_DARWIN
475 gtk_window_iconify(GTK_WINDOW(window));
476 #else
477 app->oDockLet->minimize_to_tray();
478 #endif
479 return TRUE;
480 }
481
on_window_state_event(GtkWidget * window,GdkEventWindowState * event,AppCore * app)482 gboolean AppCore::on_window_state_event(GtkWidget *window,
483 GdkEventWindowState *event, AppCore *app)
484 {
485 switch (event->changed_mask) {
486 case GDK_WINDOW_STATE_WITHDRAWN:
487 if (conf->get_bool_at("dictionary/scan_selection"))
488 app->oDockLet->set_scan_mode(true);
489 else
490 app->oDockLet->set_scan_mode(false);
491 if (!(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN)) {
492 app->oDockLet->hide_state();
493 if (app->oTopWin.get_text()[0])
494 gtk_widget_grab_focus(app->oMidWin.oTextWin.view->widget());
495 }
496 break;
497 case GDK_WINDOW_STATE_ICONIFIED:
498 if (!(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
499 if (app->oTopWin.get_text()[0]) {
500 //this is better than the next two line because it don't change selection.
501 gtk_widget_grab_focus(app->oMidWin.oTextWin.view->widget());
502 } else {
503 app->oTopWin.grab_focus();
504 }
505 }
506 break;
507 case GDK_WINDOW_STATE_MAXIMIZED:
508 conf->set_bool_at("main_window/maximized",
509 (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED));
510 break;
511 default:
512 /* nothing */break;
513 }
514
515 return FALSE;
516 }
517
vKeyPressReleaseCallback(GtkWidget * window,GdkEventKey * event,AppCore * oAppCore)518 gboolean AppCore::vKeyPressReleaseCallback(GtkWidget * window, GdkEventKey *event , AppCore *oAppCore)
519 {
520 gboolean return_val=true; //if return TRUE,the widget which in the main window will not receive any keyboard event.
521
522 gboolean only_ctrl_pressed = ((event->state & GDK_CONTROL_MASK)&&(!(event->state & GDK_MOD1_MASK))&&(!(event->state & GDK_SHIFT_MASK)));
523 gboolean only_mod1_pressed = ((event->state & GDK_MOD1_MASK)&&(!(event->state & GDK_CONTROL_MASK))&&(!(event->state & GDK_SHIFT_MASK)));
524 if ((event->keyval==GDK_KEY_q || event->keyval==GDK_KEY_Q) && only_ctrl_pressed) {
525 if (event->type==GDK_KEY_PRESS)
526 oAppCore->Quit();
527 }
528 else if ((event->keyval==GDK_KEY_x || event->keyval==GDK_KEY_X) && only_mod1_pressed) {
529 if (event->type==GDK_KEY_PRESS) {
530 oAppCore->oDockLet->minimize_to_tray();
531 }
532 }
533 else if ((event->keyval==GDK_KEY_z || event->keyval==GDK_KEY_Z) && only_mod1_pressed) {
534 if (event->type==GDK_KEY_PRESS) {
535 gtk_window_iconify(GTK_WINDOW(window));
536 }
537 }
538 else if ((event->keyval==GDK_KEY_e || event->keyval==GDK_KEY_E) && only_mod1_pressed) {
539 if (event->type==GDK_KEY_PRESS) {
540 oAppCore->oMidWin.oToolWin.do_save();
541 }
542 }
543 else if (event->keyval==GDK_KEY_F1 && (!(event->state & GDK_CONTROL_MASK)) && (!(event->state & GDK_MOD1_MASK)) && (!(event->state & GDK_SHIFT_MASK))) {
544 if (event->type==GDK_KEY_PRESS)
545 show_help(NULL);
546 }
547 else if ((event->keyval==GDK_KEY_f || event->keyval==GDK_KEY_F) && only_ctrl_pressed) {
548 if (event->type==GDK_KEY_PRESS)
549 oAppCore->oMidWin.oToolWin.do_search();
550 }
551 else if ((event->keyval==GDK_KEY_Left) && only_mod1_pressed) {
552 if (event->type==GDK_KEY_PRESS)
553 oAppCore->oTopWin.do_back();
554 }
555 else if ((event->keyval==GDK_KEY_Right) && only_mod1_pressed) {
556 if (event->type==GDK_KEY_PRESS)
557 oAppCore->oTopWin.do_forward();
558 }
559 else if ((event->keyval==GDK_KEY_Up) && only_mod1_pressed) {
560 if (event->type==GDK_KEY_PRESS)
561 oAppCore->oTopWin.do_prev();
562 }
563 else if ((event->keyval==GDK_KEY_Down) && only_mod1_pressed) {
564 if (event->type==GDK_KEY_PRESS)
565 oAppCore->oTopWin.do_next();
566 }
567 else if ((event->keyval==GDK_KEY_c || event->keyval==GDK_KEY_C) && only_mod1_pressed) {
568 if (event->type==GDK_KEY_PRESS)
569 oAppCore->oTopWin.clear_entry();
570 }
571 else if ((event->keyval==GDK_KEY_m || event->keyval==GDK_KEY_M) && only_mod1_pressed) {
572 if (event->type==GDK_KEY_PRESS)
573 oAppCore->oTopWin.do_menu();
574 }
575 else if ((event->keyval==GDK_KEY_u || event->keyval==GDK_KEY_U) && only_ctrl_pressed) {
576 if (event->type==GDK_KEY_PRESS)
577 oAppCore->oTopWin.clear_entry();
578 }
579 else if ((event->keyval==GDK_KEY_v || event->keyval==GDK_KEY_V) && only_ctrl_pressed &&
580 !oAppCore->oTopWin.has_focus() &&
581 !oAppCore->oMidWin.oTransWin.IsInputViewHasFocus() &&
582 !oAppCore->oMidWin.oTextWin.IsSearchPanelHasFocus()) {
583 if (event->type==GDK_KEY_PRESS) {
584 gtk_clipboard_request_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), oAppCore->oTopWin.ClipboardReceivedCallback, &(oAppCore->oTopWin));
585 }
586 }
587 else if (event->type==GDK_KEY_PRESS &&
588 event->keyval >= 0x21 && event->keyval <= 0x7E &&
589 !(event->state & GDK_CONTROL_MASK) &&
590 !(event->state & GDK_MOD1_MASK) &&
591 !oAppCore->oTopWin.has_focus() &&
592 !oAppCore->oMidWin.oTransWin.IsInputViewHasFocus() &&
593 !oAppCore->oMidWin.oTextWin.IsSearchPanelHasFocus()) {
594 oAppCore->oTopWin.InsertHisList(oAppCore->oTopWin.get_text());
595 oAppCore->oTopWin.InsertBackList();
596 gchar str[2] = { (gchar)(event->keyval), '\0' };
597 oAppCore->oTopWin.grab_focus();
598 oAppCore->oTopWin.SetText(str, conf->get_bool_at("main_window/search_while_typing"));
599 oAppCore->oTopWin.set_position_in_text(1);
600 } else if (event->type==GDK_KEY_PRESS && event->keyval == GDK_KEY_BackSpace &&
601 !oAppCore->oTopWin.has_focus() &&
602 !oAppCore->oMidWin.oTransWin.IsInputViewHasFocus() &&
603 !oAppCore->oMidWin.oTextWin.IsSearchPanelHasFocus()) {
604 oAppCore->oTopWin.clear_entry();
605 } else if (event->type == GDK_KEY_PRESS &&
606 event->keyval == GDK_KEY_Return &&
607 !oAppCore->oTopWin.has_focus() &&
608 !oAppCore->oMidWin.oTransWin.IsInputViewHasFocus() &&
609 !oAppCore->oMidWin.oTextWin.IsSearchPanelHasFocus()) {
610 if (oAppCore->oMidWin.oIndexWin.oListWin.treeview_has_focus()) {
611 GtkTreeModel *model;
612 GtkTreeIter iter;
613
614 GtkTreeSelection *selection =
615 gtk_tree_view_get_selection(oAppCore->oMidWin.oIndexWin.oListWin.treeview_);
616 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
617 if (gtk_tree_model_iter_has_child(model, &iter)) {
618 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
619 if (gtk_tree_view_row_expanded(
620 oAppCore->oMidWin.oIndexWin.oListWin.treeview_,
621 path))
622 gtk_tree_view_collapse_row(
623 oAppCore->oMidWin.oIndexWin.oListWin.treeview_, path);
624 else
625 gtk_tree_view_expand_row(
626 oAppCore->oMidWin.oIndexWin.oListWin.treeview_,
627 path, FALSE);
628 gtk_tree_path_free(path);
629 } else {
630 gchar *word;
631 gtk_tree_model_get(model, &iter, 0, &word, -1);
632 oAppCore->ListClick(word);
633 g_free(word);
634 }
635 }
636 }
637 else {
638 oAppCore->oTopWin.grab_focus();
639 oAppCore->TopWinEnterWord();
640 }
641 } else if (event->type==GDK_KEY_PRESS &&
642 event->keyval == 0x20 &&
643 !oAppCore->oTopWin.has_focus() &&
644 !oAppCore->oMidWin.oTransWin.IsInputViewHasFocus() &&
645 !oAppCore->oMidWin.oTextWin.IsSearchPanelHasFocus()) {
646 oAppCore->oTopWin.InsertHisList(oAppCore->oTopWin.get_text());
647 oAppCore->oTopWin.InsertBackList();
648 oAppCore->oTopWin.grab_focus();
649 } else if(event->type==GDK_KEY_PRESS && event->keyval == GDK_KEY_Escape) {
650 if(oAppCore->oMidWin.oTextWin.IsSearchPanelHasFocus())
651 oAppCore->oMidWin.oTextWin.HideSearchPanel();
652 else
653 oAppCore->oTopWin.clear_entry();
654 } else {
655 return_val=false;
656 }
657 return return_val;
658 }
659
SimpleLookupToFloat(const char * sWord,bool IgnoreScanModifierKey)660 void AppCore::SimpleLookupToFloat(const char* sWord, bool IgnoreScanModifierKey)
661 {
662 oFloatWin.StartLookup(sWord, IgnoreScanModifierKey);
663 composite_lookup_float_win.new_lookup();
664 if (IsASCII(sWord)) {
665 if (SimpleLookupToFloatLocal(sWord)) {
666 //found
667 } else {
668 gchar *sWord2 = g_strdup(sWord);
669 gchar *a = GetPureEnglishAlpha(sWord2);
670 if (*a) {
671 if (strcmp(sWord, a) == 0) {
672 // Not found.
673 oTopWin.InsertHisList(a); //really need?
674 } else {
675 SimpleLookupToFloatLocal(a);
676 }
677 } else {
678 // The string is too strange, don't show any thing.
679 }
680 g_free(sWord2);
681 }
682 } else {
683 SimpleLookupToFloatLocal(sWord);
684 }
685 bool enable_netdict = conf->get_bool_at("network/enable_netdict");
686 if (enable_netdict) {
687 STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_SELECT_QUERY, sWord);
688 if (!oStarDictClient.try_cache(c)) {
689 composite_lookup_float_win.send_StarDict_net_request(c->seq);
690 oStarDictClient.send_commands(1, c);
691 }
692 }
693 LookupNetDict(sWord, false);
694 composite_lookup_float_win.done_lookup();
695 if(composite_lookup_float_win.is_got_all_responses())
696 oFloatWin.EndLookup();
697 }
698
SimpleLookupToFloatLocal(const char * sWord)699 bool AppCore::SimpleLookupToFloatLocal(const char* sWord)
700 {
701 if (sWord==NULL || sWord[0]=='\0')
702 return true;
703 char *SearchWord = (char *)g_malloc(strlen(sWord)+1);
704 copy_normalize_trim_spaces(SearchWord, sWord);
705 if (SearchWord[0]=='\0') {
706 strcpy(SearchWord, sWord);
707 }
708 char *EndPointer = SearchWord+strlen(SearchWord);
709
710 gchar ***pppWord = (gchar ***)g_malloc(sizeof(gchar **) * scan_dictmask.size());
711 gchar ****ppppWordData = (gchar ****)g_malloc(sizeof(gchar ***) * scan_dictmask.size());
712 CurrentIndex *iIndex = (CurrentIndex *)g_malloc(sizeof(CurrentIndex) * scan_dictmask.size());
713
714 //find the word use most biggest length
715 while (EndPointer>SearchWord) {
716 EndPointer = delete_trailing_spaces_ASCII(SearchWord, EndPointer);
717
718 bool bFound = false;
719 for (size_t iLib=0;iLib<scan_dictmask.size();iLib++)
720 BuildResultData(scan_dictmask, SearchWord, iIndex, NULL, iLib, pppWord, ppppWordData, bFound, 2);
721 for (size_t iLib=0; iLib<scan_dictmask.size(); iLib++)
722 BuildVirtualDictData(scan_dictmask, SearchWord, iLib, pppWord, ppppWordData, bFound);
723 if (bFound) {
724 oFloatWin.AppendTextLocalDict(pppWord, ppppWordData, SearchWord);
725 oTopWin.InsertHisList(SearchWord);
726 FreeResultData(scan_dictmask.size(), pppWord, ppppWordData);
727 g_free(iIndex);
728 g_free(SearchWord);
729 return true;
730 }
731 if (IsASCII(SearchWord)) {
732 EndPointer = delete_trailing_word_ASCII(SearchWord, EndPointer);
733 } else {
734 EndPointer = delete_trailing_char(SearchWord, EndPointer);
735 }
736 }
737 FreeResultData(scan_dictmask.size(), pppWord, ppppWordData);
738 g_free(iIndex);
739 g_free(SearchWord);
740 return false;
741 }
742
743 #ifdef _WIN32
SmartLookupToFloat(const gchar * sWord,int BeginPos,bool IgnoreScanModifierKey)744 void AppCore::SmartLookupToFloat(const gchar* sWord, int BeginPos, bool IgnoreScanModifierKey)
745 {
746 oFloatWin.StartLookup(sWord, IgnoreScanModifierKey);
747 composite_lookup_float_win.new_lookup();
748 LocalSmartLookupToFloat(sWord, BeginPos);
749 /* sWord is not a candidate to search in net dictionaries */
750 composite_lookup_float_win.done_lookup();
751 if(composite_lookup_float_win.is_got_all_responses())
752 oFloatWin.EndLookup();
753 }
754
LocalSmartLookupToFloat(const gchar * sWord,int BeginPos)755 bool AppCore::LocalSmartLookupToFloat(const gchar* sWord, int BeginPos)
756 {
757 if (sWord==NULL || sWord[0]=='\0')
758 return false;
759 char *SearchWord = (char *)g_malloc(strlen(sWord)+1);
760 std::string TriedSearchWord;
761
762 gchar ***pppWord = (gchar ***)g_malloc(sizeof(gchar **) * scan_dictmask.size());
763 gchar ****ppppWordData = (gchar ****)g_malloc(sizeof(gchar ***) * scan_dictmask.size());
764 CurrentIndex *iIndex = (CurrentIndex *)g_malloc(sizeof(CurrentIndex) * scan_dictmask.size());
765
766 int try_cnt = 0;
767 while(true) {
768 bool skip_try = false;
769 switch(try_cnt)
770 {
771 case 0:
772 extract_word(SearchWord, sWord, BeginPos, is_space_or_punct);
773 TriedSearchWord = SearchWord;
774 ++try_cnt;
775 break;
776 case 1:
777 extract_word(SearchWord, sWord, BeginPos, is_not_alpha);
778 if(SearchWord[0])
779 TriedSearchWord = SearchWord;
780 ++try_cnt;
781 break;
782 case 2:
783 {
784 gunichar c = g_utf8_get_char(sWord + BeginPos);
785 if(g_unichar_islower(c))
786 extract_word(SearchWord, sWord, BeginPos, is_not_lower);
787 else if(g_unichar_isupper(c))
788 extract_word(SearchWord, sWord, BeginPos, is_not_upper);
789 else
790 skip_try = true;
791 if(SearchWord[0])
792 TriedSearchWord = SearchWord;
793 ++try_cnt;
794 break;
795 }
796 case 3:
797 extract_capitalized_word(SearchWord, sWord, BeginPos,
798 g_unichar_isupper, g_unichar_islower);
799 if(SearchWord[0])
800 TriedSearchWord = SearchWord;
801 ++try_cnt;
802 break;
803 case 4:
804 strcpy(SearchWord, TriedSearchWord.c_str());
805 ++try_cnt;
806 skip_try = true;
807 case 5:
808 { // cut last char
809 char *end = SearchWord + strlen(SearchWord);
810 end = g_utf8_prev_char(end);
811 *end = '\0';
812 if(!SearchWord[0]) {
813 ++try_cnt;
814 skip_try = true;
815 }
816 break;
817 }
818 default:
819 goto loop_end;
820 }
821 if(!SearchWord[0] || skip_try)
822 continue;
823
824 bool bFound = false;
825 for (size_t iLib=0;iLib<scan_dictmask.size();iLib++)
826 BuildResultData(scan_dictmask, SearchWord, iIndex, false, iLib, pppWord, ppppWordData, bFound, 2);
827 for (size_t iLib=0; iLib<scan_dictmask.size(); iLib++)
828 BuildVirtualDictData(scan_dictmask, SearchWord, iLib, pppWord, ppppWordData, bFound);
829
830 if (bFound) {
831 oFloatWin.AppendTextLocalDict(pppWord, ppppWordData, SearchWord);
832 oTopWin.InsertHisList(SearchWord);
833 FreeResultData(scan_dictmask.size(), pppWord, ppppWordData);
834 g_free(iIndex);
835 g_free(SearchWord);
836 return true;
837 }
838 }
839 loop_end:
840 FreeResultData(scan_dictmask.size(), pppWord, ppppWordData);
841 g_free(iIndex);
842 g_free(SearchWord);
843 return false;
844 }
845 #endif
846
BuildVirtualDictData(std::vector<InstantDictIndex> & dictmask,const char * sWord,int iLib,gchar *** pppWord,gchar **** ppppWordData,bool & bFound)847 void AppCore::BuildVirtualDictData(std::vector<InstantDictIndex> &dictmask, const char* sWord, int iLib, gchar ***pppWord, gchar ****ppppWordData, bool &bFound)
848 {
849 if (dictmask[iLib].type == InstantDictType_NET) {
850 const char *dict_cacheid = oStarDictPlugins->NetDictPlugins.dict_cacheid(dictmask[iLib].index);
851 NetDictResponse *resp = netdict_get_cache_resp(dict_cacheid, sWord);
852 if (resp && resp->data) {
853 pppWord[iLib] = (gchar **)g_malloc(sizeof(gchar *)*2);
854 pppWord[iLib][0] = g_strdup(resp->word);
855 pppWord[iLib][1] = NULL;
856 ppppWordData[iLib] = (gchar ***)g_malloc(sizeof(gchar **)*(1));
857 ppppWordData[iLib][0] = (gchar **)g_malloc(sizeof(gchar *)*2);
858 ppppWordData[iLib][0][0] = stardict_datadup(resp->data);
859 ppppWordData[iLib][0][1] = NULL;
860 bFound = true;
861 } else {
862 pppWord[iLib] = NULL;
863 }
864 } else if (dictmask[iLib].type == InstantDictType_VIRTUAL) {
865 oStarDictPlugins->VirtualDictPlugins.lookup(dictmask[iLib].index, sWord, &(pppWord[iLib]), &(ppppWordData[iLib]));
866 if (pppWord[iLib])
867 bFound = true;
868 }
869 }
870
BuildResultData(std::vector<InstantDictIndex> & dictmask,const char * sWord,CurrentIndex * iIndex,const gchar * piIndexValidStr,int iLib,gchar *** pppWord,gchar **** ppppWordData,bool & bFound,gint Method)871 void AppCore::BuildResultData(std::vector<InstantDictIndex> &dictmask, const char* sWord, CurrentIndex *iIndex, const gchar *piIndexValidStr, int iLib, gchar ***pppWord, gchar ****ppppWordData, bool &bFound, gint Method)
872 {
873 if (dictmask[iLib].type != InstantDictType_LOCAL)
874 return;
875
876 int iRealLib = dictmask[iLib].index;
877 gint i, j;
878 gint count=0, syncount;
879 bool bLookupWord, bLookupSynonymWord;
880 gint nWord;
881 glong iWordIdx;
882 if (piIndexValidStr) {
883 if (iIndex[iLib].idx != INVALID_INDEX) {
884 bLookupWord = !strcmp(oLibs.poGetWord(iIndex[iLib].idx, iRealLib, 0), piIndexValidStr);
885 } else {
886 bLookupWord = false;
887 }
888 if (iIndex[iLib].synidx != UNSET_INDEX && iIndex[iLib].synidx != INVALID_INDEX) {
889 bLookupSynonymWord = !strcmp(oLibs.poGetSynonymWord(iIndex[iLib].synidx, iRealLib, 0), piIndexValidStr);
890 } else {
891 bLookupSynonymWord = false;
892 }
893 } else {
894 if (Method==0) {
895 bLookupWord = oLibs.LookupWord(sWord, iIndex[iLib].idx, iIndex[iLib].idx_suggest, iRealLib, 0);
896 bLookupSynonymWord = oLibs.LookupSynonymWord(sWord, iIndex[iLib].synidx, iIndex[iLib].synidx_suggest, iRealLib, 0);
897 } else if (Method==1) {
898 bLookupWord = oLibs.LookupSimilarWord(sWord, iIndex[iLib].idx, iIndex[iLib].idx_suggest, iRealLib, 0);
899 bLookupSynonymWord = oLibs.LookupSynonymSimilarWord(sWord, iIndex[iLib].synidx, iIndex[iLib].synidx_suggest, iRealLib, 0);
900 } else {
901 bLookupWord = oLibs.SimpleLookupWord(sWord, iIndex[iLib].idx, iIndex[iLib].idx_suggest, iRealLib, 0);
902 bLookupSynonymWord = oLibs.SimpleLookupSynonymWord(sWord, iIndex[iLib].synidx, iIndex[iLib].synidx_suggest, iRealLib, 0);
903 }
904 }
905 if (bLookupWord || bLookupSynonymWord) {
906 glong orig_idx, orig_synidx;
907 orig_idx = oLibs.CltIndexToOrig(iIndex[iLib].idx, iRealLib, 0);
908 orig_synidx = oLibs.CltSynIndexToOrig(iIndex[iLib].synidx, iRealLib, 0);
909 nWord=0;
910 if (bLookupWord)
911 nWord++;
912 if (bLookupSynonymWord) {
913 syncount = oLibs.GetOrigWordCount(orig_synidx, iRealLib, false);
914 nWord+=syncount;
915 }
916 pppWord[iLib] = (gchar **)g_malloc(sizeof(gchar *)*(nWord+1));
917 ppppWordData[iLib] = (gchar ***)g_malloc(sizeof(gchar **)*(nWord));
918 if (bLookupWord) {
919 pppWord[iLib][0] = g_strdup(oLibs.poGetOrigWord(orig_idx, iRealLib));
920 count = oLibs.GetOrigWordCount(orig_idx, iRealLib, true);
921 ppppWordData[iLib][0] = (gchar **)g_malloc(sizeof(gchar *)*(count+1));
922 for (i=0;i<count;i++) {
923 ppppWordData[iLib][0][i] = stardict_datadup(oLibs.poGetOrigWordData(orig_idx+i, iRealLib));
924 }
925 ppppWordData[iLib][0][count] = NULL;
926 i=1;
927 } else {
928 i=0;
929 }
930 for (j=0;i<nWord;i++,j++) {
931 iWordIdx = oLibs.poGetOrigSynonymWordIdx(orig_synidx+j, iRealLib);
932 if (bLookupWord) {
933 if (iWordIdx>=orig_idx && (iWordIdx<orig_idx+count)) {
934 nWord--;
935 i--;
936 continue;
937 }
938 }
939 pppWord[iLib][i] = g_strdup(oLibs.poGetOrigWord(iWordIdx, iRealLib));
940 ppppWordData[iLib][i] = (gchar **)g_malloc(sizeof(gchar *)*2);
941 ppppWordData[iLib][i][0] = stardict_datadup(oLibs.poGetOrigWordData(iWordIdx, iRealLib));
942 ppppWordData[iLib][i][1] = NULL;
943 }
944 pppWord[iLib][nWord] = NULL;
945 bFound = true;
946 } else {
947 pppWord[iLib] = NULL;
948 }
949 }
950
FreeResultData(size_t dictmask_size,gchar *** pppWord,gchar **** ppppWordData)951 void AppCore::FreeResultData(size_t dictmask_size, gchar ***pppWord, gchar ****ppppWordData)
952 {
953 if (!pppWord)
954 return;
955 int j, k;
956 size_t i;
957 for (i=0; i<dictmask_size; i++) {
958 if (pppWord[i]) {
959 j=0;
960 while (pppWord[i][j]) {
961 k=0;
962 while (ppppWordData[i][j][k]) {
963 g_free(ppppWordData[i][j][k]);
964 k++;
965 }
966 g_free(pppWord[i][j]);
967 g_free(ppppWordData[i][j]);
968 j++;
969 }
970 g_free(pppWord[i]);
971 g_free(ppppWordData[i]);
972 }
973 }
974 g_free(pppWord);
975 g_free(ppppWordData);
976 }
977
978 /* The input can be:
979 * (sWord, NULL, NULL). Look up the sWord.
980 * (sWord, piIndex, NULL). Look up the sWord, and set piIndex to the new indexes that found.
981 * (sWord, piIndex, "word"), show sWord by piIndex's information, while the index point to "word".
982 */
SimpleLookupToTextWin(const char * sWord,CurrentIndex * piIndex,const gchar * piIndexValidStr,bool bTryMoreIfNotFound,bool bShowNotfound,bool isShowFirst)983 bool AppCore::SimpleLookupToTextWin(const char* sWord, CurrentIndex *piIndex, const gchar *piIndexValidStr, bool bTryMoreIfNotFound, bool bShowNotfound, bool isShowFirst)
984 {
985 bool bFound = false;
986 gchar ***pppWord = (gchar ***)g_malloc(sizeof(gchar **) * query_dictmask.size());
987 gchar ****ppppWordData = (gchar ****)g_malloc(sizeof(gchar ***) * query_dictmask.size());
988 CurrentIndex *iIndex;
989 if (!piIndex)
990 iIndex = (CurrentIndex *)g_malloc(sizeof(CurrentIndex) * query_dictmask.size());
991 else
992 iIndex = piIndex;
993
994 for (size_t iLib=0; iLib<query_dictmask.size(); iLib++)
995 BuildResultData(query_dictmask, sWord, iIndex, piIndexValidStr, iLib, pppWord, ppppWordData, bFound, 0);
996 if (!bFound && !piIndexValidStr) {
997 for (size_t iLib=0; iLib<query_dictmask.size(); iLib++)
998 BuildResultData(query_dictmask, sWord, iIndex, NULL, iLib, pppWord, ppppWordData, bFound, 1);
999 }
1000 for (size_t iLib=0; iLib<query_dictmask.size(); iLib++)
1001 BuildVirtualDictData(query_dictmask, piIndexValidStr?piIndexValidStr:sWord, iLib, pppWord, ppppWordData, bFound);
1002 if (bFound) {
1003 ShowDataToTextWin(pppWord, ppppWordData, sWord, isShowFirst);
1004 } else {
1005 if (bTryMoreIfNotFound) {
1006 gchar *word = g_strdup(sWord);
1007 gchar *hword;
1008 hword = GetHeadWord(word);
1009 if (*hword) {
1010 if (!strcmp(hword,sWord)) {
1011 if (bShowNotfound)
1012 ShowNotFoundToTextWin(sWord,_("<Not Found!>"), TEXT_WIN_NOT_FOUND);
1013 } else {
1014 for (size_t iLib=0;iLib<query_dictmask.size();iLib++)
1015 BuildResultData(query_dictmask, hword, iIndex, NULL, iLib, pppWord, ppppWordData, bFound, 0);
1016 if (!bFound) {
1017 for (size_t iLib=0; iLib<query_dictmask.size(); iLib++)
1018 BuildResultData(query_dictmask, hword, iIndex, NULL, iLib, pppWord, ppppWordData, bFound, 1);
1019 }
1020 for (size_t iLib=0; iLib<query_dictmask.size(); iLib++)
1021 BuildVirtualDictData(query_dictmask, hword, iLib, pppWord, ppppWordData, bFound);
1022 if (bFound) {
1023 ShowDataToTextWin(pppWord, ppppWordData, sWord, isShowFirst);
1024 } else {
1025 if (bShowNotfound)
1026 ShowNotFoundToTextWin(sWord,_("<Not Found!>"), TEXT_WIN_NOT_FOUND);
1027 }
1028 }
1029 } else {
1030 if (bShowNotfound)
1031 ShowNotFoundToTextWin(sWord,_("<Not Found!>"), TEXT_WIN_NOT_FOUND);
1032 }
1033 g_free(word);
1034 } else {
1035 if (bShowNotfound)
1036 ShowNotFoundToTextWin(sWord,_("<Not Found!>"), TEXT_WIN_NOT_FOUND);
1037 }
1038 }
1039
1040 if (!piIndex)
1041 g_free(iIndex);
1042
1043 FreeResultData(query_dictmask.size(), pppWord, ppppWordData);
1044
1045 return bFound;
1046 }
1047
1048 struct FullTextSearchDialog {
1049 GtkWidget *progress_bar;
1050 };
1051
updateSearchDialog(gpointer data,gdouble fraction)1052 static void updateSearchDialog(gpointer data, gdouble fraction)
1053 {
1054 FullTextSearchDialog *Dialog = (FullTextSearchDialog *)data;
1055 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(Dialog->progress_bar), fraction);
1056 while (gtk_events_pending())
1057 gtk_main_iteration();
1058 }
1059
on_fulltext_search_cancel_clicked(GtkButton * button,bool * cancel)1060 static void on_fulltext_search_cancel_clicked(GtkButton *button, bool *cancel)
1061 {
1062 *cancel = true;
1063 }
1064
on_fulltext_search_window_delete_event(GtkWidget * window,GdkEvent * event,bool * cancel)1065 static gboolean on_fulltext_search_window_delete_event(GtkWidget * window, GdkEvent *event , bool *cancel)
1066 {
1067 *cancel = true;
1068 return true;
1069 }
1070
1071 class LookupDataDialog {
1072 public:
1073 LookupDataDialog(const char *sWord);
1074 void show();
1075 private:
1076 std::string word;
1077 GtkListStore *now_tree_model;
1078 static void on_fulltext_search_dict_enable_toggled (GtkCellRendererToggle *cell, gchar *path_str, LookupDataDialog *oLookupDataDialog);
1079 };
1080
LookupDataDialog(const char * sWord)1081 LookupDataDialog::LookupDataDialog(const char *sWord)
1082 {
1083 word = sWord;
1084 }
1085
on_fulltext_search_dict_enable_toggled(GtkCellRendererToggle * cell,gchar * path_str,LookupDataDialog * oLookupDataDialog)1086 void LookupDataDialog::on_fulltext_search_dict_enable_toggled (GtkCellRendererToggle *cell, gchar *path_str, LookupDataDialog *oLookupDataDialog)
1087 {
1088 GtkTreeModel *model = GTK_TREE_MODEL(oLookupDataDialog->now_tree_model);
1089 GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
1090 GtkTreeIter iter;
1091 gtk_tree_model_get_iter (model, &iter, path);
1092 gboolean enable;
1093 gtk_tree_model_get (model, &iter, 0, &enable, -1);
1094 enable = !enable;
1095 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, enable, -1);
1096 gtk_tree_path_free (path);
1097 }
1098
show()1099 void LookupDataDialog::show()
1100 {
1101 GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Full-text Search"), GTK_WINDOW(gpAppFrame->window), GTK_DIALOG_MODAL, NULL, NULL, NULL);
1102 GtkWidget *button = gtk_dialog_add_button(GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
1103 gtk_dialog_add_button(GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
1104 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
1105 gtk_widget_grab_focus(button);
1106 #if GTK_MAJOR_VERSION >= 3
1107 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
1108 #else
1109 GtkWidget *vbox = gtk_vbox_new(false, 5);
1110 #endif
1111 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),vbox,true,true,0);
1112 GtkWidget *sw = gtk_scrolled_window_new (NULL, NULL);
1113 gtk_box_pack_start(GTK_BOX(vbox),sw,true,true,0);
1114 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
1115 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1116 gtk_widget_set_size_request (sw, 300, 200);
1117 now_tree_model = gtk_list_store_new(3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_LONG);
1118 for (std::vector<InstantDictIndex>::iterator i = gpAppFrame->query_dictmask.begin(); i != gpAppFrame->query_dictmask.end(); ++i) {
1119 if (i->type == InstantDictType_LOCAL) {
1120 GtkTreeIter new_iter;
1121 gtk_list_store_append(now_tree_model, &new_iter);
1122 gtk_list_store_set(now_tree_model, &new_iter, 0, TRUE, 1, gpAppFrame->oLibs.dict_name(i->index).c_str(), 2, i->index, -1);
1123 }
1124 }
1125 GtkWidget *now_treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL(now_tree_model));
1126 g_object_unref (G_OBJECT (now_tree_model));
1127 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (now_treeview), TRUE);
1128 GtkCellRenderer *renderer;
1129 GtkTreeViewColumn *column;
1130 renderer = gtk_cell_renderer_toggle_new ();
1131 g_signal_connect (renderer, "toggled", G_CALLBACK (on_fulltext_search_dict_enable_toggled), this);
1132 column = gtk_tree_view_column_new_with_attributes (_("Search"), renderer, "active", 0, NULL);
1133 gtk_tree_view_append_column (GTK_TREE_VIEW(now_treeview), column);
1134 gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), FALSE);
1135 renderer = gtk_cell_renderer_text_new ();
1136 g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL);
1137 column = gtk_tree_view_column_new_with_attributes (_("Dictionary Name"), renderer, "text", 1, NULL);
1138 gtk_tree_view_append_column (GTK_TREE_VIEW(now_treeview), column);
1139 gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), FALSE);
1140 gtk_container_add (GTK_CONTAINER (sw), now_treeview);
1141 gtk_widget_show_all(vbox);
1142 gint response = gtk_dialog_run(GTK_DIALOG(dialog));
1143 if (response == GTK_RESPONSE_ACCEPT) {
1144 std::vector<InstantDictIndex> dictmask;
1145 GtkTreeIter iter;
1146 GtkTreeModel *model = GTK_TREE_MODEL(now_tree_model);
1147 gboolean have_next = gtk_tree_model_get_iter_first(model, &iter);
1148 while (have_next) {
1149 gboolean enable;
1150 gtk_tree_model_get (model, &iter, 0, &enable, -1);
1151 if (enable) {
1152 glong index;
1153 gtk_tree_model_get (model, &iter, 2, &index, -1);
1154 InstantDictIndex dictindex;
1155 dictindex.type = InstantDictType_LOCAL;
1156 dictindex.index = index;
1157 dictmask.push_back(dictindex);
1158 }
1159 have_next = gtk_tree_model_iter_next(model, &iter);
1160 }
1161 gtk_widget_destroy(dialog);
1162 gpAppFrame->oMidWin.oIndexWin.oListWin.Clear();
1163 gpAppFrame->oMidWin.oIndexWin.oListWin.SetModel(false);
1164 gpAppFrame->oMidWin.oIndexWin.oListWin.list_word_type = LIST_WIN_DATA_LIST;
1165 bool enable_netdict = conf->get_bool_at("network/enable_netdict");
1166 if (enable_netdict) {
1167 std::string lookupword = "|";
1168 lookupword += word;
1169 STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_LOOKUP, lookupword.c_str());
1170 if (!gpAppFrame->oStarDictClient.try_cache(c)) {
1171 gpAppFrame->waiting_mainwin_lookupcmd_seq = c->seq;
1172 gpAppFrame->oStarDictClient.send_commands(1, c);
1173 }
1174 }
1175 gpAppFrame->LookupDataWithDictMask(word.c_str(), dictmask);
1176 } else {
1177 gtk_widget_destroy(dialog);
1178 }
1179 }
1180
LookupDataToMainWin(const gchar * sWord)1181 void AppCore::LookupDataToMainWin(const gchar *sWord)
1182 {
1183 if (query_dictmask.empty()) {
1184 oMidWin.oIndexWin.oListWin.Clear();
1185 oMidWin.oIndexWin.oListWin.SetModel(false);
1186 oMidWin.oIndexWin.oListWin.list_word_type = LIST_WIN_DATA_LIST;
1187 bool enable_netdict = conf->get_bool_at("network/enable_netdict");
1188 if (enable_netdict) {
1189 std::string lookupword = "|";
1190 lookupword += sWord;
1191 STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_LOOKUP, lookupword.c_str());
1192 if (!oStarDictClient.try_cache(c)) {
1193 waiting_mainwin_lookupcmd_seq = c->seq;
1194 oStarDictClient.send_commands(1, c);
1195 }
1196 } else {
1197 ShowNotFoundToTextWin(sWord, _("There are no dictionary articles containing this word. :-("), TEXT_WIN_FUZZY_NOT_FOUND);
1198 }
1199 } else {
1200 LookupDataDialog *dialog = new LookupDataDialog(sWord);
1201 dialog->show();
1202 delete dialog;
1203 }
1204 }
1205
LookupDataWithDictMask(const gchar * sWord,std::vector<InstantDictIndex> & dictmask)1206 void AppCore::LookupDataWithDictMask(const gchar *sWord, std::vector<InstantDictIndex> &dictmask)
1207 {
1208 if (!sWord || !*sWord)
1209 return;
1210 change_cursor busy(gtk_widget_get_window(window),
1211 get_impl(oAppSkin.watch_cursor),
1212 get_impl(oAppSkin.normal_cursor));
1213
1214 bool cancel = false;
1215 FullTextSearchDialog Dialog;
1216 GtkWidget *search_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1217 gtk_window_set_title (GTK_WINDOW(search_window), _("Full-text search..."));
1218 gtk_window_set_transient_for(GTK_WINDOW(search_window), GTK_WINDOW(window));
1219 gtk_window_set_position(GTK_WINDOW(search_window), GTK_WIN_POS_CENTER_ON_PARENT);
1220 #if GTK_MAJOR_VERSION >= 3
1221 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
1222 #else
1223 GtkWidget *vbox = gtk_vbox_new(false, 6);
1224 #endif
1225 gtk_container_add(GTK_CONTAINER(search_window),vbox);
1226 Dialog.progress_bar = gtk_progress_bar_new();
1227 gtk_box_pack_start(GTK_BOX(vbox),Dialog.progress_bar,false,false,0);
1228 GtkWidget *button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1229 gtk_box_pack_start(GTK_BOX(vbox),button,false,false,0);
1230 g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_fulltext_search_cancel_clicked), &cancel);
1231 g_signal_connect (G_OBJECT (search_window), "delete_event", G_CALLBACK (on_fulltext_search_window_delete_event), &cancel);
1232 gtk_widget_show_all(search_window);
1233
1234 //clock_t t=clock();
1235 std::vector< std::vector<gchar *> > reslist(dictmask.size());
1236 if (oLibs.LookupData(sWord, &reslist[0], updateSearchDialog, &Dialog, &cancel, dictmask)) {
1237 for (size_t i=0; i<dictmask.size(); i++) {
1238 if (!reslist[i].empty()) {
1239 SimpleLookupToTextWin(reslist[i][0], iCurrentIndex, NULL); // so iCurrentIndex is refreshed.
1240 break;
1241 }
1242 }
1243 oMidWin.oIndexWin.oListWin.SetTreeModel(&reslist[0], dictmask);
1244 oMidWin.oIndexWin.oListWin.ReScroll();
1245 } else {
1246 ShowNotFoundToTextWin(sWord, _("There are no dictionary articles containing this word. :-("), TEXT_WIN_FUZZY_NOT_FOUND);
1247 }
1248 //t=clock()-t;
1249 //g_message("Time: %.3lf sec\n", double(t)/CLOCKS_PER_SEC);
1250 gtk_widget_destroy(search_window);
1251 }
1252
LookupWithFuzzyToMainWin(const gchar * sWord)1253 void AppCore::LookupWithFuzzyToMainWin(const gchar *sWord)
1254 {
1255 if (sWord[0] == '\0')
1256 return;
1257 change_cursor busy(gtk_widget_get_window(window),
1258 get_impl(oAppSkin.watch_cursor),
1259 get_impl(oAppSkin.normal_cursor));
1260
1261 gchar *fuzzy_reslist[MAX_FUZZY_MATCH_ITEM];
1262 bool Found=
1263 oLibs.LookupWithFuzzy(sWord, fuzzy_reslist, MAX_FUZZY_MATCH_ITEM, query_dictmask);
1264
1265 // show
1266 oMidWin.oIndexWin.oListWin.Clear();
1267 oMidWin.oIndexWin.oListWin.SetModel(true);
1268 oMidWin.oIndexWin.oListWin.fuzzyWord = sWord;
1269 oMidWin.oIndexWin.oListWin.list_word_type = LIST_WIN_FUZZY_LIST;
1270
1271 if (Found) {
1272 //SimpleLookupToTextWin(oFuzzystruct[0].pMatchWord,NULL);
1273 SimpleLookupToTextWin(fuzzy_reslist[0], iCurrentIndex, NULL); // so iCurrentIndex is refreshed.
1274
1275 for (int i=0; i<MAX_FUZZY_MATCH_ITEM && fuzzy_reslist[i]; i++) {
1276 oMidWin.oIndexWin.oListWin.InsertLast(fuzzy_reslist[i]);
1277 g_free(fuzzy_reslist[i]);
1278 //g_print("fuzzy %s,%d\n",oFuzzystruct[i].pMatchWord,oFuzzystruct[i].iMatchWordDistance);
1279 }
1280 oMidWin.oIndexWin.oListWin.ReScroll();
1281 } else {
1282 ShowNotFoundToTextWin(sWord,_("There are too many spelling errors :-("), TEXT_WIN_FUZZY_NOT_FOUND);
1283 }
1284 }
1285
LookupWithFuzzyToFloatWin(const gchar * sWord)1286 void AppCore::LookupWithFuzzyToFloatWin(const gchar *sWord)
1287 {
1288 if (sWord[0] == '\0')
1289 return;
1290
1291 oFloatWin.StartLookup(sWord);
1292 composite_lookup_float_win.new_lookup();
1293 gchar *fuzzy_reslist[MAX_FLOAT_WINDOW_FUZZY_MATCH_ITEM];
1294 bool Found = oLibs.LookupWithFuzzy(sWord, fuzzy_reslist, MAX_FLOAT_WINDOW_FUZZY_MATCH_ITEM, scan_dictmask);
1295 if (Found) {
1296 int i, count=0;
1297 for (i=0; i<MAX_FLOAT_WINDOW_FUZZY_MATCH_ITEM; i++) {
1298 if (fuzzy_reslist[i])
1299 count++;
1300 else
1301 break;
1302 }
1303 gchar ****ppppWord = (gchar ****)g_malloc(sizeof(gchar ***) * count);
1304 gchar *****pppppWordData = (gchar *****)g_malloc(sizeof(gchar ****) * count);
1305 const gchar **ppOriginWord = (const gchar **)g_malloc(sizeof(gchar *) * count);
1306 CurrentIndex *iIndex = (CurrentIndex *)g_malloc(sizeof(CurrentIndex) * scan_dictmask.size());
1307
1308 gchar ***pppWord;
1309 gchar ****ppppWordData;
1310 for (i=0;i<count;i++) {
1311 bool bFound = false;
1312 pppWord = (gchar ***)g_malloc(sizeof(gchar **) * scan_dictmask.size());
1313 ppppWordData = (gchar ****)g_malloc(sizeof(gchar ***) * scan_dictmask.size());
1314
1315 ppOriginWord[i] = fuzzy_reslist[i];
1316 for (size_t iLib=0; iLib<scan_dictmask.size(); iLib++)
1317 BuildResultData(scan_dictmask, fuzzy_reslist[i], iIndex, NULL, iLib, pppWord, ppppWordData, bFound, 2);
1318 for (size_t iLib=0; iLib<scan_dictmask.size(); iLib++)
1319 BuildVirtualDictData(scan_dictmask, fuzzy_reslist[i], iLib, pppWord, ppppWordData, bFound);
1320 if (bFound) {// it is certainly be true.
1321 ppppWord[i]=pppWord;
1322 pppppWordData[i]=ppppWordData;
1323 } else {
1324 FreeResultData(scan_dictmask.size(), pppWord, ppppWordData);
1325 ppppWord[i]=NULL;
1326 }
1327 }
1328 oFloatWin.AppendTextFuzzy(ppppWord, pppppWordData, ppOriginWord, count, sWord);
1329 for (i=0; i<count; i++) {
1330 if (ppppWord[i])
1331 FreeResultData(scan_dictmask.size(), ppppWord[i], pppppWordData[i]);
1332 }
1333 g_free(ppppWord);
1334 g_free(pppppWordData);
1335 g_free(ppOriginWord);
1336 g_free(iIndex);
1337
1338 for (i=0;i<count;i++)
1339 g_free(fuzzy_reslist[i]);
1340 }
1341 composite_lookup_float_win.done_lookup();
1342 if(composite_lookup_float_win.is_got_all_responses())
1343 oFloatWin.EndLookup();
1344 }
1345
LookupWithRuleToMainWin(const gchar * word)1346 void AppCore::LookupWithRuleToMainWin(const gchar *word)
1347 {
1348 change_cursor busy(gtk_widget_get_window(window),
1349 get_impl(oAppSkin.watch_cursor),
1350 get_impl(oAppSkin.normal_cursor));
1351
1352 gchar **ppMatchWord = (gchar **)g_malloc(sizeof(gchar *) * (MAX_MATCH_ITEM_PER_LIB*2) * query_dictmask.size()); //Need to be MAX_MATCH_ITEM_PER_LIB*2 as oLibs.LookupWithRule will call LookupWithRule() and LookupWithRuleSynonym().
1353 gint iMatchCount=oLibs.LookupWithRule(word, ppMatchWord, query_dictmask);
1354 oMidWin.oIndexWin.oListWin.Clear();
1355 oMidWin.oIndexWin.oListWin.SetModel(true);
1356 oMidWin.oIndexWin.oListWin.list_word_type = LIST_WIN_PATTERN_LIST;
1357
1358 if (iMatchCount) {
1359 for (gint i=0; i<iMatchCount; i++)
1360 oMidWin.oIndexWin.oListWin.InsertLast(ppMatchWord[i]);
1361 //memset(iCurrentIndex,'\0',sizeof(iCurrentIndex)); // iCurrentIndex is ineffective now.
1362
1363 // show the first word.
1364 //SimpleLookupToTextWin(ppMatchWord[0],NULL);
1365 SimpleLookupToTextWin(ppMatchWord[0], iCurrentIndex, NULL); // so iCurrentIndex is refreshed.
1366 oMidWin.oIndexWin.oListWin.ReScroll();
1367 for(gint i=0; i<iMatchCount; i++)
1368 g_free(ppMatchWord[i]);
1369 } else {
1370 ShowNotFoundToTextWin(word,_("Found no words matching this pattern!"), TEXT_WIN_PATTERN_NOT_FOUND);
1371 }
1372 g_free(ppMatchWord);
1373 }
1374
LookupWithRegexToMainWin(const gchar * word)1375 void AppCore::LookupWithRegexToMainWin(const gchar *word)
1376 {
1377 change_cursor busy(gtk_widget_get_window(window),
1378 get_impl(oAppSkin.watch_cursor),
1379 get_impl(oAppSkin.normal_cursor));
1380
1381 gchar **ppMatchWord = (gchar **)g_malloc(sizeof(gchar *) * (MAX_MATCH_ITEM_PER_LIB*2) * query_dictmask.size()); //Need to be MAX_MATCH_ITEM_PER_LIB*2 as oLibs.LookupWithRegex will call LookupWithRegex() and LookupWithRegexSynonym().
1382 gint iMatchCount=oLibs.LookupWithRegex(word, ppMatchWord, query_dictmask);
1383 oMidWin.oIndexWin.oListWin.Clear();
1384 oMidWin.oIndexWin.oListWin.SetModel(true);
1385 oMidWin.oIndexWin.oListWin.list_word_type = LIST_WIN_PATTERN_LIST;
1386
1387 if (iMatchCount) {
1388 for (gint i=0; i<iMatchCount; i++)
1389 oMidWin.oIndexWin.oListWin.InsertLast(ppMatchWord[i]);
1390 SimpleLookupToTextWin(ppMatchWord[0], iCurrentIndex, NULL); // so iCurrentIndex is refreshed.
1391 oMidWin.oIndexWin.oListWin.ReScroll();
1392 for(gint i=0; i<iMatchCount; i++)
1393 g_free(ppMatchWord[i]);
1394 } else {
1395 ShowNotFoundToTextWin(word,_("Found no words matching this regular expression!"), TEXT_WIN_PATTERN_NOT_FOUND);
1396 }
1397 g_free(ppMatchWord);
1398 }
1399
LookupNetDict(const char * sWord,bool ismainwin)1400 void AppCore::LookupNetDict(const char *sWord, bool ismainwin)
1401 {
1402 std::vector<InstantDictIndex> *dictmask;
1403 if (ismainwin) {
1404 dictmask = &query_dictmask;
1405 } else {
1406 dictmask = &scan_dictmask;
1407 }
1408 for (size_t iLib=0; iLib<dictmask->size(); iLib++) {
1409 if ((*dictmask)[iLib].type == InstantDictType_NET) {
1410 const char *dict_cacheid = oStarDictPlugins->NetDictPlugins.dict_cacheid((*dictmask)[iLib].index);
1411 NetDictResponse *resp = netdict_get_cache_resp(dict_cacheid, sWord);
1412 if(!ismainwin)
1413 composite_lookup_float_win.send_net_dict_request(dict_cacheid, sWord);
1414 if (!resp) {
1415 oStarDictPlugins->NetDictPlugins.lookup((*dictmask)[iLib].index, sWord, ismainwin);
1416 } else {
1417 show_netdict_resp(dict_cacheid, resp, ismainwin);
1418 }
1419 }
1420 }
1421 }
1422
ShowDataToTextWin(gchar *** pppWord,gchar **** ppppWordData,const gchar * sOriginWord,bool isShowFirst)1423 void AppCore::ShowDataToTextWin(gchar ***pppWord, gchar ****ppppWordData,
1424 const gchar *sOriginWord, bool isShowFirst)
1425 {
1426 oMidWin.oTextWin.Show(sOriginWord, pppWord, ppppWordData);
1427 if (isShowFirst)
1428 oMidWin.oTextWin.query_result = TEXT_WIN_SHOW_FIRST;
1429 else
1430 oMidWin.oTextWin.query_result = TEXT_WIN_FOUND;
1431 oMidWin.oTextWin.queryWord = sOriginWord;
1432
1433 oMidWin.oIndexWin.oResultWin.Clear();
1434 int bookindex = 0;
1435 for (size_t i=0; i < query_dictmask.size(); i++) {
1436 if (pppWord[i]) {
1437 gchar *mark = g_strdup_printf("%d", bookindex);
1438 bookindex++;
1439 if (query_dictmask[i].type == InstantDictType_LOCAL)
1440 oMidWin.oIndexWin.oResultWin.InsertLast(oLibs.dict_name(query_dictmask[i].index).c_str(), mark);
1441 else if (query_dictmask[i].type == InstantDictType_VIRTUAL)
1442 oMidWin.oIndexWin.oResultWin.InsertLast(oStarDictPlugins->VirtualDictPlugins.dict_name(query_dictmask[i].index), mark);
1443 else if (query_dictmask[i].type == InstantDictType_NET)
1444 oMidWin.oIndexWin.oResultWin.InsertLast(oStarDictPlugins->NetDictPlugins.dict_name(query_dictmask[i].index), mark);
1445 g_free(mark);
1446 }
1447 }
1448
1449 oMidWin.oTextWin.readwordtype = oReadWord.canRead(sOriginWord);
1450 if (oMidWin.oTextWin.readwordtype != READWORD_CANNOT) {
1451 oMidWin.oTextWin.pronounceWord = sOriginWord;
1452 }
1453 else {
1454 for (size_t i=0;i< query_dictmask.size(); i++) {
1455 if (pppWord[i] && strcmp(pppWord[i][0], sOriginWord)) {
1456 oMidWin.oTextWin.readwordtype = oReadWord.canRead(pppWord[i][0]);
1457 if (oMidWin.oTextWin.readwordtype != READWORD_CANNOT) {
1458 oMidWin.oTextWin.pronounceWord = pppWord[i][0];
1459 }
1460 break;
1461 }
1462 }
1463 }
1464 gtk_widget_set_sensitive(GTK_WIDGET(oMidWin.oToolWin.PronounceWordMenuButton), (oMidWin.oTextWin.readwordtype != READWORD_CANNOT));
1465 }
1466
ShowTreeDictDataToTextWin(guint32 offset,guint32 size,gint iTreeDict)1467 void AppCore::ShowTreeDictDataToTextWin(guint32 offset, guint32 size, gint iTreeDict)
1468 {
1469 oMidWin.oTextWin.ShowTreeDictData(oTreeDicts.poGetWordData(offset, size, iTreeDict));
1470 oMidWin.oTextWin.query_result = TEXT_WIN_TREEDICT;
1471
1472 oMidWin.oIndexWin.oResultWin.Clear();
1473 }
1474
ShowNotFoundToTextWin(const char * sWord,const char * sReason,TextWinQueryResult query_result)1475 void AppCore::ShowNotFoundToTextWin(const char* sWord,const char* sReason, TextWinQueryResult query_result)
1476 {
1477 bool have_netdict = false;
1478 for (size_t iLib=0; iLib<query_dictmask.size(); iLib++) {
1479 if (query_dictmask[iLib].type == InstantDictType_NET) {
1480 have_netdict = true;
1481 break;
1482 }
1483 }
1484 bool enable_netdict = conf->get_bool_at("network/enable_netdict");
1485 if (!enable_netdict && !have_netdict) {
1486 oMidWin.oTextWin.Show(sReason);
1487 }
1488 oMidWin.oTextWin.query_result = query_result;
1489 oMidWin.oTextWin.queryWord = sWord;
1490
1491 oMidWin.oIndexWin.oResultWin.Clear();
1492
1493 oMidWin.oTextWin.readwordtype = oReadWord.canRead(sWord);
1494 if (oMidWin.oTextWin.readwordtype != READWORD_CANNOT)
1495 oMidWin.oTextWin.pronounceWord = sWord;
1496 gtk_widget_set_sensitive(GTK_WIDGET(oMidWin.oToolWin.PronounceWordMenuButton), oMidWin.oTextWin.readwordtype != READWORD_CANNOT);
1497 }
1498
TopWinEnterWord()1499 void AppCore::TopWinEnterWord()
1500 {
1501 const gchar *text = oTopWin.get_text();
1502 if (text[0]=='\0')
1503 return;
1504 oTopWin.select_region_in_text(0, -1);
1505 oTopWin.InsertHisList(text);
1506 oTopWin.InsertBackList();
1507 std::string res;
1508 switch (analyse_query(text, res)) {
1509 case qtFUZZY:
1510 LookupWithFuzzyToMainWin(res.c_str());
1511 break;
1512 case qtPATTERN:
1513 LookupWithRuleToMainWin(res.c_str());
1514 break;
1515 case qtREGEX:
1516 LookupWithRegexToMainWin(res.c_str());
1517 break;
1518 case qtFULLTEXT:
1519 LookupDataToMainWin(res.c_str());
1520 return;
1521 default:
1522 if (!conf->get_bool_at("main_window/search_while_typing")) {
1523 if (oMidWin.oTextWin.queryWord != res) {
1524 bool showfirst = conf->get_bool_at("main_window/showfirst_when_notfound");
1525 bool find = SimpleLookupToTextWin(res.c_str(), iCurrentIndex, NULL, true, !showfirst);
1526 if (!find && showfirst) {
1527 const gchar *sug_word = oLibs.GetSuggestWord(res.c_str(), iCurrentIndex, query_dictmask, 0);
1528 if (sug_word) {
1529 gchar *suit_word = g_strdup(sug_word);
1530 SimpleLookupToTextWin(suit_word, iCurrentIndex, NULL, false, true, true);
1531 g_free(suit_word);
1532 } else {
1533 ShowNotFoundToTextWin(res.c_str(), _("<Not Found!>"), TEXT_WIN_NOT_FOUND);
1534 }
1535 }
1536 ListWords(iCurrentIndex);
1537 break;
1538 }
1539 }
1540 switch (oMidWin.oTextWin.query_result) {
1541 case TEXT_WIN_NOT_FOUND:
1542 case TEXT_WIN_SHOW_FIRST:
1543 case TEXT_WIN_NET_NOT_FOUND:
1544 case TEXT_WIN_NET_SHOW_FIRST:
1545 LookupWithFuzzyToMainWin(res.c_str());
1546 if (conf->get_bool_at("network/enable_netdict")) {
1547 std::string word = "/";
1548 word += res;
1549 STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_LOOKUP, word.c_str());
1550 if (!oStarDictClient.try_cache(c)) {
1551 waiting_mainwin_lookupcmd_seq = c->seq;
1552 oStarDictClient.send_commands(1, c);
1553 }
1554 }
1555 return;
1556 case TEXT_WIN_INFO:
1557 case TEXT_WIN_TREEDICT:
1558 {
1559 GtkTreeSelection *selection =
1560 gtk_tree_view_get_selection(oMidWin.oIndexWin.oListWin.treeview_);
1561 GtkTreeModel *model;
1562 GtkTreeIter iter;
1563 gboolean selected = gtk_tree_selection_get_selected(selection,&model,&iter);
1564 bool not_first_row=false;
1565 if (selected) {
1566 gchar *path_str = gtk_tree_model_get_string_from_iter(model,&iter);
1567 if (!strcmp(path_str,"0"))
1568 not_first_row = false;
1569 else
1570 not_first_row = true;
1571 g_free(path_str);
1572 }
1573 if (!selected || not_first_row) {
1574 // now select the first row.
1575 GtkTreePath* path = gtk_tree_path_new_first();
1576 gtk_tree_model_get_iter(model,&iter,path);
1577 gtk_tree_selection_select_iter(selection,&iter);
1578 gtk_tree_view_scroll_to_cell(oMidWin.oIndexWin.oListWin.treeview_,
1579 path, NULL, FALSE, 0, 0);
1580 gtk_tree_path_free(path);
1581 return;
1582 } else {
1583 SimpleLookupToTextWin(res.c_str(), iCurrentIndex, res.c_str(), false); //text 's index is already cached.
1584 }
1585 break;
1586 }
1587 case TEXT_WIN_FOUND:
1588 case TEXT_WIN_NET_FOUND:
1589 if (oMidWin.oTextWin.queryWord != res) {
1590 //user have selected some other word in the list,now select the first word again.
1591 GtkTreePath* path = gtk_tree_path_new_first();
1592 GtkTreeModel *model =
1593 gtk_tree_view_get_model(oMidWin.oIndexWin.oListWin.treeview_);
1594 GtkTreeIter iter;
1595 gtk_tree_model_get_iter(model,&iter,path);
1596 GtkTreeSelection *selection =
1597 gtk_tree_view_get_selection(oMidWin.oIndexWin.oListWin.treeview_);
1598 gtk_tree_selection_select_iter(selection,&iter);
1599 gtk_tree_view_scroll_to_cell(
1600 oMidWin.oIndexWin.oListWin.treeview_, path, NULL, FALSE, 0, 0);
1601 gtk_tree_path_free(path);
1602 } else {
1603 if (gtk_widget_get_sensitive(GTK_WIDGET(oMidWin.oToolWin.PronounceWordMenuButton)))
1604 oReadWord.read(oMidWin.oTextWin.pronounceWord.c_str(), oMidWin.oTextWin.readwordtype);
1605 }
1606 return;
1607 default:
1608 /*nothing*/break;
1609 }//switch (oMidWin.oTextWin.query_result) {
1610 }
1611 if (conf->get_bool_at("network/enable_netdict")) {
1612 STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_LOOKUP, text);
1613 if (!oStarDictClient.try_cache(c)) {
1614 waiting_mainwin_lookupcmd_seq = c->seq;
1615 oStarDictClient.send_commands(1, c);
1616 }
1617 }
1618 LookupNetDict(text, true);
1619 }
1620
TopWinWordChange(const gchar * sWord)1621 void AppCore::TopWinWordChange(const gchar* sWord)
1622 {
1623 std::string res;
1624 switch (analyse_query(sWord, res)) {
1625 case qtPATTERN:
1626 oMidWin.oTextWin.Show(_("Press Enter to list the words that match the pattern."));
1627 break;
1628 case qtREGEX:
1629 oMidWin.oTextWin.Show(_("Press Enter to list the words that match this regular expression."));
1630 break;
1631 case qtFUZZY:
1632 if (strlen(sWord)==1)
1633 oMidWin.oTextWin.Show(_("Fuzzy query..."));
1634 break;
1635 case qtFULLTEXT:
1636 if (strlen(sWord)==1)
1637 oMidWin.oTextWin.Show(_("Full-text search..."));
1638 break;
1639 default:
1640 stop_word_change_timer();
1641 delayed_word_ = res;
1642 int word_change_timeout = conf->get_int_at("main_window/word_change_timeout");
1643 if(word_change_timeout > 0) {
1644 word_change_timeout_id = g_timeout_add(word_change_timeout, on_word_change_timeout, this);
1645 } else {
1646 //Allow word_change_timeout to be 0, so do an immediate search.
1647 on_word_change_timeout(this);
1648 }
1649 }
1650 }
1651
on_word_change_timeout(gpointer data)1652 gboolean AppCore::on_word_change_timeout(gpointer data)
1653 {
1654 AppCore *app = static_cast<AppCore *>(data);
1655 bool showfirst = conf->get_bool_at("main_window/showfirst_when_notfound");
1656 bool find = app->SimpleLookupToTextWin(app->delayed_word_.c_str(),
1657 app->iCurrentIndex, NULL, true,
1658 !showfirst);
1659 if (!find && showfirst) {
1660 const gchar *sug_word = app->oLibs.GetSuggestWord(app->delayed_word_.c_str(), app->iCurrentIndex, app->query_dictmask, 0);
1661 if (sug_word) {
1662 gchar *suit_word = g_strdup(sug_word);
1663 app->SimpleLookupToTextWin(suit_word, app->iCurrentIndex, NULL, false, true, true);
1664 g_free(suit_word);
1665 } else {
1666 app->ShowNotFoundToTextWin(app->delayed_word_.c_str(), _("<Not Found!>"), TEXT_WIN_NOT_FOUND);
1667 }
1668 }
1669 app->ListWords(app->iCurrentIndex);
1670
1671 bool enable_netdict = conf->get_bool_at("network/enable_netdict");
1672 if (enable_netdict) {
1673 STARDICT::Cmd *c = new STARDICT::Cmd(STARDICT::CMD_LOOKUP, app->delayed_word_.c_str());
1674 if (!app->oStarDictClient.try_cache(c)) {
1675 app->waiting_mainwin_lookupcmd_seq = c->seq;
1676 app->oStarDictClient.send_commands(1, c);
1677 }
1678 }
1679 app->LookupNetDict(app->delayed_word_.c_str(), true);
1680
1681 app->word_change_timeout_id = 0;//next line destroy timer
1682 return FALSE;
1683 }
1684
ListWords(CurrentIndex * iIndex)1685 void AppCore::ListWords(CurrentIndex* iIndex)
1686 {
1687 CurrentIndex *iCurrent = (CurrentIndex*)g_memdup(iIndex, sizeof(CurrentIndex)*query_dictmask.size());
1688
1689 oMidWin.oIndexWin.oListWin.Clear();
1690 oMidWin.oIndexWin.oListWin.SetModel(true);
1691 oMidWin.oIndexWin.oListWin.list_word_type = LIST_WIN_NORMAL_LIST;
1692
1693 int iWordCount=0;
1694 const gchar * poCurrentWord=oLibs.poGetCurrentWord(iCurrent, query_dictmask, 0);
1695 if (poCurrentWord) {
1696 oMidWin.oIndexWin.oListWin.InsertLast(poCurrentWord);
1697 iWordCount++;
1698
1699 while (iWordCount<LIST_WIN_ROW_NUM &&
1700 (poCurrentWord=oLibs.poGetNextWord(NULL,iCurrent, query_dictmask, 0))) {
1701 oMidWin.oIndexWin.oListWin.InsertLast(poCurrentWord);
1702 iWordCount++;
1703 }
1704 oMidWin.oIndexWin.oListWin.ReScroll();
1705 }
1706 g_free(iCurrent);
1707 }
1708
ListPreWords(const char * sWord)1709 void AppCore::ListPreWords(const char*sWord)
1710 {
1711 oMidWin.oIndexWin.oListWin.Clear();
1712 CurrentIndex *iPreIndex = (CurrentIndex *)g_malloc(sizeof(CurrentIndex) * query_dictmask.size());
1713 const gchar *preword = oLibs.poGetPreWord(sWord, iPreIndex, query_dictmask, 0);
1714 if (preword) {
1715 int iWordCount=1;
1716 oMidWin.oIndexWin.oListWin.Prepend(preword);
1717 while (iWordCount<15 && (preword=oLibs.poGetPreWord(NULL,iPreIndex, query_dictmask, 0))) {
1718 oMidWin.oIndexWin.oListWin.Prepend(preword);
1719 iWordCount++;
1720 }
1721 oMidWin.oIndexWin.oListWin.ReScroll();
1722 }
1723 g_free(iPreIndex);
1724 }
1725
ListNextWords(const char * sWord)1726 void AppCore::ListNextWords(const char*sWord)
1727 {
1728 oMidWin.oIndexWin.oListWin.Clear();
1729 CurrentIndex *iNextIndex = (CurrentIndex *)g_malloc(sizeof(CurrentIndex) * query_dictmask.size());
1730 const gchar *nextword = oLibs.poGetNextWord(sWord, iNextIndex, query_dictmask, 0);
1731 if (nextword) {
1732 int iWordCount=1;
1733 oMidWin.oIndexWin.oListWin.InsertLast(nextword);
1734 while (iWordCount<30 && (nextword = oLibs.poGetNextWord(NULL, iNextIndex, query_dictmask, 0))) {
1735 oMidWin.oIndexWin.oListWin.InsertLast(nextword);
1736 iWordCount++;
1737 }
1738 oMidWin.oIndexWin.oListWin.ReScroll();
1739 }
1740 g_free(iNextIndex);
1741 }
1742
Query(const gchar * word)1743 void AppCore::Query(const gchar *word)
1744 {
1745 oTopWin.InsertHisList(oTopWin.get_text());
1746 oTopWin.InsertBackList();
1747 oTopWin.SetText(word);
1748 std::string res;
1749 switch (analyse_query(word, res)) {
1750 case qtSIMPLE:
1751 break;
1752 default:
1753 TopWinEnterWord();
1754 break;
1755 }
1756
1757 oTopWin.TextSelectAll();
1758 oTopWin.grab_focus();
1759 oTopWin.InsertHisList(word);
1760 oTopWin.InsertBackList(word);
1761 }
1762
ListClick(const gchar * word)1763 void AppCore::ListClick(const gchar *word)
1764 {
1765 oTopWin.InsertHisList(oTopWin.get_text());
1766 oTopWin.InsertBackList();
1767 oTopWin.SetText(word);
1768 oTopWin.InsertHisList(word);
1769 oTopWin.InsertBackList(word);
1770 oTopWin.grab_focus();
1771 }
1772
on_stardict_client_error(const char * error_msg)1773 void AppCore::on_stardict_client_error(const char *error_msg)
1774 {
1775 GtkWindow *parent;
1776 if (dict_manage_dlg && dict_manage_dlg->window && gtk_widget_get_visible(GTK_WIDGET(dict_manage_dlg->window))) {
1777 parent = GTK_WINDOW(dict_manage_dlg->window);
1778 } else if (prefs_dlg && prefs_dlg->window) {
1779 parent = GTK_WINDOW(prefs_dlg->window);
1780 } else {
1781 parent = GTK_WINDOW(window);
1782 }
1783 GtkWidget *message_dlg =
1784 gtk_message_dialog_new(
1785 parent,
1786 (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
1787 GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
1788 "%s", error_msg);
1789 gtk_dialog_set_default_response(GTK_DIALOG(message_dlg), GTK_RESPONSE_OK);
1790 gtk_window_set_resizable(GTK_WINDOW(message_dlg), FALSE);
1791 g_signal_connect_swapped (message_dlg, "response", G_CALLBACK (gtk_widget_destroy), message_dlg);
1792 gtk_widget_show(message_dlg);
1793 }
1794
on_stardict_client_register_end(const char * msg)1795 void AppCore::on_stardict_client_register_end(const char *msg)
1796 {
1797 if (prefs_dlg) {
1798 prefs_dlg->on_register_end(msg);
1799 }
1800 }
1801
on_stardict_client_getdictmask_end(const char * msg)1802 void AppCore::on_stardict_client_getdictmask_end(const char *msg)
1803 {
1804 if (dict_manage_dlg)
1805 dict_manage_dlg->network_getdictmask(msg);
1806 }
1807
on_stardict_client_getadinfo_end(const char * msg)1808 void AppCore::on_stardict_client_getadinfo_end(const char *msg)
1809 {
1810 if (dict_manage_dlg)
1811 dict_manage_dlg->network_getadinfo(msg);
1812 }
1813
on_stardict_client_dirinfo_end(const char * msg)1814 void AppCore::on_stardict_client_dirinfo_end(const char *msg)
1815 {
1816 if (dict_manage_dlg)
1817 dict_manage_dlg->network_dirinfo(msg);
1818 }
1819
on_stardict_client_dictinfo_end(const char * msg)1820 void AppCore::on_stardict_client_dictinfo_end(const char *msg)
1821 {
1822 if (dict_manage_dlg)
1823 dict_manage_dlg->network_dictinfo(msg);
1824 }
1825
on_stardict_client_maxdictcount_end(int count)1826 void AppCore::on_stardict_client_maxdictcount_end(int count)
1827 {
1828 if (dict_manage_dlg)
1829 dict_manage_dlg->network_maxdictcount(count);
1830 }
1831
on_stardict_client_previous_end(std::list<char * > * wordlist_response)1832 void AppCore::on_stardict_client_previous_end(std::list<char *> *wordlist_response)
1833 {
1834 if (!wordlist_response->empty()) {
1835 oMidWin.oIndexWin.oListWin.MergeWordList(wordlist_response);
1836 oMidWin.oIndexWin.oListWin.ReScroll();
1837 }
1838 }
1839
on_stardict_client_next_end(std::list<char * > * wordlist_response)1840 void AppCore::on_stardict_client_next_end(std::list<char *> *wordlist_response)
1841 {
1842 if (!wordlist_response->empty()) {
1843 oMidWin.oIndexWin.oListWin.MergeWordList(wordlist_response);
1844 oMidWin.oIndexWin.oListWin.ReScroll();
1845 }
1846 }
1847
on_stardict_client_lookup_end(const struct STARDICT::LookupResponse * lookup_response,unsigned int seq)1848 void AppCore::on_stardict_client_lookup_end(const struct STARDICT::LookupResponse *lookup_response, unsigned int seq)
1849 {
1850 if (seq != 0 && waiting_mainwin_lookupcmd_seq != seq)
1851 return;
1852 oMidWin.oTextWin.Show(&(lookup_response->dict_response), lookup_response->listtype);
1853 if (lookup_response->listtype == STARDICT::LookupResponse::ListType_List || lookup_response->listtype == STARDICT::LookupResponse::ListType_Rule_List || lookup_response->listtype == STARDICT::LookupResponse::ListType_Regex_List) {
1854 if (!lookup_response->wordlist->empty()) {
1855 oMidWin.oIndexWin.oListWin.MergeWordList(lookup_response->wordlist);
1856 oMidWin.oIndexWin.oListWin.ReScroll();
1857 }
1858 } else if (lookup_response->listtype == STARDICT::LookupResponse::ListType_Fuzzy_List) {
1859 if (!lookup_response->wordlist->empty()) {
1860 oMidWin.oIndexWin.oListWin.MergeFuzzyList(lookup_response->wordlist);
1861 oMidWin.oIndexWin.oListWin.ReScroll();
1862 }
1863 } else if (lookup_response->listtype == STARDICT::LookupResponse::ListType_Tree) {
1864 if (!lookup_response->wordtree->empty()) {
1865 oMidWin.oIndexWin.oListWin.SetTreeModel(lookup_response->wordtree);
1866 oMidWin.oIndexWin.oListWin.ReScroll();
1867 }
1868 }
1869 }
1870
on_stardict_client_floatwin_lookup_end(const struct STARDICT::LookupResponse * lookup_response,unsigned int seq)1871 void AppCore::on_stardict_client_floatwin_lookup_end(const struct STARDICT::LookupResponse *lookup_response, unsigned int seq)
1872 {
1873 if(seq == 0 || composite_lookup_float_win.got_StarDict_net_responce(seq)) {
1874 oFloatWin.AppendTextStarDictNet(&(lookup_response->dict_response));
1875 if(composite_lookup_float_win.is_got_all_responses())
1876 oFloatWin.EndLookup();
1877 }
1878 }
1879
on_http_client_error(HttpClient * http_client,const char * error_msg)1880 void AppCore::on_http_client_error(HttpClient *http_client, const char *error_msg)
1881 {
1882 if (http_client->callback_func_) {
1883 http_client->callback_func_(NULL, 0, http_client->userdata);
1884 } else {
1885 GtkWindow *parent;
1886 if (dict_manage_dlg && dict_manage_dlg->window && gtk_widget_get_visible(GTK_WIDGET(dict_manage_dlg->window))) {
1887 parent = GTK_WINDOW(dict_manage_dlg->window);
1888 } else if (prefs_dlg && prefs_dlg->window) {
1889 parent = GTK_WINDOW(prefs_dlg->window);
1890 } else {
1891 parent = GTK_WINDOW(window);
1892 }
1893 GtkWidget *message_dlg =
1894 gtk_message_dialog_new(
1895 parent,
1896 (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
1897 GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
1898 "%s", error_msg);
1899 gtk_dialog_set_default_response(GTK_DIALOG(message_dlg), GTK_RESPONSE_OK);
1900 gtk_window_set_resizable(GTK_WINDOW(message_dlg), FALSE);
1901 g_signal_connect_swapped (message_dlg, "response", G_CALLBACK (gtk_widget_destroy), message_dlg);
1902 gtk_widget_show(message_dlg);
1903 }
1904 oHttpManager.Remove(http_client);
1905 }
1906
on_http_client_response(HttpClient * http_client)1907 void AppCore::on_http_client_response(HttpClient *http_client)
1908 {
1909 if (http_client->callback_func_) {
1910 http_client->callback_func_(http_client->buffer, http_client->buffer_len, http_client->userdata);
1911 oHttpManager.Remove(http_client);
1912 return;
1913 }
1914 oHttpManager.Remove(http_client);
1915 }
1916
PopupPrefsDlg()1917 void AppCore::PopupPrefsDlg()
1918 {
1919 if (!prefs_dlg) {
1920 prefs_dlg = new PrefsDlg(GTK_WINDOW(window),
1921 get_impl(oAppSkin.icon),
1922 unlock_keys->possible_combs());
1923 bool enbcol =
1924 conf->get_bool_at("dictionary/enable_collation");
1925 int colf =
1926 conf->get_int_at("dictionary/collate_function");
1927 bool exiting = prefs_dlg->ShowModal();
1928 delete prefs_dlg;
1929 prefs_dlg = NULL;
1930 if (exiting)
1931 return;
1932 if (enbcol == conf->get_bool_at("dictionary/enable_collation") &&
1933 colf == conf->get_int_at("dictionary/collate_function"))
1934 return;
1935 progress_win pw(GTK_WINDOW(gpAppFrame->window));
1936 reload_show_progress_t rsp(pw);
1937 show_progress_t *old_progress = oLibs.get_show_progress();
1938 oLibs.set_show_progress(&rsp);
1939 reload_dicts();
1940 oLibs.set_show_progress(old_progress);
1941 }
1942 }
1943
reload_dicts()1944 void AppCore::reload_dicts()
1945 {
1946 std::list<DictItemId> load_list;
1947 GetUsedDictList(load_list);
1948 std::list<std::string> s_load_list;
1949 DictItemId::convert(s_load_list, load_list);
1950 oLibs.reload(s_load_list,
1951 conf->get_bool_at("dictionary/enable_collation") ? CollationLevel_SINGLE : CollationLevel_NONE,
1952 int_to_colate_func(conf->get_int_at("dictionary/collate_function")));
1953 UpdateDictMask();
1954
1955 const gchar *sWord = oTopWin.get_text();
1956
1957 if (sWord && sWord[0])
1958 TopWinWordChange(sWord);
1959 }
1960
PopupDictManageDlg()1961 void AppCore::PopupDictManageDlg()
1962 {
1963
1964 if (!dict_manage_dlg)
1965 dict_manage_dlg = new DictManageDlg(GTK_WINDOW(window), get_impl(oAppSkin.index_wazard), get_impl(oAppSkin.index_appendix));
1966 bool dictmanage_config_changed;
1967 if (dict_manage_dlg->Show(dictmanage_config_changed))
1968 return;
1969 if (dictmanage_config_changed) {
1970 progress_win pw(GTK_WINDOW(gpAppFrame->window));
1971 reload_show_progress_t rsp(pw);
1972 show_progress_t *old_progress = oLibs.get_show_progress();
1973 oLibs.set_show_progress(&rsp);
1974 reload_dicts();
1975 oLibs.set_show_progress(old_progress);
1976 }
1977 }
1978
PopupPluginManageDlg()1979 void AppCore::PopupPluginManageDlg()
1980 {
1981 if (!plugin_manage_dlg) {
1982 plugin_manage_dlg = new PluginManageDlg();
1983 bool dict_changed;
1984 bool order_changed;
1985 bool exiting = plugin_manage_dlg->ShowModal(GTK_WINDOW(window), dict_changed, order_changed);
1986 delete plugin_manage_dlg;
1987 plugin_manage_dlg = NULL;
1988 if (exiting)
1989 return;
1990 if (order_changed) {
1991 #ifdef _WIN32
1992 std::list<std::string> plugin_order_list;
1993 {
1994 const std::list<std::string>& plugin_order_list_rel
1995 = conf->get_strlist("/apps/stardict/manage_plugins/plugin_order_list");
1996 abs_path_to_data_dir(plugin_order_list_rel, plugin_order_list);
1997 }
1998 #else
1999 const std::list<std::string>& plugin_order_list
2000 = conf->get_strlist("/apps/stardict/manage_plugins/plugin_order_list");
2001 #endif
2002 oStarDictPlugins->VirtualDictPlugins.reorder(plugin_order_list);
2003 oStarDictPlugins->NetDictPlugins.reorder(plugin_order_list);
2004 oMidWin.oToolWin.UpdatePronounceMenu();
2005 }
2006 if (dict_changed) {
2007 UpdateDictMask();
2008
2009 const gchar *sWord = oTopWin.get_text();
2010 if (sWord && sWord[0])
2011 TopWinWordChange(sWord);
2012 }
2013 }
2014 }
2015
stop_word_change_timer()2016 void AppCore::stop_word_change_timer()
2017 {
2018 if (word_change_timeout_id) {
2019 g_source_remove(word_change_timeout_id);
2020 word_change_timeout_id = 0;
2021 }
2022 }
2023
End()2024 void AppCore::End()
2025 {
2026 stop_word_change_timer();
2027 oSelection.End();
2028 #ifdef _WIN32
2029 oClipboard.End();
2030 oMouseover.End();
2031 #endif
2032 #ifdef ENABLE_LOG_WINDOW
2033 gLogWindow.End();
2034 #endif
2035 oHotkey.End();
2036 oFloatWin.End();
2037
2038 oDockLet.reset(0);
2039
2040 if (dict_manage_dlg)
2041 dict_manage_dlg->Close();
2042 if (prefs_dlg)
2043 prefs_dlg->Close(); // After user open the preferences dialog, then choose quit in the notification icon, this dialog can be closed.
2044 oTopWin.Destroy();
2045 oMidWin.oIndexWin.oListWin.Destroy();
2046 oBottomWin.Destroy();
2047
2048 gtk_widget_destroy(window);
2049 }
2050
Init(const gchar * queryword)2051 void AppCore::Init(const gchar *queryword)
2052 {
2053 conf->notify_add("/apps/stardict/preferences/main_window/hide_list",
2054 sigc::mem_fun(this, &AppCore::on_main_win_hide_list_changed));
2055 conf->notify_add("/apps/stardict/preferences/dictionary/scan_selection",
2056 sigc::mem_fun(this, &AppCore::on_dict_scan_select_changed));
2057 conf->notify_add("/apps/stardict/preferences/dictionary/scan_modifier_key",
2058 sigc::mem_fun(this, &AppCore::on_scan_modifier_key_changed));
2059
2060 g_debug(_("Loading skin..."));
2061 #ifdef _WIN32
2062 oAppSkin.load(abs_path_to_data_dir(conf->get_string_at("main_window/skin")));
2063 #else
2064 oAppSkin.load(conf->get_string_at("main_window/skin"));
2065 #endif
2066 g_debug(_("Skin loaded."));
2067
2068 if (!CmdLineOptions::get_hide())
2069 stardict_splash.show();
2070
2071 Create(queryword);
2072
2073 #ifdef CONFIG_GNOME
2074 stardict_app_server =
2075 stardict_application_server_new(gdk_screen_get_default());
2076 #endif
2077
2078 stardict_splash.on_mainwin_finish();
2079 oStarDictPlugins->MiscPlugins.on_mainwin_finish();
2080 gtk_main();
2081 }
2082
Quit()2083 void AppCore::Quit()
2084 {
2085 if (!conf->get_bool_at("main_window/maximized")) {
2086 gint width, height;
2087 gtk_window_get_size(GTK_WINDOW(window), &width, &height);
2088 conf->set_int_at("main_window/window_width", width);
2089 conf->set_int_at("main_window/window_height", height);
2090 }
2091 gint pos = gtk_paned_get_position(GTK_PANED(oMidWin.hpaned));
2092 conf->set_int_at("main_window/hpaned_pos", pos);
2093
2094 End();
2095
2096 #ifdef CONFIG_GNOME
2097 bonobo_object_unref (stardict_app_server);
2098 #endif
2099 unlock_keys.reset(0);
2100 conf.reset(0);
2101 gtk_main_quit();
2102 }
2103
on_main_win_hide_list_changed(const baseconfval * hideval)2104 void AppCore::on_main_win_hide_list_changed(const baseconfval* hideval)
2105 {
2106 bool hide = static_cast<const confval<bool> *>(hideval)->val_;
2107
2108 if (hide) {
2109 gtk_widget_hide(oMidWin.oToolWin.HideListButton);
2110 gtk_widget_show(oMidWin.oToolWin.ShowListButton);
2111 gtk_widget_hide(oMidWin.oLeftWin.vbox);
2112 gtk_widget_hide(oMidWin.oIndexWin.notebook);
2113 } else {
2114 gtk_widget_hide(oMidWin.oToolWin.ShowListButton);
2115 gtk_widget_show(oMidWin.oToolWin.HideListButton);
2116 gtk_widget_show(oMidWin.oLeftWin.vbox);
2117 gtk_widget_show(oMidWin.oIndexWin.notebook);
2118 }
2119 }
2120
on_dict_scan_select_changed(const baseconfval * scanval)2121 void AppCore::on_dict_scan_select_changed(const baseconfval* scanval)
2122 {
2123 bool scan = static_cast<const confval<bool> *>(scanval)->val_;
2124
2125 if (scan != static_cast<bool>(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(oBottomWin.ScanSelectionCheckButton))))
2126 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oBottomWin.ScanSelectionCheckButton), scan);
2127
2128 oDockLet->set_scan_mode(scan);
2129 if (gtk_widget_get_visible(GTK_WIDGET(window)))
2130 oDockLet->hide_state();
2131 if (scan) {
2132 bool lock=conf->get_bool_at("floating_window/lock");
2133 if (lock && !oFloatWin.getQueryingWord().empty())
2134 oFloatWin.Show();
2135 oSelection.start();
2136 #ifdef _WIN32
2137 if (conf->get_bool_at("dictionary/scan_clipboard")) {
2138 oClipboard.start();
2139 }
2140 oMouseover.start();
2141 #endif
2142 } else {
2143 oFloatWin.Hide();
2144 oSelection.stop();
2145 #ifdef _WIN32
2146 if (conf->get_bool_at("dictionary/scan_clipboard")) {
2147 oClipboard.stop();
2148 }
2149 oMouseover.stop();
2150 #endif
2151 }
2152 }
2153
on_scan_modifier_key_changed(const baseconfval * keyval)2154 void AppCore::on_scan_modifier_key_changed(const baseconfval* keyval)
2155 {
2156 int key = static_cast<const confval<int> *>(keyval)->val_;
2157 unlock_keys->set_comb(combnum2str(key));
2158 }
2159
GetPureEnglishAlpha(gchar * str)2160 gchar* GetPureEnglishAlpha(gchar *str)
2161 {
2162 while (*str && (!((*str >= 'a' && *str <='z')||(*str >= 'A' && *str <='Z'))))
2163 str++;
2164 gchar *p = str;
2165 while (*p && ((*p >= 'a' && *p <='z')||(*p >= 'A' && *p <='Z')||(*p==' ')))
2166 p++;
2167 *p='\0';
2168 return str;
2169 }
2170
GetHeadWord(gchar * str)2171 gchar* GetHeadWord(gchar *str)
2172 {
2173 while (g_ascii_isspace(*str))
2174 str++;
2175 glong len = g_utf8_strlen(str, -1);
2176 if (len) {
2177 gchar *last_str = g_utf8_offset_to_pointer(str, len-1);
2178 gunichar last = g_utf8_get_char(last_str);
2179 while ((g_unichar_isspace(last) || g_unichar_ispunct(last)) || g_unichar_isdigit(last)) {
2180 *last_str = '\0';
2181 last_str = g_utf8_find_prev_char(str, last_str);
2182 if (!last_str)
2183 break;
2184 last = g_utf8_get_char(last_str);
2185 }
2186 }
2187 return str;
2188 }
2189
stardict_on_enter_notify(GtkWidget * widget,GdkEventCrossing * event,gpointer data)2190 gboolean stardict_on_enter_notify(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
2191 {
2192 play_sound_on_event("buttonactive");
2193
2194 return FALSE;
2195 }
2196
2197 #ifdef CONFIG_GNOME
2198 static void
stardict_handle_automation_cmdline(const gchar * queryword)2199 stardict_handle_automation_cmdline (const gchar *queryword)
2200 {
2201 CORBA_Environment env;
2202 GNOME_Stardict_Application server;
2203
2204 CORBA_exception_init (&env);
2205 CORBA_char id[] = "OAFIID:GNOME_Stardict_Application";
2206
2207 server = bonobo_activation_activate_from_id (id, 0, NULL, &env);
2208 if (!server) {
2209 gdk_notify_startup_complete ();
2210 return;
2211 }
2212 //g_return_if_fail (server != NULL);
2213
2214 if (CmdLineOptions::get_quit()) {
2215 GNOME_Stardict_Application_quit (server, &env);
2216 }
2217 else {
2218 if (queryword) {
2219 GNOME_Stardict_Application_queryWord (server, queryword, &env);
2220 }
2221 if (CmdLineOptions::get_hide()) {
2222 GNOME_Stardict_Application_hide (server, &env);
2223 } else {
2224 GNOME_Stardict_Application_grabFocus (server, &env);
2225 g_message(_("StarDict is already running. Using the running process."));
2226 }
2227 }
2228
2229
2230 bonobo_object_release_unref (server, &env);
2231 CORBA_exception_free (&env);
2232
2233
2234 /* we never popup a window, so tell startup-notification that
2235 * we're done */
2236 gdk_notify_startup_complete ();
2237 }
2238
2239 /*
2240 static void client_die_cb (GnomeClient *client, gpointer client_data)
2241 {
2242 gpAppFrame->Quit();
2243 }
2244
2245 static gboolean save_yourself_cb (GnomeClient *client,
2246 gint phase,
2247 GnomeRestartStyle save_style,
2248 gint shutdown,
2249 GnomeInteractStyle interact_style,
2250 gint fast,
2251 gpointer client_data)
2252 {
2253 gchar *argv[] = {NULL, NULL, NULL};
2254 gchar *word = NULL;
2255 gint argc = 1;
2256
2257 argv[0] = (gchar *)client_data;
2258
2259 if (gpAppFrame->window) {
2260 if (!gtk_widget_get_visible(GTK_WIDGET(gpAppFrame->window)))
2261 argv[argc++] = (gchar *)"-h";
2262 }
2263
2264 const gchar *text = gpAppFrame->oTopWin.get_text();
2265 if (text[0]) {
2266 word = g_strdup(text);
2267 argv[argc++] = word;
2268 }
2269
2270 gnome_client_set_restart_command(client, argc, argv);
2271 gnome_client_set_clone_command(client, argc, argv);
2272 if (word)
2273 g_free(word);
2274
2275 return true;
2276 }
2277 */
2278 #endif
2279
2280 #if defined(_WIN32) && defined(_MSC_VER)
2281 /* Synchronize environment variables in CRTs.
2282 See section "Two copies of CRT" in doc/README_windows.txt for more details. */
synchronize_crt_enviroment(void)2283 void synchronize_crt_enviroment(void)
2284 {
2285 const char* varname = "LANG";
2286 size_t size;
2287 if(getenv_s(&size, NULL, 0, varname)) {
2288 g_warning("Unable to get the value of the %s environment variable", varname);
2289 return;
2290 }
2291 if(size == 0)
2292 return; // variable is not found
2293 std::vector<char> buf(size);
2294 if(getenv_s(&size, &buf[0], size, varname)) {
2295 g_warning("Unable to get the value of the %s environment variable", varname);
2296 return;
2297 }
2298 if(!g_setenv(varname, &buf[0], TRUE)) {
2299 g_warning("Unable to set the %s environment variable.", varname);
2300 return;
2301 }
2302 }
2303 #endif
2304
2305 #ifdef _WIN32
stardict_main(HINSTANCE hInstance,int argc,char ** argv)2306 DLLIMPORT int stardict_main(HINSTANCE hInstance, int argc, char **argv)
2307 #else
2308 int main(int argc,char **argv)
2309 #endif
2310 {
2311 #if defined(_WIN32)
2312 stardictexe_hInstance = hInstance;
2313 #endif // #if defined(_WIN32)
2314 CmdLineOptions::pre_parse_arguments(argc, argv);
2315 const char* const dirs_config_file = CmdLineOptions::get_dirs_config_pre();
2316 conf_dirs.reset(new AppDirs(dirs_config_file ? dirs_config_file : ""));
2317 app_dirs = conf_dirs.get();
2318 bindtextdomain (GETTEXT_PACKAGE, conf_dirs->get_locale_dir().c_str());
2319 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2320 textdomain (GETTEXT_PACKAGE);
2321
2322 #if defined(_WIN32) && defined(_MSC_VER)
2323 synchronize_crt_enviroment();
2324 #endif
2325 #if defined(_WIN32) || defined(CONFIG_GTK) || defined(CONFIG_GNOME) || defined(CONFIG_MAEMO) || defined(CONFIG_DARWIN)
2326 gtk_init(&argc, &argv);
2327 #endif
2328 /* Register an interim logger.
2329 On Windows, without the logger all output produced by g_option_context_parse will be lost.
2330 For example, g_option_context_parse prints usage message when stardict is invoked with --help option.
2331 The problem is g_option_context_parse uses g_print function to print messages,
2332 but this function produce no output on windows console. See test_windows_console
2333 function to check what works with windows console.
2334 */
2335 logger.reset(new Logger(MessageLevel_MESSAGE, MessageLevel_NONE));
2336 #if defined(_WIN32) && defined(_DEBUG)
2337 //test_windows_console();
2338 #endif
2339 #ifdef CONFIG_GPE
2340 if (gpe_application_init (&argc, &argv) == FALSE)
2341 exit (1);
2342 #endif
2343 GOptionContext *context;
2344 context = g_option_context_new(_("- Lookup words"));
2345 g_option_context_add_main_entries(context, CmdLineOptions::get_options(), GETTEXT_PACKAGE);
2346 #ifndef CONFIG_GNOME
2347 glib::Error err;
2348 if (!g_option_context_parse(context, &argc, &argv, get_addr(err))) {
2349 g_warning(_("Options parsing failed: %s\n"), err->message);
2350 g_option_context_free(context);
2351 return EXIT_FAILURE;
2352 }
2353 g_option_context_free(context);
2354 #else // #ifndef CONFIG_GNOME
2355 //GnomeProgram *program;
2356 gnome_program_init ("stardict", VERSION,
2357 LIBGNOME_MODULE, argc, argv,
2358 GNOME_PARAM_GOPTION_CONTEXT, context,
2359 GNOME_PARAM_HUMAN_READABLE_NAME,
2360 _("Dictionary"),
2361 GNOME_PARAM_APP_DATADIR, conf_dirs->get_system_data_dir().c_str(),
2362 NULL);
2363 bonobo_init(&argc, argv);
2364 #endif // #ifndef CONFIG_GNOME
2365
2366 const char *query_word = NULL;
2367 if(CmdLineOptions::get_query_words())
2368 query_word = CmdLineOptions::get_query_words()[0];
2369
2370 logger->set_console_message_level(CmdLineOptions::get_console_message_level());
2371 logger->set_log_message_level(CmdLineOptions::get_log_message_level());
2372
2373 #ifndef CONFIG_GNOME
2374 #ifdef _WIN32
2375 if (CmdLineOptions::get_newinstance() == FALSE) {
2376 gchar *title=g_locale_from_utf8(_("StarDict"), -1, NULL, NULL, NULL);
2377 HWND ll_winhandle = FindWindowA("gdkWindowToplevel", title);
2378 g_free(title);
2379 if (ll_winhandle > 0) {
2380 if (IsIconic(ll_winhandle))
2381 ShowWindow(ll_winhandle,SW_RESTORE);
2382 else
2383 SetForegroundWindow(ll_winhandle);
2384 g_message("Stardict is already running.");
2385 return EXIT_SUCCESS;
2386 }
2387 }
2388 #endif // #ifdef _WIN32
2389 #else // #ifndef CONFIG_GNOME
2390 if (CmdLineOptions::get_newinstance() == FALSE) {
2391 CORBA_Object factory;
2392 CORBA_char id[] = "OAFIID:GNOME_Stardict_Factory";
2393 factory = bonobo_activation_activate_from_id(id,
2394 Bonobo_ACTIVATION_FLAG_EXISTING_ONLY,
2395 NULL, NULL);
2396
2397 if (factory != NULL) {
2398 /* there is an instance already running, so send
2399 * commands to it if needed
2400 */
2401 stardict_handle_automation_cmdline (query_word);
2402 /* and we're done */
2403 return EXIT_SUCCESS;
2404 }
2405 }
2406
2407 /*
2408 GnomeClient *client;
2409 if ((client = gnome_master_client()) != NULL) {
2410 g_signal_connect (client, "save_yourself", G_CALLBACK (save_yourself_cb), (gpointer) argv[0]);
2411 g_signal_connect (client, "die", G_CALLBACK (client_die_cb), NULL);
2412 }
2413 */
2414 #endif // #ifndef CONFIG_GNOME
2415 g_debug(_("Loading StarDict configuration..."));
2416 conf.reset(new AppConf);
2417 g_debug(_("StarDict configuration loaded."));
2418 AppCore oAppCore;
2419 gpAppFrame = &oAppCore;
2420 oAppCore.Init(query_word);
2421
2422 return EXIT_SUCCESS;
2423 }
2424