Files
crib/src/editor/selection.cc

112 lines
3.2 KiB
C++

#include "editor/editor.h"
#include "utils/utils.h"
void selection_bounds(Editor *editor, Coord *out_start, Coord *out_end) {
std::shared_lock lock(editor->knot_mtx);
Coord start, end;
if (editor->cursor >= editor->selection) {
uint32_t prev_col;
switch (editor->selection_type) {
case CHAR:
start = editor->selection;
end = move_right(editor, editor->cursor, 1);
break;
case WORD:
word_boundaries(editor, editor->selection, &prev_col, nullptr, nullptr,
nullptr);
start = {editor->selection.row, prev_col};
end = editor->cursor;
break;
case LINE:
start = {editor->selection.row, 0};
end = editor->cursor;
break;
}
} else {
start = editor->cursor;
uint32_t next_col, line_len;
switch (editor->selection_type) {
case CHAR:
end = move_right(editor, editor->selection, 1);
break;
case WORD:
word_boundaries(editor, editor->selection, nullptr, &next_col, nullptr,
nullptr);
end = {editor->selection.row, next_col};
break;
case LINE:
LineIterator *it = begin_l_iter(editor->root, editor->selection.row);
char *line = next_line(it, &line_len);
if (!line)
return;
if (line_len > 0 && line[line_len - 1] == '\n')
line_len--;
end = {editor->selection.row, line_len};
free(it->buffer);
free(it);
break;
}
}
if (out_start)
*out_start = start;
if (out_end)
*out_end = end;
}
char *get_selection(Editor *editor, uint32_t *out_len, Coord *out_start) {
std::shared_lock lock(editor->knot_mtx);
Coord start, end;
if (editor->cursor >= editor->selection) {
uint32_t prev_col;
switch (editor->selection_type) {
case CHAR:
start = editor->selection;
end = move_right(editor, editor->cursor, 1);
break;
case WORD:
word_boundaries(editor, editor->selection, &prev_col, nullptr, nullptr,
nullptr);
start = {editor->selection.row, prev_col};
end = editor->cursor;
break;
case LINE:
start = {editor->selection.row, 0};
end = editor->cursor;
break;
}
} else {
start = editor->cursor;
uint32_t next_col, line_len;
switch (editor->selection_type) {
case CHAR:
end = move_right(editor, editor->selection, 1);
break;
case WORD:
word_boundaries(editor, editor->selection, nullptr, &next_col, nullptr,
nullptr);
end = {editor->selection.row, next_col};
break;
case LINE:
LineIterator *it = begin_l_iter(editor->root, editor->selection.row);
char *line = next_line(it, &line_len);
if (!line)
return nullptr;
if (line_len > 0 && line[line_len - 1] == '\n')
line_len--;
end = {editor->selection.row, line_len};
free(it->buffer);
free(it);
break;
}
}
if (out_start)
*out_start = start;
uint32_t start_byte =
line_to_byte(editor->root, start.row, nullptr) + start.col;
uint32_t end_byte = line_to_byte(editor->root, end.row, nullptr) + end.col;
char *text = read(editor->root, start_byte, end_byte - start_byte);
if (out_len)
*out_len = end_byte - start_byte;
return text;
}