tAdd support for Ctrl-c and Ctrl-v - ledit - Text editor (WIP) | |
git clone git://lumidify.org/ledit.git (fast, but not encrypted) | |
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow) | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 0ac206aa676b56346dd45906fe0379a1e845fb80 | |
parent 25deb9532df29d093281a2b542be2463809d7379 | |
Author: lumidify <[email protected]> | |
Date: Thu, 20 May 2021 21:37:00 +0200 | |
Add support for Ctrl-c and Ctrl-v | |
Diffstat: | |
M Makefile | 2 +- | |
M buffer.c | 54 ++++++++++++++++++++++++++---… | |
M buffer.h | 6 ++++++ | |
M ledit.c | 203 ++++++++++++++++++-----------… | |
4 files changed, 170 insertions(+), 95 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
t@@ -12,7 +12,7 @@ MAN1 = ${BIN:=.1} | |
OBJ = ${BIN:=.o} cache.o buffer.o memory.o | |
HDR = cache.h buffer.h memory.h common.h | |
-CFLAGS_LEDIT = ${CFLAGS} -g -Wall -Wextra -D_POSIX_C_SOURCE=200809L `pkg-confi… | |
+CFLAGS_LEDIT = -g -Wall -Wextra -D_POSIX_C_SOURCE=200809L `pkg-config --cflags… | |
LDFLAGS_LEDIT = ${LDFLAGS} `pkg-config --libs x11 xkbfile pangoxft xext` -lm | |
all: ${BIN} | |
diff --git a/buffer.c b/buffer.c | |
t@@ -1,3 +1,7 @@ | |
+/* FIXME: shrink buffers when text length less than a fourth of the size */ | |
+ | |
+#include <string.h> | |
+ | |
#include <X11/Xlib.h> | |
#include <X11/Xutil.h> | |
#include <pango/pangoxft.h> | |
t@@ -101,20 +105,49 @@ ledit_insert_text(ledit_buffer *buffer, int line_index, … | |
ledit_line *line = &buffer->lines[line_index]; | |
if (len == -1) | |
len = strlen(text); | |
- if (line->len + len > line->cap) { | |
- line->cap *= 2; | |
- if (line->cap == 0) | |
- line->cap = 2; | |
+ if (line->len + len > line->cap || line->text == NULL) { | |
+ /* FIXME: read up on what the best values are here */ | |
+ line->cap = line->cap * 2 > line->len + len ? line->cap * 2 : … | |
line->text = ledit_realloc(line->text, line->cap); | |
} | |
memmove(line->text + index + len, line->text + index, line->len - inde… | |
memcpy(line->text + index, text, len); | |
line->len += len; | |
pango_layout_set_text(line->layout, line->text, line->len); | |
- recalc_single_line_size(buffer, line_index); | |
+ /*recalc_single_line_size(buffer, line_index);*/ | |
line->dirty = 1; | |
} | |
+static void append_line_impl(ledit_buffer *buffer, int line_index, int text_in… | |
+ | |
+void | |
+ledit_insert_text_with_newlines( | |
+ ledit_buffer *buffer, | |
+ int line_index, int index, | |
+ char *text, int len, | |
+ int *end_line_ret, int *end_char_ret) { | |
+ if (len == -1) | |
+ len = strlen(text); | |
+ char *cur, *last = text; | |
+ int cur_line = line_index; | |
+ int cur_index = index; | |
+ while ((cur = strchr(last, '\n'))) { | |
+ ledit_insert_text(buffer, cur_line, cur_index, last, cur - las… | |
+ /* FIXME: inefficient because there's no gap buffer yet */ | |
+ append_line_impl(buffer, cur_line, -1); | |
+ cur_index = 0; | |
+ cur_line++; | |
+ last = cur + 1; | |
+ } | |
+ /* FIXME: check how legal this casting between pointers and ints is */ | |
+ ledit_insert_text(buffer, cur_line, cur_index, last, text + len - last… | |
+ if (end_line_ret) | |
+ *end_line_ret = cur_line; | |
+ if (end_char_ret) | |
+ *end_char_ret = cur_index + text + len - last; | |
+ recalc_line_size_absolute(buffer); /* FIXME: make this more efficient … | |
+} | |
+ | |
void | |
ledit_render_line(ledit_buffer *buffer, int line_index) { | |
/* FIXME: check for <= 0 on size */ | |
t@@ -171,8 +204,8 @@ init_line(ledit_buffer *buffer, ledit_line *line) { | |
} | |
/* FIXME: error checking (index out of bounds, etc.) */ | |
-void | |
-ledit_append_line(ledit_buffer *buffer, int line_index, int text_index) { | |
+static void | |
+append_line_impl(ledit_buffer *buffer, int line_index, int text_index) { | |
if (buffer->lines_num >= buffer->lines_cap) { | |
buffer->lines_cap *= 2; | |
if (buffer->lines_cap == 0) | |
t@@ -201,6 +234,11 @@ ledit_append_line(ledit_buffer *buffer, int line_index, i… | |
pango_layout_set_text(l->layout, l->text, l->len); | |
/* FIXME: set height here */ | |
} | |
+} | |
+ | |
+void | |
+ledit_append_line(ledit_buffer *buffer, int line_index, int text_index) { | |
+ append_line_impl(buffer, line_index, text_index); | |
recalc_line_size_absolute(buffer); | |
} | |
t@@ -281,7 +319,7 @@ ledit_delete_unicode_char(ledit_buffer *buffer, int line_i… | |
ledit_line *l = ledit_get_line(buffer, line_index); | |
int new_index = byte_index; | |
if (dir < 0) { | |
- int i = buffer->cur_index - 1; | |
+ int i = byte_index - 1; | |
/* find valid utf8 char - this probably needs to be improved */ | |
while (i > 0 && ((l->text[i] & 0xC0) == 0x80)) | |
i--; | |
diff --git a/buffer.h b/buffer.h | |
t@@ -44,6 +44,12 @@ void ledit_set_line_selection(ledit_buffer *buffer, int lin… | |
void ledit_set_line_cursor_attrs(ledit_buffer *buffer, int line, int index); | |
void ledit_wipe_line_cursor_attrs(ledit_buffer *buffer, int line); | |
void ledit_insert_text(ledit_buffer *buffer, int line_index, int index, char *… | |
+void ledit_insert_text_with_newlines( | |
+ ledit_buffer *buffer, | |
+ int line_index, int index, | |
+ char *text, int len, | |
+ int *end_line_ret, int *end_char_ret | |
+); | |
void ledit_render_line(ledit_buffer *buffer, int line_index); | |
void ledit_append_line(ledit_buffer *buffer, int line_index, int text_index); | |
void ledit_delete_line_entries(ledit_buffer *buffer, int index1, int index2); | |
diff --git a/ledit.c b/ledit.c | |
t@@ -1,3 +1,4 @@ | |
+/* FIXME: Fix lag when selecting with mouse */ | |
/* FIXME: Use PANGO_PIXELS() */ | |
/* FIXME: Fix cursor movement, especially buffer->trailing and writing at end … | |
/* FIXME: horizontal scrolling (also need cache to avoid too large pixmaps) */ | |
t@@ -43,6 +44,7 @@ enum key_type { | |
struct key { | |
char *text; /* for keys that correspond with text */ | |
+ unsigned int mods; /* modifier mask */ | |
KeySym keysym; /* for other keys, e.g. arrow keys */ | |
enum ledit_mode modes; /* modes in which this keybinding is function… | |
enum key_type prev_keys; /* allowed previous keys */ | |
t@@ -240,23 +242,12 @@ selnotify(XEvent *e) | |
continue; | |
} | |
- /* FIXME: Is this needed for ledit? I don't think so, right? */ | |
- /* | |
- * As seen in getsel: | |
- * Line endings are inconsistent in the terminal and GUI world | |
- * copy and pasting. When receiving some selection data, | |
- * replace all '\n' with '\r'. | |
- * FIXME: Fix the computer world. | |
- */ | |
- /* | |
- repl = data; | |
- last = data + nitems * format / 8; | |
- while ((repl = memchr(repl, '\n', last - repl))) { | |
- *repl++ = '\r'; | |
- } | |
- */ | |
- | |
- printf("%.*s\n", (int)(nitems * format / 8), (char*)data); | |
+ ledit_insert_text_with_newlines( | |
+ buffer, | |
+ buffer->cur_line, buffer->cur_index, | |
+ (char*)data, (int)(nitems * format / 8), | |
+ &buffer->cur_line, &buffer->cur_index | |
+ ); | |
XFree(data); | |
/* number of 32-bit chunks returned */ | |
ofs += nitems * format / 32; | |
t@@ -670,9 +661,11 @@ mainloop(void) { | |
running = 0; | |
break; | |
case SelectionNotify: | |
+ need_redraw = 1; | |
selnotify(&event); | |
break; | |
case PropertyNotify: | |
+ need_redraw = 1; | |
propnotify(&event); | |
break; | |
case SelectionRequest: | |
t@@ -1011,6 +1004,7 @@ sort_selection(int *line1, int *byte1, int *line2, int *… | |
} | |
} | |
+/* FIXME: don't reset selection when selection is clicked away */ | |
/* FIXME: when selecting with mouse, only call this when button is released */ | |
/* lines and bytes need to be sorted already! */ | |
static void | |
t@@ -1240,9 +1234,10 @@ backspace(void) { | |
ledit_line *l1 = ledit_get_line(buffer, buffer->cur_li… | |
ledit_line *l2 = ledit_get_line(buffer, buffer->cur_li… | |
int old_len = l1->len; | |
- ledit_insert_text( | |
+ ledit_insert_text_with_newlines( | |
buffer, buffer->cur_line - 1, | |
- l1->len, l2->text, l2->len | |
+ l1->len, l2->text, l2->len, | |
+ NULL, NULL | |
); | |
ledit_delete_line_entry(buffer, buffer->cur_line); | |
buffer->cur_line--; | |
t@@ -1267,9 +1262,10 @@ delete_key(void) { | |
buffer, buffer->cur_line + 1 | |
); | |
int old_len = cur_line->len; | |
- ledit_insert_text( | |
+ ledit_insert_text_with_newlines( | |
buffer, buffer->cur_line, cur_line->len, | |
- next_line->text, next_line->len | |
+ next_line->text, next_line->len, | |
+ NULL, NULL | |
); | |
ledit_delete_line_entry(buffer, buffer->cur_line + 1); | |
buffer->cur_index = old_len; | |
t@@ -1338,7 +1334,7 @@ move_cursor_left_right(int dir) { | |
new_index = cur_line->len; | |
} | |
} | |
- if (e != NULL & e->motion_cb != NULL) { | |
+ if (e != NULL && e->motion_cb != NULL) { | |
e->motion_cb(buffer->cur_line, new_index, KEY_MOTION_CHAR); | |
} else { | |
buffer->cur_index = new_index; | |
t@@ -1473,7 +1469,7 @@ static void | |
cursor_to_beginning(void) { | |
struct key_stack_elem *e = pop_key_stack(); | |
/* FIXME: error when no callback? */ | |
- if (e != NULL & e->motion_cb != NULL) { | |
+ if (e != NULL && e->motion_cb != NULL) { | |
e->motion_cb(buffer->cur_line, 0, KEY_MOTION_CHAR); | |
} else { | |
buffer->cur_index = 0; | |
t@@ -1508,71 +1504,75 @@ switch_selection_end(void) { | |
buffer->cur_index = buffer->sel.byte2; | |
} | |
+#define XK_ANY_MOD UINT_MAX | |
+#define XK_NO_MOD 0 | |
+ | |
static struct key keys_en[] = { | |
- {NULL, XK_BackSpace, INSERT, KEY_ANY, KEY_ANY, &backspace}, | |
- {NULL, XK_Left, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_left}, | |
- {NULL, XK_Right, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_right… | |
- {NULL, XK_Up, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_up}, | |
- {NULL, XK_Down, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_down}, | |
- {NULL, XK_Return, INSERT, KEY_ANY, KEY_ANY, &return_key}, | |
- {NULL, XK_Delete, INSERT, KEY_ANY, KEY_ANY, &delete_key}, | |
- {NULL, XK_Escape, VISUAL|INSERT, KEY_ANY, KEY_ANY, &escape_key}, | |
- {"i", 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &enter_insert}, | |
- {"h", 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cur… | |
- {"l", 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cur… | |
- {"j", 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cur… | |
- {"k", 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cur… | |
- {"0", 0, NORMAL|VISUAL, ~KEY_NUMBER, KEY_ANY, &cursor_to_beginning}, | |
- {"0", 0, NORMAL|VISUAL, KEY_NUMBER, KEY_NUMBER, &push_0}, | |
- {"1", 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_1}, | |
- {"2", 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_2}, | |
- {"3", 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_3}, | |
- {"4", 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_4}, | |
- {"5", 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_5}, | |
- {"6", 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_6}, | |
- {"7", 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_7}, | |
- {"8", 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_8}, | |
- {"9", 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_9}, | |
- {"x", 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &key_x}, | |
- {"d", 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &key_d… | |
- {"v", 0, NORMAL, KEY_ANY, KEY_ANY, &enter_visual}, | |
- {"o", 0, VISUAL, KEY_ANY, KEY_ANY, &switch_selection_end}, | |
- {"y", 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &clipcopy}, | |
- {"p", 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &clippaste} | |
+ {NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ANY, &backspace}, | |
+ {NULL, 0, XK_Left, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_lef… | |
+ {NULL, 0, XK_Right, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_ri… | |
+ {NULL, 0, XK_Up, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_up}, | |
+ {NULL, 0, XK_Down, VISUAL|INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_dow… | |
+ {NULL, 0, XK_Return, INSERT, KEY_ANY, KEY_ANY, &return_key}, | |
+ {NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ANY, &delete_key}, | |
+ {NULL, 0, XK_Escape, VISUAL|INSERT, KEY_ANY, KEY_ANY, &escape_key}, | |
+ {"i", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_ANY, &enter_insert}, | |
+ {"h", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &… | |
+ {"l", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &… | |
+ {"j", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &… | |
+ {"k", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &… | |
+ {"0", 0, 0, NORMAL|VISUAL, ~KEY_NUMBER, KEY_ANY, &cursor_to_beginning… | |
+ {"0", 0, 0, NORMAL|VISUAL, KEY_NUMBER, KEY_NUMBER, &push_0}, | |
+ {"1", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_1}, | |
+ {"2", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_2}, | |
+ {"3", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_3}, | |
+ {"4", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_4}, | |
+ {"5", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_5}, | |
+ {"6", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_6}, | |
+ {"7", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_7}, | |
+ {"8", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_8}, | |
+ {"9", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_NUMBER, &push_9}, | |
+ {"x", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &key_x}, | |
+ {"d", 0, 0, NORMAL|VISUAL, KEY_ANY, KEY_MOTION|KEY_NUMBERALLOWED, &ke… | |
+ {"v", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_visual}, | |
+ {"o", 0, 0, VISUAL, KEY_ANY, KEY_ANY, &switch_selection_end}, | |
+ {"c", ControlMask, 0, INSERT|VISUAL, KEY_ANY, KEY_ANY, &clipcopy}, | |
+ {"v", ControlMask, 0, INSERT, KEY_ANY, KEY_ANY, &clippaste} | |
}; | |
static struct key keys_ur[] = { | |
- {NULL, XK_BackSpace, INSERT, KEY_ANY, KEY_ANY, &backspace}, | |
- {NULL, XK_Left, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_left}, | |
- {NULL, XK_Right, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_right}, | |
- {NULL, XK_Up, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_up}, | |
- {NULL, XK_Down, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_down}, | |
- {NULL, XK_Return, INSERT, KEY_ANY, KEY_ANY, &return_key}, | |
- {NULL, XK_Delete, INSERT, KEY_ANY, KEY_ANY, &delete_key}, | |
- {NULL, XK_Escape, INSERT, KEY_ANY, KEY_ANY, &escape_key}, | |
- {"ی", 0, NORMAL, KEY_ANY, KEY_ANY, &enter_insert}, | |
- {"ح", 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_le… | |
- {"ل", 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_ri… | |
- {"ج", 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_do… | |
- {"ک", 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_up… | |
- {"0", 0, NORMAL, KEY_ANY, KEY_ANY, &cursor_to_beginning} | |
+ {NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ANY, &backspace}, | |
+ {NULL, 0, XK_Left, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_left}, | |
+ {NULL, 0, XK_Right, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_right}, | |
+ {NULL, 0, XK_Up, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_up}, | |
+ {NULL, 0, XK_Down, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_down}, | |
+ {NULL, 0, XK_Return, INSERT, KEY_ANY, KEY_ANY, &return_key}, | |
+ {NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ANY, &delete_key}, | |
+ {NULL, 0, XK_Escape, INSERT, KEY_ANY, KEY_ANY, &escape_key}, | |
+ {"ی", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_insert}, | |
+ {"ح", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor… | |
+ {"ل", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor… | |
+ {"ج", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor… | |
+ {"ک", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor… | |
+ {"0", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &cursor_to_beginning}, | |
+ {"چ", ControlMask, 0, INSERT|VISUAL, KEY_ANY, KEY_ANY, &clipcopy} | |
}; | |
static struct key keys_hi[] = { | |
- {NULL, XK_BackSpace, INSERT, KEY_ANY, KEY_ANY, &backspace}, | |
- {NULL, XK_Left, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_left}, | |
- {NULL, XK_Right, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_right}, | |
- {NULL, XK_Up, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_up}, | |
- {NULL, XK_Down, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_down}, | |
- {NULL, XK_Return, INSERT, KEY_ANY, KEY_ANY, &return_key}, | |
- {NULL, XK_Delete, INSERT, KEY_ANY, KEY_ANY, &delete_key}, | |
- {NULL, XK_Escape, INSERT, KEY_ANY, KEY_ANY, &escape_key}, | |
- {"ि", 0, NORMAL, KEY_ANY, KEY_ANY, &enter_insert}, | |
- {"ह", 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_l… | |
- {"ल", 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_r… | |
- {"ज", 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_d… | |
- {"क", 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &cursor_u… | |
- {"0", 0, NORMAL, KEY_ANY, KEY_ANY, &cursor_to_beginning} | |
+ {NULL, 0, XK_BackSpace, INSERT, KEY_ANY, KEY_ANY, &backspace}, | |
+ {NULL, 0, XK_Left, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_left}, | |
+ {NULL, 0, XK_Right, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_right}, | |
+ {NULL, 0, XK_Up, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_up}, | |
+ {NULL, 0, XK_Down, INSERT|NORMAL, KEY_ANY, KEY_ANY, &cursor_down}, | |
+ {NULL, 0, XK_Return, INSERT, KEY_ANY, KEY_ANY, &return_key}, | |
+ {NULL, 0, XK_Delete, INSERT, KEY_ANY, KEY_ANY, &delete_key}, | |
+ {NULL, 0, XK_Escape, INSERT, KEY_ANY, KEY_ANY, &escape_key}, | |
+ {"ि", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &enter_insert}, | |
+ {"ह", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &curso… | |
+ {"ल", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &curso… | |
+ {"ज", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &curso… | |
+ {"क", 0, 0, NORMAL, KEY_ANY, KEY_MOTION | KEY_NUMBERALLOWED, &curso… | |
+ {"0", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &cursor_to_beginning} | |
}; | |
#define LENGTH(X) (sizeof(X) / sizeof(X[0])) | |
t@@ -1602,10 +1602,37 @@ static void change_keyboard(char *lang) { | |
} | |
} | |
+/* FIXME: Does this break anything? */ | |
+static unsigned int importantmod = ShiftMask | ControlMask | Mod1Mask | Mod2Ma… | |
+ | |
+static int | |
+match(unsigned int mask, unsigned int state) | |
+{ | |
+ return mask == XK_ANY_MOD || mask == (state & importantmod); | |
+} | |
+ | |
static void | |
key_press(XEvent event) { | |
char buf[32]; | |
KeySym sym; | |
+ /* | |
+ * FIXME: I don't understand how key handling works with different key… | |
+ * If, for instance, you run "setxkbmap pk" and then type "Ctrl+c", the | |
+ * keysym will be "0x1000686, Arabic_tcheh" and the appropriate string… | |
+ * be returned by XmbLookupString (tested also using xev). | |
+ * If, however, you run "setxkbmap -layout "us,pk" -option grp:shifts_… | |
+ * and type "Ctrl+c" after switching to the pk layout, the keysym will… | |
+ * be "0x63, c" and XmbLookupString will return the control code sent … | |
+ * Ctrl+c (ascii 03). This means the handling is different depending o… | |
+ * the keymap is switched to, and I have no clue what the proper way to | |
+ * handle this would be, since the shortcuts are explicitly supposed t… | |
+ * properly in all language maps. My current solution is to just ignor… | |
+ * control key in the state so the text found by Xutf8LookupString is … | |
+ * and the modifier mask can be checked separately. Please tell me if … | |
+ * know the proper way to do this. | |
+ */ | |
+ unsigned int key_state = event.xkey.state; | |
+ event.xkey.state &= ~ControlMask; | |
/* FIXME: X_HAVE_UTF8_STRING See XmbLookupString(3) */ | |
int n = Xutf8LookupString( | |
state.xic, &event.xkey, buf, sizeof(buf), &sym, NULL | |
t@@ -1617,12 +1644,14 @@ key_press(XEvent event) { | |
if (n > 0 && | |
(cur_keys->keys[i].modes & state.mode) && | |
(!e || (e->key & cur_keys->keys[i].prev_keys)) && | |
- !strncmp(cur_keys->keys[i].text, buf, n)) { | |
+ !strncmp(cur_keys->keys[i].text, buf, n) && | |
+ match(cur_keys->keys[i].mods, key_state)) { | |
cur_keys->keys[i].func(); | |
found = 1; | |
} | |
} else if ((cur_keys->keys[i].modes & state.mode) && | |
- cur_keys->keys[i].keysym == sym) { | |
+ cur_keys->keys[i].keysym == sym && | |
+ match(cur_keys->keys[i].mods, key_state)) { | |
cur_keys->keys[i].func(); | |
found = 1; | |
} | |
t@@ -1631,10 +1660,12 @@ key_press(XEvent event) { | |
} | |
if (state.mode == INSERT && !found && n > 0) { | |
delete_selection(); | |
- ledit_insert_text( | |
- buffer, buffer->cur_line, buffer->cur_index, buf, n | |
+ ledit_insert_text_with_newlines( | |
+ buffer, | |
+ buffer->cur_line, buffer->cur_index, | |
+ buf, n, | |
+ &buffer->cur_line, &buffer->cur_index | |
); | |
- buffer->cur_index += n; | |
} | |
ensure_cursor_shown(); | |
} |