mirror of
https://github.com/tmux/tmux.git
synced 2026-09-05 13:10:45 +00:00
Changes from feedback
This commit is contained in:
@@ -101,7 +101,7 @@ control_window_layout_changed_cb(__unused const char *name,
|
||||
cp = format_expand(ft, template);
|
||||
format_free(ft);
|
||||
|
||||
control_write(c, "%s", cp);
|
||||
control_notify_write(c, "%s", cp);
|
||||
free(cp);
|
||||
}
|
||||
}
|
||||
|
||||
74
json.c
74
json.c
@@ -40,8 +40,7 @@
|
||||
* are not decoded, duplicate keys may go undetected.
|
||||
*/
|
||||
|
||||
#define INPUT_MAX (1 << 14)
|
||||
#define TOKENS_MAX (INPUT_MAX)
|
||||
#define TOKENS_MAX 1000
|
||||
#define ERROR_CTX_LEN 8
|
||||
|
||||
/* JSON Token types. */
|
||||
@@ -238,119 +237,118 @@ json_get_array(struct json_node *jn, struct json_node **a)
|
||||
}
|
||||
|
||||
/* Returns the string value from a given key in an object node. */
|
||||
const char *
|
||||
json_find_string(const struct json_node *jn, const char *key, char **cause)
|
||||
int
|
||||
json_find_string(const struct json_node *jn, const char *key, const char **out,
|
||||
char **cause)
|
||||
{
|
||||
struct json_node *field;
|
||||
static char ret[INPUT_MAX];
|
||||
|
||||
if ((field = json_find(jn, key)) == NULL) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" not found", key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
if (field->type != NODE_STRING) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" expected STRING value",
|
||||
key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
*out = field->str;
|
||||
|
||||
if (snprintf(ret, sizeof ret, "%s", field->str) >= (int)sizeof ret) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "string overflow for key \"%s\"", key);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Returns the number value from a given key in an object node. */
|
||||
const int64_t *
|
||||
json_find_number(const struct json_node *jn, const char *key, char **cause)
|
||||
int
|
||||
json_find_number(const struct json_node *jn, const char *key, int64_t *out,
|
||||
char **cause)
|
||||
{
|
||||
struct json_node *field;
|
||||
static int64_t ret;
|
||||
|
||||
if ((field = json_find(jn, key)) == NULL) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" not found", key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
if (field->type != NODE_NUMBER) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" expected NUMBER value",
|
||||
key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
ret = field->num;
|
||||
*out = field->num;
|
||||
|
||||
return (&ret);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Returns the boolean value from a given key in an object node. */
|
||||
const int *
|
||||
json_find_boolean(const struct json_node *jn, const char *key, char **cause)
|
||||
int
|
||||
json_find_boolean(const struct json_node *jn, const char *key, int *out,
|
||||
char **cause)
|
||||
{
|
||||
struct json_node *field;
|
||||
static int ret;
|
||||
|
||||
if ((field = json_find(jn, key)) == NULL) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" not found", key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
if (field->type != NODE_BOOLEAN) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" expected BOOLEAN value",
|
||||
key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
ret = field->boolean;
|
||||
*out = field->boolean;
|
||||
|
||||
return (&ret);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Returns the object value from a given key in an object node. */
|
||||
const struct json_node *
|
||||
json_find_object(const struct json_node *jn, const char *key, char **cause)
|
||||
int
|
||||
json_find_object(const struct json_node *jn, const char *key,
|
||||
struct json_node **out, char **cause)
|
||||
{
|
||||
struct json_node *field;
|
||||
|
||||
if ((field = json_find(jn, key)) == NULL) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" not found", key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
if (field->type != NODE_OBJECT) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" expected OBJECT value",
|
||||
key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
*out = field;
|
||||
|
||||
return (field);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Returns the array value from a given key in an object node. */
|
||||
const struct json_node *
|
||||
json_find_array(const struct json_node *jn, const char *key, char **cause)
|
||||
int
|
||||
json_find_array(const struct json_node *jn, const char *key,
|
||||
struct json_node **out, char **cause)
|
||||
{
|
||||
struct json_node *field;
|
||||
|
||||
if ((field = json_find(jn, key)) == NULL) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" not found", key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
if (field->type != NODE_ARRAY) {
|
||||
if (cause != NULL)
|
||||
xasprintf(cause, "key \"%s\" expected ARRAY value",
|
||||
key);
|
||||
return (NULL);
|
||||
return (-1);
|
||||
}
|
||||
*out = field;
|
||||
|
||||
return (field);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Fill an error cause. */
|
||||
|
||||
175
layout-custom.c
175
layout-custom.c
@@ -66,7 +66,6 @@ struct layout_parse_cell_ctx {
|
||||
struct layout_cell *lc;
|
||||
int active;
|
||||
int last;
|
||||
int id;
|
||||
int index;
|
||||
int zindex;
|
||||
};
|
||||
@@ -96,6 +95,8 @@ static struct layout_cell *layout_parse_json_layout(
|
||||
const struct json_node *,
|
||||
struct layout_cell *,
|
||||
struct layout_parse_ctx *);
|
||||
static int layout_parse_ctx_check_indexes(
|
||||
struct layout_parse_ctx *);
|
||||
|
||||
/* Compare cell contexts in ascending order of index. */
|
||||
static int
|
||||
@@ -182,7 +183,7 @@ layout_parse_init_ctx(struct layout_parse_ctx *pctx, char **cause)
|
||||
/* Add a cell context to the parse context. */
|
||||
static int
|
||||
layout_parse_add_cctx(struct layout_parse_ctx *pctx, struct layout_cell *lc,
|
||||
int active, int last, int id, int index, int zindex)
|
||||
int active, int last, int index, int zindex)
|
||||
{
|
||||
struct layout_parse_cell_ctx *cctx;
|
||||
|
||||
@@ -193,7 +194,6 @@ layout_parse_add_cctx(struct layout_parse_ctx *pctx, struct layout_cell *lc,
|
||||
cctx->lc = lc;
|
||||
cctx->active = active;
|
||||
cctx->last = last;
|
||||
cctx->id = id;
|
||||
cctx->index = index;
|
||||
cctx->zindex = zindex;
|
||||
|
||||
@@ -458,7 +458,10 @@ layout_parse(struct window *w, const char *layout, char **cause)
|
||||
}
|
||||
|
||||
/* Check this window will fit into the layout. */
|
||||
npanes = window_count_panes(w, 1);
|
||||
if (pctx.version < 2)
|
||||
npanes = window_count_panes(w, 0);
|
||||
else
|
||||
npanes = window_count_panes(w, 1);
|
||||
for (;;) {
|
||||
ncells = layout_count_cells(pctx.root);
|
||||
if (npanes > ncells) {
|
||||
@@ -720,9 +723,8 @@ fail:
|
||||
static int
|
||||
layout_parse_json(struct json_node *jnroot, struct layout_parse_ctx *pctx)
|
||||
{
|
||||
struct json_node *jn;
|
||||
const struct json_node *object;
|
||||
const int64_t *num;
|
||||
struct json_node *jn, *object;
|
||||
int64_t num;
|
||||
char **cause = pctx->cause;
|
||||
|
||||
if (json_get_object(jnroot, &jn) != 0) {
|
||||
@@ -730,11 +732,11 @@ layout_parse_json(struct json_node *jnroot, struct layout_parse_ctx *pctx)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((num = json_find_number(jn, "V", cause)) == NULL)
|
||||
if (json_find_number(jn, "V", &num, cause) != 0)
|
||||
goto fail;
|
||||
pctx->version = *num;
|
||||
pctx->version = num;
|
||||
|
||||
if ((object = json_find_object(jn, "L", cause)) == NULL)
|
||||
if (json_find_object(jn, "L", &object, cause) != 0)
|
||||
goto fail;
|
||||
pctx->root = layout_parse_json_layout(object, NULL, pctx);
|
||||
if (pctx->root == NULL)
|
||||
@@ -757,16 +759,15 @@ static struct layout_cell *
|
||||
layout_parse_json_layout(const struct json_node *node,
|
||||
struct layout_cell *lcparent, struct layout_parse_ctx *pctx)
|
||||
{
|
||||
struct json_node *member;
|
||||
struct layout_cell *lc = layout_create_cell(lcparent), *lcchild;
|
||||
const struct json_node *array;
|
||||
const char *str;
|
||||
const int64_t *num;
|
||||
const int *boolean;
|
||||
char *endptr, **cause = pctx->cause;
|
||||
int id, index, zindex, active = -1, last = -1;
|
||||
struct json_node *member, *array;
|
||||
struct layout_cell *lc = layout_create_cell(lcparent), *lcchild;
|
||||
const char *str;
|
||||
int64_t num;
|
||||
char **cause = pctx->cause;
|
||||
int boolean, index, zindex, active = -1;
|
||||
int last = -1;
|
||||
|
||||
if ((str = json_find_string(node, "t", cause)) == NULL)
|
||||
if (json_find_string(node, "t", &str, cause) != 0)
|
||||
goto fail;
|
||||
if (strcmp(str, "p") == 0)
|
||||
lc->type = LAYOUT_WINDOWPANE;
|
||||
@@ -779,103 +780,88 @@ layout_parse_json_layout(const struct json_node *node,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((num = json_find_number(node, "w", cause)) == NULL)
|
||||
if (json_find_number(node, "w", &num, cause) != 0)
|
||||
goto fail;
|
||||
if (*num < PANE_MINIMUM || *num > PANE_MAXIMUM) {
|
||||
xasprintf(cause, "invalid width %lld", (long long)*num);
|
||||
if (num < PANE_MINIMUM || num > PANE_MAXIMUM) {
|
||||
xasprintf(cause, "invalid width %lld", (long long)num);
|
||||
goto fail;
|
||||
}
|
||||
lc->g.sx = *num;
|
||||
lc->g.sx = num;
|
||||
|
||||
if ((num = json_find_number(node, "h", cause)) == NULL)
|
||||
if (json_find_number(node, "h", &num, cause) != 0)
|
||||
goto fail;
|
||||
if (*num < PANE_MINIMUM || *num > PANE_MAXIMUM) {
|
||||
xasprintf(cause, "invalid height %lld", (long long)*num);
|
||||
if (num < PANE_MINIMUM || num > PANE_MAXIMUM) {
|
||||
xasprintf(cause, "invalid height %lld", (long long)num);
|
||||
goto fail;
|
||||
}
|
||||
lc->g.sy = *num;
|
||||
lc->g.sy = num;
|
||||
|
||||
if ((num = json_find_number(node, "x", cause)) == NULL)
|
||||
if (json_find_number(node, "x", &num, cause) != 0)
|
||||
goto fail;
|
||||
if (*num < -WINDOW_MAXIMUM || *num > WINDOW_MAXIMUM) {
|
||||
xasprintf(cause, "invalid x-offset %lld", (long long)*num);
|
||||
if (num < -WINDOW_MAXIMUM || num > WINDOW_MAXIMUM) {
|
||||
xasprintf(cause, "invalid x-offset %lld", (long long)num);
|
||||
goto fail;
|
||||
}
|
||||
lc->g.xoff = *num;
|
||||
lc->g.xoff = num;
|
||||
|
||||
if ((num = json_find_number(node, "y", cause)) == NULL)
|
||||
if (json_find_number(node, "y", &num, cause) != 0)
|
||||
goto fail;
|
||||
if (*num < -WINDOW_MAXIMUM || *num > WINDOW_MAXIMUM) {
|
||||
xasprintf(cause, "invalid y-offset %lld", (long long)*num);
|
||||
if (num < -WINDOW_MAXIMUM || num > WINDOW_MAXIMUM) {
|
||||
xasprintf(cause, "invalid y-offset %lld", (long long)num);
|
||||
goto fail;
|
||||
}
|
||||
lc->g.yoff = *num;
|
||||
lc->g.yoff = num;
|
||||
|
||||
if (lc->type == LAYOUT_WINDOWPANE) {
|
||||
if (lc->type == LAYOUT_WINDOWPANE) { /* "I" is currently ignored */
|
||||
if (json_find(node, "c") != NULL) {
|
||||
*cause = xstrdup("panes cannot have children");
|
||||
goto fail;
|
||||
}
|
||||
if ((str = json_find_string(node, "I", cause)) == NULL)
|
||||
if (json_find_number(node, "i", &num, cause) != 0)
|
||||
goto fail;
|
||||
if (*str != '%') {
|
||||
*cause = xstrdup("pane id must begin with '%'");
|
||||
if (num < 0 || num > INT_MAX) {
|
||||
xasprintf(cause, "invalid index %lld", (long long)num);
|
||||
goto fail;
|
||||
}
|
||||
errno = 0;
|
||||
id = strtol(str + 1, &endptr, 10);
|
||||
if (errno != 0 || endptr != str + strlen(str)) {
|
||||
xasprintf(cause, "invalid number string '%s'", str);
|
||||
goto fail;
|
||||
}
|
||||
if ((num = json_find_number(node, "i", cause)) == NULL)
|
||||
goto fail;
|
||||
if (*num < 0 || *num > INT_MAX) {
|
||||
xasprintf(cause, "invalid index %lld", (long long)*num);
|
||||
goto fail;
|
||||
}
|
||||
index = *num;
|
||||
index = num;
|
||||
|
||||
if (json_find(node, "a") != NULL) {
|
||||
boolean = json_find_boolean(node, "a", cause);
|
||||
if (boolean == NULL)
|
||||
if (json_find_boolean(node, "a", &boolean, cause) != 0)
|
||||
goto fail;
|
||||
active = *boolean;
|
||||
active = boolean;
|
||||
if (active)
|
||||
pctx->num_active++;
|
||||
} else if (json_find(node, "l") != NULL) {
|
||||
num = json_find_number(node, "l", cause);
|
||||
if (num == NULL)
|
||||
if (json_find_number(node, "l", &num, cause) != 0)
|
||||
goto fail;
|
||||
if (*num < 0 || *num > INT_MAX) {
|
||||
if (num < 0 || num > INT_MAX) {
|
||||
xasprintf(cause, "invalid last %lld",
|
||||
(long long)*num);
|
||||
(long long)num);
|
||||
goto fail;
|
||||
}
|
||||
last = *num;
|
||||
last = num;
|
||||
}
|
||||
|
||||
if (json_find(node, "z") != NULL) {
|
||||
num = json_find_number(node, "z", cause);
|
||||
if (num == NULL)
|
||||
if (json_find_number(node, "z", &num, cause) != 0)
|
||||
goto fail;
|
||||
if (*num < 0 || *num > INT_MAX - 1) {
|
||||
if (num < 0 || num > INT_MAX - 1) {
|
||||
xasprintf(cause, "invalid floating zindex %lld",
|
||||
(long long)*num);
|
||||
(long long)num);
|
||||
goto fail;
|
||||
}
|
||||
zindex = *num;
|
||||
zindex = num;
|
||||
lc->flags |= LAYOUT_CELL_FLOATING;
|
||||
} else
|
||||
zindex = INT_MAX;
|
||||
|
||||
if (layout_parse_add_cctx(pctx, lc, active, last, id, index,
|
||||
if (layout_parse_add_cctx(pctx, lc, active, last, index,
|
||||
zindex) != 0) {
|
||||
*cause = xstrdup("too many panes");
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
if ((array = json_find_array(node, "c", cause)) == NULL)
|
||||
if (json_find_array(node, "c", &array, cause) != 0)
|
||||
goto fail;
|
||||
if ((member = json_array_first(array)) == NULL) {
|
||||
*cause = xstrdup("nodes must have children");
|
||||
@@ -943,6 +929,8 @@ layout_construct(const char *layout, struct layout_parse_ctx *pctx)
|
||||
*pctx->cause = xstrdup("no panes");
|
||||
return (-1);
|
||||
}
|
||||
if (!layout_parse_ctx_check_indexes(pctx))
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
@@ -1001,3 +989,56 @@ layout_parse_apply_ctx(struct window *w, struct layout_parse_ctx *pctx)
|
||||
window_pane_stack_push(&w->last_panes, wp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks for duplicate pane indexes, z-indexes, and last indexes. */
|
||||
static int
|
||||
layout_parse_ctx_check_indexes(struct layout_parse_ctx *pctx)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
qsort(pctx->cctxs, pctx->clen, sizeof pctx->cctxs[0],
|
||||
layout_parse_index_cmp);
|
||||
|
||||
for (i = 1; i < pctx->clen; i++) {
|
||||
if (pctx->cctxs[i].index == pctx->cctxs[i - 1].index) {
|
||||
*pctx->cause = xstrdup("duplicate pane index");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
qsort(pctx->cctxs, pctx->clen, sizeof pctx->cctxs[0],
|
||||
layout_parse_zindex_cmp);
|
||||
|
||||
/*
|
||||
* Sorted in descending order, so the panes without a z-index come first
|
||||
* and the floating panes run to the end.
|
||||
*/
|
||||
n = 0;
|
||||
while (n < pctx->clen && pctx->cctxs[n].zindex == INT_MAX)
|
||||
n++;
|
||||
for (i = n + 1; i < pctx->clen; i++) {
|
||||
if (pctx->cctxs[i].zindex == pctx->cctxs[i - 1].zindex) {
|
||||
*pctx->cause = xstrdup("duplicate pane z-index");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
qsort(pctx->cctxs, pctx->clen, sizeof pctx->cctxs[0],
|
||||
layout_parse_last_cmp);
|
||||
|
||||
/*
|
||||
* Sorted in descending order, so the panes without a last index come
|
||||
* last.
|
||||
*/
|
||||
n = 0;
|
||||
while (n < pctx->clen && pctx->cctxs[n].last >= 0)
|
||||
n++;
|
||||
for (i = 1; i < n; i++) {
|
||||
if (pctx->cctxs[i].last == pctx->cctxs[i - 1].last) {
|
||||
*pctx->cause = xstrdup("duplicate last pane index");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
20
tmux.h
20
tmux.h
@@ -4287,15 +4287,15 @@ int json_get_object(struct json_node *,
|
||||
struct json_node **);
|
||||
int json_get_array(struct json_node *,
|
||||
struct json_node **);
|
||||
const char *json_find_string(const struct json_node *,
|
||||
const char *, char **);
|
||||
const int64_t *json_find_number(const struct json_node *,
|
||||
const char *, char **);
|
||||
const int *json_find_boolean(const struct json_node *,
|
||||
const char *, char **);
|
||||
const struct json_node *json_find_object(const struct json_node *,
|
||||
const char *, char **);
|
||||
const struct json_node *json_find_array(const struct json_node *,
|
||||
const char *, char **);
|
||||
int json_find_string(const struct json_node *,
|
||||
const char *, const char **, char **);
|
||||
int json_find_number(const struct json_node *,
|
||||
const char *, int64_t *, char **);
|
||||
int json_find_boolean(const struct json_node *,
|
||||
const char *, int *, char **);
|
||||
int json_find_object(const struct json_node *,
|
||||
const char *, struct json_node **, char **);
|
||||
int json_find_array(const struct json_node *,
|
||||
const char *, struct json_node **, char **);
|
||||
|
||||
#endif /* TMUX_H */
|
||||
|
||||
Reference in New Issue
Block a user