summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile12
-rw-r--r--jet.c118
-rw-r--r--jet.cpp123
-rw-r--r--page.c93
-rw-r--r--page.cpp88
-rw-r--r--point.c123
-rw-r--r--point.cpp112
-rw-r--r--test/page.cpp (renamed from test/page.c)22
-rw-r--r--test/point.cpp (renamed from test/point.c)24
9 files changed, 352 insertions, 363 deletions
diff --git a/Makefile b/Makefile
index 2e84b40..b50b5a1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
FLAGS=-ggdb -O0 -fno-builtin -Wall -lcurses
-jet: Makefile *.c
- gcc $(FLAGS) jet.c -o jet
+jet: Makefile *.cpp
+ g++ $(FLAGS) jet.cpp -o jet
-page: Makefile page.c test/page.c
- gcc $(FLAGS) test/page.c -o page
+page: Makefile page.cpp test/page.cpp
+ g++ $(FLAGS) test/page.cpp -o page
-point: Makefile page.c point.c test/point.c
- gcc $(FLAGS) test/point.c -o point
+point: Makefile page.cpp point.cpp test/point.cpp
+ g++ $(FLAGS) test/point.cpp -o point
diff --git a/jet.c b/jet.c
deleted file mode 100644
index 3deabde..0000000
--- a/jet.c
+++ /dev/null
@@ -1,118 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <curses.h>
-#include "page.c"
-#include "point.c"
-
-#define NORMAL_MODE 0
-#define INSERT_MODE 1
-
-struct buffer {
- char *name;
- struct point start;
- struct point cursor;
-};
-
-struct buffer *new_buffer(char *name) {
- struct buffer *result = calloc(1, sizeof(struct buffer));
- result->name = name;
- result->start.page = new_page();
- result->cursor = result->start;
- return result;
-}
-
-int main(int argc, char *argv[]) {
- initscr();
- cbreak();
- noecho();
- intrflush(stdscr, FALSE);
- keypad(stdscr, TRUE);
-
- struct buffer *buffer = new_buffer("test");
- struct point window_start = buffer->start;
-
- if (argc > 1) {
- FILE *f = fopen(argv[1], "r");
- char c;
- while ((c = fgetc(f)) != EOF) {
- insert_at_point(&buffer->cursor, c);
- }
- buffer->cursor = buffer->start;
- fclose(f);
- }
-
- int window_height, window_width;
- getmaxyx(stdscr, window_height, window_width);
-
- int mode = NORMAL_MODE;
-
- int quit = 0;
- while (!quit) {
- clear();
-
- int x = -1, y = -1;
- struct point window_end = window_start;
- while (element(&window_end) && getcury(stdscr) < window_height - 1) {
- if (same_point(&window_end, &buffer->cursor)) {
- getyx(stdscr, y, x);
- }
- addch(element(&window_end));
- move_point_forward(&window_end);
- }
- if (x > -1 && y > -1) {
- move(y, x);
- }
-
- int input = getch();
-
- if (mode == NORMAL_MODE) {
- switch (input) {
- case '':
- quit = 1;
- break;
- case 'i':
- mode = INSERT_MODE;
- break;
- case 'k':
- prev_line(&buffer->cursor, window_width);
- if (y <= 0) {
- prev_line(&window_start, window_width);
- }
- break;
- case 'j':
- next_line(&buffer->cursor, window_width);
- if (y >= window_height - 2) {
- next_line(&window_start, window_width);
- }
- break;
- case 'h':
- move_point_backward(&buffer->cursor);
- break;
- case 'l':
- move_point_forward(&buffer->cursor);
- break;
- }
- } else {
- switch (input) {
- case '':
- mode = NORMAL_MODE;
- break;
- case KEY_BACKSPACE:
- delete_at_point(&buffer->cursor);
- break;
- default:
- insert_at_point(&buffer->cursor, input);
- }
- }
- if (element(&buffer->cursor) == 0) {
- move_point_backward(&buffer->cursor);
- }
- }
-
- endwin();
- return 0;
-}
diff --git a/jet.cpp b/jet.cpp
new file mode 100644
index 0000000..27d3f74
--- /dev/null
+++ b/jet.cpp
@@ -0,0 +1,123 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <curses.h>
+#include "page.cpp"
+#include "point.cpp"
+
+#define NORMAL_MODE 0
+#define INSERT_MODE 1
+
+struct Buffer {
+ const char *name;
+ Point start;
+ Point cursor;
+
+ Buffer(const char *name) : name(name), start(new Page()), cursor(start) {}
+
+ void prev_line(int window_width) {
+ cursor--;
+ cursor--;
+ cursor.rseek('\n', window_width - 2);
+ if (cursor.element() == '\n') {
+ cursor++;
+ }
+ }
+
+ void next_line(int window_width) {
+ cursor.seek('\n', window_width);
+ if (cursor.element() == '\n') {
+ cursor++;
+ }
+ }
+
+};
+
+int main(int argc, char *argv[]) {
+ initscr();
+ cbreak();
+ noecho();
+ intrflush(stdscr, FALSE);
+ keypad(stdscr, TRUE);
+
+ Buffer buffer = Buffer("test");
+ Point window_start = buffer.start;
+
+ if (argc > 1) {
+ FILE *f = fopen(argv[1], "r");
+ char c;
+ while ((c = fgetc(f)) != EOF) {
+ buffer.cursor.push(c);
+ }
+ buffer.cursor = buffer.start;
+ fclose(f);
+ }
+
+ int window_height, window_width;
+ getmaxyx(stdscr, window_height, window_width);
+
+ int mode = NORMAL_MODE;
+
+ int quit = 0;
+ while (!quit) {
+ clear();
+
+ int x = -1, y = -1;
+ Point window_end = window_start;
+ while (window_end.element() && getcury(stdscr) < window_height - 1) {
+ if (window_end == buffer.cursor) {
+ getyx(stdscr, y, x);
+ }
+ addch(window_end.element());
+ window_end++;
+ }
+ if (x > -1 && y > -1) {
+ move(y, x);
+ }
+
+ int input = getch();
+
+ 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;
+ }
+ } else {
+ switch (input) {
+ case '':
+ mode = NORMAL_MODE;
+ break;
+ case KEY_BACKSPACE:
+ buffer.cursor.pop();
+ break;
+ default:
+ buffer.cursor.push(input);
+ }
+ }
+ if (buffer.cursor.element() == 0) {
+ buffer.cursor--;
+ }
+ }
+
+ endwin();
+ return 0;
+}
diff --git a/page.c b/page.c
deleted file mode 100644
index dd3d29a..0000000
--- a/page.c
+++ /dev/null
@@ -1,93 +0,0 @@
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#ifndef PAGE_SIZE
-#define PAGE_SIZE 4096
-#endif
-
-struct page {
- uint8_t *elements;
- struct page *next;
- struct page *prev;
- uint16_t gap_start;
- uint16_t gap_end;
- uint16_t element_count;
-};
-
-struct page *new_page() {
- struct page *result = malloc(sizeof(struct page));
- result->elements = malloc(PAGE_SIZE);
- result->gap_start = 0;
- result->gap_end = PAGE_SIZE;
- result->next = 0;
- result->prev = 0;
- return result;
-}
-
-void split_page(struct page *back) {
- struct page *front = new_page();
-
- memcpy(front->elements, back->elements + PAGE_SIZE / 2, PAGE_SIZE / 2);
-
- front->gap_start = PAGE_SIZE / 2;
- front->gap_end = PAGE_SIZE;
- front->element_count = PAGE_SIZE / 2;
-
- back->gap_start = PAGE_SIZE / 2;
- back->gap_end = PAGE_SIZE;
- back->element_count = PAGE_SIZE / 2;
-
- if (back->next) {
- back->next->prev = front;
- }
- front->next = back->next;
- front->prev = back;
- back->next = front;
-}
-
-void copy_page(struct page *dest, struct page *src) {
- memcpy(dest->elements, src->elements, PAGE_SIZE);
- dest->gap_start = src->gap_start;
- dest->gap_end = src->gap_end;
- dest->element_count = src->element_count;
-}
-
-void free_page(struct page *page) {
- if (page->prev) {
- page->prev->next = page->next;
- }
- if (page->next) {
- page->next->prev = page->prev;
- }
- free(page->elements);
- free(page);
-}
-
-void move_gap_forward(struct page *page) {
- assert(page->gap_end < PAGE_SIZE);
- page->elements[page->gap_start] = page->elements[page->gap_end];
- page->gap_start++;
- page->gap_end++;
-}
-
-void move_gap_backward(struct page *page) {
- assert(page->gap_start > 0);
- page->gap_end--;
- page->gap_start--;
- page->elements[page->gap_end] = page->elements[page->gap_start];
-}
-
-void insert_at_gap(struct page *page, uint8_t c) {
- assert(page->element_count < PAGE_SIZE);
- page->elements[page->gap_start] = c;
- page->gap_start++;
- page->element_count++;
-}
-
-void delete_at_gap(struct page *page) {
- assert(page->gap_start > 0);
- page->gap_start--;
- page->element_count--;
-}
diff --git a/page.cpp b/page.cpp
new file mode 100644
index 0000000..7f56fc9
--- /dev/null
+++ b/page.cpp
@@ -0,0 +1,88 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+struct Page {
+ uint8_t *elements;
+ Page *next;
+ Page *prev;
+ uint16_t gap_start;
+ uint16_t gap_end;
+ uint16_t element_count;
+
+ Page() {
+ elements = new uint8_t[PAGE_SIZE];
+ gap_start = 0;
+ gap_end = PAGE_SIZE;
+ element_count = 0;
+ next = nullptr;
+ prev = nullptr;
+ }
+
+ ~Page() {
+ if (prev) prev->next = next;
+ if (next) next->prev = prev;
+ delete[] elements;
+ }
+
+ void split() {
+ Page *front = new Page();
+
+ memcpy(front->elements, elements + PAGE_SIZE / 2, PAGE_SIZE / 2);
+
+ front->gap_start = PAGE_SIZE / 2;
+ front->gap_end = PAGE_SIZE;
+ front->element_count = PAGE_SIZE / 2;
+
+ gap_start = PAGE_SIZE / 2;
+ gap_end = PAGE_SIZE;
+ element_count = PAGE_SIZE / 2;
+
+ if (next) {
+ next->prev = front;
+ }
+ front->next = next;
+ front->prev = this;
+ next = front;
+ }
+
+ void copy_to(Page *dest) {
+ memcpy(dest->elements, elements, PAGE_SIZE);
+ dest->gap_start = gap_start;
+ dest->gap_end = gap_end;
+ dest->element_count = element_count;
+ }
+
+ void operator++(int) {
+ assert(gap_end < PAGE_SIZE);
+ elements[gap_start] = elements[gap_end];
+ gap_start++;
+ gap_end++;
+ }
+
+ void operator--(int) {
+ assert(gap_start > 0);
+ gap_end--;
+ gap_start--;
+ elements[gap_end] = elements[gap_start];
+ }
+
+ void push(uint8_t c) {
+ assert(element_count < PAGE_SIZE);
+ elements[gap_start] = c;
+ gap_start++;
+ element_count++;
+ }
+
+ void pop() {
+ assert(gap_start > 0);
+ gap_start--;
+ element_count--;
+ }
+
+};
diff --git a/point.c b/point.c
deleted file mode 100644
index 515d73d..0000000
--- a/point.c
+++ /dev/null
@@ -1,123 +0,0 @@
-#include <stdint.h>
-#include <stdbool.h>
-
-struct point {
- struct page *page;
- uint16_t index;
-};
-
-uint16_t index_to_offset(struct point *point) {
- if (point->index < point->page->gap_start) {
- return point->index;
- } else {
- return point->index + (point->page->gap_end - point->page->gap_start);
- }
-}
-
-bool same_point(struct point *a, struct point *b) {
- return a->page == b->page && a->index == b->index;
-}
-
-uint8_t element(struct point *point) {
- if (point->index == point->page->element_count) {
- return !point->page->next ? 0 : point->page->next->elements[0];
- } else {
- return point->page->elements[index_to_offset(point)];
- }
-}
-
-void move_point_forward(struct point *point) {
- if (point->index < point->page->element_count) {
- point->index++;
- } else if (point->page->next) {
- point->index = 1;
- point->page = point->page->next;
- }
-}
-
-void move_point_backward(struct point *point) {
- if (point->index > 1) {
- point->index--;
- } else if (point->page->prev) {
- point->page = point->page->prev;
- point->index = point->page->element_count;
- } else {
- point->index = 0;
- }
-}
-
-uint64_t seek(struct point *point, uint8_t c, int limit) {
- uint64_t travel_distance = 0;
- while (element(point) && element(point) != c && travel_distance < limit) {
- move_point_forward(point);
- travel_distance++;
- }
- return travel_distance;
-}
-
-uint64_t rseek(struct point *point, uint8_t c, int limit) {
- uint64_t travel_distance = 0;
- while (point->index != 0 && element(point) != c && travel_distance < limit) {
- move_point_backward(point);
- travel_distance++;
- }
- return travel_distance;
-}
-
-void prev_line(struct point *point, int window_width) {
- move_point_backward(point);
- move_point_backward(point);
- rseek(point, '\n', window_width - 2);
- if (element(point) == '\n') {
- move_point_forward(point);
- }
-}
-
-void next_line(struct point *point, int window_width) {
- seek(point, '\n', window_width);
- if (element(point) == '\n') {
- move_point_forward(point);
- }
-}
-
-void align_gap(struct point *point) {
- while (point->page->gap_end < index_to_offset(point)) {
- move_gap_forward(point->page);
- }
- while (point->page->gap_end > index_to_offset(point)) {
- move_gap_backward(point->page);
- }
-}
-
-void insert_at_point(struct point *point, uint8_t c) {
- if (point->page->gap_start == point->page->gap_end) {
- split_page(point->page);
- if (point->index >= PAGE_SIZE / 2) {
- point->page = point->page->next;
- point->index -= PAGE_SIZE / 2;
- }
- }
- align_gap(point);
- insert_at_gap(point->page, c);
- move_point_forward(point);
-}
-
-void delete_at_point(struct point *point) {
- if (point->page->element_count == 1 && point->index == 1) {
- if (point->page->prev) {
- move_point_backward(point);
- free_page(point->page->next);
- } else if (point->page->next) {
- copy_page(point->page, point->page->next);
- free_page(point->page->next);
- point->index = 0;
- } else {
- delete_at_gap(point->page);
- point->index = 0;
- }
- } else if (point->index > 0) {
- align_gap(point);
- delete_at_gap(point->page);
- move_point_backward(point);
- }
-}
diff --git a/point.cpp b/point.cpp
new file mode 100644
index 0000000..e31f5de
--- /dev/null
+++ b/point.cpp
@@ -0,0 +1,112 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+struct Point {
+ Page *page;
+ uint16_t index;
+
+ Point() : page(nullptr), index(0) {}
+ Point(Page *page) : page(page), index(0) {}
+ Point(const Point& p) : page(p.page), index(p.index) {}
+
+ uint16_t index_to_offset() {
+ if (index < page->gap_start) {
+ return index;
+ } else {
+ return index + (page->gap_end - page->gap_start);
+ }
+ }
+
+ bool operator==(Point p) {
+ return page == p.page && index == p.index;
+ }
+
+ uint8_t element() {
+ if (index == page->element_count) {
+ return !page->next ? 0 : page->next->elements[0];
+ } else {
+ return page->elements[index_to_offset()];
+ }
+ }
+
+ void operator++(int) {
+ if (index < page->element_count) {
+ index++;
+ } else if (page->next) {
+ index = 1;
+ page = page->next;
+ }
+ }
+
+ void operator--(int) {
+ if (index > 1) {
+ index--;
+ } else if (page->prev) {
+ page = page->prev;
+ index = page->element_count;
+ } else {
+ index = 0;
+ }
+ }
+
+ uint64_t seek(uint8_t c, uint64_t limit) {
+ uint64_t travel_distance = 0;
+ while (element() && element() != c && travel_distance < limit) {
+ (*this)++;
+ travel_distance++;
+ }
+ return travel_distance;
+ }
+
+ uint64_t rseek(uint8_t c, uint64_t limit) {
+ uint64_t travel_distance = 0;
+ while (index != 0 && element() != c && travel_distance < limit) {
+ (*this)--;
+ travel_distance++;
+ }
+ return travel_distance;
+ }
+
+ void align_gap() {
+ while (page->gap_end < index_to_offset()) {
+ (*page)++;
+ }
+ while (page->gap_end > index_to_offset()) {
+ (*page)--;
+ }
+ }
+
+ void push(uint8_t c) {
+ if (page->gap_start == page->gap_end) {
+ page->split();
+ if (index >= PAGE_SIZE / 2) {
+ page = page->next;
+ index -= PAGE_SIZE / 2;
+ }
+ }
+ align_gap();
+ page->push(c);
+ (*this)++;
+ }
+
+ void pop() {
+ if (page->element_count == 1 && index == 1) {
+ if (page->prev) {
+ (*this)--;
+ delete page->next;
+ } else if (page->next) {
+ page->next->copy_to(page);
+ delete page->next;
+ index = 0;
+ } else {
+ page->pop();
+ index = 0;
+ }
+ } else if (index > 0) {
+ align_gap();
+ page->pop();
+ (*this)--;
+ }
+ }
+
+};
diff --git a/test/page.c b/test/page.cpp
index f558fc6..d0a4d54 100644
--- a/test/page.c
+++ b/test/page.cpp
@@ -1,11 +1,11 @@
#include <curses.h>
#define PAGE_SIZE 32
-#include "../page.c"
+#include "../page.cpp"
int main() {
int exit = 0;
- struct page *page = new_page();
+ Page page = Page();
initscr();
cbreak();
@@ -17,29 +17,29 @@ int main() {
while (!exit) {
clear();
- for (int i = 0; i < page->gap_start; i++) {
- addch(page->elements[i]);
+ for (int i = 0; i < page.gap_start; i++) {
+ addch(page.elements[i]);
}
- for (int i = page->gap_start; i < page->gap_end; i++) {
+ for (int i = page.gap_start; i < page.gap_end; i++) {
addch('.');
}
- for (int i = page->gap_end; i < PAGE_SIZE; i++) {
- addch(page->elements[i]);
+ for (int i = page.gap_end; i < PAGE_SIZE; i++) {
+ addch(page.elements[i]);
}
int input = getch();
switch (input) {
case KEY_LEFT:
- move_gap_backward(page);
+ page--;
break;
case KEY_RIGHT:
- move_gap_forward(page);
+ page++;
break;
case KEY_BACKSPACE:
- delete_at_gap(page);
+ page.pop();
break;
default:
- insert_at_gap(page, input);
+ page.push(input);
}
}
diff --git a/test/point.c b/test/point.cpp
index 0902f47..edf4492 100644
--- a/test/point.c
+++ b/test/point.cpp
@@ -1,13 +1,13 @@
#include <curses.h>
#define PAGE_SIZE 16
-#include "../page.c"
-#include "../point.c"
+#include "../page.cpp"
+#include "../point.cpp"
int main() {
int exit = 0;
- struct page *page = new_page();
- struct point point = {page, 0};
+ Page *page = new Page();
+ Point point = Point(page);
initscr();
start_color();
@@ -29,9 +29,9 @@ int main() {
while (!exit) {
clear();
- struct page *iter = page;
+ Page *iter = page;
while (iter) {
- if (iter == point.page) {
+ if (iter == point.page && iter->gap_end == point.index_to_offset()) {
attron(COLOR_PAIR(1));
} else {
attron(COLOR_PAIR(2));
@@ -56,18 +56,18 @@ int main() {
exit = 1;
break;
case KEY_LEFT:
- move_point_backward(&point);
- align_gap(&point);
+ point--;
+ point.align_gap();
break;
case KEY_RIGHT:
- move_point_forward(&point);
- align_gap(&point);
+ point++;
+ point.align_gap();
break;
case KEY_BACKSPACE:
- delete_at_point(&point);
+ point.pop();
break;
default:
- insert_at_point(&point, input);
+ point.push(input);
}
}