594 Commits
0.8 ... 1.0

Author SHA1 Message Date
no_author
be20fc8699 This commit was manufactured by cvs2svn to create tag 'TMUX_1_0'. 2009-09-20 18:54:22 +00:00
Nicholas Marriott
f82598ca2d 1.0. 2009-09-20 18:54:21 +00:00
Nicholas Marriott
b29d4affd8 Don't try to use tio if it is NULL. 2009-09-20 18:31:16 +00:00
Nicholas Marriott
6594af3729 These are done. 2009-09-20 17:52:39 +00:00
Nicholas Marriott
6df9ac7c37 FreeBSD tree.h is fine. 2009-09-20 17:51:54 +00:00
Tiago Cunha
73f58b90a0 Update. 2009-09-19 18:53:56 +00:00
Tiago Cunha
23d7ed3187 Sync OpenBSD patchset 331:
New option, set-titles-string, to allow the window title to be specified (as
for status-left/right) if set-titles is on. Also only update the title when the
status line is being redrawn.
2009-09-19 18:53:01 +00:00
Nicholas Marriott
a2e03ce3cb Add some bits. 2009-09-18 14:19:18 +00:00
Nicholas Marriott
15b643fc11 Sync from OpenBSD:
==
Rather than constructing an entire termios struct from ttydefaults.h, just let
forkpty do it and then alter the bits that should be changed after fork. A
little neater and more portable.
==

This should fix problems caused by glibc's broken ttydefaults.h file.
2009-09-16 12:36:28 +00:00
Tiago Cunha
150fba5ecd Sync OpenBSD patchset 329:
Enclose repeated buffer draining code in a new msgbuf_drain()
function, which is additionally exported for use by others.

From nicm@, who reminded me that tmux is now using buffer.c, too.
2009-09-15 23:59:40 +00:00
Tiago Cunha
c507bf25de Sync OpenBSD patchset 328:
Stick line length to what is actually used (removing an optimization that
allowed it to be bigger), and use clear line/EOL sequences rather than spaces
in copy/scroll mode.

This fixes xterm copy/paste from tmux which treats trailing spaces differently
from clearing a line with the escape sequences. Reported by martynas@.
2009-09-15 23:54:57 +00:00
Tiago Cunha
dbaa28492e Sync OpenBSD patchset 327:
The default terminal size should be 80x24, not 80x25.
2009-09-15 23:52:30 +00:00
Tiago Cunha
960cd3da69 Sync OpenBSD patchset 326:
Nuke unused server_client_index function, pointed out by martynas@.
2009-09-15 23:50:32 +00:00
Nicholas Marriott
82d6bab57c +. 2009-09-15 19:02:35 +00:00
Nicholas Marriott
24baf14e53 Update. 2009-09-15 07:43:25 +00:00
Tiago Cunha
5fcf7149d4 Always set VERASE to \177. 2009-09-13 20:56:52 +00:00
Tiago Cunha
4d4ec52df8 Zap unused variables. 2009-09-13 20:43:21 +00:00
Tiago Cunha
69e7f4af19 Sync OpenBSD patchset 324:
Tidy some common code for destroying sessions into a new function.
2009-09-13 20:37:37 +00:00
Tiago Cunha
61990deb36 Sync OpenBSD patchset 323:
tmux always outputs \177 for backspace, so explicitly set VERASE to \177 for
new windows.
2009-09-13 20:30:12 +00:00
Tiago Cunha
0ec1ce005c Sync OpenBSD patchset 322:
Permit options such as status-bg to be configured using the entire 256 colour
palette by setting "colour0" to "colour255".
2009-09-11 14:13:52 +00:00
Tiago Cunha
f0cb57d8ac Sync OpenBSD patchset 321:
While the display-panes indicator is on screen, make the number keys select the
pane with that index.
2009-09-08 00:01:11 +00:00
Tiago Cunha
930f67f474 Sync OpenBSD patchset 320:
Reference count clients and sessions rather than relying on a saved index for
cmd-choose-*.
2009-09-07 23:59:19 +00:00
Tiago Cunha
1de812d5a8 Sync OpenBSD patchset 319:
Tiny cleanup.

ok nicm@
2009-09-07 23:50:07 +00:00
Tiago Cunha
c272de7cba Sync OpenBSD patchset 318:
Give each paste buffer a size member instead of requiring them to be
zero-terminated.
2009-09-07 23:48:54 +00:00
Tiago Cunha
5edc465802 Sync OpenBSD patchset 317:
Permit embedded colour and attributes in status-left and status-right using new
#[] special characters, for example #[fg=red,bg=blue,blink].
2009-09-07 23:37:48 +00:00
Nicholas Marriott
ec195a4e15 +. 2009-09-07 15:41:52 +00:00
Tiago Cunha
bb2d57dcbf Sync OpenBSD patchset 316:
Only redraw all clients once when the backoff timer expires rather than every
second all the time.

Reported by Simon Nicolussi.
2009-09-05 19:03:41 +00:00
Tiago Cunha
02c4760ace Sync OpenBSD patchset 315:
Tidy main and make it a bit easier to read.
2009-09-04 20:37:40 +00:00
Tiago Cunha
51a1f25247 Sync OpenBSD patchset 314:
Tell the user when sleeping due to password backoff.
2009-09-04 20:27:06 +00:00
Nicholas Marriott
895efe7b05 Solaris needs a knob twiddled to get POSIX getpwduid_r. 2009-09-04 14:48:25 +00:00
Tiago Cunha
83f5581da4 Sync OpenBSD patchset 313:
Fix a race condition when asking a client to take over the terminal (switching
to a different poll loop):

If a MSG_READY was followed very quickly by a MSG_EXIT (for example if doing
"tmux new 'exit'"), both messages could be read as part of the same imsg_read
in the first client poll loop. The MSG_READY would then cause a switch to the
second client loop, which would immediately call poll(2) again, causing the
client to hang forever waiting for an exit message that it already had.

Change to call imsg_get to process any existing messages before polling.
2009-09-03 21:06:30 +00:00
Tiago Cunha
884ebb6dab Sync OpenBSD patchset 309:
Accept -l to make it easier for people who use tmux as a login shell to use
$SHELL. Originally from martynas@, tweaked by me.
2009-09-03 21:02:55 +00:00
Tiago Cunha
c274551db6 - Make it compile on operating systems other than BSD due to OpenBSD patchset
308.
- While there, remove some duplicate code from the compat header file.
2009-09-03 20:54:39 +00:00
Tiago Cunha
f796336a12 Sync OpenBSD patchset 308:
When incorrect passwords are entered, behave similarly to login(1) and backoff
for a bit. Based on a diff from martynas@.
2009-09-03 20:44:38 +00:00
Tiago Cunha
3b944fe7e8 Sync OpenBSD patchset 307:
Add a transpose-chars command in edit mode (C-t in emacs mode only). From Kalle
Olavi Niemitalo.
2009-09-02 22:45:17 +00:00
Nicholas Marriott
afd0bd7cb0 When shutting down the server, expect clients to be polite and exit when asked
with the right message.
2009-09-02 21:36:00 +00:00
Nicholas Marriott
a5c17d77bf Nuke debugging. 2009-09-02 20:17:23 +00:00
Nicholas Marriott
d33caca6c7 That was the wrong fix. MSG_ERROR should set the error and the client should
use the error and exit on MSG_EXIT (it was being handled in the default
case). Undo the last change, move the errstr check into the MSG_EXIT case, and
add a comment.
2009-09-02 20:16:29 +00:00
Nicholas Marriott
c23bde74ec Set exittype for error exit as well as the error string. 2009-09-02 20:01:22 +00:00
Nicholas Marriott
ecffcf1667 Update. 2009-09-02 19:33:47 +00:00
Nicholas Marriott
26682256b3 OS X CMSG_FIRSTHDR is broken. 2009-09-02 12:30:56 +00:00
Tiago Cunha
5838ee1263 Sync OpenBSD patchset 306:
If forking a login shell or if SHELL is otherwise not useful, set it to the
default shell. Based on a diff from martynas@.
2009-09-02 01:08:32 +00:00
Tiago Cunha
b7cb7d10f9 Update. 2009-09-02 01:06:30 +00:00
Tiago Cunha
521659db4b Adjust OpenBSD patchset 305 to the portable version. 2009-09-02 01:05:55 +00:00
Tiago Cunha
a3a150faf2 Sync OpenBSD patchset 305:
When using tmux as a login shell, there is currently no way to specify a shell
to be used as a login shell inside tmux, so add a default-shell session option.
This sets the shell invoked as a login shell when the default-command option is
empty.

The default option value is whichever of $SHELL, getpwuid(getuid())'s pw_shell
or /bin/sh is valid first.

Based on a diff from martynas@, changed by me to be a session option rather
than a window option.
2009-09-02 01:02:44 +00:00
Tiago Cunha
ce5c441f0f Sync OpenBSD patchset 304:
Use "Password:" with no space for password prompts and don't display a *s for
the password, like pretty much everything else. From martynas@ with minor
tweaks by me.
2009-09-02 00:55:49 +00:00
Tiago Cunha
99de03ea32 Sync OpenBSD patchset 303:
Sort cases same as getopt argument, from martynas.
2009-09-02 00:54:00 +00:00
Tiago Cunha
d463eddb8b Update. 2009-08-31 22:31:44 +00:00
Tiago Cunha
ed3535db8a Sync OpenBSD patchset 302:
Add a new display-panes command, with two options (display-panes-colour and
display-panes-time), which displays a visual indication of the number of each
pane.
2009-08-31 22:30:15 +00:00
Tiago Cunha
2fe369831c Sync OpenBSD patchset 301:
squash typo
2009-08-31 22:25:33 +00:00
Tiago Cunha
86fb9737dc Sync OpenBSD patchset 300:
Don't call tty_free unless the client is a terminal, otherwise tty_init hasn't
been called and it may end up doing close(0). From Kalle Olavi Niemitalo.
2009-08-31 22:24:18 +00:00
Tiago Cunha
d15e88cb68 Sync OpenBSD patchset 299:
Initialise the arg2 pointer properly (also free it when freeing the
others). Fixes crashes with J in malloc_options reported by oga.
2009-08-26 22:13:52 +00:00
Tiago Cunha
83e44c7d8e Sync OpenBSD patchset 298:
Make this work when the clock is in small characters as well. Doh.
2009-08-26 22:12:21 +00:00
Tiago Cunha
fde3bda453 Sync OpenBSD patchset 297:
Fix clock mode in black and white terminals now that tty.c tries to fix
reverse.
2009-08-26 22:11:00 +00:00
Nicholas Marriott
1a5aba47c7 ttydefchars is a fucking horlicks. Happily we only need it in one file, move it
in there to avoid multiple inclusion issues.

Perhaps it would be better to pass NULL through to forkpty in the default
case...
2009-08-26 09:10:47 +00:00
Nicholas Marriott
6b4ed722b1 FreeBSD and NetBSD HAVE got ttydefaults.h. Fixes SF bug 2844744.
Also make clang use -iquote in makefiles.
2009-08-26 08:58:39 +00:00
Tiago Cunha
1ce325b31e Sync OpenBSD patchset 296:
Print -l and -p when showing command, pointed out by Tiago Cunha.
2009-08-25 16:52:42 +00:00
Tiago Cunha
f5d38f2696 Update. 2009-08-25 16:50:34 +00:00
Tiago Cunha
bd5b011ecd Include <ctype.h>. 2009-08-25 13:55:29 +00:00
Tiago Cunha
8fd77cbb5b Sync OpenBSD patchset 294:
Add a choose-client command and extend choose-{session,window} to accept a
template. After a choice is made, %% (or %1) in the template is replaced by the
name of the session, window or client suitable for -t and the result executed
as a command. So, for example, "choose-window "killw -t '%%'"" will kill the
selected window.

The defaults if no template is given are (as now) select-window for
choose-window, switch-client for choose-session, and detach-client for
choose-client (now bound to D).
2009-08-25 13:53:39 +00:00
Tiago Cunha
c1653ff654 Sync OpenBSD patchset 293:
gcc2 doesn't understand attributes on function pointers.
2009-08-25 13:11:24 +00:00
Nicholas Marriott
22b2b7c6c5 Done. 2009-08-25 12:24:45 +00:00
Tiago Cunha
d5bc78d98b Sync OpenBSD patchset 292:
Add some other obvious variables to update-environment (WINDOWID SSH_ASKPASS
SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION) so they are updated in the session
environment on new/attach.
2009-08-24 16:35:24 +00:00
Tiago Cunha
a3799e0350 Sync OpenBSD patchset 291:
Some code tidying.
2009-08-24 16:31:26 +00:00
Tiago Cunha
35b926c445 Sync OpenBSD patchset 290:
When using source-file, run the commands in the context of the source-file
command rather than with no context. This makes things like attach work from a
file.
2009-08-24 16:27:03 +00:00
Tiago Cunha
2e2e762743 Sync OpenBSD patchset 289:
The cursession member in struct cmd_ctx is always either curclient->session or
NULL when curclient is also NULL, so just eliminate it.
2009-08-24 16:24:18 +00:00
Nicholas Marriott
266c13df18 Check the return value of strunvis against -1 not NULL. 2009-08-23 11:50:39 +00:00
Tiago Cunha
633e74ef80 Sync OpenBSD patchset 287:
Emulate dch/dch1 if missing by redrawing the entire line.
2009-08-21 21:15:00 +00:00
Tiago Cunha
1fa8a8f4a6 Sync OpenBSD patchset 285:
Ugh, committed the wrong version of this change and got both solutions rather
than just the second. Remove unused assignment.
2009-08-21 21:13:20 +00:00
Tiago Cunha
d07d18258b Sync OpenBSD patchset 284:
When moving up or down in copy mode, save the cursor position and size of the
last line with content (width != 0) and use it to determine if the cursor
should be at the end of the line. Fixes problem of the cursor always jumping to
the end of the line when scrolling past a blank line.
2009-08-21 21:12:07 +00:00
Tiago Cunha
a004fc3592 Sync OpenBSD patchset 283:
Fix grid_expand_line so it actually works when the required size is bigger than
2 * the current size.
2009-08-21 21:10:37 +00:00
Tiago Cunha
4b883524d8 Sync OpenBSD patchset 282:
A few trivial optimisations: no need to check for zero size if calling
buffer_ensure in buffer.c; expand grid lines by a greater increase than one
each time; and don't read UTF-8 data unless it actually needs to be checked
when overwriting a cell.
2009-08-21 21:09:13 +00:00
Tiago Cunha
15556ad0d6 Sync OpenBSD patchset 281:
Nuke unused variable.
2009-08-21 21:07:20 +00:00
Nicholas Marriott
27c5df22cf Move reading termios settings to before tty_open alters them, and expand the
comment.
2009-08-21 11:38:09 +00:00
Nicholas Marriott
03f4ab4bd5 Done. 2009-08-21 10:57:21 +00:00
Nicholas Marriott
f1c982608f VTIME and VMIN are only necessary in noncanonical mode, so Solaris reuses the
VEOF and VEOL indexes for them. ICANON is set by default, so don't bother to
set VTIME and VMIN.
2009-08-20 18:35:53 +00:00
Nicholas Marriott
c18e027ad5 Need this rubbish on Solaris for CMESG*. 2009-08-20 13:35:59 +00:00
Nicholas Marriott
dd9dd142c9 Add $Id$, nuke queue.h. 2009-08-20 12:54:08 +00:00
Nicholas Marriott
2f517111ef Solaris has no u_int32_t etc. 2009-08-20 12:49:18 +00:00
Nicholas Marriott
9311e4255e Didn't mean to commit this. 2009-08-20 12:39:21 +00:00
Nicholas Marriott
61c7bfc128 Also undef CTRL. 2009-08-20 12:38:37 +00:00
Nicholas Marriott
14eb6df45e Solaris defines some of these in termios.h so #ifndef them. 2009-08-20 12:27:58 +00:00
Nicholas Marriott
698e003fcd Solaris has no bzero(). 2009-08-20 12:25:17 +00:00
Tiago Cunha
cc2c061289 Sync OpenBSD patchset 280:
Handle the device attributes (DA) escape sequence.
2009-08-20 11:54:58 +00:00
Tiago Cunha
9d33b3f72a Sync OpenBSD patchset 279:
tweak previous;
2009-08-20 11:53:27 +00:00
Tiago Cunha
0027aa3d1e Sync OpenBSD patchset 278:
Don't read beyond the edge of the screen when searching (dies with debug
enabled).
2009-08-20 11:52:39 +00:00
Tiago Cunha
1292540bb5 Sync OpenBSD patchset 276:
Extend command-prompt with a -p option which is a comma-separated list of one
or more prompts to present in order.

The responses to the prompt are replaced in the template string: %% are
replaced in order, so the first prompt replaces the first %%, the second
replaces the second, and so on. In addition, %1 up to %9 are replaced with the
responses to the first the ninth prompts

The default template is "%1" so the response to the first prompt is processed
as a command.

Note that this changes the behaviour for %% so if there is only one prompt,
only the first %% will be replaced. Templates such as "neww -n '%%' 'ssh %%'"
should be changed to "neww -n '%1' 'ssh %1'".

From Tiago Cunha.
2009-08-20 11:51:20 +00:00
Tiago Cunha
4631c07483 Sync OpenBSD patchset 275:
Instead of just checking for an empty buffer, which may not be the case if
there is unconsumed data, save the previous size and use it instead. This means
that activity monitoring should work in this (unlikely) event.

Also remove a debugging statement that no longer seems necessary.
2009-08-20 11:48:01 +00:00
Tiago Cunha
d895d4a9f0 Sync OpenBSD patchset 274:
Whoops, getting the comparison the right way round is usually recommended.
2009-08-20 11:45:37 +00:00
Tiago Cunha
d3da62d53a Sync OpenBSD patchset 273:
Move another expensive options test to after a cheaper timer check/update.
2009-08-20 11:44:18 +00:00
Tiago Cunha
b644b17599 Sync OpenBSD patchset 272:
options_get_number() is relatively expensive and a check for dead panes happens
a lot more often than actually finding one, so instead of getting the option
for every check, get it for every dead window found.
2009-08-20 11:40:15 +00:00
Tiago Cunha
36475f80e9 Sync OpenBSD patchset 271:
Now that pane targets (-t) are supported, switch some commands to use them
where it makes sense: clock-mode, copy-mode, scroll-mode, send-keys,
send-prefix.
2009-08-20 11:37:46 +00:00
Tiago Cunha
52b02850ca Sync OpenBSD patchset 270:
Tag a few missed printf-like functions and fix a missing "%s".
2009-08-20 11:35:16 +00:00
Tiago Cunha
7ca3d7ac8e Do not include vis.h directly, since it's OS-dependent, due to OpenBSD
patchsets 268, and 269.
2009-08-20 11:33:13 +00:00
Tiago Cunha
3756fce553 Sync OpenBSD patchset 269:
Pass show-buffer output through vis(3) as well, and wrap it to the edge of the
terminal when used from the command line.
2009-08-20 11:30:24 +00:00
Tiago Cunha
9386f640a5 Sync OpenBSD patchset 268:
Change list-buffers to run the preview of the buffer through vis(1).
2009-08-20 11:28:05 +00:00
Tiago Cunha
bcfb4f2a07 Sync OpenBSD patchset 267:
Use the full screen width when printing output rather than one less.
2009-08-20 11:24:33 +00:00
Tiago Cunha
aa7c0f1ce8 Sync OpenBSD patchset 266:
Nuke unnecessary assignment.
2009-08-20 11:23:36 +00:00
Tiago Cunha
2a5f08c15a Sync OpenBSD patchset 265:
Add a "delete line" key when editing in the status line or the search up/down
prompt. C-u with emacs keys, d with vi.
2009-08-20 11:22:48 +00:00
Tiago Cunha
70fc085862 Sync OpenBSD patchset 264:
Add (naive) searching and goto line in copy mode. Searching is C-r and C-s with
emacs keys, / and ? with vi; n repeats the search again with either key
set. All searching wraps the top/bottom. Goto line is g for both emacs and vi.

The search prompts don't have full line editing, just simple append and delete
characters.

Also sort the mode keys list in tmux.1.
2009-08-20 11:20:24 +00:00
Nicholas Marriott
09cc530299 Solaris and AIX have no ttydefaults.h. 2009-08-20 05:34:58 +00:00
Nicholas Marriott
966818c23d Call tcsetattr(). Not tested. 2009-08-19 16:06:45 +00:00
Nicholas Marriott
7c9f827bfe In yet another triumph of stupidity over common sense, the glibc
sys/ttydefaults.h is just a copy of the file from *BSD, taking no account of
the fact that their OWN termios.h uses entirely different indexes into the
array.

I know ttydefaults.h is not meant to be portable, but you'd think it would be
obvious to anyone that no file is better than a broken one...
2009-08-19 15:57:54 +00:00
Nicholas Marriott
2a300c6661 Use cfsetispeed/cfsetospeed to set termios speed members. 2009-08-19 14:32:49 +00:00
Nicholas Marriott
53570b1505 Make this match OpenBSD. 2009-08-19 09:28:10 +00:00
Nicholas Marriott
11f0f812c5 Didn't mean to commit this stuff. 2009-08-19 09:04:48 +00:00
Nicholas Marriott
620402a833 This is a better fix for OS X stupidity. 2009-08-19 09:00:06 +00:00
Nicholas Marriott
3f7e2589cd OS X stupid poll fix. 2009-08-19 08:36:45 +00:00
Nicholas Marriott
ed26a1d3bb Update. 2009-08-18 16:21:25 +00:00
Nicholas Marriott
ae1debbc92 Example from Han Boetes. 2009-08-16 21:55:30 +00:00
Tiago Cunha
622e018570 vis(3) compat files were removed prematurely from {DragonFly,Free,Net}BSD. Add
them back, per SourceForge bug #2838408.
2009-08-16 19:48:17 +00:00
Tiago Cunha
a2a8518f74 Sync OpenBSD patchset 263:
Reset attributes as well as scroll region before poll(2) and add a big comment
explaining why.
2009-08-16 19:33:49 +00:00
Tiago Cunha
7182f6d799 Sync OpenBSD patchset 262:
Send SGR0 when initialising the screen. Fixes problems on terminals with BCE
(like putty) if the background colours is non-default when tmux starts. May
also fix problems when resuming a suspended tmux.
2009-08-16 19:31:37 +00:00
Tiago Cunha
646d6a929c Sync OpenBSD patchset 261:
Switch the prompt code to return an empty string when the user enters no
response and reserve NULL for an explicit cancel. Change all callbacks to treat
them the same so no functional change.

Also add cancel key bindings to emacs mode which were missing.
2009-08-16 19:29:24 +00:00
Tiago Cunha
6f9a2ee50a Sync OpenBSD patchset 260:
vi(1)-style half page scroll in copy and scroll modes. Move the vi full page
scroll key to C-b instead of C-u and use C-u/C-d for half page scrolling with
vi keys. In emacs mode, half page scrolling is bound to M-Up and M-Down.

Suggested by merdely (about a year ago :-)).
2009-08-16 19:26:49 +00:00
Tiago Cunha
98e9e09588 Sync OpenBSD patchset 259:
Scroll by two less than the number of lines in the screen, like emacs, rather
than by the entire screen, to make it easier to pull things out from under the
line indicator. Suggested by claudio.
2009-08-16 19:23:07 +00:00
Tiago Cunha
9541471f87 Sync OpenBSD patchset 258:
Disable mode-mouse (mouse in copy/choice mode) by default as it isn't very
useful at the moment and causes confusion.
2009-08-16 19:20:37 +00:00
Tiago Cunha
c1fee8793d Update. 2009-08-16 19:18:10 +00:00
Tiago Cunha
e61ee94e26 Sync OpenBSD patchset 257:
Add a base-index session option to specify the first index checked when looking
for an index for a new window.
2009-08-16 19:16:27 +00:00
Tiago Cunha
9116905b24 Sync OpenBSD patchset 256:
Allowing copy mode to scroll left and right is annoying, so limit it to the
real screen width. To indicate the cursor is at the end of the line rather than
the cell before, put a '$' in the last cell.

Also clear the selection when the terminal is resized to avoid tmux getting
confused.
2009-08-16 19:12:07 +00:00
Tiago Cunha
64950f4524 Sync OpenBSD patchset 255:
Rather than telling the client to exit in the function when creating a new
session detached, let the caller do it. Allows "tmux new -d \; attach" to work.
2009-08-16 19:07:40 +00:00
Tiago Cunha
8973af82c5 Include unistd.h due to OpenBSD patchset 254. At least on Linux, that's where
_POSIX_VDISABLE is defined.
2009-08-16 19:04:05 +00:00
Tiago Cunha
f415d43c3b Sync OpenBSD patchset 254:
When creating a new session from the command-line where there is an external
terminal, copy the termios(4) special characters and use them for new windows
created in the new session. Suggested by Theo.
2009-08-16 18:59:12 +00:00
Nicholas Marriott
8f9858ba2f Solaris has no strsep(3). 2009-08-16 16:15:53 +00:00
Tiago Cunha
ba42910595 Sync OpenBSD patchset 253:
Redraw the screen after resizing.
2009-08-14 21:33:42 +00:00
Tiago Cunha
78c789e1cb Sync OpenBSD patchset 252:
It was originally intended that scroll mode would show content that was
currently off-screen due to resize, but somewhere along the way this got
lost. Restore this behaviour to scroll mode by fixing screen_write_copy to read
up to the saved line length rather than the current screen width. Copy mode
remains unaltered for now.
2009-08-14 21:32:38 +00:00
Tiago Cunha
b5059bc8a4 Sync OpenBSD patchset 251:
If the client passes zero for the window size in the identify message (which it
can, for example on serial terminals), reset it to 80x25, same as for resize
messages. Problem reported by kettenis@.
2009-08-14 21:31:20 +00:00
Tiago Cunha
05fe69eb92 Sync OpenBSD patchset 250:
A tty context must not be modified as it may be reused to update multiple
clients, so make it const.

Also fix an actual modification which caused a hang when a session was
connected to multiple terminals at least one of which was missing ich/ich1.
2009-08-14 21:30:24 +00:00
Tiago Cunha
06b3f49c49 Sync OpenBSD patchset 249:
When started as the shell, __progname contains a leading -, so hardcode "tmux"
for socket path and log files, and strip it when working out the shell.
2009-08-14 21:28:00 +00:00
Tiago Cunha
1063e5d0e4 Sync OpenBSD patchset 248:
imsg closes the fd after sending, so dup() STDIN_FILENO before passing it to
the parent, otherwise TIOCGWINSZ will fail when the window is resized (that
could actually be moved into the server but this is more future-proof and
avoids breaking the protocol).
2009-08-14 21:26:07 +00:00
Tiago Cunha
7f77c395e3 Sync OpenBSD patchset 247:
Initialise log_fd to -1, prevents spurious disconnection of the client when it
ends up as fd 0 (likely if the server is started with "tmux start").

Also add some extra debugging messages to server.c.
2009-08-14 21:24:46 +00:00
Tiago Cunha
e2a18894b3 Sync OpenBSD patchset 246:
Have the client pass its stdin fd to the server when identifying itself and
have the server use that rather than reopening the tty. If the fd isn't given,
use the old behaviour (so no need for a version change).

This allows tmux to be used as the shell, so also change so that when working
out the command to execute if default-command is empty (the default), tmux will
try not execute itself.
2009-08-14 21:23:20 +00:00
Tiago Cunha
0714e41148 Sync OpenBSD patchset 245:
Add a TTY_OPENED flag and tidy a little.
2009-08-14 21:20:01 +00:00
Tiago Cunha
5cc971facd Sync OpenBSD patchset 244:
Drop the no_stop argument to tty_close and tty_free in favour of a flag in the
tty struct.
2009-08-14 21:17:54 +00:00
Tiago Cunha
b402cef338 Adjust imsg changes to the portable version due to OpenBSD patchset 243. 2009-08-14 21:13:48 +00:00
Tiago Cunha
a9b6bfdddd Sync OpenBSD patchset 243:
Switch tmux to use imsg. This is the last major change to make the
client-server protocol more resilient and make the protocol versioning work
properly. In future, the only things requiring a protocol version bump will be
changes in the message structs, and (when both client and server have this
change) mixing different versions should nicely report an error message.

As a side effect this also makes the code tidier, fixes a problem with the way
errors reported during server startup were handled, and supports fd passing
(which will be used in future).

Looked over by eric@, thanks.

Please note that mixing a client with this change with an older server or vice
versa may cause tmux to crash or hang - tmux should be completely exited before
upgrading.
2009-08-14 21:04:04 +00:00
Nicholas Marriott
a604dfbb97 +. 2009-08-13 22:39:22 +00:00
Nicholas Marriott
e9d170176d Add and remove some bits. 2009-08-13 22:36:20 +00:00
Nicholas Marriott
304296972b Sync from OpenBSD:
Add flags for 1+2 and 2 arguments to the generic target code, use it for
cmd-set-environment/option/window-option and remove the generic options
parsing.
2009-08-11 14:42:59 +00:00
Nicholas Marriott
d0eae2cbfd +. 2009-08-11 10:09:32 +00:00
Nicholas Marriott
4d90ce7b40 Update. 2009-08-11 10:06:27 +00:00
Tiago Cunha
48ede1a00a Sync OpenBSD patchset 241:
No arguments are the same as new-session and this requires the environment to
be sent, so set that flag too when argc == 0.
2009-08-10 21:43:34 +00:00
Tiago Cunha
c261ae32d2 Sync OpenBSD patchset 240:
Reset the attributes after drawing all or part of the screen, and reset the
region before poll(2). This reduces (but does not eliminate) the chance of the
attributes not being normal if tmux is disconnected without warning (ssh ~.,
reboot from inside, etc).
2009-08-10 21:41:35 +00:00
Tiago Cunha
e8ea3ccd58 Sync OpenBSD patchset 239:
Use the right source and destination lines in grid_duplicate_lines.
2009-08-10 21:40:21 +00:00
Tiago Cunha
7bcd7c2752 Sync OpenBSD patchset 238:
some minor tweaks; ok nicm
2009-08-10 21:39:15 +00:00
Nicholas Marriott
7dbabe84e4 Missing options are not illegal. 2009-08-09 18:35:38 +00:00
Tiago Cunha
3dadb349eb Sync OpenBSD patchset 237:
zap trailing whitespace;
2009-08-09 18:02:36 +00:00
Tiago Cunha
e43ce15736 Sync OpenBSD patchset 236:
Minor language tweaks, change which key bindings are summarised.
2009-08-09 18:02:02 +00:00
Tiago Cunha
6297285527 Nuke dead variable here as well, in accordance to OpenBSD patchset 235. 2009-08-09 18:00:45 +00:00
Tiago Cunha
2c863b9f2c Sync OpenBSD patchset 235:
Nuke a dead variable found with clang and an unused declaration with lint.
2009-08-09 17:57:39 +00:00
Tiago Cunha
221ce5afb3 Sync OpenBSD patchset 234:
Move the key bindings section to near the start, mention attach/detach in the
first section, and another couple of tweaks. Based on a diff from Theo.
2009-08-09 17:55:59 +00:00
Tiago Cunha
1297c39a31 Sync OpenBSD patchset 233:
Don't leak in the (rare) case of an invalid command at the end of a file not
terminated by a \n.
2009-08-09 17:53:50 +00:00
Tiago Cunha
4c944910fa Sync OpenBSD patchset 232:
Use a temporary variable for strdup of const char *.
2009-08-09 17:52:54 +00:00
Tiago Cunha
deac1fc188 Update. 2009-08-09 17:51:19 +00:00
Tiago Cunha
29b1b2fb5e Sync OpenBSD patchset 231:
Infrastructure and commands to manage the environment for processes started
within tmux.

There is a global environment, copied from the external environment when the
server is started and each session has an (initially empty) session
environment which overrides it.

New commands set-environment and show-environment manipulate or display the
environments.

A new session option, update-environment, is a space-separated list of
variables which are updated from the external environment into the session
environment every time a new session is created - the default is DISPLAY.
2009-08-09 17:48:55 +00:00
Tiago Cunha
af3db9a4fe Sync OpenBSD patchset 230:
Tidy function a little by using a temporary variable.
2009-08-09 17:43:00 +00:00
Tiago Cunha
a26817d604 Update. 2009-08-09 17:41:46 +00:00
Tiago Cunha
167a8c9edc Sync OpenBSD patchset 229:
Options to set the colours and attributes for status-left/-right. From Thomas
Adam, thanks.
2009-08-09 17:40:17 +00:00
Tiago Cunha
97eb537f38 Sync OpenBSD patchset 227:
Add a flags member to the grid_line struct and use it to differentiate lines
wrapped at the screen edge from those terminated by a newline. Then use this
when copying to combine wrapped lines together into one.
2009-08-09 17:32:06 +00:00
Tiago Cunha
37b0bcd7c1 Sync OpenBSD patchset 226:
Change the way the grid is stored, previously it was:

- a two-dimensional array of cells;
- a two-dimensional array of utf8 data;
- an array of line lengths.

Now it is a single array of a new struct grid_line each of which represents a
line and contains the length and an array of cells and an array of utf8 data.

This will make it easier to add additional per-line members, such as flags.
2009-08-09 17:28:24 +00:00
Tiago Cunha
5b56ea1816 Sync OpenBSD patchset 225:
If there is an error in the configuration file, don't just exit(1) as this can
cause the client to hang. Instead, send the error message, then mark the client
as bad and start a normal shutdown so the server exits once the error is
written.

This also allows some code duplicating daemon(3) to be trimmed and logging to
begin earlier.

Prompted by Theo noticing the behaviour on error wasn't documented.
2009-08-09 17:19:18 +00:00
Tiago Cunha
602aae7839 Sync OpenBSD patchset 224:
Move introduction section up into description. From jmc.
2009-08-09 16:59:35 +00:00
Tiago Cunha
05eb4ece44 Sync OpenBSD patchset 223:
Using the alternative screen (smcup/rmcup) should also preserve the current
colours and attributes. Found thanks to a report from Taylor Venable.

While here also nuke a couple of extra blank lines.
2009-08-09 16:57:49 +00:00
Tiago Cunha
5840c3e13a Sync OpenBSD patchset 222:
tweak INTRODUCTION; from nicm and myself (jmc)
2009-08-09 16:54:46 +00:00
Tiago Cunha
cd5294dfb4 Sync OpenBSD patchset 221:
Clear the codes array earlier as tty_term_free could be called on error.
2009-08-09 16:52:06 +00:00
Tiago Cunha
88b83be07b Sync OpenBSD patchset 220:
If colours are not supported by the terminal, try to emulate a coloured
background by setting or clearing the reverse attribute.

This makes a few applications which don't use the reverse attribute themselves
a little happier, and allows the status, message and mode options to have
default attributes and fg/bg options that work as expected when set as reverse.
2009-08-09 16:50:57 +00:00
Tiago Cunha
65a28912eb Sync OpenBSD patchset 219:
Add a -a flag to set-option and set-window-option to append to an existing
string value, useful for terminal-overrides.
2009-08-09 16:48:34 +00:00
Tiago Cunha
d8a2ceea43 Sync OpenBSD patchset 217:
Show the bell/activity/current status and the window title in the choice list.
2009-08-09 16:41:17 +00:00
Tiago Cunha
c32ca6a8e6 Sync OpenBSD patchset 216:
Check for "UTF8" as well as "UTF-8" in LANG etc as it seems this may also
appear.
2009-08-09 16:39:40 +00:00
Tiago Cunha
c9f55c1063 Make similar (untested) changes to the OS-dependent code for FreeBSD, and
NetBSD in accordance to OpenBSD patchset 214.
2009-08-09 16:37:05 +00:00
Tiago Cunha
1127a290f4 Sync OpenBSD patchset 214:
Split the comparison into a function to make this code smaller and more
understandable.
2009-08-09 16:08:12 +00:00
Tiago Cunha
bd5cf2e809 Update. 2009-08-09 15:58:09 +00:00
Tiago Cunha
9002e60adf Sync OpenBSD patchset 213:
Don't try to free old string values (and crash) when they are overridden unless
they were actually found in the source terminal description. Reported by jmc.
2009-08-09 15:57:13 +00:00
Tiago Cunha
bd2fe4ce9b Make it build on the remaining operating systems, due to the changes
introduced on OpenBSD patchset 211.
2009-08-09 15:53:02 +00:00
Tiago Cunha
e6d5633671 DragonFlyBSD, FreeBSD, and NetBSD do not need vis.c. 2009-08-09 15:48:03 +00:00
Tiago Cunha
e098f7b285 Add unvis(3) compat stuff. 2009-08-09 15:39:41 +00:00
Tiago Cunha
3deb17e841 Do not include vis.h directly, since it's OS-dependent. 2009-08-09 15:29:54 +00:00
Tiago Cunha
15f6a41a75 Sync OpenBSD patchset 211:
Add a terminal-overrides session option allowing individual terminfo(5) entries
to be overridden. The 88col/256col checks are now moved into the default
setting and out of the code.

Also remove a couple of old workarounds for xterm and rxvt which are no longer
necessary (tmux can emulate them if missing).
2009-08-09 15:26:24 +00:00
Tiago Cunha
75b6736cf4 Sync OpenBSD patchset 210:
Fix checking of setupterm(3) error codes. While there include the
name of the terminal type causing the error where relevant. ok nicm@.
2009-08-09 12:06:25 +00:00
Nicholas Marriott
80196c9abc Fix typo and add ref to infocmp. 2009-08-08 20:46:26 +00:00
Nicholas Marriott
becdf220fd Clarify 256 colours entries from Chris Jones, tweaked by me. 2009-08-08 20:42:42 +00:00
Nicholas Marriott
dcde77cd09 Update. 2009-08-08 16:03:09 +00:00
Nicholas Marriott
f03dd8d216 This file is not kept up to date and too many people are using it as-is then
finding tmux key bindings missing. Trim it down and make it clear this is an
example only.
2009-08-07 12:09:50 +00:00
Nicholas Marriott
a5d55ba16d Sync up tmux.1 from OpenBSD. 2009-08-06 19:25:44 +00:00
Nicholas Marriott
2936f4f32c tmux no longers sends init strings so this is no longer relevant. 2009-08-06 12:22:50 +00:00
Nicholas Marriott
e2686d8819 +IRC channel. 2009-08-05 16:39:28 +00:00
Nicholas Marriott
b2606c0421 Correct usage of termcap. 2009-08-05 16:29:50 +00:00
Nicholas Marriott
e3e0d70c0e +PuTTY ACS from Mike Putnam. 2009-08-05 14:56:58 +00:00
Nicholas Marriott
f42a0475e4 Tweak FAQ to mention default-terminal. 2009-08-05 14:42:08 +00:00
Tiago Cunha
a834d037bc Sync OpenBSD patchset 209:
Pass the ACS border characters through tty_get_acs so they appear correctly on
terminals which don't use the standard set.
2009-07-31 20:35:21 +00:00
Tiago Cunha
cccd072ed1 Sync OpenBSD patchset 208:
Don't leak when rollling buffers off when the paste buffer limit is reached.
2009-07-31 20:33:49 +00:00
Nicholas Marriott
5f0e688b50 Add some lines. 2009-07-31 10:58:51 +00:00
Nicholas Marriott
ec8930c144 Part of last commit, remove -lcurses. 2009-07-31 10:45:22 +00:00
Nicholas Marriott
3e46bcec93 On SUSE Linux compatibility is something that only happens to other people, so
on Linux use -lncurses instead of -lcurses.

Also use -lncurses on NetBSD because they are only now realising that
supporting the 20-year-old terminfo API in their libcurses might be nice, and
so far none of the releases do.
2009-07-31 10:44:03 +00:00
Nicholas Marriott
5d13704e04 Some Linuxes/gcc versions hide LLONG_MAX/MIN unless the compiler is told to use
C99, so use -std=c99 on Linux.
2009-07-31 10:30:40 +00:00
Nicholas Marriott
52f8578984 Some stuff that is done. 2009-07-30 21:55:16 +00:00
Tiago Cunha
09c6432854 Sync OpenBSD patchset 207:
Plug some memory leaks.
2009-07-30 21:14:04 +00:00
Tiago Cunha
796bfbd7af Update. 2009-07-30 21:11:10 +00:00
Tiago Cunha
56dd5dfff4 Sync OpenBSD patchset 206:
Don't babysit people and let them try to load /dev/zero or (more useful)
/dev/null if they want.
2009-07-30 21:07:23 +00:00
Tiago Cunha
3eb77bf53f Sync OpenBSD patchset 205:
Remove some dead code found by clang.
2009-07-30 21:04:40 +00:00
Tiago Cunha
89826983eb Sync OpenBSD patchset 204:
tweak previous;
2009-07-30 21:02:35 +00:00
Tiago Cunha
697051d1fd Sync OpenBSD patchset 203:
Similar changes for server_msg_dispatch: use a switch instead of a lookup
table and merge smaller functions inline.
2009-07-30 21:01:01 +00:00
Tiago Cunha
67266dc25c Sync OpenBSD patchset 202:
There aren't many client message types or code to handle them so get rid of
the lookup table and use a switch, merge the tiny handler functions into it,
and move the whole lot to client.c.

Also change client_msg_dispatch to consume as many messages as possible and
move the call to it to the right place so it checks for signals afterwards.

Prompted by suggestions from eric@.
2009-07-30 20:57:39 +00:00
Tiago Cunha
817e93ac94 Sync OpenBSD patchset 201:
Tell the server when the client gets SIGTERM so it can clean up the terminal
properly, rather than just exiting.
2009-07-30 20:50:10 +00:00
Tiago Cunha
1650b8552f Sync OpenBSD patchset 200:
Merge pane number into the target specification for pane commands. Instead of
using -p index, a target pane is now addressed with the normal -t window form
but suffixed with a period and a pane index, for example :0.2 or
mysess:mywin.1. An unadorned number such as -t 1 is tried as a pane index in
the current window, if that fails the same rules are followed as for a target
window and the current pane in that window used.

As a side-effect this now means that swap-pane can swap panes between
different windows.

Note that this changes the syntax of the break-pane, clear-history, kill-pane,
resize-pane, select-pane and swap-pane commands.
2009-07-30 20:45:20 +00:00
Tiago Cunha
ec1396c9ee Sync OpenBSD patchset 199:
new sentence, new line;
2009-07-30 20:33:29 +00:00
Tiago Cunha
ec3dba01b2 Sync OpenBSD patchset 198:
Add a mode-mouse option to prevent tmux taking over the mouse in choice or
copy modes.
2009-07-30 20:32:05 +00:00
Tiago Cunha
8ce1f0b047 Sync OpenBSD patchset 197:
Add an additional heuristic to work out the current session when run from the
command line. The name of all slave ptys in the server is known, so if the
client was run on a tty, look for any sessions containing that tty and use the
most recently created.

This is more reliable than looking at $TMUX if windows have been moved or
linked between sessions.
2009-07-30 20:26:20 +00:00
Tiago Cunha
6fbfcfc0d7 Sync OpenBSD patchset 196:
Rename struct hdrtype to msgtype which is a better name and can be used even
when struct hdr disappears.
2009-07-30 20:21:55 +00:00
Tiago Cunha
5a9b7b230c Sync OpenBSD patchset 195:
Taking account of the "s, 22 not 24 is the maximum length of #T in
status-right to prevent the date being cut off.
2009-07-30 20:17:25 +00:00
Tiago Cunha
522fc94d12 Sync OpenBSD patchset 194:
Final pieces of mode key rebinding: bind-key and unbind-key now accept a -t
argument to modify a table.
2009-07-28 23:19:06 +00:00
Tiago Cunha
deaba44835 Sync OpenBSD patchset 193:
Accept and print "Enter" and "Escape" for keys rather than C-m and C-[.
2009-07-28 23:13:00 +00:00
Tiago Cunha
de7483a114 Sync OpenBSD patchset 192:
Next step towards customisable mode keys: build each default table of keys
into a named tree on start and use that for lookups. Also add command to string
translation tables and modify list-keys to show the mode key bindings (new
-t argument).
2009-07-28 23:11:18 +00:00
Tiago Cunha
d9dcc5ed44 Sync OpenBSD patchset 191:
If select-layout is not given an argument, reapply the last layout used in the
window, if any.
2009-07-28 23:04:29 +00:00
Tiago Cunha
1c73e75982 Sync OpenBSD patchset 190:
Remove an unused entry in the mode keys command enum and rename
MODEKEYCOPY_QUIT to _CANCEL to match the others.
2009-07-28 22:58:20 +00:00
Tiago Cunha
920b9c5872 Sync OpenBSD patchset 189:
Change mode key bindings from big switches into a set of tables. Rather than
lumping them all together, split editing keys from those used in choice/more
mode and those for copy/scroll mode.

Tidier and clearer, and the first step towards customisable mode keys.
2009-07-28 22:55:59 +00:00
Tiago Cunha
1880b83c37 Sync OpenBSD patchset 188:
Get rid of empty mode_key_free function.
2009-07-28 22:49:26 +00:00
Tiago Cunha
46cb0de347 Sync OpenBSD patchset 187:
Add a key to delete to end of line at the prompt (^K in emacs mode, C/D in
vi).

From Kalle Olavi Niemitalo.
2009-07-28 22:44:38 +00:00
Tiago Cunha
7562781c9d Sync OpenBSD patchset 186:
Draw UTF-8 characters under the selection correctly.
2009-07-28 22:41:38 +00:00
Tiago Cunha
2a146852ef Sync OpenBSD patchset 185:
Change previous-word behavior to move to the beginning of the word (matches
emacs and vi). From Kalle Olavi Niemitalo.
2009-07-28 22:39:29 +00:00
Tiago Cunha
361801aaaa Sync OpenBSD patchset 184:
Detect backspace by looking at termios VERASE and translate it into \177
(which matches screen's behaviour if not its termcap/terminfo entry). The
terminfo kbs cap is often wrong or missing so it can't be used, and just
assuming \177 may be wrong.
2009-07-28 22:37:02 +00:00
Tiago Cunha
2aa4d47312 Sync OpenBSD patchset 183:
Calculate the space available for the prompt buffer and the cursor position
correctly, and make it work when the screen is not wide enough.

Noticed by Kalle Olavi Niemitalo.
2009-07-28 22:32:15 +00:00
Tiago Cunha
2dda197980 Make similar changes to the OS-dependent code for FreeBSD, and NetBSD in
accordance to OpenBSD patchset 182.
2009-07-28 22:28:11 +00:00
Tiago Cunha
6043d9cf89 Sync OpenBSD patchset 182:
Go to the next if the current best process is replaced, don't keep comparing
it with itself. Also fix process name comparison.
2009-07-28 22:26:13 +00:00
Tiago Cunha
a3fc9dee32 Add PASS_MAX for glibc. 2009-07-28 22:17:10 +00:00
Tiago Cunha
d637cb33da Sync OpenBSD patchset 181:
Make all messages sent between the client and server fixed size.

This is the first of two changes to make the protocol more resilient and less
sensitive to other changes in the code, particularly with commands. The client
now packs argv into a buffer and sends it to the server for parsing, rather
than doing it itself and sending the parsed command data.

As a side-effect this also removes a lot of now-unused command marshalling
code.

Mixing a server without this change and a client with or vice versa will cause
tmux to hang or crash, please ensure that tmux is entirely killed before
upgrading.
2009-07-28 22:12:16 +00:00
Nicholas Marriott
f5c0695605 This stuff is done. 2009-07-28 18:51:10 +00:00
Nicholas Marriott
21130b0c49 Add a couple of items, and wrap lines. 2009-07-26 15:58:40 +00:00
Tiago Cunha
a5ad186547 Sync OpenBSD patchset 180:
Set the active pane when respawning a window - fixes problems when respawning
a window with multiple panes.
2009-07-25 09:04:54 +00:00
Tiago Cunha
5e7a48a865 Sync OpenBSD patchset 179:
Use the full range of ACS line drawing characters to draw pane borders,
including intersections.
2009-07-25 09:03:33 +00:00
Tiago Cunha
2386fa2355 Sync OpenBSD patchset 178:
cmd_find_index should return -2 on error.
2009-07-25 08:59:38 +00:00
Tiago Cunha
723f363c07 Sync OpenBSD patchset 177:
Simplify screen redrawing by drawing the border and background together rather
than border separately, and consolidating all the drawing characters into one
string.
2009-07-25 08:58:19 +00:00
Tiago Cunha
a98dbb67b9 Sync OpenBSD patchset 176:
Accept lowercase c- and m- prefix as well as C- and M-.
2009-07-25 08:53:48 +00:00
Tiago Cunha
28cf7dc39e Sync OpenBSD patchset 175:
Permit commands to be bound to key presses without the prefix key first. The
new -n flag to bind-key and unbind-key sets or removes these bindings, and
list-key shows them in []s.
2009-07-25 08:52:04 +00:00
Tiago Cunha
744ccb7cc9 Sync OpenBSD patchset 174:
up-pane and down-pane no longer auto-repeat; update the description of
repeat-time accordingly. ok nicm@

if you prefer old behaviour;

bind -r Up up-pane
bind -r Down down-pane
2009-07-25 08:39:39 +00:00
Nicholas Marriott
db584544f4 Add some more bits. 2009-07-25 00:12:24 +00:00
Nicholas Marriott
f4718dcdf2 +another couple of items. 2009-07-25 00:00:33 +00:00
Nicholas Marriott
4ec1b5d4e2 +. 2009-07-24 22:59:06 +00:00
Nicholas Marriott
6e0626d3af Screenshot with more ACS love. 2009-07-24 19:30:51 +00:00
Nicholas Marriott
dd51dd14af Add. 2009-07-24 19:30:05 +00:00
Tiago Cunha
7cd412dc57 Sync OpenBSD patchset 173:
None of the server message functions return anything but 0, so make them all
void.

Also remove a leftover variable in client.c.
2009-07-23 23:47:23 +00:00
Tiago Cunha
1870b96578 Sync OpenBSD patchset 172:
Tidy client message return slightly: convert flags into an enum, and merge
error string into struct client_ctx as well.
2009-07-23 23:42:59 +00:00
Tiago Cunha
2e4df706f6 Sync OpenBSD patchset 171:
Redraw after starting selection to correctly remove any existing selection.
2009-07-23 23:37:14 +00:00
Tiago Cunha
1141acfd4c Revert previous per OpenBSD's patchset 170. 2009-07-23 23:35:10 +00:00
Tiago Cunha
53c1b32e02 Sync OpenBSD patchset 169:
C-d is delete as well in emacs mode.
2009-07-23 23:29:53 +00:00
Tiago Cunha
f2451c1e29 Sync OpenBSD patchset 168:
Both of cmdclient and curclient CAN be NULL - if the command is executed from
the configuration file. In this case, attach-session can't do much, and
new-session should just assume -d.
2009-07-23 13:25:27 +00:00
Tiago Cunha
a551ff2b1b Sync OpenBSD patchset 167:
If there is a current session, use its default path and working directory for
the initial window when creating a new session.
2009-07-23 13:19:12 +00:00
Tiago Cunha
7174c76bf0 Sync OpenBSD patchset 166:
Pass a set of flags into client_init rather than just a start_server
variable. Only one flag now but more to come later.
2009-07-23 13:15:41 +00:00
Tiago Cunha
6708ad19c5 Sync OpenBSD patchset 165:
window_add_pane cannot fail, so remove the unused cause argument and don't
bother to check for a NULL return.
2009-07-23 13:10:38 +00:00
Tiago Cunha
fb0301f8b8 Sync OpenBSD patchset 164:
Tidy the target parsing code a bit and correct the behaviour so that as before
a string with no colon as a target window is first looked up as a window then
as a session, noted by Iain Morgan.

Also attempt to clarify the description of the target specification in the man
page.
2009-07-23 13:06:31 +00:00
Tiago Cunha
c84145751a Sync OpenBSD patchset 164:
tty_write is relatively short and the only function left in tty-write.c so
move it into tty.c.
2009-07-23 12:57:45 +00:00
Tiago Cunha
b72f9bea43 Sync OpenBSD patchset 162:
More tty code tidying: move the saved cursor/region position (from before the
screen was updated) out of struct screen and into struct tty_ctx.
2009-07-23 12:48:18 +00:00
Tiago Cunha
9c6fa90857 Sync OpenBSD patchset 160:
enum tty_cmd is only used as an index into the array of command function
pointers, so remove it and use the function pointers directly to represent
themselves.
2009-07-23 12:38:01 +00:00
Nicholas Marriott
83d1f2b480 Some more TODO list items that are done. 2009-07-22 21:10:45 +00:00
Nicholas Marriott
19aae6dbd8 Add a couple of notes so I don't forget. 2009-07-22 21:02:07 +00:00
Tiago Cunha
aa3a262caa Update. 2009-07-22 20:42:56 +00:00
Tiago Cunha
b6afa30c39 Sync OpenBSD patchset 159:
There are relatively few arguments to tty_cmd_* functions now, so tidy them up
by using a struct rather than hiding everything with varargs.
2009-07-22 18:08:56 +00:00
Tiago Cunha
75a44d856e Sync OpenBSD patchset 158:
tty_cmd_raw is only used once, for raw UTF-8 output, so rename it to
tty_cmd_utf8character and eliminate the size argument.
2009-07-22 17:58:42 +00:00
Tiago Cunha
41207e4861 Sync OpenBSD patchset 157:
Adjust field width to fit longest key when listing.
2009-07-22 17:53:27 +00:00
Tiago Cunha
acdef09e00 Sync OpenBSD patchset 156:
Remove leftover debug logging of password.
2009-07-22 17:49:09 +00:00
Tiago Cunha
d29b57f597 Sync OpenBSD patchset 155:
Make some functions which return unused values void (mostly found by lint) and
tweak a redundant expression in window_pane_set_mode.
2009-07-22 17:46:53 +00:00
Tiago Cunha
0237e1dafd Sync OpenBSD patchset 154:
Nix a few unused attributes on arguments which are no longer unused.
2009-07-22 17:38:11 +00:00
Tiago Cunha
a92993228f Change GRID_DEBUG to use log_debug2 since log_debug3 was removed. 2009-07-22 17:33:02 +00:00
Tiago Cunha
6a97901691 Sync OpenBSD patchset 153:
Remove a couple of unused functions and fix a type ("FALLTHOUGH"), found by
lint.
2009-07-22 17:31:20 +00:00
Tiago Cunha
39aa8b32b1 Restore $Id$. 2009-07-22 16:55:22 +00:00
Tiago Cunha
1bf524c1b7 Sync OpenBSD patchset 152:
__progname is not const, pointed out by deraadt.

And, as a consequence change its declaration for operating systems which
don't provide __progname as well.
2009-07-22 16:53:30 +00:00
Tiago Cunha
a734488a4b Sync OpenBSD patchset 151:
Tidy up keys: use an enum for the key codes, and remove the macros which just
wrap flag sets/clears/tests.
2009-07-22 16:24:59 +00:00
Nicholas Marriott
94e2339842 OpenSolaris ioctl(TIOCSWINSZ) appears to be broken and can return EINVAL here
despite sx, sy and fd being fine (an fcntl on the fd succeeds). No problems on
other platforms so ignore the error under #ifdef __sun__.
2009-07-22 12:42:57 +00:00
Tiago Cunha
5263b3f61e Sync OpenBSD patchset 150:
Now that #P could be in the status line, flag it for redraw when the active
pane changes.
2009-07-21 16:27:41 +00:00
Nicholas Marriott
962b9c6548 Include .depend in GNUmakefile since GNU make does not include it
automatically.

Also remove .depend from clean target and add a clean-depend target.
2009-07-21 13:51:30 +00:00
Nicholas Marriott
48c36d628a No paths.h in cmd.c; add _PATH_DEV for Solaris. 2009-07-21 13:07:50 +00:00
Nicholas Marriott
e2a80151ae Update. 2009-07-21 13:07:14 +00:00
Tiago Cunha
2572c7139b Sync OpenBSD patchset 149:
Tweak unbind-key language very slightly.
2009-07-20 17:08:48 +00:00
Tiago Cunha
e7cda4f363 Update. 2009-07-20 17:06:13 +00:00
Tiago Cunha
54c6848d75 Sync OpenBSD patchset 148:
Display the number of failed password attempts (if any) when the server is
locked. From Tom Doherty.
2009-07-20 16:07:23 +00:00
Tiago Cunha
9a07e8f372 Sync OpenBSD patchset 147:
Add a status-justify option to allow the window list in the status line to be
positioned at the left, centre, or right.
2009-07-20 16:01:07 +00:00
Tiago Cunha
e8957009c7 Sync OpenBSD patchset 146:
New options, window-status-current-{fg,bg,attr}, to set the fg, bg and
attributes with which the current window is shown in the status line. From
Johan Friis, thanks.
2009-07-20 15:57:05 +00:00
Tiago Cunha
62017452e9 Sync OpenBSD patchset 145:
Kill some dead stores and fix a null pointer deref, found by clang.
2009-07-20 15:51:32 +00:00
Tiago Cunha
16f424d25d Sync OpenBSD patchset 144:
Move the offsets as well when swapping panes.
2009-07-20 15:48:54 +00:00
Tiago Cunha
95d593dd51 Sync OpenBSD patchset 143:
tweak previous;
2009-07-20 15:46:55 +00:00
Tiago Cunha
545893df73 Sync OpenBSD patchset 142:
Each window now has a tree of layout cells associated with it. In this tree,
each node is either a horizontal or vertical cell containing a list of other
cells running from left-to-right or top-to-bottom, or a leaf cell which is
associated with a pane.

The major functional changes are:

- panes may now be split arbitrarily both horizontally (splitw -h, C-b %) and
  vertically (splitw -v, C-b ");
- panes may be resized both horizontally and vertically (resizep -L/-R/-U/-D,
  bound to C-b left/right/up/down and C-b M-left/right/up/down);
- layouts are now applied and then may be modified by resizing or splitting
  panes, rather than being fixed and reapplied when the window is resized or
  panes are added;
- manual-vertical layout is no longer necessary, and active-only layout is gone
  (but may return in future);
- the main-pane layouts now reduce the size of the main pane to fit all panes
  if possible.

Thanks to all who tested.
2009-07-20 15:42:05 +00:00
Nicholas Marriott
680f2098f1 With gcc4, turn off unnecessart pointer sign warnings. 2009-07-20 05:40:13 +00:00
Tiago Cunha
376c808b50 Add three new session options: visual-activity, visual-bell, visual-content.
If these are enabled (and the monitor-activity, bell-action and monitor-content
options are configurated appropriately), when activity, a bell, or content is
detected, a message is shown.

Also tidy up the bell/activity/content code in server.c slightly and fix a
couple of errors.
2009-07-19 14:35:56 +00:00
Nicholas Marriott
4cf6396e4c Change a couple of screenshots which had screen in them now I've got rid of
screen on that box too :-).
2009-07-19 13:52:51 +00:00
Tiago Cunha
17170f5d6e Add a -k flag to unlink-window which makes it behave the same as the old
kill-window - if a window is linked into only one session it unlinked and
destroyed.
2009-07-19 00:39:37 +00:00
Nicholas Marriott
19cb1fb592 Make it so using kill-pane to destroy the last pane in a window destroys the
window instead of being an error.
2009-07-18 11:07:14 +00:00
Nicholas Marriott
c30fbd1d8d When resizing a screen smaller in alternate screen mode, all the lines needed
could be consumed by deleting from the bottom, leaving none to be removed from
the top. In this case, don't call grid_view_delete_lines with ny of 0 as this
is incorrect and causes a bounds check to fatal error if built with -DDEBUG.
2009-07-18 11:06:35 +00:00
Nicholas Marriott
6bc9ee3420 Tidy up new-session and attach-session and change them to work from inside
tmux, switching the current client to the new or requested session.
2009-07-18 11:06:09 +00:00
Nicholas Marriott
4192449112 Remove a duplicate key binding, and turn off autorepeat for up/down as it is
kind of annoying by default.
2009-07-18 11:05:45 +00:00
Nicholas Marriott
f1efd6b4e7 If -u is specified or UTF-8 is otherwise detected when the server is started,
enable the utf8 and status-utf8 optons. While here, note in the man page that
the server is started with the first session and exits when none remain.
2009-07-18 11:05:13 +00:00
Nicholas Marriott
21cfef45d6 When resizing a screen smaller in alternate screen mode, all the lines needed
could be consumed by deleting from the bottom, leaving none to be removed from
the top. In this case, don't call grid_view_delete_lines with ny of 0 as this
is incorrect and causes a bounds check to fatal error if built with -DDEBUG.
2009-07-17 18:35:55 +00:00
Tiago Cunha
ae7dda10ce - New command display-message (alias display) to display a message in the
status line (bound to "i" by default).
- Add support for including the window index, pane index, and window name
  in status-left, or status-right.
- Bump protocol version.
2009-07-17 18:32:54 +00:00
Nicholas Marriott
646632de1d Update TODO. 2009-07-17 18:05:06 +00:00
Nicholas Marriott
770ea563ee Changed the wrong thing here. 2009-07-17 15:56:46 +00:00
Nicholas Marriott
946affe60d Stupid cvsps. 2009-07-17 12:35:01 +00:00
Nicholas Marriott
89543e999d A similar for fix for window_choose: don't rely on the callback always being
called to free data, have a separate free callback and call it from the mode
cleanup code.
2009-07-17 12:12:54 +00:00
Nicholas Marriott
fc17ce0150 Oops, it is always a good idea to get arguments the right way round. 2009-07-17 09:28:27 +00:00
Nicholas Marriott
441c118b63 Memory could be leaked if a second prompt or message appeared while another was
still present, so add a separate prompt free callback and make the _clear
function responsible for calling it if necessary (rather than the individual
2009-07-17 09:26:21 +00:00
Nicholas Marriott
ac55534055 Remove some duplicate code that was causing the status line to be redrawn even
when it hadn't changed.
2009-07-17 07:46:08 +00:00
Nicholas Marriott
821de39b27 Fix arguments to switch-client. 2009-07-17 07:45:42 +00:00
Nicholas Marriott
ede2dd2d3a Typo in grid_duplicate_lines (sy for dy) causing it to write into the wrong
place when copying UTF-8 data. Found by Dan Colish.
2009-07-17 07:45:08 +00:00
Nicholas Marriott
08d32a1522 Update TODO. 2009-07-16 07:35:41 +00:00
Nicholas Marriott
d956ed0760 Typo in grid_duplicate_lines (sy for dy) causing it to write into the wrong
place when copying UTF-8 data. Found by Dan Colish.
2009-07-16 07:35:35 +00:00
Nicholas Marriott
6fe25a08d7 Improved NetBSD current-process detection from Roy Marples. 2009-07-15 17:53:15 +00:00
Nicholas Marriott
222b8e6743 Make status_message_set a variadic printf-like function. No functional change -
helpful for a couple of things coming soon.
2009-07-15 17:50:11 +00:00
Nicholas Marriott
d6908dd9c2 Return -1 not NULL on error, pointed out by Roy Marples. 2009-07-15 17:46:09 +00:00
Nicholas Marriott
ac2ab6501d Add a -k flag to unlink-window which makes it behave the same as the old
kill-window - if a window is linked into only one session it unlinked and
destroyed.
2009-07-15 17:45:29 +00:00
Nicholas Marriott
8bfbc8c61d The man page says that kill-window removes the window entirely, unlinking it
from any sessions. In fact the implementation only affected the current
session, making it the same as unlink-window but destroying the window if it
was linked into only one session (unlinkw gives an error). Change the behaviour
to match what it documented and was originally intended.
2009-07-15 17:45:09 +00:00
Nicholas Marriott
ff90170738 Having to update NSETOPTION/NSETWINDOWOPTION when adding new options is a bit
annoying and it is only use for iterating, so use a sentinel to mark the end of
each array instead. Different fix for a problem pointed out by Kalle Olavi
Niemitalo.
2009-07-15 17:44:47 +00:00
Nicholas Marriott
6ebb1df8fe Add main-pane-height to the options list (was missed before). 2009-07-15 17:44:25 +00:00
Nicholas Marriott
ff500b46c9 For some reason when clearing status/message it was redrawing the entire client
not just the status line. Changing this also revealed the check for the status
line was incorrect when drawing the pane.
2009-07-15 17:44:06 +00:00
Nicholas Marriott
72d56bd614 Instead of faking up a status line in status_redraw, use the same code to
redraw it as to draw the entire screen, just skip all lines but the last.
2009-07-15 17:43:45 +00:00
Nicholas Marriott
ad1945c278 Don't accept input to a window if it not visible. 2009-07-15 17:43:21 +00:00
Nicholas Marriott
82b45b460e The scroll region cannot be one line only, ignore attempts to make it so. 2009-07-15 17:43:02 +00:00
Nicholas Marriott
1e574bb70c Get rid of the PANE_HIDDEN flag in favour of a function, and moving the
decision for whether or not a pane should be drawn out of the layout code and
into the redraw code.

This is needed for the new layout design, getting it in now to make that easier
to work on.
2009-07-15 17:42:44 +00:00
Nicholas Marriott
537c32b6b6 Escape ~, pointed out by tcunha. 2009-07-14 17:44:24 +00:00
Nicholas Marriott
f44ae0535e Need time.h not sys/time.h for time(2). 2009-07-14 07:01:03 +00:00
Nicholas Marriott
910d6282c4 Whoops, chose the wrong one in a conflict. Revert. 2009-07-14 06:54:38 +00:00
Nicholas Marriott
20e322bf9b arg.c is no longer required. 2009-07-14 06:47:46 +00:00
Nicholas Marriott
edd3142d1f Don't need ncurses, use curses. 2009-07-14 06:47:12 +00:00
Nicholas Marriott
097b96ea44 Having fixed flags for single-character getopt options is a bit hard to
maintain and is only going to get worse as more are used. So instead, add a new
uint64_t member to cmd_entry which is a bitmask of upper and lowercase options
accepted by the command.

This means new single character options can be used without the need to add it
explicitly to the list.
2009-07-14 06:43:33 +00:00
Nicholas Marriott
5ccd0025a0 copy-mode and scroll-mode have a -u flag missing from usage, add it. 2009-07-14 06:42:22 +00:00
Nicholas Marriott
d358a352c0 Tidy up and improve target (-t) argument parsing:
- move the code back into cmd.c and merge with the existing functions where
  possible;
- accept "-tttyp0" as well as "-t/dev/ttyp0" for clients;
- when looking up session names, try an exact match first, and if that fails
  look for it as an fnmatch pattern and then as the start of a name - if more
  that one session matches an error is given; so if there is one session called
  "mysession", -tmysession, -tmysess, -tmysess* are equivalent but if there
  is also "mysession2", the last two are errors;
- similarly for windows, if the argument is not a valid index or exact window
  name match, try it against the window names as an fnmatch pattern and a
  prefix.
2009-07-14 06:42:06 +00:00
Nicholas Marriott
e63567d51c Support "alternate screen" mode (terminfo smcup/rmcup) typically used by full
screen interactive programs to preserve the screen contents. When activated, it
saves a copy of the visible grid and disables scrolling into and resizing out
of the history; when deactivated the visible data is restored and the history
reenabled.
2009-07-14 06:40:33 +00:00
Nicholas Marriott
f41ef2198b Missed this declaration in key bindings change. Whoops. 2009-07-14 06:40:03 +00:00
Nicholas Marriott
61bd3ae1c6 Document the -k flag to new-window. 2009-07-14 06:39:44 +00:00
Nicholas Marriott
5ef5bd7c31 Add a "back to indentation" key in copy mode to move the cursor to the first
non-whitespace character. ^ with vi and M-m with emacs key bindings. Another
from Kalle Olavi Niemitalo, thanks.
2009-07-14 06:39:25 +00:00
Nicholas Marriott
7f98193beb Merge three copies of identical code to move the cursor x position into a
single function, from Kalle Olavi Niemitalo.
2009-07-14 06:38:32 +00:00
Nicholas Marriott
d2c3dbc665 If it exist, load a system-wide configuration file /etc/tmux.conf before any
user-specified one.
2009-07-14 06:38:14 +00:00
Tiago Cunha
2f75b07d08 Update. 2009-07-13 18:29:28 +00:00
Tiago Cunha
280619a4e8 Expand leading tilde on commands which expect a filename. 2009-07-13 18:03:18 +00:00
Nicholas Marriott
6db6df882c Update. 2009-07-13 11:33:06 +00:00
Nicholas Marriott
db411ca515 Update TODO. 2009-07-13 06:29:19 +00:00
Nicholas Marriott
3fb3613d34 Limit the history to hlimit not hlimit - 1. This makes a history-limit setting
of 0 work as expected.
2009-07-12 17:12:41 +00:00
Nicholas Marriott
30f47dfc5e Add -r to the synopsis of the paste-buffer command, prompted by jmc. 2009-07-12 17:12:06 +00:00
Nicholas Marriott
27fc963631 When pasting, translate \n into \r. This matches xterm and putty's behaviour,
and makes emacs happy when pasting into some modes. A new -r (raw) flag to
paste-buffer pastes without the translation.

From Kalle Olavi Niemitalo, thanks!
2009-07-12 17:11:39 +00:00
Nicholas Marriott
d8de72ca77 Copy was using the real line length which after resize can be larger than the
screen width. When built with -DDEBUG, this made the grid bounds checking code
kill the server. Restrict copying to the actual width.

From Kalle Olavi Niemitalo, thanks.
2009-07-12 17:11:07 +00:00
Nicholas Marriott
ef5f356da2 paste-buffer -d was not documented. From Kalle Olavi Niemitalo. 2009-07-12 17:10:35 +00:00
Nicholas Marriott
1919deab1f Redraw the status line after renaming a session (it may contain the name). 2009-07-12 17:09:15 +00:00
Nicholas Marriott
fd0971542f Don't send initialisation strings is1/2/3 (barely anything else does) and move
smcup to the first and rmcup to the last sequences output to the terminal. This
allows tmux to use the alternate screen (smcup/rmcup) when available.
2009-07-12 17:08:37 +00:00
Nicholas Marriott
d7b4aa0ff3 Add a default-terminal option to set the starting value of $TERM in new
windows.
2009-07-12 17:07:58 +00:00
Nicholas Marriott
79bc6041c9 Document display-time option which seems to have been missed. 2009-07-12 17:04:21 +00:00
Nicholas Marriott
8be8016a76 When the terminal size is reduced horizontally, don't truncate lines to the new
width, so that if the same lines are later increased in size the content
reappears.
2009-07-12 17:03:11 +00:00
Nicholas Marriott
d4a143a425 Stop in the right place so all the lines selected are copied. Reported by Kalle
Olavi Niemitalo, thanks.
2009-07-12 16:56:56 +00:00
Nicholas Marriott
bf0f56d04e Update TODO. 2009-07-11 19:25:53 +00:00
Nicholas Marriott
0e7c6bdcc7 Update TODO. 2009-07-11 13:48:05 +00:00
Nicholas Marriott
7e8ff69a14 Fix $Id$. 2009-07-09 18:16:36 +00:00
Nicholas Marriott
eee3dd297e New command, if-shell (alias if). Executes the tmux command in the second
argument if the shell command in the first succeeds, for example:

       if "[ -e ~/.tmux.conf.alt ]" "source .tmux.conf.alt"

Written by Tiago Cunha, many thanks.
2009-07-09 18:14:18 +00:00
Nicholas Marriott
5afe17d147 Fix $Id$. 2009-07-09 18:08:29 +00:00
Nicholas Marriott
664a0bd559 Cursor up and down should be limited by the scroll region (cuu should stop at
the scroll region top if starting from below it and cud stop at the bottom if
starting from above). Fixes another vttest test.
2009-07-09 18:08:13 +00:00
Nicholas Marriott
4422b958c3 Don't leak FILE * on malloc failure. From ivoire at users dot sourceforge dot
net.
2009-07-09 18:05:17 +00:00
Nicholas Marriott
295879cced Change inserting and deleting lines inside the scroll region to properly clear
lines that should be inserted/deleted but not moved. Fixes problems with mutt
reported by Brian Lewis, thanks.
2009-07-09 18:04:53 +00:00
Nicholas Marriott
e073441c36 Tidy by removing unused argument from grid_view_{insert,delete}_line_region
functions (currently don't fully work, this is to make fix easier).
2009-07-09 18:04:17 +00:00
Nicholas Marriott
27e9f77a49 Fix two memory leaks when assigning shell variables in configuration
file/command prompt. From Tiago Cunha.
2009-07-09 18:03:28 +00:00
Nicholas Marriott
f8ea82d7dc Update TODO list. 2009-07-09 17:58:54 +00:00
Nicholas Marriott
890db6eaaf Accidently deleted default-command. 2009-07-08 18:12:57 +00:00
Nicholas Marriott
99395856ff Bring spacing into line. 2009-07-08 18:07:09 +00:00
Nicholas Marriott
9cf68ac868 Whoops, that shouldn't have been there. 2009-07-08 18:05:33 +00:00
Nicholas Marriott
2ddcb51df3 Fix $Id$. 2009-07-08 18:03:03 +00:00
Nicholas Marriott
9875be3327 When reinitialising the screen, do not omit to clear the last line. 2009-07-08 18:02:31 +00:00
Nicholas Marriott
a182502af0 Don't let ambiguous commands override an exact alias match: eg if commands
"abc-1", "abc-2", "abc-3" exist and "abc-3" has the alias "abc", "tmux abc"
should execute abc-3, not complain about the command being ambiguous.
2009-07-08 18:01:55 +00:00
Nicholas Marriott
86504af149 Rename the global options variables to be shorter and to make session options
clear. No functional change, getting this out of the way to make later options
changes easier.
2009-07-08 18:01:31 +00:00
Nicholas Marriott
1825609d8d Handle empty or unset TERM correctly; also fix a fatal() message while here. 2009-07-08 17:58:32 +00:00
Nicholas Marriott
43ff216fa6 When sending a "protocol mismatch" error message, tell the client to exit
afterwards, otherwise it hangs.
2009-07-08 17:58:09 +00:00
Nicholas Marriott
ff54332b66 The fix for default-path (use target session options instead of global options)
is required here as well, doh.
2009-07-08 17:57:51 +00:00
Nicholas Marriott
84da2f32ec Minor fix: look for default-path in the options for the specified session first
rather than just the global options. From Brandon Mercer, thanks.
2009-07-08 17:57:27 +00:00
Nicholas Marriott
b7a272fe6d Add a section summarising how options work, make the distinction between window
and session options clearer, and fix the incorrect synopses and descriptions of
show-options and show-window-options.
2009-07-08 17:57:07 +00:00
Nicholas Marriott
9e5a581307 When unlocking the server, don't try to clear the prompt on clients without a
prompt (such as the one issuing the unlock request).

This caused the server to die if the wrong password was entered when unlocking
from the command line with -U (nasty).
2009-07-08 17:54:36 +00:00
Nicholas Marriott
f34f1fd78d Sync. 2009-07-07 23:08:42 +00:00
Nicholas Marriott
a476d4c587 This is not really important or major. 2009-07-06 18:53:24 +00:00
Nicholas Marriott
21f8ed50db Next will be 1.0. 2009-07-06 18:21:17 +00:00
Nicholas Marriott
b8bd24817f If using the default login shell (empty default-command), strip any - prefix. 2009-07-02 18:26:55 +00:00
Nicholas Marriott
08c7249636 Change default_window_name to use window_default_command if the actual cmd is
empty. From Josh Elsasser.
2009-07-02 18:17:46 +00:00
Nicholas Marriott
29ac832cb3 Fix two copy/paste bugs: forbid zero-length buffers to prevent a fatal error
when trying to paste them, found by me, and miscalculation of the start/end
causing random fatal errors when copying in copy-mode, reported by sthen.
2009-07-02 16:23:54 +00:00
Tiago Cunha
85dac1e378 Update. 2009-07-02 13:50:27 +00:00
Nicholas Marriott
1f1623e04d Solaris has no strcasestr. 2009-07-02 07:31:02 +00:00
Nicholas Marriott
3c0500f282 Don't see a reason for sys/cdefs.h here; remove it. 2009-07-01 23:22:46 +00:00
Nicholas Marriott
9f0653386b $Id$. 2009-07-01 23:06:32 +00:00
Nicholas Marriott
ec818b8791 Move defines after includes to avoid multiple definition. 2009-07-01 22:46:13 +00:00
Nicholas Marriott
81f06ba170 Typo: bsdpoll.h -> bsd-poll.h. 2009-07-01 22:43:48 +00:00
Nicholas Marriott
851a35eb5e Change >| to rm/> as apparently Solaris /bin/sh doesn't like it. 2009-07-01 22:28:56 +00:00
Nicholas Marriott
8f2950f4ee Try to make a bit more sense here. 2009-07-01 22:15:16 +00:00
Nicholas Marriott
e0a6376690 Comment FDEBUG and bump dist version. 2009-07-01 22:10:06 +00:00
Nicholas Marriott
1903756171 Changes for 0.9. 2009-07-01 22:08:33 +00:00
Nicholas Marriott
81010f52db Update with new UTF-8 environment variable information for 0.9. 2009-07-01 19:49:56 +00:00
Nicholas Marriott
22d1b9412e Using -l to specify a login shell is non-POSIX and causes problems with shells
that do not support it. Instead, set an empty default-command to invoke $SHELL
with - prefixed to argv[0], and make this the default setting.
2009-07-01 19:42:55 +00:00
Nicholas Marriott
d50810267e This file is not going to be used as much any longer, make a note. 2009-07-01 19:33:53 +00:00
Nicholas Marriott
82b070ddfa Update ready for 0.9 2009-07-01 19:33:11 +00:00
Nicholas Marriott
55f8219d3c When unlocking the server, don't try to clear the prompt on clients without a
prompt (such as the one issuing the unlock request).

This caused the server to die if the wrong password was entered when unlocking
from the command line with -U (nasty).
2009-07-01 19:15:12 +00:00
Nicholas Marriott
35092835b0 Fix two errors with character/line insertion and deletion: the maximum number
of characters which may be inserted or deleted is the screen width, not one
less (and similarly for lines and height); and if characters or lines are
deleted by moving the ones that follow, the space at the end needs to be
cleared.

This appears to solve long-standing redraw issues most visible when using the
force-width option then scrolling in view(1) or unwrapping lines in emacs.
2009-07-01 19:14:33 +00:00
Nicholas Marriott
8fe3f1dcb2 $Id$. 2009-07-01 19:03:34 +00:00
Nicholas Marriott
eed4f7600d Fix $Id$. 2009-06-29 22:04:51 +00:00
Nicholas Marriott
503c6a3377 Don't try to page up with scroll-mode -u or copy-mode -u unless the mode was
successfully changed - if already in a different mode, it would corrupt the
mode data.
2009-06-29 22:04:07 +00:00
Nicholas Marriott
18ebc99906 Use gmtime_r so the current time isn't overwritten, the minute comparison works
and the clock is actually updated. It was already used for lock-server but not
here.
2009-06-29 22:03:36 +00:00
Nicholas Marriott
edc2e7da98 Copy the 256-colour flag into the tty saved cell as well as the actual colour,
otherwise colour 8 isn't reset.
2009-06-29 22:03:09 +00:00
Nicholas Marriott
796b2e3ec9 Add missing spaces before some alias closing brackets, otherwise they are
shown in the wrong style.
2009-06-29 22:02:20 +00:00
Nicholas Marriott
1fb3948ff1 Whoops, revert. 2009-06-26 22:18:36 +00:00
Nicholas Marriott
1496aa5dbc Remove some unused function declarations; no binary change. 2009-06-26 22:18:03 +00:00
Nicholas Marriott
6ce734cec0 After logging (if enabled) is switched to file, there is no reason to keep
stdin/stdout/stderr active, so dup them to /dev/null.
2009-06-26 22:13:57 +00:00
Nicholas Marriott
826add53f1 Set LC_ALL=C to stop i18n breaking gcc test. 2009-06-26 16:01:12 +00:00
Nicholas Marriott
1aaf47e698 Apparently NetBSD's tcgetpgrp is good enough to use, so don't need to play
complicated games, from Roy Marples.
2009-06-26 15:54:52 +00:00
Nicholas Marriott
de2ea2d178 Status line fixes: don't truncate status-right now the length calculation is
done for UTF-8, limit to the maximum length correctly when printing, and always
print a space even if the left string is longer than the width available.
2009-06-26 15:34:12 +00:00
no_author
3fcbe1e27b Remove some dead assignments, found by sthen with clang. 2009-06-26 15:32:00 +00:00
Nicholas Marriott
81b4aca934 #ifndef nitems. 2009-06-26 15:31:15 +00:00
Nicholas Marriott
63753735ec Update TODO. 2009-06-25 21:25:36 +00:00
Nicholas Marriott
32312e0252 vis compat stuff. 2009-06-25 20:27:32 +00:00
Nicholas Marriott
802e129fd7 Start of portability update: bitstring.h. 2009-06-25 17:02:59 +00:00
Nicholas Marriott
f1463ff3c1 Lose -V. 2009-06-25 16:56:08 +00:00
Nicholas Marriott
0af7fa08d2 Skip 8 line diffs ($Id$ change only). 2009-06-25 16:54:21 +00:00
Nicholas Marriott
20002ec6cd Comparison script. 2009-06-25 16:49:22 +00:00
Nicholas Marriott
8fc34ca044 libgen.h. 2009-06-25 16:49:02 +00:00
Nicholas Marriott
a9e3d5c56a More diff-to-OpenBSD reduction. Move a lot of compat stuff into compat.h. 2009-06-25 16:47:00 +00:00
Nicholas Marriott
bb459beb03 Whitespace and more syncing. 2009-06-25 16:34:50 +00:00
Nicholas Marriott
8df98d1f5b Don't need linker magic anymore. 2009-06-25 16:25:55 +00:00
Nicholas Marriott
6cde05147e No more xmalloc-debug. 2009-06-25 16:25:15 +00:00
Nicholas Marriott
8565ae234b Fix rejects. 2009-06-25 16:23:35 +00:00
Nicholas Marriott
3eb1bfddd4 Sync this properly. 2009-06-25 16:22:36 +00:00
Nicholas Marriott
a5830b9603 Restore $Id$ and add script to do so. 2009-06-25 16:21:32 +00:00
Nicholas Marriott
f17a5f1e82 If getcwd() fails, use the user's home directory, or /, instead of failing with
an error.
2009-06-25 16:11:12 +00:00
Nicholas Marriott
bfa46e8f91 lines variable can be -1 (to be ignored), so should be signed. Found by lint. 2009-06-25 16:10:18 +00:00
Nicholas Marriott
f0bcbcfa7f Remove error about using -L and -S together which was never displayed as
logging wasn't yet enabled, was unnecessary, and contradicted the man page
which says using -S will cause -L to be ignored.
2009-06-25 16:09:38 +00:00
Nicholas Marriott
1b9ac18565 tmux doesn't and won't need syslog logging, so remove it and some other unused
functions found by lint.
2009-06-25 16:09:25 +00:00
Nicholas Marriott
582660bdf3 Miscellaneous unused functions, including one which was basically a
duplicate. Found by lint.
2009-06-25 16:09:11 +00:00
Nicholas Marriott
62822b1848 Nuke unused buffer functions. Found by lint.
Also remove some old debug output which was #if 0.
2009-06-25 16:07:00 +00:00
Nicholas Marriott
abb5e36199 Unused prototypes. Found by lint, no binary change. 2009-06-25 16:06:09 +00:00
Nicholas Marriott
947fabc751 Unused variables. Found by lint, no binary change. 2009-06-25 16:05:39 +00:00
Nicholas Marriott
a03ae97fbf Now that a UTF-8-capable puts function exists, use it for printing strings in
choice/more modes - lines with UTF-8 now display properly in find-window
results.
2009-06-25 16:05:00 +00:00
Nicholas Marriott
3ec8efc803 Fix a type mismatch warning in assignment. 2009-06-25 16:04:43 +00:00
Nicholas Marriott
f7a9eb46fc Change find-window and monitor-content to use fnmatch(3). For convenience and
compatibility, *s are implicitly added at the start and end of the pattern.
2009-06-25 16:04:24 +00:00
Nicholas Marriott
853ad68162 Add a dedicated function to convert a line into a string and use it to simplify the search window function. 2009-06-25 16:02:37 +00:00
Nicholas Marriott
e6e1b45fa1 Change to match xterm's resizing behaviour, including pushing lines into the
history from the top when reducing vertical size and pulling them again when
increasing size.
2009-06-25 16:02:10 +00:00
Nicholas Marriott
944520b3a8 Make remain-on-exit work again when there is only one pane left, which was
broken sometime during the pane/layout changes. Reported/tested by Iain Morgan,
thanks.
2009-06-25 16:01:42 +00:00
Nicholas Marriott
942ea4267d Trying to predict the cursor position for UTF-8 output in the same way as for
normal eight-bit output is wrong, separate it into a different function. Fixes
spacing when mixing UTF-8 with some escape sequences, notably the way w3m does
it.
2009-06-25 16:01:26 +00:00
Nicholas Marriott
245685433e Constify utf8_width() function argument. 2009-06-25 16:00:50 +00:00
Nicholas Marriott
7eff7f7629 If a pane is "zombified" (remain-on-exit flag), don't continue to queue key and
mouse input for it (otherwise they are processed after respawn).
2009-06-25 16:00:25 +00:00
Nicholas Marriott
cd5a4f4c35 LC_ALL overrides LC_CTYPE and LANG. Comment was correct but the code
wrong. Pointed out by Hannah Schroeter, thanks.
2009-06-25 16:00:02 +00:00
Nicholas Marriott
7be69bfa03 Terminate cwd buffer before running xstrdup on it. 2009-06-25 15:59:42 +00:00
Nicholas Marriott
6f4600c533 Check the first of LC_CTYPE, LC_ALL and LANG, rather than just the last, when
trying to decide about UTF-8, and use strcasestr. Reported by Geert Hendrickx.
2009-06-25 15:59:27 +00:00
Nicholas Marriott
fbcee9f114 strdup the input to putenv to avoid in one case passing a string that is later
freed and in the other const strings.
2009-06-25 15:58:58 +00:00
Nicholas Marriott
0e95769b43 Call setproctitle earlier in the client, and include the socket name. Makes it
easier to match client to server in ps/pgrep when using several servers.
2009-06-25 15:58:33 +00:00
Nicholas Marriott
b9155e835a Print a better message than '(null)' if no command is specified ("tmux \;"). 2009-06-25 15:56:39 +00:00
Nicholas Marriott
f90450f854 Zero the password given to -U in the client as well. 2009-06-25 15:56:25 +00:00
Nicholas Marriott
418128bebc If the prompt is hidden or a password is sent with -U, zero it before freeing
it.
2009-06-25 15:55:34 +00:00
Nicholas Marriott
63b38ef628 Implement the CBT (backward tab) sequence (\033[Z). 2009-06-25 15:54:57 +00:00
Nicholas Marriott
1b245388b5 Proper support for tab stops (\033H etc), using a bitstring(3). Makes another
vttest test happy.
2009-06-25 15:54:38 +00:00
Nicholas Marriott
cd71a13a14 Okay, so I screwed up when testing this, doh. Unbreak so that CAN/SUB actually
do cancel the sequence, and tweak to make the code more clear.
2009-06-25 15:54:03 +00:00
Nicholas Marriott
4eed190649 Oops, CAN and SUB should abort the sequence (return to first state), not remain
in the same state.
2009-06-25 15:53:44 +00:00
Nicholas Marriott
c3c14817c9 More input compatibility love. Support C0 within escape sequences, and the C0
control character VT (vertical tab, \013), which is treated as LF like
VT102. Makes another vttest happy.
2009-06-25 15:52:59 +00:00
Nicholas Marriott
b8ec0c713f Support insert mode by using insert character to shift the cells before writing
as normal.
2009-06-25 15:52:12 +00:00
Nicholas Marriott
93631b3ca7 Implement the DEC alignment test. With the last change this is enough for the
first cursor test in vttest (in ports) to pass; it still shops a few more
problems though.
2009-06-25 15:51:54 +00:00
Nicholas Marriott
49477de55c Fix some miscalculations when clearing to start of screen: the number of lines
to the cursor is cy not cy - 1, and the current cursor cell should be included.
2009-06-25 15:50:48 +00:00
Nicholas Marriott
dff949747c Use vis(3) instead of handrolled function. 2009-06-25 15:50:03 +00:00
Nicholas Marriott
7597cb6834 Pass window titles through vis(1). <0x20 is dropped anyway by the input state
machine but top-bit-set nonprintables could cause trouble, and they are neater
like this anyway.
2009-06-25 15:49:27 +00:00
Nicholas Marriott
4f2e5f8c50 Do not set the window title by default (make set-titles option default to off),
wiping over the title is rude and annoying.
2009-06-25 15:48:59 +00:00
Nicholas Marriott
28bcf774e5 New session option, status-utf8, to control the interpretation of top-bit-set
characters in status-left and status-right (if on, they are treated as UTF-8;
otherwise passed through).
2009-06-25 15:48:25 +00:00
Nicholas Marriott
1e06ec41dc Add a UTF-8 aware string length function and make UTF-8 in
status-left/status-right work properly. At the moment any top-bit-set
characters are assumed to be UTF-8: a status-utf8 option to configure this will
come shortly.
2009-06-25 15:47:07 +00:00
Nicholas Marriott
0828e06ad7 Nuke unused pane flag. 2009-06-25 15:46:09 +00:00
Nicholas Marriott
d3d4bacd82 Cast char to u_char before passing to isalnum(). By ray 2009-06-25 15:45:24 +00:00
Nicholas Marriott
94f5ddb60c remove unused flag; while here, make usage's output fit on 80-column displays. 2009-06-25 15:44:44 +00:00
Nicholas Marriott
658659532a Use login shells by default. 2009-06-25 15:44:03 +00:00
Nicholas Marriott
6528d47ed8 Don't leak memory if multiple -f flags are given. From ray 2009-06-25 15:42:35 +00:00
Nicholas Marriott
5b3db7b56c Sync man page with OpenBSD. 2009-06-25 15:30:29 +00:00
Nicholas Marriott
3d7cf00359 Add missing -a flag. 2009-06-25 15:29:34 +00:00
Nicholas Marriott
e2a0c5ad7a When swapping pane positions, swap the PANE_HIDDEN flag as well, otherwise tmux
crashes when trying to find the new active pane.

While here, nuke an unused pane flag.

Fixes PR 6160, reported by and a slightly different version of diff tested by
ralf.horstmann at gmx.de.
2009-06-25 15:28:08 +00:00
Nicholas Marriott
32398b98a8 Sync to OpenBSD: fixes from ray@. 2009-06-25 15:25:45 +00:00
Nicholas Marriott
0fdd47660a UTF-8 detection is broken on sparc64; disable until I get time to test it further. 2009-06-24 17:31:03 +00:00
Nicholas Marriott
6208128fa2 Sync with private copy. 2009-06-03 17:52:29 +00:00
Nicholas Marriott
940e2ae1fd endpwent() is not required after getpwuid(). 2009-06-01 20:38:59 +00:00
Nicholas Marriott
144aed48fa +. 2009-05-29 23:26:11 +00:00
Nicholas Marriott
f63f5e6489 Clear status line on incorrect password. 2009-05-29 23:25:26 +00:00
Nicholas Marriott
17a6c01d58 Don't show real character under cursor when hidden. Doh. 2009-05-29 05:40:56 +00:00
Nicholas Marriott
8536ad0ce7 Reset activity time to avoid relock on -U. 2009-05-28 16:24:02 +00:00
Nicholas Marriott
3a55871d04 Now in base. 2009-05-26 18:31:10 +00:00
Nicholas Marriott
cd4566cd69 Spacing. 2009-05-26 18:30:51 +00:00
Nicholas Marriott
133539a2d4 Update. 2009-05-21 19:51:33 +00:00
Nicholas Marriott
89404788c9 Spacing. 2009-05-21 19:47:57 +00:00
Nicholas Marriott
6c442c19ba UPPER -> BIG, sort, and bump protocol version. 2009-05-21 19:46:00 +00:00
Nicholas Marriott
a8ec5f1d09 stat(2) files before trying to load them to avoid problems, for example with "source-file /dev/zero".
This commit dedicated to Tom: protecting idiots from their own stupidity for more than 20 years.
2009-05-21 19:38:51 +00:00
Nicholas Marriott
eb6007102e new layout plan 2009-05-20 15:46:48 +00:00
Nicholas Marriott
cdce5f739d Indentation. 2009-05-19 16:29:35 +00:00
Nicholas Marriott
5707eb3256 +. 2009-05-19 16:12:40 +00:00
Nicholas Marriott
6db7bd6791 Try to guess if the window is UTF-8 by outputting a three-byte UTF-8 wide character and seeing how much the cursor moves. Currently tries to figure out if this works by some stupid checks on the terminal, these need to be rethought. Also might be better using a width 1 character rather than width 2. 2009-05-19 16:08:35 +00:00
Nicholas Marriott
5db59a0d20 If LANG contains "UTF-8", assume the terminal supports UTF-8, on the grounds that anyone who configures it probably wants UTF-8. Not certain if this is a perfect idea but let's see if it causes any problems. 2009-05-19 16:03:18 +00:00
Tiago Cunha
80af85a102 - New window option monitor-content to search for a string in a window, and
highlight the status line if it matches.
- To make this possible, the function cmd_find_window_search from
  cmd-find-window.c had to be moved to window.c and renamed window_pane_search.
- While there use three new functions in server.c to check for bell, activity,
  and content, to avoid too much nesting.
2009-05-19 13:32:55 +00:00
Nicholas Marriott
a385f75792 Note. 2009-05-19 08:50:10 +00:00
Nicholas Marriott
0abd8ea84f (void). 2009-05-19 08:48:49 +00:00
Nicholas Marriott
72e464fa04 main-horizontal layout and main-pane-height option to match vertical. 2009-05-18 22:17:24 +00:00
Nicholas Marriott
c21ffbc772 left-vertical -> main-vertical.
Also update CHANGES/TODO.
2009-05-18 21:58:40 +00:00
Nicholas Marriott
6e4b947d71 New option main-pane-width to set width of pane in left-vertical mode. 2009-05-18 21:55:53 +00:00
Nicholas Marriott
3ee4b334e7 manual -> manual-vertical. 2009-05-18 21:32:36 +00:00
Nicholas Marriott
404411f5e7 horizontal -> h, vertical -> v, to shorten some function names a little. 2009-05-18 21:29:11 +00:00
Nicholas Marriott
d601c42ea2 Behave properly when resize not supported. 2009-05-18 21:16:09 +00:00
Nicholas Marriott
b233616853 Update TODO. 2009-05-18 21:08:11 +00:00
Nicholas Marriott
5518b6138d manual -> manual-vertical. 2009-05-18 21:06:16 +00:00
Nicholas Marriott
ab4e5e8574 Clean up manual layout code:
- change the one layout function into two _refresh and _resize
- create layout-manual.c for manual layout code
- move the fit panes/update panes code from window.c to the new file as it is only used by manual layout now
- move the resize pane code into layout-manual.c as well
- get rid of the direct calls to fit/update and make them go through layout
- rename a couple of variables

This is mainly as a first step before reworking the manual layout code to see if anything breaks.
2009-05-18 21:01:38 +00:00
Nicholas Marriott
b6b00c53bd Fix comment. 2009-05-18 20:18:08 +00:00
Nicholas Marriott
2f5c3d881d #undef everything in config.h. This is the only bit of the scripting work I am
using now :-).
2009-05-18 19:18:41 +00:00
Nicholas Marriott
a03cf0e183 +b on fopen. 2009-05-18 16:22:30 +00:00
Nicholas Marriott
d2275f4abf chmod +x configure 2009-05-18 15:42:30 +00:00
Nicholas Marriott
0c33b73db0 Move some crap into the attic, and some other stuff into tools/. 2009-05-17 18:27:18 +00:00
Nicholas Marriott
8dc73f2df5 Move website stuff into its own directory. 2009-05-17 18:20:59 +00:00
Nicholas Marriott
6805217783 Move dist.mk to tools/. 2009-05-17 18:15:41 +00:00
Nicholas Marriott
0f5168f971 Use >|. 2009-05-16 22:14:47 +00:00
Nicholas Marriott
c111310600 Use a better variable name and allow the uname to be overridden. 2009-05-16 22:06:01 +00:00
Nicholas Marriott
d58bfe5f0a clean-all. 2009-05-16 21:56:38 +00:00
Nicholas Marriott
095f16d64f clean-all target to clean configure stuff too. 2009-05-16 21:55:54 +00:00
Nicholas Marriott
25911d32e1 Use empty(), FreeBSD doesn't like ==. 2009-05-16 18:59:50 +00:00
Nicholas Marriott
1001902143 select-layout command and some key bindings. 2009-05-16 11:48:47 +00:00
Nicholas Marriott
03af7c99b5 Recreate server socket on SIGUSR1, per SF feature request 2792533. 2009-05-16 10:02:51 +00:00
Nicholas Marriott
92de1ad6c8 putenv can be char *. 2009-05-15 12:58:56 +00:00
Nicholas Marriott
0b54a2d723 Don't use -Wcast-qual and use explicit casts to shut gcc up in the few cases we can't avoid using a char *. 2009-05-15 12:57:36 +00:00
Nicholas Marriott
8913d853e4 +sfw for solaris too. 2009-05-14 19:49:26 +00:00
Nicholas Marriott
cba338ac13 Keys in status line (p in vi mode, M-y in emacs) to paste the first line of the upper paste buffer. Suggested by Dan Colish. 2009-05-14 19:36:56 +00:00
Nicholas Marriott
8931f0018a Separate tmux target. Doh. 2009-05-14 19:32:37 +00:00
Nicholas Marriott
b476fab34d PuTTY resizing from merdely. 2009-05-14 18:43:02 +00:00
Nicholas Marriott
96ca072482 clear-history command. 2009-05-14 16:56:23 +00:00
Nicholas Marriott
cc59ee4e6a This is okay. 2009-05-14 16:31:35 +00:00
Nicholas Marriott
dd2f8d7d74 Don't force wrapping with \n when asked, let the cursor code figure it out. Should fix terminals which use this to detect line breaks. 2009-05-14 16:21:55 +00:00
Nicholas Marriott
4b64bd7b01 It is HAVE_PTY_H, also add a cast to shut gcc up. 2009-05-14 07:58:38 +00:00
Nicholas Marriott
c495337e76 HAVE_. 2009-05-14 07:51:51 +00:00
Nicholas Marriott
cae92a2041 Needs a VERSION. 2009-05-14 07:51:25 +00:00
Nicholas Marriott
5adb342147 SunOS tweaks. 2009-05-14 07:49:23 +00:00
Nicholas Marriott
3b0bd5a3e6 +. 2009-05-14 07:49:15 +00:00
Nicholas Marriott
6099a3399e Add distribution stuff back in. 2009-05-14 07:48:42 +00:00
Nicholas Marriott
1a86934e09 NetBSD has no strtonum so needs compat/. 2009-05-14 00:40:58 +00:00
Nicholas Marriott
626fe978e1 NetBSD tree.h has no RB_PREV. 2009-05-14 00:35:53 +00:00
Nicholas Marriott
99dee98a2b Use a variable for uname. 2009-05-14 00:34:25 +00:00
Nicholas Marriott
db7357fdcc print is redundant. Doh. 2009-05-14 00:31:48 +00:00
Nicholas Marriott
5436f6be19 Sprinkle the magic anti-GCC-suckage for *BSD as well. 2009-05-14 00:28:04 +00:00
Nicholas Marriott
1b70993207 Move -lutil. 2009-05-14 00:17:37 +00:00
Nicholas Marriott
a8fe667267 Use the right osdep. 2009-05-14 00:12:42 +00:00
Nicholas Marriott
9ff8c354ab install depends on all. 2009-05-14 00:09:02 +00:00
Nicholas Marriott
de79ce38a5 Try to figure out if we are using gcc 4 and get rid of the stupid warning, while not breaking 3.x and 2.x... 2009-05-14 00:06:59 +00:00
Nicholas Marriott
6c27e434c6 compat/bsd-poll.h now we are not doing -Icompat. 2009-05-13 23:50:42 +00:00
Nicholas Marriott
41fb824cbe Sort. 2009-05-13 23:45:26 +00:00
Nicholas Marriott
ab5273d9a9 Don't bother with this. 2009-05-13 23:43:27 +00:00
Nicholas Marriott
488a67e5a3 Whoops, don't use the name of the rule here now. 2009-05-13 23:41:58 +00:00
Nicholas Marriott
df9a2886dd Add a changes entry. 2009-05-13 23:40:30 +00:00
Nicholas Marriott
4337a9b2d5 Two more to ignore. 2009-05-13 23:34:33 +00:00
Nicholas Marriott
78f6b511fd $(PROG) is gorn. 2009-05-13 23:33:54 +00:00
Nicholas Marriott
522bf77cf4 cmake build files. I wrote these but then decided to keep the cleanup
(getopt/HAVE_*) changes but add a manual configure script and clean up the
makefiles instead. Can always be resurrected if necessary.
2009-05-13 23:32:21 +00:00
Nicholas Marriott
f1bd3807ae Everything supported has working vsnprintf. 2009-05-13 23:29:45 +00:00
Nicholas Marriott
c8cf438d44 Rename all feature flags to HAVE_* and move out of makefiles into a configure
script which must be run before building.

Still two makefiles but they are a hell of a lot simpler.

HAVE_* also will make it easier to move to $buildsystem if necessary later.
2009-05-13 23:27:00 +00:00
Nicholas Marriott
e1b4a37722 Bye-bye nonworking IRIX, can be rescued from the attic if ever needed again. 2009-05-13 22:26:11 +00:00
Nicholas Marriott
792aeb926e Use getopt.c from openssh rather than OpenBSD's getopt_long. 2009-05-13 22:20:48 +00:00
Nicholas Marriott
88daeb5410 Bye-bye META. 2009-05-13 22:10:39 +00:00
Nicholas Marriott
83d984eca8 Works fine, escaping was the issue. 2009-05-11 19:03:30 +00:00
Nicholas Marriott
b21e356e56 Spacing. 2009-05-04 19:12:37 +00:00
Nicholas Marriott
525bd431b2 RB_INSERT returns &item if already exists, so use that rather than doing a
check beforehand.
2009-05-04 18:05:23 +00:00
Nicholas Marriott
143aa718e5 Space trimmage mega-diff. 2009-05-04 17:58:27 +00:00
Nicholas Marriott
59a5728527 This should be fixed by previous commit. 2009-05-04 17:53:06 +00:00
Nicholas Marriott
54a5f82588 Region can reset cursor to 0,0 - bad if there is an offset. So sort out region before cursor. 2009-05-04 17:52:14 +00:00
Nicholas Marriott
fb543c7707 Use ACS for line drawing characters. 2009-05-04 13:20:02 +00:00
Nicholas Marriott
9164dd63e7 Only worry about complete seconds for status line update. Also reduce poll interval and de-magic-number it. 2009-05-02 08:34:39 +00:00
Nicholas Marriott
827fac4c0b Support "neww; neww" as well "neww ; neww". 2009-04-30 21:53:32 +00:00
Nicholas Marriott
044e6f7660 previous-layout command. 2009-04-30 21:17:06 +00:00
Nicholas Marriott
a6f2d82335 Use a (pre)randomised binary tree for UTF-8 character widths. Probably overkill
but meh.
2009-04-30 20:54:53 +00:00
Nicholas Marriott
4a74349ff5 static const. 2009-04-30 18:39:34 +00:00
Nicholas Marriott
a583bbb730 Display the layout name in window lists. 2009-04-30 16:27:29 +00:00
Nicholas Marriott
631f81f519 DOH. 2009-04-30 16:24:20 +00:00
Nicholas Marriott
5732d666a1 Indentation. 2009-04-30 06:04:26 +00:00
Nicholas Marriott
eccaaeee6e cvs add is often a good move. 2009-04-30 06:01:35 +00:00
Nicholas Marriott
cdf472f2de Merge resize-pane-{up,down} into resize-pane. 2009-04-30 06:01:24 +00:00
Nicholas Marriott
a3f7928084 Oops, revert - need u_char. 2009-04-30 06:00:13 +00:00
Nicholas Marriott
38a33addf7 Don't need cp. 2009-04-30 05:42:46 +00:00
Nicholas Marriott
71a903d4be This should be fixed now. 2009-04-29 23:11:02 +00:00
Nicholas Marriott
91241f1457 Apply the make magic wand to pick an osdep-*.c file rather than using ifdefs. 2009-04-29 23:07:35 +00:00
Nicholas Marriott
ce989a91d1 /* $Id$ */ 2009-04-29 22:45:32 +00:00
Nicholas Marriott
8aa72ac803 tmux doesn't care about setres[ug]id. 2009-04-29 22:42:02 +00:00
Nicholas Marriott
2b967aa1d2 getopt_long.c not getopt.c 2009-04-29 22:40:52 +00:00
Nicholas Marriott
74dfb503a8 Solaris doesn't have TAILQ_REPLACE yet :-(. 2009-04-29 22:35:45 +00:00
Nicholas Marriott
3085ca7153 Don't need all this %p stuff anymore really. 2009-04-29 22:29:20 +00:00
Nicholas Marriott
cc9cc1aea8 Some tweaks for Solaris.
Get rid of vis.* in favour of a small replacement function.
2009-04-29 22:25:20 +00:00
Nicholas Marriott
323b7cbfbe Ignore tmux*.out as well. 2009-04-29 21:46:56 +00:00
Nicholas Marriott
f0a716f484 Use a u_char so top-bit-set update the cursor as well. 2009-04-29 17:50:52 +00:00
Nicholas Marriott
cd214f8f6a + item. 2009-04-29 17:07:18 +00:00
Nicholas Marriott
7c5f1af26f Ignore del too. 2009-04-29 17:06:45 +00:00
Tiago Cunha
53dc88e276 Simplify the code by using the generic _target functions. 2009-04-28 18:29:44 +00:00
Nicholas Marriott
6b148c8dce No TAILQ_REPLACE on NetBSD. 2009-04-27 18:10:10 +00:00
Nicholas Marriott
6317046bd1 Use cmd_prarg to include "s when necessary. 2009-04-27 17:28:30 +00:00
Nicholas Marriott
5d1b6888dc Convert hidden flag to a full flags word for the status line and add a flag to
accept after only one key. Use this so don't need to press enter after y/n for
confirm-before.
2009-04-27 17:27:36 +00:00
Nicholas Marriott
1f2d9e64bb +=. 2009-04-27 16:55:29 +00:00
Nicholas Marriott
d8a35ffa50 Perform some black and midnight cpp witchcraft to get rid of GRID_DEBUG, to fix
building with -DDEBUG on gcc2 platforms. From joshe.
2009-04-27 14:51:59 +00:00
Nicholas Marriott
850965584e Missing Ar. 2009-04-27 14:50:22 +00:00
Tiago Cunha
ddf2efe57b Update commands, and options. 2009-04-27 14:44:14 +00:00
Tiago Cunha
e397e3a5f8 - Add alias to the break-pane command.
- s/Asks/Ask/ in the confirm-before command for consistency's sake.
2009-04-27 14:40:45 +00:00
Tiago Cunha
c80ad456cc Avoid using the prompt history when the server is locked, and prevent any
input entered from being added to the client's prompt history. From nicm.
2009-04-27 13:56:51 +00:00
Tiago Cunha
058772e4e6 - confirm-before command.
- Bound "&" and "x" by default to confirm-before "kill-window" and
  confirm-before "kill-pane", respectively.
2009-04-27 13:21:16 +00:00
Nicholas Marriott
7d6896ae79 Support NEL. 2009-04-23 21:28:45 +00:00
Nicholas Marriott
5fbdca890a Use the xenl terminfo flag to detect early-wrap terminals like the FreeBSD
console. Many thanks for a very informative email from Christian Weisgerber.
2009-04-23 21:09:17 +00:00
Nicholas Marriott
a91ecf44fa Note it. 2009-04-23 17:51:57 +00:00
Nicholas Marriott
f8771a538e Gearing up for 0.9.... 2009-04-21 21:11:46 +00:00
Nicholas Marriott
ba3ad75002 Mouse supprot isn't so bad. 2009-04-21 20:57:10 +00:00
Nicholas Marriott
22b44cbb2b 0.9 here we go. 2009-04-21 20:54:18 +00:00
186 changed files with 14309 additions and 8620 deletions

156
CHANGES
View File

@@ -1,3 +1,157 @@
CHANGES FROM 0.9 TO 1.0, 20 Sept 2009
* Option to alter the format of the window title set by tmux.
* Backoff for a while after multiple incorrect password attempts.
* Quick display of pane numbers (C-b q).
* Better choose-window, choose-session commands and a new choose-client command.
* Option to request multiple responses when using command-prompt.
* Improved environment handling.
* Combine wrapped lines when pasting.
* Option to override terminal settings (terminal-overrides).
* Use the full range of ACS characters for drawing pane separator lines.
* Customisable mode keys.
* Status line colour options, with embedded colours in status-left/right, and
an option to centre the window list.
* Much improved layouts, including both horizontal and vertical splitting.
* Optional visual bell, activity and content indications.
* Set the utf8 and status-utf8 options when the server is started with -u.
* display-message command to show a message in the status line, by default some
information about the current window.
* Improved current process detection on NetBSD.
* unlink-window -k is now the same as kill-window.
* attach-session now works from inside tmux.
* A system-wide configuration file, /etc/tmux.conf.
* A number of new commands in copy mode, including searching.
* Panes are now specified using the target (-t) notation.
* -t now accepts fnmatch(3) patterns and looks for prefixes.
* Translate \r into \n when pasting.
* Support for binding commands to keys without the prefix key
* Support for alternate screen (terminfo smcup/rmcup).
* Maintain data that goes off screen after reducing the window size, so it can
be restored when the size is increased again.
* New if-shell command to test a shell command before running a tmux command.
* tmux now works as the shell.
* Man page reorganisation.
* Many minor additions, much code tidying and several bug fixes.
CHANGES FROM 0.8 TO 0.9, 01 July 2009
* Major changes to build infrastructure: cleanup of makefiles and addition
of a configure script.
* monitor-content window option to monitor a window for a specific fnmatch(3)
pattern. The find-window command also now accepts fnmatch(3) patterns.
* previous-layout and select-layout commands, and a main-horizontal layout.
* Recreate the server socket on SIGUSR1.
* clear-history command.
* Use ACS line drawing characters for pane separator lines.
* UTF-8 improvements, and code to detect UTF-8 support by looking at
environment variables.
* The resize-pane-up and resize-pane-down commands are now merged together
into a new resize-pane command with -U and -D flags.
* confirm-before command to request a yes/no answer before executing dangerous
commands.
* Status line bug fixes, support for UTF-8 (status-utf8 option), and a key to
paste from the paste buffer.
* Support for some additional escape sequences and terminal features, including
better support for insert mode and tab stops.
* Improved window resizing behaviour, modelled after xterm.
* Some code reduction and a number of miscellaneous bug fixes.
================================================================================
On 01 June 2009, tmux was imported into the OpenBSD base system. From this date
onward changes are logged as part of the normal CVS commit message to either
OpenBSD or SourceForge CVS. This file will be updated to contain a summary of
major changes with each release, and to mention important configuration or
command syntax changes during development.
The list of older changes is below.
================================================================================
21 May 2009
* stat(2) files before trying to load them to avoid problems, for example
with "source-file /dev/zero".
19 May 2009
* Try to guess if the window is UTF-8 by outputting a three-byte UTF-8 wide
character and seeing how much the cursor moves. Currently tries to figure out
if this works by some stupid checks on the terminal, these need to be
rethought. Also might be better using a width 1 character rather than width 2.
* If LANG contains "UTF-8", assume the terminal supports UTF-8, on the grounds
that anyone who configures it probably wants UTF-8. Not certain if this is
a perfect idea but let's see if it causes any problems.
* New window option: monitor-content. Searches for a string in a window and if
it matches, highlight the status line.
18 May 2009
* main-horizontal layout and main-pane-height option to match vertical.
* New window option main-pane-width to set the width of the large left pane with
main-vertical (was left-vertical) layout.
* Lots of layout cleanup. manual layout is now manual-vertical.
16 May 2009
* select-layout command and a few default key bindings (M-0, M-1, M-2, M-9) to
select layouts.
* Recreate server socket on SIGUSR1, per SF feature request 2792533.
14 May 2009
* Keys in status line (p in vi mode, M-y in emacs) to paste the first line
of the upper paste buffer. Suggested by Dan Colish.
* clear-history command to clear a pane's history.
* Don't force wrapping with \n when asked, let the cursor code figure it out.
Should fix terminals which use this to detect line breaks.
* Major cleanup and restructuring of build infrastructure. Still separate files
for GNU and BSD make, but they are now hugely simplified at the expense of
adding a configure script which must be run before make. Now build and
install with:
$ ./configure && make && sudo make install
04 May 2009
* Use ACS line drawing characters for pane separator lines.
30 April 2009
* Support command sequences without a space before the semicolon, for example
"neww; neww" now works as well as "neww ; neww". "neww;neww" is still an
error.
* previous-layout command.
* Display the layout name in window lists.
* Merge resize-pane-up and resize-pane-down into resize-pane with -U and -D
flags.
29 April 2009
* Get rid of compat/vis.* - only one function was used which is easily
replaced,and less compat code == good.
27 April 2009
* Avoid using the prompt history when the server is locked, and prevent any
input entered from being added to the client's prompt history.
* New command, confirm-before (alias confirm), which asks for confirmation
before executing a command. Bound "&" and "x" by default to confirm-before
"kill-window" and confirm-before "kill-pane", respectively.
23 April 2009
* Support NEL, yet another way of making newline. Fixes the output from some
Gentoo packaging thing. Reported by someone on SF then logs that allowed a
fix sent by tcunha.
* Use the xenl terminfo flag to detect early-wrap terminals like the FreeBSD
console. Many thanks for a very informative email from Christian Weisgerber.
21 April 2009
* tmux 0.8 released.
17 April 2009 17 April 2009
* Remove the right number of characters from the buffer when escape then * Remove the right number of characters from the buffer when escape then
@@ -1204,7 +1358,7 @@
(including mutt, emacs). No status bar yet and no key remapping or other (including mutt, emacs). No status bar yet and no key remapping or other
customisation. customisation.
$Id: CHANGES,v 1.272 2009-04-17 12:36:21 nicm Exp $ $Id: CHANGES,v 1.300 2009-09-20 18:54:21 nicm Exp $
LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms

65
FAQ
View File

@@ -42,16 +42,17 @@ include as much of the following information as possible:
Please send feature requests by email to nicm@users.sourceforge.net. Please send feature requests by email to nicm@users.sourceforge.net.
* Why do you use the screen termcap inside tmux? It sucks. * Why do you use the screen terminal description inside tmux? It sucks.
It is already widely available. It is planned to change to something else It is already widely available. It is planned to change to something else such
such as xterm-color at some point, if possible. as xterm-xfree86 at some point, if possible.
* I don't see any colour in my terminal! Help! * I don't see any colour in my terminal! Help!
On some platforms, common termcaps such as xterm do not include colour. screen On some platforms, common terminal descriptions such as xterm do not include
ignores this, tmux does not. If the terminal emulator in use supports colour, colour. screen ignores this, tmux does not. If the terminal emulator in use
use a termcap which correctly lists this, such as xterm-color. supports colour, use a value for TERM which correctly lists this, such as
xterm-color.
* tmux freezes my terminal when I attach to a session. I even have to kill -9 * tmux freezes my terminal when I attach to a session. I even have to kill -9
the shell it was started from to recover! the shell it was started from to recover!
@@ -87,17 +88,27 @@ for each tmux window or globally by setting the "utf8" flag:
setw -g utf8 on setw -g utf8 on
And, as it is not possible to automatically detect that a terminal is UTF-8 As of release 0.9, tmux attempts to autodetect a UTF-8-capable terminal by
capable, tmux must be told by passing the -u flag when creating or checking the LC_ALL, LC_CTYPE and LANG environment variables. list-clients may
attaching a client to a tmux session: be used to check if this is detected correctly; if not, the -u command-line
flag may be specified when creating or attaching a client to a tmux session:
$ tmux -u new $ tmux -u new
* How do I use a 256 colour terminal? * How do I use a 256 colour terminal?
tmux will attempt to detect a 256 colour terminal both by looking at the Co Provided the underlying terminal supports 256 colours, it is usually sufficient
termcap entry and, as this is broken for some terminals such as xterm-256color, to add the following to ~/.tmux.conf:
by looking for the string "256col" in the termcap name.
set -g default-terminal "screen-256color"
Note that some platforms do not support "screen-256color" ("infocmp
screen-256color" will return an error) - in this case see the next entry in
this FAQ.
tmux attempts to detect a 256 colour terminal both by looking at the colors
terminfo entry and by looking for the string "256col" in the TERM environment
variable.
If both these methods fail, the -2 flag may be passed to tmux when attaching If both these methods fail, the -2 flag may be passed to tmux when attaching
to a session to indicate the terminal supports 256 colours. to a session to indicate the terminal supports 256 colours.
@@ -105,22 +116,18 @@ to a session to indicate the terminal supports 256 colours.
* vim or $otherprogram doesn't display 256 colours. What's up? * vim or $otherprogram doesn't display 256 colours. What's up?
Some programs attempt to detect the number of colours a terminal is capable of Some programs attempt to detect the number of colours a terminal is capable of
by checking the Co termcap entry. However, this is not reliable, and in any by checking the colors terminfo or Co termcap entry. However, this is not
case is missing from the "screen" termcap used inside tmux. reliable, and in any case is missing from the "screen" terminal description
used inside tmux.
There are three options to allow programs to recognise they are running on There are two options (aside from using "screen-256color") to allow programs to
a 256-colour terminal inside tmux: recognise they are running on a 256-colour terminal inside tmux:
- Manually force the application to use 256 colours always or if TERM is set to - Manually force the application to use 256 colours always or if TERM is set to
screen. For vim, you can do this by overriding the t_Co option, see screen. For vim, you can do this by overriding the t_Co option, see
http://vim.wikia.com/wiki/256_colors_in_vim. http://vim.wikia.com/wiki/256_colors_in_vim.
- If the platform includes it, using the "screen-256color" termcap (set - Creating a custom terminfo file that includes colors#256 in ~/.terminfo and
TERM=screen-256color). "infocmp screen-256color" can be used to check if this using it instead. These may be compiled with tic(1).
is supported. It is not currently possible to set this globally inside tmux
but it may be done in a shell startup script by checking if TERM is screen
and exporting TERM=screen-256color instead.
- Creating a custom terminfo file that includes Co#256 in ~/.terminfo and using
it instead. These may be compiled with tic(1).
* How do I make Ctrl-PgUp and Ctrl-PgDn work in vim? * How do I make Ctrl-PgUp and Ctrl-PgDn work in vim?
@@ -186,4 +193,12 @@ Automatic window renaming may use a lot of CPU, particularly on slow computers:
if this is a problem, turn it off with "setw -g automatic-rename off". If this if this is a problem, turn it off with "setw -g automatic-rename off". If this
doesn't fix it, please report the problem. doesn't fix it, please report the problem.
$Id: FAQ,v 1.21 2009-03-31 23:17:28 nicm Exp $ * I use PuTTY and my tmux window pane separators are all qqqqqqqqq's!
PuTTY is using a character set translation that doesn't support ACS line
drawing. With a Unicode font, try setting PuTTY to use a different translation
on the Window -> Translation configuration page. For example, change UTF-8 to
ISO-8859-1 or CP437. It may also be necessary to adjust the way PuTTY treats
line drawing characters in the lower part of the same configuration page.
$Id: FAQ,v 1.29 2009-08-08 20:46:26 nicm Exp $

View File

@@ -1,144 +1,65 @@
# $Id: GNUmakefile,v 1.82 2009-04-21 20:10:22 nicm Exp $ # $Id: GNUmakefile,v 1.114 2009-09-20 18:54:21 nicm Exp $
.PHONY: clean .PHONY: clean
PROG= tmux VERSION= 1.0
VERSION= 0.8
DATE= $(shell date +%Y%m%d-%H%M)
#FDEBUG= 1 #FDEBUG= 1
META?= \002
SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
xmalloc.c xmalloc-debug.c input.c input-keys.c \
screen.c screen-write.c screen-redraw.c \
grid.c grid-view.c \
window.c session.c log.c client.c client-msg.c client-fn.c cfg.c \
key-string.c key-bindings.c resize.c arg.c mode-key.c \
layout.c cmd.c cmd-generic.c cmd-string.c cmd-list.c \
cmd-detach-client.c cmd-list-sessions.c cmd-new-window.c cmd-bind-key.c \
cmd-unbind-key.c cmd-previous-window.c cmd-last-window.c cmd-list-keys.c \
cmd-set-option.c cmd-rename-window.c cmd-select-window.c \
cmd-list-windows.c cmd-attach-session.c cmd-send-prefix.c \
cmd-refresh-client.c cmd-kill-window.c cmd-list-clients.c \
cmd-link-window.c cmd-unlink-window.c cmd-next-window.c cmd-send-keys.c \
cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \
cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c cmd-copy-mode.c \
cmd-paste-buffer.c cmd-new-session.c cmd-start-server.c \
cmd-kill-server.c cmd-set-window-option.c cmd-show-options.c \
cmd-show-window-options.c cmd-command-prompt.c cmd-set-buffer.c \
cmd-show-buffer.c cmd-list-buffers.c cmd-delete-buffer.c \
cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \
cmd-respawn-window.c cmd-source-file.c cmd-server-info.c \
cmd-clock-mode.c cmd-lock-server.c cmd-set-password.c \
cmd-save-buffer.c cmd-select-pane.c cmd-split-window.c \
cmd-resize-pane-up.c cmd-resize-pane-down.c cmd-kill-pane.c \
cmd-up-pane.c cmd-down-pane.c cmd-choose-window.c cmd-choose-session.c \
cmd-suspend-client.c cmd-find-window.c cmd-load-buffer.c \
cmd-copy-buffer.c cmd-break-pane.c cmd-swap-pane.c cmd-next-layout.c \
cmd-rotate-window.c \
window-clock.c window-scroll.c window-more.c window-copy.c \
window-choose.c \
options.c options-cmd.c paste.c colour.c utf8.c clock.c \
tty.c tty-term.c tty-keys.c tty-write.c util.c names.c \
osdep-unknown.c osdep-openbsd.c osdep-freebsd.c osdep-linux.c \
osdep-darwin.c attributes.c
CC?= gcc CC?= gcc
INCDIRS+= -I. -I- CFLAGS+= -DBUILD="\"$(VERSION)\""
CFLAGS+= -DBUILD="\"$(VERSION) ($(DATE))\"" -DMETA="'${META}'" LDFLAGS+= -L/usr/local/lib
LIBS+=
ifdef FDEBUG ifdef FDEBUG
CFLAGS+= -g -ggdb -DDEBUG CFLAGS+= -g -ggdb -DDEBUG
LDFLAGS+= -rdynamic
LIBS+= -ldl
endif
ifeq (${CC},gcc)
CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2 CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
endif endif
LDFLAGS+= # This sort of sucks but gets rid of the stupid warning and should work on
LIBS+= -lncurses # most platforms...
ifeq ($(shell (LC_ALL=C $(CC) -v 2>&1|awk '/gcc version 4|clang/') || true), )
CPPFLAGS:= -I. -I- $(CPPFLAGS)
else
CPPFLAGS:= -iquote. $(CPPFLAGS)
ifdef FDEBUG
CFLAGS+= -Wno-pointer-sign
endif
endif
PREFIX?= /usr/local PREFIX?= /usr/local
INSTALLDIR= install -d INSTALLDIR= install -d
INSTALLBIN= install -g bin -o root -m 555 INSTALLBIN= install -g bin -o root -m 555
INSTALLMAN= install -g bin -o root -m 444 INSTALLMAN= install -g bin -o root -m 444
ifeq ($(shell uname),AIX) SRCS= $(shell echo *.c|sed 's|osdep-[a-z0-9]*.c||g')
INCDIRS+= -I/usr/local/include/ncurses -Icompat include config.mk
SRCS+= compat/vis.c compat/strlcpy.c compat/strlcat.c compat/strtonum.c \
compat/fgetln.c compat/asprintf.c compat/daemon.c compat/forkpty-aix.c \
compat/getopt_long.c compat/bsd-poll.c
CFLAGS+= -DNO_TREE_H -DNO_ASPRINTF -DNO_QUEUE_H -DNO_VSYSLOG \
-DNO_PROGNAME -DNO_STRLCPY -DNO_STRLCAT -DNO_STRTONUM \
-DNO_SETPROCTITLE -DNO_QUEUE_H -DNO_TREE_H -DNO_FORKPTY -DNO_FGETLN \
-DBROKEN_GETOPT -DBROKEN_POLL -DNO_PATHS_H
LDFLAGS+= -L/usr/local/lib
endif
ifeq ($(shell uname),IRIX64)
INCDIRS+= -Icompat -I/usr/local/include/ncurses
SRCS+= compat/strlcpy.c compat/strtonum.c compat/daemon.c \
compat/asprintf.c compat/fgetln.c compat/forkpty-irix.c
CFLAGS+= -DNO_STRLCPY -DNO_STRTONUM -DNO_TREE_H -DNO_SETPROCTITLE \
-DNO_DAEMON -DNO_FORKPTY -DNO_PROGNAME -DNO_ASPRINTF -DNO_FGETLN \
-DBROKEN_VSNPRINTF -D_SGI_SOURCE -std=c99
LDFLAGS+= -L/usr/local/lib
LIBS+= -lgen
endif
ifeq ($(shell uname),SunOS)
INCDIRS+= -Icompat -I/usr/local/include/ncurses
SRCS+= compat/strtonum.c compat/daemon.c compat/forkpty-sunos.c \
compat/asprintf.c compat/fgetln.c compat/vis.c
CFLAGS+= -DNO_STRTONUM -DNO_TREE_H -DNO_PATHS_H -DNO_SETPROCTITLE \
-DNO_DAEMON -DNO_FORKPTY -DNO_PROGNAME -DNO_ASPRINTF -DNO_FGETLN
LDFLAGS+= -L/usr/local/lib
LIBS+= -lsocket -lnsl
endif
ifeq ($(shell uname),Darwin)
INCDIRS+= -Icompat
SRCS+= compat/strtonum.c compat/bsd-poll.c compat/vis.c
CFLAGS+= -DNO_STRTONUM -DNO_SETRESUID -DNO_SETRESGID -DNO_SETPROCTITLE \
-DNO_QUEUE_H -DNO_TREE_H -DBROKEN_POLL
endif
ifeq ($(shell uname),Linux)
INCDIRS+= -Icompat
SRCS+= compat/strlcpy.c compat/strlcat.c compat/strtonum.c \
compat/fgetln.c compat/getopt_long.c compat/vis.c
CFLAGS+= $(shell getconf LFS_CFLAGS) -D_GNU_SOURCE \
-DNO_STRLCPY -DNO_STRLCAT -DNO_STRTONUM -DNO_SETPROCTITLE \
-DNO_QUEUE_H -DNO_TREE_H -DUSE_PTY_H -DNO_FGETLN \
-DBROKEN_GETOPT -std=c99
LIBS+= -lcrypt -lutil
endif
OBJS= $(patsubst %.c,%.o,$(SRCS)) OBJS= $(patsubst %.c,%.o,$(SRCS))
CLEANFILES= ${PROG} *.o .depend *~ ${PROG}.core *.log compat/*.o index.html all: tmux
CPPFLAGS:= ${INCDIRS} ${CPPFLAGS} tmux: $(OBJS)
$(CC) $(LDFLAGS) -o tmux $+ $(LIBS)
all: $(PROG) depend: $(SRCS)
$(CC) $(CPPFLAGS) $(CFLAGS) -MM $(SRCS) > .depend
$(PROG): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $+ $(LIBS)
depend: $(SRCS)
$(CC) $(CPPFLAGS) $(CFLAGS) -MM $(SRCS) > .depend
install:
$(INSTALLDIR) $(DESTDIR)$(PREFIX)/bin
$(INSTALLBIN) $(PROG) $(DESTDIR)$(PREFIX)/bin/$(PROG)
$(INSTALLDIR) $(DESTDIR)$(PREFIX)/man/man1
$(INSTALLMAN) $(PROG).1 $(DESTDIR)$(PREFIX)/man/man1/$(PROG).1
clean: clean:
rm -f $(CLEANFILES) rm -f tmux *.o *~ *.core *.log compat/*.o
clean-depend:
rm -f .depend
clean-all: clean clean-depend
rm -f config.h config.mk
install: all
$(INSTALLDIR) $(DESTDIR)$(PREFIX)/bin
$(INSTALLBIN) tmux $(DESTDIR)$(PREFIX)/bin/tmux
$(INSTALLDIR) $(DESTDIR)$(PREFIX)/man/man1
$(INSTALLMAN) tmux.1 $(DESTDIR)$(PREFIX)/man/man1/tmux.1
-include .depend

160
Makefile
View File

@@ -1,158 +1,68 @@
# $Id: Makefile,v 1.121 2009-04-21 20:10:22 nicm Exp $ # $Id: Makefile,v 1.149 2009-09-20 18:54:21 nicm Exp $
.SUFFIXES: .c .o .y .h .SUFFIXES: .c .o
.PHONY: clean update-index.html upload-index.html .PHONY: clean
PROG= tmux VERSION= 1.0
VERSION= 0.8
OS!= uname
REL!= uname -r
DATE!= date +%Y%m%d-%H%M
#FDEBUG= 1 #FDEBUG= 1
META?= \002 # C-b CC?= cc
CFLAGS+= -DBUILD="\"$(VERSION)\""
LDFLAGS+= -L/usr/local/lib
LIBS+=
SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
xmalloc.c xmalloc-debug.c input.c input-keys.c \
screen.c screen-write.c screen-redraw.c \
grid.c grid-view.c \
window.c session.c log.c client.c client-msg.c client-fn.c cfg.c \
layout.c key-string.c key-bindings.c resize.c arg.c mode-key.c \
cmd.c cmd-generic.c cmd-string.c cmd-list.c \
cmd-detach-client.c cmd-list-sessions.c cmd-new-window.c cmd-bind-key.c \
cmd-unbind-key.c cmd-previous-window.c cmd-last-window.c cmd-list-keys.c \
cmd-set-option.c cmd-rename-window.c cmd-select-window.c \
cmd-list-windows.c cmd-attach-session.c cmd-send-prefix.c \
cmd-refresh-client.c cmd-kill-window.c cmd-list-clients.c \
cmd-link-window.c cmd-unlink-window.c cmd-next-window.c cmd-send-keys.c \
cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \
cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c cmd-copy-mode.c \
cmd-paste-buffer.c cmd-new-session.c cmd-start-server.c \
cmd-kill-server.c cmd-set-window-option.c cmd-show-options.c \
cmd-show-window-options.c cmd-command-prompt.c cmd-set-buffer.c \
cmd-show-buffer.c cmd-list-buffers.c cmd-delete-buffer.c \
cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \
cmd-respawn-window.c cmd-source-file.c cmd-server-info.c \
cmd-clock-mode.c cmd-lock-server.c cmd-set-password.c \
cmd-save-buffer.c cmd-select-pane.c cmd-split-window.c \
cmd-resize-pane-up.c cmd-resize-pane-down.c cmd-kill-pane.c \
cmd-up-pane.c cmd-down-pane.c cmd-choose-window.c cmd-choose-session.c \
cmd-suspend-client.c cmd-find-window.c cmd-load-buffer.c \
cmd-copy-buffer.c cmd-break-pane.c cmd-swap-pane.c cmd-next-layout.c \
cmd-rotate-window.c \
window-clock.c window-scroll.c window-more.c window-copy.c \
window-choose.c \
options.c options-cmd.c paste.c colour.c utf8.c clock.c \
tty.c tty-term.c tty-keys.c tty-write.c util.c names.c attributes.c \
osdep-unknown.c osdep-openbsd.c osdep-freebsd.c osdep-linux.c \
osdep-darwin.c osdep-netbsd.c
CC?= c
INCDIRS+= -I. -I- -I/usr/local/include
CFLAGS+= -DMETA="'${META}'"
.ifdef PROFILE
# Don't use ccache
CC= /usr/bin/gcc
CFLAGS+= -pg -DPROFILE -O0
.endif
.ifdef FDEBUG .ifdef FDEBUG
CFLAGS+= -g -ggdb -DDEBUG CFLAGS+= -g -ggdb -DDEBUG
LDFLAGS+= -Wl,-E
CFLAGS+= -DBUILD="\"$(VERSION) ($(DATE))\""
.else
CFLAGS+= -DBUILD="\"$(VERSION)\""
.endif
#CFLAGS+= -pedantic -std=c99
CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2 CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
.endif
# This sort of sucks but gets rid of the stupid warning and should work on
# most platforms...
CCV!= (LC_ALL=C ${CC} -v 2>&1|awk '/gcc version 4|clang/') || true
.if empty(CCV)
CPPFLAGS:= -I. -I- -I/usr/local/include ${CPPFLAGS}
.else
CPPFLAGS:= -iquote. -I/usr/local/include ${CPPFLAGS}
.ifdef FDEBUG
CFLAGS+= -Wno-pointer-sign
.endif
.endif
PREFIX?= /usr/local PREFIX?= /usr/local
INSTALLDIR= install -d INSTALLDIR= install -d
INSTALLBIN= install -g bin -o root -m 555 INSTALLBIN= install -g bin -o root -m 555
INSTALLMAN= install -g bin -o root -m 444 INSTALLMAN= install -g bin -o root -m 444
LDFLAGS+= -L/usr/local/lib SRCS!= echo *.c|sed 's|osdep-[a-z0-9]*.c||g'
.ifdef PROFILE .include "config.mk"
LDFLAGS+= -pg OBJS= ${SRCS:S/.c/.o/}
.endif
LIBS+= -lutil -lncurses
# FreeBSD and DragonFly
.if ${OS} == "FreeBSD" || ${OS} == "DragonFly"
INCDIRS+= -Icompat
SRCS+= compat/vis.c
CFLAGS+= -DUSE_LIBUTIL_H -DNO_QUEUE_H -DNO_TREE_H
LIBS+= -lcrypt
.endif
# NetBSD
.if ${OS} == "NetBSD"
INCDIRS= -Icompat
SRCS+= compat/strtonum.c compat/vis.c
LIBS+= -lcrypt
CFLAGS+=-DNO_STRTONUM
.endif
OBJS= ${SRCS:S/.c/.o/:S/.y/.o/}
DISTDIR= ${PROG}-${VERSION}
DISTFILES= *.[chyl] Makefile GNUmakefile *.[1-9] NOTES TODO CHANGES FAQ \
`find examples compat -type f -and ! -path '*CVS*'`
CLEANFILES= ${PROG} *.o .depend *~ ${PROG}.core *.log compat/*.o index.html
CPPFLAGS:= ${INCDIRS} ${CPPFLAGS}
.c.o: .c.o:
${CC} ${CPPFLAGS} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET} ${CC} ${CPPFLAGS} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
.y.o: all: tmux
${YACC} ${.IMPSRC}
${CC} ${CPPFLAGS} ${CFLAGS} -c y.tab.c -o ${.TARGET}
all: ${PROG} tmux: ${OBJS}
${CC} ${LDFLAGS} -o tmux ${OBJS} ${LIBS}
${PROG}: ${OBJS}
${CC} ${LDFLAGS} -o ${PROG} ${OBJS} ${LIBS}
depend: depend:
mkdep ${CPPFLAGS} ${CFLAGS} ${SRCS:M*.c} mkdep ${CPPFLAGS} ${CFLAGS} ${SRCS:M*.c}
dist: clean
grep '^#FDEBUG=' Makefile
grep '^#FDEBUG=' GNUmakefile
[ "`(grep '^VERSION' Makefile; grep '^VERSION' GNUmakefile)| \
uniq -u`" = "" ]
tar -zc \
-s '/.*/${DISTDIR}\/\0/' \
-f ${DISTDIR}.tar.gz ${DISTFILES}
lint:
lint -chvx ${CFLAGS:M-D*} ${SRCS:M*.c}
clean: clean:
rm -f ${CLEANFILES} rm -f tmux *.o *~ *.core *.log compat/*.o
upload-index.html: update-index.html clean-depend:
scp index.html images/*.png \ rm -f .depend
nicm,tmux@web.sf.net:/home/groups/t/tm/tmux/htdocs
rm -f images/small-*
update-index.html: clean-all: clean clean-depend
(cd images && \ rm -f config.h config.mk
rm -f small-* && \
for i in *.png; do \
convert "$$i" -resize 200x150 "small-$$i"; \
done \
)
sed "s/%%VERSION%%/${VERSION}/g" index.html.in >index.html
install: all install: all
${INSTALLDIR} ${DESTDIR}${PREFIX}/bin ${INSTALLDIR} ${DESTDIR}${PREFIX}/bin
${INSTALLBIN} ${PROG} ${DESTDIR}${PREFIX}/bin/ ${INSTALLBIN} tmux ${DESTDIR}${PREFIX}/bin/
${INSTALLDIR} ${DESTDIR}${PREFIX}/man/man1 ${INSTALLDIR} ${DESTDIR}${PREFIX}/man/man1
${INSTALLMAN} ${PROG}.1 ${DESTDIR}${PREFIX}/man/man1/ ${INSTALLMAN} tmux.1 ${DESTDIR}${PREFIX}/man/man1/

29
NOTES
View File

@@ -4,9 +4,10 @@ tmux is a "terminal multiplexer", it enables a number of terminals (or windows)
to be accessed and controlled from a single terminal. tmux is intended to be a to be accessed and controlled from a single terminal. tmux is intended to be a
simple, modern, BSD-licensed alternative to programs such as GNU screen. simple, modern, BSD-licensed alternative to programs such as GNU screen.
This 0.8 release runs on OpenBSD, FreeBSD, Linux and OS X and may still run on This 0.9 release runs on OpenBSD, FreeBSD, NetBSD, Linux and OS X and may still
Solaris (although it hasn't been tested in a while). It is usable, although run on Solaris and AIX (although they hasn't been tested in a while). It is
there remain a number of missing features and some remaining bugs are expected. usable, although there remain a number of missing features and some remaining
bugs are expected.
If upgrading from 0.5, PLEASE NOTE the following configuration file changes: it If upgrading from 0.5, PLEASE NOTE the following configuration file changes: it
is now required to pass the -g flag to set-option or set-window-option to set is now required to pass the -g flag to set-option or set-window-option to set
@@ -40,11 +41,6 @@ The following is a summary of major features implemented in this version:
- A configuration file. - A configuration file.
- UTF-8 support. - UTF-8 support.
And major missing features:
- Proper mouse support.
- No support for programs changing termios(4) settings or other tty(4) ioctls.
A more extensive, but rough, todo list is included in the TODO file. A more extensive, but rough, todo list is included in the TODO file.
tmux also depends on several features of the client terminal (TERM), if these tmux also depends on several features of the client terminal (TERM), if these
@@ -55,8 +51,10 @@ xterm-color or rxvt for colour.
tmux supports UTF-8. To use it, the utf8 option must be set on each window; tmux supports UTF-8. To use it, the utf8 option must be set on each window;
this may be turned on for all windows by setting it as a global option, see this may be turned on for all windows by setting it as a global option, see
tmux(1) and the FAQ file. In addition, when starting tmux or attaching to an tmux(1) and the FAQ file. As of 0.9, tmux attempts to autodetect a
existing session from a UTF-8-capable terminal, the -u flag must be specified. UTF-8-capable terminal by checking the LC_ALL, LC_CTYPE and LANG environment
variables. list-clients may be used to check if this is detected correctly; if
not, the -u command-line flag may be specified.
A Vim syntax file is available in the examples directory. To install it: A Vim syntax file is available in the examples directory. To install it:
@@ -74,15 +72,6 @@ A Vim syntax file is available in the examples directory. To install it:
For debugging, running tmux with -v or -vv will generate server and client log For debugging, running tmux with -v or -vv will generate server and client log
files in the current directory. files in the current directory.
The CVS HEAD version of tmux often has additional features from the release
versions; if interested, testing it is encouraged. It can be obtained by
anonymous CVS from SourceForge:
$ cvs -d:pserver:anoncvs@tmux.cvs.sf.net:/cvsroot/tmux co tmux
If running CVS HEAD, please note it is development code and there may be bugs
and undocumented features; please read the CHANGES file for information.
tmux mailing lists are available; visit: tmux mailing lists are available; visit:
https://sourceforge.net/mail/?group_id=200378 https://sourceforge.net/mail/?group_id=200378
@@ -94,4 +83,4 @@ welcome. Please send by email to:
-- Nicholas Marriott <nicm@users.sf.net> -- Nicholas Marriott <nicm@users.sf.net>
$Id: NOTES,v 1.45 2009-04-21 20:06:12 nicm Exp $ $Id: NOTES,v 1.49 2009-07-06 18:53:24 nicm Exp $

143
TODO
View File

@@ -1,39 +1,21 @@
- line mode/char-at-a-time mode a la telnet?
- handle ioctl/termios stuff on window sockets
- figure out once and for all what is going on with backspace and del
backspace should be translated per the termios setting.
del passed through?
- window creation/idle time - window creation/idle time
- profile/optimise, particularly (i suspect) input.c
- could use bsearch all over the place or get rid of smaller tables (clientmsg)
- better errors when creating new windows/sessions (how?) - better errors when creating new windows/sessions (how?)
- Implicitly add exec to the commands for new windows (switch to disable it) - implicitly add exec to the commands for new windows (switch to disable it)?
- it would be nice to have multichar commands so you could have C-b K K for - it would be nice to have multichar commands eg C-b K K
kill-window to limit accidental presses
- commands: - commands:
extend list-clients to list clients attached to a session (-a for all?) extend list-clients to list clients attached to a session (-a for all?)
bring back detach-session to detach all clients on a session? bring back detach-session to detach all clients on a session?
clone-session command to link all windows to a new session
- allow fnmatch for -c, so that you can, eg, detach all clients - allow fnmatch for -c, so that you can, eg, detach all clients
- bind non prefix keys
- garbage collect window history (100 lines at a time?) if it hasn't been used - garbage collect window history (100 lines at a time?) if it hasn't been used
in $x time (need window creation/use times) in $x time (need window creation/use times)
- lift SHRT_MAX limits for history - lift SHRT_MAX limits for history?
- audit copy/scroll and other modes for problems with very small windows - better mode features: search
- split clients into three RB trees by fd: attached/unattached/dead?
or tailqs? what would be fastest per-char?
- c/p is still borken in some ways
- better mode features: search, back word, forward word, etc
- flags to centre screen in window - flags to centre screen in window
- better terminal emulation (identify, insert mode, some other bits) - better terminal emulation
- when resizing, use history
- audit for leftover/unused code
- activity/bell should be per-window not per-link? what if it is cur win in - activity/bell should be per-window not per-link? what if it is cur win in
session not being watched? session not being watched?
- tidy up window modes
- next prev word etc in command prompt; also ^K - next prev word etc in command prompt; also ^K
- many more info() displays for various things - many more info() displays for various things
- vi half page scroll
- backspace should perhaps wrap backwards over newlines which were not moved - backspace should perhaps wrap backwards over newlines which were not moved
down by a newline: screen and the OS X terminal does this but xterm and most down by a newline: screen and the OS X terminal does this but xterm and most
others do not. this might be hard: a flag for each grid line (top bit of size others do not. this might be hard: a flag for each grid line (top bit of size
@@ -41,63 +23,84 @@
unwrapping unwrapping
- input.c is too complicated. simplify? - input.c is too complicated. simplify?
- use a better termcap internally instead of screen, perhaps xterm - use a better termcap internally instead of screen, perhaps xterm
- a command to display the status line briefly when it is turned off
- FAQ "Can I have some examples of cool things I can do with tmux?" -- linkw,
more??
- kill all but current pane - kill all but current pane
- fix rxvt cursor fg issue (text under cursor can have non-white fg) - fix rxvt cursor fg issue (text under cursor can have non-white fg)
- key handling sucks a bit and needs to be reworked
- some people find first window being 0 rather than 1 is awkward on the
keyboard. what about a new-window-index option that sets the base at which
tmux starts numbering new windows, then they can do: set -g new-window-index
1; bind 0 selectw -t:10
- some way to change status line colours based on something? command?
- client sx/sy should be in tty, then can let the terminal wrap at edge - client sx/sy should be in tty, then can let the terminal wrap at edge
to allow xterm to pick up it should be one line for its c/p to allow xterm to pick up it should be one line for its c/p
- should be able to move to a hidden pane and it would be moved into view. pane - 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 number in status line/top-right would be cool for this
- command to run something without a window at all - output to
window-more. what for? isnt this the same as doing it w/ splitw/neww now?
- command to purge window history? or apply history-limit changes?
- clone session command
- make command sequences more usable: don't require space around ;, handle
errors better
- would be nice if tmux could be the shell (tmux attach, but hard link to tmux
binary as "tmuxsh" or wrapper script?) -- problems with tty dev permissions
- support other mouse modes (highlight etc) and use it in copy mode - support other mouse modes (highlight etc) and use it in copy mode
- set-remain-on-exit is a bit of a hack, some way to do it generically? - set-remain-on-exit is a bit of a hack, some way to do it generically?
- set-option should be set-session-option and should be overall global options - set-option should be set-session-option and should be overall global options
for stuff like mode keys? for stuff like mode keys?
- a confirm-before command which asks "Are you sure? (y/n)" before executing also quiet, utf8 and maybe other flags?
command, eg bind-key "&" confirm-before "kill-window" -g is a bit unexpected in conf file
- might be nice if attach-session behaved like switch-client inside an
existing client
- key to switch to copy mode from scroll mode
- attach should have a flag to create session if it doesn't exist
- clear window title on exit - clear window title on exit
- better support for stupid margin terminals. strcmp for cons25 sucks, how can
these be autodetected?
- refer to windows by name etc (duplicates? fnmatch?)
- the output code (tty.c) could do with optimisation depending on term - the output code (tty.c) could do with optimisation depending on term
capibilities capibilities
- resize-pane-up/down should be resize-pane -U/-D. ditto up-pane/down-pane - would be nice to be able to use "--" to mark start of command w/ neww etc
should be select-pane -U/-D to avoid quoting
- layout/split stuff: - goto line and search history in copy/scroll modes
horiz split command, and similar resizing commands as for vert split - clone session command
display the layout in a readable format somewhere - make command sequences more usable: don't require space after ;, handle
previous-layout command errors better
select-layout command - key to switch to copy mode from scroll mode
make manual layout a bit less of a hack and make it handle a grid - attach should have a flag to create session if it doesn't exist
should the layout be a window option??? - rename split-window -> split-pane??
more layouts - fix UTF-8 guesswork on sparc64, improve tty checks
better resizing of shells when changing layout - choice and more mode would be better per client than per window?
find and fix bug with clear screen after horiz split - hooks to which commands may be attached, for example: tmux add-hook
speed improvements? -- still too slow over ssh! "new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
hardcoded 81 for left-vertical is nasty $HOME/.tmux-session.conf
- test bug sshing from freebsd console (tom iirc?) - get it passing all the vttest tests that don't require resizing the terminal
- fix build on solaris 10 - esc seq to set window title should be documented and should set
- rotate-window has redraw bugs... :-/ automatic-rename
- way to set socket path from config file
(hopefully) for 0.8, in no particular order: - XXX once env stuff is in, default-path and VISUAL/EDITOR should be picked up
- nothing! when session is started
- what about utmp etc? can tmux update it like screen? setgid?
- H/M/L commands in copy mode with vi-keys, for jumping to the top/middle/last
line on the screen
- split list-windows into separate list-windows and list-panes
- warts on current naming:
- display-time but message-fg/bg/attr
- list-* vs show-*
- server-info
- up-pane/down-pane/swap-pane -U/swap-pane -D vs next-*/previous-*
- pcvt25 doesn't work properly, why? (bce?)
- tidy up and prioritise todo list ;-)
- it is only possible to specify 8 colours to fg/bg options; should be able to
set 256 as well
- neww and attach can create a session if none exists?
would work fine with config file since
- a way for force-width/height to apply to only one pane (how?)
- **** a command to run something without a window and send any output to the
window-more. if no output, info() a line saying "'%s' returned %d". so i can
bind mpc control commands to function keys ;-)
- command to list what is actually running in each window with command line,
pid (need some adaption of the osdep code)
- string option to change/remove the symbols (*-+ etc) in status line
- support for bce
- it would be nice if the start/end line keys in copy mode were aware of
wrapped lines
- per session locking
- some way to force a screen to use the entire terminal even if it is forced
to be smaller by other clients. pan smaller terminal? (like screen F)
-- idea of a "view" onto a window, need base x/y offsets
for redraw
- a window option which means data is echoed to all panes in a window
- support running tmux from inside tmux [#(), if-shell] --
generic system-like function which may take a callback
also sets up environment (TMUX) and has a timeout
for #(): command schedular, status line queues it with a time, run in
main loop, and uses most recent result -- can also be used for persistent
commands which never exit just continually output
for if-shell, callback??
- handle resize better in copy mode
- way to copy stuff that is off screen due to resize
- fix line wrapping c&p problems in xterm etc
- a way to address panes by name ("top-left") and position ("0,0")
- ability to specify multiple prefix keys
- commands should be able to succeed or fail and have || or && for command
lists
- support the mouse wheel to scroll through history

194
arg.c
View File

@@ -1,194 +0,0 @@
/* $Id: arg.c,v 1.5 2008-08-28 17:45:25 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <fnmatch.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
struct client *arg_lookup_client(const char *);
struct session *arg_lookup_session(const char *);
struct client *
arg_lookup_client(const char *name)
{
struct client *c;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL && strcmp(name, c->tty.path) == 0)
return (c);
}
return (NULL);
}
struct session *
arg_lookup_session(const char *name)
{
struct session *s, *newest = NULL;
struct timeval *tv;
u_int i;
tv = NULL;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i);
if (s == NULL || fnmatch(name, s->name, 0) != 0)
continue;
if (tv == NULL || timercmp(&s->tv, tv, >)) {
newest = s;
tv = &s->tv;
}
}
return (newest);
}
struct client *
arg_parse_client(const char *arg)
{
struct client *c;
char *arg2;
size_t n;
if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) {
arg2 = xstrdup(arg);
/* Trim a trailing : if any from the argument. */
n = strlen(arg2);
if (arg2[n - 1] == ':')
arg2[n - 1] = '\0';
/* Try and look up the client name. */
c = arg_lookup_client(arg2);
xfree(arg2);
return (c);
}
return (NULL);
}
struct session *
arg_parse_session(const char *arg)
{
struct session *s;
struct client *c;
char *arg2;
size_t n;
if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) {
arg2 = xstrdup(arg);
/* Trim a trailing : if any from the argument. */
n = strlen(arg2);
if (arg2[n - 1] == ':')
arg2[n - 1] = '\0';
/* See if the argument matches a session. */
if ((s = arg_lookup_session(arg2)) != NULL) {
xfree(arg2);
return (s);
}
/* If not try a client. */
if ((c = arg_lookup_client(arg2)) != NULL) {
xfree(arg2);
return (c->session);
}
xfree(arg2);
}
return (NULL);
}
int
arg_parse_window(const char *arg, struct session **s, int *idx)
{
char *arg2, *ptr;
const char *errstr;
*idx = -1;
/* Handle no argument or a single :. */
if (arg == NULL || (arg[0] == ':' && arg[1] == '\0')) {
*s = arg_parse_session(NULL);
return (0);
}
/* Find the separator if any. */
arg2 = xstrdup(arg);
ptr = strrchr(arg2, ':');
/*
* If it is first, this means no session name, so use current session
* and try to convert the rest as index.
*/
if (ptr == arg2) {
*idx = strtonum(ptr + 1, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xfree(arg2);
return (1);
}
xfree(arg2);
*s = arg_parse_session(NULL);
return (0);
}
/* If missing, try as an index, else look up immediately. */
if (ptr == NULL) {
*idx = strtonum(arg2, 0, INT_MAX, &errstr);
if (errstr == NULL) {
/* This is good as an index; use current session. */
xfree(arg2);
*s = arg_parse_session(NULL);
return (0);
}
*idx = -1;
goto lookup;
}
/* If last, strip it and look up as a session. */
if (ptr[1] == '\0') {
*ptr = '\0';
goto lookup;
}
/* Present but not first and not last. Break and convert both. */
*ptr = '\0';
*idx = strtonum(ptr + 1, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xfree(arg2);
return (1);
}
lookup:
/* Look up as session. */
*s = arg_parse_session(arg2);
xfree(arg2);
if (*s == NULL)
return (1);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: attributes.c,v 1.1 2009-01-27 20:22:33 nicm Exp $ */ /* $Id: attributes.c,v 1.2 2009-06-25 15:25:45 nicm Exp $ */
/* /*
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org> * Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
@@ -45,7 +45,8 @@ attributes_tostring(u_char ch)
strlcat(buf, "hidden,", sizeof (buf)); strlcat(buf, "hidden,", sizeof (buf));
if (ch & GRID_ATTR_ITALICS) if (ch & GRID_ATTR_ITALICS)
strlcat(buf, "italics,", sizeof (buf)); strlcat(buf, "italics,", sizeof (buf));
*(strrchr(buf, ',')) = '\0'; if (*buf)
*(strrchr(buf, ',')) = '\0';
return (buf); return (buf);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: buffer-poll.c,v 1.10 2008-09-09 22:16:36 nicm Exp $ */ /* $Id: buffer-poll.c,v 1.16 2009-08-19 09:28:10 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -23,39 +23,17 @@
#include "tmux.h" #include "tmux.h"
/* Set up pollfd for buffers. */
void
buffer_set(
struct pollfd *pfd, int fd, unused struct buffer *in, struct buffer *out)
{
pfd->fd = fd;
pfd->events = POLLIN;
if (BUFFER_USED(out) > 0)
pfd->events |= POLLOUT;
}
/* Fill buffers from socket based on poll results. */ /* Fill buffers from socket based on poll results. */
int int
buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out) buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
{ {
ssize_t n; ssize_t n;
#if 0
log_debug("buffer_poll (%ld): fd=%d, revents=%d; out=%zu in=%zu",
(long) getpid(),
pfd->fd, pfd->revents, BUFFER_USED(out), BUFFER_USED(in));
#endif
#ifndef BROKEN_POLL
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP)) if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
return (-1); return (-1);
#endif
if (pfd->revents & POLLIN) { if (pfd->revents & POLLIN) {
buffer_ensure(in, BUFSIZ); buffer_ensure(in, BUFSIZ);
n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in)); n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in));
#if 0
log_debug("buffer_poll: fd=%d, read=%zd", pfd->fd, n);
#endif
if (n == 0) if (n == 0)
return (-1); return (-1);
if (n == -1) { if (n == -1) {
@@ -66,9 +44,6 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
} }
if (BUFFER_USED(out) > 0 && pfd->revents & POLLOUT) { if (BUFFER_USED(out) > 0 && pfd->revents & POLLOUT) {
n = write(pfd->fd, BUFFER_OUT(out), BUFFER_USED(out)); n = write(pfd->fd, BUFFER_OUT(out), BUFFER_USED(out));
#if 0
log_debug("buffer_poll: fd=%d, write=%zd", pfd->fd, n);
#endif
if (n == -1) { if (n == -1) {
if (errno != EINTR && errno != EAGAIN) if (errno != EINTR && errno != EAGAIN)
return (-1); return (-1);
@@ -77,23 +52,3 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
} }
return (0); return (0);
} }
/* Flush buffer output to socket. */
void
buffer_flush(int fd, struct buffer *in, struct buffer *out)
{
struct pollfd pfd;
while (BUFFER_USED(out) > 0) {
buffer_set(&pfd, fd, in, out);
if (poll(&pfd, 1, INFTIM) == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
fatal("poll failed");
}
if (buffer_poll(&pfd, in, out) != 0)
break;
}
}

View File

@@ -1,4 +1,4 @@
/* $Id: buffer.c,v 1.5 2008-08-07 20:20:52 nicm Exp $ */ /* $Id: buffer.c,v 1.8 2009-08-21 21:09:13 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -47,14 +47,6 @@ buffer_destroy(struct buffer *b)
xfree(b); xfree(b);
} }
/* Empty a buffer. */
void
buffer_clear(struct buffer *b)
{
b->size = 0;
b->off = 0;
}
/* Ensure free space for size in buffer. */ /* Ensure free space for size in buffer. */
void void
buffer_ensure(struct buffer *b, size_t size) buffer_ensure(struct buffer *b, size_t size)
@@ -91,18 +83,6 @@ buffer_add(struct buffer *b, size_t size)
b->size += size; b->size += size;
} }
/* Reverse buffer add. */
void
buffer_reverse_add(struct buffer *b, size_t size)
{
if (size == 0)
fatalx("zero size");
if (size > b->size)
fatalx("underflow");
b->size -= size;
}
/* Adjust buffer after data removed. */ /* Adjust buffer after data removed. */
void void
buffer_remove(struct buffer *b, size_t size) buffer_remove(struct buffer *b, size_t size)
@@ -116,57 +96,10 @@ buffer_remove(struct buffer *b, size_t size)
b->off += size; b->off += size;
} }
/* Reverse buffer remove. */
void
buffer_reverse_remove(struct buffer *b, size_t size)
{
if (size == 0)
fatalx("zero size");
if (size > b->off)
fatalx("overflow");
b->size += size;
b->off -= size;
}
/* Insert a section into the buffer. */
void
buffer_insert_range(struct buffer *b, size_t base, size_t size)
{
if (size == 0)
fatalx("zero size");
if (base > b->size)
fatalx("range outside buffer");
buffer_ensure(b, size);
memmove(b->base + b->off + base + size,
b->base + b->off + base, b->size - base);
b->size += size;
}
/* Delete a section from the buffer. */
void
buffer_delete_range(struct buffer *b, size_t base, size_t size)
{
if (size == 0)
fatalx("zero size");
if (size > b->size)
fatalx("size too big");
if (base + size > b->size)
fatalx("range outside buffer");
memmove(b->base + b->off + base,
b->base + b->off + base + size, b->size - base - size);
b->size -= size;
}
/* Copy data into a buffer. */ /* Copy data into a buffer. */
void void
buffer_write(struct buffer *b, const void *data, size_t size) buffer_write(struct buffer *b, const void *data, size_t size)
{ {
if (size == 0)
fatalx("zero size");
buffer_ensure(b, size); buffer_ensure(b, size);
memcpy(BUFFER_IN(b), data, size); memcpy(BUFFER_IN(b), data, size);
buffer_add(b, size); buffer_add(b, size);
@@ -191,17 +124,7 @@ buffer_write8(struct buffer *b, uint8_t n)
{ {
buffer_ensure(b, 1); buffer_ensure(b, 1);
BUFFER_IN(b)[0] = n; BUFFER_IN(b)[0] = n;
buffer_add(b, 1); b->size++;
}
/* Store a 16-bit value. */
void
buffer_write16(struct buffer *b, uint16_t n)
{
buffer_ensure(b, 2);
BUFFER_IN(b)[0] = n & 0xff;
BUFFER_IN(b)[1] = n >> 8;
buffer_add(b, 2);
} }
/* Extract an 8-bit value. */ /* Extract an 8-bit value. */
@@ -214,14 +137,3 @@ buffer_read8(struct buffer *b)
buffer_remove(b, 1); buffer_remove(b, 1);
return (n); return (n);
} }
/* Extract a 16-bit value. */
uint16_t
buffer_read16(struct buffer *b)
{
uint16_t n;
n = BUFFER_OUT(b)[0] | (BUFFER_OUT(b)[1] << 8);
buffer_remove(b, 2);
return (n);
}

22
cfg.c
View File

@@ -1,4 +1,4 @@
/* $Id: cfg.c,v 1.15 2009-03-31 22:23:43 nicm Exp $ */ /* $Id: cfg.c,v 1.22 2009-08-24 16:27:03 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -17,6 +17,7 @@
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
@@ -29,7 +30,6 @@
* argv array and executed as a command. * argv array and executed as a command.
*/ */
char *cfg_string(FILE *, char, int);
void printflike2 cfg_print(struct cmd_ctx *, const char *, ...); void printflike2 cfg_print(struct cmd_ctx *, const char *, ...);
void printflike2 cfg_error(struct cmd_ctx *, const char *, ...); void printflike2 cfg_error(struct cmd_ctx *, const char *, ...);
@@ -51,7 +51,7 @@ cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...)
} }
int int
load_cfg(const char *path, char **cause) load_cfg(const char *path, struct cmd_ctx *ctxin, char **cause)
{ {
FILE *f; FILE *f;
u_int n; u_int n;
@@ -87,16 +87,20 @@ load_cfg(const char *path, char **cause)
continue; continue;
cfg_cause = NULL; cfg_cause = NULL;
ctx.msgdata = NULL; if (ctxin == NULL) {
ctx.cursession = NULL; ctx.msgdata = NULL;
ctx.curclient = NULL; ctx.curclient = NULL;
ctx.cmdclient = NULL;
} else {
ctx.msgdata = ctxin->msgdata;
ctx.curclient = ctxin->curclient;
ctx.cmdclient = ctxin->cmdclient;
}
ctx.error = cfg_error; ctx.error = cfg_error;
ctx.print = cfg_print; ctx.print = cfg_print;
ctx.info = cfg_print; ctx.info = cfg_print;
ctx.cmdclient = NULL;
cfg_cause = NULL; cfg_cause = NULL;
cmd_list_exec(cmdlist, &ctx); cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
@@ -112,6 +116,8 @@ load_cfg(const char *path, char **cause)
return (0); return (0);
error: error:
if (line != NULL)
xfree(line);
fclose(f); fclose(f);
xasprintf(&ptr, "%s: %s at line %u", path, *cause, n); xasprintf(&ptr, "%s: %s at line %u", path, *cause, n);

View File

@@ -1,4 +1,4 @@
/* $Id: client-fn.c,v 1.6 2009-03-04 17:24:07 nicm Exp $ */ /* $Id: client-fn.c,v 1.10 2009-08-14 21:04:04 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -20,6 +20,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
@@ -63,30 +64,27 @@ client_fill_session(struct msg_command_data *data)
void void
client_write_server( client_write_server(
struct client_ctx *cctx, enum hdrtype type, void *buf, size_t len) struct client_ctx *cctx, enum msgtype type, void *buf, size_t len)
{ {
struct hdr hdr; imsg_compose(&cctx->ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
hdr.type = type;
hdr.size = len;
buffer_write(cctx->srv_out, &hdr, sizeof hdr);
if (buf != NULL && len > 0)
buffer_write(cctx->srv_out, buf, len);
} }
void void
client_write_server2(struct client_ctx *cctx, client_suspend(void)
enum hdrtype type, void *buf1, size_t len1, void *buf2, size_t len2)
{ {
struct hdr hdr; struct sigaction act;
hdr.type = type; memset(&act, 0, sizeof act);
hdr.size = len1 + len2; sigemptyset(&act.sa_mask);
buffer_write(cctx->srv_out, &hdr, sizeof hdr); act.sa_flags = SA_RESTART;
if (buf1 != NULL && len1 > 0) act.sa_handler = SIG_DFL;
buffer_write(cctx->srv_out, buf1, len1); if (sigaction(SIGTSTP, &act, NULL) != 0)
if (buf2 != NULL && len2 > 0) fatal("sigaction failed");
buffer_write(cctx->srv_out, buf2, len2);
act.sa_handler = sighandler;
if (sigaction(SIGCONT, &act, NULL) != 0)
fatal("sigaction failed");
kill(getpid(), SIGTSTP);
} }

View File

@@ -1,159 +0,0 @@
/* $Id: client-msg.c,v 1.18 2009-01-21 22:47:31 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
int client_msg_fn_detach(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_error(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_shutdown(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_exit(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_exited(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_suspend(struct hdr *, struct client_ctx *, char **);
struct client_msg {
enum hdrtype type;
int (*fn)(struct hdr *, struct client_ctx *, char **);
};
struct client_msg client_msg_table[] = {
{ MSG_DETACH, client_msg_fn_detach },
{ MSG_ERROR, client_msg_fn_error },
{ MSG_EXIT, client_msg_fn_exit },
{ MSG_EXITED, client_msg_fn_exited },
{ MSG_SHUTDOWN, client_msg_fn_shutdown },
{ MSG_SUSPEND, client_msg_fn_suspend },
};
int
client_msg_dispatch(struct client_ctx *cctx, char **error)
{
struct hdr hdr;
struct client_msg *msg;
u_int i;
if (BUFFER_USED(cctx->srv_in) < sizeof hdr)
return (1);
memcpy(&hdr, BUFFER_OUT(cctx->srv_in), sizeof hdr);
if (BUFFER_USED(cctx->srv_in) < (sizeof hdr) + hdr.size)
return (1);
buffer_remove(cctx->srv_in, sizeof hdr);
for (i = 0; i < nitems(client_msg_table); i++) {
msg = client_msg_table + i;
if (msg->type == hdr.type) {
if (msg->fn(&hdr, cctx, error) != 0)
return (-1);
return (0);
}
}
fatalx("unexpected message");
}
int
client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error)
{
if (hdr->size > SIZE_MAX - 1)
fatalx("bad MSG_ERROR size");
*error = xmalloc(hdr->size + 1);
buffer_read(cctx->srv_in, *error, hdr->size);
(*error)[hdr->size] = '\0';
return (-1);
}
int
client_msg_fn_detach(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_DETACH size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_DETACH;
return (0);
}
int
client_msg_fn_shutdown(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_SHUTDOWN size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_SHUTDOWN;
return (0);
}
int
client_msg_fn_exit(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_EXIT size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_EXIT;
return (0);
}
int
client_msg_fn_exited(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_EXITED size");
return (-1);
}
int
client_msg_fn_suspend(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
struct sigaction act;
if (hdr->size != 0)
fatalx("bad MSG_SUSPEND size");
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
act.sa_handler = SIG_DFL;
if (sigaction(SIGTSTP, &act, NULL) != 0)
fatal("sigaction failed");
act.sa_handler = sighandler;
if (sigaction(SIGCONT, &act, NULL) != 0)
fatal("sigaction failed");
kill(getpid(), SIGTSTP);
return (0);
}

230
client.c
View File

@@ -1,4 +1,4 @@
/* $Id: client.c,v 1.46 2009-03-31 22:20:42 nicm Exp $ */ /* $Id: client.c,v 1.70 2009-09-03 21:06:30 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,23 +33,32 @@
#include "tmux.h" #include "tmux.h"
void client_send_environ(struct client_ctx *);
void client_handle_winch(struct client_ctx *); void client_handle_winch(struct client_ctx *);
int int
client_init(char *path, struct client_ctx *cctx, int start_server, int flags) client_init(char *path, struct client_ctx *cctx, int cmdflags, int flags)
{ {
struct sockaddr_un sa; struct sockaddr_un sa;
struct stat sb; struct stat sb;
struct msg_identify_data data; struct msg_identify_data data;
struct winsize ws; struct winsize ws;
size_t size; size_t size;
int mode; int fd, fd2, mode;
struct buffer *b; char *name, *term;
char *name; #ifdef HAVE_SETPROCTITLE
char rpathbuf[MAXPATHLEN];
#endif
#ifdef HAVE_SETPROCTITLE
if (realpath(path, rpathbuf) == NULL)
strlcpy(rpathbuf, path, sizeof rpathbuf);
setproctitle("client (%s)", rpathbuf);
#endif
if (lstat(path, &sb) != 0) { if (lstat(path, &sb) != 0) {
if (start_server && errno == ENOENT) { if (cmdflags & CMD_STARTSERVER && errno == ENOENT) {
if ((cctx->srv_fd = server_start(path)) == -1) if ((fd = server_start(path)) == -1)
goto start_failed; goto start_failed;
goto server_started; goto server_started;
} }
@@ -68,15 +77,14 @@ client_init(char *path, struct client_ctx *cctx, int start_server, int flags)
goto not_found; goto not_found;
} }
if ((cctx->srv_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
fatal("socket"); fatal("socket");
if (connect( if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
cctx->srv_fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
if (errno == ECONNREFUSED) { if (errno == ECONNREFUSED) {
if (unlink(path) != 0 || !start_server) if (unlink(path) != 0 || !(cmdflags & CMD_STARTSERVER))
goto not_found; goto not_found;
if ((cctx->srv_fd = server_start(path)) == -1) if ((fd = server_start(path)) == -1)
goto start_failed; goto start_failed;
goto server_started; goto server_started;
} }
@@ -84,34 +92,40 @@ client_init(char *path, struct client_ctx *cctx, int start_server, int flags)
} }
server_started: server_started:
if ((mode = fcntl(cctx->srv_fd, F_GETFL)) == -1) if ((mode = fcntl(fd, F_GETFL)) == -1)
fatal("fcntl failed"); fatal("fcntl failed");
if (fcntl(cctx->srv_fd, F_SETFL, mode|O_NONBLOCK) == -1) if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl failed"); fatal("fcntl failed");
cctx->srv_in = buffer_create(BUFSIZ); imsg_init(&cctx->ibuf, fd);
cctx->srv_out = buffer_create(BUFSIZ);
if (cmdflags & CMD_SENDENVIRON)
client_send_environ(cctx);
if (isatty(STDIN_FILENO)) { if (isatty(STDIN_FILENO)) {
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
fatal("ioctl(TIOCGWINSZ)"); fatal("ioctl(TIOCGWINSZ)");
data.version = PROTOCOL_VERSION;
data.flags = flags; data.flags = flags;
data.sx = ws.ws_col; data.sx = ws.ws_col;
data.sy = ws.ws_row; data.sy = ws.ws_row;
*data.tty = '\0';
if (getcwd(data.cwd, sizeof data.cwd) == NULL) if (getcwd(data.cwd, sizeof data.cwd) == NULL)
*data.cwd = '\0'; *data.cwd = '\0';
*data.term = '\0';
if ((term = getenv("TERM")) != NULL) {
if (strlcpy(data.term,
term, sizeof data.term) >= sizeof data.term)
*data.term = '\0';
}
*data.tty = '\0';
if ((name = ttyname(STDIN_FILENO)) == NULL) if ((name = ttyname(STDIN_FILENO)) == NULL)
fatal("ttyname failed"); fatal("ttyname failed");
if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty) if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty)
fatalx("ttyname failed"); fatalx("ttyname failed");
b = buffer_create(BUFSIZ); fd2 = dup(STDIN_FILENO);
cmd_send_string(b, getenv("TERM")); imsg_compose(&cctx->ibuf, MSG_IDENTIFY,
client_write_server2(cctx, MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd2, &data, sizeof data);
&data, sizeof data, BUFFER_OUT(b), BUFFER_USED(b));
buffer_destroy(b);
} }
return (0); return (0);
@@ -125,23 +139,41 @@ not_found:
return (1); return (1);
} }
void
client_send_environ(struct client_ctx *cctx)
{
char **var;
struct msg_environ_data data;
for (var = environ; *var != NULL; var++) {
if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
continue;
client_write_server(cctx, MSG_ENVIRON, &data, sizeof data);
}
}
int int
client_main(struct client_ctx *cctx) client_main(struct client_ctx *cctx)
{ {
struct pollfd pfd; struct pollfd pfd;
char *error; int n, nfds;
int xtimeout; /* Yay for ncurses namespace! */
siginit(); siginit();
logfile("client"); logfile("client");
#ifndef NO_SETPROCTITLE
setproctitle("client");
#endif
error = NULL; /*
xtimeout = INFTIM; * imsg_read in the first client poll loop (before the terminal has
while (!sigterm) { * been initialiased) may have read messages into the buffer after the
* MSG_READY switched to here. Process anything outstanding now so poll
* doesn't hang waiting for messages that have already arrived.
*/
if (client_msg_dispatch(cctx) != 0)
goto out;
for (;;) {
if (sigterm)
client_write_server(cctx, MSG_EXITING, NULL, 0);
if (sigchld) { if (sigchld) {
waitpid(WAIT_ANY, NULL, WNOHANG); waitpid(WAIT_ANY, NULL, WNOHANG);
sigchld = 0; sigchld = 0;
@@ -154,32 +186,37 @@ client_main(struct client_ctx *cctx)
sigcont = 0; sigcont = 0;
} }
switch (client_msg_dispatch(cctx, &error)) { pfd.fd = cctx->ibuf.fd;
case -1:
goto out;
case 0:
/* May be more in buffer, don't let poll block. */
xtimeout = 0;
break;
default:
/* Out of data, poll may block. */
xtimeout = INFTIM;
break;
}
pfd.fd = cctx->srv_fd;
pfd.events = POLLIN; pfd.events = POLLIN;
if (BUFFER_USED(cctx->srv_out) > 0) if (cctx->ibuf.w.queued > 0)
pfd.events |= POLLOUT; pfd.events |= POLLOUT;
if (poll(&pfd, 1, xtimeout) == -1) { if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
continue; continue;
fatal("poll failed"); fatal("poll failed");
} }
if (nfds == 0)
continue;
if (buffer_poll(&pfd, cctx->srv_in, cctx->srv_out) != 0) if (pfd.revents & (POLLERR|POLLHUP|POLLNVAL))
goto server_dead; fatalx("socket error");
if (pfd.revents & POLLIN) {
if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) {
cctx->exittype = CCTX_DIED;
break;
}
if (client_msg_dispatch(cctx) != 0)
break;
}
if (pfd.revents & POLLOUT) {
if (msgbuf_write(&cctx->ibuf.w) < 0) {
cctx->exittype = CCTX_DIED;
break;
}
}
} }
out: out:
@@ -187,28 +224,27 @@ out:
printf("[terminated]\n"); printf("[terminated]\n");
return (1); return (1);
} }
switch (cctx->exittype) {
if (cctx->flags & CCTX_SHUTDOWN) { case CCTX_DIED:
printf("[lost server]\n");
return (0);
case CCTX_SHUTDOWN:
printf("[server exited]\n"); printf("[server exited]\n");
return (0); return (0);
} case CCTX_EXIT:
if (cctx->errstr != NULL) {
if (cctx->flags & CCTX_EXIT) { printf("[error: %s]\n", cctx->errstr);
return (1);
}
printf("[exited]\n"); printf("[exited]\n");
return (0); return (0);
} case CCTX_DETACH:
if (cctx->flags & CCTX_DETACH) {
printf("[detached]\n"); printf("[detached]\n");
return (0); return (0);
default:
printf("[unknown error]\n");
return (1);
} }
printf("[error: %s]\n", error);
return (1);
server_dead:
printf("[lost server]\n");
return (0);
} }
void void
@@ -226,3 +262,69 @@ client_handle_winch(struct client_ctx *cctx)
sigwinch = 0; sigwinch = 0;
} }
int
client_msg_dispatch(struct client_ctx *cctx)
{
struct imsg imsg;
struct msg_print_data printdata;
ssize_t n, datalen;
for (;;) {
if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
if (n == 0)
return (0);
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
switch (imsg.hdr.type) {
case MSG_DETACH:
if (datalen != 0)
fatalx("bad MSG_DETACH size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->exittype = CCTX_DETACH;
break;
case MSG_ERROR:
if (datalen != sizeof printdata)
fatalx("bad MSG_ERROR size");
memcpy(&printdata, imsg.data, sizeof printdata);
printdata.msg[(sizeof printdata.msg) - 1] = '\0';
/* Error string used after exit message from server. */
cctx->errstr = xstrdup(printdata.msg);
imsg_free(&imsg);
return (-1);
case MSG_EXIT:
if (datalen != 0)
fatalx("bad MSG_EXIT size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->exittype = CCTX_EXIT;
break;
case MSG_EXITED:
if (datalen != 0)
fatalx("bad MSG_EXITED size");
imsg_free(&imsg);
return (-1);
case MSG_SHUTDOWN:
if (datalen != 0)
fatalx("bad MSG_SHUTDOWN size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->exittype = CCTX_SHUTDOWN;
break;
case MSG_SUSPEND:
if (datalen != 0)
fatalx("bad MSG_SUSPEND size");
client_suspend();
break;
default:
fatalx("unexpected message");
}
imsg_free(&imsg);
}
}

16
clock.c
View File

@@ -1,4 +1,4 @@
/* $Id: clock.c,v 1.3 2009-03-27 16:59:57 nicm Exp $ */ /* $Id: clock.c,v 1.7 2009-09-11 14:13:52 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -112,8 +112,6 @@ clock_draw(struct screen_write_ctx *ctx, u_int colour, int style)
strftime(tim, sizeof tim, "%H:%M", localtime(&t)); strftime(tim, sizeof tim, "%H:%M", localtime(&t));
screen_write_clearscreen(ctx); screen_write_clearscreen(ctx);
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.fg = colour;
if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) { if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) {
if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) { if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) {
@@ -121,7 +119,8 @@ clock_draw(struct screen_write_ctx *ctx, u_int colour, int style)
y = screen_size_y(s) / 2; y = screen_size_y(s) / 2;
screen_write_cursormove(ctx, x, y); screen_write_cursormove(ctx, x, y);
gc.fg = colour; memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_fg(&gc, colour);
screen_write_puts(ctx, &gc, "%s", tim); screen_write_puts(ctx, &gc, "%s", tim);
} }
return; return;
@@ -130,6 +129,8 @@ clock_draw(struct screen_write_ctx *ctx, u_int colour, int style)
x = (screen_size_x(s) / 2) - 3 * strlen(tim); x = (screen_size_x(s) / 2) - 3 * strlen(tim);
y = (screen_size_y(s) / 2) - 3; y = (screen_size_y(s) / 2) - 3;
memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_bg(&gc, colour);
for (ptr = tim; *ptr != '\0'; ptr++) { for (ptr = tim; *ptr != '\0'; ptr++) {
if (*ptr >= '0' && *ptr <= '9') if (*ptr >= '0' && *ptr <= '9')
idx = *ptr - '0'; idx = *ptr - '0';
@@ -147,13 +148,10 @@ clock_draw(struct screen_write_ctx *ctx, u_int colour, int style)
} }
for (j = 0; j < 5; j++) { for (j = 0; j < 5; j++) {
screen_write_cursormove(ctx, x, y + j);
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
screen_write_cursormove(ctx, x + i, y + j);
if (clock_table[idx][j][i]) if (clock_table[idx][j][i])
gc.attr |= GRID_ATTR_REVERSE; screen_write_putc(ctx, &gc, ' ');
else
gc.attr &= ~GRID_ATTR_REVERSE;
screen_write_putc(ctx, &gc, ' ');
} }
} }
x += 6; x += 6;

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-attach-session.c,v 1.24 2009-01-23 16:59:14 nicm Exp $ */ /* $Id: cmd-attach-session.c,v 1.32 2009-08-09 17:48:55 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_attach_session_entry = { const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach", "attach-session", "attach",
"[-d] " CMD_TARGET_SESSION_USAGE, "[-d] " CMD_TARGET_SESSION_USAGE,
CMD_DFLAG|CMD_CANTNEST|CMD_STARTSERVER, CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, CMD_CHFLAG('d'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_attach_session_exec, cmd_attach_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -44,10 +42,10 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct session *s; struct session *s;
char *cause; struct client *c;
const char *update;
if (ctx->curclient != NULL) char *overrides, *cause;
return (0); u_int i;
if (ARRAY_LENGTH(&sessions) == 0) { if (ARRAY_LENGTH(&sessions) == 0) {
ctx->error(ctx, "no sessions"); ctx->error(ctx, "no sessions");
@@ -56,25 +54,53 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) { if (ctx->cmdclient == NULL && ctx->curclient == NULL)
ctx->error(ctx, "not a terminal"); return (0);
return (-1);
if (ctx->cmdclient == NULL) {
if (data->chflags & CMD_CHFLAG('d')) {
/*
* Can't use server_write_session in case attaching to
* the same session as currently attached to.
*/
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != s)
continue;
if (c == ctx->curclient)
continue;
server_write_client(c, MSG_DETACH, NULL, 0);
}
}
ctx->curclient->session = s;
server_redraw_client(ctx->curclient);
} else {
if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal");
return (-1);
}
overrides =
options_get_string(&s->options, "terminal-overrides");
if (tty_open(&ctx->cmdclient->tty, overrides, &cause) != 0) {
ctx->error(ctx, "terminal open failed: %s", cause);
xfree(cause);
return (-1);
}
if (data->chflags & CMD_CHFLAG('d'))
server_write_session(s, MSG_DETACH, NULL, 0);
ctx->cmdclient->session = s;
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
update = options_get_string(&s->options, "update-environment");
environ_update(update, &ctx->cmdclient->environ, &s->environ);
server_redraw_client(ctx->cmdclient);
} }
if (tty_open(&ctx->cmdclient->tty, &cause) != 0) {
ctx->error(ctx, "terminal open failed: %s", cause);
xfree(cause);
return (-1);
}
if (data->flags & CMD_DFLAG)
server_write_session(s, MSG_DETACH, NULL, 0);
ctx->cmdclient->session = s;
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
recalculate_sizes(); recalculate_sizes();
server_redraw_client(ctx->cmdclient);
return (1); return (1); /* 1 means don't tell command client to exit */
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-bind-key.c,v 1.20 2009-03-28 14:08:09 nicm Exp $ */ /* $Id: cmd-bind-key.c,v 1.25 2009-07-28 23:19:06 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -26,26 +28,28 @@
int cmd_bind_key_parse(struct cmd *, int, char **, char **); int cmd_bind_key_parse(struct cmd *, int, char **, char **);
int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *); int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_bind_key_send(struct cmd *, struct buffer *);
void cmd_bind_key_recv(struct cmd *, struct buffer *);
void cmd_bind_key_free(struct cmd *); void cmd_bind_key_free(struct cmd *);
size_t cmd_bind_key_print(struct cmd *, char *, size_t); size_t cmd_bind_key_print(struct cmd *, char *, size_t);
int cmd_bind_key_table(struct cmd *, struct cmd_ctx *);
struct cmd_bind_key_data { struct cmd_bind_key_data {
int key; int key;
int can_repeat; int can_repeat;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
int command_key;
char *tablename;
char *modecmd;
}; };
const struct cmd_entry cmd_bind_key_entry = { const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind", "bind-key", "bind",
"[-r] key command [arguments]", "[-cnr] [-t key-table] key command [arguments]",
0, 0, 0,
NULL, NULL,
cmd_bind_key_parse, cmd_bind_key_parse,
cmd_bind_key_exec, cmd_bind_key_exec,
cmd_bind_key_send,
cmd_bind_key_recv,
cmd_bind_key_free, cmd_bind_key_free,
cmd_bind_key_print cmd_bind_key_print
}; };
@@ -54,17 +58,29 @@ int
cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_bind_key_data *data; struct cmd_bind_key_data *data;
int opt; int opt, no_prefix = 0;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->can_repeat = 0; data->can_repeat = 0;
data->cmdlist = NULL; data->cmdlist = NULL;
data->command_key = 0;
data->tablename = NULL;
data->modecmd = NULL;
while ((opt = getopt(argc, argv, "r")) != -1) { while ((opt = getopt(argc, argv, "cnrt:")) != -1) {
switch (opt) { switch (opt) {
case 'c':
data->command_key = 1;
break;
case 'n':
no_prefix = 1;
break;
case 'r': case 'r':
data->can_repeat = 1; data->can_repeat = 1;
break; break;
case 't':
data->tablename = xstrdup(optarg);
break;
default: default:
goto usage; goto usage;
} }
@@ -78,11 +94,19 @@ cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
xasprintf(cause, "unknown key: %s", argv[0]); xasprintf(cause, "unknown key: %s", argv[0]);
goto error; goto error;
} }
if (!no_prefix)
data->key |= KEYC_PREFIX;
argc--; argc--;
argv++; argv++;
if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL) if (data->tablename != NULL) {
goto error; if (argc != 1)
goto usage;
data->modecmd = xstrdup(argv[0]);
} else {
if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL)
goto error;
}
return (0); return (0);
@@ -101,6 +125,8 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return (0); return (0);
if (data->tablename != NULL)
return (cmd_bind_key_table(self, ctx));
key_bindings_add(data->key, data->can_repeat, data->cmdlist); key_bindings_add(data->key, data->can_repeat, data->cmdlist);
data->cmdlist = NULL; /* avoid free */ data->cmdlist = NULL; /* avoid free */
@@ -108,23 +134,37 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
return (0); return (0);
} }
void int
cmd_bind_key_send(struct cmd *self, struct buffer *b) cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_bind_key_data *data = self->data; struct cmd_bind_key_data *data = self->data;
const struct mode_key_table *mtab;
struct mode_key_binding *mbind, mtmp;
enum mode_key_cmd cmd;
buffer_write(b, data, sizeof *data); if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
cmd_list_send(data->cmdlist, b); ctx->error(ctx, "unknown key table: %s", data->tablename);
} return (-1);
}
void cmd = mode_key_fromstring(mtab->cmdstr, data->modecmd);
cmd_bind_key_recv(struct cmd *self, struct buffer *b) if (cmd == MODEKEY_NONE) {
{ ctx->error(ctx, "unknown command: %s", data->modecmd);
struct cmd_bind_key_data *data; return (-1);
}
self->data = data = xmalloc(sizeof *data); mtmp.key = data->key & ~KEYC_PREFIX;
buffer_read(b, data, sizeof *data); mtmp.mode = data->command_key ? 1 : 0;
data->cmdlist = cmd_list_recv(b); if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
mbind->cmd = cmd;
return (0);
}
mbind = xmalloc(sizeof *mbind);
mbind->key = mtmp.key;
mbind->mode = mtmp.mode;
mbind->cmd = cmd;
SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
return (0);
} }
void void
@@ -134,6 +174,10 @@ cmd_bind_key_free(struct cmd *self)
if (data->cmdlist != NULL) if (data->cmdlist != NULL)
cmd_list_free(data->cmdlist); cmd_list_free(data->cmdlist);
if (data->tablename != NULL)
xfree(data->tablename);
if (data->modecmd != NULL)
xfree(data->modecmd);
xfree(data); xfree(data);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-break-pane.c,v 1.1 2009-03-07 09:29:54 nicm Exp $ */ /* $Id: cmd-break-pane.c,v 1.8 2009-08-16 19:16:27 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,41 +30,31 @@ int cmd_break_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_break_pane_entry = { const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp", "break-pane", "breakp",
CMD_PANE_WINDOW_USAGE " [-d]", CMD_TARGET_PANE_USAGE " [-d]",
CMD_DFLAG, 0, CMD_CHFLAG('d'),
cmd_pane_init, cmd_target_init,
cmd_pane_parse, cmd_target_parse,
cmd_break_pane_exec, cmd_break_pane_exec,
cmd_pane_send, cmd_target_free,
cmd_pane_recv, cmd_target_print
cmd_pane_free,
cmd_pane_print
}; };
int int
cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_pane_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct session *s; struct session *s;
struct window_pane *wp; struct window_pane *wp;
struct window *w; struct window *w;
char *cause; char *cause;
int base_idx;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_pane(ctx, data->target, &s, &wp)) == NULL)
return (-1); return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (window_count_panes(wl->window) == 1) { if (window_count_panes(wl->window) == 1) {
ctx->error(ctx, "can't break pane: %d", data->pane); ctx->error(ctx, "can't break with only one pane");
return (-1); return (-1);
} }
@@ -74,18 +64,19 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
if (wl->window->active == NULL) if (wl->window->active == NULL)
wl->window->active = TAILQ_NEXT(wp, entry); wl->window->active = TAILQ_NEXT(wp, entry);
} }
window_fit_panes(wl->window); layout_close_pane(wp);
w = wp->window = window_create1(s->sx, s->sy); w = wp->window = window_create1(s->sx, s->sy);
TAILQ_INSERT_HEAD(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp; w->active = wp;
window_fit_panes(w);
w->name = default_window_name(w); w->name = default_window_name(w);
layout_init(w);
wl = session_attach(s, w, -1, &cause); /* can't fail */ base_idx = options_get_number(&s->options, "base-index");
wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */
if (!(data->flags & CMD_DFLAG)) if (!(data->chflags & CMD_CHFLAG('d')))
session_select(s, wl->idx); session_select(s, wl->idx);
server_redraw_session(s); server_redraw_session(s);
return (0); return (0);

152
cmd-choose-client.c Normal file
View File

@@ -0,0 +1,152 @@
/* $Id: cmd-choose-client.c,v 1.3 2009-09-07 23:59:19 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <ctype.h>
#include "tmux.h"
/*
* Enter choice mode to choose a client.
*/
int cmd_choose_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_client_callback(void *, int);
void cmd_choose_client_free(void *);
const struct cmd_entry cmd_choose_client_entry = {
"choose-client", NULL,
CMD_TARGET_WINDOW_USAGE " [template]",
CMD_ARG01, 0,
cmd_target_init,
cmd_target_parse,
cmd_choose_client_exec,
cmd_target_free,
cmd_target_print
};
struct cmd_choose_client_data {
struct client *client;
char *template;
};
int
cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct cmd_choose_client_data *cdata;
struct winlink *wl;
struct client *c;
u_int i, idx, cur;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (0);
cur = idx = 0;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
if (c == ctx->curclient)
cur = idx;
idx++;
window_choose_add(wl->window->active, i,
"%s: %s [%ux%u %s]%s", c->tty.path,
c->session->name, c->tty.sx, c->tty.sy,
c->tty.termname, c->tty.flags & TTY_UTF8 ? " (utf8)" : "");
}
cdata = xmalloc(sizeof *cdata);
if (data->arg != NULL)
cdata->template = xstrdup(data->arg);
else
cdata->template = xstrdup("detach-client -t '%%'");
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready(wl->window->active,
cur, cmd_choose_client_callback, cmd_choose_client_free, cdata);
return (0);
}
void
cmd_choose_client_callback(void *data, int idx)
{
struct cmd_choose_client_data *cdata = data;
struct client *c;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *template, *cause;
if (idx == -1)
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
if ((u_int) idx > ARRAY_LENGTH(&clients) - 1)
return;
c = ARRAY_ITEM(&clients, idx);
if (c == NULL || c->session == NULL)
return;
template = cmd_template_replace(cdata->template, c->tty.path, 1);
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(c, "%s", cause);
xfree(cause);
}
xfree(template);
return;
}
xfree(template);
ctx.msgdata = NULL;
ctx.curclient = cdata->client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
void
cmd_choose_client_free(void *data)
{
struct cmd_choose_client_data *cdata = data;
cdata->client->references--;
xfree(cdata->template);
xfree(cdata);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-choose-session.c,v 1.6 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-choose-session.c,v 1.13 2009-09-07 23:59:19 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -27,22 +29,22 @@
int cmd_choose_session_exec(struct cmd *, struct cmd_ctx *); int cmd_choose_session_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_session_callback(void *, int); void cmd_choose_session_callback(void *, int);
void cmd_choose_session_free(void *);
const struct cmd_entry cmd_choose_session_entry = { const struct cmd_entry cmd_choose_session_entry = {
"choose-session", NULL, "choose-session", NULL,
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE " [template]",
0, CMD_ARG01, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_choose_session_exec, cmd_choose_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
struct cmd_choose_session_data { struct cmd_choose_session_data {
u_int client; struct client *client;
char *template;
}; };
int int
@@ -81,10 +83,15 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->client = server_client_index(ctx->curclient); if (data->arg != NULL)
cdata->template = xstrdup(data->arg);
else
cdata->template = xstrdup("switch-client -t '%%'");
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready( window_choose_ready(wl->window->active,
wl->window->active, cur, cmd_choose_session_callback, cdata); cur, cmd_choose_session_callback, cmd_choose_session_free, cdata);
return (0); return (0);
} }
@@ -93,15 +100,53 @@ void
cmd_choose_session_callback(void *data, int idx) cmd_choose_session_callback(void *data, int idx)
{ {
struct cmd_choose_session_data *cdata = data; struct cmd_choose_session_data *cdata = data;
struct client *c; struct session *s;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *template, *cause;
if (idx != -1 && cdata->client <= ARRAY_LENGTH(&clients) - 1) { if (idx == -1)
c = ARRAY_ITEM(&clients, cdata->client); return;
if (c != NULL && (u_int) idx <= ARRAY_LENGTH(&sessions) - 1) { if (cdata->client->flags & CLIENT_DEAD)
c->session = ARRAY_ITEM(&sessions, idx); return;
recalculate_sizes();
server_redraw_client(c); if ((u_int) idx > ARRAY_LENGTH(&sessions) - 1)
return;
s = ARRAY_ITEM(&sessions, idx);
if (s == NULL)
return;
template = cmd_template_replace(cdata->template, s->name, 1);
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(cdata->client, "%s", cause);
xfree(cause);
} }
xfree(template);
return;
} }
xfree(template);
ctx.msgdata = NULL;
ctx.curclient = cdata->client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
void
cmd_choose_session_free(void *data)
{
struct cmd_choose_session_data *cdata = data;
cdata->client->references--;
xfree(cdata->template);
xfree(cdata); xfree(cdata);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-choose-window.c,v 1.7 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-choose-window.c,v 1.17 2009-09-07 23:59:19 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -27,22 +29,23 @@
int cmd_choose_window_exec(struct cmd *, struct cmd_ctx *); int cmd_choose_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_window_callback(void *, int); void cmd_choose_window_callback(void *, int);
void cmd_choose_window_free(void *);
const struct cmd_entry cmd_choose_window_entry = { const struct cmd_entry cmd_choose_window_entry = {
"choose-window", NULL, "choose-window", NULL,
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE " [template]",
0, CMD_ARG01, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_choose_window_exec, cmd_choose_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
struct cmd_choose_window_data { struct cmd_choose_window_data {
u_int session; struct client *client;
struct session *session;
char *template;
}; };
int int
@@ -54,6 +57,8 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl, *wm; struct winlink *wl, *wm;
struct window *w; struct window *w;
u_int idx, cur; u_int idx, cur;
char flag, *title;
const char *left, *right;
if (ctx->curclient == NULL) { if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively"); ctx->error(ctx, "must be run interactively");
@@ -75,17 +80,44 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cur = idx; cur = idx;
idx++; idx++;
flag = ' ';
if (session_alert_has(s, wm, WINDOW_ACTIVITY))
flag = '#';
else if (session_alert_has(s, wm, WINDOW_BELL))
flag = '!';
else if (session_alert_has(s, wm, WINDOW_CONTENT))
flag = '+';
else if (wm == s->curw)
flag = '*';
else if (wm == SLIST_FIRST(&s->lastw))
flag = '-';
title = w->active->screen->title;
if (wm == wl)
title = w->active->base.title;
left = " \"";
right = "\"";
if (*title == '\0')
left = right = "";
window_choose_add(wl->window->active, window_choose_add(wl->window->active,
wm->idx, "%3d: %s [%ux%u] (%u panes)", wm->idx, w->name, wm->idx, "%3d: %s%c [%ux%u] (%u panes)%s%s%s",
w->sx, w->sy, window_count_panes(w)); wm->idx, w->name, flag, w->sx, w->sy, window_count_panes(w),
left, title, right);
} }
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
if (session_index(s, &cdata->session) != 0) if (data->arg != NULL)
fatalx("session not found"); cdata->template = xstrdup(data->arg);
else
cdata->template = xstrdup("select-window -t '%%'");
cdata->session = s;
cdata->session->references++;
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready( window_choose_ready(wl->window->active,
wl->window->active, cur, cmd_choose_window_callback, cdata); cur, cmd_choose_window_callback, cmd_choose_window_free, cdata);
return (0); return (0);
} }
@@ -94,13 +126,54 @@ void
cmd_choose_window_callback(void *data, int idx) cmd_choose_window_callback(void *data, int idx)
{ {
struct cmd_choose_window_data *cdata = data; struct cmd_choose_window_data *cdata = data;
struct session *s; struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *target, *template, *cause;
if (idx != -1 && cdata->session <= ARRAY_LENGTH(&sessions) - 1) { if (idx == -1)
s = ARRAY_ITEM(&sessions, cdata->session); return;
if (s != NULL && session_select(s, idx) == 0) if (cdata->client->flags & CLIENT_DEAD)
server_redraw_session(s); return;
recalculate_sizes(); if (cdata->session->flags & SESSION_DEAD)
return;
if (cdata->client->session != cdata->session)
return;
xasprintf(&target, "%s:%d", cdata->session->name, idx);
template = cmd_template_replace(cdata->template, target, 1);
xfree(target);
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(cdata->client, "%s", cause);
xfree(cause);
}
xfree(template);
return;
} }
xfree(template);
ctx.msgdata = NULL;
ctx.curclient = cdata->client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
void
cmd_choose_window_free(void *data)
{
struct cmd_choose_window_data *cdata = data;
cdata->session->references--;
cdata->client->references--;
xfree(cdata->template);
xfree(cdata); xfree(cdata);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: util.c,v 1.1 2009-01-18 17:20:52 nicm Exp $ */ /* $Id: cmd-clear-history.c,v 1.7 2009-07-30 21:04:40 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -20,33 +20,36 @@
#include "tmux.h" #include "tmux.h"
/* Return a section of a string around a point. */ /*
char * * Clear pane history.
section_string(char *buf, size_t len, size_t sectoff, size_t sectlen) */
int cmd_clear_history_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clear_history_entry = {
"clear-history", "clearhist",
CMD_TARGET_PANE_USAGE,
0, 0,
cmd_target_init,
cmd_target_parse,
cmd_clear_history_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
char *s; struct cmd_target_data *data = self->data;
size_t first, last; struct window_pane *wp;
struct grid *gd;
if (len <= sectlen) { if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
first = 0; return (-1);
last = len; gd = wp->base.grid;
} else if (sectoff < sectlen / 2) {
first = 0;
last = sectlen;
} else if (sectoff + sectlen / 2 > len) {
last = len;
first = last - sectlen;
} else {
first = sectoff - sectlen / 2;
last = first + sectlen;
}
if (last - first > 3 && first != 0) grid_move_lines(gd, 0, gd->hsize, gd->sy);
first += 3; gd->hsize = 0;
if (last - first > 3 && last != len)
last -= 3;
xasprintf(&s, "%s%.*s%s", first == 0 ? "" : "...", return (0);
(int) (last - first), buf + first, last == len ? "" : "...");
return (s);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-clock-mode.c,v 1.3 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-clock-mode.c,v 1.6 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,11 @@ int cmd_clock_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clock_mode_entry = { const struct cmd_entry cmd_clock_mode_entry = {
"clock-mode", NULL, "clock-mode", NULL,
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_PANE_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_clock_mode_exec, cmd_clock_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -43,12 +41,12 @@ int
cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
window_pane_set_mode(wl->window->active, &window_clock_mode); window_pane_set_mode(wp, &window_clock_mode);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-command-prompt.c,v 1.16 2009-02-16 18:58:14 nicm Exp $ */ /* $Id: cmd-command-prompt.c,v 1.25 2009-08-25 13:53:39 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,57 +27,111 @@
* Prompt for command in client. * Prompt for command in client.
*/ */
void cmd_command_prompt_init(struct cmd *, int); void cmd_command_prompt_init(struct cmd *, int);
int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *); int cmd_command_prompt_parse(struct cmd *, int, char **, char **);
int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
void cmd_command_prompt_free(struct cmd *);
size_t cmd_command_prompt_print(struct cmd *, char *, size_t);
int cmd_command_prompt_callback(void *, const char *); int cmd_command_prompt_callback(void *, const char *);
void cmd_command_prompt_cfree(void *);
const struct cmd_entry cmd_command_prompt_entry = { const struct cmd_entry cmd_command_prompt_entry = {
"command-prompt", NULL, "command-prompt", NULL,
CMD_TARGET_CLIENT_USAGE " [template]", CMD_TARGET_CLIENT_USAGE " [-p prompts] [template]",
CMD_ARG01, 0, 0,
cmd_command_prompt_init, cmd_command_prompt_init,
cmd_target_parse, cmd_command_prompt_parse,
cmd_command_prompt_exec, cmd_command_prompt_exec,
cmd_target_send, cmd_command_prompt_free,
cmd_target_recv, cmd_command_prompt_print
cmd_target_free,
cmd_target_print
}; };
struct cmd_command_prompt_data { struct cmd_command_prompt_data {
char *prompts;
char *target;
char *template;
};
struct cmd_command_prompt_cdata {
struct client *c; struct client *c;
char *next_prompt;
char *prompts;
char *template; char *template;
int idx;
}; };
void void
cmd_command_prompt_init(struct cmd *self, int key) cmd_command_prompt_init(struct cmd *self, int key)
{ {
struct cmd_target_data *data; struct cmd_command_prompt_data *data;
cmd_target_init(self, key); self->data = data = xmalloc(sizeof *data);
data = self->data; data->prompts = NULL;
data->target = NULL;
data->template = NULL;
switch (key) { switch (key) {
case ',': case ',':
data->arg = xstrdup("rename-window '%%'"); data->template = xstrdup("rename-window '%%'");
break; break;
case '.': case '.':
data->arg = xstrdup("move-window -t '%%'"); data->template = xstrdup("move-window -t '%%'");
break; break;
case 'f': case 'f':
data->arg = xstrdup("find-window '%%'"); data->template = xstrdup("find-window '%%'");
break; break;
} }
} }
int
cmd_command_prompt_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_command_prompt_data *data;
int opt;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "p:t:")) != -1) {
switch (opt) {
case 'p':
if (data->prompts == NULL)
data->prompts = xstrdup(optarg);
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0 && argc != 1)
goto usage;
if (argc == 1)
data->template = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int int
cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_command_prompt_data *data = self->data;
struct cmd_command_prompt_data *cdata; struct cmd_command_prompt_cdata *cdata;
struct client *c; struct client *c;
char *hdr, *ptr; char *prompt, *ptr;
size_t n;
if ((c = cmd_find_client(ctx, data->target)) == NULL) if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1); return (-1);
@@ -87,80 +141,102 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->c = c; cdata->c = c;
if (data->arg != NULL) { cdata->idx = 1;
cdata->template = xstrdup(data->arg); cdata->next_prompt = NULL;
if ((ptr = strchr(data->arg, ' ')) == NULL) cdata->prompts = NULL;
ptr = strchr(data->arg, '\0'); cdata->template = NULL;
xasprintf(&hdr, "(%.*s) ", (int) (ptr - data->arg), data->arg);
} else { if (data->template != NULL)
cdata->template = NULL; cdata->template = xstrdup(data->template);
hdr = xstrdup(":"); else
} cdata->template = xstrdup("%1");
status_prompt_set(c, hdr, cmd_command_prompt_callback, cdata, 0); if (data->prompts != NULL)
xfree(hdr); cdata->prompts = xstrdup(data->prompts);
else if (data->template != NULL) {
n = strcspn(data->template, " ,");
xasprintf(&cdata->prompts, "(%.*s) ", (int) n, data->template);
} else
cdata->prompts = xstrdup(":");
cdata->next_prompt = cdata->prompts;
ptr = strsep(&cdata->next_prompt, ",");
if (data->prompts == NULL)
prompt = xstrdup(ptr);
else
xasprintf(&prompt, "%s ", ptr);
status_prompt_set(c, prompt, cmd_command_prompt_callback,
cmd_command_prompt_cfree, cdata, 0);
xfree(prompt);
return (0); return (0);
} }
void
cmd_command_prompt_free(struct cmd *self)
{
struct cmd_command_prompt_data *data = self->data;
if (data->prompts != NULL)
xfree(data->prompts);
if (data->target != NULL)
xfree(data->target);
if (data->template != NULL)
xfree(data->template);
xfree(data);
}
size_t
cmd_command_prompt_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_command_prompt_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->prompts != NULL)
off += cmd_prarg(buf + off, len - off, " -p ", data->prompts);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->template != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->template);
return (off);
}
int int
cmd_command_prompt_callback(void *data, const char *s) cmd_command_prompt_callback(void *data, const char *s)
{ {
struct cmd_command_prompt_data *cdata = data; struct cmd_command_prompt_cdata *cdata = data;
struct client *c = cdata->c; struct client *c = cdata->c;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmd_ctx ctx; struct cmd_ctx ctx;
char *cause, *ptr, *buf, ch; char *cause, *newtempl, *prompt, *ptr;
size_t len, slen;
if (s == NULL) { if (s == NULL)
xfree(cdata);
return (0); return (0);
newtempl = cmd_template_replace(cdata->template, s, cdata->idx);
xfree(cdata->template);
cdata->template = newtempl;
if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) {
xasprintf(&prompt, "%s ", ptr);
status_prompt_update(c, prompt);
xfree(prompt);
cdata->idx++;
return (1);
} }
slen = strlen(s);
len = 0; if (cmd_string_parse(newtempl, &cmdlist, &cause) != 0) {
buf = NULL; if (cause != NULL) {
if (cdata->template != NULL) { *cause = toupper((u_char) *cause);
ptr = cdata->template; status_message_set(c, "%s", cause);
while (*ptr != '\0') { xfree(cause);
switch (ch = *ptr++) {
case '%':
if (*ptr != '%')
break;
ptr++;
buf = xrealloc(buf, 1, len + slen + 1);
memcpy(buf + len, s, slen);
len += slen;
break;
default:
buf = xrealloc(buf, 1, len + 2);
buf[len++] = ch;
break;
}
} }
xfree(cdata->template);
buf[len] = '\0';
s = buf;
}
xfree(cdata);
if (cmd_string_parse(s, &cmdlist, &cause) != 0) {
if (cause == NULL)
return (0);
*cause = toupper((u_char) *cause);
status_message_set(c, cause);
xfree(cause);
cmdlist = NULL;
}
if (buf != NULL)
xfree(buf);
if (cmdlist == NULL)
return (0); return (0);
}
ctx.msgdata = NULL; ctx.msgdata = NULL;
ctx.cursession = c->session;
ctx.curclient = c; ctx.curclient = c;
ctx.error = key_bindings_error; ctx.error = key_bindings_error;
@@ -172,7 +248,19 @@ cmd_command_prompt_callback(void *data, const char *s)
cmd_list_exec(cmdlist, &ctx); cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
if (c->prompt_callback != (void *) &cmd_command_prompt_callback) if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
return (1); return (1);
return (0); return (0);
} }
void
cmd_command_prompt_cfree(void *data)
{
struct cmd_command_prompt_cdata *cdata = data;
if (cdata->prompts != NULL)
xfree(cdata->prompts);
if (cdata->template != NULL)
xfree(cdata->template);
xfree(cdata);
}

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

@@ -0,0 +1,147 @@
/* $Id: cmd-confirm-before.c,v 1.11 2009-08-24 16:24:18 tcunha Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <ctype.h>
#include <string.h>
#include "tmux.h"
/*
* Asks for confirmation before executing a command.
*/
int cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *);
void cmd_confirm_before_init(struct cmd *, int);
int cmd_confirm_before_callback(void *, const char *);
void cmd_confirm_before_free(void *);
const struct cmd_entry cmd_confirm_before_entry = {
"confirm-before", "confirm",
CMD_TARGET_CLIENT_USAGE " command",
CMD_ARG1, 0,
cmd_confirm_before_init,
cmd_target_parse,
cmd_confirm_before_exec,
cmd_target_free,
cmd_target_print
};
struct cmd_confirm_before_data {
struct client *c;
char *cmd;
};
void
cmd_confirm_before_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
switch (key) {
case '&':
data->arg = xstrdup("kill-window");
break;
case 'x':
data->arg = xstrdup("kill-pane");
break;
}
}
int
cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct cmd_confirm_before_data *cdata;
struct client *c;
char *buf, *cmd, *ptr;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
ptr = xstrdup(data->arg);
if ((cmd = strtok(ptr, " \t")) == NULL)
cmd = ptr;
xasprintf(&buf, "Confirm '%s'? (y/n) ", cmd);
xfree(ptr);
cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(data->arg);
cdata->c = c;
status_prompt_set(cdata->c, buf,
cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
PROMPT_SINGLE);
xfree(buf);
return (1);
}
int
cmd_confirm_before_callback(void *data, const char *s)
{
struct cmd_confirm_before_data *cdata = data;
struct client *c = cdata->c;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *cause;
if (s == NULL || *s == '\0')
return (0);
if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
return (0);
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(c, "%s", cause);
xfree(cause);
}
return (0);
}
ctx.msgdata = NULL;
ctx.curclient = c;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
return (0);
}
void
cmd_confirm_before_free(void *data)
{
struct cmd_confirm_before_data *cdata = data;
if (cdata->cmd != NULL)
xfree(cdata->cmd);
xfree(cdata);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-copy-buffer.c,v 1.1 2009-02-03 17:21:19 tcunha Exp $ */ /* $Id: cmd-copy-buffer.c,v 1.4 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -16,7 +16,10 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "tmux.h" #include "tmux.h"
@@ -26,8 +29,6 @@
int cmd_copy_buffer_parse(struct cmd *, int, char **, char **); int cmd_copy_buffer_parse(struct cmd *, int, char **, char **);
int cmd_copy_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_copy_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_copy_buffer_send(struct cmd *, struct buffer *);
void cmd_copy_buffer_recv(struct cmd *, struct buffer *);
void cmd_copy_buffer_free(struct cmd *); void cmd_copy_buffer_free(struct cmd *);
void cmd_copy_buffer_init(struct cmd *, int); void cmd_copy_buffer_init(struct cmd *, int);
size_t cmd_copy_buffer_print(struct cmd *, char *, size_t); size_t cmd_copy_buffer_print(struct cmd *, char *, size_t);
@@ -42,12 +43,10 @@ struct cmd_copy_buffer_data {
const struct cmd_entry cmd_copy_buffer_entry = { const struct cmd_entry cmd_copy_buffer_entry = {
"copy-buffer", "copyb", "copy-buffer", "copyb",
"[-a src-index] [-b dst-index] [-s src-session] [-t dst-session]", "[-a src-index] [-b dst-index] [-s src-session] [-t dst-session]",
0, 0, 0,
cmd_copy_buffer_init, cmd_copy_buffer_init,
cmd_copy_buffer_parse, cmd_copy_buffer_parse,
cmd_copy_buffer_exec, cmd_copy_buffer_exec,
cmd_copy_buffer_send,
cmd_copy_buffer_recv,
cmd_copy_buffer_free, cmd_copy_buffer_free,
cmd_copy_buffer_print cmd_copy_buffer_print
}; };
@@ -126,61 +125,44 @@ cmd_copy_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_copy_buffer_data *data = self->data; struct cmd_copy_buffer_data *data = self->data;
struct paste_buffer *pb; struct paste_buffer *pb;
struct paste_stack *dst_ps, *src_ps;
u_char *pdata;
struct session *dst_session, *src_session; struct session *dst_session, *src_session;
u_int limit; u_int limit;
if ((dst_session = cmd_find_session(ctx, data->dst_session)) == NULL || if ((dst_session = cmd_find_session(ctx, data->dst_session)) == NULL ||
(src_session = cmd_find_session(ctx, data->src_session)) == NULL) (src_session = cmd_find_session(ctx, data->src_session)) == NULL)
return (-1); return (-1);
dst_ps = &dst_session->buffers;
src_ps = &src_session->buffers;
if (data->src_idx == -1) { if (data->src_idx == -1) {
if ((pb = paste_get_top(&src_session->buffers)) == NULL) { if ((pb = paste_get_top(src_ps)) == NULL) {
ctx->error(ctx, "no buffers"); ctx->error(ctx, "no buffers");
return (-1); return (-1);
} }
} else { } else {
if ((pb = paste_get_index(&src_session->buffers, if ((pb = paste_get_index(src_ps, data->src_idx)) == NULL) {
data->src_idx)) == NULL) {
ctx->error(ctx, "no buffer %d", data->src_idx); ctx->error(ctx, "no buffer %d", data->src_idx);
return (-1); return (-1);
} }
} }
limit = options_get_number(&dst_session->options, "buffer-limit"); limit = options_get_number(&dst_session->options, "buffer-limit");
if (data->dst_idx == -1) {
paste_add(&dst_session->buffers, xstrdup(pb->data), limit); pdata = xmalloc(pb->size);
return (0); memcpy(pdata, pb->data, pb->size);
}
if (paste_replace(&dst_session->buffers, data->dst_idx, if (data->dst_idx == -1)
xstrdup(pb->data)) != 0) { paste_add(dst_ps, pdata, pb->size, limit);
else if (paste_replace(dst_ps, data->dst_idx, pdata, pb->size) != 0) {
ctx->error(ctx, "no buffer %d", data->dst_idx); ctx->error(ctx, "no buffer %d", data->dst_idx);
xfree(pdata);
return (-1); return (-1);
} }
return (0); return (0);
} }
void
cmd_copy_buffer_send(struct cmd *self, struct buffer *b)
{
struct cmd_copy_buffer_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->dst_session);
cmd_send_string(b, data->src_session);
}
void
cmd_copy_buffer_recv(struct cmd *self, struct buffer *b)
{
struct cmd_copy_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->dst_session = cmd_recv_string(b);
data->src_session = cmd_recv_string(b);
}
void void
cmd_copy_buffer_free(struct cmd *self) cmd_copy_buffer_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-copy-mode.c,v 1.16 2009-02-25 21:56:46 nicm Exp $ */ /* $Id: cmd-copy-mode.c,v 1.23 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,11 @@ int cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_copy_mode_entry = { const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL, "copy-mode", NULL,
CMD_TARGET_WINDOW_USAGE, "[-u] " CMD_TARGET_PANE_USAGE,
CMD_UFLAG, 0, CMD_CHFLAG('u'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_copy_mode_exec, cmd_copy_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
NULL NULL
}; };
@@ -43,14 +41,14 @@ int
cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
window_pane_set_mode(wl->window->active, &window_copy_mode); window_pane_set_mode(wp, &window_copy_mode);
if (data->flags & CMD_UFLAG) if (wp->mode == &window_copy_mode && data->chflags & CMD_CHFLAG('u'))
window_copy_pageup(wl->window->active); window_copy_pageup(wp);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-delete-buffer.c,v 1.4 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-delete-buffer.c,v 1.7 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_delete_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_delete_buffer_entry = { const struct cmd_entry cmd_delete_buffer_entry = {
"delete-buffer", "deleteb", "delete-buffer", "deleteb",
CMD_BUFFER_SESSION_USAGE, CMD_BUFFER_SESSION_USAGE,
0, 0, 0,
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_delete_buffer_exec, cmd_delete_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-detach-client.c,v 1.7 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-detach-client.c,v 1.9 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_detach_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_detach_client_entry = { const struct cmd_entry cmd_detach_client_entry = {
"detach-client", "detach", "detach-client", "detach",
CMD_TARGET_CLIENT_USAGE, CMD_TARGET_CLIENT_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_detach_client_exec, cmd_detach_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

63
cmd-display-message.c Normal file
View File

@@ -0,0 +1,63 @@
/* $Id: cmd-display-message.c,v 1.2 2009-07-28 22:12:16 tcunha Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <time.h>
#include "tmux.h"
/*
* Displays a message in the status line.
*/
int cmd_display_message_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_display_message_entry = {
"display-message", "display",
CMD_TARGET_CLIENT_USAGE " [message]",
CMD_ARG01, 0,
cmd_target_init,
cmd_target_parse,
cmd_display_message_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct client *c;
const char *template;
char *msg;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
if (data->arg == NULL)
template = "[#S] #I:#W, current pane #P - (%H:%M %d-%b-%y)";
else
template = data->arg;
msg = status_replace(c->session, template, time(NULL));
status_message_set(c, "%s", msg);
xfree(msg);
return (0);
}

52
cmd-display-panes.c Normal file
View File

@@ -0,0 +1,52 @@
/* $Id: cmd-display-panes.c,v 1.1 2009-08-31 22:30:15 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include "tmux.h"
/*
* Display panes on a client.
*/
int cmd_display_panes_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_display_panes_entry = {
"display-panes", "displayp",
CMD_TARGET_CLIENT_USAGE,
0, 0,
cmd_target_init,
cmd_target_parse,
cmd_display_panes_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_display_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
server_set_identify(c);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-down-pane.c,v 1.7 2009-04-01 21:10:08 nicm Exp $ */ /* $Id: cmd-down-pane.c,v 1.12 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_down_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_down_pane_entry = { const struct cmd_entry cmd_down_pane_entry = {
"down-pane", "downp", "down-pane", "downp",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_down_pane_exec, cmd_down_pane_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -54,8 +52,8 @@ cmd_down_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
w->active = TAILQ_NEXT(w->active, entry); w->active = TAILQ_NEXT(w->active, entry);
if (w->active == NULL) if (w->active == NULL)
w->active = TAILQ_FIRST(&w->panes); w->active = TAILQ_FIRST(&w->panes);
layout_refresh(w, 1); } while (!window_pane_visible(w->active));
} while (w->active->flags & PANE_HIDDEN); server_status_window(wl->window);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-find-window.c,v 1.6 2009-03-29 11:18:28 nicm Exp $ */ /* $Id: cmd-find-window.c,v 1.13 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <fnmatch.h>
#include <string.h> #include <string.h>
#include "tmux.h" #include "tmux.h"
@@ -29,17 +30,14 @@
int cmd_find_window_exec(struct cmd *, struct cmd_ctx *); int cmd_find_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_find_window_callback(void *, int); void cmd_find_window_callback(void *, int);
char *cmd_find_window_search(struct window_pane *, const char *);
const struct cmd_entry cmd_find_window_entry = { const struct cmd_entry cmd_find_window_entry = {
"find-window", "findw", "find-window", "findw",
CMD_TARGET_WINDOW_USAGE " match-string", CMD_TARGET_WINDOW_USAGE " match-string",
CMD_ARG1, CMD_ARG1, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_find_window_exec, cmd_find_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -59,8 +57,8 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window_pane *wp; struct window_pane *wp;
ARRAY_DECL(, u_int) list_idx; ARRAY_DECL(, u_int) list_idx;
ARRAY_DECL(, char *) list_ctx; ARRAY_DECL(, char *) list_ctx;
char *sres, *sctx; char *sres, *sctx, *searchstr;
u_int i; u_int i, line;
if (ctx->curclient == NULL) { if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively"); ctx->error(ctx, "must be run interactively");
@@ -74,17 +72,18 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
ARRAY_INIT(&list_idx); ARRAY_INIT(&list_idx);
ARRAY_INIT(&list_ctx); ARRAY_INIT(&list_ctx);
xasprintf(&searchstr, "*%s*", data->arg);
RB_FOREACH(wm, winlinks, &s->windows) { RB_FOREACH(wm, winlinks, &s->windows) {
i = 0; i = 0;
TAILQ_FOREACH(wp, &wm->window->panes, entry) { TAILQ_FOREACH(wp, &wm->window->panes, entry) {
i++; i++;
if (strstr(wm->window->name, data->arg) != NULL) if (fnmatch(searchstr, wm->window->name, 0) == 0)
sctx = xstrdup(""); sctx = xstrdup("");
else { else {
sres = cmd_find_window_search(wp, data->arg); sres = window_pane_search(wp, data->arg, &line);
if (sres == NULL && if (sres == NULL &&
strstr(wp->base.title, data->arg) == NULL) fnmatch(searchstr, wp->base.title, 0) != 0)
continue; continue;
if (sres == NULL) { if (sres == NULL) {
@@ -92,7 +91,9 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
"pane %u title: \"%s\"", i - 1, "pane %u title: \"%s\"", i - 1,
wp->base.title); wp->base.title);
} else { } else {
xasprintf(&sctx, "\"%s\"", sres); xasprintf(&sctx,
"pane %u line %u: \"%s\"", i - 1,
line + 1, sres);
xfree(sres); xfree(sres);
} }
} }
@@ -101,6 +102,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
ARRAY_ADD(&list_ctx, sctx); ARRAY_ADD(&list_ctx, sctx);
} }
} }
xfree(searchstr);
if (ARRAY_LENGTH(&list_idx) == 0) { if (ARRAY_LENGTH(&list_idx) == 0) {
ctx->error(ctx, "no windows matching: %s", data->arg); ctx->error(ctx, "no windows matching: %s", data->arg);
@@ -136,7 +138,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
fatalx("session not found"); fatalx("session not found");
window_choose_ready( window_choose_ready(
wl->window->active, 0, cmd_find_window_callback, cdata); wl->window->active, 0, cmd_find_window_callback, xfree, cdata);
out: out:
ARRAY_FREE(&list_idx); ARRAY_FREE(&list_idx);
@@ -157,48 +159,4 @@ cmd_find_window_callback(void *data, int idx)
server_redraw_session(s); server_redraw_session(s);
recalculate_sizes(); recalculate_sizes();
} }
xfree(cdata);
}
char *
cmd_find_window_search(struct window_pane *wp, const char *searchstr)
{
const struct grid_cell *gc;
const struct grid_utf8 *gu;
char *buf, *s;
size_t off;
u_int i, j, k;
buf = xmalloc(1);
for (j = 0; j < screen_size_y(&wp->base); j++) {
off = 0;
for (i = 0; i < screen_size_x(&wp->base); i++) {
gc = grid_view_peek_cell(wp->base.grid, i, j);
if (gc->flags & GRID_FLAG_UTF8) {
gu = grid_view_peek_utf8(wp->base.grid, i, j);
buf = xrealloc(buf, 1, off + 8);
for (k = 0; k < UTF8_SIZE; k++) {
if (gu->data[k] == 0xff)
break;
buf[off++] = gu->data[k];
}
} else {
buf = xrealloc(buf, 1, off + 1);
buf[off++] = gc->data;
}
}
while (off > 0 && buf[off - 1] == ' ')
off--;
buf[off] = '\0';
if ((s = strstr(buf, searchstr)) != NULL) {
s = section_string(buf, off, s - buf, 40);
xfree(buf);
return (s);
}
}
xfree(buf);
return (NULL);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-generic.c,v 1.25 2009-04-03 17:31:44 nicm Exp $ */ /* $Id: cmd-generic.c,v 1.34 2009-08-26 22:13:52 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -23,101 +23,91 @@
#include "tmux.h" #include "tmux.h"
#define CMD_FLAGS "adDgkuU" int cmd_getopt(int, char **, const char *, uint64_t);
#define CMD_FLAGMASK (CMD_AFLAG|CMD_DFLAG|CMD_UPPERDFLAG|CMD_GFLAG|CMD_KFLAG| \ int cmd_flags(int, uint64_t, uint64_t *);
CMD_UFLAG|CMD_UPPERUFLAG) size_t cmd_print_flags(char *, size_t, size_t, uint64_t);
int cmd_fill_argument(int, char **, char **, int, char **);
int cmd_do_flags(int, int, int *);
size_t cmd_print_flags(char *, size_t, size_t, int);
int cmd_fill_argument(int, char **, int, char **);
size_t size_t
cmd_prarg(char *buf, size_t len, const char *prefix, char *arg) cmd_prarg(char *buf, size_t len, const char *prefix, char *arg)
{ {
if (strchr(arg, ' ' ) != NULL) if (strchr(arg, ' ') != NULL)
return (xsnprintf(buf, len, "%s\"%s\"", prefix, arg)); return (xsnprintf(buf, len, "%s\"%s\"", prefix, arg));
return (xsnprintf(buf, len, "%s%s", prefix, arg)); return (xsnprintf(buf, len, "%s%s", prefix, arg));
} }
/* Prepend flags from chflags onto flagstr and call getopt. */
int int
cmd_do_flags(int opt, int iflags, int *oflags) cmd_getopt(int argc, char **argv, const char *flagstr, uint64_t chflags)
{ {
switch (opt) { u_char ch;
case 'a': char buf[128];
if (iflags & CMD_AFLAG) { size_t len, off;
(*oflags) |= CMD_AFLAG;
return (0); *buf = '\0';
}
return (-1); len = sizeof buf;
case 'd': off = 0;
if (iflags & CMD_DFLAG) {
(*oflags) |= CMD_DFLAG; for (ch = 0; ch < 26; ch++) {
return (0); if (chflags & CMD_CHFLAG('a' + ch))
} off += xsnprintf(buf + off, len - off, "%c", 'a' + ch);
return (-1); if (chflags & CMD_CHFLAG('A' + ch))
case 'D': off += xsnprintf(buf + off, len - off, "%c", 'A' + ch);
if (iflags & CMD_UPPERDFLAG) {
(*oflags) |= CMD_UPPERDFLAG;
return (0);
}
return (-1);
case 'g':
if (iflags & CMD_GFLAG) {
(*oflags) |= CMD_GFLAG;
return (0);
}
return (-1);
case 'k':
if (iflags & CMD_KFLAG) {
(*oflags) |= CMD_KFLAG;
return (0);
}
return (-1);
case 'u':
if (iflags & CMD_UFLAG) {
(*oflags) |= CMD_UFLAG;
return (0);
}
return (-1);
case 'U':
if (iflags & CMD_UPPERUFLAG) {
(*oflags) |= CMD_UPPERUFLAG;
return (0);
}
return (-1);
} }
return (1);
strlcat(buf, flagstr, sizeof buf);
return (getopt(argc, argv, buf));
} }
size_t /*
cmd_print_flags(char *buf, size_t len, size_t off, int flags) * If this option is expected (in ichflags), set it in ochflags, otherwise
* return -1.
*/
int
cmd_flags(int opt, uint64_t ichflags, uint64_t *ochflags)
{ {
u_char ch;
for (ch = 0; ch < 26; ch++) {
if (opt == 'a' + ch && ichflags & CMD_CHFLAG(opt)) {
(*ochflags) |= CMD_CHFLAG(opt);
return (0);
}
if (opt == 'A' + ch && ichflags & CMD_CHFLAG(opt)) {
(*ochflags) |= CMD_CHFLAG(opt);
return (0);
}
}
return (-1);
}
/* Print the flags supported in chflags. */
size_t
cmd_print_flags(char *buf, size_t len, size_t off, uint64_t chflags)
{
u_char ch;
size_t boff = off; size_t boff = off;
if ((flags & CMD_FLAGMASK) == 0) if (chflags == 0)
return (0); return (0);
off += xsnprintf(buf + off, len - off, " -"); off += xsnprintf(buf + off, len - off, " -");
if (off < len && flags & CMD_AFLAG)
off += xsnprintf(buf + off, len - off, "a"); for (ch = 0; ch < 26; ch++) {
if (off < len && flags & CMD_UPPERDFLAG) if (chflags & CMD_CHFLAG('a' + ch))
off += xsnprintf(buf + off, len - off, "D"); off += xsnprintf(buf + off, len - off, "%c", 'a' + ch);
if (off < len && flags & CMD_DFLAG) if (chflags & CMD_CHFLAG('A' + ch))
off += xsnprintf(buf + off, len - off, "d"); off += xsnprintf(buf + off, len - off, "%c", 'A' + ch);
if (off < len && flags & CMD_GFLAG) }
off += xsnprintf(buf + off, len - off, "g");
if (off < len && flags & CMD_KFLAG)
off += xsnprintf(buf + off, len - off, "k");
if (off < len && flags & CMD_UFLAG)
off += xsnprintf(buf + off, len - off, "u");
if (off < len && flags & CMD_UPPERUFLAG)
off += xsnprintf(buf + off, len - off, "U");
return (off - boff); return (off - boff);
} }
int int
cmd_fill_argument(int flags, char **arg, int argc, char **argv) cmd_fill_argument(int flags, char **arg, char **arg2, int argc, char **argv)
{ {
*arg = NULL; *arg = NULL;
*arg2 = NULL;
if (flags & CMD_ARG1) { if (flags & CMD_ARG1) {
if (argc != 1) if (argc != 1)
@@ -134,6 +124,23 @@ cmd_fill_argument(int flags, char **arg, int argc, char **argv)
return (0); return (0);
} }
if (flags & CMD_ARG2) {
if (argc != 2)
return (-1);
*arg = xstrdup(argv[0]);
*arg2 = xstrdup(argv[1]);
return (0);
}
if (flags & CMD_ARG12) {
if (argc != 1 && argc != 2)
return (-1);
*arg = xstrdup(argv[0]);
if (argc == 2)
*arg2 = xstrdup(argv[1]);
return (0);
}
if (argc != 0) if (argc != 0)
return (-1); return (-1);
return (0); return (0);
@@ -145,28 +152,26 @@ cmd_target_init(struct cmd *self, unused int key)
struct cmd_target_data *data; struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->flags = 0; data->chflags = 0;
data->target = NULL; data->target = NULL;
data->arg = NULL; data->arg = NULL;
data->arg2 = NULL;
} }
int int
cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_target_data *data; struct cmd_target_data *data;
const struct cmd_entry *entry = self->entry;
int opt; int opt;
/* Don't use the entry version since it may be dependent on key. */ /* Don't use the entry version since it may be dependent on key. */
cmd_target_init(self, 0); cmd_target_init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) { while ((opt = cmd_getopt(argc, argv, "t:", entry->chflags)) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
case -1:
goto usage;
case 0:
continue; continue;
}
switch (opt) { switch (opt) {
case 't': case 't':
if (data->target == NULL) if (data->target == NULL)
@@ -179,7 +184,8 @@ cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0) if (cmd_fill_argument(
self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
goto usage; goto usage;
return (0); return (0);
@@ -190,27 +196,6 @@ usage:
return (-1); return (-1);
} }
void
cmd_target_send(struct cmd *self, struct buffer *b)
{
struct cmd_target_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_target_recv(struct cmd *self, struct buffer *b)
{
struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void void
cmd_target_free(struct cmd *self) cmd_target_free(struct cmd *self)
{ {
@@ -220,6 +205,8 @@ cmd_target_free(struct cmd *self)
xfree(data->target); xfree(data->target);
if (data->arg != NULL) if (data->arg != NULL)
xfree(data->arg); xfree(data->arg);
if (data->arg2 != NULL)
xfree(data->arg2);
xfree(data); xfree(data);
} }
@@ -232,11 +219,13 @@ cmd_target_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name); off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL) if (data == NULL)
return (off); return (off);
off += cmd_print_flags(buf, len, off, data->flags); off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->target != NULL) if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target); off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL) if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg); off += cmd_prarg(buf + off, len - off, " ", data->arg);
if (off < len && data->arg2 != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg2);
return (off); return (off);
} }
@@ -246,28 +235,26 @@ cmd_srcdst_init(struct cmd *self, unused int key)
struct cmd_srcdst_data *data; struct cmd_srcdst_data *data;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->flags = 0; data->chflags = 0;
data->src = NULL; data->src = NULL;
data->dst = NULL; data->dst = NULL;
data->arg = NULL; data->arg = NULL;
data->arg2 = NULL;
} }
int int
cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_srcdst_data *data; struct cmd_srcdst_data *data;
const struct cmd_entry *entry = self->entry;
int opt; int opt;
cmd_srcdst_init(self, 0); cmd_srcdst_init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "s:t:")) != -1) { while ((opt = cmd_getopt(argc, argv, "s:t:", entry->chflags)) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
case -1:
goto usage;
case 0:
continue; continue;
}
switch (opt) { switch (opt) {
case 's': case 's':
if (data->src == NULL) if (data->src == NULL)
@@ -284,7 +271,8 @@ cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0) if (cmd_fill_argument(
self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
goto usage; goto usage;
return (0); return (0);
@@ -295,29 +283,6 @@ usage:
return (-1); return (-1);
} }
void
cmd_srcdst_send(struct cmd *self, struct buffer *b)
{
struct cmd_srcdst_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->src);
cmd_send_string(b, data->dst);
cmd_send_string(b, data->arg);
}
void
cmd_srcdst_recv(struct cmd *self, struct buffer *b)
{
struct cmd_srcdst_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->src = cmd_recv_string(b);
data->dst = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void void
cmd_srcdst_free(struct cmd *self) cmd_srcdst_free(struct cmd *self)
{ {
@@ -329,6 +294,8 @@ cmd_srcdst_free(struct cmd *self)
xfree(data->dst); xfree(data->dst);
if (data->arg != NULL) if (data->arg != NULL)
xfree(data->arg); xfree(data->arg);
if (data->arg2 != NULL)
xfree(data->arg2);
xfree(data); xfree(data);
} }
@@ -341,13 +308,15 @@ cmd_srcdst_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name); off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL) if (data == NULL)
return (off); return (off);
off += cmd_print_flags(buf, len, off, data->flags); off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->src != NULL) if (off < len && data->src != NULL)
off += xsnprintf(buf + off, len - off, " -s %s", data->src); off += xsnprintf(buf + off, len - off, " -s %s", data->src);
if (off < len && data->dst != NULL) if (off < len && data->dst != NULL)
off += xsnprintf(buf + off, len - off, " -t %s", data->dst); off += xsnprintf(buf + off, len - off, " -t %s", data->dst);
if (off < len && data->arg != NULL) if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg); off += cmd_prarg(buf + off, len - off, " ", data->arg);
if (off < len && data->arg2 != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg2);
return (off); return (off);
} }
@@ -357,29 +326,27 @@ cmd_buffer_init(struct cmd *self, unused int key)
struct cmd_buffer_data *data; struct cmd_buffer_data *data;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->flags = 0; data->chflags = 0;
data->target = NULL; data->target = NULL;
data->buffer = -1; data->buffer = -1;
data->arg = NULL; data->arg = NULL;
data->arg2 = NULL;
} }
int int
cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_buffer_data *data; struct cmd_buffer_data *data;
const struct cmd_entry *entry = self->entry;
int opt, n; int opt, n;
const char *errstr; const char *errstr;
cmd_buffer_init(self, 0); cmd_buffer_init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "b:t:")) != -1) { while ((opt = cmd_getopt(argc, argv, "b:t:", entry->chflags)) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
case -1:
goto usage;
case 0:
continue; continue;
}
switch (opt) { switch (opt) {
case 'b': case 'b':
if (data->buffer == -1) { if (data->buffer == -1) {
@@ -402,7 +369,8 @@ cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0) if (cmd_fill_argument(
self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
goto usage; goto usage;
return (0); return (0);
@@ -414,27 +382,6 @@ error:
return (-1); return (-1);
} }
void
cmd_buffer_send(struct cmd *self, struct buffer *b)
{
struct cmd_buffer_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_buffer_recv(struct cmd *self, struct buffer *b)
{
struct cmd_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void void
cmd_buffer_free(struct cmd *self) cmd_buffer_free(struct cmd *self)
{ {
@@ -444,6 +391,8 @@ cmd_buffer_free(struct cmd *self)
xfree(data->target); xfree(data->target);
if (data->arg != NULL) if (data->arg != NULL)
xfree(data->arg); xfree(data->arg);
if (data->arg2 != NULL)
xfree(data->arg2);
xfree(data); xfree(data);
} }
@@ -456,239 +405,14 @@ cmd_buffer_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name); off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL) if (data == NULL)
return (off); return (off);
off += cmd_print_flags(buf, len, off, data->flags); off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->buffer != -1) if (off < len && data->buffer != -1)
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer); off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
if (off < len && data->target != NULL) if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target); off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL) if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg); off += cmd_prarg(buf + off, len - off, " ", data->arg);
return (off); if (off < len && data->arg2 != NULL)
} off += cmd_prarg(buf + off, len - off, " ", data->arg2);
void
cmd_option_init(struct cmd *self, unused int key)
{
struct cmd_option_data *data;
self->data = data = xmalloc(sizeof *data);
data->flags = 0;
data->target = NULL;
data->option = NULL;
data->value = NULL;
}
int
cmd_option_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_option_data *data;
int opt;
/* Don't use the entry version since it may be dependent on key. */
cmd_option_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
case -1:
goto usage;
case 0:
continue;
}
switch (opt) {
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc == 2) {
data->option = xstrdup(argv[0]);
data->value = xstrdup(argv[1]);
} else if (argc == 1)
data->option = xstrdup(argv[0]);
else
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
void
cmd_option_send(struct cmd *self, struct buffer *b)
{
struct cmd_option_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->option);
cmd_send_string(b, data->value);
}
void
cmd_option_recv(struct cmd *self, struct buffer *b)
{
struct cmd_option_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->option = cmd_recv_string(b);
data->value = cmd_recv_string(b);
}
void
cmd_option_free(struct cmd *self)
{
struct cmd_option_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->option != NULL)
xfree(data->option);
if (data->value != NULL)
xfree(data->value);
xfree(data);
}
size_t
cmd_option_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_option_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->flags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->option != NULL)
off += xsnprintf(buf + off, len - off, " %s", data->option);
if (off < len && data->value != NULL)
off += xsnprintf(buf + off, len - off, " %s", data->value);
return (off);
}
void
cmd_pane_init(struct cmd *self, unused int key)
{
struct cmd_pane_data *data;
self->data = data = xmalloc(sizeof *data);
data->flags = 0;
data->target = NULL;
data->arg = NULL;
data->pane = -1;
}
int
cmd_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_pane_data *data;
int opt, n;
const char *errstr;
/* Don't use the entry version since it may be dependent on key. */
cmd_pane_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "p:t:")) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
case -1:
goto usage;
case 0:
continue;
}
switch (opt) {
case 'p':
if (data->pane == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "pane %s", errstr);
goto error;
}
data->pane = n;
}
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
void
cmd_pane_send(struct cmd *self, struct buffer *b)
{
struct cmd_pane_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_pane_recv(struct cmd *self, struct buffer *b)
{
struct cmd_pane_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_pane_free(struct cmd *self)
{
struct cmd_pane_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->arg != NULL)
xfree(data->arg);
xfree(data);
}
size_t
cmd_pane_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_pane_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->flags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg);
return (off); return (off);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-has-session.c,v 1.12 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-has-session.c,v 1.14 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_has_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_has_session_entry = { const struct cmd_entry cmd_has_session_entry = {
"has-session", "has", "has-session", "has",
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_has_session_exec, cmd_has_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

151
cmd-if-shell.c Normal file
View File

@@ -0,0 +1,151 @@
/* $Id: cmd-if-shell.c,v 1.4 2009-07-28 22:12:16 tcunha Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Executes a tmux command if a shell command returns true.
*/
int cmd_if_shell_parse(struct cmd *, int, char **, char **);
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
void cmd_if_shell_free(struct cmd *);
void cmd_if_shell_init(struct cmd *, int);
size_t cmd_if_shell_print(struct cmd *, char *, size_t);
struct cmd_if_shell_data {
char *cmd;
char *sh_cmd;
};
const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if",
"shell-command command",
0, 0,
cmd_if_shell_init,
cmd_if_shell_parse,
cmd_if_shell_exec,
cmd_if_shell_free,
cmd_if_shell_print
};
void
cmd_if_shell_init(struct cmd *self, unused int arg)
{
struct cmd_if_shell_data *data;
self->data = data = xmalloc(sizeof *data);
data->cmd = NULL;
data->sh_cmd = NULL;
}
int
cmd_if_shell_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_if_shell_data *data;
int opt;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "")) != -1) {
switch (opt) {
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 2)
goto usage;
data->sh_cmd = xstrdup(argv[0]);
data->cmd = xstrdup(argv[1]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int
cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_if_shell_data *data = self->data;
struct cmd_list *cmdlist;
char *cause;
int ret;
if ((ret = system(data->sh_cmd)) < 0) {
ctx->error(ctx, "system error: %s", strerror(errno));
return (-1);
} else if (ret != 0)
return (0);
if (cmd_string_parse(data->cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) {
ctx->error(ctx, "%s", cause);
xfree(cause);
}
return (-1);
}
if (cmd_list_exec(cmdlist, ctx) < 0) {
cmd_list_free(cmdlist);
return (-1);
}
cmd_list_free(cmdlist);
return (0);
}
void
cmd_if_shell_free(struct cmd *self)
{
struct cmd_if_shell_data *data = self->data;
if (data->cmd != NULL)
xfree(data->cmd);
if (data->sh_cmd != NULL)
xfree(data->sh_cmd);
xfree(data);
}
size_t
cmd_if_shell_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_if_shell_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->sh_cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->sh_cmd);
if (off < len && data->cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->cmd);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-pane.c,v 1.6 2009-04-01 21:10:08 nicm Exp $ */ /* $Id: cmd-kill-pane.c,v 1.12 2009-07-30 20:45:20 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,43 +30,33 @@ int cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_pane_entry = { const struct cmd_entry cmd_kill_pane_entry = {
"kill-pane", "killp", "kill-pane", "killp",
CMD_PANE_WINDOW_USAGE, CMD_TARGET_PANE_USAGE,
0, 0, 0,
cmd_pane_init, cmd_target_init,
cmd_pane_parse, cmd_target_parse,
cmd_kill_pane_exec, cmd_kill_pane_exec,
cmd_pane_send, cmd_target_free,
cmd_pane_recv, cmd_target_print
cmd_pane_free,
cmd_pane_print
}; };
int int
cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_pane_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1); return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (window_count_panes(wl->window) == 1) { if (window_count_panes(wl->window) == 1) {
ctx->error(ctx, "can't kill pane: %d", data->pane); /* Only one pane, kill the window. */
return (-1); server_kill_window(wl->window);
return (0);
} }
layout_close_pane(wp);
window_remove_pane(wl->window, wp); window_remove_pane(wl->window, wp);
server_redraw_window(wl->window); server_redraw_window(wl->window);
layout_refresh(wl->window, 0);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-server.c,v 1.6 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-kill-server.c,v 1.8 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,13 +32,11 @@ int cmd_kill_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_server_entry = { const struct cmd_entry cmd_kill_server_entry = {
"kill-server", NULL, "kill-server", NULL,
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_kill_server_exec, cmd_kill_server_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-session.c,v 1.12 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-kill-session.c,v 1.14 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,12 +32,10 @@ int cmd_kill_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_session_entry = { const struct cmd_entry cmd_kill_session_entry = {
"kill-session", NULL, "kill-session", NULL,
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_kill_session_exec, cmd_kill_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-window.c,v 1.15 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-kill-window.c,v 1.19 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_kill_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_window_entry = { const struct cmd_entry cmd_kill_window_entry = {
"kill-window", "killw", "kill-window", "killw",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_kill_window_exec, cmd_kill_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -44,26 +42,11 @@ cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct session *s;
struct client *c;
u_int i;
int destroyed;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
destroyed = session_detach(s, wl); server_kill_window(wl->window);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != s)
continue;
if (destroyed) {
c->session = NULL;
server_write_client(c, MSG_EXIT, NULL, 0);
} else
server_redraw_client(c);
}
recalculate_sizes();
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-last-window.c,v 1.16 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-last-window.c,v 1.18 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_last_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_last_window_entry = { const struct cmd_entry cmd_last_window_entry = {
"last-window", "last", "last-window", "last",
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_last_window_exec, cmd_last_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-link-window.c,v 1.28 2009-01-23 16:59:14 nicm Exp $ */ /* $Id: cmd-link-window.c,v 1.32 2009-08-16 19:16:27 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_link_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_link_window_entry = { const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw", "link-window", "linkw",
"[-dk] " CMD_SRCDST_WINDOW_USAGE, "[-dk] " CMD_SRCDST_WINDOW_USAGE,
CMD_DFLAG|CMD_KFLAG, 0, CMD_CHFLAG('d')|CMD_CHFLAG('k'),
cmd_srcdst_init, cmd_srcdst_init,
cmd_srcdst_parse, cmd_srcdst_parse,
cmd_link_window_exec, cmd_link_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free, cmd_srcdst_free,
cmd_srcdst_print cmd_srcdst_print
}; };
@@ -52,19 +50,8 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL) if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL)
return (-1); return (-1);
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
if (arg_parse_window(data->dst, &dst, &idx) != 0) {
ctx->error(ctx, "bad window: %s", data->dst);
return (-1); return (-1);
}
if (dst == NULL)
dst = ctx->cursession;
if (dst == NULL)
dst = cmd_current_session(ctx);
if (dst == NULL) {
ctx->error(ctx, "session not found: %s", data->dst);
return (-1);
}
wl_dst = NULL; wl_dst = NULL;
if (idx != -1) if (idx != -1)
@@ -73,7 +60,7 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (wl_dst->window == wl_src->window) if (wl_dst->window == wl_src->window)
return (0); return (0);
if (data->flags & CMD_KFLAG) { if (data->chflags & CMD_CHFLAG('k')) {
/* /*
* Can't use session_detach as it will destroy session * Can't use session_detach as it will destroy session
* if this makes it empty. * if this makes it empty.
@@ -84,12 +71,14 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Force select/redraw if current. */ /* Force select/redraw if current. */
if (wl_dst == dst->curw) { if (wl_dst == dst->curw) {
data->flags &= ~CMD_DFLAG; data->chflags &= ~CMD_CHFLAG('d');
dst->curw = NULL; dst->curw = NULL;
} }
} }
} }
if (idx == -1)
idx = -1 - options_get_number(&dst->options, "base-index");
wl_dst = session_attach(dst, wl_src->window, idx, &cause); wl_dst = session_attach(dst, wl_src->window, idx, &cause);
if (wl_dst == NULL) { if (wl_dst == NULL) {
ctx->error(ctx, "create session failed: %s", cause); ctx->error(ctx, "create session failed: %s", cause);
@@ -97,7 +86,7 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
} }
if (data->flags & CMD_DFLAG) if (data->chflags & CMD_CHFLAG('d'))
server_status_session(dst); server_status_session(dst);
else { else {
session_select(dst, wl_dst->idx); session_select(dst, wl_dst->idx);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-buffers.c,v 1.7 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-list-buffers.c,v 1.12 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_list_buffers_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_buffers_entry = { const struct cmd_entry cmd_list_buffers_entry = {
"list-buffers", "lsb", "list-buffers", "lsb",
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_list_buffers_exec, cmd_list_buffers_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -48,44 +46,33 @@ cmd_list_buffers_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
u_int idx; u_int idx;
char *tmp; char tmp[51 * 4 + 1];
size_t size, in, out; size_t size, len;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
if (s->sx > 35) { /* leave three for ... */
size = s->sx - 32;
tmp = xmalloc(size + 1);
} else {
size = 0;
tmp = NULL;
}
idx = 0; idx = 0;
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) { while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) {
if (tmp != NULL) { size = pb->size;
in = out = 0;
while (out < size && pb->data[in] != '\0') {
if (pb->data[in] > 31 && pb->data[in] != 127)
tmp[out++] = pb->data[in];
in++;
}
tmp[out] = '\0';
if (out == size) {
tmp[out - 1] = '.';
tmp[out - 2] = '.';
tmp[out - 3] = '.';
}
ctx->print(ctx, "%d: %zu bytes: \"%s\"", /* Translate the first 50 characters. */
idx - 1, strlen(pb->data), tmp); len = size;
} else if (len > 50)
ctx->print(ctx, "%d: %zu bytes", idx, strlen(pb->data)); len = 50;
strvisx(tmp, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
/*
* If the first 50 characterswere encoded as a longer string,
* or there is definitely more data, add "...".
*/
if (size > 50 || strlen(tmp) > 50) {
tmp[50 - 3] = '\0';
strlcat(tmp, "...", sizeof tmp);
}
ctx->print(ctx, "%u: %zu bytes: \"%s\"", idx - 1, size, tmp);
} }
if (tmp != NULL)
xfree(tmp);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-clients.c,v 1.13 2009-02-11 17:50:32 nicm Exp $ */ /* $Id: cmd-list-clients.c,v 1.18 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,13 +32,11 @@ int cmd_list_clients_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_clients_entry = { const struct cmd_entry cmd_list_clients_entry = {
"list-clients", "lsc", "list-clients", "lsc",
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_list_clients_exec, cmd_list_clients_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };
@@ -47,14 +45,20 @@ cmd_list_clients_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{ {
struct client *c; struct client *c;
u_int i; u_int i;
const char *s_utf8;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i); c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL) if (c == NULL || c->session == NULL)
continue; continue;
ctx->print(ctx, "%s: %s [%ux%u %s]", c->tty.path, if (c->tty.flags & TTY_UTF8)
c->session->name, c->tty.sx, c->tty.sy, c->tty.termname); s_utf8 = " (utf8)";
else
s_utf8 = "";
ctx->print(ctx, "%s: %s [%ux%u %s]%s", c->tty.path,
c->session->name, c->tty.sx, c->tty.sy,
c->tty.termname, s_utf8);
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-commands.c,v 1.3 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-list-commands.c,v 1.5 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,13 +29,11 @@ int cmd_list_commands_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_commands_entry = { const struct cmd_entry cmd_list_commands_entry = {
"list-commands", "lscm", "list-commands", "lscm",
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_list_commands_exec, cmd_list_commands_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-keys.c,v 1.13 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-list-keys.c,v 1.20 2009-07-28 23:19:06 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -26,33 +28,97 @@
int cmd_list_keys_exec(struct cmd *, struct cmd_ctx *); int cmd_list_keys_exec(struct cmd *, struct cmd_ctx *);
int cmd_list_keys_table(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_keys_entry = { const struct cmd_entry cmd_list_keys_entry = {
"list-keys", "lsk", "list-keys", "lsk",
"", "[-t key-table]",
0, 0, 0,
NULL, cmd_target_init,
NULL, cmd_target_parse,
cmd_list_keys_exec, cmd_list_keys_exec,
NULL, cmd_target_free,
NULL, cmd_target_print
NULL,
NULL
}; };
int int
cmd_list_keys_exec(unused struct cmd *self, struct cmd_ctx *ctx) cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data;
struct key_binding *bd; struct key_binding *bd;
const char *key; const char *key;
char tmp[BUFSIZ]; char tmp[BUFSIZ], keytmp[64];
int width, keywidth;
if (data->target != NULL)
return (cmd_list_keys_table(self, ctx));
width = 0;
SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue;
keywidth = strlen(key) + 1;
if (!(bd->key & KEYC_PREFIX))
keywidth += 2;
if (keywidth > width)
width = keywidth;
}
SPLAY_FOREACH(bd, key_bindings, &key_bindings) { SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
if ((key = key_string_lookup_key(bd->key)) == NULL) key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue; continue;
*tmp = '\0'; *tmp = '\0';
cmd_list_print(bd->cmdlist, tmp, sizeof tmp); cmd_list_print(bd->cmdlist, tmp, sizeof tmp);
ctx->print(ctx, "%11s: %s", key, tmp); if (!(bd->key & KEYC_PREFIX)) {
xsnprintf(keytmp, sizeof keytmp, "[%s]", key);
key = keytmp;
}
ctx->print(ctx, "%*s: %s", width, key, tmp);
}
return (0);
}
int
cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
const struct mode_key_table *mtab;
struct mode_key_binding *mbind;
const char *key, *cmdstr, *mode;
int width, keywidth;
if ((mtab = mode_key_findtable(data->target)) == NULL) {
ctx->error(ctx, "unknown key table: %s", data->target);
return (-1);
}
width = 0;
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
keywidth = strlen(key) + 1;
if (keywidth > width)
width = keywidth;
}
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
mode = "";
if (mbind->mode != 0)
mode = "(command mode) ";
cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd);
if (cmdstr != NULL)
ctx->print(ctx, "%*s: %s%s", width, key, mode, cmdstr);
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-sessions.c,v 1.19 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-list-sessions.c,v 1.21 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,13 +31,11 @@ int cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_sessions_entry = { const struct cmd_entry cmd_list_sessions_entry = {
"list-sessions", "ls", "", "list-sessions", "ls", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_list_sessions_exec, cmd_list_sessions_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-windows.c,v 1.33 2009-03-28 20:17:29 nicm Exp $ */ /* $Id: cmd-list-windows.c,v 1.40 2009-08-09 17:28:23 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_list_windows_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_windows_entry = { const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw", "list-windows", "lsw",
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_list_windows_exec, cmd_list_windows_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -50,6 +48,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
struct grid *gd; struct grid *gd;
struct grid_line *gl;
u_int i; u_int i;
unsigned long long size; unsigned long long size;
const char *name; const char *name;
@@ -67,15 +66,16 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
size = 0; size = 0;
for (i = 0; i < gd->hsize; i++) { for (i = 0; i < gd->hsize; i++) {
size += gd->size[i] * sizeof **gd->data; gl = &gd->linedata[i];
size += gd->usize[i] * sizeof **gd->udata; size += gl->cellsize * sizeof *gl->celldata;
size += gl->utf8size * sizeof *gl->utf8data;
} }
size += gd->hsize * (sizeof *gd->data); size += gd->hsize * sizeof *gd->linedata;
size += gd->hsize * (sizeof *gd->size);
name = NULL;
if (wp->fd != -1) if (wp->fd != -1)
name = ttyname(wp->fd); name = ttyname(wp->fd);
else if (name == NULL)
name = "unknown"; name = "unknown";
ctx->print(ctx, ctx->print(ctx,
" %s [%ux%u] [history %u/%u, %llu bytes]", " %s [%ux%u] [history %u/%u, %llu bytes]",

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list.c,v 1.3 2009-02-16 18:57:16 nicm Exp $ */ /* $Id: cmd-list.c,v 1.6 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,28 +28,43 @@ cmd_list_parse(int argc, char **argv, char **cause)
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmd *cmd; struct cmd *cmd;
int i, lastsplit; int i, lastsplit;
size_t arglen, new_argc;
char **new_argv;
cmdlist = xmalloc(sizeof *cmdlist); cmdlist = xmalloc(sizeof *cmdlist);
TAILQ_INIT(cmdlist); TAILQ_INIT(cmdlist);
lastsplit = 0; lastsplit = 0;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
if (strcmp(argv[i], "\\;") == 0) { arglen = strlen(argv[i]);
argv[i][0] = ';'; if (arglen == 0 || argv[i][arglen - 1] != ';')
argv[i][1] = '\0'; continue;
} else if (strcmp(argv[i], ";") == 0) { argv[i][arglen - 1] = '\0';
cmd = cmd_parse(i - lastsplit, argv + lastsplit, cause);
if (cmd == NULL) if (arglen > 1 && argv[i][arglen - 2] == '\\') {
goto bad; argv[i][arglen - 2] = ';';
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry); continue;
lastsplit = i + 1;
} }
new_argc = i - lastsplit;
new_argv = argv + lastsplit;
if (arglen != 1)
new_argc++;
cmd = cmd_parse(new_argc, new_argv, cause);
if (cmd == NULL)
goto bad;
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
lastsplit = i + 1;
} }
cmd = cmd_parse(argc - lastsplit, argv + lastsplit, cause); if (lastsplit != argc) {
if (cmd == NULL) cmd = cmd_parse(argc - lastsplit, argv + lastsplit, cause);
goto bad; if (cmd == NULL)
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry); goto bad;
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
}
return (cmdlist); return (cmdlist);
@@ -71,41 +86,6 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
return (0); return (0);
} }
void
cmd_list_send(struct cmd_list *cmdlist, struct buffer *b)
{
struct cmd *cmd;
u_int n;
n = 0;
TAILQ_FOREACH(cmd, cmdlist, qentry)
n++;
buffer_write(b, &n, sizeof n);
TAILQ_FOREACH(cmd, cmdlist, qentry)
cmd_send(cmd, b);
}
struct cmd_list *
cmd_list_recv(struct buffer *b)
{
struct cmd_list *cmdlist;
struct cmd *cmd;
u_int n;
buffer_read(b, &n, sizeof n);
cmdlist = xmalloc(sizeof *cmdlist);
TAILQ_INIT(cmdlist);
while (n-- > 0) {
cmd = cmd_recv(b);
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
}
return (cmdlist);
}
void void
cmd_list_free(struct cmd_list *cmdlist) cmd_list_free(struct cmd_list *cmdlist)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-load-buffer.c,v 1.2 2009-01-27 23:26:15 nicm Exp $ */ /* $Id: cmd-load-buffer.c,v 1.10 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -35,12 +35,10 @@ int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_load_buffer_entry = { const struct cmd_entry cmd_load_buffer_entry = {
"load-buffer", "loadb", "load-buffer", "loadb",
CMD_BUFFER_SESSION_USAGE " path", CMD_BUFFER_SESSION_USAGE " path",
CMD_ARG1, CMD_ARG1, 0,
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_load_buffer_exec, cmd_load_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -50,20 +48,20 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct session *s; struct session *s;
struct stat statbuf; struct stat sb;
FILE *f; FILE *f;
char *buf; u_char *buf;
u_int limit; u_int limit;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
if (stat(data->arg, &statbuf) < 0) { if (stat(data->arg, &sb) < 0) {
ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
return (-1); return (-1);
} }
if ((f = fopen(data->arg, "r")) == NULL) { if ((f = fopen(data->arg, "rb")) == NULL) {
ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
return (-1); return (-1);
} }
@@ -72,27 +70,27 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
* We don't want to die due to memory exhaustion, hence xmalloc can't * We don't want to die due to memory exhaustion, hence xmalloc can't
* be used here. * be used here.
*/ */
if ((buf = malloc(statbuf.st_size + 1)) == NULL) { if ((buf = malloc(sb.st_size + 1)) == NULL) {
ctx->error(ctx, "malloc error: %s", strerror(errno)); ctx->error(ctx, "malloc error: %s", strerror(errno));
fclose(f);
return (-1); return (-1);
} }
if (fread(buf, 1, statbuf.st_size, f) != (size_t) statbuf.st_size) { if (fread(buf, 1, sb.st_size, f) != (size_t) sb.st_size) {
ctx->error(ctx, "%s: fread error", data->arg); ctx->error(ctx, "%s: fread error", data->arg);
xfree(buf); xfree(buf);
fclose(f); fclose(f);
return (-1); return (-1);
} }
buf[statbuf.st_size] = '\0';
fclose(f); fclose(f);
limit = options_get_number(&s->options, "buffer-limit"); limit = options_get_number(&s->options, "buffer-limit");
if (data->buffer == -1) { if (data->buffer == -1) {
paste_add(&s->buffers, buf, limit); paste_add(&s->buffers, buf, sb.st_size, limit);
return (0); return (0);
} }
if (paste_replace(&s->buffers, data->buffer, buf) != 0) { if (paste_replace(&s->buffers, data->buffer, buf, sb.st_size) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
xfree(buf); xfree(buf);
return (-1); return (-1);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-lock-server.c,v 1.2 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-lock-server.c,v 1.6 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,19 +30,15 @@
int cmd_lock_server_exec(struct cmd *, struct cmd_ctx *); int cmd_lock_server_exec(struct cmd *, struct cmd_ctx *);
int cmd_lock_server_callback(void *, const char *);
const struct cmd_entry cmd_lock_server_entry = { const struct cmd_entry cmd_lock_server_entry = {
"lock-server", "lock", "lock-server", "lock",
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_lock_server_exec, cmd_lock_server_exec,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
}; };
int int

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-move-window.c,v 1.5 2009-01-23 16:59:14 nicm Exp $ */ /* $Id: cmd-move-window.c,v 1.9 2009-08-16 19:16:27 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_move_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_move_window_entry = { const struct cmd_entry cmd_move_window_entry = {
"move-window", "movew", "move-window", "movew",
"[-dk] " CMD_SRCDST_WINDOW_USAGE, "[-dk] " CMD_SRCDST_WINDOW_USAGE,
CMD_DFLAG|CMD_KFLAG, 0, CMD_CHFLAG('d')|CMD_CHFLAG('k'),
cmd_srcdst_init, cmd_srcdst_init,
cmd_srcdst_parse, cmd_srcdst_parse,
cmd_move_window_exec, cmd_move_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free, cmd_srcdst_free,
cmd_srcdst_print cmd_srcdst_print
}; };
@@ -54,19 +52,8 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL) if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL)
return (-1); return (-1);
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
if (arg_parse_window(data->dst, &dst, &idx) != 0) {
ctx->error(ctx, "bad window: %s", data->dst);
return (-1); return (-1);
}
if (dst == NULL)
dst = ctx->cursession;
if (dst == NULL)
dst = cmd_current_session(ctx);
if (dst == NULL) {
ctx->error(ctx, "session not found: %s", data->dst);
return (-1);
}
wl_dst = NULL; wl_dst = NULL;
if (idx != -1) if (idx != -1)
@@ -75,7 +62,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (wl_dst->window == wl_src->window) if (wl_dst->window == wl_src->window)
return (0); return (0);
if (data->flags & CMD_KFLAG) { if (data->chflags & CMD_CHFLAG('k')) {
/* /*
* Can't use session_detach as it will destroy session * Can't use session_detach as it will destroy session
* if this makes it empty. * if this makes it empty.
@@ -86,12 +73,14 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Force select/redraw if current. */ /* Force select/redraw if current. */
if (wl_dst == dst->curw) { if (wl_dst == dst->curw) {
data->flags &= ~CMD_DFLAG; data->chflags &= ~CMD_CHFLAG('d');
dst->curw = NULL; dst->curw = NULL;
} }
} }
} }
if (idx == -1)
idx = -1 - options_get_number(&dst->options, "base-index");
wl_dst = session_attach(dst, wl_src->window, idx, &cause); wl_dst = session_attach(dst, wl_src->window, idx, &cause);
if (wl_dst == NULL) { if (wl_dst == NULL) {
ctx->error(ctx, "attach window failed: %s", cause); ctx->error(ctx, "attach window failed: %s", cause);
@@ -111,7 +100,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_client(c); server_redraw_client(c);
} }
if (data->flags & CMD_DFLAG) if (data->chflags & CMD_CHFLAG('d'))
server_status_session(dst); server_status_session(dst);
else { else {
session_select(dst, wl_dst->idx); session_select(dst, wl_dst->idx);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-new-session.c,v 1.40 2009-04-01 18:21:24 nicm Exp $ */ /* $Id: cmd-new-session.c,v 1.66 2009-09-16 12:36:27 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,10 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -26,8 +30,6 @@
int cmd_new_session_parse(struct cmd *, int, char **, char **); int cmd_new_session_parse(struct cmd *, int, char **, char **);
int cmd_new_session_exec(struct cmd *, struct cmd_ctx *); int cmd_new_session_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_session_send(struct cmd *, struct buffer *);
void cmd_new_session_recv(struct cmd *, struct buffer *);
void cmd_new_session_free(struct cmd *); void cmd_new_session_free(struct cmd *);
void cmd_new_session_init(struct cmd *, int); void cmd_new_session_init(struct cmd *, int);
size_t cmd_new_session_print(struct cmd *, char *, size_t); size_t cmd_new_session_print(struct cmd *, char *, size_t);
@@ -42,12 +44,10 @@ struct cmd_new_session_data {
const struct cmd_entry cmd_new_session_entry = { const struct cmd_entry cmd_new_session_entry = {
"new-session", "new", "new-session", "new",
"[-d] [-n window-name] [-s session-name] [command]", "[-d] [-n window-name] [-s session-name] [command]",
CMD_STARTSERVER|CMD_CANTNEST, CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON, 0,
cmd_new_session_init, cmd_new_session_init,
cmd_new_session_parse, cmd_new_session_parse,
cmd_new_session_exec, cmd_new_session_exec,
cmd_new_session_send,
cmd_new_session_recv,
cmd_new_session_free, cmd_new_session_free,
cmd_new_session_print cmd_new_session_print
}; };
@@ -111,106 +111,149 @@ int
cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_new_session_data *data = self->data; struct cmd_new_session_data *data = self->data;
struct client *c = ctx->cmdclient;
struct session *s; struct session *s;
char *cmd, *cwd, *cause; struct window *w;
struct environ env;
struct termios tio, *tiop;
const char *update;
char *overrides, *cmd, *cwd, *cause;
int detached, idx;
u_int sx, sy; u_int sx, sy;
if (ctx->curclient != NULL)
return (0);
if (!data->flag_detached) {
if (c == NULL) {
ctx->error(ctx, "no client to attach to");
return (-1);
}
if (!(c->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal");
return (-1);
}
}
if (data->newname != NULL && session_find(data->newname) != NULL) { if (data->newname != NULL && session_find(data->newname) != NULL) {
ctx->error(ctx, "duplicate session: %s", data->newname); ctx->error(ctx, "duplicate session: %s", data->newname);
return (-1); return (-1);
} }
cmd = data->cmd; /*
if (cmd == NULL) * There are three cases:
cmd = options_get_string(&global_options, "default-command"); *
if (c == NULL || c->cwd == NULL) * 1. If cmdclient is non-NULL, new-session has been called from the
cwd = options_get_string(&global_options, "default-path"); * command-line - cmdclient is to become a new attached, interactive
* client. Unless -d is given, the terminal must be opened and then
* the client sent MSG_READY.
*
* 2. If cmdclient is NULL, new-session has been called from an
* existing client (such as a key binding).
*
* 3. Both are NULL, the command was in the configuration file. Treat
* this as if -d was given even if it was not.
*
* In all cases, a new additional session needs to be created and
* (unless -d) set as the current session for the client.
*/
/* Set -d if no client. */
detached = data->flag_detached;
if (ctx->cmdclient == NULL && ctx->curclient == NULL)
detached = 1;
/*
* Save the termios settings, part of which is used for new windows in
* this session.
*
* This is read again with tcgetattr() rather than using tty.tio as if
* detached, tty_open won't be called. Because of this, it must be done
* before opening the terminal as that calls tcsetattr() to prepare for
* tmux taking over.
*/
if (ctx->cmdclient != NULL && ctx->cmdclient->tty.fd != -1) {
if (tcgetattr(ctx->cmdclient->tty.fd, &tio) != 0)
fatal("tcgetattr failed");
tiop = &tio;
} else
tiop = NULL;
/* Open the terminal if necessary. */
if (!detached && ctx->cmdclient != NULL) {
if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal");
return (-1);
}
overrides =
options_get_string(&global_s_options, "terminal-overrides");
if (tty_open(&ctx->cmdclient->tty, overrides, &cause) != 0) {
ctx->error(ctx, "open terminal failed: %s", cause);
xfree(cause);
return (-1);
}
}
/* Get the new session working directory. */
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
cwd = ctx->cmdclient->cwd;
else else
cwd = c->cwd; cwd = options_get_string(&global_s_options, "default-path");
sx = 80; /* Find new session size. */
sy = 25; if (detached) {
if (!data->flag_detached) { sx = 80;
sx = c->tty.sx; sy = 24;
sy = c->tty.sy; } 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--;
if (sx == 0)
sx = 1;
if (sy == 0)
sy = 1;
if (options_get_number(&global_options, "status")) { /* Figure out the command for the new window. */
if (sy == 0) if (data->cmd != NULL)
sy = 1; cmd = data->cmd;
else else
sy--; cmd = options_get_string(&global_s_options, "default-command");
}
if (!data->flag_detached && tty_open(&c->tty, &cause) != 0) { /* Construct the environment. */
ctx->error(ctx, "open terminal failed: %s", cause); environ_init(&env);
xfree(cause); update = options_get_string(&global_s_options, "update-environment");
return (-1); if (ctx->cmdclient != NULL)
} environ_update(update, &ctx->cmdclient->environ, &env);
/* Create the new session. */
s = session_create(data->newname, cmd, cwd, sx, sy, &cause); idx = -1 - options_get_number(&global_s_options, "base-index");
s = session_create(
data->newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause);
if (s == NULL) { if (s == NULL) {
ctx->error(ctx, "create session failed: %s", cause); ctx->error(ctx, "create session failed: %s", cause);
xfree(cause); xfree(cause);
return (-1); return (-1);
} }
environ_free(&env);
/* Set the initial window name if one given. */
if (data->winname != NULL) { if (data->winname != NULL) {
xfree(s->curw->window->name); w = s->curw->window;
s->curw->window->name = xstrdup(data->winname);
options_set_number( xfree(w->name);
&s->curw->window->options, "automatic-rename", 0); w->name = xstrdup(data->winname);
options_set_number(&w->options, "automatic-rename", 0);
} }
if (data->flag_detached) { /*
if (c != NULL) * Set the client to the new session. If a command client exists, it is
server_write_client(c, MSG_EXIT, NULL, 0); * taking this session and needs to get MSG_READY and stay around.
} else { */
c->session = s; if (!detached) {
server_write_client(c, MSG_READY, NULL, 0); if (ctx->cmdclient != NULL) {
server_redraw_client(c); server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
ctx->cmdclient->session = s;
server_redraw_client(ctx->cmdclient);
} else {
ctx->curclient->session = s;
server_redraw_client(ctx->curclient);
}
} }
recalculate_sizes(); recalculate_sizes();
return (1); return (!detached); /* 1 means don't tell command client to exit */
}
void
cmd_new_session_send(struct cmd *self, struct buffer *b)
{
struct cmd_new_session_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->newname);
cmd_send_string(b, data->winname);
cmd_send_string(b, data->cmd);
}
void
cmd_new_session_recv(struct cmd *self, struct buffer *b)
{
struct cmd_new_session_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->newname = cmd_recv_string(b);
data->winname = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
} }
void void

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-new-window.c,v 1.31 2009-01-23 16:59:14 nicm Exp $ */ /* $Id: cmd-new-window.c,v 1.37 2009-08-16 19:16:27 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,8 +28,6 @@
int cmd_new_window_parse(struct cmd *, int, char **, char **); int cmd_new_window_parse(struct cmd *, int, char **, char **);
int cmd_new_window_exec(struct cmd *, struct cmd_ctx *); int cmd_new_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_window_send(struct cmd *, struct buffer *);
void cmd_new_window_recv(struct cmd *, struct buffer *);
void cmd_new_window_free(struct cmd *); void cmd_new_window_free(struct cmd *);
void cmd_new_window_init(struct cmd *, int); void cmd_new_window_init(struct cmd *, int);
size_t cmd_new_window_print(struct cmd *, char *, size_t); size_t cmd_new_window_print(struct cmd *, char *, size_t);
@@ -45,12 +43,10 @@ struct cmd_new_window_data {
const struct cmd_entry cmd_new_window_entry = { const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww", "new-window", "neww",
"[-dk] [-n window-name] [-t target-window] [command]", "[-dk] [-n window-name] [-t target-window] [command]",
0, 0, 0,
cmd_new_window_init, cmd_new_window_init,
cmd_new_window_parse, cmd_new_window_parse,
cmd_new_window_exec, cmd_new_window_exec,
cmd_new_window_send,
cmd_new_window_recv,
cmd_new_window_free, cmd_new_window_free,
cmd_new_window_print cmd_new_window_print
}; };
@@ -126,18 +122,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return (0); return (0);
if (arg_parse_window(data->target, &s, &idx) != 0) { if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
ctx->error(ctx, "bad window: %s", data->target);
return (-1); return (-1);
}
if (s == NULL)
s = ctx->cursession;
if (s == NULL)
s = cmd_current_session(ctx);
if (s == NULL) {
ctx->error(ctx, "session not found: %s", data->target);
return (-1);
}
wl = NULL; wl = NULL;
if (idx != -1) if (idx != -1)
@@ -164,10 +150,12 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (cmd == NULL) if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL) if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
cwd = options_get_string(&global_options, "default-path"); cwd = options_get_string(&s->options, "default-path");
else else
cwd = ctx->cmdclient->cwd; cwd = ctx->cmdclient->cwd;
if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index");
wl = session_new(s, data->name, cmd, cwd, idx, &cause); wl = session_new(s, data->name, cmd, cwd, idx, &cause);
if (wl == NULL) { if (wl == NULL) {
ctx->error(ctx, "create window failed: %s", cause); ctx->error(ctx, "create window failed: %s", cause);
@@ -183,29 +171,6 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
void
cmd_new_window_send(struct cmd *self, struct buffer *b)
{
struct cmd_new_window_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->name);
cmd_send_string(b, data->cmd);
}
void
cmd_new_window_recv(struct cmd *self, struct buffer *b)
{
struct cmd_new_window_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->name = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
}
void void
cmd_new_window_free(struct cmd *self) cmd_new_window_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-next-layout.c,v 1.1 2009-04-01 18:21:26 nicm Exp $ */ /* $Id: cmd-next-layout.c,v 1.5 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_next_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_next_layout_entry = { const struct cmd_entry cmd_next_layout_entry = {
"next-layout", "nextl", "next-layout", "nextl",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_next_layout_exec, cmd_next_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -44,11 +42,13 @@ cmd_next_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
u_int layout;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
layout_next(wl->window); layout = layout_set_next(wl->window);
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-next-window.c,v 1.16 2009-03-28 14:08:09 nicm Exp $ */ /* $Id: cmd-next-window.c,v 1.20 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,13 +29,11 @@ int cmd_next_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_next_window_entry = { const struct cmd_entry cmd_next_window_entry = {
"next-window", "next", "next-window", "next",
CMD_TARGET_SESSION_USAGE, "[-a] " CMD_TARGET_SESSION_USAGE,
CMD_AFLAG, 0, CMD_CHFLAG('a'),
cmd_next_window_init, cmd_next_window_init,
cmd_target_parse, cmd_target_parse,
cmd_next_window_exec, cmd_next_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -48,8 +46,8 @@ cmd_next_window_init(struct cmd *self, int key)
cmd_target_init(self, key); cmd_target_init(self, key);
data = self->data; data = self->data;
if (key == KEYC_ADDESC('n')) if (key == ('n' | KEYC_ESCAPE))
data->flags |= CMD_AFLAG; data->chflags |= CMD_CHFLAG('a');
} }
int int
@@ -63,7 +61,7 @@ cmd_next_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
activity = 0; activity = 0;
if (data->flags & CMD_AFLAG) if (data->chflags & CMD_CHFLAG('a'))
activity = 1; activity = 1;
if (session_next(s, activity) == 0) if (session_next(s, activity) == 0)

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-paste-buffer.c,v 1.15 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-paste-buffer.c,v 1.20 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,16 +27,15 @@
*/ */
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_paste_buffer_lf2cr(struct buffer *, const char *, size_t);
const struct cmd_entry cmd_paste_buffer_entry = { const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb", "paste-buffer", "pasteb",
"[-d] " CMD_BUFFER_WINDOW_USAGE, "[-dr] " CMD_BUFFER_WINDOW_USAGE,
CMD_DFLAG, 0, CMD_CHFLAG('d')|CMD_CHFLAG('r'),
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_paste_buffer_exec, cmd_paste_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -46,13 +45,13 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct window *w; struct window_pane *wp;
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1); return (-1);
w = wl->window; wp = wl->window->active;
if (data->buffer == -1) if (data->buffer == -1)
pb = paste_get_top(&s->buffers); pb = paste_get_top(&s->buffers);
@@ -63,11 +62,16 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
} }
if (pb != NULL) if (pb != NULL && *pb->data != '\0') {
buffer_write(w->active->out, pb->data, strlen(pb->data)); /* -r means raw data without LF->CR conversion. */
if (data->chflags & CMD_CHFLAG('r'))
buffer_write(wp->out, pb->data, pb->size);
else
cmd_paste_buffer_lf2cr(wp->out, pb->data, pb->size);
}
/* Delete the buffer if -d. */ /* Delete the buffer if -d. */
if (data->flags & CMD_DFLAG) { if (data->chflags & CMD_CHFLAG('d')) {
if (data->buffer == -1) if (data->buffer == -1)
paste_free_top(&s->buffers); paste_free_top(&s->buffers);
else else
@@ -76,3 +80,21 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
/* Add bytes to a buffer but change every '\n' to '\r'. */
void
cmd_paste_buffer_lf2cr(struct buffer *b, const char *data, size_t size)
{
const char *end = data + size;
const char *lf;
while ((lf = memchr(data, '\n', end - data)) != NULL) {
if (lf != data)
buffer_write(b, data, lf - data);
buffer_write8(b, '\r');
data = lf + 1;
}
if (end != data)
buffer_write(b, data, end - data);
}

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

@@ -0,0 +1,54 @@
/* $Id: cmd-previous-layout.c,v 1.4 2009-07-28 22:12:16 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include "tmux.h"
/*
* Switch window to previous layout.
*/
int cmd_previous_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_previous_layout_entry = {
"previous-layout", "prevl",
CMD_TARGET_WINDOW_USAGE,
0, 0,
cmd_target_init,
cmd_target_parse,
cmd_previous_layout_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_previous_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
u_int layout;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
layout = layout_set_previous(wl->window);
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-previous-window.c,v 1.16 2009-03-28 14:08:09 nicm Exp $ */ /* $Id: cmd-previous-window.c,v 1.20 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,13 +29,11 @@ int cmd_previous_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_previous_window_entry = { const struct cmd_entry cmd_previous_window_entry = {
"previous-window", "prev", "previous-window", "prev",
CMD_TARGET_SESSION_USAGE, "[-a] " CMD_TARGET_SESSION_USAGE,
CMD_AFLAG, 0, CMD_CHFLAG('a'),
cmd_previous_window_init, cmd_previous_window_init,
cmd_target_parse, cmd_target_parse,
cmd_previous_window_exec, cmd_previous_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -48,8 +46,8 @@ cmd_previous_window_init(struct cmd *self, int key)
cmd_target_init(self, key); cmd_target_init(self, key);
data = self->data; data = self->data;
if (key == KEYC_ADDESC('p')) if (key == ('p' | KEYC_ESCAPE))
data->flags |= CMD_AFLAG; data->chflags |= CMD_CHFLAG('a');
} }
int int
@@ -63,7 +61,7 @@ cmd_previous_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
activity = 0; activity = 0;
if (data->flags & CMD_AFLAG) if (data->chflags & CMD_CHFLAG('a'))
activity = 1; activity = 1;
if (session_previous(s, activity) == 0) if (session_previous(s, activity) == 0)

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-refresh-client.c,v 1.8 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-refresh-client.c,v 1.10 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_refresh_client_entry = { const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh", "refresh-client", "refresh",
CMD_TARGET_CLIENT_USAGE, CMD_TARGET_CLIENT_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_refresh_client_exec, cmd_refresh_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-rename-session.c,v 1.15 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-rename-session.c,v 1.18 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_rename_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_session_entry = { const struct cmd_entry cmd_rename_session_entry = {
"rename-session", "rename", "rename-session", "rename",
CMD_TARGET_SESSION_USAGE " new-name", CMD_TARGET_SESSION_USAGE " new-name",
CMD_ARG1, CMD_ARG1, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_rename_session_exec, cmd_rename_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -53,5 +51,7 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx)
xfree(s->name); xfree(s->name);
s->name = xstrdup(data->arg); s->name = xstrdup(data->arg);
server_status_session(s);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-rename-window.c,v 1.26 2009-01-20 19:35:03 nicm Exp $ */ /* $Id: cmd-rename-window.c,v 1.29 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_rename_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_window_entry = { const struct cmd_entry cmd_rename_window_entry = {
"rename-window", "renamew", "rename-window", "renamew",
CMD_TARGET_WINDOW_USAGE " new-name", CMD_TARGET_WINDOW_USAGE " new-name",
CMD_ARG1, CMD_ARG1, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_rename_window_exec, cmd_rename_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,122 +0,0 @@
/* $Id: cmd-resize-pane-down.c,v 1.8 2009-04-02 21:11:52 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
/*
* Decrease pane size.
*/
void cmd_resize_pane_down_init(struct cmd *, int);
int cmd_resize_pane_down_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_resize_pane_down_entry = {
"resize-pane-down", "resizep-down",
CMD_PANE_WINDOW_USAGE " [adjustment]",
CMD_ARG01,
cmd_resize_pane_down_init,
cmd_pane_parse,
cmd_resize_pane_down_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};
void
cmd_resize_pane_down_init(struct cmd *self, int key)
{
struct cmd_pane_data *data;
cmd_pane_init(self, key);
data = self->data;
if (key == KEYC_ADDESC(KEYC_DOWN))
data->arg = xstrdup("5");
}
int
cmd_resize_pane_down_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_pane_data *data = self->data;
struct winlink *wl;
const char *errstr;
struct window_pane *wp, *wq;
u_int adjust;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (wl->window->layout != 0) {
ctx->error(ctx, "window not in manual layout");
return (-1);
}
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (data->arg == NULL)
adjust = 1;
else {
adjust = strtonum(data->arg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "adjustment %s: %s", errstr, data->arg);
return (-1);
}
}
/*
* If this is not the last window, keep trying to increase size and
* remove it from the next windows. If it is the last, do so on the
* previous window.
*/
if (TAILQ_NEXT(wp, entry) == NULL) {
if (wp == TAILQ_FIRST(&wl->window->panes)) {
/* Only one pane. */
return (0);
}
wp = TAILQ_PREV(wp, window_panes, entry);
}
while (adjust-- > 0) {
wq = wp;
while ((wq = TAILQ_NEXT(wq, entry)) != NULL) {
if (wq->sy > PANE_MINIMUM) {
window_pane_resize(wq, wq->sx, wq->sy - 1);
break;
}
}
if (wq == NULL)
break;
window_pane_resize(wp, wp->sx, wp->sy + 1);
}
window_update_panes(wl->window);
server_redraw_window(wl->window);
return (0);
}

View File

@@ -1,117 +0,0 @@
/* $Id: cmd-resize-pane-up.c,v 1.8 2009-04-02 21:11:52 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
/*
* Increase pane size.
*/
void cmd_resize_pane_up_init(struct cmd *, int);
int cmd_resize_pane_up_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_resize_pane_up_entry = {
"resize-pane-up", "resizep-up",
CMD_PANE_WINDOW_USAGE " [adjustment]",
CMD_ARG01,
cmd_resize_pane_up_init,
cmd_pane_parse,
cmd_resize_pane_up_exec,
cmd_pane_send,
cmd_pane_recv,
cmd_pane_free,
cmd_pane_print
};
void
cmd_resize_pane_up_init(struct cmd *self, int key)
{
struct cmd_pane_data *data;
cmd_pane_init(self, key);
data = self->data;
if (key == KEYC_ADDESC(KEYC_UP))
data->arg = xstrdup("5");
}
int
cmd_resize_pane_up_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_pane_data *data = self->data;
struct winlink *wl;
const char *errstr;
struct window_pane *wp, *wq;
u_int adjust;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (wl->window->layout != 0) {
ctx->error(ctx, "window not in manual layout");
return (-1);
}
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (data->arg == NULL)
adjust = 1;
else {
adjust = strtonum(data->arg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "adjustment %s: %s", errstr, data->arg);
return (-1);
}
}
/*
* If this is not the last window, keep trying to reduce size and add
* to the following window. If it is the last, do so on the previous
* window.
*/
wq = TAILQ_NEXT(wp, entry);
if (wq == NULL) {
if (wp == TAILQ_FIRST(&wl->window->panes)) {
/* Only one pane. */
return (0);
}
wq = wp;
wp = TAILQ_PREV(wq, window_panes, entry);
}
while (adjust-- > 0) {
if (wp->sy <= PANE_MINIMUM)
break;
window_pane_resize(wq, wq->sx, wq->sy + 1);
window_pane_resize(wp, wp->sx, wp->sy - 1);
}
window_update_panes(wl->window);
server_redraw_window(wl->window);
return (0);
}

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

@@ -0,0 +1,113 @@
/* $Id: cmd-resize-pane.c,v 1.12 2009-07-30 20:45:20 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
/*
* Increase or decrease pane size.
*/
void cmd_resize_pane_init(struct cmd *, int);
int cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep",
"[-DU] " CMD_TARGET_PANE_USAGE " [adjustment]",
CMD_ARG01,
CMD_CHFLAG('D')|CMD_CHFLAG('L')|CMD_CHFLAG('R')|CMD_CHFLAG('U'),
cmd_resize_pane_init,
cmd_target_parse,
cmd_resize_pane_exec,
cmd_target_free,
cmd_target_print
};
void
cmd_resize_pane_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
if (key == (KEYC_UP | KEYC_CTRL))
data->chflags |= CMD_CHFLAG('U');
if (key == (KEYC_DOWN | KEYC_CTRL))
data->chflags |= CMD_CHFLAG('D');
if (key == (KEYC_LEFT | KEYC_CTRL))
data->chflags |= CMD_CHFLAG('L');
if (key == (KEYC_RIGHT | KEYC_CTRL))
data->chflags |= CMD_CHFLAG('R');
if (key == (KEYC_UP | KEYC_ESCAPE)) {
data->chflags |= CMD_CHFLAG('U');
data->arg = xstrdup("5");
}
if (key == (KEYC_DOWN | KEYC_ESCAPE)) {
data->chflags |= CMD_CHFLAG('D');
data->arg = xstrdup("5");
}
if (key == (KEYC_LEFT | KEYC_ESCAPE)) {
data->chflags |= CMD_CHFLAG('L');
data->arg = xstrdup("5");
}
if (key == (KEYC_RIGHT | KEYC_ESCAPE)) {
data->chflags |= CMD_CHFLAG('R');
data->arg = xstrdup("5");
}
}
int
cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
const char *errstr;
struct window_pane *wp;
u_int adjust;
if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1);
if (data->arg == NULL)
adjust = 1;
else {
adjust = strtonum(data->arg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "adjustment %s: %s", errstr, data->arg);
return (-1);
}
}
if (data->chflags & (CMD_CHFLAG('L')|CMD_CHFLAG('R'))) {
if (data->chflags & CMD_CHFLAG('L'))
adjust = -adjust;
layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust);
} else {
if (data->chflags & CMD_CHFLAG('U'))
adjust = -adjust;
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust);
}
server_redraw_window(wl->window);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-respawn-window.c,v 1.14 2009-03-04 17:24:07 nicm Exp $ */ /* $Id: cmd-respawn-window.c,v 1.22 2009-09-16 12:36:27 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_respawn_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_respawn_window_entry = { const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw", "respawn-window", "respawnw",
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]", "[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
CMD_ARG01|CMD_KFLAG, CMD_ARG01, CMD_CHFLAG('k'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_respawn_window_exec, cmd_respawn_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -49,14 +47,14 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
struct session *s; struct session *s;
const char **env; struct environ env;
char *cause; char *cause;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
if (!(data->flags & CMD_KFLAG)) { if (!(data->chflags & CMD_CHFLAG('k'))) {
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->fd == -1) if (wp->fd == -1)
continue; continue;
@@ -66,22 +64,31 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
} }
env = server_fill_environ(s); environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
wp = TAILQ_FIRST(&w->panes); wp = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_REMOVE(&w->panes, wp, entry);
layout_free(w);
window_destroy_panes(w); window_destroy_panes(w);
TAILQ_INSERT_HEAD(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry);
window_pane_resize(wp, w->sx, w->sy); window_pane_resize(wp, w->sx, w->sy);
if (window_pane_spawn(wp, data->arg, NULL, env, &cause) != 0) { if (window_pane_spawn(
wp, data->arg, NULL, NULL, &env, s->tio, &cause) != 0) {
ctx->error(ctx, "respawn window failed: %s", cause); ctx->error(ctx, "respawn window failed: %s", cause);
xfree(cause); xfree(cause);
environ_free(&env);
return (-1); return (-1);
} }
layout_init(w);
screen_reinit(&wp->base); screen_reinit(&wp->base);
window_set_active_pane(w, wp);
recalculate_sizes(); recalculate_sizes();
server_redraw_window(w); server_redraw_window(w);
environ_free(&env);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-rotate-window.c,v 1.2 2009-04-21 20:06:46 nicm Exp $ */ /* $Id: cmd-rotate-window.c,v 1.9 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,12 +30,10 @@ int cmd_rotate_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rotate_window_entry = { const struct cmd_entry cmd_rotate_window_entry = {
"rotate-window", "rotatew", "rotate-window", "rotatew",
"[-DU] " CMD_TARGET_WINDOW_USAGE, "[-DU] " CMD_TARGET_WINDOW_USAGE,
CMD_UPPERUFLAG|CMD_UPPERDFLAG, 0, CMD_CHFLAG('D')|CMD_CHFLAG('U'),
cmd_rotate_window_init, cmd_rotate_window_init,
cmd_target_parse, cmd_target_parse,
cmd_rotate_window_exec, cmd_rotate_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -48,8 +46,8 @@ cmd_rotate_window_init(struct cmd *self, int key)
cmd_target_init(self, key); cmd_target_init(self, key);
data = self->data; data = self->data;
if (key == KEYC_ADDESC('o')) if (key == ('o' | KEYC_ESCAPE))
data->flags |= CMD_UPPERDFLAG; data->chflags |= CMD_CHFLAG('D');
} }
int int
@@ -59,53 +57,68 @@ cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
struct window_pane *wp, *wp2; struct window_pane *wp, *wp2;
struct layout_cell *lc;
u_int sx, sy, xoff, yoff; u_int sx, sy, xoff, yoff;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
if (data->flags & CMD_UPPERDFLAG) { if (data->chflags & CMD_CHFLAG('D')) {
wp = TAILQ_LAST(&w->panes, window_panes); wp = TAILQ_LAST(&w->panes, window_panes);
TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_REMOVE(&w->panes, wp, entry);
TAILQ_INSERT_HEAD(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry);
lc = wp->layout_cell;
xoff = wp->xoff; yoff = wp->yoff; xoff = wp->xoff; yoff = wp->yoff;
sx = wp->sx; sy = wp->sy; sx = wp->sx; sy = wp->sy;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if ((wp2 = TAILQ_NEXT(wp, entry)) == NULL) if ((wp2 = TAILQ_NEXT(wp, entry)) == NULL)
break; break;
wp->layout_cell = wp2->layout_cell;
if (wp->layout_cell != NULL)
wp->layout_cell->wp = wp;
wp->xoff = wp2->xoff; wp->yoff = wp2->yoff; wp->xoff = wp2->xoff; wp->yoff = wp2->yoff;
window_pane_resize(wp, wp2->sx, wp2->sy); window_pane_resize(wp, wp2->sx, wp2->sy);
} }
wp->layout_cell = lc;
if (wp->layout_cell != NULL)
wp->layout_cell->wp = wp;
wp->xoff = xoff; wp->yoff = yoff; wp->xoff = xoff; wp->yoff = yoff;
window_pane_resize(wp, sx, sy); window_pane_resize(wp, sx, sy);
if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL) if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL)
wp = TAILQ_LAST(&w->panes, window_panes); wp = TAILQ_LAST(&w->panes, window_panes);
window_set_active_pane(w, wp); window_set_active_pane(w, wp);
server_redraw_window(w);
} else { } else {
wp = TAILQ_FIRST(&w->panes); wp = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_REMOVE(&w->panes, wp, entry);
TAILQ_INSERT_TAIL(&w->panes, wp, entry); TAILQ_INSERT_TAIL(&w->panes, wp, entry);
lc = wp->layout_cell;
xoff = wp->xoff; yoff = wp->yoff; xoff = wp->xoff; yoff = wp->yoff;
sx = wp->sx; sy = wp->sy; sx = wp->sx; sy = wp->sy;
TAILQ_FOREACH_REVERSE(wp, &w->panes, window_panes, entry) { TAILQ_FOREACH_REVERSE(wp, &w->panes, window_panes, entry) {
if ((wp2 = TAILQ_PREV(wp, window_panes, entry)) == NULL) if ((wp2 = TAILQ_PREV(wp, window_panes, entry)) == NULL)
break; break;
wp->layout_cell = wp2->layout_cell;
if (wp->layout_cell != NULL)
wp->layout_cell->wp = wp;
wp->xoff = wp2->xoff; wp->yoff = wp2->yoff; wp->xoff = wp2->xoff; wp->yoff = wp2->yoff;
window_pane_resize(wp, wp2->sx, wp2->sy); window_pane_resize(wp, wp2->sx, wp2->sy);
} }
wp->layout_cell = lc;
if (wp->layout_cell != NULL)
wp->layout_cell->wp = wp;
wp->xoff = xoff; wp->yoff = yoff; wp->xoff = xoff; wp->yoff = yoff;
window_pane_resize(wp, sx, sy); window_pane_resize(wp, sx, sy);
if ((wp = TAILQ_NEXT(w->active, entry)) == NULL) if ((wp = TAILQ_NEXT(w->active, entry)) == NULL)
wp = TAILQ_FIRST(&w->panes); wp = TAILQ_FIRST(&w->panes);
window_set_active_pane(w, wp); window_set_active_pane(w, wp);
server_redraw_window(w);
} }
layout_refresh(w, 0);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-save-buffer.c,v 1.4 2009-02-08 13:36:40 tcunha Exp $ */ /* $Id: cmd-save-buffer.c,v 1.8 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -33,12 +33,10 @@ int cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_save_buffer_entry = { const struct cmd_entry cmd_save_buffer_entry = {
"save-buffer", "saveb", "save-buffer", "saveb",
"[-a] " CMD_BUFFER_SESSION_USAGE " path", "[-a] " CMD_BUFFER_SESSION_USAGE " path",
CMD_AFLAG|CMD_ARG1, CMD_ARG1, CMD_CHFLAG('a'),
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_save_buffer_exec, cmd_save_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -68,16 +66,16 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
mask = umask(S_IRWXG | S_IRWXO); mask = umask(S_IRWXG | S_IRWXO);
if (data->flags & CMD_AFLAG) if (data->chflags & CMD_CHFLAG('a'))
f = fopen(data->arg, "a"); f = fopen(data->arg, "ab");
else else
f = fopen(data->arg, "w"); f = fopen(data->arg, "wb");
if (f == NULL) { if (f == NULL) {
ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
return (-1); return (-1);
} }
if (fwrite(pb->data, 1, strlen(pb->data), f) != strlen(pb->data)) { if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
ctx->error(ctx, "%s: fwrite error", data->arg); ctx->error(ctx, "%s: fwrite error", data->arg);
fclose(f); fclose(f);
return (-1); return (-1);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-scroll-mode.c,v 1.16 2009-01-27 23:35:44 nicm Exp $ */ /* $Id: cmd-scroll-mode.c,v 1.23 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,13 +29,11 @@ int cmd_scroll_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_scroll_mode_entry = { const struct cmd_entry cmd_scroll_mode_entry = {
"scroll-mode", NULL, "scroll-mode", NULL,
CMD_TARGET_WINDOW_USAGE, "[-u] " CMD_TARGET_PANE_USAGE,
CMD_UFLAG, 0, CMD_CHFLAG('u'),
cmd_scroll_mode_init, cmd_scroll_mode_init,
cmd_target_parse, cmd_target_parse,
cmd_scroll_mode_exec, cmd_scroll_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -50,7 +48,7 @@ cmd_scroll_mode_init(struct cmd *self, int key)
switch (key) { switch (key) {
case KEYC_PPAGE: case KEYC_PPAGE:
data->flags |= CMD_UFLAG; data->chflags |= CMD_CHFLAG('u');
break; break;
} }
} }
@@ -59,14 +57,14 @@ int
cmd_scroll_mode_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_scroll_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
window_pane_set_mode(wl->window->active, &window_scroll_mode); window_pane_set_mode(wp, &window_scroll_mode);
if (data->flags & CMD_UFLAG) if (wp->mode == &window_scroll_mode && data->chflags & CMD_CHFLAG('u'))
window_scroll_pageup(wl->window->active); window_scroll_pageup(wp);
return (0); return (0);
} }

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

@@ -0,0 +1,88 @@
/* $Id: cmd-select-layout.c,v 1.8 2009-07-28 23:04:29 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include "tmux.h"
/*
* Switch window to selected layout.
*/
void cmd_select_layout_init(struct cmd *, int);
int cmd_select_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_layout_entry = {
"select-layout", "selectl",
CMD_TARGET_WINDOW_USAGE " [layout-name]",
CMD_ARG01, 0,
cmd_select_layout_init,
cmd_target_parse,
cmd_select_layout_exec,
cmd_target_free,
cmd_target_print
};
void
cmd_select_layout_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
switch (key) {
case ('1' | KEYC_ESCAPE):
data->arg = xstrdup("even-horizontal");
break;
case ('2' | KEYC_ESCAPE):
data->arg = xstrdup("even-vertical");
break;
case ('3' | KEYC_ESCAPE):
data->arg = xstrdup("main-horizontal");
break;
case ('4' | KEYC_ESCAPE):
data->arg = xstrdup("main-vertical");
break;
}
}
int
cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
int layout;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (data->arg == NULL) {
layout = wl->window->lastlayout;
if (layout == -1)
return (0);
} else if ((layout = layout_set_lookup(data->arg)) == -1) {
ctx->error(ctx, "unknown layout or ambiguous: %s", data->arg);
return (-1);
}
layout = layout_set_select(wl->window, layout);
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-pane.c,v 1.4 2009-04-01 21:10:08 nicm Exp $ */ /* $Id: cmd-select-pane.c,v 1.10 2009-07-30 20:45:20 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,42 +28,31 @@ int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_pane_entry = { const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp", "select-pane", "selectp",
CMD_PANE_WINDOW_USAGE, CMD_TARGET_PANE_USAGE,
0, 0, 0,
cmd_pane_init, cmd_target_init,
cmd_pane_parse, cmd_target_parse,
cmd_select_pane_exec, cmd_select_pane_exec,
cmd_pane_send, cmd_target_free,
cmd_pane_recv, cmd_target_print
cmd_pane_free,
cmd_pane_print
}; };
int int
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_pane_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1); return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (wp->flags & PANE_HIDDEN) { if (!window_pane_visible(wp)) {
ctx->error(ctx, "pane %d is hidden", data->pane); ctx->error(ctx, "pane not visible: %s", data->target);
return (-1); return (-1);
} }
window_set_active_pane(wl->window, wp); window_set_active_pane(wl->window, wp);
layout_refresh(wl->window, 1); server_status_window(wl->window);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-prompt.c,v 1.7 2009-02-13 18:57:55 nicm Exp $ */ /* $Id: cmd-select-prompt.c,v 1.12 2009-08-16 19:29:24 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,12 +33,10 @@ int cmd_select_prompt_callback(void *, const char *);
const struct cmd_entry cmd_select_prompt_entry = { const struct cmd_entry cmd_select_prompt_entry = {
"select-prompt", NULL, "select-prompt", NULL,
CMD_TARGET_CLIENT_USAGE, CMD_TARGET_CLIENT_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_select_prompt_exec, cmd_select_prompt_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -55,7 +53,7 @@ cmd_select_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
if (c->prompt_string != NULL) if (c->prompt_string != NULL)
return (0); return (0);
status_prompt_set(c, "index ", cmd_select_prompt_callback, c, 0); status_prompt_set(c, "index ", cmd_select_prompt_callback, NULL, c, 0);
return (0); return (0);
} }
@@ -68,20 +66,20 @@ cmd_select_prompt_callback(void *data, const char *s)
char msg[128]; char msg[128];
u_int idx; u_int idx;
if (s == NULL) if (s == NULL || *s == '\0')
return (0); return (0);
idx = strtonum(s, 0, UINT_MAX, &errstr); idx = strtonum(s, 0, UINT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
xsnprintf(msg, sizeof msg, "Index %s: %s", errstr, s); xsnprintf(msg, sizeof msg, "Index %s: %s", errstr, s);
status_message_set(c, msg); status_message_set(c, "%s", msg);
return (0); return (0);
} }
if (winlink_find_by_index(&c->session->windows, idx) == NULL) { if (winlink_find_by_index(&c->session->windows, idx) == NULL) {
xsnprintf(msg, sizeof msg, xsnprintf(msg, sizeof msg,
"Window not found: %s:%d", c->session->name, idx); "Window not found: %s:%d", c->session->name, idx);
status_message_set(c, msg); status_message_set(c, "%s", msg);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-window.c,v 1.21 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-select-window.c,v 1.23 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,12 +32,10 @@ int cmd_select_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_window_entry = { const struct cmd_entry cmd_select_window_entry = {
"select-window", "selectw", "select-window", "selectw",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_select_window_init, cmd_select_window_init,
cmd_target_parse, cmd_target_parse,
cmd_select_window_exec, cmd_select_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-send-keys.c,v 1.18 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-send-keys.c,v 1.21 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,8 +28,6 @@
int cmd_send_keys_parse(struct cmd *, int, char **, char **); int cmd_send_keys_parse(struct cmd *, int, char **, char **);
int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *); int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *);
void cmd_send_keys_send(struct cmd *, struct buffer *);
void cmd_send_keys_recv(struct cmd *, struct buffer *);
void cmd_send_keys_free(struct cmd *); void cmd_send_keys_free(struct cmd *);
size_t cmd_send_keys_print(struct cmd *, char *, size_t); size_t cmd_send_keys_print(struct cmd *, char *, size_t);
@@ -42,13 +40,11 @@ struct cmd_send_keys_data {
const struct cmd_entry cmd_send_keys_entry = { const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send", "send-keys", "send",
"[-t target-window] key ...", "[-t target-pane] key ...",
0, 0, 0,
NULL, NULL,
cmd_send_keys_parse, cmd_send_keys_parse,
cmd_send_keys_exec, cmd_send_keys_exec,
cmd_send_keys_send,
cmd_send_keys_recv,
cmd_send_keys_free, cmd_send_keys_free,
cmd_send_keys_print cmd_send_keys_print
}; };
@@ -110,45 +106,21 @@ int
cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_send_keys_data *data = self->data; struct cmd_send_keys_data *data = self->data;
struct winlink *wl; struct window_pane *wp;
u_int i; u_int i;
if (data == NULL) if (data == NULL)
return (-1); return (-1);
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
for (i = 0; i < data->nkeys; i++) { for (i = 0; i < data->nkeys; i++)
window_pane_key( window_pane_key(wp, ctx->curclient, data->keys[i]);
wl->window->active, ctx->curclient, data->keys[i]);
}
return (0); return (0);
} }
void
cmd_send_keys_send(struct cmd *self, struct buffer *b)
{
struct cmd_send_keys_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
buffer_write(b, data->keys, data->nkeys * sizeof *data->keys);
}
void
cmd_send_keys_recv(struct cmd *self, struct buffer *b)
{
struct cmd_send_keys_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->keys = xcalloc(data->nkeys, sizeof *data->keys);
buffer_read(b, data->keys, data->nkeys * sizeof *data->keys);
}
void void
cmd_send_keys_free(struct cmd *self) cmd_send_keys_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-send-prefix.c,v 1.23 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-send-prefix.c,v 1.26 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,11 @@ int cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_send_prefix_entry = { const struct cmd_entry cmd_send_prefix_entry = {
"send-prefix", NULL, "send-prefix", NULL,
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_PANE_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_send_prefix_exec, cmd_send_prefix_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -44,14 +42,14 @@ cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct session *s; struct session *s;
struct winlink *wl; struct window_pane *wp;
int key; int key;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
return (-1); return (-1);
key = options_get_number(&s->options, "prefix"); key = options_get_number(&s->options, "prefix");
window_pane_key(wl->window->active, ctx->curclient, key); window_pane_key(wp, ctx->curclient, key);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-server-info.c,v 1.14 2009-04-02 23:28:16 nicm Exp $ */ /* $Id: cmd-server-info.c,v 1.28 2009-09-07 23:59:19 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -23,7 +23,6 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <vis.h>
#include "tmux.h" #include "tmux.h"
@@ -36,13 +35,11 @@ int cmd_server_info_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_server_info_entry = { const struct cmd_entry cmd_server_info_entry = {
"server-info", "info", "server-info", "info",
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_server_info_exec, cmd_server_info_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };
@@ -59,8 +56,9 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
struct tty_term_code_entry *ent; struct tty_term_code_entry *ent;
struct utsname un; struct utsname un;
struct grid *gd; struct grid *gd;
struct grid_line *gl;
u_int i, j, k; u_int i, j, k;
char out[BUFSIZ]; char out[80];
char *tim; char *tim;
time_t t; time_t t;
u_int lines, ulines; u_int lines, ulines;
@@ -70,8 +68,9 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';
ctx->print(ctx, ctx->print(ctx,
"tmux " BUILD ", pid %ld, started %s", (long) getpid(), tim); "tmux " BUILD ", pid %ld, started %s", (long) getpid(), tim);
ctx->print(ctx, "socket path %s, debug level %d%s", ctx->print(ctx, "socket path %s, debug level %d%s%s",
socket_path, debug_level, be_quiet ? ", quiet" : ""); socket_path, debug_level, be_quiet ? ", quiet" : "",
login_shell ? ", login shell" : "");
if (uname(&un) == 0) { if (uname(&un) == 0) {
ctx->print(ctx, "system is %s %s %s %s", ctx->print(ctx, "system is %s %s %s %s",
un.sysname, un.release, un.version, un.machine); un.sysname, un.release, un.version, un.machine);
@@ -83,7 +82,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION); ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION);
ctx->print(ctx, "%u clients, %u sessions", ctx->print(ctx, "%u clients, %u sessions",
ARRAY_LENGTH(&clients), ARRAY_LENGTH(&sessions)); ARRAY_LENGTH(&clients), ARRAY_LENGTH(&sessions));
ctx->print(ctx, ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Clients:"); ctx->print(ctx, "Clients:");
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
@@ -91,12 +90,13 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
if (c == NULL || c->session == NULL) if (c == NULL || c->session == NULL)
continue; continue;
ctx->print(ctx, "%2d: %p %s (%d, %d): %s [%ux%u %s] " ctx->print(ctx, "%2d: %s (%d, %d): %s [%ux%u %s] "
"[flags=0x%x/0x%x]", i, c, c->tty.path, c->fd, c->tty.fd, "[flags=0x%x/0x%x, references=%u]", i, c->tty.path,
c->session->name, c->tty.sx, c->tty.sy, c->tty.termname, c->ibuf.fd, c->tty.fd, c->session->name,
c->flags, c->tty.flags); c->tty.sx, c->tty.sy, c->tty.termname, c->flags,
c->tty.flags, c->references);
} }
ctx->print(ctx, ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Sessions: [%zu/%zu]", ctx->print(ctx, "Sessions: [%zu/%zu]",
sizeof (struct grid_cell), sizeof (struct grid_utf8)); sizeof (struct grid_cell), sizeof (struct grid_utf8));
@@ -109,32 +109,35 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
tim = ctime(&t); tim = ctime(&t);
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';
ctx->print(ctx, "%2u: %p %s: %u windows (created %s) [%ux%u] " ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] "
"[flags=0x%x]", i, s, s->name, winlink_count(&s->windows), "[flags=0x%x, references=%u]", i, s->name,
tim, s->sx, s->sy, s->flags); winlink_count(&s->windows), tim, s->sx, s->sy, s->flags,
s->references);
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window; w = wl->window;
ctx->print(ctx, "%4u: %p/%p %s [%ux%u] [flags=0x%x, " ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, "
"references=%u, layout=%u]", wl->idx, wl, w, w->name, "references=%u, last layout=%d]", wl->idx, w->name,
w->sx, w->sy, w->flags, w->references, w->layout); w->sx, w->sy, w->flags, w->references,
w->lastlayout);
j = 0; j = 0;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
lines = ulines = size = usize = 0; lines = ulines = size = usize = 0;
gd = wp->base.grid; gd = wp->base.grid;
for (k = 0; k < gd->hsize + gd->sy; k++) { for (k = 0; k < gd->hsize + gd->sy; k++) {
if (gd->data[k] != NULL) { gl = &gd->linedata[k];
if (gl->celldata != NULL) {
lines++; lines++;
size += gd->size[k] * size += gl->cellsize *
sizeof (**gd->data); sizeof *gl->celldata;
} }
if (gd->udata[k] != NULL) { if (gl->utf8data != NULL) {
ulines++; ulines++;
usize += gd->usize[k] * usize += gl->utf8size *
sizeof (**gd->udata); sizeof *gl->utf8data;
} }
} }
ctx->print(ctx, "%6u: %p %s %lu %d %u/%u, %zu " ctx->print(ctx, "%6u: %s %lu %d %u/%u, %zu "
"bytes; UTF-8 %u/%u, %zu bytes", j, wp, "bytes; UTF-8 %u/%u, %zu bytes", j,
wp->tty, (u_long) wp->pid, wp->fd, lines, wp->tty, (u_long) wp->pid, wp->fd, lines,
gd->hsize + gd->sy, size, ulines, gd->hsize + gd->sy, size, ulines,
gd->hsize + gd->sy, usize); gd->hsize + gd->sy, usize);
@@ -142,7 +145,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
} }
} }
} }
ctx->print(ctx, ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Terminals:"); ctx->print(ctx, "Terminals:");
SLIST_FOREACH(term, &tty_terms, entry) { SLIST_FOREACH(term, &tty_terms, entry) {
@@ -157,10 +160,8 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
ent->code, ent->name); ent->code, ent->name);
break; break;
case TTYCODE_STRING: case TTYCODE_STRING:
strnvis(out, code->value.string, strnvis(out, code->value.string, sizeof out,
sizeof out, VIS_OCTAL|VIS_WHITE); VIS_OCTAL|VIS_TAB|VIS_NL);
out[(sizeof out) - 1] = '\0';
ctx->print(ctx, "%2u: %s: (string) %s", ctx->print(ctx, "%2u: %s: (string) %s",
ent->code, ent->name, out); ent->code, ent->name, out);
break; break;
@@ -176,7 +177,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
} }
} }
} }
ctx->print(ctx, ""); ctx->print(ctx, "%s", "");
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-buffer.c,v 1.7 2009-01-25 18:51:28 tcunha Exp $ */ /* $Id: cmd-set-buffer.c,v 1.10 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,7 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h> #include <string.h>
#include "tmux.h" #include "tmux.h"
@@ -31,12 +31,10 @@ int cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_buffer_entry = { const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb", "set-buffer", "setb",
CMD_BUFFER_SESSION_USAGE " data", CMD_BUFFER_SESSION_USAGE " data",
CMD_ARG1, CMD_ARG1, 0,
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_set_buffer_exec, cmd_set_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -47,17 +45,23 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct session *s; struct session *s;
u_int limit; u_int limit;
u_char *pdata;
size_t psize;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
limit = options_get_number(&s->options, "buffer-limit"); limit = options_get_number(&s->options, "buffer-limit");
pdata = xstrdup(data->arg);
psize = strlen(pdata);
if (data->buffer == -1) { if (data->buffer == -1) {
paste_add(&s->buffers, xstrdup(data->arg), limit); paste_add(&s->buffers, pdata, psize, limit);
return (0); return (0);
} }
if (paste_replace(&s->buffers, data->buffer, xstrdup(data->arg)) != 0) { if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
xfree(pdata);
return (-1); return (-1);
} }
return (0); return (0);

88
cmd-set-environment.c Normal file
View File

@@ -0,0 +1,88 @@
/* $Id: cmd-set-environment.c,v 1.2 2009-08-11 14:42:59 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Set an environment variable.
*/
int cmd_set_environment_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_environment_entry = {
"set-environment", "setenv",
"[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
CMD_ARG12, CMD_CHFLAG('g')|CMD_CHFLAG('r')|CMD_CHFLAG('u'),
NULL,
cmd_target_parse,
cmd_set_environment_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct environ *env;
if (*data->arg == '\0') {
ctx->error(ctx, "empty variable name");
return (-1);
}
if (strchr(data->arg, '=') != NULL) {
ctx->error(ctx, "variable name contains =");
return (-1);
}
if (data->chflags & CMD_CHFLAG('g'))
env = &global_environ;
else {
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
env = &s->environ;
}
if (data->chflags & CMD_CHFLAG('u')) {
if (data->arg2 != NULL) {
ctx->error(ctx, "can't specify a value with -u");
return (-1);
}
environ_unset(env, data->arg);
} else if (data->chflags & CMD_CHFLAG('r')) {
if (data->arg2 != NULL) {
ctx->error(ctx, "can't specify a value with -r");
return (-1);
}
environ_set(env, data->arg, NULL);
} else {
if (data->arg2 == NULL) {
ctx->error(ctx, "no value specified");
return (-1);
}
environ_set(env, data->arg, data->arg2);
}
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-option.c,v 1.60 2009-03-21 12:44:06 nicm Exp $ */ /* $Id: cmd-set-option.c,v 1.79 2009-09-19 18:53:01 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,28 +31,34 @@ int cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_option_entry = { const struct cmd_entry cmd_set_option_entry = {
"set-option", "set", "set-option", "set",
CMD_OPTION_SESSION_USAGE, "[-agu] " CMD_TARGET_SESSION_USAGE " option [value]",
CMD_GFLAG|CMD_UFLAG, CMD_ARG12, CMD_CHFLAG('a')|CMD_CHFLAG('g')|CMD_CHFLAG('u'),
NULL, NULL,
cmd_option_parse, cmd_target_parse,
cmd_set_option_exec, cmd_set_option_exec,
cmd_option_send, cmd_target_free,
cmd_option_recv, cmd_target_print
cmd_option_free,
cmd_option_print
}; };
const char *set_option_status_keys_list[] = { const char *set_option_status_keys_list[] = {
"emacs", "vi", NULL "emacs", "vi", NULL
}; };
const char *set_option_status_justify_list[] = {
"left", "centre", "right", NULL
};
const char *set_option_bell_action_list[] = { const char *set_option_bell_action_list[] = {
"none", "any", "current", NULL "none", "any", "current", NULL
}; };
const struct set_option_entry set_option_table[NSETOPTION] = { const struct set_option_entry set_option_table[] = {
{ "base-index", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list }, { "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list },
{ "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "default-command", SET_OPTION_STRING, 0, 0, NULL }, { "default-command", SET_OPTION_STRING, 0, 0, NULL },
{ "default-path", SET_OPTION_STRING, 0, 0, NULL }, { "default-path", SET_OPTION_STRING, 0, 0, NULL },
{ "default-shell", SET_OPTION_STRING, 0, 0, NULL },
{ "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
{ "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
@@ -63,68 +69,83 @@ const struct set_option_entry set_option_table[NSETOPTION] = {
{ "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, { "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL }, { "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
{ "set-titles", SET_OPTION_FLAG, 0, 0, NULL }, { "set-titles", SET_OPTION_FLAG, 0, 0, NULL },
{ "set-titles-string", SET_OPTION_STRING, 0, 0, NULL },
{ "status", SET_OPTION_FLAG, 0, 0, NULL }, { "status", SET_OPTION_FLAG, 0, 0, NULL },
{ "status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, { "status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "status-justify",
SET_OPTION_CHOICE, 0, 0, set_option_status_justify_list },
{ "status-keys", SET_OPTION_CHOICE, 0, 0, set_option_status_keys_list }, { "status-keys", SET_OPTION_CHOICE, 0, 0, set_option_status_keys_list },
{ "status-left", SET_OPTION_STRING, 0, 0, NULL }, { "status-left", SET_OPTION_STRING, 0, 0, NULL },
{ "status-left-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-left-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-left-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, { "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "status-right", SET_OPTION_STRING, 0, 0, NULL }, { "status-right", SET_OPTION_STRING, 0, 0, NULL },
{ "status-right-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-right-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-right-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, { "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "status-utf8", SET_OPTION_FLAG, 0, 0, NULL },
{ "terminal-overrides", SET_OPTION_STRING, 0, 0, NULL },
{ "update-environment", SET_OPTION_STRING, 0, 0, NULL },
{ "visual-activity", SET_OPTION_FLAG, 0, 0, NULL },
{ "visual-bell", SET_OPTION_FLAG, 0, 0, NULL },
{ "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
{ NULL, 0, 0, 0, NULL }
}; };
int int
cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_option_data *data = self->data; struct cmd_target_data *data = self->data;
struct session *s; struct session *s;
struct client *c; struct client *c;
struct options *oo; struct options *oo;
const struct set_option_entry *entry; const struct set_option_entry *entry, *opt;
u_int i; u_int i;
if (data->flags & CMD_GFLAG) if (data->chflags & CMD_CHFLAG('g'))
oo = &global_options; oo = &global_s_options;
else { else {
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
oo = &s->options; oo = &s->options;
} }
if (*data->option == '\0') { if (*data->arg == '\0') {
ctx->error(ctx, "invalid option"); ctx->error(ctx, "invalid option");
return (-1); return (-1);
} }
entry = NULL; entry = NULL;
for (i = 0; i < NSETOPTION; i++) { for (opt = set_option_table; opt->name != NULL; opt++) {
if (strncmp(set_option_table[i].name, if (strncmp(opt->name, data->arg, strlen(data->arg)) != 0)
data->option, strlen(data->option)) != 0)
continue; continue;
if (entry != NULL) { if (entry != NULL) {
ctx->error(ctx, "ambiguous option: %s", data->option); ctx->error(ctx, "ambiguous option: %s", data->arg);
return (-1); return (-1);
} }
entry = &set_option_table[i]; entry = opt;
/* Bail now if an exact match. */ /* Bail now if an exact match. */
if (strcmp(entry->name, data->option) == 0) if (strcmp(entry->name, data->arg) == 0)
break; break;
} }
if (entry == NULL) { if (entry == NULL) {
ctx->error(ctx, "unknown option: %s", data->option); ctx->error(ctx, "unknown option: %s", data->arg);
return (-1); return (-1);
} }
if (data->flags & CMD_UFLAG) { if (data->chflags & CMD_CHFLAG('u')) {
if (data->flags & CMD_GFLAG) { if (data->chflags & CMD_CHFLAG('g')) {
ctx->error(ctx, ctx->error(ctx,
"can't unset global option: %s", entry->name); "can't unset global option: %s", entry->name);
return (-1); return (-1);
} }
if (data->value != NULL) { if (data->arg2 != NULL) {
ctx->error(ctx, ctx->error(ctx,
"value passed to unset option: %s", entry->name); "value passed to unset option: %s", entry->name);
return (-1); return (-1);
@@ -135,25 +156,26 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
} else { } else {
switch (entry->type) { switch (entry->type) {
case SET_OPTION_STRING: case SET_OPTION_STRING:
set_option_string(ctx, oo, entry, data->value); set_option_string(ctx, oo, entry,
data->arg2, data->chflags & CMD_CHFLAG('a'));
break; break;
case SET_OPTION_NUMBER: case SET_OPTION_NUMBER:
set_option_number(ctx, oo, entry, data->value); set_option_number(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_KEY: case SET_OPTION_KEY:
set_option_key(ctx, oo, entry, data->value); set_option_key(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_COLOUR: case SET_OPTION_COLOUR:
set_option_colour(ctx, oo, entry, data->value); set_option_colour(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_ATTRIBUTES: case SET_OPTION_ATTRIBUTES:
set_option_attributes(ctx, oo, entry, data->value); set_option_attributes(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_FLAG: case SET_OPTION_FLAG:
set_option_flag(ctx, oo, entry, data->value); set_option_flag(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_CHOICE: case SET_OPTION_CHOICE:
set_option_choice(ctx, oo, entry, data->value); set_option_choice(ctx, oo, entry, data->arg2);
break; break;
} }
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-password.c,v 1.3 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-set-password.c,v 1.8 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,8 +29,6 @@
int cmd_set_password_parse(struct cmd *, int, char **, char **); int cmd_set_password_parse(struct cmd *, int, char **, char **);
int cmd_set_password_exec(struct cmd *, struct cmd_ctx *); int cmd_set_password_exec(struct cmd *, struct cmd_ctx *);
void cmd_set_password_send(struct cmd *, struct buffer *);
void cmd_set_password_recv(struct cmd *, struct buffer *);
void cmd_set_password_free(struct cmd *); void cmd_set_password_free(struct cmd *);
void cmd_set_password_init(struct cmd *, int); void cmd_set_password_init(struct cmd *, int);
size_t cmd_set_password_print(struct cmd *, char *, size_t); size_t cmd_set_password_print(struct cmd *, char *, size_t);
@@ -43,12 +41,10 @@ struct cmd_set_password_data {
const struct cmd_entry cmd_set_password_entry = { const struct cmd_entry cmd_set_password_entry = {
"set-password", "pass", "set-password", "pass",
"[-c] password", "[-c] password",
0, 0, 0,
cmd_set_password_init, cmd_set_password_init,
cmd_set_password_parse, cmd_set_password_parse,
cmd_set_password_exec, cmd_set_password_exec,
cmd_set_password_send,
cmd_set_password_recv,
cmd_set_password_free, cmd_set_password_free,
cmd_set_password_print cmd_set_password_print
}; };
@@ -118,30 +114,10 @@ cmd_set_password_exec(struct cmd *self, struct cmd_ctx *ctx)
server_password = NULL; server_password = NULL;
else else
server_password = xstrdup(data->password); server_password = xstrdup(data->password);
log_debug("pw now %s", server_password);
return (0); return (0);
} }
void
cmd_set_password_send(struct cmd *self, struct buffer *b)
{
struct cmd_set_password_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->password);
}
void
cmd_set_password_recv(struct cmd *self, struct buffer *b)
{
struct cmd_set_password_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->password = cmd_recv_string(b);
}
void void
cmd_set_password_free(struct cmd *self) cmd_set_password_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-window-option.c,v 1.24 2009-01-30 00:24:49 nicm Exp $ */ /* $Id: cmd-set-window-option.c,v 1.38 2009-08-11 14:42:59 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,24 +27,17 @@
* Set a window option. * Set a window option.
*/ */
int cmd_set_window_option_parse(struct cmd *, int, char **, char **);
int cmd_set_window_option_exec(struct cmd *, struct cmd_ctx *); int cmd_set_window_option_exec(struct cmd *, struct cmd_ctx *);
void cmd_set_window_option_send(struct cmd *, struct buffer *);
void cmd_set_window_option_recv(struct cmd *, struct buffer *);
void cmd_set_window_option_free(struct cmd *);
size_t cmd_set_window_option_print(struct cmd *, char *, size_t);
const struct cmd_entry cmd_set_window_option_entry = { const struct cmd_entry cmd_set_window_option_entry = {
"set-window-option", "setw", "set-window-option", "setw",
CMD_OPTION_WINDOW_USAGE, "[-agu] " CMD_TARGET_WINDOW_USAGE " option [value]",
CMD_GFLAG|CMD_UFLAG, CMD_ARG12, CMD_CHFLAG('a')|CMD_CHFLAG('g')|CMD_CHFLAG('u'),
NULL, NULL,
cmd_option_parse, cmd_target_parse,
cmd_set_window_option_exec, cmd_set_window_option_exec,
cmd_option_send, cmd_target_free,
cmd_option_recv, cmd_target_print
cmd_option_free,
cmd_option_print
}; };
const char *set_option_mode_keys_list[] = { const char *set_option_mode_keys_list[] = {
@@ -53,7 +46,7 @@ const char *set_option_mode_keys_list[] = {
const char *set_option_clock_mode_style_list[] = { const char *set_option_clock_mode_style_list[] = {
"12", "24", NULL "12", "24", NULL
}; };
const struct set_option_entry set_window_option_table[NSETWINDOWOPTION] = { const struct set_option_entry set_window_option_table[] = {
{ "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL }, { "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL },
{ "automatic-rename", SET_OPTION_FLAG, 0, 0, NULL }, { "automatic-rename", SET_OPTION_FLAG, 0, 0, NULL },
{ "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL }, { "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL },
@@ -61,69 +54,76 @@ const struct set_option_entry set_window_option_table[NSETWINDOWOPTION] = {
SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list }, SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list },
{ "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "main-pane-height", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "main-pane-width", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "mode-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, { "mode-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "mode-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "mode-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list }, { "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list },
{ "mode-mouse", SET_OPTION_FLAG, 0, 0, NULL },
{ "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL }, { "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL },
{ "monitor-content", SET_OPTION_STRING, 0, 0, NULL },
{ "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL }, { "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
{ "utf8", SET_OPTION_FLAG, 0, 0, NULL }, { "utf8", SET_OPTION_FLAG, 0, 0, NULL },
{ "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, { "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-current-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "window-status-current-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-current-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL }, { "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL },
{ NULL, 0, 0, 0, NULL }
}; };
int int
cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_option_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct client *c; struct client *c;
struct options *oo; struct options *oo;
const struct set_option_entry *entry; const struct set_option_entry *entry, *opt;
u_int i; u_int i;
if (data->flags & CMD_GFLAG) if (data->chflags & CMD_CHFLAG('g'))
oo = &global_window_options; oo = &global_w_options;
else { else {
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
oo = &wl->window->options; oo = &wl->window->options;
} }
if (*data->option == '\0') { if (*data->arg == '\0') {
ctx->error(ctx, "invalid option"); ctx->error(ctx, "invalid option");
return (-1); return (-1);
} }
entry = NULL; entry = NULL;
for (i = 0; i < NSETWINDOWOPTION; i++) { for (opt = set_window_option_table; opt->name != NULL; opt++) {
if (strncmp(set_window_option_table[i].name, if (strncmp(opt->name, data->arg, strlen(data->arg)) != 0)
data->option, strlen(data->option)) != 0)
continue; continue;
if (entry != NULL) { if (entry != NULL) {
ctx->error(ctx, "ambiguous option: %s", data->option); ctx->error(ctx, "ambiguous option: %s", data->arg);
return (-1); return (-1);
} }
entry = &set_window_option_table[i]; entry = opt;
/* Bail now if an exact match. */ /* Bail now if an exact match. */
if (strcmp(entry->name, data->option) == 0) if (strcmp(entry->name, data->arg) == 0)
break; break;
} }
if (entry == NULL) { if (entry == NULL) {
ctx->error(ctx, "unknown option: %s", data->option); ctx->error(ctx, "unknown option: %s", data->arg);
return (-1); return (-1);
} }
if (data->flags & CMD_UFLAG) { if (data->chflags & CMD_CHFLAG('u')) {
if (data->flags & CMD_GFLAG) { if (data->chflags & CMD_CHFLAG('g')) {
ctx->error(ctx, ctx->error(ctx,
"can't unset global option: %s", entry->name); "can't unset global option: %s", entry->name);
return (-1); return (-1);
} }
if (data->value != NULL) { if (data->arg2 != NULL) {
ctx->error(ctx, ctx->error(ctx,
"value passed to unset option: %s", entry->name); "value passed to unset option: %s", entry->name);
return (-1); return (-1);
@@ -134,25 +134,26 @@ cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
} else { } else {
switch (entry->type) { switch (entry->type) {
case SET_OPTION_STRING: case SET_OPTION_STRING:
set_option_string(ctx, oo, entry, data->value); set_option_string(ctx, oo, entry,
data->arg2, data->chflags & CMD_CHFLAG('a'));
break; break;
case SET_OPTION_NUMBER: case SET_OPTION_NUMBER:
set_option_number(ctx, oo, entry, data->value); set_option_number(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_KEY: case SET_OPTION_KEY:
set_option_key(ctx, oo, entry, data->value); set_option_key(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_COLOUR: case SET_OPTION_COLOUR:
set_option_colour(ctx, oo, entry, data->value); set_option_colour(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_ATTRIBUTES: case SET_OPTION_ATTRIBUTES:
set_option_attributes(ctx, oo, entry, data->value); set_option_attributes(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_FLAG: case SET_OPTION_FLAG:
set_option_flag(ctx, oo, entry, data->value); set_option_flag(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_CHOICE: case SET_OPTION_CHOICE:
set_option_choice(ctx, oo, entry, data->value); set_option_choice(ctx, oo, entry, data->arg2);
break; break;
} }
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-buffer.c,v 1.4 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-show-buffer.c,v 1.10 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,8 +18,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -31,12 +29,10 @@ int cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_buffer_entry = { const struct cmd_entry cmd_show_buffer_entry = {
"show-buffer", "showb", "show-buffer", "showb",
CMD_BUFFER_SESSION_USAGE, CMD_BUFFER_SESSION_USAGE,
0, 0, 0,
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_show_buffer_exec, cmd_show_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -47,9 +43,9 @@ cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
u_int size; char *in, *buf, *ptr;
char *buf, *ptr; size_t size, len;
size_t len; u_int width;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
@@ -63,27 +59,43 @@ cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
return (-1); return (-1);
} }
if (pb == NULL)
return (0);
if (pb != NULL) { size = pb->size;
size = s->sx; if (size > SIZE_MAX / 4 - 1)
size = SIZE_MAX / 4 - 1;
in = xmalloc(size * 4 + 1);
strvisx(in, pb->data, size, VIS_OCTAL|VIS_TAB);
buf = xmalloc(size + 1); width = s->sx;
len = 0; if (ctx->cmdclient != NULL)
width = ctx->cmdclient->tty.sx;
ptr = pb->data; buf = xmalloc(width + 1);
do { len = 0;
buf[len++] = *ptr++;
if (len == size) { ptr = in;
buf[len] = '\0'; do {
ctx->print(ctx, buf); buf[len++] = *ptr++;
len = 0; if (len == width || buf[len - 1] == '\n') {
} if (buf[len - 1] == '\n')
} while (*ptr != '\0'); len--;
buf[len] = '\0';
ctx->print(ctx, "%s", buf);
len = 0;
}
} while (*ptr != '\0');
if (len != 0) {
buf[len] = '\0'; buf[len] = '\0';
ctx->print(ctx, buf); ctx->print(ctx, "%s", buf);
} }
xfree(buf);
xfree(in);
return (0); return (0);
} }

67
cmd-show-environment.c Normal file
View File

@@ -0,0 +1,67 @@
/* $Id: cmd-show-environment.c,v 1.1 2009-08-09 17:48:55 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Show environment.
*/
int cmd_show_environment_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_environment_entry = {
"show-environment", "showenv",
"[-g] " CMD_TARGET_SESSION_USAGE,
0, CMD_CHFLAG('g'),
cmd_target_init,
cmd_target_parse,
cmd_show_environment_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct environ *env;
struct environ_entry *envent;
if (data->chflags & CMD_CHFLAG('g'))
env = &global_environ;
else {
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
env = &s->environ;
}
RB_FOREACH(envent, environ, env) {
if (envent->value != NULL)
ctx->print(ctx, "%s=%s", envent->name, envent->value);
else
ctx->print(ctx, "-%s", envent->name);
}
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-options.c,v 1.11 2009-01-27 20:22:33 nicm Exp $ */ /* $Id: cmd-show-options.c,v 1.16 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,12 +32,10 @@ int cmd_show_options_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_options_entry = { const struct cmd_entry cmd_show_options_entry = {
"show-options", "show", "show-options", "show",
"[-g] " CMD_TARGET_SESSION_USAGE, "[-g] " CMD_TARGET_SESSION_USAGE,
CMD_GFLAG, 0, CMD_CHFLAG('g'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_show_options_exec, cmd_show_options_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -49,21 +47,18 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s; struct session *s;
struct options *oo; struct options *oo;
const struct set_option_entry *entry; const struct set_option_entry *entry;
u_int i;
char *vs; char *vs;
long long vn; long long vn;
if (data->flags & CMD_GFLAG) if (data->chflags & CMD_CHFLAG('g'))
oo = &global_options; oo = &global_s_options;
else { else {
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
oo = &s->options; oo = &s->options;
} }
for (i = 0; i < NSETOPTION; i++) { for (entry = set_option_table; entry->name != NULL; entry++) {
entry = &set_option_table[i];
if (options_find1(oo, entry->name) == NULL) if (options_find1(oo, entry->name) == NULL)
continue; continue;

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-window-options.c,v 1.7 2009-01-27 20:22:33 nicm Exp $ */ /* $Id: cmd-show-window-options.c,v 1.12 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,12 +32,10 @@ int cmd_show_window_options_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_window_options_entry = { const struct cmd_entry cmd_show_window_options_entry = {
"show-window-options", "showw", "show-window-options", "showw",
"[-g] " CMD_TARGET_WINDOW_USAGE, "[-g] " CMD_TARGET_WINDOW_USAGE,
CMD_GFLAG, 0, CMD_CHFLAG('g'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_show_window_options_exec, cmd_show_window_options_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -49,21 +47,18 @@ cmd_show_window_options_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl; struct winlink *wl;
struct options *oo; struct options *oo;
const struct set_option_entry *entry; const struct set_option_entry *entry;
u_int i;
char *vs; char *vs;
long long vn; long long vn;
if (data->flags & CMD_GFLAG) if (data->chflags & CMD_CHFLAG('g'))
oo = &global_window_options; oo = &global_w_options;
else { else {
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
oo = &wl->window->options; oo = &wl->window->options;
} }
for (i = 0; i < NSETWINDOWOPTION; i++) { for (entry = set_window_option_table; entry->name != NULL; entry++) {
entry = &set_window_option_table[i];
if (options_find1(oo, entry->name) == NULL) if (options_find1(oo, entry->name) == NULL)
continue; continue;

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-source-file.c,v 1.5 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-source-file.c,v 1.8 2009-08-24 16:27:03 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
@@ -26,8 +26,6 @@
int cmd_source_file_parse(struct cmd *, int, char **, char **); int cmd_source_file_parse(struct cmd *, int, char **, char **);
int cmd_source_file_exec(struct cmd *, struct cmd_ctx *); int cmd_source_file_exec(struct cmd *, struct cmd_ctx *);
void cmd_source_file_send(struct cmd *, struct buffer *);
void cmd_source_file_recv(struct cmd *, struct buffer *);
void cmd_source_file_free(struct cmd *); void cmd_source_file_free(struct cmd *);
void cmd_source_file_init(struct cmd *, int); void cmd_source_file_init(struct cmd *, int);
size_t cmd_source_file_print(struct cmd *, char *, size_t); size_t cmd_source_file_print(struct cmd *, char *, size_t);
@@ -39,12 +37,10 @@ struct cmd_source_file_data {
const struct cmd_entry cmd_source_file_entry = { const struct cmd_entry cmd_source_file_entry = {
"source-file", "source", "source-file", "source",
"path", "path",
0, 0, 0,
cmd_source_file_init, cmd_source_file_init,
cmd_source_file_parse, cmd_source_file_parse,
cmd_source_file_exec, cmd_source_file_exec,
cmd_source_file_send,
cmd_source_file_recv,
cmd_source_file_free, cmd_source_file_free,
cmd_source_file_print cmd_source_file_print
}; };
@@ -94,7 +90,7 @@ cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
struct cmd_source_file_data *data = self->data; struct cmd_source_file_data *data = self->data;
char *cause; char *cause;
if (load_cfg(data->path, &cause) != 0) { if (load_cfg(data->path, ctx, &cause) != 0) {
ctx->error(ctx, "%s", cause); ctx->error(ctx, "%s", cause);
xfree(cause); xfree(cause);
return (-1); return (-1);
@@ -103,25 +99,6 @@ cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
void
cmd_source_file_send(struct cmd *self, struct buffer *b)
{
struct cmd_source_file_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->path);
}
void
cmd_source_file_recv(struct cmd *self, struct buffer *b)
{
struct cmd_source_file_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->path = cmd_recv_string(b);
}
void void
cmd_source_file_free(struct cmd *self) cmd_source_file_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-split-window.c,v 1.12 2009-04-03 17:21:46 nicm Exp $ */ /* $Id: cmd-split-window.c,v 1.27 2009-09-16 12:36:27 nicm Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,8 +29,6 @@
int cmd_split_window_parse(struct cmd *, int, char **, char **); int cmd_split_window_parse(struct cmd *, int, char **, char **);
int cmd_split_window_exec(struct cmd *, struct cmd_ctx *); int cmd_split_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_split_window_send(struct cmd *, struct buffer *);
void cmd_split_window_recv(struct cmd *, struct buffer *);
void cmd_split_window_free(struct cmd *); void cmd_split_window_free(struct cmd *);
void cmd_split_window_init(struct cmd *, int); void cmd_split_window_init(struct cmd *, int);
size_t cmd_split_window_print(struct cmd *, char *, size_t); size_t cmd_split_window_print(struct cmd *, char *, size_t);
@@ -39,25 +37,24 @@ struct cmd_split_window_data {
char *target; char *target;
char *cmd; char *cmd;
int flag_detached; int flag_detached;
int flag_horizontal;
int percentage; int percentage;
int lines; int size;
}; };
const struct cmd_entry cmd_split_window_entry = { const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw", "split-window", "splitw",
"[-d] [-p percentage|-l lines] [-t target-window] [command]", "[-dhv] [-p percentage|-l size] [-t target-window] [command]",
0, 0, 0,
cmd_split_window_init, cmd_split_window_init,
cmd_split_window_parse, cmd_split_window_parse,
cmd_split_window_exec, cmd_split_window_exec,
cmd_split_window_send,
cmd_split_window_recv,
cmd_split_window_free, cmd_split_window_free,
cmd_split_window_print cmd_split_window_print
}; };
void void
cmd_split_window_init(struct cmd *self, unused int arg) cmd_split_window_init(struct cmd *self, int key)
{ {
struct cmd_split_window_data *data; struct cmd_split_window_data *data;
@@ -65,50 +62,63 @@ cmd_split_window_init(struct cmd *self, unused int arg)
data->target = NULL; data->target = NULL;
data->cmd = NULL; data->cmd = NULL;
data->flag_detached = 0; data->flag_detached = 0;
data->flag_horizontal = 0;
data->percentage = -1; data->percentage = -1;
data->lines = -1; data->size = -1;
switch (key) {
case '%':
data->flag_horizontal = 1;
break;
case '"':
data->flag_horizontal = 0;
break;
}
} }
int int
cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_split_window_data *data; struct cmd_split_window_data *data;
int opt, n; int opt;
const char *errstr; const char *errstr;
self->entry->init(self, 0); self->entry->init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, "dl:p:t:")) != -1) { while ((opt = getopt(argc, argv, "dhl:p:t:v")) != -1) {
switch (opt) { switch (opt) {
case 'd': case 'd':
data->flag_detached = 1; data->flag_detached = 1;
break; break;
case 'h':
data->flag_horizontal = 1;
break;
case 't': case 't':
if (data->target == NULL) if (data->target == NULL)
data->target = xstrdup(optarg); data->target = xstrdup(optarg);
break; break;
case 'l': case 'l':
if (data->percentage == -1 && data->lines == -1) { if (data->percentage != -1 || data->size != -1)
n = strtonum(optarg, 1, INT_MAX, &errstr); break;
if (errstr != NULL) { data->size = strtonum(optarg, 1, INT_MAX, &errstr);
xasprintf(cause, "lines %s", errstr); if (errstr != NULL) {
goto error; xasprintf(cause, "size %s", errstr);
} goto error;
data->lines = n;
} }
break; break;
case 'p': case 'p':
if (data->lines == -1 && data->percentage == -1) { if (data->size != -1 || data->percentage != -1)
n = strtonum(optarg, 1, 100, &errstr); break;
if (errstr != NULL) { data->percentage = strtonum(optarg, 1, 100, &errstr);
xasprintf( if (errstr != NULL) {
cause, "percentage %s", errstr); xasprintf(cause, "percentage %s", errstr);
goto error; goto error;
}
data->percentage = n;
} }
break; break;
case 'v':
data->flag_horizontal = 0;
break;
default: default:
goto usage; goto usage;
} }
@@ -139,37 +149,53 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
const char **env; struct environ env;
char *cmd, *cwd, *cause; char *cmd, *cwd, *cause;
u_int hlimit, lines; const char *shell;
u_int hlimit;
int size;
enum layout_type type;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
env = server_fill_environ(s); environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
cmd = data->cmd; cmd = data->cmd;
if (cmd == NULL) if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL) if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
cwd = options_get_string(&global_options, "default-path"); cwd = options_get_string(&s->options, "default-path");
else else
cwd = ctx->cmdclient->cwd; cwd = ctx->cmdclient->cwd;
lines = -1; size = -1;
if (data->lines != -1) if (data->size != -1)
lines = data->lines; size = data->size;
else if (data->percentage != -1) else if (data->percentage != -1)
lines = (w->active->sy * data->percentage) / 100; size = (w->active->sy * data->percentage) / 100;
hlimit = options_get_number(&s->options, "history-limit"); hlimit = options_get_number(&s->options, "history-limit");
wp = window_add_pane(w, lines, cmd, cwd, env, hlimit, &cause);
if (wp == NULL) { type = LAYOUT_TOPBOTTOM;
ctx->error(ctx, "create pane failed: %s", cause); if (data->flag_horizontal)
xfree(cause); type = LAYOUT_LEFTRIGHT;
return (-1);
shell = options_get_string(&s->options, "default-shell");
if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL;
wp = window_add_pane(w, hlimit);
if (window_pane_spawn(wp, cmd, shell, cwd, &env, s->tio, &cause) != 0)
goto error;
if (layout_split_pane(w->active, type, size, wp) != 0) {
cause = xstrdup("pane too small");
goto error;
} }
server_redraw_window(w); server_redraw_window(w);
if (!data->flag_detached) { if (!data->flag_detached) {
@@ -178,30 +204,17 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_session(s); server_redraw_session(s);
} else } else
server_status_session(s); server_status_session(s);
layout_refresh(w, 0);
environ_free(&env);
return (0); return (0);
}
void error:
cmd_split_window_send(struct cmd *self, struct buffer *b) environ_free(&env);
{ if (wp != NULL)
struct cmd_split_window_data *data = self->data; window_remove_pane(w, wp);
ctx->error(ctx, "create pane failed: %s", cause);
buffer_write(b, data, sizeof *data); xfree(cause);
cmd_send_string(b, data->target); return (-1);
cmd_send_string(b, data->cmd);
}
void
cmd_split_window_recv(struct cmd *self, struct buffer *b)
{
struct cmd_split_window_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
} }
void void
@@ -227,6 +240,14 @@ cmd_split_window_print(struct cmd *self, char *buf, size_t len)
return (off); return (off);
if (off < len && data->flag_detached) if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, " -d"); off += xsnprintf(buf + off, len - off, " -d");
if (off < len && data->flag_horizontal)
off += xsnprintf(buf + off, len - off, " -h");
if (off < len && data->size > 0)
off += xsnprintf(buf + off, len - off, " -l %d", data->size);
if (off < len && data->percentage > 0) {
off += xsnprintf(
buf + off, len - off, " -p %d", data->percentage);
}
if (off < len && data->target != NULL) if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target); off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->cmd != NULL) if (off < len && data->cmd != NULL)

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-start-server.c,v 1.6 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-start-server.c,v 1.8 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,13 +29,11 @@ int cmd_start_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_start_server_entry = { const struct cmd_entry cmd_start_server_entry = {
"start-server", "start", "start-server", "start",
"", "",
CMD_STARTSERVER, CMD_STARTSERVER, 0,
NULL, NULL,
NULL, NULL,
cmd_start_server_exec, cmd_start_server_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-string.c,v 1.13 2009-02-16 19:29:17 nicm Exp $ */ /* $Id: cmd-string.c,v 1.23 2009-08-09 17:48:55 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,9 +19,11 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
@@ -33,6 +35,7 @@ int cmd_string_getc(const char *, size_t *);
void cmd_string_ungetc(const char *, size_t *); void cmd_string_ungetc(const char *, size_t *);
char *cmd_string_string(const char *, size_t *, char, int); char *cmd_string_string(const char *, size_t *, char, int);
char *cmd_string_variable(const char *, size_t *); char *cmd_string_variable(const char *, size_t *);
char *cmd_string_expand_tilde(const char *, size_t *);
int int
cmd_string_getc(const char *s, size_t *p) cmd_string_getc(const char *s, size_t *p)
@@ -56,21 +59,11 @@ int
cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause) cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
{ {
size_t p; size_t p;
int ch, argc, rval, have_arg; int ch, i, argc, rval, have_arg;
char **argv, *buf, *t, *u; char **argv, *buf, *t;
const char *whitespace, *equals;
size_t len; size_t len;
if ((t = strchr(s, ' ')) == NULL && (t = strchr(s, '\t')) == NULL)
t = strchr(s, '\0');
if ((u = strchr(s, '=')) != NULL && u < t) {
if (putenv(s) != 0) {
xasprintf(cause, "assignment failed: %s", s);
return (-1);
}
*cmdlist = NULL;
return (0);
}
argv = NULL; argv = NULL;
argc = 0; argc = 0;
@@ -114,6 +107,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
buf = xrealloc(buf, 1, len + strlen(t) + 1); buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1); strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t); len += strlen(t);
xfree(t);
have_arg = 1; have_arg = 1;
break; break;
@@ -143,6 +137,18 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
if (argc == 0) if (argc == 0)
goto out; goto out;
for (i = 0; i < argc; i++) {
equals = strchr(argv[i], '=');
whitespace = argv[i] + strcspn(argv[i], " \t");
if (equals == NULL || equals > whitespace)
break;
environ_put(&global_environ, argv[i]);
memmove(&argv[i], &argv[i + 1], argc - i - 1);
argc--;
}
if (argc == 0)
goto out;
*cmdlist = cmd_list_parse(argc, argv, cause); *cmdlist = cmd_list_parse(argc, argv, cause);
if (*cmdlist == NULL) if (*cmdlist == NULL)
goto out; goto out;
@@ -153,6 +159,17 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
rval = 0; rval = 0;
goto out; goto out;
case '~':
if (have_arg == 0) {
if ((t = cmd_string_expand_tilde(s, &p)) == NULL)
goto error;
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
xfree(t);
break;
}
/* FALLTHROUGH */
default: default:
if (len >= SIZE_MAX - 2) if (len >= SIZE_MAX - 2)
goto error; goto error;
@@ -200,6 +217,9 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
switch (ch = cmd_string_getc(s, p)) { switch (ch = cmd_string_getc(s, p)) {
case EOF: case EOF:
goto error; goto error;
case 'e':
ch = '\033';
break;
case 'r': case 'r':
ch = '\r'; ch = '\r';
break; break;
@@ -219,6 +239,7 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
buf = xrealloc(buf, 1, len + strlen(t) + 1); buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1); strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t); len += strlen(t);
xfree(t);
continue; continue;
} }
@@ -274,7 +295,7 @@ cmd_string_variable(const char *s, size_t *p)
buf = xrealloc(buf, 1, len + 1); buf = xrealloc(buf, 1, len + 1);
buf[len++] = ch; buf[len++] = ch;
for(;;) { for (;;) {
ch = cmd_string_getc(s, p); ch = cmd_string_getc(s, p);
if (ch == EOF || !cmd_string_other(ch)) if (ch == EOF || !cmd_string_other(ch))
break; break;
@@ -307,3 +328,31 @@ error:
xfree(buf); xfree(buf);
return (NULL); return (NULL);
} }
char *
cmd_string_expand_tilde(const char *s, size_t *p)
{
struct passwd *pw;
char *home, *path, *username;
home = NULL;
if (cmd_string_getc(s, p) == '/') {
if ((home = getenv("HOME")) == NULL) {
if ((pw = getpwuid(getuid())) != NULL)
home = pw->pw_dir;
}
} else {
cmd_string_ungetc(s, p);
if ((username = cmd_string_string(s, p, '/', 0)) == NULL)
return (NULL);
if ((pw = getpwnam(username)) != NULL)
home = pw->pw_dir;
if (username != NULL)
xfree(username);
}
if (home == NULL)
return (NULL);
xasprintf(&path, "%s/", home);
return (path);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-suspend-client.c,v 1.2 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-suspend-client.c,v 1.4 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -37,12 +37,10 @@ struct cmd_suspend_client_data {
const struct cmd_entry cmd_suspend_client_entry = { const struct cmd_entry cmd_suspend_client_entry = {
"suspend-client", "suspendc", "suspend-client", "suspendc",
"[-c target-client]", "[-c target-client]",
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_suspend_client_exec, cmd_suspend_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-swap-pane.c,v 1.4 2009-04-03 17:21:46 nicm Exp $ */ /* $Id: cmd-swap-pane.c,v 1.13 2009-07-30 21:04:40 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,260 +26,118 @@
* Swap two panes. * Swap two panes.
*/ */
int cmd_swap_pane_parse(struct cmd *, int, char **, char **);
int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_swap_pane_send(struct cmd *, struct buffer *);
void cmd_swap_pane_recv(struct cmd *, struct buffer *);
void cmd_swap_pane_free(struct cmd *);
void cmd_swap_pane_init(struct cmd *, int); void cmd_swap_pane_init(struct cmd *, int);
size_t cmd_swap_pane_print(struct cmd *, char *, size_t); int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
struct cmd_swap_pane_data {
char *target;
int src;
int dst;
int flag_detached;
int flag_up;
int flag_down;
};
const struct cmd_entry cmd_swap_pane_entry = { const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp", "swap-pane", "swapp",
"[-dDU] [-t target-window] [-p src-index] [-q dst-index]", "[-dDU] " CMD_SRCDST_PANE_USAGE,
0, 0, CMD_CHFLAG('d')|CMD_CHFLAG('D')|CMD_CHFLAG('U'),
cmd_swap_pane_init, cmd_swap_pane_init,
cmd_swap_pane_parse, cmd_srcdst_parse,
cmd_swap_pane_exec, cmd_swap_pane_exec,
cmd_swap_pane_send, cmd_srcdst_free,
cmd_swap_pane_recv, cmd_srcdst_print
cmd_swap_pane_free,
cmd_swap_pane_print
}; };
void void
cmd_swap_pane_init(struct cmd *self, int key) cmd_swap_pane_init(struct cmd *self, int key)
{ {
struct cmd_swap_pane_data *data; struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data); cmd_srcdst_init(self, key);
data->target = NULL;
data->src = -1;
data->dst = -1;
data->flag_detached = 0;
data->flag_up = 0;
data->flag_down = 0;
switch (key) {
case '{':
data->flag_up = 1;
break;
case '}':
data->flag_down = 1;
break;
}
}
int
cmd_swap_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_swap_pane_data *data;
int opt, n;
const char *errstr;
self->entry->init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, "dDt:p:q:U")) != -1) { if (key == '{')
switch (opt) { data->chflags |= CMD_CHFLAG('U');
case 'd': else if (key == '}')
data->flag_detached = 1; data->chflags |= CMD_CHFLAG('D');
break;
case 'D':
data->flag_up = 0;
data->flag_down = 1;
data->dst = -1;
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'p':
if (data->src == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "src %s", errstr);
goto error;
}
data->src = n;
}
break;
case 'q':
if (data->dst == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "dst %s", errstr);
goto error;
}
data->dst = n;
}
data->flag_up = 0;
data->flag_down = 0;
break;
case 'U':
data->flag_up = 1;
data->flag_down = 0;
data->dst = -1;
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
} }
int int
cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_swap_pane_data *data = self->data; struct cmd_srcdst_data *data = self->data;
struct winlink *wl; struct winlink *src_wl, *dst_wl;
struct window *w; struct window *src_w, *dst_w;
struct window_pane *tmp_wp, *src_wp, *dst_wp; struct window_pane *tmp_wp, *src_wp, *dst_wp;
u_int xx, yy; struct layout_cell *src_lc, *dst_lc;
u_int sx, sy, xoff, yoff;
if (data == NULL) if (data == NULL)
return (0); return (0);
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((dst_wl = cmd_find_pane(ctx, data->dst, NULL, &dst_wp)) == NULL)
return (-1); return (-1);
w = wl->window; dst_w = dst_wl->window;
if (data->src == -1) if (data->src == NULL) {
src_wp = w->active; src_w = dst_w;
else { if (data->chflags & CMD_CHFLAG('D')) {
src_wp = window_pane_at_index(w, data->src); src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL) { if (src_wp == NULL)
ctx->error(ctx, "no pane: %d", data->src); src_wp = TAILQ_FIRST(&dst_w->panes);
} else if (data->chflags & CMD_CHFLAG('U')) {
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
} else
return (0);
} else {
src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp);
if (src_wl == NULL)
return (-1); return (-1);
} src_w = src_wl->window;
}
if (data->dst == -1)
dst_wp = w->active;
else {
dst_wp = window_pane_at_index(w, data->dst);
if (dst_wp == NULL) {
ctx->error(ctx, "no pane: %d", data->dst);
return (-1);
}
}
if (data->dst == -1 && data->flag_up) {
if ((dst_wp = TAILQ_PREV(src_wp, window_panes, entry)) == NULL)
dst_wp = TAILQ_LAST(&w->panes, window_panes);
}
if (data->dst == -1 && data->flag_down) {
if ((dst_wp = TAILQ_NEXT(src_wp, entry)) == NULL)
dst_wp = TAILQ_FIRST(&w->panes);
} }
if (src_wp == dst_wp) if (src_wp == dst_wp)
return (0); return (0);
tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry); tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
TAILQ_REMOVE(&w->panes, dst_wp, entry); TAILQ_REMOVE(&dst_w->panes, dst_wp, entry);
TAILQ_REPLACE(&w->panes, src_wp, dst_wp, entry); TAILQ_REPLACE(&src_w->panes, src_wp, dst_wp, entry);
if (tmp_wp == src_wp) if (tmp_wp == src_wp)
tmp_wp = dst_wp; tmp_wp = dst_wp;
if (tmp_wp == NULL) if (tmp_wp == NULL)
TAILQ_INSERT_HEAD(&w->panes, src_wp, entry); TAILQ_INSERT_HEAD(&dst_w->panes, src_wp, entry);
else else
TAILQ_INSERT_AFTER(&w->panes, tmp_wp, src_wp, entry); TAILQ_INSERT_AFTER(&dst_w->panes, tmp_wp, src_wp, entry);
xx = src_wp->xoff; src_lc = src_wp->layout_cell;
yy = src_wp->yoff; dst_lc = dst_wp->layout_cell;
src_wp->xoff = dst_wp->xoff; src_lc->wp = dst_wp;
src_wp->yoff = dst_wp->yoff; dst_wp->layout_cell = src_lc;
dst_wp->xoff = xx; dst_lc->wp = src_wp;
dst_wp->yoff = yy; src_wp->layout_cell = dst_lc;
xx = src_wp->sx; src_wp->window = dst_w;
yy = src_wp->sy; dst_wp->window = src_w;
sx = src_wp->sx; sy = src_wp->sy;
xoff = src_wp->xoff; yoff = src_wp->yoff;
src_wp->xoff = dst_wp->xoff; src_wp->yoff = dst_wp->yoff;
window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy); window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy);
window_pane_resize(dst_wp, xx, yy); dst_wp->xoff = xoff; dst_wp->yoff = yoff;
window_pane_resize(dst_wp, sx, sy);
if (!data->flag_detached) { if (!(data->chflags & CMD_CHFLAG('d'))) {
window_set_active_pane(w, dst_wp); if (src_w != dst_w) {
layout_refresh(w, 0); window_set_active_pane(src_w, dst_wp);
window_set_active_pane(dst_w, src_wp);
} else {
tmp_wp = dst_wp;
if (!window_pane_visible(tmp_wp))
tmp_wp = src_wp;
window_set_active_pane(src_w, tmp_wp);
}
} else {
if (src_w->active == src_wp)
window_set_active_pane(src_w, dst_wp);
if (dst_w->active == dst_wp)
window_set_active_pane(dst_w, src_wp);
} }
server_redraw_window(src_w);
server_redraw_window(dst_w);
return (0); return (0);
} }
void
cmd_swap_pane_send(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
}
void
cmd_swap_pane_recv(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
}
void
cmd_swap_pane_free(struct cmd *self)
{
struct cmd_swap_pane_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
xfree(data);
}
size_t
cmd_swap_pane_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_swap_pane_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len &&
(data->flag_down || data->flag_up || data->flag_detached)) {
off += xsnprintf(buf + off, len - off, " -");
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, "d");
if (off < len && data->flag_up)
off += xsnprintf(buf + off, len - off, "D");
if (off < len && data->flag_down)
off += xsnprintf(buf + off, len - off, "U");
}
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->src != -1)
off += xsnprintf(buf + off, len - off, " -p %d", data->src);
if (off < len && data->dst != -1)
off += xsnprintf(buf + off, len - off, " -q %d", data->dst);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-swap-window.c,v 1.15 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-swap-window.c,v 1.17 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_swap_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_swap_window_entry = { const struct cmd_entry cmd_swap_window_entry = {
"swap-window", "swapw", "swap-window", "swapw",
"[-d] " CMD_SRCDST_WINDOW_USAGE, "[-d] " CMD_SRCDST_WINDOW_USAGE,
CMD_DFLAG, 0, CMD_CHFLAG('d'),
cmd_srcdst_init, cmd_srcdst_init,
cmd_srcdst_parse, cmd_srcdst_parse,
cmd_swap_window_exec, cmd_swap_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free, cmd_srcdst_free,
cmd_srcdst_print cmd_srcdst_print
}; };
@@ -61,7 +59,7 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
wl_dst->window = wl_src->window; wl_dst->window = wl_src->window;
wl_src->window = w; wl_src->window = w;
if (!(data->flags & CMD_DFLAG)) { if (!(data->chflags & CMD_CHFLAG('d'))) {
session_select(dst, wl_dst->idx); session_select(dst, wl_dst->idx);
if (src != dst) if (src != dst)
session_select(src, wl_src->idx); session_select(src, wl_src->idx);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-switch-client.c,v 1.15 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-switch-client.c,v 1.17 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,8 +29,6 @@
int cmd_switch_client_parse(struct cmd *, int, char **, char **); int cmd_switch_client_parse(struct cmd *, int, char **, char **);
int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *); int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_switch_client_send(struct cmd *, struct buffer *);
void cmd_switch_client_recv(struct cmd *, struct buffer *);
void cmd_switch_client_free(struct cmd *); void cmd_switch_client_free(struct cmd *);
size_t cmd_switch_client_print(struct cmd *, char *, size_t); size_t cmd_switch_client_print(struct cmd *, char *, size_t);
@@ -42,12 +40,10 @@ struct cmd_switch_client_data {
const struct cmd_entry cmd_switch_client_entry = { const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc", "switch-client", "switchc",
"[-c target-client] [-t target-session]", "[-c target-client] [-t target-session]",
0, 0, 0,
NULL, NULL,
cmd_switch_client_parse, cmd_switch_client_parse,
cmd_switch_client_exec, cmd_switch_client_exec,
cmd_switch_client_send,
cmd_switch_client_recv,
cmd_switch_client_free, cmd_switch_client_free,
cmd_switch_client_print cmd_switch_client_print
}; };
@@ -111,27 +107,6 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
void
cmd_switch_client_send(struct cmd *self, struct buffer *b)
{
struct cmd_switch_client_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->name);
cmd_send_string(b, data->target);
}
void
cmd_switch_client_recv(struct cmd *self, struct buffer *b)
{
struct cmd_switch_client_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->name = cmd_recv_string(b);
data->target = cmd_recv_string(b);
}
void void
cmd_switch_client_free(struct cmd *self) cmd_switch_client_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-unbind-key.c,v 1.16 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-unbind-key.c,v 1.20 2009-07-28 23:19:06 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,23 +26,24 @@
int cmd_unbind_key_parse(struct cmd *, int, char **, char **); int cmd_unbind_key_parse(struct cmd *, int, char **, char **);
int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *); int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_unbind_key_send(struct cmd *, struct buffer *);
void cmd_unbind_key_recv(struct cmd *, struct buffer *);
void cmd_unbind_key_free(struct cmd *); void cmd_unbind_key_free(struct cmd *);
int cmd_unbind_key_table(struct cmd *, struct cmd_ctx *);
struct cmd_unbind_key_data { struct cmd_unbind_key_data {
int key; int key;
int command_key;
char *tablename;
}; };
const struct cmd_entry cmd_unbind_key_entry = { const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind", "unbind-key", "unbind",
"key", "[-cn] [-t key-table] key",
0, 0, 0,
NULL, NULL,
cmd_unbind_key_parse, cmd_unbind_key_parse,
cmd_unbind_key_exec, cmd_unbind_key_exec,
cmd_unbind_key_send,
cmd_unbind_key_recv,
cmd_unbind_key_free, cmd_unbind_key_free,
NULL NULL
}; };
@@ -51,12 +52,23 @@ int
cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_unbind_key_data *data; struct cmd_unbind_key_data *data;
int opt; int opt, no_prefix = 0;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->command_key = 0;
data->tablename = NULL;
while ((opt = getopt(argc, argv, "")) != -1) { while ((opt = getopt(argc, argv, "cnt:")) != -1) {
switch (opt) { switch (opt) {
case 'c':
data->command_key = 1;
break;
case 'n':
no_prefix = 1;
break;
case 't':
data->tablename = xstrdup(optarg);
break;
default: default:
goto usage; goto usage;
} }
@@ -70,6 +82,8 @@ cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
xasprintf(cause, "unknown key: %s", argv[0]); xasprintf(cause, "unknown key: %s", argv[0]);
goto error; goto error;
} }
if (!no_prefix)
data->key |= KEYC_PREFIX;
return (0); return (0);
@@ -88,27 +102,33 @@ cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return (0); return (0);
if (data->tablename != NULL)
return (cmd_unbind_key_table(self, ctx));
key_bindings_remove(data->key); key_bindings_remove(data->key);
return (0); return (0);
} }
void int
cmd_unbind_key_send(struct cmd *self, struct buffer *b) cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_unbind_key_data *data = self->data; struct cmd_unbind_key_data *data = self->data;
const struct mode_key_table *mtab;
struct mode_key_binding *mbind, mtmp;
buffer_write(b, data, sizeof *data); if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
} ctx->error(ctx, "unknown key table: %s", data->tablename);
return (-1);
}
void mtmp.key = data->key & ~KEYC_PREFIX;
cmd_unbind_key_recv(struct cmd *self, struct buffer *b) mtmp.mode = data->command_key ? 1 : 0;
{ if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
struct cmd_unbind_key_data *data; SPLAY_REMOVE(mode_key_tree, mtab->tree, mbind);
xfree(mbind);
self->data = data = xmalloc(sizeof *data); }
buffer_read(b, data, sizeof *data); return (0);
} }
void void
@@ -116,5 +136,7 @@ cmd_unbind_key_free(struct cmd *self)
{ {
struct cmd_unbind_key_data *data = self->data; struct cmd_unbind_key_data *data = self->data;
if (data->tablename != NULL)
xfree(data->tablename);
xfree(data); xfree(data);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-unlink-window.c,v 1.13 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-unlink-window.c,v 1.16 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,11 @@ int cmd_unlink_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_unlink_window_entry = { const struct cmd_entry cmd_unlink_window_entry = {
"unlink-window", "unlinkw", "unlink-window", "unlinkw",
CMD_TARGET_WINDOW_USAGE, "[-k] " CMD_TARGET_WINDOW_USAGE,
0, 0, CMD_CHFLAG('k'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_unlink_window_exec, cmd_unlink_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -52,7 +50,7 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1); return (-1);
if (wl->window->references == 1) { if (!(data->chflags & CMD_CHFLAG('k')) && wl->window->references == 1) {
ctx->error(ctx, "window is only linked to one session"); ctx->error(ctx, "window is only linked to one session");
return (-1); return (-1);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-up-pane.c,v 1.7 2009-04-01 21:10:08 nicm Exp $ */ /* $Id: cmd-up-pane.c,v 1.12 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_up_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_up_pane_entry = { const struct cmd_entry cmd_up_pane_entry = {
"up-pane", "upp", "up-pane", "upp",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_up_pane_exec, cmd_up_pane_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -54,8 +52,8 @@ cmd_up_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
w->active = TAILQ_PREV(w->active, window_panes, entry); w->active = TAILQ_PREV(w->active, window_panes, entry);
if (w->active == NULL) if (w->active == NULL)
w->active = TAILQ_LAST(&w->panes, window_panes); w->active = TAILQ_LAST(&w->panes, window_panes);
layout_refresh(w, 1); } while (!window_pane_visible(w->active));
} while (w->active->flags & PANE_HIDDEN); server_status_window(wl->window);
return (0); return (0);
} }

790
cmd.c
View File

@@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.89 2009-04-03 17:21:46 nicm Exp $ */ /* $Id: cmd.c,v 1.115 2009-08-31 22:30:15 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,6 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <fnmatch.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@@ -29,17 +30,23 @@ const struct cmd_entry *cmd_table[] = {
&cmd_attach_session_entry, &cmd_attach_session_entry,
&cmd_bind_key_entry, &cmd_bind_key_entry,
&cmd_break_pane_entry, &cmd_break_pane_entry,
&cmd_choose_client_entry,
&cmd_choose_session_entry, &cmd_choose_session_entry,
&cmd_choose_window_entry, &cmd_choose_window_entry,
&cmd_clear_history_entry,
&cmd_clock_mode_entry, &cmd_clock_mode_entry,
&cmd_command_prompt_entry, &cmd_command_prompt_entry,
&cmd_confirm_before_entry,
&cmd_copy_buffer_entry, &cmd_copy_buffer_entry,
&cmd_copy_mode_entry, &cmd_copy_mode_entry,
&cmd_delete_buffer_entry, &cmd_delete_buffer_entry,
&cmd_detach_client_entry, &cmd_detach_client_entry,
&cmd_display_message_entry,
&cmd_display_panes_entry,
&cmd_down_pane_entry, &cmd_down_pane_entry,
&cmd_find_window_entry, &cmd_find_window_entry,
&cmd_has_session_entry, &cmd_has_session_entry,
&cmd_if_shell_entry,
&cmd_kill_pane_entry, &cmd_kill_pane_entry,
&cmd_kill_server_entry, &cmd_kill_server_entry,
&cmd_kill_session_entry, &cmd_kill_session_entry,
@@ -60,16 +67,17 @@ const struct cmd_entry *cmd_table[] = {
&cmd_next_layout_entry, &cmd_next_layout_entry,
&cmd_next_window_entry, &cmd_next_window_entry,
&cmd_paste_buffer_entry, &cmd_paste_buffer_entry,
&cmd_previous_layout_entry,
&cmd_previous_window_entry, &cmd_previous_window_entry,
&cmd_refresh_client_entry, &cmd_refresh_client_entry,
&cmd_rename_session_entry, &cmd_rename_session_entry,
&cmd_rename_window_entry, &cmd_rename_window_entry,
&cmd_resize_pane_down_entry, &cmd_resize_pane_entry,
&cmd_resize_pane_up_entry,
&cmd_respawn_window_entry, &cmd_respawn_window_entry,
&cmd_rotate_window_entry, &cmd_rotate_window_entry,
&cmd_save_buffer_entry, &cmd_save_buffer_entry,
&cmd_scroll_mode_entry, &cmd_scroll_mode_entry,
&cmd_select_layout_entry,
&cmd_select_pane_entry, &cmd_select_pane_entry,
&cmd_select_prompt_entry, &cmd_select_prompt_entry,
&cmd_select_window_entry, &cmd_select_window_entry,
@@ -77,10 +85,12 @@ const struct cmd_entry *cmd_table[] = {
&cmd_send_prefix_entry, &cmd_send_prefix_entry,
&cmd_server_info_entry, &cmd_server_info_entry,
&cmd_set_buffer_entry, &cmd_set_buffer_entry,
&cmd_set_environment_entry,
&cmd_set_option_entry, &cmd_set_option_entry,
&cmd_set_password_entry, &cmd_set_password_entry,
&cmd_set_window_option_entry, &cmd_set_window_option_entry,
&cmd_show_buffer_entry, &cmd_show_buffer_entry,
&cmd_show_environment_entry,
&cmd_show_options_entry, &cmd_show_options_entry,
&cmd_show_window_options_entry, &cmd_show_window_options_entry,
&cmd_source_file_entry, &cmd_source_file_entry,
@@ -96,22 +106,89 @@ const struct cmd_entry *cmd_table[] = {
NULL NULL
}; };
struct session *cmd_newest_session(struct sessions *);
struct client *cmd_lookup_client(const char *);
struct session *cmd_lookup_session(const char *, int *);
struct winlink *cmd_lookup_window(struct session *, const char *, int *);
int cmd_lookup_index(struct session *, const char *, int *);
int
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
{
size_t arglen;
int i;
*buf = '\0';
for (i = 0; i < argc; i++) {
if (strlcpy(buf, argv[i], len) >= len)
return (-1);
arglen = strlen(argv[i]) + 1;
buf += arglen;
len -= arglen;
}
return (0);
}
int
cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
{
int i;
size_t arglen;
if (argc == 0)
return (0);
*argv = xcalloc(argc, sizeof **argv);
buf[len - 1] = '\0';
for (i = 0; i < argc; i++) {
if (len == 0) {
cmd_free_argv(argc, *argv);
return (-1);
}
arglen = strlen(buf) + 1;
(*argv)[i] = xstrdup(buf);
buf += arglen;
len -= arglen;
}
return (0);
}
void
cmd_free_argv(int argc, char **argv)
{
int i;
if (argc == 0)
return;
for (i = 0; i < argc; i++) {
if (argv[i] != NULL)
xfree(argv[i]);
}
xfree(argv);
}
struct cmd * struct cmd *
cmd_parse(int argc, char **argv, char **cause) cmd_parse(int argc, char **argv, char **cause)
{ {
const struct cmd_entry **entryp, *entry; const struct cmd_entry **entryp, *entry;
struct cmd *cmd; struct cmd *cmd;
char s[BUFSIZ]; char s[BUFSIZ];
int opt; int opt, ambiguous = 0;
*cause = NULL; *cause = NULL;
if (argc == 0) if (argc == 0) {
xasprintf(cause, "no command");
return (NULL); return (NULL);
}
entry = NULL; entry = NULL;
for (entryp = cmd_table; *entryp != NULL; entryp++) { for (entryp = cmd_table; *entryp != NULL; entryp++) {
if ((*entryp)->alias != NULL && if ((*entryp)->alias != NULL &&
strcmp((*entryp)->alias, argv[0]) == 0) { strcmp((*entryp)->alias, argv[0]) == 0) {
ambiguous = 0;
entry = *entryp; entry = *entryp;
break; break;
} }
@@ -119,13 +196,15 @@ cmd_parse(int argc, char **argv, char **cause)
if (strncmp((*entryp)->name, argv[0], strlen(argv[0])) != 0) if (strncmp((*entryp)->name, argv[0], strlen(argv[0])) != 0)
continue; continue;
if (entry != NULL) if (entry != NULL)
goto ambiguous; ambiguous = 1;
entry = *entryp; entry = *entryp;
/* Bail now if an exact match. */ /* Bail now if an exact match. */
if (strcmp(entry->name, argv[0]) == 0) if (strcmp(entry->name, argv[0]) == 0)
break; break;
} }
if (ambiguous)
goto ambiguous;
if (entry == NULL) { if (entry == NULL) {
xasprintf(cause, "unknown command: %s", argv[0]); xasprintf(cause, "unknown command: %s", argv[0]);
return (NULL); return (NULL);
@@ -186,53 +265,6 @@ cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
return (cmd->entry->exec(cmd, ctx)); return (cmd->entry->exec(cmd, ctx));
} }
void
cmd_send(struct cmd *cmd, struct buffer *b)
{
const struct cmd_entry **entryp;
u_int n;
n = 0;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (*entryp == cmd->entry)
break;
n++;
}
if (*entryp == NULL)
fatalx("command not found");
buffer_write(b, &n, sizeof n);
if (cmd->entry->send != NULL)
cmd->entry->send(cmd, b);
}
struct cmd *
cmd_recv(struct buffer *b)
{
const struct cmd_entry **entryp;
struct cmd *cmd;
u_int m, n;
buffer_read(b, &m, sizeof m);
n = 0;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (n == m)
break;
n++;
}
if (*entryp == NULL)
fatalx("command not found");
cmd = xmalloc(sizeof *cmd);
cmd->entry = *entryp;
if (cmd->entry->recv != NULL)
cmd->entry->recv(cmd, b);
return (cmd);
}
void void
cmd_free(struct cmd *cmd) cmd_free(struct cmd *cmd)
{ {
@@ -250,141 +282,621 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
return (cmd->entry->print(cmd, buf, len)); return (cmd->entry->print(cmd, buf, len));
} }
void /*
cmd_send_string(struct buffer *b, const char *s) * Figure out the current session. Use: 1) the current session, if the command
{ * context has one; 2) the session containing the pty of the calling client, if
size_t n; * any 3) the session specified in the TMUX variable from the environment (as
* passed from the client); 3) the newest session.
if (s == NULL) { */
n = 0;
buffer_write(b, &n, sizeof n);
return;
}
n = strlen(s) + 1;
buffer_write(b, &n, sizeof n);
buffer_write(b, s, n);
}
char *
cmd_recv_string(struct buffer *b)
{
char *s;
size_t n;
buffer_read(b, &n, sizeof n);
if (n == 0)
return (NULL);
s = xmalloc(n);
buffer_read(b, s, n);
s[n - 1] = '\0';
return (s);
}
struct session * struct session *
cmd_current_session(struct cmd_ctx *ctx) cmd_current_session(struct cmd_ctx *ctx)
{ {
struct msg_command_data *data = ctx->msgdata; struct msg_command_data *data = ctx->msgdata;
struct timeval *tv; struct client *c = ctx->cmdclient;
struct session *s, *newest = NULL; struct session *s;
struct sessions ss;
struct winlink *wl;
struct window_pane *wp;
u_int i; u_int i;
int found;
if (ctx->cursession != NULL) if (ctx->curclient != NULL && ctx->curclient->session != NULL)
return (ctx->cursession); return (ctx->curclient->session);
/*
* If the name of the calling client's pty is know, build a list of the
* sessions that contain it and if any choose either the first or the
* newest.
*/
if (c != NULL && c->tty.path != NULL) {
ARRAY_INIT(&ss);
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
continue;
found = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
if (strcmp(wp->tty, c->tty.path) == 0) {
found = 1;
break;
}
}
if (found)
break;
}
if (found)
ARRAY_ADD(&ss, s);
}
s = cmd_newest_session(&ss);
ARRAY_FREE(&ss);
if (s != NULL)
return (s);
}
/* Use the session from the TMUX environment variable. */
if (data != NULL && data->pid != -1) { if (data != NULL && data->pid != -1) {
if (data->pid != getpid()) { if (data->pid != getpid())
ctx->error(ctx, "wrong server: %ld", (long) data->pid);
return (NULL); return (NULL);
} if (data->idx > ARRAY_LENGTH(&sessions))
if (data->idx > ARRAY_LENGTH(&sessions)) {
ctx->error(ctx, "index out of range: %d", data->idx);
return (NULL); return (NULL);
} if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL)
if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) {
ctx->error(ctx, "session doesn't exist: %u", data->idx);
return (NULL); return (NULL);
}
return (s); return (s);
} }
tv = NULL; return (cmd_newest_session(&sessions));
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { }
s = ARRAY_ITEM(&sessions, i);
if (s != NULL && (tv == NULL || timercmp(&s->tv, tv, >))) { /* Find the newest session. */
newest = ARRAY_ITEM(&sessions, i); struct session *
cmd_newest_session(struct sessions *ss)
{
struct session *s, *snewest;
struct timeval *tv = NULL;
u_int i;
snewest = NULL;
for (i = 0; i < ARRAY_LENGTH(ss); i++) {
if ((s = ARRAY_ITEM(ss, i)) == NULL)
continue;
if (tv == NULL || timercmp(&s->tv, tv, >)) {
snewest = s;
tv = &s->tv; tv = &s->tv;
} }
} }
return (newest);
return (snewest);
} }
/* Find the target client or report an error and return NULL. */
struct client * struct client *
cmd_find_client(struct cmd_ctx *ctx, const char *arg) cmd_find_client(struct cmd_ctx *ctx, const char *arg)
{ {
struct client *c; struct client *c;
char *tmparg;
size_t arglen;
/* A NULL argument means the current client. */
if (arg == NULL) if (arg == NULL)
c = ctx->curclient; return (ctx->curclient);
else { tmparg = xstrdup(arg);
if ((c = arg_parse_client(arg)) == NULL) {
if (arg != NULL) /* Trim a single trailing colon if any. */
ctx->error(ctx, "client not found: %s", arg); arglen = strlen(tmparg);
else if (arglen != 0 && tmparg[arglen - 1] == ':')
ctx->error(ctx, "no client found"); tmparg[arglen - 1] = '\0';
}
} /* Find the client, if any. */
c = cmd_lookup_client(tmparg);
/* If no client found, report an error. */
if (c == NULL)
ctx->error(ctx, "client not found: %s", tmparg);
xfree(tmparg);
return (c); return (c);
} }
/*
* Lookup a client by device path. Either of a full match and a match without a
* leading _PATH_DEV ("/dev/") is accepted.
*/
struct client *
cmd_lookup_client(const char *name)
{
struct client *c;
const char *path;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
if ((c = ARRAY_ITEM(&clients, i)) == NULL)
continue;
path = c->tty.path;
/* Check for exact matches. */
if (strcmp(name, path) == 0)
return (c);
/* Check without leading /dev if present. */
if (strncmp(path, _PATH_DEV, (sizeof _PATH_DEV) - 1) != 0)
continue;
if (strcmp(name, path + (sizeof _PATH_DEV) - 1) == 0)
return (c);
}
return (NULL);
}
/* Lookup a session by name. If no session is found, NULL is returned. */
struct session *
cmd_lookup_session(const char *name, int *ambiguous)
{
struct session *s, *sfound;
u_int i;
*ambiguous = 0;
/*
* Look for matches. Session names must be unique so an exact match
* can't be ambigious and can just be returned.
*/
sfound = NULL;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
continue;
/* Check for an exact match and return it if found. */
if (strcmp(name, s->name) == 0)
return (s);
/* Then check for pattern matches. */
if (strncmp(name, s->name, strlen(name)) == 0 ||
fnmatch(name, s->name, 0) == 0) {
if (sfound != NULL) {
*ambiguous = 1;
return (NULL);
}
sfound = s;
}
}
return (sfound);
}
/*
* Lookup a window or return -1 if not found or ambigious. First try as an
* index and if invalid, use fnmatch or leading prefix. Return NULL but fill in
* idx if the window index is a valid number but there is now window with that
* index.
*/
struct winlink *
cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
{
struct winlink *wl, *wlfound;
const char *errstr;
u_int idx;
*ambiguous = 0;
/* First see if this is a valid window index in this session. */
idx = strtonum(name, 0, INT_MAX, &errstr);
if (errstr == NULL) {
if ((wl = winlink_find_by_index(&s->windows, idx)) != NULL)
return (wl);
}
/* Look for exact matches, error if more than one. */
wlfound = NULL;
RB_FOREACH(wl, winlinks, &s->windows) {
if (strcmp(name, wl->window->name) == 0) {
if (wlfound != NULL) {
*ambiguous = 1;
return (NULL);
}
wlfound = wl;
}
}
if (wlfound != NULL)
return (wlfound);
/* Now look for pattern matches, again error if multiple. */
wlfound = NULL;
RB_FOREACH(wl, winlinks, &s->windows) {
if (strncmp(name, wl->window->name, strlen(name)) == 0 ||
fnmatch(name, wl->window->name, 0) == 0) {
if (wlfound != NULL) {
*ambiguous = 1;
return (NULL);
}
wlfound = wl;
}
}
if (wlfound != NULL)
return (wlfound);
return (NULL);
}
/*
* Find a window index - if the window doesn't exist, check if it is a
* potential index and return it anyway.
*/
int
cmd_lookup_index(struct session *s, const char *name, int *ambiguous)
{
struct winlink *wl;
const char *errstr;
u_int idx;
if ((wl = cmd_lookup_window(s, name, ambiguous)) != NULL)
return (wl->idx);
if (*ambiguous)
return (-1);
idx = strtonum(name, 0, INT_MAX, &errstr);
if (errstr == NULL)
return (idx);
return (-1);
}
/* Find the target session or report an error and return NULL. */
struct session * struct session *
cmd_find_session(struct cmd_ctx *ctx, const char *arg) cmd_find_session(struct cmd_ctx *ctx, const char *arg)
{ {
struct session *s; struct session *s;
struct client *c;
char *tmparg;
size_t arglen;
int ambiguous;
/* A NULL argument means the current session. */
if (arg == NULL) if (arg == NULL)
s = cmd_current_session(ctx); return (cmd_current_session(ctx));
else { tmparg = xstrdup(arg);
if ((s = arg_parse_session(arg)) == NULL) {
if (arg != NULL) /* Trim a single trailing colon if any. */
ctx->error(ctx, "session not found: %s", arg); arglen = strlen(tmparg);
else if (arglen != 0 && tmparg[arglen - 1] == ':')
ctx->error(ctx, "no session found"); tmparg[arglen - 1] = '\0';
}
/* Find the session, if any. */
s = cmd_lookup_session(tmparg, &ambiguous);
/* If it doesn't, try to match it as a client. */
if (s == NULL && (c = cmd_lookup_client(tmparg)) != NULL)
s = c->session;
/* If no session found, report an error. */
if (s == NULL) {
if (ambiguous)
ctx->error(ctx, "more than one session: %s", tmparg);
else
ctx->error(ctx, "session not found: %s", tmparg);
} }
xfree(tmparg);
return (s); return (s);
} }
/* Find the target session and window or report an error and return NULL. */
struct winlink * struct winlink *
cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
{ {
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
int idx; const char *winptr;
char *sessptr = NULL;
int ambiguous = 0;
wl = NULL; /*
if (arg_parse_window(arg, &s, &idx) != 0) { * Find the current session. There must always be a current session, if
ctx->error(ctx, "bad window: %s", arg); * it can't be found, report an error.
*/
if ((s = cmd_current_session(ctx)) == NULL) {
ctx->error(ctx, "can't establish current session");
return (NULL); return (NULL);
} }
if (s == NULL)
s = ctx->cursession; /* A NULL argument means the current session and window. */
if (s == NULL) if (arg == NULL) {
s = cmd_current_session(ctx); if (sp != NULL)
if (s == NULL) *sp = s;
return (NULL); return (s->curw);
}
/* Time to look at the argument. If it is empty, that is an error. */
if (*arg == '\0')
goto not_found;
/* Find the separating colon and split into window and session. */
winptr = strchr(arg, ':');
if (winptr == NULL)
goto no_colon;
winptr++; /* skip : */
sessptr = xstrdup(arg);
*strchr(sessptr, ':') = '\0';
/* Try to lookup the session if present. */
if (*sessptr != '\0') {
if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
goto no_session;
}
if (sp != NULL) if (sp != NULL)
*sp = s; *sp = s;
if (idx == -1) /*
* Then work out the window. An empty string is the current window,
* otherwise try to look it up in the session.
*/
if (*winptr == '\0')
wl = s->curw; wl = s->curw;
else else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL)
wl = winlink_find_by_index(&s->windows, idx); goto not_found;
if (wl == NULL)
ctx->error(ctx, "window not found: %s:%d", s->name, idx); if (sessptr != NULL)
xfree(sessptr);
return (wl); return (wl);
no_colon:
/* No colon in the string, first try as a window then as a session. */
if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL) {
if (ambiguous)
goto not_found;
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
goto no_session;
wl = s->curw;
}
if (sp != NULL)
*sp = s;
return (wl);
no_session:
if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", arg);
else
ctx->error(ctx, "session not found: %s", arg);
if (sessptr != NULL)
xfree(sessptr);
return (NULL);
not_found:
if (ambiguous)
ctx->error(ctx, "multiple windows: %s", arg);
else
ctx->error(ctx, "window not found: %s", arg);
if (sessptr != NULL)
xfree(sessptr);
return (NULL);
}
/*
* Find the target session and window index, whether or not it exists in the
* session. Return -2 on error or -1 if no window index is specified. This is
* used when parsing an argument for a window target that may not exist (for
* example if it is going to be created).
*/
int
cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
{
struct session *s;
const char *winptr;
char *sessptr = NULL;
int idx, ambiguous = 0;
/*
* Find the current session. There must always be a current session, if
* it can't be found, report an error.
*/
if ((s = cmd_current_session(ctx)) == NULL) {
ctx->error(ctx, "can't establish current session");
return (-2);
}
/* A NULL argument means the current session and "no window" (-1). */
if (arg == NULL) {
if (sp != NULL)
*sp = s;
return (-1);
}
/* Time to look at the argument. If it is empty, that is an error. */
if (*arg == '\0')
goto not_found;
/* Find the separating colon. If none, assume the current session. */
winptr = strchr(arg, ':');
if (winptr == NULL)
goto no_colon;
winptr++; /* skip : */
sessptr = xstrdup(arg);
*strchr(sessptr, ':') = '\0';
/* Try to lookup the session if present. */
if (sessptr != NULL && *sessptr != '\0') {
if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
goto no_session;
}
if (sp != NULL)
*sp = s;
/*
* Then work out the window. An empty string is a new window otherwise
* try to look it up in the session.
*/
if (*winptr == '\0')
idx = -1;
else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1) {
if (ambiguous)
goto not_found;
ctx->error(ctx, "invalid index: %s", arg);
idx = -2;
}
if (sessptr != NULL)
xfree(sessptr);
return (idx);
no_colon:
/* No colon in the string, first try as a window then as a session. */
if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1) {
if (ambiguous)
goto not_found;
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
goto no_session;
idx = -1;
}
if (sp != NULL)
*sp = s;
return (idx);
no_session:
if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", arg);
else
ctx->error(ctx, "session not found: %s", arg);
if (sessptr != NULL)
xfree(sessptr);
return (-2);
not_found:
if (ambiguous)
ctx->error(ctx, "multiple windows: %s", arg);
else
ctx->error(ctx, "window not found: %s", arg);
if (sessptr != NULL)
xfree(sessptr);
return (-2);
}
/*
* Find the target session, window and pane number or report an error and
* return NULL. The pane number is separated from the session:window by a .,
* such as mysession:mywindow.0.
*/
struct winlink *
cmd_find_pane(struct cmd_ctx *ctx,
const char *arg, struct session **sp, struct window_pane **wpp)
{
struct session *s;
struct winlink *wl;
const char *period;
char *winptr, *paneptr;
const char *errstr;
u_int idx;
/* Get the current session. */
if ((s = cmd_current_session(ctx)) == NULL) {
ctx->error(ctx, "can't establish current session");
return (NULL);
}
if (sp != NULL)
*sp = s;
/* A NULL argument means the current session, window and pane. */
if (arg == NULL) {
*wpp = s->curw->window->active;
return (s->curw);
}
/* Look for a separating period. */
if ((period = strrchr(arg, '.')) == NULL)
goto no_period;
/* Pull out the window part and parse it. */
winptr = xstrdup(arg);
winptr[period - arg] = '\0';
if (*winptr == '\0')
wl = s->curw;
else if ((wl = cmd_find_window(ctx, winptr, sp)) == NULL)
goto error;
/* Find the pane section and look it up. */
paneptr = winptr + (period - arg) + 1;
if (*paneptr == '\0')
*wpp = wl->window->active;
else {
idx = strtonum(paneptr, 0, INT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "pane %s: %s", errstr, paneptr);
goto error;
}
*wpp = window_pane_at_index(wl->window, idx);
if (*wpp == NULL) {
ctx->error(ctx, "no such pane: %u", idx);
goto error;
}
}
xfree(winptr);
return (wl);
no_period:
/* Try as a pane number alone. */
idx = strtonum(arg, 0, INT_MAX, &errstr);
if (errstr != NULL)
goto lookup_window;
/* Try index in the current session and window. */
if ((*wpp = window_pane_at_index(s->curw->window, idx)) == NULL)
goto lookup_window;
return (s->curw);
lookup_window:
/* Try as a window and use the active pane. */
if ((wl = cmd_find_window(ctx, arg, sp)) != NULL)
*wpp = wl->window->active;
return (wl);
error:
xfree(winptr);
return (NULL);
}
/* Replace the first %% or %idx in template by s. */
char *
cmd_template_replace(char *template, const char *s, int idx)
{
char ch;
char *buf, *ptr;
int replaced;
size_t len;
if (strstr(template, "%") == NULL)
return (xstrdup(template));
buf = xmalloc(1);
*buf = '\0';
len = 0;
replaced = 0;
ptr = template;
while (*ptr != '\0') {
switch (ch = *ptr++) {
case '%':
if (*ptr < '1' || *ptr > '9' || *ptr - '0' != idx) {
if (*ptr != '%' || replaced)
break;
replaced = 1;
}
ptr++;
len += strlen(s);
buf = xrealloc(buf, 1, len + 1);
strlcat(buf, s, len + 1);
continue;
}
buf = xrealloc(buf, 1, len + 2);
buf[len++] = ch;
buf[len] = '\0';
}
return (buf);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: colour.c,v 1.5 2009-03-07 10:29:06 nicm Exp $ */ /* $Id: colour.c,v 1.7 2009-09-11 14:13:52 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,13 +18,42 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "tmux.h" #include "tmux.h"
const char * /*
colour_tostring(u_char c) * Colour to string conversion functions. Bit 8 of the colour means it is one
* of the 256 colour palette.
*/
void
colour_set_fg(struct grid_cell *gc, int c)
{ {
if (c & 0x100)
gc->flags |= GRID_FLAG_FG256;
gc->fg = c;
}
void
colour_set_bg(struct grid_cell *gc, int c)
{
if (c & 0x100)
gc->flags |= GRID_FLAG_BG256;
gc->bg = c;
}
const char *
colour_tostring(int c)
{
static char s[32];
if (c & 0x100) {
xsnprintf(s, sizeof s, "colour%u", c & ~0x100);
return (s);
}
switch (c) { switch (c) {
case 0: case 0:
return ("black"); return ("black");
@@ -48,10 +77,19 @@ colour_tostring(u_char c)
return (NULL); return (NULL);
} }
/* String to colour. */
int int
colour_fromstring(const char *s) colour_fromstring(const char *s)
{ {
const char *errstr;
int n;
if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
if (errstr != NULL)
return (-1);
return (n | 0x100);
}
if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0')) if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0'))
return (0); return (0);
if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0')) if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0'))

221
compat.h Normal file
View File

@@ -0,0 +1,221 @@
/* $Id: compat.h,v 1.17 2009-09-03 20:54:39 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HAVE_U_INT
typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
typedef uint64_t u_int64_t;
#endif
#ifndef HAVE_PATHS_H
#define _PATH_BSHELL "/bin/sh"
#define _PATH_TMP "/tmp/"
#define _PATH_DEVNULL "/dev/null"
#define _PATH_TTY "/dev/tty"
#define _PATH_DEV "/dev/"
#endif
#ifdef HAVE_QUEUE_H
#include <sys/queue.h>
#else
#include "compat/queue.h"
#endif
#ifdef HAVE_TREE_H
#include <sys/tree.h>
#else
#include "compat/tree.h"
#endif
#ifdef HAVE_BITSTRING_H
#include <bitstring.h>
#else
#include "compat/bitstring.h"
#endif
#ifdef HAVE_POLL
#include <poll.h>
#else
#define POLLNVAL 0
#define POLLHUP 0
#include "compat/bsd-poll.h"
#endif
#ifdef HAVE_GETOPT
#include <getopt.h>
#endif
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#ifdef HAVE_FORKPTY
#ifdef HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#ifdef HAVE_PTY_H
#include <pty.h>
#endif
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
#endif
#ifdef HAVE_VIS
#include <vis.h>
#else
#include "compat/vis.h"
#endif
#ifndef HAVE_IMSG
#include "compat/imsg.h"
#endif
#ifdef HAVE_LOGIN_CAP
#include <login_cap.h>
#endif
#ifdef HAVE_BROKEN_CMSG_FIRSTHDR
/* Broken on OS X. */
#undef CMSG_FIRSTHDR
#define CMSG_FIRSTHDR(mhdr) \
((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
(struct cmsghdr *)(mhdr)->msg_control : \
(struct cmsghdr *)NULL)
#endif
#ifndef INFTIM
#define INFTIM -1
#endif
#ifndef WAIT_ANY
#define WAIT_ANY -1
#endif
#ifndef SUN_LEN
#define SUN_LEN(sun) (sizeof (sun)->sun_path)
#endif
#ifndef __dead
#define __dead __attribute__ ((__noreturn__))
#endif
#ifndef __packed
#define __packed __attribute__ ((__packed__))
#endif
#ifndef timercmp
#define timercmp(tvp, uvp, cmp) \
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
((tvp)->tv_sec cmp (uvp)->tv_sec))
#endif
#ifndef timeradd
#define timeradd(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
if ((vvp)->tv_usec >= 1000000) { \
(vvp)->tv_sec++; \
(vvp)->tv_usec -= 1000000; \
} \
} while (0)
#endif
#ifndef PASS_MAX
#define PASS_MAX 128
#endif
#ifndef TTY_NAME_MAX
#define TTY_NAME_MAX 32
#endif
#ifndef _PW_BUF_LEN
#define _PW_BUF_LEN 1024
#endif
#ifndef HAVE_BZERO
#define bzero(buf, len) memset((buf), 0, (len));
#endif
#ifndef HAVE_STRCASESTR
/* strcasestr.c */
char *strcasestr(const char *, const char *);
#endif
#ifndef HAVE_STRSEP
/* strsep.c */
char *strsep(char **, const char *);
#endif
#ifndef HAVE_STRTONUM
/* strtonum.c */
long long strtonum(const char *, long long, long long, const char **);
#endif
#ifndef HAVE_STRLCPY
/* strlcpy.c */
size_t strlcpy(char *, const char *, size_t);
#endif
#ifndef HAVE_STRLCAT
/* strlcat.c */
size_t strlcat(char *, const char *, size_t);
#endif
#ifndef HAVE_DAEMON
/* daemon.c */
int daemon(int, int);
#endif
#ifndef HAVE_FORKPTY
/* forkpty.c */
pid_t forkpty(int *, char *, struct termios *, struct winsize *);
#endif
#ifndef HAVE_ASPRINTF
/* asprintf.c */
int asprintf(char **, const char *, ...);
int vasprintf(char **, const char *, va_list);
#endif
#ifndef HAVE_FGETLN
/* fgetln.c */
char *fgetln(FILE *, size_t *);
#endif
#ifndef HAVE_GETOPT
/* getopt.c */
extern int BSDopterr;
extern int BSDoptind;
extern int BSDoptopt;
extern int BSDoptreset;
extern char *BSDoptarg;
int BSDgetopt(int, char *const *, const char *);
#define getopt(ac, av, o) BSDgetopt(ac, av, o)
#define opterr BSDopterr
#define optind BSDoptind
#define optopt BSDoptopt
#define optreset BSDoptreset
#define optarg BSDoptarg
#endif

129
compat/bitstring.h Normal file
View File

@@ -0,0 +1,129 @@
/* $Id: bitstring.h,v 1.1 2009-06-25 17:02:59 nicm Exp $ */
/* $OpenBSD: bitstring.h,v 1.5 2003/06/02 19:34:12 millert Exp $ */
/* $NetBSD: bitstring.h,v 1.5 1997/05/14 15:49:55 pk Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Paul Vixie.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)bitstring.h 8.1 (Berkeley) 7/19/93
*/
#ifndef _BITSTRING_H_
#define _BITSTRING_H_
/* modified for SV/AT and bitstring bugfix by M.R.Murphy, 11oct91
* bitstr_size changed gratuitously, but shorter
* bit_alloc spelling error fixed
* the following were efficient, but didn't work, they've been made to
* work, but are no longer as efficient :-)
* bit_nclear, bit_nset, bit_ffc, bit_ffs
*/
typedef unsigned char bitstr_t;
/* internal macros */
/* byte of the bitstring bit is in */
#define _bit_byte(bit) \
((bit) >> 3)
/* mask for the bit within its byte */
#define _bit_mask(bit) \
(1 << ((bit)&0x7))
/* external macros */
/* bytes in a bitstring of nbits bits */
#define bitstr_size(nbits) \
(((nbits) + 7) >> 3)
/* allocate a bitstring */
#define bit_alloc(nbits) \
(bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t))
/* allocate a bitstring on the stack */
#define bit_decl(name, nbits) \
((name)[bitstr_size(nbits)])
/* is bit N of bitstring name set? */
#define bit_test(name, bit) \
((name)[_bit_byte(bit)] & _bit_mask(bit))
/* set bit N of bitstring name */
#define bit_set(name, bit) \
((name)[_bit_byte(bit)] |= _bit_mask(bit))
/* clear bit N of bitstring name */
#define bit_clear(name, bit) \
((name)[_bit_byte(bit)] &= ~_bit_mask(bit))
/* clear bits start ... stop in bitstring */
#define bit_nclear(name, start, stop) do { \
register bitstr_t *_name = name; \
register int _start = start, _stop = stop; \
while (_start <= _stop) { \
bit_clear(_name, _start); \
_start++; \
} \
} while(0)
/* set bits start ... stop in bitstring */
#define bit_nset(name, start, stop) do { \
register bitstr_t *_name = name; \
register int _start = start, _stop = stop; \
while (_start <= _stop) { \
bit_set(_name, _start); \
_start++; \
} \
} while(0)
/* find first bit clear in name */
#define bit_ffc(name, nbits, value) do { \
register bitstr_t *_name = name; \
register int _bit, _nbits = nbits, _value = -1; \
for (_bit = 0; _bit < _nbits; ++_bit) \
if (!bit_test(_name, _bit)) { \
_value = _bit; \
break; \
} \
*(value) = _value; \
} while(0)
/* find first bit set in name */
#define bit_ffs(name, nbits, value) do { \
register bitstr_t *_name = name; \
register int _bit, _nbits = nbits, _value = -1; \
for (_bit = 0; _bit < _nbits; ++_bit) \
if (bit_test(_name, _bit)) { \
_value = _bit; \
break; \
} \
*(value) = _value; \
} while(0)
#endif /* !_BITSTRING_H_ */

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