diff options
| -rw-r--r-- | src/buffer.c | 34 | ||||
| -rw-r--r-- | src/buffer.h | 5 | ||||
| -rw-r--r-- | src/display.c | 19 | ||||
| -rw-r--r-- | src/keyboard.c | 61 | ||||
| -rw-r--r-- | src/keyboard.h | 2 | ||||
| -rw-r--r-- | src/main.c | 9 |
6 files changed, 93 insertions, 37 deletions
diff --git a/src/buffer.c b/src/buffer.c index 2e54d30..5cf1cb8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -3,6 +3,7 @@ #include "display.h" #include "minibuffer.h" #include "reactor.h" +#include "utf8.h" #include <fcntl.h> #include <stdbool.h> @@ -11,6 +12,7 @@ #include <string.h> #include <time.h> #include <unistd.h> +#include <wchar.h> struct update_hook_result buffer_linenum_hook(struct buffer *buffer, struct command_list *commands, @@ -41,22 +43,23 @@ struct buffer buffer_create(const char *name, bool modeline) { b.keymaps[0] = keymap_create("buffer-default", 128); struct binding bindings[] = { BINDING(Ctrl, 'B', "backward-char"), - BINDING(Meta, 'D', "backward-char"), + BINDING(Spec, 'D', "backward-char"), BINDING(Ctrl, 'F', "forward-char"), - BINDING(Meta, 'C', "forward-char"), + BINDING(Spec, 'C', "forward-char"), BINDING(Ctrl, 'P', "backward-line"), - BINDING(Meta, 'A', "backward-line"), + BINDING(Spec, 'A', "backward-line"), BINDING(Ctrl, 'N', "forward-line"), - BINDING(Meta, 'B', "forward-line"), + BINDING(Spec, 'B', "forward-line"), BINDING(Ctrl, 'A', "beginning-of-line"), BINDING(Ctrl, 'E', "end-of-line"), BINDING(Ctrl, 'M', "newline"), + BINDING(Ctrl, 'I', "indent"), BINDING(Ctrl, 'K', "kill-line"), - BINDING(Meta, '~', "delete-char"), + BINDING(Spec, '3', "delete-char"), BINDING(Ctrl, '?', "backward-delete-char"), }; keymap_bind_keys(&b.keymaps[0], bindings, @@ -240,6 +243,10 @@ void buffer_newline(struct buffer *buffer) { buffer_add_text(buffer, (uint8_t *)"\n", 1); } +void buffer_indent(struct buffer *buffer) { + buffer_add_text(buffer, (uint8_t *)" ", 4); +} + uint32_t buffer_add_update_hook(struct buffer *buffer, update_hook_cb hook, void *userdata) { struct update_hook *h = @@ -280,10 +287,18 @@ void render_line(struct text_chunk *line, void *userdata) { for (uint32_t bytei = 0; bytei < line->nbytes; ++bytei) { if (line->text[bytei] == '\t') { col += 3; + } else if (utf8_byte_is_unicode_start(line->text[bytei])) { + wchar_t wc; + if (mbrtowc(&wc, (char *)line->text + bytei, 6, NULL) >= 0) { + col += wcwidth(wc) - 1; + } } } - command_list_draw_repeated(cmdbuf->cmds, col, visual_line, ' ', - cmdbuf->width - line->nchars); + + if (cmdbuf->width > line->nchars) { + command_list_draw_repeated(cmdbuf->cmds, col, visual_line, ' ', + cmdbuf->width - line->nchars); + } } void scroll(struct buffer *buffer, int line_delta, int col_delta) { @@ -315,6 +330,11 @@ uint32_t visual_dot_col(struct buffer *buffer, uint32_t dot_col) { ++bytei) { if (line.text[bytei] == '\t') { visual_dot_col += 3; + } else if (utf8_byte_is_unicode_start(line.text[bytei])) { + wchar_t wc; + if (mbrtowc(&wc, (char *)line.text + bytei, 6, NULL) >= 0) { + visual_dot_col += wcwidth(wc) - 1; + } } } diff --git a/src/buffer.h b/src/buffer.h index e8ab62b..cf9c269 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -87,6 +87,7 @@ void buffer_forward_line(struct buffer *buffer); void buffer_end_of_line(struct buffer *buffer); void buffer_beginning_of_line(struct buffer *buffer); void buffer_newline(struct buffer *buffer); +void buffer_indent(struct buffer *buffer); uint32_t buffer_add_update_hook(struct buffer *buffer, update_hook_cb hook, void *userdata); @@ -115,7 +116,8 @@ BUFFER_WRAPCMD(buffer_backward_line); BUFFER_WRAPCMD(buffer_forward_line); BUFFER_WRAPCMD(buffer_end_of_line); BUFFER_WRAPCMD(buffer_beginning_of_line); -BUFFER_WRAPCMD(buffer_newline) +BUFFER_WRAPCMD(buffer_newline); +BUFFER_WRAPCMD(buffer_indent); BUFFER_WRAPCMD(buffer_to_file); static struct command BUFFER_COMMANDS[] = { @@ -129,5 +131,6 @@ static struct command BUFFER_COMMANDS[] = { {.name = "end-of-line", .fn = buffer_end_of_line_cmd}, {.name = "beginning-of-line", .fn = buffer_beginning_of_line_cmd}, {.name = "newline", .fn = buffer_newline_cmd}, + {.name = "indent", .fn = buffer_indent_cmd}, {.name = "buffer-write-to-file", .fn = buffer_to_file_cmd}, }; diff --git a/src/display.c b/src/display.c index 7116e94..3a2a0d9 100644 --- a/src/display.c +++ b/src/display.c @@ -5,6 +5,7 @@ #include <stdarg.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <unistd.h> @@ -289,7 +290,8 @@ void display_render(struct display *display, switch (cmd->type) { case RenderCommand_DrawText: { struct draw_text_cmd *txt_cmd = cmd->draw_txt; - display_move_cursor(display, txt_cmd->row, txt_cmd->col); + display_move_cursor(display, txt_cmd->row + cl->yoffset, + txt_cmd->col + cl->xoffset); putbytes(fmt_stack, fmt_stack_len, false); putbyte('m'); putbytes(txt_cmd->data, txt_cmd->len, show_whitespace_state); @@ -298,11 +300,20 @@ void display_render(struct display *display, case RenderCommand_Repeat: { struct repeat_cmd *repeat_cmd = cmd->repeat; - display_move_cursor(display, repeat_cmd->row, repeat_cmd->col); + display_move_cursor(display, repeat_cmd->row + cl->yoffset, + repeat_cmd->col + cl->xoffset); putbytes(fmt_stack, fmt_stack_len, false); putbyte('m'); - for (uint32_t i = 0; i < repeat_cmd->nrepeat; ++i) { - putbyte_ws(repeat_cmd->c, show_whitespace_state); + if (show_whitespace_state) { + for (uint32_t i = 0; i < repeat_cmd->nrepeat; ++i) { + putbyte_ws(repeat_cmd->c, show_whitespace_state); + } + } else { + char *buf = malloc(repeat_cmd->nrepeat + 1); + memset(buf, repeat_cmd->c, repeat_cmd->nrepeat); + buf[repeat_cmd->nrepeat] = '\0'; + fputs(buf, stdout); + free(buf); } break; } diff --git a/src/keyboard.c b/src/keyboard.c index e2cdc34..03d0bd4 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -23,42 +23,56 @@ struct keyboard keyboard_create(struct reactor *reactor) { .reactor_event_id = reactor_register_interest(reactor, STDIN_FILENO, ReadInterest), .has_data = false, - .last_key = {0}, }; } void parse_keys(uint8_t *bytes, uint32_t nbytes, struct key *out_keys, - uint32_t *out_nkeys, struct key *previous_key) { + uint32_t *out_nkeys) { uint32_t nkps = 0; - struct key *prevkp = previous_key; for (uint32_t bytei = 0; bytei < nbytes; ++bytei) { uint8_t b = bytes[bytei]; - struct key *kp = &out_keys[nkps]; - kp->start = bytei; - - bool inserted = true; if (b == 0x1b) { // meta - kp->mod |= Meta; + struct key *kp = &out_keys[nkps]; + kp->start = bytei; + kp->mod = Meta; + } else if (b == '[' || + b == '0') { // special char (function keys, pgdn, etc) + struct key *kp = &out_keys[nkps]; + if (kp->mod & Meta) { + kp->mod = Spec; + } } else if (b >= 0x00 && b <= 0x1f) { // ctrl char + struct key *kp = &out_keys[nkps]; kp->mod |= Ctrl; kp->key = b | 0x40; - } else if (b == 0x7f) { // ^? + kp->start = bytei; + kp->end = bytei + 1; + ++nkps; + } else if (b == 0x7f) { // ? + struct key *kp = &out_keys[nkps]; kp->mod |= Ctrl; kp->key = '?'; - } else if (prevkp->mod & Meta) { - prevkp->key = b; - prevkp->end = bytei + 1; - inserted = false; - } else { - inserted = false; - } - - kp->end = bytei + 1; - - if (inserted) { + kp->start = bytei; + kp->end = bytei + 1; ++nkps; - prevkp = kp; + } else { + struct key *kp = &out_keys[nkps]; + if (kp->mod & Spec && b == '~') { + // skip tilde in special chars + kp->end = bytei + 1; + ++nkps; + } else if (kp->mod & Meta || kp->mod & Spec) { + kp->key = b; + kp->end = bytei + 1; + + bool has_more = bytei + 1 < nbytes; + + if (kp->mod & Meta || + (kp->mod & Spec && !(has_more && bytes[bytei + 1] == '~'))) { + ++nkps; + } + } } } @@ -87,7 +101,7 @@ struct keyboard_update keyboard_update(struct keyboard *kbd, if (nbytes > 0) { upd.nbytes = nbytes; - parse_keys(upd.raw, upd.nbytes, upd.keys, &upd.nkeys, &kbd->last_key); + parse_keys(upd.raw, upd.nbytes, upd.keys, &upd.nkeys); if (nbytes < 32) { kbd->has_data = false; @@ -116,6 +130,9 @@ void key_name(struct key *key, char *buf, size_t capacity) { case Meta: mod = "m-"; break; + case Spec: + mod = "special-"; + break; } snprintf(buf, capacity, "%s%c", mod, tolower(key->key)); diff --git a/src/keyboard.h b/src/keyboard.h index b7f1940..72c61d5 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -5,6 +5,7 @@ enum modifiers { Ctrl = 1 << 0, Meta = 1 << 1, + Spec = 1 << 2, }; struct key { @@ -17,7 +18,6 @@ struct key { struct keyboard { uint32_t reactor_event_id; bool has_data; - struct key last_key; }; struct keyboard_update { @@ -240,8 +240,11 @@ int main(int argc, char *argv[]) { if (display_resized) { minibuffer_window.width = display.width; + minibuffer_window.y = display.height - 1; + main_window.height = display.height - 1; main_window.width = display.width; + display_resized = false; } @@ -336,8 +339,10 @@ int main(int argc, char *argv[]) { break; } } - } else if (current_keymap != NULL) { - minibuffer_echo_timeout(4, "key is not bound!"); + } else { + char keyname[16]; + key_name(k, keyname, 16); + minibuffer_echo_timeout(4, "key \"%s\" is not bound!", keyname); current_keymap = NULL; } } |
