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