1 /*
2 * Copyright 1999, TaBE Project, All Rights Reserved.
3 * Copyright 1999, Pai-Hsiang Hsiao, All Rights Reserved.
4 *
5 * $Id: GTKTsi.c,v 1.2 2002/08/11 01:58:11 kcwu Exp $
6 *
7 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include <pthread.h>
13
14 #include <gtk/gtk.h>
15
16 #include <tabe.h>
17
18 #include "bims.h"
19
20 /* signal handler for quit */
21 static void main_quit(GtkWidget *widget, gpointer data);
22 /* signal handler for next and prev */
23 static void browse_next(GtkWidget *widget, gpointer data);
24 static void browse_prev(GtkWidget *widget, gpointer data);
25 /* signal handler for search and set */
26 static void browse_set(GtkWidget *widget, gpointer data);
27 /* signal handler for edit */
28 static void browse_edit(GtkWidget *widget, gpointer data);
29 /* signal handler for add */
30 static void browse_add(GtkWidget *widget, gpointer data);
31 /* signal handler for delete */
32 static void browse_delete(GtkWidget *widget, gpointer data);
33 /* signal handler for selection done */
34 static void browse_selected(GtkWidget *widget,
35 gint row, gint column,
36 GdkEventButton *event, gpointer data);
37
38 /* signal handler for search_win quit */
39 static void search_quit(GtkWidget *widget, gpointer data);
40 /* signal handler for search_win done */
41 static void search_done(GtkWidget *widget, gpointer data);
42 static int search_key_input(GtkWidget *widget, GdkEventKey *event);
43
44 /* signal handler for edit_win quit */
45 static void edit_quit(GtkWidget *widget, gpointer data);
46 /* signal handler for edit_win done */
47 static void edit_done(GtkWidget *widget, gpointer data);
48 /* signal handler for toggle button */
49 static void edit_toggled(GtkWidget *widget, gpointer data);
50
51 /* signal handler for file_win quit */
52 static void file_quit(GtkWidget *widget, gpointer data);
53 /* signal handler for file_win done */
54 static void file_done(GtkWidget *widget, gpointer data);
55
56 static void *tsiyin_realdump(void *data);
57
58 static void about_me(GtkWidget *widget, gpointer data);
59 static void about_done(GtkWidget *widget, gpointer data);
60
61 #define NUMBER_OF_CLIST_ROW 15
62 #define NUMBER_OF_CLIST_COLUMN 3
63
64 /* default Tsi DB name */
65 #define DEFAULT_TSI_DB_NAME "tsi.db"
66
67 /* this sucks */
68 struct gtktsi_data {
69 GtkWidget *clist;
70 GtkWidget *search_win, *search_entry;
71 GtkWidget *edit_win;
72 GtkWidget *file_win, *file_entry;
73 GtkWidget *dump_win;
74 GtkWidget *about_win;
75 gchar *tsi_data[NUMBER_OF_CLIST_ROW];
76 gint selected_row;
77 gint yinnum;
78 Yin *yindata;
79 gint pyinnum;
80 Yin *pyindata;
81 unsigned long int yinarray;
82 char *db_name;
83 struct TsiDB *tsidb;
84 };
85
86 struct gtktsi_data *gtdata;
87
88 /*
89 * check window mutual exclusive
90 *
91 * return 0 if ok to open, -1 fails
92 */
93 int
win_mutual_exclusive()94 win_mutual_exclusive()
95 {
96 if (gtdata->search_win || gtdata->edit_win || gtdata->file_win ||
97 gtdata->dump_win || gtdata->about_win) {
98 return(-1);
99 }
100
101 return(0);
102 }
103
104 enum {
105 BROWSE_OPT_PREV,
106 BROWSE_OPT_NEXT,
107 BROWSE_OPT_SET
108 };
109
110 /*
111 * the code sucks [FIXME: the unnature mapping of DB and clist]
112 *
113 * opt == BROWSE_OPT_PREV: prev tsi
114 * opt == BROWSE_OPT_NEXT: next tsi
115 * opt == BROWSE_OPT_SET: tsi set
116 */
117 void
main_browse_tsi_in_clist(opt)118 main_browse_tsi_in_clist(opt)
119 int opt;
120 {
121 struct TsiInfo *tsi;
122 ZhiStr zuyin;
123 int i, j, k, rval, len;
124 gchar *data[3];
125
126 if (!gtdata->tsidb) {
127 gtdata->tsidb = tabeTsiDBOpen(DB_TYPE_DB, gtdata->db_name, 0);
128 if (!gtdata->tsidb) {
129 return;
130 }
131 }
132
133 tsi = (struct TsiInfo *)malloc(sizeof(struct TsiInfo));
134 memset(tsi, 0, sizeof(struct TsiInfo));
135 tsi->tsi = (unsigned char *)malloc(sizeof(unsigned char)*80);
136 memset(tsi->tsi, 0, 80);
137
138 for (i = 0; i < NUMBER_OF_CLIST_COLUMN; i++) {
139 data[i] = (gchar *)malloc(sizeof(gchar)*200);
140 memset(data[i], 0, 200);
141 }
142
143 gtk_clist_freeze(GTK_CLIST(gtdata->clist));
144
145 if (gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1]) {
146 strcpy(tsi->tsi, gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1]);
147 }
148 rval = gtdata->tsidb->CursorSet(gtdata->tsidb, tsi);
149 if (rval < 0) {
150 return;
151 }
152 gtk_clist_clear(GTK_CLIST(gtdata->clist));
153
154 switch(opt) {
155 case BROWSE_OPT_PREV: /* go back some tsi, or begin of file reached */
156 for (i = 0; i < 2*NUMBER_OF_CLIST_ROW-1; i++) {
157 rval = gtdata->tsidb->CursorPrev(gtdata->tsidb, tsi);
158 if (rval < 0) {
159 break;
160 }
161 }
162 break;
163 case BROWSE_OPT_NEXT:
164 rval = gtdata->tsidb->CursorNext(gtdata->tsidb, tsi);
165 break;
166 case BROWSE_OPT_SET:
167 /* we don't do anything else when opt == BROWSE_OPT_SET */
168 default:
169 break;
170 }
171
172 gtdata->tsi_data[0] = (gchar *)realloc(gtdata->tsi_data[0],
173 sizeof(gchar)*(strlen(tsi->tsi)+1));
174 strcpy(gtdata->tsi_data[0], tsi->tsi);
175 memset(data[0], 0, 200);
176 strcpy(data[0], gtdata->tsi_data[0]);
177 memset(data[1], 0, 200);
178 sprintf(data[1], "%8ld", tsi->refcount);
179 memset(data[2], 0, 200);
180
181 len = strlen(tsi->tsi)/2;
182 for (j = 0; j < tsi->yinnum; j++) {
183 strcat(data[2], "[");
184 for (k = 0; k < len; k++) {
185 zuyin = tabeYinToZuYinSymbolSequence(tsi->yindata[j*len+k]);
186 strcat(data[2], zuyin);
187 strcat(data[2], " ");
188 free(zuyin);
189 }
190 strcat(data[2], "] ");
191 }
192
193 gtk_clist_insert(GTK_CLIST(gtdata->clist), 0, data);
194
195 for (i = 1; i < NUMBER_OF_CLIST_ROW; i++) {
196 rval = gtdata->tsidb->CursorNext(gtdata->tsidb, tsi);
197 if (rval < 0) {
198 strcpy(gtdata->tsi_data[i], "");
199 strcpy(data[0], gtdata->tsi_data[i]);
200 strcpy(data[1], "");
201 }
202 else {
203 gtdata->tsi_data[i] =
204 (gchar *)realloc(gtdata->tsi_data[i],
205 sizeof(gchar)*(strlen(tsi->tsi)+1));
206 strcpy(gtdata->tsi_data[i], tsi->tsi);
207 strcpy(data[0], gtdata->tsi_data[i]);
208 sprintf(data[1], "%8ld", tsi->refcount);
209 memset(data[2], 0, 200);
210
211 len = strlen(tsi->tsi)/2;
212 for (j = 0; j < tsi->yinnum; j++) {
213 strcat(data[2], "[");
214 for (k = 0; k < len; k++) {
215 zuyin = tabeYinToZuYinSymbolSequence(tsi->yindata[j*len+k]);
216 strcat(data[2], zuyin);
217 strcat(data[2], " ");
218 free(zuyin);
219 }
220 strcat(data[2], "] ");
221 }
222 }
223 gtk_clist_insert(GTK_CLIST(gtdata->clist), i, data);
224 }
225
226 /*
227 * make sure next browse is ok even when there're not enough
228 * tsi in this browse */
229 strcpy(gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1], tsi->tsi);
230
231 gtk_clist_select_row(GTK_CLIST(gtdata->clist), gtdata->selected_row, 0);
232 gtk_clist_thaw(GTK_CLIST(gtdata->clist));
233
234 for (i = 0; i < NUMBER_OF_CLIST_COLUMN; i++) {
235 free(data[i]);
236 }
237 if (tsi->yindata) {
238 free(tsi->yindata);
239 tsi->yindata = (Yin *)NULL;
240 }
241 if (tsi->tsi) {
242 free(tsi->tsi);
243 }
244 free(tsi);
245 }
246
247 void
search_prompt_tsi_and_set()248 search_prompt_tsi_and_set()
249 {
250 GtkWidget *vbox, *hbox;
251 GtkWidget *done, *cancel;
252
253 if (win_mutual_exclusive() < 0) {
254 return;
255 }
256
257 if (gtdata->search_win) {
258 gtk_widget_destroy(gtdata->search_win);
259 }
260 gtdata->search_win = gtk_window_new(GTK_WINDOW_DIALOG);
261 gtk_container_set_border_width(GTK_CONTAINER(gtdata->search_win), 10);
262 gtk_window_set_title(GTK_WINDOW(gtdata->search_win), "Search & Set");
263 vbox = gtk_vbox_new(FALSE, 10);
264 gtk_container_add(GTK_CONTAINER(gtdata->search_win), vbox);
265
266 gtdata->search_entry = gtk_entry_new();
267 gtk_signal_connect_after(GTK_OBJECT(gtdata->search_entry),
268 "key_press_event",
269 GTK_SIGNAL_FUNC(search_key_input), NULL);
270 gtk_widget_show(gtdata->search_entry);
271 gtk_box_pack_start(GTK_BOX(vbox), gtdata->search_entry, TRUE, TRUE, 0);
272
273 hbox = gtk_hbox_new(TRUE, 10);
274 done = gtk_button_new_with_label("�j�M");
275 gtk_signal_connect(GTK_OBJECT(done), "clicked",
276 GTK_SIGNAL_FUNC(search_done), NULL);
277 gtk_box_pack_start(GTK_BOX(hbox), done, TRUE, TRUE, 0);
278 gtk_widget_show(done);
279 cancel = gtk_button_new_with_label("����");
280 gtk_signal_connect(GTK_OBJECT(cancel), "clicked",
281 GTK_SIGNAL_FUNC(search_quit), NULL);
282 gtk_box_pack_start(GTK_BOX(hbox), cancel, TRUE, TRUE, 0);
283 gtk_widget_show(cancel);
284 gtk_widget_show(hbox);
285 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
286
287 gtk_widget_show(vbox);
288 gtk_widget_show(gtdata->search_win);
289 }
290
291 void
edit_tsi()292 edit_tsi()
293 {
294 GtkWidget *cbutton;
295 GtkWidget *scr_win;
296 GtkWidget *box, *hbox, *vbox;
297 GtkWidget *done, *cancel;
298
299 struct TsiInfo tsi;
300 ZhiStr str = gtdata->tsi_data[gtdata->selected_row], zuyin, label;
301 int len = strlen(str)/2;
302 int rval, i, j;
303
304 if (win_mutual_exclusive() < 0) {
305 return;
306 }
307
308 memset(&tsi, 0, sizeof(tsi));
309 tsi.tsi = strdup(str);
310 rval = gtdata->tsidb->Get(gtdata->tsidb, &tsi);
311 if (rval < 0) {
312 fprintf(stderr, "Weird, no such Tsi.\n");
313 return;
314 }
315
316 /* clear, clear, clear */
317 gtdata->yinarray = 0;
318
319 gtdata->yinnum = tsi.yinnum;
320 if (gtdata->yindata) {
321 free(gtdata->yindata);
322 gtdata->yindata = (Yin *)NULL;
323 }
324 gtdata->yindata = (Yin *)malloc(sizeof(Yin)*len*gtdata->yinnum);
325 memcpy(gtdata->yindata, tsi.yindata, sizeof(Yin)*len*gtdata->yinnum);
326
327 tabeTsiInfoLookupPossibleTsiYin(&tsi);
328 gtdata->pyinnum = tsi.yinnum;
329 if (gtdata->pyindata) {
330 free(gtdata->pyindata);
331 gtdata->pyindata = (Yin *)NULL;
332 }
333 gtdata->pyindata = (Yin *)malloc(sizeof(Yin)*len*gtdata->pyinnum);
334 memcpy(gtdata->pyindata, tsi.yindata, sizeof(Yin)*len*gtdata->pyinnum);
335
336 if (gtdata->pyinnum > 64) {
337 fprintf(stderr, "System limit in Yin reached.\n");
338 return;
339 }
340
341 for (i = 0; i < gtdata->yinnum; i++) {
342 for (j = 0; j < gtdata->pyinnum; j++) {
343 if (!memcmp(gtdata->yindata+i*len, gtdata->pyindata+j*len,
344 sizeof(Yin)*len)) {
345 gtdata->yinarray |= 1 << j;
346 }
347 }
348 }
349
350 #ifdef MYDEBUG
351 printf("Total %ld combinations.\n", tsi.yinnum);
352 for (i = 0; i < gtdata->pyinnum; i++) {
353 for (j = 0; j < len; j++) {
354 printf("%s ",
355 tabeYinToZuYinSymbolSequence(gtdata->pyindata[i*len+j]));
356 }
357 printf("\n");
358 }
359 #endif /* MYDEBUG */
360
361 if (gtdata->edit_win) {
362 gtk_widget_destroy(gtdata->edit_win);
363 }
364 gtdata->edit_win = gtk_window_new(GTK_WINDOW_DIALOG);
365 gtk_container_set_border_width(GTK_CONTAINER(gtdata->edit_win), 10);
366 gtk_window_set_title(GTK_WINDOW(gtdata->edit_win), "Edit");
367 gtk_signal_connect(GTK_OBJECT(gtdata->edit_win), "destroy",
368 GTK_SIGNAL_FUNC(edit_quit), NULL);
369 box = gtk_vbox_new(FALSE, 10);
370 gtk_container_add(GTK_CONTAINER(gtdata->edit_win), box);
371 scr_win = gtk_scrolled_window_new(NULL, NULL);
372 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr_win),
373 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
374 gtk_box_pack_start(GTK_BOX(box), scr_win, TRUE, TRUE, 0);
375 gtk_widget_set_usize(scr_win, 400, 400);
376 gtk_widget_show(scr_win);
377
378 vbox = gtk_vbox_new(TRUE, 10);
379 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scr_win), vbox);
380 hbox = gtk_hbox_new(TRUE, 10);
381 gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0);
382
383 zuyin = (ZhiStr)NULL;
384 for (i = 0; i < gtdata->pyinnum; i++) {
385 label = (ZhiStr)malloc(sizeof(unsigned char));
386 strcpy(label, "");
387 for (j = 0; j < len; j++) {
388 zuyin = tabeYinToZuYinSymbolSequence(gtdata->pyindata[i*len+j]);
389 label = (ZhiStr)realloc(label, strlen(label)+strlen(zuyin)+4);
390 strcat(label, "[");
391 strcat(label, zuyin);
392 strcat(label, "] ");
393 }
394 cbutton = gtk_check_button_new_with_label(label);
395 if (gtdata->yinarray & 1 << i) {
396 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cbutton), TRUE);
397 }
398 gtk_signal_connect(GTK_OBJECT(cbutton), "clicked",
399 GTK_SIGNAL_FUNC(edit_toggled), (gpointer)i);
400 gtk_box_pack_start(GTK_BOX(vbox), cbutton, FALSE, FALSE, 0);
401 gtk_widget_show(cbutton);
402 free(zuyin);
403 free(label);
404 }
405
406 done = gtk_button_new_with_label("�]�w");
407 gtk_box_pack_start(GTK_BOX(hbox), done, TRUE, TRUE, 0);
408 gtk_signal_connect(GTK_OBJECT(done), "clicked",
409 GTK_SIGNAL_FUNC(edit_done), NULL);
410 gtk_widget_show(done);
411 cancel = gtk_button_new_with_label("����");
412 gtk_signal_connect(GTK_OBJECT(cancel), "clicked",
413 GTK_SIGNAL_FUNC(edit_quit), NULL);
414 gtk_box_pack_start(GTK_BOX(hbox), cancel, TRUE, TRUE, 0);
415 gtk_widget_show(cancel);
416
417 gtk_widget_show(vbox);
418 gtk_widget_show(hbox);
419 gtk_widget_show(box);
420 gtk_widget_show(gtdata->edit_win);
421 }
422
423 void
file_open_db()424 file_open_db()
425 {
426 GtkWidget *hbox, *vbox;
427 GtkWidget *done, *cancel;
428
429 if (win_mutual_exclusive() < 0) {
430 return;
431 }
432
433 if (gtdata->file_win) {
434 gtk_widget_destroy(gtdata->file_win);
435 }
436 gtdata->file_win = gtk_window_new(GTK_WINDOW_DIALOG);
437 gtk_container_set_border_width(GTK_CONTAINER(gtdata->file_win), 10);
438 gtk_window_set_title(GTK_WINDOW(gtdata->file_win), "File");
439 gtk_signal_connect(GTK_OBJECT(gtdata->file_win), "destroy",
440 GTK_SIGNAL_FUNC(file_quit), NULL);
441 vbox = gtk_vbox_new(FALSE, 10);
442 gtk_container_add(GTK_CONTAINER(gtdata->file_win), vbox);
443
444 gtdata->file_entry = gtk_entry_new();
445 gtk_widget_show(gtdata->file_entry);
446 gtk_box_pack_start(GTK_BOX(vbox), gtdata->file_entry, TRUE, TRUE, 0);
447
448 hbox = gtk_hbox_new(TRUE, 10);
449 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
450 done = gtk_button_new_with_label("�}��");
451 gtk_box_pack_start(GTK_BOX(hbox), done, TRUE, TRUE, 0);
452 gtk_signal_connect(GTK_OBJECT(done), "clicked",
453 GTK_SIGNAL_FUNC(file_done), NULL);
454 gtk_widget_show(done);
455 cancel = gtk_button_new_with_label("����");
456 gtk_signal_connect(GTK_OBJECT(cancel), "clicked",
457 GTK_SIGNAL_FUNC(file_quit), NULL);
458 gtk_box_pack_start(GTK_BOX(hbox), cancel, TRUE, TRUE, 0);
459 gtk_widget_show(cancel);
460
461 gtk_widget_show(vbox);
462 gtk_widget_show(hbox);
463 gtk_widget_show(gtdata->file_win);
464 }
465
466 /*
467 * dump tsiyin db
468 *
469 * we did not dump in this function, but set up a timeout to
470 * call tsiyin_realdump()
471 */
472 void
tsiyin_dump(widget,data)473 tsiyin_dump(widget, data)
474 GtkWidget *widget;
475 gpointer data;
476 {
477 GtkWidget *pbar;
478 pthread_t thread;
479
480 if (win_mutual_exclusive() < 0) {
481 return;
482 }
483
484 gtdata->dump_win = gtk_window_new(GTK_WINDOW_DIALOG);
485 gtk_container_set_border_width(GTK_CONTAINER(gtdata->dump_win), 10);
486 gtk_window_set_title(GTK_WINDOW(gtdata->dump_win), "TsiYin Dump");
487 pbar = gtk_progress_bar_new();
488 gtk_progress_set_show_text(GTK_PROGRESS(pbar), 1);
489 gtk_container_add(GTK_CONTAINER(gtdata->dump_win), pbar);
490 gtk_widget_show(pbar);
491 gtk_widget_show(gtdata->dump_win);
492
493 pthread_create(&thread, NULL, tsiyin_realdump, pbar);
494 }
495
496 /* This is the GtkItemFactoryEntry structure used to generate new menus.
497 Item 1: The menu path. The letter after the underscore indicates an
498 accelerator key once the menu is open.
499 Item 2: The accelerator key for the entry
500 Item 3: The callback function.
501 Item 4: The callback action. This changes the parameters with
502 which the function is called. The default is 0.
503 Item 5: The item type, used to define what kind of an item it is.
504 Here are the possible values:
505
506 NULL -> "<Item>"
507 "" -> "<Item>"
508 "<Title>" -> create a title item
509 "<Item>" -> create a simple item
510 "<CheckItem>" -> create a check item
511 "<ToggleItem>" -> create a toggle item
512 "<RadioItem>" -> create a radio item
513 <path> -> path of a radio item to link against
514 "<Separator>" -> create a separator
515 "<Branch>" -> create an item to hold sub items
516 "<LastBranch>" -> create a right justified branch
517 */
518
519 static GtkItemFactoryEntry menu_items[] = {
520 {"/���w", NULL, NULL, 0, "<Branch>"},
521 {"/���w/�}��", "<control>O", file_open_db, 0, NULL},
522 {"/���w/sep1", NULL, NULL, 0, "<Separator>"},
523 {"/���w/����", "<control>Q", main_quit, 0, NULL},
524 {"/�u��", NULL, NULL, 0, "<Branch>"},
525 {"/�u��/�W�@��", "<control>P", browse_prev, 0, NULL},
526 {"/�u��/�U�@��", "<control>N", browse_next, 0, NULL},
527 {"/�u��/sep1", NULL, NULL, 0, "<Separator>"},
528 {"/�u��/�j�M", "<control>S", browse_set, 0, NULL},
529 {"/�ק�", NULL, NULL, 0, "<Branch>"},
530 {"/�ק�/�s��", "<control>E", browse_edit, 0, NULL},
531 {"/�ק�/�R��", "<control>D", browse_delete, 0, NULL},
532 {"/�ק�/�s�W", "<control>A", browse_add, 0, NULL},
533 {"/����/����Ū���w", "<control>Y", tsiyin_dump, 0, NULL},
534 {"/��T", NULL, NULL, 0, "<LastBranch>"},
535 {"/��T/�������n��", NULL, about_me, 0, NULL},
536 };
537
538 void
get_main_menu(window,menubar)539 get_main_menu(window, menubar)
540 GtkWidget *window;
541 GtkWidget **menubar;
542 {
543 int nmenu_items = sizeof(menu_items)/sizeof(menu_items[0]);
544 GtkItemFactory *item_factory;
545 GtkAccelGroup *accel_group;
546
547 accel_group = gtk_accel_group_new();
548
549 /* This function initializes the item factory.
550 Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
551 or GTK_TYPE_OPTION_MENU.
552 Param 2: The path of the menu.
553 Param 3: A pointer to a gtk_accel_group. The item factory sets up
554 the accelerator table while generating menus.
555 */
556
557 item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>",
558 accel_group);
559
560 /* This function generates the menu items. Pass the item factory,
561 the number of items in the array, the array itself, and any
562 callback data for the the menu items. */
563 gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
564
565 /* Attach the new accelerator group to the window. */
566 gtk_accel_group_attach(accel_group, GTK_OBJECT (window));
567
568 if (menubar)
569 /* Finally, return the actual menu bar created by the item factory. */
570 *menubar = gtk_item_factory_get_widget(item_factory, "<main>");
571 }
572
573 static gchar *clist_title[NUMBER_OF_CLIST_COLUMN] = {
574 "��",
575 "�ѦҦ���",
576 "Ū��"
577 };
578
579 void
get_main_clist(clist)580 get_main_clist(clist)
581 GtkWidget **clist;
582 {
583 GtkWidget *widget;
584
585 widget = gtk_clist_new_with_titles(NUMBER_OF_CLIST_COLUMN, clist_title);
586 gtk_clist_set_shadow_type(GTK_CLIST(widget), GTK_SHADOW_OUT);
587 gtk_clist_set_column_width(GTK_CLIST(widget), 0, 200);
588 gtk_clist_set_column_width(GTK_CLIST(widget), 2, 400);
589 gtk_signal_connect(GTK_OBJECT(widget), "select_row",
590 GTK_SIGNAL_FUNC(browse_selected), NULL);
591
592 *clist = widget;
593 }
594
595 int
main(argc,argv)596 main(argc, argv)
597 int argc;
598 char **argv;
599 {
600 GtkWidget *window;
601 GtkWidget *main_vbox;
602 GtkWidget *menubar;
603 GtkWidget *clist;
604
605 gdk_set_locale();
606 gtk_init (&argc, &argv);
607 gtk_rc_parse("GTKTsi.rc");
608
609 bimsInit("tsi.db", "yin.db");
610
611 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
612 gtk_signal_connect(GTK_OBJECT(window), "destroy",
613 GTK_SIGNAL_FUNC(main_quit),
614 "WM destroy");
615 gtk_window_set_title(GTK_WINDOW(window), "GTKTsi");
616
617 main_vbox = gtk_vbox_new(FALSE, 1);
618 gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
619 gtk_container_add(GTK_CONTAINER(window), main_vbox);
620 gtk_widget_show(main_vbox);
621
622 get_main_menu(window, &menubar);
623 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
624 gtk_widget_show(menubar);
625
626 get_main_clist(&clist);
627 gtk_box_pack_start(GTK_BOX(main_vbox), clist, FALSE, TRUE, 0);
628 gtk_widget_show(clist);
629
630 gtdata = (struct gtktsi_data *)malloc(sizeof(struct gtktsi_data));
631 memset(gtdata, 0, sizeof(struct gtktsi_data));
632 gtdata->db_name = DEFAULT_TSI_DB_NAME;
633 gtdata->clist = clist;
634 main_browse_tsi_in_clist(BROWSE_OPT_SET);
635
636 gtk_widget_show(window);
637 gtk_main();
638
639 bimsDestroy();
640
641 return(0);
642 }
643
644 /*
645 * simply quit the program
646 */
647 static void
main_quit(widget,data)648 main_quit(widget, data)
649 GtkWidget *widget;
650 gpointer data;
651 {
652 if (gtdata->tsidb) {
653 gtdata->tsidb->Close(gtdata->tsidb);
654 }
655 gtk_main_quit();
656 }
657
658 static void
browse_next(widget,data)659 browse_next(widget, data)
660 GtkWidget *widget;
661 gpointer data;
662 {
663 if (gtdata->tsidb) {
664 main_browse_tsi_in_clist(BROWSE_OPT_NEXT);
665 }
666 }
667
668 static void
browse_prev(widget,data)669 browse_prev(widget, data)
670 GtkWidget *widget;
671 gpointer data;
672 {
673 if (gtdata->tsidb) {
674 main_browse_tsi_in_clist(BROWSE_OPT_PREV);
675 }
676 }
677
678 static void
browse_set(widget,data)679 browse_set(widget, data)
680 GtkWidget *widget;
681 gpointer data;
682 {
683 search_prompt_tsi_and_set(gtdata);
684 }
685
686 static void
browse_edit(widget,data)687 browse_edit(widget, data)
688 GtkWidget *widget;
689 gpointer data;
690 {
691 #ifdef MYDEBUG
692 printf("selected word is %s\n", gtdata->tsi_data[gtdata->selected_row]);
693 #endif
694 edit_tsi(gtdata);
695 }
696
697 static void
browse_add(widget,data)698 browse_add(widget, data)
699 GtkWidget *widget;
700 gpointer data;
701 {
702
703 }
704
705 #include <db.h>
706
707 static void
browse_delete(widget,data)708 browse_delete(widget, data)
709 GtkWidget *widget;
710 gpointer data;
711 {
712 DBT key;
713 int rval;
714
715 memset(&key, 0, sizeof(DBT));
716 printf("%s\n", gtdata->tsi_data[gtdata->selected_row]);
717 key.data = gtdata->tsi_data[gtdata->selected_row];
718 key.size = strlen(gtdata->tsi_data[gtdata->selected_row]);
719 rval = ((DB *)(gtdata->tsidb->dbp))->del((DB *)gtdata->tsidb->dbp,
720 NULL, &key, 0);
721 if (gtdata->selected_row == 0) {
722 strcpy(gtdata->tsi_data[0],
723 gtdata->tsi_data[1]);
724 }
725 strcpy(gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1], gtdata->tsi_data[0]);
726 main_browse_tsi_in_clist(BROWSE_OPT_SET);
727 }
728
729 static void
browse_selected(widget,row,column,event,data)730 browse_selected(widget, row, column, event, data)
731 GtkWidget *widget;
732 gint row;
733 gint column;
734 GdkEventButton *event;
735 gpointer data;
736 {
737 gtdata->selected_row = row;
738 }
739
740 static int
search_key_input(widget,event)741 search_key_input(widget, event)
742 GtkWidget *widget;
743 GdkEventKey *event;
744 {
745 return(bimsGTKEntryFeedKey(widget, event));
746 }
747
748 static void
search_quit(widget,data)749 search_quit(widget, data)
750 GtkWidget *widget;
751 gpointer data;
752 {
753 gtk_widget_destroy(GTK_WIDGET(gtdata->search_win));
754 gtdata->search_win = (GtkWidget *)NULL;
755 gtdata->search_entry = (GtkWidget *)NULL;
756 }
757
758 static void
search_done(widget,data)759 search_done(widget, data)
760 GtkWidget *widget;
761 gpointer data;
762 {
763 struct TsiInfo *tsi;
764 unsigned char *str;
765 int rval;
766
767 tsi = (struct TsiInfo *)malloc(sizeof(struct TsiInfo));
768 memset(tsi, 0, sizeof(struct TsiInfo));
769 tsi->tsi = (unsigned char *)malloc(sizeof(unsigned char)*80);
770
771 str = gtk_entry_get_text(GTK_ENTRY(gtdata->search_entry));
772 strcpy(tsi->tsi, str);
773
774 rval = gtdata->tsidb->Get(gtdata->tsidb, tsi);
775 if (rval < 0) {
776 gtk_entry_set_text(GTK_ENTRY(gtdata->search_entry), "�L����");
777 }
778 else {
779 gtk_widget_destroy(GTK_WIDGET(gtdata->search_win));
780 gtdata->search_win = (GtkWidget *)NULL;
781 gtdata->search_entry = (GtkWidget *)NULL;
782 gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1] =
783 (gchar *)realloc(gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1],
784 sizeof(gchar)*(strlen(tsi->tsi)+1));
785 strcpy(gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1], tsi->tsi);
786 main_browse_tsi_in_clist(BROWSE_OPT_SET);
787 }
788 }
789
790 static void
edit_done(widget,data)791 edit_done(widget, data)
792 GtkWidget *widget;
793 gpointer data;
794 {
795 unsigned long int yinarray;
796 Yin *yindata;
797 ZhiStr str = gtdata->tsi_data[gtdata->selected_row];
798 struct TsiInfo tsi;
799 int len = strlen(str)/2;
800 int i, j, num, rval, index;
801
802 yinarray = 0;
803 yindata = (Yin *)NULL;
804
805 for (i = 0; i < gtdata->yinnum; i++) {
806 for (j = 0; j < gtdata->pyinnum; j++) {
807 if (!memcmp(gtdata->yindata+i*len, gtdata->pyindata+j*len,
808 sizeof(Yin)*len)) {
809 yinarray |= 1 << j;
810 }
811 }
812 }
813
814 if (yinarray != gtdata->yinarray) { /* modified, need save */
815 num = 0;
816 index = 0;
817 for (i = gtdata->yinarray; i > 0; i = i >> 1, index++) {
818 if (i & 0x1) {
819 yindata = (Yin *)realloc(yindata, sizeof(Yin)*len*(num+1));
820 memcpy(yindata+num*len, gtdata->pyindata+index*len,
821 sizeof(Yin)*len);
822 num++;
823 }
824 }
825 if (gtdata->yindata) {
826 free(gtdata->yindata);
827 gtdata->yindata = (Yin *)NULL;
828 }
829 gtdata->yindata = yindata;
830 gtdata->yinnum = num;
831 memset(&tsi, 0, sizeof(tsi));
832 tsi.tsi = str;
833 rval = gtdata->tsidb->Get(gtdata->tsidb, &tsi);
834 if (rval < 0) {
835 fprintf(stderr, "Weird, this is the editing session, not adding one!\n");
836 return;
837 }
838 tsi.yinnum = num;
839 tsi.yindata = yindata;
840 (gtdata->tsidb)->flags |= DB_FLAG_OVERWRITE;
841 gtdata->tsidb->Put(gtdata->tsidb, &tsi);
842 (gtdata->tsidb)->flags ^= DB_FLAG_OVERWRITE;
843 /*
844 * we are doing wrong here,
845 * but, we don't expect Tsi DB to have a sync interface
846 */
847 gtdata->tsidb->Close(gtdata->tsidb);
848 gtdata->tsidb = (struct TsiDB *)NULL;
849 gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1] =
850 (ZhiStr)realloc(gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1],
851 sizeof(unsigned char)*(strlen(gtdata->tsi_data[0])+1));
852 strcpy(gtdata->tsi_data[NUMBER_OF_CLIST_ROW-1], gtdata->tsi_data[0]);
853 main_browse_tsi_in_clist(BROWSE_OPT_SET);
854 }
855 else {
856 /* do nothing */
857 }
858 gtk_widget_destroy(GTK_WIDGET(gtdata->edit_win));
859 gtdata->edit_win = (GtkWidget *)NULL;
860 }
861
862 static void
edit_quit(widget,data)863 edit_quit(widget, data)
864 GtkWidget *widget;
865 gpointer data;
866 {
867 gtk_widget_destroy(GTK_WIDGET(gtdata->edit_win));
868 gtdata->edit_win = (GtkWidget *)NULL;
869 }
870
871 static void
edit_toggled(widget,data)872 edit_toggled(widget, data)
873 GtkWidget *widget;
874 gpointer data;
875 {
876 int index = (gint)data;
877
878 gtdata->yinarray ^= 1 << index;
879 }
880
881 static void
file_quit(widget,data)882 file_quit(widget, data)
883 GtkWidget *widget;
884 gpointer data;
885 {
886 gtk_widget_destroy(GTK_WIDGET(gtdata->file_win));
887 gtdata->file_win = (GtkWidget *)NULL;
888 }
889
890 static void
file_done(widget,data)891 file_done(widget, data)
892 GtkWidget *widget;
893 gpointer data;
894 {
895 struct TsiDB *tsidb;
896 unsigned char *str;
897
898 str = gtk_entry_get_text(GTK_ENTRY(gtdata->file_entry));
899
900 gtdata->db_name = strdup(str);
901 tsidb = tabeTsiDBOpen(DB_TYPE_DB, gtdata->db_name, 0);
902 if (!tsidb) {
903 gtk_entry_set_text(GTK_ENTRY(gtdata->file_entry), "�L�����w");
904 }
905 else {
906 gtk_widget_destroy(GTK_WIDGET(gtdata->file_win));
907 gtdata->file_win = (GtkWidget *)NULL;
908 gtdata->file_entry = (GtkWidget *)NULL;
909 gtdata->tsidb = tsidb;
910 main_browse_tsi_in_clist(BROWSE_OPT_SET);
911 }
912 }
913
914 double ratio;
915
916 static int
tsiyin_dumpupdate(data)917 tsiyin_dumpupdate(data)
918 void *data;
919 {
920 GtkWidget *pbar = GTK_WIDGET(data);
921
922 gtk_progress_bar_update(GTK_PROGRESS_BAR(pbar), ratio);
923
924 return(TRUE);
925 }
926
927 static void *
tsiyin_realdump(data)928 tsiyin_realdump(data)
929 void *data;
930 {
931 struct TsiDB *tdb;
932 struct TsiYinDB *ydb;
933 struct TsiInfo *tsi;
934 struct TsiYinInfo *tsiyin;
935 char *ydb_name = "yin.db";
936 int rval, i, j, len;
937 int total;
938 int tag;
939
940 tdb = tabeTsiDBOpen(DB_TYPE_DB, gtdata->db_name, 0);
941 if (!tdb) {
942 printf("Error: could not open Tsi db %s.\n", gtdata->db_name);
943 return(FALSE);
944 }
945 total = tdb->RecordNumber(tdb);
946
947 ydb = tabeTsiYinDBOpen(DB_TYPE_DB, ydb_name,
948 DB_FLAG_CREATEDB|DB_FLAG_OVERWRITE);
949 if (!ydb) {
950 printf("Error: could not open Yin db %s.\n", ydb_name);
951 return(FALSE);
952 }
953
954 tsi = (struct TsiInfo *)malloc(sizeof(struct TsiInfo));
955 memset(tsi, 0, sizeof(struct TsiInfo));
956 tsi->tsi = (unsigned char *)malloc(sizeof(unsigned char)*80);
957 memset(tsi->tsi, 0, 80);
958
959 tsiyin = (struct TsiYinInfo *)malloc(sizeof(struct TsiYinInfo));
960 memset(tsiyin, 0, sizeof(struct TsiYinInfo));
961
962 tag = gtk_timeout_add(500, tsiyin_dumpupdate, data);
963
964 i = 0;
965 while(1) {
966 if (i == 0) {
967 tdb->CursorSet(tdb, tsi);
968 }
969 else {
970 rval = tdb->CursorNext(tdb, tsi);
971 if (rval < 0) {
972 break;
973 }
974 }
975 i++;
976 if (!(i%100)) {
977 ratio = (double)i/total;
978 }
979 tabeTsiInfoLookupPossibleTsiYin(tsi);
980 len = strlen(tsi->tsi)/2;
981 for (j = 0; j < tsi->yinnum; j++) {
982 tsiyin->yinlen = len;
983 tsiyin->yin = (Yin *)malloc(sizeof(Yin)*len);
984 memcpy(tsiyin->yin, tsi->yindata+j*len, sizeof(Yin)*len);
985 rval = ydb->Get(ydb, tsiyin);
986 if (rval < 0) { /* no such tsiyin */
987 tsiyin->tsinum = 1;
988 tsiyin->tsidata = (ZhiStr)malloc(sizeof(unsigned char)*len*2);
989 memcpy(tsiyin->tsidata, tsi->tsi, sizeof(unsigned char)*len*2);
990 ydb->Put(ydb, tsiyin);
991 }
992 else {
993 tsiyin->tsidata =
994 (ZhiStr)realloc(tsiyin->tsidata,
995 sizeof(unsigned char)*((tsiyin->tsinum+1)*len*2));
996 memcpy(tsiyin->tsidata+(tsiyin->tsinum*len*2), tsi->tsi,
997 sizeof(unsigned char)*len*2);
998 tsiyin->tsinum++;
999 ydb->Put(ydb, tsiyin);
1000 }
1001 }
1002 }
1003
1004 tdb->Close(tdb);
1005 ydb->Close(ydb);
1006 gtk_timeout_remove(tag);
1007 gtk_widget_destroy(gtdata->dump_win);
1008 gtdata->dump_win = (GtkWidget *)NULL;
1009
1010 pthread_exit(0);
1011
1012 return(NULL);
1013 }
1014
1015 static char *readme =
1016 "GTKTsi is a part of TaBE Project.\n"
1017 "Copyright 1999, TaBE Project. All Rights Reserved.\n"
1018 "There're %6ld tsi in the database.";
1019
1020 static void
about_me(widget,data)1021 about_me(widget, data)
1022 GtkWidget *widget;
1023 gpointer data;
1024 {
1025 GtkWidget *vbox;
1026 GtkWidget *label, *done;
1027 char *buf;
1028
1029 buf = (char *)malloc(sizeof(char)*(strlen(readme)+6));
1030 sprintf(buf, readme, gtdata->tsidb->RecordNumber(gtdata->tsidb));
1031 gtdata->about_win = gtk_window_new(GTK_WINDOW_DIALOG);
1032 gtk_window_set_title(GTK_WINDOW(gtdata->about_win), "About GTKTsi");
1033 gtk_container_border_width(GTK_CONTAINER(gtdata->about_win), 10);
1034 gtk_signal_connect(GTK_OBJECT(gtdata->about_win), "destroy",
1035 GTK_SIGNAL_FUNC(about_done), NULL);
1036 vbox = gtk_vbox_new(FALSE, 10);
1037 gtk_container_add(GTK_CONTAINER(gtdata->about_win), vbox);
1038
1039 label = gtk_label_new(buf);
1040 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
1041 gtk_widget_show(label);
1042
1043 done = gtk_button_new_with_label("����");
1044 gtk_signal_connect(GTK_OBJECT(done), "clicked",
1045 GTK_SIGNAL_FUNC(about_done), NULL);
1046 gtk_box_pack_start(GTK_BOX(vbox), done, FALSE, FALSE, 0);
1047 gtk_widget_show(done);
1048
1049 gtk_widget_show(vbox);
1050 gtk_widget_show(gtdata->about_win);
1051
1052 free(buf);
1053 }
1054
1055 static void
about_done(widget,data)1056 about_done(widget, data)
1057 GtkWidget *widget;
1058 gpointer data;
1059 {
1060 gtk_widget_destroy(gtdata->about_win);
1061 gtdata->about_win = (GtkWidget *)NULL;
1062 }
1063