1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
2 /* IM-JA Japanese Input Method Module for GTK-2.0
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 *
19 * Authors: Botond Botyanszki <boti@rocketmail.com>
20 *
21 */
22
23 #include <config.h>
24
25 #include <gtk/gtk.h>
26 #include <gdk/gdkkeysyms.h>
27 #include <math.h>
28 #include <string.h>
29
30 #include "im-ja.h"
31 #include "symbols.h"
32 #include "error.h"
33 #include "nls.h"
34 #include "common.h"
35
convert_line(gunichar * result,gchar ** strg,gchar * line,gint length)36 static gint convert_line(gunichar *result, gchar **strg, gchar *line, gint length) {
37 /* unichar is not changed if the input is not a 4 byte unichar string*/
38 gint i;
39 gunichar unichar = 0;
40
41 if (length < 2) return 0;
42
43 if (line[0] == '$') {
44 *strg = g_new0(gchar, length - 1);
45 g_strlcpy(*strg, line + 1, length - 1);
46 return 1;
47 }
48 if (line[0] == '.' && line[1] == '.') return 2;
49 if (length < 5) return 0;
50 for (i = 0; i < 4; i++) {
51 gint val = g_ascii_xdigit_value(line[i]);
52 if (val == -1) return 0;
53 unichar += val << 4 * (3 - i);
54 }
55 *strg = g_new0(gchar, 5);
56 g_unichar_to_utf8(unichar, *strg);
57 *result = unichar;
58 return 1;
59
60 }
61
get_symbol_table_data()62 static GSList *get_symbol_table_data() {
63
64 GIOChannel *symbol_table;
65 GError *error = NULL;
66 static GSList *symbols = NULL;
67
68 if (symbols != NULL) {
69 IM_JA_DEBUG("returning symbols from memory\n");
70 return symbols;
71 }
72
73 symbol_table = g_io_channel_new_file(IM_JA_DATADIR"/im-ja-symbols.txt", "r", &error);
74
75 if (symbol_table != NULL) {
76 GIOStatus status;
77 gchar *line;
78 gsize length;
79 gsize newline_pos;
80 GSList *symbol_group = NULL;
81 gchar *utf8_strg;
82 gint conv_result = 0, last_result = 0;
83 gunichar unichar = 0, last_unichar, i;
84
85 while ((status = g_io_channel_read_line(symbol_table, &line, &length,
86 &newline_pos, &error)) == G_IO_STATUS_NORMAL) {
87
88 /* Skip comments and empty lines */
89 if ((line[0] == '#') || (line[0] == '\n')) continue;
90 else {
91 if ((line[0] == '%') || (line[0] == ' ')) { /* process symbol group */
92 gchar *group_name;
93 symbol_group = NULL;
94 group_name = g_new0(gchar, length);
95 g_strlcpy(group_name, line + 2, length - 2);
96 symbol_group = g_slist_append(symbol_group, group_name);
97 symbols = g_slist_append(symbols, symbol_group);
98 last_result = 0;
99 }
100 else { /* process group entries */
101 last_result = conv_result;
102 last_unichar = unichar;
103 conv_result = convert_line(&unichar, &utf8_strg, line, length);
104 if (conv_result == 1) {
105 if (last_result == 2) { /* We need to generate a series of entries (2 == Range) */
106 for (i = last_unichar + 1; i <= unichar; i++) {
107 utf8_strg = g_new0(gchar, 5);
108 g_unichar_to_utf8(i, utf8_strg);
109 symbol_group = g_slist_append(symbol_group, utf8_strg);
110 }
111 }
112 else { /* Add only one entry */
113 symbol_group = g_slist_append(symbol_group, utf8_strg);
114 }
115 }
116 }
117 }
118 g_free(line);
119 }
120 g_io_channel_shutdown(symbol_table, FALSE, &error);
121 }
122
123 return symbols;
124 }
125
key_press_cb(GtkWidget * window,GdkEventKey * event,gpointer data)126 static gboolean key_press_cb(GtkWidget *window, GdkEventKey *event, gpointer data) {
127 if (event->keyval == GDK_Escape) {
128 gtk_widget_destroy(window);
129 return TRUE;
130 }
131 return FALSE;
132 }
133
symbol_pressed_cb(GtkWidget * button,IMJAContext * cn)134 static void symbol_pressed_cb(GtkWidget *button, IMJAContext *cn) {
135 GtkWidget *window;
136 gchar *symbol;
137
138 window = g_object_get_data(G_OBJECT(button), "im-ja-symbol-window");
139 symbol = g_object_get_data(G_OBJECT(button), "im-ja-utf8-symbol");
140 gtk_widget_destroy(window);
141
142 /* symbol = gtk_button_get_label(GTK_BUTTON(button)); */
143 im_ja_input_utf8(cn, symbol);
144 }
145
146 /* This makes the secondary table with the symbols */
show_symbols(GtkWidget * button,IMJAContext * cn)147 static void show_symbols(GtkWidget *button, IMJAContext *cn) {
148 GSList *symbols_ptr;
149 GSList *symbols;
150 gint rows = 0;
151 gint cols = 0;
152 gint col, row;
153 gint total = 0;
154 gint cnt = 0;
155 gdouble root;
156 GtkWidget *window;
157 GtkWidget *grp_window;
158 GtkWidget *symbol_table;
159
160 symbols = symbols_ptr = g_object_get_data(G_OBJECT(button), "im-ja-symbols");
161 grp_window = g_object_get_data(G_OBJECT(button), "im-ja-symbol-grp-window");
162 gtk_widget_destroy(grp_window);
163
164
165 /* count the elements in the table */
166 while (symbols_ptr != NULL) {
167 total++;
168 symbols_ptr = g_slist_next(symbols_ptr);
169 }
170 total--; /* The group name doesn't count; */
171
172 /* Calculate table size; */
173 root = sqrt((double) total);
174 rows = cols = (gint) root;
175 if (((gdouble) rows) < root) {
176 rows++;
177 if (rows * cols < total) cols++;
178 }
179 IM_JA_DEBUG("Total: %d, Rows: %d, cols: %d\n", total, rows, cols);
180
181 /* Create the table */
182 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
183 gtk_window_set_title(GTK_WINDOW(window), _("Symbols"));
184 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
185
186 /* FIXME */
187 #ifdef IMJA_TARGET_GTK
188 if (GTK_IS_WINDOW(cn->toplevel_gtk)) {
189 gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(cn->toplevel_gtk));
190 }
191 #endif
192 g_signal_connect(GTK_OBJECT(window), "key_press_event", G_CALLBACK(key_press_cb), NULL);
193
194 symbol_table = gtk_table_new(rows, cols, TRUE);
195 gtk_container_add(GTK_CONTAINER(window), symbol_table);
196
197 symbols_ptr = symbols;
198 symbols_ptr = g_slist_next(symbols_ptr); /* skip the group name */
199
200 col = row = 0;
201 while (symbols_ptr != NULL) {
202 while (col < cols) {
203 if (symbols_ptr->data != NULL) {
204 GtkWidget *tmpwidget = gtk_button_new_with_label(symbols_ptr->data);
205 g_object_set_data(G_OBJECT(tmpwidget), "im-ja-symbol-window", (gpointer) window);
206 g_object_set_data(G_OBJECT(tmpwidget), "im-ja-utf8-symbol", symbols_ptr->data);
207 g_signal_connect(G_OBJECT(tmpwidget), "clicked", G_CALLBACK(symbol_pressed_cb), cn);
208
209 gtk_table_attach(GTK_TABLE(symbol_table), tmpwidget, col, col + 1, row, row + 1,
210 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
211 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
212
213 symbols_ptr = g_slist_next(symbols_ptr);
214 cnt++;
215 col++;
216 if (symbols_ptr == NULL) break;
217 }
218 }
219 col = 0;
220 row++;
221 }
222
223 gtk_widget_show_all(window);
224
225 }
226
227 /* This creates the main table with the symbol groups */
im_ja_symbol_table_show(IMJAContext * cn)228 void im_ja_symbol_table_show(IMJAContext *cn) {
229 GSList *symbols_ptr = NULL;
230 GSList *symbols = NULL;
231 GSList *symbol_group_ptr = NULL;
232 gint rows = 0;
233 gint cols = 0;
234 gint col, row;
235 gint total = 0;
236 gint cnt = 0;
237 GtkWidget *window;
238 GtkWidget *symbol_grp_table;
239
240 IM_JA_DEBUG("im_ja_symbol_table_show()\n");
241
242 symbols = symbols_ptr = get_symbol_table_data();
243
244 /* count the elements in the table */
245 while (symbols_ptr != NULL) {
246 total++;
247 symbols_ptr = g_slist_next(symbols_ptr);
248 }
249 /* Calculate table size; */
250 /*
251 // if (total > 4) cols = 3;
252 // else
253 */
254 cols = 2;
255 rows = total / cols;
256
257 /* Create the table */
258 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
259 gtk_window_set_title(GTK_WINDOW(window), _("Symbol groups"));
260 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
261
262 /* FIXME */
263 #ifdef IMJA_TARGET_GTK
264 if (GTK_IS_WINDOW(cn->toplevel_gtk)) {
265 gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(cn->toplevel_gtk));
266 }
267 #endif
268
269 g_signal_connect(GTK_OBJECT(window), "key_press_event", G_CALLBACK(key_press_cb), NULL);
270
271 symbol_grp_table = gtk_table_new(rows, cols, TRUE);
272 gtk_container_add(GTK_CONTAINER(window), symbol_grp_table);
273
274 symbols_ptr = symbols;
275 col = row = 0;
276 while (symbols_ptr != NULL) {
277 while (col < cols) {
278 symbol_group_ptr = symbols_ptr->data;
279 if (symbol_group_ptr != NULL) {
280 GtkWidget *tmpwidget = gtk_button_new_with_label(symbol_group_ptr->data);
281 g_object_set_data(G_OBJECT(tmpwidget), "im-ja-symbols", (gpointer) symbol_group_ptr);
282 g_object_set_data(G_OBJECT(tmpwidget), "im-ja-symbol-grp-window", (gpointer) window);
283 g_signal_connect(G_OBJECT(tmpwidget), "clicked", G_CALLBACK(show_symbols), cn);
284
285 gtk_table_attach(GTK_TABLE(symbol_grp_table), tmpwidget, col, col + 1, row, row + 1,
286 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
287 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
288 symbols_ptr = g_slist_next(symbols_ptr);
289 cnt++;
290 col++;
291 if (symbols_ptr == NULL) break;
292 }
293 }
294 col = 0;
295 row++;
296 }
297
298 gtk_widget_show_all(window);
299
300 }
301
translate_unicode_entry_cb(GtkWidget * entry,IMJAContext * cn)302 static void translate_unicode_entry_cb(GtkWidget *entry, IMJAContext *cn) {
303 gchar *code_strg, *utf8_strg;
304 gint length;
305 gunichar unichar;
306 GtkWidget *window;
307 gboolean input_ok = TRUE;
308 gint i;
309
310 code_strg = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
311 length = strlen(code_strg);
312
313 window = g_object_get_data(G_OBJECT(entry), "im-ja-unicode-entry-window");
314 gtk_widget_destroy(window);
315
316 if (length == 0) return;
317
318 if (length != 4) input_ok = FALSE;
319 else {
320 unichar = 0;
321 for (i = 0; i < 4; i++) {
322 gint val = g_ascii_xdigit_value(code_strg[i]);
323 if (val == -1) {
324 input_ok = FALSE;
325 break;
326 }
327 unichar += val << 4 * (3 - i);
328 }
329 }
330
331 if (input_ok == TRUE) {
332 if (g_unichar_validate(unichar) == FALSE) {
333 im_ja_print_error(_("Invalid unicode character: %s"), code_strg);
334 }
335 else {
336 utf8_strg = g_new0(gchar, 5);
337 g_unichar_to_utf8(unichar, utf8_strg);
338 im_ja_input_utf8(cn, utf8_strg);
339 }
340 }
341 else {
342 im_ja_print_error(_("Invalid 4 byte HEX input: %s"), code_strg);
343 }
344 g_free(code_strg);
345 }
346
translate_jiscode_entry_cb(GtkWidget * entry,IMJAContext * cn)347 static void translate_jiscode_entry_cb(GtkWidget *entry, IMJAContext *cn) {
348 gchar *code_strg, *utf8_strg, *euc_str;
349 gint length;
350 GtkWidget *window;
351 gboolean input_ok = TRUE;
352 gint i;
353 gint val = 0;
354 wchar src_str[2];
355 int chr = 0;
356
357 code_strg = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
358 length = strlen(code_strg);
359
360 window = g_object_get_data(G_OBJECT(entry), "im-ja-jiscode-entry-window");
361 gtk_widget_destroy(window);
362
363
364 if (length == 0) return;
365
366 if (length != 4) input_ok = FALSE;
367 else {
368 val = 0;
369 chr = 0;
370 for (i = 0; i < 4; i++) {
371 gint val = g_ascii_xdigit_value(code_strg[i]);
372 if (val == -1) {
373 input_ok = FALSE;
374 break;
375 }
376 chr = (chr << 4) + val;
377 }
378 }
379 if (chr != -1) input_ok = TRUE;
380
381 src_str[0] = chr | 0x8080;
382 src_str[1] = 0;
383
384 euc_str = wc2euc(src_str, strlen((gchar*)src_str));
385 utf8_strg = euc2utf8(euc_str);
386 g_free(euc_str);
387
388 if (input_ok == TRUE) {
389 const gchar *end;
390 if (g_utf8_validate(utf8_strg, -1, &end) == FALSE) {
391 im_ja_print_error(_("Invalid unicode character: %s"), code_strg);
392 }
393 else {
394 im_ja_input_utf8(cn, utf8_strg);
395 }
396 }
397 else {
398 im_ja_print_error(_("Invalid 4 byte HEX input: %s"), code_strg);
399 }
400 g_free(code_strg);
401 }
402
im_ja_unicode_entry_show(IMJAContext * cn)403 void im_ja_unicode_entry_show(IMJAContext *cn) {
404 GtkWidget *window;
405 GtkWidget *hbox;
406 GtkWidget *label;
407 GtkWidget *entry;
408
409 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
410 gtk_window_set_title(GTK_WINDOW(window), _("Unicode entry"));
411 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
412
413 /* FIXME */
414 #ifdef IMJA_TARGET_GTK
415 if (GTK_IS_WINDOW(cn->toplevel_gtk)) {
416 gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(cn->toplevel_gtk));
417 }
418 #endif
419 g_signal_connect(GTK_OBJECT(window), "key_press_event", G_CALLBACK(key_press_cb), NULL);
420
421 hbox = gtk_vbox_new(FALSE, 5);
422 gtk_container_add(GTK_CONTAINER(window), hbox);
423
424 label = gtk_label_new(_("4 Byte HEX UniCode:"));
425 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
426
427 entry = gtk_entry_new();
428 gtk_entry_set_max_length(GTK_ENTRY(entry), 4);
429 gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
430 g_object_set_data(G_OBJECT(entry), "im-ja-unicode-entry-window", (gpointer) window);
431 g_signal_connect(GTK_OBJECT(entry), "activate", G_CALLBACK(translate_unicode_entry_cb), cn);
432
433 gtk_widget_show_all(window);
434
435 }
436
im_ja_jiscode_entry_show(IMJAContext * cn)437 void im_ja_jiscode_entry_show(IMJAContext *cn) {
438 GtkWidget *window;
439 GtkWidget *hbox;
440 GtkWidget *label;
441 GtkWidget *entry;
442
443 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
444 gtk_window_set_title(GTK_WINDOW(window), _("JIS Code entry"));
445 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
446
447 /* FIXME */
448 #ifdef IMJA_TARGET_GTK
449 if (GTK_IS_WINDOW(cn->toplevel_gtk)) {
450 gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(cn->toplevel_gtk));
451 }
452 #endif
453 g_signal_connect(GTK_OBJECT(window), "key_press_event", G_CALLBACK(key_press_cb), NULL);
454
455 hbox = gtk_vbox_new(FALSE, 5);
456 gtk_container_add(GTK_CONTAINER(window), hbox);
457
458 label = gtk_label_new(_("4 Byte JIS Code:"));
459 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
460
461 entry = gtk_entry_new();
462 gtk_entry_set_max_length(GTK_ENTRY(entry), 4);
463 gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
464 g_object_set_data(G_OBJECT(entry), "im-ja-jiscode-entry-window", (gpointer) window);
465 g_signal_connect(GTK_OBJECT(entry), "activate", G_CALLBACK(translate_jiscode_entry_cb), cn);
466
467 gtk_widget_show_all(window);
468
469 }
470