From 81dd6b162351d93dae5d71a45df56ee1a74a36ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Tom=C3=A1s?= Date: Tue, 7 Jul 2020 13:04:26 -0300 Subject: Split application into server and client --- Makefile | 2 +- buffer.cpp | 27 +++++++----- client.cpp | 79 +++++++++++++++++++++++++++++++++ jet.cpp | 142 +++++++++++++++++++++++++----------------------------------- jet2.cpp | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++ point.cpp | 95 ++++++++++++---------------------------- todo.txt | 1 - unicode.txt | 1 - 8 files changed, 310 insertions(+), 164 deletions(-) create mode 100644 client.cpp create mode 100644 jet2.cpp delete mode 100644 todo.txt delete mode 100644 unicode.txt diff --git a/Makefile b/Makefile index 959032c..45a82a3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -FLAGS=-lcurses $(shell ncursesw6-config --cflags --libs) +FLAGS=-ggdb -O0 -lcurses $(shell ncursesw6-config --cflags --libs) jet: Makefile *.cpp g++ $(FLAGS) jet.cpp -o jet diff --git a/buffer.cpp b/buffer.cpp index 9313380..d1762d0 100644 --- a/buffer.cpp +++ b/buffer.cpp @@ -1,21 +1,24 @@ struct Buffer { const char *name; - Point start; - Point cursor; + Page *storage; - Buffer(const char *name) : name(name), start(), cursor(start) {} + Buffer(const char *name) : name(name), storage(new Page()) {} - void prev_line(int window_width) { - cursor--; - cursor.rseek('\n', window_width - 1); + void read(const char *file) { + FILE *f = fopen(file, "r"); + char c; + Point p(storage, 0); + while ((c = fgetc(f)) != EOF) { + p.push(c); + } + fclose(f); } - void next_line(int window_width) { - cursor.seek('\n', window_width); - if (cursor.element() == '\n') { - cursor++; + void write(const char *file) { + FILE *f = fopen(file, "w+"); + for (Point p(storage, 0); !p.at_end(); p++) { + fputc(p.element(), f); } + fclose(f); } - }; - diff --git a/client.cpp b/client.cpp new file mode 100644 index 0000000..f99dc5d --- /dev/null +++ b/client.cpp @@ -0,0 +1,79 @@ +#define MAX_ARGS 16 +#define pos(x, y) (x) + (y) * window_w + +struct ArgList { + int len, cap; + int *args; + + ArgList(int cap) : len(0), cap(cap) { + args = new int[cap]; + for (int i = 0; i < cap; args[i++] = 0); + } + ~ArgList() { delete[] args; } + + int pop() { + return args[--len]; + } + + void push(int value) { + args[len++] = value; + } + +}; + +struct Client { + int sockfd; + Point cursor; + Point window_start; + ArgList args; + + Client(const Buffer &b) : + cursor(b.storage, 0), + window_start(cursor), + args(MAX_ARGS) + {} + + void show() { + int window_h = args.pop(); + int window_w = args.pop(); + char *view = new char[window_w * window_h]; + + Point window_end(window_start); + for (int i = 0; i < window_h; i++) { + for (int j = 0; j < window_w; j++) { + if (window_end == cursor) { + view[pos(j, i)] = '$'; + } else { + view[pos(j, i)] = window_end.element(); + } + if (window_end.element() == '\n') { + for (int k = j + 1; k < window_w; k++) { + view[pos(k, i)] = 0; + } + j = window_w; + } else if (window_end.element() == '\t') { + for (int k = j + 1; k < j + 8; k++) { + view[pos(k, i)] = 0; + } + j = j + 7; + } + window_end++; + } + } + + write(sockfd, view, window_w * window_h); + delete[] view; + } + + void move() { + int target = args.pop(); + while (target > 0) { + cursor++; + target--; + } + while (target < 0) { + cursor--; + target++; + } + } +}; diff --git a/jet.cpp b/jet.cpp index b11744a..dd70f13 100644 --- a/jet.cpp +++ b/jet.cpp @@ -1,103 +1,81 @@ #include #include -#include -#include -#include -#define PAGE_SIZE 4096 +#include + +#include +#include +#include +#include +#include +#include + #include "page.cpp" #include "point.cpp" #include "buffer.cpp" +#include "client.cpp" -#define NORMAL_MODE 0 -#define INSERT_MODE 1 - -int main(int argc, char *argv[]) { - setlocale(LC_ALL, ""); - initscr(); - cbreak(); - noecho(); - intrflush(stdscr, FALSE); - keypad(stdscr, TRUE); +#define PORT 6969 +#define MAX_COMMAND_SIZE 128 +#define MAX_EVENTS 10 - Buffer buffer("test"); - Point window_start(buffer.start); +int create_listener() { + int s = socket(AF_INET, SOCK_STREAM, 0); + sockaddr_in addr = { AF_INET, htons(PORT), htonl(INADDR_LOOPBACK)}; + int opt = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)); + bind(s, (sockaddr *) &addr, sizeof(sockaddr_in)); + listen(s, MAX_EVENTS); + return s; +} - if (argc > 1) { - FILE *f = fopen(argv[1], "r"); - char c; - while ((c = fgetc(f)) != EOF) { - buffer.cursor.push(c); +void parse_command(char *command, Client *client) { + char *token = strtok(command, " \n"); + while (token) { + if (strcmp(token, "show") == 0) { + client->show(); + } else if (strcmp(token, "move") == 0) { + client->move(); + } else { + client->args.push(atoi(token)); } - buffer.cursor = buffer.start; - fclose(f); + token = strtok(0, " \n"); } +} - int window_height, window_width; - getmaxyx(stdscr, window_height, window_width); +int main() { + Buffer scratch("scratch"); + scratch.read("LICENSE"); - int mode = NORMAL_MODE; + int listener = create_listener(); + int epollfd = epoll_create1(0); + epoll_event events[MAX_EVENTS]; + epoll_event ev; + ev.events = EPOLLIN; + ev.data.fd = listener; + epoll_ctl(epollfd, EPOLL_CTL_ADD, listener, &ev); - int quit = 0; - while (!quit) { - clear(); + Client *clients[1024] = {}; - int x = -1, y = -1; - Point window_end(window_start); - while (!window_end.at_end() && getcury(stdscr) < window_height - 1) { - if (window_end == buffer.cursor) { - getyx(stdscr, y, x); - } - printw("%lc", window_end.element()); - window_end++; - } - printw("%d", buffer.cursor.index); - if (x > -1 && y > -1) { - move(y, x); - } + for (;;) { + int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); - int input = getch(); - if (byte_type(input) == 1) { - if (mode == NORMAL_MODE) { - switch (input) { - case '': - quit = 1; - break; - case 'i': - mode = INSERT_MODE; - break; - case 'k': - buffer.prev_line(window_width); - break; - case 'j': - buffer.next_line(window_width); - break; - case 'h': - buffer.cursor--; - break; - case 'l': - buffer.cursor++; - break; - } + for (int i = 0; i < nfds; i++) { + if (events[i].data.fd == listener) { + int clientfd = accept(listener, 0, 0); + ev.events = EPOLLIN | EPOLLET; + ev.data.fd = clientfd; + Client *c = new Client(scratch); + c->sockfd = clientfd; + clients[clientfd] = c; + epoll_ctl(epollfd, EPOLL_CTL_ADD, clientfd, &ev); } else { - switch (input) { - case '': - mode = NORMAL_MODE; - break; - case KEY_BACKSPACE: - buffer.cursor.pop(); - break; - default: - buffer.cursor.push(input); - } - } - } else { - buffer.cursor.push(input); - for (int i = 0; i < byte_type(input) - 1; i++) { - buffer.cursor.push(getch()); + char command[MAX_COMMAND_SIZE] = {}; + int clientfd = events[i].data.fd; + read(clientfd, command, MAX_COMMAND_SIZE - 1); + parse_command(command, clients[clientfd]); } } } - endwin(); - return 0; + close(listener); } diff --git a/jet2.cpp b/jet2.cpp new file mode 100644 index 0000000..c00042a --- /dev/null +++ b/jet2.cpp @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include +#include "page.cpp" +#include "point.cpp" +#include "buffer.cpp" + +#define NORMAL_MODE 0 +#define INSERT_MODE 1 +#define pos(x, y) (x) + (y) * window_width + +int main(int argc, char *argv[]) { + initscr(); + cbreak(); + noecho(); + intrflush(stdscr, FALSE); + keypad(stdscr, TRUE); + + if (argc > 1) { + buffer.read(argv[1]); + } + + int window_height, window_width; + getmaxyx(stdscr, window_height, window_width); + + int *view = new int[window_width * window_height]; + for (int i = 0; i < window_width * window_height; view[i++] = 0); + + int mode = NORMAL_MODE; + + int quit = 0; + while (!quit) { + clear(); + + Point window_end(window_start); + int x = -1, y = -1; + for (int i = 0; i < window_height; i++) { + for (int j = 0; j < window_width; j++) { + if (window_end == cursor) { + x = j; + y = i; + } + view[pos(j, i)] = window_end.element(); + if (window_end.element() == '\n') { + for (int k = j + 1; k < window_width; k++) { + view[pos(k, i)] = 0; + } + j = window_width; + } else if (window_end.element() == '\t') { + for (int k = j + 1; k < j + 8; k++) { + view[pos(k, i)] = 0; + } + j = j + 7; + } + window_end++; + } + } + for (int i = 0; i < window_width * window_height; i++) { + printw("%lc", view[i]); + } + if (x != -1 && y != -1) { + move(y, x); + } + + int input = getch(); + if (byte_type(input) == 1) { + if (mode == NORMAL_MODE) { + switch (input) { + case '': + quit = 1; + break; + case 'i': + mode = INSERT_MODE; + break; + case 'j': + for (int i = pos(x, y); i < pos(x + 1, y + 1); i++) { + if (view[i]) cursor++; + } + cursor--; + if (y + 1 >= window_height) { + window_start.seek('\n', window_width - 1); + window_start++; + } + break; + case 'k': + for (int i = pos(x, y); i > pos(x, y - 1); i--) { + if (view[i]) cursor--; + } + if (y - 1 <= 0) { + window_start--; + window_start.rseek('\n', window_width - 1); + } + break; + case 'h': + cursor--; + break; + case 'l': + cursor++; + break; + } + } else { + switch (input) { + case '': + mode = NORMAL_MODE; + break; + case KEY_BACKSPACE: + cursor.pop(); + break; + default: + cursor.push(input); + } + } + } else { + cursor.push(input); + for (int i = 0; i < byte_type(input) - 1; i++) { + cursor.push(getch()); + } + } + } + + buffer.write(buffer.name); + + endwin(); + return 0; +} diff --git a/point.cpp b/point.cpp index a331cb7..b0be8e9 100644 --- a/point.cpp +++ b/point.cpp @@ -2,26 +2,6 @@ #include #include -size_t byte_type(uint8_t byte) { - if (byte & 1 << 7) { - if (byte & 1 << 6) { - if (byte & 1 << 5) { - if (byte & 1 << 4) { - return 4; - } else { - return 3; - } - } else { - return 2; - } - } else { - return 0; - } - } else { - return 1; - } -} - struct Point { Page *page; uint16_t index; @@ -76,32 +56,12 @@ struct Point { } } - void pop_byte() { - if (!at_start()) { - align_gap(); - page->pop(); - move_backward(); - if (index == 0) { - move_backward(); - } - } - if (page->is_empty()) { - if (page->prev) { - move_backward(); - delete page->next; - } else if (page->next) { - page->next->copy_to(page); - delete page->next; - index = 0; - } - } - } public: - Point() : page(new Page()), index(0) {} - Point(Page *page, uint16_t index) : page(page), index(index) {} - Point(const Point& p) : page(p.page), index(p.index) {} + Point() : page(0), index(0) {} + Point(Page* page, uint16_t index) : page(page), index(index) {} + Point(const Point &p) : page(p.page), index(p.index) {} bool operator==(Point p) { return page == p.page && index == p.index; @@ -120,30 +80,17 @@ struct Point { } void operator++(int) { - do { - if (index == page->element_count) move_forward(); - move_forward(); - } while (!byte_type(next_byte())); + if (index == page->element_count) move_forward(); + move_forward(); } void operator--(int) { - do { - move_backward(); - if (index == 0) move_backward(); - } while (!byte_type(next_byte())); - } - - wchar_t element() { - size_t type = byte_type(next_byte()); - wchar_t rune = next_byte() & (0xff >> type); - Point iter(*this); - for (size_t i = 1; i < type; i++) { - rune <<= 6; - iter.move_forward(); - if (iter.index == 0) iter.move_forward(); - rune |= (iter.next_byte() & 0x3f); - } - return rune; + move_backward(); + if (index == 0) move_backward(); + } + + char element() { + return next_byte(); } uint64_t seek(uint8_t c, uint64_t limit) { @@ -187,10 +134,24 @@ struct Point { } void pop() { - while (!byte_type(prev_byte())) { - pop_byte(); + if (!at_start()) { + align_gap(); + page->pop(); + move_backward(); + if (index == 0) { + move_backward(); + } + } + if (page->is_empty()) { + if (page->prev) { + move_backward(); + delete page->next; + } else if (page->next) { + page->next->copy_to(page); + delete page->next; + index = 0; + } } - pop_byte(); } }; diff --git a/todo.txt b/todo.txt deleted file mode 100644 index ba70618..0000000 --- a/todo.txt +++ /dev/null @@ -1 +0,0 @@ -* free page correctly after no points point to it diff --git a/unicode.txt b/unicode.txt deleted file mode 100644 index 5bcdd50..0000000 --- a/unicode.txt +++ /dev/null @@ -1 +0,0 @@ -e$¢ह€한😁 -- cgit v1.2.3