Import tmux, a terminal multiplexor allowing (among other things) a single

terminal to be switched between several different windows and programs
displayed on one terminal be detached from one terminal and moved to another.

ok deraadt pirofti
This commit is contained in:
Nicholas Marriott 2009-06-01 22:58:49 +00:00
commit 35876eaab9
127 changed files with 28294 additions and 0 deletions

48
Makefile Normal file
View File

@ -0,0 +1,48 @@
# $OpenBSD$
.PATH: ${.CURDIR}/..
PROG= tmux
SRCS= arg.c attributes.c buffer-poll.c buffer.c cfg.c client-fn.c \
client-msg.c client.c clock.c cmd-attach-session.c cmd-bind-key.c \
cmd-break-pane.c cmd-choose-session.c cmd-choose-window.c \
cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \
cmd-confirm-before.c cmd-copy-buffer.c cmd-copy-mode.c \
cmd-delete-buffer.c cmd-detach-client.c cmd-down-pane.c \
cmd-find-window.c cmd-generic.c cmd-has-session.c cmd-kill-pane.c \
cmd-kill-server.c cmd-kill-session.c cmd-kill-window.c \
cmd-last-window.c cmd-link-window.c cmd-list-buffers.c \
cmd-list-clients.c cmd-list-commands.c cmd-list-keys.c \
cmd-list-sessions.c cmd-list-windows.c cmd-list.c cmd-load-buffer.c \
cmd-lock-server.c cmd-move-window.c cmd-new-session.c cmd-new-window.c \
cmd-next-layout.c cmd-next-window.c cmd-paste-buffer.c \
cmd-previous-layout.c cmd-previous-window.c cmd-refresh-client.c \
cmd-rename-session.c cmd-rename-window.c cmd-resize-pane.c \
cmd-respawn-window.c cmd-rotate-window.c cmd-save-buffer.c \
cmd-scroll-mode.c cmd-select-layout.c cmd-select-pane.c \
cmd-select-prompt.c cmd-select-window.c cmd-send-keys.c \
cmd-send-prefix.c cmd-server-info.c cmd-set-buffer.c cmd-set-option.c \
cmd-set-password.c cmd-set-window-option.c cmd-show-buffer.c \
cmd-show-options.c cmd-show-window-options.c cmd-source-file.c \
cmd-split-window.c cmd-start-server.c cmd-string.c \
cmd-suspend-client.c cmd-swap-pane.c cmd-swap-window.c \
cmd-switch-client.c cmd-unbind-key.c cmd-unlink-window.c \
cmd-up-pane.c cmd.c colour.c grid-view.c grid.c input-keys.c \
input.c key-bindings.c key-string.c layout-manual.c layout.c log.c \
mode-key.c names.c options-cmd.c options.c paste.c procname.c \
resize.c screen-redraw.c screen-write.c screen.c server-fn.c \
server-msg.c server.c session.c status.c tmux.c tty-keys.c tty-term.c \
tty-write.c tty.c utf8.c util.c window-choose.c window-clock.c \
window-copy.c window-more.c window-scroll.c window.c xmalloc.c
CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
LDADD= -lutil -lncurses
DPADD= ${LIBUTIL}
MAN= tmux.1
.include <bsd.prog.mk>

194
arg.c Normal file
View File

@ -0,0 +1,194 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <fnmatch.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
struct client *arg_lookup_client(const char *);
struct session *arg_lookup_session(const char *);
struct client *
arg_lookup_client(const char *name)
{
struct client *c;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL && strcmp(name, c->tty.path) == 0)
return (c);
}
return (NULL);
}
struct session *
arg_lookup_session(const char *name)
{
struct session *s, *newest = NULL;
struct timeval *tv;
u_int i;
tv = NULL;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i);
if (s == NULL || fnmatch(name, s->name, 0) != 0)
continue;
if (tv == NULL || timercmp(&s->tv, tv, >)) {
newest = s;
tv = &s->tv;
}
}
return (newest);
}
struct client *
arg_parse_client(const char *arg)
{
struct client *c;
char *arg2;
size_t n;
if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) {
arg2 = xstrdup(arg);
/* Trim a trailing : if any from the argument. */
n = strlen(arg2);
if (arg2[n - 1] == ':')
arg2[n - 1] = '\0';
/* Try and look up the client name. */
c = arg_lookup_client(arg2);
xfree(arg2);
return (c);
}
return (NULL);
}
struct session *
arg_parse_session(const char *arg)
{
struct session *s;
struct client *c;
char *arg2;
size_t n;
if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) {
arg2 = xstrdup(arg);
/* Trim a trailing : if any from the argument. */
n = strlen(arg2);
if (arg2[n - 1] == ':')
arg2[n - 1] = '\0';
/* See if the argument matches a session. */
if ((s = arg_lookup_session(arg2)) != NULL) {
xfree(arg2);
return (s);
}
/* If not try a client. */
if ((c = arg_lookup_client(arg2)) != NULL) {
xfree(arg2);
return (c->session);
}
xfree(arg2);
}
return (NULL);
}
int
arg_parse_window(const char *arg, struct session **s, int *idx)
{
char *arg2, *ptr;
const char *errstr;
*idx = -1;
/* Handle no argument or a single :. */
if (arg == NULL || (arg[0] == ':' && arg[1] == '\0')) {
*s = arg_parse_session(NULL);
return (0);
}
/* Find the separator if any. */
arg2 = xstrdup(arg);
ptr = strrchr(arg2, ':');
/*
* If it is first, this means no session name, so use current session
* and try to convert the rest as index.
*/
if (ptr == arg2) {
*idx = strtonum(ptr + 1, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xfree(arg2);
return (1);
}
xfree(arg2);
*s = arg_parse_session(NULL);
return (0);
}
/* If missing, try as an index, else look up immediately. */
if (ptr == NULL) {
*idx = strtonum(arg2, 0, INT_MAX, &errstr);
if (errstr == NULL) {
/* This is good as an index; use current session. */
xfree(arg2);
*s = arg_parse_session(NULL);
return (0);
}
*idx = -1;
goto lookup;
}
/* If last, strip it and look up as a session. */
if (ptr[1] == '\0') {
*ptr = '\0';
goto lookup;
}
/* Present but not first and not last. Break and convert both. */
*ptr = '\0';
*idx = strtonum(ptr + 1, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xfree(arg2);
return (1);
}
lookup:
/* Look up as session. */
*s = arg_parse_session(arg2);
xfree(arg2);
if (*s == NULL)
return (1);
return (0);
}

119
array.h Normal file
View File

@ -0,0 +1,119 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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.
*/
#ifndef ARRAY_H
#define ARRAY_H
#define ARRAY_DECL(n, c) \
struct n { \
c *list; \
u_int num; \
size_t space; \
}
#define ARRAY_ITEM(a, i) ((a)->list[i])
#define ARRAY_ITEMSIZE(a) (sizeof *(a)->list)
#define ARRAY_INITIALSPACE(a) (10 * ARRAY_ITEMSIZE(a))
#define ARRAY_ENSURE(a, n) do { \
if (UINT_MAX - (n) < (a)->num) \
fatalx("number too big"); \
if (SIZE_MAX / ((a)->num + (n)) < ARRAY_ITEMSIZE(a)) \
fatalx("size too big"); \
if ((a)->space == 0) { \
(a)->space = ARRAY_INITIALSPACE(a); \
(a)->list = xrealloc((a)->list, 1, (a)->space); \
} \
while ((a)->space <= ((a)->num + (n)) * ARRAY_ITEMSIZE(a)) { \
(a)->list = xrealloc((a)->list, 2, (a)->space); \
(a)->space *= 2; \
} \
} while (0)
#define ARRAY_EMPTY(a) ((a) == NULL || (a)->num == 0)
#define ARRAY_LENGTH(a) ((a)->num)
#define ARRAY_DATA(a) ((a)->list)
#define ARRAY_FIRST(a) ARRAY_ITEM(a, 0)
#define ARRAY_LAST(a) ARRAY_ITEM(a, (a)->num - 1)
#define ARRAY_INIT(a) do { \
(a)->num = 0; \
(a)->list = NULL; \
(a)->space = 0; \
} while (0)
#define ARRAY_CLEAR(a) do { \
(a)->num = 0; \
} while (0)
#define ARRAY_SET(a, i, s) do { \
(a)->list[i] = s; \
} while (0)
#define ARRAY_ADD(a, s) do { \
ARRAY_ENSURE(a, 1); \
(a)->list[(a)->num] = s; \
(a)->num++; \
} while (0)
#define ARRAY_INSERT(a, i, s) do { \
ARRAY_ENSURE(a, 1); \
if ((i) < (a)->num) { \
memmove((a)->list + (i) + 1, (a)->list + (i), \
ARRAY_ITEMSIZE(a) * ((a)->num - (i))); \
} \
(a)->list[i] = s; \
(a)->num++; \
} while (0)
#define ARRAY_REMOVE(a, i) do { \
if ((i) < (a)->num - 1) { \
memmove((a)->list + (i), (a)->list + (i) + 1, \
ARRAY_ITEMSIZE(a) * ((a)->num - (i) - 1)); \
} \
(a)->num--; \
if ((a)->num == 0) \
ARRAY_FREE(a); \
} while (0)
#define ARRAY_EXPAND(a, n) do { \
ARRAY_ENSURE(a, n); \
(a)->num += n; \
} while (0)
#define ARRAY_TRUNC(a, n) do { \
if ((a)->num > n) \
(a)->num -= n; \
else \
ARRAY_FREE(a); \
} while (0)
#define ARRAY_CONCAT(a, b) do { \
ARRAY_ENSURE(a, (b)->num); \
memcpy((a)->list + (a)->num, (b)->list, (b)->num * ARRAY_ITEMSIZE(a)) \
(a)->num += (b)->num; \
} while (0)
#define ARRAY_FREE(a) do { \
if ((a)->list != NULL) \
xfree((a)->list); \
ARRAY_INIT(a); \
} while (0)
#define ARRAY_FREEALL(a) do { \
ARRAY_FREE(a); \
xfree(a); \
} while (0)
#endif

92
attributes.c Normal file
View File

@ -0,0 +1,92 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
*
* 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 <string.h>
#include "tmux.h"
const char *
attributes_tostring(u_char ch)
{
static char buf[128];
if (ch == 0)
return ("default");
buf[0] = '\0';
if (ch & GRID_ATTR_BRIGHT)
strlcat(buf, "bright,", sizeof (buf));
if (ch & GRID_ATTR_DIM)
strlcat(buf, "dim,", sizeof (buf));
if (ch & GRID_ATTR_UNDERSCORE)
strlcat(buf, "underscore,", sizeof (buf));
if (ch & GRID_ATTR_BLINK)
strlcat(buf, "blink,", sizeof (buf));
if (ch & GRID_ATTR_REVERSE)
strlcat(buf, "reverse,", sizeof (buf));
if (ch & GRID_ATTR_HIDDEN)
strlcat(buf, "hidden,", sizeof (buf));
if (ch & GRID_ATTR_ITALICS)
strlcat(buf, "italics,", sizeof (buf));
*(strrchr(buf, ',')) = '\0';
return (buf);
}
int
attributes_fromstring(const char *str)
{
const char delimiters[] = " ,|";
u_char ch;
size_t end;
if (*str == '\0' || strcspn(str, delimiters) == 0)
return (-1);
if (strchr(delimiters, str[strlen(str) - 1]) != NULL)
return (-1);
if (strcasecmp(str, "default") == 0)
return (0);
ch = 0;
do {
end = strcspn(str, delimiters);
if ((end == 6 && strncasecmp(str, "bright", end) == 0) ||
(end == 4 && strncasecmp(str, "bold", end) == 0))
ch |= GRID_ATTR_BRIGHT;
else if (end == 3 && strncasecmp(str, "dim", end) == 0)
ch |= GRID_ATTR_DIM;
else if (end == 10 && strncasecmp(str, "underscore", end) == 0)
ch |= GRID_ATTR_UNDERSCORE;
else if (end == 5 && strncasecmp(str, "blink", end) == 0)
ch |= GRID_ATTR_BLINK;
else if (end == 7 && strncasecmp(str, "reverse", end) == 0)
ch |= GRID_ATTR_REVERSE;
else if (end == 6 && strncasecmp(str, "hidden", end) == 0)
ch |= GRID_ATTR_HIDDEN;
else if (end == 7 && strncasecmp(str, "italics", end) == 0)
ch |= GRID_ATTR_ITALICS;
else
return (-1);
str += end + strspn(str + end, delimiters);
} while (*str != '\0');
return (ch);
}

97
buffer-poll.c Normal file
View File

@ -0,0 +1,97 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <errno.h>
#include <unistd.h>
#include "tmux.h"
/* Set up pollfd for buffers. */
void
buffer_set(
struct pollfd *pfd, int fd, unused struct buffer *in, struct buffer *out)
{
pfd->fd = fd;
pfd->events = POLLIN;
if (BUFFER_USED(out) > 0)
pfd->events |= POLLOUT;
}
/* Fill buffers from socket based on poll results. */
int
buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
{
ssize_t n;
#if 0
log_debug("buffer_poll (%ld): fd=%d, revents=%d; out=%zu in=%zu",
(long) getpid(),
pfd->fd, pfd->revents, BUFFER_USED(out), BUFFER_USED(in));
#endif
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
return (-1);
if (pfd->revents & POLLIN) {
buffer_ensure(in, BUFSIZ);
n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in));
#if 0
log_debug("buffer_poll: fd=%d, read=%zd", pfd->fd, n);
#endif
if (n == 0)
return (-1);
if (n == -1) {
if (errno != EINTR && errno != EAGAIN)
return (-1);
} else
buffer_add(in, n);
}
if (BUFFER_USED(out) > 0 && pfd->revents & POLLOUT) {
n = write(pfd->fd, BUFFER_OUT(out), BUFFER_USED(out));
#if 0
log_debug("buffer_poll: fd=%d, write=%zd", pfd->fd, n);
#endif
if (n == -1) {
if (errno != EINTR && errno != EAGAIN)
return (-1);
} else
buffer_remove(out, n);
}
return (0);
}
/* Flush buffer output to socket. */
void
buffer_flush(int fd, struct buffer *in, struct buffer *out)
{
struct pollfd pfd;
while (BUFFER_USED(out) > 0) {
buffer_set(&pfd, fd, in, out);
if (poll(&pfd, 1, INFTIM) == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
fatal("poll failed");
}
if (buffer_poll(&pfd, in, out) != 0)
break;
}
}

227
buffer.c Normal file
View File

@ -0,0 +1,227 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
/* Create a buffer. */
struct buffer *
buffer_create(size_t size)
{
struct buffer *b;
if (size == 0)
fatalx("zero size");
b = xcalloc(1, sizeof *b);
b->base = xmalloc(size);
b->space = size;
return (b);
}
/* Destroy a buffer. */
void
buffer_destroy(struct buffer *b)
{
xfree(b->base);
xfree(b);
}
/* Empty a buffer. */
void
buffer_clear(struct buffer *b)
{
b->size = 0;
b->off = 0;
}
/* Ensure free space for size in buffer. */
void
buffer_ensure(struct buffer *b, size_t size)
{
if (size == 0)
fatalx("zero size");
if (BUFFER_FREE(b) >= size)
return;
if (b->off > 0) {
if (b->size > 0)
memmove(b->base, b->base + b->off, b->size);
b->off = 0;
}
if (SIZE_MAX - b->size < size)
fatalx("size too big");
while (b->space < b->size + size) {
b->base = xrealloc(b->base, 2, b->space);
b->space *= 2;
}
}
/* Adjust buffer after data appended. */
void
buffer_add(struct buffer *b, size_t size)
{
if (size == 0)
fatalx("zero size");
if (size > b->space - b->size)
fatalx("overflow");
b->size += size;
}
/* Reverse buffer add. */
void
buffer_reverse_add(struct buffer *b, size_t size)
{
if (size == 0)
fatalx("zero size");
if (size > b->size)
fatalx("underflow");
b->size -= size;
}
/* Adjust buffer after data removed. */
void
buffer_remove(struct buffer *b, size_t size)
{
if (size == 0)
fatalx("zero size");
if (size > b->size)
fatalx("underflow");
b->size -= size;
b->off += size;
}
/* Reverse buffer remove. */
void
buffer_reverse_remove(struct buffer *b, size_t size)
{
if (size == 0)
fatalx("zero size");
if (size > b->off)
fatalx("overflow");
b->size += size;
b->off -= size;
}
/* Insert a section into the buffer. */
void
buffer_insert_range(struct buffer *b, size_t base, size_t size)
{
if (size == 0)
fatalx("zero size");
if (base > b->size)
fatalx("range outside buffer");
buffer_ensure(b, size);
memmove(b->base + b->off + base + size,
b->base + b->off + base, b->size - base);
b->size += size;
}
/* Delete a section from the buffer. */
void
buffer_delete_range(struct buffer *b, size_t base, size_t size)
{
if (size == 0)
fatalx("zero size");
if (size > b->size)
fatalx("size too big");
if (base + size > b->size)
fatalx("range outside buffer");
memmove(b->base + b->off + base,
b->base + b->off + base + size, b->size - base - size);
b->size -= size;
}
/* Copy data into a buffer. */
void
buffer_write(struct buffer *b, const void *data, size_t size)
{
if (size == 0)
fatalx("zero size");
buffer_ensure(b, size);
memcpy(BUFFER_IN(b), data, size);
buffer_add(b, size);
}
/* Copy data out of a buffer. */
void
buffer_read(struct buffer *b, void *data, size_t size)
{
if (size == 0)
fatalx("zero size");
if (size > b->size)
fatalx("underflow");
memcpy(data, BUFFER_OUT(b), size);
buffer_remove(b, size);
}
/* Store an 8-bit value. */
void
buffer_write8(struct buffer *b, uint8_t n)
{
buffer_ensure(b, 1);
BUFFER_IN(b)[0] = n;
buffer_add(b, 1);
}
/* Store a 16-bit value. */
void
buffer_write16(struct buffer *b, uint16_t n)
{
buffer_ensure(b, 2);
BUFFER_IN(b)[0] = n & 0xff;
BUFFER_IN(b)[1] = n >> 8;
buffer_add(b, 2);
}
/* Extract an 8-bit value. */
uint8_t
buffer_read8(struct buffer *b)
{
uint8_t n;
n = BUFFER_OUT(b)[0];
buffer_remove(b, 1);
return (n);
}
/* Extract a 16-bit value. */
uint16_t
buffer_read16(struct buffer *b)
{
uint16_t n;
n = BUFFER_OUT(b)[0] | (BUFFER_OUT(b)[1] << 8);
buffer_remove(b, 2);
return (n);
}

132
cfg.c Normal file
View File

@ -0,0 +1,132 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "tmux.h"
/*
* Config file parser. Pretty quick and simple, each line is parsed into a
* argv array and executed as a command.
*/
char *cfg_string(FILE *, char, int);
void printflike2 cfg_print(struct cmd_ctx *, const char *, ...);
void printflike2 cfg_error(struct cmd_ctx *, const char *, ...);
char *cfg_cause;
void printflike2
cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...)
{
}
void printflike2
cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
xvasprintf(&cfg_cause, fmt, ap);
va_end(ap);
}
int
load_cfg(const char *path, char **cause)
{
FILE *f;
u_int n;
struct stat sb;
char *buf, *line, *ptr;
size_t len;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
if (stat(path, &sb) != 0) {
xasprintf(cause, "%s: %s", path, strerror(errno));
return (-1);
}
if (!S_ISREG(sb.st_mode)) {
xasprintf(cause, "%s: not a regular file", path);
return (-1);
}
if ((f = fopen(path, "rb")) == NULL) {
xasprintf(cause, "%s: %s", path, strerror(errno));
return (1);
}
n = 0;
line = NULL;
while ((buf = fgetln(f, &len))) {
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';
else {
line = xrealloc(line, 1, len + 1);
memcpy(line, buf, len);
line[len] = '\0';
buf = line;
}
n++;
if (cmd_string_parse(buf, &cmdlist, cause) != 0) {
if (*cause == NULL)
continue;
goto error;
}
if (cmdlist == NULL)
continue;
cfg_cause = NULL;
ctx.msgdata = NULL;
ctx.cursession = NULL;
ctx.curclient = NULL;
ctx.error = cfg_error;
ctx.print = cfg_print;
ctx.info = cfg_print;
ctx.cmdclient = NULL;
cfg_cause = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
if (cfg_cause != NULL) {
*cause = cfg_cause;
goto error;
}
}
if (line != NULL)
xfree(line);
fclose(f);
return (0);
error:
fclose(f);
xasprintf(&ptr, "%s: %s at line %u", path, *cause, n);
xfree(*cause);
*cause = ptr;
return (1);
}

92
client-fn.c Normal file
View File

@ -0,0 +1,92 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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"
void
client_fill_session(struct msg_command_data *data)
{
char *env, *ptr1, *ptr2, buf[256];
size_t len;
const char *errstr;
long long ll;
data->pid = -1;
if ((env = getenv("TMUX")) == NULL)
return;
if ((ptr2 = strrchr(env, ',')) == NULL || ptr2 == env)
return;
for (ptr1 = ptr2 - 1; ptr1 > env && *ptr1 != ','; ptr1--)
;
if (*ptr1 != ',')
return;
ptr1++;
ptr2++;
len = ptr2 - ptr1 - 1;
if (len > (sizeof buf) - 1)
return;
memcpy(buf, ptr1, len);
buf[len] = '\0';
ll = strtonum(buf, 0, LONG_MAX, &errstr);
if (errstr != NULL)
return;
data->pid = ll;
ll = strtonum(ptr2, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return;
data->idx = ll;
}
void
client_write_server(
struct client_ctx *cctx, enum hdrtype type, void *buf, size_t len)
{
struct hdr hdr;
hdr.type = type;
hdr.size = len;
buffer_write(cctx->srv_out, &hdr, sizeof hdr);
if (buf != NULL && len > 0)
buffer_write(cctx->srv_out, buf, len);
}
void
client_write_server2(struct client_ctx *cctx,
enum hdrtype type, void *buf1, size_t len1, void *buf2, size_t len2)
{
struct hdr hdr;
hdr.type = type;
hdr.size = len1 + len2;
buffer_write(cctx->srv_out, &hdr, sizeof hdr);
if (buf1 != NULL && len1 > 0)
buffer_write(cctx->srv_out, buf1, len1);
if (buf2 != NULL && len2 > 0)
buffer_write(cctx->srv_out, buf2, len2);
}

159
client-msg.c Normal file
View File

@ -0,0 +1,159 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
int client_msg_fn_detach(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_error(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_shutdown(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_exit(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_exited(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_suspend(struct hdr *, struct client_ctx *, char **);
struct client_msg {
enum hdrtype type;
int (*fn)(struct hdr *, struct client_ctx *, char **);
};
struct client_msg client_msg_table[] = {
{ MSG_DETACH, client_msg_fn_detach },
{ MSG_ERROR, client_msg_fn_error },
{ MSG_EXIT, client_msg_fn_exit },
{ MSG_EXITED, client_msg_fn_exited },
{ MSG_SHUTDOWN, client_msg_fn_shutdown },
{ MSG_SUSPEND, client_msg_fn_suspend },
};
int
client_msg_dispatch(struct client_ctx *cctx, char **error)
{
struct hdr hdr;
struct client_msg *msg;
u_int i;
if (BUFFER_USED(cctx->srv_in) < sizeof hdr)
return (1);
memcpy(&hdr, BUFFER_OUT(cctx->srv_in), sizeof hdr);
if (BUFFER_USED(cctx->srv_in) < (sizeof hdr) + hdr.size)
return (1);
buffer_remove(cctx->srv_in, sizeof hdr);
for (i = 0; i < nitems(client_msg_table); i++) {
msg = client_msg_table + i;
if (msg->type == hdr.type) {
if (msg->fn(&hdr, cctx, error) != 0)
return (-1);
return (0);
}
}
fatalx("unexpected message");
}
int
client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error)
{
if (hdr->size > SIZE_MAX - 1)
fatalx("bad MSG_ERROR size");
*error = xmalloc(hdr->size + 1);
buffer_read(cctx->srv_in, *error, hdr->size);
(*error)[hdr->size] = '\0';
return (-1);
}
int
client_msg_fn_detach(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_DETACH size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_DETACH;
return (0);
}
int
client_msg_fn_shutdown(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_SHUTDOWN size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_SHUTDOWN;
return (0);
}
int
client_msg_fn_exit(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_EXIT size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_EXIT;
return (0);
}
int
client_msg_fn_exited(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_EXITED size");
return (-1);
}
int
client_msg_fn_suspend(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
struct sigaction act;
if (hdr->size != 0)
fatalx("bad MSG_SUSPEND size");
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
act.sa_handler = SIG_DFL;
if (sigaction(SIGTSTP, &act, NULL) != 0)
fatal("sigaction failed");
act.sa_handler = sighandler;
if (sigaction(SIGCONT, &act, NULL) != 0)
fatal("sigaction failed");
kill(getpid(), SIGTSTP);
return (0);
}

226
client.c Normal file
View File

@ -0,0 +1,226 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "tmux.h"
void client_handle_winch(struct client_ctx *);
int
client_init(char *path, struct client_ctx *cctx, int start_server, int flags)
{
struct sockaddr_un sa;
struct stat sb;
struct msg_identify_data data;
struct winsize ws;
size_t size;
int mode;
struct buffer *b;
char *name;
if (lstat(path, &sb) != 0) {
if (start_server && errno == ENOENT) {
if ((cctx->srv_fd = server_start(path)) == -1)
goto start_failed;
goto server_started;
}
goto not_found;
}
if (!S_ISSOCK(sb.st_mode)) {
errno = ENOTSOCK;
goto not_found;
}
memset(&sa, 0, sizeof sa);
sa.sun_family = AF_UNIX;
size = strlcpy(sa.sun_path, path, sizeof sa.sun_path);
if (size >= sizeof sa.sun_path) {
errno = ENAMETOOLONG;
goto not_found;
}
if ((cctx->srv_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
fatal("socket");
if (connect(
cctx->srv_fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
if (errno == ECONNREFUSED) {
if (unlink(path) != 0 || !start_server)
goto not_found;
if ((cctx->srv_fd = server_start(path)) == -1)
goto start_failed;
goto server_started;
}
goto not_found;
}
server_started:
if ((mode = fcntl(cctx->srv_fd, F_GETFL)) == -1)
fatal("fcntl failed");
if (fcntl(cctx->srv_fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl failed");
cctx->srv_in = buffer_create(BUFSIZ);
cctx->srv_out = buffer_create(BUFSIZ);
if (isatty(STDIN_FILENO)) {
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
fatal("ioctl(TIOCGWINSZ)");
data.version = PROTOCOL_VERSION;
data.flags = flags;
data.sx = ws.ws_col;
data.sy = ws.ws_row;
*data.tty = '\0';
if (getcwd(data.cwd, sizeof data.cwd) == NULL)
*data.cwd = '\0';
if ((name = ttyname(STDIN_FILENO)) == NULL)
fatal("ttyname failed");
if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty)
fatalx("ttyname failed");
b = buffer_create(BUFSIZ);
cmd_send_string(b, getenv("TERM"));
client_write_server2(cctx, MSG_IDENTIFY,
&data, sizeof data, BUFFER_OUT(b), BUFFER_USED(b));
buffer_destroy(b);
}
return (0);
start_failed:
log_warnx("server failed to start");
return (1);
not_found:
log_warn("server not found");
return (1);
}
int
client_main(struct client_ctx *cctx)
{
struct pollfd pfd;
char *error;
int xtimeout; /* Yay for ncurses namespace! */
siginit();
logfile("client");
setproctitle("client");
error = NULL;
xtimeout = INFTIM;
while (!sigterm) {
if (sigchld) {
waitpid(WAIT_ANY, NULL, WNOHANG);
sigchld = 0;
}
if (sigwinch)
client_handle_winch(cctx);
if (sigcont) {
siginit();
client_write_server(cctx, MSG_WAKEUP, NULL, 0);
sigcont = 0;
}
switch (client_msg_dispatch(cctx, &error)) {
case -1:
goto out;
case 0:
/* May be more in buffer, don't let poll block. */
xtimeout = 0;
break;
default:
/* Out of data, poll may block. */
xtimeout = INFTIM;
break;
}
pfd.fd = cctx->srv_fd;
pfd.events = POLLIN;
if (BUFFER_USED(cctx->srv_out) > 0)
pfd.events |= POLLOUT;
if (poll(&pfd, 1, xtimeout) == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
fatal("poll failed");
}
if (buffer_poll(&pfd, cctx->srv_in, cctx->srv_out) != 0)
goto server_dead;
}
out:
if (sigterm) {
printf("[terminated]\n");
return (1);
}
if (cctx->flags & CCTX_SHUTDOWN) {
printf("[server exited]\n");
return (0);
}
if (cctx->flags & CCTX_EXIT) {
printf("[exited]\n");
return (0);
}
if (cctx->flags & CCTX_DETACH) {
printf("[detached]\n");
return (0);
}
printf("[error: %s]\n", error);
return (1);
server_dead:
printf("[lost server]\n");
return (0);
}
void
client_handle_winch(struct client_ctx *cctx)
{
struct msg_resize_data data;
struct winsize ws;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
fatal("ioctl failed");
data.sx = ws.ws_col;
data.sy = ws.ws_row;
client_write_server(cctx, MSG_RESIZE, &data, sizeof data);
sigwinch = 0;
}

161
clock.c Normal file
View File

@ -0,0 +1,161 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include <time.h>
#include "tmux.h"
const char clock_table[14][5][5] = {
{ { 1,1,1,1,1 }, /* 0 */
{ 1,0,0,0,1 },
{ 1,0,0,0,1 },
{ 1,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 0,0,0,0,1 }, /* 1 */
{ 0,0,0,0,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 } },
{ { 1,1,1,1,1 }, /* 2 */
{ 0,0,0,0,1 },
{ 1,1,1,1,1 },
{ 1,0,0,0,0 },
{ 1,1,1,1,1 } },
{ { 1,1,1,1,1 }, /* 3 */
{ 0,0,0,0,1 },
{ 1,1,1,1,1 },
{ 0,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 1,0,0,0,1 }, /* 4 */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 } },
{ { 1,1,1,1,1 }, /* 5 */
{ 1,0,0,0,0 },
{ 1,1,1,1,1 },
{ 0,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 1,1,1,1,1 }, /* 6 */
{ 1,0,0,0,0 },
{ 1,1,1,1,1 },
{ 1,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 1,1,1,1,1 }, /* 7 */
{ 0,0,0,0,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 } },
{ { 1,1,1,1,1 }, /* 8 */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 1,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 1,1,1,1,1 }, /* 9 */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 0,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 0,0,0,0,0 }, /* : */
{ 0,0,1,0,0 },
{ 0,0,0,0,0 },
{ 0,0,1,0,0 },
{ 0,0,0,0,0 } },
{ { 1,1,1,1,1 }, /* A */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 1,0,0,0,1 },
{ 1,0,0,0,1 } },
{ { 1,1,1,1,1 }, /* P */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 1,0,0,0,0 },
{ 1,0,0,0,0 } },
{ { 1,0,0,0,1 }, /* M */
{ 1,1,0,1,1 },
{ 1,0,1,0,1 },
{ 1,0,0,0,1 },
{ 1,0,0,0,1 } },
};
void
clock_draw(struct screen_write_ctx *ctx, u_int colour, int style)
{
struct screen *s = ctx->s;
struct grid_cell gc;
char tim[64], *ptr;
time_t t;
u_int i, j, x, y, idx;
t = time(NULL);
if (style == 0)
strftime(tim, sizeof tim, "%l:%M %p", localtime(&t));
else
strftime(tim, sizeof tim, "%H:%M", localtime(&t));
screen_write_clearscreen(ctx);
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.fg = colour;
if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) {
if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) {
x = (screen_size_x(s) / 2) - (strlen(tim) / 2);
y = screen_size_y(s) / 2;
screen_write_cursormove(ctx, x, y);
gc.fg = colour;
screen_write_puts(ctx, &gc, "%s", tim);
}
return;
}
x = (screen_size_x(s) / 2) - 3 * strlen(tim);
y = (screen_size_y(s) / 2) - 3;
for (ptr = tim; *ptr != '\0'; ptr++) {
if (*ptr >= '0' && *ptr <= '9')
idx = *ptr - '0';
else if (*ptr == ':')
idx = 10;
else if (*ptr == 'A')
idx = 11;
else if (*ptr == 'P')
idx = 12;
else if (*ptr == 'M')
idx = 13;
else {
x += 6;
continue;
}
for (j = 0; j < 5; j++) {
screen_write_cursormove(ctx, x, y + j);
for (i = 0; i < 5; i++) {
if (clock_table[idx][j][i])
gc.attr |= GRID_ATTR_REVERSE;
else
gc.attr &= ~GRID_ATTR_REVERSE;
screen_write_putc(ctx, &gc, ' ');
}
}
x += 6;
}
}

80
cmd-attach-session.c Normal file
View File

@ -0,0 +1,80 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Attach existing session to the current terminal.
*/
int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach",
"[-d] " CMD_TARGET_SESSION_USAGE,
CMD_DFLAG|CMD_CANTNEST|CMD_STARTSERVER,
cmd_target_init,
cmd_target_parse,
cmd_attach_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
char *cause;
if (ctx->curclient != NULL)
return (0);
if (ARRAY_LENGTH(&sessions) == 0) {
ctx->error(ctx, "no sessions");
return (-1);
}
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal");
return (-1);
}
if (tty_open(&ctx->cmdclient->tty, &cause) != 0) {
ctx->error(ctx, "terminal open failed: %s", cause);
xfree(cause);
return (-1);
}
if (data->flags & CMD_DFLAG)
server_write_session(s, MSG_DETACH, NULL, 0);
ctx->cmdclient->session = s;
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
recalculate_sizes();
server_redraw_client(ctx->cmdclient);
return (1);
}

157
cmd-bind-key.c Normal file
View File

@ -0,0 +1,157 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Bind a key to a command, this recurses through cmd_*.
*/
int cmd_bind_key_parse(struct cmd *, int, char **, char **);
int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_bind_key_send(struct cmd *, struct buffer *);
void cmd_bind_key_recv(struct cmd *, struct buffer *);
void cmd_bind_key_free(struct cmd *);
size_t cmd_bind_key_print(struct cmd *, char *, size_t);
struct cmd_bind_key_data {
int key;
int can_repeat;
struct cmd_list *cmdlist;
};
const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind",
"[-r] key command [arguments]",
0,
NULL,
cmd_bind_key_parse,
cmd_bind_key_exec,
cmd_bind_key_send,
cmd_bind_key_recv,
cmd_bind_key_free,
cmd_bind_key_print
};
int
cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_bind_key_data *data;
int opt;
self->data = data = xmalloc(sizeof *data);
data->can_repeat = 0;
data->cmdlist = NULL;
while ((opt = getopt(argc, argv, "r")) != -1) {
switch (opt) {
case 'r':
data->can_repeat = 1;
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc < 1)
goto usage;
if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) {
xasprintf(cause, "unknown key: %s", argv[0]);
goto error;
}
argc--;
argv++;
if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL)
goto error;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
int
cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
{
struct cmd_bind_key_data *data = self->data;
if (data == NULL)
return (0);
key_bindings_add(data->key, data->can_repeat, data->cmdlist);
data->cmdlist = NULL; /* avoid free */
return (0);
}
void
cmd_bind_key_send(struct cmd *self, struct buffer *b)
{
struct cmd_bind_key_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_list_send(data->cmdlist, b);
}
void
cmd_bind_key_recv(struct cmd *self, struct buffer *b)
{
struct cmd_bind_key_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->cmdlist = cmd_list_recv(b);
}
void
cmd_bind_key_free(struct cmd *self)
{
struct cmd_bind_key_data *data = self->data;
if (data->cmdlist != NULL)
cmd_list_free(data->cmdlist);
xfree(data);
}
size_t
cmd_bind_key_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_bind_key_data *data = self->data;
size_t off = 0;
const char *skey;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len) {
skey = key_string_lookup_key(data->key);
off += xsnprintf(buf + off, len - off, " %s ", skey);
}
if (off < len)
off += cmd_list_print(data->cmdlist, buf + off, len - off);
return (off);
}

92
cmd-break-pane.c Normal file
View File

@ -0,0 +1,92 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Break pane off into a window.
*/
int cmd_break_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp",
CMD_PANE_WINDOW_USAGE " [-d]",
CMD_DFLAG,
cmd_pane_init,
cmd_pane_parse,
cmd_break_pane_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};
int
cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_pane_data *data = self->data;
struct winlink *wl;
struct session *s;
struct window_pane *wp;
struct window *w;
char *cause;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (window_count_panes(wl->window) == 1) {
ctx->error(ctx, "can't break pane: %d", data->pane);
return (-1);
}
TAILQ_REMOVE(&wl->window->panes, wp, entry);
if (wl->window->active == wp) {
wl->window->active = TAILQ_PREV(wp, window_panes, entry);
if (wl->window->active == NULL)
wl->window->active = TAILQ_NEXT(wp, entry);
}
layout_refresh(wl->window, 0);
w = wp->window = window_create1(s->sx, s->sy);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp;
w->name = default_window_name(w);
wl = session_attach(s, w, -1, &cause); /* can't fail */
if (!(data->flags & CMD_DFLAG))
session_select(s, wl->idx);
layout_refresh(w, 0);
server_redraw_session(s);
return (0);
}

107
cmd-choose-session.c Normal file
View File

@ -0,0 +1,107 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Enter choice mode to choose a session.
*/
int cmd_choose_session_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_session_callback(void *, int);
const struct cmd_entry cmd_choose_session_entry = {
"choose-session", NULL,
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_choose_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
struct cmd_choose_session_data {
u_int client;
};
int
cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct cmd_choose_session_data *cdata;
struct winlink *wl;
struct session *s;
u_int i, idx, cur;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (0);
cur = idx = 0;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i);
if (s == NULL)
continue;
if (s == ctx->curclient->session)
cur = idx;
idx++;
window_choose_add(wl->window->active, i,
"%s: %u windows [%ux%u]%s", s->name,
winlink_count(&s->windows), s->sx, s->sy,
s->flags & SESSION_UNATTACHED ? "" : " (attached)");
}
cdata = xmalloc(sizeof *cdata);
cdata->client = server_client_index(ctx->curclient);
window_choose_ready(
wl->window->active, cur, cmd_choose_session_callback, cdata);
return (0);
}
void
cmd_choose_session_callback(void *data, int idx)
{
struct cmd_choose_session_data *cdata = data;
struct client *c;
if (idx != -1 && cdata->client <= ARRAY_LENGTH(&clients) - 1) {
c = ARRAY_ITEM(&clients, cdata->client);
if (c != NULL && (u_int) idx <= ARRAY_LENGTH(&sessions) - 1) {
c->session = ARRAY_ITEM(&sessions, idx);
recalculate_sizes();
server_redraw_client(c);
}
}
xfree(cdata);
}

106
cmd-choose-window.c Normal file
View File

@ -0,0 +1,106 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Enter choice mode to choose a window.
*/
int cmd_choose_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_window_callback(void *, int);
const struct cmd_entry cmd_choose_window_entry = {
"choose-window", NULL,
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_choose_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
struct cmd_choose_window_data {
u_int session;
};
int
cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct cmd_choose_window_data *cdata;
struct session *s;
struct winlink *wl, *wm;
struct window *w;
u_int idx, cur;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
s = ctx->curclient->session;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (0);
cur = idx = 0;
RB_FOREACH(wm, winlinks, &s->windows) {
w = wm->window;
if (wm == s->curw)
cur = idx;
idx++;
window_choose_add(wl->window->active,
wm->idx, "%3d: %s [%ux%u %s] (%u panes)", wm->idx, w->name,
w->sx, w->sy, layout_name(w), window_count_panes(w));
}
cdata = xmalloc(sizeof *cdata);
if (session_index(s, &cdata->session) != 0)
fatalx("session not found");
window_choose_ready(
wl->window->active, cur, cmd_choose_window_callback, cdata);
return (0);
}
void
cmd_choose_window_callback(void *data, int idx)
{
struct cmd_choose_window_data *cdata = data;
struct session *s;
if (idx != -1 && cdata->session <= ARRAY_LENGTH(&sessions) - 1) {
s = ARRAY_ITEM(&sessions, cdata->session);
if (s != NULL && session_select(s, idx) == 0)
server_redraw_session(s);
recalculate_sizes();
}
xfree(cdata);
}

68
cmd-clear-history.c Normal file
View File

@ -0,0 +1,68 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Clear pane history.
*/
void cmd_clear_history_init(struct cmd *, int);
int cmd_clear_history_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clear_history_entry = {
"clear-history", "clearhist",
CMD_PANE_WINDOW_USAGE,
0,
cmd_pane_init,
cmd_pane_parse,
cmd_clear_history_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};
int
cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_pane_data *data = self->data;
struct winlink *wl;
struct window_pane *wp;
struct grid *gd;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
gd = wp->base.grid;
grid_move_lines(gd, 0, gd->hsize, gd->sy);
gd->hsize = 0;
return (0);
}

54
cmd-clock-mode.c Normal file
View File

@ -0,0 +1,54 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Enter clock mode.
*/
int cmd_clock_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clock_mode_entry = {
"clock-mode", NULL,
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_clock_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
window_pane_set_mode(wl->window->active, &window_clock_mode);
return (0);
}

178
cmd-command-prompt.c Normal file
View File

@ -0,0 +1,178 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <ctype.h>
#include <string.h>
#include "tmux.h"
/*
* Prompt for command in client.
*/
void cmd_command_prompt_init(struct cmd *, int);
int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
int cmd_command_prompt_callback(void *, const char *);
const struct cmd_entry cmd_command_prompt_entry = {
"command-prompt", NULL,
CMD_TARGET_CLIENT_USAGE " [template]",
CMD_ARG01,
cmd_command_prompt_init,
cmd_target_parse,
cmd_command_prompt_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
struct cmd_command_prompt_data {
struct client *c;
char *template;
};
void
cmd_command_prompt_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
switch (key) {
case ',':
data->arg = xstrdup("rename-window '%%'");
break;
case '.':
data->arg = xstrdup("move-window -t '%%'");
break;
case 'f':
data->arg = xstrdup("find-window '%%'");
break;
}
}
int
cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct cmd_command_prompt_data *cdata;
struct client *c;
char *hdr, *ptr;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
if (c->prompt_string != NULL)
return (0);
cdata = xmalloc(sizeof *cdata);
cdata->c = c;
if (data->arg != NULL) {
cdata->template = xstrdup(data->arg);
if ((ptr = strchr(data->arg, ' ')) == NULL)
ptr = strchr(data->arg, '\0');
xasprintf(&hdr, "(%.*s) ", (int) (ptr - data->arg), data->arg);
} else {
cdata->template = NULL;
hdr = xstrdup(":");
}
status_prompt_set(c, hdr, cmd_command_prompt_callback, cdata, 0);
xfree(hdr);
return (0);
}
int
cmd_command_prompt_callback(void *data, const char *s)
{
struct cmd_command_prompt_data *cdata = data;
struct client *c = cdata->c;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *cause, *ptr, *buf, ch;
size_t len, slen;
if (s == NULL) {
xfree(cdata);
return (0);
}
slen = strlen(s);
len = 0;
buf = NULL;
if (cdata->template != NULL) {
ptr = cdata->template;
while (*ptr != '\0') {
switch (ch = *ptr++) {
case '%':
if (*ptr != '%')
break;
ptr++;
buf = xrealloc(buf, 1, len + slen + 1);
memcpy(buf + len, s, slen);
len += slen;
break;
default:
buf = xrealloc(buf, 1, len + 2);
buf[len++] = ch;
break;
}
}
xfree(cdata->template);
buf[len] = '\0';
s = buf;
}
xfree(cdata);
if (cmd_string_parse(s, &cmdlist, &cause) != 0) {
if (cause == NULL)
return (0);
*cause = toupper((u_char) *cause);
status_message_set(c, cause);
xfree(cause);
cmdlist = NULL;
}
if (buf != NULL)
xfree(buf);
if (cmdlist == NULL)
return (0);
ctx.msgdata = NULL;
ctx.cursession = c->session;
ctx.curclient = c;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
if (c->prompt_callback != (void *) &cmd_command_prompt_callback)
return (1);
return (0);
}

141
cmd-confirm-before.c Normal file
View File

@ -0,0 +1,141 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
*
* 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 <ctype.h>
#include <string.h>
#include "tmux.h"
/*
* Asks for confirmation before executing a command.
*/
int cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *);
void cmd_confirm_before_init(struct cmd *, int);
int cmd_confirm_before_callback(void *, const char *);
struct cmd_confirm_before_data {
struct client *c;
char *cmd;
};
const struct cmd_entry cmd_confirm_before_entry = {
"confirm-before", "confirm",
CMD_TARGET_CLIENT_USAGE " command",
CMD_ARG1,
cmd_confirm_before_init,
cmd_target_parse,
cmd_confirm_before_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
void
cmd_confirm_before_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
switch (key) {
case '&':
data->arg = xstrdup("kill-window");
break;
case 'x':
data->arg = xstrdup("kill-pane");
break;
}
}
int
cmd_confirm_before_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct cmd_confirm_before_data *cdata;
struct client *c;
char *buf, *cmd, *ptr;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
ptr = xstrdup(data->arg);
if ((cmd = strtok(ptr, " \t")) == NULL)
cmd = ptr;
xasprintf(&buf, "Confirm '%s'? (y/n) ", cmd);
xfree(ptr);
cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(data->arg);
cdata->c = c;
status_prompt_set(
cdata->c, buf, cmd_confirm_before_callback, cdata, PROMPT_SINGLE);
xfree(buf);
return (1);
}
int
cmd_confirm_before_callback(void *data, const char *s)
{
struct cmd_confirm_before_data *cdata = data;
struct client *c = cdata->c;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *cause;
if (s == NULL || tolower((u_char) s[0]) != 'y' || s[1] != '\0')
goto out;
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(c, cause);
xfree(cause);
}
goto out;
}
ctx.msgdata = NULL;
ctx.cursession = c->session;
ctx.curclient = c;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
out:
if (cdata->cmd != NULL)
xfree(cdata->cmd);
xfree(cdata);
return (0);
}

222
cmd-copy-buffer.c Normal file
View File

@ -0,0 +1,222 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
*
* 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 <stdlib.h>
#include "tmux.h"
/*
* Copies a session paste buffer to another session.
*/
int cmd_copy_buffer_parse(struct cmd *, int, char **, char **);
int cmd_copy_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_copy_buffer_send(struct cmd *, struct buffer *);
void cmd_copy_buffer_recv(struct cmd *, struct buffer *);
void cmd_copy_buffer_free(struct cmd *);
void cmd_copy_buffer_init(struct cmd *, int);
size_t cmd_copy_buffer_print(struct cmd *, char *, size_t);
struct cmd_copy_buffer_data {
char *dst_session;
char *src_session;
int dst_idx;
int src_idx;
};
const struct cmd_entry cmd_copy_buffer_entry = {
"copy-buffer", "copyb",
"[-a src-index] [-b dst-index] [-s src-session] [-t dst-session]",
0,
cmd_copy_buffer_init,
cmd_copy_buffer_parse,
cmd_copy_buffer_exec,
cmd_copy_buffer_send,
cmd_copy_buffer_recv,
cmd_copy_buffer_free,
cmd_copy_buffer_print
};
void
cmd_copy_buffer_init(struct cmd *self, unused int arg)
{
struct cmd_copy_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
data->dst_session = NULL;
data->src_session = NULL;
data->dst_idx = -1;
data->src_idx = -1;
}
int
cmd_copy_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_copy_buffer_data *data;
const char *errstr;
int n, opt;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "a:b:s:t:")) != -1) {
switch (opt) {
case 'a':
if (data->src_idx == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "buffer %s", errstr);
goto error;
}
data->src_idx = n;
}
break;
case 'b':
if (data->dst_idx == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "buffer %s", errstr);
goto error;
}
data->dst_idx = n;
}
break;
case 's':
if (data->src_session == NULL)
data->src_session = xstrdup(optarg);
break;
case 't':
if (data->dst_session == NULL)
data->dst_session = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
int
cmd_copy_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_copy_buffer_data *data = self->data;
struct paste_buffer *pb;
struct session *dst_session, *src_session;
u_int limit;
if ((dst_session = cmd_find_session(ctx, data->dst_session)) == NULL ||
(src_session = cmd_find_session(ctx, data->src_session)) == NULL)
return (-1);
if (data->src_idx == -1) {
if ((pb = paste_get_top(&src_session->buffers)) == NULL) {
ctx->error(ctx, "no buffers");
return (-1);
}
} else {
if ((pb = paste_get_index(&src_session->buffers,
data->src_idx)) == NULL) {
ctx->error(ctx, "no buffer %d", data->src_idx);
return (-1);
}
}
limit = options_get_number(&dst_session->options, "buffer-limit");
if (data->dst_idx == -1) {
paste_add(&dst_session->buffers, xstrdup(pb->data), limit);
return (0);
}
if (paste_replace(&dst_session->buffers, data->dst_idx,
xstrdup(pb->data)) != 0) {
ctx->error(ctx, "no buffer %d", data->dst_idx);
return (-1);
}
return (0);
}
void
cmd_copy_buffer_send(struct cmd *self, struct buffer *b)
{
struct cmd_copy_buffer_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->dst_session);
cmd_send_string(b, data->src_session);
}
void
cmd_copy_buffer_recv(struct cmd *self, struct buffer *b)
{
struct cmd_copy_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->dst_session = cmd_recv_string(b);
data->src_session = cmd_recv_string(b);
}
void
cmd_copy_buffer_free(struct cmd *self)
{
struct cmd_copy_buffer_data *data = self->data;
if (data->dst_session != NULL)
xfree(data->dst_session);
if (data->src_session != NULL)
xfree(data->src_session);
xfree(data);
}
size_t
cmd_copy_buffer_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_copy_buffer_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->src_idx != -1) {
off += xsnprintf(buf + off, len - off, " -a %d",
data->src_idx);
}
if (off < len && data->dst_idx != -1) {
off += xsnprintf(buf + off, len - off, " -b %d",
data->dst_idx);
}
if (off < len && data->src_session != NULL) {
off += cmd_prarg(buf + off, len - off, " -s ",
data->src_session);
}
if (off < len && data->dst_session != NULL) {
off += cmd_prarg(buf + off, len - off, " -t ",
data->dst_session);
}
return (off);
}

56
cmd-copy-mode.c Normal file
View File

@ -0,0 +1,56 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Enter copy mode.
*/
int cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL,
CMD_TARGET_WINDOW_USAGE,
CMD_UFLAG,
cmd_target_init,
cmd_target_parse,
cmd_copy_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
NULL
};
int
cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
window_pane_set_mode(wl->window->active, &window_copy_mode);
if (data->flags & CMD_UFLAG)
window_copy_pageup(wl->window->active);
return (0);
}

61
cmd-delete-buffer.c Normal file
View File

@ -0,0 +1,61 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Delete a paste buffer.
*/
int cmd_delete_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_delete_buffer_entry = {
"delete-buffer", "deleteb",
CMD_BUFFER_SESSION_USAGE,
0,
cmd_buffer_init,
cmd_buffer_parse,
cmd_delete_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};
int
cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_buffer_data *data = self->data;
struct session *s;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (data->buffer == -1)
paste_free_top(&s->buffers);
else if (paste_free_index(&s->buffers, data->buffer) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer);
return (-1);
}
return (0);
}

54
cmd-detach-client.c Normal file
View File

@ -0,0 +1,54 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Detach a client.
*/
int cmd_detach_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_detach_client_entry = {
"detach-client", "detach",
CMD_TARGET_CLIENT_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_detach_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
server_write_client(c, MSG_DETACH, NULL, 0);
return (0);
}

61
cmd-down-pane.c Normal file
View File

@ -0,0 +1,61 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move down a pane.
*/
int cmd_down_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_down_pane_entry = {
"down-pane", "downp",
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_down_pane_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_down_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window *w;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
w = wl->window;
do {
w->active = TAILQ_NEXT(w->active, entry);
if (w->active == NULL)
w->active = TAILQ_FIRST(&w->panes);
layout_refresh(w, 1);
} while (w->active->flags & PANE_HIDDEN);
return (0);
}

160
cmd-find-window.c Normal file
View File

@ -0,0 +1,160 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
/*
* Find window containing text.
*/
int cmd_find_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_find_window_callback(void *, int);
const struct cmd_entry cmd_find_window_entry = {
"find-window", "findw",
CMD_TARGET_WINDOW_USAGE " match-string",
CMD_ARG1,
cmd_target_init,
cmd_target_parse,
cmd_find_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
struct cmd_find_window_data {
u_int session;
};
int
cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct cmd_find_window_data *cdata;
struct session *s;
struct winlink *wl, *wm;
struct window *w;
struct window_pane *wp;
ARRAY_DECL(, u_int) list_idx;
ARRAY_DECL(, char *) list_ctx;
char *sres, *sctx;
u_int i;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
s = ctx->curclient->session;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
ARRAY_INIT(&list_idx);
ARRAY_INIT(&list_ctx);
RB_FOREACH(wm, winlinks, &s->windows) {
i = 0;
TAILQ_FOREACH(wp, &wm->window->panes, entry) {
i++;
if (strstr(wm->window->name, data->arg) != NULL)
sctx = xstrdup("");
else {
sres = window_pane_search(wp, data->arg);
if (sres == NULL &&
strstr(wp->base.title, data->arg) == NULL)
continue;
if (sres == NULL) {
xasprintf(&sctx,
"pane %u title: \"%s\"", i - 1,
wp->base.title);
} else {
xasprintf(&sctx, "\"%s\"", sres);
xfree(sres);
}
}
ARRAY_ADD(&list_idx, wm->idx);
ARRAY_ADD(&list_ctx, sctx);
}
}
if (ARRAY_LENGTH(&list_idx) == 0) {
ctx->error(ctx, "no windows matching: %s", data->arg);
ARRAY_FREE(&list_idx);
ARRAY_FREE(&list_ctx);
return (-1);
}
if (ARRAY_LENGTH(&list_idx) == 1) {
if (session_select(s, ARRAY_FIRST(&list_idx)) == 0)
server_redraw_session(s);
recalculate_sizes();
goto out;
}
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
goto out;
for (i = 0; i < ARRAY_LENGTH(&list_idx); i++) {
wm = winlink_find_by_index(
&s->windows, ARRAY_ITEM(&list_idx, i));
w = wm->window;
sctx = ARRAY_ITEM(&list_ctx, i);
window_choose_add(wl->window->active,
wm->idx, "%3d: %s [%ux%u] (%u panes) %s", wm->idx, w->name,
w->sx, w->sy, window_count_panes(w), sctx);
xfree(sctx);
}
cdata = xmalloc(sizeof *cdata);
if (session_index(s, &cdata->session) != 0)
fatalx("session not found");
window_choose_ready(
wl->window->active, 0, cmd_find_window_callback, cdata);
out:
ARRAY_FREE(&list_idx);
ARRAY_FREE(&list_ctx);
return (0);
}
void
cmd_find_window_callback(void *data, int idx)
{
struct cmd_find_window_data *cdata = data;
struct session *s;
if (idx != -1 && cdata->session <= ARRAY_LENGTH(&sessions) - 1) {
s = ARRAY_ITEM(&sessions, cdata->session);
if (s != NULL && session_select(s, idx) == 0)
server_redraw_session(s);
recalculate_sizes();
}
xfree(cdata);
}

694
cmd-generic.c Normal file
View File

@ -0,0 +1,694 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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"
#define CMD_FLAGS "adDgkuU"
#define CMD_FLAGMASK (CMD_AFLAG|CMD_DFLAG|CMD_BIGDFLAG|CMD_GFLAG|CMD_KFLAG| \
CMD_UFLAG|CMD_BIGUFLAG)
int cmd_do_flags(int, int, int *);
size_t cmd_print_flags(char *, size_t, size_t, int);
int cmd_fill_argument(int, char **, int, char **);
size_t
cmd_prarg(char *buf, size_t len, const char *prefix, char *arg)
{
if (strchr(arg, ' ') != NULL)
return (xsnprintf(buf, len, "%s\"%s\"", prefix, arg));
return (xsnprintf(buf, len, "%s%s", prefix, arg));
}
int
cmd_do_flags(int opt, int iflags, int *oflags)
{
switch (opt) {
case 'a':
if (iflags & CMD_AFLAG) {
(*oflags) |= CMD_AFLAG;
return (0);
}
return (-1);
case 'd':
if (iflags & CMD_DFLAG) {
(*oflags) |= CMD_DFLAG;
return (0);
}
return (-1);
case 'D':
if (iflags & CMD_BIGDFLAG) {
(*oflags) |= CMD_BIGDFLAG;
return (0);
}
return (-1);
case 'g':
if (iflags & CMD_GFLAG) {
(*oflags) |= CMD_GFLAG;
return (0);
}
return (-1);
case 'k':
if (iflags & CMD_KFLAG) {
(*oflags) |= CMD_KFLAG;
return (0);
}
return (-1);
case 'u':
if (iflags & CMD_UFLAG) {
(*oflags) |= CMD_UFLAG;
return (0);
}
return (-1);
case 'U':
if (iflags & CMD_BIGUFLAG) {
(*oflags) |= CMD_BIGUFLAG;
return (0);
}
return (-1);
}
return (1);
}
size_t
cmd_print_flags(char *buf, size_t len, size_t off, int flags)
{
size_t boff = off;
if ((flags & CMD_FLAGMASK) == 0)
return (0);
off += xsnprintf(buf + off, len - off, " -");
if (off < len && flags & CMD_AFLAG)
off += xsnprintf(buf + off, len - off, "a");
if (off < len && flags & CMD_BIGDFLAG)
off += xsnprintf(buf + off, len - off, "D");
if (off < len && flags & CMD_DFLAG)
off += xsnprintf(buf + off, len - off, "d");
if (off < len && flags & CMD_GFLAG)
off += xsnprintf(buf + off, len - off, "g");
if (off < len && flags & CMD_KFLAG)
off += xsnprintf(buf + off, len - off, "k");
if (off < len && flags & CMD_UFLAG)
off += xsnprintf(buf + off, len - off, "u");
if (off < len && flags & CMD_BIGUFLAG)
off += xsnprintf(buf + off, len - off, "U");
return (off - boff);
}
int
cmd_fill_argument(int flags, char **arg, int argc, char **argv)
{
*arg = NULL;
if (flags & CMD_ARG1) {
if (argc != 1)
return (-1);
*arg = xstrdup(argv[0]);
return (0);
}
if (flags & CMD_ARG01) {
if (argc != 0 && argc != 1)
return (-1);
if (argc == 1)
*arg = xstrdup(argv[0]);
return (0);
}
if (argc != 0)
return (-1);
return (0);
}
void
cmd_target_init(struct cmd *self, unused int key)
{
struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data);
data->flags = 0;
data->target = NULL;
data->arg = NULL;
}
int
cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_target_data *data;
int opt;
/* Don't use the entry version since it may be dependent on key. */
cmd_target_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
case -1:
goto usage;
case 0:
continue;
}
switch (opt) {
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
void
cmd_target_send(struct cmd *self, struct buffer *b)
{
struct cmd_target_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_target_recv(struct cmd *self, struct buffer *b)
{
struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_target_free(struct cmd *self)
{
struct cmd_target_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->arg != NULL)
xfree(data->arg);
xfree(data);
}
size_t
cmd_target_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_target_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->flags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg);
return (off);
}
void
cmd_srcdst_init(struct cmd *self, unused int key)
{
struct cmd_srcdst_data *data;
self->data = data = xmalloc(sizeof *data);
data->flags = 0;
data->src = NULL;
data->dst = NULL;
data->arg = NULL;
}
int
cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_srcdst_data *data;
int opt;
cmd_srcdst_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "s:t:")) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
case -1:
goto usage;
case 0:
continue;
}
switch (opt) {
case 's':
if (data->src == NULL)
data->src = xstrdup(optarg);
break;
case 't':
if (data->dst == NULL)
data->dst = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
void
cmd_srcdst_send(struct cmd *self, struct buffer *b)
{
struct cmd_srcdst_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->src);
cmd_send_string(b, data->dst);
cmd_send_string(b, data->arg);
}
void
cmd_srcdst_recv(struct cmd *self, struct buffer *b)
{
struct cmd_srcdst_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->src = cmd_recv_string(b);
data->dst = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_srcdst_free(struct cmd *self)
{
struct cmd_srcdst_data *data = self->data;
if (data->src != NULL)
xfree(data->src);
if (data->dst != NULL)
xfree(data->dst);
if (data->arg != NULL)
xfree(data->arg);
xfree(data);
}
size_t
cmd_srcdst_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_srcdst_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->flags);
if (off < len && data->src != NULL)
off += xsnprintf(buf + off, len - off, " -s %s", data->src);
if (off < len && data->dst != NULL)
off += xsnprintf(buf + off, len - off, " -t %s", data->dst);
if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg);
return (off);
}
void
cmd_buffer_init(struct cmd *self, unused int key)
{
struct cmd_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
data->flags = 0;
data->target = NULL;
data->buffer = -1;
data->arg = NULL;
}
int
cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_buffer_data *data;
int opt, n;
const char *errstr;
cmd_buffer_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "b:t:")) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
case -1:
goto usage;
case 0:
continue;
}
switch (opt) {
case 'b':
if (data->buffer == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "buffer %s", errstr);
goto error;
}
data->buffer = n;
}
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
void
cmd_buffer_send(struct cmd *self, struct buffer *b)
{
struct cmd_buffer_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_buffer_recv(struct cmd *self, struct buffer *b)
{
struct cmd_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_buffer_free(struct cmd *self)
{
struct cmd_buffer_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->arg != NULL)
xfree(data->arg);
xfree(data);
}
size_t
cmd_buffer_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_buffer_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->flags);
if (off < len && data->buffer != -1)
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg);
return (off);
}
void
cmd_option_init(struct cmd *self, unused int key)
{
struct cmd_option_data *data;
self->data = data = xmalloc(sizeof *data);
data->flags = 0;
data->target = NULL;
data->option = NULL;
data->value = NULL;
}
int
cmd_option_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_option_data *data;
int opt;
/* Don't use the entry version since it may be dependent on key. */
cmd_option_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
case -1:
goto usage;
case 0:
continue;
}
switch (opt) {
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc == 2) {
data->option = xstrdup(argv[0]);
data->value = xstrdup(argv[1]);
} else if (argc == 1)
data->option = xstrdup(argv[0]);
else
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
void
cmd_option_send(struct cmd *self, struct buffer *b)
{
struct cmd_option_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->option);
cmd_send_string(b, data->value);
}
void
cmd_option_recv(struct cmd *self, struct buffer *b)
{
struct cmd_option_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->option = cmd_recv_string(b);
data->value = cmd_recv_string(b);
}
void
cmd_option_free(struct cmd *self)
{
struct cmd_option_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->option != NULL)
xfree(data->option);
if (data->value != NULL)
xfree(data->value);
xfree(data);
}
size_t
cmd_option_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_option_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->flags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->option != NULL)
off += xsnprintf(buf + off, len - off, " %s", data->option);
if (off < len && data->value != NULL)
off += xsnprintf(buf + off, len - off, " %s", data->value);
return (off);
}
void
cmd_pane_init(struct cmd *self, unused int key)
{
struct cmd_pane_data *data;
self->data = data = xmalloc(sizeof *data);
data->flags = 0;
data->target = NULL;
data->arg = NULL;
data->pane = -1;
}
int
cmd_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_pane_data *data;
int opt, n;
const char *errstr;
/* Don't use the entry version since it may be dependent on key. */
cmd_pane_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "p:t:")) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
case -1:
goto usage;
case 0:
continue;
}
switch (opt) {
case 'p':
if (data->pane == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "pane %s", errstr);
goto error;
}
data->pane = n;
}
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
void
cmd_pane_send(struct cmd *self, struct buffer *b)
{
struct cmd_pane_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_pane_recv(struct cmd *self, struct buffer *b)
{
struct cmd_pane_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_pane_free(struct cmd *self)
{
struct cmd_pane_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->arg != NULL)
xfree(data->arg);
xfree(data);
}
size_t
cmd_pane_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_pane_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->flags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg);
return (off);
}

51
cmd-has-session.c Normal file
View File

@ -0,0 +1,51 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Cause client to report an error and exit with 1 if session doesn't exist.
*/
int cmd_has_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_has_session_entry = {
"has-session", "has",
CMD_TARGET_SESSION_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_has_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_has_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
if (cmd_find_session(ctx, data->target) == NULL)
return (-1);
return (0);
}

72
cmd-kill-pane.c Normal file
View File

@ -0,0 +1,72 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Kill pane.
*/
int cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_pane_entry = {
"kill-pane", "killp",
CMD_PANE_WINDOW_USAGE,
0,
cmd_pane_init,
cmd_pane_parse,
cmd_kill_pane_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};
int
cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_pane_data *data = self->data;
struct winlink *wl;
struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (window_count_panes(wl->window) == 1) {
ctx->error(ctx, "can't kill pane: %d", data->pane);
return (-1);
}
window_remove_pane(wl->window, wp);
server_redraw_window(wl->window);
layout_refresh(wl->window, 0);
return (0);
}

51
cmd-kill-server.c Normal file
View File

@ -0,0 +1,51 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <signal.h>
#include <unistd.h>
#include "tmux.h"
/*
* Kill the server and do nothing else.
*/
int cmd_kill_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_server_entry = {
"kill-server", NULL,
"",
0,
NULL,
NULL,
cmd_kill_server_exec,
NULL,
NULL,
NULL,
NULL
};
int
cmd_kill_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx)
{
sigterm = 1;
return (0);
}

68
cmd-kill-session.c Normal file
View File

@ -0,0 +1,68 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Destroy session, detaching all clients attached to it and destroying any
* windows linked only to this session.
*
* Note this deliberately has no alias to make it hard to hit by accident.
*/
int cmd_kill_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_session_entry = {
"kill-session", NULL,
CMD_TARGET_SESSION_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_kill_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_kill_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct client *c;
u_int i;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c->session == s) {
c->session = NULL;
server_write_client(c, MSG_EXIT, NULL, 0);
}
}
recalculate_sizes();
session_destroy(s);
return (0);
}

69
cmd-kill-window.c Normal file
View File

@ -0,0 +1,69 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Destroy window.
*/
int cmd_kill_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_window_entry = {
"kill-window", "killw",
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_kill_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct session *s;
struct client *c;
u_int i;
int destroyed;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1);
destroyed = session_detach(s, wl);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != s)
continue;
if (destroyed) {
c->session = NULL;
server_write_client(c, MSG_EXIT, NULL, 0);
} else
server_redraw_client(c);
}
recalculate_sizes();
return (0);
}

60
cmd-last-window.c Normal file
View File

@ -0,0 +1,60 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move to last window.
*/
int cmd_last_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_last_window_entry = {
"last-window", "last",
CMD_TARGET_SESSION_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_last_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_last_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (session_last(s) == 0)
server_redraw_session(s);
else {
ctx->error(ctx, "no last window");
return (-1);
}
recalculate_sizes();
return (0);
}

109
cmd-link-window.c Normal file
View File

@ -0,0 +1,109 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Link a window into another session.
*/
int cmd_link_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw",
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
CMD_DFLAG|CMD_KFLAG,
cmd_srcdst_init,
cmd_srcdst_parse,
cmd_link_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free,
cmd_srcdst_print
};
int
cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_srcdst_data *data = self->data;
struct session *dst;
struct winlink *wl_src, *wl_dst;
char *cause;
int idx;
if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL)
return (-1);
if (arg_parse_window(data->dst, &dst, &idx) != 0) {
ctx->error(ctx, "bad window: %s", data->dst);
return (-1);
}
if (dst == NULL)
dst = ctx->cursession;
if (dst == NULL)
dst = cmd_current_session(ctx);
if (dst == NULL) {
ctx->error(ctx, "session not found: %s", data->dst);
return (-1);
}
wl_dst = NULL;
if (idx != -1)
wl_dst = winlink_find_by_index(&dst->windows, idx);
if (wl_dst != NULL) {
if (wl_dst->window == wl_src->window)
return (0);
if (data->flags & CMD_KFLAG) {
/*
* Can't use session_detach as it will destroy session
* if this makes it empty.
*/
session_alert_cancel(dst, wl_dst);
winlink_stack_remove(&dst->lastw, wl_dst);
winlink_remove(&dst->windows, wl_dst);
/* Force select/redraw if current. */
if (wl_dst == dst->curw) {
data->flags &= ~CMD_DFLAG;
dst->curw = NULL;
}
}
}
wl_dst = session_attach(dst, wl_src->window, idx, &cause);
if (wl_dst == NULL) {
ctx->error(ctx, "create session failed: %s", cause);
xfree(cause);
return (-1);
}
if (data->flags & CMD_DFLAG)
server_status_session(dst);
else {
session_select(dst, wl_dst->idx);
server_redraw_session(dst);
}
recalculate_sizes();
return (0);
}

91
cmd-list-buffers.c Normal file
View File

@ -0,0 +1,91 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
/*
* List paste buffers.
*/
int cmd_list_buffers_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_buffers_entry = {
"list-buffers", "lsb",
CMD_TARGET_SESSION_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_list_buffers_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_list_buffers_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct paste_buffer *pb;
u_int idx;
char *tmp;
size_t size, in, out;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (s->sx > 35) { /* leave three for ... */
size = s->sx - 32;
tmp = xmalloc(size + 1);
} else {
size = 0;
tmp = NULL;
}
idx = 0;
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) {
if (tmp != NULL) {
in = out = 0;
while (out < size && pb->data[in] != '\0') {
if (pb->data[in] > 31 && pb->data[in] != 127)
tmp[out++] = pb->data[in];
in++;
}
tmp[out] = '\0';
if (out == size) {
tmp[out - 1] = '.';
tmp[out - 2] = '.';
tmp[out - 3] = '.';
}
ctx->print(ctx, "%d: %zu bytes: \"%s\"",
idx - 1, strlen(pb->data), tmp);
} else
ctx->print(ctx, "%d: %zu bytes", idx, strlen(pb->data));
}
if (tmp != NULL)
xfree(tmp);
return (0);
}

67
cmd-list-clients.c Normal file
View File

@ -0,0 +1,67 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include <time.h>
#include "tmux.h"
/*
* List all clients.
*/
int cmd_list_clients_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_clients_entry = {
"list-clients", "lsc",
"",
0,
NULL,
NULL,
cmd_list_clients_exec,
NULL,
NULL,
NULL,
NULL
};
int
cmd_list_clients_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
struct client *c;
u_int i;
const char *s_utf8;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
if (c->tty.flags & TTY_UTF8)
s_utf8 = " (utf8)";
else
s_utf8 = "";
ctx->print(ctx, "%s: %s [%ux%u %s]%s", c->tty.path,
c->session->name, c->tty.sx, c->tty.sy,
c->tty.termname, s_utf8);
}
return (0);
}

51
cmd-list-commands.c Normal file
View File

@ -0,0 +1,51 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* List all commands with usages.
*/
int cmd_list_commands_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_commands_entry = {
"list-commands", "lscm",
"",
0,
NULL,
NULL,
cmd_list_commands_exec,
NULL,
NULL,
NULL,
NULL
};
int
cmd_list_commands_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
const struct cmd_entry **entryp;
for (entryp = cmd_table; *entryp != NULL; entryp++)
ctx->print(ctx, "%s %s", (*entryp)->name, (*entryp)->usage);
return (0);
}

59
cmd-list-keys.c Normal file
View File

@ -0,0 +1,59 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* List key bindings.
*/
int cmd_list_keys_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_keys_entry = {
"list-keys", "lsk",
"",
0,
NULL,
NULL,
cmd_list_keys_exec,
NULL,
NULL,
NULL,
NULL
};
int
cmd_list_keys_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
struct key_binding *bd;
const char *key;
char tmp[BUFSIZ];
SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
if ((key = key_string_lookup_key(bd->key)) == NULL)
continue;
*tmp = '\0';
cmd_list_print(bd->cmdlist, tmp, sizeof tmp);
ctx->print(ctx, "%11s: %s", key, tmp);
}
return (0);
}

67
cmd-list-sessions.c Normal file
View File

@ -0,0 +1,67 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include <time.h>
#include "tmux.h"
/*
* List all sessions.
*/
int cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_sessions_entry = {
"list-sessions", "ls", "",
0,
NULL,
NULL,
cmd_list_sessions_exec,
NULL,
NULL,
NULL,
NULL
};
int
cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
struct session *s;
char *tim;
u_int i;
time_t t;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i);
if (s == NULL)
continue;
t = s->tv.tv_sec;
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
ctx->print(ctx, "%s: %u windows (created %s) [%ux%u]%s",
s->name, winlink_count(&s->windows), tim, s->sx, s->sy,
s->flags & SESSION_UNATTACHED ? "" : " (attached)");
}
return (0);
}

88
cmd-list-windows.c Normal file
View File

@ -0,0 +1,88 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <unistd.h>
#include "tmux.h"
/*
* List windows on given session.
*/
int cmd_list_windows_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw",
CMD_TARGET_SESSION_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_list_windows_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct grid *gd;
u_int i;
unsigned long long size;
const char *name;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window;
ctx->print(ctx,
"%3d: %s [%ux%u]", wl->idx, w->name, w->sx, w->sy);
TAILQ_FOREACH(wp, &w->panes, entry) {
gd = wp->base.grid;
size = 0;
for (i = 0; i < gd->hsize; i++) {
size += gd->size[i] * sizeof **gd->data;
size += gd->usize[i] * sizeof **gd->udata;
}
size += gd->hsize * (sizeof *gd->data);
size += gd->hsize * (sizeof *gd->size);
if (wp->fd != -1)
name = ttyname(wp->fd);
else
name = "unknown";
ctx->print(ctx,
" %s [%ux%u %s] [history %u/%u, %llu bytes]",
name, wp->sx, wp->sy, layout_name(w), gd->hsize,
gd->hlimit, size);
}
}
return (0);
}

154
cmd-list.c Normal file
View File

@ -0,0 +1,154 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
struct cmd_list *
cmd_list_parse(int argc, char **argv, char **cause)
{
struct cmd_list *cmdlist;
struct cmd *cmd;
int i, lastsplit;
size_t arglen, new_argc;
char **new_argv;
cmdlist = xmalloc(sizeof *cmdlist);
TAILQ_INIT(cmdlist);
lastsplit = 0;
for (i = 0; i < argc; i++) {
arglen = strlen(argv[i]);
if (arglen == 0 || argv[i][arglen - 1] != ';')
continue;
argv[i][arglen - 1] = '\0';
if (arglen > 1 && argv[i][arglen - 2] == '\\') {
argv[i][arglen - 2] = ';';
continue;
}
new_argc = i - lastsplit;
new_argv = argv + lastsplit;
if (arglen != 1)
new_argc++;
cmd = cmd_parse(new_argc, new_argv, cause);
if (cmd == NULL)
goto bad;
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
lastsplit = i + 1;
}
if (lastsplit != argc) {
cmd = cmd_parse(argc - lastsplit, argv + lastsplit, cause);
if (cmd == NULL)
goto bad;
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
}
return (cmdlist);
bad:
cmd_list_free(cmdlist);
return (NULL);
}
int
cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
{
struct cmd *cmd;
int n;
TAILQ_FOREACH(cmd, cmdlist, qentry) {
if ((n = cmd_exec(cmd, ctx)) != 0)
return (n);
}
return (0);
}
void
cmd_list_send(struct cmd_list *cmdlist, struct buffer *b)
{
struct cmd *cmd;
u_int n;
n = 0;
TAILQ_FOREACH(cmd, cmdlist, qentry)
n++;
buffer_write(b, &n, sizeof n);
TAILQ_FOREACH(cmd, cmdlist, qentry)
cmd_send(cmd, b);
}
struct cmd_list *
cmd_list_recv(struct buffer *b)
{
struct cmd_list *cmdlist;
struct cmd *cmd;
u_int n;
buffer_read(b, &n, sizeof n);
cmdlist = xmalloc(sizeof *cmdlist);
TAILQ_INIT(cmdlist);
while (n-- > 0) {
cmd = cmd_recv(b);
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
}
return (cmdlist);
}
void
cmd_list_free(struct cmd_list *cmdlist)
{
struct cmd *cmd;
while (!TAILQ_EMPTY(cmdlist)) {
cmd = TAILQ_FIRST(cmdlist);
TAILQ_REMOVE(cmdlist, cmd, qentry);
cmd_free(cmd);
}
xfree(cmdlist);
}
size_t
cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len)
{
struct cmd *cmd;
size_t off;
off = 0;
TAILQ_FOREACH(cmd, cmdlist, qentry) {
if (off >= len)
break;
off += cmd_print(cmd, buf + off, len - off);
if (off >= len)
break;
if (TAILQ_NEXT(cmd, qentry) != NULL)
off += xsnprintf(buf + off, len - off, " ; ");
}
return (off);
}

106
cmd-load-buffer.c Normal file
View File

@ -0,0 +1,106 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
*
* 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 <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
/*
* Loads a session paste buffer from a file.
*/
int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_load_buffer_entry = {
"load-buffer", "loadb",
CMD_BUFFER_SESSION_USAGE " path",
CMD_ARG1,
cmd_buffer_init,
cmd_buffer_parse,
cmd_load_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};
int
cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_buffer_data *data = self->data;
struct session *s;
struct stat statbuf;
FILE *f;
char *buf;
u_int limit;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (stat(data->arg, &statbuf) < 0) {
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
return (-1);
}
if (!S_ISREG(statbuf.st_mode)) {
ctx->error(ctx, "%s: not a regular file", data->arg);
return (-1);
}
if ((f = fopen(data->arg, "rb")) == NULL) {
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
return (-1);
}
/*
* We don't want to die due to memory exhaustion, hence xmalloc can't
* be used here.
*/
if ((buf = malloc(statbuf.st_size + 1)) == NULL) {
ctx->error(ctx, "malloc error: %s", strerror(errno));
return (-1);
}
if (fread(buf, 1, statbuf.st_size, f) != (size_t) statbuf.st_size) {
ctx->error(ctx, "%s: fread error", data->arg);
xfree(buf);
fclose(f);
return (-1);
}
buf[statbuf.st_size] = '\0';
fclose(f);
limit = options_get_number(&s->options, "buffer-limit");
if (data->buffer == -1) {
paste_add(&s->buffers, buf, limit);
return (0);
}
if (paste_replace(&s->buffers, data->buffer, buf) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer);
xfree(buf);
return (-1);
}
return (0);
}

54
cmd-lock-server.c Normal file
View File

@ -0,0 +1,54 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <pwd.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
/*
* Lock server.
*/
int cmd_lock_server_exec(struct cmd *, struct cmd_ctx *);
int cmd_lock_server_callback(void *, const char *);
const struct cmd_entry cmd_lock_server_entry = {
"lock-server", "lock",
"",
0,
NULL,
NULL,
cmd_lock_server_exec,
NULL,
NULL,
NULL,
NULL,
};
int
cmd_lock_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx)
{
server_lock();
return (0);
}

123
cmd-move-window.c Normal file
View File

@ -0,0 +1,123 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move a window.
*/
int cmd_move_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_move_window_entry = {
"move-window", "movew",
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
CMD_DFLAG|CMD_KFLAG,
cmd_srcdst_init,
cmd_srcdst_parse,
cmd_move_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free,
cmd_srcdst_print
};
int
cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_srcdst_data *data = self->data;
struct session *src, *dst;
struct winlink *wl_src, *wl_dst;
struct client *c;
u_int i;
int destroyed, idx;
char *cause;
if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL)
return (-1);
if (arg_parse_window(data->dst, &dst, &idx) != 0) {
ctx->error(ctx, "bad window: %s", data->dst);
return (-1);
}
if (dst == NULL)
dst = ctx->cursession;
if (dst == NULL)
dst = cmd_current_session(ctx);
if (dst == NULL) {
ctx->error(ctx, "session not found: %s", data->dst);
return (-1);
}
wl_dst = NULL;
if (idx != -1)
wl_dst = winlink_find_by_index(&dst->windows, idx);
if (wl_dst != NULL) {
if (wl_dst->window == wl_src->window)
return (0);
if (data->flags & CMD_KFLAG) {
/*
* Can't use session_detach as it will destroy session
* if this makes it empty.
*/
session_alert_cancel(dst, wl_dst);
winlink_stack_remove(&dst->lastw, wl_dst);
winlink_remove(&dst->windows, wl_dst);
/* Force select/redraw if current. */
if (wl_dst == dst->curw) {
data->flags &= ~CMD_DFLAG;
dst->curw = NULL;
}
}
}
wl_dst = session_attach(dst, wl_src->window, idx, &cause);
if (wl_dst == NULL) {
ctx->error(ctx, "attach window failed: %s", cause);
xfree(cause);
return (-1);
}
destroyed = session_detach(src, wl_src);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != src)
continue;
if (destroyed) {
c->session = NULL;
server_write_client(c, MSG_EXIT, NULL, 0);
} else
server_redraw_client(c);
}
if (data->flags & CMD_DFLAG)
server_status_session(dst);
else {
session_select(dst, wl_dst->idx);
server_redraw_session(dst);
}
recalculate_sizes();
return (0);
}

248
cmd-new-session.c Normal file
View File

@ -0,0 +1,248 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Create a new session and attach to the current terminal unless -d is given.
*/
int cmd_new_session_parse(struct cmd *, int, char **, char **);
int cmd_new_session_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_session_send(struct cmd *, struct buffer *);
void cmd_new_session_recv(struct cmd *, struct buffer *);
void cmd_new_session_free(struct cmd *);
void cmd_new_session_init(struct cmd *, int);
size_t cmd_new_session_print(struct cmd *, char *, size_t);
struct cmd_new_session_data {
char *newname;
char *winname;
char *cmd;
int flag_detached;
};
const struct cmd_entry cmd_new_session_entry = {
"new-session", "new",
"[-d] [-n window-name] [-s session-name] [command]",
CMD_STARTSERVER|CMD_CANTNEST,
cmd_new_session_init,
cmd_new_session_parse,
cmd_new_session_exec,
cmd_new_session_send,
cmd_new_session_recv,
cmd_new_session_free,
cmd_new_session_print
};
void
cmd_new_session_init(struct cmd *self, unused int arg)
{
struct cmd_new_session_data *data;
self->data = data = xmalloc(sizeof *data);
data->flag_detached = 0;
data->newname = NULL;
data->winname = NULL;
data->cmd = NULL;
}
int
cmd_new_session_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_new_session_data *data;
int opt;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "ds:n:")) != -1) {
switch (opt) {
case 'd':
data->flag_detached = 1;
break;
case 's':
if (data->newname == NULL)
data->newname = xstrdup(optarg);
break;
case 'n':
if (data->winname == NULL)
data->winname = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0 && argc != 1)
goto usage;
if (argc == 1)
data->cmd = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int
cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_new_session_data *data = self->data;
struct client *c = ctx->cmdclient;
struct session *s;
char *cmd, *cwd, *cause;
u_int sx, sy;
if (ctx->curclient != NULL)
return (0);
if (!data->flag_detached) {
if (c == NULL) {
ctx->error(ctx, "no client to attach to");
return (-1);
}
if (!(c->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal");
return (-1);
}
}
if (data->newname != NULL && session_find(data->newname) != NULL) {
ctx->error(ctx, "duplicate session: %s", data->newname);
return (-1);
}
cmd = data->cmd;
if (cmd == NULL)
cmd = options_get_string(&global_options, "default-command");
if (c == NULL || c->cwd == NULL)
cwd = options_get_string(&global_options, "default-path");
else
cwd = c->cwd;
sx = 80;
sy = 25;
if (!data->flag_detached) {
sx = c->tty.sx;
sy = c->tty.sy;
}
if (options_get_number(&global_options, "status")) {
if (sy == 0)
sy = 1;
else
sy--;
}
if (!data->flag_detached && tty_open(&c->tty, &cause) != 0) {
ctx->error(ctx, "open terminal failed: %s", cause);
xfree(cause);
return (-1);
}
s = session_create(data->newname, cmd, cwd, sx, sy, &cause);
if (s == NULL) {
ctx->error(ctx, "create session failed: %s", cause);
xfree(cause);
return (-1);
}
if (data->winname != NULL) {
xfree(s->curw->window->name);
s->curw->window->name = xstrdup(data->winname);
options_set_number(
&s->curw->window->options, "automatic-rename", 0);
}
if (data->flag_detached) {
if (c != NULL)
server_write_client(c, MSG_EXIT, NULL, 0);
} else {
c->session = s;
server_write_client(c, MSG_READY, NULL, 0);
server_redraw_client(c);
}
recalculate_sizes();
return (1);
}
void
cmd_new_session_send(struct cmd *self, struct buffer *b)
{
struct cmd_new_session_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->newname);
cmd_send_string(b, data->winname);
cmd_send_string(b, data->cmd);
}
void
cmd_new_session_recv(struct cmd *self, struct buffer *b)
{
struct cmd_new_session_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->newname = cmd_recv_string(b);
data->winname = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
}
void
cmd_new_session_free(struct cmd *self)
{
struct cmd_new_session_data *data = self->data;
if (data->newname != NULL)
xfree(data->newname);
if (data->winname != NULL)
xfree(data->winname);
if (data->cmd != NULL)
xfree(data->cmd);
xfree(data);
}
size_t
cmd_new_session_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_new_session_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, " -d");
if (off < len && data->newname != NULL)
off += cmd_prarg(buf + off, len - off, " -s ", data->newname);
if (off < len && data->winname != NULL)
off += cmd_prarg(buf + off, len - off, " -n ", data->winname);
if (off < len && data->cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->cmd);
return (off);
}

241
cmd-new-window.c Normal file
View File

@ -0,0 +1,241 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Create a new window.
*/
int cmd_new_window_parse(struct cmd *, int, char **, char **);
int cmd_new_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_window_send(struct cmd *, struct buffer *);
void cmd_new_window_recv(struct cmd *, struct buffer *);
void cmd_new_window_free(struct cmd *);
void cmd_new_window_init(struct cmd *, int);
size_t cmd_new_window_print(struct cmd *, char *, size_t);
struct cmd_new_window_data {
char *target;
char *name;
char *cmd;
int flag_detached;
int flag_kill;
};
const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww",
"[-dk] [-n window-name] [-t target-window] [command]",
0,
cmd_new_window_init,
cmd_new_window_parse,
cmd_new_window_exec,
cmd_new_window_send,
cmd_new_window_recv,
cmd_new_window_free,
cmd_new_window_print
};
void
cmd_new_window_init(struct cmd *self, unused int arg)
{
struct cmd_new_window_data *data;
self->data = data = xmalloc(sizeof *data);
data->target = NULL;
data->name = NULL;
data->cmd = NULL;
data->flag_detached = 0;
data->flag_kill = 0;
}
int
cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_new_window_data *data;
int opt;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "dkt:n:")) != -1) {
switch (opt) {
case 'd':
data->flag_detached = 1;
break;
case 'k':
data->flag_kill = 1;
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'n':
if (data->name == NULL)
data->name = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0 && argc != 1)
goto usage;
if (argc == 1)
data->cmd = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int
cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_new_window_data *data = self->data;
struct session *s;
struct winlink *wl;
char *cmd, *cwd, *cause;
int idx;
if (data == NULL)
return (0);
if (arg_parse_window(data->target, &s, &idx) != 0) {
ctx->error(ctx, "bad window: %s", data->target);
return (-1);
}
if (s == NULL)
s = ctx->cursession;
if (s == NULL)
s = cmd_current_session(ctx);
if (s == NULL) {
ctx->error(ctx, "session not found: %s", data->target);
return (-1);
}
wl = NULL;
if (idx != -1)
wl = winlink_find_by_index(&s->windows, idx);
if (wl != NULL) {
if (data->flag_kill) {
/*
* Can't use session_detach as it will destroy session
* if this makes it empty.
*/
session_alert_cancel(s, wl);
winlink_stack_remove(&s->lastw, wl);
winlink_remove(&s->windows, wl);
/* Force select/redraw if current. */
if (wl == s->curw) {
data->flag_detached = 0;
s->curw = NULL;
}
}
}
cmd = data->cmd;
if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command");
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
cwd = options_get_string(&global_options, "default-path");
else
cwd = ctx->cmdclient->cwd;
wl = session_new(s, data->name, cmd, cwd, idx, &cause);
if (wl == NULL) {
ctx->error(ctx, "create window failed: %s", cause);
xfree(cause);
return (-1);
}
if (!data->flag_detached) {
session_select(s, wl->idx);
server_redraw_session(s);
} else
server_status_session(s);
return (0);
}
void
cmd_new_window_send(struct cmd *self, struct buffer *b)
{
struct cmd_new_window_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->name);
cmd_send_string(b, data->cmd);
}
void
cmd_new_window_recv(struct cmd *self, struct buffer *b)
{
struct cmd_new_window_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->name = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
}
void
cmd_new_window_free(struct cmd *self)
{
struct cmd_new_window_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->name != NULL)
xfree(data->name);
if (data->cmd != NULL)
xfree(data->cmd);
xfree(data);
}
size_t
cmd_new_window_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_new_window_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, " -d");
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->name != NULL)
off += cmd_prarg(buf + off, len - off, " -n ", data->name);
if (off < len && data->cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->cmd);
return (off);
}

55
cmd-next-layout.c Normal file
View File

@ -0,0 +1,55 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Switch window to next layout.
*/
int cmd_next_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_next_layout_entry = {
"next-layout", "nextl",
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_next_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_next_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
layout_next(wl->window);
ctx->info(ctx, "layout now: %s", layout_name(wl->window));
return (0);
}

78
cmd-next-window.c Normal file
View File

@ -0,0 +1,78 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move to next window.
*/
void cmd_next_window_init(struct cmd *, int);
int cmd_next_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_next_window_entry = {
"next-window", "next",
CMD_TARGET_SESSION_USAGE,
CMD_AFLAG,
cmd_next_window_init,
cmd_target_parse,
cmd_next_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
void
cmd_next_window_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
if (key == KEYC_ADDESC('n'))
data->flags |= CMD_AFLAG;
}
int
cmd_next_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
int activity;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
activity = 0;
if (data->flags & CMD_AFLAG)
activity = 1;
if (session_next(s, activity) == 0)
server_redraw_session(s);
else {
ctx->error(ctx, "no next window");
return (-1);
}
recalculate_sizes();
return (0);
}

78
cmd-paste-buffer.c Normal file
View File

@ -0,0 +1,78 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
/*
* Paste paste buffer if present.
*/
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb",
"[-d] " CMD_BUFFER_WINDOW_USAGE,
CMD_DFLAG,
cmd_buffer_init,
cmd_buffer_parse,
cmd_paste_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};
int
cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_buffer_data *data = self->data;
struct winlink *wl;
struct window *w;
struct session *s;
struct paste_buffer *pb;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1);
w = wl->window;
if (data->buffer == -1)
pb = paste_get_top(&s->buffers);
else {
if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) {
ctx->error(ctx, "no buffer %d", data->buffer);
return (-1);
}
}
if (pb != NULL)
buffer_write(w->active->out, pb->data, strlen(pb->data));
/* Delete the buffer if -d. */
if (data->flags & CMD_DFLAG) {
if (data->buffer == -1)
paste_free_top(&s->buffers);
else
paste_free_index(&s->buffers, data->buffer);
}
return (0);
}

55
cmd-previous-layout.c Normal file
View File

@ -0,0 +1,55 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Switch window to previous layout.
*/
int cmd_previous_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_previous_layout_entry = {
"previous-layout", "prevl",
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_previous_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_previous_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
layout_previous(wl->window);
ctx->info(ctx, "layout now: %s", layout_name(wl->window));
return (0);
}

78
cmd-previous-window.c Normal file
View File

@ -0,0 +1,78 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move to previous window.
*/
void cmd_previous_window_init(struct cmd *, int);
int cmd_previous_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_previous_window_entry = {
"previous-window", "prev",
CMD_TARGET_SESSION_USAGE,
CMD_AFLAG,
cmd_previous_window_init,
cmd_target_parse,
cmd_previous_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
void
cmd_previous_window_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
if (key == KEYC_ADDESC('p'))
data->flags |= CMD_AFLAG;
}
int
cmd_previous_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
int activity;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
activity = 0;
if (data->flags & CMD_AFLAG)
activity = 1;
if (session_previous(s, activity) == 0)
server_redraw_session(s);
else {
ctx->error(ctx, "no previous window");
return (-1);
}
recalculate_sizes();
return (0);
}

54
cmd-refresh-client.c Normal file
View File

@ -0,0 +1,54 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Refresh client.
*/
int cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh",
CMD_TARGET_CLIENT_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_refresh_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_refresh_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
server_redraw_client(c);
return (0);
}

57
cmd-rename-session.c Normal file
View File

@ -0,0 +1,57 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Change session name.
*/
int cmd_rename_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_session_entry = {
"rename-session", "rename",
CMD_TARGET_SESSION_USAGE " new-name",
CMD_ARG1,
cmd_target_init,
cmd_target_parse,
cmd_rename_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
xfree(s->name);
s->name = xstrdup(data->arg);
return (0);
}

61
cmd-rename-window.c Normal file
View File

@ -0,0 +1,61 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Rename a window.
*/
int cmd_rename_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_window_entry = {
"rename-window", "renamew",
CMD_TARGET_WINDOW_USAGE " new-name",
CMD_ARG1,
cmd_target_init,
cmd_target_parse,
cmd_rename_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct winlink *wl;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1);
xfree(wl->window->name);
wl->window->name = xstrdup(data->arg);
options_set_number(&wl->window->options, "automatic-rename", 0);
server_status_session(s);
return (0);
}

105
cmd-resize-pane.c Normal file
View File

@ -0,0 +1,105 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Increase or decrease pane size.
*/
void cmd_resize_pane_init(struct cmd *, int);
int cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep",
CMD_PANE_WINDOW_USAGE "[-DU] [adjustment]",
CMD_ARG01|CMD_BIGUFLAG|CMD_BIGDFLAG,
cmd_resize_pane_init,
cmd_pane_parse,
cmd_resize_pane_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};
void
cmd_resize_pane_init(struct cmd *self, int key)
{
struct cmd_pane_data *data;
cmd_pane_init(self, key);
data = self->data;
if (key == KEYC_ADDCTL(KEYC_DOWN))
data->flags |= CMD_BIGDFLAG;
if (key == KEYC_ADDESC(KEYC_UP))
data->arg = xstrdup("5");
if (key == KEYC_ADDESC(KEYC_DOWN)) {
data->flags |= CMD_BIGDFLAG;
data->arg = xstrdup("5");
}
}
int
cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_pane_data *data = self->data;
struct winlink *wl;
const char *errstr;
struct window_pane *wp;
u_int adjust;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (data->arg == NULL)
adjust = 1;
else {
adjust = strtonum(data->arg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "adjustment %s: %s", errstr, data->arg);
return (-1);
}
}
if (!(data->flags & CMD_BIGDFLAG))
adjust = -adjust;
if (layout_resize(wp, adjust) != 0) {
ctx->error(ctx, "layout %s "
"does not support resizing", layout_name(wp->window));
return (-1);
}
server_redraw_window(wl->window);
return (0);
}

87
cmd-respawn-window.c Normal file
View File

@ -0,0 +1,87 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <unistd.h>
#include "tmux.h"
/*
* Respawn a window (restart the command). Kill existing if -k given.
*/
int cmd_respawn_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw",
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
CMD_ARG01|CMD_KFLAG,
cmd_target_init,
cmd_target_parse,
cmd_respawn_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct session *s;
const char **env;
char *cause;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1);
w = wl->window;
if (!(data->flags & CMD_KFLAG)) {
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->fd == -1)
continue;
ctx->error(ctx,
"window still active: %s:%d", s->name, wl->idx);
return (-1);
}
}
env = server_fill_environ(s);
wp = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, wp, entry);
window_destroy_panes(w);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
window_pane_resize(wp, w->sx, w->sy);
if (window_pane_spawn(wp, data->arg, NULL, env, &cause) != 0) {
ctx->error(ctx, "respawn window failed: %s", cause);
xfree(cause);
return (-1);
}
screen_reinit(&wp->base);
recalculate_sizes();
server_redraw_window(w);
return (0);
}

111
cmd-rotate-window.c Normal file
View File

@ -0,0 +1,111 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Rotate the panes in a window.
*/
void cmd_rotate_window_init(struct cmd *, int);
int cmd_rotate_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rotate_window_entry = {
"rotate-window", "rotatew",
"[-DU] " CMD_TARGET_WINDOW_USAGE,
CMD_BIGUFLAG|CMD_BIGDFLAG,
cmd_rotate_window_init,
cmd_target_parse,
cmd_rotate_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
void
cmd_rotate_window_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
if (key == KEYC_ADDESC('o'))
data->flags |= CMD_BIGDFLAG;
}
int
cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window *w;
struct window_pane *wp, *wp2;
u_int sx, sy, xoff, yoff;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
w = wl->window;
if (data->flags & CMD_BIGDFLAG) {
wp = TAILQ_LAST(&w->panes, window_panes);
TAILQ_REMOVE(&w->panes, wp, entry);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
xoff = wp->xoff; yoff = wp->yoff;
sx = wp->sx; sy = wp->sy;
TAILQ_FOREACH(wp, &w->panes, entry) {
if ((wp2 = TAILQ_NEXT(wp, entry)) == NULL)
break;
wp->xoff = wp2->xoff; wp->yoff = wp2->yoff;
window_pane_resize(wp, wp2->sx, wp2->sy);
}
wp->xoff = xoff; wp->yoff = yoff;
window_pane_resize(wp, sx, sy);
if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL)
wp = TAILQ_LAST(&w->panes, window_panes);
window_set_active_pane(w, wp);
} else {
wp = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, wp, entry);
TAILQ_INSERT_TAIL(&w->panes, wp, entry);
xoff = wp->xoff; yoff = wp->yoff;
sx = wp->sx; sy = wp->sy;
TAILQ_FOREACH_REVERSE(wp, &w->panes, window_panes, entry) {
if ((wp2 = TAILQ_PREV(wp, window_panes, entry)) == NULL)
break;
wp->xoff = wp2->xoff; wp->yoff = wp2->yoff;
window_pane_resize(wp, wp2->sx, wp2->sy);
}
wp->xoff = xoff; wp->yoff = yoff;
window_pane_resize(wp, sx, sy);
if ((wp = TAILQ_NEXT(w->active, entry)) == NULL)
wp = TAILQ_FIRST(&w->panes);
window_set_active_pane(w, wp);
}
layout_refresh(w, 0);
return (0);
}

90
cmd-save-buffer.c Normal file
View File

@ -0,0 +1,90 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
*
* 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 <sys/stat.h>
#include <errno.h>
#include <string.h>
#include "tmux.h"
/*
* Saves a session paste buffer to a file.
*/
int cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_save_buffer_entry = {
"save-buffer", "saveb",
"[-a] " CMD_BUFFER_SESSION_USAGE " path",
CMD_AFLAG|CMD_ARG1,
cmd_buffer_init,
cmd_buffer_parse,
cmd_save_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};
int
cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_buffer_data *data = self->data;
struct session *s;
struct paste_buffer *pb;
mode_t mask;
FILE *f;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (data->buffer == -1) {
if ((pb = paste_get_top(&s->buffers)) == NULL) {
ctx->error(ctx, "no buffers");
return (-1);
}
} else {
if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) {
ctx->error(ctx, "no buffer %d", data->buffer);
return (-1);
}
}
mask = umask(S_IRWXG | S_IRWXO);
if (data->flags & CMD_AFLAG)
f = fopen(data->arg, "ab");
else
f = fopen(data->arg, "wb");
if (f == NULL) {
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
return (-1);
}
if (fwrite(pb->data, 1, strlen(pb->data), f) != strlen(pb->data)) {
ctx->error(ctx, "%s: fwrite error", data->arg);
fclose(f);
return (-1);
}
fclose(f);
umask(mask);
return (0);
}

72
cmd-scroll-mode.c Normal file
View File

@ -0,0 +1,72 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Enter scroll mode.
*/
void cmd_scroll_mode_init(struct cmd *, int);
int cmd_scroll_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_scroll_mode_entry = {
"scroll-mode", NULL,
CMD_TARGET_WINDOW_USAGE,
CMD_UFLAG,
cmd_scroll_mode_init,
cmd_target_parse,
cmd_scroll_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
void
cmd_scroll_mode_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
switch (key) {
case KEYC_PPAGE:
data->flags |= CMD_UFLAG;
break;
}
}
int
cmd_scroll_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
window_pane_set_mode(wl->window->active, &window_scroll_mode);
if (data->flags & CMD_UFLAG)
window_scroll_pageup(wl->window->active);
return (0);
}

86
cmd-select-layout.c Normal file
View File

@ -0,0 +1,86 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Switch window to selected layout.
*/
void cmd_select_layout_init(struct cmd *, int);
int cmd_select_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_layout_entry = {
"select-layout", "selectl",
CMD_TARGET_WINDOW_USAGE " layout-name",
CMD_ARG1,
cmd_select_layout_init,
cmd_target_parse,
cmd_select_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
void
cmd_select_layout_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
switch (key) {
case KEYC_ADDESC('0'):
data->arg = xstrdup("manual-vertical");
break;
case KEYC_ADDESC('1'):
data->arg = xstrdup("even-horizontal");
break;
case KEYC_ADDESC('2'):
data->arg = xstrdup("even-vertical");
break;
case KEYC_ADDESC('9'):
data->arg = xstrdup("active-only");
break;
}
}
int
cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
int layout;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if ((layout = layout_lookup(data->arg)) == -1) {
ctx->error(ctx, "unknown or ambiguous layout: %s", data->arg);
return (-1);
}
if (layout_select(wl->window, layout) == 0)
ctx->info(ctx, "layout now: %s", layout_name(wl->window));
return (0);
}

69
cmd-select-pane.c Normal file
View File

@ -0,0 +1,69 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Select pane.
*/
int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp",
CMD_PANE_WINDOW_USAGE,
0,
cmd_pane_init,
cmd_pane_parse,
cmd_select_pane_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};
int
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_pane_data *data = self->data;
struct winlink *wl;
struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (wp->flags & PANE_HIDDEN) {
ctx->error(ctx, "pane %d is hidden", data->pane);
return (-1);
}
window_set_active_pane(wl->window, wp);
layout_refresh(wl->window, 1);
return (0);
}

93
cmd-select-prompt.c Normal file
View File

@ -0,0 +1,93 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Prompt for window index and select it.
*/
int cmd_select_prompt_exec(struct cmd *, struct cmd_ctx *);
int cmd_select_prompt_callback(void *, const char *);
const struct cmd_entry cmd_select_prompt_entry = {
"select-prompt", NULL,
CMD_TARGET_CLIENT_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_select_prompt_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_select_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
if (c->prompt_string != NULL)
return (0);
status_prompt_set(c, "index ", cmd_select_prompt_callback, c, 0);
return (0);
}
int
cmd_select_prompt_callback(void *data, const char *s)
{
struct client *c = data;
const char *errstr;
char msg[128];
u_int idx;
if (s == NULL)
return (0);
idx = strtonum(s, 0, UINT_MAX, &errstr);
if (errstr != NULL) {
xsnprintf(msg, sizeof msg, "Index %s: %s", errstr, s);
status_message_set(c, msg);
return (0);
}
if (winlink_find_by_index(&c->session->windows, idx) == NULL) {
xsnprintf(msg, sizeof msg,
"Window not found: %s:%d", c->session->name, idx);
status_message_set(c, msg);
return (0);
}
if (session_select(c->session, idx) == 0)
server_redraw_session(c->session);
recalculate_sizes();
return (0);
}

71
cmd-select-window.c Normal file
View File

@ -0,0 +1,71 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Select window by index.
*/
void cmd_select_window_init(struct cmd *, int);
int cmd_select_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_window_entry = {
"select-window", "selectw",
CMD_TARGET_WINDOW_USAGE,
0,
cmd_select_window_init,
cmd_target_parse,
cmd_select_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
void
cmd_select_window_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
xasprintf(&data->target, ":%d", key - '0');
}
int
cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct session *s;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1);
if (session_select(s, wl->idx) == 0)
server_redraw_session(s);
recalculate_sizes();
return (0);
}

184
cmd-send-keys.c Normal file
View File

@ -0,0 +1,184 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Send keys to client.
*/
int cmd_send_keys_parse(struct cmd *, int, char **, char **);
int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *);
void cmd_send_keys_send(struct cmd *, struct buffer *);
void cmd_send_keys_recv(struct cmd *, struct buffer *);
void cmd_send_keys_free(struct cmd *);
size_t cmd_send_keys_print(struct cmd *, char *, size_t);
struct cmd_send_keys_data {
char *target;
int idx;
u_int nkeys;
int *keys;
};
const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send",
"[-t target-window] key ...",
0,
NULL,
cmd_send_keys_parse,
cmd_send_keys_exec,
cmd_send_keys_send,
cmd_send_keys_recv,
cmd_send_keys_free,
cmd_send_keys_print
};
int
cmd_send_keys_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_send_keys_data *data;
int opt, key;
char *s;
self->data = data = xmalloc(sizeof *data);
data->target = NULL;
data->idx = -1;
data->nkeys = 0;
data->keys = NULL;
while ((opt = getopt(argc, argv, "t:")) != -1) {
switch (opt) {
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc == 0)
goto usage;
while (argc-- != 0) {
if ((key = key_string_lookup_string(*argv)) != KEYC_NONE) {
data->keys = xrealloc(
data->keys, data->nkeys + 1, sizeof *data->keys);
data->keys[data->nkeys++] = key;
} else {
for (s = *argv; *s != '\0'; s++) {
data->keys = xrealloc(data->keys,
data->nkeys + 1, sizeof *data->keys);
data->keys[data->nkeys++] = *s;
}
}
argv++;
}
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int
cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_send_keys_data *data = self->data;
struct winlink *wl;
u_int i;
if (data == NULL)
return (-1);
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
for (i = 0; i < data->nkeys; i++) {
window_pane_key(
wl->window->active, ctx->curclient, data->keys[i]);
}
return (0);
}
void
cmd_send_keys_send(struct cmd *self, struct buffer *b)
{
struct cmd_send_keys_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
buffer_write(b, data->keys, data->nkeys * sizeof *data->keys);
}
void
cmd_send_keys_recv(struct cmd *self, struct buffer *b)
{
struct cmd_send_keys_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->keys = xcalloc(data->nkeys, sizeof *data->keys);
buffer_read(b, data->keys, data->nkeys * sizeof *data->keys);
}
void
cmd_send_keys_free(struct cmd *self)
{
struct cmd_send_keys_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
xfree(data);
}
size_t
cmd_send_keys_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_send_keys_data *data = self->data;
size_t off = 0;
u_int i;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->idx != -1)
off += xsnprintf(buf + off, len - off, " -i %d", data->idx);
for (i = 0; i < data->nkeys; i++) {
if (off >= len)
break;
off += xsnprintf(buf + off,
len - off, " %s", key_string_lookup_key(data->keys[i]));
}
return (off);
}

57
cmd-send-prefix.c Normal file
View File

@ -0,0 +1,57 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Send prefix key as a key.
*/
int cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_send_prefix_entry = {
"send-prefix", NULL,
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_send_prefix_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct winlink *wl;
int key;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1);
key = options_get_number(&s->options, "prefix");
window_pane_key(wl->window->active, ctx->curclient, key);
return (0);
}

179
cmd-server-info.c Normal file
View File

@ -0,0 +1,179 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/utsname.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
/*
* Show various information about server.
*/
int cmd_server_info_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_server_info_entry = {
"server-info", "info",
"",
0,
NULL,
NULL,
cmd_server_info_exec,
NULL,
NULL,
NULL,
NULL
};
int
cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
struct tty_term *term;
struct client *c;
struct session *s;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct tty_code *code;
struct tty_term_code_entry *ent;
struct utsname un;
struct grid *gd;
u_int i, j, k;
char out[80];
char *tim;
time_t t;
u_int lines, ulines;
size_t size, usize;
tim = ctime(&start_time);
*strchr(tim, '\n') = '\0';
ctx->print(ctx, "pid %ld, started %s", (long) getpid(), tim);
ctx->print(ctx, "socket path %s, debug level %d%s",
socket_path, debug_level, be_quiet ? ", quiet" : "");
if (uname(&un) == 0) {
ctx->print(ctx, "system is %s %s %s %s",
un.sysname, un.release, un.version, un.machine);
}
if (cfg_file != NULL)
ctx->print(ctx, "configuration file is %s", cfg_file);
else
ctx->print(ctx, "configuration file not specified");
ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION);
ctx->print(ctx, "%u clients, %u sessions",
ARRAY_LENGTH(&clients), ARRAY_LENGTH(&sessions));
ctx->print(ctx, "");
ctx->print(ctx, "Clients:");
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
ctx->print(ctx, "%2d: %s (%d, %d): %s [%ux%u %s] "
"[flags=0x%x/0x%x]", i, c->tty.path, c->fd, c->tty.fd,
c->session->name, c->tty.sx, c->tty.sy, c->tty.termname,
c->flags, c->tty.flags);
}
ctx->print(ctx, "");
ctx->print(ctx, "Sessions: [%zu/%zu]",
sizeof (struct grid_cell), sizeof (struct grid_utf8));
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i);
if (s == NULL)
continue;
t = s->tv.tv_sec;
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] "
"[flags=0x%x]", i, s->name, winlink_count(&s->windows),
tim, s->sx, s->sy, s->flags);
RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window;
ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, "
"references=%u, layout=%u]", wl->idx, w->name,
w->sx, w->sy, w->flags, w->references,
w->layout);
j = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
lines = ulines = size = usize = 0;
gd = wp->base.grid;
for (k = 0; k < gd->hsize + gd->sy; k++) {
if (gd->data[k] != NULL) {
lines++;
size += gd->size[k] *
sizeof (**gd->data);
}
if (gd->udata[k] != NULL) {
ulines++;
usize += gd->usize[k] *
sizeof (**gd->udata);
}
}
ctx->print(ctx, "%6u: %s %lu %d %u/%u, %zu "
"bytes; UTF-8 %u/%u, %zu bytes", j,
wp->tty, (u_long) wp->pid, wp->fd, lines,
gd->hsize + gd->sy, size, ulines,
gd->hsize + gd->sy, usize);
j++;
}
}
}
ctx->print(ctx, "");
ctx->print(ctx, "Terminals:");
SLIST_FOREACH(term, &tty_terms, entry) {
ctx->print(ctx, "%s [references=%u, flags=0x%x]:",
term->name, term->references, term->flags);
for (i = 0; i < NTTYCODE; i++) {
ent = &tty_term_codes[i];
code = &term->codes[ent->code];
switch (code->type) {
case TTYCODE_NONE:
ctx->print(ctx, "%2u: %s: [missing]",
ent->code, ent->name);
break;
case TTYCODE_STRING:
clean_string(
code->value.string, out, sizeof out);
ctx->print(ctx, "%2u: %s: (string) %s",
ent->code, ent->name, out);
break;
case TTYCODE_NUMBER:
ctx->print(ctx, "%2u: %s: (number) %d",
ent->code, ent->name, code->value.number);
break;
case TTYCODE_FLAG:
ctx->print(ctx, "%2u: %s: (flag) %s",
ent->code, ent->name,
code->value.flag ? "true" : "false");
break;
}
}
}
ctx->print(ctx, "");
return (0);
}

64
cmd-set-buffer.c Normal file
View File

@ -0,0 +1,64 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Add or set a session paste buffer.
*/
int cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb",
CMD_BUFFER_SESSION_USAGE " data",
CMD_ARG1,
cmd_buffer_init,
cmd_buffer_parse,
cmd_set_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};
int
cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_buffer_data *data = self->data;
struct session *s;
u_int limit;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
limit = options_get_number(&s->options, "buffer-limit");
if (data->buffer == -1) {
paste_add(&s->buffers, xstrdup(data->arg), limit);
return (0);
}
if (paste_replace(&s->buffers, data->buffer, xstrdup(data->arg)) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer);
return (-1);
}
return (0);
}

169
cmd-set-option.c Normal file
View File

@ -0,0 +1,169 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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"
/*
* Set an option.
*/
int cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_option_entry = {
"set-option", "set",
CMD_OPTION_SESSION_USAGE,
CMD_GFLAG|CMD_UFLAG,
NULL,
cmd_option_parse,
cmd_set_option_exec,
cmd_option_send,
cmd_option_recv,
cmd_option_free,
cmd_option_print
};
const char *set_option_status_keys_list[] = {
"emacs", "vi", NULL
};
const char *set_option_bell_action_list[] = {
"none", "any", "current", NULL
};
const struct set_option_entry set_option_table[NSETOPTION] = {
{ "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list },
{ "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "default-command", SET_OPTION_STRING, 0, 0, NULL },
{ "default-path", SET_OPTION_STRING, 0, 0, NULL },
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "message-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "message-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "prefix", SET_OPTION_KEY, 0, 0, NULL },
{ "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
{ "set-titles", SET_OPTION_FLAG, 0, 0, NULL },
{ "status", SET_OPTION_FLAG, 0, 0, NULL },
{ "status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "status-keys", SET_OPTION_CHOICE, 0, 0, set_option_status_keys_list },
{ "status-left", SET_OPTION_STRING, 0, 0, NULL },
{ "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "status-right", SET_OPTION_STRING, 0, 0, NULL },
{ "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
};
int
cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_option_data *data = self->data;
struct session *s;
struct client *c;
struct options *oo;
const struct set_option_entry *entry;
u_int i;
if (data->flags & CMD_GFLAG)
oo = &global_options;
else {
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
oo = &s->options;
}
if (*data->option == '\0') {
ctx->error(ctx, "invalid option");
return (-1);
}
entry = NULL;
for (i = 0; i < NSETOPTION; i++) {
if (strncmp(set_option_table[i].name,
data->option, strlen(data->option)) != 0)
continue;
if (entry != NULL) {
ctx->error(ctx, "ambiguous option: %s", data->option);
return (-1);
}
entry = &set_option_table[i];
/* Bail now if an exact match. */
if (strcmp(entry->name, data->option) == 0)
break;
}
if (entry == NULL) {
ctx->error(ctx, "unknown option: %s", data->option);
return (-1);
}
if (data->flags & CMD_UFLAG) {
if (data->flags & CMD_GFLAG) {
ctx->error(ctx,
"can't unset global option: %s", entry->name);
return (-1);
}
if (data->value != NULL) {
ctx->error(ctx,
"value passed to unset option: %s", entry->name);
return (-1);
}
options_remove(oo, entry->name);
ctx->info(ctx, "unset option: %s", entry->name);
} else {
switch (entry->type) {
case SET_OPTION_STRING:
set_option_string(ctx, oo, entry, data->value);
break;
case SET_OPTION_NUMBER:
set_option_number(ctx, oo, entry, data->value);
break;
case SET_OPTION_KEY:
set_option_key(ctx, oo, entry, data->value);
break;
case SET_OPTION_COLOUR:
set_option_colour(ctx, oo, entry, data->value);
break;
case SET_OPTION_ATTRIBUTES:
set_option_attributes(ctx, oo, entry, data->value);
break;
case SET_OPTION_FLAG:
set_option_flag(ctx, oo, entry, data->value);
break;
case SET_OPTION_CHOICE:
set_option_choice(ctx, oo, entry, data->value);
break;
}
}
recalculate_sizes();
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL && c->session != NULL)
server_redraw_client(c);
}
return (0);
}

169
cmd-set-password.c Normal file
View File

@ -0,0 +1,169 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <pwd.h>
#include <unistd.h>
#include "tmux.h"
/*
* Set server password.
*/
int cmd_set_password_parse(struct cmd *, int, char **, char **);
int cmd_set_password_exec(struct cmd *, struct cmd_ctx *);
void cmd_set_password_send(struct cmd *, struct buffer *);
void cmd_set_password_recv(struct cmd *, struct buffer *);
void cmd_set_password_free(struct cmd *);
void cmd_set_password_init(struct cmd *, int);
size_t cmd_set_password_print(struct cmd *, char *, size_t);
struct cmd_set_password_data {
char *password;
int flag_encrypted;
};
const struct cmd_entry cmd_set_password_entry = {
"set-password", "pass",
"[-c] password",
0,
cmd_set_password_init,
cmd_set_password_parse,
cmd_set_password_exec,
cmd_set_password_send,
cmd_set_password_recv,
cmd_set_password_free,
cmd_set_password_print
};
void
cmd_set_password_init(struct cmd *self, unused int arg)
{
struct cmd_set_password_data *data;
self->data = data = xmalloc(sizeof *data);
data->password = NULL;
data->flag_encrypted = 0;
}
int
cmd_set_password_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_set_password_data *data;
int opt;
char *out;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "c")) != -1) {
switch (opt) {
case 'c':
data->flag_encrypted = 1;
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 1)
goto usage;
if (!data->flag_encrypted) {
if ((out = crypt(argv[0], "$1")) != NULL)
data->password = xstrdup(out);
} else
data->password = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int
cmd_set_password_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_set_password_data *data = self->data;
if (data->password == NULL) {
ctx->error(ctx, "failed to encrypt password");
return (-1);
}
if (server_password != NULL)
xfree(server_password);
if (*data->password == '\0')
server_password = NULL;
else
server_password = xstrdup(data->password);
log_debug("pw now %s", server_password);
return (0);
}
void
cmd_set_password_send(struct cmd *self, struct buffer *b)
{
struct cmd_set_password_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->password);
}
void
cmd_set_password_recv(struct cmd *self, struct buffer *b)
{
struct cmd_set_password_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->password = cmd_recv_string(b);
}
void
cmd_set_password_free(struct cmd *self)
{
struct cmd_set_password_data *data = self->data;
if (data->password != NULL)
xfree(data->password);
xfree(data);
}
size_t
cmd_set_password_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_set_password_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_encrypted)
off += xsnprintf(buf + off, len - off, " -c");
if (off < len && data->password != NULL)
off += xsnprintf(buf + off, len - off, " password");
return (off);
}

170
cmd-set-window-option.c Normal file
View File

@ -0,0 +1,170 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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"
/*
* Set a window option.
*/
int cmd_set_window_option_parse(struct cmd *, int, char **, char **);
int cmd_set_window_option_exec(struct cmd *, struct cmd_ctx *);
void cmd_set_window_option_send(struct cmd *, struct buffer *);
void cmd_set_window_option_recv(struct cmd *, struct buffer *);
void cmd_set_window_option_free(struct cmd *);
size_t cmd_set_window_option_print(struct cmd *, char *, size_t);
const struct cmd_entry cmd_set_window_option_entry = {
"set-window-option", "setw",
CMD_OPTION_WINDOW_USAGE,
CMD_GFLAG|CMD_UFLAG,
NULL,
cmd_option_parse,
cmd_set_window_option_exec,
cmd_option_send,
cmd_option_recv,
cmd_option_free,
cmd_option_print
};
const char *set_option_mode_keys_list[] = {
"emacs", "vi", NULL
};
const char *set_option_clock_mode_style_list[] = {
"12", "24", NULL
};
const struct set_option_entry set_window_option_table[NSETWINDOWOPTION] = {
{ "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL },
{ "automatic-rename", SET_OPTION_FLAG, 0, 0, NULL },
{ "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL },
{ "clock-mode-style",
SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list },
{ "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "main-pane-width", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "mode-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "mode-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list },
{ "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL },
{ "monitor-content", SET_OPTION_STRING, 0, 0, NULL },
{ "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
{ "utf8", SET_OPTION_FLAG, 0, 0, NULL },
{ "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL },
};
int
cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_option_data *data = self->data;
struct winlink *wl;
struct client *c;
struct options *oo;
const struct set_option_entry *entry;
u_int i;
if (data->flags & CMD_GFLAG)
oo = &global_window_options;
else {
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
oo = &wl->window->options;
}
if (*data->option == '\0') {
ctx->error(ctx, "invalid option");
return (-1);
}
entry = NULL;
for (i = 0; i < NSETWINDOWOPTION; i++) {
if (strncmp(set_window_option_table[i].name,
data->option, strlen(data->option)) != 0)
continue;
if (entry != NULL) {
ctx->error(ctx, "ambiguous option: %s", data->option);
return (-1);
}
entry = &set_window_option_table[i];
/* Bail now if an exact match. */
if (strcmp(entry->name, data->option) == 0)
break;
}
if (entry == NULL) {
ctx->error(ctx, "unknown option: %s", data->option);
return (-1);
}
if (data->flags & CMD_UFLAG) {
if (data->flags & CMD_GFLAG) {
ctx->error(ctx,
"can't unset global option: %s", entry->name);
return (-1);
}
if (data->value != NULL) {
ctx->error(ctx,
"value passed to unset option: %s", entry->name);
return (-1);
}
options_remove(oo, entry->name);
ctx->info(ctx, "unset option: %s", entry->name);
} else {
switch (entry->type) {
case SET_OPTION_STRING:
set_option_string(ctx, oo, entry, data->value);
break;
case SET_OPTION_NUMBER:
set_option_number(ctx, oo, entry, data->value);
break;
case SET_OPTION_KEY:
set_option_key(ctx, oo, entry, data->value);
break;
case SET_OPTION_COLOUR:
set_option_colour(ctx, oo, entry, data->value);
break;
case SET_OPTION_ATTRIBUTES:
set_option_attributes(ctx, oo, entry, data->value);
break;
case SET_OPTION_FLAG:
set_option_flag(ctx, oo, entry, data->value);
break;
case SET_OPTION_CHOICE:
set_option_choice(ctx, oo, entry, data->value);
break;
}
}
recalculate_sizes();
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL && c->session != NULL)
server_redraw_client(c);
}
return (0);
}

89
cmd-show-buffer.c Normal file
View File

@ -0,0 +1,89 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Show a session paste buffer.
*/
int cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_buffer_entry = {
"show-buffer", "showb",
CMD_BUFFER_SESSION_USAGE,
0,
cmd_buffer_init,
cmd_buffer_parse,
cmd_show_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free,
cmd_buffer_print
};
int
cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_buffer_data *data = self->data;
struct session *s;
struct paste_buffer *pb;
u_int size;
char *buf, *ptr;
size_t len;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (data->buffer == -1) {
if ((pb = paste_get_top(&s->buffers)) == NULL) {
ctx->error(ctx, "no buffers");
return (-1);
}
} else if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) {
ctx->error(ctx, "no buffer %d", data->buffer);
return (-1);
}
if (pb != NULL) {
size = s->sx;
buf = xmalloc(size + 1);
len = 0;
ptr = pb->data;
do {
buf[len++] = *ptr++;
if (len == size) {
buf[len] = '\0';
ctx->print(ctx, buf);
len = 0;
}
} while (*ptr != '\0');
buf[len] = '\0';
ctx->print(ctx, buf);
}
return (0);
}

110
cmd-show-options.c Normal file
View File

@ -0,0 +1,110 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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"
/*
* Show options.
*/
int cmd_show_options_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_options_entry = {
"show-options", "show",
"[-g] " CMD_TARGET_SESSION_USAGE,
CMD_GFLAG,
cmd_target_init,
cmd_target_parse,
cmd_show_options_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct options *oo;
const struct set_option_entry *entry;
u_int i;
char *vs;
long long vn;
if (data->flags & CMD_GFLAG)
oo = &global_options;
else {
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
oo = &s->options;
}
for (i = 0; i < NSETOPTION; i++) {
entry = &set_option_table[i];
if (options_find1(oo, entry->name) == NULL)
continue;
switch (entry->type) {
case SET_OPTION_STRING:
vs = options_get_string(oo, entry->name);
ctx->print(ctx, "%s \"%s\"", entry->name, vs);
break;
case SET_OPTION_NUMBER:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %lld", entry->name, vn);
break;
case SET_OPTION_KEY:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %s",
entry->name, key_string_lookup_key(vn));
break;
case SET_OPTION_COLOUR:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %s",
entry->name, colour_tostring(vn));
break;
case SET_OPTION_ATTRIBUTES:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %s",
entry->name, attributes_tostring(vn));
break;
case SET_OPTION_FLAG:
vn = options_get_number(oo, entry->name);
if (vn)
ctx->print(ctx, "%s on", entry->name);
else
ctx->print(ctx, "%s off", entry->name);
break;
case SET_OPTION_CHOICE:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %s",
entry->name, entry->choices[vn]);
break;
}
}
return (0);
}

110
cmd-show-window-options.c Normal file
View File

@ -0,0 +1,110 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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"
/*
* Show window options.
*/
int cmd_show_window_options_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_window_options_entry = {
"show-window-options", "showw",
"[-g] " CMD_TARGET_WINDOW_USAGE,
CMD_GFLAG,
cmd_target_init,
cmd_target_parse,
cmd_show_window_options_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_show_window_options_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct options *oo;
const struct set_option_entry *entry;
u_int i;
char *vs;
long long vn;
if (data->flags & CMD_GFLAG)
oo = &global_window_options;
else {
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
oo = &wl->window->options;
}
for (i = 0; i < NSETWINDOWOPTION; i++) {
entry = &set_window_option_table[i];
if (options_find1(oo, entry->name) == NULL)
continue;
switch (entry->type) {
case SET_OPTION_STRING:
vs = options_get_string(oo, entry->name);
ctx->print(ctx, "%s \"%s\"", entry->name, vs);
break;
case SET_OPTION_NUMBER:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %lld", entry->name, vn);
break;
case SET_OPTION_KEY:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %s",
entry->name, key_string_lookup_key(vn));
break;
case SET_OPTION_COLOUR:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %s",
entry->name, colour_tostring(vn));
break;
case SET_OPTION_ATTRIBUTES:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %s",
entry->name, attributes_tostring(vn));
break;
case SET_OPTION_FLAG:
vn = options_get_number(oo, entry->name);
if (vn)
ctx->print(ctx, "%s on", entry->name);
else
ctx->print(ctx, "%s off", entry->name);
break;
case SET_OPTION_CHOICE:
vn = options_get_number(oo, entry->name);
ctx->print(ctx, "%s %s",
entry->name, entry->choices[vn]);
break;
}
}
return (0);
}

147
cmd-source-file.c Normal file
View File

@ -0,0 +1,147 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
*
* 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 "tmux.h"
/*
* Sources a configuration file.
*/
int cmd_source_file_parse(struct cmd *, int, char **, char **);
int cmd_source_file_exec(struct cmd *, struct cmd_ctx *);
void cmd_source_file_send(struct cmd *, struct buffer *);
void cmd_source_file_recv(struct cmd *, struct buffer *);
void cmd_source_file_free(struct cmd *);
void cmd_source_file_init(struct cmd *, int);
size_t cmd_source_file_print(struct cmd *, char *, size_t);
struct cmd_source_file_data {
char *path;
};
const struct cmd_entry cmd_source_file_entry = {
"source-file", "source",
"path",
0,
cmd_source_file_init,
cmd_source_file_parse,
cmd_source_file_exec,
cmd_source_file_send,
cmd_source_file_recv,
cmd_source_file_free,
cmd_source_file_print
};
void
cmd_source_file_init(struct cmd *self, unused int arg)
{
struct cmd_source_file_data *data;
self->data = data = xmalloc(sizeof *data);
data->path = NULL;
}
int
cmd_source_file_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_source_file_data *data;
int opt;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "")) != -1) {
switch (opt) {
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 1)
goto usage;
data->path = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int
cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_source_file_data *data = self->data;
char *cause;
if (load_cfg(data->path, &cause) != 0) {
ctx->error(ctx, "%s", cause);
xfree(cause);
return (-1);
}
return (0);
}
void
cmd_source_file_send(struct cmd *self, struct buffer *b)
{
struct cmd_source_file_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->path);
}
void
cmd_source_file_recv(struct cmd *self, struct buffer *b)
{
struct cmd_source_file_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->path = cmd_recv_string(b);
}
void
cmd_source_file_free(struct cmd *self)
{
struct cmd_source_file_data *data = self->data;
if (data->path != NULL)
xfree(data->path);
xfree(data);
}
size_t
cmd_source_file_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_source_file_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->path != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->path);
return (off);
}

235
cmd-split-window.c Normal file
View File

@ -0,0 +1,235 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <unistd.h>
#include "tmux.h"
/*
* Split a window (add a new pane).
*/
int cmd_split_window_parse(struct cmd *, int, char **, char **);
int cmd_split_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_split_window_send(struct cmd *, struct buffer *);
void cmd_split_window_recv(struct cmd *, struct buffer *);
void cmd_split_window_free(struct cmd *);
void cmd_split_window_init(struct cmd *, int);
size_t cmd_split_window_print(struct cmd *, char *, size_t);
struct cmd_split_window_data {
char *target;
char *cmd;
int flag_detached;
int percentage;
int lines;
};
const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw",
"[-d] [-p percentage|-l lines] [-t target-window] [command]",
0,
cmd_split_window_init,
cmd_split_window_parse,
cmd_split_window_exec,
cmd_split_window_send,
cmd_split_window_recv,
cmd_split_window_free,
cmd_split_window_print
};
void
cmd_split_window_init(struct cmd *self, unused int arg)
{
struct cmd_split_window_data *data;
self->data = data = xmalloc(sizeof *data);
data->target = NULL;
data->cmd = NULL;
data->flag_detached = 0;
data->percentage = -1;
data->lines = -1;
}
int
cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_split_window_data *data;
int opt, n;
const char *errstr;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "dl:p:t:")) != -1) {
switch (opt) {
case 'd':
data->flag_detached = 1;
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'l':
if (data->percentage == -1 && data->lines == -1) {
n = strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "lines %s", errstr);
goto error;
}
data->lines = n;
}
break;
case 'p':
if (data->lines == -1 && data->percentage == -1) {
n = strtonum(optarg, 1, 100, &errstr);
if (errstr != NULL) {
xasprintf(
cause, "percentage %s", errstr);
goto error;
}
data->percentage = n;
}
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0 && argc != 1)
goto usage;
if (argc == 1)
data->cmd = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
int
cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_split_window_data *data = self->data;
struct session *s;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
const char **env;
char *cmd, *cwd, *cause;
u_int hlimit, lines;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1);
w = wl->window;
env = server_fill_environ(s);
cmd = data->cmd;
if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command");
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
cwd = options_get_string(&global_options, "default-path");
else
cwd = ctx->cmdclient->cwd;
lines = -1;
if (data->lines != -1)
lines = data->lines;
else if (data->percentage != -1)
lines = (w->active->sy * data->percentage) / 100;
hlimit = options_get_number(&s->options, "history-limit");
wp = window_add_pane(w, lines, cmd, cwd, env, hlimit, &cause);
if (wp == NULL) {
ctx->error(ctx, "create pane failed: %s", cause);
xfree(cause);
return (-1);
}
server_redraw_window(w);
if (!data->flag_detached) {
window_set_active_pane(w, wp);
session_select(s, wl->idx);
server_redraw_session(s);
} else
server_status_session(s);
layout_refresh(w, 0);
return (0);
}
void
cmd_split_window_send(struct cmd *self, struct buffer *b)
{
struct cmd_split_window_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->cmd);
}
void
cmd_split_window_recv(struct cmd *self, struct buffer *b)
{
struct cmd_split_window_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
}
void
cmd_split_window_free(struct cmd *self)
{
struct cmd_split_window_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->cmd != NULL)
xfree(data->cmd);
xfree(data);
}
size_t
cmd_split_window_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_split_window_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, " -d");
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->cmd);
return (off);
}

46
cmd-start-server.c Normal file
View File

@ -0,0 +1,46 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Start the server and do nothing else.
*/
int cmd_start_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_start_server_entry = {
"start-server", "start",
"",
CMD_STARTSERVER,
NULL,
NULL,
cmd_start_server_exec,
NULL,
NULL,
NULL,
NULL
};
int
cmd_start_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx)
{
return (0);
}

309
cmd-string.c Normal file
View File

@ -0,0 +1,309 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "tmux.h"
/*
* Parse a command from a string.
*/
int cmd_string_getc(const char *, size_t *);
void cmd_string_ungetc(const char *, size_t *);
char *cmd_string_string(const char *, size_t *, char, int);
char *cmd_string_variable(const char *, size_t *);
int
cmd_string_getc(const char *s, size_t *p)
{
if (s[*p] == '\0')
return (EOF);
return (s[(*p)++]);
}
void
cmd_string_ungetc(unused const char *s, size_t *p)
{
(*p)--;
}
/*
* Parse command string. Returns -1 on error. If returning -1, cause is error
* string, or NULL for empty command.
*/
int
cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
{
size_t p;
int ch, argc, rval, have_arg;
char **argv, *buf, *t, *u;
size_t len;
if ((t = strchr(s, ' ')) == NULL && (t = strchr(s, '\t')) == NULL)
t = strchr(s, '\0');
if ((u = strchr(s, '=')) != NULL && u < t) {
if (putenv((char *) s) != 0) {
xasprintf(cause, "assignment failed: %s", s);
return (-1);
}
*cmdlist = NULL;
return (0);
}
argv = NULL;
argc = 0;
buf = NULL;
len = 0;
have_arg = 0;
*cause = NULL;
*cmdlist = NULL;
rval = -1;
p = 0;
for (;;) {
ch = cmd_string_getc(s, &p);
switch (ch) {
case '\'':
if ((t = cmd_string_string(s, &p, '\'', 0)) == NULL)
goto error;
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
xfree(t);
have_arg = 1;
break;
case '"':
if ((t = cmd_string_string(s, &p, '"', 1)) == NULL)
goto error;
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
xfree(t);
have_arg = 1;
break;
case '$':
if ((t = cmd_string_variable(s, &p)) == NULL)
goto error;
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
have_arg = 1;
break;
case '#':
/* Comment: discard rest of line. */
while ((ch = cmd_string_getc(s, &p)) != EOF)
;
/* FALLTHROUGH */
case EOF:
case ' ':
case '\t':
if (have_arg) {
buf = xrealloc(buf, 1, len + 1);
buf[len] = '\0';
argv = xrealloc(argv, argc + 1, sizeof *argv);
argv[argc++] = buf;
buf = NULL;
len = 0;
have_arg = 0;
}
if (ch != EOF)
break;
if (argc == 0)
goto out;
*cmdlist = cmd_list_parse(argc, argv, cause);
if (*cmdlist == NULL)
goto out;
do
xfree(argv[argc - 1]);
while (--argc > 0);
rval = 0;
goto out;
default:
if (len >= SIZE_MAX - 2)
goto error;
buf = xrealloc(buf, 1, len + 1);
buf[len++] = ch;
have_arg = 1;
break;
}
}
error:
xasprintf(cause, "invalid or unknown command: %s", s);
out:
if (buf != NULL)
xfree(buf);
while (--argc >= 0)
xfree(argv[argc]);
if (argv != NULL)
xfree(argv);
return (rval);
}
char *
cmd_string_string(const char *s, size_t *p, char endch, int esc)
{
int ch;
char *buf, *t;
size_t len;
buf = NULL;
len = 0;
while ((ch = cmd_string_getc(s, p)) != endch) {
switch (ch) {
case EOF:
goto error;
case '\\':
if (!esc)
break;
switch (ch = cmd_string_getc(s, p)) {
case EOF:
goto error;
case 'r':
ch = '\r';
break;
case 'n':
ch = '\n';
break;
case 't':
ch = '\t';
break;
}
break;
case '$':
if (!esc)
break;
if ((t = cmd_string_variable(s, p)) == NULL)
goto error;
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
continue;
}
if (len >= SIZE_MAX - 2)
goto error;
buf = xrealloc(buf, 1, len + 1);
buf[len++] = ch;
}
buf = xrealloc(buf, 1, len + 1);
buf[len] = '\0';
return (buf);
error:
if (buf != NULL)
xfree(buf);
return (NULL);
}
char *
cmd_string_variable(const char *s, size_t *p)
{
int ch, fch;
char *buf, *t;
size_t len;
#define cmd_string_first(ch) ((ch) == '_' || \
((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z'))
#define cmd_string_other(ch) ((ch) == '_' || \
((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z') || \
((ch) >= '0' && (ch) <= '9'))
buf = NULL;
len = 0;
fch = EOF;
switch (ch = cmd_string_getc(s, p)) {
case EOF:
goto error;
case '{':
fch = '{';
ch = cmd_string_getc(s, p);
if (!cmd_string_first(ch))
goto error;
/* FALLTHROUGH */
default:
if (!cmd_string_first(ch)) {
xasprintf(&t, "$%c", ch);
return (t);
}
buf = xrealloc(buf, 1, len + 1);
buf[len++] = ch;
for (;;) {
ch = cmd_string_getc(s, p);
if (ch == EOF || !cmd_string_other(ch))
break;
else {
if (len >= SIZE_MAX - 3)
goto error;
buf = xrealloc(buf, 1, len + 1);
buf[len++] = ch;
}
}
}
if (fch == '{' && ch != '}')
goto error;
if (ch != EOF && fch != '{')
cmd_string_ungetc(s, p); /* ch */
buf = xrealloc(buf, 1, len + 1);
buf[len] = '\0';
if ((t = getenv(buf)) == NULL) {
xfree(buf);
return (xstrdup(""));
}
xfree(buf);
return (xstrdup(t));
error:
if (buf != NULL)
xfree(buf);
return (NULL);
}

64
cmd-suspend-client.c Normal file
View File

@ -0,0 +1,64 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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"
/*
* Suspend client with SIGTSTP.
*/
int cmd_suspend_client_exec(struct cmd *, struct cmd_ctx *);
struct cmd_suspend_client_data {
char *name;
char *target;
};
const struct cmd_entry cmd_suspend_client_entry = {
"suspend-client", "suspendc",
"[-c target-client]",
0,
cmd_target_init,
cmd_target_parse,
cmd_suspend_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_suspend_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
tty_stop_tty(&c->tty);
c->flags |= CLIENT_SUSPENDED;
server_write_client(c, MSG_SUSPEND, NULL, 0);
return (0);
}

285
cmd-swap-pane.c Normal file
View File

@ -0,0 +1,285 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Swap two panes.
*/
int cmd_swap_pane_parse(struct cmd *, int, char **, char **);
int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_swap_pane_send(struct cmd *, struct buffer *);
void cmd_swap_pane_recv(struct cmd *, struct buffer *);
void cmd_swap_pane_free(struct cmd *);
void cmd_swap_pane_init(struct cmd *, int);
size_t cmd_swap_pane_print(struct cmd *, char *, size_t);
struct cmd_swap_pane_data {
char *target;
int src;
int dst;
int flag_detached;
int flag_up;
int flag_down;
};
const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp",
"[-dDU] [-t target-window] [-p src-index] [-q dst-index]",
0,
cmd_swap_pane_init,
cmd_swap_pane_parse,
cmd_swap_pane_exec,
cmd_swap_pane_send,
cmd_swap_pane_recv,
cmd_swap_pane_free,
cmd_swap_pane_print
};
void
cmd_swap_pane_init(struct cmd *self, int key)
{
struct cmd_swap_pane_data *data;
self->data = data = xmalloc(sizeof *data);
data->target = NULL;
data->src = -1;
data->dst = -1;
data->flag_detached = 0;
data->flag_up = 0;
data->flag_down = 0;
switch (key) {
case '{':
data->flag_up = 1;
break;
case '}':
data->flag_down = 1;
break;
}
}
int
cmd_swap_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_swap_pane_data *data;
int opt, n;
const char *errstr;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "dDt:p:q:U")) != -1) {
switch (opt) {
case 'd':
data->flag_detached = 1;
break;
case 'D':
data->flag_up = 0;
data->flag_down = 1;
data->dst = -1;
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'p':
if (data->src == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "src %s", errstr);
goto error;
}
data->src = n;
}
break;
case 'q':
if (data->dst == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "dst %s", errstr);
goto error;
}
data->dst = n;
}
data->flag_up = 0;
data->flag_down = 0;
break;
case 'U':
data->flag_up = 1;
data->flag_down = 0;
data->dst = -1;
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
int
cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_swap_pane_data *data = self->data;
struct winlink *wl;
struct window *w;
struct window_pane *tmp_wp, *src_wp, *dst_wp;
u_int xx, yy;
if (data == NULL)
return (0);
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
w = wl->window;
if (data->src == -1)
src_wp = w->active;
else {
src_wp = window_pane_at_index(w, data->src);
if (src_wp == NULL) {
ctx->error(ctx, "no pane: %d", data->src);
return (-1);
}
}
if (data->dst == -1)
dst_wp = w->active;
else {
dst_wp = window_pane_at_index(w, data->dst);
if (dst_wp == NULL) {
ctx->error(ctx, "no pane: %d", data->dst);
return (-1);
}
}
if (data->dst == -1 && data->flag_up) {
if ((dst_wp = TAILQ_PREV(src_wp, window_panes, entry)) == NULL)
dst_wp = TAILQ_LAST(&w->panes, window_panes);
}
if (data->dst == -1 && data->flag_down) {
if ((dst_wp = TAILQ_NEXT(src_wp, entry)) == NULL)
dst_wp = TAILQ_FIRST(&w->panes);
}
if (src_wp == dst_wp)
return (0);
tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
TAILQ_REMOVE(&w->panes, dst_wp, entry);
TAILQ_REPLACE(&w->panes, src_wp, dst_wp, entry);
if (tmp_wp == src_wp)
tmp_wp = dst_wp;
if (tmp_wp == NULL)
TAILQ_INSERT_HEAD(&w->panes, src_wp, entry);
else
TAILQ_INSERT_AFTER(&w->panes, tmp_wp, src_wp, entry);
xx = src_wp->xoff;
yy = src_wp->yoff;
src_wp->xoff = dst_wp->xoff;
src_wp->yoff = dst_wp->yoff;
dst_wp->xoff = xx;
dst_wp->yoff = yy;
xx = src_wp->sx;
yy = src_wp->sy;
window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy);
window_pane_resize(dst_wp, xx, yy);
if (!data->flag_detached) {
window_set_active_pane(w, dst_wp);
layout_refresh(w, 0);
}
return (0);
}
void
cmd_swap_pane_send(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
}
void
cmd_swap_pane_recv(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
}
void
cmd_swap_pane_free(struct cmd *self)
{
struct cmd_swap_pane_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
xfree(data);
}
size_t
cmd_swap_pane_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_swap_pane_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len &&
(data->flag_down || data->flag_up || data->flag_detached)) {
off += xsnprintf(buf + off, len - off, " -");
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, "d");
if (off < len && data->flag_up)
off += xsnprintf(buf + off, len - off, "D");
if (off < len && data->flag_down)
off += xsnprintf(buf + off, len - off, "U");
}
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->src != -1)
off += xsnprintf(buf + off, len - off, " -p %d", data->src);
if (off < len && data->dst != -1)
off += xsnprintf(buf + off, len - off, " -q %d", data->dst);
return (off);
}

75
cmd-swap-window.c Normal file
View File

@ -0,0 +1,75 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Swap one window with another.
*/
int cmd_swap_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_swap_window_entry = {
"swap-window", "swapw",
"[-d] " CMD_SRCDST_WINDOW_USAGE,
CMD_DFLAG,
cmd_srcdst_init,
cmd_srcdst_parse,
cmd_swap_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free,
cmd_srcdst_print
};
int
cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_srcdst_data *data = self->data;
struct session *src, *dst;
struct winlink *wl_src, *wl_dst;
struct window *w;
if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL)
return (-1);
if ((wl_dst = cmd_find_window(ctx, data->dst, &dst)) == NULL)
return (-1);
if (wl_dst->window == wl_src->window)
return (0);
w = wl_dst->window;
wl_dst->window = wl_src->window;
wl_src->window = w;
if (!(data->flags & CMD_DFLAG)) {
session_select(dst, wl_dst->idx);
if (src != dst)
session_select(src, wl_src->idx);
}
server_redraw_session(src);
if (src != dst)
server_redraw_session(dst);
recalculate_sizes();
return (0);
}

161
cmd-switch-client.c Normal file
View File

@ -0,0 +1,161 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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"
/*
* Switch client to a different session.
*/
int cmd_switch_client_parse(struct cmd *, int, char **, char **);
int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_switch_client_send(struct cmd *, struct buffer *);
void cmd_switch_client_recv(struct cmd *, struct buffer *);
void cmd_switch_client_free(struct cmd *);
size_t cmd_switch_client_print(struct cmd *, char *, size_t);
struct cmd_switch_client_data {
char *name;
char *target;
};
const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc",
"[-c target-client] [-t target-session]",
0,
NULL,
cmd_switch_client_parse,
cmd_switch_client_exec,
cmd_switch_client_send,
cmd_switch_client_recv,
cmd_switch_client_free,
cmd_switch_client_print
};
int
cmd_switch_client_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_switch_client_data *data;
int opt;
self->data = data = xmalloc(sizeof *data);
data->name = NULL;
data->target = NULL;
while ((opt = getopt(argc, argv, "c:t:")) != -1) {
switch (opt) {
case 'c':
data->name = xstrdup(optarg);
break;
case 't':
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int
cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_switch_client_data *data = self->data;
struct client *c;
struct session *s;
if (data == NULL)
return (0);
if ((c = cmd_find_client(ctx, data->name)) == NULL)
return (-1);
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
c->session = s;
recalculate_sizes();
server_redraw_client(c);
return (0);
}
void
cmd_switch_client_send(struct cmd *self, struct buffer *b)
{
struct cmd_switch_client_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->name);
cmd_send_string(b, data->target);
}
void
cmd_switch_client_recv(struct cmd *self, struct buffer *b)
{
struct cmd_switch_client_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->name = cmd_recv_string(b);
data->target = cmd_recv_string(b);
}
void
cmd_switch_client_free(struct cmd *self)
{
struct cmd_switch_client_data *data = self->data;
if (data->name != NULL)
xfree(data->name);
if (data->target != NULL)
xfree(data->target);
xfree(data);
}
size_t
cmd_switch_client_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_switch_client_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->name != NULL)
off += cmd_prarg(buf + off, len - off, " -c ", data->name);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
return (off);
}

120
cmd-unbind-key.c Normal file
View File

@ -0,0 +1,120 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Unbind key from command.
*/
int cmd_unbind_key_parse(struct cmd *, int, char **, char **);
int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_unbind_key_send(struct cmd *, struct buffer *);
void cmd_unbind_key_recv(struct cmd *, struct buffer *);
void cmd_unbind_key_free(struct cmd *);
struct cmd_unbind_key_data {
int key;
};
const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind",
"key",
0,
NULL,
cmd_unbind_key_parse,
cmd_unbind_key_exec,
cmd_unbind_key_send,
cmd_unbind_key_recv,
cmd_unbind_key_free,
NULL
};
int
cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_unbind_key_data *data;
int opt;
self->data = data = xmalloc(sizeof *data);
while ((opt = getopt(argc, argv, "")) != -1) {
switch (opt) {
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 1)
goto usage;
if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) {
xasprintf(cause, "unknown key: %s", argv[0]);
goto error;
}
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
xfree(data);
return (-1);
}
int
cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
{
struct cmd_unbind_key_data *data = self->data;
if (data == NULL)
return (0);
key_bindings_remove(data->key);
return (0);
}
void
cmd_unbind_key_send(struct cmd *self, struct buffer *b)
{
struct cmd_unbind_key_data *data = self->data;
buffer_write(b, data, sizeof *data);
}
void
cmd_unbind_key_recv(struct cmd *self, struct buffer *b)
{
struct cmd_unbind_key_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
}
void
cmd_unbind_key_free(struct cmd *self)
{
struct cmd_unbind_key_data *data = self->data;
xfree(data);
}

74
cmd-unlink-window.c Normal file
View File

@ -0,0 +1,74 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Unlink a window, unless it would be destroyed by doing so (only one link).
*/
int cmd_unlink_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_unlink_window_entry = {
"unlink-window", "unlinkw",
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_unlink_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct session *s;
struct client *c;
u_int i;
int destroyed;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1);
if (wl->window->references == 1) {
ctx->error(ctx, "window is only linked to one session");
return (-1);
}
destroyed = session_detach(s, wl);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != s)
continue;
if (destroyed) {
c->session = NULL;
server_write_client(c, MSG_EXIT, NULL, 0);
} else
server_redraw_client(c);
}
recalculate_sizes();
return (0);
}

61
cmd-up-pane.c Normal file
View File

@ -0,0 +1,61 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move up a pane.
*/
int cmd_up_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_up_pane_entry = {
"up-pane", "upp",
CMD_TARGET_WINDOW_USAGE,
0,
cmd_target_init,
cmd_target_parse,
cmd_up_pane_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free,
cmd_target_print
};
int
cmd_up_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window *w;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
w = wl->window;
do {
w->active = TAILQ_PREV(w->active, window_panes, entry);
if (w->active == NULL)
w->active = TAILQ_LAST(&w->panes, window_panes);
layout_refresh(w, 1);
} while (w->active->flags & PANE_HIDDEN);
return (0);
}

393
cmd.c Normal file
View File

@ -0,0 +1,393 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
const struct cmd_entry *cmd_table[] = {
&cmd_attach_session_entry,
&cmd_bind_key_entry,
&cmd_break_pane_entry,
&cmd_choose_session_entry,
&cmd_choose_window_entry,
&cmd_clear_history_entry,
&cmd_clock_mode_entry,
&cmd_command_prompt_entry,
&cmd_confirm_before_entry,
&cmd_copy_buffer_entry,
&cmd_copy_mode_entry,
&cmd_delete_buffer_entry,
&cmd_detach_client_entry,
&cmd_down_pane_entry,
&cmd_find_window_entry,
&cmd_has_session_entry,
&cmd_kill_pane_entry,
&cmd_kill_server_entry,
&cmd_kill_session_entry,
&cmd_kill_window_entry,
&cmd_last_window_entry,
&cmd_link_window_entry,
&cmd_list_buffers_entry,
&cmd_list_clients_entry,
&cmd_list_commands_entry,
&cmd_list_keys_entry,
&cmd_list_sessions_entry,
&cmd_list_windows_entry,
&cmd_load_buffer_entry,
&cmd_lock_server_entry,
&cmd_move_window_entry,
&cmd_new_session_entry,
&cmd_new_window_entry,
&cmd_next_layout_entry,
&cmd_next_window_entry,
&cmd_paste_buffer_entry,
&cmd_previous_layout_entry,
&cmd_previous_window_entry,
&cmd_refresh_client_entry,
&cmd_rename_session_entry,
&cmd_rename_window_entry,
&cmd_resize_pane_entry,
&cmd_respawn_window_entry,
&cmd_rotate_window_entry,
&cmd_save_buffer_entry,
&cmd_scroll_mode_entry,
&cmd_select_layout_entry,
&cmd_select_pane_entry,
&cmd_select_prompt_entry,
&cmd_select_window_entry,
&cmd_send_keys_entry,
&cmd_send_prefix_entry,
&cmd_server_info_entry,
&cmd_set_buffer_entry,
&cmd_set_option_entry,
&cmd_set_password_entry,
&cmd_set_window_option_entry,
&cmd_show_buffer_entry,
&cmd_show_options_entry,
&cmd_show_window_options_entry,
&cmd_source_file_entry,
&cmd_split_window_entry,
&cmd_start_server_entry,
&cmd_suspend_client_entry,
&cmd_swap_pane_entry,
&cmd_swap_window_entry,
&cmd_switch_client_entry,
&cmd_unbind_key_entry,
&cmd_unlink_window_entry,
&cmd_up_pane_entry,
NULL
};
struct cmd *
cmd_parse(int argc, char **argv, char **cause)
{
const struct cmd_entry **entryp, *entry;
struct cmd *cmd;
char s[BUFSIZ];
int opt;
*cause = NULL;
if (argc == 0)
return (NULL);
entry = NULL;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if ((*entryp)->alias != NULL &&
strcmp((*entryp)->alias, argv[0]) == 0) {
entry = *entryp;
break;
}
if (strncmp((*entryp)->name, argv[0], strlen(argv[0])) != 0)
continue;
if (entry != NULL)
goto ambiguous;
entry = *entryp;
/* Bail now if an exact match. */
if (strcmp(entry->name, argv[0]) == 0)
break;
}
if (entry == NULL) {
xasprintf(cause, "unknown command: %s", argv[0]);
return (NULL);
}
optreset = 1;
optind = 1;
if (entry->parse == NULL) {
while ((opt = getopt(argc, argv, "")) != -1) {
switch (opt) {
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0)
goto usage;
}
cmd = xmalloc(sizeof *cmd);
cmd->entry = entry;
cmd->data = NULL;
if (entry->parse != NULL) {
if (entry->parse(cmd, argc, argv, cause) != 0) {
xfree(cmd);
return (NULL);
}
}
return (cmd);
ambiguous:
*s = '\0';
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (strncmp((*entryp)->name, argv[0], strlen(argv[0])) != 0)
continue;
if (strlcat(s, (*entryp)->name, sizeof s) >= sizeof s)
break;
if (strlcat(s, ", ", sizeof s) >= sizeof s)
break;
}
s[strlen(s) - 2] = '\0';
xasprintf(cause, "ambiguous command: %s, could be: %s", argv[0], s);
return (NULL);
usage:
xasprintf(cause, "usage: %s %s", entry->name, entry->usage);
return (NULL);
}
int
cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
{
if (server_locked) {
ctx->error(ctx, "server is locked");
return (-1);
}
return (cmd->entry->exec(cmd, ctx));
}
void
cmd_send(struct cmd *cmd, struct buffer *b)
{
const struct cmd_entry **entryp;
u_int n;
n = 0;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (*entryp == cmd->entry)
break;
n++;
}
if (*entryp == NULL)
fatalx("command not found");
buffer_write(b, &n, sizeof n);
if (cmd->entry->send != NULL)
cmd->entry->send(cmd, b);
}
struct cmd *
cmd_recv(struct buffer *b)
{
const struct cmd_entry **entryp;
struct cmd *cmd;
u_int m, n;
buffer_read(b, &m, sizeof m);
n = 0;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (n == m)
break;
n++;
}
if (*entryp == NULL)
fatalx("command not found");
cmd = xmalloc(sizeof *cmd);
cmd->entry = *entryp;
if (cmd->entry->recv != NULL)
cmd->entry->recv(cmd, b);
return (cmd);
}
void
cmd_free(struct cmd *cmd)
{
if (cmd->data != NULL && cmd->entry->free != NULL)
cmd->entry->free(cmd);
xfree(cmd);
}
size_t
cmd_print(struct cmd *cmd, char *buf, size_t len)
{
if (cmd->entry->print == NULL) {
return (xsnprintf(buf, len, "%s", cmd->entry->name));
}
return (cmd->entry->print(cmd, buf, len));
}
void
cmd_send_string(struct buffer *b, const char *s)
{
size_t n;
if (s == NULL) {
n = 0;
buffer_write(b, &n, sizeof n);
return;
}
n = strlen(s) + 1;
buffer_write(b, &n, sizeof n);
buffer_write(b, s, n);
}
char *
cmd_recv_string(struct buffer *b)
{
char *s;
size_t n;
buffer_read(b, &n, sizeof n);
if (n == 0)
return (NULL);
s = xmalloc(n);
buffer_read(b, s, n);
s[n - 1] = '\0';
return (s);
}
struct session *
cmd_current_session(struct cmd_ctx *ctx)
{
struct msg_command_data *data = ctx->msgdata;
struct timeval *tv;
struct session *s, *newest = NULL;
u_int i;
if (ctx->cursession != NULL)
return (ctx->cursession);
if (data != NULL && data->pid != -1) {
if (data->pid != getpid()) {
ctx->error(ctx, "wrong server: %ld", (long) data->pid);
return (NULL);
}
if (data->idx > ARRAY_LENGTH(&sessions)) {
ctx->error(ctx, "index out of range: %d", data->idx);
return (NULL);
}
if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) {
ctx->error(ctx, "session doesn't exist: %u", data->idx);
return (NULL);
}
return (s);
}
tv = NULL;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i);
if (s != NULL && (tv == NULL || timercmp(&s->tv, tv, >))) {
newest = ARRAY_ITEM(&sessions, i);
tv = &s->tv;
}
}
return (newest);
}
struct client *
cmd_find_client(struct cmd_ctx *ctx, const char *arg)
{
struct client *c;
if (arg == NULL)
c = ctx->curclient;
else {
if ((c = arg_parse_client(arg)) == NULL) {
if (arg != NULL)
ctx->error(ctx, "client not found: %s", arg);
else
ctx->error(ctx, "no client found");
}
}
return (c);
}
struct session *
cmd_find_session(struct cmd_ctx *ctx, const char *arg)
{
struct session *s;
if (arg == NULL)
s = cmd_current_session(ctx);
else {
if ((s = arg_parse_session(arg)) == NULL) {
if (arg != NULL)
ctx->error(ctx, "session not found: %s", arg);
else
ctx->error(ctx, "no session found");
}
}
return (s);
}
struct winlink *
cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
{
struct session *s;
struct winlink *wl;
int idx;
wl = NULL;
if (arg_parse_window(arg, &s, &idx) != 0) {
ctx->error(ctx, "bad window: %s", arg);
return (NULL);
}
if (s == NULL)
s = ctx->cursession;
if (s == NULL)
s = cmd_current_session(ctx);
if (s == NULL)
return (NULL);
if (sp != NULL)
*sp = s;
if (idx == -1)
wl = s->curw;
else
wl = winlink_find_by_index(&s->windows, idx);
if (wl == NULL)
ctx->error(ctx, "window not found: %s:%d", s->name, idx);
return (wl);
}

123
colour.c Normal file
View File

@ -0,0 +1,123 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
const char *
colour_tostring(u_char c)
{
switch (c) {
case 0:
return ("black");
case 1:
return ("red");
case 2:
return ("green");
case 3:
return ("yellow");
case 4:
return ("blue");
case 5:
return ("magenta");
case 6:
return ("cyan");
case 7:
return ("white");
case 8:
return ("default");
}
return (NULL);
}
int
colour_fromstring(const char *s)
{
if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0'))
return (0);
if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0'))
return (1);
if (strcasecmp(s, "green") == 0 || (s[0] == '2' && s[1] == '\0'))
return (2);
if (strcasecmp(s, "yellow") == 0 || (s[0] == '3' && s[1] == '\0'))
return (3);
if (strcasecmp(s, "blue") == 0 || (s[0] == '4' && s[1] == '\0'))
return (4);
if (strcasecmp(s, "magenta") == 0 || (s[0] == '5' && s[1] == '\0'))
return (5);
if (strcasecmp(s, "cyan") == 0 || (s[0] == '6' && s[1] == '\0'))
return (6);
if (strcasecmp(s, "white") == 0 || (s[0] == '7' && s[1] == '\0'))
return (7);
if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0'))
return (8);
return (-1);
}
u_char
colour_256to16(u_char c)
{
static const u_char table[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 4, 4, 4, 12, 12, 2, 6, 4, 4, 12, 12, 2, 2, 6, 4,
12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
10, 10, 10, 14, 1, 5, 4, 4, 12, 12, 3, 8, 4, 4, 12, 12,
2, 2, 6, 4, 12, 12, 2, 2, 2, 6, 12, 12, 10, 10, 10, 10,
14, 12, 10, 10, 10, 10, 10, 14, 1, 1, 5, 4, 12, 12, 1, 1,
5, 4, 12, 12, 3, 3, 8, 4, 12, 12, 2, 2, 2, 6, 12, 12,
10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14, 1, 1, 1, 5,
12, 12, 1, 1, 1, 5, 12, 12, 1, 1, 1, 5, 12, 12, 3, 3,
3, 7, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,
9, 9, 9, 9, 13, 12, 9, 9, 9, 9, 13, 12, 9, 9, 9, 9,
13, 12, 9, 9, 9, 9, 13, 12, 11, 11, 11, 11, 7, 12, 10, 10,
10, 10, 10, 14, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 13,
9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9,
9, 13, 11, 11, 11, 11, 11, 15, 0, 0, 0, 0, 0, 0, 8, 8,
8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15
};
return (table[c]);
}
u_char
colour_256to88(u_char c)
{
static const u_char table[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 17, 18, 18, 19, 20, 21, 21, 22, 22, 23, 20, 21, 21, 22,
22, 23, 24, 25, 25, 26, 26, 27, 24, 25, 25, 26, 26, 27, 28, 29,
29, 30, 30, 31, 32, 33, 33, 34, 34, 35, 36, 37, 37, 38, 38, 39,
36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43, 40, 41, 41, 42,
42, 43, 44, 45, 45, 46, 46, 47, 32, 33, 33, 34, 34, 35, 36, 37,
37, 38, 38, 39, 36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43,
40, 41, 41, 42, 42, 43, 44, 45, 45, 46, 46, 47, 48, 49, 49, 50,
50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54, 54, 55, 56, 57,
57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61, 61, 62, 62, 63,
48, 49, 49, 50, 50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54,
54, 55, 56, 57, 57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61,
61, 62, 62, 63, 64, 65, 65, 66, 66, 67, 68, 69, 69, 70, 70, 71,
68, 69, 69, 70, 70, 71, 72, 73, 73, 74, 74, 75, 72, 73, 73, 74,
74, 75, 76, 77, 77, 78, 78, 79, 0, 0, 80, 80, 80, 81, 81, 81,
82, 82, 82, 83, 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87
};
return (table[c]);
}

211
grid-view.c Normal file
View File

@ -0,0 +1,211 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
/*
* Grid view functions. These work using coordinates relative to the visible
* screen area.
*/
#define grid_view_x(gd, x) (x)
#define grid_view_y(gd, y) ((gd)->hsize + (y))
/* Get cell for reading. */
const struct grid_cell *
grid_view_peek_cell(struct grid *gd, u_int px, u_int py)
{
return (grid_peek_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
}
/* Get cell for writing. */
struct grid_cell *
grid_view_get_cell(struct grid *gd, u_int px, u_int py)
{
return (grid_get_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
}
/* Set cell. */
void
grid_view_set_cell(
struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
{
grid_set_cell(gd, grid_view_x(gd, px), grid_view_y(gd, py), gc);
}
/* Get UTF-8 for reading. */
const struct grid_utf8 *
grid_view_peek_utf8(struct grid *gd, u_int px, u_int py)
{
return (grid_peek_utf8(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
}
/* Get UTF-8 for writing. */
struct grid_utf8 *
grid_view_get_utf8(struct grid *gd, u_int px, u_int py)
{
return (grid_get_utf8(gd, grid_view_x(gd, px), grid_view_y(gd, py)));
}
/* Set UTF-8. */
void
grid_view_set_utf8(
struct grid *gd, u_int px, u_int py, const struct grid_utf8 *gu)
{
grid_set_utf8(gd, grid_view_x(gd, px), grid_view_y(gd, py), gu);
}
/* Clear area. */
void
grid_view_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
{
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
px = grid_view_x(gd, px);
py = grid_view_y(gd, py);
grid_clear(gd, px, py, nx, ny);
}
/* Scroll region up. */
void
grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower)
{
GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
if (rupper == 0 && rlower == gd->sy - 1) {
grid_scroll_line(gd);
return;
}
rupper = grid_view_y(gd, rupper);
rlower = grid_view_y(gd, rlower);
grid_move_lines(gd, rupper, rupper + 1, rlower - rupper);
}
/* Scroll region down. */
void
grid_view_scroll_region_down(struct grid *gd, u_int rupper, u_int rlower)
{
GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
rupper = grid_view_y(gd, rupper);
rlower = grid_view_y(gd, rlower);
grid_move_lines(gd, rupper + 1, rupper, rlower - rupper);
}
/* Insert lines. */
void
grid_view_insert_lines(struct grid *gd, u_int py, u_int ny)
{
u_int sy;
GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
py = grid_view_y(gd, py);
sy = grid_view_y(gd, gd->sy);
grid_move_lines(gd, py + ny, py, sy - py - ny);
}
/* Insert lines in region. */
void
grid_view_insert_lines_region(
struct grid *gd, unused u_int rupper, u_int rlower, u_int py, u_int ny)
{
GRID_DEBUG(
gd, "rupper=%u, rlower=%u, py=%u, ny=%u", rupper, rlower, py, ny);
rlower = grid_view_y(gd, rlower);
py = grid_view_y(gd, py);
grid_move_lines(gd, py + ny, py, (rlower + 1) - py - ny);
}
/* Delete lines. */
void
grid_view_delete_lines(struct grid *gd, u_int py, u_int ny)
{
u_int sy;
GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
py = grid_view_y(gd, py);
sy = grid_view_y(gd, gd->sy);
grid_move_lines(gd, py, py + ny, sy - py - ny);
}
/* Delete lines inside scroll region. */
void
grid_view_delete_lines_region(
struct grid *gd, unused u_int rupper, u_int rlower, u_int py, u_int ny)
{
GRID_DEBUG(
gd, "rupper=%u, rlower=%u, py=%u, ny=%u", rupper, rlower, py, ny);
rlower = grid_view_y(gd, rlower);
py = grid_view_y(gd, py);
grid_move_lines(gd, py, py + ny, (rlower + 1) - py - ny);
}
/* Insert characters. */
void
grid_view_insert_cells(struct grid *gd, u_int px, u_int py, u_int nx)
{
u_int sx;
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
px = grid_view_x(gd, px);
py = grid_view_y(gd, py);
sx = grid_view_x(gd, gd->sx);
if (px == sx - 1)
grid_clear(gd, px, py, 1, 1);
else
grid_move_cells(gd, px + nx, px, py, (sx - 1) - (px + nx));
}
/* Delete characters. */
void
grid_view_delete_cells(struct grid *gd, u_int px, u_int py, u_int nx)
{
u_int sx;
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
px = grid_view_x(gd, px);
py = grid_view_y(gd, py);
sx = grid_view_x(gd, gd->sx);
grid_move_cells(gd, px, px + nx, py, (sx - 1) - (px + nx));
}

497
grid.c Normal file
View File

@ -0,0 +1,497 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
/*
* Grid data. This is the basic data structure that represents what is shown on
* screen.
*
* A grid is a grid of cells (struct grid_cell). Lines are not allocated until
* cells in that line are written to. The grid is split into history and
* viewable data with the history starting at row (line) 0 and extending to
* (hsize - 1); from hsize to hsize + (sy - 1) is the viewable data. All
* functions in this file work on absolute coordinates, grid-view.c has
* functions which work on the screen data.
*/
/* Default grid cell data. */
const struct grid_cell grid_default_cell = { 0, 0, 8, 8, ' ' };
#define grid_put_cell(gd, px, py, gc) do { \
memcpy(&gd->data[py][px], gc, sizeof gd->data[py][px]); \
} while (0)
#define grid_put_utf8(gd, px, py, gc) do { \
memcpy(&gd->udata[py][px], gc, sizeof gd->udata[py][px]); \
} while (0)
int grid_check_x(struct grid *, u_int);
int grid_check_y(struct grid *, u_int);
#ifdef DEBUG
int
grid_check_x(struct grid *gd, u_int px)
{
if ((px) >= (gd)->sx)
log_fatalx("x out of range: %u", px);
return (0);
}
int
grid_check_y(struct grid *gd, u_int py)
{
if ((py) >= (gd)->hsize + (gd)->sy)
log_fatalx("y out of range: %u", py);
return (0);
}
#else
int
grid_check_x(struct grid *gd, u_int px)
{
if ((px) >= (gd)->sx) {
log_debug("x out of range: %u", px);
return (-1);
}
return (0);
}
int
grid_check_y(struct grid *gd, u_int py)
{
if ((py) >= (gd)->hsize + (gd)->sy) {
log_debug("y out of range: %u", py);
return (-1);
}
return (0);
}
#endif
/* Create a new grid. */
struct grid *
grid_create(u_int sx, u_int sy, u_int hlimit)
{
struct grid *gd;
gd = xmalloc(sizeof *gd);
gd->sx = sx;
gd->sy = sy;
gd->hsize = 0;
gd->hlimit = hlimit;
gd->size = xcalloc(gd->sy, sizeof *gd->size);
gd->data = xcalloc(gd->sy, sizeof *gd->data);
gd->usize = xcalloc(gd->sy, sizeof *gd->usize);
gd->udata = xcalloc(gd->sy, sizeof *gd->udata);
return (gd);
}
/* Destroy grid. */
void
grid_destroy(struct grid *gd)
{
u_int yy;
for (yy = 0; yy < gd->hsize + gd->sy; yy++) {
if (gd->udata[yy] != NULL)
xfree(gd->udata[yy]);
if (gd->data[yy] != NULL)
xfree(gd->data[yy]);
}
if (gd->udata != NULL)
xfree(gd->udata);
if (gd->usize != NULL)
xfree(gd->usize);
if (gd->data != NULL)
xfree(gd->data);
if (gd->size != NULL)
xfree(gd->size);
xfree(gd);
}
/* Compare grids. */
int
grid_compare(struct grid *ga, struct grid *gb)
{
struct grid_cell *gca, *gcb;
struct grid_utf8 *gua, *gub;
u_int xx, yy;
if (ga->sx != gb->sx || ga->sy != ga->sy)
return (1);
for (yy = 0; yy < ga->sy; yy++) {
if (ga->size[yy] != gb->size[yy])
return (1);
for (xx = 0; xx < ga->sx; xx++) {
gca = &ga->data[yy][xx];
gcb = &gb->data[yy][xx];
if (memcmp(gca, gcb, sizeof (struct grid_cell)) != 0)
return (1);
if (!(gca->flags & GRID_FLAG_UTF8))
continue;
gua = &ga->udata[yy][xx];
gub = &gb->udata[yy][xx];
if (memcmp(gua, gub, sizeof (struct grid_utf8)) != 0)
return (1);
}
}
return (0);
}
/* Scroll a line into the history. */
void
grid_scroll_line(struct grid *gd)
{
u_int yy;
GRID_DEBUG(gd, "");
if (gd->hsize >= gd->hlimit - 1) {
/* If the limit is hit, free the bottom 10% and shift up. */
yy = gd->hlimit / 10;
if (yy < 1)
yy = 1;
grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy);
gd->hsize -= yy;
}
yy = gd->hsize + gd->sy;
gd->size = xrealloc(gd->size, yy + 1, sizeof *gd->size);
gd->size[yy] = 0;
gd->data = xrealloc(gd->data, yy + 1, sizeof *gd->data);
gd->data[yy] = NULL;
gd->usize = xrealloc(gd->usize, yy + 1, sizeof *gd->usize);
gd->usize[yy] = 0;
gd->udata = xrealloc(gd->udata, yy + 1, sizeof *gd->udata);
gd->udata[yy] = NULL;
gd->hsize++;
}
/* Reduce line to fit to cell. */
void
grid_reduce_line(struct grid *gd, u_int py, u_int sx)
{
if (sx < gd->size[py]) {
gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
gd->size[py] = sx;
}
if (sx < gd->usize[py]) {
gd->udata[py] = xrealloc(gd->udata[py], sx, sizeof **gd->udata);
gd->usize[py] = sx;
}
}
/* Expand line to fit to cell. */
void
grid_expand_line(struct grid *gd, u_int py, u_int sx)
{
u_int xx;
if (sx <= gd->size[py])
return;
gd->data[py] = xrealloc(gd->data[py], sx, sizeof **gd->data);
for (xx = gd->size[py]; xx < sx; xx++)
grid_put_cell(gd, xx, py, &grid_default_cell);
gd->size[py] = sx;
}
/* Expand line to fit to cell for UTF-8. */
void
grid_expand_line_utf8(struct grid *gd, u_int py, u_int sx)
{
if (sx <= gd->usize[py])
return;
gd->udata[py] = xrealloc(gd->udata[py], sx, sizeof **gd->udata);
gd->usize[py] = sx;
}
/* Get cell for reading. */
const struct grid_cell *
grid_peek_cell(struct grid *gd, u_int px, u_int py)
{
if (grid_check_x(gd, px) != 0)
return (&grid_default_cell);
if (grid_check_y(gd, py) != 0)
return (&grid_default_cell);
if (px >= gd->size[py])
return (&grid_default_cell);
return (&gd->data[py][px]);
}
/* Get cell at relative position (for writing). */
struct grid_cell *
grid_get_cell(struct grid *gd, u_int px, u_int py)
{
if (grid_check_x(gd, px) != 0)
return (NULL);
if (grid_check_y(gd, py) != 0)
return (NULL);
grid_expand_line(gd, py, px + 1);
return (&gd->data[py][px]);
}
/* Set cell at relative position. */
void
grid_set_cell(
struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
{
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
grid_expand_line(gd, py, px + 1);
grid_put_cell(gd, px, py, gc);
}
/* Get UTF-8 for reading. */
const struct grid_utf8 *
grid_peek_utf8(struct grid *gd, u_int px, u_int py)
{
if (grid_check_x(gd, px) != 0)
return (NULL);
if (grid_check_y(gd, py) != 0)
return (NULL);
if (px >= gd->usize[py])
return (NULL);
return (&gd->udata[py][px]);
}
/* Get utf8 at relative position (for writing). */
struct grid_utf8 *
grid_get_utf8(struct grid *gd, u_int px, u_int py)
{
if (grid_check_x(gd, px) != 0)
return (NULL);
if (grid_check_y(gd, py) != 0)
return (NULL);
grid_expand_line_utf8(gd, py, px + 1);
return (&gd->udata[py][px]);
}
/* Set utf8 at relative position. */
void
grid_set_utf8(
struct grid *gd, u_int px, u_int py, const struct grid_utf8 *gc)
{
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
grid_expand_line_utf8(gd, py, px + 1);
grid_put_utf8(gd, px, py, gc);
}
/*
* Clear area. Note this is different from a fill as it just omits unallocated
* cells.
*/
void
grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
{
u_int xx, yy;
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
if (nx == 0 || ny == 0)
return;
if (px == 0 && nx == gd->sx) {
grid_clear_lines(gd, py, ny);
return;
}
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_x(gd, px + nx - 1) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
if (grid_check_y(gd, py + ny - 1) != 0)
return;
for (yy = py; yy < py + ny; yy++) {
for (xx = px; xx < px + nx; xx++) {
if (xx >= gd->size[yy])
break;
grid_put_cell(gd, xx, yy, &grid_default_cell);
}
}
}
/* Clear lines. This just frees and truncates the lines. */
void
grid_clear_lines(struct grid *gd, u_int py, u_int ny)
{
u_int yy;
GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
if (ny == 0)
return;
if (grid_check_y(gd, py) != 0)
return;
if (grid_check_y(gd, py + ny - 1) != 0)
return;
for (yy = py; yy < py + ny; yy++) {
if (gd->data[yy] != NULL) {
xfree(gd->data[yy]);
gd->data[yy] = NULL;
gd->size[yy] = 0;
}
if (gd->udata[yy] != NULL) {
xfree(gd->udata[yy]);
gd->udata[yy] = NULL;
gd->usize[yy] = 0;
}
}
}
/* Move a group of lines. */
void
grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny)
{
u_int yy;
GRID_DEBUG(gd, "dy=%u, py=%u, ny=%u", dy, py, ny);
if (ny == 0 || py == dy)
return;
if (grid_check_y(gd, py) != 0)
return;
if (grid_check_y(gd, py + ny - 1) != 0)
return;
if (grid_check_y(gd, dy) != 0)
return;
if (grid_check_y(gd, dy + ny - 1) != 0)
return;
/* Free any lines which are being replaced. */
for (yy = dy; yy < dy + ny; yy++) {
if (yy >= py && yy < py + ny)
continue;
grid_clear_lines(gd, yy, 1);
}
memmove(&gd->data[dy], &gd->data[py], ny * (sizeof *gd->data));
memmove(&gd->size[dy], &gd->size[py], ny * (sizeof *gd->size));
memmove(&gd->udata[dy], &gd->udata[py], ny * (sizeof *gd->udata));
memmove(&gd->usize[dy], &gd->usize[py], ny * (sizeof *gd->usize));
/* Wipe any lines that have been moved (without freeing them). */
for (yy = py; yy < py + ny; yy++) {
if (yy >= dy && yy < dy + ny)
continue;
gd->data[yy] = NULL;
gd->size[yy] = 0;
gd->udata[yy] = NULL;
gd->usize[yy] = 0;
}
}
/* Clear a group of cells. */
void
grid_clear_cells(struct grid *gd, u_int px, u_int py, u_int nx)
{
u_int xx;
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
if (nx == 0)
return;
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_x(gd, px + nx - 1) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
for (xx = px; xx < px + nx; xx++) {
if (xx >= gd->size[py])
break;
grid_put_cell(gd, xx, py, &grid_default_cell);
}
}
/* Move a group of cells. */
void
grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
{
u_int xx;
GRID_DEBUG(gd, "dx=%u, px=%u, py=%u, nx=%u", dx, px, py, nx);
if (nx == 0 || px == dx)
return;
if (grid_check_x(gd, px) != 0)
return;
if (grid_check_x(gd, px + nx - 1) != 0)
return;
if (grid_check_x(gd, dx + nx - 1) != 0)
return;
if (grid_check_y(gd, py) != 0)
return;
grid_expand_line(gd, py, px + nx);
grid_expand_line(gd, py, dx + nx);
memmove(&gd->data[py][dx], &gd->data[py][px], nx * (sizeof **gd->data));
if (gd->udata[py] != NULL) {
grid_expand_line_utf8(gd, py, px + nx);
grid_expand_line_utf8(gd, py, dx + nx);
memmove(&gd->udata[py][dx],
&gd->udata[py][px], nx * (sizeof **gd->udata));
}
/* Wipe any cells that have been moved. */
for (xx = px; xx < px + nx; xx++) {
if (xx >= dx && xx < dx + nx)
continue;
grid_put_cell(gd, xx, py, &grid_default_cell);
}
}

227
input-keys.c Normal file
View File

@ -0,0 +1,227 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
struct input_key_ent {
int key;
const char *data;
int flags;
#define INPUTKEY_KEYPAD 0x1 /* keypad key */
#define INPUTKEY_CURSOR 0x2 /* cursor key */
#define INPUTKEY_CTRL 0x4 /* may be modified with ctrl */
#define INPUTKEY_XTERM 0x4 /* may have xterm argument appended */
};
struct input_key_ent input_keys[] = {
/* Function keys. */
{ KEYC_F1, "\033OP", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F2, "\033OQ", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F3, "\033OR", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F4, "\033OS", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F5, "\033[15~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F6, "\033[17~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F7, "\033[18~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F8, "\033[19~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F9, "\033[20~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F10, "\033[21~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F11, "\033[23~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F12, "\033[24~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F13, "\033[25~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F14, "\033[26~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F15, "\033[28~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F16, "\033[29~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F17, "\033[31~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F18, "\033[32~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F19, "\033[33~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_F20, "\033[34~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_IC, "\033[2~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_DC, "\033[3~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_HOME, "\033[1~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_END, "\033[4~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_NPAGE, "\033[6~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_PPAGE, "\033[5~", INPUTKEY_CTRL|INPUTKEY_XTERM },
{ KEYC_BTAB, "\033[Z", INPUTKEY_CTRL },
/* Arrow keys. Cursor versions must come first. */
{ KEYC_ADDCTL(KEYC_UP), "\033Oa", 0 },
{ KEYC_ADDCTL(KEYC_DOWN), "\033Ob", 0 },
{ KEYC_ADDCTL(KEYC_RIGHT), "\033Oc", 0 },
{ KEYC_ADDCTL(KEYC_LEFT), "\033Od", 0 },
{ KEYC_ADDSFT(KEYC_UP), "\033[a", 0 },
{ KEYC_ADDSFT(KEYC_DOWN), "\033[b", 0 },
{ KEYC_ADDSFT(KEYC_RIGHT), "\033[c", 0 },
{ KEYC_ADDSFT(KEYC_LEFT), "\033[d", 0 },
{ KEYC_UP, "\033OA", INPUTKEY_CURSOR },
{ KEYC_DOWN, "\033OB", INPUTKEY_CURSOR },
{ KEYC_RIGHT, "\033OC", INPUTKEY_CURSOR },
{ KEYC_LEFT, "\033OD", INPUTKEY_CURSOR },
{ KEYC_UP, "\033[A", 0 },
{ KEYC_DOWN, "\033[B", 0 },
{ KEYC_RIGHT, "\033[C", 0 },
{ KEYC_LEFT, "\033[D", 0 },
/* Keypad keys. Keypad versions must come first. */
{ KEYC_KP0_1, "/", INPUTKEY_KEYPAD },
{ KEYC_KP0_2, "*", INPUTKEY_KEYPAD },
{ KEYC_KP0_3, "-", INPUTKEY_KEYPAD },
{ KEYC_KP1_0, "7", INPUTKEY_KEYPAD },
{ KEYC_KP1_1, "8", INPUTKEY_KEYPAD },
{ KEYC_KP1_2, "9", INPUTKEY_KEYPAD },
{ KEYC_KP1_3, "+", INPUTKEY_KEYPAD },
{ KEYC_KP2_0, "4", INPUTKEY_KEYPAD },
{ KEYC_KP2_1, "5", INPUTKEY_KEYPAD },
{ KEYC_KP2_2, "6", INPUTKEY_KEYPAD },
{ KEYC_KP3_0, "1", INPUTKEY_KEYPAD },
{ KEYC_KP3_1, "2", INPUTKEY_KEYPAD },
{ KEYC_KP3_2, "3", INPUTKEY_KEYPAD },
{ KEYC_KP3_3, "\n", INPUTKEY_KEYPAD }, /* this can be CRLF too? */
{ KEYC_KP4_0, "0", INPUTKEY_KEYPAD },
{ KEYC_KP4_2, ".", INPUTKEY_KEYPAD },
{ KEYC_KP0_1, "\033Oo", 0 },
{ KEYC_KP0_2, "\033Oj", 0 },
{ KEYC_KP0_3, "\033Om", 0 },
{ KEYC_KP1_0, "\033Ow", 0 },
{ KEYC_KP1_1, "\033Ox", 0 },
{ KEYC_KP1_2, "\033Oy", 0 },
{ KEYC_KP1_3, "\033Ok", 0 },
{ KEYC_KP2_0, "\033Ot", 0 },
{ KEYC_KP2_1, "\033Ou", 0 },
{ KEYC_KP2_2, "\033Ov", 0 },
{ KEYC_KP3_0, "\033Oq", 0 },
{ KEYC_KP3_1, "\033Or", 0 },
{ KEYC_KP3_2, "\033Os", 0 },
{ KEYC_KP3_3, "\033OM", 0 },
{ KEYC_KP4_0, "\033Op", 0 },
{ KEYC_KP4_2, "\033On", 0 },
};
/* Translate a key code from client into an output key sequence. */
void
input_key(struct window_pane *wp, int key)
{
struct input_key_ent *ike;
u_int i;
char ch;
size_t dlen;
int xterm_keys;
log_debug2("writing key 0x%x", key);
if (key != KEYC_NONE && KEYC_REMOVEESC(key) < KEYC_OFFSET) {
if (KEYC_ISESC(key))
buffer_write8(wp->out, '\033');
buffer_write8(wp->out, (uint8_t) KEYC_REMOVEESC(key));
return;
}
for (i = 0; i < nitems(input_keys); i++) {
ike = &input_keys[i];
if ((ike->flags & INPUTKEY_KEYPAD) &&
!(wp->screen->mode & MODE_KKEYPAD))
continue;
if ((ike->flags & INPUTKEY_CURSOR) &&
!(wp->screen->mode & MODE_KCURSOR))
continue;
if (KEYC_ISESC(key) && KEYC_ADDESC(ike->key) == key)
break;
if (KEYC_ISSFT(key) && KEYC_ADDSFT(ike->key) == key)
break;
if (KEYC_ISCTL(key) && KEYC_ADDCTL(ike->key) == key) {
if (ike->flags & INPUTKEY_CTRL)
break;
}
if (ike->key == key)
break;
}
if (i == nitems(input_keys)) {
log_debug2("key 0x%x missing", key);
return;
}
dlen = strlen(ike->data);
log_debug2("found key 0x%x: \"%s\"", key, ike->data);
/*
* If in xterm keys mode, work out and append the modifier as an
* argument.
*/
xterm_keys = options_get_number(&wp->window->options, "xterm-keys");
if (xterm_keys && ike->flags & INPUTKEY_XTERM) {
ch = '\0';
if (KEYC_ISSFT(key) && KEYC_ISESC(key) && KEYC_ISCTL(key))
ch = '8';
else if (KEYC_ISESC(key) && KEYC_ISCTL(key))
ch = '7';
else if (KEYC_ISSFT(key) && KEYC_ISCTL(key))
ch = '6';
else if (KEYC_ISCTL(key))
ch = '5';
else if (KEYC_ISSFT(key) && KEYC_ISESC(key))
ch = '4';
else if (KEYC_ISESC(key))
ch = '3';
else if (KEYC_ISSFT(key))
ch = '2';
if (ch != '\0') {
buffer_write(wp->out, ike->data, dlen - 1);
buffer_write8(wp->out, ';');
buffer_write8(wp->out, ch);
buffer_write8(wp->out, ike->data[dlen - 1]);
} else
buffer_write(wp->out, ike->data, dlen);
return;
}
/*
* Not in xterm mode. Prefix a \033 for escape, and set bit 5 of the
* last byte for ctrl.
*/
if (KEYC_ISESC(key))
buffer_write8(wp->out, '\033');
if (KEYC_ISCTL(key) && ike->flags & INPUTKEY_CTRL) {
buffer_write(wp->out, ike->data, dlen - 1);
buffer_write8(wp->out, ike->data[dlen - 1] ^ 0x20);
return;
}
buffer_write(wp->out, ike->data, dlen);
}
/* Handle input mouse. */
void
input_mouse(struct window_pane *wp, u_char b, u_char x, u_char y)
{
if (wp->screen->mode & MODE_MOUSE) {
buffer_write(wp->out, "\033[M", 3);
buffer_write8(wp->out, b + 32);
buffer_write8(wp->out, x + 33);
buffer_write8(wp->out, y + 33);
}
}

1276
input.c Normal file

File diff suppressed because it is too large Load Diff

237
key-bindings.c Normal file
View File

@ -0,0 +1,237 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
SPLAY_GENERATE(key_bindings, key_binding, entry, key_bindings_cmp);
struct key_bindings key_bindings;
int
key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
{
return (bd1->key - bd2->key);
}
struct key_binding *
key_bindings_lookup(int key)
{
struct key_binding bd;
bd.key = key;
return (SPLAY_FIND(key_bindings, &key_bindings, &bd));
}
void
key_bindings_add(int key, int can_repeat, struct cmd_list *cmdlist)
{
struct key_binding *bd;
if ((bd = key_bindings_lookup(key)) == NULL) {
bd = xmalloc(sizeof *bd);
bd->key = key;
SPLAY_INSERT(key_bindings, &key_bindings, bd);
} else
cmd_list_free(bd->cmdlist);
bd->can_repeat = can_repeat;
bd->cmdlist = cmdlist;
}
void
key_bindings_remove(int key)
{
struct key_binding *bd;
if ((bd = key_bindings_lookup(key)) == NULL)
return;
SPLAY_REMOVE(key_bindings, &key_bindings, bd);
cmd_list_free(bd->cmdlist);
xfree(bd);
}
void
key_bindings_init(void)
{
static const struct {
int key;
int can_repeat;
const struct cmd_entry *entry;
} table[] = {
{ ' ', 0, &cmd_next_layout_entry },
{ '!', 0, &cmd_break_pane_entry },
{ '"', 0, &cmd_split_window_entry },
{ '#', 0, &cmd_list_buffers_entry },
{ '&', 0, &cmd_confirm_before_entry },
{ ',', 0, &cmd_command_prompt_entry },
{ '-', 0, &cmd_delete_buffer_entry },
{ '.', 0, &cmd_command_prompt_entry },
{ '0', 0, &cmd_select_window_entry },
{ '1', 0, &cmd_select_window_entry },
{ '2', 0, &cmd_select_window_entry },
{ '3', 0, &cmd_select_window_entry },
{ '4', 0, &cmd_select_window_entry },
{ '5', 0, &cmd_select_window_entry },
{ '6', 0, &cmd_select_window_entry },
{ '7', 0, &cmd_select_window_entry },
{ '8', 0, &cmd_select_window_entry },
{ '9', 0, &cmd_select_window_entry },
{ ':', 0, &cmd_command_prompt_entry },
{ '=', 0, &cmd_scroll_mode_entry },
{ '?', 0, &cmd_list_keys_entry },
{ '[', 0, &cmd_copy_mode_entry },
{ '\'', 0, &cmd_select_prompt_entry },
{ '\032', /* C-z */ 0, &cmd_suspend_client_entry },
{ ']', 0, &cmd_paste_buffer_entry },
{ 'c', 0, &cmd_new_window_entry },
{ 'd', 0, &cmd_detach_client_entry },
{ 'f', 0, &cmd_command_prompt_entry },
{ 'l', 0, &cmd_last_window_entry },
{ 'n', 0, &cmd_next_window_entry },
{ 'o', 0, &cmd_down_pane_entry },
{ 'p', 0, &cmd_previous_window_entry },
{ 'r', 0, &cmd_refresh_client_entry },
{ 's', 0, &cmd_choose_session_entry },
{ 't', 0, &cmd_clock_mode_entry },
{ 'w', 0, &cmd_choose_window_entry },
{ 'x', 0, &cmd_confirm_before_entry },
{ '{', 0, &cmd_swap_pane_entry },
{ '}', 0, &cmd_swap_pane_entry },
{ '\002', 0, &cmd_send_prefix_entry },
{ KEYC_ADDESC('0'), 0, &cmd_select_layout_entry },
{ KEYC_ADDESC('1'), 0, &cmd_select_layout_entry },
{ KEYC_ADDESC('2'), 0, &cmd_select_layout_entry },
{ KEYC_ADDESC('9'), 0, &cmd_select_layout_entry },
{ KEYC_ADDCTL(KEYC_DOWN), 1, &cmd_resize_pane_entry },
{ KEYC_PPAGE, 0, &cmd_scroll_mode_entry },
{ KEYC_ADDESC('n'), 0, &cmd_next_window_entry },
{ KEYC_ADDESC('p'), 0, &cmd_previous_window_entry },
{ KEYC_UP, 1, &cmd_up_pane_entry },
{ KEYC_DOWN, 1, &cmd_down_pane_entry },
{ KEYC_ADDESC(KEYC_UP), 1, &cmd_resize_pane_entry },
{ KEYC_ADDESC(KEYC_DOWN), 1, &cmd_resize_pane_entry },
{ KEYC_ADDCTL(KEYC_UP), 1, &cmd_resize_pane_entry },
{ KEYC_ADDCTL(KEYC_DOWN), 1, &cmd_resize_pane_entry },
{ KEYC_ADDESC('o'), 0, &cmd_rotate_window_entry },
{ '\017', 0, &cmd_rotate_window_entry },
};
u_int i;
struct cmd *cmd;
struct cmd_list *cmdlist;
SPLAY_INIT(&key_bindings);
for (i = 0; i < nitems(table); i++) {
cmdlist = xmalloc(sizeof *cmdlist);
TAILQ_INIT(cmdlist);
cmd = xmalloc(sizeof *cmd);
cmd->entry = table[i].entry;
cmd->data = NULL;
if (cmd->entry->init != NULL)
cmd->entry->init(cmd, table[i].key);
TAILQ_INSERT_HEAD(cmdlist, cmd, qentry);
key_bindings_add(table[i].key, table[i].can_repeat, cmdlist);
}
}
void
key_bindings_free(void)
{
struct key_binding *bd;
while (!SPLAY_EMPTY(&key_bindings)) {
bd = SPLAY_ROOT(&key_bindings);
SPLAY_REMOVE(key_bindings, &key_bindings, bd);
cmd_list_free(bd->cmdlist);
xfree(bd);
}
}
void printflike2
key_bindings_error(struct cmd_ctx *ctx, const char *fmt, ...)
{
va_list ap;
char *msg;
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
va_end(ap);
*msg = toupper((u_char) *msg);
status_message_set(ctx->curclient, msg);
xfree(msg);
}
void printflike2
key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...)
{
struct winlink *wl = ctx->cursession->curw;
va_list ap;
if (wl->window->active->mode != &window_more_mode)
window_pane_reset_mode(wl->window->active);
window_pane_set_mode(wl->window->active, &window_more_mode);
va_start(ap, fmt);
window_more_vadd(wl->window->active, fmt, ap);
va_end(ap);
}
void printflike2
key_bindings_info(struct cmd_ctx *ctx, const char *fmt, ...)
{
va_list ap;
char *msg;
if (be_quiet)
return;
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
va_end(ap);
*msg = toupper((u_char) *msg);
status_message_set(ctx->curclient, msg);
xfree(msg);
}
void
key_bindings_dispatch(struct key_binding *bd, struct client *c)
{
struct cmd_ctx ctx;
ctx.msgdata = NULL;
ctx.cursession = c->session;
ctx.curclient = c;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(bd->cmdlist, &ctx);
}

198
key-string.c Normal file
View File

@ -0,0 +1,198 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
int key_string_search_table(const char *);
struct {
const char *string;
int key;
} key_string_table[] = {
/* Function keys. */
{ "F1", KEYC_F1 },
{ "F2", KEYC_F2 },
{ "F3", KEYC_F3 },
{ "F4", KEYC_F4 },
{ "F5", KEYC_F5 },
{ "F6", KEYC_F6 },
{ "F7", KEYC_F7 },
{ "F8", KEYC_F8 },
{ "F9", KEYC_F9 },
{ "F10", KEYC_F10 },
{ "F11", KEYC_F11 },
{ "F12", KEYC_F12 },
{ "F13", KEYC_F13 },
{ "F14", KEYC_F14 },
{ "F15", KEYC_F15 },
{ "F16", KEYC_F16 },
{ "F17", KEYC_F17 },
{ "F18", KEYC_F18 },
{ "F19", KEYC_F19 },
{ "F20", KEYC_F20 },
{ "IC", KEYC_IC },
{ "DC", KEYC_DC },
{ "Home", KEYC_HOME },
{ "End", KEYC_END },
{ "NPage", KEYC_NPAGE },
{ "PPage", KEYC_PPAGE },
{ "Tab", '\011' },
{ "BTab", KEYC_BTAB },
/* Arrow keys. */
{ "Up", KEYC_UP },
{ "Down", KEYC_DOWN },
{ "Left", KEYC_LEFT },
{ "Right", KEYC_RIGHT },
/* Numeric keypad. */
{ "KP/", KEYC_KP0_1 },
{ "KP*", KEYC_KP0_2 },
{ "KP-", KEYC_KP0_3 },
{ "KP7", KEYC_KP1_0 },
{ "KP8", KEYC_KP1_1 },
{ "KP9", KEYC_KP1_2 },
{ "KP+", KEYC_KP1_3 },
{ "KP4", KEYC_KP2_0 },
{ "KP5", KEYC_KP2_1 },
{ "KP6", KEYC_KP2_2 },
{ "KP1", KEYC_KP3_0 },
{ "KP2", KEYC_KP3_1 },
{ "KP3", KEYC_KP3_2 },
{ "KPEnter", KEYC_KP3_3 },
{ "KP0", KEYC_KP4_0 },
{ "KP.", KEYC_KP4_2 },
};
int
key_string_search_table(const char *string)
{
u_int i;
for (i = 0; i < nitems(key_string_table); i++) {
if (strcasecmp(string, key_string_table[i].string) == 0)
return (key_string_table[i].key);
}
return (KEYC_NONE);
}
int
key_string_lookup_string(const char *string)
{
int key;
const u_char *ptr;
if (string[0] == '\0')
return (KEYC_NONE);
if (string[1] == '\0')
return (string[0]);
ptr = NULL;
if (string[0] == 'C' && string[1] == '-')
ptr = string + 2;
else if (string[0] == '^')
ptr = string + 1;
if (ptr != NULL) {
if (ptr[0] == '\0')
return (KEYC_NONE);
if (ptr[1] == '\0') {
if (ptr[0] == 32)
return (0);
if (ptr[0] >= 64 && ptr[0] <= 95)
return (ptr[0] - 64);
if (ptr[0] >= 97 && ptr[0] <= 122)
return (ptr[0] - 96);
return (KEYC_NONE);
}
key = key_string_search_table(ptr);
if (key != KEYC_NONE)
return (KEYC_ADDCTL(key));
return (KEYC_NONE);
}
if (string[0] == 'M' && string[1] == '-') {
ptr = string + 2;
if (ptr[0] == '\0')
return (KEYC_NONE);
if (ptr[1] == '\0') {
if (ptr[0] < 32 || ptr[0] > 127)
return (KEYC_NONE);
return (KEYC_ADDESC(ptr[0]));
}
key = key_string_lookup_string(ptr);
if (key != KEYC_NONE)
return (KEYC_ADDESC(key));
return (KEYC_NONE);
}
return (key_string_search_table(string));
}
const char *
key_string_lookup_key(int key)
{
static char tmp[24], tmp2[24];
const char *s;
u_int i;
if (key == 127)
return (NULL);
if (KEYC_ISESC(key)) {
if ((s = key_string_lookup_key(KEYC_REMOVEESC(key))) == NULL)
return (NULL);
xsnprintf(tmp2, sizeof tmp2, "M-%s", s);
return (tmp2);
}
if (KEYC_ISCTL(key)) {
if ((s = key_string_lookup_key(KEYC_REMOVECTL(key))) == NULL)
return (NULL);
xsnprintf(tmp2, sizeof tmp2, "C-%s", s);
return (tmp2);
}
if (KEYC_ISSFT(key)) {
if ((s = key_string_lookup_key(KEYC_REMOVESFT(key))) == NULL)
return (NULL);
xsnprintf(tmp2, sizeof tmp2, "S-%s", s);
return (tmp2);
}
if (key >= 32 && key <= 255) {
tmp[0] = key;
tmp[1] = '\0';
return (tmp);
}
if (key >= 0 && key <= 32) {
if (key == 0 || key > 26)
xsnprintf(tmp, sizeof tmp, "C-%c", 64 + key);
else
xsnprintf(tmp, sizeof tmp, "C-%c", 96 + key);
return (tmp);
}
for (i = 0; i < nitems(key_string_table); i++) {
if (key == key_string_table[i].key)
return (key_string_table[i].string);
}
return (NULL);
}

183
layout-manual.c Normal file
View File

@ -0,0 +1,183 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
void layout_manual_v_update_offsets(struct window *);
void
layout_manual_v_refresh(struct window *w, unused int active_only)
{
struct window_pane *wp;
u_int npanes, canfit, total;
int left;
if (active_only)
return;
if (TAILQ_EMPTY(&w->panes))
return;
/* Clear hidden flags. */
TAILQ_FOREACH(wp, &w->panes, entry)
wp->flags &= ~PANE_HIDDEN;
/* Check the new size. */
npanes = window_count_panes(w);
if (w->sy <= PANE_MINIMUM * npanes) {
/* How many can we fit? */
canfit = w->sy / PANE_MINIMUM;
if (canfit == 0) {
/* None. Just use this size for the first. */
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp == TAILQ_FIRST(&w->panes))
wp->sy = w->sy;
else
wp->flags |= PANE_HIDDEN;
}
} else {
/* >=1, set minimum for them all. */
TAILQ_FOREACH(wp, &w->panes, entry) {
if (canfit-- > 0)
wp->sy = PANE_MINIMUM - 1;
else
wp->flags |= PANE_HIDDEN;
}
/* And increase the first by the rest. */
TAILQ_FIRST(&w->panes)->sy += 1 + w->sy % PANE_MINIMUM;
}
} else {
/* In theory they will all fit. Find the current total. */
total = 0;
TAILQ_FOREACH(wp, &w->panes, entry)
total += wp->sy;
total += npanes - 1;
/* Growing or shrinking? */
left = w->sy - total;
if (left > 0) {
/* Growing. Expand evenly. */
while (left > 0) {
TAILQ_FOREACH(wp, &w->panes, entry) {
wp->sy++;
if (--left == 0)
break;
}
}
} else {
/* Shrinking. Reduce evenly down to minimum. */
while (left < 0) {
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->sy <= PANE_MINIMUM - 1)
continue;
wp->sy--;
if (++left == 0)
break;
}
}
}
}
/* Now do the resize. */
TAILQ_FOREACH(wp, &w->panes, entry) {
wp->sy--;
window_pane_resize(wp, w->sx, wp->sy + 1);
}
/* Fill in the offsets. */
layout_manual_v_update_offsets(w);
/* Switch the active window if necessary. */
window_set_active_pane(w, w->active);
}
void
layout_manual_v_resize(struct window_pane *wp, int adjust)
{
struct window *w = wp->window;
struct window_pane *wq;
if (adjust > 0) {
/*
* If this is not the last pane, keep trying to increase size
* and remove it from the next panes. If it is the last, do
* so on the previous pane.
*/
if (TAILQ_NEXT(wp, entry) == NULL) {
if (wp == TAILQ_FIRST(&w->panes)) {
/* Only one pane. */
return;
}
wp = TAILQ_PREV(wp, window_panes, entry);
}
while (adjust-- > 0) {
wq = wp;
while ((wq = TAILQ_NEXT(wq, entry)) != NULL) {
if (wq->sy <= PANE_MINIMUM)
continue;
window_pane_resize(wq, wq->sx, wq->sy - 1);
break;
}
if (wq == NULL)
break;
window_pane_resize(wp, wp->sx, wp->sy + 1);
}
} else {
adjust = -adjust;
/*
* If this is not the last pane, keep trying to reduce size
* and add to the following pane. If it is the last, do so on
* the previous pane.
*/
wq = TAILQ_NEXT(wp, entry);
if (wq == NULL) {
if (wp == TAILQ_FIRST(&w->panes)) {
/* Only one pane. */
return;
}
wq = wp;
wp = TAILQ_PREV(wq, window_panes, entry);
}
while (adjust-- > 0) {
if (wp->sy <= PANE_MINIMUM)
break;
window_pane_resize(wq, wq->sx, wq->sy + 1);
window_pane_resize(wp, wp->sx, wp->sy - 1);
}
}
layout_manual_v_update_offsets(w);
}
void
layout_manual_v_update_offsets(struct window *w)
{
struct window_pane *wp;
u_int yoff;
yoff = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_HIDDEN)
continue;
wp->xoff = 0;
wp->yoff = yoff;
yoff += wp->sy + 1;
}
}

373
layout.c Normal file
View File

@ -0,0 +1,373 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <string.h>
#include "tmux.h"
/*
* Each layout has two functions, _refresh to relayout the panes and _resize to
* resize a single pane.
*
* Second argument (int) to _refresh is 1 if the only change has been that the
* active pane has changed. If 0 then panes, active pane or both may have
* changed.
*/
void layout_active_only_refresh(struct window *, int);
void layout_even_h_refresh(struct window *, int);
void layout_even_v_refresh(struct window *, int);
void layout_main_h_refresh(struct window *, int);
void layout_main_v_refresh(struct window *, int);
const struct {
const char *name;
void (*refresh)(struct window *, int);
void (*resize)(struct window_pane *, int);
} layouts[] = {
{ "manual-vertical", layout_manual_v_refresh, layout_manual_v_resize },
{ "active-only", layout_active_only_refresh, NULL },
{ "even-horizontal", layout_even_h_refresh, NULL },
{ "even-vertical", layout_even_v_refresh, NULL },
{ "main-horizontal", layout_main_h_refresh, NULL },
{ "main-vertical", layout_main_v_refresh, NULL },
};
const char *
layout_name(struct window *w)
{
return (layouts[w->layout].name);
}
int
layout_lookup(const char *name)
{
u_int i;
int matched = -1;
for (i = 0; i < nitems(layouts); i++) {
if (strncmp(layouts[i].name, name, strlen(name)) == 0) {
if (matched != -1) /* ambiguous */
return (-1);
matched = i;
}
}
return (matched);
}
int
layout_select(struct window *w, u_int layout)
{
if (layout > nitems(layouts) - 1 || layout == w->layout)
return (-1);
w->layout = layout;
layout_refresh(w, 0);
return (0);
}
void
layout_next(struct window *w)
{
w->layout++;
if (w->layout > nitems(layouts) - 1)
w->layout = 0;
layout_refresh(w, 0);
}
void
layout_previous(struct window *w)
{
if (w->layout == 0)
w->layout = nitems(layouts) - 1;
else
w->layout--;
layout_refresh(w, 0);
}
void
layout_refresh(struct window *w, int active_only)
{
layouts[w->layout].refresh(w, active_only);
server_redraw_window(w);
}
int
layout_resize(struct window_pane *wp, int adjust)
{
struct window *w = wp->window;
if (layouts[w->layout].resize == NULL)
return (-1);
layouts[w->layout].resize(wp, adjust);
return (0);
}
void
layout_active_only_refresh(struct window *w, unused int active_only)
{
struct window_pane *wp;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp == w->active) {
wp->flags &= ~PANE_HIDDEN;
wp->xoff = wp->yoff = 0;
window_pane_resize(wp, w->sx, w->sy);
} else
wp->flags |= PANE_HIDDEN;
}
}
void
layout_even_h_refresh(struct window *w, int active_only)
{
struct window_pane *wp;
u_int i, n, width, xoff;
if (active_only)
return;
/* Get number of panes. */
n = window_count_panes(w);
if (n == 0)
return;
/* How many can we fit? */
if (w->sx / n < PANE_MINIMUM) {
width = PANE_MINIMUM;
n = w->sx / PANE_MINIMUM;
} else
width = w->sx / n;
/* Fit the panes. */
i = xoff = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (i > n) {
wp->flags |= PANE_HIDDEN;
continue;
}
wp->flags &= ~PANE_HIDDEN;
wp->xoff = xoff;
wp->yoff = 0;
if (i != n - 1)
window_pane_resize(wp, width - 1, w->sy);
else
window_pane_resize(wp, width, w->sy);
i++;
xoff += width;
}
/* Any space left? */
while (xoff++ < w->sx) {
wp = TAILQ_LAST(&w->panes, window_panes);
window_pane_resize(wp, wp->sx + 1, wp->sy);
}
}
void
layout_even_v_refresh(struct window *w, int active_only)
{
struct window_pane *wp;
u_int i, n, height, yoff;
if (active_only)
return;
/* Get number of panes. */
n = window_count_panes(w);
if (n == 0)
return;
/* How many can we fit? */
if (w->sy / n < PANE_MINIMUM) {
height = PANE_MINIMUM;
n = w->sy / PANE_MINIMUM;
} else
height = w->sy / n;
/* Fit the panes. */
i = yoff = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (i > n) {
wp->flags |= PANE_HIDDEN;
continue;
}
wp->flags &= ~PANE_HIDDEN;
wp->xoff = 0;
wp->yoff = yoff;
if (i != n - 1)
window_pane_resize(wp, w->sx, height - 1);
else
window_pane_resize(wp, w->sx, height);
i++;
yoff += height;
}
/* Any space left? */
while (yoff++ < w->sy) {
wp = TAILQ_LAST(&w->panes, window_panes);
window_pane_resize(wp, wp->sx, wp->sy + 1);
}
}
void
layout_main_v_refresh(struct window *w, int active_only)
{
struct window_pane *wp;
u_int i, n, mainwidth, height, yoff;
if (active_only)
return;
/* Get number of panes. */
n = window_count_panes(w);
if (n == 0)
return;
/* Get the main pane width and add one for separator line. */
mainwidth = options_get_number(&w->options, "main-pane-width") + 1;
/* Need >1 pane and minimum columns; if fewer, display active only. */
if (n == 1 || w->sx < mainwidth + PANE_MINIMUM) {
layout_active_only_refresh(w, active_only);
return;
}
n--;
/* How many can we fit, not including first? */
if (w->sy / n < PANE_MINIMUM) {
height = PANE_MINIMUM;
n = w->sy / PANE_MINIMUM;
} else
height = w->sy / n;
/* Fit the panes. */
i = yoff = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp == TAILQ_FIRST(&w->panes)) {
wp->xoff = 0;
wp->yoff = 0;
window_pane_resize(wp, mainwidth - 1, w->sy);
wp->flags &= ~PANE_HIDDEN;
continue;
}
if (i > n) {
wp->flags |= PANE_HIDDEN;
continue;
}
wp->flags &= ~PANE_HIDDEN;
wp->xoff = mainwidth;
wp->yoff = yoff;
if (i != n - 1)
window_pane_resize(wp, w->sx - mainwidth, height - 1);
else
window_pane_resize(wp, w->sx - mainwidth, height);
i++;
yoff += height;
}
/* Any space left? */
while (yoff++ < w->sy) {
wp = TAILQ_LAST(&w->panes, window_panes);
while (wp != NULL && wp == TAILQ_FIRST(&w->panes))
wp = TAILQ_PREV(wp, window_panes, entry);
if (wp == NULL)
break;
window_pane_resize(wp, wp->sx, wp->sy + 1);
}
}
void
layout_main_h_refresh(struct window *w, int active_only)
{
struct window_pane *wp;
u_int i, n, mainheight, width, xoff;
if (active_only)
return;
/* Get number of panes. */
n = window_count_panes(w);
if (n == 0)
return;
/* Get the main pane height and add one for separator line. */
mainheight = options_get_number(&w->options, "main-pane-height") + 1;
/* Need >1 pane and minimum rows; if fewer, display active only. */
if (n == 1 || w->sy < mainheight + PANE_MINIMUM) {
layout_active_only_refresh(w, active_only);
return;
}
n--;
/* How many can we fit, not including first? */
if (w->sx / n < PANE_MINIMUM) {
width = PANE_MINIMUM;
n = w->sx / PANE_MINIMUM;
} else
width = w->sx / n;
/* Fit the panes. */
i = xoff = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp == TAILQ_FIRST(&w->panes)) {
wp->xoff = 0;
wp->yoff = 0;
window_pane_resize(wp, w->sx, mainheight - 1);
wp->flags &= ~PANE_HIDDEN;
continue;
}
if (i > n) {
wp->flags |= PANE_HIDDEN;
continue;
}
wp->flags &= ~PANE_HIDDEN;
wp->xoff = xoff;
wp->yoff = mainheight;
if (i != n - 1)
window_pane_resize(wp, width - 1, w->sy - mainheight);
else
window_pane_resize(wp, width - 1, w->sy - mainheight);
i++;
xoff += width;
}
/* Any space left? */
while (xoff++ < w->sx + 1) {
wp = TAILQ_LAST(&w->panes, window_panes);
while (wp != NULL && wp == TAILQ_FIRST(&w->panes))
wp = TAILQ_PREV(wp, window_panes, entry);
if (wp == NULL)
break;
window_pane_resize(wp, wp->sx + 1, wp->sy);
}
}

250
log.c Normal file
View File

@ -0,0 +1,250 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include "tmux.h"
/* Logging type. */
#define LOG_TYPE_OFF 0
#define LOG_TYPE_SYSLOG 1
#define LOG_TYPE_TTY 2
#define LOG_TYPE_FILE 3
int log_type = LOG_TYPE_OFF;
/* Log file, if needed. */
FILE *log_file;
/* Debug level. */
int log_level;
/* Open logging to syslog. */
void
log_open_syslog(int level)
{
log_type = LOG_TYPE_SYSLOG;
log_level = level;
openlog(__progname, LOG_PID|LOG_NDELAY, LOG_FACILITY);
tzset();
}
/* Open logging to tty. */
void
log_open_tty(int level)
{
log_type = LOG_TYPE_TTY;
log_level = level;
setlinebuf(stderr);
setlinebuf(stdout);
tzset();
}
/* Open logging to file. */
void
log_open_file(int level, const char *path)
{
log_file = fopen(path, "w");
if (log_file == NULL)
return;
log_type = LOG_TYPE_FILE;
log_level = level;
setlinebuf(log_file);
tzset();
}
/* Close logging. */
void
log_close(void)
{
if (log_type == LOG_TYPE_FILE)
fclose(log_file);
log_type = LOG_TYPE_OFF;
}
/* Write a log message. */
void
log_write(int pri, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
log_vwrite(pri, msg, ap);
va_end(ap);
}
/* Write a log message. */
void
log_vwrite(int pri, const char *msg, va_list ap)
{
char *fmt;
FILE *f = log_file;
switch (log_type) {
case LOG_TYPE_SYSLOG:
vsyslog(pri, msg, ap);
break;
case LOG_TYPE_TTY:
if (pri == LOG_INFO)
f = stdout;
else
f = stderr;
/* FALLTHROUGH */
case LOG_TYPE_FILE:
if (asprintf(&fmt, "%s\n", msg) == -1)
exit(1);
if (vfprintf(f, fmt, ap) == -1)
exit(1);
fflush(f);
free(fmt);
break;
}
}
/* Log a warning with error string. */
void printflike1
log_warn(const char *msg, ...)
{
va_list ap;
char *fmt;
va_start(ap, msg);
if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1)
exit(1);
log_vwrite(LOG_CRIT, fmt, ap);
free(fmt);
va_end(ap);
}
/* Log a warning. */
void printflike1
log_warnx(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
log_vwrite(LOG_CRIT, msg, ap);
va_end(ap);
}
/* Log an informational message. */
void printflike1
log_info(const char *msg, ...)
{
va_list ap;
if (log_level > -1) {
va_start(ap, msg);
log_vwrite(LOG_INFO, msg, ap);
va_end(ap);
}
}
/* Log a debug message. */
void printflike1
log_debug(const char *msg, ...)
{
va_list ap;
if (log_level > 0) {
va_start(ap, msg);
log_vwrite(LOG_DEBUG, msg, ap);
va_end(ap);
}
}
/* Log a debug message at level 2. */
void printflike1
log_debug2(const char *msg, ...)
{
va_list ap;
if (log_level > 1) {
va_start(ap, msg);
log_vwrite(LOG_DEBUG, msg, ap);
va_end(ap);
}
}
/* Log a debug message at level 3. */
void printflike1
log_debug3(const char *msg, ...)
{
va_list ap;
if (log_level > 2) {
va_start(ap, msg);
log_vwrite(LOG_DEBUG, msg, ap);
va_end(ap);
}
}
/* Log a critical error, with error string if necessary, and die. */
__dead void
log_vfatal(const char *msg, va_list ap)
{
char *fmt;
if (errno != 0) {
if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
exit(1);
log_vwrite(LOG_CRIT, fmt, ap);
} else {
if (asprintf(&fmt, "fatal: %s", msg) == -1)
exit(1);
log_vwrite(LOG_CRIT, fmt, ap);
}
free(fmt);
exit(1);
}
/* Log a critical error, with error string, and die. */
__dead void printflike1
log_fatal(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
log_vfatal(msg, ap);
}
/* Log a critical error and die. */
__dead void printflike1
log_fatalx(const char *msg, ...)
{
va_list ap;
errno = 0;
va_start(ap, msg);
log_vfatal(msg, ap);
}

210
mode-key.c Normal file
View File

@ -0,0 +1,210 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
enum mode_key_cmd mode_key_lookup_vi(struct mode_key_data *, int);
enum mode_key_cmd mode_key_lookup_emacs(struct mode_key_data *, int);
void
mode_key_init(struct mode_key_data *mdata, int type, int flags)
{
mdata->type = type;
if (flags & MODEKEY_CANEDIT)
flags |= MODEKEY_EDITMODE;
mdata->flags = flags;
}
void
mode_key_free(unused struct mode_key_data *mdata)
{
}
enum mode_key_cmd
mode_key_lookup(struct mode_key_data *mdata, int key)
{
switch (mdata->type) {
case MODEKEY_VI:
return (mode_key_lookup_vi(mdata, key));
case MODEKEY_EMACS:
return (mode_key_lookup_emacs(mdata, key));
default:
fatalx("unknown mode key type");
}
}
enum mode_key_cmd
mode_key_lookup_vi(struct mode_key_data *mdata, int key)
{
if (KEYC_ISESC(key)) {
key = KEYC_REMOVEESC(key);
if (mdata->flags & MODEKEY_CANEDIT)
mdata->flags ^= MODEKEY_EDITMODE;
}
if (mdata->flags & MODEKEY_EDITMODE) {
switch (key) {
case '\003':
return (MODEKEYCMD_QUIT);
case '\033':
if (mdata->flags & MODEKEY_CANEDIT)
mdata->flags &= ~MODEKEY_EDITMODE;
return (MODEKEYCMD_NONE);
case '\010':
case '\177':
return (MODEKEYCMD_BACKSPACE);
case '\011':
return (MODEKEYCMD_COMPLETE);
case KEYC_DC:
return (MODEKEYCMD_DELETE);
case '\r':
return (MODEKEYCMD_CHOOSE);
}
return (MODEKEYCMD_OTHERKEY);
}
switch (key) {
case '\010':
case '\177':
return (MODEKEYCMD_LEFT);
case KEYC_DC:
return (MODEKEYCMD_DELETE);
case '\011':
return (MODEKEYCMD_COMPLETE);
case 'i':
if (mdata->flags & MODEKEY_CANEDIT)
mdata->flags |= MODEKEY_EDITMODE;
break;
case 'a':
if (mdata->flags & MODEKEY_CANEDIT) {
mdata->flags |= MODEKEY_EDITMODE;
return (MODEKEYCMD_RIGHT);
}
break;
case '\r':
if (mdata->flags & (MODEKEY_CANEDIT|MODEKEY_CHOOSEMODE))
return (MODEKEYCMD_CHOOSE);
return (MODEKEYCMD_COPYSELECTION);
case '0':
case '^':
return (MODEKEYCMD_STARTOFLINE);
case '\033':
return (MODEKEYCMD_CLEARSELECTION);
case 'j':
case KEYC_DOWN:
return (MODEKEYCMD_DOWN);
case '$':
return (MODEKEYCMD_ENDOFLINE);
case 'h':
case KEYC_LEFT:
return (MODEKEYCMD_LEFT);
case '\006':
case KEYC_NPAGE:
return (MODEKEYCMD_NEXTPAGE);
case 'w':
return (MODEKEYCMD_NEXTWORD);
case '\025':
case KEYC_PPAGE:
return (MODEKEYCMD_PREVIOUSPAGE);
case 'b':
return (MODEKEYCMD_PREVIOUSWORD);
case 'q':
case '\003':
return (MODEKEYCMD_QUIT);
case 'l':
case KEYC_RIGHT:
return (MODEKEYCMD_RIGHT);
case ' ':
return (MODEKEYCMD_STARTSELECTION);
case 'k':
case KEYC_UP:
return (MODEKEYCMD_UP);
case 'p':
return (MODEKEYCMD_PASTE);
}
return (MODEKEYCMD_NONE);
}
enum mode_key_cmd
mode_key_lookup_emacs(struct mode_key_data *mdata, int key)
{
switch (key) {
case '\010':
case '\177':
return (MODEKEYCMD_BACKSPACE);
case KEYC_DC:
return (MODEKEYCMD_DELETE);
case '\011':
return (MODEKEYCMD_COMPLETE);
case '\r':
return (MODEKEYCMD_CHOOSE);
case '\001':
return (MODEKEYCMD_STARTOFLINE);
case '\007':
return (MODEKEYCMD_CLEARSELECTION);
case '\027':
case KEYC_ADDESC('w'):
return (MODEKEYCMD_COPYSELECTION);
case '\016':
case KEYC_DOWN:
return (MODEKEYCMD_DOWN);
case '\005':
return (MODEKEYCMD_ENDOFLINE);
case '\002':
case KEYC_LEFT:
return (MODEKEYCMD_LEFT);
case ' ':
if (mdata->flags & MODEKEY_CANEDIT)
break;
/* FALLTHROUGH */
case '\026':
case KEYC_NPAGE:
return (MODEKEYCMD_NEXTPAGE);
case KEYC_ADDESC('f'):
return (MODEKEYCMD_NEXTWORD);
case '\031':
return (MODEKEYCMD_PASTE);
case KEYC_ADDESC('v'):
case KEYC_PPAGE:
return (MODEKEYCMD_PREVIOUSPAGE);
case KEYC_ADDESC('b'):
return (MODEKEYCMD_PREVIOUSWORD);
case '\006':
case KEYC_RIGHT:
return (MODEKEYCMD_RIGHT);
case '\000':
return (MODEKEYCMD_STARTSELECTION);
case '\020':
case KEYC_UP:
return (MODEKEYCMD_UP);
case 'q':
if (mdata->flags & MODEKEY_CANEDIT)
break;
/* FALLTHROUGH */
case '\003':
case '\033':
return (MODEKEYCMD_QUIT);
}
return (MODEKEYCMD_OTHERKEY);
}

110
names.c Normal file
View File

@ -0,0 +1,110 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <ctype.h>
#include <libgen.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
char *parse_window_name(const char *);
void
set_window_names(void)
{
struct window *w;
u_int i;
char *name, *wname;
struct timeval tv, tv2;
if (gettimeofday(&tv, NULL) != 0)
fatal("gettimeofday");
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
w = ARRAY_ITEM(&windows, i);
if (w == NULL || w->active == NULL)
continue;
if (!options_get_number(&w->options, "automatic-rename"))
continue;
if (timercmp(&tv, &w->name_timer, <))
continue;
memcpy(&w->name_timer, &tv, sizeof w->name_timer);
tv2.tv_sec = 0;
tv2.tv_usec = NAME_INTERVAL * 1000L;
timeradd(&w->name_timer, &tv2, &w->name_timer);
if (w->active->screen != &w->active->base)
name = NULL;
else
name = get_proc_name(w->active->fd, w->active->tty);
if (name == NULL)
wname = default_window_name(w);
else {
wname = parse_window_name(name);
xfree(name);
}
if (strcmp(wname, w->name) == 0)
xfree(wname);
else {
xfree(w->name);
w->name = wname;
server_status_window(w);
}
}
}
char *
default_window_name(struct window *w)
{
if (w->active->screen != &w->active->base)
return (xstrdup("[tmux]"));
return (parse_window_name(w->active->cmd));
}
char *
parse_window_name(const char *in)
{
char *copy, *name, *ptr;
name = copy = xstrdup(in);
if (strncmp(name, "exec ", (sizeof "exec ") - 1) == 0)
name = name + (sizeof "exec ") - 1;
while (*name == ' ')
name++;
if ((ptr = strchr(name, ' ')) != NULL)
*ptr = '\0';
if (*name != '\0') {
ptr = name + strlen(name) - 1;
while (ptr > name && !isalnum(*ptr))
*ptr-- = '\0';
}
if (*name == '/')
name = basename(name);
name = xstrdup(name);
xfree(copy);
return (name);
}

182
options-cmd.c Normal file
View File

@ -0,0 +1,182 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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"
void
set_option_string(struct cmd_ctx *ctx, struct options *oo,
const struct set_option_entry *entry, char *value)
{
if (value == NULL) {
ctx->error(ctx, "empty value");
return;
}
options_set_string(oo, entry->name, "%s", value);
ctx->info(ctx, "set option: %s -> %s", entry->name, value);
}
void
set_option_number(struct cmd_ctx *ctx, struct options *oo,
const struct set_option_entry *entry, char *value)
{
long long number;
const char *errstr;
if (value == NULL) {
ctx->error(ctx, "empty value");
return;
}
number = strtonum(value, entry->minimum, entry->maximum, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "value is %s: %s", errstr, value);
return;
}
options_set_number(oo, entry->name, number);
ctx->info(ctx, "set option: %s -> %lld", entry->name, number);
}
void
set_option_key(struct cmd_ctx *ctx, struct options *oo,
const struct set_option_entry *entry, char *value)
{
int key;
if (value == NULL) {
ctx->error(ctx, "empty value");
return;
}
if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
ctx->error(ctx, "unknown key: %s", value);
return;
}
options_set_number(oo, entry->name, key);
ctx->info(ctx,
"set option: %s -> %s", entry->name, key_string_lookup_key(key));
}
void
set_option_colour(struct cmd_ctx *ctx, struct options *oo,
const struct set_option_entry *entry, char *value)
{
int colour;
if (value == NULL) {
ctx->error(ctx, "empty value");
return;
}
if ((colour = colour_fromstring(value)) == -1) {
ctx->error(ctx, "bad colour: %s", value);
return;
}
options_set_number(oo, entry->name, colour);
ctx->info(ctx,
"set option: %s -> %s", entry->name, colour_tostring(colour));
}
void
set_option_attributes(struct cmd_ctx *ctx, struct options *oo,
const struct set_option_entry *entry, char *value)
{
int attr;
if (value == NULL) {
ctx->error(ctx, "empty value");
return;
}
if ((attr = attributes_fromstring(value)) == -1) {
ctx->error(ctx, "bad attributes: %s", value);
return;
}
options_set_number(oo, entry->name, attr);
ctx->info(ctx,
"set option: %s -> %s", entry->name, attributes_tostring(attr));
}
void
set_option_flag(struct cmd_ctx *ctx, struct options *oo,
const struct set_option_entry *entry, char *value)
{
int flag;
if (value == NULL || *value == '\0')
flag = !options_get_number(oo, entry->name);
else {
if ((value[0] == '1' && value[1] == '\0') ||
strcasecmp(value, "on") == 0 ||
strcasecmp(value, "yes") == 0)
flag = 1;
else if ((value[0] == '0' && value[1] == '\0') ||
strcasecmp(value, "off") == 0 ||
strcasecmp(value, "no") == 0)
flag = 0;
else {
ctx->error(ctx, "bad value: %s", value);
return;
}
}
options_set_number(oo, entry->name, flag);
ctx->info(ctx,
"set option: %s -> %s", entry->name, flag ? "on" : "off");
}
void
set_option_choice(struct cmd_ctx *ctx, struct options *oo,
const struct set_option_entry *entry, char *value)
{
const char **choicep;
int n, choice = -1;
if (value == NULL) {
ctx->error(ctx, "empty value");
return;
}
n = 0;
for (choicep = entry->choices; *choicep != NULL; choicep++) {
n++;
if (strncmp(*choicep, value, strlen(value)) != 0)
continue;
if (choice != -1) {
ctx->error(ctx, "ambiguous option: %s", value);
return;
}
choice = n - 1;
}
if (choice == -1) {
ctx->error(ctx, "unknown option: %s", value);
return;
}
options_set_number(oo, entry->name, choice);
ctx->info(ctx,
"set option: %s -> %s", entry->name, entry->choices[choice]);
}

160
options.c Normal file
View File

@ -0,0 +1,160 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <stdarg.h>
#include <string.h>
#include "tmux.h"
/*
* Option handling; each option has a name, type and value and is stored in
* a splay tree.
*/
SPLAY_GENERATE(options_tree, options_entry, entry, options_cmp);
int
options_cmp(struct options_entry *o1, struct options_entry *o2)
{
return (strcmp(o1->name, o2->name));
}
void
options_init(struct options *oo, struct options *parent)
{
SPLAY_INIT(&oo->tree);
oo->parent = parent;
}
void
options_free(struct options *oo)
{
struct options_entry *o;
while (!SPLAY_EMPTY(&oo->tree)) {
o = SPLAY_ROOT(&oo->tree);
SPLAY_REMOVE(options_tree, &oo->tree, o);
xfree(o->name);
if (o->type == OPTIONS_STRING)
xfree(o->value.string);
xfree(o);
}
}
struct options_entry *
options_find1(struct options *oo, const char *name)
{
struct options_entry p;
p.name = (char *) name;
return (SPLAY_FIND(options_tree, &oo->tree, &p));
}
struct options_entry *
options_find(struct options *oo, const char *name)
{
struct options_entry *o, p;
p.name = (char *) name;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
while (o == NULL) {
oo = oo->parent;
if (oo == NULL)
break;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
}
return (o);
}
int
options_remove(struct options *oo, const char *name)
{
struct options_entry *o;
if ((o = options_find1(oo, name)) == NULL)
return (-1);
SPLAY_REMOVE(options_tree, &oo->tree, o);
xfree(o->name);
if (o->type == OPTIONS_STRING)
xfree(o->value.string);
xfree(o);
return (0);
}
void printflike3
options_set_string(struct options *oo, const char *name, const char *fmt, ...)
{
struct options_entry *o;
va_list ap;
if ((o = options_find1(oo, name)) == NULL) {
o = xmalloc(sizeof *o);
o->name = xstrdup(name);
SPLAY_INSERT(options_tree, &oo->tree, o);
} else if (o->type == OPTIONS_STRING)
xfree(o->value.string);
va_start(ap, fmt);
o->type = OPTIONS_STRING;
xvasprintf(&o->value.string, fmt, ap);
va_end(ap);
}
char *
options_get_string(struct options *oo, const char *name)
{
struct options_entry *o;
if ((o = options_find(oo, name)) == NULL)
fatalx("missing option");
if (o->type != OPTIONS_STRING)
fatalx("option not a string");
return (o->value.string);
}
void
options_set_number(struct options *oo, const char *name, long long value)
{
struct options_entry *o;
if ((o = options_find1(oo, name)) == NULL) {
o = xmalloc(sizeof *o);
o->name = xstrdup(name);
SPLAY_INSERT(options_tree, &oo->tree, o);
} else if (o->type == OPTIONS_STRING)
xfree(o->value.string);
o->type = OPTIONS_NUMBER;
o->value.number = value;
}
long long
options_get_number(struct options *oo, const char *name)
{
struct options_entry *o;
if ((o = options_find(oo, name)) == NULL)
fatalx("missing option");
if (o->type != OPTIONS_NUMBER)
fatalx("option not a number");
return (o->value.number);
}

131
paste.c Normal file
View File

@ -0,0 +1,131 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <sys/time.h>
#include <string.h>
#include "tmux.h"
void
paste_init_stack(struct paste_stack *ps)
{
ARRAY_INIT(ps);
}
void
paste_free_stack(struct paste_stack *ps)
{
while (paste_free_top(ps) == 0)
;
}
struct paste_buffer *
paste_walk_stack(struct paste_stack *ps, uint *idx)
{
struct paste_buffer *pb;
pb = paste_get_index(ps, *idx);
(*idx)++;
return (pb);
}
struct paste_buffer *
paste_get_top(struct paste_stack *ps)
{
if (ARRAY_LENGTH(ps) == 0)
return (NULL);
return (ARRAY_FIRST(ps));
}
struct paste_buffer *
paste_get_index(struct paste_stack *ps, u_int idx)
{
if (idx >= ARRAY_LENGTH(ps))
return (NULL);
return (ARRAY_ITEM(ps, idx));
}
int
paste_free_top(struct paste_stack *ps)
{
struct paste_buffer *pb;
if (ARRAY_LENGTH(ps) == 0)
return (-1);
pb = ARRAY_FIRST(ps);
ARRAY_REMOVE(ps, 0);
xfree(pb->data);
xfree(pb);
return (0);
}
int
paste_free_index(struct paste_stack *ps, u_int idx)
{
struct paste_buffer *pb;
if (idx >= ARRAY_LENGTH(ps))
return (-1);
pb = ARRAY_ITEM(ps, idx);
ARRAY_REMOVE(ps, idx);
xfree(pb->data);
xfree(pb);
return (0);
}
void
paste_add(struct paste_stack *ps, char *data, u_int limit)
{
struct paste_buffer *pb;
while (ARRAY_LENGTH(ps) >= limit)
ARRAY_TRUNC(ps, 1);
pb = xmalloc(sizeof *pb);
ARRAY_INSERT(ps, 0, pb);
pb->data = data;
if (gettimeofday(&pb->tv, NULL) != 0)
fatal("gettimeofday");
}
int
paste_replace(struct paste_stack *ps, u_int idx, char *data)
{
struct paste_buffer *pb;
if (idx >= ARRAY_LENGTH(ps))
return (-1);
pb = ARRAY_ITEM(ps, idx);
xfree(pb->data);
pb->data = data;
if (gettimeofday(&pb->tv, NULL) != 0)
fatal("gettimeofday");
return (0);
}

Some files were not shown because too many files have changed in this diff Show More