mirror of
https://github.com/tmux/tmux.git
synced 2026-06-20 17:25:57 +00:00
Merge branch 'master' into screen_redraw
This commit is contained in:
@@ -168,6 +168,7 @@ cmd_refresh_report(struct tty *tty, const char *value)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
u_int pane;
|
||||
int fg, bg;
|
||||
size_t size = 0;
|
||||
char *copy, *split;
|
||||
|
||||
@@ -184,8 +185,14 @@ cmd_refresh_report(struct tty *tty, const char *value)
|
||||
if (wp == NULL)
|
||||
goto out;
|
||||
|
||||
tty_keys_colours(tty, split, strlen(split), &size, &wp->control_fg,
|
||||
&wp->control_bg);
|
||||
fg = wp->control_fg;
|
||||
bg = wp->control_bg;
|
||||
if (tty_keys_colours(tty, split, strlen(split), &size, &fg, &bg) == 0) {
|
||||
if (bg != wp->control_bg)
|
||||
wp->flags |= PANE_THEMECHANGED;
|
||||
wp->control_fg = fg;
|
||||
wp->control_bg = bg;
|
||||
}
|
||||
|
||||
out:
|
||||
free(copy);
|
||||
|
||||
22
colour.c
22
colour.c
@@ -120,6 +120,28 @@ colour_force_rgb(int c)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Dim colour by a percentage. */
|
||||
int
|
||||
colour_dim(int c, u_int dim)
|
||||
{
|
||||
u_char r, g, b;
|
||||
|
||||
if (dim == 0 || COLOUR_DEFAULT(c))
|
||||
return (c);
|
||||
if (dim >= 100)
|
||||
return (colour_join_rgb(0, 0, 0));
|
||||
|
||||
c = colour_force_rgb(c);
|
||||
if (c == -1)
|
||||
return (-1);
|
||||
colour_split_rgb(c, &r, &g, &b);
|
||||
|
||||
r = (r * (100 - dim)) / 100;
|
||||
g = (g * (100 - dim)) / 100;
|
||||
b = (b * (100 - dim)) / 100;
|
||||
return (colour_join_rgb(r, g, b));
|
||||
}
|
||||
|
||||
/* Convert colour to a string. */
|
||||
const char *
|
||||
colour_tostring(int c)
|
||||
|
||||
@@ -224,6 +224,14 @@ control_notify_session_window_changed(struct session *s)
|
||||
{
|
||||
struct client *c;
|
||||
|
||||
/*
|
||||
* A deferred session-window-changed notification can fire after the
|
||||
* session has been destroyed (which sets curw to NULL) but is kept
|
||||
* alive by the notification's reference. Skip the notification.
|
||||
*/
|
||||
if (s->curw == NULL)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||
continue;
|
||||
|
||||
180
format.c
180
format.c
@@ -128,6 +128,9 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
|
||||
/* Limit on time taken (milliseconds). */
|
||||
#define FORMAT_TIME_LIMIT 100
|
||||
|
||||
/* How often to check the time in long loops. */
|
||||
#define FORMAT_TIME_LOOP_CHECK 10000
|
||||
|
||||
/* Format expand flags. */
|
||||
#define FORMAT_EXPAND_TIME 0x1
|
||||
#define FORMAT_EXPAND_NOJOBS 0x2
|
||||
@@ -573,7 +576,7 @@ format_cb_session_attached_list(struct format_tree *ft)
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
@@ -712,7 +715,7 @@ format_cb_window_linked_sessions_list(struct format_tree *ft)
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
@@ -766,7 +769,7 @@ format_cb_window_active_sessions_list(struct format_tree *ft)
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
@@ -830,7 +833,7 @@ format_cb_window_active_clients_list(struct format_tree *ft)
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
@@ -1005,7 +1008,7 @@ format_cb_pane_tabs(struct format_tree *ft)
|
||||
evbuffer_add_printf(buffer, "%u", i);
|
||||
}
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
@@ -1020,7 +1023,7 @@ format_cb_pane_fg(struct format_tree *ft)
|
||||
if (wp == NULL)
|
||||
return (NULL);
|
||||
|
||||
tty_default_colours(&gc, wp);
|
||||
tty_default_colours(&gc, wp, NULL);
|
||||
return (xstrdup(colour_tostring(gc.fg)));
|
||||
}
|
||||
|
||||
@@ -1057,7 +1060,7 @@ format_cb_pane_bg(struct format_tree *ft)
|
||||
if (wp == NULL)
|
||||
return (NULL);
|
||||
|
||||
tty_default_colours(&gc, wp);
|
||||
tty_default_colours(&gc, wp, NULL);
|
||||
return (xstrdup(colour_tostring(gc.bg)));
|
||||
}
|
||||
|
||||
@@ -1089,7 +1092,7 @@ format_cb_session_group_list(struct format_tree *ft)
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
@@ -1129,7 +1132,7 @@ format_cb_session_group_attached_list(struct format_tree *ft)
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
xasprintf(&value, "%.*s", size, EVBUFFER_DATA(buffer));
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
@@ -1853,15 +1856,6 @@ format_cb_keypad_flag(struct format_tree *ft)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Callback for loop_last_flag. */
|
||||
static void *
|
||||
format_cb_loop_last_flag(struct format_tree *ft)
|
||||
{
|
||||
if (ft->flags & FORMAT_LAST)
|
||||
return (xstrdup("1"));
|
||||
return (xstrdup("0"));
|
||||
}
|
||||
|
||||
/* Callback for mouse_all_flag. */
|
||||
static void *
|
||||
format_cb_mouse_all_flag(struct format_tree *ft)
|
||||
@@ -3346,9 +3340,6 @@ static const struct format_table_entry format_table[] = {
|
||||
{ "last_window_index", FORMAT_TABLE_STRING,
|
||||
format_cb_last_window_index
|
||||
},
|
||||
{ "loop_last_flag", FORMAT_TABLE_STRING,
|
||||
format_cb_loop_last_flag
|
||||
},
|
||||
{ "mouse_all_flag", FORMAT_TABLE_STRING,
|
||||
format_cb_mouse_all_flag
|
||||
},
|
||||
@@ -4237,10 +4228,14 @@ found:
|
||||
|
||||
/* Check if format has not taken too long. */
|
||||
static int
|
||||
format_check_time(struct format_expand_state *es)
|
||||
format_check_time(struct format_expand_state *es, u_int *check)
|
||||
{
|
||||
uint64_t t = get_timer();
|
||||
uint64_t t;
|
||||
|
||||
if (check != NULL && ++*check % FORMAT_TIME_LOOP_CHECK != 0)
|
||||
return (1);
|
||||
|
||||
t = get_timer();
|
||||
if (t - es->start_time < FORMAT_TIME_LIMIT)
|
||||
return (1);
|
||||
t -= es->start_time;
|
||||
@@ -4251,21 +4246,24 @@ format_check_time(struct format_expand_state *es)
|
||||
|
||||
/* Unescape escaped characters. */
|
||||
static char *
|
||||
format_unescape(struct format_expand_state *es, const char *s)
|
||||
format_unescape(struct format_expand_state *es, const char *s, size_t n)
|
||||
{
|
||||
char *out, *cp;
|
||||
int brackets = 0;
|
||||
const char *end = s + n;
|
||||
char *out, *cp;
|
||||
int brackets = 0;
|
||||
u_int check = 0;
|
||||
|
||||
cp = out = xmalloc(strlen(s) + 1);
|
||||
for (; *s != '\0'; s++) {
|
||||
if (!format_check_time(es)){
|
||||
cp = out = xmalloc(n + 1);
|
||||
for (; s != end; s++) {
|
||||
if (!format_check_time(es, &check)) {
|
||||
free(out);
|
||||
return (xstrdup(""));
|
||||
}
|
||||
if (*s == '#' && s[1] == '{')
|
||||
if (*s == '#' && s + 1 != end && s[1] == '{')
|
||||
brackets++;
|
||||
if (brackets == 0 &&
|
||||
*s == '#' &&
|
||||
s + 1 != end &&
|
||||
strchr(",#{}:", s[1]) != NULL) {
|
||||
*cp++ = *++s;
|
||||
continue;
|
||||
@@ -4284,10 +4282,11 @@ format_strip(struct format_expand_state *es, const char *s)
|
||||
{
|
||||
char *out, *cp;
|
||||
int brackets = 0;
|
||||
u_int check = 0;
|
||||
|
||||
cp = out = xmalloc(strlen(s) + 1);
|
||||
for (; *s != '\0'; s++) {
|
||||
if (!format_check_time(es)){
|
||||
if (!format_check_time(es, &check)) {
|
||||
free(out);
|
||||
return (xstrdup(""));
|
||||
}
|
||||
@@ -4311,9 +4310,10 @@ static const char *
|
||||
format_skip1(struct format_expand_state *es, const char *s, const char *end)
|
||||
{
|
||||
int brackets = 0;
|
||||
u_int check = 0;
|
||||
|
||||
for (; *s != '\0'; s++) {
|
||||
if (es != NULL && !format_check_time(es))
|
||||
if (es != NULL && !format_check_time(es, &check))
|
||||
return (NULL);
|
||||
if (*s == '#' && s[1] == '{')
|
||||
brackets++;
|
||||
@@ -4484,7 +4484,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
||||
break;
|
||||
|
||||
argv = xcalloc(1, sizeof *argv);
|
||||
value = xstrndup(cp + 1, end - (cp + 1));
|
||||
value = format_unescape(es, cp + 1, end - (cp + 1));
|
||||
argv[0] = format_expand1(es, value);
|
||||
free(value);
|
||||
argc = 1;
|
||||
@@ -4508,7 +4508,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
|
||||
cp++;
|
||||
|
||||
argv = xreallocarray(argv, argc + 1, sizeof *argv);
|
||||
value = xstrndup(cp, end - cp);
|
||||
value = format_unescape(es, cp, end - cp);
|
||||
argv[argc++] = format_expand1(es, value);
|
||||
free(value);
|
||||
|
||||
@@ -4671,17 +4671,19 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
||||
struct format_tree *nft;
|
||||
struct format_expand_state next;
|
||||
char *all, *active, *use, *expanded, *value;
|
||||
size_t valuelen;
|
||||
struct evbuffer *buffer;
|
||||
size_t size;
|
||||
struct session *s, **l;
|
||||
int i, n, last = 0;
|
||||
int i, n;
|
||||
|
||||
if (format_choose(es, fmt, &all, &active, 0) != 0) {
|
||||
all = xstrdup(fmt);
|
||||
active = NULL;
|
||||
}
|
||||
|
||||
value = xcalloc(1, 1);
|
||||
valuelen = 1;
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
l = sort_get_sessions(&n, sc);
|
||||
for (i = 0; i < n; i++) {
|
||||
@@ -4693,25 +4695,27 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
||||
use = active;
|
||||
else
|
||||
use = all;
|
||||
if (i == n - 1)
|
||||
last = FORMAT_LAST;
|
||||
nft = format_create(c, item, FORMAT_NONE, ft->flags|last);
|
||||
nft = format_create(c, item, FORMAT_NONE, ft->flags);
|
||||
format_add(nft, "loop_index", "%d", i);
|
||||
format_add(nft, "loop_last_flag", "%d", i == n - 1);
|
||||
format_defaults(nft, ft->c, s, NULL, NULL);
|
||||
format_copy_state(&next, es, 0);
|
||||
next.ft = nft;
|
||||
expanded = format_expand1(&next, use);
|
||||
format_free(next.ft);
|
||||
|
||||
valuelen += strlen(expanded);
|
||||
value = xrealloc(value, valuelen);
|
||||
|
||||
strlcat(value, expanded, valuelen);
|
||||
evbuffer_add(buffer, expanded, strlen(expanded));
|
||||
free(expanded);
|
||||
}
|
||||
|
||||
free(active);
|
||||
free(all);
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
else
|
||||
value = xstrdup("");
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
|
||||
@@ -4781,10 +4785,11 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
||||
struct format_tree *nft;
|
||||
struct format_expand_state next;
|
||||
char *all, *active, *use, *expanded, *value;
|
||||
size_t valuelen;
|
||||
struct evbuffer *buffer;
|
||||
size_t size;
|
||||
struct winlink *wl, **l;
|
||||
struct window *w;
|
||||
int i, n, last = 0;
|
||||
int i, n;
|
||||
|
||||
if (ft->s == NULL) {
|
||||
format_log(es, "window loop but no session");
|
||||
@@ -4796,8 +4801,9 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
||||
active = NULL;
|
||||
}
|
||||
|
||||
value = xcalloc(1, 1);
|
||||
valuelen = 1;
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
l = sort_get_winlinks_session(ft->s, &n, sc);
|
||||
for (i = 0; i < n; i++) {
|
||||
@@ -4808,10 +4814,10 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
||||
use = active;
|
||||
else
|
||||
use = all;
|
||||
if (i == n - 1)
|
||||
last = FORMAT_LAST;
|
||||
nft = format_create(c, item, FORMAT_WINDOW|w->id,
|
||||
ft->flags|last);
|
||||
ft->flags);
|
||||
format_add(nft, "loop_index", "%d", i);
|
||||
format_add(nft, "loop_last_flag", "%d", i == n - 1);
|
||||
format_defaults(nft, ft->c, ft->s, wl, NULL);
|
||||
|
||||
/* Add neighbor window data to the format tree. */
|
||||
@@ -4829,16 +4835,18 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
||||
expanded = format_expand1(&next, use);
|
||||
format_free(nft);
|
||||
|
||||
valuelen += strlen(expanded);
|
||||
value = xrealloc(value, valuelen);
|
||||
|
||||
strlcat(value, expanded, valuelen);
|
||||
evbuffer_add(buffer, expanded, strlen(expanded));
|
||||
free(expanded);
|
||||
}
|
||||
|
||||
free(active);
|
||||
free(all);
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
else
|
||||
value = xstrdup("");
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
|
||||
@@ -4853,9 +4861,10 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
||||
struct format_tree *nft;
|
||||
struct format_expand_state next;
|
||||
char *all, *active, *use, *expanded, *value;
|
||||
size_t valuelen;
|
||||
struct evbuffer *buffer;
|
||||
size_t size;
|
||||
struct window_pane *wp, **l;
|
||||
int i, n, last = 0;
|
||||
int i, n;
|
||||
|
||||
if (ft->w == NULL) {
|
||||
format_log(es, "pane loop but no window");
|
||||
@@ -4867,8 +4876,9 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
||||
active = NULL;
|
||||
}
|
||||
|
||||
value = xcalloc(1, 1);
|
||||
valuelen = 1;
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
l = sort_get_panes_window(ft->w, &n, sc);
|
||||
for (i = 0; i < n; i++) {
|
||||
@@ -4878,26 +4888,28 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
||||
use = active;
|
||||
else
|
||||
use = all;
|
||||
if (i == n - 1)
|
||||
last = FORMAT_LAST;
|
||||
nft = format_create(c, item, FORMAT_PANE|wp->id,
|
||||
ft->flags|last);
|
||||
ft->flags);
|
||||
format_add(nft, "loop_index", "%d", i);
|
||||
format_add(nft, "loop_last_flag", "%d", i == n - 1);
|
||||
format_defaults(nft, ft->c, ft->s, ft->wl, wp);
|
||||
format_copy_state(&next, es, 0);
|
||||
next.ft = nft;
|
||||
expanded = format_expand1(&next, use);
|
||||
format_free(nft);
|
||||
|
||||
valuelen += strlen(expanded);
|
||||
value = xrealloc(value, valuelen);
|
||||
|
||||
strlcat(value, expanded, valuelen);
|
||||
evbuffer_add(buffer, expanded, strlen(expanded));
|
||||
free(expanded);
|
||||
}
|
||||
|
||||
free(active);
|
||||
free(all);
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
else
|
||||
value = xstrdup("");
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
|
||||
@@ -4912,32 +4924,36 @@ format_loop_clients(struct format_expand_state *es, const char *fmt)
|
||||
struct format_tree *nft;
|
||||
struct format_expand_state next;
|
||||
char *expanded, *value;
|
||||
size_t valuelen;
|
||||
int i, n, last = 0;
|
||||
struct evbuffer *buffer;
|
||||
size_t size;
|
||||
int i, n;
|
||||
|
||||
value = xcalloc(1, 1);
|
||||
valuelen = 1;
|
||||
buffer = evbuffer_new();
|
||||
if (buffer == NULL)
|
||||
fatalx("out of memory");
|
||||
|
||||
l = sort_get_clients(&n, sc);
|
||||
for (i = 0; i < n; i++) {
|
||||
c = l[i];
|
||||
format_log(es, "client loop: %s", c->name);
|
||||
if (i == n - 1)
|
||||
last = FORMAT_LAST;
|
||||
nft = format_create(c, item, 0, ft->flags|last);
|
||||
nft = format_create(c, item, 0, ft->flags);
|
||||
format_add(nft, "loop_index", "%d", i);
|
||||
format_add(nft, "loop_last_flag", "%d", i == n - 1);
|
||||
format_defaults(nft, c, ft->s, ft->wl, ft->wp);
|
||||
format_copy_state(&next, es, 0);
|
||||
next.ft = nft;
|
||||
expanded = format_expand1(&next, fmt);
|
||||
format_free(nft);
|
||||
|
||||
valuelen += strlen(expanded);
|
||||
value = xrealloc(value, valuelen);
|
||||
|
||||
strlcat(value, expanded, valuelen);
|
||||
evbuffer_add(buffer, expanded, strlen(expanded));
|
||||
free(expanded);
|
||||
}
|
||||
|
||||
if ((size = EVBUFFER_LENGTH(buffer)) != 0)
|
||||
value = xmemdup(EVBUFFER_DATA(buffer), size);
|
||||
else
|
||||
value = xstrdup("");
|
||||
evbuffer_free(buffer);
|
||||
return (value);
|
||||
}
|
||||
|
||||
@@ -5103,7 +5119,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
struct format_modifier *list, *cmp = NULL, *search = NULL;
|
||||
struct format_modifier **sub = NULL, *mexp = NULL, *fm;
|
||||
struct format_modifier *bool_op_n = NULL;
|
||||
u_int i, count, nsub = 0, nrep;
|
||||
u_int i, count, nsub = 0, nrep, check = 0;
|
||||
struct format_expand_state next;
|
||||
struct environ_entry *envent;
|
||||
|
||||
@@ -5360,7 +5376,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
/* Is this a literal string? */
|
||||
if (modifiers & FORMAT_LITERAL) {
|
||||
format_log(es, "literal string is '%s'", copy);
|
||||
value = format_unescape(es, copy);
|
||||
value = format_unescape(es, copy, strlen(copy));
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -5436,7 +5452,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
else {
|
||||
value = xstrdup("");
|
||||
for (i = 0; i < nrep; i++) {
|
||||
if (!format_check_time(es)) {
|
||||
if (!format_check_time(es, &check)) {
|
||||
free(right);
|
||||
free(left);
|
||||
free(value);
|
||||
@@ -5716,7 +5732,7 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
||||
int ch, brackets;
|
||||
char expanded[8192];
|
||||
|
||||
if (fmt == NULL || *fmt == '\0' || !format_check_time(es))
|
||||
if (fmt == NULL || *fmt == '\0' || !format_check_time(es, NULL))
|
||||
return (xstrdup(""));
|
||||
|
||||
if (es->loop == FORMAT_LOOP_LIMIT) {
|
||||
|
||||
@@ -450,11 +450,11 @@ sixel_scale(struct sixel_image *si, u_int xpixel, u_int ypixel, u_int ox,
|
||||
|
||||
new->set_ra = si->set_ra;
|
||||
/* subtract offset */
|
||||
new->ra_x = new->ra_x > pox ? new->ra_x - pox : 0;
|
||||
new->ra_y = new->ra_y > poy ? new->ra_y - poy : 0;
|
||||
new->ra_x = si->ra_x > pox ? si->ra_x - pox : 0;
|
||||
new->ra_y = si->ra_y > poy ? si->ra_y - poy : 0;
|
||||
/* clamp to size */
|
||||
new->ra_x = si->ra_x < psx ? si->ra_x : psx;
|
||||
new->ra_y = si->ra_y < psy ? si->ra_y : psy;
|
||||
new->ra_x = new->ra_x < psx ? new->ra_x : psx;
|
||||
new->ra_y = new->ra_y < psy ? new->ra_y : psy;
|
||||
/* resize */
|
||||
new->ra_x = new->ra_x * xpixel / si->xpixel;
|
||||
new->ra_y = new->ra_y * ypixel / si->ypixel;
|
||||
|
||||
2
input.c
2
input.c
@@ -3055,7 +3055,7 @@ input_osc_10(struct input_ctx *ictx, const char *p)
|
||||
return;
|
||||
c = window_pane_get_fg_control_client(wp);
|
||||
if (c == -1) {
|
||||
tty_default_colours(&defaults, wp);
|
||||
tty_default_colours(&defaults, wp, NULL);
|
||||
if (COLOUR_DEFAULT(defaults.fg))
|
||||
c = window_pane_get_fg(wp);
|
||||
else
|
||||
|
||||
@@ -25,11 +25,10 @@
|
||||
#include "tmux.h"
|
||||
|
||||
#define DEFAULT_SESSION_MENU \
|
||||
" 'Next' 'n' {switch-client -n}" \
|
||||
" 'Previous' 'p' {switch-client -p}" \
|
||||
" #{S/t:#{?#{&&:#{<:#{loop_index},6},#{!:#{session_active}}},'Switch To #[underscore]#{session_name}' '' {switch-client -t=#{session_id}#} ,}}" \
|
||||
" ''" \
|
||||
" 'Renumber' 'N' {move-window -r}" \
|
||||
" 'Rename' 'r' {command-prompt -I \"#S\" {rename-session -- '%%'}}" \
|
||||
" 'Rename' 'r' {command-prompt -I '#S' {rename-session -- '%%'}}" \
|
||||
" 'Detach' 'd' {detach-client}" \
|
||||
" ''" \
|
||||
" 'New Session' 's' {new-session}" \
|
||||
@@ -486,8 +485,8 @@ key_bindings_init(void)
|
||||
"bind -n WheelUpStatus { previous-window }",
|
||||
|
||||
/* Mouse button 3 down on status left. */
|
||||
"bind -n MouseDown3StatusLeft { display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU " }",
|
||||
"bind -n M-MouseDown3StatusLeft { display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU " }",
|
||||
"bind -n MouseDown3StatusLeft { run -C \"display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU "\" }",
|
||||
"bind -n M-MouseDown3StatusLeft { run -C \"display-menu -t= -xM -yW -T '#[align=centre]#{session_name}' " DEFAULT_SESSION_MENU "\" }",
|
||||
|
||||
/* Mouse button 3 down on status line. */
|
||||
"bind -n MouseDown3Status { display-menu -t= -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU "}",
|
||||
@@ -578,6 +577,8 @@ key_bindings_init(void)
|
||||
"bind -Tcopy-mode M-Down { send -X halfpage-down }",
|
||||
"bind -Tcopy-mode C-Up { send -X scroll-up }",
|
||||
"bind -Tcopy-mode C-Down { send -X scroll-down }",
|
||||
"bind -Tcopy-mode M-C-Up { send -X previous-prompt }",
|
||||
"bind -Tcopy-mode M-C-Down { send -X next-prompt }",
|
||||
|
||||
/* Copy mode (vi) keys. */
|
||||
"bind -Tcopy-mode-vi '#' { send -FX search-backward -- '#{copy_cursor_word}' }",
|
||||
|
||||
131
mode-tree.c
131
mode-tree.c
@@ -84,6 +84,7 @@ struct mode_tree_data {
|
||||
int no_matches;
|
||||
enum mode_tree_search_dir search_dir;
|
||||
int search_icase;
|
||||
int help;
|
||||
};
|
||||
|
||||
struct mode_tree_item {
|
||||
@@ -124,6 +125,8 @@ struct mode_tree_menu {
|
||||
};
|
||||
|
||||
static void mode_tree_free_items(struct mode_tree_list *);
|
||||
static void mode_tree_draw_help(struct mode_tree_data *,
|
||||
struct screen_write_ctx *);
|
||||
|
||||
static const struct menu_item mode_tree_menu_items[] = {
|
||||
{ "Scroll Left", '<', NULL },
|
||||
@@ -135,31 +138,31 @@ static const struct menu_item mode_tree_menu_items[] = {
|
||||
};
|
||||
|
||||
static const char* mode_tree_help_start[] = {
|
||||
"\r\033[1m Up, k \033[0m\016x\017 \033[0mMove cursor up\n",
|
||||
"\r\033[1m Down, j \033[0m\016x\017 \033[0mMove cursor down\n",
|
||||
"\r\033[1m g \033[0m\016x\017 \033[0mGo to top\n",
|
||||
"\r\033[1m G \033[0m\016x\017 \033[0mGo to bottom\n",
|
||||
"\r\033[1m PPage, C-b \033[0m\016x\017 \033[0mPage up\n",
|
||||
"\r\033[1m NPage, C-f \033[0m\016x\017 \033[0mPage down\n",
|
||||
"\r\033[1m Left, h \033[0m\016x\017 \033[0mCollapse %1\n",
|
||||
"\r\033[1m Right, l \033[0m\016x\017 \033[0mExpand %1\n",
|
||||
"\r\033[1m M-- \033[0m\016x\017 \033[0mCollapse all %1s\n",
|
||||
"\r\033[1m M-+ \033[0m\016x\017 \033[0mExpand all %1s\n",
|
||||
"\r\033[1m t \033[0m\016x\017 \033[0mToggle %1 tag\n",
|
||||
"\r\033[1m T \033[0m\016x\017 \033[0mUntag all %1s\n",
|
||||
"\r\033[1m C-t \033[0m\016x\017 \033[0mTag all %1s\n",
|
||||
"\r\033[1m C-s \033[0m\016x\017 \033[0mSearch forward\n",
|
||||
"\r\033[1m C-r \033[0m\016x\017 \033[0mSearch backward\n",
|
||||
"\r\033[1m n \033[0m\016x\017 \033[0mRepeat search forward\n",
|
||||
"\r\033[1m N \033[0m\016x\017 \033[0mRepeat search backward\n",
|
||||
"\r\033[1m f \033[0m\016x\017 \033[0mFilter %1s\n",
|
||||
"\r\033[1m O \033[0m\016x\017 \033[0mChange sort order\n",
|
||||
"\r\033[1m r \033[0m\016x\017 \033[0mReverse sort order\n",
|
||||
"\r\033[1m v \033[0m\016x\017 \033[0mToggle preview\n",
|
||||
"#[bold] Up, k #[default]#[acs]x#[default] Move cursor up",
|
||||
"#[bold] Down, j #[default]#[acs]x#[default] Move cursor down",
|
||||
"#[bold] g #[default]#[acs]x#[default] Go to top",
|
||||
"#[bold] G #[default]#[acs]x#[default] Go to bottom",
|
||||
"#[bold] PPage, C-b #[default]#[acs]x#[default] Page up",
|
||||
"#[bold] NPage, C-f #[default]#[acs]x#[default] Page down",
|
||||
"#[bold] Left, h #[default]#[acs]x#[default] Collapse %1",
|
||||
"#[bold] Right, l #[default]#[acs]x#[default] Expand %1",
|
||||
"#[bold] M-- #[default]#[acs]x#[default] Collapse all %1s",
|
||||
"#[bold] M-+ #[default]#[acs]x#[default] Expand all %1s",
|
||||
"#[bold] t #[default]#[acs]x#[default] Toggle %1 tag",
|
||||
"#[bold] T #[default]#[acs]x#[default] Untag all %1s",
|
||||
"#[bold] C-t #[default]#[acs]x#[default] Tag all %1s",
|
||||
"#[bold] C-s #[default]#[acs]x#[default] Search forward",
|
||||
"#[bold] C-r #[default]#[acs]x#[default] Search backward",
|
||||
"#[bold] n #[default]#[acs]x#[default] Repeat search forward",
|
||||
"#[bold] N #[default]#[acs]x#[default] Repeat search backward",
|
||||
"#[bold] f #[default]#[acs]x#[default] Filter %1s",
|
||||
"#[bold] O #[default]#[acs]x#[default] Change sort order",
|
||||
"#[bold] r #[default]#[acs]x#[default] Reverse sort order",
|
||||
"#[bold] v #[default]#[acs]x#[default] Toggle preview",
|
||||
NULL
|
||||
};
|
||||
static const char* mode_tree_help_end[] = {
|
||||
"\r\033[1m q, Escape \033[0m\016x\017 \033[0mExit mode\033[H",
|
||||
"#[bold] q, Escape #[default]#[acs]x#[default] Exit mode",
|
||||
NULL
|
||||
};
|
||||
#define MODE_TREE_HELP_DEFAULT_WIDTH 39
|
||||
@@ -928,6 +931,8 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
||||
}
|
||||
|
||||
done:
|
||||
if (mtd->help)
|
||||
mode_tree_draw_help(mtd, &ctx);
|
||||
screen_write_cursormove(&ctx, 0, mtd->current - mtd->offset, 0);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
@@ -1175,12 +1180,28 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
|
||||
}
|
||||
|
||||
static void
|
||||
mode_tree_display_help(__unused struct mode_tree_data *mtd, struct client *c)
|
||||
mode_tree_draw_help_line(struct screen_write_ctx *ctx,
|
||||
const struct grid_cell *gc, const char *line, const char *item, u_int x,
|
||||
u_int y, u_int w)
|
||||
{
|
||||
struct session *s = c->session;
|
||||
u_int px, py, w, h = 0;
|
||||
const char **line, **lines = NULL, *item = "item";
|
||||
char *new_line;
|
||||
char *expanded;
|
||||
|
||||
expanded = cmd_template_replace(line, item, 1);
|
||||
screen_write_cursormove(ctx, x, y, 0);
|
||||
screen_write_clearcharacter(ctx, w, gc->bg);
|
||||
screen_write_cursormove(ctx, x, y, 0);
|
||||
format_draw(ctx, gc, w, expanded, NULL, 0);
|
||||
free(expanded);
|
||||
}
|
||||
|
||||
static void
|
||||
mode_tree_draw_help(struct mode_tree_data *mtd, struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = &mtd->screen;
|
||||
struct grid_cell gc;
|
||||
const char **line, **lines = NULL, *item = "item";
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
u_int x, y, w, h = 0, box_w, box_h;
|
||||
|
||||
if (mtd->helpcb == NULL)
|
||||
w = MODE_TREE_HELP_DEFAULT_WIDTH;
|
||||
@@ -1196,33 +1217,32 @@ mode_tree_display_help(__unused struct mode_tree_data *mtd, struct client *c)
|
||||
for (line = mode_tree_help_end; *line != NULL; line++)
|
||||
h++;
|
||||
|
||||
if (c->tty.sx < w || c->tty.sy < h)
|
||||
box_w = w + 2;
|
||||
box_h = h + 2;
|
||||
if (sx < box_w || sy < box_h)
|
||||
return;
|
||||
px = (c->tty.sx - w) / 2;
|
||||
py = (c->tty.sy - h) / 2;
|
||||
x = (sx - box_w) / 2;
|
||||
y = (sy - box_h) / 2;
|
||||
|
||||
if (popup_display(POPUP_CLOSEANYKEY|POPUP_NOJOB, BOX_LINES_DEFAULT,
|
||||
NULL, px, py, w, h, NULL, NULL, 0, NULL, NULL, NULL, c, s, NULL,
|
||||
NULL, NULL, NULL) != 0)
|
||||
return;
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
screen_write_cursormove(ctx, x, y, 0);
|
||||
screen_write_box(ctx, box_w, box_h, BOX_LINES_DEFAULT, &gc, NULL);
|
||||
|
||||
popup_write(c, "\033[H\033[?25l\033[?7l\033)0", 17);
|
||||
for (line = mode_tree_help_start; *line != NULL; line++) {
|
||||
new_line = cmd_template_replace(*line, item, 1);
|
||||
popup_write(c, new_line, strlen(new_line));
|
||||
free(new_line);
|
||||
}
|
||||
for (line = lines; line != NULL && *line != NULL; line++) {
|
||||
new_line = cmd_template_replace(*line, item, 1);
|
||||
popup_write(c, new_line, strlen(new_line));
|
||||
free(new_line);
|
||||
}
|
||||
for (line = mode_tree_help_end; *line != NULL; line++) {
|
||||
new_line = cmd_template_replace(*line, item, 1);
|
||||
popup_write(c, new_line, strlen(new_line));
|
||||
free(new_line);
|
||||
}
|
||||
popup_write(c, "\033[H", 3);
|
||||
y++;
|
||||
x++;
|
||||
for (line = mode_tree_help_start; *line != NULL; line++, y++)
|
||||
mode_tree_draw_help_line(ctx, &gc, *line, item, x, y, w);
|
||||
for (line = lines; line != NULL && *line != NULL; line++, y++)
|
||||
mode_tree_draw_help_line(ctx, &gc, *line, item, x, y, w);
|
||||
for (line = mode_tree_help_end; *line != NULL; line++, y++)
|
||||
mode_tree_draw_help_line(ctx, &gc, *line, item, x, y, w);
|
||||
}
|
||||
|
||||
static void
|
||||
mode_tree_display_help(struct mode_tree_data *mtd)
|
||||
{
|
||||
mtd->help = 1;
|
||||
mode_tree_draw(mtd);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1239,6 +1259,13 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (mtd->help) {
|
||||
mtd->help = 0;
|
||||
mode_tree_draw(mtd);
|
||||
*key = KEYC_NONE;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (KEYC_IS_MOUSE(*key) && m != NULL) {
|
||||
if (cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0) {
|
||||
*key = KEYC_NONE;
|
||||
@@ -1304,7 +1331,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
return (1);
|
||||
case KEYC_F1:
|
||||
case 'h'|KEYC_CTRL:
|
||||
mode_tree_display_help(mtd, c);
|
||||
mode_tree_display_help(mtd);
|
||||
break;
|
||||
case KEYC_UP:
|
||||
case 'k':
|
||||
|
||||
1
popup.c
1
popup.c
@@ -327,6 +327,7 @@ popup_draw_cb(struct client *c, void *data)
|
||||
defaults.bg = pd->palette.bg;
|
||||
style_ctx.defaults = &defaults;
|
||||
style_ctx.palette = &pd->palette;
|
||||
style_ctx.dim = 0;
|
||||
style_ctx.hyperlinks = s.hyperlinks;
|
||||
|
||||
if (pd->md != NULL) {
|
||||
|
||||
20
regress/command-alias.sh
Normal file
20
regress/command-alias.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
# command-alias expansion
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
$TMUX new-session -d -sfoo || exit 1
|
||||
$TMUX split-window -d -tfoo:0.0 || exit 1
|
||||
$TMUX set -s command-alias[100] zoom='resize-pane -Z' || exit 1
|
||||
$TMUX zoom -tfoo:0.0 || exit 1
|
||||
[ "$($TMUX display-message -p -tfoo:0.0 '#{window_zoomed_flag}')" = 1 ] || exit 1
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
exit 0
|
||||
@@ -67,6 +67,7 @@ $TMUX set @true 1 || exit 1
|
||||
$TMUX set @false 0 || exit 1
|
||||
$TMUX set @warm Summer || exit 1
|
||||
$TMUX set @cold Winter || exit 1
|
||||
$TMUX set @v 'foo:bar' || exit 1
|
||||
|
||||
# Plain string without substitutions et al
|
||||
test_format "abc xyz" "abc xyz"
|
||||
@@ -74,6 +75,8 @@ test_format "abc xyz" "abc xyz"
|
||||
# Test basic escapes for "#", "{", "#{" "}", "#}", ","
|
||||
test_format "##" "#"
|
||||
test_format "#," ","
|
||||
test_format "#{s/#:/_/:@v}" "foo_bar"
|
||||
test_format "#{s/o/#:/:@v}" "f:::bar"
|
||||
test_format "{" "{"
|
||||
test_format "##{" "#{"
|
||||
test_format "#}" "}"
|
||||
|
||||
@@ -252,7 +252,8 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
|
||||
} else {
|
||||
ttyctx->redraw_cb = screen_write_redraw_cb;
|
||||
if (ctx->wp != NULL) {
|
||||
tty_default_colours(&ttyctx->defaults, ctx->wp);
|
||||
tty_default_colours(&ttyctx->defaults, ctx->wp,
|
||||
&ttyctx->style_ctx.dim);
|
||||
ttyctx->style_ctx.palette = &ctx->wp->palette;
|
||||
ttyctx->set_client_cb = screen_write_set_client_cb;
|
||||
ttyctx->arg = ctx->wp;
|
||||
|
||||
16
style.c
16
style.c
@@ -32,6 +32,7 @@
|
||||
static struct style style_default = {
|
||||
{ { { ' ' }, 0, 1, 1 }, 0, 0, 8, 8, 0, 0 },
|
||||
0,
|
||||
0,
|
||||
|
||||
8,
|
||||
STYLE_ALIGN_DEFAULT,
|
||||
@@ -201,6 +202,13 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
|
||||
if ((value = colour_fromstring(tmp + 5)) == -1)
|
||||
goto error;
|
||||
sy->fill = value;
|
||||
} else if (end > 4 && strncasecmp(tmp, "dim=", 4) == 0) {
|
||||
if (tmp[end - 1] == '%')
|
||||
tmp[end - 1] = '\0';
|
||||
n = strtonum(tmp + 4, 0, 100, &errstr);
|
||||
if (errstr != NULL)
|
||||
goto error;
|
||||
sy->dim = n;
|
||||
} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
|
||||
if ((value = colour_fromstring(tmp + 3)) == -1)
|
||||
goto error;
|
||||
@@ -346,6 +354,11 @@ style_tostring(struct style *sy)
|
||||
colour_tostring(sy->fill));
|
||||
comma = ",";
|
||||
}
|
||||
if (sy->dim != 0) {
|
||||
off += xsnprintf(s + off, sizeof s - off, "%sdim=%d%%", comma,
|
||||
sy->dim);
|
||||
comma = ",";
|
||||
}
|
||||
if (gc->fg != 8) {
|
||||
off += xsnprintf(s + off, sizeof s - off, "%sfg=%s", comma,
|
||||
colour_tostring(gc->fg));
|
||||
@@ -386,7 +399,7 @@ style_tostring(struct style *sy)
|
||||
}
|
||||
|
||||
/* Apply a style on top of the given style. */
|
||||
void
|
||||
struct style *
|
||||
style_add(struct grid_cell *gc, struct options *oo, const char *name,
|
||||
struct format_tree *ft)
|
||||
{
|
||||
@@ -409,6 +422,7 @@ style_add(struct grid_cell *gc, struct options *oo, const char *name,
|
||||
|
||||
if (ft0 != NULL)
|
||||
format_free(ft0);
|
||||
return (sy);
|
||||
}
|
||||
|
||||
/* Apply a style on top of the default style. */
|
||||
|
||||
4
tmux.1
4
tmux.1
@@ -6776,6 +6776,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "keypad_flag" Ta "" Ta "Pane keypad flag"
|
||||
.It Li "last_window_index" Ta "" Ta "Index of last window in session"
|
||||
.It Li "line" Ta "" Ta "Line number in the list"
|
||||
.It Li "loop_index" Ta "" Ta "Index of item in the W:, P:, S:, or L: loop"
|
||||
.It Li "loop_last_flag" Ta "" Ta "1 if last window, pane, session, client in the W:, P:, S:, or L: loop"
|
||||
.It Li "mouse_all_flag" Ta "" Ta "Pane mouse all flag"
|
||||
.It Li "mouse_any_flag" Ta "" Ta "Pane mouse any flag"
|
||||
@@ -7013,6 +7014,9 @@ is the terminal alternate character set.
|
||||
Align text to the left, centre or right of the available space if appropriate.
|
||||
.It Ic fill=colour
|
||||
Fill the available space with a background colour if appropriate.
|
||||
.It Ic dim=percentage
|
||||
Dim foreground and background colours by
|
||||
.Ar percentage .
|
||||
.It Ic width=N
|
||||
Set the width of the styled area.
|
||||
.Ar N
|
||||
|
||||
9
tmux.h
9
tmux.h
@@ -960,6 +960,7 @@ enum style_default_type {
|
||||
struct style {
|
||||
struct grid_cell gc;
|
||||
int ignore;
|
||||
int dim;
|
||||
|
||||
int fill;
|
||||
enum style_align align;
|
||||
@@ -1307,6 +1308,8 @@ struct window_pane {
|
||||
|
||||
struct grid_cell cached_gc;
|
||||
struct grid_cell cached_active_gc;
|
||||
u_int cached_dim;
|
||||
u_int cached_active_dim;
|
||||
struct colour_palette palette;
|
||||
enum client_theme last_theme;
|
||||
struct style_line_entry border_status_line;
|
||||
@@ -1648,6 +1651,7 @@ LIST_HEAD(tty_terms, tty_term);
|
||||
struct tty_style_ctx {
|
||||
const struct grid_cell *defaults;
|
||||
struct colour_palette *palette;
|
||||
u_int dim;
|
||||
struct hyperlinks *hyperlinks;
|
||||
};
|
||||
|
||||
@@ -2751,7 +2755,7 @@ void tty_cmd_sixelimage(struct tty *, const struct tty_ctx *);
|
||||
void tty_draw_images(struct client *, struct window_pane *, struct screen *);
|
||||
#endif
|
||||
void tty_cmd_syncstart(struct tty *, const struct tty_ctx *);
|
||||
void tty_default_colours(struct grid_cell *, struct window_pane *);
|
||||
void tty_default_colours(struct grid_cell *, struct window_pane *, u_int *);
|
||||
|
||||
/* tty-term.c */
|
||||
extern struct tty_terms tty_terms;
|
||||
@@ -3188,6 +3192,7 @@ int colour_find_rgb(u_char, u_char, u_char);
|
||||
int colour_join_rgb(u_char, u_char, u_char);
|
||||
void colour_split_rgb(int, u_char *, u_char *, u_char *);
|
||||
int colour_force_rgb(int);
|
||||
int colour_dim(int, u_int);
|
||||
const char *colour_tostring(int);
|
||||
enum client_theme colour_totheme(int);
|
||||
int colour_fromstring(const char *);
|
||||
@@ -3856,7 +3861,7 @@ int popup_modify(struct client *, const char *, const char *,
|
||||
int style_parse(struct style *,const struct grid_cell *,
|
||||
const char *);
|
||||
const char *style_tostring(struct style *);
|
||||
void style_add(struct grid_cell *, struct options *,
|
||||
struct style *style_add(struct grid_cell *, struct options *,
|
||||
const char *, struct format_tree *);
|
||||
void style_apply(struct grid_cell *, struct options *,
|
||||
const char *, struct format_tree *);
|
||||
|
||||
98
tty-draw.c
98
tty-draw.c
@@ -78,7 +78,7 @@ tty_draw_line_clear(struct tty *tty, u_int px, u_int py, u_int nx,
|
||||
}
|
||||
}
|
||||
|
||||
/* Couldn't use an escape sequence, use spaces. */
|
||||
/* Couldn't use an escape sequence, use spaces. */
|
||||
if (px != 0 || !wrapped)
|
||||
tty_cursor(tty, px, py);
|
||||
if (nx == 1)
|
||||
@@ -89,6 +89,30 @@ tty_draw_line_clear(struct tty *tty, u_int px, u_int py, u_int nx,
|
||||
tty_repeat_space(tty, nx);
|
||||
}
|
||||
|
||||
/* Is this cell empty? */
|
||||
static u_int
|
||||
tty_draw_line_get_empty(const struct grid_cell *gc,
|
||||
const struct grid_cell *last, u_int nx)
|
||||
{
|
||||
u_int empty = 0;
|
||||
|
||||
if (gc->data.width > nx)
|
||||
empty = nx;
|
||||
else if (gc->flags & GRID_FLAG_PADDING)
|
||||
empty = 1;
|
||||
else if (gc->flags & GRID_FLAG_SELECTED)
|
||||
empty = 0;
|
||||
else if (gc->bg == last->bg && gc->attr == 0 && gc->link == 0) {
|
||||
if (gc->flags & GRID_FLAG_CLEARED)
|
||||
empty = 1;
|
||||
else if (gc->flags & GRID_FLAG_TAB)
|
||||
empty = gc->data.width;
|
||||
else if (gc->data.size == 1 && *gc->data.data == ' ')
|
||||
empty = 1;
|
||||
}
|
||||
return (empty);
|
||||
}
|
||||
|
||||
/* Draw a line from screen to tty. */
|
||||
void
|
||||
tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
@@ -105,13 +129,14 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
size_t len;
|
||||
enum tty_draw_line_state current_state, next_state;
|
||||
struct tty_style_ctx default_style_ctx = { 0 };
|
||||
|
||||
const struct grid_cell *defaults;
|
||||
|
||||
if (style_ctx == NULL) {
|
||||
default_style_ctx.defaults = &grid_default_cell;
|
||||
default_style_ctx.hyperlinks = s->hyperlinks;
|
||||
style_ctx = &default_style_ctx;
|
||||
}
|
||||
defaults = style_ctx->defaults;
|
||||
|
||||
/*
|
||||
* py is the line in the screen to draw. px is the start x and nx is
|
||||
@@ -138,8 +163,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
else
|
||||
ex = screen_size_x(s);
|
||||
log_debug("%s: drawing %u-%u,%u (end %u) at %u,%u; defaults: fg=%d, "
|
||||
"bg=%d", __func__, px, px + nx, py, ex, atx, aty,
|
||||
style_ctx->defaults->fg, style_ctx->defaults->bg);
|
||||
"bg=%d", __func__, px, px + nx, py, ex, atx, aty, defaults->fg,
|
||||
defaults->bg);
|
||||
|
||||
/* Turn off cursor while redrawing and reset region and margins. */
|
||||
flags = (tty->flags & TTY_NOCURSOR);
|
||||
@@ -150,7 +175,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
|
||||
/* Start with the default cell as the last cell. */
|
||||
memcpy(&last, &grid_default_cell, sizeof last);
|
||||
last.bg = style_ctx->defaults->bg;
|
||||
last.bg = defaults->bg;
|
||||
tty_default_attributes(tty, 8, style_ctx);
|
||||
|
||||
/*
|
||||
@@ -172,7 +197,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
bg = style_ctx->defaults->bg;
|
||||
bg = defaults->bg;
|
||||
else {
|
||||
bg = gc.bg;
|
||||
if (gc.flags & GRID_FLAG_SELECTED) {
|
||||
@@ -183,7 +208,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
}
|
||||
tty_attributes(tty, &last, style_ctx);
|
||||
log_debug("%s: clearing %u padding cells", __func__, cx);
|
||||
tty_draw_line_clear(tty, atx, aty, cx, style_ctx->defaults, bg, 0);
|
||||
tty_draw_line_clear(tty, atx, aty, cx, defaults, bg, 0);
|
||||
if (cx == ex)
|
||||
goto out;
|
||||
atx += cx;
|
||||
@@ -218,43 +243,31 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
if (i > nx)
|
||||
fatalx("position %u > width %u", i, nx);
|
||||
|
||||
/* Get the current cell. */
|
||||
grid_view_get_cell(gd, px + i, py, &gc);
|
||||
|
||||
/* Update for codeset if needed. */
|
||||
gcp = tty_check_codeset(tty, &gc);
|
||||
|
||||
/* And for selection. */
|
||||
if (gcp->flags & GRID_FLAG_SELECTED) {
|
||||
memcpy(&ngc, gcp, sizeof ngc);
|
||||
if (screen_select_cell(s, &ngc, gcp))
|
||||
gcp = &ngc;
|
||||
}
|
||||
|
||||
/* Work out the the empty width. */
|
||||
empty = 0;
|
||||
if (px >= ex || i >= ex - px) {
|
||||
/* Outside the area being drawn. */
|
||||
empty = 1;
|
||||
} else if (gcp->data.width > nx - i) {
|
||||
/* Wide character that has been truncated. */
|
||||
empty = nx - i;
|
||||
} else if (gcp->flags & GRID_FLAG_PADDING) {
|
||||
/* Orphan padding cell. */
|
||||
empty = 1;
|
||||
} else if (gcp->bg == last.bg && gcp->attr == 0 &&
|
||||
gcp->link == 0) {
|
||||
/*
|
||||
* No attributes - empty if cleared, tab or
|
||||
* space.
|
||||
*/
|
||||
if (gcp->flags & GRID_FLAG_CLEARED)
|
||||
empty = 1;
|
||||
else if (gcp->flags & GRID_FLAG_TAB)
|
||||
empty = gcp->data.width;
|
||||
else if (gcp->data.size == 1 &&
|
||||
*gcp->data.data == ' ')
|
||||
empty = 1;
|
||||
gcp = &grid_default_cell;
|
||||
} else {
|
||||
/* Get the current cell. */
|
||||
grid_view_get_cell(gd, px + i, py, &gc);
|
||||
|
||||
/* Work out empty cells. */
|
||||
empty = tty_draw_line_get_empty(&gc, &last,
|
||||
nx - i);
|
||||
if (empty != 0)
|
||||
gcp = &gc;
|
||||
else {
|
||||
/* Update for codeset if needed. */
|
||||
gcp = tty_check_codeset(tty, &gc);
|
||||
|
||||
/* And for selection. */
|
||||
if (gcp->flags & GRID_FLAG_SELECTED) {
|
||||
memcpy(&ngc, gcp, sizeof ngc);
|
||||
if (screen_select_cell(s, &ngc,
|
||||
gcp))
|
||||
gcp = &ngc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Work out the next state. */
|
||||
@@ -284,8 +297,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
if (current_state == TTY_DRAW_LINE_EMPTY) {
|
||||
tty_attributes(tty, &last, style_ctx);
|
||||
tty_draw_line_clear(tty, atx + last_i, aty,
|
||||
i - last_i, style_ctx->defaults, last.bg,
|
||||
wrapped);
|
||||
i - last_i, defaults, last.bg, wrapped);
|
||||
wrapped = 0;
|
||||
} else if (next_state != TTY_DRAW_LINE_SAME &&
|
||||
len != 0) {
|
||||
|
||||
65
tty.c
65
tty.c
@@ -85,7 +85,7 @@ static void tty_write_one(void (*)(struct tty *, const struct tty_ctx *),
|
||||
#define TTY_REQUEST_LIMIT 30
|
||||
|
||||
static struct tty_style_ctx tty_default_style_ctx = {
|
||||
&grid_default_cell, NULL, NULL
|
||||
&grid_default_cell, NULL, 0, NULL
|
||||
};
|
||||
|
||||
void
|
||||
@@ -2591,16 +2591,39 @@ tty_hyperlink(struct tty *tty, const struct grid_cell *gc,
|
||||
tty_putcode_ss(tty, TTYC_HLS, id, uri);
|
||||
}
|
||||
|
||||
static int
|
||||
tty_dim_default_colour(struct tty *tty, int c, int foreground)
|
||||
{
|
||||
enum client_theme theme;
|
||||
|
||||
if (!COLOUR_DEFAULT(c))
|
||||
return (c);
|
||||
|
||||
if (foreground && tty->fg != -1)
|
||||
return (tty->fg);
|
||||
if (!foreground && tty->bg != -1)
|
||||
return (tty->bg);
|
||||
|
||||
theme = tty->client->theme;
|
||||
if (theme == THEME_DARK)
|
||||
return (foreground ? 7 : 0);
|
||||
if (theme == THEME_LIGHT)
|
||||
return (foreground ? 0 : 7);
|
||||
return (c);
|
||||
}
|
||||
|
||||
void
|
||||
tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
const struct tty_style_ctx *style_ctx)
|
||||
{
|
||||
struct grid_cell *tc = &tty->cell, gc2;
|
||||
struct colour_palette *palette;
|
||||
int changed;
|
||||
|
||||
/* Use default style if not given. */
|
||||
if (style_ctx == NULL)
|
||||
style_ctx = &tty_default_style_ctx;
|
||||
palette = style_ctx->palette;
|
||||
|
||||
/* Copy cell and update default colours. */
|
||||
memcpy(&gc2, gc, sizeof gc2);
|
||||
@@ -2609,6 +2632,24 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
gc2.fg = style_ctx->defaults->fg;
|
||||
if (gc2.bg == 8)
|
||||
gc2.bg = style_ctx->defaults->bg;
|
||||
if (palette != NULL) {
|
||||
changed = colour_palette_get(palette, gc2.fg);
|
||||
if (changed != -1)
|
||||
gc2.fg = changed;
|
||||
changed = colour_palette_get(palette, gc2.bg);
|
||||
if (changed != -1)
|
||||
gc2.bg = changed;
|
||||
}
|
||||
}
|
||||
if (style_ctx->dim != 0) {
|
||||
gc2.fg = tty_dim_default_colour(tty, gc2.fg, 1);
|
||||
gc2.bg = tty_dim_default_colour(tty, gc2.bg, 0);
|
||||
changed = colour_dim(gc2.fg, style_ctx->dim);
|
||||
if (changed != -1)
|
||||
gc2.fg = changed;
|
||||
changed = colour_dim(gc2.bg, style_ctx->dim);
|
||||
if (changed != -1)
|
||||
gc2.bg = changed;
|
||||
}
|
||||
|
||||
/* Ignore cell if it is the same as the last one. */
|
||||
@@ -2635,9 +2676,9 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
}
|
||||
|
||||
/* Fix up the colours if necessary. */
|
||||
tty_check_fg(tty, style_ctx->palette, &gc2);
|
||||
tty_check_bg(tty, style_ctx->palette, &gc2);
|
||||
tty_check_us(tty, style_ctx->palette, &gc2);
|
||||
tty_check_fg(tty, palette, &gc2);
|
||||
tty_check_bg(tty, palette, &gc2);
|
||||
tty_check_us(tty, palette, &gc2);
|
||||
|
||||
/*
|
||||
* If any bits are being cleared or the underline colour is now default,
|
||||
@@ -3049,6 +3090,7 @@ tty_style_changed(struct window_pane *wp)
|
||||
{
|
||||
struct options *oo = wp->options;
|
||||
struct format_tree *ft;
|
||||
struct style *sy;
|
||||
|
||||
log_debug("%%%u: style changed", wp->id);
|
||||
wp->flags &= ~PANE_STYLECHANGED;
|
||||
@@ -3057,16 +3099,18 @@ tty_style_changed(struct window_pane *wp)
|
||||
format_defaults(ft, NULL, NULL, NULL, wp);
|
||||
|
||||
tty_window_default_style(&wp->cached_active_gc, wp);
|
||||
style_add(&wp->cached_active_gc, oo, "window-active-style", ft);
|
||||
sy = style_add(&wp->cached_active_gc, oo, "window-active-style", ft);
|
||||
wp->cached_active_dim = sy->dim;
|
||||
|
||||
tty_window_default_style(&wp->cached_gc, wp);
|
||||
style_add(&wp->cached_gc, oo, "window-style", ft);
|
||||
sy = style_add(&wp->cached_gc, oo, "window-style", ft);
|
||||
wp->cached_dim = sy->dim;
|
||||
|
||||
format_free(ft);
|
||||
}
|
||||
|
||||
void
|
||||
tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
|
||||
tty_default_colours(struct grid_cell *gc, struct window_pane *wp, u_int *dim)
|
||||
{
|
||||
if (wp->flags & PANE_STYLECHANGED)
|
||||
tty_style_changed (wp);
|
||||
@@ -3080,6 +3124,13 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
|
||||
gc->bg = wp->cached_active_gc.bg;
|
||||
else
|
||||
gc->bg = wp->cached_gc.bg;
|
||||
|
||||
if (dim != NULL) {
|
||||
if (wp == wp->window->active)
|
||||
*dim = wp->cached_active_dim;
|
||||
else
|
||||
*dim = wp->cached_dim;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -330,13 +330,13 @@ window_buffer_sort(struct sort_criteria *sort_crit)
|
||||
}
|
||||
|
||||
static const char* window_buffer_help_lines[] = {
|
||||
"\r\033[1m Enter \033[0m\016x\017 \033[0mPaste selected %1\n",
|
||||
"\r\033[1m p \033[0m\016x\017 \033[0mPaste selected %1\n",
|
||||
"\r\033[1m P \033[0m\016x\017 \033[0mPaste tagged %1s\n",
|
||||
"\r\033[1m d \033[0m\016x\017 \033[0mDelete selected %1\n",
|
||||
"\r\033[1m D \033[0m\016x\017 \033[0mDelete tagged %1s\n",
|
||||
"\r\033[1m e \033[0m\016x\017 \033[0mOpen %1 in editor\n",
|
||||
"\r\033[1m f \033[0m\016x\017 \033[0mEnter a filter\n",
|
||||
"#[bold] Enter #[default]#[acs]x#[default] Paste selected %1",
|
||||
"#[bold] p #[default]#[acs]x#[default] Paste selected %1",
|
||||
"#[bold] P #[default]#[acs]x#[default] Paste tagged %1s",
|
||||
"#[bold] d #[default]#[acs]x#[default] Delete selected %1",
|
||||
"#[bold] D #[default]#[acs]x#[default] Delete tagged %1s",
|
||||
"#[bold] e #[default]#[acs]x#[default] Open %1 in editor",
|
||||
"#[bold] f #[default]#[acs]x#[default] Enter a filter",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -369,15 +369,15 @@ window_client_sort(struct sort_criteria *sort_crit)
|
||||
}
|
||||
|
||||
static const char* window_client_help_lines[] = {
|
||||
"\r\033[1m i \033[0m\016x\017 \033[0mToggle info view\n",
|
||||
"\r\033[1m Enter \033[0m\016x\017 \033[0mChoose selected %1\n",
|
||||
"\r\033[1m d \033[0m\016x\017 \033[0mDetach selected %1\n",
|
||||
"\r\033[1m D \033[0m\016x\017 \033[0mDetach tagged %1s\n",
|
||||
"\r\033[1m x \033[0m\016x\017 \033[0mDetach selected %1\n",
|
||||
"\r\033[1m X \033[0m\016x\017 \033[0mDetach tagged %1s\n",
|
||||
"\r\033[1m z \033[0m\016x\017 \033[0mSuspend selected %1\n",
|
||||
"\r\033[1m Z \033[0m\016x\017 \033[0mSuspend tagged %1s\n",
|
||||
"\r\033[1m f \033[0m\016x\017 \033[0mEnter a filter\n",
|
||||
"#[bold] i #[default]#[acs]x#[default] Toggle info view",
|
||||
"#[bold] Enter #[default]#[acs]x#[default] Choose selected %1",
|
||||
"#[bold] d #[default]#[acs]x#[default] Detach selected %1",
|
||||
"#[bold] D #[default]#[acs]x#[default] Detach tagged %1s",
|
||||
"#[bold] x #[default]#[acs]x#[default] Detach selected %1",
|
||||
"#[bold] X #[default]#[acs]x#[default] Detach tagged %1s",
|
||||
"#[bold] z #[default]#[acs]x#[default] Suspend selected %1",
|
||||
"#[bold] Z #[default]#[acs]x#[default] Suspend tagged %1s",
|
||||
"#[bold] f #[default]#[acs]x#[default] Enter a filter",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -869,15 +869,15 @@ window_customize_height(__unused void *modedata, __unused u_int height)
|
||||
}
|
||||
|
||||
static const char* window_customize_help_lines[] = {
|
||||
"\r\033[1m Enter, s \033[0m\016x\017 \033[0mSet %1 value\n",
|
||||
"\r\033[1m S \033[0m\016x\017 \033[0mSet global %1 value\n",
|
||||
"\r\033[1m w \033[0m\016x\017 \033[0mSet window %1 value\n",
|
||||
"\r\033[1m d \033[0m\016x\017 \033[0mSet to default value\n",
|
||||
"\r\033[1m D \033[0m\016x\017 \033[0mSet tagged %1s to default value\n",
|
||||
"\r\033[1m u \033[0m\016x\017 \033[0mUnset an %1\n",
|
||||
"\r\033[1m U \033[0m\016x\017 \033[0mUnset tagged %1s\n",
|
||||
"\r\033[1m f \033[0m\016x\017 \033[0mEnter a filter\n",
|
||||
"\r\033[1m v \033[0m\016x\017 \033[0mToggle information\n",
|
||||
"#[bold] Enter, s #[default]#[acs]x#[default] Set %1 value",
|
||||
"#[bold] S #[default]#[acs]x#[default] Set global %1 value",
|
||||
"#[bold] w #[default]#[acs]x#[default] Set window %1 value",
|
||||
"#[bold] d #[default]#[acs]x#[default] Set to default value",
|
||||
"#[bold] D #[default]#[acs]x#[default] Set tagged %1s to default value",
|
||||
"#[bold] u #[default]#[acs]x#[default] Unset an %1",
|
||||
"#[bold] U #[default]#[acs]x#[default] Unset tagged %1s",
|
||||
"#[bold] f #[default]#[acs]x#[default] Enter a filter",
|
||||
"#[bold] v #[default]#[acs]x#[default] Toggle information",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -889,18 +889,18 @@ window_tree_sort(struct sort_criteria *sort_crit)
|
||||
}
|
||||
|
||||
static const char* window_tree_help_lines[] = {
|
||||
"\r\033[1m Enter \033[0m\016x\017 \033[0mChoose selected item\n",
|
||||
"\r\033[1m S-Up \033[0m\016x\017 \033[0mSwap current and previous window\n",
|
||||
"\r\033[1m S-Down \033[0m\016x\017 \033[0mSwap current and next window\n",
|
||||
"\r\033[1m x \033[0m\016x\017 \033[0mKill selected item\n",
|
||||
"\r\033[1m X \033[0m\016x\017 \033[0mKill tagged items\n",
|
||||
"\r\033[1m < \033[0m\016x\017 \033[0mScroll previews left\n",
|
||||
"\r\033[1m > \033[0m\016x\017 \033[0mScroll previews right\n",
|
||||
"\r\033[1m m \033[0m\016x\017 \033[0mSet the marked pane\n",
|
||||
"\r\033[1m M \033[0m\016x\017 \033[0mClear the marked pane\n",
|
||||
"\r\033[1m : \033[0m\016x\017 \033[0mRun a command for each tagged item\n",
|
||||
"\r\033[1m f \033[0m\016x\017 \033[0mEnter a format\n",
|
||||
"\r\033[1m H \033[0m\016x\017 \033[0mJump to the starting pane\n",
|
||||
"#[bold] Enter #[default]#[acs]x#[default] Choose selected item",
|
||||
"#[bold] S-Up #[default]#[acs]x#[default] Swap current and previous window",
|
||||
"#[bold] S-Down #[default]#[acs]x#[default] Swap current and next window",
|
||||
"#[bold] x #[default]#[acs]x#[default] Kill selected item",
|
||||
"#[bold] X #[default]#[acs]x#[default] Kill tagged items",
|
||||
"#[bold] < #[default]#[acs]x#[default] Scroll previews left",
|
||||
"#[bold] > #[default]#[acs]x#[default] Scroll previews right",
|
||||
"#[bold] m #[default]#[acs]x#[default] Set the marked pane",
|
||||
"#[bold] M #[default]#[acs]x#[default] Clear the marked pane",
|
||||
"#[bold] : #[default]#[acs]x#[default] Run a command for each tagged item",
|
||||
"#[bold] f #[default]#[acs]x#[default] Enter a format",
|
||||
"#[bold] H #[default]#[acs]x#[default] Jump to the starting pane",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
4
window.c
4
window.c
@@ -599,6 +599,8 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
|
||||
gc2 = &wp->cached_active_gc;
|
||||
if (!grid_cells_look_equal(gc1, gc2))
|
||||
wp->flags |= PANE_REDRAW;
|
||||
else if (wp->cached_dim != wp->cached_active_dim)
|
||||
wp->flags |= PANE_REDRAW;
|
||||
else {
|
||||
c1 = window_pane_get_palette(wp, gc1->fg);
|
||||
c2 = window_pane_get_palette(wp, gc2->fg);
|
||||
@@ -1979,7 +1981,7 @@ window_pane_get_bg(struct window_pane *wp)
|
||||
|
||||
c = window_pane_get_bg_control_client(wp);
|
||||
if (c == -1) {
|
||||
tty_default_colours(&defaults, wp);
|
||||
tty_default_colours(&defaults, wp, NULL);
|
||||
if (COLOUR_DEFAULT(defaults.bg))
|
||||
c = window_get_bg_client(wp);
|
||||
else
|
||||
|
||||
12
xmalloc.c
12
xmalloc.c
@@ -105,6 +105,18 @@ xstrndup(const char *str, size_t maxlen)
|
||||
return cp;
|
||||
}
|
||||
|
||||
char *
|
||||
xmemdup(const void *ptr, size_t len)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
cp = xmalloc(len + 1);
|
||||
if (len != 0)
|
||||
memcpy(cp, ptr, len);
|
||||
cp[len] = '\0';
|
||||
return cp;
|
||||
}
|
||||
|
||||
int
|
||||
xasprintf(char **ret, const char *fmt, ...)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ void *xreallocarray(void *, size_t, size_t);
|
||||
void *xrecallocarray(void *, size_t, size_t, size_t);
|
||||
char *xstrdup(const char *);
|
||||
char *xstrndup(const char *, size_t);
|
||||
char *xmemdup(const void *, size_t);
|
||||
int xasprintf(char **, const char *, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)))
|
||||
__attribute__((__nonnull__ (2)));
|
||||
|
||||
Reference in New Issue
Block a user