aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/e-text-event-processor-emacs-like.c
diff options
context:
space:
mode:
Diffstat (limited to 'widgets/e-text-event-processor-emacs-like.c')
-rw-r--r--widgets/e-text-event-processor-emacs-like.c327
1 files changed, 327 insertions, 0 deletions
diff --git a/widgets/e-text-event-processor-emacs-like.c b/widgets/e-text-event-processor-emacs-like.c
new file mode 100644
index 0000000000..1d7d36d45f
--- /dev/null
+++ b/widgets/e-text-event-processor-emacs-like.c
@@ -0,0 +1,327 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* e-text-event-processor.c
+ * Copyright (C) 2000 Helix Code, Inc.
+ * Author: Chris Lahey <clahey@helixcode.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gnome.h>
+#include "e-text-event-processor-emacs-like.h"
+static void e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *card);
+static void e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass);
+static gint e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
+
+static ETextEventProcessorClass *parent_class = NULL;
+
+/* The arguments we take */
+enum {
+ ARG_0
+};
+
+static const ETextEventProcessorCommand control_keys[26] =
+{
+ { E_TEP_START_OF_LINE, E_TEP_MOVE, 0, "" }, /* a */
+ { E_TEP_BACKWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* b */
+ { E_TEP_SELECTION, E_TEP_COPY, 0, "" }, /* c */
+ { E_TEP_FORWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* d */
+ { E_TEP_END_OF_LINE, E_TEP_MOVE, 0, "" }, /* e */
+ { E_TEP_FORWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* f */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
+ { E_TEP_BACKWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* h */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
+ { E_TEP_END_OF_LINE, E_TEP_DELETE, 0, "" }, /* k */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
+ { E_TEP_FORWARD_LINE, E_TEP_MOVE, 0, "" }, /* n */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
+ { E_TEP_BACKWARD_LINE, E_TEP_MOVE, 0, "" }, /* p */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
+ { E_TEP_START_OF_LINE, E_TEP_DELETE, 0, "" }, /* u */
+ { E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* v */
+ { E_TEP_BACKWARD_WORD, E_TEP_DELETE, 0, "" }, /* w */
+ { E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* x */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
+};
+
+static const ETextEventProcessorCommand alt_keys[26] =
+{
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* a */
+ { E_TEP_BACKWARD_WORD, E_TEP_MOVE, 0, "" }, /* b */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* c */
+ { E_TEP_FORWARD_WORD, E_TEP_DELETE, 0, "" }, /* d */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* e */
+ { E_TEP_FORWARD_WORD, E_TEP_MOVE, 0, "" }, /* f */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* h */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* k */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* n */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* p */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* u */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* v */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* w */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* x */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
+ { E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
+
+};
+
+GtkType
+e_text_event_processor_emacs_like_get_type (void)
+{
+ static GtkType text_event_processor_emacs_like_type = 0;
+
+ if (!text_event_processor_emacs_like_type)
+ {
+ static const GtkTypeInfo text_event_processor_emacs_like_info =
+ {
+ "ETextEventProcessorEmacsLike",
+ sizeof (ETextEventProcessorEmacsLike),
+ sizeof (ETextEventProcessorEmacsLikeClass),
+ (GtkClassInitFunc) e_text_event_processor_emacs_like_class_init,
+ (GtkObjectInitFunc) e_text_event_processor_emacs_like_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ text_event_processor_emacs_like_type = gtk_type_unique (e_text_event_processor_get_type (), &text_event_processor_emacs_like_info);
+ }
+
+ return text_event_processor_emacs_like_type;
+}
+
+static void
+e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass)
+{
+ GtkObjectClass *object_class;
+ ETextEventProcessorClass *processor_class;
+
+ object_class = (GtkObjectClass*) klass;
+ processor_class = (ETextEventProcessorClass*) klass;
+
+ parent_class = gtk_type_class (e_text_event_processor_get_type ());
+
+ processor_class->event = e_text_event_processor_emacs_like_event;
+}
+
+static void
+e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *tep)
+{
+}
+
+static gint
+e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event)
+{
+ ETextEventProcessorCommand command;
+ ETextEventProcessorEmacsLike *tep_el = E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(tep);
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ if (event->button.button == 1) {
+ if (event->button.state & GDK_SHIFT_MASK)
+ command.action = E_TEP_SELECT;
+ else
+ command.action = E_TEP_MOVE;
+ command.position = E_TEP_VALUE;
+ command.value = event->button.position;
+ tep_el->mouse_down = TRUE;
+ }
+ break;
+ case GDK_BUTTON_RELEASE:
+ if (event->button.button == 1) {
+ tep_el->mouse_down = FALSE;
+ }
+ break;
+ case GDK_MOTION_NOTIFY:
+ if (tep_el->mouse_down) {
+ command.action = E_TEP_SELECT;
+ command.position = E_TEP_VALUE;
+ command.value = event->motion.position;
+ }
+ break;
+ case GDK_KEY_PRESS:
+ {
+ ETextEventProcessorEventKey key = event->key;
+ if (key.state & GDK_SHIFT_MASK)
+ command.action = E_TEP_SELECT;
+ else
+ command.action = E_TEP_MOVE;
+ switch(key.keyval) {
+ case GDK_Home:
+ if (key.state & GDK_CONTROL_MASK)
+ command.position = E_TEP_START_OF_BUFFER;
+ else
+ command.position = E_TEP_START_OF_LINE;
+ break;
+ case GDK_End:
+ if (key.state & GDK_CONTROL_MASK)
+ command.position = E_TEP_END_OF_BUFFER;
+ else
+ command.position = E_TEP_END_OF_LINE;
+ break;
+ case GDK_Page_Up: command.position = E_TEP_BACKWARD_PAGE; break;
+ case GDK_Page_Down: command.position = E_TEP_FORWARD_PAGE; break;
+ /* CUA has Ctrl-Up/Ctrl-Down as paragraph up down */
+ case GDK_Up: command.position = E_TEP_BACKWARD_LINE; break;
+ case GDK_Down: command.position = E_TEP_FORWARD_LINE; break;
+ case GDK_Left:
+ if (key.state & GDK_CONTROL_MASK)
+ command.position = E_TEP_BACKWARD_WORD;
+ else
+ command.position = E_TEP_BACKWARD_CHARACTER;
+ break;
+ case GDK_Right:
+ if (key.state & GDK_CONTROL_MASK)
+ command.position = E_TEP_FORWARD_WORD;
+ else
+ command.position = E_TEP_FORWARD_CHARACTER;
+ break;
+
+ case GDK_BackSpace:
+ command.action = E_TEP_DELETE;
+ if (key.state & GDK_CONTROL_MASK)
+ command.position = E_TEP_BACKWARD_WORD;
+ else
+ command.position = E_TEP_BACKWARD_CHARACTER;
+ break;
+ case GDK_Clear:
+ command.action = E_TEP_DELETE;
+ command.position = E_TEP_END_OF_LINE;
+ break;
+ case GDK_Insert:
+ if (key.state & GDK_SHIFT_MASK) {
+ command.action = E_TEP_PASTE;
+ command.position = E_TEP_SELECTION;
+ } else if (key.state & GDK_CONTROL_MASK) {
+ command.action = E_TEP_COPY;
+ command.position = E_TEP_SELECTION;
+ } else {
+ /* gtk_toggle_insert(text) -- IMPLEMENT */
+ }
+ break;
+ case GDK_Delete:
+ if (key.state & GDK_CONTROL_MASK){
+ command.action = E_TEP_DELETE;
+ command.position = E_TEP_FORWARD_WORD;
+ } else if (key.state & GDK_SHIFT_MASK) {
+ command.action = E_TEP_COPY;
+
+ command.action = E_TEP_DELETE;
+ command.position = E_TEP_SELECTION;
+ } else {
+ command.action = E_TEP_DELETE;
+ command.position = E_TEP_FORWARD_CHARACTER;
+ }
+ break;
+ case GDK_Tab:
+ command.action = E_TEP_INSERT;
+ command.position = E_TEP_SELECTION;
+ command.value = 1;
+ command.string = "\t";
+ break;
+ case GDK_Return:
+ if (key.state & GDK_CONTROL_MASK) {
+ command.action = E_TEP_ACTIVATE;
+ command.position = E_TEP_SELECTION;
+ } else {
+ command.action = E_TEP_INSERT;
+ command.position = E_TEP_SELECTION;
+ command.value = 1;
+ command.string = "\n";
+ }
+ break;
+ case GDK_Escape:
+ command.action = E_TEP_NOP;
+ command.position = E_TEP_SELECTION;
+ /* Don't insert literally */
+ break;
+
+ default:
+ if (key.state & GDK_CONTROL_MASK) {
+ if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
+ key.keyval -= 'A' - 'a';
+
+ if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
+ command.position = control_keys[(int) (key.keyval - 'a')].position;
+ if (control_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
+ command.action = control_keys[(int) (key.keyval - 'a')].action;
+ command.value = control_keys[(int) (key.keyval - 'a')].value;
+ command.string = control_keys[(int) (key.keyval - 'a')].string;
+ }
+
+ if (key.keyval == 'x') {
+ }
+
+ break;
+ } else if (key.state & GDK_MOD1_MASK) {
+ if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
+ key.keyval -= 'A' - 'a';
+
+ if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
+ command.position = alt_keys[(int) (key.keyval - 'a')].position;
+ if (alt_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
+ command.action = alt_keys[(int) (key.keyval - 'a')].action;
+ command.value = alt_keys[(int) (key.keyval - 'a')].value;
+ command.string = alt_keys[(int) (key.keyval - 'a')].string;
+ }
+ } else if (key.length > 0) {
+ command.action = E_TEP_INSERT;
+ command.position = E_TEP_SELECTION;
+ command.value = strlen(key.string);
+ command.string = key.string;
+
+ } else {
+ command.action = E_TEP_NOP;
+ }
+ }
+ break;
+ case GDK_KEY_RELEASE:
+ command.action = E_TEP_NOP;
+ break;
+ default:
+ command.action = E_TEP_NOP;
+ break;
+ }
+ }
+ if (command.action != E_TEP_NOP) {
+ gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+ETextEventProcessor *
+e_text_event_processor_emacs_like_new (void)
+{
+ ETextEventProcessorEmacsLike *retval = gtk_type_new (e_text_event_processor_emacs_like_get_type ());
+ return E_TEXT_EVENT_PROCESSOR (retval);
+}
+