mirror of https://github.com/tmux/tmux.git
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 piroftipull/1/head
commit
35876eaab9
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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]);
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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]);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue