summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2023-01-15 23:07:37 +0100
committerAlbert Cervin <albert@acervin.com>2023-01-15 23:07:37 +0100
commit385c9d62a5507d901ff7e54d7a4c0342cf3aff43 (patch)
tree53e53ee0075e34ef59aeeeb554a69580af1e2d1c /src
parentd806403fe93daa2fb84e2c72aa7660575c33000e (diff)
downloaddged-385c9d62a5507d901ff7e54d7a4c0342cf3aff43.tar.gz
dged-385c9d62a5507d901ff7e54d7a4c0342cf3aff43.tar.xz
dged-385c9d62a5507d901ff7e54d7a4c0342cf3aff43.zip
Lots of fixes for rendering, utf-8 and kbd.
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c34
-rw-r--r--src/buffer.h5
-rw-r--r--src/display.c19
-rw-r--r--src/keyboard.c61
-rw-r--r--src/keyboard.h2
-rw-r--r--src/main.c9
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 {
diff --git a/src/main.c b/src/main.c
index f93140d..028f926 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}
}