1 /* gtkeditkey.c - key defs for gtk
2 
3    Copyright (C) 1996-2000 the Free Software Foundation
4 
5    Authors: 1996, 1997 Paul Sheer
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307, USA.
21 */
22 
23 #include <config.h>
24 #include "edit.h"
25 #include "editcmddef.h"
26 #include <gdk/gdkkeysyms.h>
27 
28 int mod_type_key (guint x);
29 
30 int (*user_defined_key_function) (unsigned int state, unsigned int keycode, KeySym keysym) = 0;
31 
32 int option_interpret_numlock = 0;
33 
edit_set_user_key_function(int (* user_def_key_func)(unsigned int,unsigned int,KeySym))34 void edit_set_user_key_function (int (*user_def_key_func) (unsigned int, unsigned int, KeySym))
35 {
36     user_defined_key_function = user_def_key_func;
37 }
38 
edit_translate_key(unsigned int x_keycode,long x_key,int x_state,int * cmd,int * ch)39 int edit_translate_key (unsigned int x_keycode, long x_key, int x_state, int *cmd, int *ch)
40 {
41     int command = -1;
42     int char_for_insertion = -1;
43 
44     static long key_map[128] =
45     {GDK_BackSpace, CK_BackSpace, GDK_Delete, CK_Delete, GDK_Return, CK_Enter, GDK_Page_Up, CK_Page_Up,
46      GDK_Page_Down, CK_Page_Down, GDK_Left, CK_Left, GDK_Right, CK_Right, GDK_Up, CK_Up, GDK_Down, CK_Down,
47      GDK_Home, CK_Home, GDK_End, CK_End, GDK_Tab, CK_Tab, GDK_Undo, CK_Undo, GDK_Insert, CK_Toggle_Insert,
48      GDK_F3, CK_Mark, GDK_F5, CK_Copy, GDK_F6, CK_Move, GDK_F8, CK_Remove, GDK_F2, CK_Save, GDK_F12, CK_Save_As,
49      GDK_F10, CK_Exit, GDK_Escape, CK_Cancel, GDK_F9, CK_Menu,
50      GDK_F4, CK_Replace, GDK_F4, CK_Replace_Again, GDK_F17, CK_Find_Again, GDK_F7, CK_Find, GDK_F15, CK_Insert_File, 0, 0};
51 
52     static long key_pad_map[10] =
53     {GDK_Insert, GDK_End, GDK_Down, GDK_Page_Down, GDK_Left,
54      GDK_Down, GDK_Right, GDK_Home, GDK_Up, GDK_Page_Up};
55 
56 
57 #define DEFAULT_NUM_LOCK        1
58 
59     static int num_lock = DEFAULT_NUM_LOCK;
60     static int raw = 0;
61     static int compose = 0;
62     static int decimal = 0;
63     static int hex = 0;
64     int i = 0;
65     int h;
66 
67     if (compose) {
68 	if (mod_type_key (x_key)) {
69 	    goto fin;
70 	} else {
71 	    int c;
72 	    compose = 0;
73 	    c = get_international_character (x_key);
74 	    if (c == 1) {
75 /* *** */
76 #if 0
77 		get_international_character (0);
78 #endif
79 		goto fin;
80 	    } else if (c) {
81 		char_for_insertion = c;
82 		goto fin;
83 	    }
84 	    goto fin;
85 	}
86     }
87     if (option_international_characters) {
88 	if (x_key >= ' ' && x_key <= '~') {
89 /* *** */
90 #if 0
91 	    extern int compose_key_pressed;
92 #endif
93 	    if (compose_key_pressed) {
94 		int c;
95 		c = (x_key >= 'A' && x_key <= 'Z') ? x_key - 'A' + 'a' : x_key;
96 		c = get_international_character ((x_state & ShiftMask) ?
97 			     ((c >= 'a' && c <= 'z') ? c + 'A' - 'a' : c)
98 						 : c);
99 		if (c == 1) {
100 		    compose = 1;
101 		    goto fin;
102 		}
103 		compose = 0;
104 		if (c)
105 		    char_for_insertion = c;
106 		else
107 		    goto fin;
108 	    }
109 	}
110     }
111     if (x_key <= 0 || mod_type_key (x_key))
112 	goto fin;
113 
114     if (raw) {
115 	if (!x_state) {
116 	    if (strchr ("0123456789abcdefh", x_key)) {
117 		char u[2] =
118 		{0, 0};
119 		if (raw == 3) {
120 		    if (x_key == 'h') {
121 			char_for_insertion = hex;
122 			raw = 0;
123 			goto fin;
124 		    } else {
125 			if (x_key > '9') {
126 			    raw = 0;
127 			    goto fin;
128 			}
129 		    }
130 		}
131 		decimal += (x_key - '0') * ((int) ("d\n\001")[raw - 1]);
132 		u[0] = x_key;
133 		hex += (strcspn ("0123456789abcdef", u) << (4 * (2 - raw)));
134 		if (raw == 3) {
135 		    char_for_insertion = decimal;
136 		    raw = 0;
137 		    goto fin;
138 		}
139 		raw++;
140 		goto fin;
141 	    }
142 	}
143 	if (raw > 1) {
144 	    raw = 0;
145 	    goto fin;
146 	}
147 	raw = 0;
148 	if (x_key == GDK_Return)
149 	    char_for_insertion = '\n';
150 	else
151 	    char_for_insertion = x_key;
152 
153 	if (x_state & ControlMask)
154 	    char_for_insertion &= 31;
155 	if (x_state & (MyAltMask))
156 	    char_for_insertion |= 128;
157 	goto fin;
158     }
159 
160     if (user_defined_key_function)
161 	if ((h = (*(user_defined_key_function)) (x_state, x_keycode, x_key))) {
162 	    command = h;
163 	    goto fin;
164 	}
165 
166     if ((x_state & MyAltMask)) {
167 	switch ((int) x_key) {
168 	case GDK_Left:
169 	case GDK_KP_Left:
170 	    command = CK_Delete_Word_Left;
171 	    goto fin;
172 	case GDK_Right:
173 	case GDK_KP_Right:
174 	    command = CK_Delete_Word_Right;
175 	    goto fin;
176 	case GDK_l:
177 	case GDK_L:
178 	    command = CK_Goto;
179 	    goto fin;
180 	case GDK_Insert:
181 	case GDK_KP_Insert:
182 	    command = CK_Selection_History;
183 	    goto fin;
184 	case GDK_Up:
185 	case GDK_KP_Up:
186 	    command = CK_Scroll_Up;
187 	    goto fin;
188 	case GDK_Down:
189 	case GDK_KP_Down:
190 	    command = CK_Scroll_Down;
191 	    goto fin;
192 	case GDK_Delete:
193 	case GDK_KP_Delete:
194 	    command = CK_Delete_To_Line_End;
195 	    goto fin;
196 	case GDK_BackSpace:
197 	    command = CK_Delete_To_Line_Begin;
198 	    goto fin;
199 	case GDK_m:
200 	case GDK_M:
201 	    command = CK_Mail;
202 	    goto fin;
203 	case GDK_x:
204 	case GDK_X:
205 	    command = CK_Save_And_Quit;
206 	    goto fin;
207 	case GDK_p:
208 	case GDK_P:
209 	    command = CK_Paragraph_Format;
210 	    goto fin;
211 	}
212     }
213     if ((x_state & MyAltMask) && (x_state & ShiftMask)) {
214 	switch ((int) x_key) {
215 	case GDK_Up:
216 	case GDK_KP_Up:
217 	    command = CK_Scroll_Up_Highlight;
218 	    goto fin;
219 	case GDK_Down:
220 	case GDK_KP_Down:
221 	    command = CK_Scroll_Down_Highlight;
222 	    goto fin;
223 	}
224     }
225     if (!(x_state & MyAltMask)) {
226 
227 	if ((x_key == GDK_a || x_key == GDK_A) && (x_state & ControlMask)) {
228 #if 0
229 	    command = CK_Macro (CKeySymMod (CRawkeyQuery (0, 0, 0, " Execute Macro ", " Press macro hotkey: ")));
230 	    if (command == CK_Macro (0))
231 #endif
232 		command = -1;
233 	    goto fin;
234 	}
235 	if (x_key == GDK_Num_Lock && option_interpret_numlock) {
236 	    num_lock = 1 - num_lock;
237 	    goto fin;
238 	}
239 	switch ((int) x_key) {
240 	case GDK_KP_Home:
241 	    x_key = GDK_Home;
242 	    break;
243 	case GDK_KP_End:
244 	    x_key = GDK_End;
245 	    break;
246 	case GDK_KP_Page_Up:
247 	    x_key = GDK_Page_Up;
248 	    break;
249 	case GDK_KP_Page_Down:
250 	    x_key = GDK_Page_Down;
251 	    break;
252 	case GDK_KP_Up:
253 	    x_key = GDK_Up;
254 	    break;
255 	case GDK_KP_Down:
256 	    x_key = GDK_Down;
257 	    break;
258 	case GDK_KP_Left:
259 	    x_key = GDK_Left;
260 	    break;
261 	case GDK_KP_Right:
262 	    x_key = GDK_Right;
263 	    break;
264 	case GDK_KP_Insert:
265 	    x_key = GDK_Insert;
266 	    break;
267 	case GDK_KP_Delete:
268 	    x_key = GDK_Delete;
269 	    break;
270 	case GDK_KP_Enter:
271 	    x_key = GDK_Return;
272 	    break;
273 	case GDK_KP_Add:
274 	    x_key = GDK_plus;
275 	    break;
276 	case GDK_KP_Subtract:
277 	    x_key = GDK_minus;
278 	    break;
279 	}
280 
281 /* first translate the key-pad */
282 	if (num_lock) {
283 	    if (x_key >= GDK_R1 && x_key <= GDK_R9) {
284 		x_key = key_pad_map[x_key - GDK_R1 + 1];
285 	    } else if (x_key >= GDK_KP_0 && x_key <= GDK_KP_9) {
286 		x_key = key_pad_map[x_key - GDK_KP_0];
287 	    } else if (x_key == GDK_KP_Decimal) {
288 		x_key = GDK_Delete;
289 	    }
290 	} else {
291 	    if (x_key >= GDK_KP_0 && x_key <= GDK_KP_9) {
292 		x_key += GDK_0 - GDK_KP_0;
293 	    }
294 	    if (x_key == GDK_KP_Decimal) {
295 		x_key = GDK_period;
296 	    }
297 	}
298 
299 	if ((x_state & ShiftMask) && (x_state & ControlMask)) {
300 	    switch ((int) x_key) {
301 	    case GDK_Page_Up:
302 		command = CK_Beginning_Of_Text_Highlight;
303 		goto fin;
304 	    case GDK_Page_Down:
305 		command = CK_End_Of_Text_Highlight;
306 		goto fin;
307 	    case GDK_Left:
308 		command = CK_Word_Left_Highlight;
309 		goto fin;
310 	    case GDK_Right:
311 		command = CK_Word_Right_Highlight;
312 		goto fin;
313 	    case GDK_Up:
314 		command = CK_Paragraph_Up_Highlight;
315 		goto fin;
316 	    case GDK_Down:
317 		command = CK_Paragraph_Down_Highlight;
318 		goto fin;
319 	    case GDK_Home:
320 		command = CK_Begin_Page_Highlight;
321 		goto fin;
322 	    case GDK_End:
323 		command = CK_End_Page_Highlight;
324 		goto fin;
325 	    }
326 	}
327 	if ((x_state & ShiftMask) && !(x_state & ControlMask)) {
328 	    switch ((int) x_key) {
329 	    case GDK_Page_Up:
330 		command = CK_Page_Up_Highlight;
331 		goto fin;
332 	    case GDK_Page_Down:
333 		command = CK_Page_Down_Highlight;
334 		goto fin;
335 	    case GDK_Left:
336 		command = CK_Left_Highlight;
337 		goto fin;
338 	    case GDK_Right:
339 		command = CK_Right_Highlight;
340 		goto fin;
341 	    case GDK_Up:
342 		command = CK_Up_Highlight;
343 		goto fin;
344 	    case GDK_Down:
345 		command = CK_Down_Highlight;
346 		goto fin;
347 	    case GDK_Home:
348 		command = CK_Home_Highlight;
349 		goto fin;
350 	    case GDK_End:
351 		command = CK_End_Highlight;
352 		goto fin;
353 	    case GDK_Insert:
354 		command = CK_XPaste;
355 		goto fin;
356 	    case GDK_Delete:
357 		command = CK_XCut;
358 		goto fin;
359 	    case GDK_Return:
360 		command = CK_Return;
361 		goto fin;
362 /* this parallel F12, F19, F15, and F17 for some systems */
363 	    case GDK_F2:
364 		command = CK_Save_As;
365 		goto fin;
366 	    case GDK_F5:
367 		command = CK_Insert_File;
368 		goto fin;
369 	    case GDK_F7:
370 		command = CK_Find_Again;
371 		goto fin;
372 	    case GDK_F4:
373 		command = CK_Replace_Again;
374 		goto fin;
375 	    case GDK_F3:
376 		command = CK_Run_Another;
377 		goto fin;
378 	    }
379 	}
380 /* things that need a control key */
381 	if (x_state & ControlMask) {
382 	    switch ((int) x_key) {
383 	    case GDK_F1:
384 		command = CK_Man_Page;
385 		goto fin;
386 	    case GDK_U:
387 	    case GDK_u:
388 	    case GDK_BackSpace:
389 		command = CK_Undo;
390 		goto fin;
391 	    case GDK_Page_Up:
392 		command = CK_Beginning_Of_Text;
393 		goto fin;
394 	    case GDK_Page_Down:
395 		command = CK_End_Of_Text;
396 		goto fin;
397 	    case GDK_Up:
398 		command = CK_Paragraph_Up;
399 		goto fin;
400 	    case GDK_Down:
401 		command = CK_Paragraph_Down;
402 		goto fin;
403 	    case GDK_Left:
404 		command = CK_Word_Left;
405 		goto fin;
406 	    case GDK_Right:
407 		command = CK_Word_Right;
408 		goto fin;
409 	    case GDK_Home:
410 		command = CK_Begin_Page;
411 		goto fin;
412 	    case GDK_End:
413 		command = CK_End_Page;
414 		goto fin;
415 	    case GDK_N:
416 	    case GDK_n:
417 		command = CK_New;
418 		goto fin;
419 	    case GDK_O:
420 	    case GDK_o:
421 		command = CK_Load;
422 		goto fin;
423 	    case GDK_D:
424 	    case GDK_d:
425 		command = CK_Date;
426 		goto fin;
427 	    case GDK_Q:
428 	    case GDK_q:
429 		raw = 1;
430 		decimal = 0;
431 		hex = 0;
432 		goto fin;
433 	    case GDK_F:
434 	    case GDK_f:
435 		command = CK_Save_Block;
436 		goto fin;
437 	    case GDK_F5:
438 	    case GDK_F15:
439 		command = CK_Insert_File;
440 		goto fin;
441 	    case GDK_Insert:
442 		command = CK_XStore;
443 		goto fin;
444 	    case GDK_y:
445 	    case GDK_Y:
446 		command = CK_Delete_Line;
447 		goto fin;
448 	    case GDK_Delete:
449 		command = CK_Remove;
450 		goto fin;
451 	    case GDK_F2:
452 		command = CK_Save_Desktop;
453 		goto fin;
454 	    case GDK_F3:
455 		command = CK_New_Window;
456 		goto fin;
457 	    case GDK_F6:
458 		command = CK_Cycle;
459 		goto fin;
460 	    case GDK_F10:
461 		command = CK_Check_Save_And_Quit;
462 		goto fin;
463 	    case GDK_Tab:
464 	    case GDK_KP_Tab:
465 		command = CK_Complete;
466 		goto fin;
467 	    case GDK_b:
468 		command = CK_Column_Mark;
469 		goto fin;
470 	    }
471 	}
472 /* an ordinary ascii character or international character */
473 	if (!(x_state & MyAltMask)) {
474 	    if (!(x_state & ControlMask)) {
475 		if ((x_key >= GDK_space && x_key <= GDK_asciitilde) || ((x_key >= 160 && x_key < 256) && option_international_characters)) {
476 		    char_for_insertion = x_key;
477 		    goto fin;
478 		}
479 /* other commands */
480 		if (!(x_state & ShiftMask)) {
481 		    i = 0;
482 		    while (key_map[i] != x_key && key_map[i])
483 			i += 2;
484 		    command = key_map[i + 1];
485 		    if (command)
486 			goto fin;
487 		}
488 	    }
489 	}
490     }
491   fin:
492 
493     *cmd = command;
494     *ch = char_for_insertion;
495 
496     if ((command == -1 || command == 0) && char_for_insertion == -1)	/* unchanged, key has no function here */
497 	return 0;
498     return 1;
499 }
500 
501