1 /**
2  * \file qt4/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 "KeySymbol.h"
14 #include "GuiApplication.h"
15 
16 #include "qt_helpers.h"
17 
18 #include "support/lassert.h"
19 #include "support/debug.h"
20 
21 #include "Encoding.h"
22 #include "Language.h"
23 
24 #include <QKeyEvent>
25 #include <QKeySequence>
26 #include <QEvent>
27 #include <QTextCodec>
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  */
isModifier(int qkey)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  */
string_to_qkey(std::string const & str)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 	return Qt::Key_unknown;
357 }
358 
359 
360 /**
361  * qkey_to_string - convert Qt keypress into LyX
362  *
363  * Convert the Qt keypress into a string understandable
364  * by the LyX core (same as XKeysymToString).
365  */
qkey_to_string(int lkey)366 static std::string const qkey_to_string(int lkey)
367 {
368 	switch (lkey) {
369 	case Qt::Key_0: return "0";
370 	case Qt::Key_1: return "1";
371 	case Qt::Key_2: return "2";
372 	case Qt::Key_3: return "3";
373 	case Qt::Key_4: return "4";
374 	case Qt::Key_5: return "5";
375 	case Qt::Key_6: return "6";
376 	case Qt::Key_7: return "7";
377 	case Qt::Key_8: return "8";
378 	case Qt::Key_9: return "9";
379 
380 	case Qt::Key_A: return "a";
381 	case Qt::Key_B: return "b";
382 	case Qt::Key_C: return "c";
383 	case Qt::Key_D: return "d";
384 	case Qt::Key_E: return "e";
385 	case Qt::Key_F: return "f";
386 	case Qt::Key_G: return "g";
387 	case Qt::Key_H: return "h";
388 	case Qt::Key_I: return "i";
389 	case Qt::Key_J: return "j";
390 	case Qt::Key_K: return "k";
391 	case Qt::Key_L: return "l";
392 	case Qt::Key_M: return "m";
393 	case Qt::Key_N: return "n";
394 	case Qt::Key_O: return "o";
395 	case Qt::Key_P: return "p";
396 	case Qt::Key_Q: return "q";
397 	case Qt::Key_R: return "r";
398 	case Qt::Key_S: return "s";
399 	case Qt::Key_T: return "t";
400 	case Qt::Key_U: return "u";
401 	case Qt::Key_V: return "v";
402 	case Qt::Key_W: return "w";
403 	case Qt::Key_X: return "x";
404 	case Qt::Key_Y: return "y";
405 	case Qt::Key_Z: return "z";
406 
407 	case Qt::Key_Return: return "Return";
408 	case Qt::Key_Escape: return "Escape";
409 	case Qt::Key_Tab: return "Tab";
410 	case Qt::Key_Backspace: return "BackSpace";
411 	case Qt::Key_Insert: return "Insert";
412 	case Qt::Key_Delete: return "Delete";
413 	case Qt::Key_Pause: return "Pause";
414 	case Qt::Key_Print: return "Print";
415 	case Qt::Key_SysReq: return "Sys_Req";
416 	case Qt::Key_Home: return "Home";
417 	case Qt::Key_End: return "End";
418 	case Qt::Key_Left: return "Left";
419 	case Qt::Key_Up: return "Up";
420 	case Qt::Key_Right: return "Right";
421 	case Qt::Key_Down: return "Down";
422 	case Qt::Key_PageUp: return "Prior";
423 	case Qt::Key_PageDown: return "Next";
424 	case Qt::Key_Shift: return "Shift_L";
425 	case Qt::Key_Control: return "Control_L";
426 	case Qt::Key_Meta: return "Alt_L"; // correct ?
427 	case Qt::Key_Alt: return "Alt_R";
428 	case Qt::Key_CapsLock: return "Caps_Lock";
429 	case Qt::Key_NumLock: return "Num_Lock";
430 	case Qt::Key_ScrollLock: return "Scroll_Lock";
431 	case Qt::Key_F1: return "F1";
432 	case Qt::Key_F2: return "F2";
433 	case Qt::Key_F3: return "F3";
434 	case Qt::Key_F4: return "F4";
435 	case Qt::Key_F5: return "F5";
436 	case Qt::Key_F6: return "F6";
437 	case Qt::Key_F7: return "F7";
438 	case Qt::Key_F8: return "F8";
439 	case Qt::Key_F9: return "F9";
440 	case Qt::Key_F10: return "F10";
441 	case Qt::Key_F11: return "F11";
442 	case Qt::Key_F12: return "F12";
443 	case Qt::Key_F13: return "F13";
444 	case Qt::Key_F14: return "F14";
445 	case Qt::Key_F15: return "F15";
446 	case Qt::Key_F16: return "F16";
447 	case Qt::Key_F17: return "F17";
448 	case Qt::Key_F18: return "F18";
449 	case Qt::Key_F19: return "F19";
450 	case Qt::Key_F20: return "F20";
451 	case Qt::Key_F21: return "F21";
452 	case Qt::Key_F22: return "F22";
453 	case Qt::Key_F23: return "F23";
454 	case Qt::Key_F24: return "F24";
455 	case Qt::Key_F25: return "F25";
456 	case Qt::Key_F26: return "F26";
457 	case Qt::Key_F27: return "F27";
458 	case Qt::Key_F28: return "F28";
459 	case Qt::Key_F29: return "F29";
460 	case Qt::Key_F30: return "F30";
461 	case Qt::Key_F31: return "F31";
462 	case Qt::Key_F32: return "F32";
463 	case Qt::Key_F33: return "F33";
464 	case Qt::Key_F34: return "F34";
465 	case Qt::Key_F35: return "F35";
466 	case Qt::Key_Colon: return "colon";
467 	case Qt::Key_Semicolon: return "semicolon";
468 	case Qt::Key_Less: return "less";
469 	case Qt::Key_Equal: return "equal";
470 	case Qt::Key_Greater: return "greater";
471 	case Qt::Key_Question: return "question";
472 	case Qt::Key_At: return "at";
473 	case Qt::Key_BracketLeft: return "bracketleft";
474 	case Qt::Key_Backslash: return "backslash";
475 	case Qt::Key_BracketRight: return "bracketright";
476 	case Qt::Key_Underscore: return "underscore";
477 	case Qt::Key_Space: return "space";
478 	case Qt::Key_ParenLeft: return "parenleft";
479 	case Qt::Key_ParenRight: return "parenright";
480 	case Qt::Key_QuoteDbl: return "quotedbl";
481 	case Qt::Key_Exclam: return "exclam";
482 	case Qt::Key_NumberSign: return "numbersign";
483 	case Qt::Key_AsciiCircum: return "asciicircum";
484 	case Qt::Key_Dollar: return "dollar";
485 	case Qt::Key_Percent: return "percent";
486 	case Qt::Key_Ampersand: return "ampersand";
487 	case Qt::Key_Asterisk: return "asterisk";
488 	case Qt::Key_Apostrophe: return "apostrophe";
489 	case Qt::Key_Plus: return "plus";
490 	case Qt::Key_Minus: return "minus";
491 	case Qt::Key_Comma: return "comma";
492 	case Qt::Key_Period: return "period";
493 	case Qt::Key_Slash: return "slash";
494 	case Qt::Key_AsciiTilde: return "asciitilde";
495 	case Qt::Key_BraceLeft: return "braceleft";
496 	case Qt::Key_BraceRight: return "braceright";
497 	case Qt::Key_QuoteLeft: return "grave"; // ???
498 	case Qt::Key_notsign: return "notsign";
499 	case Qt::Key_nobreakspace: return "nobreakspace";
500 	case Qt::Key_exclamdown: return "exclamdown";
501 	case Qt::Key_cent: return "cent";
502 	case Qt::Key_sterling: return "sterling";
503 	case Qt::Key_currency: return "currency";
504 	case Qt::Key_yen: return "yen";
505 	case Qt::Key_brokenbar: return "brokenbar";
506 	case Qt::Key_section: return "section";
507 	case Qt::Key_diaeresis: return "diaeresis";
508 	case Qt::Key_copyright: return "copyright";
509 	case Qt::Key_ordfeminine: return "ordfeminine";
510 	case Qt::Key_guillemotleft: return "guillemotleft";
511 	case Qt::Key_hyphen: return "hyphen";
512 	case Qt::Key_registered: return "registered";
513 	case Qt::Key_macron: return "macron";
514 	case Qt::Key_degree: return "degree";
515 	case Qt::Key_plusminus: return "plusminus";
516 	case Qt::Key_twosuperior: return "twosuperior";
517 	case Qt::Key_threesuperior: return "threesuperior";
518 	case Qt::Key_acute: return "acute";
519 	case Qt::Key_mu: return "mu";
520 	case Qt::Key_paragraph: return "paragraph";
521 	case Qt::Key_periodcentered: return "periodcentered";
522 	case Qt::Key_cedilla: return "cedilla";
523 	case Qt::Key_onesuperior: return "onesuperior";
524 	case Qt::Key_masculine: return "masculine";
525 	case Qt::Key_guillemotright: return "guillemotright";
526 	case Qt::Key_onequarter: return "onequarter";
527 	case Qt::Key_onehalf: return "onehalf";
528 	case Qt::Key_threequarters: return "threequarters";
529 	case Qt::Key_questiondown: return "questiondown";
530 	case Qt::Key_Agrave: return "Agrave";
531 	case Qt::Key_Aacute: return "Aacute";
532 	case Qt::Key_Acircumflex: return "Acircumflex";
533 	case Qt::Key_Atilde: return "Atilde";
534 	case Qt::Key_Adiaeresis: return "Adiaeresis";
535 	case Qt::Key_Aring: return "Aring";
536 	case Qt::Key_AE: return "AE";
537 	case Qt::Key_Ccedilla: return "Ccedilla";
538 	case Qt::Key_Egrave: return "Egrave";
539 	case Qt::Key_Eacute: return "Eacute";
540 	case Qt::Key_Ecircumflex: return "Ecircumflex";
541 	case Qt::Key_Ediaeresis: return "Ediaeresis";
542 	case Qt::Key_Igrave: return "Igrave";
543 	case Qt::Key_Iacute: return "Iacute";
544 	case Qt::Key_Icircumflex: return "Icircumflex";
545 	case Qt::Key_Idiaeresis: return "Idiaeresis";
546 	case Qt::Key_ETH: return "ETH";
547 	case Qt::Key_Ntilde: return "Ntilde";
548 	case Qt::Key_Ograve: return "Ograve";
549 	case Qt::Key_Oacute: return "Oacute";
550 	case Qt::Key_Ocircumflex: return "Ocircumflex";
551 	case Qt::Key_Otilde: return "Otilde";
552 	case Qt::Key_Odiaeresis: return "Odiaeresis";
553 	case Qt::Key_multiply: return "multiply";
554 	case Qt::Key_Ooblique: return "Ooblique";
555 	case Qt::Key_Ugrave: return "Ugrave";
556 	case Qt::Key_Uacute: return "Uacute";
557 	case Qt::Key_Ucircumflex: return "Ucircumflex";
558 	case Qt::Key_Udiaeresis: return "Udiaeresis";
559 	case Qt::Key_Yacute: return "Yacute";
560 	case Qt::Key_THORN: return "THORN";
561 	case Qt::Key_ssharp: return "ssharp";
562 	case Qt::Key_ydiaeresis: return "ydiaeresis";
563 	case Qt::Key_Bar: return "bar";
564 	case Qt::Key_Dead_Caron: return "Dead_Caron";
565 
566 	// FIXME: these ones I don't know the names of ... help !
567 	// what's here is basically guesses ...
568 	case Qt::Key_Super_L: return "Super_L";
569 	case Qt::Key_Super_R: return "Super_R";
570 	case Qt::Key_Menu: return "Menu";
571 	case Qt::Key_Hyper_L: return "Hyper_L";
572 	case Qt::Key_Hyper_R: return "Hyper_R";
573 	case Qt::Key_Help: return "Help";
574 	case Qt::Key_Backtab: return "BackTab";
575 
576 	default:
577 	case Qt::Key_unknown: return "";
578 	}
579 }
580 
581 
582 #if 0
583 static char encode(string const & encoding, QString const & str)
584 {
585 	typedef map<string, QTextCodec *> EncodingMap;
586 	EncodingMap encoding_map;
587 
588 	QTextCodec * codec = 0;
589 
590 	EncodingMap::const_iterator cit = encoding_map.find(encoding);
591 	if (cit == encoding_map.end()) {
592 		LYXERR(Debug::KEY, "Unrecognised encoding '" << encoding << "'.");
593 		codec = encoding_map.find("")->second;
594 	} else {
595 		codec = cit->second;
596 	}
597 
598 	if (!codec) {
599 		LYXERR(Debug::KEY, "No codec for encoding '" << encoding << "' found.");
600 		return 0;
601 	}
602 
603 	LYXERR(Debug::KEY, "Using codec " << codec->name());
604 
605 	if (!codec->canEncode(str)) {
606 		LYXERR(Debug::KEY, "Oof. Can't encode the text !");
607 		return 0;
608 	}
609 
610 	return codec->fromUnicode(str).data()[0];
611 }
612 #endif
613 
614 
setKeySymbol(KeySymbol * sym,QKeyEvent const * ev)615 void setKeySymbol(KeySymbol * sym, QKeyEvent const * ev)
616 {
617 	sym->setKey(ev->key());
618 	if (ev->text().isNull()) {
619 		LYXERR(Debug::KEY, "keyevent has isNull() text !");
620 		sym->setText(docstring());
621 		return;
622 	}
623 	LYXERR(Debug::KEY, "Getting key " << ev->key() << ", with text '"
624 		<< ev->text() << "'");
625 	// This is unsafe because ev->text() is the unicode representation of the
626 	// key, not the name of the key. For example, Ctrl-x and Alt-x produce
627 	// different texts.
628 	sym->setText(qstring_to_ucs4(ev->text()));
629 	LYXERR(Debug::KEY, "Setting key to " << sym->key() << ", "
630 		<< to_utf8(sym->text()));
631 }
632 
633 
init(string const & symbolname)634 void KeySymbol::init(string const & symbolname)
635 {
636 	key_ = string_to_qkey(symbolname);
637 	text_ = from_utf8(symbolname);
638 	LYXERR(Debug::KEY, "Init key to " << key_ << ", " << to_utf8(text_));
639 }
640 
641 
isOK() const642 bool KeySymbol::isOK() const
643 {
644 	bool const ok = !(text_.empty() && qkey_to_string(key_).empty());
645 	LYXERR(Debug::KEY, "isOK is " << ok);
646 	return ok;
647 }
648 
649 
isModifier() const650 bool KeySymbol::isModifier() const
651 {
652 	bool const mod = lyx::isModifier(key_);
653 	LYXERR(Debug::KEY, "isModifier is " << mod);
654 	return mod;
655 }
656 
657 
getSymbolName() const658 string KeySymbol::getSymbolName() const
659 {
660 	string name = qkey_to_string(key_);
661 
662 	// others
663 	if (name.empty())
664 		name = to_utf8(text_);
665 
666 	return name;
667 }
668 
669 
getUCSEncoded() const670 char_type KeySymbol::getUCSEncoded() const
671 {
672 	if (text_.empty())
673 		return 0;
674 
675 	// UTF16 has a maximum of two characters.
676 	LASSERT(text_.size() <= 2, return 0);
677 
678 	if (lyxerr.debugging() && text_.size() > 1) {
679 		// We don't know yet how well support the full ucs4 range.
680 		LYXERR(Debug::KEY, "KeySymbol::getUCSEncoded()");
681 		for (int i = 0; i != int(text_.size()); ++i)
682 			LYXERR(Debug::KEY, "char " << i << ": " << int(text_[i]));
683 	}
684 
685 	return text_[0];
686 }
687 
688 
print(KeyModifier mod,bool forgui) const689 docstring const KeySymbol::print(KeyModifier mod, bool forgui) const
690 {
691 	int tmpkey = key_;
692 
693 	if (mod & ShiftModifier && !(tmpkey == Qt::Key_Shift))
694 		tmpkey += Qt::ShiftModifier;
695 	if (mod & ControlModifier && !(tmpkey == Qt::Key_Control))
696 		tmpkey += Qt::ControlModifier;
697 	if (mod & AltModifier && !(tmpkey == Qt::Key_Alt))
698 		tmpkey += Qt::AltModifier;
699 	if (mod & MetaModifier && !(tmpkey == Qt::Key_Meta))
700 		tmpkey += Qt::MetaModifier;
701 
702 	QKeySequence seq(tmpkey);
703 	QString str;
704 
705 	if (forgui)
706 		str = seq.toString(QKeySequence::NativeText);
707 	else {
708 #ifdef Q_OS_MAC
709 		// Qt/Mac does not use Command and friends in the
710 		// portable case, but the windows-like Control+x (bug 5421).
711 		str = seq.toString(QKeySequence::NativeText);
712 		str.replace(QChar(0x21E7), qt_("Shift-"));
713 		str.replace(QChar(0x2303), qt_("Control-"));
714 		str.replace(QChar(0x2325), qt_("Option-"));
715 		str.replace(QChar(0x2318), qt_("Command-"));
716 #else
717 		str = seq.toString(QKeySequence::PortableText);
718 #endif
719 	}
720 
721 	return qstring_to_ucs4(str);
722 }
723 
724 
isText() const725 bool KeySymbol::isText() const
726 {
727 	if (!text_.empty())
728 		return true;
729 	LYXERR(Debug::KEY, "text_ empty, isText() == false");
730 	return false;
731 }
732 
733 
operator ==(KeySymbol const & ks) const734 bool KeySymbol::operator==(KeySymbol const & ks) const
735 {
736 	// we do not have enough info for a fair comparison, so return
737 	// false. This works out OK because unknown text from Qt will
738 	// get inserted anyway after the isText() check
739 	if (key_ == Qt::Key_unknown || ks.key_ == Qt::Key_unknown)
740 		return false;
741 	return key_ == ks.key_;
742 }
743 
744 
q_key_state(Qt::KeyboardModifiers state)745 KeyModifier q_key_state(Qt::KeyboardModifiers state)
746 {
747 	KeyModifier k = NoModifier;
748 #if defined(Q_OS_MAC) && QT_VERSION > 0x050000
749 	/// Additional check for Control and Meta modifier swap state.
750 	/// Starting with Qt 5 the modifiers aren't reported correctly.
751 	/// Until this is fixed a correction is required.
752 	const bool dontSwapCtrlAndMeta =
753 		frontend::theGuiApp()->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
754 #else
755 	const bool dontSwapCtrlAndMeta = false;
756 #endif
757 
758 	if (state & (dontSwapCtrlAndMeta ? Qt::MetaModifier : Qt::ControlModifier))
759 		k |= ControlModifier;
760 	if (state & Qt::ShiftModifier)
761 		k |= ShiftModifier;
762 	if (state & Qt::AltModifier)
763 		k |= AltModifier;
764 #if defined(USE_MACOSX_PACKAGING) || defined(USE_META_KEYBINDING)
765 	if (state & (dontSwapCtrlAndMeta ? Qt::ControlModifier : Qt::MetaModifier))
766 		k |= MetaModifier;
767 #else
768 	if (state & Qt::MetaModifier)
769 		k |= AltModifier;
770 #endif
771 	return k;
772 }
773 
774 } // namespace lyx
775