106 lines
2.0 KiB
C
106 lines
2.0 KiB
C
|
|
#include "line-editor.h"
|
||
|
|
|
||
|
|
#include <fx/encoding.h>
|
||
|
|
|
||
|
|
static void convert_offset_to_xy(
|
||
|
|
struct bshell_line_ed_p *ed,
|
||
|
|
unsigned long offset,
|
||
|
|
unsigned long *out_x,
|
||
|
|
unsigned long *out_y)
|
||
|
|
{
|
||
|
|
unsigned long x = 0, y = 0;
|
||
|
|
unsigned int w = 0, h = 0;
|
||
|
|
fx_tty_get_dimensions(ed->ed_tty, &w, &h);
|
||
|
|
if (!w || !h) {
|
||
|
|
w = 80;
|
||
|
|
h = 25;
|
||
|
|
}
|
||
|
|
|
||
|
|
fx_string *prompt = line_ed_get_prompt(ed);
|
||
|
|
fx_string *buffer = line_ed_get_buffer(ed);
|
||
|
|
const char *s = fx_string_get_cstr(prompt);
|
||
|
|
size_t len = fx_string_get_size(prompt, FX_STRLEN_CODEPOINTS);
|
||
|
|
fx_wchar prev = FX_WCHAR_INVALID;
|
||
|
|
|
||
|
|
for (unsigned long i = 0; i < len; i++) {
|
||
|
|
fx_wchar c = fx_wchar_utf8_codepoint_decode(s);
|
||
|
|
if (prev != FX_WCHAR_INVALID) {
|
||
|
|
if (prev == '\n' || x + 1 >= w) {
|
||
|
|
x = 0;
|
||
|
|
y++;
|
||
|
|
} else {
|
||
|
|
x += line_ed_get_char_width(c);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
unsigned int stride = fx_wchar_utf8_codepoint_size(c);
|
||
|
|
if (stride == 0) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
s += stride;
|
||
|
|
prev = c;
|
||
|
|
}
|
||
|
|
|
||
|
|
s = fx_string_get_cstr(buffer);
|
||
|
|
len = fx_string_get_size(buffer, FX_STRLEN_CODEPOINTS);
|
||
|
|
for (unsigned long i = 0; i < offset && i < len; i++) {
|
||
|
|
fx_wchar c = fx_wchar_utf8_codepoint_decode(s);
|
||
|
|
if (prev != FX_WCHAR_INVALID) {
|
||
|
|
if (prev == '\n' || x + 1 >= w) {
|
||
|
|
x = 0;
|
||
|
|
y++;
|
||
|
|
} else {
|
||
|
|
x += line_ed_get_char_width(c);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
unsigned int stride = fx_wchar_utf8_codepoint_size(c);
|
||
|
|
if (stride == 0) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
s += stride;
|
||
|
|
prev = c;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (offset > len) {
|
||
|
|
if (x + 1 >= w) {
|
||
|
|
x = 0;
|
||
|
|
y++;
|
||
|
|
} else {
|
||
|
|
x++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (out_x) {
|
||
|
|
*out_x = x;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (out_y) {
|
||
|
|
*out_y = y;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void line_ed_get_points(struct bshell_line_ed_p *ed, struct cursor_points *out)
|
||
|
|
{
|
||
|
|
unsigned long cursor = line_ed_get_cursor(ed);
|
||
|
|
fx_string *buffer = line_ed_get_buffer(ed);
|
||
|
|
|
||
|
|
convert_offset_to_xy(
|
||
|
|
ed,
|
||
|
|
cursor + 1,
|
||
|
|
&out->c_cursor_x,
|
||
|
|
&out->c_cursor_y);
|
||
|
|
convert_offset_to_xy(
|
||
|
|
ed,
|
||
|
|
fx_string_get_size(buffer, FX_STRLEN_CODEPOINTS),
|
||
|
|
&out->c_render_limit_x,
|
||
|
|
&out->c_render_limit_y);
|
||
|
|
convert_offset_to_xy(
|
||
|
|
ed,
|
||
|
|
fx_string_get_size(buffer, FX_STRLEN_CODEPOINTS) + 1,
|
||
|
|
&out->c_cursor_limit_x,
|
||
|
|
&out->c_cursor_limit_y);
|
||
|
|
}
|