Move folder

This commit is contained in:
2026-04-13 10:32:46 +01:00
parent c683754d49
commit 037f884050
107 changed files with 292 additions and 155 deletions

113
include/editor/visual.h Executable file
View File

@@ -0,0 +1,113 @@
#include "editor/decl.h"
#include "io/knot.h"
#include "io/sysio.h"
#include "utils/utils.h"
struct GraphemeIterator {
char *line{nullptr};
uint32_t len{0};
GraphemeIterator(char *line, uint32_t len) : line(line), len(len) {}
char *next(uint32_t *o_len, uint32_t *o_width) {
if (!line || len == 0)
return nullptr;
char *cur = line;
uint32_t g = grapheme_next_character_break_utf8(cur, len);
if (o_width)
*o_width = display_width(cur, g);
if (o_len)
*o_len = g;
line += g;
len -= g;
return cur;
}
};
struct VisualIterator {
LineIterator *it{nullptr};
uint32_t line_index{UINT32_MAX};
uint32_t offset{0};
uint32_t len{0};
bool first{true};
char *line{nullptr};
uint32_t render_width{io::cols};
std::stack<std::pair<Coord, Coord>> prev_stack;
VisualIterator(Knot *root, Coord pos, uint32_t width)
: it(begin_l_iter(root, pos.row)), offset(pos.col),
line_index(pos.row - 1), render_width(width) {}
std::pair<Coord, Coord> prev() {
if (!it)
return {{UINT32_MAX, UINT32_MAX}, {UINT32_MAX, UINT32_MAX}};
if (prev_stack.empty())
return _prev();
auto ret = prev_stack.top();
offset = ret.first.col;
prev_stack.pop();
return ret;
}
std::pair<Coord, Coord> _prev() {
if (!it)
return {{UINT32_MAX, UINT32_MAX}, {UINT32_MAX, UINT32_MAX}};
line_index--;
line = prev_line(it, &len);
if (!line)
return {{UINT32_MAX, UINT32_MAX}, {UINT32_MAX, UINT32_MAX}};
if (len > 0 && line[len - 1] == '\n')
len--;
offset = first ? offset : 0;
first = false;
GraphemeIterator g(line + offset, len - offset);
uint32_t o_len, o_width, rendered = 0, advance = 0;
while (g.next(&o_len, &o_width)) {
if (rendered + o_width > render_width) {
prev_stack.push({{line_index, offset}, {line_index, offset + advance}});
offset += advance;
rendered = 0;
advance = 0;
}
advance += o_len;
rendered += o_width;
}
return {{line_index, offset}, {line_index, offset + advance}};
}
std::pair<Coord, Coord> next() {
if (!it)
return {{UINT32_MAX, UINT32_MAX}, {UINT32_MAX, UINT32_MAX}};
if (!line) {
line_index++;
line = next_line(it, &len);
if (!line)
return {{UINT32_MAX, UINT32_MAX}, {UINT32_MAX, UINT32_MAX}};
if (len > 0 && line[len - 1] == '\n')
len--;
offset = first ? offset : 0;
first = false;
}
GraphemeIterator g(line + offset, len - offset);
uint32_t o_len, o_width, rendered = 0, advance = 0;
while (g.next(&o_len, &o_width)) {
if (rendered + o_width > render_width) {
offset += advance;
return {{line_index, offset - advance}, {line_index, offset}};
}
advance += o_len;
rendered += o_width;
}
offset += advance;
if (offset >= len)
line = nullptr;
return {{line_index, offset}, {line_index, offset + advance}};
}
~VisualIterator() {
if (!it)
return;
free(it->buffer);
free(it);
}
};