diff options
| author | Albert Cervin <albert@acervin.com> | 2022-11-02 22:20:04 +0100 |
|---|---|---|
| committer | Albert Cervin <albert@acervin.com> | 2022-11-16 23:33:49 +0100 |
| commit | 2f4cb88d5c60f725323739300bb49dfa8923e7d5 (patch) | |
| tree | 6ec22c2be92eff05f18e5919e747faab56e555ad /src/main.c | |
| download | dged-2f4cb88d5c60f725323739300bb49dfa8923e7d5.tar.gz dged-2f4cb88d5c60f725323739300bb49dfa8923e7d5.tar.xz dged-2f4cb88d5c60f725323739300bb49dfa8923e7d5.zip | |
🎉 And so it begins
Diffstat (limited to 'src/main.c')
| -rw-r--r-- | src/main.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..140b281 --- /dev/null +++ b/src/main.c @@ -0,0 +1,166 @@ +#include <locale.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <assert.h> +#include <signal.h> +#include <sys/epoll.h> + +#include "binding.h" +#include "buffer.h" +#include "display.h" + +struct reactor { + int epoll_fd; +}; + +struct reactor reactor_create(); +int reactor_register_interest(struct reactor *reactor, int fd); + +struct frame_allocator { + uint8_t *buf; + size_t offset; + size_t capacity; +}; + +struct frame_allocator frame_allocator_create(size_t capacity) { + return (struct frame_allocator){ + .capacity = capacity, .offset = 0, .buf = (uint8_t *)malloc(capacity)}; +} + +void *frame_allocator_alloc(struct frame_allocator *alloc, size_t sz) { + if (alloc->offset + sz > alloc->capacity) { + return NULL; + } + + void *mem = alloc->buf + alloc->offset; + alloc->offset += sz; + + return mem; +} + +void frame_allocator_clear(struct frame_allocator *alloc) { alloc->offset = 0; } + +struct frame_allocator frame_allocator; + +void *frame_alloc(size_t sz) { + return frame_allocator_alloc(&frame_allocator, sz); +} + +bool running = true; + +void terminate() { running = false; } + +void unimplemented_command(struct buffer *buffer) {} +void exit_editor(struct buffer *buffer) { terminate(); } + +static struct command GLOBAL_COMMANDS[] = { + {.name = "find-file", .fn = unimplemented_command}, + {.name = "exit", .fn = exit_editor}}; + +int main(int argc, char *argv[]) { + const char *filename = NULL; + if (argc >= 1) { + filename = argv[1]; + } + + setlocale(LC_ALL, ""); + signal(SIGTERM, terminate); + + frame_allocator = frame_allocator_create(1024 * 1024); + + // create reactor + struct reactor reactor = reactor_create(); + + // initialize display + struct display display = display_create(); + display_clear(&display); + + // init keyboard + struct keyboard kbd = keyboard_create(); + + // commands + struct commands commands = command_list_create(32); + register_commands(&commands, GLOBAL_COMMANDS, + sizeof(GLOBAL_COMMANDS) / sizeof(GLOBAL_COMMANDS[0])); + register_commands(&commands, BUFFER_COMMANDS, + sizeof(BUFFER_COMMANDS) / sizeof(BUFFER_COMMANDS[0])); + + // keymaps + struct keymap global_keymap = keymap_create("global", 32); + struct binding global_binds[] = { + BINDING(Ctrl, 'X', "exit"), + }; + keymap_bind_keys(&global_keymap, global_binds, + sizeof(global_binds) / sizeof(global_binds[0])); + + // TODO: load initial buffer + struct buffer curbuf = buffer_create("welcome"); + const char *welcome_txt = "Welcome to the editor for datagubbar 👴\n"; + buffer_add_text(&curbuf, (uint8_t *)welcome_txt, strlen(welcome_txt)); + + while (running) { + // update keyboard + struct keymap *local_keymaps = NULL; + uint32_t nbuffer_keymaps = buffer_keymaps(&curbuf, &local_keymaps); + struct keyboard_update kbd_upd = keyboard_begin_frame(&kbd); + for (uint32_t ki = 0; ki < kbd_upd.nkeys; ++ki) { + struct key *k = &kbd_upd.keys[ki]; + + // check first the global keymap, then the buffer ones + struct command *cmd = lookup_key(&global_keymap, 1, k, &commands); + if (cmd == NULL) { + cmd = lookup_key(local_keymaps, nbuffer_keymaps, k, &commands); + } + + if (cmd != NULL) { + cmd->fn(&curbuf); + } else { + buffer_add_text(&curbuf, &k->c, 1); + } + } + + // update current buffer + struct buffer_update buf_upd = buffer_begin_frame( + &curbuf, display.width, display.height - 1, frame_alloc); + + // update screen + if (buf_upd.ncmds > 0) { + display_update(&display, buf_upd.cmds, buf_upd.ncmds, curbuf.dot_line, + curbuf.dot_col); + } + + buffer_end_frame(&curbuf, &buf_upd); + frame_allocator_clear(&frame_allocator); + } + + display_clear(&display); + display_destroy(&display); + keymap_destroy(&global_keymap); + command_list_destroy(&commands); + + return 0; +} + +struct reactor reactor_create() { + int epollfd = epoll_create1(0); + if (epollfd == -1) { + perror("epoll_create1"); + } + + return (struct reactor){.epoll_fd = epollfd}; +} + +int reactor_register_interest(struct reactor *reactor, int fd) { + struct epoll_event ev; + ev.events = EPOLLIN; + ev.data.fd = fd; + if (epoll_ctl(reactor->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { + perror("epoll_ctl"); + return -1; + } + + return fd; +} |
