diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2022-10-05 00:16:57 +0200 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2022-10-05 00:55:59 +0200 | 
| commit | 26ed2dbc77dea089f769180940d452353826eee7 (patch) | |
| tree | 93fcd37e81f88975c786642976624a11f684906b /xC.c | |
| parent | 4b7258cba0dc71cfc7d3adef1b5dd7f9e610c28b (diff) | |
| download | xK-26ed2dbc77dea089f769180940d452353826eee7.tar.gz xK-26ed2dbc77dea089f769180940d452353826eee7.tar.xz xK-26ed2dbc77dea089f769180940d452353826eee7.zip | |
xC: fully synchronize input history with frontends
The missing parts were:
 - frontends to client
 - client to frontends after the initial sync
 - frontend to other frontends
Diffstat (limited to 'xC.c')
| -rw-r--r-- | xC.c | 116 | 
1 files changed, 96 insertions, 20 deletions
| @@ -228,11 +228,13 @@ struct input_vtable  	/// Create a new input buffer  	input_buffer_t (*buffer_new) (void *input);  	/// Destroy an input buffer -	void (*buffer_destroy) (void *input, input_buffer_t buffer); +	void (*buffer_destroy) (void *input, input_buffer_t);  	/// Switch to a different input buffer -	void (*buffer_switch) (void *input, input_buffer_t buffer); +	void (*buffer_switch) (void *input, input_buffer_t);  	/// Return all history lines in the locale encoding -	struct strv (*buffer_history) (void *input, input_buffer_t buffer); +	struct strv (*buffer_get_history) (void *input, input_buffer_t); +	/// Add a history line in the locale encoding +	void (*buffer_add_history) (void *input, input_buffer_t, const char *);  	/// Register a function that can be bound to character sequences  	void (*register_fn) (void *input, @@ -260,7 +262,8 @@ struct input_vtable  #define INPUT_VTABLE(XX)                                                       \  	XX (start) XX (stop) XX (prepare) XX (destroy)                             \  	XX (hide) XX (show) XX (get_prompt) XX (set_prompt) XX (ding)              \ -	XX (buffer_new) XX (buffer_destroy) XX (buffer_switch) XX (buffer_history) \ +	XX (buffer_new) XX (buffer_destroy) XX (buffer_switch)                     \ +	XX (buffer_get_history) XX (buffer_add_history)                            \  	XX (register_fn) XX (bind) XX (bind_control) XX (bind_meta)                \  	XX (get_line) XX (clear_line) XX (insert)                                  \  	XX (on_tty_resized) XX (on_tty_readable) @@ -564,6 +567,7 @@ input_rl_buffer_switch (void *input, input_buffer_t input_buffer)  {  	struct input_rl *self = input;  	struct input_rl_buffer *buffer = input_buffer; +  	// There could possibly be occurences of the current undo list in some  	// history entry.  We either need to free the undo list, or move it  	// somewhere else to load back later, as the buffer we're switching to @@ -587,8 +591,9 @@ input_rl_buffer_switch (void *input, input_buffer_t input_buffer)  }  static struct strv -input_rl_buffer_history (void *input, input_buffer_t input_buffer) +input_rl_buffer_get_history (void *input, input_buffer_t input_buffer)  { +	(void) input;  	struct input_rl_buffer *buffer = input_buffer;  	HIST_ENTRY **p =  		buffer->history ? buffer->history->entries : history_list(); @@ -599,6 +604,25 @@ input_rl_buffer_history (void *input, input_buffer_t input_buffer)  }  static void +input_rl_buffer_add_history (void *input, input_buffer_t input_buffer, +	const char *line) +{ +	(void) input; +	struct input_rl_buffer *buffer = input_buffer; + +	// For inactive buffers, we'd have to either alloc_history_entry(), +	// construe a timestamp, and manually insert it into saved HISTORY_STATEs, +	// or temporarily switch histories. +	if (!buffer->history) +	{ +		bool at_end = history_offset == history_length; +		add_history (line); +		if (at_end) +			next_history (); +	} +} + +static void  input_rl__buffer_destroy_wo_history (struct input_rl_buffer *self)  {  	free (self->history); @@ -1069,13 +1093,15 @@ input_el_buffer_switch (void *input, input_buffer_t input_buffer)  	self->current = buffer;  	el_wset (self->editline, EL_HIST, history, buffer->history); +	// We only know how to reset the history position to be at the end.  	input_el__start_over (self);  	input_el__restore_buffer (self, buffer);  }  static struct strv -input_el_buffer_history (void *input, input_buffer_t input_buffer) +input_el_buffer_get_history (void *input, input_buffer_t input_buffer)  { +	(void) input;  	struct input_el_buffer *buffer = input_buffer;  	struct strv v = strv_make ();  	HistEventW ev; @@ -1097,6 +1123,26 @@ input_el_buffer_history (void *input, input_buffer_t input_buffer)  }  static void +input_el_buffer_add_history (void *input, input_buffer_t input_buffer, +	const char *line) +{ +	(void) input; +	struct input_el_buffer *buffer = input_buffer; + +	// When currently iterating history, this makes editline's internal +	// history pointer wrongly point to a newer entry. +	size_t len = mbstowcs (NULL, line, 0); +	if (len++ != (size_t) -1) +	{ +		wchar_t *wc = xcalloc (len, sizeof *wc); +		wc[mbstowcs (wc, line, len)] = 0; +		HistEventW ev; +		(void) history_w (buffer->history, &ev, H_ENTER, wc); +		free (wc); +	} +} + +static void  input_el_buffer_destroy (void *input, input_buffer_t input_buffer)  {  	struct input_el *self = input; @@ -2899,12 +2945,15 @@ relay_send (struct client *c)  }  static void -relay_broadcast (struct app_context *ctx) +relay_broadcast_except (struct app_context *ctx, struct client *exception)  {  	LIST_FOR_EACH (struct client, c, ctx->clients) -		relay_send (c); +		if (c != exception) +			relay_send (c);  } +#define relay_broadcast(ctx) relay_broadcast_except ((ctx), NULL) +  static struct relay_event_message *  relay_prepare (struct app_context *ctx)  { @@ -3131,16 +3180,13 @@ relay_prepare_buffer_activate (struct app_context *ctx, struct buffer *buffer)  static void  relay_prepare_buffer_input (struct app_context *ctx, struct buffer *buffer, -	const char *locale_input) +	const char *input)  {  	struct relay_event_message *m = relay_prepare (ctx);  	struct relay_event_data_buffer_input *e = &m->data.buffer_input;  	e->event = RELAY_EVENT_BUFFER_INPUT;  	e->buffer_name = str_from_cstr (buffer->name); -	char *input = iconv_xstrdup (ctx->term_to_utf8, -		(char *) locale_input, -1, NULL);  	e->text = str_from_cstr (input); -	free (input);  }  static void @@ -15305,12 +15351,18 @@ on_pending_input (struct app_context *ctx)  	poller_idle_reset (&ctx->input_event);  	for (size_t i = 0; i < ctx->pending_input.len; i++)  	{ -		char *input = iconv_xstrdup -			(ctx->term_to_utf8, ctx->pending_input.vector[i], -1, NULL); -		if (input) -			process_input (ctx, ctx->current_buffer, input); -		else +		char *input = iconv_xstrdup (ctx->term_to_utf8, +			ctx->pending_input.vector[i], -1, NULL); +		if (!input) +		{  			print_error ("character conversion failed for: %s", "user input"); +			continue; +		} + +		relay_prepare_buffer_input (ctx, ctx->current_buffer, input); +		relay_broadcast (ctx); + +		process_input (ctx, ctx->current_buffer, input);  		free (input);  	}  	strv_reset (&ctx->pending_input); @@ -15362,11 +15414,21 @@ static void  client_resync_buffer_input (struct client *c, struct buffer *buffer)  {  	struct strv history = -		CALL_ (c->ctx->input, buffer_history, buffer->input_data); +		CALL_ (c->ctx->input, buffer_get_history, buffer->input_data);  	for (size_t i = 0; i < history.len; i++)  	{ -		relay_prepare_buffer_input (c->ctx, buffer, history.vector[i]); +		char *input = iconv_xstrdup (c->ctx->term_to_utf8, +			history.vector[i], -1, NULL); +		if (!input) +		{ +			print_error ("character conversion failed for: %s", +				"user input history"); +			continue; +		} + +		relay_prepare_buffer_input (c->ctx, buffer, input);  		relay_send (c); +		free (input);  	}  	strv_free (&history);  } @@ -15463,6 +15525,20 @@ out:  }  static void +client_process_buffer_input +	(struct client *c, struct buffer *buffer, const char *input) +{ +	char *mb = iconv_xstrdup (c->ctx->term_from_utf8, (char *) input, -1, NULL); +	CALL_ (c->ctx->input, buffer_add_history, buffer->input_data, mb); +	free (mb); + +	relay_prepare_buffer_input (c->ctx, buffer, input); +	relay_broadcast_except (c->ctx, c); + +	process_input (c->ctx, buffer, input); +} + +static void  client_process_buffer_log  	(struct client *c, uint32_t seq, struct buffer *buffer)  { @@ -15544,7 +15620,7 @@ client_process_message (struct client *c,  		buffer_activate (c->ctx, buffer);  		break;  	case RELAY_COMMAND_BUFFER_INPUT: -		process_input (c->ctx, buffer, m->data.buffer_input.text.str); +		client_process_buffer_input (c, buffer, m->data.buffer_input.text.str);  		break;  	case RELAY_COMMAND_BUFFER_TOGGLE_UNIMPORTANT:  		buffer_toggle_unimportant (c->ctx, buffer); | 
