=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/status.c,v retrieving revision 1.45 retrieving revision 1.46 diff -c -r1.45 -r1.46 *** src/usr.bin/tmux/status.c 2009/11/19 10:22:07 1.45 --- src/usr.bin/tmux/status.c 2009/11/19 11:38:54 1.46 *************** *** 1,4 **** ! /* $OpenBSD: status.c,v 1.45 2009/11/19 10:22:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: status.c,v 1.46 2009/11/19 11:38:54 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott *************** *** 33,38 **** --- 33,40 ---- void status_job_callback(struct job *); size_t status_width(struct winlink *); 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_prompt_add_history(struct client *); *************** *** 318,456 **** return (1); } ! char * ! status_replace(struct client *c, const char *fmt, time_t t, int run_jobs) { struct session *s = c->session; struct winlink *wl = s->curw; static char out[BUFSIZ]; ! char in[BUFSIZ], tmp[256], ch, *iptr, *optr, *ptr, *endptr; ! char *savedptr; /* freed at end of each loop */ ! size_t len; ! long n; - strftime(in, sizeof in, fmt, localtime(&t)); in[(sizeof in) - 1] = '\0'; iptr = in; optr = out; - savedptr = NULL; while (*iptr != '\0') { if (optr >= out + (sizeof out) - 1) break; ! switch (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; ! 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; ! break; } } *optr = '\0'; return (xstrdup(out)); } char * status_job(struct client *c, char **iptr) { --- 320,452 ---- return (1); } ! /* Replace a single special sequence (prefixed by #). */ ! void ! status_replace1(struct client *c, ! char **iptr, char **optr, char *out, size_t outsize, int jobsflag) { struct session *s = c->session; struct winlink *wl = s->curw; + char ch, tmp[256], *ptr, *endptr, *freeptr; + size_t ptrlen; + long limit; + + 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)); in[(sizeof in) - 1] = '\0'; iptr = in; optr = out; while (*iptr != '\0') { if (optr >= out + (sizeof out) - 1) break; ! ch = *iptr++; ! if (ch != '#') { *optr++ = ch; ! continue; } + status_replace1(c, &iptr, &optr, out, sizeof out, jobsflag); } *optr = '\0'; return (xstrdup(out)); } + /* Figure out job name and get its result, starting it off if necessary. */ char * status_job(struct client *c, char **iptr) { *************** *** 498,503 **** --- 494,500 ---- return (xstrdup(job->data)); } + /* Job has finished: save its result. */ void status_job_callback(struct job *job) { *************** *** 523,534 **** --- 520,533 ---- xfree(buf); } + /* Calculate winlink status line entry width. */ size_t status_width(struct winlink *wl) { return (xsnprintf(NULL, 0, "%d:%s ", wl->idx, wl->window->name)); } + /* Return winlink status line entry and adjust gc as necessary. */ char * status_print(struct session *s, struct winlink *wl, struct grid_cell *gc) { *************** *** 577,582 **** --- 576,582 ---- return (text); } + /* Set a status line message. */ void printflike2 status_message_set(struct client *c, const char *fmt, ...) { *************** *** 621,626 **** --- 621,627 ---- c->flags |= CLIENT_STATUS; } + /* Clear status line message. */ void status_message_clear(struct client *c) { *************** *** 636,641 **** --- 637,643 ---- screen_reinit(&c->status); } + /* Clear status line message after timer expires. */ void status_message_callback(unused int fd, unused short event, void *data) { *************** *** 685,690 **** --- 687,693 ---- return (1); } + /* Enable status line prompt. */ void status_prompt_set(struct client *c, const char *msg, int (*callbackfn)(void *, const char *), void (*freefn)(void *), *************** *** 718,723 **** --- 721,727 ---- c->flags |= CLIENT_STATUS; } + /* Remove status line prompt. */ void status_prompt_clear(struct client *c) { *************** *** 739,744 **** --- 743,749 ---- screen_reinit(&c->status); } + /* Update status line prompt with a new prompt string. */ void status_prompt_update(struct client *c, const char *msg) {