1 #include <ctype.h>
2 #include <glib.h>
3 #include <ibus.h>
4 #include <IBusChewingUtil.h>
5 
6 /**
7  * Utility routines that do not depend on
8  * IBusChewingEngine
9  */
10 
11 /*=====================================
12  * Tone
13  */
14 const gchar *toneKeys[] = {
15     "6347",			//Default
16     "jfds",			//hsu
17     "uiop",			//ibm
18     "zaq1",			//gin-yieh
19     "4321",			//eten
20     "kjfd",			//eten26
21     "6347",			//dvorak
22     "thdn",			//dvorak_hsu
23     "yert",			//dachen_26
24     "1234",			//hanyu
25     NULL
26 };
27 
get_tone(ChewingKbType kbType,KSym kSym)28 gint get_tone(ChewingKbType kbType, KSym kSym)
29 {
30     int i = 0;
31     if (kSym == ' ')
32 	return 1;
33     for (i = 0; i < 4; i++) {
34 	if (toneKeys[kbType][i] == kSym) {
35 	    return i + 2;
36 	}
37     }
38     return -1;
39 }
40 
add_tone(char * str,gint tone)41 void add_tone(char *str, gint tone)
42 {
43     switch (tone) {
44     case 2:
45 	g_strlcat(str, "ˊ", ZHUYIN_BUFFER_SIZE);
46 	break;
47     case 3:
48 	g_strlcat(str, "ˇ", ZHUYIN_BUFFER_SIZE);
49 	break;
50     case 4:
51 	g_strlcat(str, "ˋ", ZHUYIN_BUFFER_SIZE);
52 	break;
53     case 5:
54 	g_strlcat(str, "˙", ZHUYIN_BUFFER_SIZE);
55 	break;
56     default:
57 	break;
58     }
59 }
60 
61 /*=====================================
62  * Key
63  */
64 
key_sym_KP_to_normal(KSym k)65 KSym key_sym_KP_to_normal(KSym k)
66 {
67     if (k < IBUS_KP_0 || k > IBUS_KP_9) {
68 	switch (k) {
69 	case IBUS_KP_Decimal:
70 	    return IBUS_period;
71 	case IBUS_KP_Add:
72 	    return IBUS_plus;
73 	case IBUS_KP_Subtract:
74 	    return IBUS_minus;
75 	case IBUS_KP_Multiply:
76 	    return IBUS_asterisk;
77 	case IBUS_KP_Divide:
78 	    return IBUS_slash;
79 	default:
80 	    return 0;
81 	}
82     }
83     return k - IBUS_KP_0 + IBUS_0;
84 }
85 
86 const char asciiConst[] =
87     " \0" "!\0" "\"\0" "#\0" "$\0" "%\0" "&\0" "'\0" "(\0" ")\0"
88     "*\0" "+\0" ",\0" "-\0" ".\0" "/\0" "0\0" "1\0" "2\0" "3\0"
89     "4\0" "5\0" "6\0" "7\0" "8\0" "9\0" ":\0" ";\0" "<\0" "=\0"
90     ">\0" "?\0" "@\0" "A\0" "B\0" "C\0" "D\0" "E\0" "F\0" "G\0"
91     "H\0" "I\0" "J\0" "K\0" "L\0" "M\0" "N\0" "O\0" "P\0" "Q\0"
92     "R\0" "S\0" "T\0" "U\0" "V\0" "W\0" "X\0" "Y\0" "Z\0" "[\0"
93     "\\\0" "]\0" "^\0" "_\0" "`\0" "a\0" "b\0" "c\0" "d\0" "e\0"
94     "f\0" "g\0" "h\0" "i\0" "j\0" "k\0" "l\0" "m\0" "n\0" "o\0"
95     "p\0" "q\0" "r\0" "s\0" "t\0" "u\0" "v\0" "w\0" "x\0" "y\0"
96     "z\0" "{\0" "|\0" "}\0" "~\0";
97 
key_sym_get_name(KSym k)98 const char *key_sym_get_name(KSym k)
99 {
100     switch (k) {
101     case IBUS_Return:
102 	return "Return";
103     case IBUS_KP_Enter:
104 	return "KP_Enter";
105     case IBUS_Escape:
106 	return "Escape";
107     case IBUS_BackSpace:
108 	return "BackSpace";
109     case IBUS_Delete:
110 	return "Delete";
111     case IBUS_KP_Delete:
112 	return "KP_Delete";
113     case IBUS_space:
114 	return "space";
115     case IBUS_KP_Space:
116 	return "KP_space";
117     case IBUS_Page_Up:
118 	return "Page_Up";
119     case IBUS_KP_Page_Up:
120 	return "KP_Page_Up";
121     case IBUS_Page_Down:
122 	return "Page_Down";
123     case IBUS_KP_Page_Down:
124 	return "KP_Page_Down";
125     case IBUS_Up:
126 	return "Up";
127     case IBUS_KP_Up:
128 	return "KP_Up";
129     case IBUS_Down:
130 	return "Down";
131     case IBUS_KP_Down:
132 	return "KP_Down";
133     case IBUS_Left:
134 	return "Left";
135     case IBUS_KP_Left:
136 	return "KP_Left";
137     case IBUS_Right:
138 	return "Right";
139     case IBUS_KP_Right:
140 	return "KP_Right";
141     case IBUS_Home:
142 	return "Home";
143     case IBUS_KP_Home:
144 	return "KP_Home";
145     case IBUS_End:
146 	return "End";
147     case IBUS_KP_End:
148 	return "KP_End";
149     case IBUS_Tab:
150 	return "Tab";
151     case IBUS_Caps_Lock:
152 	return "Caps";
153     case IBUS_Shift_L:
154 	return "Shift_L";
155     case IBUS_Shift_R:
156 	return "Shift_R";
157     case IBUS_Alt_L:
158 	return "Alt_L";
159     case IBUS_Alt_R:
160 	return "Alt_R";
161     case IBUS_Control_L:
162 	return "Control_L";
163     case IBUS_Control_R:
164 	return "Control_R";
165     case IBUS_Super_L:
166 	return "Super_L";
167     case IBUS_Super_R:
168 	return "Super_R";
169     case IBUS_ISO_Lock:
170 	return "ISO_Lock";
171     case IBUS_ISO_Level3_Lock:
172 	return "ISO_Level3_Lock";
173     case IBUS_ISO_Level3_Shift:
174 	return "ISO_Level3_Shift";
175     case IBUS_KP_0:
176 	return "KP_0";
177     case IBUS_KP_1:
178 	return "KP_1";
179     case IBUS_KP_2:
180 	return "KP_2";
181     case IBUS_KP_3:
182 	return "KP_3";
183     case IBUS_KP_4:
184 	return "KP_4";
185     case IBUS_KP_5:
186 	return "KP_5";
187     case IBUS_KP_6:
188 	return "KP_6";
189     case IBUS_KP_7:
190 	return "KP_7";
191     case IBUS_KP_8:
192 	return "KP_8";
193     case IBUS_KP_9:
194 	return "KP_9";
195     default:
196 	if (isprint(k)) {
197 	    return &asciiConst[(k - ' ') * 2];
198 	}
199 	break;
200     }
201     return "Others";
202 }
203 
204 /*=====================================
205  * Modifiers
206  */
207 
208 #define CAPS_LOCK_MASK 2
is_caps_led_on(Display * pDisplay)209 gboolean is_caps_led_on(Display * pDisplay)
210 {
211     XKeyboardState retState;
212     XGetKeyboardControl(pDisplay, &retState);
213     XFlush(pDisplay);
214     return (retState.led_mask & 1) ? TRUE : FALSE;
215 }
216 
set_caps_led(gboolean on,Display * pDisplay)217 void set_caps_led(gboolean on, Display * pDisplay)
218 {
219     XKeyboardControl control;
220     control.led_mode = (on) ? LedModeOn : LedModeOff;
221     control.led = CAPS_LOCK_MASK;
222     guint flags = (on) ? CAPS_LOCK_MASK : 0;
223     XChangeKeyboardControl(pDisplay, KBLedMode, &control);
224     XkbLockModifiers(pDisplay, XkbUseCoreKbd, control.led, flags);
225     XFlush(pDisplay);
226 }
227 
modifier_get_string(guint modifier)228 const gchar *modifier_get_string(guint modifier)
229 {
230     switch (modifier) {
231     case 0:
232 	return "";
233     case IBUS_SHIFT_MASK:
234 	return "SHIFT";
235     case IBUS_LOCK_MASK:
236 	return "LOCK";
237     case IBUS_CONTROL_MASK:
238 	return "CONTROL";
239     case IBUS_MOD1_MASK:
240 	return "MOD1";
241     case IBUS_MOD2_MASK:
242 	return "MOD2";
243     case IBUS_MOD3_MASK:
244 	return "MOD3";
245     case IBUS_MOD4_MASK:
246 	return "MOD4";
247     case IBUS_MOD5_MASK:
248 	return "MOD5";
249     case IBUS_HANDLED_MASK:
250 	return "HANDLED";
251     case IBUS_FORWARD_MASK:
252 	return "FORWARD";
253     case IBUS_SUPER_MASK:
254 	return "SUPER";
255     case IBUS_HYPER_MASK:
256 	return "HYPER";
257     case IBUS_META_MASK:
258 	return "META";
259     case IBUS_RELEASE_MASK:
260 	return "RELEASE";
261     default:
262 	break;
263     }
264     return "UNRECOGNIZED_MASK";
265 }
266 
267 #define MODIFIER_BUFFER_SIZE 100
modifiers_to_string(guint modifier)268 const gchar *modifiers_to_string(guint modifier)
269 {
270     static gchar modifierBuf[MODIFIER_BUFFER_SIZE];
271     g_strlcpy(modifierBuf, "", MODIFIER_BUFFER_SIZE);
272     gboolean first = TRUE;
273     gint i, mask;
274     for (i = 0; i < 32; i++) {
275 	mask = 1 << i;
276 	if (modifier & mask) {
277 	    if (first) {
278 		g_strlcpy(modifierBuf, modifier_get_string(mask),
279 			  MODIFIER_BUFFER_SIZE);
280 		first = FALSE;
281 	    } else {
282 		g_strlcat(modifierBuf, "| ", MODIFIER_BUFFER_SIZE);
283 		g_strlcat(modifierBuf, modifier_get_string(mask),
284 			  MODIFIER_BUFFER_SIZE);
285 	    }
286 	}
287     }
288     return modifierBuf;
289 }
290 
291 /*=====================================
292  * Misc
293  */
294 
ibus_chewing_property_get_state(IBusProperty * prop)295 gboolean ibus_chewing_property_get_state(IBusProperty * prop)
296 {
297 #if IBUS_CHECK_VERSION(1, 4, 0)
298     return ibus_property_get_state(prop);
299 #else
300     return prop->state;
301 #endif
302 }
303