171 lines
3.6 KiB
C++
171 lines
3.6 KiB
C++
#include "gap_buffer.hpp"
|
|
|
|
#include "sh7091/serial.hpp"
|
|
/*
|
|
2 3 4 5 6 7
|
|
s e
|
|
[a] [ ] [b] [q] | [ ] [ ] [ ] [ ]
|
|
i ^
|
|
*/
|
|
|
|
void line_init_from_buf(struct gap_buffer& gb,
|
|
int32_t * offsets,
|
|
int32_t size)
|
|
{
|
|
gb.line.offsets = offsets;
|
|
gb.line.size = size;
|
|
gb.line.length = 0;
|
|
|
|
for (int32_t i = 0; i < gb.gap_start; i++) {
|
|
serial::integer<uint32_t>(i);
|
|
if (gb.buf[i] == '\n') {
|
|
gb.line.offsets[gb.line.length++] = i;
|
|
}
|
|
}
|
|
|
|
gb.line.gap = gb.line.length;
|
|
|
|
for (int32_t i = gb.gap_end; i < gb.size; i++) {
|
|
if (gb.buf[i] == '\n') {
|
|
gb.line.offsets[gb.line.length++] = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gap_init_from_buf(struct gap_buffer& gb,
|
|
char_type * buf,
|
|
int32_t size,
|
|
int32_t length)
|
|
{
|
|
gb.buf = buf;
|
|
gb.size = size;
|
|
|
|
gb.gap_start = length;
|
|
gb.gap_end = size;
|
|
}
|
|
|
|
/*
|
|
void gap_resize(struct gap_buffer& gb)
|
|
{
|
|
for (int32_t i = (gb.size - 1); i >= gb.gap_end; i--) {
|
|
gb.buf[i + gb.size] = gb.buf[i];
|
|
}
|
|
gb.gap_end += gb.size;
|
|
gb.size += gb.size;
|
|
}
|
|
*/
|
|
|
|
void gap_append(struct gap_buffer& gb, char_type c)
|
|
{
|
|
if (gb.gap_start == gb.gap_end) {
|
|
return;
|
|
//gap_resize(gb);
|
|
}
|
|
|
|
if (c == '\n') {
|
|
for (int32_t i = gb.line.length - 1; i >= gb.line.gap; i--) {
|
|
gb.line.offsets[i + 1] = gb.line.offsets[i];
|
|
}
|
|
gb.line.offsets[gb.line.gap++] = gb.gap_start;
|
|
gb.line.length += 1;
|
|
}
|
|
gb.buf[gb.gap_start++] = c;
|
|
}
|
|
|
|
void gap_pop(struct gap_buffer& gb)
|
|
{
|
|
gb.gap_start--;
|
|
if (gb.buf[gb.gap_start] == '\n') {
|
|
for (int32_t i = gb.line.gap; i < gb.line.length; i++) {
|
|
gb.line.offsets[i - 1] = gb.line.offsets[i];
|
|
}
|
|
gb.line.gap -= 1;
|
|
gb.line.length -= 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
0 1 2 3 4 5 6 7
|
|
[a] [b] [ ] [ ] [ ] [ ] [q] [r]
|
|
^ e
|
|
*/
|
|
|
|
/*
|
|
*/
|
|
|
|
void gap_cursor_pos(struct gap_buffer& gb, int32_t delta)
|
|
{
|
|
if (delta > 0) {
|
|
if (gb.gap_end + delta >= gb.size) {
|
|
delta = gb.size - gb.gap_end;
|
|
}
|
|
for (int32_t i = 0; i < delta; i++) {
|
|
char_type c = gb.buf[gb.gap_end++];
|
|
if (c == '\n') {
|
|
gb.line.offsets[gb.line.gap++] = gb.gap_start;
|
|
}
|
|
gb.buf[gb.gap_start++] = c;
|
|
}
|
|
} else {
|
|
if (gb.gap_start + delta < 0) {
|
|
delta = -gb.gap_start;
|
|
}
|
|
for (int32_t i = delta; i < 0; i++) {
|
|
char_type c = gb.buf[--gb.gap_start];
|
|
gb.buf[--gb.gap_end] = c;
|
|
if (c == '\n') {
|
|
gb.line.offsets[--gb.line.gap] = gb.gap_end;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void gap_cursor_pos_abs(struct gap_buffer& gb, int32_t pos)
|
|
{
|
|
if (pos > gb.gap_start) {
|
|
pos -= (gb.gap_end - gb.gap_start);
|
|
}
|
|
gap_cursor_pos(gb, pos - gb.gap_start);
|
|
}
|
|
|
|
int32_t gap_column_number(struct gap_buffer& gb)
|
|
{
|
|
int32_t line_start = 0;
|
|
if (gb.line.gap > 0)
|
|
line_start = gb.line.offsets[gb.line.gap - 1] + 1;
|
|
return gb.gap_start - line_start;
|
|
}
|
|
|
|
constexpr inline int32_t min(int32_t a, int32_t b)
|
|
{
|
|
return (a < b) ? a : b;
|
|
}
|
|
|
|
constexpr inline int32_t max(int32_t a, int32_t b)
|
|
{
|
|
return (a > b) ? a : b;
|
|
}
|
|
|
|
void gap_cursor_pos_line(struct gap_buffer& gb, int32_t delta)
|
|
{
|
|
if (delta > 0) {
|
|
int32_t max_pos_delta = gb.line.length - gb.line.gap;
|
|
delta = min(max_pos_delta, delta);
|
|
} else {
|
|
int32_t min_pos_delta = (-gb.line.gap) - 1;
|
|
delta = max(min_pos_delta, delta);
|
|
}
|
|
if (delta == 0)
|
|
return;
|
|
int32_t column = gap_column_number(gb);
|
|
int32_t offset_ix = (gb.line.gap - 1) + delta;
|
|
int32_t buf_ix = 0;
|
|
if (offset_ix >= 0)
|
|
buf_ix = gb.line.offsets[offset_ix] + 1;
|
|
while (buf_ix < gb.size && column > 0 && gb.buf[buf_ix] != '\n') {
|
|
buf_ix += 1;
|
|
column -= 1;
|
|
}
|
|
gap_cursor_pos_abs(gb, buf_ix);
|
|
}
|