mirror of
https://github.com/tmux/tmux.git
synced 2026-03-17 22:18:15 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd1ae9e79b |
89
CHANGES
89
CHANGES
@@ -1,90 +1,3 @@
|
|||||||
CHANGES FROM 1.3 TO 1.4, 27 December 2010
|
|
||||||
|
|
||||||
* Window bell reporting fixed.
|
|
||||||
* Show which pane is active in the list-panes output.
|
|
||||||
* Backoff reworked.
|
|
||||||
* Prevent the server from dying when switching into copy mode when already
|
|
||||||
in a different mode.
|
|
||||||
* Reset running jobs when the status line is enabled or disabled.
|
|
||||||
* Simplify xterm modifier detection.
|
|
||||||
* Avoid crashing in copy mode if the screen size is too small for the
|
|
||||||
indicator.
|
|
||||||
* Flags -n and -p added to switch-client.
|
|
||||||
* Use UTF-8 line drawing characters on UTF-8 terminals, thus fixing some
|
|
||||||
terminals (eg putty) which disable the vt100 ACS mode switching sequences
|
|
||||||
in UTF-8 mode. On terminals without ACS, use ASCII equivalents.
|
|
||||||
* New server option exit-unattached added.
|
|
||||||
* New session option destroy-unattached added.
|
|
||||||
* Fall back on normal session choice method if $TMUX exists but is invalid
|
|
||||||
rather than rejecting.
|
|
||||||
* Mark repeating keys with "(repeat)" in the key list.
|
|
||||||
* When removing a pane, don't change the active pane unless the active pane
|
|
||||||
is actually the one being removed.
|
|
||||||
* New command last-pane added.
|
|
||||||
* AIX fixes.
|
|
||||||
* Flag -a added to unbind-key.
|
|
||||||
* Add XAUTHORITY to update-environment.
|
|
||||||
* More info regarding window and pane flags is now shown in list-*.
|
|
||||||
* If VISUAL or EDITOR contains "vi" configure mode-keys and status-key to vi.
|
|
||||||
* New window option monitor-silence and session option visual-silence added.
|
|
||||||
* In the built-in layouts distribute the panes more evenly.
|
|
||||||
* Set the default value of main-pane-width to 80 instead of 81.
|
|
||||||
* Command-line flag -V added.
|
|
||||||
* Instead of keeping a per-client prompt history make it global.
|
|
||||||
* Fix rectangle copy to behave like emacs (the cursor is not part of the
|
|
||||||
selection on the right edge but on the left it is).
|
|
||||||
* Flag -l added to switch-client.
|
|
||||||
* Retrieve environment variables from the global environment rather than
|
|
||||||
getenv(3), thus allowing them to be updated during the configuration file.
|
|
||||||
* New window options other-pane-{height,width} added.
|
|
||||||
* More minor bugs fixed and manpage improvements.
|
|
||||||
|
|
||||||
CHANGES FROM 1.2 TO 1.3, 18 July 2010
|
|
||||||
|
|
||||||
* New input parser.
|
|
||||||
* Flags to move through panes -UDLR added to select-pane.
|
|
||||||
* Commands up-pane, and down-pane removed, since equivalent behaviour is now
|
|
||||||
available through the target flag (-t:+ and -t:-).
|
|
||||||
* Jump-forward/backward in copy move (based on vi's F, and f commands).
|
|
||||||
* Make paste-buffer accept a pane as a target.
|
|
||||||
* Flag -a added to new-window to insert a window after an existing one, moving
|
|
||||||
windows up if necessary.
|
|
||||||
* Merge more mode into copy mode.
|
|
||||||
* Run job commands explicitly in the global environment (which can be modified
|
|
||||||
with setenv -g), rather than with the environment tmux started with.
|
|
||||||
* Use the machine's hostname as the default title, instead of an empty string.
|
|
||||||
* Prevent double free if the window option remain-on-exit is set.
|
|
||||||
* Key string conversions rewritten.
|
|
||||||
* Mark zombie windows as dead in the choose-window list.
|
|
||||||
* Tiled layout added.
|
|
||||||
* Signal handling reworked.
|
|
||||||
* Reset SIGCHLD after fork to fix problems with some shells.
|
|
||||||
* Select-prompt command removed. Therefore, bound ' to command-prompt -p index
|
|
||||||
"select-window -t:%%" by default.
|
|
||||||
* Catch SIGHUP and terminate if running as a client, thus avoiding clients from
|
|
||||||
being left hanging around when, for instance, a SSH session is disconnected.
|
|
||||||
* Solaris 9 fixes (such as adding compat {get,set}env(3) code).
|
|
||||||
* Accept none instead of default for attributes.
|
|
||||||
* Window options window-status-alert-{alert,bg,fg} added.
|
|
||||||
* Flag -s added to the paste-buffer command to specify a custom separator.
|
|
||||||
* Allow dragging to make a selection in copy mode if the mode-mouse option is
|
|
||||||
set.
|
|
||||||
* Support the mouse scroll wheel.
|
|
||||||
* Make pipe-pane accept special character sequences (eg #I).
|
|
||||||
* Fix problems with window sizing when starting tmux from .xinitrc.
|
|
||||||
* Give tmux sockets (but not the containing folder) group permissions.
|
|
||||||
* Extend the target flags (ie -t) to accept an offset (for example -t:+2), and
|
|
||||||
make it wrap windows, and panes.
|
|
||||||
* New command choose-buffer added.
|
|
||||||
* New server option detach-on-destroy to set what happens to a client when the
|
|
||||||
session it is attached to is destroyed. If on (default), the client is
|
|
||||||
detached. Otherwise, the client is switched to the most recently active of
|
|
||||||
the remaining sessions.
|
|
||||||
* The commands load-buffer, and save-buffer now accept a dash (-) as the file
|
|
||||||
to read from stdin, or write to stdout.
|
|
||||||
* Custom layouts added.
|
|
||||||
* Additional code reduction, bug fixes, and manpage enhancements.
|
|
||||||
|
|
||||||
CHANGES FROM 1.1 TO 1.2, 10 March 2010
|
CHANGES FROM 1.1 TO 1.2, 10 March 2010
|
||||||
|
|
||||||
* Switch to libevent.
|
* Switch to libevent.
|
||||||
@@ -1554,7 +1467,7 @@ The list of older changes is below.
|
|||||||
(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.304 2010-12-27 21:37:42 tcunha Exp $
|
$Id: CHANGES,v 1.302 2010-03-10 15:18:11 tcunha 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
|
||||||
|
|||||||
173
FAQ
173
FAQ
@@ -12,99 +12,29 @@ tmux frequently asked questions
|
|||||||
* and derivatives. *
|
* and derivatives. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
|
|
||||||
* How is tmux different from GNU screen?
|
* How is tmux different from GNU screen? What else does it offer?
|
||||||
|
|
||||||
tmux and GNU screen have many similarities. Some of the main differences I am
|
tmux offers several advantages over screen:
|
||||||
aware of are (bearing in mind I haven't used screen for a few years now):
|
|
||||||
|
|
||||||
- tmux uses a client-server model. Each server has single Unix domain socket in
|
- a clearly-defined client-server model: windows are independent entities which
|
||||||
/tmp and within one server there are multiple sessions which may be attached
|
may be attached simultaneously to multiple sessions and viewed from multiple
|
||||||
to multiple clients (terminals).
|
clients (terminals), as well as moved freely between sessions within the same
|
||||||
|
tmux server;
|
||||||
|
- a consistent, well-documented command interface, with the same syntax
|
||||||
|
whether used interactively, as a key binding, or from the shell;
|
||||||
|
- easily scriptable from the shell;
|
||||||
|
- multiple paste buffers;
|
||||||
|
- choice of vi or emacs key layouts;
|
||||||
|
- an option to limit the window size;
|
||||||
|
- a more usable status line syntax, with the ability to display the first line
|
||||||
|
of output of a specific command;
|
||||||
|
- a cleaner, modern, easily extended, BSD-licensed codebase.
|
||||||
|
|
||||||
This has advantages, notably: windows may be linked simultaneously to
|
There are still a few features screen includes that tmux omits:
|
||||||
multiple sessions; windows may be moved freely between sessions; and a client
|
|
||||||
may be switched between sessions easily (C-b D). There is one major
|
|
||||||
disadvantage: if the server crashes, game over, all sessions die. In
|
|
||||||
practice, however, tmux is quite stable and gets more so as people report any
|
|
||||||
bugs they hit :-).
|
|
||||||
|
|
||||||
This model is different from screen, where typically each new screen instance
|
- builtin serial and telnet support; this is bloat and is unlikely to be added
|
||||||
is independent. tmux supports the same behaviour by using multiple servers
|
to tmux;
|
||||||
with the -L option but it is not typically recommended.
|
- wider platform support, for example IRIX and HP-UX, and for odd terminals.
|
||||||
|
|
||||||
- Different command interfaces. One of the goals of tmux is that the shell
|
|
||||||
should be easily usable as a scripting language - almost all tmux commands
|
|
||||||
can be used from the shell and behave identically whether used from the
|
|
||||||
shell, from a key binding or from the command prompt. Personally I also find
|
|
||||||
tmux's command interface much more consistent and clearer, but this is
|
|
||||||
subjective.
|
|
||||||
|
|
||||||
- tmux calls window names (what you see in the status line) "names", screen
|
|
||||||
calls them "titles".
|
|
||||||
|
|
||||||
- tmux has a multiple paste buffers. Not a major one but comes in handy quite a
|
|
||||||
lot.
|
|
||||||
|
|
||||||
- tmux supports automatically renaming windows to the running application
|
|
||||||
without gross hacks using escape sequences. Its even on by default.
|
|
||||||
|
|
||||||
- tmux has a choice of vi or emacs key layouts. Again, not major, but I use
|
|
||||||
emacs so if tmux did support only one key set it would be emacs and then all
|
|
||||||
the vi users would get humpy. Key bindings may be completely reconfigured in
|
|
||||||
any case.
|
|
||||||
|
|
||||||
- tmux has an option to limit the window size.
|
|
||||||
|
|
||||||
- tmux has search in windows (C-b f).
|
|
||||||
|
|
||||||
- The window split (pane) model is different. tmux has two objects, windows and
|
|
||||||
panes; screen has just windows. This difference has several implications:
|
|
||||||
|
|
||||||
* In screen you can have a window appear in several layouts, in tmux a pane
|
|
||||||
can only be in one window (fixing this is a big todo item but quite
|
|
||||||
invasive).
|
|
||||||
|
|
||||||
* tmux layouts are immutable and do not get changed unless you modify them.
|
|
||||||
|
|
||||||
* In tmux, all panes are closed when you kill a window.
|
|
||||||
|
|
||||||
* tmux panes do not have individual names, titles and so on.
|
|
||||||
|
|
||||||
I think tmux's model is much easier to manage and navigate within a window,
|
|
||||||
but breaking panes off from and joining them to windows is more clumsy.
|
|
||||||
|
|
||||||
tmux also has support for preset pane layouts.
|
|
||||||
|
|
||||||
- tmux's status line syntax is more readable and easier to use. I think it'd be
|
|
||||||
hard for anyone to argue with this. tmux doesn't support running a command
|
|
||||||
constantly and always using the last line of its output, commands must be run
|
|
||||||
again each time.
|
|
||||||
|
|
||||||
- tmux has modern, easily extended code. Again hard to argue screen is better
|
|
||||||
if you have looked at the code.
|
|
||||||
|
|
||||||
- tmux depends on libevent. I don't see this as a disadvantage: libevent is
|
|
||||||
small and portable, and on modern systems with current package management
|
|
||||||
systems dependencies are not an issue. libevent brings advantages in code
|
|
||||||
simplicity and performance.
|
|
||||||
|
|
||||||
- screen allows the window to be bigger than the terminal and can pan around
|
|
||||||
it. tmux limits the size to the largest attached client. This is a big todo
|
|
||||||
item for tmux but it is not trivial.
|
|
||||||
|
|
||||||
- screen has builtin serial and telnet support; this is bloat and is unlikely
|
|
||||||
to be added to tmux.
|
|
||||||
|
|
||||||
- screen has support for updating utmp. Nobody has really come up with a clean,
|
|
||||||
portable way to do this without making tmux setuid or setgid yet.
|
|
||||||
|
|
||||||
- Environment handling is different.
|
|
||||||
|
|
||||||
- tmux tends to be more demanding on the terminal so tends to show up terminal
|
|
||||||
and application bugs which screen does not.
|
|
||||||
|
|
||||||
- screen has wider platform support, for example IRIX and HP-UX, and for odd
|
|
||||||
terminals.
|
|
||||||
|
|
||||||
* I found a bug! What do I do?
|
* I found a bug! What do I do?
|
||||||
|
|
||||||
@@ -237,8 +167,6 @@ the ctrl (bit 5 set, for example ^[[5~ to ^[[5^) modifier in non-xterm(1) mode;
|
|||||||
it may be possible to configure vim to accept these, an example of how to do so
|
it may be possible to configure vim to accept these, an example of how to do so
|
||||||
would be welcome.
|
would be welcome.
|
||||||
|
|
||||||
vim users may also want to set the "ttyfast" option inside tmux.
|
|
||||||
|
|
||||||
* Why doesn't elinks set the window title inside tmux?
|
* Why doesn't elinks set the window title inside tmux?
|
||||||
|
|
||||||
There isn't a way to detect if a terminal supports setting the window title, so
|
There isn't a way to detect if a terminal supports setting the window title, so
|
||||||
@@ -311,65 +239,4 @@ set -g terminal-overrides "xterm*:kLFT5=\eOD:kRIT5=\eOC:kUP5=\eOA:kDN5=\eOB:smkx
|
|||||||
|
|
||||||
Note that this will only work in tmux 1.2 and above.
|
Note that this will only work in tmux 1.2 and above.
|
||||||
|
|
||||||
* How can I blank the tmux window?
|
$Id: FAQ,v 1.36 2010-02-04 21:01:59 nicm Exp $
|
||||||
|
|
||||||
GNU screen has a feature whereby it will blank the screen after a period of
|
|
||||||
inactivity. To do the same thing in tmux, use the lock-command setting, for
|
|
||||||
example (with GNU bash):
|
|
||||||
|
|
||||||
set -g lock-command 'tput civis && read -s -n1'
|
|
||||||
|
|
||||||
This will remove the cursor and tell the shell to quit once a key has been
|
|
||||||
pressed. For zsh, use "read -s -k1".
|
|
||||||
|
|
||||||
In addition, it's possible to have both blanking and locking (for instance via
|
|
||||||
lock(1) or vlock(1)) by using the following:
|
|
||||||
|
|
||||||
bind x set lock-command '/usr/bin/vlock' \; lock-client \; set lock-command 'tput civis && read -s -n1'
|
|
||||||
|
|
||||||
* How can I open a new window in the same directory as the current window?
|
|
||||||
|
|
||||||
One option is to just run "TMUX= tmux" in the window. However, this only works if no
|
|
||||||
command is running, so that you can input the command.
|
|
||||||
|
|
||||||
A workaround is to let tmux know about the current path through an environment
|
|
||||||
variable. To do so, use the following command:
|
|
||||||
|
|
||||||
[ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#I") $PWD
|
|
||||||
|
|
||||||
Which sets TMUXPWD_i (where i is the number of the current window) to the path
|
|
||||||
of the current directory. This command can be added to PS1, for example:
|
|
||||||
|
|
||||||
PS1='$([ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#I") $PWD)\h$ '
|
|
||||||
|
|
||||||
When a new window is created, the shell should be asked to change
|
|
||||||
directory. You can define a new binding (for example, if using GNU bash):
|
|
||||||
|
|
||||||
bind-key C-c run-shell 'tmux neww "cd $(tmux display -p "\$TMUXPWD_#I"); exec bash"'
|
|
||||||
|
|
||||||
This solution will work even if a command is currently running in the terminal,
|
|
||||||
but it will not work from a window that has just been swapped with another
|
|
||||||
because TMUXPWD_i will not be updated after a swap. However, once a new prompt
|
|
||||||
is displayed, TMUXPWD_i is updated properly.
|
|
||||||
|
|
||||||
* tmux doesn't start with "daemon failed"
|
|
||||||
|
|
||||||
tmux shows something similar to this when started:
|
|
||||||
|
|
||||||
fatal: server_start: daemon failed: No such file or directory
|
|
||||||
fatal: main_dispatch: imsg_read failed
|
|
||||||
|
|
||||||
A possible reason is that /dev/null is not a character device or is otherwise
|
|
||||||
inaccessible.
|
|
||||||
|
|
||||||
Check with:
|
|
||||||
|
|
||||||
file /dev/null
|
|
||||||
ls -l /dev/null
|
|
||||||
|
|
||||||
If it is not a character device or has incorrect permissions, it can typically
|
|
||||||
be recreated with:
|
|
||||||
|
|
||||||
cd /dev && rm null && ./MAKEDEV null
|
|
||||||
|
|
||||||
$Id: FAQ,v 1.41 2010-12-15 23:31:30 nicm Exp $
|
|
||||||
|
|||||||
15
GNUmakefile
15
GNUmakefile
@@ -1,4 +1,4 @@
|
|||||||
# $Id: GNUmakefile,v 1.130 2010-12-27 21:32:16 tcunha Exp $
|
# $Id: GNUmakefile,v 1.122 2010-03-10 15:15:33 tcunha Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
#
|
#
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
VERSION= 1.4
|
VERSION= 1.2
|
||||||
|
|
||||||
#FDEBUG= 1
|
#FDEBUG= 1
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ LIBS+=
|
|||||||
|
|
||||||
# Sun CC
|
# Sun CC
|
||||||
ifneq ($(shell ($(CC) -V 2>&1|awk '/Sun C/' || true)), )
|
ifneq ($(shell ($(CC) -V 2>&1|awk '/Sun C/' || true)), )
|
||||||
CFLAGS+= -erroff=E_EMPTY_DECLARATION
|
CFLAGS+=-erroff=E_EMPTY_DECLARATION
|
||||||
FDEBUG=
|
FDEBUG=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -52,12 +52,11 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
PREFIX?= /usr/local
|
PREFIX?= /usr/local
|
||||||
INSTALL?= install
|
INSTALLDIR= install -d
|
||||||
INSTALLDIR= $(INSTALL) -d
|
INSTALLBIN= install -g bin -o root -m 555
|
||||||
INSTALLBIN= $(INSTALL) -m 555
|
INSTALLMAN= install -g bin -o root -m 444
|
||||||
INSTALLMAN= $(INSTALL) -m 444
|
|
||||||
|
|
||||||
SRCS= $(shell echo *.c|LC_ALL=C sed 's|osdep-[a-z0-9]*.c||g')
|
SRCS= $(shell echo *.c|sed 's|osdep-[a-z0-9]*.c||g')
|
||||||
include config.mk
|
include config.mk
|
||||||
OBJS= $(patsubst %.c,%.o,$(SRCS))
|
OBJS= $(patsubst %.c,%.o,$(SRCS))
|
||||||
|
|
||||||
|
|||||||
13
Makefile
13
Makefile
@@ -1,4 +1,4 @@
|
|||||||
# $Id: Makefile,v 1.162 2010-12-27 21:32:16 tcunha Exp $
|
# $Id: Makefile,v 1.155 2010-03-10 15:15:33 tcunha Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
#
|
#
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
.SUFFIXES: .c .o
|
.SUFFIXES: .c .o
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
VERSION= 1.4
|
VERSION= 1.2
|
||||||
|
|
||||||
#FDEBUG= 1
|
#FDEBUG= 1
|
||||||
|
|
||||||
@@ -48,12 +48,11 @@ CFLAGS+= -Wno-pointer-sign
|
|||||||
.endif
|
.endif
|
||||||
|
|
||||||
PREFIX?= /usr/local
|
PREFIX?= /usr/local
|
||||||
INSTALL?= install
|
INSTALLDIR= install -d
|
||||||
INSTALLDIR= ${INSTALL} -d
|
INSTALLBIN= install -g bin -o root -m 555
|
||||||
INSTALLBIN= ${INSTALL} -m 555
|
INSTALLMAN= install -g bin -o root -m 444
|
||||||
INSTALLMAN= ${INSTALL} -m 444
|
|
||||||
|
|
||||||
SRCS!= echo *.c|LC_ALL=C sed 's|osdep-[a-z0-9]*.c||g'
|
SRCS!= echo *.c|sed 's|osdep-[a-z0-9]*.c||g'
|
||||||
.include "config.mk"
|
.include "config.mk"
|
||||||
OBJS= ${SRCS:S/.c/.o/}
|
OBJS= ${SRCS:S/.c/.o/}
|
||||||
|
|
||||||
|
|||||||
25
NOTES
25
NOTES
@@ -25,11 +25,34 @@ windows into several simultaneously displayed panes; and to bind and unbind
|
|||||||
command keys (invoked preceded by a prefix key, by default ctrl-b). Please see
|
command keys (invoked preceded by a prefix key, by default ctrl-b). Please see
|
||||||
the tmux(1) man page for further information.
|
the tmux(1) man page for further information.
|
||||||
|
|
||||||
|
The following is a summary of major features implemented in this version:
|
||||||
|
|
||||||
|
- Basic multiplexing, window switching, attaching and detaching.
|
||||||
|
- Window listing and renaming.
|
||||||
|
- Key binding.
|
||||||
|
- Handling of client terminal resize.
|
||||||
|
- Terminal emulation sufficient to handle most curses applications.
|
||||||
|
- A optional status line (enabled by default).
|
||||||
|
- Window history and copy and paste.
|
||||||
|
- Support for VT100 line drawing characters.
|
||||||
|
- A large command set.
|
||||||
|
- Vertical window splitting and layout.
|
||||||
|
- Automatic server locking on inactivity by running an external command.
|
||||||
|
- A configuration file.
|
||||||
|
- UTF-8 support.
|
||||||
|
|
||||||
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
|
||||||
are missing it may refuse to run, or not behave correctly.
|
are missing it may refuse to run, or not behave correctly.
|
||||||
|
|
||||||
|
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
|
||||||
|
tmux(1) and the FAQ file. As of 0.9, tmux attempts to autodetect a
|
||||||
|
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:
|
||||||
|
|
||||||
- Drop the file in the syntax directory in your runtimepath (such as
|
- Drop the file in the syntax directory in your runtimepath (such as
|
||||||
@@ -63,4 +86,4 @@ start. Please contact me with any queries.
|
|||||||
|
|
||||||
-- Nicholas Marriott <nicm@users.sf.net>
|
-- Nicholas Marriott <nicm@users.sf.net>
|
||||||
|
|
||||||
$Id: NOTES,v 1.54 2010-12-27 21:36:37 tcunha Exp $
|
$Id: NOTES,v 1.53 2010-03-10 15:18:11 tcunha Exp $
|
||||||
|
|||||||
91
TODO
91
TODO
@@ -1,3 +1,4 @@
|
|||||||
|
- window creation/idle time
|
||||||
- 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 eg C-b K K
|
- it would be nice to have multichar commands eg C-b K K
|
||||||
@@ -6,18 +7,27 @@
|
|||||||
bring back detach-session to detach all clients on a session?
|
bring back detach-session to detach all clients on a 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
|
||||||
- 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
|
in $x time (need window creation/use times)
|
||||||
- lift SHRT_MAX limits for history?
|
- lift SHRT_MAX limits for history?
|
||||||
- flags to centre screen in window
|
- flags to centre screen in window
|
||||||
|
- better terminal emulation
|
||||||
- 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?
|
||||||
- next prev word etc in command prompt
|
- next prev word etc in command prompt
|
||||||
|
- many more info() displays for various things
|
||||||
|
- input.c is too complicated. simplify?
|
||||||
- use a better termcap internally instead of screen, perhaps xterm
|
- use a better termcap internally instead of screen, perhaps xterm
|
||||||
|
- fix rxvt cursor fg issue (text under cursor can have non-white fg)
|
||||||
- should be able to move to a hidden pane and it would be moved into view. pane
|
- 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
|
||||||
- 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
|
||||||
|
also quiet, utf8 and maybe other flags?
|
||||||
|
-g is a bit unexpected in conf file
|
||||||
- clear window title on exit
|
- clear window title on exit
|
||||||
|
- the output code (tty.c) could do with optimisation depending on term
|
||||||
|
capabilities
|
||||||
- would be nice to be able to use "--" to mark start of command w/ neww etc
|
- would be nice to be able to use "--" to mark start of command w/ neww etc
|
||||||
to avoid quoting
|
to avoid quoting
|
||||||
- make command sequences more usable: don't require space after ;, handle
|
- make command sequences more usable: don't require space after ;, handle
|
||||||
@@ -28,7 +38,11 @@
|
|||||||
"new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
|
"new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
|
||||||
$HOME/.tmux-session.conf
|
$HOME/.tmux-session.conf
|
||||||
- get it passing all the vttest tests that don't require resizing the terminal
|
- get it passing all the vttest tests that don't require resizing the terminal
|
||||||
|
- esc seq to set window name and title should be documented, and name variant
|
||||||
|
should clear automatic-rename
|
||||||
- way to set socket path from config file
|
- way to set socket path from config file
|
||||||
|
- XXX once env stuff is in, default-path and VISUAL/EDITOR should be picked up
|
||||||
|
when session is started
|
||||||
- what about utmp etc? can tmux update it like screen? setgid?
|
- what about utmp etc? can tmux update it like screen? setgid?
|
||||||
- warts on current naming:
|
- warts on current naming:
|
||||||
- display-time but message-fg/bg/attr
|
- display-time but message-fg/bg/attr
|
||||||
@@ -36,30 +50,48 @@
|
|||||||
- server-info
|
- server-info
|
||||||
- up-pane/down-pane/swap-pane -U/swap-pane -D vs next-*/previous-*
|
- up-pane/down-pane/swap-pane -U/swap-pane -D vs next-*/previous-*
|
||||||
- split-window -> split-pane??
|
- split-window -> split-pane??
|
||||||
|
- tidy up and prioritise todo list ;-)
|
||||||
|
- 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 way for force-width/height to apply to only one pane (how?)
|
||||||
- command to list what is actually running in each window with command line,
|
- command to list what is actually running in each window with command line,
|
||||||
pid (need some adaption of the osdep code)
|
pid (need some adaption of the osdep code)
|
||||||
- support for bce
|
- support for bce
|
||||||
|
- it would be nice if the start/end line keys in copy mode were aware of
|
||||||
|
wrapped lines
|
||||||
- some way to force a screen to use the entire terminal even if it is forced
|
- 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)
|
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
|
-- idea of a "view" onto a window, need base x/y offsets
|
||||||
|
for redraw
|
||||||
- handle resize better in copy mode
|
- handle resize better in copy mode
|
||||||
- way to copy stuff that is off screen due to resize
|
- way to copy stuff that is off screen due to resize
|
||||||
- commands should be able to succeed or fail and have || or && for command
|
- commands should be able to succeed or fail and have || or && for command
|
||||||
lists
|
lists
|
||||||
|
- support the mouse wheel to scroll through history
|
||||||
- some way to KEEP a command running continually and just use its LAST line of
|
- some way to KEEP a command running continually and just use its LAST line of
|
||||||
output
|
output
|
||||||
- bind commands to mouse buttons
|
- bind commands to mouse buttons
|
||||||
- UTF-8 to a non-UTF-8 terminal should not be able to balls up
|
- UTF-8 to a non-UTF-8 terminal should not be able to balls up
|
||||||
the terminal - www/ruby-addressable; make regress
|
the terminal - www/ruby-addressable; make regress
|
||||||
|
- copy mode needs a tidy/cleanup
|
||||||
|
- ability to save history (to buffer?)
|
||||||
- multiple keys could be done with tables, ie have prefixes go and instead
|
- multiple keys could be done with tables, ie have prefixes go and instead
|
||||||
bind -n ^A prefix-table "default"
|
bind -n ^A prefix-table "default"
|
||||||
where prefix-table sets command lookup table and sets prefix flag, then next
|
where prefix-table sets command lookup table and sets prefix flag, then next
|
||||||
key is looked up in that table
|
key is looked up in that table
|
||||||
|
- UTF-8 should be a pointer into a combined string buffer
|
||||||
|
- check irssi (term_charset) works with UTF-8
|
||||||
- support esc-esc to quit in modes
|
- support esc-esc to quit in modes
|
||||||
- fix ctrl+F1-F4 output. to what?
|
- fix ctrl+F1-F4 output. to what?
|
||||||
- look into xterm clearing its selection when scrolling etc
|
- look into xterm clearing its selection when scrolling etc
|
||||||
- better utf8 support: window names, prompt input, message display
|
- better utf8 support:
|
||||||
|
window names
|
||||||
|
prompt input
|
||||||
|
message display
|
||||||
|
copy and paste cursor and wide characters
|
||||||
|
...?
|
||||||
|
- option so that when session is destroyed, attach client to another session
|
||||||
|
rather than exiting
|
||||||
- session history for client and last-session command
|
- session history for client and last-session command
|
||||||
- option to change status line colour when current window is in a mode?
|
- option to change status line colour when current window is in a mode?
|
||||||
- option to move copy mode indicator into status line
|
- option to move copy mode indicator into status line
|
||||||
@@ -67,10 +99,13 @@
|
|||||||
- selection behaviour closer to vi in vi mode
|
- selection behaviour closer to vi in vi mode
|
||||||
- live update: server started with -U connects to server, requests sessions and
|
- live update: server started with -U connects to server, requests sessions and
|
||||||
windows, receives fds
|
windows, receives fds
|
||||||
|
- convert status line history to be server global (anything else?)
|
||||||
|
- something for -t "last window in session" so a session can be used as a stack
|
||||||
- command to show a tree of sessions-windows-panes (active marked with *)
|
- command to show a tree of sessions-windows-panes (active marked with *)
|
||||||
- sort out inheriting config from shell on new sessions/windows:
|
- sort out inheriting config from shell on new sessions/windows:
|
||||||
should pick up default-path/termios/etc from client if possible,
|
should pick up default-path/termios/etc from client if possible,
|
||||||
else leave empty/default
|
else leave empty/default
|
||||||
|
- define custom layouts
|
||||||
- link panes into multiple windows
|
- link panes into multiple windows
|
||||||
- -h option to capture-pane to capture the history as well
|
- -h option to capture-pane to capture the history as well
|
||||||
- bells should be passed between sessions with visual-bell etc
|
- bells should be passed between sessions with visual-bell etc
|
||||||
@@ -80,51 +115,21 @@
|
|||||||
- better session sharing: create-socket command to create socket somewhere (-r
|
- better session sharing: create-socket command to create socket somewhere (-r
|
||||||
flag for readonly)
|
flag for readonly)
|
||||||
- allow buffer to be specified when copying in copy mode
|
- allow buffer to be specified when copying in copy mode
|
||||||
- multiline status line (no?)
|
- multiline status line
|
||||||
- flag for absolute pane size to resize-pane
|
- flag for absolute pane size to resize-pane
|
||||||
- sanity check input to socket
|
- sanity check input to socket
|
||||||
|
- stdin fd should be passed up to parent so load-buffer and others could use it
|
||||||
|
for nonattaching clients
|
||||||
|
- environment should be set up for jobs
|
||||||
- select-buffer command
|
- select-buffer command
|
||||||
|
- fix jobs so they block in config file rather than executing at an arbitrary
|
||||||
|
future point -- need state stored in client so other clients can proceed
|
||||||
|
- rectangle copy:
|
||||||
|
when selecting leftward, cursor should be inside block per emacs
|
||||||
|
key to rotate corner at which cursor is
|
||||||
|
- double C-a should walk back over wrapped lines like C-e
|
||||||
- support title stack, both internally and externally
|
- support title stack, both internally and externally
|
||||||
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
|
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
|
||||||
- copy buffers should be global, limit can be server option, nuke copy-buffer
|
- copy buffers should be global, limit can be server option, nuke copy-buffer
|
||||||
command
|
command
|
||||||
- command to show status line information briefly when it is off
|
- command to show status line information briefly when it is off
|
||||||
- some way to pad # stuff with spaces, #!2T maybe
|
|
||||||
- FreeBSD console problems
|
|
||||||
- a binding to "scroll down and exit at bottom" copy mode
|
|
||||||
- some way to pass keystrokes in copy mode through to underlying window
|
|
||||||
- last window update time and # replacement for it for display-message
|
|
||||||
- find-window across sessions - other ways to make session handling easier?
|
|
||||||
- ' and " should be parsed the same (eg "\e" vs '\e') in config and command
|
|
||||||
prompt?
|
|
||||||
- command to toggle selection not to move it in copy-mode
|
|
||||||
- why are alerts per-winlink? try per window?
|
|
||||||
- audit of escape sequence support vs xterm
|
|
||||||
- support binding keys to mouse (mouse-select-pane -> mouse-keys or something,
|
|
||||||
mouse click == select-pane -t %%, mouse scroll up == copy-mode)
|
|
||||||
- something for -t "last window in session" so a session can be used as a stack
|
|
||||||
- synchronous commands - client sends cmd and blocks, neww/splitw saves client
|
|
||||||
ptr then when program inside died, sends MSG_SOMETHING with wait status to
|
|
||||||
client
|
|
||||||
- documentation improvements - rlpowell's tutorial - build instructions
|
|
||||||
- better configure? with-libevent
|
|
||||||
- bind commands to key sequences?
|
|
||||||
- monitor, bell etc should monitor /all/ panes in the window not just one
|
|
||||||
- a history of commands that can be reversed (reverse member of each command,
|
|
||||||
and a buffer) info() when changing to same window
|
|
||||||
- don't pass UTF-8 through vis for titles
|
|
||||||
- clearing screen should push lines into history
|
|
||||||
- add a unique ever-increasing pane id to each pane, export it in $TMUX_PANE
|
|
||||||
(as %1, %2 etc) and allow it to be used as a target
|
|
||||||
- way to add dest for break-pane; maybe some easier way to unbreak-pane
|
|
||||||
- case insensitive searching
|
|
||||||
- dynamically generated jobs (eg "date ...") do not work well because
|
|
||||||
their entries are never collected, should either store status jobs in
|
|
||||||
a different tree or flush all unused persist jobs every update rather
|
|
||||||
than just updating them
|
|
||||||
- pane-index option like base-index
|
|
||||||
- option to move status line to top
|
|
||||||
- support "xterm2" mouse mode
|
|
||||||
- respawn-pane command
|
|
||||||
- configurable borders and empty space filler for when panes < window?
|
|
||||||
|
|
||||||
|
|||||||
4
array.h
4
array.h
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: array.h,v 1.11 2010-06-06 00:27:08 tcunha Exp $ */
|
/* $Id: array.h,v 1.10 2010-02-08 18:29:32 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ARRAY_EMPTY(a) (((void *) (a)) == NULL || (a)->num == 0)
|
#define ARRAY_EMPTY(a) ((a) == NULL || (a)->num == 0)
|
||||||
#define ARRAY_LENGTH(a) ((a)->num)
|
#define ARRAY_LENGTH(a) ((a)->num)
|
||||||
#define ARRAY_DATA(a) ((a)->list)
|
#define ARRAY_DATA(a) ((a)->list)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: attributes.c,v 1.4 2010-06-05 23:54:51 tcunha Exp $ */
|
/* $Id: attributes.c,v 1.3 2009-11-28 14:46:23 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
|
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
|
||||||
@@ -28,7 +28,7 @@ attributes_tostring(u_char attr)
|
|||||||
static char buf[128];
|
static char buf[128];
|
||||||
|
|
||||||
if (attr == 0)
|
if (attr == 0)
|
||||||
return ("none");
|
return ("default");
|
||||||
|
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
if (attr & GRID_ATTR_BRIGHT)
|
if (attr & GRID_ATTR_BRIGHT)
|
||||||
@@ -63,7 +63,7 @@ attributes_fromstring(const char *str)
|
|||||||
if (strchr(delimiters, str[strlen(str) - 1]) != NULL)
|
if (strchr(delimiters, str[strlen(str) - 1]) != NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (strcasecmp(str, "default") == 0 || strcasecmp(str, "none") == 0)
|
if (strcasecmp(str, "default") == 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
attr = 0;
|
attr = 0;
|
||||||
|
|||||||
4
cfg.c
4
cfg.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cfg.c,v 1.27 2010-06-06 00:04:18 tcunha Exp $ */
|
/* $Id: cfg.c,v 1.26 2010-02-08 18:29:32 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -69,7 +69,7 @@ cfg_add_cause(struct causelist *causes, const char *fmt, ...)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Load configuration file. Returns -1 for an error with a list of messages in
|
* Load configuration file. Returns -1 for an error with a list of messages in
|
||||||
* causes. Note that causes must be initialised by the caller!
|
* causes. Note that causes and ncauses must be initialised by the caller!
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
|
load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
|
||||||
|
|||||||
369
client.c
369
client.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: client.c,v 1.100 2010-10-24 19:54:41 nicm Exp $ */
|
/* $Id: client.c,v 1.90 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@@ -36,180 +38,93 @@ struct imsgbuf client_ibuf;
|
|||||||
struct event client_event;
|
struct event client_event;
|
||||||
const char *client_exitmsg;
|
const char *client_exitmsg;
|
||||||
int client_exitval;
|
int client_exitval;
|
||||||
int client_attached;
|
|
||||||
|
|
||||||
int client_connect(char *, int);
|
|
||||||
void client_send_identify(int);
|
void client_send_identify(int);
|
||||||
void client_send_environ(void);
|
void client_send_environ(void);
|
||||||
void client_write_server(enum msgtype, void *, size_t);
|
void client_write_server(enum msgtype, void *, size_t);
|
||||||
void client_update_event(void);
|
void client_update_event(void);
|
||||||
void client_signal(int, short, void *);
|
void client_signal(int, short, void *);
|
||||||
void client_callback(int, short, void *);
|
void client_callback(int, short, void *);
|
||||||
int client_dispatch_attached(void);
|
int client_dispatch(void);
|
||||||
int client_dispatch_wait(void *);
|
|
||||||
|
|
||||||
/* Connect client to server. */
|
struct imsgbuf *
|
||||||
int
|
client_init(char *path, int cmdflags, int flags)
|
||||||
client_connect(char *path, int start_server)
|
|
||||||
{
|
{
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
size_t size;
|
size_t size;
|
||||||
int fd, mode;
|
int fd, mode;
|
||||||
|
#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
|
||||||
|
|
||||||
memset(&sa, 0, sizeof sa);
|
memset(&sa, 0, sizeof sa);
|
||||||
sa.sun_family = AF_UNIX;
|
sa.sun_family = AF_UNIX;
|
||||||
size = strlcpy(sa.sun_path, path, sizeof sa.sun_path);
|
size = strlcpy(sa.sun_path, path, sizeof sa.sun_path);
|
||||||
if (size >= sizeof sa.sun_path) {
|
if (size >= sizeof sa.sun_path) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return (-1);
|
goto not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||||
fatal("socket failed");
|
fatal("socket failed");
|
||||||
|
|
||||||
if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
|
if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
|
||||||
if (!start_server)
|
if (!(cmdflags & CMD_STARTSERVER))
|
||||||
goto failed;
|
goto not_found;
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case ECONNREFUSED:
|
case ECONNREFUSED:
|
||||||
if (unlink(path) != 0)
|
if (unlink(path) != 0)
|
||||||
goto failed;
|
goto not_found;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
if ((fd = server_start()) == -1)
|
if ((fd = server_start(path)) == -1)
|
||||||
goto failed;
|
goto start_failed;
|
||||||
break;
|
goto server_started;
|
||||||
default:
|
|
||||||
goto failed;
|
|
||||||
}
|
}
|
||||||
|
goto not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server_started:
|
||||||
if ((mode = fcntl(fd, F_GETFL)) == -1)
|
if ((mode = fcntl(fd, F_GETFL)) == -1)
|
||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
return (fd);
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
fatal("fcntl failed");
|
||||||
failed:
|
|
||||||
close(fd);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Client main loop. */
|
|
||||||
int
|
|
||||||
client_main(int argc, char **argv, int flags)
|
|
||||||
{
|
|
||||||
struct cmd *cmd;
|
|
||||||
struct cmd_list *cmdlist;
|
|
||||||
struct msg_command_data cmddata;
|
|
||||||
int cmdflags, fd;
|
|
||||||
enum msgtype msg;
|
|
||||||
char *cause;
|
|
||||||
|
|
||||||
/* Set up the initial command. */
|
|
||||||
cmdflags = 0;
|
|
||||||
if (shell_cmd != NULL) {
|
|
||||||
msg = MSG_SHELL;
|
|
||||||
cmdflags = CMD_STARTSERVER;
|
|
||||||
} else if (argc == 0) {
|
|
||||||
msg = MSG_COMMAND;
|
|
||||||
cmdflags = CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST;
|
|
||||||
} else {
|
|
||||||
msg = MSG_COMMAND;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It sucks parsing the command string twice (in client and
|
|
||||||
* later in server) but it is necessary to get the start server
|
|
||||||
* flag.
|
|
||||||
*/
|
|
||||||
if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
|
|
||||||
log_warnx("%s", cause);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
cmdflags &= ~CMD_STARTSERVER;
|
|
||||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
|
||||||
if (cmd->entry->flags & CMD_STARTSERVER)
|
|
||||||
cmdflags |= CMD_STARTSERVER;
|
|
||||||
if (cmd->entry->flags & CMD_SENDENVIRON)
|
|
||||||
cmdflags |= CMD_SENDENVIRON;
|
|
||||||
if (cmd->entry->flags & CMD_CANTNEST)
|
|
||||||
cmdflags |= CMD_CANTNEST;
|
|
||||||
}
|
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if this could be a nested session, if the command can't nest:
|
|
||||||
* if the socket path matches $TMUX, this is probably the same server.
|
|
||||||
*/
|
|
||||||
if (shell_cmd == NULL && environ_path != NULL &&
|
|
||||||
cmdflags & CMD_CANTNEST && strcmp(socket_path, environ_path) == 0) {
|
|
||||||
log_warnx("sessions should be nested with care. "
|
|
||||||
"unset $TMUX to force.");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialise the client socket and start the server. */
|
|
||||||
fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER);
|
|
||||||
if (fd == -1) {
|
|
||||||
log_warn("failed to connect to server");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set process title, log and signals now this is the client. */
|
|
||||||
#ifdef HAVE_SETPROCTITLE
|
|
||||||
setproctitle("client (%s)", socket_path);
|
|
||||||
#endif
|
|
||||||
logfile("client");
|
|
||||||
|
|
||||||
/* Create imsg. */
|
|
||||||
imsg_init(&client_ibuf, fd);
|
imsg_init(&client_ibuf, fd);
|
||||||
event_set(&client_event, fd, EV_READ, client_callback, shell_cmd);
|
|
||||||
|
|
||||||
/* Establish signal handlers. */
|
|
||||||
set_signals(client_signal);
|
|
||||||
|
|
||||||
/* Send initial environment. */
|
|
||||||
if (cmdflags & CMD_SENDENVIRON)
|
if (cmdflags & CMD_SENDENVIRON)
|
||||||
client_send_environ();
|
client_send_environ();
|
||||||
client_send_identify(flags);
|
if (isatty(STDIN_FILENO))
|
||||||
|
client_send_identify(flags);
|
||||||
|
|
||||||
/* Send first command. */
|
return (&client_ibuf);
|
||||||
if (msg == MSG_COMMAND) {
|
|
||||||
/* Fill in command line arguments. */
|
|
||||||
cmddata.pid = environ_pid;
|
|
||||||
cmddata.idx = environ_idx;
|
|
||||||
|
|
||||||
/* Prepare command for server. */
|
start_failed:
|
||||||
cmddata.argc = argc;
|
log_warnx("server failed to start");
|
||||||
if (cmd_pack_argv(
|
return (NULL);
|
||||||
argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
|
|
||||||
log_warnx("command too long");
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
client_write_server(msg, &cmddata, sizeof cmddata);
|
not_found:
|
||||||
} else if (msg == MSG_SHELL)
|
log_warn("server not found");
|
||||||
client_write_server(msg, NULL, 0);
|
return (NULL);
|
||||||
|
|
||||||
/* Set the event and dispatch. */
|
|
||||||
client_update_event();
|
|
||||||
event_dispatch();
|
|
||||||
|
|
||||||
/* Print the exit message, if any, and exit. */
|
|
||||||
if (client_attached && client_exitmsg != NULL && !login_shell)
|
|
||||||
printf("[%s]\n", client_exitmsg);
|
|
||||||
return (client_exitval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send identify message to server with the file descriptors. */
|
|
||||||
void
|
void
|
||||||
client_send_identify(int flags)
|
client_send_identify(int flags)
|
||||||
{
|
{
|
||||||
struct msg_identify_data data;
|
struct msg_identify_data data;
|
||||||
|
struct winsize ws;
|
||||||
char *term;
|
char *term;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
|
||||||
|
fatal("ioctl(TIOCGWINSZ)");
|
||||||
data.flags = flags;
|
data.flags = flags;
|
||||||
|
|
||||||
if (getcwd(data.cwd, sizeof data.cwd) == NULL)
|
if (getcwd(data.cwd, sizeof data.cwd) == NULL)
|
||||||
@@ -224,19 +139,8 @@ client_send_identify(int flags)
|
|||||||
fatal("dup failed");
|
fatal("dup failed");
|
||||||
imsg_compose(&client_ibuf,
|
imsg_compose(&client_ibuf,
|
||||||
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
|
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
|
||||||
|
|
||||||
if ((fd = dup(STDOUT_FILENO)) == -1)
|
|
||||||
fatal("dup failed");
|
|
||||||
imsg_compose(&client_ibuf,
|
|
||||||
MSG_STDOUT, PROTOCOL_VERSION, -1, fd, NULL, 0);
|
|
||||||
|
|
||||||
if ((fd = dup(STDERR_FILENO)) == -1)
|
|
||||||
fatal("dup failed");
|
|
||||||
imsg_compose(&client_ibuf,
|
|
||||||
MSG_STDERR, PROTOCOL_VERSION, -1, fd, NULL, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Forward entire environment to server. */
|
|
||||||
void
|
void
|
||||||
client_send_environ(void)
|
client_send_environ(void)
|
||||||
{
|
{
|
||||||
@@ -250,14 +154,12 @@ client_send_environ(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a message to the server without a file descriptor. */
|
|
||||||
void
|
void
|
||||||
client_write_server(enum msgtype type, void *buf, size_t len)
|
client_write_server(enum msgtype type, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
|
imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update client event based on whether it needs to read or read and write. */
|
|
||||||
void
|
void
|
||||||
client_update_event(void)
|
client_update_event(void)
|
||||||
{
|
{
|
||||||
@@ -267,74 +169,102 @@ client_update_event(void)
|
|||||||
events = EV_READ;
|
events = EV_READ;
|
||||||
if (client_ibuf.w.queued > 0)
|
if (client_ibuf.w.queued > 0)
|
||||||
events |= EV_WRITE;
|
events |= EV_WRITE;
|
||||||
event_set(
|
event_set(&client_event, client_ibuf.fd, events, client_callback, NULL);
|
||||||
&client_event, client_ibuf.fd, events, client_callback, shell_cmd);
|
|
||||||
event_add(&client_event, NULL);
|
event_add(&client_event, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback to handle signals in the client. */
|
__dead void
|
||||||
|
client_main(void)
|
||||||
|
{
|
||||||
|
struct event ev_sigcont, ev_sigterm, ev_sigwinch;
|
||||||
|
struct sigaction sigact;
|
||||||
|
|
||||||
|
logfile("client");
|
||||||
|
|
||||||
|
/* Note: event_init() has already been called. */
|
||||||
|
|
||||||
|
/* Set up signals. */
|
||||||
|
memset(&sigact, 0, sizeof sigact);
|
||||||
|
sigemptyset(&sigact.sa_mask);
|
||||||
|
sigact.sa_flags = SA_RESTART;
|
||||||
|
sigact.sa_handler = SIG_IGN;
|
||||||
|
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGUSR1, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
|
||||||
|
signal_set(&ev_sigcont, SIGCONT, client_signal, NULL);
|
||||||
|
signal_add(&ev_sigcont, NULL);
|
||||||
|
signal_set(&ev_sigterm, SIGTERM, client_signal, NULL);
|
||||||
|
signal_add(&ev_sigterm, NULL);
|
||||||
|
signal_set(&ev_sigwinch, SIGWINCH, client_signal, NULL);
|
||||||
|
signal_add(&ev_sigwinch, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* imsg_read in the first client poll loop (before the terminal has
|
||||||
|
* been initialised) may have read messages into the buffer after the
|
||||||
|
* MSG_READY switched to here. Process anything outstanding now to
|
||||||
|
* avoid hanging waiting for messages that have already arrived.
|
||||||
|
*/
|
||||||
|
if (client_dispatch() != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Set the event and dispatch. */
|
||||||
|
client_update_event();
|
||||||
|
event_dispatch();
|
||||||
|
|
||||||
|
out:
|
||||||
|
/* Print the exit message, if any, and exit. */
|
||||||
|
if (client_exitmsg != NULL && !login_shell)
|
||||||
|
printf("[%s]\n", client_exitmsg);
|
||||||
|
exit(client_exitval);
|
||||||
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
client_signal(int sig, unused short events, unused void *data)
|
client_signal(int sig, unused short events, unused void *data)
|
||||||
{
|
{
|
||||||
struct sigaction sigact;
|
struct sigaction sigact;
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!client_attached) {
|
switch (sig) {
|
||||||
switch (sig) {
|
case SIGTERM:
|
||||||
case SIGCHLD:
|
client_exitmsg = "terminated";
|
||||||
waitpid(WAIT_ANY, &status, WNOHANG);
|
client_exitval = 1;
|
||||||
break;
|
client_write_server(MSG_EXITING, NULL, 0);
|
||||||
case SIGTERM:
|
break;
|
||||||
event_loopexit(NULL);
|
case SIGWINCH:
|
||||||
break;
|
client_write_server(MSG_RESIZE, NULL, 0);
|
||||||
}
|
break;
|
||||||
} else {
|
case SIGCONT:
|
||||||
switch (sig) {
|
memset(&sigact, 0, sizeof sigact);
|
||||||
case SIGHUP:
|
sigemptyset(&sigact.sa_mask);
|
||||||
client_exitmsg = "lost tty";
|
sigact.sa_flags = SA_RESTART;
|
||||||
client_exitval = 1;
|
sigact.sa_handler = SIG_IGN;
|
||||||
client_write_server(MSG_EXITING, NULL, 0);
|
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||||
break;
|
fatal("sigaction failed");
|
||||||
case SIGTERM:
|
client_write_server(MSG_WAKEUP, NULL, 0);
|
||||||
client_exitmsg = "terminated";
|
break;
|
||||||
client_exitval = 1;
|
|
||||||
client_write_server(MSG_EXITING, NULL, 0);
|
|
||||||
break;
|
|
||||||
case SIGWINCH:
|
|
||||||
client_write_server(MSG_RESIZE, NULL, 0);
|
|
||||||
break;
|
|
||||||
case SIGCONT:
|
|
||||||
memset(&sigact, 0, sizeof sigact);
|
|
||||||
sigemptyset(&sigact.sa_mask);
|
|
||||||
sigact.sa_flags = SA_RESTART;
|
|
||||||
sigact.sa_handler = SIG_IGN;
|
|
||||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
client_write_server(MSG_WAKEUP, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client_update_event();
|
client_update_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for client imsg read events. */
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
client_callback(unused int fd, short events, void *data)
|
client_callback(unused int fd, short events, unused void *data)
|
||||||
{
|
{
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
int retval;
|
|
||||||
|
|
||||||
if (events & EV_READ) {
|
if (events & EV_READ) {
|
||||||
if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
|
if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
|
||||||
goto lost_server;
|
goto lost_server;
|
||||||
if (client_attached)
|
if (client_dispatch() != 0) {
|
||||||
retval = client_dispatch_attached();
|
|
||||||
else
|
|
||||||
retval = client_dispatch_wait(data);
|
|
||||||
if (retval != 0) {
|
|
||||||
event_loopexit(NULL);
|
event_loopexit(NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -354,76 +284,8 @@ lost_server:
|
|||||||
event_loopexit(NULL);
|
event_loopexit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dispatch imsgs when in wait state (before MSG_READY). */
|
|
||||||
int
|
int
|
||||||
client_dispatch_wait(void *data)
|
client_dispatch(void)
|
||||||
{
|
|
||||||
struct imsg imsg;
|
|
||||||
ssize_t n, datalen;
|
|
||||||
struct msg_shell_data shelldata;
|
|
||||||
struct msg_exit_data exitdata;
|
|
||||||
const char *shellcmd = data;
|
|
||||||
|
|
||||||
if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
|
|
||||||
fatalx("imsg_read failed");
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if ((n = imsg_get(&client_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_EXIT:
|
|
||||||
case MSG_SHUTDOWN:
|
|
||||||
if (datalen != sizeof exitdata) {
|
|
||||||
if (datalen != 0)
|
|
||||||
fatalx("bad MSG_EXIT size");
|
|
||||||
} else {
|
|
||||||
memcpy(&exitdata, imsg.data, sizeof exitdata);
|
|
||||||
client_exitval = exitdata.retcode;
|
|
||||||
}
|
|
||||||
imsg_free(&imsg);
|
|
||||||
return (-1);
|
|
||||||
case MSG_READY:
|
|
||||||
if (datalen != 0)
|
|
||||||
fatalx("bad MSG_READY size");
|
|
||||||
|
|
||||||
client_attached = 1;
|
|
||||||
break;
|
|
||||||
case MSG_VERSION:
|
|
||||||
if (datalen != 0)
|
|
||||||
fatalx("bad MSG_VERSION size");
|
|
||||||
|
|
||||||
log_warnx("protocol version mismatch (client %u, "
|
|
||||||
"server %u)", PROTOCOL_VERSION, imsg.hdr.peerid);
|
|
||||||
client_exitval = 1;
|
|
||||||
|
|
||||||
imsg_free(&imsg);
|
|
||||||
return (-1);
|
|
||||||
case MSG_SHELL:
|
|
||||||
if (datalen != sizeof shelldata)
|
|
||||||
fatalx("bad MSG_SHELL size");
|
|
||||||
memcpy(&shelldata, imsg.data, sizeof shelldata);
|
|
||||||
shelldata.shell[(sizeof shelldata.shell) - 1] = '\0';
|
|
||||||
|
|
||||||
clear_signals(0);
|
|
||||||
|
|
||||||
shell_exec(shelldata.shell, shellcmd);
|
|
||||||
/* NOTREACHED */
|
|
||||||
default:
|
|
||||||
fatalx("unexpected message");
|
|
||||||
}
|
|
||||||
|
|
||||||
imsg_free(&imsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dispatch imsgs in attached state (after MSG_READY). */
|
|
||||||
/* ARGSUSED */
|
|
||||||
int
|
|
||||||
client_dispatch_attached(void)
|
|
||||||
{
|
{
|
||||||
struct imsg imsg;
|
struct imsg imsg;
|
||||||
struct msg_lock_data lockdata;
|
struct msg_lock_data lockdata;
|
||||||
@@ -447,8 +309,7 @@ client_dispatch_attached(void)
|
|||||||
client_exitmsg = "detached";
|
client_exitmsg = "detached";
|
||||||
break;
|
break;
|
||||||
case MSG_EXIT:
|
case MSG_EXIT:
|
||||||
if (datalen != 0 &&
|
if (datalen != 0)
|
||||||
datalen != sizeof (struct msg_exit_data))
|
|
||||||
fatalx("bad MSG_EXIT size");
|
fatalx("bad MSG_EXIT size");
|
||||||
|
|
||||||
client_write_server(MSG_EXITING, NULL, 0);
|
client_write_server(MSG_EXITING, NULL, 0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-attach-session.c,v 1.37 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: cmd-attach-session.c,v 1.36 2010-02-08 18:27:34 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -47,7 +47,7 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
char *overrides, *cause;
|
char *overrides, *cause;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (RB_EMPTY(&sessions)) {
|
if (ARRAY_LENGTH(&sessions) == 0) {
|
||||||
ctx->error(ctx, "no sessions");
|
ctx->error(ctx, "no sessions");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-bind-key.c,v 1.29 2010-07-02 02:43:01 tcunha Exp $ */
|
/* $Id: cmd-bind-key.c,v 1.28 2010-01-25 17:12:44 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -130,7 +130,7 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
|
|||||||
return (cmd_bind_key_table(self, ctx));
|
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->references++;
|
data->cmdlist = NULL; /* avoid free */
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -192,17 +192,8 @@ cmd_bind_key_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);
|
||||||
|
|
||||||
if (off < len && data->command_key)
|
|
||||||
off += xsnprintf(buf + off, len - off, " -c");
|
|
||||||
if (off < len && !(data->key & KEYC_PREFIX))
|
|
||||||
off += xsnprintf(buf + off, len - off, " -n");
|
|
||||||
if (off < len && data->can_repeat)
|
|
||||||
off += xsnprintf(buf + off, len - off, " -r");
|
|
||||||
if (off < len && data->tablename != NULL)
|
|
||||||
off += cmd_prarg(buf + off, len - off, " -t ", data->tablename);
|
|
||||||
if (off < len) {
|
if (off < len) {
|
||||||
skey = key_string_lookup_key(data->key & ~KEYC_PREFIX);
|
skey = key_string_lookup_key(data->key);
|
||||||
off += xsnprintf(buf + off, len - off, " %s ", skey);
|
off += xsnprintf(buf + off, len - off, " %s ", skey);
|
||||||
}
|
}
|
||||||
if (off < len)
|
if (off < len)
|
||||||
|
|||||||
@@ -1,146 +0,0 @@
|
|||||||
/* $Id: cmd-choose-buffer.c,v 1.1 2010-06-22 23:35:20 tcunha Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enter choice mode to choose a buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int cmd_choose_buffer_exec(struct cmd *, struct cmd_ctx *);
|
|
||||||
|
|
||||||
void cmd_choose_buffer_callback(void *, int);
|
|
||||||
void cmd_choose_buffer_free(void *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_choose_buffer_entry = {
|
|
||||||
"choose-buffer", NULL,
|
|
||||||
CMD_TARGET_WINDOW_USAGE " [template]",
|
|
||||||
CMD_ARG01, "",
|
|
||||||
cmd_target_init,
|
|
||||||
cmd_target_parse,
|
|
||||||
cmd_choose_buffer_exec,
|
|
||||||
cmd_target_free,
|
|
||||||
cmd_target_print
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cmd_choose_buffer_data {
|
|
||||||
struct client *client;
|
|
||||||
char *template;
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct cmd_target_data *data = self->data;
|
|
||||||
struct cmd_choose_buffer_data *cdata;
|
|
||||||
struct session *s;
|
|
||||||
struct winlink *wl;
|
|
||||||
struct paste_buffer *pb;
|
|
||||||
u_int idx;
|
|
||||||
char *tmp;
|
|
||||||
|
|
||||||
if (ctx->curclient == NULL) {
|
|
||||||
ctx->error(ctx, "must be run interactively");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
s = ctx->curclient->session;
|
|
||||||
|
|
||||||
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
if (paste_get_top(&s->buffers) == NULL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
idx = 0;
|
|
||||||
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) {
|
|
||||||
tmp = paste_print(pb, 50);
|
|
||||||
window_choose_add(wl->window->active, idx - 1,
|
|
||||||
"%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);
|
|
||||||
xfree(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
cdata = xmalloc(sizeof *cdata);
|
|
||||||
if (data->arg != NULL)
|
|
||||||
cdata->template = xstrdup(data->arg);
|
|
||||||
else
|
|
||||||
cdata->template = xstrdup("paste-buffer -b '%%'");
|
|
||||||
cdata->client = ctx->curclient;
|
|
||||||
cdata->client->references++;
|
|
||||||
|
|
||||||
window_choose_ready(wl->window->active,
|
|
||||||
0, cmd_choose_buffer_callback, cmd_choose_buffer_free, cdata);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
cmd_choose_buffer_callback(void *data, int idx)
|
|
||||||
{
|
|
||||||
struct cmd_choose_buffer_data *cdata = data;
|
|
||||||
struct cmd_list *cmdlist;
|
|
||||||
struct cmd_ctx ctx;
|
|
||||||
char *template, *cause, tmp[16];
|
|
||||||
|
|
||||||
if (idx == -1)
|
|
||||||
return;
|
|
||||||
if (cdata->client->flags & CLIENT_DEAD)
|
|
||||||
return;
|
|
||||||
|
|
||||||
xsnprintf(tmp, sizeof tmp, "%u", idx);
|
|
||||||
template = cmd_template_replace(cdata->template, tmp, 1);
|
|
||||||
|
|
||||||
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
|
|
||||||
if (cause != NULL) {
|
|
||||||
*cause = toupper((u_char) *cause);
|
|
||||||
status_message_set(cdata->client, "%s", cause);
|
|
||||||
xfree(cause);
|
|
||||||
}
|
|
||||||
xfree(template);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xfree(template);
|
|
||||||
|
|
||||||
ctx.msgdata = NULL;
|
|
||||||
ctx.curclient = cdata->client;
|
|
||||||
|
|
||||||
ctx.error = key_bindings_error;
|
|
||||||
ctx.print = key_bindings_print;
|
|
||||||
ctx.info = key_bindings_info;
|
|
||||||
|
|
||||||
ctx.cmdclient = NULL;
|
|
||||||
|
|
||||||
cmd_list_exec(cmdlist, &ctx);
|
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
cmd_choose_buffer_free(void *data)
|
|
||||||
{
|
|
||||||
struct cmd_choose_buffer_data *cdata = data;
|
|
||||||
|
|
||||||
cdata->client->references--;
|
|
||||||
xfree(cdata->template);
|
|
||||||
xfree(cdata);
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-choose-session.c,v 1.17 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: cmd-choose-session.c,v 1.15 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -55,7 +55,7 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct session_group *sg;
|
struct session_group *sg;
|
||||||
u_int idx, sgidx, cur;
|
u_int i, idx, cur;
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
|
|
||||||
if (ctx->curclient == NULL) {
|
if (ctx->curclient == NULL) {
|
||||||
@@ -70,7 +70,10 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
cur = idx = 0;
|
cur = idx = 0;
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
|
if (s == NULL)
|
||||||
|
continue;
|
||||||
if (s == ctx->curclient->session)
|
if (s == ctx->curclient->session)
|
||||||
cur = idx;
|
cur = idx;
|
||||||
idx++;
|
idx++;
|
||||||
@@ -79,11 +82,11 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if (sg == NULL)
|
if (sg == NULL)
|
||||||
*tmp = '\0';
|
*tmp = '\0';
|
||||||
else {
|
else {
|
||||||
sgidx = session_group_index(sg);
|
idx = session_group_index(sg);
|
||||||
xsnprintf(tmp, sizeof tmp, " (group %u)", sgidx);
|
xsnprintf(tmp, sizeof tmp, " (group %u)", idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
window_choose_add(wl->window->active, s->idx,
|
window_choose_add(wl->window->active, i,
|
||||||
"%s: %u windows [%ux%u]%s%s", s->name,
|
"%s: %u windows [%ux%u]%s%s", s->name,
|
||||||
winlink_count(&s->windows), s->sx, s->sy,
|
winlink_count(&s->windows), s->sx, s->sy,
|
||||||
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
|
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
|
||||||
@@ -117,7 +120,9 @@ cmd_choose_session_callback(void *data, int idx)
|
|||||||
if (cdata->client->flags & CLIENT_DEAD)
|
if (cdata->client->flags & CLIENT_DEAD)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s = session_find_by_index(idx);
|
if ((u_int) idx > ARRAY_LENGTH(&sessions) - 1)
|
||||||
|
return;
|
||||||
|
s = ARRAY_ITEM(&sessions, idx);
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return;
|
return;
|
||||||
template = cmd_template_replace(cdata->template, s->name, 1);
|
template = cmd_template_replace(cdata->template, s->name, 1);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-choose-window.c,v 1.24 2010-12-22 15:28:50 tcunha Exp $ */
|
/* $Id: cmd-choose-window.c,v 1.20 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -81,14 +81,12 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
idx++;
|
idx++;
|
||||||
|
|
||||||
flag = ' ';
|
flag = ' ';
|
||||||
if (wm->flags & WINLINK_ACTIVITY)
|
if (session_alert_has(s, wm, WINDOW_ACTIVITY))
|
||||||
flag = '#';
|
flag = '#';
|
||||||
else if (wm->flags & WINLINK_BELL)
|
else if (session_alert_has(s, wm, WINDOW_BELL))
|
||||||
flag = '!';
|
flag = '!';
|
||||||
else if (wm->flags & WINLINK_CONTENT)
|
else if (session_alert_has(s, wm, WINDOW_CONTENT))
|
||||||
flag = '+';
|
flag = '+';
|
||||||
else if (wm->flags & WINLINK_SILENCE)
|
|
||||||
flag = '~';
|
|
||||||
else if (wm == s->curw)
|
else if (wm == s->curw)
|
||||||
flag = '*';
|
flag = '*';
|
||||||
else if (wm == TAILQ_FIRST(&s->lastw))
|
else if (wm == TAILQ_FIRST(&s->lastw))
|
||||||
@@ -103,9 +101,8 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
left = right = "";
|
left = right = "";
|
||||||
|
|
||||||
window_choose_add(wl->window->active,
|
window_choose_add(wl->window->active,
|
||||||
wm->idx, "%3d: %s%c [%ux%u] (%u panes%s)%s%s%s",
|
wm->idx, "%3d: %s%c [%ux%u] (%u panes)%s%s%s",
|
||||||
wm->idx, w->name, flag, w->sx, w->sy, window_count_panes(w),
|
wm->idx, w->name, flag, w->sx, w->sy, window_count_panes(w),
|
||||||
w->active->fd == -1 ? ", dead" : "",
|
|
||||||
left, title, right);
|
left, title, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,19 +126,20 @@ 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 = cdata->session;
|
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
struct cmd_ctx ctx;
|
struct cmd_ctx ctx;
|
||||||
char *target, *template, *cause;
|
char *target, *template, *cause;
|
||||||
|
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
return;
|
return;
|
||||||
if (!session_alive(s))
|
|
||||||
return;
|
|
||||||
if (cdata->client->flags & CLIENT_DEAD)
|
if (cdata->client->flags & CLIENT_DEAD)
|
||||||
return;
|
return;
|
||||||
|
if (cdata->session->flags & SESSION_DEAD)
|
||||||
|
return;
|
||||||
|
if (cdata->client->session != cdata->session)
|
||||||
|
return;
|
||||||
|
|
||||||
xasprintf(&target, "%s:%d", s->name, idx);
|
xasprintf(&target, "%s:%d", cdata->session->name, idx);
|
||||||
template = cmd_template_replace(cdata->template, target, 1);
|
template = cmd_template_replace(cdata->template, target, 1);
|
||||||
xfree(target);
|
xfree(target);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-command-prompt.c,v 1.28 2010-05-14 14:33:39 tcunha Exp $ */
|
/* $Id: cmd-command-prompt.c,v 1.27 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -81,10 +81,6 @@ cmd_command_prompt_init(struct cmd *self, int key)
|
|||||||
case 'f':
|
case 'f':
|
||||||
data->template = xstrdup("find-window '%%'");
|
data->template = xstrdup("find-window '%%'");
|
||||||
break;
|
break;
|
||||||
case '\'':
|
|
||||||
data->template = xstrdup("select-window -t ':%%'");
|
|
||||||
data->prompts = xstrdup("index");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-copy-mode.c,v 1.28 2010-08-11 22:18:28 tcunha Exp $ */
|
/* $Id: cmd-copy-mode.c,v 1.26 2010-01-05 23:50:22 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -62,9 +62,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
|
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (window_pane_set_mode(wp, &window_copy_mode) != 0)
|
window_pane_set_mode(wp, &window_copy_mode);
|
||||||
return (0);
|
|
||||||
window_copy_init_from_pane(wp);
|
|
||||||
if (wp->mode == &window_copy_mode && cmd_check_flag(data->chflags, 'u'))
|
if (wp->mode == &window_copy_mode && cmd_check_flag(data->chflags, 'u'))
|
||||||
window_copy_pageup(wp);
|
window_copy_pageup(wp);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* $Id: cmd-last-pane.c,v 1.1 2010-10-24 01:34:30 tcunha Exp $ */
|
/* $Id: cmd-down-pane.c,v 1.14 2010-01-05 23:52:37 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -21,24 +21,24 @@
|
|||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move to last pane.
|
* Move down a pane.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int cmd_last_pane_exec(struct cmd *, struct cmd_ctx *);
|
int cmd_down_pane_exec(struct cmd *, struct cmd_ctx *);
|
||||||
|
|
||||||
const struct cmd_entry cmd_last_pane_entry = {
|
const struct cmd_entry cmd_down_pane_entry = {
|
||||||
"last-pane", "lastp",
|
"down-pane", "downp",
|
||||||
CMD_TARGET_WINDOW_USAGE,
|
CMD_TARGET_WINDOW_USAGE,
|
||||||
0, "",
|
0, "",
|
||||||
cmd_target_init,
|
cmd_target_init,
|
||||||
cmd_target_parse,
|
cmd_target_parse,
|
||||||
cmd_last_pane_exec,
|
cmd_down_pane_exec,
|
||||||
cmd_target_free,
|
cmd_target_free,
|
||||||
cmd_target_print
|
cmd_target_print
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_last_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
cmd_down_pane_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;
|
||||||
@@ -48,11 +48,13 @@ cmd_last_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
return (-1);
|
return (-1);
|
||||||
w = wl->window;
|
w = wl->window;
|
||||||
|
|
||||||
if (w->last == NULL) {
|
do {
|
||||||
ctx->error(ctx, "no last pane");
|
w->active = TAILQ_NEXT(w->active, entry);
|
||||||
return (-1);
|
if (w->active == NULL)
|
||||||
}
|
w->active = TAILQ_FIRST(&w->panes);
|
||||||
window_set_active_pane(w, w->last);
|
} while (!window_pane_visible(w->active));
|
||||||
|
server_status_window(wl->window);
|
||||||
|
server_redraw_window_borders(wl->window);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-find-window.c,v 1.15 2010-12-22 15:28:50 tcunha Exp $ */
|
/* $Id: cmd-find-window.c,v 1.14 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
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);
|
||||||
void cmd_find_window_free(void *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_find_window_entry = {
|
const struct cmd_entry cmd_find_window_entry = {
|
||||||
"find-window", "findw",
|
"find-window", "findw",
|
||||||
@@ -44,7 +43,7 @@ const struct cmd_entry cmd_find_window_entry = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct cmd_find_window_data {
|
struct cmd_find_window_data {
|
||||||
struct session *session;
|
u_int session;
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -135,11 +134,11 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cdata = xmalloc(sizeof *cdata);
|
cdata = xmalloc(sizeof *cdata);
|
||||||
cdata->session = s;
|
if (session_index(s, &cdata->session) != 0)
|
||||||
cdata->session->references++;
|
fatalx("session not found");
|
||||||
|
|
||||||
window_choose_ready(wl->window->active,
|
window_choose_ready(
|
||||||
0, cmd_find_window_callback, cmd_find_window_free, cdata);
|
wl->window->active, 0, cmd_find_window_callback, xfree, cdata);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ARRAY_FREE(&list_idx);
|
ARRAY_FREE(&list_idx);
|
||||||
@@ -152,24 +151,12 @@ void
|
|||||||
cmd_find_window_callback(void *data, int idx)
|
cmd_find_window_callback(void *data, int idx)
|
||||||
{
|
{
|
||||||
struct cmd_find_window_data *cdata = data;
|
struct cmd_find_window_data *cdata = data;
|
||||||
struct session *s = cdata->session;
|
struct session *s;
|
||||||
|
|
||||||
if (idx == -1)
|
if (idx != -1 && cdata->session <= ARRAY_LENGTH(&sessions) - 1) {
|
||||||
return;
|
s = ARRAY_ITEM(&sessions, cdata->session);
|
||||||
if (!session_alive(s))
|
if (s != NULL && session_select(s, idx) == 0)
|
||||||
return;
|
server_redraw_session(s);
|
||||||
|
|
||||||
if (session_select(s, idx) == 0) {
|
|
||||||
server_redraw_session(s);
|
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
cmd_find_window_free(void *data)
|
|
||||||
{
|
|
||||||
struct cmd_find_window_data *cdata = data;
|
|
||||||
|
|
||||||
cdata->session->references--;
|
|
||||||
xfree(cdata);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-if-shell.c,v 1.10 2010-08-09 21:44:25 tcunha Exp $ */
|
/* $Id: cmd-if-shell.c,v 1.8 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -104,12 +104,10 @@ cmd_if_shell_free(void *data)
|
|||||||
{
|
{
|
||||||
struct cmd_if_shell_data *cdata = data;
|
struct cmd_if_shell_data *cdata = data;
|
||||||
struct cmd_ctx *ctx = &cdata->ctx;
|
struct cmd_ctx *ctx = &cdata->ctx;
|
||||||
struct msg_exit_data exitdata;
|
|
||||||
|
|
||||||
if (ctx->cmdclient != NULL) {
|
if (ctx->cmdclient != NULL) {
|
||||||
ctx->cmdclient->references--;
|
ctx->cmdclient->references--;
|
||||||
exitdata.retcode = ctx->cmdclient->retcode;
|
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
|
||||||
ctx->cmdclient->flags |= CLIENT_EXIT;
|
|
||||||
}
|
}
|
||||||
if (ctx->curclient != NULL)
|
if (ctx->curclient != NULL)
|
||||||
ctx->curclient->references--;
|
ctx->curclient->references--;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-join-pane.c,v 1.5 2010-08-11 22:17:32 tcunha Exp $ */
|
/* $Id: cmd-join-pane.c,v 1.2 2010-01-08 16:34:17 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -44,7 +44,7 @@ struct cmd_join_pane_data {
|
|||||||
|
|
||||||
const struct cmd_entry cmd_join_pane_entry = {
|
const struct cmd_entry cmd_join_pane_entry = {
|
||||||
"join-pane", "joinp",
|
"join-pane", "joinp",
|
||||||
"[-dhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
|
"[-dhv] [-p percentage|-l size] [-t src-pane] [-t dst-pane] [command]",
|
||||||
0, "",
|
0, "",
|
||||||
cmd_join_pane_init,
|
cmd_join_pane_init,
|
||||||
cmd_join_pane_parse,
|
cmd_join_pane_parse,
|
||||||
@@ -150,14 +150,13 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct winlink *src_wl, *dst_wl;
|
struct winlink *src_wl, *dst_wl;
|
||||||
struct window *src_w, *dst_w;
|
struct window *src_w, *dst_w;
|
||||||
struct window_pane *src_wp, *dst_wp;
|
struct window_pane *src_wp, *dst_wp;
|
||||||
int size, dst_idx;
|
int size;
|
||||||
enum layout_type type;
|
enum layout_type type;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
|
|
||||||
if ((dst_wl = cmd_find_pane(ctx, data->dst, &dst_s, &dst_wp)) == NULL)
|
if ((dst_wl = cmd_find_pane(ctx, data->dst, &dst_s, &dst_wp)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
dst_w = dst_wl->window;
|
dst_w = dst_wl->window;
|
||||||
dst_idx = dst_wl->idx;
|
|
||||||
|
|
||||||
if ((src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp)) == NULL)
|
if ((src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -210,7 +209,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
|
|
||||||
if (!data->flag_detached) {
|
if (!data->flag_detached) {
|
||||||
window_set_active_pane(dst_w, src_wp);
|
window_set_active_pane(dst_w, src_wp);
|
||||||
session_select(dst_s, dst_idx);
|
session_select(dst_s, dst_wl->idx);
|
||||||
server_redraw_session(dst_s);
|
server_redraw_session(dst_s);
|
||||||
} else
|
} else
|
||||||
server_status_session(dst_s);
|
server_status_session(dst_s);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-kill-session.c,v 1.18 2010-07-02 02:43:50 tcunha Exp $ */
|
/* $Id: cmd-kill-session.c,v 1.17 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -45,11 +45,21 @@ cmd_kill_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;
|
||||||
|
struct client *c;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
server_destroy_session(s);
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
|
c = ARRAY_ITEM(&clients, i);
|
||||||
|
if (c != NULL && c->session == s) {
|
||||||
|
c->session = NULL;
|
||||||
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recalculate_sizes();
|
||||||
|
|
||||||
session_destroy(s);
|
session_destroy(s);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list-buffers.c,v 1.16 2010-06-22 23:35:20 tcunha Exp $ */
|
/* $Id: cmd-list-buffers.c,v 1.15 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -46,17 +46,32 @@ 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, len;
|
||||||
|
|
||||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) {
|
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) {
|
||||||
tmp = paste_print(pb, 50);
|
size = pb->size;
|
||||||
ctx->print(ctx,
|
|
||||||
"%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);
|
/* Translate the first 50 characters. */
|
||||||
xfree(tmp);
|
len = size;
|
||||||
|
if (len > 50)
|
||||||
|
len = 50;
|
||||||
|
strvisx(tmp, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the first 50 characters were encoded as a longer string,
|
||||||
|
* or there is definitely more data, add "...".
|
||||||
|
*/
|
||||||
|
if (size > 50 || strlen(tmp) > 50) {
|
||||||
|
tmp[50 - 3] = '\0';
|
||||||
|
strlcat(tmp, "...", sizeof tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->print(ctx, "%u: %zu bytes: \"%s\"", idx - 1, size, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list-keys.c,v 1.25 2010-10-24 01:31:57 tcunha Exp $ */
|
/* $Id: cmd-list-keys.c,v 1.24 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -80,11 +80,6 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if (used >= sizeof tmp)
|
if (used >= sizeof tmp)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (bd->can_repeat) {
|
|
||||||
used = strlcat(tmp, "(repeat) ", sizeof tmp);
|
|
||||||
if (used >= sizeof tmp)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cmd_list_print(bd->cmdlist, tmp + used, (sizeof tmp) - used);
|
cmd_list_print(bd->cmdlist, tmp + used, (sizeof tmp) - used);
|
||||||
ctx->print(ctx, "%s", tmp);
|
ctx->print(ctx, "%s", tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list-panes.c,v 1.6 2010-12-06 21:56:32 nicm Exp $ */
|
/* $Id: cmd-list-panes.c,v 1.4 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -65,10 +65,8 @@ cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
size += gd->hsize * sizeof *gd->linedata;
|
size += gd->hsize * sizeof *gd->linedata;
|
||||||
|
|
||||||
ctx->print(ctx, "%u: [%ux%u] [history %u/%u, %llu bytes]%s%s",
|
ctx->print(ctx, "%u: [%ux%u] [history %u/%u, %llu bytes]",
|
||||||
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size,
|
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size);
|
||||||
wp == wp->window->active ? " (active)" : "",
|
|
||||||
wp->fd == -1 ? " (dead)" : "");
|
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list-sessions.c,v 1.26 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: cmd-list-sessions.c,v 1.25 2009-11-28 14:50:36 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -46,10 +46,14 @@ cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct session *s;
|
struct session *s;
|
||||||
struct session_group *sg;
|
struct session_group *sg;
|
||||||
char *tim, tmp[64];
|
char *tim, tmp[64];
|
||||||
u_int idx;
|
u_int i, idx;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
|
if (s == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
sg = session_group_find(s);
|
sg = session_group_find(s);
|
||||||
if (sg == NULL)
|
if (sg == NULL)
|
||||||
*tmp = '\0';
|
*tmp = '\0';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list-windows.c,v 1.44 2010-12-06 21:56:32 nicm Exp $ */
|
/* $Id: cmd-list-windows.c,v 1.42 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -45,17 +45,13 @@ cmd_list_windows_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 winlink *wl;
|
||||||
char *layout;
|
|
||||||
|
|
||||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
layout = layout_dump(wl->window);
|
ctx->print(ctx, "%d: %s [%ux%u]",
|
||||||
ctx->print(ctx, "%d: %s [%ux%u] [layout %s]%s",
|
wl->idx, wl->window->name, wl->window->sx, wl->window->sy);
|
||||||
wl->idx, wl->window->name, wl->window->sx, wl->window->sy,
|
|
||||||
layout, wl == s->curw ? " (active)" : "");
|
|
||||||
xfree(layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
46
cmd-list.c
46
cmd-list.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list.c,v 1.10 2010-12-06 21:48:56 nicm Exp $ */
|
/* $Id: cmd-list.c,v 1.7 2010-02-02 23:51:04 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -29,52 +29,47 @@ cmd_list_parse(int argc, char **argv, char **cause)
|
|||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
int i, lastsplit;
|
int i, lastsplit;
|
||||||
size_t arglen, new_argc;
|
size_t arglen, new_argc;
|
||||||
char **copy_argv, **new_argv;
|
char **new_argv;
|
||||||
|
|
||||||
copy_argv = cmd_copy_argv(argc, argv);
|
|
||||||
|
|
||||||
cmdlist = xmalloc(sizeof *cmdlist);
|
cmdlist = xmalloc(sizeof *cmdlist);
|
||||||
cmdlist->references = 1;
|
TAILQ_INIT(cmdlist);
|
||||||
TAILQ_INIT(&cmdlist->list);
|
|
||||||
|
|
||||||
lastsplit = 0;
|
lastsplit = 0;
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
arglen = strlen(copy_argv[i]);
|
arglen = strlen(argv[i]);
|
||||||
if (arglen == 0 || copy_argv[i][arglen - 1] != ';')
|
if (arglen == 0 || argv[i][arglen - 1] != ';')
|
||||||
continue;
|
continue;
|
||||||
copy_argv[i][arglen - 1] = '\0';
|
argv[i][arglen - 1] = '\0';
|
||||||
|
|
||||||
if (arglen > 1 && copy_argv[i][arglen - 2] == '\\') {
|
if (arglen > 1 && argv[i][arglen - 2] == '\\') {
|
||||||
copy_argv[i][arglen - 2] = ';';
|
argv[i][arglen - 2] = ';';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_argc = i - lastsplit;
|
new_argc = i - lastsplit;
|
||||||
new_argv = copy_argv + lastsplit;
|
new_argv = argv + lastsplit;
|
||||||
if (arglen != 1)
|
if (arglen != 1)
|
||||||
new_argc++;
|
new_argc++;
|
||||||
|
|
||||||
cmd = cmd_parse(new_argc, new_argv, cause);
|
cmd = cmd_parse(new_argc, new_argv, cause);
|
||||||
if (cmd == NULL)
|
if (cmd == NULL)
|
||||||
goto bad;
|
goto bad;
|
||||||
TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
|
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
|
||||||
|
|
||||||
lastsplit = i + 1;
|
lastsplit = i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastsplit != argc) {
|
if (lastsplit != argc) {
|
||||||
cmd = cmd_parse(argc - lastsplit, copy_argv + lastsplit, cause);
|
cmd = cmd_parse(argc - lastsplit, argv + lastsplit, cause);
|
||||||
if (cmd == NULL)
|
if (cmd == NULL)
|
||||||
goto bad;
|
goto bad;
|
||||||
TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
|
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_free_argv(argc, copy_argv);
|
|
||||||
return (cmdlist);
|
return (cmdlist);
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
cmd_free_argv(argc, copy_argv);
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +80,7 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
|
|||||||
int n, retval;
|
int n, retval;
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
||||||
if ((n = cmd_exec(cmd, ctx)) == -1)
|
if ((n = cmd_exec(cmd, ctx)) == -1)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
@@ -104,10 +99,6 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
|
|||||||
if (ctx->curclient == NULL) {
|
if (ctx->curclient == NULL) {
|
||||||
ctx->curclient = ctx->cmdclient;
|
ctx->curclient = ctx->cmdclient;
|
||||||
ctx->cmdclient = NULL;
|
ctx->cmdclient = NULL;
|
||||||
|
|
||||||
ctx->error = key_bindings_error;
|
|
||||||
ctx->print = key_bindings_print;
|
|
||||||
ctx->info = key_bindings_info;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,12 +110,9 @@ cmd_list_free(struct cmd_list *cmdlist)
|
|||||||
{
|
{
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
|
|
||||||
if (--cmdlist->references != 0)
|
while (!TAILQ_EMPTY(cmdlist)) {
|
||||||
return;
|
cmd = TAILQ_FIRST(cmdlist);
|
||||||
|
TAILQ_REMOVE(cmdlist, cmd, qentry);
|
||||||
while (!TAILQ_EMPTY(&cmdlist->list)) {
|
|
||||||
cmd = TAILQ_FIRST(&cmdlist->list);
|
|
||||||
TAILQ_REMOVE(&cmdlist->list, cmd, qentry);
|
|
||||||
cmd_free(cmd);
|
cmd_free(cmd);
|
||||||
}
|
}
|
||||||
xfree(cmdlist);
|
xfree(cmdlist);
|
||||||
@@ -137,7 +125,7 @@ cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len)
|
|||||||
size_t off;
|
size_t off;
|
||||||
|
|
||||||
off = 0;
|
off = 0;
|
||||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
||||||
if (off >= len)
|
if (off >= len)
|
||||||
break;
|
break;
|
||||||
off += cmd_print(cmd, buf + off, len - off);
|
off += cmd_print(cmd, buf + off, len - off);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-load-buffer.c,v 1.18 2010-12-22 15:28:50 tcunha Exp $ */
|
/* $Id: cmd-load-buffer.c,v 1.15 2010-02-26 13:30:07 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -16,13 +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 <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@@ -31,7 +28,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
|
int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
|
||||||
void cmd_load_buffer_callback(struct client *, void *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_load_buffer_entry = {
|
const struct cmd_entry cmd_load_buffer_entry = {
|
||||||
"load-buffer", "loadb",
|
"load-buffer", "loadb",
|
||||||
@@ -44,53 +40,20 @@ const struct cmd_entry cmd_load_buffer_entry = {
|
|||||||
cmd_buffer_print
|
cmd_buffer_print
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cmd_load_buffer_cdata {
|
|
||||||
struct session *session;
|
|
||||||
int buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
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 cmd_load_buffer_cdata *cdata;
|
struct session *s;
|
||||||
struct session *s;
|
FILE *f;
|
||||||
struct client *c = ctx->cmdclient;
|
char *pdata, *new_pdata;
|
||||||
FILE *f;
|
size_t psize;
|
||||||
char *pdata, *new_pdata;
|
u_int limit;
|
||||||
size_t psize;
|
int ch;
|
||||||
u_int limit;
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (strcmp(data->arg, "-") == 0) {
|
|
||||||
if (c == NULL) {
|
|
||||||
ctx->error(ctx, "%s: can't read from stdin", data->arg);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
if (c->flags & CLIENT_TERMINAL) {
|
|
||||||
ctx->error(ctx, "%s: stdin is a tty", data->arg);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
if (c->stdin_fd == -1) {
|
|
||||||
ctx->error(ctx, "%s: can't read from stdin", data->arg);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
cdata = xmalloc(sizeof *cdata);
|
|
||||||
cdata->session = s;
|
|
||||||
cdata->session->references++;
|
|
||||||
cdata->buffer = data->buffer;
|
|
||||||
c->stdin_data = cdata;
|
|
||||||
c->stdin_callback = cmd_load_buffer_callback;
|
|
||||||
|
|
||||||
c->references++;
|
|
||||||
bufferevent_enable(c->stdin_event, EV_READ);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((f = fopen(data->arg, "rb")) == 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);
|
||||||
@@ -115,7 +78,6 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
pdata[psize] = '\0';
|
pdata[psize] = '\0';
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
f = NULL;
|
|
||||||
|
|
||||||
limit = options_get_number(&s->options, "buffer-limit");
|
limit = options_get_number(&s->options, "buffer-limit");
|
||||||
if (data->buffer == -1) {
|
if (data->buffer == -1) {
|
||||||
@@ -124,7 +86,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 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);
|
||||||
return (-1);
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@@ -132,54 +94,6 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
error:
|
error:
|
||||||
if (pdata != NULL)
|
if (pdata != NULL)
|
||||||
xfree(pdata);
|
xfree(pdata);
|
||||||
if (f != NULL)
|
fclose(f);
|
||||||
fclose(f);
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
cmd_load_buffer_callback(struct client *c, void *data)
|
|
||||||
{
|
|
||||||
struct cmd_load_buffer_cdata *cdata = data;
|
|
||||||
struct session *s = cdata->session;
|
|
||||||
char *pdata;
|
|
||||||
size_t psize;
|
|
||||||
u_int limit;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Event callback has already checked client is not dead and reduced
|
|
||||||
* its reference count. But tell it to exit.
|
|
||||||
*/
|
|
||||||
c->flags |= CLIENT_EXIT;
|
|
||||||
|
|
||||||
/* Does the target session still exist? */
|
|
||||||
if (!session_alive(s))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
psize = EVBUFFER_LENGTH(c->stdin_event->input);
|
|
||||||
if (psize == 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
pdata = malloc(psize + 1);
|
|
||||||
if (pdata == NULL)
|
|
||||||
goto out;
|
|
||||||
bufferevent_read(c->stdin_event, pdata, psize);
|
|
||||||
pdata[psize] = '\0';
|
|
||||||
|
|
||||||
limit = options_get_number(&s->options, "buffer-limit");
|
|
||||||
if (cdata->buffer == -1) {
|
|
||||||
paste_add(&s->buffers, pdata, psize, limit);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (paste_replace(&s->buffers, cdata->buffer, pdata, psize) != 0) {
|
|
||||||
/* No context so can't use server_client_msg_error. */
|
|
||||||
evbuffer_add_printf(
|
|
||||||
c->stderr_event->output, "no buffer %d\n", cdata->buffer);
|
|
||||||
bufferevent_enable(c->stderr_event, EV_WRITE);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
cdata->session->references--;
|
|
||||||
xfree(cdata);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-new-session.c,v 1.80 2010-12-22 15:31:00 tcunha Exp $ */
|
/* $Id: cmd-new-session.c,v 1.76 2010-02-26 13:28:15 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -18,10 +18,8 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@@ -122,14 +120,13 @@ 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 session *s, *old_s, *groupwith;
|
struct session *s, *groupwith;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct environ env;
|
struct environ env;
|
||||||
struct termios tio, *tiop;
|
struct termios tio, *tiop;
|
||||||
struct passwd *pw;
|
const char *update;
|
||||||
const char *update, *cwd;
|
char *overrides, *cmd, *cwd, *cause;
|
||||||
char *overrides, *cmd, *cause;
|
|
||||||
int detached, idx;
|
int detached, idx;
|
||||||
u_int sx, sy, i;
|
u_int sx, sy, i;
|
||||||
|
|
||||||
@@ -201,13 +198,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
/* Get the new session working directory. */
|
/* Get the new session working directory. */
|
||||||
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
|
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
|
||||||
cwd = ctx->cmdclient->cwd;
|
cwd = ctx->cmdclient->cwd;
|
||||||
else {
|
else
|
||||||
pw = getpwuid(getuid());
|
cwd = options_get_string(&global_s_options, "default-path");
|
||||||
if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
|
|
||||||
cwd = pw->pw_dir;
|
|
||||||
else
|
|
||||||
cwd = "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find new session size. */
|
/* Find new session size. */
|
||||||
if (detached) {
|
if (detached) {
|
||||||
@@ -279,16 +271,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if (!detached) {
|
if (!detached) {
|
||||||
if (ctx->cmdclient != NULL) {
|
if (ctx->cmdclient != NULL) {
|
||||||
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
|
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
|
||||||
|
|
||||||
old_s = ctx->cmdclient->session;
|
|
||||||
if (old_s != NULL)
|
|
||||||
ctx->cmdclient->last_session = old_s;
|
|
||||||
ctx->cmdclient->session = s;
|
ctx->cmdclient->session = s;
|
||||||
server_redraw_client(ctx->cmdclient);
|
server_redraw_client(ctx->cmdclient);
|
||||||
} else {
|
} else {
|
||||||
old_s = ctx->curclient->session;
|
|
||||||
if (old_s != NULL)
|
|
||||||
ctx->curclient->last_session = old_s;
|
|
||||||
ctx->curclient->session = s;
|
ctx->curclient->session = s;
|
||||||
server_redraw_client(ctx->curclient);
|
server_redraw_client(ctx->curclient);
|
||||||
}
|
}
|
||||||
@@ -302,11 +287,10 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
*/
|
*/
|
||||||
if (cfg_finished && !ARRAY_EMPTY(&cfg_causes)) {
|
if (cfg_finished && !ARRAY_EMPTY(&cfg_causes)) {
|
||||||
wp = s->curw->window->active;
|
wp = s->curw->window->active;
|
||||||
window_pane_set_mode(wp, &window_copy_mode);
|
window_pane_set_mode(wp, &window_more_mode);
|
||||||
window_copy_init_for_output(wp);
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
|
||||||
cause = ARRAY_ITEM(&cfg_causes, i);
|
cause = ARRAY_ITEM(&cfg_causes, i);
|
||||||
window_copy_add(wp, "%s", cause);
|
window_more_add(wp, "%s", cause);
|
||||||
xfree(cause);
|
xfree(cause);
|
||||||
}
|
}
|
||||||
ARRAY_FREE(&cfg_causes);
|
ARRAY_FREE(&cfg_causes);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-new-window.c,v 1.47 2010-07-02 02:49:19 tcunha Exp $ */
|
/* $Id: cmd-new-window.c,v 1.43 2010-01-22 17:28:34 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -36,14 +36,13 @@ struct cmd_new_window_data {
|
|||||||
char *target;
|
char *target;
|
||||||
char *name;
|
char *name;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
int flag_insert_after;
|
|
||||||
int flag_detached;
|
int flag_detached;
|
||||||
int flag_kill;
|
int flag_kill;
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct cmd_entry cmd_new_window_entry = {
|
const struct cmd_entry cmd_new_window_entry = {
|
||||||
"new-window", "neww",
|
"new-window", "neww",
|
||||||
"[-adk] [-n window-name] [-t target-window] [command]",
|
"[-dk] [-n window-name] [-t target-window] [command]",
|
||||||
0, "",
|
0, "",
|
||||||
cmd_new_window_init,
|
cmd_new_window_init,
|
||||||
cmd_new_window_parse,
|
cmd_new_window_parse,
|
||||||
@@ -62,7 +61,6 @@ cmd_new_window_init(struct cmd *self, unused int arg)
|
|||||||
data->target = NULL;
|
data->target = NULL;
|
||||||
data->name = NULL;
|
data->name = NULL;
|
||||||
data->cmd = NULL;
|
data->cmd = NULL;
|
||||||
data->flag_insert_after = 0;
|
|
||||||
data->flag_detached = 0;
|
data->flag_detached = 0;
|
||||||
data->flag_kill = 0;
|
data->flag_kill = 0;
|
||||||
}
|
}
|
||||||
@@ -76,11 +74,8 @@ cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
self->entry->init(self, KEYC_NONE);
|
self->entry->init(self, KEYC_NONE);
|
||||||
data = self->data;
|
data = self->data;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "adkt:n:")) != -1) {
|
while ((opt = getopt(argc, argv, "dkt:n:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'a':
|
|
||||||
data->flag_insert_after = 1;
|
|
||||||
break;
|
|
||||||
case 'd':
|
case 'd':
|
||||||
data->flag_detached = 1;
|
data->flag_detached = 1;
|
||||||
break;
|
break;
|
||||||
@@ -123,36 +118,13 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct session *s;
|
struct session *s;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
char *cmd, *cwd, *cause;
|
char *cmd, *cwd, *cause;
|
||||||
int idx, last;
|
int idx;
|
||||||
|
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (data->flag_insert_after) {
|
if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
|
||||||
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
|
return (-1);
|
||||||
return (-1);
|
|
||||||
idx = wl->idx + 1;
|
|
||||||
|
|
||||||
/* Find the next free index. */
|
|
||||||
for (last = idx; last < INT_MAX; last++) {
|
|
||||||
if (winlink_find_by_index(&s->windows, last) == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (last == INT_MAX) {
|
|
||||||
ctx->error(ctx, "no free window indexes");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move everything from last - 1 to idx up a bit. */
|
|
||||||
for (; last > idx; last--) {
|
|
||||||
wl = winlink_find_by_index(&s->windows, last - 1);
|
|
||||||
server_link_window(s, wl, s, last, 0, 0, NULL);
|
|
||||||
server_unlink_window(s, wl);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl = NULL;
|
wl = NULL;
|
||||||
if (idx != -1)
|
if (idx != -1)
|
||||||
@@ -162,7 +134,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
* Can't use session_detach as it will destroy session if this
|
* Can't use session_detach as it will destroy session if this
|
||||||
* makes it empty.
|
* makes it empty.
|
||||||
*/
|
*/
|
||||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
session_alert_cancel(s, wl);
|
||||||
winlink_stack_remove(&s->lastw, wl);
|
winlink_stack_remove(&s->lastw, wl);
|
||||||
winlink_remove(&s->windows, wl);
|
winlink_remove(&s->windows, wl);
|
||||||
|
|
||||||
@@ -176,13 +148,10 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
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");
|
||||||
cwd = options_get_string(&s->options, "default-path");
|
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
|
||||||
if (*cwd == '\0') {
|
cwd = options_get_string(&s->options, "default-path");
|
||||||
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
|
else
|
||||||
cwd = ctx->cmdclient->cwd;
|
cwd = ctx->cmdclient->cwd;
|
||||||
else
|
|
||||||
cwd = s->cwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
idx = -1 - options_get_number(&s->options, "base-index");
|
idx = -1 - options_get_number(&s->options, "base-index");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-paste-buffer.c,v 1.29 2010-08-11 22:17:32 tcunha Exp $ */
|
/* $Id: cmd-paste-buffer.c,v 1.24 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@@ -27,112 +26,32 @@
|
|||||||
* Paste paste buffer if present.
|
* Paste paste buffer if present.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct cmd_paste_buffer_data {
|
|
||||||
char *target;
|
|
||||||
int buffer;
|
|
||||||
|
|
||||||
int flag_delete;
|
|
||||||
char *sepstr;
|
|
||||||
};
|
|
||||||
|
|
||||||
void cmd_paste_buffer_init(struct cmd *, int);
|
|
||||||
int cmd_paste_buffer_parse(struct cmd *, int, char **, char **);
|
|
||||||
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
|
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
|
||||||
void cmd_paste_buffer_filter(
|
void cmd_paste_buffer_lf2cr(struct window_pane *, const char *, size_t);
|
||||||
struct window_pane *, const char *, size_t, char *);
|
|
||||||
void cmd_paste_buffer_free(struct cmd *);
|
|
||||||
size_t cmd_paste_buffer_print(struct cmd *, char *, size_t);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_paste_buffer_entry = {
|
const struct cmd_entry cmd_paste_buffer_entry = {
|
||||||
"paste-buffer", "pasteb",
|
"paste-buffer", "pasteb",
|
||||||
"[-dr] [-s separator] [-b buffer-index] [-t target-pane]",
|
"[-dr] " CMD_BUFFER_WINDOW_USAGE,
|
||||||
0, "",
|
0, "dr",
|
||||||
cmd_paste_buffer_init,
|
cmd_buffer_init,
|
||||||
cmd_paste_buffer_parse,
|
cmd_buffer_parse,
|
||||||
cmd_paste_buffer_exec,
|
cmd_paste_buffer_exec,
|
||||||
cmd_paste_buffer_free,
|
cmd_buffer_free,
|
||||||
cmd_paste_buffer_print
|
cmd_buffer_print
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
void
|
|
||||||
cmd_paste_buffer_init(struct cmd *self, unused int arg)
|
|
||||||
{
|
|
||||||
struct cmd_paste_buffer_data *data;
|
|
||||||
|
|
||||||
self->data = data = xmalloc(sizeof *data);
|
|
||||||
data->target = NULL;
|
|
||||||
data->buffer = -1;
|
|
||||||
data->flag_delete = 0;
|
|
||||||
data->sepstr = xstrdup("\r");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cmd_paste_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|
||||||
{
|
|
||||||
struct cmd_paste_buffer_data *data;
|
|
||||||
int opt, n;
|
|
||||||
const char *errstr;
|
|
||||||
|
|
||||||
cmd_paste_buffer_init(self, 0);
|
|
||||||
data = self->data;
|
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "b:ds:t:r")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'b':
|
|
||||||
if (data->buffer == -1) {
|
|
||||||
n = strtonum(optarg, 0, INT_MAX, &errstr);
|
|
||||||
if (errstr != NULL) {
|
|
||||||
xasprintf(cause, "buffer %s", errstr);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
data->buffer = n;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
data->flag_delete = 1;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
if (data->sepstr != NULL)
|
|
||||||
xfree(data->sepstr);
|
|
||||||
data->sepstr = xstrdup(optarg);
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
if (data->target == NULL)
|
|
||||||
data->target = xstrdup(optarg);
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
if (data->sepstr != NULL)
|
|
||||||
xfree(data->sepstr);
|
|
||||||
data->sepstr = xstrdup("\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto usage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
usage:
|
|
||||||
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
|
|
||||||
|
|
||||||
error:
|
|
||||||
self->entry->free(self);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct cmd_paste_buffer_data *data = self->data;
|
struct cmd_buffer_data *data = self->data;
|
||||||
struct window_pane *wp;
|
struct winlink *wl;
|
||||||
struct session *s;
|
struct window_pane *wp;
|
||||||
struct paste_buffer *pb;
|
struct session *s;
|
||||||
|
struct paste_buffer *pb;
|
||||||
|
|
||||||
if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
|
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
wp = wl->window->active;
|
||||||
|
|
||||||
if (data->buffer == -1)
|
if (data->buffer == -1)
|
||||||
pb = paste_get_top(&s->buffers);
|
pb = paste_get_top(&s->buffers);
|
||||||
@@ -143,11 +62,16 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pb != NULL)
|
if (pb != NULL) {
|
||||||
cmd_paste_buffer_filter(wp, pb->data, pb->size, data->sepstr);
|
/* -r means raw data without LF->CR conversion. */
|
||||||
|
if (cmd_check_flag(data->chflags, 'r'))
|
||||||
|
bufferevent_write(wp->event, pb->data, pb->size);
|
||||||
|
else
|
||||||
|
cmd_paste_buffer_lf2cr(wp, pb->data, pb->size);
|
||||||
|
}
|
||||||
|
|
||||||
/* Delete the buffer if -d. */
|
/* Delete the buffer if -d. */
|
||||||
if (data->flag_delete) {
|
if (cmd_check_flag(data->chflags, 'd')) {
|
||||||
if (data->buffer == -1)
|
if (data->buffer == -1)
|
||||||
paste_free_top(&s->buffers);
|
paste_free_top(&s->buffers);
|
||||||
else
|
else
|
||||||
@@ -157,66 +81,20 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add bytes to a buffer and filter '\n' according to separator. */
|
/* Add bytes to a buffer but change every '\n' to '\r'. */
|
||||||
void
|
void
|
||||||
cmd_paste_buffer_filter(
|
cmd_paste_buffer_lf2cr(struct window_pane *wp, const char *data, size_t size)
|
||||||
struct window_pane *wp, const char *data, size_t size, char *sep)
|
|
||||||
{
|
{
|
||||||
const char *end = data + size;
|
const char *end = data + size;
|
||||||
const char *lf;
|
const char *lf;
|
||||||
size_t seplen;
|
|
||||||
|
|
||||||
seplen = strlen(sep);
|
|
||||||
while ((lf = memchr(data, '\n', end - data)) != NULL) {
|
while ((lf = memchr(data, '\n', end - data)) != NULL) {
|
||||||
if (lf != data)
|
if (lf != data)
|
||||||
bufferevent_write(wp->event, data, lf - data);
|
bufferevent_write(wp->event, data, lf - data);
|
||||||
bufferevent_write(wp->event, sep, seplen);
|
bufferevent_write(wp->event, "\r", 1);
|
||||||
data = lf + 1;
|
data = lf + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end != data)
|
if (end != data)
|
||||||
bufferevent_write(wp->event, data, end - data);
|
bufferevent_write(wp->event, data, end - data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
cmd_paste_buffer_free(struct cmd *self)
|
|
||||||
{
|
|
||||||
struct cmd_paste_buffer_data *data = self->data;
|
|
||||||
|
|
||||||
if (data->target != NULL)
|
|
||||||
xfree(data->target);
|
|
||||||
if (data->sepstr != NULL)
|
|
||||||
xfree(data->sepstr);
|
|
||||||
xfree(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
cmd_paste_buffer_print(struct cmd *self, char *buf, size_t len)
|
|
||||||
{
|
|
||||||
struct cmd_paste_buffer_data *data = self->data;
|
|
||||||
size_t off = 0;
|
|
||||||
char tmp[BUFSIZ];
|
|
||||||
int r_flag;
|
|
||||||
|
|
||||||
r_flag = 0;
|
|
||||||
if (data->sepstr != NULL)
|
|
||||||
r_flag = (data->sepstr[0] == '\n' && data->sepstr[1] == '\0');
|
|
||||||
|
|
||||||
off += xsnprintf(buf, len, "%s", self->entry->name);
|
|
||||||
if (data == NULL)
|
|
||||||
return (off);
|
|
||||||
if (off < len && data->flag_delete)
|
|
||||||
off += xsnprintf(buf + off, len - off, " -d");
|
|
||||||
if (off < len && r_flag)
|
|
||||||
off += xsnprintf(buf + off, len - off, " -r");
|
|
||||||
if (off < len && data->buffer != -1)
|
|
||||||
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
|
|
||||||
if (off < len && data->sepstr != NULL && !r_flag) {
|
|
||||||
strnvis(
|
|
||||||
tmp, data->sepstr, sizeof tmp, VIS_OCTAL|VIS_TAB|VIS_NL);
|
|
||||||
off += cmd_prarg(buf + off, len - off, " -s ", tmp);
|
|
||||||
}
|
|
||||||
if (off < len && data->target != NULL)
|
|
||||||
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
|
|
||||||
return (off);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-pipe-pane.c,v 1.15 2010-10-24 00:45:57 tcunha Exp $ */
|
/* $Id: cmd-pipe-pane.c,v 1.10 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@@ -50,14 +49,9 @@ int
|
|||||||
cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct cmd_target_data *data = self->data;
|
struct cmd_target_data *data = self->data;
|
||||||
struct client *c;
|
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
char *command;
|
|
||||||
int old_fd, pipe_fd[2], null_fd, mode;
|
int old_fd, pipe_fd[2], null_fd, mode;
|
||||||
|
|
||||||
if ((c = cmd_find_client(ctx, NULL)) == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
|
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
@@ -96,7 +90,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
case 0:
|
case 0:
|
||||||
/* Child process. */
|
/* Child process. */
|
||||||
close(pipe_fd[0]);
|
close(pipe_fd[0]);
|
||||||
clear_signals(1);
|
server_signal_clear();
|
||||||
|
|
||||||
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
|
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
|
||||||
_exit(1);
|
_exit(1);
|
||||||
@@ -111,10 +105,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO)
|
if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO)
|
||||||
close(null_fd);
|
close(null_fd);
|
||||||
|
|
||||||
closefrom(STDERR_FILENO + 1);
|
execl(_PATH_BSHELL, "sh", "-c", data->arg, (char *) NULL);
|
||||||
|
|
||||||
command = status_replace(c, NULL, data->arg, time(NULL), 0);
|
|
||||||
execl(_PATH_BSHELL, "sh", "-c", command, (char *) NULL);
|
|
||||||
_exit(1);
|
_exit(1);
|
||||||
default:
|
default:
|
||||||
/* Parent process. */
|
/* Parent process. */
|
||||||
@@ -131,6 +122,8 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
if (fcntl(wp->pipe_fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
if (fcntl(wp->pipe_fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
|
if (fcntl(wp->pipe_fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
fatal("fcntl failed");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-rename-session.c,v 1.21 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: cmd-rename-session.c,v 1.19 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -45,18 +45,11 @@ cmd_rename_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;
|
||||||
|
|
||||||
if (data->arg != NULL && session_find(data->arg) != NULL) {
|
|
||||||
ctx->error(ctx, "duplicate session: %s", data->arg);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
RB_REMOVE(sessions, &sessions, s);
|
|
||||||
xfree(s->name);
|
xfree(s->name);
|
||||||
s->name = xstrdup(data->arg);
|
s->name = xstrdup(data->arg);
|
||||||
RB_INSERT(sessions, &sessions, s);
|
|
||||||
|
|
||||||
server_status_session(s);
|
server_status_session(s);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-run-shell.c,v 1.9 2010-08-09 21:44:25 tcunha Exp $ */
|
/* $Id: cmd-run-shell.c,v 1.6 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -82,11 +82,6 @@ cmd_run_shell_callback(struct job *job)
|
|||||||
int retcode;
|
int retcode;
|
||||||
u_int lines;
|
u_int lines;
|
||||||
|
|
||||||
if (ctx->cmdclient != NULL && ctx->cmdclient->flags & CLIENT_DEAD)
|
|
||||||
return;
|
|
||||||
if (ctx->curclient != NULL && ctx->curclient->flags & CLIENT_DEAD)
|
|
||||||
return;
|
|
||||||
|
|
||||||
lines = 0;
|
lines = 0;
|
||||||
do {
|
do {
|
||||||
if ((line = evbuffer_readline(job->event->input)) != NULL) {
|
if ((line = evbuffer_readline(job->event->input)) != NULL) {
|
||||||
@@ -134,7 +129,7 @@ cmd_run_shell_free(void *data)
|
|||||||
|
|
||||||
if (ctx->cmdclient != NULL) {
|
if (ctx->cmdclient != NULL) {
|
||||||
ctx->cmdclient->references--;
|
ctx->cmdclient->references--;
|
||||||
ctx->cmdclient->flags |= CLIENT_EXIT;
|
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
|
||||||
}
|
}
|
||||||
if (ctx->curclient != NULL)
|
if (ctx->curclient != NULL)
|
||||||
ctx->curclient->references--;
|
ctx->curclient->references--;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-save-buffer.c,v 1.12 2010-08-09 21:44:25 tcunha Exp $ */
|
/* $Id: cmd-save-buffer.c,v 1.10 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -47,7 +47,7 @@ cmd_save_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;
|
||||||
mode_t mask;
|
mode_t mask;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
@@ -65,31 +65,24 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(data->arg, "-") == 0) {
|
mask = umask(S_IRWXG | S_IRWXO);
|
||||||
if (ctx->cmdclient == NULL) {
|
if (cmd_check_flag(data->chflags, 'a'))
|
||||||
ctx->error(ctx, "%s: can't write to stdout", data->arg);
|
f = fopen(data->arg, "ab");
|
||||||
return (-1);
|
else
|
||||||
}
|
f = fopen(data->arg, "wb");
|
||||||
bufferevent_write(
|
umask(mask);
|
||||||
ctx->cmdclient->stdout_event, pb->data, pb->size);
|
if (f == NULL) {
|
||||||
} else {
|
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
||||||
mask = umask(S_IRWXG | S_IRWXO);
|
return (-1);
|
||||||
if (cmd_check_flag(data->chflags, 'a'))
|
|
||||||
f = fopen(data->arg, "ab");
|
|
||||||
else
|
|
||||||
f = fopen(data->arg, "wb");
|
|
||||||
umask(mask);
|
|
||||||
if (f == NULL) {
|
|
||||||
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
|
|
||||||
ctx->error(ctx, "%s: fwrite error", data->arg);
|
|
||||||
fclose(f);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
|
||||||
|
ctx->error(ctx, "%s: fwrite error", data->arg);
|
||||||
|
fclose(f);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-select-layout.c,v 1.12 2010-07-02 02:54:52 tcunha Exp $ */
|
/* $Id: cmd-select-layout.c,v 1.10 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -59,9 +59,6 @@ cmd_select_layout_init(struct cmd *self, int key)
|
|||||||
case ('4' | KEYC_ESCAPE):
|
case ('4' | KEYC_ESCAPE):
|
||||||
data->arg = xstrdup("main-vertical");
|
data->arg = xstrdup("main-vertical");
|
||||||
break;
|
break;
|
||||||
case ('5' | KEYC_ESCAPE):
|
|
||||||
data->arg = xstrdup("tiled");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,16 +76,13 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
layout = wl->window->lastlayout;
|
layout = wl->window->lastlayout;
|
||||||
if (layout == -1)
|
if (layout == -1)
|
||||||
return (0);
|
return (0);
|
||||||
} else if ((layout = layout_set_lookup(data->arg)) != -1) {
|
} else if ((layout = layout_set_lookup(data->arg)) == -1) {
|
||||||
layout = layout_set_select(wl->window, layout);
|
ctx->error(ctx, "unknown layout or ambiguous: %s", data->arg);
|
||||||
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
|
return (-1);
|
||||||
} else {
|
|
||||||
if (layout_parse(wl->window, data->arg) == -1) {
|
|
||||||
ctx->error(ctx, "can't set layout: %s", data->arg);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
ctx->info(ctx, "arranging in: %s", data->arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layout = layout_set_select(wl->window, layout);
|
||||||
|
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-select-pane.c,v 1.13 2010-03-15 22:03:38 nicm Exp $ */
|
/* $Id: cmd-select-pane.c,v 1.12 2010-01-05 23:52:37 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -24,40 +24,19 @@
|
|||||||
* Select pane.
|
* Select pane.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void cmd_select_pane_init(struct cmd *, int);
|
|
||||||
int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
|
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",
|
||||||
"[-DLRU] " CMD_TARGET_PANE_USAGE,
|
CMD_TARGET_PANE_USAGE,
|
||||||
0, "DLRU",
|
0, "",
|
||||||
cmd_select_pane_init,
|
cmd_target_init,
|
||||||
cmd_target_parse,
|
cmd_target_parse,
|
||||||
cmd_select_pane_exec,
|
cmd_select_pane_exec,
|
||||||
cmd_target_free,
|
cmd_target_free,
|
||||||
cmd_target_print
|
cmd_target_print
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
|
||||||
cmd_select_pane_init(struct cmd *self, int key)
|
|
||||||
{
|
|
||||||
struct cmd_target_data *data;
|
|
||||||
|
|
||||||
cmd_target_init(self, key);
|
|
||||||
data = self->data;
|
|
||||||
|
|
||||||
if (key == KEYC_UP)
|
|
||||||
cmd_set_flag(&data->chflags, 'U');
|
|
||||||
if (key == KEYC_DOWN)
|
|
||||||
cmd_set_flag(&data->chflags, 'D');
|
|
||||||
if (key == KEYC_LEFT)
|
|
||||||
cmd_set_flag(&data->chflags, 'L');
|
|
||||||
if (key == KEYC_RIGHT)
|
|
||||||
cmd_set_flag(&data->chflags, 'R');
|
|
||||||
if (key == 'o')
|
|
||||||
data->target = xstrdup(":.+");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
@@ -72,20 +51,6 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
ctx->error(ctx, "pane not visible: %s", data->target);
|
ctx->error(ctx, "pane not visible: %s", data->target);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd_check_flag(data->chflags, 'L'))
|
|
||||||
wp = window_pane_find_left(wp);
|
|
||||||
else if (cmd_check_flag(data->chflags, 'R'))
|
|
||||||
wp = window_pane_find_right(wp);
|
|
||||||
else if (cmd_check_flag(data->chflags, 'U'))
|
|
||||||
wp = window_pane_find_up(wp);
|
|
||||||
else if (cmd_check_flag(data->chflags, 'D'))
|
|
||||||
wp = window_pane_find_down(wp);
|
|
||||||
if (wp == NULL) {
|
|
||||||
ctx->error(ctx, "pane not found");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
window_set_active_pane(wl->window, wp);
|
window_set_active_pane(wl->window, wp);
|
||||||
server_status_window(wl->window);
|
server_status_window(wl->window);
|
||||||
server_redraw_window_borders(wl->window);
|
server_redraw_window_borders(wl->window);
|
||||||
|
|||||||
91
cmd-select-prompt.c
Normal file
91
cmd-select-prompt.c
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/* $Id: cmd-select-prompt.c,v 1.13 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prompt for window index and select it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int cmd_select_prompt_exec(struct cmd *, struct cmd_ctx *);
|
||||||
|
|
||||||
|
int cmd_select_prompt_callback(void *, const char *);
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_select_prompt_entry = {
|
||||||
|
"select-prompt", NULL,
|
||||||
|
CMD_TARGET_CLIENT_USAGE,
|
||||||
|
0, "",
|
||||||
|
cmd_target_init,
|
||||||
|
cmd_target_parse,
|
||||||
|
cmd_select_prompt_exec,
|
||||||
|
cmd_target_free,
|
||||||
|
cmd_target_print
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
cmd_select_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct cmd_target_data *data = self->data;
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
|
if ((c = cmd_find_client(ctx, data->target)) == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
if (c->prompt_string != NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
status_prompt_set(c, "index ", cmd_select_prompt_callback, NULL, c, 0);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cmd_select_prompt_callback(void *data, const char *s)
|
||||||
|
{
|
||||||
|
struct client *c = data;
|
||||||
|
const char *errstr;
|
||||||
|
char msg[128];
|
||||||
|
u_int idx;
|
||||||
|
|
||||||
|
if (s == NULL || *s == '\0')
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
idx = strtonum(s, 0, UINT_MAX, &errstr);
|
||||||
|
if (errstr != NULL) {
|
||||||
|
xsnprintf(msg, sizeof msg, "Index %s: %s", errstr, s);
|
||||||
|
status_message_set(c, "%s", msg);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (winlink_find_by_index(&c->session->windows, idx) == NULL) {
|
||||||
|
xsnprintf(msg, sizeof msg,
|
||||||
|
"Window not found: %s:%d", c->session->name, idx);
|
||||||
|
status_message_set(c, "%s", msg);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session_select(c->session, idx) == 0)
|
||||||
|
server_redraw_session(c->session);
|
||||||
|
recalculate_sizes();
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-send-keys.c,v 1.25 2010-05-22 21:56:04 micahcowan Exp $ */
|
/* $Id: cmd-send-keys.c,v 1.24 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -105,17 +105,16 @@ 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 window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct session *s;
|
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (cmd_find_pane(ctx, data->target, &s, &wp) == 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(wp, s, data->keys[i]);
|
window_pane_key(wp, ctx->curclient, data->keys[i]);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-send-prefix.c,v 1.29 2010-05-22 21:56:04 micahcowan Exp $ */
|
/* $Id: cmd-send-prefix.c,v 1.28 2009-11-14 17:56:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -49,7 +49,7 @@ cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
keylist = options_get_data(&s->options, "prefix");
|
keylist = options_get_data(&s->options, "prefix");
|
||||||
window_pane_key(wp, s, ARRAY_FIRST(keylist));
|
window_pane_key(wp, ctx->curclient, ARRAY_FIRST(keylist));
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-server-info.c,v 1.38 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: cmd-server-info.c,v 1.37 2009-12-10 16:59:02 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -81,6 +81,8 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
else
|
else
|
||||||
ctx->print(ctx, "configuration file not specified");
|
ctx->print(ctx, "configuration file not specified");
|
||||||
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",
|
||||||
|
ARRAY_LENGTH(&clients), ARRAY_LENGTH(&sessions));
|
||||||
ctx->print(ctx, "%s", "");
|
ctx->print(ctx, "%s", "");
|
||||||
|
|
||||||
ctx->print(ctx, "Clients:");
|
ctx->print(ctx, "Clients:");
|
||||||
@@ -99,14 +101,19 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
|
|
||||||
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));
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
|
if (s == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
t = s->creation_time.tv_sec;
|
t = s->creation_time.tv_sec;
|
||||||
tim = ctime(&t);
|
tim = ctime(&t);
|
||||||
*strchr(tim, '\n') = '\0';
|
*strchr(tim, '\n') = '\0';
|
||||||
|
|
||||||
ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] "
|
ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] "
|
||||||
"[flags=0x%x]", s->idx, s->name,
|
"[flags=0x%x, references=%u]", i, s->name,
|
||||||
winlink_count(&s->windows), 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: %s [%ux%u] [flags=0x%x, "
|
ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, "
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-set-option.c,v 1.102 2010-12-22 15:23:59 tcunha Exp $ */
|
/* $Id: cmd-set-option.c,v 1.96 2010-02-26 13:31:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -75,7 +75,6 @@ const char *set_option_bell_action_list[] = {
|
|||||||
|
|
||||||
const struct set_option_entry set_option_table[] = {
|
const struct set_option_entry set_option_table[] = {
|
||||||
{ "escape-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
|
{ "escape-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
|
||||||
{ "exit-unattached", SET_OPTION_FLAG, 0, 0, NULL },
|
|
||||||
{ "quiet", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "quiet", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ NULL, 0, 0, 0, NULL }
|
{ NULL, 0, 0, 0, NULL }
|
||||||
};
|
};
|
||||||
@@ -88,8 +87,6 @@ const struct set_option_entry set_session_option_table[] = {
|
|||||||
{ "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-shell", SET_OPTION_STRING, 0, 0, NULL },
|
||||||
{ "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
|
{ "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
|
||||||
{ "destroy-unattached", SET_OPTION_FLAG, 0, 0, NULL },
|
|
||||||
{ "detach-on-destroy", SET_OPTION_FLAG, 0, 0, NULL },
|
|
||||||
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
|
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||||
{ "display-panes-active-colour", SET_OPTION_COLOUR, 0, 0, NULL },
|
{ "display-panes-active-colour", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||||
{ "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
|
{ "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
|
||||||
@@ -136,7 +133,6 @@ const struct set_option_entry set_session_option_table[] = {
|
|||||||
{ "visual-activity", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "visual-activity", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "visual-bell", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "visual-bell", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "visual-silence", SET_OPTION_FLAG, 0, 0, NULL },
|
|
||||||
{ NULL, 0, 0, 0, NULL }
|
{ NULL, 0, 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -158,15 +154,9 @@ const struct set_option_entry set_window_option_table[] = {
|
|||||||
{ "mode-mouse", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "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 },
|
{ "monitor-content", SET_OPTION_STRING, 0, 0, NULL },
|
||||||
{ "monitor-silence",SET_OPTION_NUMBER, 0, INT_MAX, NULL},
|
|
||||||
{ "other-pane-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
|
|
||||||
{ "other-pane-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
|
|
||||||
{ "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "synchronize-panes", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "synchronize-panes", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "utf8", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "utf8", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "window-status-alert-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
|
||||||
{ "window-status-alert-bg", SET_OPTION_COLOUR, 0, 0, NULL },
|
|
||||||
{ "window-status-alert-fg", SET_OPTION_COLOUR, 0, 0, NULL },
|
|
||||||
{ "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
{ "window-status-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-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
||||||
@@ -299,7 +289,6 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
*/
|
*/
|
||||||
if (strcmp(entry->name, "status-left") == 0 ||
|
if (strcmp(entry->name, "status-left") == 0 ||
|
||||||
strcmp(entry->name, "status-right") == 0 ||
|
strcmp(entry->name, "status-right") == 0 ||
|
||||||
strcmp(entry->name, "status") == 0 ||
|
|
||||||
strcmp(entry->name, "set-titles-string") == 0 ||
|
strcmp(entry->name, "set-titles-string") == 0 ||
|
||||||
strcmp(entry->name, "window-status-format") == 0) {
|
strcmp(entry->name, "window-status-format") == 0) {
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-split-window.c,v 1.35 2010-07-02 02:49:19 tcunha Exp $ */
|
/* $Id: cmd-split-window.c,v 1.34 2010-01-08 16:31:35 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -169,13 +169,10 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
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");
|
||||||
cwd = options_get_string(&s->options, "default-path");
|
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
|
||||||
if (*cwd == '\0') {
|
cwd = options_get_string(&s->options, "default-path");
|
||||||
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
|
else
|
||||||
cwd = ctx->cmdclient->cwd;
|
cwd = ctx->cmdclient->cwd;
|
||||||
else
|
|
||||||
cwd = s->cwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
type = LAYOUT_TOPBOTTOM;
|
type = LAYOUT_TOPBOTTOM;
|
||||||
if (data->flag_horizontal)
|
if (data->flag_horizontal)
|
||||||
|
|||||||
32
cmd-string.c
32
cmd-string.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-string.c,v 1.32 2010-12-13 22:53:56 nicm Exp $ */
|
/* $Id: cmd-string.c,v 1.31 2010-02-26 13:27:38 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -247,10 +247,9 @@ error:
|
|||||||
char *
|
char *
|
||||||
cmd_string_variable(const char *s, size_t *p)
|
cmd_string_variable(const char *s, size_t *p)
|
||||||
{
|
{
|
||||||
int ch, fch;
|
int ch, fch;
|
||||||
char *buf, *t;
|
char *buf, *t;
|
||||||
size_t len;
|
size_t len;
|
||||||
struct environ_entry *envent;
|
|
||||||
|
|
||||||
#define cmd_string_first(ch) ((ch) == '_' || \
|
#define cmd_string_first(ch) ((ch) == '_' || \
|
||||||
((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z'))
|
((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z'))
|
||||||
@@ -302,11 +301,12 @@ cmd_string_variable(const char *s, size_t *p)
|
|||||||
buf = xrealloc(buf, 1, len + 1);
|
buf = xrealloc(buf, 1, len + 1);
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
|
|
||||||
envent = environ_find(&global_environ, buf);
|
if ((t = getenv(buf)) == NULL) {
|
||||||
xfree(buf);
|
xfree(buf);
|
||||||
if (envent == NULL)
|
|
||||||
return (xstrdup(""));
|
return (xstrdup(""));
|
||||||
return (xstrdup(envent->value));
|
}
|
||||||
|
xfree(buf);
|
||||||
|
return (xstrdup(t));
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (buf != NULL)
|
if (buf != NULL)
|
||||||
@@ -317,17 +317,15 @@ error:
|
|||||||
char *
|
char *
|
||||||
cmd_string_expand_tilde(const char *s, size_t *p)
|
cmd_string_expand_tilde(const char *s, size_t *p)
|
||||||
{
|
{
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct environ_entry *envent;
|
char *home, *path, *username;
|
||||||
char *home, *path, *username;
|
|
||||||
|
|
||||||
home = NULL;
|
home = NULL;
|
||||||
if (cmd_string_getc(s, p) == '/') {
|
if (cmd_string_getc(s, p) == '/') {
|
||||||
envent = environ_find(&global_environ, "HOME");
|
if ((home = getenv("HOME")) == NULL || *home == '\0') {
|
||||||
if (envent != NULL && *envent->value != '\0')
|
if ((pw = getpwuid(getuid())) != NULL)
|
||||||
home = envent->value;
|
home = pw->pw_dir;
|
||||||
else if ((pw = getpwuid(getuid())) != NULL)
|
}
|
||||||
home = pw->pw_dir;
|
|
||||||
} else {
|
} else {
|
||||||
cmd_string_ungetc(p);
|
cmd_string_ungetc(p);
|
||||||
if ((username = cmd_string_string(s, p, '/', 0)) == NULL)
|
if ((username = cmd_string_string(s, p, '/', 0)) == NULL)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-switch-client.c,v 1.23 2010-12-22 15:31:00 tcunha Exp $ */
|
/* $Id: cmd-switch-client.c,v 1.19 2010-01-25 17:12:44 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -27,7 +27,6 @@
|
|||||||
* Switch client to a different session.
|
* Switch client to a different session.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void cmd_switch_client_init(struct cmd *, int);
|
|
||||||
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_free(struct cmd *);
|
void cmd_switch_client_free(struct cmd *);
|
||||||
@@ -36,83 +35,36 @@ size_t cmd_switch_client_print(struct cmd *, char *, size_t);
|
|||||||
struct cmd_switch_client_data {
|
struct cmd_switch_client_data {
|
||||||
char *name;
|
char *name;
|
||||||
char *target;
|
char *target;
|
||||||
int flag_last;
|
|
||||||
int flag_next;
|
|
||||||
int flag_previous;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct cmd_entry cmd_switch_client_entry = {
|
const struct cmd_entry cmd_switch_client_entry = {
|
||||||
"switch-client", "switchc",
|
"switch-client", "switchc",
|
||||||
"[-lnp] [-c target-client] [-t target-session]",
|
"[-c target-client] [-t target-session]",
|
||||||
0, "",
|
0, "",
|
||||||
cmd_switch_client_init,
|
NULL,
|
||||||
cmd_switch_client_parse,
|
cmd_switch_client_parse,
|
||||||
cmd_switch_client_exec,
|
cmd_switch_client_exec,
|
||||||
cmd_switch_client_free,
|
cmd_switch_client_free,
|
||||||
cmd_switch_client_print
|
cmd_switch_client_print
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
|
||||||
cmd_switch_client_init(struct cmd *self, int key)
|
|
||||||
{
|
|
||||||
struct cmd_switch_client_data *data;
|
|
||||||
|
|
||||||
self->data = data = xmalloc(sizeof *data);
|
|
||||||
data->name = NULL;
|
|
||||||
data->target = NULL;
|
|
||||||
data->flag_last = 0;
|
|
||||||
data->flag_next = 0;
|
|
||||||
data->flag_previous = 0;
|
|
||||||
|
|
||||||
switch (key) {
|
|
||||||
case '(':
|
|
||||||
data->flag_previous = 1;
|
|
||||||
break;
|
|
||||||
case ')':
|
|
||||||
data->flag_next = 1;
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
data->flag_last = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_switch_client_parse(struct cmd *self, int argc, char **argv, char **cause)
|
cmd_switch_client_parse(struct cmd *self, int argc, char **argv, char **cause)
|
||||||
{
|
{
|
||||||
struct cmd_switch_client_data *data;
|
struct cmd_switch_client_data *data;
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
self->entry->init(self, KEYC_NONE);
|
self->data = data = xmalloc(sizeof *data);
|
||||||
data = self->data;
|
data->name = NULL;
|
||||||
|
data->target = NULL;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "c:lnpt:")) != -1) {
|
while ((opt = getopt(argc, argv, "c:t:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'c':
|
case 'c':
|
||||||
if (data->name == NULL)
|
if (data->name == NULL)
|
||||||
data->name = xstrdup(optarg);
|
data->name = xstrdup(optarg);
|
||||||
break;
|
break;
|
||||||
case 'l':
|
|
||||||
if (data->flag_next || data->flag_previous ||
|
|
||||||
data->target != NULL)
|
|
||||||
goto usage;
|
|
||||||
data->flag_last = 1;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
if (data->flag_previous || data->flag_last ||
|
|
||||||
data->target != NULL)
|
|
||||||
goto usage;
|
|
||||||
data->flag_next = 1;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
if (data->flag_next || data->flag_last ||
|
|
||||||
data->target != NULL)
|
|
||||||
goto usage;
|
|
||||||
data->flag_next = 1;
|
|
||||||
break;
|
|
||||||
case 't':
|
case 't':
|
||||||
if (data->flag_next || data->flag_previous)
|
|
||||||
goto usage;
|
|
||||||
if (data->target == NULL)
|
if (data->target == NULL)
|
||||||
data->target = xstrdup(optarg);
|
data->target = xstrdup(optarg);
|
||||||
break;
|
break;
|
||||||
@@ -146,36 +98,12 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
|
|
||||||
if ((c = cmd_find_client(ctx, data->name)) == NULL)
|
if ((c = cmd_find_client(ctx, data->name)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
s = NULL;
|
|
||||||
if (data->flag_next) {
|
|
||||||
if ((s = session_next_session(c->session)) == NULL) {
|
|
||||||
ctx->error(ctx, "can't find next session");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
} else if (data->flag_previous) {
|
|
||||||
if ((s = session_previous_session(c->session)) == NULL) {
|
|
||||||
ctx->error(ctx, "can't find previous session");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
} else if (data->flag_last) {
|
|
||||||
if (c->last_session != NULL && session_alive(c->last_session))
|
|
||||||
s = c->last_session;
|
|
||||||
if (s == NULL) {
|
|
||||||
ctx->error(ctx, "can't find last session");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
s = cmd_find_session(ctx, data->target);
|
|
||||||
if (s == NULL)
|
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (c->session != NULL)
|
|
||||||
c->last_session = c->session;
|
|
||||||
c->session = s;
|
c->session = s;
|
||||||
|
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
server_check_unattached();
|
|
||||||
server_redraw_client(c);
|
server_redraw_client(c);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@@ -202,12 +130,6 @@ cmd_switch_client_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);
|
||||||
if (off < len && data->flag_last)
|
|
||||||
off += xsnprintf(buf + off, len - off, "%s", " -l");
|
|
||||||
if (off < len && data->flag_next)
|
|
||||||
off += xsnprintf(buf + off, len - off, "%s", " -n");
|
|
||||||
if (off < len && data->flag_previous)
|
|
||||||
off += xsnprintf(buf + off, len - off, "%s", " -p");
|
|
||||||
if (off < len && data->name != NULL)
|
if (off < len && data->name != NULL)
|
||||||
off += cmd_prarg(buf + off, len - off, " -c ", data->name);
|
off += cmd_prarg(buf + off, len - off, " -c ", data->name);
|
||||||
if (off < len && data->target != NULL)
|
if (off < len && data->target != NULL)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-unbind-key.c,v 1.23 2010-12-06 21:51:02 nicm Exp $ */
|
/* $Id: cmd-unbind-key.c,v 1.22 2010-01-25 17:12:44 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -33,14 +33,13 @@ 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 flag_all;
|
|
||||||
int command_key;
|
int command_key;
|
||||||
char *tablename;
|
char *tablename;
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct cmd_entry cmd_unbind_key_entry = {
|
const struct cmd_entry cmd_unbind_key_entry = {
|
||||||
"unbind-key", "unbind",
|
"unbind-key", "unbind",
|
||||||
"[-acn] [-t key-table] key",
|
"[-cn] [-t key-table] key",
|
||||||
0, "",
|
0, "",
|
||||||
NULL,
|
NULL,
|
||||||
cmd_unbind_key_parse,
|
cmd_unbind_key_parse,
|
||||||
@@ -56,15 +55,11 @@ cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
int opt, no_prefix = 0;
|
int opt, no_prefix = 0;
|
||||||
|
|
||||||
self->data = data = xmalloc(sizeof *data);
|
self->data = data = xmalloc(sizeof *data);
|
||||||
data->flag_all = 0;
|
|
||||||
data->command_key = 0;
|
data->command_key = 0;
|
||||||
data->tablename = NULL;
|
data->tablename = NULL;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "acnt:")) != -1) {
|
while ((opt = getopt(argc, argv, "cnt:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'a':
|
|
||||||
data->flag_all = 1;
|
|
||||||
break;
|
|
||||||
case 'c':
|
case 'c':
|
||||||
data->command_key = 1;
|
data->command_key = 1;
|
||||||
break;
|
break;
|
||||||
@@ -81,20 +76,15 @@ cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
}
|
}
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
if (data->flag_all && (argc != 0 || data->tablename))
|
if (argc != 1)
|
||||||
goto usage;
|
|
||||||
if (!data->flag_all && argc != 1)
|
|
||||||
goto usage;
|
goto usage;
|
||||||
|
|
||||||
if (!data->flag_all) {
|
if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) {
|
||||||
data->key = key_string_lookup_string(argv[0]);
|
xasprintf(cause, "unknown key: %s", argv[0]);
|
||||||
if (data->key == KEYC_NONE) {
|
goto error;
|
||||||
xasprintf(cause, "unknown key: %s", argv[0]);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (!no_prefix)
|
|
||||||
data->key |= KEYC_PREFIX;
|
|
||||||
}
|
}
|
||||||
|
if (!no_prefix)
|
||||||
|
data->key |= KEYC_PREFIX;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
@@ -110,23 +100,13 @@ int
|
|||||||
cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
|
cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct cmd_unbind_key_data *data = self->data;
|
struct cmd_unbind_key_data *data = self->data;
|
||||||
struct key_binding *bd;
|
|
||||||
|
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
if (data->flag_all) {
|
if (data->tablename != NULL)
|
||||||
while (!SPLAY_EMPTY(&key_bindings)) {
|
return (cmd_unbind_key_table(self, ctx));
|
||||||
bd = SPLAY_ROOT(&key_bindings);
|
|
||||||
SPLAY_REMOVE(key_bindings, &key_bindings, bd);
|
|
||||||
cmd_list_free(bd->cmdlist);
|
|
||||||
xfree(bd);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
60
cmd-up-pane.c
Normal file
60
cmd-up-pane.c
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/* $Id: cmd-up-pane.c,v 1.14 2010-01-05 23:52:37 tcunha Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move up a pane.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int cmd_up_pane_exec(struct cmd *, struct cmd_ctx *);
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_up_pane_entry = {
|
||||||
|
"up-pane", "upp",
|
||||||
|
CMD_TARGET_WINDOW_USAGE,
|
||||||
|
0, "",
|
||||||
|
cmd_target_init,
|
||||||
|
cmd_target_parse,
|
||||||
|
cmd_up_pane_exec,
|
||||||
|
cmd_target_free,
|
||||||
|
cmd_target_print
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
cmd_up_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct cmd_target_data *data = self->data;
|
||||||
|
struct winlink *wl;
|
||||||
|
struct window *w;
|
||||||
|
|
||||||
|
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
|
||||||
|
return (-1);
|
||||||
|
w = wl->window;
|
||||||
|
|
||||||
|
do {
|
||||||
|
w->active = TAILQ_PREV(w->active, window_panes, entry);
|
||||||
|
if (w->active == NULL)
|
||||||
|
w->active = TAILQ_LAST(&w->panes, window_panes);
|
||||||
|
} while (!window_pane_visible(w->active));
|
||||||
|
server_status_window(wl->window);
|
||||||
|
server_redraw_window_borders(wl->window);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
252
cmd.c
252
cmd.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd.c,v 1.146 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: cmd.c,v 1.137 2010-01-22 17:28:34 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -31,7 +31,6 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_bind_key_entry,
|
&cmd_bind_key_entry,
|
||||||
&cmd_break_pane_entry,
|
&cmd_break_pane_entry,
|
||||||
&cmd_capture_pane_entry,
|
&cmd_capture_pane_entry,
|
||||||
&cmd_choose_buffer_entry,
|
|
||||||
&cmd_choose_client_entry,
|
&cmd_choose_client_entry,
|
||||||
&cmd_choose_session_entry,
|
&cmd_choose_session_entry,
|
||||||
&cmd_choose_window_entry,
|
&cmd_choose_window_entry,
|
||||||
@@ -45,6 +44,7 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_detach_client_entry,
|
&cmd_detach_client_entry,
|
||||||
&cmd_display_message_entry,
|
&cmd_display_message_entry,
|
||||||
&cmd_display_panes_entry,
|
&cmd_display_panes_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_if_shell_entry,
|
||||||
@@ -53,7 +53,6 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_kill_server_entry,
|
&cmd_kill_server_entry,
|
||||||
&cmd_kill_session_entry,
|
&cmd_kill_session_entry,
|
||||||
&cmd_kill_window_entry,
|
&cmd_kill_window_entry,
|
||||||
&cmd_last_pane_entry,
|
|
||||||
&cmd_last_window_entry,
|
&cmd_last_window_entry,
|
||||||
&cmd_link_window_entry,
|
&cmd_link_window_entry,
|
||||||
&cmd_list_buffers_entry,
|
&cmd_list_buffers_entry,
|
||||||
@@ -86,6 +85,7 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_save_buffer_entry,
|
&cmd_save_buffer_entry,
|
||||||
&cmd_select_layout_entry,
|
&cmd_select_layout_entry,
|
||||||
&cmd_select_pane_entry,
|
&cmd_select_pane_entry,
|
||||||
|
&cmd_select_prompt_entry,
|
||||||
&cmd_select_window_entry,
|
&cmd_select_window_entry,
|
||||||
&cmd_send_keys_entry,
|
&cmd_send_keys_entry,
|
||||||
&cmd_send_prefix_entry,
|
&cmd_send_prefix_entry,
|
||||||
@@ -108,19 +108,16 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_switch_client_entry,
|
&cmd_switch_client_entry,
|
||||||
&cmd_unbind_key_entry,
|
&cmd_unbind_key_entry,
|
||||||
&cmd_unlink_window_entry,
|
&cmd_unlink_window_entry,
|
||||||
|
&cmd_up_pane_entry,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct session *cmd_choose_session_list(struct sessionslist *);
|
struct session *cmd_choose_session(struct sessions *);
|
||||||
struct session *cmd_choose_session(void);
|
|
||||||
struct client *cmd_choose_client(struct clients *);
|
struct client *cmd_choose_client(struct clients *);
|
||||||
struct client *cmd_lookup_client(const char *);
|
struct client *cmd_lookup_client(const char *);
|
||||||
struct session *cmd_lookup_session(const char *, int *);
|
struct session *cmd_lookup_session(const char *, int *);
|
||||||
struct winlink *cmd_lookup_window(struct 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_lookup_index(struct session *, const char *, int *);
|
||||||
struct winlink *cmd_find_window_offset(const char *, struct session *, int *);
|
|
||||||
int cmd_find_index_offset(const char *, struct session *, int *);
|
|
||||||
struct window_pane *cmd_find_pane_offset(const char *, struct winlink *);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
|
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
|
||||||
@@ -166,22 +163,6 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char **
|
|
||||||
cmd_copy_argv(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char **new_argv;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (argc == 0)
|
|
||||||
return (NULL);
|
|
||||||
new_argv = xcalloc(argc, sizeof *new_argv);
|
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
if (argv[i] != NULL)
|
|
||||||
new_argv[i] = xstrdup(argv[i]);
|
|
||||||
}
|
|
||||||
return (new_argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
cmd_free_argv(int argc, char **argv)
|
cmd_free_argv(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -316,9 +297,10 @@ cmd_current_session(struct cmd_ctx *ctx)
|
|||||||
struct msg_command_data *data = ctx->msgdata;
|
struct msg_command_data *data = ctx->msgdata;
|
||||||
struct client *c = ctx->cmdclient;
|
struct client *c = ctx->cmdclient;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct sessionslist ss;
|
struct sessions ss;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
|
u_int i;
|
||||||
int found;
|
int found;
|
||||||
|
|
||||||
if (ctx->curclient != NULL && ctx->curclient->session != NULL)
|
if (ctx->curclient != NULL && ctx->curclient->session != NULL)
|
||||||
@@ -331,7 +313,9 @@ cmd_current_session(struct cmd_ctx *ctx)
|
|||||||
*/
|
*/
|
||||||
if (c != NULL && c->tty.path != NULL) {
|
if (c != NULL && c->tty.path != NULL) {
|
||||||
ARRAY_INIT(&ss);
|
ARRAY_INIT(&ss);
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
|
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
||||||
|
continue;
|
||||||
found = 0;
|
found = 0;
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||||
@@ -347,43 +331,29 @@ cmd_current_session(struct cmd_ctx *ctx)
|
|||||||
ARRAY_ADD(&ss, s);
|
ARRAY_ADD(&ss, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = cmd_choose_session_list(&ss);
|
s = cmd_choose_session(&ss);
|
||||||
ARRAY_FREE(&ss);
|
ARRAY_FREE(&ss);
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the session from the TMUX environment variable. */
|
/* Use the session from the TMUX environment variable. */
|
||||||
if (data != NULL && data->pid == getpid()) {
|
if (data != NULL && data->pid != -1) {
|
||||||
s = session_find_by_index(data->idx);
|
if (data->pid != getpid())
|
||||||
if (s != NULL)
|
return (NULL);
|
||||||
return (s);
|
if (data->idx > ARRAY_LENGTH(&sessions))
|
||||||
|
return (NULL);
|
||||||
|
if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (cmd_choose_session());
|
return (cmd_choose_session(&sessions));
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the most recently used session. */
|
|
||||||
struct session *
|
|
||||||
cmd_choose_session(void)
|
|
||||||
{
|
|
||||||
struct session *s, *sbest;
|
|
||||||
struct timeval *tv = NULL;
|
|
||||||
|
|
||||||
sbest = NULL;
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
|
||||||
if (tv == NULL || timercmp(&s->activity_time, tv, >)) {
|
|
||||||
sbest = s;
|
|
||||||
tv = &s->activity_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (sbest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the most recently used session from a list. */
|
/* Find the most recently used session from a list. */
|
||||||
struct session *
|
struct session *
|
||||||
cmd_choose_session_list(struct sessionslist *ss)
|
cmd_choose_session(struct sessions *ss)
|
||||||
{
|
{
|
||||||
struct session *s, *sbest;
|
struct session *s, *sbest;
|
||||||
struct timeval *tv = NULL;
|
struct timeval *tv = NULL;
|
||||||
@@ -531,6 +501,7 @@ struct session *
|
|||||||
cmd_lookup_session(const char *name, int *ambiguous)
|
cmd_lookup_session(const char *name, int *ambiguous)
|
||||||
{
|
{
|
||||||
struct session *s, *sfound;
|
struct session *s, *sfound;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
*ambiguous = 0;
|
*ambiguous = 0;
|
||||||
|
|
||||||
@@ -539,15 +510,21 @@ cmd_lookup_session(const char *name, int *ambiguous)
|
|||||||
* be unique so an exact match can't be ambigious and can just be
|
* be unique so an exact match can't be ambigious and can just be
|
||||||
* returned.
|
* returned.
|
||||||
*/
|
*/
|
||||||
if ((s = session_find(name)) != NULL)
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
return (s);
|
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
||||||
|
continue;
|
||||||
|
if (strcmp(name, s->name) == 0)
|
||||||
|
return (s);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise look for partial matches, returning early if it is found to
|
* Otherwise look for partial matches, returning early if it is found to
|
||||||
* be ambiguous.
|
* be ambiguous.
|
||||||
*/
|
*/
|
||||||
sfound = NULL;
|
sfound = NULL;
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
|
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
||||||
|
continue;
|
||||||
if (strncmp(name, s->name, strlen(name)) == 0 ||
|
if (strncmp(name, s->name, strlen(name)) == 0 ||
|
||||||
fnmatch(name, s->name, 0) == 0) {
|
fnmatch(name, s->name, 0) == 0) {
|
||||||
if (sfound != NULL) {
|
if (sfound != NULL) {
|
||||||
@@ -563,7 +540,7 @@ cmd_lookup_session(const char *name, int *ambiguous)
|
|||||||
/*
|
/*
|
||||||
* Lookup a window or return -1 if not found or ambigious. First try as an
|
* 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
|
* 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 no window with that
|
* idx if the window index is a valid number but there is now window with that
|
||||||
* index.
|
* index.
|
||||||
*/
|
*/
|
||||||
struct winlink *
|
struct winlink *
|
||||||
@@ -730,8 +707,10 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
|
|||||||
wl = s->curw;
|
wl = s->curw;
|
||||||
else if (winptr[0] == '!' && winptr[1] == '\0')
|
else if (winptr[0] == '!' && winptr[1] == '\0')
|
||||||
wl = TAILQ_FIRST(&s->lastw);
|
wl = TAILQ_FIRST(&s->lastw);
|
||||||
else if (winptr[0] == '+' || winptr[0] == '-')
|
else if (winptr[0] == '+' && winptr[1] == '\0')
|
||||||
wl = cmd_find_window_offset(winptr, s, &ambiguous);
|
wl = winlink_next(s->curw);
|
||||||
|
else if (winptr[0] == '-' && winptr[1] == '\0')
|
||||||
|
wl = winlink_previous(s->curw);
|
||||||
else
|
else
|
||||||
wl = cmd_lookup_window(s, winptr, &ambiguous);
|
wl = cmd_lookup_window(s, winptr, &ambiguous);
|
||||||
if (wl == NULL)
|
if (wl == NULL)
|
||||||
@@ -749,28 +728,25 @@ no_colon:
|
|||||||
if (arg[0] == '!' && arg[1] == '\0') {
|
if (arg[0] == '!' && arg[1] == '\0') {
|
||||||
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
} else if (arg[0] == '+' || arg[0] == '-') {
|
} else if (arg[0] == '+' && arg[1] == '\0') {
|
||||||
if ((wl = cmd_find_window_offset(arg, s, &ambiguous)) == NULL)
|
if ((wl = winlink_next(s->curw)) == NULL)
|
||||||
goto lookup_session;
|
goto not_found;
|
||||||
} else if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL)
|
} else if (arg[0] == '-' && arg[1] == '\0') {
|
||||||
goto lookup_session;
|
if ((wl = winlink_previous(s->curw)) == NULL)
|
||||||
|
goto not_found;
|
||||||
|
} else if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL) {
|
||||||
|
if (ambiguous)
|
||||||
|
goto not_found;
|
||||||
|
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
|
||||||
|
goto no_session;
|
||||||
|
wl = s->curw;
|
||||||
|
}
|
||||||
|
|
||||||
if (sp != NULL)
|
if (sp != NULL)
|
||||||
*sp = s;
|
*sp = s;
|
||||||
|
|
||||||
return (wl);
|
return (wl);
|
||||||
|
|
||||||
lookup_session:
|
|
||||||
if (ambiguous)
|
|
||||||
goto not_found;
|
|
||||||
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
|
|
||||||
goto no_session;
|
|
||||||
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
|
|
||||||
return (s->curw);
|
|
||||||
|
|
||||||
no_session:
|
no_session:
|
||||||
if (ambiguous)
|
if (ambiguous)
|
||||||
ctx->error(ctx, "multiple sessions: %s", arg);
|
ctx->error(ctx, "multiple sessions: %s", arg);
|
||||||
@@ -790,26 +766,6 @@ not_found:
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct winlink *
|
|
||||||
cmd_find_window_offset(const char *winptr, struct session *s, int *ambiguous)
|
|
||||||
{
|
|
||||||
struct winlink *wl;
|
|
||||||
int offset = 1;
|
|
||||||
|
|
||||||
if (winptr[1] != '\0')
|
|
||||||
offset = strtonum(winptr + 1, 1, INT_MAX, NULL);
|
|
||||||
if (offset == 0)
|
|
||||||
wl = cmd_lookup_window(s, winptr, ambiguous);
|
|
||||||
else {
|
|
||||||
if (winptr[0] == '+')
|
|
||||||
wl = winlink_next_by_number(s->curw, s, offset);
|
|
||||||
else
|
|
||||||
wl = winlink_previous_by_number(s->curw, s, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the target session and window index, whether or not it exists in the
|
* 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
|
* session. Return -2 on error or -1 if no window index is specified. This is
|
||||||
@@ -871,11 +827,20 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
|
|||||||
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
idx = wl->idx;
|
idx = wl->idx;
|
||||||
} else if (winptr[0] == '+' || winptr[0] == '-') {
|
} else if (winptr[0] == '+' && winptr[1] == '\0') {
|
||||||
if ((idx = cmd_find_index_offset(winptr, s, &ambiguous)) < 0)
|
if (s->curw->idx == INT_MAX)
|
||||||
goto invalid_index;
|
goto not_found;
|
||||||
} else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1)
|
idx = s->curw->idx + 1;
|
||||||
goto invalid_index;
|
} else if (winptr[0] == '-' && winptr[1] == '\0') {
|
||||||
|
if (s->curw->idx == 0)
|
||||||
|
goto not_found;
|
||||||
|
idx = s->curw->idx - 1;
|
||||||
|
} else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1) {
|
||||||
|
if (ambiguous)
|
||||||
|
goto not_found;
|
||||||
|
ctx->error(ctx, "invalid index: %s", arg);
|
||||||
|
idx = -2;
|
||||||
|
}
|
||||||
|
|
||||||
if (sessptr != NULL)
|
if (sessptr != NULL)
|
||||||
xfree(sessptr);
|
xfree(sessptr);
|
||||||
@@ -890,28 +855,27 @@ no_colon:
|
|||||||
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
|
||||||
goto not_found;
|
goto not_found;
|
||||||
idx = wl->idx;
|
idx = wl->idx;
|
||||||
} else if (arg[0] == '+' || arg[0] == '-') {
|
} else if (arg[0] == '+' && arg[1] == '\0') {
|
||||||
if ((idx = cmd_find_index_offset(arg, s, &ambiguous)) < 0)
|
if (s->curw->idx == INT_MAX)
|
||||||
goto lookup_session;
|
goto not_found;
|
||||||
} else if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1)
|
idx = s->curw->idx + 1;
|
||||||
goto lookup_session;
|
} else if (arg[0] == '-' && arg[1] == '\0') {
|
||||||
|
if (s->curw->idx == 0)
|
||||||
|
goto not_found;
|
||||||
|
idx = s->curw->idx - 1;
|
||||||
|
} else if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1) {
|
||||||
|
if (ambiguous)
|
||||||
|
goto not_found;
|
||||||
|
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
|
||||||
|
goto no_session;
|
||||||
|
idx = -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (sp != NULL)
|
if (sp != NULL)
|
||||||
*sp = s;
|
*sp = s;
|
||||||
|
|
||||||
return (idx);
|
return (idx);
|
||||||
|
|
||||||
lookup_session:
|
|
||||||
if (ambiguous)
|
|
||||||
goto not_found;
|
|
||||||
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
|
|
||||||
goto no_session;
|
|
||||||
|
|
||||||
if (sp != NULL)
|
|
||||||
*sp = s;
|
|
||||||
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
no_session:
|
no_session:
|
||||||
if (ambiguous)
|
if (ambiguous)
|
||||||
ctx->error(ctx, "multiple sessions: %s", arg);
|
ctx->error(ctx, "multiple sessions: %s", arg);
|
||||||
@@ -921,15 +885,6 @@ no_session:
|
|||||||
xfree(sessptr);
|
xfree(sessptr);
|
||||||
return (-2);
|
return (-2);
|
||||||
|
|
||||||
invalid_index:
|
|
||||||
if (ambiguous)
|
|
||||||
goto not_found;
|
|
||||||
ctx->error(ctx, "invalid index: %s", arg);
|
|
||||||
|
|
||||||
if (sessptr != NULL)
|
|
||||||
xfree(sessptr);
|
|
||||||
return (-2);
|
|
||||||
|
|
||||||
not_found:
|
not_found:
|
||||||
if (ambiguous)
|
if (ambiguous)
|
||||||
ctx->error(ctx, "multiple windows: %s", arg);
|
ctx->error(ctx, "multiple windows: %s", arg);
|
||||||
@@ -940,32 +895,6 @@ not_found:
|
|||||||
return (-2);
|
return (-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
cmd_find_index_offset(const char *winptr, struct session *s, int *ambiguous)
|
|
||||||
{
|
|
||||||
int idx, offset = 1;
|
|
||||||
|
|
||||||
if (winptr[1] != '\0')
|
|
||||||
offset = strtonum(winptr + 1, 1, INT_MAX, NULL);
|
|
||||||
if (offset == 0)
|
|
||||||
idx = cmd_lookup_index(s, winptr, ambiguous);
|
|
||||||
else {
|
|
||||||
if (winptr[0] == '+') {
|
|
||||||
if (s->curw->idx == INT_MAX)
|
|
||||||
idx = cmd_lookup_index(s, winptr, ambiguous);
|
|
||||||
else
|
|
||||||
idx = s->curw->idx + offset;
|
|
||||||
} else {
|
|
||||||
if (s->curw->idx == 0)
|
|
||||||
idx = cmd_lookup_index(s, winptr, ambiguous);
|
|
||||||
else
|
|
||||||
idx = s->curw->idx - offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the target session, window and pane number or report an error and
|
* 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 .,
|
* return NULL. The pane number is separated from the session:window by a .,
|
||||||
@@ -1012,8 +941,6 @@ cmd_find_pane(struct cmd_ctx *ctx,
|
|||||||
paneptr = winptr + (period - arg) + 1;
|
paneptr = winptr + (period - arg) + 1;
|
||||||
if (*paneptr == '\0')
|
if (*paneptr == '\0')
|
||||||
*wpp = wl->window->active;
|
*wpp = wl->window->active;
|
||||||
else if (paneptr[0] == '+' || paneptr[0] == '-')
|
|
||||||
*wpp = cmd_find_pane_offset(paneptr, wl);
|
|
||||||
else {
|
else {
|
||||||
idx = strtonum(paneptr, 0, INT_MAX, &errstr);
|
idx = strtonum(paneptr, 0, INT_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
@@ -1028,14 +955,14 @@ cmd_find_pane(struct cmd_ctx *ctx,
|
|||||||
|
|
||||||
lookup_string:
|
lookup_string:
|
||||||
/* Try pane string description. */
|
/* Try pane string description. */
|
||||||
if ((lc = layout_find_string(wl->window, paneptr)) == NULL) {
|
if ((lc = layout_find_string(s->curw->window, paneptr)) == NULL) {
|
||||||
ctx->error(ctx, "can't find pane: %s", paneptr);
|
ctx->error(ctx, "can't find pane: %s", paneptr);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
*wpp = lc->wp;
|
*wpp = lc->wp;
|
||||||
|
|
||||||
xfree(winptr);
|
xfree(winptr);
|
||||||
return (wl);
|
return (s->curw);
|
||||||
|
|
||||||
no_period:
|
no_period:
|
||||||
/* Try as a pane number alone. */
|
/* Try as a pane number alone. */
|
||||||
@@ -1066,25 +993,6 @@ error:
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct window_pane *
|
|
||||||
cmd_find_pane_offset(const char *paneptr, struct winlink *wl)
|
|
||||||
{
|
|
||||||
struct window *w = wl->window;
|
|
||||||
struct window_pane *wp = w->active;
|
|
||||||
u_int offset = 1;
|
|
||||||
|
|
||||||
if (paneptr[1] != '\0')
|
|
||||||
offset = strtonum(paneptr + 1, 1, INT_MAX, NULL);
|
|
||||||
if (offset > 0) {
|
|
||||||
if (paneptr[0] == '+')
|
|
||||||
wp = window_pane_next_by_number(w, wp, offset);
|
|
||||||
else
|
|
||||||
wp = window_pane_previous_by_number(w, wp, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace the first %% or %idx in template by s. */
|
/* Replace the first %% or %idx in template by s. */
|
||||||
char *
|
char *
|
||||||
cmd_template_replace(char *template, const char *s, int idx)
|
cmd_template_replace(char *template, const char *s, int idx)
|
||||||
|
|||||||
96
compat.h
96
compat.h
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: compat.h,v 1.31 2010-11-11 20:45:49 nicm Exp $ */
|
/* $Id: compat.h,v 1.20 2009-11-08 22:51:34 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -16,20 +16,6 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef COMPAT_H
|
|
||||||
#define COMPAT_H
|
|
||||||
|
|
||||||
#ifndef __GNUC__
|
|
||||||
#define __attribute__(a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __dead
|
|
||||||
#define __dead __attribute__ ((__noreturn__))
|
|
||||||
#endif
|
|
||||||
#ifndef __packed
|
|
||||||
#define __packed __attribute__ ((__packed__))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_U_INT
|
#ifndef HAVE_U_INT
|
||||||
typedef uint8_t u_int8_t;
|
typedef uint8_t u_int8_t;
|
||||||
typedef uint16_t u_int16_t;
|
typedef uint16_t u_int16_t;
|
||||||
@@ -56,13 +42,21 @@ typedef uint64_t u_int64_t;
|
|||||||
#else
|
#else
|
||||||
#include "compat/tree.h"
|
#include "compat/tree.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_BITSTRING_H
|
#ifdef HAVE_BITSTRING_H
|
||||||
#include <bitstring.h>
|
#include <bitstring.h>
|
||||||
#else
|
#else
|
||||||
#include "compat/bitstring.h"
|
#include "compat/bitstring.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_GETOPT
|
||||||
|
#include <getopt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CRYPT_H
|
||||||
|
#include <crypt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_PATHS_H
|
#ifdef HAVE_PATHS_H
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -85,44 +79,19 @@ typedef uint64_t u_int64_t;
|
|||||||
#include "compat/vis.h"
|
#include "compat/vis.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_IMSG
|
#ifndef HAVE_IMSG
|
||||||
#include <imsg.h>
|
|
||||||
#else
|
|
||||||
#include "compat/imsg.h"
|
#include "compat/imsg.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_STDINT_H
|
|
||||||
#include <stdint.h>
|
|
||||||
#else
|
|
||||||
#include <inttypes.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_BROKEN_CMSG_FIRSTHDR
|
#ifdef HAVE_BROKEN_CMSG_FIRSTHDR
|
||||||
/* CMSG_FIRSTHDR broken on OS X. */
|
/* Broken on OS X. */
|
||||||
#undef CMSG_FIRSTHDR
|
#undef CMSG_FIRSTHDR
|
||||||
#define CMSG_FIRSTHDR(mhdr) \
|
#define CMSG_FIRSTHDR(mhdr) \
|
||||||
((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
|
((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
|
||||||
(struct cmsghdr *)(mhdr)->msg_control : \
|
(struct cmsghdr *)(mhdr)->msg_control : \
|
||||||
(struct cmsghdr *)NULL)
|
(struct cmsghdr *)NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* CMSG_ALIGN, CMSG_SPACE, CMSG_LEN missing from Solaris 9. */
|
|
||||||
#ifndef CMSG_ALIGN
|
|
||||||
#ifdef __sun
|
|
||||||
#define CMSG_ALIGN _CMSG_DATA_ALIGN
|
|
||||||
#else
|
|
||||||
#define CMSG_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long) - 1))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CMSG_SPACE
|
|
||||||
#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CMSG_LEN
|
|
||||||
#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef INFTIM
|
#ifndef INFTIM
|
||||||
#define INFTIM -1
|
#define INFTIM -1
|
||||||
#endif
|
#endif
|
||||||
@@ -135,6 +104,13 @@ typedef uint64_t u_int64_t;
|
|||||||
#define SUN_LEN(sun) (sizeof (sun)->sun_path)
|
#define SUN_LEN(sun) (sizeof (sun)->sun_path)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __dead
|
||||||
|
#define __dead __attribute__ ((__noreturn__))
|
||||||
|
#endif
|
||||||
|
#ifndef __packed
|
||||||
|
#define __packed __attribute__ ((__packed__))
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef timercmp
|
#ifndef timercmp
|
||||||
#define timercmp(tvp, uvp, cmp) \
|
#define timercmp(tvp, uvp, cmp) \
|
||||||
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
||||||
@@ -159,16 +135,7 @@ typedef uint64_t u_int64_t;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_BZERO
|
#ifndef HAVE_BZERO
|
||||||
#undef bzero
|
#define bzero(buf, len) memset((buf), 0, (len));
|
||||||
#define bzero(buf, len) memset(buf, 0, len);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef HAVE_CLOSEFROM
|
|
||||||
/* closefrom.c */
|
|
||||||
#define HAVE_FCNTL_H
|
|
||||||
#define HAVE_DIRENT_H
|
|
||||||
#define HAVE_SYSCONF
|
|
||||||
void closefrom(int);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_STRCASESTR
|
#ifndef HAVE_STRCASESTR
|
||||||
@@ -203,30 +170,21 @@ int daemon(int, int);
|
|||||||
|
|
||||||
#ifndef HAVE_FORKPTY
|
#ifndef HAVE_FORKPTY
|
||||||
/* forkpty.c */
|
/* forkpty.c */
|
||||||
#include <sys/ioctl.h>
|
|
||||||
pid_t forkpty(int *, char *, struct termios *, struct winsize *);
|
pid_t forkpty(int *, char *, struct termios *, struct winsize *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_ASPRINTF
|
#ifndef HAVE_ASPRINTF
|
||||||
/* asprintf.c */
|
/* asprintf.c */
|
||||||
int asprintf(char **, const char *, ...);
|
int asprintf(char **, const char *, ...);
|
||||||
int vasprintf(char **, const char *, va_list);
|
int vasprintf(char **, const char *, va_list);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_FGETLN
|
#ifndef HAVE_FGETLN
|
||||||
/* fgetln.c */
|
/* fgetln.c */
|
||||||
char *fgetln(FILE *, size_t *);
|
char *fgetln(FILE *, size_t *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_SETENV
|
#ifndef HAVE_GETOPT
|
||||||
/* setenv.c */
|
|
||||||
int setenv(const char *, const char *, int);
|
|
||||||
int unsetenv(const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_GETOPT
|
|
||||||
#include <getopt.h>
|
|
||||||
#else
|
|
||||||
/* getopt.c */
|
/* getopt.c */
|
||||||
extern int BSDopterr;
|
extern int BSDopterr;
|
||||||
extern int BSDoptind;
|
extern int BSDoptind;
|
||||||
@@ -241,5 +199,3 @@ int BSDgetopt(int, char *const *, const char *);
|
|||||||
#define optreset BSDoptreset
|
#define optreset BSDoptreset
|
||||||
#define optarg BSDoptarg
|
#define optarg BSDoptarg
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* COMPAT_H */
|
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
/* $Id: closefrom.c,v 1.1 2010-10-27 20:21:01 nicm Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2004-2005 Todd C. Miller <Todd.Miller@courtesan.com>
|
|
||||||
*
|
|
||||||
* 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 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 "tmux.h"
|
|
||||||
|
|
||||||
#ifndef HAVE_CLOSEFROM
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifdef HAVE_FCNTL_H
|
|
||||||
# include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef HAVE_DIRENT_H
|
|
||||||
# include <dirent.h>
|
|
||||||
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
|
||||||
#else
|
|
||||||
# define dirent direct
|
|
||||||
# define NAMLEN(dirent) (dirent)->d_namlen
|
|
||||||
# ifdef HAVE_SYS_NDIR_H
|
|
||||||
# include <sys/ndir.h>
|
|
||||||
# endif
|
|
||||||
# ifdef HAVE_SYS_DIR_H
|
|
||||||
# include <sys/dir.h>
|
|
||||||
# endif
|
|
||||||
# ifdef HAVE_NDIR_H
|
|
||||||
# include <ndir.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPEN_MAX
|
|
||||||
# define OPEN_MAX 256
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $";
|
|
||||||
#endif /* lint */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close all file descriptors greater than or equal to lowfd.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_FCNTL_CLOSEM
|
|
||||||
void
|
|
||||||
closefrom(int lowfd)
|
|
||||||
{
|
|
||||||
(void) fcntl(lowfd, F_CLOSEM, 0);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void
|
|
||||||
closefrom(int lowfd)
|
|
||||||
{
|
|
||||||
long fd, maxfd;
|
|
||||||
#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
|
|
||||||
char fdpath[PATH_MAX], *endp;
|
|
||||||
struct dirent *dent;
|
|
||||||
DIR *dirp;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
/* Check for a /proc/$$/fd directory. */
|
|
||||||
len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
|
|
||||||
if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
|
|
||||||
while ((dent = readdir(dirp)) != NULL) {
|
|
||||||
fd = strtol(dent->d_name, &endp, 10);
|
|
||||||
if (dent->d_name != endp && *endp == '\0' &&
|
|
||||||
fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
|
|
||||||
(void) close((int) fd);
|
|
||||||
}
|
|
||||||
(void) closedir(dirp);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Fall back on sysconf() or getdtablesize(). We avoid checking
|
|
||||||
* resource limits since it is possible to open a file descriptor
|
|
||||||
* and then drop the rlimit such that it is below the open fd.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_SYSCONF
|
|
||||||
maxfd = sysconf(_SC_OPEN_MAX);
|
|
||||||
#else
|
|
||||||
maxfd = getdtablesize();
|
|
||||||
#endif /* HAVE_SYSCONF */
|
|
||||||
if (maxfd < 0)
|
|
||||||
maxfd = OPEN_MAX;
|
|
||||||
|
|
||||||
for (fd = lowfd; fd < maxfd; fd++)
|
|
||||||
(void) close((int) fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_FCNTL_CLOSEM */
|
|
||||||
#endif /* HAVE_CLOSEFROM */
|
|
||||||
@@ -32,6 +32,10 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_PATHS_H
|
||||||
|
#include <paths.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* $Id: imsg-buffer.c,v 1.5 2010-06-06 00:08:28 tcunha Exp $ */
|
/* $Id: imsg-buffer.c,v 1.4 2009-09-15 23:59:40 tcunha Exp $ */
|
||||||
/* $OpenBSD: imsg-buffer.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
|
/* $OpenBSD: imsg-buffer.c,v 1.2 2009/09/15 18:12:51 jacekm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||||
@@ -28,16 +28,16 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
int ibuf_realloc(struct ibuf *, size_t);
|
int buf_realloc(struct buf *, size_t);
|
||||||
void ibuf_enqueue(struct msgbuf *, struct ibuf *);
|
void buf_enqueue(struct msgbuf *, struct buf *);
|
||||||
void ibuf_dequeue(struct msgbuf *, struct ibuf *);
|
void buf_dequeue(struct msgbuf *, struct buf *);
|
||||||
|
|
||||||
struct ibuf *
|
struct buf *
|
||||||
ibuf_open(size_t len)
|
buf_open(size_t len)
|
||||||
{
|
{
|
||||||
struct ibuf *buf;
|
struct buf *buf;
|
||||||
|
|
||||||
if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
|
if ((buf = calloc(1, sizeof(struct buf))) == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
if ((buf->buf = malloc(len)) == NULL) {
|
if ((buf->buf = malloc(len)) == NULL) {
|
||||||
free(buf);
|
free(buf);
|
||||||
@@ -49,15 +49,15 @@ ibuf_open(size_t len)
|
|||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ibuf *
|
struct buf *
|
||||||
ibuf_dynamic(size_t len, size_t max)
|
buf_dynamic(size_t len, size_t max)
|
||||||
{
|
{
|
||||||
struct ibuf *buf;
|
struct buf *buf;
|
||||||
|
|
||||||
if (max < len)
|
if (max < len)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
if ((buf = ibuf_open(len)) == NULL)
|
if ((buf = buf_open(len)) == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
if (max > 0)
|
if (max > 0)
|
||||||
@@ -67,7 +67,7 @@ ibuf_dynamic(size_t len, size_t max)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ibuf_realloc(struct ibuf *buf, size_t len)
|
buf_realloc(struct buf *buf, size_t len)
|
||||||
{
|
{
|
||||||
u_char *b;
|
u_char *b;
|
||||||
|
|
||||||
@@ -87,10 +87,10 @@ ibuf_realloc(struct ibuf *buf, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ibuf_add(struct ibuf *buf, const void *data, size_t len)
|
buf_add(struct buf *buf, const void *data, size_t len)
|
||||||
{
|
{
|
||||||
if (buf->wpos + len > buf->size)
|
if (buf->wpos + len > buf->size)
|
||||||
if (ibuf_realloc(buf, len) == -1)
|
if (buf_realloc(buf, len) == -1)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
memcpy(buf->buf + buf->wpos, data, len);
|
memcpy(buf->buf + buf->wpos, data, len);
|
||||||
@@ -99,12 +99,12 @@ ibuf_add(struct ibuf *buf, const void *data, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
ibuf_reserve(struct ibuf *buf, size_t len)
|
buf_reserve(struct buf *buf, size_t len)
|
||||||
{
|
{
|
||||||
void *b;
|
void *b;
|
||||||
|
|
||||||
if (buf->wpos + len > buf->size)
|
if (buf->wpos + len > buf->size)
|
||||||
if (ibuf_realloc(buf, len) == -1)
|
if (buf_realloc(buf, len) == -1)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
b = buf->buf + buf->wpos;
|
b = buf->buf + buf->wpos;
|
||||||
@@ -113,7 +113,7 @@ ibuf_reserve(struct ibuf *buf, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
|
buf_seek(struct buf *buf, size_t pos, size_t len)
|
||||||
{
|
{
|
||||||
/* only allowed to seek in already written parts */
|
/* only allowed to seek in already written parts */
|
||||||
if (pos + len > buf->wpos)
|
if (pos + len > buf->wpos)
|
||||||
@@ -123,28 +123,28 @@ ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ibuf_size(struct ibuf *buf)
|
buf_size(struct buf *buf)
|
||||||
{
|
{
|
||||||
return (buf->wpos);
|
return (buf->wpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ibuf_left(struct ibuf *buf)
|
buf_left(struct buf *buf)
|
||||||
{
|
{
|
||||||
return (buf->max - buf->wpos);
|
return (buf->max - buf->wpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
|
buf_close(struct msgbuf *msgbuf, struct buf *buf)
|
||||||
{
|
{
|
||||||
ibuf_enqueue(msgbuf, buf);
|
buf_enqueue(msgbuf, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ibuf_write(struct msgbuf *msgbuf)
|
buf_write(struct msgbuf *msgbuf)
|
||||||
{
|
{
|
||||||
struct iovec iov[IOV_MAX];
|
struct iovec iov[IOV_MAX];
|
||||||
struct ibuf *buf;
|
struct buf *buf;
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ ibuf_write(struct msgbuf *msgbuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ibuf_free(struct ibuf *buf)
|
buf_free(struct buf *buf)
|
||||||
{
|
{
|
||||||
free(buf->buf);
|
free(buf->buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
@@ -193,14 +193,14 @@ msgbuf_init(struct msgbuf *msgbuf)
|
|||||||
void
|
void
|
||||||
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
|
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
|
||||||
{
|
{
|
||||||
struct ibuf *buf, *next;
|
struct buf *buf, *next;
|
||||||
|
|
||||||
for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
|
for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
|
||||||
buf = next) {
|
buf = next) {
|
||||||
next = TAILQ_NEXT(buf, entry);
|
next = TAILQ_NEXT(buf, entry);
|
||||||
if (buf->rpos + n >= buf->wpos) {
|
if (buf->rpos + n >= buf->wpos) {
|
||||||
n -= buf->wpos - buf->rpos;
|
n -= buf->wpos - buf->rpos;
|
||||||
ibuf_dequeue(msgbuf, buf);
|
buf_dequeue(msgbuf, buf);
|
||||||
} else {
|
} else {
|
||||||
buf->rpos += n;
|
buf->rpos += n;
|
||||||
n = 0;
|
n = 0;
|
||||||
@@ -211,17 +211,17 @@ msgbuf_drain(struct msgbuf *msgbuf, size_t n)
|
|||||||
void
|
void
|
||||||
msgbuf_clear(struct msgbuf *msgbuf)
|
msgbuf_clear(struct msgbuf *msgbuf)
|
||||||
{
|
{
|
||||||
struct ibuf *buf;
|
struct buf *buf;
|
||||||
|
|
||||||
while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
|
while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
|
||||||
ibuf_dequeue(msgbuf, buf);
|
buf_dequeue(msgbuf, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
msgbuf_write(struct msgbuf *msgbuf)
|
msgbuf_write(struct msgbuf *msgbuf)
|
||||||
{
|
{
|
||||||
struct iovec iov[IOV_MAX];
|
struct iovec iov[IOV_MAX];
|
||||||
struct ibuf *buf;
|
struct buf *buf;
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
@@ -284,14 +284,14 @@ msgbuf_write(struct msgbuf *msgbuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
|
buf_enqueue(struct msgbuf *msgbuf, struct buf *buf)
|
||||||
{
|
{
|
||||||
TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
|
TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
|
||||||
msgbuf->queued++;
|
msgbuf->queued++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
|
buf_dequeue(struct msgbuf *msgbuf, struct buf *buf)
|
||||||
{
|
{
|
||||||
TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
|
TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
|
||||||
|
|
||||||
@@ -299,5 +299,5 @@ ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
|
|||||||
close(buf->fd);
|
close(buf->fd);
|
||||||
|
|
||||||
msgbuf->queued--;
|
msgbuf->queued--;
|
||||||
ibuf_free(buf);
|
buf_free(buf);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* $Id: imsg.c,v 1.7 2010-11-13 16:29:05 nicm Exp $ */
|
/* $Id: imsg.c,v 1.3 2009-08-20 12:54:08 nicm Exp $ */
|
||||||
/* $OpenBSD: imsg.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
|
/* $OpenBSD: imsg.c,v 1.1 2009/08/11 17:18:35 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||||
@@ -79,7 +79,7 @@ imsg_read(struct imsgbuf *ibuf)
|
|||||||
cmsg->cmsg_type == SCM_RIGHTS) {
|
cmsg->cmsg_type == SCM_RIGHTS) {
|
||||||
fd = (*(int *)CMSG_DATA(cmsg));
|
fd = (*(int *)CMSG_DATA(cmsg));
|
||||||
if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) {
|
if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) {
|
||||||
close(fd);
|
/* XXX: this return can leak */
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
ifd->fd = fd;
|
ifd->fd = fd;
|
||||||
@@ -111,7 +111,7 @@ imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
|
|||||||
return (0);
|
return (0);
|
||||||
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
|
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
|
||||||
ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
|
ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
|
||||||
if ((imsg->data = malloc(datalen)) == NULL && datalen != 0)
|
if ((imsg->data = malloc(datalen)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (imsg->hdr.flags & IMSGF_HASFD)
|
if (imsg->hdr.flags & IMSGF_HASFD)
|
||||||
@@ -135,7 +135,7 @@ int
|
|||||||
imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
imsg_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||||
pid_t pid, int fd, void *data, u_int16_t datalen)
|
pid_t pid, int fd, void *data, u_int16_t datalen)
|
||||||
{
|
{
|
||||||
struct ibuf *wbuf;
|
struct buf *wbuf;
|
||||||
|
|
||||||
if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
|
if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -154,7 +154,7 @@ int
|
|||||||
imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||||
pid_t pid, int fd, const struct iovec *iov, int iovcnt)
|
pid_t pid, int fd, const struct iovec *iov, int iovcnt)
|
||||||
{
|
{
|
||||||
struct ibuf *wbuf;
|
struct buf *wbuf;
|
||||||
int i, datalen = 0;
|
int i, datalen = 0;
|
||||||
|
|
||||||
for (i = 0; i < iovcnt; i++)
|
for (i = 0; i < iovcnt; i++)
|
||||||
@@ -175,11 +175,11 @@ imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
struct ibuf *
|
struct buf *
|
||||||
imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
||||||
pid_t pid, u_int16_t datalen)
|
pid_t pid, u_int16_t datalen)
|
||||||
{
|
{
|
||||||
struct ibuf *wbuf;
|
struct buf *wbuf;
|
||||||
struct imsg_hdr hdr;
|
struct imsg_hdr hdr;
|
||||||
|
|
||||||
datalen += IMSG_HEADER_SIZE;
|
datalen += IMSG_HEADER_SIZE;
|
||||||
@@ -193,7 +193,7 @@ imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
|||||||
hdr.peerid = peerid;
|
hdr.peerid = peerid;
|
||||||
if ((hdr.pid = pid) == 0)
|
if ((hdr.pid = pid) == 0)
|
||||||
hdr.pid = ibuf->pid;
|
hdr.pid = ibuf->pid;
|
||||||
if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
|
if ((wbuf = buf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
|
if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
|
||||||
@@ -203,18 +203,18 @@ imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
imsg_add(struct ibuf *msg, void *data, u_int16_t datalen)
|
imsg_add(struct buf *msg, void *data, u_int16_t datalen)
|
||||||
{
|
{
|
||||||
if (datalen)
|
if (datalen)
|
||||||
if (ibuf_add(msg, data, datalen) == -1) {
|
if (buf_add(msg, data, datalen) == -1) {
|
||||||
ibuf_free(msg);
|
buf_free(msg);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
return (datalen);
|
return (datalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
|
imsg_close(struct imsgbuf *ibuf, struct buf *msg)
|
||||||
{
|
{
|
||||||
struct imsg_hdr *hdr;
|
struct imsg_hdr *hdr;
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
|
|||||||
|
|
||||||
hdr->len = (u_int16_t)msg->wpos;
|
hdr->len = (u_int16_t)msg->wpos;
|
||||||
|
|
||||||
ibuf_close(&ibuf->w, msg);
|
buf_close(&ibuf->w, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* $Id: imsg.h,v 1.5 2010-06-06 00:08:28 tcunha Exp $ */
|
/* $Id: imsg.h,v 1.4 2009-09-15 23:59:40 tcunha Exp $ */
|
||||||
/* $OpenBSD: imsg.h,v 1.4 2010/05/26 13:56:07 nicm Exp $ */
|
/* $OpenBSD: imsg.h,v 1.2 2009/09/15 18:12:51 jacekm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
|
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
#define IBUF_READ_SIZE 65535
|
#define READ_BUF_SIZE 65535
|
||||||
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
|
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
|
||||||
#define MAX_IMSGSIZE 16384
|
#define MAX_IMSGSIZE 16384
|
||||||
|
|
||||||
struct ibuf {
|
struct buf {
|
||||||
TAILQ_ENTRY(ibuf) entry;
|
TAILQ_ENTRY(buf) entry;
|
||||||
u_char *buf;
|
u_char *buf;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t max;
|
size_t max;
|
||||||
@@ -36,13 +36,13 @@ struct ibuf {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct msgbuf {
|
struct msgbuf {
|
||||||
TAILQ_HEAD(, ibuf) bufs;
|
TAILQ_HEAD(, buf) bufs;
|
||||||
u_int32_t queued;
|
u_int32_t queued;
|
||||||
int fd;
|
int fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ibuf_read {
|
struct buf_read {
|
||||||
u_char buf[IBUF_READ_SIZE];
|
u_char buf[READ_BUF_SIZE];
|
||||||
u_char *rptr;
|
u_char *rptr;
|
||||||
size_t wpos;
|
size_t wpos;
|
||||||
};
|
};
|
||||||
@@ -54,7 +54,7 @@ struct imsg_fd {
|
|||||||
|
|
||||||
struct imsgbuf {
|
struct imsgbuf {
|
||||||
TAILQ_HEAD(, imsg_fd) fds;
|
TAILQ_HEAD(, imsg_fd) fds;
|
||||||
struct ibuf_read r;
|
struct buf_read r;
|
||||||
struct msgbuf w;
|
struct msgbuf w;
|
||||||
int fd;
|
int fd;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
@@ -78,16 +78,16 @@ struct imsg {
|
|||||||
|
|
||||||
|
|
||||||
/* buffer.c */
|
/* buffer.c */
|
||||||
struct ibuf *ibuf_open(size_t);
|
struct buf *buf_open(size_t);
|
||||||
struct ibuf *ibuf_dynamic(size_t, size_t);
|
struct buf *buf_dynamic(size_t, size_t);
|
||||||
int ibuf_add(struct ibuf *, const void *, size_t);
|
int buf_add(struct buf *, const void *, size_t);
|
||||||
void *ibuf_reserve(struct ibuf *, size_t);
|
void *buf_reserve(struct buf *, size_t);
|
||||||
void *ibuf_seek(struct ibuf *, size_t, size_t);
|
void *buf_seek(struct buf *, size_t, size_t);
|
||||||
size_t ibuf_size(struct ibuf *);
|
size_t buf_size(struct buf *);
|
||||||
size_t ibuf_left(struct ibuf *);
|
size_t buf_left(struct buf *);
|
||||||
void ibuf_close(struct msgbuf *, struct ibuf *);
|
void buf_close(struct msgbuf *, struct buf *);
|
||||||
int ibuf_write(struct msgbuf *);
|
int buf_write(struct msgbuf *);
|
||||||
void ibuf_free(struct ibuf *);
|
void buf_free(struct buf *);
|
||||||
void msgbuf_init(struct msgbuf *);
|
void msgbuf_init(struct msgbuf *);
|
||||||
void msgbuf_clear(struct msgbuf *);
|
void msgbuf_clear(struct msgbuf *);
|
||||||
int msgbuf_write(struct msgbuf *);
|
int msgbuf_write(struct msgbuf *);
|
||||||
@@ -101,10 +101,10 @@ int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
|||||||
int, void *, u_int16_t);
|
int, void *, u_int16_t);
|
||||||
int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
||||||
int, const struct iovec *, int);
|
int, const struct iovec *, int);
|
||||||
struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
struct buf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
|
||||||
u_int16_t);
|
u_int16_t);
|
||||||
int imsg_add(struct ibuf *, void *, u_int16_t);
|
int imsg_add(struct buf *, void *, u_int16_t);
|
||||||
void imsg_close(struct imsgbuf *, struct ibuf *);
|
void imsg_close(struct imsgbuf *, struct buf *);
|
||||||
void imsg_free(struct imsg *);
|
void imsg_free(struct imsg *);
|
||||||
int imsg_flush(struct imsgbuf *);
|
int imsg_flush(struct imsgbuf *);
|
||||||
void imsg_clear(struct imsgbuf *);
|
void imsg_clear(struct imsgbuf *);
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
/* $Id: setenv.c,v 1.2 2010-06-05 18:20:48 nicm Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Dagobert Michelsen
|
|
||||||
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
setenv(const char *name, const char *value, unused int overwrite)
|
|
||||||
{
|
|
||||||
char *newval;
|
|
||||||
|
|
||||||
xasprintf(&newval, "%s=%s", name, value);
|
|
||||||
return (putenv(newval));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
unsetenv(const char *name)
|
|
||||||
{
|
|
||||||
char **envptr;
|
|
||||||
int namelen;
|
|
||||||
|
|
||||||
namelen = strlen(name);
|
|
||||||
for (envptr = environ; *envptr != NULL; envptr++) {
|
|
||||||
if (strncmp(name, *envptr, namelen) == 0 &&
|
|
||||||
((*envptr)[namelen] == '=' || (*envptr)[namelen] == '\0'))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (; *envptr != NULL; envptr++)
|
|
||||||
*envptr = *(envptr + 1);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
67
configure
vendored
67
configure
vendored
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# $Id: configure,v 1.59 2010-12-08 19:55:31 nicm Exp $
|
# $Id: configure,v 1.47 2009-12-11 20:08:18 nicm Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
#
|
#
|
||||||
@@ -33,22 +33,18 @@ cat <<EOF >>$CONFIG_H
|
|||||||
#undef HAVE_BROKEN_KQUEUE
|
#undef HAVE_BROKEN_KQUEUE
|
||||||
#undef HAVE_BROKEN_POLL
|
#undef HAVE_BROKEN_POLL
|
||||||
#undef HAVE_BZERO
|
#undef HAVE_BZERO
|
||||||
#undef HAVE_CLOSEFROM
|
#undef HAVE_CRYPT_H
|
||||||
#undef HAVE_DAEMON
|
#undef HAVE_DAEMON
|
||||||
#undef HAVE_DIRFD
|
|
||||||
#undef HAVE_FCNTL_CLOSEM
|
|
||||||
#undef HAVE_FGETLN
|
#undef HAVE_FGETLN
|
||||||
#undef HAVE_FORKPTY
|
#undef HAVE_FORKPTY
|
||||||
#undef HAVE_GETOPT
|
#undef HAVE_GETOPT
|
||||||
#undef HAVE_IMSG
|
#undef HAVE_IMSG
|
||||||
#undef HAVE_LIBUTIL_H
|
#undef HAVE_LIBUTIL_H
|
||||||
#undef HAVE_PATHS_H
|
#undef HAVE_PATHS_H
|
||||||
#undef HAVE_PROC_PID
|
|
||||||
#undef HAVE_PROGNAME
|
#undef HAVE_PROGNAME
|
||||||
#undef HAVE_PTY_H
|
#undef HAVE_PTY_H
|
||||||
#undef HAVE_QUEUE_H
|
#undef HAVE_QUEUE_H
|
||||||
#undef HAVE_SETPROCTITLE
|
#undef HAVE_SETPROCTITLE
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
#undef HAVE_STRCASESTR
|
#undef HAVE_STRCASESTR
|
||||||
#undef HAVE_STRLCAT
|
#undef HAVE_STRLCAT
|
||||||
#undef HAVE_STRLCPY
|
#undef HAVE_STRLCPY
|
||||||
@@ -67,18 +63,14 @@ case $TMUX_PLATFORM in
|
|||||||
#define HAVE_ASPRINTF
|
#define HAVE_ASPRINTF
|
||||||
#define HAVE_BITSTRING_H
|
#define HAVE_BITSTRING_H
|
||||||
#define HAVE_BZERO
|
#define HAVE_BZERO
|
||||||
#define HAVE_CLOSEFROM
|
|
||||||
#define HAVE_DAEMON
|
#define HAVE_DAEMON
|
||||||
#define HAVE_FGETLN
|
#define HAVE_FGETLN
|
||||||
#define HAVE_FORKPTY
|
#define HAVE_FORKPTY
|
||||||
#define HAVE_GETOPT
|
#define HAVE_GETOPT
|
||||||
#define HAVE_IMSG
|
|
||||||
#define HAVE_PATHS_H
|
#define HAVE_PATHS_H
|
||||||
#define HAVE_PROGNAME
|
#define HAVE_PROGNAME
|
||||||
#define HAVE_QUEUE_H
|
#define HAVE_QUEUE_H
|
||||||
#define HAVE_SETENV
|
|
||||||
#define HAVE_SETPROCTITLE
|
#define HAVE_SETPROCTITLE
|
||||||
#define HAVE_STDINT_H
|
|
||||||
#define HAVE_STRCASESTR
|
#define HAVE_STRCASESTR
|
||||||
#define HAVE_STRLCAT
|
#define HAVE_STRLCAT
|
||||||
#define HAVE_STRLCPY
|
#define HAVE_STRLCPY
|
||||||
@@ -91,7 +83,9 @@ case $TMUX_PLATFORM in
|
|||||||
EOF
|
EOF
|
||||||
cat <<EOF >>$CONFIG_MK
|
cat <<EOF >>$CONFIG_MK
|
||||||
LIBS+= -lcurses -lutil -levent
|
LIBS+= -lcurses -lutil -levent
|
||||||
SRCS+= osdep-openbsd.c
|
SRCS+= osdep-openbsd.c \
|
||||||
|
compat/imsg-buffer.c \
|
||||||
|
compat/imsg.c
|
||||||
EOF
|
EOF
|
||||||
;;
|
;;
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -100,28 +94,23 @@ EOF
|
|||||||
#define HAVE_ASPRINTF
|
#define HAVE_ASPRINTF
|
||||||
#define HAVE_BZERO
|
#define HAVE_BZERO
|
||||||
#define HAVE_DAEMON
|
#define HAVE_DAEMON
|
||||||
#define HAVE_DIRFD
|
|
||||||
#define HAVE_FORKPTY
|
#define HAVE_FORKPTY
|
||||||
#define HAVE_PATHS_H
|
#define HAVE_PATHS_H
|
||||||
#define HAVE_PROC_PID
|
|
||||||
#define HAVE_PROGNAME
|
#define HAVE_PROGNAME
|
||||||
#define HAVE_PTY_H
|
#define HAVE_PTY_H
|
||||||
#define HAVE_SETENV
|
|
||||||
#define HAVE_STDINT_H
|
|
||||||
#define HAVE_STRCASESTR
|
#define HAVE_STRCASESTR
|
||||||
#define HAVE_STRSEP
|
#define HAVE_STRSEP
|
||||||
#define HAVE_U_INT
|
#define HAVE_U_INT
|
||||||
EOF
|
EOF
|
||||||
cat <<EOF >>$CONFIG_MK
|
cat <<EOF >>$CONFIG_MK
|
||||||
CFLAGS+= -std=c99 -D_GNU_SOURCE -D_POSIX_SOURCE
|
CFLAGS+= -std=c99 -D_GNU_SOURCE -D_POSIX_SOURCE
|
||||||
LIBS+= -lncurses -lutil -levent -lrt
|
LIBS+= -lncurses -lcrypt -lutil -levent
|
||||||
SRCS+= osdep-linux.c \
|
SRCS+= osdep-linux.c \
|
||||||
compat/closefrom.c \
|
|
||||||
compat/fgetln.c \
|
compat/fgetln.c \
|
||||||
compat/strlcat.c \
|
compat/strlcat.c \
|
||||||
compat/strlcpy.c \
|
compat/strlcpy.c \
|
||||||
compat/strtonum.c \
|
compat/strtonum.c \
|
||||||
compat/getopt.c \
|
compat/getopt.c \
|
||||||
compat/vis.c \
|
compat/vis.c \
|
||||||
compat/unvis.c \
|
compat/unvis.c \
|
||||||
compat/imsg-buffer.c \
|
compat/imsg-buffer.c \
|
||||||
@@ -131,14 +120,13 @@ EOF
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
AIX)
|
AIX)
|
||||||
cat <<EOF >>$CONFIG_H
|
cat <<EOF >>$CONFIG_H
|
||||||
#define HAVE_SETENV
|
#define HAVE_BZERO
|
||||||
#define HAVE_STDINT_H
|
#define HAVE_DAEMON
|
||||||
EOF
|
EOF
|
||||||
cat <<EOF >>$CONFIG_MK
|
cat <<EOF >>$CONFIG_MK
|
||||||
LIBS+= -lcurses -levent
|
LIBS+= -lcurses -levent
|
||||||
SRCS+= osdep-unknown.c \
|
SRCS+= osdep-unknown.c \
|
||||||
compat/asprintf.c \
|
compat/asprintf.c \
|
||||||
compat/closefrom.c \
|
|
||||||
compat/daemon.c \
|
compat/daemon.c \
|
||||||
compat/forkpty-aix.c \
|
compat/forkpty-aix.c \
|
||||||
compat/strcasestr.c \
|
compat/strcasestr.c \
|
||||||
@@ -157,7 +145,7 @@ EOF
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
SunOS)
|
SunOS)
|
||||||
cat <<EOF >>$CONFIG_H
|
cat <<EOF >>$CONFIG_H
|
||||||
#define HAVE_CLOSEFROM
|
#define HAVE_CRYPT_H
|
||||||
#define HAVE_STRLCAT
|
#define HAVE_STRLCAT
|
||||||
#define HAVE_STRLCPY
|
#define HAVE_STRLCPY
|
||||||
EOF
|
EOF
|
||||||
@@ -170,7 +158,6 @@ SRCS+= osdep-sunos.c \
|
|||||||
compat/fgetln.c \
|
compat/fgetln.c \
|
||||||
compat/forkpty-sunos.c \
|
compat/forkpty-sunos.c \
|
||||||
compat/getopt.c \
|
compat/getopt.c \
|
||||||
compat/setenv.c \
|
|
||||||
compat/strcasestr.c \
|
compat/strcasestr.c \
|
||||||
compat/strsep.c \
|
compat/strsep.c \
|
||||||
compat/strtonum.c \
|
compat/strtonum.c \
|
||||||
@@ -189,15 +176,11 @@ EOF
|
|||||||
#define HAVE_BROKEN_POLL
|
#define HAVE_BROKEN_POLL
|
||||||
#define HAVE_BZERO
|
#define HAVE_BZERO
|
||||||
#define HAVE_DAEMON
|
#define HAVE_DAEMON
|
||||||
#define HAVE_DIRFD
|
|
||||||
#define HAVE_FGETLN
|
#define HAVE_FGETLN
|
||||||
#define HAVE_FORKPTY
|
#define HAVE_FORKPTY
|
||||||
#define HAVE_GETOPT
|
#define HAVE_GETOPT
|
||||||
#define HAVE_PATHS_H
|
#define HAVE_PATHS_H
|
||||||
#define HAVE_PROC_PID
|
|
||||||
#define HAVE_PROGNAME
|
#define HAVE_PROGNAME
|
||||||
#define HAVE_SETENV
|
|
||||||
#define HAVE_STDINT_H
|
|
||||||
#define HAVE_STRCASESTR
|
#define HAVE_STRCASESTR
|
||||||
#define HAVE_STRLCAT
|
#define HAVE_STRLCAT
|
||||||
#define HAVE_STRLCPY
|
#define HAVE_STRLCPY
|
||||||
@@ -210,7 +193,6 @@ CPPFLAGS+= -I/opt/local/include
|
|||||||
LDFLAGS+= -L/opt/local/lib
|
LDFLAGS+= -L/opt/local/lib
|
||||||
LIBS+= -lcurses -levent
|
LIBS+= -lcurses -levent
|
||||||
SRCS+= osdep-darwin.c \
|
SRCS+= osdep-darwin.c \
|
||||||
compat/closefrom.c \
|
|
||||||
compat/strtonum.c \
|
compat/strtonum.c \
|
||||||
compat/vis.c \
|
compat/vis.c \
|
||||||
compat/unvis.c \
|
compat/unvis.c \
|
||||||
@@ -222,9 +204,7 @@ EOF
|
|||||||
FreeBSD|DragonFly)
|
FreeBSD|DragonFly)
|
||||||
cat <<EOF >>$CONFIG_H
|
cat <<EOF >>$CONFIG_H
|
||||||
#define HAVE_ASPRINTF
|
#define HAVE_ASPRINTF
|
||||||
#define HAVE_BROKEN_KQUEUE
|
|
||||||
#define HAVE_BZERO
|
#define HAVE_BZERO
|
||||||
#define HAVE_CLOSEFROM
|
|
||||||
#define HAVE_DAEMON
|
#define HAVE_DAEMON
|
||||||
#define HAVE_FGETLN
|
#define HAVE_FGETLN
|
||||||
#define HAVE_FORKPTY
|
#define HAVE_FORKPTY
|
||||||
@@ -232,18 +212,16 @@ EOF
|
|||||||
#define HAVE_LIBUTIL_H
|
#define HAVE_LIBUTIL_H
|
||||||
#define HAVE_PATHS_H
|
#define HAVE_PATHS_H
|
||||||
#define HAVE_PROGNAME
|
#define HAVE_PROGNAME
|
||||||
#define HAVE_SETENV
|
|
||||||
#define HAVE_SETPROCTITLE
|
#define HAVE_SETPROCTITLE
|
||||||
#define HAVE_STDINT_H
|
|
||||||
#define HAVE_STRCASESTR
|
#define HAVE_STRCASESTR
|
||||||
#define HAVE_STRLCAT
|
#define HAVE_STRLCAT
|
||||||
#define HAVE_STRLCPY
|
#define HAVE_STRLCPY
|
||||||
#define HAVE_STRSEP
|
|
||||||
#define HAVE_STRTONUM
|
#define HAVE_STRTONUM
|
||||||
|
#define HAVE_STRSEP
|
||||||
#define HAVE_U_INT
|
#define HAVE_U_INT
|
||||||
EOF
|
EOF
|
||||||
cat <<EOF >>$CONFIG_MK
|
cat <<EOF >>$CONFIG_MK
|
||||||
LIBS+= -lcurses -lutil -levent
|
LIBS+= -lcurses -lcrypt -lutil -levent
|
||||||
SRCS+= osdep-freebsd.c \
|
SRCS+= osdep-freebsd.c \
|
||||||
compat/vis.c \
|
compat/vis.c \
|
||||||
compat/unvis.c \
|
compat/unvis.c \
|
||||||
@@ -255,17 +233,15 @@ EOF
|
|||||||
NetBSD)
|
NetBSD)
|
||||||
cat <<EOF >>$CONFIG_H
|
cat <<EOF >>$CONFIG_H
|
||||||
#define HAVE_ASPRINTF
|
#define HAVE_ASPRINTF
|
||||||
|
#define HAVE_BROKEN_CURSES_H
|
||||||
#define HAVE_BZERO
|
#define HAVE_BZERO
|
||||||
#define HAVE_CLOSEFROM
|
|
||||||
#define HAVE_DAEMON
|
#define HAVE_DAEMON
|
||||||
#define HAVE_FGETLN
|
#define HAVE_FGETLN
|
||||||
#define HAVE_FORKPTY
|
#define HAVE_FORKPTY
|
||||||
#define HAVE_GETOPT
|
#define HAVE_GETOPT
|
||||||
#define HAVE_PATHS_H
|
#define HAVE_PATHS_H
|
||||||
#define HAVE_PROGNAME
|
#define HAVE_PROGNAME
|
||||||
#define HAVE_SETENV
|
|
||||||
#define HAVE_SETPROCTITLE
|
#define HAVE_SETPROCTITLE
|
||||||
#define HAVE_STDINT_H
|
|
||||||
#define HAVE_STRCASESTR
|
#define HAVE_STRCASESTR
|
||||||
#define HAVE_STRLCAT
|
#define HAVE_STRLCAT
|
||||||
#define HAVE_STRLCPY
|
#define HAVE_STRLCPY
|
||||||
@@ -273,23 +249,10 @@ EOF
|
|||||||
#define HAVE_UTIL_H
|
#define HAVE_UTIL_H
|
||||||
#define HAVE_U_INT
|
#define HAVE_U_INT
|
||||||
EOF
|
EOF
|
||||||
# NetBSD-6 has its own terminfo implementation
|
cat <<EOF >>$CONFIG_MK
|
||||||
if test -f /lib/libterminfo.so; then
|
|
||||||
cat <<EOF >>$CONFIG_MK
|
|
||||||
LIBS+= -lterminfo
|
|
||||||
EOF
|
|
||||||
else
|
|
||||||
cat <<EOF >>$CONFIG_MK
|
|
||||||
CPPFLAGS+= -I/usr/pkg/include
|
CPPFLAGS+= -I/usr/pkg/include
|
||||||
LDFLAGS+= -L/usr/pkg/lib
|
LDFLAGS+= -L/usr/pkg/lib
|
||||||
LIBS+= -lncurses
|
LIBS+= -lncurses -lcrypt -lutil -levent
|
||||||
EOF
|
|
||||||
cat <<EOF >>$CONFIG_H
|
|
||||||
#define HAVE_BROKEN_CURSES_H
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
cat <<EOF >>$CONFIG_MK
|
|
||||||
LIBS+= -lutil -levent
|
|
||||||
SRCS+= osdep-netbsd.c \
|
SRCS+= osdep-netbsd.c \
|
||||||
compat/strtonum.c \
|
compat/strtonum.c \
|
||||||
compat/vis.c \
|
compat/vis.c \
|
||||||
|
|||||||
40
environ.c
40
environ.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: environ.c,v 1.4 2010-04-06 21:59:19 nicm Exp $ */
|
/* $Id: environ.c,v 1.3 2009-08-09 17:57:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -35,14 +35,12 @@ environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
|
|||||||
return (strcmp(envent1->name, envent2->name));
|
return (strcmp(envent1->name, envent2->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise the environment. */
|
|
||||||
void
|
void
|
||||||
environ_init(struct environ *env)
|
environ_init(struct environ *env)
|
||||||
{
|
{
|
||||||
RB_INIT(env);
|
RB_INIT(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free an environment. */
|
|
||||||
void
|
void
|
||||||
environ_free(struct environ *env)
|
environ_free(struct environ *env)
|
||||||
{
|
{
|
||||||
@@ -58,7 +56,6 @@ environ_free(struct environ *env)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy one environment into another. */
|
|
||||||
void
|
void
|
||||||
environ_copy(struct environ *srcenv, struct environ *dstenv)
|
environ_copy(struct environ *srcenv, struct environ *dstenv)
|
||||||
{
|
{
|
||||||
@@ -68,7 +65,6 @@ environ_copy(struct environ *srcenv, struct environ *dstenv)
|
|||||||
environ_set(dstenv, envent->name, envent->value);
|
environ_set(dstenv, envent->name, envent->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find an environment variable. */
|
|
||||||
struct environ_entry *
|
struct environ_entry *
|
||||||
environ_find(struct environ *env, const char *name)
|
environ_find(struct environ *env, const char *name)
|
||||||
{
|
{
|
||||||
@@ -78,7 +74,6 @@ environ_find(struct environ *env, const char *name)
|
|||||||
return (RB_FIND(environ, env, &envent));
|
return (RB_FIND(environ, env, &envent));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set an environment variable. */
|
|
||||||
void
|
void
|
||||||
environ_set(struct environ *env, const char *name, const char *value)
|
environ_set(struct environ *env, const char *name, const char *value)
|
||||||
{
|
{
|
||||||
@@ -102,11 +97,10 @@ environ_set(struct environ *env, const char *name, const char *value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set an environment variable from a NAME=VALUE string. */
|
|
||||||
void
|
void
|
||||||
environ_put(struct environ *env, const char *var)
|
environ_put(struct environ *env, const char *var)
|
||||||
{
|
{
|
||||||
char *name, *value;
|
char *name, *value;
|
||||||
|
|
||||||
value = strchr(var, '=');
|
value = strchr(var, '=');
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
@@ -120,7 +114,6 @@ environ_put(struct environ *env, const char *var)
|
|||||||
xfree(name);
|
xfree(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unset an environment variable. */
|
|
||||||
void
|
void
|
||||||
environ_unset(struct environ *env, const char *name)
|
environ_unset(struct environ *env, const char *name)
|
||||||
{
|
{
|
||||||
@@ -135,10 +128,6 @@ environ_unset(struct environ *env, const char *name)
|
|||||||
xfree(envent);
|
xfree(envent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy a space-separated list of variables from a destination into a source
|
|
||||||
* environment.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
|
environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
|
||||||
{
|
{
|
||||||
@@ -154,28 +143,3 @@ environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
|
|||||||
}
|
}
|
||||||
xfree(copyvars);
|
xfree(copyvars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push environment into the real environment - use after fork(). */
|
|
||||||
void
|
|
||||||
environ_push(struct environ *env)
|
|
||||||
{
|
|
||||||
ARRAY_DECL(, char *) varlist;
|
|
||||||
struct environ_entry *envent;
|
|
||||||
char **varp, *var;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
ARRAY_INIT(&varlist);
|
|
||||||
for (varp = environ; *varp != NULL; varp++) {
|
|
||||||
var = xstrdup(*varp);
|
|
||||||
var[strcspn(var, "=")] = '\0';
|
|
||||||
ARRAY_ADD(&varlist, var);
|
|
||||||
}
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&varlist); i++)
|
|
||||||
unsetenv(ARRAY_ITEM(&varlist, i));
|
|
||||||
ARRAY_FREE(&varlist);
|
|
||||||
|
|
||||||
RB_FOREACH(envent, environ, env) {
|
|
||||||
if (envent->value != NULL)
|
|
||||||
setenv(envent->name, envent->value, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
# START tmux completion
|
|
||||||
# This file is in the public domain
|
|
||||||
# See: http://www.debian-administration.org/articles/317 for how to write more.
|
|
||||||
# Usage: Put "source bash_completion_tmux.sh" into your .bashrc
|
|
||||||
_tmux()
|
|
||||||
{
|
|
||||||
local cur prev opts
|
|
||||||
COMPREPLY=()
|
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
||||||
|
|
||||||
opts=" \
|
|
||||||
attach-session \
|
|
||||||
bind-key \
|
|
||||||
break-pane \
|
|
||||||
capture-pane \
|
|
||||||
choose-client \
|
|
||||||
choose-session \
|
|
||||||
choose-window \
|
|
||||||
clear-history \
|
|
||||||
clock-mode \
|
|
||||||
command-prompt \
|
|
||||||
confirm-before \
|
|
||||||
copy-buffer \
|
|
||||||
copy-mode \
|
|
||||||
delete-buffer \
|
|
||||||
detach-client \
|
|
||||||
display-message \
|
|
||||||
display-panes \
|
|
||||||
down-pane \
|
|
||||||
find-window \
|
|
||||||
has-session \
|
|
||||||
if-shell \
|
|
||||||
join-pane \
|
|
||||||
kill-pane \
|
|
||||||
kill-server \
|
|
||||||
kill-session \
|
|
||||||
kill-window \
|
|
||||||
last-window \
|
|
||||||
link-window \
|
|
||||||
list-buffers \
|
|
||||||
list-clients \
|
|
||||||
list-commands \
|
|
||||||
list-keys \
|
|
||||||
list-panes \
|
|
||||||
list-sessions \
|
|
||||||
list-windows \
|
|
||||||
load-buffer \
|
|
||||||
lock-client \
|
|
||||||
lock-server \
|
|
||||||
lock-session \
|
|
||||||
move-window \
|
|
||||||
new-session \
|
|
||||||
new-window \
|
|
||||||
next-layout \
|
|
||||||
next-window \
|
|
||||||
paste-buffer \
|
|
||||||
pipe-pane \
|
|
||||||
previous-layout \
|
|
||||||
previous-window \
|
|
||||||
refresh-client \
|
|
||||||
rename-session \
|
|
||||||
rename-window \
|
|
||||||
resize-pane \
|
|
||||||
respawn-window \
|
|
||||||
rotate-window \
|
|
||||||
run-shell \
|
|
||||||
save-buffer \
|
|
||||||
select-layout \
|
|
||||||
select-pane \
|
|
||||||
select-prompt \
|
|
||||||
select-window \
|
|
||||||
send-keys \
|
|
||||||
send-prefix \
|
|
||||||
server-info \
|
|
||||||
set-buffer \
|
|
||||||
set-environment \
|
|
||||||
set-option \
|
|
||||||
set-window-option \
|
|
||||||
show-buffer \
|
|
||||||
show-environment \
|
|
||||||
show-messages \
|
|
||||||
show-options \
|
|
||||||
show-window-options \
|
|
||||||
source-file \
|
|
||||||
split-window \
|
|
||||||
start-server \
|
|
||||||
suspend-client \
|
|
||||||
swap-pane \
|
|
||||||
swap-window \
|
|
||||||
switch-client \
|
|
||||||
unbind-key \
|
|
||||||
unlink-window \
|
|
||||||
up-pane"
|
|
||||||
|
|
||||||
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
}
|
|
||||||
complete -F _tmux tmux
|
|
||||||
|
|
||||||
# END tmux completion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# $Id: screen-keys.conf,v 1.7 2010-07-31 11:39:13 nicm Exp $
|
# $Id: screen-keys.conf,v 1.6 2010-02-02 21:34:16 nicm Exp $
|
||||||
#
|
#
|
||||||
# By Nicholas Marriott. Public domain.
|
# By Nicholas Marriott. Public domain.
|
||||||
#
|
#
|
||||||
@@ -93,9 +93,9 @@ bind | split-window
|
|||||||
|
|
||||||
# :kB: focus up
|
# :kB: focus up
|
||||||
unbind Tab
|
unbind Tab
|
||||||
bind Tab select-pane -t:.+
|
bind Tab down-pane
|
||||||
unbind BTab
|
unbind BTab
|
||||||
bind BTab select-pane -t:.-
|
bind BTab up-pane
|
||||||
|
|
||||||
# " windowlist -b
|
# " windowlist -b
|
||||||
unbind '"'
|
unbind '"'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
" Vim syntax file
|
" Vim syntax file
|
||||||
" Language: tmux(1) configuration file
|
" Language: tmux(1) configuration file
|
||||||
" Maintainer: Tiago Cunha <me@tiagocunha.org>
|
" Maintainer: Tiago Cunha <me@tiagocunha.org>
|
||||||
" Last Change: $Date: 2010-07-27 18:29:07 $
|
" Last Change: $Date: 2010-02-26 13:33:22 $
|
||||||
" License: This file is placed in the public domain.
|
" License: This file is placed in the public domain.
|
||||||
|
|
||||||
if version < 600
|
if version < 600
|
||||||
@@ -29,11 +29,11 @@ syn keyword tmuxCmds new[-session] start[-server] kill-server setw
|
|||||||
syn keyword tmuxCmds set-window-option show[-options] showw show-window-options
|
syn keyword tmuxCmds set-window-option show[-options] showw show-window-options
|
||||||
syn keyword tmuxCmds command-prompt setb set-buffer showb show-buffer lsb
|
syn keyword tmuxCmds command-prompt setb set-buffer showb show-buffer lsb
|
||||||
syn keyword tmuxCmds list-buffers deleteb delete-buffer lscm list-commands
|
syn keyword tmuxCmds list-buffers deleteb delete-buffer lscm list-commands
|
||||||
syn keyword tmuxCmds movew move-window respawnw respawn-window
|
syn keyword tmuxCmds movew move-window select-prompt respawnw respawn-window
|
||||||
syn keyword tmuxCmds source[-file] info server-info clock-mode lock[-server]
|
syn keyword tmuxCmds source[-file] info server-info clock-mode lock[-server]
|
||||||
syn keyword tmuxCmds saveb save-buffer killp
|
syn keyword tmuxCmds saveb save-buffer downp down-pane killp
|
||||||
syn keyword tmuxCmds kill-pane resizep resize-pane selectp select-pane swapp
|
syn keyword tmuxCmds kill-pane resizep resize-pane selectp select-pane swapp
|
||||||
syn keyword tmuxCmds swap-pane splitw split-window choose-session
|
syn keyword tmuxCmds swap-pane splitw split-window upp up-pane choose-session
|
||||||
syn keyword tmuxCmds choose-window loadb load-buffer copyb copy-buffer suspendc
|
syn keyword tmuxCmds choose-window loadb load-buffer copyb copy-buffer suspendc
|
||||||
syn keyword tmuxCmds suspend-client findw find-window breakp break-pane nextl
|
syn keyword tmuxCmds suspend-client findw find-window breakp break-pane nextl
|
||||||
syn keyword tmuxCmds next-layout rotatew rotate-window confirm[-before]
|
syn keyword tmuxCmds next-layout rotatew rotate-window confirm[-before]
|
||||||
@@ -42,7 +42,7 @@ syn keyword tmuxCmds display[-message] setenv set-environment showenv
|
|||||||
syn keyword tmuxCmds show-environment choose-client displayp display-panes
|
syn keyword tmuxCmds show-environment choose-client displayp display-panes
|
||||||
syn keyword tmuxCmds run[-shell] lockc lock-client locks lock-session lsp
|
syn keyword tmuxCmds run[-shell] lockc lock-client locks lock-session lsp
|
||||||
syn keyword tmuxCmds list-panes pipep pipe-pane showmsgs show-messages capturep
|
syn keyword tmuxCmds list-panes pipep pipe-pane showmsgs show-messages capturep
|
||||||
syn keyword tmuxCmds capture-pane joinp join-pane choose-buffer
|
syn keyword tmuxCmds capture-pane joinp join-pane
|
||||||
|
|
||||||
syn keyword tmuxOptsSet prefix status status-fg status-bg bell-action
|
syn keyword tmuxOptsSet prefix status status-fg status-bg bell-action
|
||||||
syn keyword tmuxOptsSet default-command history-limit status-left status-right
|
syn keyword tmuxOptsSet default-command history-limit status-left status-right
|
||||||
@@ -61,7 +61,6 @@ syn keyword tmuxOptsSet mouse-select-pane message-limit quiet escape-time
|
|||||||
syn keyword tmuxOptsSet pane-active-border-bg pane-active-border-fg
|
syn keyword tmuxOptsSet pane-active-border-bg pane-active-border-fg
|
||||||
syn keyword tmuxOptsSet pane-border-bg pane-border-fg
|
syn keyword tmuxOptsSet pane-border-bg pane-border-fg
|
||||||
syn keyword tmuxOptsSet display-panes-active-colour alternate-screen
|
syn keyword tmuxOptsSet display-panes-active-colour alternate-screen
|
||||||
syn keyword tmuxOptsSet detach-on-destroy
|
|
||||||
|
|
||||||
syn keyword tmuxOptsSetw monitor-activity aggressive-resize force-width
|
syn keyword tmuxOptsSetw monitor-activity aggressive-resize force-width
|
||||||
syn keyword tmuxOptsSetw force-height remain-on-exit uft8 mode-fg mode-bg
|
syn keyword tmuxOptsSetw force-height remain-on-exit uft8 mode-fg mode-bg
|
||||||
@@ -72,8 +71,7 @@ syn keyword tmuxOptsSetw main-pane-width main-pane-height monitor-content
|
|||||||
syn keyword tmuxOptsSetw window-status-current-attr window-status-current-bg
|
syn keyword tmuxOptsSetw window-status-current-attr window-status-current-bg
|
||||||
syn keyword tmuxOptsSetw window-status-current-fg mode-mouse synchronize-panes
|
syn keyword tmuxOptsSetw window-status-current-fg mode-mouse synchronize-panes
|
||||||
syn keyword tmuxOptsSetw window-status-format window-status-current-format
|
syn keyword tmuxOptsSetw window-status-format window-status-current-format
|
||||||
syn keyword tmuxOptsSetw word-separators window-status-alert-alert
|
syn keyword tmuxOptsSetw word-separators
|
||||||
syn keyword tmuxOptsSetw window-status-alert-bg window-status-alert-fg
|
|
||||||
|
|
||||||
syn keyword tmuxTodo FIXME NOTE TODO XXX contained
|
syn keyword tmuxTodo FIXME NOTE TODO XXX contained
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
# $Id: vim-keys.conf,v 1.2 2010-09-18 09:36:15 nicm Exp $
|
# $Id: vim-keys.conf,v 1.1 2010-01-17 16:24:09 nicm Exp $
|
||||||
#
|
#
|
||||||
# vim-keys.conf, v1.2 2010/09/12
|
# vim-keys.conf, v1.0 2010/01/15
|
||||||
#
|
#
|
||||||
# By Daniel Thau. Public domain.
|
# By Daniel Thau. Public domain.
|
||||||
#
|
#
|
||||||
# This configuration file binds many vi- and vim-like bindings to the
|
# This configuration file binds many vi- and vim-like bindings to the
|
||||||
# appropriate tmux key bindings. Note that for many key bindings there is no
|
# appropriate tmux key bindings. Note that for many key bindings there is no
|
||||||
# tmux analogue. This is intended for tmux 1.3, which handles pane selection
|
# tmux analogue.
|
||||||
# differently from the previous versions
|
|
||||||
|
|
||||||
# split windows like vim
|
# split windows like vim
|
||||||
# vim's definition of a horizontal/vertical split is reversed from tmux's
|
# vim's definition of a horizontal/vertical split is reversed from tmux's
|
||||||
bind s split-window -v
|
bind s split-window -v
|
||||||
bind v split-window -h
|
bind v split-window -h
|
||||||
|
|
||||||
# move around panes with hjkl, as one would in vim after pressing ctrl-w
|
# move around panes with j and k, a bit like vim
|
||||||
bind h select-pane -L
|
# as of tmux 1.1, there is no way to move based on pane position (ie, no way to
|
||||||
bind j select-pane -D
|
# move the pane to the right)
|
||||||
bind k select-pane -U
|
bind j down-pane
|
||||||
bind l select-pane -R
|
bind k up-pane
|
||||||
|
|
||||||
# resize panes like vim
|
# resize panes like vim
|
||||||
# feel free to change the "1" to however many lines you want to resize by, only
|
# feel free to change the "1" to however many lines you want to resize by, only
|
||||||
|
|||||||
43
grid.c
43
grid.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: grid.c,v 1.37 2010-04-05 05:11:43 micahcowan Exp $ */
|
/* $Id: grid.c,v 1.36 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -46,9 +46,18 @@ const struct grid_cell grid_default_cell = { 0, 0, 8, 8, ' ' };
|
|||||||
gc, sizeof gd->linedata[py].utf8data[px]); \
|
gc, sizeof gd->linedata[py].utf8data[px]); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
int grid_check_x(struct grid *, u_int);
|
||||||
int grid_check_y(struct grid *, u_int);
|
int grid_check_y(struct grid *, u_int);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
int
|
||||||
|
grid_check_x(struct grid *gd, u_int px)
|
||||||
|
{
|
||||||
|
if ((px) >= (gd)->sx)
|
||||||
|
log_fatalx("x out of range: %u", px);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
grid_check_y(struct grid *gd, u_int py)
|
grid_check_y(struct grid *gd, u_int py)
|
||||||
{
|
{
|
||||||
@@ -57,6 +66,16 @@ grid_check_y(struct grid *gd, u_int py)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
int
|
||||||
|
grid_check_x(struct grid *gd, u_int px)
|
||||||
|
{
|
||||||
|
if ((px) >= (gd)->sx) {
|
||||||
|
log_debug("x out of range: %u", px);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
grid_check_y(struct grid *gd, u_int py)
|
grid_check_y(struct grid *gd, u_int py)
|
||||||
{
|
{
|
||||||
@@ -251,6 +270,8 @@ grid_expand_line_utf8(struct grid *gd, u_int py, u_int sx)
|
|||||||
const struct grid_cell *
|
const struct grid_cell *
|
||||||
grid_peek_cell(struct grid *gd, u_int px, u_int py)
|
grid_peek_cell(struct grid *gd, u_int px, u_int py)
|
||||||
{
|
{
|
||||||
|
if (grid_check_x(gd, px) != 0)
|
||||||
|
return (&grid_default_cell);
|
||||||
if (grid_check_y(gd, py) != 0)
|
if (grid_check_y(gd, py) != 0)
|
||||||
return (&grid_default_cell);
|
return (&grid_default_cell);
|
||||||
|
|
||||||
@@ -263,6 +284,8 @@ grid_peek_cell(struct grid *gd, u_int px, u_int py)
|
|||||||
struct grid_cell *
|
struct grid_cell *
|
||||||
grid_get_cell(struct grid *gd, u_int px, u_int py)
|
grid_get_cell(struct grid *gd, u_int px, u_int py)
|
||||||
{
|
{
|
||||||
|
if (grid_check_x(gd, px) != 0)
|
||||||
|
return (NULL);
|
||||||
if (grid_check_y(gd, py) != 0)
|
if (grid_check_y(gd, py) != 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
@@ -275,6 +298,8 @@ void
|
|||||||
grid_set_cell(
|
grid_set_cell(
|
||||||
struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
||||||
{
|
{
|
||||||
|
if (grid_check_x(gd, px) != 0)
|
||||||
|
return;
|
||||||
if (grid_check_y(gd, py) != 0)
|
if (grid_check_y(gd, py) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -286,6 +311,8 @@ grid_set_cell(
|
|||||||
const struct grid_utf8 *
|
const struct grid_utf8 *
|
||||||
grid_peek_utf8(struct grid *gd, u_int px, u_int py)
|
grid_peek_utf8(struct grid *gd, u_int px, u_int py)
|
||||||
{
|
{
|
||||||
|
if (grid_check_x(gd, px) != 0)
|
||||||
|
return (NULL);
|
||||||
if (grid_check_y(gd, py) != 0)
|
if (grid_check_y(gd, py) != 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
@@ -298,6 +325,8 @@ grid_peek_utf8(struct grid *gd, u_int px, u_int py)
|
|||||||
struct grid_utf8 *
|
struct grid_utf8 *
|
||||||
grid_get_utf8(struct grid *gd, u_int px, u_int py)
|
grid_get_utf8(struct grid *gd, u_int px, u_int py)
|
||||||
{
|
{
|
||||||
|
if (grid_check_x(gd, px) != 0)
|
||||||
|
return (NULL);
|
||||||
if (grid_check_y(gd, py) != 0)
|
if (grid_check_y(gd, py) != 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
@@ -310,6 +339,8 @@ void
|
|||||||
grid_set_utf8(
|
grid_set_utf8(
|
||||||
struct grid *gd, u_int px, u_int py, const struct grid_utf8 *gc)
|
struct grid *gd, u_int px, u_int py, const struct grid_utf8 *gc)
|
||||||
{
|
{
|
||||||
|
if (grid_check_x(gd, px) != 0)
|
||||||
|
return;
|
||||||
if (grid_check_y(gd, py) != 0)
|
if (grid_check_y(gd, py) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -333,6 +364,10 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (grid_check_x(gd, px) != 0)
|
||||||
|
return;
|
||||||
|
if (grid_check_x(gd, px + nx - 1) != 0)
|
||||||
|
return;
|
||||||
if (grid_check_y(gd, py) != 0)
|
if (grid_check_y(gd, py) != 0)
|
||||||
return;
|
return;
|
||||||
if (grid_check_y(gd, py + ny - 1) != 0)
|
if (grid_check_y(gd, py + ny - 1) != 0)
|
||||||
@@ -430,6 +465,12 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx)
|
|||||||
if (nx == 0 || px == dx)
|
if (nx == 0 || px == dx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (grid_check_x(gd, px) != 0)
|
||||||
|
return;
|
||||||
|
if (grid_check_x(gd, px + nx - 1) != 0)
|
||||||
|
return;
|
||||||
|
if (grid_check_x(gd, dx + nx - 1) != 0)
|
||||||
|
return;
|
||||||
if (grid_check_y(gd, py) != 0)
|
if (grid_check_y(gd, py) != 0)
|
||||||
return;
|
return;
|
||||||
gl = &gd->linedata[py];
|
gl = &gd->linedata[py];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: input-keys.c,v 1.45 2010-09-07 19:32:58 nicm Exp $ */
|
/* $Id: input-keys.c,v 1.44 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|||||||
11
job.c
11
job.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: job.c,v 1.19 2010-10-24 00:45:57 tcunha Exp $ */
|
/* $Id: job.c,v 1.15 2010-02-26 13:35:04 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -148,9 +148,8 @@ job_run(struct job *job)
|
|||||||
case -1:
|
case -1:
|
||||||
return (-1);
|
return (-1);
|
||||||
case 0: /* child */
|
case 0: /* child */
|
||||||
clear_signals(1);
|
server_signal_clear();
|
||||||
|
/* XXX environ? */
|
||||||
environ_push(&global_environ);
|
|
||||||
|
|
||||||
if (dup2(out[1], STDOUT_FILENO) == -1)
|
if (dup2(out[1], STDOUT_FILENO) == -1)
|
||||||
fatal("dup2 failed");
|
fatal("dup2 failed");
|
||||||
@@ -168,8 +167,6 @@ job_run(struct job *job)
|
|||||||
if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO)
|
if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO)
|
||||||
close(nullfd);
|
close(nullfd);
|
||||||
|
|
||||||
closefrom(STDERR_FILENO + 1);
|
|
||||||
|
|
||||||
execl(_PATH_BSHELL, "sh", "-c", job->cmd, (char *) NULL);
|
execl(_PATH_BSHELL, "sh", "-c", job->cmd, (char *) NULL);
|
||||||
fatal("execl failed");
|
fatal("execl failed");
|
||||||
default: /* parent */
|
default: /* parent */
|
||||||
@@ -180,6 +177,8 @@ job_run(struct job *job)
|
|||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
if (fcntl(job->fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
if (fcntl(job->fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
|
if (fcntl(job->fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
fatal("fcntl failed");
|
||||||
|
|
||||||
if (job->event != NULL)
|
if (job->event != NULL)
|
||||||
bufferevent_free(job->event);
|
bufferevent_free(job->event);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: key-bindings.c,v 1.97 2010-12-11 18:42:20 nicm Exp $ */
|
/* $Id: key-bindings.c,v 1.88 2010-02-08 18:27:34 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -108,8 +108,6 @@ key_bindings_init(void)
|
|||||||
{ '#', 0, &cmd_list_buffers_entry },
|
{ '#', 0, &cmd_list_buffers_entry },
|
||||||
{ '%', 0, &cmd_split_window_entry },
|
{ '%', 0, &cmd_split_window_entry },
|
||||||
{ '&', 0, &cmd_confirm_before_entry },
|
{ '&', 0, &cmd_confirm_before_entry },
|
||||||
{ '(', 0, &cmd_switch_client_entry },
|
|
||||||
{ ')', 0, &cmd_switch_client_entry },
|
|
||||||
{ ',', 0, &cmd_command_prompt_entry },
|
{ ',', 0, &cmd_command_prompt_entry },
|
||||||
{ '-', 0, &cmd_delete_buffer_entry },
|
{ '-', 0, &cmd_delete_buffer_entry },
|
||||||
{ '.', 0, &cmd_command_prompt_entry },
|
{ '.', 0, &cmd_command_prompt_entry },
|
||||||
@@ -124,13 +122,10 @@ key_bindings_init(void)
|
|||||||
{ '8', 0, &cmd_select_window_entry },
|
{ '8', 0, &cmd_select_window_entry },
|
||||||
{ '9', 0, &cmd_select_window_entry },
|
{ '9', 0, &cmd_select_window_entry },
|
||||||
{ ':', 0, &cmd_command_prompt_entry },
|
{ ':', 0, &cmd_command_prompt_entry },
|
||||||
{ ';', 0, &cmd_last_pane_entry },
|
|
||||||
{ '=', 0, &cmd_choose_buffer_entry },
|
|
||||||
{ '?', 0, &cmd_list_keys_entry },
|
{ '?', 0, &cmd_list_keys_entry },
|
||||||
{ 'D', 0, &cmd_choose_client_entry },
|
{ 'D', 0, &cmd_choose_client_entry },
|
||||||
{ 'L', 0, &cmd_switch_client_entry },
|
|
||||||
{ '[', 0, &cmd_copy_mode_entry },
|
{ '[', 0, &cmd_copy_mode_entry },
|
||||||
{ '\'', 0, &cmd_command_prompt_entry },
|
{ '\'', 0, &cmd_select_prompt_entry },
|
||||||
{ '\002', /* C-b */ 0, &cmd_send_prefix_entry },
|
{ '\002', /* C-b */ 0, &cmd_send_prefix_entry },
|
||||||
{ '\017', /* C-o */ 0, &cmd_rotate_window_entry },
|
{ '\017', /* C-o */ 0, &cmd_rotate_window_entry },
|
||||||
{ '\032', /* C-z */ 0, &cmd_suspend_client_entry },
|
{ '\032', /* C-z */ 0, &cmd_suspend_client_entry },
|
||||||
@@ -141,7 +136,7 @@ key_bindings_init(void)
|
|||||||
{ 'i', 0, &cmd_display_message_entry },
|
{ 'i', 0, &cmd_display_message_entry },
|
||||||
{ 'l', 0, &cmd_last_window_entry },
|
{ 'l', 0, &cmd_last_window_entry },
|
||||||
{ 'n', 0, &cmd_next_window_entry },
|
{ 'n', 0, &cmd_next_window_entry },
|
||||||
{ 'o', 0, &cmd_select_pane_entry },
|
{ 'o', 0, &cmd_down_pane_entry },
|
||||||
{ 'p', 0, &cmd_previous_window_entry },
|
{ 'p', 0, &cmd_previous_window_entry },
|
||||||
{ 'q', 0, &cmd_display_panes_entry },
|
{ 'q', 0, &cmd_display_panes_entry },
|
||||||
{ 'r', 0, &cmd_refresh_client_entry },
|
{ 'r', 0, &cmd_refresh_client_entry },
|
||||||
@@ -156,15 +151,12 @@ key_bindings_init(void)
|
|||||||
{ '2' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
{ '2' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
||||||
{ '3' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
{ '3' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
||||||
{ '4' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
{ '4' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
||||||
{ '5' | KEYC_ESCAPE, 0, &cmd_select_layout_entry },
|
|
||||||
{ KEYC_PPAGE, 0, &cmd_copy_mode_entry },
|
{ KEYC_PPAGE, 0, &cmd_copy_mode_entry },
|
||||||
{ 'n' | KEYC_ESCAPE, 0, &cmd_next_window_entry },
|
{ 'n' | KEYC_ESCAPE, 0, &cmd_next_window_entry },
|
||||||
{ 'o' | KEYC_ESCAPE, 0, &cmd_rotate_window_entry },
|
{ 'o' | KEYC_ESCAPE, 0, &cmd_rotate_window_entry },
|
||||||
{ 'p' | KEYC_ESCAPE, 0, &cmd_previous_window_entry },
|
{ 'p' | KEYC_ESCAPE, 0, &cmd_previous_window_entry },
|
||||||
{ KEYC_UP, 1, &cmd_select_pane_entry },
|
{ KEYC_UP, 0, &cmd_up_pane_entry },
|
||||||
{ KEYC_DOWN, 1, &cmd_select_pane_entry },
|
{ KEYC_DOWN, 0, &cmd_down_pane_entry },
|
||||||
{ KEYC_LEFT, 1, &cmd_select_pane_entry },
|
|
||||||
{ KEYC_RIGHT, 1, &cmd_select_pane_entry },
|
|
||||||
{ KEYC_UP | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
|
{ KEYC_UP | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
|
||||||
{ KEYC_DOWN | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
|
{ KEYC_DOWN | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
|
||||||
{ KEYC_LEFT | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
|
{ KEYC_LEFT | KEYC_ESCAPE, 1, &cmd_resize_pane_entry },
|
||||||
@@ -182,15 +174,14 @@ key_bindings_init(void)
|
|||||||
|
|
||||||
for (i = 0; i < nitems(table); i++) {
|
for (i = 0; i < nitems(table); i++) {
|
||||||
cmdlist = xmalloc(sizeof *cmdlist);
|
cmdlist = xmalloc(sizeof *cmdlist);
|
||||||
TAILQ_INIT(&cmdlist->list);
|
TAILQ_INIT(cmdlist);
|
||||||
cmdlist->references = 1;
|
|
||||||
|
|
||||||
cmd = xmalloc(sizeof *cmd);
|
cmd = xmalloc(sizeof *cmd);
|
||||||
cmd->entry = table[i].entry;
|
cmd->entry = table[i].entry;
|
||||||
cmd->data = NULL;
|
cmd->data = NULL;
|
||||||
if (cmd->entry->init != NULL)
|
if (cmd->entry->init != NULL)
|
||||||
cmd->entry->init(cmd, table[i].key);
|
cmd->entry->init(cmd, table[i].key);
|
||||||
TAILQ_INSERT_HEAD(&cmdlist->list, cmd, qentry);
|
TAILQ_INSERT_HEAD(cmdlist, cmd, qentry);
|
||||||
|
|
||||||
key_bindings_add(
|
key_bindings_add(
|
||||||
table[i].key | KEYC_PREFIX, table[i].can_repeat, cmdlist);
|
table[i].key | KEYC_PREFIX, table[i].can_repeat, cmdlist);
|
||||||
@@ -218,14 +209,12 @@ key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...)
|
|||||||
struct winlink *wl = ctx->curclient->session->curw;
|
struct winlink *wl = ctx->curclient->session->curw;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (wl->window->active->mode != &window_copy_mode) {
|
if (wl->window->active->mode != &window_more_mode)
|
||||||
window_pane_reset_mode(wl->window->active);
|
window_pane_reset_mode(wl->window->active);
|
||||||
window_pane_set_mode(wl->window->active, &window_copy_mode);
|
window_pane_set_mode(wl->window->active, &window_more_mode);
|
||||||
window_copy_init_for_output(wl->window->active);
|
|
||||||
}
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
window_copy_vadd(wl->window->active, fmt, ap);
|
window_more_vadd(wl->window->active, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +253,7 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c)
|
|||||||
ctx.cmdclient = NULL;
|
ctx.cmdclient = NULL;
|
||||||
|
|
||||||
readonly = 1;
|
readonly = 1;
|
||||||
TAILQ_FOREACH(cmd, &bd->cmdlist->list, qentry) {
|
TAILQ_FOREACH(cmd, bd->cmdlist, qentry) {
|
||||||
if (!(cmd->entry->flags & CMD_READONLY))
|
if (!(cmd->entry->flags & CMD_READONLY))
|
||||||
readonly = 0;
|
readonly = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
222
key-string.c
222
key-string.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: key-string.c,v 1.34 2010-06-05 20:29:11 micahcowan Exp $ */
|
/* $Id: key-string.c,v 1.29 2010-01-17 19:01:27 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -23,11 +23,10 @@
|
|||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
int key_string_search_table(const char *);
|
int key_string_search_table(const char *);
|
||||||
int key_string_get_modifiers(const char **);
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
const char *string;
|
const char *string;
|
||||||
int key;
|
int key;
|
||||||
} key_string_table[] = {
|
} key_string_table[] = {
|
||||||
/* Function keys. */
|
/* Function keys. */
|
||||||
{ "F1", KEYC_F1 },
|
{ "F1", KEYC_F1 },
|
||||||
@@ -101,131 +100,146 @@ key_string_search_table(const char *string)
|
|||||||
return (KEYC_NONE);
|
return (KEYC_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find modifiers. */
|
/* Lookup a string and convert to a key value, handling C-/M-/S- prefix. */
|
||||||
int
|
|
||||||
key_string_get_modifiers(const char **string)
|
|
||||||
{
|
|
||||||
int modifiers;
|
|
||||||
|
|
||||||
modifiers = 0;
|
|
||||||
while (((*string)[0] != '\0') && (*string)[1] == '-') {
|
|
||||||
switch ((*string)[0]) {
|
|
||||||
case 'C':
|
|
||||||
case 'c':
|
|
||||||
modifiers |= KEYC_CTRL;
|
|
||||||
break;
|
|
||||||
case 'M':
|
|
||||||
case 'm':
|
|
||||||
modifiers |= KEYC_ESCAPE;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
case 's':
|
|
||||||
modifiers |= KEYC_SHIFT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*string += 2;
|
|
||||||
}
|
|
||||||
return (modifiers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lookup a string and convert to a key value. */
|
|
||||||
int
|
int
|
||||||
key_string_lookup_string(const char *string)
|
key_string_lookup_string(const char *string)
|
||||||
{
|
{
|
||||||
int key, modifiers;
|
int key;
|
||||||
|
const char *ptr;
|
||||||
|
|
||||||
/* Check for modifiers. */
|
|
||||||
modifiers = 0;
|
|
||||||
if (string[0] == '^' && string[1] != '\0') {
|
|
||||||
modifiers |= KEYC_CTRL;
|
|
||||||
string++;
|
|
||||||
}
|
|
||||||
modifiers |= key_string_get_modifiers(&string);
|
|
||||||
if (string[0] == '\0')
|
if (string[0] == '\0')
|
||||||
return (KEYC_NONE);
|
return (KEYC_NONE);
|
||||||
|
if (string[1] == '\0')
|
||||||
|
return ((u_char) string[0]);
|
||||||
|
|
||||||
/* Is this a standard ASCII key? */
|
ptr = NULL;
|
||||||
if (string[1] == '\0') {
|
if ((string[0] == 'C' || string[0] == 'c') && string[1] == '-')
|
||||||
key = (u_char) string[0];
|
ptr = string + 2;
|
||||||
if (key < 32 || key > 126)
|
else if (string[0] == '^')
|
||||||
|
ptr = string + 1;
|
||||||
|
if (ptr != NULL) {
|
||||||
|
if (ptr[0] == '\0')
|
||||||
return (KEYC_NONE);
|
return (KEYC_NONE);
|
||||||
} else {
|
/*
|
||||||
/* Otherwise look the key up in the table. */
|
* Lookup as a named key. If a function key (>= KEYC_BASE),
|
||||||
key = key_string_search_table(string);
|
* return it with the ctrl modifier, otherwise fallthrough with
|
||||||
if (key == KEYC_NONE)
|
* the key value from the table (eg for C-Space). If not a
|
||||||
return (KEYC_NONE);
|
* named key, check for single character keys and try that.
|
||||||
}
|
*/
|
||||||
|
key = key_string_search_table(ptr);
|
||||||
|
if (key != KEYC_NONE) {
|
||||||
|
if (key >= KEYC_BASE)
|
||||||
|
return (key | KEYC_CTRL);
|
||||||
|
} else {
|
||||||
|
if (ptr[1] != '\0')
|
||||||
|
return (KEYC_NONE);
|
||||||
|
key = (u_char) ptr[0];
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert the standard control keys. */
|
/*
|
||||||
if (key < KEYC_BASE && (modifiers & KEYC_CTRL)) {
|
* Figure out if the single character in key is a valid ctrl
|
||||||
|
* key.
|
||||||
|
*/
|
||||||
|
if (key == 32)
|
||||||
|
return (0);
|
||||||
|
if (key == 63)
|
||||||
|
return (KEYC_BSPACE);
|
||||||
|
if (key >= 64 && key <= 95)
|
||||||
|
return (key - 64);
|
||||||
if (key >= 97 && key <= 122)
|
if (key >= 97 && key <= 122)
|
||||||
key -= 96;
|
return (key - 96);
|
||||||
else if (key >= 64 && key <= 95)
|
return (KEYC_NONE);
|
||||||
key -= 64;
|
|
||||||
else if (key == 32)
|
|
||||||
key = 0;
|
|
||||||
else if (key == 63)
|
|
||||||
key = KEYC_BSPACE;
|
|
||||||
else
|
|
||||||
return (KEYC_NONE);
|
|
||||||
modifiers &= ~KEYC_CTRL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (key | modifiers);
|
if ((string[0] == 'M' || string[0] == 'm') && string[1] == '-') {
|
||||||
|
ptr = string + 2;
|
||||||
|
if (ptr[0] == '\0')
|
||||||
|
return (KEYC_NONE);
|
||||||
|
key = key_string_lookup_string(ptr);
|
||||||
|
if (key != KEYC_NONE) {
|
||||||
|
if (key >= KEYC_BASE)
|
||||||
|
return (key | KEYC_ESCAPE);
|
||||||
|
} else {
|
||||||
|
if (ptr[1] == '\0')
|
||||||
|
return (KEYC_NONE);
|
||||||
|
key = (u_char) ptr[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key >= 32 && key <= 127)
|
||||||
|
return (key | KEYC_ESCAPE);
|
||||||
|
return (KEYC_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((string[0] == 'S' || string[0] == 's') && string[1] == '-') {
|
||||||
|
ptr = string + 2;
|
||||||
|
if (ptr[0] == '\0')
|
||||||
|
return (KEYC_NONE);
|
||||||
|
key = key_string_lookup_string(ptr);
|
||||||
|
if (key != KEYC_NONE) {
|
||||||
|
if (key >= KEYC_BASE)
|
||||||
|
return (key | KEYC_SHIFT);
|
||||||
|
} else {
|
||||||
|
if (ptr[1] == '\0')
|
||||||
|
return (KEYC_NONE);
|
||||||
|
key = (u_char) ptr[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key >= 32 && key <= 127)
|
||||||
|
return (key | KEYC_SHIFT);
|
||||||
|
return (KEYC_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (key_string_search_table(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert a key code into string format, with prefix if necessary. */
|
/* Convert a key code into string format, with prefix if necessary. */
|
||||||
const char *
|
const char *
|
||||||
key_string_lookup_key(int key)
|
key_string_lookup_key(int key)
|
||||||
{
|
{
|
||||||
static char out[24];
|
static char tmp[24], tmp2[24];
|
||||||
char tmp[8];
|
const char *s;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
*out = '\0';
|
if (key == 127)
|
||||||
|
|
||||||
/*
|
|
||||||
* Special case: display C-@ as C-Space. Could do this below in
|
|
||||||
* the (key >= 0 && key <= 32), but this way we let it be found
|
|
||||||
* in key_string_table, for the unlikely chance that we might
|
|
||||||
* change its name.
|
|
||||||
*/
|
|
||||||
if ((key & KEYC_MASK_KEY) == 0)
|
|
||||||
key = ' ' | KEYC_CTRL | (key & KEYC_MASK_MOD);
|
|
||||||
|
|
||||||
/* Fill in the modifiers. */
|
|
||||||
if (key & KEYC_CTRL)
|
|
||||||
strlcat(out, "C-", sizeof out);
|
|
||||||
if (key & KEYC_ESCAPE)
|
|
||||||
strlcat(out, "M-", sizeof out);
|
|
||||||
if (key & KEYC_SHIFT)
|
|
||||||
strlcat(out, "S-", sizeof out);
|
|
||||||
key &= KEYC_MASK_KEY;
|
|
||||||
|
|
||||||
/* Try the key against the string table. */
|
|
||||||
for (i = 0; i < nitems(key_string_table); i++) {
|
|
||||||
if (key == key_string_table[i].key)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i != nitems(key_string_table)) {
|
|
||||||
strlcat(out, key_string_table[i].string, sizeof out);
|
|
||||||
return (out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Invalid keys are errors. */
|
|
||||||
if (key >= 127)
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
/* Check for standard or control key. */
|
if (key & KEYC_ESCAPE) {
|
||||||
|
if ((s = key_string_lookup_key(key & ~KEYC_ESCAPE)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
xsnprintf(tmp2, sizeof tmp2, "M-%s", s);
|
||||||
|
return (tmp2);
|
||||||
|
}
|
||||||
|
if (key & KEYC_CTRL) {
|
||||||
|
if ((s = key_string_lookup_key(key & ~KEYC_CTRL)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
xsnprintf(tmp2, sizeof tmp2, "C-%s", s);
|
||||||
|
return (tmp2);
|
||||||
|
}
|
||||||
|
if (key & KEYC_SHIFT) {
|
||||||
|
if ((s = key_string_lookup_key(key & ~KEYC_SHIFT)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
xsnprintf(tmp2, sizeof tmp2, "S-%s", s);
|
||||||
|
return (tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nitems(key_string_table); i++) {
|
||||||
|
if (key == key_string_table[i].key)
|
||||||
|
return (key_string_table[i].string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key >= 32 && key <= 255) {
|
||||||
|
tmp[0] = (char) key;
|
||||||
|
tmp[1] = '\0';
|
||||||
|
return (tmp);
|
||||||
|
}
|
||||||
|
|
||||||
if (key >= 0 && key <= 32) {
|
if (key >= 0 && key <= 32) {
|
||||||
if (key == 0 || key > 26)
|
if (key == 0 || key > 26)
|
||||||
xsnprintf(tmp, sizeof tmp, "C-%c", 64 + key);
|
xsnprintf(tmp, sizeof tmp, "C-%c", 64 + key);
|
||||||
else
|
else
|
||||||
xsnprintf(tmp, sizeof tmp, "C-%c", 96 + key);
|
xsnprintf(tmp, sizeof tmp, "C-%c", 96 + key);
|
||||||
} else if (key >= 32 && key <= 126) {
|
return (tmp);
|
||||||
tmp[0] = key;
|
|
||||||
tmp[1] = '\0';
|
|
||||||
}
|
}
|
||||||
strlcat(out, tmp, sizeof out);
|
|
||||||
return (out);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
264
layout-custom.c
264
layout-custom.c
@@ -1,264 +0,0 @@
|
|||||||
/* $Id: layout-custom.c,v 1.1 2010-07-02 02:54:52 tcunha Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
u_short layout_checksum(const char *);
|
|
||||||
int layout_append(struct layout_cell *, char *, size_t);
|
|
||||||
struct layout_cell *layout_construct(struct layout_cell *, const char **);
|
|
||||||
void layout_assign(struct window_pane **, struct layout_cell *);
|
|
||||||
|
|
||||||
/* Calculate layout checksum. */
|
|
||||||
u_short
|
|
||||||
layout_checksum(const char *layout)
|
|
||||||
{
|
|
||||||
u_short csum;
|
|
||||||
|
|
||||||
csum = 0;
|
|
||||||
for (; *layout != '\0'; layout++) {
|
|
||||||
csum = (csum >> 1) + ((csum & 1) << 15);
|
|
||||||
csum += *layout;
|
|
||||||
}
|
|
||||||
return (csum);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dump layout as a string. */
|
|
||||||
char *
|
|
||||||
layout_dump(struct window *w)
|
|
||||||
{
|
|
||||||
char layout[BUFSIZ], *out;
|
|
||||||
|
|
||||||
*layout = '\0';
|
|
||||||
if (layout_append(w->layout_root, layout, sizeof layout) != 0)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
xasprintf(&out, "%4x,%s", layout_checksum(layout), layout);
|
|
||||||
return (out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append information for a single cell. */
|
|
||||||
int
|
|
||||||
layout_append(struct layout_cell *lc, char *buf, size_t len)
|
|
||||||
{
|
|
||||||
struct layout_cell *lcchild;
|
|
||||||
char tmp[64];
|
|
||||||
size_t tmplen;
|
|
||||||
const char *brackets = "][";
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
tmplen = xsnprintf(tmp, sizeof tmp,
|
|
||||||
"%ux%u,%u,%u", lc->sx, lc->sy, lc->xoff, lc->yoff);
|
|
||||||
if (tmplen > (sizeof tmp) - 1)
|
|
||||||
return (-1);
|
|
||||||
if (strlcat(buf, tmp, len) >= len)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
switch (lc->type) {
|
|
||||||
case LAYOUT_LEFTRIGHT:
|
|
||||||
brackets = "}{";
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case LAYOUT_TOPBOTTOM:
|
|
||||||
if (strlcat(buf, &brackets[1], len) >= len)
|
|
||||||
return (-1);
|
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
|
||||||
if (layout_append(lcchild, buf, len) != 0)
|
|
||||||
return (-1);
|
|
||||||
if (strlcat(buf, ",", len) >= len)
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
buf[strlen(buf) - 1] = brackets[0];
|
|
||||||
break;
|
|
||||||
case LAYOUT_WINDOWPANE:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse a layout string and arrange window as layout. */
|
|
||||||
int
|
|
||||||
layout_parse(struct window *w, const char *layout)
|
|
||||||
{
|
|
||||||
struct layout_cell *lc, *lcchild;
|
|
||||||
struct window_pane *wp;
|
|
||||||
u_int npanes, ncells, sx, sy;
|
|
||||||
u_short csum;
|
|
||||||
|
|
||||||
/* Check validity. */
|
|
||||||
if (sscanf(layout, "%hx,", &csum) != 1)
|
|
||||||
return (-1);
|
|
||||||
layout += 5;
|
|
||||||
if (csum != layout_checksum(layout))
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
/* Build the layout. */
|
|
||||||
lc = layout_construct(NULL, &layout);
|
|
||||||
if (lc == NULL)
|
|
||||||
return (-1);
|
|
||||||
if (*layout != '\0')
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* Check this window will fit into the layout. */
|
|
||||||
for (;;) {
|
|
||||||
npanes = window_count_panes(w);
|
|
||||||
ncells = layout_count_cells(lc);
|
|
||||||
if (npanes > ncells)
|
|
||||||
goto fail;
|
|
||||||
if (npanes == ncells)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Fewer panes than cells - close the bottom right. */
|
|
||||||
lcchild = layout_find_bottomright(lc);
|
|
||||||
layout_destroy_cell(lcchild, &lc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save the old window size and resize to the layout size. */
|
|
||||||
sx = w->sx; sy = w->sy;
|
|
||||||
window_resize(w, lc->sx, lc->sy);
|
|
||||||
|
|
||||||
/* Destroy the old layout and swap to the new. */
|
|
||||||
layout_free_cell(w->layout_root);
|
|
||||||
w->layout_root = lc;
|
|
||||||
|
|
||||||
/* Assign the panes into the cells. */
|
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
|
||||||
layout_assign(&wp, lc);
|
|
||||||
|
|
||||||
/* Update pane offsets and sizes. */
|
|
||||||
layout_fix_offsets(lc);
|
|
||||||
layout_fix_panes(w, lc->sx, lc->sy);
|
|
||||||
|
|
||||||
/* Then resize the layout back to the original window size. */
|
|
||||||
layout_resize(w, sx, sy);
|
|
||||||
window_resize(w, sx, sy);
|
|
||||||
|
|
||||||
layout_print_cell(lc, __func__, 0);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
fail:
|
|
||||||
layout_free_cell(lc);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assign panes into cells. */
|
|
||||||
void
|
|
||||||
layout_assign(struct window_pane **wp, struct layout_cell *lc)
|
|
||||||
{
|
|
||||||
struct layout_cell *lcchild;
|
|
||||||
|
|
||||||
switch (lc->type) {
|
|
||||||
case LAYOUT_WINDOWPANE:
|
|
||||||
layout_make_leaf(lc, *wp);
|
|
||||||
*wp = TAILQ_NEXT(*wp, entry);
|
|
||||||
return;
|
|
||||||
case LAYOUT_LEFTRIGHT:
|
|
||||||
case LAYOUT_TOPBOTTOM:
|
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
|
||||||
layout_assign(wp, lcchild);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Construct a cell from all or part of a layout tree. */
|
|
||||||
struct layout_cell *
|
|
||||||
layout_construct(struct layout_cell *lcparent, const char **layout)
|
|
||||||
{
|
|
||||||
struct layout_cell *lc, *lcchild;
|
|
||||||
u_int sx, sy, xoff, yoff;
|
|
||||||
|
|
||||||
if (!isdigit((u_char) **layout))
|
|
||||||
return (NULL);
|
|
||||||
if (sscanf(*layout, "%ux%u,%u,%u", &sx, &sy, &xoff, &yoff) != 4)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
while (isdigit((u_char) **layout))
|
|
||||||
(*layout)++;
|
|
||||||
if (**layout != 'x')
|
|
||||||
return (NULL);
|
|
||||||
(*layout)++;
|
|
||||||
while (isdigit((u_char) **layout))
|
|
||||||
(*layout)++;
|
|
||||||
if (**layout != ',')
|
|
||||||
return (NULL);
|
|
||||||
(*layout)++;
|
|
||||||
while (isdigit((u_char) **layout))
|
|
||||||
(*layout)++;
|
|
||||||
if (**layout != ',')
|
|
||||||
return (NULL);
|
|
||||||
(*layout)++;
|
|
||||||
while (isdigit((u_char) **layout))
|
|
||||||
(*layout)++;
|
|
||||||
|
|
||||||
lc = layout_create_cell(lcparent);
|
|
||||||
lc->sx = sx;
|
|
||||||
lc->sy = sy;
|
|
||||||
lc->xoff = xoff;
|
|
||||||
lc->yoff = yoff;
|
|
||||||
|
|
||||||
switch (**layout) {
|
|
||||||
case ',':
|
|
||||||
case '}':
|
|
||||||
case ']':
|
|
||||||
case '\0':
|
|
||||||
return (lc);
|
|
||||||
case '{':
|
|
||||||
lc->type = LAYOUT_LEFTRIGHT;
|
|
||||||
break;
|
|
||||||
case '[':
|
|
||||||
lc->type = LAYOUT_TOPBOTTOM;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
(*layout)++;
|
|
||||||
lcchild = layout_construct(lc, layout);
|
|
||||||
if (lcchild == NULL)
|
|
||||||
goto fail;
|
|
||||||
TAILQ_INSERT_TAIL(&lc->cells, lcchild, entry);
|
|
||||||
} while (**layout == ',');
|
|
||||||
|
|
||||||
switch (lc->type) {
|
|
||||||
case LAYOUT_LEFTRIGHT:
|
|
||||||
if (**layout != '}')
|
|
||||||
goto fail;
|
|
||||||
break;
|
|
||||||
case LAYOUT_TOPBOTTOM:
|
|
||||||
if (**layout != ']')
|
|
||||||
goto fail;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
(*layout)++;
|
|
||||||
|
|
||||||
return (lc);
|
|
||||||
|
|
||||||
fail:
|
|
||||||
layout_free_cell(lc);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
194
layout-set.c
194
layout-set.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: layout-set.c,v 1.8 2010-12-22 15:23:59 tcunha Exp $ */
|
/* $Id: layout-set.c,v 1.5 2010-02-05 01:29:04 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -31,7 +31,6 @@ void layout_set_even_h(struct window *);
|
|||||||
void layout_set_even_v(struct window *);
|
void layout_set_even_v(struct window *);
|
||||||
void layout_set_main_h(struct window *);
|
void layout_set_main_h(struct window *);
|
||||||
void layout_set_main_v(struct window *);
|
void layout_set_main_v(struct window *);
|
||||||
void layout_set_tiled(struct window *);
|
|
||||||
|
|
||||||
const struct {
|
const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -41,7 +40,6 @@ const struct {
|
|||||||
{ "even-vertical", layout_set_even_v },
|
{ "even-vertical", layout_set_even_v },
|
||||||
{ "main-horizontal", layout_set_main_h },
|
{ "main-horizontal", layout_set_main_h },
|
||||||
{ "main-vertical", layout_set_main_v },
|
{ "main-vertical", layout_set_main_v },
|
||||||
{ "tiled", layout_set_tiled },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
@@ -135,9 +133,10 @@ layout_set_even_h(struct window *w)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* How many can we fit? */
|
/* How many can we fit? */
|
||||||
width = (w->sx - (n - 1)) / n;
|
if (w->sx / n < PANE_MINIMUM + 1)
|
||||||
if (width < PANE_MINIMUM)
|
width = PANE_MINIMUM + 1;
|
||||||
width = PANE_MINIMUM;
|
else
|
||||||
|
width = w->sx / n;
|
||||||
|
|
||||||
/* Free the old root and construct a new. */
|
/* Free the old root and construct a new. */
|
||||||
layout_free(w);
|
layout_free(w);
|
||||||
@@ -150,12 +149,12 @@ layout_set_even_h(struct window *w)
|
|||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
/* Create child cell. */
|
/* Create child cell. */
|
||||||
lcnew = layout_create_cell(lc);
|
lcnew = layout_create_cell(lc);
|
||||||
layout_set_size(lcnew, width, w->sy, xoff, 0);
|
layout_set_size(lcnew, width - 1, w->sy, xoff, 0);
|
||||||
layout_make_leaf(lcnew, wp);
|
layout_make_leaf(lcnew, wp);
|
||||||
TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
|
TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
xoff += width + 1;
|
xoff += width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate any remaining space. */
|
/* Allocate any remaining space. */
|
||||||
@@ -188,9 +187,10 @@ layout_set_even_v(struct window *w)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* How many can we fit? */
|
/* How many can we fit? */
|
||||||
height = (w->sy - (n - 1)) / n;
|
if (w->sy / n < PANE_MINIMUM + 1)
|
||||||
if (height < PANE_MINIMUM)
|
height = PANE_MINIMUM + 1;
|
||||||
height = PANE_MINIMUM;
|
else
|
||||||
|
height = w->sy / n;
|
||||||
|
|
||||||
/* Free the old root and construct a new. */
|
/* Free the old root and construct a new. */
|
||||||
layout_free(w);
|
layout_free(w);
|
||||||
@@ -203,12 +203,12 @@ layout_set_even_v(struct window *w)
|
|||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
/* Create child cell. */
|
/* Create child cell. */
|
||||||
lcnew = layout_create_cell(lc);
|
lcnew = layout_create_cell(lc);
|
||||||
layout_set_size(lcnew, w->sx, height, 0, yoff);
|
layout_set_size(lcnew, w->sx, height - 1, 0, yoff);
|
||||||
layout_make_leaf(lcnew, wp);
|
layout_make_leaf(lcnew, wp);
|
||||||
TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
|
TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
yoff += height + 1;
|
yoff += height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate any remaining space. */
|
/* Allocate any remaining space. */
|
||||||
@@ -231,8 +231,8 @@ layout_set_main_h(struct window *w)
|
|||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct layout_cell *lc, *lcmain, *lcrow, *lcchild;
|
struct layout_cell *lc, *lcmain, *lcrow, *lcchild;
|
||||||
u_int n, mainheight, otherheight, width, height;
|
u_int n, mainheight, width, height, used;
|
||||||
u_int used, i, j, columns, rows, totalrows;
|
u_int i, j, columns, rows, totalrows;
|
||||||
|
|
||||||
layout_print_cell(w->layout_root, __func__, 1);
|
layout_print_cell(w->layout_root, __func__, 1);
|
||||||
|
|
||||||
@@ -242,26 +242,16 @@ layout_set_main_h(struct window *w)
|
|||||||
return;
|
return;
|
||||||
n--; /* take off main pane */
|
n--; /* take off main pane */
|
||||||
|
|
||||||
/* How many rows and columns will be needed, not counting main? */
|
/* How many rows and columns will be needed? */
|
||||||
columns = (w->sx + 1) / (PANE_MINIMUM + 1); /* maximum columns */
|
columns = w->sx / (PANE_MINIMUM + 1); /* maximum columns */
|
||||||
if (columns == 0)
|
if (columns == 0)
|
||||||
columns = 1;
|
columns = 1;
|
||||||
rows = 1 + (n - 1) / columns;
|
rows = 1 + (n - 1) / columns;
|
||||||
columns = 1 + (n - 1) / rows;
|
columns = 1 + (n - 1) / rows;
|
||||||
width = (w->sx - (n - 1)) / columns;
|
width = w->sx / columns;
|
||||||
|
|
||||||
/* Get the main pane height and add one for separator line. */
|
/* Get the main pane height and add one for separator line. */
|
||||||
mainheight = options_get_number(&w->options, "main-pane-height") + 1;
|
mainheight = options_get_number(&w->options, "main-pane-height") + 1;
|
||||||
|
|
||||||
/* Get the optional other pane height and add one for separator line. */
|
|
||||||
otherheight = options_get_number(&w->options, "other-pane-height") + 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If an other pane height was specified, honour it so long as it
|
|
||||||
* doesn't shrink the main height to less than the main-pane-height
|
|
||||||
*/
|
|
||||||
if (otherheight > 1 && w->sx - otherheight > mainheight)
|
|
||||||
mainheight = w->sx - otherheight;
|
|
||||||
if (mainheight < PANE_MINIMUM + 1)
|
if (mainheight < PANE_MINIMUM + 1)
|
||||||
mainheight = PANE_MINIMUM + 1;
|
mainheight = PANE_MINIMUM + 1;
|
||||||
|
|
||||||
@@ -272,14 +262,14 @@ layout_set_main_h(struct window *w)
|
|||||||
mainheight = PANE_MINIMUM + 2;
|
mainheight = PANE_MINIMUM + 2;
|
||||||
else
|
else
|
||||||
mainheight = w->sy - totalrows;
|
mainheight = w->sy - totalrows;
|
||||||
height = PANE_MINIMUM;
|
height = PANE_MINIMUM + 1;
|
||||||
} else
|
} else
|
||||||
height = (w->sy - mainheight - (rows - 1)) / rows;
|
height = (w->sy - mainheight) / rows;
|
||||||
|
|
||||||
/* Free old tree and create a new root. */
|
/* Free old tree and create a new root. */
|
||||||
layout_free(w);
|
layout_free(w);
|
||||||
lc = w->layout_root = layout_create_cell(NULL);
|
lc = w->layout_root = layout_create_cell(NULL);
|
||||||
layout_set_size(lc, w->sx, mainheight + rows * (height + 1) - 1, 0, 0);
|
layout_set_size(lc, w->sx, mainheight + rows * height, 0, 0);
|
||||||
layout_make_node(lc, LAYOUT_TOPBOTTOM);
|
layout_make_node(lc, LAYOUT_TOPBOTTOM);
|
||||||
|
|
||||||
/* Create the main pane. */
|
/* Create the main pane. */
|
||||||
@@ -297,7 +287,7 @@ layout_set_main_h(struct window *w)
|
|||||||
|
|
||||||
/* Create the new row. */
|
/* Create the new row. */
|
||||||
lcrow = layout_create_cell(lc);
|
lcrow = layout_create_cell(lc);
|
||||||
layout_set_size(lcrow, w->sx, height, 0, 0);
|
layout_set_size(lcrow, w->sx, height - 1, 0, 0);
|
||||||
TAILQ_INSERT_TAIL(&lc->cells, lcrow, entry);
|
TAILQ_INSERT_TAIL(&lc->cells, lcrow, entry);
|
||||||
|
|
||||||
/* If only one column, just use the row directly. */
|
/* If only one column, just use the row directly. */
|
||||||
@@ -312,7 +302,7 @@ layout_set_main_h(struct window *w)
|
|||||||
for (i = 0; i < columns; i++) {
|
for (i = 0; i < columns; i++) {
|
||||||
/* Create and add a pane cell. */
|
/* Create and add a pane cell. */
|
||||||
lcchild = layout_create_cell(lcrow);
|
lcchild = layout_create_cell(lcrow);
|
||||||
layout_set_size(lcchild, width, height, 0, 0);
|
layout_set_size(lcchild, width - 1, height - 1, 0, 0);
|
||||||
layout_make_leaf(lcchild, wp);
|
layout_make_leaf(lcchild, wp);
|
||||||
TAILQ_INSERT_TAIL(&lcrow->cells, lcchild, entry);
|
TAILQ_INSERT_TAIL(&lcrow->cells, lcchild, entry);
|
||||||
|
|
||||||
@@ -324,7 +314,7 @@ layout_set_main_h(struct window *w)
|
|||||||
/* Adjust the row to fit the full width if necessary. */
|
/* Adjust the row to fit the full width if necessary. */
|
||||||
if (i == columns)
|
if (i == columns)
|
||||||
i--;
|
i--;
|
||||||
used = ((i + 1) * (width + 1)) - 1;
|
used = ((i + 1) * width) - 1;
|
||||||
if (w->sx <= used)
|
if (w->sx <= used)
|
||||||
continue;
|
continue;
|
||||||
lcchild = TAILQ_LAST(&lcrow->cells, layout_cells);
|
lcchild = TAILQ_LAST(&lcrow->cells, layout_cells);
|
||||||
@@ -332,7 +322,7 @@ layout_set_main_h(struct window *w)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust the last row height to fit if necessary. */
|
/* Adjust the last row height to fit if necessary. */
|
||||||
used = mainheight + (rows * height) + rows - 1;
|
used = mainheight + (rows * height) - 1;
|
||||||
if (w->sy > used) {
|
if (w->sy > used) {
|
||||||
lcrow = TAILQ_LAST(&lc->cells, layout_cells);
|
lcrow = TAILQ_LAST(&lc->cells, layout_cells);
|
||||||
layout_resize_adjust(lcrow, LAYOUT_TOPBOTTOM, w->sy - used);
|
layout_resize_adjust(lcrow, LAYOUT_TOPBOTTOM, w->sy - used);
|
||||||
@@ -352,8 +342,8 @@ layout_set_main_v(struct window *w)
|
|||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct layout_cell *lc, *lcmain, *lccolumn, *lcchild;
|
struct layout_cell *lc, *lcmain, *lccolumn, *lcchild;
|
||||||
u_int n, mainwidth, otherwidth, width, height;
|
u_int n, mainwidth, width, height, used;
|
||||||
u_int used, i, j, columns, rows, totalcolumns;
|
u_int i, j, columns, rows, totalcolumns;
|
||||||
|
|
||||||
layout_print_cell(w->layout_root, __func__, 1);
|
layout_print_cell(w->layout_root, __func__, 1);
|
||||||
|
|
||||||
@@ -363,26 +353,16 @@ layout_set_main_v(struct window *w)
|
|||||||
return;
|
return;
|
||||||
n--; /* take off main pane */
|
n--; /* take off main pane */
|
||||||
|
|
||||||
/* How many rows and columns will be needed, not counting main? */
|
/* How many rows and columns will be needed? */
|
||||||
rows = (w->sy + 1) / (PANE_MINIMUM + 1); /* maximum rows */
|
rows = w->sy / (PANE_MINIMUM + 1); /* maximum rows */
|
||||||
if (rows == 0)
|
if (rows == 0)
|
||||||
rows = 1;
|
rows = 1;
|
||||||
columns = 1 + (n - 1) / rows;
|
columns = 1 + (n - 1) / rows;
|
||||||
rows = 1 + (n - 1) / columns;
|
rows = 1 + (n - 1) / columns;
|
||||||
height = (w->sy - (n - 1)) / rows;
|
height = w->sy / rows;
|
||||||
|
|
||||||
/* Get the main pane width and add one for separator line. */
|
/* Get the main pane width and add one for separator line. */
|
||||||
mainwidth = options_get_number(&w->options, "main-pane-width") + 1;
|
mainwidth = options_get_number(&w->options, "main-pane-width") + 1;
|
||||||
|
|
||||||
/* Get the optional other pane width and add one for separator line. */
|
|
||||||
otherwidth = options_get_number(&w->options, "other-pane-width") + 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If an other pane width was specified, honour it so long as it
|
|
||||||
* doesn't shrink the main width to less than the main-pane-width
|
|
||||||
*/
|
|
||||||
if (otherwidth > 1 && w->sx - otherwidth > mainwidth)
|
|
||||||
mainwidth = w->sx - otherwidth;
|
|
||||||
if (mainwidth < PANE_MINIMUM + 1)
|
if (mainwidth < PANE_MINIMUM + 1)
|
||||||
mainwidth = PANE_MINIMUM + 1;
|
mainwidth = PANE_MINIMUM + 1;
|
||||||
|
|
||||||
@@ -393,14 +373,14 @@ layout_set_main_v(struct window *w)
|
|||||||
mainwidth = PANE_MINIMUM + 2;
|
mainwidth = PANE_MINIMUM + 2;
|
||||||
else
|
else
|
||||||
mainwidth = w->sx - totalcolumns;
|
mainwidth = w->sx - totalcolumns;
|
||||||
width = PANE_MINIMUM;
|
width = PANE_MINIMUM + 1;
|
||||||
} else
|
} else
|
||||||
width = (w->sx - mainwidth - (columns - 1)) / columns;
|
width = (w->sx - mainwidth) / columns;
|
||||||
|
|
||||||
/* Free old tree and create a new root. */
|
/* Free old tree and create a new root. */
|
||||||
layout_free(w);
|
layout_free(w);
|
||||||
lc = w->layout_root = layout_create_cell(NULL);
|
lc = w->layout_root = layout_create_cell(NULL);
|
||||||
layout_set_size(lc, mainwidth + columns * (width + 1) - 1, w->sy, 0, 0);
|
layout_set_size(lc, mainwidth + columns * width, w->sy, 0, 0);
|
||||||
layout_make_node(lc, LAYOUT_LEFTRIGHT);
|
layout_make_node(lc, LAYOUT_LEFTRIGHT);
|
||||||
|
|
||||||
/* Create the main pane. */
|
/* Create the main pane. */
|
||||||
@@ -418,7 +398,7 @@ layout_set_main_v(struct window *w)
|
|||||||
|
|
||||||
/* Create the new column. */
|
/* Create the new column. */
|
||||||
lccolumn = layout_create_cell(lc);
|
lccolumn = layout_create_cell(lc);
|
||||||
layout_set_size(lccolumn, width, w->sy, 0, 0);
|
layout_set_size(lccolumn, width - 1, w->sy, 0, 0);
|
||||||
TAILQ_INSERT_TAIL(&lc->cells, lccolumn, entry);
|
TAILQ_INSERT_TAIL(&lc->cells, lccolumn, entry);
|
||||||
|
|
||||||
/* If only one row, just use the row directly. */
|
/* If only one row, just use the row directly. */
|
||||||
@@ -433,7 +413,7 @@ layout_set_main_v(struct window *w)
|
|||||||
for (i = 0; i < rows; i++) {
|
for (i = 0; i < rows; i++) {
|
||||||
/* Create and add a pane cell. */
|
/* Create and add a pane cell. */
|
||||||
lcchild = layout_create_cell(lccolumn);
|
lcchild = layout_create_cell(lccolumn);
|
||||||
layout_set_size(lcchild, width, height, 0, 0);
|
layout_set_size(lcchild, width - 1, height - 1, 0, 0);
|
||||||
layout_make_leaf(lcchild, wp);
|
layout_make_leaf(lcchild, wp);
|
||||||
TAILQ_INSERT_TAIL(&lccolumn->cells, lcchild, entry);
|
TAILQ_INSERT_TAIL(&lccolumn->cells, lcchild, entry);
|
||||||
|
|
||||||
@@ -445,7 +425,7 @@ layout_set_main_v(struct window *w)
|
|||||||
/* Adjust the column to fit the full height if necessary. */
|
/* Adjust the column to fit the full height if necessary. */
|
||||||
if (i == rows)
|
if (i == rows)
|
||||||
i--;
|
i--;
|
||||||
used = ((i + 1) * (height + 1)) - 1;
|
used = ((i + 1) * height) - 1;
|
||||||
if (w->sy <= used)
|
if (w->sy <= used)
|
||||||
continue;
|
continue;
|
||||||
lcchild = TAILQ_LAST(&lccolumn->cells, layout_cells);
|
lcchild = TAILQ_LAST(&lccolumn->cells, layout_cells);
|
||||||
@@ -453,7 +433,7 @@ layout_set_main_v(struct window *w)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust the last column width to fit if necessary. */
|
/* Adjust the last column width to fit if necessary. */
|
||||||
used = mainwidth + (columns * width) + columns - 1;
|
used = mainwidth + (columns * width) - 1;
|
||||||
if (w->sx > used) {
|
if (w->sx > used) {
|
||||||
lccolumn = TAILQ_LAST(&lc->cells, layout_cells);
|
lccolumn = TAILQ_LAST(&lc->cells, layout_cells);
|
||||||
layout_resize_adjust(lccolumn, LAYOUT_LEFTRIGHT, w->sx - used);
|
layout_resize_adjust(lccolumn, LAYOUT_LEFTRIGHT, w->sx - used);
|
||||||
@@ -467,103 +447,3 @@ layout_set_main_v(struct window *w)
|
|||||||
|
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
layout_set_tiled(struct window *w)
|
|
||||||
{
|
|
||||||
struct window_pane *wp;
|
|
||||||
struct layout_cell *lc, *lcrow, *lcchild;
|
|
||||||
u_int n, width, height, used;
|
|
||||||
u_int i, j, columns, rows;
|
|
||||||
|
|
||||||
layout_print_cell(w->layout_root, __func__, 1);
|
|
||||||
|
|
||||||
/* Get number of panes. */
|
|
||||||
n = window_count_panes(w);
|
|
||||||
if (n <= 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* How many rows and columns are wanted? */
|
|
||||||
rows = columns = 1;
|
|
||||||
while (rows * columns < n) {
|
|
||||||
rows++;
|
|
||||||
if (rows * columns < n)
|
|
||||||
columns++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* What width and height should they be? */
|
|
||||||
width = (w->sx - (columns - 1)) / columns;
|
|
||||||
if (width < PANE_MINIMUM)
|
|
||||||
width = PANE_MINIMUM;
|
|
||||||
height = (w->sy - (rows - 1)) / rows;
|
|
||||||
if (height < PANE_MINIMUM)
|
|
||||||
height = PANE_MINIMUM;
|
|
||||||
|
|
||||||
/* Free old tree and create a new root. */
|
|
||||||
layout_free(w);
|
|
||||||
lc = w->layout_root = layout_create_cell(NULL);
|
|
||||||
layout_set_size(lc, (width + 1) * columns - 1,
|
|
||||||
(height + 1) * rows - 1, 0, 0);
|
|
||||||
layout_make_node(lc, LAYOUT_TOPBOTTOM);
|
|
||||||
|
|
||||||
/* Create a grid of the cells. */
|
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
|
||||||
for (j = 0; j < rows; j++) {
|
|
||||||
/* If this is the last cell, all done. */
|
|
||||||
if (wp == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Create the new row. */
|
|
||||||
lcrow = layout_create_cell(lc);
|
|
||||||
layout_set_size(lcrow, w->sx, height, 0, 0);
|
|
||||||
TAILQ_INSERT_TAIL(&lc->cells, lcrow, entry);
|
|
||||||
|
|
||||||
/* If only one column, just use the row directly. */
|
|
||||||
if (n - (j * columns) == 1) {
|
|
||||||
layout_make_leaf(lcrow, wp);
|
|
||||||
wp = TAILQ_NEXT(wp, entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add in the columns. */
|
|
||||||
layout_make_node(lcrow, LAYOUT_LEFTRIGHT);
|
|
||||||
for (i = 0; i < columns; i++) {
|
|
||||||
/* Create and add a pane cell. */
|
|
||||||
lcchild = layout_create_cell(lcrow);
|
|
||||||
layout_set_size(lcchild, width, height, 0, 0);
|
|
||||||
layout_make_leaf(lcchild, wp);
|
|
||||||
TAILQ_INSERT_TAIL(&lcrow->cells, lcchild, entry);
|
|
||||||
|
|
||||||
/* Move to the next cell. */
|
|
||||||
if ((wp = TAILQ_NEXT(wp, entry)) == NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Adjust the row and columns to fit the full width if
|
|
||||||
* necessary.
|
|
||||||
*/
|
|
||||||
if (i == columns)
|
|
||||||
i--;
|
|
||||||
used = ((i + 1) * (width + 1)) - 1;
|
|
||||||
if (w->sx <= used)
|
|
||||||
continue;
|
|
||||||
lcchild = TAILQ_LAST(&lcrow->cells, layout_cells);
|
|
||||||
layout_resize_adjust(lcchild, LAYOUT_LEFTRIGHT, w->sx - used);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust the last row height to fit if necessary. */
|
|
||||||
used = (rows * height) + rows - 1;
|
|
||||||
if (w->sy > used) {
|
|
||||||
lcrow = TAILQ_LAST(&lc->cells, layout_cells);
|
|
||||||
layout_resize_adjust(lcrow, LAYOUT_TOPBOTTOM, w->sy - used);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fix cell offsets. */
|
|
||||||
layout_fix_offsets(lc);
|
|
||||||
layout_fix_panes(w, w->sx, w->sy);
|
|
||||||
|
|
||||||
layout_print_cell(w->layout_root, __func__, 1);
|
|
||||||
|
|
||||||
server_redraw_window(w);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: layout-string.c,v 1.4 2010-07-02 02:54:52 tcunha Exp $ */
|
/* $Id: layout-string.c,v 1.3 2010-01-08 16:28:04 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -36,6 +36,7 @@ struct layout_cell *layout_find_right(struct layout_cell *);
|
|||||||
struct layout_cell *layout_find_topleft(struct layout_cell *);
|
struct layout_cell *layout_find_topleft(struct layout_cell *);
|
||||||
struct layout_cell *layout_find_topright(struct layout_cell *);
|
struct layout_cell *layout_find_topright(struct layout_cell *);
|
||||||
struct layout_cell *layout_find_bottomleft(struct layout_cell *);
|
struct layout_cell *layout_find_bottomleft(struct layout_cell *);
|
||||||
|
struct layout_cell *layout_find_bottomright(struct layout_cell *);
|
||||||
|
|
||||||
/* Find the cell; returns NULL if string not understood. */
|
/* Find the cell; returns NULL if string not understood. */
|
||||||
struct layout_cell *
|
struct layout_cell *
|
||||||
|
|||||||
130
layout.c
130
layout.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: layout.c,v 1.19 2010-07-02 02:54:52 tcunha Exp $ */
|
/* $Id: layout.c,v 1.18 2010-01-08 16:31:35 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -218,27 +218,6 @@ layout_fix_panes(struct window *w, u_int wsx, u_int wsy)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Count the number of available cells in a layout. */
|
|
||||||
u_int
|
|
||||||
layout_count_cells(struct layout_cell *lc)
|
|
||||||
{
|
|
||||||
struct layout_cell *lcchild;
|
|
||||||
u_int n;
|
|
||||||
|
|
||||||
switch (lc->type) {
|
|
||||||
case LAYOUT_WINDOWPANE:
|
|
||||||
return (1);
|
|
||||||
case LAYOUT_LEFTRIGHT:
|
|
||||||
case LAYOUT_TOPBOTTOM:
|
|
||||||
n = 0;
|
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
|
||||||
n += layout_count_cells(lcchild);
|
|
||||||
return (n);
|
|
||||||
default:
|
|
||||||
fatalx("bad layout type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate how much size is available to be removed from a cell. */
|
/* Calculate how much size is available to be removed from a cell. */
|
||||||
u_int
|
u_int
|
||||||
layout_resize_check(struct layout_cell *lc, enum layout_type type)
|
layout_resize_check(struct layout_cell *lc, enum layout_type type)
|
||||||
@@ -323,56 +302,6 @@ layout_resize_adjust(struct layout_cell *lc, enum layout_type type, int change)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy a cell and redistribute the space. */
|
|
||||||
void
|
|
||||||
layout_destroy_cell(struct layout_cell *lc, struct layout_cell **lcroot)
|
|
||||||
{
|
|
||||||
struct layout_cell *lcother, *lcparent;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If no parent, this is the last pane so window close is imminent and
|
|
||||||
* there is no need to resize anything.
|
|
||||||
*/
|
|
||||||
lcparent = lc->parent;
|
|
||||||
if (lcparent == NULL) {
|
|
||||||
layout_free_cell(lc);
|
|
||||||
*lcroot = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Merge the space into the previous or next cell. */
|
|
||||||
if (lc == TAILQ_FIRST(&lcparent->cells))
|
|
||||||
lcother = TAILQ_NEXT(lc, entry);
|
|
||||||
else
|
|
||||||
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
|
||||||
if (lcparent->type == LAYOUT_LEFTRIGHT)
|
|
||||||
layout_resize_adjust(lcother, lcparent->type, lc->sx + 1);
|
|
||||||
else
|
|
||||||
layout_resize_adjust(lcother, lcparent->type, lc->sy + 1);
|
|
||||||
|
|
||||||
/* Remove this from the parent's list. */
|
|
||||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
|
||||||
layout_free_cell(lc);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the parent now has one cell, remove the parent from the tree and
|
|
||||||
* replace it by that cell.
|
|
||||||
*/
|
|
||||||
lc = TAILQ_FIRST(&lcparent->cells);
|
|
||||||
if (TAILQ_NEXT(lc, entry) == NULL) {
|
|
||||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
|
||||||
|
|
||||||
lc->parent = lcparent->parent;
|
|
||||||
if (lc->parent == NULL) {
|
|
||||||
lc->xoff = 0; lc->yoff = 0;
|
|
||||||
*lcroot = lc;
|
|
||||||
} else
|
|
||||||
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
|
|
||||||
|
|
||||||
layout_free_cell(lcparent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
layout_init(struct window *w)
|
layout_init(struct window *w)
|
||||||
{
|
{
|
||||||
@@ -668,16 +597,59 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size)
|
|||||||
return (lcnew);
|
return (lcnew);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy the cell associated with a pane. */
|
/* Destroy the layout associated with a pane and redistribute the space. */
|
||||||
void
|
void
|
||||||
layout_close_pane(struct window_pane *wp)
|
layout_close_pane(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
/* Remove the cell. */
|
struct layout_cell *lc, *lcother, *lcparent;
|
||||||
layout_destroy_cell(wp->layout_cell, &wp->window->layout_root);
|
|
||||||
|
lc = wp->layout_cell;
|
||||||
|
lcparent = lc->parent;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no parent, this is the last pane so window close is imminent and
|
||||||
|
* there is no need to resize anything.
|
||||||
|
*/
|
||||||
|
if (lcparent == NULL) {
|
||||||
|
layout_free_cell(lc);
|
||||||
|
wp->window->layout_root = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge the space into the previous or next cell. */
|
||||||
|
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||||
|
lcother = TAILQ_NEXT(lc, entry);
|
||||||
|
else
|
||||||
|
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||||
|
if (lcparent->type == LAYOUT_LEFTRIGHT)
|
||||||
|
layout_resize_adjust(lcother, lcparent->type, lc->sx + 1);
|
||||||
|
else
|
||||||
|
layout_resize_adjust(lcother, lcparent->type, lc->sy + 1);
|
||||||
|
|
||||||
|
/* Remove this from the parent's list. */
|
||||||
|
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||||
|
layout_free_cell(lc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the parent now has one cell, remove the parent from the tree and
|
||||||
|
* replace it by that cell.
|
||||||
|
*/
|
||||||
|
lc = TAILQ_FIRST(&lcparent->cells);
|
||||||
|
if (TAILQ_NEXT(lc, entry) == NULL) {
|
||||||
|
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||||
|
|
||||||
|
lc->parent = lcparent->parent;
|
||||||
|
if (lc->parent == NULL) {
|
||||||
|
lc->xoff = 0; lc->yoff = 0;
|
||||||
|
wp->window->layout_root = lc;
|
||||||
|
} else
|
||||||
|
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
|
||||||
|
|
||||||
|
layout_free_cell(lcparent);
|
||||||
|
}
|
||||||
|
|
||||||
/* Fix pane offsets and sizes. */
|
/* Fix pane offsets and sizes. */
|
||||||
if (wp->window->layout_root != NULL) {
|
layout_fix_offsets(wp->window->layout_root);
|
||||||
layout_fix_offsets(wp->window->layout_root);
|
layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
|
||||||
layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
mode-key.c
15
mode-key.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: mode-key.c,v 1.46 2010-03-16 17:30:58 micahcowan Exp $ */
|
/* $Id: mode-key.c,v 1.45 2010-03-08 15:02:07 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -88,10 +88,6 @@ struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
|
|||||||
{ MODEKEYCOPY_GOTOLINE, "goto-line" },
|
{ MODEKEYCOPY_GOTOLINE, "goto-line" },
|
||||||
{ MODEKEYCOPY_HISTORYBOTTOM, "history-bottom" },
|
{ MODEKEYCOPY_HISTORYBOTTOM, "history-bottom" },
|
||||||
{ MODEKEYCOPY_HISTORYTOP, "history-top" },
|
{ MODEKEYCOPY_HISTORYTOP, "history-top" },
|
||||||
{ MODEKEYCOPY_JUMP, "jump-forward" },
|
|
||||||
{ MODEKEYCOPY_JUMPAGAIN, "jump-again" },
|
|
||||||
{ MODEKEYCOPY_JUMPREVERSE, "jump-reverse" },
|
|
||||||
{ MODEKEYCOPY_JUMPBACK, "jump-backward" },
|
|
||||||
{ MODEKEYCOPY_LEFT, "cursor-left" },
|
{ MODEKEYCOPY_LEFT, "cursor-left" },
|
||||||
{ MODEKEYCOPY_RECTANGLETOGGLE, "rectangle-toggle" },
|
{ MODEKEYCOPY_RECTANGLETOGGLE, "rectangle-toggle" },
|
||||||
{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
|
{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
|
||||||
@@ -181,8 +177,6 @@ struct mode_key_tree mode_key_tree_vi_choice;
|
|||||||
const struct mode_key_entry mode_key_vi_copy[] = {
|
const struct mode_key_entry mode_key_vi_copy[] = {
|
||||||
{ ' ', 0, MODEKEYCOPY_STARTSELECTION },
|
{ ' ', 0, MODEKEYCOPY_STARTSELECTION },
|
||||||
{ '$', 0, MODEKEYCOPY_ENDOFLINE },
|
{ '$', 0, MODEKEYCOPY_ENDOFLINE },
|
||||||
{ ',', 0, MODEKEYCOPY_JUMPREVERSE },
|
|
||||||
{ ';', 0, MODEKEYCOPY_JUMPAGAIN },
|
|
||||||
{ '/', 0, MODEKEYCOPY_SEARCHDOWN },
|
{ '/', 0, MODEKEYCOPY_SEARCHDOWN },
|
||||||
{ '0', 0, MODEKEYCOPY_STARTOFLINE },
|
{ '0', 0, MODEKEYCOPY_STARTOFLINE },
|
||||||
{ '1', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
{ '1', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||||
@@ -198,7 +192,6 @@ const struct mode_key_entry mode_key_vi_copy[] = {
|
|||||||
{ '?', 0, MODEKEYCOPY_SEARCHUP },
|
{ '?', 0, MODEKEYCOPY_SEARCHUP },
|
||||||
{ 'B', 0, MODEKEYCOPY_PREVIOUSSPACE },
|
{ 'B', 0, MODEKEYCOPY_PREVIOUSSPACE },
|
||||||
{ 'E', 0, MODEKEYCOPY_NEXTSPACEEND },
|
{ 'E', 0, MODEKEYCOPY_NEXTSPACEEND },
|
||||||
{ 'F', 0, MODEKEYCOPY_JUMPBACK },
|
|
||||||
{ 'G', 0, MODEKEYCOPY_HISTORYBOTTOM },
|
{ 'G', 0, MODEKEYCOPY_HISTORYBOTTOM },
|
||||||
{ 'H', 0, MODEKEYCOPY_TOPLINE },
|
{ 'H', 0, MODEKEYCOPY_TOPLINE },
|
||||||
{ 'J', 0, MODEKEYCOPY_SCROLLDOWN },
|
{ 'J', 0, MODEKEYCOPY_SCROLLDOWN },
|
||||||
@@ -220,7 +213,6 @@ const struct mode_key_entry mode_key_vi_copy[] = {
|
|||||||
{ '^', 0, MODEKEYCOPY_BACKTOINDENTATION },
|
{ '^', 0, MODEKEYCOPY_BACKTOINDENTATION },
|
||||||
{ 'b', 0, MODEKEYCOPY_PREVIOUSWORD },
|
{ 'b', 0, MODEKEYCOPY_PREVIOUSWORD },
|
||||||
{ 'e', 0, MODEKEYCOPY_NEXTWORDEND },
|
{ 'e', 0, MODEKEYCOPY_NEXTWORDEND },
|
||||||
{ 'f', 0, MODEKEYCOPY_JUMP },
|
|
||||||
{ 'g', 0, MODEKEYCOPY_HISTORYTOP },
|
{ 'g', 0, MODEKEYCOPY_HISTORYTOP },
|
||||||
{ 'h', 0, MODEKEYCOPY_LEFT },
|
{ 'h', 0, MODEKEYCOPY_LEFT },
|
||||||
{ 'j', 0, MODEKEYCOPY_DOWN },
|
{ 'j', 0, MODEKEYCOPY_DOWN },
|
||||||
@@ -298,8 +290,6 @@ struct mode_key_tree mode_key_tree_emacs_choice;
|
|||||||
/* emacs copy mode keys. */
|
/* emacs copy mode keys. */
|
||||||
const struct mode_key_entry mode_key_emacs_copy[] = {
|
const struct mode_key_entry mode_key_emacs_copy[] = {
|
||||||
{ ' ', 0, MODEKEYCOPY_NEXTPAGE },
|
{ ' ', 0, MODEKEYCOPY_NEXTPAGE },
|
||||||
{ ',', 0, MODEKEYCOPY_JUMPREVERSE },
|
|
||||||
{ ';', 0, MODEKEYCOPY_JUMPAGAIN },
|
|
||||||
{ '1' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
{ '1' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||||
{ '2' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
{ '2' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||||
{ '3' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
{ '3' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||||
@@ -311,8 +301,6 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
|
|||||||
{ '9' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
{ '9' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||||
{ '<' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYTOP },
|
{ '<' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYTOP },
|
||||||
{ '>' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYBOTTOM },
|
{ '>' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYBOTTOM },
|
||||||
{ 'F', 0, MODEKEYCOPY_JUMPBACK },
|
|
||||||
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
|
|
||||||
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCOPY_TOPLINE },
|
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCOPY_TOPLINE },
|
||||||
{ 'R', 0, MODEKEYCOPY_RECTANGLETOGGLE },
|
{ 'R', 0, MODEKEYCOPY_RECTANGLETOGGLE },
|
||||||
{ '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION },
|
{ '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION },
|
||||||
@@ -331,7 +319,6 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
|
|||||||
{ '\033' /* Escape */, 0, MODEKEYCOPY_CANCEL },
|
{ '\033' /* Escape */, 0, MODEKEYCOPY_CANCEL },
|
||||||
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
|
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
|
||||||
{ 'b' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSWORD },
|
{ 'b' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSWORD },
|
||||||
{ 'f', 0, MODEKEYCOPY_JUMP },
|
|
||||||
{ 'f' | KEYC_ESCAPE, 0, MODEKEYCOPY_NEXTWORDEND },
|
{ 'f' | KEYC_ESCAPE, 0, MODEKEYCOPY_NEXTWORDEND },
|
||||||
{ 'g', 0, MODEKEYCOPY_GOTOLINE },
|
{ 'g', 0, MODEKEYCOPY_GOTOLINE },
|
||||||
{ 'm' | KEYC_ESCAPE, 0, MODEKEYCOPY_BACKTOINDENTATION },
|
{ 'm' | KEYC_ESCAPE, 0, MODEKEYCOPY_BACKTOINDENTATION },
|
||||||
|
|||||||
26
paste.c
26
paste.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: paste.c,v 1.15 2010-06-22 23:36:54 tcunha Exp $ */
|
/* $Id: paste.c,v 1.13 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -156,27 +156,3 @@ paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size)
|
|||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert a buffer into a visible string. */
|
|
||||||
char *
|
|
||||||
paste_print(struct paste_buffer *pb, size_t width)
|
|
||||||
{
|
|
||||||
char *buf;
|
|
||||||
size_t len, used;
|
|
||||||
|
|
||||||
if (width < 3)
|
|
||||||
width = 3;
|
|
||||||
buf = xmalloc(width * 4 + 1);
|
|
||||||
|
|
||||||
len = pb->size;
|
|
||||||
if (len > width)
|
|
||||||
len = width;
|
|
||||||
|
|
||||||
used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
|
|
||||||
if (pb->size > width || used > width) {
|
|
||||||
buf[width - 3] = '\0';
|
|
||||||
strlcat(buf, "...", width);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (buf);
|
|
||||||
}
|
|
||||||
|
|||||||
20
resize.c
20
resize.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: resize.c,v 1.27 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: resize.c,v 1.24 2009-09-25 17:47:42 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -52,7 +52,11 @@ recalculate_sizes(void)
|
|||||||
u_int i, j, ssx, ssy, has, limit;
|
u_int i, j, ssx, ssy, has, limit;
|
||||||
int flag;
|
int flag;
|
||||||
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
|
if (s == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
ssx = ssy = UINT_MAX;
|
ssx = ssy = UINT_MAX;
|
||||||
for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
|
for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
|
||||||
c = ARRAY_ITEM(&clients, j);
|
c = ARRAY_ITEM(&clients, j);
|
||||||
@@ -94,13 +98,14 @@ recalculate_sizes(void)
|
|||||||
flag = options_get_number(&w->options, "aggressive-resize");
|
flag = options_get_number(&w->options, "aggressive-resize");
|
||||||
|
|
||||||
ssx = ssy = UINT_MAX;
|
ssx = ssy = UINT_MAX;
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (j = 0; j < ARRAY_LENGTH(&sessions); j++) {
|
||||||
if (s->flags & SESSION_UNATTACHED)
|
s = ARRAY_ITEM(&sessions, j);
|
||||||
|
if (s == NULL || s->flags & SESSION_UNATTACHED)
|
||||||
continue;
|
continue;
|
||||||
if (flag)
|
if (flag)
|
||||||
has = s->curw->window == w;
|
has = s->curw->window == w;
|
||||||
else
|
else
|
||||||
has = session_has(s, w) != NULL;
|
has = session_has(s, w);
|
||||||
if (has) {
|
if (has) {
|
||||||
if (s->sx < ssx)
|
if (s->sx < ssx)
|
||||||
ssx = s->sx;
|
ssx = s->sx;
|
||||||
@@ -108,8 +113,11 @@ recalculate_sizes(void)
|
|||||||
ssy = s->sy;
|
ssy = s->sy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ssx == UINT_MAX || ssy == UINT_MAX)
|
if (ssx == UINT_MAX || ssy == UINT_MAX) {
|
||||||
|
w->flags |= WINDOW_HIDDEN;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
w->flags &= ~WINDOW_HIDDEN;
|
||||||
|
|
||||||
limit = options_get_number(&w->options, "force-width");
|
limit = options_get_number(&w->options, "force-width");
|
||||||
if (limit != 0 && ssx > limit)
|
if (limit != 0 && ssx > limit)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: screen-redraw.c,v 1.53 2010-09-18 15:43:53 tcunha Exp $ */
|
/* $Id: screen-redraw.c,v 1.52 2010-02-05 01:31:06 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -41,8 +41,6 @@ void screen_redraw_draw_number(struct client *, struct window_pane *);
|
|||||||
#define CELL_JOIN 11
|
#define CELL_JOIN 11
|
||||||
#define CELL_OUTSIDE 12
|
#define CELL_OUTSIDE 12
|
||||||
|
|
||||||
#define CELL_BORDERS " xqlkmjwvtun~"
|
|
||||||
|
|
||||||
/* Check if cell is on the border of a particular pane. */
|
/* Check if cell is on the border of a particular pane. */
|
||||||
int
|
int
|
||||||
screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py)
|
screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py)
|
||||||
@@ -175,6 +173,8 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
|||||||
struct grid_cell active_gc, other_gc;
|
struct grid_cell active_gc, other_gc;
|
||||||
u_int i, j, type;
|
u_int i, j, type;
|
||||||
int status, fg, bg;
|
int status, fg, bg;
|
||||||
|
const u_char *base, *ptr;
|
||||||
|
u_char ch, border[20];
|
||||||
|
|
||||||
/* Get status line, er, status. */
|
/* Get status line, er, status. */
|
||||||
if (c->message_string != NULL || c->prompt_string != NULL)
|
if (c->message_string != NULL || c->prompt_string != NULL)
|
||||||
@@ -193,7 +193,6 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
|||||||
memcpy(&other_gc, &grid_default_cell, sizeof other_gc);
|
memcpy(&other_gc, &grid_default_cell, sizeof other_gc);
|
||||||
memcpy(&active_gc, &grid_default_cell, sizeof active_gc);
|
memcpy(&active_gc, &grid_default_cell, sizeof active_gc);
|
||||||
active_gc.data = other_gc.data = 'x'; /* not space */
|
active_gc.data = other_gc.data = 'x'; /* not space */
|
||||||
active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET;
|
|
||||||
fg = options_get_number(&c->session->options, "pane-border-fg");
|
fg = options_get_number(&c->session->options, "pane-border-fg");
|
||||||
colour_set_fg(&other_gc, fg);
|
colour_set_fg(&other_gc, fg);
|
||||||
bg = options_get_number(&c->session->options, "pane-border-bg");
|
bg = options_get_number(&c->session->options, "pane-border-bg");
|
||||||
@@ -204,6 +203,16 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
|||||||
colour_set_bg(&active_gc, bg);
|
colour_set_bg(&active_gc, bg);
|
||||||
|
|
||||||
/* Draw background and borders. */
|
/* Draw background and borders. */
|
||||||
|
strlcpy(border, " |-....--||+.", sizeof border);
|
||||||
|
if (tty_term_has(tty->term, TTYC_ACSC)) {
|
||||||
|
base = " xqlkmjwvtun~";
|
||||||
|
for (ptr = base; *ptr != '\0'; ptr++) {
|
||||||
|
if ((ch = tty_get_acs(tty, *ptr)) != '\0')
|
||||||
|
border[ptr - base] = ch;
|
||||||
|
}
|
||||||
|
other_gc.attr |= GRID_ATTR_CHARSET;
|
||||||
|
active_gc.attr |= GRID_ATTR_CHARSET;
|
||||||
|
}
|
||||||
for (j = 0; j < tty->sy - status; j++) {
|
for (j = 0; j < tty->sy - status; j++) {
|
||||||
if (status_only && j != tty->sy - 1)
|
if (status_only && j != tty->sy - 1)
|
||||||
continue;
|
continue;
|
||||||
@@ -216,7 +225,7 @@ screen_redraw_screen(struct client *c, int status_only, int borders_only)
|
|||||||
else
|
else
|
||||||
tty_attributes(tty, &other_gc);
|
tty_attributes(tty, &other_gc);
|
||||||
tty_cursor(tty, i, j);
|
tty_cursor(tty, i, j);
|
||||||
tty_putc(tty, CELL_BORDERS[type]);
|
tty_putc(tty, border[type]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: screen-write.c,v 1.90 2010-06-16 18:09:23 micahcowan Exp $ */
|
/* $Id: screen-write.c,v 1.88 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
void screen_write_initctx(struct screen_write_ctx *, struct tty_ctx *, int);
|
void screen_write_initctx(struct screen_write_ctx *, struct tty_ctx *, int);
|
||||||
void screen_write_overwrite(struct screen_write_ctx *, u_int);
|
void screen_write_overwrite(struct screen_write_ctx *);
|
||||||
int screen_write_combine(
|
int screen_write_combine(
|
||||||
struct screen_write_ctx *, const struct utf8_data *);
|
struct screen_write_ctx *, const struct utf8_data *);
|
||||||
|
|
||||||
@@ -1009,18 +1009,17 @@ screen_write_cell(struct screen_write_ctx *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check this will fit on the current line and wrap if not. */
|
/* Check this will fit on the current line and wrap if not. */
|
||||||
if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) {
|
if (s->cx > screen_size_x(s) - width) {
|
||||||
screen_write_linefeed(ctx, 1);
|
screen_write_linefeed(ctx, 1);
|
||||||
s->cx = 0; /* carriage return */
|
s->cx = 0; /* carriage return */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity checks. */
|
/* Sanity checks. */
|
||||||
if (((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - 1)
|
if (s->cx > screen_size_x(s) - 1 || s->cy > screen_size_y(s) - 1)
|
||||||
|| s->cy > screen_size_y(s) - 1)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Handle overwriting of UTF-8 characters. */
|
/* Handle overwriting of UTF-8 characters. */
|
||||||
screen_write_overwrite(ctx, width);
|
screen_write_overwrite(ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the new character is UTF-8 wide, fill in padding cells. Have
|
* If the new character is UTF-8 wide, fill in padding cells. Have
|
||||||
@@ -1123,11 +1122,12 @@ screen_write_combine(
|
|||||||
* by the same character.
|
* by the same character.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
|
screen_write_overwrite(struct screen_write_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct grid *gd = s->grid;
|
struct grid *gd = s->grid;
|
||||||
const struct grid_cell *gc;
|
const struct grid_cell *gc;
|
||||||
|
const struct grid_utf8 *gu;
|
||||||
u_int xx;
|
u_int xx;
|
||||||
|
|
||||||
gc = grid_view_peek_cell(gd, s->cx, s->cy);
|
gc = grid_view_peek_cell(gd, s->cx, s->cy);
|
||||||
@@ -1147,17 +1147,30 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
|
|||||||
|
|
||||||
/* Overwrite the character at the start of this padding. */
|
/* Overwrite the character at the start of this padding. */
|
||||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/* Overwrite following padding cells. */
|
||||||
* Overwrite any padding cells that belong to a UTF-8 character
|
xx = s->cx;
|
||||||
* we'll be overwriting with the current character.
|
while (++xx < screen_size_x(s)) {
|
||||||
*/
|
gc = grid_view_peek_cell(gd, xx, s->cy);
|
||||||
xx = s->cx + width - 1;
|
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||||
while (++xx < screen_size_x(s)) {
|
break;
|
||||||
gc = grid_view_peek_cell(gd, xx, s->cy);
|
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
}
|
||||||
break;
|
} else if (gc->flags & GRID_FLAG_UTF8) {
|
||||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
gu = grid_view_peek_utf8(gd, s->cx, s->cy);
|
||||||
|
if (gu->width > 1) {
|
||||||
|
/*
|
||||||
|
* An UTF-8 wide cell; overwrite following padding
|
||||||
|
* cells only.
|
||||||
|
*/
|
||||||
|
xx = s->cx;
|
||||||
|
while (++xx < screen_size_x(s)) {
|
||||||
|
gc = grid_view_peek_cell(gd, xx, s->cy);
|
||||||
|
if (!(gc->flags & GRID_FLAG_PADDING))
|
||||||
|
break;
|
||||||
|
grid_view_set_cell(
|
||||||
|
gd, xx, s->cy, &grid_default_cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
screen.c
17
screen.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: screen.c,v 1.103 2010-12-11 17:57:28 nicm Exp $ */
|
/* $Id: screen.c,v 1.99 2010-02-08 18:13:17 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -18,10 +18,8 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@@ -32,14 +30,9 @@ void screen_resize_y(struct screen *, u_int);
|
|||||||
void
|
void
|
||||||
screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
|
screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
|
||||||
{
|
{
|
||||||
char hn[MAXHOSTNAMELEN];
|
|
||||||
|
|
||||||
s->grid = grid_create(sx, sy, hlimit);
|
s->grid = grid_create(sx, sy, hlimit);
|
||||||
|
|
||||||
if (gethostname(hn, MAXHOSTNAMELEN) == 0)
|
s->title = xstrdup("");
|
||||||
s->title = xstrdup(hn);
|
|
||||||
else
|
|
||||||
s->title = xstrdup("");
|
|
||||||
|
|
||||||
s->tabs = NULL;
|
s->tabs = NULL;
|
||||||
|
|
||||||
@@ -56,7 +49,7 @@ screen_reinit(struct screen *s)
|
|||||||
s->rupper = 0;
|
s->rupper = 0;
|
||||||
s->rlower = screen_size_y(s) - 1;
|
s->rlower = screen_size_y(s) - 1;
|
||||||
|
|
||||||
s->mode = MODE_CURSOR | MODE_WRAP;
|
s->mode = MODE_CURSOR;
|
||||||
|
|
||||||
screen_reset_tabs(s);
|
screen_reset_tabs(s);
|
||||||
|
|
||||||
@@ -287,7 +280,7 @@ screen_check_selection(struct screen *s, u_int px, u_int py)
|
|||||||
*/
|
*/
|
||||||
if (sel->ex < sel->sx) {
|
if (sel->ex < sel->sx) {
|
||||||
/* Cursor (ex) is on the left. */
|
/* Cursor (ex) is on the left. */
|
||||||
if (px < sel->ex)
|
if (px <= sel->ex)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (px > sel->sx)
|
if (px > sel->sx)
|
||||||
@@ -297,7 +290,7 @@ screen_check_selection(struct screen *s, u_int px, u_int py)
|
|||||||
if (px < sel->sx)
|
if (px < sel->sx)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (px > sel->ex)
|
if (px >= sel->ex)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
245
server-client.c
245
server-client.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: server-client.c,v 1.48 2010-12-22 15:31:00 tcunha Exp $ */
|
/* $Id: server-client.c,v 1.31 2010-02-08 18:27:34 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -28,14 +28,9 @@
|
|||||||
|
|
||||||
void server_client_handle_key(int, struct mouse_event *, void *);
|
void server_client_handle_key(int, struct mouse_event *, void *);
|
||||||
void server_client_repeat_timer(int, short, void *);
|
void server_client_repeat_timer(int, short, void *);
|
||||||
void server_client_check_exit(struct client *);
|
|
||||||
void server_client_check_backoff(struct client *);
|
|
||||||
void server_client_check_redraw(struct client *);
|
void server_client_check_redraw(struct client *);
|
||||||
void server_client_set_title(struct client *);
|
void server_client_set_title(struct client *);
|
||||||
void server_client_reset_state(struct client *);
|
void server_client_reset_state(struct client *);
|
||||||
void server_client_in_callback(struct bufferevent *, short, void *);
|
|
||||||
void server_client_out_callback(struct bufferevent *, short, void *);
|
|
||||||
void server_client_err_callback(struct bufferevent *, short, void *);
|
|
||||||
|
|
||||||
int server_client_msg_dispatch(struct client *);
|
int server_client_msg_dispatch(struct client *);
|
||||||
void server_client_msg_command(struct client *, struct msg_command_data *);
|
void server_client_msg_command(struct client *, struct msg_command_data *);
|
||||||
@@ -59,6 +54,8 @@ server_client_create(int fd)
|
|||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
fatal("fcntl failed");
|
||||||
|
|
||||||
c = xcalloc(1, sizeof *c);
|
c = xcalloc(1, sizeof *c);
|
||||||
c->references = 0;
|
c->references = 0;
|
||||||
@@ -69,15 +66,12 @@ server_client_create(int fd)
|
|||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday failed");
|
||||||
memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time);
|
memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time);
|
||||||
|
|
||||||
c->stdin_event = NULL;
|
ARRAY_INIT(&c->prompt_hdata);
|
||||||
c->stdout_event = NULL;
|
|
||||||
c->stderr_event = NULL;
|
|
||||||
|
|
||||||
c->tty.fd = -1;
|
c->tty.fd = -1;
|
||||||
c->title = NULL;
|
c->title = NULL;
|
||||||
|
|
||||||
c->session = NULL;
|
c->session = NULL;
|
||||||
c->last_session = NULL;
|
|
||||||
c->tty.sx = 80;
|
c->tty.sx = 80;
|
||||||
c->tty.sy = 24;
|
c->tty.sy = 24;
|
||||||
|
|
||||||
@@ -123,19 +117,6 @@ server_client_lost(struct client *c)
|
|||||||
if (c->flags & CLIENT_TERMINAL)
|
if (c->flags & CLIENT_TERMINAL)
|
||||||
tty_free(&c->tty);
|
tty_free(&c->tty);
|
||||||
|
|
||||||
if (c->stdin_fd != -1)
|
|
||||||
close(c->stdin_fd);
|
|
||||||
if (c->stdin_event != NULL)
|
|
||||||
bufferevent_free(c->stdin_event);
|
|
||||||
if (c->stdout_fd != -1)
|
|
||||||
close(c->stdout_fd);
|
|
||||||
if (c->stdout_event != NULL)
|
|
||||||
bufferevent_free(c->stdout_event);
|
|
||||||
if (c->stderr_fd != -1)
|
|
||||||
close(c->stderr_fd);
|
|
||||||
if (c->stderr_event != NULL)
|
|
||||||
bufferevent_free(c->stderr_event);
|
|
||||||
|
|
||||||
screen_free(&c->status);
|
screen_free(&c->status);
|
||||||
job_tree_free(&c->status_jobs);
|
job_tree_free(&c->status_jobs);
|
||||||
|
|
||||||
@@ -159,6 +140,9 @@ server_client_lost(struct client *c)
|
|||||||
xfree(c->prompt_string);
|
xfree(c->prompt_string);
|
||||||
if (c->prompt_buffer != NULL)
|
if (c->prompt_buffer != NULL)
|
||||||
xfree(c->prompt_buffer);
|
xfree(c->prompt_buffer);
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(&c->prompt_hdata); i++)
|
||||||
|
xfree(ARRAY_ITEM(&c->prompt_hdata, i));
|
||||||
|
ARRAY_FREE(&c->prompt_hdata);
|
||||||
|
|
||||||
if (c->cwd != NULL)
|
if (c->cwd != NULL)
|
||||||
xfree(c->cwd);
|
xfree(c->cwd);
|
||||||
@@ -178,7 +162,6 @@ server_client_lost(struct client *c)
|
|||||||
c->flags |= CLIENT_DEAD;
|
c->flags |= CLIENT_DEAD;
|
||||||
|
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
server_check_unattached();
|
|
||||||
server_update_socket();
|
server_update_socket();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +299,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
|
|||||||
server_redraw_window_borders(w);
|
server_redraw_window_borders(w);
|
||||||
wp = w->active;
|
wp = w->active;
|
||||||
}
|
}
|
||||||
window_pane_mouse(wp, c->session, mouse);
|
window_pane_mouse(wp, c, mouse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +321,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
|
|||||||
/* Try as a non-prefix key binding. */
|
/* Try as a non-prefix key binding. */
|
||||||
if ((bd = key_bindings_lookup(key)) == NULL) {
|
if ((bd = key_bindings_lookup(key)) == NULL) {
|
||||||
if (!(c->flags & CLIENT_READONLY))
|
if (!(c->flags & CLIENT_READONLY))
|
||||||
window_pane_key(wp, c->session, key);
|
window_pane_key(wp, c, key);
|
||||||
} else
|
} else
|
||||||
key_bindings_dispatch(bd, c);
|
key_bindings_dispatch(bd, c);
|
||||||
}
|
}
|
||||||
@@ -354,7 +337,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
|
|||||||
if (isprefix)
|
if (isprefix)
|
||||||
c->flags |= CLIENT_PREFIX;
|
c->flags |= CLIENT_PREFIX;
|
||||||
else if (!(c->flags & CLIENT_READONLY))
|
else if (!(c->flags & CLIENT_READONLY))
|
||||||
window_pane_key(wp, c->session, key);
|
window_pane_key(wp, c, key);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -365,7 +348,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data)
|
|||||||
if (isprefix)
|
if (isprefix)
|
||||||
c->flags |= CLIENT_PREFIX;
|
c->flags |= CLIENT_PREFIX;
|
||||||
else if (!(c->flags & CLIENT_READONLY))
|
else if (!(c->flags & CLIENT_READONLY))
|
||||||
window_pane_key(wp, c->session, key);
|
window_pane_key(wp, c, key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,14 +378,11 @@ server_client_loop(void)
|
|||||||
|
|
||||||
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)
|
if (c == NULL || c->session == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
server_client_check_exit(c);
|
server_client_check_redraw(c);
|
||||||
if (c->session != NULL) {
|
server_client_reset_state(c);
|
||||||
server_client_check_redraw(c);
|
|
||||||
server_client_reset_state(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -465,72 +445,6 @@ server_client_repeat_timer(unused int fd, unused short events, void *data)
|
|||||||
c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT);
|
c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if client should be exited. */
|
|
||||||
void
|
|
||||||
server_client_check_exit(struct client *c)
|
|
||||||
{
|
|
||||||
struct msg_exit_data exitdata;
|
|
||||||
|
|
||||||
if (!(c->flags & CLIENT_EXIT))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (c->stdout_fd != -1 && c->stdout_event != NULL &&
|
|
||||||
EVBUFFER_LENGTH(c->stdout_event->output) != 0)
|
|
||||||
return;
|
|
||||||
if (c->stderr_fd != -1 && c->stderr_event != NULL &&
|
|
||||||
EVBUFFER_LENGTH(c->stderr_event->output) != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
exitdata.retcode = c->retcode;
|
|
||||||
server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata);
|
|
||||||
|
|
||||||
c->flags &= ~CLIENT_EXIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the client should backoff. During backoff, data from external
|
|
||||||
* programs is not written to the terminal. When the existing data drains, the
|
|
||||||
* client is redrawn.
|
|
||||||
*
|
|
||||||
* There are two backoff phases - both the tty and client have backoff flags -
|
|
||||||
* the first to allow existing data to drain and the latter to ensure backoff
|
|
||||||
* is disabled until the redraw has finished and prevent the redraw triggering
|
|
||||||
* another backoff.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
server_client_check_backoff(struct client *c)
|
|
||||||
{
|
|
||||||
struct tty *tty = &c->tty;
|
|
||||||
size_t used;
|
|
||||||
|
|
||||||
used = EVBUFFER_LENGTH(tty->event->output);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If in the second backoff phase (redrawing), don't check backoff
|
|
||||||
* until the redraw has completed (or enough of it to drop below the
|
|
||||||
* backoff threshold).
|
|
||||||
*/
|
|
||||||
if (c->flags & CLIENT_BACKOFF) {
|
|
||||||
if (used > BACKOFF_THRESHOLD)
|
|
||||||
return;
|
|
||||||
c->flags &= ~CLIENT_BACKOFF;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Once drained, allow data through again and schedule redraw. */
|
|
||||||
if (tty->flags & TTY_BACKOFF) {
|
|
||||||
if (used != 0)
|
|
||||||
return;
|
|
||||||
tty->flags &= ~TTY_BACKOFF;
|
|
||||||
c->flags |= (CLIENT_BACKOFF|CLIENT_REDRAWWINDOW|CLIENT_STATUS);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If too much data, start backoff. */
|
|
||||||
if (used > BACKOFF_THRESHOLD)
|
|
||||||
tty->flags |= TTY_BACKOFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for client redraws. */
|
/* Check for client redraws. */
|
||||||
void
|
void
|
||||||
server_client_check_redraw(struct client *c)
|
server_client_check_redraw(struct client *c)
|
||||||
@@ -559,10 +473,6 @@ server_client_check_redraw(struct client *c)
|
|||||||
if (c->flags & CLIENT_REDRAW) {
|
if (c->flags & CLIENT_REDRAW) {
|
||||||
screen_redraw_screen(c, 0, 0);
|
screen_redraw_screen(c, 0, 0);
|
||||||
c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS);
|
c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS);
|
||||||
} else if (c->flags & CLIENT_REDRAWWINDOW) {
|
|
||||||
TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry)
|
|
||||||
screen_redraw_pane(c, wp);
|
|
||||||
c->flags &= ~CLIENT_REDRAWWINDOW;
|
|
||||||
} else {
|
} else {
|
||||||
TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
|
TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
|
||||||
if (wp->flags & PANE_REDRAW)
|
if (wp->flags & PANE_REDRAW)
|
||||||
@@ -601,52 +511,6 @@ server_client_set_title(struct client *c)
|
|||||||
xfree(title);
|
xfree(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Error callback for client stdin. Caller must increase reference count when
|
|
||||||
* enabling event!
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
server_client_in_callback(
|
|
||||||
unused struct bufferevent *bufev, unused short what, void *data)
|
|
||||||
{
|
|
||||||
struct client *c = data;
|
|
||||||
|
|
||||||
c->references--;
|
|
||||||
if (c->flags & CLIENT_DEAD)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bufferevent_disable(c->stdin_event, EV_READ|EV_WRITE);
|
|
||||||
close(c->stdin_fd);
|
|
||||||
c->stdin_fd = -1;
|
|
||||||
|
|
||||||
if (c->stdin_callback != NULL)
|
|
||||||
c->stdin_callback(c, c->stdin_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Error callback for client stdout. */
|
|
||||||
void
|
|
||||||
server_client_out_callback(
|
|
||||||
unused struct bufferevent *bufev, unused short what, unused void *data)
|
|
||||||
{
|
|
||||||
struct client *c = data;
|
|
||||||
|
|
||||||
bufferevent_disable(c->stdout_event, EV_READ|EV_WRITE);
|
|
||||||
close(c->stdout_fd);
|
|
||||||
c->stdout_fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Error callback for client stderr. */
|
|
||||||
void
|
|
||||||
server_client_err_callback(
|
|
||||||
unused struct bufferevent *bufev, unused short what, unused void *data)
|
|
||||||
{
|
|
||||||
struct client *c = data;
|
|
||||||
|
|
||||||
bufferevent_disable(c->stderr_event, EV_READ|EV_WRITE);
|
|
||||||
close(c->stderr_fd);
|
|
||||||
c->stderr_fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dispatch message from client. */
|
/* Dispatch message from client. */
|
||||||
int
|
int
|
||||||
server_client_msg_dispatch(struct client *c)
|
server_client_msg_dispatch(struct client *c)
|
||||||
@@ -656,7 +520,6 @@ server_client_msg_dispatch(struct client *c)
|
|||||||
struct msg_identify_data identifydata;
|
struct msg_identify_data identifydata;
|
||||||
struct msg_environ_data environdata;
|
struct msg_environ_data environdata;
|
||||||
ssize_t n, datalen;
|
ssize_t n, datalen;
|
||||||
int mode;
|
|
||||||
|
|
||||||
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0)
|
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -691,55 +554,15 @@ server_client_msg_dispatch(struct client *c)
|
|||||||
fatalx("MSG_IDENTIFY missing fd");
|
fatalx("MSG_IDENTIFY missing fd");
|
||||||
memcpy(&identifydata, imsg.data, sizeof identifydata);
|
memcpy(&identifydata, imsg.data, sizeof identifydata);
|
||||||
|
|
||||||
c->stdin_fd = imsg.fd;
|
|
||||||
c->stdin_event = bufferevent_new(c->stdin_fd,
|
|
||||||
NULL, NULL, server_client_in_callback, c);
|
|
||||||
if (c->stdin_event == NULL)
|
|
||||||
fatalx("failed to create stdin event");
|
|
||||||
|
|
||||||
if ((mode = fcntl(c->stdin_fd, F_GETFL)) != -1)
|
|
||||||
fcntl(c->stdin_fd, F_SETFL, mode|O_NONBLOCK);
|
|
||||||
|
|
||||||
server_client_msg_identify(c, &identifydata, imsg.fd);
|
server_client_msg_identify(c, &identifydata, imsg.fd);
|
||||||
break;
|
break;
|
||||||
case MSG_STDOUT:
|
|
||||||
if (datalen != 0)
|
|
||||||
fatalx("bad MSG_STDOUT size");
|
|
||||||
if (imsg.fd == -1)
|
|
||||||
fatalx("MSG_STDOUT missing fd");
|
|
||||||
|
|
||||||
c->stdout_fd = imsg.fd;
|
|
||||||
c->stdout_event = bufferevent_new(c->stdout_fd,
|
|
||||||
NULL, NULL, server_client_out_callback, c);
|
|
||||||
if (c->stdout_event == NULL)
|
|
||||||
fatalx("failed to create stdout event");
|
|
||||||
|
|
||||||
if ((mode = fcntl(c->stdout_fd, F_GETFL)) != -1)
|
|
||||||
fcntl(c->stdout_fd, F_SETFL, mode|O_NONBLOCK);
|
|
||||||
break;
|
|
||||||
case MSG_STDERR:
|
|
||||||
if (datalen != 0)
|
|
||||||
fatalx("bad MSG_STDERR size");
|
|
||||||
if (imsg.fd == -1)
|
|
||||||
fatalx("MSG_STDERR missing fd");
|
|
||||||
|
|
||||||
c->stderr_fd = imsg.fd;
|
|
||||||
c->stderr_event = bufferevent_new(c->stderr_fd,
|
|
||||||
NULL, NULL, server_client_err_callback, c);
|
|
||||||
if (c->stderr_event == NULL)
|
|
||||||
fatalx("failed to create stderr event");
|
|
||||||
|
|
||||||
if ((mode = fcntl(c->stderr_fd, F_GETFL)) != -1)
|
|
||||||
fcntl(c->stderr_fd, F_SETFL, mode|O_NONBLOCK);
|
|
||||||
break;
|
|
||||||
case MSG_RESIZE:
|
case MSG_RESIZE:
|
||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
fatalx("bad MSG_RESIZE size");
|
fatalx("bad MSG_RESIZE size");
|
||||||
|
|
||||||
if (tty_resize(&c->tty)) {
|
tty_resize(&c->tty);
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
server_redraw_client(c);
|
server_redraw_client(c);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MSG_EXITING:
|
case MSG_EXITING:
|
||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
@@ -797,43 +620,45 @@ server_client_msg_dispatch(struct client *c)
|
|||||||
void printflike2
|
void printflike2
|
||||||
server_client_msg_error(struct cmd_ctx *ctx, const char *fmt, ...)
|
server_client_msg_error(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
struct msg_print_data data;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
evbuffer_add_vprintf(ctx->cmdclient->stderr_event->output, fmt, ap);
|
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
bufferevent_write(ctx->cmdclient->stderr_event, "\n", 1);
|
server_write_client(ctx->cmdclient, MSG_ERROR, &data, sizeof data);
|
||||||
ctx->cmdclient->retcode = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback to send print message to client. */
|
/* Callback to send print message to client. */
|
||||||
void printflike2
|
void printflike2
|
||||||
server_client_msg_print(struct cmd_ctx *ctx, const char *fmt, ...)
|
server_client_msg_print(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
struct msg_print_data data;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
evbuffer_add_vprintf(ctx->cmdclient->stdout_event->output, fmt, ap);
|
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
bufferevent_write(ctx->cmdclient->stdout_event, "\n", 1);
|
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback to send print message to client, if not quiet. */
|
/* Callback to send print message to client, if not quiet. */
|
||||||
void printflike2
|
void printflike2
|
||||||
server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...)
|
server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
struct msg_print_data data;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
if (options_get_number(&global_options, "quiet"))
|
if (options_get_number(&global_options, "quiet"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
evbuffer_add_vprintf(ctx->cmdclient->stdout_event->output, fmt, ap);
|
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
bufferevent_write(ctx->cmdclient->stdout_event, "\n", 1);
|
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle command message. */
|
/* Handle command message. */
|
||||||
@@ -875,14 +700,14 @@ server_client_msg_command(struct client *c, struct msg_command_data *data)
|
|||||||
cmd_free_argv(argc, argv);
|
cmd_free_argv(argc, argv);
|
||||||
|
|
||||||
if (cmd_list_exec(cmdlist, &ctx) != 1)
|
if (cmd_list_exec(cmdlist, &ctx) != 1)
|
||||||
c->flags |= CLIENT_EXIT;
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (cmdlist != NULL)
|
if (cmdlist != NULL)
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
c->flags |= CLIENT_EXIT;
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle identify message. */
|
/* Handle identify message. */
|
||||||
@@ -890,19 +715,13 @@ void
|
|||||||
server_client_msg_identify(
|
server_client_msg_identify(
|
||||||
struct client *c, struct msg_identify_data *data, int fd)
|
struct client *c, struct msg_identify_data *data, int fd)
|
||||||
{
|
{
|
||||||
int tty_fd;
|
|
||||||
|
|
||||||
c->cwd = NULL;
|
c->cwd = NULL;
|
||||||
data->cwd[(sizeof data->cwd) - 1] = '\0';
|
data->cwd[(sizeof data->cwd) - 1] = '\0';
|
||||||
if (*data->cwd != '\0')
|
if (*data->cwd != '\0')
|
||||||
c->cwd = xstrdup(data->cwd);
|
c->cwd = xstrdup(data->cwd);
|
||||||
|
|
||||||
if (!isatty(fd))
|
|
||||||
return;
|
|
||||||
if ((tty_fd = dup(fd)) == -1)
|
|
||||||
fatal("dup failed");
|
|
||||||
data->term[(sizeof data->term) - 1] = '\0';
|
data->term[(sizeof data->term) - 1] = '\0';
|
||||||
tty_init(&c->tty, tty_fd, data->term);
|
tty_init(&c->tty, fd, data->term);
|
||||||
if (data->flags & IDENTIFY_UTF8)
|
if (data->flags & IDENTIFY_UTF8)
|
||||||
c->tty.flags |= TTY_UTF8;
|
c->tty.flags |= TTY_UTF8;
|
||||||
if (data->flags & IDENTIFY_256COLOURS)
|
if (data->flags & IDENTIFY_256COLOURS)
|
||||||
|
|||||||
105
server-fn.c
105
server-fn.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: server-fn.c,v 1.117 2010-12-25 23:44:37 tcunha Exp $ */
|
/* $Id: server-fn.c,v 1.102 2010-01-25 17:13:43 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -24,22 +24,33 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
struct session *server_next_session(struct session *);
|
void server_callback_identify(int, short, void *);
|
||||||
void server_callback_identify(int, short, void *);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
server_fill_environ(struct session *s, struct environ *env)
|
server_fill_environ(struct session *s, struct environ *env)
|
||||||
{
|
{
|
||||||
char tmuxvar[MAXPATHLEN], *term;
|
char tmuxvar[MAXPATHLEN], *term;
|
||||||
|
u_int idx;
|
||||||
|
|
||||||
|
if (session_index(s, &idx) != 0)
|
||||||
|
fatalx("session not found");
|
||||||
xsnprintf(tmuxvar, sizeof tmuxvar,
|
xsnprintf(tmuxvar, sizeof tmuxvar,
|
||||||
"%s,%ld,%u", socket_path, (long) getpid(), s->idx);
|
"%s,%ld,%u", socket_path, (long) getpid(), idx);
|
||||||
environ_set(env, "TMUX", tmuxvar);
|
environ_set(env, "TMUX", tmuxvar);
|
||||||
|
|
||||||
term = options_get_string(&s->options, "default-terminal");
|
term = options_get_string(&s->options, "default-terminal");
|
||||||
environ_set(env, "TERM", term);
|
environ_set(env, "TERM", term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
server_write_error(struct client *c, const char *msg)
|
||||||
|
{
|
||||||
|
struct msg_print_data printdata;
|
||||||
|
|
||||||
|
strlcpy(printdata.msg, msg, sizeof printdata.msg);
|
||||||
|
server_write_client(c, MSG_ERROR, &printdata, sizeof printdata);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
server_write_client(
|
server_write_client(
|
||||||
struct client *c, enum msgtype type, const void *buf, size_t len)
|
struct client *c, enum msgtype type, const void *buf, size_t len)
|
||||||
@@ -172,6 +183,7 @@ void
|
|||||||
server_status_window(struct window *w)
|
server_status_window(struct window *w)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is slightly different. We want to redraw the status line of any
|
* This is slightly different. We want to redraw the status line of any
|
||||||
@@ -179,8 +191,9 @@ server_status_window(struct window *w)
|
|||||||
* current window.
|
* current window.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
if (session_has(s, w) != NULL)
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
|
if (s != NULL && session_has(s, w))
|
||||||
server_status_session(s);
|
server_status_session(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,15 +252,13 @@ server_lock_client(struct client *c)
|
|||||||
void
|
void
|
||||||
server_kill_window(struct window *w)
|
server_kill_window(struct window *w)
|
||||||
{
|
{
|
||||||
struct session *s, *next_s;
|
struct session *s;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
next_s = RB_MIN(sessions, &sessions);
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
while (next_s != NULL) {
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
s = next_s;
|
if (s == NULL || !session_has(s, w))
|
||||||
next_s = RB_NEXT(sessions, &sessions, s);
|
|
||||||
|
|
||||||
if (session_has(s, w) == NULL)
|
|
||||||
continue;
|
continue;
|
||||||
while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) {
|
while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) {
|
||||||
if (session_detach(s, wl)) {
|
if (session_detach(s, wl)) {
|
||||||
@@ -277,16 +288,14 @@ server_link_window(struct session *src, struct winlink *srcwl,
|
|||||||
if (dstidx != -1)
|
if (dstidx != -1)
|
||||||
dstwl = winlink_find_by_index(&dst->windows, dstidx);
|
dstwl = winlink_find_by_index(&dst->windows, dstidx);
|
||||||
if (dstwl != NULL) {
|
if (dstwl != NULL) {
|
||||||
if (dstwl->window == srcwl->window) {
|
if (dstwl->window == srcwl->window)
|
||||||
xasprintf(cause, "same index: %d", dstidx);
|
return (0);
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
if (killflag) {
|
if (killflag) {
|
||||||
/*
|
/*
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
dstwl->flags &= ~WINLINK_ALERTFLAGS;
|
session_alert_cancel(dst, dstwl);
|
||||||
winlink_stack_remove(&dst->lastw, dstwl);
|
winlink_stack_remove(&dst->lastw, dstwl);
|
||||||
winlink_remove(&dst->windows, dstwl);
|
winlink_remove(&dst->windows, dstwl);
|
||||||
|
|
||||||
@@ -325,11 +334,9 @@ server_destroy_pane(struct window_pane *wp)
|
|||||||
{
|
{
|
||||||
struct window *w = wp->window;
|
struct window *w = wp->window;
|
||||||
|
|
||||||
if (wp->fd != -1) {
|
close(wp->fd);
|
||||||
close(wp->fd);
|
bufferevent_free(wp->event);
|
||||||
bufferevent_free(wp->event);
|
wp->fd = -1;
|
||||||
wp->fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options_get_number(&w->options, "remain-on-exit"))
|
if (options_get_number(&w->options, "remain-on-exit"))
|
||||||
return;
|
return;
|
||||||
@@ -358,64 +365,18 @@ server_destroy_session_group(struct session *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct session *
|
|
||||||
server_next_session(struct session *s)
|
|
||||||
{
|
|
||||||
struct session *s_loop, *s_out;
|
|
||||||
|
|
||||||
s_out = NULL;
|
|
||||||
RB_FOREACH(s_loop, sessions, &sessions) {
|
|
||||||
if (s_loop == s)
|
|
||||||
continue;
|
|
||||||
if (s_out == NULL ||
|
|
||||||
timercmp(&s_loop->activity_time, &s_out->activity_time, <))
|
|
||||||
s_out = s_loop;
|
|
||||||
}
|
|
||||||
return (s_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
server_destroy_session(struct session *s)
|
server_destroy_session(struct session *s)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct session *s_new;
|
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (!options_get_number(&s->options, "detach-on-destroy"))
|
|
||||||
s_new = server_next_session(s);
|
|
||||||
else
|
|
||||||
s_new = NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
c = ARRAY_ITEM(&clients, i);
|
c = ARRAY_ITEM(&clients, i);
|
||||||
if (c == NULL || c->session != s)
|
if (c == NULL || c->session != s)
|
||||||
continue;
|
continue;
|
||||||
if (s_new == NULL) {
|
c->session = NULL;
|
||||||
c->session = NULL;
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
c->flags |= CLIENT_EXIT;
|
|
||||||
} else {
|
|
||||||
c->last_session = NULL;
|
|
||||||
c->session = s_new;
|
|
||||||
server_redraw_client(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
recalculate_sizes();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
server_check_unattached (void)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If any sessions are no longer attached and have destroy-unattached
|
|
||||||
* set, collect them.
|
|
||||||
*/
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
|
||||||
if (!(s->flags & SESSION_UNATTACHED))
|
|
||||||
continue;
|
|
||||||
if (options_get_number (&s->options, "destroy-unattached"))
|
|
||||||
session_destroy(s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
153
server-window.c
153
server-window.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: server-window.c,v 1.19 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: server-window.c,v 1.14 2010-02-26 13:26:44 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -24,56 +24,90 @@
|
|||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
int server_window_backoff(struct window_pane *);
|
int server_window_backoff(struct window_pane *);
|
||||||
int server_window_check_bell(struct session *, struct winlink *);
|
int server_window_check_bell(struct session *, struct window *);
|
||||||
int server_window_check_activity(struct session *, struct winlink *);
|
int server_window_check_activity(struct session *, struct window *);
|
||||||
int server_window_check_silence(struct session *, struct winlink *);
|
|
||||||
int server_window_check_content(
|
int server_window_check_content(
|
||||||
struct session *, struct winlink *, struct window_pane *);
|
struct session *, struct window *, struct window_pane *);
|
||||||
|
|
||||||
|
/* Check if this window should suspend reading. */
|
||||||
|
int
|
||||||
|
server_window_backoff(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct client *c;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
if (!window_pane_visible(wp))
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
|
c = ARRAY_ITEM(&clients, i);
|
||||||
|
if (c == NULL || c->session == NULL)
|
||||||
|
continue;
|
||||||
|
if ((c->flags & (CLIENT_SUSPENDED|CLIENT_DEAD)) != 0)
|
||||||
|
continue;
|
||||||
|
if (c->session->curw->window != wp->window)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (EVBUFFER_LENGTH(c->tty.event->output) > BACKOFF_THRESHOLD)
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Window functions that need to happen every loop. */
|
/* Window functions that need to happen every loop. */
|
||||||
void
|
void
|
||||||
server_window_loop(void)
|
server_window_loop(void)
|
||||||
{
|
{
|
||||||
struct window *w;
|
struct window *w;
|
||||||
struct winlink *wl;
|
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
u_int i;
|
u_int i, j;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
||||||
w = ARRAY_ITEM(&windows, i);
|
w = ARRAY_ITEM(&windows, i);
|
||||||
if (w == NULL)
|
if (w == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
wl = session_has(s, w);
|
if (wp->fd == -1)
|
||||||
if (wl == NULL)
|
continue;
|
||||||
|
if (!(wp->flags & PANE_FREEZE)) {
|
||||||
|
if (server_window_backoff(wp))
|
||||||
|
bufferevent_disable(wp->event, EV_READ);
|
||||||
|
else
|
||||||
|
bufferevent_enable(wp->event, EV_READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < ARRAY_LENGTH(&sessions); j++) {
|
||||||
|
s = ARRAY_ITEM(&sessions, j);
|
||||||
|
if (s == NULL || !session_has(s, w))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (server_window_check_bell(s, wl) ||
|
if (server_window_check_bell(s, w) ||
|
||||||
server_window_check_activity(s, wl) ||
|
server_window_check_activity(s, w))
|
||||||
server_window_check_silence(s, wl))
|
|
||||||
server_status_session(s);
|
server_status_session(s);
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry)
|
TAILQ_FOREACH(wp, &w->panes, entry)
|
||||||
server_window_check_content(s, wl, wp);
|
server_window_check_content(s, w, wp);
|
||||||
}
|
}
|
||||||
w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY);
|
w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_CONTENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for bell in window. */
|
/* Check for bell in window. */
|
||||||
int
|
int
|
||||||
server_window_check_bell(struct session *s, struct winlink *wl)
|
server_window_check_bell(struct session *s, struct window *w)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct window *w = wl->window;
|
|
||||||
u_int i;
|
u_int i;
|
||||||
int action, visual;
|
int action, visual;
|
||||||
|
|
||||||
if (!(w->flags & WINDOW_BELL) || wl->flags & WINLINK_BELL)
|
if (!(w->flags & WINDOW_BELL))
|
||||||
return (0);
|
return (0);
|
||||||
if (s->curw != wl)
|
|
||||||
wl->flags |= WINLINK_BELL;
|
if (session_alert_has_window(s, w, WINDOW_BELL))
|
||||||
|
return (0);
|
||||||
|
session_alert_add(s, w, WINDOW_BELL);
|
||||||
|
|
||||||
action = options_get_number(&s->options, "bell-action");
|
action = options_get_number(&s->options, "bell-action");
|
||||||
switch (action) {
|
switch (action) {
|
||||||
@@ -121,22 +155,25 @@ server_window_check_bell(struct session *s, struct winlink *wl)
|
|||||||
|
|
||||||
/* Check for activity in window. */
|
/* Check for activity in window. */
|
||||||
int
|
int
|
||||||
server_window_check_activity(struct session *s, struct winlink *wl)
|
server_window_check_activity(struct session *s, struct window *w)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct window *w = wl->window;
|
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
|
if (!(w->flags & WINDOW_ACTIVITY))
|
||||||
return (0);
|
return (0);
|
||||||
if (s->curw == wl)
|
if (s->curw->window == w)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (!options_get_number(&w->options, "monitor-activity"))
|
if (!options_get_number(&w->options, "monitor-activity"))
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
wl->flags |= WINLINK_ACTIVITY;
|
if (session_alert_has_window(s, w, WINDOW_ACTIVITY))
|
||||||
|
return (0);
|
||||||
|
session_alert_add(s, w, WINDOW_ACTIVITY);
|
||||||
|
|
||||||
|
if (s->flags & SESSION_UNATTACHED)
|
||||||
|
return (0);
|
||||||
if (options_get_number(&s->options, "visual-activity")) {
|
if (options_get_number(&s->options, "visual-activity")) {
|
||||||
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);
|
||||||
@@ -150,80 +187,34 @@ server_window_check_activity(struct session *s, struct winlink *wl)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for silence in window. */
|
|
||||||
int
|
|
||||||
server_window_check_silence(struct session *s, struct winlink *wl)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
struct window *w = wl->window;
|
|
||||||
struct timeval timer;
|
|
||||||
u_int i;
|
|
||||||
int silence_interval, timer_difference;
|
|
||||||
|
|
||||||
if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (s->curw == wl) {
|
|
||||||
/*
|
|
||||||
* Reset the timer for this window if we've focused it. We
|
|
||||||
* don't want the timer tripping as soon as we've switched away
|
|
||||||
* from this window.
|
|
||||||
*/
|
|
||||||
if (gettimeofday(&w->silence_timer, NULL) != 0)
|
|
||||||
fatal("gettimeofday failed.");
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
silence_interval = options_get_number(&w->options, "monitor-silence");
|
|
||||||
if (silence_interval == 0)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (gettimeofday(&timer, NULL) != 0)
|
|
||||||
fatal("gettimeofday");
|
|
||||||
timer_difference = timer.tv_sec - w->silence_timer.tv_sec;
|
|
||||||
if (timer_difference <= silence_interval)
|
|
||||||
return (0);
|
|
||||||
wl->flags |= WINLINK_SILENCE;
|
|
||||||
|
|
||||||
if (options_get_number(&s->options, "visual-silence")) {
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
c = ARRAY_ITEM(&clients, i);
|
|
||||||
if (c == NULL || c->session != s)
|
|
||||||
continue;
|
|
||||||
status_message_set(c, "Silence in window %u",
|
|
||||||
winlink_find_by_window(&s->windows, w)->idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for content change in window. */
|
/* Check for content change in window. */
|
||||||
int
|
int
|
||||||
server_window_check_content(
|
server_window_check_content(
|
||||||
struct session *s, struct winlink *wl, struct window_pane *wp)
|
struct session *s, struct window *w, struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct window *w = wl->window;
|
|
||||||
u_int i;
|
u_int i;
|
||||||
char *found, *ptr;
|
char *found, *ptr;
|
||||||
|
|
||||||
/* Activity flag must be set for new content. */
|
if (!(w->flags & WINDOW_ACTIVITY)) /* activity for new content */
|
||||||
if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_CONTENT)
|
|
||||||
return (0);
|
return (0);
|
||||||
if (s->curw == wl)
|
if (s->curw->window == w)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
ptr = options_get_string(&w->options, "monitor-content");
|
ptr = options_get_string(&w->options, "monitor-content");
|
||||||
if (ptr == NULL || *ptr == '\0')
|
if (ptr == NULL || *ptr == '\0')
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
if (session_alert_has_window(s, w, WINDOW_CONTENT))
|
||||||
|
return (0);
|
||||||
|
|
||||||
if ((found = window_pane_search(wp, ptr, NULL)) == NULL)
|
if ((found = window_pane_search(wp, ptr, NULL)) == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
xfree(found);
|
xfree(found);
|
||||||
|
|
||||||
wl->flags |= WINLINK_CONTENT;
|
session_alert_add(s, w, WINDOW_CONTENT);
|
||||||
|
if (s->flags & SESSION_UNATTACHED)
|
||||||
|
return (0);
|
||||||
if (options_get_number(&s->options, "visual-content")) {
|
if (options_get_number(&s->options, "visual-content")) {
|
||||||
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);
|
||||||
|
|||||||
188
server.c
188
server.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: server.c,v 1.249 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: server.c,v 1.235 2010-02-08 18:29:32 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -48,6 +48,9 @@ struct clients dead_clients;
|
|||||||
int server_fd;
|
int server_fd;
|
||||||
int server_shutdown;
|
int server_shutdown;
|
||||||
struct event server_ev_accept;
|
struct event server_ev_accept;
|
||||||
|
struct event server_ev_sigterm;
|
||||||
|
struct event server_ev_sigusr1;
|
||||||
|
struct event server_ev_sigchld;
|
||||||
struct event server_ev_second;
|
struct event server_ev_second;
|
||||||
|
|
||||||
int server_create_socket(void);
|
int server_create_socket(void);
|
||||||
@@ -85,7 +88,7 @@ server_create_socket(void)
|
|||||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||||
fatal("socket failed");
|
fatal("socket failed");
|
||||||
|
|
||||||
mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
|
mask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
|
||||||
if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1)
|
if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1)
|
||||||
fatal("bind failed");
|
fatal("bind failed");
|
||||||
umask(mask);
|
umask(mask);
|
||||||
@@ -97,6 +100,8 @@ server_create_socket(void)
|
|||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
fatal("fcntl failed");
|
||||||
|
|
||||||
server_update_socket();
|
server_update_socket();
|
||||||
|
|
||||||
@@ -105,13 +110,16 @@ server_create_socket(void)
|
|||||||
|
|
||||||
/* Fork new server. */
|
/* Fork new server. */
|
||||||
int
|
int
|
||||||
server_start(void)
|
server_start(char *path)
|
||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
int pair[2];
|
int pair[2], retval;
|
||||||
char *cause;
|
char *cause;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
#ifdef HAVE_SETPROCTITLE
|
||||||
|
char rpathbuf[MAXPATHLEN];
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The first client is special and gets a socketpair; create it. */
|
/* The first client is special and gets a socketpair; create it. */
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
|
||||||
@@ -135,33 +143,49 @@ server_start(void)
|
|||||||
if (daemon(1, 0) != 0)
|
if (daemon(1, 0) != 0)
|
||||||
fatal("daemon failed");
|
fatal("daemon failed");
|
||||||
|
|
||||||
/* event_init() was called in our parent, need to reinit. */
|
|
||||||
if (event_reinit(ev_base) != 0)
|
|
||||||
fatal("event_reinit failed");
|
|
||||||
clear_signals(0);
|
|
||||||
|
|
||||||
logfile("server");
|
logfile("server");
|
||||||
log_debug("server started, pid %ld", (long) getpid());
|
log_debug("server started, pid %ld", (long) getpid());
|
||||||
|
|
||||||
ARRAY_INIT(&windows);
|
ARRAY_INIT(&windows);
|
||||||
ARRAY_INIT(&clients);
|
ARRAY_INIT(&clients);
|
||||||
ARRAY_INIT(&dead_clients);
|
ARRAY_INIT(&dead_clients);
|
||||||
RB_INIT(&sessions);
|
ARRAY_INIT(&sessions);
|
||||||
RB_INIT(&dead_sessions);
|
ARRAY_INIT(&dead_sessions);
|
||||||
TAILQ_INIT(&session_groups);
|
TAILQ_INIT(&session_groups);
|
||||||
mode_key_init_trees();
|
mode_key_init_trees();
|
||||||
key_bindings_init();
|
key_bindings_init();
|
||||||
utf8_build();
|
utf8_build();
|
||||||
|
|
||||||
start_time = time(NULL);
|
start_time = time(NULL);
|
||||||
log_debug("socket path %s", socket_path);
|
socket_path = path;
|
||||||
|
|
||||||
#ifdef HAVE_SETPROCTITLE
|
#ifdef HAVE_SETPROCTITLE
|
||||||
setproctitle("server (%s)", socket_path);
|
if (realpath(socket_path, rpathbuf) == NULL)
|
||||||
|
strlcpy(rpathbuf, socket_path, sizeof rpathbuf);
|
||||||
|
log_debug("socket path %s", socket_path);
|
||||||
|
setproctitle("server (%s)", rpathbuf);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_BROKEN_KQUEUE
|
||||||
|
if (setenv("EVENT_NOKQUEUE", "1", 1) != 0)
|
||||||
|
fatal("setenv failed");
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_BROKEN_POLL
|
||||||
|
if (setenv("EVENT_NOPOLL", "1", 1) != 0)
|
||||||
|
fatal("setenv failed");
|
||||||
|
#endif
|
||||||
|
event_init();
|
||||||
|
#ifdef HAVE_BROKEN_KQUEUE
|
||||||
|
unsetenv("EVENT_NOKQUEUE");
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_BROKEN_POLL
|
||||||
|
unsetenv("EVENT_NOPOLL");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
server_fd = server_create_socket();
|
server_fd = server_create_socket();
|
||||||
server_client_create(pair[1]);
|
server_client_create(pair[1]);
|
||||||
|
|
||||||
|
retval = 0;
|
||||||
if (access(SYSTEM_CFG, R_OK) == 0)
|
if (access(SYSTEM_CFG, R_OK) == 0)
|
||||||
load_cfg(SYSTEM_CFG, NULL, &cfg_causes);
|
load_cfg(SYSTEM_CFG, NULL, &cfg_causes);
|
||||||
else if (errno != ENOENT) {
|
else if (errno != ENOENT) {
|
||||||
@@ -175,13 +199,12 @@ server_start(void)
|
|||||||
* If there is a session already, put the current window and pane into
|
* If there is a session already, put the current window and pane into
|
||||||
* more mode.
|
* more mode.
|
||||||
*/
|
*/
|
||||||
if (!RB_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) {
|
if (!ARRAY_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) {
|
||||||
wp = RB_MIN(sessions, &sessions)->curw->window->active;
|
wp = ARRAY_FIRST(&sessions)->curw->window->active;
|
||||||
window_pane_set_mode(wp, &window_copy_mode);
|
window_pane_set_mode(wp, &window_more_mode);
|
||||||
window_copy_init_for_output(wp);
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
|
||||||
cause = ARRAY_ITEM(&cfg_causes, i);
|
cause = ARRAY_ITEM(&cfg_causes, i);
|
||||||
window_copy_add(wp, "%s", cause);
|
window_more_add(wp, "%s", cause);
|
||||||
xfree(cause);
|
xfree(cause);
|
||||||
}
|
}
|
||||||
ARRAY_FREE(&cfg_causes);
|
ARRAY_FREE(&cfg_causes);
|
||||||
@@ -197,7 +220,7 @@ server_start(void)
|
|||||||
evtimer_set(&server_ev_second, server_second_callback, NULL);
|
evtimer_set(&server_ev_second, server_second_callback, NULL);
|
||||||
evtimer_add(&server_ev_second, &tv);
|
evtimer_add(&server_ev_second, &tv);
|
||||||
|
|
||||||
set_signals(server_signal_callback);
|
server_signal_set();
|
||||||
server_loop();
|
server_loop();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@@ -217,14 +240,14 @@ server_loop(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the server should be shutting down (no more clients or sessions). */
|
/* Check if the server should be shutting down (no more clients or windows). */
|
||||||
int
|
int
|
||||||
server_should_shutdown(void)
|
server_should_shutdown(void)
|
||||||
{
|
{
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (!options_get_number(&global_options, "exit-unattached")) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
if (!RB_EMPTY(&sessions))
|
if (ARRAY_ITEM(&sessions, i) != NULL)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
@@ -239,7 +262,7 @@ void
|
|||||||
server_send_shutdown(void)
|
server_send_shutdown(void)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct session *s, *next_s;
|
struct session *s;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
@@ -253,11 +276,9 @@ server_send_shutdown(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s = RB_MIN(sessions, &sessions);
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
while (s != NULL) {
|
if ((s = ARRAY_ITEM(&sessions, i)) != NULL)
|
||||||
next_s = RB_NEXT(sessions, &sessions, s);
|
session_destroy(s);
|
||||||
session_destroy(s);
|
|
||||||
s = next_s;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,19 +286,16 @@ server_send_shutdown(void)
|
|||||||
void
|
void
|
||||||
server_clean_dead(void)
|
server_clean_dead(void)
|
||||||
{
|
{
|
||||||
struct session *s, *next_s;
|
struct session *s;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
s = RB_MIN(sessions, &dead_sessions);
|
for (i = 0; i < ARRAY_LENGTH(&dead_sessions); i++) {
|
||||||
while (s != NULL) {
|
s = ARRAY_ITEM(&dead_sessions, i);
|
||||||
next_s = RB_NEXT(sessions, &dead_sessions, s);
|
if (s == NULL || s->references != 0)
|
||||||
if (s->references == 0) {
|
continue;
|
||||||
RB_REMOVE(sessions, &dead_sessions, s);
|
ARRAY_SET(&dead_sessions, i, NULL);
|
||||||
xfree(s->name);
|
xfree(s);
|
||||||
xfree(s);
|
|
||||||
}
|
|
||||||
s = next_s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
|
||||||
@@ -294,13 +312,14 @@ void
|
|||||||
server_update_socket(void)
|
server_update_socket(void)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
u_int i;
|
||||||
static int last = -1;
|
static int last = -1;
|
||||||
int n, mode;
|
int n;
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
if (!(s->flags & SESSION_UNATTACHED)) {
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
|
if (s != NULL && !(s->flags & SESSION_UNATTACHED)) {
|
||||||
n++;
|
n++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -308,20 +327,10 @@ server_update_socket(void)
|
|||||||
|
|
||||||
if (n != last) {
|
if (n != last) {
|
||||||
last = n;
|
last = n;
|
||||||
|
if (n != 0)
|
||||||
if (stat(socket_path, &sb) != 0)
|
chmod(socket_path, S_IRWXU);
|
||||||
return;
|
else
|
||||||
mode = sb.st_mode;
|
chmod(socket_path, S_IRUSR|S_IWUSR);
|
||||||
if (n != 0) {
|
|
||||||
if (mode & S_IRUSR)
|
|
||||||
mode |= S_IXUSR;
|
|
||||||
if (mode & S_IRGRP)
|
|
||||||
mode |= S_IXGRP;
|
|
||||||
if (mode & S_IROTH)
|
|
||||||
mode |= S_IXOTH;
|
|
||||||
} else
|
|
||||||
mode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
|
|
||||||
chmod(socket_path, mode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,6 +359,61 @@ server_accept_callback(int fd, short events, unused void *data)
|
|||||||
server_client_create(newfd);
|
server_client_create(newfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set up server signal handling. */
|
||||||
|
void
|
||||||
|
server_signal_set(void)
|
||||||
|
{
|
||||||
|
struct sigaction sigact;
|
||||||
|
|
||||||
|
memset(&sigact, 0, sizeof sigact);
|
||||||
|
sigemptyset(&sigact.sa_mask);
|
||||||
|
sigact.sa_flags = SA_RESTART;
|
||||||
|
sigact.sa_handler = SIG_IGN;
|
||||||
|
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGHUP, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
|
||||||
|
signal_set(&server_ev_sigchld, SIGCHLD, server_signal_callback, NULL);
|
||||||
|
signal_add(&server_ev_sigchld, NULL);
|
||||||
|
signal_set(&server_ev_sigterm, SIGTERM, server_signal_callback, NULL);
|
||||||
|
signal_add(&server_ev_sigterm, NULL);
|
||||||
|
signal_set(&server_ev_sigusr1, SIGUSR1, server_signal_callback, NULL);
|
||||||
|
signal_add(&server_ev_sigusr1, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroy server signal events. */
|
||||||
|
void
|
||||||
|
server_signal_clear(void)
|
||||||
|
{
|
||||||
|
struct sigaction sigact;
|
||||||
|
|
||||||
|
memset(&sigact, 0, sizeof sigact);
|
||||||
|
sigemptyset(&sigact.sa_mask);
|
||||||
|
sigact.sa_flags = SA_RESTART;
|
||||||
|
sigact.sa_handler = SIG_DFL;
|
||||||
|
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGHUP, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
|
||||||
|
signal_del(&server_ev_sigchld);
|
||||||
|
signal_del(&server_ev_sigterm);
|
||||||
|
signal_del(&server_ev_sigusr1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Signal handler. */
|
/* Signal handler. */
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
@@ -487,11 +551,15 @@ void
|
|||||||
server_lock_server(void)
|
server_lock_server(void)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
u_int i;
|
||||||
int timeout;
|
int timeout;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
|
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (s->flags & SESSION_UNATTACHED) {
|
if (s->flags & SESSION_UNATTACHED) {
|
||||||
if (gettimeofday(&s->activity_time, NULL) != 0)
|
if (gettimeofday(&s->activity_time, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday failed");
|
||||||
@@ -512,11 +580,15 @@ void
|
|||||||
server_lock_sessions(void)
|
server_lock_sessions(void)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
u_int i;
|
||||||
int timeout;
|
int timeout;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
|
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (s->flags & SESSION_UNATTACHED) {
|
if (s->flags & SESSION_UNATTACHED) {
|
||||||
if (gettimeofday(&s->activity_time, NULL) != 0)
|
if (gettimeofday(&s->activity_time, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday failed");
|
||||||
|
|||||||
238
session.c
238
session.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: session.c,v 1.83 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: session.c,v 1.74 2009-12-26 23:45:21 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -29,56 +29,87 @@
|
|||||||
/* Global session list. */
|
/* Global session list. */
|
||||||
struct sessions sessions;
|
struct sessions sessions;
|
||||||
struct sessions dead_sessions;
|
struct sessions dead_sessions;
|
||||||
u_int next_session;
|
|
||||||
struct session_groups session_groups;
|
struct session_groups session_groups;
|
||||||
|
|
||||||
struct winlink *session_next_alert(struct winlink *);
|
struct winlink *session_next_activity(struct session *, struct winlink *);
|
||||||
struct winlink *session_previous_alert(struct winlink *);
|
struct winlink *session_previous_activity(struct session *, struct winlink *);
|
||||||
|
|
||||||
RB_GENERATE(sessions, session, entry, session_cmp);
|
void
|
||||||
|
session_alert_cancel(struct session *s, struct winlink *wl)
|
||||||
int
|
|
||||||
session_cmp(struct session *s1, struct session *s2)
|
|
||||||
{
|
{
|
||||||
return (strcmp(s1->name, s2->name));
|
struct session_alert *sa, *sb;
|
||||||
|
|
||||||
|
sa = SLIST_FIRST(&s->alerts);
|
||||||
|
while (sa != NULL) {
|
||||||
|
sb = sa;
|
||||||
|
sa = SLIST_NEXT(sa, entry);
|
||||||
|
|
||||||
|
if (wl == NULL || sb->wl == wl) {
|
||||||
|
SLIST_REMOVE(&s->alerts, sb, session_alert, entry);
|
||||||
|
xfree(sb);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void
|
||||||
* Find if session is still alive. This is true if it is still on the global
|
session_alert_add(struct session *s, struct window *w, int type)
|
||||||
* sessions list.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
session_alive(struct session *s)
|
|
||||||
{
|
{
|
||||||
struct session *s_loop;
|
struct session_alert *sa;
|
||||||
|
struct winlink *wl;
|
||||||
|
|
||||||
RB_FOREACH(s_loop, sessions, &sessions) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
if (s_loop == s)
|
if (wl == s->curw)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (wl->window == w &&
|
||||||
|
!session_alert_has(s, wl, type)) {
|
||||||
|
sa = xmalloc(sizeof *sa);
|
||||||
|
sa->wl = wl;
|
||||||
|
sa->type = type;
|
||||||
|
SLIST_INSERT_HEAD(&s->alerts, sa, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
session_alert_has(struct session *s, struct winlink *wl, int type)
|
||||||
|
{
|
||||||
|
struct session_alert *sa;
|
||||||
|
|
||||||
|
SLIST_FOREACH(sa, &s->alerts, entry) {
|
||||||
|
if (sa->wl == wl && sa->type == type)
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
session_alert_has_window(struct session *s, struct window *w, int type)
|
||||||
|
{
|
||||||
|
struct session_alert *sa;
|
||||||
|
|
||||||
|
SLIST_FOREACH(sa, &s->alerts, entry) {
|
||||||
|
if (sa->wl->window == w && sa->type == type)
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find session by name. */
|
/* Find session by name. */
|
||||||
struct session *
|
struct session *
|
||||||
session_find(const char *name)
|
session_find(const char *name)
|
||||||
{
|
|
||||||
struct session s;
|
|
||||||
|
|
||||||
s.name = (char *) name;
|
|
||||||
return (RB_FIND(sessions, &sessions, &s));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find session by index. */
|
|
||||||
struct session *
|
|
||||||
session_find_by_index(u_int idx)
|
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
if (s->idx == idx)
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
|
if (s != NULL && strcmp(s->name, name) == 0)
|
||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +120,7 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
char **cause)
|
char **cause)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
s = xmalloc(sizeof *s);
|
s = xmalloc(sizeof *s);
|
||||||
s->references = 0;
|
s->references = 0;
|
||||||
@@ -98,11 +130,10 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday failed");
|
||||||
memcpy(&s->activity_time, &s->creation_time, sizeof s->activity_time);
|
memcpy(&s->activity_time, &s->creation_time, sizeof s->activity_time);
|
||||||
|
|
||||||
s->cwd = xstrdup(cwd);
|
|
||||||
|
|
||||||
s->curw = NULL;
|
s->curw = NULL;
|
||||||
TAILQ_INIT(&s->lastw);
|
TAILQ_INIT(&s->lastw);
|
||||||
RB_INIT(&s->windows);
|
RB_INIT(&s->windows);
|
||||||
|
SLIST_INIT(&s->alerts);
|
||||||
|
|
||||||
paste_init_stack(&s->buffers);
|
paste_init_stack(&s->buffers);
|
||||||
|
|
||||||
@@ -120,12 +151,19 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
s->sx = sx;
|
s->sx = sx;
|
||||||
s->sy = sy;
|
s->sy = sy;
|
||||||
|
|
||||||
s->idx = next_session++;
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
|
if (ARRAY_ITEM(&sessions, i) == NULL) {
|
||||||
|
ARRAY_SET(&sessions, i, s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == ARRAY_LENGTH(&sessions))
|
||||||
|
ARRAY_ADD(&sessions, s);
|
||||||
|
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
s->name = xstrdup(name);
|
s->name = xstrdup(name);
|
||||||
else
|
else
|
||||||
xasprintf(&s->name, "%u", s->idx);
|
xasprintf(&s->name, "%u", i);
|
||||||
RB_INSERT(sessions, &sessions, s);
|
|
||||||
|
|
||||||
if (cmd != NULL) {
|
if (cmd != NULL) {
|
||||||
if (session_new(s, NULL, cmd, cwd, idx, cause) == NULL) {
|
if (session_new(s, NULL, cmd, cwd, idx, cause) == NULL) {
|
||||||
@@ -144,14 +182,21 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
void
|
void
|
||||||
session_destroy(struct session *s)
|
session_destroy(struct session *s)
|
||||||
{
|
{
|
||||||
|
u_int i;
|
||||||
|
|
||||||
log_debug("session %s destroyed", s->name);
|
log_debug("session %s destroyed", s->name);
|
||||||
|
|
||||||
RB_REMOVE(sessions, &sessions, s);
|
if (session_index(s, &i) != 0)
|
||||||
|
fatalx("session not found");
|
||||||
|
ARRAY_SET(&sessions, i, NULL);
|
||||||
|
while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL)
|
||||||
|
ARRAY_TRUNC(&sessions, 1);
|
||||||
|
|
||||||
if (s->tio != NULL)
|
if (s->tio != NULL)
|
||||||
xfree(s->tio);
|
xfree(s->tio);
|
||||||
|
|
||||||
session_group_remove(s);
|
session_group_remove(s);
|
||||||
|
session_alert_cancel(s, NULL);
|
||||||
environ_free(&s->environ);
|
environ_free(&s->environ);
|
||||||
options_free(&s->options);
|
options_free(&s->options);
|
||||||
paste_free_stack(&s->buffers);
|
paste_free_stack(&s->buffers);
|
||||||
@@ -161,49 +206,28 @@ session_destroy(struct session *s)
|
|||||||
while (!RB_EMPTY(&s->windows))
|
while (!RB_EMPTY(&s->windows))
|
||||||
winlink_remove(&s->windows, RB_ROOT(&s->windows));
|
winlink_remove(&s->windows, RB_ROOT(&s->windows));
|
||||||
|
|
||||||
xfree(s->cwd);
|
xfree(s->name);
|
||||||
|
|
||||||
RB_INSERT(sessions, &dead_sessions, s);
|
for (i = 0; i < ARRAY_LENGTH(&dead_sessions); i++) {
|
||||||
|
if (ARRAY_ITEM(&dead_sessions, i) == NULL) {
|
||||||
|
ARRAY_SET(&dead_sessions, i, s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == ARRAY_LENGTH(&dead_sessions))
|
||||||
|
ARRAY_ADD(&dead_sessions, s);
|
||||||
|
s->flags |= SESSION_DEAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the next usable session. */
|
/* Find session index. */
|
||||||
struct session *
|
int
|
||||||
session_next_session(struct session *s)
|
session_index(struct session *s, u_int *i)
|
||||||
{
|
{
|
||||||
struct session *s2;
|
for (*i = 0; *i < ARRAY_LENGTH(&sessions); (*i)++) {
|
||||||
|
if (s == ARRAY_ITEM(&sessions, *i))
|
||||||
if (RB_EMPTY(&sessions) || !session_alive(s))
|
return (0);
|
||||||
return (NULL);
|
}
|
||||||
|
return (-1);
|
||||||
s2 = s;
|
|
||||||
do {
|
|
||||||
s2 = RB_NEXT(sessions, &sessions, s2);
|
|
||||||
if (s2 == NULL)
|
|
||||||
s2 = RB_MIN(sessions, &sessions);
|
|
||||||
} while (s2 != s);
|
|
||||||
if (s2 == s)
|
|
||||||
return (NULL);
|
|
||||||
return (s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the previous usable session. */
|
|
||||||
struct session *
|
|
||||||
session_previous_session(struct session *s)
|
|
||||||
{
|
|
||||||
struct session *s2;
|
|
||||||
|
|
||||||
if (RB_EMPTY(&sessions) || !session_alive(s))
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
s2 = s;
|
|
||||||
do {
|
|
||||||
s2 = RB_PREV(sessions, &sessions, s2);
|
|
||||||
if (s2 == NULL)
|
|
||||||
s2 = RB_MAX(sessions, &sessions);
|
|
||||||
} while (s2 != s);
|
|
||||||
if (s2 == s)
|
|
||||||
return (NULL);
|
|
||||||
return (s2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new window on a session. */
|
/* Create a new window on a session. */
|
||||||
@@ -260,7 +284,7 @@ session_detach(struct session *s, struct winlink *wl)
|
|||||||
session_last(s) != 0 && session_previous(s, 0) != 0)
|
session_last(s) != 0 && session_previous(s, 0) != 0)
|
||||||
session_next(s, 0);
|
session_next(s, 0);
|
||||||
|
|
||||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
session_alert_cancel(s, wl);
|
||||||
winlink_stack_remove(&s->lastw, wl);
|
winlink_stack_remove(&s->lastw, wl);
|
||||||
winlink_remove(&s->windows, wl);
|
winlink_remove(&s->windows, wl);
|
||||||
session_group_synchronize_from(s);
|
session_group_synchronize_from(s);
|
||||||
@@ -272,23 +296,27 @@ session_detach(struct session *s, struct winlink *wl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return if session has window. */
|
/* Return if session has window. */
|
||||||
struct winlink *
|
int
|
||||||
session_has(struct session *s, struct window *w)
|
session_has(struct session *s, struct window *w)
|
||||||
{
|
{
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
if (wl->window == w)
|
if (wl->window == w)
|
||||||
return (wl);
|
return (1);
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct winlink *
|
struct winlink *
|
||||||
session_next_alert(struct winlink *wl)
|
session_next_activity(struct session *s, struct winlink *wl)
|
||||||
{
|
{
|
||||||
while (wl != NULL) {
|
while (wl != NULL) {
|
||||||
if (wl->flags & WINLINK_ALERTFLAGS)
|
if (session_alert_has(s, wl, WINDOW_BELL))
|
||||||
|
break;
|
||||||
|
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||||
|
break;
|
||||||
|
if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||||
break;
|
break;
|
||||||
wl = winlink_next(wl);
|
wl = winlink_next(wl);
|
||||||
}
|
}
|
||||||
@@ -297,7 +325,7 @@ session_next_alert(struct winlink *wl)
|
|||||||
|
|
||||||
/* Move session to next window. */
|
/* Move session to next window. */
|
||||||
int
|
int
|
||||||
session_next(struct session *s, int alert)
|
session_next(struct session *s, int activity)
|
||||||
{
|
{
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
|
|
||||||
@@ -305,11 +333,11 @@ session_next(struct session *s, int alert)
|
|||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
wl = winlink_next(s->curw);
|
wl = winlink_next(s->curw);
|
||||||
if (alert)
|
if (activity)
|
||||||
wl = session_next_alert(wl);
|
wl = session_next_activity(s, wl);
|
||||||
if (wl == NULL) {
|
if (wl == NULL) {
|
||||||
wl = RB_MIN(winlinks, &s->windows);
|
wl = RB_MIN(winlinks, &s->windows);
|
||||||
if (alert && ((wl = session_next_alert(wl)) == NULL))
|
if (activity && ((wl = session_next_activity(s, wl)) == NULL))
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if (wl == s->curw)
|
if (wl == s->curw)
|
||||||
@@ -317,15 +345,19 @@ session_next(struct session *s, int alert)
|
|||||||
winlink_stack_remove(&s->lastw, wl);
|
winlink_stack_remove(&s->lastw, wl);
|
||||||
winlink_stack_push(&s->lastw, s->curw);
|
winlink_stack_push(&s->lastw, s->curw);
|
||||||
s->curw = wl;
|
s->curw = wl;
|
||||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
session_alert_cancel(s, wl);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct winlink *
|
struct winlink *
|
||||||
session_previous_alert(struct winlink *wl)
|
session_previous_activity(struct session *s, struct winlink *wl)
|
||||||
{
|
{
|
||||||
while (wl != NULL) {
|
while (wl != NULL) {
|
||||||
if (wl->flags & WINLINK_ALERTFLAGS)
|
if (session_alert_has(s, wl, WINDOW_BELL))
|
||||||
|
break;
|
||||||
|
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||||
|
break;
|
||||||
|
if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||||
break;
|
break;
|
||||||
wl = winlink_previous(wl);
|
wl = winlink_previous(wl);
|
||||||
}
|
}
|
||||||
@@ -334,7 +366,7 @@ session_previous_alert(struct winlink *wl)
|
|||||||
|
|
||||||
/* Move session to previous window. */
|
/* Move session to previous window. */
|
||||||
int
|
int
|
||||||
session_previous(struct session *s, int alert)
|
session_previous(struct session *s, int activity)
|
||||||
{
|
{
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
|
|
||||||
@@ -342,11 +374,11 @@ session_previous(struct session *s, int alert)
|
|||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
wl = winlink_previous(s->curw);
|
wl = winlink_previous(s->curw);
|
||||||
if (alert)
|
if (activity)
|
||||||
wl = session_previous_alert(wl);
|
wl = session_previous_activity(s, wl);
|
||||||
if (wl == NULL) {
|
if (wl == NULL) {
|
||||||
wl = RB_MAX(winlinks, &s->windows);
|
wl = RB_MAX(winlinks, &s->windows);
|
||||||
if (alert && (wl = session_previous_alert(wl)) == NULL)
|
if (activity && (wl = session_previous_activity(s, wl)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if (wl == s->curw)
|
if (wl == s->curw)
|
||||||
@@ -354,7 +386,7 @@ session_previous(struct session *s, int alert)
|
|||||||
winlink_stack_remove(&s->lastw, wl);
|
winlink_stack_remove(&s->lastw, wl);
|
||||||
winlink_stack_push(&s->lastw, s->curw);
|
winlink_stack_push(&s->lastw, s->curw);
|
||||||
s->curw = wl;
|
s->curw = wl;
|
||||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
session_alert_cancel(s, wl);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +404,7 @@ session_select(struct session *s, int idx)
|
|||||||
winlink_stack_remove(&s->lastw, wl);
|
winlink_stack_remove(&s->lastw, wl);
|
||||||
winlink_stack_push(&s->lastw, s->curw);
|
winlink_stack_push(&s->lastw, s->curw);
|
||||||
s->curw = wl;
|
s->curw = wl;
|
||||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
session_alert_cancel(s, wl);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,7 +423,7 @@ session_last(struct session *s)
|
|||||||
winlink_stack_remove(&s->lastw, wl);
|
winlink_stack_remove(&s->lastw, wl);
|
||||||
winlink_stack_push(&s->lastw, s->curw);
|
winlink_stack_push(&s->lastw, s->curw);
|
||||||
s->curw = wl;
|
s->curw = wl;
|
||||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
session_alert_cancel(s, wl);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,6 +540,7 @@ session_group_synchronize1(struct session *target, struct session *s)
|
|||||||
struct winlinks old_windows, *ww;
|
struct winlinks old_windows, *ww;
|
||||||
struct winlink_stack old_lastw;
|
struct winlink_stack old_lastw;
|
||||||
struct winlink *wl, *wl2;
|
struct winlink *wl, *wl2;
|
||||||
|
struct session_alert *sa;
|
||||||
|
|
||||||
/* Don't do anything if the session is empty (it'll be destroyed). */
|
/* Don't do anything if the session is empty (it'll be destroyed). */
|
||||||
ww = &target->windows;
|
ww = &target->windows;
|
||||||
@@ -525,10 +558,8 @@ session_group_synchronize1(struct session *target, struct session *s)
|
|||||||
RB_INIT(&s->windows);
|
RB_INIT(&s->windows);
|
||||||
|
|
||||||
/* Link all the windows from the target. */
|
/* Link all the windows from the target. */
|
||||||
RB_FOREACH(wl, winlinks, ww) {
|
RB_FOREACH(wl, winlinks, ww)
|
||||||
wl2 = winlink_add(&s->windows, wl->window, wl->idx);
|
winlink_add(&s->windows, wl->window, wl->idx);
|
||||||
wl2->flags |= wl->flags & WINLINK_ALERTFLAGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fix up the current window. */
|
/* Fix up the current window. */
|
||||||
if (s->curw != NULL)
|
if (s->curw != NULL)
|
||||||
@@ -545,6 +576,15 @@ session_group_synchronize1(struct session *target, struct session *s)
|
|||||||
TAILQ_INSERT_TAIL(&s->lastw, wl2, sentry);
|
TAILQ_INSERT_TAIL(&s->lastw, wl2, sentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* And update the alerts list. */
|
||||||
|
SLIST_FOREACH(sa, &s->alerts, entry) {
|
||||||
|
wl = winlink_find_by_index(&s->windows, sa->wl->idx);
|
||||||
|
if (wl == NULL)
|
||||||
|
session_alert_cancel(s, sa->wl);
|
||||||
|
else
|
||||||
|
sa->wl = wl;
|
||||||
|
}
|
||||||
|
|
||||||
/* Then free the old winlinks list. */
|
/* Then free the old winlinks list. */
|
||||||
while (!RB_EMPTY(&old_windows)) {
|
while (!RB_EMPTY(&old_windows)) {
|
||||||
wl = RB_ROOT(&old_windows);
|
wl = RB_ROOT(&old_windows);
|
||||||
|
|||||||
103
signal.c
103
signal.c
@@ -1,103 +0,0 @@
|
|||||||
/* $Id: signal.c,v 1.3 2010-08-29 14:42:11 tcunha Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
|
||||||
* Copyright (c) 2010 Romain Francoise <rfrancoise@debian.org>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
struct event ev_sighup;
|
|
||||||
struct event ev_sigchld;
|
|
||||||
struct event ev_sigcont;
|
|
||||||
struct event ev_sigterm;
|
|
||||||
struct event ev_sigusr1;
|
|
||||||
struct event ev_sigwinch;
|
|
||||||
|
|
||||||
void
|
|
||||||
set_signals(void(*handler)(int, short, unused void *))
|
|
||||||
{
|
|
||||||
struct sigaction sigact;
|
|
||||||
|
|
||||||
memset(&sigact, 0, sizeof sigact);
|
|
||||||
sigemptyset(&sigact.sa_mask);
|
|
||||||
sigact.sa_flags = SA_RESTART;
|
|
||||||
sigact.sa_handler = SIG_IGN;
|
|
||||||
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
|
|
||||||
signal_set(&ev_sighup, SIGHUP, handler, NULL);
|
|
||||||
signal_add(&ev_sighup, NULL);
|
|
||||||
signal_set(&ev_sigchld, SIGCHLD, handler, NULL);
|
|
||||||
signal_add(&ev_sigchld, NULL);
|
|
||||||
signal_set(&ev_sigcont, SIGCONT, handler, NULL);
|
|
||||||
signal_add(&ev_sigcont, NULL);
|
|
||||||
signal_set(&ev_sigterm, SIGTERM, handler, NULL);
|
|
||||||
signal_add(&ev_sigterm, NULL);
|
|
||||||
signal_set(&ev_sigusr1, SIGUSR1, handler, NULL);
|
|
||||||
signal_add(&ev_sigusr1, NULL);
|
|
||||||
signal_set(&ev_sigwinch, SIGWINCH, handler, NULL);
|
|
||||||
signal_add(&ev_sigwinch, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clear_signals(int after_fork)
|
|
||||||
{
|
|
||||||
struct sigaction sigact;
|
|
||||||
|
|
||||||
memset(&sigact, 0, sizeof sigact);
|
|
||||||
sigemptyset(&sigact.sa_mask);
|
|
||||||
sigact.sa_flags = SA_RESTART;
|
|
||||||
sigact.sa_handler = SIG_DFL;
|
|
||||||
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
|
|
||||||
if (after_fork) {
|
|
||||||
if (sigaction(SIGHUP, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGCHLD, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGCONT, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGTERM, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGUSR1, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
if (sigaction(SIGWINCH, &sigact, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
} else {
|
|
||||||
event_del(&ev_sighup);
|
|
||||||
event_del(&ev_sigchld);
|
|
||||||
event_del(&ev_sigcont);
|
|
||||||
event_del(&ev_sigterm);
|
|
||||||
event_del(&ev_sigusr1);
|
|
||||||
event_del(&ev_sigwinch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
157
status.c
157
status.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: status.c,v 1.151 2010-12-11 16:15:02 nicm Exp $ */
|
/* $Id: status.c,v 1.144 2010-03-10 13:41:13 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -35,20 +35,16 @@ char *status_redraw_get_right(
|
|||||||
struct client *, time_t, int, struct grid_cell *, size_t *);
|
struct client *, time_t, int, struct grid_cell *, size_t *);
|
||||||
char *status_job(struct client *, char **);
|
char *status_job(struct client *, char **);
|
||||||
void status_job_callback(struct job *);
|
void status_job_callback(struct job *);
|
||||||
|
size_t status_width(struct client *, struct winlink *, time_t);
|
||||||
char *status_print(
|
char *status_print(
|
||||||
struct client *, struct winlink *, time_t, struct grid_cell *);
|
struct client *, struct winlink *, time_t, struct grid_cell *);
|
||||||
void status_replace1(struct client *,
|
void status_replace1(struct client *,
|
||||||
struct winlink *, char **, char **, char *, size_t, int);
|
struct winlink *, char **, char **, char *, size_t, int);
|
||||||
void status_message_callback(int, short, void *);
|
void status_message_callback(int, short, void *);
|
||||||
|
|
||||||
const char *status_prompt_up_history(u_int *);
|
void status_prompt_add_history(struct client *);
|
||||||
const char *status_prompt_down_history(u_int *);
|
|
||||||
void status_prompt_add_history(const char *);
|
|
||||||
char *status_prompt_complete(const char *);
|
char *status_prompt_complete(const char *);
|
||||||
|
|
||||||
/* Status prompt history. */
|
|
||||||
ARRAY_DECL(, char *) status_prompt_history = ARRAY_INITIALIZER;
|
|
||||||
|
|
||||||
/* Retrieve options for left string. */
|
/* Retrieve options for left string. */
|
||||||
char *
|
char *
|
||||||
status_redraw_get_left(struct client *c,
|
status_redraw_get_left(struct client *c,
|
||||||
@@ -253,15 +249,25 @@ status_redraw(struct client *c)
|
|||||||
*/
|
*/
|
||||||
offset = 0;
|
offset = 0;
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
if (wl->flags & WINLINK_ALERTFLAGS &&
|
if (larrow == 1 && offset < wlstart) {
|
||||||
larrow == 1 && offset < wlstart)
|
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||||
larrow = -1;
|
larrow = -1;
|
||||||
|
else if (session_alert_has(s, wl, WINDOW_BELL))
|
||||||
|
larrow = -1;
|
||||||
|
else if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||||
|
larrow = -1;
|
||||||
|
}
|
||||||
|
|
||||||
offset += wl->status_width;
|
offset += wl->status_width;
|
||||||
|
|
||||||
if (wl->flags & WINLINK_ALERTFLAGS &&
|
if (rarrow == 1 && offset > wlstart + wlwidth) {
|
||||||
rarrow == 1 && offset > wlstart + wlwidth)
|
if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||||
rarrow = -1;
|
rarrow = -1;
|
||||||
|
else if (session_alert_has(s, wl, WINDOW_BELL))
|
||||||
|
rarrow = -1;
|
||||||
|
else if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||||
|
rarrow = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw:
|
draw:
|
||||||
@@ -394,14 +400,12 @@ status_replace1(struct client *c,struct winlink *wl,
|
|||||||
goto do_replace;
|
goto do_replace;
|
||||||
case 'F':
|
case 'F':
|
||||||
tmp[0] = ' ';
|
tmp[0] = ' ';
|
||||||
if (wl->flags & WINLINK_CONTENT)
|
if (session_alert_has(s, wl, WINDOW_CONTENT))
|
||||||
tmp[0] = '+';
|
tmp[0] = '+';
|
||||||
else if (wl->flags & WINLINK_BELL)
|
else if (session_alert_has(s, wl, WINDOW_BELL))
|
||||||
tmp[0] = '!';
|
tmp[0] = '!';
|
||||||
else if (wl->flags & WINLINK_ACTIVITY)
|
else if (session_alert_has(s, wl, WINDOW_ACTIVITY))
|
||||||
tmp[0] = '#';
|
tmp[0] = '#';
|
||||||
else if (wl->flags & WINLINK_SILENCE)
|
|
||||||
tmp[0] = '~';
|
|
||||||
else if (wl == s->curw)
|
else if (wl == s->curw)
|
||||||
tmp[0] = '*';
|
tmp[0] = '*';
|
||||||
else if (wl == TAILQ_FIRST(&s->lastw))
|
else if (wl == TAILQ_FIRST(&s->lastw))
|
||||||
@@ -556,6 +560,30 @@ status_job_callback(struct job *job)
|
|||||||
job->data = xstrdup(line);
|
job->data = xstrdup(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate winlink status line entry width. */
|
||||||
|
size_t
|
||||||
|
status_width(struct client *c, struct winlink *wl, time_t t)
|
||||||
|
{
|
||||||
|
struct options *oo = &wl->window->options;
|
||||||
|
struct session *s = c->session;
|
||||||
|
const char *fmt;
|
||||||
|
char *text;
|
||||||
|
size_t size;
|
||||||
|
int utf8flag;
|
||||||
|
|
||||||
|
utf8flag = options_get_number(&s->options, "status-utf8");
|
||||||
|
|
||||||
|
fmt = options_get_string(&wl->window->options, "window-status-format");
|
||||||
|
if (wl == s->curw)
|
||||||
|
fmt = options_get_string(oo, "window-status-current-format");
|
||||||
|
|
||||||
|
text = status_replace(c, wl, fmt, t, 1);
|
||||||
|
size = screen_write_cstrlen(utf8flag, "%s", text);
|
||||||
|
xfree(text);
|
||||||
|
|
||||||
|
return (size);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return winlink status line entry and adjust gc as necessary. */
|
/* Return winlink status line entry and adjust gc as necessary. */
|
||||||
char *
|
char *
|
||||||
status_print(
|
status_print(
|
||||||
@@ -590,17 +618,10 @@ status_print(
|
|||||||
fmt = options_get_string(oo, "window-status-current-format");
|
fmt = options_get_string(oo, "window-status-current-format");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wl->flags & WINLINK_ALERTFLAGS) {
|
if (session_alert_has(s, wl, WINDOW_ACTIVITY) ||
|
||||||
fg = options_get_number(oo, "window-status-alert-fg");
|
session_alert_has(s, wl, WINDOW_BELL) ||
|
||||||
if (fg != 8)
|
session_alert_has(s, wl, WINDOW_CONTENT))
|
||||||
colour_set_fg(gc, fg);
|
gc->attr ^= GRID_ATTR_REVERSE;
|
||||||
bg = options_get_number(oo, "window-status-alert-bg");
|
|
||||||
if (bg != 8)
|
|
||||||
colour_set_bg(gc, bg);
|
|
||||||
attr = options_get_number(oo, "window-status-alert-attr");
|
|
||||||
if (attr != 0)
|
|
||||||
gc->attr = attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
text = status_replace(c, wl, fmt, t, 1);
|
text = status_replace(c, wl, fmt, t, 1);
|
||||||
return (text);
|
return (text);
|
||||||
@@ -865,7 +886,6 @@ status_prompt_key(struct client *c, int key)
|
|||||||
{
|
{
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb;
|
||||||
char *s, *first, *last, word[64], swapc;
|
char *s, *first, *last, word[64], swapc;
|
||||||
const char *histstr;
|
|
||||||
u_char ch;
|
u_char ch;
|
||||||
size_t size, n, off, idx;
|
size_t size, n, off, idx;
|
||||||
|
|
||||||
@@ -978,20 +998,29 @@ status_prompt_key(struct client *c, int key)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MODEKEYEDIT_HISTORYUP:
|
case MODEKEYEDIT_HISTORYUP:
|
||||||
histstr = status_prompt_up_history(&c->prompt_hindex);
|
if (ARRAY_LENGTH(&c->prompt_hdata) == 0)
|
||||||
if (histstr == NULL)
|
|
||||||
break;
|
break;
|
||||||
xfree(c->prompt_buffer);
|
xfree(c->prompt_buffer);
|
||||||
c->prompt_buffer = xstrdup(histstr);
|
|
||||||
|
c->prompt_buffer = xstrdup(ARRAY_ITEM(&c->prompt_hdata,
|
||||||
|
ARRAY_LENGTH(&c->prompt_hdata) - 1 - c->prompt_hindex));
|
||||||
|
if (c->prompt_hindex != ARRAY_LENGTH(&c->prompt_hdata) - 1)
|
||||||
|
c->prompt_hindex++;
|
||||||
|
|
||||||
c->prompt_index = strlen(c->prompt_buffer);
|
c->prompt_index = strlen(c->prompt_buffer);
|
||||||
c->flags |= CLIENT_STATUS;
|
c->flags |= CLIENT_STATUS;
|
||||||
break;
|
break;
|
||||||
case MODEKEYEDIT_HISTORYDOWN:
|
case MODEKEYEDIT_HISTORYDOWN:
|
||||||
histstr = status_prompt_down_history(&c->prompt_hindex);
|
|
||||||
if (histstr == NULL)
|
|
||||||
break;
|
|
||||||
xfree(c->prompt_buffer);
|
xfree(c->prompt_buffer);
|
||||||
c->prompt_buffer = xstrdup(histstr);
|
|
||||||
|
if (c->prompt_hindex != 0) {
|
||||||
|
c->prompt_hindex--;
|
||||||
|
c->prompt_buffer = xstrdup(ARRAY_ITEM(
|
||||||
|
&c->prompt_hdata, ARRAY_LENGTH(
|
||||||
|
&c->prompt_hdata) - 1 - c->prompt_hindex));
|
||||||
|
} else
|
||||||
|
c->prompt_buffer = xstrdup("");
|
||||||
|
|
||||||
c->prompt_index = strlen(c->prompt_buffer);
|
c->prompt_index = strlen(c->prompt_buffer);
|
||||||
c->flags |= CLIENT_STATUS;
|
c->flags |= CLIENT_STATUS;
|
||||||
break;
|
break;
|
||||||
@@ -1033,7 +1062,7 @@ status_prompt_key(struct client *c, int key)
|
|||||||
break;
|
break;
|
||||||
case MODEKEYEDIT_ENTER:
|
case MODEKEYEDIT_ENTER:
|
||||||
if (*c->prompt_buffer != '\0')
|
if (*c->prompt_buffer != '\0')
|
||||||
status_prompt_add_history(c->prompt_buffer);
|
status_prompt_add_history(c);
|
||||||
if (c->prompt_callbackfn(c->prompt_data, c->prompt_buffer) == 0)
|
if (c->prompt_callbackfn(c->prompt_data, c->prompt_buffer) == 0)
|
||||||
status_prompt_clear(c);
|
status_prompt_clear(c);
|
||||||
break;
|
break;
|
||||||
@@ -1042,7 +1071,7 @@ status_prompt_key(struct client *c, int key)
|
|||||||
status_prompt_clear(c);
|
status_prompt_clear(c);
|
||||||
break;
|
break;
|
||||||
case MODEKEY_OTHER:
|
case MODEKEY_OTHER:
|
||||||
if ((key & 0xff00) != 0 || key < 32 || key == 127)
|
if (key < 32 || key == 127)
|
||||||
break;
|
break;
|
||||||
c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + 2);
|
c->prompt_buffer = xrealloc(c->prompt_buffer, 1, size + 2);
|
||||||
|
|
||||||
@@ -1069,56 +1098,20 @@ status_prompt_key(struct client *c, int key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get previous line from the history. */
|
|
||||||
const char *
|
|
||||||
status_prompt_up_history(u_int *idx)
|
|
||||||
{
|
|
||||||
u_int size;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* History runs from 0 to size - 1.
|
|
||||||
*
|
|
||||||
* Index is from 0 to size. Zero is empty.
|
|
||||||
*/
|
|
||||||
|
|
||||||
size = ARRAY_LENGTH(&status_prompt_history);
|
|
||||||
if (size == 0 || *idx == size)
|
|
||||||
return (NULL);
|
|
||||||
(*idx)++;
|
|
||||||
return (ARRAY_ITEM(&status_prompt_history, size - *idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get next line from the history. */
|
|
||||||
const char *
|
|
||||||
status_prompt_down_history(u_int *idx)
|
|
||||||
{
|
|
||||||
u_int size;
|
|
||||||
|
|
||||||
size = ARRAY_LENGTH(&status_prompt_history);
|
|
||||||
if (size == 0 || *idx == 0)
|
|
||||||
return ("");
|
|
||||||
(*idx)--;
|
|
||||||
if (*idx == 0)
|
|
||||||
return ("");
|
|
||||||
return (ARRAY_ITEM(&status_prompt_history, size - *idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add line to the history. */
|
/* Add line to the history. */
|
||||||
void
|
void
|
||||||
status_prompt_add_history(const char *line)
|
status_prompt_add_history(struct client *c)
|
||||||
{
|
{
|
||||||
u_int size;
|
if (ARRAY_LENGTH(&c->prompt_hdata) > 0 &&
|
||||||
|
strcmp(ARRAY_LAST(&c->prompt_hdata), c->prompt_buffer) == 0)
|
||||||
size = ARRAY_LENGTH(&status_prompt_history);
|
|
||||||
if (size > 0 && strcmp(ARRAY_LAST(&status_prompt_history), line) == 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (size == PROMPT_HISTORY) {
|
if (ARRAY_LENGTH(&c->prompt_hdata) == PROMPT_HISTORY) {
|
||||||
xfree(ARRAY_FIRST(&status_prompt_history));
|
xfree(ARRAY_FIRST(&c->prompt_hdata));
|
||||||
ARRAY_REMOVE(&status_prompt_history, 0);
|
ARRAY_REMOVE(&c->prompt_hdata, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ARRAY_ADD(&status_prompt_history, xstrdup(line));
|
ARRAY_ADD(&c->prompt_hdata, xstrdup(c->prompt_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complete word. */
|
/* Complete word. */
|
||||||
|
|||||||
498
tmux.1
498
tmux.1
@@ -1,4 +1,4 @@
|
|||||||
.\" $Id: tmux.1,v 1.280 2010-12-27 21:17:25 tcunha Exp $
|
.\" $Id: tmux.1,v 1.237 2010-03-08 15:02:07 tcunha Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
.\"
|
.\"
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
.\" 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.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: December 10 2010 $
|
.Dd $Mdocdate: March 2 2010 $
|
||||||
.Dt TMUX 1
|
.Dt TMUX 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm tmux
|
.Nm tmux
|
||||||
.Bk -words
|
.Bk -words
|
||||||
.Op Fl 28lquvV
|
.Op Fl 28lquv
|
||||||
.Op Fl c Ar shell-command
|
.Op Fl c Ar shell-command
|
||||||
.Op Fl f Ar file
|
.Op Fl f Ar file
|
||||||
.Op Fl L Ar socket-name
|
.Op Fl L Ar socket-name
|
||||||
@@ -131,6 +131,10 @@ commands which are executed in sequence when the server is first started.
|
|||||||
If a command in the configuration file fails,
|
If a command in the configuration file fails,
|
||||||
.Nm
|
.Nm
|
||||||
will report an error and exit without executing further commands.
|
will report an error and exit without executing further commands.
|
||||||
|
.It Fl l
|
||||||
|
Behave as a login shell.
|
||||||
|
This flag currently has no effect and is for compatibility with other shells
|
||||||
|
when using tmux as a login shell.
|
||||||
.It Fl L Ar socket-name
|
.It Fl L Ar socket-name
|
||||||
.Nm
|
.Nm
|
||||||
stores the server socket in a directory under
|
stores the server socket in a directory under
|
||||||
@@ -151,10 +155,6 @@ If the socket is accidentally removed, the
|
|||||||
signal may be sent to the
|
signal may be sent to the
|
||||||
.Nm
|
.Nm
|
||||||
server process to recreate it.
|
server process to recreate it.
|
||||||
.It Fl l
|
|
||||||
Behave as a login shell.
|
|
||||||
This flag currently has no effect and is for compatibility with other shells
|
|
||||||
when using tmux as a login shell.
|
|
||||||
.It Fl q
|
.It Fl q
|
||||||
Set the
|
Set the
|
||||||
.Ic quiet
|
.Ic quiet
|
||||||
@@ -198,10 +198,6 @@ and
|
|||||||
files in the current directory, where
|
files in the current directory, where
|
||||||
.Em PID
|
.Em PID
|
||||||
is the PID of the server or client process.
|
is the PID of the server or client process.
|
||||||
.It Fl V
|
|
||||||
Report the
|
|
||||||
.Nm
|
|
||||||
version.
|
|
||||||
.It Ar command Op Ar flags
|
.It Ar command Op Ar flags
|
||||||
This specifies one of a set of commands used to control
|
This specifies one of a set of commands used to control
|
||||||
.Nm ,
|
.Nm ,
|
||||||
@@ -217,114 +213,32 @@ prefix key,
|
|||||||
.Ql C-b
|
.Ql C-b
|
||||||
(Ctrl-b) by default, followed by a command key.
|
(Ctrl-b) by default, followed by a command key.
|
||||||
.Pp
|
.Pp
|
||||||
The default command key bindings are:
|
Some of the default key bindings are:
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -tag -width "XXXXXXXXXX" -offset indent -compact
|
.Bl -tag -width Ds -offset indent -compact
|
||||||
.It C-b
|
|
||||||
Send the prefix key (C-b) through to the application.
|
|
||||||
.It C-o
|
|
||||||
Rotate the panes in the current window forwards.
|
|
||||||
.It C-z
|
|
||||||
Suspend the
|
|
||||||
.Nm
|
|
||||||
client.
|
|
||||||
.It !
|
|
||||||
Break the current pane out of the window.
|
|
||||||
.It \&"
|
|
||||||
Split the current pane into two, top and bottom.
|
|
||||||
.It #
|
|
||||||
List all paste buffers.
|
|
||||||
.It %
|
|
||||||
Split the current pane into two, left and right.
|
|
||||||
.It &
|
|
||||||
Kill the current window.
|
|
||||||
.It '
|
|
||||||
Prompt for a window index to select.
|
|
||||||
.It ,
|
|
||||||
Rename the current window.
|
|
||||||
.It -
|
|
||||||
Delete the most recently copied buffer of text.
|
|
||||||
.It .
|
|
||||||
Prompt for an index to move the current window.
|
|
||||||
.It 0 to 9
|
|
||||||
Select windows 0 to 9.
|
|
||||||
.It :
|
|
||||||
Enter the
|
|
||||||
.Nm
|
|
||||||
command prompt.
|
|
||||||
.It ;
|
|
||||||
Move to the previously active pane.
|
|
||||||
.It =
|
|
||||||
Choose which buffer to paste interactively from a list.
|
|
||||||
.It \&?
|
|
||||||
List all key bindings.
|
|
||||||
.It D
|
|
||||||
Choose a client to detach.
|
|
||||||
.It \&[
|
|
||||||
Enter copy mode to copy text or view the history.
|
|
||||||
.It \&]
|
|
||||||
Paste the most recently copied buffer of text.
|
|
||||||
.It c
|
.It c
|
||||||
Create a new window.
|
Create a new window.
|
||||||
.It d
|
.It d
|
||||||
Detach the current client.
|
Detach the current client.
|
||||||
.It f
|
|
||||||
Prompt to search for text in open windows.
|
|
||||||
.It i
|
|
||||||
Display some information about the current window.
|
|
||||||
.It l
|
.It l
|
||||||
Move to the previously selected window.
|
Move to the previously selected window.
|
||||||
.It n
|
.It n
|
||||||
Change to the next window.
|
Change to the next window.
|
||||||
.It o
|
|
||||||
Select the next pane in the current window.
|
|
||||||
.It p
|
.It p
|
||||||
Change to the previous window.
|
Change to the previous window.
|
||||||
.It q
|
.It &
|
||||||
Briefly display pane indexes.
|
Kill the current window.
|
||||||
.It r
|
.It ,
|
||||||
Force redraw of the attached client.
|
Rename the current window.
|
||||||
.It s
|
.It \&?
|
||||||
Select a new session for the attached client interactively.
|
List all key bindings.
|
||||||
.It L
|
|
||||||
Switch the attached client back to the last session.
|
|
||||||
.It t
|
|
||||||
Show the time.
|
|
||||||
.It w
|
|
||||||
Choose the current window interactively.
|
|
||||||
.It x
|
|
||||||
Kill the current pane.
|
|
||||||
.It {
|
|
||||||
Swap the current pane with the previous pane.
|
|
||||||
.It }
|
|
||||||
Swap the current pane with the next pane.
|
|
||||||
.It ~
|
|
||||||
Show previous messages from
|
|
||||||
.Nm ,
|
|
||||||
if any.
|
|
||||||
.It Page Up
|
|
||||||
Enter copy mode and scroll one page up.
|
|
||||||
.It Up, Down
|
|
||||||
.It Left, Right
|
|
||||||
Change to the pane above, below, to the left, or to the right of the current
|
|
||||||
pane.
|
|
||||||
.It M-1 to M-5
|
|
||||||
Arrange panes in one of the five preset layouts: even-horizontal,
|
|
||||||
even-vertical, main-horizontal, main-vertical, or tiled.
|
|
||||||
.It M-n
|
|
||||||
Move to the next window with a bell or activity marker.
|
|
||||||
.It M-o
|
|
||||||
Rotate the panes in the current window backwards.
|
|
||||||
.It M-p
|
|
||||||
Move to the previous window with a bell or activity marker.
|
|
||||||
.It C-Up, C-Down
|
|
||||||
.It C-Left, C-Right
|
|
||||||
Resize the current pane in steps of one cell.
|
|
||||||
.It M-Up, M-Down
|
|
||||||
.It M-Left, M-Right
|
|
||||||
Resize the current pane in steps of five cells.
|
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
|
A complete list may be obtained with the
|
||||||
|
.Ic list-keys
|
||||||
|
command (bound to
|
||||||
|
.Ql \&?
|
||||||
|
by default).
|
||||||
Key bindings may be changed with the
|
Key bindings may be changed with the
|
||||||
.Ic bind-key
|
.Ic bind-key
|
||||||
and
|
and
|
||||||
@@ -422,11 +336,6 @@ If neither a colon nor period appears,
|
|||||||
first attempts to use the argument as a pane index; if that fails, it is looked
|
first attempts to use the argument as a pane index; if that fails, it is looked
|
||||||
up as for
|
up as for
|
||||||
.Ar target-window .
|
.Ar target-window .
|
||||||
A
|
|
||||||
.Ql +
|
|
||||||
or
|
|
||||||
.Ql -
|
|
||||||
indicate the next or previous pane index, respectively.
|
|
||||||
One of the strings
|
One of the strings
|
||||||
.Em top ,
|
.Em top ,
|
||||||
.Em bottom ,
|
.Em bottom ,
|
||||||
@@ -438,18 +347,6 @@ One of the strings
|
|||||||
.Em bottom-right
|
.Em bottom-right
|
||||||
may be used instead of a pane index.
|
may be used instead of a pane index.
|
||||||
.Pp
|
.Pp
|
||||||
The special characters
|
|
||||||
.Ql +
|
|
||||||
and
|
|
||||||
.Ql -
|
|
||||||
may be followed by an offset, for example:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
select-window -t:+2
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
When dealing with a session that doesn't contain sequential window indexes,
|
|
||||||
they will be correctly skipped.
|
|
||||||
.Pp
|
|
||||||
.Ar shell-command
|
.Ar shell-command
|
||||||
arguments are
|
arguments are
|
||||||
.Xr sh 1
|
.Xr sh 1
|
||||||
@@ -471,6 +368,7 @@ bind-key F1 set-window-option force-width 81
|
|||||||
.Pp
|
.Pp
|
||||||
Or if using
|
Or if using
|
||||||
.Xr sh 1 :
|
.Xr sh 1 :
|
||||||
|
.Pp
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
$ tmux bind-key F1 set-window-option force-width 81
|
$ tmux bind-key F1 set-window-option force-width 81
|
||||||
.Ed
|
.Ed
|
||||||
@@ -498,12 +396,13 @@ new-window ; split-window -d
|
|||||||
.Pp
|
.Pp
|
||||||
Or from
|
Or from
|
||||||
.Xr sh 1 :
|
.Xr sh 1 :
|
||||||
|
.Pp
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
$ tmux kill-window -t :1
|
$ tmux kill-window -t :1
|
||||||
|
|
||||||
$ tmux new-window \e; split-window -d
|
$ tmux new-window \\; split-window -d
|
||||||
|
|
||||||
$ tmux new-session -d 'vi /etc/passwd' \e; split-window -d \e; attach
|
$ tmux new-session -d 'vi /etc/passwd' \\; split-window -d \\; attach
|
||||||
.Ed
|
.Ed
|
||||||
.Sh CLIENTS AND SESSIONS
|
.Sh CLIENTS AND SESSIONS
|
||||||
The
|
The
|
||||||
@@ -515,7 +414,7 @@ when they are created with the
|
|||||||
command, or later with the
|
command, or later with the
|
||||||
.Ic attach-session
|
.Ic attach-session
|
||||||
command.
|
command.
|
||||||
Each session has one or more windows
|
Each session has one of more windows
|
||||||
.Em linked
|
.Em linked
|
||||||
into it.
|
into it.
|
||||||
Windows may be linked to multiple sessions and are made up of one or
|
Windows may be linked to multiple sessions and are made up of one or
|
||||||
@@ -576,15 +475,17 @@ List the syntax of all commands supported by
|
|||||||
.It Ic list-sessions
|
.It Ic list-sessions
|
||||||
.D1 (alias: Ic ls )
|
.D1 (alias: Ic ls )
|
||||||
List all sessions managed by the server.
|
List all sessions managed by the server.
|
||||||
.It Ic lock-client Op Fl t Ar target-client
|
.It Xo Ic lock-client
|
||||||
.D1 (alias: Ic lockc )
|
.Op Fl t Ar target-client
|
||||||
|
.Xc
|
||||||
Lock
|
Lock
|
||||||
.Ar target-client ,
|
.Ar target-client ,
|
||||||
see the
|
see the
|
||||||
.Ic lock-server
|
.Ic lock-server
|
||||||
command.
|
command.
|
||||||
.It Ic lock-session Op Fl t Ar target-session
|
.It Xo Ic lock-session
|
||||||
.D1 (alias: Ic locks )
|
.Op Fl t Ar target-session
|
||||||
|
.Xc
|
||||||
Lock all clients attached to
|
Lock all clients attached to
|
||||||
.Ar target-session .
|
.Ar target-session .
|
||||||
.It Xo Ic new-session
|
.It Xo Ic new-session
|
||||||
@@ -668,7 +569,6 @@ Suspend a client by sending
|
|||||||
.Dv SIGTSTP
|
.Dv SIGTSTP
|
||||||
(tty stop).
|
(tty stop).
|
||||||
.It Xo Ic switch-client
|
.It Xo Ic switch-client
|
||||||
.Op Fl lnp
|
|
||||||
.Op Fl c Ar target-client
|
.Op Fl c Ar target-client
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Xc
|
.Xc
|
||||||
@@ -677,21 +577,20 @@ Switch the current session for client
|
|||||||
.Ar target-client
|
.Ar target-client
|
||||||
to
|
to
|
||||||
.Ar target-session .
|
.Ar target-session .
|
||||||
If
|
|
||||||
.Fl l ,
|
|
||||||
.Fl n
|
|
||||||
or
|
|
||||||
.Fl p
|
|
||||||
is used, the client is moved to the last, next or previous session
|
|
||||||
respectively.
|
|
||||||
.El
|
.El
|
||||||
.Sh WINDOWS AND PANES
|
.Sh WINDOWS AND PANES
|
||||||
A
|
A
|
||||||
.Nm
|
.Nm
|
||||||
window may be in one of several modes.
|
window may be in one of several modes.
|
||||||
The default permits direct access to the terminal attached to the window.
|
The default permits direct access to the terminal attached to the window.
|
||||||
The other is copy mode, which permits a section of a window or its
|
The others are:
|
||||||
history to be copied to a
|
.Bl -tag -width Ds
|
||||||
|
.It Em output mode
|
||||||
|
This is entered when a command which produces output, such as
|
||||||
|
.Ic list-keys ,
|
||||||
|
is executed from a key binding.
|
||||||
|
.It Em copy mode
|
||||||
|
This permits a section of a window or its history to be copied to a
|
||||||
.Em paste buffer
|
.Em paste buffer
|
||||||
for later insertion into another window.
|
for later insertion into another window.
|
||||||
This mode is entered with the
|
This mode is entered with the
|
||||||
@@ -699,16 +598,14 @@ This mode is entered with the
|
|||||||
command, bound to
|
command, bound to
|
||||||
.Ql \&[
|
.Ql \&[
|
||||||
by default.
|
by default.
|
||||||
It is also entered when a command that produces output, such as
|
.El
|
||||||
.Ic list-keys ,
|
|
||||||
is executed from a key binding.
|
|
||||||
.Pp
|
.Pp
|
||||||
The keys available depend on whether emacs or vi mode is selected
|
The keys available depend on whether emacs or vi mode is selected
|
||||||
(see the
|
(see the
|
||||||
.Ic mode-keys
|
.Ic mode-keys
|
||||||
option).
|
option).
|
||||||
The following keys are supported as appropriate for the mode:
|
The following keys are supported as appropriate for the mode:
|
||||||
.Bl -column "FunctionXXXXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent
|
.Bl -column "FunctionXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent
|
||||||
.It Sy "Function" Ta Sy "vi" Ta Sy "emacs"
|
.It Sy "Function" Ta Sy "vi" Ta Sy "emacs"
|
||||||
.It Li "Back to indentation" Ta "^" Ta "M-m"
|
.It Li "Back to indentation" Ta "^" Ta "M-m"
|
||||||
.It Li "Bottom of history" Ta "G" Ta "M-<"
|
.It Li "Bottom of history" Ta "G" Ta "M-<"
|
||||||
@@ -727,10 +624,6 @@ The following keys are supported as appropriate for the mode:
|
|||||||
.It Li "Go to line" Ta ":" Ta "g"
|
.It Li "Go to line" Ta ":" Ta "g"
|
||||||
.It Li "Half page down" Ta "C-d" Ta "M-Down"
|
.It Li "Half page down" Ta "C-d" Ta "M-Down"
|
||||||
.It Li "Half page up" Ta "C-u" Ta "M-Up"
|
.It Li "Half page up" Ta "C-u" Ta "M-Up"
|
||||||
.It Li "Jump forward" Ta "f" Ta "f"
|
|
||||||
.It Li "Jump backward" Ta "F" Ta "F"
|
|
||||||
.It Li "Jump again" Ta ";" Ta ";"
|
|
||||||
.It Li "Jump again in reverse" Ta "," Ta ","
|
|
||||||
.It Li "Next page" Ta "C-f" Ta "Page down"
|
.It Li "Next page" Ta "C-f" Ta "Page down"
|
||||||
.It Li "Next space" Ta "W" Ta ""
|
.It Li "Next space" Ta "W" Ta ""
|
||||||
.It Li "Next space, end of word" Ta "E" Ta ""
|
.It Li "Next space, end of word" Ta "E" Ta ""
|
||||||
@@ -768,18 +661,6 @@ next word and previous word to the start of the previous word.
|
|||||||
The three next and previous space keys work similarly but use a space alone as
|
The three next and previous space keys work similarly but use a space alone as
|
||||||
the word separator.
|
the word separator.
|
||||||
.Pp
|
.Pp
|
||||||
The jump commands enable quick movement within a line.
|
|
||||||
For instance, typing
|
|
||||||
.Ql f
|
|
||||||
followed by
|
|
||||||
.Ql /
|
|
||||||
will move the cursor to the next
|
|
||||||
.Ql /
|
|
||||||
character on the current line.
|
|
||||||
A
|
|
||||||
.Ql \&;
|
|
||||||
will then jump to the next occurrence.
|
|
||||||
.Pp
|
|
||||||
Commands in copy mode may be prefaced by an optional repeat count.
|
Commands in copy mode may be prefaced by an optional repeat count.
|
||||||
With vi key bindings, a prefix is entered using the number keys; with
|
With vi key bindings, a prefix is entered using the number keys; with
|
||||||
emacs, the Alt (meta) key and a number begins prefix entry.
|
emacs, the Alt (meta) key and a number begins prefix entry.
|
||||||
@@ -799,7 +680,7 @@ and
|
|||||||
.Em emacs-choice
|
.Em emacs-choice
|
||||||
for keys used when choosing from lists (such as produced by the
|
for keys used when choosing from lists (such as produced by the
|
||||||
.Ic choose-window
|
.Ic choose-window
|
||||||
command); and
|
command) or in output mode; and
|
||||||
.Em vi-copy
|
.Em vi-copy
|
||||||
and
|
and
|
||||||
.Em emacs-copy
|
.Em emacs-copy
|
||||||
@@ -814,9 +695,7 @@ and
|
|||||||
The paste buffer key pastes the first line from the top paste buffer on the
|
The paste buffer key pastes the first line from the top paste buffer on the
|
||||||
stack.
|
stack.
|
||||||
.Pp
|
.Pp
|
||||||
The synopsis for the
|
The mode commands are as follows:
|
||||||
.Ic copy-mode
|
|
||||||
command is:
|
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Xo Ic copy-mode
|
.It Xo Ic copy-mode
|
||||||
.Op Fl u
|
.Op Fl u
|
||||||
@@ -848,8 +727,10 @@ command (bound to
|
|||||||
and
|
and
|
||||||
.Ql C-right
|
.Ql C-right
|
||||||
by default), the current pane may be changed with the
|
by default), the current pane may be changed with the
|
||||||
.Ic select-pane
|
.Ic up-pane
|
||||||
command and the
|
and
|
||||||
|
.Ic down-pane
|
||||||
|
commands and the
|
||||||
.Ic rotate-window
|
.Ic rotate-window
|
||||||
and
|
and
|
||||||
.Ic swap-pane
|
.Ic swap-pane
|
||||||
@@ -888,30 +769,8 @@ bottom along the right.
|
|||||||
See the
|
See the
|
||||||
.Em main-pane-width
|
.Em main-pane-width
|
||||||
window option.
|
window option.
|
||||||
.It Ic tiled
|
|
||||||
Panes are spread out as evenly as possible over the window in both rows and
|
|
||||||
columns.
|
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
In addition,
|
|
||||||
.Ic select-layout
|
|
||||||
may be used to apply a previously used layout - the
|
|
||||||
.Ic list-windows
|
|
||||||
command displays the layout of each window in a form suitable for use with
|
|
||||||
.Ic select-layout .
|
|
||||||
For example:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
$ tmux list-windows
|
|
||||||
0: ksh [159x48]
|
|
||||||
layout: bb62,159x48,0,0{79x48,0,0,79x48,80,0}
|
|
||||||
$ tmux select-layout bb62,159x48,0,0{79x48,0,0,79x48,80,0}
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
.Nm
|
|
||||||
automatically adjusts the size of the layout for the current window size.
|
|
||||||
Note that a layout cannot be applied to a window with more panes than that
|
|
||||||
from which the layout was originally defined.
|
|
||||||
.Pp
|
|
||||||
Commands related to windows and panes are as follows:
|
Commands related to windows and panes are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Xo Ic break-pane
|
.It Xo Ic break-pane
|
||||||
@@ -1000,6 +859,9 @@ While the indicator is on screen, a pane may be selected with the
|
|||||||
to
|
to
|
||||||
.Ql 9
|
.Ql 9
|
||||||
keys.
|
keys.
|
||||||
|
.It Ic down-pane Op Fl t Ar target-pane
|
||||||
|
.D1 (alias: Ic downp )
|
||||||
|
Change the active pane to the next pane (higher index).
|
||||||
.It Xo Ic find-window
|
.It Xo Ic find-window
|
||||||
.Op Fl t Ar target-window
|
.Op Fl t Ar target-window
|
||||||
.Ar match-string
|
.Ar match-string
|
||||||
@@ -1048,9 +910,6 @@ option kills all but the pane given with
|
|||||||
Kill the current window or the window at
|
Kill the current window or the window at
|
||||||
.Ar target-window ,
|
.Ar target-window ,
|
||||||
removing it from any sessions to which it is linked.
|
removing it from any sessions to which it is linked.
|
||||||
.It Ic last-pane Op Fl t Ar target-window
|
|
||||||
.D1 (alias: Ic lastp )
|
|
||||||
Select the last (previously selected) pane.
|
|
||||||
.It Ic last-window Op Fl t Ar target-session
|
.It Ic last-window Op Fl t Ar target-session
|
||||||
.D1 (alias: Ic last )
|
.D1 (alias: Ic last )
|
||||||
Select the last (previously selected) window.
|
Select the last (previously selected) window.
|
||||||
@@ -1089,7 +948,7 @@ List the panes in the current window or in
|
|||||||
List windows in the current session or in
|
List windows in the current session or in
|
||||||
.Ar target-session .
|
.Ar target-session .
|
||||||
.It Xo Ic move-window
|
.It Xo Ic move-window
|
||||||
.Op Fl dk
|
.Op Fl d
|
||||||
.Op Fl s Ar src-window
|
.Op Fl s Ar src-window
|
||||||
.Op Fl t Ar dst-window
|
.Op Fl t Ar dst-window
|
||||||
.Xc
|
.Xc
|
||||||
@@ -1101,22 +960,13 @@ except the window at
|
|||||||
is moved to
|
is moved to
|
||||||
.Ar dst-window .
|
.Ar dst-window .
|
||||||
.It Xo Ic new-window
|
.It Xo Ic new-window
|
||||||
.Op Fl adk
|
.Op Fl dk
|
||||||
.Op Fl n Ar window-name
|
.Op Fl n Ar window-name
|
||||||
.Op Fl t Ar target-window
|
.Op Fl t Ar target-window
|
||||||
.Op Ar shell-command
|
.Op Ar shell-command
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic neww )
|
.D1 (alias: Ic neww )
|
||||||
Create a new window.
|
Create a new window.
|
||||||
With
|
|
||||||
.Fl a ,
|
|
||||||
the new window is inserted at the next index up from the specified
|
|
||||||
.Ar target-window ,
|
|
||||||
moving windows up if necessary,
|
|
||||||
otherwise
|
|
||||||
.Ar target-window
|
|
||||||
is the new window location.
|
|
||||||
.Pp
|
|
||||||
If
|
If
|
||||||
.Fl d
|
.Fl d
|
||||||
is given, the session does not make the new window the current window.
|
is given, the session does not make the new window the current window.
|
||||||
@@ -1174,11 +1024,6 @@ A pane may only be piped to one command at a time, any existing pipe is
|
|||||||
closed before
|
closed before
|
||||||
.Ar shell-command
|
.Ar shell-command
|
||||||
is executed.
|
is executed.
|
||||||
The
|
|
||||||
.Ar shell-command
|
|
||||||
string may contain the special character sequences supported by the
|
|
||||||
.Ic status-left
|
|
||||||
command.
|
|
||||||
If no
|
If no
|
||||||
.Ar shell-command
|
.Ar shell-command
|
||||||
is given, the current pipe (if any) is closed.
|
is given, the current pipe (if any) is closed.
|
||||||
@@ -1188,13 +1033,8 @@ The
|
|||||||
option only opens a new pipe if no previous pipe exists, allowing a pipe to
|
option only opens a new pipe if no previous pipe exists, allowing a pipe to
|
||||||
be toggled with a single key, for example:
|
be toggled with a single key, for example:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
bind-key C-p pipe-pane -o 'cat >>~/output.#I-#P'
|
bind-key C-p pipe-pane -o 'cat >>~/output'
|
||||||
.Ed
|
.Ed
|
||||||
.It Xo Ic previous-layout
|
|
||||||
.Op Fl t Ar target-window
|
|
||||||
.Xc
|
|
||||||
.D1 (alias: Ic prevl )
|
|
||||||
Move to the previous layout in the session.
|
|
||||||
.It Xo Ic previous-window
|
.It Xo Ic previous-window
|
||||||
.Op Fl a
|
.Op Fl a
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
@@ -1258,28 +1098,17 @@ or downward (numerically higher).
|
|||||||
.Op Fl t Ar target-window
|
.Op Fl t Ar target-window
|
||||||
.Op Ar layout-name
|
.Op Ar layout-name
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic selectl )
|
.D1 (alias: selectl )
|
||||||
Choose a specific layout for a window.
|
Choose a specific layout for a window.
|
||||||
If
|
If
|
||||||
.Ar layout-name
|
.Ar layout-name
|
||||||
is not given, the last preset layout used (if any) is reapplied.
|
is not given, the last layout used (if any) is reapplied.
|
||||||
.It Xo Ic select-pane
|
.It Ic select-pane Op Fl t Ar target-pane
|
||||||
.Op Fl DLRU
|
|
||||||
.Op Fl t Ar target-pane
|
|
||||||
.Xc
|
|
||||||
.D1 (alias: Ic selectp )
|
.D1 (alias: Ic selectp )
|
||||||
Make pane
|
Make pane
|
||||||
.Ar target-pane
|
.Ar target-pane
|
||||||
the active pane in window
|
the active pane in window
|
||||||
.Ar target-window .
|
.Ar target-window .
|
||||||
If one of
|
|
||||||
.Fl D ,
|
|
||||||
.Fl L ,
|
|
||||||
.Fl R ,
|
|
||||||
or
|
|
||||||
.Fl U
|
|
||||||
is used, respectively the pane below, to the left, to the right, or above the
|
|
||||||
target pane is used.
|
|
||||||
.It Ic select-window Op Fl t Ar target-window
|
.It Ic select-window Op Fl t Ar target-window
|
||||||
.D1 (alias: Ic selectw )
|
.D1 (alias: Ic selectw )
|
||||||
Select the window at
|
Select the window at
|
||||||
@@ -1292,7 +1121,7 @@ Select the window at
|
|||||||
.Op Fl t Ar target-pane
|
.Op Fl t Ar target-pane
|
||||||
.Op Ar shell-command
|
.Op Ar shell-command
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic splitw )
|
.D1 (alias: splitw )
|
||||||
Create a new pane by splitting
|
Create a new pane by splitting
|
||||||
.Ar target-pane :
|
.Ar target-pane :
|
||||||
.Fl h
|
.Fl h
|
||||||
@@ -1355,6 +1184,9 @@ if
|
|||||||
.Fl k
|
.Fl k
|
||||||
is specified and the window is linked to only one session, it is unlinked and
|
is specified and the window is linked to only one session, it is unlinked and
|
||||||
destroyed.
|
destroyed.
|
||||||
|
.It Ic up-pane Op Fl t Ar target-pane
|
||||||
|
.D1 (alias: Ic upp )
|
||||||
|
Change the active pane to the previous pane (lower index).
|
||||||
.El
|
.El
|
||||||
.Sh KEY BINDINGS
|
.Sh KEY BINDINGS
|
||||||
.Nm
|
.Nm
|
||||||
@@ -1401,7 +1233,7 @@ or
|
|||||||
keys, quotation marks are necessary, for example:
|
keys, quotation marks are necessary, for example:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
bind-key '"' split-window
|
bind-key '"' split-window
|
||||||
bind-key "'" new-window
|
bind-key "'" select-prompt
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Commands related to key bindings are as follows:
|
Commands related to key bindings are as follows:
|
||||||
@@ -1488,7 +1320,7 @@ All arguments are sent sequentially from first to last.
|
|||||||
Send the prefix key to a window as if it was pressed.
|
Send the prefix key to a window as if it was pressed.
|
||||||
If multiple prefix keys are configured, only the first is sent.
|
If multiple prefix keys are configured, only the first is sent.
|
||||||
.It Xo Ic unbind-key
|
.It Xo Ic unbind-key
|
||||||
.Op Fl acn
|
.Op Fl cn
|
||||||
.Op Fl t Ar key-table
|
.Op Fl t Ar key-table
|
||||||
.Ar key
|
.Ar key
|
||||||
.Xc
|
.Xc
|
||||||
@@ -1502,9 +1334,6 @@ the primary key bindings are modified; in this case, if
|
|||||||
is specified, the command bound to
|
is specified, the command bound to
|
||||||
.Ar key
|
.Ar key
|
||||||
without a prefix (if any) is removed.
|
without a prefix (if any) is removed.
|
||||||
If
|
|
||||||
.Fl a
|
|
||||||
is present, all key bindings are removed.
|
|
||||||
.Pp
|
.Pp
|
||||||
If
|
If
|
||||||
.Fl t
|
.Fl t
|
||||||
@@ -1604,9 +1433,6 @@ Set the time in milliseconds for which
|
|||||||
waits after an escape is input to determine if it is part of a function or meta
|
waits after an escape is input to determine if it is part of a function or meta
|
||||||
key sequences.
|
key sequences.
|
||||||
The default is 500 milliseconds.
|
The default is 500 milliseconds.
|
||||||
.It Ic exit-unattached
|
|
||||||
If enabled, the server will exit when there are no attached clients, rather
|
|
||||||
than when there are no attached sessions.
|
|
||||||
.It Ic quiet
|
.It Ic quiet
|
||||||
Enable or disable the display of various informational messages (see also the
|
Enable or disable the display of various informational messages (see also the
|
||||||
.Fl q
|
.Fl q
|
||||||
@@ -1646,11 +1472,6 @@ The default is an empty string, which instructs
|
|||||||
to create a login shell using the value of the
|
to create a login shell using the value of the
|
||||||
.Ic default-shell
|
.Ic default-shell
|
||||||
option.
|
option.
|
||||||
.It Ic default-path Ar path
|
|
||||||
Set the default working directory for processes created from keys, or
|
|
||||||
interactively from the prompt.
|
|
||||||
The default is empty, which means to use the working directory of the shell
|
|
||||||
from which the server was started if it is available or the user's home if not.
|
|
||||||
.It Ic default-shell Ar path
|
.It Ic default-shell Ar path
|
||||||
Specify the default shell.
|
Specify the default shell.
|
||||||
This is used as the login shell for new windows when the
|
This is used as the login shell for new windows when the
|
||||||
@@ -1667,6 +1488,10 @@ or
|
|||||||
This option should be configured when
|
This option should be configured when
|
||||||
.Nm
|
.Nm
|
||||||
is used as a login shell.
|
is used as a login shell.
|
||||||
|
.It Ic default-path Ar path
|
||||||
|
Set the default working directory for processes created from keys, or
|
||||||
|
interactively from the prompt.
|
||||||
|
The default is the current working directory when the server is started.
|
||||||
.It Ic default-terminal Ar terminal
|
.It Ic default-terminal Ar terminal
|
||||||
Set the default terminal for new windows created in this session - the
|
Set the default terminal for new windows created in this session - the
|
||||||
default value of the
|
default value of the
|
||||||
@@ -1679,14 +1504,6 @@ to work correctly, this
|
|||||||
be set to
|
be set to
|
||||||
.Ql screen
|
.Ql screen
|
||||||
or a derivative of it.
|
or a derivative of it.
|
||||||
.It Ic destroy-unattached
|
|
||||||
If enabled and the session is no longer attached to any clients, it is
|
|
||||||
destroyed.
|
|
||||||
.It Ic detach-on-destroy
|
|
||||||
If on (the default), the client is detached when the session it is attached to
|
|
||||||
is destroyed.
|
|
||||||
If off, the client is switched to the most recently active of the remaining
|
|
||||||
sessions.
|
|
||||||
.It Ic display-panes-active-colour Ar colour
|
.It Ic display-panes-active-colour Ar colour
|
||||||
Set the colour used by the
|
Set the colour used by the
|
||||||
.Ic display-panes
|
.Ic display-panes
|
||||||
@@ -1740,7 +1557,7 @@ This has no effect as a session option; it must be set as a global option.
|
|||||||
Set status line message attributes, where
|
Set status line message attributes, where
|
||||||
.Ar attributes
|
.Ar attributes
|
||||||
is either
|
is either
|
||||||
.Ic none
|
.Ic default
|
||||||
or a comma-delimited list of one or more of:
|
or a comma-delimited list of one or more of:
|
||||||
.Ic bright
|
.Ic bright
|
||||||
(or
|
(or
|
||||||
@@ -1783,12 +1600,12 @@ If on,
|
|||||||
captures the mouse and when a window is split into multiple panes the mouse may
|
captures the mouse and when a window is split into multiple panes the mouse may
|
||||||
be used to select the current pane.
|
be used to select the current pane.
|
||||||
The mouse click is also passed through to the application as normal.
|
The mouse click is also passed through to the application as normal.
|
||||||
.It Ic pane-active-border-bg Ar colour
|
|
||||||
.It Ic pane-active-border-fg Ar colour
|
|
||||||
Set the pane border colour for the currently active pane.
|
|
||||||
.It Ic pane-border-bg Ar colour
|
|
||||||
.It Ic pane-border-fg Ar colour
|
.It Ic pane-border-fg Ar colour
|
||||||
|
.It Ic pane-border-bg Ar colour
|
||||||
Set the pane border colour for panes aside from the active pane.
|
Set the pane border colour for panes aside from the active pane.
|
||||||
|
.It Ic pane-active-border-fg Ar colour
|
||||||
|
.It Ic pane-active-border-bg Ar colour
|
||||||
|
Set the pane border colour for the currently active pane.
|
||||||
.It Ic prefix Ar keys
|
.It Ic prefix Ar keys
|
||||||
Set the keys accepted as a prefix key.
|
Set the keys accepted as a prefix key.
|
||||||
.Ar keys
|
.Ar keys
|
||||||
@@ -1861,12 +1678,7 @@ or right justified.
|
|||||||
.Xc
|
.Xc
|
||||||
Use vi or emacs-style
|
Use vi or emacs-style
|
||||||
key bindings in the status line, for example at the command prompt.
|
key bindings in the status line, for example at the command prompt.
|
||||||
The default is emacs, unless the
|
Defaults to emacs.
|
||||||
.Ev VISUAL
|
|
||||||
or
|
|
||||||
.Ev EDITOR
|
|
||||||
environment variables are set and contain the string
|
|
||||||
.Ql vi .
|
|
||||||
.It Ic status-left Ar string
|
.It Ic status-left Ar string
|
||||||
Display
|
Display
|
||||||
.Ar string
|
.Ar string
|
||||||
@@ -1900,19 +1712,6 @@ the
|
|||||||
.Ic status-interval
|
.Ic status-interval
|
||||||
option: if the status line is redrawn in the meantime, the previous result is
|
option: if the status line is redrawn in the meantime, the previous result is
|
||||||
used.
|
used.
|
||||||
Shell commands are executed with the
|
|
||||||
.Nm
|
|
||||||
global environment set (see the
|
|
||||||
.Sx ENVIRONMENT
|
|
||||||
section).
|
|
||||||
.Pp
|
|
||||||
The window title (#T) is the title set by the program running within the window
|
|
||||||
using the OSC title setting sequence, for example:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
$ printf '\e033]2;My Title\e033\e\e'
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
When a window is first created, its title is the hostname.
|
|
||||||
.Pp
|
.Pp
|
||||||
#[attributes] allows a comma-separated list of attributes to be specified,
|
#[attributes] allows a comma-separated list of attributes to be specified,
|
||||||
these may be
|
these may be
|
||||||
@@ -1943,10 +1742,10 @@ is not interpreted, to enable UTF-8, use the
|
|||||||
option.
|
option.
|
||||||
.It Ic status-left-attr Ar attributes
|
.It Ic status-left-attr Ar attributes
|
||||||
Set the attribute of the left part of the status line.
|
Set the attribute of the left part of the status line.
|
||||||
.It Ic status-left-bg Ar colour
|
|
||||||
Set the background colour of the left part of the status line.
|
|
||||||
.It Ic status-left-fg Ar colour
|
.It Ic status-left-fg Ar colour
|
||||||
Set the foreground colour of the left part of the status line.
|
Set the foreground colour of the left part of the status line.
|
||||||
|
.It Ic status-left-bg Ar colour
|
||||||
|
Set the background colour of the left part of the status line.
|
||||||
.It Ic status-left-length Ar length
|
.It Ic status-left-length Ar length
|
||||||
Set the maximum
|
Set the maximum
|
||||||
.Ar length
|
.Ar length
|
||||||
@@ -1968,15 +1767,16 @@ character pairs are replaced, and UTF-8 is dependent on the
|
|||||||
option.
|
option.
|
||||||
.It Ic status-right-attr Ar attributes
|
.It Ic status-right-attr Ar attributes
|
||||||
Set the attribute of the right part of the status line.
|
Set the attribute of the right part of the status line.
|
||||||
.It Ic status-right-bg Ar colour
|
|
||||||
Set the background colour of the right part of the status line.
|
|
||||||
.It Ic status-right-fg Ar colour
|
.It Ic status-right-fg Ar colour
|
||||||
Set the foreground colour of the right part of the status line.
|
Set the foreground colour of the right part of the status line.
|
||||||
|
.It Ic status-right-bg Ar colour
|
||||||
|
Set the background colour of the right part of the status line.
|
||||||
.It Ic status-right-length Ar length
|
.It Ic status-right-length Ar length
|
||||||
Set the maximum
|
Set the maximum
|
||||||
.Ar length
|
.Ar length
|
||||||
of the right component of the status bar.
|
of the right component of the status bar.
|
||||||
The default is 40.
|
The default is 40.
|
||||||
|
.Pp
|
||||||
.It Xo Ic status-utf8
|
.It Xo Ic status-utf8
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
@@ -2035,8 +1835,7 @@ was given to the
|
|||||||
.Ic set-environment
|
.Ic set-environment
|
||||||
command).
|
command).
|
||||||
The default is
|
The default is
|
||||||
"DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION WINDOWID
|
"DISPLAY WINDOWID SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION".
|
||||||
XAUTHORITY".
|
|
||||||
.It Xo Ic visual-activity
|
.It Xo Ic visual-activity
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
@@ -2061,12 +1860,6 @@ display a message when content is present in a window
|
|||||||
for which the
|
for which the
|
||||||
.Ic monitor-content
|
.Ic monitor-content
|
||||||
window option is enabled.
|
window option is enabled.
|
||||||
.It Xo Ic visual-silence
|
|
||||||
.Op Ic on | off
|
|
||||||
.Xc
|
|
||||||
If
|
|
||||||
.Ic monitor-silence
|
|
||||||
is enabled, prints a message after the interval has expired on a given window.
|
|
||||||
.El
|
.El
|
||||||
.It Xo Ic set-window-option
|
.It Xo Ic set-window-option
|
||||||
.Op Fl agu
|
.Op Fl agu
|
||||||
@@ -2100,19 +1893,6 @@ this option is good for full-screen programs which support
|
|||||||
.Dv SIGWINCH
|
.Dv SIGWINCH
|
||||||
and poor for interactive programs such as shells.
|
and poor for interactive programs such as shells.
|
||||||
.Pp
|
.Pp
|
||||||
.It Xo Ic alternate-screen
|
|
||||||
.Op Ic on | off
|
|
||||||
.Xc
|
|
||||||
This option configures whether programs running inside
|
|
||||||
.Nm
|
|
||||||
may use the terminal alternate screen feature, which allows the
|
|
||||||
.Em smcup
|
|
||||||
and
|
|
||||||
.Em rmcup
|
|
||||||
.Xr terminfo 5
|
|
||||||
capabilities to be issued to preserve the existing window content on start and
|
|
||||||
restore it on exit.
|
|
||||||
.Pp
|
|
||||||
.It Xo Ic automatic-rename
|
.It Xo Ic automatic-rename
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
@@ -2123,8 +1903,7 @@ will attempt - on supported platforms - to rename the window to reflect the
|
|||||||
command currently running in it.
|
command currently running in it.
|
||||||
This flag is automatically disabled for an individual window when a name
|
This flag is automatically disabled for an individual window when a name
|
||||||
is specified at creation with
|
is specified at creation with
|
||||||
.Ic new-window
|
.Ic new-window or
|
||||||
or
|
|
||||||
.Ic new-session ,
|
.Ic new-session ,
|
||||||
or later with
|
or later with
|
||||||
.Ic rename-window .
|
.Ic rename-window .
|
||||||
@@ -2151,8 +1930,8 @@ or
|
|||||||
.Ar height .
|
.Ar height .
|
||||||
A value of zero restores the default unlimited setting.
|
A value of zero restores the default unlimited setting.
|
||||||
.Pp
|
.Pp
|
||||||
.It Ic main-pane-height Ar height
|
|
||||||
.It Ic main-pane-width Ar width
|
.It Ic main-pane-width Ar width
|
||||||
|
.It Ic main-pane-height Ar height
|
||||||
Set the width or height of the main (left or top) pane in the
|
Set the width or height of the main (left or top) pane in the
|
||||||
.Ic main-horizontal
|
.Ic main-horizontal
|
||||||
or
|
or
|
||||||
@@ -2172,21 +1951,16 @@ Set window modes foreground colour.
|
|||||||
.Op Ic vi | emacs
|
.Op Ic vi | emacs
|
||||||
.Xc
|
.Xc
|
||||||
Use vi or emacs-style key bindings in copy and choice modes.
|
Use vi or emacs-style key bindings in copy and choice modes.
|
||||||
As with the
|
Key bindings default to emacs.
|
||||||
.Ic status-keys
|
|
||||||
option, the default is emacs, unless
|
|
||||||
.Ev VISUAL
|
|
||||||
or
|
|
||||||
.Ev EDITOR
|
|
||||||
contains
|
|
||||||
.Ql vi .
|
|
||||||
.Pp
|
.Pp
|
||||||
.It Xo Ic mode-mouse
|
.It Xo Ic mode-mouse
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
Mouse state in modes.
|
Mouse state in modes.
|
||||||
If on, the mouse may be used to copy a selection by dragging in copy mode, or
|
If on,
|
||||||
to select an option in choice mode.
|
.Nm
|
||||||
|
will respond to mouse clicks by moving the cursor in copy mode or selecting an
|
||||||
|
option in choice mode.
|
||||||
.Pp
|
.Pp
|
||||||
.It Xo Ic monitor-activity
|
.It Xo Ic monitor-activity
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
@@ -2202,35 +1976,6 @@ pattern
|
|||||||
.Ar match-string
|
.Ar match-string
|
||||||
appears in the window, it is highlighted in the status line.
|
appears in the window, it is highlighted in the status line.
|
||||||
.Pp
|
.Pp
|
||||||
.It Xo Ic monitor-silence
|
|
||||||
.Op Ic interval
|
|
||||||
.Xc
|
|
||||||
Monitor for silence (no activity) in the window within
|
|
||||||
.Ic interval
|
|
||||||
seconds.
|
|
||||||
Windows that have been silent for the interval are highlighted in the
|
|
||||||
status line.
|
|
||||||
An interval of zero disables the monitoring.
|
|
||||||
.Pp
|
|
||||||
.It Ic other-pane-height Ar height
|
|
||||||
Set the height of the other panes (not the main pane) in the
|
|
||||||
.Ic main-horizontal
|
|
||||||
layout.
|
|
||||||
If this option is set to 0 (the default), it will have no effect.
|
|
||||||
If both the
|
|
||||||
.Ic main-pane-height
|
|
||||||
and
|
|
||||||
.Ic other-pane-height
|
|
||||||
options are set, the main pane will grow taller to make the other panes the
|
|
||||||
specified height, but will never shrink to do so.
|
|
||||||
.Pp
|
|
||||||
.It Ic other-pane-width Ar width
|
|
||||||
Like
|
|
||||||
.Ic other-pane-height ,
|
|
||||||
but set the width of other panes in the
|
|
||||||
.Ic main-vertical
|
|
||||||
layout.
|
|
||||||
.Pp
|
|
||||||
.It Xo Ic remain-on-exit
|
.It Xo Ic remain-on-exit
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
@@ -2243,8 +1988,21 @@ command.
|
|||||||
.It Xo Ic synchronize-panes
|
.It Xo Ic synchronize-panes
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
Duplicate input to any pane to all other panes in the same window (only
|
Duplicate input to any pane to all other panes in the same window, except
|
||||||
for panes that are not in any special mode).
|
for panes that are not in output mode.
|
||||||
|
.Pp
|
||||||
|
.It Xo Ic alternate-screen
|
||||||
|
.Op Ic on | off
|
||||||
|
.Xc
|
||||||
|
This option configures whether programs running inside
|
||||||
|
.Nm
|
||||||
|
may use the terminal alternate screen feature, which allows the
|
||||||
|
.Em smcup
|
||||||
|
and
|
||||||
|
.Em rmcup
|
||||||
|
.Xr terminfo 5
|
||||||
|
capabilities to be issued to preserve the existing window content on start and
|
||||||
|
restore it on exit.
|
||||||
.Pp
|
.Pp
|
||||||
.It Xo Ic utf8
|
.It Xo Ic utf8
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
@@ -2270,16 +2028,6 @@ option for details of special character sequences available.
|
|||||||
The default is
|
The default is
|
||||||
.Ql #I:#W#F .
|
.Ql #I:#W#F .
|
||||||
.Pp
|
.Pp
|
||||||
.It Ic window-status-alert-attr Ar attributes
|
|
||||||
Set status line attributes for windows which have an alert (bell, activity
|
|
||||||
or content).
|
|
||||||
.Pp
|
|
||||||
.It Ic window-status-alert-bg Ar colour
|
|
||||||
Set status line background colour for windows with an alert.
|
|
||||||
.Pp
|
|
||||||
.It Ic window-status-alert-fg Ar colour
|
|
||||||
Set status line foreground colour for windows with an alert.
|
|
||||||
.Pp
|
|
||||||
.It Ic window-status-current-attr Ar attributes
|
.It Ic window-status-current-attr Ar attributes
|
||||||
Set status line attributes for the currently active window.
|
Set status line attributes for the currently active window.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -2346,9 +2094,9 @@ copies the environment into the
|
|||||||
.Em global environment ;
|
.Em global environment ;
|
||||||
in addition, each session has a
|
in addition, each session has a
|
||||||
.Em session environment .
|
.Em session environment .
|
||||||
When a window is created, the session and global environments are merged.
|
When a window is created, the session and global environments are merged with
|
||||||
If a variable exists in both, the value from the session environment is used.
|
the session environment overriding any variable present in both.
|
||||||
The result is the initial environment passed to the new process.
|
This is the initial environment passed to the new process.
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Ic update-environment
|
.Ic update-environment
|
||||||
@@ -2429,7 +2177,6 @@ The flag is one of the following symbols appended to the window name:
|
|||||||
.It Li "#" Ta "Window is monitored and activity has been detected."
|
.It Li "#" Ta "Window is monitored and activity has been detected."
|
||||||
.It Li "!" Ta "A bell has occurred in the window."
|
.It Li "!" Ta "A bell has occurred in the window."
|
||||||
.It Li "+" Ta "Window is monitored for content and it has appeared."
|
.It Li "+" Ta "Window is monitored for content and it has appeared."
|
||||||
.It Li "~" Ta "The window has been silent for the monitor-silence interval."
|
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The # symbol relates to the
|
The # symbol relates to the
|
||||||
@@ -2524,6 +2271,10 @@ The format of
|
|||||||
is as for
|
is as for
|
||||||
.Ic status-left ,
|
.Ic status-left ,
|
||||||
with the exception that #() are not handled.
|
with the exception that #() are not handled.
|
||||||
|
.It Ic select-prompt Op Fl t Ar target-client
|
||||||
|
Open a prompt inside
|
||||||
|
.Ar target-client
|
||||||
|
allowing a window index to be entered interactively.
|
||||||
.El
|
.El
|
||||||
.Sh BUFFERS
|
.Sh BUFFERS
|
||||||
.Nm
|
.Nm
|
||||||
@@ -2551,23 +2302,6 @@ command above).
|
|||||||
.Pp
|
.Pp
|
||||||
The buffer commands are as follows:
|
The buffer commands are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Xo
|
|
||||||
.Ic choose-buffer
|
|
||||||
.Op Fl t Ar target-window
|
|
||||||
.Op Ar template
|
|
||||||
.Xc
|
|
||||||
Put a window into buffer choice mode, where a buffer may be chosen
|
|
||||||
interactively from a list.
|
|
||||||
After a buffer is selected,
|
|
||||||
.Ql %%
|
|
||||||
is replaced by the buffer index in
|
|
||||||
.Ar template
|
|
||||||
and the result executed as a command.
|
|
||||||
If
|
|
||||||
.Ar template
|
|
||||||
is not given, "paste-buffer -b '%%'" is used.
|
|
||||||
This command works only from inside
|
|
||||||
.Nm .
|
|
||||||
.It Ic clear-history Op Fl t Ar target-pane
|
.It Ic clear-history Op Fl t Ar target-pane
|
||||||
.D1 (alias: Ic clearhist )
|
.D1 (alias: Ic clearhist )
|
||||||
Remove and free the history for the specified pane.
|
Remove and free the history for the specified pane.
|
||||||
@@ -2602,23 +2336,18 @@ Load the contents of the specified paste buffer from
|
|||||||
.It Xo Ic paste-buffer
|
.It Xo Ic paste-buffer
|
||||||
.Op Fl dr
|
.Op Fl dr
|
||||||
.Op Fl b Ar buffer-index
|
.Op Fl b Ar buffer-index
|
||||||
.Op Fl s Ar separator
|
.Op Fl t Ar target-window
|
||||||
.Op Fl t Ar target-pane
|
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic pasteb )
|
.D1 (alias: Ic pasteb )
|
||||||
Insert the contents of a paste buffer into the specified pane.
|
Insert the contents of a paste buffer into the current window.
|
||||||
If not specified, paste into the current one.
|
|
||||||
With
|
With
|
||||||
.Fl d ,
|
.Fl d ,
|
||||||
also delete the paste buffer from the stack.
|
also delete the paste buffer from the stack.
|
||||||
When output, any linefeed (LF) characters in the paste buffer are replaced with
|
When output, any linefeed (LF) characters in the paste buffer are replaced with
|
||||||
a separator, by default carriage return (CR).
|
carriage returns (CR).
|
||||||
A custom separator may be specified using the
|
This translation may be disabled with the
|
||||||
.Fl s
|
|
||||||
flag.
|
|
||||||
The
|
|
||||||
.Fl r
|
.Fl r
|
||||||
flag means to do no replacement (equivalent to a separator of LF).
|
flag.
|
||||||
.It Xo Ic save-buffer
|
.It Xo Ic save-buffer
|
||||||
.Op Fl a
|
.Op Fl a
|
||||||
.Op Fl b Ar buffer-index
|
.Op Fl b Ar buffer-index
|
||||||
@@ -2647,6 +2376,7 @@ Set the contents of the specified buffer to
|
|||||||
Display the contents of the specified buffer.
|
Display the contents of the specified buffer.
|
||||||
.El
|
.El
|
||||||
.Sh MISCELLANEOUS
|
.Sh MISCELLANEOUS
|
||||||
|
.Pp
|
||||||
Miscellaneous commands are as follows:
|
Miscellaneous commands are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Ic clock-mode Op Fl t Ar target-pane
|
.It Ic clock-mode Op Fl t Ar target-pane
|
||||||
@@ -2668,7 +2398,7 @@ option.
|
|||||||
Execute
|
Execute
|
||||||
.Ar shell-command
|
.Ar shell-command
|
||||||
in the background without creating a window.
|
in the background without creating a window.
|
||||||
After it finishes, any output to stdout is displayed in copy mode.
|
After it finishes, any output to stdout is displayed in output mode.
|
||||||
If the command doesn't return success, the exit status is also displayed.
|
If the command doesn't return success, the exit status is also displayed.
|
||||||
.It Ic server-info
|
.It Ic server-info
|
||||||
.D1 (alias: Ic info )
|
.D1 (alias: Ic info )
|
||||||
|
|||||||
393
tmux.c
393
tmux.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: tmux.c,v 1.228 2010-12-27 21:22:24 tcunha Exp $ */
|
/* $Id: tmux.c,v 1.204 2010-02-26 13:31:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -21,10 +21,11 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <event.h>
|
#include <event.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@@ -33,26 +34,37 @@
|
|||||||
extern char *malloc_options;
|
extern char *malloc_options;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char *cfg_file;
|
||||||
struct options global_options; /* server options */
|
struct options global_options; /* server options */
|
||||||
struct options global_s_options; /* session options */
|
struct options global_s_options; /* session options */
|
||||||
struct options global_w_options; /* window options */
|
struct options global_w_options; /* window options */
|
||||||
struct environ global_environ;
|
struct environ global_environ;
|
||||||
|
|
||||||
struct event_base *ev_base;
|
|
||||||
|
|
||||||
char *cfg_file;
|
|
||||||
char *shell_cmd;
|
|
||||||
int debug_level;
|
int debug_level;
|
||||||
time_t start_time;
|
time_t start_time;
|
||||||
char socket_path[MAXPATHLEN];
|
char *socket_path;
|
||||||
int login_shell;
|
int login_shell;
|
||||||
char *environ_path;
|
|
||||||
pid_t environ_pid;
|
struct env_data {
|
||||||
u_int environ_idx;
|
char *path;
|
||||||
|
pid_t pid;
|
||||||
|
u_int idx;
|
||||||
|
};
|
||||||
|
|
||||||
__dead void usage(void);
|
__dead void usage(void);
|
||||||
void parseenvironment(void);
|
void parse_env(struct env_data *);
|
||||||
char *makesocketpath(const char *);
|
char *makesockpath(const char *);
|
||||||
|
__dead void shell_exec(const char *, const char *);
|
||||||
|
|
||||||
|
struct imsgbuf *main_ibuf;
|
||||||
|
struct event main_ev_sigterm;
|
||||||
|
int main_exitval;
|
||||||
|
|
||||||
|
void main_set_signals(void);
|
||||||
|
void main_clear_signals(void);
|
||||||
|
void main_signal(int, short, unused void *);
|
||||||
|
void main_callback(int, short, void *);
|
||||||
|
void main_dispatch(const char *);
|
||||||
|
|
||||||
#ifndef HAVE_PROGNAME
|
#ifndef HAVE_PROGNAME
|
||||||
char *__progname = (char *) "tmux";
|
char *__progname = (char *) "tmux";
|
||||||
@@ -62,7 +74,7 @@ __dead void
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage: %s [-28lquvV] [-c shell-command] [-f file] [-L socket-name]\n"
|
"usage: %s [-28lquv] [-c shell-command] [-f file] [-L socket-name]\n"
|
||||||
" [-S socket-path] [command [flags]]\n",
|
" [-S socket-path] [command [flags]]\n",
|
||||||
__progname);
|
__progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -126,14 +138,14 @@ areshell(const char *shell)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
parseenvironment(void)
|
parse_env(struct env_data *data)
|
||||||
{
|
{
|
||||||
char *env, *path_pid, *pid_idx, buf[256];
|
char *env, *path_pid, *pid_idx, buf[256];
|
||||||
size_t len;
|
size_t len;
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
long long ll;
|
long long ll;
|
||||||
|
|
||||||
environ_pid = -1;
|
data->pid = -1;
|
||||||
if ((env = getenv("TMUX")) == NULL)
|
if ((env = getenv("TMUX")) == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -146,9 +158,9 @@ parseenvironment(void)
|
|||||||
|
|
||||||
/* path */
|
/* path */
|
||||||
len = path_pid - env;
|
len = path_pid - env;
|
||||||
environ_path = xmalloc(len + 1);
|
data->path = xmalloc (len + 1);
|
||||||
memcpy(environ_path, env, len);
|
memcpy(data->path, env, len);
|
||||||
environ_path[len] = '\0';
|
data->path[len] = '\0';
|
||||||
|
|
||||||
/* pid */
|
/* pid */
|
||||||
len = pid_idx - path_pid - 1;
|
len = pid_idx - path_pid - 1;
|
||||||
@@ -160,17 +172,17 @@ parseenvironment(void)
|
|||||||
ll = strtonum(buf, 0, LONG_MAX, &errstr);
|
ll = strtonum(buf, 0, LONG_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
return;
|
return;
|
||||||
environ_pid = ll;
|
data->pid = ll;
|
||||||
|
|
||||||
/* idx */
|
/* idx */
|
||||||
ll = strtonum(pid_idx + 1, 0, UINT_MAX, &errstr);
|
ll = strtonum(pid_idx+1, 0, UINT_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
return;
|
return;
|
||||||
environ_idx = ll;
|
data->idx = ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
makesocketpath(const char *label)
|
makesockpath(const char *label)
|
||||||
{
|
{
|
||||||
char base[MAXPATHLEN], *path;
|
char base[MAXPATHLEN], *path;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
@@ -202,7 +214,6 @@ shell_exec(const char *shell, const char *shellcmd)
|
|||||||
{
|
{
|
||||||
const char *shellname, *ptr;
|
const char *shellname, *ptr;
|
||||||
char *argv0;
|
char *argv0;
|
||||||
int mode;
|
|
||||||
|
|
||||||
ptr = strrchr(shell, '/');
|
ptr = strrchr(shell, '/');
|
||||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
if (ptr != NULL && *(ptr + 1) != '\0')
|
||||||
@@ -215,14 +226,6 @@ shell_exec(const char *shell, const char *shellcmd)
|
|||||||
xasprintf(&argv0, "%s", shellname);
|
xasprintf(&argv0, "%s", shellname);
|
||||||
setenv("SHELL", shell, 1);
|
setenv("SHELL", shell, 1);
|
||||||
|
|
||||||
if ((mode = fcntl(STDIN_FILENO, F_GETFL)) != -1)
|
|
||||||
fcntl(STDIN_FILENO, F_SETFL, mode & ~O_NONBLOCK);
|
|
||||||
if ((mode = fcntl(STDOUT_FILENO, F_GETFL)) != -1)
|
|
||||||
fcntl(STDOUT_FILENO, F_SETFL, mode & ~O_NONBLOCK);
|
|
||||||
if ((mode = fcntl(STDERR_FILENO, F_GETFL)) != -1)
|
|
||||||
fcntl(STDERR_FILENO, F_SETFL, mode & ~O_NONBLOCK);
|
|
||||||
closefrom(STDERR_FILENO + 1);
|
|
||||||
|
|
||||||
execl(shell, argv0, "-c", shellcmd, (char *) NULL);
|
execl(shell, argv0, "-c", shellcmd, (char *) NULL);
|
||||||
fatal("execl failed");
|
fatal("execl failed");
|
||||||
}
|
}
|
||||||
@@ -230,20 +233,30 @@ shell_exec(const char *shell, const char *shellcmd)
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct passwd *pw;
|
struct cmd_list *cmdlist;
|
||||||
struct options *oo, *so, *wo;
|
struct cmd *cmd;
|
||||||
struct keylist *keylist;
|
enum msgtype msg;
|
||||||
char *s, *path, *label, *home, **var;
|
struct passwd *pw;
|
||||||
int opt, flags, quiet, keys;
|
struct options *oo, *so, *wo;
|
||||||
|
struct keylist *keylist;
|
||||||
|
struct env_data envdata;
|
||||||
|
struct msg_command_data cmddata;
|
||||||
|
char *s, *shellcmd, *path, *label, *home, *cause;
|
||||||
|
char cwd[MAXPATHLEN], **var;
|
||||||
|
void *buf;
|
||||||
|
size_t len;
|
||||||
|
int opt, flags, quiet = 0, cmdflags = 0;
|
||||||
|
short events;
|
||||||
|
|
||||||
#if defined(DEBUG) && defined(__OpenBSD__)
|
#if defined(DEBUG) && defined(__OpenBSD__)
|
||||||
malloc_options = (char *) "AFGJPX";
|
malloc_options = (char *) "AFGJPX";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
quiet = flags = 0;
|
flags = 0;
|
||||||
label = path = NULL;
|
shellcmd = label = path = NULL;
|
||||||
|
envdata.path = NULL;
|
||||||
login_shell = (**argv == '-');
|
login_shell = (**argv == '-');
|
||||||
while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUvV")) != -1) {
|
while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUv")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case '2':
|
case '2':
|
||||||
flags |= IDENTIFY_256COLOURS;
|
flags |= IDENTIFY_256COLOURS;
|
||||||
@@ -254,13 +267,10 @@ main(int argc, char **argv)
|
|||||||
flags &= ~IDENTIFY_256COLOURS;
|
flags &= ~IDENTIFY_256COLOURS;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
if (shell_cmd != NULL)
|
if (shellcmd != NULL)
|
||||||
xfree(shell_cmd);
|
xfree(shellcmd);
|
||||||
shell_cmd = xstrdup(optarg);
|
shellcmd = xstrdup(optarg);
|
||||||
break;
|
break;
|
||||||
case 'V':
|
|
||||||
printf("%s %s\n", __progname, BUILD);
|
|
||||||
exit(0);
|
|
||||||
case 'f':
|
case 'f':
|
||||||
if (cfg_file != NULL)
|
if (cfg_file != NULL)
|
||||||
xfree(cfg_file);
|
xfree(cfg_file);
|
||||||
@@ -295,7 +305,7 @@ main(int argc, char **argv)
|
|||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (shell_cmd != NULL && argc != 0)
|
if (shellcmd != NULL && argc != 0)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
log_open_tty(debug_level);
|
log_open_tty(debug_level);
|
||||||
@@ -325,7 +335,6 @@ main(int argc, char **argv)
|
|||||||
oo = &global_options;
|
oo = &global_options;
|
||||||
options_set_number(oo, "quiet", quiet);
|
options_set_number(oo, "quiet", quiet);
|
||||||
options_set_number(oo, "escape-time", 500);
|
options_set_number(oo, "escape-time", 500);
|
||||||
options_set_number(oo, "exit-unattached", 0);
|
|
||||||
|
|
||||||
options_init(&global_s_options, NULL);
|
options_init(&global_s_options, NULL);
|
||||||
so = &global_s_options;
|
so = &global_s_options;
|
||||||
@@ -333,13 +342,10 @@ main(int argc, char **argv)
|
|||||||
options_set_number(so, "bell-action", BELL_ANY);
|
options_set_number(so, "bell-action", BELL_ANY);
|
||||||
options_set_number(so, "buffer-limit", 9);
|
options_set_number(so, "buffer-limit", 9);
|
||||||
options_set_string(so, "default-command", "%s", "");
|
options_set_string(so, "default-command", "%s", "");
|
||||||
options_set_string(so, "default-path", "%s", "");
|
|
||||||
options_set_string(so, "default-shell", "%s", getshell());
|
options_set_string(so, "default-shell", "%s", getshell());
|
||||||
options_set_string(so, "default-terminal", "screen");
|
options_set_string(so, "default-terminal", "screen");
|
||||||
options_set_number(so, "destroy-unattached", 0);
|
|
||||||
options_set_number(so, "detach-on-destroy", 1);
|
|
||||||
options_set_number(so, "display-panes-active-colour", 1);
|
|
||||||
options_set_number(so, "display-panes-colour", 4);
|
options_set_number(so, "display-panes-colour", 4);
|
||||||
|
options_set_number(so, "display-panes-active-colour", 1);
|
||||||
options_set_number(so, "display-panes-time", 1000);
|
options_set_number(so, "display-panes-time", 1000);
|
||||||
options_set_number(so, "display-time", 750);
|
options_set_number(so, "display-time", 750);
|
||||||
options_set_number(so, "history-limit", 2000);
|
options_set_number(so, "history-limit", 2000);
|
||||||
@@ -351,8 +357,8 @@ main(int argc, char **argv)
|
|||||||
options_set_number(so, "message-fg", 0);
|
options_set_number(so, "message-fg", 0);
|
||||||
options_set_number(so, "message-limit", 20);
|
options_set_number(so, "message-limit", 20);
|
||||||
options_set_number(so, "mouse-select-pane", 0);
|
options_set_number(so, "mouse-select-pane", 0);
|
||||||
options_set_number(so, "pane-active-border-bg", 8);
|
options_set_number(so, "pane-active-border-bg", 2);
|
||||||
options_set_number(so, "pane-active-border-fg", 2);
|
options_set_number(so, "pane-active-border-fg", 8);
|
||||||
options_set_number(so, "pane-border-bg", 8);
|
options_set_number(so, "pane-border-bg", 8);
|
||||||
options_set_number(so, "pane-border-fg", 8);
|
options_set_number(so, "pane-border-fg", 8);
|
||||||
options_set_number(so, "repeat-time", 500);
|
options_set_number(so, "repeat-time", 500);
|
||||||
@@ -365,6 +371,7 @@ main(int argc, char **argv)
|
|||||||
options_set_number(so, "status-fg", 0);
|
options_set_number(so, "status-fg", 0);
|
||||||
options_set_number(so, "status-interval", 15);
|
options_set_number(so, "status-interval", 15);
|
||||||
options_set_number(so, "status-justify", 0);
|
options_set_number(so, "status-justify", 0);
|
||||||
|
options_set_number(so, "status-keys", MODEKEY_EMACS);
|
||||||
options_set_string(so, "status-left", "[#S]");
|
options_set_string(so, "status-left", "[#S]");
|
||||||
options_set_number(so, "status-left-attr", 0);
|
options_set_number(so, "status-left-attr", 0);
|
||||||
options_set_number(so, "status-left-bg", 8);
|
options_set_number(so, "status-left-bg", 8);
|
||||||
@@ -377,15 +384,11 @@ main(int argc, char **argv)
|
|||||||
options_set_number(so, "status-right-length", 40);
|
options_set_number(so, "status-right-length", 40);
|
||||||
options_set_string(so, "terminal-overrides",
|
options_set_string(so, "terminal-overrides",
|
||||||
"*88col*:colors=88,*256col*:colors=256");
|
"*88col*:colors=88,*256col*:colors=256");
|
||||||
options_set_string(so, "update-environment",
|
options_set_string(so, "update-environment", "DISPLAY "
|
||||||
"DISPLAY "
|
"WINDOWID SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION");
|
||||||
"SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION "
|
|
||||||
"WINDOWID "
|
|
||||||
"XAUTHORITY");
|
|
||||||
options_set_number(so, "visual-activity", 0);
|
options_set_number(so, "visual-activity", 0);
|
||||||
options_set_number(so, "visual-bell", 0);
|
options_set_number(so, "visual-bell", 0);
|
||||||
options_set_number(so, "visual-content", 0);
|
options_set_number(so, "visual-content", 0);
|
||||||
options_set_number(so, "visual-silence", 0);
|
|
||||||
|
|
||||||
keylist = xmalloc(sizeof *keylist);
|
keylist = xmalloc(sizeof *keylist);
|
||||||
ARRAY_INIT(keylist);
|
ARRAY_INIT(keylist);
|
||||||
@@ -402,25 +405,20 @@ main(int argc, char **argv)
|
|||||||
options_set_number(wo, "force-height", 0);
|
options_set_number(wo, "force-height", 0);
|
||||||
options_set_number(wo, "force-width", 0);
|
options_set_number(wo, "force-width", 0);
|
||||||
options_set_number(wo, "main-pane-height", 24);
|
options_set_number(wo, "main-pane-height", 24);
|
||||||
options_set_number(wo, "main-pane-width", 80);
|
options_set_number(wo, "main-pane-width", 81);
|
||||||
options_set_number(wo, "mode-attr", 0);
|
options_set_number(wo, "mode-attr", 0);
|
||||||
options_set_number(wo, "mode-bg", 3);
|
options_set_number(wo, "mode-bg", 3);
|
||||||
options_set_number(wo, "mode-fg", 0);
|
options_set_number(wo, "mode-fg", 0);
|
||||||
|
options_set_number(wo, "mode-keys", MODEKEY_EMACS);
|
||||||
options_set_number(wo, "mode-mouse", 0);
|
options_set_number(wo, "mode-mouse", 0);
|
||||||
options_set_number(wo, "monitor-activity", 0);
|
options_set_number(wo, "monitor-activity", 0);
|
||||||
options_set_string(wo, "monitor-content", "%s", "");
|
options_set_string(wo, "monitor-content", "%s", "");
|
||||||
options_set_number(wo, "monitor-silence", 0);
|
|
||||||
options_set_number(wo, "other-pane-height", 0);
|
|
||||||
options_set_number(wo, "other-pane-width", 0);
|
|
||||||
options_set_number(wo, "window-status-attr", 0);
|
options_set_number(wo, "window-status-attr", 0);
|
||||||
options_set_number(wo, "window-status-bg", 8);
|
options_set_number(wo, "window-status-bg", 8);
|
||||||
options_set_number(wo, "window-status-current-attr", 0);
|
options_set_number(wo, "window-status-current-attr", 0);
|
||||||
options_set_number(wo, "window-status-current-bg", 8);
|
options_set_number(wo, "window-status-current-bg", 8);
|
||||||
options_set_number(wo, "window-status-current-fg", 8);
|
options_set_number(wo, "window-status-current-fg", 8);
|
||||||
options_set_number(wo, "window-status-fg", 8);
|
options_set_number(wo, "window-status-fg", 8);
|
||||||
options_set_number(wo, "window-status-alert-attr", GRID_ATTR_REVERSE);
|
|
||||||
options_set_number(wo, "window-status-alert-bg", 8);
|
|
||||||
options_set_number(wo, "window-status-alert-fg", 8);
|
|
||||||
options_set_string(wo, "window-status-format", "#I:#W#F");
|
options_set_string(wo, "window-status-format", "#I:#W#F");
|
||||||
options_set_string(wo, "window-status-current-format", "#I:#W#F");
|
options_set_string(wo, "window-status-current-format", "#I:#W#F");
|
||||||
options_set_string(wo, "word-separators", " -_@");
|
options_set_string(wo, "word-separators", " -_@");
|
||||||
@@ -436,17 +434,15 @@ main(int argc, char **argv)
|
|||||||
options_set_number(wo, "utf8", 0);
|
options_set_number(wo, "utf8", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
keys = MODEKEY_EMACS;
|
if (getcwd(cwd, sizeof cwd) == NULL) {
|
||||||
if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) {
|
pw = getpwuid(getuid());
|
||||||
if (strrchr(s, '/') != NULL)
|
if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
|
||||||
s = strrchr(s, '/') + 1;
|
strlcpy(cwd, pw->pw_dir, sizeof cwd);
|
||||||
if (strstr(s, "vi") != NULL)
|
else
|
||||||
keys = MODEKEY_VI;
|
strlcpy(cwd, "/", sizeof cwd);
|
||||||
}
|
}
|
||||||
options_set_number(so, "status-keys", keys);
|
options_set_string(so, "default-path", "%s", cwd);
|
||||||
options_set_number(wo, "mode-keys", keys);
|
|
||||||
|
|
||||||
/* Locate the configuration file. */
|
|
||||||
if (cfg_file == NULL) {
|
if (cfg_file == NULL) {
|
||||||
home = getenv("HOME");
|
home = getenv("HOME");
|
||||||
if (home == NULL || *home == '\0') {
|
if (home == NULL || *home == '\0') {
|
||||||
@@ -462,22 +458,21 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out the socket path. If specified on the command-line with -S
|
* Figure out the socket path. If specified on the command-line with
|
||||||
* or -L, use it, otherwise try $TMUX or assume -L default.
|
* -S or -L, use it, otherwise try $TMUX or assume -L default.
|
||||||
*/
|
*/
|
||||||
parseenvironment();
|
parse_env(&envdata);
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
/* If no -L, use the environment. */
|
/* No -L. Try $TMUX, or default. */
|
||||||
if (label == NULL) {
|
if (label == NULL) {
|
||||||
if (environ_path != NULL)
|
path = envdata.path;
|
||||||
path = xstrdup(environ_path);
|
if (path == NULL)
|
||||||
else
|
|
||||||
label = xstrdup("default");
|
label = xstrdup("default");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -L or default set. */
|
/* -L or default set. */
|
||||||
if (label != NULL) {
|
if (label != NULL) {
|
||||||
if ((path = makesocketpath(label)) == NULL) {
|
if ((path = makesockpath(label)) == NULL) {
|
||||||
log_warn("can't create socket");
|
log_warn("can't create socket");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -485,16 +480,70 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (label != NULL)
|
if (label != NULL)
|
||||||
xfree(label);
|
xfree(label);
|
||||||
if (realpath(path, socket_path) == NULL)
|
|
||||||
strlcpy(socket_path, path, sizeof socket_path);
|
if (shellcmd != NULL) {
|
||||||
|
msg = MSG_SHELL;
|
||||||
|
buf = NULL;
|
||||||
|
len = 0;
|
||||||
|
} else {
|
||||||
|
cmddata.pid = envdata.pid;
|
||||||
|
cmddata.idx = envdata.idx;
|
||||||
|
|
||||||
|
/* Prepare command for server. */
|
||||||
|
cmddata.argc = argc;
|
||||||
|
if (cmd_pack_argv(
|
||||||
|
argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
|
||||||
|
log_warnx("command too long");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = MSG_COMMAND;
|
||||||
|
buf = &cmddata;
|
||||||
|
len = sizeof cmddata;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shellcmd != NULL)
|
||||||
|
cmdflags |= CMD_STARTSERVER;
|
||||||
|
else if (argc == 0) /* new-session is the default */
|
||||||
|
cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST;
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* It sucks parsing the command string twice (in client and
|
||||||
|
* later in server) but it is necessary to get the start server
|
||||||
|
* flag.
|
||||||
|
*/
|
||||||
|
if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
|
||||||
|
log_warnx("%s", cause);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
cmdflags &= ~CMD_STARTSERVER;
|
||||||
|
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
||||||
|
if (cmd->entry->flags & CMD_STARTSERVER)
|
||||||
|
cmdflags |= CMD_STARTSERVER;
|
||||||
|
if (cmd->entry->flags & CMD_SENDENVIRON)
|
||||||
|
cmdflags |= CMD_SENDENVIRON;
|
||||||
|
if (cmd->entry->flags & CMD_CANTNEST)
|
||||||
|
cmdflags |= CMD_CANTNEST;
|
||||||
|
}
|
||||||
|
cmd_list_free(cmdlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if this could be a nested session, if the command can't nest:
|
||||||
|
* if the socket path matches $TMUX, this is probably the same server.
|
||||||
|
*/
|
||||||
|
if (shellcmd == NULL && envdata.path != NULL &&
|
||||||
|
cmdflags & CMD_CANTNEST &&
|
||||||
|
(path == envdata.path || strcmp(path, envdata.path) == 0)) {
|
||||||
|
log_warnx("sessions should be nested with care. "
|
||||||
|
"unset $TMUX to force.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((main_ibuf = client_init(path, cmdflags, flags)) == NULL)
|
||||||
|
exit(1);
|
||||||
xfree(path);
|
xfree(path);
|
||||||
|
|
||||||
#ifdef HAVE_SETPROCTITLE
|
|
||||||
/* Set process title. */
|
|
||||||
setproctitle("%s (%s)", __progname, socket_path);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Pass control to the client. */
|
|
||||||
#ifdef HAVE_BROKEN_KQUEUE
|
#ifdef HAVE_BROKEN_KQUEUE
|
||||||
if (setenv("EVENT_NOKQUEUE", "1", 1) != 0)
|
if (setenv("EVENT_NOKQUEUE", "1", 1) != 0)
|
||||||
fatal("setenv failed");
|
fatal("setenv failed");
|
||||||
@@ -503,12 +552,170 @@ main(int argc, char **argv)
|
|||||||
if (setenv("EVENT_NOPOLL", "1", 1) != 0)
|
if (setenv("EVENT_NOPOLL", "1", 1) != 0)
|
||||||
fatal("setenv failed");
|
fatal("setenv failed");
|
||||||
#endif
|
#endif
|
||||||
ev_base = event_init();
|
event_init();
|
||||||
#ifdef HAVE_BROKEN_KQUEUE
|
#ifdef HAVE_BROKEN_KQUEUE
|
||||||
unsetenv("EVENT_NOKQUEUE");
|
unsetenv("EVENT_NOKQUEUE");
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_BROKEN_POLL
|
#ifdef HAVE_BROKEN_POLL
|
||||||
unsetenv("EVENT_NOPOLL");
|
unsetenv("EVENT_NOPOLL");
|
||||||
#endif
|
#endif
|
||||||
exit(client_main(argc, argv, flags));
|
|
||||||
|
imsg_compose(main_ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len);
|
||||||
|
|
||||||
|
main_set_signals();
|
||||||
|
|
||||||
|
events = EV_READ;
|
||||||
|
if (main_ibuf->w.queued > 0)
|
||||||
|
events |= EV_WRITE;
|
||||||
|
event_once(main_ibuf->fd, events, main_callback, shellcmd, NULL);
|
||||||
|
|
||||||
|
main_exitval = 0;
|
||||||
|
event_dispatch();
|
||||||
|
|
||||||
|
main_clear_signals();
|
||||||
|
|
||||||
|
client_main(); /* doesn't return */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main_set_signals(void)
|
||||||
|
{
|
||||||
|
struct sigaction sigact;
|
||||||
|
|
||||||
|
memset(&sigact, 0, sizeof sigact);
|
||||||
|
sigemptyset(&sigact.sa_mask);
|
||||||
|
sigact.sa_flags = SA_RESTART;
|
||||||
|
sigact.sa_handler = SIG_IGN;
|
||||||
|
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGUSR1, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
|
||||||
|
signal_set(&main_ev_sigterm, SIGTERM, main_signal, NULL);
|
||||||
|
signal_add(&main_ev_sigterm, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main_clear_signals(void)
|
||||||
|
{
|
||||||
|
struct sigaction sigact;
|
||||||
|
|
||||||
|
memset(&sigact, 0, sizeof sigact);
|
||||||
|
sigemptyset(&sigact.sa_mask);
|
||||||
|
sigact.sa_flags = SA_RESTART;
|
||||||
|
sigact.sa_handler = SIG_DFL;
|
||||||
|
if (sigaction(SIGINT, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGUSR1, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
|
||||||
|
event_del(&main_ev_sigterm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
|
void
|
||||||
|
main_signal(int sig, unused short events, unused void *data)
|
||||||
|
{
|
||||||
|
switch (sig) {
|
||||||
|
case SIGTERM:
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
|
void
|
||||||
|
main_callback(unused int fd, short events, void *data)
|
||||||
|
{
|
||||||
|
char *shellcmd = data;
|
||||||
|
|
||||||
|
if (events & EV_READ)
|
||||||
|
main_dispatch(shellcmd);
|
||||||
|
|
||||||
|
if (events & EV_WRITE) {
|
||||||
|
if (msgbuf_write(&main_ibuf->w) < 0)
|
||||||
|
fatalx("msgbuf_write failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
events = EV_READ;
|
||||||
|
if (main_ibuf->w.queued > 0)
|
||||||
|
events |= EV_WRITE;
|
||||||
|
event_once(main_ibuf->fd, events, main_callback, shellcmd, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
main_dispatch(const char *shellcmd)
|
||||||
|
{
|
||||||
|
struct imsg imsg;
|
||||||
|
ssize_t n, datalen;
|
||||||
|
struct msg_print_data printdata;
|
||||||
|
struct msg_shell_data shelldata;
|
||||||
|
|
||||||
|
if ((n = imsg_read(main_ibuf)) == -1 || n == 0)
|
||||||
|
fatalx("imsg_read failed");
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((n = imsg_get(main_ibuf, &imsg)) == -1)
|
||||||
|
fatalx("imsg_get failed");
|
||||||
|
if (n == 0)
|
||||||
|
return;
|
||||||
|
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
|
||||||
|
|
||||||
|
switch (imsg.hdr.type) {
|
||||||
|
case MSG_EXIT:
|
||||||
|
case MSG_SHUTDOWN:
|
||||||
|
if (datalen != 0)
|
||||||
|
fatalx("bad MSG_EXIT size");
|
||||||
|
|
||||||
|
exit(main_exitval);
|
||||||
|
case MSG_ERROR:
|
||||||
|
case MSG_PRINT:
|
||||||
|
if (datalen != sizeof printdata)
|
||||||
|
fatalx("bad MSG_PRINT size");
|
||||||
|
memcpy(&printdata, imsg.data, sizeof printdata);
|
||||||
|
printdata.msg[(sizeof printdata.msg) - 1] = '\0';
|
||||||
|
|
||||||
|
log_info("%s", printdata.msg);
|
||||||
|
if (imsg.hdr.type == MSG_ERROR)
|
||||||
|
main_exitval = 1;
|
||||||
|
break;
|
||||||
|
case MSG_READY:
|
||||||
|
if (datalen != 0)
|
||||||
|
fatalx("bad MSG_READY size");
|
||||||
|
|
||||||
|
event_loopexit(NULL); /* move to client_main() */
|
||||||
|
break;
|
||||||
|
case MSG_VERSION:
|
||||||
|
if (datalen != 0)
|
||||||
|
fatalx("bad MSG_VERSION size");
|
||||||
|
|
||||||
|
log_warnx("protocol version mismatch (client %u, "
|
||||||
|
"server %u)", PROTOCOL_VERSION, imsg.hdr.peerid);
|
||||||
|
exit(1);
|
||||||
|
case MSG_SHELL:
|
||||||
|
if (datalen != sizeof shelldata)
|
||||||
|
fatalx("bad MSG_SHELL size");
|
||||||
|
memcpy(&shelldata, imsg.data, sizeof shelldata);
|
||||||
|
shelldata.shell[(sizeof shelldata.shell) - 1] = '\0';
|
||||||
|
|
||||||
|
main_clear_signals();
|
||||||
|
|
||||||
|
shell_exec(shelldata.shell, shellcmd);
|
||||||
|
default:
|
||||||
|
fatalx("unexpected message");
|
||||||
|
}
|
||||||
|
|
||||||
|
imsg_free(&imsg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
253
tmux.h
253
tmux.h
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: tmux.h,v 1.591 2010-12-22 15:36:44 tcunha Exp $ */
|
/* $Id: tmux.h,v 1.547 2010-03-08 15:02:07 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define PROTOCOL_VERSION 6
|
#define PROTOCOL_VERSION 5
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
@@ -57,8 +58,8 @@ extern char **environ;
|
|||||||
/* Automatic name refresh interval, in milliseconds. */
|
/* Automatic name refresh interval, in milliseconds. */
|
||||||
#define NAME_INTERVAL 500
|
#define NAME_INTERVAL 500
|
||||||
|
|
||||||
/* Maximum data to buffer for output before suspending writing to a tty. */
|
/* Maximum data to buffer for output before suspending reading from panes. */
|
||||||
#define BACKOFF_THRESHOLD 16384
|
#define BACKOFF_THRESHOLD 1024
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Maximum sizes of strings in message data. Don't forget to bump
|
* Maximum sizes of strings in message data. Don't forget to bump
|
||||||
@@ -66,6 +67,7 @@ extern char **environ;
|
|||||||
*/
|
*/
|
||||||
#define COMMAND_LENGTH 2048 /* packed argv size */
|
#define COMMAND_LENGTH 2048 /* packed argv size */
|
||||||
#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
|
#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
|
||||||
|
#define PRINT_LENGTH 512 /* printed error/message size */
|
||||||
#define ENVIRON_LENGTH 1024 /* environment variable length */
|
#define ENVIRON_LENGTH 1024 /* environment variable length */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -108,10 +110,6 @@ extern char **environ;
|
|||||||
#define KEYC_SHIFT 0x8000
|
#define KEYC_SHIFT 0x8000
|
||||||
#define KEYC_PREFIX 0x10000
|
#define KEYC_PREFIX 0x10000
|
||||||
|
|
||||||
/* Mask to obtain key w/o modifiers */
|
|
||||||
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT|KEYC_PREFIX)
|
|
||||||
#define KEYC_MASK_KEY (~KEYC_MASK_MOD)
|
|
||||||
|
|
||||||
/* Other key codes. */
|
/* Other key codes. */
|
||||||
enum key_code {
|
enum key_code {
|
||||||
/* Mouse key. */
|
/* Mouse key. */
|
||||||
@@ -370,9 +368,7 @@ enum msgtype {
|
|||||||
MSG_ENVIRON,
|
MSG_ENVIRON,
|
||||||
MSG_UNLOCK,
|
MSG_UNLOCK,
|
||||||
MSG_LOCK,
|
MSG_LOCK,
|
||||||
MSG_SHELL,
|
MSG_SHELL
|
||||||
MSG_STDERR,
|
|
||||||
MSG_STDOUT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -380,6 +376,10 @@ enum msgtype {
|
|||||||
*
|
*
|
||||||
* Don't forget to bump PROTOCOL_VERSION if any of these change!
|
* Don't forget to bump PROTOCOL_VERSION if any of these change!
|
||||||
*/
|
*/
|
||||||
|
struct msg_print_data {
|
||||||
|
char msg[PRINT_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
struct msg_command_data {
|
struct msg_command_data {
|
||||||
pid_t pid; /* pid from $TMUX or -1 */
|
pid_t pid; /* pid from $TMUX or -1 */
|
||||||
u_int idx; /* index from $TMUX */
|
u_int idx; /* index from $TMUX */
|
||||||
@@ -411,10 +411,6 @@ struct msg_shell_data {
|
|||||||
char shell[MAXPATHLEN];
|
char shell[MAXPATHLEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msg_exit_data {
|
|
||||||
int retcode;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Mode key commands. */
|
/* Mode key commands. */
|
||||||
enum mode_key_cmd {
|
enum mode_key_cmd {
|
||||||
MODEKEY_NONE,
|
MODEKEY_NONE,
|
||||||
@@ -462,10 +458,6 @@ enum mode_key_cmd {
|
|||||||
MODEKEYCOPY_HALFPAGEUP,
|
MODEKEYCOPY_HALFPAGEUP,
|
||||||
MODEKEYCOPY_HISTORYBOTTOM,
|
MODEKEYCOPY_HISTORYBOTTOM,
|
||||||
MODEKEYCOPY_HISTORYTOP,
|
MODEKEYCOPY_HISTORYTOP,
|
||||||
MODEKEYCOPY_JUMP,
|
|
||||||
MODEKEYCOPY_JUMPAGAIN,
|
|
||||||
MODEKEYCOPY_JUMPREVERSE,
|
|
||||||
MODEKEYCOPY_JUMPBACK,
|
|
||||||
MODEKEYCOPY_LEFT,
|
MODEKEYCOPY_LEFT,
|
||||||
MODEKEYCOPY_MIDDLELINE,
|
MODEKEYCOPY_MIDDLELINE,
|
||||||
MODEKEYCOPY_NEXTPAGE,
|
MODEKEYCOPY_NEXTPAGE,
|
||||||
@@ -544,8 +536,6 @@ struct mode_key_table {
|
|||||||
#define MODE_KCURSOR 0x4
|
#define MODE_KCURSOR 0x4
|
||||||
#define MODE_KKEYPAD 0x8 /* set = application, clear = number */
|
#define MODE_KKEYPAD 0x8 /* set = application, clear = number */
|
||||||
#define MODE_MOUSE 0x10
|
#define MODE_MOUSE 0x10
|
||||||
#define MODE_MOUSEMOTION 0x20
|
|
||||||
#define MODE_WRAP 0x40 /* whether lines wrap */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A single UTF-8 character.
|
* A single UTF-8 character.
|
||||||
@@ -728,52 +718,59 @@ struct screen_write_ctx {
|
|||||||
#define screen_hsize(s) ((s)->grid->hsize)
|
#define screen_hsize(s) ((s)->grid->hsize)
|
||||||
#define screen_hlimit(s) ((s)->grid->hlimit)
|
#define screen_hlimit(s) ((s)->grid->hlimit)
|
||||||
|
|
||||||
|
/* Input parser sequence argument. */
|
||||||
|
struct input_arg {
|
||||||
|
u_char data[64];
|
||||||
|
size_t used;
|
||||||
|
};
|
||||||
|
|
||||||
/* Input parser context. */
|
/* Input parser context. */
|
||||||
struct input_ctx {
|
struct input_ctx {
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
|
|
||||||
struct grid_cell cell;
|
u_char *buf;
|
||||||
|
size_t len;
|
||||||
|
size_t off;
|
||||||
|
size_t was;
|
||||||
|
|
||||||
struct grid_cell old_cell;
|
struct grid_cell cell;
|
||||||
u_int old_cx;
|
|
||||||
u_int old_cy;
|
|
||||||
|
|
||||||
u_char interm_buf[4];
|
struct grid_cell saved_cell;
|
||||||
size_t interm_len;
|
u_int saved_cx;
|
||||||
|
u_int saved_cy;
|
||||||
|
|
||||||
u_char param_buf[64];
|
#define MAXSTRINGLEN 1024
|
||||||
size_t param_len;
|
u_char *string_buf;
|
||||||
|
size_t string_len;
|
||||||
|
int string_type;
|
||||||
|
#define STRING_SYSTEM 0
|
||||||
|
#define STRING_APPLICATION 1
|
||||||
|
#define STRING_NAME 2
|
||||||
|
|
||||||
u_char input_buf[256];
|
struct utf8_data utf8data;
|
||||||
size_t input_len;
|
|
||||||
|
|
||||||
int param_list[24]; /* -1 not present */
|
u_char intermediate;
|
||||||
u_int param_list_len;
|
void *(*state)(u_char, struct input_ctx *);
|
||||||
|
|
||||||
struct utf8_data utf8data;
|
u_char private;
|
||||||
|
ARRAY_DECL(, struct input_arg) args;
|
||||||
int ch;
|
|
||||||
int flags;
|
|
||||||
#define INPUT_DISCARD 0x1
|
|
||||||
|
|
||||||
const struct input_state *state;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Window mode. Windows can be in several modes and this is used to call the
|
* Window mode. Windows can be in several modes and this is used to call the
|
||||||
* right function to handle input and output.
|
* right function to handle input and output.
|
||||||
*/
|
*/
|
||||||
struct session;
|
struct client;
|
||||||
struct window;
|
struct window;
|
||||||
struct mouse_event;
|
struct mouse_event;
|
||||||
struct window_mode {
|
struct window_mode {
|
||||||
struct screen *(*init)(struct window_pane *);
|
struct screen *(*init)(struct window_pane *);
|
||||||
void (*free)(struct window_pane *);
|
void (*free)(struct window_pane *);
|
||||||
void (*resize)(struct window_pane *, u_int, u_int);
|
void (*resize)(struct window_pane *, u_int, u_int);
|
||||||
void (*key)(struct window_pane *, struct session *, int);
|
void (*key)(struct window_pane *, struct client *, int);
|
||||||
void (*mouse)(struct window_pane *,
|
void (*mouse)(struct window_pane *,
|
||||||
struct session *, struct mouse_event *);
|
struct client *, struct mouse_event *);
|
||||||
void (*timer)(struct window_pane *);
|
void (*timer)(struct window_pane *);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -828,10 +825,8 @@ TAILQ_HEAD(window_panes, window_pane);
|
|||||||
struct window {
|
struct window {
|
||||||
char *name;
|
char *name;
|
||||||
struct event name_timer;
|
struct event name_timer;
|
||||||
struct timeval silence_timer;
|
|
||||||
|
|
||||||
struct window_pane *active;
|
struct window_pane *active;
|
||||||
struct window_pane *last;
|
|
||||||
struct window_panes panes;
|
struct window_panes panes;
|
||||||
|
|
||||||
int lastlayout;
|
int lastlayout;
|
||||||
@@ -842,9 +837,10 @@ struct window {
|
|||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
#define WINDOW_BELL 0x1
|
#define WINDOW_BELL 0x1
|
||||||
#define WINDOW_ACTIVITY 0x2
|
#define WINDOW_HIDDEN 0x2
|
||||||
#define WINDOW_REDRAW 0x4
|
#define WINDOW_ACTIVITY 0x4
|
||||||
#define WINDOW_SILENCE 0x8
|
#define WINDOW_CONTENT 0x8
|
||||||
|
#define WINDOW_REDRAW 0x10
|
||||||
|
|
||||||
struct options options;
|
struct options options;
|
||||||
|
|
||||||
@@ -861,14 +857,6 @@ struct winlink {
|
|||||||
struct grid_cell status_cell;
|
struct grid_cell status_cell;
|
||||||
char *status_text;
|
char *status_text;
|
||||||
|
|
||||||
int flags;
|
|
||||||
#define WINLINK_BELL 0x1
|
|
||||||
#define WINLINK_ACTIVITY 0x2
|
|
||||||
#define WINLINK_CONTENT 0x4
|
|
||||||
#define WINLINK_SILENCE 0x8
|
|
||||||
#define WINLINK_ALERTFLAGS \
|
|
||||||
(WINLINK_BELL|WINLINK_ACTIVITY|WINLINK_CONTENT|WINLINK_SILENCE)
|
|
||||||
|
|
||||||
RB_ENTRY(winlink) entry;
|
RB_ENTRY(winlink) entry;
|
||||||
TAILQ_ENTRY(winlink) sentry;
|
TAILQ_ENTRY(winlink) sentry;
|
||||||
};
|
};
|
||||||
@@ -920,6 +908,13 @@ struct environ_entry {
|
|||||||
RB_HEAD(environ, environ_entry);
|
RB_HEAD(environ, environ_entry);
|
||||||
|
|
||||||
/* Client session. */
|
/* Client session. */
|
||||||
|
struct session_alert {
|
||||||
|
struct winlink *wl;
|
||||||
|
int type;
|
||||||
|
|
||||||
|
SLIST_ENTRY(session_alert) entry;
|
||||||
|
};
|
||||||
|
|
||||||
struct session_group {
|
struct session_group {
|
||||||
TAILQ_HEAD(, session) sessions;
|
TAILQ_HEAD(, session) sessions;
|
||||||
|
|
||||||
@@ -928,10 +923,7 @@ struct session_group {
|
|||||||
TAILQ_HEAD(session_groups, session_group);
|
TAILQ_HEAD(session_groups, session_group);
|
||||||
|
|
||||||
struct session {
|
struct session {
|
||||||
u_int idx;
|
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
char *cwd;
|
|
||||||
|
|
||||||
struct timeval creation_time;
|
struct timeval creation_time;
|
||||||
struct timeval activity_time;
|
struct timeval activity_time;
|
||||||
@@ -947,7 +939,10 @@ struct session {
|
|||||||
|
|
||||||
struct paste_stack buffers;
|
struct paste_stack buffers;
|
||||||
|
|
||||||
|
SLIST_HEAD(, session_alert) alerts;
|
||||||
|
|
||||||
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */
|
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */
|
||||||
|
#define SESSION_DEAD 0x2
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
struct termios *tio;
|
struct termios *tio;
|
||||||
@@ -957,10 +952,8 @@ struct session {
|
|||||||
int references;
|
int references;
|
||||||
|
|
||||||
TAILQ_ENTRY(session) gentry;
|
TAILQ_ENTRY(session) gentry;
|
||||||
RB_ENTRY(session) entry;
|
|
||||||
};
|
};
|
||||||
RB_HEAD(sessions, session);
|
ARRAY_DECL(sessions, struct session *);
|
||||||
ARRAY_DECL(sessionslist, struct session *);
|
|
||||||
|
|
||||||
/* TTY information. */
|
/* TTY information. */
|
||||||
struct tty_key {
|
struct tty_key {
|
||||||
@@ -977,8 +970,6 @@ struct tty_term {
|
|||||||
char *name;
|
char *name;
|
||||||
u_int references;
|
u_int references;
|
||||||
|
|
||||||
char acs[UCHAR_MAX + 1][2];
|
|
||||||
|
|
||||||
struct tty_code codes[NTTYCODE];
|
struct tty_code codes[NTTYCODE];
|
||||||
|
|
||||||
#define TERM_256COLOURS 0x1
|
#define TERM_256COLOURS 0x1
|
||||||
@@ -1016,13 +1007,14 @@ struct tty {
|
|||||||
|
|
||||||
struct grid_cell cell;
|
struct grid_cell cell;
|
||||||
|
|
||||||
|
u_char acs[UCHAR_MAX + 1];
|
||||||
|
|
||||||
#define TTY_NOCURSOR 0x1
|
#define TTY_NOCURSOR 0x1
|
||||||
#define TTY_FREEZE 0x2
|
#define TTY_FREEZE 0x2
|
||||||
#define TTY_ESCAPE 0x4
|
#define TTY_ESCAPE 0x4
|
||||||
#define TTY_UTF8 0x8
|
#define TTY_UTF8 0x8
|
||||||
#define TTY_STARTED 0x10
|
#define TTY_STARTED 0x10
|
||||||
#define TTY_OPENED 0x20
|
#define TTY_OPENED 0x20
|
||||||
#define TTY_BACKOFF 0x40
|
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
int term_flags;
|
int term_flags;
|
||||||
@@ -1060,23 +1052,9 @@ struct tty_ctx {
|
|||||||
u_int last_width;
|
u_int last_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* xterm mouse mode is fairly silly. Buttons are in the bottom two
|
|
||||||
* bits: 0 button 1; 1 button 2; 2 button 3; 3 buttons released.
|
|
||||||
*
|
|
||||||
* Bit 3 is shift; bit 4 is meta; bit 5 control.
|
|
||||||
*
|
|
||||||
* Bit 6 is added for mouse buttons 4 and 5.
|
|
||||||
*/
|
|
||||||
/* Mouse input. */
|
/* Mouse input. */
|
||||||
struct mouse_event {
|
struct mouse_event {
|
||||||
u_char b;
|
u_char b;
|
||||||
#define MOUSE_1 0
|
|
||||||
#define MOUSE_2 1
|
|
||||||
#define MOUSE_3 2
|
|
||||||
#define MOUSE_UP 3
|
|
||||||
#define MOUSE_BUTTON 3
|
|
||||||
#define MOUSE_45 64
|
|
||||||
u_char x;
|
u_char x;
|
||||||
u_char y;
|
u_char y;
|
||||||
};
|
};
|
||||||
@@ -1091,7 +1069,6 @@ struct message_entry {
|
|||||||
struct client {
|
struct client {
|
||||||
struct imsgbuf ibuf;
|
struct imsgbuf ibuf;
|
||||||
struct event event;
|
struct event event;
|
||||||
int retcode;
|
|
||||||
|
|
||||||
struct timeval creation_time;
|
struct timeval creation_time;
|
||||||
struct timeval activity_time;
|
struct timeval activity_time;
|
||||||
@@ -1102,18 +1079,6 @@ struct client {
|
|||||||
char *cwd;
|
char *cwd;
|
||||||
|
|
||||||
struct tty tty;
|
struct tty tty;
|
||||||
|
|
||||||
int stdin_fd;
|
|
||||||
void *stdin_data;
|
|
||||||
void (*stdin_callback)(struct client *, void *);
|
|
||||||
struct bufferevent *stdin_event;
|
|
||||||
|
|
||||||
int stdout_fd;
|
|
||||||
struct bufferevent *stdout_event;
|
|
||||||
|
|
||||||
int stderr_fd;
|
|
||||||
struct bufferevent *stderr_event;
|
|
||||||
|
|
||||||
struct event repeat_timer;
|
struct event repeat_timer;
|
||||||
|
|
||||||
struct timeval status_timer;
|
struct timeval status_timer;
|
||||||
@@ -1122,7 +1087,7 @@ struct client {
|
|||||||
|
|
||||||
#define CLIENT_TERMINAL 0x1
|
#define CLIENT_TERMINAL 0x1
|
||||||
#define CLIENT_PREFIX 0x2
|
#define CLIENT_PREFIX 0x2
|
||||||
#define CLIENT_EXIT 0x4
|
#define CLIENT_MOUSE 0x4
|
||||||
#define CLIENT_REDRAW 0x8
|
#define CLIENT_REDRAW 0x8
|
||||||
#define CLIENT_STATUS 0x10
|
#define CLIENT_STATUS 0x10
|
||||||
#define CLIENT_REPEAT 0x20 /* allow command to repeat within repeat time */
|
#define CLIENT_REPEAT 0x20 /* allow command to repeat within repeat time */
|
||||||
@@ -1132,8 +1097,6 @@ struct client {
|
|||||||
#define CLIENT_DEAD 0x200
|
#define CLIENT_DEAD 0x200
|
||||||
#define CLIENT_BORDERS 0x400
|
#define CLIENT_BORDERS 0x400
|
||||||
#define CLIENT_READONLY 0x800
|
#define CLIENT_READONLY 0x800
|
||||||
#define CLIENT_BACKOFF 0x1000
|
|
||||||
#define CLIENT_REDRAWWINDOW 0x2000
|
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
struct event identify_timer;
|
struct event identify_timer;
|
||||||
@@ -1148,15 +1111,16 @@ struct client {
|
|||||||
int (*prompt_callbackfn)(void *, const char *);
|
int (*prompt_callbackfn)(void *, const char *);
|
||||||
void (*prompt_freefn)(void *);
|
void (*prompt_freefn)(void *);
|
||||||
void *prompt_data;
|
void *prompt_data;
|
||||||
u_int prompt_hindex;
|
|
||||||
|
|
||||||
#define PROMPT_SINGLE 0x1
|
#define PROMPT_SINGLE 0x1
|
||||||
int prompt_flags;
|
int prompt_flags;
|
||||||
|
|
||||||
|
u_int prompt_hindex;
|
||||||
|
ARRAY_DECL(, char *) prompt_hdata;
|
||||||
|
|
||||||
struct mode_key_data prompt_mdata;
|
struct mode_key_data prompt_mdata;
|
||||||
|
|
||||||
struct session *session;
|
struct session *session;
|
||||||
struct session *last_session;
|
|
||||||
|
|
||||||
int references;
|
int references;
|
||||||
};
|
};
|
||||||
@@ -1197,10 +1161,7 @@ struct cmd {
|
|||||||
|
|
||||||
TAILQ_ENTRY(cmd) qentry;
|
TAILQ_ENTRY(cmd) qentry;
|
||||||
};
|
};
|
||||||
struct cmd_list {
|
TAILQ_HEAD(cmd_list, cmd);
|
||||||
int references;
|
|
||||||
TAILQ_HEAD(, cmd) list;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cmd_entry {
|
struct cmd_entry {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -1293,25 +1254,20 @@ extern struct options global_options;
|
|||||||
extern struct options global_s_options;
|
extern struct options global_s_options;
|
||||||
extern struct options global_w_options;
|
extern struct options global_w_options;
|
||||||
extern struct environ global_environ;
|
extern struct environ global_environ;
|
||||||
extern struct event_base *ev_base;
|
|
||||||
extern char *cfg_file;
|
extern char *cfg_file;
|
||||||
extern char *shell_cmd;
|
|
||||||
extern int debug_level;
|
extern int debug_level;
|
||||||
|
extern int be_quiet;
|
||||||
extern time_t start_time;
|
extern time_t start_time;
|
||||||
extern char socket_path[MAXPATHLEN];
|
extern char *socket_path;
|
||||||
extern int login_shell;
|
extern int login_shell;
|
||||||
extern char *environ_path;
|
|
||||||
extern pid_t environ_pid;
|
|
||||||
extern u_int environ_idx;
|
|
||||||
void logfile(const char *);
|
void logfile(const char *);
|
||||||
const char *getshell(void);
|
const char *getshell(void);
|
||||||
int checkshell(const char *);
|
int checkshell(const char *);
|
||||||
int areshell(const char *);
|
int areshell(const char *);
|
||||||
__dead void shell_exec(const char *, const char *);
|
|
||||||
|
|
||||||
/* cfg.c */
|
/* cfg.c */
|
||||||
extern int cfg_finished;
|
extern int cfg_finished;
|
||||||
extern struct causelist cfg_causes;
|
struct causelist cfg_causes;
|
||||||
void printflike2 cfg_add_cause(struct causelist *, const char *, ...);
|
void printflike2 cfg_add_cause(struct causelist *, const char *, ...);
|
||||||
int load_cfg(const char *, struct cmd_ctx *, struct causelist *);
|
int load_cfg(const char *, struct cmd_ctx *, struct causelist *);
|
||||||
|
|
||||||
@@ -1376,10 +1332,10 @@ void environ_set(struct environ *, const char *, const char *);
|
|||||||
void environ_put(struct environ *, const char *);
|
void environ_put(struct environ *, const char *);
|
||||||
void environ_unset(struct environ *, const char *);
|
void environ_unset(struct environ *, const char *);
|
||||||
void environ_update(const char *, struct environ *, struct environ *);
|
void environ_update(const char *, struct environ *, struct environ *);
|
||||||
void environ_push(struct environ *);
|
|
||||||
|
|
||||||
/* tty.c */
|
/* tty.c */
|
||||||
void tty_raw(struct tty *, const char *);
|
void tty_raw(struct tty *, const char *);
|
||||||
|
u_char tty_get_acs(struct tty *, u_char);
|
||||||
void tty_attributes(struct tty *, const struct grid_cell *);
|
void tty_attributes(struct tty *, const struct grid_cell *);
|
||||||
void tty_reset(struct tty *);
|
void tty_reset(struct tty *);
|
||||||
void tty_region_pane(struct tty *, const struct tty_ctx *, u_int, u_int);
|
void tty_region_pane(struct tty *, const struct tty_ctx *, u_int, u_int);
|
||||||
@@ -1393,7 +1349,7 @@ void tty_puts(struct tty *, const char *);
|
|||||||
void tty_putc(struct tty *, u_char);
|
void tty_putc(struct tty *, u_char);
|
||||||
void tty_pututf8(struct tty *, const struct grid_utf8 *);
|
void tty_pututf8(struct tty *, const struct grid_utf8 *);
|
||||||
void tty_init(struct tty *, int, char *);
|
void tty_init(struct tty *, int, char *);
|
||||||
int tty_resize(struct tty *);
|
void tty_resize(struct tty *);
|
||||||
void tty_start_tty(struct tty *);
|
void tty_start_tty(struct tty *);
|
||||||
void tty_stop_tty(struct tty *);
|
void tty_stop_tty(struct tty *);
|
||||||
void tty_set_title(struct tty *, const char *);
|
void tty_set_title(struct tty *, const char *);
|
||||||
@@ -1433,9 +1389,6 @@ const char *tty_term_string2(
|
|||||||
int tty_term_number(struct tty_term *, enum tty_code_code);
|
int tty_term_number(struct tty_term *, enum tty_code_code);
|
||||||
int tty_term_flag(struct tty_term *, enum tty_code_code);
|
int tty_term_flag(struct tty_term *, enum tty_code_code);
|
||||||
|
|
||||||
/* tty-acs.c */
|
|
||||||
const char *tty_acs_get(struct tty *, u_char);
|
|
||||||
|
|
||||||
/* tty-keys.c */
|
/* tty-keys.c */
|
||||||
void tty_keys_init(struct tty *);
|
void tty_keys_init(struct tty *);
|
||||||
void tty_keys_free(struct tty *);
|
void tty_keys_free(struct tty *);
|
||||||
@@ -1451,7 +1404,6 @@ int paste_free_top(struct paste_stack *);
|
|||||||
int paste_free_index(struct paste_stack *, u_int);
|
int paste_free_index(struct paste_stack *, u_int);
|
||||||
void paste_add(struct paste_stack *, char *, size_t, u_int);
|
void paste_add(struct paste_stack *, char *, size_t, u_int);
|
||||||
int paste_replace(struct paste_stack *, u_int, char *, size_t);
|
int paste_replace(struct paste_stack *, u_int, char *, size_t);
|
||||||
char *paste_print(struct paste_buffer *, size_t);
|
|
||||||
|
|
||||||
/* clock.c */
|
/* clock.c */
|
||||||
extern const char clock_table[14][5][5];
|
extern const char clock_table[14][5][5];
|
||||||
@@ -1467,7 +1419,6 @@ const char *cmd_set_option_print(
|
|||||||
/* cmd.c */
|
/* cmd.c */
|
||||||
int cmd_pack_argv(int, char **, char *, size_t);
|
int cmd_pack_argv(int, char **, char *, size_t);
|
||||||
int cmd_unpack_argv(char *, size_t, int, char ***);
|
int cmd_unpack_argv(char *, size_t, int, char ***);
|
||||||
char **cmd_copy_argv(int, char **);
|
|
||||||
void cmd_free_argv(int, char **);
|
void cmd_free_argv(int, char **);
|
||||||
struct cmd *cmd_parse(int, char **, char **);
|
struct cmd *cmd_parse(int, char **, char **);
|
||||||
int cmd_exec(struct cmd *, struct cmd_ctx *);
|
int cmd_exec(struct cmd *, struct cmd_ctx *);
|
||||||
@@ -1489,7 +1440,6 @@ extern const struct cmd_entry cmd_attach_session_entry;
|
|||||||
extern const struct cmd_entry cmd_bind_key_entry;
|
extern const struct cmd_entry cmd_bind_key_entry;
|
||||||
extern const struct cmd_entry cmd_break_pane_entry;
|
extern const struct cmd_entry cmd_break_pane_entry;
|
||||||
extern const struct cmd_entry cmd_capture_pane_entry;
|
extern const struct cmd_entry cmd_capture_pane_entry;
|
||||||
extern const struct cmd_entry cmd_choose_buffer_entry;
|
|
||||||
extern const struct cmd_entry cmd_choose_client_entry;
|
extern const struct cmd_entry cmd_choose_client_entry;
|
||||||
extern const struct cmd_entry cmd_choose_session_entry;
|
extern const struct cmd_entry cmd_choose_session_entry;
|
||||||
extern const struct cmd_entry cmd_choose_window_entry;
|
extern const struct cmd_entry cmd_choose_window_entry;
|
||||||
@@ -1512,7 +1462,6 @@ extern const struct cmd_entry cmd_kill_pane_entry;
|
|||||||
extern const struct cmd_entry cmd_kill_server_entry;
|
extern const struct cmd_entry cmd_kill_server_entry;
|
||||||
extern const struct cmd_entry cmd_kill_session_entry;
|
extern const struct cmd_entry cmd_kill_session_entry;
|
||||||
extern const struct cmd_entry cmd_kill_window_entry;
|
extern const struct cmd_entry cmd_kill_window_entry;
|
||||||
extern const struct cmd_entry cmd_last_pane_entry;
|
|
||||||
extern const struct cmd_entry cmd_last_window_entry;
|
extern const struct cmd_entry cmd_last_window_entry;
|
||||||
extern const struct cmd_entry cmd_link_window_entry;
|
extern const struct cmd_entry cmd_link_window_entry;
|
||||||
extern const struct cmd_entry cmd_list_buffers_entry;
|
extern const struct cmd_entry cmd_list_buffers_entry;
|
||||||
@@ -1545,6 +1494,7 @@ extern const struct cmd_entry cmd_run_shell_entry;
|
|||||||
extern const struct cmd_entry cmd_save_buffer_entry;
|
extern const struct cmd_entry cmd_save_buffer_entry;
|
||||||
extern const struct cmd_entry cmd_select_layout_entry;
|
extern const struct cmd_entry cmd_select_layout_entry;
|
||||||
extern const struct cmd_entry cmd_select_pane_entry;
|
extern const struct cmd_entry cmd_select_pane_entry;
|
||||||
|
extern const struct cmd_entry cmd_select_prompt_entry;
|
||||||
extern const struct cmd_entry cmd_select_window_entry;
|
extern const struct cmd_entry cmd_select_window_entry;
|
||||||
extern const struct cmd_entry cmd_send_keys_entry;
|
extern const struct cmd_entry cmd_send_keys_entry;
|
||||||
extern const struct cmd_entry cmd_send_prefix_entry;
|
extern const struct cmd_entry cmd_send_prefix_entry;
|
||||||
@@ -1608,7 +1558,8 @@ void cmd_buffer_free(struct cmd *);
|
|||||||
size_t cmd_buffer_print(struct cmd *, char *, size_t);
|
size_t cmd_buffer_print(struct cmd *, char *, size_t);
|
||||||
|
|
||||||
/* client.c */
|
/* client.c */
|
||||||
int client_main(int, char **, int);
|
struct imsgbuf *client_init(char *, int, int);
|
||||||
|
__dead void client_main(void);
|
||||||
|
|
||||||
/* key-bindings.c */
|
/* key-bindings.c */
|
||||||
extern struct key_bindings key_bindings;
|
extern struct key_bindings key_bindings;
|
||||||
@@ -1631,7 +1582,9 @@ const char *key_string_lookup_key(int);
|
|||||||
/* server.c */
|
/* server.c */
|
||||||
extern struct clients clients;
|
extern struct clients clients;
|
||||||
extern struct clients dead_clients;
|
extern struct clients dead_clients;
|
||||||
int server_start(void);
|
int server_start(char *);
|
||||||
|
void server_signal_set(void);
|
||||||
|
void server_signal_clear(void);
|
||||||
void server_update_socket(void);
|
void server_update_socket(void);
|
||||||
|
|
||||||
/* server-client.c */
|
/* server-client.c */
|
||||||
@@ -1646,6 +1599,7 @@ void server_window_loop(void);
|
|||||||
|
|
||||||
/* server-fn.c */
|
/* server-fn.c */
|
||||||
void server_fill_environ(struct session *, struct environ *);
|
void server_fill_environ(struct session *, struct environ *);
|
||||||
|
void server_write_error(struct client *, const char *);
|
||||||
void server_write_client(
|
void server_write_client(
|
||||||
struct client *, enum msgtype, const void *, size_t);
|
struct client *, enum msgtype, const void *, size_t);
|
||||||
void server_write_session(
|
void server_write_session(
|
||||||
@@ -1670,7 +1624,6 @@ void server_unlink_window(struct session *, struct winlink *);
|
|||||||
void server_destroy_pane(struct window_pane *);
|
void server_destroy_pane(struct window_pane *);
|
||||||
void server_destroy_session_group(struct session *);
|
void server_destroy_session_group(struct session *);
|
||||||
void server_destroy_session(struct session *);
|
void server_destroy_session(struct session *);
|
||||||
void server_check_unattached (void);
|
|
||||||
void server_set_identify(struct client *);
|
void server_set_identify(struct client *);
|
||||||
void server_clear_identify(struct client *);
|
void server_clear_identify(struct client *);
|
||||||
void server_update_event(struct client *);
|
void server_update_event(struct client *);
|
||||||
@@ -1836,7 +1789,9 @@ int screen_check_selection(struct screen *, u_int, u_int);
|
|||||||
|
|
||||||
/* window.c */
|
/* window.c */
|
||||||
extern struct windows windows;
|
extern struct windows windows;
|
||||||
|
int window_cmp(struct window *, struct window *);
|
||||||
int winlink_cmp(struct winlink *, struct winlink *);
|
int winlink_cmp(struct winlink *, struct winlink *);
|
||||||
|
RB_PROTOTYPE(windows, window, entry, window_cmp);
|
||||||
RB_PROTOTYPE(winlinks, winlink, entry, winlink_cmp);
|
RB_PROTOTYPE(winlinks, winlink, entry, winlink_cmp);
|
||||||
struct winlink *winlink_find_by_index(struct winlinks *, int);
|
struct winlink *winlink_find_by_index(struct winlinks *, int);
|
||||||
struct winlink *winlink_find_by_window(struct winlinks *, struct window *);
|
struct winlink *winlink_find_by_window(struct winlinks *, struct window *);
|
||||||
@@ -1846,10 +1801,6 @@ struct winlink *winlink_add(struct winlinks *, struct window *, int);
|
|||||||
void winlink_remove(struct winlinks *, struct winlink *);
|
void winlink_remove(struct winlinks *, struct winlink *);
|
||||||
struct winlink *winlink_next(struct winlink *);
|
struct winlink *winlink_next(struct winlink *);
|
||||||
struct winlink *winlink_previous(struct winlink *);
|
struct winlink *winlink_previous(struct winlink *);
|
||||||
struct winlink *winlink_next_by_number(struct winlink *, struct session *,
|
|
||||||
int);
|
|
||||||
struct winlink *winlink_previous_by_number(struct winlink *, struct session *,
|
|
||||||
int);
|
|
||||||
void winlink_stack_push(struct winlink_stack *, struct winlink *);
|
void winlink_stack_push(struct winlink_stack *, struct winlink *);
|
||||||
void winlink_stack_remove(struct winlink_stack *, struct winlink *);
|
void winlink_stack_remove(struct winlink_stack *, struct winlink *);
|
||||||
int window_index(struct window *, u_int *);
|
int window_index(struct window *, u_int *);
|
||||||
@@ -1864,10 +1815,6 @@ struct window_pane *window_add_pane(struct window *, u_int);
|
|||||||
void window_resize(struct window *, u_int, u_int);
|
void window_resize(struct window *, u_int, u_int);
|
||||||
void window_remove_pane(struct window *, struct window_pane *);
|
void window_remove_pane(struct window *, struct window_pane *);
|
||||||
struct window_pane *window_pane_at_index(struct window *, u_int);
|
struct window_pane *window_pane_at_index(struct window *, u_int);
|
||||||
struct window_pane *window_pane_next_by_number(struct window *,
|
|
||||||
struct window_pane *, u_int);
|
|
||||||
struct window_pane *window_pane_previous_by_number(struct window *,
|
|
||||||
struct window_pane *, u_int);
|
|
||||||
u_int window_pane_index(struct window *, struct window_pane *);
|
u_int window_pane_index(struct window *, struct window_pane *);
|
||||||
u_int window_count_panes(struct window *);
|
u_int window_count_panes(struct window *);
|
||||||
void window_destroy_panes(struct window *);
|
void window_destroy_panes(struct window *);
|
||||||
@@ -1877,30 +1824,21 @@ int window_pane_spawn(struct window_pane *, const char *,
|
|||||||
const char *, const char *, struct environ *,
|
const char *, const char *, struct environ *,
|
||||||
struct termios *, char **);
|
struct termios *, char **);
|
||||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||||
void window_pane_alternate_on(
|
|
||||||
struct window_pane *, struct grid_cell *);
|
|
||||||
void window_pane_alternate_off(
|
|
||||||
struct window_pane *, struct grid_cell *);
|
|
||||||
int window_pane_set_mode(
|
int window_pane_set_mode(
|
||||||
struct window_pane *, const struct window_mode *);
|
struct window_pane *, const struct window_mode *);
|
||||||
void window_pane_reset_mode(struct window_pane *);
|
void window_pane_reset_mode(struct window_pane *);
|
||||||
void window_pane_key(struct window_pane *, struct session *, int);
|
void window_pane_parse(struct window_pane *);
|
||||||
|
void window_pane_key(struct window_pane *, struct client *, int);
|
||||||
void window_pane_mouse(struct window_pane *,
|
void window_pane_mouse(struct window_pane *,
|
||||||
struct session *, struct mouse_event *);
|
struct client *, struct mouse_event *);
|
||||||
int window_pane_visible(struct window_pane *);
|
int window_pane_visible(struct window_pane *);
|
||||||
char *window_pane_search(
|
char *window_pane_search(
|
||||||
struct window_pane *, const char *, u_int *);
|
struct window_pane *, const char *, u_int *);
|
||||||
struct window_pane *window_pane_find_up(struct window_pane *);
|
|
||||||
struct window_pane *window_pane_find_down(struct window_pane *);
|
|
||||||
struct window_pane *window_pane_find_left(struct window_pane *);
|
|
||||||
struct window_pane *window_pane_find_right(struct window_pane *);
|
|
||||||
|
|
||||||
/* layout.c */
|
/* layout.c */
|
||||||
u_int layout_count_cells(struct layout_cell *);
|
|
||||||
struct layout_cell *layout_create_cell(struct layout_cell *);
|
struct layout_cell *layout_create_cell(struct layout_cell *);
|
||||||
void layout_free_cell(struct layout_cell *);
|
void layout_free_cell(struct layout_cell *);
|
||||||
void layout_print_cell(struct layout_cell *, const char *, u_int);
|
void layout_print_cell(struct layout_cell *, const char *, u_int);
|
||||||
void layout_destroy_cell(struct layout_cell *, struct layout_cell **);
|
|
||||||
void layout_set_size(
|
void layout_set_size(
|
||||||
struct layout_cell *, u_int, u_int, u_int, u_int);
|
struct layout_cell *, u_int, u_int, u_int, u_int);
|
||||||
void layout_make_leaf(
|
void layout_make_leaf(
|
||||||
@@ -1921,10 +1859,6 @@ struct layout_cell *layout_split_pane(
|
|||||||
struct window_pane *, enum layout_type, int);
|
struct window_pane *, enum layout_type, int);
|
||||||
void layout_close_pane(struct window_pane *);
|
void layout_close_pane(struct window_pane *);
|
||||||
|
|
||||||
/* layout-custom.c */
|
|
||||||
char *layout_dump(struct window *);
|
|
||||||
int layout_parse(struct window *, const char *);
|
|
||||||
|
|
||||||
/* layout-set.c */
|
/* layout-set.c */
|
||||||
const char *layout_set_name(u_int);
|
const char *layout_set_name(u_int);
|
||||||
int layout_set_lookup(const char *);
|
int layout_set_lookup(const char *);
|
||||||
@@ -1935,19 +1869,19 @@ void layout_set_active_changed(struct window *);
|
|||||||
|
|
||||||
/* layout-string.c */
|
/* layout-string.c */
|
||||||
struct layout_cell *layout_find_string(struct window *, const char *);
|
struct layout_cell *layout_find_string(struct window *, const char *);
|
||||||
struct layout_cell *layout_find_bottomright(struct layout_cell *);
|
|
||||||
|
|
||||||
/* window-clock.c */
|
/* window-clock.c */
|
||||||
extern const struct window_mode window_clock_mode;
|
extern const struct window_mode window_clock_mode;
|
||||||
|
|
||||||
/* window-copy.c */
|
/* window-copy.c */
|
||||||
extern const struct window_mode window_copy_mode;
|
extern const struct window_mode window_copy_mode;
|
||||||
void window_copy_init_from_pane(struct window_pane *);
|
|
||||||
void window_copy_init_for_output(struct window_pane *);
|
|
||||||
void window_copy_add(struct window_pane *, const char *, ...);
|
|
||||||
void window_copy_vadd(struct window_pane *, const char *, va_list);
|
|
||||||
void window_copy_pageup(struct window_pane *);
|
void window_copy_pageup(struct window_pane *);
|
||||||
|
|
||||||
|
/* window-more.c */
|
||||||
|
extern const struct window_mode window_more_mode;
|
||||||
|
void window_more_add(struct window_pane *, const char *, ...);
|
||||||
|
void window_more_vadd(struct window_pane *, const char *, va_list);
|
||||||
|
|
||||||
/* window-choose.c */
|
/* window-choose.c */
|
||||||
extern const struct window_mode window_choose_mode;
|
extern const struct window_mode window_choose_mode;
|
||||||
void window_choose_vadd(
|
void window_choose_vadd(
|
||||||
@@ -1961,31 +1895,26 @@ void window_choose_ready(struct window_pane *,
|
|||||||
void queue_window_name(struct window *);
|
void queue_window_name(struct window *);
|
||||||
char *default_window_name(struct window *);
|
char *default_window_name(struct window *);
|
||||||
|
|
||||||
/* signal.c */
|
|
||||||
void set_signals(void(*)(int, short, void *));
|
|
||||||
void clear_signals(int);
|
|
||||||
|
|
||||||
/* session.c */
|
/* session.c */
|
||||||
extern struct sessions sessions;
|
extern struct sessions sessions;
|
||||||
extern struct sessions dead_sessions;
|
extern struct sessions dead_sessions;
|
||||||
extern struct session_groups session_groups;
|
extern struct session_groups session_groups;
|
||||||
int session_cmp(struct session *, struct session *);
|
void session_alert_add(struct session *, struct window *, int);
|
||||||
RB_PROTOTYPE(sessions, session, entry, session_cmp);
|
void session_alert_cancel(struct session *, struct winlink *);
|
||||||
int session_alive(struct session *);
|
int session_alert_has(struct session *, struct winlink *, int);
|
||||||
|
int session_alert_has_window(struct session *, struct window *, int);
|
||||||
struct session *session_find(const char *);
|
struct session *session_find(const char *);
|
||||||
struct session *session_find_by_index(u_int);
|
|
||||||
struct session *session_create(const char *, const char *, const char *,
|
struct session *session_create(const char *, const char *, const char *,
|
||||||
struct environ *, struct termios *, int, u_int, u_int,
|
struct environ *, struct termios *, int, u_int, u_int,
|
||||||
char **);
|
char **);
|
||||||
void session_destroy(struct session *);
|
void session_destroy(struct session *);
|
||||||
struct session *session_next_session(struct session *);
|
int session_index(struct session *, u_int *);
|
||||||
struct session *session_previous_session(struct session *);
|
|
||||||
struct winlink *session_new(struct session *,
|
struct winlink *session_new(struct session *,
|
||||||
const char *, const char *, const char *, int, char **);
|
const char *, const char *, const char *, int, char **);
|
||||||
struct winlink *session_attach(
|
struct winlink *session_attach(
|
||||||
struct session *, struct window *, int, char **);
|
struct session *, struct window *, int, char **);
|
||||||
int session_detach(struct session *, struct winlink *);
|
int session_detach(struct session *, struct winlink *);
|
||||||
struct winlink* session_has(struct session *, struct window *);
|
int session_has(struct session *, struct window *);
|
||||||
int session_next(struct session *, int);
|
int session_next(struct session *, int);
|
||||||
int session_previous(struct session *, int);
|
int session_previous(struct session *, int);
|
||||||
int session_select(struct session *, int);
|
int session_select(struct session *, int);
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
# $Id: check-compat.sh,v 1.1 2010-10-24 00:42:04 tcunha Exp $
|
|
||||||
|
|
||||||
grep "#include" compat.h|while read line; do
|
|
||||||
grep "$line" *.[ch] compat/*.[ch]
|
|
||||||
done
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# $Id: dist.mk,v 1.11 2010-12-27 21:32:16 tcunha Exp $
|
# $Id: dist.mk,v 1.8 2010-03-10 15:16:19 tcunha Exp $
|
||||||
|
|
||||||
VERSION= 1.4
|
VERSION= 1.2
|
||||||
|
|
||||||
DISTDIR= tmux-${VERSION}
|
DISTDIR= tmux-${VERSION}
|
||||||
DISTFILES= *.[ch] Makefile GNUmakefile configure tmux.1 \
|
DISTFILES= *.[ch] Makefile GNUmakefile configure tmux.1 \
|
||||||
@@ -20,7 +20,7 @@ dist:
|
|||||||
|
|
||||||
upload-index.html: update-index.html
|
upload-index.html: update-index.html
|
||||||
scp www/index.html www/main.css www/images/*.png \
|
scp www/index.html www/main.css www/images/*.png \
|
||||||
${USER},tmux@web.sf.net:/home/groups/t/tm/tmux/htdocs
|
nicm,tmux@web.sf.net:/home/groups/t/tm/tmux/htdocs
|
||||||
rm -f www/index.html www/images/small-*
|
rm -f www/index.html www/images/small-*
|
||||||
|
|
||||||
update-index.html:
|
update-index.html:
|
||||||
|
|||||||
31
tools/fuzz.c
31
tools/fuzz.c
@@ -1,31 +0,0 @@
|
|||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
int
|
|
||||||
main(void)
|
|
||||||
{
|
|
||||||
time_t t;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
|
||||||
|
|
||||||
t = time(NULL);
|
|
||||||
srandom((u_int) t);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
putchar('\033');
|
|
||||||
|
|
||||||
for (i = 0; i < random() % 25; i++) {
|
|
||||||
if (i > 22)
|
|
||||||
putchar(';');
|
|
||||||
else
|
|
||||||
putchar(random() % 256);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* usleep(100); */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
97
tty-acs.c
97
tty-acs.c
@@ -1,97 +0,0 @@
|
|||||||
/* $Id: tty-acs.c,v 1.1 2010-09-18 15:43:53 tcunha Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
int tty_acs_cmp(const void *, const void *);
|
|
||||||
|
|
||||||
/* Table mapping ACS entries to UTF-8. */
|
|
||||||
struct tty_acs_entry {
|
|
||||||
u_char key;
|
|
||||||
const char *string;
|
|
||||||
};
|
|
||||||
const struct tty_acs_entry tty_acs_table[] = {
|
|
||||||
{ '+', "\342\206\222" },
|
|
||||||
{ ',', "\342\206\220" },
|
|
||||||
{ '-', "\342\206\221" },
|
|
||||||
{ '.', "\342\206\223" },
|
|
||||||
{ '0', "\342\226\256" },
|
|
||||||
{ '`', "\342\227\206" },
|
|
||||||
{ 'a', "\342\226\222" },
|
|
||||||
{ 'f', "\302\260" },
|
|
||||||
{ 'g', "\302\261" },
|
|
||||||
{ 'h', "\342\226\222" },
|
|
||||||
{ 'i', "\342\230\203" },
|
|
||||||
{ 'j', "\342\224\230" },
|
|
||||||
{ 'k', "\342\224\220" },
|
|
||||||
{ 'l', "\342\224\214" },
|
|
||||||
{ 'm', "\342\224\224" },
|
|
||||||
{ 'n', "\342\224\274" },
|
|
||||||
{ 'o', "\342\216\272" },
|
|
||||||
{ 'p', "\342\216\273" },
|
|
||||||
{ 'q', "\342\224\200" },
|
|
||||||
{ 'r', "\342\216\274" },
|
|
||||||
{ 's', "\342\216\275" },
|
|
||||||
{ 't', "\342\224\234" },
|
|
||||||
{ 'u', "\342\224\244" },
|
|
||||||
{ 'v', "\342\224\264" },
|
|
||||||
{ 'w', "\342\224\254" },
|
|
||||||
{ 'x', "\342\224\202" },
|
|
||||||
{ 'y', "\342\211\244" },
|
|
||||||
{ 'z', "\342\211\245" },
|
|
||||||
{ '{', "\317\200" },
|
|
||||||
{ '|', "\342\211\240" },
|
|
||||||
{ '}', "\302\243" },
|
|
||||||
{ '~', "\302\267" }
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
tty_acs_cmp(const void *key, const void *value)
|
|
||||||
{
|
|
||||||
const struct tty_acs_entry *entry = value;
|
|
||||||
u_char ch;
|
|
||||||
|
|
||||||
ch = *(u_char *) key;
|
|
||||||
return (ch - entry->key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve ACS to output as a string. */
|
|
||||||
const char *
|
|
||||||
tty_acs_get(struct tty *tty, u_char ch)
|
|
||||||
{
|
|
||||||
struct tty_acs_entry *entry;
|
|
||||||
|
|
||||||
/* If not a UTF-8 terminal, use the ACS set. */
|
|
||||||
if (!(tty->flags & TTY_UTF8)) {
|
|
||||||
if (tty->term->acs[ch][0] == '\0')
|
|
||||||
return (NULL);
|
|
||||||
return (&tty->term->acs[ch][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise look up the UTF-8 translation. */
|
|
||||||
entry = bsearch(&ch,
|
|
||||||
tty_acs_table, nitems(tty_acs_table), sizeof tty_acs_table[0],
|
|
||||||
tty_acs_cmp);
|
|
||||||
if (entry == NULL)
|
|
||||||
return (NULL);
|
|
||||||
return (entry->string);
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: tty-keys.c,v 1.57 2010-06-06 00:23:44 tcunha Exp $ */
|
/* $Id: tty-keys.c,v 1.55 2009-12-18 18:57:00 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -408,7 +408,7 @@ tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
|
|||||||
(*size)++;
|
(*size)++;
|
||||||
|
|
||||||
/* At the end of the string, return the current node. */
|
/* At the end of the string, return the current node. */
|
||||||
if (len == 0 || (tk->next == NULL && tk->key != KEYC_NONE))
|
if (len == 0)
|
||||||
return (tk);
|
return (tk);
|
||||||
|
|
||||||
/* Move into the next tree for the following character. */
|
/* Move into the next tree for the following character. */
|
||||||
@@ -612,8 +612,7 @@ tty_keys_mouse(const char *buf, size_t len, size_t *size, struct mouse_event *m)
|
|||||||
return (1);
|
return (1);
|
||||||
*size = 6;
|
*size = 6;
|
||||||
|
|
||||||
log_debug(
|
log_debug("mouse input is: %.6s", buf);
|
||||||
"mouse input: %.6s (%hhu,%hhu/%hhu)", buf, buf[4], buf[5], buf[3]);
|
|
||||||
|
|
||||||
m->b = buf[3];
|
m->b = buf[3];
|
||||||
m->x = buf[4];
|
m->x = buf[4];
|
||||||
|
|||||||
17
tty-term.c
17
tty-term.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: tty-term.c,v 1.43 2010-09-18 15:43:53 tcunha Exp $ */
|
/* $Id: tty-term.c,v 1.41 2009-12-18 07:42:30 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -252,8 +252,7 @@ tty_term_override(struct tty_term *term, const char *overrides)
|
|||||||
} else if (entstr[strlen(entstr) - 1] == '@') {
|
} else if (entstr[strlen(entstr) - 1] == '@') {
|
||||||
entstr[strlen(entstr) - 1] = '\0';
|
entstr[strlen(entstr) - 1] = '\0';
|
||||||
removeflag = 1;
|
removeflag = 1;
|
||||||
} else
|
}
|
||||||
continue;
|
|
||||||
|
|
||||||
for (i = 0; i < NTTYCODE; i++) {
|
for (i = 0; i < NTTYCODE; i++) {
|
||||||
ent = &tty_term_codes[i];
|
ent = &tty_term_codes[i];
|
||||||
@@ -305,7 +304,6 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
|
|||||||
u_int i;
|
u_int i;
|
||||||
int n, error;
|
int n, error;
|
||||||
char *s;
|
char *s;
|
||||||
const char *acs;
|
|
||||||
|
|
||||||
SLIST_FOREACH(term, &tty_terms, entry) {
|
SLIST_FOREACH(term, &tty_terms, entry) {
|
||||||
if (strcmp(term->name, name) == 0) {
|
if (strcmp(term->name, name) == 0) {
|
||||||
@@ -319,7 +317,7 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
|
|||||||
term->name = xstrdup(name);
|
term->name = xstrdup(name);
|
||||||
term->references = 1;
|
term->references = 1;
|
||||||
term->flags = 0;
|
term->flags = 0;
|
||||||
memset(term->codes, 0, sizeof term->codes);
|
memset(&term->codes, 0, sizeof term->codes);
|
||||||
SLIST_INSERT_HEAD(&tty_terms, term, entry);
|
SLIST_INSERT_HEAD(&tty_terms, term, entry);
|
||||||
|
|
||||||
/* Set up curses terminal. */
|
/* Set up curses terminal. */
|
||||||
@@ -417,15 +415,6 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
|
|||||||
if (!tty_term_flag(term, TTYC_XENL))
|
if (!tty_term_flag(term, TTYC_XENL))
|
||||||
term->flags |= TERM_EARLYWRAP;
|
term->flags |= TERM_EARLYWRAP;
|
||||||
|
|
||||||
/* Generate ACS table. If none is present, use nearest ASCII. */
|
|
||||||
memset(term->acs, 0, sizeof term->acs);
|
|
||||||
if (tty_term_has(term, TTYC_ACSC))
|
|
||||||
acs = tty_term_string(term, TTYC_ACSC);
|
|
||||||
else
|
|
||||||
acs = "a#j+k+l+m+n+o-p-q-r-s-t+u+v+w+x|y<z>~.";
|
|
||||||
for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2)
|
|
||||||
term->acs[(u_char) acs[0]][0] = acs[1];
|
|
||||||
|
|
||||||
return (term);
|
return (term);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|||||||
124
tty.c
124
tty.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: tty.c,v 1.197 2010-12-06 21:57:56 nicm Exp $ */
|
/* $Id: tty.c,v 1.189 2010-03-08 14:53:49 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -31,6 +31,8 @@
|
|||||||
void tty_read_callback(struct bufferevent *, void *);
|
void tty_read_callback(struct bufferevent *, void *);
|
||||||
void tty_error_callback(struct bufferevent *, short, void *);
|
void tty_error_callback(struct bufferevent *, short, void *);
|
||||||
|
|
||||||
|
void tty_fill_acs(struct tty *);
|
||||||
|
|
||||||
int tty_try_256(struct tty *, u_char, const char *);
|
int tty_try_256(struct tty *, u_char, const char *);
|
||||||
int tty_try_88(struct tty *, u_char, const char *);
|
int tty_try_88(struct tty *, u_char, const char *);
|
||||||
|
|
||||||
@@ -46,9 +48,6 @@ void tty_emulate_repeat(
|
|||||||
void tty_cell(struct tty *,
|
void tty_cell(struct tty *,
|
||||||
const struct grid_cell *, const struct grid_utf8 *);
|
const struct grid_cell *, const struct grid_utf8 *);
|
||||||
|
|
||||||
#define tty_use_acs(tty) \
|
|
||||||
(tty_term_has(tty->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8))
|
|
||||||
|
|
||||||
void
|
void
|
||||||
tty_init(struct tty *tty, int fd, char *term)
|
tty_init(struct tty *tty, int fd, char *term)
|
||||||
{
|
{
|
||||||
@@ -61,6 +60,9 @@ tty_init(struct tty *tty, int fd, char *term)
|
|||||||
tty->termname = xstrdup("unknown");
|
tty->termname = xstrdup("unknown");
|
||||||
else
|
else
|
||||||
tty->termname = xstrdup(term);
|
tty->termname = xstrdup(term);
|
||||||
|
|
||||||
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
fatal("fcntl failed");
|
||||||
tty->fd = fd;
|
tty->fd = fd;
|
||||||
|
|
||||||
if ((path = ttyname(fd)) == NULL)
|
if ((path = ttyname(fd)) == NULL)
|
||||||
@@ -71,55 +73,34 @@ tty_init(struct tty *tty, int fd, char *term)
|
|||||||
tty->term_flags = 0;
|
tty->term_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
tty_resize(struct tty *tty)
|
tty_resize(struct tty *tty)
|
||||||
{
|
{
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
u_int sx, sy;
|
|
||||||
|
|
||||||
if (ioctl(tty->fd, TIOCGWINSZ, &ws) != -1) {
|
if (ioctl(tty->fd, TIOCGWINSZ, &ws) != -1) {
|
||||||
sx = ws.ws_col;
|
tty->sx = ws.ws_col;
|
||||||
if (sx == 0)
|
tty->sy = ws.ws_row;
|
||||||
sx = 80;
|
|
||||||
sy = ws.ws_row;
|
|
||||||
if (sy == 0)
|
|
||||||
sy = 24;
|
|
||||||
} else {
|
|
||||||
sx = 80;
|
|
||||||
sy = 24;
|
|
||||||
}
|
}
|
||||||
if (sx == tty->sx && sy == tty->sy)
|
if (tty->sx == 0)
|
||||||
return (0);
|
tty->sx = 80;
|
||||||
tty->sx = sx;
|
if (tty->sy == 0)
|
||||||
tty->sy = sy;
|
tty->sy = 24;
|
||||||
|
|
||||||
tty->cx = UINT_MAX;
|
tty->cx = UINT_MAX;
|
||||||
tty->cy = UINT_MAX;
|
tty->cy = UINT_MAX;
|
||||||
|
|
||||||
tty->rupper = UINT_MAX;
|
tty->rupper = UINT_MAX;
|
||||||
tty->rlower = UINT_MAX;
|
tty->rlower = UINT_MAX;
|
||||||
|
|
||||||
/*
|
|
||||||
* If the terminal has been started, reset the actual scroll region and
|
|
||||||
* cursor position, as this may not have happened.
|
|
||||||
*/
|
|
||||||
if (tty->flags & TTY_STARTED) {
|
|
||||||
tty_cursor(tty, 0, 0);
|
|
||||||
tty_region(tty, 0, tty->sy - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tty_open(struct tty *tty, const char *overrides, char **cause)
|
tty_open(struct tty *tty, const char *overrides, char **cause)
|
||||||
{
|
{
|
||||||
char out[64];
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (debug_level > 3) {
|
if (debug_level > 3) {
|
||||||
xsnprintf(out, sizeof out, "tmux-out-%ld.log", (long) getpid());
|
fd = open("tmux.out", O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||||
fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
|
||||||
if (fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
if (fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
tty->log_fd = fd;
|
tty->log_fd = fd;
|
||||||
@@ -141,6 +122,8 @@ tty_open(struct tty *tty, const char *overrides, char **cause)
|
|||||||
|
|
||||||
tty_keys_init(tty);
|
tty_keys_init(tty);
|
||||||
|
|
||||||
|
tty_fill_acs(tty);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,8 +180,7 @@ tty_start_tty(struct tty *tty)
|
|||||||
memcpy(&tty->cell, &grid_default_cell, sizeof tty->cell);
|
memcpy(&tty->cell, &grid_default_cell, sizeof tty->cell);
|
||||||
|
|
||||||
tty_putcode(tty, TTYC_RMKX);
|
tty_putcode(tty, TTYC_RMKX);
|
||||||
if (tty_use_acs(tty))
|
tty_putcode(tty, TTYC_ENACS);
|
||||||
tty_putcode(tty, TTYC_ENACS);
|
|
||||||
tty_putcode(tty, TTYC_CLEAR);
|
tty_putcode(tty, TTYC_CLEAR);
|
||||||
|
|
||||||
tty_putcode(tty, TTYC_CNORM);
|
tty_putcode(tty, TTYC_CNORM);
|
||||||
@@ -239,8 +221,7 @@ tty_stop_tty(struct tty *tty)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1));
|
tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1));
|
||||||
if (tty_use_acs(tty))
|
tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS));
|
||||||
tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS));
|
|
||||||
tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0));
|
tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0));
|
||||||
tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX));
|
tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX));
|
||||||
tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR));
|
tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR));
|
||||||
@@ -255,6 +236,30 @@ tty_stop_tty(struct tty *tty)
|
|||||||
fcntl(tty->fd, F_SETFL, mode & ~O_NONBLOCK);
|
fcntl(tty->fd, F_SETFL, mode & ~O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tty_fill_acs(struct tty *tty)
|
||||||
|
{
|
||||||
|
const char *ptr;
|
||||||
|
|
||||||
|
memset(tty->acs, 0, sizeof tty->acs);
|
||||||
|
if (!tty_term_has(tty->term, TTYC_ACSC))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ptr = tty_term_string(tty->term, TTYC_ACSC);
|
||||||
|
if (strlen(ptr) % 2 != 0)
|
||||||
|
return;
|
||||||
|
for (; *ptr != '\0'; ptr += 2)
|
||||||
|
tty->acs[(u_char) ptr[0]] = ptr[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
u_char
|
||||||
|
tty_get_acs(struct tty *tty, u_char ch)
|
||||||
|
{
|
||||||
|
if (tty->acs[ch] != '\0')
|
||||||
|
return (tty->acs[ch]);
|
||||||
|
return (ch);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tty_close(struct tty *tty)
|
tty_close(struct tty *tty)
|
||||||
{
|
{
|
||||||
@@ -334,17 +339,11 @@ tty_puts(struct tty *tty, const char *s)
|
|||||||
void
|
void
|
||||||
tty_putc(struct tty *tty, u_char ch)
|
tty_putc(struct tty *tty, u_char ch)
|
||||||
{
|
{
|
||||||
const char *acs;
|
u_int sx;
|
||||||
u_int sx;
|
|
||||||
|
|
||||||
if (tty->cell.attr & GRID_ATTR_CHARSET) {
|
if (tty->cell.attr & GRID_ATTR_CHARSET)
|
||||||
acs = tty_acs_get(tty, ch);
|
ch = tty_get_acs(tty, ch);
|
||||||
if (acs != NULL)
|
bufferevent_write(tty->event, &ch, 1);
|
||||||
bufferevent_write(tty->event, acs, strlen(acs));
|
|
||||||
else
|
|
||||||
bufferevent_write(tty->event, &ch, 1);
|
|
||||||
} else
|
|
||||||
bufferevent_write(tty->event, &ch, 1);
|
|
||||||
|
|
||||||
if (ch >= 0x20 && ch != 0x7f) {
|
if (ch >= 0x20 && ch != 0x7f) {
|
||||||
sx = tty->sx;
|
sx = tty->sx;
|
||||||
@@ -403,18 +402,11 @@ tty_update_mode(struct tty *tty, int mode)
|
|||||||
else
|
else
|
||||||
tty_putcode(tty, TTYC_CIVIS);
|
tty_putcode(tty, TTYC_CIVIS);
|
||||||
}
|
}
|
||||||
if (changed & (MODE_MOUSE|MODE_MOUSEMOTION)) {
|
if (changed & MODE_MOUSE) {
|
||||||
if (mode & MODE_MOUSE) {
|
if (mode & MODE_MOUSE)
|
||||||
if (mode & MODE_MOUSEMOTION)
|
tty_puts(tty, "\033[?1000h");
|
||||||
tty_puts(tty, "\033[?1003h");
|
else
|
||||||
else
|
tty_puts(tty, "\033[?1000l");
|
||||||
tty_puts(tty, "\033[?1000h");
|
|
||||||
} else {
|
|
||||||
if (mode & MODE_MOUSEMOTION)
|
|
||||||
tty_puts(tty, "\033[?1003l");
|
|
||||||
else
|
|
||||||
tty_puts(tty, "\033[?1000l");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (changed & MODE_KKEYPAD) {
|
if (changed & MODE_KKEYPAD) {
|
||||||
if (mode & MODE_KKEYPAD)
|
if (mode & MODE_KKEYPAD)
|
||||||
@@ -547,7 +539,7 @@ tty_write(void (*cmdfn)(
|
|||||||
|
|
||||||
if (wp->window->flags & WINDOW_REDRAW || wp->flags & PANE_REDRAW)
|
if (wp->window->flags & WINDOW_REDRAW || wp->flags & PANE_REDRAW)
|
||||||
return;
|
return;
|
||||||
if (!window_pane_visible(wp))
|
if (wp->window->flags & WINDOW_HIDDEN || !window_pane_visible(wp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
@@ -558,9 +550,7 @@ tty_write(void (*cmdfn)(
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (c->session->curw->window == wp->window) {
|
if (c->session->curw->window == wp->window) {
|
||||||
if (c->tty.term == NULL)
|
if (c->tty.flags & TTY_FREEZE || c->tty.term == NULL)
|
||||||
continue;
|
|
||||||
if (c->tty.flags & (TTY_FREEZE|TTY_BACKOFF))
|
|
||||||
continue;
|
continue;
|
||||||
cmdfn(&c->tty, ctx);
|
cmdfn(&c->tty, ctx);
|
||||||
}
|
}
|
||||||
@@ -977,7 +967,7 @@ tty_reset(struct tty *tty)
|
|||||||
if (memcmp(gc, &grid_default_cell, sizeof *gc) == 0)
|
if (memcmp(gc, &grid_default_cell, sizeof *gc) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((gc->attr & GRID_ATTR_CHARSET) && tty_use_acs(tty))
|
if (tty_term_has(tty->term, TTYC_RMACS) && gc->attr & GRID_ATTR_CHARSET)
|
||||||
tty_putcode(tty, TTYC_RMACS);
|
tty_putcode(tty, TTYC_RMACS);
|
||||||
tty_putcode(tty, TTYC_SGR0);
|
tty_putcode(tty, TTYC_SGR0);
|
||||||
memcpy(gc, &grid_default_cell, sizeof *gc);
|
memcpy(gc, &grid_default_cell, sizeof *gc);
|
||||||
@@ -1093,7 +1083,7 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy)
|
|||||||
* Use HPA if change is larger than absolute, otherwise move
|
* Use HPA if change is larger than absolute, otherwise move
|
||||||
* the cursor with CUB/CUF.
|
* the cursor with CUB/CUF.
|
||||||
*/
|
*/
|
||||||
if ((u_int) abs(change) > cx && tty_term_has(term, TTYC_HPA)) {
|
if (abs(change) > cx && tty_term_has(term, TTYC_HPA)) {
|
||||||
tty_putcode1(tty, TTYC_HPA, cx);
|
tty_putcode1(tty, TTYC_HPA, cx);
|
||||||
goto out;
|
goto out;
|
||||||
} else if (change > 0 && tty_term_has(term, TTYC_CUB)) {
|
} else if (change > 0 && tty_term_has(term, TTYC_CUB)) {
|
||||||
@@ -1129,7 +1119,7 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy)
|
|||||||
* Try to use VPA if change is larger than absolute or if this
|
* Try to use VPA if change is larger than absolute or if this
|
||||||
* change would cross the scroll region, otherwise use CUU/CUD.
|
* change would cross the scroll region, otherwise use CUU/CUD.
|
||||||
*/
|
*/
|
||||||
if ((u_int) abs(change) > cy ||
|
if (abs(change) > cy ||
|
||||||
(change < 0 && cy - change > tty->rlower) ||
|
(change < 0 && cy - change > tty->rlower) ||
|
||||||
(change > 0 && cy - change < tty->rupper)) {
|
(change > 0 && cy - change < tty->rupper)) {
|
||||||
if (tty_term_has(term, TTYC_VPA)) {
|
if (tty_term_has(term, TTYC_VPA)) {
|
||||||
@@ -1214,7 +1204,7 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc)
|
|||||||
}
|
}
|
||||||
if (changed & GRID_ATTR_HIDDEN)
|
if (changed & GRID_ATTR_HIDDEN)
|
||||||
tty_putcode(tty, TTYC_INVIS);
|
tty_putcode(tty, TTYC_INVIS);
|
||||||
if ((changed & GRID_ATTR_CHARSET) && tty_use_acs(tty))
|
if (changed & GRID_ATTR_CHARSET)
|
||||||
tty_putcode(tty, TTYC_SMACS);
|
tty_putcode(tty, TTYC_SMACS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: window-choose.c,v 1.30 2010-05-22 21:56:04 micahcowan Exp $ */
|
/* $Id: window-choose.c,v 1.29 2010-02-02 23:55:21 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -25,9 +25,9 @@
|
|||||||
struct screen *window_choose_init(struct window_pane *);
|
struct screen *window_choose_init(struct window_pane *);
|
||||||
void window_choose_free(struct window_pane *);
|
void window_choose_free(struct window_pane *);
|
||||||
void window_choose_resize(struct window_pane *, u_int, u_int);
|
void window_choose_resize(struct window_pane *, u_int, u_int);
|
||||||
void window_choose_key(struct window_pane *, struct session *, int);
|
void window_choose_key(struct window_pane *, struct client *, int);
|
||||||
void window_choose_mouse(
|
void window_choose_mouse(
|
||||||
struct window_pane *, struct session *, struct mouse_event *);
|
struct window_pane *, struct client *, struct mouse_event *);
|
||||||
|
|
||||||
void window_choose_redraw_screen(struct window_pane *);
|
void window_choose_redraw_screen(struct window_pane *);
|
||||||
void window_choose_write_line(
|
void window_choose_write_line(
|
||||||
@@ -171,7 +171,7 @@ window_choose_resize(struct window_pane *wp, u_int sx, u_int sy)
|
|||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
|
window_choose_key(struct window_pane *wp, unused struct client *c, int key)
|
||||||
{
|
{
|
||||||
struct window_choose_mode_data *data = wp->modedata;
|
struct window_choose_mode_data *data = wp->modedata;
|
||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
@@ -304,7 +304,7 @@ window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
|
|||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
window_choose_mouse(
|
window_choose_mouse(
|
||||||
struct window_pane *wp, unused struct session *sess, struct mouse_event *m)
|
struct window_pane *wp, unused struct client *c, struct mouse_event *m)
|
||||||
{
|
{
|
||||||
struct window_choose_mode_data *data = wp->modedata;
|
struct window_choose_mode_data *data = wp->modedata;
|
||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: window-clock.c,v 1.12 2010-05-22 21:56:04 micahcowan Exp $ */
|
/* $Id: window-clock.c,v 1.11 2009-12-04 22:14:47 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
struct screen *window_clock_init(struct window_pane *);
|
struct screen *window_clock_init(struct window_pane *);
|
||||||
void window_clock_free(struct window_pane *);
|
void window_clock_free(struct window_pane *);
|
||||||
void window_clock_resize(struct window_pane *, u_int, u_int);
|
void window_clock_resize(struct window_pane *, u_int, u_int);
|
||||||
void window_clock_key(struct window_pane *, struct session *, int);
|
void window_clock_key(struct window_pane *, struct client *, int);
|
||||||
void window_clock_timer(struct window_pane *);
|
void window_clock_timer(struct window_pane *);
|
||||||
|
|
||||||
void window_clock_draw_screen(struct window_pane *);
|
void window_clock_draw_screen(struct window_pane *);
|
||||||
@@ -85,7 +85,7 @@ window_clock_resize(struct window_pane *wp, u_int sx, u_int sy)
|
|||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
window_clock_key(
|
window_clock_key(
|
||||||
struct window_pane *wp, unused struct session *sess, unused int key)
|
struct window_pane *wp, unused struct client *c, unused int key)
|
||||||
{
|
{
|
||||||
window_pane_reset_mode(wp);
|
window_pane_reset_mode(wp);
|
||||||
}
|
}
|
||||||
|
|||||||
463
window-copy.c
463
window-copy.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: window-copy.c,v 1.125 2010-12-11 17:57:28 nicm Exp $ */
|
/* $Id: window-copy.c,v 1.109 2010-03-08 15:02:07 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -26,11 +26,11 @@
|
|||||||
struct screen *window_copy_init(struct window_pane *);
|
struct screen *window_copy_init(struct window_pane *);
|
||||||
void window_copy_free(struct window_pane *);
|
void window_copy_free(struct window_pane *);
|
||||||
void window_copy_resize(struct window_pane *, u_int, u_int);
|
void window_copy_resize(struct window_pane *, u_int, u_int);
|
||||||
void window_copy_key(struct window_pane *, struct session *, int);
|
void window_copy_key(struct window_pane *, struct client *, int);
|
||||||
int window_copy_key_input(struct window_pane *, int);
|
int window_copy_key_input(struct window_pane *, int);
|
||||||
int window_copy_key_numeric_prefix(struct window_pane *, int);
|
int window_copy_key_numeric_prefix(struct window_pane *, int);
|
||||||
void window_copy_mouse(
|
void window_copy_mouse(
|
||||||
struct window_pane *, struct session *, struct mouse_event *);
|
struct window_pane *, struct client *, struct mouse_event *);
|
||||||
|
|
||||||
void window_copy_redraw_lines(struct window_pane *, u_int, u_int);
|
void window_copy_redraw_lines(struct window_pane *, u_int, u_int);
|
||||||
void window_copy_redraw_screen(struct window_pane *);
|
void window_copy_redraw_screen(struct window_pane *);
|
||||||
@@ -52,7 +52,7 @@ void window_copy_goto_line(struct window_pane *, const char *);
|
|||||||
void window_copy_update_cursor(struct window_pane *, u_int, u_int);
|
void window_copy_update_cursor(struct window_pane *, u_int, u_int);
|
||||||
void window_copy_start_selection(struct window_pane *);
|
void window_copy_start_selection(struct window_pane *);
|
||||||
int window_copy_update_selection(struct window_pane *);
|
int window_copy_update_selection(struct window_pane *);
|
||||||
void window_copy_copy_selection(struct window_pane *, struct session *);
|
void window_copy_copy_selection(struct window_pane *, struct client *);
|
||||||
void window_copy_clear_selection(struct window_pane *);
|
void window_copy_clear_selection(struct window_pane *);
|
||||||
void window_copy_copy_line(
|
void window_copy_copy_line(
|
||||||
struct window_pane *, char **, size_t *, u_int, u_int, u_int);
|
struct window_pane *, char **, size_t *, u_int, u_int, u_int);
|
||||||
@@ -65,8 +65,6 @@ void window_copy_cursor_left(struct window_pane *);
|
|||||||
void window_copy_cursor_right(struct window_pane *);
|
void window_copy_cursor_right(struct window_pane *);
|
||||||
void window_copy_cursor_up(struct window_pane *, int);
|
void window_copy_cursor_up(struct window_pane *, int);
|
||||||
void window_copy_cursor_down(struct window_pane *, int);
|
void window_copy_cursor_down(struct window_pane *, int);
|
||||||
void window_copy_cursor_jump(struct window_pane *);
|
|
||||||
void window_copy_cursor_jump_back(struct window_pane *);
|
|
||||||
void window_copy_cursor_next_word(struct window_pane *, const char *);
|
void window_copy_cursor_next_word(struct window_pane *, const char *);
|
||||||
void window_copy_cursor_next_word_end(struct window_pane *, const char *);
|
void window_copy_cursor_next_word_end(struct window_pane *, const char *);
|
||||||
void window_copy_cursor_previous_word(struct window_pane *, const char *);
|
void window_copy_cursor_previous_word(struct window_pane *, const char *);
|
||||||
@@ -88,33 +86,12 @@ enum window_copy_input_type {
|
|||||||
WINDOW_COPY_NUMERICPREFIX,
|
WINDOW_COPY_NUMERICPREFIX,
|
||||||
WINDOW_COPY_SEARCHUP,
|
WINDOW_COPY_SEARCHUP,
|
||||||
WINDOW_COPY_SEARCHDOWN,
|
WINDOW_COPY_SEARCHDOWN,
|
||||||
WINDOW_COPY_JUMPFORWARD,
|
|
||||||
WINDOW_COPY_JUMPBACK,
|
|
||||||
WINDOW_COPY_GOTOLINE,
|
WINDOW_COPY_GOTOLINE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy-mode's visible screen (the "screen" field) is filled from one of
|
|
||||||
* two sources: the original contents of the pane (used when we
|
|
||||||
* actually enter via the "copy-mode" command, to copy the contents of
|
|
||||||
* the current pane), or else a series of lines containing the output
|
|
||||||
* from an output-writing tmux command (such as any of the "show-*" or
|
|
||||||
* "list-*" commands).
|
|
||||||
*
|
|
||||||
* In either case, the full content of the copy-mode grid is pointed at
|
|
||||||
* by the "backing" field, and is copied into "screen" as needed (that
|
|
||||||
* is, when scrolling occurs). When copy-mode is backed by a pane,
|
|
||||||
* backing points directly at that pane's screen structure (&wp->base);
|
|
||||||
* when backed by a list of output-lines from a command, it points at
|
|
||||||
* a newly-allocated screen structure (which is deallocated when the
|
|
||||||
* mode ends).
|
|
||||||
*/
|
|
||||||
struct window_copy_mode_data {
|
struct window_copy_mode_data {
|
||||||
struct screen screen;
|
struct screen screen;
|
||||||
|
|
||||||
struct screen *backing;
|
|
||||||
int backing_written; /* backing display has started */
|
|
||||||
|
|
||||||
struct mode_key_data mdata;
|
struct mode_key_data mdata;
|
||||||
|
|
||||||
u_int oy;
|
u_int oy;
|
||||||
@@ -138,9 +115,6 @@ struct window_copy_mode_data {
|
|||||||
|
|
||||||
enum window_copy_input_type searchtype;
|
enum window_copy_input_type searchtype;
|
||||||
char *searchstr;
|
char *searchstr;
|
||||||
|
|
||||||
enum window_copy_input_type jumptype;
|
|
||||||
char jumpchar;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct screen *
|
struct screen *
|
||||||
@@ -148,18 +122,18 @@ window_copy_init(struct window_pane *wp)
|
|||||||
{
|
{
|
||||||
struct window_copy_mode_data *data;
|
struct window_copy_mode_data *data;
|
||||||
struct screen *s;
|
struct screen *s;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
u_int i;
|
||||||
int keys;
|
int keys;
|
||||||
|
|
||||||
wp->modedata = data = xmalloc(sizeof *data);
|
wp->modedata = data = xmalloc(sizeof *data);
|
||||||
data->oy = 0;
|
data->oy = 0;
|
||||||
data->cx = 0;
|
data->cx = wp->base.cx;
|
||||||
data->cy = 0;
|
data->cy = wp->base.cy;
|
||||||
|
|
||||||
data->lastcx = 0;
|
data->lastcx = 0;
|
||||||
data->lastsx = 0;
|
data->lastsx = 0;
|
||||||
|
|
||||||
data->backing_written = 0;
|
|
||||||
|
|
||||||
data->rectflag = 0;
|
data->rectflag = 0;
|
||||||
|
|
||||||
data->inputtype = WINDOW_COPY_OFF;
|
data->inputtype = WINDOW_COPY_OFF;
|
||||||
@@ -171,11 +145,7 @@ window_copy_init(struct window_pane *wp)
|
|||||||
data->searchstr = NULL;
|
data->searchstr = NULL;
|
||||||
|
|
||||||
wp->flags |= PANE_FREEZE;
|
wp->flags |= PANE_FREEZE;
|
||||||
if (wp->fd != -1)
|
bufferevent_disable(wp->event, EV_READ|EV_WRITE);
|
||||||
bufferevent_disable(wp->event, EV_READ|EV_WRITE);
|
|
||||||
|
|
||||||
data->jumptype = WINDOW_COPY_OFF;
|
|
||||||
data->jumpchar = '\0';
|
|
||||||
|
|
||||||
s = &data->screen;
|
s = &data->screen;
|
||||||
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
|
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
|
||||||
@@ -188,26 +158,6 @@ window_copy_init(struct window_pane *wp)
|
|||||||
else
|
else
|
||||||
mode_key_init(&data->mdata, &mode_key_tree_vi_copy);
|
mode_key_init(&data->mdata, &mode_key_tree_vi_copy);
|
||||||
|
|
||||||
data->backing = NULL;
|
|
||||||
|
|
||||||
return (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
window_copy_init_from_pane(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
|
||||||
struct screen *s = &data->screen;
|
|
||||||
struct screen_write_ctx ctx;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
if (wp->mode != &window_copy_mode)
|
|
||||||
fatalx("not in copy mode");
|
|
||||||
|
|
||||||
data->backing = &wp->base;
|
|
||||||
data->cx = data->backing->cx;
|
|
||||||
data->cy = data->backing->cy;
|
|
||||||
|
|
||||||
s->cx = data->cx;
|
s->cx = data->cx;
|
||||||
s->cy = data->cy;
|
s->cy = data->cy;
|
||||||
|
|
||||||
@@ -216,17 +166,8 @@ window_copy_init_from_pane(struct window_pane *wp)
|
|||||||
window_copy_write_line(wp, &ctx, i);
|
window_copy_write_line(wp, &ctx, i);
|
||||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||||
screen_write_stop(&ctx);
|
screen_write_stop(&ctx);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
return (s);
|
||||||
window_copy_init_for_output(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
|
||||||
|
|
||||||
data->backing = xmalloc(sizeof *data->backing);
|
|
||||||
screen_init(data->backing, screen_size_x(&wp->base),
|
|
||||||
screen_size_y(&wp->base), UINT_MAX);
|
|
||||||
data->backing->mode &= ~MODE_WRAP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -235,80 +176,17 @@ window_copy_free(struct window_pane *wp)
|
|||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
|
|
||||||
wp->flags &= ~PANE_FREEZE;
|
wp->flags &= ~PANE_FREEZE;
|
||||||
if (wp->fd != -1)
|
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
||||||
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
|
||||||
|
|
||||||
if (data->searchstr != NULL)
|
if (data->searchstr != NULL)
|
||||||
xfree(data->searchstr);
|
xfree(data->searchstr);
|
||||||
xfree(data->inputstr);
|
xfree(data->inputstr);
|
||||||
|
|
||||||
if (data->backing != &wp->base) {
|
|
||||||
screen_free(data->backing);
|
|
||||||
xfree(data->backing);
|
|
||||||
}
|
|
||||||
screen_free(&data->screen);
|
screen_free(&data->screen);
|
||||||
|
|
||||||
xfree(data);
|
xfree(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
window_copy_add(struct window_pane *wp, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
window_copy_vadd(wp, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
|
||||||
struct screen *backing = data->backing;
|
|
||||||
struct screen_write_ctx back_ctx, ctx;
|
|
||||||
struct grid_cell gc;
|
|
||||||
int utf8flag;
|
|
||||||
u_int old_hsize;
|
|
||||||
|
|
||||||
if (backing == &wp->base)
|
|
||||||
return;
|
|
||||||
|
|
||||||
utf8flag = options_get_number(&wp->window->options, "utf8");
|
|
||||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
|
||||||
|
|
||||||
old_hsize = screen_hsize(data->backing);
|
|
||||||
screen_write_start(&back_ctx, NULL, backing);
|
|
||||||
if (data->backing_written) {
|
|
||||||
/*
|
|
||||||
* On the second or later line, do a CRLF before writing
|
|
||||||
* (so it's on a new line).
|
|
||||||
*/
|
|
||||||
screen_write_carriagereturn(&back_ctx);
|
|
||||||
screen_write_linefeed(&back_ctx, 0);
|
|
||||||
} else
|
|
||||||
data->backing_written = 1;
|
|
||||||
screen_write_vnputs(&back_ctx, 0, &gc, utf8flag, fmt, ap);
|
|
||||||
screen_write_stop(&back_ctx);
|
|
||||||
|
|
||||||
data->oy += screen_hsize(data->backing) - old_hsize;
|
|
||||||
|
|
||||||
screen_write_start(&ctx, wp, &data->screen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the history has changed, draw the top line.
|
|
||||||
* (If there's any history at all, it has changed.)
|
|
||||||
*/
|
|
||||||
if (screen_hsize(data->backing))
|
|
||||||
window_copy_redraw_lines(wp, 0, 1);
|
|
||||||
|
|
||||||
/* Write the line, if it's visible. */
|
|
||||||
if (backing->cy + data->oy < screen_size_y(backing))
|
|
||||||
window_copy_redraw_lines(wp, backing->cy, 1);
|
|
||||||
|
|
||||||
screen_write_stop(&ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
window_copy_pageup(struct window_pane *wp)
|
window_copy_pageup(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
@@ -319,8 +197,8 @@ window_copy_pageup(struct window_pane *wp)
|
|||||||
n = 1;
|
n = 1;
|
||||||
if (screen_size_y(s) > 2)
|
if (screen_size_y(s) > 2)
|
||||||
n = screen_size_y(s) - 2;
|
n = screen_size_y(s) - 2;
|
||||||
if (data->oy + n > screen_hsize(data->backing))
|
if (data->oy + n > screen_hsize(&wp->base))
|
||||||
data->oy = screen_hsize(data->backing);
|
data->oy = screen_hsize(&wp->base);
|
||||||
else
|
else
|
||||||
data->oy += n;
|
data->oy += n;
|
||||||
window_copy_update_selection(wp);
|
window_copy_update_selection(wp);
|
||||||
@@ -335,15 +213,11 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
|
|||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
|
|
||||||
screen_resize(s, sx, sy);
|
screen_resize(s, sx, sy);
|
||||||
if (data->backing != &wp->base)
|
|
||||||
screen_resize(data->backing, sx, sy);
|
|
||||||
|
|
||||||
if (data->cy > sy - 1)
|
if (data->cy > sy - 1)
|
||||||
data->cy = sy - 1;
|
data->cy = sy - 1;
|
||||||
if (data->cx > sx)
|
if (data->cx > sx)
|
||||||
data->cx = sx;
|
data->cx = sx;
|
||||||
if (data->oy > screen_hsize(data->backing))
|
|
||||||
data->oy = screen_hsize(data->backing);
|
|
||||||
|
|
||||||
window_copy_clear_selection(wp);
|
window_copy_clear_selection(wp);
|
||||||
|
|
||||||
@@ -355,7 +229,7 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
window_copy_key(struct window_pane *wp, struct client *c, int key)
|
||||||
{
|
{
|
||||||
const char *word_separators;
|
const char *word_separators;
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
@@ -368,24 +242,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
if (np == 0)
|
if (np == 0)
|
||||||
np = 1;
|
np = 1;
|
||||||
|
|
||||||
if (data->inputtype == WINDOW_COPY_JUMPFORWARD
|
if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) {
|
||||||
|| data->inputtype == WINDOW_COPY_JUMPBACK) {
|
|
||||||
/* Ignore keys with modifiers. */
|
|
||||||
if ((key & KEYC_MASK_MOD) == 0) {
|
|
||||||
data->jumpchar = key;
|
|
||||||
if (data->inputtype == WINDOW_COPY_JUMPFORWARD) {
|
|
||||||
for (; np != 0; np--)
|
|
||||||
window_copy_cursor_jump(wp);
|
|
||||||
} else {
|
|
||||||
for (; np != 0; np--)
|
|
||||||
window_copy_cursor_jump_back(wp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data->jumptype = data->inputtype;
|
|
||||||
data->inputtype = WINDOW_COPY_OFF;
|
|
||||||
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
|
|
||||||
return;
|
|
||||||
} if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) {
|
|
||||||
if (window_copy_key_numeric_prefix(wp, key) == 0)
|
if (window_copy_key_numeric_prefix(wp, key) == 0)
|
||||||
return;
|
return;
|
||||||
data->inputtype = WINDOW_COPY_OFF;
|
data->inputtype = WINDOW_COPY_OFF;
|
||||||
@@ -399,8 +256,9 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
cmd = mode_key_lookup(&data->mdata, key);
|
cmd = mode_key_lookup(&data->mdata, key);
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case MODEKEYCOPY_CANCEL:
|
case MODEKEYCOPY_CANCEL:
|
||||||
window_pane_reset_mode(wp);
|
for (; np != 0; np--)
|
||||||
return;
|
window_pane_reset_mode(wp);
|
||||||
|
break;
|
||||||
case MODEKEYCOPY_LEFT:
|
case MODEKEYCOPY_LEFT:
|
||||||
for (; np != 0; np--)
|
for (; np != 0; np--)
|
||||||
window_copy_cursor_left(wp);
|
window_copy_cursor_left(wp);
|
||||||
@@ -445,8 +303,8 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
case MODEKEYCOPY_HALFPAGEUP:
|
case MODEKEYCOPY_HALFPAGEUP:
|
||||||
n = screen_size_y(s) / 2;
|
n = screen_size_y(s) / 2;
|
||||||
for (; np != 0; np--) {
|
for (; np != 0; np--) {
|
||||||
if (data->oy + n > screen_hsize(data->backing))
|
if (data->oy + n > screen_hsize(&wp->base))
|
||||||
data->oy = screen_hsize(data->backing);
|
data->oy = screen_hsize(&wp->base);
|
||||||
else
|
else
|
||||||
data->oy += n;
|
data->oy += n;
|
||||||
}
|
}
|
||||||
@@ -485,7 +343,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
case MODEKEYCOPY_HISTORYTOP:
|
case MODEKEYCOPY_HISTORYTOP:
|
||||||
data->cx = 0;
|
data->cx = 0;
|
||||||
data->cy = 0;
|
data->cy = 0;
|
||||||
data->oy = screen_hsize(data->backing);
|
data->oy = screen_hsize(&wp->base);
|
||||||
window_copy_update_selection(wp);
|
window_copy_update_selection(wp);
|
||||||
window_copy_redraw_screen(wp);
|
window_copy_redraw_screen(wp);
|
||||||
break;
|
break;
|
||||||
@@ -505,10 +363,9 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
window_copy_redraw_screen(wp);
|
window_copy_redraw_screen(wp);
|
||||||
break;
|
break;
|
||||||
case MODEKEYCOPY_COPYSELECTION:
|
case MODEKEYCOPY_COPYSELECTION:
|
||||||
if (sess != NULL) {
|
if (c != NULL && c->session != NULL) {
|
||||||
window_copy_copy_selection(wp, sess);
|
window_copy_copy_selection(wp, c);
|
||||||
window_pane_reset_mode(wp);
|
window_pane_reset_mode(wp);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MODEKEYCOPY_STARTOFLINE:
|
case MODEKEYCOPY_STARTOFLINE:
|
||||||
@@ -550,36 +407,6 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
for (; np != 0; np--)
|
for (; np != 0; np--)
|
||||||
window_copy_cursor_previous_word(wp, word_separators);
|
window_copy_cursor_previous_word(wp, word_separators);
|
||||||
break;
|
break;
|
||||||
case MODEKEYCOPY_JUMP:
|
|
||||||
data->inputtype = WINDOW_COPY_JUMPFORWARD;
|
|
||||||
data->inputprompt = "Jump Forward";
|
|
||||||
*data->inputstr = '\0';
|
|
||||||
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
|
|
||||||
return; /* skip numprefix reset */
|
|
||||||
case MODEKEYCOPY_JUMPAGAIN:
|
|
||||||
if (data->jumptype == WINDOW_COPY_JUMPFORWARD) {
|
|
||||||
for (; np != 0; np--)
|
|
||||||
window_copy_cursor_jump(wp);
|
|
||||||
} else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
|
|
||||||
for (; np != 0; np--)
|
|
||||||
window_copy_cursor_jump_back(wp);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MODEKEYCOPY_JUMPREVERSE:
|
|
||||||
if (data->jumptype == WINDOW_COPY_JUMPFORWARD) {
|
|
||||||
for (; np != 0; np--)
|
|
||||||
window_copy_cursor_jump_back(wp);
|
|
||||||
} else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
|
|
||||||
for (; np != 0; np--)
|
|
||||||
window_copy_cursor_jump(wp);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MODEKEYCOPY_JUMPBACK:
|
|
||||||
data->inputtype = WINDOW_COPY_JUMPBACK;
|
|
||||||
data->inputprompt = "Jump Back";
|
|
||||||
*data->inputstr = '\0';
|
|
||||||
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
|
|
||||||
return; /* skip numprefix reset */
|
|
||||||
case MODEKEYCOPY_SEARCHUP:
|
case MODEKEYCOPY_SEARCHUP:
|
||||||
data->inputtype = WINDOW_COPY_SEARCHUP;
|
data->inputtype = WINDOW_COPY_SEARCHUP;
|
||||||
data->inputprompt = "Search Up";
|
data->inputprompt = "Search Up";
|
||||||
@@ -593,8 +420,6 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
switch (data->searchtype) {
|
switch (data->searchtype) {
|
||||||
case WINDOW_COPY_OFF:
|
case WINDOW_COPY_OFF:
|
||||||
case WINDOW_COPY_GOTOLINE:
|
case WINDOW_COPY_GOTOLINE:
|
||||||
case WINDOW_COPY_JUMPFORWARD:
|
|
||||||
case WINDOW_COPY_JUMPBACK:
|
|
||||||
case WINDOW_COPY_NUMERICPREFIX:
|
case WINDOW_COPY_NUMERICPREFIX:
|
||||||
break;
|
break;
|
||||||
case WINDOW_COPY_SEARCHUP:
|
case WINDOW_COPY_SEARCHUP:
|
||||||
@@ -631,7 +456,7 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
*data->inputstr = '\0';
|
*data->inputstr = '\0';
|
||||||
goto input_on;
|
goto input_on;
|
||||||
case MODEKEYCOPY_STARTNUMBERPREFIX:
|
case MODEKEYCOPY_STARTNUMBERPREFIX:
|
||||||
key &= KEYC_MASK_KEY;
|
key &= 0xff;
|
||||||
if (key >= '0' && key <= '9') {
|
if (key >= '0' && key <= '9') {
|
||||||
data->inputtype = WINDOW_COPY_NUMERICPREFIX;
|
data->inputtype = WINDOW_COPY_NUMERICPREFIX;
|
||||||
data->numprefix = 0;
|
data->numprefix = 0;
|
||||||
@@ -699,8 +524,6 @@ window_copy_key_input(struct window_pane *wp, int key)
|
|||||||
|
|
||||||
switch (data->inputtype) {
|
switch (data->inputtype) {
|
||||||
case WINDOW_COPY_OFF:
|
case WINDOW_COPY_OFF:
|
||||||
case WINDOW_COPY_JUMPFORWARD:
|
|
||||||
case WINDOW_COPY_JUMPBACK:
|
|
||||||
case WINDOW_COPY_NUMERICPREFIX:
|
case WINDOW_COPY_NUMERICPREFIX:
|
||||||
break;
|
break;
|
||||||
case WINDOW_COPY_SEARCHUP:
|
case WINDOW_COPY_SEARCHUP:
|
||||||
@@ -745,7 +568,7 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
|
|||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
|
|
||||||
key &= KEYC_MASK_KEY;
|
key &= 0xff;
|
||||||
if (key < '0' || key > '9')
|
if (key < '0' || key > '9')
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -760,63 +583,29 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
|
|||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
window_copy_mouse(
|
window_copy_mouse(
|
||||||
struct window_pane *wp, unused struct session *sess, struct mouse_event *m)
|
struct window_pane *wp, unused struct client *c, struct mouse_event *m)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
|
if ((m->b & 3) == 3)
|
||||||
|
return;
|
||||||
if (m->x >= screen_size_x(s))
|
if (m->x >= screen_size_x(s))
|
||||||
return;
|
return;
|
||||||
if (m->y >= screen_size_y(s))
|
if (m->y >= screen_size_y(s))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* If mouse wheel (buttons 4 and 5), scroll. */
|
window_copy_update_cursor(wp, m->x, m->y);
|
||||||
if ((m->b & MOUSE_45)) {
|
if (window_copy_update_selection(wp))
|
||||||
if ((m->b & MOUSE_BUTTON) == MOUSE_1) {
|
|
||||||
for (i = 0; i < 5; i++)
|
|
||||||
window_copy_cursor_up(wp, 0);
|
|
||||||
} else if ((m->b & MOUSE_BUTTON) == MOUSE_2) {
|
|
||||||
for (i = 0; i < 5; i++)
|
|
||||||
window_copy_cursor_down(wp, 0);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If already reading motion, move the cursor while buttons are still
|
|
||||||
* pressed, or stop the selection on their release.
|
|
||||||
*/
|
|
||||||
if (s->mode & MODE_MOUSEMOTION) {
|
|
||||||
if ((m->b & MOUSE_BUTTON) != MOUSE_UP) {
|
|
||||||
window_copy_update_cursor(wp, m->x, m->y);
|
|
||||||
if (window_copy_update_selection(wp))
|
|
||||||
window_copy_redraw_screen(wp);
|
|
||||||
} else {
|
|
||||||
s->mode &= ~MODE_MOUSEMOTION;
|
|
||||||
if (sess != NULL) {
|
|
||||||
window_copy_copy_selection(wp, sess);
|
|
||||||
window_pane_reset_mode(wp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise i other buttons pressed, start selection and motion. */
|
|
||||||
if ((m->b & MOUSE_BUTTON) != MOUSE_UP) {
|
|
||||||
s->mode |= MODE_MOUSEMOTION;
|
|
||||||
|
|
||||||
window_copy_update_cursor(wp, m->x, m->y);
|
|
||||||
window_copy_start_selection(wp);
|
|
||||||
window_copy_redraw_screen(wp);
|
window_copy_redraw_screen(wp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_copy_scroll_to(struct window_pane *wp, u_int px, u_int py)
|
window_copy_scroll_to(struct window_pane *wp, u_int px, u_int py)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct grid *gd = data->backing->grid;
|
struct screen *s = &wp->base;
|
||||||
|
struct grid *gd = s->grid;
|
||||||
u_int offset, gap;
|
u_int offset, gap;
|
||||||
|
|
||||||
data->cx = px;
|
data->cx = px;
|
||||||
@@ -911,7 +700,7 @@ void
|
|||||||
window_copy_search_up(struct window_pane *wp, const char *searchstr)
|
window_copy_search_up(struct window_pane *wp, const char *searchstr)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct screen *s = data->backing, ss;
|
struct screen *s = &wp->base, ss;
|
||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
struct grid *gd = s->grid, *sgd;
|
struct grid *gd = s->grid, *sgd;
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
@@ -968,7 +757,7 @@ void
|
|||||||
window_copy_search_down(struct window_pane *wp, const char *searchstr)
|
window_copy_search_down(struct window_pane *wp, const char *searchstr)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct screen *s = data->backing, ss;
|
struct screen *s = &wp->base, ss;
|
||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
struct grid *gd = s->grid, *sgd;
|
struct grid *gd = s->grid, *sgd;
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
@@ -1028,7 +817,7 @@ window_copy_goto_line(struct window_pane *wp, const char *linestr)
|
|||||||
const char *errstr;
|
const char *errstr;
|
||||||
u_int lineno;
|
u_int lineno;
|
||||||
|
|
||||||
lineno = strtonum(linestr, 0, screen_hsize(data->backing), &errstr);
|
lineno = strtonum(linestr, 0, screen_hsize(&wp->base), &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1056,9 +845,7 @@ window_copy_write_line(
|
|||||||
last = screen_size_y(s) - 1;
|
last = screen_size_y(s) - 1;
|
||||||
if (py == 0) {
|
if (py == 0) {
|
||||||
size = xsnprintf(hdr, sizeof hdr,
|
size = xsnprintf(hdr, sizeof hdr,
|
||||||
"[%u/%u]", data->oy, screen_hsize(data->backing));
|
"[%u/%u]", data->oy, screen_hsize(&wp->base));
|
||||||
if (size > screen_size_x(s))
|
|
||||||
size = screen_size_x(s);
|
|
||||||
screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
|
screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
|
||||||
screen_write_puts(ctx, &gc, "%s", hdr);
|
screen_write_puts(ctx, &gc, "%s", hdr);
|
||||||
} else if (py == last && data->inputtype != WINDOW_COPY_OFF) {
|
} else if (py == last && data->inputtype != WINDOW_COPY_OFF) {
|
||||||
@@ -1075,9 +862,8 @@ window_copy_write_line(
|
|||||||
size = 0;
|
size = 0;
|
||||||
|
|
||||||
screen_write_cursormove(ctx, xoff, py);
|
screen_write_cursormove(ctx, xoff, py);
|
||||||
screen_write_copy(ctx, data->backing, xoff,
|
screen_write_copy(ctx, &wp->base, xoff, (screen_hsize(&wp->base) -
|
||||||
(screen_hsize(data->backing) - data->oy) + py,
|
data->oy) + py, screen_size_x(s) - size, 1);
|
||||||
screen_size_x(s) - size, 1);
|
|
||||||
|
|
||||||
if (py == data->cy && data->cx == screen_size_x(s)) {
|
if (py == data->cy && data->cx == screen_size_x(s)) {
|
||||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
@@ -1146,7 +932,7 @@ window_copy_start_selection(struct window_pane *wp)
|
|||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
|
|
||||||
data->selx = data->cx;
|
data->selx = data->cx;
|
||||||
data->sely = screen_hsize(data->backing) + data->cy - data->oy;
|
data->sely = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
|
|
||||||
s->sel.flag = 1;
|
s->sel.flag = 1;
|
||||||
window_copy_update_selection(wp);
|
window_copy_update_selection(wp);
|
||||||
@@ -1171,7 +957,7 @@ window_copy_update_selection(struct window_pane *wp)
|
|||||||
gc.attr |= options_get_number(oo, "mode-attr");
|
gc.attr |= options_get_number(oo, "mode-attr");
|
||||||
|
|
||||||
/* Find top of screen. */
|
/* Find top of screen. */
|
||||||
ty = screen_hsize(data->backing) - data->oy;
|
ty = screen_hsize(&wp->base) - data->oy;
|
||||||
|
|
||||||
/* Adjust the selection. */
|
/* Adjust the selection. */
|
||||||
sx = data->selx;
|
sx = data->selx;
|
||||||
@@ -1208,7 +994,7 @@ window_copy_update_selection(struct window_pane *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_copy_copy_selection(struct window_pane *wp, struct session *sess)
|
window_copy_copy_selection(struct window_pane *wp, struct client *c)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
@@ -1232,7 +1018,7 @@ window_copy_copy_selection(struct window_pane *wp, struct session *sess)
|
|||||||
|
|
||||||
/* Find start and end. */
|
/* Find start and end. */
|
||||||
xx = data->cx;
|
xx = data->cx;
|
||||||
yy = screen_hsize(data->backing) + data->cy - data->oy;
|
yy = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
if (yy < data->sely || (yy == data->sely && xx < data->selx)) {
|
if (yy < data->sely || (yy == data->sely && xx < data->selx)) {
|
||||||
sx = xx; sy = yy;
|
sx = xx; sy = yy;
|
||||||
ex = data->selx; ey = data->sely;
|
ex = data->selx; ey = data->sely;
|
||||||
@@ -1267,8 +1053,8 @@ window_copy_copy_selection(struct window_pane *wp, struct session *sess)
|
|||||||
/* Cursor is on the left. */
|
/* Cursor is on the left. */
|
||||||
lastex = data->selx + 1;
|
lastex = data->selx + 1;
|
||||||
restex = data->selx + 1;
|
restex = data->selx + 1;
|
||||||
firstsx = data->cx;
|
firstsx = data->cx + 1;
|
||||||
restsx = data->cx;
|
restsx = data->cx + 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@@ -1303,21 +1089,20 @@ window_copy_copy_selection(struct window_pane *wp, struct session *sess)
|
|||||||
off--; /* remove final \n */
|
off--; /* remove final \n */
|
||||||
|
|
||||||
/* Add the buffer to the stack. */
|
/* Add the buffer to the stack. */
|
||||||
limit = options_get_number(&sess->options, "buffer-limit");
|
limit = options_get_number(&c->session->options, "buffer-limit");
|
||||||
paste_add(&sess->buffers, buf, off, limit);
|
paste_add(&c->session->buffers, buf, off, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_copy_copy_line(struct window_pane *wp,
|
window_copy_copy_line(struct window_pane *wp,
|
||||||
char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
|
char **buf, size_t *off, u_int sy, u_int sx, u_int ex)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct grid *gd = wp->base.grid;
|
||||||
struct grid *gd = data->backing->grid;
|
const struct grid_cell *gc;
|
||||||
const struct grid_cell *gc;
|
const struct grid_utf8 *gu;
|
||||||
const struct grid_utf8 *gu;
|
struct grid_line *gl;
|
||||||
struct grid_line *gl;
|
u_int i, xx, wrapped = 0;
|
||||||
u_int i, xx, wrapped = 0;
|
size_t size;
|
||||||
size_t size;
|
|
||||||
|
|
||||||
if (sx > ex)
|
if (sx > ex)
|
||||||
return;
|
return;
|
||||||
@@ -1372,7 +1157,7 @@ window_copy_clear_selection(struct window_pane *wp)
|
|||||||
|
|
||||||
screen_clear_selection(&data->screen);
|
screen_clear_selection(&data->screen);
|
||||||
|
|
||||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
px = window_copy_find_length(wp, py);
|
px = window_copy_find_length(wp, py);
|
||||||
if (data->cx > px)
|
if (data->cx > px)
|
||||||
window_copy_update_cursor(wp, px, data->cy);
|
window_copy_update_cursor(wp, px, data->cy);
|
||||||
@@ -1381,10 +1166,9 @@ window_copy_clear_selection(struct window_pane *wp)
|
|||||||
int
|
int
|
||||||
window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
|
window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
const struct grid_cell *gc;
|
||||||
const struct grid_cell *gc;
|
|
||||||
|
|
||||||
gc = grid_peek_cell(data->backing->grid, px, py);
|
gc = grid_peek_cell(wp->base.grid, px, py);
|
||||||
if (gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8))
|
if (gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8))
|
||||||
return (0);
|
return (0);
|
||||||
if (gc->data == 0x00 || gc->data == 0x7f)
|
if (gc->data == 0x00 || gc->data == 0x7f)
|
||||||
@@ -1395,10 +1179,8 @@ window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
|
|||||||
u_int
|
u_int
|
||||||
window_copy_find_length(struct window_pane *wp, u_int py)
|
window_copy_find_length(struct window_pane *wp, u_int py)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
const struct grid_cell *gc;
|
||||||
struct screen *s = data->backing;
|
u_int px;
|
||||||
const struct grid_cell *gc;
|
|
||||||
u_int px;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the pane has been resized, its grid can contain old overlong
|
* If the pane has been resized, its grid can contain old overlong
|
||||||
@@ -1406,11 +1188,11 @@ window_copy_find_length(struct window_pane *wp, u_int py)
|
|||||||
* width of the grid, and screen_write_copy treats them as spaces, so
|
* width of the grid, and screen_write_copy treats them as spaces, so
|
||||||
* ignore them here too.
|
* ignore them here too.
|
||||||
*/
|
*/
|
||||||
px = s->grid->linedata[py].cellsize;
|
px = wp->base.grid->linedata[py].cellsize;
|
||||||
if (px > screen_size_x(s))
|
if (px > screen_size_x(&wp->base))
|
||||||
px = screen_size_x(s);
|
px = screen_size_x(&wp->base);
|
||||||
while (px > 0) {
|
while (px > 0) {
|
||||||
gc = grid_peek_cell(s->grid, px - 1, py);
|
gc = grid_peek_cell(wp->base.grid, px - 1, py);
|
||||||
if (gc->flags & GRID_FLAG_UTF8)
|
if (gc->flags & GRID_FLAG_UTF8)
|
||||||
break;
|
break;
|
||||||
if (gc->data != ' ')
|
if (gc->data != ' ')
|
||||||
@@ -1424,17 +1206,7 @@ void
|
|||||||
window_copy_cursor_start_of_line(struct window_pane *wp)
|
window_copy_cursor_start_of_line(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct screen *back_s = data->backing;
|
|
||||||
struct grid *gd = back_s->grid;
|
|
||||||
u_int py;
|
|
||||||
|
|
||||||
if (data->cx == 0) {
|
|
||||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
|
||||||
while (py > 0 && gd->linedata[py-1].flags & GRID_LINE_WRAPPED) {
|
|
||||||
window_copy_cursor_up(wp, 0);
|
|
||||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window_copy_update_cursor(wp, 0, data->cy);
|
window_copy_update_cursor(wp, 0, data->cy);
|
||||||
if (window_copy_update_selection(wp))
|
if (window_copy_update_selection(wp))
|
||||||
window_copy_redraw_lines(wp, data->cy, 1);
|
window_copy_redraw_lines(wp, data->cy, 1);
|
||||||
@@ -1448,11 +1220,11 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp)
|
|||||||
const struct grid_cell *gc;
|
const struct grid_cell *gc;
|
||||||
|
|
||||||
px = 0;
|
px = 0;
|
||||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
xx = window_copy_find_length(wp, py);
|
xx = window_copy_find_length(wp, py);
|
||||||
|
|
||||||
while (px < xx) {
|
while (px < xx) {
|
||||||
gc = grid_peek_cell(data->backing->grid, px, py);
|
gc = grid_peek_cell(wp->base.grid, px, py);
|
||||||
if (gc->flags & GRID_FLAG_UTF8)
|
if (gc->flags & GRID_FLAG_UTF8)
|
||||||
break;
|
break;
|
||||||
if (gc->data != ' ')
|
if (gc->data != ' ')
|
||||||
@@ -1469,22 +1241,21 @@ void
|
|||||||
window_copy_cursor_end_of_line(struct window_pane *wp)
|
window_copy_cursor_end_of_line(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct screen *back_s = data->backing;
|
struct screen *base_s = &wp->base;
|
||||||
struct grid *gd = back_s->grid;
|
struct grid *gd = base_s->grid;
|
||||||
u_int px, py;
|
u_int px, py;
|
||||||
|
|
||||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||||
px = window_copy_find_length(wp, py);
|
px = window_copy_find_length(wp, py);
|
||||||
|
|
||||||
if (data->cx == px) {
|
if (data->cx == px) {
|
||||||
if (data->screen.sel.flag && data->rectflag)
|
if (data->screen.sel.flag && data->rectflag)
|
||||||
px = screen_size_x(back_s);
|
px = screen_size_x(&wp->base);
|
||||||
if (gd->linedata[py].flags & GRID_LINE_WRAPPED) {
|
if (gd->linedata[py].flags & GRID_LINE_WRAPPED) {
|
||||||
while (py < gd->sy + gd->hsize &&
|
while (py < gd->sy + gd->hsize &&
|
||||||
gd->linedata[py].flags & GRID_LINE_WRAPPED) {
|
gd->linedata[py].flags & GRID_LINE_WRAPPED) {
|
||||||
window_copy_cursor_down(wp, 0);
|
window_copy_cursor_down(wp, 0);
|
||||||
py = screen_hsize(back_s)
|
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||||
+ data->cy - data->oy;
|
|
||||||
}
|
}
|
||||||
px = window_copy_find_length(wp, py);
|
px = window_copy_find_length(wp, py);
|
||||||
}
|
}
|
||||||
@@ -1519,7 +1290,7 @@ window_copy_cursor_right(struct window_pane *wp)
|
|||||||
if (data->screen.sel.flag && data->rectflag)
|
if (data->screen.sel.flag && data->rectflag)
|
||||||
px = screen_size_x(&data->screen);
|
px = screen_size_x(&data->screen);
|
||||||
else {
|
else {
|
||||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
px = window_copy_find_length(wp, py);
|
px = window_copy_find_length(wp, py);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1540,7 +1311,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
|||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
u_int ox, oy, px, py;
|
u_int ox, oy, px, py;
|
||||||
|
|
||||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
oy = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
ox = window_copy_find_length(wp, oy);
|
ox = window_copy_find_length(wp, oy);
|
||||||
if (ox != 0) {
|
if (ox != 0) {
|
||||||
data->lastcx = data->cx;
|
data->lastcx = data->cx;
|
||||||
@@ -1567,7 +1338,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!data->screen.sel.flag || !data->rectflag) {
|
if (!data->screen.sel.flag || !data->rectflag) {
|
||||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
px = window_copy_find_length(wp, py);
|
px = window_copy_find_length(wp, py);
|
||||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||||
data->cx > px)
|
data->cx > px)
|
||||||
@@ -1582,7 +1353,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
|||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
u_int ox, oy, px, py;
|
u_int ox, oy, px, py;
|
||||||
|
|
||||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
oy = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
ox = window_copy_find_length(wp, oy);
|
ox = window_copy_find_length(wp, oy);
|
||||||
if (ox != 0) {
|
if (ox != 0) {
|
||||||
data->lastcx = data->cx;
|
data->lastcx = data->cx;
|
||||||
@@ -1601,7 +1372,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!data->screen.sel.flag || !data->rectflag) {
|
if (!data->screen.sel.flag || !data->rectflag) {
|
||||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
px = window_copy_find_length(wp, py);
|
px = window_copy_find_length(wp, py);
|
||||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||||
data->cx > px)
|
data->cx > px)
|
||||||
@@ -1609,74 +1380,18 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
window_copy_cursor_jump(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
|
||||||
struct screen *back_s = data->backing;
|
|
||||||
const struct grid_cell *gc;
|
|
||||||
uint px, py, xx;
|
|
||||||
|
|
||||||
px = data->cx + 1;
|
|
||||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
|
||||||
xx = window_copy_find_length(wp, py);
|
|
||||||
|
|
||||||
while (px < xx) {
|
|
||||||
gc = grid_peek_cell(back_s->grid, px, py);
|
|
||||||
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
|
|
||||||
&& gc->data == data->jumpchar) {
|
|
||||||
|
|
||||||
window_copy_update_cursor(wp, px, data->cy);
|
|
||||||
if (window_copy_update_selection(wp))
|
|
||||||
window_copy_redraw_lines(wp, data->cy, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
px++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
window_copy_cursor_jump_back(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
|
||||||
struct screen *back_s = data->backing;
|
|
||||||
const struct grid_cell *gc;
|
|
||||||
uint px, py;
|
|
||||||
|
|
||||||
px = data->cx;
|
|
||||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
|
||||||
|
|
||||||
if (px > 0)
|
|
||||||
px--;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
gc = grid_peek_cell(back_s->grid, px, py);
|
|
||||||
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
|
|
||||||
&& gc->data == data->jumpchar) {
|
|
||||||
|
|
||||||
window_copy_update_cursor(wp, px, data->cy);
|
|
||||||
if (window_copy_update_selection(wp))
|
|
||||||
window_copy_redraw_lines(wp, data->cy, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (px == 0)
|
|
||||||
break;
|
|
||||||
px--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
|
window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct screen *back_s = data->backing;
|
struct screen *base_s = &wp->base;
|
||||||
u_int px, py, xx, yy;
|
u_int px, py, xx, yy;
|
||||||
int expected = 0;
|
int expected = 0;
|
||||||
|
|
||||||
px = data->cx;
|
px = data->cx;
|
||||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||||
xx = window_copy_find_length(wp, py);
|
xx = window_copy_find_length(wp, py);
|
||||||
yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
|
yy = screen_hsize(base_s) + screen_size_y(base_s) - 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First skip past any nonword characters and then any word characters.
|
* First skip past any nonword characters and then any word characters.
|
||||||
@@ -1694,7 +1409,7 @@ window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
|
|||||||
window_copy_cursor_down(wp, 0);
|
window_copy_cursor_down(wp, 0);
|
||||||
px = 0;
|
px = 0;
|
||||||
|
|
||||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||||
xx = window_copy_find_length(wp, py);
|
xx = window_copy_find_length(wp, py);
|
||||||
} else
|
} else
|
||||||
px++;
|
px++;
|
||||||
@@ -1711,14 +1426,14 @@ void
|
|||||||
window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
|
window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
struct screen *back_s = data->backing;
|
struct screen *base_s = &wp->base;
|
||||||
u_int px, py, xx, yy;
|
u_int px, py, xx, yy;
|
||||||
int expected = 1;
|
int expected = 1;
|
||||||
|
|
||||||
px = data->cx;
|
px = data->cx;
|
||||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||||
xx = window_copy_find_length(wp, py);
|
xx = window_copy_find_length(wp, py);
|
||||||
yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
|
yy = screen_hsize(base_s) + screen_size_y(base_s) - 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First skip past any word characters, then any nonword characters.
|
* First skip past any word characters, then any nonword characters.
|
||||||
@@ -1736,7 +1451,7 @@ window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
|
|||||||
window_copy_cursor_down(wp, 0);
|
window_copy_cursor_down(wp, 0);
|
||||||
px = 0;
|
px = 0;
|
||||||
|
|
||||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
py = screen_hsize(base_s) + data->cy - data->oy;
|
||||||
xx = window_copy_find_length(wp, py);
|
xx = window_copy_find_length(wp, py);
|
||||||
} else
|
} else
|
||||||
px++;
|
px++;
|
||||||
@@ -1757,7 +1472,7 @@ window_copy_cursor_previous_word(struct window_pane *wp, const char *separators)
|
|||||||
u_int px, py;
|
u_int px, py;
|
||||||
|
|
||||||
px = data->cx;
|
px = data->cx;
|
||||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
|
|
||||||
/* Move back to the previous word character. */
|
/* Move back to the previous word character. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -1767,12 +1482,12 @@ window_copy_cursor_previous_word(struct window_pane *wp, const char *separators)
|
|||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (data->cy == 0 &&
|
if (data->cy == 0 &&
|
||||||
(screen_hsize(data->backing) == 0 ||
|
(screen_hsize(&wp->base) == 0 ||
|
||||||
data->oy >= screen_hsize(data->backing) - 1))
|
data->oy >= screen_hsize(&wp->base) - 1))
|
||||||
goto out;
|
goto out;
|
||||||
window_copy_cursor_up(wp, 0);
|
window_copy_cursor_up(wp, 0);
|
||||||
|
|
||||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
px = window_copy_find_length(wp, py);
|
px = window_copy_find_length(wp, py);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1825,11 +1540,11 @@ window_copy_scroll_down(struct window_pane *wp, u_int ny)
|
|||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
|
|
||||||
if (ny > screen_hsize(data->backing))
|
if (ny > screen_hsize(&wp->base))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (data->oy > screen_hsize(data->backing) - ny)
|
if (data->oy > screen_hsize(&wp->base) - ny)
|
||||||
ny = screen_hsize(data->backing) - data->oy;
|
ny = screen_hsize(&wp->base) - data->oy;
|
||||||
if (ny == 0)
|
if (ny == 0)
|
||||||
return;
|
return;
|
||||||
data->oy += ny;
|
data->oy += ny;
|
||||||
@@ -1856,7 +1571,7 @@ window_copy_rectangle_toggle(struct window_pane *wp)
|
|||||||
|
|
||||||
data->rectflag = !data->rectflag;
|
data->rectflag = !data->rectflag;
|
||||||
|
|
||||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
py = screen_hsize(&wp->base) + data->cy - data->oy;
|
||||||
px = window_copy_find_length(wp, py);
|
px = window_copy_find_length(wp, py);
|
||||||
if (data->cx > px)
|
if (data->cx > px)
|
||||||
window_copy_update_cursor(wp, px, data->cy);
|
window_copy_update_cursor(wp, px, data->cy);
|
||||||
|
|||||||
260
window-more.c
Normal file
260
window-more.c
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
/* $Id: window-more.c,v 1.42 2010-02-08 18:10:07 tcunha Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
struct screen *window_more_init(struct window_pane *);
|
||||||
|
void window_more_free(struct window_pane *);
|
||||||
|
void window_more_resize(struct window_pane *, u_int, u_int);
|
||||||
|
void window_more_key(struct window_pane *, struct client *, int);
|
||||||
|
|
||||||
|
void window_more_redraw_screen(struct window_pane *);
|
||||||
|
void window_more_write_line(
|
||||||
|
struct window_pane *, struct screen_write_ctx *, u_int);
|
||||||
|
|
||||||
|
void window_more_scroll_up(struct window_pane *);
|
||||||
|
void window_more_scroll_down(struct window_pane *);
|
||||||
|
|
||||||
|
const struct window_mode window_more_mode = {
|
||||||
|
window_more_init,
|
||||||
|
window_more_free,
|
||||||
|
window_more_resize,
|
||||||
|
window_more_key,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct window_more_mode_data {
|
||||||
|
struct screen screen;
|
||||||
|
|
||||||
|
struct mode_key_data mdata;
|
||||||
|
|
||||||
|
ARRAY_DECL(, char *) list;
|
||||||
|
u_int top;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
window_more_add(struct window_pane *wp, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
window_more_vadd(wp, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_more_vadd(struct window_pane *wp, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
struct window_more_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
char *msg;
|
||||||
|
u_int size;
|
||||||
|
|
||||||
|
xvasprintf(&msg, fmt, ap);
|
||||||
|
ARRAY_ADD(&data->list, msg);
|
||||||
|
|
||||||
|
screen_write_start(&ctx, wp, NULL);
|
||||||
|
size = ARRAY_LENGTH(&data->list) - 1;
|
||||||
|
if (size >= data->top && size <= data->top + screen_size_y(s) - 1) {
|
||||||
|
window_more_write_line(wp, &ctx, size - data->top);
|
||||||
|
if (size != data->top)
|
||||||
|
window_more_write_line(wp, &ctx, 0);
|
||||||
|
} else
|
||||||
|
window_more_write_line(wp, &ctx, 0);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct screen *
|
||||||
|
window_more_init(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_more_mode_data *data;
|
||||||
|
struct screen *s;
|
||||||
|
int keys;
|
||||||
|
|
||||||
|
wp->modedata = data = xmalloc(sizeof *data);
|
||||||
|
ARRAY_INIT(&data->list);
|
||||||
|
data->top = 0;
|
||||||
|
|
||||||
|
s = &data->screen;
|
||||||
|
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
|
||||||
|
s->mode &= ~MODE_CURSOR;
|
||||||
|
|
||||||
|
keys = options_get_number(&wp->window->options, "mode-keys");
|
||||||
|
if (keys == MODEKEY_EMACS)
|
||||||
|
mode_key_init(&data->mdata, &mode_key_tree_emacs_choice);
|
||||||
|
else
|
||||||
|
mode_key_init(&data->mdata, &mode_key_tree_vi_choice);
|
||||||
|
|
||||||
|
return (s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_more_free(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_more_mode_data *data = wp->modedata;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(&data->list); i++)
|
||||||
|
xfree(ARRAY_ITEM(&data->list, i));
|
||||||
|
ARRAY_FREE(&data->list);
|
||||||
|
|
||||||
|
screen_free(&data->screen);
|
||||||
|
xfree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_more_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||||
|
{
|
||||||
|
struct window_more_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
|
||||||
|
screen_resize(s, sx, sy);
|
||||||
|
window_more_redraw_screen(wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ARGSUSED */
|
||||||
|
void
|
||||||
|
window_more_key(struct window_pane *wp, unused struct client *c, int key)
|
||||||
|
{
|
||||||
|
struct window_more_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
|
||||||
|
switch (mode_key_lookup(&data->mdata, key)) {
|
||||||
|
case MODEKEYCHOICE_CANCEL:
|
||||||
|
window_pane_reset_mode(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCHOICE_UP:
|
||||||
|
case MODEKEYCHOICE_SCROLLUP:
|
||||||
|
window_more_scroll_up(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCHOICE_DOWN:
|
||||||
|
case MODEKEYCHOICE_SCROLLDOWN:
|
||||||
|
window_more_scroll_down(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCHOICE_PAGEUP:
|
||||||
|
if (data->top < screen_size_y(s))
|
||||||
|
data->top = 0;
|
||||||
|
else
|
||||||
|
data->top -= screen_size_y(s);
|
||||||
|
window_more_redraw_screen(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCHOICE_PAGEDOWN:
|
||||||
|
if (data->top + screen_size_y(s) > ARRAY_LENGTH(&data->list))
|
||||||
|
data->top = ARRAY_LENGTH(&data->list);
|
||||||
|
else
|
||||||
|
data->top += screen_size_y(s);
|
||||||
|
window_more_redraw_screen(wp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_more_write_line(
|
||||||
|
struct window_pane *wp, struct screen_write_ctx *ctx, u_int py)
|
||||||
|
{
|
||||||
|
struct window_more_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
struct options *oo = &wp->window->options;
|
||||||
|
struct grid_cell gc;
|
||||||
|
char *msg, hdr[32];
|
||||||
|
size_t size;
|
||||||
|
int utf8flag;
|
||||||
|
|
||||||
|
utf8flag = options_get_number(&wp->window->options, "utf8");
|
||||||
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
|
|
||||||
|
if (py == 0) {
|
||||||
|
size = xsnprintf(hdr, sizeof hdr,
|
||||||
|
"[%u/%u]", data->top, ARRAY_LENGTH(&data->list));
|
||||||
|
screen_write_cursormove(ctx, screen_size_x(s) - size, 0);
|
||||||
|
colour_set_fg(&gc, options_get_number(oo, "mode-fg"));
|
||||||
|
colour_set_bg(&gc, options_get_number(oo, "mode-bg"));
|
||||||
|
gc.attr |= options_get_number(oo, "mode-attr");
|
||||||
|
screen_write_puts(ctx, &gc, "%s", hdr);
|
||||||
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
|
} else
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
screen_write_cursormove(ctx, 0, py);
|
||||||
|
if (data->top + py < ARRAY_LENGTH(&data->list)) {
|
||||||
|
msg = ARRAY_ITEM(&data->list, data->top + py);
|
||||||
|
screen_write_nputs(
|
||||||
|
ctx, screen_size_x(s) - size, &gc, utf8flag, "%s", msg);
|
||||||
|
}
|
||||||
|
while (s->cx < screen_size_x(s) - size)
|
||||||
|
screen_write_putc(ctx, &gc, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_more_redraw_screen(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_more_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
screen_write_start(&ctx, wp, NULL);
|
||||||
|
for (i = 0; i < screen_size_y(s); i++)
|
||||||
|
window_more_write_line(wp, &ctx, i);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_more_scroll_up(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_more_mode_data *data = wp->modedata;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
|
||||||
|
if (data->top == 0)
|
||||||
|
return;
|
||||||
|
data->top--;
|
||||||
|
|
||||||
|
screen_write_start(&ctx, wp, NULL);
|
||||||
|
screen_write_cursormove(&ctx, 0, 0);
|
||||||
|
screen_write_insertline(&ctx, 1);
|
||||||
|
window_more_write_line(wp, &ctx, 0);
|
||||||
|
window_more_write_line(wp, &ctx, 1);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_more_scroll_down(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_more_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
|
||||||
|
if (data->top >= ARRAY_LENGTH(&data->list))
|
||||||
|
return;
|
||||||
|
data->top++;
|
||||||
|
|
||||||
|
screen_write_start(&ctx, wp, NULL);
|
||||||
|
screen_write_cursormove(&ctx, 0, 0);
|
||||||
|
screen_write_deleteline(&ctx, 1);
|
||||||
|
window_more_write_line(wp, &ctx, screen_size_y(s) - 1);
|
||||||
|
window_more_write_line(wp, &ctx, 0);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
335
window.c
335
window.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: window.c,v 1.142 2010-12-06 22:52:21 nicm Exp $ */
|
/* $Id: window.c,v 1.126 2010-02-08 18:10:07 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
@@ -169,28 +170,6 @@ winlink_previous(struct winlink *wl)
|
|||||||
return (RB_PREV(winlinks, wwl, wl));
|
return (RB_PREV(winlinks, wwl, wl));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct winlink *
|
|
||||||
winlink_next_by_number(struct winlink *wl, struct session *s, int n)
|
|
||||||
{
|
|
||||||
for (; n > 0; n--) {
|
|
||||||
if ((wl = RB_NEXT(winlinks, wwl, wl)) == NULL)
|
|
||||||
wl = RB_MIN(winlinks, &s->windows);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct winlink *
|
|
||||||
winlink_previous_by_number(struct winlink *wl, struct session *s, int n)
|
|
||||||
{
|
|
||||||
for (; n > 0; n--) {
|
|
||||||
if ((wl = RB_PREV(winlinks, wwl, wl)) == NULL)
|
|
||||||
wl = RB_MAX(winlinks, &s->windows);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (wl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
winlink_stack_push(struct winlink_stack *stack, struct winlink *wl)
|
winlink_stack_push(struct winlink_stack *stack, struct winlink *wl)
|
||||||
{
|
{
|
||||||
@@ -322,9 +301,6 @@ window_resize(struct window *w, u_int sx, u_int sy)
|
|||||||
void
|
void
|
||||||
window_set_active_pane(struct window *w, struct window_pane *wp)
|
window_set_active_pane(struct window *w, struct window_pane *wp)
|
||||||
{
|
{
|
||||||
if (wp == w->active)
|
|
||||||
return;
|
|
||||||
w->last = w->active;
|
|
||||||
w->active = wp;
|
w->active = wp;
|
||||||
while (!window_pane_visible(w->active)) {
|
while (!window_pane_visible(w->active)) {
|
||||||
w->active = TAILQ_PREV(w->active, window_panes, entry);
|
w->active = TAILQ_PREV(w->active, window_panes, entry);
|
||||||
@@ -341,7 +317,7 @@ window_set_active_at(struct window *w, u_int x, u_int y)
|
|||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
if (wp == w->active || !window_pane_visible(wp))
|
if (!window_pane_visible(wp))
|
||||||
continue;
|
continue;
|
||||||
if (x < wp->xoff || x >= wp->xoff + wp->sx)
|
if (x < wp->xoff || x >= wp->xoff + wp->sx)
|
||||||
continue;
|
continue;
|
||||||
@@ -368,16 +344,9 @@ window_add_pane(struct window *w, u_int hlimit)
|
|||||||
void
|
void
|
||||||
window_remove_pane(struct window *w, struct window_pane *wp)
|
window_remove_pane(struct window *w, struct window_pane *wp)
|
||||||
{
|
{
|
||||||
if (wp == w->active) {
|
w->active = TAILQ_PREV(wp, window_panes, entry);
|
||||||
w->active = w->last;
|
if (w->active == NULL)
|
||||||
w->last = NULL;
|
w->active = TAILQ_NEXT(wp, entry);
|
||||||
if (w->active == NULL) {
|
|
||||||
w->active = TAILQ_PREV(wp, window_panes, entry);
|
|
||||||
if (w->active == NULL)
|
|
||||||
w->active = TAILQ_NEXT(wp, entry);
|
|
||||||
}
|
|
||||||
} else if (wp == w->last)
|
|
||||||
w->last = NULL;
|
|
||||||
|
|
||||||
TAILQ_REMOVE(&w->panes, wp, entry);
|
TAILQ_REMOVE(&w->panes, wp, entry);
|
||||||
window_pane_destroy(wp);
|
window_pane_destroy(wp);
|
||||||
@@ -398,29 +367,6 @@ window_pane_at_index(struct window *w, u_int idx)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct window_pane *
|
|
||||||
window_pane_next_by_number(struct window *w, struct window_pane *wp, u_int n)
|
|
||||||
{
|
|
||||||
for (; n > 0; n--) {
|
|
||||||
if ((wp = TAILQ_NEXT(wp, entry)) == NULL)
|
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct window_pane *
|
|
||||||
window_pane_previous_by_number(struct window *w, struct window_pane *wp,
|
|
||||||
u_int n)
|
|
||||||
{
|
|
||||||
for (; n > 0; n--) {
|
|
||||||
if ((wp = TAILQ_PREV(wp, window_panes, entry)) == NULL)
|
|
||||||
wp = TAILQ_LAST(&w->panes, window_panes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
u_int
|
u_int
|
||||||
window_pane_index(struct window *w, struct window_pane *wp)
|
window_pane_index(struct window *w, struct window_pane *wp)
|
||||||
{
|
{
|
||||||
@@ -502,8 +448,6 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
|||||||
void
|
void
|
||||||
window_pane_destroy(struct window_pane *wp)
|
window_pane_destroy(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
window_pane_reset_mode(wp);
|
|
||||||
|
|
||||||
if (wp->fd != -1) {
|
if (wp->fd != -1) {
|
||||||
close(wp->fd);
|
close(wp->fd);
|
||||||
bufferevent_free(wp->event);
|
bufferevent_free(wp->event);
|
||||||
@@ -511,6 +455,7 @@ window_pane_destroy(struct window_pane *wp)
|
|||||||
|
|
||||||
input_free(wp);
|
input_free(wp);
|
||||||
|
|
||||||
|
window_pane_reset_mode(wp);
|
||||||
screen_free(&wp->base);
|
screen_free(&wp->base);
|
||||||
if (wp->saved_grid != NULL)
|
if (wp->saved_grid != NULL)
|
||||||
grid_destroy(wp->saved_grid);
|
grid_destroy(wp->saved_grid);
|
||||||
@@ -533,11 +478,14 @@ int
|
|||||||
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
||||||
const char *cwd, struct environ *env, struct termios *tio, char **cause)
|
const char *cwd, struct environ *env, struct termios *tio, char **cause)
|
||||||
{
|
{
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
int mode;
|
int mode;
|
||||||
char *argv0;
|
char *argv0, **varp, *var;
|
||||||
const char *ptr;
|
ARRAY_DECL(, char *) varlist;
|
||||||
struct termios tio2;
|
struct environ_entry *envent;
|
||||||
|
const char *ptr;
|
||||||
|
struct termios tio2;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
if (wp->fd != -1) {
|
if (wp->fd != -1) {
|
||||||
close(wp->fd);
|
close(wp->fd);
|
||||||
@@ -580,11 +528,22 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
|||||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
|
if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
|
||||||
fatal("tcgetattr failed");
|
fatal("tcgetattr failed");
|
||||||
|
|
||||||
closefrom(STDERR_FILENO + 1);
|
ARRAY_INIT(&varlist);
|
||||||
|
for (varp = environ; *varp != NULL; varp++) {
|
||||||
|
var = xstrdup(*varp);
|
||||||
|
var[strcspn(var, "=")] = '\0';
|
||||||
|
ARRAY_ADD(&varlist, var);
|
||||||
|
}
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(&varlist); i++) {
|
||||||
|
var = ARRAY_ITEM(&varlist, i);
|
||||||
|
unsetenv(var);
|
||||||
|
}
|
||||||
|
RB_FOREACH(envent, environ, env) {
|
||||||
|
if (envent->value != NULL)
|
||||||
|
setenv(envent->name, envent->value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
environ_push(env);
|
server_signal_clear();
|
||||||
|
|
||||||
clear_signals(1);
|
|
||||||
log_close();
|
log_close();
|
||||||
|
|
||||||
if (*wp->cmd != '\0') {
|
if (*wp->cmd != '\0') {
|
||||||
@@ -612,6 +571,8 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
|||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
if (fcntl(wp->fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
if (fcntl(wp->fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
||||||
fatal("fcntl failed");
|
fatal("fcntl failed");
|
||||||
|
if (fcntl(wp->fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
|
fatal("fcntl failed");
|
||||||
wp->event = bufferevent_new(wp->fd,
|
wp->event = bufferevent_new(wp->fd,
|
||||||
window_pane_read_callback, NULL, window_pane_error_callback, wp);
|
window_pane_read_callback, NULL, window_pane_error_callback, wp);
|
||||||
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
||||||
@@ -623,27 +584,9 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
|||||||
void
|
void
|
||||||
window_pane_read_callback(unused struct bufferevent *bufev, void *data)
|
window_pane_read_callback(unused struct bufferevent *bufev, void *data)
|
||||||
{
|
{
|
||||||
struct window_pane *wp = data;
|
struct window_pane *wp = data;
|
||||||
char *new_data;
|
|
||||||
size_t new_size;
|
|
||||||
|
|
||||||
new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off;
|
window_pane_parse(wp);
|
||||||
if (wp->pipe_fd != -1 && new_size > 0) {
|
|
||||||
new_data = EVBUFFER_DATA(wp->event->input);
|
|
||||||
bufferevent_write(wp->pipe_event, new_data, new_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
input_parse(wp);
|
|
||||||
|
|
||||||
wp->pipe_off = EVBUFFER_LENGTH(wp->event->input);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we get here, we're not outputting anymore, so set the silence
|
|
||||||
* flag on the window.
|
|
||||||
*/
|
|
||||||
wp->window->flags |= WINDOW_SILENCE;
|
|
||||||
if (gettimeofday(&wp->window->silence_timer, NULL) != 0)
|
|
||||||
fatal("gettimeofday failed.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
@@ -687,81 +630,6 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
|||||||
fatal("ioctl failed");
|
fatal("ioctl failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Enter alternative screen mode. A copy of the visible screen is saved and the
|
|
||||||
* history is not updated
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
window_pane_alternate_on(struct window_pane *wp, struct grid_cell *gc)
|
|
||||||
{
|
|
||||||
struct screen *s = &wp->base;
|
|
||||||
u_int sx, sy;
|
|
||||||
|
|
||||||
if (wp->saved_grid != NULL)
|
|
||||||
return;
|
|
||||||
if (!options_get_number(&wp->window->options, "alternate-screen"))
|
|
||||||
return;
|
|
||||||
sx = screen_size_x(s);
|
|
||||||
sy = screen_size_y(s);
|
|
||||||
|
|
||||||
wp->saved_grid = grid_create(sx, sy, 0);
|
|
||||||
grid_duplicate_lines(wp->saved_grid, 0, s->grid, screen_hsize(s), sy);
|
|
||||||
wp->saved_cx = s->cx;
|
|
||||||
wp->saved_cy = s->cy;
|
|
||||||
memcpy(&wp->saved_cell, gc, sizeof wp->saved_cell);
|
|
||||||
|
|
||||||
grid_view_clear(s->grid, 0, 0, sx, sy);
|
|
||||||
|
|
||||||
wp->base.grid->flags &= ~GRID_HISTORY;
|
|
||||||
|
|
||||||
wp->flags |= PANE_REDRAW;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Exit alternate screen mode and restore the copied grid. */
|
|
||||||
void
|
|
||||||
window_pane_alternate_off(struct window_pane *wp, struct grid_cell *gc)
|
|
||||||
{
|
|
||||||
struct screen *s = &wp->base;
|
|
||||||
u_int sx, sy;
|
|
||||||
|
|
||||||
if (wp->saved_grid == NULL)
|
|
||||||
return;
|
|
||||||
if (!options_get_number(&wp->window->options, "alternate-screen"))
|
|
||||||
return;
|
|
||||||
sx = screen_size_x(s);
|
|
||||||
sy = screen_size_y(s);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the current size is bigger, temporarily resize to the old size
|
|
||||||
* before copying back.
|
|
||||||
*/
|
|
||||||
if (sy > wp->saved_grid->sy)
|
|
||||||
screen_resize(s, sx, wp->saved_grid->sy);
|
|
||||||
|
|
||||||
/* Restore the grid, cursor position and cell. */
|
|
||||||
grid_duplicate_lines(s->grid, screen_hsize(s), wp->saved_grid, 0, sy);
|
|
||||||
s->cx = wp->saved_cx;
|
|
||||||
if (s->cx > screen_size_x(s) - 1)
|
|
||||||
s->cx = screen_size_x(s) - 1;
|
|
||||||
s->cy = wp->saved_cy;
|
|
||||||
if (s->cy > screen_size_y(s) - 1)
|
|
||||||
s->cy = screen_size_y(s) - 1;
|
|
||||||
memcpy(gc, &wp->saved_cell, sizeof *gc);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Turn history back on (so resize can use it) and then resize back to
|
|
||||||
* the current size.
|
|
||||||
*/
|
|
||||||
wp->base.grid->flags |= GRID_HISTORY;
|
|
||||||
if (sy > wp->saved_grid->sy)
|
|
||||||
screen_resize(s, sx, sy);
|
|
||||||
|
|
||||||
grid_destroy(wp->saved_grid);
|
|
||||||
wp->saved_grid = NULL;
|
|
||||||
|
|
||||||
wp->flags |= PANE_REDRAW;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode)
|
window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode)
|
||||||
{
|
{
|
||||||
@@ -791,7 +659,24 @@ window_pane_reset_mode(struct window_pane *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_pane_key(struct window_pane *wp, struct session *sess, int key)
|
window_pane_parse(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
char *data;
|
||||||
|
size_t new_size;
|
||||||
|
|
||||||
|
new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off;
|
||||||
|
if (wp->pipe_fd != -1 && new_size > 0) {
|
||||||
|
data = EVBUFFER_DATA(wp->event->input);
|
||||||
|
bufferevent_write(wp->pipe_event, data, new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
input_parse(wp);
|
||||||
|
|
||||||
|
wp->pipe_off = EVBUFFER_LENGTH(wp->event->input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_pane_key(struct window_pane *wp, struct client *c, int key)
|
||||||
{
|
{
|
||||||
struct window_pane *wp2;
|
struct window_pane *wp2;
|
||||||
|
|
||||||
@@ -800,7 +685,7 @@ window_pane_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
|
|
||||||
if (wp->mode != NULL) {
|
if (wp->mode != NULL) {
|
||||||
if (wp->mode->key != NULL)
|
if (wp->mode->key != NULL)
|
||||||
wp->mode->key(wp, sess, key);
|
wp->mode->key(wp, c, key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -819,7 +704,7 @@ window_pane_key(struct window_pane *wp, struct session *sess, int key)
|
|||||||
|
|
||||||
void
|
void
|
||||||
window_pane_mouse(
|
window_pane_mouse(
|
||||||
struct window_pane *wp, struct session *sess, struct mouse_event *m)
|
struct window_pane *wp, struct client *c, struct mouse_event *m)
|
||||||
{
|
{
|
||||||
if (!window_pane_visible(wp))
|
if (!window_pane_visible(wp))
|
||||||
return;
|
return;
|
||||||
@@ -833,7 +718,7 @@ window_pane_mouse(
|
|||||||
|
|
||||||
if (wp->mode != NULL) {
|
if (wp->mode != NULL) {
|
||||||
if (wp->mode->mouse != NULL)
|
if (wp->mode->mouse != NULL)
|
||||||
wp->mode->mouse(wp, sess, m);
|
wp->mode->mouse(wp, c, m);
|
||||||
} else if (wp->fd != -1)
|
} else if (wp->fd != -1)
|
||||||
input_mouse(wp, m);
|
input_mouse(wp, m);
|
||||||
}
|
}
|
||||||
@@ -874,113 +759,3 @@ window_pane_search(struct window_pane *wp, const char *searchstr, u_int *lineno)
|
|||||||
xfree(newsearchstr);
|
xfree(newsearchstr);
|
||||||
return (msg);
|
return (msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the pane directly above another. */
|
|
||||||
struct window_pane *
|
|
||||||
window_pane_find_up(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct window_pane *wp2;
|
|
||||||
u_int left, top;
|
|
||||||
|
|
||||||
if (wp == NULL || !window_pane_visible(wp))
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
top = wp->yoff;
|
|
||||||
if (top == 0)
|
|
||||||
top = wp->window->sy + 1;
|
|
||||||
left = wp->xoff;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
|
||||||
if (!window_pane_visible(wp2))
|
|
||||||
continue;
|
|
||||||
if (wp2->yoff + wp2->sy + 1 != top)
|
|
||||||
continue;
|
|
||||||
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
|
|
||||||
return (wp2);
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the pane directly below another. */
|
|
||||||
struct window_pane *
|
|
||||||
window_pane_find_down(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct window_pane *wp2;
|
|
||||||
u_int left, bottom;
|
|
||||||
|
|
||||||
if (wp == NULL || !window_pane_visible(wp))
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
bottom = wp->yoff + wp->sy + 1;
|
|
||||||
if (bottom >= wp->window->sy)
|
|
||||||
bottom = 0;
|
|
||||||
left = wp->xoff;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
|
||||||
if (!window_pane_visible(wp2))
|
|
||||||
continue;
|
|
||||||
if (wp2->yoff != bottom)
|
|
||||||
continue;
|
|
||||||
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
|
|
||||||
return (wp2);
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the pane directly to the left of another, adjacent to the left side and
|
|
||||||
* containing the top edge.
|
|
||||||
*/
|
|
||||||
struct window_pane *
|
|
||||||
window_pane_find_left(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct window_pane *wp2;
|
|
||||||
u_int left, top;
|
|
||||||
|
|
||||||
if (wp == NULL || !window_pane_visible(wp))
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
left = wp->xoff;
|
|
||||||
if (left == 0)
|
|
||||||
left = wp->window->sx + 1;
|
|
||||||
top = wp->yoff;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
|
||||||
if (!window_pane_visible(wp2))
|
|
||||||
continue;
|
|
||||||
if (wp2->xoff + wp2->sx + 1 != left)
|
|
||||||
continue;
|
|
||||||
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
|
|
||||||
return (wp2);
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the pane directly to the right of another, that is adjacent to the
|
|
||||||
* right edge and including the top edge.
|
|
||||||
*/
|
|
||||||
struct window_pane *
|
|
||||||
window_pane_find_right(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct window_pane *wp2;
|
|
||||||
u_int right, top;
|
|
||||||
|
|
||||||
if (wp == NULL || !window_pane_visible(wp))
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
right = wp->xoff + wp->sx + 1;
|
|
||||||
if (right >= wp->window->sx)
|
|
||||||
right = 0;
|
|
||||||
top = wp->yoff;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
|
||||||
if (!window_pane_visible(wp2))
|
|
||||||
continue;
|
|
||||||
if (wp2->xoff != right)
|
|
||||||
continue;
|
|
||||||
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
|
|
||||||
return (wp2);
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user