diff --git a/tmate-decoder.c b/tmate-decoder.c index 5c207126..34701ebe 100644 --- a/tmate-decoder.c +++ b/tmate-decoder.c @@ -306,6 +306,77 @@ static void tmate_status(struct tmate_unpacker *uk) } } +extern void window_copy_redraw_screen(struct window_pane *); +extern int window_copy_update_selection(struct window_pane *); + +static void tmate_sync_copy_mode(struct tmate_unpacker *uk) +{ + struct tmate_unpacker cm_uk, sel_uk, input_uk; + struct window_copy_mode_data *data; + struct screen_write_ctx ctx; + struct window_pane *wp; + int pane_id; + + pane_id = unpack_int(uk); + wp = window_pane_find_by_id(pane_id); + if (!wp) + tmate_fatal("can't find window pane=%d", pane_id); + + unpack_array(uk, &cm_uk); + + if (cm_uk.argc == 0) { + if (wp->mode) { + data = wp->modedata; + free((char *)data->inputprompt); + window_pane_reset_mode(wp); + } + return; + } + + if (window_pane_set_mode(wp, &window_copy_mode) == 0) + window_copy_init_from_pane(wp); + data = wp->modedata; + + data->oy = unpack_int(&cm_uk); + data->cx = unpack_int(&cm_uk); + data->cy = unpack_int(&cm_uk); + + unpack_array(&cm_uk, &sel_uk); + + if (sel_uk.argc) { + data->screen.sel.flag = 1; + data->selx = unpack_int(&sel_uk); + data->sely = unpack_int(&sel_uk); + data->rectflag = unpack_int(&sel_uk); + } else + data->screen.sel.flag = 0; + + unpack_array(&cm_uk, &input_uk); + + if (input_uk.argc) { + /* + * XXX In the original tmux code, inputprompt is not a + * malloced string, the two piece of code must not run at the + * same time, otherwise, we'll either get a memory leak, or a + * crash. + */ + data->inputtype = unpack_int(&input_uk); + + free((char *)data->inputprompt); + data->inputprompt = unpack_string(&input_uk); + + free(data->inputstr); + data->inputstr = unpack_string(&input_uk); + } else { + data->inputtype = WINDOW_COPY_OFF; + free((char *)data->inputprompt); + data->inputprompt = NULL; + } + + window_copy_update_selection(wp); + window_copy_redraw_screen(wp); +} + static void handle_message(msgpack_object obj) { struct tmate_unpacker _uk; @@ -315,13 +386,14 @@ static void handle_message(msgpack_object obj) init_unpacker(uk, obj); switch (unpack_int(uk)) { - case TMATE_HEADER: tmate_header(uk); break; - case TMATE_SYNC_LAYOUT: tmate_sync_layout(uk); break; - case TMATE_PTY_DATA: tmate_pty_data(uk); break; - case TMATE_EXEC_CMD: tmate_exec_cmd(uk); break; - case TMATE_FAILED_CMD: tmate_failed_cmd(uk); break; - case TMATE_STATUS: tmate_status(uk); break; - default: decoder_error(); + case TMATE_HEADER: tmate_header(uk); break; + case TMATE_SYNC_LAYOUT: tmate_sync_layout(uk); break; + case TMATE_PTY_DATA: tmate_pty_data(uk); break; + case TMATE_EXEC_CMD: tmate_exec_cmd(uk); break; + case TMATE_FAILED_CMD: tmate_failed_cmd(uk); break; + case TMATE_STATUS: tmate_status(uk); break; + case TMATE_SYNC_COPY_MODE: tmate_sync_copy_mode(uk); break; + default: decoder_error(); } } diff --git a/tmate.h b/tmate.h index acbf0801..8a2e1faf 100644 --- a/tmate.h +++ b/tmate.h @@ -38,7 +38,7 @@ extern int tmate_should_exec_cmd_locally(const struct cmd_entry *cmd); /* tmate-decoder.c */ -#define TMATE_HLIMIT 1000 +#define TMATE_HLIMIT 2000 #define TMATE_MAX_MESSAGE_SIZE (16*1024) extern char *tmate_left_status, *tmate_right_status; @@ -50,6 +50,7 @@ enum tmate_commands { TMATE_EXEC_CMD, TMATE_FAILED_CMD, TMATE_STATUS, + TMATE_SYNC_COPY_MODE, }; #define TMATE_PANE_ACTIVE 1 diff --git a/tmux.h b/tmux.h index 7e37afa2..f3141765 100644 --- a/tmux.h +++ b/tmux.h @@ -2251,6 +2251,68 @@ void layout_set_active_changed(struct window *); extern const struct window_mode window_clock_mode; /* window-copy.c */ +enum window_copy_input_type { + WINDOW_COPY_OFF, + WINDOW_COPY_NUMERICPREFIX, + WINDOW_COPY_SEARCHUP, + WINDOW_COPY_SEARCHDOWN, + WINDOW_COPY_JUMPFORWARD, + WINDOW_COPY_JUMPBACK, + WINDOW_COPY_JUMPTOFORWARD, + WINDOW_COPY_JUMPTOBACK, + WINDOW_COPY_GOTOLINE, +}; + +/* + * Copy-mode's visible screen (the "screen" field) is filled from one of + * two sources: the original contents of the pane (used when we + * actually enter via the "copy-mode" command, to copy the contents of + * the current pane), or else a series of lines containing the output + * from an output-writing tmux command (such as any of the "show-*" or + * "list-*" commands). + * + * In either case, the full content of the copy-mode grid is pointed at + * by the "backing" field, and is copied into "screen" as needed (that + * is, when scrolling occurs). When copy-mode is backed by a pane, + * backing points directly at that pane's screen structure (&wp->base); + * when backed by a list of output-lines from a command, it points at + * a newly-allocated screen structure (which is deallocated when the + * mode ends). + */ +struct window_copy_mode_data { + struct screen screen; + + struct screen *backing; + int backing_written; /* backing display has started */ + + struct mode_key_data mdata; + + u_int oy; + + u_int selx; + u_int sely; + + u_int rectflag; /* are we in rectangle copy mode? */ + + u_int cx; + u_int cy; + + u_int lastcx; /* position in last line with content */ + u_int lastsx; /* size of last line with content */ + + enum window_copy_input_type inputtype; + const char *inputprompt; + char *inputstr; + + int numprefix; + + enum window_copy_input_type searchtype; + char *searchstr; + + enum window_copy_input_type jumptype; + char jumpchar; +}; + extern const struct window_mode window_copy_mode; void window_copy_init_from_pane(struct window_pane *); void window_copy_init_for_output(struct window_pane *); diff --git a/window-copy.c b/window-copy.c index 173550f8..b5523906 100644 --- a/window-copy.c +++ b/window-copy.c @@ -89,68 +89,6 @@ const struct window_mode window_copy_mode = { NULL, }; -enum window_copy_input_type { - WINDOW_COPY_OFF, - WINDOW_COPY_NUMERICPREFIX, - WINDOW_COPY_SEARCHUP, - WINDOW_COPY_SEARCHDOWN, - WINDOW_COPY_JUMPFORWARD, - WINDOW_COPY_JUMPBACK, - WINDOW_COPY_JUMPTOFORWARD, - WINDOW_COPY_JUMPTOBACK, - WINDOW_COPY_GOTOLINE, -}; - -/* - * Copy-mode's visible screen (the "screen" field) is filled from one of - * two sources: the original contents of the pane (used when we - * actually enter via the "copy-mode" command, to copy the contents of - * the current pane), or else a series of lines containing the output - * from an output-writing tmux command (such as any of the "show-*" or - * "list-*" commands). - * - * In either case, the full content of the copy-mode grid is pointed at - * by the "backing" field, and is copied into "screen" as needed (that - * is, when scrolling occurs). When copy-mode is backed by a pane, - * backing points directly at that pane's screen structure (&wp->base); - * when backed by a list of output-lines from a command, it points at - * a newly-allocated screen structure (which is deallocated when the - * mode ends). - */ -struct window_copy_mode_data { - struct screen screen; - - struct screen *backing; - int backing_written; /* backing display has started */ - - struct mode_key_data mdata; - - u_int oy; - - u_int selx; - u_int sely; - - u_int rectflag; /* are we in rectangle copy mode? */ - - u_int cx; - u_int cy; - - u_int lastcx; /* position in last line with content */ - u_int lastsx; /* size of last line with content */ - - enum window_copy_input_type inputtype; - const char *inputprompt; - char *inputstr; - - int numprefix; - - enum window_copy_input_type searchtype; - char *searchstr; - - enum window_copy_input_type jumptype; - char jumpchar; -}; - struct screen * window_copy_init(struct window_pane *wp) {