Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: Makefile
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/Makefile,v
- retrieving revision 1.92
- diff -u -p -r1.92 Makefile
- --- Makefile 18 Oct 2018 08:38:01 -0000 1.92
- +++ Makefile 17 Mar 2019 19:57:49 -0000
- @@ -75,6 +75,7 @@ SRCS= alerts.c \
- control.c \
- environ.c \
- format.c \
- + format-draw.c \
- grid-view.c \
- grid.c \
- hooks.c \
- Index: format-draw.c
- ===================================================================
- RCS file: format-draw.c
- diff -N format-draw.c
- --- /dev/null 1 Jan 1970 00:00:00 -0000
- +++ format-draw.c 17 Mar 2019 19:57:49 -0000
- @@ -0,0 +1,878 @@
- +/* $OpenBSD$ */
- +
- +/*
- + * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
- + *
- + * 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 <stdlib.h>
- +#include <string.h>
- +
- +#include "tmux.h"
- +
- +/* Format range. */
- +struct format_range {
- + u_int index;
- + struct screen *s;
- +
- + u_int start;
- + u_int end;
- +
- + enum style_range_type type;
- + u_int argument;
- +
- + TAILQ_ENTRY(format_range) entry;
- +};
- +TAILQ_HEAD(format_ranges, format_range);
- +
- +/* Does this range match this style? */
- +static int
- +format_is_type(struct format_range *fr, struct style *sy)
- +{
- + if (fr->type != sy->range_type)
- + return (0);
- + if (fr->type == STYLE_RANGE_WINDOW &&
- + fr->argument != sy->range_argument)
- + return (0);
- + return (1);
- +}
- +
- +/* Free a range. */
- +static void
- +format_free_range(struct format_ranges *frs, struct format_range *fr)
- +{
- + TAILQ_REMOVE(frs, fr, entry);
- + free(fr);
- +}
- +
- +/* Fix range positions. */
- +static void
- +format_update_ranges(struct format_ranges *frs, struct screen *s, u_int offset,
- + u_int start, u_int width)
- +{
- + struct format_range *fr, *fr1;
- +
- + if (frs == NULL)
- + return;
- +
- + TAILQ_FOREACH_SAFE(fr, frs, entry, fr1) {
- + if (fr->s != s)
- + continue;
- +
- + if (fr->end <= start || fr->start >= start + width) {
- + format_free_range(frs, fr);
- + continue;
- + }
- +
- + if (fr->start < start)
- + fr->start = start;
- + if (fr->end > start + width)
- + fr->end = start + width;
- + if (fr->start == fr->end) {
- + format_free_range(frs, fr);
- + continue;
- + }
- +
- + fr->start += offset;
- + fr->end += offset;
- + }
- +}
- +
- +/* Draw a part of the format. */
- +static void
- +format_draw_put(struct screen_write_ctx *octx, u_int ocx, u_int ocy,
- + struct screen *s, struct format_ranges *frs, u_int offset, u_int start,
- + u_int width)
- +{
- + /*
- + * The offset is how far from the cursor on the target screen; start
- + * and width how much to copy from the source screen.
- + */
- + screen_write_cursormove(octx, ocx + offset, ocy, 0);
- + screen_write_fast_copy(octx, s, start, 0, width, 1);
- + format_update_ranges(frs, s, offset, start, width);
- +}
- +
- +/* Draw list part of format. */
- +static void
- +format_draw_put_list(struct screen_write_ctx *octx,
- + u_int ocx, u_int ocy, u_int offset, u_int width, struct screen *list,
- + struct screen *list_left, struct screen *list_right, int focus_start,
- + int focus_end, struct format_ranges *frs)
- +{
- + u_int start, focus_centre;
- +
- + /* If there is enough space for the list, draw it entirely. */
- + if (width >= list->cx) {
- + format_draw_put(octx, ocx, ocy, list, frs, offset, 0, width);
- + return;
- + }
- +
- + /* The list needs to be trimmed. Try to keep the focus visible. */
- + focus_centre = focus_start + (focus_end - focus_start) / 2;
- + if (focus_centre < width / 2)
- + start = 0;
- + else
- + start = focus_centre - width / 2;
- + if (start + width > list->cx)
- + start = list->cx - width;
- +
- + /* Draw <> markers at either side if needed. */
- + if (start != 0 && width > list_left->cx) {
- + screen_write_cursormove(octx, ocx + offset, ocy, 0);
- + screen_write_fast_copy(octx, list_left, 0, 0, list_left->cx, 1);
- + offset += list_left->cx;
- + start += list_left->cx;
- + width -= list_left->cx;
- + }
- + if (start + width < list->cx && width > list_right->cx) {
- + screen_write_cursormove(octx, ocx + offset + width - 1, ocy, 0);
- + screen_write_fast_copy(octx, list_right, 0, 0, list_right->cx,
- + 1);
- + width -= list_right->cx;
- + }
- +
- + /* Draw the list screen itself. */
- + format_draw_put(octx, ocx, ocy, list, frs, offset, start, width);
- +}
- +
- +/* Draw format with no list. */
- +static void
- +format_draw_none(struct screen_write_ctx *octx, u_int available, u_int ocx,
- + u_int ocy, struct screen *left, struct screen *centre, struct screen *right,
- + struct format_ranges *frs)
- +{
- + u_int width_left, width_centre, width_right;
- +
- + log_debug("%s", __func__);
- +
- + width_left = left->cx;
- + width_centre = centre->cx;
- + width_right = right->cx;
- +
- + /*
- + * Try to keep as much of the left and right as possible at the expense
- + * of the centre.
- + */
- + while (width_left + width_centre + width_right > available) {
- + if (width_centre > 0)
- + width_centre--;
- + else if (width_right > 0)
- + width_right--;
- + else
- + width_left--;
- + }
- +
- + /* Write left. */
- + format_draw_put(octx, ocx, ocy, left, frs, 0, 0, width_left);
- +
- + /* Write right at available - width_right. */
- + format_draw_put(octx, ocx, ocy, right, frs,
- + available - width_right,
- + right->cx - width_right,
- + width_right);
- +
- + /*
- + * Write centre halfway between
- + * width_left
- + * and
- + * available - width_right.
- + */
- + format_draw_put(octx, ocx, ocy, centre, frs,
- + width_left
- + + ((available - width_right) - width_left) / 2
- + - width_centre / 2,
- + centre->cx / 2 - width_centre / 2,
- + width_centre);
- +}
- +
- +/* Draw format with list on the left. */
- +static void
- +format_draw_left(struct screen_write_ctx *octx, u_int available, u_int ocx,
- + u_int ocy, struct screen *left, struct screen *centre, struct screen *right,
- + struct screen *list, struct screen *list_left, struct screen *list_right,
- + struct screen *after, int focus_start, int focus_end,
- + struct format_ranges *frs)
- +{
- + u_int width_left, width_centre, width_right;
- + u_int width_list, width_after;
- + struct screen_write_ctx ctx;
- +
- + log_debug("%s", __func__);
- +
- + width_left = left->cx;
- + width_centre = centre->cx;
- + width_right = right->cx;
- + width_list = list->cx;
- + width_after = after->cx;
- +
- + /*
- + * Trim first the centre, then the list, then the right, then after the
- + * list, then the left.
- + */
- + while (width_left +
- + width_centre +
- + width_right +
- + width_list +
- + width_after > available) {
- + if (width_centre > 0)
- + width_centre--;
- + else if (width_list > 0)
- + width_list--;
- + else if (width_right > 0)
- + width_right--;
- + else if (width_after > 0)
- + width_after--;
- + else
- + width_left--;
- + }
- +
- + /* If there is no list left, pass off to the no list function. */
- + if (width_list == 0) {
- + screen_write_start(&ctx, NULL, left);
- + screen_write_fast_copy(&ctx, after, 0, 0, width_after, 1);
- + screen_write_stop(&ctx);
- +
- + format_draw_none(octx, available, ocx, ocy, left, centre,
- + right, frs);
- + return;
- + }
- +
- + /* Write left at 0. */
- + format_draw_put(octx, ocx, ocy, left, frs, 0, 0, width_left);
- +
- + /* Write right at available - width_right. */
- + format_draw_put(octx, ocx, ocy, right, frs,
- + available - width_right,
- + right->cx - width_right,
- + width_right);
- +
- + /* Write after at width_left + width_list. */
- + format_draw_put(octx, ocx, ocy, after, frs,
- + width_left + width_list,
- + 0,
- + width_after);
- +
- + /*
- + * Write centre halfway between
- + * width_left + width_list + width_after
- + * and
- + * available - width_right.
- + */
- + format_draw_put(octx, ocx, ocy, centre, frs,
- + (width_left + width_list + width_after)
- + + ((available - width_right)
- + - (width_left + width_list + width_after)) / 2
- + - width_centre / 2,
- + centre->cx / 2 - width_centre / 2,
- + width_centre);
- +
- + /*
- + * The list now goes from
- + * width_left
- + * to
- + * width_left + width_list.
- + * If there is no focus given, keep the left in focus.
- + */
- + if (focus_start == -1 || focus_end == -1)
- + focus_start = focus_end = 0;
- + format_draw_put_list(octx, ocx, ocy, width_left, width_list, list,
- + list_left, list_right, focus_start, focus_end, frs);
- +}
- +
- +/* Draw format with list in the centre. */
- +static void
- +format_draw_centre(struct screen_write_ctx *octx, u_int available, u_int ocx,
- + u_int ocy, struct screen *left, struct screen *centre, struct screen *right,
- + struct screen *list, struct screen *list_left, struct screen *list_right,
- + struct screen *after, int focus_start, int focus_end,
- + struct format_ranges *frs)
- +{
- + u_int width_left, width_centre, width_right;
- + u_int width_list, width_after, middle;
- + struct screen_write_ctx ctx;
- +
- + log_debug("%s", __func__);
- +
- + width_left = left->cx;
- + width_centre = centre->cx;
- + width_right = right->cx;
- + width_list = list->cx;
- + width_after = after->cx;
- +
- + /*
- + * Trim first the list, then after the list, then the centre, then the
- + * right, then the left.
- + */
- + while (width_left +
- + width_centre +
- + width_right +
- + width_list +
- + width_after > available) {
- + if (width_list > 0)
- + width_list--;
- + else if (width_after > 0)
- + width_after--;
- + else if (width_centre > 0)
- + width_centre--;
- + else if (width_right > 0)
- + width_right--;
- + else
- + width_left--;
- + }
- +
- + /* If there is no list left, pass off to the no list function. */
- + if (width_list == 0) {
- + screen_write_start(&ctx, NULL, centre);
- + screen_write_fast_copy(&ctx, after, 0, 0, width_after, 1);
- + screen_write_stop(&ctx);
- +
- + format_draw_none(octx, available, ocx, ocy, left, centre,
- + right, frs);
- + return;
- + }
- +
- + /* Write left at 0. */
- + format_draw_put(octx, ocx, ocy, left, frs, 0, 0, width_left);
- +
- + /* Write after at available - width_after. */
- + format_draw_put(octx, ocx, ocy, after, frs,
- + available - width_after,
- + after->cx - width_after,
- + width_after);
- +
- + /* Write right at available - width_right. */
- + format_draw_put(octx, ocx, ocy, right, frs,
- + available - width_right,
- + right->cx - width_right,
- + width_right);
- +
- + /*
- + * All three centre sections are offset from the middle of the
- + * available space.
- + */
- + middle = (width_left + ((available - width_right) - width_left) / 2);
- +
- + /*
- + * Write centre at
- + * middle - width_list / 2 - width_centre.
- + */
- + format_draw_put(octx, ocx, ocy, centre, frs,
- + middle - width_list / 2 - width_centre,
- + 0,
- + width_centre);
- +
- + /*
- + * Write after at
- + * middle + width_list / 2 - width_centre.
- + */
- + format_draw_put(octx, ocx, ocy, after, frs,
- + middle + width_list / 2,
- + 0,
- + width_after);
- +
- + /*
- + * The list now goes from
- + * middle - width_list / 2
- + * to
- + * middle + width_list / 2
- + * If there is no focus given, keep the centre in focus.
- + */
- + if (focus_start == -1 || focus_end == -1)
- + focus_start = focus_end = list->cx / 2;
- + format_draw_put_list(octx, ocx, ocy, middle - width_list / 2,
- + width_list, list, list_left, list_right, focus_start, focus_end,
- + frs);
- +}
- +
- +/* Draw format with list on the right. */
- +static void
- +format_draw_right(struct screen_write_ctx *octx, u_int available, u_int ocx,
- + u_int ocy, struct screen *left, struct screen *centre, struct screen *right,
- + struct screen *list, struct screen *list_left, struct screen *list_right,
- + struct screen *after, int focus_start, int focus_end,
- + struct format_ranges *frs)
- +{
- + u_int width_left, width_centre, width_right;
- + u_int width_list, width_after;
- + struct screen_write_ctx ctx;
- +
- + log_debug("%s", __func__);
- +
- + width_left = left->cx;
- + width_centre = centre->cx;
- + width_right = right->cx;
- + width_list = list->cx;
- + width_after = after->cx;
- +
- + /*
- + * Trim first the centre, then the list, then the right, then
- + * after the list, then the left.
- + */
- + while (width_left +
- + width_centre +
- + width_right +
- + width_list +
- + width_after > available) {
- + if (width_centre > 0)
- + width_centre--;
- + else if (width_list > 0)
- + width_list--;
- + else if (width_right > 0)
- + width_right--;
- + else if (width_after > 0)
- + width_after--;
- + else
- + width_left--;
- + }
- +
- + /* If there is no list left, pass off to the no list function. */
- + if (width_list == 0) {
- + screen_write_start(&ctx, NULL, right);
- + screen_write_fast_copy(&ctx, after, 0, 0, width_after, 1);
- + screen_write_stop(&ctx);
- +
- + format_draw_none(octx, available, ocx, ocy, left, centre,
- + right, frs);
- + return;
- + }
- +
- + /* Write left at 0. */
- + format_draw_put(octx, ocx, ocy, left, frs, 0, 0, width_left);
- +
- + /* Write after at available - width_after. */
- + format_draw_put(octx, ocx, ocy, after, frs,
- + available - width_after,
- + after->cx - width_after,
- + width_after);
- +
- + /*
- + * Write right at
- + * available - width_right - width_list - width_after.
- + */
- + format_draw_put(octx, ocx, ocy, right, frs,
- + available - width_right - width_list - width_after,
- + 0,
- + width_right);
- +
- + /*
- + * Write centre halfway between
- + * width_left
- + * and
- + * available - width_right - width_list - width_after.
- + */
- + format_draw_put(octx, ocx, ocy, centre, frs,
- + width_left
- + + ((available - width_right - width_list - width_after)
- + - width_left) / 2
- + - width_centre / 2,
- + centre->cx / 2 - width_centre / 2,
- + width_centre);
- +
- + /*
- + * The list now goes from
- + * available - width_list - width_after
- + * to
- + * available - width_after
- + * If there is no focus given, keep the right in focus.
- + */
- + if (focus_start == -1 || focus_end == -1)
- + focus_start = focus_end = 0;
- + format_draw_put_list(octx, ocx, ocy, available - width_list -
- + width_after, width_list, list, list_left, list_right, focus_start,
- + focus_end, frs);
- +}
- +
- +/* Draw a format to a screen. */
- +void
- +format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
- + u_int available, const char *expanded, struct style_ranges *srs)
- +{
- + enum { LEFT,
- + CENTRE,
- + RIGHT,
- + LIST,
- + LIST_LEFT,
- + LIST_RIGHT,
- + AFTER,
- + TOTAL } current = LEFT, last = LEFT;
- + const char *names[] = { "LEFT",
- + "CENTRE",
- + "RIGHT",
- + "LIST",
- + "LIST_LEFT",
- + "LIST_RIGHT",
- + "AFTER" };
- + size_t size = strlen(expanded);
- + struct screen *os = octx->s, s[TOTAL];
- + struct screen_write_ctx ctx[TOTAL];
- + u_int ocx = os->cx, ocy = os->cy, i, width[TOTAL];
- + u_int map[] = { LEFT, LEFT, CENTRE, RIGHT };
- + int focus_start = -1, focus_end = -1;
- + int list_state = -1;
- + enum style_align list_align = STYLE_ALIGN_DEFAULT;
- + struct style sy;
- + struct utf8_data *ud = &sy.gc.data;
- + const char *cp, *end;
- + enum utf8_state more;
- + char *tmp;
- + struct format_range *fr = NULL, *fr1;
- + struct format_ranges frs;
- + struct style_range *sr;
- +
- + style_set(&sy, base);
- + TAILQ_INIT(&frs);
- +
- + /*
- + * We build three screens for left, right, centre alignment, one for
- + * the list, and one for anything after the list.
- + */
- + for (i = 0; i < TOTAL; i++) {
- + screen_init(&s[i], size, 1, 0);
- + screen_write_start(&ctx[i], NULL, &s[i]);
- + screen_write_clearendofline(&ctx[i], base->bg);
- + width[i] = 0;
- + }
- +
- + /*
- + * Walk the string and add to the corresponding screens,
- + * parsing styles as we go.
- + */
- + cp = expanded;
- + while (*cp != '\0') {
- + if (cp[0] != '#' || cp[1] != '[') {
- + /* See if this is a UTF-8 character. */
- + if ((more = utf8_open(ud, *cp)) == UTF8_MORE) {
- + while (*++cp != '\0' && more == UTF8_MORE)
- + more = utf8_append(ud, *cp);
- + if (more != UTF8_DONE)
- + cp -= ud->have;
- + }
- +
- + /* Not a UTF-8 character - ASCII or not valid. */
- + if (more != UTF8_DONE) {
- + if (*cp < 0x20 || *cp > 0x7e) {
- + /* Ignore nonprintable characters. */
- + cp++;
- + continue;
- + }
- + utf8_set(ud, *cp);
- + cp++;
- + }
- +
- + /* Draw the cell to th current screen. */
- + screen_write_cell(&ctx[current], &sy.gc);
- + width[current] += ud->width;
- + continue;
- + }
- +
- + /* This is a style. Work out where the end is and parse it. */
- + end = format_skip(cp + 2, "]");
- + if (end == NULL)
- + return;
- + tmp = xstrndup(cp + 2, end - (cp + 2));
- + if (style_parse(&sy, base, tmp) != 0) {
- + free(tmp);
- + return;
- + }
- + log_debug("style '%s' -> '%s'", tmp, style_tostring(&sy));
- + free(tmp);
- +
- + /* Check the list state. */
- + switch (sy.list) {
- + case STYLE_LIST_ON:
- + /*
- + * Entering the list, exiting a marker, or exiting the
- + * focus.
- + */
- + if (list_state != 0) {
- + if (fr != NULL) { /* abort any region */
- + free(fr);
- + fr = NULL;
- + }
- + list_state = 0;
- + list_align = sy.align;
- + }
- +
- + /* End the focus if started. */
- + if (focus_start != -1 && focus_end == -1)
- + focus_end = s[LIST].cx;
- +
- + current = LIST;
- + break;
- + case STYLE_LIST_FOCUS:
- + /* Entering the focus. */
- + if (list_state != 0) /* not inside the list */
- + break;
- + if (focus_start == -1) /* focus already started */
- + focus_start = s[LIST].cx;
- + break;
- + case STYLE_LIST_OFF:
- + /* Exiting or outside the list. */
- + if (list_state == 0) {
- + if (fr != NULL) { /* abort any region */
- + free(fr);
- + fr = NULL;
- + }
- + if (focus_start != -1 && focus_end == -1)
- + focus_end = s[LIST].cx;
- +
- + map[list_align] = AFTER;
- + if (list_align == STYLE_ALIGN_LEFT)
- + map[STYLE_ALIGN_DEFAULT] = AFTER;
- + list_state = 1;
- + }
- + current = map[sy.align];
- + break;
- + case STYLE_LIST_LEFT_MARKER:
- + /* Entering left marker. */
- + if (list_state != 0) /* not inside the list */
- + break;
- + if (s[LIST_LEFT].cx != 0) /* already have marker */
- + break;
- + if (fr != NULL) { /* abort any region */
- + free(fr);
- + fr = NULL;
- + }
- + if (focus_start != -1 && focus_end == -1)
- + focus_start = focus_end = -1;
- + current = LIST_LEFT;
- + break;
- + case STYLE_LIST_RIGHT_MARKER:
- + /* Entering right marker. */
- + if (list_state != 0) /* not inside the list */
- + break;
- + if (s[LIST_RIGHT].cx != 0) /* already have marker */
- + break;
- + if (fr != NULL) { /* abort any region */
- + free(fr);
- + fr = NULL;
- + }
- + if (focus_start != -1 && focus_end == -1)
- + focus_start = focus_end = -1;
- + current = LIST_RIGHT;
- + break;
- + }
- + if (current != last) {
- + log_debug("%s: change %s -> %s", __func__,
- + names[last], names[current]);
- + last = current;
- + }
- +
- + /*
- + * Check if the range style has changed and if so end the
- + * current range and start a new one if needed.
- + */
- + if (srs != NULL) {
- + if (fr != NULL && !format_is_type(fr, &sy)) {
- + if (s[current].cx != fr->start) {
- + fr->end = s[current].cx + 1;
- + TAILQ_INSERT_TAIL(&frs, fr, entry);
- + } else
- + free(fr);
- + fr = NULL;
- + }
- + if (fr == NULL && sy.range_type != STYLE_RANGE_NONE) {
- + fr = xcalloc(1, sizeof *fr);
- + fr->index = current;
- +
- + fr->s = &s[current];
- + fr->start = s[current].cx;
- +
- + fr->type = sy.range_type;
- + fr->argument = sy.range_argument;
- + }
- + }
- +
- + cp = end + 1;
- + }
- + free(fr);
- +
- + for (i = 0; i < TOTAL; i++)
- + log_debug("%s: width %s is %u", __func__, names[i], width[i]);
- + if (focus_start != -1 && focus_end != -1)
- + log_debug("focus is %d-%d", focus_start, focus_end);
- + TAILQ_FOREACH(fr, &frs, entry) {
- + log_debug("%s: range %d|%u is %s %u-%u", __func__, fr->type,
- + fr->argument, names[fr->index], fr->start, fr->end);
- + }
- +
- + /*
- + * Draw the screens. How they are arranged depends on where the list
- + * appearsq.
- + */
- + switch (list_align) {
- + case STYLE_ALIGN_DEFAULT:
- + /* No list. */
- + format_draw_none(octx, available, ocx, ocy, &s[LEFT],
- + &s[CENTRE], &s[RIGHT], &frs);
- + break;
- + case STYLE_ALIGN_LEFT:
- + /* List is part of the left. */
- + format_draw_left(octx, available, ocx, ocy, &s[LEFT],
- + &s[CENTRE], &s[RIGHT], &s[LIST], &s[LIST_LEFT],
- + &s[LIST_RIGHT], &s[AFTER], focus_start, focus_end, &frs);
- + break;
- + case STYLE_ALIGN_CENTRE:
- + /* List is part of the centre. */
- + format_draw_centre(octx, available, ocx, ocy, &s[LEFT],
- + &s[CENTRE], &s[RIGHT], &s[LIST], &s[LIST_LEFT],
- + &s[LIST_RIGHT], &s[AFTER], focus_start, focus_end, &frs);
- + break;
- + case STYLE_ALIGN_RIGHT:
- + /* List is part of the right. */
- + format_draw_right(octx, available, ocx, ocy, &s[LEFT],
- + &s[CENTRE], &s[RIGHT], &s[LIST], &s[LIST_LEFT],
- + &s[LIST_RIGHT], &s[AFTER], focus_start, focus_end, &frs);
- + break;
- + }
- +
- + /* Create ranges to return. */
- + TAILQ_FOREACH_SAFE(fr, &frs, entry, fr1) {
- + sr = xcalloc(1, sizeof *sr);
- + sr->type = fr->type;
- + sr->argument = fr->argument;
- + sr->start = fr->start;
- + sr->end = fr->end;
- + TAILQ_INSERT_TAIL(srs, sr, entry);
- +
- + log_debug("%s: range %d|%u at %u-%u", __func__, sr->type,
- + sr->argument, sr->start, sr->end);
- +
- + format_free_range(&frs, fr);
- + }
- +
- + /* Restore the original cursor position. */
- + screen_write_cursormove(octx, ocx, ocy, 0);
- +}
- +
- +/* Get width, taking #[] into account. */
- +u_int
- +format_width(const char *expanded)
- +{
- + const char *cp, *end;
- + u_int width = 0;
- + struct utf8_data ud;
- + enum utf8_state more;
- +
- + cp = expanded;
- + while (*cp != '\0') {
- + if (cp[0] == '#' && cp[1] == '[') {
- + end = format_skip(cp + 2, "]");
- + if (end == NULL)
- + return 0;
- + cp = end + 1;
- + } else if ((more = utf8_open(&ud, *cp)) == UTF8_MORE) {
- + while (*++cp != '\0' && more == UTF8_MORE)
- + more = utf8_append(&ud, *cp);
- + if (more == UTF8_DONE)
- + width += ud.width;
- + else
- + cp -= ud.have;
- + } else if (*cp > 0x1f && *cp < 0x7f) {
- + width++;
- + cp++;
- + }
- + }
- + return (width);
- +}
- +
- +/* Trim on the left, taking #[] into account. */
- +char *
- +format_trim_left(const char *expanded, u_int limit)
- +{
- + char *copy, *out;
- + const char *cp = expanded, *end;
- + u_int width = 0;
- + struct utf8_data ud;
- + enum utf8_state more;
- +
- + out = copy = xmalloc(strlen(expanded) + 1);
- + while (*cp != '\0') {
- + if (cp[0] == '#' && cp[1] == '[') {
- + end = format_skip(cp + 2, "]");
- + if (end == NULL)
- + break;
- + memcpy(out, cp, end + 1 - cp);
- + out += (end + 1 - cp);
- + cp = end + 1;
- + } else if ((more = utf8_open(&ud, *cp)) == UTF8_MORE) {
- + while (*++cp != '\0' && more == UTF8_MORE)
- + more = utf8_append(&ud, *cp);
- + if (more == UTF8_DONE) {
- + if (width + ud.width <= limit) {
- + memcpy(out, ud.data, ud.size);
- + out += ud.size;
- + }
- + width += ud.width;
- + } else
- + cp -= ud.have;
- + } else if (*cp > 0x1f && *cp < 0x7f) {
- + if (width + 1 <= limit)
- + *out++ = *cp;
- + width++;
- + cp++;
- + }
- + }
- + *out = '\0';
- + return (copy);
- +}
- +
- +/* Trim on the right, taking #[] into account. */
- +char *
- +format_trim_right(const char *expanded, u_int limit)
- +{
- + char *copy, *out;
- + const char *cp = expanded, *end;
- + u_int width = 0, total_width, skip;
- + struct utf8_data ud;
- + enum utf8_state more;
- +
- + total_width = format_width(expanded);
- + if (total_width <= limit)
- + return (xstrdup(expanded));
- + skip = total_width - limit;
- +
- + out = copy = xmalloc(strlen(expanded) + 1);
- + while (*cp != '\0') {
- + if (cp[0] == '#' && cp[1] == '[') {
- + end = format_skip(cp + 2, "]");
- + if (end == NULL)
- + break;
- + memcpy(out, cp, end + 1 - cp);
- + out += (end + 1 - cp);
- + cp = end + 1;
- + } else if ((more = utf8_open(&ud, *cp)) == UTF8_MORE) {
- + while (*++cp != '\0' && more == UTF8_MORE)
- + more = utf8_append(&ud, *cp);
- + if (more == UTF8_DONE) {
- + if (width >= skip) {
- + memcpy(out, ud.data, ud.size);
- + out += ud.size;
- + }
- + width += ud.width;
- + } else
- + cp -= ud.have;
- + } else if (*cp > 0x1f && *cp < 0x7f) {
- + if (width >= skip)
- + *out++ = *cp;
- + width++;
- + cp++;
- + }
- + }
- + *out = '\0';
- + return (copy);
- +}
- Index: format.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/format.c,v
- retrieving revision 1.182
- diff -u -p -r1.182 format.c
- --- format.c 15 Mar 2019 15:02:25 -0000 1.182
- +++ format.c 17 Mar 2019 19:57:50 -0000
- @@ -936,7 +936,7 @@ found:
- }
- /* Skip until end. */
- -static const char *
- +const char *
- format_skip(const char *s, const char *end)
- {
- int brackets = 0;
- @@ -1544,12 +1544,12 @@ done:
- /* Truncate the value if needed. */
- if (limit > 0) {
- - new = utf8_trimcstr(value, limit);
- + new = format_trim_left(value, limit);
- format_log(ft, "applied length limit %d: %s", limit, new);
- free(value);
- value = new;
- } else if (limit < 0) {
- - new = utf8_rtrimcstr(value, -limit);
- + new = format_trim_right(value, -limit);
- format_log(ft, "applied length limit %d: %s", limit, new);
- free(value);
- value = new;
- Index: mode-tree.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/mode-tree.c,v
- retrieving revision 1.26
- diff -u -p -r1.26 mode-tree.c
- --- mode-tree.c 12 Mar 2019 20:02:47 -0000 1.26
- +++ mode-tree.c 17 Mar 2019 19:57:50 -0000
- @@ -497,7 +497,7 @@ mode_tree_draw(struct mode_tree_data *mt
- struct options *oo = wp->window->options;
- struct screen_write_ctx ctx;
- struct grid_cell gc0, gc;
- - u_int w, h, i, j, sy, box_x, box_y;
- + u_int w, h, i, j, sy, box_x, box_y, width;
- char *text, *start, key[7];
- const char *tag, *symbol;
- size_t size, n;
- @@ -572,8 +572,9 @@ mode_tree_draw(struct mode_tree_data *mt
- tag = "*";
- else
- tag = "";
- - xasprintf(&text, "%-*s%s%s%s: %s", keylen, key, start,
- - mti->name, tag, mti->text);
- + xasprintf(&text, "%-*s%s%s%s: ", keylen, key, start, mti->name,
- + tag);
- + width = utf8_cstrwidth(text);
- free(start);
- if (mti->tagged) {
- @@ -582,11 +583,13 @@ mode_tree_draw(struct mode_tree_data *mt
- }
- if (i != mtd->current) {
- - screen_write_cnputs(&ctx, w, &gc0, "%s", text);
- screen_write_clearendofline(&ctx, 8);
- + screen_write_puts(&ctx, &gc0, "%s", text);
- + format_draw(&ctx, &gc0, w - width, mti->text, NULL);
- } else {
- - screen_write_cnputs(&ctx, w, &gc, "%s", text);
- screen_write_clearendofline(&ctx, gc.bg);
- + screen_write_puts(&ctx, &gc, "%s", text);
- + format_draw(&ctx, &gc, w - width, mti->text, NULL);
- }
- free(text);
- Index: options-table.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/options-table.c,v
- retrieving revision 1.98
- diff -u -p -r1.98 options-table.c
- --- options-table.c 25 Oct 2018 15:13:38 -0000 1.98
- +++ options-table.c 17 Mar 2019 19:57:50 -0000
- @@ -39,6 +39,9 @@ static const char *options_table_mode_ke
- static const char *options_table_clock_mode_style_list[] = {
- "12", "24", NULL
- };
- +static const char *options_table_status_list[] = {
- + "off", "on", "2", "3", "4", "5", NULL
- +};
- static const char *options_table_status_keys_list[] = {
- "emacs", "vi", NULL
- };
- @@ -64,6 +67,46 @@ static const char *options_table_window_
- "largest", "smallest", "manual", NULL
- };
- +/* Status line format. */
- +#define OPTIONS_TABLE_STATUS_FORMAT1 \
- + "#[align=left range=left #{status-left-style}]" \
- + "#{T;=/#{status-left-length}:status-left}#[norange default]" \
- + "#[list=on align=#{status-justify}]" \
- + "#[list=left-marker]<#[list=right-marker]>#[list=on]" \
- + "#{W:" \
- + "#[range=window|#{window_index}" \
- + "#{?window_last_flag, #{window-status-last-style},}" \
- + "#{?window_bell_flag," \
- + " #{window-status-bell-style}," \
- + "#{?window_activity_flag," \
- + " #{window-status-activity-style},}" \
- + "}" \
- + "]" \
- + "#{T:window-status-format}" \
- + "#[norange default]" \
- + "#{?window_end_flag,,#{window-status-separator}}" \
- + "," \
- + "#[range=window|#{window_index} list=focus" \
- + "#{?window_last_flag, #{window-status-last-style},}" \
- + "#{?window_bell_flag," \
- + " #{window-status-bell-style}," \
- + "#{?window_activity_flag," \
- + " #{window-status-activity-style},}" \
- + "}" \
- + "]" \
- + "#{T:window-status-current-format}" \
- + "#[norange list=on default]" \
- + "#{?window_end_flag,,#{window-status-separator}}" \
- + "}" \
- + "#[nolist align=right range=right #{status-right-style}]" \
- + "#{T;=/#{status-right-length}:status-right}#[norange default]"
- +#define OPTIONS_TABLE_STATUS_FORMAT2 \
- + "#[align=centre]#{P:#{?pane_active,#[reverse],}" \
- + "#{pane_index}[#{pane_width}x#{pane_height}]#[default] }"
- +static const char *options_table_status_format_default[] = {
- + OPTIONS_TABLE_STATUS_FORMAT1, OPTIONS_TABLE_STATUS_FORMAT2, NULL
- +};
- +
- /* Top-level options. */
- const struct options_table_entry options_table[] = {
- { .name = "buffer-limit",
- @@ -378,8 +421,9 @@ const struct options_table_entry options
- },
- { .name = "status",
- - .type = OPTIONS_TABLE_FLAG,
- + .type = OPTIONS_TABLE_CHOICE,
- .scope = OPTIONS_TABLE_SESSION,
- + .choices = options_table_status_list,
- .default_num = 1
- },
- @@ -402,6 +446,12 @@ const struct options_table_entry options
- .scope = OPTIONS_TABLE_SESSION,
- .default_num = 0,
- .style = "status-style"
- + },
- +
- + { .name = "status-format",
- + .type = OPTIONS_TABLE_ARRAY,
- + .scope = OPTIONS_TABLE_SESSION,
- + .default_arr = options_table_status_format_default,
- },
- { .name = "status-interval",
- Index: screen-redraw.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/screen-redraw.c,v
- retrieving revision 1.58
- diff -u -p -r1.58 screen-redraw.c
- --- screen-redraw.c 16 Mar 2019 19:12:13 -0000 1.58
- +++ screen-redraw.c 17 Mar 2019 19:57:50 -0000
- @@ -274,8 +274,8 @@ screen_redraw_make_pane_status(struct cl
- struct grid_cell gc;
- const char *fmt;
- struct format_tree *ft;
- - char *out;
- - size_t outlen;
- + char *expanded;
- + u_int width, i;
- struct screen_write_ctx ctx;
- struct screen old;
- @@ -289,26 +289,26 @@ screen_redraw_make_pane_status(struct cl
- ft = format_create(c, NULL, FORMAT_PANE|wp->id, 0);
- format_defaults(ft, c, NULL, NULL, wp);
- + expanded = format_expand_time(ft, fmt);
- + wp->status_size = width = wp->sx - 4;
- +
- memcpy(&old, &wp->status_screen, sizeof old);
- - screen_init(&wp->status_screen, wp->sx, 1, 0);
- + screen_init(&wp->status_screen, width, 1, 0);
- wp->status_screen.mode = 0;
- - out = format_expand(ft, fmt);
- - outlen = screen_write_cstrlen("%s", out);
- - if (outlen > wp->sx - 4)
- - outlen = wp->sx - 4;
- - screen_resize(&wp->status_screen, outlen, 1, 0);
- -
- screen_write_start(&ctx, NULL, &wp->status_screen);
- +
- + gc.attr |= GRID_ATTR_CHARSET;
- + for (i = 0; i < width; i++)
- + screen_write_putc(&ctx, &gc, 'q');
- + gc.attr &= ~GRID_ATTR_CHARSET;
- +
- screen_write_cursormove(&ctx, 0, 0, 0);
- - screen_write_clearline(&ctx, 8);
- - screen_write_cnputs(&ctx, outlen, &gc, "%s", out);
- + format_draw(&ctx, &gc, width, expanded, NULL);
- screen_write_stop(&ctx);
- - free(out);
- + free(expanded);
- format_free(ft);
- -
- - wp->status_size = outlen;
- if (grid_compare(wp->status_screen.grid, old.grid) == 0) {
- screen_free(&old);
- Index: screen-write.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/screen-write.c,v
- retrieving revision 1.148
- diff -u -p -r1.148 screen-write.c
- --- screen-write.c 14 Mar 2019 09:53:52 -0000 1.148
- +++ screen-write.c 17 Mar 2019 19:57:50 -0000
- @@ -169,41 +169,6 @@ screen_write_putc(struct screen_write_ct
- screen_write_cell(ctx, &gc);
- }
- -/* Calculate string length, with embedded formatting. */
- -size_t
- -screen_write_cstrlen(const char *fmt, ...)
- -{
- - va_list ap;
- - char *msg, *msg2, *ptr, *ptr2;
- - size_t size;
- -
- - va_start(ap, fmt);
- - xvasprintf(&msg, fmt, ap);
- - va_end(ap);
- - msg2 = xmalloc(strlen(msg) + 1);
- -
- - ptr = msg;
- - ptr2 = msg2;
- - while (*ptr != '\0') {
- - if (ptr[0] == '#' && ptr[1] == '[') {
- - while (*ptr != ']' && *ptr != '\0')
- - ptr++;
- - if (*ptr == ']')
- - ptr++;
- - continue;
- - }
- - *ptr2++ = *ptr++;
- - }
- - *ptr2 = '\0';
- -
- - size = screen_write_strlen("%s", msg2);
- -
- - free(msg);
- - free(msg2);
- -
- - return (size);
- -}
- -
- /* Calculate string length. */
- size_t
- screen_write_strlen(const char *fmt, ...)
- @@ -314,78 +279,6 @@ screen_write_vnputs(struct screen_write_
- else if (*ptr > 0x1f && *ptr < 0x7f) {
- size++;
- screen_write_putc(ctx, &gc, *ptr);
- - }
- - ptr++;
- - }
- - }
- -
- - free(msg);
- -}
- -
- -/* Write string, similar to nputs, but with embedded formatting (#[]). */
- -void
- -screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
- - const struct grid_cell *gcp, const char *fmt, ...)
- -{
- - struct style sy;
- - struct utf8_data *ud = &sy.gc.data;
- - va_list ap;
- - char *msg;
- - u_char *ptr, *last;
- - size_t left, size = 0;
- - enum utf8_state more;
- -
- - style_set(&sy, gcp);
- -
- - va_start(ap, fmt);
- - xvasprintf(&msg, fmt, ap);
- - va_end(ap);
- -
- - ptr = msg;
- - while (*ptr != '\0') {
- - if (ptr[0] == '#' && ptr[1] == '[') {
- - ptr += 2;
- - last = ptr + strcspn(ptr, "]");
- - if (*last == '\0') {
- - /* No ]. Not much point in doing anything. */
- - break;
- - }
- - *last = '\0';
- -
- - style_parse(&sy, gcp, ptr);
- - ptr = last + 1;
- - continue;
- - }
- - if (*ptr > 0x7f && utf8_open(ud, *ptr) == UTF8_MORE) {
- - ptr++;
- -
- - left = strlen(ptr);
- - if (left < (size_t)ud->size - 1)
- - break;
- - while ((more = utf8_append(ud, *ptr)) == UTF8_MORE)
- - ptr++;
- - ptr++;
- -
- - if (more != UTF8_DONE)
- - continue;
- - if (maxlen > 0 && size + ud->width > (size_t)maxlen) {
- - while (size < (size_t)maxlen) {
- - screen_write_putc(ctx, &sy.gc, ' ');
- - size++;
- - }
- - break;
- - }
- - size += ud->width;
- - screen_write_cell(ctx, &sy.gc);
- - } else {
- - if (maxlen > 0 && size + 1 > (size_t)maxlen)
- - break;
- -
- - if (*ptr == '\001')
- - sy.gc.attr ^= GRID_ATTR_CHARSET;
- - else if (*ptr > 0x1f && *ptr < 0x7f) {
- - size++;
- - screen_write_putc(ctx, &sy.gc, *ptr);
- }
- ptr++;
- }
- Index: server-client.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/server-client.c,v
- retrieving revision 1.271
- diff -u -p -r1.271 server-client.c
- --- server-client.c 16 Mar 2019 17:14:07 -0000 1.271
- +++ server-client.c 17 Mar 2019 19:57:50 -0000
- @@ -411,12 +411,13 @@ server_client_check_mouse(struct client
- {
- struct session *s = c->session;
- struct mouse_event *m = &c->tty.mouse;
- - struct window *w;
- + struct winlink *wl;
- struct window_pane *wp;
- u_int x, y, b, sx, sy, px, py;
- int flag;
- key_code key;
- struct timeval tv;
- + struct style_range *sr;
- enum { NOTYPE, MOVE, DOWN, UP, DRAG, WHEEL, DOUBLE, TRIPLE } type;
- enum { NOWHERE, PANE, STATUS, STATUS_LEFT, STATUS_RIGHT, BORDER } where;
- @@ -503,17 +504,29 @@ have_event:
- /* Is this on the status line? */
- m->statusat = status_at_line(c);
- - if (m->statusat != -1 && y == (u_int)m->statusat) {
- - if (x < c->status.left_size)
- + if (m->statusat != -1 &&
- + y >= (u_int)m->statusat &&
- + y < m->statusat + status_line_size(c))
- + sr = status_get_range(c, x, y - m->statusat);
- + else
- + sr = NULL;
- + if (sr != NULL) {
- + switch (sr->type) {
- + case STYLE_RANGE_NONE:
- + break;
- + case STYLE_RANGE_LEFT:
- where = STATUS_LEFT;
- - else if (x > c->tty.sx - c->status.right_size)
- + break;
- + case STYLE_RANGE_RIGHT:
- where = STATUS_RIGHT;
- - else {
- - w = status_get_window_at(c, x);
- - if (w == NULL)
- - return (KEYC_UNKNOWN);
- - m->w = w->id;
- - where = STATUS;
- + break;
- + case STYLE_RANGE_WINDOW:
- + wl = winlink_find_by_index(&s->windows, sr->argument);
- + if (wl != NULL) {
- + m->w = wl->window->id;
- + where = STATUS;
- + }
- + break;
- }
- }
- Index: status.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/status.c,v
- retrieving revision 1.189
- diff -u -p -r1.189 status.c
- --- status.c 16 Mar 2019 19:12:13 -0000 1.189
- +++ status.c 17 Mar 2019 19:57:50 -0000
- @@ -29,14 +29,6 @@
- #include "tmux.h"
- -static char *status_redraw_get_left(struct client *, struct grid_cell *,
- - size_t *);
- -static char *status_redraw_get_right(struct client *, struct grid_cell *,
- - size_t *);
- -static char *status_print(struct client *, struct winlink *,
- - struct grid_cell *);
- -static char *status_replace(struct client *, struct winlink *,
- - const char *);
- static void status_message_callback(int, short, void *);
- static void status_timer_callback(int, short, void *);
- @@ -196,7 +188,8 @@ status_timer_start_all(void)
- void
- status_update_cache(struct session *s)
- {
- - if (!options_get_number(s->options, "status"))
- + s->statuslines = options_get_number(s->options, "status");
- + if (s->statuslines == 0)
- s->statusat = -1;
- else if (options_get_number(s->options, "status-position") == 0)
- s->statusat = 0;
- @@ -225,75 +218,35 @@ status_line_size(struct client *c)
- if (c->flags & CLIENT_STATUSOFF)
- return (0);
- - if (s->statusat == -1)
- - return (0);
- - return (1);
- + return (s->statuslines);
- }
- -/* Retrieve options for left string. */
- -static char *
- -status_redraw_get_left(struct client *c, struct grid_cell *gc, size_t *size)
- +/* Get window at window list position. */
- +struct style_range *
- +status_get_range(struct client *c, u_int x, u_int y)
- {
- - struct session *s = c->session;
- - const char *template;
- - char *left;
- - size_t leftlen;
- -
- - style_apply_update(gc, s->options, "status-left-style");
- -
- - template = options_get_string(s->options, "status-left");
- - left = status_replace(c, NULL, template);
- + struct status_line *sl = &c->status;
- + struct style_range *sr;
- - *size = options_get_number(s->options, "status-left-length");
- - leftlen = screen_write_cstrlen("%s", left);
- - if (leftlen < *size)
- - *size = leftlen;
- - return (left);
- + if (y >= nitems(sl->entries))
- + return (NULL);
- + TAILQ_FOREACH(sr, &sl->entries[y].ranges, entry) {
- + if (x >= sr->start && x < sr->end)
- + return (sr);
- + }
- + return (NULL);
- }
- -/* Retrieve options for right string. */
- -static char *
- -status_redraw_get_right(struct client *c, struct grid_cell *gc, size_t *size)
- +/* Free all ranges. */
- +static void
- +status_free_ranges(struct style_ranges *srs)
- {
- - struct session *s = c->session;
- - const char *template;
- - char *right;
- - size_t rightlen;
- -
- - style_apply_update(gc, s->options, "status-right-style");
- -
- - template = options_get_string(s->options, "status-right");
- - right = status_replace(c, NULL, template);
- -
- - *size = options_get_number(s->options, "status-right-length");
- - rightlen = screen_write_cstrlen("%s", right);
- - if (rightlen < *size)
- - *size = rightlen;
- - return (right);
- -}
- + struct style_range *sr, *sr1;
- -/* Get window at window list position. */
- -struct window *
- -status_get_window_at(struct client *c, u_int x)
- -{
- - struct session *s = c->session;
- - struct winlink *wl;
- - struct options *oo;
- - const char *sep;
- - size_t seplen;
- -
- - x += c->status.window_list_offset;
- - RB_FOREACH(wl, winlinks, &s->windows) {
- - oo = wl->window->options;
- -
- - sep = options_get_string(oo, "window-status-separator");
- - seplen = screen_write_cstrlen("%s", sep);
- -
- - if (x < wl->status_width)
- - return (wl->window);
- - x -= wl->status_width + seplen;
- + TAILQ_FOREACH_SAFE(sr, srs, entry, sr1) {
- + TAILQ_REMOVE(srs, sr, entry);
- + free(sr);
- }
- - return (NULL);
- }
- /* Save old status line. */
- @@ -327,6 +280,10 @@ void
- status_init(struct client *c)
- {
- struct status_line *sl = &c->status;
- + u_int i;
- +
- + for (i = 0; i < nitems(sl->entries); i++)
- + TAILQ_INIT(&sl->entries[i].ranges);
- screen_init(&sl->screen, c->tty.sx, 1, 0);
- sl->active = &sl->screen;
- @@ -337,6 +294,12 @@ void
- status_free(struct client *c)
- {
- struct status_line *sl = &c->status;
- + u_int i;
- +
- + for (i = 0; i < nitems(sl->entries); i++) {
- + status_free_ranges(&sl->entries[i].ranges);
- + free((void *)sl->entries[i].expanded);
- + }
- if (event_initialized(&sl->timer))
- evtimer_del(&sl->timer);
- @@ -352,19 +315,19 @@ status_free(struct client *c)
- int
- status_redraw(struct client *c)
- {
- - struct status_line *sl = &c->status;
- - struct screen_write_ctx ctx;
- - struct session *s = c->session;
- - struct winlink *wl;
- - struct screen old_screen, window_list;
- - struct grid_cell stdgc, lgc, rgc, gc;
- - struct options *oo;
- - char *left, *right;
- - const char *sep;
- - u_int offset, needed, lines;
- - u_int wlstart, wlwidth, wlavailable, wloffset, wlsize;
- - size_t llen, rlen, seplen;
- - int larrow, rarrow;
- + struct status_line *sl = &c->status;
- + struct status_line_entry *sle;
- + struct session *s = c->session;
- + struct screen_write_ctx ctx;
- + struct grid_cell gc;
- + u_int lines, i, width = c->tty.sx;
- + int flags, force = 0, changed = 0;
- + struct options_entry *o;
- + struct format_tree *ft;
- + const char *fmt;
- + char *expanded;
- +
- + log_debug("%s enter", __func__);
- /* Shouldn't get here if not the active screen. */
- if (sl->active != &sl->screen)
- @@ -374,257 +337,71 @@ status_redraw(struct client *c)
- lines = status_line_size(c);
- if (c->tty.sy == 0 || lines == 0)
- return (1);
- - left = right = NULL;
- - larrow = rarrow = 0;
- /* Set up default colour. */
- - style_apply(&stdgc, s->options, "status-style");
- -
- - /* Create the target screen. */
- - memcpy(&old_screen, sl->active, sizeof old_screen);
- - screen_init(sl->active, c->tty.sx, lines, 0);
- - screen_write_start(&ctx, NULL, sl->active);
- - for (offset = 0; offset < lines * c->tty.sx; offset++)
- - screen_write_putc(&ctx, &stdgc, ' ');
- - screen_write_stop(&ctx);
- -
- - /* If the height is too small, blank status line. */
- - if (c->tty.sy < lines)
- - goto out;
- -
- - /* Work out left and right strings. */
- - memcpy(&lgc, &stdgc, sizeof lgc);
- - left = status_redraw_get_left(c, &lgc, &llen);
- - memcpy(&rgc, &stdgc, sizeof rgc);
- - right = status_redraw_get_right(c, &rgc, &rlen);
- -
- - /*
- - * Figure out how much space we have for the window list. If there
- - * isn't enough space, just show a blank status line.
- - */
- - needed = 0;
- - if (llen != 0)
- - needed += llen;
- - if (rlen != 0)
- - needed += rlen;
- - if (c->tty.sx == 0 || c->tty.sx <= needed)
- - goto out;
- - wlavailable = c->tty.sx - needed;
- -
- - /* Calculate the total size needed for the window list. */
- - wlstart = wloffset = wlwidth = 0;
- - RB_FOREACH(wl, winlinks, &s->windows) {
- - free(wl->status_text);
- - memcpy(&wl->status_cell, &stdgc, sizeof wl->status_cell);
- - wl->status_text = status_print(c, wl, &wl->status_cell);
- - wl->status_width = screen_write_cstrlen("%s", wl->status_text);
- -
- - if (wl == s->curw)
- - wloffset = wlwidth;
- -
- - oo = wl->window->options;
- - sep = options_get_string(oo, "window-status-separator");
- - seplen = screen_write_cstrlen("%s", sep);
- - wlwidth += wl->status_width + seplen;
- - }
- -
- - /* Create a new screen for the window list. */
- - screen_init(&window_list, wlwidth, 1, 0);
- -
- - /* And draw the window list into it. */
- - screen_write_start(&ctx, NULL, &window_list);
- - RB_FOREACH(wl, winlinks, &s->windows) {
- - screen_write_cnputs(&ctx, -1, &wl->status_cell, "%s",
- - wl->status_text);
- -
- - oo = wl->window->options;
- - sep = options_get_string(oo, "window-status-separator");
- - screen_write_cnputs(&ctx, -1, &stdgc, "%s", sep);
- - }
- - screen_write_stop(&ctx);
- -
- - /* If there is enough space for the total width, skip to draw now. */
- - if (wlwidth <= wlavailable)
- - goto draw;
- -
- - /* Find size of current window text. */
- - wlsize = s->curw->status_width;
- -
- - /*
- - * If the current window is already on screen, good to draw from the
- - * start and just leave off the end.
- - */
- - if (wloffset + wlsize < wlavailable) {
- - if (wlavailable > 0) {
- - rarrow = 1;
- - wlavailable--;
- - }
- - wlwidth = wlavailable;
- - } else {
- - /*
- - * Work out how many characters we need to omit from the
- - * start. There are wlavailable characters to fill, and
- - * wloffset + wlsize must be the last. So, the start character
- - * is wloffset + wlsize - wlavailable.
- - */
- - if (wlavailable > 0) {
- - larrow = 1;
- - wlavailable--;
- - }
- -
- - wlstart = wloffset + wlsize - wlavailable;
- - if (wlavailable > 0 && wlwidth > wlstart + wlavailable + 1) {
- - rarrow = 1;
- - wlstart++;
- - wlavailable--;
- - }
- - wlwidth = wlavailable;
- - }
- -
- - /* Bail if anything is now too small too. */
- - if (wlwidth == 0 || wlavailable == 0) {
- - screen_free(&window_list);
- - goto out;
- + style_apply(&gc, s->options, "status-style");
- + if (!grid_cells_equal(&gc, &sl->style)) {
- + force = 1;
- + memcpy(&sl->style, &gc, sizeof sl->style);
- + }
- +
- + /* Resize the target screen. */
- + if (screen_size_x(&sl->screen) != width ||
- + screen_size_y(&sl->screen) != lines) {
- + if (screen_size_x(&sl->screen) != width)
- + force = 1;
- + screen_resize(&sl->screen, width, lines, 0);
- + changed = 1;
- }
- + screen_write_start(&ctx, NULL, &sl->screen);
- - /*
- - * Now the start position is known, work out the state of the left and
- - * right arrows.
- - */
- - offset = 0;
- - RB_FOREACH(wl, winlinks, &s->windows) {
- - if (wl->flags & WINLINK_ALERTFLAGS &&
- - larrow == 1 && offset < wlstart)
- - larrow = -1;
- + /* Create format tree. */
- + flags = FORMAT_STATUS;
- + if (c->flags & CLIENT_STATUSFORCE)
- + flags |= FORMAT_FORCE;
- + ft = format_create(c, NULL, FORMAT_NONE, flags);
- + format_defaults(ft, c, NULL, NULL, NULL);
- - offset += wl->status_width;
- + /* Write the status lines. */
- + o = options_get(s->options, "status-format");
- + if (o == NULL)
- + screen_write_clearscreen(&ctx, gc.bg);
- + else {
- + for (i = 0; i < lines; i++) {
- + screen_write_cursormove(&ctx, 0, i, 0);
- +
- + fmt = options_array_get(o, i);
- + if (fmt == NULL) {
- + screen_write_clearline(&ctx, gc.bg);
- + continue;
- + }
- + sle = &sl->entries[i];
- - if (wl->flags & WINLINK_ALERTFLAGS &&
- - rarrow == 1 && offset > wlstart + wlwidth)
- - rarrow = -1;
- - }
- + expanded = format_expand_time(ft, fmt);
- + if (!force &&
- + sle->expanded != NULL &&
- + strcmp(expanded, sle->expanded) == 0) {
- + free(expanded);
- + continue;
- + }
- + changed = 1;
- -draw:
- - /* Begin drawing. */
- - screen_write_start(&ctx, NULL, sl->active);
- + screen_write_clearline(&ctx, gc.bg);
- + status_free_ranges(&sle->ranges);
- + format_draw(&ctx, &gc, width, expanded, &sle->ranges);
- - /* Draw the left string and arrow. */
- - screen_write_cursormove(&ctx, 0, 0, 0);
- - if (llen != 0)
- - screen_write_cnputs(&ctx, llen, &lgc, "%s", left);
- - if (larrow != 0) {
- - memcpy(&gc, &stdgc, sizeof gc);
- - if (larrow == -1)
- - gc.attr ^= GRID_ATTR_REVERSE;
- - screen_write_putc(&ctx, &gc, '<');
- - }
- -
- - /* Draw the right string and arrow. */
- - if (rarrow != 0) {
- - screen_write_cursormove(&ctx, c->tty.sx - rlen - 1, 0, 0);
- - memcpy(&gc, &stdgc, sizeof gc);
- - if (rarrow == -1)
- - gc.attr ^= GRID_ATTR_REVERSE;
- - screen_write_putc(&ctx, &gc, '>');
- - } else
- - screen_write_cursormove(&ctx, c->tty.sx - rlen, 0, 0);
- - if (rlen != 0)
- - screen_write_cnputs(&ctx, rlen, &rgc, "%s", right);
- -
- - /* Figure out the offset for the window list. */
- - if (llen != 0)
- - wloffset = llen;
- - else
- - wloffset = 0;
- - if (wlwidth < wlavailable) {
- - switch (options_get_number(s->options, "status-justify")) {
- - case 1: /* centred */
- - wloffset += (wlavailable - wlwidth) / 2;
- - break;
- - case 2: /* right */
- - wloffset += (wlavailable - wlwidth);
- - break;
- + free(sle->expanded);
- + sle->expanded = expanded;
- }
- }
- - if (larrow != 0)
- - wloffset++;
- -
- - /* Copy the window list. */
- - sl->window_list_offset = -wloffset + wlstart;
- - screen_write_cursormove(&ctx, wloffset, 0, 0);
- - screen_write_fast_copy(&ctx, &window_list, wlstart, 0, wlwidth, 1);
- - screen_free(&window_list);
- -
- - /* Save left and right size. */
- - sl->left_size = llen;
- - sl->right_size = rlen;
- -
- screen_write_stop(&ctx);
- -out:
- - free(left);
- - free(right);
- -
- - if (grid_compare(sl->active->grid, old_screen.grid) == 0) {
- - screen_free(&old_screen);
- - return (0);
- - }
- - screen_free(&old_screen);
- - return (1);
- -}
- -
- -/* Replace special sequences in fmt. */
- -static char *
- -status_replace(struct client *c, struct winlink *wl, const char *fmt)
- -{
- - struct format_tree *ft;
- - char *expanded;
- - u_int tag;
- -
- - if (fmt == NULL)
- - return (xstrdup(""));
- -
- - if (wl != NULL)
- - tag = FORMAT_WINDOW|wl->window->id;
- - else
- - tag = FORMAT_NONE;
- - if (c->flags & CLIENT_STATUSFORCE)
- - ft = format_create(c, NULL, tag, FORMAT_STATUS|FORMAT_FORCE);
- - else
- - ft = format_create(c, NULL, tag, FORMAT_STATUS);
- - format_defaults(ft, c, NULL, wl, NULL);
- -
- - expanded = format_expand_time(ft, fmt);
- -
- + /* Free the format tree. */
- format_free(ft);
- - return (expanded);
- -}
- -
- -/* Return winlink status line entry and adjust gc as necessary. */
- -static char *
- -status_print(struct client *c, struct winlink *wl, struct grid_cell *gc)
- -{
- - struct options *oo = wl->window->options;
- - struct session *s = c->session;
- - const char *fmt;
- - char *text;
- - style_apply_update(gc, oo, "window-status-style");
- - fmt = options_get_string(oo, "window-status-format");
- - if (wl == s->curw) {
- - style_apply_update(gc, oo, "window-status-current-style");
- - fmt = options_get_string(oo, "window-status-current-format");
- - }
- - if (wl == TAILQ_FIRST(&s->lastw))
- - style_apply_update(gc, oo, "window-status-last-style");
- -
- - if (wl->flags & WINLINK_BELL)
- - style_apply_update(gc, oo, "window-status-bell-style");
- - else if (wl->flags & (WINLINK_ACTIVITY|WINLINK_SILENCE))
- - style_apply_update(gc, oo, "window-status-activity-style");
- -
- - text = status_replace(c, wl, fmt);
- - return (text);
- + /* Return if the status line has changed. */
- + log_debug("%s exit: force=%d, changed=%d", __func__, force, changed);
- + return (force || changed);
- }
- /* Set a status line message. */
- @@ -704,7 +481,7 @@ status_message_redraw(struct client *c)
- lines = status_line_size(c);
- if (lines <= 1)
- lines = 1;
- - screen_init(sl->active, c->tty.sx, 1, 0);
- + screen_init(sl->active, c->tty.sx, lines, 0);
- len = screen_write_strlen("%s", c->message_string);
- if (len > c->tty.sx)
- @@ -713,8 +490,9 @@ status_message_redraw(struct client *c)
- style_apply(&gc, s->options, "message-style");
- screen_write_start(&ctx, NULL, sl->active);
- - screen_write_cursormove(&ctx, 0, 0, 0);
- - for (offset = 0; offset < lines * c->tty.sx; offset++)
- + screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines - 1);
- + screen_write_cursormove(&ctx, 0, lines - 1, 0);
- + for (offset = 0; offset < c->tty.sx; offset++)
- screen_write_putc(&ctx, &gc, ' ');
- screen_write_cursormove(&ctx, 0, lines - 1, 0);
- screen_write_nputs(&ctx, len, &gc, "%s", c->message_string);
- @@ -864,12 +642,13 @@ status_prompt_redraw(struct client *c)
- start = c->tty.sx;
- screen_write_start(&ctx, NULL, sl->active);
- - screen_write_cursormove(&ctx, 0, 0, 0);
- - for (offset = 0; offset < lines * c->tty.sx; offset++)
- + screen_write_fast_copy(&ctx, &sl->screen, 0, 0, c->tty.sx, lines - 1);
- + screen_write_cursormove(&ctx, 0, lines - 1, 0);
- + for (offset = 0; offset < c->tty.sx; offset++)
- screen_write_putc(&ctx, &gc, ' ');
- - screen_write_cursormove(&ctx, 0, 0, 0);
- + screen_write_cursormove(&ctx, 0, lines - 1, 0);
- screen_write_nputs(&ctx, start, &gc, "%s", c->prompt_string);
- - screen_write_cursormove(&ctx, start, 0, 0);
- + screen_write_cursormove(&ctx, start, lines - 1, 0);
- left = c->tty.sx - start;
- if (left == 0)
- Index: style.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/style.c,v
- retrieving revision 1.17
- diff -u -p -r1.17 style.c
- --- style.c 14 Mar 2019 21:46:08 -0000 1.17
- +++ style.c 17 Mar 2019 19:57:50 -0000
- @@ -19,6 +19,8 @@
- #include <sys/types.h>
- +#include <ctype.h>
- +#include <stdlib.h>
- #include <string.h>
- #include "tmux.h"
- @@ -28,7 +30,12 @@
- /* Default style. */
- static struct style style_default = {
- - { 0, 0, 8, 8, { { ' ' }, 0, 1, 1 } }
- + { 0, 0, 8, 8, { { ' ' }, 0, 1, 1 } },
- +
- + STYLE_ALIGN_DEFAULT,
- + STYLE_LIST_OFF,
- +
- + STYLE_RANGE_NONE, 0
- };
- /*
- @@ -40,8 +47,8 @@ int
- style_parse(struct style *sy, const struct grid_cell *base, const char *in)
- {
- struct style saved;
- - const char delimiters[] = " ,";
- - char tmp[32];
- + const char delimiters[] = " ,", *cp;
- + char tmp[256], *found;
- int value;
- size_t end;
- @@ -68,6 +75,60 @@ style_parse(struct style *sy, const stru
- sy->gc.bg = base->bg;
- sy->gc.attr = base->attr;
- sy->gc.flags = base->flags;
- + } else if (strcasecmp(tmp, "nolist") == 0)
- + sy->list = STYLE_LIST_OFF;
- + else if (strncasecmp(tmp, "list=", 5) == 0) {
- + if (strcasecmp(tmp + 5, "on") == 0)
- + sy->list = STYLE_LIST_ON;
- + else if (strcasecmp(tmp + 5, "focus") == 0)
- + sy->list = STYLE_LIST_FOCUS;
- + else if (strcasecmp(tmp + 5, "left-marker") == 0)
- + sy->list = STYLE_LIST_LEFT_MARKER;
- + else if (strcasecmp(tmp + 5, "right-marker") == 0)
- + sy->list = STYLE_LIST_RIGHT_MARKER;
- + else
- + goto error;
- + } else if (strcasecmp(tmp, "norange") == 0) {
- + sy->range_type = style_default.range_type;
- + sy->range_argument = style_default.range_type;
- + } else if (end > 6 && strncasecmp(tmp, "range=", 6) == 0) {
- + found = strchr(tmp + 6, '|');
- + if (found != NULL) {
- + *found++ = '\0';
- + if (*found == '\0')
- + goto error;
- + for (cp = found; *cp != '\0'; cp++) {
- + if (!isdigit((u_char)*cp))
- + goto error;
- + }
- + }
- + if (strcasecmp(tmp + 6, "left") == 0) {
- + if (found != NULL)
- + goto error;
- + sy->range_type = STYLE_RANGE_LEFT;
- + sy->range_argument = 0;
- + } else if (strcasecmp(tmp + 6, "right") == 0) {
- + if (found != NULL)
- + goto error;
- + sy->range_type = STYLE_RANGE_RIGHT;
- + sy->range_argument = 0;
- + } else if (strcasecmp(tmp + 6, "window") == 0) {
- + if (found == NULL)
- + goto error;
- + sy->range_type = STYLE_RANGE_WINDOW;
- + sy->range_argument = atoi(found);
- + }
- + } else if (strcasecmp(tmp, "noalign") == 0)
- + sy->align = style_default.align;
- + else if (end > 6 && strncasecmp(tmp, "align=", 6) == 0) {
- + if (strcasecmp(tmp + 6, "left") == 0)
- + sy->align = STYLE_ALIGN_LEFT;
- + else if (strcasecmp(tmp + 6, "centre") == 0)
- + sy->align = STYLE_ALIGN_CENTRE;
- + else if (strcasecmp(tmp + 6, "right") == 0)
- + sy->align = STYLE_ALIGN_RIGHT;
- + else
- + goto error;
- } else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
- if ((value = colour_fromstring(tmp + 3)) == -1)
- goto error;
- @@ -111,11 +172,49 @@ style_tostring(struct style *sy)
- {
- struct grid_cell *gc = &sy->gc;
- int off = 0;
- - const char *comma = "";
- + const char *comma = "", *tmp;
- static char s[256];
- + char b[16];
- *s = '\0';
- + if (sy->list != STYLE_LIST_OFF) {
- + if (sy->list == STYLE_LIST_ON)
- + tmp = "on";
- + else if (sy->list == STYLE_LIST_FOCUS)
- + tmp = "focus";
- + else if (sy->list == STYLE_LIST_LEFT_MARKER)
- + tmp = "left-marker";
- + else if (sy->list == STYLE_LIST_RIGHT_MARKER)
- + tmp = "right-marker";
- + off += xsnprintf(s + off, sizeof s - off, "%slist=%s", comma,
- + tmp);
- + comma = ",";
- + }
- + if (sy->range_type != STYLE_RANGE_NONE) {
- + if (sy->range_type == STYLE_RANGE_LEFT)
- + tmp = "left";
- + else if (sy->range_type == STYLE_RANGE_RIGHT)
- + tmp = "right";
- + else if (sy->range_type == STYLE_RANGE_WINDOW) {
- + snprintf(b, sizeof b, "window|%u", sy->range_argument);
- + tmp = b;
- + }
- + off += xsnprintf(s + off, sizeof s - off, "%srange=%s", comma,
- + tmp);
- + comma = ",";
- + }
- + if (sy->align != STYLE_ALIGN_DEFAULT) {
- + if (sy->align == STYLE_ALIGN_LEFT)
- + tmp = "left";
- + else if (sy->align == STYLE_ALIGN_CENTRE)
- + tmp = "centre";
- + else if (sy->align == STYLE_ALIGN_RIGHT)
- + tmp = "right";
- + off += xsnprintf(s + off, sizeof s - off, "%salign=%s", comma,
- + tmp);
- + comma = ",";
- + }
- if (gc->fg != 8) {
- off += xsnprintf(s + off, sizeof s - off, "%sfg=%s", comma,
- colour_tostring(gc->fg));
- @@ -180,7 +279,7 @@ style_copy(struct style *dst, struct sty
- memcpy(dst, src, sizeof *dst);
- }
- -/* Check if two styles are the same. */
- +/* Check if two styles are (visibly) the same. */
- int
- style_equal(struct style *sy1, struct style *sy2)
- {
- @@ -192,6 +291,8 @@ style_equal(struct style *sy1, struct st
- if (gc1->bg != gc2->bg)
- return (0);
- if ((gc1->attr & STYLE_ATTR_MASK) != (gc2->attr & STYLE_ATTR_MASK))
- + return (0);
- + if (sy1->align != sy2->align)
- return (0);
- return (1);
- }
- Index: tmux.1
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/tmux.1,v
- retrieving revision 1.623
- diff -u -p -r1.623 tmux.1
- --- tmux.1 17 Mar 2019 19:33:12 -0000 1.623
- +++ tmux.1 17 Mar 2019 19:57:51 -0000
- @@ -251,6 +251,7 @@ client.
- .It !
- Break the current pane out of the window.
- .It \&"
- +.\" "
- Split the current pane into two, top and bottom.
- .It #
- List all paste buffers.
- @@ -2838,9 +2839,22 @@ is on.
- The values are the same as those for
- .Ic activity-action .
- .It Xo Ic status
- -.Op Ic on | off
- +.Op Ic off | on | 2 | 3 | 4 | 5
- .Xc
- -Show or hide the status line.
- +Show or hide the status line or specify its size.
- +Using
- +.Ic on
- +gives a status line one row in height;
- +.Ic 2 ,
- +.Ic 3 ,
- +.Ic 4
- +or
- +.Ic 5
- +more rows.
- +.It Ic status-format[] Ar format
- +Specify the format to be used for each line of the status line.
- +The default builds the top status line from the various individual status
- +options below.
- .It Ic status-interval Ar interval
- Update the status line every
- .Ar interval
- @@ -3872,8 +3886,9 @@ for the terminal default colour; or a he
- Set the background colour.
- .It Ic none
- Set no attributes (turn off any active attributes).
- -.It Xo Ic bright (or
- -.Ic bold )
- +.It Xo Ic bright
- +(or
- +.Ic bold ) ,
- .Ic dim ,
- .Ic underscore ,
- .Ic blink ,
- @@ -3890,6 +3905,54 @@ Set an attribute.
- Any of the attributes may be prefixed with
- .Ql no
- to unset.
- +.It Xo Ic align=left
- +(or
- +.Ic noalign ) ,
- +.Ic align=centre ,
- +.Ic align=right
- +.Xc
- +Align text to the left, centre or right of the available space if appropriate.
- +.It Xo Ic list=on ,
- +.Ic list=focus ,
- +.Ic list=left-marker ,
- +.Ic list=right=marker
- +.Ic nolist
- +.Xc
- +Mark the position of the various window list components in the
- +.Ic status-format
- +option:
- +.Ic list=on
- +marks the start of the list;
- +.Ic list=focus
- +is the part of the list that should be kept in focus if the entire list won't fit
- +in the available space (typically the current window);
- +.Ic list=left-marker
- +and
- +.Ic list=right-marker
- +mark the text to be used to mark that text has been trimmed from the left or
- +right of the list if there is not enough space.
- +.It Xo Ic range=left ,
- +.Ic range=right ,
- +.Ic range=window|X ,
- +.Ic norange
- +.Xc
- +Mark a range in the
- +. Ic status-format
- +option.
- +.Ic range=left
- +and
- +.Ic range=right
- +are the text used for the
- +.Ql StatusLeft
- +and
- +.Ql StatusRight
- +mouse keys.
- +.Ic range=window|X
- +is the range for a window passed to the
- +.Ql Status
- +mouse key, where
- +.Ql X
- +is a window index.
- .El
- .Pp
- Examples are:
- Index: tmux.h
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
- retrieving revision 1.871
- diff -u -p -r1.871 tmux.h
- --- tmux.h 16 Mar 2019 19:12:13 -0000 1.871
- +++ tmux.h 17 Mar 2019 19:57:51 -0000
- @@ -634,9 +634,50 @@ struct grid {
- struct grid_line *linedata;
- };
- +/* Style alignment. */
- +enum style_align {
- + STYLE_ALIGN_DEFAULT,
- + STYLE_ALIGN_LEFT,
- + STYLE_ALIGN_CENTRE,
- + STYLE_ALIGN_RIGHT
- +};
- +
- +/* Style list. */
- +enum style_list {
- + STYLE_LIST_OFF,
- + STYLE_LIST_ON,
- + STYLE_LIST_FOCUS,
- + STYLE_LIST_LEFT_MARKER,
- + STYLE_LIST_RIGHT_MARKER,
- +};
- +
- +/* Style range. */
- +enum style_range_type {
- + STYLE_RANGE_NONE,
- + STYLE_RANGE_LEFT,
- + STYLE_RANGE_RIGHT,
- + STYLE_RANGE_WINDOW
- +};
- +struct style_range {
- + enum style_range_type type;
- + u_int argument;
- +
- + u_int start;
- + u_int end; /* not included */
- +
- + TAILQ_ENTRY(style_range) entry;
- +};
- +TAILQ_HEAD(style_ranges, style_range);
- +
- /* Style option. */
- struct style {
- - struct grid_cell gc;
- + struct grid_cell gc;
- +
- + enum style_align align;
- + enum style_list list;
- +
- + enum style_range_type range_type;
- + u_int range_argument;
- };
- /* Hook data structures. */
- @@ -867,10 +908,6 @@ struct winlink {
- struct session *session;
- struct window *window;
- - size_t status_width;
- - struct grid_cell status_cell;
- - char *status_text;
- -
- int flags;
- #define WINLINK_BELL 0x1
- #define WINLINK_ACTIVITY 0x2
- @@ -952,6 +989,7 @@ struct session {
- struct winlinks windows;
- int statusat;
- + u_int statuslines;
- struct hooks *hooks;
- struct options *options;
- @@ -996,7 +1034,9 @@ struct mouse_event {
- int valid;
- key_code key;
- +
- int statusat;
- + u_int statuslines;
- u_int x;
- u_int y;
- @@ -1311,17 +1351,20 @@ struct cmd_entry {
- };
- /* Status line. */
- +#define STATUS_LINES_LIMIT 5
- +struct status_line_entry {
- + char *expanded;
- + struct style_ranges ranges;
- +};
- struct status_line {
- - struct event timer;
- -
- - struct screen screen;
- - struct screen *active;
- - int references;
- + struct event timer;
- - int window_list_offset;
- + struct screen screen;
- + struct screen *active;
- + int references;
- - u_int left_size;
- - u_int right_size;
- + struct grid_cell style;
- + struct status_line_entry entries[STATUS_LINES_LIMIT];
- };
- /* Client connection. */
- @@ -1580,6 +1623,7 @@ char *paste_make_sample(struct paste_bu
- #define FORMAT_PANE 0x80000000U
- #define FORMAT_WINDOW 0x40000000U
- struct format_tree;
- +const char *format_skip(const char *s, const char *end);
- int format_true(const char *);
- struct format_tree *format_create(struct client *, struct cmdq_item *, int,
- int);
- @@ -1600,6 +1644,14 @@ void format_defaults_paste_buffer(stru
- struct paste_buffer *);
- void format_lost_client(struct client *);
- +/* format-draw.c */
- +void format_draw(struct screen_write_ctx *,
- + const struct grid_cell *, u_int, const char *,
- + struct style_ranges *);
- +u_int format_width(const char *);
- +char *format_trim_left(const char *, u_int);
- +char *format_trim_right(const char *, u_int);
- +
- /* hooks.c */
- struct hook;
- struct hooks *hooks_get(struct session *);
- @@ -1971,7 +2023,7 @@ void status_timer_start_all(void);
- void status_update_cache(struct session *);
- int status_at_line(struct client *);
- u_int status_line_size(struct client *);
- -struct window *status_get_window_at(struct client *, u_int);
- +struct style_range *status_get_range(struct client *, u_int, u_int);
- void status_init(struct client *);
- void status_free(struct client *);
- int status_redraw(struct client *);
- @@ -2071,9 +2123,6 @@ void screen_write_start(struct screen_w
- struct screen *);
- void screen_write_stop(struct screen_write_ctx *);
- void screen_write_reset(struct screen_write_ctx *);
- -size_t printflike(1, 2) screen_write_cstrlen(const char *, ...);
- -void printflike(4, 5) screen_write_cnputs(struct screen_write_ctx *,
- - ssize_t, const struct grid_cell *, const char *, ...);
- size_t printflike(1, 2) screen_write_strlen(const char *, ...);
- void printflike(3, 4) screen_write_puts(struct screen_write_ctx *,
- const struct grid_cell *, const char *, ...);
- @@ -2409,8 +2458,6 @@ u_int utf8_strwidth(const struct utf8_
- struct utf8_data *utf8_fromcstr(const char *);
- char *utf8_tocstr(struct utf8_data *);
- u_int utf8_cstrwidth(const char *);
- -char *utf8_rtrimcstr(const char *, u_int);
- -char *utf8_trimcstr(const char *, u_int);
- char *utf8_padcstr(const char *, u_int);
- /* procname.c */
- Index: utf8.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/utf8.c,v
- retrieving revision 1.39
- diff -u -p -r1.39 utf8.c
- --- utf8.c 4 Jun 2017 09:02:57 -0000 1.39
- +++ utf8.c 17 Mar 2019 19:57:51 -0000
- @@ -383,66 +383,6 @@ utf8_cstrwidth(const char *s)
- return (width);
- }
- -/* Trim UTF-8 string to width. Caller frees. */
- -char *
- -utf8_trimcstr(const char *s, u_int width)
- -{
- - struct utf8_data *tmp, *next;
- - char *out;
- - u_int at;
- -
- - tmp = utf8_fromcstr(s);
- -
- - at = 0;
- - for (next = tmp; next->size != 0; next++) {
- - if (at + next->width > width) {
- - next->size = 0;
- - break;
- - }
- - at += next->width;
- - }
- -
- - out = utf8_tocstr(tmp);
- - free(tmp);
- - return (out);
- -}
- -
- -/* Trim UTF-8 string to width. Caller frees. */
- -char *
- -utf8_rtrimcstr(const char *s, u_int width)
- -{
- - struct utf8_data *tmp, *next, *end;
- - char *out;
- - u_int at;
- -
- - tmp = utf8_fromcstr(s);
- -
- - for (end = tmp; end->size != 0; end++)
- - /* nothing */;
- - if (end == tmp) {
- - free(tmp);
- - return (xstrdup(""));
- - }
- - next = end - 1;
- -
- - at = 0;
- - for (;;) {
- - if (at + next->width > width) {
- - next++;
- - break;
- - }
- - at += next->width;
- -
- - if (next == tmp)
- - break;
- - next--;
- - }
- -
- - out = utf8_tocstr(next);
- - free(tmp);
- - return (out);
- -}
- -
- /* Pad UTF-8 string to width. Caller frees. */
- char *
- utf8_padcstr(const char *s, u_int width)
- Index: window.c
- ===================================================================
- RCS file: /cvs/src/usr.bin/tmux/window.c,v
- retrieving revision 1.221
- diff -u -p -r1.221 window.c
- --- window.c 14 Mar 2019 09:53:52 -0000 1.221
- +++ window.c 17 Mar 2019 19:57:51 -0000
- @@ -206,7 +206,6 @@ winlink_remove(struct winlinks *wwl, str
- }
- RB_REMOVE(winlinks, wwl, wl);
- - free(wl->status_text);
- free(wl);
- }
- @@ -825,7 +824,6 @@ window_pane_create(struct window *w, u_i
- wp->pipe_event = NULL;
- wp->saved_grid = NULL;
- -
- style_set(&wp->style, &grid_default_cell);
- screen_init(&wp->base, sx, sy, hlimit);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement