mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Fix issues in the command prompt: set PROMPT_QUOTENEXT after quoting
than before, meaning that accidentally scrolling the mouse wheel doesn't break quoting; and move the cursor correctly over wide characters. From Alexander Arch in GitHub issue 4212.
This commit is contained in:
		
							
								
								
									
										81
									
								
								status.c
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								status.c
									
									
									
									
									
								
							@@ -728,6 +728,55 @@ status_prompt_update(struct client *c, const char *msg, const char *input)
 | 
				
			|||||||
	format_free(ft);
 | 
						format_free(ft);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Redraw character. Return 1 if can continue redrawing, 0 otherwise. */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					status_prompt_redraw_character(struct screen_write_ctx *ctx, u_int offset,
 | 
				
			||||||
 | 
					    u_int pwidth, u_int *width, struct grid_cell *gc,
 | 
				
			||||||
 | 
					    const struct utf8_data *ud)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u_char	ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*width < offset) {
 | 
				
			||||||
 | 
							*width += ud->width;
 | 
				
			||||||
 | 
							return (1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (*width >= offset + pwidth)
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
						*width += ud->width;
 | 
				
			||||||
 | 
						if (*width > offset + pwidth)
 | 
				
			||||||
 | 
							return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ch = *ud->data;
 | 
				
			||||||
 | 
						if (ud->size == 1 && (ch <= 0x1f || ch == 0x7f)) {
 | 
				
			||||||
 | 
							gc->data.data[0] = '^';
 | 
				
			||||||
 | 
							gc->data.data[1] = (ch == 0x7f) ? '?' : ch|0x40;
 | 
				
			||||||
 | 
							gc->data.size = gc->data.have = 2;
 | 
				
			||||||
 | 
							gc->data.width = 2;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							utf8_copy(&gc->data, ud);
 | 
				
			||||||
 | 
						screen_write_cell(ctx, gc);
 | 
				
			||||||
 | 
						return (1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Redraw quote indicator '^' if necessary. Return 1 if can continue redrawing,
 | 
				
			||||||
 | 
					 * 0 otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					status_prompt_redraw_quote(const struct client *c, u_int pcursor,
 | 
				
			||||||
 | 
					    struct screen_write_ctx *ctx, u_int offset, u_int pwidth, u_int *width,
 | 
				
			||||||
 | 
					    struct grid_cell *gc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct utf8_data	ud;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->prompt_flags & PROMPT_QUOTENEXT && ctx->s->cx == pcursor + 1) {
 | 
				
			||||||
 | 
							utf8_set(&ud, '^');
 | 
				
			||||||
 | 
							return (status_prompt_redraw_character(ctx, offset, pwidth,
 | 
				
			||||||
 | 
							    width, gc, &ud));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Draw client prompt on status line of present else on last line. */
 | 
					/* Draw client prompt on status line of present else on last line. */
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
status_prompt_redraw(struct client *c)
 | 
					status_prompt_redraw(struct client *c)
 | 
				
			||||||
@@ -740,8 +789,6 @@ status_prompt_redraw(struct client *c)
 | 
				
			|||||||
	u_int			 pcursor, pwidth, promptline;
 | 
						u_int			 pcursor, pwidth, promptline;
 | 
				
			||||||
	struct grid_cell	 gc;
 | 
						struct grid_cell	 gc;
 | 
				
			||||||
	struct format_tree	*ft;
 | 
						struct format_tree	*ft;
 | 
				
			||||||
	u_char			 ch;
 | 
					 | 
				
			||||||
	struct utf8_data	*ud;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->tty.sx == 0 || c->tty.sy == 0)
 | 
						if (c->tty.sx == 0 || c->tty.sy == 0)
 | 
				
			||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
@@ -788,6 +835,8 @@ status_prompt_redraw(struct client *c)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	pcursor = utf8_strwidth(c->prompt_buffer, c->prompt_index);
 | 
						pcursor = utf8_strwidth(c->prompt_buffer, c->prompt_index);
 | 
				
			||||||
	pwidth = utf8_strwidth(c->prompt_buffer, -1);
 | 
						pwidth = utf8_strwidth(c->prompt_buffer, -1);
 | 
				
			||||||
 | 
						if (c->prompt_flags & PROMPT_QUOTENEXT)
 | 
				
			||||||
 | 
							pwidth++;
 | 
				
			||||||
	if (pcursor >= left) {
 | 
						if (pcursor >= left) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * The cursor would be outside the screen so start drawing
 | 
							 * The cursor would be outside the screen so start drawing
 | 
				
			||||||
@@ -799,31 +848,19 @@ status_prompt_redraw(struct client *c)
 | 
				
			|||||||
		offset = 0;
 | 
							offset = 0;
 | 
				
			||||||
	if (pwidth > left)
 | 
						if (pwidth > left)
 | 
				
			||||||
		pwidth = left;
 | 
							pwidth = left;
 | 
				
			||||||
	c->prompt_cursor = start + c->prompt_index - offset;
 | 
						c->prompt_cursor = start + pcursor - offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	width = 0;
 | 
						width = 0;
 | 
				
			||||||
	for (i = 0; c->prompt_buffer[i].size != 0; i++) {
 | 
						for (i = 0; c->prompt_buffer[i].size != 0; i++) {
 | 
				
			||||||
		ud = &c->prompt_buffer[i];
 | 
							if (!status_prompt_redraw_quote(c, pcursor, &ctx, offset,
 | 
				
			||||||
		if (width < offset) {
 | 
							    pwidth, &width, &gc))
 | 
				
			||||||
			width += ud->width;
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (width >= offset + pwidth)
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		width += ud->width;
 | 
							if (!status_prompt_redraw_character(&ctx, offset, pwidth,
 | 
				
			||||||
		if (width > offset + pwidth)
 | 
							    &width, &gc, &c->prompt_buffer[i]))
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		ch = *ud->data;
 | 
					 | 
				
			||||||
		if (ud->size == 1 && (ch <= 0x1f || ch == 0x7f)) {
 | 
					 | 
				
			||||||
			gc.data.data[0] = '^';
 | 
					 | 
				
			||||||
			gc.data.data[1] = (ch == 0x7f) ? '?' : ch|0x40;
 | 
					 | 
				
			||||||
			gc.data.size = gc.data.have = 2;
 | 
					 | 
				
			||||||
			gc.data.width = 2;
 | 
					 | 
				
			||||||
		} else
 | 
					 | 
				
			||||||
			utf8_copy(&gc.data, ud);
 | 
					 | 
				
			||||||
		screen_write_cell(&ctx, &gc);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						status_prompt_redraw_quote(c, pcursor, &ctx, offset, pwidth, &width,
 | 
				
			||||||
 | 
						    &gc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
finished:
 | 
					finished:
 | 
				
			||||||
	screen_write_stop(&ctx);
 | 
						screen_write_stop(&ctx);
 | 
				
			||||||
@@ -1274,7 +1311,6 @@ status_prompt_key(struct client *c, key_code key)
 | 
				
			|||||||
	key &= ~KEYC_MASK_FLAGS;
 | 
						key &= ~KEYC_MASK_FLAGS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->prompt_flags & (PROMPT_SINGLE|PROMPT_QUOTENEXT)) {
 | 
						if (c->prompt_flags & (PROMPT_SINGLE|PROMPT_QUOTENEXT)) {
 | 
				
			||||||
		c->prompt_flags &= ~PROMPT_QUOTENEXT;
 | 
					 | 
				
			||||||
		if ((key & KEYC_MASK_KEY) == KEYC_BSPACE)
 | 
							if ((key & KEYC_MASK_KEY) == KEYC_BSPACE)
 | 
				
			||||||
			key = 0x7f;
 | 
								key = 0x7f;
 | 
				
			||||||
		else if ((key & KEYC_MASK_KEY) > 0x7f) {
 | 
							else if ((key & KEYC_MASK_KEY) > 0x7f) {
 | 
				
			||||||
@@ -1283,6 +1319,7 @@ status_prompt_key(struct client *c, key_code key)
 | 
				
			|||||||
			key &= KEYC_MASK_KEY;
 | 
								key &= KEYC_MASK_KEY;
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
			key &= (key & KEYC_CTRL) ? 0x1f : KEYC_MASK_KEY;
 | 
								key &= (key & KEYC_CTRL) ? 0x1f : KEYC_MASK_KEY;
 | 
				
			||||||
 | 
							c->prompt_flags &= ~PROMPT_QUOTENEXT;
 | 
				
			||||||
		goto append_key;
 | 
							goto append_key;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user