чување 6ea2dd3f75174c680d0eaf08792222f2d823faea
родитељ 16e40914fc3cea52c854011cffbb0f517787d254
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Tue, 22 Feb 2022 20:16:49 +0100
WIP copy/paste
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
измењених датотека: 6, додавања: 209(+), брисања: 92(-)
diff --git a/config.def.h b/config.def.h
@@ -69,11 +69,13 @@ int move_screen_top(struct DrawState* state);
int move_start(struct DrawState* state);
int move_top(struct DrawState* state);
int move_up(struct DrawState* state);
+int paste_from_paste(struct DrawState* state);
int reread_or_callback(struct DrawState* state);
int show_go_to_line(struct DrawState* state);
int show_help(struct DrawState* state);
int toggle_selection(struct DrawState* state);
int write_file(struct DrawState* state);
+int yank_to_paste(struct DrawState* state);
/* clang-format off */
@@ -102,6 +104,8 @@ static const struct Key global_keys[] = {
.callback = move_start },
{ .ev = { .key = TB_KEY_CTRL_B },
.callback = move_page_up },
+ { .ev = { .key = TB_KEY_CTRL_C },
+ .callback = yank_to_paste },
{ .ev = { .key = TB_KEY_CTRL_E },
.callback = move_end },
{ .ev = { .key = TB_KEY_CTRL_F },
@@ -122,6 +126,8 @@ static const struct Key global_keys[] = {
.callback = move_next_word },
{ .ev = { .key = TB_KEY_CTRL_U },
.callback = erase_to_start },
+ { .ev = { .key = TB_KEY_CTRL_V },
+ .callback = paste_from_paste },
{ .ev = { .key = TB_KEY_DELETE },
.callback = erase_forward },
{ .ev = { .key = TB_KEY_F1 }, .callback = show_help },
@@ -167,7 +173,7 @@ static const struct Key input_dialog_keys[] = {
/* Only when in insert mode */
static const struct Key insert_keys[] = {
- { .ev = { .key = TB_KEY_CTRL_C },
+ { .ev = { .key = TB_KEY_CTRL_M },
.callback = enter_command_mode },
{ .ev = { .key = TB_KEY_ENTER },
.callback = insert_line },
@@ -178,7 +184,7 @@ static const struct Key insert_keys[] = {
/* Only when in command mode */
static const struct Key command_keys[] = {
- { .ev = { .key = TB_KEY_CTRL_C },
+ { .ev = { .key = TB_KEY_CTRL_M },
.callback = enter_insert_mode },
{ .ev = { .ch = ':' }, .callback = show_go_to_line },
{ .ev = { .ch = '0' }, .callback = move_start },
@@ -192,10 +198,12 @@ static const struct Key command_keys[] = {
{ .ev = { .ch = 'L' }, .callback = move_screen_bottom },
{ .ev = { .ch = 'l' }, .callback = move_right },
{ .ev = { .ch = 'M' }, .callback = move_screen_middle },
+ { .ev = { .ch = 'p' }, .callback = paste_from_paste },
{ .ev = { .ch = 'q' }, .callback = exit_program },
{ .ev = { .ch = 'v' }, .callback = toggle_selection },
{ .ev = { .ch = 'W' }, .callback = move_prev_word },
- { .ev = { .ch = 'w' }, .callback = move_next_word }
+ { .ev = { .ch = 'w' }, .callback = move_next_word },
+ { .ev = { .ch = 'y' }, .callback = yank_to_paste }
};
/* clang-format on */
#endif /* SLED_C_GLOBALS */
diff --git a/config.h b/config.h
@@ -69,11 +69,13 @@ int move_screen_top(struct DrawState* state);
int move_start(struct DrawState* state);
int move_top(struct DrawState* state);
int move_up(struct DrawState* state);
+int paste_from_paste(struct DrawState* state);
int reread_or_callback(struct DrawState* state);
int show_go_to_line(struct DrawState* state);
int show_help(struct DrawState* state);
int toggle_selection(struct DrawState* state);
int write_file(struct DrawState* state);
+int yank_to_paste(struct DrawState* state);
/* clang-format off */
@@ -102,6 +104,8 @@ static const struct Key global_keys[] = {
.callback = move_start },
{ .ev = { .key = TB_KEY_CTRL_B },
.callback = move_page_up },
+ { .ev = { .key = TB_KEY_CTRL_C },
+ .callback = yank_to_paste },
{ .ev = { .key = TB_KEY_CTRL_E },
.callback = move_end },
{ .ev = { .key = TB_KEY_CTRL_F },
@@ -122,6 +126,8 @@ static const struct Key global_keys[] = {
.callback = move_next_word },
{ .ev = { .key = TB_KEY_CTRL_U },
.callback = erase_to_start },
+ { .ev = { .key = TB_KEY_CTRL_V },
+ .callback = paste_from_paste },
{ .ev = { .key = TB_KEY_DELETE },
.callback = erase_forward },
{ .ev = { .key = TB_KEY_F1 }, .callback = show_help },
@@ -167,7 +173,7 @@ static const struct Key input_dialog_keys[] = {
/* Only when in insert mode */
static const struct Key insert_keys[] = {
- { .ev = { .key = TB_KEY_CTRL_C },
+ { .ev = { .key = TB_KEY_CTRL_M },
.callback = enter_command_mode },
{ .ev = { .key = TB_KEY_ENTER },
.callback = insert_line },
@@ -178,7 +184,7 @@ static const struct Key insert_keys[] = {
/* Only when in command mode */
static const struct Key command_keys[] = {
- { .ev = { .key = TB_KEY_CTRL_C },
+ { .ev = { .key = TB_KEY_CTRL_M },
.callback = enter_insert_mode },
{ .ev = { .ch = ':' }, .callback = show_go_to_line },
{ .ev = { .ch = '0' }, .callback = move_start },
@@ -192,10 +198,12 @@ static const struct Key command_keys[] = {
{ .ev = { .ch = 'L' }, .callback = move_screen_bottom },
{ .ev = { .ch = 'l' }, .callback = move_right },
{ .ev = { .ch = 'M' }, .callback = move_screen_middle },
+ { .ev = { .ch = 'p' }, .callback = paste_from_paste },
{ .ev = { .ch = 'q' }, .callback = exit_program },
{ .ev = { .ch = 'v' }, .callback = toggle_selection },
{ .ev = { .ch = 'W' }, .callback = move_prev_word },
- { .ev = { .ch = 'w' }, .callback = move_next_word }
+ { .ev = { .ch = 'w' }, .callback = move_next_word },
+ { .ev = { .ch = 'y' }, .callback = yank_to_paste }
};
/* clang-format on */
#endif /* SLED_C_GLOBALS */
diff --git a/draw.c b/draw.c
@@ -111,8 +111,9 @@ init_drawstate(struct DrawState* state, char* error, char* action,
state->saved_column = -1;
state->help_width = calculate_help_width(state);
state->input_dialog_width = calculate_input_dialog_width(state);
- state->paste_buffer = NULL;
- state->paste_rows_count = 0;
+ state->paste = NULL;
+ state->paste_count = 0;
+ state->paste_size = 0;
state->prompt = prompt;
state->prompt_callback = NULL;
state->input_callback = NULL;
@@ -137,9 +138,9 @@ free_drawstate(struct DrawState* state)
for (row = 0; row < state->buffer_size; row++)
free_bufferline(state->buffer + row);
free(state->buffer);
- for (row = 0; row < state->paste_rows_count; row++)
- free_bufferline(state->paste_buffer + row);
- free(state->paste_buffer);
+ for (row = 0; row < state->paste_size; row++)
+ free_bufferline(state->paste + row);
+ free(state->paste);
free(state->input);
}
@@ -563,8 +564,8 @@ draw_help(const struct DrawState* state)
draw_box(startx, endx, starty, endy, DLG_FG, DLG_BG);
if (!draw_string(startx, starty, TITLE_FG, TITLE_BG, help_title,
- strlen(help_title) + 2, w - 2, 1, 1, CENTER, 0, 0, NULL, 0,
- 0, 0, 0, 0, 0))
+ strlen(help_title) + 2, w, 1, 1, CENTER, 0, 0, NULL, 0, 0,
+ 0, 0, 0, 0))
return NULL;
while (row < LEN(help))
{
diff --git a/draw.h b/draw.h
@@ -46,13 +46,14 @@ struct DrawState {
int input_display_column;
int input_column;
char* input_title;
- int rows_count;
+ size_t rows_count;
int display_column;
int saved_column;
int help_width;
int input_dialog_width;
- struct BufferLine* paste_buffer;
- int paste_rows_count;
+ struct BufferLine* paste;
+ size_t paste_count;
+ size_t paste_size;
void (*prompt_callback)(struct DrawState*, struct tb_event*);
void (*input_callback)(struct DrawState*);
int running;
diff --git a/sled.1.in b/sled.1.in
@@ -90,12 +90,13 @@ _
\fCHome\fP or \fCC-A\fP@Go to start of line
\fCPgUp\fP or \fCC-B\fP@Go to previous page
\fCBackspace\fP@Erase character before cursor
-\fCC-C\fP@Switch between command and insert mode
+\fCC-C\fP@Yank to paste buffer
\fCDelete\fP@Erase character under cursor
\fCEnd\fP or \fCC-E\fP@Go to end of line
\fCPgDown\fP or \fCC-F\fP@Go to next page
\fCC-K\fP@Erase to end of line
\fCC-L\fP@Show Go to line dialog
+\fCC-M\fP@Switch between command and insert mode
\fCC-O\fP@Reread (reopen) file
\fCC-Q\fP@Quit
\fCC-R\fP@Go to previous word
@@ -103,6 +104,7 @@ _
\fCC-Space\fP@Toggle selection mode
\fCC-T\fP@Go to next word
\fCC-U\fP@Erase to start of line
+\fCC-V\fP@Paste from paste buffer
.TE
.
.sp 1
@@ -137,10 +139,12 @@ _
\fCL\fP@Go to last line on the screen
\fCl\fP@Go to next character
\fCM\fP@Go to middle line on the screen
+\fCp\fP@Paste from paste buffer
\fCq\fP@Quit
\fCv\fP@Toggle selection mode
\fCW\fP@Go to previous word
\fCw\fP@Go to next word
+\fCy\fP@Yank to paste buffer
.TE
.
.sp 1
diff --git a/sled.c b/sled.c
@@ -90,9 +90,9 @@ reread_file(struct DrawState* state)
for (row = 0; row < state->buffer_size; row++)
free_bufferline(state->buffer + row);
free(state->buffer);
- for (row = 0; row < state->paste_rows_count; row++)
- free_bufferline(state->paste_buffer + row);
- free(state->paste_buffer);
+ for (row = 0; row < state->paste_size; row++)
+ free_bufferline(state->paste + row);
+ free(state->paste);
init_drawstate(state, state->error, state->action, state->filename,
state->prompt);
@@ -355,94 +355,189 @@ save_file_cleanup:
return SAVE_ERR_NONE;
}
-struct DrawState*
-paste_paste_buffer_to_input(struct DrawState* state)
+int
+yank_to_paste(struct DrawState* state)
{
- /*
- if (state->edit_info_focused)
- return state;
+ /* Selection start row/col */
+ size_t ssr = 0;
+ size_t ssc = 0;
+ /* Selection end row/col */
+ size_t ser = 0;
+ size_t sec = 0;
+ struct BufferLine* newbuf = NULL;
+
+ if (!SEL_NOT_EMPTY(state))
+ return 0;
- if (!state->in_prompt && *state->input_buffer->text)
+ if (state->sel_start_row <= state->sel_end_row)
{
- state->in_prompt = 1;
- strcpy(state->prompt, prompt_overwrite);
- state->prompt_callback = overwrite_paste_callback;
- return state;
+ ssr = state->sel_start_row;
+ ssc = state->sel_start_col;
+ ser = state->sel_end_row;
+ sec = state->sel_end_col;
+ }
+ else /* Swap */
+ {
+ ssr = state->sel_end_row;
+ ssc = state->sel_end_col;
+ ser = state->sel_start_row;
+ sec = state->sel_start_col;
}
- if (state->msgid_number == 1)
+ state->paste_count = ser - ssr + 1;
+ if (!state->paste_size)
{
- strcpy(state->error, errors[ERR_ILLEGAL_ON_FIRST]);
- return NULL;
+ state->paste_size = ALLOC_DELTA;
+ newbuf = calloc(state->paste_size, sizeof(struct BufferLine));
+ }
+ else if (state->paste_count > state->paste_size)
+ {
+ state->paste_size += ALLOC_DELTA;
+ newbuf = realloc(state->paste,
+ state->paste_size * sizeof(struct BufferLine));
+ }
+ else
+ newbuf = state->paste;
+ for (size_t row = state->paste_size - ALLOC_DELTA;
+ row < state->paste_size; row++)
+ {
+ uint32_t* newtext = NULL;
+ init_bufferline(newbuf + row);
+ newtext = calloc(MAXBUFLINE, sizeof(uint32_t));
+ if (!newtext)
+ strcpy(state->error, errors[ERR_CANT_ALLOC]);
+ newbuf[row].text = newtext;
+ newbuf[row].length = 0;
+ }
+ state->paste = newbuf;
+ if (state->paste_count == 1)
+ state->paste[0].length = u32_strncpy(state->paste[0].text,
+ state->buffer[ssr].text + ssc, sec - ssc + 1);
+ else
+ {
+ state->paste[0].length = u32_strcpy(state->paste[0].text,
+ state->buffer[ssr].text + ssc);
+ for (size_t row = 1; row < state->paste_count - 1; row++)
+ state->paste[row].length
+ = u32_strcpy(state->paste[row].text,
+ state->buffer[ssr + row].text);
+ state->paste[state->paste_count - 1].length
+ = u32_strncpy(state->paste[state->paste_count - 1].text,
+ state->buffer[ser].text, sec + 1);
}
- size_t lines_to_init = 0;
- size_t lines_to_free = 0;
- struct BufferLine* pinput = NULL;
+ clear_selection(state);
+
+ return 0;
+}
+
+int
+paste_from_paste(struct DrawState* state)
+{
+ /* Selection start row/col */
+ size_t ssr = 0;
+ size_t ssc = 0;
+ /* Selection end row/col */
+ size_t ser = 0;
+ size_t sec = 0;
+ uint32_t* newtext = NULL;
+ struct BufferLine* line = NULL;
struct BufferLine* newbuf = NULL;
- struct BufferLine* ppaste = NULL;
-
- if (!state->paste_buffer || !(*state->paste_buffer).text
- || !*(*state->paste_buffer).text)
- {
- / leave one row /
- for (size_t i = 1; i < state->input_rows_count; i++)
- free_bufferline(state->input_buffer + i);
- state->input_buffer = realloc(state->input_buffer,
- sizeof(struct BufferLine));
- *(state->input_buffer->text) = 0;
- state->input_column = 0;
- state->input_display_column = 0;
- state->input_first_shown_column = 0;
- state->input_first_shown_row = 0;
- state->input_row = 0;
- state->input_rows_count = 1;
- state->dirty = 1;
- return state;
- }
-
- lines_to_init = state->input_rows_count < state->paste_rows_count
- ? state->paste_rows_count - state->input_rows_count
- : 0;
- lines_to_free = state->input_rows_count > state->paste_rows_count
- ? state->input_rows_count - state->paste_rows_count
- : 0;
-
- for (size_t i = 0; i < lines_to_free; i++)
- free_bufferline(
- state->input_buffer + state->input_rows_count - i - 1);
- newbuf = realloc(state->input_buffer,
- state->paste_rows_count * sizeof(struct BufferLine));
- ppaste = state->paste_buffer;
-
- if (!newbuf)
- return NULL;
- for (size_t i = 0; i < lines_to_init; i++)
+ if (!state->paste_count)
+ return 0;
+
+ if (SEL_NOT_EMPTY(state))
+ {
+ position_to_selection_start(state);
+ erase_selection(state);
+ clear_selection(state);
+ }
+
+ if (state->paste_count > 1)
{
- pinput = newbuf + state->paste_rows_count - 1 - i;
- init_bufferline(pinput);
- uint32_t* newtext = calloc(MAXBUFLINE, sizeof(uint32_t));
- if (!newtext)
- return NULL;
- pinput->text = newtext;
+ if (state->rows_count + state->paste_count > state->buffer_size)
+ {
+ size_t old_size = state->buffer_size;
+ while (state->rows_count + state->paste_count
+ > state->buffer_size)
+ state->buffer_size += ALLOC_DELTA;
+ newbuf = realloc(state->buffer,
+ state->buffer_size * sizeof(struct BufferLine));
+ for (size_t row = 0;
+ row < state->buffer_size - old_size; row++)
+ {
+ init_bufferline(newbuf + row);
+ newtext = calloc(MAXBUFLINE, sizeof(uint32_t));
+ newbuf[row].text = newtext;
+ }
+ state->buffer = newbuf;
+ }
+ /* TODO: */
+ for (size_t row = 0; row < state->rows_count - state->row; row++)
+ {
+ line = state->buffer + state->row + state->paste_count
+ + row;
+ line->length = u32_strcpy(line->text,
+ state->buffer[state->row + row].text);
+ }
}
- if (ppaste)
- for (size_t i = 0; i < state->paste_rows_count; i++)
+ line = state->buffer + state->row;
+ newtext = calloc(MAXBUFLINE, sizeof(uint32_t));
+ u32_strncpy(newtext, line->text, state->column + 1);
+ u32_strcat(newtext, state->paste[0].text);
+
+ if (state->paste_count == 1)
+ {
+ u32_strcat(newtext, line->text + state->column);
+ line->length = u32_strcpy(line->text, newtext);
+ }
+ else
+ {
+ line->length = u32_strcpy(line->text, newtext);
+ for (size_t row = 1; row < state->paste_count - 1; row++)
{
- pinput = newbuf + i;
- u32_strncpy(pinput->text, ppaste->text,
- MIN(ppaste->length + 1, MAXBUFLINE));
- pinput->length = ppaste->length;
- ppaste++;
+ line = state->buffer + state->row + row;
+ line->length = u32_strcpy(line->text,
+ state->paste[row].text);
}
- state->input_rows_count = state->paste_rows_count;
- state->input_buffer = newbuf;
- state->dirty = 1;
-*/
- return state;
+ line = state->buffer + state->row + state->paste_count - 1;
+ u32_strcpy(newtext, state->paste[state->paste_count - 1].text);
+ u32_strcat(newtext, line->text);
+ line->length = u32_strcpy(line->text, newtext);
+ }
+ free(newtext);
+ /*for (size_t row = state->paste_size - ALLOC_DELTA;
+ row < state->paste_size; row++)
+ {
+ uint32_t* newtext = NULL;
+ init_bufferline(newbuf + row);
+ newtext = calloc(MAXBUFLINE, sizeof(uint32_t));
+ if (!newtext)
+ strcpy(state->error, errors[ERR_CANT_ALLOC]);
+ newbuf[row].text = newtext;
+ newbuf[row].length = 0;
+ }
+ state->paste = newbuf;
+ if (state->paste_count == 0)
+ state->paste[0].length = u32_strncpy(state->paste[0].text,
+ state->buffer[ssr].text + ssc, sec - ssc + 1);
+ else
+ {
+ state->paste[0].length = u32_strcpy(state->paste[0].text,
+ state->buffer[ssr].text + ssc);
+ for (size_t row = 1; row < state->paste_count - 1; row++)
+ state->paste[row].length
+ = u32_strcpy(state->paste[row].text,
+ state->buffer[ssr + row].text);
+ state->paste[state->paste_count - 1].length
+ = u32_strncpy(state->paste[state->paste_count - 1].text,
+ state->buffer[ser].text, sec + 1);
+ }*/
+
+ return 0;
}
int