mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Cleanup by moving various (mostly horrible) little bits handling UTF-8 grid
data into functions in a new file, grid-utf8.c, and use sizeof intead of UTF8_DATA. Also nuke trailing whitespace from tmux.1, reminded by jmc.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -30,7 +30,7 @@ SRCS=	attributes.c cfg.c client.c clock.c \ | ||||
| 	cmd-set-environment.c cmd-show-environment.c cmd-choose-client.c \ | ||||
| 	cmd-up-pane.c cmd-display-message.c cmd-display-panes.c \ | ||||
| 	cmd-pipe-pane.c cmd.c \ | ||||
| 	colour.c environ.c grid-view.c grid.c input-keys.c \ | ||||
| 	colour.c environ.c grid-view.c grid-utf8.c grid.c input-keys.c \ | ||||
| 	imsg.c imsg-buffer.c input.c key-bindings.c key-string.c \ | ||||
| 	layout-set.c layout.c log.c job.c \ | ||||
| 	mode-key.c names.c options-cmd.c options.c paste.c procname.c \ | ||||
|   | ||||
							
								
								
									
										96
									
								
								grid-utf8.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								grid-utf8.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| /* $OpenBSD$ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
|  * | ||||
|  * Permission to use, copy, modify, and distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER | ||||
|  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | ||||
|  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include "tmux.h" | ||||
|  | ||||
| /* | ||||
|  * Grid UTF-8 utility functions. | ||||
|  */ | ||||
|  | ||||
| /* Calculate UTF-8 grid cell size. Data is terminated by 0xff. */ | ||||
| size_t | ||||
| grid_utf8_size(const struct grid_utf8 *gu) | ||||
| { | ||||
| 	size_t	size; | ||||
|  | ||||
| 	for (size = 0; size < sizeof gu->data; size++) { | ||||
| 		if (gu->data[size] == 0xff) | ||||
| 			break; | ||||
| 	} | ||||
| 	return (size); | ||||
| } | ||||
|  | ||||
| /* Copy UTF-8 out into a buffer. */ | ||||
| size_t | ||||
| grid_utf8_copy(const struct grid_utf8 *gu, char *buf, size_t len) | ||||
| { | ||||
| 	size_t	size; | ||||
|  | ||||
| 	size = grid_utf8_size(gu); | ||||
| 	if (size > len) | ||||
| 		fatalx("UTF-8 copy overflow"); | ||||
| 	memcpy(buf, gu->data, size); | ||||
| 	return (size); | ||||
| } | ||||
|  | ||||
| /* Set UTF-8 grid data from input UTF-8. */ | ||||
| void | ||||
| grid_utf8_set(struct grid_utf8 *gu, const struct utf8_data *utf8data) | ||||
| { | ||||
| 	if (utf8data->size == 0) | ||||
| 		fatalx("UTF-8 data empty"); | ||||
| 	if (utf8data->size > sizeof gu->data) | ||||
| 		fatalx("UTF-8 data too long"); | ||||
| 	memcpy(gu->data, utf8data->data, utf8data->size); | ||||
| 	if (utf8data->size != sizeof gu->data) | ||||
| 		gu->data[utf8data->size] = 0xff; | ||||
| 	gu->width = utf8data->width; | ||||
| } | ||||
|  | ||||
| /* Append UTF-8 character onto the cell data (for combined characters). */ | ||||
| int | ||||
| grid_utf8_append(struct grid_utf8 *gu, const struct utf8_data *utf8data) | ||||
| { | ||||
| 	size_t	old_size; | ||||
|  | ||||
| 	old_size = grid_utf8_size(gu); | ||||
| 	if (old_size + utf8data->size > sizeof gu->data) | ||||
| 		return (-1); | ||||
| 	memcpy(gu->data + old_size, utf8data->data, utf8data->size); | ||||
| 	if (old_size + utf8data->size != sizeof gu->data) | ||||
| 		gu->data[old_size + utf8data->size] = 0xff; | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
| /* Compare two UTF-8 cells. */ | ||||
| int | ||||
| grid_utf8_compare(const struct grid_utf8 *gu1, const struct grid_utf8 *gu2) | ||||
| { | ||||
| 	size_t	size; | ||||
|  | ||||
| 	size = grid_utf8_size(gu1); | ||||
| 	if (size != grid_utf8_size(gu2)) | ||||
| 		return (0); | ||||
| 	if (memcmp(gu1->data, gu2->data, size) != 0) | ||||
| 		return (0); | ||||
| 	return (1);	 | ||||
| } | ||||
							
								
								
									
										16
									
								
								grid.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								grid.c
									
									
									
									
									
								
							| @@ -502,8 +502,8 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) | ||||
|  	const struct grid_cell	*gc; | ||||
|  	const struct grid_utf8	*gu; | ||||
| 	char			*buf; | ||||
| 	size_t			 len, off; | ||||
| 	u_int			 xx, i; | ||||
| 	size_t			 len, off, size; | ||||
| 	u_int			 xx; | ||||
|  | ||||
| 	GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx); | ||||
|  | ||||
| @@ -517,17 +517,15 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx) | ||||
| 			continue; | ||||
|  | ||||
| 		if (gc->flags & GRID_FLAG_UTF8) { | ||||
| 			while (len < off + UTF8_SIZE + 1) { | ||||
| 			gu = grid_peek_utf8(gd, xx, py); | ||||
|  | ||||
| 			size = grid_utf8_size(gu); | ||||
| 			while (len < off + size + 1) { | ||||
| 				buf = xrealloc(buf, 2, len); | ||||
| 				len *= 2; | ||||
| 			} | ||||
|  | ||||
| 			gu = grid_peek_utf8(gd, xx, py); | ||||
| 			for (i = 0; i < UTF8_SIZE; i++) { | ||||
| 				if (gu->data[i] == 0xff) | ||||
| 					break; | ||||
| 				buf[off++] = gu->data[i]; | ||||
| 			} | ||||
| 			off += grid_utf8_copy(gu, buf + off, len - off); | ||||
| 		} else { | ||||
| 			while (len < off + 2) { | ||||
| 				buf = xrealloc(buf, 2, len); | ||||
|   | ||||
| @@ -354,7 +354,7 @@ screen_write_copy(struct screen_write_ctx *ctx, | ||||
| 	const struct grid_cell	*gc; | ||||
| 	const struct grid_utf8	*gu; | ||||
| 	struct utf8_data	 utf8data; | ||||
| 	u_int		 	 xx, yy, cx, cy, ax, bx, i; | ||||
| 	u_int		 	 xx, yy, cx, cy, ax, bx; | ||||
|  | ||||
| 	cx = s->cx; | ||||
| 	cy = s->cy; | ||||
| @@ -381,18 +381,15 @@ screen_write_copy(struct screen_write_ctx *ctx, | ||||
| 					gc = &grid_default_cell; | ||||
| 				else | ||||
| 					gc = &gl->celldata[xx]; | ||||
| 				if (gc->flags & GRID_FLAG_UTF8) { | ||||
| 				if (!(gc->flags & GRID_FLAG_UTF8)) { | ||||
| 					screen_write_cell(ctx, gc, NULL); | ||||
| 					continue; | ||||
| 				} | ||||
| 				/* Reinject the UTF-8 sequence. */ | ||||
| 				gu = &gl->utf8data[xx]; | ||||
| 					memcpy(utf8data.data, | ||||
| 					    gu->data, sizeof utf8data.data); | ||||
| 				utf8data.size = grid_utf8_copy( | ||||
| 				    gu, utf8data.data, sizeof utf8data.data); | ||||
| 				utf8data.width = gu->width; | ||||
| 					utf8data.size = 0; | ||||
| 					for (i = 0; i < UTF8_SIZE; i++) { | ||||
| 						if (gu->data[i] == 0xff) | ||||
| 							break; | ||||
| 						utf8data.size++; | ||||
| 					} | ||||
| 				} | ||||
| 				screen_write_cell(ctx, gc, &utf8data); | ||||
| 			} | ||||
| 			if (px + nx == gd->sx && px + nx > gl->cellsize) | ||||
| @@ -1037,13 +1034,7 @@ screen_write_cell(struct screen_write_ctx *ctx, | ||||
| 	grid_view_set_cell(gd, s->cx, s->cy, gc); | ||||
| 	if (gc->flags & GRID_FLAG_UTF8) { | ||||
| 		/* Construct UTF-8 and write it. */ | ||||
| 		gu.width = utf8data->width; | ||||
| 		memset(gu.data, 0xff, sizeof gu.data); | ||||
| 		if (utf8data->size == 0) | ||||
| 			fatalx("UTF-8 data empty"); | ||||
| 		if (utf8data->size > sizeof gu.data) | ||||
| 			fatalx("UTF-8 data overflow"); | ||||
| 		memcpy(gu.data, utf8data->data, utf8data->size); | ||||
| 		grid_utf8_set(&gu, utf8data); | ||||
| 		grid_view_set_utf8(gd, s->cx, s->cy, &gu); | ||||
| 	} | ||||
|  | ||||
| @@ -1080,7 +1071,7 @@ screen_write_combine( | ||||
| 	struct grid		*gd = s->grid; | ||||
| 	struct grid_cell	*gc; | ||||
| 	struct grid_utf8	*gu, tmp_gu; | ||||
| 	u_int			 i, old_size; | ||||
| 	u_int			 i; | ||||
|  | ||||
| 	/* Can't combine if at 0. */ | ||||
| 	if (s->cx == 0) | ||||
| @@ -1093,35 +1084,30 @@ screen_write_combine( | ||||
| 	/* Retrieve the previous cell and convert to UTF-8 if not already. */ | ||||
| 	gc = grid_view_get_cell(gd, s->cx - 1, s->cy); | ||||
| 	if (!(gc->flags & GRID_FLAG_UTF8)) { | ||||
| 		memset(&tmp_gu.data, 0xff, sizeof tmp_gu.data); | ||||
| 		*tmp_gu.data = gc->data; | ||||
| 		tmp_gu.data[0] = gc->data; | ||||
| 		tmp_gu.data[1] = 0xff; | ||||
| 		tmp_gu.width = 1; | ||||
|  | ||||
| 		grid_view_set_utf8(gd, s->cx - 1, s->cy, &tmp_gu); | ||||
| 		gc->flags |= GRID_FLAG_UTF8; | ||||
| 	} | ||||
|  | ||||
| 	/* Get the previous cell's UTF-8 data and its size. */ | ||||
| 	/* Append the current cell. */ | ||||
| 	gu = grid_view_get_utf8(gd, s->cx - 1, s->cy); | ||||
| 	for (old_size = 0; old_size < UTF8_SIZE; old_size++) { | ||||
| 		if (gu->data[old_size] == 0xff) | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| 	/* If there isn't space, scrap this character. */ | ||||
| 	if (old_size + utf8data->size > UTF8_SIZE) { | ||||
| 		for (i = 0; i < gu->width && i != UTF8_SIZE; i++) | ||||
| 	if (grid_utf8_append(gu, utf8data) != 0) { | ||||
| 		/* Failed: scrap this character and replace with underscores. */ | ||||
| 		if (gu->width == 1) { | ||||
| 			gc->data = '_'; | ||||
| 			gc->flags &= ~GRID_FLAG_UTF8; | ||||
| 		} else { | ||||
| 			for (i = 0; i < gu->width && i != sizeof gu->data; i++) | ||||
| 				gu->data[i] = '_'; | ||||
| 		if (i != UTF8_SIZE) | ||||
| 			if (i != sizeof gu->data) | ||||
| 				gu->data[i] = 0xff; | ||||
| 			gu->width = i; | ||||
| 		return (0); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Otherwise save the character. */ | ||||
| 	memcpy(gu->data + old_size, utf8data->data, utf8data->size); | ||||
| 	if (old_size + utf8data->size != UTF8_SIZE) | ||||
| 		gu->data[old_size + utf8data->size] = 0xff; | ||||
| 	return (0); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										14
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -74,6 +74,12 @@ extern char   **environ; | ||||
| #define PRINT_LENGTH 512	/* printed error/message size */ | ||||
| #define ENVIRON_LENGTH 1024	/* environment variable length */ | ||||
|  | ||||
| /* | ||||
|  * UTF-8 data size. This must be big enough to hold combined characters as well | ||||
|  * as single. | ||||
|  */ | ||||
| #define UTF8_SIZE 9 | ||||
|  | ||||
| /* Fatal errors. */ | ||||
| #define fatal(msg) log_fatal("%s: %s", __func__, msg); | ||||
| #define fatalx(msg) log_fatalx("%s: %s", __func__, msg); | ||||
| @@ -531,7 +537,6 @@ struct mode_key_table { | ||||
|  * reinject stored UTF-8 data back into screen_write_cell after combining (ugh | ||||
|  * XXX XXX). | ||||
|  */ | ||||
| #define UTF8_SIZE 9 | ||||
| struct utf8_data { | ||||
| 	u_char	data[UTF8_SIZE]; | ||||
|  | ||||
| @@ -1675,6 +1680,13 @@ char	*grid_string_cells(struct grid *, u_int, u_int, u_int); | ||||
| void	 grid_duplicate_lines( | ||||
|     	     struct grid *, u_int, struct grid *, u_int, u_int); | ||||
|  | ||||
| /* grid-utf8.c */ | ||||
| size_t	 grid_utf8_size(const struct grid_utf8 *); | ||||
| size_t	 grid_utf8_copy(const struct grid_utf8 *, char *, size_t); | ||||
| void	 grid_utf8_set(struct grid_utf8 *, const struct utf8_data *); | ||||
| int	 grid_utf8_append(struct grid_utf8 *, const struct utf8_data *); | ||||
| int	 grid_utf8_compare(const struct grid_utf8 *, const struct grid_utf8 *); | ||||
|  | ||||
| /* grid-view.c */ | ||||
| const struct grid_cell *grid_view_peek_cell(struct grid *, u_int, u_int); | ||||
| struct grid_cell *grid_view_get_cell(struct grid *, u_int, u_int); | ||||
|   | ||||
							
								
								
									
										12
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								tty.c
									
									
									
									
									
								
							| @@ -365,16 +365,12 @@ tty_putc(struct tty *tty, u_char ch) | ||||
| void | ||||
| tty_pututf8(struct tty *tty, const struct grid_utf8 *gu) | ||||
| { | ||||
| 	u_int	i; | ||||
| 	size_t	size; | ||||
|  | ||||
| 	for (i = 0; i < UTF8_SIZE; i++) { | ||||
| 		if (gu->data[i] == 0xff) | ||||
| 			break; | ||||
| 		bufferevent_write(tty->event, &gu->data[i], 1); | ||||
| 	size = grid_utf8_size(gu); | ||||
| 	bufferevent_write(tty->event, gu->data, size); | ||||
| 	if (tty->log_fd != -1) | ||||
| 			write(tty->log_fd, &gu->data[i], 1); | ||||
| 	} | ||||
|  | ||||
| 		write(tty->log_fd, gu->data, size); | ||||
| 	tty->cx += gu->width; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -486,6 +486,7 @@ window_copy_search_compare( | ||||
| { | ||||
| 	const struct grid_cell	*gc, *sgc; | ||||
| 	const struct grid_utf8	*gu, *sgu; | ||||
| 	size_t			 size; | ||||
|  | ||||
| 	gc = grid_peek_cell(gd, px, py); | ||||
| 	sgc = grid_peek_cell(sgd, spx, 0); | ||||
| @@ -496,7 +497,7 @@ window_copy_search_compare( | ||||
| 	if (gc->flags & GRID_FLAG_UTF8) { | ||||
| 		gu = grid_peek_utf8(gd, px, py); | ||||
| 		sgu = grid_peek_utf8(sgd, spx, 0); | ||||
| 		if (memcmp(gu->data, sgu->data, UTF8_SIZE) == 0) | ||||
| 		if (grid_utf8_compare(gu, sgu)) | ||||
| 			return (1); | ||||
| 	} else { | ||||
| 		if (gc->data == sgc->data) | ||||
| @@ -895,7 +896,8 @@ window_copy_copy_line(struct window_pane *wp, | ||||
|  	const struct grid_cell	*gc; | ||||
|  	const struct grid_utf8	*gu; | ||||
| 	struct grid_line	*gl; | ||||
| 	u_int			 i, j, xx, wrapped = 0; | ||||
| 	u_int			 i, xx, wrapped = 0; | ||||
| 	size_t			 size; | ||||
|  | ||||
| 	if (sx > ex) | ||||
| 		return; | ||||
| @@ -928,12 +930,9 @@ window_copy_copy_line(struct window_pane *wp, | ||||
| 				(*buf)[(*off)++] = gc->data; | ||||
| 			} else { | ||||
| 				gu = grid_peek_utf8(gd, i, sy); | ||||
| 				*buf = xrealloc(*buf, 1, (*off) + UTF8_SIZE); | ||||
| 				for (j = 0; j < UTF8_SIZE; j++) { | ||||
| 					if (gu->data[j] == 0xff) | ||||
| 						break; | ||||
| 					(*buf)[(*off)++] = gu->data[j]; | ||||
| 				} | ||||
| 				size = grid_utf8_size(gu); | ||||
| 				*buf = xrealloc(*buf, 1, (*off) + size); | ||||
| 				*off += grid_utf8_copy(gu, *buf + *off, size); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Nicholas Marriott
					Nicholas Marriott