aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES11
-rw-r--r--FAQ34
-rw-r--r--Makefile.am27
-rw-r--r--SYNCING9
-rw-r--r--TODO50
-rw-r--r--arguments.c15
-rw-r--r--array.h4
-rw-r--r--attributes.c2
-rw-r--r--cfg.c96
-rw-r--r--client.c62
-rw-r--r--clock.c166
-rw-r--r--cmd-attach-session.c19
-rw-r--r--cmd-bind-key.c11
-rw-r--r--cmd-break-pane.c23
-rw-r--r--cmd-capture-pane.c77
-rw-r--r--cmd-choose-buffer.c21
-rw-r--r--cmd-choose-client.c12
-rw-r--r--cmd-choose-list.c97
-rw-r--r--cmd-choose-tree.c14
-rw-r--r--cmd-clear-history.c3
-rw-r--r--cmd-clock-mode.c3
-rw-r--r--cmd-command-prompt.c32
-rw-r--r--cmd-confirm-before.c24
-rw-r--r--cmd-copy-mode.c12
-rw-r--r--cmd-delete-buffer.c20
-rw-r--r--cmd-detach-client.c67
-rw-r--r--cmd-display-message.c14
-rw-r--r--cmd-display-panes.c3
-rw-r--r--cmd-find-window.c19
-rw-r--r--cmd-has-session.c47
-rw-r--r--cmd-if-shell.c37
-rw-r--r--cmd-join-pane.c25
-rw-r--r--cmd-kill-pane.c3
-rw-r--r--cmd-kill-server.c4
-rw-r--r--cmd-kill-session.c3
-rw-r--r--cmd-kill-window.c46
-rw-r--r--cmd-link-window.c64
-rw-r--r--cmd-list-buffers.c14
-rw-r--r--cmd-list-clients.c11
-rw-r--r--cmd-list-commands.c54
-rw-r--r--cmd-list-keys.c35
-rw-r--r--cmd-list-panes.c7
-rw-r--r--cmd-list-sessions.c13
-rw-r--r--cmd-list-windows.c23
-rw-r--r--cmd-list.c14
-rw-r--r--cmd-load-buffer.c60
-rw-r--r--cmd-lock-server.c9
-rw-r--r--cmd-move-window.c22
-rw-r--r--cmd-new-session.c74
-rw-r--r--cmd-new-window.c56
-rw-r--r--cmd-paste-buffer.c40
-rw-r--r--cmd-pipe-pane.c25
-rw-r--r--cmd-queue.c72
-rw-r--r--cmd-refresh-client.c3
-rw-r--r--cmd-rename-session.c3
-rw-r--r--cmd-rename-window.c3
-rw-r--r--cmd-resize-pane.c50
-rw-r--r--cmd-respawn-pane.c21
-rw-r--r--cmd-respawn-window.c22
-rw-r--r--cmd-rotate-window.c12
-rw-r--r--cmd-run-shell.c20
-rw-r--r--cmd-save-buffer.c29
-rw-r--r--cmd-select-layout.c34
-rw-r--r--cmd-select-pane.c54
-rw-r--r--cmd-select-window.c21
-rw-r--r--cmd-send-keys.c4
-rw-r--r--cmd-set-buffer.c87
-rw-r--r--cmd-set-environment.c3
-rw-r--r--cmd-set-option.c68
-rw-r--r--cmd-show-environment.c3
-rw-r--r--cmd-show-messages.c4
-rw-r--r--cmd-show-options.c24
-rw-r--r--cmd-source-file.c25
-rw-r--r--cmd-split-window.c71
-rw-r--r--cmd-string.c21
-rw-r--r--cmd-suspend-client.c55
-rw-r--r--cmd-swap-pane.c14
-rw-r--r--cmd-swap-window.c3
-rw-r--r--cmd-switch-client.c28
-rw-r--r--cmd-unbind-key.c11
-rw-r--r--cmd-unlink-window.c69
-rw-r--r--cmd-wait-for.c29
-rw-r--r--cmd.c144
-rw-r--r--colour.c2
-rw-r--r--compat.h15
-rw-r--r--compat/asprintf.c4
-rw-r--r--compat/bitstring.h1
-rw-r--r--compat/cfmakeraw.c2
-rw-r--r--compat/closefrom.c2
-rw-r--r--compat/daemon.c1
-rw-r--r--compat/fgetln.c1
-rw-r--r--compat/forkpty-aix.c26
-rw-r--r--compat/forkpty-hpux.c4
-rw-r--r--compat/forkpty-sunos.c4
-rw-r--r--compat/fparseln.c221
-rw-r--r--compat/getopt.c2
-rw-r--r--compat/imsg-buffer.c39
-rw-r--r--compat/imsg.c100
-rw-r--r--compat/imsg.h12
-rw-r--r--compat/openat.c2
-rw-r--r--compat/setenv.c2
-rw-r--r--compat/strcasestr.c1
-rw-r--r--compat/strlcat.c1
-rw-r--r--compat/strlcpy.c1
-rw-r--r--compat/strsep.c1
-rw-r--r--compat/strtonum.c1
-rw-r--r--compat/tree.h1
-rw-r--r--compat/unvis.c1
-rw-r--r--compat/vis.c1
-rw-r--r--compat/vis.h1
-rw-r--r--configure.ac116
-rw-r--r--control-notify.c19
-rw-r--r--control.c4
-rw-r--r--environ.c12
-rw-r--r--examples/tmux.vim276
-rw-r--r--examples/xterm-keys.vim49
-rw-r--r--format.c229
-rw-r--r--grid-view.c30
-rw-r--r--grid.c49
-rw-r--r--input-keys.c50
-rw-r--r--input.c180
-rw-r--r--job.c5
-rw-r--r--key-bindings.c201
-rw-r--r--key-string.c10
-rw-r--r--layout-custom.c2
-rw-r--r--layout-set.c6
-rw-r--r--layout.c2
-rw-r--r--log.c125
-rw-r--r--mode-key.c23
-rw-r--r--names.c18
-rw-r--r--notify.c2
-rw-r--r--options-table.c146
-rw-r--r--options.c4
-rw-r--r--osdep-aix.c2
-rw-r--r--osdep-cygwin.c88
-rw-r--r--osdep-darwin.c2
-rw-r--r--osdep-dragonfly.c2
-rw-r--r--osdep-freebsd.c38
-rw-r--r--osdep-hpux.c2
-rw-r--r--osdep-linux.c14
-rw-r--r--osdep-netbsd.c2
-rw-r--r--osdep-openbsd.c9
-rw-r--r--osdep-sunos.c13
-rw-r--r--osdep-unknown.c2
-rw-r--r--paste.c245
-rw-r--r--resize.c18
-rw-r--r--screen-redraw.c49
-rw-r--r--screen-write.c35
-rw-r--r--screen.c36
-rw-r--r--server-client.c55
-rw-r--r--server-fn.c11
-rw-r--r--server-window.c62
-rw-r--r--server.c47
-rw-r--r--session.c41
-rw-r--r--signal.c4
-rw-r--r--status.c147
-rw-r--r--style.c32
-rw-r--r--tmux.1431
-rw-r--r--tmux.c25
-rw-r--r--tmux.h462
-rw-r--r--tools/fix-ids.sh8
-rw-r--r--tty-acs.c4
-rw-r--r--tty-keys.c146
-rw-r--r--tty-term.c56
-rw-r--r--tty.c39
-rw-r--r--utf8.c168
-rw-r--r--window-choose.c101
-rw-r--r--window-clock.c145
-rw-r--r--window-copy.c376
-rw-r--r--window.c376
-rw-r--r--www/index.html.in10
-rw-r--r--xmalloc.c28
-rw-r--r--xterm-keys.c91
173 files changed, 4549 insertions, 3520 deletions
diff --git a/CHANGES b/CHANGES
index 6cec717b..abd1ac0a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,14 @@
+CHANGES FROM 1.9 to 1.9a 22 February 2014
+
+NOTE: This is a bug-fix release to address some important bugs which just
+missed the 1.9 deadline, but were found afterwards.
+
+Normal Changes
+==============
+
+* Fix crash due to uninitialized lastwp member of layout_cell
+* Fix -fg/-bg/-style with 256 colour terminals.
+
CHANGES FROM 1.8 to 1.9, 20 February 2014
NOTE: This release has bumped the tmux protocol version. It is therefore
diff --git a/FAQ b/FAQ
index da72d433..2ca0a596 100644
--- a/FAQ
+++ b/FAQ
@@ -95,9 +95,6 @@ aware of are (bearing in mind I haven't used screen for a few years now):
- screen has builtin serial and telnet support; this is bloat and is unlikely
to be added to tmux.
-- screen has support for updating utmp. Nobody has really come up with a clean,
- portable way to do this without making tmux setuid or setgid yet.
-
- Environment handling is different.
- tmux tends to be more demanding on the terminal so tends to show up terminal
@@ -107,6 +104,10 @@ aware of are (bearing in mind I haven't used screen for a few years now):
* I found a bug! What do I do?
+Check the latest version of tmux from Git to see if the problem is still
+reproducible. Sometimes the length of time between releases means a lot of
+fixes can be sitting in Git and the problem might already be fixed.
+
Please send bug reports by email to nicm@users.sourceforge.net or
tmux-users@lists.sourceforge.net. Please include as much of the following
information as possible:
@@ -238,6 +239,31 @@ would be welcome.
vim users may also want to set the "ttyfast" option inside tmux.
+* How do I make ctrl and shift arrow keys work in emacs?
+
+The terminal-init-screen function in term/screen.el is called for new frames,
+but it doesn't configure any function keys.
+
+If the tmux xterm-keys option is on, it is enough to define the same keys as
+xterm. Add the following to init.el or .emacs to do this:
+
+(defadvice terminal-init-screen
+ ;; The advice is named `tmux', and is run before `terminal-init-screen' runs.
+ (before tmux activate)
+ ;; Docstring. This describes the advice and is made available inside emacs;
+ ;; for example when doing C-h f terminal-init-screen RET
+ "Apply xterm keymap, allowing use of keys passed through tmux."
+ ;; This is the elisp code that is run before `terminal-init-screen'.
+ (if (getenv "TMUX")
+ (let ((map (copy-keymap xterm-function-map)))
+ (set-keymap-parent map (keymap-parent input-decode-map))
+ (set-keymap-parent input-decode-map map))))
+
+And ensure .tmux.conf contains "set -g xterm-keys on".
+
+Alternatively, the screen.el file can be copied to the load path and
+customized.
+
* Why doesn't elinks set the window title inside tmux?
There isn't a way to detect if a terminal supports setting the window title, so
@@ -377,7 +403,7 @@ always (or ever) be added to the scrollback.
You can make tmux use the normal screen by telling it that your terminal does
not have an alternate screen. Put the following in ~/.tmux.conf:
- set -g terminal-overrides 'xterm*:smcup@:rmcup@'
+ set -ga terminal-overrides ',xterm*:smcup@:rmcup@'
Adjust if your $TERM does not start with xterm.
diff --git a/Makefile.am b/Makefile.am
index e5a7286e..071c3a17 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,6 +9,7 @@ EXTRA_DIST = \
CHANGES FAQ README TODO COPYING examples compat \
array.h compat.h tmux.h osdep-*.c mdoc2man.awk tmux.1
dist-hook:
+ make clean
grep "^#found_debug=" configure
find $(distdir) -name .svn -type d|xargs rm -Rf
@@ -24,25 +25,23 @@ endif
# Set flags for gcc. gcc4 whines abouts silly stuff so it needs slightly
# different flags.
if IS_GCC
-CFLAGS += -std=gnu99
+CFLAGS += -std=gnu99 -O2
if IS_DEBUG
-CFLAGS += -O0 -g
+CFLAGS += -g
CFLAGS += -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
CFLAGS += -Wdeclaration-after-statement
CPPFLAGS += -DDEBUG
-else
-CFLAGS += -O2
endif
if IS_GCC4
-CPPFLAGS += -iquote. -I/usr/local/include
+CPPFLAGS += -iquote.
if IS_DEBUG
CFLAGS += -Wno-pointer-sign
endif
else
-CPPFLAGS += -I. -I- -I/usr/local/include
+CPPFLAGS += -I. -I-
endif
endif
@@ -66,14 +65,12 @@ dist_tmux_SOURCES = \
attributes.c \
cfg.c \
client.c \
- clock.c \
cmd-attach-session.c \
cmd-bind-key.c \
cmd-break-pane.c \
cmd-capture-pane.c \
cmd-choose-buffer.c \
cmd-choose-client.c \
- cmd-choose-list.c \
cmd-choose-tree.c \
cmd-clear-history.c \
cmd-clock-mode.c \
@@ -85,17 +82,14 @@ dist_tmux_SOURCES = \
cmd-display-message.c \
cmd-display-panes.c \
cmd-find-window.c \
- cmd-has-session.c \
cmd-if-shell.c \
cmd-join-pane.c \
cmd-kill-pane.c \
cmd-kill-server.c \
cmd-kill-session.c \
cmd-kill-window.c \
- cmd-link-window.c \
cmd-list-buffers.c \
cmd-list-clients.c \
- cmd-list-commands.c \
cmd-list-keys.c \
cmd-list-panes.c \
cmd-list-sessions.c \
@@ -131,12 +125,10 @@ dist_tmux_SOURCES = \
cmd-source-file.c \
cmd-split-window.c \
cmd-string.c \
- cmd-suspend-client.c \
cmd-swap-pane.c \
cmd-swap-window.c \
cmd-switch-client.c \
cmd-unbind-key.c \
- cmd-unlink-window.c \
cmd-wait-for.c \
cmd.c \
colour.c \
@@ -216,6 +208,9 @@ endif
if NO_FGETLN
nodist_tmux_SOURCES += compat/fgetln.c
endif
+if NO_FPARSELN
+nodist_tmux_SOURCES += compat/fparseln.c
+endif
if NO_GETOPT
nodist_tmux_SOURCES += compat/getopt.c
endif
@@ -248,9 +243,9 @@ install-exec-hook:
>$(srcdir)/tmux.1.mdoc; \
else \
sed -e "s|@SYSCONFDIR@|$(sysconfdir)|g" $(srcdir)/tmux.1| \
- $(AWK) -fmdoc2man.awk >$(srcdir)/tmux.1.man; \
+ $(AWK) -f$(srcdir)/mdoc2man.awk >$(srcdir)/tmux.1.man; \
fi
- $(MKDIR_P) $(DESTDIR)$(mandir)/man1
+ $(mkdir_p) $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(srcdir)/tmux.1.@MANFORMAT@ \
$(DESTDIR)$(mandir)/man1/tmux.1
@@ -267,4 +262,4 @@ update-index.html:
convert "$$i" -resize 200x150 "small-$$i"; \
done \
)
- sed "s/%%VERSION%%/${VERSION}/g" www/index.html.in >www/index.html
+ sed "s/%%RELEASE%%/${RELEASE}/g" www/index.html.in >www/index.html
diff --git a/SYNCING b/SYNCING
index eba24177..218685c3 100644
--- a/SYNCING
+++ b/SYNCING
@@ -131,6 +131,15 @@ And if happy:
% git push origin master
+Keeping an eye on libutil in OpenBSD
+====================================
+
+A lot of the compat/ code in tmux comes from libutil, especially imsg.
+Sometimes the API can change, etc., which might cause interesting problems
+trying to run the portable version of tmux. It's worth checking
+periodically for any changes to libutil in OpenBSD and syncing those files
+to compat/ as and when appropriate.
+
Release tmux for next version
=============================
diff --git a/TODO b/TODO
index b9a83fb4..a0a7570a 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,4 @@
- command bits and pieces:
- * use "--" to mark start of command w/ neww etc to avoid quoting
* why doesn't command-prompt work if made read-only?
* allow multiple targets: fnmatch for -t/-c, for example detach all
clients with -t*
@@ -20,10 +19,10 @@
* way to set socket path from config file
- format improvements:
+ * last bits of status_replace into formats?
* option to quote format (#{session_name:quoted})
* formats need conditions for >0 (for #P)
* some way to pad # stuff with spaces, #!2T maybe
- * status stuff is redundant with formats
* last window update time and format for it
* formats to show if a window is linked into multiple sessions, into
multiple attached sessions, and is the active window in multiple
@@ -33,7 +32,7 @@
* choose-pane command (augment choose-tree to do this?)
* choose-mode and copy-mode are very similar, make choose-mode a subset?
* flag to choose-* for sort order
- * choose mode would be better per client than per window
+ * choose mode would be better per client than per window?
* two choices (first one then second, for swap-pane and join-pane)
- improve monitor-*:
@@ -44,11 +43,29 @@
- improve mouse support:
* bind commands to mouse in different areas?
- * more fine-grained options
+ * more fine-grained options?
* commands executed when clicking on a pattern (URL)
- * send arrow key sequences for mouse scroll wheel in alternate screen
* mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets
the flag on w/o checking the others before calling tty_update_mode)
+ * mouse can be like normal key bindings?
+ - {button-{1,2,3},wheel-{up,down}}-{status,pane,border} and
+ drag-{start,end}-{status,pane,border} plus the modifiers
+ - resize and copy can be special cases - once you call something
+ like copy-mode -M or resize-pane -M to start the drag, it tracks
+ mouse until you call -m to stop the drag. or just keep drags
+ entirely special?
+ - what happens with stuff that wants mouse inside? especially for
+ pane clicks which need to run command AND pass event through
+ (like mouse-select-pane). maybe just a flag to say whether it
+ always runs or only if pane hasn't taken mouse? or it could be
+ eg bind Button1Pane "select-pane -t=; send-keys -Mt='
+ - also need a) some way to tell commands bound to key which
+ window or pane the mouse key binding applies to (maybe a new
+ special char in target, or pass targets through formats?) b) a
+ way to bind repeat count to mode keys so that wheel up/down can
+ do multiple lines c) send-keys -M to pass a mouse event through?
+ - what does the mouse->KEYC_* conversion and find-the-pane bit?
+ server_client_handle_key?
- hooks!
@@ -58,18 +75,15 @@
* split-window -> split-pane??
- better UTF-8 support:
- * #22T can split in the middle of UTF-8 characters!
* window names and titles
* message display
* prompt input
* multibyte key input
- * buffer_sample and the choose-* could show UTF-8 properly
- copy/paste improvements:
* incremental searching
* append to buffer
* paste w/o trailing whitespace
- * named buffers and allow gaps in the stack
* command to toggle selection not to move it in copy-mode
- layout stuff
@@ -83,14 +97,16 @@
panelink to replace layout_cell
* way to set hints/limits about pane size for resizing
* panning over window (window larger than visible)
+ * a mode where one application can cross two panes (ie x|y, width =
+ COLUMNS/2 but height = ROWS * 2)
+ * general key to space cells out evenly (horiz or vert) within their
+ parent cell (could replace even-vert/even-horiz layouts)
- terminfo bits
* use a better termcap internally instead of screen, perhaps xterm
* use screen-256color when started on 256 colour terminal?
* need a tmux terminfo entry to document the extensions we are using in
upstream terminfo
- * support title stack, both internally and externally (restore on
- detach) http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
- code cleanup
* instead of separate window and session options, just one master
@@ -116,18 +132,24 @@
tell when in the config file - then we use cmdq->c if we need a
client w/o a session else cmd_current_client
* optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx
+ * cmd_find_* could be much simpler - parse everything the same, only
+ difference is what to choose when not given a ":" or "." (such as a
+ plain "0" could be session, window or pane). So just cmd_find_target
+ with a type (session, window, or pane)..
- miscellaneous
* way to keep a job running just read its last line of output for #()
- link panes into multiple windows
+ * link panes into multiple windows
* live update: server started with -U connects to server, requests
sessions and windows, receives file descriptors
* there are inconsistencies in what we get from old shell and what
- comes from config for new sessions and windows
+ comes from config for new sessions and windows. likewise, panes and
+ jobs and run-shell and lock command all start with slightly different
+ environments
* multiline status line?
* bind commands to key sequences -- make it so ALL keys go through a
table, first an implicit table in which C-b is the only default
binding to a command that says "next key from $othertable" and so
on. means -n can go away as well
-
-
+ * customizable command aliases
+ * any remaining clients in wait-for should be woken when server exits
diff --git a/arguments.c b/arguments.c
index d4e5e53f..05ff97eb 100644
--- a/arguments.c
+++ b/arguments.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,7 @@
#include <sys/types.h>
+#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -125,7 +126,7 @@ args_free(struct args *args)
size_t
args_print(struct args *args, char *buf, size_t len)
{
- size_t off;
+ size_t off, used;
int i;
const char *quotes;
struct args_entry *entry;
@@ -165,9 +166,12 @@ args_print(struct args *args, char *buf, size_t len)
quotes = "\"";
else
quotes = "";
- off += xsnprintf(buf + off, len - off, "%s-%c %s%s%s",
+ used = xsnprintf(buf + off, len - off, "%s-%c %s%s%s",
off != 0 ? " " : "", entry->flag, quotes, entry->value,
quotes);
+ if (used > len - off)
+ used = len - off;
+ off += used;
}
/* And finally the argument vector. */
@@ -181,8 +185,11 @@ args_print(struct args *args, char *buf, size_t len)
quotes = "\"";
else
quotes = "";
- off += xsnprintf(buf + off, len - off, "%s%s%s%s",
+ used = xsnprintf(buf + off, len - off, "%s%s%s%s",
off != 0 ? " " : "", quotes, args->argv[i], quotes);
+ if (used > len - off)
+ used = len - off;
+ off += used;
}
return (off);
diff --git a/array.h b/array.h
index 11e963bc..2c70c310 100644
--- a/array.h
+++ b/array.h
@@ -39,10 +39,10 @@
fatalx("size too big"); \
if ((a)->space == 0) { \
(a)->space = ARRAY_INITIALSPACE(a); \
- (a)->list = xrealloc((a)->list, 1, (a)->space); \
+ (a)->list = xrealloc((a)->list, (a)->space); \
} \
while ((a)->space <= ((a)->num + (n)) * ARRAY_ITEMSIZE(a)) { \
- (a)->list = xrealloc((a)->list, 2, (a)->space); \
+ (a)->list = xreallocarray((a)->list, 2, (a)->space); \
(a)->space *= 2; \
} \
} while (0)
diff --git a/attributes.c b/attributes.c
index f9871108..84e4f9c6 100644
--- a/attributes.c
+++ b/attributes.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
diff --git a/cfg.c b/cfg.c
index bfcdaea4..b3b86e76 100644
--- a/cfg.c
+++ b/cfg.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -17,7 +17,6 @@
*/
#include <sys/types.h>
-#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
@@ -30,16 +29,17 @@
struct cmd_q *cfg_cmd_q;
int cfg_finished;
int cfg_references;
-struct causelist cfg_causes;
+ARRAY_DECL (, char *) cfg_causes = ARRAY_INITIALIZER;
struct client *cfg_client;
int
load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
{
FILE *f;
- u_int n, found;
- char *buf, *copy, *line, *cause1, *msg;
- size_t len, oldlen;
+ char delim[3] = { '\\', '\\', '\0' };
+ u_int found;
+ size_t line = 0;
+ char *buf, *cause1, *p;
struct cmd_list *cmdlist;
log_debug("loading %s", path);
@@ -48,60 +48,29 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
return (-1);
}
- n = found = 0;
- line = NULL;
- while ((buf = fgetln(f, &len))) {
- /* Trim \n. */
- if (buf[len - 1] == '\n')
- len--;
- log_debug("%s: %.*s", path, (int)len, buf);
-
- /* Current line is the continuation of the previous one. */
- if (line != NULL) {
- oldlen = strlen(line);
- line = xrealloc(line, 1, oldlen + len + 1);
- } else {
- oldlen = 0;
- line = xmalloc(len + 1);
- }
-
- /* Append current line to the previous. */
- memcpy(line + oldlen, buf, len);
- line[oldlen + len] = '\0';
- n++;
-
- /* Continuation: get next line? */
- len = strlen(line);
- if (len > 0 && line[len - 1] == '\\') {
- line[len - 1] = '\0';
-
- /* Ignore escaped backslash at EOL. */
- if (len > 1 && line[len - 2] != '\\')
- continue;
- }
- copy = line;
- line = NULL;
+ found = 0;
+ while ((buf = fparseln(f, NULL, &line, delim, 0))) {
+ log_debug("%s: %s", path, buf);
/* Skip empty lines. */
- buf = copy;
- while (isspace((u_char)*buf))
- buf++;
- if (*buf == '\0') {
- free(copy);
+ p = buf;
+ while (isspace((u_char) *p))
+ p++;
+ if (*p == '\0') {
+ free(buf);
continue;
}
/* Parse and run the command. */
- if (cmd_string_parse(buf, &cmdlist, path, n, &cause1) != 0) {
- free(copy);
+ if (cmd_string_parse(p, &cmdlist, path, line, &cause1) != 0) {
+ free(buf);
if (cause1 == NULL)
continue;
- xasprintf(&msg, "%s:%u: %s", path, n, cause1);
- ARRAY_ADD(&cfg_causes, msg);
+ cfg_add_cause("%s:%zu: %s", path, line, cause1);
free(cause1);
continue;
}
- free(copy);
+ free(buf);
if (cmdlist == NULL)
continue;
@@ -109,8 +78,6 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
cmd_list_free(cmdlist);
found++;
}
- if (line != NULL)
- free(line);
fclose(f);
return (found);
@@ -145,6 +112,33 @@ cfg_default_done(unused struct cmd_q *cmdq)
}
void
+cfg_add_cause(const char* fmt, ...)
+{
+ va_list ap;
+ char* msg;
+
+ va_start(ap, fmt);
+ xvasprintf(&msg, fmt, ap);
+ va_end (ap);
+
+ ARRAY_ADD(&cfg_causes, msg);
+}
+
+void
+cfg_print_causes(struct cmd_q *cmdq)
+{
+ char *cause;
+ u_int i;
+
+ for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
+ cause = ARRAY_ITEM(&cfg_causes, i);
+ cmdq_print(cmdq, "%s", cause);
+ free(cause);
+ }
+ ARRAY_FREE(&cfg_causes);
+}
+
+void
cfg_show_causes(struct session *s)
{
struct window_pane *wp;
diff --git a/client.c b/client.c
index 277efb65..042ec920 100644
--- a/client.c
+++ b/client.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,7 +26,7 @@
#include <errno.h>
#include <event.h>
#include <fcntl.h>
-#include <pwd.h>
+#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -78,13 +78,18 @@ client_get_lock(char *lockfile)
if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1)
fatal("open failed");
+ log_debug("lock file is %s", lockfile);
- if (lockf(lockfd, F_TLOCK, 0) == -1 && errno == EAGAIN) {
- while (lockf(lockfd, F_LOCK, 0) == -1 && errno == EINTR)
+ if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
+ log_debug("flock failed: %s", strerror(errno));
+ if (errno != EAGAIN)
+ return (lockfd);
+ while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR)
/* nothing */;
close(lockfd);
return (-1);
}
+ log_debug("flock succeeded");
return (lockfd);
}
@@ -95,8 +100,8 @@ client_connect(char *path, int start_server)
{
struct sockaddr_un sa;
size_t size;
- int fd, lockfd;
- char *lockfile;
+ int fd, lockfd = -1, locked = 0;
+ char *lockfile = NULL;
memset(&sa, 0, sizeof sa);
sa.sun_family = AF_UNIX;
@@ -105,29 +110,48 @@ client_connect(char *path, int start_server)
errno = ENAMETOOLONG;
return (-1);
}
+ log_debug("socket is %s", path);
retry:
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
fatal("socket failed");
+ log_debug("trying connect");
if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
+ log_debug("connect failed: %s", strerror(errno));
if (errno != ECONNREFUSED && errno != ENOENT)
goto failed;
if (!start_server)
goto failed;
close(fd);
- xasprintf(&lockfile, "%s.lock", path);
- if ((lockfd = client_get_lock(lockfile)) == -1) {
- free(lockfile);
+ if (!locked) {
+ xasprintf(&lockfile, "%s.lock", path);
+ if ((lockfd = client_get_lock(lockfile)) == -1) {
+ log_debug("didn't get lock");
+ free(lockfile);
+ goto retry;
+ }
+ log_debug("got lock");
+
+ /*
+ * Always retry at least once, even if we got the lock,
+ * because another client could have taken the lock,
+ * started the server and released the lock between our
+ * connect() and flock().
+ */
+ locked = 1;
goto retry;
}
+
if (unlink(path) != 0 && errno != ENOENT) {
free(lockfile);
close(lockfd);
return (-1);
}
fd = server_start(lockfd, lockfile);
+ }
+ if (locked) {
free(lockfile);
close(lockfd);
}
@@ -234,7 +258,7 @@ client_main(int argc, char **argv, int flags)
return (1);
}
- /* Initialise the client socket and start the server. */
+ /* Initialize the client socket and start the server. */
fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER);
if (fd == -1) {
fprintf(stderr, "failed to connect to server: %s\n",
@@ -292,7 +316,7 @@ client_main(int argc, char **argv, int flags)
/* Prepare command for server. */
data->argc = argc;
- if (cmd_pack_argv(argc, argv, (char*)(data + 1), size) != 0) {
+ if (cmd_pack_argv(argc, argv, (char *)(data + 1), size) != 0) {
fprintf(stderr, "command too long\n");
free(data);
return (1);
@@ -374,7 +398,7 @@ client_write_one(enum msgtype type, int fd, const void *buf, size_t len)
int retval;
retval = imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, fd,
- (void*)buf, len);
+ (void *)buf, len);
if (retval != 1)
return (-1);
return (0);
@@ -414,15 +438,11 @@ client_signal(int sig, unused short events, unused void *data)
struct sigaction sigact;
int status;
- if (!client_attached) {
- switch (sig) {
- case SIGCHLD:
- waitpid(WAIT_ANY, &status, WNOHANG);
- break;
- case SIGTERM:
+ if (sig == SIGCHLD)
+ waitpid(WAIT_ANY, &status, WNOHANG);
+ else if (!client_attached) {
+ if (sig == SIGTERM)
event_loopexit(NULL);
- break;
- }
} else {
switch (sig) {
case SIGHUP:
@@ -474,7 +494,7 @@ client_callback(unused int fd, short events, void *data)
}
if (events & EV_WRITE) {
- if (msgbuf_write(&client_ibuf.w) < 0 && errno != EAGAIN)
+ if (msgbuf_write(&client_ibuf.w) <= 0 && errno != EAGAIN)
goto lost_server;
}
diff --git a/clock.c b/clock.c
deleted file mode 100644
index ec742884..00000000
--- a/clock.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/* $Id$ */
-
-/*
- * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include <string.h>
-#include <time.h>
-
-#include "tmux.h"
-
-const char clock_table[14][5][5] = {
- { { 1,1,1,1,1 }, /* 0 */
- { 1,0,0,0,1 },
- { 1,0,0,0,1 },
- { 1,0,0,0,1 },
- { 1,1,1,1,1 } },
- { { 0,0,0,0,1 }, /* 1 */
- { 0,0,0,0,1 },
- { 0,0,0,0,1 },
- { 0,0,0,0,1 },
- { 0,0,0,0,1 } },
- { { 1,1,1,1,1 }, /* 2 */
- { 0,0,0,0,1 },
- { 1,1,1,1,1 },
- { 1,0,0,0,0 },
- { 1,1,1,1,1 } },
- { { 1,1,1,1,1 }, /* 3 */
- { 0,0,0,0,1 },
- { 1,1,1,1,1 },
- { 0,0,0,0,1 },
- { 1,1,1,1,1 } },
- { { 1,0,0,0,1 }, /* 4 */
- { 1,0,0,0,1 },
- { 1,1,1,1,1 },
- { 0,0,0,0,1 },
- { 0,0,0,0,1 } },
- { { 1,1,1,1,1 }, /* 5 */
- { 1,0,0,0,0 },
- { 1,1,1,1,1 },
- { 0,0,0,0,1 },
- { 1,1,1,1,1 } },
- { { 1,1,1,1,1 }, /* 6 */
- { 1,0,0,0,0 },
- { 1,1,1,1,1 },
- { 1,0,0,0,1 },
- { 1,1,1,1,1 } },
- { { 1,1,1,1,1 }, /* 7 */
- { 0,0,0,0,1 },
- { 0,0,0,0,1 },
- { 0,0,0,0,1 },
- { 0,0,0,0,1 } },
- { { 1,1,1,1,1 }, /* 8 */
- { 1,0,0,0,1 },
- { 1,1,1,1,1 },
- { 1,0,0,0,1 },
- { 1,1,1,1,1 } },
- { { 1,1,1,1,1 }, /* 9 */
- { 1,0,0,0,1 },
- { 1,1,1,1,1 },
- { 0,0,0,0,1 },
- { 1,1,1,1,1 } },
- { { 0,0,0,0,0 }, /* : */
- { 0,0,1,0,0 },
- { 0,0,0,0,0 },
- { 0,0,1,0,0 },
- { 0,0,0,0,0 } },
- { { 1,1,1,1,1 }, /* A */
- { 1,0,0,0,1 },
- { 1,1,1,1,1 },
- { 1,0,0,0,1 },
- { 1,0,0,0,1 } },
- { { 1,1,1,1,1 }, /* P */
- { 1,0,0,0,1 },
- { 1,1,1,1,1 },
- { 1,0,0,0,0 },
- { 1,0,0,0,0 } },
- { { 1,0,0,0,1 }, /* M */
- { 1,1,0,1,1 },
- { 1,0,1,0,1 },
- { 1,0,0,0,1 },
- { 1,0,0,0,1 } },
-};
-
-void
-clock_draw(struct screen_write_ctx *ctx, int colour, int style)
-{
- struct screen *s = ctx->s;
- struct grid_cell gc;
- char tim[64], *ptr;
- time_t t;
- struct tm *tm;
- u_int i, j, x, y, idx;
-
- t = time(NULL);
- tm = localtime(&t);
- if (style == 0) {
- strftime(tim, sizeof tim, "%l:%M ", localtime(&t));
- if (tm->tm_hour >= 12)
- strlcat(tim, "PM", sizeof tim);
- else
- strlcat(tim, "AM", sizeof tim);
- } else
- strftime(tim, sizeof tim, "%H:%M", tm);
-
-
- screen_write_clearscreen(ctx);
-
- if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) {
- if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) {
- x = (screen_size_x(s) / 2) - (strlen(tim) / 2);
- y = screen_size_y(s) / 2;
- screen_write_cursormove(ctx, x, y);
-
- memcpy(&gc, &grid_default_cell, sizeof gc);
- colour_set_fg(&gc, colour);
- screen_write_puts(ctx, &gc, "%s", tim);
- }
- return;
- }
-
- x = (screen_size_x(s) / 2) - 3 * strlen(tim);
- y = (screen_size_y(s) / 2) - 3;
-
- memcpy(&gc, &grid_default_cell, sizeof gc);
- colour_set_bg(&gc, colour);
- for (ptr = tim; *ptr != '\0'; ptr++) {
- if (*ptr >= '0' && *ptr <= '9')
- idx = *ptr - '0';
- else if (*ptr == ':')
- idx = 10;
- else if (*ptr == 'A')
- idx = 11;
- else if (*ptr == 'P')
- idx = 12;
- else if (*ptr == 'M')
- idx = 13;
- else {
- x += 6;
- continue;
- }
-
- for (j = 0; j < 5; j++) {
- for (i = 0; i < 5; i++) {
- screen_write_cursormove(ctx, x + i, y + j);
- if (clock_table[idx][j][i])
- screen_write_putc(ctx, &gc, ' ');
- }
- }
- x += 6;
- }
-}
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 8094d78b..a67ec82c 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -37,7 +37,6 @@ const struct cmd_entry cmd_attach_session_entry = {
"c:drt:", 0, 0,
"[-dr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
CMD_CANTNEST|CMD_STARTSERVER,
- NULL,
cmd_attach_session_exec
};
@@ -107,11 +106,8 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
if (cflag != NULL) {
ft = format_create();
- if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
- format_client(ft, c);
- format_session(ft, s);
- format_winlink(ft, s, s->curw);
- format_window_pane(ft, s->curw->window->active);
+ format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s,
+ NULL, NULL);
cp = format_expand(ft, cflag);
format_free(ft);
@@ -132,7 +128,7 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
server_redraw_client(cmdq->client);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
} else {
- if (server_client_open(cmdq->client, s, &cause) != 0) {
+ if (server_client_open(cmdq->client, &cause) != 0) {
cmdq_error(cmdq, "open terminal failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
@@ -140,11 +136,8 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
if (cflag != NULL) {
ft = format_create();
- if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
- format_client(ft, c);
- format_session(ft, s);
- format_winlink(ft, s, s->curw);
- format_window_pane(ft, s->curw->window->active);
+ format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s,
+ NULL, NULL);
cp = format_expand(ft, cflag);
format_free(ft);
diff --git a/cmd-bind-key.c b/cmd-bind-key.c
index 4ff3ac84..5d68d486 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,14 +29,13 @@
enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmd_q *);
-enum cmd_retval cmd_bind_key_table(struct cmd *, struct cmd_q *, int);
+enum cmd_retval cmd_bind_key_mode_table(struct cmd *, struct cmd_q *, int);
const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind",
"cnrt:", 1, -1,
- "[-cnr] [-t key-table] key command [arguments]",
+ "[-cnr] [-t mode-table] key command [arguments]",
0,
- NULL,
cmd_bind_key_exec
};
@@ -67,7 +66,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
if (args_has(args, 't'))
- return (cmd_bind_key_table(self, cmdq, key));
+ return (cmd_bind_key_mode_table(self, cmdq, key));
cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, NULL, 0,
&cause);
@@ -84,7 +83,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
enum cmd_retval
-cmd_bind_key_table(struct cmd *self, struct cmd_q *cmdq, int key)
+cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, int key)
{
struct args *args = self->args;
const char *tablename;
diff --git a/cmd-break-pane.c b/cmd-break-pane.c
index d0a5a450..a1da0a3a 100644
--- a/cmd-break-pane.c
+++ b/cmd-break-pane.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,6 +26,8 @@
* Break pane off into a window.
*/
+#define BREAK_PANE_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
+
enum cmd_retval cmd_break_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_break_pane_entry = {
@@ -33,7 +35,6 @@ const struct cmd_entry cmd_break_pane_entry = {
"dPF:t:", 0, 0,
"[-dP] [-F format] " CMD_TARGET_PANE_USAGE,
0,
- NULL,
cmd_break_pane_exec
};
@@ -48,7 +49,6 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
char *name;
char *cause;
int base_idx;
- struct client *c;
struct format_tree *ft;
const char *template;
char *cp;
@@ -65,16 +65,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
server_unzoom_window(w);
TAILQ_REMOVE(&w->panes, wp, entry);
- if (wp == w->active) {
- w->active = w->last;
- w->last = NULL;
- if (w->active == NULL) {
- w->active = TAILQ_PREV(wp, window_panes, entry);
- if (w->active == NULL)
- w->active = TAILQ_NEXT(wp, entry);
- }
- } else if (wp == w->last)
- w->last = NULL;
+ window_lost_pane(w, wp);
layout_close_pane(wp);
w = wp->window = window_create1(s->sx, s->sy);
@@ -98,11 +89,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
template = BREAK_PANE_TEMPLATE;
ft = format_create();
- if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
- format_client(ft, c);
- format_session(ft, s);
- format_winlink(ft, s, wl);
- format_window_pane(ft, wp);
+ format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, wl, wp);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c
index e157e3cb..ce60b4c5 100644
--- a/cmd-capture-pane.c
+++ b/cmd-capture-pane.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
@@ -38,17 +38,16 @@ char *cmd_capture_pane_history(struct args *, struct cmd_q *,
const struct cmd_entry cmd_capture_pane_entry = {
"capture-pane", "capturep",
"ab:CeE:JpPqS:t:", 0, 0,
- "[-aCeJpPq] [-b buffer-index] [-E end-line] [-S start-line]"
+ "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] [-S start-line]"
CMD_TARGET_PANE_USAGE,
0,
- NULL,
cmd_capture_pane_exec
};
char *
cmd_capture_pane_append(char *buf, size_t *len, char *line, size_t linelen)
{
- buf = xrealloc(buf, 1, *len + linelen + 1);
+ buf = xrealloc(buf, *len + linelen + 1);
memcpy(buf + *len, line, linelen);
*len += linelen;
return (buf);
@@ -94,6 +93,7 @@ cmd_capture_pane_history(struct args *args, struct cmd_q *cmdq,
int n, with_codes, escape_c0, join_lines;
u_int i, sx, top, bottom, tmp;
char *cause, *buf, *line;
+ const char *Sflag, *Eflag;
size_t linelen;
sx = screen_size_x(&wp->base);
@@ -109,27 +109,37 @@ cmd_capture_pane_history(struct args *args, struct cmd_q *cmdq,
} else
gd = wp->base.grid;
- n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
- if (cause != NULL) {
- top = gd->hsize;
- free(cause);
- } else if (n < 0 && (u_int) -n > gd->hsize)
+ Sflag = args_get(args, 'S');
+ if (Sflag != NULL && strcmp(Sflag, "-") == 0)
top = 0;
- else
- top = gd->hsize + n;
- if (top > gd->hsize + gd->sy - 1)
- top = gd->hsize + gd->sy - 1;
+ else {
+ n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
+ if (cause != NULL) {
+ top = gd->hsize;
+ free(cause);
+ } else if (n < 0 && (u_int) -n > gd->hsize)
+ top = 0;
+ else
+ top = gd->hsize + n;
+ if (top > gd->hsize + gd->sy - 1)
+ top = gd->hsize + gd->sy - 1;
+ }
- n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
- if (cause != NULL) {
- bottom = gd->hsize + gd->sy - 1;
- free(cause);
- } else if (n < 0 && (u_int) -n > gd->hsize)
- bottom = 0;
- else
- bottom = gd->hsize + n;
- if (bottom > gd->hsize + gd->sy - 1)
+ Eflag = args_get(args, 'E');
+ if (Eflag != NULL && strcmp(Eflag, "-") == 0)
bottom = gd->hsize + gd->sy - 1;
+ else {
+ n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
+ if (cause != NULL) {
+ bottom = gd->hsize + gd->sy - 1;
+ free(cause);
+ } else if (n < 0 && (u_int) -n > gd->hsize)
+ bottom = 0;
+ else
+ bottom = gd->hsize + n;
+ if (bottom > gd->hsize + gd->sy - 1)
+ bottom = gd->hsize + gd->sy - 1;
+ }
if (bottom < top) {
tmp = bottom;
@@ -165,8 +175,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c;
struct window_pane *wp;
char *buf, *cause;
- int buffer;
- u_int limit;
+ const char *bufname;
size_t len;
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
@@ -192,23 +201,15 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
} else {
- limit = options_get_number(&global_options, "buffer-limit");
- if (!args_has(args, 'b')) {
- paste_add(&global_buffers, buf, len, limit);
- return (CMD_RETURN_NORMAL);
- }
- buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
- if (cause != NULL) {
- cmdq_error(cmdq, "buffer %s", cause);
- free(buf);
- free(cause);
- return (CMD_RETURN_ERROR);
- }
+ bufname = NULL;
+ if (args_has(args, 'b'))
+ bufname = args_get(args, 'b');
- if (paste_replace(&global_buffers, buffer, buf, len) != 0) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ if (paste_set(buf, len, bufname, &cause) != 0) {
+ cmdq_error(cmdq, "%s", cause);
free(buf);
+ free(cause);
return (CMD_RETURN_ERROR);
}
}
diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c
index d79f6fdc..33125a0e 100644
--- a/cmd-choose-buffer.c
+++ b/cmd-choose-buffer.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,6 +27,9 @@
* Enter choice mode to choose a buffer.
*/
+#define CHOOSE_BUFFER_TEMPLATE \
+ "#{buffer_name}: #{buffer_size} bytes: #{buffer_sample}"
+
enum cmd_retval cmd_choose_buffer_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_choose_buffer_entry = {
@@ -34,7 +37,6 @@ const struct cmd_entry cmd_choose_buffer_entry = {
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
- NULL,
cmd_choose_buffer_exec
};
@@ -49,6 +51,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
char *action, *action_data;
const char *template;
u_int idx;
+ int utf8flag;
if ((c = cmd_current_client(cmdq)) == NULL) {
cmdq_error(cmdq, "no client available");
@@ -60,8 +63,9 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
+ utf8flag = options_get_number(&wl->window->options, "utf8");
- if (paste_get_top(&global_buffers) == NULL)
+ if (paste_get_top() == NULL)
return (CMD_RETURN_NORMAL);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
@@ -73,19 +77,20 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
action = xstrdup("paste-buffer -b '%%'");
idx = 0;
- while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
+ pb = NULL;
+ while ((pb = paste_walk(pb)) != NULL) {
cdata = window_choose_data_create(TREE_OTHER, c, c->session);
- cdata->idx = idx - 1;
+ cdata->idx = idx;
cdata->ft_template = xstrdup(template);
- format_add(cdata->ft, "line", "%u", idx - 1);
- format_paste_buffer(cdata->ft, pb);
+ format_defaults_paste_buffer(cdata->ft, pb, utf8flag);
- xasprintf(&action_data, "%u", idx - 1);
+ xasprintf(&action_data, "%s", pb->name);
cdata->command = cmd_template_replace(action, action_data, 1);
free(action_data);
window_choose_add(wl->window->active, cdata);
+ idx++;
}
free(action);
diff --git a/cmd-choose-client.c b/cmd-choose-client.c
index 93671987..3002f7ba 100644
--- a/cmd-choose-client.c
+++ b/cmd-choose-client.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,6 +27,12 @@
* Enter choice mode to choose a client.
*/
+#define CHOOSE_CLIENT_TEMPLATE \
+ "#{client_tty}: #{session_name} " \
+ "[#{client_width}x#{client_height} #{client_termname}]" \
+ "#{?client_utf8, (utf8),}#{?client_readonly, (ro),} " \
+ "(last used #{client_activity_string})"
+
enum cmd_retval cmd_choose_client_exec(struct cmd *, struct cmd_q *);
void cmd_choose_client_callback(struct window_choose_data *);
@@ -36,7 +42,6 @@ const struct cmd_entry cmd_choose_client_entry = {
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
- NULL,
cmd_choose_client_exec
};
@@ -89,8 +94,7 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq)
cdata->ft_template = xstrdup(template);
format_add(cdata->ft, "line", "%u", i);
- format_session(cdata->ft, c1->session);
- format_client(cdata->ft, c1);
+ format_defaults(cdata->ft, c1, NULL, NULL, NULL);
cdata->command = cmd_template_replace(action, c1->tty.path, 1);
diff --git a/cmd-choose-list.c b/cmd-choose-list.c
deleted file mode 100644
index c3caabba..00000000
--- a/cmd-choose-list.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* $Id$ */
-
-/*
- * Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <stdlib.h>
-
-#include <string.h>
-
-#include "tmux.h"
-
-#define CMD_CHOOSE_LIST_DEFAULT_TEMPLATE "run-shell '%%'"
-
-/*
- * Enter choose mode to choose a custom list.
- */
-
-enum cmd_retval cmd_choose_list_exec(struct cmd *, struct cmd_q *);
-
-const struct cmd_entry cmd_choose_list_entry = {
- "choose-list", NULL,
- "l:t:", 0, 1,
- "[-l items] " CMD_TARGET_WINDOW_USAGE "[template]",
- 0,
- NULL,
- cmd_choose_list_exec
-};
-
-enum cmd_retval
-cmd_choose_list_exec(struct cmd *self, struct cmd_q *cmdq)
-{
- struct args *args = self->args;
- struct client *c;
- struct winlink *wl;
- const char *list1;
- char *template, *item, *copy, *list;
- u_int idx;
-
- if ((c = cmd_current_client(cmdq)) == NULL) {
- cmdq_error(cmdq, "no client available");
- return (CMD_RETURN_ERROR);
- }
-
- if ((list1 = args_get(args, 'l')) == NULL)
- return (CMD_RETURN_ERROR);
-
- if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
- return (CMD_RETURN_ERROR);
-
- if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
- return (CMD_RETURN_NORMAL);
-
- if (args->argc != 0)
- template = xstrdup(args->argv[0]);
- else
- template = xstrdup(CMD_CHOOSE_LIST_DEFAULT_TEMPLATE);
-
- copy = list = xstrdup(list1);
- idx = 0;
- while ((item = strsep(&list, ",")) != NULL)
- {
- if (*item == '\0') /* no empty entries */
- continue;
- window_choose_add_item(wl->window->active, c, wl, item,
- template, idx);
- idx++;
- }
- free(copy);
-
- if (idx == 0) {
- free(template);
- window_pane_reset_mode(wl->window->active);
- return (CMD_RETURN_ERROR);
- }
-
- window_choose_ready(wl->window->active, 0, NULL);
-
- free(template);
-
- return (CMD_RETURN_NORMAL);
-}
diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c
index be3bd69a..823d0423 100644
--- a/cmd-choose-tree.c
+++ b/cmd-choose-tree.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
@@ -32,6 +32,15 @@
* Enter choice mode to choose a session and/or window.
*/
+#define CHOOSE_TREE_SESSION_TEMPLATE \
+ "#{session_name}: #{session_windows} windows" \
+ "#{?session_grouped, (group ,}" \
+ "#{session_group}#{?session_grouped,),}" \
+ "#{?session_attached, (attached),}"
+#define CHOOSE_TREE_WINDOW_TEMPLATE \
+ "#{window_index}: #{window_name}#{window_flags} " \
+ "\"#{pane_title}\""
+
enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_choose_tree_entry = {
@@ -40,7 +49,6 @@ const struct cmd_entry cmd_choose_tree_entry = {
"[-suw] [-b session-template] [-c window template] [-S format] " \
"[-W format] " CMD_TARGET_WINDOW_USAGE,
0,
- NULL,
cmd_choose_tree_exec
};
@@ -49,7 +57,6 @@ const struct cmd_entry cmd_choose_session_entry = {
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
- NULL,
cmd_choose_tree_exec
};
@@ -58,7 +65,6 @@ const struct cmd_entry cmd_choose_window_entry = {
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
0,
- NULL,
cmd_choose_tree_exec
};
diff --git a/cmd-clear-history.c b/cmd-clear-history.c
index cce3ea18..e1342880 100644
--- a/cmd-clear-history.c
+++ b/cmd-clear-history.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,7 +31,6 @@ const struct cmd_entry cmd_clear_history_entry = {
"t:", 0, 0,
CMD_TARGET_PANE_USAGE,
0,
- NULL,
cmd_clear_history_exec
};
diff --git a/cmd-clock-mode.c b/cmd-clock-mode.c
index 50e4ab8b..80835813 100644
--- a/cmd-clock-mode.c
+++ b/cmd-clock-mode.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,7 +31,6 @@ const struct cmd_entry cmd_clock_mode_entry = {
"t:", 0, 0,
CMD_TARGET_PANE_USAGE,
0,
- NULL,
cmd_clock_mode_exec
};
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index 759d578b..22b1d84e 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,7 +29,6 @@
* Prompt for command in client.
*/
-void cmd_command_prompt_key_binding(struct cmd *, int);
enum cmd_retval cmd_command_prompt_exec(struct cmd *, struct cmd_q *);
int cmd_command_prompt_callback(void *, const char *);
@@ -40,7 +39,6 @@ const struct cmd_entry cmd_command_prompt_entry = {
"I:p:t:", 0, 1,
"[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
0,
- cmd_command_prompt_key_binding,
cmd_command_prompt_exec
};
@@ -54,34 +52,6 @@ struct cmd_command_prompt_cdata {
int idx;
};
-void
-cmd_command_prompt_key_binding(struct cmd *self, int key)
-{
- switch (key) {
- case '$':
- self->args = args_create(1, "rename-session '%%'");
- args_set(self->args, 'I', "#S");
- break;
- case ',':
- self->args = args_create(1, "rename-window '%%'");
- args_set(self->args, 'I', "#W");
- break;
- case '.':
- self->args = args_create(1, "move-window -t '%%'");
- break;
- case 'f':
- self->args = args_create(1, "find-window '%%'");
- break;
- case '\'':
- self->args = args_create(1, "select-window -t ':%%'");
- args_set(self->args, 'p', "index");
- break;
- default:
- self->args = args_create(0);
- break;
- }
-}
-
enum cmd_retval
cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq)
{
diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c
index 9266721f..0bf58449 100644
--- a/cmd-confirm-before.c
+++ b/cmd-confirm-before.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -16,6 +16,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/types.h>
+
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@@ -26,7 +28,6 @@
* Asks for confirmation before executing a command.
*/
-void cmd_confirm_before_key_binding(struct cmd *, int);
enum cmd_retval cmd_confirm_before_exec(struct cmd *, struct cmd_q *);
int cmd_confirm_before_callback(void *, const char *);
@@ -37,7 +38,6 @@ const struct cmd_entry cmd_confirm_before_entry = {
"p:t:", 1, 1,
"[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
0,
- cmd_confirm_before_key_binding,
cmd_confirm_before_exec
};
@@ -46,24 +46,6 @@ struct cmd_confirm_before_data {
struct client *client;
};
-void
-cmd_confirm_before_key_binding(struct cmd *self, int key)
-{
- switch (key) {
- case '&':
- self->args = args_create(1, "kill-window");
- args_set(self->args, 'p', "kill-window #W? (y/n)");
- break;
- case 'x':
- self->args = args_create(1, "kill-pane");
- args_set(self->args, 'p', "kill-pane #P? (y/n)");
- break;
- default:
- self->args = args_create(0);
- break;
- }
-}
-
enum cmd_retval
cmd_confirm_before_exec(struct cmd *self, struct cmd_q *cmdq)
{
diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c
index f11c7aff..89335296 100644
--- a/cmd-copy-mode.c
+++ b/cmd-copy-mode.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,6 @@
* Enter copy mode.
*/
-void cmd_copy_mode_key_binding(struct cmd *, int);
enum cmd_retval cmd_copy_mode_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_copy_mode_entry = {
@@ -32,18 +31,9 @@ const struct cmd_entry cmd_copy_mode_entry = {
"t:u", 0, 0,
"[-u] " CMD_TARGET_PANE_USAGE,
0,
- cmd_copy_mode_key_binding,
cmd_copy_mode_exec
};
-void
-cmd_copy_mode_key_binding(struct cmd *self, int key)
-{
- self->args = args_create(0);
- if (key == KEYC_PPAGE)
- args_set(self->args, 'u', NULL);
-}
-
enum cmd_retval
cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
{
diff --git a/cmd-delete-buffer.c b/cmd-delete-buffer.c
index b8f55db4..42268b78 100644
--- a/cmd-delete-buffer.c
+++ b/cmd-delete-buffer.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,7 +33,6 @@ const struct cmd_entry cmd_delete_buffer_entry = {
"b:", 0, 0,
CMD_BUFFER_USAGE,
0,
- NULL,
cmd_delete_buffer_exec
};
@@ -41,23 +40,16 @@ enum cmd_retval
cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
- char *cause;
- int buffer;
+ const char *bufname;
if (!args_has(args, 'b')) {
- paste_free_top(&global_buffers);
+ paste_free_top();
return (CMD_RETURN_NORMAL);
}
+ bufname = args_get(args, 'b');
- buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
- if (cause != NULL) {
- cmdq_error(cmdq, "buffer %s", cause);
- free(cause);
- return (CMD_RETURN_ERROR);
- }
-
- if (paste_free_index(&global_buffers, buffer) != 0) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ if (paste_free_name(bufname) != 0) {
+ cmdq_error(cmdq, "no buffer %s", bufname);
return (CMD_RETURN_ERROR);
}
diff --git a/cmd-detach-client.c b/cmd-detach-client.c
index fe4b2397..7f87d2c6 100644
--- a/cmd-detach-client.c
+++ b/cmd-detach-client.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,7 +33,14 @@ const struct cmd_entry cmd_detach_client_entry = {
"as:t:P", 0, 0,
"[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
CMD_READONLY,
- NULL,
+ cmd_detach_client_exec
+};
+
+const struct cmd_entry cmd_suspend_client_entry = {
+ "suspend-client", "suspendc",
+ "t:", 0, 0,
+ CMD_TARGET_CLIENT_USAGE,
+ 0,
cmd_detach_client_exec
};
@@ -41,11 +48,20 @@ enum cmd_retval
cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
- struct client *c, *c2;
+ struct client *c, *cloop;
struct session *s;
enum msgtype msgtype;
u_int i;
+ if (self->entry == &cmd_suspend_client_entry) {
+ if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
+ return (CMD_RETURN_ERROR);
+ tty_stop_tty(&c->tty);
+ c->flags |= CLIENT_SUSPENDED;
+ server_write_client(c, MSG_SUSPEND, NULL, 0);
+ return (CMD_RETURN_NORMAL);
+ }
+
if (args_has(args, 'P'))
msgtype = MSG_DETACHKILL;
else
@@ -57,32 +73,35 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
- c = ARRAY_ITEM(&clients, i);
- if (c == NULL || c->session != s)
+ cloop = ARRAY_ITEM(&clients, i);
+ if (cloop == NULL || cloop->session != s)
continue;
- server_write_client(c, msgtype, c->session->name,
- strlen(c->session->name) + 1);
+ server_write_client(cloop, msgtype,
+ cloop->session->name,
+ strlen(cloop->session->name) + 1);
}
- } else {
- c = cmd_find_client(cmdq, args_get(args, 't'), 0);
- if (c == NULL)
- return (CMD_RETURN_ERROR);
+ return (CMD_RETURN_STOP);
+ }
+
+ c = cmd_find_client(cmdq, args_get(args, 't'), 0);
+ if (c == NULL)
+ return (CMD_RETURN_ERROR);
- if (args_has(args, 'a')) {
- for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
- c2 = ARRAY_ITEM(&clients, i);
- if (c2 == NULL || c2->session == NULL ||
- c2 == c)
- continue;
- server_write_client(c2, msgtype,
- c2->session->name,
- strlen(c2->session->name) + 1);
- }
- } else {
- server_write_client(c, msgtype, c->session->name,
- strlen(c->session->name) + 1);
+ if (args_has(args, 'a')) {
+ for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
+ cloop = ARRAY_ITEM(&clients, i);
+ if (cloop == NULL || cloop->session == NULL)
+ continue;
+ if (cloop == c)
+ continue;
+ server_write_client(cloop, msgtype,
+ cloop->session->name,
+ strlen(cloop->session->name) + 1);
}
+ return (CMD_RETURN_NORMAL);
}
+ server_write_client(c, msgtype, c->session->name,
+ strlen(c->session->name) + 1);
return (CMD_RETURN_STOP);
}
diff --git a/cmd-display-message.c b/cmd-display-message.c
index 78752f86..0a61fd1e 100644
--- a/cmd-display-message.c
+++ b/cmd-display-message.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -27,6 +27,11 @@
* Displays a message in the status line.
*/
+#define DISPLAY_MESSAGE_TEMPLATE \
+ "[#{session_name}] #{window_index}:" \
+ "#{window_name}, current pane #{pane_index} " \
+ "- (%H:%M %d-%b-%y)"
+
enum cmd_retval cmd_display_message_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_display_message_entry = {
@@ -35,7 +40,6 @@ const struct cmd_entry cmd_display_message_entry = {
"[-p] [-c target-client] [-F format] " CMD_TARGET_PANE_USAGE
" [message]",
0,
- NULL,
cmd_display_message_exec
};
@@ -88,11 +92,7 @@ cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
template = DISPLAY_MESSAGE_TEMPLATE;
ft = format_create();
- if (c != NULL)
- format_client(ft, c);
- format_session(ft, s);
- format_winlink(ft, s, wl);
- format_window_pane(ft, wp);
+ format_defaults(ft, c, s, wl, wp);
t = time(NULL);
len = strftime(out, sizeof out, template, localtime(&t));
diff --git a/cmd-display-panes.c b/cmd-display-panes.c
index c137feef..9ce89712 100644
--- a/cmd-display-panes.c
+++ b/cmd-display-panes.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,7 +31,6 @@ const struct cmd_entry cmd_display_panes_entry = {
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
- NULL,
cmd_display_panes_exec
};
diff --git a/cmd-find-window.c b/cmd-find-window.c
index 647cc8fb..25155f7b 100644
--- a/cmd-find-window.c
+++ b/cmd-find-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,6 +28,11 @@
* Find window containing text.
*/
+#define FIND_WINDOW_TEMPLATE \
+ "#{window_index}: #{window_name} " \
+ "[#{window_width}x#{window_height}] " \
+ "(#{window_panes} panes) #{window_find_matches}"
+
enum cmd_retval cmd_find_window_exec(struct cmd *, struct cmd_q *);
void cmd_find_window_callback(struct window_choose_data *);
@@ -47,7 +52,6 @@ const struct cmd_entry cmd_find_window_entry = {
"F:CNt:T", 1, 4,
"[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
0,
- NULL,
cmd_find_window_exec
};
@@ -84,7 +88,8 @@ cmd_find_window_match_flags(struct args *args)
void
cmd_find_window_match(struct cmd_find_window_data_list *find_list,
- int match_flags, struct winlink *wl, const char *str, const char *searchstr)
+ int match_flags, struct winlink *wl, const char *str,
+ const char *searchstr)
{
struct cmd_find_window_data find_data;
struct window_pane *wp;
@@ -157,7 +162,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
xasprintf(&searchstr, "*%s*", str);
RB_FOREACH(wm, winlinks, &s->windows)
- cmd_find_window_match (&find_list, match_flags, wm, str, searchstr);
+ cmd_find_window_match(&find_list, match_flags, wm, str, searchstr);
free(searchstr);
if (ARRAY_LENGTH(&find_list) == 0) {
@@ -189,9 +194,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_add(cdata->ft, "line", "%u", i);
format_add(cdata->ft, "window_find_matches", "%s",
ARRAY_ITEM(&find_list, i).list_ctx);
- format_session(cdata->ft, s);
- format_winlink(cdata->ft, s, wm);
- format_window_pane(cdata->ft, wm->window->active);
+ format_defaults(cdata->ft, NULL, s, wm, NULL);
window_choose_add(wl->window->active, cdata);
}
@@ -199,6 +202,8 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
window_choose_ready(wl->window->active, 0, cmd_find_window_callback);
out:
+ for (i = 0; i < ARRAY_LENGTH(&find_list); i++)
+ free(ARRAY_ITEM(&find_list, i).list_ctx);
ARRAY_FREE(&find_list);
return (CMD_RETURN_NORMAL);
}
diff --git a/cmd-has-session.c b/cmd-has-session.c
deleted file mode 100644
index 38a92f61..00000000
--- a/cmd-has-session.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $Id$ */
-
-/*
- * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include "tmux.h"
-
-/*
- * Cause client to report an error and exit with 1 if session doesn't exist.
- */
-
-enum cmd_retval cmd_has_session_exec(struct cmd *, struct cmd_q *);
-
-const struct cmd_entry cmd_has_session_entry = {
- "has-session", "has",
- "t:", 0, 0,
- CMD_TARGET_SESSION_USAGE,
- 0,
- NULL,
- cmd_has_session_exec
-};
-
-enum cmd_retval
-cmd_has_session_exec(struct cmd *self, struct cmd_q *cmdq)
-{
- struct args *args = self->args;
-
- if (cmd_find_session(cmdq, args_get(args, 't'), 0) == NULL)
- return (CMD_RETURN_ERROR);
-
- return (CMD_RETURN_NORMAL);
-}
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index 9b6dcf30..8c6620da 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -37,10 +37,9 @@ void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if",
- "bt:", 2, 3,
- "[-b] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
+ "bFt:", 2, 3,
+ "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
0,
- NULL,
cmd_if_shell_exec
};
@@ -57,7 +56,8 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct cmd_if_shell_data *cdata;
- char *shellcmd;
+ char *shellcmd, *cmd, *cause;
+ struct cmd_list *cmdlist;
struct client *c;
struct session *s = NULL;
struct winlink *wl = NULL;
@@ -76,15 +76,30 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
}
ft = format_create();
- if (s != NULL)
- format_session(ft, s);
- if (s != NULL && wl != NULL)
- format_winlink(ft, s, wl);
- if (wp != NULL)
- format_window_pane(ft, wp);
+ format_defaults(ft, NULL, s, wl, wp);
shellcmd = format_expand(ft, args->argv[0]);
format_free(ft);
+ if (args_has(args, 'F')) {
+ cmd = NULL;
+ if (*shellcmd != '0' && *shellcmd != '\0')
+ cmd = args->argv[1];
+ else if (args->argc == 3)
+ cmd = args->argv[2];
+ if (cmd == NULL)
+ return (CMD_RETURN_NORMAL);
+ if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
+ if (cause != NULL) {
+ cmdq_error(cmdq, "%s", cause);
+ free(cause);
+ }
+ return (CMD_RETURN_ERROR);
+ }
+ cmdq_run(cmdq, cmdlist);
+ cmd_list_free(cmdlist);
+ return (CMD_RETURN_NORMAL);
+ }
+
cdata = xmalloc(sizeof *cdata);
cdata->cmd_if = xstrdup(args->argv[1]);
if (args->argc == 3)
diff --git a/cmd-join-pane.c b/cmd-join-pane.c
index 1a710cec..5603541a 100644
--- a/cmd-join-pane.c
+++ b/cmd-join-pane.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
@@ -28,7 +28,6 @@
* Join or move a pane into another (like split/swap/kill).
*/
-void cmd_join_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmd_q *);
enum cmd_retval join_pane(struct cmd *, struct cmd_q *, int);
@@ -38,7 +37,6 @@ const struct cmd_entry cmd_join_pane_entry = {
"bdhvp:l:s:t:", 0, 0,
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
- cmd_join_pane_key_binding,
cmd_join_pane_exec
};
@@ -47,24 +45,9 @@ const struct cmd_entry cmd_move_pane_entry = {
"bdhvp:l:s:t:", 0, 0,
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
- NULL,
cmd_join_pane_exec
};
-void
-cmd_join_pane_key_binding(struct cmd *self, int key)
-{
- switch (key) {
- case '%':
- self->args = args_create(0);
- args_set(self->args, 'h', NULL);
- break;
- default:
- self->args = args_create(0);
- break;
- }
-}
-
enum cmd_retval
cmd_join_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
@@ -138,11 +121,7 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
layout_close_pane(src_wp);
- if (src_w->active == src_wp) {
- src_w->active = TAILQ_PREV(src_wp, window_panes, entry);
- if (src_w->active == NULL)
- src_w->active = TAILQ_NEXT(src_wp, entry);
- }
+ window_lost_pane(src_w, src_wp);
TAILQ_REMOVE(&src_w->panes, src_wp, entry);
if (window_count_panes(src_w) == 0)
diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c
index bf486eb3..f4735fd2 100644
--- a/cmd-kill-pane.c
+++ b/cmd-kill-pane.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,7 +33,6 @@ const struct cmd_entry cmd_kill_pane_entry = {
"at:", 0, 0,
"[-a] " CMD_TARGET_PANE_USAGE,
0,
- NULL,
cmd_kill_pane_exec
};
diff --git a/cmd-kill-server.c b/cmd-kill-server.c
index 03016869..07d94302 100644
--- a/cmd-kill-server.c
+++ b/cmd-kill-server.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_kill_server_entry = {
"", 0, 0,
"",
0,
- NULL,
cmd_kill_server_exec
};
@@ -43,7 +42,6 @@ const struct cmd_entry cmd_start_server_entry = {
"", 0, 0,
"",
CMD_STARTSERVER,
- NULL,
cmd_kill_server_exec
};
diff --git a/cmd-kill-session.c b/cmd-kill-session.c
index 54b0c31b..d7e2a219 100644
--- a/cmd-kill-session.c
+++ b/cmd-kill-session.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_kill_session_entry = {
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
- NULL,
cmd_kill_session_exec
};
diff --git a/cmd-kill-window.c b/cmd-kill-window.c
index ca8fe3d6..d402acce 100644
--- a/cmd-kill-window.c
+++ b/cmd-kill-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,27 +31,51 @@ const struct cmd_entry cmd_kill_window_entry = {
"at:", 0, 0,
"[-a] " CMD_TARGET_WINDOW_USAGE,
0,
- NULL,
+ cmd_kill_window_exec
+};
+
+const struct cmd_entry cmd_unlink_window_entry = {
+ "unlink-window", "unlinkw",
+ "kt:", 0, 0,
+ "[-k] " CMD_TARGET_WINDOW_USAGE,
+ 0,
cmd_kill_window_exec
};
enum cmd_retval
cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
- struct args *args = self->args;
- struct winlink *wl, *wl2, *wl3;
- struct session *s;
+ struct args *args = self->args;
+ struct winlink *wl, *wl2, *wl3;
+ struct window *w;
+ struct session *s;
+ struct session_group *sg;
+ u_int references;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
+ w = wl->window;
- if (args_has(args, 'a')) {
- RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) {
- if (wl != wl2)
- server_kill_window(wl2->window);
+ if (self->entry == &cmd_unlink_window_entry) {
+ sg = session_group_find(s);
+ if (sg != NULL)
+ references = session_group_count(sg);
+ else
+ references = 1;
+ if (!args_has(self->args, 'k') && w->references == references) {
+ cmdq_error(cmdq, "window only linked to one session");
+ return (CMD_RETURN_ERROR);
}
- } else
- server_kill_window(wl->window);
+ server_unlink_window(s, wl);
+ } else {
+ if (args_has(args, 'a')) {
+ RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) {
+ if (wl != wl2)
+ server_kill_window(wl2->window);
+ }
+ } else
+ server_kill_window(wl->window);
+ }
recalculate_sizes();
return (CMD_RETURN_NORMAL);
diff --git a/cmd-link-window.c b/cmd-link-window.c
deleted file mode 100644
index d94eb38a..00000000
--- a/cmd-link-window.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* $Id$ */
-
-/*
- * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include <stdlib.h>
-
-#include "tmux.h"
-
-/*
- * Link a window into another session.
- */
-
-enum cmd_retval cmd_link_window_exec(struct cmd *, struct cmd_q *);
-
-const struct cmd_entry cmd_link_window_entry = {
- "link-window", "linkw",
- "dks:t:", 0, 0,
- "[-dk] " CMD_SRCDST_WINDOW_USAGE,
- 0,
- NULL,
- cmd_link_window_exec
-};
-
-enum cmd_retval
-cmd_link_window_exec(struct cmd *self, struct cmd_q *cmdq)
-{
- struct args *args = self->args;
- struct session *src, *dst;
- struct winlink *wl;
- char *cause;
- int idx, kflag, dflag;
-
- if ((wl = cmd_find_window(cmdq, args_get(args, 's'), &src)) == NULL)
- return (CMD_RETURN_ERROR);
- if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &dst)) == -2)
- return (CMD_RETURN_ERROR);
-
- kflag = args_has(self->args, 'k');
- dflag = args_has(self->args, 'd');
- if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
- cmdq_error(cmdq, "can't link window: %s", cause);
- free(cause);
- return (CMD_RETURN_ERROR);
- }
- recalculate_sizes();
-
- return (CMD_RETURN_NORMAL);
-}
diff --git a/cmd-list-buffers.c b/cmd-list-buffers.c
index 02a4183e..37571b80 100644
--- a/cmd-list-buffers.c
+++ b/cmd-list-buffers.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,6 +27,9 @@
* List paste buffers.
*/
+#define LIST_BUFFERS_TEMPLATE \
+ "#{buffer_name}: #{buffer_size} bytes: \"#{buffer_sample}\""
+
enum cmd_retval cmd_list_buffers_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_buffers_entry = {
@@ -34,7 +37,6 @@ const struct cmd_entry cmd_list_buffers_entry = {
"F:", 0, 0,
"[-F format]",
0,
- NULL,
cmd_list_buffers_exec
};
@@ -44,18 +46,16 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
struct paste_buffer *pb;
struct format_tree *ft;
- u_int idx;
char *line;
const char *template;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_BUFFERS_TEMPLATE;
- idx = 0;
- while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
+ pb = NULL;
+ while ((pb = paste_walk(pb)) != NULL) {
ft = format_create();
- format_add(ft, "line", "%u", idx - 1);
- format_paste_buffer(ft, pb);
+ format_defaults_paste_buffer(ft, pb, 0);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);
diff --git a/cmd-list-clients.c b/cmd-list-clients.c
index 904ec005..893a6d05 100644
--- a/cmd-list-clients.c
+++ b/cmd-list-clients.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,6 +28,11 @@
* List all clients.
*/
+#define LIST_CLIENTS_TEMPLATE \
+ "#{client_tty}: #{session_name} " \
+ "[#{client_width}x#{client_height} #{client_termname}]" \
+ "#{?client_utf8, (utf8),} #{?client_readonly, (ro),}"
+
enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_clients_entry = {
@@ -35,7 +40,6 @@ const struct cmd_entry cmd_list_clients_entry = {
"F:t:", 0, 0,
"[-F format] " CMD_TARGET_SESSION_USAGE,
CMD_READONLY,
- NULL,
cmd_list_clients_exec
};
@@ -70,8 +74,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq)
ft = format_create();
format_add(ft, "line", "%u", i);
- format_session(ft, c->session);
- format_client(ft, c);
+ format_defaults(ft, c, NULL, NULL, NULL);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);
diff --git a/cmd-list-commands.c b/cmd-list-commands.c
deleted file mode 100644
index 06e48378..00000000
--- a/cmd-list-commands.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* $Id$ */
-
-/*
- * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include "tmux.h"
-
-/*
- * List all commands with usages.
- */
-
-enum cmd_retval cmd_list_commands_exec(struct cmd *, struct cmd_q *);
-
-const struct cmd_entry cmd_list_commands_entry = {
- "list-commands", "lscm",
- "", 0, 0,
- "",
- 0,
- NULL,
- cmd_list_commands_exec
-};
-
-enum cmd_retval
-cmd_list_commands_exec(unused struct cmd *self, struct cmd_q *cmdq)
-{
- const struct cmd_entry **entryp;
-
- for (entryp = cmd_table; *entryp != NULL; entryp++) {
- if ((*entryp)->alias != NULL) {
- cmdq_print(cmdq, "%s (%s) %s", (*entryp)->name,
- (*entryp)->alias, (*entryp)->usage);
- } else {
- cmdq_print(cmdq, "%s %s", (*entryp)->name,
- (*entryp)->usage);
- }
- }
-
- return (CMD_RETURN_NORMAL);
-}
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index 615c5ce1..0733ee28 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,14 +27,23 @@
*/
enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmd_q *);
+
enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_q *);
+enum cmd_retval cmd_list_keys_commands(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_keys_entry = {
"list-keys", "lsk",
"t:", 0, 0,
"[-t key-table]",
0,
- NULL,
+ cmd_list_keys_exec
+};
+
+const struct cmd_entry cmd_list_commands_entry = {
+ "list-commands", "lscm",
+ "", 0, 0,
+ "",
+ 0,
cmd_list_keys_exec
};
@@ -48,6 +57,9 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
size_t used;
int width, keywidth;
+ if (self->entry == &cmd_list_commands_entry)
+ return (cmd_list_keys_commands(self, cmdq));
+
if (args_has(args, 't'))
return (cmd_list_keys_table(self, cmdq));
@@ -148,3 +160,22 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
+
+enum cmd_retval
+cmd_list_keys_commands(unused struct cmd *self, struct cmd_q *cmdq)
+{
+ const struct cmd_entry **entryp;
+ const struct cmd_entry *entry;
+
+ for (entryp = cmd_table; *entryp != NULL; entryp++) {
+ entry = *entryp;
+ if (entry->alias == NULL) {
+ cmdq_print(cmdq, "%s %s", entry->name, entry->usage);
+ continue;
+ }
+ cmdq_print(cmdq, "%s (%s) %s", entry->name, entry->alias,
+ entry->usage);
+ }
+
+ return (CMD_RETURN_NORMAL);
+}
diff --git a/cmd-list-panes.c b/cmd-list-panes.c
index c989eba1..bd34344f 100644
--- a/cmd-list-panes.c
+++ b/cmd-list-panes.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -40,7 +40,6 @@ const struct cmd_entry cmd_list_panes_entry = {
"asF:t:", 0, 0,
"[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
0,
- NULL,
cmd_list_panes_exec
};
@@ -129,9 +128,7 @@ cmd_list_panes_window(struct cmd *self,
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
ft = format_create();
format_add(ft, "line", "%u", n);
- format_session(ft, s);
- format_winlink(ft, s, wl);
- format_window_pane(ft, wp);
+ format_defaults(ft, NULL, s, wl, wp);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);
diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c
index a3613c87..8ad55d03 100644
--- a/cmd-list-sessions.c
+++ b/cmd-list-sessions.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,6 +28,14 @@
* List all sessions.
*/
+#define LIST_SESSIONS_TEMPLATE \
+ "#{session_name}: #{session_windows} windows " \
+ "(created #{session_created_string}) " \
+ "[#{session_width}x#{session_height}]" \
+ "#{?session_grouped, (group ,}" \
+ "#{session_group}#{?session_grouped,),}" \
+ "#{?session_attached, (attached),}"
+
enum cmd_retval cmd_list_sessions_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_sessions_entry = {
@@ -35,7 +43,6 @@ const struct cmd_entry cmd_list_sessions_entry = {
"F:", 0, 0,
"[-F format]",
0,
- NULL,
cmd_list_sessions_exec
};
@@ -56,7 +63,7 @@ cmd_list_sessions_exec(struct cmd *self, struct cmd_q *cmdq)
RB_FOREACH(s, sessions, &sessions) {
ft = format_create();
format_add(ft, "line", "%u", n);
- format_session(ft, s);
+ format_defaults(ft, NULL, s, NULL, NULL);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);
diff --git a/cmd-list-windows.c b/cmd-list-windows.c
index ce122f45..3f6b2a4c 100644
--- a/cmd-list-windows.c
+++ b/cmd-list-windows.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,18 +27,29 @@
* List windows on given session.
*/
+#define LIST_WINDOWS_TEMPLATE \
+ "#{window_index}: #{window_name}#{window_flags} " \
+ "(#{window_panes} panes) " \
+ "[#{window_width}x#{window_height}] " \
+ "[layout #{window_layout}] #{window_id}" \
+ "#{?window_active, (active),}";
+#define LIST_WINDOWS_WITH_SESSION_TEMPLATE \
+ "#{session_name}:" \
+ "#{window_index}: #{window_name}#{window_flags} " \
+ "(#{window_panes} panes) " \
+ "[#{window_width}x#{window_height}] "
+
enum cmd_retval cmd_list_windows_exec(struct cmd *, struct cmd_q *);
void cmd_list_windows_server(struct cmd *, struct cmd_q *);
-void cmd_list_windows_session(
- struct cmd *, struct session *, struct cmd_q *, int);
+void cmd_list_windows_session(struct cmd *, struct session *,
+ struct cmd_q *, int);
const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw",
"F:at:", 0, 0,
"[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
0,
- NULL,
cmd_list_windows_exec
};
@@ -96,9 +107,7 @@ cmd_list_windows_session(
RB_FOREACH(wl, winlinks, &s->windows) {
ft = format_create();
format_add(ft, "line", "%u", n);
- format_session(ft, s);
- format_winlink(ft, s, wl);
- format_window_pane(ft, wl->window->active);
+ format_defaults(ft, NULL, s, wl, NULL);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);
diff --git a/cmd-list.c b/cmd-list.c
index 08e2067c..0c75ed49 100644
--- a/cmd-list.c
+++ b/cmd-list.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,7 @@
#include "tmux.h"
struct cmd_list *
-cmd_list_parse(int argc, char **argv, const char* file, u_int line,
+cmd_list_parse(int argc, char **argv, const char *file, u_int line,
char **cause)
{
struct cmd_list *cmdlist;
@@ -103,7 +103,7 @@ size_t
cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len)
{
struct cmd *cmd;
- size_t off;
+ size_t off, used;
off = 0;
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
@@ -112,8 +112,12 @@ cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len)
off += cmd_print(cmd, buf + off, len - off);
if (off >= len)
break;
- if (TAILQ_NEXT(cmd, qentry) != NULL)
- off += xsnprintf(buf + off, len - off, " ; ");
+ if (TAILQ_NEXT(cmd, qentry) != NULL) {
+ used = xsnprintf(buf + off, len - off, " ; ");
+ if (used > len - off)
+ used = len - off;
+ off += used;
+ }
}
return (off);
}
diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c
index 2cb01b97..785a7011 100644
--- a/cmd-load-buffer.c
+++ b/cmd-load-buffer.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -39,7 +39,6 @@ const struct cmd_entry cmd_load_buffer_entry = {
"b:", 1, 1,
CMD_BUFFER_USAGE " path",
0,
- NULL,
cmd_load_buffer_exec
};
@@ -50,30 +49,19 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c = cmdq->client;
struct session *s;
FILE *f;
- const char *path;
+ const char *path, *bufname;
char *pdata, *new_pdata, *cause;
size_t psize;
- u_int limit;
- int ch, error, buffer, *buffer_ptr, cwd, fd;
-
- if (!args_has(args, 'b'))
- buffer = -1;
- else {
- buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
- if (cause != NULL) {
- cmdq_error(cmdq, "buffer %s", cause);
- free(cause);
- return (CMD_RETURN_ERROR);
- }
- }
+ int ch, error, cwd, fd;
+
+ bufname = NULL;
+ if (args_has(args, 'b'))
+ bufname = args_get(args, 'b');
path = args->argv[0];
if (strcmp(path, "-") == 0) {
- buffer_ptr = xmalloc(sizeof *buffer_ptr);
- *buffer_ptr = buffer;
-
error = server_set_stdin_callback(c, cmd_load_buffer_callback,
- buffer_ptr, &cause);
+ (void *)bufname, &cause);
if (error != 0) {
cmdq_error(cmdq, "%s: %s", path, cause);
free(cause);
@@ -117,14 +105,10 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
fclose(f);
- limit = options_get_number(&global_options, "buffer-limit");
- if (buffer == -1) {
- paste_add(&global_buffers, pdata, psize, limit);
- return (CMD_RETURN_NORMAL);
- }
- if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ if (paste_set(pdata, psize, bufname, &cause) != 0) {
+ cmdq_error(cmdq, "%s", cause);
free(pdata);
+ free(cause);
return (CMD_RETURN_ERROR);
}
@@ -140,10 +124,9 @@ error:
void
cmd_load_buffer_callback(struct client *c, int closed, void *data)
{
- int *buffer = data;
- char *pdata;
- size_t psize;
- u_int limit;
+ const char *bufname = data;
+ char *pdata, *cause;
+ size_t psize;
if (!closed)
return;
@@ -154,26 +137,21 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
return;
psize = EVBUFFER_LENGTH(c->stdin_data);
- if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) {
- free(data);
+ if (psize == 0 || (pdata = malloc(psize + 1)) == NULL)
goto out;
- }
+
memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize);
pdata[psize] = '\0';
evbuffer_drain(c->stdin_data, psize);
- limit = options_get_number(&global_options, "buffer-limit");
- if (*buffer == -1)
- paste_add(&global_buffers, pdata, psize, limit);
- else if (paste_replace(&global_buffers, *buffer, pdata, psize) != 0) {
+ if (paste_set(pdata, psize, bufname, &cause) != 0) {
/* No context so can't use server_client_msg_error. */
- evbuffer_add_printf(c->stderr_data, "no buffer %d\n", *buffer);
+ evbuffer_add_printf(c->stderr_data, "%s", cause);
server_push_stderr(c);
free(pdata);
+ free(cause);
}
- free(data);
-
out:
cmdq_continue(c->cmdq);
}
diff --git a/cmd-lock-server.c b/cmd-lock-server.c
index 2b591ecf..de76475d 100644
--- a/cmd-lock-server.c
+++ b/cmd-lock-server.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,10 +18,6 @@
#include <sys/types.h>
-#include <pwd.h>
-#include <string.h>
-#include <unistd.h>
-
#include "tmux.h"
/*
@@ -35,7 +31,6 @@ const struct cmd_entry cmd_lock_server_entry = {
"", 0, 0,
"",
0,
- NULL,
cmd_lock_server_exec
};
@@ -44,7 +39,6 @@ const struct cmd_entry cmd_lock_session_entry = {
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
- NULL,
cmd_lock_server_exec
};
@@ -53,7 +47,6 @@ const struct cmd_entry cmd_lock_client_entry = {
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
- NULL,
cmd_lock_server_exec
};
diff --git a/cmd-move-window.c b/cmd-move-window.c
index 21606755..3064cd6e 100644
--- a/cmd-move-window.c
+++ b/cmd-move-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,7 +33,14 @@ const struct cmd_entry cmd_move_window_entry = {
"dkrs:t:", 0, 0,
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
0,
- NULL,
+ cmd_move_window_exec
+};
+
+const struct cmd_entry cmd_link_window_entry = {
+ "link-window", "linkw",
+ "dks:t:", 0, 0,
+ "[-dk] " CMD_SRCDST_WINDOW_USAGE,
+ 0,
cmd_move_window_exec
};
@@ -47,7 +54,8 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
int idx, kflag, dflag;
if (args_has(args, 'r')) {
- if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
+ s = cmd_find_session(cmdq, args_get(args, 't'), 0);
+ if (s == NULL)
return (CMD_RETURN_ERROR);
session_renumber_windows(s);
@@ -63,12 +71,14 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd');
- if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
- cmdq_error(cmdq, "can't move window: %s", cause);
+ if (server_link_window(src, wl, dst, idx, kflag, !dflag,
+ &cause) != 0) {
+ cmdq_error(cmdq, "can't link window: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
- server_unlink_window(src, wl);
+ if (self->entry == &cmd_move_window_entry)
+ server_unlink_window(src, wl);
recalculate_sizes();
return (CMD_RETURN_NORMAL);
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 15e411d0..ec292fa8 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -20,7 +20,6 @@
#include <errno.h>
#include <fcntl.h>
-#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
@@ -32,16 +31,25 @@
* Create a new session and attach to the current terminal unless -d is given.
*/
+#define NEW_SESSION_TEMPLATE "#{session_name}:"
+
enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_new_session_entry = {
"new-session", "new",
- "Ac:dDF:n:Ps:t:x:y:", 0, 1,
+ "Ac:dDF:n:Ps:t:x:y:", 0, -1,
"[-AdDP] [-c start-directory] [-F format] [-n window-name] "
- "[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
- "[command]",
+ "[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
+ "[-y height] [command]",
CMD_STARTSERVER|CMD_CANTNEST,
- NULL,
+ cmd_new_session_exec
+};
+
+const struct cmd_entry cmd_has_session_entry = {
+ "has-session", "has",
+ "t:", 0, 0,
+ CMD_TARGET_SESSION_USAGE,
+ 0,
cmd_new_session_exec
};
@@ -55,10 +63,19 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
struct environ env;
struct termios tio, *tiop;
const char *newname, *target, *update, *errstr, *template;
- char *cmd, *cause, *cp;
+ const char *path;
+ char **argv, *cmd, *cause, *cp;
int detached, already_attached, idx, cwd, fd = -1;
+ int argc;
u_int sx, sy;
struct format_tree *ft;
+ struct environ_entry *envent;
+
+ if (self->entry == &cmd_has_session_entry) {
+ if (cmd_find_session(cmdq, args_get(args, 't'), 0) == NULL)
+ return (CMD_RETURN_ERROR);
+ return (CMD_RETURN_NORMAL);
+ }
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) {
cmdq_error(cmdq, "command or window name given with target");
@@ -102,8 +119,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
/* Get the new session working directory. */
if (args_has(args, 'c')) {
ft = format_create();
- if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
- format_client(ft, c0);
+ format_defaults(ft, cmd_find_client(cmdq, NULL, 1), NULL, NULL,
+ NULL);
cp = format_expand(ft, args_get(args, 'c'));
format_free(ft);
@@ -145,7 +162,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
/* Open the terminal if necessary. */
if (!detached && !already_attached) {
- if (server_client_open(c, NULL, &cause) != 0) {
+ if (server_client_open(c, &cause) != 0) {
cmdq_error(cmdq, "open terminal failed: %s", cause);
free(cause);
goto error;
@@ -182,12 +199,29 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
sy = 1;
/* Figure out the command for the new window. */
- if (target != NULL)
- cmd = NULL;
- else if (args->argc != 0)
- cmd = args->argv[0];
- else
+ argc = -1;
+ argv = NULL;
+ if (target == NULL && args->argc != 0) {
+ argc = args->argc;
+ argv = args->argv;
+ } else if (target == NULL) {
cmd = options_get_string(&global_s_options, "default-command");
+ if (cmd != NULL && *cmd != '\0') {
+ argc = 1;
+ argv = &cmd;
+ } else {
+ argc = 0;
+ argv = NULL;
+ }
+ }
+
+ path = NULL;
+ if (c != NULL && c->session == NULL)
+ envent = environ_find(&c->environ, "PATH");
+ else
+ envent = environ_find(&global_environ, "PATH");
+ if (envent != NULL)
+ path = envent->value;
/* Construct the environment. */
environ_init(&env);
@@ -197,7 +231,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
/* Create the new session. */
idx = -1 - options_get_number(&global_s_options, "base-index");
- s = session_create(newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause);
+ s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx,
+ sy, &cause);
if (s == NULL) {
cmdq_error(cmdq, "create session failed: %s", cause);
free(cause);
@@ -206,7 +241,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
environ_free(&env);
/* Set the initial window name if one given. */
- if (cmd != NULL && args_has(args, 'n')) {
+ if (argc >= 0 && args_has(args, 'n')) {
w = s->curw->window;
window_set_name(w, args_get(args, 'n'));
options_set_number(&w->options, "automatic-rename", 0);
@@ -252,9 +287,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
template = NEW_SESSION_TEMPLATE;
ft = format_create();
- if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
- format_client(ft, c0);
- format_session(ft, s);
+ format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, NULL,
+ NULL);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
diff --git a/cmd-new-window.c b/cmd-new-window.c
index 58a5eb65..c05a0ce8 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,15 +30,16 @@
* Create a new window.
*/
+#define NEW_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
+
enum cmd_retval cmd_new_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww",
- "ac:dF:kn:Pt:", 0, 1,
+ "ac:dF:kn:Pt:", 0, -1,
"[-adkP] [-c start-directory] [-F format] [-n window-name] "
CMD_TARGET_WINDOW_USAGE " [command]",
0,
- NULL,
cmd_new_window_exec
};
@@ -48,11 +49,11 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
struct session *s;
struct winlink *wl;
- struct client *c;
- const char *cmd, *template;
- char *cause, *cp;
- int idx, last, detached, cwd, fd = -1;
+ const char *cmd, *path, *template;
+ char **argv, *cause, *cp;
+ int argc, idx, last, detached, cwd, fd = -1;
struct format_tree *ft;
+ struct environ_entry *envent;
if (args_has(args, 'a')) {
wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
@@ -77,23 +78,38 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
server_unlink_window(s, wl);
}
} else {
- if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &s)) == -2)
+ idx = cmd_find_index(cmdq, args_get(args, 't'), &s);
+ if (idx == -2)
return (CMD_RETURN_ERROR);
}
detached = args_has(args, 'd');
- if (args->argc == 0)
+ if (args->argc == 0) {
cmd = options_get_string(&s->options, "default-command");
+ if (cmd != NULL && *cmd != '\0') {
+ argc = 1;
+ argv = (char **)&cmd;
+ } else {
+ argc = 0;
+ argv = NULL;
+ }
+ } else {
+ argc = args->argc;
+ argv = args->argv;
+ }
+
+ path = NULL;
+ if (cmdq->client != NULL && cmdq->client->session == NULL)
+ envent = environ_find(&cmdq->client->environ, "PATH");
else
- cmd = args->argv[0];
+ envent = environ_find(&s->environ, "PATH");
+ if (envent != NULL)
+ path = envent->value;
if (args_has(args, 'c')) {
ft = format_create();
- if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
- format_client(ft, c);
- format_session(ft, s);
- format_winlink(ft, s, s->curw);
- format_window_pane(ft, s->curw->window->active);
+ format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, NULL,
+ NULL);
cp = format_expand(ft, args_get(args, 'c'));
format_free(ft);
@@ -135,7 +151,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index");
- wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause);
+ wl = session_new(s, args_get(args, 'n'), argc, argv, path, cwd, idx,
+ &cause);
if (wl == NULL) {
cmdq_error(cmdq, "create window failed: %s", cause);
free(cause);
@@ -152,11 +169,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
template = NEW_WINDOW_TEMPLATE;
ft = format_create();
- if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
- format_client(ft, c);
- format_session(ft, s);
- format_winlink(ft, s, wl);
- format_window_pane(ft, wl->window->active);
+ format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, wl,
+ NULL);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c
index 5305b7e6..5d91aeff 100644
--- a/cmd-paste-buffer.c
+++ b/cmd-paste-buffer.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -35,9 +35,8 @@ void cmd_paste_buffer_filter(struct window_pane *,
const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb",
"db:prs:t:", 0, 0,
- "[-dpr] [-s separator] [-b buffer-index] " CMD_TARGET_PANE_USAGE,
+ "[-dpr] [-s separator] " CMD_BUFFER_USAGE " " CMD_TARGET_PANE_USAGE,
0,
- NULL,
cmd_paste_buffer_exec
};
@@ -48,31 +47,21 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct window_pane *wp;
struct session *s;
struct paste_buffer *pb;
- const char *sepstr;
- char *cause;
- int buffer;
- int pflag;
+ const char *sepstr, *bufname;
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
- if (!args_has(args, 'b'))
- buffer = -1;
- else {
- buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
- if (cause != NULL) {
- cmdq_error(cmdq, "buffer %s", cause);
- free(cause);
- return (CMD_RETURN_ERROR);
- }
- }
+ bufname = NULL;
+ if (args_has(args, 'b'))
+ bufname = args_get(args, 'b');
- if (buffer == -1)
- pb = paste_get_top(&global_buffers);
+ if (bufname == NULL)
+ pb = paste_get_top();
else {
- pb = paste_get_index(&global_buffers, buffer);
+ pb = paste_get_name(bufname);
if (pb == NULL) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ cmdq_error(cmdq, "no buffer %s", bufname);
return (CMD_RETURN_ERROR);
}
}
@@ -85,16 +74,15 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
else
sepstr = "\r";
}
- pflag = (wp->screen->mode & MODE_BRACKETPASTE);
- paste_send_pane(pb, wp, sepstr, args_has(args, 'p') && pflag);
+ paste_send_pane(pb, wp, sepstr, args_has(args, 'p'));
}
/* Delete the buffer if -d. */
if (args_has(args, 'd')) {
- if (buffer == -1)
- paste_free_top(&global_buffers);
+ if (bufname == NULL)
+ paste_free_top();
else
- paste_free_index(&global_buffers, buffer);
+ paste_free_name(bufname);
}
return (CMD_RETURN_NORMAL);
diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c
index 611ad8cf..49b156c6 100644
--- a/cmd-pipe-pane.c
+++ b/cmd-pipe-pane.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -21,6 +21,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
@@ -40,7 +41,6 @@ const struct cmd_entry cmd_pipe_pane_entry = {
"ot:", 0, 1,
"[-o] " CMD_TARGET_PANE_USAGE " [command]",
0,
- NULL,
cmd_pipe_pane_exec
};
@@ -49,11 +49,14 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
+ struct session *s;
+ struct winlink *wl;
struct window_pane *wp;
- char *command;
+ char *cmd;
int old_fd, pipe_fd[2], null_fd;
+ struct format_tree *ft;
- if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
+ if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
c = cmd_find_client(cmdq, NULL, 1);
@@ -84,10 +87,18 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
+ /* Expand the command. */
+ ft = format_create();
+ format_defaults(ft, c, s, wl, wp);
+ cmd = format_expand_time(ft, args->argv[0], time(NULL));
+ format_free(ft);
+
/* Fork the child. */
switch (fork()) {
case -1:
cmdq_error(cmdq, "fork error: %s", strerror(errno));
+
+ free(cmd);
return (CMD_RETURN_ERROR);
case 0:
/* Child process. */
@@ -109,9 +120,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
closefrom(STDERR_FILENO + 1);
- command = status_replace(
- c, NULL, NULL, NULL, args->argv[0], time(NULL), 0);
- execl(_PATH_BSHELL, "sh", "-c", command, (char *) NULL);
+ execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
_exit(1);
default:
/* Parent process. */
@@ -125,6 +134,8 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
bufferevent_enable(wp->pipe_event, EV_WRITE);
setblocking(wp->pipe_fd, 0);
+
+ free(cmd);
return (CMD_RETURN_NORMAL);
}
}
diff --git a/cmd-queue.c b/cmd-queue.c
index 17955b82..58282c8f 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -57,7 +57,7 @@ cmdq_free(struct cmd_q *cmdq)
}
/* Show message from command. */
-void printflike2
+void
cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
{
struct client *c = cmdq->client;
@@ -86,55 +86,23 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
va_end(ap);
}
-/* Show info from command. */
-void printflike2
-cmdq_info(struct cmd_q *cmdq, const char *fmt, ...)
-{
- struct client *c = cmdq->client;
- va_list ap;
- char *msg;
-
- if (options_get_number(&global_options, "quiet"))
- return;
-
- va_start(ap, fmt);
-
- if (c == NULL)
- /* nothing */;
- else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
- evbuffer_add_vprintf(c->stdout_data, fmt, ap);
-
- evbuffer_add(c->stdout_data, "\n", 1);
- server_push_stdout(c);
- } else {
- xvasprintf(&msg, fmt, ap);
- *msg = toupper((u_char) *msg);
- status_message_set(c, "%s", msg);
- free(msg);
- }
-
- va_end(ap);
-
-}
-
/* Show error from command. */
-void printflike2
+void
cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
{
struct client *c = cmdq->client;
struct cmd *cmd = cmdq->cmd;
va_list ap;
- char *msg, *cause;
+ char *msg;
size_t msglen;
va_start(ap, fmt);
msglen = xvasprintf(&msg, fmt, ap);
va_end(ap);
- if (c == NULL) {
- xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg);
- ARRAY_ADD(&cfg_causes, cause);
- } else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
+ if (c == NULL)
+ cfg_add_cause("%s:%u: %s", cmd->file, cmd->line, msg);
+ else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
evbuffer_add(c->stderr_data, msg, msglen);
evbuffer_add(c->stderr_data, "\n", 1);
@@ -149,20 +117,17 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
}
/* Print a guard line. */
-int
+void
cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
{
struct client *c = cmdq->client;
- if (c == NULL)
- return 0;
- if (!(c->flags & CLIENT_CONTROL))
- return 0;
+ if (c == NULL || !(c->flags & CLIENT_CONTROL))
+ return;
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
(long) cmdq->time, cmdq->number, flags);
server_push_stdout(c);
- return 1;
}
/* Add command list to queue and begin processing if needed. */
@@ -195,7 +160,7 @@ cmdq_continue(struct cmd_q *cmdq)
{
struct cmd_q_item *next;
enum cmd_retval retval;
- int empty, guard, flags;
+ int empty, flags;
char s[1024];
notify_disable();
@@ -211,8 +176,6 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
do {
- next = TAILQ_NEXT(cmdq->item, qentry);
-
while (cmdq->cmd != NULL) {
cmd_print(cmdq->cmd, s, sizeof s);
log_debug("cmdq %p: %s (client %d)", cmdq, s,
@@ -222,16 +185,14 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->number++;
flags = !!(cmdq->cmd->flags & CMD_CONTROL);
- guard = cmdq_guard(cmdq, "begin", flags);
+ cmdq_guard(cmdq, "begin", flags);
retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
- if (guard) {
- if (retval == CMD_RETURN_ERROR)
- cmdq_guard(cmdq, "error", flags);
- else
- cmdq_guard(cmdq, "end", flags);
- }
+ if (retval == CMD_RETURN_ERROR)
+ cmdq_guard(cmdq, "error", flags);
+ else
+ cmdq_guard(cmdq, "end", flags);
if (retval == CMD_RETURN_ERROR)
break;
@@ -244,6 +205,7 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
}
+ next = TAILQ_NEXT(cmdq->item, qentry);
TAILQ_REMOVE(&cmdq->queue, cmdq->item, qentry);
cmd_list_free(cmdq->item->cmdlist);
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index 45804fbe..f693872c 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,7 +31,6 @@ const struct cmd_entry cmd_refresh_client_entry = {
"C:St:", 0, 0,
"[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
0,
- NULL,
cmd_refresh_client_exec
};
diff --git a/cmd-rename-session.c b/cmd-rename-session.c
index 4c8ae122..481154ce 100644
--- a/cmd-rename-session.c
+++ b/cmd-rename-session.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,7 +33,6 @@ const struct cmd_entry cmd_rename_session_entry = {
"t:", 1, 1,
CMD_TARGET_SESSION_USAGE " new-name",
0,
- NULL,
cmd_rename_session_exec
};
diff --git a/cmd-rename-window.c b/cmd-rename-window.c
index f647abb3..2f677a48 100644
--- a/cmd-rename-window.c
+++ b/cmd-rename-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,7 +33,6 @@ const struct cmd_entry cmd_rename_window_entry = {
"t:", 1, 1,
CMD_TARGET_WINDOW_USAGE " new-name",
0,
- NULL,
cmd_rename_window_exec
};
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index d31f8868..42f0f39a 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,7 +26,6 @@
* Increase or decrease pane size.
*/
-void cmd_resize_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_resize_pane_entry = {
@@ -34,56 +33,9 @@ const struct cmd_entry cmd_resize_pane_entry = {
"DLRt:Ux:y:Z", 0, 1,
"[-DLRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " [adjustment]",
0,
- cmd_resize_pane_key_binding,
cmd_resize_pane_exec
};
-void
-cmd_resize_pane_key_binding(struct cmd *self, int key)
-{
- switch (key) {
- case KEYC_UP | KEYC_CTRL:
- self->args = args_create(0);
- args_set(self->args, 'U', NULL);
- break;
- case KEYC_DOWN | KEYC_CTRL:
- self->args = args_create(0);
- args_set(self->args, 'D', NULL);
- break;
- case KEYC_LEFT | KEYC_CTRL:
- self->args = args_create(0);
- args_set(self->args, 'L', NULL);
- break;
- case KEYC_RIGHT | KEYC_CTRL:
- self->args = args_create(0);
- args_set(self->args, 'R', NULL);
- break;
- case KEYC_UP | KEYC_ESCAPE:
- self->args = args_create(1, "5");
- args_set(self->args, 'U', NULL);
- break;
- case KEYC_DOWN | KEYC_ESCAPE:
- self->args = args_create(1, "5");
- args_set(self->args, 'D', NULL);
- break;
- case KEYC_LEFT | KEYC_ESCAPE:
- self->args = args_create(1, "5");
- args_set(self->args, 'L', NULL);
- break;
- case KEYC_RIGHT | KEYC_ESCAPE:
- self->args = args_create(1, "5");
- args_set(self->args, 'R', NULL);
- break;
- case 'z':
- self->args = args_create(0);
- args_set(self->args, 'Z', NULL);
- break;
- default:
- self->args = args_create(0);
- break;
- }
-}
-
enum cmd_retval
cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
diff --git a/cmd-respawn-pane.c b/cmd-respawn-pane.c
index bcde2754..47031539 100644
--- a/cmd-respawn-pane.c
+++ b/cmd-respawn-pane.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,10 +32,9 @@ enum cmd_retval cmd_respawn_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_respawn_pane_entry = {
"respawn-pane", "respawnp",
- "kt:", 0, 1,
+ "kt:", 0, -1,
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
0,
- NULL,
cmd_respawn_pane_exec
};
@@ -48,9 +47,10 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
struct window_pane *wp;
struct session *s;
struct environ env;
- const char *cmd;
+ const char *path;
char *cause;
u_int idx;
+ struct environ_entry *envent;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
@@ -73,11 +73,16 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
screen_reinit(&wp->base);
input_init(wp);
- if (args->argc != 0)
- cmd = args->argv[0];
+ path = NULL;
+ if (cmdq->client != NULL && cmdq->client->session == NULL)
+ envent = environ_find(&cmdq->client->environ, "PATH");
else
- cmd = NULL;
- if (window_pane_spawn(wp, cmd, NULL, -1, &env, s->tio, &cause) != 0) {
+ envent = environ_find(&s->environ, "PATH");
+ if (envent != NULL)
+ path = envent->value;
+
+ if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
+ s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn pane failed: %s", cause);
free(cause);
environ_free(&env);
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
index e6d913cf..06102ed0 100644
--- a/cmd-respawn-window.c
+++ b/cmd-respawn-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,10 +31,9 @@ enum cmd_retval cmd_respawn_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw",
- "kt:", 0, 1,
+ "kt:", 0, -1,
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
0,
- NULL,
cmd_respawn_window_exec
};
@@ -47,8 +46,9 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct window_pane *wp;
struct session *s;
struct environ env;
- const char *cmd;
+ const char *path;
char *cause;
+ struct environ_entry *envent;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
@@ -75,11 +75,17 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
window_destroy_panes(w);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
window_pane_resize(wp, w->sx, w->sy);
- if (args->argc != 0)
- cmd = args->argv[0];
+
+ path = NULL;
+ if (cmdq->client != NULL && cmdq->client->session == NULL)
+ envent = environ_find(&cmdq->client->environ, "PATH");
else
- cmd = NULL;
- if (window_pane_spawn(wp, cmd, NULL, -1, &env, s->tio, &cause) != 0) {
+ envent = environ_find(&s->environ, "PATH");
+ if (envent != NULL)
+ path = envent->value;
+
+ if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
+ s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn window failed: %s", cause);
free(cause);
environ_free(&env);
diff --git a/cmd-rotate-window.c b/cmd-rotate-window.c
index 9f4cc751..859ff04a 100644
--- a/cmd-rotate-window.c
+++ b/cmd-rotate-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,6 @@
* Rotate the panes in a window.
*/
-void cmd_rotate_window_key_binding(struct cmd *, int);
enum cmd_retval cmd_rotate_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_rotate_window_entry = {
@@ -32,18 +31,9 @@ const struct cmd_entry cmd_rotate_window_entry = {
"Dt:U", 0, 0,
"[-DU] " CMD_TARGET_WINDOW_USAGE,
0,
- cmd_rotate_window_key_binding,
cmd_rotate_window_exec
};
-void
-cmd_rotate_window_key_binding(struct cmd *self, int key)
-{
- self->args = args_create(0);
- if (key == ('o' | KEYC_ESCAPE))
- args_set(self->args, 'D', NULL);
-}
-
enum cmd_retval
cmd_rotate_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
diff --git a/cmd-run-shell.c b/cmd-run-shell.c
index f5231814..5d6d178b 100644
--- a/cmd-run-shell.c
+++ b/cmd-run-shell.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -40,7 +40,6 @@ const struct cmd_entry cmd_run_shell_entry = {
"bt:", 1, 1,
"[-b] " CMD_TARGET_PANE_USAGE " shell-command",
0,
- NULL,
cmd_run_shell_exec
};
@@ -94,12 +93,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
}
ft = format_create();
- if (s != NULL)
- format_session(ft, s);
- if (s != NULL && wl != NULL)
- format_winlink(ft, s, wl);
- if (wp != NULL)
- format_window_pane(ft, wp);
+ format_defaults(ft, NULL, s, wl, wp);
shellcmd = format_expand(ft, args->argv[0]);
format_free(ft);
@@ -161,13 +155,9 @@ cmd_run_shell_callback(struct job *job)
retcode = WTERMSIG(job->status);
xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
}
- if (msg != NULL) {
- if (lines == 0)
- cmdq_info(cmdq, "%s", msg);
- else
- cmd_run_shell_print(job, msg);
- free(msg);
- }
+ if (msg != NULL)
+ cmd_run_shell_print(job, msg);
+ free(msg);
}
void
diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c
index 3788fc22..47a263da 100644
--- a/cmd-save-buffer.c
+++ b/cmd-save-buffer.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -38,7 +38,6 @@ const struct cmd_entry cmd_save_buffer_entry = {
"ab:", 1, 1,
"[-a] " CMD_BUFFER_USAGE " path",
0,
- NULL,
cmd_save_buffer_exec
};
@@ -47,7 +46,6 @@ const struct cmd_entry cmd_show_buffer_entry = {
"b:", 0, 0,
CMD_BUFFER_USAGE,
0,
- NULL,
cmd_save_buffer_exec
};
@@ -58,28 +56,22 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c = cmdq->client;
struct session *s;
struct paste_buffer *pb;
- const char *path;
- char *cause, *start, *end, *msg;
+ const char *path, *bufname;
+ char *start, *end, *msg;
size_t size, used, msglen;
- int cwd, fd, buffer;
+ int cwd, fd;
FILE *f;
if (!args_has(args, 'b')) {
- if ((pb = paste_get_top(&global_buffers)) == NULL) {
+ if ((pb = paste_get_top()) == NULL) {
cmdq_error(cmdq, "no buffers");
return (CMD_RETURN_ERROR);
}
} else {
- buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
- if (cause != NULL) {
- cmdq_error(cmdq, "buffer %s", cause);
- free(cause);
- return (CMD_RETURN_ERROR);
- }
-
- pb = paste_get_index(&global_buffers, buffer);
+ bufname = args_get(args, 'b');
+ pb = paste_get_name(bufname);
if (pb == NULL) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ cmdq_error(cmdq, "no buffer %s", bufname);
return (CMD_RETURN_ERROR);
}
}
@@ -111,7 +103,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
if (fd != -1)
f = fdopen(fd, "ab");
} else {
- fd = openat(cwd, path, O_CREAT|O_RDWR, 0600);
+ fd = openat(cwd, path, O_CREAT|O_RDWR|O_TRUNC, 0600);
if (fd != -1)
f = fdopen(fd, "wb");
}
@@ -141,7 +133,6 @@ do_print:
return (CMD_RETURN_ERROR);
}
msg = NULL;
- msglen = 0;
used = 0;
while (used != pb->size) {
@@ -153,7 +144,7 @@ do_print:
size = pb->size - used;
msglen = size * 4 + 1;
- msg = xrealloc(msg, 1, msglen);
+ msg = xrealloc(msg, msglen);
strvisx(msg, start, size, VIS_OCTAL|VIS_TAB);
cmdq_print(cmdq, "%s", msg);
diff --git a/cmd-select-layout.c b/cmd-select-layout.c
index 053f3e40..77137b74 100644
--- a/cmd-select-layout.c
+++ b/cmd-select-layout.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,7 +24,6 @@
* Switch window to selected layout.
*/
-void cmd_select_layout_key_binding(struct cmd *, int);
enum cmd_retval cmd_select_layout_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_layout_entry = {
@@ -32,7 +31,6 @@ const struct cmd_entry cmd_select_layout_entry = {
"npt:", 0, 1,
"[-np] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
0,
- cmd_select_layout_key_binding,
cmd_select_layout_exec
};
@@ -41,7 +39,6 @@ const struct cmd_entry cmd_next_layout_entry = {
"t:", 0, 0,
CMD_TARGET_WINDOW_USAGE,
0,
- NULL,
cmd_select_layout_exec
};
@@ -50,35 +47,9 @@ const struct cmd_entry cmd_previous_layout_entry = {
"t:", 0, 0,
CMD_TARGET_WINDOW_USAGE,
0,
- NULL,
cmd_select_layout_exec
};
-void
-cmd_select_layout_key_binding(struct cmd *self, int key)
-{
- switch (key) {
- case '1' | KEYC_ESCAPE:
- self->args = args_create(1, "even-horizontal");
- break;
- case '2' | KEYC_ESCAPE:
- self->args = args_create(1, "even-vertical");
- break;
- case '3' | KEYC_ESCAPE:
- self->args = args_create(1, "main-horizontal");
- break;
- case '4' | KEYC_ESCAPE:
- self->args = args_create(1, "main-vertical");
- break;
- case '5' | KEYC_ESCAPE:
- self->args = args_create(1, "tiled");
- break;
- default:
- self->args = args_create(0);
- break;
- }
-}
-
enum cmd_retval
cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
{
@@ -104,7 +75,6 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
else
layout = layout_set_previous(wl->window);
server_redraw_window(wl->window);
- cmdq_info(cmdq, "arranging in: %s", layout_set_name(layout));
return (CMD_RETURN_NORMAL);
}
@@ -115,7 +85,6 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
if (layout != -1) {
layout = layout_set_select(wl->window, layout);
server_redraw_window(wl->window);
- cmdq_info(cmdq, "arranging in: %s", layout_set_name(layout));
return (CMD_RETURN_NORMAL);
}
@@ -126,7 +95,6 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
server_redraw_window(wl->window);
- cmdq_info(cmdq, "arranging in: %s", layoutname);
}
return (CMD_RETURN_NORMAL);
}
diff --git a/cmd-select-pane.c b/cmd-select-pane.c
index c342fef3..5810eeab 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,43 +24,24 @@
* Select pane.
*/
-void cmd_select_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_select_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp",
- "lDLRt:U", 0, 0,
- "[-lDLRU] " CMD_TARGET_PANE_USAGE,
+ "DdeLlRt:U", 0, 0,
+ "[-DdeLlRU] " CMD_TARGET_PANE_USAGE,
0,
- cmd_select_pane_key_binding,
cmd_select_pane_exec
};
const struct cmd_entry cmd_last_pane_entry = {
"last-pane", "lastp",
- "t:", 0, 0,
- CMD_TARGET_WINDOW_USAGE,
+ "det:", 0, 0,
+ "[-de] " CMD_TARGET_WINDOW_USAGE,
0,
- NULL,
cmd_select_pane_exec
};
-void
-cmd_select_pane_key_binding(struct cmd *self, int key)
-{
- self->args = args_create(0);
- if (key == KEYC_UP)
- args_set(self->args, 'U', NULL);
- if (key == KEYC_DOWN)
- args_set(self->args, 'D', NULL);
- if (key == KEYC_LEFT)
- args_set(self->args, 'L', NULL);
- if (key == KEYC_RIGHT)
- args_set(self->args, 'R', NULL);
- if (key == 'o')
- args_set(self->args, 't', ":.+");
-}
-
enum cmd_retval
cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
@@ -78,10 +59,16 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
- server_unzoom_window(wl->window);
- window_set_active_pane(wl->window, wl->window->last);
- server_status_window(wl->window);
- server_redraw_window_borders(wl->window);
+ if (args_has(self->args, 'e'))
+ wl->window->last->flags &= ~PANE_INPUTOFF;
+ else if (args_has(self->args, 'd'))
+ wl->window->last->flags |= PANE_INPUTOFF;
+ else {
+ server_unzoom_window(wl->window);
+ window_set_active_pane(wl->window, wl->window->last);
+ server_status_window(wl->window);
+ server_redraw_window_borders(wl->window);
+ }
return (CMD_RETURN_NORMAL);
}
@@ -108,9 +95,14 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
- window_set_active_pane(wl->window, wp);
- server_status_window(wl->window);
- server_redraw_window_borders(wl->window);
+ if (args_has(self->args, 'e'))
+ wp->flags &= ~PANE_INPUTOFF;
+ else if (args_has(self->args, 'd'))
+ wp->flags |= PANE_INPUTOFF;
+ else if (window_set_active_pane(wl->window, wp)) {
+ server_status_window(wl->window);
+ server_redraw_window_borders(wl->window);
+ }
return (CMD_RETURN_NORMAL);
}
diff --git a/cmd-select-window.c b/cmd-select-window.c
index 73196200..f530f1fe 100644
--- a/cmd-select-window.c
+++ b/cmd-select-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,7 +26,6 @@
* Select window by index.
*/
-void cmd_select_window_key_binding(struct cmd *, int);
enum cmd_retval cmd_select_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_window_entry = {
@@ -34,7 +33,6 @@ const struct cmd_entry cmd_select_window_entry = {
"lnpTt:", 0, 0,
"[-lnpT] " CMD_TARGET_WINDOW_USAGE,
0,
- cmd_select_window_key_binding,
cmd_select_window_exec
};
@@ -43,7 +41,6 @@ const struct cmd_entry cmd_next_window_entry = {
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
- cmd_select_window_key_binding,
cmd_select_window_exec
};
@@ -52,7 +49,6 @@ const struct cmd_entry cmd_previous_window_entry = {
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
- cmd_select_window_key_binding,
cmd_select_window_exec
};
@@ -61,24 +57,9 @@ const struct cmd_entry cmd_last_window_entry = {
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
- NULL,
cmd_select_window_exec
};
-void
-cmd_select_window_key_binding(struct cmd *self, int key)
-{
- char tmp[16];
-
- self->args = args_create(0);
- if (key >= '0' && key <= '9') {
- xsnprintf(tmp, sizeof tmp, ":%d", key - '0');
- args_set(self->args, 't', tmp);
- }
- if (key == ('n' | KEYC_ESCAPE) || key == ('p' | KEYC_ESCAPE))
- args_set(self->args, 'a', NULL);
-}
-
enum cmd_retval
cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index 50cb70e2..7a4d97d5 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_send_keys_entry = {
"lRt:", 0, -1,
"[-lR] " CMD_TARGET_PANE_USAGE " key ...",
0,
- NULL,
cmd_send_keys_exec
};
@@ -43,7 +42,6 @@ const struct cmd_entry cmd_send_prefix_entry = {
"2t:", 0, 0,
"[-2] " CMD_TARGET_PANE_USAGE,
0,
- NULL,
cmd_send_keys_exec
};
diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c
index fade4fe3..0ec362b3 100644
--- a/cmd-set-buffer.c
+++ b/cmd-set-buffer.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,50 +24,93 @@
#include "tmux.h"
/*
- * Add or set a paste buffer.
+ * Add, set, or append to a paste buffer.
*/
enum cmd_retval cmd_set_buffer_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb",
- "b:", 1, 1,
- CMD_BUFFER_USAGE " data",
+ "ab:n:", 0, 1,
+ "[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
0,
- NULL,
cmd_set_buffer_exec
};
enum cmd_retval
cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
- struct args *args = self->args;
- u_int limit;
- char *pdata, *cause;
- size_t psize;
- int buffer;
+ struct args *args = self->args;
+ struct paste_buffer *pb;
+ char *pdata, *cause;
+ const char *bufname;
+ size_t psize, newsize;
- limit = options_get_number(&global_options, "buffer-limit");
+ bufname = NULL;
- pdata = xstrdup(args->argv[0]);
- psize = strlen(pdata);
+ if (args_has(args, 'n')) {
+ if (args->argc > 0) {
+ cmdq_error(cmdq, "don't provide data with n flag");
+ return (CMD_RETURN_ERROR);
+ }
+
+ if (args_has(args, 'b'))
+ bufname = args_get(args, 'b');
+
+ if (bufname == NULL) {
+ pb = paste_get_top();
+ if (pb == NULL) {
+ cmdq_error(cmdq, "no buffer");
+ return (CMD_RETURN_ERROR);
+ }
+ bufname = pb->name;
+ }
+
+ if (paste_rename(bufname, args_get(args, 'n'), &cause) != 0) {
+ cmdq_error(cmdq, "%s", cause);
+ free(cause);
+ return (CMD_RETURN_ERROR);
+ }
- if (!args_has(args, 'b')) {
- paste_add(&global_buffers, pdata, psize, limit);
return (CMD_RETURN_NORMAL);
}
- buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
- if (cause != NULL) {
- cmdq_error(cmdq, "buffer %s", cause);
- free(cause);
- free(pdata);
+ if (args->argc != 1) {
+ cmdq_error(cmdq, "no data specified");
return (CMD_RETURN_ERROR);
}
- if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) {
- cmdq_error(cmdq, "no buffer %d", buffer);
+ psize = 0;
+ pdata = NULL;
+
+ pb = NULL;
+
+ if ((newsize = strlen(args->argv[0])) == 0)
+ return (CMD_RETURN_NORMAL);
+
+ if (args_has(args, 'b')) {
+ bufname = args_get(args, 'b');
+ pb = paste_get_name(bufname);
+ } else if (args_has(args, 'a')) {
+ pb = paste_get_top();
+ if (pb != NULL)
+ bufname = pb->name;
+ }
+
+ if (args_has(args, 'a') && pb != NULL) {
+ psize = pb->size;
+ pdata = xmalloc(psize);
+ memcpy(pdata, pb->data, psize);
+ }
+
+ pdata = xrealloc(pdata, psize + newsize);
+ memcpy(pdata + psize, args->argv[0], newsize);
+ psize += newsize;
+
+ if (paste_set(pdata, psize, bufname, &cause) != 0) {
+ cmdq_error(cmdq, "%s", cause);
free(pdata);
+ free(cause);
return (CMD_RETURN_ERROR);
}
diff --git a/cmd-set-environment.c b/cmd-set-environment.c
index 8d067c35..83e63b48 100644
--- a/cmd-set-environment.c
+++ b/cmd-set-environment.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_set_environment_entry = {
"grt:u", 1, 2,
"[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
0,
- NULL,
cmd_set_environment_exec
};
diff --git a/cmd-set-option.c b/cmd-set-option.c
index 5ae4e5c3..01d691d5 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -69,7 +69,6 @@ const struct cmd_entry cmd_set_option_entry = {
"agoqst:uw", 1, 2,
"[-agosquw] [-t target-session|target-window] option [value]",
0,
- NULL,
cmd_set_option_exec
};
@@ -78,7 +77,6 @@ const struct cmd_entry cmd_set_window_option_entry = {
"agoqt:u", 1, 2,
"[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
0,
- NULL,
cmd_set_option_exec
};
@@ -117,8 +115,11 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
if (oe == NULL) {
- cmdq_error(cmdq, "unknown option: %s", optstr);
- return (CMD_RETURN_ERROR);
+ if (!args_has(args, 'q')) {
+ cmdq_error(cmdq, "unknown option: %s", optstr);
+ return (CMD_RETURN_ERROR);
+ }
+ return (CMD_RETURN_NORMAL);
}
/* Work out the tree from the table. */
@@ -163,8 +164,10 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
} else {
if (args_has(args, 'o') && options_find1(oo, optstr) != NULL) {
- if (!args_has(args, 'q'))
- cmdq_print(cmdq, "already set: %s", optstr);
+ if (!args_has(args, 'q')) {
+ cmdq_error(cmdq, "already set: %s", optstr);
+ return (CMD_RETURN_ERROR);
+ }
return (CMD_RETURN_NORMAL);
}
if (cmd_set_option_set(self, cmdq, oe, oo, valstr) != 0)
@@ -196,7 +199,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
/* Set user option. */
enum cmd_retval
-cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char* optstr,
+cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char *optstr,
const char *valstr)
{
struct args *args = self->args;
@@ -229,8 +232,11 @@ cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char* optstr,
if (args_has(args, 'u')) {
if (options_find1(oo, optstr) == NULL) {
- cmdq_error(cmdq, "unknown option: %s", optstr);
- return (CMD_RETURN_ERROR);
+ if (!args_has(args, 'q')) {
+ cmdq_error(cmdq, "unknown option: %s", optstr);
+ return (CMD_RETURN_ERROR);
+ }
+ return (CMD_RETURN_NORMAL);
}
if (valstr != NULL) {
cmdq_error(cmdq, "value passed to unset option: %s",
@@ -244,15 +250,13 @@ cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char* optstr,
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'o') && options_find1(oo, optstr) != NULL) {
- if (!args_has(args, 'q'))
- cmdq_print(cmdq, "already set: %s", optstr);
+ if (!args_has(args, 'q')) {
+ cmdq_error(cmdq, "already set: %s", optstr);
+ return (CMD_RETURN_ERROR);
+ }
return (CMD_RETURN_NORMAL);
}
options_set_string(oo, optstr, "%s", valstr);
- if (!args_has(args, 'q')) {
- cmdq_info(cmdq, "set option: %s -> %s", optstr,
- valstr);
- }
}
return (CMD_RETURN_NORMAL);
}
@@ -261,7 +265,8 @@ cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char* optstr,
/* Unset an option. */
int
cmd_set_option_unset(struct cmd *self, struct cmd_q *cmdq,
- const struct options_table_entry *oe, struct options *oo, const char *value)
+ const struct options_table_entry *oe, struct options *oo,
+ const char *value)
{
struct args *args = self->args;
@@ -275,19 +280,16 @@ cmd_set_option_unset(struct cmd *self, struct cmd_q *cmdq,
}
options_remove(oo, oe->name);
- if (!args_has(args, 'q'))
- cmdq_info(cmdq, "unset option: %s", oe->name);
return (0);
}
/* Set an option. */
int
cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
- const struct options_table_entry *oe, struct options *oo, const char *value)
+ const struct options_table_entry *oe, struct options *oo,
+ const char *value)
{
- struct args *args = self->args;
struct options_entry *o;
- const char *s;
if (oe->type != OPTIONS_TABLE_FLAG && value == NULL) {
cmdq_error(cmdq, "empty value");
@@ -327,17 +329,14 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
}
if (o == NULL)
return (-1);
-
- s = options_table_print_entry(oe, o, 0);
- if (!args_has(args, 'q'))
- cmdq_info(cmdq, "set option: %s -> %s", oe->name, s);
return (0);
}
/* Set a string option. */
struct options_entry *
cmd_set_option_string(struct cmd *self, unused struct cmd_q *cmdq,
- const struct options_table_entry *oe, struct options *oo, const char *value)
+ const struct options_table_entry *oe, struct options *oo,
+ const char *value)
{
struct args *args = self->args;
struct options_entry *o;
@@ -358,7 +357,8 @@ cmd_set_option_string(struct cmd *self, unused struct cmd_q *cmdq,
/* Set a number option. */
struct options_entry *
cmd_set_option_number(unused struct cmd *self, struct cmd_q *cmdq,
- const struct options_table_entry *oe, struct options *oo, const char *value)
+ const struct options_table_entry *oe, struct options *oo,
+ const char *value)
{
long long ll;
const char *errstr;
@@ -375,7 +375,8 @@ cmd_set_option_number(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a key option. */
struct options_entry *
cmd_set_option_key(unused struct cmd *self, struct cmd_q *cmdq,
- const struct options_table_entry *oe, struct options *oo, const char *value)
+ const struct options_table_entry *oe, struct options *oo,
+ const char *value)
{
int key;
@@ -390,7 +391,8 @@ cmd_set_option_key(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a colour option. */
struct options_entry *
cmd_set_option_colour(unused struct cmd *self, struct cmd_q *cmdq,
- const struct options_table_entry *oe, struct options *oo, const char *value)
+ const struct options_table_entry *oe, struct options *oo,
+ const char *value)
{
int colour;
@@ -405,7 +407,8 @@ cmd_set_option_colour(unused struct cmd *self, struct cmd_q *cmdq,
/* Set an attributes option. */
struct options_entry *
cmd_set_option_attributes(unused struct cmd *self, struct cmd_q *cmdq,
- const struct options_table_entry *oe, struct options *oo, const char *value)
+ const struct options_table_entry *oe, struct options *oo,
+ const char *value)
{
int attr;
@@ -420,7 +423,8 @@ cmd_set_option_attributes(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a flag option. */
struct options_entry *
cmd_set_option_flag(unused struct cmd *self, struct cmd_q *cmdq,
- const struct options_table_entry *oe, struct options *oo, const char *value)
+ const struct options_table_entry *oe, struct options *oo,
+ const char *value)
{
int flag;
diff --git a/cmd-show-environment.c b/cmd-show-environment.c
index 2238929e..7737752f 100644
--- a/cmd-show-environment.c
+++ b/cmd-show-environment.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -34,7 +34,6 @@ const struct cmd_entry cmd_show_environment_entry = {
"gt:", 0, 1,
"[-g] " CMD_TARGET_SESSION_USAGE " [name]",
0,
- NULL,
cmd_show_environment_exec
};
diff --git a/cmd-show-messages.c b/cmd-show-messages.c
index 551966ed..308668f1 100644
--- a/cmd-show-messages.c
+++ b/cmd-show-messages.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_show_messages_entry = {
"IJTt:", 0, 0,
"[-IJT] " CMD_TARGET_CLIENT_USAGE,
0,
- NULL,
cmd_show_messages_exec
};
@@ -44,7 +43,6 @@ const struct cmd_entry cmd_server_info_entry = {
"", 0, 0,
"",
0,
- NULL,
cmd_show_messages_exec
};
diff --git a/cmd-show-options.c b/cmd-show-options.c
index 943353f6..a5011e72 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -39,7 +39,6 @@ const struct cmd_entry cmd_show_options_entry = {
"gqst:vw", 0, 1,
"[-gqsvw] [-t target-session|target-window] [option]",
0,
- NULL,
cmd_show_options_exec
};
@@ -48,7 +47,6 @@ const struct cmd_entry cmd_show_window_options_entry = {
"gvt:", 0, 1,
"[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
0,
- NULL,
cmd_show_options_exec
};
@@ -100,15 +98,17 @@ cmd_show_options_one(struct cmd *self, struct cmd_q *cmdq,
struct options *oo, int quiet)
{
struct args *args = self->args;
+ const char *name = args->argv[0];
const struct options_table_entry *table, *oe;
struct options_entry *o;
const char *optval;
- if (*args->argv[0] == '@') {
- if ((o = options_find1(oo, args->argv[0])) == NULL) {
+retry:
+ if (*name == '@') {
+ if ((o = options_find1(oo, name)) == NULL) {
if (quiet)
return (CMD_RETURN_NORMAL);
- cmdq_error(cmdq, "unknown option: %s", args->argv[0]);
+ cmdq_error(cmdq, "unknown option: %s", name);
return (CMD_RETURN_ERROR);
}
if (args_has(self->args, 'v'))
@@ -119,16 +119,20 @@ cmd_show_options_one(struct cmd *self, struct cmd_q *cmdq,
}
table = oe = NULL;
- if (options_table_find(args->argv[0], &table, &oe) != 0) {
- cmdq_error(cmdq, "ambiguous option: %s", args->argv[0]);
+ if (options_table_find(name, &table, &oe) != 0) {
+ cmdq_error(cmdq, "ambiguous option: %s", name);
return (CMD_RETURN_ERROR);
}
if (oe == NULL) {
if (quiet)
return (CMD_RETURN_NORMAL);
- cmdq_error(cmdq, "unknown option: %s", args->argv[0]);
+ cmdq_error(cmdq, "unknown option: %s", name);
return (CMD_RETURN_ERROR);
}
+ if (oe->style != NULL) {
+ name = oe->style;
+ goto retry;
+ }
if ((o = options_find1(oo, oe->name)) == NULL)
return (CMD_RETURN_NORMAL);
optval = options_table_print_entry(oe, o, args_has(self->args, 'v'));
@@ -157,6 +161,8 @@ cmd_show_options_all(struct cmd *self, struct cmd_q *cmdq,
}
for (oe = table; oe->name != NULL; oe++) {
+ if (oe->style != NULL)
+ continue;
if ((o = options_find1(oo, oe->name)) == NULL)
continue;
optval = options_table_print_entry(oe, o,
diff --git a/cmd-source-file.c b/cmd-source-file.c
index eb7e1490..e5710a0c 100644
--- a/cmd-source-file.c
+++ b/cmd-source-file.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
@@ -28,7 +28,6 @@
enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmd_q *);
-void cmd_source_file_show(struct cmd_q *);
void cmd_source_file_done(struct cmd_q *);
const struct cmd_entry cmd_source_file_entry = {
@@ -36,7 +35,6 @@ const struct cmd_entry cmd_source_file_entry = {
"", 1, 1,
"path",
0,
- NULL,
cmd_source_file_exec
};
@@ -60,11 +58,12 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
free(cause);
return (CMD_RETURN_ERROR);
}
- ARRAY_ADD(&cfg_causes, cause);
+ cfg_add_cause("%s", cause);
+ free(cause);
/* FALLTHROUGH */
case 0:
if (cfg_references == 0)
- cmd_source_file_show(cmdq);
+ cfg_print_causes(cmdq);
cmdq_free(cmdq1);
return (CMD_RETURN_NORMAL);
}
@@ -77,20 +76,6 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
}
void
-cmd_source_file_show(struct cmd_q *cmdq)
-{
- u_int i;
- char *cause;
-
- for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
- cause = ARRAY_ITEM(&cfg_causes, i);
- cmdq_print(cmdq, "%s", cause);
- free(cause);
- }
- ARRAY_FREE(&cfg_causes);
-}
-
-void
cmd_source_file_done(struct cmd_q *cmdq1)
{
struct cmd_q *cmdq = cmdq1->data;
@@ -106,6 +91,6 @@ cmd_source_file_done(struct cmd_q *cmdq1)
return;
if (cfg_references == 0)
- cmd_source_file_show(cmdq);
+ cfg_print_causes(cmdq);
cmdq_continue(cmdq);
}
diff --git a/cmd-split-window.c b/cmd-split-window.c
index c43cb96b..1e7bc16a 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,27 +30,19 @@
* Split a window (add a new pane).
*/
-void cmd_split_window_key_binding(struct cmd *, int);
+#define SPLIT_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
+
enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw",
- "c:dF:l:hp:Pt:v", 0, 1,
- "[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
+ "bc:dF:l:hp:Pt:v", 0, -1,
+ "[-bdhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
CMD_TARGET_PANE_USAGE " [command]",
0,
- cmd_split_window_key_binding,
cmd_split_window_exec
};
-void
-cmd_split_window_key_binding(struct cmd *self, int key)
-{
- self->args = args_create(0);
- if (key == '%')
- args_set(self->args, 'h', NULL);
-}
-
enum cmd_retval
cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
@@ -60,14 +52,14 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct window *w;
struct window_pane *wp, *new_wp = NULL;
struct environ env;
- const char *cmd, *shell, *template;
- char *cause, *new_cause, *cp;
+ const char *cmd, *path, *shell, *template;
+ char **argv, *cause, *new_cause, *cp;
u_int hlimit;
- int size, percentage, cwd, fd = -1;
+ int argc, size, percentage, cwd, fd = -1;
enum layout_type type;
struct layout_cell *lc;
- struct client *c;
struct format_tree *ft;
+ struct environ_entry *envent;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
@@ -79,18 +71,24 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
- if (args->argc == 0)
+ if (args->argc == 0) {
cmd = options_get_string(&s->options, "default-command");
- else
- cmd = args->argv[0];
+ if (cmd != NULL && *cmd != '\0') {
+ argc = 1;
+ argv = (char **)&cmd;
+ } else {
+ argc = 0;
+ argv = NULL;
+ }
+ } else {
+ argc = args->argc;
+ argv = args->argv;
+ }
if (args_has(args, 'c')) {
ft = format_create();
- if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
- format_client(ft, c);
- format_session(ft, s);
- format_winlink(ft, s, s->curw);
- format_window_pane(ft, s->curw->window->active);
+ format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, NULL,
+ NULL);
cp = format_expand(ft, args_get(args, 'c'));
format_free(ft);
@@ -142,13 +140,23 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL;
- if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) {
+ lc = layout_split_pane(wp, type, size, args_has(args, 'b'));
+ if (lc == NULL) {
cause = xstrdup("pane too small");
goto error;
}
new_wp = window_add_pane(w, hlimit);
- if (window_pane_spawn(
- new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0)
+
+ path = NULL;
+ if (cmdq->client != NULL && cmdq->client->session == NULL)
+ envent = environ_find(&cmdq->client->environ, "PATH");
+ else
+ envent = environ_find(&s->environ, "PATH");
+ if (envent != NULL)
+ path = envent->value;
+
+ if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env,
+ s->tio, &cause) != 0)
goto error;
layout_assign_pane(lc, new_wp);
@@ -168,11 +176,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
template = SPLIT_WINDOW_TEMPLATE;
ft = format_create();
- if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
- format_client(ft, c);
- format_session(ft, s);
- format_winlink(ft, s, wl);
- format_window_pane(ft, new_wp);
+ format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, wl,
+ new_wp);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
diff --git a/cmd-string.c b/cmd-string.c
index e793ea02..db1723cb 100644
--- a/cmd-string.c
+++ b/cmd-string.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -107,10 +107,11 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, const char *file,
case ' ':
case '\t':
if (buf != NULL) {
- buf = xrealloc(buf, 1, len + 1);
+ buf = xrealloc(buf, len + 1);
buf[len] = '\0';
- argv = xrealloc(argv, argc + 1, sizeof *argv);
+ argv = xreallocarray(argv, argc + 1,
+ sizeof *argv);
argv[argc++] = buf;
buf = NULL;
@@ -151,7 +152,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, const char *file,
if (len >= SIZE_MAX - 2)
goto error;
- buf = xrealloc(buf, 1, len + 1);
+ buf = xrealloc(buf, len + 1);
buf[len++] = ch;
break;
}
@@ -179,7 +180,7 @@ cmd_string_copy(char **dst, char *src, size_t *len)
srclen = strlen(src);
- *dst = xrealloc(*dst, 1, *len + srclen + 1);
+ *dst = xrealloc(*dst, *len + srclen + 1);
strlcpy(*dst + *len, src, srclen + 1);
*len += srclen;
@@ -231,11 +232,11 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
if (len >= SIZE_MAX - 2)
goto error;
- buf = xrealloc(buf, 1, len + 1);
+ buf = xrealloc(buf, len + 1);
buf[len++] = ch;
}
- buf = xrealloc(buf, 1, len + 1);
+ buf = xrealloc(buf, len + 1);
buf[len] = '\0';
return (buf);
@@ -278,7 +279,7 @@ cmd_string_variable(const char *s, size_t *p)
return (t);
}
- buf = xrealloc(buf, 1, len + 1);
+ buf = xrealloc(buf, len + 1);
buf[len++] = ch;
for (;;) {
@@ -288,7 +289,7 @@ cmd_string_variable(const char *s, size_t *p)
else {
if (len >= SIZE_MAX - 3)
goto error;
- buf = xrealloc(buf, 1, len + 1);
+ buf = xrealloc(buf, len + 1);
buf[len++] = ch;
}
}
@@ -299,7 +300,7 @@ cmd_string_variable(const char *s, size_t *p)
if (ch != EOF && fch != '{')
cmd_string_ungetc(p); /* ch */
- buf = xrealloc(buf, 1, len + 1);
+ buf = xrealloc(buf, len + 1);
buf[len] = '\0';
envent = environ_find(&global_environ, buf);
diff --git a/cmd-suspend-client.c b/cmd-suspend-client.c
deleted file mode 100644
index e0e375fc..00000000
--- a/cmd-suspend-client.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* $Id$ */
-
-/*
- * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "tmux.h"
-
-/*
- * Suspend client with SIGTSTP.
- */
-
-enum cmd_retval cmd_suspend_client_exec(struct cmd *, struct cmd_q *);
-
-const struct cmd_entry cmd_suspend_client_entry = {
- "suspend-client", "suspendc",
- "t:", 0, 0,
- CMD_TARGET_CLIENT_USAGE,
- 0,
- NULL,
- cmd_suspend_client_exec
-};
-
-enum cmd_retval
-cmd_suspend_client_exec(struct cmd *self, struct cmd_q *cmdq)
-{
- struct args *args = self->args;
- struct client *c;
-
- if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
- return (CMD_RETURN_ERROR);
-
- tty_stop_tty(&c->tty);
- c->flags |= CLIENT_SUSPENDED;
- server_write_client(c, MSG_SUSPEND, NULL, 0);
-
- return (CMD_RETURN_NORMAL);
-}
diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c
index b8ff7690..918a2e4f 100644
--- a/cmd-swap-pane.c
+++ b/cmd-swap-pane.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,7 +26,6 @@
* Swap two panes.
*/
-void cmd_swap_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_swap_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_swap_pane_entry = {
@@ -34,20 +33,9 @@ const struct cmd_entry cmd_swap_pane_entry = {
"dDs:t:U", 0, 0,
"[-dDU] " CMD_SRCDST_PANE_USAGE,
0,
- cmd_swap_pane_key_binding,
cmd_swap_pane_exec
};
-void
-cmd_swap_pane_key_binding(struct cmd *self, int key)
-{
- self->args = args_create(0);
- if (key == '{')
- args_set(self->args, 'U', NULL);
- else if (key == '}')
- args_set(self->args, 'D', NULL);
-}
-
enum cmd_retval
cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
diff --git a/cmd-swap-window.c b/cmd-swap-window.c
index 1591d403..655b910c 100644
--- a/cmd-swap-window.c
+++ b/cmd-swap-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,7 +33,6 @@ const struct cmd_entry cmd_swap_window_entry = {
"ds:t:", 0, 0,
"[-d] " CMD_SRCDST_WINDOW_USAGE,
0,
- NULL,
cmd_swap_window_exec
};
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index d8f7346f..439f593b 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,7 +27,6 @@
* Switch client to a different session.
*/
-void cmd_switch_client_key_binding(struct cmd *, int);
enum cmd_retval cmd_switch_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_switch_client_entry = {
@@ -35,27 +34,9 @@ const struct cmd_entry cmd_switch_client_entry = {
"lc:npt:r", 0, 0,
"[-lnpr] [-c target-client] [-t target-session]",
CMD_READONLY,
- cmd_switch_client_key_binding,
cmd_switch_client_exec
};
-void
-cmd_switch_client_key_binding(struct cmd *self, int key)
-{
- self->args = args_create(0);
- switch (key) {
- case '(':
- args_set(self->args, 'p', NULL);
- break;
- case ')':
- args_set(self->args, 'n', NULL);
- break;
- case 'L':
- args_set(self->args, 'l', NULL);
- break;
- }
-}
-
enum cmd_retval
cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
@@ -71,13 +52,10 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
if (args_has(args, 'r')) {
- if (c->flags & CLIENT_READONLY) {
+ if (c->flags & CLIENT_READONLY)
c->flags &= ~CLIENT_READONLY;
- cmdq_info(cmdq, "made client writable");
- } else {
+ else
c->flags |= CLIENT_READONLY;
- cmdq_info(cmdq, "made client read-only");
- }
}
tflag = args_get(args, 't');
diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c
index cf6ad506..710210ce 100644
--- a/cmd-unbind-key.c
+++ b/cmd-unbind-key.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,14 +27,13 @@
*/
enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
-enum cmd_retval cmd_unbind_key_table(struct cmd *, struct cmd_q *, int);
+enum cmd_retval cmd_unbind_key_mode_table(struct cmd *, struct cmd_q *, int);
const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind",
"acnt:", 0, 1,
- "[-acn] [-t key-table] key",
+ "[-acn] [-t mode-table] key",
0,
- NULL,
cmd_unbind_key_exec
};
@@ -64,7 +63,7 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
if (args_has(args, 't'))
- return (cmd_unbind_key_table(self, cmdq, key));
+ return (cmd_unbind_key_mode_table(self, cmdq, key));
if (key == KEYC_NONE) {
while (!RB_EMPTY(&key_bindings)) {
@@ -81,7 +80,7 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
enum cmd_retval
-cmd_unbind_key_table(struct cmd *self, struct cmd_q *cmdq, int key)
+cmd_unbind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, int key)
{
struct args *args = self->args;
const char *tablename;
diff --git a/cmd-unlink-window.c b/cmd-unlink-window.c
deleted file mode 100644
index ec69b91f..00000000
--- a/cmd-unlink-window.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* $Id$ */
-
-/*
- * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include "tmux.h"
-
-/*
- * Unlink a window, unless it would be destroyed by doing so (only one link).
- */
-
-enum cmd_retval cmd_unlink_window_exec(struct cmd *, struct cmd_q *);
-
-const struct cmd_entry cmd_unlink_window_entry = {
- "unlink-window", "unlinkw",
- "kt:", 0, 0,
- "[-k] " CMD_TARGET_WINDOW_USAGE,
- 0,
- NULL,
- cmd_unlink_window_exec
-};
-
-enum cmd_retval
-cmd_unlink_window_exec(struct cmd *self, struct cmd_q *cmdq)
-{
- struct args *args = self->args;
- struct winlink *wl;
- struct window *w;
- struct session *s, *s2;
- struct session_group *sg;
- u_int references;
-
- if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
- return (CMD_RETURN_ERROR);
- w = wl->window;
-
- sg = session_group_find(s);
- if (sg != NULL) {
- references = 0;
- TAILQ_FOREACH(s2, &sg->sessions, gentry)
- references++;
- } else
- references = 1;
-
- if (!args_has(self->args, 'k') && w->references == references) {
- cmdq_error(cmdq, "window is only linked to one session");
- return (CMD_RETURN_ERROR);
- }
-
- server_unlink_window(s, wl);
- recalculate_sizes();
-
- return (CMD_RETURN_NORMAL);
-}
diff --git a/cmd-wait-for.c b/cmd-wait-for.c
index e251863d..a3e85856 100644
--- a/cmd-wait-for.c
+++ b/cmd-wait-for.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -35,7 +35,6 @@ const struct cmd_entry cmd_wait_for_entry = {
"LSU", 1, 1,
"[-L|-S|-U] channel",
0,
- NULL,
cmd_wait_for_exec
};
@@ -108,7 +107,7 @@ cmd_wait_for_signal(struct cmd_q *cmdq, const char *name,
if (!wc->locked) {
RB_REMOVE(wait_channels, &wait_channels, wc);
- free((void*) wc->name);
+ free((void *)wc->name);
free(wc);
}
@@ -186,7 +185,7 @@ cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name,
wc->locked = 0;
if (TAILQ_EMPTY(&wc->waiters)) {
RB_REMOVE(wait_channels, &wait_channels, wc);
- free((void*) wc->name);
+ free((void *)wc->name);
free(wc);
}
}
@@ -194,3 +193,25 @@ cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name,
return (CMD_RETURN_NORMAL);
}
+void
+cmd_wait_for_flush(void)
+{
+ struct wait_channel *wc, *wc1;
+ struct cmd_q *wq, *wq1;
+
+ RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) {
+ TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) {
+ TAILQ_REMOVE(&wc->waiters, wq, waitentry);
+ if (!cmdq_free(wq))
+ cmdq_continue(wq);
+ }
+ while ((wq = TAILQ_FIRST(&wc->lockers)) != NULL) {
+ TAILQ_REMOVE(&wc->lockers, wq, waitentry);
+ if (!cmdq_free(wq))
+ cmdq_continue(wq);
+ }
+ RB_REMOVE(wait_channels, &wait_channels, wc);
+ free((void *)wc->name);
+ free(wc);
+ }
+}
diff --git a/cmd.c b/cmd.c
index 5e6b93aa..eeffe4c7 100644
--- a/cmd.c
+++ b/cmd.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -34,7 +34,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_capture_pane_entry,
&cmd_choose_buffer_entry,
&cmd_choose_client_entry,
- &cmd_choose_list_entry,
&cmd_choose_session_entry,
&cmd_choose_tree_entry,
&cmd_choose_window_entry,
@@ -121,7 +120,7 @@ struct session *cmd_choose_session_list(struct sessionslist *);
struct session *cmd_choose_session(int);
struct client *cmd_choose_client(struct clients *);
struct client *cmd_lookup_client(const char *);
-struct session *cmd_lookup_session(const char *, int *);
+struct session *cmd_lookup_session(struct cmd_q *, const char *, int *);
struct session *cmd_lookup_session_id(const char *);
struct winlink *cmd_lookup_window(struct session *, const char *, int *);
int cmd_lookup_index(struct session *, const char *, int *);
@@ -138,6 +137,9 @@ cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
size_t arglen;
int i;
+ if (argc == 0)
+ return (0);
+
*buf = '\0';
for (i = 0; i < argc; i++) {
if (strlcpy(buf, argv[i], len) >= len)
@@ -177,14 +179,14 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
}
char **
-cmd_copy_argv(int argc, char *const *argv)
+cmd_copy_argv(int argc, char **argv)
{
char **new_argv;
int i;
if (argc == 0)
return (NULL);
- new_argv = xcalloc(argc, sizeof *new_argv);
+ new_argv = xcalloc(argc + 1, sizeof *new_argv);
for (i = 0; i < argc; i++) {
if (argv[i] != NULL)
new_argv[i] = xstrdup(argv[i]);
@@ -204,6 +206,32 @@ cmd_free_argv(int argc, char **argv)
free(argv);
}
+char *
+cmd_stringify_argv(int argc, char **argv)
+{
+ char *buf;
+ int i;
+ size_t len;
+
+ if (argc == 0)
+ return (xstrdup(""));
+
+ len = 0;
+ buf = NULL;
+
+ for (i = 0; i < argc; i++) {
+ len += strlen(argv[i]) + 1;
+ buf = xrealloc(buf, len);
+
+ if (i == 0)
+ *buf = '\0';
+ else
+ strlcat(buf, " ", len);
+ strlcat(buf, argv[i], len);
+ }
+ return (buf);
+}
+
struct cmd *
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
{
@@ -556,9 +584,11 @@ cmd_lookup_session_id(const char *arg)
/* Lookup a session by name. If no session is found, NULL is returned. */
struct session *
-cmd_lookup_session(const char *name, int *ambiguous)
+cmd_lookup_session(struct cmd_q *cmdq, const char *name, int *ambiguous)
{
- struct session *s, *sfound;
+ struct session *s, *sfound;
+ struct window *w;
+ struct window_pane *wp;
*ambiguous = 0;
@@ -566,6 +596,12 @@ cmd_lookup_session(const char *name, int *ambiguous)
if ((s = cmd_lookup_session_id(name)) != NULL)
return (s);
+ /* Try as pane or window id. */
+ if ((wp = cmd_lookup_paneid(name)) != NULL)
+ return (cmd_window_session(cmdq, wp->window, NULL));
+ if ((w = cmd_lookup_windowid(name)) != NULL)
+ return (cmd_window_session(cmdq, w, NULL));
+
/*
* Look for matches. First look for exact matches - session names must
* be unique so an exact match can't be ambigious and can just be
@@ -601,16 +637,30 @@ cmd_lookup_session(const char *name, int *ambiguous)
struct winlink *
cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
{
- struct winlink *wl, *wlfound;
- const char *errstr;
- u_int idx;
+ struct winlink *wl, *wlfound;
+ struct window *w;
+ struct window_pane *wp;
+ const char *errstr;
+ u_int idx;
*ambiguous = 0;
- /* Try as a window id. */
+ /* Try as pane or window id. */
if ((wl = cmd_lookup_winlink_windowid(s, name)) != NULL)
return (wl);
+ /* Lookup as pane or window id. */
+ if ((wp = cmd_lookup_paneid(name)) != NULL) {
+ wl = winlink_find_by_window(&s->windows, wp->window);
+ if (wl != NULL)
+ return (wl);
+ }
+ if ((w = cmd_lookup_windowid(name)) != NULL) {
+ wl = winlink_find_by_window(&s->windows, w);
+ if (wl != NULL)
+ return (wl);
+ }
+
/* First see if this is a valid window index in this session. */
idx = strtonum(name, 0, INT_MAX, &errstr);
if (errstr == NULL) {
@@ -757,23 +807,18 @@ cmd_window_session(struct cmd_q *cmdq, struct window *w, struct winlink **wlp)
struct session *
cmd_find_session(struct cmd_q *cmdq, const char *arg, int prefer_unattached)
{
- struct session *s;
- struct window_pane *wp;
- struct window *w;
- struct client *c;
- char *tmparg;
- size_t arglen;
- int ambiguous;
+ struct session *s;
+ struct client *c;
+ char *tmparg;
+ size_t arglen;
+ int ambiguous;
/* A NULL argument means the current session. */
- if (arg == NULL)
- return (cmd_current_session(cmdq, prefer_unattached));
-
- /* Lookup as pane id or window id. */
- if ((wp = cmd_lookup_paneid(arg)) != NULL)
- return (cmd_window_session(cmdq, wp->window, NULL));
- if ((w = cmd_lookup_windowid(arg)) != NULL)
- return (cmd_window_session(cmdq, w, NULL));
+ if (arg == NULL) {
+ if ((s = cmd_current_session(cmdq, prefer_unattached)) == NULL)
+ cmdq_error(cmdq, "can't establish current session");
+ return (s);
+ }
/* Trim a single trailing colon if any. */
tmparg = xstrdup(arg);
@@ -784,11 +829,13 @@ cmd_find_session(struct cmd_q *cmdq, const char *arg, int prefer_unattached)
/* An empty session name is the current session. */
if (*tmparg == '\0') {
free(tmparg);
- return (cmd_current_session(cmdq, prefer_unattached));
+ if ((s = cmd_current_session(cmdq, prefer_unattached)) == NULL)
+ cmdq_error(cmdq, "can't establish current session");
+ return (s);
}
/* Find the session, if any. */
- s = cmd_lookup_session(tmparg, &ambiguous);
+ s = cmd_lookup_session(cmdq, tmparg, &ambiguous);
/* If it doesn't, try to match it as a client. */
if (s == NULL && (c = cmd_lookup_client(tmparg)) != NULL)
@@ -810,12 +857,11 @@ cmd_find_session(struct cmd_q *cmdq, const char *arg, int prefer_unattached)
struct winlink *
cmd_find_window(struct cmd_q *cmdq, const char *arg, struct session **sp)
{
- struct session *s;
- struct winlink *wl;
- struct window_pane *wp;
- const char *winptr;
- char *sessptr = NULL;
- int ambiguous = 0;
+ struct session *s;
+ struct winlink *wl;
+ const char *winptr;
+ char *sessptr = NULL;
+ int ambiguous = 0;
/*
* Find the current session. There must always be a current session, if
@@ -833,14 +879,6 @@ cmd_find_window(struct cmd_q *cmdq, const char *arg, struct session **sp)
return (s->curw);
}
- /* Lookup as pane id. */
- if ((wp = cmd_lookup_paneid(arg)) != NULL) {
- s = cmd_window_session(cmdq, wp->window, &wl);
- if (sp != NULL)
- *sp = s;
- return (wl);
- }
-
/* Time to look at the argument. If it is empty, that is an error. */
if (*arg == '\0')
goto not_found;
@@ -855,7 +893,7 @@ cmd_find_window(struct cmd_q *cmdq, const char *arg, struct session **sp)
/* Try to lookup the session if present. */
if (*sessptr != '\0') {
- if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
+ if ((s = cmd_lookup_session(cmdq, sessptr, &ambiguous)) == NULL)
goto no_session;
}
if (sp != NULL)
@@ -906,7 +944,8 @@ no_colon:
lookup_session:
if (ambiguous)
goto not_found;
- if (*arg != '\0' && (s = cmd_lookup_session(arg, &ambiguous)) == NULL)
+ if (*arg != '\0' &&
+ (s = cmd_lookup_session(cmdq, arg, &ambiguous)) == NULL)
goto no_session;
if (sp != NULL)
@@ -996,7 +1035,7 @@ cmd_find_index(struct cmd_q *cmdq, const char *arg, struct session **sp)
/* Try to lookup the session if present. */
if (sessptr != NULL && *sessptr != '\0') {
- if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
+ if ((s = cmd_lookup_session(cmdq, sessptr, &ambiguous)) == NULL)
goto no_session;
}
if (sp != NULL)
@@ -1044,7 +1083,8 @@ no_colon:
lookup_session:
if (ambiguous)
goto not_found;
- if (*arg != '\0' && (s = cmd_lookup_session(arg, &ambiguous)) == NULL)
+ if (*arg != '\0' &&
+ (s = cmd_lookup_session(cmdq, arg, &ambiguous)) == NULL)
goto no_session;
if (sp != NULL)
@@ -1158,7 +1198,13 @@ cmd_find_pane(struct cmd_q *cmdq,
*wpp = wl->window->active;
else if (paneptr[0] == '+' || paneptr[0] == '-')
*wpp = cmd_find_pane_offset(paneptr, wl);
- else {
+ else if (paneptr[0] == '!' && paneptr[1] == '\0') {
+ if (wl->window->last == NULL) {
+ cmdq_error(cmdq, "no last pane");
+ goto error;
+ }
+ *wpp = wl->window->last;
+ } else {
idx = strtonum(paneptr, 0, INT_MAX, &errstr);
if (errstr != NULL)
goto lookup_string;
@@ -1255,11 +1301,11 @@ cmd_template_replace(const char *template, const char *s, int idx)
ptr++;
len += strlen(s);
- buf = xrealloc(buf, 1, len + 1);
+ buf = xrealloc(buf, len + 1);
strlcat(buf, s, len + 1);
continue;
}
- buf = xrealloc(buf, 1, len + 2);
+ buf = xrealloc(buf, len + 2);
buf[len++] = ch;
buf[len] = '\0';
}
diff --git a/colour.c b/colour.c
index da1cb421..9e90596f 100644
--- a/colour.c
+++ b/colour.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/compat.h b/compat.h
index 65d6ec7a..5f3ff8fc 100644
--- a/compat.h
+++ b/compat.h
@@ -176,6 +176,17 @@ typedef uint64_t u_int64_t;
#define TTY_NAME_MAX 32
#endif
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 255
+#endif
+
+#ifndef HAVE_FLOCK
+#define LOCK_SH 0
+#define LOCK_EX 0
+#define LOCK_NB 0
+#define flock(fd, op) (0)
+#endif
+
#ifndef HAVE_BZERO
#undef bzero
#define bzero(buf, len) memset(buf, 0, len);
@@ -239,6 +250,10 @@ int vasprintf(char **, const char *, va_list);
char *fgetln(FILE *, size_t *);
#endif
+#ifndef HAVE_FPARSELN
+char *fparseln(FILE *, size_t *, size_t *, const char *, int);
+#endif
+
#ifndef HAVE_SETENV
/* setenv.c */
int setenv(const char *, const char *, int);
diff --git a/compat/asprintf.c b/compat/asprintf.c
index 66f00996..09020b35 100644
--- a/compat/asprintf.c
+++ b/compat/asprintf.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/*
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
*
@@ -56,10 +54,12 @@ vasprintf(char **ret, const char *fmt, va_list ap)
free(*ret);
goto error;
}
+ va_end(ap2);
return (n);
error:
+ va_end(ap2);
*ret = NULL;
return (-1);
}
diff --git a/compat/bitstring.h b/compat/bitstring.h
index 28817c08..8fc3423e 100644
--- a/compat/bitstring.h
+++ b/compat/bitstring.h
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: bitstring.h,v 1.5 2003/06/02 19:34:12 millert Exp $ */
/* $NetBSD: bitstring.h,v 1.5 1997/05/14 15:49:55 pk Exp $ */
diff --git a/compat/cfmakeraw.c b/compat/cfmakeraw.c
index 3f8dc7e5..85b2c9bc 100644
--- a/compat/cfmakeraw.c
+++ b/compat/cfmakeraw.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/*
* Copyright (c) 2013 Dagobert Michelsen
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/compat/closefrom.c b/compat/closefrom.c
index 74714c13..591769dd 100644
--- a/compat/closefrom.c
+++ b/compat/closefrom.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/*
* Copyright (c) 2004-2005 Todd C. Miller <Todd.Miller@courtesan.com>
*
diff --git a/compat/daemon.c b/compat/daemon.c
index 661f7fd5..3e87874b 100644
--- a/compat/daemon.c
+++ b/compat/daemon.c
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: daemon.c,v 1.6 2005/08/08 08:05:33 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
diff --git a/compat/fgetln.c b/compat/fgetln.c
index 08ddc840..a5c2489d 100644
--- a/compat/fgetln.c
+++ b/compat/fgetln.c
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $NetBSD: fgetln.c,v 1.3 2007/08/07 02:06:58 lukem Exp $ */
/*-
diff --git a/compat/forkpty-aix.c b/compat/forkpty-aix.c
index db9c2e71..fd558eb8 100644
--- a/compat/forkpty-aix.c
+++ b/compat/forkpty-aix.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
@@ -23,19 +21,23 @@
#include <stdlib.h>
#include <stropts.h>
#include <unistd.h>
+#include <errno.h>
#include "tmux.h"
pid_t
forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
{
- int slave, fd;
- char *path;
+ int slave = -1, fd, pipe_fd[2];
+ char *path, dummy;
pid_t pid;
- if ((*master = open("/dev/ptc", O_RDWR|O_NOCTTY)) == -1)
+ if (pipe(pipe_fd) == -1)
return (-1);
+ if ((*master = open("/dev/ptc", O_RDWR|O_NOCTTY)) == -1)
+ goto out;
+
if ((path = ttyname(*master)) == NULL)
goto out;
if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1)
@@ -47,6 +49,13 @@ forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
case 0:
close(*master);
+ close(pipe_fd[1]);
+ while (read(pipe_fd[0], &dummy, 1) == -1) {
+ if (errno != EINTR)
+ break;
+ }
+ close(pipe_fd[0]);
+
fd = open(_PATH_TTY, O_RDWR|O_NOCTTY);
if (fd >= 0) {
ioctl(fd, TIOCNOTTY, NULL);
@@ -80,10 +89,14 @@ forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
dup2(slave, 2);
if (slave > 2)
close(slave);
+
return (0);
}
close(slave);
+
+ close(pipe_fd[0]);
+ close(pipe_fd[1]);
return (pid);
out:
@@ -91,5 +104,8 @@ out:
close(*master);
if (slave != -1)
close(slave);
+
+ close(pipe_fd[0]);
+ close(pipe_fd[1]);
return (-1);
}
diff --git a/compat/forkpty-hpux.c b/compat/forkpty-hpux.c
index 90452f8d..59130e1b 100644
--- a/compat/forkpty-hpux.c
+++ b/compat/forkpty-hpux.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
@@ -29,7 +27,7 @@
pid_t
forkpty(int *master, char *name, struct termios *tio, struct winsize *ws)
{
- int slave;
+ int slave = -1;
char *path;
pid_t pid;
diff --git a/compat/forkpty-sunos.c b/compat/forkpty-sunos.c
index 7b254d82..554e51ac 100644
--- a/compat/forkpty-sunos.c
+++ b/compat/forkpty-sunos.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
@@ -30,7 +28,7 @@
pid_t
forkpty(int *master, char *name, struct termios *tio, struct winsize *ws)
{
- int slave;
+ int slave = -1;
char *path;
pid_t pid;
diff --git a/compat/fparseln.c b/compat/fparseln.c
new file mode 100644
index 00000000..348bfa14
--- /dev/null
+++ b/compat/fparseln.c
@@ -0,0 +1,221 @@
+/* $OpenBSD: fparseln.c,v 1.6 2005/08/02 21:46:23 espie Exp $ */
+/* $NetBSD: fparseln.c,v 1.7 1999/07/02 15:49:12 simonb Exp $ */
+
+/*
+ * Copyright (c) 1997 Christos Zoulas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* OPENBSD ORIGINAL: lib/libutil/fparseln.c */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tmux.h"
+
+/*
+ * fparseln() specific operation flags.
+ */
+#define FPARSELN_UNESCESC 0x01
+#define FPARSELN_UNESCCONT 0x02
+#define FPARSELN_UNESCCOMM 0x04
+#define FPARSELN_UNESCREST 0x08
+#define FPARSELN_UNESCALL 0x0f
+
+static int isescaped(const char *, const char *, int);
+
+/* isescaped():
+ * Return true if the character in *p that belongs to a string
+ * that starts in *sp, is escaped by the escape character esc.
+ */
+static int
+isescaped(const char *sp, const char *p, int esc)
+{
+ const char *cp;
+ size_t ne;
+
+ /* No escape character */
+ if (esc == '\0')
+ return 1;
+
+ /* Count the number of escape characters that precede ours */
+ for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++)
+ continue;
+
+ /* Return true if odd number of escape characters */
+ return (ne & 1) != 0;
+}
+
+
+/* fparseln():
+ * Read a line from a file parsing continuations ending in \
+ * and eliminating trailing newlines, or comments starting with
+ * the comment char.
+ */
+char *
+fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3],
+ int flags)
+{
+ static const char dstr[3] = { '\\', '\\', '#' };
+ char *buf = NULL, *ptr, *cp, esc, con, nl, com;
+ size_t s, len = 0;
+ int cnt = 1;
+
+ if (str == NULL)
+ str = dstr;
+
+ esc = str[0];
+ con = str[1];
+ com = str[2];
+
+ /*
+ * XXX: it would be cool to be able to specify the newline character,
+ * but unfortunately, fgetln does not let us
+ */
+ nl = '\n';
+
+ while (cnt) {
+ cnt = 0;
+
+ if (lineno)
+ (*lineno)++;
+
+ if ((ptr = fgetln(fp, &s)) == NULL)
+ break;
+
+ if (s && com) { /* Check and eliminate comments */
+ for (cp = ptr; cp < ptr + s; cp++)
+ if (*cp == com && !isescaped(ptr, cp, esc)) {
+ s = cp - ptr;
+ cnt = s == 0 && buf == NULL;
+ break;
+ }
+ }
+
+ if (s && nl) { /* Check and eliminate newlines */
+ cp = &ptr[s - 1];
+
+ if (*cp == nl)
+ s--; /* forget newline */
+ }
+
+ if (s && con) { /* Check and eliminate continuations */
+ cp = &ptr[s - 1];
+
+ if (*cp == con && !isescaped(ptr, cp, esc)) {
+ s--; /* forget escape */
+ cnt = 1;
+ }
+ }
+
+ if (s == 0 && buf != NULL)
+ continue;
+
+ if ((cp = realloc(buf, len + s + 1)) == NULL) {
+ free(buf);
+ return NULL;
+ }
+ buf = cp;
+
+ (void) memcpy(buf + len, ptr, s);
+ len += s;
+ buf[len] = '\0';
+ }
+
+ if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
+ strchr(buf, esc) != NULL) {
+ ptr = cp = buf;
+ while (cp[0] != '\0') {
+ int skipesc;
+
+ while (cp[0] != '\0' && cp[0] != esc)
+ *ptr++ = *cp++;
+ if (cp[0] == '\0' || cp[1] == '\0')
+ break;
+
+ skipesc = 0;
+ if (cp[1] == com)
+ skipesc += (flags & FPARSELN_UNESCCOMM);
+ if (cp[1] == con)
+ skipesc += (flags & FPARSELN_UNESCCONT);
+ if (cp[1] == esc)
+ skipesc += (flags & FPARSELN_UNESCESC);
+ if (cp[1] != com && cp[1] != con && cp[1] != esc)
+ skipesc = (flags & FPARSELN_UNESCREST);
+
+ if (skipesc)
+ cp++;
+ else
+ *ptr++ = *cp++;
+ *ptr++ = *cp++;
+ }
+ *ptr = '\0';
+ len = strlen(buf);
+ }
+
+ if (size)
+ *size = len;
+ return buf;
+}
+
+#ifdef TEST
+
+int main(int, char **);
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *ptr;
+ size_t size, line;
+
+ line = 0;
+ while ((ptr = fparseln(stdin, &size, &line, NULL,
+ FPARSELN_UNESCALL)) != NULL)
+ printf("line %d (%d) |%s|\n", line, size, ptr);
+ return 0;
+}
+
+/*
+
+# This is a test
+line 1
+line 2 \
+line 3 # Comment
+line 4 \# Not comment \\\\
+
+# And a comment \
+line 5 \\\
+line 6
+
+*/
+
+#endif /* TEST */
diff --git a/compat/getopt.c b/compat/getopt.c
index 38c317cc..a93f368a 100644
--- a/compat/getopt.c
+++ b/compat/getopt.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
diff --git a/compat/imsg-buffer.c b/compat/imsg-buffer.c
index 2ddf0f77..450fdf1b 100644
--- a/compat/imsg-buffer.c
+++ b/compat/imsg-buffer.c
@@ -1,5 +1,4 @@
-/* $Id$ */
-/* $OpenBSD: imsg-buffer.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
+/* $OpenBSD: imsg-buffer.c,v 1.4 2014/06/30 00:25:17 deraadt Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -17,17 +16,19 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <strings.h>
#include <unistd.h>
#include "tmux.h"
+#include "imsg.h"
int ibuf_realloc(struct ibuf *, size_t);
void ibuf_enqueue(struct msgbuf *, struct ibuf *);
@@ -158,22 +159,23 @@ ibuf_write(struct msgbuf *msgbuf)
i++;
}
+again:
if ((n = writev(msgbuf->fd, iov, i)) == -1) {
- if (errno == EAGAIN || errno == ENOBUFS ||
- errno == EINTR) /* try later */
- return (0);
- else
- return (-1);
+ if (errno == EINTR)
+ goto again;
+ if (errno == ENOBUFS)
+ errno = EAGAIN;
+ return (-1);
}
if (n == 0) { /* connection closed */
errno = 0;
- return (-2);
+ return (0);
}
msgbuf_drain(msgbuf, n);
- return (0);
+ return (1);
}
void
@@ -257,17 +259,18 @@ msgbuf_write(struct msgbuf *msgbuf)
*(int *)CMSG_DATA(cmsg) = buf->fd;
}
+again:
if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
- if (errno == EAGAIN || errno == ENOBUFS ||
- errno == EINTR) /* try later */
- return (0);
- else
- return (-1);
+ if (errno == EINTR)
+ goto again;
+ if (errno == ENOBUFS)
+ errno = EAGAIN;
+ return (-1);
}
if (n == 0) { /* connection closed */
errno = 0;
- return (-2);
+ return (0);
}
/*
@@ -281,7 +284,7 @@ msgbuf_write(struct msgbuf *msgbuf)
msgbuf_drain(msgbuf, n);
- return (0);
+ return (1);
}
void
diff --git a/compat/imsg.c b/compat/imsg.c
index c4dd191d..af0da44f 100644
--- a/compat/imsg.c
+++ b/compat/imsg.c
@@ -1,5 +1,4 @@
-/* $Id$ */
-/* $OpenBSD: imsg.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
+/* $OpenBSD: imsg.c,v 1.6 2014/06/30 00:26:22 deraadt Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -17,20 +16,55 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <strings.h>
#include <unistd.h>
#include "tmux.h"
+#include "imsg.h"
+
+int imsg_fd_overhead = 0;
int imsg_get_fd(struct imsgbuf *);
+int available_fds(unsigned int);
+
+/* TA: 2014-09-08: Note that the original code calls getdtablecount() which is
+ * OpenBSD specific. Until such time that it's ported elsewhere from
+ * <unistd.h>, I've mimicked what OpenSMTPD are doing, by using available_fds()
+ * instead.
+ */
+
+int
+available_fds(unsigned int n)
+{
+ unsigned int i;
+ int ret, fds[256];
+
+ if (n > (sizeof(fds)/sizeof(fds[0])))
+ return (1);
+
+ ret = 0;
+ for (i = 0; i < n; i++) {
+ fds[i] = -1;
+ if ((fds[i] = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ ret = 1;
+ break;
+ }
+ }
+
+ for (i = 0; i < n && fds[i] >= 0; i++)
+ close(fds[i]);
+
+ return (ret);
+}
+
void
imsg_init(struct imsgbuf *ibuf, int fd)
{
@@ -49,10 +83,10 @@ imsg_read(struct imsgbuf *ibuf)
struct cmsghdr *cmsg;
union {
struct cmsghdr hdr;
- char buf[CMSG_SPACE(sizeof(int) * 16)];
+ char buf[CMSG_SPACE(sizeof(int) * 1)];
} cmsgbuf;
struct iovec iov;
- ssize_t n;
+ ssize_t n = -1;
int fd;
struct imsg_fd *ifd;
@@ -65,11 +99,23 @@ imsg_read(struct imsgbuf *ibuf)
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
+ if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
+ return (-1);
+
+again:
+ if (available_fds(imsg_fd_overhead +
+ (CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))) {
+ errno = EAGAIN;
+ free(ifd);
+ return (-1);
+ }
+
if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
- if (errno != EINTR && errno != EAGAIN) {
- return (-1);
- }
- return (-2);
+ if (errno == EMSGSIZE)
+ goto fail;
+ if (errno != EINTR && errno != EAGAIN)
+ goto fail;
+ goto again;
}
ibuf->r.wpos += n;
@@ -78,17 +124,33 @@ imsg_read(struct imsgbuf *ibuf)
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
- fd = (*(int *)CMSG_DATA(cmsg));
- if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) {
- close(fd);
- return (-1);
+ int i;
+ int j;
+
+ /*
+ * We only accept one file descriptor. Due to C
+ * padding rules, our control buffer might contain
+ * more than one fd, and we must close them.
+ */
+ j = ((char *)cmsg + cmsg->cmsg_len -
+ (char *)CMSG_DATA(cmsg)) / sizeof(int);
+ for (i = 0; i < j; i++) {
+ fd = ((int *)CMSG_DATA(cmsg))[i];
+ if (ifd != NULL) {
+ ifd->fd = fd;
+ TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
+ entry);
+ ifd = NULL;
+ } else
+ close(fd);
}
- ifd->fd = fd;
- TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry);
}
/* we do not handle other ctl data level */
}
+fail:
+ if (ifd)
+ free(ifd);
return (n);
}
@@ -112,7 +174,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
return (0);
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
- if ((imsg->data = malloc(datalen)) == NULL && datalen != 0)
+ if ((imsg->data = malloc(datalen)) == NULL)
return (-1);
if (imsg->hdr.flags & IMSGF_HASFD)
@@ -134,7 +196,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
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)
+ pid_t pid, int fd, const void *data, u_int16_t datalen)
{
struct ibuf *wbuf;
@@ -204,7 +266,7 @@ imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
}
int
-imsg_add(struct ibuf *msg, void *data, u_int16_t datalen)
+imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen)
{
if (datalen)
if (ibuf_add(msg, data, datalen) == -1) {
diff --git a/compat/imsg.h b/compat/imsg.h
index f8a78e22..06fe1bc1 100644
--- a/compat/imsg.h
+++ b/compat/imsg.h
@@ -1,5 +1,4 @@
-/* $Id$ */
-/* $OpenBSD: imsg.h,v 1.4 2010/05/26 13:56:07 nicm Exp $ */
+/* $OpenBSD: imsg.h,v 1.3 2013/12/26 17:32:33 eric Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -21,6 +20,9 @@
#include "tmux.h"
+#ifndef _IMSG_H_
+#define _IMSG_H_
+
#define IBUF_READ_SIZE 65535
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
#define MAX_IMSGSIZE 16384
@@ -98,13 +100,15 @@ void imsg_init(struct imsgbuf *, int);
ssize_t imsg_read(struct imsgbuf *);
ssize_t imsg_get(struct imsgbuf *, struct imsg *);
int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
- int, void *, u_int16_t);
+ int, const void *, u_int16_t);
int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
int, const struct iovec *, int);
struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
u_int16_t);
-int imsg_add(struct ibuf *, void *, u_int16_t);
+int imsg_add(struct ibuf *, const 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 *);
+
+#endif
diff --git a/compat/openat.c b/compat/openat.c
index 005235b4..5cd9e551 100644
--- a/compat/openat.c
+++ b/compat/openat.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
*
diff --git a/compat/setenv.c b/compat/setenv.c
index 43122ba5..6c7d29ec 100644
--- a/compat/setenv.c
+++ b/compat/setenv.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
/*
* Copyright (c) 2010 Dagobert Michelsen
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/compat/strcasestr.c b/compat/strcasestr.c
index 5e03bbb0..aa74c017 100644
--- a/compat/strcasestr.c
+++ b/compat/strcasestr.c
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: strcasestr.c,v 1.3 2006/03/31 05:34:55 deraadt Exp $ */
/* $NetBSD: strcasestr.c,v 1.2 2005/02/09 21:35:47 kleink Exp $ */
diff --git a/compat/strlcat.c b/compat/strlcat.c
index 1ba236e2..e081c4f6 100644
--- a/compat/strlcat.c
+++ b/compat/strlcat.c
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
/*
diff --git a/compat/strlcpy.c b/compat/strlcpy.c
index 80e13a8f..d6e8e77c 100644
--- a/compat/strlcpy.c
+++ b/compat/strlcpy.c
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
/*
diff --git a/compat/strsep.c b/compat/strsep.c
index 0a7aa328..c44bc5b2 100644
--- a/compat/strsep.c
+++ b/compat/strsep.c
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: strsep.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
/*-
diff --git a/compat/strtonum.c b/compat/strtonum.c
index 860e5508..4c7b0c9f 100644
--- a/compat/strtonum.c
+++ b/compat/strtonum.c
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
/*
diff --git a/compat/tree.h b/compat/tree.h
index 73041340..80d0f538 100644
--- a/compat/tree.h
+++ b/compat/tree.h
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: tree.h,v 1.13 2011/07/09 00:19:45 pirofti Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
diff --git a/compat/unvis.c b/compat/unvis.c
index 874b2275..e1f09ec9 100644
--- a/compat/unvis.c
+++ b/compat/unvis.c
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: unvis.c,v 1.12 2005/08/08 08:05:34 espie Exp $ */
/*-
* Copyright (c) 1989, 1993
diff --git a/compat/vis.c b/compat/vis.c
index da4ac7cd..97eb5271 100644
--- a/compat/vis.c
+++ b/compat/vis.c
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: vis.c,v 1.19 2005/09/01 17:15:49 millert Exp $ */
/*-
* Copyright (c) 1989, 1993
diff --git a/compat/vis.h b/compat/vis.h
index e43e9adc..d6ff235d 100644
--- a/compat/vis.h
+++ b/compat/vis.h
@@ -1,4 +1,3 @@
-/* $Id$ */
/* $OpenBSD: vis.h,v 1.11 2005/08/09 19:38:31 millert Exp $ */
/* $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $ */
diff --git a/configure.ac b/configure.ac
index 4d6f2d1c..a5b212ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,9 @@
# $Id$
# Miscellaneous autofoo bullshit.
-AC_INIT(tmux, 1.9)
+AC_INIT(tmux, 2.0)
+RELEASE=1.9a
+AC_SUBST(RELEASE)
AC_CONFIG_AUX_DIR(etc)
AM_INIT_AUTOMAKE([foreign subdir-objects])
@@ -16,36 +18,13 @@ AC_CANONICAL_HOST
# Set up the compiler in two different ways and say yes we may want to install.
AC_PROG_CC
AM_PROG_CC_C_O
-AC_PROG_MKDIR_P
AC_PROG_INSTALL
# Default tmux.conf goes in /etc not ${prefix}/etc.
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
-# Check for various headers. Alternatives included from compat.h.
-AC_CHECK_HEADERS(
- [ \
- bitstring.h \
- curses.h \
- dirent.h \
- fcntl.h \
- inttypes.h \
- libutil.h \
- ncurses.h \
- ndir.h \
- paths.h \
- pty.h \
- stdint.h \
- sys/dir.h \
- sys/ndir.h \
- sys/tree.h \
- term.h \
- util.h \
- ]
-)
-
# Is this a debug build?
-#found_debug=yes
+found_debug=yes
AC_ARG_ENABLE(
debug,
AC_HELP_STRING(--enable-debug, create a debug build),
@@ -55,12 +34,12 @@ AM_CONDITIONAL(IS_DEBUG, test "x$found_debug" = xyes)
# Is this a static build?
AC_ARG_ENABLE(
- static,
- AC_HELP_STRING(--enable-static, create a static build),
- found_static=$enable_static
+ static,
+ AC_HELP_STRING(--enable-static, create a static build),
+ found_static=$enable_static
)
if test "x$found_static" = xyes; then
- LDFLAGS="$LDFLAGS -static"
+ LDFLAGS="$LDFLAGS -static"
fi
# Is this gcc?
@@ -108,6 +87,40 @@ AC_EGREP_CPP(
AM_CONDITIONAL(IS_GLIBC, test "x$found_glibc" = xyes)
AC_MSG_RESULT($found_glibc)
+# Check for various headers. Alternatives included from compat.h.
+AC_CHECK_HEADERS(
+ [ \
+ bitstring.h \
+ curses.h \
+ dirent.h \
+ fcntl.h \
+ inttypes.h \
+ libutil.h \
+ ncurses.h \
+ ndir.h \
+ paths.h \
+ pty.h \
+ stdint.h \
+ sys/dir.h \
+ sys/ndir.h \
+ sys/tree.h \
+ term.h \
+ util.h \
+ ]
+)
+
+# Check for some functions that are replaced or omitted.
+AC_CHECK_FUNCS(
+ [ \
+ bzero \
+ dirfd \
+ flock \
+ setproctitle \
+ sysconf \
+ cfmakeraw \
+ ]
+)
+
# Look for clock_gettime. Must come before event_init.
AC_SEARCH_LIBS(clock_gettime, rt)
@@ -141,7 +154,14 @@ AC_SEARCH_LIBS(
found_curses=no
)
if test "x$found_curses" = xno; then
- AC_MSG_ERROR("curses not found")
+ AC_MSG_ERROR("curses not found")
+fi
+
+# Look for utempter.
+AC_CHECK_HEADER(utempter.h, have_utempter=yes, have_utempter=no)
+if test "x$have_utempter" = xyes; then
+ AC_DEFINE(HAVE_UTEMPTER)
+ LIBS="$LIBS -lutempter"
fi
# Check for b64_ntop.
@@ -221,7 +241,7 @@ if test "x$found_cmsg_data" = xno; then
if test "x$found_cmsg_data" = xyes; then
XOPEN_DEFINES="-D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED"
else
- AC_MSG_ERROR("CMSG_DATA not found")
+ AC_MSG_ERROR("CMSG_DATA not found")
fi
fi
AC_SUBST(XOPEN_DEFINES)
@@ -289,6 +309,13 @@ if test "x$found_fgetln" = xyes; then
fi
AM_CONDITIONAL(NO_FGETLN, [test "x$found_fgetln" = xno])
+# Look for fparseln, compat/fparseln.c used if missing.
+AC_CHECK_FUNC(fparseln, found_fparseln=yes, found_fparseln=no)
+if test "x$found_fparseln" = xyes; then
+ AC_DEFINE(HAVE_FPARSELN)
+fi
+AM_CONDITIONAL(NO_FPARSELN, [test "x$found_fparseln" = xno])
+
# Look for strcasestr, compat/strcasestr.c used if missing.
AC_CHECK_FUNC(strcasestr, found_strcasestr=yes, found_strcasestr=no)
if test "x$found_strcasestr" = xyes; then
@@ -315,8 +342,8 @@ AC_CHECK_FUNC(strnvis, found_strnvis=yes, found_strnvis=no)
if test "x$found_strnvis" = xyes; then
AC_MSG_CHECKING(if strnvis is broken)
AC_EGREP_HEADER([strnvis\(char \*, const char \*, size_t, int\)],
- vis.h,
- AC_MSG_RESULT(no),
+ vis.h,
+ AC_MSG_RESULT(no),
[found_strnvis=no])
if test "x$found_strnvis" = xno; then
AC_MSG_RESULT(yes)
@@ -366,17 +393,6 @@ if test "x$found_getopt" != xno; then
fi
AM_CONDITIONAL(NO_GETOPT, [test "x$found_getopt" = xno])
-# Check for some functions that are replaced or omitted.
-AC_CHECK_FUNCS(
- [ \
- bzero \
- dirfd \
- setproctitle \
- sysconf \
- cfmakeraw \
- ]
-)
-
# Check for BSD-style integer types.
AC_MSG_CHECKING(for BSD-style unsigned types)
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
@@ -386,10 +402,10 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
#include <stdint.h>
#else
#include <inttypes.h>
- #endif
+ #endif
int main(void)
{ u_int8_t u8; u_int16_t u16; u_int32_t u32; u_int64_t u64; }
- ])],
+ ])],
[AC_DEFINE(HAVE_BSD_TYPES) AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no)
)
@@ -423,7 +439,7 @@ AC_LINK_IFELSE([AC_LANG_SOURCE(
printf("%s\n", cp);
exit(0);
}
- ])],
+ ])],
[AC_DEFINE(HAVE___PROGNAME) AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no)
)
@@ -494,6 +510,10 @@ case "$host_os" in
AC_MSG_RESULT(hpux)
PLATFORM=hpux
;;
+ *cygwin*)
+ AC_MSG_RESULT(cygwin)
+ PLATFORM=cygwin
+ ;;
*)
AC_MSG_RESULT(unknown)
PLATFORM=unknown
@@ -511,5 +531,5 @@ AM_CONDITIONAL(IS_SUNOS, test "x$PLATFORM" = xsunos)
AM_CONDITIONAL(IS_HPUX, test "x$PLATFORM" = xhpux)
AM_CONDITIONAL(IS_UNKNOWN, test "x$PLATFORM" = xunknown)
-# autoconf should create a Makefile. A shock!
+# autoconf should create a Makefile.
AC_OUTPUT(Makefile)
diff --git a/control-notify.c b/control-notify.c
index a298cdc5..747ef5b4 100644
--- a/control-notify.c
+++ b/control-notify.c
@@ -88,7 +88,7 @@ control_notify_window_layout_changed(struct window *w)
ft = format_create();
wl = winlink_find_by_window(&s->windows, w);
if (wl != NULL) {
- format_winlink(ft, c->session, wl);
+ format_defaults(ft, c, NULL, wl, NULL);
control_write(c, "%s", format_expand(ft, template));
}
format_free(ft);
@@ -99,14 +99,19 @@ void
control_notify_window_unlinked(unused struct session *s, struct window *w)
{
struct client *c;
+ struct session *cs;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
continue;
+ cs = c->session;
- control_write(c, "%%window-close @%u", w->id);
+ if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
+ control_write(c, "%%window-close @%u", w->id);
+ else
+ control_write(c, "%%unlinked-window-close @%u", w->id);
}
}
@@ -134,14 +139,22 @@ void
control_notify_window_renamed(struct window *w)
{
struct client *c;
+ struct session *cs;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
continue;
+ cs = c->session;
- control_write(c, "%%window-renamed @%u %s", w->id, w->name);
+ if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
+ control_write(c, "%%window-renamed @%u %s", w->id,
+ w->name);
+ } else {
+ control_write(c, "%%unlinked-window-renamed @%u %s",
+ w->id, w->name);
+ }
}
}
diff --git a/control.c b/control.c
index 52fdb524..0ace6c12 100644
--- a/control.c
+++ b/control.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,7 +27,7 @@
#include "tmux.h"
/* Write a line. */
-void printflike2
+void
control_write(struct client *c, const char *fmt, ...)
{
va_list ap;
diff --git a/environ.c b/environ.c
index 3c0a5cb2..0dd91783 100644
--- a/environ.c
+++ b/environ.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -137,7 +137,8 @@ environ_unset(struct environ *env, const char *name)
* environment.
*/
void
-environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
+environ_update(const char *vars, struct environ *srcenv,
+ struct environ *dstenv)
{
struct environ_entry *envent;
char *copyvars, *var, *next;
@@ -167,8 +168,11 @@ environ_push(struct environ *env)
var[strcspn(var, "=")] = '\0';
ARRAY_ADD(&varlist, var);
}
- for (i = 0; i < ARRAY_LENGTH(&varlist); i++)
- unsetenv(ARRAY_ITEM(&varlist, i));
+ for (i = 0; i < ARRAY_LENGTH(&varlist); i++) {
+ var = ARRAY_ITEM(&varlist, i);
+ unsetenv(var);
+ free(var);
+ }
ARRAY_FREE(&varlist);
RB_FOREACH(envent, environ, env) {
diff --git a/examples/tmux.vim b/examples/tmux.vim
index 037ddf7b..4d64514a 100644
--- a/examples/tmux.vim
+++ b/examples/tmux.vim
@@ -31,59 +31,237 @@ syn keyword tmuxAction any current none
syn keyword tmuxBoolean off on
syn keyword tmuxCmds
- \ attach[-session] bind[-key] break-pane breakp capture-pane capturep
- \ choose-buffer choose-client choose-list choose-session choose-tree
- \ choose-window clear-history clearhist clock-mode command-prompt
- \ confirm[-before] copy-mode delete-buffer deleteb detach[-client]
- \ display[-message] display-panes displayp find-window findw
- \ has[-session] if[-shell] join-pane joinp kill-pane killp kill-server
- \ kill-session kill-window killw last-pane lastp last[-window]
- \ link-window linkw list-buffers lsb list-clients lsc
- \ list-commands lscm list-keys lsk list-panes lsp list-sessions ls
- \ list-windows lsw load-buffer loadb lock-client lockc lock[-server]
- \ lock-session locks move-pane movep move-window movew new[-session]
- \ next-layout nextl next[-window] paste-buffer pasteb pipe-pane pipep
- \ previous-layout prevl prev[ious-window] refresh[-client]
- \ rename[-session] rename-window renamew resize-pane resizep
- \ respawn-pane respawnp respawn-window respawnw rotate-window rotatew
- \ run[-shell] save-buffer saveb select-layout selectl
- \ select-pane selectp select-window selectw send[-keys] send-prefix
- \ server-info info set-buffer setb set-environment setenv set[-option]
- \ set-window-option setw show-buffer showb show-environment showenv
- \ show-messages showmsgs show[-options] show-window-options showw
- \ source[-file] split-window splitw start[-server]
- \ suspend-client suspendc swap-pane swapp swap-window swapw
- \ switch-client switchc unbind[-key] unlink-window unlinkw wait[-for]
+ \ attach[-session]
+ \ bind[-key]
+ \ break-pane
+ \ breakp
+ \ capture-pane
+ \ capturep
+ \ choose-buffer
+ \ choose-client
+ \ choose-list
+ \ choose-session
+ \ choose-tree
+ \ choose-window
+ \ clear-history
+ \ clearhist
+ \ clock-mode
+ \ command-prompt
+ \ confirm[-before]
+ \ copy-mode
+ \ delete-buffer
+ \ deleteb
+ \ detach[-client]
+ \ display[-message]
+ \ display-panes
+ \ displayp
+ \ find-window
+ \ findw
+ \ has[-session]
+ \ if[-shell]
+ \ join-pane
+ \ joinp
+ \ kill-pane
+ \ killp
+ \ kill-server
+ \ kill-session
+ \ kill-window
+ \ killw
+ \ last-pane
+ \ lastp
+ \ last[-window]
+ \ link-window
+ \ linkw
+ \ list-buffers
+ \ lsb
+ \ list-clients
+ \ lsc
+ \ list-commands
+ \ lscm
+ \ list-keys
+ \ lsk
+ \ list-panes
+ \ lsp
+ \ list-sessions
+ \ ls
+ \ list-windows
+ \ lsw
+ \ load-buffer
+ \ loadb
+ \ lock-client
+ \ lockc
+ \ lock[-server]
+ \ lock-session
+ \ locks
+ \ move-pane
+ \ movep
+ \ move-window
+ \ movew
+ \ new[-session]
+ \ next-layout
+ \ nextl
+ \ next[-window]
+ \ paste-buffer
+ \ pasteb
+ \ pipe-pane
+ \ pipep
+ \ previous-layout
+ \ prevl
+ \ prev[ious-window]
+ \ refresh[-client]
+ \ rename[-session]
+ \ rename-window
+ \ renamew
+ \ resize-pane
+ \ resizep
+ \ respawn-pane
+ \ respawnp
+ \ respawn-window
+ \ respawnw
+ \ rotate-window
+ \ rotatew
+ \ run[-shell]
+ \ save-buffer
+ \ saveb
+ \ select-layout
+ \ selectl
+ \ select-pane
+ \ selectp
+ \ select-window
+ \ selectw
+ \ send[-keys]
+ \ send-prefix
+ \ server-info
+ \ info
+ \ set-buffer
+ \ setb
+ \ set-environment
+ \ setenv
+ \ set[-option]
+ \ set-window-option
+ \ setw
+ \ show-buffer
+ \ showb
+ \ show-environment
+ \ showenv
+ \ show-messages
+ \ showmsgs
+ \ show[-options]
+ \ show-window-options
+ \ showw
+ \ source[-file]
+ \ split-window
+ \ splitw
+ \ start[-server]
+ \ suspend-client
+ \ suspendc
+ \ swap-pane
+ \ swapp
+ \ swap-window
+ \ swapw
+ \ switch-client
+ \ switchc
+ \ unbind[-key]
+ \ unlink-window
+ \ unlinkw
+ \ wait[-for]
syn keyword tmuxOptsSet
- \ buffer-limit escape-time exit-unattached exit-unattached focus-events
- \ quiet set-clipboard
- \ assume-paste-time base-index bell-action bell-on-alert default-command
- \ default-shell default-terminal destroy-unattached detach-on-destroy
- \ display-panes-active-colour display-panes-colour display-panes-time
- \ display-time history-limit lock-after-time lock-command lock-server
- \ message-command-style message-limit message-style mouse-resize-pane
- \ mouse-select-pane mouse-select-window mouse-utf8
- \ pane-active-border-style pane-border-style prefix prefix2
- \ renumber-windows repeat-time set-remain-on-exit set-titles
- \ set-titles-string status status-interval status-justify status-keys
- \ status-left status-left-length status-left-style status-position
- \ status-right status-right-length staus-right-style status-utf8
- \ terminal-overrides update-environment visual-activity visual-bell
- \ visual-content visual-silence word-separators
+ \ assume-paste-time
+ \ base-index
+ \ bell-action
+ \ bell-on-alert
+ \ buffer-limit
+ \ default-command
+ \ default-shell
+ \ default-terminal
+ \ destroy-unattached
+ \ detach-on-destroy
+ \ display-panes-active-colour
+ \ display-panes-colour
+ \ display-panes-time
+ \ display-time
+ \ escape-time
+ \ exit-unattached
+ \ focus-events
+ \ history-limit
+ \ lock-after-time
+ \ lock-command
+ \ lock-server
+ \ message-command-style
+ \ message-limit
+ \ message-style
+ \ mouse-resize-pane
+ \ mouse-select-pane
+ \ mouse-select-window
+ \ mouse-utf8
+ \ pane-active-border-style
+ \ pane-border-style
+ \ prefix
+ \ prefix2
+ \ quiet
+ \ renumber-windows
+ \ repeat-time
+ \ set-clipboard
+ \ set-remain-on-exit
+ \ set-titles
+ \ set-titles-string
+ \ status
+ \ status-interval
+ \ status-justify
+ \ status-keys
+ \ status-left
+ \ status-left-length
+ \ status-left-style
+ \ status-position
+ \ status-right
+ \ status-right-length
+ \ status-utf8
+ \ staus-right-style
+ \ terminal-overrides
+ \ update-environment
+ \ visual-activity
+ \ visual-bell
+ \ visual-content
+ \ visual-silence
+ \ word-separators
syn keyword tmuxOptsSetw
- \ aggressive-resize allow-rename alternate-screen automatic-rename
- \ c0-change-interval c0-change-trigger clock-mode-colour
- \ clock-mode-style force-height force-width force-height
- \ force-width main-pane-height main-pane-width mode-keys
- \ mode-mouse mode-style monitor-activity monitor-content monitor-silence
- \ other-pane-height other-pane-width pane-base-index remain-on-exit
- \ synchronize-panes utf8 window-status-activity-style
- \ window-status-bell-style window-status-content-style
- \ window-status-current-format window-status-current-style
- \ window-status-format window-status-last-style window-status-separator
- \ window-status-style wrap-search xterm-keys
+ \ aggressive-resize
+ \ allow-rename
+ \ alternate-screen
+ \ automatic-rename
+ \ c0-change-interval
+ \ c0-change-trigger
+ \ clock-mode-colour
+ \ clock-mode-style
+ \ force-height
+ \ force-width
+ \ main-pane-height
+ \ main-pane-width
+ \ mode-keys
+ \ mode-mouse
+ \ mode-style
+ \ monitor-activity
+ \ monitor-content
+ \ monitor-silence
+ \ other-pane-height
+ \ other-pane-width
+ \ pane-base-index
+ \ remain-on-exit
+ \ synchronize-panes
+ \ utf8
+ \ window-status-activity-style
+ \ window-status-bell-style
+ \ window-status-content-style
+ \ window-status-current-format
+ \ window-status-current-style
+ \ window-status-format
+ \ window-status-last-style
+ \ window-status-separator
+ \ window-status-style
+ \ wrap-search
+ \ xterm-keys
syn keyword tmuxTodo FIXME NOTE TODO XXX contained
diff --git a/examples/xterm-keys.vim b/examples/xterm-keys.vim
new file mode 100644
index 00000000..5672c26a
--- /dev/null
+++ b/examples/xterm-keys.vim
@@ -0,0 +1,49 @@
+" tmux.vim - Set xterm input codes passed by tmux
+" Author: Mark Oteiza
+" License: Public domain
+" Description: Simple plugin that assigns some xterm(1)-style keys to escape
+" sequences passed by tmux when "xterm-keys" is set to "on". Inspired by an
+" example given by Chris Johnsen at:
+" https://stackoverflow.com/a/15471820
+"
+" Documentation: help:xterm-modifier-keys man:tmux(1)
+
+if exists("g:loaded_tmux") || &cp
+ finish
+endif
+let g:loaded_tmux = 1
+
+function! s:SetXtermCapabilities()
+ set ttymouse=sgr
+
+ execute "set <xUp>=\e[1;*A"
+ execute "set <xDown>=\e[1;*B"
+ execute "set <xRight>=\e[1;*C"
+ execute "set <xLeft>=\e[1;*D"
+
+ execute "set <xHome>=\e[1;*H"
+ execute "set <xEnd>=\e[1;*F"
+
+ execute "set <Insert>=\e[2;*~"
+ execute "set <Delete>=\e[3;*~"
+ execute "set <PageUp>=\e[5;*~"
+ execute "set <PageDown>=\e[6;*~"
+
+ execute "set <xF1>=\e[1;*P"
+ execute "set <xF2>=\e[1;*Q"
+ execute "set <xF3>=\e[1;*R"
+ execute "set <xF4>=\e[1;*S"
+
+ execute "set <F5>=\e[15;*~"
+ execute "set <F6>=\e[17;*~"
+ execute "set <F7>=\e[18;*~"
+ execute "set <F8>=\e[19;*~"
+ execute "set <F9>=\e[20;*~"
+ execute "set <F10>=\e[21;*~"
+ execute "set <F11>=\e[23;*~"
+ execute "set <F12>=\e[24;*~"
+endfunction
+
+if exists('$TMUX')
+ call s:SetXtermCapabilities()
+endif
diff --git a/format.c b/format.c
index 10ac613e..776de960 100644
--- a/format.c
+++ b/format.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -17,6 +17,8 @@
*/
#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/wait.h>
#include <ctype.h>
#include <errno.h>
@@ -37,10 +39,33 @@
int format_replace(struct format_tree *, const char *, size_t, char **,
size_t *, size_t *);
char *format_get_command(struct window_pane *);
-void format_window_pane_tabs(struct format_tree *, struct window_pane *);
+
+void format_defaults_pane_tabs(struct format_tree *, struct window_pane *);
+void format_defaults_session(struct format_tree *, struct session *);
+void format_defaults_client(struct format_tree *, struct client *);
+void format_defaults_winlink(struct format_tree *, struct session *,
+ struct winlink *);
+
+/* Entry in format tree. */
+struct format_entry {
+ char *key;
+ char *value;
+
+ RB_ENTRY(format_entry) entry;
+};
+
+/* Tree of format entries. */
+struct format_tree {
+ struct window *w;
+ struct session *s;
+
+ RB_HEAD(format_rb_tree, format_entry) tree;
+};
/* Format key-value replacement entry. */
-RB_GENERATE(format_tree, format_entry, entry, format_cmp);
+int format_cmp(struct format_entry *, struct format_entry *);
+RB_PROTOTYPE(format_rb_tree, format_entry, entry, format_cmp);
+RB_GENERATE(format_rb_tree, format_entry, entry, format_cmp);
/* Format tree comparison function. */
int
@@ -114,10 +139,10 @@ struct format_tree *
format_create(void)
{
struct format_tree *ft;
- char host[MAXHOSTNAMELEN], *ptr;
+ char host[HOST_NAME_MAX+1], *ptr;
- ft = xmalloc(sizeof *ft);
- RB_INIT(ft);
+ ft = xcalloc(1, sizeof *ft);
+ RB_INIT(&ft->tree);
if (gethostname(host, sizeof host) == 0) {
format_add(ft, "host", "%s", host);
@@ -133,14 +158,10 @@ format_create(void)
void
format_free(struct format_tree *ft)
{
- struct format_entry *fe, *fe_next;
-
- fe_next = RB_MIN(format_tree, ft);
- while (fe_next != NULL) {
- fe = fe_next;
- fe_next = RB_NEXT(format_tree, ft, fe);
+ struct format_entry *fe, *fe1;
- RB_REMOVE(format_tree, ft, fe);
+ RB_FOREACH_SAFE(fe, format_rb_tree, &ft->tree, fe1) {
+ RB_REMOVE(format_rb_tree, &ft->tree, fe);
free(fe->value);
free(fe->key);
free(fe);
@@ -164,7 +185,7 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
xvasprintf(&fe->value, fmt, ap);
va_end(ap);
- fe_now = RB_INSERT(format_tree, ft, fe);
+ fe_now = RB_INSERT(format_rb_tree, &ft->tree, fe);
if (fe_now != NULL) {
free(fe_now->value);
fe_now->value = fe->value;
@@ -178,9 +199,32 @@ const char *
format_find(struct format_tree *ft, const char *key)
{
struct format_entry *fe, fe_find;
+ struct options_entry *o;
+ static char s[16];
+
+ o = options_find(&global_options, key);
+ if (o == NULL && ft->w != NULL)
+ o = options_find(&ft->w->options, key);
+ if (o == NULL)
+ o = options_find(&global_w_options, key);
+ if (o == NULL && ft->s != NULL)
+ o = options_find(&ft->s->options, key);
+ if (o == NULL)
+ o = options_find(&global_s_options, key);
+ if (o != NULL) {
+ switch (o->type) {
+ case OPTIONS_STRING:
+ return (o->str);
+ case OPTIONS_NUMBER:
+ snprintf(s, sizeof s, "%lld", o->num);
+ return (s);
+ case OPTIONS_STYLE:
+ return (style_tostring(&o->style));
+ }
+ }
fe_find.key = (char *) key;
- fe = RB_FIND(format_tree, ft, &fe_find);
+ fe = RB_FIND(format_rb_tree, &ft->tree, &fe_find);
if (fe == NULL)
return (NULL);
return (fe->value);
@@ -194,10 +238,10 @@ int
format_replace(struct format_tree *ft, const char *key, size_t keylen,
char **buf, size_t *len, size_t *off)
{
- char *copy, *copy0, *endptr, *ptr, *saved;
+ char *copy, *copy0, *endptr, *ptr, *saved, *trimmed;
const char *value;
size_t valuelen;
- u_long limit = ULONG_MAX;
+ u_long limit = 0;
/* Make a copy of the key. */
copy0 = copy = xmalloc(keylen + 1);
@@ -205,7 +249,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
copy[keylen] = '\0';
/* Is there a length limit or whatnot? */
- if (!islower((u_char) *copy) && *copy != '?') {
+ if (!islower((u_char) *copy) && *copy != '@' && *copy != '?') {
while (*copy != ':' && *copy != '\0') {
switch (*copy) {
case '=':
@@ -236,7 +280,8 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
*ptr = '\0';
value = format_find(ft, copy + 1);
- if (value != NULL && (value[0] != '0' || value[1] != '\0')) {
+ if (value != NULL && *value != '\0' &&
+ (value[0] != '0' || value[1] != '\0')) {
value = ptr + 1;
ptr = strchr(value, ',');
if (ptr == NULL)
@@ -256,15 +301,18 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
value = "";
saved = NULL;
}
- valuelen = strlen(value);
/* Truncate the value if needed. */
- if (valuelen > limit)
- valuelen = limit;
+ if (limit != 0) {
+ value = trimmed = utf8_trimcstr(value, limit);
+ free(saved);
+ saved = trimmed;
+ }
+ valuelen = strlen(value);
/* Expand the buffer and copy in the value. */
while (*len - *off < valuelen + 1) {
- *buf = xrealloc(*buf, 2, *len);
+ *buf = xreallocarray(*buf, 2, *len);
*len *= 2;
}
memcpy(*buf + *off, value, valuelen);
@@ -279,6 +327,33 @@ fail:
return (-1);
}
+/* Expand keys in a template, passing through strftime first. */
+char *
+format_expand_time(struct format_tree *ft, const char *fmt, time_t t)
+{
+ char *tmp, *expanded;
+ size_t tmplen;
+ struct tm *tm;
+
+ if (fmt == NULL)
+ return (xstrdup(""));
+
+ tm = localtime(&t);
+
+ tmp = NULL;
+ tmplen = strlen(fmt);
+
+ do {
+ tmp = xreallocarray(tmp, 2, tmplen);
+ tmplen *= 2;
+ } while (strftime(tmp, tmplen, fmt, tm) == 0);
+
+ expanded = format_expand(ft, tmp);
+ free(tmp);
+
+ return (expanded);
+}
+
/* Expand keys in a template. */
char *
format_expand(struct format_tree *ft, const char *fmt)
@@ -288,6 +363,9 @@ format_expand(struct format_tree *ft, const char *fmt)
size_t off, len, n;
int ch, brackets;
+ if (fmt == NULL)
+ return (xstrdup(""));
+
len = 64;
buf = xmalloc(len);
off = 0;
@@ -295,7 +373,7 @@ format_expand(struct format_tree *ft, const char *fmt)
while (*fmt != '\0') {
if (*fmt != '#') {
while (len - off < 2) {
- buf = xrealloc(buf, 2, len);
+ buf = xreallocarray(buf, 2, len);
len *= 2;
}
buf[off++] = *fmt++;
@@ -323,7 +401,7 @@ format_expand(struct format_tree *ft, const char *fmt)
continue;
case '#':
while (len - off < 2) {
- buf = xrealloc(buf, 2, len);
+ buf = xreallocarray(buf, 2, len);
len *= 2;
}
buf[off++] = '#';
@@ -336,7 +414,7 @@ format_expand(struct format_tree *ft, const char *fmt)
s = format_lower[ch - 'a'];
if (s == NULL) {
while (len - off < 3) {
- buf = xrealloc(buf, 2, len);
+ buf = xreallocarray(buf, 2, len);
len *= 2;
}
buf[off++] = '#';
@@ -365,7 +443,7 @@ format_get_command(struct window_pane *wp)
cmd = osdep_get_name(wp->fd, wp->tty);
if (cmd == NULL || *cmd == '\0') {
free(cmd);
- cmd = xstrdup(wp->cmd);
+ cmd = cmd_stringify_argv(wp->argc, wp->argv);
if (cmd == NULL || *cmd == '\0') {
free(cmd);
cmd = xstrdup(wp->shell);
@@ -376,14 +454,38 @@ format_get_command(struct window_pane *wp)
return (out);
}
+/* Set defaults for any of arguments that are not NULL. */
+void
+format_defaults(struct format_tree *ft, struct client *c, struct session *s,
+ struct winlink *wl, struct window_pane *wp)
+{
+ if (s == NULL && c != NULL)
+ s = c->session;
+ if (wl == NULL && s != NULL)
+ wl = s->curw;
+ if (wp == NULL && wl != NULL)
+ wp = wl->window->active;
+
+ if (c != NULL)
+ format_defaults_client(ft, c);
+ if (s != NULL)
+ format_defaults_session(ft, s);
+ if (s != NULL && wl != NULL)
+ format_defaults_winlink(ft, s, wl);
+ if (wp != NULL)
+ format_defaults_pane(ft, wp);
+}
+
/* Set default format keys for a session. */
void
-format_session(struct format_tree *ft, struct session *s)
+format_defaults_session(struct format_tree *ft, struct session *s)
{
struct session_group *sg;
char *tim;
time_t t;
+ ft->s = s;
+
format_add(ft, "session_name", "%s", s->name);
format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
format_add(ft, "session_width", "%u", s->sx);
@@ -401,20 +503,21 @@ format_session(struct format_tree *ft, struct session *s)
*strchr(tim, '\n') = '\0';
format_add(ft, "session_created_string", "%s", tim);
- if (s->flags & SESSION_UNATTACHED)
- format_add(ft, "session_attached", "%d", 0);
- else
- format_add(ft, "session_attached", "%d", 1);
+ format_add(ft, "session_attached", "%u", s->attached);
+ format_add(ft, "session_many_attached", "%u", s->attached > 1);
}
/* Set default format keys for a client. */
void
-format_client(struct format_tree *ft, struct client *c)
+format_defaults_client(struct format_tree *ft, struct client *c)
{
char *tim;
time_t t;
struct session *s;
+ if (ft->s == NULL)
+ ft->s = c->session;
+
format_add(ft, "client_height", "%u", c->tty.sy);
format_add(ft, "client_width", "%u", c->tty.sx);
if (c->tty.path != NULL)
@@ -456,10 +559,12 @@ format_client(struct format_tree *ft, struct client *c)
/* Set default format keys for a window. */
void
-format_window(struct format_tree *ft, struct window *w)
+format_defaults_window(struct format_tree *ft, struct window *w)
{
char *layout;
+ ft->w = w;
+
layout = layout_dump(w);
format_add(ft, "window_id", "@%u", w->id);
@@ -468,20 +573,26 @@ format_window(struct format_tree *ft, struct window *w)
format_add(ft, "window_height", "%u", w->sy);
format_add(ft, "window_layout", "%s", layout);
format_add(ft, "window_panes", "%u", window_count_panes(w));
+ format_add(ft, "window_zoomed_flag", "%u",
+ !!(w->flags & WINDOW_ZOOMED));
free(layout);
}
/* Set default format keys for a winlink. */
void
-format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
+format_defaults_winlink(struct format_tree *ft, struct session *s,
+ struct winlink *wl)
{
struct window *w = wl->window;
char *flags;
+ if (ft->w == NULL)
+ ft->w = wl->window;
+
flags = window_printable_flags(s, wl);
- format_window(ft, w);
+ format_defaults_window(ft, w);
format_add(ft, "window_index", "%d", wl->idx);
format_add(ft, "window_flags", "%s", flags);
@@ -489,20 +600,19 @@ format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
format_add(ft, "window_bell_flag", "%u",
!!(wl->flags & WINLINK_BELL));
- format_add(ft, "window_content_flag", "%u",
- !!(wl->flags & WINLINK_CONTENT));
format_add(ft, "window_activity_flag", "%u",
!!(wl->flags & WINLINK_ACTIVITY));
format_add(ft, "window_silence_flag", "%u",
!!(wl->flags & WINLINK_SILENCE));
-
+ format_add(ft, "window_last_flag", "%u",
+ !!(wl == TAILQ_FIRST(&s->lastw)));
free(flags);
}
/* Add window pane tabs. */
void
-format_window_pane_tabs(struct format_tree *ft, struct window_pane *wp)
+format_defaults_pane_tabs(struct format_tree *ft, struct window_pane *wp)
{
struct evbuffer *buffer;
u_int i;
@@ -524,13 +634,17 @@ format_window_pane_tabs(struct format_tree *ft, struct window_pane *wp)
/* Set default format keys for a window pane. */
void
-format_window_pane(struct format_tree *ft, struct window_pane *wp)
+format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
{
struct grid *gd = wp->base.grid;
struct grid_line *gl;
unsigned long long size;
u_int i, idx;
char *cmd, *cwd;
+ int status;
+
+ if (ft->w == NULL)
+ ft->w = wp->window;
size = 0;
for (i = 0; i < gd->hsize; i++) {
@@ -551,8 +665,20 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_title", "%s", wp->base.title);
format_add(ft, "pane_id", "%%%u", wp->id);
format_add(ft, "pane_active", "%d", wp == wp->window->active);
+ format_add(ft, "pane_input_off", "%d", !!(wp->flags & PANE_INPUTOFF));
+
+ status = wp->status;
+ if (wp->fd == -1 && WIFEXITED(status))
+ format_add(ft, "pane_dead_status", "%d", WEXITSTATUS(status));
format_add(ft, "pane_dead", "%d", wp->fd == -1);
+ if (window_pane_visible(wp)) {
+ format_add(ft, "pane_left", "%u", wp->xoff);
+ format_add(ft, "pane_top", "%u", wp->yoff);
+ format_add(ft, "pane_right", "%u", wp->xoff + wp->sx - 1);
+ format_add(ft, "pane_bottom", "%u", wp->yoff + wp->sy - 1);
+ }
+
format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base);
format_add(ft, "pane_synchronized", "%d",
!!options_get_number(&wp->window->options, "synchronize-panes"));
@@ -560,10 +686,12 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
if (wp->tty != NULL)
format_add(ft, "pane_tty", "%s", wp->tty);
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
- if (wp->cmd != NULL)
- format_add(ft, "pane_start_command", "%s", wp->cmd);
if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
format_add(ft, "pane_current_path", "%s", cwd);
+ if ((cmd = cmd_stringify_argv(wp->argc, wp->argv)) != NULL) {
+ format_add(ft, "pane_start_command", "%s", cmd);
+ free(cmd);
+ }
if ((cmd = format_get_command(wp)) != NULL) {
format_add(ft, "pane_current_command", "%s", cmd);
free(cmd);
@@ -595,22 +723,23 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
!!(wp->base.mode & MODE_MOUSE_STANDARD));
format_add(ft, "mouse_button_flag", "%d",
!!(wp->base.mode & MODE_MOUSE_BUTTON));
- format_add(ft, "mouse_any_flag", "%d",
- !!(wp->base.mode & MODE_MOUSE_ANY));
format_add(ft, "mouse_utf8_flag", "%d",
!!(wp->base.mode & MODE_MOUSE_UTF8));
- format_window_pane_tabs(ft, wp);
+ format_defaults_pane_tabs(ft, wp);
}
/* Set default format keys for paste buffer. */
void
-format_paste_buffer(struct format_tree *ft, struct paste_buffer *pb)
+format_defaults_paste_buffer(struct format_tree *ft, struct paste_buffer *pb,
+ int utf8flag)
{
- char *pb_print = paste_print(pb, 50);
+ char *s;
format_add(ft, "buffer_size", "%zu", pb->size);
- format_add(ft, "buffer_sample", "%s", pb_print);
+ format_add(ft, "buffer_name", "%s", pb->name);
- free(pb_print);
+ s = paste_make_sample(pb, utf8flag);
+ format_add(ft, "buffer_sample", "%s", s);
+ free(s);
}
diff --git a/grid-view.c b/grid-view.c
index 7ef443a3..badabd56 100644
--- a/grid-view.c
+++ b/grid-view.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -59,8 +59,6 @@ grid_view_clear_history(struct grid *gd)
struct grid_line *gl;
u_int yy, last;
- GRID_DEBUG(gd, "");
-
/* Find the last used line. */
last = 0;
for (yy = 0; yy < gd->sy; yy++) {
@@ -82,8 +80,6 @@ grid_view_clear_history(struct grid *gd)
void
grid_view_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
{
- GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
-
px = grid_view_x(gd, px);
py = grid_view_y(gd, py);
@@ -94,8 +90,6 @@ grid_view_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
void
grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower)
{
- GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
-
if (gd->flags & GRID_HISTORY) {
grid_collect_history(gd);
if (rupper == 0 && rlower == gd->sy - 1)
@@ -116,8 +110,6 @@ grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower)
void
grid_view_scroll_region_down(struct grid *gd, u_int rupper, u_int rlower)
{
- GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
-
rupper = grid_view_y(gd, rupper);
rlower = grid_view_y(gd, rlower);
@@ -130,8 +122,6 @@ grid_view_insert_lines(struct grid *gd, u_int py, u_int ny)
{
u_int sy;
- GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
-
py = grid_view_y(gd, py);
sy = grid_view_y(gd, gd->sy);
@@ -141,12 +131,11 @@ grid_view_insert_lines(struct grid *gd, u_int py, u_int ny)
/* Insert lines in region. */
void
-grid_view_insert_lines_region(struct grid *gd, u_int rlower, u_int py, u_int ny)
+grid_view_insert_lines_region(struct grid *gd, u_int rlower, u_int py,
+ u_int ny)
{
u_int ny2;
- GRID_DEBUG(gd, "rlower=%u, py=%u, ny=%u", rlower, py, ny);
-
rlower = grid_view_y(gd, rlower);
py = grid_view_y(gd, py);
@@ -162,8 +151,6 @@ grid_view_delete_lines(struct grid *gd, u_int py, u_int ny)
{
u_int sy;
- GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
-
py = grid_view_y(gd, py);
sy = grid_view_y(gd, gd->sy);
@@ -174,12 +161,11 @@ grid_view_delete_lines(struct grid *gd, u_int py, u_int ny)
/* Delete lines inside scroll region. */
void
-grid_view_delete_lines_region(struct grid *gd, u_int rlower, u_int py, u_int ny)
+grid_view_delete_lines_region(struct grid *gd, u_int rlower, u_int py,
+ u_int ny)
{
u_int ny2;
- GRID_DEBUG(gd, "rlower=%u, py=%u, ny=%u", rlower, py, ny);
-
rlower = grid_view_y(gd, rlower);
py = grid_view_y(gd, py);
@@ -195,8 +181,6 @@ grid_view_insert_cells(struct grid *gd, u_int px, u_int py, u_int nx)
{
u_int sx;
- GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
-
px = grid_view_x(gd, px);
py = grid_view_y(gd, py);
@@ -214,8 +198,6 @@ grid_view_delete_cells(struct grid *gd, u_int px, u_int py, u_int nx)
{
u_int sx;
- GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
-
px = grid_view_x(gd, px);
py = grid_view_y(gd, py);
@@ -229,8 +211,6 @@ grid_view_delete_cells(struct grid *gd, u_int px, u_int py, u_int nx)
char *
grid_view_string_cells(struct grid *gd, u_int px, u_int py, u_int nx)
{
- GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
-
px = grid_view_x(gd, px);
py = grid_view_y(gd, py);
diff --git a/grid.c b/grid.c
index 52d6f6bc..ef7c374b 100644
--- a/grid.c
+++ b/grid.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -151,8 +151,6 @@ grid_collect_history(struct grid *gd)
{
u_int yy;
- GRID_DEBUG(gd, "");
-
if (gd->hsize < gd->hlimit)
return;
@@ -173,10 +171,9 @@ grid_scroll_history(struct grid *gd)
{
u_int yy;
- GRID_DEBUG(gd, "");
-
yy = gd->hsize + gd->sy;
- gd->linedata = xrealloc(gd->linedata, yy + 1, sizeof *gd->linedata);
+ gd->linedata = xreallocarray(gd->linedata, yy + 1,
+ sizeof *gd->linedata);
memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]);
gd->hsize++;
@@ -189,11 +186,10 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower)
struct grid_line *gl_history, *gl_upper, *gl_lower;
u_int yy;
- GRID_DEBUG(gd, "upper=%u, lower=%u", upper, lower);
-
/* Create a space for a new line. */
yy = gd->hsize + gd->sy;
- gd->linedata = xrealloc(gd->linedata, yy + 1, sizeof *gd->linedata);
+ gd->linedata = xreallocarray(gd->linedata, yy + 1,
+ sizeof *gd->linedata);
/* Move the entire screen down to free a space for this line. */
gl_history = &gd->linedata[gd->hsize];
@@ -227,7 +223,7 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx)
if (sx <= gl->cellsize)
return;
- gl->celldata = xrealloc(gl->celldata, sx, sizeof *gl->celldata);
+ gl->celldata = xreallocarray(gl->celldata, sx, sizeof *gl->celldata);
for (xx = gl->cellsize; xx < sx; xx++)
grid_put_cell(gd, xx, py, &grid_default_cell);
gl->cellsize = sx;
@@ -282,8 +278,6 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
{
u_int xx, yy;
- GRID_DEBUG(gd, "px=%u, py=%u, nx=%u, ny=%u", px, py, nx, ny);
-
if (nx == 0 || ny == 0)
return;
@@ -319,8 +313,6 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny)
struct grid_line *gl;
u_int yy;
- GRID_DEBUG(gd, "py=%u, ny=%u", py, ny);
-
if (ny == 0)
return;
@@ -342,8 +334,6 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny)
{
u_int yy;
- GRID_DEBUG(gd, "dy=%u, py=%u, ny=%u", dy, py, ny);
-
if (ny == 0 || py == dy)
return;
@@ -381,8 +371,6 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
struct grid_line *gl;
u_int xx;
- GRID_DEBUG(gd, "dx=%u, px=%u, py=%u, nx=%u", dx, px, py, nx);
-
if (nx == 0 || px == dx)
return;
@@ -528,20 +516,18 @@ grid_string_cells_code(const struct grid_cell *lastgc,
s[n++] = attrs[i].code;
}
- /* If the foreground c changed, append its parameters. */
+ /* If the foreground colour changed, append its parameters. */
nnewc = grid_string_cells_fg(gc, newc);
noldc = grid_string_cells_fg(lastgc, oldc);
- if (nnewc != noldc ||
- memcmp(newc,oldc, nnewc * sizeof newc[0]) != 0) {
+ if (nnewc != noldc || memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0) {
for (i = 0; i < nnewc; i++)
s[n++] = newc[i];
}
- /* If the background c changed, append its parameters. */
+ /* If the background colour changed, append its parameters. */
nnewc = grid_string_cells_bg(gc, newc);
noldc = grid_string_cells_bg(lastgc, oldc);
- if (nnewc != noldc ||
- memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0) {
+ if (nnewc != noldc || memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0) {
for (i = 0; i < nnewc; i++)
s[n++] = newc[i];
}
@@ -586,14 +572,12 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
const struct grid_cell *gc;
static struct grid_cell lastgc1;
struct utf8_data ud;
- const char* data;
+ const char *data;
char *buf, code[128];
size_t len, off, size, codelen;
u_int xx;
const struct grid_line *gl;
- GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
-
if (lastgc != NULL && *lastgc == NULL) {
memcpy(&lastgc1, &grid_default_cell, sizeof lastgc1);
*lastgc = &lastgc1;
@@ -628,7 +612,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
}
while (len < off + size + codelen + 1) {
- buf = xrealloc(buf, 2, len);
+ buf = xreallocarray(buf, 2, len);
len *= 2;
}
@@ -640,7 +624,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
off += size;
}
- if (trim) {
+ if (trim) {
while (off > 0 && buf[off - 1] == ' ')
off--;
}
@@ -661,8 +645,6 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
struct grid_line *dstl, *srcl;
u_int yy;
- GRID_DEBUG(src, "dy=%u, sy=%u, ny=%u", dy, sy, ny);
-
if (dy + ny > dst->hsize + dst->sy)
ny = dst->hsize + dst->sy - dy;
if (sy + ny > src->hsize + src->sy)
@@ -705,7 +687,7 @@ grid_reflow_join(struct grid *dst, u_int *py, struct grid_line *src_gl,
nx = ox + to_copy;
/* Resize the destination line. */
- dst_gl->celldata = xrealloc(dst_gl->celldata, nx,
+ dst_gl->celldata = xreallocarray(dst_gl->celldata, nx,
sizeof *dst_gl->celldata);
dst_gl->cellsize = nx;
@@ -744,7 +726,8 @@ grid_reflow_split(struct grid *dst, u_int *py, struct grid_line *src_gl,
to_copy = src_gl->cellsize;
/* Expand destination line. */
- dst_gl->celldata = xmalloc(to_copy * sizeof *dst_gl->celldata);
+ dst_gl->celldata = xreallocarray(NULL, to_copy,
+ sizeof *dst_gl->celldata);
dst_gl->cellsize = to_copy;
dst_gl->flags |= GRID_LINE_WRAPPED;
diff --git a/input-keys.c b/input-keys.c
index 7582a638..ef652ee1 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -56,14 +56,14 @@ const struct input_key_ent input_keys[] = {
{ KEYC_F10, "\033[21~", 0 },
{ KEYC_F11, "\033[23~", 0 },
{ KEYC_F12, "\033[24~", 0 },
- { KEYC_F13, "\033[25~", 0 },
- { KEYC_F14, "\033[26~", 0 },
- { KEYC_F15, "\033[28~", 0 },
- { KEYC_F16, "\033[29~", 0 },
- { KEYC_F17, "\033[31~", 0 },
- { KEYC_F18, "\033[32~", 0 },
- { KEYC_F19, "\033[33~", 0 },
- { KEYC_F20, "\033[34~", 0 },
+ { KEYC_F1|KEYC_SHIFT, "\033[25~", 0 },
+ { KEYC_F2|KEYC_SHIFT, "\033[26~", 0 },
+ { KEYC_F3|KEYC_SHIFT, "\033[28~", 0 },
+ { KEYC_F4|KEYC_SHIFT, "\033[29~", 0 },
+ { KEYC_F5|KEYC_SHIFT, "\033[31~", 0 },
+ { KEYC_F6|KEYC_SHIFT, "\033[32~", 0 },
+ { KEYC_F7|KEYC_SHIFT, "\033[33~", 0 },
+ { KEYC_F8|KEYC_SHIFT, "\033[34~", 0 },
{ KEYC_IC, "\033[2~", 0 },
{ KEYC_DC, "\033[3~", 0 },
{ KEYC_HOME, "\033[1~", 0 },
@@ -142,7 +142,7 @@ input_key(struct window_pane *wp, int key)
char *out;
u_char ch;
- log_debug2("writing key 0x%x", key);
+ log_debug("writing key 0x%x", key);
/*
* If this is a normal 7-bit key, just send it, with a leading escape
@@ -185,11 +185,11 @@ input_key(struct window_pane *wp, int key)
break;
}
if (i == nitems(input_keys)) {
- log_debug2("key 0x%x missing", key);
+ log_debug("key 0x%x missing", key);
return;
}
dlen = strlen(ike->data);
- log_debug2("found key 0x%x: \"%s\"", key, ike->data);
+ log_debug("found key 0x%x: \"%s\"", key, ike->data);
/* Prefix a \033 for escape. */
if (key & KEYC_ESCAPE)
@@ -204,6 +204,7 @@ input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m)
char buf[40];
size_t len;
struct paste_buffer *pb;
+ int event;
if (wp->screen->mode & ALL_MOUSE_MODES) {
/*
@@ -237,19 +238,16 @@ input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m)
return;
}
- if (m->button == 1 && (m->event & MOUSE_EVENT_CLICK) &&
- options_get_number(&wp->window->options, "mode-mouse") == 1) {
- pb = paste_get_top(&global_buffers);
- if (pb != NULL) {
- paste_send_pane(pb, wp, "\r",
- wp->screen->mode & MODE_BRACKETPASTE);
- }
- } else if ((m->xb & 3) != 1 &&
- options_get_number(&wp->window->options, "mode-mouse") == 1) {
- if (window_pane_set_mode(wp, &window_copy_mode) == 0) {
- window_copy_init_from_pane(wp);
- if (wp->mode->mouse != NULL)
- wp->mode->mouse(wp, s, m);
- }
+ if (options_get_number(&wp->window->options, "mode-mouse") != 1)
+ return;
+ event = m->event & (MOUSE_EVENT_CLICK|MOUSE_EVENT_WHEEL);
+ if (wp->mode == NULL && m->button == 1 && event == MOUSE_EVENT_CLICK) {
+ pb = paste_get_top();
+ if (pb != NULL)
+ paste_send_pane(pb, wp, "\r", 1);
+ } else if (window_pane_set_mode(wp, &window_copy_mode) == 0) {
+ window_copy_init_from_pane(wp);
+ if (wp->mode->mouse != NULL)
+ wp->mode->mouse(wp, s, m);
}
}
diff --git a/input.c b/input.c
index ce103bd2..de11f629 100644
--- a/input.c
+++ b/input.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -52,9 +52,11 @@ int input_split(struct input_ctx *);
int input_get(struct input_ctx *, u_int, int, int);
void input_reply(struct input_ctx *, const char *, ...);
void input_set_state(struct window_pane *, const struct input_transition *);
+void input_reset_cell(struct input_ctx *);
/* Transition entry/exit handlers. */
void input_clear(struct input_ctx *);
+void input_ground(struct input_ctx *);
void input_enter_osc(struct input_ctx *);
void input_exit_osc(struct input_ctx *);
void input_enter_apc(struct input_ctx *);
@@ -103,19 +105,23 @@ enum input_esc_type {
INPUT_ESC_NEL,
INPUT_ESC_RI,
INPUT_ESC_RIS,
- INPUT_ESC_SCSOFF_G0,
- INPUT_ESC_SCSON_G0,
+ INPUT_ESC_SCSG0_OFF,
+ INPUT_ESC_SCSG0_ON,
+ INPUT_ESC_SCSG1_OFF,
+ INPUT_ESC_SCSG1_ON,
};
/* Escape command table. */
const struct input_table_entry input_esc_table[] = {
- { '0', "(", INPUT_ESC_SCSOFF_G0 },
+ { '0', "(", INPUT_ESC_SCSG0_ON },
+ { '0', ")", INPUT_ESC_SCSG1_ON },
{ '7', "", INPUT_ESC_DECSC },
{ '8', "", INPUT_ESC_DECRC },
{ '8', "#", INPUT_ESC_DECALN },
{ '=', "", INPUT_ESC_DECKPAM },
{ '>', "", INPUT_ESC_DECKPNM },
- { 'B', "(", INPUT_ESC_SCSON_G0 },
+ { 'B', "(", INPUT_ESC_SCSG0_OFF },
+ { 'B', ")", INPUT_ESC_SCSG1_OFF },
{ 'D', "", INPUT_ESC_IND },
{ 'E', "", INPUT_ESC_NEL },
{ 'H', "", INPUT_ESC_HTS },
@@ -242,7 +248,7 @@ const struct input_transition input_state_utf8_one_table[];
/* ground state definition. */
const struct input_state input_state_ground = {
"ground",
- NULL, NULL,
+ input_ground, NULL,
input_state_ground_table
};
@@ -683,17 +689,26 @@ input_table_compare(const void *key, const void *value)
return (strcmp(ictx->interm_buf, entry->interm));
}
+/* Reset cell state to default. */
+void
+input_reset_cell(struct input_ctx *ictx)
+{
+ memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell);
+ ictx->cell.set = 0;
+ ictx->cell.g0set = ictx->cell.g1set = 0;
+
+ memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
+ ictx->old_cx = 0;
+ ictx->old_cy = 0;
+}
+
/* Initialise input parser. */
void
input_init(struct window_pane *wp)
{
struct input_ctx *ictx = &wp->ictx;
- memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
-
- memcpy(&ictx->old_cell, &grid_default_cell, sizeof ictx->old_cell);
- ictx->old_cx = 0;
- ictx->old_cy = 0;
+ input_reset_cell(ictx);
*ictx->interm_buf = '\0';
ictx->interm_len = 0;
@@ -701,6 +716,12 @@ input_init(struct window_pane *wp)
*ictx->param_buf = '\0';
ictx->param_len = 0;
+ ictx->input_space = INPUT_BUF_START;
+ ictx->input_buf = xmalloc(INPUT_BUF_START);
+
+ *ictx->input_buf = '\0';
+ ictx->input_len = 0;
+
ictx->state = &input_state_ground;
ictx->flags = 0;
@@ -711,8 +732,11 @@ input_init(struct window_pane *wp)
void
input_free(struct window_pane *wp)
{
- if (wp != NULL)
- evbuffer_free(wp->ictx.since_ground);
+ if (wp == NULL)
+ return;
+
+ free(wp->ictx.input_buf);
+ evbuffer_free(wp->ictx.since_ground);
}
/* Change input state. */
@@ -720,14 +744,9 @@ void
input_set_state(struct window_pane *wp, const struct input_transition *itr)
{
struct input_ctx *ictx = &wp->ictx;
- struct evbuffer *ground_evb = ictx->since_ground;
if (ictx->state->exit != NULL)
ictx->state->exit(ictx);
-
- if (itr->state == &input_state_ground)
- evbuffer_drain(ground_evb, EVBUFFER_LENGTH(ground_evb));
-
ictx->state = itr->state;
if (ictx->state->enter != NULL)
ictx->state->enter(ictx);
@@ -882,12 +901,34 @@ input_clear(struct input_ctx *ictx)
ictx->flags &= ~INPUT_DISCARD;
}
+/* Reset for ground state. */
+void
+input_ground(struct input_ctx *ictx)
+{
+ evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
+
+ if (ictx->input_space > INPUT_BUF_START) {
+ ictx->input_space = INPUT_BUF_START;
+ ictx->input_buf = xrealloc(ictx->input_buf, INPUT_BUF_START);
+ }
+}
+
/* Output this character to the screen. */
int
input_print(struct input_ctx *ictx)
{
- grid_cell_one(&ictx->cell, ictx->ch);
- screen_write_cell(&ictx->ctx, &ictx->cell);
+ int set;
+
+ set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
+ if (set == 1)
+ ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
+ else
+ ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
+
+ grid_cell_one(&ictx->cell.cell, ictx->ch);
+ screen_write_cell(&ictx->ctx, &ictx->cell.cell);
+
+ ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
return (0);
}
@@ -924,12 +965,20 @@ input_parameter(struct input_ctx *ictx)
int
input_input(struct input_ctx *ictx)
{
- if (ictx->input_len == (sizeof ictx->input_buf) - 1)
- ictx->flags |= INPUT_DISCARD;
- else {
- ictx->input_buf[ictx->input_len++] = ictx->ch;
- ictx->input_buf[ictx->input_len] = '\0';
+ size_t available;
+
+ available = ictx->input_space;
+ while (ictx->input_len + 1 >= available) {
+ available *= 2;
+ if (available > INPUT_BUF_LIMIT) {
+ ictx->flags |= INPUT_DISCARD;
+ return (0);
+ }
+ ictx->input_buf = xrealloc(ictx->input_buf, available);
+ ictx->input_space = available;
}
+ ictx->input_buf[ictx->input_len++] = ictx->ch;
+ ictx->input_buf[ictx->input_len] = '\0';
return (0);
}
@@ -975,10 +1024,10 @@ input_c0_dispatch(struct input_ctx *ictx)
screen_write_carriagereturn(sctx);
goto count_c0;
case '\016': /* SO */
- ictx->cell.attr |= GRID_ATTR_CHARSET;
+ ictx->cell.set = 1;
break;
case '\017': /* SI */
- ictx->cell.attr &= ~GRID_ATTR_CHARSET;
+ ictx->cell.set = 0;
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
@@ -989,7 +1038,7 @@ input_c0_dispatch(struct input_ctx *ictx)
count_c0:
trigger = options_get_number(&wp->window->options, "c0-change-trigger");
- if (++wp->changes == trigger) {
+ if (trigger != 0 && ++wp->changes >= trigger) {
wp->flags |= PANE_DROP;
window_pane_timer_start(wp);
}
@@ -1018,11 +1067,7 @@ input_esc_dispatch(struct input_ctx *ictx)
switch (entry->type) {
case INPUT_ESC_RIS:
- memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
- memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
- ictx->old_cx = 0;
- ictx->old_cy = 0;
-
+ input_reset_cell(ictx);
screen_write_reset(sctx);
break;
case INPUT_ESC_IND:
@@ -1057,16 +1102,17 @@ input_esc_dispatch(struct input_ctx *ictx)
case INPUT_ESC_DECALN:
screen_write_alignmenttest(sctx);
break;
- case INPUT_ESC_SCSON_G0:
- /*
- * Not really supported, but fake it up enough for those that
- * use it to switch character sets (by redefining G0 to
- * graphics set, rather than switching to G1).
- */
- ictx->cell.attr &= ~GRID_ATTR_CHARSET;
+ case INPUT_ESC_SCSG0_ON:
+ ictx->cell.g0set = 1;
break;
- case INPUT_ESC_SCSOFF_G0:
- ictx->cell.attr |= GRID_ATTR_CHARSET;
+ case INPUT_ESC_SCSG0_OFF:
+ ictx->cell.g0set = 0;
+ break;
+ case INPUT_ESC_SCSG1_ON:
+ ictx->cell.g1set = 1;
+ break;
+ case INPUT_ESC_SCSG1_OFF:
+ ictx->cell.g1set = 0;
break;
}
@@ -1147,7 +1193,7 @@ input_csi_dispatch(struct input_ctx *ictx)
case INPUT_CSI_DA_TWO:
switch (input_get(ictx, 0, 0, 0)) {
case 0:
- input_reply(ictx, "\033[>0;95;0c");
+ input_reply(ictx, "\033[>84;0;0c");
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
@@ -1296,6 +1342,9 @@ input_csi_dispatch_rm(struct input_ctx *ictx)
case 4: /* IRM */
screen_write_mode_clear(&ictx->ctx, MODE_INSERT);
break;
+ case 34:
+ screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
+ break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
@@ -1307,7 +1356,8 @@ input_csi_dispatch_rm(struct input_ctx *ictx)
void
input_csi_dispatch_rm_private(struct input_ctx *ictx)
{
- u_int i;
+ struct window_pane *wp = ictx->wp;
+ u_int i;
for (i = 0; i < ictx->param_list_len; i++) {
switch (input_get(ictx, i, 0, -1)) {
@@ -1321,13 +1371,15 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
case 7: /* DECAWM */
screen_write_mode_clear(&ictx->ctx, MODE_WRAP);
break;
+ case 12:
+ screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
+ break;
case 25: /* TCEM */
screen_write_mode_clear(&ictx->ctx, MODE_CURSOR);
break;
case 1000:
case 1001:
case 1002:
- case 1003:
screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
break;
case 1004:
@@ -1341,10 +1393,10 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
break;
case 47:
case 1047:
- window_pane_alternate_off(ictx->wp, &ictx->cell, 0);
+ window_pane_alternate_off(wp, &ictx->cell.cell, 0);
break;
case 1049:
- window_pane_alternate_off(ictx->wp, &ictx->cell, 1);
+ window_pane_alternate_off(wp, &ictx->cell.cell, 1);
break;
case 2004:
screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE);
@@ -1367,6 +1419,9 @@ input_csi_dispatch_sm(struct input_ctx *ictx)
case 4: /* IRM */
screen_write_mode_set(&ictx->ctx, MODE_INSERT);
break;
+ case 34:
+ screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
+ break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
@@ -1378,7 +1433,8 @@ input_csi_dispatch_sm(struct input_ctx *ictx)
void
input_csi_dispatch_sm_private(struct input_ctx *ictx)
{
- u_int i;
+ struct window_pane *wp = ictx->wp;
+ u_int i;
for (i = 0; i < ictx->param_list_len; i++) {
switch (input_get(ictx, i, 0, -1)) {
@@ -1392,6 +1448,9 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
case 7: /* DECAWM */
screen_write_mode_set(&ictx->ctx, MODE_WRAP);
break;
+ case 12:
+ screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
+ break;
case 25: /* TCEM */
screen_write_mode_set(&ictx->ctx, MODE_CURSOR);
break;
@@ -1403,15 +1462,11 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON);
break;
- case 1003:
- screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
- screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ANY);
- break;
case 1004:
if (ictx->ctx.s->mode & MODE_FOCUSON)
break;
screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
- ictx->wp->flags |= PANE_FOCUSPUSH; /* force update */
+ wp->flags |= PANE_FOCUSPUSH; /* force update */
break;
case 1005:
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
@@ -1421,10 +1476,10 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
break;
case 47:
case 1047:
- window_pane_alternate_on(ictx->wp, &ictx->cell, 0);
+ window_pane_alternate_on(wp, &ictx->cell.cell, 0);
break;
case 1049:
- window_pane_alternate_on(ictx->wp, &ictx->cell, 1);
+ window_pane_alternate_on(wp, &ictx->cell.cell, 1);
break;
case 2004:
screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE);
@@ -1489,15 +1544,12 @@ input_csi_dispatch_winops(struct input_ctx *ictx)
void
input_csi_dispatch_sgr(struct input_ctx *ictx)
{
- struct grid_cell *gc = &ictx->cell;
+ struct grid_cell *gc = &ictx->cell.cell;
u_int i;
int n, m;
- u_char attr;
if (ictx->param_list_len == 0) {
- attr = gc->attr;
memcpy(gc, &grid_default_cell, sizeof *gc);
- gc->attr |= (attr & GRID_ATTR_CHARSET);
return;
}
@@ -1535,9 +1587,7 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
switch (n) {
case 0:
case 10:
- attr = gc->attr;
memcpy(gc, &grid_default_cell, sizeof *gc);
- gc->attr |= (attr & GRID_ATTR_CHARSET);
break;
case 1:
gc->attr |= GRID_ATTR_BRIGHT;
@@ -1666,8 +1716,8 @@ input_enter_osc(struct input_ctx *ictx)
void
input_exit_osc(struct input_ctx *ictx)
{
- u_char *p = ictx->input_buf;
- int option;
+ u_char *p = ictx->input_buf;
+ int option;
if (ictx->flags & INPUT_DISCARD)
return;
@@ -1781,8 +1831,8 @@ input_utf8_close(struct input_ctx *ictx)
utf8_append(&ictx->utf8data, ictx->ch);
- grid_cell_set(&ictx->cell, &ictx->utf8data);
- screen_write_cell(&ictx->ctx, &ictx->cell);
+ grid_cell_set(&ictx->cell.cell, &ictx->utf8data);
+ screen_write_cell(&ictx->ctx, &ictx->cell.cell);
return (0);
}
diff --git a/job.c b/job.c
index d7bd852b..023a1d47 100644
--- a/job.c
+++ b/job.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <signal.h>
#include "tmux.h"
@@ -59,6 +60,8 @@ job_run(const char *cmd, struct session *s,
switch (pid = fork()) {
case -1:
environ_free(&env);
+ close(out[0]);
+ close(out[1]);
return (NULL);
case 0: /* child */
clear_signals(1);
diff --git a/key-bindings.c b/key-bindings.c
index 86048ea6..00f73d73 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,7 +27,6 @@
RB_GENERATE(key_bindings, key_binding, entry, key_bindings_cmp);
struct key_bindings key_bindings;
-struct key_bindings dead_key_bindings;
int
key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
@@ -78,126 +77,106 @@ key_bindings_remove(int key)
if ((bd = key_bindings_lookup(key)) == NULL)
return;
RB_REMOVE(key_bindings, &key_bindings, bd);
- RB_INSERT(key_bindings, &dead_key_bindings, bd);
-}
-
-void
-key_bindings_clean(void)
-{
- struct key_binding *bd;
-
- while (!RB_EMPTY(&dead_key_bindings)) {
- bd = RB_ROOT(&dead_key_bindings);
- RB_REMOVE(key_bindings, &dead_key_bindings, bd);
- cmd_list_free(bd->cmdlist);
- free(bd);
- }
+ cmd_list_free(bd->cmdlist);
+ free(bd);
}
void
key_bindings_init(void)
{
- static const struct {
- int key;
- int can_repeat;
- const struct cmd_entry *entry;
- } table[] = {
- { ' ', 0, &cmd_next_layout_entry },
- { '!', 0, &cmd_break_pane_entry },
- { '"', 0, &cmd_split_window_entry },
- { '#', 0, &cmd_list_buffers_entry },
- { '$', 0, &cmd_command_prompt_entry },
- { '%', 0, &cmd_split_window_entry },
- { '&', 0, &cmd_confirm_before_entry },
- { '(', 0, &cmd_switch_client_entry },
- { ')', 0, &cmd_switch_client_entry },
- { ',', 0, &cmd_command_prompt_entry },
- { '-', 0, &cmd_delete_buffer_entry },
- { '.', 0, &cmd_command_prompt_entry },
- { '0', 0, &cmd_select_window_entry },
- { '1', 0, &cmd_select_window_entry },
- { '2', 0, &cmd_select_window_entry },
- { '3', 0, &cmd_select_window_entry },
- { '4', 0, &cmd_select_window_entry },
- { '5', 0, &cmd_select_window_entry },
- { '6', 0, &cmd_select_window_entry },
- { '7', 0, &cmd_select_window_entry },
- { '8', 0, &cmd_select_window_entry },
- { '9', 0, &cmd_select_window_entry },
- { ':', 0, &cmd_command_prompt_entry },
- { ';', 0, &cmd_last_pane_entry },
- { '=', 0, &cmd_choose_buffer_entry },
- { '?', 0, &cmd_list_keys_entry },
- { 'D', 0, &cmd_choose_client_entry },
- { 'L', 0, &cmd_switch_client_entry },
- { '[', 0, &cmd_copy_mode_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 },
- { ']', 0, &cmd_paste_buffer_entry },
- { 'c', 0, &cmd_new_window_entry },
- { 'd', 0, &cmd_detach_client_entry },
- { 'f', 0, &cmd_command_prompt_entry },
- { 'i', 0, &cmd_display_message_entry },
- { 'l', 0, &cmd_last_window_entry },
- { 'n', 0, &cmd_next_window_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 },
- { 's', 0, &cmd_choose_tree_entry },
- { 't', 0, &cmd_clock_mode_entry },
- { 'w', 0, &cmd_choose_window_entry },
- { 'x', 0, &cmd_confirm_before_entry },
- { 'z', 0, &cmd_resize_pane_entry },
- { '{', 0, &cmd_swap_pane_entry },
- { '}', 0, &cmd_swap_pane_entry },
- { '~', 0, &cmd_show_messages_entry },
- { '1' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
- { '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, 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 },
- { KEYC_RIGHT | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
- { KEYC_UP | KEYC_CTRL, 1, &cmd_resize_pane_entry },
- { KEYC_DOWN | KEYC_CTRL, 1, &cmd_resize_pane_entry },
- { KEYC_LEFT | KEYC_CTRL, 1, &cmd_resize_pane_entry },
- { KEYC_RIGHT | KEYC_CTRL, 1, &cmd_resize_pane_entry },
+ static const char* defaults[] = {
+ "bind C-b send-prefix",
+ "bind C-o rotate-window",
+ "bind C-z suspend-client",
+ "bind Space next-layout",
+ "bind ! break-pane",
+ "bind '\"' split-window",
+ "bind '#' list-buffers",
+ "bind '$' command-prompt -I'#S' \"rename-session '%%'\"",
+ "bind % split-window -h",
+ "bind & confirm-before -p\"kill-window #W? (y/n)\" kill-window",
+ "bind \"'\" command-prompt -pindex \"select-window -t ':%%'\"",
+ "bind ( switch-client -p",
+ "bind ) switch-client -n",
+ "bind , command-prompt -I'#W' \"rename-window '%%'\"",
+ "bind - delete-buffer",
+ "bind . command-prompt \"move-window -t '%%'\"",
+ "bind 0 select-window -t:0",
+ "bind 1 select-window -t:1",
+ "bind 2 select-window -t:2",
+ "bind 3 select-window -t:3",
+ "bind 4 select-window -t:4",
+ "bind 5 select-window -t:5",
+ "bind 6 select-window -t:6",
+ "bind 7 select-window -t:7",
+ "bind 8 select-window -t:8",
+ "bind 9 select-window -t:9",
+ "bind : command-prompt",
+ "bind \\; last-pane",
+ "bind = choose-buffer",
+ "bind ? list-keys",
+ "bind D choose-client",
+ "bind L switch-client -l",
+ "bind [ copy-mode",
+ "bind ] paste-buffer",
+ "bind c new-window",
+ "bind d detach-client",
+ "bind f command-prompt \"find-window '%%'\"",
+ "bind i display-message",
+ "bind l last-window",
+ "bind n next-window",
+ "bind o select-pane -t:.+",
+ "bind p previous-window",
+ "bind q display-panes",
+ "bind r refresh-client",
+ "bind s choose-tree",
+ "bind t clock-mode",
+ "bind w choose-window",
+ "bind x confirm-before -p\"kill-pane #P? (y/n)\" kill-pane",
+ "bind z resize-pane -Z",
+ "bind { swap-pane -U",
+ "bind } swap-pane -D",
+ "bind '~' show-messages",
+ "bind PPage copy-mode -u",
+ "bind -r Up select-pane -U",
+ "bind -r Down select-pane -D",
+ "bind -r Left select-pane -L",
+ "bind -r Right select-pane -R",
+ "bind M-1 select-layout even-horizontal",
+ "bind M-2 select-layout even-vertical",
+ "bind M-3 select-layout main-horizontal",
+ "bind M-4 select-layout main-vertical",
+ "bind M-5 select-layout tiled",
+ "bind M-n next-window -a",
+ "bind M-o rotate-window -D",
+ "bind M-p previous-window -a",
+ "bind -r M-Up resize-pane -U 5",
+ "bind -r M-Down resize-pane -D 5",
+ "bind -r M-Left resize-pane -L 5",
+ "bind -r M-Right resize-pane -R 5",
+ "bind -r C-Up resize-pane -U",
+ "bind -r C-Down resize-pane -D",
+ "bind -r C-Left resize-pane -L",
+ "bind -r C-Right resize-pane -R",
};
u_int i;
- struct cmd *cmd;
struct cmd_list *cmdlist;
+ char* cause;
+ int error;
+ struct cmd_q *cmdq;
RB_INIT(&key_bindings);
- for (i = 0; i < nitems(table); i++) {
- cmdlist = xcalloc(1, sizeof *cmdlist);
- cmdlist->references = 1;
- TAILQ_INIT(&cmdlist->list);
-
- cmd = xcalloc(1, sizeof *cmd);
- cmd->entry = table[i].entry;
- if (cmd->entry->key_binding != NULL)
- cmd->entry->key_binding(cmd, table[i].key);
- else
- cmd->args = args_create(0);
- TAILQ_INSERT_HEAD(&cmdlist->list, cmd, qentry);
-
- key_bindings_add(
- table[i].key | KEYC_PREFIX, table[i].can_repeat, cmdlist);
+ cmdq = cmdq_new(NULL);
+ for (i = 0; i < nitems(defaults); i++) {
+ error = cmd_string_parse(defaults[i], &cmdlist,
+ "<default-keys>", i, &cause);
+ if (error != 0)
+ fatalx("bad default key");
+ cmdq_run(cmdq, cmdlist);
+ cmd_list_free(cmdlist);
}
+ cmdq_free(cmdq);
}
void
@@ -212,7 +191,7 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c)
readonly = 0;
}
if (!readonly && (c->flags & CLIENT_READONLY)) {
- cmdq_info(c->cmdq, "client is read-only");
+ cmdq_error(c->cmdq, "client is read-only");
return;
}
diff --git a/key-string.c b/key-string.c
index 797eedd5..db968279 100644
--- a/key-string.c
+++ b/key-string.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -42,14 +42,6 @@ const struct {
{ "F10", KEYC_F10 },
{ "F11", KEYC_F11 },
{ "F12", KEYC_F12 },
- { "F13", KEYC_F13 },
- { "F14", KEYC_F14 },
- { "F15", KEYC_F15 },
- { "F16", KEYC_F16 },
- { "F17", KEYC_F17 },
- { "F18", KEYC_F18 },
- { "F19", KEYC_F19 },
- { "F20", KEYC_F20 },
{ "IC", KEYC_IC },
{ "DC", KEYC_DC },
{ "Home", KEYC_HOME },
diff --git a/layout-custom.c b/layout-custom.c
index e32d9d9d..c9cf49c2 100644
--- a/layout-custom.c
+++ b/layout-custom.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/layout-set.c b/layout-set.c
index 646528ba..64b655a0 100644
--- a/layout-set.c
+++ b/layout-set.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -23,8 +23,8 @@
#include "tmux.h"
/*
- * Set window layouts - predefined methods to arrange windows. These are one-off
- * and generate a layout tree.
+ * Set window layouts - predefined methods to arrange windows. These are
+ * one-off and generate a layout tree.
*/
void layout_set_even_h(struct window *);
diff --git a/layout.c b/layout.c
index 646d1bd9..b91b86cd 100644
--- a/layout.c
+++ b/layout.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/log.c b/log.c
index dbf9ee15..066165e8 100644
--- a/log.c
+++ b/log.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -17,43 +17,36 @@
*/
#include <sys/types.h>
+#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <syslog.h>
-#include <time.h>
#include "tmux.h"
-/* Log file, if needed. */
-FILE *log_file;
+FILE *log_file;
-/* Debug level. */
-int log_level = 0;
-
-void log_event_cb(int, const char *);
-void log_vwrite(const char *, va_list);
-__dead void log_vfatal(const char *, va_list);
+void log_event_cb(int, const char *);
+void log_vwrite(const char *, va_list);
/* Log callback for libevent. */
void
log_event_cb(unused int severity, const char *msg)
{
- log_warnx("%s", msg);
+ log_debug("%s", msg);
}
/* Open logging to file. */
void
-log_open(int level, const char *path)
+log_open(const char *path)
{
log_file = fopen(path, "w");
if (log_file == NULL)
return;
- log_level = level;
- setlinebuf(log_file);
+ setvbuf(log_file, NULL, _IOLBF, 0);
event_set_log_callback(log_event_cb);
tzset();
@@ -65,6 +58,7 @@ log_close(void)
{
if (log_file != NULL)
fclose(log_file);
+ log_file = NULL;
event_set_log_callback(NULL);
}
@@ -86,24 +80,9 @@ log_vwrite(const char *msg, va_list ap)
free(fmt);
}
-/* Log a warning with error string. */
-void printflike1
-log_warn(const char *msg, ...)
-{
- va_list ap;
- char *fmt;
-
- va_start(ap, msg);
- if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1)
- exit(1);
- log_vwrite(fmt, ap);
- free(fmt);
- va_end(ap);
-}
-
-/* Log a warning. */
-void printflike1
-log_warnx(const char *msg, ...)
+/* Log a debug message. */
+void
+log_debug(const char *msg, ...)
{
va_list ap;
@@ -112,82 +91,30 @@ log_warnx(const char *msg, ...)
va_end(ap);
}
-/* Log an informational message. */
-void printflike1
-log_info(const char *msg, ...)
-{
- va_list ap;
-
- if (log_level > -1) {
- va_start(ap, msg);
- log_vwrite(msg, ap);
- va_end(ap);
- }
-}
-
-/* Log a debug message. */
-void printflike1
-log_debug(const char *msg, ...)
-{
- va_list ap;
-
- if (log_level > 0) {
- va_start(ap, msg);
- log_vwrite(msg, ap);
- va_end(ap);
- }
-}
-
-/* Log a debug message at level 2. */
-void printflike1
-log_debug2(const char *msg, ...)
-{
- va_list ap;
-
- if (log_level > 1) {
- va_start(ap, msg);
- log_vwrite(msg, ap);
- va_end(ap);
- }
-}
-
-/* Log a critical error, with error string if necessary, and die. */
+/* Log a critical error with error string and die. */
__dead void
-log_vfatal(const char *msg, va_list ap)
-{
- char *fmt;
-
- if (errno != 0) {
- if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
- exit(1);
- log_vwrite(fmt, ap);
- } else {
- if (asprintf(&fmt, "fatal: %s", msg) == -1)
- exit(1);
- log_vwrite(fmt, ap);
- }
- free(fmt);
-
- exit(1);
-}
-
-/* Log a critical error, with error string, and die. */
-__dead void printflike1
log_fatal(const char *msg, ...)
{
- va_list ap;
+ char *fmt;
+ va_list ap;
va_start(ap, msg);
- log_vfatal(msg, ap);
+ if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
+ exit(1);
+ log_vwrite(fmt, ap);
+ exit(1);
}
/* Log a critical error and die. */
-__dead void printflike1
+__dead void
log_fatalx(const char *msg, ...)
{
- va_list ap;
+ char *fmt;
+ va_list ap;
- errno = 0;
va_start(ap, msg);
- log_vfatal(msg, ap);
+ if (asprintf(&fmt, "fatal: %s", msg) == -1)
+ exit(1);
+ log_vwrite(fmt, ap);
+ exit(1);
}
diff --git a/mode-key.c b/mode-key.c
index 95fad285..72d66f37 100644
--- a/mode-key.c
+++ b/mode-key.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -76,14 +76,18 @@ const struct mode_key_cmdstr mode_key_cmdstr_edit[] = {
/* Choice keys command strings. */
const struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
{ MODEKEYCHOICE_BACKSPACE, "backspace" },
+ { MODEKEYCHOICE_BOTTOMLINE, "bottom-line"},
{ MODEKEYCHOICE_CANCEL, "cancel" },
{ MODEKEYCHOICE_CHOOSE, "choose" },
{ MODEKEYCHOICE_DOWN, "down" },
+ { MODEKEYCHOICE_ENDOFLIST, "end-of-list"},
{ MODEKEYCHOICE_PAGEDOWN, "page-down" },
{ MODEKEYCHOICE_PAGEUP, "page-up" },
{ MODEKEYCHOICE_SCROLLDOWN, "scroll-down" },
{ MODEKEYCHOICE_SCROLLUP, "scroll-up" },
{ MODEKEYCHOICE_STARTNUMBERPREFIX, "start-number-prefix" },
+ { MODEKEYCHOICE_STARTOFLIST, "start-of-list"},
+ { MODEKEYCHOICE_TOPLINE, "top-line"},
{ MODEKEYCHOICE_TREE_COLLAPSE, "tree-collapse" },
{ MODEKEYCHOICE_TREE_COLLAPSE_ALL, "tree-collapse-all" },
{ MODEKEYCHOICE_TREE_EXPAND, "tree-expand" },
@@ -96,6 +100,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
/* Copy keys command strings. */
const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
+ { MODEKEYCOPY_APPENDSELECTION, "append-selection" },
{ MODEKEYCOPY_BACKTOINDENTATION, "back-to-indentation" },
{ MODEKEYCOPY_BOTTOMLINE, "bottom-line" },
{ MODEKEYCOPY_CANCEL, "cancel" },
@@ -125,6 +130,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
{ MODEKEYCOPY_NEXTSPACEEND, "next-space-end" },
{ MODEKEYCOPY_NEXTWORD, "next-word" },
{ MODEKEYCOPY_NEXTWORDEND, "next-word-end" },
+ { MODEKEYCOPY_OTHEREND, "other-end" },
{ MODEKEYCOPY_PREVIOUSPAGE, "page-up" },
{ MODEKEYCOPY_PREVIOUSSPACE, "previous-space" },
{ MODEKEYCOPY_PREVIOUSWORD, "previous-word" },
@@ -136,6 +142,7 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
{ MODEKEYCOPY_SEARCHREVERSE, "search-reverse" },
{ MODEKEYCOPY_SEARCHUP, "search-backward" },
{ MODEKEYCOPY_SELECTLINE, "select-line" },
+ { MODEKEYCOPY_STARTNAMEDBUFFER, "start-named-buffer" },
{ MODEKEYCOPY_STARTNUMBERPREFIX, "start-number-prefix" },
{ MODEKEYCOPY_STARTOFLINE, "start-of-line" },
{ MODEKEYCOPY_STARTSELECTION, "begin-selection" },
@@ -226,6 +233,12 @@ const struct mode_key_entry mode_key_vi_choice[] = {
{ 'j', 0, MODEKEYCHOICE_DOWN },
{ 'k', 0, MODEKEYCHOICE_UP },
{ 'q', 0, MODEKEYCHOICE_CANCEL },
+ { KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST },
+ { 'g', 0, MODEKEYCHOICE_STARTOFLIST },
+ { 'H', 0, MODEKEYCHOICE_TOPLINE },
+ { 'L', 0, MODEKEYCHOICE_BOTTOMLINE },
+ { 'G', 0, MODEKEYCHOICE_ENDOFLIST },
+ { KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST },
{ KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE },
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN },
{ KEYC_DOWN, 0, MODEKEYCHOICE_DOWN },
@@ -246,6 +259,7 @@ struct mode_key_tree mode_key_tree_vi_choice;
/* vi copy mode keys. */
const struct mode_key_entry mode_key_vi_copy[] = {
{ ' ', 0, MODEKEYCOPY_STARTSELECTION },
+ { '"', 0, MODEKEYCOPY_STARTNAMEDBUFFER },
{ '$', 0, MODEKEYCOPY_ENDOFLINE },
{ ',', 0, MODEKEYCOPY_JUMPREVERSE },
{ ';', 0, MODEKEYCOPY_JUMPAGAIN },
@@ -262,6 +276,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
{ '9', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
{ ':', 0, MODEKEYCOPY_GOTOLINE },
{ '?', 0, MODEKEYCOPY_SEARCHUP },
+ { 'A', 0, MODEKEYCOPY_APPENDSELECTION },
{ 'B', 0, MODEKEYCOPY_PREVIOUSSPACE },
{ 'D', 0, MODEKEYCOPY_COPYENDOFLINE },
{ 'E', 0, MODEKEYCOPY_NEXTSPACEEND },
@@ -274,6 +289,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
{ 'M', 0, MODEKEYCOPY_MIDDLELINE },
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
{ 'T', 0, MODEKEYCOPY_JUMPTOBACK },
+ { 'V', 0, MODEKEYCOPY_SELECTLINE },
{ 'W', 0, MODEKEYCOPY_NEXTSPACE },
{ '\002' /* C-b */, 0, MODEKEYCOPY_PREVIOUSPAGE },
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL },
@@ -372,6 +388,11 @@ const struct mode_key_entry mode_key_emacs_choice[] = {
{ '\r', 0, MODEKEYCHOICE_CHOOSE },
{ 'q', 0, MODEKEYCHOICE_CANCEL },
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCHOICE_PAGEUP },
+ { KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST },
+ { '<' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTOFLIST },
+ { 'R' | KEYC_ESCAPE, 0, MODEKEYCHOICE_TOPLINE },
+ { '>' | KEYC_ESCAPE, 0, MODEKEYCHOICE_ENDOFLIST },
+ { KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST },
{ KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE },
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN },
{ KEYC_DOWN, 0, MODEKEYCHOICE_DOWN },
diff --git a/names.c b/names.c
index 7c02961c..1ceb83c0 100644
--- a/names.c
+++ b/names.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -68,9 +68,15 @@ window_name_callback(unused int fd, unused short events, void *data)
char *
default_window_name(struct window *w)
{
- if (w->active->cmd != NULL && *w->active->cmd != '\0')
- return (parse_window_name(w->active->cmd));
- return (parse_window_name(w->active->shell));
+ char *cmd, *s;
+
+ cmd = cmd_stringify_argv(w->active->argc, w->active->argv);
+ if (cmd != NULL && *cmd != '\0')
+ s = parse_window_name(cmd);
+ else
+ s = parse_window_name(w->active->shell);
+ free(cmd);
+ return (s);
}
char *
@@ -80,8 +86,8 @@ format_window_name(struct window *w)
char *fmt, *name;
ft = format_create();
- format_window(ft, w);
- format_window_pane(ft, w->active);
+ format_defaults_window(ft, w);
+ format_defaults_pane(ft, w->active);
fmt = options_get_string(&w->options, "automatic-rename-format");
name = format_expand(ft, fmt);
diff --git a/notify.c b/notify.c
index bd5c7d83..47945aec 100644
--- a/notify.c
+++ b/notify.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2012 George Nachman <tmux@georgester.com>
diff --git a/options-table.c b/options-table.c
index 64d3edcd..2bcf29b4 100644
--- a/options-table.c
+++ b/options-table.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,8 +27,8 @@
* options. These tables are the master copy of the options with their real
* (user-visible) types, range limits and default values. At start these are
* copied into the runtime global options trees (which only has number and
- * string types). These tables are then used to loop up the real type when
- * the user sets an option or its value needs to be shown.
+ * string types). These tables are then used to look up the real type when the
+ * user sets an option or its value needs to be shown.
*/
/* Choice option type lists. */
@@ -80,9 +80,16 @@ const struct options_table_entry server_options_table[] = {
.default_num = 0
},
+ { .name = "message-limit",
+ .type = OPTIONS_TABLE_NUMBER,
+ .minimum = 0,
+ .maximum = INT_MAX,
+ .default_num = 100
+ },
+
{ .name = "quiet",
.type = OPTIONS_TABLE_FLAG,
- .default_num = 0 /* overridden in main() */
+ .default_num = 0
},
{ .name = "set-clipboard",
@@ -90,6 +97,14 @@ const struct options_table_entry server_options_table[] = {
.default_num = 1
},
+ { .name = "terminal-overrides",
+ .type = OPTIONS_TABLE_STRING,
+ .default_str = "*256col*:colors=256"
+ ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
+ ":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007"
+ ":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT"
+ },
+
{ .name = NULL }
};
@@ -234,13 +249,6 @@ const struct options_table_entry session_options_table[] = {
.style = "message-style"
},
- { .name = "message-limit",
- .type = OPTIONS_TABLE_NUMBER,
- .minimum = 0,
- .maximum = INT_MAX,
- .default_num = 20
- },
-
{ .name = "message-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "bg=yellow,fg=black"
@@ -266,40 +274,6 @@ const struct options_table_entry session_options_table[] = {
.default_num = 0
},
- { .name = "pane-active-border-bg",
- .type = OPTIONS_TABLE_COLOUR,
- .default_num = 8,
- .style = "pane-active-border-style"
- },
-
- { .name = "pane-active-border-fg",
- .type = OPTIONS_TABLE_COLOUR,
- .default_num = 2,
- .style = "pane-active-border-style"
- },
-
- { .name = "pane-active-border-style",
- .type = OPTIONS_TABLE_STYLE,
- .default_str = "fg=green"
- },
-
- { .name = "pane-border-bg",
- .type = OPTIONS_TABLE_COLOUR,
- .default_num = 8,
- .style = "pane-border-style"
- },
-
- { .name = "pane-border-fg",
- .type = OPTIONS_TABLE_COLOUR,
- .default_num = 8,
- .style = "pane-border-style"
- },
-
- { .name = "pane-border-style",
- .type = OPTIONS_TABLE_STYLE,
- .default_str = "default"
- },
-
{ .name = "prefix",
.type = OPTIONS_TABLE_KEY,
.default_num = '\002',
@@ -381,7 +355,7 @@ const struct options_table_entry session_options_table[] = {
{ .name = "status-left",
.type = OPTIONS_TABLE_STRING,
- .default_str = "[#S]"
+ .default_str = "[#S] "
},
{ .name = "status-left-attr",
@@ -422,7 +396,7 @@ const struct options_table_entry session_options_table[] = {
{ .name = "status-right",
.type = OPTIONS_TABLE_STRING,
- .default_str = "\"#{=22:pane_title}\" %H:%M %d-%b-%y"
+ .default_str = " \"#{=21:pane_title}\" %H:%M %d-%b-%y"
},
{ .name = "status-right-attr",
@@ -465,14 +439,6 @@ const struct options_table_entry session_options_table[] = {
.default_num = 0 /* overridden in main() */
},
- { .name = "terminal-overrides",
- .type = OPTIONS_TABLE_STRING,
- .default_str = "*256col*:colors=256"
- ",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
- ":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007"
- ":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT"
- },
-
{ .name = "update-environment",
.type = OPTIONS_TABLE_STRING,
.default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID "
@@ -490,11 +456,6 @@ const struct options_table_entry session_options_table[] = {
.default_num = 0
},
- { .name = "visual-content",
- .type = OPTIONS_TABLE_FLAG,
- .default_num = 0
- },
-
{ .name = "visual-silence",
.type = OPTIONS_TABLE_FLAG,
.default_num = 0
@@ -532,7 +493,8 @@ const struct options_table_entry window_options_table[] = {
{ .name = "automatic-rename-format",
.type = OPTIONS_TABLE_STRING,
- .default_str = "#{?pane_in_mode,[tmux],#{pane_current_command}}#{?pane_dead,[dead],}"
+ .default_str = "#{?pane_in_mode,[tmux],#{pane_current_command}}"
+ "#{?pane_dead,[dead],}"
},
{ .name = "c0-change-trigger",
@@ -628,11 +590,6 @@ const struct options_table_entry window_options_table[] = {
.default_num = 0
},
- { .name = "monitor-content",
- .type = OPTIONS_TABLE_STRING,
- .default_str = ""
- },
-
{ .name = "monitor-silence",
.type = OPTIONS_TABLE_NUMBER,
.minimum = 0,
@@ -654,6 +611,23 @@ const struct options_table_entry window_options_table[] = {
.default_num = 0
},
+ { .name = "pane-active-border-bg",
+ .type = OPTIONS_TABLE_COLOUR,
+ .default_num = 8,
+ .style = "pane-active-border-style"
+ },
+
+ { .name = "pane-active-border-fg",
+ .type = OPTIONS_TABLE_COLOUR,
+ .default_num = 2,
+ .style = "pane-active-border-style"
+ },
+
+ { .name = "pane-active-border-style",
+ .type = OPTIONS_TABLE_STYLE,
+ .default_str = "fg=green"
+ },
+
{ .name = "pane-base-index",
.type = OPTIONS_TABLE_NUMBER,
.minimum = 0,
@@ -661,6 +635,23 @@ const struct options_table_entry window_options_table[] = {
.default_num = 0
},
+ { .name = "pane-border-bg",
+ .type = OPTIONS_TABLE_COLOUR,
+ .default_num = 8,
+ .style = "pane-border-style"
+ },
+
+ { .name = "pane-border-fg",
+ .type = OPTIONS_TABLE_COLOUR,
+ .default_num = 8,
+ .style = "pane-border-style"
+ },
+
+ { .name = "pane-border-style",
+ .type = OPTIONS_TABLE_STYLE,
+ .default_str = "default"
+ },
+
{ .name = "remain-on-exit",
.type = OPTIONS_TABLE_FLAG,
.default_num = 0
@@ -734,29 +725,6 @@ const struct options_table_entry window_options_table[] = {
.style = "window-status-style"
},
- { .name = "window-status-content-attr",
- .type = OPTIONS_TABLE_ATTRIBUTES,
- .default_num = GRID_ATTR_REVERSE,
- .style = "window-status-content-style"
- },
-
- { .name = "window-status-content-bg",
- .type = OPTIONS_TABLE_COLOUR,
- .default_num = 8,
- .style = "window-status-content-style"
- },
-
- { .name = "window-status-content-fg",
- .type = OPTIONS_TABLE_COLOUR,
- .default_num = 8,
- .style = "window-status-content-style"
- },
-
- { .name = "window-status-content-style",
- .type = OPTIONS_TABLE_STYLE,
- .default_str = "reverse"
- },
-
{ .name = "window-status-current-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0,
diff --git a/options.c b/options.c
index 8bec8e5c..67f8abde 100644
--- a/options.c
+++ b/options.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -99,7 +99,7 @@ options_remove(struct options *oo, const char *name)
free(o);
}
-struct options_entry *printflike3
+struct options_entry *
options_set_string(struct options *oo, const char *name, const char *fmt, ...)
{
struct options_entry *o;
diff --git a/osdep-aix.c b/osdep-aix.c
index 8d590816..24051ab8 100644
--- a/osdep-aix.c
+++ b/osdep-aix.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/osdep-cygwin.c b/osdep-cygwin.c
new file mode 100644
index 00000000..91bc5fc9
--- /dev/null
+++ b/osdep-cygwin.c
@@ -0,0 +1,88 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <event.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+char *
+osdep_get_name(int fd, unused char *tty)
+{
+ FILE *f;
+ char *path, *buf;
+ size_t len;
+ int ch;
+ pid_t pgrp;
+
+ if ((pgrp = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ xasprintf(&path, "/proc/%lld/cmdline", (long long) pgrp);
+ if ((f = fopen(path, "r")) == NULL) {
+ free(path);
+ return (NULL);
+ }
+ free(path);
+
+ len = 0;
+ buf = NULL;
+ while ((ch = fgetc(f)) != EOF) {
+ if (ch == '\0')
+ break;
+ buf = xrealloc(buf, len + 2);
+ buf[len++] = ch;
+ }
+ if (buf != NULL)
+ buf[len] = '\0';
+
+ fclose(f);
+ return (buf);
+}
+
+char *
+osdep_get_cwd(int fd)
+{
+ static char target[MAXPATHLEN + 1];
+ char *path;
+ pid_t pgrp;
+ ssize_t n;
+
+ if ((pgrp = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ xasprintf(&path, "/proc/%lld/cwd", (long long) pgrp);
+ n = readlink(path, target, MAXPATHLEN);
+ free(path);
+ if (n > 0) {
+ target[n] = '\0';
+ return (target);
+ }
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ return (event_init());
+}
diff --git a/osdep-darwin.c b/osdep-darwin.c
index dc60b092..7be70375 100644
--- a/osdep-darwin.c
+++ b/osdep-darwin.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
diff --git a/osdep-dragonfly.c b/osdep-dragonfly.c
index ad417d98..f9b0efcf 100644
--- a/osdep-dragonfly.c
+++ b/osdep-dragonfly.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/osdep-freebsd.c b/osdep-freebsd.c
index d596eab4..d7f419b8 100644
--- a/osdep-freebsd.c
+++ b/osdep-freebsd.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -132,8 +132,8 @@ error:
return (NULL);
}
-char *
-osdep_get_cwd(int fd)
+static char *
+osdep_get_cwd_fallback(int fd)
{
static char wd[PATH_MAX];
struct kinfo_file *info = NULL;
@@ -158,6 +158,38 @@ osdep_get_cwd(int fd)
return (NULL);
}
+#ifdef KERN_PROC_CWD
+char *
+osdep_get_cwd(int fd)
+{
+ static struct kinfo_file info;
+ static int fallback;
+ int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_CWD, 0 };
+ size_t len = sizeof info;
+
+ if (fallback)
+ return (osdep_get_cwd_fallback(fd));
+
+ if ((name[3] = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ if (sysctl(name, 4, &info, &len, NULL, 0) == -1) {
+ if (errno == ENOENT) {
+ fallback = 1;
+ return (osdep_get_cwd_fallback(fd));
+ }
+ return (NULL);
+ }
+ return (info.kf_path);
+}
+#else /* !KERN_PROC_CWD */
+char *
+osdep_get_cwd(int fd)
+{
+ return (osdep_get_cwd_fallback(fd));
+}
+#endif /* KERN_PROC_CWD */
+
struct event_base *
osdep_event_init(void)
{
diff --git a/osdep-hpux.c b/osdep-hpux.c
index 352e375b..4baa6d49 100644
--- a/osdep-hpux.c
+++ b/osdep-hpux.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/osdep-linux.c b/osdep-linux.c
index ccac2670..ad4c11cd 100644
--- a/osdep-linux.c
+++ b/osdep-linux.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/param.h>
#include <event.h>
#include <stdio.h>
@@ -50,7 +51,7 @@ osdep_get_name(int fd, unused char *tty)
while ((ch = fgetc(f)) != EOF) {
if (ch == '\0')
break;
- buf = xrealloc(buf, 1, len + 2);
+ buf = xrealloc(buf, len + 2);
buf[len++] = ch;
}
if (buf != NULL)
@@ -65,7 +66,7 @@ osdep_get_cwd(int fd)
{
static char target[MAXPATHLEN + 1];
char *path;
- pid_t pgrp;
+ pid_t pgrp, sid;
ssize_t n;
if ((pgrp = tcgetpgrp(fd)) == -1)
@@ -74,6 +75,13 @@ osdep_get_cwd(int fd)
xasprintf(&path, "/proc/%lld/cwd", (long long) pgrp);
n = readlink(path, target, MAXPATHLEN);
free(path);
+
+ if (n == -1 && ioctl(fd, TIOCGSID, &sid) != -1) {
+ xasprintf(&path, "/proc/%lld/cwd", (long long) sid);
+ n = readlink(path, target, MAXPATHLEN);
+ free(path);
+ }
+
if (n > 0) {
target[n] = '\0';
return (target);
diff --git a/osdep-netbsd.c b/osdep-netbsd.c
index f16d0dc8..15686860 100644
--- a/osdep-netbsd.c
+++ b/osdep-netbsd.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/osdep-openbsd.c b/osdep-openbsd.c
index 0a4c1445..414228b7 100644
--- a/osdep-openbsd.c
+++ b/osdep-openbsd.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -16,7 +16,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
+#include <sys/param.h> /* MAXCOMLEN */
+#include <sys/types.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/stat.h>
@@ -34,7 +35,7 @@
#define is_runnable(p) \
((p)->p_stat == SRUN || (p)->p_stat == SIDL || (p)->p_stat == SONPROC)
#define is_stopped(p) \
- ((p)->p_stat == SSTOP || (p)->p_stat == SZOMB || (p)->p_stat == SDEAD)
+ ((p)->p_stat == SSTOP || (p)->p_stat == SDEAD)
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
char *osdep_get_name(int, char *);
@@ -99,7 +100,7 @@ osdep_get_name(int fd, char *tty)
retry:
if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1)
- return (NULL);
+ goto error;
len = (len * 5) / 4;
if ((newbuf = realloc(buf, len)) == NULL)
diff --git a/osdep-sunos.c b/osdep-sunos.c
index fd644f5d..855cac9d 100644
--- a/osdep-sunos.c
+++ b/osdep-sunos.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Todd Carson <toc@daybefore.net>
@@ -69,10 +69,19 @@ osdep_get_cwd(int fd)
{
static char target[MAXPATHLEN + 1];
char *path;
+ const char *ttypath;
ssize_t n;
pid_t pgrp;
+ int retval, ttyfd;
- if ((pgrp = tcgetpgrp(fd)) == -1)
+ if ((ttypath = ptsname(fd)) == NULL)
+ return (NULL);
+ if ((ttyfd = open(ttypath, O_RDONLY|O_NOCTTY)) == -1)
+ return (NULL);
+
+ retval = ioctl(ttyfd, TIOCGPGRP, &pgrp);
+ close(ttyfd);
+ if (retval == -1)
return (NULL);
xasprintf(&path, "/proc/%u/path/cwd", (u_int) pgrp);
diff --git a/osdep-unknown.c b/osdep-unknown.c
index 41f435bc..4de1ee1e 100644
--- a/osdep-unknown.c
+++ b/osdep-unknown.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/paste.c b/paste.c
index bc9b4686..998b975a 100644
--- a/paste.c
+++ b/paste.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -25,159 +25,282 @@
#include "tmux.h"
/*
- * Stack of paste buffers. Note that paste buffer data is not necessarily a C
+ * Set of paste buffers. Note that paste buffer data is not necessarily a C
* string!
*/
-/* Return each item of the stack in turn. */
-struct paste_buffer *
-paste_walk_stack(struct paste_stack *ps, u_int *idx)
+u_int paste_next_index;
+u_int paste_next_order;
+u_int paste_num_automatic;
+RB_HEAD(paste_name_tree, paste_buffer) paste_by_name;
+RB_HEAD(paste_time_tree, paste_buffer) paste_by_time;
+
+int paste_cmp_names(const struct paste_buffer *, const struct paste_buffer *);
+RB_PROTOTYPE(paste_name_tree, paste_buffer, name_entry, paste_cmp_names);
+RB_GENERATE(paste_name_tree, paste_buffer, name_entry, paste_cmp_names);
+
+int paste_cmp_times(const struct paste_buffer *, const struct paste_buffer *);
+RB_PROTOTYPE(paste_time_tree, paste_buffer, time_entry, paste_cmp_times);
+RB_GENERATE(paste_time_tree, paste_buffer, time_entry, paste_cmp_times);
+
+int
+paste_cmp_names(const struct paste_buffer *a, const struct paste_buffer *b)
{
- struct paste_buffer *pb;
+ return (strcmp(a->name, b->name));
+}
- pb = paste_get_index(ps, *idx);
- (*idx)++;
- return (pb);
+int
+paste_cmp_times(const struct paste_buffer *a, const struct paste_buffer *b)
+{
+ if (a->order > b->order)
+ return (-1);
+ if (a->order < b->order)
+ return (1);
+ return (0);
}
-/* Get the top item on the stack. */
+/* Walk paste buffers by name. */
struct paste_buffer *
-paste_get_top(struct paste_stack *ps)
+paste_walk(struct paste_buffer *pb)
{
- if (ARRAY_LENGTH(ps) == 0)
- return (NULL);
- return (ARRAY_FIRST(ps));
+ if (pb == NULL)
+ return (RB_MIN(paste_time_tree, &paste_by_time));
+ return (RB_NEXT(paste_time_tree, &paste_by_time, pb));
}
-/* Get an item by its index. */
+/* Get the most recent automatic buffer. */
struct paste_buffer *
-paste_get_index(struct paste_stack *ps, u_int idx)
+paste_get_top(void)
{
- if (idx >= ARRAY_LENGTH(ps))
+ struct paste_buffer *pb;
+
+ pb = RB_MIN(paste_time_tree, &paste_by_time);
+ if (pb == NULL)
return (NULL);
- return (ARRAY_ITEM(ps, idx));
+ return (pb);
}
-/* Free the top item on the stack. */
+/* Free the most recent buffer. */
int
-paste_free_top(struct paste_stack *ps)
+paste_free_top(void)
{
struct paste_buffer *pb;
- if (ARRAY_LENGTH(ps) == 0)
+ pb = paste_get_top();
+ if (pb == NULL)
return (-1);
+ return (paste_free_name(pb->name));
+}
- pb = ARRAY_FIRST(ps);
- ARRAY_REMOVE(ps, 0);
+/* Get a paste buffer by name. */
+struct paste_buffer *
+paste_get_name(const char *name)
+{
+ struct paste_buffer pbfind;
- free(pb->data);
- free(pb);
+ if (name == NULL || *name == '\0')
+ return (NULL);
- return (0);
+ pbfind.name = (char *)name;
+ return (RB_FIND(paste_name_tree, &paste_by_name, &pbfind));
}
-/* Free an item by index. */
+/* Free a paste buffer by name. */
int
-paste_free_index(struct paste_stack *ps, u_int idx)
+paste_free_name(const char *name)
{
- struct paste_buffer *pb;
+ struct paste_buffer *pb, pbfind;
+
+ if (name == NULL || *name == '\0')
+ return (-1);
- if (idx >= ARRAY_LENGTH(ps))
+ pbfind.name = (char *)name;
+ pb = RB_FIND(paste_name_tree, &paste_by_name, &pbfind);
+ if (pb == NULL)
return (-1);
- pb = ARRAY_ITEM(ps, idx);
- ARRAY_REMOVE(ps, idx);
+ RB_REMOVE(paste_name_tree, &paste_by_name, pb);
+ RB_REMOVE(paste_time_tree, &paste_by_time, pb);
+ if (pb->automatic)
+ paste_num_automatic--;
free(pb->data);
+ free(pb->name);
free(pb);
-
return (0);
}
/*
- * Add an item onto the top of the stack, freeing the bottom if at limit. Note
+ * Add an automatic buffer, freeing the oldest automatic item if at limit. Note
* that the caller is responsible for allocating data.
*/
void
-paste_add(struct paste_stack *ps, char *data, size_t size, u_int limit)
+paste_add(char *data, size_t size)
{
- struct paste_buffer *pb;
+ struct paste_buffer *pb, *pb1;
+ u_int limit;
if (size == 0)
return;
- while (ARRAY_LENGTH(ps) >= limit) {
- pb = ARRAY_LAST(ps);
- free(pb->data);
- free(pb);
- ARRAY_TRUNC(ps, 1);
+ limit = options_get_number(&global_options, "buffer-limit");
+ RB_FOREACH_REVERSE_SAFE(pb, paste_time_tree, &paste_by_time, pb1) {
+ if (paste_num_automatic < limit)
+ break;
+ if (pb->automatic)
+ paste_free_name(pb->name);
}
pb = xmalloc(sizeof *pb);
- ARRAY_INSERT(ps, 0, pb);
+
+ pb->name = NULL;
+ do {
+ free(pb->name);
+ xasprintf(&pb->name, "buffer%04u", paste_next_index);
+ paste_next_index++;
+ } while (paste_get_name(pb->name) != NULL);
pb->data = data;
pb->size = size;
+
+ pb->automatic = 1;
+ paste_num_automatic++;
+
+ pb->order = paste_next_order++;
+ RB_INSERT(paste_name_tree, &paste_by_name, pb);
+ RB_INSERT(paste_time_tree, &paste_by_time, pb);
}
+/* Rename a paste buffer. */
+int
+paste_rename(const char *oldname, const char *newname, char **cause)
+{
+ struct paste_buffer *pb, *pb_new;
+
+ if (cause != NULL)
+ *cause = NULL;
+
+ if (oldname == NULL || *oldname == '\0') {
+ if (cause != NULL)
+ *cause = xstrdup("no buffer");
+ return (-1);
+ }
+ if (newname == NULL || *newname == '\0') {
+ if (cause != NULL)
+ *cause = xstrdup("new name is empty");
+ return (-1);
+ }
+
+ pb = paste_get_name(oldname);
+ if (pb == NULL) {
+ if (cause != NULL)
+ xasprintf(cause, "no buffer %s", oldname);
+ return (-1);
+ }
+
+ pb_new = paste_get_name(newname);
+ if (pb_new != NULL) {
+ if (cause != NULL)
+ xasprintf(cause, "buffer %s already exists", newname);
+ return (-1);
+ }
+
+ RB_REMOVE(paste_name_tree, &paste_by_name, pb);
+
+ free(pb->name);
+ pb->name = xstrdup(newname);
+
+ if (pb->automatic)
+ paste_num_automatic--;
+ pb->automatic = 0;
+
+ RB_INSERT(paste_name_tree, &paste_by_name, pb);
+
+ return (0);
+}
/*
- * Replace an item on the stack. Note that the caller is responsible for
+ * Add or replace an item in the store. Note that the caller is responsible for
* allocating data.
*/
int
-paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size)
+paste_set(char *data, size_t size, const char *name, char **cause)
{
struct paste_buffer *pb;
+ if (cause != NULL)
+ *cause = NULL;
+
if (size == 0) {
free(data);
return (0);
}
+ if (name == NULL) {
+ paste_add(data, size);
+ return (0);
+ }
- if (idx >= ARRAY_LENGTH(ps))
+ if (*name == '\0') {
+ if (cause != NULL)
+ *cause = xstrdup("empty buffer name");
return (-1);
+ }
- pb = ARRAY_ITEM(ps, idx);
- free(pb->data);
+ pb = paste_get_name(name);
+ if (pb != NULL)
+ paste_free_name(name);
+
+ pb = xmalloc(sizeof *pb);
+
+ pb->name = xstrdup(name);
pb->data = data;
pb->size = size;
+ pb->automatic = 0;
+ pb->order = paste_next_order++;
+
+ RB_INSERT(paste_name_tree, &paste_by_name, pb);
+ RB_INSERT(paste_time_tree, &paste_by_time, pb);
+
return (0);
}
-/* Convert a buffer into a visible string. */
+/* Convert start of buffer into a nice string. */
char *
-paste_print(struct paste_buffer *pb, size_t width)
+paste_make_sample(struct paste_buffer *pb, int utf8flag)
{
- char *buf;
- size_t len, used;
-
- if (width < 3)
- width = 3;
- buf = xmalloc(width * 4 + 1);
+ char *buf;
+ size_t len, used;
+ const int flags = VIS_OCTAL|VIS_TAB|VIS_NL;
+ const size_t width = 200;
len = pb->size;
if (len > width)
len = width;
+ buf = xreallocarray(NULL, len, 4 + 4);
- used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
+ if (utf8flag)
+ used = utf8_strvis(buf, pb->data, len, flags);
+ else
+ used = strvisx(buf, pb->data, len, flags);
if (pb->size > width || used > width)
- strlcpy(buf + width - 3, "...", 4);
-
+ strlcpy(buf + width, "...", 4);
return (buf);
}
/* Paste into a window pane, filtering '\n' according to separator. */
void
-paste_send_pane (struct paste_buffer *pb, struct window_pane *wp,
+paste_send_pane(struct paste_buffer *pb, struct window_pane *wp,
const char *sep, int bracket)
{
const char *data = pb->data, *end = data + pb->size, *lf;
size_t seplen;
- if (bracket)
+ if (wp->flags & PANE_INPUTOFF)
+ return;
+
+ if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
bufferevent_write(wp->event, "\033[200~", 6);
seplen = strlen(sep);
@@ -191,6 +314,6 @@ paste_send_pane (struct paste_buffer *pb, struct window_pane *wp,
if (end != data)
bufferevent_write(wp->event, data, end - data);
- if (bracket)
+ if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
bufferevent_write(wp->event, "\033[201~", 6);
}
diff --git a/resize.c b/resize.c
index 8d0bd275..9ad73c81 100644
--- a/resize.c
+++ b/resize.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -50,11 +50,12 @@ recalculate_sizes(void)
struct window *w;
struct window_pane *wp;
u_int i, j, ssx, ssy, has, limit;
- int flag, has_status, is_zoomed;
+ int flag, has_status, is_zoomed, forced;
RB_FOREACH(s, sessions, &sessions) {
has_status = options_get_number(&s->options, "status");
+ s->attached = 0;
ssx = ssy = UINT_MAX;
for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
c = ARRAY_ITEM(&clients, j);
@@ -69,6 +70,7 @@ recalculate_sizes(void)
ssy = c->tty.sy - 1;
else if (c->tty.sy < ssy)
ssy = c->tty.sy;
+ s->attached++;
}
}
if (ssx == UINT_MAX || ssy == UINT_MAX) {
@@ -114,18 +116,26 @@ recalculate_sizes(void)
if (ssx == UINT_MAX || ssy == UINT_MAX)
continue;
+ forced = 0;
limit = options_get_number(&w->options, "force-width");
- if (limit != 0 && ssx > limit)
+ if (limit >= PANE_MINIMUM && ssx > limit) {
ssx = limit;
+ forced |= WINDOW_FORCEWIDTH;
+ }
limit = options_get_number(&w->options, "force-height");
- if (limit != 0 && ssy > limit)
+ if (limit >= PANE_MINIMUM && ssy > limit) {
ssy = limit;
+ forced |= WINDOW_FORCEHEIGHT;
+ }
if (w->sx == ssx && w->sy == ssy)
continue;
log_debug("window size %u,%u (was %u,%u)", ssx, ssy, w->sx,
w->sy);
+ w->flags &= ~(WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
+ w->flags |= forced;
+
is_zoomed = w->flags & WINDOW_ZOOMED;
if (is_zoomed)
window_unzoom(w);
diff --git a/screen-redraw.c b/screen-redraw.c
index 6db1064b..c2b2ece6 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -275,11 +275,40 @@ void
screen_redraw_draw_borders(struct client *c, int status, u_int top)
{
struct window *w = c->session->curw->window;
- struct options *oo = &c->session->options;
+ struct options *oo = &w->options;
struct tty *tty = &c->tty;
struct window_pane *wp;
- struct grid_cell active_gc, other_gc;
- u_int i, j, type;
+ struct grid_cell active_gc, other_gc, msg_gc;
+ u_int i, j, type, msgx = 0, msgy = 0;
+ int small, flags;
+ char msg[256];
+ const char *tmp;
+ size_t msglen = 0;
+
+ small = (tty->sy - status + top > w->sy) || (tty->sx > w->sx);
+ if (small) {
+ flags = w->flags & (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
+ if (flags == (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT))
+ tmp = "force-width, force-height";
+ else if (flags == WINDOW_FORCEWIDTH)
+ tmp = "force-width";
+ else if (flags == WINDOW_FORCEHEIGHT)
+ tmp = "force-height";
+ else
+ tmp = "a smaller client";
+ xsnprintf(msg, sizeof msg, "(size %ux%u from %s)",
+ w->sx, w->sy, tmp);
+ msglen = strlen(msg);
+
+ if (tty->sy - 1 - status + top > w->sy && tty->sx >= msglen) {
+ msgx = tty->sx - msglen;
+ msgy = tty->sy - 1 - status + top;
+ } else if (tty->sx - w->sx > msglen) {
+ msgx = tty->sx - msglen;
+ msgy = tty->sy - 1 - status + top;
+ } else
+ small = 0;
+ }
style_apply(&other_gc, oo, "pane-border-style");
style_apply(&active_gc, oo, "pane-active-border-style");
@@ -290,6 +319,9 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
type = screen_redraw_check_cell(c, i, j, &wp);
if (type == CELL_INSIDE)
continue;
+ if (type == CELL_OUTSIDE &&
+ small && i > msgx && j == msgy)
+ continue;
if (screen_redraw_check_active(i, j, type, w, wp))
tty_attributes(tty, &active_gc);
else
@@ -298,6 +330,13 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
tty_putc(tty, CELL_BORDERS[type]);
}
}
+
+ if (small) {
+ memcpy(&msg_gc, &grid_default_cell, sizeof msg_gc);
+ tty_attributes(tty, &msg_gc);
+ tty_cursor(tty, msgx, msgy);
+ tty_puts(tty, msg);
+ }
}
/* Draw the panes. */
@@ -381,7 +420,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
for (j = 0; j < 5; j++) {
for (i = px; i < px + 5; i++) {
tty_cursor(tty, xoff + i, yoff + py + j);
- if (clock_table[idx][j][i - px])
+ if (window_clock_table[idx][j][i - px])
tty_putc(tty, ' ');
}
}
diff --git a/screen-write.c b/screen-write.c
index 0de1df40..e38c9f53 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -25,13 +25,13 @@
void screen_write_initctx(struct screen_write_ctx *, struct tty_ctx *, int);
void screen_write_overwrite(struct screen_write_ctx *, u_int);
-int screen_write_combine(
- struct screen_write_ctx *, const struct utf8_data *);
+int screen_write_combine(struct screen_write_ctx *,
+ const struct utf8_data *);
/* Initialise writing with a window. */
void
-screen_write_start(
- struct screen_write_ctx *ctx, struct window_pane *wp, struct screen *s)
+screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
+ struct screen *s)
{
ctx->wp = wp;
if (wp != NULL && s == NULL)
@@ -65,14 +65,15 @@ screen_write_reset(struct screen_write_ctx *ctx)
/* Write character. */
void
-screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc, u_char ch)
+screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc,
+ u_char ch)
{
grid_cell_one(gc, ch);
screen_write_cell(ctx, gc);
}
/* Calculate string length, with embedded formatting. */
-size_t printflike2
+size_t
screen_write_cstrlen(int utf8flag, const char *fmt, ...)
{
va_list ap;
@@ -107,7 +108,7 @@ screen_write_cstrlen(int utf8flag, const char *fmt, ...)
}
/* Calculate string length. */
-size_t printflike2
+size_t
screen_write_strlen(int utf8flag, const char *fmt, ...)
{
va_list ap;
@@ -144,9 +145,9 @@ screen_write_strlen(int utf8flag, const char *fmt, ...)
}
/* Write simple string (no UTF-8 or maximum length). */
-void printflike3
-screen_write_puts(
- struct screen_write_ctx *ctx, struct grid_cell *gc, const char *fmt, ...)
+void
+screen_write_puts(struct screen_write_ctx *ctx, struct grid_cell *gc,
+ const char *fmt, ...)
{
va_list ap;
@@ -156,9 +157,9 @@ screen_write_puts(
}
/* Write string with length limit (-1 for unlimited). */
-void printflike5
-screen_write_nputs(struct screen_write_ctx *ctx,
- ssize_t maxlen, struct grid_cell *gc, int utf8flag, const char *fmt, ...)
+void
+screen_write_nputs(struct screen_write_ctx *ctx, ssize_t maxlen,
+ struct grid_cell *gc, int utf8flag, const char *fmt, ...)
{
va_list ap;
@@ -220,7 +221,7 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
}
/* Write string, similar to nputs, but with embedded formatting (#[]). */
-void printflike5
+void
screen_write_cnputs(struct screen_write_ctx *ctx,
ssize_t maxlen, struct grid_cell *gc, int utf8flag, const char *fmt, ...)
{
@@ -794,8 +795,6 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
gl = &s->grid->linedata[s->grid->hsize + s->cy];
if (wrapped)
gl->flags |= GRID_LINE_WRAPPED;
- else
- gl->flags &= ~GRID_LINE_WRAPPED;
if (s->cy == s->rlower)
grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);
@@ -989,6 +988,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
grid_cell_get(gc, &ud);
grid_cell_set(&tmp_gc, &ud);
+ tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET;
+ tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET;
tmp_gc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
tmp_gc.flags |= s->sel.cell.flags &
(GRID_FLAG_FG256|GRID_FLAG_BG256);
diff --git a/screen.c b/screen.c
index 7bfc0154..c1df95ad 100644
--- a/screen.c
+++ b/screen.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,12 +32,12 @@ 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];
+ char host[HOST_NAME_MAX+1];
s->grid = grid_create(sx, sy, hlimit);
- if (gethostname(hn, MAXHOSTNAMELEN) == 0)
- s->title = xstrdup(hn);
+ if (gethostname(host, sizeof(host)) == 0)
+ s->title = xstrdup(host);
else
s->title = xstrdup("");
@@ -216,8 +216,8 @@ screen_resize_y(struct screen *s, u_int sy)
}
/* Resize line arrays. */
- gd->linedata = xrealloc(
- gd->linedata, gd->hsize + sy, sizeof *gd->linedata);
+ gd->linedata = xreallocarray(gd->linedata, gd->hsize + sy,
+ sizeof *gd->linedata);
/* Size increasing. */
if (sy > oldy) {
@@ -270,6 +270,7 @@ screen_clear_selection(struct screen *s)
struct screen_sel *sel = &s->sel;
sel->flag = 0;
+ sel->lineflag = LINE_SEL_NONE;
}
/* Check if cell in selection. */
@@ -277,6 +278,7 @@ int
screen_check_selection(struct screen *s, u_int px, u_int py)
{
struct screen_sel *sel = &s->sel;
+ u_int xx;
if (!sel->flag)
return (0);
@@ -326,16 +328,24 @@ screen_check_selection(struct screen *s, u_int px, u_int py)
if (py < sel->sy || py > sel->ey)
return (0);
- if ((py == sel->sy && px < sel->sx)
- || (py == sel->ey && px > sel->ex))
+ if (py == sel->sy && px < sel->sx)
+ return (0);
+
+ if (py == sel->ey && px > sel->ex)
return (0);
} else if (sel->sy > sel->ey) {
/* starting line > ending line -- upward selection. */
if (py > sel->sy || py < sel->ey)
return (0);
- if ((py == sel->sy && px >= sel->sx)
- || (py == sel->ey && px < sel->ex))
+ if (py == sel->ey && px < sel->ex)
+ return (0);
+
+ if (sel->modekeys == MODEKEY_EMACS)
+ xx = sel->sx - 1;
+ else
+ xx = sel->sx;
+ if (py == sel->sy && px > xx)
return (0);
} else {
/* starting line == ending line. */
@@ -344,7 +354,11 @@ screen_check_selection(struct screen *s, u_int px, u_int py)
if (sel->ex < sel->sx) {
/* cursor (ex) is on the left */
- if (px > sel->sx || px < sel->ex)
+ if (sel->modekeys == MODEKEY_EMACS)
+ xx = sel->sx - 1;
+ else
+ xx = sel->sx;
+ if (px > xx || px < sel->ex)
return (0);
} else {
/* selection start (sx) is on the left */
diff --git a/server-client.c b/server-client.c
index 07ef5697..3ca99077 100644
--- a/server-client.c
+++ b/server-client.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -113,21 +113,22 @@ server_client_create(int fd)
/* Open client terminal if needed. */
int
-server_client_open(struct client *c, struct session *s, char **cause)
+server_client_open(struct client *c, char **cause)
{
- struct options *oo = s != NULL ? &s->options : &global_s_options;
- char *overrides;
-
if (c->flags & CLIENT_CONTROL)
return (0);
+ if (strcmp(c->ttyname, "/dev/tty") == 0) {
+ *cause = xstrdup("can't use /dev/tty");
+ return (-1);
+ }
+
if (!(c->flags & CLIENT_TERMINAL)) {
*cause = xstrdup("not a terminal");
return (-1);
}
- overrides = options_get_string(oo, "terminal-overrides");
- if (tty_open(&c->tty, overrides, cause) != 0)
+ if (tty_open(&c->tty, cause) != 0)
return (-1);
return (0);
@@ -158,7 +159,7 @@ server_client_lost(struct client *c)
evbuffer_free(c->stdin_data);
evbuffer_free(c->stdout_data);
if (c->stderr_data != c->stdout_data)
- evbuffer_free (c->stderr_data);
+ evbuffer_free(c->stderr_data);
status_free_jobs(&c->status_new);
status_free_jobs(&c->status_old);
@@ -222,7 +223,7 @@ server_client_callback(int fd, short events, void *data)
return;
if (fd == c->ibuf.fd) {
- if (events & EV_WRITE && msgbuf_write(&c->ibuf.w) < 0 &&
+ if (events & EV_WRITE && msgbuf_write(&c->ibuf.w) <= 0 &&
errno != EAGAIN)
goto client_lost;
@@ -327,6 +328,7 @@ server_client_check_mouse(struct client *c, struct window_pane *wp)
if (options_get_number(oo, "mouse-select-pane") &&
(m->event == MOUSE_EVENT_DOWN || m->event == MOUSE_EVENT_WHEEL)) {
window_set_active_at(wp->window, m->x, m->y);
+ server_status_window(wp->window);
server_redraw_window_borders(wp->window);
wp = wp->window->active; /* may have changed */
}
@@ -540,8 +542,18 @@ server_client_check_resize(struct window_pane *wp)
ws.ws_col = wp->sx;
ws.ws_row = wp->sy;
- if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1)
+ if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) {
+#ifdef __sun
+ /*
+ * Some versions of Solaris apparently can return an error when
+ * resizing; don't know why this happens, can't reproduce on
+ * other platforms and ignoring it doesn't seem to cause any
+ * issues.
+ */
+ if (errno != EINVAL && errno != ENXIO)
+#endif
fatal("ioctl failed");
+ }
wp->flags &= ~PANE_RESIZE;
}
@@ -635,7 +647,7 @@ server_client_reset_state(struct client *c)
if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - status)
tty_cursor(&c->tty, 0, 0);
else {
- o = status && options_get_number (oo, "status-position") == 0;
+ o = status && options_get_number(oo, "status-position") == 0;
tty_cursor(&c->tty, wp->xoff + s->cx, o + wp->yoff + s->cy);
}
@@ -645,7 +657,7 @@ server_client_reset_state(struct client *c)
*/
mode = s->mode;
if ((c->tty.mouse.flags & MOUSE_RESIZE_PANE) &&
- !(mode & (MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)))
+ !(mode & MODE_MOUSE_BUTTON))
mode |= MODE_MOUSE_BUTTON;
/*
@@ -770,19 +782,25 @@ server_client_check_redraw(struct client *c)
void
server_client_set_title(struct client *c)
{
- struct session *s = c->session;
- const char *template;
- char *title;
+ struct session *s = c->session;
+ const char *template;
+ char *title;
+ struct format_tree *ft;
template = options_get_string(&s->options, "set-titles-string");
- title = status_replace(c, NULL, NULL, NULL, template, time(NULL), 1);
+ ft = format_create();
+ format_defaults(ft, c, NULL, NULL, NULL);
+
+ title = format_expand_time(ft, template, time(NULL));
if (c->title == NULL || strcmp(title, c->title) != 0) {
free(c->title);
c->title = xstrdup(title);
tty_set_title(&c->tty, c->title);
}
free(title);
+
+ format_free(ft);
}
/* Dispatch message from client. */
@@ -873,6 +891,9 @@ server_client_msg_dispatch(struct client *c)
break;
c->flags &= ~CLIENT_SUSPENDED;
+ if (c->tty.fd == -1) /* exited in the meantime */
+ break;
+
if (gettimeofday(&c->activity_time, NULL) != 0)
fatal("gettimeofday");
if (c->session != NULL)
@@ -909,7 +930,7 @@ server_client_msg_command(struct client *c, struct imsg *imsg)
fatalx("bad MSG_COMMAND size");
memcpy(&data, imsg->data, sizeof data);
- buf = (char*)imsg->data + sizeof data;
+ buf = (char *)imsg->data + sizeof data;
len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data;
if (len > 0 && buf[len - 1] != '\0')
fatalx("bad MSG_COMMAND string");
diff --git a/server-fn.c b/server-fn.c
index a00cadbd..1ed3a01f 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,7 +31,7 @@ void server_callback_identify(int, short, void *);
void
server_fill_environ(struct session *s, struct environ *env)
{
- char var[MAXPATHLEN], *term;
+ char var[PATH_MAX], *term;
u_int idx;
long pid;
@@ -270,6 +270,7 @@ server_kill_window(struct window *w)
if (session_has(s, w) == NULL)
continue;
+ server_unzoom_window(w);
while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) {
if (session_detach(s, wl)) {
server_destroy_session_group(s);
@@ -291,7 +292,8 @@ server_kill_window(struct window *w)
int
server_link_window(struct session *src, struct winlink *srcwl,
- struct session *dst, int dstidx, int killflag, int selectflag, char **cause)
+ struct session *dst, int dstidx, int killflag, int selectflag,
+ char **cause)
{
struct winlink *dstwl;
struct session_group *srcsg, *dstsg;
@@ -361,6 +363,9 @@ server_destroy_pane(struct window_pane *wp)
old_fd = wp->fd;
if (wp->fd != -1) {
+#ifdef HAVE_UTEMPTER
+ utempter_remove_record(wp->fd);
+#endif
bufferevent_free(wp->event);
close(wp->fd);
wp->fd = -1;
diff --git a/server-window.c b/server-window.c
index 687d4239..a14c3150 100644
--- a/server-window.c
+++ b/server-window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,19 +27,16 @@
int server_window_check_bell(struct session *, struct winlink *);
int server_window_check_activity(struct session *, struct winlink *);
int server_window_check_silence(struct session *, struct winlink *);
-int server_window_check_content(
- struct session *, struct winlink *, struct window_pane *);
void ring_bell(struct session *);
/* Window functions that need to happen every loop. */
void
server_window_loop(void)
{
- struct window *w;
- struct winlink *wl;
- struct window_pane *wp;
- struct session *s;
- u_int i;
+ struct window *w;
+ struct winlink *wl;
+ struct session *s;
+ u_int i;
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
w = ARRAY_ITEM(&windows, i);
@@ -55,8 +52,6 @@ server_window_loop(void)
server_window_check_activity(s, wl) ||
server_window_check_silence(s, wl))
server_status_session(s);
- TAILQ_FOREACH(wp, &w->panes, entry)
- server_window_check_content(s, wl, wp);
}
}
}
@@ -85,10 +80,11 @@ server_window_check_bell(struct session *s, struct winlink *wl)
return (0);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
- if (c == NULL || c->session != s || (c->flags & CLIENT_CONTROL))
+ if (c == NULL || c->session != s || c->flags & CLIENT_CONTROL)
continue;
if (!visual) {
- tty_bell(&c->tty);
+ if (c->session->curw->window == w || action == BELL_ANY)
+ tty_bell(&c->tty);
continue;
}
if (c->session->curw->window == w)
@@ -186,48 +182,6 @@ server_window_check_silence(struct session *s, struct winlink *wl)
return (1);
}
-/* Check for content change in window. */
-int
-server_window_check_content(
- struct session *s, struct winlink *wl, struct window_pane *wp)
-{
- struct client *c;
- struct window *w = wl->window;
- u_int i;
- char *found, *ptr;
-
- /* Activity flag must be set for new content. */
- if (s->curw->window == w)
- w->flags &= ~WINDOW_ACTIVITY;
-
- if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_CONTENT)
- return (0);
- if (s->curw == wl && !(s->flags & SESSION_UNATTACHED))
- return (0);
-
- ptr = options_get_string(&w->options, "monitor-content");
- if (ptr == NULL || *ptr == '\0')
- return (0);
- if ((found = window_pane_search(wp, ptr, NULL)) == NULL)
- return (0);
- free(found);
-
- if (options_get_number(&s->options, "bell-on-alert"))
- ring_bell(s);
- 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);
- if (c == NULL || c->session != s)
- continue;
- status_message_set(c, "Content in window %u", wl->idx);
- }
- }
-
- return (1);
-}
-
/* Ring terminal bell. */
void
ring_bell(struct session *s)
diff --git a/server.c b/server.c
index f372de4f..9b11e019 100644
--- a/server.c
+++ b/server.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -50,8 +50,6 @@ int server_shutdown;
struct event server_ev_accept;
struct event server_ev_second;
-struct paste_stack global_buffers;
-
int server_create_socket(void);
void server_loop(void);
int server_should_shutdown(void);
@@ -112,6 +110,7 @@ server_start(int lockfd, char *lockfile)
/* The first client is special and gets a socketpair; create it. */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
fatal("socketpair failed");
+ log_debug("starting server");
switch (fork()) {
case -1:
@@ -146,7 +145,6 @@ server_start(int lockfd, char *lockfile)
RB_INIT(&sessions);
RB_INIT(&dead_sessions);
TAILQ_INIT(&session_groups);
- ARRAY_INIT(&global_buffers);
mode_key_init_trees();
key_bindings_init();
utf8_build();
@@ -168,25 +166,18 @@ server_start(int lockfd, char *lockfile)
cfg_cmd_q->emptyfn = cfg_default_done;
cfg_finished = 0;
cfg_references = 1;
- ARRAY_INIT(&cfg_causes);
cfg_client = ARRAY_FIRST(&clients);
if (cfg_client != NULL)
cfg_client->references++;
if (access(TMUX_CONF, R_OK) == 0) {
- if (load_cfg(TMUX_CONF, cfg_cmd_q, &cause) == -1) {
- xasprintf(&cause, "%s: %s", TMUX_CONF, cause);
- ARRAY_ADD(&cfg_causes, cause);
- }
- } else if (errno != ENOENT) {
- xasprintf(&cause, "%s: %s", TMUX_CONF, strerror(errno));
- ARRAY_ADD(&cfg_causes, cause);
- }
+ if (load_cfg(TMUX_CONF, cfg_cmd_q, &cause) == -1)
+ cfg_add_cause("%s: %s", TMUX_CONF, cause);
+ } else if (errno != ENOENT)
+ cfg_add_cause("%s: %s", TMUX_CONF, strerror(errno));
if (cfg_file != NULL) {
- if (load_cfg(cfg_file, cfg_cmd_q, &cause) == -1) {
- xasprintf(&cause, "%s: %s", cfg_file, cause);
- ARRAY_ADD(&cfg_causes, cause);
- }
+ if (load_cfg(cfg_file, cfg_cmd_q, &cause) == -1)
+ cfg_add_cause("%s: %s", cfg_file, cause);
}
cmdq_continue(cfg_cmd_q);
@@ -212,25 +203,38 @@ server_loop(void)
server_window_loop();
server_client_loop();
- key_bindings_clean();
server_clean_dead();
}
}
-/* Check if the server should be shutting down (no more clients or sessions). */
+/* Check if the server should exit (no more clients or sessions). */
int
server_should_shutdown(void)
{
- u_int i;
+ struct client *c;
+ u_int i;
if (!options_get_number(&global_options, "exit-unattached")) {
if (!RB_EMPTY(&sessions))
return (0);
}
+
+ for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
+ c = ARRAY_ITEM(&clients, i);
+ if (c != NULL && c->session != NULL)
+ return (0);
+ }
+
+ /*
+ * No attached clients therefore want to exit - flush any waiting
+ * clients but don't actually exit until they've gone.
+ */
+ cmd_wait_for_flush();
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
if (ARRAY_ITEM(&clients, i) != NULL)
return (0);
}
+
return (1);
}
@@ -242,6 +246,8 @@ server_send_shutdown(void)
struct session *s, *next_s;
u_int i;
+ cmd_wait_for_flush();
+
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL) {
@@ -436,6 +442,7 @@ server_child_exited(pid_t pid, int status)
continue;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->pid == pid) {
+ wp->status = status;
server_destroy_pane(wp);
break;
}
diff --git a/session.c b/session.c
index 07307710..3ac9fb2b 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -84,10 +84,12 @@ session_find_by_id(u_int id)
/* Create a new session. */
struct session *
-session_create(const char *name, const char *cmd, int cwd, struct environ *env,
- struct termios *tio, int idx, u_int sx, u_int sy, char **cause)
+session_create(const char *name, int argc, char **argv, const char *path,
+ int cwd, struct environ *env, struct termios *tio, int idx, u_int sx,
+ u_int sy, char **cause)
{
struct session *s;
+ struct winlink *wl;
s = xmalloc(sizeof *s);
s->references = 0;
@@ -124,14 +126,15 @@ session_create(const char *name, const char *cmd, int cwd, struct environ *env,
s->name = NULL;
do {
s->id = next_session_id++;
- free (s->name);
+ free(s->name);
xasprintf(&s->name, "%u", s->id);
} while (RB_FIND(sessions, &sessions, s) != NULL);
}
RB_INSERT(sessions, &sessions, s);
- if (cmd != NULL) {
- if (session_new(s, NULL, cmd, cwd, idx, cause) == NULL) {
+ if (argc >= 0) {
+ wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause);
+ if (wl == NULL) {
session_destroy(s);
return (NULL);
}
@@ -225,8 +228,8 @@ session_previous_session(struct session *s)
/* Create a new window on a session. */
struct winlink *
-session_new(struct session *s, const char *name, const char *cmd, int cwd,
- int idx, char **cause)
+session_new(struct session *s, const char *name, int argc, char **argv,
+ const char *path, int cwd, int idx, char **cause)
{
struct window *w;
struct winlink *wl;
@@ -249,8 +252,8 @@ session_new(struct session *s, const char *name, const char *cmd, int cwd,
shell = _PATH_BSHELL;
hlimit = options_get_number(&s->options, "history-limit");
- w = window_create(name, cmd, shell, cwd, &env, s->tio, s->sx, s->sy,
- hlimit, cause);
+ w = window_create(name, argc, argv, path, shell, cwd, &env, s->tio,
+ s->sx, s->sy, hlimit, cause);
if (w == NULL) {
winlink_remove(&s->windows, wl);
environ_free(&env);
@@ -488,6 +491,19 @@ session_group_remove(struct session *s)
}
}
+/* Count number of sessions in session group. */
+u_int
+session_group_count(struct session_group *sg)
+{
+ struct session *s;
+ u_int n;
+
+ n = 0;
+ TAILQ_FOREACH(s, &sg->sessions, gentry)
+ n++;
+ return (n);
+}
+
/* Synchronize a session to its session group. */
void
session_group_synchronize_to(struct session *s)
@@ -575,8 +591,9 @@ session_group_synchronize1(struct session *target, struct session *s)
/* Then free the old winlinks list. */
while (!RB_EMPTY(&old_windows)) {
wl = RB_ROOT(&old_windows);
- if (winlink_find_by_window_id(&s->windows, wl->window->id) == NULL)
- notify_window_unlinked(s, wl->window);
+ wl2 = winlink_find_by_window_id(&s->windows, wl->window->id);
+ if (wl2 == NULL)
+ notify_window_unlinked(s, wl->window);
winlink_remove(&old_windows, wl);
}
}
diff --git a/signal.c b/signal.c
index 56333522..7e6268a7 100644
--- a/signal.c
+++ b/signal.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -17,6 +17,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/types.h>
+
#include <string.h>
#include <signal.h>
diff --git a/status.c b/status.c
index 9967dc68..e7714a00 100644
--- a/status.c
+++ b/status.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,16 +29,17 @@
#include "tmux.h"
-char *status_redraw_get_left(
- struct client *, time_t, int, struct grid_cell *, size_t *);
-char *status_redraw_get_right(
- struct client *, time_t, int, struct grid_cell *, size_t *);
+char *status_redraw_get_left(struct client *, time_t, int, struct grid_cell *,
+ size_t *);
+char *status_redraw_get_right(struct client *, time_t, int,
+ struct grid_cell *, size_t *);
char *status_find_job(struct client *, char **);
void status_job_free(void *);
void status_job_callback(struct job *);
-char *status_print(
- struct client *, struct winlink *, time_t, struct grid_cell *);
-void status_replace1(struct client *, char **, char **, char *, size_t, int);
+char *status_print(struct client *, struct winlink *, time_t,
+ struct grid_cell *);
+char *status_replace(struct client *, struct winlink *, const char *, time_t);
+void status_replace1(struct client *, char **, char **, char *, size_t);
void status_message_callback(int, short, void *);
const char *status_prompt_up_history(u_int *);
@@ -75,17 +76,18 @@ status_at_line(struct client *c)
/* Retrieve options for left string. */
char *
-status_redraw_get_left(struct client *c,
- time_t t, int utf8flag, struct grid_cell *gc, size_t *size)
+status_redraw_get_left(struct client *c, time_t t, int utf8flag,
+ struct grid_cell *gc, size_t *size)
{
struct session *s = c->session;
+ const char *template;
char *left;
size_t leftlen;
style_apply_update(gc, &s->options, "status-left-style");
- left = status_replace(c, NULL,
- NULL, NULL, options_get_string(&s->options, "status-left"), t, 1);
+ template = options_get_string(&s->options, "status-left");
+ left = status_replace(c, NULL, template, t);
*size = options_get_number(&s->options, "status-left-length");
leftlen = screen_write_cstrlen(utf8flag, "%s", left);
@@ -96,17 +98,18 @@ status_redraw_get_left(struct client *c,
/* Retrieve options for right string. */
char *
-status_redraw_get_right(struct client *c,
- time_t t, int utf8flag, struct grid_cell *gc, size_t *size)
+status_redraw_get_right(struct client *c, time_t t, int utf8flag,
+ struct grid_cell *gc, size_t *size)
{
struct session *s = c->session;
+ const char *template;
char *right;
size_t rightlen;
style_apply_update(gc, &s->options, "status-right-style");
- right = status_replace(c, NULL,
- NULL, NULL, options_get_string(&s->options, "status-right"), t, 1);
+ template = options_get_string(&s->options, "status-right");
+ right = status_replace(c, NULL, template, t);
*size = options_get_number(&s->options, "status-right-length");
rightlen = screen_write_cstrlen(utf8flag, "%s", right);
@@ -121,12 +124,17 @@ status_set_window_at(struct client *c, u_int x)
{
struct session *s = c->session;
struct winlink *wl;
+ struct options *oo;
+ size_t len;
x += c->wlmouse;
RB_FOREACH(wl, winlinks, &s->windows) {
+ oo = &wl->window->options;
+
+ len = strlen(options_get_string(oo, "window-status-separator"));
if (x < wl->status_width && session_select(s, wl->idx) == 0)
server_redraw_session(s);
- x -= wl->status_width + 1;
+ x -= wl->status_width + len;
}
}
@@ -188,9 +196,9 @@ status_redraw(struct client *c)
*/
needed = 0;
if (llen != 0)
- needed += llen + 1;
+ needed += llen;
if (rlen != 0)
- needed += rlen + 1;
+ needed += rlen;
if (c->tty.sx == 0 || c->tty.sx <= needed)
goto out;
wlavailable = c->tty.sx - needed;
@@ -295,10 +303,8 @@ draw:
/* Draw the left string and arrow. */
screen_write_cursormove(&ctx, 0, 0);
- if (llen != 0) {
+ if (llen != 0)
screen_write_cnputs(&ctx, llen, &lgc, utf8flag, "%s", left);
- screen_write_putc(&ctx, &stdgc, ' ');
- }
if (larrow != 0) {
memcpy(&gc, &stdgc, sizeof gc);
if (larrow == -1)
@@ -308,26 +314,24 @@ draw:
/* Draw the right string and arrow. */
if (rarrow != 0) {
- screen_write_cursormove(&ctx, c->tty.sx - rlen - 2, 0);
+ screen_write_cursormove(&ctx, c->tty.sx - rlen - 1, 0);
memcpy(&gc, &stdgc, sizeof gc);
if (rarrow == -1)
gc.attr ^= GRID_ATTR_REVERSE;
screen_write_putc(&ctx, &gc, '>');
} else
- screen_write_cursormove(&ctx, c->tty.sx - rlen - 1, 0);
- if (rlen != 0) {
- screen_write_putc(&ctx, &stdgc, ' ');
+ screen_write_cursormove(&ctx, c->tty.sx - rlen, 0);
+ if (rlen != 0)
screen_write_cnputs(&ctx, rlen, &rgc, utf8flag, "%s", right);
- }
/* Figure out the offset for the window list. */
if (llen != 0)
- wloffset = llen + 1;
+ wloffset = llen;
else
wloffset = 0;
if (wlwidth < wlavailable) {
switch (options_get_number(&s->options, "status-justify")) {
- case 1: /* centered */
+ case 1: /* centred */
wloffset += (wlavailable - wlwidth) / 2;
break;
case 2: /* right */
@@ -361,7 +365,7 @@ out:
/* Replace a single special sequence (prefixed by #). */
void
status_replace1(struct client *c, char **iptr, char **optr, char *out,
- size_t outsize, int jobsflag)
+ size_t outsize)
{
char ch, tmp[256], *ptr, *endptr;
size_t ptrlen;
@@ -379,10 +383,6 @@ status_replace1(struct client *c, char **iptr, char **optr, char *out,
switch (*(*iptr)++) {
case '(':
- if (!jobsflag) {
- ch = ')';
- goto skip_to;
- }
if ((ptr = status_find_job(c, iptr)) == NULL)
return;
goto do_replace;
@@ -396,9 +396,6 @@ status_replace1(struct client *c, char **iptr, char **optr, char *out,
case '{':
ptr = (char *) "#{";
goto do_replace;
- case '#':
- *(*optr)++ = '#';
- break;
default:
xsnprintf(tmp, sizeof tmp, "#%c", *(*iptr - 1));
ptr = tmp;
@@ -434,8 +431,7 @@ skip_to:
/* Replace special sequences in fmt. */
char *
-status_replace(struct client *c, struct session *s, struct winlink *wl,
- struct window_pane *wp, const char *fmt, time_t t, int jobsflag)
+status_replace(struct client *c, struct winlink *wl, const char *fmt, time_t t)
{
static char out[BUFSIZ];
char in[BUFSIZ], ch, *iptr, *optr, *expanded;
@@ -445,13 +441,6 @@ status_replace(struct client *c, struct session *s, struct winlink *wl,
if (fmt == NULL)
return (xstrdup(""));
- if (s == NULL && c != NULL)
- s = c->session;
- if (wl == NULL && s != NULL)
- wl = s->curw;
- if (wp == NULL && wl != NULL)
- wp = wl->window->active;
-
len = strftime(in, sizeof in, fmt, localtime(&t));
in[len] = '\0';
@@ -467,19 +456,12 @@ status_replace(struct client *c, struct session *s, struct winlink *wl,
*optr++ = ch;
continue;
}
- status_replace1(c, &iptr, &optr, out, sizeof out, jobsflag);
+ status_replace1(c, &iptr, &optr, out, sizeof out);
}
*optr = '\0';
ft = format_create();
- if (c != NULL)
- format_client(ft, c);
- if (s != NULL)
- format_session(ft, s);
- if (s != NULL && wl != NULL)
- format_winlink(ft, s, wl);
- if (wp != NULL)
- format_window_pane(ft, wp);
+ format_defaults(ft, c, NULL, wl, NULL);
expanded = format_expand(ft, out);
format_free(ft);
return (expanded);
@@ -622,8 +604,8 @@ status_job_callback(struct job *job)
/* Return winlink status line entry and adjust gc as necessary. */
char *
-status_print(
- struct client *c, struct winlink *wl, time_t t, struct grid_cell *gc)
+status_print(struct client *c, struct winlink *wl, time_t t,
+ struct grid_cell *gc)
{
struct options *oo = &wl->window->options;
struct session *s = c->session;
@@ -641,21 +623,18 @@ status_print(
if (wl->flags & WINLINK_BELL)
style_apply_update(gc, oo, "window-status-bell-style");
- else if (wl->flags & WINLINK_CONTENT)
- style_apply_update(gc, oo, "window-status-content-style");
else if (wl->flags & (WINLINK_ACTIVITY|WINLINK_SILENCE))
style_apply_update(gc, oo, "window-status-activity-style");
- text = status_replace(c, NULL, wl, NULL, fmt, t, 1);
+ text = status_replace(c, wl, fmt, t);
return (text);
}
/* Set a status line message. */
-void printflike2
+void
status_message_set(struct client *c, const char *fmt, ...)
{
struct timeval tv;
- struct session *s = c->session;
struct message_entry *msg;
va_list ap;
int delay;
@@ -673,10 +652,7 @@ status_message_set(struct client *c, const char *fmt, ...)
msg->msg_time = time(NULL);
msg->msg = xstrdup(c->message_string);
- if (s == NULL)
- limit = 0;
- else
- limit = options_get_number(&s->options, "message-limit");
+ limit = options_get_number(&global_options, "message-limit");
if (ARRAY_LENGTH(&c->message_log) > limit) {
limit = ARRAY_LENGTH(&c->message_log) - limit;
for (i = 0; i < limit; i++) {
@@ -771,16 +747,20 @@ status_prompt_set(struct client *c, const char *msg, const char *input,
int (*callbackfn)(void *, const char *), void (*freefn)(void *),
void *data, int flags)
{
- int keys;
+ struct format_tree *ft;
+ int keys;
+ time_t t;
+
+ ft = format_create();
+ format_defaults(ft, c, NULL, NULL, NULL);
+ t = time(NULL);
status_message_clear(c);
status_prompt_clear(c);
- c->prompt_string = status_replace(c, NULL, NULL, NULL, msg,
- time(NULL), 0);
+ c->prompt_string = format_expand_time(ft, msg, time(NULL));
- c->prompt_buffer = status_replace(c, NULL, NULL, NULL, input,
- time(NULL), 0);
+ c->prompt_buffer = format_expand_time(ft, input, time(NULL));
c->prompt_index = strlen(c->prompt_buffer);
c->prompt_callbackfn = callbackfn;
@@ -799,6 +779,8 @@ status_prompt_set(struct client *c, const char *msg, const char *input,
c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
c->flags |= CLIENT_STATUS;
+
+ format_free(ft);
}
/* Remove status line prompt. */
@@ -827,18 +809,25 @@ status_prompt_clear(struct client *c)
void
status_prompt_update(struct client *c, const char *msg, const char *input)
{
+ struct format_tree *ft;
+ time_t t;
+
+ ft = format_create();
+ format_defaults(ft, c, NULL, NULL, NULL);
+ t = time(NULL);
+
free(c->prompt_string);
- c->prompt_string = status_replace(c, NULL, NULL, NULL, msg,
- time(NULL), 0);
+ c->prompt_string = format_expand_time(ft, msg, time(NULL));
free(c->prompt_buffer);
- c->prompt_buffer = status_replace(c, NULL, NULL, NULL, input,
- time(NULL), 0);
+ c->prompt_buffer = format_expand_time(ft, input, time(NULL));
c->prompt_index = strlen(c->prompt_buffer);
c->prompt_hindex = 0;
c->flags |= CLIENT_STATUS;
+
+ format_free(ft);
}
/* Draw client prompt on status line of present else on last line. */
@@ -996,7 +985,7 @@ status_prompt_key(struct client *c, int key)
/* Insert the new word. */
size += strlen(s);
off = first - c->prompt_buffer;
- c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + 1);
+ c->prompt_buffer = xrealloc(c->prompt_buffer, size + 1);
first = c->prompt_buffer + off;
memmove(first + strlen(s), first, n);
memcpy(first, s, strlen(s));
@@ -1166,7 +1155,7 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS;
break;
case MODEKEYEDIT_PASTE:
- if ((pb = paste_get_top(&global_buffers)) == NULL)
+ if ((pb = paste_get_top()) == NULL)
break;
for (n = 0; n < pb->size; n++) {
ch = (u_char) pb->data[n];
@@ -1174,7 +1163,7 @@ status_prompt_key(struct client *c, int key)
break;
}
- c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + n + 1);
+ c->prompt_buffer = xrealloc(c->prompt_buffer, size + n + 1);
if (c->prompt_index == size) {
memcpy(c->prompt_buffer + c->prompt_index, pb->data, n);
c->prompt_index += n;
@@ -1214,7 +1203,7 @@ status_prompt_key(struct client *c, int key)
case MODEKEY_OTHER:
if ((key & 0xff00) != 0 || key < 32 || key == 127)
break;
- c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + 2);
+ c->prompt_buffer = xrealloc(c->prompt_buffer, size + 2);
if (c->prompt_index == size) {
c->prompt_buffer[c->prompt_index++] = key;
diff --git a/style.c b/style.c
index 97d5576e..6df2ed04 100644
--- a/style.c
+++ b/style.c
@@ -17,6 +17,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/types.h>
+
#include <string.h>
#include "tmux.h"
@@ -117,7 +119,7 @@ style_tostring(struct grid_cell *gc)
*s = '\0';
- if (gc->fg != 8) {
+ if (gc->fg != 8 || gc->flags & GRID_FLAG_FG256) {
if (gc->flags & GRID_FLAG_FG256)
c = gc->fg | 0x100;
else
@@ -126,7 +128,7 @@ style_tostring(struct grid_cell *gc)
comma = 1;
}
- if (gc->bg != 8) {
+ if (gc->bg != 8 || gc->flags & GRID_FLAG_BG256) {
if (gc->flags & GRID_FLAG_BG256)
c = gc->bg | 0x100;
else
@@ -203,8 +205,14 @@ style_apply(struct grid_cell *gc, struct options *oo, const char *name)
memcpy(gc, &grid_default_cell, sizeof *gc);
gcp = options_get_style(oo, name);
- colour_set_fg(gc, gcp->fg);
- colour_set_bg(gc, gcp->bg);
+ if (gcp->flags & GRID_FLAG_FG256)
+ colour_set_fg(gc, gcp->fg | 0x100);
+ else
+ colour_set_fg(gc, gcp->fg);
+ if (gcp->flags & GRID_FLAG_BG256)
+ colour_set_bg(gc, gcp->bg | 0x100);
+ else
+ colour_set_bg(gc, gcp->bg);
gc->attr |= gcp->attr;
}
@@ -215,10 +223,18 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
struct grid_cell *gcp;
gcp = options_get_style(oo, name);
- if (gcp->fg != 8)
- colour_set_fg(gc, gcp->fg);
- if (gcp->bg != 8)
- colour_set_bg(gc, gcp->bg);
+ if (gcp->fg != 8 || gcp->flags & GRID_FLAG_FG256) {
+ if (gcp->flags & GRID_FLAG_FG256)
+ colour_set_fg(gc, gcp->fg | 0x100);
+ else
+ colour_set_fg(gc, gcp->fg);
+ }
+ if (gcp->bg != 8 || gcp->flags & GRID_FLAG_BG256) {
+ if (gcp->flags & GRID_FLAG_BG256)
+ colour_set_bg(gc, gcp->bg | 0x100);
+ else
+ colour_set_bg(gc, gcp->bg);
+ }
if (gcp->attr != 0)
gc->attr |= gcp->attr;
}
diff --git a/tmux.1 b/tmux.1
index aa3e11ce..f615dd0f 100644
--- a/tmux.1
+++ b/tmux.1
@@ -61,7 +61,7 @@ A window occupies the entire screen
and may be split into rectangular panes,
each of which is a separate pseudo terminal
(the
-.Xr pty 4
+.Xr pty 7
manual page documents the technical details of pseudo terminals).
Any number of
.Nm
@@ -168,10 +168,6 @@ server process to recreate it.
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
-server option to prevent the server sending various informational messages.
.It Fl S Ar socket-path
Specify a full alternative path to the server socket.
If
@@ -255,6 +251,10 @@ Split the current pane into two, left and right.
Kill the current window.
.It '
Prompt for a window index to select.
+.It \&(
+Switch the attached client to the previous session.
+.It \&)
+Switch the attached client to the next session.
.It ,
Rename the current window.
.It -
@@ -275,6 +275,8 @@ Choose which buffer to paste interactively from a list.
List all key bindings.
.It D
Choose a client to detach.
+.It L
+Switch the attached client back to the last session.
.It \&[
Enter copy mode to copy text or view the history.
.It \&]
@@ -301,14 +303,14 @@ Briefly display pane indexes.
Force redraw of the attached client.
.It s
Select a new session for the attached client interactively.
-.It L
-Switch the attached client back to the last session.
.It t
Show the time.
.It w
Choose the current window interactively.
.It x
Kill the current pane.
+.It z
+Toggle zoom state of the current pane.
.It {
Swap the current pane with the previous pane.
.It }
@@ -326,6 +328,8 @@ 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 Space
+Arrange the current window in the next preset layout.
.It M-n
Move to the next window with a bell or activity marker.
.It M-o
@@ -359,7 +363,7 @@ or
These specify the client, session, window or pane which a command should affect.
.Ar target-client
is the name of the
-.Xr pty 4
+.Xr pty 7
file to which the client is connected, for example either of
.Pa /dev/ttyp1
or
@@ -443,10 +447,11 @@ 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 + ,
.Ql -
-indicate the next or previous pane index, respectively.
+or
+.Ql \&!
+indicate the next, previous or last pane.
One of the strings
.Em top ,
.Em bottom ,
@@ -486,12 +491,37 @@ It may be used alone to target a pane or the window containing it.
arguments are
.Xr sh 1
commands.
-These must be passed as a single item, which typically means quoting them, for
-example:
+This may be a single argument passed to the shell, for example:
.Bd -literal -offset indent
new-window 'vi /etc/passwd'
.Ed
.Pp
+Will run:
+.Bd -literal -offset indent
+/bin/sh -c 'vi /etc/passwd'
+.Ed
+.Pp
+Additionally, the
+.Ic new-window ,
+.Ic new-session ,
+.Ic split-window ,
+.Ic respawn-window
+and
+.Ic respawn-pane
+commands allow
+.Ar shell-command
+to be given as multiple arguments and executed directly (without
+.Ql sh -c ) .
+This can avoid issues with shell quoting.
+For example:
+.Bd -literal -offset indent
+$ tmux new-window vi /etc/passwd
+.Ed
+.Pp
+Will run
+.Xr vi 1
+directly without invoking the shell.
+.Pp
.Ar command
.Op Ar arguments
refers to a
@@ -710,7 +740,7 @@ and
specify the size of the initial window (80 by 24 if not given).
.Pp
If run from a terminal, any
-.Xr termios 4
+.Xr termios 3
special characters are saved and used for new windows in the new session.
.Pp
The
@@ -782,7 +812,7 @@ Show client messages or server information.
Any messages displayed on the status line are saved in a per-client message
log, up to a maximum of the limit set by the
.Ar message-limit
-session option for the session attached to that client.
+server option.
With
.Fl t ,
display the log for
@@ -855,10 +885,12 @@ option).
The following keys are supported as appropriate for the mode:
.Bl -column "FunctionXXXXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent
.It Sy "Function" Ta Sy "vi" Ta Sy "emacs"
+.It Li "Append selection" Ta "A" Ta ""
.It Li "Back to indentation" Ta "^" Ta "M-m"
.It Li "Bottom of history" Ta "G" Ta "M-<"
.It Li "Clear selection" Ta "Escape" Ta "C-g"
.It Li "Copy selection" Ta "Enter" Ta "M-w"
+.It Li "Copy to named buffer" Ta \&" Ta ""
.It Li "Cursor down" Ta "j" Ta "Down"
.It Li "Cursor left" Ta "h" Ta "Left"
.It Li "Cursor right" Ta "l" Ta "Right"
@@ -872,12 +904,12 @@ 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 to forward" Ta "t" Ta ""
-.It Li "Jump backward" Ta "F" Ta "F"
-.It Li "Jump to backward" Ta "T" Ta ""
.It Li "Jump again" Ta ";" Ta ";"
.It Li "Jump again in reverse" Ta "," Ta ","
+.It Li "Jump backward" Ta "F" Ta "F"
+.It Li "Jump forward" Ta "f" Ta "f"
+.It Li "Jump to backward" Ta "T" Ta ""
+.It Li "Jump to forward" Ta "t" 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 ""
@@ -886,8 +918,8 @@ The following keys are supported as appropriate for the mode:
.It Li "Other end of selection" Ta "o" Ta ""
.It Li "Paste buffer" Ta "p" Ta "C-y"
.It Li "Previous page" Ta "C-b" Ta "Page up"
-.It Li "Previous word" Ta "b" Ta "M-b"
.It Li "Previous space" Ta "B" Ta ""
+.It Li "Previous word" Ta "b" Ta "M-b"
.It Li "Quit mode" Ta "q" Ta "Escape"
.It Li "Rectangle toggle" Ta "v" Ta "R"
.It Li "Scroll down" Ta "C-Down or C-e" Ta "C-Down"
@@ -896,6 +928,7 @@ The following keys are supported as appropriate for the mode:
.It Li "Search again in reverse" Ta "N" Ta "N"
.It Li "Search backward" Ta "?" Ta "C-r"
.It Li "Search forward" Ta "/" Ta "C-s"
+.It Li "Select line" Ta "V" Ta ""
.It Li "Start of line" Ta "0" Ta "C-a"
.It Li "Start selection" Ta "Space" Ta "C-Space"
.It Li "Top of history" Ta "g" Ta "M->"
@@ -937,9 +970,6 @@ in emacs mode, and
.Ql 10w
in vi.
.Pp
-When copying the selection, the repeat count indicates the buffer index to
-replace, if used.
-.Pp
Mode key bindings are defined in a set of named tables:
.Em vi-edit
and
@@ -1097,7 +1127,7 @@ but a different format may be specified with
.Fl F .
.It Xo Ic capture-pane
.Op Fl aepPq
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Op Fl E Ar end-line
.Op Fl S Ar start-line
.Op Fl t Ar target-pane
@@ -1132,6 +1162,12 @@ and
.Fl E
specify the starting and ending line numbers, zero is the first line of the
visible pane and negative numbers are lines in the history.
+.Ql -
+to
+.Fl S
+is the start of the history and to
+.Fl E
+the end of the visible pane.
The default is to capture only the visible contents of the pane.
.It Xo
.Ic choose-client
@@ -1144,7 +1180,7 @@ interactively from a list.
After a client is chosen,
.Ql %%
is replaced by the client
-.Xr pty 4
+.Xr pty 7
path in
.Ar template
and the result executed as a command.
@@ -1158,32 +1194,6 @@ flag, see the
section.
This command works only if at least one client is attached.
.It Xo
-.Ic choose-list
-.Op Fl l Ar items
-.Op Fl t Ar target-window
-.Op Ar template
-.Xc
-Put a window into list choice mode, allowing
-.Ar items
-to be selected.
-.Ar items
-can be a comma-separated list to display more than one item.
-If an item has spaces, that entry must be quoted.
-After an item is chosen,
-.Ql %%
-is replaced by the chosen item in the
-.Ar template
-and the result is executed as a command.
-If
-.Ar template
-is not given, "run-shell '%%'" is used.
-.Ar items
-also accepts format specifiers.
-For the meaning of this see the
-.Sx FORMATS
-section.
-This command works only if at least one client is attached.
-.It Xo
.Ic choose-session
.Op Fl F Ar format
.Op Fl t Ar target-window
@@ -1296,7 +1306,7 @@ flag, see the
section.
This command works only if at least one client is attached.
.It Ic display-panes Op Fl t Ar target-client
-.D1 (alias: Ic displayp)
+.D1 (alias: Ic displayp )
Display a visible indicator of each pane shown by
.Ar target-client .
See the
@@ -1386,9 +1396,16 @@ The
.Fl a
option kills all but the window given with
.Fl t .
-.It Ic last-pane Op Fl t Ar target-window
+.It Xo Ic last-pane
+.Op Fl de
+.Op Fl t Ar target-window
+.Xc
.D1 (alias: Ic lastp )
Select the last (previously selected) pane.
+.Fl e
+enables or
+.Fl d
+disables input to the pane.
.It Ic last-window Op Fl t Ar target-session
.D1 (alias: Ic last )
Select the last (previously selected) window.
@@ -1705,7 +1722,7 @@ and
.Ic previous-layout
commands.
.It Xo Ic select-pane
-.Op Fl lDLRU
+.Op Fl DdeLlRU
.Op Fl t Ar target-pane
.Xc
.D1 (alias: Ic selectp )
@@ -1725,6 +1742,10 @@ target pane is used.
is the same as using the
.Ic last-pane
command.
+.Fl e
+enables or
+.Fl d
+disables input to the pane.
.It Xo Ic select-window
.Op Fl lnpT
.Op Fl t Ar target-window
@@ -1748,7 +1769,7 @@ is given and the selected window is already the current window,
the command behaves like
.Ic last-window .
.It Xo Ic split-window
-.Op Fl dhvP
+.Op Fl bdhvP
.Op Fl c Ar start-directory
.Oo Fl l
.Ar size |
@@ -1772,6 +1793,10 @@ and
.Fl p
options specify the size of the new pane in lines (for vertical split) or in
cells (for horizontal split), or as a percentage, respectively.
+The
+.Fl b
+option causes the new pane to be created to the left of or above
+.Ar target-pane .
All other options have the same meaning as for the
.Ic new-window
command.
@@ -1848,7 +1873,7 @@ In addition, the following special key names are accepted:
.Em Escape ,
.Em F1
to
-.Em F20 ,
+.Em F12 ,
.Em Home ,
.Em IC
(Insert),
@@ -1871,7 +1896,7 @@ Commands related to key bindings are as follows:
.Bl -tag -width Ds
.It Xo Ic bind-key
.Op Fl cnr
-.Op Fl t Ar key-table
+.Op Fl t Ar mode-table
.Ar key Ar command Op Ar arguments
.Xc
.D1 (alias: Ic bind )
@@ -1900,7 +1925,7 @@ If
is present,
.Ar key
is bound in
-.Ar key-table :
+.Ar mode-table :
the binding for command mode with
.Fl c
or for normal mode without.
@@ -1958,7 +1983,7 @@ Send the prefix key, or with
the secondary prefix key, to a window as if it was pressed.
.It Xo Ic unbind-key
.Op Fl acn
-.Op Fl t Ar key-table
+.Op Fl t Ar mode-table
.Ar key
.Xc
.D1 (alias: Ic unbind )
@@ -1980,7 +2005,7 @@ If
is present,
.Ar key
in
-.Ar key-table
+.Ar mode-table
is unbound: the binding for command mode with
.Fl c
or for normal mode without.
@@ -2076,9 +2101,7 @@ flag prevents setting an option that is already set.
.Pp
The
.Fl q
-flag suppresses the informational message (as if the
-.Ic quiet
-server option was set).
+flag suppresses errors about unknown options.
.Pp
With
.Fl a ,
@@ -2137,12 +2160,10 @@ passed through to applications running in
.Nm .
Attached clients should be detached and attached again after changing this
option.
-.It Xo Ic quiet
-.Op Ic on | off
-.Xc
-Enable or disable the display of various informational messages (see also the
-.Fl q
-command line flag).
+.It Ic message-limit Ar number
+Set the number of error or information messages to save in the message log for
+each client.
+The default is 100.
.It Xo Ic set-clipboard
.Op Ic on | off
.Xc
@@ -2165,6 +2186,42 @@ disallowedWindowOps: 20,21,SetXprop
Or changing this property from the
.Xr xterm 1
interactive menu when required.
+.It Ic terminal-overrides Ar string
+Contains a list of entries which override terminal descriptions read using
+.Xr terminfo 5 .
+.Ar string
+is a comma-separated list of items each a colon-separated string made up of a
+terminal type pattern (matched using
+.Xr fnmatch 3 )
+and a set of
+.Em name=value
+entries.
+.Pp
+For example, to set the
+.Ql clear
+.Xr terminfo 5
+entry to
+.Ql \ee[H\ee[2J
+for all terminal types and the
+.Ql dch1
+entry to
+.Ql \ee[P
+for the
+.Ql rxvt
+terminal type, the option could be set to the string:
+.Bd -literal -offset indent
+"*:clear=\ee[H\ee[2J,rxvt:dch1=\ee[P"
+.Ed
+.Pp
+The terminal entry value is passed through
+.Xr strunvis 3
+before interpretation.
+The default value forcibly corrects the
+.Ql colors
+entry for terminals which support 256 colours:
+.Bd -literal -offset indent
+"*256col*:colors=256,xterm*:XT"
+.Ed
.El
.Pp
Available session options are:
@@ -2358,10 +2415,6 @@ With the
flag to the
.Ic set-option
command the new style is added otherwise the existing style is replaced.
-.It Ic message-limit Ar number
-Set the number of error or information messages to save in the message log for
-each client.
-The default is 20.
.It Ic message-style Ar style
Set status line message style.
For how to specify
@@ -2392,22 +2445,6 @@ window.
.Op Ic on | off
.Xc
If enabled, request mouse input as UTF-8 on UTF-8 terminals.
-.It Ic pane-active-border-style Ar style
-Set the pane border style for the currently active pane.
-For how to specify
-.Ar style ,
-see the
-.Ic message-command-style
-option.
-Attributes are ignored.
-.It Ic pane-border-style Ar style
-Set the pane border style for paneas aside from the active pane.
-For how to specify
-.Ar style ,
-see the
-.Ic message-command-style
-option.
-Attributes are ignored.
.It Ic prefix Ar key
Set the key accepted as a prefix key.
.It Ic prefix2 Ar key
@@ -2540,15 +2577,14 @@ Examples are:
#[fg=yellow,bold]#(apm -l)%%#[default] [#S]
.Ed
.Pp
-Where appropriate, special character sequences may be prefixed with a number to
-specify the maximum length, for example
-.Ql #24T .
-.Pp
By default, UTF-8 in
.Ar string
is not interpreted, to enable UTF-8, use the
.Ic status-utf8
option.
+.Pp
+The default is
+.Ql "[#S] " .
.It Ic status-left-length Ar length
Set the maximum
.Ar length
@@ -2609,42 +2645,6 @@ and
.Ic status-right
strings as UTF-8; notably, this is important for wide characters.
This option defaults to off.
-.It Ic terminal-overrides Ar string
-Contains a list of entries which override terminal descriptions read using
-.Xr terminfo 5 .
-.Ar string
-is a comma-separated list of items each a colon-separated string made up of a
-terminal type pattern (matched using
-.Xr fnmatch 3 )
-and a set of
-.Em name=value
-entries.
-.Pp
-For example, to set the
-.Ql clear
-.Xr terminfo 5
-entry to
-.Ql \ee[H\ee[2J
-for all terminal types and the
-.Ql dch1
-entry to
-.Ql \ee[P
-for the
-.Ql rxvt
-terminal type, the option could be set to the string:
-.Bd -literal -offset indent
-"*:clear=\ee[H\ee[2J,rxvt:dch1=\ee[P"
-.Ed
-.Pp
-The terminal entry value is passed through
-.Xr strunvis 3
-before interpretation.
-The default value forcibly corrects the
-.Ql colors
-entry for terminals which support 256 colours:
-.Bd -literal -offset indent
-"*256col*:colors=256,xterm*:XT"
-.Ed
.It Ic update-environment Ar variables
Set a space-separated string containing a list of environment variables to be
copied into the session environment when a new session is created or an
@@ -2673,15 +2673,6 @@ through to the terminal (which normally makes a sound).
Also see the
.Ic bell-action
option.
-.It Xo Ic visual-content
-.Op Ic on | off
-.Xc
-Like
-.Ic visual-activity ,
-display a message when content is present in a window
-for which the
-.Ic monitor-content
-window option is enabled.
.It Xo Ic visual-silence
.Op Ic on | off
.Xc
@@ -2863,14 +2854,6 @@ option.
Monitor for activity in the window.
Windows with activity are highlighted in the status line.
.Pp
-.It Ic monitor-content Ar match-string
-Monitor content in the window.
-When
-.Xr fnmatch 3
-pattern
-.Ar match-string
-appears in the window, it is highlighted in the status line.
-.Pp
.It Xo Ic monitor-silence
.Op Ic interval
.Xc
@@ -2900,11 +2883,29 @@ but set the width of other panes in the
.Ic main-vertical
layout.
.Pp
+.It Ic pane-active-border-style Ar style
+Set the pane border style for the currently active pane.
+For how to specify
+.Ar style ,
+see the
+.Ic message-command-style
+option.
+Attributes are ignored.
+.Pp
.It Ic pane-base-index Ar index
Like
.Ic base-index ,
but set the starting index for pane numbers.
.Pp
+.It Ic pane-border-style Ar style
+Set the pane border style for panes aside from the active pane.
+For how to specify
+.Ar style ,
+see the
+.Ic message-command-style
+option.
+Attributes are ignored.
+.Pp
.It Xo Ic remain-on-exit
.Op Ic on | off
.Xc
@@ -2943,14 +2944,6 @@ see the
.Ic message-command-style
option.
.Pp
-.It Ic window-status-content-style Ar style
-Set status line style for windows with a content alert.
-For how to specify
-.Ar style ,
-see the
-.Ic message-command-style
-option.
-.Pp
.It Ic window-status-current-format Ar string
Like
.Ar window-status-format ,
@@ -3060,12 +3053,17 @@ and
.Ql } ,
for example
.Ql #{session_name} .
-Some variables also have an shorter alias such as
-.Ql #S .
+The possible variables are listed in the table below, or the name of a
+.Nm
+option may be used for an option's value.
+Some variables have a shorter alias such as
+.Ql #S ,
+and
.Ql ##
is replaced by a single
.Ql # .
-Conditionals are also accepted by prefixing with
+.Pp
+Conditionals are available by prefixing with
.Ql \&?
and separating two alternatives with a comma;
if the specified variable exists and is not zero, the first alternative
@@ -3076,7 +3074,15 @@ will include the string
.Ql attached
if the session is attached and the string
.Ql not attached
-if it is unattached.
+if it is unattached, or
+.Ql #{?automatic-rename,yes,no}
+will include
+.Ql yes
+if
+.Ic automatic-rename
+is enabled, or
+.Ql no
+if not.
A limit may be placed on the length of the resultant string by prefixing it
by an
.Ql = ,
@@ -3090,7 +3096,7 @@ The following variables are available, where appropriate:
.It Li "alternate_on" Ta "" Ta "If pane is in alternate screen"
.It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen"
.It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen"
-.It Li "buffer_sample" Ta "" Ta "First 50 characters from buffer"
+.It Li "buffer_sample" Ta "" Ta "Sample of start of buffer"
.It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes"
.It Li "client_activity" Ta "" Ta "Integer time client last had activity"
.It Li "client_activity_string" Ta "" Ta "String time client last had activity"
@@ -3122,49 +3128,56 @@ The following variables are available, where appropriate:
.It Li "mouse_standard_flag" Ta "" Ta "Pane mouse standard flag"
.It Li "mouse_utf8_flag" Ta "" Ta "Pane mouse UTF-8 flag"
.It Li "pane_active" Ta "" Ta "1 if active pane"
+.It Li "pane_bottom" Ta "" Ta "Bottom of pane"
.It Li "pane_current_command" Ta "" Ta "Current command if available"
.It Li "pane_current_path" Ta "" Ta "Current path if available"
.It Li "pane_dead" Ta "" Ta "1 if pane is dead"
+.It Li "pane_dead_status" Ta "" Ta "Exit status of process in dead pane"
.It Li "pane_height" Ta "" Ta "Height of pane"
.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
.It Li "pane_in_mode" Ta "" Ta "If pane is in a mode"
-.It Li "pane_synchronized" Ta "" Ta "If pane is synchronized"
+.It Li "pane_input_off" Ta "" Ta "If input to pane is disabled"
.It Li "pane_index" Ta "#P" Ta "Index of pane"
+.It Li "pane_left" Ta "" Ta "Left of pane"
.It Li "pane_pid" Ta "" Ta "PID of first process in pane"
+.It Li "pane_right" Ta "" Ta "Right of pane"
.It Li "pane_start_command" Ta "" Ta "Command pane started with"
-.It Li "pane_start_path" Ta "" Ta "Path pane started with"
+.It Li "pane_synchronized" Ta "" Ta "If pane is synchronized"
.It Li "pane_tabs" Ta "" Ta "Pane tab positions"
.It Li "pane_title" Ta "#T" Ta "Title of pane"
+.It Li "pane_top" Ta "" Ta "Top of pane"
.It Li "pane_tty" Ta "" Ta "Pseudo terminal of pane"
.It Li "pane_width" Ta "" Ta "Width of pane"
.It Li "saved_cursor_x" Ta "" Ta "Saved cursor X in pane"
.It Li "saved_cursor_y" Ta "" Ta "Saved cursor Y in pane"
.It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"
.It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane"
-.It Li "session_attached" Ta "" Ta "1 if session attached"
+.It Li "session_attached" Ta "" Ta "Number of clients session is attached to"
.It Li "session_created" Ta "" Ta "Integer time session created"
.It Li "session_created_string" Ta "" Ta "String time session created"
.It Li "session_group" Ta "" Ta "Number of session group"
.It Li "session_grouped" Ta "" Ta "1 if session in a group"
.It Li "session_height" Ta "" Ta "Height of session"
.It Li "session_id" Ta "" Ta "Unique session ID"
+.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
.It Li "session_name" Ta "#S" Ta "Name of session"
.It Li "session_width" Ta "" Ta "Width of session"
.It Li "session_windows" Ta "" Ta "Number of windows in session"
.It Li "window_active" Ta "" Ta "1 if window active"
.It Li "window_activity_flag" Ta "" Ta "1 if window has activity alert"
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
-.It Li "window_content_flag" Ta "" Ta "1 if window has content alert"
.It Li "window_find_matches" Ta "" Ta "Matched data from the find-window"
.It Li "window_flags" Ta "#F" Ta "Window flags"
.It Li "window_height" Ta "" Ta "Height of window"
.It Li "window_id" Ta "" Ta "Unique window ID"
.It Li "window_index" Ta "#I" Ta "Index of window"
+.It Li "window_last_flag" Ta "" Ta "1 if window is the last used"
.It Li "window_layout" Ta "" Ta "Window layout description"
.It Li "window_name" Ta "#W" Ta "Name of window"
.It Li "window_panes" Ta "" Ta "Number of panes in window"
.It Li "window_silence_flag" Ta "" Ta "1 if window has silence alert"
.It Li "window_width" Ta "" Ta "Width of window"
+.It Li "window_zoomed_flag" Ta "" Ta "1 if window is zoomed"
.It Li "wrap_flag" Ta "" Ta "Pane wrap flag"
.El
.Sh NAMES AND TITLES
@@ -3316,18 +3329,15 @@ The flag is one of the following symbols appended to the window name:
.It Li "-" Ta "Marks the last window (previously selected)."
.It Li "#" Ta "Window is monitored and activity has been detected."
.It Li "!" Ta "A bell has occurred in the window."
-.It Li "+" Ta "Window is monitored for content and it has appeared."
.It Li "~" Ta "The window has been silent for the monitor-silence interval."
.It Li "Z" Ta "The window's active pane is zoomed."
.El
.Pp
The # symbol relates to the
.Ic monitor-activity
-and + to the
-.Ic monitor-content
-window options.
+window option.
The window name is printed in inverted colours if an alert (bell, activity or
-content) is present.
+silence) is present.
.Pp
The colour and attributes of the status line may be configured, the entire
status line using the
@@ -3441,19 +3451,40 @@ is given, otherwise the active pane for the session attached to
.El
.Sh BUFFERS
.Nm
-maintains a stack of
+maintains a set of named
.Em paste buffers .
-Up to the value of the
+Each buffer may be either explicitly or automatically named.
+Explicitly named buffers are named when created with the
+.Ic set-buffer
+or
+.Ic load-buffer
+commands, or by renaming an automatically named buffer with
+.Ic set-buffer
+.Fl n .
+Automatically named buffers are given a name such as
+.Ql buffer0001 ,
+.Ql buffer0002
+and so on.
+When the
.Ic buffer-limit
-option are kept; when a new buffer is added, the buffer at the bottom of the
-stack is removed.
+option is reached, the oldest automatically named buffer is deleted.
+Explicitly named are not subject to
+.Ic buffer-limit
+and may be deleted with
+.Ic delete-buffer
+command.
+.Pp
Buffers may be added using
.Ic copy-mode
or the
.Ic set-buffer
-command, and pasted into a window using the
+and
+.Ic load-buffer
+commands, and pasted into a window using the
.Ic paste-buffer
command.
+If a buffer command is used and no buffer is specified, the most
+recently added automatically named buffer is assumed.
.Pp
A configurable history buffer is also maintained for each window.
By default, up to 2000 lines are kept; this can be altered with the
@@ -3474,7 +3505,7 @@ 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
+is replaced by the buffer name in
.Ar template
and the result executed as a command.
If
@@ -3489,11 +3520,11 @@ This command works only if at least one client is attached.
.It Ic clear-history Op Fl t Ar target-pane
.D1 (alias: Ic clearhist )
Remove and free the history for the specified pane.
-.It Ic delete-buffer Op Fl b Ar buffer-index
+.It Ic delete-buffer Op Fl b Ar buffer-name
.D1 (alias: Ic deleteb )
-Delete the buffer at
-.Ar buffer-index ,
-or the top buffer if not specified.
+Delete the buffer named
+.Ar buffer-name ,
+or the most recently added automatically named buffer if not specified.
.It Xo Ic list-buffers
.Op Fl F Ar format
.Xc
@@ -3505,7 +3536,7 @@ flag, see the
.Sx FORMATS
section.
.It Xo Ic load-buffer
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Ar path
.Xc
.D1 (alias: Ic loadb )
@@ -3513,7 +3544,7 @@ Load the contents of the specified paste buffer from
.Ar path .
.It Xo Ic paste-buffer
.Op Fl dpr
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Op Fl s Ar separator
.Op Fl t Ar target-pane
.Xc
@@ -3522,7 +3553,7 @@ 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.
+also delete the paste buffer.
When output, any linefeed (LF) characters in the paste buffer are replaced with
a separator, by default carriage return (CR).
A custom separator may be specified using the
@@ -3537,7 +3568,7 @@ is specified, paste bracket control codes are inserted around the
buffer if the application has requested bracketed paste mode.
.It Xo Ic save-buffer
.Op Fl a
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Ar path
.Xc
.D1 (alias: Ic saveb )
@@ -3547,14 +3578,23 @@ The
.Fl a
option appends to rather than overwriting the file.
.It Xo Ic set-buffer
-.Op Fl b Ar buffer-index
+.Op Fl a
+.Op Fl b Ar buffer-name
+.Op Fl n Ar new-buffer-name
.Ar data
.Xc
.D1 (alias: Ic setb )
Set the contents of the specified buffer to
.Ar data .
+The
+.Fl a
+option appends to rather than overwriting the buffer.
+The
+.Fl n
+option renames the buffer to
+.Ar new-buffer-name .
.It Xo Ic show-buffer
-.Op Fl b Ar buffer-index
+.Op Fl b Ar buffer-name
.Xc
.D1 (alias: Ic showb )
Display the contents of the specified buffer.
@@ -3565,7 +3605,7 @@ Miscellaneous commands are as follows:
.It Ic clock-mode Op Fl t Ar target-pane
Display a large clock.
.It Xo Ic if-shell
-.Op Fl b
+.Op Fl bF
.Op Fl t Ar target-pane
.Ar shell-command command
.Op Ar command
@@ -3578,7 +3618,9 @@ if
returns success or the second
.Ar command
otherwise.
-Before being executed, shell-command is expanded using the rules specified in the
+Before being executed,
+.Ar shell-command
+is expanded using the rules specified in the
.Sx FORMATS
section, including those relevant to
.Ar target-pane .
@@ -3586,6 +3628,13 @@ With
.Fl b ,
.Ar shell-command
is run in the background.
+.Pp
+If
+.Fl F
+is given,
+.Ar shell-command
+is not executed but considered success if neither empty nor zero (after formats
+are expanded).
.It Ic lock-server
.D1 (alias: Ic lock )
Lock each client individually by running the command specified by the
@@ -3646,7 +3695,7 @@ to change the cursor colour from inside
$ printf '\e033]12;red\e033\e\e'
.Ed
.It Em \&Ss , Se
-Change the cursor style.
+Set or reset the cursor style.
If set, a sequence such as this may be used
to change the cursor to an underline:
.Bd -literal -offset indent
@@ -3654,10 +3703,8 @@ $ printf '\e033[4 q'
.Ed
.Pp
If
-.Em Csr
-is set, it will be used to reset the cursor style instead
-of
-.Em Cs .
+.Em Se
+is not set, \&Ss with argument 0 will be used to reset the cursor style instead.
.It Em \&Ms
This sequence can be used by
.Nm
@@ -3852,6 +3899,6 @@ bind-key / command-prompt "split-window 'exec man %%'"
bind-key S command-prompt "new-window -n %1 'ssh %1'"
.Ed
.Sh SEE ALSO
-.Xr pty 4
+.Xr pty 7
.Sh AUTHORS
.An Nicholas Marriott Aq Mt nicm@users.sourceforge.net
diff --git a/tmux.c b/tmux.c
index a804e6f7..8b675761 100644
--- a/tmux.c
+++ b/tmux.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,6 +22,7 @@
#include <errno.h>
#include <event.h>
#include <fcntl.h>
+#include <getopt.h>
#include <locale.h>
#include <pwd.h>
#include <stdlib.h>
@@ -45,7 +46,7 @@ char *cfg_file;
char *shell_cmd;
int debug_level;
time_t start_time;
-char socket_path[MAXPATHLEN];
+char socket_path[PATH_MAX];
int login_shell;
char *environ_path;
@@ -73,7 +74,7 @@ logfile(const char *name)
if (debug_level > 0) {
xasprintf(&path, "tmux-%s-%ld.log", name, (long) getpid());
- log_open(debug_level, path);
+ log_open(path);
free(path);
}
}
@@ -127,13 +128,13 @@ areshell(const char *shell)
char *
makesocketpath(const char *label)
{
- char base[MAXPATHLEN], realbase[MAXPATHLEN], *path, *s;
+ char base[PATH_MAX], realbase[PATH_MAX], *path, *s;
struct stat sb;
u_int uid;
uid = getuid();
if ((s = getenv("TMUX_TMPDIR")) != NULL && *s != '\0')
- xsnprintf(base, sizeof base, "%s/", s);
+ xsnprintf(base, sizeof base, "%s/tmux-%u", s, uid);
else if ((s = getenv("TMPDIR")) != NULL && *s != '\0')
xsnprintf(base, sizeof base, "%s/tmux-%u", s, uid);
else
@@ -148,8 +149,7 @@ makesocketpath(const char *label)
errno = ENOTDIR;
return (NULL);
}
- if (sb.st_uid != uid || (!S_ISDIR(sb.st_mode) &&
- sb.st_mode & (S_IRWXG|S_IRWXO)) != 0) {
+ if (sb.st_uid != uid || (sb.st_mode & S_IRWXO) != 0) {
errno = EACCES;
return (NULL);
}
@@ -205,11 +205,11 @@ int
main(int argc, char **argv)
{
struct passwd *pw;
- char *s, *path, *label, **var, tmp[MAXPATHLEN];
+ char *s, *path, *label, **var, tmp[PATH_MAX];
char in[256];
const char *home;
long long pid;
- int opt, flags, quiet, keys, session;
+ int opt, flags, keys, session;
#if defined(DEBUG) && defined(__OpenBSD__)
malloc_options = (char *) "AFGJPX";
@@ -217,7 +217,7 @@ main(int argc, char **argv)
setlocale(LC_TIME, "");
- quiet = flags = 0;
+ flags = 0;
label = path = NULL;
login_shell = (**argv == '-');
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1) {
@@ -250,7 +250,6 @@ main(int argc, char **argv)
label = xstrdup(optarg);
break;
case 'q':
- quiet = 1;
break;
case 'S':
free(path);
@@ -297,11 +296,11 @@ main(int argc, char **argv)
options_init(&global_options, NULL);
options_table_populate_tree(server_options_table, &global_options);
- options_set_number(&global_options, "quiet", quiet);
options_init(&global_s_options, NULL);
options_table_populate_tree(session_options_table, &global_s_options);
- options_set_string(&global_s_options, "default-shell", "%s", getshell());
+ options_set_string(&global_s_options, "default-shell", "%s",
+ getshell());
options_init(&global_w_options, NULL);
options_table_populate_tree(window_options_table, &global_w_options);
diff --git a/tmux.h b/tmux.h
index 7d5f230b..e296ac7c 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -21,17 +21,19 @@
#define PROTOCOL_VERSION 8
-#include <sys/param.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <event.h>
#include <limits.h>
-#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <termios.h>
+#ifdef HAVE_UTEMPTER
+#include <utempter.h>
+#endif
+
#include "array.h"
#include "compat.h"
@@ -65,88 +67,13 @@ extern char **environ;
#define unused __attribute__ ((unused))
/* Attribute to make gcc check printf-like arguments. */
-#define printflike1 __attribute__ ((format (printf, 1, 2)))
-#define printflike2 __attribute__ ((format (printf, 2, 3)))
-#define printflike3 __attribute__ ((format (printf, 3, 4)))
-#define printflike4 __attribute__ ((format (printf, 4, 5)))
-#define printflike5 __attribute__ ((format (printf, 5, 6)))
+#define printflike(a, b) __attribute__ ((format (printf, a, b)))
/* Number of items in array. */
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
-/* Default template for choose-buffer. */
-#define CHOOSE_BUFFER_TEMPLATE \
- "#{line}: #{buffer_size} bytes: \"#{buffer_sample}\""
-
-/* Default template for choose-client. */
-#define CHOOSE_CLIENT_TEMPLATE \
- "#{client_tty}: #{session_name} " \
- "[#{client_width}x#{client_height} #{client_termname}]" \
- "#{?client_utf8, (utf8),}#{?client_readonly, (ro),} " \
- "(last used #{client_activity_string})"
-
-/* Default templates for choose-tree. */
-#define CHOOSE_TREE_SESSION_TEMPLATE \
- "#{session_name}: #{session_windows} windows" \
- "#{?session_grouped, (group ,}" \
- "#{session_group}#{?session_grouped,),}" \
- "#{?session_attached, (attached),}"
-#define CHOOSE_TREE_WINDOW_TEMPLATE \
- "#{window_index}: #{window_name}#{window_flags} " \
- "\"#{pane_title}\""
-
-/* Default template for display-message. */
-#define DISPLAY_MESSAGE_TEMPLATE \
- "[#{session_name}] #{window_index}:" \
- "#{window_name}, current pane #{pane_index} " \
- "- (%H:%M %d-%b-%y)"
-
-/* Default template for find-window. */
-#define FIND_WINDOW_TEMPLATE \
- "#{window_index}: #{window_name} " \
- "[#{window_width}x#{window_height}] " \
- "(#{window_panes} panes) #{window_find_matches}"
-
-/* Default template for list-buffers. */
-#define LIST_BUFFERS_TEMPLATE \
- "#{line}: #{buffer_size} bytes: \"#{buffer_sample}\""
-
-/* Default template for list-clients. */
-#define LIST_CLIENTS_TEMPLATE \
- "#{client_tty}: #{session_name} " \
- "[#{client_width}x#{client_height} #{client_termname}]" \
- "#{?client_utf8, (utf8),} #{?client_readonly, (ro),}"
-
-/* Default template for list-sessions. */
-#define LIST_SESSIONS_TEMPLATE \
- "#{session_name}: #{session_windows} windows " \
- "(created #{session_created_string}) " \
- "[#{session_width}x#{session_height}]" \
- "#{?session_grouped, (group ,}" \
- "#{session_group}#{?session_grouped,),}" \
- "#{?session_attached, (attached),}"
-
-/* Default templates for list-windows. */
-#define LIST_WINDOWS_TEMPLATE \
- "#{window_index}: #{window_name}#{window_flags} " \
- "(#{window_panes} panes) " \
- "[#{window_width}x#{window_height}] " \
- "[layout #{window_layout}] #{window_id}" \
- "#{?window_active, (active),}";
-#define LIST_WINDOWS_WITH_SESSION_TEMPLATE \
- "#{session_name}:" \
- "#{window_index}: #{window_name}#{window_flags} " \
- "(#{window_panes} panes) " \
- "[#{window_width}x#{window_height}] "
-
-/* Default templates for break-pane, new-window and split-window. */
-#define BREAK_PANE_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
-#define NEW_SESSION_TEMPLATE "#{session_name}:"
-#define NEW_WINDOW_TEMPLATE BREAK_PANE_TEMPLATE
-#define SPLIT_WINDOW_TEMPLATE BREAK_PANE_TEMPLATE
-
/* Bell option values. */
#define BELL_NONE 0
#define BELL_ANY 1
@@ -187,14 +114,6 @@ enum key_code {
KEYC_F10,
KEYC_F11,
KEYC_F12,
- KEYC_F13,
- KEYC_F14,
- KEYC_F15,
- KEYC_F16,
- KEYC_F17,
- KEYC_F18,
- KEYC_F19,
- KEYC_F20,
KEYC_IC,
KEYC_DC,
KEYC_HOME,
@@ -254,6 +173,7 @@ enum tty_code_code {
TTYC_CUP, /* cursor_address, cm */
TTYC_CUU, /* parm_up_cursor, UP */
TTYC_CUU1, /* cursor_up, up */
+ TTYC_CVVIS, /* cursor_visible, vs */
TTYC_DCH, /* parm_dch, DC */
TTYC_DCH1, /* delete_character, dc */
TTYC_DIM, /* enter_dim_mode, mh */
@@ -300,26 +220,69 @@ enum tty_code_code {
TTYC_KEND5,
TTYC_KEND6,
TTYC_KEND7,
- TTYC_KF1, /* key_f1, k1 */
- TTYC_KF10, /* key_f10, k; */
- TTYC_KF11, /* key_f11, F1 */
- TTYC_KF12, /* key_f12, F2 */
- TTYC_KF13, /* key_f13, F3 */
- TTYC_KF14, /* key_f14, F4 */
- TTYC_KF15, /* key_f15, F5 */
- TTYC_KF16, /* key_f16, F6 */
- TTYC_KF17, /* key_f17, F7 */
- TTYC_KF18, /* key_f18, F8 */
- TTYC_KF19, /* key_f19, F9 */
- TTYC_KF2, /* key_f2, k2 */
- TTYC_KF20, /* key_f20, F10 */
- TTYC_KF3, /* key_f3, k3 */
- TTYC_KF4, /* key_f4, k4 */
- TTYC_KF5, /* key_f5, k5 */
- TTYC_KF6, /* key_f6, k6 */
- TTYC_KF7, /* key_f7, k7 */
- TTYC_KF8, /* key_f8, k8 */
- TTYC_KF9, /* key_f9, k9 */
+ TTYC_KF1,
+ TTYC_KF10,
+ TTYC_KF11,
+ TTYC_KF12,
+ TTYC_KF13,
+ TTYC_KF14,
+ TTYC_KF15,
+ TTYC_KF16,
+ TTYC_KF17,
+ TTYC_KF18,
+ TTYC_KF19,
+ TTYC_KF2,
+ TTYC_KF20,
+ TTYC_KF21,
+ TTYC_KF22,
+ TTYC_KF23,
+ TTYC_KF24,
+ TTYC_KF25,
+ TTYC_KF26,
+ TTYC_KF27,
+ TTYC_KF28,
+ TTYC_KF29,
+ TTYC_KF3,
+ TTYC_KF30,
+ TTYC_KF31,
+ TTYC_KF32,
+ TTYC_KF33,
+ TTYC_KF34,
+ TTYC_KF35,
+ TTYC_KF36,
+ TTYC_KF37,
+ TTYC_KF38,
+ TTYC_KF39,
+ TTYC_KF4,
+ TTYC_KF40,
+ TTYC_KF41,
+ TTYC_KF42,
+ TTYC_KF43,
+ TTYC_KF44,
+ TTYC_KF45,
+ TTYC_KF46,
+ TTYC_KF47,
+ TTYC_KF48,
+ TTYC_KF49,
+ TTYC_KF5,
+ TTYC_KF50,
+ TTYC_KF51,
+ TTYC_KF52,
+ TTYC_KF53,
+ TTYC_KF54,
+ TTYC_KF55,
+ TTYC_KF56,
+ TTYC_KF57,
+ TTYC_KF58,
+ TTYC_KF59,
+ TTYC_KF6,
+ TTYC_KF60,
+ TTYC_KF61,
+ TTYC_KF62,
+ TTYC_KF63,
+ TTYC_KF7,
+ TTYC_KF8,
+ TTYC_KF9,
TTYC_KHOM2,
TTYC_KHOM3,
TTYC_KHOM4,
@@ -417,9 +380,6 @@ struct tty_term_code_entry {
const char *name;
};
-/* List of error causes. */
-ARRAY_DECL(causelist, char *);
-
/* Message codes. */
enum msgtype {
MSG_VERSION = 12,
@@ -513,14 +473,18 @@ enum mode_key_cmd {
/* Menu (choice) keys. */
MODEKEYCHOICE_BACKSPACE,
+ MODEKEYCHOICE_BOTTOMLINE,
MODEKEYCHOICE_CANCEL,
MODEKEYCHOICE_CHOOSE,
MODEKEYCHOICE_DOWN,
+ MODEKEYCHOICE_ENDOFLIST,
MODEKEYCHOICE_PAGEDOWN,
MODEKEYCHOICE_PAGEUP,
MODEKEYCHOICE_SCROLLDOWN,
MODEKEYCHOICE_SCROLLUP,
MODEKEYCHOICE_STARTNUMBERPREFIX,
+ MODEKEYCHOICE_STARTOFLIST,
+ MODEKEYCHOICE_TOPLINE,
MODEKEYCHOICE_TREE_COLLAPSE,
MODEKEYCHOICE_TREE_COLLAPSE_ALL,
MODEKEYCHOICE_TREE_EXPAND,
@@ -529,6 +493,7 @@ enum mode_key_cmd {
MODEKEYCHOICE_UP,
/* Copy keys. */
+ MODEKEYCOPY_APPENDSELECTION,
MODEKEYCOPY_BACKTOINDENTATION,
MODEKEYCOPY_BOTTOMLINE,
MODEKEYCOPY_CANCEL,
@@ -570,6 +535,7 @@ enum mode_key_cmd {
MODEKEYCOPY_SEARCHREVERSE,
MODEKEYCOPY_SEARCHUP,
MODEKEYCOPY_SELECTLINE,
+ MODEKEYCOPY_STARTNAMEDBUFFER,
MODEKEYCOPY_STARTNUMBERPREFIX,
MODEKEYCOPY_STARTOFLINE,
MODEKEYCOPY_STARTSELECTION,
@@ -633,13 +599,13 @@ struct mode_key_table {
#define MODE_WRAP 0x10 /* whether lines wrap */
#define MODE_MOUSE_STANDARD 0x20
#define MODE_MOUSE_BUTTON 0x40
-#define MODE_MOUSE_ANY 0x80
+#define MODE_BLINKING 0x80
#define MODE_MOUSE_UTF8 0x100
#define MODE_MOUSE_SGR 0x200
#define MODE_BRACKETPASTE 0x400
#define MODE_FOCUSON 0x800
-#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)
+#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON)
/* A single UTF-8 character. */
struct utf8_data {
@@ -651,16 +617,6 @@ struct utf8_data {
u_int width;
};
-/* Grid output. */
-#if defined(DEBUG) && \
- ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
- (defined(__GNUC__) && __GNUC__ >= 3))
-#define GRID_DEBUG(gd, fmt, ...) log_debug2("%s: (sx=%u, sy=%u, hsize=%u) " \
- fmt, __func__, (gd)->sx, (gd)->sy, (gd)->hsize, ## __VA_ARGS__)
-#else
-#define GRID_DEBUG(...)
-#endif
-
/* Grid attributes. */
#define GRID_ATTR_BRIGHT 0x1
#define GRID_ATTR_DIM 0x2
@@ -755,6 +711,13 @@ LIST_HEAD(joblist, job);
struct screen_sel {
int flag;
int rectflag;
+ enum {
+ LINE_SEL_NONE,
+ LINE_SEL_LEFT_RIGHT,
+ LINE_SEL_RIGHT_LEFT,
+ } lineflag;
+
+ int modekeys;
u_int sx;
u_int sy;
@@ -799,14 +762,22 @@ struct screen_write_ctx {
#define screen_hsize(s) ((s)->grid->hsize)
#define screen_hlimit(s) ((s)->grid->hlimit)
+/* Input parser cell. */
+struct input_cell {
+ struct grid_cell cell;
+ int set;
+ int g0set; /* 1 if ACS */
+ int g1set; /* 1 if ACS */
+};
+
/* Input parser context. */
struct input_ctx {
struct window_pane *wp;
struct screen_write_ctx ctx;
- struct grid_cell cell;
+ struct input_cell cell;
- struct grid_cell old_cell;
+ struct input_cell old_cell;
u_int old_cx;
u_int old_cy;
@@ -816,8 +787,11 @@ struct input_ctx {
u_char param_buf[64];
size_t param_len;
- u_char input_buf[256];
+#define INPUT_BUF_START 32
+#define INPUT_BUF_LIMIT 1048576
+ u_char *input_buf;
size_t input_len;
+ size_t input_space;
int param_list[24]; /* -1 not present */
u_int param_list_len;
@@ -887,6 +861,7 @@ struct window_choose_mode_item {
/* Child window structure. */
struct window_pane {
u_int id;
+ u_int active_point;
struct window *window;
@@ -905,13 +880,16 @@ struct window_pane {
#define PANE_FOCUSED 0x4
#define PANE_RESIZE 0x8
#define PANE_FOCUSPUSH 0x10
+#define PANE_INPUTOFF 0x20
- char *cmd;
+ int argc;
+ char **argv;
char *shell;
int cwd;
pid_t pid;
char tty[TTY_NAME_MAX];
+ int status;
u_int changes;
struct event changes_timer;
@@ -943,6 +921,7 @@ struct window_pane {
};
TAILQ_HEAD(window_panes, window_pane);
RB_HEAD(window_pane_tree, window_pane);
+ARRAY_DECL(window_pane_list, struct window_pane *);
/* Window structure. */
struct window {
@@ -967,7 +946,9 @@ struct window {
#define WINDOW_ACTIVITY 0x2
#define WINDOW_REDRAW 0x4
#define WINDOW_SILENCE 0x8
-#define WINDOW_ZOOMED 0x10
+#define WINDOW_ZOOMED 0x1000
+#define WINDOW_FORCEWIDTH 0x2000
+#define WINDOW_FORCEHEIGHT 0x4000
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
struct options options;
@@ -988,10 +969,8 @@ struct winlink {
int flags;
#define WINLINK_BELL 0x1
#define WINLINK_ACTIVITY 0x2
-#define WINLINK_CONTENT 0x4
-#define WINLINK_SILENCE 0x8
-#define WINLINK_ALERTFLAGS \
- (WINLINK_BELL|WINLINK_ACTIVITY|WINLINK_CONTENT|WINLINK_SILENCE)
+#define WINLINK_SILENCE 0x4
+#define WINLINK_ALERTFLAGS (WINLINK_BELL|WINLINK_ACTIVITY|WINLINK_SILENCE)
RB_ENTRY(winlink) entry;
TAILQ_ENTRY(winlink) sentry;
@@ -1022,8 +1001,6 @@ struct layout_cell {
u_int yoff;
struct window_pane *wp;
- struct window_pane *lastwp;
-
struct layout_cells cells;
TAILQ_ENTRY(layout_cell) entry;
@@ -1033,8 +1010,14 @@ struct layout_cell {
struct paste_buffer {
char *data;
size_t size;
+
+ char *name;
+ int automatic;
+ u_int order;
+
+ RB_ENTRY(paste_buffer) name_entry;
+ RB_ENTRY(paste_buffer) time_entry;
};
-ARRAY_DECL(paste_stack, struct paste_buffer *);
/* Environment variable. */
struct environ_entry {
@@ -1075,6 +1058,8 @@ struct session {
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */
int flags;
+ u_int attached;
+
struct termios *tio;
struct environ environ;
@@ -1114,19 +1099,30 @@ struct tty_term {
};
LIST_HEAD(tty_terms, tty_term);
+/* Mouse button masks. */
+#define MOUSE_MASK_BUTTONS 3
+#define MOUSE_MASK_SHIFT 4
+#define MOUSE_MASK_META 8
+#define MOUSE_MASK_CTRL 16
+#define MOUSE_MASK_DRAG 32
+#define MOUSE_MASK_WHEEL 64
+
/* Mouse wheel states. */
#define MOUSE_WHEEL_UP 0
#define MOUSE_WHEEL_DOWN 1
-/* Mouse events. */
-#define MOUSE_EVENT_DOWN (1 << 0)
-#define MOUSE_EVENT_DRAG (1 << 1)
-#define MOUSE_EVENT_UP (1 << 2)
-#define MOUSE_EVENT_CLICK (1 << 3)
-#define MOUSE_EVENT_WHEEL (1 << 4)
+/* Mouse wheel multipler. */
+#define MOUSE_WHEEL_SCALE 3
+
+/* Mouse event bits. */
+#define MOUSE_EVENT_DOWN 0x1
+#define MOUSE_EVENT_DRAG 0x2
+#define MOUSE_EVENT_UP 0x4
+#define MOUSE_EVENT_CLICK 0x8
+#define MOUSE_EVENT_WHEEL 0x10
-/* Mouse flags. */
-#define MOUSE_RESIZE_PANE (1 << 0)
+/* Mouse flag bits. */
+#define MOUSE_RESIZE_PANE 0x1
/*
* Mouse input. When sent by xterm:
@@ -1156,6 +1152,7 @@ struct mouse_event {
u_int button;
u_int clicks;
+ u_int scroll;
int wheel;
int event;
@@ -1421,7 +1418,6 @@ struct cmd_entry {
#define CMD_READONLY 0x4
int flags;
- void (*key_binding)(struct cmd *, int);
enum cmd_retval (*exec)(struct cmd *, struct cmd_q *);
};
@@ -1465,15 +1461,6 @@ struct options_table_entry {
const char *style;
};
-/* Tree of format entries. */
-struct format_entry {
- char *key;
- char *value;
-
- RB_ENTRY(format_entry) entry;
-};
-RB_HEAD(format_tree, format_entry);
-
/* Common command usages. */
#define CMD_TARGET_PANE_USAGE "[-t target-pane]"
#define CMD_TARGET_WINDOW_USAGE "[-t target-window]"
@@ -1483,7 +1470,7 @@ RB_HEAD(format_tree, format_entry);
#define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]"
#define CMD_SRCDST_SESSION_USAGE "[-s src-session] [-t dst-session]"
#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
-#define CMD_BUFFER_USAGE "[-b buffer-index]"
+#define CMD_BUFFER_USAGE "[-b buffer-name]"
/* tmux.c */
extern struct options global_options;
@@ -1495,7 +1482,7 @@ extern char *cfg_file;
extern char *shell_cmd;
extern int debug_level;
extern time_t start_time;
-extern char socket_path[MAXPATHLEN];
+extern char socket_path[PATH_MAX];
extern int login_shell;
extern char *environ_path;
void logfile(const char *);
@@ -1509,30 +1496,29 @@ __dead void shell_exec(const char *, const char *);
extern struct cmd_q *cfg_cmd_q;
extern int cfg_finished;
extern int cfg_references;
-extern struct causelist cfg_causes;
extern struct client *cfg_client;
int load_cfg(const char *, struct cmd_q *, char **);
void cfg_default_done(struct cmd_q *);
+void cfg_add_cause(const char *, ...);
+void cfg_print_causes(struct cmd_q *);
void cfg_show_causes(struct session *);
/* format.c */
-int format_cmp(struct format_entry *, struct format_entry *);
-RB_PROTOTYPE(format_tree, format_entry, entry, format_cmp);
+struct format_tree;
struct format_tree *format_create(void);
void format_free(struct format_tree *);
-void printflike3 format_add(struct format_tree *, const char *, const char *,
- ...);
+void printflike(3, 4) format_add(struct format_tree *, const char *,
+ const char *, ...);
const char *format_find(struct format_tree *, const char *);
+char *format_expand_time(struct format_tree *, const char *, time_t);
char *format_expand(struct format_tree *, const char *);
-void format_session(struct format_tree *, struct session *);
-void format_client(struct format_tree *, struct client *);
-void format_window(struct format_tree *, struct window *);
-void format_winlink(struct format_tree *, struct session *,
- struct winlink *);
-void format_window_pane(struct format_tree *,
+void format_defaults(struct format_tree *, struct client *,
+ struct session *, struct winlink *, struct window_pane *);
+void format_defaults_window(struct format_tree *, struct window *);
+void format_defaults_pane(struct format_tree *,
struct window_pane *);
-void format_paste_buffer(struct format_tree *,
- struct paste_buffer *);
+void format_defaults_paste_buffer(struct format_tree *,
+ struct paste_buffer *, int);
/* mode-key.c */
extern const struct mode_key_table mode_key_tables[];
@@ -1574,7 +1560,7 @@ void options_free(struct options *);
struct options_entry *options_find1(struct options *, const char *);
struct options_entry *options_find(struct options *, const char *);
void options_remove(struct options *, const char *);
-struct options_entry *printflike3 options_set_string(struct options *,
+struct options_entry *printflike(3, 4) options_set_string(struct options *,
const char *, const char *, ...);
char *options_get_string(struct options *, const char *);
struct options_entry *options_set_number(struct options *, const char *,
@@ -1643,7 +1629,7 @@ void tty_set_title(struct tty *, const char *);
void tty_update_mode(struct tty *, int, struct screen *);
void tty_force_cursor_colour(struct tty *, const char *);
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int);
-int tty_open(struct tty *, const char *, char **);
+int tty_open(struct tty *, char **);
void tty_close(struct tty *);
void tty_free(struct tty *);
void tty_write(
@@ -1672,7 +1658,7 @@ void tty_bell(struct tty *);
/* tty-term.c */
extern struct tty_terms tty_terms;
extern const struct tty_term_code_entry tty_term_codes[NTTYCODE];
-struct tty_term *tty_term_find(char *, int, const char *, char **);
+struct tty_term *tty_term_find(char *, int, char **);
void tty_term_free(struct tty_term *);
int tty_term_has(struct tty_term *, enum tty_code_code);
const char *tty_term_string(struct tty_term *, enum tty_code_code);
@@ -1695,21 +1681,18 @@ void tty_keys_free(struct tty *);
int tty_keys_next(struct tty *);
/* paste.c */
-struct paste_buffer *paste_walk_stack(struct paste_stack *, u_int *);
-struct paste_buffer *paste_get_top(struct paste_stack *);
-struct paste_buffer *paste_get_index(struct paste_stack *, u_int);
-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);
+struct paste_buffer *paste_walk(struct paste_buffer *);
+struct paste_buffer *paste_get_top(void);
+struct paste_buffer *paste_get_name(const char *);
+int paste_free_top(void);
+int paste_free_name(const char *);
+void paste_add(char *, size_t);
+int paste_rename(const char *, const char *, char **);
+int paste_set(char *, size_t, const char *, char **);
+char *paste_make_sample(struct paste_buffer *, int);
void paste_send_pane(struct paste_buffer *, struct window_pane *,
const char *, int);
-/* clock.c */
-extern const char clock_table[14][5][5];
-void clock_draw(struct screen_write_ctx *, int, int);
-
/* arguments.c */
int args_cmp(struct args_entry *, struct args_entry *);
RB_PROTOTYPE(args_tree, args_entry, entry, args_cmp);
@@ -1726,8 +1709,9 @@ long long args_strtonum(
/* cmd.c */
int cmd_pack_argv(int, char **, char *, size_t);
int cmd_unpack_argv(char *, size_t, int, char ***);
-char **cmd_copy_argv(int, char *const *);
+char **cmd_copy_argv(int, char **);
void cmd_free_argv(int, char **);
+char *cmd_stringify_argv(int, char **);
struct cmd *cmd_parse(int, char **, const char *, u_int, char **);
size_t cmd_print(struct cmd *, char *, size_t);
struct session *cmd_current_session(struct cmd_q *, int);
@@ -1750,7 +1734,6 @@ 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_list_entry;
extern const struct cmd_entry cmd_choose_session_entry;
extern const struct cmd_entry cmd_choose_tree_entry;
extern const struct cmd_entry cmd_choose_window_entry;
@@ -1844,10 +1827,9 @@ size_t cmd_list_print(struct cmd_list *, char *, size_t);
/* cmd-queue.c */
struct cmd_q *cmdq_new(struct client *);
int cmdq_free(struct cmd_q *);
-void printflike2 cmdq_print(struct cmd_q *, const char *, ...);
-void printflike2 cmdq_info(struct cmd_q *, const char *, ...);
-void printflike2 cmdq_error(struct cmd_q *, const char *, ...);
-int cmdq_guard(struct cmd_q *, const char *, int);
+void printflike(2, 3) cmdq_print(struct cmd_q *, const char *, ...);
+void printflike(2, 3) cmdq_error(struct cmd_q *, const char *, ...);
+void cmdq_guard(struct cmd_q *, const char *, int);
void cmdq_run(struct cmd_q *, struct cmd_list *);
void cmdq_append(struct cmd_q *, struct cmd_list *);
int cmdq_continue(struct cmd_q *);
@@ -1857,6 +1839,9 @@ void cmdq_flush(struct cmd_q *);
int cmd_string_parse(const char *, struct cmd_list **, const char *,
u_int, char **);
+/* cmd-wait-for.c */
+void cmd_wait_for_flush(void);
+
/* client.c */
int client_main(int, char **, int);
@@ -1867,7 +1852,6 @@ RB_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
struct key_binding *key_bindings_lookup(int);
void key_bindings_add(int, int, struct cmd_list *);
void key_bindings_remove(int);
-void key_bindings_clean(void);
void key_bindings_init(void);
void key_bindings_dispatch(struct key_binding *, struct client *);
@@ -1878,7 +1862,6 @@ const char *key_string_lookup_key(int);
/* server.c */
extern struct clients clients;
extern struct clients dead_clients;
-extern struct paste_stack global_buffers;
int server_start(int, char *);
void server_update_socket(void);
void server_add_accept(int);
@@ -1886,7 +1869,7 @@ void server_add_accept(int);
/* server-client.c */
void server_client_handle_key(struct client *, int);
void server_client_create(int);
-int server_client_open(struct client *, struct session *, char **);
+int server_client_open(struct client *, char **);
void server_client_lost(struct client *);
void server_client_callback(int, short, void *);
void server_client_status_timer(void);
@@ -1940,9 +1923,7 @@ void status_free_jobs(struct status_out_tree *);
void status_update_jobs(struct client *);
void status_set_window_at(struct client *, u_int);
int status_redraw(struct client *);
-char *status_replace(struct client *, struct session *,
- struct winlink *, struct window_pane *, const char *, time_t, int);
-void printflike2 status_message_set(struct client *, const char *, ...);
+void printflike(2, 3) status_message_set(struct client *, const char *, ...);
void status_message_clear(struct client *);
int status_message_redraw(struct client *);
void status_prompt_set(struct client *, const char *, const char *,
@@ -2032,13 +2013,13 @@ void screen_write_start(
struct screen_write_ctx *, struct window_pane *, struct screen *);
void screen_write_stop(struct screen_write_ctx *);
void screen_write_reset(struct screen_write_ctx *);
-size_t printflike2 screen_write_cstrlen(int, const char *, ...);
-void printflike5 screen_write_cnputs(struct screen_write_ctx *,
+size_t printflike(2, 3) screen_write_cstrlen(int, const char *, ...);
+void printflike(5, 6) screen_write_cnputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, int, const char *, ...);
-size_t printflike2 screen_write_strlen(int, const char *, ...);
-void printflike3 screen_write_puts(struct screen_write_ctx *,
+size_t printflike(2, 3) screen_write_strlen(int, const char *, ...);
+void printflike(3, 4) screen_write_puts(struct screen_write_ctx *,
struct grid_cell *, const char *, ...);
-void printflike5 screen_write_nputs(struct screen_write_ctx *,
+void printflike(5, 6) screen_write_nputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, int, const char *, ...);
void screen_write_vnputs(struct screen_write_ctx *,
ssize_t, struct grid_cell *, int, const char *, va_list);
@@ -2121,18 +2102,19 @@ void winlink_stack_remove(struct winlink_stack *, struct winlink *);
int window_index(struct window *, u_int *);
struct window *window_find_by_id(u_int);
struct window *window_create1(u_int, u_int);
-struct window *window_create(const char *, const char *, const char *, int,
- struct environ *, struct termios *, u_int, u_int, u_int,
- char **);
+struct window *window_create(const char *, int, char **, const char *,
+ const char *, int, struct environ *, struct termios *,
+ u_int, u_int, u_int, char **);
void window_destroy(struct window *);
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
void window_set_active_at(struct window *, u_int, u_int);
struct window_pane *window_find_string(struct window *, const char *);
-void window_set_active_pane(struct window *, struct window_pane *);
+int window_set_active_pane(struct window *, struct window_pane *);
struct window_pane *window_add_pane(struct window *, u_int);
void window_resize(struct window *, u_int, u_int);
int window_zoom(struct window_pane *);
int window_unzoom(struct window *);
+void window_lost_pane(struct window *, struct window_pane *);
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 *,
@@ -2146,9 +2128,9 @@ struct window_pane *window_pane_find_by_id(u_int);
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
void window_pane_destroy(struct window_pane *);
void window_pane_timer_start(struct window_pane *);
-int window_pane_spawn(struct window_pane *, const char *,
- const char *, int, struct environ *, struct termios *,
- char **);
+int window_pane_spawn(struct window_pane *, int, char **,
+ const char *, const char *, int, 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 *, int);
@@ -2215,12 +2197,13 @@ void layout_set_active_changed(struct window *);
/* window-clock.c */
extern const struct window_mode window_clock_mode;
+extern const char window_clock_table[14][5][5];
/* 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 printflike2 window_copy_add(struct window_pane *, const char *, ...);
+void printflike(2, 3) 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 *);
@@ -2240,9 +2223,6 @@ struct window_choose_data *window_choose_add_window(struct window_pane *,
struct window_choose_data *window_choose_add_session(struct window_pane *,
struct client *, struct session *, const char *,
const char *, u_int);
-struct window_choose_data *window_choose_add_item(struct window_pane *,
- struct client *, struct winlink *, const char *,
- const char *, u_int);
void window_choose_expand_all(struct window_pane *);
void window_choose_collapse_all(struct window_pane *);
void window_choose_set_current(struct window_pane *, u_int);
@@ -2258,8 +2238,8 @@ void set_signals(void(*)(int, short, void *));
void clear_signals(int);
/* control.c */
-void control_callback(struct client *, int, void*);
-void printflike2 control_write(struct client *, const char *, ...);
+void control_callback(struct client *, int, void *);
+void printflike(2, 3) control_write(struct client *, const char *, ...);
void control_write_buffer(struct client *, struct evbuffer *);
/* control-notify.c */
@@ -2283,20 +2263,20 @@ RB_PROTOTYPE(sessions, session, entry, session_cmp);
int session_alive(struct session *);
struct session *session_find(const char *);
struct session *session_find_by_id(u_int);
-struct session *session_create(const char *, const char *, int,
- struct environ *, struct termios *, int, u_int, u_int,
- char **);
+struct session *session_create(const char *, int, char **, const char *,
+ int, struct environ *, struct termios *, int, u_int,
+ u_int, char **);
void session_destroy(struct session *);
int session_check_name(const char *);
void session_update_activity(struct session *);
struct session *session_next_session(struct session *);
struct session *session_previous_session(struct session *);
-struct winlink *session_new(struct session *, const char *, const char *, int,
- int, char **);
-struct winlink *session_attach(
- struct session *, struct window *, int, char **);
+struct winlink *session_new(struct session *, const char *, int, char **,
+ const char *, int, int, char **);
+struct winlink *session_attach(struct session *, struct window *, int,
+ char **);
int session_detach(struct session *, struct winlink *);
-struct winlink* 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);
@@ -2306,17 +2286,24 @@ struct session_group *session_group_find(struct session *);
u_int session_group_index(struct session_group *);
void session_group_add(struct session *, struct session *);
void session_group_remove(struct session *);
+u_int session_group_count(struct session_group *);
void session_group_synchronize_to(struct session *);
void session_group_synchronize_from(struct session *);
void session_group_synchronize1(struct session *, struct session *);
void session_renumber_windows(struct session *);
/* utf8.c */
-void utf8_build(void);
-int utf8_open(struct utf8_data *, u_char);
-int utf8_append(struct utf8_data *, u_char);
-u_int utf8_combine(const struct utf8_data *);
-u_int utf8_split2(u_int, u_char *);
+void utf8_build(void);
+void utf8_set(struct utf8_data *, u_char);
+int utf8_open(struct utf8_data *, u_char);
+int utf8_append(struct utf8_data *, u_char);
+u_int utf8_combine(const struct utf8_data *);
+u_int utf8_split2(u_int, u_char *);
+int utf8_strvis(char *, const char *, size_t, int);
+struct utf8_data *utf8_fromcstr(const char *);
+char *utf8_tocstr(struct utf8_data *);
+u_int utf8_cstrwidth(const char *);
+char *utf8_trimcstr(const char *, u_int);
/* osdep-*.c */
char *osdep_get_name(int, char *);
@@ -2324,24 +2311,21 @@ char *osdep_get_cwd(int);
struct event_base *osdep_event_init(void);
/* log.c */
-void log_open(int, const char *);
+void log_open(const char *);
void log_close(void);
-void printflike1 log_warn(const char *, ...);
-void printflike1 log_warnx(const char *, ...);
-void printflike1 log_info(const char *, ...);
-void printflike1 log_debug(const char *, ...);
-void printflike1 log_debug2(const char *, ...);
-__dead void printflike1 log_fatal(const char *, ...);
-__dead void printflike1 log_fatalx(const char *, ...);
+void printflike(1, 2) log_debug(const char *, ...);
+__dead void printflike(1, 2) log_fatal(const char *, ...);
+__dead void printflike(1, 2) log_fatalx(const char *, ...);
/* xmalloc.c */
char *xstrdup(const char *);
void *xcalloc(size_t, size_t);
void *xmalloc(size_t);
-void *xrealloc(void *, size_t, size_t);
-int printflike2 xasprintf(char **, const char *, ...);
+void *xrealloc(void *, size_t);
+void *xreallocarray(void *, size_t, size_t);
+int printflike(2, 3) xasprintf(char **, const char *, ...);
int xvasprintf(char **, const char *, va_list);
-int printflike3 xsnprintf(char *, size_t, const char *, ...);
+int printflike(3, 4) xsnprintf(char *, size_t, const char *, ...);
int xvsnprintf(char *, size_t, const char *, va_list);
/* style.c */
@@ -2351,7 +2335,9 @@ const char *style_tostring(struct grid_cell *);
void style_update_new(struct options *, const char *, const char *);
void style_update_old(struct options *, const char *,
struct grid_cell *);
-void style_apply(struct grid_cell *, struct options *, const char *);
-void style_apply_update(struct grid_cell *, struct options *, const char *);
+void style_apply(struct grid_cell *, struct options *,
+ const char *);
+void style_apply_update(struct grid_cell *, struct options *,
+ const char *);
#endif /* TMUX_H */
diff --git a/tools/fix-ids.sh b/tools/fix-ids.sh
deleted file mode 100644
index 4621d2b4..00000000
--- a/tools/fix-ids.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-# $Id$
-
-for i in *.[ch] tmux.1; do
- (head -1 $i|grep '$OpenBSD' >/dev/null) || continue
- mv $i $i~ || exit
- sed 's/\$OpenBSD.* \$/$\Id$/' $i~ >$i || exit
- echo $i
-done
diff --git a/tty-acs.c b/tty-acs.c
index ae84f0d4..5d03c3eb 100644
--- a/tty-acs.c
+++ b/tty-acs.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -81,7 +81,7 @@ tty_acs_get(struct tty *tty, u_char ch)
struct tty_acs_entry *entry;
/* If not a UTF-8 terminal, use the ACS set. */
- if (!(tty->flags & TTY_UTF8)) {
+ if (tty != NULL && !(tty->flags & TTY_UTF8)) {
if (tty->term->acs[ch][0] == '\0')
return (NULL);
return (&tty->term->acs[ch][0]);
diff --git a/tty-keys.c b/tty-keys.c
index 7fb91a84..a987c44b 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -113,14 +113,6 @@ const struct tty_default_key_raw tty_default_raw_keys[] = {
{ "\033[21^", KEYC_F10|KEYC_CTRL },
{ "\033[23^", KEYC_F11|KEYC_CTRL },
{ "\033[24^", KEYC_F12|KEYC_CTRL },
- { "\033[25^", KEYC_F13|KEYC_CTRL },
- { "\033[26^", KEYC_F14|KEYC_CTRL },
- { "\033[28^", KEYC_F15|KEYC_CTRL },
- { "\033[29^", KEYC_F16|KEYC_CTRL },
- { "\033[31^", KEYC_F17|KEYC_CTRL },
- { "\033[32^", KEYC_F18|KEYC_CTRL },
- { "\033[33^", KEYC_F19|KEYC_CTRL },
- { "\033[34^", KEYC_F20|KEYC_CTRL },
{ "\033[2^", KEYC_IC|KEYC_CTRL },
{ "\033[3^", KEYC_DC|KEYC_CTRL },
{ "\033[7^", KEYC_HOME|KEYC_CTRL },
@@ -140,14 +132,6 @@ const struct tty_default_key_raw tty_default_raw_keys[] = {
{ "\033[21$", KEYC_F10|KEYC_SHIFT },
{ "\033[23$", KEYC_F11|KEYC_SHIFT },
{ "\033[24$", KEYC_F12|KEYC_SHIFT },
- { "\033[25$", KEYC_F13|KEYC_SHIFT },
- { "\033[26$", KEYC_F14|KEYC_SHIFT },
- { "\033[28$", KEYC_F15|KEYC_SHIFT },
- { "\033[29$", KEYC_F16|KEYC_SHIFT },
- { "\033[31$", KEYC_F17|KEYC_SHIFT },
- { "\033[32$", KEYC_F18|KEYC_SHIFT },
- { "\033[33$", KEYC_F19|KEYC_SHIFT },
- { "\033[34$", KEYC_F20|KEYC_SHIFT },
{ "\033[2$", KEYC_IC|KEYC_SHIFT },
{ "\033[3$", KEYC_DC|KEYC_SHIFT },
{ "\033[7$", KEYC_HOME|KEYC_SHIFT },
@@ -167,14 +151,6 @@ const struct tty_default_key_raw tty_default_raw_keys[] = {
{ "\033[21@", KEYC_F10|KEYC_CTRL|KEYC_SHIFT },
{ "\033[23@", KEYC_F11|KEYC_CTRL|KEYC_SHIFT },
{ "\033[24@", KEYC_F12|KEYC_CTRL|KEYC_SHIFT },
- { "\033[25@", KEYC_F13|KEYC_CTRL|KEYC_SHIFT },
- { "\033[26@", KEYC_F14|KEYC_CTRL|KEYC_SHIFT },
- { "\033[28@", KEYC_F15|KEYC_CTRL|KEYC_SHIFT },
- { "\033[29@", KEYC_F16|KEYC_CTRL|KEYC_SHIFT },
- { "\033[31@", KEYC_F17|KEYC_CTRL|KEYC_SHIFT },
- { "\033[32@", KEYC_F18|KEYC_CTRL|KEYC_SHIFT },
- { "\033[33@", KEYC_F19|KEYC_CTRL|KEYC_SHIFT },
- { "\033[34@", KEYC_F20|KEYC_CTRL|KEYC_SHIFT },
{ "\033[2@", KEYC_IC|KEYC_CTRL|KEYC_SHIFT },
{ "\033[3@", KEYC_DC|KEYC_CTRL|KEYC_SHIFT },
{ "\033[7@", KEYC_HOME|KEYC_CTRL|KEYC_SHIFT },
@@ -206,14 +182,63 @@ const struct tty_default_key_code tty_default_code_keys[] = {
{ TTYC_KF10, KEYC_F10 },
{ TTYC_KF11, KEYC_F11 },
{ TTYC_KF12, KEYC_F12 },
- { TTYC_KF13, KEYC_F13 },
- { TTYC_KF14, KEYC_F14 },
- { TTYC_KF15, KEYC_F15 },
- { TTYC_KF16, KEYC_F16 },
- { TTYC_KF17, KEYC_F17 },
- { TTYC_KF18, KEYC_F18 },
- { TTYC_KF19, KEYC_F19 },
- { TTYC_KF20, KEYC_F20 },
+
+ { TTYC_KF13, KEYC_F1|KEYC_SHIFT },
+ { TTYC_KF14, KEYC_F2|KEYC_SHIFT },
+ { TTYC_KF15, KEYC_F3|KEYC_SHIFT },
+ { TTYC_KF16, KEYC_F4|KEYC_SHIFT },
+ { TTYC_KF17, KEYC_F5|KEYC_SHIFT },
+ { TTYC_KF18, KEYC_F6|KEYC_SHIFT },
+ { TTYC_KF19, KEYC_F7|KEYC_SHIFT },
+ { TTYC_KF20, KEYC_F8|KEYC_SHIFT },
+ { TTYC_KF21, KEYC_F9|KEYC_SHIFT },
+ { TTYC_KF22, KEYC_F10|KEYC_SHIFT },
+ { TTYC_KF23, KEYC_F11|KEYC_SHIFT },
+ { TTYC_KF24, KEYC_F12|KEYC_SHIFT },
+
+ { TTYC_KF25, KEYC_F1|KEYC_CTRL },
+ { TTYC_KF26, KEYC_F2|KEYC_CTRL },
+ { TTYC_KF27, KEYC_F3|KEYC_CTRL },
+ { TTYC_KF28, KEYC_F4|KEYC_CTRL },
+ { TTYC_KF29, KEYC_F5|KEYC_CTRL },
+ { TTYC_KF30, KEYC_F6|KEYC_CTRL },
+ { TTYC_KF31, KEYC_F7|KEYC_CTRL },
+ { TTYC_KF32, KEYC_F8|KEYC_CTRL },
+ { TTYC_KF33, KEYC_F9|KEYC_CTRL },
+ { TTYC_KF34, KEYC_F10|KEYC_CTRL },
+ { TTYC_KF35, KEYC_F11|KEYC_CTRL },
+ { TTYC_KF36, KEYC_F12|KEYC_CTRL },
+
+ { TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL },
+ { TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL },
+
+ { TTYC_KF49, KEYC_F1|KEYC_ESCAPE },
+ { TTYC_KF50, KEYC_F2|KEYC_ESCAPE },
+ { TTYC_KF51, KEYC_F3|KEYC_ESCAPE },
+ { TTYC_KF52, KEYC_F4|KEYC_ESCAPE },
+ { TTYC_KF53, KEYC_F5|KEYC_ESCAPE },
+ { TTYC_KF54, KEYC_F6|KEYC_ESCAPE },
+ { TTYC_KF55, KEYC_F7|KEYC_ESCAPE },
+ { TTYC_KF56, KEYC_F8|KEYC_ESCAPE },
+ { TTYC_KF57, KEYC_F9|KEYC_ESCAPE },
+ { TTYC_KF58, KEYC_F10|KEYC_ESCAPE },
+ { TTYC_KF59, KEYC_F11|KEYC_ESCAPE },
+ { TTYC_KF60, KEYC_F12|KEYC_ESCAPE },
+
+ { TTYC_KF61, KEYC_F1|KEYC_ESCAPE|KEYC_SHIFT },
+ { TTYC_KF62, KEYC_F2|KEYC_ESCAPE|KEYC_SHIFT },
+ { TTYC_KF63, KEYC_F3|KEYC_ESCAPE|KEYC_SHIFT },
+
{ TTYC_KICH1, KEYC_IC },
{ TTYC_KDCH1, KEYC_DC },
{ TTYC_KHOME, KEYC_HOME },
@@ -357,7 +382,7 @@ tty_keys_build(struct tty *tty)
const char *s;
if (tty->key_tree != NULL)
- tty_keys_free (tty);
+ tty_keys_free(tty);
tty->key_tree = NULL;
for (i = 0; i < nitems(tty_default_raw_keys); i++) {
@@ -475,6 +500,8 @@ tty_keys_next(struct tty *tty)
goto complete_key;
case -1: /* no, or not valid */
break;
+ case -2: /* yes, but we don't care. */
+ goto discard_key;
case 1: /* partial */
goto partial_key;
}
@@ -586,6 +613,14 @@ complete_key:
server_client_handle_key(tty->client, key);
return (1);
+
+discard_key:
+ log_debug("discard key %.*s %#x", (int) size, buf, key);
+
+ /* Remove data from buffer. */
+ evbuffer_drain(tty->event->input, size);
+
+ return (1);
}
/* Key timer callback. */
@@ -730,6 +765,15 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
sgr = 1;
sgr_rel = (c == 'm');
+ /*
+ * Some terminals (like PuTTY 0.63) mistakenly send
+ * button-release events for scroll-wheel button-press event.
+ * Discard it before it reaches any program running inside
+ * tmux.
+ */
+ if (sgr_rel && (sgr_b & 64))
+ return (-2);
+
/* Figure out what b would be in old format. */
b = sgr_b;
if (sgr_rel)
@@ -748,33 +792,43 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
m->sgr_rel = sgr_rel;
m->x = x;
m->y = y;
- if (b & 64) { /* wheel button */
- b &= 3;
+ if (b & MOUSE_MASK_WHEEL) {
+ if (b & MOUSE_MASK_SHIFT)
+ m->scroll = 1;
+ else
+ m->scroll = MOUSE_WHEEL_SCALE;
+ if (b & MOUSE_MASK_META)
+ m->scroll *= MOUSE_WHEEL_SCALE;
+ if (b & MOUSE_MASK_CTRL)
+ m->scroll *= MOUSE_WHEEL_SCALE;
+
+ b &= MOUSE_MASK_BUTTONS;
if (b == 0)
m->wheel = MOUSE_WHEEL_UP;
else if (b == 1)
m->wheel = MOUSE_WHEEL_DOWN;
m->event = MOUSE_EVENT_WHEEL;
- } else if ((b & 3) == 3) {
- if (~m->event & MOUSE_EVENT_DRAG && x == m->x && y == m->y) {
+
+ m->button = 3;
+ } else if ((b & MOUSE_MASK_BUTTONS) == 3) {
+ if (~m->event & MOUSE_EVENT_DRAG && x == m->sx && y == m->sy) {
m->event = MOUSE_EVENT_CLICK;
+ m->clicks = (m->clicks + 1) % 3;
} else
m->event = MOUSE_EVENT_DRAG;
m->event |= MOUSE_EVENT_UP;
} else {
- if (b & 32) /* drag motion */
+ if (b & MOUSE_MASK_DRAG)
m->event = MOUSE_EVENT_DRAG;
else {
- if (m->event & MOUSE_EVENT_UP && x == m->x && y == m->y)
- m->clicks = (m->clicks + 1) % 3;
- else
- m->clicks = 0;
- m->sx = x;
- m->sy = y;
m->event = MOUSE_EVENT_DOWN;
+ if (x != m->sx || y != m->sy)
+ m->clicks = 0;
}
- m->button = (b & 3);
+ m->button = (b & MOUSE_MASK_BUTTONS);
}
+ m->sx = x;
+ m->sy = y;
return (0);
}
diff --git a/tty-term.c b/tty-term.c
index a3292eb6..365da5fb 100644
--- a/tty-term.c
+++ b/tty-term.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -57,6 +57,7 @@ const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
{ TTYC_CUP, TTYCODE_STRING, "cup" },
{ TTYC_CUU, TTYCODE_STRING, "cuu" },
{ TTYC_CUU1, TTYCODE_STRING, "cuu1" },
+ { TTYC_CVVIS, TTYCODE_STRING, "cvvis" },
{ TTYC_DCH, TTYCODE_STRING, "dch" },
{ TTYC_DCH1, TTYCODE_STRING, "dch1" },
{ TTYC_DIM, TTYCODE_STRING, "dim" },
@@ -116,10 +117,53 @@ const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
{ TTYC_KF19, TTYCODE_STRING, "kf19" },
{ TTYC_KF2, TTYCODE_STRING, "kf2" },
{ TTYC_KF20, TTYCODE_STRING, "kf20" },
+ { TTYC_KF21, TTYCODE_STRING, "kf21" },
+ { TTYC_KF22, TTYCODE_STRING, "kf22" },
+ { TTYC_KF23, TTYCODE_STRING, "kf23" },
+ { TTYC_KF24, TTYCODE_STRING, "kf24" },
+ { TTYC_KF25, TTYCODE_STRING, "kf25" },
+ { TTYC_KF26, TTYCODE_STRING, "kf26" },
+ { TTYC_KF27, TTYCODE_STRING, "kf27" },
+ { TTYC_KF28, TTYCODE_STRING, "kf28" },
+ { TTYC_KF29, TTYCODE_STRING, "kf29" },
{ TTYC_KF3, TTYCODE_STRING, "kf3" },
+ { TTYC_KF30, TTYCODE_STRING, "kf30" },
+ { TTYC_KF31, TTYCODE_STRING, "kf31" },
+ { TTYC_KF32, TTYCODE_STRING, "kf32" },
+ { TTYC_KF33, TTYCODE_STRING, "kf33" },
+ { TTYC_KF34, TTYCODE_STRING, "kf34" },
+ { TTYC_KF35, TTYCODE_STRING, "kf35" },
+ { TTYC_KF36, TTYCODE_STRING, "kf36" },
+ { TTYC_KF37, TTYCODE_STRING, "kf37" },
+ { TTYC_KF38, TTYCODE_STRING, "kf38" },
+ { TTYC_KF39, TTYCODE_STRING, "kf39" },
{ TTYC_KF4, TTYCODE_STRING, "kf4" },
+ { TTYC_KF40, TTYCODE_STRING, "kf40" },
+ { TTYC_KF41, TTYCODE_STRING, "kf41" },
+ { TTYC_KF42, TTYCODE_STRING, "kf42" },
+ { TTYC_KF43, TTYCODE_STRING, "kf43" },
+ { TTYC_KF44, TTYCODE_STRING, "kf44" },
+ { TTYC_KF45, TTYCODE_STRING, "kf45" },
+ { TTYC_KF46, TTYCODE_STRING, "kf46" },
+ { TTYC_KF47, TTYCODE_STRING, "kf47" },
+ { TTYC_KF48, TTYCODE_STRING, "kf48" },
+ { TTYC_KF49, TTYCODE_STRING, "kf49" },
{ TTYC_KF5, TTYCODE_STRING, "kf5" },
+ { TTYC_KF50, TTYCODE_STRING, "kf50" },
+ { TTYC_KF51, TTYCODE_STRING, "kf51" },
+ { TTYC_KF52, TTYCODE_STRING, "kf52" },
+ { TTYC_KF53, TTYCODE_STRING, "kf53" },
+ { TTYC_KF54, TTYCODE_STRING, "kf54" },
+ { TTYC_KF55, TTYCODE_STRING, "kf55" },
+ { TTYC_KF56, TTYCODE_STRING, "kf56" },
+ { TTYC_KF57, TTYCODE_STRING, "kf57" },
+ { TTYC_KF58, TTYCODE_STRING, "kf58" },
+ { TTYC_KF59, TTYCODE_STRING, "kf59" },
{ TTYC_KF6, TTYCODE_STRING, "kf6" },
+ { TTYC_KF60, TTYCODE_STRING, "kf60" },
+ { TTYC_KF61, TTYCODE_STRING, "kf61" },
+ { TTYC_KF62, TTYCODE_STRING, "kf62" },
+ { TTYC_KF63, TTYCODE_STRING, "kf63" },
{ TTYC_KF7, TTYCODE_STRING, "kf7" },
{ TTYC_KF8, TTYCODE_STRING, "kf8" },
{ TTYC_KF9, TTYCODE_STRING, "kf9" },
@@ -308,7 +352,7 @@ tty_term_override(struct tty_term *term, const char *overrides)
}
struct tty_term *
-tty_term_find(char *name, int fd, const char *overrides, char **cause)
+tty_term_find(char *name, int fd, char **cause)
{
struct tty_term *term;
const struct tty_term_code_entry *ent;
@@ -386,7 +430,10 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
break;
}
}
- tty_term_override(term, overrides);
+
+ /* Apply terminal overrides. */
+ s = options_get_string(&global_options, "terminal-overrides");
+ tty_term_override(term, s);
/* Delete curses data. */
#if !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR > 5 || \
@@ -509,7 +556,8 @@ tty_term_ptr1(struct tty_term *term, enum tty_code_code code, const void *a)
}
const char *
-tty_term_ptr2(struct tty_term *term, enum tty_code_code code, const void *a, const void *b)
+tty_term_ptr2(struct tty_term *term, enum tty_code_code code, const void *a,
+ const void *b)
{
return (tparm((char *) tty_term_string(term, code), a, b, 0, 0, 0, 0, 0, 0, 0));
}
diff --git a/tty.c b/tty.c
index eb2511c9..1bb89811 100644
--- a/tty.c
+++ b/tty.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -128,7 +128,7 @@ tty_set_size(struct tty *tty, u_int sx, u_int sy) {
}
int
-tty_open(struct tty *tty, const char *overrides, char **cause)
+tty_open(struct tty *tty, char **cause)
{
char out[64];
int fd;
@@ -141,7 +141,7 @@ tty_open(struct tty *tty, const char *overrides, char **cause)
tty->log_fd = fd;
}
- tty->term = tty_term_find(tty->termname, tty->fd, overrides, cause);
+ tty->term = tty_term_find(tty->termname, tty->fd, cause);
if (tty->term == NULL) {
tty_close(tty);
return (-1);
@@ -193,7 +193,7 @@ tty_init_termios(int fd, struct termios *orig_tio, struct bufferevent *bufev)
tio.c_iflag |= IGNBRK;
tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET);
tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL|
- ECHOPRT|ECHOKE|ECHOCTL|ISIG);
+ ECHOPRT|ECHOKE|ISIG);
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSANOW, &tio) == 0)
@@ -281,6 +281,8 @@ tty_stop_tty(struct tty *tty)
else
tty_raw(tty, tty_term_string1(tty->term, TTYC_SS, 0));
}
+ if (tty->mode & MODE_BRACKETPASTE)
+ tty_raw(tty, "\033[?2004l");
tty_raw(tty, tty_term_string(tty->term, TTYC_CR));
tty_raw(tty, tty_term_string(tty->term, TTYC_CNORM));
@@ -290,7 +292,7 @@ tty_stop_tty(struct tty *tty)
if (tty_term_has(tty->term, TTYC_XT)) {
if (tty->flags & TTY_FOCUS) {
tty->flags &= ~TTY_FOCUS;
- tty_puts(tty, "\033[?1004l");
+ tty_raw(tty, "\033[?1004l");
}
}
@@ -388,7 +390,8 @@ tty_putcode_ptr1(struct tty *tty, enum tty_code_code code, const void *a)
}
void
-tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a, const void *b)
+tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a,
+ const void *b)
{
if (a != NULL && b != NULL)
tty_puts(tty, tty_term_ptr2(tty->term, code, a, b));
@@ -481,10 +484,14 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
mode &= ~MODE_CURSOR;
changed = mode ^ tty->mode;
- if (changed & MODE_CURSOR) {
- if (mode & MODE_CURSOR)
- tty_putcode(tty, TTYC_CNORM);
- else
+ if (changed & (MODE_CURSOR|MODE_BLINKING)) {
+ if (mode & MODE_CURSOR) {
+ if (mode & MODE_BLINKING &&
+ tty_term_has(tty->term, TTYC_CVVIS))
+ tty_putcode(tty, TTYC_CVVIS);
+ else
+ tty_putcode(tty, TTYC_CNORM);
+ } else
tty_putcode(tty, TTYC_CIVIS);
}
if (tty->cstyle != s->cstyle) {
@@ -512,16 +519,12 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
tty_puts(tty, "\033[?1005l");
tty_puts(tty, "\033[?1006h");
- if (mode & MODE_MOUSE_ANY)
- tty_puts(tty, "\033[?1003h");
- else if (mode & MODE_MOUSE_BUTTON)
+ if (mode & MODE_MOUSE_BUTTON)
tty_puts(tty, "\033[?1002h");
else if (mode & MODE_MOUSE_STANDARD)
tty_puts(tty, "\033[?1000h");
} else {
- if (tty->mode & MODE_MOUSE_ANY)
- tty_puts(tty, "\033[?1003l");
- else if (tty->mode & MODE_MOUSE_BUTTON)
+ if (tty->mode & MODE_MOUSE_BUTTON)
tty_puts(tty, "\033[?1002l");
else if (tty->mode & MODE_MOUSE_STANDARD)
tty_puts(tty, "\033[?1000l");
@@ -547,8 +550,8 @@ tty_update_mode(struct tty *tty, int mode, struct screen *s)
}
void
-tty_emulate_repeat(
- struct tty *tty, enum tty_code_code code, enum tty_code_code code1, u_int n)
+tty_emulate_repeat(struct tty *tty, enum tty_code_code code,
+ enum tty_code_code code1, u_int n)
{
if (tty_term_has(tty->term, code))
tty_putcode1(tty, code, n);
diff --git a/utf8.c b/utf8.c
index 63723d7f..39e708ba 100644
--- a/utf8.c
+++ b/utf8.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,7 @@
#include <sys/types.h>
+#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -200,6 +201,16 @@ int utf8_overlap(struct utf8_width_entry *, struct utf8_width_entry *);
u_int utf8_combine(const struct utf8_data *);
u_int utf8_width(const struct utf8_data *);
+/* Set a single character. */
+void
+utf8_set(struct utf8_data *utf8data, u_char ch)
+{
+ *utf8data->data = ch;
+ utf8data->size = 1;
+
+ utf8data->width = 1;
+}
+
/*
* Open UTF-8 sequence.
*
@@ -248,8 +259,7 @@ utf8_append(struct utf8_data *utf8data, u_char ch)
/* Check if two width tree entries overlap. */
int
-utf8_overlap(
- struct utf8_width_entry *item1, struct utf8_width_entry *item2)
+utf8_overlap(struct utf8_width_entry *item1, struct utf8_width_entry *item2)
{
if (item1->first >= item2->first && item1->first <= item2->last)
return (1);
@@ -313,7 +323,7 @@ utf8_combine(const struct utf8_data *utf8data)
value = utf8data->data[3] & 0x3f;
value |= (utf8data->data[2] & 0x3f) << 6;
value |= (utf8data->data[1] & 0x3f) << 12;
- value |= (utf8data->data[0] & 0x3f) << 18;
+ value |= (utf8data->data[0] & 0x07) << 18;
break;
}
return (value);
@@ -352,3 +362,153 @@ utf8_width(const struct utf8_data *utf8data)
}
return (1);
}
+
+/*
+ * Encode len characters from src into dst, which is guaranteed to have four
+ * bytes available for each character from src (for \abc or UTF-8) plus space
+ * for \0.
+ */
+int
+utf8_strvis(char *dst, const char *src, size_t len, int flag)
+{
+ struct utf8_data utf8data;
+ const char *start, *end;
+ int more;
+ size_t i;
+
+ start = dst;
+ end = src + len;
+
+ while (src < end) {
+ if (utf8_open(&utf8data, *src)) {
+ more = 1;
+ while (++src < end && more)
+ more = utf8_append(&utf8data, *src);
+ if (!more) {
+ /* UTF-8 character finished. */
+ for (i = 0; i < utf8data.size; i++)
+ *dst++ = utf8data.data[i];
+ continue;
+ } else if (utf8data.have > 0) {
+ /* Not a complete UTF-8 character. */
+ src -= utf8data.have;
+ }
+ }
+ if (src < end - 1)
+ dst = vis(dst, src[0], flag, src[1]);
+ else if (src < end)
+ dst = vis(dst, src[0], flag, '\0');
+ src++;
+ }
+
+ *dst = '\0';
+ return (dst - start);
+}
+
+/*
+ * Convert a string into a buffer of UTF-8 characters. Terminated by size == 0.
+ * Caller frees.
+ */
+struct utf8_data *
+utf8_fromcstr(const char *src)
+{
+ struct utf8_data *dst;
+ size_t n;
+ int more;
+
+ dst = NULL;
+
+ n = 0;
+ while (*src != '\0') {
+ dst = xreallocarray(dst, n + 1, sizeof *dst);
+ if (utf8_open(&dst[n], *src)) {
+ more = 1;
+ while (*++src != '\0' && more)
+ more = utf8_append(&dst[n], *src);
+ if (!more) {
+ n++;
+ continue;
+ }
+ src -= dst[n].have;
+ }
+ utf8_set(&dst[n], *src);
+ src++;
+
+ n++;
+ }
+
+ dst = xreallocarray(dst, n + 1, sizeof *dst);
+ dst[n].size = 0;
+ return (dst);
+}
+
+/* Convert from a buffer of UTF-8 characters into a string. Caller frees. */
+char *
+utf8_tocstr(struct utf8_data *src)
+{
+ char *dst;
+ size_t n;
+
+ dst = NULL;
+
+ n = 0;
+ for(; src->size != 0; src++) {
+ dst = xreallocarray(dst, n + src->size, 1);
+ memcpy(dst + n, src->data, src->size);
+ n += src->size;
+ }
+
+ dst = xreallocarray(dst, n + 1, 1);
+ dst[n] = '\0';
+ return (dst);
+}
+
+/* Get width of UTF-8 string. */
+u_int
+utf8_cstrwidth(const char *s)
+{
+ struct utf8_data tmp;
+ u_int width;
+ int more;
+
+ width = 0;
+ while (*s != '\0') {
+ if (utf8_open(&tmp, *s)) {
+ more = 1;
+ while (*++s != '\0' && more)
+ more = utf8_append(&tmp, *s);
+ if (!more) {
+ width += tmp.width;
+ continue;
+ }
+ s -= tmp.have;
+ }
+ width++;
+ s++;
+ }
+ return (width);
+}
+
+/* Trim UTF-8 string to width. Caller frees. */
+char *
+utf8_trimcstr(const char *s, u_int width)
+{
+ struct utf8_data *tmp, *next;
+ char *out;
+ u_int at;
+
+ tmp = utf8_fromcstr(s);
+
+ at = 0;
+ for (next = tmp; next->size != 0; next++) {
+ if (at + next->width > width) {
+ next->size = 0;
+ break;
+ }
+ at += next->width;
+ }
+
+ out = utf8_tocstr(tmp);
+ free(tmp);
+ return (out);
+}
diff --git a/window-choose.c b/window-choose.c
index 7b2b32b9..69141676 100644
--- a/window-choose.c
+++ b/window-choose.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -98,7 +98,7 @@ window_choose_add(struct window_pane *wp, struct window_choose_data *wcd)
item->pos = ARRAY_LENGTH(&data->list) - 1;
item->state = 0;
- data->width = xsnprintf (tmp, sizeof tmp , "%u", item->pos);
+ data->width = xsnprintf(tmp, sizeof tmp , "%u", item->pos);
}
void
@@ -317,7 +317,7 @@ window_choose_prompt_input(enum window_choose_input_type input_type,
data->input_prompt = prompt;
input_len = strlen(data->input_str) + 2;
- data->input_str = xrealloc(data->input_str, 1, input_len);
+ data->input_str = xrealloc(data->input_str, input_len);
data->input_str[input_len - 2] = key;
data->input_str[input_len - 1] = '\0';
@@ -330,14 +330,12 @@ window_choose_collapse(struct window_pane *wp, struct session *s)
struct window_choose_mode_data *data = wp->modedata;
struct window_choose_mode_item *item, *chosen;
struct window_choose_data *wcd;
- u_int i, pos;
+ u_int i;
ARRAY_DECL(, struct window_choose_mode_item) list_copy;
ARRAY_INIT(&list_copy);
- pos = data->selected;
-
- chosen = &ARRAY_ITEM(&data->list, pos);
+ chosen = &ARRAY_ITEM(&data->list, data->selected);
chosen->state &= ~TREE_EXPANDED;
/*
@@ -353,9 +351,8 @@ window_choose_collapse(struct window_pane *wp, struct session *s)
/* We only show the session when collapsed. */
if (wcd->type & TREE_SESSION) {
item->state &= ~TREE_EXPANDED;
+ ARRAY_ADD(&list_copy, *item);
- ARRAY_ADD(&list_copy,
- ARRAY_ITEM(&data->list, i));
/*
* Update the selection to this session item so
* we don't end up highlighting a non-existent
@@ -679,6 +676,29 @@ window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM,
"Goto Item", wp, key);
break;
+ case MODEKEYCHOICE_STARTOFLIST:
+ data->selected = 0;
+ data->top = 0;
+ window_choose_redraw_screen(wp);
+ break;
+ case MODEKEYCHOICE_TOPLINE:
+ data->selected = data->top;
+ window_choose_redraw_screen(wp);
+ break;
+ case MODEKEYCHOICE_BOTTOMLINE:
+ data->selected = data->top + screen_size_y(s) - 1;
+ if (data->selected > items - 1)
+ data->selected = items - 1;
+ window_choose_redraw_screen(wp);
+ break;
+ case MODEKEYCHOICE_ENDOFLIST:
+ data->selected = items - 1;
+ if (screen_size_y(s) < items)
+ data->top = items - screen_size_y(s);
+ else
+ data->top = 0;
+ window_choose_redraw_screen(wp);
+ break;
default:
idx = window_choose_index_key(data, key);
if (idx < 0 || (u_int) idx >= ARRAY_LENGTH(&data->list))
@@ -692,13 +712,30 @@ window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
}
void
-window_choose_mouse(
- struct window_pane *wp, unused struct session *sess, struct mouse_event *m)
+window_choose_mouse(struct window_pane *wp, struct session *sess,
+ struct mouse_event *m)
{
struct window_choose_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
struct window_choose_mode_item *item;
- u_int idx;
+ u_int idx, i, n;
+
+ if (m->event == MOUSE_EVENT_WHEEL) {
+ /*
+ * Multiple line scrolling by default is annoying, so scale
+ * m->scroll back down.
+ */
+ n = m->scroll;
+ if (n >= MOUSE_WHEEL_SCALE)
+ n /= MOUSE_WHEEL_SCALE;
+ for (i = 0; i < n; i++) {
+ if (m->wheel == MOUSE_WHEEL_UP)
+ window_choose_key(wp, sess, KEYC_UP);
+ else
+ window_choose_key(wp, sess, KEYC_DOWN);
+ }
+ return;
+ }
if (~m->event & MOUSE_EVENT_CLICK)
return;
@@ -747,9 +784,9 @@ window_choose_write_line(
key = window_choose_key_index(data, data->top + py);
if (key != -1)
- xsnprintf (label, sizeof label, "(%c)", key);
+ xsnprintf(label, sizeof label, "(%c)", key);
else
- xsnprintf (label, sizeof label, "(%d)", item->pos);
+ xsnprintf(label, sizeof label, "(%d)", item->pos);
screen_write_nputs(ctx, screen_size_x(s) - 1, &gc, utf8flag,
"%*s %s %s", data->width + 2, label,
/*
@@ -882,7 +919,7 @@ window_choose_add_session(struct window_pane *wp, struct client *c,
wcd->ft_template = xstrdup(template);
format_add(wcd->ft, "line", "%u", idx);
- format_session(wcd->ft, s);
+ format_defaults(wcd->ft, NULL, s, NULL, NULL);
wcd->command = cmd_template_replace(action, s->name, 1);
@@ -892,36 +929,6 @@ window_choose_add_session(struct window_pane *wp, struct client *c,
}
struct window_choose_data *
-window_choose_add_item(struct window_pane *wp, struct client *c,
- struct winlink *wl, const char *template, const char *action, u_int idx)
-{
- struct window_choose_data *wcd;
- char *expanded;
-
- wcd = window_choose_data_create(TREE_OTHER, c, c->session);
- wcd->idx = wl->idx;
-
- wcd->ft_template = xstrdup(template);
- format_add(wcd->ft, "line", "%u", idx);
- format_session(wcd->ft, wcd->start_session);
- format_winlink(wcd->ft, wcd->start_session, wl);
- format_window_pane(wcd->ft, wl->window->active);
-
- /*
- * Interpolate action here, since the data we pass back is the expanded
- * template itself.
- */
- xasprintf(&expanded, "%s", format_expand(wcd->ft, wcd->ft_template));
- wcd->command = cmd_template_replace(action, expanded, 1);
- free(expanded);
-
- window_choose_add(wp, wcd);
-
- return (wcd);
-
-}
-
-struct window_choose_data *
window_choose_add_window(struct window_pane *wp, struct client *c,
struct session *s, struct winlink *wl, const char *template,
const char *action, u_int idx)
@@ -939,9 +946,7 @@ window_choose_add_window(struct window_pane *wp, struct client *c,
wcd->ft_template = xstrdup(template);
format_add(wcd->ft, "line", "%u", idx);
- format_session(wcd->ft, s);
- format_winlink(wcd->ft, s, wl);
- format_window_pane(wcd->ft, wl->window->active);
+ format_defaults(wcd->ft, NULL, s, wl, NULL);
xasprintf(&expanded, "%s:%d", s->name, wl->idx);
wcd->command = cmd_template_replace(action, expanded, 1);
diff --git a/window-clock.c b/window-clock.c
index 61cf1502..ede8df5b 100644
--- a/window-clock.c
+++ b/window-clock.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -46,6 +46,79 @@ struct window_clock_mode_data {
time_t tim;
};
+const char window_clock_table[14][5][5] = {
+ { { 1,1,1,1,1 }, /* 0 */
+ { 1,0,0,0,1 },
+ { 1,0,0,0,1 },
+ { 1,0,0,0,1 },
+ { 1,1,1,1,1 } },
+ { { 0,0,0,0,1 }, /* 1 */
+ { 0,0,0,0,1 },
+ { 0,0,0,0,1 },
+ { 0,0,0,0,1 },
+ { 0,0,0,0,1 } },
+ { { 1,1,1,1,1 }, /* 2 */
+ { 0,0,0,0,1 },
+ { 1,1,1,1,1 },
+ { 1,0,0,0,0 },
+ { 1,1,1,1,1 } },
+ { { 1,1,1,1,1 }, /* 3 */
+ { 0,0,0,0,1 },
+ { 1,1,1,1,1 },
+ { 0,0,0,0,1 },
+ { 1,1,1,1,1 } },
+ { { 1,0,0,0,1 }, /* 4 */
+ { 1,0,0,0,1 },
+ { 1,1,1,1,1 },
+ { 0,0,0,0,1 },
+ { 0,0,0,0,1 } },
+ { { 1,1,1,1,1 }, /* 5 */
+ { 1,0,0,0,0 },
+ { 1,1,1,1,1 },
+ { 0,0,0,0,1 },
+ { 1,1,1,1,1 } },
+ { { 1,1,1,1,1 }, /* 6 */
+ { 1,0,0,0,0 },
+ { 1,1,1,1,1 },
+ { 1,0,0,0,1 },
+ { 1,1,1,1,1 } },
+ { { 1,1,1,1,1 }, /* 7 */
+ { 0,0,0,0,1 },
+ { 0,0,0,0,1 },
+ { 0,0,0,0,1 },
+ { 0,0,0,0,1 } },
+ { { 1,1,1,1,1 }, /* 8 */
+ { 1,0,0,0,1 },
+ { 1,1,1,1,1 },
+ { 1,0,0,0,1 },
+ { 1,1,1,1,1 } },
+ { { 1,1,1,1,1 }, /* 9 */
+ { 1,0,0,0,1 },
+ { 1,1,1,1,1 },
+ { 0,0,0,0,1 },
+ { 1,1,1,1,1 } },
+ { { 0,0,0,0,0 }, /* : */
+ { 0,0,1,0,0 },
+ { 0,0,0,0,0 },
+ { 0,0,1,0,0 },
+ { 0,0,0,0,0 } },
+ { { 1,1,1,1,1 }, /* A */
+ { 1,0,0,0,1 },
+ { 1,1,1,1,1 },
+ { 1,0,0,0,1 },
+ { 1,0,0,0,1 } },
+ { { 1,1,1,1,1 }, /* P */
+ { 1,0,0,0,1 },
+ { 1,1,1,1,1 },
+ { 1,0,0,0,0 },
+ { 1,0,0,0,0 } },
+ { { 1,0,0,0,1 }, /* M */
+ { 1,1,0,1,1 },
+ { 1,0,1,0,1 },
+ { 1,0,0,0,1 },
+ { 1,0,0,0,1 } },
+};
+
struct screen *
window_clock_init(struct window_pane *wp)
{
@@ -114,11 +187,77 @@ window_clock_draw_screen(struct window_pane *wp)
struct window_clock_mode_data *data = wp->modedata;
struct screen_write_ctx ctx;
int colour, style;
+ struct screen *s = &data->screen;
+ struct grid_cell gc;
+ char tim[64], *ptr;
+ time_t t;
+ struct tm *tm;
+ u_int i, j, x, y, idx;
colour = options_get_number(&wp->window->options, "clock-mode-colour");
style = options_get_number(&wp->window->options, "clock-mode-style");
- screen_write_start(&ctx, NULL, &data->screen);
- clock_draw(&ctx, colour, style);
+ screen_write_start(&ctx, NULL, s);
+
+ t = time(NULL);
+ tm = localtime(&t);
+ if (style == 0) {
+ strftime(tim, sizeof tim, "%l:%M ", localtime(&t));
+ if (tm->tm_hour >= 12)
+ strlcat(tim, "PM", sizeof tim);
+ else
+ strlcat(tim, "AM", sizeof tim);
+ } else
+ strftime(tim, sizeof tim, "%H:%M", tm);
+
+ screen_write_clearscreen(&ctx);
+
+ if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) {
+ if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) {
+ x = (screen_size_x(s) / 2) - (strlen(tim) / 2);
+ y = screen_size_y(s) / 2;
+ screen_write_cursormove(&ctx, x, y);
+
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ colour_set_fg(&gc, colour);
+ screen_write_puts(&ctx, &gc, "%s", tim);
+ }
+
+
+ screen_write_stop(&ctx);
+ return;
+ }
+
+ x = (screen_size_x(s) / 2) - 3 * strlen(tim);
+ y = (screen_size_y(s) / 2) - 3;
+
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ colour_set_bg(&gc, colour);
+ for (ptr = tim; *ptr != '\0'; ptr++) {
+ if (*ptr >= '0' && *ptr <= '9')
+ idx = *ptr - '0';
+ else if (*ptr == ':')
+ idx = 10;
+ else if (*ptr == 'A')
+ idx = 11;
+ else if (*ptr == 'P')
+ idx = 12;
+ else if (*ptr == 'M')
+ idx = 13;
+ else {
+ x += 6;
+ continue;
+ }
+
+ for (j = 0; j < 5; j++) {
+ for (i = 0; i < 5; i++) {
+ screen_write_cursormove(&ctx, x + i, y + j);
+ if (window_clock_table[idx][j][i])
+ screen_write_putc(&ctx, &gc, ' ');
+ }
+ }
+ x += 6;
+ }
+
screen_write_stop(&ctx);
}
diff --git a/window-copy.c b/window-copy.c
index 527c95c2..223df88a 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,23 +30,24 @@ void window_copy_resize(struct window_pane *, u_int, u_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 session *, struct mouse_event *);
+void window_copy_mouse(struct window_pane *, struct session *,
+ struct mouse_event *);
+void window_copy_redraw_selection(struct window_pane *, u_int);
void window_copy_redraw_lines(struct window_pane *, u_int, u_int);
void window_copy_redraw_screen(struct window_pane *);
-void window_copy_write_line(
- struct window_pane *, struct screen_write_ctx *, u_int);
-void window_copy_write_lines(
- struct window_pane *, struct screen_write_ctx *, u_int, u_int);
+void window_copy_write_line(struct window_pane *, struct screen_write_ctx *,
+ u_int);
+void window_copy_write_lines(struct window_pane *,
+ struct screen_write_ctx *, u_int, u_int);
void window_copy_scroll_to(struct window_pane *, u_int, u_int);
-int window_copy_search_compare(
- struct grid *, u_int, u_int, struct grid *, u_int, int);
-int window_copy_search_lr(
- struct grid *, struct grid *, u_int *, u_int, u_int, u_int, int);
-int window_copy_search_rl(
- struct grid *, struct grid *, u_int *, u_int, u_int, u_int, int);
+int window_copy_search_compare(struct grid *, u_int, u_int, struct grid *,
+ u_int, int);
+int window_copy_search_lr(struct grid *, struct grid *, u_int *, u_int,
+ u_int, u_int, int);
+int window_copy_search_rl(struct grid *, struct grid *, u_int *, u_int,
+ u_int, u_int, int);
void window_copy_search_up(struct window_pane *, const char *);
void window_copy_search_down(struct window_pane *, const char *);
void window_copy_goto_line(struct window_pane *, const char *);
@@ -54,13 +55,15 @@ 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 *, int);
void *window_copy_get_selection(struct window_pane *, size_t *);
-void window_copy_copy_buffer(struct window_pane *, int, void *, size_t);
-void window_copy_copy_pipe(
- struct window_pane *, struct session *, int, const char *);
-void window_copy_copy_selection(struct window_pane *, int);
+void window_copy_copy_buffer(struct window_pane *, const char *, void *,
+ size_t);
+void window_copy_copy_pipe(struct window_pane *, struct session *,
+ const char *, const char *);
+void window_copy_copy_selection(struct window_pane *, const char *);
+void window_copy_append_selection(struct window_pane *, const char *);
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);
+void window_copy_copy_line(struct window_pane *, char **, size_t *, u_int,
+ u_int, u_int);
int window_copy_in_set(struct window_pane *, u_int, u_int, const char *);
u_int window_copy_find_length(struct window_pane *, u_int);
void window_copy_cursor_start_of_line(struct window_pane *);
@@ -93,6 +96,7 @@ const struct window_mode window_copy_mode = {
enum window_copy_input_type {
WINDOW_COPY_OFF,
+ WINDOW_COPY_NAMEDBUFFER,
WINDOW_COPY_NUMERICPREFIX,
WINDOW_COPY_SEARCHUP,
WINDOW_COPY_SEARCHDOWN,
@@ -196,6 +200,7 @@ window_copy_init(struct window_pane *wp)
mode_key_init(&data->mdata, &mode_key_tree_emacs_copy);
else
mode_key_init(&data->mdata, &mode_key_tree_vi_copy);
+ s->sel.modekeys = keys;
data->backing = NULL;
@@ -235,7 +240,6 @@ window_copy_init_for_output(struct window_pane *wp)
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
@@ -276,7 +280,7 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
struct screen_write_ctx back_ctx, ctx;
struct grid_cell gc;
int utf8flag;
- u_int old_hsize;
+ u_int old_hsize, old_cy;
if (backing == &wp->base)
return;
@@ -295,6 +299,7 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
screen_write_linefeed(&back_ctx, 0);
} else
data->backing_written = 1;
+ old_cy = backing->cy;
screen_write_vnputs(&back_ctx, 0, &gc, utf8flag, fmt, ap);
screen_write_stop(&back_ctx);
@@ -309,9 +314,8 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
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);
+ /* Write the new lines. */
+ window_copy_redraw_lines(wp, old_cy, backing->cy - old_cy + 1);
screen_write_stop(&ctx);
}
@@ -341,9 +345,9 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
struct screen *s = &data->screen;
struct screen_write_ctx ctx;
- screen_resize(s, sx, sy, 0);
+ screen_resize(s, sx, sy, 1);
if (data->backing != &wp->base)
- screen_resize(data->backing, sx, sy, 0);
+ screen_resize(data->backing, sx, sy, 1);
if (data->cy > sy - 1)
data->cy = sy - 1;
@@ -370,7 +374,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
u_int n;
int np, keys;
enum mode_key_cmd cmd;
- const char *arg;
+ const char *arg, *ss;
np = data->numprefix;
if (np <= 0)
@@ -386,13 +390,16 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
if (data->inputtype == WINDOW_COPY_JUMPFORWARD) {
for (; np != 0; np--)
window_copy_cursor_jump(wp);
- } else if (data->inputtype == WINDOW_COPY_JUMPBACK) {
+ }
+ if (data->inputtype == WINDOW_COPY_JUMPBACK) {
for (; np != 0; np--)
window_copy_cursor_jump_back(wp);
- } else if (data->inputtype == WINDOW_COPY_JUMPTOFORWARD) {
+ }
+ if (data->inputtype == WINDOW_COPY_JUMPTOFORWARD) {
for (; np != 0; np--)
window_copy_cursor_jump_to(wp);
- } else if (data->inputtype == WINDOW_COPY_JUMPTOBACK) {
+ }
+ if (data->inputtype == WINDOW_COPY_JUMPTOBACK) {
for (; np != 0; np--)
window_copy_cursor_jump_to_back(wp);
}
@@ -414,11 +421,18 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
cmd = mode_key_lookup(&data->mdata, key, &arg);
switch (cmd) {
+ case MODEKEYCOPY_APPENDSELECTION:
+ if (sess != NULL) {
+ window_copy_append_selection(wp, NULL);
+ window_pane_reset_mode(wp);
+ return;
+ }
+ break;
case MODEKEYCOPY_CANCEL:
window_pane_reset_mode(wp);
return;
case MODEKEYCOPY_OTHEREND:
- for (; np != 0; np--)
+ if (np % 2)
window_copy_other_end(wp);
break;
case MODEKEYCOPY_LEFT:
@@ -517,11 +531,15 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
window_copy_redraw_screen(wp);
break;
case MODEKEYCOPY_STARTSELECTION:
+ s->sel.lineflag = LINE_SEL_NONE;
window_copy_start_selection(wp);
window_copy_redraw_screen(wp);
break;
- case MODEKEYCOPY_COPYLINE:
case MODEKEYCOPY_SELECTLINE:
+ s->sel.lineflag = LINE_SEL_LEFT_RIGHT;
+ data->rectflag = 0;
+ /* FALLTHROUGH */
+ case MODEKEYCOPY_COPYLINE:
window_copy_cursor_start_of_line(wp);
/* FALLTHROUGH */
case MODEKEYCOPY_COPYENDOFLINE:
@@ -535,7 +553,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
if (sess != NULL &&
(cmd == MODEKEYCOPY_COPYLINE ||
cmd == MODEKEYCOPY_COPYENDOFLINE)) {
- window_copy_copy_selection(wp, -1);
+ window_copy_copy_selection(wp, NULL);
window_pane_reset_mode(wp);
return;
}
@@ -546,14 +564,14 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
break;
case MODEKEYCOPY_COPYPIPE:
if (sess != NULL) {
- window_copy_copy_pipe(wp, sess, data->numprefix, arg);
+ window_copy_copy_pipe(wp, sess, NULL, arg);
window_pane_reset_mode(wp);
return;
}
break;
case MODEKEYCOPY_COPYSELECTION:
if (sess != NULL) {
- window_copy_copy_selection(wp, data->numprefix);
+ window_copy_copy_selection(wp, NULL);
window_pane_reset_mode(wp);
return;
}
@@ -668,32 +686,27 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
case WINDOW_COPY_JUMPBACK:
case WINDOW_COPY_JUMPTOFORWARD:
case WINDOW_COPY_JUMPTOBACK:
+ case WINDOW_COPY_NAMEDBUFFER:
case WINDOW_COPY_NUMERICPREFIX:
break;
case WINDOW_COPY_SEARCHUP:
+ ss = data->searchstr;
if (cmd == MODEKEYCOPY_SEARCHAGAIN) {
- for (; np != 0; np--) {
- window_copy_search_up(
- wp, data->searchstr);
- }
+ for (; np != 0; np--)
+ window_copy_search_up(wp, ss);
} else {
- for (; np != 0; np--) {
- window_copy_search_down(
- wp, data->searchstr);
- }
+ for (; np != 0; np--)
+ window_copy_search_down(wp, ss);
}
break;
case WINDOW_COPY_SEARCHDOWN:
+ ss = data->searchstr;
if (cmd == MODEKEYCOPY_SEARCHAGAIN) {
- for (; np != 0; np--) {
- window_copy_search_down(
- wp, data->searchstr);
- }
+ for (; np != 0; np--)
+ window_copy_search_down(wp, ss);
} else {
- for (; np != 0; np--) {
- window_copy_search_up(
- wp, data->searchstr);
- }
+ for (; np != 0; np--)
+ window_copy_search_up(wp, ss);
}
break;
}
@@ -703,6 +716,11 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
data->inputprompt = "Goto Line";
*data->inputstr = '\0';
goto input_on;
+ case MODEKEYCOPY_STARTNAMEDBUFFER:
+ data->inputtype = WINDOW_COPY_NAMEDBUFFER;
+ data->inputprompt = "Buffer";
+ *data->inputstr = '\0';
+ goto input_on;
case MODEKEYCOPY_STARTNUMBERPREFIX:
key &= KEYC_MASK_KEY;
if (key >= '0' && key <= '9') {
@@ -713,6 +731,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
}
break;
case MODEKEYCOPY_RECTANGLETOGGLE:
+ s->sel.lineflag = LINE_SEL_NONE;
window_copy_rectangle_toggle(wp);
break;
default:
@@ -768,7 +787,7 @@ window_copy_key_input(struct window_pane *wp, int key)
*data->inputstr = '\0';
break;
case MODEKEYEDIT_PASTE:
- if ((pb = paste_get_top(&global_buffers)) == NULL)
+ if ((pb = paste_get_top()) == NULL)
break;
for (n = 0; n < pb->size; n++) {
ch = (u_char) pb->data[n];
@@ -777,7 +796,7 @@ window_copy_key_input(struct window_pane *wp, int key)
}
inputlen = strlen(data->inputstr);
- data->inputstr = xrealloc(data->inputstr, 1, inputlen + n + 1);
+ data->inputstr = xrealloc(data->inputstr, inputlen + n + 1);
memcpy(data->inputstr + inputlen, pb->data, n);
data->inputstr[inputlen + n] = '\0';
break;
@@ -806,6 +825,11 @@ window_copy_key_input(struct window_pane *wp, int key)
data->searchtype = data->inputtype;
data->searchstr = xstrdup(data->inputstr);
break;
+ case WINDOW_COPY_NAMEDBUFFER:
+ window_copy_copy_selection(wp, data->inputstr);
+ *data->inputstr = '\0';
+ window_pane_reset_mode(wp);
+ return (0);
case WINDOW_COPY_GOTOLINE:
window_copy_goto_line(wp, data->inputstr);
*data->inputstr = '\0';
@@ -818,7 +842,7 @@ window_copy_key_input(struct window_pane *wp, int key)
break;
inputlen = strlen(data->inputstr) + 2;
- data->inputstr = xrealloc(data->inputstr, 1, inputlen);
+ data->inputstr = xrealloc(data->inputstr, inputlen);
data->inputstr[inputlen - 2] = key;
data->inputstr[inputlen - 1] = '\0';
break;
@@ -849,12 +873,12 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
}
void
-window_copy_mouse(
- struct window_pane *wp, struct session *sess, struct mouse_event *m)
+window_copy_mouse(struct window_pane *wp, struct session *sess,
+ struct mouse_event *m)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
- u_int i;
+ u_int i, old_cy;
if (m->x >= screen_size_x(s))
return;
@@ -863,18 +887,20 @@ window_copy_mouse(
/* If mouse wheel (buttons 4 and 5), scroll. */
if (m->event == MOUSE_EVENT_WHEEL) {
- if (m->wheel == MOUSE_WHEEL_UP) {
- for (i = 0; i < 5; i++)
+ for (i = 0; i < m->scroll; i++) {
+ if (m->wheel == MOUSE_WHEEL_UP)
window_copy_cursor_up(wp, 1);
- } else if (m->wheel == MOUSE_WHEEL_DOWN) {
- for (i = 0; i < 5; i++)
+ else {
window_copy_cursor_down(wp, 1);
- /*
- * We reached the bottom, leave copy mode,
- * but only if no selection is in progress.
- */
- if (data->oy == 0 && !s->sel.flag)
- goto reset_mode;
+
+ /*
+ * We reached the bottom, leave copy mode, but
+ * only if no selection is in progress.
+ */
+ if (data->oy == 0 && !s->sel.flag &&
+ s->sel.lineflag == LINE_SEL_NONE)
+ goto reset_mode;
+ }
}
return;
}
@@ -885,9 +911,10 @@ window_copy_mouse(
*/
if (s->mode & MODE_MOUSE_BUTTON) {
if (~m->event & MOUSE_EVENT_UP) {
+ old_cy = data->cy;
window_copy_update_cursor(wp, m->x, m->y);
if (window_copy_update_selection(wp, 1))
- window_copy_redraw_screen(wp);
+ window_copy_redraw_selection(wp, old_cy);
return;
}
goto reset_mode;
@@ -909,7 +936,7 @@ reset_mode:
s->mode &= ~MODE_MOUSE_BUTTON;
s->mode |= MODE_MOUSE_STANDARD;
if (sess != NULL) {
- window_copy_copy_selection(wp, -1);
+ window_copy_copy_selection(wp, NULL);
window_pane_reset_mode(wp);
}
}
@@ -941,8 +968,8 @@ window_copy_scroll_to(struct window_pane *wp, u_int px, u_int py)
}
int
-window_copy_search_compare(
- struct grid *gd, u_int px, u_int py, struct grid *sgd, u_int spx, int cis)
+window_copy_search_compare(struct grid *gd, u_int px, u_int py,
+ struct grid *sgd, u_int spx, int cis)
{
const struct grid_cell *gc, *sgc;
struct utf8_data ud, sud;
@@ -1163,8 +1190,8 @@ window_copy_goto_line(struct window_pane *wp, const char *linestr)
}
void
-window_copy_write_line(
- struct window_pane *wp, struct screen_write_ctx *ctx, u_int py)
+window_copy_write_line(struct window_pane *wp, struct screen_write_ctx *ctx,
+ u_int py)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
@@ -1185,8 +1212,8 @@ window_copy_write_line(
screen_write_puts(ctx, &gc, "%s", hdr);
} else if (py == last && data->inputtype != WINDOW_COPY_OFF) {
limit = sizeof hdr;
- if (limit > screen_size_x(s))
- limit = screen_size_x(s);
+ if (limit > screen_size_x(s) + 1)
+ limit = screen_size_x(s) + 1;
if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) {
xoff = size = xsnprintf(hdr, limit,
"Repeat: %u", data->numprefix);
@@ -1199,10 +1226,12 @@ window_copy_write_line(
} else
size = 0;
- screen_write_cursormove(ctx, xoff, py);
- screen_write_copy(ctx, data->backing, xoff,
- (screen_hsize(data->backing) - data->oy) + py,
- screen_size_x(s) - size, 1);
+ if (size < screen_size_x(s)) {
+ screen_write_cursormove(ctx, xoff, py);
+ 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);
@@ -1212,8 +1241,8 @@ window_copy_write_line(
}
void
-window_copy_write_lines(
- struct window_pane *wp, struct screen_write_ctx *ctx, u_int py, u_int ny)
+window_copy_write_lines(struct window_pane *wp, struct screen_write_ctx *ctx,
+ u_int py, u_int ny)
{
u_int yy;
@@ -1222,6 +1251,23 @@ window_copy_write_lines(
}
void
+window_copy_redraw_selection(struct window_pane *wp, u_int old_y)
+{
+ struct window_copy_mode_data *data = wp->modedata;
+ u_int new_y, start, end;
+
+ new_y = data->cy;
+ if (old_y <= new_y) {
+ start = old_y;
+ end = new_y;
+ } else {
+ start = new_y;
+ end = old_y;
+ }
+ window_copy_redraw_lines(wp, start, end - start + 1);
+}
+
+void
window_copy_redraw_lines(struct window_pane *wp, u_int py, u_int ny)
{
struct window_copy_mode_data *data = wp->modedata;
@@ -1286,7 +1332,7 @@ window_copy_update_selection(struct window_pane *wp, int may_redraw)
struct grid_cell gc;
u_int sx, sy, ty, cy;
- if (!s->sel.flag)
+ if (!s->sel.flag && s->sel.lineflag == LINE_SEL_NONE)
return (0);
/* Set colours. */
@@ -1336,11 +1382,11 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
struct screen *s = &data->screen;
char *buf;
size_t off;
- u_int i, xx, yy, sx, sy, ex, ey;
+ u_int i, xx, yy, sx, sy, ex, ey, ey_last;
u_int firstsx, lastex, restex, restsx;
int keys;
- if (!s->sel.flag)
+ if (!s->sel.flag && s->sel.lineflag == LINE_SEL_NONE)
return (NULL);
buf = xmalloc(1);
@@ -1365,9 +1411,9 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
}
/* Trim ex to end of line. */
- xx = window_copy_find_length(wp, ey);
- if (ex > xx)
- ex = xx;
+ ey_last = window_copy_find_length(wp, ey);
+ if (ex > ey_last)
+ ex = ey_last;
/*
* Deal with rectangle-copy if necessary; four situations: start of
@@ -1418,17 +1464,10 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
}
/* Copy the lines. */
- if (sy == ey)
- window_copy_copy_line(wp, &buf, &off, sy, firstsx, lastex);
- else {
- window_copy_copy_line(wp, &buf, &off, sy, firstsx, restex);
- if (ey - sy > 1) {
- for (i = sy + 1; i < ey; i++) {
- window_copy_copy_line(
- wp, &buf, &off, i, restsx, restex);
- }
- }
- window_copy_copy_line(wp, &buf, &off, ey, restsx, lastex);
+ for (i = sy; i <= ey; i++) {
+ window_copy_copy_line(wp, &buf, &off, i,
+ (i == sy ? firstsx : restsx),
+ (i == ey ? lastex : restex));
}
/* Don't bother if no data. */
@@ -1436,14 +1475,16 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
free(buf);
return (NULL);
}
- *len = off - 1; /* remove final \n */
+ if (keys == MODEKEY_EMACS || lastex <= ey_last)
+ off -= 1; /* remove final \n (unless at end in vi mode) */
+ *len = off;
return (buf);
}
void
-window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len)
+window_copy_copy_buffer(struct window_pane *wp, const char *bufname, void *buf,
+ size_t len)
{
- u_int limit;
struct screen_write_ctx ctx;
if (options_get_number(&global_options, "set-clipboard")) {
@@ -1452,43 +1493,82 @@ window_copy_copy_buffer(struct window_pane *wp, int idx, void *buf, size_t len)
screen_write_stop(&ctx);
}
- if (idx == -1) {
- limit = options_get_number(&global_options, "buffer-limit");
- paste_add(&global_buffers, buf, len, limit);
- } else if (paste_replace(&global_buffers, idx, buf, len) != 0)
+ if (paste_set(buf, len, bufname, NULL) != 0)
free(buf);
}
void
-window_copy_copy_pipe(
- struct window_pane *wp, struct session *sess, int idx, const char *arg)
+window_copy_copy_pipe(struct window_pane *wp, struct session *sess,
+ const char *bufname, const char *arg)
{
- void *buf;
- size_t len;
- struct job *job;
-
+ void *buf;
+ size_t len;
+ struct job *job;
+ struct format_tree *ft;
+ char *expanded;
buf = window_copy_get_selection(wp, &len);
if (buf == NULL)
return;
- job = job_run(arg, sess, NULL, NULL, NULL);
+ ft = format_create();
+ format_defaults(ft, NULL, sess, NULL, wp);
+ expanded = format_expand(ft, arg);
+
+ job = job_run(expanded, sess, NULL, NULL, NULL);
bufferevent_write(job->event, buf, len);
- window_copy_copy_buffer(wp, idx, buf, len);
+ free(expanded);
+ format_free(ft);
+
+ window_copy_copy_buffer(wp, bufname, buf, len);
+}
+
+void
+window_copy_copy_selection(struct window_pane *wp, const char *bufname)
+{
+ void *buf;
+ size_t len;
+
+ buf = window_copy_get_selection(wp, &len);
+ if (buf == NULL)
+ return;
+
+ window_copy_copy_buffer(wp, bufname, buf, len);
}
void
-window_copy_copy_selection(struct window_pane *wp, int idx)
+window_copy_append_selection(struct window_pane *wp, const char *bufname)
{
- void* buf;
- size_t len;
+ char *buf;
+ struct paste_buffer *pb;
+ size_t len;
+ struct screen_write_ctx ctx;
buf = window_copy_get_selection(wp, &len);
if (buf == NULL)
return;
- window_copy_copy_buffer(wp, idx, buf, len);
+ if (options_get_number(&global_options, "set-clipboard")) {
+ screen_write_start(&ctx, wp, NULL);
+ screen_write_setselection(&ctx, buf, len);
+ screen_write_stop(&ctx);
+ }
+
+ if (bufname == NULL || *bufname == '\0') {
+ pb = paste_get_top();
+ if (pb != NULL)
+ bufname = pb->name;
+ } else
+ pb = paste_get_name(bufname);
+ if (pb != NULL) {
+ buf = xrealloc(buf, len + pb->size);
+ memmove(buf + pb->size, buf, len);
+ memcpy(buf, pb->data, pb->size);
+ len += pb->size;
+ }
+ if (paste_set(buf, len, bufname, NULL) != 0)
+ free(buf);
}
void
@@ -1501,6 +1581,7 @@ window_copy_copy_line(struct window_pane *wp,
struct grid_line *gl;
struct utf8_data ud;
u_int i, xx, wrapped = 0;
+ const char *s;
if (sx > ex)
return;
@@ -1529,8 +1610,15 @@ window_copy_copy_line(struct window_pane *wp,
if (gc->flags & GRID_FLAG_PADDING)
continue;
grid_cell_get(gc, &ud);
+ if (ud.size == 1 && (gc->attr & GRID_ATTR_CHARSET)) {
+ s = tty_acs_get(NULL, ud.data[0]);
+ if (s != NULL && strlen(s) <= sizeof ud.data) {
+ ud.size = strlen(s);
+ memcpy(ud.data, s, ud.size);
+ }
+ }
- *buf = xrealloc(*buf, 1, (*off) + ud.size);
+ *buf = xrealloc(*buf, (*off) + ud.size);
memcpy(*buf + *off, ud.data, ud.size);
*off += ud.size;
}
@@ -1538,7 +1626,7 @@ window_copy_copy_line(struct window_pane *wp,
/* Only add a newline if the line wasn't wrapped. */
if (!wrapped || ex != xx) {
- *buf = xrealloc(*buf, 1, (*off) + 1);
+ *buf = xrealloc(*buf, (*off) + 1);
(*buf)[(*off)++] = '\n';
}
}
@@ -1606,12 +1694,14 @@ 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 screen *s = &data->screen;
struct grid *gd = back_s->grid;
u_int py;
- if (data->cx == 0) {
+ if (data->cx == 0 && s->sel.lineflag == LINE_SEL_NONE) {
py = screen_hsize(back_s) + data->cy - data->oy;
- while (py > 0 && gd->linedata[py-1].flags & GRID_LINE_WRAPPED) {
+ 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;
}
@@ -1651,13 +1741,14 @@ window_copy_cursor_end_of_line(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing;
+ struct screen *s = &data->screen;
struct grid *gd = back_s->grid;
u_int px, py;
py = screen_hsize(back_s) + data->cy - data->oy;
px = window_copy_find_length(wp, py);
- if (data->cx == px) {
+ if (data->cx == px && s->sel.lineflag == LINE_SEL_NONE) {
if (data->screen.sel.flag && data->rectflag)
px = screen_size_x(back_s);
if (gd->linedata[py].flags & GRID_LINE_WRAPPED) {
@@ -1681,11 +1772,16 @@ window_copy_other_end(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
- u_int selx, sely, cx, cy, yy;
+ u_int selx, sely, cx, cy, yy, hsize;
- if (!s->sel.flag)
+ if (!s->sel.flag && s->sel.lineflag == LINE_SEL_NONE)
return;
+ if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT)
+ s->sel.lineflag = LINE_SEL_RIGHT_LEFT;
+ else if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT)
+ s->sel.lineflag = LINE_SEL_LEFT_RIGHT;
+
selx = data->selx;
sely = data->sely;
cx = data->cx;
@@ -1696,13 +1792,13 @@ window_copy_other_end(struct window_pane *wp)
data->sely = yy;
data->cx = selx;
- if (sely < screen_hsize(data->backing) - data->oy) {
- data->oy = screen_hsize(data->backing) - sely;
+ hsize = screen_hsize(data->backing);
+ if (sely < hsize - data->oy) {
+ data->oy = hsize - sely;
data->cy = 0;
- } else if (sely > screen_hsize(data->backing) - data->oy + screen_size_y(s)) {
- data->oy = screen_hsize(data->backing) - sely + screen_size_y(s) - 1;
+ } else if (sely > hsize - data->oy + screen_size_y(s)) {
+ data->oy = hsize - sely + screen_size_y(s) - 1;
data->cy = screen_size_y(s) - 1;
-
} else
data->cy = cy + sely - yy;
@@ -1761,6 +1857,9 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
data->lastsx = ox;
}
+ if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
+ window_copy_other_end(wp);
+
data->cx = data->lastcx;
if (scroll_only || data->cy == 0) {
window_copy_scroll_down(wp, 1);
@@ -1787,6 +1886,11 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
data->cx > px)
window_copy_cursor_end_of_line(wp);
}
+
+ if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT)
+ window_copy_cursor_end_of_line(wp);
+ else if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT)
+ window_copy_cursor_start_of_line(wp);
}
void
@@ -1803,6 +1907,9 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
data->lastsx = ox;
}
+ if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT && oy == data->sely)
+ window_copy_other_end(wp);
+
data->cx = data->lastcx;
if (scroll_only || data->cy == screen_size_y(s) - 1) {
window_copy_scroll_up(wp, 1);
@@ -1821,6 +1928,11 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
data->cx > px)
window_copy_cursor_end_of_line(wp);
}
+
+ if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT)
+ window_copy_cursor_end_of_line(wp);
+ else if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT)
+ window_copy_cursor_start_of_line(wp);
}
void
@@ -1982,7 +2094,8 @@ window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
}
void
-window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
+window_copy_cursor_next_word_end(struct window_pane *wp,
+ const char *separators)
{
struct window_copy_mode_data *data = wp->modedata;
struct options *oo = &wp->window->options;
@@ -2033,7 +2146,8 @@ window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
/* Move to the previous place where a word begins. */
void
-window_copy_cursor_previous_word(struct window_pane *wp, const char *separators)
+window_copy_cursor_previous_word(struct window_pane *wp,
+ const char *separators)
{
struct window_copy_mode_data *data = wp->modedata;
u_int px, py;
diff --git a/window.c b/window.c
index 858463cf..54129634 100644
--- a/window.c
+++ b/window.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -17,13 +17,11 @@
*/
#include <sys/types.h>
-#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
-#include <pwd.h>
-#include <signal.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
@@ -57,15 +55,14 @@ struct windows windows;
struct window_pane_tree all_window_panes;
u_int next_window_pane_id;
u_int next_window_id;
-
-struct window_pane *window_pane_active_set(struct window_pane *,
- struct window_pane *);
-void window_pane_active_lost(struct window_pane *, struct window_pane *);
+u_int next_active_point;
void window_pane_timer_callback(int, short, void *);
void window_pane_read_callback(struct bufferevent *, void *);
void window_pane_error_callback(struct bufferevent *, short, void *);
+struct window_pane *window_pane_choose_best(struct window_pane_list *);
+
RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
int
@@ -309,8 +306,8 @@ window_create1(u_int sx, u_int sy)
}
struct window *
-window_create(const char *name, const char *cmd, const char *shell,
- int cwd, struct environ *env, struct termios *tio,
+window_create(const char *name, int argc, char **argv, const char *path,
+ const char *shell, int cwd, struct environ *env, struct termios *tio,
u_int sx, u_int sy, u_int hlimit, char **cause)
{
struct window *w;
@@ -320,7 +317,8 @@ window_create(const char *name, const char *cmd, const char *shell,
wp = window_add_pane(w, hlimit);
layout_init(w, wp);
- if (window_pane_spawn(wp, cmd, shell, cwd, env, tio, cause) != 0) {
+ if (window_pane_spawn(wp, argc, argv, path, shell, cwd, env, tio,
+ cause) != 0) {
window_destroy(w);
return (NULL);
}
@@ -387,74 +385,22 @@ window_resize(struct window *w, u_int sx, u_int sy)
w->sy = sy;
}
-/*
- * Restore previously active pane when changing from wp to nextwp. The intended
- * pane is in nextwp and it returns the previously focused pane.
- */
-struct window_pane *
-window_pane_active_set(struct window_pane *wp, struct window_pane *nextwp)
-{
- struct layout_cell *lc;
- struct window_pane *lastwp;
-
- /* Target pane's parent must not be an ancestor of source pane. */
- for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) {
- if (lc == nextwp->layout_cell->parent)
- return (nextwp);
- }
-
- /*
- * Previously active pane, if any, must not be the same as the source
- * pane.
- */
- if (nextwp->layout_cell->parent != NULL) {
- lastwp = nextwp->layout_cell->parent->lastwp;
- if (lastwp != wp && window_pane_visible(lastwp))
- return (lastwp);
- }
- return (nextwp);
-}
-
-/* Remember previously active pane when changing from wp to nextwp. */
-void
-window_pane_active_lost(struct window_pane *wp, struct window_pane *nextwp)
-{
- struct layout_cell *lc, *lc2;
-
- /* Save the target pane in its parent. */
- nextwp->layout_cell->parent->lastwp = nextwp;
-
- /*
- * Save the source pane in all of its parents up to, but not including,
- * the common ancestor of itself and the target panes.
- */
- if (wp == NULL)
- return;
- for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) {
- lc2 = nextwp->layout_cell->parent;
- for (; lc2 != NULL; lc2 = lc2->parent) {
- if (lc == lc2)
- return;
- }
- lc->lastwp = wp;
- }
-}
-
-void
+int
window_set_active_pane(struct window *w, struct window_pane *wp)
{
if (wp == w->active)
- return;
+ return (0);
w->last = w->active;
w->active = wp;
- window_pane_active_lost(w->last, wp);
while (!window_pane_visible(w->active)) {
w->active = TAILQ_PREV(w->active, window_panes, entry);
if (w->active == NULL)
w->active = TAILQ_LAST(&w->panes, window_panes);
if (w->active == wp)
- return;
+ return (1);
}
+ w->active->active_point = next_active_point++;
+ return (1);
}
struct window_pane *
@@ -544,6 +490,7 @@ window_zoom(struct window_pane *wp)
w->saved_layout_root = w->layout_root;
layout_init(w, wp);
w->flags |= WINDOW_ZOOMED;
+ notify_window_layout_changed(w);
return (0);
}
@@ -565,6 +512,7 @@ window_unzoom(struct window *w)
wp->saved_layout_cell = NULL;
}
layout_fix_panes(w, w->sx, w->sy);
+ notify_window_layout_changed(w);
return (0);
}
@@ -583,7 +531,7 @@ window_add_pane(struct window *w, u_int hlimit)
}
void
-window_remove_pane(struct window *w, struct window_pane *wp)
+window_lost_pane(struct window *w, struct window_pane *wp)
{
if (wp == w->active) {
w->active = w->last;
@@ -595,6 +543,12 @@ window_remove_pane(struct window *w, struct window_pane *wp)
}
} else if (wp == w->last)
w->last = NULL;
+}
+
+void
+window_remove_pane(struct window *w, struct window_pane *wp)
+{
+ window_lost_pane(w, wp);
TAILQ_REMOVE(&w->panes, wp, entry);
window_pane_destroy(wp);
@@ -691,8 +645,6 @@ window_printable_flags(struct session *s, struct winlink *wl)
flags[pos++] = '#';
if (wl->flags & WINLINK_BELL)
flags[pos++] = '!';
- if (wl->flags & WINLINK_CONTENT)
- flags[pos++] = '+';
if (wl->flags & WINLINK_SILENCE)
flags[pos++] = '~';
if (wl == s->curw)
@@ -728,7 +680,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp->id = next_window_pane_id++;
RB_INSERT(window_pane_tree, &all_window_panes, wp);
- wp->cmd = NULL;
+ wp->argc = 0;
+ wp->argv = NULL;
wp->shell = NULL;
wp->cwd = -1;
@@ -762,22 +715,15 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
void
window_pane_destroy(struct window_pane *wp)
{
- struct window_pane *wp2;
-
- /* Forget removed pane in all layout cells that remember it. */
- RB_FOREACH(wp2, window_pane_tree, &all_window_panes) {
- if (wp2->layout_cell != NULL &&
- wp2->layout_cell->parent != NULL &&
- wp2->layout_cell->parent->lastwp == wp)
- wp2->layout_cell->parent->lastwp = NULL;
- }
-
window_pane_reset_mode(wp);
if (event_initialized(&wp->changes_timer))
evtimer_del(&wp->changes_timer);
if (wp->fd != -1) {
+#ifdef HAVE_UTEMPTER
+ utempter_remove_record(wp->fd);
+#endif
bufferevent_free(wp->event);
close(wp->fd);
}
@@ -797,26 +743,32 @@ window_pane_destroy(struct window_pane *wp)
close(wp->cwd);
free(wp->shell);
- free(wp->cmd);
+ cmd_free_argv(wp->argc, wp->argv);
free(wp);
}
int
-window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
- int cwd, struct environ *env, struct termios *tio, char **cause)
+window_pane_spawn(struct window_pane *wp, int argc, char **argv,
+ const char *path, const char *shell, int cwd, struct environ *env,
+ struct termios *tio, char **cause)
{
struct winsize ws;
- char *argv0, paneid[16];
- const char *ptr;
+ char *argv0, *cmd, **argvp, paneid[16];
+ const char *ptr, *first;
struct termios tio2;
+#ifdef HAVE_UTEMPTER
+ char s[32];
+#endif
+ int i;
if (wp->fd != -1) {
bufferevent_free(wp->event);
close(wp->fd);
}
- if (cmd != NULL) {
- free(wp->cmd);
- wp->cmd = xstrdup(cmd);
+ if (argc > 0) {
+ cmd_free_argv(wp->argc, wp->argv);
+ wp->argc = argc;
+ wp->argv = cmd_copy_argv(argc, argv);
}
if (shell != NULL) {
free(wp->shell);
@@ -827,7 +779,10 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
wp->cwd = dup(cwd);
}
- log_debug("spawn: %s -- %s", wp->shell, wp->cmd);
+ cmd = cmd_stringify_argv(wp->argc, wp->argv);
+ log_debug("spawn: %s -- %s", wp->shell, cmd);
+ for (i = 0; i < wp->argc; i++)
+ log_debug("spawn: argv[%d] = %s", i, wp->argv[i]);
memset(&ws, 0, sizeof ws);
ws.ws_col = screen_size_x(&wp->base);
@@ -837,6 +792,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
case -1:
wp->fd = -1;
xasprintf(cause, "%s: %s", cmd, strerror(errno));
+ free(cmd);
return (-1);
case 0:
if (fchdir(wp->cwd) != 0)
@@ -856,6 +812,8 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
closefrom(STDERR_FILENO + 1);
+ if (path != NULL)
+ environ_set(env, "PATH", path);
xsnprintf(paneid, sizeof paneid, "%%%u", wp->id);
environ_set(env, "TMUX_PANE", paneid);
environ_push(env);
@@ -866,31 +824,47 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
setenv("SHELL", wp->shell, 1);
ptr = strrchr(wp->shell, '/');
- if (*wp->cmd != '\0') {
- /* Use the command. */
+ /*
+ * If given one argument, assume it should be passed to sh -c;
+ * with more than one argument, use execvp(). If there is no
+ * arguments, create a login shell.
+ */
+ if (wp->argc > 0) {
+ if (wp->argc != 1) {
+ /* Copy to ensure argv ends in NULL. */
+ argvp = cmd_copy_argv(wp->argc, wp->argv);
+ execvp(argvp[0], argvp);
+ fatal("execvp failed");
+ }
+ first = wp->argv[0];
+
if (ptr != NULL && *(ptr + 1) != '\0')
xasprintf(&argv0, "%s", ptr + 1);
else
xasprintf(&argv0, "%s", wp->shell);
- execl(wp->shell, argv0, "-c", wp->cmd, (char *) NULL);
+ execl(wp->shell, argv0, "-c", first, (char *)NULL);
fatal("execl failed");
}
-
- /* No command; fork a login shell. */
if (ptr != NULL && *(ptr + 1) != '\0')
xasprintf(&argv0, "-%s", ptr + 1);
else
xasprintf(&argv0, "-%s", wp->shell);
- execl(wp->shell, argv0, (char *) NULL);
+ execl(wp->shell, argv0, (char *)NULL);
fatal("execl failed");
}
+#ifdef HAVE_UTEMPTER
+ xsnprintf(s, sizeof s, "tmux(%lu).%%%u", (long) getpid(), wp->id);
+ utempter_add_record(wp->fd, s);
+#endif
+
setblocking(wp->fd, 0);
- wp->event = bufferevent_new(wp->fd,
- window_pane_read_callback, NULL, window_pane_error_callback, wp);
+ wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
+ window_pane_error_callback, wp);
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
+ free(cmd);
return (0);
}
@@ -920,7 +894,6 @@ window_pane_timer_callback(unused int fd, unused short events, void *data)
if (wp->changes_redraw++ == interval) {
wp->flags |= PANE_REDRAW;
wp->changes_redraw = 0;
-
}
if (trigger == 0 || wp->changes < trigger) {
@@ -1095,17 +1068,15 @@ window_pane_key(struct window_pane *wp, struct session *sess, int key)
{
struct window_pane *wp2;
- if (!window_pane_visible(wp))
- return;
-
if (wp->mode != NULL) {
if (wp->mode->key != NULL)
wp->mode->key(wp, sess, key);
return;
}
- if (wp->fd == -1)
+ if (wp->fd == -1 || wp->flags & PANE_INPUTOFF)
return;
+
input_key(wp, key);
if (options_get_number(&wp->window->options, "synchronize-panes")) {
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
@@ -1118,8 +1089,8 @@ window_pane_key(struct window_pane *wp, struct session *sess, int key)
}
void
-window_pane_mouse(
- struct window_pane *wp, struct session *sess, struct mouse_event *m)
+window_pane_mouse(struct window_pane *wp, struct session *sess,
+ struct mouse_event *m)
{
if (!window_pane_visible(wp))
return;
@@ -1154,7 +1125,8 @@ window_pane_visible(struct window_pane *wp)
}
char *
-window_pane_search(struct window_pane *wp, const char *searchstr, u_int *lineno)
+window_pane_search(struct window_pane *wp, const char *searchstr,
+ u_int *lineno)
{
struct screen *s = &wp->base;
char *newsearchstr, *line, *msg;
@@ -1178,114 +1150,198 @@ window_pane_search(struct window_pane *wp, const char *searchstr, u_int *lineno)
return (msg);
}
-/* Find the pane directly above another. */
+/* Get MRU pane from a list. */
+struct window_pane *
+window_pane_choose_best(struct window_pane_list *list)
+{
+ struct window_pane *next, *best;
+ u_int i;
+
+ if (ARRAY_LENGTH(list) == 0)
+ return (NULL);
+
+ best = ARRAY_FIRST(list);
+ for (i = 1; i < ARRAY_LENGTH(list); i++) {
+ next = ARRAY_ITEM(list, i);
+ if (next->active_point > best->active_point)
+ best = next;
+ }
+ return (best);
+}
+
+/*
+ * Find the pane directly above another. We build a list of those adjacent to
+ * top edge and then choose the best.
+ */
struct window_pane *
window_pane_find_up(struct window_pane *wp)
{
- struct window_pane *wp2;
- u_int left, top;
+ struct window_pane *next, *best;
+ u_int edge, left, right, end;
+ struct window_pane_list list;
+ int found;
if (wp == NULL || !window_pane_visible(wp))
return (NULL);
+ ARRAY_INIT(&list);
+
+ edge = wp->yoff;
+ if (edge == 0)
+ edge = wp->window->sy + 1;
- top = wp->yoff;
- if (top == 0)
- top = wp->window->sy + 1;
left = wp->xoff;
+ right = wp->xoff + wp->sx;
- TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
- if (!window_pane_visible(wp2))
+ TAILQ_FOREACH(next, &wp->window->panes, entry) {
+ if (next == wp || !window_pane_visible(next))
continue;
- if (wp2->yoff + wp2->sy + 1 != top)
+ if (next->yoff + next->sy + 1 != edge)
continue;
- if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
- return (window_pane_active_set(wp, wp2));
+ end = next->xoff + next->sx - 1;
+
+ found = 0;
+ if (next->xoff < left && end > right)
+ found = 1;
+ else if (next->xoff >= left && next->xoff <= right)
+ found = 1;
+ else if (end >= left && end <= right)
+ found = 1;
+ if (found)
+ ARRAY_ADD(&list, next);
}
- return (NULL);
+
+ best = window_pane_choose_best(&list);
+ ARRAY_FREE(&list);
+ return (best);
}
/* 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;
+ struct window_pane *next, *best;
+ u_int edge, left, right, end;
+ struct window_pane_list list;
+ int found;
if (wp == NULL || !window_pane_visible(wp))
return (NULL);
+ ARRAY_INIT(&list);
+
+ edge = wp->yoff + wp->sy + 1;
+ if (edge >= wp->window->sy)
+ edge = 0;
- bottom = wp->yoff + wp->sy + 1;
- if (bottom >= wp->window->sy)
- bottom = 0;
left = wp->xoff;
+ right = wp->xoff + wp->sx;
- TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
- if (!window_pane_visible(wp2))
+ TAILQ_FOREACH(next, &wp->window->panes, entry) {
+ if (next == wp || !window_pane_visible(next))
continue;
- if (wp2->yoff != bottom)
+ if (next->yoff != edge)
continue;
- if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
- return (window_pane_active_set(wp, wp2));
+ end = next->xoff + next->sx - 1;
+
+ found = 0;
+ if (next->xoff < left && end > right)
+ found = 1;
+ else if (next->xoff >= left && next->xoff <= right)
+ found = 1;
+ else if (end >= left && end <= right)
+ found = 1;
+ if (found)
+ ARRAY_ADD(&list, next);
}
- return (NULL);
+
+ best = window_pane_choose_best(&list);
+ ARRAY_FREE(&list);
+ return (best);
}
-/*
- * Find the pane directly to the left of another, adjacent to the left side and
- * containing the top edge.
- */
+/* Find the pane directly to the left of another. */
struct window_pane *
window_pane_find_left(struct window_pane *wp)
{
- struct window_pane *wp2;
- u_int left, top;
+ struct window_pane *next, *best;
+ u_int edge, top, bottom, end;
+ struct window_pane_list list;
+ int found;
if (wp == NULL || !window_pane_visible(wp))
return (NULL);
+ ARRAY_INIT(&list);
+
+ edge = wp->xoff;
+ if (edge == 0)
+ edge = wp->window->sx + 1;
- left = wp->xoff;
- if (left == 0)
- left = wp->window->sx + 1;
top = wp->yoff;
+ bottom = wp->yoff + wp->sy;
- TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
- if (!window_pane_visible(wp2))
+ TAILQ_FOREACH(next, &wp->window->panes, entry) {
+ if (next == wp || !window_pane_visible(next))
continue;
- if (wp2->xoff + wp2->sx + 1 != left)
+ if (next->xoff + next->sx + 1 != edge)
continue;
- if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
- return (window_pane_active_set(wp, wp2));
+ end = next->yoff + next->sy - 1;
+
+ found = 0;
+ if (next->yoff < top && end > bottom)
+ found = 1;
+ else if (next->yoff >= top && next->yoff <= bottom)
+ found = 1;
+ else if (end >= top && end <= bottom)
+ found = 1;
+ if (found)
+ ARRAY_ADD(&list, next);
}
- return (NULL);
+
+ best = window_pane_choose_best(&list);
+ ARRAY_FREE(&list);
+ return (best);
}
-/*
- * Find the pane directly to the right of another, that is adjacent to the
- * right edge and including the top edge.
- */
+/* Find the pane directly to the right of another. */
struct window_pane *
window_pane_find_right(struct window_pane *wp)
{
- struct window_pane *wp2;
- u_int right, top;
+ struct window_pane *next, *best;
+ u_int edge, top, bottom, end;
+ struct window_pane_list list;
+ int found;
if (wp == NULL || !window_pane_visible(wp))
return (NULL);
+ ARRAY_INIT(&list);
+
+ edge = wp->xoff + wp->sx + 1;
+ if (edge >= wp->window->sx)
+ edge = 0;
- right = wp->xoff + wp->sx + 1;
- if (right >= wp->window->sx)
- right = 0;
top = wp->yoff;
+ bottom = wp->yoff + wp->sy;
- TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
- if (!window_pane_visible(wp2))
+ TAILQ_FOREACH(next, &wp->window->panes, entry) {
+ if (next == wp || !window_pane_visible(next))
continue;
- if (wp2->xoff != right)
+ if (next->xoff != edge)
continue;
- if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
- return (window_pane_active_set(wp, wp2));
+ end = next->yoff + next->sy - 1;
+
+ found = 0;
+ if (next->yoff < top && end > bottom)
+ found = 1;
+ else if (next->yoff >= top && next->yoff <= bottom)
+ found = 1;
+ else if (end >= top && end <= bottom)
+ found = 1;
+ if (found)
+ ARRAY_ADD(&list, next);
}
- return (NULL);
+
+ best = window_pane_choose_best(&list);
+ ARRAY_FREE(&list);
+ return (best);
}
/* Clear alert flags for a winlink */
diff --git a/www/index.html.in b/www/index.html.in
index 5e0276e8..e9ec46bd 100644
--- a/www/index.html.in
+++ b/www/index.html.in
@@ -11,7 +11,7 @@
<div id="left-menu-container">
<p id="upper-left-title">tmux</p>
<ul id="left-menu">
- <li><a href="http://downloads.sourceforge.net/tmux/tmux-%%VERSION%%.tar.gz">Download</a></li>
+ <li><a href="http://downloads.sourceforge.net/tmux/tmux-%%RELEASE%%.tar.gz">Download</a></li>
<li><a href="https://sourceforge.net/p/tmux/tmux-code/ci/master/tree/README">README</a></li>
<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=tmux&sektion=1">Manual Page</a></li>
<li><a href="https://sourceforge.net/p/tmux/tmux-code/ci/master/tree/FAQ">FAQ</a></li>
@@ -31,8 +31,9 @@ background) and reattach them to a different terminal. And do a lot more. See
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=tmux&sektion=1">
the manual</a>.</p>
-<p><b><a href="http://downloads.sourceforge.net/tmux/tmux-%%VERSION%%.tar.gz">
-Download tmux %%VERSION%%</a></b> or
+<p><b><a href="http://downloads.sourceforge.net/tmux/tmux-%%RELEASE%%.tar.gz">
+Download tmux %%RELEASE%%</a></b>
+<b><a href="https://sourceforge.net/p/tmux/tmux-code/ci/master/tree/CHANGES">(changelog)</a></b> or
<a href="https://sourceforge.net/p/tmux/tmux-code/ci/master/tree/">
get the development version.</a>
tmux is hosted on
@@ -40,8 +41,7 @@ tmux is hosted on
and needs
<a href="http://www.monkey.org/~provos/libevent/">libevent</a>
and
-<a href="http://invisible-island.net/ncurses/">ncurses</a>
-.</p>
+<a href="http://invisible-island.net/ncurses/">ncurses</a>.</p>
<p>For support contact the
<a href="mailto:tmux-users@lists.sf.net">tmux-users@lists.sf.net</a>
diff --git a/xmalloc.c b/xmalloc.c
index df583e55..b1570a3a 100644
--- a/xmalloc.c
+++ b/xmalloc.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2004 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -16,10 +16,9 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h>
+#include <sys/types.h>
-#include <errno.h>
-#include <libgen.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -67,7 +66,20 @@ xmalloc(size_t size)
}
void *
-xrealloc(void *oldptr, size_t nmemb, size_t size)
+xrealloc(void *oldptr, size_t newsize)
+{
+ void *newptr;
+
+ if (newsize == 0)
+ fatalx("zero size");
+ if ((newptr = realloc(oldptr, newsize)) == NULL)
+ fatal("xrealloc failed");
+
+ return (newptr);
+}
+
+void *
+xreallocarray(void *oldptr, size_t nmemb, size_t size)
{
size_t newsize = nmemb * size;
void *newptr;
@@ -77,12 +89,12 @@ xrealloc(void *oldptr, size_t nmemb, size_t size)
if (SIZE_MAX / nmemb < size)
fatalx("nmemb * size > SIZE_MAX");
if ((newptr = realloc(oldptr, newsize)) == NULL)
- fatal("xrealloc failed");
+ fatal("xreallocarray failed");
return (newptr);
}
-int printflike2
+int
xasprintf(char **ret, const char *fmt, ...)
{
va_list ap;
@@ -107,7 +119,7 @@ xvasprintf(char **ret, const char *fmt, va_list ap)
return (i);
}
-int printflike3
+int
xsnprintf(char *buf, size_t len, const char *fmt, ...)
{
va_list ap;
diff --git a/xterm-keys.c b/xterm-keys.c
index af3f1e76..5ca75d89 100644
--- a/xterm-keys.c
+++ b/xterm-keys.c
@@ -1,4 +1,4 @@
-/* $Id$ */
+/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -40,8 +40,8 @@
* We accept any but always output the latter (it comes first in the table).
*/
-int xterm_keys_match(const char *, const char *, size_t);
-int xterm_keys_modifiers(const char *, const char *, size_t);
+int xterm_keys_match(const char *, const char *, size_t, size_t *, u_int *);
+int xterm_keys_modifiers(const char *, size_t, size_t *, u_int *);
struct xterm_keys_entry {
int key;
@@ -69,14 +69,6 @@ const struct xterm_keys_entry xterm_keys_table[] = {
{ KEYC_F10, "\033[21;_~" },
{ KEYC_F11, "\033[23;_~" },
{ KEYC_F12, "\033[24;_~" },
- { KEYC_F13, "\033[25;_~" },
- { KEYC_F14, "\033[26;_~" },
- { KEYC_F15, "\033[28;_~" },
- { KEYC_F16, "\033[29;_~" },
- { KEYC_F17, "\033[31;_~" },
- { KEYC_F18, "\033[32;_~" },
- { KEYC_F19, "\033[33;_~" },
- { KEYC_F20, "\033[34;_~" },
{ KEYC_UP, "\033[1;_A" },
{ KEYC_DOWN, "\033[1;_B" },
{ KEYC_RIGHT, "\033[1;_C" },
@@ -122,49 +114,62 @@ const struct xterm_keys_entry xterm_keys_table[] = {
* 0 for match, 1 if the end of the buffer is reached (need more data).
*/
int
-xterm_keys_match(const char *template, const char *buf, size_t len)
+xterm_keys_match(const char *template, const char *buf, size_t len,
+ size_t *size, u_int *modifiers)
{
size_t pos;
+ int retval;
if (len == 0)
return (0);
pos = 0;
do {
- if (*template == '_' && buf[pos] >= '1' && buf[pos] <= '8')
+ if (*template == '_') {
+ retval = xterm_keys_modifiers(buf, len, &pos,
+ modifiers);
+ if (retval != 0)
+ return (retval);
continue;
+ }
if (buf[pos] != *template)
return (-1);
- } while (*++template != '\0' && ++pos != len);
+ pos++;
+ } while (*++template != '\0' && pos != len);
if (*template != '\0') /* partial */
return (1);
+ *size = pos;
return (0);
}
-/* Find modifiers based on template. */
+/* Find modifiers from buffer. */
int
-xterm_keys_modifiers(const char *template, const char *buf, size_t len)
+xterm_keys_modifiers(const char *buf, size_t len, size_t *pos, u_int *modifiers)
{
- size_t idx;
- int param, modifiers;
+ u_int flags;
- idx = strcspn(template, "_");
- if (idx >= len)
- return (0);
- param = buf[idx] - '1';
-
- modifiers = 0;
- if (param & 1)
- modifiers |= KEYC_SHIFT;
- if (param & 2)
- modifiers |= KEYC_ESCAPE;
- if (param & 4)
- modifiers |= KEYC_CTRL;
- if (param & 8)
- modifiers |= KEYC_ESCAPE;
- return (modifiers);
+ if (len - *pos < 2)
+ return (1);
+
+ if (buf[*pos] < '0' || buf[*pos] > '9')
+ return (-1);
+ flags = buf[(*pos)++] - '0';
+ if (buf[*pos] >= '0' && buf[*pos] <= '9')
+ flags = (flags * 10) + (buf[(*pos)++] - '0');
+ flags -= 1;
+
+ *modifiers = 0;
+ if (flags & 1)
+ *modifiers |= KEYC_SHIFT;
+ if (flags & 2)
+ *modifiers |= KEYC_ESCAPE;
+ if (flags & 4)
+ *modifiers |= KEYC_CTRL;
+ if (flags & 8)
+ *modifiers |= KEYC_ESCAPE;
+ return (0);
}
/*
@@ -175,19 +180,19 @@ int
xterm_keys_find(const char *buf, size_t len, size_t *size, int *key)
{
const struct xterm_keys_entry *entry;
- u_int i;
+ u_int i, modifiers;
+ int matched;
for (i = 0; i < nitems(xterm_keys_table); i++) {
entry = &xterm_keys_table[i];
- switch (xterm_keys_match(entry->template, buf, len)) {
- case 0:
- *size = strlen(entry->template);
- *key = entry->key;
- *key |= xterm_keys_modifiers(entry->template, buf, len);
- return (0);
- case 1:
- return (1);
- }
+
+ matched = xterm_keys_match(entry->template, buf, len, size,
+ &modifiers);
+ if (matched == -1)
+ continue;
+ if (matched == 0)
+ *key = entry->key | modifiers;
+ return (matched);
}
return (-1);
}