commit 53f769b1d999f6964bc2431b316cf07a3b8166ec
parent feafabfe8d714cc8d08d0000a91a7a6e8baf8492
Author: lumidify <nobody@lumidify.org>
Date: Thu, 7 Jul 2022 13:14:00 +0200
Check for XBufferOverflow when handling keys; misc fixes
Diffstat:
7 files changed, 58 insertions(+), 20 deletions(-)
diff --git a/keys.c b/keys.c
@@ -19,16 +19,31 @@
/* LockMask and Mod2Mask in particular are disabled (caps lock and numlock usually) */
static unsigned int importantmod = ShiftMask | ControlMask | Mod1Mask | Mod3Mask | Mod4Mask | Mod5Mask;
+#define KEY_TEXT_INITIAL_SIZE 32
+static char *key_text = NULL;
+static size_t key_text_alloc = 0;
+
+void
+key_processing_cleanup(void) {
+ free(key_text);
+}
+
int
match_key(unsigned int mask, unsigned int state)
{
return mask == XK_ANY_MOD || mask == (state & importantmod);
}
+#ifdef X_HAVE_UTF8_STRING
+#define LOOKUP_STRING_FUNC Xutf8LookupString
+#else
+#define LOOKUP_STRING_FUNC XmbLookupString
+#endif
+
void
preprocess_key(
- ledit_window *window, XEvent *event, KeySym *sym_ret,
- char *buf_ret, int buf_size, int *buf_len_ret) {
+ ledit_window *window, XKeyEvent *event, KeySym *sym_ret,
+ char **buf_ret, int *buf_len_ret) {
/*
* FIXME: I don't understand how key handling works with different keymaps.
* If, for instance, you run "setxkbmap pk" and then type "Ctrl+c", the
@@ -52,9 +67,29 @@ preprocess_key(
* keys don't use control in normal mode, and it just messes with all the
* keys that do use control because ledit does its own mapping.
*/
- event->xkey.state &= ~ControlMask;
- /* FIXME: X_HAVE_UTF8_STRING See XmbLookupString(3) */
- *buf_len_ret = Xutf8LookupString(
- window->xic, &event->xkey, buf_ret, buf_size, sym_ret, NULL
- );
+ if (key_text_alloc == 0) {
+ key_text = ledit_malloc(KEY_TEXT_INITIAL_SIZE);
+ key_text_alloc = KEY_TEXT_INITIAL_SIZE;
+ }
+ event->state &= ~ControlMask;
+
+ int len = 0;
+ Status status;
+ if (window->xic && event->type == KeyPress) {
+ len = LOOKUP_STRING_FUNC(window->xic, event, key_text, key_text_alloc - 1, sym_ret, &status);
+ if (status == XBufferOverflow) {
+ key_text_alloc = ideal_array_size(key_text_alloc, len + 1);
+ key_text = ledit_realloc(key_text, key_text_alloc);
+ len = LOOKUP_STRING_FUNC(window->xic, event, key_text, key_text_alloc - 1, sym_ret, &status);
+ }
+ } else {
+ /* FIXME: anything equivalent to XBufferOverflow here? */
+ len = XLookupString(event, key_text, key_text_alloc - 1, sym_ret, NULL);
+ status = XLookupBoth;
+ }
+ *buf_len_ret = len >= (int)key_text_alloc ? (int)key_text_alloc - 1 : len;
+ key_text[*buf_len_ret] = '\0';
+ if (status != XLookupBoth && status != XLookupKeySym)
+ *sym_ret = NoSymbol;
+ *buf_ret = key_text;
}
diff --git a/keys.h b/keys.h
@@ -15,9 +15,10 @@ int get_language_index(char *lang);
int match_key(unsigned int mask, unsigned int state);
/* preprocess key, i.e. get the KeySym and text corresponding to it */
void preprocess_key(
- ledit_window *window, XEvent *event, KeySym *sym_ret,
- char *buf_ret, int buf_size, int *buf_len_ret
+ ledit_window *window, XKeyEvent *event, KeySym *sym_ret,
+ char **buf_ret, int *buf_len_ret
);
+void key_processing_cleanup(void);
/* FIXME: documentation */
#define GEN_CB_MAP_HELPERS(name, typename, cmp_entry) \
diff --git a/keys_basic.c b/keys_basic.c
@@ -2622,12 +2622,12 @@ repeat_command(ledit_view *view, char *text, size_t len) {
struct action
basic_key_handler(ledit_view *view, XEvent *event, int lang_index) {
- char buf[64];
- KeySym sym;
+ char *buf = NULL;
+ KeySym sym = NoSymbol;
int n;
unsigned int key_state = event->xkey.state;
- preprocess_key(view->window, event, &sym, buf, sizeof(buf), &n);
+ preprocess_key(view->window, &event->xkey, &sym, &buf, &n);
struct repetition_stack_elem *re = push_repetition_stack();
re->key_text = ledit_strndup(buf, (size_t)n);
diff --git a/keys_command.c b/keys_command.c
@@ -214,6 +214,8 @@ static int parse_range(
);
static int handle_cmd(ledit_view *view, char *cmd, size_t len, size_t lang_index);
+/* FIXME: USE LEN EVERYWHERE INSTEAD OF RELYING ON cmd BEING NUL-TERMINATED */
+/* FIXME: return error so write_quit knows when to quit */
static int
handle_write(ledit_view *view, char *cmd, size_t l1, size_t l2) {
(void)l1;
@@ -946,13 +948,13 @@ edit_discard(ledit_view *view, char *key_text, size_t len, size_t lang_index) {
struct action
command_key_handler(ledit_view *view, XEvent *event, int lang_index) {
- char buf[64];
- KeySym sym;
+ char *buf = NULL;
+ KeySym sym = NoSymbol;
int n;
command_key_array *cur_keys = config_get_command_keys(lang_index);
size_t num_keys = cur_keys->num_keys;
unsigned int key_state = event->xkey.state;
- preprocess_key(view->window, event, &sym, buf, sizeof(buf), &n);
+ preprocess_key(view->window, &event->xkey, &sym, &buf, &n);
int grabkey = 1, found = 0;
command_key_cb_flags flags = KEY_FLAG_NONE;
for (size_t i = 0; i < num_keys; i++) {
diff --git a/ledit.c b/ledit.c
@@ -114,7 +114,6 @@ mainloop(void) {
change_kbd = 1;
continue;
}
- /* FIXME: why None? */
if (XFilterEvent(&event, None))
continue;
ledit_view *view = NULL;
@@ -450,6 +449,7 @@ ledit_cleanup(void) {
search_cleanup();
basic_key_cleanup();
command_key_cleanup();
+ key_processing_cleanup();
if (buffer)
buffer_destroy(buffer);
config_cleanup(&common);
diff --git a/leditrc.5 b/leditrc.5
@@ -619,12 +619,12 @@ Note that this command works with soft lines, regardless of the current mode.
.It Ar scroll-with-cursor-down Oo normal, insert Oc Oo num Oc
Move
.Ar num
-lines down, attemting to leave the cursor in its current line and character position.
+lines down, attempting to leave the cursor in its current line and character position.
Note that this command works with soft lines, regardless of the current mode.
.It Ar scroll-with-cursor-up Oo normal, insert Oc Oo num Oc
Move
.Ar num
-lines up, attemting to leave the cursor in its current line and character position.
+lines up, attempting to leave the cursor in its current line and character position.
Note that this command works with soft lines, regardless of the current mode.
.It Ar search-next Op normal, insert
Move to the next search result.
diff --git a/leditrc.example b/leditrc.example
@@ -221,7 +221,7 @@ language-mapping = {
map "^" "^"
}
command-mapping = {
- map "वग" "wq"
+ map "व" "wq"
map "व" "w"
map "" "q"
map "ड" "v"
@@ -293,7 +293,7 @@ language-mapping = {
map "^" "^"
}
command-mapping = {
- map "وگ" "wq"
+ map "وق" "wq"
map "و" "w"
map "ق" "q"
map "ط" "v"