diff --git a/hash-editor/src/che.c b/hash-editor/src/che.c index 34d2740..a49b321 100644 --- a/hash-editor/src/che.c +++ b/hash-editor/src/che.c @@ -8,82 +8,69 @@ #define PLAT_SEPARATOR "/" #define HASH_FILE "uhash.dat" -static char *hashfilename; - -GtkWidget *main_window; - -int main(int argc, char *argv[]) -{ - GtkWidget *menu; - GtkWidget *tree; - GtkWidget *scroll; - GtkWidget *vbox; - - /* load zhuin dictionary */ - zhuin_dictionary = zhuindict_load_default_dict(); - - gtk_init(&argc, &argv); - - main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - g_signal_connect (G_OBJECT (main_window), "delete_event", - G_CALLBACK (che_quit), NULL); - gtk_window_set_default_size(GTK_WINDOW(main_window), 500, 400); - vbox = gtk_vbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(main_window), vbox); - - menu = che_create_menu(GTK_WINDOW(main_window)); - gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, TRUE, 0); - - /* new scrolled window */ - scroll = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_ETCHED_IN); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0); - - tree = che_create_tree(GTK_WINDOW(main_window)); - //gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), tree); /* this breaks scrolling */ - /* GtkTreeView has its native scrolling mechanism, so we don't need a viewport */ - gtk_container_add(scroll, tree); +enum { HF_TEXT, HF_BINARY }; +/* ------------------------------- */ +struct _widget_pair { + GtkWidget *w1; + GtkWidget *w2; +}; +typedef struct _widget_pair wp_t; - is_file_saved = FALSE; +static char *hashfilename; +static GtkWindow *main_window; - if (argc > 1) - che_read_hash(argv[1]); - else { - if (getenv("HOME")) { - hashfilename = g_strdup_printf("%s%s", getenv("HOME"), - PLAT_SEPARATOR CHEWING_HASH_PATH - PLAT_SEPARATOR HASH_FILE); - /* writable uhash? */ - if (access(hashfilename, W_OK) != 0) { - /* specify another uhash */ - g_free(hashfilename); - file_open(main_window); - } - } - else { - file_open(main_window); - } - che_read_hash(hashfilename); - g_free(hashfilename); - } +/* gtk radio menu items to choose the file format */ +static GtkWidget *format_menu_text; +static GtkWidget *format_menu_binary; - gtk_widget_show_all( main_window ); - gtk_main(); +static GtkTreeStore *store; +static GtkTreeIter iter; +static gboolean is_editing_existing_phrase; +static GtkTreeSelection *selection; +static GtkTreeView *main_tree_view; +static gchar current_filename[1024]; +static GtkWidget *editor_dialog; +static GtkWidget *search_dialog; - zhuindict_free(zhuin_dictionary); +static struct zhuindict *zhuin_dictionary; - return 0; -} +static gboolean is_file_saved; +static gchar prev_search_text[0xff] = {}; +static uint32_t chewing_lifetime = 0; -GtkWidget * -che_create_tree( GtkWindow *parient ) +static GtkWidget *che_new_phrase_box(); +static void entry_active_callback(GtkWidget *obj, gpointer vbox); +static void button_click_callback(GtkWidget *btn, gpointer parent); +#ifdef ENABLE_TEXT_HASH +static void convertu2b(char *input, char *output, int n_char); +static void convert(char *input, char *output, int n_char); +#endif +static void che_select_row(GtkTreeIter *it); +static void che_phrase_dlg(const char *title); +static void cell_edited(GtkCellRendererText *cellrenderertext, gchar *p, + gchar *value, gpointer column); +static void file_open(GtkWindow *parent); +static void file_save(const gchar *fname); +static void file_save_as(GtkWindow *parent); +static void file_export(void *ptr); +static void file_import(void *ptr); +static void che_quit(GtkWindow *ptr); +static void che_new_phrase_dlg(GtkWidget *widget); +static void che_remove_phrase(GtkWidget *widget); +static void che_show_search_dlg(GtkWidget *widget); +static void che_show_about_dlg(GtkWidget *widget); +static void entry_active(GtkWidget *obj, gpointer vbox, const char *zhuin); +static void che_save_phrase(GtkWidget *obj, gpointer vbox); +static void treeview_keypress_callback(GtkWidget*, GdkEvent*, gpointer); +static void treeview_row_activated_callback(GtkTreeView*, GtkTreePath*, + GtkTreeViewColumn*, gpointer); + +static GtkWidget* +che_create_tree( GtkWindow *parent ) { GtkTreeViewColumn *column; GtkCellRenderer *renderer; GtkWidget *tree; - void treeview_keypress_callback(GtkWidget*, GdkEvent*, gpointer); - void treeview_row_activated_callback(GtkTreeView*, GtkTreePath*, GtkTreeViewColumn*, gpointer); store = gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, @@ -92,8 +79,9 @@ che_create_tree( GtkWindow *parient ) G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); - - tree = main_tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); + + main_tree_view = + GTK_TREE_VIEW(tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store))); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); g_object_unref (G_OBJECT (store)); @@ -151,7 +139,7 @@ che_create_tree( GtkWindow *parient ) "text", MAXFREQ_COLUMN, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); - + /* OrigFreq */ renderer = gtk_cell_renderer_text_new (); g_object_set(renderer, "editable", TRUE, NULL); @@ -166,12 +154,8 @@ che_create_tree( GtkWindow *parient ) return tree; } -/* gtk radio menu items to choose the file format */ -static GtkWidget *format_menu_text; -static GtkWidget *format_menu_binary; - -GtkWidget * -che_create_menu( GtkWindow *parient ) +static GtkWidget * +che_create_menu( GtkWindow *parent ) { GtkWidget *menu_bar; GtkWidget *menu_bar_file; @@ -188,20 +172,16 @@ che_create_menu( GtkWindow *parient ) GtkWidget *edit_menu_newtsi; GtkWidget *edit_menu_remove; GtkWidget *edit_menu_search; - GtkWidget *edit_menu_format; - GtkWidget *format_menu; - GSList *format_group = NULL; GtkWidget *separate; - GtkWidget *separate2; GtkAccelGroup *accel_group = NULL; accel_group = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(main_window), accel_group); - + gtk_window_add_accel_group(main_window, accel_group); + file_menu = gtk_menu_new(); file_menu_open = gtk_image_menu_item_new_from_stock (GTK_STOCK_OPEN, NULL); g_signal_connect_swapped (G_OBJECT (file_menu_open), "activate", - G_CALLBACK (file_open), parient); + G_CALLBACK (file_open), parent); gtk_widget_add_accelerator(file_menu_open, "activate", accel_group, GDK_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), file_menu_open); @@ -214,7 +194,7 @@ che_create_menu( GtkWindow *parient ) file_menu_saveas = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL); gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), file_menu_saveas); g_signal_connect_swapped (G_OBJECT (file_menu_saveas), "activate", - G_CALLBACK (file_save_as), parient); + G_CALLBACK (file_save_as), parent); file_menu_export = gtk_menu_item_new_with_mnemonic ("匯出(_E)"); g_signal_connect_swapped (G_OBJECT (file_menu_export), "activate", G_CALLBACK (file_export), NULL); @@ -244,6 +224,11 @@ che_create_menu( GtkWindow *parient ) g_signal_connect (G_OBJECT (edit_menu_search), "activate", G_CALLBACK (che_show_search_dlg), NULL); gtk_menu_shell_append (GTK_MENU_SHELL (edit_menu), edit_menu_search); #ifdef ENABLE_TEXT_HASH + GtkWidget *edit_menu_format; + GSList *format_group = NULL; + GtkWidget *format_menu; + GtkWidget *separate2; + separate2 = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (edit_menu), separate2); edit_menu_format = gtk_menu_item_new_with_mnemonic ("格式(_F)"); @@ -274,9 +259,7 @@ che_create_menu( GtkWindow *parient ) return menu_bar; } -enum { HF_TEXT, HF_BINARY }; - -void +static void che_set_hash_format(int fmt) { switch (fmt) { @@ -291,7 +274,8 @@ che_set_hash_format(int fmt) } } -int +#ifdef ENABLE_TEXT_HASH +static int che_get_hash_format() { if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (format_menu_text))) @@ -302,7 +286,7 @@ che_get_hash_format() assert(!"Either text or binary should be selected."); } -void +static void che_read_hash_txt(gchar *filename) { FILE *hash; @@ -358,11 +342,12 @@ che_read_hash_txt(gchar *filename) -1); } } - + fclose(hash); } +#endif -void +static void che_read_hash_bin(gchar *filename) { FILE *hash; @@ -377,7 +362,6 @@ che_read_hash_bin(gchar *filename) unsigned char recbuf[FIELD_SIZE]; unsigned char *puchar; uint16_t *pshort; - int header_length = strlen(BIN_HASH_SIG) + sizeof(uint32_t); ls = 126; rs = ls * 3 / 2 + 1; @@ -441,11 +425,11 @@ che_read_hash_bin(gchar *filename) ORIGFREQ_COLUMN, origfreq, -1); } - + fclose(hash); } -void +static void che_read_hash(gchar *filename) { /* check if the file is a binary hash */ @@ -469,7 +453,7 @@ che_read_hash(gchar *filename) * The first field is the phrase, and the second field is * its zhuin symbol. **/ -void +static void che_import_txt(gchar *filename) { FILE *file; @@ -526,11 +510,11 @@ che_import_txt(gchar *filename) -1); } } - + fclose(file); } -void +static void che_quit(GtkWindow *ptr /* reserved */) { file_save(NULL); @@ -538,13 +522,13 @@ che_quit(GtkWindow *ptr /* reserved */) } /* callback */ -void -file_open( GtkWindow *parient ) +static void +file_open( GtkWindow *parent ) { GtkWidget *dialog; dialog = gtk_file_chooser_dialog_new ("Open File", - parient, + parent, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, @@ -560,13 +544,13 @@ file_open( GtkWindow *parient ) gtk_widget_destroy (dialog); } -void -file_save_as( GtkWindow *parient ) +static void +file_save_as( GtkWindow *parent ) { GtkWidget *dialog; dialog = gtk_file_chooser_dialog_new ("Save As", - parient, + parent, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, @@ -584,8 +568,9 @@ file_save_as( GtkWindow *parient ) gtk_widget_destroy (dialog); } -void -file_save_txt( gchar *fname ) +#ifdef ENABLE_TEXT_HASH +static void +file_save_txt(const gchar *fname) { gchar *zuin; gchar *buffer, buf[125], str[125], bbuf[125]; @@ -611,7 +596,7 @@ file_save_txt( gchar *fname ) -1); convertu2b(buffer, bbuf, 125); sprintf(str,"%s ", bbuf); - pos = strtok(zuin, " "); + pos = strtok(zuin, " "); while( pos != NULL ) { sprintf(buf, "%d ", zhuin_to_inx(pos)); strcat(str, buf); @@ -626,12 +611,13 @@ file_save_txt( gchar *fname ) } fclose(file); } +#endif -void -file_save_bin( gchar *fname ) +static void +file_save_bin(const gchar *fname) { gchar *zuin; - gchar *buffer, buf[125], str[125], bbuf[125]; + gchar *buffer; gchar *pos; uint32_t userfreq, time, maxfreq, origfreq; uint8_t phrase_length; /* zuin string length in chinese characters */ @@ -681,7 +667,7 @@ file_save_bin( gchar *fname ) } /* phrase length in bytes */ - + string_length = strlen(buffer); pchar = (uint8_t*)pshort; *pchar = string_length; @@ -697,8 +683,8 @@ file_save_bin( gchar *fname ) fclose(file); } -void -file_save( gchar *fname ) +static void +file_save(const gchar *fname) { const char tmp_suffix[] = ".tmp"; char *tmp_filename; @@ -735,12 +721,11 @@ file_save( gchar *fname ) } /* export the database to a text file */ -void +static void file_export_as_text( gchar *fname ) { gchar *zuin; gchar *buffer, buf[125], str[125]; - gchar *pos; gint userfreq, time, maxfreq, origfreq; FILE *file; @@ -771,7 +756,7 @@ file_export_as_text( gchar *fname ) fclose(file); } -void file_export(void *ptr) +static void file_export(void *ptr) { GtkWidget *dialog; @@ -794,7 +779,7 @@ void file_export(void *ptr) gtk_widget_destroy (dialog); } -void file_import(void *ptr) +static void file_import(void *ptr) { GtkWidget *dialog; @@ -817,7 +802,7 @@ void file_import(void *ptr) gtk_widget_destroy (dialog); } -void +static void che_remove_phrase(GtkWidget *widget) { gboolean valid = gtk_tree_selection_get_selected(selection, @@ -829,20 +814,20 @@ che_remove_phrase(GtkWidget *widget) gtk_tree_selection_select_iter(selection, &iter); /* select the next item */ } -void +static void che_select_prev_phrase() { GtkTreePath *path; path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); if (path && gtk_tree_path_prev(path)) { - gtk_tree_model_get_iter(store, &iter, path); + gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, path); gtk_tree_selection_select_iter(selection, &iter); che_select_row(&iter); } gtk_tree_path_free(path); } -void +static void che_select_next_phrase() { gboolean valid = gtk_tree_selection_get_selected(selection, @@ -857,7 +842,8 @@ che_select_next_phrase() } } -void +#ifdef ENABLE_TEXT_HASH +static void convert(char *input, char *output, int n_char) { const char *inptr = input; @@ -873,7 +859,7 @@ convert(char *input, char *output, int n_char) iconv_close(cd); } -void +static void convertu2b(char *input, char *output, int n_char) { const char *inptr = input; @@ -888,8 +874,9 @@ convertu2b(char *input, char *output, int n_char) iconv_close(cd); } +#endif -void +static void cell_edited(GtkCellRendererText *cellrenderertext, gchar *p, gchar *value, gpointer column) { GtkTreePath *path; @@ -899,57 +886,22 @@ cell_edited(GtkCellRendererText *cellrenderertext, gchar *p, gchar *value, gpoin atoi((gpointer)column), atoi(value), -1); } -/* ------------------------------- */ -struct _widget_pair { - GtkWidget *w1; - GtkWidget *w2; -}; -typedef struct _widget_pair wp_t; - -GtkWidget *che_new_phrase_box(); -void entry_active_callback(GtkWidget *obj, gpointer vbox); -void button_click_callback(GtkWidget *btn, gpointer parent); -/* -int main(int argc, char *argv[]) -{ - GtkWidget *main_window; - GtkWidget *vbox; - GtkWidget *testbox; - - gtk_init(&argc, &argv); - - main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title( GTK_WINDOW (main_window), "Test" ); - g_signal_connect (G_OBJECT (main_window), "delete_event", - G_CALLBACK (gtk_main_quit), NULL); - vbox = gtk_vbox_new(FALSE, 1); - testbox = (GtkWidget*)che_new_phrase_box(); - gtk_box_pack_start( GTK_BOX(vbox), GTK_WIDGET(testbox), - FALSE, FALSE, 0); - - gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(vbox)); - gtk_widget_show_all(main_window); - - gtk_main(); - return 0; -} -*/ /* Show the phrase editor dialog for adding new phrases. */ -void che_new_phrase_dlg(GtkWidget *widget) +static void che_new_phrase_dlg(GtkWidget *widget) { is_editing_existing_phrase = FALSE; che_phrase_dlg("新增語詞"); } /* Show the phrase editor dialog for editing an existing phrase. */ -void che_edit_phrase_dlg(GtkWidget *widget) +static void che_edit_phrase_dlg(GtkWidget *widget) { is_editing_existing_phrase = TRUE; che_phrase_dlg("編輯語詞"); } -void che_phrase_dlg(const char *title) +static void che_phrase_dlg(const char *title) { GtkWidget *dlg = gtk_dialog_new_with_buttons (title, main_window, @@ -965,17 +917,16 @@ void che_phrase_dlg(const char *title) gtk_widget_show_all(GTK_WIDGET(dlg)); } -GtkWidget *che_new_phrase_box() +static GtkWidget *che_new_phrase_box() { GtkWidget *vbox_top; GtkWidget *vbox0; GtkWidget *hbox0; GtkWidget *vbox1; - GtkWidget *vbox2; GtkWidget *label; GtkWidget *entry; GtkWidget *btn, *btn2; - + vbox_top = gtk_vbox_new(FALSE, 1); vbox0 = gtk_vbox_new(FALSE, 1); hbox0 = gtk_hbox_new(FALSE, 1); @@ -1001,33 +952,32 @@ GtkWidget *che_new_phrase_box() NULL, &iter); if (valid) { - int length; gtk_tree_model_get (GTK_TREE_MODEL(store), &iter, - SEQ_COLUMN, &buffer, - ZUIN_COLUMN, &zhuin, - -1); - gtk_entry_set_text(entry, buffer); - entry_active(entry, (gpointer)vbox1, zhuin); - - g_free(buffer); - g_free(zhuin); - } + SEQ_COLUMN, &buffer, + ZUIN_COLUMN, &zhuin, + -1); + gtk_entry_set_text(GTK_ENTRY(entry), buffer); + entry_active(entry, (gpointer)vbox1, zhuin); + + g_free(buffer); + g_free(zhuin); + } } g_signal_connect( G_OBJECT(entry), "activate", G_CALLBACK(entry_active_callback), (gpointer)vbox1); g_signal_connect( G_OBJECT(btn), "clicked", G_CALLBACK(entry_active_callback), (gpointer)entry); g_signal_connect( G_OBJECT(btn2), "clicked", G_CALLBACK(che_save_phrase), (gpointer)vbox1); - + return vbox_top; } -GtkWidget *che_new_label_button_box(char *tsi, char *zhuin) +static GtkWidget *che_new_label_button_box(const char *tsi, const char *zhuin) { GtkWidget *hbox; GtkWidget *label; GtkWidget *button; - + hbox = gtk_hbox_new(FALSE, 5); label = gtk_label_new(tsi); gtk_box_pack_start( GTK_BOX(hbox), GTK_WIDGET (label), @@ -1036,37 +986,38 @@ GtkWidget *che_new_label_button_box(char *tsi, char *zhuin) gtk_box_pack_start( GTK_BOX(hbox), GTK_WIDGET (button), FALSE, FALSE, 0); g_signal_connect( button, "clicked", G_CALLBACK(button_click_callback), (gpointer)(GTK_WIDGET(hbox)->parent)); - return hbox; + return hbox; } -void entry_active(GtkWidget *obj, gpointer vbox, const char *zhuin) +static void entry_active(GtkWidget *obj, gpointer vbox, const char *zhuin) { int i, length; - char *chr_zhuin; + const char *chr_zhuin; GtkWidget *box = vbox; GtkWidget *bl; gchar buf[4]; - gchar *text = gtk_entry_get_text(GTK_ENTRY(obj)); + const gchar *text = gtk_entry_get_text(GTK_ENTRY(obj)); /* the representation of Mandarin Phonetic Symbols consists of initial, - middle, fnal consonants (each occupies 3 bytes in UTF-8), and tone + middle, fnal consonants (each occupies 3 bytes in UTF-8), and tone (2 bytes in UTF-8). Therefore, we declare 11 bytes in zhuin_buffer. */ char zhuin_buffer[3 * 3 + 2 + 1]; length = chewing_utf8_strlen(text); - gtk_container_foreach(GTK_CONTAINER(box), gtk_widget_destroy, NULL); + gtk_container_foreach(GTK_CONTAINER(box), + (GtkCallback)gtk_widget_destroy, NULL); if (zhuin) - chr_zhuin = strtok(zhuin, " "); + chr_zhuin = strtok((char*)zhuin, " "); else chr_zhuin = " "; for(i = 0; i < length; i++) { chewing_utf8_strncpy(buf, chewing_utf8_strseek(text, i), 1, 1); /* try to find the zhuin for the chinese character */ if (zhuin_dictionary && find_zhuin(zhuin_dictionary, buf, zhuin_buffer)) { - chr_zhuin = zhuin_buffer; + chr_zhuin = zhuin_buffer; } else { chr_zhuin = " "; } @@ -1078,7 +1029,7 @@ void entry_active(GtkWidget *obj, gpointer vbox, const char *zhuin) } } -void entry_active_callback(GtkWidget *obj, gpointer vbox) +static void entry_active_callback(GtkWidget *obj, gpointer vbox) { if(!GTK_IS_ENTRY(obj)) { @@ -1088,10 +1039,9 @@ void entry_active_callback(GtkWidget *obj, gpointer vbox) entry_active(obj, vbox, NULL); } -void che_save_phrase(GtkWidget *obj, gpointer vbox) +static void che_save_phrase(GtkWidget *obj, gpointer vbox) { GtkWidget *box = vbox; - GtkWidget *hbox; char zuin[256]; char phrase[256]; gboolean valid; @@ -1106,13 +1056,13 @@ void che_save_phrase(GtkWidget *obj, gpointer vbox) { GtkWidget *lab = g_list_nth_data(gtk_container_get_children(GTK_CONTAINER(hboxes->data)), 0); GtkWidget *btn = g_list_nth_data(gtk_container_get_children(GTK_CONTAINER(hboxes->data)), 1); - gchar *label = gtk_button_get_label(btn); + const gchar *label = gtk_button_get_label(GTK_BUTTON(btn)); strcat(zuin, label); strcat(zuin, " "); strcat(phrase, GTK_LABEL(lab)->label); } while((hboxes = g_list_next(hboxes)) != NULL); - + if (is_editing_existing_phrase) valid = gtk_tree_selection_get_selected(selection, NULL, &iter); @@ -1137,22 +1087,22 @@ void che_save_phrase(GtkWidget *obj, gpointer vbox) is_file_saved = FALSE; } -void append_text(GtkWidget *btn, gpointer entry) +static void append_text(GtkWidget *btn, gpointer entry) { - gchar *label = gtk_button_get_label(GTK_BUTTON(btn)); + const gchar *label = gtk_button_get_label(GTK_BUTTON(btn)); gtk_entry_append_text(GTK_ENTRY(entry), label); } -void che_set_context(GtkWidget *dlg, gint arg, wp_t *pwp) +static void che_set_context(GtkWidget *dlg, gint arg, wp_t *pwp) { wp_t *wp = (wp_t*)pwp; - gchar *context = gtk_entry_get_text(GTK_ENTRY(wp->w2)); + const gchar *context = gtk_entry_get_text(GTK_ENTRY(wp->w2)); gtk_button_set_label(GTK_BUTTON(wp->w1), context); gtk_widget_destroy(dlg); free(pwp); } -void button_click_callback(GtkWidget *cbtn, gpointer parent) +static void button_click_callback(GtkWidget *cbtn, gpointer parent) { const char *zhuin_tab[] = { "ㄅ", "ㄆ", "ㄇ", "ㄈ", "ㄉ", "ㄊ", "ㄋ", "ㄌ", "ㄍ", "ㄎ", "ㄏ", @@ -1172,13 +1122,14 @@ void button_click_callback(GtkWidget *cbtn, gpointer parent) GTK_RESPONSE_OK, NULL); entry = gtk_entry_new(); - gtk_entry_set_text(entry, gtk_button_get_label(cbtn)); + gtk_entry_set_text(GTK_ENTRY(entry), gtk_button_get_label(GTK_BUTTON(cbtn))); gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dlg)->vbox), entry); hbox = gtk_hbox_new(FALSE, 0); for(i = 0; i < 11; i++) { btn = gtk_button_new_with_label(zhuin_tab[i]); - gtk_signal_connect(GTK_WIDGET(btn), "clicked", G_CALLBACK(append_text), (gpointer)entry); + g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(append_text), + entry); gtk_box_pack_start_defaults(GTK_BOX(hbox), btn); } gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox); @@ -1186,7 +1137,8 @@ void button_click_callback(GtkWidget *cbtn, gpointer parent) for(i = 11; i < 22; i++) { btn = gtk_button_new_with_label(zhuin_tab[i]); - gtk_signal_connect(GTK_WIDGET(btn), "clicked", G_CALLBACK(append_text), (gpointer)entry); + g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(append_text), + entry); gtk_box_pack_start_defaults(GTK_BOX(hbox), btn); } gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox); @@ -1194,7 +1146,8 @@ void button_click_callback(GtkWidget *cbtn, gpointer parent) for(i = 22; i < 33; i++) { btn = gtk_button_new_with_label(zhuin_tab[i]); - gtk_signal_connect(btn, "clicked", G_CALLBACK(append_text), (gpointer)entry); + g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(append_text), + entry); gtk_box_pack_start_defaults(GTK_BOX(hbox), btn); } gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox); @@ -1202,7 +1155,8 @@ void button_click_callback(GtkWidget *cbtn, gpointer parent) for(i = 33; i < 42; i++) { btn = gtk_button_new_with_label(zhuin_tab[i]); - gtk_signal_connect(btn, "clicked", G_CALLBACK(append_text), (gpointer)entry); + g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(append_text), + entry); gtk_box_pack_start_defaults(GTK_BOX(hbox), btn); } gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox); @@ -1210,13 +1164,13 @@ void button_click_callback(GtkWidget *cbtn, gpointer parent) wp->w1 = cbtn; wp->w2 = entry; g_signal_connect (dlg, - "response", + "response", G_CALLBACK (che_set_context), wp); gtk_widget_show_all(GTK_WIDGET(dlg)); } -void +static void treeview_keypress_callback(GtkWidget *widget, GdkEvent *event, gpointer data) { if (event->type == GDK_KEY_PRESS) { @@ -1234,21 +1188,22 @@ treeview_keypress_callback(GtkWidget *widget, GdkEvent *event, gpointer data) } } -void +static void treeview_row_activated_callback(GtkTreeView* treeview, GtkTreePath* path, GtkTreeViewColumn* column, gpointer ptr) { - che_edit_phrase_dlg(treeview); + che_edit_phrase_dlg(GTK_WIDGET(treeview)); } -int match_phrase(char *key, char *text) +static int match_phrase(const char *key, const char *text) { - if (strlen(key) > strlen(text)) return 0; + if (strlen(key) > strlen(text)) + return 0; return memcmp(key, text, strlen(key)) == 0; } /* select the row and make it visible */ -void che_select_row(GtkTreeIter *it) +static void che_select_row(GtkTreeIter *it) { GtkTreeModel *model; GtkTreePath *path; @@ -1263,7 +1218,7 @@ void che_select_row(GtkTreeIter *it) } } -void search_phrase_callback(GtkWidget *obj, gpointer entry) +static void search_phrase_callback(GtkWidget *obj, gpointer entry) { gchar *ptr; gchar buffer[256]; @@ -1286,7 +1241,7 @@ void search_phrase_callback(GtkWidget *obj, gpointer entry) do { gtk_tree_model_get (GTK_TREE_MODEL(store), &iter, SEQ_COLUMN, &ptr, - -1); + -1); strcpy(buffer, ptr); //printf("phrase: %s\n", buffer); g_free(ptr); @@ -1298,7 +1253,7 @@ void search_phrase_callback(GtkWidget *obj, gpointer entry) gtk_tree_model_get_iter_first( GTK_TREE_MODEL(store), &iter); /* wrap search */ } /* phrase not found */ - + } finished: @@ -1308,17 +1263,16 @@ void search_phrase_callback(GtkWidget *obj, gpointer entry) g_signal_emit_by_name(G_OBJECT(search_dialog), "response", G_TYPE_NONE); } -GtkWidget *che_new_search_box() +static GtkWidget *che_new_search_box() { GtkWidget *vbox_top; GtkWidget *vbox0; GtkWidget *hbox0; GtkWidget *vbox1; - GtkWidget *vbox2; GtkWidget *label; GtkWidget *entry; GtkWidget *btn; - + vbox_top = gtk_vbox_new(FALSE, 1); vbox0 = gtk_vbox_new(FALSE, 1); hbox0 = gtk_hbox_new(FALSE, 1); @@ -1336,16 +1290,16 @@ GtkWidget *che_new_search_box() gtk_box_pack_start_defaults( GTK_BOX(hbox0), GTK_WIDGET(entry) ); gtk_box_pack_start_defaults( GTK_BOX(hbox0), GTK_WIDGET(btn) ); - gtk_entry_set_text(entry, prev_search_text); + gtk_entry_set_text(GTK_ENTRY(entry), prev_search_text); g_signal_connect( G_OBJECT(entry), "activate", G_CALLBACK(search_phrase_callback), (gpointer)entry); g_signal_connect( G_OBJECT(btn), "clicked", G_CALLBACK(search_phrase_callback), (gpointer)entry); - + return vbox_top; } -void che_show_search_dlg(GtkWidget *widget) +static void che_show_search_dlg(GtkWidget *widget) { GtkWidget *dlg = gtk_dialog_new_with_buttons ("搜尋", main_window, @@ -1361,14 +1315,14 @@ void che_show_search_dlg(GtkWidget *widget) gtk_widget_show_all(GTK_WIDGET(dlg)); } -void che_show_about_dlg(GtkWidget *widget) +static void che_show_about_dlg(GtkWidget *widget) { /* Author list is obtained from build system. */ const char *authors[] = { #include "/dev/stdin" NULL }; - GtkAboutDialog *dialog = gtk_about_dialog_new(); + GtkAboutDialog *dialog = GTK_ABOUT_DIALOG(gtk_about_dialog_new()); gtk_about_dialog_set_program_name(dialog, "新酷音詞庫編輯器"); gtk_about_dialog_set_authors(dialog, authors); @@ -1379,9 +1333,74 @@ void che_show_about_dlg(GtkWidget *widget) gtk_about_dialog_set_website_label(dialog, "開啟專案首頁"); gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); - gtk_window_set_transient_for(dialog, main_window); + gtk_window_set_transient_for(GTK_WINDOW(dialog), + main_window); + + gtk_dialog_run(GTK_DIALOG(dialog)); + + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +int main(int argc, char *argv[]) +{ + GtkWidget *menu; + GtkWidget *tree; + GtkWidget *scroll; + GtkWidget *vbox; + + /* load zhuin dictionary */ + zhuin_dictionary = zhuindict_load_default_dict(); + + gtk_init(&argc, &argv); + + main_window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); + g_signal_connect (G_OBJECT (main_window), "delete_event", + G_CALLBACK (che_quit), NULL); + gtk_window_set_default_size(main_window, 500, 400); + vbox = gtk_vbox_new(FALSE, 5); + gtk_container_add(GTK_CONTAINER(main_window), vbox); + + menu = che_create_menu(main_window); + gtk_box_pack_start(GTK_BOX(vbox), menu, FALSE, TRUE, 0); + + /* new scrolled window */ + scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_ETCHED_IN); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0); + + tree = che_create_tree(main_window); + //gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), tree); /* this breaks scrolling */ + /* GtkTreeView has its native scrolling mechanism, so we don't need a viewport */ + gtk_container_add(GTK_CONTAINER(scroll), tree); - gtk_dialog_run(dialog); + is_file_saved = FALSE; - gtk_widget_destroy(dialog); + if (argc > 1) + che_read_hash(argv[1]); + else { + if (getenv("HOME")) { + hashfilename = g_strdup_printf("%s%s", getenv("HOME"), + PLAT_SEPARATOR CHEWING_HASH_PATH + PLAT_SEPARATOR HASH_FILE); + /* writable uhash? */ + if (access(hashfilename, W_OK) != 0) { + /* specify another uhash */ + g_free(hashfilename); + file_open(main_window); + } + } + else { + file_open(main_window); + } + che_read_hash(hashfilename); + g_free(hashfilename); + } + + gtk_widget_show_all(GTK_WIDGET(main_window)); + gtk_main(); + + zhuindict_free(zhuin_dictionary); + + return 0; } diff --git a/hash-editor/src/che.h b/hash-editor/src/che.h index 42f1bf6..2feb7b4 100644 --- a/hash-editor/src/che.h +++ b/hash-editor/src/che.h @@ -23,39 +23,3 @@ enum { ORIGFREQ_COLUMN, N_COLUMNS }; - -GtkTreeStore *store; -GtkTreeIter iter; -gboolean is_editing_existing_phrase; -GtkTreeSelection *selection; -GtkTreeView *main_tree_view; -gchar current_filename[1024]; -GtkWidget *editor_dialog; -GtkWidget *search_dialog; - -GtkWidget *che_create_tree( GtkWindow* ); -GtkWidget *che_create_menu( GtkWindow* ); -void che_read_hash(gchar *filename); -void convert(char*, char*, int); -void che_select_prev_phrase(); -void che_select_next_phrase(); - -struct zhuindict *zhuin_dictionary; - -gboolean is_file_saved; -gchar prev_search_text[0xff] = {}; -uint32_t chewing_lifetime = 0; - -/* callback */ -void che_quit(GtkWindow*); -void file_open( GtkWindow* ); -void file_save_as( GtkWindow* ); -void file_save( gchar* ); -void file_export(void*); -void file_import(void*); -void cell_edited(GtkCellRendererText *cellrenderertext, gchar *arg1, gchar *arg2, gpointer column); -void che_new_phrase_dlg( GtkWidget* ); -void che_save_phrase(GtkWidget *obj, gpointer vbox); -void che_remove_phrase(GtkWidget *menu); -void che_show_search_dlg(GtkWidget *widget); -void che_show_about_dlg(GtkWidget *widget); diff --git a/hash-editor/src/chewing-utf8-util.c b/hash-editor/src/chewing-utf8-util.c index 5a08c45..8fc971f 100644 --- a/hash-editor/src/chewing-utf8-util.c +++ b/hash-editor/src/chewing-utf8-util.c @@ -16,12 +16,12 @@ static char utf8len_tab[256] = }; /* Return length of UTF-8 string */ -int -chewing_utf8_strlen(char *str) +size_t +chewing_utf8_strlen(const char *str) { - int length = 0; - char *strptr = str; - + size_t length = 0; + const char *strptr = str; + while (strptr[0] != '\0') { strptr += chewing_utf8_byte2len(strptr[0]); @@ -31,48 +31,48 @@ chewing_utf8_strlen(char *str) } /* Return bytes of a UTF-8 character */ -int +size_t chewing_utf8_byte2len(unsigned char b) { return utf8len_tab[b]; } /* Return how many bytes was copied */ -int +size_t chewing_utf8_strncpy(char *dest, const char *src, int n, int end) { int i = 0, len = 0; - char *iter = (char*)src; + const char *iter = src; for( i = 0; i < n; i++ ) { len += chewing_utf8_byte2len(iter[len]); } memcpy(dest, iter, len); if( end == 1) - ((char*)dest)[len] = '\0'; + dest[len] = '\0'; return len; } -void* -chewing_utf8_strseek(char *src, size_t n) +char* +chewing_utf8_strseek(const char *src, size_t n) { int i = 0; - char *iter = (char*)src; + const char *iter = src; for( i = 0; i < n; i++ ) { iter += chewing_utf8_byte2len(iter[0]); } - return (void*)iter; + return (char*)iter; } -int chewing_utf8_is_valid_str(char *str) +int chewing_utf8_is_valid_str(const char *str) { if ( str == NULL || *str == '\0' ) { return 0; } while ( *str != '\0' ) { - int len = utf8len_tab[(unsigned char) *str]; + int len = utf8len_tab[(unsigned char)*str]; if ( len <= 1 ) { return 0; } @@ -80,4 +80,3 @@ int chewing_utf8_is_valid_str(char *str) }; return 1; } - diff --git a/hash-editor/src/chewing-utf8-util.h b/hash-editor/src/chewing-utf8-util.h index afca51c..5e6ca59 100644 --- a/hash-editor/src/chewing-utf8-util.h +++ b/hash-editor/src/chewing-utf8-util.h @@ -1,10 +1,12 @@ +#include + #ifndef CHEWING_UTF8_UTIL_H #define CHEWING_UTF8_UTIL_H -int chewing_utf8_strlen(char *str); -int chewing_utf8_byte2len(unsigned char b); -int chewing_utf8_strncpy(char *dest, const char *src, int n, int end); -int chewing_utf8_is_valid_str(char *str); -int chewing_utf8_strlen(char *str); +size_t chewing_utf8_strlen(const char *str); +size_t chewing_utf8_byte2len(unsigned char b); +size_t chewing_utf8_strncpy(char *dest, const char *src, int n, int end); +int chewing_utf8_is_valid_str(const char *str); +char *chewing_utf8_strseek(const char *src, size_t n); #endif /* CHEWING_UTF8_UTIL_H */ diff --git a/hash-editor/src/key2pho-utf8.c b/hash-editor/src/key2pho-utf8.c index 3fb8f04..f394eeb 100644 --- a/hash-editor/src/key2pho-utf8.c +++ b/hash-editor/src/key2pho-utf8.c @@ -1,9 +1,10 @@ //#include "global.h" //#include "zhuin.h" #include "chewing-utf8-util.h" +#include "key2pho-utf8.h" #include -const char *zhuin_tab[] = { +static const char *zhuin_tab[] = { "ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙ", "ㄧㄨㄩ", "ㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦ", @@ -13,7 +14,7 @@ static const int zhuin_tab_num[] = { 22, 4, 14, 6 }; static const int shift[] = { 9, 7, 3, 0 }; -const static int sb[] = { 31, 3, 15, 7 }; +static const int sb[] = { 31, 3, 15, 7 }; //static const char *ph_str = //"ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄧㄨㄩㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦ˙ˊˇˋ" ; @@ -33,16 +34,16 @@ const static int sb[] = { 31, 3, 15, 7 }; /* Read one zhuin string, return the number it means */ int -zhuin_to_inx( char *zhuin ) +zhuin_to_inx(const char *zhuin) { - char *iter = zhuin, *pos; + const char *iter = zhuin, *pos; char buf[4]; int len, result = 0; int i; - - /* Here the constant 4 is the number + + /* Here the constant 4 is the number of zhuin_tab and zhuin_tab_num */ -/* for( i = 0; i < 3; i++ ) */ + /* for( i = 0; i < 3; i++ ) */ for( i = 0; i < 4; i++ ) { len = chewing_utf8_byte2len( iter[0] ); @@ -60,17 +61,35 @@ zhuin_to_inx( char *zhuin ) return result; } +int Uint2PhoneUTF8(char *phone, long seq) +{ + int i, j, k; + const char *pos; + char buffer[5]; + for ( i = 0, j = 0; i < 4; i++) { + k = ((seq >> shift[ i ]) & sb[ i ] ) - 1; + if ( k >= 0 && (pos = chewing_utf8_strseek( zhuin_tab[ i ], k )) ) + { + chewing_utf8_strncpy(buffer, pos, 1, 1); + strcat(phone, buffer); + j++; + } + } + return j; +} + +#if 0 /* Read one zhuin string, return the number of tones*/ -int -zhuin_to_tone( char *zhuin ) +static int +zhuin_to_tone(const char *zhuin) { char *iter = zhuin, *pos = 0; char buf[4]; int len, result = 0; int i; - - /* Here the constant 4 is the number + + /* Here the constant 4 is the number of zhuin_tab and zhuin_tab_num */ for( i = 0; i < 4; i++ ) { @@ -88,24 +107,6 @@ zhuin_to_tone( char *zhuin ) return result; } -int Uint2PhoneUTF8( char *phone, long seq ) -{ - int i, j, k; - char *pos; - char buffer[5]; - for ( i = 0, j = 0; i < 4; i++) { - k = ((seq >> shift[ i ]) & sb[ i ] ) - 1; - if ( k >= 0 && (pos = chewing_utf8_strseek( zhuin_tab[ i ], k )) ) - { - chewing_utf8_strncpy(buffer, pos, 1, 1); - strcat(phone, buffer); - j++; - } - } - return j; -} - -#if 0 int Key2PhoneInxUTF8( int key, int type, int kbtype, int searchTimes ) { char keyStr[ 5 ], bgStr[ 10 ], *p; @@ -136,9 +137,9 @@ int Key2PhoUTF8( char *pho, const char *inputkey, int kbtype, int searchTimes ) char *findptr = NULL; int index; - for ( - s = 0, pTarget = key_str[ kbtype ]; - s < searchTimes; + for ( + s = 0, pTarget = key_str[ kbtype ]; + s < searchTimes; s++, pTarget = findptr + 1 ) { findptr = strchr( pTarget, inputkey[ i ] ); if ( ! findptr ) { diff --git a/hash-editor/src/key2pho-utf8.h b/hash-editor/src/key2pho-utf8.h index 89f522e..db4bf94 100644 --- a/hash-editor/src/key2pho-utf8.h +++ b/hash-editor/src/key2pho-utf8.h @@ -1,6 +1,7 @@ #ifndef KEY2PHO_UTF8_H #define KEY2PHO_UTF8_H -int Uint2PhoneUTF8( char *phone, long seq ); +int Uint2PhoneUTF8(char *phone, long seq); +int zhuin_to_inx(const char *zhuin); #endif /* KEY2PHO_UTF8_H */ diff --git a/hash-editor/src/key2pho8.c b/hash-editor/src/key2pho8.c index 4f1a259..4654aae 100644 --- a/hash-editor/src/key2pho8.c +++ b/hash-editor/src/key2pho8.c @@ -1,8 +1,8 @@ #include "key2pho8.h" -const static int shift[] = { 9, 7, 3, 0 }; -const static int sb[] = { 31, 3, 15, 7 }; -const char *ph_pho[] = { /* number of bits */ +static const int shift[] = { 9, 7, 3, 0 }; +static const int sb[] = { 31, 3, 15, 7 }; +static const char *ph_pho[] = { /* number of bits */ " ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙ", /* 5 */ " ㄧㄨㄩ", /* 2 */ " ㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦ", /* 4 */ diff --git a/hash-editor/src/zhuindict.c b/hash-editor/src/zhuindict.c index 83b7f2f..6b2d61e 100644 --- a/hash-editor/src/zhuindict.c +++ b/hash-editor/src/zhuindict.c @@ -142,7 +142,7 @@ struct zhuindict* zhuindict_load_default_dict() { int i; - struct entry *p_entry = default_data; + const struct entry *p_entry = default_data; struct zhuindict *ptr = zhuindict_new(); for (i=0; ip_char, p_entry->zhuin);