1 /***************************************************************************
2  *   Copyright (C) 2002~2005 by Yuking                                     *
3  *   yuking_net@sohu.com                                                   *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program 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         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
19  ***************************************************************************/
20 
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "fcitx/fcitx.h"
25 #include "fcitx-utils/log.h"
26 #include "fcitx-utils/utils.h"
27 #include <ctype.h>
28 #include "hotkey.h"
29 #include "keydata.h"
30 
31 /**
32  * String to key list.
33  **/
34 
35 typedef struct _KEY_LIST {
36     /**
37      * string name for the key in fcitx
38      **/
39     char         *strKey;
40     /**
41      * the keyval for the key.
42      **/
43     FcitxKeySym  code;
44 } KEY_LIST;
45 
46 /* fcitx key name translist */
47 KEY_LIST        keyList[] = {
48     {"TAB", FcitxKey_Tab},
49     {"ENTER", FcitxKey_Return},
50     {"LCTRL", FcitxKey_Control_L},
51     {"LSHIFT", FcitxKey_Shift_L},
52     {"LALT", FcitxKey_Alt_L},
53     {"RCTRL", FcitxKey_Control_R},
54     {"RSHIFT", FcitxKey_Shift_R},
55     {"RALT", FcitxKey_Alt_R},
56     {"INSERT", FcitxKey_Insert},
57     {"HOME", FcitxKey_Home},
58     {"PGUP", FcitxKey_Page_Up},
59     {"END", FcitxKey_End},
60     {"PGDN", FcitxKey_Page_Down},
61     {"ESCAPE", FcitxKey_Escape},
62     {"SPACE", FcitxKey_space},
63     {"BACKSPACE", FcitxKey_BackSpace},
64     {"DELETE", FcitxKey_Delete},
65     {"UP", FcitxKey_Up},
66     {"DOWN", FcitxKey_Down},
67     {"LEFT", FcitxKey_Left},
68     {"RIGHT", FcitxKey_Right},
69     {"LINEFEED", FcitxKey_Linefeed },
70     {"CLEAR", FcitxKey_Clear },
71     {"MULTIKEY", FcitxKey_Multi_key },
72     {"CODEINPUT", FcitxKey_Codeinput },
73     {"SINGLECANDIDATE", FcitxKey_SingleCandidate },
74     {"MULTIPLECANDIDATE", FcitxKey_MultipleCandidate },
75     {"PREVIOUSCANDIDATE", FcitxKey_PreviousCandidate },
76     {"KANJI", FcitxKey_Kanji },
77     {"MUHENKAN", FcitxKey_Muhenkan },
78     {"HENKANMODE", FcitxKey_Henkan_Mode },
79     {"HENKAN", FcitxKey_Henkan },
80     {"ROMAJI", FcitxKey_Romaji },
81     {"HIRAGANA", FcitxKey_Hiragana },
82     {"KATAKANA", FcitxKey_Katakana },
83     {"HIRAGANAKATAKANA", FcitxKey_Hiragana_Katakana },
84     {"ZENKAKU", FcitxKey_Zenkaku },
85     {"HANKAKU", FcitxKey_Hankaku },
86     {"ZENKAKUHANKAKU", FcitxKey_Zenkaku_Hankaku },
87     {"TOUROKU", FcitxKey_Touroku },
88     {"MASSYO", FcitxKey_Massyo },
89     {"KANALOCK", FcitxKey_Kana_Lock },
90     {"KANASHIFT", FcitxKey_Kana_Shift },
91     {"EISUSHIFT", FcitxKey_Eisu_Shift },
92     {"EISUTOGGLE", FcitxKey_Eisu_toggle },
93     {"KANJIBANGOU", FcitxKey_Kanji_Bangou },
94     {"ZENKOHO", FcitxKey_Zen_Koho },
95     {"MAEKOHO", FcitxKey_Mae_Koho },
96     {"F1", FcitxKey_F1 },
97     {"F2", FcitxKey_F2 },
98     {"F3", FcitxKey_F3 },
99     {"F4", FcitxKey_F4 },
100     {"F5", FcitxKey_F5 },
101     {"F6", FcitxKey_F6 },
102     {"F7", FcitxKey_F7 },
103     {"F8", FcitxKey_F8 },
104     {"F9", FcitxKey_F9 },
105     {"F10", FcitxKey_F10 },
106     {"F11", FcitxKey_F11 },
107     {"L1", FcitxKey_L1 },
108     {"F12", FcitxKey_F12 },
109     {"L2", FcitxKey_L2 },
110     {"F13", FcitxKey_F13 },
111     {"L3", FcitxKey_L3 },
112     {"F14", FcitxKey_F14 },
113     {"L4", FcitxKey_L4 },
114     {"F15", FcitxKey_F15 },
115     {"L5", FcitxKey_L5 },
116     {"F16", FcitxKey_F16 },
117     {"L6", FcitxKey_L6 },
118     {"F17", FcitxKey_F17 },
119     {"L7", FcitxKey_L7 },
120     {"F18", FcitxKey_F18 },
121     {"L8", FcitxKey_L8 },
122     {"F19", FcitxKey_F19 },
123     {"L9", FcitxKey_L9 },
124     {"F20", FcitxKey_F20 },
125     {"L10", FcitxKey_L10 },
126     {"F21", FcitxKey_F21 },
127     {"R1", FcitxKey_R1 },
128     {"F22", FcitxKey_F22 },
129     {"R2", FcitxKey_R2 },
130     {"F23", FcitxKey_F23 },
131     {"R3", FcitxKey_R3 },
132     {"F24", FcitxKey_F24 },
133     {"R4", FcitxKey_R4 },
134     {"F25", FcitxKey_F25 },
135     {"R5", FcitxKey_R5 },
136     {"F26", FcitxKey_F26 },
137     {"R6", FcitxKey_R6 },
138     {"F27", FcitxKey_F27 },
139     {"R7", FcitxKey_R7 },
140     {"F28", FcitxKey_F28 },
141     {"R8", FcitxKey_R8 },
142     {"F29", FcitxKey_F29 },
143     {"R9", FcitxKey_R9 },
144     {"F30", FcitxKey_F30 },
145     {"R10", FcitxKey_R10 },
146     {"F31", FcitxKey_F31 },
147     {"R11", FcitxKey_R11 },
148     {"F32", FcitxKey_F32 },
149     {"R12", FcitxKey_R12 },
150     {"F33", FcitxKey_F33 },
151     {"R13", FcitxKey_R13 },
152     {"F34", FcitxKey_F34 },
153     {"R14", FcitxKey_R14 },
154     {"F35", FcitxKey_F35 },
155     {"R15", FcitxKey_R15 },
156     {"FIRSTVIRTUALSCREEN", FcitxKey_First_Virtual_Screen },
157     {"PREVVIRTUALSCREEN", FcitxKey_Prev_Virtual_Screen },
158     {"NEXTVIRTUALSCREEN", FcitxKey_Next_Virtual_Screen },
159     {"LASTVIRTUALSCREEN", FcitxKey_Last_Virtual_Screen },
160     {"TERMINATESERVER", FcitxKey_Terminate_Server },
161     {"ACCESSXENABLE", FcitxKey_AccessX_Enable },
162     {"ACCESSXFEEDBACKENABLE", FcitxKey_AccessX_Feedback_Enable },
163     {"REPEATKEYSENABLE", FcitxKey_RepeatKeys_Enable },
164     {"SLOWKEYSENABLE", FcitxKey_SlowKeys_Enable },
165     {"BOUNCEKEYSENABLE", FcitxKey_BounceKeys_Enable },
166     {"STICKYKEYSENABLE", FcitxKey_StickyKeys_Enable },
167     {"MOUSEKEYSENABLE", FcitxKey_MouseKeys_Enable },
168     {"MOUSEKEYSACCELENABLE", FcitxKey_MouseKeys_Accel_Enable },
169     {"OVERLAY1ENABLE", FcitxKey_Overlay1_Enable },
170     {"OVERLAY2ENABLE", FcitxKey_Overlay2_Enable },
171     {"AUDIBLEBELLENABLE", FcitxKey_AudibleBell_Enable },
172     {"KAPPA", FcitxKey_kappa },
173     {"KANAMIDDLEDOT", FcitxKey_kana_middledot },
174     {"KANATU", FcitxKey_kana_tu },
175     {"KANATI", FcitxKey_kana_TI },
176     {"KANATU", FcitxKey_kana_TU },
177     {"KANAHU", FcitxKey_kana_HU },
178     {"KANASWITCH", FcitxKey_kana_switch },
179     {"ARABICHEH", FcitxKey_Arabic_heh },
180     {"ARABICSWITCH", FcitxKey_Arabic_switch },
181     {"UKRANIANJE", FcitxKey_Ukranian_je },
182     {"UKRANIANI", FcitxKey_Ukranian_i },
183     {"UKRANIANYI", FcitxKey_Ukranian_yi },
184     {"SERBIANJE", FcitxKey_Serbian_je },
185     {"SERBIANLJE", FcitxKey_Serbian_lje },
186     {"SERBIANNJE", FcitxKey_Serbian_nje },
187     {"SERBIANDZE", FcitxKey_Serbian_dze },
188     {"UKRANIANJE", FcitxKey_Ukranian_JE },
189     {"UKRANIANI", FcitxKey_Ukranian_I },
190     {"UKRANIANYI", FcitxKey_Ukranian_YI },
191     {"SERBIANJE", FcitxKey_Serbian_JE },
192     {"SERBIANLJE", FcitxKey_Serbian_LJE },
193     {"SERBIANNJE", FcitxKey_Serbian_NJE },
194     {"SERBIANDZE", FcitxKey_Serbian_DZE },
195     {"GREEKIOTADIAERESIS", FcitxKey_Greek_IOTAdiaeresis },
196     {"GREEKSWITCH", FcitxKey_Greek_switch },
197     {"TOPLEFTSUMMATION", FcitxKey_topleftsummation },
198     {"BOTLEFTSUMMATION", FcitxKey_botleftsummation },
199     {"TOPVERTSUMMATIONCONNECTOR", FcitxKey_topvertsummationconnector },
200     {"BOTVERTSUMMATIONCONNECTOR", FcitxKey_botvertsummationconnector },
201     {"TOPRIGHTSUMMATION", FcitxKey_toprightsummation },
202     {"BOTRIGHTSUMMATION", FcitxKey_botrightsummation },
203     {"RIGHTMIDDLESUMMATION", FcitxKey_rightmiddlesummation },
204     {"BLANK", FcitxKey_blank },
205     {"MARKER", FcitxKey_marker },
206     {"TRADEMARKINCIRCLE", FcitxKey_trademarkincircle },
207     {"HEXAGRAM", FcitxKey_hexagram },
208     {"CURSOR", FcitxKey_cursor },
209     {"HEBREWBETH", FcitxKey_hebrew_beth },
210     {"HEBREWGIMMEL", FcitxKey_hebrew_gimmel },
211     {"HEBREWDALETH", FcitxKey_hebrew_daleth },
212     {"HEBREWZAYIN", FcitxKey_hebrew_zayin },
213     {"HEBREWHET", FcitxKey_hebrew_het },
214     {"HEBREWTETH", FcitxKey_hebrew_teth },
215     {"HEBREWSAMEKH", FcitxKey_hebrew_samekh },
216     {"HEBREWFINALZADI", FcitxKey_hebrew_finalzadi },
217     {"HEBREWZADI", FcitxKey_hebrew_zadi },
218     {"HEBREWKUF", FcitxKey_hebrew_kuf },
219     {"HEBREWTAF", FcitxKey_hebrew_taf },
220     {"HEBREWSWITCH", FcitxKey_Hebrew_switch },
221     {"THAIMAIHANAKATMAITHO", FcitxKey_Thai_maihanakat_maitho },
222     {"HANGUL", FcitxKey_Hangul },
223     {"HANGULSTART", FcitxKey_Hangul_Start },
224     {"HANGULEND", FcitxKey_Hangul_End },
225     {"HANGULHANJA", FcitxKey_Hangul_Hanja },
226     {"HANGULJAMO", FcitxKey_Hangul_Jamo },
227     {"HANGULROMAJA", FcitxKey_Hangul_Romaja },
228     {"HANGULCODEINPUT", FcitxKey_Hangul_Codeinput },
229     {"HANGULJEONJA", FcitxKey_Hangul_Jeonja },
230     {"HANGULBANJA", FcitxKey_Hangul_Banja },
231     {"HANGULPREHANJA", FcitxKey_Hangul_PreHanja },
232     {"HANGULPOSTHANJA", FcitxKey_Hangul_PostHanja },
233     {"HANGULSINGLECANDIDATE", FcitxKey_Hangul_SingleCandidate },
234     {"HANGULMULTIPLECANDIDATE", FcitxKey_Hangul_MultipleCandidate },
235     {"HANGULPREVIOUSCANDIDATE", FcitxKey_Hangul_PreviousCandidate },
236     {"HANGULSPECIAL", FcitxKey_Hangul_Special },
237     {"HANGULSWITCH", FcitxKey_Hangul_switch },
238     {"HANGULKIYEOG", FcitxKey_Hangul_Kiyeog },
239     {"HANGULSSANGKIYEOG", FcitxKey_Hangul_SsangKiyeog },
240     {"HANGULKIYEOGSIOS", FcitxKey_Hangul_KiyeogSios },
241     {"HANGULNIEUN", FcitxKey_Hangul_Nieun },
242     {"HANGULNIEUNJIEUJ", FcitxKey_Hangul_NieunJieuj },
243     {"HANGULNIEUNHIEUH", FcitxKey_Hangul_NieunHieuh },
244     {"HANGULDIKEUD", FcitxKey_Hangul_Dikeud },
245     {"HANGULSSANGDIKEUD", FcitxKey_Hangul_SsangDikeud },
246     {"HANGULRIEUL", FcitxKey_Hangul_Rieul },
247     {"HANGULRIEULKIYEOG", FcitxKey_Hangul_RieulKiyeog },
248     {"HANGULRIEULMIEUM", FcitxKey_Hangul_RieulMieum },
249     {"HANGULRIEULPIEUB", FcitxKey_Hangul_RieulPieub },
250     {"HANGULRIEULSIOS", FcitxKey_Hangul_RieulSios },
251     {"HANGULRIEULTIEUT", FcitxKey_Hangul_RieulTieut },
252     {"HANGULRIEULPHIEUF", FcitxKey_Hangul_RieulPhieuf },
253     {"HANGULRIEULHIEUH", FcitxKey_Hangul_RieulHieuh },
254     {"HANGULMIEUM", FcitxKey_Hangul_Mieum },
255     {"HANGULPIEUB", FcitxKey_Hangul_Pieub },
256     {"HANGULSSANGPIEUB", FcitxKey_Hangul_SsangPieub },
257     {"HANGULPIEUBSIOS", FcitxKey_Hangul_PieubSios },
258     {"HANGULSIOS", FcitxKey_Hangul_Sios },
259     {"HANGULSSANGSIOS", FcitxKey_Hangul_SsangSios },
260     {"HANGULIEUNG", FcitxKey_Hangul_Ieung },
261     {"HANGULJIEUJ", FcitxKey_Hangul_Jieuj },
262     {"HANGULSSANGJIEUJ", FcitxKey_Hangul_SsangJieuj },
263     {"HANGULCIEUC", FcitxKey_Hangul_Cieuc },
264     {"HANGULKHIEUQ", FcitxKey_Hangul_Khieuq },
265     {"HANGULTIEUT", FcitxKey_Hangul_Tieut },
266     {"HANGULPHIEUF", FcitxKey_Hangul_Phieuf },
267     {"HANGULHIEUH", FcitxKey_Hangul_Hieuh },
268     {"HANGULA", FcitxKey_Hangul_A },
269     {"HANGULAE", FcitxKey_Hangul_AE },
270     {"HANGULYA", FcitxKey_Hangul_YA },
271     {"HANGULYAE", FcitxKey_Hangul_YAE },
272     {"HANGULEO", FcitxKey_Hangul_EO },
273     {"HANGULE", FcitxKey_Hangul_E },
274     {"HANGULYEO", FcitxKey_Hangul_YEO },
275     {"HANGULYE", FcitxKey_Hangul_YE },
276     {"HANGULO", FcitxKey_Hangul_O },
277     {"HANGULWA", FcitxKey_Hangul_WA },
278     {"HANGULWAE", FcitxKey_Hangul_WAE },
279     {"HANGULOE", FcitxKey_Hangul_OE },
280     {"HANGULYO", FcitxKey_Hangul_YO },
281     {"HANGULU", FcitxKey_Hangul_U },
282     {"HANGULWEO", FcitxKey_Hangul_WEO },
283     {"HANGULWE", FcitxKey_Hangul_WE },
284     {"HANGULWI", FcitxKey_Hangul_WI },
285     {"HANGULYU", FcitxKey_Hangul_YU },
286     {"HANGULEU", FcitxKey_Hangul_EU },
287     {"HANGULYI", FcitxKey_Hangul_YI },
288     {"HANGULI", FcitxKey_Hangul_I },
289     {"HANGULJKIYEOG", FcitxKey_Hangul_J_Kiyeog },
290     {"HANGULJSSANGKIYEOG", FcitxKey_Hangul_J_SsangKiyeog },
291     {"HANGULJKIYEOGSIOS", FcitxKey_Hangul_J_KiyeogSios },
292     {"HANGULJNIEUN", FcitxKey_Hangul_J_Nieun },
293     {"HANGULJNIEUNJIEUJ", FcitxKey_Hangul_J_NieunJieuj },
294     {"HANGULJNIEUNHIEUH", FcitxKey_Hangul_J_NieunHieuh },
295     {"HANGULJDIKEUD", FcitxKey_Hangul_J_Dikeud },
296     {"HANGULJRIEUL", FcitxKey_Hangul_J_Rieul },
297     {"HANGULJRIEULKIYEOG", FcitxKey_Hangul_J_RieulKiyeog },
298     {"HANGULJRIEULMIEUM", FcitxKey_Hangul_J_RieulMieum },
299     {"HANGULJRIEULPIEUB", FcitxKey_Hangul_J_RieulPieub },
300     {"HANGULJRIEULSIOS", FcitxKey_Hangul_J_RieulSios },
301     {"HANGULJRIEULTIEUT", FcitxKey_Hangul_J_RieulTieut },
302     {"HANGULJRIEULPHIEUF", FcitxKey_Hangul_J_RieulPhieuf },
303     {"HANGULJRIEULHIEUH", FcitxKey_Hangul_J_RieulHieuh },
304     {"HANGULJMIEUM", FcitxKey_Hangul_J_Mieum },
305     {"HANGULJPIEUB", FcitxKey_Hangul_J_Pieub },
306     {"HANGULJPIEUBSIOS", FcitxKey_Hangul_J_PieubSios },
307     {"HANGULJSIOS", FcitxKey_Hangul_J_Sios },
308     {"HANGULJSSANGSIOS", FcitxKey_Hangul_J_SsangSios },
309     {"HANGULJIEUNG", FcitxKey_Hangul_J_Ieung },
310     {"HANGULJJIEUJ", FcitxKey_Hangul_J_Jieuj },
311     {"HANGULJCIEUC", FcitxKey_Hangul_J_Cieuc },
312     {"HANGULJKHIEUQ", FcitxKey_Hangul_J_Khieuq },
313     {"HANGULJTIEUT", FcitxKey_Hangul_J_Tieut },
314     {"HANGULJPHIEUF", FcitxKey_Hangul_J_Phieuf },
315     {"HANGULJHIEUH", FcitxKey_Hangul_J_Hieuh },
316     {"HANGULRIEULYEORINHIEUH", FcitxKey_Hangul_RieulYeorinHieuh },
317     {"HANGULSUNKYEONGEUMMIEUM", FcitxKey_Hangul_SunkyeongeumMieum },
318     {"HANGULSUNKYEONGEUMPIEUB", FcitxKey_Hangul_SunkyeongeumPieub },
319     {"HANGULPANSIOS", FcitxKey_Hangul_PanSios },
320     {"HANGULKKOGJIDALRINIEUNG", FcitxKey_Hangul_KkogjiDalrinIeung },
321     {"HANGULSUNKYEONGEUMPHIEUF", FcitxKey_Hangul_SunkyeongeumPhieuf },
322     {"HANGULYEORINHIEUH", FcitxKey_Hangul_YeorinHieuh },
323     {"HANGULARAEA", FcitxKey_Hangul_AraeA },
324     {"HANGULARAEAE", FcitxKey_Hangul_AraeAE },
325     {"HANGULJPANSIOS", FcitxKey_Hangul_J_PanSios },
326     {"HANGULJKKOGJIDALRINIEUNG", FcitxKey_Hangul_J_KkogjiDalrinIeung },
327     {"HANGULJYEORINHIEUH", FcitxKey_Hangul_J_YeorinHieuh },
328     {"BRAILLEDOT1", FcitxKey_braille_dot_1 },
329     {"BRAILLEDOT2", FcitxKey_braille_dot_2 },
330     {"BRAILLEDOT3", FcitxKey_braille_dot_3 },
331     {"BRAILLEDOT4", FcitxKey_braille_dot_4 },
332     {"BRAILLEDOT5", FcitxKey_braille_dot_5 },
333     {"BRAILLEDOT6", FcitxKey_braille_dot_6 },
334     {"BRAILLEDOT7", FcitxKey_braille_dot_7 },
335     {"BRAILLEDOT8", FcitxKey_braille_dot_8 },
336     {"BRAILLEDOT9", FcitxKey_braille_dot_9 },
337     {"BRAILLEDOT10",FcitxKey_braille_dot_10 },
338     {"SELECT",      FcitxKey_Select },
339     {"EXECUTE",     FcitxKey_Execute },
340     {"PRINT",       FcitxKey_Print },
341     {"UNDO",        FcitxKey_Undo },
342     {"REDO",        FcitxKey_Redo },
343     {"MENU",        FcitxKey_Menu },
344     {"FIND",        FcitxKey_Find },
345     {"CANCEL",      FcitxKey_Cancel },
346     {"HELP",        FcitxKey_Help },
347     {"BREAK",       FcitxKey_Break },
348     {"PAUSE", FcitxKey_Pause},
349     {"SCROLLLOCK", FcitxKey_Scroll_Lock},
350     {"SYSREQ", FcitxKey_Sys_Req},
351     {"BEGIN", FcitxKey_Begin},
352     {"MODESWITCH", FcitxKey_Mode_switch},
353     {"SCRIPTSWITCH", FcitxKey_script_switch},
354     {"NUMLOCK", FcitxKey_Num_Lock},
355     {"KPSPACE", FcitxKey_KP_Space},
356     {"KPTAB", FcitxKey_KP_Tab},
357     {"KPENTER", FcitxKey_KP_Enter},
358     {"KPF1", FcitxKey_KP_F1},
359     {"KPF2", FcitxKey_KP_F2},
360     {"KPF3", FcitxKey_KP_F3},
361     {"KPF4", FcitxKey_KP_F4},
362     {"KPHOME", FcitxKey_KP_Home},
363     {"KPLEFT", FcitxKey_KP_Left},
364     {"KPUP", FcitxKey_KP_Up},
365     {"KPRIGHT", FcitxKey_KP_Right},
366     {"KPDOWN", FcitxKey_KP_Down},
367     {"KPPGUP", FcitxKey_KP_Page_Up},
368     {"KPPGDOWN", FcitxKey_KP_Page_Down},
369     {"KPEND", FcitxKey_KP_End},
370     {"KPBEGIN", FcitxKey_KP_Begin},
371     {"KPINSERT", FcitxKey_KP_Insert},
372     {"KPDELETE", FcitxKey_KP_Delete},
373     {"KPEQUAL", FcitxKey_KP_Equal},
374     {"KPMULTIPLY", FcitxKey_KP_Multiply},
375     {"KPADD", FcitxKey_KP_Add},
376     {"KPSEPARATOR", FcitxKey_KP_Separator},
377     {"KPSUBTRACT", FcitxKey_KP_Subtract},
378     {"KPDECIMAL", FcitxKey_KP_Decimal},
379     {"KPDIVIDE", FcitxKey_KP_Divide},
380     {"KP0", FcitxKey_KP_0},
381     {"KP1", FcitxKey_KP_1},
382     {"KP2", FcitxKey_KP_2},
383     {"KP3", FcitxKey_KP_3},
384     {"KP4", FcitxKey_KP_4},
385     {"KP5", FcitxKey_KP_5},
386     {"KP6", FcitxKey_KP_6},
387     {"KP7", FcitxKey_KP_7},
388     {"KP8", FcitxKey_KP_8},
389     {"KP9", FcitxKey_KP_9},
390     {"CAPSLOCK", FcitxKey_Caps_Lock},
391     {"SHIFTLOCK", FcitxKey_Shift_Lock},
392     {"LMETA", FcitxKey_Meta_L},
393     {"RMETA", FcitxKey_Meta_R},
394     {"LSUPER", FcitxKey_Super_L},
395     {"RSUPER", FcitxKey_Super_R},
396     {"LHYPER", FcitxKey_Hyper_L},
397     {"RHYPER", FcitxKey_Hyper_R},
398 
399 
400     {"\0", 0}
401 };
402 
403 
404 FCITX_EXPORT_API
405 uint32_t
FcitxKeySymToUnicode(FcitxKeySym keyval)406 FcitxKeySymToUnicode (FcitxKeySym keyval)
407 {
408     int min = 0;
409     int max = sizeof (gdk_keysym_to_unicode_tab) / sizeof(gdk_keysym_to_unicode_tab[0]) - 1;
410     int mid;
411 
412     /* First check for Latin-1 characters (1:1 mapping) */
413     if ((keyval >= 0x0020 && keyval <= 0x007e) ||
414             (keyval >= 0x00a0 && keyval <= 0x00ff))
415         return keyval;
416 
417     /* Also check for directly encoded 24-bit UCS characters:
418     */
419     if ((keyval & 0xff000000) == 0x01000000)
420         return keyval & 0x00ffffff;
421 
422     /* binary search in table */
423     while (max >= min) {
424         mid = (min + max) / 2;
425         if (gdk_keysym_to_unicode_tab[mid].keysym < keyval)
426             min = mid + 1;
427         else if (gdk_keysym_to_unicode_tab[mid].keysym > keyval)
428             max = mid - 1;
429         else {
430             /* found it */
431             return gdk_keysym_to_unicode_tab[mid].ucs;
432         }
433     }
434 
435     /* No matching Unicode value found */
436     return 0;
437 }
438 
439 FCITX_EXPORT_API
440 FcitxKeySym
FcitxUnicodeToKeySym(uint32_t wc)441 FcitxUnicodeToKeySym (uint32_t wc)
442 {
443     int min = 0;
444     int max = sizeof(gdk_unicode_to_keysym_tab) / sizeof(gdk_unicode_to_keysym_tab[0]) - 1;
445     int mid;
446 
447     /* First check for Latin-1 characters (1:1 mapping) */
448     if ((wc >= 0x0020 && wc <= 0x007e) ||
449             (wc >= 0x00a0 && wc <= 0x00ff))
450         return wc;
451 
452     /* Binary search in table */
453     while (max >= min) {
454         mid = (min + max) / 2;
455         if (gdk_unicode_to_keysym_tab[mid].ucs < wc)
456             min = mid + 1;
457         else if (gdk_unicode_to_keysym_tab[mid].ucs > wc)
458             max = mid - 1;
459         else {
460             /* found it */
461             return gdk_unicode_to_keysym_tab[mid].keysym;
462         }
463     }
464 
465     /*
466     * No matching keysym value found, return Unicode value plus 0x01000000
467     * (a convention introduced in the UTF-8 work on xterm).
468     */
469     return wc | 0x01000000;
470 }
471 
472 static int FcitxHotkeyGetKeyList(const char *strKey);
473 static char *FcitxHotkeyGetKeyListString(int key);
474 
475 FCITX_EXPORT_API
FcitxHotkeyIsHotKeyDigit(FcitxKeySym sym,unsigned int state)476 boolean FcitxHotkeyIsHotKeyDigit(FcitxKeySym sym, unsigned int state)
477 {
478     if (state)
479         return false;
480 
481     if (sym >= FcitxKey_0 && sym <= FcitxKey_9)
482         return true;
483 
484     return false;
485 }
486 
487 FCITX_EXPORT_API
FcitxHotkeyIsHotKeyUAZ(FcitxKeySym sym,unsigned int state)488 boolean FcitxHotkeyIsHotKeyUAZ(FcitxKeySym sym, unsigned int state)
489 {
490     if (state)
491         return false;
492 
493     if (sym >= FcitxKey_A && sym <= FcitxKey_Z)
494         return true;
495 
496     return false;
497 }
498 
499 FCITX_EXPORT_API
FcitxHotkeyIsHotKeySimple(FcitxKeySym sym,unsigned int state)500 boolean FcitxHotkeyIsHotKeySimple(FcitxKeySym sym, unsigned int state)
501 {
502     if (state)
503         return false;
504 
505     if (sym >= FcitxKey_space && sym <= FcitxKey_asciitilde)
506         return true;
507 
508     return false;
509 }
510 
511 FCITX_EXPORT_API
FcitxHotkeyIsHotKeyLAZ(FcitxKeySym sym,unsigned int state)512 boolean FcitxHotkeyIsHotKeyLAZ(FcitxKeySym sym, unsigned int state)
513 {
514     if (state)
515         return false;
516 
517     if (sym >= FcitxKey_a && sym <= FcitxKey_z)
518         return true;
519 
520     return false;
521 }
522 
523 FCITX_EXPORT_API
FcitxHotkeyIsKey(FcitxKeySym sym,unsigned int state,FcitxKeySym symcmp,unsigned int statecmp)524 boolean FcitxHotkeyIsKey(FcitxKeySym sym, unsigned int state, FcitxKeySym symcmp, unsigned int statecmp)
525 {
526     FcitxHotkey key[2] = { {0, symcmp, statecmp }, {0, 0, 0} };
527     return FcitxHotkeyIsHotKey(sym ,state, key);
528 }
529 
530 FCITX_EXPORT_API
FcitxHotkeyIsHotKey(FcitxKeySym sym,unsigned int state,const FcitxHotkey * hotkey)531 boolean FcitxHotkeyIsHotKey(FcitxKeySym sym, unsigned int state, const FcitxHotkey * hotkey)
532 {
533     state &= FcitxKeyState_Ctrl_Alt_Shift | FcitxKeyState_Super;
534     if (hotkey[0].sym && sym == hotkey[0].sym && (hotkey[0].state == state))
535         return true;
536     if (hotkey[1].sym && sym == hotkey[1].sym && (hotkey[1].state == state))
537         return true;
538     return false;
539 }
540 
541 FCITX_EXPORT_API
FcitxHotkeyIsHotkeyCursorMove(FcitxKeySym sym,unsigned int state)542 boolean FcitxHotkeyIsHotkeyCursorMove(FcitxKeySym sym, unsigned int state)
543 {
544     if ((
545                 sym == FcitxKey_Left
546                 || sym == FcitxKey_Right
547                 || sym == FcitxKey_Up
548                 || sym == FcitxKey_Down
549                 || sym == FcitxKey_Page_Up
550                 || sym == FcitxKey_Page_Down
551                 || sym == FcitxKey_Home
552                 || sym == FcitxKey_End
553             ) && (
554                 state == FcitxKeyState_Ctrl
555                 || state == FcitxKeyState_Ctrl_Shift
556                 || state == FcitxKeyState_Shift
557                 || state == FcitxKeyState_None
558             )
559 
560        ) {
561         return true;
562     }
563     return false;
564 }
565 
566 FCITX_EXPORT_API
FcitxHotkeyIsHotKeyModifierCombine(FcitxKeySym sym,unsigned int state)567 boolean FcitxHotkeyIsHotKeyModifierCombine(FcitxKeySym sym, unsigned int state)
568 {
569     FCITX_UNUSED(state);
570     if (sym == FcitxKey_Control_L || sym == FcitxKey_Control_R
571      || sym == FcitxKey_Alt_L || sym == FcitxKey_Alt_R
572      || sym == FcitxKey_Super_L || sym == FcitxKey_Super_R
573      || sym == FcitxKey_Hyper_L || sym == FcitxKey_Hyper_R
574      || sym == FcitxKey_Shift_L || sym == FcitxKey_Shift_R)
575         return true;
576     return false;
577 }
578 
579 /*
580  * Do some custom process
581  */
582 FCITX_EXPORT_API
FcitxHotkeyGetKey(FcitxKeySym keysym,unsigned int iKeyState,FcitxKeySym * outk,unsigned int * outs)583 void FcitxHotkeyGetKey(FcitxKeySym keysym, unsigned int iKeyState, FcitxKeySym* outk, unsigned int* outs)
584 {
585     /* key state != 0 */
586     if (iKeyState) {
587         if (iKeyState != FcitxKeyState_Shift && FcitxHotkeyIsHotKeyLAZ(keysym, 0))
588             keysym = keysym + FcitxKey_A - FcitxKey_a;
589         /*
590          * alt shift 1 shoud be alt + !
591          * shift+s should be S
592          */
593 
594         if (FcitxHotkeyIsHotKeyLAZ(keysym, 0) || FcitxHotkeyIsHotKeyUAZ(keysym, 0)) {
595             if (iKeyState == FcitxKeyState_Shift)
596                 iKeyState &= ~FcitxKeyState_Shift;
597         }
598         else {
599             if ((iKeyState & FcitxKeyState_Shift)
600                 && (((FcitxHotkeyIsHotKeySimple(keysym, 0) || FcitxKeySymToUnicode(keysym) != 0)
601                     && keysym != FcitxKey_space && keysym != FcitxKey_Return)
602                     || (keysym >= FcitxKey_KP_0 && keysym <= FcitxKey_KP_9)))
603                 iKeyState &= ~FcitxKeyState_Shift;
604         }
605     }
606 
607     if (keysym == FcitxKey_ISO_Left_Tab)
608         keysym = FcitxKey_Tab;
609 
610     *outk = keysym;
611 
612     *outs = iKeyState;
613 }
614 
615 FCITX_EXPORT_API
FcitxHotkeyGetReadableKeyString(FcitxKeySym sym,unsigned int state)616 char* FcitxHotkeyGetReadableKeyString(FcitxKeySym sym, unsigned int state)
617 {
618     char *str;
619     size_t len = 0;
620 
621     if ((state & FcitxKeyState_Ctrl) &&
622         sym != FcitxKey_Control_R &&
623         sym != FcitxKey_Control_L)
624         len += strlen("Ctrl+");
625 
626     if ((state & FcitxKeyState_Alt) &&
627         sym != FcitxKey_Alt_R &&
628         sym != FcitxKey_Alt_L)
629         len += strlen("Alt+");
630 
631     if ((state & FcitxKeyState_Shift) &&
632         sym != FcitxKey_Shift_R &&
633         sym != FcitxKey_Shift_L)
634         len += strlen("Shift+");
635 
636     if ((state & FcitxKeyState_Super) &&
637         sym != FcitxKey_Super_L &&
638         sym != FcitxKey_Super_R)
639         len += strlen("Super+");
640 
641     if (sym == FcitxKey_ISO_Left_Tab)
642         sym = FcitxKey_Tab;
643 
644     char *key = FcitxHotkeyGetKeyListString(sym);
645 
646     if (!key)
647         return NULL;
648 
649     size_t keylen = strlen(key);
650 
651     str = fcitx_utils_malloc0(sizeof(char) * (len + keylen + 1));
652 
653     if ((state & FcitxKeyState_Ctrl) &&
654         sym != FcitxKey_Control_R &&
655         sym != FcitxKey_Control_L)
656         strcat(str, "Ctrl+");
657 
658     if ((state & FcitxKeyState_Alt) &&
659         sym != FcitxKey_Alt_R &&
660         sym != FcitxKey_Alt_L)
661         strcat(str, "Alt+");
662 
663     if ((state & FcitxKeyState_Shift) &&
664         sym != FcitxKey_Shift_R &&
665         sym != FcitxKey_Shift_L)
666         strcat(str, "Shift+");
667 
668     if ((state & FcitxKeyState_Super) &&
669         sym != FcitxKey_Super_L &&
670         sym != FcitxKey_Super_R)
671         strcat(str, "Super+");
672 
673     int i = 0;
674     for (i = 0; i < keylen; i ++) {
675         if (i == 0) {
676             continue;
677         }
678         key[i] = tolower(key[i]);
679     }
680     strcpy(str + len, key);
681 
682     free(key);
683 
684     return str;
685 }
686 
687 FCITX_EXPORT_API
FcitxHotkeyGetKeyString(FcitxKeySym sym,unsigned int state)688 char* FcitxHotkeyGetKeyString(FcitxKeySym sym, unsigned int state)
689 {
690     char *str;
691     size_t len = 0;
692 
693     if (state & FcitxKeyState_Ctrl)
694         len += strlen("CTRL_");
695 
696     if (state & FcitxKeyState_Alt)
697         len += strlen("ALT_");
698 
699     if (state & FcitxKeyState_Shift)
700         len += strlen("SHIFT_");
701 
702     if (state & FcitxKeyState_Super)
703         len += strlen("SUPER_");
704 
705     if (sym == FcitxKey_ISO_Left_Tab)
706         sym = FcitxKey_Tab;
707 
708     char *key = FcitxHotkeyGetKeyListString(sym);
709 
710     if (!key)
711         return NULL;
712 
713     len += strlen(key);
714 
715     str = fcitx_utils_malloc0(sizeof(char) * (len + 1));
716 
717     if (state & FcitxKeyState_Ctrl)
718         strcat(str, "CTRL_");
719 
720     if (state & FcitxKeyState_Alt)
721         strcat(str, "ALT_");
722 
723     if (state & FcitxKeyState_Shift)
724         strcat(str, "SHIFT_");
725 
726     if (state & FcitxKeyState_Super)
727         strcat(str, "SUPER_");
728 
729 
730     strcat(str, key);
731 
732     free(key);
733 
734     return str;
735 }
736 
737 FCITX_EXPORT_API
FcitxHotkeyParseKey(const char * strKey,FcitxKeySym * sym,unsigned int * state)738 boolean FcitxHotkeyParseKey(const char *strKey, FcitxKeySym* sym, unsigned int* state)
739 {
740     const char      *p;
741     int             iKey;
742     int             iKeyState = 0;
743 
744     p = strKey;
745 
746     if (strstr(p, "CTRL_")) {
747         iKeyState |= FcitxKeyState_Ctrl;
748         p += strlen("CTRL_");
749     }
750 
751     if (strstr(p, "ALT_")) {
752         iKeyState |= FcitxKeyState_Alt;
753         p += strlen("ALT_");
754     }
755 
756     if (strstr(strKey, "SHIFT_")) {
757         iKeyState |= FcitxKeyState_Shift;
758         p += strlen("SHIFT_");
759     }
760 
761     if (strstr(strKey, "SUPER_")) {
762         iKeyState |= FcitxKeyState_Super;
763         p += strlen("SUPER_");
764     }
765 
766     iKey = FcitxHotkeyGetKeyList(p);
767 
768     if (iKey == -1)
769         return false;
770 
771     *sym = iKey;
772 
773     *state = iKeyState;
774 
775     return true;
776 }
777 
778 FCITX_EXPORT_API
FcitxHotkeyGetKeyList(const char * strKey)779 int FcitxHotkeyGetKeyList(const char *strKey)
780 {
781     int             i;
782 
783     i = 0;
784 
785     for (;;) {
786         if (!keyList[i].code)
787             break;
788 
789         if (!strcmp(strKey, keyList[i].strKey))
790             return keyList[i].code;
791 
792         i++;
793     }
794 
795     if (strlen(strKey) == 1)
796         return strKey[0];
797 
798     return -1;
799 }
800 
FcitxHotkeyGetKeyListString(int key)801 char *FcitxHotkeyGetKeyListString(int key)
802 {
803     if (key > FcitxKey_space && key <= FcitxKey_asciitilde) {
804         char *p;
805         p = malloc(sizeof(char) * 2);
806         p[0] = key;
807         p[1] = '\0';
808         return p;
809     }
810 
811     int             i;
812 
813     i = 0;
814 
815     for (;;) {
816         if (!keyList[i].code)
817             break;
818 
819         if (keyList[i].code == key)
820             return strdup(keyList[i].strKey);
821 
822         i++;
823     }
824 
825     return NULL;
826 
827 }
828 
829 FCITX_EXPORT_API
FcitxHotkeySetKey(const char * str,FcitxHotkey * hotkey)830 void FcitxHotkeySetKey(const char *str, FcitxHotkey * hotkey)
831 {
832     char           *p;
833     char           *strKey;
834     int             i = 0, j = 0, k;
835 
836     char* strKeys = fcitx_utils_trim(str);
837     p = strKeys;
838 
839     for (k = 0; k < 2; k++) {
840         FcitxKeySym sym;
841         unsigned int state;
842         i = 0;
843 
844         while (p[i] != ' ' && p[i] != '\0')
845             i++;
846 
847         strKey = strndup(p, i);
848 
849         strKey[i] = '\0';
850 
851         if (FcitxHotkeyParseKey(strKey, &sym, &state)) {
852             hotkey[j].sym = sym;
853             hotkey[j].state = state;
854             hotkey[j].desc = fcitx_utils_trim(strKey);
855             j ++;
856         }
857 
858         free(strKey);
859 
860         if (p[i] == '\0')
861             break;
862 
863         p = &p[i + 1];
864     }
865 
866     for (; j < 2; j++) {
867         hotkey[j].sym = 0;
868         hotkey[j].state = 0;
869         hotkey[j].desc = NULL;
870     }
871 
872     free(strKeys);
873 }
874 
875 FCITX_EXPORT_API
FcitxHotkeyPadToMain(FcitxKeySym sym)876 FcitxKeySym FcitxHotkeyPadToMain(FcitxKeySym sym)
877 {
878 #define PAD_TO_MAIN(keypad, keymain) case keypad: return keymain
879     switch (sym) {
880         PAD_TO_MAIN(FcitxKey_KP_Space, FcitxKey_space);
881         PAD_TO_MAIN(FcitxKey_KP_Tab, FcitxKey_Tab);
882         PAD_TO_MAIN(FcitxKey_KP_Enter, FcitxKey_Return);
883         PAD_TO_MAIN(FcitxKey_KP_F1, FcitxKey_F1);
884         PAD_TO_MAIN(FcitxKey_KP_F2, FcitxKey_F2);
885         PAD_TO_MAIN(FcitxKey_KP_F3, FcitxKey_F3);
886         PAD_TO_MAIN(FcitxKey_KP_F4, FcitxKey_F4);
887         PAD_TO_MAIN(FcitxKey_KP_Home, FcitxKey_Home);
888         PAD_TO_MAIN(FcitxKey_KP_Left, FcitxKey_Left);
889         PAD_TO_MAIN(FcitxKey_KP_Up, FcitxKey_Up);
890         PAD_TO_MAIN(FcitxKey_KP_Right, FcitxKey_Right);
891         PAD_TO_MAIN(FcitxKey_KP_Down, FcitxKey_Down);
892         PAD_TO_MAIN(FcitxKey_KP_Page_Up, FcitxKey_Page_Up);
893         PAD_TO_MAIN(FcitxKey_KP_Page_Down, FcitxKey_Page_Down);
894         PAD_TO_MAIN(FcitxKey_KP_End, FcitxKey_End);
895         PAD_TO_MAIN(FcitxKey_KP_Begin, FcitxKey_Begin);
896         PAD_TO_MAIN(FcitxKey_KP_Insert, FcitxKey_Insert);
897         PAD_TO_MAIN(FcitxKey_KP_Delete, FcitxKey_Delete);
898         PAD_TO_MAIN(FcitxKey_KP_Multiply, FcitxKey_asterisk);
899         PAD_TO_MAIN(FcitxKey_KP_Add, FcitxKey_plus);
900         PAD_TO_MAIN(FcitxKey_KP_Separator, FcitxKey_comma);
901         PAD_TO_MAIN(FcitxKey_KP_Subtract, FcitxKey_minus);
902         PAD_TO_MAIN(FcitxKey_KP_Decimal, FcitxKey_period);
903         PAD_TO_MAIN(FcitxKey_KP_Divide, FcitxKey_slash);
904 
905         PAD_TO_MAIN(FcitxKey_KP_0, FcitxKey_0);
906         PAD_TO_MAIN(FcitxKey_KP_1, FcitxKey_1);
907         PAD_TO_MAIN(FcitxKey_KP_2, FcitxKey_2);
908         PAD_TO_MAIN(FcitxKey_KP_3, FcitxKey_3);
909         PAD_TO_MAIN(FcitxKey_KP_4, FcitxKey_4);
910         PAD_TO_MAIN(FcitxKey_KP_5, FcitxKey_5);
911         PAD_TO_MAIN(FcitxKey_KP_6, FcitxKey_6);
912         PAD_TO_MAIN(FcitxKey_KP_7, FcitxKey_7);
913         PAD_TO_MAIN(FcitxKey_KP_8, FcitxKey_8);
914         PAD_TO_MAIN(FcitxKey_KP_9, FcitxKey_9);
915 
916         PAD_TO_MAIN(FcitxKey_KP_Equal, FcitxKey_equal);
917     default:
918         break;
919     }
920 #undef PAD_TO_MAIN
921     return sym;
922 }
923 
924 FCITX_EXPORT_API
FcitxHotkeyModifierToState(FcitxKeySym sym)925 unsigned int FcitxHotkeyModifierToState(FcitxKeySym sym)
926 {
927     switch (sym) {
928         case FcitxKey_Control_L:
929         case FcitxKey_Control_R:
930             return FcitxKeyState_Ctrl;
931         case FcitxKey_Alt_L:
932         case FcitxKey_Alt_R:
933             return FcitxKeyState_Alt;
934         case FcitxKey_Shift_L:
935         case FcitxKey_Shift_R:
936             return FcitxKeyState_Shift;
937         case FcitxKey_Super_L:
938         case FcitxKey_Super_R:
939             return FcitxKeyState_Super;
940         case FcitxKey_Hyper_L:
941         case FcitxKey_Hyper_R:
942             return FcitxKeyState_Hyper;
943         default:
944             return 0;
945     }
946     return 0;
947 }
948 
949 FCITX_EXPORT_API
FcitxHotkeyFree(FcitxHotkey * hotkey)950 void FcitxHotkeyFree(FcitxHotkey* hotkey)
951 {
952     if (hotkey[0].desc)
953         free(hotkey[0].desc);
954     if (hotkey[1].desc)
955         free(hotkey[1].desc);
956     hotkey[0].desc = NULL;
957     hotkey[1].desc = NULL;
958 }
959 
960 // kate: indent-mode cstyle; space-indent on; indent-width 0;
961