From 6d071c468cbed78426eebdaab0639dac873cd39f Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 1 Apr 2019 19:33:38 +0000 Subject: [PATCH 1/7] Restore a check to stop scrolled lines becoming larger than total lines, fixes a crash reported by Thomas Sattler. --- grid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grid.c b/grid.c index f8016356..531afa9d 100644 --- a/grid.c +++ b/grid.c @@ -1284,6 +1284,8 @@ grid_reflow(struct grid *gd, u_int sx) if (target->sy < gd->sy) grid_reflow_add(target, gd->sy - target->sy); gd->hsize = target->sy - gd->sy; + if (gd->hscrolled > gd->hsize) + gd->hscrolled = gd->hsize; free(gd->linedata); gd->linedata = target->linedata; free(target); From bbcfee362fdf8d39501131d3a3f8739dacd5c66e Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 2 Apr 2019 08:45:32 +0000 Subject: [PATCH 2/7] Store and restore cursor across reflow by working out a position based on unwrapped lines, rather than a grid offset. Fixes problems reported by Thomas Sattler and Paul de Weerd. --- grid.c | 69 ++++++++++++++++++++++++++++++++++++-------------------- screen.c | 8 +++---- tmux.h | 4 ++-- 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/grid.c b/grid.c index 531afa9d..53751c03 100644 --- a/grid.c +++ b/grid.c @@ -1291,40 +1291,61 @@ grid_reflow(struct grid *gd, u_int sx) free(target); } -/* Convert point position to offset from the start of the grid. */ -u_int -grid_to_offset(struct grid *gd, u_int px, u_int py) +/* Convert to position based on wrapped lines. */ +void +grid_wrap_position(struct grid *gd, u_int px, u_int py, u_int *wx, u_int *wy) { - u_int yy, offset = 0; + u_int ax = 0, ay = 0, yy; - if (py > gd->hsize + gd->sy - 1) { - px = UINT_MAX; - py = gd->hsize + gd->sy - 1; + for (yy = 0; yy < py; yy++) { + if (gd->linedata[yy].flags & GRID_LINE_WRAPPED) + ax += gd->linedata[yy].cellused; + else { + ax = 0; + ay++; + } } - - for (yy = 0; yy < py; yy++) - offset += gd->linedata[yy].cellused; - if (px > gd->linedata[yy].cellused) - px = gd->linedata[yy].cellused; - return (offset + px); + if (px >= gd->linedata[yy].cellused) + ax = UINT_MAX; + else + ax += px; + *wx = ax; + *wy = ay; } -/* Convert offset from the start of the grid to point position. */ +/* Convert position based on wrapped lines back. */ void -grid_from_offset(struct grid *gd, u_int offset, u_int *px, u_int *py) +grid_unwrap_position(struct grid *gd, u_int *px, u_int *py, u_int wx, u_int wy) { - u_int yy; - - *px = *py = 0; + u_int yy, ax = 0, ay = 0; for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) { - if (offset <= gd->linedata[yy].cellused) + if (ay == wy) break; - offset -= gd->linedata[yy].cellused; + if (gd->linedata[yy].flags & GRID_LINE_WRAPPED) + ax += gd->linedata[yy].cellused; + else { + ax = 0; + ay++; + } } - if (offset < gd->linedata[yy].cellused) - *px = offset; - else - *px = gd->linedata[yy].cellused; + + /* + * yy is now 0 on the unwrapped line which contains wx. Walk forwards + * until we find the end or the line now containing wx. + */ + if (wx == UINT_MAX) { + while (gd->linedata[yy].flags & GRID_LINE_WRAPPED) + yy++; + wx = gd->linedata[yy].cellused; + } else { + while (gd->linedata[yy].flags & GRID_LINE_WRAPPED) { + if (wx < gd->linedata[yy].cellused) + break; + wx -= gd->linedata[yy].cellused; + yy++; + } + } + *px = wx; *py = yy; } diff --git a/screen.c b/screen.c index eae5fb12..9b67e7e8 100644 --- a/screen.c +++ b/screen.c @@ -463,17 +463,17 @@ screen_select_cell(struct screen *s, struct grid_cell *dst, static void screen_reflow(struct screen *s, u_int new_x) { - u_int offset, cx = s->cx, cy = s->grid->hsize + s->cy; + u_int cx = s->cx, cy = s->grid->hsize + s->cy, wx, wy; struct timeval start, tv; gettimeofday(&start, NULL); - offset = grid_to_offset(s->grid, cx, cy); - log_debug("%s: cursor %u,%u offset is %u", __func__, cx, cy, offset); + grid_wrap_position(s->grid, cx, cy, &wx, &wy); + log_debug("%s: cursor %u,%u is %u,%u", __func__, cx, cy, wx, wy); grid_reflow(s->grid, new_x); - grid_from_offset(s->grid, offset, &cx, &cy); + grid_unwrap_position(s->grid, &cx, &cy, wx, wy); log_debug("%s: new cursor is %u,%u", __func__, cx, cy); if (cy >= s->grid->hsize) { diff --git a/tmux.h b/tmux.h index c1f18857..d7f38199 100644 --- a/tmux.h +++ b/tmux.h @@ -2103,8 +2103,8 @@ 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); void grid_reflow(struct grid *, u_int); -u_int grid_to_offset(struct grid *, u_int, u_int); -void grid_from_offset(struct grid *, u_int, u_int *, u_int *); +void grid_wrap_position(struct grid *, u_int, u_int, u_int *, u_int *); +void grid_unwrap_position(struct grid *, u_int *, u_int *, u_int, u_int); /* grid-view.c */ void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *); From fac792dc2714aa5a5d0d44aeacd7c53578486aae Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 2 Apr 2019 11:11:19 +0100 Subject: [PATCH 3/7] Update regress from master. --- regress/Makefile | 1 + regress/control-client-size.sh | 4 ++-- regress/cursor-test.txt | 6 +++++ regress/cursor-test1.result | 33 ++++++++++++++++++++++++++++ regress/cursor-test1.sh | 29 ++++++++++++++++++++++++ regress/cursor-test2.result | 33 ++++++++++++++++++++++++++++ regress/cursor-test2.sh | 29 ++++++++++++++++++++++++ regress/cursor-test3.result | 9 ++++++++ regress/cursor-test3.sh | 29 ++++++++++++++++++++++++ regress/cursor-test4.result | 16 ++++++++++++++ regress/cursor-test4.sh | 31 ++++++++++++++++++++++++++ regress/kill-session-process-exit.sh | 4 ++-- 12 files changed, 220 insertions(+), 4 deletions(-) create mode 100644 regress/cursor-test.txt create mode 100644 regress/cursor-test1.result create mode 100644 regress/cursor-test1.sh create mode 100644 regress/cursor-test2.result create mode 100644 regress/cursor-test2.sh create mode 100644 regress/cursor-test3.result create mode 100644 regress/cursor-test3.sh create mode 100644 regress/cursor-test4.result create mode 100644 regress/cursor-test4.sh diff --git a/regress/Makefile b/regress/Makefile index 3775a711..e6c3619f 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -7,3 +7,4 @@ all: $(TESTS) $(TESTS): sh $*.sh + sleep 1 diff --git a/regress/control-client-size.sh b/regress/control-client-size.sh index b8d9aef0..dd1850c5 100644 --- a/regress/control-client-size.sh +++ b/regress/control-client-size.sh @@ -28,7 +28,7 @@ $TMUX kill-server 2>/dev/null $TMUX -f/dev/null new -d || exit 1 sleep 1 -cat <$TMP +cat <$TMP ls -F':#{window_width} #{window_height}' refresh -C 80,24 ls -F':#{window_width} #{window_height}' @@ -37,7 +37,7 @@ grep ^: $TMP >$OUT printf ":80 24\n:80 23\n"|cmp -s $OUT - || exit 1 $TMUX kill-server 2>/dev/null -cat <$TMP +cat <$TMP ls -F':#{window_width} #{window_height}' refresh -C 80,24 ls -F':#{window_width} #{window_height}' diff --git a/regress/cursor-test.txt b/regress/cursor-test.txt new file mode 100644 index 00000000..67ed52c8 --- /dev/null +++ b/regress/cursor-test.txt @@ -0,0 +1,6 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor +incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea +commodo consequat. Duis aute +irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat +nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia +deserunt mollit anim id est laborum. diff --git a/regress/cursor-test1.result b/regress/cursor-test1.result new file mode 100644 index 00000000..71b9a4b6 --- /dev/null +++ b/regress/cursor-test1.result @@ -0,0 +1,33 @@ +14 8 t +0 ud exercitation ullamco laboris nisi ut +1 aliquip ex ea +2 commodo consequat. Duis aute +3 irure dolor in reprehenderit in voluptat +4 e velit esse cillum dolore eu fugiat +5 nulla pariatur. Excepteur sint occaecat +6 cupidatat non proident, sunt in culpa qu +7 i officia +8 deserunt mollit anim id est laborum. +9 +4 6 t +0 cupidatat +1 non proide +2 nt, sunt i +3 n culpa qu +4 i officia +5 deserunt m +6 ollit anim +7 id est la +8 borum. +9 +14 8 t +0 incididunt ut labore et dolore magna aliqua. Ut en +1 im ad minim veniam, quis nostrud exercitation ulla +2 mco laboris nisi ut aliquip ex ea +3 commodo consequat. Duis aute +4 irure dolor in reprehenderit in voluptate velit es +5 se cillum dolore eu fugiat +6 nulla pariatur. Excepteur sint occaecat cupidatat +7 non proident, sunt in culpa qui officia +8 deserunt mollit anim id est laborum. +9 diff --git a/regress/cursor-test1.sh b/regress/cursor-test1.sh new file mode 100644 index 00000000..2dc20539 --- /dev/null +++ b/regress/cursor-test1.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +TERM=screen + +[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) +TMUX="$TEST_TMUX -f/dev/null -Ltest" +$TMUX kill-server 2>/dev/null + +TMP=$(mktemp) +trap "rm -f $TMP" 0 1 15 + +$TMUX -f/dev/null new -d -x40 -y10 \ + "cat cursor-test.txt; printf '\e[9;15H'; cat" || exit 1 +$TMUX set -g window-size manual || exit 1 + +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP +$TMUX resizew -x10 || exit 1 +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP +$TMUX resizew -x50 || exit 1 +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP + +cmp -s $TMP cursor-test1.result || exit 1 + +$TMUX kill-server 2>/dev/null +exit 0 diff --git a/regress/cursor-test2.result b/regress/cursor-test2.result new file mode 100644 index 00000000..dc005d2b --- /dev/null +++ b/regress/cursor-test2.result @@ -0,0 +1,33 @@ +9 7 a +0 cupidatat +1 non proide +2 nt, sunt i +3 n culpa qu +4 i officia +5 deserunt m +6 ollit anim +7 id est la +8 borum. +9 +4 6 a +0 icia +1 deser +2 unt m +3 ollit +4 anim +5 id e +6 st la +7 borum +8 . +9 +29 8 a +0 incididunt ut labore et dolore magna aliqua. Ut en +1 im ad minim veniam, quis nostrud exercitation ulla +2 mco laboris nisi ut aliquip ex ea +3 commodo consequat. Duis aute +4 irure dolor in reprehenderit in voluptate velit es +5 se cillum dolore eu fugiat +6 nulla pariatur. Excepteur sint occaecat cupidatat +7 non proident, sunt in culpa qui officia +8 deserunt mollit anim id est laborum. +9 diff --git a/regress/cursor-test2.sh b/regress/cursor-test2.sh new file mode 100644 index 00000000..9791f567 --- /dev/null +++ b/regress/cursor-test2.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +TERM=screen + +[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) +TMUX="$TEST_TMUX -Ltest" +$TMUX kill-server 2>/dev/null + +TMP=$(mktemp) +trap "rm -f $TMP" 0 1 15 + +$TMUX -f/dev/null new -d -x10 -y10 \ + "cat cursor-test.txt; printf '\e[8;10H'; cat" || exit 1 +$TMUX set -g window-size manual || exit 1 + +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP +$TMUX resizew -x5 || exit 1 +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP +$TMUX resizew -x50 || exit 1 +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP + +cmp -s $TMP cursor-test2.result || exit 1 + +$TMUX kill-server 2>/dev/null +exit 0 diff --git a/regress/cursor-test3.result b/regress/cursor-test3.result new file mode 100644 index 00000000..e72b1a9b --- /dev/null +++ b/regress/cursor-test3.result @@ -0,0 +1,9 @@ +6 1 b +0 abcdefa +1 bcdefab +3 1 b +0 fabcd +1 efab +6 1 b +0 abcdefa +1 bcdefab diff --git a/regress/cursor-test3.sh b/regress/cursor-test3.sh new file mode 100644 index 00000000..8bb4bd6f --- /dev/null +++ b/regress/cursor-test3.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +TERM=screen + +[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) +TMUX="$TEST_TMUX -Ltest" +$TMUX kill-server 2>/dev/null + +TMP=$(mktemp) +trap "rm -f $TMP" 0 1 15 + +$TMUX -f/dev/null new -d -x7 -y2 \ + "printf 'abcdefabcdefab'; printf '\e[2;7H'; cat" || exit 1 +$TMUX set -g window-size manual || exit 1 + +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP +$TMUX resizew -x5 || exit 1 +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP +$TMUX resizew -x7 || exit 1 +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP + +cmp -s $TMP cursor-test3.result || exit 1 + +$TMUX kill-server 2>/dev/null +exit 0 diff --git a/regress/cursor-test4.result b/regress/cursor-test4.result new file mode 100644 index 00000000..db26e4fa --- /dev/null +++ b/regress/cursor-test4.result @@ -0,0 +1,16 @@ +0 1 +0 abcdef +1 +2 +0 1 +0 abcdef +1 +2 +0 1 +0 def +1 +2 +0 1 +0 abcdef +1 +2 diff --git a/regress/cursor-test4.sh b/regress/cursor-test4.sh new file mode 100644 index 00000000..2bf1bb0e --- /dev/null +++ b/regress/cursor-test4.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +TERM=screen + +[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) +TMUX="$TEST_TMUX -Ltest" +$TMUX kill-server 2>/dev/null + +TMP=$(mktemp) +trap "rm -f $TMP" 0 1 15 + +$TMUX -f/dev/null new -d -x10 -y3 "printf 'abcdef\n'; cat" || exit 1 +$TMUX set -g window-size manual || exit 1 + +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP +$TMUX resizew -x20 || exit 1 +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP +$TMUX resizew -x3 || exit 1 +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP +$TMUX resizew -x10 || exit 1 +$TMUX display -pF '#{cursor_x} #{cursor_y} #{cursor_character}' >>$TMP +$TMUX capturep -p|awk '{print NR-1,$0}' >>$TMP + +cmp -s $TMP cursor-test4.result || exit 1 + +$TMUX kill-server 2>/dev/null +exit 0 diff --git a/regress/kill-session-process-exit.sh b/regress/kill-session-process-exit.sh index 27d883e2..69ee27a2 100644 --- a/regress/kill-session-process-exit.sh +++ b/regress/kill-session-process-exit.sh @@ -9,9 +9,9 @@ TERM=screen TMUX="$TEST_TMUX -Ltest" $TMUX kill-server 2>/dev/null -$TMUX new -d 'sleep 1000' || exit 1 +$TMUX -f/dev/null new -d 'sleep 1000' || exit 1 P=$($TMUX display -pt0:0.0 '#{pane_pid}') -$TMUX new -d || exit 1 +$TMUX -f/dev/null new -d || exit 1 sleep 1 $TMUX kill-session -t0: sleep 1 From 916c4c499de80025eb732e1b26ffda7f06abaa45 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 2 Apr 2019 11:12:24 +0100 Subject: [PATCH 4/7] Version RC2. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 453e734b..79e3ba8c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac -AC_INIT([tmux], 2.9-rc) +AC_INIT([tmux], 2.9-rc2) AC_PREREQ([2.60]) AC_CONFIG_AUX_DIR(etc) From 8968acd678d14cf1ff820ad829d06ca93c2047f1 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 2 Apr 2019 18:41:24 +0000 Subject: [PATCH 5/7] Silence flag should use the same option as activity, reported by Thomas Sattler. --- options-table.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/options-table.c b/options-table.c index 541e66f2..1301f92d 100644 --- a/options-table.c +++ b/options-table.c @@ -82,7 +82,8 @@ static const char *options_table_window_size_list[] = { "#{?#{&&:#{window_bell_flag}," \ "#{!=:#{window-status-bell-style},default}}, " \ "#{window-status-bell-style}," \ - "#{?#{&&:#{window_activity_flag}," \ + "#{?#{&&:#{||:#{window_activity_flag}," \ + "#{window_silence_flag}}," \ "#{!=:" \ "#{window-status-activity-style}," \ "default}}, " \ @@ -103,7 +104,8 @@ static const char *options_table_window_size_list[] = { "#{?#{&&:#{window_bell_flag}," \ "#{!=:#{window-status-bell-style},default}}, " \ "#{window-status-bell-style}," \ - "#{?#{&&:#{window_activity_flag}," \ + "#{?#{&&:#{||:#{window_activity_flag}," \ + "#{window_silence_flag}}," \ "#{!=:" \ "#{window-status-activity-style}," \ "default}}, " \ From 481c3f3f2ea5de650da836cd9684a2d1a2cb2c33 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 3 Apr 2019 06:43:04 +0000 Subject: [PATCH 6/7] screen_write_fast_copy can no longer assume the target screen is default (it isn't for the pane status lines). --- screen-write.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/screen-write.c b/screen-write.c index 0d57b818..566d4d14 100644 --- a/screen-write.c +++ b/screen-write.c @@ -324,7 +324,7 @@ screen_write_copy(struct screen_write_ctx *ctx, struct screen *src, u_int px, /* * Copy from another screen but without the selection stuff. Also assumes the - * target region is already big enough and already cleared. + * target region is already big enough. */ void screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src, @@ -349,8 +349,7 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src, grid_get_cell(gd, xx, yy, &gc); if (xx + gc.data.width > px + nx) break; - if (!grid_cells_equal(&gc, &grid_default_cell)) - grid_view_set_cell(ctx->s->grid, cx, cy, &gc); + grid_view_set_cell(ctx->s->grid, cx, cy, &gc); cx++; } cy++; From 73b54a0e5fa14736d1b7fbac997dd5b12c6940fb Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 4 Apr 2019 10:25:35 +0000 Subject: [PATCH 7/7] Fix size check for splitw -f and top level pane size for tiled layout, problems reported by Thomas Sattler. --- layout-set.c | 3 +-- layout.c | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/layout-set.c b/layout-set.c index b9769ed5..d99453c2 100644 --- a/layout-set.c +++ b/layout-set.c @@ -450,8 +450,7 @@ layout_set_tiled(struct window *w) /* Free old tree and create a new root. */ layout_free(w); lc = w->layout_root = layout_create_cell(NULL); - layout_set_size(lc, (width + 1) * columns - 1, - (height + 1) * rows - 1, 0, 0); + layout_set_size(lc, w->sx, w->sy, 0, 0); layout_make_node(lc, LAYOUT_TOPBOTTOM); /* Create a grid of the cells. */ diff --git a/layout.c b/layout.c index 89026b91..7093c607 100644 --- a/layout.c +++ b/layout.c @@ -722,7 +722,7 @@ layout_set_size_check(struct window *w, struct layout_cell *lc, enum layout_type type, int size) { struct layout_cell *lcchild; - u_int new_size, available, previous, count, idx; + u_int new_size, available, previous, count, idx; /* Cells with no children must just be bigger than minimum. */ if (lc->type == LAYOUT_WINDOWPANE) @@ -736,6 +736,9 @@ layout_set_size_check(struct window *w, struct layout_cell *lc, /* Check new size will work for each child. */ if (lc->type == type) { + if (available < (count * 2) - 1) + return (0); + if (type == LAYOUT_LEFTRIGHT) previous = lc->sx; else @@ -745,13 +748,17 @@ layout_set_size_check(struct window *w, struct layout_cell *lc, TAILQ_FOREACH(lcchild, &lc->cells, entry) { new_size = layout_new_pane_size(w, previous, lcchild, type, size, count - idx, available); - if (new_size > available) - return (0); - - available -= (new_size + 1); + if (idx == count - 1) { + if (new_size > available) + return (0); + available -= new_size; + } else { + if (new_size + 1 > available) + return (0); + available -= new_size + 1; + } if (!layout_set_size_check(w, lcchild, type, new_size)) return (0); - idx++; } } else {