Updated Hungarian translation
[evolution.git] / e-util / e-text-event-processor-emacs-like.c
bloba99529a6bb9709e2228a954f674cafe5d962554f
1 /*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful, but
7 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9 * for more details.
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 * Authors:
16 * Chris Lahey <clahey@ximian.com>
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <string.h>
28 #include <gdk/gdkkeysyms.h>
30 #include "e-text-event-processor-emacs-like.h"
32 static gint e_text_event_processor_emacs_like_event
33 (ETextEventProcessor *tep,
34 ETextEventProcessorEvent *event);
36 G_DEFINE_TYPE (
37 ETextEventProcessorEmacsLike,
38 e_text_event_processor_emacs_like,
39 E_TYPE_TEXT_EVENT_PROCESSOR)
41 static const ETextEventProcessorCommand control_keys[26] = {
42 { E_TEP_START_OF_LINE, E_TEP_MOVE, 0, "" }, /* a */
43 { E_TEP_BACKWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* b */
44 { E_TEP_SELECTION, E_TEP_COPY, 0, "" }, /* c */
45 { E_TEP_FORWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* d */
46 { E_TEP_END_OF_LINE, E_TEP_MOVE, 0, "" }, /* e */
47 { E_TEP_FORWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* f */
48 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
49 { E_TEP_BACKWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* h */
50 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
51 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
52 { E_TEP_END_OF_LINE, E_TEP_DELETE, 0, "" }, /* k */
53 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
54 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
55 { E_TEP_FORWARD_LINE, E_TEP_MOVE, 0, "" }, /* n */
56 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
57 { E_TEP_BACKWARD_LINE, E_TEP_MOVE, 0, "" }, /* p */
58 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
59 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
60 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
61 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
62 { E_TEP_START_OF_LINE, E_TEP_DELETE, 0, "" }, /* u */
63 { E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* v */
64 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* w */
65 { E_TEP_SELECTION, E_TEP_DELETE, 0, "" }, /* x */
66 { E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* y */
67 { E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
70 static const ETextEventProcessorCommand alt_keys[26] = {
71 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* a */
72 { E_TEP_BACKWARD_WORD, E_TEP_MOVE, 0, "" }, /* b */
73 { E_TEP_SELECTION, E_TEP_CAPS, E_TEP_CAPS_TITLE, "" },/* c */
74 { E_TEP_FORWARD_WORD, E_TEP_DELETE, 0, "" }, /* d */
75 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* e */
76 { E_TEP_FORWARD_WORD, E_TEP_MOVE, 0, "" }, /* f */
77 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
78 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* h */
79 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
80 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
81 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* k */
82 { E_TEP_SELECTION, E_TEP_CAPS, E_TEP_CAPS_LOWER, "" }, /* l */
83 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
84 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* n */
85 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
86 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* p */
87 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
88 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
89 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
90 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
91 { E_TEP_SELECTION, E_TEP_CAPS, E_TEP_CAPS_UPPER, "" }, /* u */
92 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* v */
93 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* w */
94 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* x */
95 { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
96 { E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
100 static void
101 e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *class)
103 ETextEventProcessorClass *processor_class;
105 processor_class = (ETextEventProcessorClass *) class;
107 processor_class->event = e_text_event_processor_emacs_like_event;
110 static void
111 e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *tep)
115 static gint
116 e_text_event_processor_emacs_like_event (ETextEventProcessor *tep,
117 ETextEventProcessorEvent *event)
119 ETextEventProcessorCommand command;
120 ETextEventProcessorEmacsLike *tep_el = E_TEXT_EVENT_PROCESSOR_EMACS_LIKE (tep);
121 command.action = E_TEP_NOP;
123 /* Warning from the Intel compiler here:
124 * e-text-event-processor-emacs-like.c(136): warning #589:
125 * transfer of control bypasses initialization of:
126 * variable "key" (declared at line 194)
127 * switch (event->type) {
130 switch (event->type) {
131 case GDK_BUTTON_PRESS:
132 if (event->button.button == 1 || event->button.button == 2) {
133 command.action = E_TEP_GRAB;
134 command.device = event->button.device;
135 command.time = event->button.time;
136 g_signal_emit_by_name (tep, "command", &command);
137 if (event->button.button == 1 && event->button.state & GDK_SHIFT_MASK)
138 command.action = E_TEP_SELECT;
139 else
140 command.action = E_TEP_MOVE;
141 command.position = E_TEP_VALUE;
142 command.value = event->button.position;
143 command.time = event->button.time;
144 tep_el->mouse_down = event->button.button == 1;
146 break;
148 case GDK_2BUTTON_PRESS:
149 if (event->button.button == 1) {
150 command.action = E_TEP_SELECT;
151 command.position = E_TEP_SELECT_WORD;
152 command.time = event->button.time;
154 break;
156 case GDK_3BUTTON_PRESS:
157 if (event->button.button == 1) {
158 command.action = E_TEP_SELECT;
159 command.position = E_TEP_SELECT_ALL;
160 command.time = event->button.time;
162 break;
164 case GDK_BUTTON_RELEASE:
165 if (event->button.button == 1) {
166 command.action = E_TEP_UNGRAB;
167 command.time = event->button.time;
168 tep_el->mouse_down = FALSE;
169 } else if (event->button.button == 2) {
170 command.action = E_TEP_MOVE;
171 command.position = E_TEP_VALUE;
172 command.value = event->button.position;
173 command.time = event->button.time;
174 g_signal_emit_by_name (tep, "command", &command);
176 command.action = E_TEP_GET_SELECTION;
177 command.position = E_TEP_SELECTION;
178 command.value = 0;
179 command.time = event->button.time;
181 break;
183 case GDK_MOTION_NOTIFY:
184 if (tep_el->mouse_down) {
185 command.action = E_TEP_SELECT;
186 command.position = E_TEP_VALUE;
187 command.time = event->motion.time;
188 command.value = event->motion.position;
190 break;
192 case GDK_KEY_PRESS:
194 ETextEventProcessorEventKey key = event->key;
196 command.time = event->key.time;
198 if (key.state & GDK_SHIFT_MASK)
199 command.action = E_TEP_SELECT;
200 else if (key.state & GDK_MOD1_MASK)
201 command.action = E_TEP_NOP;
202 else
203 command.action = E_TEP_MOVE;
205 switch (key.keyval) {
206 case GDK_KEY_Home:
207 case GDK_KEY_KP_Home:
208 if (key.state & GDK_CONTROL_MASK)
209 command.position = E_TEP_START_OF_BUFFER;
210 else
211 command.position = E_TEP_START_OF_LINE;
212 break;
214 case GDK_KEY_End:
215 case GDK_KEY_KP_End:
216 if (key.state & GDK_CONTROL_MASK)
217 command.position = E_TEP_END_OF_BUFFER;
218 else
219 command.position = E_TEP_END_OF_LINE;
220 break;
222 case GDK_KEY_Page_Up:
223 case GDK_KEY_KP_Page_Up:
224 command.position = E_TEP_BACKWARD_PAGE;
225 break;
227 case GDK_KEY_Page_Down:
228 case GDK_KEY_KP_Page_Down:
229 command.position = E_TEP_FORWARD_PAGE;
230 break;
232 /* CUA has Ctrl-Up/Ctrl-Down as paragraph up down */
233 case GDK_KEY_Up:
234 case GDK_KEY_KP_Up:
235 command.position = E_TEP_BACKWARD_LINE;
236 break;
238 case GDK_KEY_Down:
239 case GDK_KEY_KP_Down:
240 command.position = E_TEP_FORWARD_LINE;
241 break;
243 case GDK_KEY_Left:
244 case GDK_KEY_KP_Left:
245 if (key.state & GDK_CONTROL_MASK)
246 command.position = E_TEP_BACKWARD_WORD;
247 else
248 command.position = E_TEP_BACKWARD_CHARACTER;
249 break;
251 case GDK_KEY_Right:
252 case GDK_KEY_KP_Right:
253 if (key.state & GDK_CONTROL_MASK)
254 command.position = E_TEP_FORWARD_WORD;
255 else
256 command.position = E_TEP_FORWARD_CHARACTER;
257 break;
259 case GDK_KEY_BackSpace:
260 command.action = E_TEP_DELETE;
261 if (key.state & GDK_CONTROL_MASK)
262 command.position = E_TEP_BACKWARD_WORD;
263 else
264 command.position = E_TEP_BACKWARD_CHARACTER;
265 break;
267 case GDK_KEY_Clear:
268 command.action = E_TEP_DELETE;
269 command.position = E_TEP_END_OF_LINE;
270 break;
272 case GDK_KEY_Insert:
273 case GDK_KEY_KP_Insert:
274 if (key.state & GDK_SHIFT_MASK) {
275 command.action = E_TEP_PASTE;
276 command.position = E_TEP_SELECTION;
277 } else if (key.state & GDK_CONTROL_MASK) {
278 command.action = E_TEP_COPY;
279 command.position = E_TEP_SELECTION;
280 } else {
281 /* gtk_toggle_insert(text) -- IMPLEMENT -- FIXME */
283 break;
285 case GDK_KEY_F16:
286 command.action = E_TEP_COPY;
287 command.position = E_TEP_SELECTION;
288 break;
290 case GDK_KEY_F18:
291 command.action = E_TEP_PASTE;
292 command.position = E_TEP_SELECTION;
293 break;
295 case GDK_KEY_F20:
296 command.action = E_TEP_COPY;
297 command.position = E_TEP_SELECTION;
298 g_signal_emit_by_name (
299 tep, "command", &command);
301 command.action = E_TEP_DELETE;
302 command.position = E_TEP_SELECTION;
303 break;
305 case GDK_KEY_Delete:
306 case GDK_KEY_KP_Delete:
307 if (key.state & GDK_CONTROL_MASK) {
308 command.action = E_TEP_DELETE;
309 command.position = E_TEP_FORWARD_WORD;
310 } else if (key.state & GDK_SHIFT_MASK) {
311 command.action = E_TEP_COPY;
312 command.position = E_TEP_SELECTION;
313 g_signal_emit_by_name (
314 tep, "command", &command);
316 command.action = E_TEP_DELETE;
317 command.position = E_TEP_SELECTION;
318 } else {
319 command.action = E_TEP_DELETE;
320 command.position = E_TEP_FORWARD_CHARACTER;
322 break;
324 case GDK_KEY_Tab:
325 case GDK_KEY_KP_Tab:
326 case GDK_KEY_ISO_Left_Tab:
327 case GDK_KEY_3270_BackTab:
328 /* Don't insert literally */
329 command.action = E_TEP_NOP;
330 command.position = E_TEP_SELECTION;
331 break;
333 case GDK_KEY_Return:
334 case GDK_KEY_KP_Enter:
335 if (tep->allow_newlines) {
336 if (key.state & GDK_CONTROL_MASK) {
337 command.action = E_TEP_ACTIVATE;
338 command.position = E_TEP_SELECTION;
339 } else {
340 command.action = E_TEP_INSERT;
341 command.position = E_TEP_SELECTION;
342 command.value = 1;
343 command.string = "\n";
345 } else {
346 if (key.state & GDK_CONTROL_MASK) {
347 command.action = E_TEP_NOP;
348 command.position = E_TEP_SELECTION;
349 } else {
350 command.action = E_TEP_ACTIVATE;
351 command.position = E_TEP_SELECTION;
354 break;
356 case GDK_KEY_Escape:
357 /* Don't insert literally */
358 command.action = E_TEP_NOP;
359 command.position = E_TEP_SELECTION;
360 break;
362 case GDK_KEY_KP_Space:
363 command.action = E_TEP_INSERT;
364 command.position = E_TEP_SELECTION;
365 command.value = 1;
366 command.string = " ";
367 break;
369 case GDK_KEY_KP_Equal:
370 command.action = E_TEP_INSERT;
371 command.position = E_TEP_SELECTION;
372 command.value = 1;
373 command.string = "=";
374 break;
376 case GDK_KEY_KP_Multiply:
377 command.action = E_TEP_INSERT;
378 command.position = E_TEP_SELECTION;
379 command.value = 1;
380 command.string = "*";
381 break;
383 case GDK_KEY_KP_Add:
384 command.action = E_TEP_INSERT;
385 command.position = E_TEP_SELECTION;
386 command.value = 1;
387 command.string = "+";
388 break;
390 case GDK_KEY_KP_Subtract:
391 command.action = E_TEP_INSERT;
392 command.position = E_TEP_SELECTION;
393 command.value = 1;
394 command.string = "-";
395 break;
397 case GDK_KEY_KP_Decimal:
398 command.action = E_TEP_INSERT;
399 command.position = E_TEP_SELECTION;
400 command.value = 1;
401 command.string = ".";
402 break;
404 case GDK_KEY_KP_Divide:
405 command.action = E_TEP_INSERT;
406 command.position = E_TEP_SELECTION;
407 command.value = 1;
408 command.string = "/";
409 break;
411 case GDK_KEY_KP_0:
412 command.action = E_TEP_INSERT;
413 command.position = E_TEP_SELECTION;
414 command.value = 1;
415 command.string = "0";
416 break;
418 case GDK_KEY_KP_1:
419 command.action = E_TEP_INSERT;
420 command.position = E_TEP_SELECTION;
421 command.value = 1;
422 command.string = "1";
423 break;
425 case GDK_KEY_KP_2:
426 command.action = E_TEP_INSERT;
427 command.position = E_TEP_SELECTION;
428 command.value = 1;
429 command.string = "2";
430 break;
432 case GDK_KEY_KP_3:
433 command.action = E_TEP_INSERT;
434 command.position = E_TEP_SELECTION;
435 command.value = 1;
436 command.string = "3";
437 break;
439 case GDK_KEY_KP_4:
440 command.action = E_TEP_INSERT;
441 command.position = E_TEP_SELECTION;
442 command.value = 1;
443 command.string = "4";
444 break;
446 case GDK_KEY_KP_5:
447 command.action = E_TEP_INSERT;
448 command.position = E_TEP_SELECTION;
449 command.value = 1;
450 command.string = "5";
451 break;
453 case GDK_KEY_KP_6:
454 command.action = E_TEP_INSERT;
455 command.position = E_TEP_SELECTION;
456 command.value = 1;
457 command.string = "6";
458 break;
460 case GDK_KEY_KP_7:
461 command.action = E_TEP_INSERT;
462 command.position = E_TEP_SELECTION;
463 command.value = 1;
464 command.string = "7";
465 break;
467 case GDK_KEY_KP_8:
468 command.action = E_TEP_INSERT;
469 command.position = E_TEP_SELECTION;
470 command.value = 1;
471 command.string = "8";
472 break;
474 case GDK_KEY_KP_9:
475 command.action = E_TEP_INSERT;
476 command.position = E_TEP_SELECTION;
477 command.value = 1;
478 command.string = "9";
479 break;
481 default:
482 if ((key.state & GDK_CONTROL_MASK) &&
483 !(key.state & GDK_MOD1_MASK)) {
484 if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
485 key.keyval -= 'A' - 'a';
487 if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
488 command.position = control_keys[(gint) (key.keyval - 'a')].position;
489 if (control_keys[(gint) (key.keyval - 'a')].action != E_TEP_MOVE)
490 command.action = control_keys[(gint) (key.keyval - 'a')].action;
491 command.value = control_keys[(gint) (key.keyval - 'a')].value;
492 command.string = control_keys[(gint) (key.keyval - 'a')].string;
495 if (key.keyval == ' ') {
496 command.action = E_TEP_NOP;
499 if (key.keyval == 'x') {
500 command.action = E_TEP_COPY;
501 command.position = E_TEP_SELECTION;
502 g_signal_emit_by_name (tep, "command", &command);
504 command.action = E_TEP_DELETE;
505 command.position = E_TEP_SELECTION;
508 break;
510 } else if ((key.state & GDK_MOD1_MASK) &&
511 !(key.state & GDK_CONTROL_MASK)) {
512 if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
513 key.keyval -= 'A' - 'a';
515 if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
516 command.position = alt_keys[(gint) (key.keyval - 'a')].position;
517 if (alt_keys[(gint) (key.keyval - 'a')].action != E_TEP_MOVE)
518 command.action = alt_keys[(gint) (key.keyval - 'a')].action;
519 command.value = alt_keys[(gint) (key.keyval - 'a')].value;
520 command.string = alt_keys[(gint) (key.keyval - 'a')].string;
522 } else if (!(key.state & GDK_MOD1_MASK) &&
523 !(key.state & GDK_CONTROL_MASK) &&
524 key.length > 0) {
525 if (key.keyval >= GDK_KEY_KP_0 &&
526 key.keyval <= GDK_KEY_KP_9) {
527 key.keyval = '0';
528 key.string = "0";
530 command.action = E_TEP_INSERT;
531 command.position = E_TEP_SELECTION;
532 command.value = strlen (key.string);
533 command.string = key.string;
535 } else {
536 command.action = E_TEP_NOP;
539 break;
541 case GDK_KEY_RELEASE:
542 command.time = event->key.time;
543 command.action = E_TEP_NOP;
544 break;
546 default:
547 command.action = E_TEP_NOP;
548 break;
552 if (command.action != E_TEP_NOP) {
553 g_signal_emit_by_name (tep, "command", &command);
554 return 1;
555 } else
556 return 0;
559 ETextEventProcessor *
560 e_text_event_processor_emacs_like_new (void)
562 return g_object_new (E_TYPE_TEXT_EVENT_PROCESSOR_EMACS_LIKE, NULL);