119 Commits
1.5 ... 1.6

Author SHA1 Message Date
Tiago Cunha
88c831af6e Tag 1.6 release. 2012-01-23 12:59:12 +00:00
Tiago Cunha
e254aeb9f9 Major changes since the previous version. 2012-01-23 12:41:36 +00:00
Tiago Cunha
1d4c54717c Add notes about some potential configuration file breaking in the 1.6 release. 2012-01-23 12:38:05 +00:00
Tiago Cunha
30b816f101 Done. 2012-01-23 12:35:55 +00:00
Tiago Cunha
9803aee98e Releases don't have debugging enabled. 2012-01-23 12:34:47 +00:00
Tiago Cunha
a34a72d2d9 Sync OpenBSD patchset 1011:
Remove unused backoff code that doesn't do any good.
2012-01-23 12:24:00 +00:00
Tiago Cunha
4d80980e50 Sync OpenBSD patchset 1010:
Show pane size in top right of display panes mode.
2012-01-23 12:23:27 +00:00
Tiago Cunha
85152ef35c Expand the Id keyword. 2012-01-22 23:41:34 +00:00
Tiago Cunha
ebce251183 Sync OpenBSD patchset 1009:
it's -> its.
2012-01-21 21:40:33 +00:00
Tiago Cunha
a3c1b730c9 Sync OpenBSD patchset 1008:
Use RB trees not SPLAY.
2012-01-21 19:38:26 +00:00
Tiago Cunha
a7b0b30bdd Sync OpenBSD patchset 1007:
Drop the ability to have a list of keys in the prefix in favour of two
separate options, prefix and prefix2. This simplifies the code and gets
rid the data options type which was only used for this one option.

Also add a -2 flag to send-prefix to send the secondary prefix key,
fixing a cause of minor irritation.

People who want three prefix keys are out of luck :-).
2012-01-21 19:36:40 +00:00
Tiago Cunha
d4c2a935f2 Sync OpenBSD patchset 1006:
Add strings to allow the aixterm bright colours to be used when
configuring colours, requested by Elliott Cable a few months ago.
2012-01-21 19:33:45 +00:00
Tiago Cunha
cc967ffeb9 Sync OpenBSD patchset 1005:
One day I will actually fix ALL the warnings before I commit...
2012-01-21 19:32:36 +00:00
Tiago Cunha
4bea559037 Sync OpenBSD patchset 1004:
Add a -R flag to send-keys to reset the terminal. Written ages ago and
Suggested by someone, I forget who.
2012-01-21 19:31:59 +00:00
Tiago Cunha
674de910ca Sync OpenBSD patchset 1003:
Only hide flags on the current window when the session is attached, from
Roland Walker.
2012-01-21 19:30:07 +00:00
Tiago Cunha
5434a2759a Sync OpenBSD patchset 1002:
Add some const and fix a warning.
2012-01-20 21:21:32 +00:00
Tiago Cunha
b7551c9193 Sync OpenBSD patchset 1001:
Add some trivial additional status line attributes from jwcxz at users
dot sourceforge dot net.
2012-01-20 21:20:35 +00:00
Tiago Cunha
d4312281da Sync OpenBSD patchset 1000:
Remove trailing spaces.
2012-01-20 21:19:20 +00:00
Tiago Cunha
d9eb34b28d Sync OpenBSD patchset 999:
Add an option to disable the window rename escape sequence, from Romain
Francoise.
2012-01-20 21:18:39 +00:00
Tiago Cunha
b79189958f Sync OpenBSD patchset 998:
Add space movement keys for vi mode in the status line from Ben Boeckel.
2012-01-20 21:17:18 +00:00
Tiago Cunha
ad5c4e719b Sync OpenBSD patchset 997:
Calculate last position correctly for UTF-8 wide characters, reported by
Matthias Lederhofer.
2012-01-20 21:16:07 +00:00
Nicholas Marriott
db7570daab Set IUTF8 in termios where supported, suggested by Egmont Koblinger. 2012-01-20 20:18:20 +00:00
Tiago Cunha
60069fe8fe Sync OpenBSD patchset 995:
Add a man page section on window names and pane titles, from Felix
Rosencrantz.
2012-01-03 18:36:40 +00:00
Tiago Cunha
d817f88fec Sync OpenBSD patchset 995:
Show how to set default-path to revert to tmux's old behaviour of opening
new windows in the current working directory at the time tmux was started,
it's not obvious. naddy@ agrees this is a useful inclusion.
2012-01-03 18:35:54 +00:00
Tiago Cunha
90b331ea46 Sync OpenBSD patchset 994:
Add CNL and CPL escape sequences.
2011-12-30 14:21:40 +00:00
Tiago Cunha
e2d59a6c17 Sync OpenBSD patchset 993:
Allow $HOME as default-path in tmux.conf so the same config file can be used
on different machines regardless of where the user's home directory is.
ok nicm
2011-12-30 14:21:02 +00:00
Tiago Cunha
2ca1849350 Sync OpenBSD patchset 992:
Add \033[s and \033[u to save and restore cursor position.
2011-12-30 14:19:21 +00:00
Tiago Cunha
e210abf335 $Id$ not $OpenBSD$. 2011-12-30 14:18:27 +00:00
Tiago Cunha
f9b4095188 Sync OpenBSD patchset 991:
Extend history that can be captured to INT_MIN rather than
SHRT_MIN. From Chris Johnsen.
2011-12-30 14:16:44 +00:00
Tiago Cunha
d1f0138653 Sync OpenBSD patchset 990:
Reset flags on every loop or it is displayed too often, from Chris
Johnsen.
2011-12-30 14:15:40 +00:00
Tiago Cunha
9e7ec2e971 Sync OpenBSD patchset 989:
formatting errors, found using freebsd's "igor";
2011-12-25 23:36:27 +00:00
Tiago Cunha
3a9a24a7c0 Sync OpenBSD patchset 988:
Fix so that when mouse-select-pane and mouse-select-window are both
enabled, clicking on the status line does not change the current
pane. From Romain Francoise.
2011-12-25 23:33:30 +00:00
Nicholas Marriott
c1b9948525 Change the way the working directory for new processes is discovered. If
default-path isn't empty, it is used. Otherwise:

1) If tmux neww is run from the command line, the working directory of the
client is used.

2) Otherwise use some platform specific code to retrieve the current working
directory of the process in the active pane.

3) If that fails, the directory where the session was created is used.

Idea and support code, Linux, Solaris, FreeBSD bits by Romain Francoise,
OpenBSD bits by me.
2011-12-09 16:37:29 +00:00
Tiago Cunha
76862acf3e Sync OpenBSD patchset 986:
Support "jump to" like vi in copy mode using t and T keys. Also add x
and X for delete in edit mode.

From Ben Boeckel, thanks.
2011-12-06 18:50:26 +00:00
Tiago Cunha
f308663ad4 Sync OpenBSD patchset 985:
Log terminal overrides.
2011-12-06 18:48:45 +00:00
Tiago Cunha
876f46abb9 Sync OpenBSD patchset 984:
Add home and end keys for command prompt, from Matthias Lederhofer.
2011-12-06 18:48:02 +00:00
Tiago Cunha
620a87db25 Sync OpenBSD patchset 983:
Make M-f and M-b work the same at the command prompt as in copy mode,
pointed out by Romain Francoise.
2011-12-06 18:47:14 +00:00
Tiago Cunha
08014af243 New commands and options. From Ben Boeckel. 2011-11-25 14:31:11 +00:00
Tiago Cunha
774bffb3c6 Sync OpenBSD patchset 982:
Add word movement and editing command for command prompt editing, from
Ben Boeckel.
2011-11-25 13:34:20 +00:00
Tiago Cunha
9c920214e6 Sync OpenBSD patchset 981:
Move word-separators to be a session rather than window option, from Ben
Boeckel.
2011-11-25 13:33:04 +00:00
Tiago Cunha
5cc3d50289 Sync OpenBSD patchset 980:
Add a pane_index format string and use it, from Ben Boeckel.
2011-11-25 13:31:56 +00:00
Tiago Cunha
9ec457575d Sync OpenBSD patchset 979:
Make window_pane_index work the same as window_index, from Ben Boeckel.
2011-11-25 13:30:45 +00:00
Nicholas Marriott
398af28d2a +. 2011-11-15 23:12:28 +00:00
Tiago Cunha
8798079ab0 Typo. From Bastien Dejean. 2011-11-10 21:50:40 +00:00
Tiago Cunha
c26ec766cb Add command colour options. From Ben Boeckel. 2011-11-10 21:49:27 +00:00
Tiago Cunha
c3794d4303 Sync OpenBSD patchset 978:
Fix a trivial copy-and-paste error (sx->sy), from Chris Johnsen.
2011-11-10 21:41:37 +00:00
Tiago Cunha
4fbb296438 Sync OpenBSD patchset 977:
Missing bits for new keys and buffer indexes, from Tiago Cunha
2011-11-10 21:41:01 +00:00
Tiago Cunha
21128fea1e Sync OpenBSD patchset 976:
Option to change status line (message) background when using vi keys and
in command mode. From Ben Boeckel.
2011-11-10 21:40:17 +00:00
Nicholas Marriott
693c106a1d Add. 2011-11-09 12:00:11 +00:00
Tiago Cunha
046d8b096f Sync OpenBSD patchset 975:
minor formatting fix;
2011-10-31 13:56:55 +00:00
Tiago Cunha
0cbab892d5 Sync OpenBSD patchset 974:
Add screen*:XT to terminal-overrides for tmux-in-tmux, from Romain
Francoise.
2011-10-31 13:56:16 +00:00
Tiago Cunha
b44f78fe9f Sync OpenBSD patchset 973:
Missing -o on usage for pipe-pane, from Tiago Cunha.
2011-10-31 13:55:43 +00:00
Tiago Cunha
3f5ec24b5a Sync OpenBSD patchset 972:
Didn't really think the else behaviour through - requiring argv to
contain "else" is silly so just omit that, also some manpage
tweaks. From Tiago Cunha.
2011-10-31 13:55:10 +00:00
Tiago Cunha
d8d9c2af98 Sync OpenBSD patchset 971:
When copying, make repeat count indicate buffer to replace if used.
2011-10-31 13:54:28 +00:00
Nicholas Marriott
cf317412d9 Use pkg-config for libevent. 2011-10-27 23:00:45 +00:00
Nicholas Marriott
5213d9674b Add. 2011-10-27 22:43:02 +00:00
Tiago Cunha
0e45ca1718 Recognise special keys and binds with multiple modifiers. From Bastien Dejean. 2011-10-23 15:42:15 +00:00
Tiago Cunha
c1eeac86fe Sync OpenBSD patchset 970:
Alias NPage/PPage as PageDown/PgDn/PageUp/PgUp to reduce occasional
confusion.
2011-10-23 15:11:09 +00:00
Tiago Cunha
03ee7f7edf Sync OpenBSD patchset 969:
Support for \e[3J to clear the history. Also send the corresponding
terminfo code (E3) before locking.
2011-10-23 15:10:22 +00:00
Tiago Cunha
a8ca1340ad Sync OpenBSD patchset 968:
Try to resolve relative paths for loadb and saveb (first using client
working directory if any then default-path or session wd).
2011-10-23 15:08:58 +00:00
Tiago Cunha
7d169a3679 Sync OpenBSD patchset 967:
For initial session, use size of command client even if detached.
2011-10-23 15:05:20 +00:00
Tiago Cunha
98e500f598 Sync OpenBSD patchset 966:
Ignore LC_ALL and LC_CTYPE if they are empty as well as unset.
2011-10-23 15:04:30 +00:00
Tiago Cunha
1c1797e4f2 Sync OpenBSD patchset 965:
Add client formats, from Ben Boeckel.
2011-10-23 15:03:50 +00:00
Tiago Cunha
653d1e2fc8 Sync OpenBSD patchset 964:
Plug a memory leak and update some comments, from Tiago Cunha.
2011-10-23 15:02:20 +00:00
Tiago Cunha
9b48c77493 Sync OpenBSD patchset 963:
Add an else clause for if-shell, from "arno-" on SourceForge.
2011-10-23 15:00:41 +00:00
Nicholas Marriott
96146a8c6f Done. 2011-10-23 10:21:02 +00:00
Nicholas Marriott
7d53e2c946 Done! 2011-10-23 08:36:19 +00:00
Nicholas Marriott
213deb5c66 +. 2011-10-23 00:43:58 +00:00
Nicholas Marriott
69c1521895 +. 2011-10-23 00:31:35 +00:00
Nicholas Marriott
17e6dc4405 Add manpage, also spaces->tabs. 2011-10-10 20:17:17 +00:00
Nicholas Marriott
a7341715c1 Fix some warnings with newer autoconf, from Matt Curtis. 2011-10-06 12:14:22 +00:00
Tiago Cunha
521bf41d12 Sync OpenBSD patchset 962:
Add a few more formats for panes (tty, pid, start cmd/cwd).
2011-10-02 11:34:04 +00:00
Tiago Cunha
f0c3e9babe Sync OpenBSD patchset 961:
Add -S option to refresh-client to redraw status line, from Marco Beck.
2011-10-02 11:33:14 +00:00
Tiago Cunha
edd59d9e0f Sync OpenBSD patchset 960:
Reject $SHELL if it is not a full path.
2011-10-02 11:32:24 +00:00
Tiago Cunha
326c5bf1b4 Sync OpenBSD patchset 959:
Tweaks to the format parts, from Tiago Cunha.
2011-10-02 11:31:34 +00:00
Tiago Cunha
550906cb09 Sync OpenBSD patchset 958:
Fix typo: ) -> }.
2011-10-02 11:30:26 +00:00
Nicholas Marriott
175d82c95b Done. 2011-10-02 06:56:31 +00:00
Nicholas Marriott
3740f8f846 Add. 2011-10-02 06:44:16 +00:00
Nicholas Marriott
adfa5050d5 Add. 2011-10-02 06:33:32 +00:00
Nicholas Marriott
f62dcc1ea1 Separate dfly from fbsd as one or the other keeps becoming incompatible
;-). From Antonio Huete Jimenez
2011-09-29 08:43:01 +00:00
Nicholas Marriott
d6dc4c30f4 +. 2011-09-25 18:45:15 +00:00
Nicholas Marriott
d635d79042 The HAVE_DIRFD check should be for dirfd() not /proc/$$/fd. Doh. 2011-09-23 12:35:08 +00:00
Nicholas Marriott
b8ce435a54 +. 2011-09-23 12:34:31 +00:00
Tiago Cunha
6e0c097d9f Sync OpenBSD patchset 957:
Mark dead panes with some text saying they are dead, suggested by and
with help from Randy Stauner.
2011-09-21 16:35:13 +00:00
Tiago Cunha
d9807eeba1 Sync OpenBSD patchset 956:
Another memory leak from Tiago Cunha.
2011-09-21 16:34:34 +00:00
Tiago Cunha
cb752f9938 Sync OpenBSD patchset 955:
Plug memory leak, from Tiago Cunha.
2011-09-21 16:34:04 +00:00
Tiago Cunha
2e98603db9 Sync OpenBSD patchset 954:
tweak previous;
2011-09-21 16:33:19 +00:00
Tiago Cunha
39628e8280 Add format.c to the list of sources. 2011-09-21 16:32:31 +00:00
Tiago Cunha
40af1a854c Sync OpenBSD patchset 953:
Add initial framework for more powerful formatting of command output and
use it for list-{panes,windows,sessions}. This allows more descriptive
replacements (such as #{session_name}) and conditionals.

Later this will be used for status_replace and list-keys and other
places.
2011-09-21 16:31:15 +00:00
Nicholas Marriott
fb5b958837 Add build instructions based on diff from Frank Terbeck. 2011-09-15 12:58:39 +00:00
Nicholas Marriott
99f78340af Use %u for process group on Sun OS. 2011-09-11 23:54:32 +00:00
Tiago Cunha
4a01da19df Sync OpenBSD patchset 951:
Support \ for line continuation in the configuration file, from Julius
Plenz.
2011-08-25 21:14:23 +00:00
Tiago Cunha
d390a90bf0 Sync OpenBSD patchset 950:
Add pane-base-index option, from Ben Barbour.
2011-08-25 21:13:45 +00:00
Tiago Cunha
c41a93d130 Sync OpenBSD patchset 949:
Add a tty_bell wrapper function, from Dylan Alex Simon.
2011-08-25 21:12:52 +00:00
Tiago Cunha
0a4fd0f7a4 libm isn't needed anymore. 2011-08-25 21:12:10 +00:00
Tiago Cunha
a54e670301 Sync OpenBSD patchset 948:
There is no need to use sqrt()/INFINITY here which simplifies the code
and makes it more portable, from Havard Eidnes.
2011-08-25 21:11:16 +00:00
Tiago Cunha
2651c0d69c Sync OpenBSD patchset 947:
Fix a couple of memory leaks, from marcel partap.
2011-08-21 12:39:34 +00:00
Tiago Cunha
87a2a13f68 Sync OpenBSD patchset 946:
Add a -r flag to switch-client to toggle the client read-only flag. From
Johan Commelin.
2011-08-21 12:38:55 +00:00
Tiago Cunha
5775074f73 Sync OpenBSD patchset 945:
Add up/down/left/right keys in vi edit mode. From "livibetter" SF bug
3385651.
2011-08-21 12:37:26 +00:00
Tiago Cunha
abb4af7a14 Sync OpenBSD patchset 944:
Use key_bindings_remove for unbind-key -a to allow it to work from key
bindings. From "miaout17" SF bug 3392063.
2011-08-21 12:36:43 +00:00
Tiago Cunha
b9bbe1d81c Sync OpenBSD patchset 943:
Correctly skip existing numbers when generating the name for a new
session.
2011-08-21 12:35:47 +00:00
Nicholas Marriott
cd62411d78 +. 2011-08-16 09:58:49 +00:00
Nicholas Marriott
e39c5a9e14 +. 2011-08-15 09:01:23 +00:00
Nicholas Marriott
b2fe881307 +. 2011-08-14 15:36:15 +00:00
Tiago Cunha
b6659dc563 Sync OpenBSD patchset 942:
fix error in previous;
2011-08-04 17:06:10 +00:00
Tiago Cunha
3ce1b91b1b Sync OpenBSD patchset 941:
Extend the mode-mouse option to add a third choice which means the mouse
does not enter copy mode. Patch from SF bug 3374493.

In future the mode-mouse option is likely to die and be broken into
several smaller options.
2011-08-04 17:05:35 +00:00
Tiago Cunha
2589d117b0 Sync OpenBSD patchset 940:
Do not require a client here, or pipe-pane will not work from the
command line.
2011-08-04 17:04:08 +00:00
Tiago Cunha
8aec4c93eb $Id$ not $OpenBSD$. 2011-08-04 17:03:29 +00:00
Tiago Cunha
9960a06a67 Sync OpenBSD patchset 939:
Sort options alphabetically, from Tiago Cunha.
2011-08-04 17:01:55 +00:00
Nicholas Marriott
0ecb11fe4f Add. 2011-07-30 17:47:21 +00:00
Nicholas Marriott
7d604ab717 Add. 2011-07-30 17:44:24 +00:00
Nicholas Marriott
ee5e97926d Fix --enable-static and add a different check for b64_ntop that might work on
OS X.
2011-07-27 09:31:08 +00:00
Nicholas Marriott
e9ebdac3dd Can't use the same va_list twice, from Emanuele Giaquinta. 2011-07-25 09:56:43 +00:00
Nicholas Marriott
5339b8ce3a Typo. 2011-07-22 15:10:24 +00:00
Nicholas Marriott
20134fa9f4 Compatibility for b64_ntop, missing from some alternative libc. 2011-07-22 10:49:33 +00:00
Nicholas Marriott
1f01dd8c0a +. 2011-07-19 01:47:26 +00:00
Nicholas Marriott
25eb48aea3 Only get -lrt when needed, from Pietro Cerutti. 2011-07-19 01:35:33 +00:00
Nicholas Marriott
e5cee89727 Typo, from Si Feng. 2011-07-19 01:31:00 +00:00
Tiago Cunha
d86c6b2fff Bump version and create a debug build by default. 2011-07-09 16:24:44 +00:00
72 changed files with 2461 additions and 673 deletions

50
CHANGES
View File

@@ -1,3 +1,53 @@
CHANGES FROM 1.5 TO 1.6, 23 January 2012
* Extend the mode-mouse option to add a third choice which means the mouse
does not enter copy mode.
* Add a -r flag to switch-client to toggle the client read-only flag.
* Add pane-base-index option.
* Support \ for line continuation in the configuration file.
* Framework for more powerful formatting of command output and use it for
list-{panes,windows,sessions}. This allows more descriptive replacements
(such as #{session_name}) and conditionals.
* Mark dead panes with some text saying they are dead.
* Reject $SHELL if it is not a full path.
* Add -S option to refresh-client to redraw status line.
* Add an else clause for if-shell.
* Try to resolve relative paths for loadb and saveb (first, using client
working directory, if any, then default-path or session working directory).
* Support for \e[3J to clear the history and send the corresponding
terminfo code (E3) before locking.
* When in copy mode, make repeat count indicate buffer to replace, if used.
* Add screen*:XT to terminal-overrides for tmux-in-tmux.
* Status-line message attributes added.
* Move word-separators to be a session rather than window option.
* Change the way the working directory for new processes is discovered. If
default-path isn't empty, it is used. Otherwise, if a new window is created
from the command-line, the working directory of the client is used. If not,
platform specific code is used to retrieve the current working directory
of the process in the active pane. If that fails, the directory where the
session was created is used, instead.
* Do not change the current pane if both mouse-select-{pane,window} are
enabled.
* Add \033[s and \033[u to save and restore cursor position.
* Allow $HOME to be used as default-path.
* Add CNL and CPL escape sequences.
* Calculate last position correctly for UTF-8 wide characters.
* Add an option allow-rename to disable the window rename escape sequence.
* Attributes for each type of status-line alert (ie bell, content and
activity) added. Therefore, remove the superfluous options
window-status-alert-{attr,bg,fg}.
* Add a -R flag to send-keys to reset the terminal.
* Add strings to allow the aixterm bright colours to be used when
configuring colours.
* Drop the ability to have a list of keys in the prefix in favour of two
separate options, prefix and prefix2.
* Flag -2 added to send-prefix to send the secondary prefix key.
* Show pane size in top right of display panes mode.
* Some memory leaks plugged.
* More command-prompt editing improvements.
* Various manpage improvements.
* More Vi mode improvements.
CHANGES FROM 1.4 TO 1.5, 09 July 2011
* Support xterm mouse modes 1002 and 1003.

View File

@@ -43,11 +43,6 @@ CPPFLAGS += -I. -I- -I/usr/local/include
endif
endif
# Set flags for static.
if IS_STATIC
LDFLAGS += -static
endif
# Set flags for Solaris.
if IS_SUNOS
CPPFLAGS += -D_XPG4_2 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
@@ -141,6 +136,7 @@ dist_tmux_SOURCES = \
cmd.c \
colour.c \
environ.c \
format.c \
grid-utf8.c \
grid-view.c \
grid.c \
@@ -226,6 +222,9 @@ endif
if NO_STRTONUM
nodist_tmux_SOURCES += compat/strtonum.c
endif
if NO_B64_NTOP
nodist_tmux_SOURCES += compat/b64_ntop.c
endif
# Update SF web site.
upload-index.html: update-index.html

17
NOTES
View File

@@ -9,10 +9,27 @@ run on Solaris and AIX (although they haven't been tested in a while). It is
usable, although there remain a number of missing features and some remaining
bugs are expected.
If upgrading from 1.5, PLEASE NOTE:
- The word-separators window option is now a session option.
- The options used to change the window attributes when an alert occurs were
removed. Each kind of alert has its own individual set of options.
- The ability to have a list of prefix keys was dropped in favour of two
separate options, prefix and prefix2.
Since the 1.2 release that tmux depends on libevent. Download it from:
http://www.monkey.org/~provos/libevent/
To build tmux from a release tarball, do:
$ ./configure && make
$ sudo make install
To build from a version control checkout, the configure script must be
generated by running:
$ sh autogen.sh
tmux consists of a server part and multiple clients. The server is created when
required and runs continuously unless killed by the user. Clients access the
server through a socket in /tmp. Multiple sessions may be created on a single

24
TODO
View File

@@ -6,7 +6,6 @@
- flags to centre screen in window
- activity/bell should be per-window not per-link? what if it is cur win in
session not being watched?
- next prev word etc in command prompt
- use a better termcap internally instead of screen, perhaps xterm
- should be able to move to a hidden pane and it would be moved into view. pane
number in status line/top-right would be cool for this
@@ -67,7 +66,6 @@
sequence until its shell exits, to allow them to be used from the config file
- better session sharing: create-socket command to create socket somewhere (-r
flag for readonly)
- allow buffer to be specified when copying in copy mode
- multiline status line (no?)
- flag for absolute pane size to resize-pane
- sanity check input to socket
@@ -100,7 +98,6 @@
and a buffer) info() when changing to same window
- way to add dest for break-pane; maybe some easier way to unbreak-pane
- case insensitive searching
- pane-index option like base-index
- option to move status line to top
- configurable borders and empty space filler for when panes < window?
- mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets the
@@ -113,13 +110,8 @@
in commands without quotes
- a command to choose from a generic list, so you can do eg
choose-list -l Abc,Moo,Blah "run-shell 'sh /my/choose/script %%'"
- else part for if-shell
- add general internal format for lists (key=value) and a way to output them in
different representations, use for list-windows, etc etc. see message id
20110221205346.GA1580@yelena.nicm.ath.cx
- numeric prefix in copy mode should be paste buffer for C-w
- named buffers and allow gaps in the stack
- npage/ppage/dc/ic should have aliases for more typical names
- get rid of separate UTF-8 cell stuff: add 1 byte to cell and store BMP as
uint16_t+3 bits of flags. anything <=0xffff is Unicode, higher are used to
build tree of combined characters/non-BMP (LRU dropped when full)
@@ -128,13 +120,25 @@
- monitor-activity is broken in several ways with multiple clients
- monitor-activity should be more powerful (eg set a region)
- maybe a way to put pane names instead of window names in status line
- Support for borderless panes
- support for borderless panes
- run-shell/if-shell should support status_replace stuff
- wait-pane command or another way to make it synchronous/wait for command to
finish
- way to get command window was started with (part of format stuff?)
- last-pane across sessions
- attach should take a pane and select it as well as attaching
- should default-path be a window option?
- option to put status line at top (why?)
- panes should have names like windows
- command-prompt doesn't work if made read-only. why?
- option to quote format eg #{session_name:quoted}
- formats need to be used for much much more stuff!
- formats need conditions for >0 (for #P)
- flags to find-window to select what is searched (title, name, content, history)
- fetch full command line on !Linux, and add option to strip prefixes
such as "sh " "/bin/sh " etc etc
- synchronize-windows option
- possibly support rxvt-unicode extended mouse input (1015)
- append to buffer in copy mode
* We need a tmux terminfo entry to document the extensions we are using in
upstream terminfo. Must NOT change (only add or remove) anything from
TERM=screen so we can fallback!

35
cfg.c
View File

@@ -92,22 +92,37 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
retval = 0;
while ((buf = fgetln(f, &len))) {
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';
len--;
if (line != NULL)
line = xrealloc(line, 1, strlen(line) + len + 1);
else {
line = xrealloc(line, 1, len + 1);
memcpy(line, buf, len);
line[len] = '\0';
buf = line;
line = xmalloc(len + 1);
*line = '\0';
}
/* Append buffer to line. strncat will terminate. */
strncat(line, buf, len);
n++;
/* Continuation: get next line? */
len = strlen(line);
if (len > 0 && line[len - 1] == '\\') {
line[len - 1] = '\0';
continue;
}
buf = line;
line = NULL;
if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
xfree(buf);
if (cause == NULL)
continue;
cfg_add_cause(causes, "%s: %u: %s", path, n, cause);
xfree(cause);
continue;
}
} else
xfree(buf);
if (cmdlist == NULL)
continue;
cfg_cause = NULL;
@@ -131,12 +146,16 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
retval = 1;
cmd_list_free(cmdlist);
if (cfg_cause != NULL) {
cfg_add_cause(causes, "%s: %d: %s", path, n, cfg_cause);
cfg_add_cause(
causes, "%s: %d: %s", path, n, cfg_cause);
xfree(cfg_cause);
}
}
if (line != NULL)
if (line != NULL) {
cfg_add_cause(causes,
"%s: %d: line continuation at end of file", path, n);
xfree(line);
}
fclose(f);
return (retval);

View File

@@ -76,6 +76,7 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
ctx->curclient->session = s;
session_update_activity(s);
server_redraw_client(ctx->curclient);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
} else {
if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal");
@@ -104,6 +105,7 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
environ_update(update, &ctx->cmdclient->environ, &s->environ);
server_redraw_client(ctx->cmdclient);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
}
recalculate_sizes();
server_update_socket();

View File

@@ -107,7 +107,7 @@ cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key)
mtmp.key = key;
mtmp.mode = !!args_has(args, 'c');
if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
if ((mbind = RB_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
mbind->cmd = cmd;
return (0);
}
@@ -115,6 +115,6 @@ cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key)
mbind->key = mtmp.key;
mbind->mode = mtmp.mode;
mbind->cmd = cmd;
SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
RB_INSERT(mode_key_tree, mtab->tree, mbind);
return (0);
}

View File

@@ -59,7 +59,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
buf = NULL;
len = 0;
n = args_strtonum(args, 'S', SHRT_MIN, SHRT_MAX, &cause);
n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
top = gd->hsize;
xfree(cause);
@@ -70,7 +70,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
if (top > gd->hsize + gd->sy - 1)
top = gd->hsize + gd->sy - 1;
n = args_strtonum(args, 'E', SHRT_MIN, SHRT_MAX, &cause);
n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
bottom = gd->hsize + gd->sy - 1;
xfree(cause);
@@ -109,6 +109,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
xfree(buf);
xfree(cause);
return (-1);
}

View File

@@ -76,9 +76,11 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
idx++;
window_choose_add(wl->window->active, i,
"%s: %s [%ux%u %s]%s", c->tty.path,
"%s: %s [%ux%u %s]%s%s", c->tty.path,
c->session->name, c->tty.sx, c->tty.sy,
c->tty.termname, c->tty.flags & TTY_UTF8 ? " (utf8)" : "");
c->tty.termname,
c->tty.flags & TTY_UTF8 ? " (utf8)" : "",
c->flags & CLIENT_READONLY ? " (ro)" : "");
}
cdata = xmalloc(sizeof *cdata);

View File

@@ -25,7 +25,7 @@
#include "tmux.h"
/*
* Executes a tmux command if a shell command returns true.
* Executes a tmux command if a shell command returns true or false.
*/
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
@@ -35,8 +35,8 @@ void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if",
"", 2, 2,
"shell-command command",
"", 2, 3,
"shell-command command [command]",
0,
NULL,
NULL,
@@ -44,7 +44,8 @@ const struct cmd_entry cmd_if_shell_entry = {
};
struct cmd_if_shell_data {
char *cmd;
char *cmd_if;
char *cmd_else;
struct cmd_ctx ctx;
};
@@ -56,7 +57,11 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *shellcmd = args->argv[0];
cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(args->argv[1]);
cdata->cmd_if = xstrdup(args->argv[1]);
if (args->argc == 3)
cdata->cmd_else = xstrdup(args->argv[2]);
else
cdata->cmd_else = NULL;
memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
if (ctx->cmdclient != NULL)
@@ -75,12 +80,15 @@ cmd_if_shell_callback(struct job *job)
struct cmd_if_shell_data *cdata = job->data;
struct cmd_ctx *ctx = &cdata->ctx;
struct cmd_list *cmdlist;
char *cause;
char *cause, *cmd;
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
return;
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) {
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) {
cmd = cdata->cmd_else;
if (cmd == NULL)
return;
} else
cmd = cdata->cmd_if;
if (cmd_string_parse(cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) {
ctx->error(ctx, "%s", cause);
xfree(cause);
@@ -107,6 +115,8 @@ cmd_if_shell_free(void *data)
if (ctx->curclient != NULL)
ctx->curclient->references--;
xfree(cdata->cmd);
if (cdata->cmd_else != NULL)
xfree(cdata->cmd_else);
xfree(cdata->cmd_if);
xfree(cdata);
}

View File

@@ -31,9 +31,9 @@ int cmd_list_clients_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_clients_entry = {
"list-clients", "lsc",
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
"F:t:", 0, 0,
"[-F format] " CMD_TARGET_SESSION_USAGE,
CMD_READONLY,
NULL,
NULL,
cmd_list_clients_exec
@@ -43,11 +43,13 @@ const struct cmd_entry cmd_list_clients_entry = {
int
cmd_list_clients_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c;
struct session *s;
u_int i;
const char *s_utf8;
struct args *args = self->args;
struct client *c;
struct session *s;
struct format_tree *ft;
const char *template;
u_int i;
char *line;
if (args_has(args, 't')) {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
@@ -56,21 +58,32 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_ctx *ctx)
} else
s = NULL;
template = args_get(args, 'F');
if (template == NULL) {
template = "#{client_tty}: #{session_name} "
"[#{client_width}x#{client_height} #{client_termname}]"
"#{?client_utf8, (utf8),}"
"#{?client_readonly, (ro),}";
}
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
if (c->tty.flags & TTY_UTF8)
s_utf8 = " (utf8)";
else
s_utf8 = "";
if (s != NULL && s != c->session)
continue;
ctx->print(ctx, "%s: %s [%ux%u %s]%s", c->tty.path,
c->session->name, c->tty.sx, c->tty.sy,
c->tty.termname, s_utf8);
ft = format_create();
format_add(ft, "line", "%u", i);
format_session(ft, c->session);
format_client(ft, c);
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
xfree(line);
format_free(ft);
}
return (0);

View File

@@ -54,9 +54,8 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
return (cmd_list_keys_table(self, ctx));
width = 0;
*flags = '\0';
SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
RB_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue;
@@ -73,11 +72,12 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
width = keywidth;
}
SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
RB_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue;
*flags = '\0';
if (!(bd->key & KEYC_PREFIX)) {
if (bd->can_repeat)
xsnprintf(flags, sizeof flags, "-rn ");
@@ -116,7 +116,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
width = 0;
any_mode = 0;
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) {
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
@@ -129,7 +129,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
width = keywidth;
}
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) {
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;

View File

@@ -28,15 +28,16 @@
int cmd_list_panes_exec(struct cmd *, struct cmd_ctx *);
void cmd_list_panes_server(struct cmd_ctx *);
void cmd_list_panes_session(struct session *, struct cmd_ctx *, int);
void cmd_list_panes_window(
void cmd_list_panes_server(struct cmd *, struct cmd_ctx *);
void cmd_list_panes_session(
struct cmd *, struct session *, struct cmd_ctx *, int);
void cmd_list_panes_window(struct cmd *,
struct session *, struct winlink *, struct cmd_ctx *, int);
const struct cmd_entry cmd_list_panes_entry = {
"list-panes", "lsp",
"ast:", 0, 0,
"[-as] [-t target]",
"asF:t:", 0, 0,
"[-as] [-F format] [-t target]",
0,
NULL,
NULL,
@@ -51,87 +52,92 @@ cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl;
if (args_has(args, 'a'))
cmd_list_panes_server(ctx);
cmd_list_panes_server(self, ctx);
else if (args_has(args, 's')) {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (-1);
cmd_list_panes_session(s, ctx, 1);
cmd_list_panes_session(self, s, ctx, 1);
} else {
wl = cmd_find_window(ctx, args_get(args, 't'), &s);
if (wl == NULL)
return (-1);
cmd_list_panes_window(s, wl, ctx, 0);
cmd_list_panes_window(self, s, wl, ctx, 0);
}
return (0);
}
void
cmd_list_panes_server(struct cmd_ctx *ctx)
cmd_list_panes_server(struct cmd *self, struct cmd_ctx *ctx)
{
struct session *s;
RB_FOREACH(s, sessions, &sessions)
cmd_list_panes_session(s, ctx, 2);
cmd_list_panes_session(self, s, ctx, 2);
}
void
cmd_list_panes_session(struct session *s, struct cmd_ctx *ctx, int type)
cmd_list_panes_session(
struct cmd *self, struct session *s, struct cmd_ctx *ctx, int type)
{
struct winlink *wl;
RB_FOREACH(wl, winlinks, &s->windows)
cmd_list_panes_window(s, wl, ctx, type);
cmd_list_panes_window(self, s, wl, ctx, type);
}
void
cmd_list_panes_window(
cmd_list_panes_window(struct cmd *self,
struct session *s, struct winlink *wl, struct cmd_ctx *ctx, int type)
{
struct args *args = self->args;
struct window_pane *wp;
struct grid *gd;
struct grid_line *gl;
u_int i, n;
unsigned long long size;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
template = args_get(args, 'F');
if (template == NULL) {
switch (type) {
case 0:
template = "#{pane_index}: "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
case 1:
template = "#{window_index}.#{pane_index}: "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
case 2:
template = "#{session_name}:#{window_index}.#{pane_index}: "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
}
}
n = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
gd = wp->base.grid;
ft = format_create();
format_add(ft, "line", "%u", n);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wp);
size = 0;
for (i = 0; i < gd->hsize; i++) {
gl = &gd->linedata[i];
size += gl->cellsize * sizeof *gl->celldata;
size += gl->utf8size * sizeof *gl->utf8data;
}
size += gd->hsize * sizeof *gd->linedata;
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
xfree(line);
switch (type) {
case 0:
ctx->print(ctx,
"%u: [%ux%u] [history %u/%u, %llu bytes] %%%u%s%s",
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size,
wp->id, wp == wp->window->active ? " (active)" : "",
wp->fd == -1 ? " (dead)" : "");
break;
case 1:
ctx->print(ctx,
"%d.%u: [%ux%u] [history %u/%u, %llu bytes] "
"%%%u%s%s", wl->idx,
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size,
wp->id, wp == wp->window->active ? " (active)" : "",
wp->fd == -1 ? " (dead)" : "");
break;
case 2:
ctx->print(ctx,
"%s:%d.%u: [%ux%u] [history %u/%u, %llu bytes] "
"%%%u%s%s", s->name, wl->idx,
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size,
wp->id, wp == wp->window->active ? " (active)" : "",
wp->fd == -1 ? " (dead)" : "");
break;
}
format_free(ft);
n++;
}
}

View File

@@ -31,40 +31,45 @@ int cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_sessions_entry = {
"list-sessions", "ls",
"", 0, 0,
"",
"F:", 0, 0,
"[-F format]",
0,
NULL,
NULL,
cmd_list_sessions_exec
};
/* ARGSUSED */
int
cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
cmd_list_sessions_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct session *s;
struct session_group *sg;
char *tim, tmp[64];
u_int idx;
time_t t;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
template = args_get(args, 'F');
if (template == NULL) {
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),}";
}
n = 0;
RB_FOREACH(s, sessions, &sessions) {
sg = session_group_find(s);
if (sg == NULL)
*tmp = '\0';
else {
idx = session_group_index(sg);
xsnprintf(tmp, sizeof tmp, " (group %u)", idx);
}
ft = format_create();
format_add(ft, "line", "%u", n);
format_session(ft, s);
t = s->creation_time.tv_sec;
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
xfree(line);
ctx->print(ctx, "%s: %u windows (created %s) [%ux%u]%s%s",
s->name, winlink_count(&s->windows), tim, s->sx, s->sy,
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
format_free(ft);
n++;
}
return (0);

View File

@@ -28,13 +28,14 @@
int cmd_list_windows_exec(struct cmd *, struct cmd_ctx *);
void cmd_list_windows_server(struct cmd_ctx *);
void cmd_list_windows_session(struct session *, struct cmd_ctx *, int);
void cmd_list_windows_server(struct cmd *, struct cmd_ctx *);
void cmd_list_windows_session(
struct cmd *, struct session *, struct cmd_ctx *, int);
const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw",
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
"aF:t:", 0, 0,
"[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
@@ -48,45 +49,69 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s;
if (args_has(args, 'a'))
cmd_list_windows_server(ctx);
cmd_list_windows_server(self, ctx);
else {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (-1);
cmd_list_windows_session(s, ctx, 0);
cmd_list_windows_session(self, s, ctx, 0);
}
return (0);
}
void
cmd_list_windows_server(struct cmd_ctx *ctx)
cmd_list_windows_server(struct cmd *self, struct cmd_ctx *ctx)
{
struct session *s;
RB_FOREACH(s, sessions, &sessions)
cmd_list_windows_session(s, ctx, 1);
cmd_list_windows_session(self, s, ctx, 1);
}
void
cmd_list_windows_session(struct session *s, struct cmd_ctx *ctx, int type)
cmd_list_windows_session(
struct cmd *self, struct session *s, struct cmd_ctx *ctx, int type)
{
struct winlink *wl;
char *layout;
struct args *args = self->args;
struct winlink *wl;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
RB_FOREACH(wl, winlinks, &s->windows) {
layout = layout_dump(wl->window);
if (type) {
ctx->print(ctx, "%s:%d: %s [%ux%u] [layout %s]%s",
s->name, wl->idx, wl->window->name, wl->window->sx,
wl->window->sy, layout,
wl == s->curw ? " (active)" : "");
} else {
ctx->print(ctx, "%d: %s [%ux%u] [layout %s]%s",
wl->idx, wl->window->name, wl->window->sx,
wl->window->sy, layout,
wl == s->curw ? " (active)" : "");
template = args_get(args, 'F');
if (template == NULL) {
switch (type) {
case 0:
template = "#{window_index}: "
"#{window_name} "
"[#{window_width}x#{window_height}] "
"[layout #{window_layout}]"
"#{?window_active, (active),}";
break;
case 1:
template = "#{session_name}:#{window_index}: "
"#{window_name} "
"[#{window_width}x#{window_height}] "
"[layout #{window_layout}]"
"#{?window_active, (active),}";
break;
}
xfree(layout);
}
n = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
ft = format_create();
format_add(ft, "line", "%u", n);
format_session(ft, s);
format_winlink(ft, s, wl);
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
xfree(line);
format_free(ft);
n++;
}
}

View File

@@ -27,7 +27,7 @@
#include "tmux.h"
/*
* Loads a session paste buffer from a file.
* Loads a paste buffer from a file.
*/
int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
@@ -48,8 +48,9 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c = ctx->cmdclient;
struct session *s;
FILE *f;
const char *path;
const char *path, *newpath, *wd;
char *pdata, *new_pdata, *cause;
size_t psize;
u_int limit;
@@ -93,6 +94,19 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (1);
}
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(ctx, 0)) != NULL) {
wd = options_get_string(&s->options, "default-path");
if (*wd == '\0')
wd = s->cwd;
} else
wd = NULL;
if (wd != NULL && *wd != '\0') {
newpath = get_full_path(wd, path);
if (newpath != NULL)
path = newpath;
}
if ((f = fopen(path, "rb")) == NULL) {
ctx->error(ctx, "%s: %s", path, strerror(errno));
return (-1);
@@ -125,6 +139,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
}
if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", buffer);
xfree(pdata);
return (-1);
}

View File

@@ -154,9 +154,17 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
}
/* Find new session size. */
if (detached) {
if (ctx->cmdclient != NULL) {
sx = ctx->cmdclient->tty.sx;
sy = ctx->cmdclient->tty.sy;
} else if (ctx->curclient != NULL) {
sx = ctx->curclient->tty.sx;
sy = ctx->curclient->tty.sy;
} else {
sx = 80;
sy = 24;
}
if (detached) {
if (args_has(args, 'x')) {
sx = strtonum(
args_get(args, 'x'), 1, USHRT_MAX, &errstr);
@@ -173,12 +181,6 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1);
}
}
} else if (ctx->cmdclient != NULL) {
sx = ctx->cmdclient->tty.sx;
sy = ctx->cmdclient->tty.sy;
} else {
sx = ctx->curclient->tty.sx;
sy = ctx->curclient->tty.sy;
}
if (sy > 0 && options_get_number(&global_s_options, "status"))
sy--;

View File

@@ -44,7 +44,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct args *args = self->args;
struct session *s;
struct winlink *wl;
char *cmd, *cwd, *cause;
const char *cmd, *cwd;
char *cause;
int idx, last, detached;
if (args_has(args, 'a')) {
@@ -98,13 +99,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
cwd = options_get_string(&s->options, "default-path");
if (*cwd == '\0') {
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
cwd = ctx->cmdclient->cwd;
else
cwd = s->cwd;
}
cwd = cmd_get_default_path(ctx);
if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index");

View File

@@ -38,7 +38,7 @@ void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *);
const struct cmd_entry cmd_pipe_pane_entry = {
"pipe-pane", "pipep",
"ot:", 0, 1,
CMD_TARGET_PANE_USAGE "[-o] [command]",
"[-o] " CMD_TARGET_PANE_USAGE " [command]",
0,
NULL,
NULL,
@@ -54,11 +54,9 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
char *command;
int old_fd, pipe_fd[2], null_fd;
if ((c = cmd_find_client(ctx, NULL)) == NULL)
return (-1);
if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (-1);
c = cmd_find_client(ctx, NULL);
/* Destroy the old pipe. */
old_fd = wp->pipe_fd;

View File

@@ -28,8 +28,8 @@ int cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
"St:", 0, 0,
"[-S] " CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
@@ -45,7 +45,11 @@ cmd_refresh_client_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (-1);
server_redraw_client(c);
if (args_has(args, 'S')) {
status_update_jobs(c);
server_status_client(c);
} else
server_redraw_client(c);
return (0);
}

View File

@@ -49,15 +49,18 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s;
struct environ env;
const char *cmd;
char *cause;
char *cause;
u_int idx;
if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL)
return (-1);
w = wl->window;
if (!args_has(self->args, 'k') && wp->fd != -1) {
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
ctx->error(ctx, "pane still active: %s:%u.%u",
s->name, wl->idx, window_pane_index(w, wp));
s->name, wl->idx, idx);
return (-1);
}

View File

@@ -25,7 +25,7 @@
#include "tmux.h"
/*
* Saves a session paste buffer to a file.
* Saves a paste buffer to a file.
*/
int cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *);
@@ -45,8 +45,9 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c = ctx->cmdclient;
struct session *s;
struct paste_buffer *pb;
const char *path;
const char *path, *newpath, *wd;
char *cause;
int buffer;
mode_t mask;
@@ -80,6 +81,20 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
}
bufferevent_write(c->stdout_event, pb->data, pb->size);
} else {
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(ctx, 0)) != NULL) {
wd = options_get_string(&s->options, "default-path");
if (*wd == '\0')
wd = s->cwd;
} else
wd = NULL;
if (wd != NULL && *wd != '\0') {
newpath = get_full_path(wd, path);
if (newpath != NULL)
path = newpath;
}
mask = umask(S_IRWXG | S_IRWXO);
if (args_has(self->args, 'a'))
f = fopen(path, "ab");

View File

@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -30,8 +31,8 @@ int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send",
"t:", 0, -1,
"[-t target-pane] key ...",
"Rt:", 0, -1,
"[-R] [-t target-pane] key ...",
0,
NULL,
NULL,
@@ -44,12 +45,29 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
struct args *args = self->args;
struct window_pane *wp;
struct session *s;
struct input_ctx *ictx;
const char *str;
int i, key;
if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
return (-1);
if (args_has(args, 'R')) {
ictx = &wp->ictx;
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;
if (wp->mode == NULL)
screen_write_start(&ictx->ctx, wp, &wp->base);
else
screen_write_start(&ictx->ctx, NULL, &wp->base);
screen_write_reset(&ictx->ctx);
screen_write_stop(&ictx->ctx);
}
for (i = 0; i < args->argc; i++) {
str = args->argv[i];

View File

@@ -28,8 +28,8 @@ int cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_send_prefix_entry = {
"send-prefix", NULL,
"t:", 0, 0,
CMD_TARGET_PANE_USAGE,
"2t:", 0, 0,
"[-2] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
@@ -42,13 +42,16 @@ cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
struct args *args = self->args;
struct session *s;
struct window_pane *wp;
struct keylist *keylist;
int key;
if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
return (-1);
keylist = options_get_data(&s->options, "prefix");
window_pane_key(wp, s, ARRAY_FIRST(keylist));
if (args_has(args, '2'))
key = options_get_number(&s->options, "prefix2");
else
key = options_get_number(&s->options, "prefix");
window_pane_key(wp, s, key);
return (0);
}

View File

@@ -23,7 +23,7 @@
#include "tmux.h"
/*
* Add or set a session paste buffer.
* Add or set a paste buffer.
*/
int cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *);

View File

@@ -45,7 +45,7 @@ struct options_entry *cmd_set_option_string(struct cmd *, struct cmd_ctx *,
struct options_entry *cmd_set_option_number(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_keys(struct cmd *, struct cmd_ctx *,
struct options_entry *cmd_set_option_key(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_colour(struct cmd *, struct cmd_ctx *,
@@ -236,8 +236,8 @@ cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx,
case OPTIONS_TABLE_NUMBER:
o = cmd_set_option_number(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_KEYS:
o = cmd_set_option_keys(self, ctx, oe, oo, value);
case OPTIONS_TABLE_KEY:
o = cmd_set_option_key(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_COLOUR:
o = cmd_set_option_colour(self, ctx, oe, oo, value);
@@ -298,31 +298,19 @@ cmd_set_option_number(unused struct cmd *self, struct cmd_ctx *ctx,
return (options_set_number(oo, oe->name, ll));
}
/* Set a keys option. */
/* Set a key option. */
struct options_entry *
cmd_set_option_keys(unused struct cmd *self, struct cmd_ctx *ctx,
cmd_set_option_key(unused struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{
struct keylist *keylist;
char *copy, *ptr, *s;
int key;
int key;
keylist = xmalloc(sizeof *keylist);
ARRAY_INIT(keylist);
ptr = copy = xstrdup(value);
while ((s = strsep(&ptr, ",")) != NULL) {
if ((key = key_string_lookup_string(s)) == KEYC_NONE) {
ctx->error(ctx, "unknown key: %s", s);
xfree(copy);
xfree(keylist);
return (NULL);
}
ARRAY_ADD(keylist, key);
if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
ctx->error(ctx, "bad key: %s", value);
return (NULL);
}
xfree(copy);
return (options_set_data(oo, oe->name, keylist, xfree));
return (options_set_number(oo, oe->name, key));
}
/* Set a colour option. */

View File

@@ -21,7 +21,7 @@
#include "tmux.h"
/*
* Show a session paste buffer.
* Show a paste buffer.
*/
int cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *);

View File

@@ -57,8 +57,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w;
struct window_pane *wp, *new_wp = NULL;
struct environ env;
char *cmd, *cwd, *cause;
const char *shell;
const char *cmd, *cwd, *shell;
char *cause, *new_cause;
u_int hlimit, paneidx;
int size, percentage;
enum layout_type type;
@@ -77,13 +77,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
cwd = options_get_string(&s->options, "default-path");
if (*cwd == '\0') {
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
cwd = ctx->cmdclient->cwd;
else
cwd = s->cwd;
}
cwd = cmd_get_default_path(ctx);
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
@@ -93,16 +87,18 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (args_has(args, 'l')) {
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "size %s", cause);
xasprintf(&new_cause, "size %s", cause);
xfree(cause);
return (-1);
cause = new_cause;
goto error;
}
} else if (args_has(args, 'p')) {
percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "percentage %s", cause);
xasprintf(&new_cause, "percentage %s", cause);
xfree(cause);
return (-1);
cause = new_cause;
goto error;
}
if (type == LAYOUT_TOPBOTTOM)
size = (wp->sy * percentage) / 100;
@@ -137,7 +133,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
environ_free(&env);
if (args_has(args, 'P')) {
paneidx = window_pane_index(wl->window, new_wp);
if (window_pane_index(new_wp, &paneidx) != 0)
fatalx("index not found");
ctx->print(ctx, "%s:%u.%u", s->name, wl->idx, paneidx);
}
return (0);

View File

@@ -32,9 +32,9 @@ int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc",
"lc:npt:", 0, 0,
"[-lnp] [-c target-client] [-t target-session]",
0,
"lc:npt:r", 0, 0,
"[-lnpr] [-c target-client] [-t target-session]",
CMD_READONLY,
cmd_switch_client_key_binding,
NULL,
cmd_switch_client_exec
@@ -67,6 +67,16 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((c = cmd_find_client(ctx, args_get(args, 'c'))) == NULL)
return (-1);
if (args_has(args, 'r')) {
if (c->flags & CLIENT_READONLY) {
c->flags &= ~CLIENT_READONLY;
ctx->info(ctx, "made client writable");
} else {
c->flags |= CLIENT_READONLY;
ctx->info(ctx, "made client read-only");
}
}
s = NULL;
if (args_has(args, 'n')) {
if ((s = session_next_session(c->session)) == NULL) {
@@ -98,6 +108,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
recalculate_sizes();
server_check_unattached();
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
return (0);
}

View File

@@ -57,11 +57,9 @@ cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
int key;
if (args_has(args, 'a')) {
while (!SPLAY_EMPTY(&key_bindings)) {
bd = SPLAY_ROOT(&key_bindings);
SPLAY_REMOVE(key_bindings, &key_bindings, bd);
cmd_list_free(bd->cmdlist);
xfree(bd);
while (!RB_EMPTY(&key_bindings)) {
bd = RB_ROOT(&key_bindings);
key_bindings_remove(bd->key);
}
return (0);
}
@@ -97,8 +95,8 @@ cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key)
mtmp.key = key;
mtmp.mode = !!args_has(args, 'c');
if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
SPLAY_REMOVE(mode_key_tree, mtab->tree, mbind);
if ((mbind = RB_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
RB_REMOVE(mode_key_tree, mtab->tree, mbind);
xfree(mbind);
}
return (0);

32
cmd.c
View File

@@ -1212,3 +1212,35 @@ cmd_template_replace(char *template, const char *s, int idx)
return (buf);
}
/* Return the default path for a new pane. */
const char *
cmd_get_default_path(struct cmd_ctx *ctx)
{
const char *cwd;
struct session *s;
struct window_pane *wp;
struct environ_entry *envent;
if ((s = cmd_current_session(ctx, 0)) == NULL)
return (NULL);
cwd = options_get_string(&s->options, "default-path");
if ((cwd[0] == '~' && cwd[1] == '\0') || !strcmp(cwd, "$HOME")) {
envent = environ_find(&global_environ, "HOME");
if (envent != NULL && *envent->value != '\0')
return envent->value;
cwd = "";
}
if (*cwd == '\0') {
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
return (ctx->cmdclient->cwd);
if (ctx->curclient != NULL) {
wp = s->curw->window->active;
if ((cwd = osdep_get_cwd(wp->pid)) != NULL)
return (cwd);
}
return (s->cwd);
}
return (cwd);
}

View File

@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -41,7 +40,7 @@ struct colour_rgb {
struct colour_rgb *colour_rgb_256;
void colour_rgb_generate256(void);
double colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
u_int colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
int colour_rgb_find(struct colour_rgb *);
/* Generate 256 colour RGB table. */
@@ -91,7 +90,7 @@ colour_rgb_generate256(void)
}
/* Get colour RGB distance. */
double
u_int
colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
{
int r, g, b;
@@ -99,21 +98,20 @@ colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
r = rgb1->r - rgb2->r;
g = rgb1->g - rgb2->g;
b = rgb1->b - rgb2->b;
return (sqrt(r * r + g * g + b * b));
return (r * r + g * g + b * b);
}
/* Work out the nearest colour from the 256 colour set. */
int
colour_rgb_find(struct colour_rgb *rgb)
{
double distance, lowest;
u_int colour, i;
u_int distance, lowest, colour, i;
if (colour_rgb_256 == NULL)
colour_rgb_generate256();
colour = 16;
lowest = INFINITY;
lowest = UINT_MAX;
for (i = 0; i < 240; i++) {
distance = colour_rgb_distance(&colour_rgb_256[i], rgb);
if (distance < lowest) {
@@ -172,6 +170,22 @@ colour_tostring(int c)
return ("white");
case 8:
return ("default");
case 90:
return ("brightblack");
case 91:
return ("brightred");
case 92:
return ("brightgreen");
case 93:
return ("brightyellow");
case 94:
return ("brightblue");
case 95:
return ("brightmagenta");
case 96:
return ("brightcyan");
case 97:
return ("brightwhite");
}
return (NULL);
}
@@ -221,6 +235,30 @@ colour_fromstring(const char *s)
return (7);
if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0'))
return (8);
if (strcasecmp(s, "brightblack") == 0 ||
(s[0] == '9' && s[1] == '0' && s[1] == '\0'))
return (90);
if (strcasecmp(s, "brightred") == 0 ||
(s[0] == '9' && s[1] == '1' && s[1] == '\0'))
return (91);
if (strcasecmp(s, "brightgreen") == 0 ||
(s[0] == '9' && s[1] == '2' && s[1] == '\0'))
return (92);
if (strcasecmp(s, "brightyellow") == 0 ||
(s[0] == '9' && s[1] == '3' && s[1] == '\0'))
return (93);
if (strcasecmp(s, "brightblue") == 0 ||
(s[0] == '9' && s[1] == '4' && s[1] == '\0'))
return (94);
if (strcasecmp(s, "brightmagenta") == 0 ||
(s[0] == '9' && s[1] == '5' && s[1] == '\0'))
return (95);
if (strcasecmp(s, "brightcyan") == 0 ||
(s[0] == '9' && s[1] == '6' && s[1] == '\0'))
return (96);
if (strcasecmp(s, "brightwhite") == 0 ||
(s[0] == '9' && s[1] == '7' && s[1] == '\0'))
return (97);
return (-1);
}

View File

@@ -196,6 +196,11 @@ size_t strlcat(char *, const char *, size_t);
int daemon(int, int);
#endif
#ifndef HAVE_B64_NTOP
/* b64_ntop.c */
int b64_ntop(const char *, size_t, char *, size_t);
#endif
#ifndef HAVE_FORKPTY
/* forkpty.c */
#include <sys/ioctl.h>

View File

@@ -44,12 +44,15 @@ int
vasprintf(char **ret, const char *fmt, va_list ap)
{
int n;
va_list ap2;
va_copy(ap2, ap);
if ((n = vsnprintf(NULL, 0, fmt, ap)) < 0)
goto error;
*ret = xmalloc(n + 1);
if ((n = vsnprintf(*ret, n + 1, fmt, ap)) < 0) {
if ((n = vsnprintf(*ret, n + 1, fmt, ap2)) < 0) {
xfree(*ret);
goto error;
}

182
compat/b64_ntop.c Normal file
View File

@@ -0,0 +1,182 @@
/*
* Copyright (c) 1996, 1998 by Internet Software Consortium.
*
* 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 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.
*/
/*
* Portions Copyright (c) 1995 by International Business Machines, Inc.
*
* International Business Machines, Inc. (hereinafter called IBM) grants
* permission under its copyrights to use, copy, modify, and distribute this
* Software with or without fee, provided that the above copyright notice and
* all paragraphs of this notice appear in all copies, and that the name of IBM
* not be used in connection with the marketing of any product incorporating
* the Software or modifications thereof, without specific, written prior
* permission.
*
* To the extent it has a right to do so, IBM grants an immunity from suit
* under its patents, if any, for the use, sale or manufacture of products to
* the extent that such products are used for performing Domain Name System
* dynamic updates in TCP/IP networks by means of the Software. No immunity is
* granted for any product per se or for any other function of any product.
*
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Assert(Cond) if (!(Cond)) abort()
static const char Base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char Pad64 = '=';
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
The following encoding technique is taken from RFC 1521 by Borenstein
and Freed. It is reproduced here in a slightly edited form for
convenience.
A 65-character subset of US-ASCII is used, enabling 6 bits to be
represented per printable character. (The extra 65th character, "=",
is used to signify a special processing function.)
The encoding process represents 24-bit groups of input bits as output
strings of 4 encoded characters. Proceeding from left to right, a
24-bit input group is formed by concatenating 3 8-bit input groups.
These 24 bits are then treated as 4 concatenated 6-bit groups, each
of which is translated into a single digit in the base64 alphabet.
Each 6-bit group is used as an index into an array of 64 printable
characters. The character referenced by the index is placed in the
output string.
Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
Special processing is performed if fewer than 24 bits are available
at the end of the data being encoded. A full encoding quantum is
always completed at the end of a quantity. When fewer than 24 input
bits are available in an input group, zero bits are added (on the
right) to form an integral number of 6-bit groups. Padding at the
end of the data is performed using the '=' character.
Since all base64 input is an integral number of octets, only the
-------------------------------------------------
following cases can arise:
(1) the final quantum of encoding input is an integral
multiple of 24 bits; here, the final unit of encoded
output will be an integral multiple of 4 characters
with no "=" padding,
(2) the final quantum of encoding input is exactly 8 bits;
here, the final unit of encoded output will be two
characters followed by two "=" padding characters, or
(3) the final quantum of encoding input is exactly 16 bits;
here, the final unit of encoded output will be three
characters followed by one "=" padding character.
*/
int
b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
size_t datalength = 0;
uint8_t input[3];
uint8_t output[4];
size_t i;
while (2 < srclength) {
input[0] = *src++;
input[1] = *src++;
input[2] = *src++;
srclength -= 3;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
output[3] = input[2] & 0x3f;
Assert(output[0] < 64);
Assert(output[1] < 64);
Assert(output[2] < 64);
Assert(output[3] < 64);
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
target[datalength++] = Base64[output[2]];
target[datalength++] = Base64[output[3]];
}
/* Now we worry about padding. */
if (0 != srclength) {
/* Get what's left. */
input[0] = input[1] = input[2] = '\0';
for (i = 0; i < srclength; i++)
input[i] = *src++;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
Assert(output[0] < 64);
Assert(output[1] < 64);
Assert(output[2] < 64);
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
if (srclength == 1)
target[datalength++] = Pad64;
else
target[datalength++] = Base64[output[2]];
target[datalength++] = Pad64;
}
if (datalength >= targsize)
return (-1);
target[datalength] = '\0'; /* Returned value doesn't count \0. */
return (datalength);
}

View File

@@ -1,7 +1,7 @@
# $Id$
# Miscellaneous autofoo bullshit.
AC_INIT(tmux, 1.5)
AC_INIT(tmux, 1.6)
AC_CONFIG_AUX_DIR(etc)
AM_INIT_AUTOMAKE([foreign])
@@ -12,6 +12,7 @@ AC_CANONICAL_HOST
# autoconf will automatically use CFLAGS="-O2 -g". Prevent that by using an
# empty default.
: ${CFLAGS=""}
# Set up the compiler in two different ways and say yes we may want to install.
AC_PROG_CC
AM_PROG_CC_C_O
@@ -52,9 +53,8 @@ AM_CONDITIONAL(IS_DEBUG, test "x$found_debug" = xyes)
AC_ARG_ENABLE(
static,
AC_HELP_STRING(--enable-static, create a static build),
[found_static=$enable_static]
[LDFLAGS="$LDFLAGS -static"]
)
AM_CONDITIONAL(IS_STATIC, test "x" = xyes)
# Is this gcc?
AM_CONDITIONAL(IS_GCC, test "x$GCC" = xyes)
@@ -102,12 +102,28 @@ AM_CONDITIONAL(IS_GLIBC, test "x$found_glibc" = xyes)
AC_MSG_RESULT($found_glibc)
# Look for clock_gettime. Must come before event_init.
AC_CHECK_LIB(rt, clock_gettime)
AC_SEARCH_LIBS(clock_gettime, rt)
# Look for libevent.
AC_SEARCH_LIBS(event_init, [event event-1.4 event2], found_libevent=yes, found_libevent=no)
PKG_CHECK_MODULES(
LIBEVENT,
libevent,
[
CPPFLAGS="$LIBEVENT_CFLAGS $CPPFLAGS"
LIBS="$LIBEVENT_LIBS $LIBS"
found_libevent=yes
],
[
AC_SEARCH_LIBS(
event_init,
[event event-1.4 event2],
found_libevent=yes,
found_libevent=no
)
]
)
if test "x$found_libevent" = xno; then
AC_MSG_ERROR("libevent not found")
AC_MSG_ERROR("libevent not found")
fi
# Look for curses.
@@ -121,16 +137,48 @@ if test "x$found_curses" = xno; then
AC_MSG_ERROR("curses not found")
fi
# Check for b64_ntop.
AC_MSG_CHECKING(for b64_ntop)
AC_TRY_LINK(
[
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
],
[b64_ntop(NULL, 0, NULL, 0);],
found_b64_ntop=yes,
found_b64_ntop=no
)
if test "x$found_b64_ntop" = xno; then
AC_MSG_RESULT(no)
AC_MSG_CHECKING(for b64_ntop with -lresolv)
LIBS="$LIBS -lresolv"
AC_TRY_LINK(
[
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
],
[b64_ntop(NULL, 0, NULL, 0);],
found_b64_ntop=yes,
found_b64_ntop=no
)
if test "x$found_b64_ntop" = xno; then
AC_MSG_RESULT(no)
fi
fi
if test "x$found_b64_ntop" = xyes; then
AC_DEFINE(HAVE_B64_NTOP)
AC_MSG_RESULT(yes)
fi
AM_CONDITIONAL(NO_B64_NTOP, [test "x$found_b64_ntop" = xno])
# Look for networking libraries.
AC_SEARCH_LIBS(b64_ntop, resolv)
AC_SEARCH_LIBS(__b64_ntop, resolv)
AC_SEARCH_LIBS(inet_ntoa, nsl)
AC_SEARCH_LIBS(socket, socket)
AC_CHECK_LIB(xnet, socket)
# Look for sqrt.
AC_SEARCH_LIBS(sqrt, m)
# Check for CMSG_DATA. Some platforms require _XOPEN_SOURCE_EXTENDED (for
# example see xopen_networking(7) on HP-UX).
XOPEN_DEFINES=
@@ -291,6 +339,7 @@ AM_CONDITIONAL(NO_GETOPT, [test "x$found_getopt" = xno])
AC_CHECK_FUNCS(
[ \
bzero \
dirfd \
setproctitle \
sysconf \
]
@@ -298,7 +347,7 @@ AC_CHECK_FUNCS(
# Check for BSD-style integer types.
AC_MSG_CHECKING(for BSD-style unsigned types)
AC_COMPILE_IFELSE(
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[
#include <sys/types.h>
#ifdef HAVE_STDINT_H
@@ -308,7 +357,7 @@ AC_COMPILE_IFELSE(
#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)
)
@@ -332,7 +381,7 @@ fi
# Look for __progname.
AC_MSG_CHECKING(for __progname)
AC_LINK_IFELSE(
AC_LINK_IFELSE([AC_LANG_SOURCE(
[
#include <stdio.h>
#include <stdlib.h>
@@ -342,7 +391,7 @@ AC_LINK_IFELSE(
printf("%s\n", cp);
exit(0);
}
],
])],
[AC_DEFINE(HAVE___PROGNAME) AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no)
)
@@ -364,15 +413,6 @@ else
AC_MSG_RESULT(no)
fi
# Look for /proc/$$/fd.
AC_MSG_CHECKING(for /proc/\$\$/fd)
if test -d /proc/$$/fd; then
AC_DEFINE(HAVE_DIRFD)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
# Figure out the platform for osdep-*.c and forkpty-*.c.
AC_MSG_CHECKING(platform)
case "$host_os" in
@@ -385,11 +425,15 @@ case "$host_os" in
AC_DEFINE(BROKEN_CMSG_FIRSTHDR)
PLATFORM=darwin
;;
*dragonfly*)
AC_MSG_RESULT(dragonfly)
PLATFORM=dragonfly
;;
*linux*)
AC_MSG_RESULT(linux)
PLATFORM=linux
;;
*freebsd*|*dragonfly*)
*freebsd*)
AC_MSG_RESULT(freebsd)
PLATFORM=freebsd
;;
@@ -421,6 +465,7 @@ esac
AC_SUBST(PLATFORM)
AM_CONDITIONAL(IS_AIX, test "x$PLATFORM" = xaix)
AM_CONDITIONAL(IS_DARWIN, test "x$PLATFORM" = xdarwin)
AM_CONDITIONAL(IS_DRAGONFLY, test "x$PLATFORM" = xdragonfly)
AM_CONDITIONAL(IS_LINUX, test "x$PLATFORM" = xlinux)
AM_CONDITIONAL(IS_FREEBSD, test "x$PLATFORM" = xfreebsd)
AM_CONDITIONAL(IS_NETBSD, test "x$PLATFORM" = xnetbsd)

View File

@@ -26,7 +26,7 @@ bind x lock-server
# screen ^C c
unbind ^C
bind ^C new-window
bind c
unbind c
bind c new-window
# detach ^D d

View File

@@ -47,11 +47,11 @@ syn keyword tmuxCmds capture-pane joinp join-pane choose-buffer
syn keyword tmuxOptsSet prefix status status-fg status-bg bell-action
syn keyword tmuxOptsSet default-command history-limit status-left status-right
syn keyword tmuxOptsSet status-interval set-titles display-time buffer-limit
syn keyword tmuxOptsSet status-left-length status-right-length message-fg
syn keyword tmuxOptsSet message-bg lock-after-time default-path repeat-time
syn keyword tmuxOptsSet message-attr status-attr status-keys set-remain-on-exit
syn keyword tmuxOptsSet status-utf8 default-terminal visual-activity
syn keyword tmuxOptsSet visual-bell visual-content status-justify
syn keyword tmuxOptsSet status-left-length status-right-length
syn keyword tmuxOptsSet message-[command-]bg lock-after-time default-path
syn keyword tmuxOptsSet message-[command-]attr status-attr set-remain-on-exit
syn keyword tmuxOptsSet status-utf8 default-terminal visual-activity repeat-time
syn keyword tmuxOptsSet visual-bell visual-content status-justify status-keys
syn keyword tmuxOptsSet terminal-overrides status-left-attr status-left-bg
syn keyword tmuxOptsSet status-left-fg status-right-attr status-right-bg
syn keyword tmuxOptsSet status-right-fg update-environment base-index
@@ -59,9 +59,11 @@ syn keyword tmuxOptsSet display-panes-colour display-panes-time default-shell
syn keyword tmuxOptsSet set-titles-string lock-command lock-server
syn keyword tmuxOptsSet mouse-select-pane message-limit quiet escape-time
syn keyword tmuxOptsSet pane-active-border-bg pane-active-border-fg
syn keyword tmuxOptsSet pane-border-bg pane-border-fg
syn keyword tmuxOptsSet pane-border-bg pane-border-fg message-[command-]fg
syn keyword tmuxOptsSet display-panes-active-colour alternate-screen
syn keyword tmuxOptsSet detach-on-destroy
syn keyword tmuxOptsSet detach-on-destroy word-separators
syn keyword tmuxOptsSet destroy-unattached exit-unattached set-clipboard
syn keyword tmuxOptsSet bell-on-alert mouse-select-window mouse-utf8
syn keyword tmuxOptsSetw monitor-activity aggressive-resize force-width
syn keyword tmuxOptsSetw force-height remain-on-exit uft8 mode-fg mode-bg
@@ -72,12 +74,13 @@ syn keyword tmuxOptsSetw main-pane-width main-pane-height monitor-content
syn keyword tmuxOptsSetw window-status-current-attr window-status-current-bg
syn keyword tmuxOptsSetw window-status-current-fg mode-mouse synchronize-panes
syn keyword tmuxOptsSetw window-status-format window-status-current-format
syn keyword tmuxOptsSetw word-separators window-status-alert-alert
syn keyword tmuxOptsSetw window-status-alert-attr
syn keyword tmuxOptsSetw window-status-alert-bg window-status-alert-fg
syn keyword tmuxOptsSetw pane-base-index other-pane-height other-pane-width
syn keyword tmuxTodo FIXME NOTE TODO XXX contained
syn match tmuxKey /\(C-\|M-\|\^\)\p/ display
syn match tmuxKey /\(C-\|M-\|\^\)\+\S\+/ display
syn match tmuxNumber /\d\+/ display
syn match tmuxOptions /\s-\a\+/ display
syn match tmuxVariable /\w\+=/ display

393
format.c Normal file
View File

@@ -0,0 +1,393 @@
/* $Id$ */
/*
* Copyright (c) 2011 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 <netdb.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
/*
* Build a list of key-value pairs and use them to expand #{key} entries in a
* string.
*/
int format_replace(struct format_tree *,
const char *, size_t, char **, size_t *, size_t *);
/* Format key-value replacement entry. */
RB_GENERATE(format_tree, format_entry, entry, format_cmp);
/* Format tree comparison function. */
int
format_cmp(struct format_entry *fe1, struct format_entry *fe2)
{
return (strcmp(fe1->key, fe2->key));
}
/* Single-character aliases. */
const char *format_aliases[26] = {
NULL, /* A */
NULL, /* B */
NULL, /* C */
"pane_id", /* D */
NULL, /* E */
"window_flags", /* F */
NULL, /* G */
"host", /* H */
"window_index", /* I */
NULL, /* J */
NULL, /* K */
NULL, /* L */
NULL, /* M */
NULL, /* N */
NULL, /* O */
"pane_index", /* P */
NULL, /* Q */
NULL, /* R */
"session_name", /* S */
"pane_title", /* T */
NULL, /* U */
NULL, /* V */
"window_name", /* W */
NULL, /* X */
NULL, /* Y */
NULL /* Z */
};
/* Create a new tree. */
struct format_tree *
format_create(void)
{
struct format_tree *ft;
char host[MAXHOSTNAMELEN];
ft = xmalloc(sizeof *ft);
RB_INIT(ft);
if (gethostname(host, sizeof host) == 0)
format_add(ft, "host", "%s", host);
return (ft);
}
/* Free a tree. */
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);
RB_REMOVE(format_tree, ft, fe);
xfree(fe->value);
xfree(fe->key);
xfree(fe);
}
xfree (ft);
}
/* Add a key-value pair. */
void
format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
{
struct format_entry *fe;
va_list ap;
fe = xmalloc(sizeof *fe);
fe->key = xstrdup(key);
va_start(ap, fmt);
xvasprintf(&fe->value, fmt, ap);
va_end(ap);
RB_INSERT(format_tree, ft, fe);
}
/* Find a format entry. */
const char *
format_find(struct format_tree *ft, const char *key)
{
struct format_entry *fe, fe_find;
fe_find.key = (char *) key;
fe = RB_FIND(format_tree, ft, &fe_find);
if (fe == NULL)
return (NULL);
return (fe->value);
}
/*
* Replace a key/value pair in buffer. #{blah} is expanded directly,
* #{?blah,a,b} is replace with a if blah exists and is nonzero else b.
*/
int
format_replace(struct format_tree *ft,
const char *key, size_t keylen, char **buf, size_t *len, size_t *off)
{
char *copy, *ptr;
const char *value;
size_t valuelen;
/* Make a copy of the key. */
copy = xmalloc(keylen + 1);
memcpy(copy, key, keylen);
copy[keylen] = '\0';
/*
* Is this a conditional? If so, check it exists and extract either the
* first or second element. If not, look up the key directly.
*/
if (*copy == '?') {
ptr = strchr(copy, ',');
if (ptr == NULL)
goto fail;
*ptr = '\0';
value = format_find(ft, copy + 1);
if (value != NULL && (value[0] != '0' || value[1] != '\0')) {
value = ptr + 1;
ptr = strchr(value, ',');
if (ptr == NULL)
goto fail;
*ptr = '\0';
} else {
ptr = strchr(ptr + 1, ',');
if (ptr == NULL)
goto fail;
value = ptr + 1;
}
} else {
value = format_find(ft, copy);
if (value == NULL)
value = "";
}
valuelen = strlen(value);
/* Expand the buffer and copy in the value. */
while (*len - *off < valuelen + 1) {
*buf = xrealloc(*buf, 2, *len);
*len *= 2;
}
memcpy(*buf + *off, value, valuelen);
*off += valuelen;
xfree(copy);
return (0);
fail:
xfree(copy);
return (-1);
}
/* Expand keys in a template. */
char *
format_expand(struct format_tree *ft, const char *fmt)
{
char *buf, *ptr;
const char *s;
size_t off, len, n;
int ch;
len = 64;
buf = xmalloc(len);
off = 0;
while (*fmt != '\0') {
if (*fmt != '#') {
while (len - off < 2) {
buf = xrealloc(buf, 2, len);
len *= 2;
}
buf[off++] = *fmt++;
continue;
}
fmt++;
ch = (u_char) *fmt++;
switch (ch) {
case '{':
ptr = strchr(fmt, '}');
if (ptr == NULL)
break;
n = ptr - fmt;
if (format_replace(ft, fmt, n, &buf, &len, &off) != 0)
break;
fmt += n + 1;
continue;
default:
if (ch >= 'A' && ch <= 'Z') {
s = format_aliases[ch - 'A'];
if (s != NULL) {
n = strlen(s);
if (format_replace (
ft, s, n, &buf, &len, &off) != 0)
break;
continue;
}
}
while (len - off < 2) {
buf = xrealloc(buf, 2, len);
len *= 2;
}
buf[off++] = ch;
continue;
}
break;
}
buf[off] = '\0';
return (buf);
}
/* Set default format keys for a session. */
void
format_session(struct format_tree *ft, struct session *s)
{
struct session_group *sg;
char *tim;
time_t t;
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);
format_add(ft, "session_height", "%u", s->sy);
sg = session_group_find(s);
format_add(ft, "session_grouped", "%d", sg != NULL);
if (sg != NULL)
format_add(ft, "session_group", "%u", session_group_index(sg));
t = s->creation_time.tv_sec;
format_add(ft, "session_created", "%ld", (long) t);
tim = ctime(&t);
*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);
}
/* Set default format keys for a client. */
void
format_client(struct format_tree *ft, struct client *c)
{
char *tim;
time_t t;
format_add(ft, "client_cwd", "%s", c->cwd);
format_add(ft, "client_height", "%u", c->tty.sx);
format_add(ft, "client_width", "%u", c->tty.sy);
format_add(ft, "client_tty", "%s", c->tty.path);
format_add(ft, "client_termname", "%s", c->tty.termname);
t = c->creation_time.tv_sec;
format_add(ft, "client_created", "%ld", (long) t);
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
format_add(ft, "client_created_string", "%s", tim);
t = c->activity_time.tv_sec;
format_add(ft, "client_activity", "%ld", (long) t);
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
format_add(ft, "client_activity_string", "%s", tim);
if (c->tty.flags & TTY_UTF8)
format_add(ft, "client_utf8", "%d", 1);
else
format_add(ft, "client_utf8", "%d", 0);
if (c->flags & CLIENT_READONLY)
format_add(ft, "client_readonly", "%d", 1);
else
format_add(ft, "client_readonly", "%d", 0);
}
/* Set default format keys for a winlink. */
void
format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
{
struct window *w = wl->window;
char *layout, *flags;
layout = layout_dump(w);
flags = window_printable_flags(s, wl);
format_add(ft, "window_index", "%d", wl->idx);
format_add(ft, "window_name", "%s", w->name);
format_add(ft, "window_width", "%u", w->sx);
format_add(ft, "window_height", "%u", w->sy);
format_add(ft, "window_flags", "%s", flags);
format_add(ft, "window_layout", "%s", layout);
format_add(ft, "window_active", "%d", wl == s->curw);
xfree(flags);
xfree(layout);
}
/* Set default format keys for a window pane. */
void
format_window_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;
u_int idx;
size = 0;
for (i = 0; i < gd->hsize; i++) {
gl = &gd->linedata[i];
size += gl->cellsize * sizeof *gl->celldata;
size += gl->utf8size * sizeof *gl->utf8data;
}
size += gd->hsize * sizeof *gd->linedata;
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
format_add(ft, "pane_width", "%u", wp->sx);
format_add(ft, "pane_height", "%u", wp->sy);
format_add(ft, "pane_title", "%s", wp->base.title);
format_add(ft, "pane_index", "%u", idx);
format_add(ft, "history_size", "%u", gd->hsize);
format_add(ft, "history_limit", "%u", gd->hlimit);
format_add(ft, "history_bytes", "%llu", size);
format_add(ft, "pane_id", "%%%u", wp->id);
format_add(ft, "pane_active", "%d", wp == wp->window->active);
format_add(ft, "pane_dead", "%d", wp->fd == -1);
if (wp->cmd != NULL)
format_add(ft, "pane_start_command", "%s", wp->cmd);
if (wp->cwd != NULL)
format_add(ft, "pane_start_path", "%s", wp->cwd);
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
format_add(ft, "pane_tty", "%s", wp->tty);
}

View File

@@ -203,6 +203,7 @@ input_mouse(struct window_pane *wp, struct mouse_event *m)
{
char buf[10];
size_t len;
int value;
if (wp->screen->mode & ALL_MOUSE_MODES) {
if (wp->screen->mode & MODE_MOUSE_UTF8) {
@@ -220,7 +221,8 @@ input_mouse(struct window_pane *wp, struct mouse_event *m)
}
bufferevent_write(wp->event, buf, len);
} else if ((m->b & MOUSE_BUTTON) != MOUSE_2) {
if (options_get_number(&wp->window->options, "mode-mouse") &&
value = options_get_number(&wp->window->options, "mode-mouse");
if (value == 1 &&
window_pane_set_mode(wp, &window_copy_mode) == 0) {
window_copy_init_from_pane(wp);
if (wp->mode->mouse != NULL)

52
input.c
View File

@@ -119,6 +119,8 @@ const struct input_table_entry input_esc_table[] = {
/* Control (CSI) commands. */
enum input_csi_type {
INPUT_CSI_CBT,
INPUT_CSI_CNL,
INPUT_CSI_CPL,
INPUT_CSI_CUB,
INPUT_CSI_CUD,
INPUT_CSI_CUF,
@@ -135,8 +137,10 @@ enum input_csi_type {
INPUT_CSI_HPA,
INPUT_CSI_ICH,
INPUT_CSI_IL,
INPUT_CSI_RCP,
INPUT_CSI_RM,
INPUT_CSI_RM_PRIVATE,
INPUT_CSI_SCP,
INPUT_CSI_SGR,
INPUT_CSI_SM,
INPUT_CSI_SM_PRIVATE,
@@ -151,6 +155,8 @@ const struct input_table_entry input_csi_table[] = {
{ 'B', "", INPUT_CSI_CUD },
{ 'C', "", INPUT_CSI_CUF },
{ 'D', "", INPUT_CSI_CUB },
{ 'E', "", INPUT_CSI_CNL },
{ 'F', "", INPUT_CSI_CPL },
{ 'G', "", INPUT_CSI_HPA },
{ 'H', "", INPUT_CSI_CUP },
{ 'J', "", INPUT_CSI_ED },
@@ -171,6 +177,8 @@ const struct input_table_entry input_csi_table[] = {
{ 'n', "", INPUT_CSI_DSR },
{ 'q', " ", INPUT_CSI_DECSCUSR },
{ 'r', "", INPUT_CSI_DECSTBM },
{ 's', "", INPUT_CSI_SCP },
{ 'u', "", INPUT_CSI_RCP },
};
/* Input transition. */
@@ -970,17 +978,7 @@ input_esc_dispatch(struct input_ctx *ictx)
ictx->old_cx = 0;
ictx->old_cy = 0;
screen_reset_tabs(sctx->s);
screen_write_scrollregion(sctx, 0, screen_size_y(sctx->s) - 1);
screen_write_insertmode(sctx, 0);
screen_write_kcursormode(sctx, 0);
screen_write_kkeypadmode(sctx, 0);
screen_write_mousemode_off(sctx);
screen_write_clearscreen(sctx);
screen_write_cursormove(sctx, 0, 0);
screen_write_reset(sctx);
break;
case INPUT_ESC_IND:
screen_write_linefeed(sctx, 0);
@@ -1081,6 +1079,14 @@ input_csi_dispatch(struct input_ctx *ictx)
case INPUT_CSI_CUU:
screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
break;
case INPUT_CSI_CNL:
screen_write_carriagereturn(sctx);
screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
break;
case INPUT_CSI_CPL:
screen_write_carriagereturn(sctx);
screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
break;
case INPUT_CSI_DA:
switch (input_get(ictx, 0, 0, 0)) {
case 0:
@@ -1126,6 +1132,17 @@ input_csi_dispatch(struct input_ctx *ictx)
case 2:
screen_write_clearscreen(sctx);
break;
case 3:
switch (input_get(ictx, 1, 0, 0)) {
case 0:
/*
* Linux console extension to clear history
* (for example before locking the screen).
*/
screen_write_clearhistory(sctx);
break;
}
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
@@ -1157,6 +1174,10 @@ input_csi_dispatch(struct input_ctx *ictx)
case INPUT_CSI_IL:
screen_write_insertline(sctx, input_get(ictx, 0, 1, 1));
break;
case INPUT_CSI_RCP:
memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
break;
case INPUT_CSI_RM:
switch (input_get(ictx, 0, 0, -1)) {
case 4: /* IRM */
@@ -1196,6 +1217,11 @@ input_csi_dispatch(struct input_ctx *ictx)
break;
}
break;
case INPUT_CSI_SCP:
memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
ictx->old_cx = s->cx;
ictx->old_cy = s->cy;
break;
case INPUT_CSI_SGR:
input_csi_dispatch_sgr(ictx);
break;
@@ -1410,7 +1436,7 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
case 106:
case 107:
gc->flags &= ~GRID_FLAG_BG256;
gc->bg = n;
gc->bg = n - 10;
break;
}
}
@@ -1522,6 +1548,8 @@ input_exit_rename(struct input_ctx *ictx)
{
if (ictx->flags & INPUT_DISCARD)
return;
if (!options_get_number(&ictx->wp->window->options, "allow-rename"))
return;
log_debug("%s: \"%s\"", __func__, ictx->input_buf);
xfree(ictx->wp->window->name);

View File

@@ -24,7 +24,7 @@
#include "tmux.h"
SPLAY_GENERATE(key_bindings, key_binding, entry, key_bindings_cmp);
RB_GENERATE(key_bindings, key_binding, entry, key_bindings_cmp);
struct key_bindings key_bindings;
struct key_bindings dead_key_bindings;
@@ -52,7 +52,7 @@ key_bindings_lookup(int key)
struct key_binding bd;
bd.key = key;
return (SPLAY_FIND(key_bindings, &key_bindings, &bd));
return (RB_FIND(key_bindings, &key_bindings, &bd));
}
void
@@ -64,7 +64,7 @@ key_bindings_add(int key, int can_repeat, struct cmd_list *cmdlist)
bd = xmalloc(sizeof *bd);
bd->key = key;
SPLAY_INSERT(key_bindings, &key_bindings, bd);
RB_INSERT(key_bindings, &key_bindings, bd);
bd->can_repeat = can_repeat;
bd->cmdlist = cmdlist;
@@ -77,8 +77,8 @@ key_bindings_remove(int key)
if ((bd = key_bindings_lookup(key)) == NULL)
return;
SPLAY_REMOVE(key_bindings, &key_bindings, bd);
SPLAY_INSERT(key_bindings, &dead_key_bindings, bd);
RB_REMOVE(key_bindings, &key_bindings, bd);
RB_INSERT(key_bindings, &dead_key_bindings, bd);
}
void
@@ -86,9 +86,9 @@ key_bindings_clean(void)
{
struct key_binding *bd;
while (!SPLAY_EMPTY(&dead_key_bindings)) {
bd = SPLAY_ROOT(&dead_key_bindings);
SPLAY_REMOVE(key_bindings, &dead_key_bindings, 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);
xfree(bd);
}
@@ -179,7 +179,7 @@ key_bindings_init(void)
struct cmd *cmd;
struct cmd_list *cmdlist;
SPLAY_INIT(&key_bindings);
RB_INIT(&key_bindings);
for (i = 0; i < nitems(table); i++) {
cmdlist = xmalloc(sizeof *cmdlist);

View File

@@ -55,7 +55,11 @@ const struct {
{ "Home", KEYC_HOME },
{ "End", KEYC_END },
{ "NPage", KEYC_NPAGE },
{ "PageDown", KEYC_NPAGE },
{ "PgDn", KEYC_NPAGE },
{ "PPage", KEYC_PPAGE },
{ "PageUp", KEYC_PPAGE },
{ "PgUp", KEYC_PPAGE },
{ "Tab", '\011' },
{ "BTab", KEYC_BTAB },
{ "Space", ' ' },
@@ -184,6 +188,10 @@ key_string_lookup_key(int key)
*out = '\0';
/* Handle no key. */
if (key == KEYC_NONE)
return ("none");
/*
* Special case: display C-@ as C-Space. Could do this below in
* the (key >= 0 && key <= 32), but this way we let it be found

View File

@@ -260,8 +260,8 @@ layout_set_main_h(struct window *w)
* If an other pane height was specified, honour it so long as it
* doesn't shrink the main height to less than the main-pane-height
*/
if (otherheight > 1 && w->sx - otherheight > mainheight)
mainheight = w->sx - otherheight;
if (otherheight > 1 && w->sy - otherheight > mainheight)
mainheight = w->sy - otherheight;
if (mainheight < PANE_MINIMUM + 1)
mainheight = PANE_MINIMUM + 1;

View File

@@ -49,11 +49,18 @@ const struct mode_key_cmdstr mode_key_cmdstr_edit[] = {
{ MODEKEYEDIT_DELETE, "delete" },
{ MODEKEYEDIT_DELETELINE, "delete-line" },
{ MODEKEYEDIT_DELETETOENDOFLINE, "delete-end-of-line" },
{ MODEKEYEDIT_DELETEWORD, "delete-word" },
{ MODEKEYEDIT_ENDOFLINE, "end-of-line" },
{ MODEKEYEDIT_ENTER, "enter" },
{ MODEKEYEDIT_HISTORYDOWN, "history-down" },
{ MODEKEYEDIT_HISTORYUP, "history-up" },
{ MODEKEYEDIT_NEXTSPACE, "next-space" },
{ MODEKEYEDIT_NEXTSPACEEND, "next-space-end" },
{ MODEKEYEDIT_NEXTWORD, "next-word" },
{ MODEKEYEDIT_NEXTWORDEND, "next-word-end" },
{ MODEKEYEDIT_PASTE, "paste" },
{ MODEKEYEDIT_PREVIOUSSPACE, "previous-space" },
{ MODEKEYEDIT_PREVIOUSWORD, "previous-word" },
{ MODEKEYEDIT_STARTOFLINE, "start-of-line" },
{ MODEKEYEDIT_SWITCHMODE, "switch-mode" },
{ MODEKEYEDIT_SWITCHMODEAPPEND, "switch-mode-append" },
@@ -94,6 +101,8 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
{ MODEKEYCOPY_JUMPAGAIN, "jump-again" },
{ MODEKEYCOPY_JUMPREVERSE, "jump-reverse" },
{ MODEKEYCOPY_JUMPBACK, "jump-backward" },
{ MODEKEYCOPY_JUMPTO, "jump-to-forward" },
{ MODEKEYCOPY_JUMPTOBACK, "jump-to-backward" },
{ MODEKEYCOPY_LEFT, "cursor-left" },
{ MODEKEYCOPY_RECTANGLETOGGLE, "rectangle-toggle" },
{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
@@ -126,28 +135,43 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
const struct mode_key_entry mode_key_vi_edit[] = {
{ '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL },
{ '\010' /* C-h */, 0, MODEKEYEDIT_BACKSPACE },
{ '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE },
{ '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE },
{ '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE },
{ '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD },
{ '\033' /* Escape */, 0, MODEKEYEDIT_SWITCHMODE },
{ '\r', 0, MODEKEYEDIT_ENTER },
{ KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE },
{ KEYC_DC, 0, MODEKEYEDIT_DELETE },
{ KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN },
{ KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT },
{ KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT },
{ KEYC_UP, 0, MODEKEYEDIT_HISTORYUP },
{ KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE },
{ KEYC_END, 0, MODEKEYEDIT_ENDOFLINE },
{ '$', 1, MODEKEYEDIT_ENDOFLINE },
{ '0', 1, MODEKEYEDIT_STARTOFLINE },
{ 'B', 1, MODEKEYEDIT_PREVIOUSSPACE },
{ 'D', 1, MODEKEYEDIT_DELETETOENDOFLINE },
{ 'E', 1, MODEKEYEDIT_NEXTSPACEEND },
{ 'W', 1, MODEKEYEDIT_NEXTSPACE },
{ 'X', 1, MODEKEYEDIT_BACKSPACE },
{ '\003' /* C-c */, 1, MODEKEYEDIT_CANCEL },
{ '\010' /* C-h */, 1, MODEKEYEDIT_BACKSPACE },
{ '\r', 1, MODEKEYEDIT_ENTER },
{ '^', 1, MODEKEYEDIT_STARTOFLINE },
{ 'a', 1, MODEKEYEDIT_SWITCHMODEAPPEND },
{ 'b', 1, MODEKEYEDIT_PREVIOUSWORD },
{ 'd', 1, MODEKEYEDIT_DELETELINE },
{ 'e', 1, MODEKEYEDIT_NEXTWORDEND },
{ 'h', 1, MODEKEYEDIT_CURSORLEFT },
{ 'i', 1, MODEKEYEDIT_SWITCHMODE },
{ 'j', 1, MODEKEYEDIT_HISTORYDOWN },
{ 'k', 1, MODEKEYEDIT_HISTORYUP },
{ 'l', 1, MODEKEYEDIT_CURSORRIGHT },
{ 'p', 1, MODEKEYEDIT_PASTE },
{ 'w', 1, MODEKEYEDIT_NEXTWORD },
{ 'x', 1, MODEKEYEDIT_DELETE },
{ KEYC_BSPACE, 1, MODEKEYEDIT_BACKSPACE },
{ KEYC_DC, 1, MODEKEYEDIT_DELETE },
{ KEYC_DOWN, 1, MODEKEYEDIT_HISTORYDOWN },
@@ -211,6 +235,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
{ 'L', 0, MODEKEYCOPY_BOTTOMLINE },
{ 'M', 0, MODEKEYCOPY_MIDDLELINE },
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
{ 'T', 0, MODEKEYCOPY_JUMPTOBACK },
{ 'W', 0, MODEKEYCOPY_NEXTSPACE },
{ '\002' /* C-b */, 0, MODEKEYCOPY_PREVIOUSPAGE },
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL },
@@ -232,6 +257,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
{ 'k', 0, MODEKEYCOPY_UP },
{ 'l', 0, MODEKEYCOPY_RIGHT },
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
{ 't', 0, MODEKEYCOPY_JUMPTO },
{ 'q', 0, MODEKEYCOPY_CANCEL },
{ 'v', 0, MODEKEYCOPY_RECTANGLETOGGLE },
{ 'w', 0, MODEKEYCOPY_NEXTWORD },
@@ -255,18 +281,21 @@ const struct mode_key_entry mode_key_emacs_edit[] = {
{ '\002' /* C-b */, 0, MODEKEYEDIT_CURSORLEFT },
{ '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL },
{ '\004' /* C-d */, 0, MODEKEYEDIT_DELETE },
{ '\005' /* C-e */, 0, MODEKEYEDIT_ENDOFLINE },
{ '\005' /* C-e */, 0, MODEKEYEDIT_ENDOFLINE },
{ '\006' /* C-f */, 0, MODEKEYEDIT_CURSORRIGHT },
{ '\010' /* C-H */, 0, MODEKEYEDIT_BACKSPACE },
{ '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE },
{ '\013' /* C-k */, 0, MODEKEYEDIT_DELETETOENDOFLINE },
{ '\010' /* C-H */, 0, MODEKEYEDIT_BACKSPACE },
{ '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE },
{ '\013' /* C-k */, 0, MODEKEYEDIT_DELETETOENDOFLINE },
{ '\016' /* C-n */, 0, MODEKEYEDIT_HISTORYDOWN },
{ '\020' /* C-p */, 0, MODEKEYEDIT_HISTORYUP },
{ '\024' /* C-t */, 0, MODEKEYEDIT_TRANSPOSECHARS },
{ '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE },
{ '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE },
{ '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD },
{ '\031' /* C-y */, 0, MODEKEYEDIT_PASTE },
{ '\033' /* Escape */, 0, MODEKEYEDIT_CANCEL },
{ '\r', 0, MODEKEYEDIT_ENTER },
{ 'b' | KEYC_ESCAPE, 0, MODEKEYEDIT_PREVIOUSWORD },
{ 'f' | KEYC_ESCAPE, 0, MODEKEYEDIT_NEXTWORDEND },
{ 'm' | KEYC_ESCAPE, 0, MODEKEYEDIT_STARTOFLINE },
{ KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE },
{ KEYC_DC, 0, MODEKEYEDIT_DELETE },
@@ -274,6 +303,8 @@ const struct mode_key_entry mode_key_emacs_edit[] = {
{ KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT },
{ KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT },
{ KEYC_UP, 0, MODEKEYEDIT_HISTORYUP },
{ KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE },
{ KEYC_END, 0, MODEKEYEDIT_ENDOFLINE },
{ 0, -1, 0 }
};
@@ -320,6 +351,7 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCOPY_TOPLINE },
{ 'R', 0, MODEKEYCOPY_RECTANGLETOGGLE },
{ 'T', 0, MODEKEYCOPY_JUMPTOBACK },
{ '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION },
{ '\001' /* C-a */, 0, MODEKEYCOPY_STARTOFLINE },
{ '\002' /* C-b */, 0, MODEKEYCOPY_LEFT },
@@ -344,6 +376,7 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
{ 'q', 0, MODEKEYCOPY_CANCEL },
{ 'r' | KEYC_ESCAPE, 0, MODEKEYCOPY_MIDDLELINE },
{ 't', 0, MODEKEYCOPY_JUMPTO },
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSPAGE },
{ 'w' | KEYC_ESCAPE, 0, MODEKEYCOPY_COPYSELECTION },
{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
@@ -379,7 +412,7 @@ const struct mode_key_table mode_key_tables[] = {
{ NULL, NULL, NULL, NULL }
};
SPLAY_GENERATE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
RB_GENERATE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
int
mode_key_cmp(struct mode_key_binding *mbind1, struct mode_key_binding *mbind2)
@@ -429,13 +462,13 @@ mode_key_init_trees(void)
struct mode_key_binding *mbind;
for (mtab = mode_key_tables; mtab->name != NULL; mtab++) {
SPLAY_INIT(mtab->tree);
RB_INIT(mtab->tree);
for (ment = mtab->table; ment->mode != -1; ment++) {
mbind = xmalloc(sizeof *mbind);
mbind->key = ment->key;
mbind->mode = ment->mode;
mbind->cmd = ment->cmd;
SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
RB_INSERT(mode_key_tree, mtab->tree, mbind);
}
}
}
@@ -454,7 +487,7 @@ mode_key_lookup(struct mode_key_data *mdata, int key)
mtmp.key = key;
mtmp.mode = mdata->mode;
if ((mbind = SPLAY_FIND(mode_key_tree, mdata->tree, &mtmp)) == NULL) {
if ((mbind = RB_FIND(mode_key_tree, mdata->tree, &mtmp)) == NULL) {
if (mdata->mode != 0)
return (MODEKEY_NONE);
return (MODEKEY_OTHER);

View File

@@ -35,6 +35,9 @@
const char *options_table_mode_keys_list[] = {
"emacs", "vi", NULL
};
const char *options_table_mode_mouse_list[] = {
"off", "on", "copy-mode", NULL
};
const char *options_table_clock_mode_style_list[] = {
"12", "24", NULL
};
@@ -190,6 +193,21 @@ const struct options_table_entry session_options_table[] = {
.default_num = 3
},
{ .name = "message-command-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = 0
},
{ .name = "message-command-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 0
},
{ .name = "message-command-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 3
},
{ .name = "message-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 0
@@ -243,8 +261,13 @@ const struct options_table_entry session_options_table[] = {
},
{ .name = "prefix",
.type = OPTIONS_TABLE_KEYS,
/* set in main() */
.type = OPTIONS_TABLE_KEY,
.default_num = '\002',
},
{ .name = "prefix2",
.type = OPTIONS_TABLE_KEY,
.default_num = KEYC_NONE,
},
{ .name = "repeat-time",
@@ -372,7 +395,7 @@ const struct options_table_entry session_options_table[] = {
.default_str = "*88col*:colors=88,*256col*:colors=256"
",xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
":Cc=\\E]12;%p1%s\\007:Cr=\\E]112\\007"
":Cs=\\E[%p1%d q:Csr=\\E[2 q"
":Cs=\\E[%p1%d q:Csr=\\E[2 q,screen*:XT"
},
{ .name = "update-environment",
@@ -402,6 +425,11 @@ const struct options_table_entry session_options_table[] = {
.default_num = 0
},
{ .name = "word-separators",
.type = OPTIONS_TABLE_STRING,
.default_str = " -_@"
},
{ .name = NULL }
};
@@ -412,6 +440,11 @@ const struct options_table_entry window_options_table[] = {
.default_num = 0
},
{ .name = "allow-rename",
.type = OPTIONS_TABLE_FLAG,
.default_num = 1
},
{ .name = "alternate-screen",
.type = OPTIONS_TABLE_FLAG,
.default_num = 1
@@ -483,7 +516,8 @@ const struct options_table_entry window_options_table[] = {
},
{ .name = "mode-mouse",
.type = OPTIONS_TABLE_FLAG,
.type = OPTIONS_TABLE_CHOICE,
.choices = options_table_mode_mouse_list,
.default_num = 0
},
@@ -518,6 +552,13 @@ const struct options_table_entry window_options_table[] = {
.default_num = 0
},
{ .name = "pane-base-index",
.type = OPTIONS_TABLE_NUMBER,
.minimum = 0,
.maximum = USHRT_MAX,
.default_num = 0
},
{ .name = "remain-on-exit",
.type = OPTIONS_TABLE_FLAG,
.default_num = 0
@@ -533,17 +574,47 @@ const struct options_table_entry window_options_table[] = {
.default_num = 0 /* overridden in main() */
},
{ .name = "window-status-alert-attr",
{ .name = "window-status-bell-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = GRID_ATTR_REVERSE
},
{ .name = "window-status-alert-bg",
{ .name = "window-status-bell-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
{ .name = "window-status-alert-fg",
{ .name = "window-status-bell-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
{ .name = "window-status-content-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = GRID_ATTR_REVERSE
},
{ .name = "window-status-content-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
{ .name = "window-status-content-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
{ .name = "window-status-activity-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = GRID_ATTR_REVERSE
},
{ .name = "window-status-activity-bg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
{ .name = "window-status-activity-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
},
@@ -588,11 +659,6 @@ const struct options_table_entry window_options_table[] = {
.default_str = "#I:#W#F"
},
{ .name = "word-separators",
.type = OPTIONS_TABLE_STRING,
.default_str = " -_@"
},
{ .name = "xterm-keys",
.type = OPTIONS_TABLE_FLAG,
.default_num = 0
@@ -621,10 +687,8 @@ const char *
options_table_print_entry(
const struct options_table_entry *oe, struct options_entry *o)
{
static char out[BUFSIZ];
const char *s;
struct keylist *keylist;
u_int i;
static char out[BUFSIZ];
const char *s;
*out = '\0';
switch (oe->type) {
@@ -634,14 +698,8 @@ options_table_print_entry(
case OPTIONS_TABLE_NUMBER:
xsnprintf(out, sizeof out, "%lld", o->num);
break;
case OPTIONS_TABLE_KEYS:
keylist = o->data;
for (i = 0; i < ARRAY_LENGTH(keylist); i++) {
s = key_string_lookup_key(ARRAY_ITEM(keylist, i));
strlcat(out, s, sizeof out);
if (i != ARRAY_LENGTH(keylist) - 1)
strlcat(out, ",", sizeof out);
}
case OPTIONS_TABLE_KEY:
xsnprintf(out, sizeof out, "%s", key_string_lookup_key(o->num));
break;
case OPTIONS_TABLE_COLOUR:
s = colour_tostring(o->num);

View File

@@ -28,7 +28,7 @@
* a splay tree.
*/
SPLAY_GENERATE(options_tree, options_entry, entry, options_cmp);
RB_GENERATE(options_tree, options_entry, entry, options_cmp);
int
options_cmp(struct options_entry *o1, struct options_entry *o2)
@@ -39,7 +39,7 @@ options_cmp(struct options_entry *o1, struct options_entry *o2)
void
options_init(struct options *oo, struct options *parent)
{
SPLAY_INIT(&oo->tree);
RB_INIT(&oo->tree);
oo->parent = parent;
}
@@ -48,14 +48,12 @@ options_free(struct options *oo)
{
struct options_entry *o;
while (!SPLAY_EMPTY(&oo->tree)) {
o = SPLAY_ROOT(&oo->tree);
SPLAY_REMOVE(options_tree, &oo->tree, o);
while (!RB_EMPTY(&oo->tree)) {
o = RB_ROOT(&oo->tree);
RB_REMOVE(options_tree, &oo->tree, o);
xfree(o->name);
if (o->type == OPTIONS_STRING)
xfree(o->str);
else if (o->type == OPTIONS_DATA)
o->freefn(o->data);
xfree(o);
}
}
@@ -66,7 +64,7 @@ options_find1(struct options *oo, const char *name)
struct options_entry p;
p.name = (char *) name;
return (SPLAY_FIND(options_tree, &oo->tree, &p));
return (RB_FIND(options_tree, &oo->tree, &p));
}
struct options_entry *
@@ -75,12 +73,12 @@ options_find(struct options *oo, const char *name)
struct options_entry *o, p;
p.name = (char *) name;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
o = RB_FIND(options_tree, &oo->tree, &p);
while (o == NULL) {
oo = oo->parent;
if (oo == NULL)
break;
o = SPLAY_FIND(options_tree, &oo->tree, &p);
o = RB_FIND(options_tree, &oo->tree, &p);
}
return (o);
}
@@ -93,12 +91,10 @@ options_remove(struct options *oo, const char *name)
if ((o = options_find1(oo, name)) == NULL)
return;
SPLAY_REMOVE(options_tree, &oo->tree, o);
RB_REMOVE(options_tree, &oo->tree, o);
xfree(o->name);
if (o->type == OPTIONS_STRING)
xfree(o->str);
else if (o->type == OPTIONS_DATA)
o->freefn(o->data);
xfree(o);
}
@@ -111,11 +107,9 @@ options_set_string(struct options *oo, const char *name, const char *fmt, ...)
if ((o = options_find1(oo, name)) == NULL) {
o = xmalloc(sizeof *o);
o->name = xstrdup(name);
SPLAY_INSERT(options_tree, &oo->tree, o);
RB_INSERT(options_tree, &oo->tree, o);
} else if (o->type == OPTIONS_STRING)
xfree(o->str);
else if (o->type == OPTIONS_DATA)
o->freefn(o->data);
va_start(ap, fmt);
o->type = OPTIONS_STRING;
@@ -144,11 +138,9 @@ options_set_number(struct options *oo, const char *name, long long value)
if ((o = options_find1(oo, name)) == NULL) {
o = xmalloc(sizeof *o);
o->name = xstrdup(name);
SPLAY_INSERT(options_tree, &oo->tree, o);
RB_INSERT(options_tree, &oo->tree, o);
} else if (o->type == OPTIONS_STRING)
xfree(o->str);
else if (o->type == OPTIONS_DATA)
o->freefn(o->data);
o->type = OPTIONS_NUMBER;
o->num = value;
@@ -166,36 +158,3 @@ options_get_number(struct options *oo, const char *name)
fatalx("option not a number");
return (o->num);
}
struct options_entry *
options_set_data(
struct options *oo, const char *name, void *value, void (*freefn)(void *))
{
struct options_entry *o;
if ((o = options_find1(oo, name)) == NULL) {
o = xmalloc(sizeof *o);
o->name = xstrdup(name);
SPLAY_INSERT(options_tree, &oo->tree, o);
} else if (o->type == OPTIONS_STRING)
xfree(o->str);
else if (o->type == OPTIONS_DATA)
o->freefn(o->data);
o->type = OPTIONS_DATA;
o->data = value;
o->freefn = freefn;
return (o);
}
void *
options_get_data(struct options *oo, const char *name)
{
struct options_entry *o;
if ((o = options_find(oo, name)) == NULL)
fatalx("missing option");
if (o->type != OPTIONS_DATA)
fatalx("option not data");
return (o->data);
}

View File

@@ -28,6 +28,12 @@ osdep_get_name(unused int fd, unused char *tty)
return (NULL);
}
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base *
osdep_event_init(void)
{

View File

@@ -25,6 +25,7 @@
#include <unistd.h>
char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void);
#define unused __attribute__ ((unused))
@@ -48,6 +49,12 @@ osdep_get_name(int fd, unused char *tty)
return (strdup(kp.kp_proc.p_comm));
}
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base *
osdep_event_init(void)
{

133
osdep-dragonfly.c Normal file
View File

@@ -0,0 +1,133 @@
/* $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/param.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <err.h>
#include <errno.h>
#include <event.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void);
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
#define is_runnable(p) \
((p)->kp_stat == SACTIVE || (p)->kp_stat == SIDL)
#define is_stopped(p) \
((p)->kp_stat == SSTOP || (p)->kp_stat == SZOMB)
struct kinfo_proc *
cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
{
if (is_runnable(p1) && !is_runnable(p2))
return (p1);
if (!is_runnable(p1) && is_runnable(p2))
return (p2);
if (is_stopped(p1) && !is_stopped(p2))
return (p1);
if (!is_stopped(p1) && is_stopped(p2))
return (p2);
if (strcmp(p1->kp_comm, p2->kp_comm) < 0)
return (p1);
if (strcmp(p1->kp_comm, p2->kp_comm) > 0)
return (p2);
if (p1->kp_pid > p2->kp_pid)
return (p1);
return (p2);
}
char *
osdep_get_name(int fd, char *tty)
{
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0 };
struct stat sb;
size_t len;
struct kinfo_proc *buf, *newbuf, *bestp;
u_int i;
char *name;
buf = NULL;
if (stat(tty, &sb) == -1)
return (NULL);
if ((mib[3] = tcgetpgrp(fd)) == -1)
return (NULL);
retry:
if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1)
return (NULL);
len = (len * 5) / 4;
if ((newbuf = realloc(buf, len)) == NULL)
goto error;
buf = newbuf;
if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) {
if (errno == ENOMEM)
goto retry;
goto error;
}
bestp = NULL;
for (i = 0; i < len / sizeof (struct kinfo_proc); i++) {
if (buf[i].kp_tdev != sb.st_rdev)
continue;
if (bestp == NULL)
bestp = &buf[i];
else
bestp = cmp_procs(&buf[i], bestp);
}
name = NULL;
if (bestp != NULL)
name = strdup(bestp->kp_comm);
free(buf);
return (name);
error:
free(buf);
return (NULL);
}
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base *
osdep_event_init(void)
{
return (event_init());
}

View File

@@ -29,9 +29,11 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libutil.h>
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void);
#ifndef nitems
@@ -130,6 +132,28 @@ error:
return (NULL);
}
char *
osdep_get_cwd(pid_t pid)
{
static char wd[PATH_MAX];
struct kinfo_file *info = NULL;
int nrecords, i;
if ((info = kinfo_getfile(pid, &nrecords)) == NULL)
return (NULL);
for (i = 0; i < nrecords; i++) {
if (info[i].kf_fd == KF_FD_TYPE_CWD) {
strlcpy(wd, info[i].kf_path, sizeof wd);
free(info);
return (wd);
}
}
free(info);
return (NULL);
}
struct event_base *
osdep_event_init(void)
{

View File

@@ -28,6 +28,12 @@ osdep_get_name(unused int fd, unused char *tty)
return (NULL);
}
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base *
osdep_event_init(void)
{

View File

@@ -60,6 +60,23 @@ osdep_get_name(int fd, unused char *tty)
return (buf);
}
char *
osdep_get_cwd(pid_t pid)
{
static char target[MAXPATHLEN + 1];
char *path;
ssize_t n;
xasprintf(&path, "/proc/%d/cwd", pid);
n = readlink(path, target, MAXPATHLEN);
xfree(path);
if (n > 0) {
target[n] = '\0';
return (target);
}
return (NULL);
}
struct event_base *
osdep_event_init(void)
{

View File

@@ -34,6 +34,7 @@
struct kinfo_proc2 *cmp_procs(struct kinfo_proc2 *, struct kinfo_proc2 *);
char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void);
struct kinfo_proc2 *
@@ -123,6 +124,12 @@ error:
return (NULL);
}
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base *
osdep_event_init(void)
{

View File

@@ -37,6 +37,7 @@
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void);
struct kinfo_proc *
@@ -133,6 +134,18 @@ error:
return (NULL);
}
char*
osdep_get_cwd(pid_t pid)
{
int name[] = { CTL_KERN, KERN_PROC_CWD, (int)pid };
static char path[MAXPATHLEN];
size_t pathlen = sizeof path;
if (sysctl(name, 3, path, &pathlen, NULL, 0) != 0)
return (NULL);
return (path);
}
struct event_base *
osdep_event_init(void)
{

View File

@@ -41,14 +41,13 @@ osdep_get_name(int fd, char *tty)
if ((f = open(tty, O_RDONLY)) < 0)
return (NULL);
if ((fstat(f, &st) != 0) ||
(ioctl(f, TIOCGPGRP, &pgrp) != 0)) {
if (fstat(f, &st) != 0 || ioctl(f, TIOCGPGRP, &pgrp) != 0) {
close(f);
return (NULL);
}
close(f);
xasprintf(&path, "/proc/%hu/psinfo", pgrp);
xasprintf(&path, "/proc/%u/psinfo", (u_int) pgrp);
f = open(path, O_RDONLY);
xfree(path);
if (f < 0)
@@ -65,6 +64,23 @@ osdep_get_name(int fd, char *tty)
return (xstrdup(p.pr_fname));
}
char *
osdep_get_cwd(pid_t pid)
{
static char target[MAXPATHLEN + 1];
char *path;
ssize_t n;
xasprintf(&path, "/proc/%u/path/cwd", (u_int) pid);
n = readlink(path, target, MAXPATHLEN);
xfree(path);
if (n > 0) {
target[n] = '\0';
return (target);
}
return (NULL);
}
struct event_base *
osdep_event_init(void)
{

View File

@@ -28,6 +28,12 @@ osdep_get_name(unused int fd, unused char *tty)
return (NULL);
}
char *
osdep_get_cwd(pid_t pid)
{
return (NULL);
}
struct event_base *
osdep_event_init(void)
{

View File

@@ -264,7 +264,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
{
struct tty *tty = &c->tty;
struct session *s = c->session;
struct options *oo = &s->options;
struct options *oo = &s->options;
struct window *w = wp->window;
struct grid_cell gc;
u_int idx, px, py, i, j, xoff, yoff;
@@ -272,7 +272,8 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
char buf[16], *ptr;
size_t len;
idx = window_pane_index(w, wp);
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
len = xsnprintf(buf, sizeof buf, "%u", idx);
if (wp->sx < len)
@@ -285,15 +286,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
if (wp->sx < len * 6 || wp->sy < 5) {
tty_cursor(tty, xoff + px - len / 2, yoff + py);
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.data = '_'; /* not space */
if (w->active == wp)
colour_set_fg(&gc, active_colour);
else
colour_set_fg(&gc, colour);
tty_attributes(tty, &gc);
tty_puts(tty, buf);
return;
goto draw_text;
}
px -= len * 3;
@@ -320,4 +313,21 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
}
px += 6;
}
len = xsnprintf(buf, sizeof buf, "%ux%u", wp->sx, wp->sy);
if (wp->sx < len || wp->sy < 6)
return;
tty_cursor(tty, xoff + wp->sx - len, yoff);
draw_text:
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.data = '_'; /* not space */
if (w->active == wp)
colour_set_fg(&gc, active_colour);
else
colour_set_fg(&gc, colour);
tty_attributes(tty, &gc);
tty_puts(tty, buf);
tty_cursor(tty, 0, 0);
}

View File

@@ -46,6 +46,24 @@ screen_write_stop(unused struct screen_write_ctx *ctx)
{
}
/* Reset screen state. */
void
screen_write_reset(struct screen_write_ctx *ctx)
{
screen_reset_tabs(ctx->s);
screen_write_scrollregion(ctx, 0, screen_size_y(ctx->s) - 1);
screen_write_insertmode(ctx, 0);
screen_write_kcursormode(ctx, 0);
screen_write_kkeypadmode(ctx, 0);
screen_write_mousemode_off(ctx);
screen_write_clearscreen(ctx);
screen_write_cursormove(ctx, 0, 0);
}
/* Write character. */
void
screen_write_putc(
@@ -985,6 +1003,17 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
tty_write(tty_cmd_clearscreen, &ttyctx);
}
/* Clear entire history. */
void
screen_write_clearhistory(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct grid *gd = s->grid;
grid_move_lines(gd, 0, gd->hsize, gd->sy);
gd->hsize = 0;
}
/* Write cell data. */
void
screen_write_cell(struct screen_write_ctx *ctx,

View File

@@ -170,6 +170,8 @@ server_client_lost(struct client *c)
if (c->cwd != NULL)
xfree(c->cwd);
environ_free(&c->environ);
close(c->ibuf.fd);
imsg_clear(&c->ibuf);
event_del(&c->event);
@@ -270,9 +272,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
struct options *oo;
struct timeval tv;
struct key_binding *bd;
struct keylist *keylist;
int xtimeout, isprefix;
u_int i;
/* Check the client is good to accept input. */
if ((c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
@@ -317,6 +317,8 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
if (c->flags & CLIENT_READONLY)
return;
if (options_get_number(oo, "mouse-select-pane") &&
(!(options_get_number(oo, "status") &&
mouse->y + 1 == c->tty.sy)) &&
((!(mouse->b & MOUSE_DRAG) && mouse->b != MOUSE_UP) ||
wp->mode != &window_copy_mode)) {
/*
@@ -355,14 +357,12 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
}
/* Is this a prefix key? */
keylist = options_get_data(&c->session->options, "prefix");
isprefix = 0;
for (i = 0; i < ARRAY_LENGTH(keylist); i++) {
if (key == ARRAY_ITEM(keylist, i)) {
isprefix = 1;
break;
}
}
if (key == options_get_number(&c->session->options, "prefix"))
isprefix = 1;
else if (key == options_get_number(&c->session->options, "prefix2"))
isprefix = 1;
else
isprefix = 0;
/* No previous prefix key. */
if (!(c->flags & CLIENT_PREFIX)) {
@@ -560,50 +560,6 @@ server_client_check_exit(struct client *c)
c->flags &= ~CLIENT_EXIT;
}
/*
* Check if the client should backoff. During backoff, data from external
* programs is not written to the terminal. When the existing data drains, the
* client is redrawn.
*
* There are two backoff phases - both the tty and client have backoff flags -
* the first to allow existing data to drain and the latter to ensure backoff
* is disabled until the redraw has finished and prevent the redraw triggering
* another backoff.
*/
void
server_client_check_backoff(struct client *c)
{
struct tty *tty = &c->tty;
size_t used;
used = EVBUFFER_LENGTH(tty->event->output);
/*
* If in the second backoff phase (redrawing), don't check backoff
* until the redraw has completed (or enough of it to drop below the
* backoff threshold).
*/
if (c->flags & CLIENT_BACKOFF) {
if (used > BACKOFF_THRESHOLD)
return;
c->flags &= ~CLIENT_BACKOFF;
return;
}
/* Once drained, allow data through again and schedule redraw. */
if (tty->flags & TTY_BACKOFF) {
if (used != 0)
return;
tty->flags &= ~TTY_BACKOFF;
c->flags |= (CLIENT_BACKOFF|CLIENT_REDRAWWINDOW|CLIENT_STATUS);
return;
}
/* If too much data, start backoff. */
if (used > BACKOFF_THRESHOLD)
tty->flags |= TTY_BACKOFF;
}
/* Check for client redraws. */
void
server_client_check_redraw(struct client *c)

View File

@@ -237,6 +237,7 @@ server_lock_client(struct client *c)
tty_stop_tty(&c->tty);
tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_SMCUP));
tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_CLEAR));
tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_E3));
c->flags |= CLIENT_SUSPENDED;
server_write_client(c, MSG_LOCK, &lockdata, sizeof lockdata);
@@ -329,16 +330,32 @@ server_unlink_window(struct session *s, struct winlink *wl)
void
server_destroy_pane(struct window_pane *wp)
{
struct window *w = wp->window;
struct window *w = wp->window;
int old_fd;
struct screen_write_ctx ctx;
struct grid_cell gc;
old_fd = wp->fd;
if (wp->fd != -1) {
close(wp->fd);
bufferevent_free(wp->event);
wp->fd = -1;
}
if (options_get_number(&w->options, "remain-on-exit"))
if (options_get_number(&w->options, "remain-on-exit")) {
if (old_fd == -1)
return;
screen_write_start(&ctx, wp, &wp->base);
screen_write_scrollregion(&ctx, 0, screen_size_y(ctx.s) - 1);
screen_write_cursormove(&ctx, 0, screen_size_y(ctx.s) - 1);
screen_write_linefeed(&ctx, 1);
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.attr |= GRID_ATTR_BRIGHT;
screen_write_puts(&ctx, &gc, "Pane is dead");
screen_write_stop(&ctx);
wp->flags |= PANE_REDRAW;
return;
}
layout_close_pane(wp);
window_remove_pane(w, wp);

View File

@@ -56,8 +56,10 @@ server_window_loop(void)
server_status_session(s);
TAILQ_FOREACH(wp, &w->panes, entry)
server_window_check_content(s, wl, wp);
if (!(s->flags & SESSION_UNATTACHED))
w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY);
}
w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY);
}
}
@@ -72,7 +74,7 @@ server_window_check_bell(struct session *s, struct winlink *wl)
if (!(w->flags & WINDOW_BELL) || wl->flags & WINLINK_BELL)
return (0);
if (s->curw != wl)
if (s->curw != wl || s->flags & SESSION_UNATTACHED)
wl->flags |= WINLINK_BELL;
action = options_get_number(&s->options, "bell-action");
@@ -86,7 +88,7 @@ server_window_check_bell(struct session *s, struct winlink *wl)
if (c == NULL || c->session != s)
continue;
if (!visual) {
tty_putcode(&c->tty, TTYC_BEL);
tty_bell(&c->tty);
continue;
}
if (c->session->curw->window == w) {
@@ -108,7 +110,7 @@ server_window_check_bell(struct session *s, struct winlink *wl)
if (c->session->curw->window != w)
continue;
if (!visual) {
tty_putcode(&c->tty, TTYC_BEL);
tty_bell(&c->tty);
continue;
}
status_message_set(c, "Bell in current window");
@@ -129,7 +131,7 @@ server_window_check_activity(struct session *s, struct winlink *wl)
if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
return (0);
if (s->curw == wl)
if (s->curw == wl && !(s->flags & SESSION_UNATTACHED))
return (0);
if (!options_get_number(&w->options, "monitor-activity"))
@@ -165,7 +167,7 @@ server_window_check_silence(struct session *s, struct winlink *wl)
if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
return (0);
if (s->curw == wl) {
if (s->curw == wl && !(s->flags & SESSION_UNATTACHED)) {
/*
* Reset the timer for this window if we've focused it. We
* don't want the timer tripping as soon as we've switched away
@@ -217,7 +219,7 @@ server_window_check_content(
/* Activity flag must be set for new content. */
if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_CONTENT)
return (0);
if (s->curw == wl)
if (s->curw == wl && !(s->flags & SESSION_UNATTACHED))
return (0);
ptr = options_get_string(&w->options, "monitor-content");
@@ -254,6 +256,6 @@ ring_bell(struct session *s)
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL && c->session == s)
tty_putcode(&c->tty, TTYC_BEL);
tty_bell(&c->tty);
}
}

View File

@@ -118,11 +118,18 @@ session_create(const char *name, const char *cmd, const char *cwd,
s->sx = sx;
s->sy = sy;
s->idx = next_session++;
if (name != NULL)
if (name != NULL) {
s->name = xstrdup(name);
else
xasprintf(&s->name, "%u", s->idx);
s->idx = next_session++;
} else {
s->name = NULL;
do {
s->idx = next_session++;
if (s->name != NULL)
xfree (s->name);
xasprintf(&s->name, "%u", s->idx);
} while (RB_FIND(sessions, &sessions, s) != NULL);
}
RB_INSERT(sessions, &sessions, s);
if (cmd != NULL) {

165
status.c
View File

@@ -372,6 +372,7 @@ status_replace1(struct client *c, struct session *s, struct winlink *wl,
char ch, tmp[256], *ptr, *endptr, *freeptr;
size_t ptrlen;
long limit;
u_int idx;
if (s == NULL)
s = c->session;
@@ -422,8 +423,10 @@ status_replace1(struct client *c, struct session *s, struct winlink *wl,
ptr = tmp;
goto do_replace;
case 'P':
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
xsnprintf(
tmp, sizeof tmp, "%u", window_pane_index(wl->window, wp));
tmp, sizeof tmp, "%u", idx);
ptr = tmp;
goto do_replace;
case 'S':
@@ -551,8 +554,10 @@ status_find_job(struct client *c, char **iptr)
/* First try in the new tree. */
so_find.cmd = cmd;
so = RB_FIND(status_out_tree, &c->status_new, &so_find);
if (so != NULL && so->out != NULL)
if (so != NULL && so->out != NULL) {
xfree(cmd);
return (so->out);
}
/* If not found at all, start the job and add to the tree. */
if (so == NULL) {
@@ -679,14 +684,34 @@ status_print(
fmt = options_get_string(oo, "window-status-current-format");
}
if (wl->flags & WINLINK_ALERTFLAGS) {
fg = options_get_number(oo, "window-status-alert-fg");
if (wl->flags & WINLINK_BELL) {
fg = options_get_number(oo, "window-status-bell-fg");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(oo, "window-status-alert-bg");
bg = options_get_number(oo, "window-status-bell-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(oo, "window-status-alert-attr");
attr = options_get_number(oo, "window-status-bell-attr");
if (attr != 0)
gc->attr = attr;
} else if (wl->flags & WINLINK_CONTENT) {
fg = options_get_number(oo, "window-status-content-fg");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(oo, "window-status-content-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(oo, "window-status-content-attr");
if (attr != 0)
gc->attr = attr;
} else if (wl->flags & (WINLINK_ACTIVITY|WINLINK_SILENCE)) {
fg = options_get_number(oo, "window-status-activity-fg");
if (fg != 8)
colour_set_fg(gc, fg);
bg = options_get_number(oo, "window-status-activity-bg");
if (bg != 8)
colour_set_bg(gc, bg);
attr = options_get_number(oo, "window-status-activity-attr");
if (attr != 0)
gc->attr = attr;
}
@@ -917,9 +942,16 @@ status_prompt_redraw(struct client *c)
off = 0;
memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_fg(&gc, options_get_number(&s->options, "message-fg"));
colour_set_bg(&gc, options_get_number(&s->options, "message-bg"));
gc.attr |= options_get_number(&s->options, "message-attr");
/* Change colours for command mode. */
if (c->prompt_mdata.mode == 1) {
colour_set_fg(&gc, options_get_number(&s->options, "message-command-fg"));
colour_set_bg(&gc, options_get_number(&s->options, "message-command-bg"));
gc.attr |= options_get_number(&s->options, "message-command-attr");
} else {
colour_set_fg(&gc, options_get_number(&s->options, "message-fg"));
colour_set_bg(&gc, options_get_number(&s->options, "message-bg"));
gc.attr |= options_get_number(&s->options, "message-attr");
}
screen_write_start(&ctx, NULL, &c->status);
@@ -961,9 +993,12 @@ status_prompt_redraw(struct client *c)
void
status_prompt_key(struct client *c, int key)
{
struct session *sess = c->session;
struct options *oo = &sess->options;
struct paste_buffer *pb;
char *s, *first, *last, word[64], swapc;
const char *histstr;
char *s, *first, *last, word[64], swapc;
const char *histstr;
const char *wsep = NULL;
u_char ch;
size_t size, n, off, idx;
@@ -975,7 +1010,12 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS;
}
break;
case MODEKEYEDIT_SWITCHMODE:
c->flags |= CLIENT_STATUS;
break;
case MODEKEYEDIT_SWITCHMODEAPPEND:
c->flags |= CLIENT_STATUS;
/* FALLTHROUGH */
case MODEKEYEDIT_CURSORRIGHT:
if (c->prompt_index < size) {
c->prompt_index++;
@@ -1075,11 +1115,112 @@ status_prompt_key(struct client *c, int key)
c->flags |= CLIENT_STATUS;
}
break;
case MODEKEYEDIT_DELETEWORD:
wsep = options_get_string(oo, "word-separators");
idx = c->prompt_index;
/* Find a non-separator. */
while (idx != 0) {
idx--;
if (!strchr(wsep, c->prompt_buffer[idx]))
break;
}
/* Find the separator at the beginning of the word. */
while (idx != 0) {
idx--;
if (strchr(wsep, c->prompt_buffer[idx])) {
/* Go back to the word. */
idx++;
break;
}
}
memmove(c->prompt_buffer + idx,
c->prompt_buffer + c->prompt_index,
size + 1 - c->prompt_index);
memset(c->prompt_buffer + size - (c->prompt_index - idx),
'\0', c->prompt_index - idx);
c->prompt_index = idx;
c->flags |= CLIENT_STATUS;
break;
case MODEKEYEDIT_NEXTSPACE:
wsep = " ";
/* FALLTHROUGH */
case MODEKEYEDIT_NEXTWORD:
if (wsep == NULL)
wsep = options_get_string(oo, "word-separators");
/* Find a separator. */
while (c->prompt_index != size) {
c->prompt_index++;
if (strchr(wsep, c->prompt_buffer[c->prompt_index]))
break;
}
/* Find the word right after the separation. */
while (c->prompt_index != size) {
c->prompt_index++;
if (!strchr(wsep, c->prompt_buffer[c->prompt_index]))
break;
}
c->flags |= CLIENT_STATUS;
break;
case MODEKEYEDIT_NEXTSPACEEND:
wsep = " ";
/* FALLTHROUGH */
case MODEKEYEDIT_NEXTWORDEND:
if (wsep == NULL)
wsep = options_get_string(oo, "word-separators");
/* Find a word. */
while (c->prompt_index != size) {
c->prompt_index++;
if (!strchr(wsep, c->prompt_buffer[c->prompt_index]))
break;
}
/* Find the separator at the end of the word. */
while (c->prompt_index != size) {
c->prompt_index++;
if (strchr(wsep, c->prompt_buffer[c->prompt_index]))
break;
}
c->flags |= CLIENT_STATUS;
break;
case MODEKEYEDIT_PREVIOUSSPACE:
wsep = " ";
/* FALLTHROUGH */
case MODEKEYEDIT_PREVIOUSWORD:
if (wsep == NULL)
wsep = options_get_string(oo, "word-separators");
/* Find a non-separator. */
while (c->prompt_index != 0) {
c->prompt_index--;
if (!strchr(wsep, c->prompt_buffer[c->prompt_index]))
break;
}
/* Find the separator at the beginning of the word. */
while (c->prompt_index != 0) {
c->prompt_index--;
if (strchr(wsep, c->prompt_buffer[c->prompt_index])) {
/* Go back to the word. */
c->prompt_index++;
break;
}
}
c->flags |= CLIENT_STATUS;
break;
case MODEKEYEDIT_HISTORYUP:
histstr = status_prompt_up_history(&c->prompt_hindex);
if (histstr == NULL)
break;
xfree(c->prompt_buffer);
xfree(c->prompt_buffer);
c->prompt_buffer = xstrdup(histstr);
c->prompt_index = strlen(c->prompt_buffer);
c->flags |= CLIENT_STATUS;

419
tmux.1
View File

@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: July 8 2011 $
.Dd $Mdocdate: December 4 2011 $
.Dt TMUX 1
.Os
.Sh NAME
@@ -495,7 +495,8 @@ $ tmux bind-key F1 set-window-option force-width 81
Multiple commands may be specified together as part of a
.Em command sequence .
Each command should be separated by spaces and a semicolon;
commands are executed sequentially from left to right.
commands are executed sequentially from left to right and
lines ending with a backslash continue on to the next line.
A literal semicolon may be included by escaping it with a backslash (for
example, when specifying a command sequence to
.Ic bind-key ) .
@@ -511,6 +512,9 @@ rename-session -tfirst newname
set-window-option -t:0 monitor-activity on
new-window ; split-window -d
bind-key R source-file ~/.tmux.conf \e; \e
display-message "source-file done"
.Ed
.Pp
Or from
@@ -562,7 +566,9 @@ is specified, any other clients attached to the session are detached.
.Fl r
signifies the client is read-only (only keys bound to the
.Ic detach-client
command have any effect)
or
.Ic switch-client
commands have any effect)
.Pp
If no server is started,
.Ic attach-session
@@ -587,7 +593,7 @@ session.
.D1 (alias: Ic detach )
Detach the current client if bound to a key, the client specified with
.Fl t ,
or all clients currently attached to to the session specified by
or all clients currently attached to the session specified by
.Fl s .
If
.Fl P
@@ -604,9 +610,17 @@ server and clients and destroy all sessions.
.It Ic kill-session Op Fl t Ar target-session
Destroy the given session, closing any windows linked to it and no other
sessions, and detaching all clients attached to it.
.It Ic list-clients Op Fl t Ar target-session
.It Xo Ic list-clients
.Op Fl F Ar format
.Op Fl t Ar target-session
.Xc
.D1 (alias: Ic lsc )
List all clients attached to the server.
For the meaning of the
.Fl F
flag, see the
.Sx FORMATS
section.
If
.Ar target-session
is specified, list only clients connected to that session.
@@ -614,9 +628,14 @@ is specified, list only clients connected to that session.
.D1 (alias: Ic lscm )
List the syntax of all commands supported by
.Nm .
.It Ic list-sessions
.It Ic list-sessions Op Fl F Ar format
.D1 (alias: Ic ls )
List all sessions managed by the server.
For the meaning of the
.Fl F
flag, see the
.Sx FORMATS
section.
.It Ic lock-client Op Fl t Ar target-client
.D1 (alias: Ic lockc )
Lock
@@ -679,11 +698,17 @@ or
are invalid if
.Fl t
is used.
.It Ic refresh-client Op Fl t Ar target-client
.It Xo Ic refresh-client
.Op Fl S
.Op Fl t Ar target-client
.Xc
.D1 (alias: Ic refresh )
Refresh the current client if bound to a key, or a single client if one is given
with
.Fl t .
If
.Fl S
is specified, only update the client's status bar.
.It Xo Ic rename-session
.Op Fl t Ar target-session
.Ar new-name
@@ -718,7 +743,7 @@ Suspend a client by sending
.Dv SIGTSTP
(tty stop).
.It Xo Ic switch-client
.Op Fl lnp
.Op Fl lnpr
.Op Fl c Ar target-client
.Op Fl t Ar target-session
.Xc
@@ -734,6 +759,10 @@ or
.Fl p
is used, the client is moved to the last, next or previous session
respectively.
.Fl r
toggles whether a client is read-only (see the
.Ic attach-session
command).
.El
.Sh WINDOWS AND PANES
A
@@ -778,7 +807,9 @@ The following keys are supported as appropriate for the mode:
.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 "Next page" Ta "C-f" Ta "Page down"
@@ -812,7 +843,7 @@ and
characters as word delimiters by default, but this can be adjusted by
setting the
.Em word-separators
window option.
session option.
Next word moves to the start of the next word, next word end to the end of the
next word and previous word to the start of the previous word.
The three next and previous space keys work similarly but use a space alone as
@@ -839,6 +870,9 @@ 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
@@ -1141,6 +1175,7 @@ If
is given, the newly linked window is not selected.
.It Xo Ic list-panes
.Op Fl as
.Op Fl F Ar format
.Op Fl t Ar target
.Xc
.D1 (alias: Ic lsp )
@@ -1157,8 +1192,14 @@ is a session (or the current session).
If neither is given,
.Ar target
is a window (or the current window).
For the meaning of the
.Fl F
flag, see the
.Sx FORMATS
section.
.It Xo Ic list-windows
.Op Fl a
.Op Fl F Ar format
.Op Fl t Ar target-session
.Xc
.D1 (alias: Ic lsw )
@@ -1167,6 +1208,11 @@ If
is given, list all windows on the server.
Otherwise, list windows in the current session or in
.Ar target-session .
For the meaning of the
.Fl F
flag, see the
.Sx FORMATS
section.
.It Xo Ic move-window
.Op Fl dk
.Op Fl s Ar src-window
@@ -1511,10 +1557,8 @@ to
.Em Home ,
.Em IC
(Insert),
.Em NPage
(Page Up),
.Em PPage
(Page Down),
.Em NPage/PageDown/PgDn ,
.Em PPage/PageUp/PgUp ,
.Em Space ,
and
.Em Tab .
@@ -1594,6 +1638,7 @@ are listed; this may be one of:
or
.Em emacs-copy .
.It Xo Ic send-keys
.Fl R
.Op Fl t Ar target-pane
.Ar key Ar ...
.Xc
@@ -1608,9 +1653,16 @@ or
) to send; if the string is not recognised as a key, it is sent as a series of
characters.
All arguments are sent sequentially from first to last.
.It Ic send-prefix Op Fl t Ar target-pane
Send the prefix key to a window as if it was pressed.
If multiple prefix keys are configured, only the first is sent.
The
.Fl R
flag causes the terminal state to be reset.
.It Xo Ic send-prefix
.Op Fl 2
.Op Fl t Ar target-pane
.Xc
Send the prefix key, or with
.Fl 2
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
@@ -1726,6 +1778,22 @@ Available server options are:
Set the number of buffers; as new buffers are added to the top of the stack,
old ones are removed from the bottom if necessary to maintain this maximum
length.
.It Ic escape-time Ar time
Set the time in milliseconds for which
.Nm
waits after an escape is input to determine if it is part of a function or meta
key sequences.
The default is 500 milliseconds.
.It Xo Ic exit-unattached
.Op Ic on | off
.Xc
If enabled, the server will exit when there are no attached clients.
.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 Xo Ic set-clipboard
.Op Ic on | off
.Xc
@@ -1748,22 +1816,6 @@ disallowedWindowOps: 20,21,SetXprop
Or changing this property from the
.Xr xterm 1
interactive menu when required.
.It Ic escape-time Ar time
Set the time in milliseconds for which
.Nm
waits after an escape is input to determine if it is part of a function or meta
key sequences.
The default is 500 milliseconds.
.It Xo Ic exit-unattached
.Op Ic on | off
.Xc
If enabled, the server will exit when there are no attached clients.
.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).
.El
.Pp
Available session options are:
@@ -1801,10 +1853,20 @@ to create a login shell using the value of the
.Ic default-shell
option.
.It Ic default-path Ar path
Set the default working directory for processes created from keys, or
interactively from the prompt.
The default is empty, which means to use the working directory of the shell
from which the server was started if it is available or the user's home if not.
Set the default working directory for new panes.
If empty (the default), the working directory is determined from the process
running in the active pane, from the command line environment or from the
working directory where the session was created.
If
.Ar path
is "$HOME" or "~", the value of the
.Ev HOME
environment variable is used.
If
.Ar path
is ".", the working directory when
.Nm
was started is used.
.It Ic default-shell Ar path
Specify the default shell.
This is used as the login shell for new windows when the
@@ -1922,6 +1984,10 @@ is one of:
.Ic magenta ,
.Ic cyan ,
.Ic white ,
aixterm bright variants (if supported:
.Ic brightred ,
.Ic brightgreen ,
and so on),
.Ic colour0
to
.Ic colour255
@@ -1930,6 +1996,12 @@ from the 256-colour set,
or a hexadecimal RGB string such as
.Ql #ffffff ,
which chooses the closest match from the default 256-colour set.
.It Ic message-command-attr Ar attributes
Set status line message attributes when in command mode.
.It Ic message-command-bg Ar colour
Set status line message background colour when in command mode.
.It Ic message-command-fg Ar colour
Set status line message foreground colour when in command mode.
.It Ic message-fg Ar colour
Set status line message foreground colour.
.It Ic message-limit Ar number
@@ -1955,17 +2027,20 @@ The mouse click is also passed through to the application as normal.
.Xc
If on, clicking the mouse on a window name in the status line will select that
window.
.It Xo Ic mouse-utf8
.Op Ic on | off
.Xc
If enabled, request mouse input as UTF-8 on UTF-8 terminals.
.It Ic pane-active-border-bg Ar colour
.It Ic pane-active-border-fg Ar colour
Set the pane border colour for the currently active pane.
.It Ic pane-border-bg Ar colour
.It Ic pane-border-fg Ar colour
Set the pane border colour for panes aside from the active pane.
.It Ic prefix Ar keys
Set the keys accepted as a prefix key.
.Ar keys
is a comma-separated list of key names, each of which individually behave as
the prefix key.
.It Ic prefix Ar key
Set the key accepted as a prefix key.
.It Ic prefix2 Ar key
Set a secondary key accepted as a prefix key.
.It Ic repeat-time Ar time
Allow multiple commands to be entered without pressing the prefix-key again
in the specified
@@ -1978,10 +2053,6 @@ flag to
Repeat is enabled for the default keys bound to the
.Ic resize-pane
command.
.It Xo Ic mouse-utf8
.Op Ic on | off
.Xc
If enabled, request mouse input as UTF-8 on UTF-8 terminals.
.It Xo Ic set-remain-on-exit
.Op Ic on | off
.Xc
@@ -1998,7 +2069,14 @@ command to destroy it.
.It Xo Ic set-titles
.Op Ic on | off
.Xc
Attempt to set the window title using the \ee]2;...\e007 xterm code if
Attempt to set the client terminal title using the
.Em tsl
and
.Em fsl
.Xr terminfo 5
entries if they exist.
.Nm
automatically sets these to the \ee]2;...\e007 sequence if
the terminal appears to be an xterm.
This option is off by default.
Note that elinks
@@ -2064,7 +2142,7 @@ may contain any of the following special character sequences:
.It Li "#I" Ta "Current window index"
.It Li "#P" Ta "Current pane index"
.It Li "#S" Ta "Session name"
.It Li "#T" Ta "Current window title"
.It Li "#T" Ta "Current pane title"
.It Li "#W" Ta "Current window name"
.It Li "##" Ta "A literal" Ql #
.El
@@ -2083,13 +2161,9 @@ global environment set (see the
.Sx ENVIRONMENT
section).
.Pp
The window title (#T) is the title set by the program running within the window
using the OSC title setting sequence, for example:
.Bd -literal -offset indent
$ printf '\e033]2;My Title\e033\e\e'
.Ed
.Pp
When a window is first created, its title is the hostname.
For details on how the names and titles can be set see the
.Sx "NAMES AND TITLES"
section.
.Pp
#[attributes] allows a comma-separated list of attributes to be specified,
these may be
@@ -2244,6 +2318,12 @@ window option is enabled.
If
.Ic monitor-silence
is enabled, prints a message after the interval has expired on a given window.
.It Ic word-separators Ar string
Sets the session's conception of what characters are considered word
separators, for the purposes of the next and previous word commands in
copy mode.
The default is
.Ql \ -_@ .
.El
.It Xo Ic set-window-option
.Op Fl agu
@@ -2277,6 +2357,13 @@ this option is good for full-screen programs which support
.Dv SIGWINCH
and poor for interactive programs such as shells.
.Pp
.It Xo Ic allow-rename
.Op Ic on | off
.Xc
Allow programs to change the window name using a terminal escape
sequence (\\033k...\\033\\\\).
The default is on.
.Pp
.It Xo Ic alternate-screen
.Op Ic on | off
.Xc
@@ -2307,7 +2394,8 @@ is specified at creation with
or
.Ic new-session ,
or later with
.Ic rename-window .
.Ic rename-window ,
or with a terminal escape sequence.
It may be switched off globally with:
.Bd -literal -offset indent
set-window-option -g automatic-rename off
@@ -2362,12 +2450,16 @@ contains
.Ql vi .
.Pp
.It Xo Ic mode-mouse
.Op Ic on | off
.Op Ic on | off | copy-mode
.Xc
Mouse state in modes.
If on, the mouse may be used to enter copy mode and copy a selection by
dragging, to enter copy mode and scroll with the mouse wheel, or to select an
option in choice mode.
If set to
.Em copy-mode ,
the mouse behaves as set to on, but cannot be used to enter copy
mode.
.Pp
.It Xo Ic monitor-activity
.Op Ic on | off
@@ -2412,6 +2504,11 @@ but set the width of other panes in the
.Ic main-vertical
layout.
.Pp
.It Ic pane-base-index Ar index
Like
.Ic base-index ,
but set the starting index for pane numbers.
.Pp
.It Xo Ic remain-on-exit
.Op Ic on | off
.Xc
@@ -2434,33 +2531,39 @@ Instructs
.Nm
to expect UTF-8 sequences to appear in this window.
.Pp
.It Ic window-status-bell-attr Ar attributes
Set status line attributes for windows which have a bell alert.
.Pp
.It Ic window-status-bell-bg Ar colour
Set status line background colour for windows with a bell alert.
.Pp
.It Ic window-status-bell-fg Ar colour
Set status line foreground colour for windows with a bell alert.
.Pp
.It Ic window-status-content-attr Ar attributes
Set status line attributes for windows which have a content alert.
.Pp
.It Ic window-status-content-bg Ar colour
Set status line background colour for windows with a content alert.
.Pp
.It Ic window-status-content-fg Ar colour
Set status line foreground colour for windows with a content alert.
.Pp
.It Ic window-status-activity-attr Ar attributes
Set status line attributes for windows which have an activity (or silence) alert.
.Pp
.It Ic window-status-activity-bg Ar colour
Set status line background colour for windows with an activity alert.
.Pp
.It Ic window-status-activity-fg Ar colour
Set status line foreground colour for windows with an activity alert.
.Pp
.It Ic window-status-attr Ar attributes
Set status line attributes for a single window.
.Pp
.It Ic window-status-bg Ar colour
Set status line background colour for a single window.
.Pp
.It Ic window-status-fg Ar colour
Set status line foreground colour for a single window.
.Pp
.It Ic window-status-format Ar string
Set the format in which the window is displayed in the status line window list.
See the
.Ar status-left
option for details of special character sequences available.
The default is
.Ql #I:#W#F .
.Pp
.It Ic window-status-alert-attr Ar attributes
Set status line attributes for windows which have an alert (bell, activity
or content).
.Pp
.It Ic window-status-alert-bg Ar colour
Set status line background colour for windows with an alert.
.Pp
.It Ic window-status-alert-fg Ar colour
Set status line foreground colour for windows with an alert.
.Pp
.It Ic window-status-current-attr Ar attributes
Set status line attributes for the currently active window.
.Pp
@@ -2475,12 +2578,16 @@ Like
.Ar window-status-format ,
but is the format used when the window is the current window.
.Pp
.It Ic word-separators Ar string
Sets the window's conception of what characters are considered word
separators, for the purposes of the next and previous word commands in
copy mode.
.It Ic window-status-fg Ar colour
Set status line foreground colour for a single window.
.Pp
.It Ic window-status-format Ar string
Set the format in which the window is displayed in the status line window list.
See the
.Ar status-left
option for details of special character sequences available.
The default is
.Ql \ -_@ .
.Ql #I:#W#F .
.Pp
.It Xo Ic xterm-keys
.Op Ic on | off
@@ -2520,6 +2627,142 @@ or the global window options if
.Fl g
is used.
.El
.Sh FORMATS
The
.Ic list-clients ,
.Ic list-sessions ,
.Ic list-windows
and
.Ic list-panes
commands accept the
.Fl F
flag with a
.Ar format
argument.
This is a string which controls the output format of the command.
Special character sequences are replaced as documented under the
.Ic status-left
option and an additional long form is accepted.
Replacement variables are enclosed in
.Ql #{
and
.Ql } ,
for example
.Ql #{session_name}
is equivalent to
.Ql #S .
Conditionals are also accepted by prefixing with
.Ql \&?
and separating two alternatives with a comma;
if the specified variable exists and is not zero, the first alternative
is chosen, otherwise the second is used.
For example
.Ql #{?session_attached,attached,not attached}
will include the string
.Ql attached
if the session is attached and the string
.Ql not attached
if it is unattached.
.Pp
The following variables are available, where appropriate:
.Bl -column "session_created_string" "Replaced with" -offset indent
.It Sy "Variable name" Ta Sy "Replaced with"
.It Li "client_activity" Ta "Integer time client last had activity"
.It Li "client_activity_string" Ta "String time client last had activity"
.It Li "client_created" Ta "Integer time client created"
.It Li "client_created_string" Ta "String time client created"
.It Li "client_cwd" Ta "Working directory of client"
.It Li "client_height" Ta "Height of client"
.It Li "client_readonly" Ta "1 if client is readonly"
.It Li "client_termname" Ta "Terminal name of client"
.It Li "client_tty" Ta "Pseudo terminal of client"
.It Li "client_utf8" Ta "1 if client supports utf8"
.It Li "client_width" Ta "Width of client"
.It Li "host" Ta "Hostname of local host"
.It Li "line" Ta "Line number in the list"
.It Li "pane_active" Ta "1 if active pane"
.It Li "pane_dead" Ta "1 if pane is dead"
.It Li "pane_height" Ta "Height of pane"
.It Li "pane_id" Ta "Unique pane id"
.It Li "pane_pid" Ta "PID of first process in pane"
.It Li "pane_start_command" Ta "Command pane started with"
.It Li "pane_start_path" Ta "Path pane started with"
.It Li "pane_title" Ta "Title of pane"
.It Li "pane_tty" Ta "Pseudo terminal of pane"
.It Li "pane_width" Ta "Width of pane"
.It Li "session_attached" Ta "1 if session attached"
.It Li "session_created" Ta "Integer time session created"
.It Li "session_created_string" Ta "String time session created"
.It Li "session_group" Ta "Number of session group"
.It Li "session_grouped" Ta "1 if session in a group"
.It Li "session_height" Ta "Height of session"
.It Li "session_name" Ta "Name of session"
.It Li "session_width" Ta "Width of session"
.It Li "session_windows" Ta "Number of windows in session"
.It Li "window_active" Ta "1 if window active"
.It Li "window_flags" Ta "Window flags"
.It Li "window_height" Ta "Height of window"
.It Li "window_index" Ta "Index of window"
.It Li "window_layout" Ta "Window layout description"
.It Li "window_name" Ta "Name of window"
.It Li "window_width" Ta "Width of window"
.El
.Sh NAMES AND TITLES
.Nm
distinguishes between names and titles.
Windows and sessions have names, which may be used to specify them in targets
and are displayed in the status line and various lists: the name is the
.Nm
identifier for a window or session.
Only panes have titles.
A pane's title is typically set by the program running inside the pane and
is not modified by
.Nm .
It is the same mechanism used to set for example the
.Xr xterm 1
window title in an
.Xr X 7
window manager.
Windows themselves do not have titles - a window's title is the title of its
active pane.
.Nm
itself may set the title of the terminal in which the client is running, see
the
.Ic set-titles
option.
.Pp
A session's name is set with the
.Ic new-session
and
.Ic rename-session
commands.
A window's name is set with one of:
.Bl -enum -width Ds
.It
A command argument (such as
.Fl n
for
.Ic new-window
or
.Ic new-session ) .
.It
An escape sequence:
.Bd -literal -offset indent
$ printf '\e033kWINDOW_NAME\e033\e\e'
.Ed
.It
Automatic renaming, which sets the name to the active command in the window's
active pane.
See the
.Ic automatic-rename
option.
.El
.Pp
When a pane is first created, its title is the hostname.
A pane's title can be set via the OSC title setting sequence, for example:
.Bd -literal -offset indent
$ printf '\e033]2;My Title\e033\e\e'
.Ed
.Sh ENVIRONMENT
When the server is started,
.Nm
@@ -2583,8 +2826,8 @@ terminal.
By default, the status line is enabled (it may be disabled with the
.Ic status
session option) and contains, from left-to-right: the name of the current
session in square brackets; the window list; the current window title in double
quotes; and the time and date.
session in square brackets; the window list; the title of the active pane
in double quotes; and the time and date.
.Pp
The status line is made of three parts: configurable left and right sections
(which may contain dynamic content such as the time or output from a shell
@@ -2846,13 +3089,15 @@ Miscellaneous commands are as follows:
.Bl -tag -width Ds
.It Ic clock-mode Op Fl t Ar target-pane
Display a large clock.
.It Ic if-shell Ar shell-command command
.It Ic if-shell Ar shell-command command Op Ar command
.D1 (alias: Ic if )
Execute
Execute the first
.Ar command
if
.Ar shell-command
returns success.
returns success or the second
.Ar command
otherwise.
.It Ic lock-server
.D1 (alias: Ic lock )
Lock each client individually by running the command specified by the

31
tmux.c
View File

@@ -101,7 +101,9 @@ getshell(void)
int
checkshell(const char *shell)
{
if (shell == NULL || *shell == '\0' || areshell(shell))
if (shell == NULL || *shell == '\0' || *shell != '/')
return (0);
if (areshell(shell))
return (0);
if (access(shell, X_OK) != 0)
return (0);
@@ -125,6 +127,22 @@ areshell(const char *shell)
return (0);
}
const char*
get_full_path(const char *wd, const char *path)
{
static char newpath[MAXPATHLEN];
char oldpath[MAXPATHLEN];
if (getcwd(oldpath, sizeof oldpath) == NULL)
return (NULL);
if (chdir(wd) != 0)
return (NULL);
if (realpath(path, newpath) != 0)
return (NULL);
chdir(oldpath);
return (newpath);
}
void
parseenvironment(void)
{
@@ -217,7 +235,6 @@ int
main(int argc, char **argv)
{
struct passwd *pw;
struct keylist *keylist;
char *s, *path, *label, *home, **var;
int opt, flags, quiet, keys;
@@ -293,8 +310,8 @@ main(int argc, char **argv)
* if not they know that output from UTF-8-capable programs may
* be wrong.
*/
if ((s = getenv("LC_ALL")) == NULL) {
if ((s = getenv("LC_CTYPE")) == NULL)
if ((s = getenv("LC_ALL")) == NULL || *s == '\0') {
if ((s = getenv("LC_CTYPE")) == NULL || *s == '\0')
s = getenv("LANG");
}
if (s != NULL && (strcasestr(s, "UTF-8") != NULL ||
@@ -317,12 +334,6 @@ main(int argc, char **argv)
options_init(&global_w_options, NULL);
options_table_populate_tree(window_options_table, &global_w_options);
/* Set the prefix option (its a list, so not in the table). */
keylist = xmalloc(sizeof *keylist);
ARRAY_INIT(keylist);
ARRAY_ADD(keylist, '\002');
options_set_data(&global_s_options, "prefix", keylist, xfree);
/* Enable UTF-8 if the first client is on UTF-8 terminal. */
if (flags & IDENTIFY_UTF8) {
options_set_number(&global_s_options, "status-utf8", 1);

74
tmux.h
View File

@@ -202,6 +202,7 @@ enum tty_code_code {
TTYC_DIM, /* enter_dim_mode, mh */
TTYC_DL, /* parm_delete_line, DL */
TTYC_DL1, /* delete_line, dl */
TTYC_E3,
TTYC_EL, /* clr_eol, ce */
TTYC_EL1, /* clr_bol, cb */
TTYC_ENACS, /* ena_acs, eA */
@@ -437,11 +438,18 @@ enum mode_key_cmd {
MODEKEYEDIT_DELETE,
MODEKEYEDIT_DELETELINE,
MODEKEYEDIT_DELETETOENDOFLINE,
MODEKEYEDIT_DELETEWORD,
MODEKEYEDIT_ENDOFLINE,
MODEKEYEDIT_ENTER,
MODEKEYEDIT_HISTORYDOWN,
MODEKEYEDIT_HISTORYUP,
MODEKEYEDIT_NEXTSPACE,
MODEKEYEDIT_NEXTSPACEEND,
MODEKEYEDIT_NEXTWORD,
MODEKEYEDIT_NEXTWORDEND,
MODEKEYEDIT_PASTE,
MODEKEYEDIT_PREVIOUSSPACE,
MODEKEYEDIT_PREVIOUSWORD,
MODEKEYEDIT_STARTOFLINE,
MODEKEYEDIT_SWITCHMODE,
MODEKEYEDIT_SWITCHMODEAPPEND,
@@ -476,6 +484,8 @@ enum mode_key_cmd {
MODEKEYCOPY_JUMPAGAIN,
MODEKEYCOPY_JUMPREVERSE,
MODEKEYCOPY_JUMPBACK,
MODEKEYCOPY_JUMPTO,
MODEKEYCOPY_JUMPTOBACK,
MODEKEYCOPY_LEFT,
MODEKEYCOPY_MIDDLELINE,
MODEKEYCOPY_NEXTPAGE,
@@ -531,9 +541,9 @@ struct mode_key_binding {
int mode;
enum mode_key_cmd cmd;
SPLAY_ENTRY(mode_key_binding) entry;
RB_ENTRY(mode_key_binding) entry;
};
SPLAY_HEAD(mode_key_tree, mode_key_binding);
RB_HEAD(mode_key_tree, mode_key_binding);
/* Command to string mapping. */
struct mode_key_cmdstr {
@@ -659,21 +669,15 @@ struct options_entry {
char *str;
long long num;
void *data;
void (*freefn)(void *);
SPLAY_ENTRY(options_entry) entry;
RB_ENTRY(options_entry) entry;
};
struct options {
SPLAY_HEAD(options_tree, options_entry) tree;
RB_HEAD(options_tree, options_entry) tree;
struct options *parent;
};
/* Key list for prefix option. */
ARRAY_DECL(keylist, int);
/* Scheduled job. */
struct job {
char *cmd;
@@ -1160,8 +1164,7 @@ struct client {
#define CLIENT_DEAD 0x200
#define CLIENT_BORDERS 0x400
#define CLIENT_READONLY 0x800
#define CLIENT_BACKOFF 0x1000
#define CLIENT_REDRAWWINDOW 0x2000
#define CLIENT_REDRAWWINDOW 0x1000
int flags;
struct event identify_timer;
@@ -1268,9 +1271,9 @@ struct key_binding {
struct cmd_list *cmdlist;
int can_repeat;
SPLAY_ENTRY(key_binding) entry;
RB_ENTRY(key_binding) entry;
};
SPLAY_HEAD(key_bindings, key_binding);
RB_HEAD(key_bindings, key_binding);
/*
* Option table entries. The option table is the user-visible part of the
@@ -1280,7 +1283,7 @@ SPLAY_HEAD(key_bindings, key_binding);
enum options_table_type {
OPTIONS_TABLE_STRING,
OPTIONS_TABLE_NUMBER,
OPTIONS_TABLE_KEYS,
OPTIONS_TABLE_KEY,
OPTIONS_TABLE_COLOUR,
OPTIONS_TABLE_ATTRIBUTES,
OPTIONS_TABLE_FLAG,
@@ -1299,6 +1302,15 @@ struct options_table_entry {
long long default_num;
};
/* Tree of format entries. */
struct format_entry {
char *key;
char *value;
RB_ENTRY(format_entry) entry;
};
RB_HEAD(format_tree, format_entry);
/* List of configuration causes. */
ARRAY_DECL(causelist, char *);
@@ -1332,6 +1344,7 @@ void logfile(const char *);
const char *getshell(void);
int checkshell(const char *);
int areshell(const char *);
const char* get_full_path(const char *, const char *);
void setblocking(int, int);
__dead void shell_exec(const char *, const char *);
@@ -1341,6 +1354,21 @@ extern struct causelist cfg_causes;
void printflike2 cfg_add_cause(struct causelist *, const char *, ...);
int load_cfg(const char *, struct cmd_ctx *, struct causelist *);
/* format.c */
int format_cmp(struct format_entry *, struct format_entry *);
RB_PROTOTYPE(format_tree, format_entry, entry, format_cmp);
struct format_tree *format_create(void);
void format_free(struct format_tree *);
void format_add(
struct format_tree *, const char *, const char *, ...);
const char *format_find(struct format_tree *, const char *);
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_winlink(
struct format_tree *, struct session *, struct winlink *);
void format_window_pane(struct format_tree *, struct window_pane *);
/* mode-key.c */
extern const struct mode_key_table mode_key_tables[];
extern struct mode_key_tree mode_key_tree_vi_edit;
@@ -1350,7 +1378,7 @@ extern struct mode_key_tree mode_key_tree_emacs_edit;
extern struct mode_key_tree mode_key_tree_emacs_choice;
extern struct mode_key_tree mode_key_tree_emacs_copy;
int mode_key_cmp(struct mode_key_binding *, struct mode_key_binding *);
SPLAY_PROTOTYPE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
RB_PROTOTYPE(mode_key_tree, mode_key_binding, entry, mode_key_cmp);
const char *mode_key_tostring(const struct mode_key_cmdstr *,
enum mode_key_cmd);
enum mode_key_cmd mode_key_fromstring(const struct mode_key_cmdstr *,
@@ -1362,7 +1390,7 @@ enum mode_key_cmd mode_key_lookup(struct mode_key_data *, int);
/* options.c */
int options_cmp(struct options_entry *, struct options_entry *);
SPLAY_PROTOTYPE(options_tree, options_entry, entry, options_cmp);
RB_PROTOTYPE(options_tree, options_entry, entry, options_cmp);
void options_init(struct options *, struct options *);
void options_free(struct options *);
struct options_entry *options_find1(struct options *, const char *);
@@ -1374,9 +1402,6 @@ char *options_get_string(struct options *, const char *);
struct options_entry *options_set_number(
struct options *, const char *, long long);
long long options_get_number(struct options *, const char *);
struct options_entry *options_set_data(
struct options *, const char *, void *, void (*)(void *));
void *options_get_data(struct options *, const char *);
/* options-table.c */
extern const struct options_table_entry server_options_table[];
@@ -1454,6 +1479,7 @@ void tty_cmd_utf8character(struct tty *, const struct tty_ctx *);
void tty_cmd_reverseindex(struct tty *, const struct tty_ctx *);
void tty_cmd_setselection(struct tty *, const struct tty_ctx *);
void tty_cmd_rawstring(struct tty *, const struct tty_ctx *);
void tty_bell(struct tty *);
/* tty-term.c */
extern struct tty_terms tty_terms;
@@ -1525,6 +1551,7 @@ int cmd_find_index(
struct winlink *cmd_find_pane(struct cmd_ctx *,
const char *, struct session **, struct window_pane **);
char *cmd_template_replace(char *, const char *, int);
const char *cmd_get_default_path(struct cmd_ctx *ctx);
extern const struct cmd_entry *cmd_table[];
extern const struct cmd_entry cmd_attach_session_entry;
extern const struct cmd_entry cmd_bind_key_entry;
@@ -1625,7 +1652,7 @@ int client_main(int, char **, int);
/* key-bindings.c */
extern struct key_bindings key_bindings;
int key_bindings_cmp(struct key_binding *, struct key_binding *);
SPLAY_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
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);
@@ -1791,6 +1818,7 @@ char *grid_view_string_cells(struct grid *, u_int, u_int, u_int);
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 *,
ssize_t, struct grid_cell *, int, const char *, ...);
@@ -1836,6 +1864,7 @@ void screen_write_kkeypadmode(struct screen_write_ctx *, int);
void screen_write_clearendofscreen(struct screen_write_ctx *);
void screen_write_clearstartofscreen(struct screen_write_ctx *);
void screen_write_clearscreen(struct screen_write_ctx *);
void screen_write_clearhistory(struct screen_write_ctx *);
void screen_write_cell(struct screen_write_ctx *,
const struct grid_cell *, const struct utf8_data *);
void screen_write_setselection(struct screen_write_ctx *, u_char *, u_int);
@@ -1899,7 +1928,7 @@ struct window_pane *window_pane_next_by_number(struct window *,
struct window_pane *, u_int);
struct window_pane *window_pane_previous_by_number(struct window *,
struct window_pane *, u_int);
u_int window_pane_index(struct window *, struct window_pane *);
int window_pane_index(struct window_pane *, u_int *);
u_int window_count_panes(struct window *);
void window_destroy_panes(struct window *);
struct window_pane *window_pane_find_by_id(u_int);
@@ -2041,6 +2070,7 @@ u_int utf8_split2(u_int, u_char *);
/* osdep-*.c */
char *osdep_get_name(int, char *);
char *osdep_get_cwd(pid_t);
struct event_base *osdep_event_init(void);
/* log.c */

View File

@@ -64,6 +64,7 @@ const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
{ TTYC_DIM, TTYCODE_STRING, "dim" },
{ TTYC_DL, TTYCODE_STRING, "dl" },
{ TTYC_DL1, TTYCODE_STRING, "dl1" },
{ TTYC_E3, TTYCODE_STRING, "E3" },
{ TTYC_EL, TTYCODE_STRING, "el" },
{ TTYC_EL1, TTYCODE_STRING, "el1" },
{ TTYC_ENACS, TTYCODE_STRING, "enacs" },
@@ -265,6 +266,8 @@ tty_term_override(struct tty_term *term, const char *overrides)
} else
val = xstrdup("");
log_debug("%s override: %s %s",
term->name, entstr, removeflag ? "@" : val);
for (i = 0; i < NTTYCODE; i++) {
ent = &tty_term_codes[i];
if (strcmp(entstr, ent->name) != 0)

19
tty.c
View File

@@ -969,7 +969,10 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
* move as far left as possible and redraw the last
* cell to move into the last position.
*/
cx = screen_size_x(s) - width;
if (ctx->last_cell.flags & GRID_FLAG_UTF8)
cx = screen_size_x(s) - ctx->last_utf8.width;
else
cx = screen_size_x(s) - 1;
tty_cursor_pane(tty, ctx, cx, ctx->ocy);
tty_cell(tty, &ctx->last_cell, &ctx->last_utf8);
}
@@ -1437,7 +1440,7 @@ tty_check_bg(struct tty *tty, struct grid_cell *gc)
/* Is this an aixterm colour? */
colours = tty_term_number(tty->term, TTYC_COLORS);
if (gc->bg >= 100 && gc->bg <= 107 && colours < 16) {
if (gc->bg >= 90 && gc->bg <= 97 && colours < 16) {
gc->bg -= 90;
gc->attr |= GRID_ATTR_BRIGHT;
}
@@ -1497,14 +1500,14 @@ tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
}
/* Is this an aixterm bright colour? */
if (bg >= 100 && bg <= 107) {
if (bg >= 90 && bg <= 97) {
/* 16 colour terminals or above only. */
if (tty_term_number(tty->term, TTYC_COLORS) >= 16) {
xsnprintf(s, sizeof s, "\033[%dm", bg);
xsnprintf(s, sizeof s, "\033[%dm", bg + 10);
tty_puts(tty, s);
goto save_bg;
}
bg -= 100;
bg -= 90;
/* no such thing as a bold background */
}
@@ -1546,3 +1549,9 @@ tty_try_88(struct tty *tty, u_char colour, const char *type)
tty_puts(tty, s);
return (0);
}
void
tty_bell(struct tty *tty)
{
tty_putcode(tty, TTYC_BEL);
}

View File

@@ -52,7 +52,7 @@ void window_copy_goto_line(struct window_pane *, const char *);
void window_copy_update_cursor(struct window_pane *, u_int, u_int);
void window_copy_start_selection(struct window_pane *);
int window_copy_update_selection(struct window_pane *);
void window_copy_copy_selection(struct window_pane *);
void window_copy_copy_selection(struct window_pane *, int);
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);
@@ -67,6 +67,8 @@ void window_copy_cursor_up(struct window_pane *, int);
void window_copy_cursor_down(struct window_pane *, int);
void window_copy_cursor_jump(struct window_pane *);
void window_copy_cursor_jump_back(struct window_pane *);
void window_copy_cursor_jump_to(struct window_pane *);
void window_copy_cursor_jump_to_back(struct window_pane *);
void window_copy_cursor_next_word(struct window_pane *, const char *);
void window_copy_cursor_next_word_end(struct window_pane *, const char *);
void window_copy_cursor_previous_word(struct window_pane *, const char *);
@@ -90,6 +92,8 @@ enum window_copy_input_type {
WINDOW_COPY_SEARCHDOWN,
WINDOW_COPY_JUMPFORWARD,
WINDOW_COPY_JUMPBACK,
WINDOW_COPY_JUMPTOFORWARD,
WINDOW_COPY_JUMPTOBACK,
WINDOW_COPY_GOTOLINE,
};
@@ -132,9 +136,9 @@ struct window_copy_mode_data {
enum window_copy_input_type inputtype;
const char *inputprompt;
char *inputstr;
char *inputstr;
u_int numprefix;
int numprefix;
enum window_copy_input_type searchtype;
char *searchstr;
@@ -165,7 +169,7 @@ window_copy_init(struct window_pane *wp)
data->inputtype = WINDOW_COPY_OFF;
data->inputprompt = NULL;
data->inputstr = xstrdup("");
data->numprefix = 0;
data->numprefix = -1;
data->searchtype = WINDOW_COPY_OFF;
data->searchstr = NULL;
@@ -358,25 +362,33 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
const char *word_separators;
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
u_int n, np;
int keys;
u_int n;
int np, keys;
enum mode_key_cmd cmd;
np = data->numprefix;
if (np == 0)
if (np <= 0)
np = 1;
if (data->inputtype == WINDOW_COPY_JUMPFORWARD ||
data->inputtype == WINDOW_COPY_JUMPBACK) {
data->inputtype == WINDOW_COPY_JUMPBACK ||
data->inputtype == WINDOW_COPY_JUMPTOFORWARD ||
data->inputtype == WINDOW_COPY_JUMPTOBACK) {
/* Ignore keys with modifiers. */
if ((key & KEYC_MASK_MOD) == 0) {
data->jumpchar = key;
if (data->inputtype == WINDOW_COPY_JUMPFORWARD) {
for (; np != 0; np--)
window_copy_cursor_jump(wp);
} else {
} else if (data->inputtype == WINDOW_COPY_JUMPBACK) {
for (; np != 0; np--)
window_copy_cursor_jump_back(wp);
} else if (data->inputtype == WINDOW_COPY_JUMPTOFORWARD) {
for (; np != 0; np--)
window_copy_cursor_jump_to(wp);
} else if (data->inputtype == WINDOW_COPY_JUMPTOBACK) {
for (; np != 0; np--)
window_copy_cursor_jump_to_back(wp);
}
}
data->jumptype = data->inputtype;
@@ -513,7 +525,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);
window_copy_copy_selection(wp, -1);
window_pane_reset_mode(wp);
return;
}
@@ -524,7 +536,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
break;
case MODEKEYCOPY_COPYSELECTION:
if (sess != NULL) {
window_copy_copy_selection(wp);
window_copy_copy_selection(wp, data->numprefix);
window_pane_reset_mode(wp);
return;
}
@@ -548,13 +560,13 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
break;
case MODEKEYCOPY_NEXTWORD:
word_separators =
options_get_string(&wp->window->options, "word-separators");
options_get_string(&sess->options, "word-separators");
for (; np != 0; np--)
window_copy_cursor_next_word(wp, word_separators);
break;
case MODEKEYCOPY_NEXTWORDEND:
word_separators =
options_get_string(&wp->window->options, "word-separators");
options_get_string(&sess->options, "word-separators");
for (; np != 0; np--)
window_copy_cursor_next_word_end(wp, word_separators);
break;
@@ -564,7 +576,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
break;
case MODEKEYCOPY_PREVIOUSWORD:
word_separators =
options_get_string(&wp->window->options, "word-separators");
options_get_string(&sess->options, "word-separators");
for (; np != 0; np--)
window_copy_cursor_previous_word(wp, word_separators);
break;
@@ -581,6 +593,12 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
} else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
for (; np != 0; np--)
window_copy_cursor_jump_back(wp);
} else if (data->jumptype == WINDOW_COPY_JUMPTOFORWARD) {
for (; np != 0; np--)
window_copy_cursor_jump_to(wp);
} else if (data->jumptype == WINDOW_COPY_JUMPTOBACK) {
for (; np != 0; np--)
window_copy_cursor_jump_to_back(wp);
}
break;
case MODEKEYCOPY_JUMPREVERSE:
@@ -590,6 +608,12 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
} else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
for (; np != 0; np--)
window_copy_cursor_jump(wp);
} else if (data->jumptype == WINDOW_COPY_JUMPTOFORWARD) {
for (; np != 0; np--)
window_copy_cursor_jump_to_back(wp);
} else if (data->jumptype == WINDOW_COPY_JUMPTOBACK) {
for (; np != 0; np--)
window_copy_cursor_jump_to(wp);
}
break;
case MODEKEYCOPY_JUMPBACK:
@@ -598,6 +622,18 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
*data->inputstr = '\0';
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
return; /* skip numprefix reset */
case MODEKEYCOPY_JUMPTO:
data->inputtype = WINDOW_COPY_JUMPTOFORWARD;
data->inputprompt = "Jump To";
*data->inputstr = '\0';
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
return; /* skip numprefix reset */
case MODEKEYCOPY_JUMPTOBACK:
data->inputtype = WINDOW_COPY_JUMPTOBACK;
data->inputprompt = "Jump To Back";
*data->inputstr = '\0';
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
return; /* skip numprefix reset */
case MODEKEYCOPY_SEARCHUP:
data->inputtype = WINDOW_COPY_SEARCHUP;
data->inputprompt = "Search Up";
@@ -613,6 +649,8 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
case WINDOW_COPY_GOTOLINE:
case WINDOW_COPY_JUMPFORWARD:
case WINDOW_COPY_JUMPBACK:
case WINDOW_COPY_JUMPTOFORWARD:
case WINDOW_COPY_JUMPTOBACK:
case WINDOW_COPY_NUMERICPREFIX:
break;
case WINDOW_COPY_SEARCHUP:
@@ -664,7 +702,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
break;
}
data->numprefix = 0;
data->numprefix = -1;
return;
input_on:
@@ -696,11 +734,11 @@ window_copy_key_input(struct window_pane *wp, int key)
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
size_t inputlen;
u_int np;
int np;
switch (mode_key_lookup(&data->mdata, key)) {
case MODEKEYEDIT_CANCEL:
data->numprefix = 0;
data->numprefix = -1;
return (-1);
case MODEKEYEDIT_BACKSPACE:
inputlen = strlen(data->inputstr);
@@ -712,13 +750,15 @@ window_copy_key_input(struct window_pane *wp, int key)
break;
case MODEKEYEDIT_ENTER:
np = data->numprefix;
if (np == 0)
if (np <= 0)
np = 1;
switch (data->inputtype) {
case WINDOW_COPY_OFF:
case WINDOW_COPY_JUMPFORWARD:
case WINDOW_COPY_JUMPBACK:
case WINDOW_COPY_JUMPTOFORWARD:
case WINDOW_COPY_JUMPTOBACK:
case WINDOW_COPY_NUMERICPREFIX:
break;
case WINDOW_COPY_SEARCHUP:
@@ -738,7 +778,7 @@ window_copy_key_input(struct window_pane *wp, int key)
*data->inputstr = '\0';
break;
}
data->numprefix = 0;
data->numprefix = -1;
return (1);
case MODEKEY_OTHER:
if (key < 32 || key > 126)
@@ -767,7 +807,7 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
if (key < '0' || key > '9')
return 1;
if (data->numprefix >= 100) /* no more than three digits */
if (data->numprefix >= 100) /* no more than three digits */
return 0;
data->numprefix = data->numprefix * 10 + key - '0';
@@ -834,7 +874,7 @@ reset_mode:
s->mode &= ~MODE_MOUSE_BUTTON;
s->mode |= MODE_MOUSE_STANDARD;
if (sess != NULL) {
window_copy_copy_selection(wp);
window_copy_copy_selection(wp, -1);
window_pane_reset_mode(wp);
}
}
@@ -1235,7 +1275,7 @@ window_copy_update_selection(struct window_pane *wp)
}
void
window_copy_copy_selection(struct window_pane *wp)
window_copy_copy_selection(struct window_pane *wp, int idx)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
@@ -1315,7 +1355,7 @@ window_copy_copy_selection(struct window_pane *wp)
} else {
if (keys == MODEKEY_EMACS)
lastex = ex;
else
else
lastex = ex + 1;
restex = xx;
firstsx = sx;
@@ -1347,8 +1387,11 @@ window_copy_copy_selection(struct window_pane *wp)
screen_write_setselection(&wp->ictx.ctx, buf, off);
/* Add the buffer to the stack. */
limit = options_get_number(&global_options, "buffer-limit");
paste_add(&global_buffers, buf, off, limit);
if (idx == -1) {
limit = options_get_number(&global_options, "buffer-limit");
paste_add(&global_buffers, buf, off, limit);
} else
paste_replace(&global_buffers, idx, buf, off);
}
void
@@ -1709,6 +1752,62 @@ window_copy_cursor_jump_back(struct window_pane *wp)
}
}
void
window_copy_cursor_jump_to(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing;
const struct grid_cell *gc;
u_int px, py, xx;
px = data->cx + 1;
py = screen_hsize(back_s) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
while (px < xx) {
gc = grid_peek_cell(back_s->grid, px, py);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
&& gc->data == data->jumpchar) {
window_copy_update_cursor(wp, px - 1, data->cy);
if (window_copy_update_selection(wp))
window_copy_redraw_lines(wp, data->cy, 1);
return;
}
px++;
}
}
void
window_copy_cursor_jump_to_back(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing;
const struct grid_cell *gc;
u_int px, py;
px = data->cx;
py = screen_hsize(back_s) + data->cy - data->oy;
if (px > 0)
px--;
for (;;) {
gc = grid_peek_cell(back_s->grid, px, py);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
&& gc->data == data->jumpchar) {
window_copy_update_cursor(wp, px + 1, data->cy);
if (window_copy_update_selection(wp))
window_copy_redraw_lines(wp, data->cy, 1);
return;
}
if (px == 0)
break;
px--;
}
}
void
window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
{

View File

@@ -451,7 +451,7 @@ window_pane_at_index(struct window *w, u_int idx)
struct window_pane *wp;
u_int n;
n = 0;
n = options_get_number(&w->options, "pane-base-index");
TAILQ_FOREACH(wp, &w->panes, entry) {
if (n == idx)
return (wp);
@@ -483,19 +483,21 @@ window_pane_previous_by_number(struct window *w, struct window_pane *wp,
return (wp);
}
u_int
window_pane_index(struct window *w, struct window_pane *wp)
int
window_pane_index(struct window_pane *wp, u_int *i)
{
struct window_pane *wq;
u_int n;
struct window *w = wp->window;
n = 0;
*i = options_get_number(&w->options, "pane-base-index");
TAILQ_FOREACH(wq, &w->panes, entry) {
if (wp == wq)
break;
n++;
if (wp == wq) {
return (0);
}
(*i)++;
}
return (n);
return (-1);
}
u_int
@@ -679,6 +681,10 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
if (tio != NULL)
memcpy(tio2.c_cc, tio->c_cc, sizeof tio2.c_cc);
tio2.c_cc[VERASE] = '\177';
#ifdef IUTF8
if (options_get_number(&wp->window->options, "utf8"))
tio2.c_iflag |= IUTF8;
#endif
if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
fatal("tcgetattr failed");
@@ -694,7 +700,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
if (*wp->cmd != '\0') {
/* Set SHELL but only if it is currently not useful. */
shell = getenv("SHELL");
if (shell == NULL || *shell == '\0' || areshell(shell))
if (checkshell(shell))
setenv("SHELL", wp->shell, 1);
execl(_PATH_BSHELL, "sh", "-c", wp->cmd, (char *) NULL);

View File

@@ -3,33 +3,33 @@
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>tmux</title>
<link rel="stylesheet" type="text/css" media="screen" href="main.css"/>
<title>tmux</title>
<link rel="stylesheet" type="text/css" media="screen" href="main.css"/>
</head>
<body>
<div id="body-wrapper">
<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://tmux.svn.sourceforge.net/viewvc/tmux/trunk/NOTES">Release Notes</a></li>
<li><a href="http://tmux.svn.sourceforge.net/viewvc/tmux/trunk/CHANGES">Changelog</a></li>
<li><a href="http://tmux.svn.sourceforge.net/viewvc/tmux/trunk/FAQ">FAQ</a></li>
<div id="body-wrapper">
<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://tmux.svn.sourceforge.net/viewvc/tmux/trunk/NOTES">Release Notes</a></li>
<li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=tmux&sektion=1">Manual Page</a></li>
<li><a href="http://tmux.svn.sourceforge.net/viewvc/tmux/trunk/FAQ">FAQ</a></li>
<li><a href="http://www.openbsd.org/faq/faq7.html#tmux">tmux in the OpenBSD FAQ</a></li>
<li><a href="http://tmux.svn.sourceforge.net/viewvc/tmux/trunk/examples/">Examples</a></li>
<li>&nbsp;</li>
<li class="menu-headings">Source Code</li>
<li>&nbsp;</li>
<li class="menu-headings">Source Code</li>
<li><a href="http://tmux.svn.sourceforge.net/viewvc/tmux/trunk/">SourceForge</a></li>
<li><a href="http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/tmux/">OpenBSD</a></li>
<li>&nbsp;</li>
<li class="menu-headings">Support</li>
<li><a href="https://lists.sourceforge.net/lists/listinfo/tmux-users">tmux-users</a></li>
<li><a href="https://lists.sourceforge.net/lists/listinfo/tmux-cvs">tmux-cvs</a></li>
<li>IRC: #tmux on Freenode</li>
<li><a href="http://sf.net/projects/tmux">SourceForge Project Page</a></li>
</ul>
</div>
<div id="main-content-wrapper">
<li>&nbsp;</li>
<li class="menu-headings">Support</li>
<li><a href="https://lists.sourceforge.net/lists/listinfo/tmux-users">tmux-users</a></li>
<li><a href="https://lists.sourceforge.net/lists/listinfo/tmux-cvs">tmux-cvs</a></li>
<li>IRC: #tmux on Freenode</li>
<li><a href="http://sf.net/projects/tmux">SourceForge Project Page</a></li>
</ul>
</div>
<div id="main-content-wrapper">
<p>tmux is a terminal multiplexer: it enables a number of terminals (or
windows), each running a separate program, to be created, accessed, and
@@ -74,13 +74,12 @@ terminfo implementation (normally <a href="http://invisible-island.net/ncurses/"
<a href="https://github.com/lmartinking/tmux-applets">tmux-applets</a> and
<a href="https://github.com/remiprev/teamocil">teamocil</a>.</p>
<div id="screenshots">
<a href="tmux3.png"><img src="small-tmux3.png" alt="Screenshot"/></a>
<a href="tmux4.png"><img src="small-tmux4.png" alt="Screenshot"/></a>
<a href="tmux5.png"><img src="small-tmux5.png" alt="Screenshot"/></a>
</div>
</div>
<div id="screenshots">
<a href="tmux3.png"><img src="small-tmux3.png" alt="Screenshot"/></a>
<a href="tmux4.png"><img src="small-tmux4.png" alt="Screenshot"/></a>
<a href="tmux5.png"><img src="small-tmux5.png" alt="Screenshot"/></a>
</div>
</div>
</div>
</body>
</html>