112 lines
3.2 KiB
C++
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;
|
|
}
|