mirror of
https://github.com/tmux/tmux.git
synced 2026-03-22 16:29:48 +00:00
Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
946fd162ba | ||
|
|
9b47a48393 | ||
|
|
0482983d53 | ||
|
|
2b512dc49d | ||
|
|
ae45c2ea45 | ||
|
|
11f81e8134 | ||
|
|
ad6a528f61 | ||
|
|
46f27eab22 | ||
|
|
e4703bacb5 | ||
|
|
e4573de97b | ||
|
|
63e76b555d | ||
|
|
13e7f060b1 | ||
|
|
fa34c76275 | ||
|
|
985cd3a4de | ||
|
|
03c1c1cd9f | ||
|
|
0e70c8801c | ||
|
|
617386370b | ||
|
|
bf1e237410 | ||
|
|
8d3b726396 | ||
|
|
47b335dee7 | ||
|
|
6c76724201 | ||
|
|
29434cb043 | ||
|
|
b7454e37cb | ||
|
|
e2a5e02022 | ||
|
|
cac532c3d1 | ||
|
|
e186450788 | ||
|
|
3e8092709c | ||
|
|
1b77ae2684 | ||
|
|
60134cebda | ||
|
|
f34861bad4 | ||
|
|
6503207185 | ||
|
|
3bba401609 | ||
|
|
31657820bc | ||
|
|
be3643fba0 | ||
|
|
f62d3d22bb | ||
|
|
67dc249d0e | ||
|
|
0778ef230b | ||
|
|
bebfd7c2c8 | ||
|
|
348c3e69de | ||
|
|
0d6a64070c | ||
|
|
bb4d770e45 | ||
|
|
e55a59eebc | ||
|
|
11cd05db27 | ||
|
|
6c6255f2d7 | ||
|
|
227e458ebb | ||
|
|
89eb95265a | ||
|
|
d98efa5378 | ||
|
|
a9c6976268 | ||
|
|
d9c99b83c7 | ||
|
|
d27956f160 | ||
|
|
e334deb872 | ||
|
|
e50dc0745f | ||
|
|
f11f71752a | ||
|
|
9e7a5fa5ef | ||
|
|
9c01a3d0db | ||
|
|
278effd7ea | ||
|
|
59c13133de | ||
|
|
41afc38dcc | ||
|
|
0beb31c261 | ||
|
|
6694a01861 | ||
|
|
9900e28ba8 | ||
|
|
fc69b9ccb7 | ||
|
|
d3dd6709bc | ||
|
|
3cded44623 | ||
|
|
50cad52ae6 | ||
|
|
701b5bdf61 | ||
|
|
4e120c00f7 | ||
|
|
7d4588f470 | ||
|
|
893be14cf8 | ||
|
|
342a47bc77 | ||
|
|
18ed37622e | ||
|
|
ec56ec7920 | ||
|
|
0c5a964e63 | ||
|
|
c4c542efb9 | ||
|
|
2bc150d16d | ||
|
|
7163907ab6 | ||
|
|
02fc1fe0da | ||
|
|
8e67b07489 | ||
|
|
0ed80637e7 | ||
|
|
b03418fc6b | ||
|
|
c0f03afbac | ||
|
|
0646b3caf2 | ||
|
|
b2e752b384 | ||
|
|
08632b4f0a | ||
|
|
10b73b7a11 | ||
|
|
cd0f22b96e | ||
|
|
610056abbe | ||
|
|
3743238a86 | ||
|
|
531db321e3 | ||
|
|
642f549e4d | ||
|
|
0fc65537a3 | ||
|
|
091db41bc9 | ||
|
|
67300e9524 | ||
|
|
f2a4ef5260 | ||
|
|
7dc1720522 | ||
|
|
07dcf8610f | ||
|
|
2d74ce1d3a | ||
|
|
5879e2a32b | ||
|
|
1392fba63d | ||
|
|
1c6ab725f5 | ||
|
|
4012917302 | ||
|
|
dd7abd9b4c | ||
|
|
51c776fe93 | ||
|
|
9382e546df | ||
|
|
659d15786a | ||
|
|
2307b91ecb | ||
|
|
a2c87eb899 | ||
|
|
33a90efc93 | ||
|
|
009d8d2ea7 | ||
|
|
aa8f9018ea | ||
|
|
4de04fac2c | ||
|
|
593bcbdd49 | ||
|
|
9f5b9ba0d6 | ||
|
|
b1a3090877 | ||
|
|
4271320bb7 | ||
|
|
51eab54102 | ||
|
|
51c135ed73 | ||
|
|
f6d36e60cf | ||
|
|
38bc7e87c5 |
48
CHANGES
48
CHANGES
@@ -1,3 +1,49 @@
|
||||
CHANGES FROM 1.2 TO 1.3, 18 July 2010
|
||||
|
||||
* New input parser.
|
||||
* Flags to move through panes -UDLR added to select-pane.
|
||||
* Commands up-pane, and down-pane removed, since equivalent behaviour is now
|
||||
available through the target flag (-t:+ and -t:-).
|
||||
* Jump-forward/backward in copy move (based on vi's F, and f commands).
|
||||
* Make paste-buffer accept a pane as a target.
|
||||
* Flag -a added to new-window to insert a window after an existing one, moving
|
||||
windows up if necessary.
|
||||
* Merge more mode into copy mode.
|
||||
* Run job commands explicitly in the global environment (which can be modified
|
||||
with setenv -g), rather than with the environment tmux started with.
|
||||
* Use the machine's hostname as the default title, instead of an empty string.
|
||||
* Prevent double free if the window option remain-on-exit is set.
|
||||
* Key string conversions rewritten.
|
||||
* Mark zombie windows as dead in the choose-window list.
|
||||
* Tiled layout added.
|
||||
* Signal handling reworked.
|
||||
* Reset SIGCHLD after fork to fix problems with some shells.
|
||||
* Select-prompt command removed. Therefore, bound ' to command-prompt -p index
|
||||
"select-window -t:%%" by default.
|
||||
* Catch SIGHUP and terminate if running as a client, thus avoiding clients from
|
||||
being left hanging around when, for instance, a SSH session is disconnected.
|
||||
* Solaris 9 fixes (such as adding compat {get,set}env(3) code).
|
||||
* Accept none instead of default for attributes.
|
||||
* Window options window-status-alert-{alert,bg,fg} added.
|
||||
* Flag -s added to the paste-buffer command to specify a custom separator.
|
||||
* Allow dragging to make a selection in copy mode if the mode-mouse option is
|
||||
set.
|
||||
* Support the mouse scroll wheel.
|
||||
* Make pipe-pane accept special character sequences (eg #I).
|
||||
* Fix problems with window sizing when starting tmux from .xinitrc.
|
||||
* Give tmux sockets (but not the containing folder) group permissions.
|
||||
* Extend the target flags (ie -t) to accept an offset (for example -t:+2), and
|
||||
make it wrap windows, and panes.
|
||||
* New command choose-buffer added.
|
||||
* New server option detach-on-destroy to set what happens to a client when the
|
||||
session it is attached to is destroyed. If on (default), the client is
|
||||
detached. Otherwise, the client is switched to the most recently active of
|
||||
the remaining sessions.
|
||||
* The commands load-buffer, and save-buffer now accept a dash (-) as the file
|
||||
to read from stdin, or write to stdout.
|
||||
* Custom layouts added.
|
||||
* Additional code reduction, bug fixes, and manpage enhancements.
|
||||
|
||||
CHANGES FROM 1.1 TO 1.2, 10 March 2010
|
||||
|
||||
* Switch to libevent.
|
||||
@@ -1467,7 +1513,7 @@ The list of older changes is below.
|
||||
(including mutt, emacs). No status bar yet and no key remapping or other
|
||||
customisation.
|
||||
|
||||
$Id: CHANGES,v 1.302 2010-03-10 15:18:11 tcunha Exp $
|
||||
$Id: CHANGES,v 1.303 2010-07-18 13:40:59 tcunha Exp $
|
||||
|
||||
LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
|
||||
LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms
|
||||
|
||||
15
GNUmakefile
15
GNUmakefile
@@ -1,4 +1,4 @@
|
||||
# $Id: GNUmakefile,v 1.122 2010-03-10 15:15:33 tcunha Exp $
|
||||
# $Id: GNUmakefile,v 1.128 2010-07-18 13:36:52 tcunha Exp $
|
||||
#
|
||||
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
#
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
VERSION= 1.2
|
||||
VERSION= 1.3
|
||||
|
||||
#FDEBUG= 1
|
||||
|
||||
@@ -28,7 +28,7 @@ LIBS+=
|
||||
|
||||
# Sun CC
|
||||
ifneq ($(shell ($(CC) -V 2>&1|awk '/Sun C/' || true)), )
|
||||
CFLAGS+=-erroff=E_EMPTY_DECLARATION
|
||||
CFLAGS+= -erroff=E_EMPTY_DECLARATION
|
||||
FDEBUG=
|
||||
endif
|
||||
|
||||
@@ -52,11 +52,12 @@ endif
|
||||
endif
|
||||
|
||||
PREFIX?= /usr/local
|
||||
INSTALLDIR= install -d
|
||||
INSTALLBIN= install -g bin -o root -m 555
|
||||
INSTALLMAN= install -g bin -o root -m 444
|
||||
INSTALL?= install
|
||||
INSTALLDIR= $(INSTALL) -d
|
||||
INSTALLBIN= $(INSTALL) -m 555
|
||||
INSTALLMAN= $(INSTALL) -m 444
|
||||
|
||||
SRCS= $(shell echo *.c|sed 's|osdep-[a-z0-9]*.c||g')
|
||||
SRCS= $(shell echo *.c|LC_ALL=C sed 's|osdep-[a-z0-9]*.c||g')
|
||||
include config.mk
|
||||
OBJS= $(patsubst %.c,%.o,$(SRCS))
|
||||
|
||||
|
||||
13
Makefile
13
Makefile
@@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.155 2010-03-10 15:15:33 tcunha Exp $
|
||||
# $Id: Makefile,v 1.160 2010-07-18 13:36:52 tcunha Exp $
|
||||
#
|
||||
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
#
|
||||
@@ -18,7 +18,7 @@
|
||||
.SUFFIXES: .c .o
|
||||
.PHONY: clean
|
||||
|
||||
VERSION= 1.2
|
||||
VERSION= 1.3
|
||||
|
||||
#FDEBUG= 1
|
||||
|
||||
@@ -48,11 +48,12 @@ CFLAGS+= -Wno-pointer-sign
|
||||
.endif
|
||||
|
||||
PREFIX?= /usr/local
|
||||
INSTALLDIR= install -d
|
||||
INSTALLBIN= install -g bin -o root -m 555
|
||||
INSTALLMAN= install -g bin -o root -m 444
|
||||
INSTALL?= install
|
||||
INSTALLDIR= ${INSTALL} -d
|
||||
INSTALLBIN= ${INSTALL} -m 555
|
||||
INSTALLMAN= ${INSTALL} -m 444
|
||||
|
||||
SRCS!= echo *.c|sed 's|osdep-[a-z0-9]*.c||g'
|
||||
SRCS!= echo *.c|LC_ALL=C sed 's|osdep-[a-z0-9]*.c||g'
|
||||
.include "config.mk"
|
||||
OBJS= ${SRCS:S/.c/.o/}
|
||||
|
||||
|
||||
45
TODO
45
TODO
@@ -15,7 +15,6 @@
|
||||
session not being watched?
|
||||
- next prev word etc in command prompt
|
||||
- many more info() displays for various things
|
||||
- input.c is too complicated. simplify?
|
||||
- use a better termcap internally instead of screen, perhaps xterm
|
||||
- fix rxvt cursor fg issue (text under cursor can have non-white fg)
|
||||
- should be able to move to a hidden pane and it would be moved into view. pane
|
||||
@@ -90,8 +89,6 @@
|
||||
message display
|
||||
copy and paste cursor and wide characters
|
||||
...?
|
||||
- option so that when session is destroyed, attach client to another session
|
||||
rather than exiting
|
||||
- session history for client and last-session command
|
||||
- option to change status line colour when current window is in a mode?
|
||||
- option to move copy mode indicator into status line
|
||||
@@ -100,12 +97,10 @@
|
||||
- live update: server started with -U connects to server, requests sessions and
|
||||
windows, receives fds
|
||||
- convert status line history to be server global (anything else?)
|
||||
- something for -t "last window in session" so a session can be used as a stack
|
||||
- command to show a tree of sessions-windows-panes (active marked with *)
|
||||
- sort out inheriting config from shell on new sessions/windows:
|
||||
should pick up default-path/termios/etc from client if possible,
|
||||
else leave empty/default
|
||||
- define custom layouts
|
||||
- link panes into multiple windows
|
||||
- -h option to capture-pane to capture the history as well
|
||||
- bells should be passed between sessions with visual-bell etc
|
||||
@@ -118,18 +113,40 @@
|
||||
- multiline status line
|
||||
- flag for absolute pane size to resize-pane
|
||||
- sanity check input to socket
|
||||
- stdin fd should be passed up to parent so load-buffer and others could use it
|
||||
for nonattaching clients
|
||||
- environment should be set up for jobs
|
||||
- select-buffer command
|
||||
- fix jobs so they block in config file rather than executing at an arbitrary
|
||||
future point -- need state stored in client so other clients can proceed
|
||||
- rectangle copy:
|
||||
when selecting leftward, cursor should be inside block per emacs
|
||||
key to rotate corner at which cursor is
|
||||
- double C-a should walk back over wrapped lines like C-e
|
||||
- support title stack, both internally and externally
|
||||
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
|
||||
- copy buffers should be global, limit can be server option, nuke copy-buffer
|
||||
command
|
||||
- command to show status line information briefly when it is off
|
||||
- some way to pad # stuff with spaces, #!2T maybe
|
||||
- FreeBSD console problems
|
||||
- a binding to "scroll down and exit at bottom" copy mode
|
||||
- some way to pass keystrokes in copy mode through to underlying window
|
||||
- last window update time and # replacement for it for display-message
|
||||
- find-window across sessions - other ways to make session handling easier?
|
||||
- ' and " should be parsed the same (eg "\e" vs '\e') in config and command
|
||||
prompt?
|
||||
- command to toggle selection not to move it in copy-mode
|
||||
|
||||
For 1.3 (not in order):
|
||||
|
||||
3 why are alerts per-winlink? try per window?
|
||||
4 audit of escape sequence support vs xterm
|
||||
6 rectangle copy: when selecting leftward, cursor should be inside block per
|
||||
emacs key to rotate corner at which cursor is
|
||||
9 something for -t "last window in session" so a session can be used as a stack
|
||||
10 synchronous commands - client sends cmd and blocks, neww/splitw saves client
|
||||
ptr then when program inside died, sends MSG_SOMETHING with wait status to
|
||||
client
|
||||
11 documentation improvements - rlpowell's tutorial
|
||||
- build instructions
|
||||
12 better configure? with-libevent
|
||||
14 bind commands to key sequences?
|
||||
16 monitor, bell etc should monitor /all/ panes in the window not just one
|
||||
17 wd should be updated on attach etc. maybe lose default-path and use PWD
|
||||
18 a history of commands that can be reversed (reverse member of each command, and a buffer)
|
||||
19 info() when changing to same window
|
||||
20 don't pass UTF-8 through vis for titles
|
||||
...
|
||||
|
||||
|
||||
4
array.h
4
array.h
@@ -1,4 +1,4 @@
|
||||
/* $Id: array.h,v 1.10 2010-02-08 18:29:32 tcunha Exp $ */
|
||||
/* $Id: array.h,v 1.11 2010-06-06 00:27:08 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -47,7 +47,7 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ARRAY_EMPTY(a) ((a) == NULL || (a)->num == 0)
|
||||
#define ARRAY_EMPTY(a) (((void *) (a)) == NULL || (a)->num == 0)
|
||||
#define ARRAY_LENGTH(a) ((a)->num)
|
||||
#define ARRAY_DATA(a) ((a)->list)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: attributes.c,v 1.3 2009-11-28 14:46:23 tcunha Exp $ */
|
||||
/* $Id: attributes.c,v 1.4 2010-06-05 23:54:51 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
|
||||
@@ -28,7 +28,7 @@ attributes_tostring(u_char attr)
|
||||
static char buf[128];
|
||||
|
||||
if (attr == 0)
|
||||
return ("default");
|
||||
return ("none");
|
||||
|
||||
buf[0] = '\0';
|
||||
if (attr & GRID_ATTR_BRIGHT)
|
||||
@@ -63,7 +63,7 @@ attributes_fromstring(const char *str)
|
||||
if (strchr(delimiters, str[strlen(str) - 1]) != NULL)
|
||||
return (-1);
|
||||
|
||||
if (strcasecmp(str, "default") == 0)
|
||||
if (strcasecmp(str, "default") == 0 || strcasecmp(str, "none") == 0)
|
||||
return (0);
|
||||
|
||||
attr = 0;
|
||||
|
||||
4
cfg.c
4
cfg.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: cfg.c,v 1.26 2010-02-08 18:29:32 tcunha Exp $ */
|
||||
/* $Id: cfg.c,v 1.27 2010-06-06 00:04:18 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -69,7 +69,7 @@ cfg_add_cause(struct causelist *causes, const char *fmt, ...)
|
||||
|
||||
/*
|
||||
* Load configuration file. Returns -1 for an error with a list of messages in
|
||||
* causes. Note that causes and ncauses must be initialised by the caller!
|
||||
* causes. Note that causes must be initialised by the caller!
|
||||
*/
|
||||
int
|
||||
load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
|
||||
|
||||
52
client.c
52
client.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: client.c,v 1.90 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: client.c,v 1.95 2010-07-02 02:52:13 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
@@ -101,8 +100,7 @@ server_started:
|
||||
|
||||
if (cmdflags & CMD_SENDENVIRON)
|
||||
client_send_environ();
|
||||
if (isatty(STDIN_FILENO))
|
||||
client_send_identify(flags);
|
||||
client_send_identify(flags);
|
||||
|
||||
return (&client_ibuf);
|
||||
|
||||
@@ -119,12 +117,9 @@ void
|
||||
client_send_identify(int flags)
|
||||
{
|
||||
struct msg_identify_data data;
|
||||
struct winsize ws;
|
||||
char *term;
|
||||
int fd;
|
||||
|
||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
|
||||
fatal("ioctl(TIOCGWINSZ)");
|
||||
data.flags = flags;
|
||||
|
||||
if (getcwd(data.cwd, sizeof data.cwd) == NULL)
|
||||
@@ -139,6 +134,14 @@ client_send_identify(int flags)
|
||||
fatal("dup failed");
|
||||
imsg_compose(&client_ibuf,
|
||||
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
|
||||
|
||||
if ((fd = dup(STDOUT_FILENO)) == -1)
|
||||
fatal("dup failed");
|
||||
imsg_compose(&client_ibuf, MSG_STDOUT, PROTOCOL_VERSION, -1, fd, NULL, 0);
|
||||
|
||||
if ((fd = dup(STDERR_FILENO)) == -1)
|
||||
fatal("dup failed");
|
||||
imsg_compose(&client_ibuf, MSG_STDERR, PROTOCOL_VERSION, -1, fd, NULL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -176,35 +179,19 @@ client_update_event(void)
|
||||
__dead void
|
||||
client_main(void)
|
||||
{
|
||||
struct event ev_sigcont, ev_sigterm, ev_sigwinch;
|
||||
struct sigaction sigact;
|
||||
|
||||
logfile("client");
|
||||
|
||||
/* Note: event_init() has already been called. */
|
||||
|
||||
/* Set up signals. */
|
||||
memset(&sigact, 0, sizeof sigact);
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = SA_RESTART;
|
||||
sigact.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR1, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
set_signals(client_signal);
|
||||
|
||||
signal_set(&ev_sigcont, SIGCONT, client_signal, NULL);
|
||||
signal_add(&ev_sigcont, NULL);
|
||||
signal_set(&ev_sigterm, SIGTERM, client_signal, NULL);
|
||||
signal_add(&ev_sigterm, NULL);
|
||||
signal_set(&ev_sigwinch, SIGWINCH, client_signal, NULL);
|
||||
signal_add(&ev_sigwinch, NULL);
|
||||
/*
|
||||
* Send a resize message immediately in case the terminal size has
|
||||
* changed between the identify message to the server and the MSG_READY
|
||||
* telling us to move into the client code.
|
||||
*/
|
||||
client_write_server(MSG_RESIZE, NULL, 0);
|
||||
|
||||
/*
|
||||
* imsg_read in the first client poll loop (before the terminal has
|
||||
@@ -233,6 +220,11 @@ client_signal(int sig, unused short events, unused void *data)
|
||||
struct sigaction sigact;
|
||||
|
||||
switch (sig) {
|
||||
case SIGHUP:
|
||||
client_exitmsg = "lost tty";
|
||||
client_exitval = 1;
|
||||
client_write_server(MSG_EXITING, NULL, 0);
|
||||
break;
|
||||
case SIGTERM:
|
||||
client_exitmsg = "terminated";
|
||||
client_exitval = 1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-bind-key.c,v 1.28 2010-01-25 17:12:44 tcunha Exp $ */
|
||||
/* $Id: cmd-bind-key.c,v 1.29 2010-07-02 02:43:01 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -130,7 +130,7 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
|
||||
return (cmd_bind_key_table(self, ctx));
|
||||
|
||||
key_bindings_add(data->key, data->can_repeat, data->cmdlist);
|
||||
data->cmdlist = NULL; /* avoid free */
|
||||
data->cmdlist->references++;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -192,8 +192,17 @@ cmd_bind_key_print(struct cmd *self, char *buf, size_t len)
|
||||
off += xsnprintf(buf, len, "%s", self->entry->name);
|
||||
if (data == NULL)
|
||||
return (off);
|
||||
|
||||
if (off < len && data->command_key)
|
||||
off += xsnprintf(buf + off, len - off, " -c");
|
||||
if (off < len && !(data->key & KEYC_PREFIX))
|
||||
off += xsnprintf(buf + off, len - off, " -n");
|
||||
if (off < len && data->can_repeat)
|
||||
off += xsnprintf(buf + off, len - off, " -r");
|
||||
if (off < len && data->tablename != NULL)
|
||||
off += cmd_prarg(buf + off, len - off, " -t ", data->tablename);
|
||||
if (off < len) {
|
||||
skey = key_string_lookup_key(data->key);
|
||||
skey = key_string_lookup_key(data->key & ~KEYC_PREFIX);
|
||||
off += xsnprintf(buf + off, len - off, " %s ", skey);
|
||||
}
|
||||
if (off < len)
|
||||
|
||||
146
cmd-choose-buffer.c
Normal file
146
cmd-choose-buffer.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/* $Id: cmd-choose-buffer.c,v 1.1 2010-06-22 23:35:20 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 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 "tmux.h"
|
||||
|
||||
/*
|
||||
* Enter choice mode to choose a buffer.
|
||||
*/
|
||||
|
||||
int cmd_choose_buffer_exec(struct cmd *, struct cmd_ctx *);
|
||||
|
||||
void cmd_choose_buffer_callback(void *, int);
|
||||
void cmd_choose_buffer_free(void *);
|
||||
|
||||
const struct cmd_entry cmd_choose_buffer_entry = {
|
||||
"choose-buffer", NULL,
|
||||
CMD_TARGET_WINDOW_USAGE " [template]",
|
||||
CMD_ARG01, "",
|
||||
cmd_target_init,
|
||||
cmd_target_parse,
|
||||
cmd_choose_buffer_exec,
|
||||
cmd_target_free,
|
||||
cmd_target_print
|
||||
};
|
||||
|
||||
struct cmd_choose_buffer_data {
|
||||
struct client *client;
|
||||
char *template;
|
||||
};
|
||||
|
||||
int
|
||||
cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
{
|
||||
struct cmd_target_data *data = self->data;
|
||||
struct cmd_choose_buffer_data *cdata;
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct paste_buffer *pb;
|
||||
u_int idx;
|
||||
char *tmp;
|
||||
|
||||
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 (paste_get_top(&s->buffers) == NULL)
|
||||
return (0);
|
||||
|
||||
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
|
||||
return (0);
|
||||
|
||||
idx = 0;
|
||||
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) {
|
||||
tmp = paste_print(pb, 50);
|
||||
window_choose_add(wl->window->active, idx - 1,
|
||||
"%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);
|
||||
xfree(tmp);
|
||||
}
|
||||
|
||||
cdata = xmalloc(sizeof *cdata);
|
||||
if (data->arg != NULL)
|
||||
cdata->template = xstrdup(data->arg);
|
||||
else
|
||||
cdata->template = xstrdup("paste-buffer -b '%%'");
|
||||
cdata->client = ctx->curclient;
|
||||
cdata->client->references++;
|
||||
|
||||
window_choose_ready(wl->window->active,
|
||||
0, cmd_choose_buffer_callback, cmd_choose_buffer_free, cdata);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_choose_buffer_callback(void *data, int idx)
|
||||
{
|
||||
struct cmd_choose_buffer_data *cdata = data;
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmd_ctx ctx;
|
||||
char *template, *cause, tmp[16];
|
||||
|
||||
if (idx == -1)
|
||||
return;
|
||||
if (cdata->client->flags & CLIENT_DEAD)
|
||||
return;
|
||||
|
||||
xsnprintf(tmp, sizeof tmp, "%u", idx);
|
||||
template = cmd_template_replace(cdata->template, tmp, 1);
|
||||
|
||||
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
|
||||
if (cause != NULL) {
|
||||
*cause = toupper((u_char) *cause);
|
||||
status_message_set(cdata->client, "%s", cause);
|
||||
xfree(cause);
|
||||
}
|
||||
xfree(template);
|
||||
return;
|
||||
}
|
||||
xfree(template);
|
||||
|
||||
ctx.msgdata = NULL;
|
||||
ctx.curclient = cdata->client;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_choose_buffer_free(void *data)
|
||||
{
|
||||
struct cmd_choose_buffer_data *cdata = data;
|
||||
|
||||
cdata->client->references--;
|
||||
xfree(cdata->template);
|
||||
xfree(cdata);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-choose-window.c,v 1.20 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: cmd-choose-window.c,v 1.22 2010-06-22 23:26:18 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -81,11 +81,11 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
idx++;
|
||||
|
||||
flag = ' ';
|
||||
if (session_alert_has(s, wm, WINDOW_ACTIVITY))
|
||||
if (wm->flags & WINLINK_ACTIVITY)
|
||||
flag = '#';
|
||||
else if (session_alert_has(s, wm, WINDOW_BELL))
|
||||
else if (wm->flags & WINLINK_BELL)
|
||||
flag = '!';
|
||||
else if (session_alert_has(s, wm, WINDOW_CONTENT))
|
||||
else if (wm->flags & WINLINK_CONTENT)
|
||||
flag = '+';
|
||||
else if (wm == s->curw)
|
||||
flag = '*';
|
||||
@@ -101,8 +101,9 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
left = right = "";
|
||||
|
||||
window_choose_add(wl->window->active,
|
||||
wm->idx, "%3d: %s%c [%ux%u] (%u panes)%s%s%s",
|
||||
wm->idx, "%3d: %s%c [%ux%u] (%u panes%s)%s%s%s",
|
||||
wm->idx, w->name, flag, w->sx, w->sy, window_count_panes(w),
|
||||
w->active->fd == -1 ? ", dead" : "",
|
||||
left, title, right);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-command-prompt.c,v 1.27 2009-11-14 17:56:39 tcunha Exp $ */
|
||||
/* $Id: cmd-command-prompt.c,v 1.28 2010-05-14 14:33:39 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -81,6 +81,10 @@ cmd_command_prompt_init(struct cmd *self, int key)
|
||||
case 'f':
|
||||
data->template = xstrdup("find-window '%%'");
|
||||
break;
|
||||
case '\'':
|
||||
data->template = xstrdup("select-window -t ':%%'");
|
||||
data->prompts = xstrdup("index");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-copy-mode.c,v 1.26 2010-01-05 23:50:22 tcunha Exp $ */
|
||||
/* $Id: cmd-copy-mode.c,v 1.27 2010-04-05 05:11:42 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -63,6 +63,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
return (-1);
|
||||
|
||||
window_pane_set_mode(wp, &window_copy_mode);
|
||||
window_copy_init_from_pane(wp);
|
||||
if (wp->mode == &window_copy_mode && cmd_check_flag(data->chflags, 'u'))
|
||||
window_copy_pageup(wp);
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/* $Id: cmd-down-pane.c,v 1.14 2010-01-05 23:52:37 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* 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_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);
|
||||
} while (!window_pane_visible(w->active));
|
||||
server_status_window(wl->window);
|
||||
server_redraw_window_borders(wl->window);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-if-shell.c,v 1.8 2009-11-14 17:56:39 tcunha Exp $ */
|
||||
/* $Id: cmd-if-shell.c,v 1.9 2010-07-17 14:36:40 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||
@@ -104,10 +104,13 @@ cmd_if_shell_free(void *data)
|
||||
{
|
||||
struct cmd_if_shell_data *cdata = data;
|
||||
struct cmd_ctx *ctx = &cdata->ctx;
|
||||
struct msg_exit_data exitdata;
|
||||
|
||||
if (ctx->cmdclient != NULL) {
|
||||
ctx->cmdclient->references--;
|
||||
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
|
||||
exitdata.retcode = ctx->cmdclient->retcode;
|
||||
server_write_client(
|
||||
ctx->cmdclient, MSG_EXIT, &exitdata, sizeof exitdata);
|
||||
}
|
||||
if (ctx->curclient != NULL)
|
||||
ctx->curclient->references--;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-join-pane.c,v 1.2 2010-01-08 16:34:17 tcunha Exp $ */
|
||||
/* $Id: cmd-join-pane.c,v 1.4 2010-04-09 07:09:37 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -44,7 +44,7 @@ struct cmd_join_pane_data {
|
||||
|
||||
const struct cmd_entry cmd_join_pane_entry = {
|
||||
"join-pane", "joinp",
|
||||
"[-dhv] [-p percentage|-l size] [-t src-pane] [-t dst-pane] [command]",
|
||||
"[-dhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane] [command]",
|
||||
0, "",
|
||||
cmd_join_pane_init,
|
||||
cmd_join_pane_parse,
|
||||
@@ -150,13 +150,14 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct winlink *src_wl, *dst_wl;
|
||||
struct window *src_w, *dst_w;
|
||||
struct window_pane *src_wp, *dst_wp;
|
||||
int size;
|
||||
int size, dst_idx;
|
||||
enum layout_type type;
|
||||
struct layout_cell *lc;
|
||||
|
||||
if ((dst_wl = cmd_find_pane(ctx, data->dst, &dst_s, &dst_wp)) == NULL)
|
||||
return (-1);
|
||||
dst_w = dst_wl->window;
|
||||
dst_idx = dst_wl->idx;
|
||||
|
||||
if ((src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp)) == NULL)
|
||||
return (-1);
|
||||
@@ -209,7 +210,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
|
||||
if (!data->flag_detached) {
|
||||
window_set_active_pane(dst_w, src_wp);
|
||||
session_select(dst_s, dst_wl->idx);
|
||||
session_select(dst_s, dst_idx);
|
||||
server_redraw_session(dst_s);
|
||||
} else
|
||||
server_status_session(dst_s);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-kill-session.c,v 1.17 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: cmd-kill-session.c,v 1.18 2010-07-02 02:43:50 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -45,21 +45,11 @@ 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 != NULL && c->session == s) {
|
||||
c->session = NULL;
|
||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||
}
|
||||
}
|
||||
recalculate_sizes();
|
||||
|
||||
server_destroy_session(s);
|
||||
session_destroy(s);
|
||||
|
||||
return (0);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-list-buffers.c,v 1.15 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: cmd-list-buffers.c,v 1.16 2010-06-22 23:35:20 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -46,32 +46,17 @@ cmd_list_buffers_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct session *s;
|
||||
struct paste_buffer *pb;
|
||||
u_int idx;
|
||||
char tmp[51 * 4 + 1];
|
||||
size_t size, len;
|
||||
char *tmp;
|
||||
|
||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||
return (-1);
|
||||
|
||||
idx = 0;
|
||||
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) {
|
||||
size = pb->size;
|
||||
|
||||
/* Translate the first 50 characters. */
|
||||
len = size;
|
||||
if (len > 50)
|
||||
len = 50;
|
||||
strvisx(tmp, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
|
||||
|
||||
/*
|
||||
* If the first 50 characters were encoded as a longer string,
|
||||
* or there is definitely more data, add "...".
|
||||
*/
|
||||
if (size > 50 || strlen(tmp) > 50) {
|
||||
tmp[50 - 3] = '\0';
|
||||
strlcat(tmp, "...", sizeof tmp);
|
||||
}
|
||||
|
||||
ctx->print(ctx, "%u: %zu bytes: \"%s\"", idx - 1, size, tmp);
|
||||
tmp = paste_print(pb, 50);
|
||||
ctx->print(ctx,
|
||||
"%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);
|
||||
xfree(tmp);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-list-windows.c,v 1.42 2009-11-14 17:56:39 tcunha Exp $ */
|
||||
/* $Id: cmd-list-windows.c,v 1.43 2010-07-02 02:54:52 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -45,6 +45,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct cmd_target_data *data = self->data;
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
char *layout;
|
||||
|
||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||
return (-1);
|
||||
@@ -52,6 +53,9 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
ctx->print(ctx, "%d: %s [%ux%u]",
|
||||
wl->idx, wl->window->name, wl->window->sx, wl->window->sy);
|
||||
layout = layout_dump(wl->window);
|
||||
ctx->print(ctx, " layout: %s", layout);
|
||||
xfree(layout);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
26
cmd-list.c
26
cmd-list.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-list.c,v 1.7 2010-02-02 23:51:04 tcunha Exp $ */
|
||||
/* $Id: cmd-list.c,v 1.9 2010-07-02 02:43:01 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -32,7 +32,8 @@ cmd_list_parse(int argc, char **argv, char **cause)
|
||||
char **new_argv;
|
||||
|
||||
cmdlist = xmalloc(sizeof *cmdlist);
|
||||
TAILQ_INIT(cmdlist);
|
||||
cmdlist->references = 1;
|
||||
TAILQ_INIT(&cmdlist->list);
|
||||
|
||||
lastsplit = 0;
|
||||
for (i = 0; i < argc; i++) {
|
||||
@@ -54,7 +55,7 @@ cmd_list_parse(int argc, char **argv, char **cause)
|
||||
cmd = cmd_parse(new_argc, new_argv, cause);
|
||||
if (cmd == NULL)
|
||||
goto bad;
|
||||
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
|
||||
TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
|
||||
|
||||
lastsplit = i + 1;
|
||||
}
|
||||
@@ -63,7 +64,7 @@ cmd_list_parse(int argc, char **argv, char **cause)
|
||||
cmd = cmd_parse(argc - lastsplit, argv + lastsplit, cause);
|
||||
if (cmd == NULL)
|
||||
goto bad;
|
||||
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
|
||||
TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
|
||||
}
|
||||
|
||||
return (cmdlist);
|
||||
@@ -80,7 +81,7 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
|
||||
int n, retval;
|
||||
|
||||
retval = 0;
|
||||
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
||||
if ((n = cmd_exec(cmd, ctx)) == -1)
|
||||
return (-1);
|
||||
|
||||
@@ -99,6 +100,10 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
|
||||
if (ctx->curclient == NULL) {
|
||||
ctx->curclient = ctx->cmdclient;
|
||||
ctx->cmdclient = NULL;
|
||||
|
||||
ctx->error = key_bindings_error;
|
||||
ctx->print = key_bindings_print;
|
||||
ctx->info = key_bindings_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,9 +115,12 @@ cmd_list_free(struct cmd_list *cmdlist)
|
||||
{
|
||||
struct cmd *cmd;
|
||||
|
||||
while (!TAILQ_EMPTY(cmdlist)) {
|
||||
cmd = TAILQ_FIRST(cmdlist);
|
||||
TAILQ_REMOVE(cmdlist, cmd, qentry);
|
||||
if (--cmdlist->references != 0)
|
||||
return;
|
||||
|
||||
while (!TAILQ_EMPTY(&cmdlist->list)) {
|
||||
cmd = TAILQ_FIRST(&cmdlist->list);
|
||||
TAILQ_REMOVE(&cmdlist->list, cmd, qentry);
|
||||
cmd_free(cmd);
|
||||
}
|
||||
xfree(cmdlist);
|
||||
@@ -125,7 +133,7 @@ cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len)
|
||||
size_t off;
|
||||
|
||||
off = 0;
|
||||
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
||||
if (off >= len)
|
||||
break;
|
||||
off += cmd_print(cmd, buf + off, len - off);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-load-buffer.c,v 1.15 2010-02-26 13:30:07 tcunha Exp $ */
|
||||
/* $Id: cmd-load-buffer.c,v 1.16 2010-07-02 02:52:13 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||
@@ -16,10 +16,13 @@
|
||||
* 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 <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@@ -45,7 +48,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
{
|
||||
struct cmd_buffer_data *data = self->data;
|
||||
struct session *s;
|
||||
FILE *f;
|
||||
FILE *f, *close_f;
|
||||
char *pdata, *new_pdata;
|
||||
size_t psize;
|
||||
u_int limit;
|
||||
@@ -54,9 +57,23 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||
return (-1);
|
||||
|
||||
if ((f = fopen(data->arg, "rb")) == NULL) {
|
||||
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
||||
return (-1);
|
||||
if (strcmp(data->arg, "-") == 0 ) {
|
||||
if (ctx->cmdclient == NULL) {
|
||||
ctx->error(ctx, "%s: can't read from stdin", data->arg);
|
||||
return (-1);
|
||||
}
|
||||
f = ctx->cmdclient->stdin_file;
|
||||
if (isatty(fileno(ctx->cmdclient->stdin_file))) {
|
||||
ctx->error(ctx, "%s: stdin is a tty", data->arg);
|
||||
return (-1);
|
||||
}
|
||||
close_f = NULL;
|
||||
} else {
|
||||
if ((f = fopen(data->arg, "rb")) == NULL) {
|
||||
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
close_f = f;
|
||||
}
|
||||
|
||||
pdata = NULL;
|
||||
@@ -77,7 +94,8 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
if (pdata != NULL)
|
||||
pdata[psize] = '\0';
|
||||
|
||||
fclose(f);
|
||||
if (close_f != NULL)
|
||||
fclose(close_f);
|
||||
|
||||
limit = options_get_number(&s->options, "buffer-limit");
|
||||
if (data->buffer == -1) {
|
||||
@@ -94,6 +112,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
error:
|
||||
if (pdata != NULL)
|
||||
xfree(pdata);
|
||||
fclose(f);
|
||||
if (close_f != NULL)
|
||||
fclose(close_f);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-new-session.c,v 1.76 2010-02-26 13:28:15 tcunha Exp $ */
|
||||
/* $Id: cmd-new-session.c,v 1.78 2010-07-02 02:49:19 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -18,8 +18,10 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@@ -125,8 +127,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct window_pane *wp;
|
||||
struct environ env;
|
||||
struct termios tio, *tiop;
|
||||
const char *update;
|
||||
char *overrides, *cmd, *cwd, *cause;
|
||||
struct passwd *pw;
|
||||
const char *update, *cwd;
|
||||
char *overrides, *cmd, *cause;
|
||||
int detached, idx;
|
||||
u_int sx, sy, i;
|
||||
|
||||
@@ -198,8 +201,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
/* Get the new session working directory. */
|
||||
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
|
||||
cwd = ctx->cmdclient->cwd;
|
||||
else
|
||||
cwd = options_get_string(&global_s_options, "default-path");
|
||||
else {
|
||||
pw = getpwuid(getuid());
|
||||
if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
|
||||
cwd = pw->pw_dir;
|
||||
else
|
||||
cwd = "/";
|
||||
}
|
||||
|
||||
/* Find new session size. */
|
||||
if (detached) {
|
||||
@@ -287,10 +295,11 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
*/
|
||||
if (cfg_finished && !ARRAY_EMPTY(&cfg_causes)) {
|
||||
wp = s->curw->window->active;
|
||||
window_pane_set_mode(wp, &window_more_mode);
|
||||
window_pane_set_mode(wp, &window_copy_mode);
|
||||
window_copy_init_for_output(wp);
|
||||
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
|
||||
cause = ARRAY_ITEM(&cfg_causes, i);
|
||||
window_more_add(wp, "%s", cause);
|
||||
window_copy_add(wp, "%s", cause);
|
||||
xfree(cause);
|
||||
}
|
||||
ARRAY_FREE(&cfg_causes);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-new-window.c,v 1.43 2010-01-22 17:28:34 tcunha Exp $ */
|
||||
/* $Id: cmd-new-window.c,v 1.47 2010-07-02 02:49:19 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -36,13 +36,14 @@ struct cmd_new_window_data {
|
||||
char *target;
|
||||
char *name;
|
||||
char *cmd;
|
||||
int flag_insert_after;
|
||||
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]",
|
||||
"[-adk] [-n window-name] [-t target-window] [command]",
|
||||
0, "",
|
||||
cmd_new_window_init,
|
||||
cmd_new_window_parse,
|
||||
@@ -61,6 +62,7 @@ cmd_new_window_init(struct cmd *self, unused int arg)
|
||||
data->target = NULL;
|
||||
data->name = NULL;
|
||||
data->cmd = NULL;
|
||||
data->flag_insert_after = 0;
|
||||
data->flag_detached = 0;
|
||||
data->flag_kill = 0;
|
||||
}
|
||||
@@ -74,8 +76,11 @@ cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause)
|
||||
self->entry->init(self, KEYC_NONE);
|
||||
data = self->data;
|
||||
|
||||
while ((opt = getopt(argc, argv, "dkt:n:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "adkt:n:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
data->flag_insert_after = 1;
|
||||
break;
|
||||
case 'd':
|
||||
data->flag_detached = 1;
|
||||
break;
|
||||
@@ -118,13 +123,36 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
char *cmd, *cwd, *cause;
|
||||
int idx;
|
||||
int idx, last;
|
||||
|
||||
if (data == NULL)
|
||||
return (0);
|
||||
|
||||
if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
|
||||
return (-1);
|
||||
if (data->flag_insert_after) {
|
||||
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
|
||||
return (-1);
|
||||
idx = wl->idx + 1;
|
||||
|
||||
/* Find the next free index. */
|
||||
for (last = idx; last < INT_MAX; last++) {
|
||||
if (winlink_find_by_index(&s->windows, last) == NULL)
|
||||
break;
|
||||
}
|
||||
if (last == INT_MAX) {
|
||||
ctx->error(ctx, "no free window indexes");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Move everything from last - 1 to idx up a bit. */
|
||||
for (; last > idx; last--) {
|
||||
wl = winlink_find_by_index(&s->windows, last - 1);
|
||||
server_link_window(s, wl, s, last, 0, 0, NULL);
|
||||
server_unlink_window(s, wl);
|
||||
}
|
||||
} else {
|
||||
if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
wl = NULL;
|
||||
if (idx != -1)
|
||||
@@ -134,7 +162,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
* Can't use session_detach as it will destroy session if this
|
||||
* makes it empty.
|
||||
*/
|
||||
session_alert_cancel(s, wl);
|
||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
||||
winlink_stack_remove(&s->lastw, wl);
|
||||
winlink_remove(&s->windows, wl);
|
||||
|
||||
@@ -148,10 +176,13 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
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(&s->options, "default-path");
|
||||
else
|
||||
cwd = ctx->cmdclient->cwd;
|
||||
cwd = options_get_string(&s->options, "default-path");
|
||||
if (*cwd == '\0') {
|
||||
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
|
||||
cwd = ctx->cmdclient->cwd;
|
||||
else
|
||||
cwd = s->cwd;
|
||||
}
|
||||
|
||||
if (idx == -1)
|
||||
idx = -1 - options_get_number(&s->options, "base-index");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-paste-buffer.c,v 1.24 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: cmd-paste-buffer.c,v 1.28 2010-06-06 00:03:02 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
@@ -26,32 +27,112 @@
|
||||
* Paste paste buffer if present.
|
||||
*/
|
||||
|
||||
struct cmd_paste_buffer_data {
|
||||
char *target;
|
||||
int buffer;
|
||||
|
||||
int flag_delete;
|
||||
char *sepstr;
|
||||
};
|
||||
|
||||
void cmd_paste_buffer_init(struct cmd *, int);
|
||||
int cmd_paste_buffer_parse(struct cmd *, int, char **, char **);
|
||||
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
|
||||
void cmd_paste_buffer_lf2cr(struct window_pane *, const char *, size_t);
|
||||
void cmd_paste_buffer_filter(
|
||||
struct window_pane *, const char *, size_t, char *);
|
||||
void cmd_paste_buffer_free(struct cmd *);
|
||||
size_t cmd_paste_buffer_print(struct cmd *, char *, size_t);
|
||||
|
||||
const struct cmd_entry cmd_paste_buffer_entry = {
|
||||
"paste-buffer", "pasteb",
|
||||
"[-dr] " CMD_BUFFER_WINDOW_USAGE,
|
||||
0, "dr",
|
||||
cmd_buffer_init,
|
||||
cmd_buffer_parse,
|
||||
"[-dr] [-s separator] [-b buffer-index] [-t target-window]",
|
||||
0, "",
|
||||
cmd_paste_buffer_init,
|
||||
cmd_paste_buffer_parse,
|
||||
cmd_paste_buffer_exec,
|
||||
cmd_buffer_free,
|
||||
cmd_buffer_print
|
||||
cmd_paste_buffer_free,
|
||||
cmd_paste_buffer_print
|
||||
};
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
cmd_paste_buffer_init(struct cmd *self, unused int arg)
|
||||
{
|
||||
struct cmd_paste_buffer_data *data;
|
||||
|
||||
self->data = data = xmalloc(sizeof *data);
|
||||
data->target = NULL;
|
||||
data->buffer = -1;
|
||||
data->flag_delete = 0;
|
||||
data->sepstr = xstrdup("\r");
|
||||
}
|
||||
|
||||
int
|
||||
cmd_paste_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
|
||||
{
|
||||
struct cmd_paste_buffer_data *data;
|
||||
int opt, n;
|
||||
const char *errstr;
|
||||
|
||||
cmd_paste_buffer_init(self, 0);
|
||||
data = self->data;
|
||||
|
||||
while ((opt = getopt(argc, argv, "b:ds:t:r")) != -1) {
|
||||
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 'd':
|
||||
data->flag_delete = 1;
|
||||
break;
|
||||
case 's':
|
||||
if (data->sepstr != NULL)
|
||||
xfree(data->sepstr);
|
||||
data->sepstr = xstrdup(optarg);
|
||||
break;
|
||||
case 't':
|
||||
if (data->target == NULL)
|
||||
data->target = xstrdup(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
if (data->sepstr != NULL)
|
||||
xfree(data->sepstr);
|
||||
data->sepstr = xstrdup("\n");
|
||||
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_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
{
|
||||
struct cmd_buffer_data *data = self->data;
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
struct session *s;
|
||||
struct paste_buffer *pb;
|
||||
struct cmd_paste_buffer_data *data = self->data;
|
||||
struct window_pane *wp;
|
||||
struct session *s;
|
||||
struct paste_buffer *pb;
|
||||
|
||||
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
|
||||
if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
|
||||
return (-1);
|
||||
wp = wl->window->active;
|
||||
|
||||
if (data->buffer == -1)
|
||||
pb = paste_get_top(&s->buffers);
|
||||
@@ -62,16 +143,11 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
if (pb != NULL) {
|
||||
/* -r means raw data without LF->CR conversion. */
|
||||
if (cmd_check_flag(data->chflags, 'r'))
|
||||
bufferevent_write(wp->event, pb->data, pb->size);
|
||||
else
|
||||
cmd_paste_buffer_lf2cr(wp, pb->data, pb->size);
|
||||
}
|
||||
if (pb != NULL)
|
||||
cmd_paste_buffer_filter(wp, pb->data, pb->size, data->sepstr);
|
||||
|
||||
/* Delete the buffer if -d. */
|
||||
if (cmd_check_flag(data->chflags, 'd')) {
|
||||
if (data->flag_delete) {
|
||||
if (data->buffer == -1)
|
||||
paste_free_top(&s->buffers);
|
||||
else
|
||||
@@ -81,20 +157,66 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Add bytes to a buffer but change every '\n' to '\r'. */
|
||||
/* Add bytes to a buffer and filter '\n' according to separator. */
|
||||
void
|
||||
cmd_paste_buffer_lf2cr(struct window_pane *wp, const char *data, size_t size)
|
||||
cmd_paste_buffer_filter(
|
||||
struct window_pane *wp, const char *data, size_t size, char *sep)
|
||||
{
|
||||
const char *end = data + size;
|
||||
const char *lf;
|
||||
size_t seplen;
|
||||
|
||||
seplen = strlen(sep);
|
||||
while ((lf = memchr(data, '\n', end - data)) != NULL) {
|
||||
if (lf != data)
|
||||
bufferevent_write(wp->event, data, lf - data);
|
||||
bufferevent_write(wp->event, "\r", 1);
|
||||
bufferevent_write(wp->event, sep, seplen);
|
||||
data = lf + 1;
|
||||
}
|
||||
|
||||
if (end != data)
|
||||
bufferevent_write(wp->event, data, end - data);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_paste_buffer_free(struct cmd *self)
|
||||
{
|
||||
struct cmd_paste_buffer_data *data = self->data;
|
||||
|
||||
if (data->target != NULL)
|
||||
xfree(data->target);
|
||||
if (data->sepstr != NULL)
|
||||
xfree(data->sepstr);
|
||||
xfree(data);
|
||||
}
|
||||
|
||||
size_t
|
||||
cmd_paste_buffer_print(struct cmd *self, char *buf, size_t len)
|
||||
{
|
||||
struct cmd_paste_buffer_data *data = self->data;
|
||||
size_t off = 0;
|
||||
char tmp[BUFSIZ];
|
||||
int r_flag;
|
||||
|
||||
r_flag = 0;
|
||||
if (data->sepstr != NULL)
|
||||
r_flag = (data->sepstr[0] == '\n' && data->sepstr[1] == '\0');
|
||||
|
||||
off += xsnprintf(buf, len, "%s", self->entry->name);
|
||||
if (data == NULL)
|
||||
return (off);
|
||||
if (off < len && data->flag_delete)
|
||||
off += xsnprintf(buf + off, len - off, " -d");
|
||||
if (off < len && r_flag)
|
||||
off += xsnprintf(buf + off, len - off, " -r");
|
||||
if (off < len && data->buffer != -1)
|
||||
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
|
||||
if (off < len && data->sepstr != NULL && !r_flag) {
|
||||
strnvis(
|
||||
tmp, data->sepstr, sizeof tmp, VIS_OCTAL|VIS_TAB|VIS_NL);
|
||||
off += cmd_prarg(buf + off, len - off, " -s ", tmp);
|
||||
}
|
||||
if (off < len && data->target != NULL)
|
||||
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
|
||||
return (off);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-pipe-pane.c,v 1.10 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: cmd-pipe-pane.c,v 1.13 2010-06-15 20:25:40 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
@@ -49,9 +50,14 @@ int
|
||||
cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
{
|
||||
struct cmd_target_data *data = self->data;
|
||||
struct client *c;
|
||||
struct window_pane *wp;
|
||||
char *command;
|
||||
int old_fd, pipe_fd[2], null_fd, mode;
|
||||
|
||||
if ((c = cmd_find_client(ctx, NULL)) == NULL)
|
||||
return (-1);
|
||||
|
||||
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
|
||||
return (-1);
|
||||
|
||||
@@ -90,7 +96,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
case 0:
|
||||
/* Child process. */
|
||||
close(pipe_fd[0]);
|
||||
server_signal_clear();
|
||||
clear_signals();
|
||||
|
||||
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
|
||||
_exit(1);
|
||||
@@ -105,7 +111,8 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO)
|
||||
close(null_fd);
|
||||
|
||||
execl(_PATH_BSHELL, "sh", "-c", data->arg, (char *) NULL);
|
||||
command = status_replace(c, NULL, data->arg, time(NULL), 0);
|
||||
execl(_PATH_BSHELL, "sh", "-c", command, (char *) NULL);
|
||||
_exit(1);
|
||||
default:
|
||||
/* Parent process. */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-run-shell.c,v 1.6 2009-11-14 17:56:39 tcunha Exp $ */
|
||||
/* $Id: cmd-run-shell.c,v 1.8 2010-07-17 14:36:40 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||
@@ -82,6 +82,11 @@ cmd_run_shell_callback(struct job *job)
|
||||
int retcode;
|
||||
u_int lines;
|
||||
|
||||
if (ctx->cmdclient != NULL && ctx->cmdclient->flags & CLIENT_DEAD)
|
||||
return;
|
||||
if (ctx->curclient != NULL && ctx->curclient->flags & CLIENT_DEAD)
|
||||
return;
|
||||
|
||||
lines = 0;
|
||||
do {
|
||||
if ((line = evbuffer_readline(job->event->input)) != NULL) {
|
||||
@@ -126,10 +131,13 @@ cmd_run_shell_free(void *data)
|
||||
{
|
||||
struct cmd_run_shell_data *cdata = data;
|
||||
struct cmd_ctx *ctx = &cdata->ctx;
|
||||
struct msg_exit_data exitdata;
|
||||
|
||||
if (ctx->cmdclient != NULL) {
|
||||
ctx->cmdclient->references--;
|
||||
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
|
||||
exitdata.retcode = ctx->cmdclient->retcode;
|
||||
server_write_client(
|
||||
ctx->cmdclient, MSG_EXIT, &exitdata, sizeof exitdata);
|
||||
}
|
||||
if (ctx->curclient != NULL)
|
||||
ctx->curclient->references--;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-save-buffer.c,v 1.10 2009-11-14 17:56:39 tcunha Exp $ */
|
||||
/* $Id: cmd-save-buffer.c,v 1.11 2010-07-02 02:52:13 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||
@@ -48,7 +48,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct session *s;
|
||||
struct paste_buffer *pb;
|
||||
mode_t mask;
|
||||
FILE *f;
|
||||
FILE *f, *close_f;
|
||||
|
||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||
return (-1);
|
||||
@@ -65,15 +65,25 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
mask = umask(S_IRWXG | S_IRWXO);
|
||||
if (cmd_check_flag(data->chflags, 'a'))
|
||||
f = fopen(data->arg, "ab");
|
||||
else
|
||||
f = fopen(data->arg, "wb");
|
||||
umask(mask);
|
||||
if (f == NULL) {
|
||||
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
||||
return (-1);
|
||||
if (strcmp(data->arg, "-") == 0) {
|
||||
if (ctx->cmdclient == NULL) {
|
||||
ctx->error(ctx, "%s: can't write to stdout", data->arg);
|
||||
return (-1);
|
||||
}
|
||||
f = ctx->cmdclient->stdout_file;
|
||||
close_f = NULL;
|
||||
} else {
|
||||
mask = umask(S_IRWXG | S_IRWXO);
|
||||
if (cmd_check_flag(data->chflags, 'a'))
|
||||
f = fopen(data->arg, "ab");
|
||||
else
|
||||
f = fopen(data->arg, "wb");
|
||||
umask(mask);
|
||||
if (f == NULL) {
|
||||
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
close_f = f;
|
||||
}
|
||||
|
||||
if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
|
||||
@@ -82,7 +92,8 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
if (close_f != NULL)
|
||||
fclose(close_f);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-select-layout.c,v 1.10 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: cmd-select-layout.c,v 1.12 2010-07-02 02:54:52 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -59,6 +59,9 @@ cmd_select_layout_init(struct cmd *self, int key)
|
||||
case ('4' | KEYC_ESCAPE):
|
||||
data->arg = xstrdup("main-vertical");
|
||||
break;
|
||||
case ('5' | KEYC_ESCAPE):
|
||||
data->arg = xstrdup("tiled");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,13 +79,16 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
layout = wl->window->lastlayout;
|
||||
if (layout == -1)
|
||||
return (0);
|
||||
} else if ((layout = layout_set_lookup(data->arg)) == -1) {
|
||||
ctx->error(ctx, "unknown layout or ambiguous: %s", data->arg);
|
||||
return (-1);
|
||||
} else if ((layout = layout_set_lookup(data->arg)) != -1) {
|
||||
layout = layout_set_select(wl->window, layout);
|
||||
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
|
||||
} else {
|
||||
if (layout_parse(wl->window, data->arg) == -1) {
|
||||
ctx->error(ctx, "can't set layout: %s", data->arg);
|
||||
return (-1);
|
||||
}
|
||||
ctx->info(ctx, "arranging in: %s", data->arg);
|
||||
}
|
||||
|
||||
layout = layout_set_select(wl->window, layout);
|
||||
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-select-pane.c,v 1.12 2010-01-05 23:52:37 tcunha Exp $ */
|
||||
/* $Id: cmd-select-pane.c,v 1.13 2010-03-15 22:03:38 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -24,19 +24,40 @@
|
||||
* Select pane.
|
||||
*/
|
||||
|
||||
void cmd_select_pane_init(struct cmd *, int);
|
||||
int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
|
||||
|
||||
const struct cmd_entry cmd_select_pane_entry = {
|
||||
"select-pane", "selectp",
|
||||
CMD_TARGET_PANE_USAGE,
|
||||
0, "",
|
||||
cmd_target_init,
|
||||
"[-DLRU] " CMD_TARGET_PANE_USAGE,
|
||||
0, "DLRU",
|
||||
cmd_select_pane_init,
|
||||
cmd_target_parse,
|
||||
cmd_select_pane_exec,
|
||||
cmd_target_free,
|
||||
cmd_target_print
|
||||
};
|
||||
|
||||
void
|
||||
cmd_select_pane_init(struct cmd *self, int key)
|
||||
{
|
||||
struct cmd_target_data *data;
|
||||
|
||||
cmd_target_init(self, key);
|
||||
data = self->data;
|
||||
|
||||
if (key == KEYC_UP)
|
||||
cmd_set_flag(&data->chflags, 'U');
|
||||
if (key == KEYC_DOWN)
|
||||
cmd_set_flag(&data->chflags, 'D');
|
||||
if (key == KEYC_LEFT)
|
||||
cmd_set_flag(&data->chflags, 'L');
|
||||
if (key == KEYC_RIGHT)
|
||||
cmd_set_flag(&data->chflags, 'R');
|
||||
if (key == 'o')
|
||||
data->target = xstrdup(":.+");
|
||||
}
|
||||
|
||||
int
|
||||
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
{
|
||||
@@ -51,6 +72,20 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
ctx->error(ctx, "pane not visible: %s", data->target);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (cmd_check_flag(data->chflags, 'L'))
|
||||
wp = window_pane_find_left(wp);
|
||||
else if (cmd_check_flag(data->chflags, 'R'))
|
||||
wp = window_pane_find_right(wp);
|
||||
else if (cmd_check_flag(data->chflags, 'U'))
|
||||
wp = window_pane_find_up(wp);
|
||||
else if (cmd_check_flag(data->chflags, 'D'))
|
||||
wp = window_pane_find_down(wp);
|
||||
if (wp == NULL) {
|
||||
ctx->error(ctx, "pane not found");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
window_set_active_pane(wl->window, wp);
|
||||
server_status_window(wl->window);
|
||||
server_redraw_window_borders(wl->window);
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/* $Id: cmd-select-prompt.c,v 1.13 2009-11-14 17:56:39 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* 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_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, NULL, 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 || *s == '\0')
|
||||
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, "%s", 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, "%s", msg);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (session_select(c->session, idx) == 0)
|
||||
server_redraw_session(c->session);
|
||||
recalculate_sizes();
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-send-keys.c,v 1.24 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: cmd-send-keys.c,v 1.25 2010-05-22 21:56:04 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -105,16 +105,17 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
{
|
||||
struct cmd_send_keys_data *data = self->data;
|
||||
struct window_pane *wp;
|
||||
struct session *s;
|
||||
u_int i;
|
||||
|
||||
if (data == NULL)
|
||||
return (-1);
|
||||
|
||||
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
|
||||
if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
|
||||
return (-1);
|
||||
|
||||
for (i = 0; i < data->nkeys; i++)
|
||||
window_pane_key(wp, ctx->curclient, data->keys[i]);
|
||||
window_pane_key(wp, s, data->keys[i]);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-send-prefix.c,v 1.28 2009-11-14 17:56:39 tcunha Exp $ */
|
||||
/* $Id: cmd-send-prefix.c,v 1.29 2010-05-22 21:56:04 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -49,7 +49,7 @@ cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
return (-1);
|
||||
|
||||
keylist = options_get_data(&s->options, "prefix");
|
||||
window_pane_key(wp, ctx->curclient, ARRAY_FIRST(keylist));
|
||||
window_pane_key(wp, s, ARRAY_FIRST(keylist));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-set-option.c,v 1.96 2010-02-26 13:31:39 tcunha Exp $ */
|
||||
/* $Id: cmd-set-option.c,v 1.98 2010-07-02 02:45:52 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -87,6 +87,7 @@ const struct set_option_entry set_session_option_table[] = {
|
||||
{ "default-path", SET_OPTION_STRING, 0, 0, NULL },
|
||||
{ "default-shell", SET_OPTION_STRING, 0, 0, NULL },
|
||||
{ "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
|
||||
{ "detach-on-destroy", SET_OPTION_FLAG, 0, 0, NULL },
|
||||
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||
{ "display-panes-active-colour", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||
{ "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
|
||||
@@ -157,6 +158,9 @@ const struct set_option_entry set_window_option_table[] = {
|
||||
{ "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
|
||||
{ "synchronize-panes", SET_OPTION_FLAG, 0, 0, NULL },
|
||||
{ "utf8", SET_OPTION_FLAG, 0, 0, NULL },
|
||||
{ "window-status-alert-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
||||
{ "window-status-alert-bg", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||
{ "window-status-alert-fg", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||
{ "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
||||
{ "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||
{ "window-status-current-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd-split-window.c,v 1.34 2010-01-08 16:31:35 tcunha Exp $ */
|
||||
/* $Id: cmd-split-window.c,v 1.35 2010-07-02 02:49:19 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -169,10 +169,13 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
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(&s->options, "default-path");
|
||||
else
|
||||
cwd = ctx->cmdclient->cwd;
|
||||
cwd = options_get_string(&s->options, "default-path");
|
||||
if (*cwd == '\0') {
|
||||
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
|
||||
cwd = ctx->cmdclient->cwd;
|
||||
else
|
||||
cwd = s->cwd;
|
||||
}
|
||||
|
||||
type = LAYOUT_TOPBOTTOM;
|
||||
if (data->flag_horizontal)
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/* $Id: cmd-up-pane.c,v 1.14 2010-01-05 23:52:37 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* 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_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);
|
||||
} while (!window_pane_visible(w->active));
|
||||
server_status_window(wl->window);
|
||||
server_redraw_window_borders(wl->window);
|
||||
|
||||
return (0);
|
||||
}
|
||||
176
cmd.c
176
cmd.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: cmd.c,v 1.137 2010-01-22 17:28:34 tcunha Exp $ */
|
||||
/* $Id: cmd.c,v 1.142 2010-07-17 14:38:13 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -31,6 +31,7 @@ const struct cmd_entry *cmd_table[] = {
|
||||
&cmd_bind_key_entry,
|
||||
&cmd_break_pane_entry,
|
||||
&cmd_capture_pane_entry,
|
||||
&cmd_choose_buffer_entry,
|
||||
&cmd_choose_client_entry,
|
||||
&cmd_choose_session_entry,
|
||||
&cmd_choose_window_entry,
|
||||
@@ -44,7 +45,6 @@ const struct cmd_entry *cmd_table[] = {
|
||||
&cmd_detach_client_entry,
|
||||
&cmd_display_message_entry,
|
||||
&cmd_display_panes_entry,
|
||||
&cmd_down_pane_entry,
|
||||
&cmd_find_window_entry,
|
||||
&cmd_has_session_entry,
|
||||
&cmd_if_shell_entry,
|
||||
@@ -85,7 +85,6 @@ const struct cmd_entry *cmd_table[] = {
|
||||
&cmd_save_buffer_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,
|
||||
@@ -108,7 +107,6 @@ const struct cmd_entry *cmd_table[] = {
|
||||
&cmd_switch_client_entry,
|
||||
&cmd_unbind_key_entry,
|
||||
&cmd_unlink_window_entry,
|
||||
&cmd_up_pane_entry,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -118,6 +116,9 @@ struct client *cmd_lookup_client(const char *);
|
||||
struct session *cmd_lookup_session(const char *, int *);
|
||||
struct winlink *cmd_lookup_window(struct session *, const char *, int *);
|
||||
int cmd_lookup_index(struct session *, const char *, int *);
|
||||
struct winlink *cmd_find_window_offset(const char *, struct session *, int *);
|
||||
int cmd_find_index_offset(const char *, struct session *, int *);
|
||||
struct window_pane *cmd_find_pane_offset(const char *, struct winlink *);
|
||||
|
||||
int
|
||||
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
|
||||
@@ -540,7 +541,7 @@ cmd_lookup_session(const char *name, int *ambiguous)
|
||||
/*
|
||||
* Lookup a window or return -1 if not found or ambigious. First try as an
|
||||
* index and if invalid, use fnmatch or leading prefix. Return NULL but fill in
|
||||
* idx if the window index is a valid number but there is now window with that
|
||||
* idx if the window index is a valid number but there is no window with that
|
||||
* index.
|
||||
*/
|
||||
struct winlink *
|
||||
@@ -707,10 +708,8 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
|
||||
wl = s->curw;
|
||||
else if (winptr[0] == '!' && winptr[1] == '\0')
|
||||
wl = TAILQ_FIRST(&s->lastw);
|
||||
else if (winptr[0] == '+' && winptr[1] == '\0')
|
||||
wl = winlink_next(s->curw);
|
||||
else if (winptr[0] == '-' && winptr[1] == '\0')
|
||||
wl = winlink_previous(s->curw);
|
||||
else if (winptr[0] == '+' || winptr[0] == '-')
|
||||
wl = cmd_find_window_offset(winptr, s, &ambiguous);
|
||||
else
|
||||
wl = cmd_lookup_window(s, winptr, &ambiguous);
|
||||
if (wl == NULL)
|
||||
@@ -728,25 +727,28 @@ no_colon:
|
||||
if (arg[0] == '!' && arg[1] == '\0') {
|
||||
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
||||
goto not_found;
|
||||
} else if (arg[0] == '+' && arg[1] == '\0') {
|
||||
if ((wl = winlink_next(s->curw)) == NULL)
|
||||
goto not_found;
|
||||
} else if (arg[0] == '-' && arg[1] == '\0') {
|
||||
if ((wl = winlink_previous(s->curw)) == NULL)
|
||||
goto not_found;
|
||||
} else if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL) {
|
||||
if (ambiguous)
|
||||
goto not_found;
|
||||
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
|
||||
goto no_session;
|
||||
wl = s->curw;
|
||||
}
|
||||
} else if (arg[0] == '+' || arg[0] == '-') {
|
||||
if ((wl = cmd_find_window_offset(arg, s, &ambiguous)) == NULL)
|
||||
goto lookup_session;
|
||||
} else if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL)
|
||||
goto lookup_session;
|
||||
|
||||
if (sp != NULL)
|
||||
*sp = s;
|
||||
|
||||
return (wl);
|
||||
|
||||
lookup_session:
|
||||
if (ambiguous)
|
||||
goto not_found;
|
||||
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
|
||||
goto no_session;
|
||||
|
||||
if (sp != NULL)
|
||||
*sp = s;
|
||||
|
||||
return (s->curw);
|
||||
|
||||
no_session:
|
||||
if (ambiguous)
|
||||
ctx->error(ctx, "multiple sessions: %s", arg);
|
||||
@@ -766,6 +768,26 @@ not_found:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct winlink *
|
||||
cmd_find_window_offset(const char *winptr, struct session *s, int *ambiguous)
|
||||
{
|
||||
struct winlink *wl;
|
||||
int offset = 1;
|
||||
|
||||
if (winptr[1] != '\0')
|
||||
offset = strtonum(winptr + 1, 1, INT_MAX, NULL);
|
||||
if (offset == 0)
|
||||
wl = cmd_lookup_window(s, winptr, ambiguous);
|
||||
else {
|
||||
if (winptr[0] == '+')
|
||||
wl = winlink_next_by_number(s->curw, s, offset);
|
||||
else
|
||||
wl = winlink_previous_by_number(s->curw, s, offset);
|
||||
}
|
||||
|
||||
return (wl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the target session and window index, whether or not it exists in the
|
||||
* session. Return -2 on error or -1 if no window index is specified. This is
|
||||
@@ -827,20 +849,11 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
|
||||
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
||||
goto not_found;
|
||||
idx = wl->idx;
|
||||
} else if (winptr[0] == '+' && winptr[1] == '\0') {
|
||||
if (s->curw->idx == INT_MAX)
|
||||
goto not_found;
|
||||
idx = s->curw->idx + 1;
|
||||
} else if (winptr[0] == '-' && winptr[1] == '\0') {
|
||||
if (s->curw->idx == 0)
|
||||
goto not_found;
|
||||
idx = s->curw->idx - 1;
|
||||
} else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1) {
|
||||
if (ambiguous)
|
||||
goto not_found;
|
||||
ctx->error(ctx, "invalid index: %s", arg);
|
||||
idx = -2;
|
||||
}
|
||||
} else if (winptr[0] == '+' || winptr[0] == '-') {
|
||||
if ((idx = cmd_find_index_offset(winptr, s, &ambiguous)) < 0)
|
||||
goto invalid_index;
|
||||
} else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1)
|
||||
goto invalid_index;
|
||||
|
||||
if (sessptr != NULL)
|
||||
xfree(sessptr);
|
||||
@@ -855,27 +868,28 @@ no_colon:
|
||||
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
||||
goto not_found;
|
||||
idx = wl->idx;
|
||||
} else if (arg[0] == '+' && arg[1] == '\0') {
|
||||
if (s->curw->idx == INT_MAX)
|
||||
goto not_found;
|
||||
idx = s->curw->idx + 1;
|
||||
} else if (arg[0] == '-' && arg[1] == '\0') {
|
||||
if (s->curw->idx == 0)
|
||||
goto not_found;
|
||||
idx = s->curw->idx - 1;
|
||||
} else if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1) {
|
||||
if (ambiguous)
|
||||
goto not_found;
|
||||
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
|
||||
goto no_session;
|
||||
idx = -1;
|
||||
}
|
||||
} else if (arg[0] == '+' || arg[0] == '-') {
|
||||
if ((idx = cmd_find_index_offset(arg, s, &ambiguous)) < 0)
|
||||
goto lookup_session;
|
||||
} else if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1)
|
||||
goto lookup_session;
|
||||
|
||||
if (sp != NULL)
|
||||
*sp = s;
|
||||
|
||||
return (idx);
|
||||
|
||||
lookup_session:
|
||||
if (ambiguous)
|
||||
goto not_found;
|
||||
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
|
||||
goto no_session;
|
||||
|
||||
if (sp != NULL)
|
||||
*sp = s;
|
||||
|
||||
return (-1);
|
||||
|
||||
no_session:
|
||||
if (ambiguous)
|
||||
ctx->error(ctx, "multiple sessions: %s", arg);
|
||||
@@ -885,6 +899,15 @@ no_session:
|
||||
xfree(sessptr);
|
||||
return (-2);
|
||||
|
||||
invalid_index:
|
||||
if (ambiguous)
|
||||
goto not_found;
|
||||
ctx->error(ctx, "invalid index: %s", arg);
|
||||
|
||||
if (sessptr != NULL)
|
||||
xfree(sessptr);
|
||||
return (-2);
|
||||
|
||||
not_found:
|
||||
if (ambiguous)
|
||||
ctx->error(ctx, "multiple windows: %s", arg);
|
||||
@@ -895,6 +918,32 @@ not_found:
|
||||
return (-2);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_find_index_offset(const char *winptr, struct session *s, int *ambiguous)
|
||||
{
|
||||
int idx, offset = 1;
|
||||
|
||||
if (winptr[1] != '\0')
|
||||
offset = strtonum(winptr + 1, 1, INT_MAX, NULL);
|
||||
if (offset == 0)
|
||||
idx = cmd_lookup_index(s, winptr, ambiguous);
|
||||
else {
|
||||
if (winptr[0] == '+') {
|
||||
if (s->curw->idx == INT_MAX)
|
||||
idx = cmd_lookup_index(s, winptr, ambiguous);
|
||||
else
|
||||
idx = s->curw->idx + offset;
|
||||
} else {
|
||||
if (s->curw->idx == 0)
|
||||
idx = cmd_lookup_index(s, winptr, ambiguous);
|
||||
else
|
||||
idx = s->curw->idx - offset;
|
||||
}
|
||||
}
|
||||
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the target session, window and pane number or report an error and
|
||||
* return NULL. The pane number is separated from the session:window by a .,
|
||||
@@ -941,6 +990,8 @@ cmd_find_pane(struct cmd_ctx *ctx,
|
||||
paneptr = winptr + (period - arg) + 1;
|
||||
if (*paneptr == '\0')
|
||||
*wpp = wl->window->active;
|
||||
else if (paneptr[0] == '+' || paneptr[0] == '-')
|
||||
*wpp = cmd_find_pane_offset(paneptr, wl);
|
||||
else {
|
||||
idx = strtonum(paneptr, 0, INT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
@@ -955,14 +1006,14 @@ cmd_find_pane(struct cmd_ctx *ctx,
|
||||
|
||||
lookup_string:
|
||||
/* Try pane string description. */
|
||||
if ((lc = layout_find_string(s->curw->window, paneptr)) == NULL) {
|
||||
if ((lc = layout_find_string(wl->window, paneptr)) == NULL) {
|
||||
ctx->error(ctx, "can't find pane: %s", paneptr);
|
||||
goto error;
|
||||
}
|
||||
*wpp = lc->wp;
|
||||
|
||||
xfree(winptr);
|
||||
return (s->curw);
|
||||
return (wl);
|
||||
|
||||
no_period:
|
||||
/* Try as a pane number alone. */
|
||||
@@ -993,6 +1044,25 @@ error:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct window_pane *
|
||||
cmd_find_pane_offset(const char *paneptr, struct winlink *wl)
|
||||
{
|
||||
struct window *w = wl->window;
|
||||
struct window_pane *wp = w->active;
|
||||
u_int offset = 1;
|
||||
|
||||
if (paneptr[1] != '\0')
|
||||
offset = strtonum(paneptr + 1, 1, INT_MAX, NULL);
|
||||
if (offset > 0) {
|
||||
if (paneptr[0] == '+')
|
||||
wp = window_pane_next_by_number(w, wp, offset);
|
||||
else
|
||||
wp = window_pane_previous_by_number(w, wp, offset);
|
||||
}
|
||||
|
||||
return (wp);
|
||||
}
|
||||
|
||||
/* Replace the first %% or %idx in template by s. */
|
||||
char *
|
||||
cmd_template_replace(char *template, const char *s, int idx)
|
||||
|
||||
43
compat.h
43
compat.h
@@ -1,4 +1,4 @@
|
||||
/* $Id: compat.h,v 1.20 2009-11-08 22:51:34 tcunha Exp $ */
|
||||
/* $Id: compat.h,v 1.25 2010-06-06 13:00:46 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -42,7 +42,7 @@ typedef uint64_t u_int64_t;
|
||||
#else
|
||||
#include "compat/tree.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_BITSTRING_H
|
||||
#include <bitstring.h>
|
||||
#else
|
||||
@@ -81,17 +81,36 @@ typedef uint64_t u_int64_t;
|
||||
|
||||
#ifndef HAVE_IMSG
|
||||
#include "compat/imsg.h"
|
||||
#else
|
||||
#include <imsg.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_CMSG_FIRSTHDR
|
||||
/* Broken on OS X. */
|
||||
/* CMSG_FIRSTHDR broken on OS X. */
|
||||
#undef CMSG_FIRSTHDR
|
||||
#define CMSG_FIRSTHDR(mhdr) \
|
||||
((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
|
||||
(struct cmsghdr *)(mhdr)->msg_control : \
|
||||
((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
|
||||
(struct cmsghdr *)(mhdr)->msg_control : \
|
||||
(struct cmsghdr *)NULL)
|
||||
#endif
|
||||
|
||||
/* CMSG_ALIGN, CMSG_SPACE, CMSG_LEN missing from Solaris 9. */
|
||||
#ifndef CMSG_ALIGN
|
||||
#ifdef __sun
|
||||
#define CMSG_ALIGN _CMSG_DATA_ALIGN
|
||||
#else
|
||||
#define CMSG_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long) - 1))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CMSG_SPACE
|
||||
#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
|
||||
#endif
|
||||
|
||||
#ifndef CMSG_LEN
|
||||
#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
|
||||
#endif
|
||||
|
||||
#ifndef INFTIM
|
||||
#define INFTIM -1
|
||||
#endif
|
||||
@@ -135,7 +154,7 @@ typedef uint64_t u_int64_t;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BZERO
|
||||
#define bzero(buf, len) memset((buf), 0, (len));
|
||||
#define bzero(buf, len) memset(buf, 0, len);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRCASESTR
|
||||
@@ -175,13 +194,19 @@ pid_t forkpty(int *, char *, struct termios *, struct winsize *);
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
/* asprintf.c */
|
||||
int asprintf(char **, const char *, ...);
|
||||
int vasprintf(char **, const char *, va_list);
|
||||
int asprintf(char **, const char *, ...);
|
||||
int vasprintf(char **, const char *, va_list);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FGETLN
|
||||
/* fgetln.c */
|
||||
char *fgetln(FILE *, size_t *);
|
||||
char *fgetln(FILE *, size_t *);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SETENV
|
||||
/* setenv.c */
|
||||
int setenv(const char *, const char *, int);
|
||||
int unsetenv(const char *);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETOPT
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* $Id: imsg-buffer.c,v 1.4 2009-09-15 23:59:40 tcunha Exp $ */
|
||||
/* $OpenBSD: imsg-buffer.c,v 1.2 2009/09/15 18:12:51 jacekm Exp $ */
|
||||
/* $Id: imsg-buffer.c,v 1.5 2010-06-06 00:08:28 tcunha Exp $ */
|
||||
/* $OpenBSD: imsg-buffer.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||
@@ -28,16 +28,16 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
int buf_realloc(struct buf *, size_t);
|
||||
void buf_enqueue(struct msgbuf *, struct buf *);
|
||||
void buf_dequeue(struct msgbuf *, struct buf *);
|
||||
int ibuf_realloc(struct ibuf *, size_t);
|
||||
void ibuf_enqueue(struct msgbuf *, struct ibuf *);
|
||||
void ibuf_dequeue(struct msgbuf *, struct ibuf *);
|
||||
|
||||
struct buf *
|
||||
buf_open(size_t len)
|
||||
struct ibuf *
|
||||
ibuf_open(size_t len)
|
||||
{
|
||||
struct buf *buf;
|
||||
struct ibuf *buf;
|
||||
|
||||
if ((buf = calloc(1, sizeof(struct buf))) == NULL)
|
||||
if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
|
||||
return (NULL);
|
||||
if ((buf->buf = malloc(len)) == NULL) {
|
||||
free(buf);
|
||||
@@ -49,15 +49,15 @@ buf_open(size_t len)
|
||||
return (buf);
|
||||
}
|
||||
|
||||
struct buf *
|
||||
buf_dynamic(size_t len, size_t max)
|
||||
struct ibuf *
|
||||
ibuf_dynamic(size_t len, size_t max)
|
||||
{
|
||||
struct buf *buf;
|
||||
struct ibuf *buf;
|
||||
|
||||
if (max < len)
|
||||
return (NULL);
|
||||
|
||||
if ((buf = buf_open(len)) == NULL)
|
||||
if ((buf = ibuf_open(len)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (max > 0)
|
||||
@@ -67,7 +67,7 @@ buf_dynamic(size_t len, size_t max)
|
||||
}
|
||||
|
||||
int
|
||||
buf_realloc(struct buf *buf, size_t len)
|
||||
ibuf_realloc(struct ibuf *buf, size_t len)
|
||||
{
|
||||
u_char *b;
|
||||
|
||||
@@ -87,10 +87,10 @@ buf_realloc(struct buf *buf, size_t len)
|
||||
}
|
||||
|
||||
int
|
||||
buf_add(struct buf *buf, const void *data, size_t len)
|
||||
ibuf_add(struct ibuf *buf, const void *data, size_t len)
|
||||
{
|
||||
if (buf->wpos + len > buf->size)
|
||||
if (buf_realloc(buf, len) == -1)
|
||||
if (ibuf_realloc(buf, len) == -1)
|
||||
return (-1);
|
||||
|
||||
memcpy(buf->buf + buf->wpos, data, len);
|
||||
@@ -99,12 +99,12 @@ buf_add(struct buf *buf, const void *data, size_t len)
|
||||
}
|
||||
|
||||
void *
|
||||
buf_reserve(struct buf *buf, size_t len)
|
||||
ibuf_reserve(struct ibuf *buf, size_t len)
|
||||
{
|
||||
void *b;
|
||||
|
||||
if (buf->wpos + len > buf->size)
|
||||
if (buf_realloc(buf, len) == -1)
|
||||
if (ibuf_realloc(buf, len) == -1)
|
||||
return (NULL);
|
||||
|
||||
b = buf->buf + buf->wpos;
|
||||
@@ -113,7 +113,7 @@ buf_reserve(struct buf *buf, size_t len)
|
||||
}
|
||||
|
||||
void *
|
||||
buf_seek(struct buf *buf, size_t pos, size_t len)
|
||||
ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
|
||||
{
|
||||
/* only allowed to seek in already written parts */
|
||||
if (pos + len > buf->wpos)
|
||||
@@ -123,28 +123,28 @@ buf_seek(struct buf *buf, size_t pos, size_t len)
|
||||
}
|
||||
|
||||
size_t
|
||||
buf_size(struct buf *buf)
|
||||
ibuf_size(struct ibuf *buf)
|
||||
{
|
||||
return (buf->wpos);
|
||||
}
|
||||
|
||||
size_t
|
||||
buf_left(struct buf *buf)
|
||||
ibuf_left(struct ibuf *buf)
|
||||
{
|
||||
return (buf->max - buf->wpos);
|
||||
}
|
||||
|
||||
void
|
||||
buf_close(struct msgbuf *msgbuf, struct buf *buf)
|
||||
ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
{
|
||||
buf_enqueue(msgbuf, buf);
|
||||
ibuf_enqueue(msgbuf, buf);
|
||||
}
|
||||
|
||||
int
|
||||
buf_write(struct msgbuf *msgbuf)
|
||||
ibuf_write(struct msgbuf *msgbuf)
|
||||
{
|
||||
struct iovec iov[IOV_MAX];
|
||||
struct buf *buf;
|
||||
struct ibuf *buf;
|
||||
unsigned int i = 0;
|
||||
ssize_t n;
|
||||
|
||||
@@ -176,7 +176,7 @@ buf_write(struct msgbuf *msgbuf)
|
||||
}
|
||||
|
||||
void
|
||||
buf_free(struct buf *buf)
|
||||
ibuf_free(struct ibuf *buf)
|
||||
{
|
||||
free(buf->buf);
|
||||
free(buf);
|
||||
@@ -193,14 +193,14 @@ msgbuf_init(struct msgbuf *msgbuf)
|
||||
void
|
||||
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
|
||||
{
|
||||
struct buf *buf, *next;
|
||||
struct ibuf *buf, *next;
|
||||
|
||||
for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
|
||||
buf = next) {
|
||||
next = TAILQ_NEXT(buf, entry);
|
||||
if (buf->rpos + n >= buf->wpos) {
|
||||
n -= buf->wpos - buf->rpos;
|
||||
buf_dequeue(msgbuf, buf);
|
||||
ibuf_dequeue(msgbuf, buf);
|
||||
} else {
|
||||
buf->rpos += n;
|
||||
n = 0;
|
||||
@@ -211,17 +211,17 @@ msgbuf_drain(struct msgbuf *msgbuf, size_t n)
|
||||
void
|
||||
msgbuf_clear(struct msgbuf *msgbuf)
|
||||
{
|
||||
struct buf *buf;
|
||||
struct ibuf *buf;
|
||||
|
||||
while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
|
||||
buf_dequeue(msgbuf, buf);
|
||||
ibuf_dequeue(msgbuf, buf);
|
||||
}
|
||||
|
||||
int
|
||||
msgbuf_write(struct msgbuf *msgbuf)
|
||||
{
|
||||
struct iovec iov[IOV_MAX];
|
||||
struct buf *buf;
|
||||
struct ibuf *buf;
|
||||
unsigned int i = 0;
|
||||
ssize_t n;
|
||||
struct msghdr msg;
|
||||
@@ -284,14 +284,14 @@ msgbuf_write(struct msgbuf *msgbuf)
|
||||
}
|
||||
|
||||
void
|
||||
buf_enqueue(struct msgbuf *msgbuf, struct buf *buf)
|
||||
ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
|
||||
msgbuf->queued++;
|
||||
}
|
||||
|
||||
void
|
||||
buf_dequeue(struct msgbuf *msgbuf, struct buf *buf)
|
||||
ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
{
|
||||
TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
|
||||
|
||||
@@ -299,5 +299,5 @@ buf_dequeue(struct msgbuf *msgbuf, struct buf *buf)
|
||||
close(buf->fd);
|
||||
|
||||
msgbuf->queued--;
|
||||
buf_free(buf);
|
||||
ibuf_free(buf);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* $Id: imsg.c,v 1.3 2009-08-20 12:54:08 nicm Exp $ */
|
||||
/* $OpenBSD: imsg.c,v 1.1 2009/08/11 17:18:35 nicm Exp $ */
|
||||
/* $Id: imsg.c,v 1.5 2010-06-06 00:08:28 tcunha Exp $ */
|
||||
/* $OpenBSD: imsg.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||
@@ -79,7 +79,7 @@ imsg_read(struct imsgbuf *ibuf)
|
||||
cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
fd = (*(int *)CMSG_DATA(cmsg));
|
||||
if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) {
|
||||
/* XXX: this return can leak */
|
||||
close(fd);
|
||||
return (-1);
|
||||
}
|
||||
ifd->fd = fd;
|
||||
@@ -135,7 +135,7 @@ int
|
||||
imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
pid_t pid, int fd, void *data, u_int16_t datalen)
|
||||
{
|
||||
struct buf *wbuf;
|
||||
struct ibuf *wbuf;
|
||||
|
||||
if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
|
||||
return (-1);
|
||||
@@ -154,7 +154,7 @@ int
|
||||
imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
pid_t pid, int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
struct buf *wbuf;
|
||||
struct ibuf *wbuf;
|
||||
int i, datalen = 0;
|
||||
|
||||
for (i = 0; i < iovcnt; i++)
|
||||
@@ -175,11 +175,11 @@ imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
struct buf *
|
||||
struct ibuf *
|
||||
imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
pid_t pid, u_int16_t datalen)
|
||||
{
|
||||
struct buf *wbuf;
|
||||
struct ibuf *wbuf;
|
||||
struct imsg_hdr hdr;
|
||||
|
||||
datalen += IMSG_HEADER_SIZE;
|
||||
@@ -193,7 +193,7 @@ imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
hdr.peerid = peerid;
|
||||
if ((hdr.pid = pid) == 0)
|
||||
hdr.pid = ibuf->pid;
|
||||
if ((wbuf = buf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
|
||||
if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
|
||||
@@ -203,18 +203,18 @@ imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||
}
|
||||
|
||||
int
|
||||
imsg_add(struct buf *msg, void *data, u_int16_t datalen)
|
||||
imsg_add(struct ibuf *msg, void *data, u_int16_t datalen)
|
||||
{
|
||||
if (datalen)
|
||||
if (buf_add(msg, data, datalen) == -1) {
|
||||
buf_free(msg);
|
||||
if (ibuf_add(msg, data, datalen) == -1) {
|
||||
ibuf_free(msg);
|
||||
return (-1);
|
||||
}
|
||||
return (datalen);
|
||||
}
|
||||
|
||||
void
|
||||
imsg_close(struct imsgbuf *ibuf, struct buf *msg)
|
||||
imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
|
||||
{
|
||||
struct imsg_hdr *hdr;
|
||||
|
||||
@@ -226,7 +226,7 @@ imsg_close(struct imsgbuf *ibuf, struct buf *msg)
|
||||
|
||||
hdr->len = (u_int16_t)msg->wpos;
|
||||
|
||||
buf_close(&ibuf->w, msg);
|
||||
ibuf_close(&ibuf->w, msg);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* $Id: imsg.h,v 1.4 2009-09-15 23:59:40 tcunha Exp $ */
|
||||
/* $OpenBSD: imsg.h,v 1.2 2009/09/15 18:12:51 jacekm Exp $ */
|
||||
/* $Id: imsg.h,v 1.5 2010-06-06 00:08:28 tcunha Exp $ */
|
||||
/* $OpenBSD: imsg.h,v 1.4 2010/05/26 13:56:07 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
|
||||
@@ -21,12 +21,12 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
#define READ_BUF_SIZE 65535
|
||||
#define IBUF_READ_SIZE 65535
|
||||
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
|
||||
#define MAX_IMSGSIZE 16384
|
||||
|
||||
struct buf {
|
||||
TAILQ_ENTRY(buf) entry;
|
||||
struct ibuf {
|
||||
TAILQ_ENTRY(ibuf) entry;
|
||||
u_char *buf;
|
||||
size_t size;
|
||||
size_t max;
|
||||
@@ -36,13 +36,13 @@ struct buf {
|
||||
};
|
||||
|
||||
struct msgbuf {
|
||||
TAILQ_HEAD(, buf) bufs;
|
||||
TAILQ_HEAD(, ibuf) bufs;
|
||||
u_int32_t queued;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct buf_read {
|
||||
u_char buf[READ_BUF_SIZE];
|
||||
struct ibuf_read {
|
||||
u_char buf[IBUF_READ_SIZE];
|
||||
u_char *rptr;
|
||||
size_t wpos;
|
||||
};
|
||||
@@ -54,7 +54,7 @@ struct imsg_fd {
|
||||
|
||||
struct imsgbuf {
|
||||
TAILQ_HEAD(, imsg_fd) fds;
|
||||
struct buf_read r;
|
||||
struct ibuf_read r;
|
||||
struct msgbuf w;
|
||||
int fd;
|
||||
pid_t pid;
|
||||
@@ -78,16 +78,16 @@ struct imsg {
|
||||
|
||||
|
||||
/* buffer.c */
|
||||
struct buf *buf_open(size_t);
|
||||
struct buf *buf_dynamic(size_t, size_t);
|
||||
int buf_add(struct buf *, const void *, size_t);
|
||||
void *buf_reserve(struct buf *, size_t);
|
||||
void *buf_seek(struct buf *, size_t, size_t);
|
||||
size_t buf_size(struct buf *);
|
||||
size_t buf_left(struct buf *);
|
||||
void buf_close(struct msgbuf *, struct buf *);
|
||||
int buf_write(struct msgbuf *);
|
||||
void buf_free(struct buf *);
|
||||
struct ibuf *ibuf_open(size_t);
|
||||
struct ibuf *ibuf_dynamic(size_t, size_t);
|
||||
int ibuf_add(struct ibuf *, const void *, size_t);
|
||||
void *ibuf_reserve(struct ibuf *, size_t);
|
||||
void *ibuf_seek(struct ibuf *, size_t, size_t);
|
||||
size_t ibuf_size(struct ibuf *);
|
||||
size_t ibuf_left(struct ibuf *);
|
||||
void ibuf_close(struct msgbuf *, struct ibuf *);
|
||||
int ibuf_write(struct msgbuf *);
|
||||
void ibuf_free(struct ibuf *);
|
||||
void msgbuf_init(struct msgbuf *);
|
||||
void msgbuf_clear(struct msgbuf *);
|
||||
int msgbuf_write(struct msgbuf *);
|
||||
@@ -101,10 +101,10 @@ int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
||||
int, void *, u_int16_t);
|
||||
int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
||||
int, const struct iovec *, int);
|
||||
struct buf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
||||
struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
||||
u_int16_t);
|
||||
int imsg_add(struct buf *, void *, u_int16_t);
|
||||
void imsg_close(struct imsgbuf *, struct buf *);
|
||||
int imsg_add(struct ibuf *, void *, u_int16_t);
|
||||
void imsg_close(struct imsgbuf *, struct ibuf *);
|
||||
void imsg_free(struct imsg *);
|
||||
int imsg_flush(struct imsgbuf *);
|
||||
void imsg_clear(struct imsgbuf *);
|
||||
|
||||
49
compat/setenv.c
Normal file
49
compat/setenv.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/* $Id: setenv.c,v 1.2 2010-06-05 18:20:48 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Dagobert Michelsen
|
||||
* Copyright (c) 2010 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
int
|
||||
setenv(const char *name, const char *value, unused int overwrite)
|
||||
{
|
||||
char *newval;
|
||||
|
||||
xasprintf(&newval, "%s=%s", name, value);
|
||||
return (putenv(newval));
|
||||
}
|
||||
|
||||
int
|
||||
unsetenv(const char *name)
|
||||
{
|
||||
char **envptr;
|
||||
int namelen;
|
||||
|
||||
namelen = strlen(name);
|
||||
for (envptr = environ; *envptr != NULL; envptr++) {
|
||||
if (strncmp(name, *envptr, namelen) == 0 &&
|
||||
((*envptr)[namelen] == '=' || (*envptr)[namelen] == '\0'))
|
||||
break;
|
||||
}
|
||||
for (; *envptr != NULL; envptr++)
|
||||
*envptr = *(envptr + 1);
|
||||
return (0);
|
||||
}
|
||||
35
configure
vendored
35
configure
vendored
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# $Id: configure,v 1.47 2009-12-11 20:08:18 nicm Exp $
|
||||
# $Id: configure,v 1.53 2010-06-06 13:00:47 tcunha Exp $
|
||||
#
|
||||
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
#
|
||||
@@ -67,9 +67,11 @@ case $TMUX_PLATFORM in
|
||||
#define HAVE_FGETLN
|
||||
#define HAVE_FORKPTY
|
||||
#define HAVE_GETOPT
|
||||
#define HAVE_IMSG
|
||||
#define HAVE_PATHS_H
|
||||
#define HAVE_PROGNAME
|
||||
#define HAVE_QUEUE_H
|
||||
#define HAVE_SETENV
|
||||
#define HAVE_SETPROCTITLE
|
||||
#define HAVE_STRCASESTR
|
||||
#define HAVE_STRLCAT
|
||||
@@ -83,9 +85,7 @@ case $TMUX_PLATFORM in
|
||||
EOF
|
||||
cat <<EOF >>$CONFIG_MK
|
||||
LIBS+= -lcurses -lutil -levent
|
||||
SRCS+= osdep-openbsd.c \
|
||||
compat/imsg-buffer.c \
|
||||
compat/imsg.c
|
||||
SRCS+= osdep-openbsd.c
|
||||
EOF
|
||||
;;
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -98,13 +98,14 @@ EOF
|
||||
#define HAVE_PATHS_H
|
||||
#define HAVE_PROGNAME
|
||||
#define HAVE_PTY_H
|
||||
#define HAVE_SETENV
|
||||
#define HAVE_STRCASESTR
|
||||
#define HAVE_STRSEP
|
||||
#define HAVE_U_INT
|
||||
EOF
|
||||
cat <<EOF >>$CONFIG_MK
|
||||
CFLAGS+= -std=c99 -D_GNU_SOURCE -D_POSIX_SOURCE
|
||||
LIBS+= -lncurses -lcrypt -lutil -levent
|
||||
LIBS+= -lncurses -lcrypt -lutil -levent -lrt
|
||||
SRCS+= osdep-linux.c \
|
||||
compat/fgetln.c \
|
||||
compat/strlcat.c \
|
||||
@@ -122,6 +123,7 @@ EOF
|
||||
cat <<EOF >>$CONFIG_H
|
||||
#define HAVE_BZERO
|
||||
#define HAVE_DAEMON
|
||||
#define HAVE_SETENV
|
||||
EOF
|
||||
cat <<EOF >>$CONFIG_MK
|
||||
LIBS+= -lcurses -levent
|
||||
@@ -158,6 +160,7 @@ SRCS+= osdep-sunos.c \
|
||||
compat/fgetln.c \
|
||||
compat/forkpty-sunos.c \
|
||||
compat/getopt.c \
|
||||
compat/setenv.c \
|
||||
compat/strcasestr.c \
|
||||
compat/strsep.c \
|
||||
compat/strtonum.c \
|
||||
@@ -181,6 +184,7 @@ EOF
|
||||
#define HAVE_GETOPT
|
||||
#define HAVE_PATHS_H
|
||||
#define HAVE_PROGNAME
|
||||
#define HAVE_SETENV
|
||||
#define HAVE_STRCASESTR
|
||||
#define HAVE_STRLCAT
|
||||
#define HAVE_STRLCPY
|
||||
@@ -204,6 +208,7 @@ EOF
|
||||
FreeBSD|DragonFly)
|
||||
cat <<EOF >>$CONFIG_H
|
||||
#define HAVE_ASPRINTF
|
||||
#define HAVE_BROKEN_KQUEUE
|
||||
#define HAVE_BZERO
|
||||
#define HAVE_DAEMON
|
||||
#define HAVE_FGETLN
|
||||
@@ -212,6 +217,7 @@ EOF
|
||||
#define HAVE_LIBUTIL_H
|
||||
#define HAVE_PATHS_H
|
||||
#define HAVE_PROGNAME
|
||||
#define HAVE_SETENV
|
||||
#define HAVE_SETPROCTITLE
|
||||
#define HAVE_STRCASESTR
|
||||
#define HAVE_STRLCAT
|
||||
@@ -233,7 +239,6 @@ EOF
|
||||
NetBSD)
|
||||
cat <<EOF >>$CONFIG_H
|
||||
#define HAVE_ASPRINTF
|
||||
#define HAVE_BROKEN_CURSES_H
|
||||
#define HAVE_BZERO
|
||||
#define HAVE_DAEMON
|
||||
#define HAVE_FGETLN
|
||||
@@ -242,6 +247,7 @@ EOF
|
||||
#define HAVE_PATHS_H
|
||||
#define HAVE_PROGNAME
|
||||
#define HAVE_SETPROCTITLE
|
||||
#define HAVE_SETENV
|
||||
#define HAVE_STRCASESTR
|
||||
#define HAVE_STRLCAT
|
||||
#define HAVE_STRLCPY
|
||||
@@ -249,10 +255,23 @@ EOF
|
||||
#define HAVE_UTIL_H
|
||||
#define HAVE_U_INT
|
||||
EOF
|
||||
cat <<EOF >>$CONFIG_MK
|
||||
# NetBSD-6 has its own terminfo implementation
|
||||
if test -f /lib/libterminfo.so; then
|
||||
cat <<EOF >>$CONFIG_MK
|
||||
LIBS+= -lterminfo
|
||||
EOF
|
||||
else
|
||||
cat <<EOF >>$CONFIG_MK
|
||||
CPPFLAGS+= -I/usr/pkg/include
|
||||
LDFLAGS+= -L/usr/pkg/lib
|
||||
LIBS+= -lncurses -lcrypt -lutil -levent
|
||||
LIBS+= -lncurses
|
||||
EOF
|
||||
cat <<EOF >>$CONFIG_H
|
||||
#define HAVE_BROKEN_CURSES_H
|
||||
EOF
|
||||
fi
|
||||
cat <<EOF >>$CONFIG_MK
|
||||
LIBS+= -lcrypt -lutil -levent
|
||||
SRCS+= osdep-netbsd.c \
|
||||
compat/strtonum.c \
|
||||
compat/vis.c \
|
||||
|
||||
40
environ.c
40
environ.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: environ.c,v 1.3 2009-08-09 17:57:39 tcunha Exp $ */
|
||||
/* $Id: environ.c,v 1.4 2010-04-06 21:59:19 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -35,12 +35,14 @@ environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
|
||||
return (strcmp(envent1->name, envent2->name));
|
||||
}
|
||||
|
||||
/* Initialise the environment. */
|
||||
void
|
||||
environ_init(struct environ *env)
|
||||
{
|
||||
RB_INIT(env);
|
||||
}
|
||||
|
||||
/* Free an environment. */
|
||||
void
|
||||
environ_free(struct environ *env)
|
||||
{
|
||||
@@ -56,6 +58,7 @@ environ_free(struct environ *env)
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy one environment into another. */
|
||||
void
|
||||
environ_copy(struct environ *srcenv, struct environ *dstenv)
|
||||
{
|
||||
@@ -65,6 +68,7 @@ environ_copy(struct environ *srcenv, struct environ *dstenv)
|
||||
environ_set(dstenv, envent->name, envent->value);
|
||||
}
|
||||
|
||||
/* Find an environment variable. */
|
||||
struct environ_entry *
|
||||
environ_find(struct environ *env, const char *name)
|
||||
{
|
||||
@@ -74,6 +78,7 @@ environ_find(struct environ *env, const char *name)
|
||||
return (RB_FIND(environ, env, &envent));
|
||||
}
|
||||
|
||||
/* Set an environment variable. */
|
||||
void
|
||||
environ_set(struct environ *env, const char *name, const char *value)
|
||||
{
|
||||
@@ -97,10 +102,11 @@ environ_set(struct environ *env, const char *name, const char *value)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set an environment variable from a NAME=VALUE string. */
|
||||
void
|
||||
environ_put(struct environ *env, const char *var)
|
||||
{
|
||||
char *name, *value;
|
||||
char *name, *value;
|
||||
|
||||
value = strchr(var, '=');
|
||||
if (value == NULL)
|
||||
@@ -114,6 +120,7 @@ environ_put(struct environ *env, const char *var)
|
||||
xfree(name);
|
||||
}
|
||||
|
||||
/* Unset an environment variable. */
|
||||
void
|
||||
environ_unset(struct environ *env, const char *name)
|
||||
{
|
||||
@@ -128,6 +135,10 @@ environ_unset(struct environ *env, const char *name)
|
||||
xfree(envent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a space-separated list of variables from a destination into a source
|
||||
* environment.
|
||||
*/
|
||||
void
|
||||
environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
|
||||
{
|
||||
@@ -143,3 +154,28 @@ environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
|
||||
}
|
||||
xfree(copyvars);
|
||||
}
|
||||
|
||||
/* Push environment into the real environment - use after fork(). */
|
||||
void
|
||||
environ_push(struct environ *env)
|
||||
{
|
||||
ARRAY_DECL(, char *) varlist;
|
||||
struct environ_entry *envent;
|
||||
char **varp, *var;
|
||||
u_int i;
|
||||
|
||||
ARRAY_INIT(&varlist);
|
||||
for (varp = environ; *varp != NULL; varp++) {
|
||||
var = xstrdup(*varp);
|
||||
var[strcspn(var, "=")] = '\0';
|
||||
ARRAY_ADD(&varlist, var);
|
||||
}
|
||||
for (i = 0; i < ARRAY_LENGTH(&varlist); i++)
|
||||
unsetenv(ARRAY_ITEM(&varlist, i));
|
||||
ARRAY_FREE(&varlist);
|
||||
|
||||
RB_FOREACH(envent, environ, env) {
|
||||
if (envent->value != NULL)
|
||||
setenv(envent->name, envent->value, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
" Vim syntax file
|
||||
" Language: tmux(1) configuration file
|
||||
" Maintainer: Tiago Cunha <me@tiagocunha.org>
|
||||
" Last Change: $Date: 2010-02-26 13:33:22 $
|
||||
" Last Change: $Date: 2010-07-02 02:46:39 $
|
||||
" License: This file is placed in the public domain.
|
||||
|
||||
if version < 600
|
||||
@@ -29,7 +29,7 @@ syn keyword tmuxCmds new[-session] start[-server] kill-server setw
|
||||
syn keyword tmuxCmds set-window-option show[-options] showw show-window-options
|
||||
syn keyword tmuxCmds command-prompt setb set-buffer showb show-buffer lsb
|
||||
syn keyword tmuxCmds list-buffers deleteb delete-buffer lscm list-commands
|
||||
syn keyword tmuxCmds movew move-window select-prompt respawnw respawn-window
|
||||
syn keyword tmuxCmds movew move-window respawnw respawn-window
|
||||
syn keyword tmuxCmds source[-file] info server-info clock-mode lock[-server]
|
||||
syn keyword tmuxCmds saveb save-buffer downp down-pane killp
|
||||
syn keyword tmuxCmds kill-pane resizep resize-pane selectp select-pane swapp
|
||||
@@ -42,7 +42,7 @@ syn keyword tmuxCmds display[-message] setenv set-environment showenv
|
||||
syn keyword tmuxCmds show-environment choose-client displayp display-panes
|
||||
syn keyword tmuxCmds run[-shell] lockc lock-client locks lock-session lsp
|
||||
syn keyword tmuxCmds list-panes pipep pipe-pane showmsgs show-messages capturep
|
||||
syn keyword tmuxCmds capture-pane joinp join-pane
|
||||
syn keyword tmuxCmds capture-pane joinp join-pane choose-buffer
|
||||
|
||||
syn keyword tmuxOptsSet prefix status status-fg status-bg bell-action
|
||||
syn keyword tmuxOptsSet default-command history-limit status-left status-right
|
||||
@@ -61,6 +61,7 @@ syn keyword tmuxOptsSet mouse-select-pane message-limit quiet escape-time
|
||||
syn keyword tmuxOptsSet pane-active-border-bg pane-active-border-fg
|
||||
syn keyword tmuxOptsSet pane-border-bg pane-border-fg
|
||||
syn keyword tmuxOptsSet display-panes-active-colour alternate-screen
|
||||
syn keyword tmuxOptsSet detach-on-destroy
|
||||
|
||||
syn keyword tmuxOptsSetw monitor-activity aggressive-resize force-width
|
||||
syn keyword tmuxOptsSetw force-height remain-on-exit uft8 mode-fg mode-bg
|
||||
|
||||
43
grid.c
43
grid.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: grid.c,v 1.36 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: grid.c,v 1.37 2010-04-05 05:11:43 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -46,18 +46,9 @@ const struct grid_cell grid_default_cell = { 0, 0, 8, 8, ' ' };
|
||||
gc, sizeof gd->linedata[py].utf8data[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)
|
||||
{
|
||||
@@ -66,16 +57,6 @@ grid_check_y(struct grid *gd, u_int 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)
|
||||
{
|
||||
@@ -270,8 +251,6 @@ grid_expand_line_utf8(struct grid *gd, u_int py, u_int sx)
|
||||
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);
|
||||
|
||||
@@ -284,8 +263,6 @@ grid_peek_cell(struct grid *gd, u_int px, u_int py)
|
||||
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);
|
||||
|
||||
@@ -298,8 +275,6 @@ 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;
|
||||
|
||||
@@ -311,8 +286,6 @@ grid_set_cell(
|
||||
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);
|
||||
|
||||
@@ -325,8 +298,6 @@ grid_peek_utf8(struct grid *gd, u_int px, u_int py)
|
||||
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);
|
||||
|
||||
@@ -339,8 +310,6 @@ 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;
|
||||
|
||||
@@ -364,10 +333,6 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int 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)
|
||||
@@ -465,12 +430,6 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int 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;
|
||||
gl = &gd->linedata[py];
|
||||
|
||||
7
job.c
7
job.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: job.c,v 1.15 2010-02-26 13:35:04 tcunha Exp $ */
|
||||
/* $Id: job.c,v 1.17 2010-05-14 14:30:01 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -148,8 +148,9 @@ job_run(struct job *job)
|
||||
case -1:
|
||||
return (-1);
|
||||
case 0: /* child */
|
||||
server_signal_clear();
|
||||
/* XXX environ? */
|
||||
clear_signals();
|
||||
|
||||
environ_push(&global_environ);
|
||||
|
||||
if (dup2(out[1], STDOUT_FILENO) == -1)
|
||||
fatal("dup2 failed");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: key-bindings.c,v 1.88 2010-02-08 18:27:34 tcunha Exp $ */
|
||||
/* $Id: key-bindings.c,v 1.94 2010-07-02 02:43:01 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -122,10 +122,11 @@ key_bindings_init(void)
|
||||
{ '8', 0, &cmd_select_window_entry },
|
||||
{ '9', 0, &cmd_select_window_entry },
|
||||
{ ':', 0, &cmd_command_prompt_entry },
|
||||
{ '=', 0, &cmd_choose_buffer_entry },
|
||||
{ '?', 0, &cmd_list_keys_entry },
|
||||
{ 'D', 0, &cmd_choose_client_entry },
|
||||
{ '[', 0, &cmd_copy_mode_entry },
|
||||
{ '\'', 0, &cmd_select_prompt_entry },
|
||||
{ '\'', 0, &cmd_command_prompt_entry },
|
||||
{ '\002', /* C-b */ 0, &cmd_send_prefix_entry },
|
||||
{ '\017', /* C-o */ 0, &cmd_rotate_window_entry },
|
||||
{ '\032', /* C-z */ 0, &cmd_suspend_client_entry },
|
||||
@@ -136,7 +137,7 @@ key_bindings_init(void)
|
||||
{ 'i', 0, &cmd_display_message_entry },
|
||||
{ 'l', 0, &cmd_last_window_entry },
|
||||
{ 'n', 0, &cmd_next_window_entry },
|
||||
{ 'o', 0, &cmd_down_pane_entry },
|
||||
{ 'o', 0, &cmd_select_pane_entry },
|
||||
{ 'p', 0, &cmd_previous_window_entry },
|
||||
{ 'q', 0, &cmd_display_panes_entry },
|
||||
{ 'r', 0, &cmd_refresh_client_entry },
|
||||
@@ -151,12 +152,15 @@ key_bindings_init(void)
|
||||
{ '2' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
||||
{ '3' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
||||
{ '4' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
||||
{ '5' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
||||
{ KEYC_PPAGE, 0, &cmd_copy_mode_entry },
|
||||
{ 'n' | KEYC_ESCAPE, 0, &cmd_next_window_entry },
|
||||
{ 'o' | KEYC_ESCAPE, 0, &cmd_rotate_window_entry },
|
||||
{ 'p' | KEYC_ESCAPE, 0, &cmd_previous_window_entry },
|
||||
{ KEYC_UP, 0, &cmd_up_pane_entry },
|
||||
{ KEYC_DOWN, 0, &cmd_down_pane_entry },
|
||||
{ KEYC_UP, 1, &cmd_select_pane_entry },
|
||||
{ KEYC_DOWN, 1, &cmd_select_pane_entry },
|
||||
{ KEYC_LEFT, 1, &cmd_select_pane_entry },
|
||||
{ KEYC_RIGHT, 1, &cmd_select_pane_entry },
|
||||
{ KEYC_UP | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
|
||||
{ KEYC_DOWN | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
|
||||
{ KEYC_LEFT | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
|
||||
@@ -174,14 +178,15 @@ key_bindings_init(void)
|
||||
|
||||
for (i = 0; i < nitems(table); i++) {
|
||||
cmdlist = xmalloc(sizeof *cmdlist);
|
||||
TAILQ_INIT(cmdlist);
|
||||
TAILQ_INIT(&cmdlist->list);
|
||||
cmdlist->references = 1;
|
||||
|
||||
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);
|
||||
TAILQ_INSERT_HEAD(&cmdlist->list, cmd, qentry);
|
||||
|
||||
key_bindings_add(
|
||||
table[i].key | KEYC_PREFIX, table[i].can_repeat, cmdlist);
|
||||
@@ -209,12 +214,14 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||
struct winlink *wl = ctx->curclient->session->curw;
|
||||
va_list ap;
|
||||
|
||||
if (wl->window->active->mode != &window_more_mode)
|
||||
if (wl->window->active->mode != &window_copy_mode) {
|
||||
window_pane_reset_mode(wl->window->active);
|
||||
window_pane_set_mode(wl->window->active, &window_more_mode);
|
||||
window_pane_set_mode(wl->window->active, &window_copy_mode);
|
||||
window_copy_init_for_output(wl->window->active);
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
window_more_vadd(wl->window->active, fmt, ap);
|
||||
window_copy_vadd(wl->window->active, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
@@ -253,7 +260,7 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c)
|
||||
ctx.cmdclient = NULL;
|
||||
|
||||
readonly = 1;
|
||||
TAILQ_FOREACH(cmd, bd->cmdlist, qentry) {
|
||||
TAILQ_FOREACH(cmd, &bd->cmdlist->list, qentry) {
|
||||
if (!(cmd->entry->flags & CMD_READONLY))
|
||||
readonly = 0;
|
||||
}
|
||||
|
||||
210
key-string.c
210
key-string.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: key-string.c,v 1.29 2010-01-17 19:01:27 tcunha Exp $ */
|
||||
/* $Id: key-string.c,v 1.34 2010-06-05 20:29:11 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -23,10 +23,11 @@
|
||||
#include "tmux.h"
|
||||
|
||||
int key_string_search_table(const char *);
|
||||
int key_string_get_modifiers(const char **);
|
||||
|
||||
struct {
|
||||
const char *string;
|
||||
int key;
|
||||
const char *string;
|
||||
int key;
|
||||
} key_string_table[] = {
|
||||
/* Function keys. */
|
||||
{ "F1", KEYC_F1 },
|
||||
@@ -100,146 +101,131 @@ key_string_search_table(const char *string)
|
||||
return (KEYC_NONE);
|
||||
}
|
||||
|
||||
/* Lookup a string and convert to a key value, handling C-/M-/S- prefix. */
|
||||
/* Find modifiers. */
|
||||
int
|
||||
key_string_get_modifiers(const char **string)
|
||||
{
|
||||
int modifiers;
|
||||
|
||||
modifiers = 0;
|
||||
while (((*string)[0] != '\0') && (*string)[1] == '-') {
|
||||
switch ((*string)[0]) {
|
||||
case 'C':
|
||||
case 'c':
|
||||
modifiers |= KEYC_CTRL;
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
modifiers |= KEYC_ESCAPE;
|
||||
break;
|
||||
case 'S':
|
||||
case 's':
|
||||
modifiers |= KEYC_SHIFT;
|
||||
break;
|
||||
}
|
||||
*string += 2;
|
||||
}
|
||||
return (modifiers);
|
||||
}
|
||||
|
||||
/* Lookup a string and convert to a key value. */
|
||||
int
|
||||
key_string_lookup_string(const char *string)
|
||||
{
|
||||
int key;
|
||||
const char *ptr;
|
||||
int key, modifiers;
|
||||
|
||||
/* Check for modifiers. */
|
||||
modifiers = 0;
|
||||
if (string[0] == '^' && string[1] != '\0') {
|
||||
modifiers |= KEYC_CTRL;
|
||||
string++;
|
||||
}
|
||||
modifiers |= key_string_get_modifiers(&string);
|
||||
if (string[0] == '\0')
|
||||
return (KEYC_NONE);
|
||||
if (string[1] == '\0')
|
||||
return ((u_char) string[0]);
|
||||
|
||||
ptr = NULL;
|
||||
if ((string[0] == 'C' || string[0] == 'c') && string[1] == '-')
|
||||
ptr = string + 2;
|
||||
else if (string[0] == '^')
|
||||
ptr = string + 1;
|
||||
if (ptr != NULL) {
|
||||
if (ptr[0] == '\0')
|
||||
/* Is this a standard ASCII key? */
|
||||
if (string[1] == '\0') {
|
||||
key = (u_char) string[0];
|
||||
if (key < 32 || key > 126)
|
||||
return (KEYC_NONE);
|
||||
/*
|
||||
* Lookup as a named key. If a function key (>= KEYC_BASE),
|
||||
* return it with the ctrl modifier, otherwise fallthrough with
|
||||
* the key value from the table (eg for C-Space). If not a
|
||||
* named key, check for single character keys and try that.
|
||||
*/
|
||||
key = key_string_search_table(ptr);
|
||||
if (key != KEYC_NONE) {
|
||||
if (key >= KEYC_BASE)
|
||||
return (key | KEYC_CTRL);
|
||||
} else {
|
||||
if (ptr[1] != '\0')
|
||||
return (KEYC_NONE);
|
||||
key = (u_char) ptr[0];
|
||||
}
|
||||
} else {
|
||||
/* Otherwise look the key up in the table. */
|
||||
key = key_string_search_table(string);
|
||||
if (key == KEYC_NONE)
|
||||
return (KEYC_NONE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out if the single character in key is a valid ctrl
|
||||
* key.
|
||||
*/
|
||||
if (key == 32)
|
||||
return (0);
|
||||
if (key == 63)
|
||||
return (KEYC_BSPACE);
|
||||
if (key >= 64 && key <= 95)
|
||||
return (key - 64);
|
||||
/* Convert the standard control keys. */
|
||||
if (key < KEYC_BASE && (modifiers & KEYC_CTRL)) {
|
||||
if (key >= 97 && key <= 122)
|
||||
return (key - 96);
|
||||
return (KEYC_NONE);
|
||||
}
|
||||
|
||||
if ((string[0] == 'M' || string[0] == 'm') && string[1] == '-') {
|
||||
ptr = string + 2;
|
||||
if (ptr[0] == '\0')
|
||||
key -= 96;
|
||||
else if (key >= 64 && key <= 95)
|
||||
key -= 64;
|
||||
else if (key == 32)
|
||||
key = 0;
|
||||
else if (key == 63)
|
||||
key = KEYC_BSPACE;
|
||||
else
|
||||
return (KEYC_NONE);
|
||||
key = key_string_lookup_string(ptr);
|
||||
if (key != KEYC_NONE) {
|
||||
if (key >= KEYC_BASE)
|
||||
return (key | KEYC_ESCAPE);
|
||||
} else {
|
||||
if (ptr[1] == '\0')
|
||||
return (KEYC_NONE);
|
||||
key = (u_char) ptr[0];
|
||||
}
|
||||
|
||||
if (key >= 32 && key <= 127)
|
||||
return (key | KEYC_ESCAPE);
|
||||
return (KEYC_NONE);
|
||||
modifiers &= ~KEYC_CTRL;
|
||||
}
|
||||
|
||||
if ((string[0] == 'S' || string[0] == 's') && string[1] == '-') {
|
||||
ptr = string + 2;
|
||||
if (ptr[0] == '\0')
|
||||
return (KEYC_NONE);
|
||||
key = key_string_lookup_string(ptr);
|
||||
if (key != KEYC_NONE) {
|
||||
if (key >= KEYC_BASE)
|
||||
return (key | KEYC_SHIFT);
|
||||
} else {
|
||||
if (ptr[1] == '\0')
|
||||
return (KEYC_NONE);
|
||||
key = (u_char) ptr[0];
|
||||
}
|
||||
|
||||
if (key >= 32 && key <= 127)
|
||||
return (key | KEYC_SHIFT);
|
||||
return (KEYC_NONE);
|
||||
}
|
||||
|
||||
return (key_string_search_table(string));
|
||||
return (key | modifiers);
|
||||
}
|
||||
|
||||
/* Convert a key code into string format, with prefix if necessary. */
|
||||
const char *
|
||||
key_string_lookup_key(int key)
|
||||
{
|
||||
static char tmp[24], tmp2[24];
|
||||
const char *s;
|
||||
u_int i;
|
||||
static char out[24];
|
||||
char tmp[8];
|
||||
u_int i;
|
||||
|
||||
if (key == 127)
|
||||
return (NULL);
|
||||
*out = '\0';
|
||||
|
||||
if (key & KEYC_ESCAPE) {
|
||||
if ((s = key_string_lookup_key(key & ~KEYC_ESCAPE)) == NULL)
|
||||
return (NULL);
|
||||
xsnprintf(tmp2, sizeof tmp2, "M-%s", s);
|
||||
return (tmp2);
|
||||
}
|
||||
if (key & KEYC_CTRL) {
|
||||
if ((s = key_string_lookup_key(key & ~KEYC_CTRL)) == NULL)
|
||||
return (NULL);
|
||||
xsnprintf(tmp2, sizeof tmp2, "C-%s", s);
|
||||
return (tmp2);
|
||||
}
|
||||
if (key & KEYC_SHIFT) {
|
||||
if ((s = key_string_lookup_key(key & ~KEYC_SHIFT)) == NULL)
|
||||
return (NULL);
|
||||
xsnprintf(tmp2, sizeof tmp2, "S-%s", s);
|
||||
return (tmp2);
|
||||
}
|
||||
/*
|
||||
* Special case: display C-@ as C-Space. Could do this below in
|
||||
* the (key >= 0 && key <= 32), but this way we let it be found
|
||||
* in key_string_table, for the unlikely chance that we might
|
||||
* change its name.
|
||||
*/
|
||||
if ((key & KEYC_MASK_KEY) == 0)
|
||||
key = ' ' | KEYC_CTRL | (key & KEYC_MASK_MOD);
|
||||
|
||||
/* Fill in the modifiers. */
|
||||
if (key & KEYC_CTRL)
|
||||
strlcat(out, "C-", sizeof out);
|
||||
if (key & KEYC_ESCAPE)
|
||||
strlcat(out, "M-", sizeof out);
|
||||
if (key & KEYC_SHIFT)
|
||||
strlcat(out, "S-", sizeof out);
|
||||
key &= KEYC_MASK_KEY;
|
||||
|
||||
/* Try the key against the string table. */
|
||||
for (i = 0; i < nitems(key_string_table); i++) {
|
||||
if (key == key_string_table[i].key)
|
||||
return (key_string_table[i].string);
|
||||
break;
|
||||
}
|
||||
if (i != nitems(key_string_table)) {
|
||||
strlcat(out, key_string_table[i].string, sizeof out);
|
||||
return (out);
|
||||
}
|
||||
|
||||
if (key >= 32 && key <= 255) {
|
||||
tmp[0] = (char) key;
|
||||
tmp[1] = '\0';
|
||||
return (tmp);
|
||||
}
|
||||
/* Invalid keys are errors. */
|
||||
if (key >= 127)
|
||||
return (NULL);
|
||||
|
||||
/* Check for standard or control key. */
|
||||
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);
|
||||
} else if (key >= 32 && key <= 126) {
|
||||
tmp[0] = key;
|
||||
tmp[1] = '\0';
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
strlcat(out, tmp, sizeof out);
|
||||
return (out);
|
||||
}
|
||||
|
||||
264
layout-custom.c
Normal file
264
layout-custom.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/* $Id: layout-custom.c,v 1.1 2010-07-02 02:54:52 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 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"
|
||||
|
||||
u_short layout_checksum(const char *);
|
||||
int layout_append(struct layout_cell *, char *, size_t);
|
||||
struct layout_cell *layout_construct(struct layout_cell *, const char **);
|
||||
void layout_assign(struct window_pane **, struct layout_cell *);
|
||||
|
||||
/* Calculate layout checksum. */
|
||||
u_short
|
||||
layout_checksum(const char *layout)
|
||||
{
|
||||
u_short csum;
|
||||
|
||||
csum = 0;
|
||||
for (; *layout != '\0'; layout++) {
|
||||
csum = (csum >> 1) + ((csum & 1) << 15);
|
||||
csum += *layout;
|
||||
}
|
||||
return (csum);
|
||||
}
|
||||
|
||||
/* Dump layout as a string. */
|
||||
char *
|
||||
layout_dump(struct window *w)
|
||||
{
|
||||
char layout[BUFSIZ], *out;
|
||||
|
||||
*layout = '\0';
|
||||
if (layout_append(w->layout_root, layout, sizeof layout) != 0)
|
||||
return (NULL);
|
||||
|
||||
xasprintf(&out, "%4x,%s", layout_checksum(layout), layout);
|
||||
return (out);
|
||||
}
|
||||
|
||||
/* Append information for a single cell. */
|
||||
int
|
||||
layout_append(struct layout_cell *lc, char *buf, size_t len)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
char tmp[64];
|
||||
size_t tmplen;
|
||||
const char *brackets = "][";
|
||||
|
||||
if (len == 0)
|
||||
return (-1);
|
||||
|
||||
tmplen = xsnprintf(tmp, sizeof tmp,
|
||||
"%ux%u,%u,%u", lc->sx, lc->sy, lc->xoff, lc->yoff);
|
||||
if (tmplen > (sizeof tmp) - 1)
|
||||
return (-1);
|
||||
if (strlcat(buf, tmp, len) >= len)
|
||||
return (-1);
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
brackets = "}{";
|
||||
/* FALLTHROUGH */
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
if (strlcat(buf, &brackets[1], len) >= len)
|
||||
return (-1);
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (layout_append(lcchild, buf, len) != 0)
|
||||
return (-1);
|
||||
if (strlcat(buf, ",", len) >= len)
|
||||
return (-1);
|
||||
}
|
||||
buf[strlen(buf) - 1] = brackets[0];
|
||||
break;
|
||||
case LAYOUT_WINDOWPANE:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Parse a layout string and arrange window as layout. */
|
||||
int
|
||||
layout_parse(struct window *w, const char *layout)
|
||||
{
|
||||
struct layout_cell *lc, *lcchild;
|
||||
struct window_pane *wp;
|
||||
u_int npanes, ncells, sx, sy;
|
||||
u_short csum;
|
||||
|
||||
/* Check validity. */
|
||||
if (sscanf(layout, "%hx,", &csum) != 1)
|
||||
return (-1);
|
||||
layout += 5;
|
||||
if (csum != layout_checksum(layout))
|
||||
return (-1);
|
||||
|
||||
/* Build the layout. */
|
||||
lc = layout_construct(NULL, &layout);
|
||||
if (lc == NULL)
|
||||
return (-1);
|
||||
if (*layout != '\0')
|
||||
goto fail;
|
||||
|
||||
/* Check this window will fit into the layout. */
|
||||
for (;;) {
|
||||
npanes = window_count_panes(w);
|
||||
ncells = layout_count_cells(lc);
|
||||
if (npanes > ncells)
|
||||
goto fail;
|
||||
if (npanes == ncells)
|
||||
break;
|
||||
|
||||
/* Fewer panes than cells - close the bottom right. */
|
||||
lcchild = layout_find_bottomright(lc);
|
||||
layout_destroy_cell(lcchild, &lc);
|
||||
}
|
||||
|
||||
/* Save the old window size and resize to the layout size. */
|
||||
sx = w->sx; sy = w->sy;
|
||||
window_resize(w, lc->sx, lc->sy);
|
||||
|
||||
/* Destroy the old layout and swap to the new. */
|
||||
layout_free_cell(w->layout_root);
|
||||
w->layout_root = lc;
|
||||
|
||||
/* Assign the panes into the cells. */
|
||||
wp = TAILQ_FIRST(&w->panes);
|
||||
layout_assign(&wp, lc);
|
||||
|
||||
/* Update pane offsets and sizes. */
|
||||
layout_fix_offsets(lc);
|
||||
layout_fix_panes(w, lc->sx, lc->sy);
|
||||
|
||||
/* Then resize the layout back to the original window size. */
|
||||
layout_resize(w, sx, sy);
|
||||
window_resize(w, sx, sy);
|
||||
|
||||
layout_print_cell(lc, __func__, 0);
|
||||
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
layout_free_cell(lc);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Assign panes into cells. */
|
||||
void
|
||||
layout_assign(struct window_pane **wp, struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_WINDOWPANE:
|
||||
layout_make_leaf(lc, *wp);
|
||||
*wp = TAILQ_NEXT(*wp, entry);
|
||||
return;
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
layout_assign(wp, lcchild);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct a cell from all or part of a layout tree. */
|
||||
struct layout_cell *
|
||||
layout_construct(struct layout_cell *lcparent, const char **layout)
|
||||
{
|
||||
struct layout_cell *lc, *lcchild;
|
||||
u_int sx, sy, xoff, yoff;
|
||||
|
||||
if (!isdigit((u_char) **layout))
|
||||
return (NULL);
|
||||
if (sscanf(*layout, "%ux%u,%u,%u", &sx, &sy, &xoff, &yoff) != 4)
|
||||
return (NULL);
|
||||
|
||||
while (isdigit((u_char) **layout))
|
||||
(*layout)++;
|
||||
if (**layout != 'x')
|
||||
return (NULL);
|
||||
(*layout)++;
|
||||
while (isdigit((u_char) **layout))
|
||||
(*layout)++;
|
||||
if (**layout != ',')
|
||||
return (NULL);
|
||||
(*layout)++;
|
||||
while (isdigit((u_char) **layout))
|
||||
(*layout)++;
|
||||
if (**layout != ',')
|
||||
return (NULL);
|
||||
(*layout)++;
|
||||
while (isdigit((u_char) **layout))
|
||||
(*layout)++;
|
||||
|
||||
lc = layout_create_cell(lcparent);
|
||||
lc->sx = sx;
|
||||
lc->sy = sy;
|
||||
lc->xoff = xoff;
|
||||
lc->yoff = yoff;
|
||||
|
||||
switch (**layout) {
|
||||
case ',':
|
||||
case '}':
|
||||
case ']':
|
||||
case '\0':
|
||||
return (lc);
|
||||
case '{':
|
||||
lc->type = LAYOUT_LEFTRIGHT;
|
||||
break;
|
||||
case '[':
|
||||
lc->type = LAYOUT_TOPBOTTOM;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
do {
|
||||
(*layout)++;
|
||||
lcchild = layout_construct(lc, layout);
|
||||
if (lcchild == NULL)
|
||||
goto fail;
|
||||
TAILQ_INSERT_TAIL(&lc->cells, lcchild, entry);
|
||||
} while (**layout == ',');
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
if (**layout != '}')
|
||||
goto fail;
|
||||
break;
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
if (**layout != ']')
|
||||
goto fail;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
(*layout)++;
|
||||
|
||||
return (lc);
|
||||
|
||||
fail:
|
||||
layout_free_cell(lc);
|
||||
return (NULL);
|
||||
}
|
||||
103
layout-set.c
103
layout-set.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: layout-set.c,v 1.5 2010-02-05 01:29:04 tcunha Exp $ */
|
||||
/* $Id: layout-set.c,v 1.6 2010-05-14 14:16:37 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -31,6 +31,7 @@ void layout_set_even_h(struct window *);
|
||||
void layout_set_even_v(struct window *);
|
||||
void layout_set_main_h(struct window *);
|
||||
void layout_set_main_v(struct window *);
|
||||
void layout_set_tiled(struct window *);
|
||||
|
||||
const struct {
|
||||
const char *name;
|
||||
@@ -40,6 +41,7 @@ const struct {
|
||||
{ "even-vertical", layout_set_even_v },
|
||||
{ "main-horizontal", layout_set_main_h },
|
||||
{ "main-vertical", layout_set_main_v },
|
||||
{ "tiled", layout_set_tiled },
|
||||
};
|
||||
|
||||
const char *
|
||||
@@ -447,3 +449,102 @@ layout_set_main_v(struct window *w)
|
||||
|
||||
server_redraw_window(w);
|
||||
}
|
||||
|
||||
void
|
||||
layout_set_tiled(struct window *w)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
struct layout_cell *lc, *lcrow, *lcchild;
|
||||
u_int n, width, height, used;
|
||||
u_int i, j, columns, rows;
|
||||
|
||||
layout_print_cell(w->layout_root, __func__, 1);
|
||||
|
||||
/* Get number of panes. */
|
||||
n = window_count_panes(w);
|
||||
if (n <= 1)
|
||||
return;
|
||||
|
||||
/* How many rows and columns are wanted? */
|
||||
rows = columns = 1;
|
||||
while (rows * columns < n) {
|
||||
rows++;
|
||||
if (rows * columns < n)
|
||||
columns++;
|
||||
}
|
||||
|
||||
/* What width and height should they be? */
|
||||
width = w->sx / columns;
|
||||
if (width < PANE_MINIMUM + 1)
|
||||
width = PANE_MINIMUM + 1;
|
||||
height = w->sy / rows;
|
||||
if (width < PANE_MINIMUM + 1)
|
||||
width = PANE_MINIMUM + 1;
|
||||
|
||||
/* Free old tree and create a new root. */
|
||||
layout_free(w);
|
||||
lc = w->layout_root = layout_create_cell(NULL);
|
||||
layout_set_size(lc, width * columns, height * rows, 0, 0);
|
||||
layout_make_node(lc, LAYOUT_TOPBOTTOM);
|
||||
|
||||
/* Create a grid of the cells. */
|
||||
wp = TAILQ_FIRST(&w->panes);
|
||||
for (j = 0; j < rows; j++) {
|
||||
/* If this is the last cell, all done. */
|
||||
if (wp == NULL)
|
||||
break;
|
||||
|
||||
/* Create the new row. */
|
||||
lcrow = layout_create_cell(lc);
|
||||
layout_set_size(lcrow, w->sx, height - 1, 0, 0);
|
||||
TAILQ_INSERT_TAIL(&lc->cells, lcrow, entry);
|
||||
|
||||
/* If only one column, just use the row directly. */
|
||||
if (n - (j * columns) == 1) {
|
||||
layout_make_leaf(lcrow, wp);
|
||||
wp = TAILQ_NEXT(wp, entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add in the columns. */
|
||||
layout_make_node(lcrow, LAYOUT_LEFTRIGHT);
|
||||
for (i = 0; i < columns; i++) {
|
||||
/* Create and add a pane cell. */
|
||||
lcchild = layout_create_cell(lcrow);
|
||||
layout_set_size(lcchild, width - 1, height - 1, 0, 0);
|
||||
layout_make_leaf(lcchild, wp);
|
||||
TAILQ_INSERT_TAIL(&lcrow->cells, lcchild, entry);
|
||||
|
||||
/* Move to the next cell. */
|
||||
if ((wp = TAILQ_NEXT(wp, entry)) == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust the row and columns to fit the full width if
|
||||
* necessary.
|
||||
*/
|
||||
if (i == columns)
|
||||
i--;
|
||||
used = ((i + 1) * width) - 1;
|
||||
if (w->sx <= used)
|
||||
continue;
|
||||
lcchild = TAILQ_LAST(&lcrow->cells, layout_cells);
|
||||
layout_resize_adjust(lcchild, LAYOUT_LEFTRIGHT, w->sx - used);
|
||||
}
|
||||
|
||||
/* Adjust the last row height to fit if necessary. */
|
||||
used = (rows * height) - 1;
|
||||
if (w->sy > used) {
|
||||
lcrow = TAILQ_LAST(&lc->cells, layout_cells);
|
||||
layout_resize_adjust(lcrow, LAYOUT_TOPBOTTOM, w->sy - used);
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
layout_fix_offsets(lc);
|
||||
layout_fix_panes(w, w->sx, w->sy);
|
||||
|
||||
layout_print_cell(w->layout_root, __func__, 1);
|
||||
|
||||
server_redraw_window(w);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: layout-string.c,v 1.3 2010-01-08 16:28:04 tcunha Exp $ */
|
||||
/* $Id: layout-string.c,v 1.4 2010-07-02 02:54:52 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -36,7 +36,6 @@ struct layout_cell *layout_find_right(struct layout_cell *);
|
||||
struct layout_cell *layout_find_topleft(struct layout_cell *);
|
||||
struct layout_cell *layout_find_topright(struct layout_cell *);
|
||||
struct layout_cell *layout_find_bottomleft(struct layout_cell *);
|
||||
struct layout_cell *layout_find_bottomright(struct layout_cell *);
|
||||
|
||||
/* Find the cell; returns NULL if string not understood. */
|
||||
struct layout_cell *
|
||||
|
||||
130
layout.c
130
layout.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: layout.c,v 1.18 2010-01-08 16:31:35 tcunha Exp $ */
|
||||
/* $Id: layout.c,v 1.19 2010-07-02 02:54:52 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -218,6 +218,27 @@ layout_fix_panes(struct window *w, u_int wsx, u_int wsy)
|
||||
}
|
||||
}
|
||||
|
||||
/* Count the number of available cells in a layout. */
|
||||
u_int
|
||||
layout_count_cells(struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
u_int n;
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_WINDOWPANE:
|
||||
return (1);
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
n = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
n += layout_count_cells(lcchild);
|
||||
return (n);
|
||||
default:
|
||||
fatalx("bad layout type");
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate how much size is available to be removed from a cell. */
|
||||
u_int
|
||||
layout_resize_check(struct layout_cell *lc, enum layout_type type)
|
||||
@@ -302,6 +323,56 @@ layout_resize_adjust(struct layout_cell *lc, enum layout_type type, int change)
|
||||
}
|
||||
}
|
||||
|
||||
/* Destroy a cell and redistribute the space. */
|
||||
void
|
||||
layout_destroy_cell(struct layout_cell *lc, struct layout_cell **lcroot)
|
||||
{
|
||||
struct layout_cell *lcother, *lcparent;
|
||||
|
||||
/*
|
||||
* If no parent, this is the last pane so window close is imminent and
|
||||
* there is no need to resize anything.
|
||||
*/
|
||||
lcparent = lc->parent;
|
||||
if (lcparent == NULL) {
|
||||
layout_free_cell(lc);
|
||||
*lcroot = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Merge the space into the previous or next cell. */
|
||||
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||
lcother = TAILQ_NEXT(lc, entry);
|
||||
else
|
||||
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||
if (lcparent->type == LAYOUT_LEFTRIGHT)
|
||||
layout_resize_adjust(lcother, lcparent->type, lc->sx + 1);
|
||||
else
|
||||
layout_resize_adjust(lcother, lcparent->type, lc->sy + 1);
|
||||
|
||||
/* Remove this from the parent's list. */
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
layout_free_cell(lc);
|
||||
|
||||
/*
|
||||
* If the parent now has one cell, remove the parent from the tree and
|
||||
* replace it by that cell.
|
||||
*/
|
||||
lc = TAILQ_FIRST(&lcparent->cells);
|
||||
if (TAILQ_NEXT(lc, entry) == NULL) {
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
|
||||
lc->parent = lcparent->parent;
|
||||
if (lc->parent == NULL) {
|
||||
lc->xoff = 0; lc->yoff = 0;
|
||||
*lcroot = lc;
|
||||
} else
|
||||
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
|
||||
|
||||
layout_free_cell(lcparent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
layout_init(struct window *w)
|
||||
{
|
||||
@@ -597,59 +668,16 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size)
|
||||
return (lcnew);
|
||||
}
|
||||
|
||||
/* Destroy the layout associated with a pane and redistribute the space. */
|
||||
/* Destroy the cell associated with a pane. */
|
||||
void
|
||||
layout_close_pane(struct window_pane *wp)
|
||||
{
|
||||
struct layout_cell *lc, *lcother, *lcparent;
|
||||
|
||||
lc = wp->layout_cell;
|
||||
lcparent = lc->parent;
|
||||
|
||||
/*
|
||||
* If no parent, this is the last pane so window close is imminent and
|
||||
* there is no need to resize anything.
|
||||
*/
|
||||
if (lcparent == NULL) {
|
||||
layout_free_cell(lc);
|
||||
wp->window->layout_root = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Merge the space into the previous or next cell. */
|
||||
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||
lcother = TAILQ_NEXT(lc, entry);
|
||||
else
|
||||
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||
if (lcparent->type == LAYOUT_LEFTRIGHT)
|
||||
layout_resize_adjust(lcother, lcparent->type, lc->sx + 1);
|
||||
else
|
||||
layout_resize_adjust(lcother, lcparent->type, lc->sy + 1);
|
||||
|
||||
/* Remove this from the parent's list. */
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
layout_free_cell(lc);
|
||||
|
||||
/*
|
||||
* If the parent now has one cell, remove the parent from the tree and
|
||||
* replace it by that cell.
|
||||
*/
|
||||
lc = TAILQ_FIRST(&lcparent->cells);
|
||||
if (TAILQ_NEXT(lc, entry) == NULL) {
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
|
||||
lc->parent = lcparent->parent;
|
||||
if (lc->parent == NULL) {
|
||||
lc->xoff = 0; lc->yoff = 0;
|
||||
wp->window->layout_root = lc;
|
||||
} else
|
||||
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
|
||||
|
||||
layout_free_cell(lcparent);
|
||||
}
|
||||
/* Remove the cell. */
|
||||
layout_destroy_cell(wp->layout_cell, &wp->window->layout_root);
|
||||
|
||||
/* Fix pane offsets and sizes. */
|
||||
layout_fix_offsets(wp->window->layout_root);
|
||||
layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
|
||||
if (wp->window->layout_root != NULL) {
|
||||
layout_fix_offsets(wp->window->layout_root);
|
||||
layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
mode-key.c
15
mode-key.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: mode-key.c,v 1.45 2010-03-08 15:02:07 tcunha Exp $ */
|
||||
/* $Id: mode-key.c,v 1.46 2010-03-16 17:30:58 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -88,6 +88,10 @@ struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
|
||||
{ MODEKEYCOPY_GOTOLINE, "goto-line" },
|
||||
{ MODEKEYCOPY_HISTORYBOTTOM, "history-bottom" },
|
||||
{ MODEKEYCOPY_HISTORYTOP, "history-top" },
|
||||
{ MODEKEYCOPY_JUMP, "jump-forward" },
|
||||
{ MODEKEYCOPY_JUMPAGAIN, "jump-again" },
|
||||
{ MODEKEYCOPY_JUMPREVERSE, "jump-reverse" },
|
||||
{ MODEKEYCOPY_JUMPBACK, "jump-backward" },
|
||||
{ MODEKEYCOPY_LEFT, "cursor-left" },
|
||||
{ MODEKEYCOPY_RECTANGLETOGGLE, "rectangle-toggle" },
|
||||
{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
|
||||
@@ -177,6 +181,8 @@ struct mode_key_tree mode_key_tree_vi_choice;
|
||||
const struct mode_key_entry mode_key_vi_copy[] = {
|
||||
{ ' ', 0, MODEKEYCOPY_STARTSELECTION },
|
||||
{ '$', 0, MODEKEYCOPY_ENDOFLINE },
|
||||
{ ',', 0, MODEKEYCOPY_JUMPREVERSE },
|
||||
{ ';', 0, MODEKEYCOPY_JUMPAGAIN },
|
||||
{ '/', 0, MODEKEYCOPY_SEARCHDOWN },
|
||||
{ '0', 0, MODEKEYCOPY_STARTOFLINE },
|
||||
{ '1', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
@@ -192,6 +198,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
|
||||
{ '?', 0, MODEKEYCOPY_SEARCHUP },
|
||||
{ 'B', 0, MODEKEYCOPY_PREVIOUSSPACE },
|
||||
{ 'E', 0, MODEKEYCOPY_NEXTSPACEEND },
|
||||
{ 'F', 0, MODEKEYCOPY_JUMPBACK },
|
||||
{ 'G', 0, MODEKEYCOPY_HISTORYBOTTOM },
|
||||
{ 'H', 0, MODEKEYCOPY_TOPLINE },
|
||||
{ 'J', 0, MODEKEYCOPY_SCROLLDOWN },
|
||||
@@ -213,6 +220,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
|
||||
{ '^', 0, MODEKEYCOPY_BACKTOINDENTATION },
|
||||
{ 'b', 0, MODEKEYCOPY_PREVIOUSWORD },
|
||||
{ 'e', 0, MODEKEYCOPY_NEXTWORDEND },
|
||||
{ 'f', 0, MODEKEYCOPY_JUMP },
|
||||
{ 'g', 0, MODEKEYCOPY_HISTORYTOP },
|
||||
{ 'h', 0, MODEKEYCOPY_LEFT },
|
||||
{ 'j', 0, MODEKEYCOPY_DOWN },
|
||||
@@ -290,6 +298,8 @@ struct mode_key_tree mode_key_tree_emacs_choice;
|
||||
/* emacs copy mode keys. */
|
||||
const struct mode_key_entry mode_key_emacs_copy[] = {
|
||||
{ ' ', 0, MODEKEYCOPY_NEXTPAGE },
|
||||
{ ',', 0, MODEKEYCOPY_JUMPREVERSE },
|
||||
{ ';', 0, MODEKEYCOPY_JUMPAGAIN },
|
||||
{ '1' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '2' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '3' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
@@ -301,6 +311,8 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
|
||||
{ '9' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '<' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYTOP },
|
||||
{ '>' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYBOTTOM },
|
||||
{ 'F', 0, MODEKEYCOPY_JUMPBACK },
|
||||
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
|
||||
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCOPY_TOPLINE },
|
||||
{ 'R', 0, MODEKEYCOPY_RECTANGLETOGGLE },
|
||||
{ '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION },
|
||||
@@ -319,6 +331,7 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
|
||||
{ '\033' /* Escape */, 0, MODEKEYCOPY_CANCEL },
|
||||
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
|
||||
{ 'b' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSWORD },
|
||||
{ 'f', 0, MODEKEYCOPY_JUMP },
|
||||
{ 'f' | KEYC_ESCAPE, 0, MODEKEYCOPY_NEXTWORDEND },
|
||||
{ 'g', 0, MODEKEYCOPY_GOTOLINE },
|
||||
{ 'm' | KEYC_ESCAPE, 0, MODEKEYCOPY_BACKTOINDENTATION },
|
||||
|
||||
26
paste.c
26
paste.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: paste.c,v 1.13 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: paste.c,v 1.15 2010-06-22 23:36:54 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -156,3 +156,27 @@ paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Convert a buffer into a visible string. */
|
||||
char *
|
||||
paste_print(struct paste_buffer *pb, size_t width)
|
||||
{
|
||||
char *buf;
|
||||
size_t len, used;
|
||||
|
||||
if (width < 3)
|
||||
width = 3;
|
||||
buf = xmalloc(width * 4 + 1);
|
||||
|
||||
len = pb->size;
|
||||
if (len > width)
|
||||
len = width;
|
||||
|
||||
used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
|
||||
if (pb->size > width || used > width) {
|
||||
buf[width - 3] = '\0';
|
||||
strlcat(buf, "...", width);
|
||||
}
|
||||
|
||||
return (buf);
|
||||
}
|
||||
|
||||
4
resize.c
4
resize.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: resize.c,v 1.24 2009-09-25 17:47:42 tcunha Exp $ */
|
||||
/* $Id: resize.c,v 1.25 2010-06-22 23:26:18 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -105,7 +105,7 @@ recalculate_sizes(void)
|
||||
if (flag)
|
||||
has = s->curw->window == w;
|
||||
else
|
||||
has = session_has(s, w);
|
||||
has = session_has(s, w) != NULL;
|
||||
if (has) {
|
||||
if (s->sx < ssx)
|
||||
ssx = s->sx;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: screen-write.c,v 1.88 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: screen-write.c,v 1.90 2010-06-16 18:09:23 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "tmux.h"
|
||||
|
||||
void screen_write_initctx(struct screen_write_ctx *, struct tty_ctx *, int);
|
||||
void screen_write_overwrite(struct screen_write_ctx *);
|
||||
void screen_write_overwrite(struct screen_write_ctx *, u_int);
|
||||
int screen_write_combine(
|
||||
struct screen_write_ctx *, const struct utf8_data *);
|
||||
|
||||
@@ -1009,17 +1009,18 @@ screen_write_cell(struct screen_write_ctx *ctx,
|
||||
}
|
||||
|
||||
/* Check this will fit on the current line and wrap if not. */
|
||||
if (s->cx > screen_size_x(s) - width) {
|
||||
if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) {
|
||||
screen_write_linefeed(ctx, 1);
|
||||
s->cx = 0; /* carriage return */
|
||||
}
|
||||
|
||||
/* Sanity checks. */
|
||||
if (s->cx > screen_size_x(s) - 1 || s->cy > screen_size_y(s) - 1)
|
||||
if (((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - 1)
|
||||
|| s->cy > screen_size_y(s) - 1)
|
||||
return;
|
||||
|
||||
/* Handle overwriting of UTF-8 characters. */
|
||||
screen_write_overwrite(ctx);
|
||||
screen_write_overwrite(ctx, width);
|
||||
|
||||
/*
|
||||
* If the new character is UTF-8 wide, fill in padding cells. Have
|
||||
@@ -1122,12 +1123,11 @@ screen_write_combine(
|
||||
* by the same character.
|
||||
*/
|
||||
void
|
||||
screen_write_overwrite(struct screen_write_ctx *ctx)
|
||||
screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
const struct grid_cell *gc;
|
||||
const struct grid_utf8 *gu;
|
||||
u_int xx;
|
||||
|
||||
gc = grid_view_peek_cell(gd, s->cx, s->cy);
|
||||
@@ -1147,30 +1147,17 @@ screen_write_overwrite(struct screen_write_ctx *ctx)
|
||||
|
||||
/* Overwrite the character at the start of this padding. */
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
}
|
||||
|
||||
/* Overwrite following padding cells. */
|
||||
xx = s->cx;
|
||||
while (++xx < screen_size_x(s)) {
|
||||
gc = grid_view_peek_cell(gd, xx, s->cy);
|
||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||
break;
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
}
|
||||
} else if (gc->flags & GRID_FLAG_UTF8) {
|
||||
gu = grid_view_peek_utf8(gd, s->cx, s->cy);
|
||||
if (gu->width > 1) {
|
||||
/*
|
||||
* An UTF-8 wide cell; overwrite following padding
|
||||
* cells only.
|
||||
*/
|
||||
xx = s->cx;
|
||||
while (++xx < screen_size_x(s)) {
|
||||
gc = grid_view_peek_cell(gd, xx, s->cy);
|
||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||
break;
|
||||
grid_view_set_cell(
|
||||
gd, xx, s->cy, &grid_default_cell);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Overwrite any padding cells that belong to a UTF-8 character
|
||||
* we'll be overwriting with the current character.
|
||||
*/
|
||||
xx = s->cx + width - 1;
|
||||
while (++xx < screen_size_x(s)) {
|
||||
gc = grid_view_peek_cell(gd, xx, s->cy);
|
||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||
break;
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
}
|
||||
}
|
||||
|
||||
12
screen.c
12
screen.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: screen.c,v 1.99 2010-02-08 18:13:17 tcunha Exp $ */
|
||||
/* $Id: screen.c,v 1.101 2010-04-06 22:01:32 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@@ -30,9 +31,14 @@ void screen_resize_y(struct screen *, u_int);
|
||||
void
|
||||
screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
|
||||
{
|
||||
char hn[MAXHOSTNAMELEN];
|
||||
|
||||
s->grid = grid_create(sx, sy, hlimit);
|
||||
|
||||
s->title = xstrdup("");
|
||||
if (gethostname(hn, MAXHOSTNAMELEN) == 0)
|
||||
s->title = xstrdup(hn);
|
||||
else
|
||||
s->title = xstrdup("");
|
||||
|
||||
s->tabs = NULL;
|
||||
|
||||
@@ -49,7 +55,7 @@ screen_reinit(struct screen *s)
|
||||
s->rupper = 0;
|
||||
s->rlower = screen_size_y(s) - 1;
|
||||
|
||||
s->mode = MODE_CURSOR;
|
||||
s->mode = MODE_CURSOR | MODE_WRAP;
|
||||
|
||||
screen_reset_tabs(s);
|
||||
|
||||
|
||||
103
server-client.c
103
server-client.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: server-client.c,v 1.31 2010-02-08 18:27:34 tcunha Exp $ */
|
||||
/* $Id: server-client.c,v 1.35 2010-07-17 14:36:40 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -68,6 +68,10 @@ server_client_create(int fd)
|
||||
|
||||
ARRAY_INIT(&c->prompt_hdata);
|
||||
|
||||
c->stdin_file = NULL;
|
||||
c->stdout_file = NULL;
|
||||
c->stderr_file = NULL;
|
||||
|
||||
c->tty.fd = -1;
|
||||
c->title = NULL;
|
||||
|
||||
@@ -117,6 +121,13 @@ server_client_lost(struct client *c)
|
||||
if (c->flags & CLIENT_TERMINAL)
|
||||
tty_free(&c->tty);
|
||||
|
||||
if (c->stdin_file != NULL)
|
||||
fclose(c->stdin_file);
|
||||
if (c->stdout_file != NULL)
|
||||
fclose(c->stdout_file);
|
||||
if (c->stderr_file != NULL)
|
||||
fclose(c->stderr_file);
|
||||
|
||||
screen_free(&c->status);
|
||||
job_tree_free(&c->status_jobs);
|
||||
|
||||
@@ -299,7 +310,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
|
||||
server_redraw_window_borders(w);
|
||||
wp = w->active;
|
||||
}
|
||||
window_pane_mouse(wp, c, mouse);
|
||||
window_pane_mouse(wp, c->session, mouse);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -321,7 +332,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
|
||||
/* Try as a non-prefix key binding. */
|
||||
if ((bd = key_bindings_lookup(key)) == NULL) {
|
||||
if (!(c->flags & CLIENT_READONLY))
|
||||
window_pane_key(wp, c, key);
|
||||
window_pane_key(wp, c->session, key);
|
||||
} else
|
||||
key_bindings_dispatch(bd, c);
|
||||
}
|
||||
@@ -337,7 +348,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
|
||||
if (isprefix)
|
||||
c->flags |= CLIENT_PREFIX;
|
||||
else if (!(c->flags & CLIENT_READONLY))
|
||||
window_pane_key(wp, c, key);
|
||||
window_pane_key(wp, c->session, key);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -348,7 +359,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
|
||||
if (isprefix)
|
||||
c->flags |= CLIENT_PREFIX;
|
||||
else if (!(c->flags & CLIENT_READONLY))
|
||||
window_pane_key(wp, c, key);
|
||||
window_pane_key(wp, c->session, key);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -554,15 +565,39 @@ server_client_msg_dispatch(struct client *c)
|
||||
fatalx("MSG_IDENTIFY missing fd");
|
||||
memcpy(&identifydata, imsg.data, sizeof identifydata);
|
||||
|
||||
c->stdin_file = fdopen(imsg.fd, "r");
|
||||
if (c->stdin_file == NULL)
|
||||
fatal("fdopen(stdin) failed");
|
||||
server_client_msg_identify(c, &identifydata, imsg.fd);
|
||||
break;
|
||||
case MSG_STDOUT:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_STDOUT size");
|
||||
if (imsg.fd == -1)
|
||||
fatalx("MSG_STDOUT missing fd");
|
||||
|
||||
c->stdout_file = fdopen(imsg.fd, "w");
|
||||
if (c->stdout_file == NULL)
|
||||
fatal("fdopen(stdout) failed");
|
||||
break;
|
||||
case MSG_STDERR:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_STDERR size");
|
||||
if (imsg.fd == -1)
|
||||
fatalx("MSG_STDERR missing fd");
|
||||
|
||||
c->stderr_file = fdopen(imsg.fd, "w");
|
||||
if (c->stderr_file == NULL)
|
||||
fatal("fdopen(stderr) failed");
|
||||
break;
|
||||
case MSG_RESIZE:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_RESIZE size");
|
||||
|
||||
tty_resize(&c->tty);
|
||||
recalculate_sizes();
|
||||
server_redraw_client(c);
|
||||
if (tty_resize(&c->tty)) {
|
||||
recalculate_sizes();
|
||||
server_redraw_client(c);
|
||||
}
|
||||
break;
|
||||
case MSG_EXITING:
|
||||
if (datalen != 0)
|
||||
@@ -620,55 +655,58 @@ server_client_msg_dispatch(struct client *c)
|
||||
void printflike2
|
||||
server_client_msg_error(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||
{
|
||||
struct msg_print_data data;
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
||||
vfprintf(ctx->cmdclient->stderr_file, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
server_write_client(ctx->cmdclient, MSG_ERROR, &data, sizeof data);
|
||||
fputc('\n', ctx->cmdclient->stderr_file);
|
||||
fflush(ctx->cmdclient->stderr_file);
|
||||
|
||||
ctx->cmdclient->retcode = 1;
|
||||
}
|
||||
|
||||
/* Callback to send print message to client. */
|
||||
void printflike2
|
||||
server_client_msg_print(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||
{
|
||||
struct msg_print_data data;
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
||||
vfprintf(ctx->cmdclient->stdout_file, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
|
||||
fputc('\n', ctx->cmdclient->stdout_file);
|
||||
fflush(ctx->cmdclient->stdout_file);
|
||||
}
|
||||
|
||||
/* Callback to send print message to client, if not quiet. */
|
||||
void printflike2
|
||||
server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||
{
|
||||
struct msg_print_data data;
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
|
||||
if (options_get_number(&global_options, "quiet"))
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
||||
vfprintf(ctx->cmdclient->stdout_file, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
|
||||
fputc('\n', ctx->cmdclient->stderr_file);
|
||||
fflush(ctx->cmdclient->stdout_file);
|
||||
}
|
||||
|
||||
/* Handle command message. */
|
||||
void
|
||||
server_client_msg_command(struct client *c, struct msg_command_data *data)
|
||||
{
|
||||
struct cmd_ctx ctx;
|
||||
struct cmd_list *cmdlist = NULL;
|
||||
int argc;
|
||||
char **argv, *cause;
|
||||
struct cmd_ctx ctx;
|
||||
struct cmd_list *cmdlist = NULL;
|
||||
struct msg_exit_data exitdata;
|
||||
int argc;
|
||||
char **argv, *cause;
|
||||
|
||||
ctx.error = server_client_msg_error;
|
||||
ctx.print = server_client_msg_print;
|
||||
@@ -699,15 +737,18 @@ server_client_msg_command(struct client *c, struct msg_command_data *data)
|
||||
}
|
||||
cmd_free_argv(argc, argv);
|
||||
|
||||
if (cmd_list_exec(cmdlist, &ctx) != 1)
|
||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||
if (cmd_list_exec(cmdlist, &ctx) != 1) {
|
||||
exitdata.retcode = c->retcode;
|
||||
server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata);
|
||||
}
|
||||
cmd_list_free(cmdlist);
|
||||
return;
|
||||
|
||||
error:
|
||||
if (cmdlist != NULL)
|
||||
cmd_list_free(cmdlist);
|
||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||
exitdata.retcode = c->retcode;
|
||||
server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata);
|
||||
}
|
||||
|
||||
/* Handle identify message. */
|
||||
@@ -715,13 +756,19 @@ void
|
||||
server_client_msg_identify(
|
||||
struct client *c, struct msg_identify_data *data, int fd)
|
||||
{
|
||||
int tty_fd;
|
||||
|
||||
c->cwd = NULL;
|
||||
data->cwd[(sizeof data->cwd) - 1] = '\0';
|
||||
if (*data->cwd != '\0')
|
||||
c->cwd = xstrdup(data->cwd);
|
||||
|
||||
if (!isatty(fd))
|
||||
return;
|
||||
if ((tty_fd = dup(fd)) == -1)
|
||||
fatal("dup failed");
|
||||
data->term[(sizeof data->term) - 1] = '\0';
|
||||
tty_init(&c->tty, fd, data->term);
|
||||
tty_init(&c->tty, tty_fd, data->term);
|
||||
if (data->flags & IDENTIFY_UTF8)
|
||||
c->tty.flags |= TTY_UTF8;
|
||||
if (data->flags & IDENTIFY_256COLOURS)
|
||||
|
||||
62
server-fn.c
62
server-fn.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: server-fn.c,v 1.102 2010-01-25 17:13:43 tcunha Exp $ */
|
||||
/* $Id: server-fn.c,v 1.108 2010-07-02 02:45:52 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -24,7 +24,8 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
void server_callback_identify(int, short, void *);
|
||||
struct session *server_next_session(struct session *);
|
||||
void server_callback_identify(int, short, void *);
|
||||
|
||||
void
|
||||
server_fill_environ(struct session *s, struct environ *env)
|
||||
@@ -42,15 +43,6 @@ server_fill_environ(struct session *s, struct environ *env)
|
||||
environ_set(env, "TERM", term);
|
||||
}
|
||||
|
||||
void
|
||||
server_write_error(struct client *c, const char *msg)
|
||||
{
|
||||
struct msg_print_data printdata;
|
||||
|
||||
strlcpy(printdata.msg, msg, sizeof printdata.msg);
|
||||
server_write_client(c, MSG_ERROR, &printdata, sizeof printdata);
|
||||
}
|
||||
|
||||
void
|
||||
server_write_client(
|
||||
struct client *c, enum msgtype type, const void *buf, size_t len)
|
||||
@@ -193,7 +185,7 @@ server_status_window(struct window *w)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||
s = ARRAY_ITEM(&sessions, i);
|
||||
if (s != NULL && session_has(s, w))
|
||||
if (s != NULL && session_has(s, w) != NULL)
|
||||
server_status_session(s);
|
||||
}
|
||||
}
|
||||
@@ -258,7 +250,7 @@ server_kill_window(struct window *w)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||
s = ARRAY_ITEM(&sessions, i);
|
||||
if (s == NULL || !session_has(s, w))
|
||||
if (s == NULL || session_has(s, w) == NULL)
|
||||
continue;
|
||||
while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) {
|
||||
if (session_detach(s, wl)) {
|
||||
@@ -295,7 +287,7 @@ server_link_window(struct session *src, struct winlink *srcwl,
|
||||
* Can't use session_detach as it will destroy session
|
||||
* if this makes it empty.
|
||||
*/
|
||||
session_alert_cancel(dst, dstwl);
|
||||
dstwl->flags &= ~WINLINK_ALERTFLAGS;
|
||||
winlink_stack_remove(&dst->lastw, dstwl);
|
||||
winlink_remove(&dst->windows, dstwl);
|
||||
|
||||
@@ -334,9 +326,11 @@ server_destroy_pane(struct window_pane *wp)
|
||||
{
|
||||
struct window *w = wp->window;
|
||||
|
||||
close(wp->fd);
|
||||
bufferevent_free(wp->event);
|
||||
wp->fd = -1;
|
||||
if (wp->fd != -1) {
|
||||
close(wp->fd);
|
||||
bufferevent_free(wp->event);
|
||||
wp->fd = -1;
|
||||
}
|
||||
|
||||
if (options_get_number(&w->options, "remain-on-exit"))
|
||||
return;
|
||||
@@ -365,19 +359,49 @@ server_destroy_session_group(struct session *s)
|
||||
}
|
||||
}
|
||||
|
||||
struct session *
|
||||
server_next_session(struct session *s)
|
||||
{
|
||||
struct session *s_loop, *s_out;
|
||||
u_int i;
|
||||
|
||||
s_out = NULL;
|
||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||
s_loop = ARRAY_ITEM(&sessions, i);
|
||||
if (s_loop == s)
|
||||
continue;
|
||||
if (s_out == NULL ||
|
||||
timercmp(&s_loop->activity_time, &s_out->activity_time, <))
|
||||
s_out = s_loop;
|
||||
}
|
||||
return (s_out);
|
||||
}
|
||||
|
||||
void
|
||||
server_destroy_session(struct session *s)
|
||||
{
|
||||
struct client *c;
|
||||
struct session *s_new;
|
||||
u_int i;
|
||||
|
||||
if (!options_get_number(&s->options, "detach-on-destroy"))
|
||||
s_new = server_next_session(s);
|
||||
else
|
||||
s_new = NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (c == NULL || c->session != s)
|
||||
continue;
|
||||
c->session = NULL;
|
||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||
if (s_new == NULL) {
|
||||
c->session = NULL;
|
||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||
} else {
|
||||
c->session = s_new;
|
||||
server_redraw_client(c);
|
||||
}
|
||||
}
|
||||
recalculate_sizes();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: server-window.c,v 1.14 2010-02-26 13:26:44 tcunha Exp $ */
|
||||
/* $Id: server-window.c,v 1.15 2010-06-22 23:26:18 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -24,10 +24,10 @@
|
||||
#include "tmux.h"
|
||||
|
||||
int server_window_backoff(struct window_pane *);
|
||||
int server_window_check_bell(struct session *, struct window *);
|
||||
int server_window_check_activity(struct session *, struct window *);
|
||||
int server_window_check_bell(struct session *, struct winlink *);
|
||||
int server_window_check_activity(struct session *, struct winlink *);
|
||||
int server_window_check_content(
|
||||
struct session *, struct window *, struct window_pane *);
|
||||
struct session *, struct winlink *, struct window_pane *);
|
||||
|
||||
/* Check if this window should suspend reading. */
|
||||
int
|
||||
@@ -59,6 +59,7 @@ void
|
||||
server_window_loop(void)
|
||||
{
|
||||
struct window *w;
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
struct session *s;
|
||||
u_int i, j;
|
||||
@@ -81,33 +82,37 @@ server_window_loop(void)
|
||||
|
||||
for (j = 0; j < ARRAY_LENGTH(&sessions); j++) {
|
||||
s = ARRAY_ITEM(&sessions, j);
|
||||
if (s == NULL || !session_has(s, w))
|
||||
if (s == NULL)
|
||||
continue;
|
||||
wl = session_has(s, w);
|
||||
if (wl == NULL)
|
||||
continue;
|
||||
|
||||
if (server_window_check_bell(s, w) ||
|
||||
server_window_check_activity(s, w))
|
||||
if (server_window_check_bell(s, wl) ||
|
||||
server_window_check_activity(s, wl))
|
||||
server_status_session(s);
|
||||
TAILQ_FOREACH(wp, &w->panes, entry)
|
||||
server_window_check_content(s, w, wp);
|
||||
server_window_check_content(s, wl, wp);
|
||||
}
|
||||
w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_CONTENT);
|
||||
w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for bell in window. */
|
||||
int
|
||||
server_window_check_bell(struct session *s, struct window *w)
|
||||
server_window_check_bell(struct session *s, struct winlink *wl)
|
||||
{
|
||||
struct client *c;
|
||||
struct window *w = wl->window;
|
||||
u_int i;
|
||||
int action, visual;
|
||||
|
||||
if (!(w->flags & WINDOW_BELL))
|
||||
if (!(w->flags & WINDOW_BELL) || wl->flags & WINLINK_BELL)
|
||||
return (0);
|
||||
if (s->curw == wl)
|
||||
return (0);
|
||||
|
||||
if (session_alert_has_window(s, w, WINDOW_BELL))
|
||||
return (0);
|
||||
session_alert_add(s, w, WINDOW_BELL);
|
||||
wl->flags |= WINLINK_BELL;
|
||||
|
||||
action = options_get_number(&s->options, "bell-action");
|
||||
switch (action) {
|
||||
@@ -155,25 +160,22 @@ server_window_check_bell(struct session *s, struct window *w)
|
||||
|
||||
/* Check for activity in window. */
|
||||
int
|
||||
server_window_check_activity(struct session *s, struct window *w)
|
||||
server_window_check_activity(struct session *s, struct winlink *wl)
|
||||
{
|
||||
struct client *c;
|
||||
struct window *w = wl->window;
|
||||
u_int i;
|
||||
|
||||
if (!(w->flags & WINDOW_ACTIVITY))
|
||||
if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
|
||||
return (0);
|
||||
if (s->curw->window == w)
|
||||
if (s->curw == wl)
|
||||
return (0);
|
||||
|
||||
if (!options_get_number(&w->options, "monitor-activity"))
|
||||
return (0);
|
||||
|
||||
if (session_alert_has_window(s, w, WINDOW_ACTIVITY))
|
||||
return (0);
|
||||
session_alert_add(s, w, WINDOW_ACTIVITY);
|
||||
wl->flags |= WINLINK_ACTIVITY;
|
||||
|
||||
if (s->flags & SESSION_UNATTACHED)
|
||||
return (0);
|
||||
if (options_get_number(&s->options, "visual-activity")) {
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
@@ -190,31 +192,28 @@ server_window_check_activity(struct session *s, struct window *w)
|
||||
/* Check for content change in window. */
|
||||
int
|
||||
server_window_check_content(
|
||||
struct session *s, struct window *w, struct window_pane *wp)
|
||||
struct session *s, struct winlink *wl, struct window_pane *wp)
|
||||
{
|
||||
struct client *c;
|
||||
struct window *w = wl->window;
|
||||
u_int i;
|
||||
char *found, *ptr;
|
||||
|
||||
if (!(w->flags & WINDOW_ACTIVITY)) /* activity for new content */
|
||||
/* Activity flag must be set for new content. */
|
||||
if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_CONTENT)
|
||||
return (0);
|
||||
if (s->curw->window == w)
|
||||
if (s->curw == wl)
|
||||
return (0);
|
||||
|
||||
ptr = options_get_string(&w->options, "monitor-content");
|
||||
if (ptr == NULL || *ptr == '\0')
|
||||
return (0);
|
||||
|
||||
if (session_alert_has_window(s, w, WINDOW_CONTENT))
|
||||
return (0);
|
||||
|
||||
if ((found = window_pane_search(wp, ptr, NULL)) == NULL)
|
||||
return (0);
|
||||
xfree(found);
|
||||
|
||||
session_alert_add(s, w, WINDOW_CONTENT);
|
||||
if (s->flags & SESSION_UNATTACHED)
|
||||
return (0);
|
||||
wl->flags |= WINLINK_CONTENT;
|
||||
|
||||
if (options_get_number(&s->options, "visual-content")) {
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
|
||||
97
server.c
97
server.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: server.c,v 1.235 2010-02-08 18:29:32 tcunha Exp $ */
|
||||
/* $Id: server.c,v 1.242 2010-06-22 23:21:39 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -48,9 +48,6 @@ struct clients dead_clients;
|
||||
int server_fd;
|
||||
int server_shutdown;
|
||||
struct event server_ev_accept;
|
||||
struct event server_ev_sigterm;
|
||||
struct event server_ev_sigusr1;
|
||||
struct event server_ev_sigchld;
|
||||
struct event server_ev_second;
|
||||
|
||||
int server_create_socket(void);
|
||||
@@ -88,7 +85,7 @@ server_create_socket(void)
|
||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
fatal("socket failed");
|
||||
|
||||
mask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
|
||||
mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
|
||||
if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1)
|
||||
fatal("bind failed");
|
||||
umask(mask);
|
||||
@@ -113,7 +110,7 @@ int
|
||||
server_start(char *path)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
int pair[2], retval;
|
||||
int pair[2];
|
||||
char *cause;
|
||||
struct timeval tv;
|
||||
u_int i;
|
||||
@@ -143,6 +140,11 @@ server_start(char *path)
|
||||
if (daemon(1, 0) != 0)
|
||||
fatal("daemon failed");
|
||||
|
||||
/* event_init() was called in our parent, need to reinit. */
|
||||
if (event_reinit(ev_base) != 0)
|
||||
fatal("event_reinit failed");
|
||||
clear_signals();
|
||||
|
||||
logfile("server");
|
||||
log_debug("server started, pid %ld", (long) getpid());
|
||||
|
||||
@@ -166,26 +168,9 @@ server_start(char *path)
|
||||
setproctitle("server (%s)", rpathbuf);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_KQUEUE
|
||||
if (setenv("EVENT_NOKQUEUE", "1", 1) != 0)
|
||||
fatal("setenv failed");
|
||||
#endif
|
||||
#ifdef HAVE_BROKEN_POLL
|
||||
if (setenv("EVENT_NOPOLL", "1", 1) != 0)
|
||||
fatal("setenv failed");
|
||||
#endif
|
||||
event_init();
|
||||
#ifdef HAVE_BROKEN_KQUEUE
|
||||
unsetenv("EVENT_NOKQUEUE");
|
||||
#endif
|
||||
#ifdef HAVE_BROKEN_POLL
|
||||
unsetenv("EVENT_NOPOLL");
|
||||
#endif
|
||||
|
||||
server_fd = server_create_socket();
|
||||
server_client_create(pair[1]);
|
||||
|
||||
retval = 0;
|
||||
if (access(SYSTEM_CFG, R_OK) == 0)
|
||||
load_cfg(SYSTEM_CFG, NULL, &cfg_causes);
|
||||
else if (errno != ENOENT) {
|
||||
@@ -201,10 +186,11 @@ server_start(char *path)
|
||||
*/
|
||||
if (!ARRAY_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) {
|
||||
wp = ARRAY_FIRST(&sessions)->curw->window->active;
|
||||
window_pane_set_mode(wp, &window_more_mode);
|
||||
window_pane_set_mode(wp, &window_copy_mode);
|
||||
window_copy_init_for_output(wp);
|
||||
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
|
||||
cause = ARRAY_ITEM(&cfg_causes, i);
|
||||
window_more_add(wp, "%s", cause);
|
||||
window_copy_add(wp, "%s", cause);
|
||||
xfree(cause);
|
||||
}
|
||||
ARRAY_FREE(&cfg_causes);
|
||||
@@ -220,7 +206,7 @@ server_start(char *path)
|
||||
evtimer_set(&server_ev_second, server_second_callback, NULL);
|
||||
evtimer_add(&server_ev_second, &tv);
|
||||
|
||||
server_signal_set();
|
||||
set_signals(server_signal_callback);
|
||||
server_loop();
|
||||
exit(0);
|
||||
}
|
||||
@@ -328,9 +314,9 @@ server_update_socket(void)
|
||||
if (n != last) {
|
||||
last = n;
|
||||
if (n != 0)
|
||||
chmod(socket_path, S_IRWXU);
|
||||
chmod(socket_path, S_IRWXU|S_IRWXG);
|
||||
else
|
||||
chmod(socket_path, S_IRUSR|S_IWUSR);
|
||||
chmod(socket_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,61 +345,6 @@ server_accept_callback(int fd, short events, unused void *data)
|
||||
server_client_create(newfd);
|
||||
}
|
||||
|
||||
/* Set up server signal handling. */
|
||||
void
|
||||
server_signal_set(void)
|
||||
{
|
||||
struct sigaction sigact;
|
||||
|
||||
memset(&sigact, 0, sizeof sigact);
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = SA_RESTART;
|
||||
sigact.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGHUP, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
|
||||
signal_set(&server_ev_sigchld, SIGCHLD, server_signal_callback, NULL);
|
||||
signal_add(&server_ev_sigchld, NULL);
|
||||
signal_set(&server_ev_sigterm, SIGTERM, server_signal_callback, NULL);
|
||||
signal_add(&server_ev_sigterm, NULL);
|
||||
signal_set(&server_ev_sigusr1, SIGUSR1, server_signal_callback, NULL);
|
||||
signal_add(&server_ev_sigusr1, NULL);
|
||||
}
|
||||
|
||||
/* Destroy server signal events. */
|
||||
void
|
||||
server_signal_clear(void)
|
||||
{
|
||||
struct sigaction sigact;
|
||||
|
||||
memset(&sigact, 0, sizeof sigact);
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = SA_RESTART;
|
||||
sigact.sa_handler = SIG_DFL;
|
||||
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGHUP, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
|
||||
signal_del(&server_ev_sigchld);
|
||||
signal_del(&server_ev_sigterm);
|
||||
signal_del(&server_ev_sigusr1);
|
||||
}
|
||||
|
||||
/* Signal handler. */
|
||||
/* ARGSUSED */
|
||||
void
|
||||
|
||||
138
session.c
138
session.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: session.c,v 1.74 2009-12-26 23:45:21 tcunha Exp $ */
|
||||
/* $Id: session.c,v 1.77 2010-07-02 02:49:19 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -31,71 +31,8 @@ struct sessions sessions;
|
||||
struct sessions dead_sessions;
|
||||
struct session_groups session_groups;
|
||||
|
||||
struct winlink *session_next_activity(struct session *, struct winlink *);
|
||||
struct winlink *session_previous_activity(struct session *, struct winlink *);
|
||||
|
||||
void
|
||||
session_alert_cancel(struct session *s, struct winlink *wl)
|
||||
{
|
||||
struct session_alert *sa, *sb;
|
||||
|
||||
sa = SLIST_FIRST(&s->alerts);
|
||||
while (sa != NULL) {
|
||||
sb = sa;
|
||||
sa = SLIST_NEXT(sa, entry);
|
||||
|
||||
if (wl == NULL || sb->wl == wl) {
|
||||
SLIST_REMOVE(&s->alerts, sb, session_alert, entry);
|
||||
xfree(sb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
session_alert_add(struct session *s, struct window *w, int type)
|
||||
{
|
||||
struct session_alert *sa;
|
||||
struct winlink *wl;
|
||||
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (wl == s->curw)
|
||||
continue;
|
||||
|
||||
if (wl->window == w &&
|
||||
!session_alert_has(s, wl, type)) {
|
||||
sa = xmalloc(sizeof *sa);
|
||||
sa->wl = wl;
|
||||
sa->type = type;
|
||||
SLIST_INSERT_HEAD(&s->alerts, sa, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
session_alert_has(struct session *s, struct winlink *wl, int type)
|
||||
{
|
||||
struct session_alert *sa;
|
||||
|
||||
SLIST_FOREACH(sa, &s->alerts, entry) {
|
||||
if (sa->wl == wl && sa->type == type)
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
session_alert_has_window(struct session *s, struct window *w, int type)
|
||||
{
|
||||
struct session_alert *sa;
|
||||
|
||||
SLIST_FOREACH(sa, &s->alerts, entry) {
|
||||
if (sa->wl->window == w && sa->type == type)
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
struct winlink *session_next_alert(struct winlink *);
|
||||
struct winlink *session_previous_alert(struct winlink *);
|
||||
|
||||
/* Find session by name. */
|
||||
struct session *
|
||||
@@ -130,10 +67,11 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
||||
fatal("gettimeofday failed");
|
||||
memcpy(&s->activity_time, &s->creation_time, sizeof s->activity_time);
|
||||
|
||||
s->cwd = xstrdup(cwd);
|
||||
|
||||
s->curw = NULL;
|
||||
TAILQ_INIT(&s->lastw);
|
||||
RB_INIT(&s->windows);
|
||||
SLIST_INIT(&s->alerts);
|
||||
|
||||
paste_init_stack(&s->buffers);
|
||||
|
||||
@@ -196,7 +134,6 @@ session_destroy(struct session *s)
|
||||
xfree(s->tio);
|
||||
|
||||
session_group_remove(s);
|
||||
session_alert_cancel(s, NULL);
|
||||
environ_free(&s->environ);
|
||||
options_free(&s->options);
|
||||
paste_free_stack(&s->buffers);
|
||||
@@ -206,6 +143,7 @@ session_destroy(struct session *s)
|
||||
while (!RB_EMPTY(&s->windows))
|
||||
winlink_remove(&s->windows, RB_ROOT(&s->windows));
|
||||
|
||||
xfree(s->cwd);
|
||||
xfree(s->name);
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&dead_sessions); i++) {
|
||||
@@ -284,7 +222,7 @@ session_detach(struct session *s, struct winlink *wl)
|
||||
session_last(s) != 0 && session_previous(s, 0) != 0)
|
||||
session_next(s, 0);
|
||||
|
||||
session_alert_cancel(s, wl);
|
||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
||||
winlink_stack_remove(&s->lastw, wl);
|
||||
winlink_remove(&s->windows, wl);
|
||||
session_group_synchronize_from(s);
|
||||
@@ -296,27 +234,23 @@ session_detach(struct session *s, struct winlink *wl)
|
||||
}
|
||||
|
||||
/* Return if session has window. */
|
||||
int
|
||||
struct winlink *
|
||||
session_has(struct session *s, struct window *w)
|
||||
{
|
||||
struct winlink *wl;
|
||||
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (wl->window == w)
|
||||
return (1);
|
||||
return (wl);
|
||||
}
|
||||
return (0);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct winlink *
|
||||
session_next_activity(struct session *s, struct winlink *wl)
|
||||
session_next_alert(struct winlink *wl)
|
||||
{
|
||||
while (wl != NULL) {
|
||||
if (session_alert_has(s, wl, WINDOW_BELL))
|
||||
break;
|
||||
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||
break;
|
||||
if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||
if (wl->flags & WINLINK_ALERTFLAGS)
|
||||
break;
|
||||
wl = winlink_next(wl);
|
||||
}
|
||||
@@ -325,7 +259,7 @@ session_next_activity(struct session *s, struct winlink *wl)
|
||||
|
||||
/* Move session to next window. */
|
||||
int
|
||||
session_next(struct session *s, int activity)
|
||||
session_next(struct session *s, int alert)
|
||||
{
|
||||
struct winlink *wl;
|
||||
|
||||
@@ -333,11 +267,11 @@ session_next(struct session *s, int activity)
|
||||
return (-1);
|
||||
|
||||
wl = winlink_next(s->curw);
|
||||
if (activity)
|
||||
wl = session_next_activity(s, wl);
|
||||
if (alert)
|
||||
wl = session_next_alert(wl);
|
||||
if (wl == NULL) {
|
||||
wl = RB_MIN(winlinks, &s->windows);
|
||||
if (activity && ((wl = session_next_activity(s, wl)) == NULL))
|
||||
if (alert && ((wl = session_next_alert(wl)) == NULL))
|
||||
return (-1);
|
||||
}
|
||||
if (wl == s->curw)
|
||||
@@ -345,19 +279,15 @@ session_next(struct session *s, int activity)
|
||||
winlink_stack_remove(&s->lastw, wl);
|
||||
winlink_stack_push(&s->lastw, s->curw);
|
||||
s->curw = wl;
|
||||
session_alert_cancel(s, wl);
|
||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct winlink *
|
||||
session_previous_activity(struct session *s, struct winlink *wl)
|
||||
session_previous_alert(struct winlink *wl)
|
||||
{
|
||||
while (wl != NULL) {
|
||||
if (session_alert_has(s, wl, WINDOW_BELL))
|
||||
break;
|
||||
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||
break;
|
||||
if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||
if (wl->flags & WINLINK_ALERTFLAGS)
|
||||
break;
|
||||
wl = winlink_previous(wl);
|
||||
}
|
||||
@@ -366,7 +296,7 @@ session_previous_activity(struct session *s, struct winlink *wl)
|
||||
|
||||
/* Move session to previous window. */
|
||||
int
|
||||
session_previous(struct session *s, int activity)
|
||||
session_previous(struct session *s, int alert)
|
||||
{
|
||||
struct winlink *wl;
|
||||
|
||||
@@ -374,11 +304,11 @@ session_previous(struct session *s, int activity)
|
||||
return (-1);
|
||||
|
||||
wl = winlink_previous(s->curw);
|
||||
if (activity)
|
||||
wl = session_previous_activity(s, wl);
|
||||
if (alert)
|
||||
wl = session_previous_alert(wl);
|
||||
if (wl == NULL) {
|
||||
wl = RB_MAX(winlinks, &s->windows);
|
||||
if (activity && (wl = session_previous_activity(s, wl)) == NULL)
|
||||
if (alert && (wl = session_previous_alert(wl)) == NULL)
|
||||
return (-1);
|
||||
}
|
||||
if (wl == s->curw)
|
||||
@@ -386,7 +316,7 @@ session_previous(struct session *s, int activity)
|
||||
winlink_stack_remove(&s->lastw, wl);
|
||||
winlink_stack_push(&s->lastw, s->curw);
|
||||
s->curw = wl;
|
||||
session_alert_cancel(s, wl);
|
||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -404,7 +334,7 @@ session_select(struct session *s, int idx)
|
||||
winlink_stack_remove(&s->lastw, wl);
|
||||
winlink_stack_push(&s->lastw, s->curw);
|
||||
s->curw = wl;
|
||||
session_alert_cancel(s, wl);
|
||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -423,7 +353,7 @@ session_last(struct session *s)
|
||||
winlink_stack_remove(&s->lastw, wl);
|
||||
winlink_stack_push(&s->lastw, s->curw);
|
||||
s->curw = wl;
|
||||
session_alert_cancel(s, wl);
|
||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -540,7 +470,6 @@ session_group_synchronize1(struct session *target, struct session *s)
|
||||
struct winlinks old_windows, *ww;
|
||||
struct winlink_stack old_lastw;
|
||||
struct winlink *wl, *wl2;
|
||||
struct session_alert *sa;
|
||||
|
||||
/* Don't do anything if the session is empty (it'll be destroyed). */
|
||||
ww = &target->windows;
|
||||
@@ -558,8 +487,10 @@ session_group_synchronize1(struct session *target, struct session *s)
|
||||
RB_INIT(&s->windows);
|
||||
|
||||
/* Link all the windows from the target. */
|
||||
RB_FOREACH(wl, winlinks, ww)
|
||||
winlink_add(&s->windows, wl->window, wl->idx);
|
||||
RB_FOREACH(wl, winlinks, ww) {
|
||||
wl2 = winlink_add(&s->windows, wl->window, wl->idx);
|
||||
wl2->flags |= wl->flags & WINLINK_ALERTFLAGS;
|
||||
}
|
||||
|
||||
/* Fix up the current window. */
|
||||
if (s->curw != NULL)
|
||||
@@ -576,15 +507,6 @@ session_group_synchronize1(struct session *target, struct session *s)
|
||||
TAILQ_INSERT_TAIL(&s->lastw, wl2, sentry);
|
||||
}
|
||||
|
||||
/* And update the alerts list. */
|
||||
SLIST_FOREACH(sa, &s->alerts, entry) {
|
||||
wl = winlink_find_by_index(&s->windows, sa->wl->idx);
|
||||
if (wl == NULL)
|
||||
session_alert_cancel(s, sa->wl);
|
||||
else
|
||||
sa->wl = wl;
|
||||
}
|
||||
|
||||
/* Then free the old winlinks list. */
|
||||
while (!RB_EMPTY(&old_windows)) {
|
||||
wl = RB_ROOT(&old_windows);
|
||||
|
||||
88
signal.c
Normal file
88
signal.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/* $Id: signal.c,v 1.2 2010-05-14 14:35:26 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
* Copyright (c) 2010 Romain Francoise <rfrancoise@debian.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 <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
struct event ev_sighup;
|
||||
struct event ev_sigchld;
|
||||
struct event ev_sigcont;
|
||||
struct event ev_sigterm;
|
||||
struct event ev_sigusr1;
|
||||
struct event ev_sigwinch;
|
||||
|
||||
void
|
||||
set_signals(void(*handler)(int, short, unused void *))
|
||||
{
|
||||
struct sigaction sigact;
|
||||
|
||||
memset(&sigact, 0, sizeof sigact);
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = SA_RESTART;
|
||||
sigact.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
|
||||
signal_set(&ev_sighup, SIGHUP, handler, NULL);
|
||||
signal_add(&ev_sighup, NULL);
|
||||
signal_set(&ev_sigchld, SIGCHLD, handler, NULL);
|
||||
signal_add(&ev_sigchld, NULL);
|
||||
signal_set(&ev_sigcont, SIGCONT, handler, NULL);
|
||||
signal_add(&ev_sigcont, NULL);
|
||||
signal_set(&ev_sigterm, SIGTERM, handler, NULL);
|
||||
signal_add(&ev_sigterm, NULL);
|
||||
signal_set(&ev_sigusr1, SIGUSR1, handler, NULL);
|
||||
signal_add(&ev_sigusr1, NULL);
|
||||
signal_set(&ev_sigwinch, SIGWINCH, handler, NULL);
|
||||
signal_add(&ev_sigwinch, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
clear_signals(void)
|
||||
{
|
||||
struct sigaction sigact;
|
||||
|
||||
memset(&sigact, 0, sizeof sigact);
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = SA_RESTART;
|
||||
sigact.sa_handler = SIG_DFL;
|
||||
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
|
||||
event_del(&ev_sighup);
|
||||
event_del(&ev_sigchld);
|
||||
event_del(&ev_sigcont);
|
||||
event_del(&ev_sigterm);
|
||||
event_del(&ev_sigusr1);
|
||||
event_del(&ev_sigwinch);
|
||||
}
|
||||
72
status.c
72
status.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: status.c,v 1.144 2010-03-10 13:41:13 nicm Exp $ */
|
||||
/* $Id: status.c,v 1.149 2010-06-22 23:26:18 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -35,7 +35,6 @@ char *status_redraw_get_right(
|
||||
struct client *, time_t, int, struct grid_cell *, size_t *);
|
||||
char *status_job(struct client *, char **);
|
||||
void status_job_callback(struct job *);
|
||||
size_t status_width(struct client *, struct winlink *, time_t);
|
||||
char *status_print(
|
||||
struct client *, struct winlink *, time_t, struct grid_cell *);
|
||||
void status_replace1(struct client *,
|
||||
@@ -249,25 +248,15 @@ status_redraw(struct client *c)
|
||||
*/
|
||||
offset = 0;
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
if (larrow == 1 && offset < wlstart) {
|
||||
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||
larrow = -1;
|
||||
else if (session_alert_has(s, wl, WINDOW_BELL))
|
||||
larrow = -1;
|
||||
else if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||
larrow = -1;
|
||||
}
|
||||
if (wl->flags & WINLINK_ALERTFLAGS &&
|
||||
larrow == 1 && offset < wlstart)
|
||||
larrow = -1;
|
||||
|
||||
offset += wl->status_width;
|
||||
|
||||
if (rarrow == 1 && offset > wlstart + wlwidth) {
|
||||
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||
rarrow = -1;
|
||||
else if (session_alert_has(s, wl, WINDOW_BELL))
|
||||
rarrow = -1;
|
||||
else if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||
rarrow = -1;
|
||||
}
|
||||
if (wl->flags & WINLINK_ALERTFLAGS &&
|
||||
rarrow == 1 && offset > wlstart + wlwidth)
|
||||
rarrow = -1;
|
||||
}
|
||||
|
||||
draw:
|
||||
@@ -400,11 +389,11 @@ status_replace1(struct client *c,struct winlink *wl,
|
||||
goto do_replace;
|
||||
case 'F':
|
||||
tmp[0] = ' ';
|
||||
if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||
if (wl->flags & WINLINK_CONTENT)
|
||||
tmp[0] = '+';
|
||||
else if (session_alert_has(s, wl, WINDOW_BELL))
|
||||
else if (wl->flags & WINLINK_BELL)
|
||||
tmp[0] = '!';
|
||||
else if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||
else if (wl->flags & WINLINK_ACTIVITY)
|
||||
tmp[0] = '#';
|
||||
else if (wl == s->curw)
|
||||
tmp[0] = '*';
|
||||
@@ -560,30 +549,6 @@ status_job_callback(struct job *job)
|
||||
job->data = xstrdup(line);
|
||||
}
|
||||
|
||||
/* Calculate winlink status line entry width. */
|
||||
size_t
|
||||
status_width(struct client *c, struct winlink *wl, time_t t)
|
||||
{
|
||||
struct options *oo = &wl->window->options;
|
||||
struct session *s = c->session;
|
||||
const char *fmt;
|
||||
char *text;
|
||||
size_t size;
|
||||
int utf8flag;
|
||||
|
||||
utf8flag = options_get_number(&s->options, "status-utf8");
|
||||
|
||||
fmt = options_get_string(&wl->window->options, "window-status-format");
|
||||
if (wl == s->curw)
|
||||
fmt = options_get_string(oo, "window-status-current-format");
|
||||
|
||||
text = status_replace(c, wl, fmt, t, 1);
|
||||
size = screen_write_cstrlen(utf8flag, "%s", text);
|
||||
xfree(text);
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
/* Return winlink status line entry and adjust gc as necessary. */
|
||||
char *
|
||||
status_print(
|
||||
@@ -618,10 +583,17 @@ status_print(
|
||||
fmt = options_get_string(oo, "window-status-current-format");
|
||||
}
|
||||
|
||||
if (session_alert_has(s, wl, WINDOW_ACTIVITY) ||
|
||||
session_alert_has(s, wl, WINDOW_BELL) ||
|
||||
session_alert_has(s, wl, WINDOW_CONTENT))
|
||||
gc->attr ^= GRID_ATTR_REVERSE;
|
||||
if (wl->flags & WINLINK_ALERTFLAGS) {
|
||||
fg = options_get_number(oo, "window-status-alert-fg");
|
||||
if (fg != 8)
|
||||
colour_set_fg(gc, fg);
|
||||
bg = options_get_number(oo, "window-status-alert-bg");
|
||||
if (bg != 8)
|
||||
colour_set_bg(gc, bg);
|
||||
attr = options_get_number(oo, "window-status-alert-attr");
|
||||
if (attr != 0)
|
||||
gc->attr = attr;
|
||||
}
|
||||
|
||||
text = status_replace(c, wl, fmt, t, 1);
|
||||
return (text);
|
||||
@@ -1071,7 +1043,7 @@ status_prompt_key(struct client *c, int key)
|
||||
status_prompt_clear(c);
|
||||
break;
|
||||
case MODEKEY_OTHER:
|
||||
if (key < 32 || key == 127)
|
||||
if ((key & 0xff00) != 0 || key < 32 || key == 127)
|
||||
break;
|
||||
c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + 2);
|
||||
|
||||
|
||||
347
tmux.1
347
tmux.1
@@ -1,4 +1,4 @@
|
||||
.\" $Id: tmux.1,v 1.237 2010-03-08 15:02:07 tcunha Exp $
|
||||
.\" $Id: tmux.1,v 1.264 2010-07-17 14:39:01 tcunha Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
.\"
|
||||
@@ -14,7 +14,7 @@
|
||||
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: March 2 2010 $
|
||||
.Dd $Mdocdate: July 15 2010 $
|
||||
.Dt TMUX 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -131,10 +131,6 @@ commands which are executed in sequence when the server is first started.
|
||||
If a command in the configuration file fails,
|
||||
.Nm
|
||||
will report an error and exit without executing further commands.
|
||||
.It Fl l
|
||||
Behave as a login shell.
|
||||
This flag currently has no effect and is for compatibility with other shells
|
||||
when using tmux as a login shell.
|
||||
.It Fl L Ar socket-name
|
||||
.Nm
|
||||
stores the server socket in a directory under
|
||||
@@ -155,6 +151,10 @@ If the socket is accidentally removed, the
|
||||
signal may be sent to the
|
||||
.Nm
|
||||
server process to recreate it.
|
||||
.It Fl l
|
||||
Behave as a login shell.
|
||||
This flag currently has no effect and is for compatibility with other shells
|
||||
when using tmux as a login shell.
|
||||
.It Fl q
|
||||
Set the
|
||||
.Ic quiet
|
||||
@@ -213,32 +213,110 @@ prefix key,
|
||||
.Ql C-b
|
||||
(Ctrl-b) by default, followed by a command key.
|
||||
.Pp
|
||||
Some of the default key bindings are:
|
||||
The default command key bindings are:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -offset indent -compact
|
||||
.Bl -tag -width "XXXXXXXXXX" -offset indent -compact
|
||||
.It C-b
|
||||
Send the prefix key (C-b) through to the application.
|
||||
.It C-o
|
||||
Rotate the panes in the current window forwards.
|
||||
.It C-z
|
||||
Suspend the
|
||||
.Nm
|
||||
client.
|
||||
.It !
|
||||
Break the current pane out of the window.
|
||||
.It \&"
|
||||
Split the current pane into two, top and bottom.
|
||||
.It #
|
||||
List all paste buffers.
|
||||
.It %
|
||||
Split the current pane into two, left and right.
|
||||
.It &
|
||||
Kill the current window.
|
||||
.It '
|
||||
Prompt for a window index to select.
|
||||
.It ,
|
||||
Rename the current window.
|
||||
.It -
|
||||
Delete the most recently copied buffer of text.
|
||||
.It .
|
||||
Prompt for an index to move the current window.
|
||||
.It 0 to 9
|
||||
Select windows 0 to 9.
|
||||
.It :
|
||||
Enter the
|
||||
.Nm
|
||||
command prompt.
|
||||
.It =
|
||||
Choose which buffer to paste interactively from a list.
|
||||
.It \&?
|
||||
List all key bindings.
|
||||
.It D
|
||||
Choose a client to detach.
|
||||
.It \&[
|
||||
Enter copy mode to copy text or view the history.
|
||||
.It \&]
|
||||
Paste the most recently copied buffer of text.
|
||||
.It c
|
||||
Create a new window.
|
||||
.It d
|
||||
Detach the current client.
|
||||
.It f
|
||||
Prompt to search for text in open windows.
|
||||
.It i
|
||||
Display some information about the current window.
|
||||
.It l
|
||||
Move to the previously selected window.
|
||||
.It n
|
||||
Change to the next window.
|
||||
.It o
|
||||
Select the next pane in the current window.
|
||||
.It p
|
||||
Change to the previous window.
|
||||
.It &
|
||||
Kill the current window.
|
||||
.It ,
|
||||
Rename the current window.
|
||||
.It \&?
|
||||
List all key bindings.
|
||||
.It q
|
||||
Briefly display pane indexes.
|
||||
.It r
|
||||
Force redraw of the attached client.
|
||||
.It s
|
||||
Select a new session for the attached client interactively.
|
||||
.It t
|
||||
Show the time.
|
||||
.It w
|
||||
Choose the current window interactively.
|
||||
.It x
|
||||
Kill the current pane.
|
||||
.It {
|
||||
Swap the current pane with the previous pane.
|
||||
.It }
|
||||
Swap the current pane with the next pane.
|
||||
.It ~
|
||||
Show previous messages from
|
||||
.Nm ,
|
||||
if any.
|
||||
.It Page Up
|
||||
Enter copy mode and scroll one page up.
|
||||
.It Up, Down
|
||||
.It Left, Right
|
||||
Change to the pane above, below, to the left, or to the right of the current
|
||||
pane.
|
||||
.It M-1 to M-5
|
||||
Arrange panes in one of the five preset layouts: even-horizontal,
|
||||
even-vertical, main-horizontal, main-vertical, or tiled.
|
||||
.It M-n
|
||||
Move to the next window with a bell or activity marker.
|
||||
.It M-o
|
||||
Rotate the panes in the current window backwards.
|
||||
.It M-p
|
||||
Move to the previous window with a bell or activity marker.
|
||||
.It C-Up, C-Down
|
||||
.It C-Left, C-Right
|
||||
Resize the current pane in steps of one cell.
|
||||
.It M-Up, M-Down
|
||||
.It M-Left, M-Right
|
||||
Resize the current pane in steps of five cells.
|
||||
.El
|
||||
.Pp
|
||||
A complete list may be obtained with the
|
||||
.Ic list-keys
|
||||
command (bound to
|
||||
.Ql \&?
|
||||
by default).
|
||||
Key bindings may be changed with the
|
||||
.Ic bind-key
|
||||
and
|
||||
@@ -336,6 +414,11 @@ If neither a colon nor period appears,
|
||||
first attempts to use the argument as a pane index; if that fails, it is looked
|
||||
up as for
|
||||
.Ar target-window .
|
||||
A
|
||||
.Ql +
|
||||
or
|
||||
.Ql -
|
||||
indicate the next or previous pane index, respectively.
|
||||
One of the strings
|
||||
.Em top ,
|
||||
.Em bottom ,
|
||||
@@ -347,6 +430,18 @@ One of the strings
|
||||
.Em bottom-right
|
||||
may be used instead of a pane index.
|
||||
.Pp
|
||||
The special characters
|
||||
.Ql +
|
||||
and
|
||||
.Ql -
|
||||
may be followed by an offset, for example:
|
||||
.Bd -literal -offset indent
|
||||
select-window -t:+2
|
||||
.Ed
|
||||
.Pp
|
||||
When dealing with a session that doesn't contain sequential window indexes,
|
||||
they will be correctly skipped.
|
||||
.Pp
|
||||
.Ar shell-command
|
||||
arguments are
|
||||
.Xr sh 1
|
||||
@@ -368,7 +463,6 @@ bind-key F1 set-window-option force-width 81
|
||||
.Pp
|
||||
Or if using
|
||||
.Xr sh 1 :
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
$ tmux bind-key F1 set-window-option force-width 81
|
||||
.Ed
|
||||
@@ -396,13 +490,12 @@ new-window ; split-window -d
|
||||
.Pp
|
||||
Or from
|
||||
.Xr sh 1 :
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
$ tmux kill-window -t :1
|
||||
|
||||
$ tmux new-window \\; split-window -d
|
||||
$ tmux new-window \e; split-window -d
|
||||
|
||||
$ tmux new-session -d 'vi /etc/passwd' \\; split-window -d \\; attach
|
||||
$ tmux new-session -d 'vi /etc/passwd' \e; split-window -d \e; attach
|
||||
.Ed
|
||||
.Sh CLIENTS AND SESSIONS
|
||||
The
|
||||
@@ -475,17 +568,15 @@ List the syntax of all commands supported by
|
||||
.It Ic list-sessions
|
||||
.D1 (alias: Ic ls )
|
||||
List all sessions managed by the server.
|
||||
.It Xo Ic lock-client
|
||||
.Op Fl t Ar target-client
|
||||
.Xc
|
||||
.It Ic lock-client Op Fl t Ar target-client
|
||||
.D1 (alias: Ic lockc )
|
||||
Lock
|
||||
.Ar target-client ,
|
||||
see the
|
||||
.Ic lock-server
|
||||
command.
|
||||
.It Xo Ic lock-session
|
||||
.Op Fl t Ar target-session
|
||||
.Xc
|
||||
.It Ic lock-session Op Fl t Ar target-session
|
||||
.D1 (alias: Ic locks )
|
||||
Lock all clients attached to
|
||||
.Ar target-session .
|
||||
.It Xo Ic new-session
|
||||
@@ -583,14 +674,8 @@ A
|
||||
.Nm
|
||||
window may be in one of several modes.
|
||||
The default permits direct access to the terminal attached to the window.
|
||||
The others are:
|
||||
.Bl -tag -width Ds
|
||||
.It Em output mode
|
||||
This is entered when a command which produces output, such as
|
||||
.Ic list-keys ,
|
||||
is executed from a key binding.
|
||||
.It Em copy mode
|
||||
This permits a section of a window or its history to be copied to a
|
||||
The other is copy mode, which permits a section of a window or its
|
||||
history to be copied to a
|
||||
.Em paste buffer
|
||||
for later insertion into another window.
|
||||
This mode is entered with the
|
||||
@@ -598,14 +683,16 @@ This mode is entered with the
|
||||
command, bound to
|
||||
.Ql \&[
|
||||
by default.
|
||||
.El
|
||||
It is also entered when a command that produces output, such as
|
||||
.Ic list-keys ,
|
||||
is executed from a key binding.
|
||||
.Pp
|
||||
The keys available depend on whether emacs or vi mode is selected
|
||||
(see the
|
||||
.Ic mode-keys
|
||||
option).
|
||||
The following keys are supported as appropriate for the mode:
|
||||
.Bl -column "FunctionXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent
|
||||
.Bl -column "FunctionXXXXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent
|
||||
.It Sy "Function" Ta Sy "vi" Ta Sy "emacs"
|
||||
.It Li "Back to indentation" Ta "^" Ta "M-m"
|
||||
.It Li "Bottom of history" Ta "G" Ta "M-<"
|
||||
@@ -624,6 +711,10 @@ The following keys are supported as appropriate for the mode:
|
||||
.It Li "Go to line" Ta ":" Ta "g"
|
||||
.It Li "Half page down" Ta "C-d" Ta "M-Down"
|
||||
.It Li "Half page up" Ta "C-u" Ta "M-Up"
|
||||
.It Li "Jump forward" Ta "f" Ta "f"
|
||||
.It Li "Jump backward" Ta "F" Ta "F"
|
||||
.It Li "Jump again" Ta ";" Ta ";"
|
||||
.It Li "Jump again in reverse" Ta "," Ta ","
|
||||
.It Li "Next page" Ta "C-f" Ta "Page down"
|
||||
.It Li "Next space" Ta "W" Ta ""
|
||||
.It Li "Next space, end of word" Ta "E" Ta ""
|
||||
@@ -661,6 +752,18 @@ next word and previous word to the start of the previous word.
|
||||
The three next and previous space keys work similarly but use a space alone as
|
||||
the word separator.
|
||||
.Pp
|
||||
The jump commands enable quick movement within a line.
|
||||
For instance, typing
|
||||
.Ql f
|
||||
followed by
|
||||
.Ql /
|
||||
will move the cursor to the next
|
||||
.Ql /
|
||||
character on the current line.
|
||||
A
|
||||
.Ql \&;
|
||||
will then jump to the next occurrence.
|
||||
.Pp
|
||||
Commands in copy mode may be prefaced by an optional repeat count.
|
||||
With vi key bindings, a prefix is entered using the number keys; with
|
||||
emacs, the Alt (meta) key and a number begins prefix entry.
|
||||
@@ -680,7 +783,7 @@ and
|
||||
.Em emacs-choice
|
||||
for keys used when choosing from lists (such as produced by the
|
||||
.Ic choose-window
|
||||
command) or in output mode; and
|
||||
command); and
|
||||
.Em vi-copy
|
||||
and
|
||||
.Em emacs-copy
|
||||
@@ -695,7 +798,9 @@ and
|
||||
The paste buffer key pastes the first line from the top paste buffer on the
|
||||
stack.
|
||||
.Pp
|
||||
The mode commands are as follows:
|
||||
The synopsis for the
|
||||
.Ic copy-mode
|
||||
command is:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic copy-mode
|
||||
.Op Fl u
|
||||
@@ -727,10 +832,8 @@ command (bound to
|
||||
and
|
||||
.Ql C-right
|
||||
by default), the current pane may be changed with the
|
||||
.Ic up-pane
|
||||
and
|
||||
.Ic down-pane
|
||||
commands and the
|
||||
.Ic select-pane
|
||||
command and the
|
||||
.Ic rotate-window
|
||||
and
|
||||
.Ic swap-pane
|
||||
@@ -769,8 +872,29 @@ bottom along the right.
|
||||
See the
|
||||
.Em main-pane-width
|
||||
window option.
|
||||
.It Ic tiled
|
||||
Panes are spread out as evenly as possible over the window in both rows and
|
||||
columns.
|
||||
.El
|
||||
.Pp
|
||||
In addition,
|
||||
.Ic select-layout
|
||||
may be used to apply a previously used layout - the
|
||||
.Ic list-windows
|
||||
command displays the layout of each window in a form suitable for use with
|
||||
.Ic select-layout .
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ tmux list-windows
|
||||
0: ksh [159x48]
|
||||
layout: bb62,159x48,0,0{79x48,0,0,79x48,80,0}
|
||||
$ tmux select-layout bb62,159x48,0,0{79x48,0,0,79x48,80,0}
|
||||
.Ed
|
||||
.Nm
|
||||
automatically adjusts the size of the layout for the current window size.
|
||||
Note that a layout cannot be applied to a window with more panes than that
|
||||
from which the layout was originally defined.
|
||||
.Pp
|
||||
Commands related to windows and panes are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic break-pane
|
||||
@@ -859,9 +983,6 @@ While the indicator is on screen, a pane may be selected with the
|
||||
to
|
||||
.Ql 9
|
||||
keys.
|
||||
.It Ic down-pane Op Fl t Ar target-pane
|
||||
.D1 (alias: Ic downp )
|
||||
Change the active pane to the next pane (higher index).
|
||||
.It Xo Ic find-window
|
||||
.Op Fl t Ar target-window
|
||||
.Ar match-string
|
||||
@@ -948,7 +1069,7 @@ List the panes in the current window or in
|
||||
List windows in the current session or in
|
||||
.Ar target-session .
|
||||
.It Xo Ic move-window
|
||||
.Op Fl d
|
||||
.Op Fl dk
|
||||
.Op Fl s Ar src-window
|
||||
.Op Fl t Ar dst-window
|
||||
.Xc
|
||||
@@ -960,13 +1081,22 @@ except the window at
|
||||
is moved to
|
||||
.Ar dst-window .
|
||||
.It Xo Ic new-window
|
||||
.Op Fl dk
|
||||
.Op Fl adk
|
||||
.Op Fl n Ar window-name
|
||||
.Op Fl t Ar target-window
|
||||
.Op Ar shell-command
|
||||
.Xc
|
||||
.D1 (alias: Ic neww )
|
||||
Create a new window.
|
||||
With
|
||||
.Fl a ,
|
||||
the new window is inserted at the next index up from the specified
|
||||
.Ar target-window ,
|
||||
moving windows up if necessary,
|
||||
otherwise
|
||||
.Ar target-window
|
||||
is the new window location.
|
||||
.Pp
|
||||
If
|
||||
.Fl d
|
||||
is given, the session does not make the new window the current window.
|
||||
@@ -1024,6 +1154,11 @@ A pane may only be piped to one command at a time, any existing pipe is
|
||||
closed before
|
||||
.Ar shell-command
|
||||
is executed.
|
||||
The
|
||||
.Ar shell-command
|
||||
string may contain the special character sequences supported by the
|
||||
.Ic status-left
|
||||
command.
|
||||
If no
|
||||
.Ar shell-command
|
||||
is given, the current pipe (if any) is closed.
|
||||
@@ -1033,8 +1168,13 @@ The
|
||||
option only opens a new pipe if no previous pipe exists, allowing a pipe to
|
||||
be toggled with a single key, for example:
|
||||
.Bd -literal -offset indent
|
||||
bind-key C-p pipe-pane -o 'cat >>~/output'
|
||||
bind-key C-p pipe-pane -o 'cat >>~/output.#I-#P'
|
||||
.Ed
|
||||
.It Xo Ic previous-layout
|
||||
.Op Fl t Ar target-window
|
||||
.Xc
|
||||
.D1 (alias: Ic prevl )
|
||||
Move to the previous layout in the session.
|
||||
.It Xo Ic previous-window
|
||||
.Op Fl a
|
||||
.Op Fl t Ar target-session
|
||||
@@ -1098,17 +1238,28 @@ or downward (numerically higher).
|
||||
.Op Fl t Ar target-window
|
||||
.Op Ar layout-name
|
||||
.Xc
|
||||
.D1 (alias: selectl )
|
||||
.D1 (alias: Ic selectl )
|
||||
Choose a specific layout for a window.
|
||||
If
|
||||
.Ar layout-name
|
||||
is not given, the last layout used (if any) is reapplied.
|
||||
.It Ic select-pane Op Fl t Ar target-pane
|
||||
is not given, the last preset layout used (if any) is reapplied.
|
||||
.It Xo Ic select-pane
|
||||
.Op Fl DLRU
|
||||
.Op Fl t Ar target-pane
|
||||
.Xc
|
||||
.D1 (alias: Ic selectp )
|
||||
Make pane
|
||||
.Ar target-pane
|
||||
the active pane in window
|
||||
.Ar target-window .
|
||||
If one of
|
||||
.Fl D ,
|
||||
.Fl L ,
|
||||
.Fl R ,
|
||||
or
|
||||
.Fl U
|
||||
is used, respectively the pane below, to the left, to the right, or above the
|
||||
target pane is used.
|
||||
.It Ic select-window Op Fl t Ar target-window
|
||||
.D1 (alias: Ic selectw )
|
||||
Select the window at
|
||||
@@ -1121,7 +1272,7 @@ Select the window at
|
||||
.Op Fl t Ar target-pane
|
||||
.Op Ar shell-command
|
||||
.Xc
|
||||
.D1 (alias: splitw )
|
||||
.D1 (alias: Ic splitw )
|
||||
Create a new pane by splitting
|
||||
.Ar target-pane :
|
||||
.Fl h
|
||||
@@ -1184,9 +1335,6 @@ if
|
||||
.Fl k
|
||||
is specified and the window is linked to only one session, it is unlinked and
|
||||
destroyed.
|
||||
.It Ic up-pane Op Fl t Ar target-pane
|
||||
.D1 (alias: Ic upp )
|
||||
Change the active pane to the previous pane (lower index).
|
||||
.El
|
||||
.Sh KEY BINDINGS
|
||||
.Nm
|
||||
@@ -1233,7 +1381,7 @@ or
|
||||
keys, quotation marks are necessary, for example:
|
||||
.Bd -literal -offset indent
|
||||
bind-key '"' split-window
|
||||
bind-key "'" select-prompt
|
||||
bind-key "'" new-window
|
||||
.Ed
|
||||
.Pp
|
||||
Commands related to key bindings are as follows:
|
||||
@@ -1427,6 +1575,11 @@ Available window options are listed under
|
||||
.Pp
|
||||
Available server options are:
|
||||
.Bl -tag -width Ds
|
||||
.It Ic detach-on-destroy
|
||||
If on (the default), the client is detached when the session it is attached to
|
||||
is destroyed.
|
||||
If off, the client is switched to the most recently active of the remaining
|
||||
sessions.
|
||||
.It Ic escape-time
|
||||
Set the time in milliseconds for which
|
||||
.Nm
|
||||
@@ -1491,7 +1644,8 @@ is used as a login shell.
|
||||
.It Ic default-path Ar path
|
||||
Set the default working directory for processes created from keys, or
|
||||
interactively from the prompt.
|
||||
The default is the current working directory when the server is started.
|
||||
The default is empty, which means to use the working directory of the shell
|
||||
from which the server was started if it is available or the user's home if not.
|
||||
.It Ic default-terminal Ar terminal
|
||||
Set the default terminal for new windows created in this session - the
|
||||
default value of the
|
||||
@@ -1557,7 +1711,7 @@ This has no effect as a session option; it must be set as a global option.
|
||||
Set status line message attributes, where
|
||||
.Ar attributes
|
||||
is either
|
||||
.Ic default
|
||||
.Ic none
|
||||
or a comma-delimited list of one or more of:
|
||||
.Ic bright
|
||||
(or
|
||||
@@ -1712,6 +1866,19 @@ the
|
||||
.Ic status-interval
|
||||
option: if the status line is redrawn in the meantime, the previous result is
|
||||
used.
|
||||
Shell commands are executed with the
|
||||
.Nm
|
||||
global environment set (see the
|
||||
.Sx ENVIRONMENT
|
||||
section).
|
||||
.Pp
|
||||
The window title (#T) is the title set by the program running within the window
|
||||
using the OSC title setting sequence, for example:
|
||||
.Bd -literal -offset indent
|
||||
$ printf '\e033]2;My Title\e033\e\e'
|
||||
.Ed
|
||||
.Pp
|
||||
When a window is first created, its title is the hostname.
|
||||
.Pp
|
||||
#[attributes] allows a comma-separated list of attributes to be specified,
|
||||
these may be
|
||||
@@ -1957,10 +2124,8 @@ Key bindings default to emacs.
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
Mouse state in modes.
|
||||
If on,
|
||||
.Nm
|
||||
will respond to mouse clicks by moving the cursor in copy mode or selecting an
|
||||
option in choice mode.
|
||||
If on, the mouse may be used to copy a selection by dragging in copy mode, or
|
||||
to select an option in choice mode.
|
||||
.Pp
|
||||
.It Xo Ic monitor-activity
|
||||
.Op Ic on | off
|
||||
@@ -1988,8 +2153,8 @@ command.
|
||||
.It Xo Ic synchronize-panes
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
Duplicate input to any pane to all other panes in the same window, except
|
||||
for panes that are not in output mode.
|
||||
Duplicate input to any pane to all other panes in the same window (only
|
||||
for panes that are not in any special mode).
|
||||
.Pp
|
||||
.It Xo Ic alternate-screen
|
||||
.Op Ic on | off
|
||||
@@ -2028,6 +2193,16 @@ option for details of special character sequences available.
|
||||
The default is
|
||||
.Ql #I:#W#F .
|
||||
.Pp
|
||||
.It Ic window-status-alert-attr Ar attributes
|
||||
Set status line attributes for windows which have an alert (bell, activity
|
||||
or content).
|
||||
.Pp
|
||||
.It Ic window-status-alert-bg Ar colour
|
||||
Set status line background colour for windows with an alert.
|
||||
.Pp
|
||||
.It Ic window-status-alert-fg Ar colour
|
||||
Set status line foreground colour for windows with an alert.
|
||||
.Pp
|
||||
.It Ic window-status-current-attr Ar attributes
|
||||
Set status line attributes for the currently active window.
|
||||
.Pp
|
||||
@@ -2271,10 +2446,6 @@ The format of
|
||||
is as for
|
||||
.Ic status-left ,
|
||||
with the exception that #() are not handled.
|
||||
.It Ic select-prompt Op Fl t Ar target-client
|
||||
Open a prompt inside
|
||||
.Ar target-client
|
||||
allowing a window index to be entered interactively.
|
||||
.El
|
||||
.Sh BUFFERS
|
||||
.Nm
|
||||
@@ -2302,6 +2473,23 @@ command above).
|
||||
.Pp
|
||||
The buffer commands are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo
|
||||
.Ic choose-buffer
|
||||
.Op Fl t Ar target-window
|
||||
.Op Ar template
|
||||
.Xc
|
||||
Put a window into buffer choice mode, where a buffer may be chosen
|
||||
interactively from a list.
|
||||
After a buffer is selected,
|
||||
.Ql %%
|
||||
is replaced by the buffer index in
|
||||
.Ar template
|
||||
and the result executed as a command.
|
||||
If
|
||||
.Ar template
|
||||
is not given, "paste-buffer -b '%%'" is used.
|
||||
This command works only from inside
|
||||
.Nm .
|
||||
.It Ic clear-history Op Fl t Ar target-pane
|
||||
.D1 (alias: Ic clearhist )
|
||||
Remove and free the history for the specified pane.
|
||||
@@ -2336,18 +2524,23 @@ Load the contents of the specified paste buffer from
|
||||
.It Xo Ic paste-buffer
|
||||
.Op Fl dr
|
||||
.Op Fl b Ar buffer-index
|
||||
.Op Fl t Ar target-window
|
||||
.Op Fl s Ar separator
|
||||
.Op Fl t Ar target-pane
|
||||
.Xc
|
||||
.D1 (alias: Ic pasteb )
|
||||
Insert the contents of a paste buffer into the current window.
|
||||
Insert the contents of a paste buffer into the specified pane.
|
||||
If not specified, paste into the current one.
|
||||
With
|
||||
.Fl d ,
|
||||
also delete the paste buffer from the stack.
|
||||
When output, any linefeed (LF) characters in the paste buffer are replaced with
|
||||
carriage returns (CR).
|
||||
This translation may be disabled with the
|
||||
.Fl r
|
||||
a separator, by default carriage return (CR).
|
||||
A custom separator may be specified using the
|
||||
.Fl s
|
||||
flag.
|
||||
The
|
||||
.Fl r
|
||||
flag means to do no replacement (equivalent to a separator of LF).
|
||||
.It Xo Ic save-buffer
|
||||
.Op Fl a
|
||||
.Op Fl b Ar buffer-index
|
||||
@@ -2398,7 +2591,7 @@ option.
|
||||
Execute
|
||||
.Ar shell-command
|
||||
in the background without creating a window.
|
||||
After it finishes, any output to stdout is displayed in output mode.
|
||||
After it finishes, any output to stdout is displayed in copy mode.
|
||||
If the command doesn't return success, the exit status is also displayed.
|
||||
.It Ic server-info
|
||||
.D1 (alias: Ic info )
|
||||
|
||||
128
tmux.c
128
tmux.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: tmux.c,v 1.204 2010-02-26 13:31:39 tcunha Exp $ */
|
||||
/* $Id: tmux.c,v 1.214 2010-07-17 14:36:41 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <event.h>
|
||||
@@ -40,6 +41,8 @@ struct options global_s_options; /* session options */
|
||||
struct options global_w_options; /* window options */
|
||||
struct environ global_environ;
|
||||
|
||||
struct event_base *ev_base;
|
||||
|
||||
int debug_level;
|
||||
time_t start_time;
|
||||
char *socket_path;
|
||||
@@ -57,11 +60,7 @@ char *makesockpath(const char *);
|
||||
__dead void shell_exec(const char *, const char *);
|
||||
|
||||
struct imsgbuf *main_ibuf;
|
||||
struct event main_ev_sigterm;
|
||||
int main_exitval;
|
||||
|
||||
void main_set_signals(void);
|
||||
void main_clear_signals(void);
|
||||
void main_signal(int, short, unused void *);
|
||||
void main_callback(int, short, void *);
|
||||
void main_dispatch(const char *);
|
||||
@@ -242,7 +241,7 @@ main(int argc, char **argv)
|
||||
struct env_data envdata;
|
||||
struct msg_command_data cmddata;
|
||||
char *s, *shellcmd, *path, *label, *home, *cause;
|
||||
char cwd[MAXPATHLEN], **var;
|
||||
char **var;
|
||||
void *buf;
|
||||
size_t len;
|
||||
int opt, flags, quiet = 0, cmdflags = 0;
|
||||
@@ -342,10 +341,12 @@ main(int argc, char **argv)
|
||||
options_set_number(so, "bell-action", BELL_ANY);
|
||||
options_set_number(so, "buffer-limit", 9);
|
||||
options_set_string(so, "default-command", "%s", "");
|
||||
options_set_string(so, "default-path", "%s", "");
|
||||
options_set_string(so, "default-shell", "%s", getshell());
|
||||
options_set_string(so, "default-terminal", "screen");
|
||||
options_set_number(so, "display-panes-colour", 4);
|
||||
options_set_number(so, "detach-on-destroy", 1);
|
||||
options_set_number(so, "display-panes-active-colour", 1);
|
||||
options_set_number(so, "display-panes-colour", 4);
|
||||
options_set_number(so, "display-panes-time", 1000);
|
||||
options_set_number(so, "display-time", 750);
|
||||
options_set_number(so, "history-limit", 2000);
|
||||
@@ -357,8 +358,8 @@ main(int argc, char **argv)
|
||||
options_set_number(so, "message-fg", 0);
|
||||
options_set_number(so, "message-limit", 20);
|
||||
options_set_number(so, "mouse-select-pane", 0);
|
||||
options_set_number(so, "pane-active-border-bg", 2);
|
||||
options_set_number(so, "pane-active-border-fg", 8);
|
||||
options_set_number(so, "pane-active-border-bg", 8);
|
||||
options_set_number(so, "pane-active-border-fg", 2);
|
||||
options_set_number(so, "pane-border-bg", 8);
|
||||
options_set_number(so, "pane-border-fg", 8);
|
||||
options_set_number(so, "repeat-time", 500);
|
||||
@@ -419,6 +420,9 @@ main(int argc, char **argv)
|
||||
options_set_number(wo, "window-status-current-bg", 8);
|
||||
options_set_number(wo, "window-status-current-fg", 8);
|
||||
options_set_number(wo, "window-status-fg", 8);
|
||||
options_set_number(wo, "window-status-alert-attr", GRID_ATTR_REVERSE);
|
||||
options_set_number(wo, "window-status-alert-bg", 8);
|
||||
options_set_number(wo, "window-status-alert-fg", 8);
|
||||
options_set_string(wo, "window-status-format", "#I:#W#F");
|
||||
options_set_string(wo, "window-status-current-format", "#I:#W#F");
|
||||
options_set_string(wo, "word-separators", " -_@");
|
||||
@@ -434,15 +438,6 @@ main(int argc, char **argv)
|
||||
options_set_number(wo, "utf8", 0);
|
||||
}
|
||||
|
||||
if (getcwd(cwd, sizeof cwd) == NULL) {
|
||||
pw = getpwuid(getuid());
|
||||
if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
|
||||
strlcpy(cwd, pw->pw_dir, sizeof cwd);
|
||||
else
|
||||
strlcpy(cwd, "/", sizeof cwd);
|
||||
}
|
||||
options_set_string(so, "default-path", "%s", cwd);
|
||||
|
||||
if (cfg_file == NULL) {
|
||||
home = getenv("HOME");
|
||||
if (home == NULL || *home == '\0') {
|
||||
@@ -517,7 +512,7 @@ main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
cmdflags &= ~CMD_STARTSERVER;
|
||||
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
||||
if (cmd->entry->flags & CMD_STARTSERVER)
|
||||
cmdflags |= CMD_STARTSERVER;
|
||||
if (cmd->entry->flags & CMD_SENDENVIRON)
|
||||
@@ -540,10 +535,6 @@ main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((main_ibuf = client_init(path, cmdflags, flags)) == NULL)
|
||||
exit(1);
|
||||
xfree(path);
|
||||
|
||||
#ifdef HAVE_BROKEN_KQUEUE
|
||||
if (setenv("EVENT_NOKQUEUE", "1", 1) != 0)
|
||||
fatal("setenv failed");
|
||||
@@ -552,85 +543,46 @@ main(int argc, char **argv)
|
||||
if (setenv("EVENT_NOPOLL", "1", 1) != 0)
|
||||
fatal("setenv failed");
|
||||
#endif
|
||||
event_init();
|
||||
ev_base = event_init();
|
||||
#ifdef HAVE_BROKEN_KQUEUE
|
||||
unsetenv("EVENT_NOKQUEUE");
|
||||
#endif
|
||||
#ifdef HAVE_BROKEN_POLL
|
||||
unsetenv("EVENT_NOPOLL");
|
||||
#endif
|
||||
set_signals(main_signal);
|
||||
|
||||
/* Initialise the client socket/start the server. */
|
||||
if ((main_ibuf = client_init(path, cmdflags, flags)) == NULL)
|
||||
exit(1);
|
||||
xfree(path);
|
||||
|
||||
imsg_compose(main_ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len);
|
||||
|
||||
main_set_signals();
|
||||
|
||||
events = EV_READ;
|
||||
if (main_ibuf->w.queued > 0)
|
||||
events |= EV_WRITE;
|
||||
event_once(main_ibuf->fd, events, main_callback, shellcmd, NULL);
|
||||
|
||||
main_exitval = 0;
|
||||
event_dispatch();
|
||||
|
||||
main_clear_signals();
|
||||
clear_signals();
|
||||
|
||||
client_main(); /* doesn't return */
|
||||
}
|
||||
|
||||
void
|
||||
main_set_signals(void)
|
||||
{
|
||||
struct sigaction sigact;
|
||||
|
||||
memset(&sigact, 0, sizeof sigact);
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = SA_RESTART;
|
||||
sigact.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR1, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
|
||||
signal_set(&main_ev_sigterm, SIGTERM, main_signal, NULL);
|
||||
signal_add(&main_ev_sigterm, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
main_clear_signals(void)
|
||||
{
|
||||
struct sigaction sigact;
|
||||
|
||||
memset(&sigact, 0, sizeof sigact);
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_flags = SA_RESTART;
|
||||
sigact.sa_handler = SIG_DFL;
|
||||
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR1, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||
fatal("sigaction failed");
|
||||
|
||||
event_del(&main_ev_sigterm);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
main_signal(int sig, unused short events, unused void *data)
|
||||
{
|
||||
int status;
|
||||
|
||||
switch (sig) {
|
||||
case SIGTERM:
|
||||
exit(1);
|
||||
case SIGCHLD:
|
||||
waitpid(WAIT_ANY, &status, WNOHANG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,8 +611,8 @@ main_dispatch(const char *shellcmd)
|
||||
{
|
||||
struct imsg imsg;
|
||||
ssize_t n, datalen;
|
||||
struct msg_print_data printdata;
|
||||
struct msg_shell_data shelldata;
|
||||
struct msg_exit_data exitdata;
|
||||
|
||||
if ((n = imsg_read(main_ibuf)) == -1 || n == 0)
|
||||
fatalx("imsg_read failed");
|
||||
@@ -675,21 +627,13 @@ main_dispatch(const char *shellcmd)
|
||||
switch (imsg.hdr.type) {
|
||||
case MSG_EXIT:
|
||||
case MSG_SHUTDOWN:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_EXIT size");
|
||||
|
||||
exit(main_exitval);
|
||||
case MSG_ERROR:
|
||||
case MSG_PRINT:
|
||||
if (datalen != sizeof printdata)
|
||||
fatalx("bad MSG_PRINT size");
|
||||
memcpy(&printdata, imsg.data, sizeof printdata);
|
||||
printdata.msg[(sizeof printdata.msg) - 1] = '\0';
|
||||
|
||||
log_info("%s", printdata.msg);
|
||||
if (imsg.hdr.type == MSG_ERROR)
|
||||
main_exitval = 1;
|
||||
break;
|
||||
if (datalen != sizeof exitdata) {
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_EXIT size");
|
||||
exit(0);
|
||||
}
|
||||
memcpy(&exitdata, imsg.data, sizeof exitdata);
|
||||
exit(exitdata.retcode);
|
||||
case MSG_READY:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_READY size");
|
||||
@@ -709,7 +653,7 @@ main_dispatch(const char *shellcmd)
|
||||
memcpy(&shelldata, imsg.data, sizeof shelldata);
|
||||
shelldata.shell[(sizeof shelldata.shell) - 1] = '\0';
|
||||
|
||||
main_clear_signals();
|
||||
clear_signals();
|
||||
|
||||
shell_exec(shelldata.shell, shellcmd);
|
||||
default:
|
||||
|
||||
182
tmux.h
182
tmux.h
@@ -1,4 +1,4 @@
|
||||
/* $Id: tmux.h,v 1.547 2010-03-08 15:02:07 tcunha Exp $ */
|
||||
/* $Id: tmux.h,v 1.571 2010-07-17 14:38:13 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define PROTOCOL_VERSION 5
|
||||
#define PROTOCOL_VERSION 6
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
@@ -67,7 +67,6 @@ extern char **environ;
|
||||
*/
|
||||
#define COMMAND_LENGTH 2048 /* packed argv size */
|
||||
#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
|
||||
#define PRINT_LENGTH 512 /* printed error/message size */
|
||||
#define ENVIRON_LENGTH 1024 /* environment variable length */
|
||||
|
||||
/*
|
||||
@@ -110,6 +109,10 @@ extern char **environ;
|
||||
#define KEYC_SHIFT 0x8000
|
||||
#define KEYC_PREFIX 0x10000
|
||||
|
||||
/* Mask to obtain key w/o modifiers */
|
||||
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT|KEYC_PREFIX)
|
||||
#define KEYC_MASK_KEY (~KEYC_MASK_MOD)
|
||||
|
||||
/* Other key codes. */
|
||||
enum key_code {
|
||||
/* Mouse key. */
|
||||
@@ -368,7 +371,9 @@ enum msgtype {
|
||||
MSG_ENVIRON,
|
||||
MSG_UNLOCK,
|
||||
MSG_LOCK,
|
||||
MSG_SHELL
|
||||
MSG_SHELL,
|
||||
MSG_STDERR,
|
||||
MSG_STDOUT,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -376,10 +381,6 @@ enum msgtype {
|
||||
*
|
||||
* Don't forget to bump PROTOCOL_VERSION if any of these change!
|
||||
*/
|
||||
struct msg_print_data {
|
||||
char msg[PRINT_LENGTH];
|
||||
};
|
||||
|
||||
struct msg_command_data {
|
||||
pid_t pid; /* pid from $TMUX or -1 */
|
||||
u_int idx; /* index from $TMUX */
|
||||
@@ -411,6 +412,10 @@ struct msg_shell_data {
|
||||
char shell[MAXPATHLEN];
|
||||
};
|
||||
|
||||
struct msg_exit_data {
|
||||
int retcode;
|
||||
};
|
||||
|
||||
/* Mode key commands. */
|
||||
enum mode_key_cmd {
|
||||
MODEKEY_NONE,
|
||||
@@ -458,6 +463,10 @@ enum mode_key_cmd {
|
||||
MODEKEYCOPY_HALFPAGEUP,
|
||||
MODEKEYCOPY_HISTORYBOTTOM,
|
||||
MODEKEYCOPY_HISTORYTOP,
|
||||
MODEKEYCOPY_JUMP,
|
||||
MODEKEYCOPY_JUMPAGAIN,
|
||||
MODEKEYCOPY_JUMPREVERSE,
|
||||
MODEKEYCOPY_JUMPBACK,
|
||||
MODEKEYCOPY_LEFT,
|
||||
MODEKEYCOPY_MIDDLELINE,
|
||||
MODEKEYCOPY_NEXTPAGE,
|
||||
@@ -536,6 +545,8 @@ struct mode_key_table {
|
||||
#define MODE_KCURSOR 0x4
|
||||
#define MODE_KKEYPAD 0x8 /* set = application, clear = number */
|
||||
#define MODE_MOUSE 0x10
|
||||
#define MODE_MOUSEMOTION 0x20
|
||||
#define MODE_WRAP 0x40 /* whether lines wrap */
|
||||
|
||||
/*
|
||||
* A single UTF-8 character.
|
||||
@@ -718,59 +729,52 @@ struct screen_write_ctx {
|
||||
#define screen_hsize(s) ((s)->grid->hsize)
|
||||
#define screen_hlimit(s) ((s)->grid->hlimit)
|
||||
|
||||
/* Input parser sequence argument. */
|
||||
struct input_arg {
|
||||
u_char data[64];
|
||||
size_t used;
|
||||
};
|
||||
|
||||
/* Input parser context. */
|
||||
struct input_ctx {
|
||||
struct window_pane *wp;
|
||||
struct window_pane *wp;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
u_char *buf;
|
||||
size_t len;
|
||||
size_t off;
|
||||
size_t was;
|
||||
struct grid_cell cell;
|
||||
|
||||
struct grid_cell cell;
|
||||
struct grid_cell old_cell;
|
||||
u_int old_cx;
|
||||
u_int old_cy;
|
||||
|
||||
struct grid_cell saved_cell;
|
||||
u_int saved_cx;
|
||||
u_int saved_cy;
|
||||
u_char interm_buf[4];
|
||||
size_t interm_len;
|
||||
|
||||
#define MAXSTRINGLEN 1024
|
||||
u_char *string_buf;
|
||||
size_t string_len;
|
||||
int string_type;
|
||||
#define STRING_SYSTEM 0
|
||||
#define STRING_APPLICATION 1
|
||||
#define STRING_NAME 2
|
||||
u_char param_buf[64];
|
||||
size_t param_len;
|
||||
|
||||
struct utf8_data utf8data;
|
||||
u_char input_buf[256];
|
||||
size_t input_len;
|
||||
|
||||
u_char intermediate;
|
||||
void *(*state)(u_char, struct input_ctx *);
|
||||
int param_list[24]; /* -1 not present */
|
||||
u_int param_list_len;
|
||||
|
||||
u_char private;
|
||||
ARRAY_DECL(, struct input_arg) args;
|
||||
struct utf8_data utf8data;
|
||||
|
||||
int ch;
|
||||
int flags;
|
||||
#define INPUT_DISCARD 0x1
|
||||
|
||||
const struct input_state *state;
|
||||
};
|
||||
|
||||
/*
|
||||
* Window mode. Windows can be in several modes and this is used to call the
|
||||
* right function to handle input and output.
|
||||
*/
|
||||
struct client;
|
||||
struct session;
|
||||
struct window;
|
||||
struct mouse_event;
|
||||
struct window_mode {
|
||||
struct screen *(*init)(struct window_pane *);
|
||||
void (*free)(struct window_pane *);
|
||||
void (*resize)(struct window_pane *, u_int, u_int);
|
||||
void (*key)(struct window_pane *, struct client *, int);
|
||||
void (*key)(struct window_pane *, struct session *, int);
|
||||
void (*mouse)(struct window_pane *,
|
||||
struct client *, struct mouse_event *);
|
||||
struct session *, struct mouse_event *);
|
||||
void (*timer)(struct window_pane *);
|
||||
};
|
||||
|
||||
@@ -839,8 +843,7 @@ struct window {
|
||||
#define WINDOW_BELL 0x1
|
||||
#define WINDOW_HIDDEN 0x2
|
||||
#define WINDOW_ACTIVITY 0x4
|
||||
#define WINDOW_CONTENT 0x8
|
||||
#define WINDOW_REDRAW 0x10
|
||||
#define WINDOW_REDRAW 0x8
|
||||
|
||||
struct options options;
|
||||
|
||||
@@ -857,6 +860,12 @@ struct winlink {
|
||||
struct grid_cell status_cell;
|
||||
char *status_text;
|
||||
|
||||
int flags;
|
||||
#define WINLINK_BELL 0x1
|
||||
#define WINLINK_ACTIVITY 0x2
|
||||
#define WINLINK_CONTENT 0x4
|
||||
#define WINLINK_ALERTFLAGS (WINLINK_BELL|WINLINK_ACTIVITY|WINLINK_CONTENT)
|
||||
|
||||
RB_ENTRY(winlink) entry;
|
||||
TAILQ_ENTRY(winlink) sentry;
|
||||
};
|
||||
@@ -908,13 +917,6 @@ struct environ_entry {
|
||||
RB_HEAD(environ, environ_entry);
|
||||
|
||||
/* Client session. */
|
||||
struct session_alert {
|
||||
struct winlink *wl;
|
||||
int type;
|
||||
|
||||
SLIST_ENTRY(session_alert) entry;
|
||||
};
|
||||
|
||||
struct session_group {
|
||||
TAILQ_HEAD(, session) sessions;
|
||||
|
||||
@@ -924,6 +926,7 @@ TAILQ_HEAD(session_groups, session_group);
|
||||
|
||||
struct session {
|
||||
char *name;
|
||||
char *cwd;
|
||||
|
||||
struct timeval creation_time;
|
||||
struct timeval activity_time;
|
||||
@@ -939,8 +942,6 @@ struct session {
|
||||
|
||||
struct paste_stack buffers;
|
||||
|
||||
SLIST_HEAD(, session_alert) alerts;
|
||||
|
||||
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */
|
||||
#define SESSION_DEAD 0x2
|
||||
int flags;
|
||||
@@ -1052,9 +1053,23 @@ struct tty_ctx {
|
||||
u_int last_width;
|
||||
};
|
||||
|
||||
/*
|
||||
* xterm mouse mode is fairly silly. Buttons are in the bottom two
|
||||
* bits: 0 button 1; 1 button 2; 2 button 3; 3 buttons released.
|
||||
*
|
||||
* Bit 3 is shift; bit 4 is meta; bit 5 control.
|
||||
*
|
||||
* Bit 6 is added for mouse buttons 4 and 5.
|
||||
*/
|
||||
/* Mouse input. */
|
||||
struct mouse_event {
|
||||
u_char b;
|
||||
#define MOUSE_1 0
|
||||
#define MOUSE_2 1
|
||||
#define MOUSE_3 2
|
||||
#define MOUSE_UP 3
|
||||
#define MOUSE_BUTTON 3
|
||||
#define MOUSE_45 64
|
||||
u_char x;
|
||||
u_char y;
|
||||
};
|
||||
@@ -1069,6 +1084,7 @@ struct message_entry {
|
||||
struct client {
|
||||
struct imsgbuf ibuf;
|
||||
struct event event;
|
||||
int retcode;
|
||||
|
||||
struct timeval creation_time;
|
||||
struct timeval activity_time;
|
||||
@@ -1079,6 +1095,10 @@ struct client {
|
||||
char *cwd;
|
||||
|
||||
struct tty tty;
|
||||
FILE *stdin_file;
|
||||
FILE *stdout_file;
|
||||
FILE *stderr_file;
|
||||
|
||||
struct event repeat_timer;
|
||||
|
||||
struct timeval status_timer;
|
||||
@@ -1087,7 +1107,7 @@ struct client {
|
||||
|
||||
#define CLIENT_TERMINAL 0x1
|
||||
#define CLIENT_PREFIX 0x2
|
||||
#define CLIENT_MOUSE 0x4
|
||||
/* 0x4 unused */
|
||||
#define CLIENT_REDRAW 0x8
|
||||
#define CLIENT_STATUS 0x10
|
||||
#define CLIENT_REPEAT 0x20 /* allow command to repeat within repeat time */
|
||||
@@ -1161,7 +1181,10 @@ struct cmd {
|
||||
|
||||
TAILQ_ENTRY(cmd) qentry;
|
||||
};
|
||||
TAILQ_HEAD(cmd_list, cmd);
|
||||
struct cmd_list {
|
||||
int references;
|
||||
TAILQ_HEAD(, cmd) list;
|
||||
};
|
||||
|
||||
struct cmd_entry {
|
||||
const char *name;
|
||||
@@ -1254,6 +1277,7 @@ extern struct options global_options;
|
||||
extern struct options global_s_options;
|
||||
extern struct options global_w_options;
|
||||
extern struct environ global_environ;
|
||||
extern struct event_base *ev_base;
|
||||
extern char *cfg_file;
|
||||
extern int debug_level;
|
||||
extern int be_quiet;
|
||||
@@ -1332,6 +1356,7 @@ void environ_set(struct environ *, const char *, const char *);
|
||||
void environ_put(struct environ *, const char *);
|
||||
void environ_unset(struct environ *, const char *);
|
||||
void environ_update(const char *, struct environ *, struct environ *);
|
||||
void environ_push(struct environ *);
|
||||
|
||||
/* tty.c */
|
||||
void tty_raw(struct tty *, const char *);
|
||||
@@ -1349,7 +1374,7 @@ void tty_puts(struct tty *, const char *);
|
||||
void tty_putc(struct tty *, u_char);
|
||||
void tty_pututf8(struct tty *, const struct grid_utf8 *);
|
||||
void tty_init(struct tty *, int, char *);
|
||||
void tty_resize(struct tty *);
|
||||
int tty_resize(struct tty *);
|
||||
void tty_start_tty(struct tty *);
|
||||
void tty_stop_tty(struct tty *);
|
||||
void tty_set_title(struct tty *, const char *);
|
||||
@@ -1404,6 +1429,7 @@ int paste_free_top(struct paste_stack *);
|
||||
int paste_free_index(struct paste_stack *, u_int);
|
||||
void paste_add(struct paste_stack *, char *, size_t, u_int);
|
||||
int paste_replace(struct paste_stack *, u_int, char *, size_t);
|
||||
char *paste_print(struct paste_buffer *, size_t);
|
||||
|
||||
/* clock.c */
|
||||
extern const char clock_table[14][5][5];
|
||||
@@ -1440,6 +1466,7 @@ extern const struct cmd_entry cmd_attach_session_entry;
|
||||
extern const struct cmd_entry cmd_bind_key_entry;
|
||||
extern const struct cmd_entry cmd_break_pane_entry;
|
||||
extern const struct cmd_entry cmd_capture_pane_entry;
|
||||
extern const struct cmd_entry cmd_choose_buffer_entry;
|
||||
extern const struct cmd_entry cmd_choose_client_entry;
|
||||
extern const struct cmd_entry cmd_choose_session_entry;
|
||||
extern const struct cmd_entry cmd_choose_window_entry;
|
||||
@@ -1494,7 +1521,6 @@ extern const struct cmd_entry cmd_run_shell_entry;
|
||||
extern const struct cmd_entry cmd_save_buffer_entry;
|
||||
extern const struct cmd_entry cmd_select_layout_entry;
|
||||
extern const struct cmd_entry cmd_select_pane_entry;
|
||||
extern const struct cmd_entry cmd_select_prompt_entry;
|
||||
extern const struct cmd_entry cmd_select_window_entry;
|
||||
extern const struct cmd_entry cmd_send_keys_entry;
|
||||
extern const struct cmd_entry cmd_send_prefix_entry;
|
||||
@@ -1583,8 +1609,6 @@ const char *key_string_lookup_key(int);
|
||||
extern struct clients clients;
|
||||
extern struct clients dead_clients;
|
||||
int server_start(char *);
|
||||
void server_signal_set(void);
|
||||
void server_signal_clear(void);
|
||||
void server_update_socket(void);
|
||||
|
||||
/* server-client.c */
|
||||
@@ -1599,7 +1623,6 @@ void server_window_loop(void);
|
||||
|
||||
/* server-fn.c */
|
||||
void server_fill_environ(struct session *, struct environ *);
|
||||
void server_write_error(struct client *, const char *);
|
||||
void server_write_client(
|
||||
struct client *, enum msgtype, const void *, size_t);
|
||||
void server_write_session(
|
||||
@@ -1801,6 +1824,10 @@ struct winlink *winlink_add(struct winlinks *, struct window *, int);
|
||||
void winlink_remove(struct winlinks *, struct winlink *);
|
||||
struct winlink *winlink_next(struct winlink *);
|
||||
struct winlink *winlink_previous(struct winlink *);
|
||||
struct winlink *winlink_next_by_number(struct winlink *, struct session *,
|
||||
int);
|
||||
struct winlink *winlink_previous_by_number(struct winlink *, struct session *,
|
||||
int);
|
||||
void winlink_stack_push(struct winlink_stack *, struct winlink *);
|
||||
void winlink_stack_remove(struct winlink_stack *, struct winlink *);
|
||||
int window_index(struct window *, u_int *);
|
||||
@@ -1815,6 +1842,10 @@ struct window_pane *window_add_pane(struct window *, u_int);
|
||||
void window_resize(struct window *, u_int, u_int);
|
||||
void window_remove_pane(struct window *, struct window_pane *);
|
||||
struct window_pane *window_pane_at_index(struct window *, u_int);
|
||||
struct window_pane *window_pane_next_by_number(struct window *,
|
||||
struct window_pane *, u_int);
|
||||
struct window_pane *window_pane_previous_by_number(struct window *,
|
||||
struct window_pane *, u_int);
|
||||
u_int window_pane_index(struct window *, struct window_pane *);
|
||||
u_int window_count_panes(struct window *);
|
||||
void window_destroy_panes(struct window *);
|
||||
@@ -1824,21 +1855,30 @@ int window_pane_spawn(struct window_pane *, const char *,
|
||||
const char *, const char *, struct environ *,
|
||||
struct termios *, char **);
|
||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||
void window_pane_alternate_on(
|
||||
struct window_pane *, struct grid_cell *);
|
||||
void window_pane_alternate_off(
|
||||
struct window_pane *, struct grid_cell *);
|
||||
int window_pane_set_mode(
|
||||
struct window_pane *, const struct window_mode *);
|
||||
void window_pane_reset_mode(struct window_pane *);
|
||||
void window_pane_parse(struct window_pane *);
|
||||
void window_pane_key(struct window_pane *, struct client *, int);
|
||||
void window_pane_key(struct window_pane *, struct session *, int);
|
||||
void window_pane_mouse(struct window_pane *,
|
||||
struct client *, struct mouse_event *);
|
||||
struct session *, struct mouse_event *);
|
||||
int window_pane_visible(struct window_pane *);
|
||||
char *window_pane_search(
|
||||
struct window_pane *, const char *, u_int *);
|
||||
struct window_pane *window_pane_find_up(struct window_pane *);
|
||||
struct window_pane *window_pane_find_down(struct window_pane *);
|
||||
struct window_pane *window_pane_find_left(struct window_pane *);
|
||||
struct window_pane *window_pane_find_right(struct window_pane *);
|
||||
|
||||
/* layout.c */
|
||||
u_int layout_count_cells(struct layout_cell *);
|
||||
struct layout_cell *layout_create_cell(struct layout_cell *);
|
||||
void layout_free_cell(struct layout_cell *);
|
||||
void layout_print_cell(struct layout_cell *, const char *, u_int);
|
||||
void layout_destroy_cell(struct layout_cell *, struct layout_cell **);
|
||||
void layout_set_size(
|
||||
struct layout_cell *, u_int, u_int, u_int, u_int);
|
||||
void layout_make_leaf(
|
||||
@@ -1859,6 +1899,10 @@ struct layout_cell *layout_split_pane(
|
||||
struct window_pane *, enum layout_type, int);
|
||||
void layout_close_pane(struct window_pane *);
|
||||
|
||||
/* layout-custom.c */
|
||||
char *layout_dump(struct window *);
|
||||
int layout_parse(struct window *, const char *);
|
||||
|
||||
/* layout-set.c */
|
||||
const char *layout_set_name(u_int);
|
||||
int layout_set_lookup(const char *);
|
||||
@@ -1869,19 +1913,19 @@ void layout_set_active_changed(struct window *);
|
||||
|
||||
/* layout-string.c */
|
||||
struct layout_cell *layout_find_string(struct window *, const char *);
|
||||
struct layout_cell *layout_find_bottomright(struct layout_cell *);
|
||||
|
||||
/* window-clock.c */
|
||||
extern const struct window_mode window_clock_mode;
|
||||
|
||||
/* window-copy.c */
|
||||
extern const struct window_mode window_copy_mode;
|
||||
void window_copy_init_from_pane(struct window_pane *);
|
||||
void window_copy_init_for_output(struct window_pane *);
|
||||
void window_copy_add(struct window_pane *, const char *, ...);
|
||||
void window_copy_vadd(struct window_pane *, const char *, va_list);
|
||||
void window_copy_pageup(struct window_pane *);
|
||||
|
||||
/* window-more.c */
|
||||
extern const struct window_mode window_more_mode;
|
||||
void window_more_add(struct window_pane *, const char *, ...);
|
||||
void window_more_vadd(struct window_pane *, const char *, va_list);
|
||||
|
||||
/* window-choose.c */
|
||||
extern const struct window_mode window_choose_mode;
|
||||
void window_choose_vadd(
|
||||
@@ -1895,14 +1939,14 @@ void window_choose_ready(struct window_pane *,
|
||||
void queue_window_name(struct window *);
|
||||
char *default_window_name(struct window *);
|
||||
|
||||
/* signal.c */
|
||||
void set_signals(void(*handler)(int, short, unused void *));
|
||||
void clear_signals(void);
|
||||
|
||||
/* session.c */
|
||||
extern struct sessions sessions;
|
||||
extern struct sessions dead_sessions;
|
||||
extern struct session_groups session_groups;
|
||||
void session_alert_add(struct session *, struct window *, int);
|
||||
void session_alert_cancel(struct session *, struct winlink *);
|
||||
int session_alert_has(struct session *, struct winlink *, int);
|
||||
int session_alert_has_window(struct session *, struct window *, int);
|
||||
struct session *session_find(const char *);
|
||||
struct session *session_create(const char *, const char *, const char *,
|
||||
struct environ *, struct termios *, int, u_int, u_int,
|
||||
@@ -1914,7 +1958,7 @@ struct winlink *session_new(struct session *,
|
||||
struct winlink *session_attach(
|
||||
struct session *, struct window *, int, char **);
|
||||
int session_detach(struct session *, struct winlink *);
|
||||
int session_has(struct session *, struct window *);
|
||||
struct winlink* session_has(struct session *, struct window *);
|
||||
int session_next(struct session *, int);
|
||||
int session_previous(struct session *, int);
|
||||
int session_select(struct session *, int);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# $Id: dist.mk,v 1.8 2010-03-10 15:16:19 tcunha Exp $
|
||||
# $Id: dist.mk,v 1.9 2010-07-18 13:36:52 tcunha Exp $
|
||||
|
||||
VERSION= 1.2
|
||||
VERSION= 1.3
|
||||
|
||||
DISTDIR= tmux-${VERSION}
|
||||
DISTFILES= *.[ch] Makefile GNUmakefile configure tmux.1 \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: tty-keys.c,v 1.55 2009-12-18 18:57:00 tcunha Exp $ */
|
||||
/* $Id: tty-keys.c,v 1.57 2010-06-06 00:23:44 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -408,7 +408,7 @@ tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
|
||||
(*size)++;
|
||||
|
||||
/* At the end of the string, return the current node. */
|
||||
if (len == 0)
|
||||
if (len == 0 || (tk->next == NULL && tk->key != KEYC_NONE))
|
||||
return (tk);
|
||||
|
||||
/* Move into the next tree for the following character. */
|
||||
@@ -612,7 +612,8 @@ tty_keys_mouse(const char *buf, size_t len, size_t *size, struct mouse_event *m)
|
||||
return (1);
|
||||
*size = 6;
|
||||
|
||||
log_debug("mouse input is: %.6s", buf);
|
||||
log_debug(
|
||||
"mouse input: %.6s (%hhu,%hhu/%hhu)", buf, buf[4], buf[5], buf[3]);
|
||||
|
||||
m->b = buf[3];
|
||||
m->x = buf[4];
|
||||
|
||||
60
tty.c
60
tty.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: tty.c,v 1.189 2010-03-08 14:53:49 tcunha Exp $ */
|
||||
/* $Id: tty.c,v 1.192 2010-06-06 00:30:34 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -73,34 +73,55 @@ tty_init(struct tty *tty, int fd, char *term)
|
||||
tty->term_flags = 0;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
tty_resize(struct tty *tty)
|
||||
{
|
||||
struct winsize ws;
|
||||
u_int sx, sy;
|
||||
|
||||
if (ioctl(tty->fd, TIOCGWINSZ, &ws) != -1) {
|
||||
tty->sx = ws.ws_col;
|
||||
tty->sy = ws.ws_row;
|
||||
sx = ws.ws_col;
|
||||
if (sx == 0)
|
||||
sx = 80;
|
||||
sy = ws.ws_row;
|
||||
if (sy == 0)
|
||||
sy = 24;
|
||||
} else {
|
||||
sx = 80;
|
||||
sy = 24;
|
||||
}
|
||||
if (tty->sx == 0)
|
||||
tty->sx = 80;
|
||||
if (tty->sy == 0)
|
||||
tty->sy = 24;
|
||||
if (sx == tty->sx && sy == tty->sy)
|
||||
return (0);
|
||||
tty->sx = sx;
|
||||
tty->sy = sy;
|
||||
|
||||
tty->cx = UINT_MAX;
|
||||
tty->cy = UINT_MAX;
|
||||
|
||||
tty->rupper = UINT_MAX;
|
||||
tty->rlower = UINT_MAX;
|
||||
|
||||
/*
|
||||
* If the terminal has been started, reset the actual scroll region and
|
||||
* cursor position, as this may not have happened.
|
||||
*/
|
||||
if (tty->flags & TTY_STARTED) {
|
||||
tty_cursor(tty, 0, 0);
|
||||
tty_region(tty, 0, tty->sy - 1);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
tty_open(struct tty *tty, const char *overrides, char **cause)
|
||||
{
|
||||
char out[64];
|
||||
int fd;
|
||||
|
||||
if (debug_level > 3) {
|
||||
fd = open("tmux.out", O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
xsnprintf(out, sizeof out, "tmux-out-%ld.log", (long) getpid());
|
||||
fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
if (fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||
fatal("fcntl failed");
|
||||
tty->log_fd = fd;
|
||||
@@ -402,11 +423,18 @@ tty_update_mode(struct tty *tty, int mode)
|
||||
else
|
||||
tty_putcode(tty, TTYC_CIVIS);
|
||||
}
|
||||
if (changed & MODE_MOUSE) {
|
||||
if (mode & MODE_MOUSE)
|
||||
tty_puts(tty, "\033[?1000h");
|
||||
else
|
||||
tty_puts(tty, "\033[?1000l");
|
||||
if (changed & (MODE_MOUSE|MODE_MOUSEMOTION)) {
|
||||
if (mode & MODE_MOUSE) {
|
||||
if (mode & MODE_MOUSEMOTION)
|
||||
tty_puts(tty, "\033[?1003h");
|
||||
else
|
||||
tty_puts(tty, "\033[?1000h");
|
||||
} else {
|
||||
if (mode & MODE_MOUSEMOTION)
|
||||
tty_puts(tty, "\033[?1003l");
|
||||
else
|
||||
tty_puts(tty, "\033[?1000l");
|
||||
}
|
||||
}
|
||||
if (changed & MODE_KKEYPAD) {
|
||||
if (mode & MODE_KKEYPAD)
|
||||
@@ -1083,7 +1111,7 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy)
|
||||
* Use HPA if change is larger than absolute, otherwise move
|
||||
* the cursor with CUB/CUF.
|
||||
*/
|
||||
if (abs(change) > cx && tty_term_has(term, TTYC_HPA)) {
|
||||
if ((u_int) abs(change) > cx && tty_term_has(term, TTYC_HPA)) {
|
||||
tty_putcode1(tty, TTYC_HPA, cx);
|
||||
goto out;
|
||||
} else if (change > 0 && tty_term_has(term, TTYC_CUB)) {
|
||||
@@ -1119,7 +1147,7 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy)
|
||||
* Try to use VPA if change is larger than absolute or if this
|
||||
* change would cross the scroll region, otherwise use CUU/CUD.
|
||||
*/
|
||||
if (abs(change) > cy ||
|
||||
if ((u_int) abs(change) > cy ||
|
||||
(change < 0 && cy - change > tty->rlower) ||
|
||||
(change > 0 && cy - change < tty->rupper)) {
|
||||
if (tty_term_has(term, TTYC_VPA)) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: window-choose.c,v 1.29 2010-02-02 23:55:21 tcunha Exp $ */
|
||||
/* $Id: window-choose.c,v 1.30 2010-05-22 21:56:04 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -25,9 +25,9 @@
|
||||
struct screen *window_choose_init(struct window_pane *);
|
||||
void window_choose_free(struct window_pane *);
|
||||
void window_choose_resize(struct window_pane *, u_int, u_int);
|
||||
void window_choose_key(struct window_pane *, struct client *, int);
|
||||
void window_choose_key(struct window_pane *, struct session *, int);
|
||||
void window_choose_mouse(
|
||||
struct window_pane *, struct client *, struct mouse_event *);
|
||||
struct window_pane *, struct session *, struct mouse_event *);
|
||||
|
||||
void window_choose_redraw_screen(struct window_pane *);
|
||||
void window_choose_write_line(
|
||||
@@ -171,7 +171,7 @@ window_choose_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
window_choose_key(struct window_pane *wp, unused struct client *c, int key)
|
||||
window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
|
||||
{
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
@@ -304,7 +304,7 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key)
|
||||
/* ARGSUSED */
|
||||
void
|
||||
window_choose_mouse(
|
||||
struct window_pane *wp, unused struct client *c, struct mouse_event *m)
|
||||
struct window_pane *wp, unused struct session *sess, struct mouse_event *m)
|
||||
{
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: window-clock.c,v 1.11 2009-12-04 22:14:47 tcunha Exp $ */
|
||||
/* $Id: window-clock.c,v 1.12 2010-05-22 21:56:04 micahcowan Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -26,7 +26,7 @@
|
||||
struct screen *window_clock_init(struct window_pane *);
|
||||
void window_clock_free(struct window_pane *);
|
||||
void window_clock_resize(struct window_pane *, u_int, u_int);
|
||||
void window_clock_key(struct window_pane *, struct client *, int);
|
||||
void window_clock_key(struct window_pane *, struct session *, int);
|
||||
void window_clock_timer(struct window_pane *);
|
||||
|
||||
void window_clock_draw_screen(struct window_pane *);
|
||||
@@ -85,7 +85,7 @@ window_clock_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
/* ARGSUSED */
|
||||
void
|
||||
window_clock_key(
|
||||
struct window_pane *wp, unused struct client *c, unused int key)
|
||||
struct window_pane *wp, unused struct session *sess, unused int key)
|
||||
{
|
||||
window_pane_reset_mode(wp);
|
||||
}
|
||||
|
||||
449
window-copy.c
449
window-copy.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: window-copy.c,v 1.109 2010-03-08 15:02:07 tcunha Exp $ */
|
||||
/* $Id: window-copy.c,v 1.121 2010-07-02 02:56:07 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -26,11 +26,11 @@
|
||||
struct screen *window_copy_init(struct window_pane *);
|
||||
void window_copy_free(struct window_pane *);
|
||||
void window_copy_resize(struct window_pane *, u_int, u_int);
|
||||
void window_copy_key(struct window_pane *, struct client *, int);
|
||||
void window_copy_key(struct window_pane *, struct session *, int);
|
||||
int window_copy_key_input(struct window_pane *, int);
|
||||
int window_copy_key_numeric_prefix(struct window_pane *, int);
|
||||
void window_copy_mouse(
|
||||
struct window_pane *, struct client *, struct mouse_event *);
|
||||
struct window_pane *, struct session *, struct mouse_event *);
|
||||
|
||||
void window_copy_redraw_lines(struct window_pane *, u_int, u_int);
|
||||
void window_copy_redraw_screen(struct window_pane *);
|
||||
@@ -52,7 +52,7 @@ void window_copy_goto_line(struct window_pane *, const char *);
|
||||
void window_copy_update_cursor(struct window_pane *, u_int, u_int);
|
||||
void window_copy_start_selection(struct window_pane *);
|
||||
int window_copy_update_selection(struct window_pane *);
|
||||
void window_copy_copy_selection(struct window_pane *, struct client *);
|
||||
void window_copy_copy_selection(struct window_pane *, struct session *);
|
||||
void window_copy_clear_selection(struct window_pane *);
|
||||
void window_copy_copy_line(
|
||||
struct window_pane *, char **, size_t *, u_int, u_int, u_int);
|
||||
@@ -65,6 +65,8 @@ void window_copy_cursor_left(struct window_pane *);
|
||||
void window_copy_cursor_right(struct window_pane *);
|
||||
void window_copy_cursor_up(struct window_pane *, int);
|
||||
void window_copy_cursor_down(struct window_pane *, int);
|
||||
void window_copy_cursor_jump(struct window_pane *);
|
||||
void window_copy_cursor_jump_back(struct window_pane *);
|
||||
void window_copy_cursor_next_word(struct window_pane *, const char *);
|
||||
void window_copy_cursor_next_word_end(struct window_pane *, const char *);
|
||||
void window_copy_cursor_previous_word(struct window_pane *, const char *);
|
||||
@@ -86,12 +88,33 @@ enum window_copy_input_type {
|
||||
WINDOW_COPY_NUMERICPREFIX,
|
||||
WINDOW_COPY_SEARCHUP,
|
||||
WINDOW_COPY_SEARCHDOWN,
|
||||
WINDOW_COPY_JUMPFORWARD,
|
||||
WINDOW_COPY_JUMPBACK,
|
||||
WINDOW_COPY_GOTOLINE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Copy-mode's visible screen (the "screen" field) is filled from one of
|
||||
* two sources: the original contents of the pane (used when we
|
||||
* actually enter via the "copy-mode" command, to copy the contents of
|
||||
* the current pane), or else a series of lines containing the output
|
||||
* from an output-writing tmux command (such as any of the "show-*" or
|
||||
* "list-*" commands).
|
||||
*
|
||||
* In either case, the full content of the copy-mode grid is pointed at
|
||||
* by the "backing" field, and is copied into "screen" as needed (that
|
||||
* is, when scrolling occurs). When copy-mode is backed by a pane,
|
||||
* backing points directly at that pane's screen structure (&wp->base);
|
||||
* when backed by a list of output-lines from a command, it points at
|
||||
* a newly-allocated screen structure (which is deallocated when the
|
||||
* mode ends).
|
||||
*/
|
||||
struct window_copy_mode_data {
|
||||
struct screen screen;
|
||||
|
||||
struct screen *backing;
|
||||
int backing_written; /* backing display has started */
|
||||
|
||||
struct mode_key_data mdata;
|
||||
|
||||
u_int oy;
|
||||
@@ -115,6 +138,9 @@ struct window_copy_mode_data {
|
||||
|
||||
enum window_copy_input_type searchtype;
|
||||
char *searchstr;
|
||||
|
||||
enum window_copy_input_type jumptype;
|
||||
char jumpchar;
|
||||
};
|
||||
|
||||
struct screen *
|
||||
@@ -122,18 +148,18 @@ window_copy_init(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data;
|
||||
struct screen *s;
|
||||
struct screen_write_ctx ctx;
|
||||
u_int i;
|
||||
int keys;
|
||||
|
||||
wp->modedata = data = xmalloc(sizeof *data);
|
||||
data->oy = 0;
|
||||
data->cx = wp->base.cx;
|
||||
data->cy = wp->base.cy;
|
||||
data->cx = 0;
|
||||
data->cy = 0;
|
||||
|
||||
data->lastcx = 0;
|
||||
data->lastsx = 0;
|
||||
|
||||
data->backing_written = 0;
|
||||
|
||||
data->rectflag = 0;
|
||||
|
||||
data->inputtype = WINDOW_COPY_OFF;
|
||||
@@ -147,6 +173,9 @@ window_copy_init(struct window_pane *wp)
|
||||
wp->flags |= PANE_FREEZE;
|
||||
bufferevent_disable(wp->event, EV_READ|EV_WRITE);
|
||||
|
||||
data->jumptype = WINDOW_COPY_OFF;
|
||||
data->jumpchar = '\0';
|
||||
|
||||
s = &data->screen;
|
||||
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
|
||||
if (options_get_number(&wp->window->options, "mode-mouse"))
|
||||
@@ -158,6 +187,26 @@ window_copy_init(struct window_pane *wp)
|
||||
else
|
||||
mode_key_init(&data->mdata, &mode_key_tree_vi_copy);
|
||||
|
||||
data->backing = NULL;
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_init_from_pane(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
u_int i;
|
||||
|
||||
if (wp->mode != &window_copy_mode)
|
||||
fatalx("not in copy mode");
|
||||
|
||||
data->backing = &wp->base;
|
||||
data->cx = data->backing->cx;
|
||||
data->cy = data->backing->cy;
|
||||
|
||||
s->cx = data->cx;
|
||||
s->cy = data->cy;
|
||||
|
||||
@@ -166,8 +215,17 @@ window_copy_init(struct window_pane *wp)
|
||||
window_copy_write_line(wp, &ctx, i);
|
||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
return (s);
|
||||
void
|
||||
window_copy_init_for_output(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
|
||||
data->backing = xmalloc(sizeof *data->backing);
|
||||
screen_init(data->backing, screen_size_x(&wp->base),
|
||||
screen_size_y(&wp->base), UINT_MAX);
|
||||
data->backing->mode &= ~MODE_WRAP;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -182,11 +240,73 @@ window_copy_free(struct window_pane *wp)
|
||||
xfree(data->searchstr);
|
||||
xfree(data->inputstr);
|
||||
|
||||
if (data->backing != &wp->base) {
|
||||
screen_free(data->backing);
|
||||
xfree(data->backing);
|
||||
}
|
||||
screen_free(&data->screen);
|
||||
|
||||
xfree(data);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_add(struct window_pane *wp, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
window_copy_vadd(wp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *backing = data->backing;
|
||||
struct screen_write_ctx back_ctx, ctx;
|
||||
struct grid_cell gc;
|
||||
int utf8flag;
|
||||
u_int old_hsize;
|
||||
|
||||
if (backing == &wp->base)
|
||||
return;
|
||||
|
||||
utf8flag = options_get_number(&wp->window->options, "utf8");
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
|
||||
old_hsize = screen_hsize(data->backing);
|
||||
screen_write_start(&back_ctx, NULL, backing);
|
||||
if (data->backing_written) {
|
||||
/*
|
||||
* On the second or later line, do a CRLF before writing
|
||||
* (so it's on a new line).
|
||||
*/
|
||||
screen_write_carriagereturn(&back_ctx);
|
||||
screen_write_linefeed(&back_ctx, 0);
|
||||
} else
|
||||
data->backing_written = 1;
|
||||
screen_write_vnputs(&back_ctx, 0, &gc, utf8flag, fmt, ap);
|
||||
screen_write_stop(&back_ctx);
|
||||
|
||||
data->oy += screen_hsize(data->backing) - old_hsize;
|
||||
|
||||
screen_write_start(&ctx, wp, &data->screen);
|
||||
|
||||
/*
|
||||
* If the history has changed, draw the top line.
|
||||
* (If there's any history at all, it has changed.)
|
||||
*/
|
||||
if (screen_hsize(data->backing))
|
||||
window_copy_redraw_lines(wp, 0, 1);
|
||||
|
||||
/* Write the line, if it's visible. */
|
||||
if (backing->cy + data->oy < screen_size_y(backing))
|
||||
window_copy_redraw_lines(wp, backing->cy, 1);
|
||||
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_pageup(struct window_pane *wp)
|
||||
{
|
||||
@@ -197,8 +317,8 @@ window_copy_pageup(struct window_pane *wp)
|
||||
n = 1;
|
||||
if (screen_size_y(s) > 2)
|
||||
n = screen_size_y(s) - 2;
|
||||
if (data->oy + n > screen_hsize(&wp->base))
|
||||
data->oy = screen_hsize(&wp->base);
|
||||
if (data->oy + n > screen_hsize(data->backing))
|
||||
data->oy = screen_hsize(data->backing);
|
||||
else
|
||||
data->oy += n;
|
||||
window_copy_update_selection(wp);
|
||||
@@ -213,6 +333,8 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
screen_resize(s, sx, sy);
|
||||
if (data->backing != &wp->base)
|
||||
screen_resize(data->backing, sx, sy);
|
||||
|
||||
if (data->cy > sy - 1)
|
||||
data->cy = sy - 1;
|
||||
@@ -229,7 +351,7 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||
window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
||||
{
|
||||
const char *word_separators;
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
@@ -242,7 +364,24 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||
if (np == 0)
|
||||
np = 1;
|
||||
|
||||
if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) {
|
||||
if (data->inputtype == WINDOW_COPY_JUMPFORWARD
|
||||
|| data->inputtype == WINDOW_COPY_JUMPBACK) {
|
||||
/* Ignore keys with modifiers. */
|
||||
if ((key & KEYC_MASK_MOD) == 0) {
|
||||
data->jumpchar = key;
|
||||
if (data->inputtype == WINDOW_COPY_JUMPFORWARD) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_cursor_jump(wp);
|
||||
} else {
|
||||
for (; np != 0; np--)
|
||||
window_copy_cursor_jump_back(wp);
|
||||
}
|
||||
}
|
||||
data->jumptype = data->inputtype;
|
||||
data->inputtype = WINDOW_COPY_OFF;
|
||||
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
|
||||
return;
|
||||
} if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) {
|
||||
if (window_copy_key_numeric_prefix(wp, key) == 0)
|
||||
return;
|
||||
data->inputtype = WINDOW_COPY_OFF;
|
||||
@@ -256,9 +395,8 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||
cmd = mode_key_lookup(&data->mdata, key);
|
||||
switch (cmd) {
|
||||
case MODEKEYCOPY_CANCEL:
|
||||
for (; np != 0; np--)
|
||||
window_pane_reset_mode(wp);
|
||||
break;
|
||||
window_pane_reset_mode(wp);
|
||||
return;
|
||||
case MODEKEYCOPY_LEFT:
|
||||
for (; np != 0; np--)
|
||||
window_copy_cursor_left(wp);
|
||||
@@ -303,8 +441,8 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||
case MODEKEYCOPY_HALFPAGEUP:
|
||||
n = screen_size_y(s) / 2;
|
||||
for (; np != 0; np--) {
|
||||
if (data->oy + n > screen_hsize(&wp->base))
|
||||
data->oy = screen_hsize(&wp->base);
|
||||
if (data->oy + n > screen_hsize(data->backing))
|
||||
data->oy = screen_hsize(data->backing);
|
||||
else
|
||||
data->oy += n;
|
||||
}
|
||||
@@ -343,7 +481,7 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||
case MODEKEYCOPY_HISTORYTOP:
|
||||
data->cx = 0;
|
||||
data->cy = 0;
|
||||
data->oy = screen_hsize(&wp->base);
|
||||
data->oy = screen_hsize(data->backing);
|
||||
window_copy_update_selection(wp);
|
||||
window_copy_redraw_screen(wp);
|
||||
break;
|
||||
@@ -363,9 +501,10 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||
window_copy_redraw_screen(wp);
|
||||
break;
|
||||
case MODEKEYCOPY_COPYSELECTION:
|
||||
if (c != NULL && c->session != NULL) {
|
||||
window_copy_copy_selection(wp, c);
|
||||
if (sess != NULL) {
|
||||
window_copy_copy_selection(wp, sess);
|
||||
window_pane_reset_mode(wp);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MODEKEYCOPY_STARTOFLINE:
|
||||
@@ -407,6 +546,36 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||
for (; np != 0; np--)
|
||||
window_copy_cursor_previous_word(wp, word_separators);
|
||||
break;
|
||||
case MODEKEYCOPY_JUMP:
|
||||
data->inputtype = WINDOW_COPY_JUMPFORWARD;
|
||||
data->inputprompt = "Jump Forward";
|
||||
*data->inputstr = '\0';
|
||||
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
|
||||
return; /* skip numprefix reset */
|
||||
case MODEKEYCOPY_JUMPAGAIN:
|
||||
if (data->jumptype == WINDOW_COPY_JUMPFORWARD) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_cursor_jump(wp);
|
||||
} else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_cursor_jump_back(wp);
|
||||
}
|
||||
break;
|
||||
case MODEKEYCOPY_JUMPREVERSE:
|
||||
if (data->jumptype == WINDOW_COPY_JUMPFORWARD) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_cursor_jump_back(wp);
|
||||
} else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_cursor_jump(wp);
|
||||
}
|
||||
break;
|
||||
case MODEKEYCOPY_JUMPBACK:
|
||||
data->inputtype = WINDOW_COPY_JUMPBACK;
|
||||
data->inputprompt = "Jump Back";
|
||||
*data->inputstr = '\0';
|
||||
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
|
||||
return; /* skip numprefix reset */
|
||||
case MODEKEYCOPY_SEARCHUP:
|
||||
data->inputtype = WINDOW_COPY_SEARCHUP;
|
||||
data->inputprompt = "Search Up";
|
||||
@@ -420,6 +589,8 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||
switch (data->searchtype) {
|
||||
case WINDOW_COPY_OFF:
|
||||
case WINDOW_COPY_GOTOLINE:
|
||||
case WINDOW_COPY_JUMPFORWARD:
|
||||
case WINDOW_COPY_JUMPBACK:
|
||||
case WINDOW_COPY_NUMERICPREFIX:
|
||||
break;
|
||||
case WINDOW_COPY_SEARCHUP:
|
||||
@@ -456,7 +627,7 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||
*data->inputstr = '\0';
|
||||
goto input_on;
|
||||
case MODEKEYCOPY_STARTNUMBERPREFIX:
|
||||
key &= 0xff;
|
||||
key &= KEYC_MASK_KEY;
|
||||
if (key >= '0' && key <= '9') {
|
||||
data->inputtype = WINDOW_COPY_NUMERICPREFIX;
|
||||
data->numprefix = 0;
|
||||
@@ -524,6 +695,8 @@ window_copy_key_input(struct window_pane *wp, int key)
|
||||
|
||||
switch (data->inputtype) {
|
||||
case WINDOW_COPY_OFF:
|
||||
case WINDOW_COPY_JUMPFORWARD:
|
||||
case WINDOW_COPY_JUMPBACK:
|
||||
case WINDOW_COPY_NUMERICPREFIX:
|
||||
break;
|
||||
case WINDOW_COPY_SEARCHUP:
|
||||
@@ -568,7 +741,7 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
key &= 0xff;
|
||||
key &= KEYC_MASK_KEY;
|
||||
if (key < '0' || key > '9')
|
||||
return 1;
|
||||
|
||||
@@ -583,29 +756,63 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
|
||||
/* ARGSUSED */
|
||||
void
|
||||
window_copy_mouse(
|
||||
struct window_pane *wp, unused struct client *c, struct mouse_event *m)
|
||||
struct window_pane *wp, unused struct session *sess, struct mouse_event *m)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
u_int i;
|
||||
|
||||
if ((m->b & 3) == 3)
|
||||
return;
|
||||
if (m->x >= screen_size_x(s))
|
||||
return;
|
||||
if (m->y >= screen_size_y(s))
|
||||
return;
|
||||
|
||||
window_copy_update_cursor(wp, m->x, m->y);
|
||||
if (window_copy_update_selection(wp))
|
||||
/* If mouse wheel (buttons 4 and 5), scroll. */
|
||||
if ((m->b & MOUSE_45)) {
|
||||
if ((m->b & MOUSE_BUTTON) == MOUSE_1) {
|
||||
for (i = 0; i < 5; i++)
|
||||
window_copy_cursor_up(wp, 0);
|
||||
} else if ((m->b & MOUSE_BUTTON) == MOUSE_2) {
|
||||
for (i = 0; i < 5; i++)
|
||||
window_copy_cursor_down(wp, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If already reading motion, move the cursor while buttons are still
|
||||
* pressed, or stop the selection on their release.
|
||||
*/
|
||||
if (s->mode & MODE_MOUSEMOTION) {
|
||||
if ((m->b & MOUSE_BUTTON) != MOUSE_UP) {
|
||||
window_copy_update_cursor(wp, m->x, m->y);
|
||||
if (window_copy_update_selection(wp))
|
||||
window_copy_redraw_screen(wp);
|
||||
} else {
|
||||
s->mode &= ~MODE_MOUSEMOTION;
|
||||
if (sess != NULL) {
|
||||
window_copy_copy_selection(wp, sess);
|
||||
window_pane_reset_mode(wp);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise i other buttons pressed, start selection and motion. */
|
||||
if ((m->b & MOUSE_BUTTON) != MOUSE_UP) {
|
||||
s->mode |= MODE_MOUSEMOTION;
|
||||
|
||||
window_copy_update_cursor(wp, m->x, m->y);
|
||||
window_copy_start_selection(wp);
|
||||
window_copy_redraw_screen(wp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_scroll_to(struct window_pane *wp, u_int px, u_int py)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &wp->base;
|
||||
struct grid *gd = s->grid;
|
||||
struct grid *gd = data->backing->grid;
|
||||
u_int offset, gap;
|
||||
|
||||
data->cx = px;
|
||||
@@ -700,7 +907,7 @@ void
|
||||
window_copy_search_up(struct window_pane *wp, const char *searchstr)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &wp->base, ss;
|
||||
struct screen *s = data->backing, ss;
|
||||
struct screen_write_ctx ctx;
|
||||
struct grid *gd = s->grid, *sgd;
|
||||
struct grid_cell gc;
|
||||
@@ -757,7 +964,7 @@ void
|
||||
window_copy_search_down(struct window_pane *wp, const char *searchstr)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &wp->base, ss;
|
||||
struct screen *s = data->backing, ss;
|
||||
struct screen_write_ctx ctx;
|
||||
struct grid *gd = s->grid, *sgd;
|
||||
struct grid_cell gc;
|
||||
@@ -817,7 +1024,7 @@ window_copy_goto_line(struct window_pane *wp, const char *linestr)
|
||||
const char *errstr;
|
||||
u_int lineno;
|
||||
|
||||
lineno = strtonum(linestr, 0, screen_hsize(&wp->base), &errstr);
|
||||
lineno = strtonum(linestr, 0, screen_hsize(data->backing), &errstr);
|
||||
if (errstr != NULL)
|
||||
return;
|
||||
|
||||
@@ -845,7 +1052,7 @@ window_copy_write_line(
|
||||
last = screen_size_y(s) - 1;
|
||||
if (py == 0) {
|
||||
size = xsnprintf(hdr, sizeof hdr,
|
||||
"[%u/%u]", data->oy, screen_hsize(&wp->base));
|
||||
"[%u/%u]", data->oy, screen_hsize(data->backing));
|
||||
screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
|
||||
screen_write_puts(ctx, &gc, "%s", hdr);
|
||||
} else if (py == last && data->inputtype != WINDOW_COPY_OFF) {
|
||||
@@ -862,8 +1069,9 @@ window_copy_write_line(
|
||||
size = 0;
|
||||
|
||||
screen_write_cursormove(ctx, xoff, py);
|
||||
screen_write_copy(ctx, &wp->base, xoff, (screen_hsize(&wp->base) -
|
||||
data->oy) + py, screen_size_x(s) - size, 1);
|
||||
screen_write_copy(ctx, data->backing, xoff,
|
||||
(screen_hsize(data->backing) - data->oy) + py,
|
||||
screen_size_x(s) - size, 1);
|
||||
|
||||
if (py == data->cy && data->cx == screen_size_x(s)) {
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
@@ -932,7 +1140,7 @@ window_copy_start_selection(struct window_pane *wp)
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
data->selx = data->cx;
|
||||
data->sely = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
data->sely = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
|
||||
s->sel.flag = 1;
|
||||
window_copy_update_selection(wp);
|
||||
@@ -957,7 +1165,7 @@ window_copy_update_selection(struct window_pane *wp)
|
||||
gc.attr |= options_get_number(oo, "mode-attr");
|
||||
|
||||
/* Find top of screen. */
|
||||
ty = screen_hsize(&wp->base) - data->oy;
|
||||
ty = screen_hsize(data->backing) - data->oy;
|
||||
|
||||
/* Adjust the selection. */
|
||||
sx = data->selx;
|
||||
@@ -994,7 +1202,7 @@ window_copy_update_selection(struct window_pane *wp)
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_copy_selection(struct window_pane *wp, struct client *c)
|
||||
window_copy_copy_selection(struct window_pane *wp, struct session *sess)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
@@ -1018,7 +1226,7 @@ window_copy_copy_selection(struct window_pane *wp, struct client *c)
|
||||
|
||||
/* Find start and end. */
|
||||
xx = data->cx;
|
||||
yy = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
yy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
if (yy < data->sely || (yy == data->sely && xx < data->selx)) {
|
||||
sx = xx; sy = yy;
|
||||
ex = data->selx; ey = data->sely;
|
||||
@@ -1089,20 +1297,21 @@ window_copy_copy_selection(struct window_pane *wp, struct client *c)
|
||||
off--; /* remove final \n */
|
||||
|
||||
/* Add the buffer to the stack. */
|
||||
limit = options_get_number(&c->session->options, "buffer-limit");
|
||||
paste_add(&c->session->buffers, buf, off, limit);
|
||||
limit = options_get_number(&sess->options, "buffer-limit");
|
||||
paste_add(&sess->buffers, buf, off, limit);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_copy_line(struct window_pane *wp,
|
||||
char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
|
||||
{
|
||||
struct grid *gd = wp->base.grid;
|
||||
const struct grid_cell *gc;
|
||||
const struct grid_utf8 *gu;
|
||||
struct grid_line *gl;
|
||||
u_int i, xx, wrapped = 0;
|
||||
size_t size;
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct grid *gd = data->backing->grid;
|
||||
const struct grid_cell *gc;
|
||||
const struct grid_utf8 *gu;
|
||||
struct grid_line *gl;
|
||||
u_int i, xx, wrapped = 0;
|
||||
size_t size;
|
||||
|
||||
if (sx > ex)
|
||||
return;
|
||||
@@ -1157,7 +1366,7 @@ window_copy_clear_selection(struct window_pane *wp)
|
||||
|
||||
screen_clear_selection(&data->screen);
|
||||
|
||||
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
if (data->cx > px)
|
||||
window_copy_update_cursor(wp, px, data->cy);
|
||||
@@ -1166,9 +1375,10 @@ window_copy_clear_selection(struct window_pane *wp)
|
||||
int
|
||||
window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
|
||||
{
|
||||
const struct grid_cell *gc;
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
const struct grid_cell *gc;
|
||||
|
||||
gc = grid_peek_cell(wp->base.grid, px, py);
|
||||
gc = grid_peek_cell(data->backing->grid, px, py);
|
||||
if (gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8))
|
||||
return (0);
|
||||
if (gc->data == 0x00 || gc->data == 0x7f)
|
||||
@@ -1179,8 +1389,10 @@ window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
|
||||
u_int
|
||||
window_copy_find_length(struct window_pane *wp, u_int py)
|
||||
{
|
||||
const struct grid_cell *gc;
|
||||
u_int px;
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = data->backing;
|
||||
const struct grid_cell *gc;
|
||||
u_int px;
|
||||
|
||||
/*
|
||||
* If the pane has been resized, its grid can contain old overlong
|
||||
@@ -1188,11 +1400,11 @@ window_copy_find_length(struct window_pane *wp, u_int py)
|
||||
* width of the grid, and screen_write_copy treats them as spaces, so
|
||||
* ignore them here too.
|
||||
*/
|
||||
px = wp->base.grid->linedata[py].cellsize;
|
||||
if (px > screen_size_x(&wp->base))
|
||||
px = screen_size_x(&wp->base);
|
||||
px = s->grid->linedata[py].cellsize;
|
||||
if (px > screen_size_x(s))
|
||||
px = screen_size_x(s);
|
||||
while (px > 0) {
|
||||
gc = grid_peek_cell(wp->base.grid, px - 1, py);
|
||||
gc = grid_peek_cell(s->grid, px - 1, py);
|
||||
if (gc->flags & GRID_FLAG_UTF8)
|
||||
break;
|
||||
if (gc->data != ' ')
|
||||
@@ -1206,7 +1418,17 @@ void
|
||||
window_copy_cursor_start_of_line(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *back_s = data->backing;
|
||||
struct grid *gd = back_s->grid;
|
||||
u_int py;
|
||||
|
||||
if (data->cx == 0) {
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
while (py > 0 && gd->linedata[py-1].flags & GRID_LINE_WRAPPED) {
|
||||
window_copy_cursor_up(wp, 0);
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
}
|
||||
}
|
||||
window_copy_update_cursor(wp, 0, data->cy);
|
||||
if (window_copy_update_selection(wp))
|
||||
window_copy_redraw_lines(wp, data->cy, 1);
|
||||
@@ -1220,11 +1442,11 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp)
|
||||
const struct grid_cell *gc;
|
||||
|
||||
px = 0;
|
||||
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
xx = window_copy_find_length(wp, py);
|
||||
|
||||
while (px < xx) {
|
||||
gc = grid_peek_cell(wp->base.grid, px, py);
|
||||
gc = grid_peek_cell(data->backing->grid, px, py);
|
||||
if (gc->flags & GRID_FLAG_UTF8)
|
||||
break;
|
||||
if (gc->data != ' ')
|
||||
@@ -1241,21 +1463,22 @@ void
|
||||
window_copy_cursor_end_of_line(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *base_s = &wp->base;
|
||||
struct grid *gd = base_s->grid;
|
||||
struct screen *back_s = data->backing;
|
||||
struct grid *gd = back_s->grid;
|
||||
u_int px, py;
|
||||
|
||||
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
|
||||
if (data->cx == px) {
|
||||
if (data->screen.sel.flag && data->rectflag)
|
||||
px = screen_size_x(&wp->base);
|
||||
px = screen_size_x(back_s);
|
||||
if (gd->linedata[py].flags & GRID_LINE_WRAPPED) {
|
||||
while (py < gd->sy + gd->hsize &&
|
||||
gd->linedata[py].flags & GRID_LINE_WRAPPED) {
|
||||
window_copy_cursor_down(wp, 0);
|
||||
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||
py = screen_hsize(back_s)
|
||||
+ data->cy - data->oy;
|
||||
}
|
||||
px = window_copy_find_length(wp, py);
|
||||
}
|
||||
@@ -1290,7 +1513,7 @@ window_copy_cursor_right(struct window_pane *wp)
|
||||
if (data->screen.sel.flag && data->rectflag)
|
||||
px = screen_size_x(&data->screen);
|
||||
else {
|
||||
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
}
|
||||
|
||||
@@ -1311,7 +1534,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
||||
struct screen *s = &data->screen;
|
||||
u_int ox, oy, px, py;
|
||||
|
||||
oy = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
ox = window_copy_find_length(wp, oy);
|
||||
if (ox != 0) {
|
||||
data->lastcx = data->cx;
|
||||
@@ -1338,7 +1561,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
||||
}
|
||||
|
||||
if (!data->screen.sel.flag || !data->rectflag) {
|
||||
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||
data->cx > px)
|
||||
@@ -1353,7 +1576,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
||||
struct screen *s = &data->screen;
|
||||
u_int ox, oy, px, py;
|
||||
|
||||
oy = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
ox = window_copy_find_length(wp, oy);
|
||||
if (ox != 0) {
|
||||
data->lastcx = data->cx;
|
||||
@@ -1372,7 +1595,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
||||
}
|
||||
|
||||
if (!data->screen.sel.flag || !data->rectflag) {
|
||||
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||
data->cx > px)
|
||||
@@ -1380,18 +1603,74 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_cursor_jump(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *back_s = data->backing;
|
||||
const struct grid_cell *gc;
|
||||
uint px, py, xx;
|
||||
|
||||
px = data->cx + 1;
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
xx = window_copy_find_length(wp, py);
|
||||
|
||||
while (px < xx) {
|
||||
gc = grid_peek_cell(back_s->grid, px, py);
|
||||
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
|
||||
&& gc->data == data->jumpchar) {
|
||||
|
||||
window_copy_update_cursor(wp, px, data->cy);
|
||||
if (window_copy_update_selection(wp))
|
||||
window_copy_redraw_lines(wp, data->cy, 1);
|
||||
return;
|
||||
}
|
||||
px++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_cursor_jump_back(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *back_s = data->backing;
|
||||
const struct grid_cell *gc;
|
||||
uint px, py;
|
||||
|
||||
px = data->cx;
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
|
||||
if (px > 0)
|
||||
px--;
|
||||
|
||||
for (;;) {
|
||||
gc = grid_peek_cell(back_s->grid, px, py);
|
||||
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
|
||||
&& gc->data == data->jumpchar) {
|
||||
|
||||
window_copy_update_cursor(wp, px, data->cy);
|
||||
if (window_copy_update_selection(wp))
|
||||
window_copy_redraw_lines(wp, data->cy, 1);
|
||||
return;
|
||||
}
|
||||
if (px == 0)
|
||||
break;
|
||||
px--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *base_s = &wp->base;
|
||||
struct screen *back_s = data->backing;
|
||||
u_int px, py, xx, yy;
|
||||
int expected = 0;
|
||||
|
||||
px = data->cx;
|
||||
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
xx = window_copy_find_length(wp, py);
|
||||
yy = screen_hsize(base_s) + screen_size_y(base_s) - 1;
|
||||
yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
|
||||
|
||||
/*
|
||||
* First skip past any nonword characters and then any word characters.
|
||||
@@ -1409,7 +1688,7 @@ window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
|
||||
window_copy_cursor_down(wp, 0);
|
||||
px = 0;
|
||||
|
||||
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
xx = window_copy_find_length(wp, py);
|
||||
} else
|
||||
px++;
|
||||
@@ -1426,14 +1705,14 @@ void
|
||||
window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *base_s = &wp->base;
|
||||
struct screen *back_s = data->backing;
|
||||
u_int px, py, xx, yy;
|
||||
int expected = 1;
|
||||
|
||||
px = data->cx;
|
||||
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
xx = window_copy_find_length(wp, py);
|
||||
yy = screen_hsize(base_s) + screen_size_y(base_s) - 1;
|
||||
yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
|
||||
|
||||
/*
|
||||
* First skip past any word characters, then any nonword characters.
|
||||
@@ -1451,7 +1730,7 @@ window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
|
||||
window_copy_cursor_down(wp, 0);
|
||||
px = 0;
|
||||
|
||||
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
xx = window_copy_find_length(wp, py);
|
||||
} else
|
||||
px++;
|
||||
@@ -1472,7 +1751,7 @@ window_copy_cursor_previous_word(struct window_pane *wp, const char *separators)
|
||||
u_int px, py;
|
||||
|
||||
px = data->cx;
|
||||
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
|
||||
/* Move back to the previous word character. */
|
||||
for (;;) {
|
||||
@@ -1482,12 +1761,12 @@ window_copy_cursor_previous_word(struct window_pane *wp, const char *separators)
|
||||
break;
|
||||
} else {
|
||||
if (data->cy == 0 &&
|
||||
(screen_hsize(&wp->base) == 0 ||
|
||||
data->oy >= screen_hsize(&wp->base) - 1))
|
||||
(screen_hsize(data->backing) == 0 ||
|
||||
data->oy >= screen_hsize(data->backing) - 1))
|
||||
goto out;
|
||||
window_copy_cursor_up(wp, 0);
|
||||
|
||||
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
}
|
||||
}
|
||||
@@ -1540,11 +1819,11 @@ window_copy_scroll_down(struct window_pane *wp, u_int ny)
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
if (ny > screen_hsize(&wp->base))
|
||||
if (ny > screen_hsize(data->backing))
|
||||
return;
|
||||
|
||||
if (data->oy > screen_hsize(&wp->base) - ny)
|
||||
ny = screen_hsize(&wp->base) - data->oy;
|
||||
if (data->oy > screen_hsize(data->backing) - ny)
|
||||
ny = screen_hsize(data->backing) - data->oy;
|
||||
if (ny == 0)
|
||||
return;
|
||||
data->oy += ny;
|
||||
@@ -1571,7 +1850,7 @@ window_copy_rectangle_toggle(struct window_pane *wp)
|
||||
|
||||
data->rectflag = !data->rectflag;
|
||||
|
||||
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
if (data->cx > px)
|
||||
window_copy_update_cursor(wp, px, data->cy);
|
||||
|
||||
260
window-more.c
260
window-more.c
@@ -1,260 +0,0 @@
|
||||
/* $Id: window-more.c,v 1.42 2010-02-08 18:10:07 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* 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"
|
||||
|
||||
struct screen *window_more_init(struct window_pane *);
|
||||
void window_more_free(struct window_pane *);
|
||||
void window_more_resize(struct window_pane *, u_int, u_int);
|
||||
void window_more_key(struct window_pane *, struct client *, int);
|
||||
|
||||
void window_more_redraw_screen(struct window_pane *);
|
||||
void window_more_write_line(
|
||||
struct window_pane *, struct screen_write_ctx *, u_int);
|
||||
|
||||
void window_more_scroll_up(struct window_pane *);
|
||||
void window_more_scroll_down(struct window_pane *);
|
||||
|
||||
const struct window_mode window_more_mode = {
|
||||
window_more_init,
|
||||
window_more_free,
|
||||
window_more_resize,
|
||||
window_more_key,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct window_more_mode_data {
|
||||
struct screen screen;
|
||||
|
||||
struct mode_key_data mdata;
|
||||
|
||||
ARRAY_DECL(, char *) list;
|
||||
u_int top;
|
||||
};
|
||||
|
||||
void
|
||||
window_more_add(struct window_pane *wp, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
window_more_vadd(wp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
window_more_vadd(struct window_pane *wp, const char *fmt, va_list ap)
|
||||
{
|
||||
struct window_more_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
char *msg;
|
||||
u_int size;
|
||||
|
||||
xvasprintf(&msg, fmt, ap);
|
||||
ARRAY_ADD(&data->list, msg);
|
||||
|
||||
screen_write_start(&ctx, wp, NULL);
|
||||
size = ARRAY_LENGTH(&data->list) - 1;
|
||||
if (size >= data->top && size <= data->top + screen_size_y(s) - 1) {
|
||||
window_more_write_line(wp, &ctx, size - data->top);
|
||||
if (size != data->top)
|
||||
window_more_write_line(wp, &ctx, 0);
|
||||
} else
|
||||
window_more_write_line(wp, &ctx, 0);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
struct screen *
|
||||
window_more_init(struct window_pane *wp)
|
||||
{
|
||||
struct window_more_mode_data *data;
|
||||
struct screen *s;
|
||||
int keys;
|
||||
|
||||
wp->modedata = data = xmalloc(sizeof *data);
|
||||
ARRAY_INIT(&data->list);
|
||||
data->top = 0;
|
||||
|
||||
s = &data->screen;
|
||||
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
|
||||
s->mode &= ~MODE_CURSOR;
|
||||
|
||||
keys = options_get_number(&wp->window->options, "mode-keys");
|
||||
if (keys == MODEKEY_EMACS)
|
||||
mode_key_init(&data->mdata, &mode_key_tree_emacs_choice);
|
||||
else
|
||||
mode_key_init(&data->mdata, &mode_key_tree_vi_choice);
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
void
|
||||
window_more_free(struct window_pane *wp)
|
||||
{
|
||||
struct window_more_mode_data *data = wp->modedata;
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&data->list); i++)
|
||||
xfree(ARRAY_ITEM(&data->list, i));
|
||||
ARRAY_FREE(&data->list);
|
||||
|
||||
screen_free(&data->screen);
|
||||
xfree(data);
|
||||
}
|
||||
|
||||
void
|
||||
window_more_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_more_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
screen_resize(s, sx, sy);
|
||||
window_more_redraw_screen(wp);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
window_more_key(struct window_pane *wp, unused struct client *c, int key)
|
||||
{
|
||||
struct window_more_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
switch (mode_key_lookup(&data->mdata, key)) {
|
||||
case MODEKEYCHOICE_CANCEL:
|
||||
window_pane_reset_mode(wp);
|
||||
break;
|
||||
case MODEKEYCHOICE_UP:
|
||||
case MODEKEYCHOICE_SCROLLUP:
|
||||
window_more_scroll_up(wp);
|
||||
break;
|
||||
case MODEKEYCHOICE_DOWN:
|
||||
case MODEKEYCHOICE_SCROLLDOWN:
|
||||
window_more_scroll_down(wp);
|
||||
break;
|
||||
case MODEKEYCHOICE_PAGEUP:
|
||||
if (data->top < screen_size_y(s))
|
||||
data->top = 0;
|
||||
else
|
||||
data->top -= screen_size_y(s);
|
||||
window_more_redraw_screen(wp);
|
||||
break;
|
||||
case MODEKEYCHOICE_PAGEDOWN:
|
||||
if (data->top + screen_size_y(s) > ARRAY_LENGTH(&data->list))
|
||||
data->top = ARRAY_LENGTH(&data->list);
|
||||
else
|
||||
data->top += screen_size_y(s);
|
||||
window_more_redraw_screen(wp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
window_more_write_line(
|
||||
struct window_pane *wp, struct screen_write_ctx *ctx, u_int py)
|
||||
{
|
||||
struct window_more_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct options *oo = &wp->window->options;
|
||||
struct grid_cell gc;
|
||||
char *msg, hdr[32];
|
||||
size_t size;
|
||||
int utf8flag;
|
||||
|
||||
utf8flag = options_get_number(&wp->window->options, "utf8");
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
|
||||
if (py == 0) {
|
||||
size = xsnprintf(hdr, sizeof hdr,
|
||||
"[%u/%u]", data->top, ARRAY_LENGTH(&data->list));
|
||||
screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
|
||||
colour_set_fg(&gc, options_get_number(oo, "mode-fg"));
|
||||
colour_set_bg(&gc, options_get_number(oo, "mode-bg"));
|
||||
gc.attr |= options_get_number(oo, "mode-attr");
|
||||
screen_write_puts(ctx, &gc, "%s", hdr);
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
} else
|
||||
size = 0;
|
||||
|
||||
screen_write_cursormove(ctx, 0, py);
|
||||
if (data->top + py < ARRAY_LENGTH(&data->list)) {
|
||||
msg = ARRAY_ITEM(&data->list, data->top + py);
|
||||
screen_write_nputs(
|
||||
ctx, screen_size_x(s) - size, &gc, utf8flag, "%s", msg);
|
||||
}
|
||||
while (s->cx < screen_size_x(s) - size)
|
||||
screen_write_putc(ctx, &gc, ' ');
|
||||
}
|
||||
|
||||
void
|
||||
window_more_redraw_screen(struct window_pane *wp)
|
||||
{
|
||||
struct window_more_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
u_int i;
|
||||
|
||||
screen_write_start(&ctx, wp, NULL);
|
||||
for (i = 0; i < screen_size_y(s); i++)
|
||||
window_more_write_line(wp, &ctx, i);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
void
|
||||
window_more_scroll_up(struct window_pane *wp)
|
||||
{
|
||||
struct window_more_mode_data *data = wp->modedata;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
if (data->top == 0)
|
||||
return;
|
||||
data->top--;
|
||||
|
||||
screen_write_start(&ctx, wp, NULL);
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_insertline(&ctx, 1);
|
||||
window_more_write_line(wp, &ctx, 0);
|
||||
window_more_write_line(wp, &ctx, 1);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
|
||||
void
|
||||
window_more_scroll_down(struct window_pane *wp)
|
||||
{
|
||||
struct window_more_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
if (data->top >= ARRAY_LENGTH(&data->list))
|
||||
return;
|
||||
data->top++;
|
||||
|
||||
screen_write_start(&ctx, wp, NULL);
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_deleteline(&ctx, 1);
|
||||
window_more_write_line(wp, &ctx, screen_size_y(s) - 1);
|
||||
window_more_write_line(wp, &ctx, 0);
|
||||
screen_write_stop(&ctx);
|
||||
}
|
||||
301
window.c
301
window.c
@@ -1,4 +1,4 @@
|
||||
/* $Id: window.c,v 1.126 2010-02-08 18:10:07 tcunha Exp $ */
|
||||
/* $Id: window.c,v 1.134 2010-07-17 14:38:13 tcunha Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||
@@ -170,6 +170,28 @@ winlink_previous(struct winlink *wl)
|
||||
return (RB_PREV(winlinks, wwl, wl));
|
||||
}
|
||||
|
||||
struct winlink *
|
||||
winlink_next_by_number(struct winlink *wl, struct session *s, int n)
|
||||
{
|
||||
for (; n > 0; n--) {
|
||||
if ((wl = RB_NEXT(winlinks, wwl, wl)) == NULL)
|
||||
wl = RB_MIN(winlinks, &s->windows);
|
||||
}
|
||||
|
||||
return (wl);
|
||||
}
|
||||
|
||||
struct winlink *
|
||||
winlink_previous_by_number(struct winlink *wl, struct session *s, int n)
|
||||
{
|
||||
for (; n > 0; n--) {
|
||||
if ((wl = RB_PREV(winlinks, wwl, wl)) == NULL)
|
||||
wl = RB_MAX(winlinks, &s->windows);
|
||||
}
|
||||
|
||||
return (wl);
|
||||
}
|
||||
|
||||
void
|
||||
winlink_stack_push(struct winlink_stack *stack, struct winlink *wl)
|
||||
{
|
||||
@@ -367,6 +389,29 @@ window_pane_at_index(struct window *w, u_int idx)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct window_pane *
|
||||
window_pane_next_by_number(struct window *w, struct window_pane *wp, u_int n)
|
||||
{
|
||||
for (; n > 0; n--) {
|
||||
if ((wp = TAILQ_NEXT(wp, entry)) == NULL)
|
||||
wp = TAILQ_FIRST(&w->panes);
|
||||
}
|
||||
|
||||
return (wp);
|
||||
}
|
||||
|
||||
struct window_pane *
|
||||
window_pane_previous_by_number(struct window *w, struct window_pane *wp,
|
||||
u_int n)
|
||||
{
|
||||
for (; n > 0; n--) {
|
||||
if ((wp = TAILQ_PREV(wp, window_panes, entry)) == NULL)
|
||||
wp = TAILQ_LAST(&w->panes, window_panes);
|
||||
}
|
||||
|
||||
return (wp);
|
||||
}
|
||||
|
||||
u_int
|
||||
window_pane_index(struct window *w, struct window_pane *wp)
|
||||
{
|
||||
@@ -478,14 +523,11 @@ int
|
||||
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
||||
const char *cwd, struct environ *env, struct termios *tio, char **cause)
|
||||
{
|
||||
struct winsize ws;
|
||||
int mode;
|
||||
char *argv0, **varp, *var;
|
||||
ARRAY_DECL(, char *) varlist;
|
||||
struct environ_entry *envent;
|
||||
const char *ptr;
|
||||
struct termios tio2;
|
||||
u_int i;
|
||||
struct winsize ws;
|
||||
int mode;
|
||||
char *argv0;
|
||||
const char *ptr;
|
||||
struct termios tio2;
|
||||
|
||||
if (wp->fd != -1) {
|
||||
close(wp->fd);
|
||||
@@ -528,22 +570,9 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
|
||||
fatal("tcgetattr failed");
|
||||
|
||||
ARRAY_INIT(&varlist);
|
||||
for (varp = environ; *varp != NULL; varp++) {
|
||||
var = xstrdup(*varp);
|
||||
var[strcspn(var, "=")] = '\0';
|
||||
ARRAY_ADD(&varlist, var);
|
||||
}
|
||||
for (i = 0; i < ARRAY_LENGTH(&varlist); i++) {
|
||||
var = ARRAY_ITEM(&varlist, i);
|
||||
unsetenv(var);
|
||||
}
|
||||
RB_FOREACH(envent, environ, env) {
|
||||
if (envent->value != NULL)
|
||||
setenv(envent->name, envent->value, 1);
|
||||
}
|
||||
environ_push(env);
|
||||
|
||||
server_signal_clear();
|
||||
clear_signals();
|
||||
log_close();
|
||||
|
||||
if (*wp->cmd != '\0') {
|
||||
@@ -584,9 +613,19 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
||||
void
|
||||
window_pane_read_callback(unused struct bufferevent *bufev, void *data)
|
||||
{
|
||||
struct window_pane *wp = data;
|
||||
struct window_pane *wp = data;
|
||||
char *new_data;
|
||||
size_t new_size;
|
||||
|
||||
window_pane_parse(wp);
|
||||
new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off;
|
||||
if (wp->pipe_fd != -1 && new_size > 0) {
|
||||
new_data = EVBUFFER_DATA(wp->event->input);
|
||||
bufferevent_write(wp->pipe_event, new_data, new_size);
|
||||
}
|
||||
|
||||
input_parse(wp);
|
||||
|
||||
wp->pipe_off = EVBUFFER_LENGTH(wp->event->input);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@@ -630,6 +669,81 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
fatal("ioctl failed");
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter alternative screen mode. A copy of the visible screen is saved and the
|
||||
* history is not updated
|
||||
*/
|
||||
void
|
||||
window_pane_alternate_on(struct window_pane *wp, struct grid_cell *gc)
|
||||
{
|
||||
struct screen *s = &wp->base;
|
||||
u_int sx, sy;
|
||||
|
||||
if (wp->saved_grid != NULL)
|
||||
return;
|
||||
if (!options_get_number(&wp->window->options, "alternate-screen"))
|
||||
return;
|
||||
sx = screen_size_x(s);
|
||||
sy = screen_size_y(s);
|
||||
|
||||
wp->saved_grid = grid_create(sx, sy, 0);
|
||||
grid_duplicate_lines(wp->saved_grid, 0, s->grid, screen_hsize(s), sy);
|
||||
wp->saved_cx = s->cx;
|
||||
wp->saved_cy = s->cy;
|
||||
memcpy(&wp->saved_cell, gc, sizeof wp->saved_cell);
|
||||
|
||||
grid_view_clear(s->grid, 0, 0, sx, sy);
|
||||
|
||||
wp->base.grid->flags &= ~GRID_HISTORY;
|
||||
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
|
||||
/* Exit alternate screen mode and restore the copied grid. */
|
||||
void
|
||||
window_pane_alternate_off(struct window_pane *wp, struct grid_cell *gc)
|
||||
{
|
||||
struct screen *s = &wp->base;
|
||||
u_int sx, sy;
|
||||
|
||||
if (wp->saved_grid == NULL)
|
||||
return;
|
||||
if (!options_get_number(&wp->window->options, "alternate-screen"))
|
||||
return;
|
||||
sx = screen_size_x(s);
|
||||
sy = screen_size_y(s);
|
||||
|
||||
/*
|
||||
* If the current size is bigger, temporarily resize to the old size
|
||||
* before copying back.
|
||||
*/
|
||||
if (sy > wp->saved_grid->sy)
|
||||
screen_resize(s, sx, wp->saved_grid->sy);
|
||||
|
||||
/* Restore the grid, cursor position and cell. */
|
||||
grid_duplicate_lines(s->grid, screen_hsize(s), wp->saved_grid, 0, sy);
|
||||
s->cx = wp->saved_cx;
|
||||
if (s->cx > screen_size_x(s) - 1)
|
||||
s->cx = screen_size_x(s) - 1;
|
||||
s->cy = wp->saved_cy;
|
||||
if (s->cy > screen_size_y(s) - 1)
|
||||
s->cy = screen_size_y(s) - 1;
|
||||
memcpy(gc, &wp->saved_cell, sizeof *gc);
|
||||
|
||||
/*
|
||||
* Turn history back on (so resize can use it) and then resize back to
|
||||
* the current size.
|
||||
*/
|
||||
wp->base.grid->flags |= GRID_HISTORY;
|
||||
if (sy > wp->saved_grid->sy)
|
||||
screen_resize(s, sx, sy);
|
||||
|
||||
grid_destroy(wp->saved_grid);
|
||||
wp->saved_grid = NULL;
|
||||
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode)
|
||||
{
|
||||
@@ -659,24 +773,7 @@ window_pane_reset_mode(struct window_pane *wp)
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_parse(struct window_pane *wp)
|
||||
{
|
||||
char *data;
|
||||
size_t new_size;
|
||||
|
||||
new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off;
|
||||
if (wp->pipe_fd != -1 && new_size > 0) {
|
||||
data = EVBUFFER_DATA(wp->event->input);
|
||||
bufferevent_write(wp->pipe_event, data, new_size);
|
||||
}
|
||||
|
||||
input_parse(wp);
|
||||
|
||||
wp->pipe_off = EVBUFFER_LENGTH(wp->event->input);
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_key(struct window_pane *wp, struct client *c, int key)
|
||||
window_pane_key(struct window_pane *wp, struct session *sess, int key)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
|
||||
@@ -685,7 +782,7 @@ window_pane_key(struct window_pane *wp, struct client *c, int key)
|
||||
|
||||
if (wp->mode != NULL) {
|
||||
if (wp->mode->key != NULL)
|
||||
wp->mode->key(wp, c, key);
|
||||
wp->mode->key(wp, sess, key);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -704,7 +801,7 @@ window_pane_key(struct window_pane *wp, struct client *c, int key)
|
||||
|
||||
void
|
||||
window_pane_mouse(
|
||||
struct window_pane *wp, struct client *c, struct mouse_event *m)
|
||||
struct window_pane *wp, struct session *sess, struct mouse_event *m)
|
||||
{
|
||||
if (!window_pane_visible(wp))
|
||||
return;
|
||||
@@ -718,7 +815,7 @@ window_pane_mouse(
|
||||
|
||||
if (wp->mode != NULL) {
|
||||
if (wp->mode->mouse != NULL)
|
||||
wp->mode->mouse(wp, c, m);
|
||||
wp->mode->mouse(wp, sess, m);
|
||||
} else if (wp->fd != -1)
|
||||
input_mouse(wp, m);
|
||||
}
|
||||
@@ -759,3 +856,113 @@ window_pane_search(struct window_pane *wp, const char *searchstr, u_int *lineno)
|
||||
xfree(newsearchstr);
|
||||
return (msg);
|
||||
}
|
||||
|
||||
/* Find the pane directly above another. */
|
||||
struct window_pane *
|
||||
window_pane_find_up(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
u_int left, top;
|
||||
|
||||
if (wp == NULL || !window_pane_visible(wp))
|
||||
return (NULL);
|
||||
|
||||
top = wp->yoff;
|
||||
if (top == 0)
|
||||
top = wp->window->sy + 1;
|
||||
left = wp->xoff;
|
||||
|
||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
||||
if (!window_pane_visible(wp2))
|
||||
continue;
|
||||
if (wp2->yoff + wp2->sy + 1 != top)
|
||||
continue;
|
||||
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
|
||||
return (wp2);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Find the pane directly below another. */
|
||||
struct window_pane *
|
||||
window_pane_find_down(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
u_int left, bottom;
|
||||
|
||||
if (wp == NULL || !window_pane_visible(wp))
|
||||
return (NULL);
|
||||
|
||||
bottom = wp->yoff + wp->sy + 1;
|
||||
if (bottom >= wp->window->sy)
|
||||
bottom = 0;
|
||||
left = wp->xoff;
|
||||
|
||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
||||
if (!window_pane_visible(wp2))
|
||||
continue;
|
||||
if (wp2->yoff != bottom)
|
||||
continue;
|
||||
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
|
||||
return (wp2);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the pane directly to the left of another, adjacent to the left side and
|
||||
* containing the top edge.
|
||||
*/
|
||||
struct window_pane *
|
||||
window_pane_find_left(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
u_int left, top;
|
||||
|
||||
if (wp == NULL || !window_pane_visible(wp))
|
||||
return (NULL);
|
||||
|
||||
left = wp->xoff;
|
||||
if (left == 0)
|
||||
left = wp->window->sx + 1;
|
||||
top = wp->yoff;
|
||||
|
||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
||||
if (!window_pane_visible(wp2))
|
||||
continue;
|
||||
if (wp2->xoff + wp2->sx + 1 != left)
|
||||
continue;
|
||||
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
|
||||
return (wp2);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the pane directly to the right of another, that is adjacent to the
|
||||
* right edge and including the top edge.
|
||||
*/
|
||||
struct window_pane *
|
||||
window_pane_find_right(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
u_int right, top;
|
||||
|
||||
if (wp == NULL || !window_pane_visible(wp))
|
||||
return (NULL);
|
||||
|
||||
right = wp->xoff + wp->sx + 1;
|
||||
if (right >= wp->window->sx)
|
||||
right = 0;
|
||||
top = wp->yoff;
|
||||
|
||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
||||
if (!window_pane_visible(wp2))
|
||||
continue;
|
||||
if (wp2->xoff != right)
|
||||
continue;
|
||||
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
|
||||
return (wp2);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -63,6 +63,9 @@ development.</li>
|
||||
system. The portable version is hosted on <a href="http://sf.net/projects/tmux">
|
||||
SourceForge</a> and runs on Linux, FreeBSD, NetBSD, Solaris and AIX.</p>
|
||||
|
||||
<p>tmux depends on <a href="http://www.monkey.org/~provos/libevent/">libevent 1.4</a> and a
|
||||
terminfo implementation (normally <a href="http://invisible-island.net/ncurses/">ncurses</a>).</p>
|
||||
|
||||
<div id="screenshots">
|
||||
<a href="tmux3.png"><img src="small-tmux3.png" alt="Screenshot"/></a>
|
||||
<a href="tmux4.png"><img src="small-tmux4.png" alt="Screenshot"/></a>
|
||||
|
||||
Reference in New Issue
Block a user