aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/interface-gtk
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2024-09-12 13:55:40 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2024-09-12 16:44:13 +0200
commitabb5d23eba21a2aafda0346c0c5dd845561b2aa2 (patch)
tree9e42c1e72e0d61c322c0af8d54a9d740a7e2e45c /src/interface-gtk
parent73d574b71a10d4661ada20275cafde75aff6c1ba (diff)
downloadsciteco-abb5d23eba21a2aafda0346c0c5dd845561b2aa2.tar.gz
function key macros have been reworked into a more generic key macro feature
* ALL keypresses (the UTF-8 sequences resulting from key presses) can now be remapped. * This is especially useful with Unicode support, as you might want to alias international characters to their corresponding latin form in the start state, so you don't have to change keyboard layouts so often. This is done automatically in Gtk, where we have hardware key press information, but has to be done with key macros in Curses. There is a new key mask 4 (bit 3) for that purpose now. * Also, you might want to define non-ANSI letters to perform special functions in the start state where it won't be accepted by the parser anyway. Suppose you have a macro M→, you could define @^U[^K→]{m→} 1^_U[^K→] This effectively "extends" the parser and allow you to call macro "→" by a single key press. See also #5. * The register prefix has been changed from ^F (for function) to ^K (for key). This is the only thing you have to change in order to migrate existing function key macros. * Key macros are enabled by default. There is no longer any way to disable function key handling in curses, as I never found any reason or need to disable it. Theoretically, the default ESCDELAY could turn out to be too small and function keys don't get through. I doubt that's possible unless on extremely slow serial lines. Even then, you'd have to increase ESCDELAY and instead of disabling function keys simply define an escape surrogate. * The ED flag has been removed and its place is reserved for a future mouse support flag (which does make sense to disable in curses sometimes). fnkeys.tes is consequently also enabled by default in sample.teco_ini. * Key macros are handled as an unit. If one character results in an error, the entire string is rubbed out. This fixes the "CLOSE" key on Gtk. It also makes sure that the original error message is preserved and not overwritten by some subsequent syntax error. It was never useful that we kept inserting characters after the first error.
Diffstat (limited to 'src/interface-gtk')
-rw-r--r--src/interface-gtk/interface.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c
index 9c1ce6a..f19c76c 100644
--- a/src/interface-gtk/interface.c
+++ b/src/interface-gtk/interface.c
@@ -927,19 +927,19 @@ teco_interface_handle_key_press(GdkEventKey *event, GError **error)
switch (event->keyval) {
case GDK_KEY_Escape:
- if (!teco_cmdline_keypress_wc('\e', error))
+ if (!teco_cmdline_keymacro_c('\e', error))
return FALSE;
break;
case GDK_KEY_BackSpace:
- if (!teco_cmdline_keypress_wc(TECO_CTL_KEY('H'), error))
+ if (!teco_cmdline_keymacro_c(TECO_CTL_KEY('H'), error))
return FALSE;
break;
case GDK_KEY_Tab:
- if (!teco_cmdline_keypress_wc('\t', error))
+ if (!teco_cmdline_keymacro_c('\t', error))
return FALSE;
break;
case GDK_KEY_Return:
- if (!teco_cmdline_keypress_wc('\n', error))
+ if (!teco_cmdline_keymacro_c('\n', error))
return FALSE;
break;
@@ -948,12 +948,12 @@ teco_interface_handle_key_press(GdkEventKey *event, GError **error)
*/
#define FN(KEY, MACRO) \
case GDK_KEY_##KEY: \
- if (!teco_cmdline_fnmacro(#MACRO, error)) \
+ if (!teco_cmdline_keymacro(#MACRO, -1, error)) \
return FALSE; \
break
#define FNS(KEY, MACRO) \
case GDK_KEY_##KEY: \
- if (!teco_cmdline_fnmacro(event->state & GDK_SHIFT_MASK ? "S" #MACRO : #MACRO, error)) \
+ if (!teco_cmdline_keymacro(event->state & GDK_SHIFT_MASK ? "S" #MACRO : #MACRO, -1, error)) \
return FALSE; \
break
FN(Down, DOWN); FN(Up, UP);
@@ -965,8 +965,8 @@ teco_interface_handle_key_press(GdkEventKey *event, GError **error)
gchar macro_name[3+1];
g_snprintf(macro_name, sizeof(macro_name),
- "F%d", event->keyval - GDK_KEY_F1 + 1);
- if (!teco_cmdline_fnmacro(macro_name, error))
+ "F%d", event->keyval - GDK_KEY_F1 + 1);
+ if (!teco_cmdline_keymacro(macro_name, -1, error))
return FALSE;
break;
}
@@ -994,13 +994,35 @@ teco_interface_handle_key_press(GdkEventKey *event, GError **error)
if ((event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) == GDK_CONTROL_MASK) {
gchar c = teco_interface_get_ansi_key(event);
if (c) {
- if (!teco_cmdline_keypress_wc(TECO_CTL_KEY(g_ascii_toupper(c)), error))
+ if (!teco_cmdline_keymacro_c(TECO_CTL_KEY(g_ascii_toupper(c)), error))
return FALSE;
break;
}
}
/*
+ * First look up a key macro.
+ * Only if it's undefined, we try to automatically find an ANSI key.
+ * On the downside, this means we cannot define key macros for dead keys
+ * or keys that require some sort of input method editing.
+ *
+ * FIXME: This might be a good reason to be able to disable the
+ * automatic ANSIfication, as we could look up the key macro in
+ * teco_interface_cmdline_commit_cb().
+ */
+ gunichar cp = gdk_keyval_to_unicode(event->keyval);
+ if (cp) {
+ char buf[6];
+ gsize len = g_unichar_to_utf8(cp, buf);
+ teco_keymacro_status_t rc = teco_cmdline_keymacro(buf, len, error);
+ if (rc == TECO_KEYMACRO_ERROR)
+ return FALSE;
+ if (rc == TECO_KEYMACRO_SUCCESS)
+ break;
+ g_assert(rc == TECO_KEYMACRO_UNDEFINED);
+ }
+
+ /*
* If the current state is case-insensitive, it is a command name -
* which consists only of ANSI letters - we try to
* accept non-ANSI letters as well.
@@ -1010,10 +1032,11 @@ teco_interface_handle_key_press(GdkEventKey *event, GError **error)
* within Q-Register specs as well.
* Unfortunately, Q-Reg specs and string building can be nested
* indefinitely.
- * This would effectively require a new is_case_sensitive_cb().
+ * This would effectively require a new keymacro_mask_cb().
*/
- if (teco_cmdline.machine.parent.current->is_case_insensitive ||
- teco_cmdline.machine.expectstring.machine.parent.current->is_case_insensitive)
+ if ((teco_cmdline.machine.parent.current->keymacro_mask |
+ teco_cmdline.machine.expectstring.machine.parent.current->keymacro_mask) &
+ TECO_KEYMACRO_MASK_CASEINSENSITIVE)
teco_interface_get_ansi_key(event);
/*
@@ -1029,7 +1052,6 @@ teco_interface_handle_key_press(GdkEventKey *event, GError **error)
}
teco_interface_refresh(teco_interface_current_view != last_view);
-
return TRUE;
}