diff options
Diffstat (limited to 'point.c')
-rw-r--r-- | point.c | 87 |
1 files changed, 87 insertions, 0 deletions
@@ -0,0 +1,87 @@ +#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); + } +} + +uint8_t element(struct point *point) { + return point->page->buffer[index_to_offset(point)]; +} + +bool at_eof(struct point *point) { + return point->index == point->page->element_count; +} + +void move_point_forward(struct point *point) { + if (point->index < point->page->element_count) { + point->index++; + } + if (point->index == point->page->element_count && point->page->next) { + point->index = 0; + point->page = point->page->next; + } +} + +void move_point_backward(struct point *point) { + if (point->index == 0 && point->page->prev) { + point->index = point->page->prev->element_count; + point->page = point->page->prev; + } + if (point->index > 0) { + point->index--; + } +} + +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); + point->page->buffer[point->page->gap_start] = c; + point->page->gap_start++; + point->page->element_count++; + move_point_forward(point); +} + +void delete_at_point(struct point *point) { + if (point->page->element_count == 0) { + if (point->page->prev) { + point->page = point->page->prev; + point->index = point->page->element_count; + free_page(point->page->next); + } else if (point->page->next) { + point->page = point->page->next; + point->index = 0; + free_page(point->page->prev); + } + } + align_gap(point); + if (point->page->gap_start != 0) { + point->page->gap_start--; + point->page->element_count--; + move_point_backward(point); + } +} |