]> git.lyx.org Git - lyx.git/blob - src/frontends/qt/GuiKeySymbol.cpp
Move Lexer to support/ directory (and lyx::support namespace)
[lyx.git] / src / frontends / qt / GuiKeySymbol.cpp
1 /**
2  * \file qt/GuiKeySymbol.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger & Jürgen
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "GuiKeySymbol.h"
14 #if defined(Q_OS_MAC)
15 #include "GuiApplication.h"
16 #endif
17 #include "qt_helpers.h"
18
19 #include "support/lassert.h"
20 #include "support/debug.h"
21
22 #include "Encoding.h"
23 #include "Language.h"
24
25 #include <QKeyEvent>
26 #include <QKeySequence>
27 #include <QEvent>
28
29 #include <map>
30 #include <string>
31
32 using namespace std;
33
34
35 namespace lyx {
36
37 /**
38  * Return true if the key event is a modifier.
39  */
40 static bool isModifier(int qkey)
41 {
42         switch (qkey) {
43                 case Qt::Key_Hyper_L:
44                 case Qt::Key_Hyper_R:
45                 case Qt::Key_Super_L:
46                 case Qt::Key_Super_R:
47                 case Qt::Key_Shift:
48                 case Qt::Key_Control:
49                 case Qt::Key_Meta:
50                 case Qt::Key_Alt:
51                 case Qt::Key_AltGr:
52                         return true;
53         }
54         return false;
55 }
56
57
58 /**
59  * Return the numeric Qt Key corresponding to the
60  * given symbol name.
61  */
62 static int string_to_qkey(std::string const & str)
63 {
64         // FIX! (Lgb)
65
66         if (str == "Escape") return Qt::Key_Escape;
67         if (str == "Tab") return Qt::Key_Tab;
68         if (str == "ISO_Left_Tab") return Qt::Key_Backtab;
69         if (str == "BackSpace") return Qt::Key_Backspace;
70         if (str == "Return") return Qt::Key_Return;
71         if (str == "KP_Enter") return Qt::Key_Enter; // correct ?
72         if (str == "Insert") return Qt::Key_Insert;
73         if (str == "KP_Insert") return Qt::Key_Insert;
74         if (str == "Delete") return Qt::Key_Delete;
75         if (str == "KP_Delete") return Qt::Key_Delete;
76         if (str == "Pause") return Qt::Key_Pause;
77         if (str == "Print") return Qt::Key_Print;
78         if (str == "Sys_Req") return Qt::Key_SysReq;
79         if (str == "Home") return Qt::Key_Home;
80         if (str == "End") return Qt::Key_End;
81         if (str == "Left") return Qt::Key_Left;
82         if (str == "Up") return Qt::Key_Up;
83         if (str == "Right") return Qt::Key_Right;
84         if (str == "Down") return Qt::Key_Down;
85         if (str == "Prior") return Qt::Key_PageUp;
86         if (str == "Next") return Qt::Key_PageDown;
87         if (str == "KP_Home") return Qt::Key_Home;
88         if (str == "KP_End") return Qt::Key_End;
89         if (str == "KP_Left") return Qt::Key_Left;
90         if (str == "KP_Up") return Qt::Key_Up;
91         if (str == "KP_Right") return Qt::Key_Right;
92         if (str == "KP_Down") return Qt::Key_Down;
93         if (str == "KP_Prior") return Qt::Key_PageUp;
94         if (str == "KP_Next") return Qt::Key_PageDown;
95         if (str == "Shift_L") return Qt::Key_Shift;
96         if (str == "Control_L") return Qt::Key_Control;
97         if (str == "Alt_L") return Qt::Key_Meta; // correct ?
98         if (str == "Alt_R") return Qt::Key_Alt;
99         if (str == "Caps_Lock") return Qt::Key_CapsLock;
100         if (str == "Num_Lock") return Qt::Key_NumLock;
101         if (str == "Scroll_Lock") return Qt::Key_ScrollLock;
102         if (str == "F1") return Qt::Key_F1;
103         if (str == "F2") return Qt::Key_F2;
104         if (str == "F3") return Qt::Key_F3;
105         if (str == "F4") return Qt::Key_F4;
106         if (str == "F5") return Qt::Key_F5;
107         if (str == "F6") return Qt::Key_F6;
108         if (str == "F7") return Qt::Key_F7;
109         if (str == "F8") return Qt::Key_F8;
110         if (str == "F9") return Qt::Key_F9;
111         if (str == "F10") return Qt::Key_F10;
112         if (str == "F11") return Qt::Key_F11;
113         if (str == "F12") return Qt::Key_F12;
114         if (str == "F13") return Qt::Key_F13;
115         if (str == "F14") return Qt::Key_F14;
116         if (str == "F15") return Qt::Key_F15;
117         if (str == "F16") return Qt::Key_F16;
118         if (str == "F17") return Qt::Key_F17;
119         if (str == "F18") return Qt::Key_F18;
120         if (str == "F19") return Qt::Key_F19;
121         if (str == "F20") return Qt::Key_F20;
122         if (str == "F21") return Qt::Key_F21;
123         if (str == "F22") return Qt::Key_F22;
124         if (str == "F23") return Qt::Key_F23;
125         if (str == "F24") return Qt::Key_F24;
126         if (str == "F25") return Qt::Key_F25;
127         if (str == "F26") return Qt::Key_F26;
128         if (str == "F27") return Qt::Key_F27;
129         if (str == "F28") return Qt::Key_F28;
130         if (str == "F29") return Qt::Key_F29;
131         if (str == "F30") return Qt::Key_F30;
132         if (str == "F31") return Qt::Key_F31;
133         if (str == "F32") return Qt::Key_F32;
134         if (str == "F33") return Qt::Key_F33;
135         if (str == "F34") return Qt::Key_F34;
136         if (str == "F35") return Qt::Key_F35;
137         if (str == "0") return Qt::Key_0;
138         if (str == "1") return Qt::Key_1;
139         if (str == "2") return Qt::Key_2;
140         if (str == "3") return Qt::Key_3;
141         if (str == "4") return Qt::Key_4;
142         if (str == "5") return Qt::Key_5;
143         if (str == "6") return Qt::Key_6;
144         if (str == "7") return Qt::Key_7;
145         if (str == "8") return Qt::Key_8;
146         if (str == "9") return Qt::Key_9;
147         if (str == "KP_0") return Qt::Key_0;
148         if (str == "KP_1") return Qt::Key_1;
149         if (str == "KP_2") return Qt::Key_2;
150         if (str == "KP_3") return Qt::Key_3;
151         if (str == "KP_4") return Qt::Key_4;
152         if (str == "KP_5") return Qt::Key_5;
153         if (str == "KP_6") return Qt::Key_6;
154         if (str == "KP_7") return Qt::Key_7;
155         if (str == "KP_8") return Qt::Key_8;
156         if (str == "KP_9") return Qt::Key_9;
157         if (str == "colon") return Qt::Key_Colon;
158         if (str == "semicolon") return Qt::Key_Semicolon;
159         if (str == "less") return Qt::Key_Less;
160         if (str == "equal") return Qt::Key_Equal;
161         if (str == "greater") return Qt::Key_Greater;
162         if (str == "question") return Qt::Key_Question;
163         if (str == "at") return Qt::Key_At;
164         if (str == "A") return Qt::Key_A;
165         if (str == "B") return Qt::Key_B;
166         if (str == "C") return Qt::Key_C;
167         if (str == "D") return Qt::Key_D;
168         if (str == "E") return Qt::Key_E;
169         if (str == "F") return Qt::Key_F;
170         if (str == "G") return Qt::Key_G;
171         if (str == "H") return Qt::Key_H;
172         if (str == "I") return Qt::Key_I;
173         if (str == "J") return Qt::Key_J;
174         if (str == "K") return Qt::Key_K;
175         if (str == "L") return Qt::Key_L;
176         if (str == "M") return Qt::Key_M;
177         if (str == "N") return Qt::Key_N;
178         if (str == "O") return Qt::Key_O;
179         if (str == "P") return Qt::Key_P;
180         if (str == "Q") return Qt::Key_Q;
181         if (str == "R") return Qt::Key_R;
182         if (str == "S") return Qt::Key_S;
183         if (str == "T") return Qt::Key_T;
184         if (str == "U") return Qt::Key_U;
185         if (str == "V") return Qt::Key_V;
186         if (str == "W") return Qt::Key_W;
187         if (str == "X") return Qt::Key_X;
188         if (str == "Y") return Qt::Key_Y;
189         if (str == "Z") return Qt::Key_Z;
190         if (str == "a") return Qt::Key_A;
191         if (str == "b") return Qt::Key_B;
192         if (str == "c") return Qt::Key_C;
193         if (str == "d") return Qt::Key_D;
194         if (str == "e") return Qt::Key_E;
195         if (str == "f") return Qt::Key_F;
196         if (str == "g") return Qt::Key_G;
197         if (str == "h") return Qt::Key_H;
198         if (str == "i") return Qt::Key_I;
199         if (str == "j") return Qt::Key_J;
200         if (str == "k") return Qt::Key_K;
201         if (str == "l") return Qt::Key_L;
202         if (str == "m") return Qt::Key_M;
203         if (str == "n") return Qt::Key_N;
204         if (str == "o") return Qt::Key_O;
205         if (str == "p") return Qt::Key_P;
206         if (str == "q") return Qt::Key_Q;
207         if (str == "r") return Qt::Key_R;
208         if (str == "s") return Qt::Key_S;
209         if (str == "t") return Qt::Key_T;
210         if (str == "u") return Qt::Key_U;
211         if (str == "v") return Qt::Key_V;
212         if (str == "w") return Qt::Key_W;
213         if (str == "x") return Qt::Key_X;
214         if (str == "y") return Qt::Key_Y;
215         if (str == "z") return Qt::Key_Z;
216         if (str == "bracketleft") return Qt::Key_BracketLeft;
217         if (str == "backslash") return Qt::Key_Backslash;
218         if (str == "bracketright") return Qt::Key_BracketRight;
219         if (str == "bar") return Qt::Key_Bar;
220         if (str == "underscore") return Qt::Key_Underscore;
221         if (str == "space") return Qt::Key_Space;
222         if (str == "parenleft") return Qt::Key_ParenLeft;
223         if (str == "parenright") return Qt::Key_ParenRight;
224         if (str == "quotedbl") return Qt::Key_QuoteDbl;
225         if (str == "quoteright") return Qt::Key_Apostrophe;
226         if (str == "quoteleft") return Qt::Key_QuoteLeft;
227         if (str == "exclam") return Qt::Key_Exclam;
228         if (str == "numbersign") return Qt::Key_NumberSign;
229         if (str == "asciicircum") return Qt::Key_AsciiCircum;
230         if (str == "dollar") return Qt::Key_Dollar;
231         if (str == "percent") return Qt::Key_Percent;
232         if (str == "ampersand") return Qt::Key_Ampersand;
233         if (str == "asterisk") return Qt::Key_Asterisk;
234         if (str == "KP_Multiply") return Qt::Key_Asterisk;
235         if (str == "apostrophe") return Qt::Key_Apostrophe;
236         if (str == "plus") return Qt::Key_Plus;
237         if (str == "KP_Add") return Qt::Key_Plus;
238         if (str == "minus") return Qt::Key_Minus;
239         if (str == "KP_Subtract") return Qt::Key_Minus;
240         if (str == "comma") return Qt::Key_Comma;
241         if (str == "period") return Qt::Key_Period;
242         if (str == "KP_Decimal") return Qt::Key_Period;
243         if (str == "slash") return Qt::Key_Slash;
244         if (str == "KP_Divide") return Qt::Key_Slash;
245         if (str == "asciitilde") return Qt::Key_AsciiTilde;
246         if (str == "braceleft") return Qt::Key_BraceLeft;
247         if (str == "braceright") return Qt::Key_BraceRight;
248         if (str == "grave") return Qt::Key_QuoteLeft; // ???
249         if (str == "notsign") return Qt::Key_notsign;
250         if (str == "nobreakspace") return Qt::Key_nobreakspace;
251         if (str == "exclamdown") return Qt::Key_exclamdown;
252         if (str == "cent") return Qt::Key_cent;
253         if (str == "sterling") return Qt::Key_sterling;
254         if (str == "currency") return Qt::Key_currency;
255         if (str == "yen") return Qt::Key_yen;
256         if (str == "brokenbar") return Qt::Key_brokenbar;
257         if (str == "section") return Qt::Key_section;
258         if (str == "diaeresis") return Qt::Key_diaeresis;
259         if (str == "copyright") return Qt::Key_copyright;
260         if (str == "ordfeminine") return Qt::Key_ordfeminine;
261         if (str == "guillemotleft") return Qt::Key_guillemotleft;
262         if (str == "hyphen") return Qt::Key_hyphen;
263         if (str == "registered") return Qt::Key_registered;
264         if (str == "macron") return Qt::Key_macron;
265         if (str == "degree") return Qt::Key_degree;
266         if (str == "plusminus") return Qt::Key_plusminus;
267         if (str == "twosuperior") return Qt::Key_twosuperior;
268         if (str == "threesuperior") return Qt::Key_threesuperior;
269         if (str == "acute") return Qt::Key_acute;
270         if (str == "mu") return Qt::Key_mu;
271         if (str == "paragraph") return Qt::Key_paragraph;
272         if (str == "periodcentered") return Qt::Key_periodcentered;
273         if (str == "cedilla") return Qt::Key_cedilla;
274         if (str == "onesuperior") return Qt::Key_onesuperior;
275         if (str == "masculine") return Qt::Key_masculine;
276         if (str == "guillemotright") return Qt::Key_guillemotright;
277         if (str == "onequarter") return Qt::Key_onequarter;
278         if (str == "onehalf") return Qt::Key_onehalf;
279         if (str == "threequarters") return Qt::Key_threequarters;
280         if (str == "questiondown") return Qt::Key_questiondown;
281         if (str == "Agrave") return Qt::Key_Agrave;
282         if (str == "Aacute") return Qt::Key_Aacute;
283         if (str == "Acircumflex") return Qt::Key_Acircumflex;
284         if (str == "Atilde") return Qt::Key_Atilde;
285         if (str == "Adiaeresis") return Qt::Key_Adiaeresis;
286         if (str == "Aring") return Qt::Key_Aring;
287         if (str == "AE") return Qt::Key_AE;
288         if (str == "Ccedilla") return Qt::Key_Ccedilla;
289         if (str == "Egrave") return Qt::Key_Egrave;
290         if (str == "Eacute") return Qt::Key_Eacute;
291         if (str == "Ecircumflex") return Qt::Key_Ecircumflex;
292         if (str == "Ediaeresis") return Qt::Key_Ediaeresis;
293         if (str == "Igrave") return Qt::Key_Igrave;
294         if (str == "Iacute") return Qt::Key_Iacute;
295         if (str == "Icircumflex") return Qt::Key_Icircumflex;
296         if (str == "Idiaeresis") return Qt::Key_Idiaeresis;
297         if (str == "ETH") return Qt::Key_ETH;
298         if (str == "Ntilde") return Qt::Key_Ntilde;
299         if (str == "Ograve") return Qt::Key_Ograve;
300         if (str == "Oacute") return Qt::Key_Oacute;
301         if (str == "Ocircumflex") return Qt::Key_Ocircumflex;
302         if (str == "Otilde") return Qt::Key_Otilde;
303         if (str == "Odiaeresis") return Qt::Key_Odiaeresis;
304         if (str == "multiply") return Qt::Key_multiply;
305         if (str == "Ooblique") return Qt::Key_Ooblique;
306         if (str == "Ugrave") return Qt::Key_Ugrave;
307         if (str == "Uacute") return Qt::Key_Uacute;
308         if (str == "Ucircumflex") return Qt::Key_Ucircumflex;
309         if (str == "Udiaeresis") return Qt::Key_Udiaeresis;
310         if (str == "Yacute") return Qt::Key_Yacute;
311         if (str == "THORN") return Qt::Key_THORN;
312         if (str == "ssharp") return Qt::Key_ssharp;
313         if (str == "agrave") return Qt::Key_Agrave;
314         if (str == "aacute") return Qt::Key_Aacute;
315         if (str == "acircumflex") return Qt::Key_Acircumflex;
316         if (str == "atilde") return Qt::Key_Atilde;
317         if (str == "adiaeresis") return Qt::Key_Adiaeresis;
318         if (str == "aring") return Qt::Key_Aring;
319         if (str == "ae") return Qt::Key_AE;
320         if (str == "ccedilla") return Qt::Key_Ccedilla;
321         if (str == "egrave") return Qt::Key_Egrave;
322         if (str == "eacute") return Qt::Key_Eacute;
323         if (str == "ecircumflex") return Qt::Key_Ecircumflex;
324         if (str == "ediaeresis") return Qt::Key_Ediaeresis;
325         if (str == "igrave") return Qt::Key_Igrave;
326         if (str == "iacute") return Qt::Key_Iacute;
327         if (str == "icircumflex") return Qt::Key_Icircumflex;
328         if (str == "idiaeresis") return Qt::Key_Idiaeresis;
329         if (str == "eth") return Qt::Key_ETH;
330         if (str == "ntilde") return Qt::Key_Ntilde;
331         if (str == "ograve") return Qt::Key_Ograve;
332         if (str == "oacute") return Qt::Key_Oacute;
333         if (str == "ocircumflex") return Qt::Key_Ocircumflex;
334         if (str == "otilde") return Qt::Key_Otilde;
335         if (str == "odiaeresis") return Qt::Key_Odiaeresis;
336         if (str == "division") return Qt::Key_division;
337         if (str == "oslash") return Qt::Key_Ooblique;
338         if (str == "ugrave") return Qt::Key_Ugrave;
339         if (str == "uacute") return Qt::Key_Uacute;
340         if (str == "ucircumflex") return Qt::Key_Ucircumflex;
341         if (str == "udiaeresis") return Qt::Key_Udiaeresis;
342         if (str == "yacute") return Qt::Key_Yacute;
343         if (str == "thorn") return Qt::Key_THORN;
344         if (str == "ydiaeresis") return Qt::Key_ydiaeresis;
345         if (str == "Dead_Caron") return Qt::Key_Dead_Caron;
346
347         // FIXME, correct for all these ?
348         if (str == "Super_L") return Qt::Key_Super_L;
349         if (str == "Super_R") return Qt::Key_Super_R;
350         if (str == "Menu") return Qt::Key_Menu;
351         if (str == "Hyper_L") return Qt::Key_Hyper_L;
352         if (str == "Hyper_R") return Qt::Key_Hyper_R;
353         if (str == "Help") return Qt::Key_Help;
354         if (str == "BackTab") return Qt::Key_Backtab;
355
356         // Keyboard codes for Cyrillic letters
357         if (str == "А") return 1040;
358         if (str == "Б") return 1041;
359         if (str == "В") return 1042;
360         if (str == "Г") return 1043;
361         if (str == "Д") return 1044;
362         if (str == "Е") return 1045;
363         if (str == "Є") return 1028;
364         if (str == "Ё") return 1025;
365         if (str == "Ж") return 1046;
366         if (str == "З") return 1047;
367         if (str == "И") return 1048;
368         if (str == "І") return 1030;
369         if (str == "Ї") return 1031;
370         if (str == "Й") return 1049;
371         if (str == "К") return 1050;
372         if (str == "Л") return 1051;
373         if (str == "М") return 1052;
374         if (str == "Н") return 1053;
375         if (str == "О") return 1054;
376         if (str == "П") return 1055;
377         if (str == "Р") return 1056;
378         if (str == "С") return 1057;
379         if (str == "Т") return 1058;
380         if (str == "У") return 1059;
381         if (str == "Ф") return 1060;
382         if (str == "Х") return 1061;
383         if (str == "Ц") return 1062;
384         if (str == "Ч") return 1063;
385         if (str == "Ш") return 1064;
386         if (str == "Щ") return 1065;
387         if (str == "Ъ") return 1066;
388         if (str == "Ы") return 1067;
389         if (str == "Ь") return 1068;
390         if (str == "Э") return 1069;
391         if (str == "Ю") return 1070;
392         if (str == "Я") return 1071;
393         if (str == "а") return 1040;
394         if (str == "б") return 1041;
395         if (str == "в") return 1042;
396         if (str == "г") return 1043;
397         if (str == "д") return 1044;
398         if (str == "е") return 1045;
399         if (str == "є") return 1028;
400         if (str == "ё") return 1025;
401         if (str == "ж") return 1046;
402         if (str == "з") return 1047;
403         if (str == "и") return 1048;
404         if (str == "і") return 1030;
405         if (str == "ї") return 1031;
406         if (str == "й") return 1049;
407         if (str == "к") return 1050;
408         if (str == "л") return 1051;
409         if (str == "м") return 1052;
410         if (str == "н") return 1053;
411         if (str == "о") return 1054;
412         if (str == "п") return 1055;
413         if (str == "р") return 1056;
414         if (str == "с") return 1057;
415         if (str == "т") return 1058;
416         if (str == "у") return 1059;
417         if (str == "ф") return 1060;
418         if (str == "х") return 1061;
419         if (str == "ц") return 1062;
420         if (str == "ч") return 1063;
421         if (str == "ш") return 1064;
422         if (str == "щ") return 1065;
423         if (str == "ъ") return 1066;
424         if (str == "ы") return 1067;
425         if (str == "ь") return 1068;
426         if (str == "э") return 1069;
427         if (str == "ю") return 1070;
428         if (str == "я") return 1071;
429
430         return Qt::Key_unknown;
431 }
432
433
434 /**
435  * qkey_to_string - convert Qt keypress into LyX
436  *
437  * Convert the Qt keypress into a string understandable
438  * by the LyX core (same as XKeysymToString).
439  */
440 static std::string const qkey_to_string(int lkey)
441 {
442         switch (lkey) {
443         case Qt::Key_0: return "0";
444         case Qt::Key_1: return "1";
445         case Qt::Key_2: return "2";
446         case Qt::Key_3: return "3";
447         case Qt::Key_4: return "4";
448         case Qt::Key_5: return "5";
449         case Qt::Key_6: return "6";
450         case Qt::Key_7: return "7";
451         case Qt::Key_8: return "8";
452         case Qt::Key_9: return "9";
453
454         case Qt::Key_A: return "a";
455         case Qt::Key_B: return "b";
456         case Qt::Key_C: return "c";
457         case Qt::Key_D: return "d";
458         case Qt::Key_E: return "e";
459         case Qt::Key_F: return "f";
460         case Qt::Key_G: return "g";
461         case Qt::Key_H: return "h";
462         case Qt::Key_I: return "i";
463         case Qt::Key_J: return "j";
464         case Qt::Key_K: return "k";
465         case Qt::Key_L: return "l";
466         case Qt::Key_M: return "m";
467         case Qt::Key_N: return "n";
468         case Qt::Key_O: return "o";
469         case Qt::Key_P: return "p";
470         case Qt::Key_Q: return "q";
471         case Qt::Key_R: return "r";
472         case Qt::Key_S: return "s";
473         case Qt::Key_T: return "t";
474         case Qt::Key_U: return "u";
475         case Qt::Key_V: return "v";
476         case Qt::Key_W: return "w";
477         case Qt::Key_X: return "x";
478         case Qt::Key_Y: return "y";
479         case Qt::Key_Z: return "z";
480
481         case Qt::Key_Return: return "Return";
482         case Qt::Key_Escape: return "Escape";
483         case Qt::Key_Tab: return "Tab";
484         case Qt::Key_Backspace: return "BackSpace";
485         case Qt::Key_Insert: return "Insert";
486         case Qt::Key_Delete: return "Delete";
487         case Qt::Key_Pause: return "Pause";
488         case Qt::Key_Print: return "Print";
489         case Qt::Key_SysReq: return "Sys_Req";
490         case Qt::Key_Home: return "Home";
491         case Qt::Key_End: return "End";
492         case Qt::Key_Left: return "Left";
493         case Qt::Key_Up: return "Up";
494         case Qt::Key_Right: return "Right";
495         case Qt::Key_Down: return "Down";
496         case Qt::Key_PageUp: return "Prior";
497         case Qt::Key_PageDown: return "Next";
498         case Qt::Key_Shift: return "Shift_L";
499         case Qt::Key_Control: return "Control_L";
500         case Qt::Key_Meta: return "Alt_L"; // correct ?
501         case Qt::Key_Alt: return "Alt_R";
502         case Qt::Key_CapsLock: return "Caps_Lock";
503         case Qt::Key_NumLock: return "Num_Lock";
504         case Qt::Key_ScrollLock: return "Scroll_Lock";
505         case Qt::Key_F1: return "F1";
506         case Qt::Key_F2: return "F2";
507         case Qt::Key_F3: return "F3";
508         case Qt::Key_F4: return "F4";
509         case Qt::Key_F5: return "F5";
510         case Qt::Key_F6: return "F6";
511         case Qt::Key_F7: return "F7";
512         case Qt::Key_F8: return "F8";
513         case Qt::Key_F9: return "F9";
514         case Qt::Key_F10: return "F10";
515         case Qt::Key_F11: return "F11";
516         case Qt::Key_F12: return "F12";
517         case Qt::Key_F13: return "F13";
518         case Qt::Key_F14: return "F14";
519         case Qt::Key_F15: return "F15";
520         case Qt::Key_F16: return "F16";
521         case Qt::Key_F17: return "F17";
522         case Qt::Key_F18: return "F18";
523         case Qt::Key_F19: return "F19";
524         case Qt::Key_F20: return "F20";
525         case Qt::Key_F21: return "F21";
526         case Qt::Key_F22: return "F22";
527         case Qt::Key_F23: return "F23";
528         case Qt::Key_F24: return "F24";
529         case Qt::Key_F25: return "F25";
530         case Qt::Key_F26: return "F26";
531         case Qt::Key_F27: return "F27";
532         case Qt::Key_F28: return "F28";
533         case Qt::Key_F29: return "F29";
534         case Qt::Key_F30: return "F30";
535         case Qt::Key_F31: return "F31";
536         case Qt::Key_F32: return "F32";
537         case Qt::Key_F33: return "F33";
538         case Qt::Key_F34: return "F34";
539         case Qt::Key_F35: return "F35";
540         case Qt::Key_Colon: return "colon";
541         case Qt::Key_Semicolon: return "semicolon";
542         case Qt::Key_Less: return "less";
543         case Qt::Key_Equal: return "equal";
544         case Qt::Key_Greater: return "greater";
545         case Qt::Key_Question: return "question";
546         case Qt::Key_At: return "at";
547         case Qt::Key_BracketLeft: return "bracketleft";
548         case Qt::Key_Backslash: return "backslash";
549         case Qt::Key_BracketRight: return "bracketright";
550         case Qt::Key_Underscore: return "underscore";
551         case Qt::Key_Space: return "space";
552         case Qt::Key_ParenLeft: return "parenleft";
553         case Qt::Key_ParenRight: return "parenright";
554         case Qt::Key_QuoteDbl: return "quotedbl";
555         case Qt::Key_Exclam: return "exclam";
556         case Qt::Key_NumberSign: return "numbersign";
557         case Qt::Key_AsciiCircum: return "asciicircum";
558         case Qt::Key_Dollar: return "dollar";
559         case Qt::Key_Percent: return "percent";
560         case Qt::Key_Ampersand: return "ampersand";
561         case Qt::Key_Asterisk: return "asterisk";
562         case Qt::Key_Apostrophe: return "apostrophe";
563         case Qt::Key_Plus: return "plus";
564         case Qt::Key_Minus: return "minus";
565         case Qt::Key_Comma: return "comma";
566         case Qt::Key_Period: return "period";
567         case Qt::Key_Slash: return "slash";
568         case Qt::Key_AsciiTilde: return "asciitilde";
569         case Qt::Key_BraceLeft: return "braceleft";
570         case Qt::Key_BraceRight: return "braceright";
571         case Qt::Key_QuoteLeft: return "grave"; // ???
572         case Qt::Key_notsign: return "notsign";
573         case Qt::Key_nobreakspace: return "nobreakspace";
574         case Qt::Key_exclamdown: return "exclamdown";
575         case Qt::Key_cent: return "cent";
576         case Qt::Key_sterling: return "sterling";
577         case Qt::Key_currency: return "currency";
578         case Qt::Key_yen: return "yen";
579         case Qt::Key_brokenbar: return "brokenbar";
580         case Qt::Key_section: return "section";
581         case Qt::Key_diaeresis: return "diaeresis";
582         case Qt::Key_copyright: return "copyright";
583         case Qt::Key_ordfeminine: return "ordfeminine";
584         case Qt::Key_guillemotleft: return "guillemotleft";
585         case Qt::Key_hyphen: return "hyphen";
586         case Qt::Key_registered: return "registered";
587         case Qt::Key_macron: return "macron";
588         case Qt::Key_degree: return "degree";
589         case Qt::Key_plusminus: return "plusminus";
590         case Qt::Key_twosuperior: return "twosuperior";
591         case Qt::Key_threesuperior: return "threesuperior";
592         case Qt::Key_acute: return "acute";
593         case Qt::Key_mu: return "mu";
594         case Qt::Key_paragraph: return "paragraph";
595         case Qt::Key_periodcentered: return "periodcentered";
596         case Qt::Key_cedilla: return "cedilla";
597         case Qt::Key_onesuperior: return "onesuperior";
598         case Qt::Key_masculine: return "masculine";
599         case Qt::Key_guillemotright: return "guillemotright";
600         case Qt::Key_onequarter: return "onequarter";
601         case Qt::Key_onehalf: return "onehalf";
602         case Qt::Key_threequarters: return "threequarters";
603         case Qt::Key_questiondown: return "questiondown";
604         case Qt::Key_Agrave: return "Agrave";
605         case Qt::Key_Aacute: return "Aacute";
606         case Qt::Key_Acircumflex: return "Acircumflex";
607         case Qt::Key_Atilde: return "Atilde";
608         case Qt::Key_Adiaeresis: return "Adiaeresis";
609         case Qt::Key_Aring: return "Aring";
610         case Qt::Key_AE: return "AE";
611         case Qt::Key_Ccedilla: return "Ccedilla";
612         case Qt::Key_Egrave: return "Egrave";
613         case Qt::Key_Eacute: return "Eacute";
614         case Qt::Key_Ecircumflex: return "Ecircumflex";
615         case Qt::Key_Ediaeresis: return "Ediaeresis";
616         case Qt::Key_Igrave: return "Igrave";
617         case Qt::Key_Iacute: return "Iacute";
618         case Qt::Key_Icircumflex: return "Icircumflex";
619         case Qt::Key_Idiaeresis: return "Idiaeresis";
620         case Qt::Key_ETH: return "ETH";
621         case Qt::Key_Ntilde: return "Ntilde";
622         case Qt::Key_Ograve: return "Ograve";
623         case Qt::Key_Oacute: return "Oacute";
624         case Qt::Key_Ocircumflex: return "Ocircumflex";
625         case Qt::Key_Otilde: return "Otilde";
626         case Qt::Key_Odiaeresis: return "Odiaeresis";
627         case Qt::Key_multiply: return "multiply";
628         case Qt::Key_Ooblique: return "Ooblique";
629         case Qt::Key_Ugrave: return "Ugrave";
630         case Qt::Key_Uacute: return "Uacute";
631         case Qt::Key_Ucircumflex: return "Ucircumflex";
632         case Qt::Key_Udiaeresis: return "Udiaeresis";
633         case Qt::Key_Yacute: return "Yacute";
634         case Qt::Key_THORN: return "THORN";
635         case Qt::Key_ssharp: return "ssharp";
636         case Qt::Key_ydiaeresis: return "ydiaeresis";
637         case Qt::Key_Bar: return "bar";
638         case Qt::Key_Dead_Caron: return "Dead_Caron";
639
640         // FIXME: these ones I don't know the names of ... help !
641         // what's here is basically guesses ...
642         case Qt::Key_Super_L: return "Super_L";
643         case Qt::Key_Super_R: return "Super_R";
644         case Qt::Key_Menu: return "Menu";
645         case Qt::Key_Hyper_L: return "Hyper_L";
646         case Qt::Key_Hyper_R: return "Hyper_R";
647         case Qt::Key_Help: return "Help";
648         case Qt::Key_Backtab: return "BackTab";
649
650         // Cyrillic
651         case 1040: return "а";
652         case 1041: return "б";
653         case 1042: return "в";
654         case 1043: return "г";
655         case 1044: return "д";
656         case 1045: return "е";
657         case 1028: return "є";
658         case 1025: return "ё";
659         case 1046: return "ж";
660         case 1047: return "з";
661         case 1048: return "и";
662         case 1030: return "і";
663         case 1031: return "ї";
664         case 1049: return "й";
665         case 1050: return "к";
666         case 1051: return "л";
667         case 1052: return "м";
668         case 1053: return "н";
669         case 1054: return "о";
670         case 1055: return "п";
671         case 1056: return "р";
672         case 1057: return "с";
673         case 1058: return "т";
674         case 1059: return "у";
675         case 1060: return "ф";
676         case 1061: return "х";
677         case 1062: return "ц";
678         case 1063: return "ч";
679         case 1064: return "ш";
680         case 1065: return "щ";
681         case 1066: return "ъ";
682         case 1067: return "ы";
683         case 1068: return "ь";
684         case 1069: return "э";
685         case 1070: return "ю";
686         case 1071: return "я";
687
688         default:
689         case Qt::Key_unknown: return "";
690         }
691 }
692
693
694 void setKeySymbol(KeySymbol * sym, QKeyEvent const * ev)
695 {
696         sym->setKey(ev->key());
697         if (ev->text().isNull()) {
698                 LYXERR(Debug::KEY, "keyevent has isNull() text !");
699                 sym->setText(docstring());
700                 return;
701         }
702         LYXERR(Debug::KEY, "Getting key " << ev->key() << ", with text '"
703                 << ev->text() << "'");
704         // This is unsafe because ev->text() is the unicode representation of the
705         // key, not the name of the key. For example, Ctrl-x and Alt-x produce
706         // different texts.
707         sym->setText(qstring_to_ucs4(ev->text()));
708         LYXERR(Debug::KEY, "Setting key to " << sym->key() << ", "
709                 << to_utf8(sym->text()));
710 }
711
712
713 void KeySymbol::init(string const & symbolname)
714 {
715         key_ = string_to_qkey(symbolname);
716         text_ = from_utf8(symbolname);
717         LYXERR(Debug::KEY, "Init key to " << key_ << ", " << to_utf8(text_));
718 }
719
720
721 void KeySymbol::init(int key)
722 {
723         key_ = key;
724         text_ = from_utf8(qkey_to_string(key));
725         LYXERR(Debug::KEY, "Init key to " << key_ << ", " << to_utf8(text_));
726 }
727
728
729 bool KeySymbol::isOK() const
730 {
731         bool const ok = !(text_.empty() && qkey_to_string(key_).empty());
732         LYXERR(Debug::KEY, "isOK is " << ok);
733         return ok;
734 }
735
736
737 bool KeySymbol::isModifier() const
738 {
739         bool const mod = lyx::isModifier(key_);
740         LYXERR(Debug::KEY, "isModifier is " << mod);
741         return mod;
742 }
743
744
745 string KeySymbol::getSymbolName() const
746 {
747         string name = qkey_to_string(key_);
748
749         // others
750         if (name.empty())
751                 name = to_utf8(text_);
752
753         return name;
754 }
755
756
757 char_type KeySymbol::getUCSEncoded() const
758 {
759         if (text_.empty())
760                 return 0;
761
762         // UTF16 has a maximum of two characters.
763         LASSERT(text_.size() <= 2, return 0);
764
765         if (lyxerr.debugging() && text_.size() > 1) {
766                 // We don't know yet how well support the full ucs4 range.
767                 LYXERR(Debug::KEY, "KeySymbol::getUCSEncoded()");
768                 for (int i = 0; i != int(text_.size()); ++i)
769                         LYXERR(Debug::KEY, "char " << i << ": " << int(text_[i]));
770         }
771
772         return text_[0];
773 }
774
775
776 docstring const KeySymbol::print(KeyModifier mod, bool forgui, bool untranslated) const
777 {
778         int tmpkey = key_;
779
780         if (mod & ShiftModifier && !(tmpkey == Qt::Key_Shift))
781                 tmpkey += Qt::ShiftModifier;
782         if (mod & ControlModifier && !(tmpkey == Qt::Key_Control))
783                 tmpkey += Qt::ControlModifier;
784         if (mod & AltModifier && !(tmpkey == Qt::Key_Alt))
785                 tmpkey += Qt::AltModifier;
786         if (mod & MetaModifier && !(tmpkey == Qt::Key_Meta))
787                 tmpkey += Qt::MetaModifier;
788
789         QKeySequence seq(tmpkey);
790         QString str;
791
792         if (forgui)
793                 str = untranslated ? seq.toString(QKeySequence::PortableText)
794                                    : seq.toString(QKeySequence::NativeText);
795         else {
796 #ifdef Q_OS_MAC
797                 // Qt/Mac does not use Command and friends in the
798                 // portable case, but the windows-like Control+x (bug 5421).
799                 str = seq.toString(QKeySequence::NativeText);
800                 str.replace(QChar(0x21E7), qt_("Shift-"));
801                 str.replace(QChar(0x2303), qt_("Control-"));
802                 str.replace(QChar(0x2325), qt_("Option-"));
803                 str.replace(QChar(0x2318), qt_("Command-"));
804 #else
805                 str = seq.toString(QKeySequence::PortableText);
806 #endif
807         }
808
809         return qstring_to_ucs4(str);
810 }
811
812
813 bool KeySymbol::isText() const
814 {
815         if (!text_.empty())
816                 return true;
817         LYXERR(Debug::KEY, "text_ empty, isText() == false");
818         return false;
819 }
820
821
822 bool KeySymbol::operator==(KeySymbol const & ks) const
823 {
824         // we do not have enough info for a fair comparison, so return
825         // false. This works out OK because unknown text from Qt will
826         // get inserted anyway after the isText() check
827         if (key_ == Qt::Key_unknown || ks.key_ == Qt::Key_unknown)
828                 return false;
829         return key_ == ks.key_;
830 }
831
832
833 KeyModifier q_key_state(Qt::KeyboardModifiers state)
834 {
835         KeyModifier k = NoModifier;
836 #if defined(Q_OS_MAC) && (QT_VERSION < QT_VERSION_CHECK(5, 12, 0))
837         /// Additional check for Control and Meta modifier swap state.
838         /// Starting with Qt 5 the modifiers aren't reported correctly.
839         /// Until this is fixed a correction is required.
840         /// AFAIK it is fixed at least with Qt 5.12.0
841         const bool dontSwapCtrlAndMeta =
842                 frontend::theGuiApp()->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
843 #else
844         const bool dontSwapCtrlAndMeta = false;
845 #endif
846
847         if (state & (dontSwapCtrlAndMeta ? Qt::MetaModifier : Qt::ControlModifier))
848                 k |= ControlModifier;
849         if (state & Qt::ShiftModifier)
850                 k |= ShiftModifier;
851         if (state & Qt::AltModifier)
852                 k |= AltModifier;
853 #if defined(USE_MACOSX_PACKAGING) || defined(USE_META_KEYBINDING)
854         if (state & (dontSwapCtrlAndMeta ? Qt::ControlModifier : Qt::MetaModifier))
855                 k |= MetaModifier;
856 #else
857         if (state & Qt::MetaModifier)
858                 k |= AltModifier;
859 #endif
860         return k;
861 }
862
863 } // namespace lyx