1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
2 /* vs: set ts=2 sw=2: */
3 /* IM-JA Japanese Input Method Module for GTK-2.0
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Authors: Botond Botyanszki <boti@rocketmail.com>
21  *          Srin Tuar <srintuar26@earthlink.net>
22  */
23 
24 #include <gdk/gdkevents.h>
25 #include <gdk/gdkkeysyms.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "common.h"
30 #include "conf.h"
31 #include "error.h"
32 
euc2utf8(const gchar * str)33 gchar *euc2utf8(const gchar *str) {
34   GError *error = NULL;
35   gchar *result;
36 
37   result = g_convert (str, -1, "UTF-8", "EUC-JP", NULL, NULL, &error);
38   if (!result)  {
39 		result = g_convert (str, -1, "UTF-8", "EUC-JISX0213", NULL, NULL, &error);
40 		if( !result ) {
41 			g_warning ("Error converting text from EUC-JP to UTF-8: %s\n", error->message);
42 			g_error_free (error);
43 			result = g_strdup("???");
44 		}
45   }
46 
47   return result;
48 }
49 
utf82euc(const gchar * str)50 gchar *utf82euc(const gchar *str) {
51   GError *error = NULL;
52   gchar *result;
53 
54   result = g_convert (str, -1, "EUC-JP", "UTF-8", NULL, NULL, &error);
55   if (!result)  {
56     g_warning ("Error converting text from UTF-8 to EUC-JP: %s\n", error->message);
57     g_error_free (error);
58   }
59 
60   return result;
61 }
62 
utf8to16(const gchar * str)63 gchar *utf8to16(const gchar *str) {
64   GError *error = NULL;
65   gchar *result;
66 
67   result = g_convert (str, -1, "UTF-16", "UTF-8", NULL, NULL, &error);
68   if (!result)  {
69     g_warning ("Error converting text from UTF-8 to UTF-16: %s\n", error->message);
70     g_error_free (error);
71   }
72 
73   return result;
74 }
75 
euc2wc(gchar * eucstr)76 int euc2wc(gchar *eucstr) { /* probably reinvented the wheel here. */
77 	int wcchar;
78 
79 	if (((unsigned char) (*eucstr)) > 128) {
80 		wcchar = ((int) *eucstr << 8) + ((int) *(eucstr + 1) & 0xff);
81 	}
82 	else {
83 		wcchar = *eucstr;
84 	}
85 	return wcchar;
86 }
87 
wc2euc(wchar * wcstr,gint size)88 gchar *wc2euc(wchar *wcstr, gint size) { /* probably reinvented the wheel here. */
89 	gchar *eucstr, *eucptr;
90 	int i;
91 	eucstr = g_new0(gchar, size * 2 + 1);
92 	eucptr = eucstr;
93 	i = 0;
94 	for (i = 0; i < size; i++) {
95 		if (*wcstr == 0) break;
96 		if (*(wcstr + i) > 128) {
97 			*eucptr = *(wcstr + i) >> 8;
98 			*(eucptr + 1) = *(wcstr + i) & 0xff;
99 			eucptr += 2;
100 		}
101 		else {
102 			*eucptr = *(wcstr + i);
103 			eucptr++;
104 		}
105 	}
106 	return eucstr;
107 }
108 
109 
isJPChar(gunichar c)110 gboolean isJPChar(gunichar c) {
111   if (isKanaChar(c) == TRUE) return TRUE;
112   if (isKanjiChar(c) == TRUE) return TRUE;
113   if (isOtherChar(c) == TRUE) return TRUE;
114   return FALSE;
115 }
isKanaChar(gunichar c)116 gboolean isKanaChar(gunichar c) {
117   if (isKatakanaChar(c) == TRUE) return TRUE;
118   if (isHiraganaChar(c) == TRUE) return TRUE;
119   return FALSE;
120 }
isKatakanaChar(gunichar c)121 gboolean isKatakanaChar(gunichar c) {
122   if ((c >= 0x30A0) && (c <= 0x30FF)) return TRUE; /* Full and half Katakana */
123   if ((c >= 0xFF65) && (c <= 0xFF9F)) return TRUE; /* Narrow Katakana */
124   return FALSE;
125 }
isHiraganaChar(gunichar c)126 gboolean isHiraganaChar(gunichar c) {
127   if ((c >= 0x3040) && (c <= 0x309F)) return TRUE; /* Hiragana */
128   return FALSE;
129 }
isKanjiChar(gunichar c)130 gboolean isKanjiChar(gunichar c) {
131   if ((c >= 0x3300) && (c <= 0x33FF)) return TRUE; /* cjk compatibility */
132   if ((c >= 0x3400) && (c <= 0x4DBF)) return TRUE; /* cjk ext A */
133   if ((c >= 0x4E00) && (c <= 0x9FAF)) return TRUE; /* cjk unified */
134   if ((c >= 0x20000) && (c <= 0x2A6DF)) return TRUE; /* cjk ext B */
135   if ((c >= 0x2F800) && (c <= 0x2FA1F)) return TRUE;  /* cjk supplement */
136   return FALSE;
137 }
isOtherChar(gunichar c)138 gboolean isOtherChar(gunichar c) {
139   if ((c >= 0x2E80) && (c <= 0x2EFF)) return TRUE;  /* cjk radical */
140   if ((c >= 0x2F00) && (c <= 0x2FDF)) return TRUE;  /* cjk kangxi radicals */
141   if ((c >= 0x2FF0) && (c <= 0x2FFF)) return TRUE;  /* ideographic */
142   if ((c >= 0x3000) && (c <= 0x303F)) return TRUE;  /* punctuation */
143   if ((c >= 0x3200) && (c <= 0x32FF)) return TRUE;  /* enclosed letters */
144   if ((c >= 0xFE30) && (c <= 0xFE4F)) return TRUE;  /* compatibility forms */
145   if ((c >= 0xFF00) && (c <= 0xFF64)) return TRUE;  /* compatibility forms2 */
146   if ((c >= 0xFFA0) && (c <= 0xFFEF)) return TRUE;  /* compatibility forms3 */
147   return FALSE;
148 }
149 
150 /* Convert Hiragana -> Katakana.*/
hira2kata(gchar * hirastr)151 gchar *hira2kata(gchar *hirastr) {
152   gchar *hiraptr;
153   gchar *kata = g_new0(gchar, strlen(hirastr) + 6);
154   gchar *kataptr = kata;
155   int length;
156 
157   hiraptr = hirastr;
158   while (*hiraptr != 0) {
159     if (isHiraganaChar(g_utf8_get_char(hiraptr)) == TRUE) {
160       g_unichar_to_utf8(g_utf8_get_char(hiraptr) + 96, kataptr);
161     }
162     else {
163       length = g_utf8_next_char(hiraptr) - hiraptr;
164       strncat(kataptr, hiraptr, length);
165       kataptr[length + 1] = 0;
166     }
167     kataptr = g_utf8_next_char(kataptr);
168     hiraptr = g_utf8_next_char(hiraptr);
169     if (hiraptr == NULL) break;
170   }
171   return kata;
172 }
173 
174 /*
175 gint char_to_byte_pos(gchar *str, gint pos) {
176 	gint byte_pos = 0;
177 	gchar *ptr = str;
178 	gint len = strlen(str);
179 	gint cnt = 0;
180 
181 	if (len == 0) return 0;
182 
183 	while (byte_pos <= len) {
184 		if (cnt == pos) break;
185 		ptr = g_utf8_next_char(ptr);
186 		byte_pos = ptr - str;
187 		cnt++;
188 	}
189 	return byte_pos;
190 }
191 */
192 
193 /* Convert fullsize katakana to half width*/
194 /*
195 gchar *full2half(gchar *instr) {
196   gchar *inptr = instr;
197   gchar *out = g_new0(gchar, strlen(instr));
198   gchar *outptr = out;
199   int length;
200 
201   IM_JA_DEBUG("instr:%s\n", utf82euc(instr));
202 
203   while (*inptr != 0) {
204     if (isKanaChar(g_utf8_get_char(inptr)) == TRUE) {
205       IM_JA_DEBUG("hex:%x\n", (int)g_utf8_get_char(inptr));
206       g_unichar_to_utf8(g_utf8_get_char(inptr) - 1, outptr);
207     }
208     else {
209       length = g_utf8_next_char(inptr) - inptr;
210       strncat(outptr, inptr, length);
211       outptr[length + 1] = 0;
212     }
213     outptr = g_utf8_next_char(outptr);
214     inptr = g_utf8_next_char(inptr);
215     if (inptr == NULL) break;
216   }
217   IM_JA_DEBUG("outstr:%s\n", utf82euc(out));
218   return out;
219 }
220 */
221 
222 #define ALL_ACCELS_MASK (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)
im_ja_is_printable_key(GdkEventKey * key)223 gboolean im_ja_is_printable_key(GdkEventKey *key) {
224 	/*
225 	guint keyval;
226 	gint eff_group, level;
227 	GdkModifierType consumed;
228 
229 	gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(), key->hardware_keycode,
230 																			key->state, key->group,
231                                      &keyval, &eff_group, &level, &consumed);
232 	if (key->state & ~consumed & ALL_ACCELS_MASK) return FALSE;
233 	*/
234 
235 	if (key->state & (gtk_accelerator_get_default_mod_mask() & ~GDK_SHIFT_MASK)) return FALSE;
236 
237 	/* non-printable KP keys */
238 	if (key->keyval >= GDK_KP_Enter && key->keyval <= GDK_KP_Delete) {
239 		return FALSE;
240 	}
241 
242 	IM_JA_DEBUG(" printable by gdk\n");
243   /* NORMAL CHAR KEYS */
244 	if ((key->keyval >= GDK_exclam && key->keyval <= GDK_overline) ||
245 			(key->keyval >= GDK_KP_Space && key->keyval <= GDK_KP_9)) {
246 		return TRUE;
247 	}
248 
249 	return FALSE;
250 
251 }
252 
ishotkey(GdkEventKey * key,int hotkey,IMJAConfig * cfg)253 gboolean ishotkey(GdkEventKey *key, int hotkey, IMJAConfig *cfg) {
254   guint state = key->state;
255 
256   state &= ~GDK_LOCK_MASK;
257   state &= ~GDK_MOD2_MASK;
258   state &= ~GDK_MOD5_MASK;
259 
260   if ((state == cfg->hotkey_states[hotkey]) &&
261       (key->keyval == cfg->hotkey_values[hotkey])) return TRUE;
262 
263   return FALSE;
264 
265 }
266 
buffer_delchar(gchar * buf)267 gboolean buffer_delchar(gchar* buf) {
268   if( buf == NULL ) return FALSE;
269 
270   g_utf8_prev_char(buf + strlen(buf))[0] = 0;
271   return TRUE;
272 }
273 
274 /*
275 gchar *get_utf8_for_keyval(guint keyval) {
276   gchar *utf8strg = g_new0(gchar, 7);
277   int written = g_unichar_to_utf8(gdk_keyval_to_unicode(keyval), utf8strg);
278   utf8strg[written] = 0;
279   return utf8strg;
280 }
281 */
282 
buffer_inschar(char * buf,int maxbuf,char * ins,int pos)283 int buffer_inschar(char* buf, int maxbuf, char *ins, int pos) {
284 	char *repo, *end;
285 	int clen = strlen(buf);
286 	int nlen = strlen(ins);
287 
288 	if (clen+nlen >= maxbuf)	{
289 		nlen = maxbuf - clen - 1;
290 	}
291 
292 	clen += nlen;
293 
294 	repo = buf + clen;
295 	end = buf + pos + nlen;
296 
297 	while (repo >= end) {
298 		*repo = *(repo-nlen);
299 		--repo;
300 	}
301 
302 	repo = buf + pos;
303 	end = repo + nlen;
304 
305 	while (repo < end) *repo++ = *ins++;
306 
307 	return nlen;
308 }
309 
buffer_bkspchar(char * buf,int pos)310 int buffer_bkspchar(char* buf, int pos) {
311 	int delta=0;
312 	char *prev, *at;
313 
314 	at = buf + pos;
315 	prev = g_utf8_find_prev_char(buf, at);
316 
317 	if (prev) {
318 		delta = at - prev;
319 		do {
320 			*prev++ = *at++;
321 		}
322 		while (*prev);
323 	}
324 
325 	return delta;
326 }
327 
buffer_deltchar(char * buf,int pos)328 int buffer_deltchar(char* buf, int pos) {
329 	int delta=0;
330 	char *next, *at;
331 
332 	at = buf + pos;
333 	next = g_utf8_find_next_char(at, 0);
334 
335 	if (next) {
336 		delta = next - at;
337 		do {
338 			*at++ = *next++;
339 		}
340 		while (*at);
341 	}
342 
343 	return delta;
344 }
345