Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions include/slash/slash.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,9 @@ struct slash_command {
* @cursor_screen: Current index of cursor in line buffer on screen.
* @length: Current amount of used bytes in line buffer.
* @length_screen: Current amount of used bytes in line buffer on screen.
* @change_start: Index of first byte in line buffer that needs screen refresh.
* @change_end: Index of first byte in line buffer that does not need screen refresh.
* @refresh_full: Force a full screen refresh including prompt.
* @refresh_buffer: Force a screen refresh of buffer.
* @last_char: Last input character.
* @history_size: Size in byte of the history buffer.
* @history_depth: Number of history entries browsed back.
Expand Down Expand Up @@ -314,8 +315,9 @@ struct slash {
size_t cursor_screen;
size_t length;
size_t length_screen;
size_t change_start;
size_t change_end;
bool refresh_full;
bool refresh_buffer;
char last_char;

/* History */
Expand Down
166 changes: 107 additions & 59 deletions src/slash.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,19 @@ static int slash_getchar(struct slash *slash)
return c;
}

static void slash_mark_changed(struct slash *slash, size_t start, size_t end)
{
if (slash->change_start == slash->change_end) {
slash->change_start = start;
slash->change_end = end;
} else {
if (start < slash->change_start)
slash->change_start = start;
if (end > slash->change_end)
slash->change_end = end;
}
}

#ifdef SLASH_HAVE_SELECT
static int slash_wait_select(struct slash *slash, unsigned int ms)
{
Expand Down Expand Up @@ -622,7 +635,9 @@ static void slash_set_completion(struct slash *slash,
complete[len] = '\0';
if (space)
strncat(complete, " ", slash->line_size - 1);
slash->cursor = slash->length = strlen(slash->buffer);
slash->length = strlen(slash->buffer);
slash_mark_changed(slash, slash->cursor, slash->length);
slash->cursor = slash->length;
}

static bool slash_complete_matches(struct slash *slash,
Expand Down Expand Up @@ -875,7 +890,7 @@ static bool slash_history_next(struct slash *slash)
slash->buffer[srclen] = '\0';
slash->history_cursor = src;
slash->cursor = slash->length = srclen;
slash->refresh_buffer = true;
slash_mark_changed(slash, 0, slash->length);

/* Rewind if use to store buffer temporarily */
if (!slash->history_depth && slash->history_cursor != slash->history_tail)
Expand Down Expand Up @@ -905,28 +920,64 @@ static bool slash_history_previous(struct slash *slash)
slash->buffer[srclen] = '\0';
slash->history_cursor = src;
slash->cursor = slash->length = srclen;
slash->refresh_buffer = true;
slash_mark_changed(slash, 0, slash->length);

return true;
}

/* Line editing */
static int slash_cursor_back(struct slash *slash, size_t n)
static int slash_screen_cursor_back(struct slash *slash, size_t n)
{
/* If we need to move more than 3 colums, CUB uses fewer bytes */
if (n > 3) {
slash_printf(slash, ESCAPE("%zuD"), n);
slash->cursor_screen -= n;
} else {
while (n--)
while (n--) {
slash_putchar(slash, '\b');
slash->cursor_screen--;
}
}

return 0;
}

static int slash_screen_cursor_forward(struct slash *slash, size_t n)
{
/* If we need to move more than 3 colums, CUF uses fewer bytes */
if (n > 3) {
slash_printf(slash, ESCAPE("%zuC"), n);
slash->cursor_screen += n;
} else {
while (n--) {
slash_putchar(slash, slash->buffer[slash->cursor_screen]);
slash->cursor_screen++;
}
}

return 0;
}

static int slash_screen_cursor_to_column(struct slash *slash, size_t col)
{
size_t diff;

if (col > slash->cursor_screen) {
diff = col - slash->cursor_screen;
return slash_screen_cursor_forward(slash, diff);
} else if (col < slash->cursor_screen) {
diff = slash->cursor_screen - col;
return slash_screen_cursor_back(slash, diff);
}

return 0;
}

int slash_refresh(struct slash *slash)
{
const char *esc = ESCAPE("K");

/* Full refresh with prompt */
if (slash->refresh_full) {
slash_putchar(slash, '\r');
if (slash_write(slash, esc, strlen(esc)) < 0)
Expand All @@ -935,61 +986,64 @@ int slash_refresh(struct slash *slash)
return -1;
slash->cursor_screen = 0;
slash->length_screen = 0;
slash->change_start = 0;
slash->change_end = slash->length;
slash->refresh_full = false;
}

if (slash->refresh_buffer) {
slash_cursor_back(slash, slash->cursor_screen);
slash->cursor_screen = 0;
slash->refresh_buffer = false;
}

while (slash->cursor_screen < slash->cursor) {
slash_putchar(slash, slash->buffer[slash->cursor_screen]);
slash->cursor_screen++;
}

if (slash->cursor_screen > slash->cursor) {
slash_cursor_back(slash,
slash->cursor_screen - slash->cursor);
slash->cursor_screen = slash->cursor;
}

if (slash->length_screen != slash->length) {
/* Buffer contents have changed */
if (slash->change_start != slash->change_end) {
if (slash_screen_cursor_to_column(slash, slash->change_start) < 0)
return -1;
if (slash_write(slash,
&slash->buffer[slash->cursor],
slash->length - slash->cursor) < 0)
&slash->buffer[slash->change_start],
slash->change_end - slash->change_start) < 0)
return -1;
slash->cursor_screen = slash->length;

if (slash->length_screen > slash->length) {
if (slash_write(slash, esc, strlen(esc)) < 0)
return -1;
}

if (slash->cursor_screen > slash->cursor) {
slash_cursor_back(slash,
slash->cursor_screen - slash->cursor);
slash->cursor_screen = slash->cursor;
}
slash->cursor_screen = slash->change_end;
slash->change_start = slash->change_end = 0;
}

slash->length_screen = slash->length;
/* If screen contents were truncated, erase remainder */
if (slash->length_screen > slash->length) {
if (slash_screen_cursor_to_column(slash, slash->length) < 0)
return -1;
if (slash_write(slash, esc, strlen(esc)) < 0)
return -1;
}
slash->length_screen = slash->length;

/* Restore screen cursor position */
if (slash_screen_cursor_to_column(slash, slash->cursor) < 0)
return -1;

return slash_write_flush(slash);
}

static void slash_insert(struct slash *slash, int c)
{
if (slash->length + 1 > slash->line_size)
if (slash->length >= slash->line_size)
return;

memmove(&slash->buffer[slash->cursor + 1],
&slash->buffer[slash->cursor],
slash->length - slash->cursor);
slash->buffer[slash->cursor] = c;
slash->cursor++;
slash->length++;
slash_mark_changed(slash, slash->cursor, slash->length);
slash->cursor++;
slash->buffer[slash->length] = '\0';
}

static void slash_delete(struct slash *slash)
{
if (slash->cursor >= slash->length)
return;

slash->length--;
memmove(&slash->buffer[slash->cursor],
&slash->buffer[slash->cursor + 1],
slash->length - slash->cursor);
slash_mark_changed(slash, slash->cursor, slash->length);
slash->buffer[slash->length] = '\0';
}

Expand All @@ -998,6 +1052,8 @@ void slash_reset(struct slash *slash)
slash->buffer[0] = '\0';
slash->length = 0;
slash->cursor = 0;
slash->change_start = 0;
slash->change_end = 0;
slash->refresh_full = true;
}

Expand Down Expand Up @@ -1025,17 +1081,6 @@ static void slash_arrow_left(struct slash *slash)
slash->cursor--;
}

static void slash_delete(struct slash *slash)
{
if (slash->cursor < slash->length) {
slash->length--;
memmove(&slash->buffer[slash->cursor],
&slash->buffer[slash->cursor + 1],
slash->length - slash->cursor);
slash->buffer[slash->length] = '\0';
}
}

void slash_clear_screen(struct slash *slash)
{
const char *esc = ESCAPE("H") ESCAPE("2J");
Expand All @@ -1045,14 +1090,16 @@ void slash_clear_screen(struct slash *slash)

static void slash_backspace(struct slash *slash)
{
if (slash->cursor > 0) {
slash->cursor--;
slash->length--;
memmove(&slash->buffer[slash->cursor],
&slash->buffer[slash->cursor + 1],
slash->length - slash->cursor);
slash->buffer[slash->length] = '\0';
}
if (slash->cursor == 0)
return;

slash->cursor--;
slash->length--;
memmove(&slash->buffer[slash->cursor],
&slash->buffer[slash->cursor + 1],
slash->length - slash->cursor);
slash_mark_changed(slash, slash->cursor, slash->length);
slash->buffer[slash->length] = '\0';
}

static void slash_delete_word(struct slash *slash)
Expand All @@ -1068,6 +1115,7 @@ static void slash_delete_word(struct slash *slash)
memmove(&slash->buffer[slash->cursor],
&slash->buffer[old_cursor],
slash->length - slash->cursor);
slash_mark_changed(slash, slash->cursor, slash->length);
slash->buffer[slash->length] = '\0';
}

Expand Down