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