Fix input line wrapping pushing chat up
- Horizontal scroll for input when exceeding terminal width - Never wraps to next line or disturbs scroll region
This commit is contained in:
@@ -768,10 +768,58 @@ static size_t utf8_back(const char *buf, size_t pos)
|
|||||||
static void redraw_input(const char *input_line, size_t input_len,
|
static void redraw_input(const char *input_line, size_t input_len,
|
||||||
size_t input_pos)
|
size_t input_pos)
|
||||||
{
|
{
|
||||||
|
int avail = term_cols - 2; /* columns available after "> " */
|
||||||
|
size_t total_cols = display_cols(input_line, input_len);
|
||||||
size_t cpos_cols = display_cols(input_line, input_pos);
|
size_t cpos_cols = display_cols(input_line, input_pos);
|
||||||
|
|
||||||
printf("\033[%d;1H\033[K\033[32m>\033[0m ", term_rows);
|
printf("\033[%d;1H\033[K\033[32m>\033[0m ", term_rows);
|
||||||
fwrite(input_line, 1, input_len, stdout);
|
|
||||||
printf("\033[%d;%dH", term_rows, (int)(cpos_cols + 3));
|
if ((int)total_cols <= avail) {
|
||||||
|
/* Fits entirely */
|
||||||
|
fwrite(input_line, 1, input_len, stdout);
|
||||||
|
printf("\033[%d;%dH", term_rows, (int)(cpos_cols + 3));
|
||||||
|
} else {
|
||||||
|
/* Scroll horizontally: show a window around cursor */
|
||||||
|
size_t win_start_bytes = 0;
|
||||||
|
size_t win_start_cols = 0;
|
||||||
|
|
||||||
|
/* If cursor is past the visible area, shift window */
|
||||||
|
if ((int)cpos_cols >= avail) {
|
||||||
|
/* Move window so cursor is near the right edge */
|
||||||
|
size_t target_cols = cpos_cols - (size_t)(avail - 1);
|
||||||
|
size_t i = 0, cols = 0;
|
||||||
|
while (i < input_len && cols < target_cols) {
|
||||||
|
unsigned char c = (unsigned char)input_line[i];
|
||||||
|
if (c < 0x80) i++;
|
||||||
|
else if ((c & 0xE0) == 0xC0) i += 2;
|
||||||
|
else if ((c & 0xF0) == 0xE0) i += 3;
|
||||||
|
else if ((c & 0xF8) == 0xF0) i += 4;
|
||||||
|
else i++;
|
||||||
|
cols++;
|
||||||
|
}
|
||||||
|
win_start_bytes = i;
|
||||||
|
win_start_cols = cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write characters that fit in avail columns */
|
||||||
|
size_t i = win_start_bytes;
|
||||||
|
int cols_written = 0;
|
||||||
|
while (i < input_len && cols_written < avail) {
|
||||||
|
unsigned char c = (unsigned char)input_line[i];
|
||||||
|
size_t clen = 1;
|
||||||
|
if (c >= 0x80) {
|
||||||
|
if ((c & 0xE0) == 0xC0) clen = 2;
|
||||||
|
else if ((c & 0xF0) == 0xE0) clen = 3;
|
||||||
|
else if ((c & 0xF8) == 0xF0) clen = 4;
|
||||||
|
}
|
||||||
|
fwrite(input_line + i, 1, clen, stdout);
|
||||||
|
i += clen;
|
||||||
|
cols_written++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cursor_col = (int)(cpos_cols - win_start_cols + 3);
|
||||||
|
printf("\033[%d;%dH", term_rows, cursor_col);
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user