summaryrefslogtreecommitdiff
path: root/userland/ante
diff options
context:
space:
mode:
Diffstat (limited to 'userland/ante')
-rw-r--r--userland/ante/Makefile15
-rw-r--r--userland/ante/ante.c296
2 files changed, 311 insertions, 0 deletions
diff --git a/userland/ante/Makefile b/userland/ante/Makefile
new file mode 100644
index 0000000..412b302
--- /dev/null
+++ b/userland/ante/Makefile
@@ -0,0 +1,15 @@
+CC="/home/anton/prj/osdev/sysroot/bin/i686-sb-gcc"
+CFLAGS = -ggdb -O2 -Wall -Wextra -pedantic -static
+LIB=-L../libgui -lgui -lgcc
+INC=-I../libgui/
+BINS=ante
+all: $(BINS)
+
+ante.o: ante.c
+ $(CC) $(CFLAGS) $(INC) $(LIB) -o $@ -c $<
+
+ante: ante.o
+ $(CC) $(CFLAGS) -o $@ $^ $(LIB)
+
+clean:
+ rm $(BINS) *.o
diff --git a/userland/ante/ante.c b/userland/ante/ante.c
new file mode 100644
index 0000000..753e7f2
--- /dev/null
+++ b/userland/ante/ante.c
@@ -0,0 +1,296 @@
+#include <assert.h>
+#include <fcntl.h>
+#include <libgui.h>
+#include <poll.h>
+#include <pty.h>
+#include <socket.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BACKGROUND_COLOR 0x000000
+
+int file_fd;
+char *file_buffer;
+uint64_t file_buffer_size;
+uint64_t file_size = 0;
+uint64_t file_real_position = 0;
+GUI_Window *global_w;
+
+typedef enum {
+ NORMAL,
+ INSERT,
+ COMMAND,
+} editor_mode_t;
+
+editor_mode_t current_mode = NORMAL;
+uint32_t cursor_pos_x = 0;
+uint64_t cursor_pos_y = 0;
+void draw_file(void);
+void write_file(void);
+
+int clamp(int *x, int *y) {
+ int clamped = 0;
+ if (*x < 0) {
+ *x = 0;
+ clamped = 1;
+ }
+ if (*y < 0) {
+ *y = 0;
+ clamped = 1;
+ }
+ if (*x + 8 > global_w->sx) {
+ *x = (global_w->sx - 8) / 8;
+ clamped = 1;
+ }
+ if (*y + 8 > global_w->sy) {
+ *y = (global_w->sy - 8) / 8;
+ clamped = 1;
+ }
+ return clamped;
+}
+
+void insert_char(int pos, char c) {
+ if (0 == file_size) {
+ file_size++;
+ file_buffer[0] = c;
+ return;
+ }
+
+ // Shift the buffer at 'pos' to the right by one.
+ memmove(file_buffer + pos + 1, file_buffer + pos, file_size - pos);
+
+ file_buffer[pos] = c;
+ file_size++;
+}
+
+void delete_char(int pos, int *deleted_newline) {
+ if (0 == pos) {
+ return;
+ }
+ // Delete the characther at 'pos'. This makes sense if 'pos' is
+ // at the end of the file and as a result the shift operation done
+ // later in the function is not overwritting the characther.
+ if ('\n' == file_buffer[pos - 1])
+ *deleted_newline = 1;
+ file_buffer[pos - 1] = 0;
+
+ // Shift the buffer at 'pos' to the left by one
+ memmove(file_buffer + pos - 1, file_buffer + pos, file_size - pos);
+ file_size--;
+}
+
+uint64_t cursor_to_real(int x, int y, int *is_valid) {
+ *is_valid = 0;
+ if (clamp(&x, &y))
+ return file_real_position;
+ if (0 == file_size) {
+ if (0 == x && 0 == y) {
+ *is_valid = 1;
+ return 0;
+ }
+ return 0;
+ }
+ uint64_t p = 0;
+ int cx = 0;
+ int cy = 0;
+ for (; p < file_size; p++) {
+ if (cx == x && cy == y) {
+ *is_valid = 1;
+ break;
+ }
+ if ('\n' == file_buffer[p]) {
+ cx = 0;
+ cy++;
+ continue;
+ }
+ cx++;
+ }
+ if (*is_valid)
+ return p;
+ else
+ return file_real_position;
+}
+
+void key_event(char c) {
+ int x = 0;
+ int y = 0;
+ if (COMMAND == current_mode) {
+ if ('w' == c) {
+ printf("wrote to file\n");
+ write_file();
+ current_mode = NORMAL;
+ return;
+ }
+ if ('q' == c) {
+ close(file_fd);
+ close(global_w->ws_socket);
+ current_mode = NORMAL;
+ exit(0);
+ return;
+ }
+ return;
+ } else if (NORMAL == current_mode) {
+ switch (c) {
+ case 'j':
+ y++;
+ break;
+ case 'k':
+ y--;
+ break;
+ case 'l':
+ x++;
+ break;
+ case 'h':
+ x--;
+ break;
+ case 'c':
+ printf("entering command mode\n");
+ current_mode = COMMAND;
+ return;
+ break;
+ case 'i':
+ current_mode = INSERT;
+ return;
+ break;
+ default:
+ return;
+ }
+ } else {
+ if ('\x1B' == c) {
+ current_mode = NORMAL;
+ return;
+ }
+ if ('\b' == c) {
+ int deleted_newline = 0;
+ delete_char(file_real_position, &deleted_newline);
+ if (deleted_newline) {
+ y--;
+ } else {
+ x--;
+ }
+ GUI_ClearScreen(global_w, BACKGROUND_COLOR);
+ } else {
+ insert_char(file_real_position, c);
+ printf("inserting char: %c\n", c);
+ if ('\n' == c) {
+ cursor_pos_x = 0;
+ y++;
+ } else {
+ x++;
+ }
+ GUI_ClearScreen(global_w, BACKGROUND_COLOR);
+ }
+ }
+
+ int is_valid_position = 0;
+ file_real_position =
+ cursor_to_real(cursor_pos_x + x, cursor_pos_y + y, &is_valid_position);
+ if (!is_valid_position) {
+ return;
+ }
+ GUI_OverwriteFont(global_w, cursor_pos_x * 8, cursor_pos_y * 8,
+ BACKGROUND_COLOR);
+ draw_file();
+ cursor_pos_x += x;
+ cursor_pos_y += y;
+ GUI_OverwriteFont(global_w, cursor_pos_x * 8, cursor_pos_y * 8, 0xFFFFFF);
+
+ GUI_UpdateWindow(global_w);
+}
+
+void draw_file(void) {
+ assert(file_buffer);
+ uint32_t screen_pos_x = 0;
+ uint64_t screen_pos_y = 0;
+ for (uint64_t i = 0; i < file_size; i++) {
+ char c = file_buffer[i];
+ if ('\n' == c) {
+ screen_pos_x = 0;
+ screen_pos_y += 8;
+ continue;
+ }
+ GUI_DrawFont(global_w, screen_pos_x, screen_pos_y, c);
+ screen_pos_x += 8;
+ }
+}
+
+void write_file(void) {
+ assert(file_buffer);
+ pwrite(file_fd, file_buffer, file_size, 0);
+}
+
+int open_file(const char *file) {
+ file_fd = open(file, O_RDWR, O_CREAT);
+ printf("file_fd: %d\n", file_fd);
+ if (0 > file_fd) {
+ perror("open");
+ return 0;
+ }
+
+ file_buffer_size = 0x1000;
+ file_buffer = malloc(file_buffer_size);
+ uint64_t index = 0;
+ assert(file_buffer);
+ for (;;) {
+ char buffer[4096];
+ int rc = read(file_fd, buffer, 4096);
+ if (-1 == rc) {
+ perror("read");
+ assert(0);
+ }
+
+ if (0 == rc)
+ break;
+
+ file_size += rc;
+ if (file_size > file_buffer_size) {
+ file_buffer_size = file_size;
+ file_buffer = realloc(file_buffer, file_buffer_size);
+ assert(file_buffer);
+ }
+
+ for (int i = 0; i < rc; i++, index++) {
+ file_buffer[index] = buffer[i];
+ }
+ }
+ return 1;
+}
+
+void run() {
+ struct pollfd fds[1];
+ fds[0].fd = global_w->ws_socket;
+ fds[0].events = POLLIN;
+ fds[0].revents = 0;
+ for (;; fds[0].revents = 0) {
+ poll(fds, 1, 0);
+ if (fds[0].revents & POLLIN) {
+ WS_EVENT e;
+ int rc;
+ if (0 >= (rc = read(global_w->ws_socket, &e, sizeof(e))))
+ continue;
+ if (0 == e.c)
+ continue;
+ key_event(e.c);
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ if (argc < 2) {
+ printf("File has to be specified.\n");
+ return 1;
+ }
+ global_w = GUI_CreateWindow(10, 10, 150 * 4, 150 * 4);
+ assert(global_w);
+ GUI_ClearScreen(global_w, BACKGROUND_COLOR);
+ GUI_UpdateWindow(global_w);
+
+ assert(open_file(argv[1]));
+ draw_file();
+ run();
+ return 0;
+}