aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/interface-gtk/interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interface-gtk/interface.c')
-rw-r--r--src/interface-gtk/interface.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c
index 544ff22..ae1dd74 100644
--- a/src/interface-gtk/interface.c
+++ b/src/interface-gtk/interface.c
@@ -75,6 +75,7 @@ static void teco_interface_popup_clicked_cb(GtkWidget *popup, gchar *str, gulong
static gboolean teco_interface_window_delete_cb(GtkWidget *widget, GdkEventAny *event,
gpointer user_data);
static gboolean teco_interface_sigterm_handler(gpointer user_data) G_GNUC_UNUSED;
+static gchar teco_interface_get_ansi_key(GdkEventKey *event);
/**
* Interval between polling for keypresses.
@@ -423,6 +424,103 @@ teco_interface_msg_clear(void)
teco_gtk_label_set_text(TECO_GTK_LABEL(teco_interface.message_widget), "", 0);
}
+static void
+teco_interface_getch_commit_cb(GtkIMContext *context, gchar *str, gpointer user_data)
+{
+ teco_int_t *cp = user_data;
+
+ /*
+ * FIXME: What if str contains several characters?
+ */
+ *cp = g_utf8_get_char_validated(str, -1);
+ g_assert(*cp >= 0);
+ gtk_main_quit();
+}
+
+/*
+ * FIXME: Redundancies with teco_interface_handle_keypress()
+ * FIXME: Report function keys
+ */
+static gboolean
+teco_interface_getch_input_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data)
+{
+ teco_int_t *cp = user_data;
+
+ g_assert(event->type == GDK_KEY_PRESS);
+
+ switch (event->key.keyval) {
+ case GDK_KEY_Escape: *cp = '\e'; break;
+ case GDK_KEY_BackSpace: *cp = TECO_CTL_KEY('H'); break;
+ case GDK_KEY_Tab: *cp = '\t'; break;
+ case GDK_KEY_Return: *cp = '\n'; break;
+ default:
+ /*
+ * NOTE: Alt-Gr key-combinations are sometimes reported as
+ * Ctrl+Alt, so we filter those out.
+ */
+ if ((event->key.state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) == GDK_CONTROL_MASK &&
+ (*cp = teco_interface_get_ansi_key(&event->key))) {
+ *cp = TECO_CTL_KEY(g_ascii_toupper(*cp));
+ switch (*cp) {
+ case TECO_CTL_KEY('C'):
+ teco_interrupted = TRUE;
+ /* fall through */
+ case TECO_CTL_KEY('D'):
+ *cp = -1;
+ }
+ break;
+ }
+
+ gtk_im_context_filter_keypress(teco_interface.input_method, &event->key);
+ return TRUE;
+ }
+
+ gtk_main_quit();
+ return TRUE;
+}
+
+teco_int_t
+teco_interface_getch(gboolean widechar)
+{
+ if (!gtk_main_level())
+ /* batch mode */
+ return teco_interface_stdio_getch(widechar);
+
+ teco_int_t cp = -1;
+ gulong key_handler, commit_handler;
+
+ /* temporarily replace the "key-press-event" and "commit" handlers */
+ g_signal_handlers_block_by_func(teco_interface.window,
+ teco_interface_input_cb, NULL);
+ key_handler = g_signal_connect(teco_interface.window, "key-press-event",
+ G_CALLBACK(teco_interface_getch_input_cb), &cp);
+ g_signal_handlers_block_by_func(teco_interface.input_method,
+ teco_interface_cmdline_commit_cb, NULL);
+ commit_handler = g_signal_connect(teco_interface.input_method, "commit",
+ G_CALLBACK(teco_interface_getch_commit_cb), &cp);
+
+ /*
+ * Highlights the first character in the label.
+ * This mimics what the Curses UI does.
+ * Is there a better way to signal that we expect input?
+ */
+ teco_gtk_label_highlight_getch(TECO_GTK_LABEL(teco_interface.message_widget));
+
+ GdkWindow *top_window = gdk_window_get_toplevel(gtk_widget_get_window(teco_interface.window));
+ gdk_window_thaw_updates(top_window);
+
+ gtk_main();
+
+ gdk_window_freeze_updates(top_window);
+
+ g_signal_handler_disconnect(teco_interface.input_method, commit_handler);
+ g_signal_handlers_unblock_by_func(teco_interface.input_method, teco_interface_cmdline_commit_cb, NULL);
+ g_signal_handler_disconnect(teco_interface.window, key_handler);
+ g_signal_handlers_unblock_by_func(teco_interface.window, teco_interface_input_cb, NULL);
+
+ return cp;
+}
+
void
teco_interface_show_view(teco_view_t *view)
{