Sync OpenBSD patchset 550:

Tidy up by breaking the # replacement code into a separate function, also add a
few comments.
This commit is contained in:
Tiago Cunha 2009-11-19 22:30:39 +00:00
parent 5fd1cf743e
commit 224ae13ab0

227
status.c
View File

@ -1,4 +1,4 @@
/* $Id: status.c,v 1.130 2009-11-19 22:25:52 tcunha Exp $ */ /* $Id: status.c,v 1.131 2009-11-19 22:30:39 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -33,6 +33,8 @@ char *status_job(struct client *, char **);
void status_job_callback(struct job *); void status_job_callback(struct job *);
size_t status_width(struct winlink *); size_t status_width(struct winlink *);
char *status_print(struct session *, struct winlink *, struct grid_cell *); char *status_print(struct session *, struct winlink *, struct grid_cell *);
void status_replace1(
struct client *, char **, char **, char *, size_t, int);
void status_message_callback(int, short, void *); void status_message_callback(int, short, void *);
void status_prompt_add_history(struct client *); void status_prompt_add_history(struct client *);
@ -318,139 +320,133 @@ out:
return (1); return (1);
} }
char * /* Replace a single special sequence (prefixed by #). */
status_replace(struct client *c, const char *fmt, time_t t, int run_jobs) void
status_replace1(struct client *c,
char **iptr, char **optr, char *out, size_t outsize, int jobsflag)
{ {
struct session *s = c->session; struct session *s = c->session;
struct winlink *wl = s->curw; struct winlink *wl = s->curw;
static char out[BUFSIZ]; char ch, tmp[256], *ptr, *endptr, *freeptr;
char in[BUFSIZ], tmp[256], ch, *iptr, *optr, *ptr, *endptr; size_t ptrlen;
char *savedptr; /* freed at end of each loop */ long limit;
size_t len;
long n; errno = 0;
limit = strtol(*iptr, &endptr, 10);
if ((limit == 0 && errno != EINVAL) ||
(limit == LONG_MIN && errno != ERANGE) ||
(limit == LONG_MAX && errno != ERANGE) ||
limit != 0)
*iptr = endptr;
if (limit <= 0)
limit = LONG_MAX;
freeptr = NULL;
switch (*(*iptr)++) {
case '(':
if (!jobsflag) {
ch = ')';
goto skip_to;
}
if ((ptr = status_job(c, iptr)) == NULL)
return;
freeptr = ptr;
goto do_replace;
case 'H':
if (gethostname(tmp, sizeof tmp) != 0)
fatal("gethostname failed");
ptr = tmp;
goto do_replace;
case 'I':
xsnprintf(tmp, sizeof tmp, "%d", wl->idx);
ptr = tmp;
goto do_replace;
case 'P':
xsnprintf(tmp, sizeof tmp, "%u",
window_pane_index(wl->window, wl->window->active));
ptr = tmp;
goto do_replace;
case 'S':
ptr = s->name;
goto do_replace;
case 'T':
ptr = wl->window->active->base.title;
goto do_replace;
case 'W':
ptr = wl->window->name;
goto do_replace;
case '[':
/*
* Embedded style, handled at display time. Leave present and
* skip input until ].
*/
ch = ']';
goto skip_to;
case '#':
*(*optr++) = '#';
break;
}
return;
do_replace:
ptrlen = strlen(ptr);
if ((size_t) limit < ptrlen)
ptrlen = limit;
if (*optr + ptrlen >= out + outsize - 1)
return;
while (ptrlen > 0 && *ptr != '\0') {
*(*optr)++ = *ptr++;
ptrlen--;
}
if (freeptr != NULL)
xfree(freeptr);
return;
skip_to:
*(*optr)++ = '#';
(*iptr)--; /* include ch */
while (**iptr != ch && **iptr != '\0') {
if (*optr >= out + outsize - 1)
break;
*(*optr)++ = *(*iptr)++;
}
}
/* Replace special sequences in fmt. */
char *
status_replace(struct client *c, const char *fmt, time_t t, int jobsflag)
{
static char out[BUFSIZ];
char in[BUFSIZ], ch, *iptr, *optr;
strftime(in, sizeof in, fmt, localtime(&t)); strftime(in, sizeof in, fmt, localtime(&t));
in[(sizeof in) - 1] = '\0'; in[(sizeof in) - 1] = '\0';
iptr = in; iptr = in;
optr = out; optr = out;
savedptr = NULL;
while (*iptr != '\0') { while (*iptr != '\0') {
if (optr >= out + (sizeof out) - 1) if (optr >= out + (sizeof out) - 1)
break; break;
switch (ch = *iptr++) { ch = *iptr++;
case '#':
errno = 0;
n = strtol(iptr, &endptr, 10);
if ((n == 0 && errno != EINVAL) ||
(n == LONG_MIN && errno != ERANGE) ||
(n == LONG_MAX && errno != ERANGE) ||
n != 0)
iptr = endptr;
if (n <= 0)
n = LONG_MAX;
ptr = NULL; if (ch != '#') {
switch (*iptr++) {
case '(':
if (run_jobs) {
if (ptr == NULL) {
ptr = status_job(c, &iptr);
if (ptr == NULL)
break;
savedptr = ptr;
}
} else {
/* Don't run jobs. Copy to ). */
*optr++ = '#';
iptr--; /* include [ */
while (*iptr != ')' && *iptr != '\0') {
if (optr >=
out + (sizeof out) - 1)
break;
*optr++ = *iptr++;
}
break;
}
/* FALLTHROUGH */
case 'H':
if (ptr == NULL) {
if (gethostname(tmp, sizeof tmp) != 0)
fatal("gethostname failed");
ptr = tmp;
}
/* FALLTHROUGH */
case 'I':
if (ptr == NULL) {
xsnprintf(tmp, sizeof tmp, "%d", wl->idx);
ptr = tmp;
}
/* FALLTHROUGH */
case 'P':
if (ptr == NULL) {
xsnprintf(tmp, sizeof tmp, "%u",
window_pane_index(wl->window,
wl->window->active));
ptr = tmp;
}
/* FALLTHROUGH */
case 'S':
if (ptr == NULL)
ptr = s->name;
/* FALLTHROUGH */
case 'T':
if (ptr == NULL)
ptr = wl->window->active->base.title;
/* FALLTHROUGH */
case 'W':
if (ptr == NULL)
ptr = wl->window->name;
len = strlen(ptr);
if ((size_t) n < len)
len = n;
if (optr + len >= out + (sizeof out) - 1)
break;
while (len > 0 && *ptr != '\0') {
*optr++ = *ptr++;
len--;
}
break;
case '[':
/*
* Embedded style, handled at display time.
* Leave present and skip input until ].
*/
*optr++ = '#';
iptr--; /* include [ */
while (*iptr != ']' && *iptr != '\0') {
if (optr >= out + (sizeof out) - 1)
break;
*optr++ = *iptr++;
}
break;
case '#':
*optr++ = '#';
break;
}
if (savedptr != NULL) {
xfree(savedptr);
savedptr = NULL;
}
break;
default:
*optr++ = ch; *optr++ = ch;
break; continue;
} }
status_replace1(c, &iptr, &optr, out, sizeof out, jobsflag);
} }
*optr = '\0'; *optr = '\0';
return (xstrdup(out)); return (xstrdup(out));
} }
/* Figure out job name and get its result, starting it off if necessary. */
char * char *
status_job(struct client *c, char **iptr) status_job(struct client *c, char **iptr)
{ {
@ -498,6 +494,7 @@ status_job(struct client *c, char **iptr)
return (xstrdup(job->data)); return (xstrdup(job->data));
} }
/* Job has finished: save its result. */
void void
status_job_callback(struct job *job) status_job_callback(struct job *job)
{ {
@ -523,12 +520,14 @@ status_job_callback(struct job *job)
xfree(buf); xfree(buf);
} }
/* Calculate winlink status line entry width. */
size_t size_t
status_width(struct winlink *wl) status_width(struct winlink *wl)
{ {
return (xsnprintf(NULL, 0, "%d:%s ", wl->idx, wl->window->name)); return (xsnprintf(NULL, 0, "%d:%s ", wl->idx, wl->window->name));
} }
/* Return winlink status line entry and adjust gc as necessary. */
char * char *
status_print(struct session *s, struct winlink *wl, struct grid_cell *gc) status_print(struct session *s, struct winlink *wl, struct grid_cell *gc)
{ {
@ -577,6 +576,7 @@ status_print(struct session *s, struct winlink *wl, struct grid_cell *gc)
return (text); return (text);
} }
/* Set a status line message. */
void printflike2 void printflike2
status_message_set(struct client *c, const char *fmt, ...) status_message_set(struct client *c, const char *fmt, ...)
{ {
@ -621,6 +621,7 @@ status_message_set(struct client *c, const char *fmt, ...)
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
} }
/* Clear status line message. */
void void
status_message_clear(struct client *c) status_message_clear(struct client *c)
{ {
@ -636,6 +637,7 @@ status_message_clear(struct client *c)
screen_reinit(&c->status); screen_reinit(&c->status);
} }
/* Clear status line message after timer expires. */
void void
status_message_callback(unused int fd, unused short event, void *data) status_message_callback(unused int fd, unused short event, void *data)
{ {
@ -685,6 +687,7 @@ status_message_redraw(struct client *c)
return (1); return (1);
} }
/* Enable status line prompt. */
void void
status_prompt_set(struct client *c, const char *msg, status_prompt_set(struct client *c, const char *msg,
int (*callbackfn)(void *, const char *), void (*freefn)(void *), int (*callbackfn)(void *, const char *), void (*freefn)(void *),
@ -718,6 +721,7 @@ status_prompt_set(struct client *c, const char *msg,
c->flags |= CLIENT_STATUS; c->flags |= CLIENT_STATUS;
} }
/* Remove status line prompt. */
void void
status_prompt_clear(struct client *c) status_prompt_clear(struct client *c)
{ {
@ -739,6 +743,7 @@ status_prompt_clear(struct client *c)
screen_reinit(&c->status); screen_reinit(&c->status);
} }
/* Update status line prompt with a new prompt string. */
void void
status_prompt_update(struct client *c, const char *msg) status_prompt_update(struct client *c, const char *msg)
{ {