mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Some old tmux versions can sometimes generate layout strings which have
the incorrect size for the top cell. Previously tmux didn't care but now that panes can be partly hidden, the size matters and is checked more strictly. So add some code to fix up the most common problem and a sanity check to reject layouts with any other size problems. Reported by Aleksandrs Ledovskis in GitHub issue 1930.
This commit is contained in:
		| @@ -125,7 +125,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) | |||||||
|  |  | ||||||
| 			cp = utf8_padcstr(table->name, tablewidth); | 			cp = utf8_padcstr(table->name, tablewidth); | ||||||
| 			cplen = strlen(cp) + 1; | 			cplen = strlen(cp) + 1; | ||||||
| 			while (tmpused + cplen + 1>= tmpsize) { | 			while (tmpused + cplen + 1 >= tmpsize) { | ||||||
| 				tmpsize *= 2; | 				tmpsize *= 2; | ||||||
| 				tmp = xrealloc(tmp, tmpsize); | 				tmp = xrealloc(tmp, tmpsize); | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -116,13 +116,49 @@ layout_append(struct layout_cell *lc, char *buf, size_t len) | |||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Check layout sizes fit. */ | ||||||
|  | static int | ||||||
|  | layout_check(struct layout_cell *lc) | ||||||
|  | { | ||||||
|  | 	struct layout_cell	*lcchild; | ||||||
|  | 	u_int			 n = 0; | ||||||
|  |  | ||||||
|  | 	switch (lc->type) { | ||||||
|  | 	case LAYOUT_WINDOWPANE: | ||||||
|  | 		break; | ||||||
|  | 	case LAYOUT_LEFTRIGHT: | ||||||
|  | 		TAILQ_FOREACH(lcchild, &lc->cells, entry) { | ||||||
|  | 			if (lcchild->sy != lc->sy) | ||||||
|  | 				return (0); | ||||||
|  | 			if (!layout_check(lcchild)) | ||||||
|  | 				return (0); | ||||||
|  | 			n += lcchild->sx + 1; | ||||||
|  | 		} | ||||||
|  | 		if (n - 1 != lc->sx) | ||||||
|  | 			return (0); | ||||||
|  | 		break; | ||||||
|  | 	case LAYOUT_TOPBOTTOM: | ||||||
|  | 		TAILQ_FOREACH(lcchild, &lc->cells, entry) { | ||||||
|  | 			if (lcchild->sx != lc->sx) | ||||||
|  | 				return (0); | ||||||
|  | 			if (!layout_check(lcchild)) | ||||||
|  | 				return (0); | ||||||
|  | 			n += lcchild->sy + 1; | ||||||
|  | 		} | ||||||
|  | 		if (n - 1 != lc->sy) | ||||||
|  | 			return (0); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	return (1); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Parse a layout string and arrange window as layout. */ | /* Parse a layout string and arrange window as layout. */ | ||||||
| int | int | ||||||
| layout_parse(struct window *w, const char *layout) | layout_parse(struct window *w, const char *layout) | ||||||
| { | { | ||||||
| 	struct layout_cell	*lc, *lcchild; | 	struct layout_cell	*lc, *lcchild; | ||||||
| 	struct window_pane	*wp; | 	struct window_pane	*wp; | ||||||
| 	u_int			 npanes, ncells; | 	u_int			 npanes, ncells, sx = 0, sy = 0; | ||||||
| 	u_short			 csum; | 	u_short			 csum; | ||||||
|  |  | ||||||
| 	/* Check validity. */ | 	/* Check validity. */ | ||||||
| @@ -153,6 +189,37 @@ layout_parse(struct window *w, const char *layout) | |||||||
| 		layout_destroy_cell(w, lcchild, &lc); | 		layout_destroy_cell(w, lcchild, &lc); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * It appears older versions of tmux were able to generate layouts with | ||||||
|  | 	 * an incorrect top cell size - if it is larger than the top child then | ||||||
|  | 	 * correct that (if this is still wrong the check code will catch it). | ||||||
|  | 	 */ | ||||||
|  | 	switch (lc->type) { | ||||||
|  | 	case LAYOUT_WINDOWPANE: | ||||||
|  | 		break; | ||||||
|  | 	case LAYOUT_LEFTRIGHT: | ||||||
|  | 		TAILQ_FOREACH(lcchild, &lc->cells, entry) { | ||||||
|  | 			sy = lcchild->sy + 1; | ||||||
|  | 			sx += lcchild->sx + 1; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case LAYOUT_TOPBOTTOM: | ||||||
|  | 		TAILQ_FOREACH(lcchild, &lc->cells, entry) { | ||||||
|  | 			sx = lcchild->sx + 1; | ||||||
|  | 			sy += lcchild->sy + 1; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	if (lc->sx != sx || lc->sy != sy) { | ||||||
|  | 		log_debug("fix layout %u,%u to %u,%u", lc->sx, lc->sy, sx,sy); | ||||||
|  | 		layout_print_cell(lc, __func__, 0); | ||||||
|  | 		lc->sx = sx - 1; lc->sy = sy - 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Check the new layout. */ | ||||||
|  | 	if (!layout_check(lc)) | ||||||
|  | 		return (-1); | ||||||
|  |  | ||||||
| 	/* Resize to the layout size. */ | 	/* Resize to the layout size. */ | ||||||
| 	window_resize(w, lc->sx, lc->sy); | 	window_resize(w, lc->sx, lc->sy); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm